From c8a13b7651b96e41bc3756cf0fc65614a5abee2c Mon Sep 17 00:00:00 2001 From: zerofrog Date: Mon, 2 Apr 2007 01:06:17 +0000 Subject: [PATCH] pcsx2 0.9.3 and a lot of other additions --- INSTALL | 66 + bin/.pixmaps/pcsxAbout.bmp | Bin 0 -> 251192 bytes bin/A39517AB.xml | 183 + bin/Langs/ar_AR/LC_MESSAGES/pcsx2.mo | Bin 0 -> 6197 bytes bin/Langs/bg_BG/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11915 bytes bin/Langs/cz_CZ/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11085 bytes bin/Langs/de_DE/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11840 bytes bin/Langs/du_DU/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11583 bytes bin/Langs/el_EL/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11225 bytes bin/Langs/es_ES/LC_MESSAGES/pcsx2.mo | Bin 0 -> 10632 bytes bin/Langs/fr_FR/LC_MESSAGES/pcsx2.mo | Bin 0 -> 6176 bytes bin/Langs/hb_HB/LC_MESSAGES/pcsx2.mo | Bin 0 -> 6302 bytes bin/Langs/it_IT/LC_MESSAGES/pcsx2.mo | Bin 0 -> 5411 bytes bin/Langs/ja_JA/LC_MESSAGES/pcsx2.mo | Bin 0 -> 15213 bytes bin/Langs/pe_PE/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11165 bytes bin/Langs/pl_PL/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11183 bytes bin/Langs/po_BR/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11024 bytes bin/Langs/po_PO/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11385 bytes bin/Langs/ro_RO/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11443 bytes bin/Langs/ru_RU/LC_MESSAGES/pcsx2.mo | Bin 0 -> 11125 bytes bin/Langs/sh_SH/LC_MESSAGES/pcsx2.mo | Bin 0 -> 9723 bytes bin/Langs/sw_SW/LC_MESSAGES/other.po | 868 + bin/Langs/sw_SW/LC_MESSAGES/pcsx2.mo | Bin 0 -> 10929 bytes bin/Langs/tc_TC/LC_MESSAGES/Pcsx2.mo | Bin 0 -> 9723 bytes bin/Langs/tr_TR/LC_MESSAGES/pcsx2.mo | Bin 0 -> 10871 bytes bin/compat_list/compat_list.html | 22498 ++++++++++++++++ bin/compat_list/h_console.jpg | Bin 0 -> 544 bytes bin/compat_list/h_region.jpg | Bin 0 -> 486 bytes bin/compat_list/h_serial.jpg | Bin 0 -> 477 bytes bin/compat_list/h_status.jpg | Bin 0 -> 518 bytes bin/compat_list/h_title.jpg | Bin 0 -> 455 bytes bin/compat_list/h_version.jpg | Bin 0 -> 511 bytes bin/compat_list/sq_ingame.jpg | Bin 0 -> 304 bytes bin/compat_list/sq_intro.jpg | Bin 0 -> 305 bytes bin/compat_list/sq_menus.jpg | Bin 0 -> 305 bytes bin/compat_list/sq_nothing.jpg | Bin 0 -> 305 bytes bin/compat_list/sq_playable.jpg | Bin 0 -> 304 bytes bin/inis/pcsx2.ini | 32 + bin/patches/013E349D.pnach | 4 + bin/patches/015314A2.pnach | 4 + bin/patches/034836F8.pnach | 13 + bin/patches/0442B1BD.pnach | 4 + bin/patches/05177ECE.pnach | 4 + bin/patches/0518D274.pnach | 4 + bin/patches/0518D275.pnach | 4 + bin/patches/07AD79C9.pnach | 4 + bin/patches/0838D766.pnach | 6 + bin/patches/08901101.pnach | 13 + bin/patches/08FB9DCF.pnach | 9 + bin/patches/0999F9DB.pnach | 13 + bin/patches/0A342A88.pnach | 4 + bin/patches/0B359BBF.pnach | 5 + bin/patches/0C370E94.pnach | 4 + bin/patches/0F6B6315.pnach | 4 + bin/patches/1025D50A.pnach | 7 + bin/patches/116154AD.pnach | 8 + bin/patches/1248FE3A.pnach | 6 + bin/patches/129C8600.pnach | 8 + bin/patches/12AFF4D4.pnach | 23 + bin/patches/1468C474.pnach | 4 + bin/patches/1510E1D1.pnach | 7 + bin/patches/1629D655.pnach | 20 + bin/patches/163F0461.pnach | 18 + bin/patches/1738A5B0.pnach | 13 + bin/patches/19D145D7.pnach | 12 + bin/patches/1CAC8A56.pnach | 4 + bin/patches/1D2818AF.pnach | 13 + bin/patches/200BC0E6.pnach | 4 + bin/patches/2088950A.pnach | 4 + bin/patches/21068223.pnach | 3 + bin/patches/27E54B37.pnach | 16 + bin/patches/280DAC56.pnach | 16 + bin/patches/295D2F96.pnach | 6 + bin/patches/29D80A23.pnach | 9 + bin/patches/2B2E1535.pnach | 5 + bin/patches/2C728173.pnach | 4 + bin/patches/2CFFFA50.pnach | 9 + bin/patches/2D919421.pnach | 15 + bin/patches/2F56CBC9.pnach | 4 + bin/patches/302797DF.pnach | 5 + bin/patches/304C115C.pnach | 4 + bin/patches/32629F36.pnach | 9 + bin/patches/339A0B8C.pnach | 4 + bin/patches/33F7D21A.pnach | 14 + bin/patches/36FEEE3A.pnach | 19 + bin/patches/37BA81B1.pnach | 4 + bin/patches/37C07E96.pnach | 3 + bin/patches/38F29E28.pnach | 4 + bin/patches/3BD85DA4.pnach | 7 + bin/patches/3CFE3B37.pnach | 6 + bin/patches/3DB65A75.pnach | 5 + bin/patches/3E0A256D.pnach | 4 + bin/patches/3E68955A.pnach | 4 + bin/patches/3F0452DE.pnach | 4 + bin/patches/3FB69323.pnach | 8 + bin/patches/4043F228.pnach | 4 + bin/patches/41A3191C.pnach | 4 + bin/patches/4321A427.pnach | 5 + bin/patches/4334E17D.pnach | 4 + bin/patches/44A61C8F.pnach | 4 + bin/patches/4691F6F7.pnach | 4 + bin/patches/46A7ECA4.pnach | 4 + bin/patches/472C9E70.pnach | 6 + bin/patches/48FE0C71.pnach | 20 + bin/patches/49DA19CE.pnach | 4 + bin/patches/4B6DDB6B.pnach | 3 + bin/patches/4C4D7072.pnach | 11 + bin/patches/4C9EE7DF.pnach | 20 + bin/patches/4D6DBB75.pnach | 4 + bin/patches/4DAC50C2.pnach | 5 + bin/patches/4F3D3CF0.pnach | 5 + bin/patches/506644B3.pnach | 5 + bin/patches/5162BCCA.pnach | 5 + bin/patches/51D8A6A9.pnach | 20 + bin/patches/53A803AF.pnach | 4 + bin/patches/53DF159B.pnach | 16 + bin/patches/54A548B4.pnach | 6 + bin/patches/54AD76D7.pnach | 8 + bin/patches/54D6BEE3.pnach | 4 + bin/patches/582EED0D.pnach | 8 + bin/patches/586EA828.pnach | 7 + bin/patches/58EE1AFA.pnach | 4 + bin/patches/5A7635C1.pnach | 4 + bin/patches/5BBC2F40.pnach | 20 + bin/patches/5BC8C9E8.pnach | 3 + bin/patches/5BE3F481.pnach | 4 + bin/patches/5CCA0737.pnach | 7 + bin/patches/5DFBE144.pnach | 8 + bin/patches/5E115FB6.pnach | 3 + bin/patches/5EB127E7.pnach | 4 + bin/patches/5F2A0E36.pnach | 7 + bin/patches/60013EBD.pnach | 5 + bin/patches/60FA8C69.pnach | 4 + bin/patches/624F11F1.pnach | 5 + bin/patches/625AF967.pnach | 4 + bin/patches/627B8252.pnach | 9 + bin/patches/62F6F886.pnach | 4 + bin/patches/63F6B523.pnach | 4 + bin/patches/68EAF48F.pnach | 8 + bin/patches/6926B199.pnach | 4 + bin/patches/692CBA8E.pnach | 4 + bin/patches/6A4EFE60.pnach | 4 + bin/patches/6ADBC24B.pnach | 6 + bin/patches/6BA2F6B9.pnach | 4 + bin/patches/6D70F0E0.pnach | 4 + bin/patches/6EA9DDA9.pnach | 4 + bin/patches/7098BE76.pnach | 6 + bin/patches/7130C553.pnach | 5 + bin/patches/71584BAC.pnach | 4 + bin/patches/722BBD62.pnach | 4 + bin/patches/7377BC6F.pnach | 4 + bin/patches/763D3BF9.pnach | 8 + bin/patches/78168525.pnach | 3 + bin/patches/789D6B71.pnach | 4 + bin/patches/78E20421.pnach | 7 + bin/patches/78FFA39F.pnach | 10 + bin/patches/7ABDBB5E.pnach | 4 + bin/patches/7BA0128E.pnach | 3 + bin/patches/7CD1CDCD.pnach | 12 + bin/patches/7D8F539A.pnach | 7 + bin/patches/7FD7A1B9.pnach | 8 + bin/patches/83261085.pnach | 15 + bin/patches/83584608.pnach | 12 + bin/patches/83D0CE43.pnach | 7 + bin/patches/844B58EE.pnach | 4 + bin/patches/85AE91B3.pnach | 5 + bin/patches/85E92C92.pnach | 9 + bin/patches/8BC79F96.pnach | 9 + bin/patches/8BC95883.pnach | 4 + bin/patches/8BE3D7B2.pnach | 4 + bin/patches/8DC64680.pnach | 30 + bin/patches/8FDE8E16.pnach | 6 + bin/patches/93223BE4.pnach | 7 + bin/patches/934F9081.pnach | 4 + bin/patches/941BB7D9.pnach | 29 + bin/patches/94C56923.pnach | 4 + bin/patches/950241D3.pnach | 4 + bin/patches/951555A0.pnach | 4 + bin/patches/95BB1901.pnach | 3 + bin/patches/96B2F56D.pnach | 7 + bin/patches/96B76E56.pnach | 9 + bin/patches/96C20D6F.pnach | 4 + bin/patches/9AAC5309.pnach | 4 + bin/patches/9AAC530D.pnach | 6 + bin/patches/9AC65D6A.pnach | 4 + bin/patches/9B1EE9EB.pnach | 4 + bin/patches/9BE3F92D.pnach | 4 + bin/patches/9D6F46F0.pnach | 4 + bin/patches/A029B109.pnach | 12 + bin/patches/A1B752C7.pnach | 4 + bin/patches/A36CFF6C.pnach | 3 + bin/patches/A39517AB.pnach | 16 + bin/patches/A3ACF3C7.pnach | 8 + bin/patches/A4E2C043.pnach | 8 + bin/patches/A5BF36A8.pnach | 3 + bin/patches/A63C896C.pnach | 6 + bin/patches/A719D130.pnach | 4 + bin/patches/A74F99CD.pnach | 4 + bin/patches/A7A2F7C5.pnach | 16 + bin/patches/A88ACA28.pnach | 9 + bin/patches/A929A697.pnach | 3 + bin/patches/A9759015.pnach | 9 + bin/patches/AC7E88D9.pnach | 18 + bin/patches/ACB1989A.pnach | 10 + bin/patches/AD9D2B54.pnach | 4 + bin/patches/ADAA1256.pnach | 8 + bin/patches/AE0E098F.pnach | 6 + bin/patches/AE3EAA05.pnach | 13 + bin/patches/AE9EB9A0.pnach | 4 + bin/patches/AEDAEE99.pnach | 3 + bin/patches/AFAC88EF.pnach | 14 + bin/patches/B0AE1898.pnach | 6 + bin/patches/B1BE3E51.pnach | 6 + bin/patches/B234036E.pnach | 4 + bin/patches/B2BDE9F3.pnach | 6 + bin/patches/B338676A.pnach | 6 + bin/patches/B34DA141.pnach | 8 + bin/patches/B36EE21E.pnach | 5 + bin/patches/B590CE04.pnach | 5 + bin/patches/B82E4C4B.pnach | 4 + bin/patches/B99379B7.pnach | 4 + bin/patches/BB3D833A.pnach | 4 + bin/patches/BD3DBCF9.pnach | 4 + bin/patches/BF5D9AEC.pnach | 4 + bin/patches/C04FB5FD.pnach | 4 + bin/patches/C1625F14.pnach | 9 + bin/patches/C1767D64.pnach | 5 + bin/patches/C1B141D6.pnach | 7 + bin/patches/C220951A.pnach | 5 + bin/patches/C3D28EB9.pnach | 4 + bin/patches/C4467D30.pnach | 4 + bin/patches/C488EC04.pnach | 8 + bin/patches/C4A60986.pnach | 4 + bin/patches/C502AD6E.pnach | 8 + bin/patches/C5DEFEA0.pnach | 5 + bin/patches/C9246E9C.pnach | 4 + bin/patches/C9C145BF.pnach | 10 + bin/patches/CA295E61.pnach | 4 + bin/patches/CA6243B9.pnach | 9 + bin/patches/CB4EBD11.pnach | 7 + bin/patches/CBBC2E7F.pnach | 15 + bin/patches/CC4B9CDE.pnach | 4 + bin/patches/CC6AA742.pnach | 4 + bin/patches/CDE7C999.pnach | 22 + bin/patches/CF11CD83.pnach | 6 + bin/patches/CFB873AD.pnach | 6 + bin/patches/D03BEF2A.pnach | 13 + bin/patches/D08648B6.pnach | 3 + bin/patches/D0E17D26.pnach | 4 + bin/patches/D1ACD489.pnach | 5 + bin/patches/D4781770.pnach | 6 + bin/patches/D48A92E1.pnach | 10 + bin/patches/D4FB6049.pnach | 3 + bin/patches/D79F697A.pnach | 4 + bin/patches/DAC14B26.pnach | 7 + bin/patches/DB719F5C.pnach | 7 + bin/patches/DC85FC8F.pnach | 4 + bin/patches/DCC4EEEA.pnach | 10 + bin/patches/DDA2FA6A.pnach | 4 + bin/patches/E0127F2D.pnach | 5 + bin/patches/E0426FC6.pnach | 8 + bin/patches/E0DADD1A.pnach | 5 + bin/patches/E138094A.pnach | 7 + bin/patches/E1C5F607.pnach | 6 + bin/patches/E2F1DB6B.pnach | 6 + bin/patches/E4A275B2.pnach | 4 + bin/patches/E677B8F1.pnach | 7 + bin/patches/E7A35274.pnach | 4 + bin/patches/E906EA37.pnach | 7 + bin/patches/EAD76247.pnach | 19 + bin/patches/EADE437E.pnach | 4 + bin/patches/EDD7E0FF.pnach | 4 + bin/patches/EE838B5C.pnach | 7 + bin/patches/EEC3B310.pnach | 9 + bin/patches/EF5B6AAD.pnach | 4 + bin/patches/EF9E43EF.pnach | 5 + bin/patches/F1370E83.pnach | 4 + bin/patches/F22CDDAF.pnach | 4 + bin/patches/F4992CC1.pnach | 4 + bin/patches/F52FB2BE.pnach | 4 + bin/patches/F56C7948.pnach | 4 + bin/patches/F5C7B45F.pnach | 4 + bin/patches/F6DC728D.pnach | 4 + bin/patches/F758234F.pnach | 7 + bin/patches/F9E575D0.pnach | 4 + bin/patches/FAC64195.pnach | 3 + bin/patches/FB0E6D72.pnach | 6 + bin/patches/FC618D82.pnach | 8 + bin/patches/FEA030CB.pnach | 23 + bin/patches/FF920E90.pnach | 8 + bin/patches/default.xml | 0 branches/pcsx2_0.9.1/CDVD.c | 1806 ++ branches/pcsx2_0.9.1/CDVD.h | 144 + branches/pcsx2_0.9.1/CDVDiso.c | 834 + branches/pcsx2_0.9.1/CDVDiso.h | 131 + branches/pcsx2_0.9.1/CDVDisodrv.c | 263 + branches/pcsx2_0.9.1/CDVDisodrv.h | 22 + branches/pcsx2_0.9.1/CDVDlib.h | 185 + branches/pcsx2_0.9.1/COP0.c | 318 + branches/pcsx2_0.9.1/COP0.h | 27 + branches/pcsx2_0.9.1/Cache.c | 355 + branches/pcsx2_0.9.1/Cache.h | 34 + branches/pcsx2_0.9.1/CdRom.c | 1078 + branches/pcsx2_0.9.1/CdRom.h | 92 + branches/pcsx2_0.9.1/Common.h | 260 + branches/pcsx2_0.9.1/Counters.c | 493 + branches/pcsx2_0.9.1/Counters.h | 46 + branches/pcsx2_0.9.1/DebugTools/Debug.h | 135 + branches/pcsx2_0.9.1/DebugTools/DisASM.h | 54 + branches/pcsx2_0.9.1/DebugTools/DisR3000A.c | 318 + branches/pcsx2_0.9.1/DebugTools/DisR3000asm.c | 361 + branches/pcsx2_0.9.1/DebugTools/DisR5900.c | 993 + branches/pcsx2_0.9.1/DebugTools/DisR5900asm.c | 1679 ++ branches/pcsx2_0.9.1/DebugTools/DisVU0Micro.c | 84 + branches/pcsx2_0.9.1/DebugTools/DisVU1Micro.c | 123 + branches/pcsx2_0.9.1/DebugTools/DisVUmicro.h | 209 + branches/pcsx2_0.9.1/DebugTools/DisVUops.h | 197 + branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.c | 1063 + branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.h | 456 + branches/pcsx2_0.9.1/Decode_XA.c | 305 + branches/pcsx2_0.9.1/Decode_XA.h | 26 + branches/pcsx2_0.9.1/Docs/BetaTesters.txt | 13 + branches/pcsx2_0.9.1/Docs/ChangeLog.txt | 2742 ++ branches/pcsx2_0.9.1/Docs/License.txt | 342 + branches/pcsx2_0.9.1/Docs/PS2Edefs.txt | 443 + branches/pcsx2_0.9.1/Docs/Readme.txt | 196 + branches/pcsx2_0.9.1/Docs/RemoteDebugging.txt | 105 + branches/pcsx2_0.9.1/Docs/RunCDVD.txt | 86 + branches/pcsx2_0.9.1/Docs/ToDo.txt | 22 + branches/pcsx2_0.9.1/Docs/Translating.txt | 24 + branches/pcsx2_0.9.1/Docs/What_Is_Host.txt | 45 + branches/pcsx2_0.9.1/Docs/WhatsNew.txt | 598 + branches/pcsx2_0.9.1/Docs/devblog.txt | 272 + .../pcsx2_0.9.1/Docs/efpchangesv0.9linux.txt | 112 + branches/pcsx2_0.9.1/Docs/pcsx2_faq.txt | 229 + branches/pcsx2_0.9.1/Docs/specs.tex | 159 + branches/pcsx2_0.9.1/Docs/threads.txt | 34 + branches/pcsx2_0.9.1/EEregs.h | 40 + branches/pcsx2_0.9.1/Elfheader.c | 631 + branches/pcsx2_0.9.1/Elfheader.h | 30 + branches/pcsx2_0.9.1/FPU.c | 174 + branches/pcsx2_0.9.1/FPU2.cpp | 25 + branches/pcsx2_0.9.1/FiFo.c | 181 + branches/pcsx2_0.9.1/GS.c | 1707 ++ branches/pcsx2_0.9.1/GS.h | 126 + branches/pcsx2_0.9.1/Gte.c | 2846 ++ branches/pcsx2_0.9.1/Gte.h | 52 + branches/pcsx2_0.9.1/Hw.c | 2620 ++ branches/pcsx2_0.9.1/Hw.h | 400 + branches/pcsx2_0.9.1/IPU/IPU.c | 1865 ++ branches/pcsx2_0.9.1/IPU/IPU.h | 209 + branches/pcsx2_0.9.1/IPU/idct_mmx.obj | Bin 0 -> 11510 bytes branches/pcsx2_0.9.1/IPU/mpeg2lib/Idct.c | 302 + branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.c | 1252 + branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.h | 185 + branches/pcsx2_0.9.1/IPU/mpeg2lib/Vlc.h | 441 + branches/pcsx2_0.9.1/IPU/yuv2rgb.c | 510 + branches/pcsx2_0.9.1/IPU/yuv2rgb.h | 57 + branches/pcsx2_0.9.1/InterTables.c | 224 + branches/pcsx2_0.9.1/InterTables.h | 491 + branches/pcsx2_0.9.1/Interpreter.c | 1072 + .../pcsx2_0.9.1/Linux/.pixmaps/pcsxAbout.xpm | 334 + branches/pcsx2_0.9.1/Linux/Config.c | 137 + branches/pcsx2_0.9.1/Linux/GladeCalls.c | 828 + branches/pcsx2_0.9.1/Linux/GladeCalls.h | 411 + branches/pcsx2_0.9.1/Linux/GladeFuncs.c | 162 + branches/pcsx2_0.9.1/Linux/GladeFuncs.h | 61 + branches/pcsx2_0.9.1/Linux/GladeGui.c | 3008 +++ branches/pcsx2_0.9.1/Linux/GladeGui.h | 17 + branches/pcsx2_0.9.1/Linux/GtkGui.c | 1481 + branches/pcsx2_0.9.1/Linux/Linux.h | 47 + branches/pcsx2_0.9.1/Linux/LnxMain.c | 327 + branches/pcsx2_0.9.1/Linux/Makefile | 106 + branches/pcsx2_0.9.1/Linux/Makefile.cfg.in | 6 + branches/pcsx2_0.9.1/Linux/configure.in | 33 + branches/pcsx2_0.9.1/Linux/pcsx2.glade | 4413 +++ branches/pcsx2_0.9.1/MMI.c | 1475 + branches/pcsx2_0.9.1/Mdec.c | 521 + branches/pcsx2_0.9.1/Mdec.h | 31 + branches/pcsx2_0.9.1/Memory.c | 3097 +++ branches/pcsx2_0.9.1/Memory.h | 263 + branches/pcsx2_0.9.1/Misc.c | 816 + branches/pcsx2_0.9.1/Misc.h | 158 + branches/pcsx2_0.9.1/PS2Edefs.h | 803 + branches/pcsx2_0.9.1/PS2Etypes.h | 47 + branches/pcsx2_0.9.1/Patch.c | 322 + branches/pcsx2_0.9.1/Patch.h | 10 + branches/pcsx2_0.9.1/Plugins.c | 603 + branches/pcsx2_0.9.1/Plugins.h | 32 + branches/pcsx2_0.9.1/PsxBios.c | 300 + branches/pcsx2_0.9.1/PsxBios.h | 35 + branches/pcsx2_0.9.1/PsxBios2.h | 94 + branches/pcsx2_0.9.1/PsxCommon.h | 50 + branches/pcsx2_0.9.1/PsxCounters.c | 642 + branches/pcsx2_0.9.1/PsxCounters.h | 56 + branches/pcsx2_0.9.1/PsxDma.c | 254 + branches/pcsx2_0.9.1/PsxDma.h | 42 + branches/pcsx2_0.9.1/PsxGPU.c | 1067 + branches/pcsx2_0.9.1/PsxGPU.h | 32 + branches/pcsx2_0.9.1/PsxHw.c | 2850 ++ branches/pcsx2_0.9.1/PsxHw.h | 117 + branches/pcsx2_0.9.1/PsxInterpreter.c | 782 + branches/pcsx2_0.9.1/PsxMem.c | 1605 ++ branches/pcsx2_0.9.1/PsxMem.h | 113 + branches/pcsx2_0.9.1/PsxSio2.c | 249 + branches/pcsx2_0.9.1/PsxSio2.h | 98 + branches/pcsx2_0.9.1/R3000A.c | 214 + branches/pcsx2_0.9.1/R3000A.h | 213 + branches/pcsx2_0.9.1/R5900.c | 506 + branches/pcsx2_0.9.1/R5900.h | 276 + branches/pcsx2_0.9.1/RDebug/deci2.c | 26 + branches/pcsx2_0.9.1/RDebug/deci2.h | 66 + branches/pcsx2_0.9.1/RDebug/deci2.txt | 27 + branches/pcsx2_0.9.1/RDebug/deci2_dbgp.c | 410 + branches/pcsx2_0.9.1/RDebug/deci2_dbgp.h | 28 + branches/pcsx2_0.9.1/RDebug/deci2_dcmp.c | 83 + branches/pcsx2_0.9.1/RDebug/deci2_dcmp.h | 28 + branches/pcsx2_0.9.1/RDebug/deci2_drfp.c | 46 + branches/pcsx2_0.9.1/RDebug/deci2_drfp.h | 27 + branches/pcsx2_0.9.1/RDebug/deci2_iloadp.c | 106 + branches/pcsx2_0.9.1/RDebug/deci2_iloadp.h | 27 + branches/pcsx2_0.9.1/RDebug/deci2_netmp.c | 134 + branches/pcsx2_0.9.1/RDebug/deci2_netmp.h | 27 + branches/pcsx2_0.9.1/RDebug/deci2_ttyp.c | 41 + branches/pcsx2_0.9.1/RDebug/deci2_ttyp.h | 28 + branches/pcsx2_0.9.1/RDebug/iloadp.txt | 32 + branches/pcsx2_0.9.1/SPR.c | 385 + branches/pcsx2_0.9.1/SPR.h | 29 + branches/pcsx2_0.9.1/Sif.c | 616 + branches/pcsx2_0.9.1/Sif.h | 49 + branches/pcsx2_0.9.1/Sifcmd.h | 193 + branches/pcsx2_0.9.1/Sio.c | 566 + branches/pcsx2_0.9.1/Sio.h | 114 + branches/pcsx2_0.9.1/Stats.c | 70 + branches/pcsx2_0.9.1/Stats.h | 43 + branches/pcsx2_0.9.1/System.h | 59 + branches/pcsx2_0.9.1/VU.h | 174 + branches/pcsx2_0.9.1/VU0.c | 383 + branches/pcsx2_0.9.1/VU0.h | 49 + branches/pcsx2_0.9.1/VU0micro.c | 712 + branches/pcsx2_0.9.1/VU1micro.c | 665 + branches/pcsx2_0.9.1/VUflags.c | 96 + branches/pcsx2_0.9.1/VUflags.h | 38 + branches/pcsx2_0.9.1/VUmicro.h | 1263 + branches/pcsx2_0.9.1/VUops.c | 2945 ++ branches/pcsx2_0.9.1/VUops.h | 393 + branches/pcsx2_0.9.1/Vif.c | 2950 ++ branches/pcsx2_0.9.1/Vif.h | 108 + branches/pcsx2_0.9.1/VifDma.c | 1872 ++ branches/pcsx2_0.9.1/VifDma.h | 120 + branches/pcsx2_0.9.1/ix86-32/iR5900Arit.c | 1996 ++ branches/pcsx2_0.9.1/ix86-32/iR5900Arit.h | 45 + branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.c | 659 + branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.h | 41 + branches/pcsx2_0.9.1/ix86-32/iR5900Branch.c | 1087 + branches/pcsx2_0.9.1/ix86-32/iR5900Branch.h | 47 + branches/pcsx2_0.9.1/ix86-32/iR5900Jump.c | 131 + branches/pcsx2_0.9.1/ix86-32/iR5900Jump.h | 35 + .../pcsx2_0.9.1/ix86-32/iR5900LoadStore.c | 4218 +++ .../pcsx2_0.9.1/ix86-32/iR5900LoadStore.h | 90 + branches/pcsx2_0.9.1/ix86-32/iR5900Move.c | 822 + branches/pcsx2_0.9.1/ix86-32/iR5900Move.h | 33 + branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.c | 949 + branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.h | 35 + branches/pcsx2_0.9.1/ix86-32/iR5900Shift.c | 1349 + branches/pcsx2_0.9.1/ix86-32/iR5900Shift.h | 47 + branches/pcsx2_0.9.1/memcpy_amd.cpp | 590 + branches/pcsx2_0.9.1/pcl/pcl.c | 490 + branches/pcsx2_0.9.1/pcl/pcl.h | 49 + branches/pcsx2_0.9.1/pcl/pcl_config.h | 60 + branches/pcsx2_0.9.1/pcsxAbout.bmp | Bin 0 -> 251192 bytes branches/pcsx2_0.9.1/windows/AboutDlg.c | 65 + branches/pcsx2_0.9.1/windows/AboutDlg.h | 24 + branches/pcsx2_0.9.1/windows/Cdrom02.ico | Bin 0 -> 12862 bytes branches/pcsx2_0.9.1/windows/ConfigDlg.c | 499 + branches/pcsx2_0.9.1/windows/CpuDlg.c | 120 + branches/pcsx2_0.9.1/windows/DebugMemory.c | 239 + branches/pcsx2_0.9.1/windows/Debugger.c | 562 + branches/pcsx2_0.9.1/windows/Debugger.h | 54 + branches/pcsx2_0.9.1/windows/Debugreg.c | 1483 + branches/pcsx2_0.9.1/windows/Makefile | 108 + branches/pcsx2_0.9.1/windows/McdsDlg.c | 124 + branches/pcsx2_0.9.1/windows/McdsDlg.h | 24 + branches/pcsx2_0.9.1/windows/PatchBrowser.c | 352 + branches/pcsx2_0.9.1/windows/RDebugger.c | 375 + branches/pcsx2_0.9.1/windows/RDebugger.h | 26 + .../windows/VCprojects/pcsx2_2003.sln | 30 + .../windows/VCprojects/pcsx2_2003.vcproj | 1216 + .../windows/VCprojects/pcsx2_2005.sln | 25 + .../windows/VCprojects/pcsx2_2005.vcproj | 1439 + .../VCprojects/pcsx2_2005beta1_64bits.sln | 20 + .../VCprojects/pcsx2_2005beta1_64bits.vcproj | 1358 + branches/pcsx2_0.9.1/windows/Win32.h | 49 + branches/pcsx2_0.9.1/windows/WinMain.c | 1849 ++ branches/pcsx2_0.9.1/windows/afxresmw.h | 5 + branches/pcsx2_0.9.1/windows/ini.c | 173 + .../pcsx2_0.9.1/windows/libs/gnu_gettext.lib | Bin 0 -> 2916 bytes .../pcsx2_0.9.1/windows/libs/libintlmsc.h | 116 + branches/pcsx2_0.9.1/windows/libs/pthread.h | 1368 + .../pcsx2_0.9.1/windows/libs/pthreadVC2.lib | Bin 0 -> 29280 bytes branches/pcsx2_0.9.1/windows/libs/sched.h | 178 + branches/pcsx2_0.9.1/windows/libs/semaphore.h | 166 + .../pcsx2_0.9.1/windows/mingw/Makefile.win | 348 + branches/pcsx2_0.9.1/windows/mingw/afxres.h | 5 + branches/pcsx2_0.9.1/windows/mingw/pcsx2.dev | 2116 ++ .../pcsx2_0.9.1/windows/mingw/pcsx2.layout | 1424 + .../pcsx2_0.9.1/windows/mingw/pcsx2_private.h | 23 + .../windows/mingw/pcsx2_private.rc | 5 + branches/pcsx2_0.9.1/windows/pcsx2.rc | 1417 + branches/pcsx2_0.9.1/windows/ps2_silver.bmp | Bin 0 -> 37974 bytes branches/pcsx2_0.9.1/windows/pthreadVC2.lib | Bin 0 -> 29280 bytes branches/pcsx2_0.9.1/windows/resource.h | 640 + branches/pcsx2_0.9.1/x86-64/iR5900Arit.c | 542 + branches/pcsx2_0.9.1/x86-64/iR5900Arit.h | 45 + branches/pcsx2_0.9.1/x86-64/iR5900AritImm.c | 314 + branches/pcsx2_0.9.1/x86-64/iR5900AritImm.h | 41 + branches/pcsx2_0.9.1/x86-64/iR5900Branch.c | 341 + branches/pcsx2_0.9.1/x86-64/iR5900Branch.h | 47 + branches/pcsx2_0.9.1/x86-64/iR5900Jump.c | 84 + branches/pcsx2_0.9.1/x86-64/iR5900Jump.h | 35 + branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.c | 554 + branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.h | 56 + branches/pcsx2_0.9.1/x86-64/iR5900Move.c | 256 + branches/pcsx2_0.9.1/x86-64/iR5900Move.h | 33 + branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.c | 138 + branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.h | 35 + branches/pcsx2_0.9.1/x86-64/iR5900Shift.c | 761 + branches/pcsx2_0.9.1/x86-64/iR5900Shift.h | 47 + branches/pcsx2_0.9.1/x86/iCP0.c | 245 + branches/pcsx2_0.9.1/x86/iCP0.h | 42 + branches/pcsx2_0.9.1/x86/iCore.cpp | 2368 ++ branches/pcsx2_0.9.1/x86/iCore.h | 416 + branches/pcsx2_0.9.1/x86/iFPU.c | 1364 + branches/pcsx2_0.9.1/x86/iFPU.h | 60 + branches/pcsx2_0.9.1/x86/iMMI.c | 3337 +++ branches/pcsx2_0.9.1/x86/iMMI.h | 133 + branches/pcsx2_0.9.1/x86/iR3000A.cpp | 1371 + branches/pcsx2_0.9.1/x86/iR3000A.h | 99 + branches/pcsx2_0.9.1/x86/iR3000Atables.cpp | 2054 ++ branches/pcsx2_0.9.1/x86/iR5900.c | 3118 +++ branches/pcsx2_0.9.1/x86/iR5900.h | 256 + branches/pcsx2_0.9.1/x86/iVU0micro.c | 789 + branches/pcsx2_0.9.1/x86/iVU0micro.h | 221 + branches/pcsx2_0.9.1/x86/iVU1micro.c | 201 + branches/pcsx2_0.9.1/x86/iVU1micro.h | 31 + branches/pcsx2_0.9.1/x86/iVUmicro.c | 4541 ++++ branches/pcsx2_0.9.1/x86/iVUmicro.h | 274 + branches/pcsx2_0.9.1/x86/iVUops.h | 47 + branches/pcsx2_0.9.1/x86/iVUzerorec.cpp | 3639 +++ branches/pcsx2_0.9.1/x86/iVUzerorec.h | 49 + branches/pcsx2_0.9.1/x86/ir5900tables.c | 1362 + branches/pcsx2_0.9.1/x86/ix86/ix86.c | 3086 +++ branches/pcsx2_0.9.1/x86/ix86/ix86.h | 1637 ++ branches/pcsx2_0.9.1/x86/ix86/ix86_3dnow.c | 184 + .../pcsx2_0.9.1/x86/ix86/ix86_cpudetect.c | 482 + branches/pcsx2_0.9.1/x86/ix86/ix86_fpu.c | 269 + branches/pcsx2_0.9.1/x86/ix86/ix86_mmx.c | 632 + branches/pcsx2_0.9.1/x86/ix86/ix86_sse.c | 1540 ++ branches/pcsx2_0.9.1/x86/recCOP2.c | 739 + branches/pcsx2_0.9.1/zlib/ChangeLog | 722 + branches/pcsx2_0.9.1/zlib/README | 126 + branches/pcsx2_0.9.1/zlib/adler32.c | 74 + branches/pcsx2_0.9.1/zlib/compress.c | 79 + branches/pcsx2_0.9.1/zlib/crc32.c | 311 + branches/pcsx2_0.9.1/zlib/crc32.h | 441 + branches/pcsx2_0.9.1/zlib/deflate.c | 1502 ++ branches/pcsx2_0.9.1/zlib/deflate.h | 326 + branches/pcsx2_0.9.1/zlib/gzio.c | 1005 + branches/pcsx2_0.9.1/zlib/infback.c | 619 + branches/pcsx2_0.9.1/zlib/inffast.c | 305 + branches/pcsx2_0.9.1/zlib/inffast.h | 11 + branches/pcsx2_0.9.1/zlib/inffixed.h | 94 + branches/pcsx2_0.9.1/zlib/inflate.c | 1270 + branches/pcsx2_0.9.1/zlib/inflate.h | 117 + branches/pcsx2_0.9.1/zlib/inftrees.c | 321 + branches/pcsx2_0.9.1/zlib/inftrees.h | 55 + branches/pcsx2_0.9.1/zlib/trees.c | 1215 + branches/pcsx2_0.9.1/zlib/trees.h | 128 + branches/pcsx2_0.9.1/zlib/uncompr.c | 61 + branches/pcsx2_0.9.1/zlib/zconf.h | 323 + branches/pcsx2_0.9.1/zlib/zlib.h | 1200 + branches/pcsx2_0.9.1/zlib/zutil.c | 319 + branches/pcsx2_0.9.1/zlib/zutil.h | 258 + branches/pcsx2_0.9.2/CDVD.c | 1852 ++ branches/pcsx2_0.9.2/CDVD.h | 144 + branches/pcsx2_0.9.2/CDVDiso.c | 835 + branches/pcsx2_0.9.2/CDVDiso.h | 131 + branches/pcsx2_0.9.2/CDVDisodrv.c | 263 + branches/pcsx2_0.9.2/CDVDisodrv.h | 22 + branches/pcsx2_0.9.2/CDVDlib.h | 185 + branches/pcsx2_0.9.2/COP0.c | 363 + branches/pcsx2_0.9.2/COP0.h | 27 + branches/pcsx2_0.9.2/Cache.c | 355 + branches/pcsx2_0.9.2/Cache.h | 34 + branches/pcsx2_0.9.2/CdRom.c | 1078 + branches/pcsx2_0.9.2/CdRom.h | 92 + branches/pcsx2_0.9.2/Common.h | 277 + branches/pcsx2_0.9.2/Counters.c | 654 + branches/pcsx2_0.9.2/Counters.h | 46 + branches/pcsx2_0.9.2/DebugTools/Debug.h | 137 + branches/pcsx2_0.9.2/DebugTools/DisASM.h | 54 + branches/pcsx2_0.9.2/DebugTools/DisR3000A.c | 318 + branches/pcsx2_0.9.2/DebugTools/DisR3000asm.c | 361 + branches/pcsx2_0.9.2/DebugTools/DisR5900.c | 993 + branches/pcsx2_0.9.2/DebugTools/DisR5900asm.c | 1679 ++ branches/pcsx2_0.9.2/DebugTools/DisVU0Micro.c | 84 + branches/pcsx2_0.9.2/DebugTools/DisVU1Micro.c | 123 + branches/pcsx2_0.9.2/DebugTools/DisVUmicro.h | 209 + branches/pcsx2_0.9.2/DebugTools/DisVUops.h | 197 + branches/pcsx2_0.9.2/DebugTools/Makefile.am | 7 + branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.c | 1063 + branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.h | 456 + branches/pcsx2_0.9.2/Decode_XA.c | 305 + branches/pcsx2_0.9.2/Decode_XA.h | 26 + branches/pcsx2_0.9.2/Docs/BetaTesters.txt | 13 + branches/pcsx2_0.9.2/Docs/ChangeLog.txt | 2848 ++ branches/pcsx2_0.9.2/Docs/License.txt | 342 + branches/pcsx2_0.9.2/Docs/PS2Edefs.txt | 443 + branches/pcsx2_0.9.2/Docs/Readme.txt | 196 + branches/pcsx2_0.9.2/Docs/RemoteDebugging.txt | 105 + branches/pcsx2_0.9.2/Docs/RunCDVD.txt | 86 + branches/pcsx2_0.9.2/Docs/ToDo.txt | 22 + branches/pcsx2_0.9.2/Docs/Translating.txt | 24 + branches/pcsx2_0.9.2/Docs/What_Is_Host.txt | 45 + branches/pcsx2_0.9.2/Docs/WhatsNew.txt | 598 + branches/pcsx2_0.9.2/Docs/devblog.txt | 273 + .../pcsx2_0.9.2/Docs/efpchangesv0.9linux.txt | 112 + branches/pcsx2_0.9.2/Docs/pcsx2_faq.txt | 229 + branches/pcsx2_0.9.2/Docs/specs.tex | 159 + branches/pcsx2_0.9.2/Docs/threads.txt | 34 + branches/pcsx2_0.9.2/EEregs.h | 40 + branches/pcsx2_0.9.2/Elfheader.c | 660 + branches/pcsx2_0.9.2/Elfheader.h | 30 + branches/pcsx2_0.9.2/FPU.c | 174 + branches/pcsx2_0.9.2/FPU2.cpp | 25 + branches/pcsx2_0.9.2/FiFo.c | 177 + branches/pcsx2_0.9.2/GS.cpp | 1989 ++ branches/pcsx2_0.9.2/GS.h | 218 + branches/pcsx2_0.9.2/Gte.h | 52 + branches/pcsx2_0.9.2/Hw.c | 2643 ++ branches/pcsx2_0.9.2/Hw.h | 408 + branches/pcsx2_0.9.2/INSTALL.txt | 24 + branches/pcsx2_0.9.2/IPU/IPU.c | 1965 ++ branches/pcsx2_0.9.2/IPU/IPU.h | 204 + branches/pcsx2_0.9.2/IPU/Makefile.am | 8 + branches/pcsx2_0.9.2/IPU/idct_mmx.obj | Bin 0 -> 11510 bytes branches/pcsx2_0.9.2/IPU/mpeg2lib/Idct.c | 302 + branches/pcsx2_0.9.2/IPU/mpeg2lib/Makefile.am | 4 + branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.c | 1281 + branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.h | 186 + branches/pcsx2_0.9.2/IPU/mpeg2lib/Vlc.h | 441 + branches/pcsx2_0.9.2/IPU/yuv2rgb.asm | 242 + branches/pcsx2_0.9.2/IPU/yuv2rgb.c | 510 + branches/pcsx2_0.9.2/IPU/yuv2rgb.h | 57 + branches/pcsx2_0.9.2/InterTables.c | 224 + branches/pcsx2_0.9.2/InterTables.h | 491 + branches/pcsx2_0.9.2/Interpreter.c | 1058 + .../pcsx2_0.9.2/Linux/.pixmaps/pcsxAbout.xpm | 334 + branches/pcsx2_0.9.2/Linux/Config.c | 137 + branches/pcsx2_0.9.2/Linux/GladeCalls.c | 828 + branches/pcsx2_0.9.2/Linux/GladeCalls.h | 411 + branches/pcsx2_0.9.2/Linux/GladeFuncs.c | 162 + branches/pcsx2_0.9.2/Linux/GladeFuncs.h | 61 + branches/pcsx2_0.9.2/Linux/GladeGui.c | 3008 +++ branches/pcsx2_0.9.2/Linux/GladeGui.h | 17 + branches/pcsx2_0.9.2/Linux/GtkGui.c | 1481 + branches/pcsx2_0.9.2/Linux/Linux.h | 47 + branches/pcsx2_0.9.2/Linux/LnxMain.c | 327 + branches/pcsx2_0.9.2/Linux/Makefile.am | 16 + branches/pcsx2_0.9.2/MMI.c | 1475 + branches/pcsx2_0.9.2/Makefile.am | 23 + branches/pcsx2_0.9.2/Mdec.c | 521 + branches/pcsx2_0.9.2/Mdec.h | 31 + branches/pcsx2_0.9.2/Memory.c | 3056 +++ branches/pcsx2_0.9.2/Memory.h | 263 + branches/pcsx2_0.9.2/Misc.c | 895 + branches/pcsx2_0.9.2/Misc.h | 210 + branches/pcsx2_0.9.2/PS2Edefs.h | 805 + branches/pcsx2_0.9.2/PS2Etypes.h | 75 + branches/pcsx2_0.9.2/Patch.c | 381 + branches/pcsx2_0.9.2/Patch.h | 78 + branches/pcsx2_0.9.2/Plugins.c | 607 + branches/pcsx2_0.9.2/Plugins.h | 32 + branches/pcsx2_0.9.2/PsxBios.c | 300 + branches/pcsx2_0.9.2/PsxBios.h | 35 + branches/pcsx2_0.9.2/PsxBios2.h | 94 + branches/pcsx2_0.9.2/PsxCommon.h | 46 + branches/pcsx2_0.9.2/PsxCounters.c | 631 + branches/pcsx2_0.9.2/PsxCounters.h | 55 + branches/pcsx2_0.9.2/PsxDma.c | 255 + branches/pcsx2_0.9.2/PsxDma.h | 42 + branches/pcsx2_0.9.2/PsxGPU.c | 1067 + branches/pcsx2_0.9.2/PsxGPU.h | 32 + branches/pcsx2_0.9.2/PsxHw.c | 2941 ++ branches/pcsx2_0.9.2/PsxHw.h | 117 + branches/pcsx2_0.9.2/PsxInterpreter.c | 782 + branches/pcsx2_0.9.2/PsxMem.c | 1605 ++ branches/pcsx2_0.9.2/PsxMem.h | 113 + branches/pcsx2_0.9.2/PsxSio2.c | 251 + branches/pcsx2_0.9.2/PsxSio2.h | 98 + branches/pcsx2_0.9.2/R3000A.c | 213 + branches/pcsx2_0.9.2/R3000A.h | 213 + branches/pcsx2_0.9.2/R5900.c | 578 + branches/pcsx2_0.9.2/R5900.h | 285 + branches/pcsx2_0.9.2/RDebug/Makefile.am | 7 + branches/pcsx2_0.9.2/RDebug/deci2.c | 26 + branches/pcsx2_0.9.2/RDebug/deci2.h | 66 + branches/pcsx2_0.9.2/RDebug/deci2.txt | 27 + branches/pcsx2_0.9.2/RDebug/deci2_dbgp.c | 410 + branches/pcsx2_0.9.2/RDebug/deci2_dbgp.h | 28 + branches/pcsx2_0.9.2/RDebug/deci2_dcmp.c | 83 + branches/pcsx2_0.9.2/RDebug/deci2_dcmp.h | 28 + branches/pcsx2_0.9.2/RDebug/deci2_drfp.c | 48 + branches/pcsx2_0.9.2/RDebug/deci2_drfp.h | 27 + branches/pcsx2_0.9.2/RDebug/deci2_iloadp.c | 106 + branches/pcsx2_0.9.2/RDebug/deci2_iloadp.h | 27 + branches/pcsx2_0.9.2/RDebug/deci2_netmp.c | 134 + branches/pcsx2_0.9.2/RDebug/deci2_netmp.h | 27 + branches/pcsx2_0.9.2/RDebug/deci2_ttyp.c | 41 + branches/pcsx2_0.9.2/RDebug/deci2_ttyp.h | 28 + branches/pcsx2_0.9.2/RDebug/iloadp.txt | 32 + branches/pcsx2_0.9.2/SPR.c | 399 + branches/pcsx2_0.9.2/SPR.h | 29 + branches/pcsx2_0.9.2/Sif.c | 616 + branches/pcsx2_0.9.2/Sif.h | 49 + branches/pcsx2_0.9.2/Sifcmd.h | 193 + branches/pcsx2_0.9.2/Sio.c | 566 + branches/pcsx2_0.9.2/Sio.h | 114 + branches/pcsx2_0.9.2/Stats.c | 71 + branches/pcsx2_0.9.2/Stats.h | 43 + branches/pcsx2_0.9.2/System.h | 59 + branches/pcsx2_0.9.2/VU.h | 174 + branches/pcsx2_0.9.2/VU0.c | 383 + branches/pcsx2_0.9.2/VU0.h | 49 + branches/pcsx2_0.9.2/VU0micro.c | 714 + branches/pcsx2_0.9.2/VU1micro.c | 669 + branches/pcsx2_0.9.2/VUflags.c | 95 + branches/pcsx2_0.9.2/VUflags.h | 38 + branches/pcsx2_0.9.2/VUmicro.h | 1263 + branches/pcsx2_0.9.2/VUops.c | 2959 ++ branches/pcsx2_0.9.2/VUops.h | 393 + branches/pcsx2_0.9.2/Vif.c | 989 + branches/pcsx2_0.9.2/Vif.h | 108 + branches/pcsx2_0.9.2/VifDma.c | 2347 ++ branches/pcsx2_0.9.2/VifDma.h | 164 + branches/pcsx2_0.9.2/cheatscpp.h | 31 + branches/pcsx2_0.9.2/configure.ac | 91 + branches/pcsx2_0.9.2/depcomp | 529 + branches/pcsx2_0.9.2/install-sh | 323 + branches/pcsx2_0.9.2/memcpy_amd.cpp | 612 + branches/pcsx2_0.9.2/missing | 360 + branches/pcsx2_0.9.2/mkinstalldirs | 158 + branches/pcsx2_0.9.2/pcl/Makefile.am | 3 + branches/pcsx2_0.9.2/pcl/pcl.c | 507 + branches/pcsx2_0.9.2/pcl/pcl.h | 49 + branches/pcsx2_0.9.2/pcl/pcl_config.h | 60 + branches/pcsx2_0.9.2/pcsxAbout.bmp | Bin 0 -> 251192 bytes branches/pcsx2_0.9.2/tinyxml/Makefile.am | 5 + branches/pcsx2_0.9.2/tinyxml/tinystr.cpp | 116 + branches/pcsx2_0.9.2/tinyxml/tinystr.h | 319 + branches/pcsx2_0.9.2/tinyxml/tinyxml.cpp | 1866 ++ branches/pcsx2_0.9.2/tinyxml/tinyxml.h | 1776 ++ branches/pcsx2_0.9.2/tinyxml/tinyxmlerror.cpp | 53 + .../pcsx2_0.9.2/tinyxml/tinyxmlparser.cpp | 1606 ++ .../pcsx2_0.9.2/tinyxml/xmlpatchloader.cpp | 352 + branches/pcsx2_0.9.2/windows/AboutDlg.c | 65 + branches/pcsx2_0.9.2/windows/AboutDlg.h | 24 + branches/pcsx2_0.9.2/windows/Cdrom02.ico | Bin 0 -> 12862 bytes branches/pcsx2_0.9.2/windows/ConfigDlg.c | 499 + branches/pcsx2_0.9.2/windows/CpuDlg.c | 138 + branches/pcsx2_0.9.2/windows/DebugMemory.c | 239 + branches/pcsx2_0.9.2/windows/Debugger.c | 562 + branches/pcsx2_0.9.2/windows/Debugger.h | 54 + branches/pcsx2_0.9.2/windows/Debugreg.c | 1483 + branches/pcsx2_0.9.2/windows/McdsDlg.c | 124 + branches/pcsx2_0.9.2/windows/McdsDlg.h | 24 + branches/pcsx2_0.9.2/windows/PatchBrowser.c | 352 + branches/pcsx2_0.9.2/windows/RDebugger.c | 375 + branches/pcsx2_0.9.2/windows/RDebugger.h | 26 + .../windows/VCprojects/pcsx2_2003.sln | 30 + .../windows/VCprojects/pcsx2_2003.vcproj | 1260 + .../windows/VCprojects/pcsx2_2005.sln | 25 + .../windows/VCprojects/pcsx2_2005.vcproj | 1535 ++ .../VCprojects/pcsx2_2005beta1_64bits.sln | 20 + .../VCprojects/pcsx2_2005beta1_64bits.vcproj | 1358 + branches/pcsx2_0.9.2/windows/Win32.h | 49 + branches/pcsx2_0.9.2/windows/WinMain.c | 1977 ++ branches/pcsx2_0.9.2/windows/afxresmw.h | 5 + .../pcsx2_0.9.2/windows/cheats/browser.cpp | 121 + .../pcsx2_0.9.2/windows/cheats/cheats.cpp | 600 + branches/pcsx2_0.9.2/windows/cheats/cheats.h | 19 + branches/pcsx2_0.9.2/windows/ini.c | 173 + .../pcsx2_0.9.2/windows/libs/gnu_gettext.lib | Bin 0 -> 2916 bytes .../pcsx2_0.9.2/windows/libs/libintlmsc.h | 116 + branches/pcsx2_0.9.2/windows/libs/pthread.h | 1368 + .../pcsx2_0.9.2/windows/libs/pthreadVC2.lib | Bin 0 -> 29280 bytes branches/pcsx2_0.9.2/windows/libs/sched.h | 178 + branches/pcsx2_0.9.2/windows/libs/semaphore.h | 166 + .../pcsx2_0.9.2/windows/mingw/Makefile.win | 348 + branches/pcsx2_0.9.2/windows/mingw/afxres.h | 5 + branches/pcsx2_0.9.2/windows/mingw/pcsx2.dev | 2116 ++ .../pcsx2_0.9.2/windows/mingw/pcsx2.layout | 1424 + .../pcsx2_0.9.2/windows/mingw/pcsx2_private.h | 23 + .../windows/mingw/pcsx2_private.rc | 5 + branches/pcsx2_0.9.2/windows/pcsx2.rc | 1535 ++ branches/pcsx2_0.9.2/windows/ps2_silver.bmp | Bin 0 -> 37974 bytes branches/pcsx2_0.9.2/windows/pthreadVC2.lib | Bin 0 -> 29280 bytes branches/pcsx2_0.9.2/windows/resource.h | 675 + branches/pcsx2_0.9.2/x86/Makefile.am | 18 + branches/pcsx2_0.9.2/x86/iCP0.c | 370 + branches/pcsx2_0.9.2/x86/iCP0.h | 42 + branches/pcsx2_0.9.2/x86/iCore.cpp | 2413 ++ branches/pcsx2_0.9.2/x86/iCore.h | 421 + branches/pcsx2_0.9.2/x86/iFPU.c | 1357 + branches/pcsx2_0.9.2/x86/iFPU.h | 60 + branches/pcsx2_0.9.2/x86/iMMI.c | 3370 +++ branches/pcsx2_0.9.2/x86/iMMI.h | 133 + branches/pcsx2_0.9.2/x86/iR3000A.cpp | 1376 + branches/pcsx2_0.9.2/x86/iR3000A.h | 99 + branches/pcsx2_0.9.2/x86/iR3000Atables.cpp | 2069 ++ branches/pcsx2_0.9.2/x86/iR5900-32.S | 181 + branches/pcsx2_0.9.2/x86/iR5900.c | 3187 +++ branches/pcsx2_0.9.2/x86/iR5900.h | 256 + branches/pcsx2_0.9.2/x86/iVU0micro.c | 790 + branches/pcsx2_0.9.2/x86/iVU0micro.h | 229 + branches/pcsx2_0.9.2/x86/iVU1micro.c | 229 + branches/pcsx2_0.9.2/x86/iVU1micro.h | 31 + branches/pcsx2_0.9.2/x86/iVUmicro.c | 4807 ++++ branches/pcsx2_0.9.2/x86/iVUmicro.h | 274 + branches/pcsx2_0.9.2/x86/iVUops.h | 47 + branches/pcsx2_0.9.2/x86/iVUzerorec.cpp | 4039 +++ branches/pcsx2_0.9.2/x86/iVUzerorec.h | 49 + branches/pcsx2_0.9.2/x86/iVif.S | 0 branches/pcsx2_0.9.2/x86/iVif.cpp | 2142 ++ branches/pcsx2_0.9.2/x86/ir5900tables.c | 1369 + branches/pcsx2_0.9.2/x86/ix86-32/Makefile.am | 8 + branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.c | 1996 ++ branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.h | 45 + .../pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.c | 659 + .../pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.h | 41 + .../pcsx2_0.9.2/x86/ix86-32/iR5900Branch.c | 1087 + .../pcsx2_0.9.2/x86/ix86-32/iR5900Branch.h | 47 + branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.c | 131 + branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.h | 35 + .../pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.c | 4286 +++ .../pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.h | 90 + branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.c | 836 + branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.h | 33 + .../pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.c | 953 + .../pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.h | 35 + .../pcsx2_0.9.2/x86/ix86-32/iR5900Shift.c | 1349 + .../pcsx2_0.9.2/x86/ix86-32/iR5900Shift.h | 47 + branches/pcsx2_0.9.2/x86/ix86-64/Makefile.am | 3 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.c | 542 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.h | 45 + .../pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.c | 314 + .../pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.h | 41 + .../pcsx2_0.9.2/x86/ix86-64/iR5900Branch.c | 341 + .../pcsx2_0.9.2/x86/ix86-64/iR5900Branch.h | 47 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.c | 84 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.h | 35 + .../pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.c | 554 + .../pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.h | 56 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.c | 256 + branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.h | 33 + .../pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.c | 138 + .../pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.h | 35 + .../pcsx2_0.9.2/x86/ix86-64/iR5900Shift.c | 761 + .../pcsx2_0.9.2/x86/ix86-64/iR5900Shift.h | 47 + branches/pcsx2_0.9.2/x86/ix86/Makefile.am | 4 + branches/pcsx2_0.9.2/x86/ix86/ix86.c | 3133 +++ branches/pcsx2_0.9.2/x86/ix86/ix86.h | 1642 ++ branches/pcsx2_0.9.2/x86/ix86/ix86_3dnow.c | 184 + .../pcsx2_0.9.2/x86/ix86/ix86_cpudetect.c | 500 + branches/pcsx2_0.9.2/x86/ix86/ix86_fpu.c | 269 + branches/pcsx2_0.9.2/x86/ix86/ix86_mmx.c | 632 + branches/pcsx2_0.9.2/x86/ix86/ix86_sse.c | 1582 ++ branches/pcsx2_0.9.2/x86/recCOP2.c | 744 + branches/pcsx2_0.9.2/zlib/ChangeLog | 722 + branches/pcsx2_0.9.2/zlib/Makefile.am | 6 + branches/pcsx2_0.9.2/zlib/README | 126 + branches/pcsx2_0.9.2/zlib/adler32.c | 74 + branches/pcsx2_0.9.2/zlib/compress.c | 79 + branches/pcsx2_0.9.2/zlib/crc32.c | 311 + branches/pcsx2_0.9.2/zlib/crc32.h | 441 + branches/pcsx2_0.9.2/zlib/deflate.c | 1502 ++ branches/pcsx2_0.9.2/zlib/deflate.h | 326 + branches/pcsx2_0.9.2/zlib/gzio.c | 1005 + branches/pcsx2_0.9.2/zlib/infback.c | 619 + branches/pcsx2_0.9.2/zlib/inffast.c | 305 + branches/pcsx2_0.9.2/zlib/inffast.h | 11 + branches/pcsx2_0.9.2/zlib/inffixed.h | 94 + branches/pcsx2_0.9.2/zlib/inflate.c | 1270 + branches/pcsx2_0.9.2/zlib/inflate.h | 117 + branches/pcsx2_0.9.2/zlib/inftrees.c | 321 + branches/pcsx2_0.9.2/zlib/inftrees.h | 55 + branches/pcsx2_0.9.2/zlib/trees.c | 1215 + branches/pcsx2_0.9.2/zlib/trees.h | 128 + branches/pcsx2_0.9.2/zlib/uncompr.c | 61 + branches/pcsx2_0.9.2/zlib/zconf.h | 323 + branches/pcsx2_0.9.2/zlib/zlib.h | 1200 + branches/pcsx2_0.9.2/zlib/zutil.c | 319 + branches/pcsx2_0.9.2/zlib/zutil.h | 258 + build.sh | 29 + pcsx2/CDVD.c | 1862 ++ pcsx2/CDVD.h | 144 + pcsx2/CDVDiso.c | 835 + pcsx2/CDVDiso.h | 131 + pcsx2/CDVDisodrv.c | 263 + pcsx2/CDVDisodrv.h | 22 + pcsx2/CDVDlib.h | 185 + pcsx2/COP0.c | 363 + pcsx2/COP0.h | 27 + pcsx2/Cache.c | 392 + pcsx2/Cache.h | 47 + pcsx2/CdRom.c | 1080 + pcsx2/CdRom.h | 92 + pcsx2/Common.h | 254 + pcsx2/Counters.c | 663 + pcsx2/Counters.h | 46 + pcsx2/DebugTools/Debug.h | 137 + pcsx2/DebugTools/DisASM.h | 54 + pcsx2/DebugTools/DisR3000A.c | 318 + pcsx2/DebugTools/DisR3000asm.c | 361 + pcsx2/DebugTools/DisR5900.c | 993 + pcsx2/DebugTools/DisR5900asm.c | 1679 ++ pcsx2/DebugTools/DisVU0Micro.c | 84 + pcsx2/DebugTools/DisVU1Micro.c | 123 + pcsx2/DebugTools/DisVUmicro.h | 209 + pcsx2/DebugTools/DisVUops.h | 197 + pcsx2/DebugTools/Makefile.am | 7 + pcsx2/DebugTools/cpuopsDebug.c | 1063 + pcsx2/DebugTools/cpuopsDebug.h | 456 + pcsx2/Decode_XA.c | 305 + pcsx2/Decode_XA.h | 26 + pcsx2/Docs/BetaTesters.txt | 13 + pcsx2/Docs/ChangeLog.txt | 2851 ++ pcsx2/Docs/License.txt | 342 + pcsx2/Docs/PS2Edefs.txt | 443 + pcsx2/Docs/Readme.txt | 196 + pcsx2/Docs/RemoteDebugging.txt | 105 + pcsx2/Docs/RunCDVD.txt | 86 + pcsx2/Docs/Translating.txt | 24 + pcsx2/Docs/What_Is_Host.txt | 45 + pcsx2/Docs/WhatsNew.txt | 598 + pcsx2/Docs/devblog.txt | 273 + pcsx2/Docs/pcsx2_faq.txt | 229 + pcsx2/Docs/specs.tex | 159 + pcsx2/EEregs.h | 40 + pcsx2/Elfheader.c | 689 + pcsx2/Elfheader.h | 30 + pcsx2/FPU.c | 174 + pcsx2/FPU2.cpp | 25 + pcsx2/FiFo.c | 179 + pcsx2/GS.cpp | 1757 ++ pcsx2/GS.h | 229 + pcsx2/Hw.c | 1471 + pcsx2/Hw.h | 419 + pcsx2/IPU/IPU.c | 2007 ++ pcsx2/IPU/IPU.h | 203 + pcsx2/IPU/Makefile.am | 8 + pcsx2/IPU/acoroutine.S | 187 + pcsx2/IPU/acoroutine.asm | 140 + pcsx2/IPU/coroutine.c | 172 + pcsx2/IPU/coroutine.h | 39 + pcsx2/IPU/idct_mmx.obj | Bin 0 -> 11510 bytes pcsx2/IPU/mpeg2lib/Idct.c | 301 + pcsx2/IPU/mpeg2lib/Makefile.am | 4 + pcsx2/IPU/mpeg2lib/Mpeg.c | 1280 + pcsx2/IPU/mpeg2lib/Mpeg.h | 200 + pcsx2/IPU/mpeg2lib/Vlc.h | 441 + pcsx2/IPU/yuv2rgb.asm | 242 + pcsx2/IPU/yuv2rgb.c | 510 + pcsx2/IPU/yuv2rgb.h | 57 + pcsx2/InterTables.c | 224 + pcsx2/InterTables.h | 491 + pcsx2/Interpreter.c | 1062 + pcsx2/Linux/.pixmaps/pcsxAbout.xpm | 334 + pcsx2/Linux/Config.c | 146 + pcsx2/Linux/GtkGui.c | 1604 ++ pcsx2/Linux/Linux.h | 47 + pcsx2/Linux/LnxMain.c | 616 + pcsx2/Linux/Makefile.am | 21 + pcsx2/Linux/buildgui.sh | 9 + pcsx2/Linux/callbacks.h | 386 + pcsx2/Linux/interface.c | 2742 ++ pcsx2/Linux/interface.h | 17 + pcsx2/Linux/pcsx2.glade | 5235 ++++ pcsx2/Linux/support.c | 144 + pcsx2/Linux/support.h | 69 + pcsx2/MMI.c | 1475 + pcsx2/Makefile.am | 29 + pcsx2/Mdec.c | 521 + pcsx2/Mdec.h | 31 + pcsx2/Memory.c | 3238 +++ pcsx2/Memory.h | 265 + pcsx2/Misc.c | 1108 + pcsx2/Misc.h | 342 + pcsx2/PS2Edefs.h | 834 + pcsx2/PS2Etypes.h | 76 + pcsx2/Patch.c | 415 + pcsx2/Patch.h | 78 + pcsx2/Plugins.c | 653 + pcsx2/Plugins.h | 32 + pcsx2/PsxBios.c | 300 + pcsx2/PsxBios.h | 35 + pcsx2/PsxBios2.h | 94 + pcsx2/PsxCommon.h | 46 + pcsx2/PsxCounters.c | 631 + pcsx2/PsxCounters.h | 55 + pcsx2/PsxDma.c | 255 + pcsx2/PsxDma.h | 42 + pcsx2/PsxHw.c | 1807 ++ pcsx2/PsxHw.h | 117 + pcsx2/PsxInterpreter.c | 797 + pcsx2/PsxMem.c | 778 + pcsx2/PsxMem.h | 113 + pcsx2/PsxSio2.c | 241 + pcsx2/PsxSio2.h | 98 + pcsx2/R3000A.c | 216 + pcsx2/R3000A.h | 213 + pcsx2/R5900.c | 598 + pcsx2/R5900.h | 281 + pcsx2/RDebug/Makefile.am | 7 + pcsx2/RDebug/deci2.c | 26 + pcsx2/RDebug/deci2.h | 70 + pcsx2/RDebug/deci2.txt | 27 + pcsx2/RDebug/deci2_dbgp.c | 414 + pcsx2/RDebug/deci2_dbgp.h | 28 + pcsx2/RDebug/deci2_dcmp.c | 83 + pcsx2/RDebug/deci2_dcmp.h | 28 + pcsx2/RDebug/deci2_drfp.c | 48 + pcsx2/RDebug/deci2_drfp.h | 27 + pcsx2/RDebug/deci2_iloadp.c | 106 + pcsx2/RDebug/deci2_iloadp.h | 27 + pcsx2/RDebug/deci2_netmp.c | 134 + pcsx2/RDebug/deci2_netmp.h | 27 + pcsx2/RDebug/deci2_ttyp.c | 41 + pcsx2/RDebug/deci2_ttyp.h | 28 + pcsx2/RDebug/iloadp.txt | 32 + pcsx2/SPR.c | 403 + pcsx2/SPR.h | 29 + pcsx2/Sif.c | 616 + pcsx2/Sif.h | 49 + pcsx2/Sifcmd.h | 193 + pcsx2/Sio.c | 590 + pcsx2/Sio.h | 115 + pcsx2/Stats.c | 71 + pcsx2/Stats.h | 43 + pcsx2/System.h | 64 + pcsx2/VU.h | 181 + pcsx2/VU0.c | 401 + pcsx2/VU0.h | 49 + pcsx2/VU0micro.c | 738 + pcsx2/VU1micro.c | 698 + pcsx2/VUflags.c | 95 + pcsx2/VUflags.h | 38 + pcsx2/VUmicro.h | 1266 + pcsx2/VUops.c | 2955 ++ pcsx2/VUops.h | 393 + pcsx2/Vif.c | 1055 + pcsx2/Vif.h | 108 + pcsx2/VifDma.c | 2456 ++ pcsx2/VifDma.h | 118 + pcsx2/build.sh | 36 + pcsx2/cheatscpp.h | 31 + pcsx2/configure.ac | 134 + pcsx2/depcomp | 529 + pcsx2/install-sh | 323 + pcsx2/missing | 360 + pcsx2/mkinstalldirs | 158 + pcsx2/pcsxAbout.bmp | Bin 0 -> 251192 bytes pcsx2/tinyxml/Makefile.am | 5 + pcsx2/tinyxml/tinystr.cpp | 116 + pcsx2/tinyxml/tinystr.h | 319 + pcsx2/tinyxml/tinyxml.cpp | 1866 ++ pcsx2/tinyxml/tinyxml.h | 1776 ++ pcsx2/tinyxml/tinyxmlerror.cpp | 53 + pcsx2/tinyxml/tinyxmlparser.cpp | 1606 ++ pcsx2/windows/AboutDlg.c | 59 + pcsx2/windows/AboutDlg.h | 24 + pcsx2/windows/Cdrom02.ico | Bin 0 -> 12862 bytes pcsx2/windows/ConfigDlg.c | 502 + pcsx2/windows/CpuDlg.c | 157 + pcsx2/windows/DebugMemory.c | 239 + pcsx2/windows/Debugger.c | 560 + pcsx2/windows/Debugger.h | 54 + pcsx2/windows/Debugreg.c | 1483 + pcsx2/windows/McdsDlg.c | 124 + pcsx2/windows/McdsDlg.h | 24 + pcsx2/windows/PatchBrowser.c | 352 + pcsx2/windows/RDebugger.c | 375 + pcsx2/windows/RDebugger.h | 26 + pcsx2/windows/VCprojects/pcsx2_2003.sln | 72 + pcsx2/windows/VCprojects/pcsx2_2003.vcproj | 1311 + pcsx2/windows/VCprojects/pcsx2_2005.sln | 76 + pcsx2/windows/VCprojects/pcsx2_2005.vcproj | 1562 ++ pcsx2/windows/VCprojects/pcsx2_2005_x64.sln | 82 + .../windows/VCprojects/pcsx2_2005_x64.vcproj | 2245 ++ pcsx2/windows/Win32.h | 49 + pcsx2/windows/WinMain.c | 1912 ++ pcsx2/windows/afxresmw.h | 5 + pcsx2/windows/cheats/browser.cpp | 121 + pcsx2/windows/cheats/cheats.cpp | 600 + pcsx2/windows/cheats/cheats.h | 19 + pcsx2/windows/ini.c | 173 + pcsx2/windows/libs/gnu_gettext.lib | Bin 0 -> 2916 bytes pcsx2/windows/libs/libintlmsc.h | 116 + pcsx2/windows/libs/pthread.h | 1368 + pcsx2/windows/libs/pthreadVC2.lib | Bin 0 -> 29280 bytes pcsx2/windows/libs/sched.h | 178 + pcsx2/windows/libs/semaphore.h | 166 + pcsx2/windows/mingw/Makefile.win | 348 + pcsx2/windows/mingw/afxres.h | 5 + pcsx2/windows/mingw/pcsx2.dev | 2116 ++ pcsx2/windows/mingw/pcsx2.layout | 1424 + pcsx2/windows/mingw/pcsx2_private.h | 23 + pcsx2/windows/mingw/pcsx2_private.rc | 5 + pcsx2/windows/pcsx2.rc | 1537 ++ pcsx2/windows/ps2_silver.bmp | Bin 0 -> 37974 bytes pcsx2/windows/pthreadVC2.lib | Bin 0 -> 29280 bytes pcsx2/windows/resource.h | 677 + pcsx2/x86/Makefile.am | 22 + pcsx2/x86/README | 12 + pcsx2/x86/aR3000A.S | 440 + pcsx2/x86/aVUzerorec.S | 158 + pcsx2/x86/aVif.S | 1590 ++ pcsx2/x86/aVif.asm | 1898 ++ pcsx2/x86/fast_routines.S | 351 + pcsx2/x86/fast_routines.cpp | 595 + pcsx2/x86/iCOP2.c | 861 + pcsx2/x86/iCP0.c | 347 + pcsx2/x86/iCP0.h | 41 + pcsx2/x86/iCore.cpp | 1436 + pcsx2/x86/iCore.h | 486 + pcsx2/x86/iFPU.c | 1427 + pcsx2/x86/iFPU.h | 60 + pcsx2/x86/iGS.cpp | 515 + pcsx2/x86/iHw.c | 1235 + pcsx2/x86/iMMI.c | 3393 +++ pcsx2/x86/iMMI.h | 133 + pcsx2/x86/iPsxHw.c | 1163 + pcsx2/x86/iPsxMem.c | 869 + pcsx2/x86/iR3000A.cpp | 1469 + pcsx2/x86/iR3000A.h | 99 + pcsx2/x86/iR3000Atables.cpp | 2051 ++ pcsx2/x86/iR5900.h | 254 + pcsx2/x86/iR5900Arit.h | 45 + pcsx2/x86/iR5900AritImm.h | 41 + pcsx2/x86/iR5900Branch.h | 47 + pcsx2/x86/iR5900Jump.h | 35 + pcsx2/x86/iR5900LoadStore.h | 90 + pcsx2/x86/iR5900Move.h | 33 + pcsx2/x86/iR5900MultDiv.h | 35 + pcsx2/x86/iR5900Shift.h | 47 + pcsx2/x86/iVU0micro.c | 777 + pcsx2/x86/iVU0micro.h | 229 + pcsx2/x86/iVU1micro.c | 212 + pcsx2/x86/iVU1micro.h | 31 + pcsx2/x86/iVUmicro.c | 4910 ++++ pcsx2/x86/iVUmicro.h | 274 + pcsx2/x86/iVUops.h | 44 + pcsx2/x86/iVUzerorec.cpp | 4182 +++ pcsx2/x86/iVUzerorec.h | 49 + pcsx2/x86/iVif.cpp | 158 + pcsx2/x86/ir5900tables.c | 1285 + pcsx2/x86/ix86-32/aR5900-32.S | 216 + pcsx2/x86/ix86-32/aVif_proc-32.asm | 1800 ++ pcsx2/x86/ix86-32/iCore-32.cpp | 1205 + pcsx2/x86/ix86-32/iR5900-32.c | 3295 +++ pcsx2/x86/ix86-32/iR5900Arit.c | 2001 ++ pcsx2/x86/ix86-32/iR5900AritImm.c | 663 + pcsx2/x86/ix86-32/iR5900Branch.c | 1093 + pcsx2/x86/ix86-32/iR5900Jump.c | 136 + pcsx2/x86/ix86-32/iR5900LoadStore.c | 4297 +++ pcsx2/x86/ix86-32/iR5900Move.c | 841 + pcsx2/x86/ix86-32/iR5900MultDiv.c | 957 + pcsx2/x86/ix86-32/iR5900Shift.c | 1353 + pcsx2/x86/ix86-64/aR3000A-64.asm | 209 + pcsx2/x86/ix86-64/aR5900-64.S | 255 + pcsx2/x86/ix86-64/aR5900-64.asm | 261 + pcsx2/x86/ix86-64/aVUzerorec-64.asm | 110 + pcsx2/x86/ix86-64/aVif_proc-64.asm | 1787 ++ pcsx2/x86/ix86-64/fast_routines-64.asm | 294 + pcsx2/x86/ix86-64/iCore-64.cpp | 703 + pcsx2/x86/ix86-64/iR5900-64.c | 2754 ++ pcsx2/x86/ix86-64/iR5900Arit-64.c | 212 + pcsx2/x86/ix86-64/iR5900AritImm-64.c | 168 + pcsx2/x86/ix86-64/iR5900Branch-64.c | 536 + pcsx2/x86/ix86-64/iR5900Jump-64.c | 113 + pcsx2/x86/ix86-64/iR5900LoadStore-64.c | 422 + pcsx2/x86/ix86-64/iR5900Move-64.c | 84 + pcsx2/x86/ix86-64/iR5900MultDiv-64.c | 163 + pcsx2/x86/ix86-64/iR5900Shift-64.c | 263 + pcsx2/x86/ix86/Makefile.am | 9 + pcsx2/x86/ix86/ix86.c | 3261 +++ pcsx2/x86/ix86/ix86.h | 1768 ++ pcsx2/x86/ix86/ix86_3dnow.c | 188 + pcsx2/x86/ix86/ix86_cpudetect.c | 480 + pcsx2/x86/ix86/ix86_fpu.c | 274 + pcsx2/x86/ix86/ix86_mmx.c | 636 + pcsx2/x86/ix86/ix86_sse.c | 1477 + pcsx2/xmlpatchloader.cpp | 376 + pcsx2/zlib/ChangeLog | 722 + pcsx2/zlib/Makefile.am | 6 + pcsx2/zlib/README | 126 + pcsx2/zlib/adler32.c | 74 + pcsx2/zlib/compress.c | 79 + pcsx2/zlib/crc32.c | 311 + pcsx2/zlib/crc32.h | 441 + pcsx2/zlib/deflate.c | 1502 ++ pcsx2/zlib/deflate.h | 326 + pcsx2/zlib/gzio.c | 1005 + pcsx2/zlib/infback.c | 619 + pcsx2/zlib/inffast.c | 305 + pcsx2/zlib/inffast.h | 11 + pcsx2/zlib/inffixed.h | 94 + pcsx2/zlib/inflate.c | 1270 + pcsx2/zlib/inflate.h | 117 + pcsx2/zlib/inftrees.c | 321 + pcsx2/zlib/inftrees.h | 55 + pcsx2/zlib/trees.c | 1215 + pcsx2/zlib/trees.h | 128 + pcsx2/zlib/uncompr.c | 61 + pcsx2/zlib/zconf.h | 323 + pcsx2/zlib/zlib.h | 1200 + pcsx2/zlib/zutil.c | 319 + pcsx2/zlib/zutil.h | 258 + plugins/build.sh | 59 + plugins/cdvd/CDVDbin/CDVDbin.dll | Bin 0 -> 69632 bytes plugins/cdvd/CDVDbin/CDVDbin.ro.dll | Bin 0 -> 53248 bytes plugins/cdvd/CDVDbin/CDVDbinA64.dll | Bin 0 -> 11264 bytes plugins/cdvd/CDVDbin/readme.ps1.txt | 52 + plugins/cdvd/CDVDbin/readme.txt | 94 + plugins/cdvd/CDVDbin/src/CDVD.h | 90 + plugins/cdvd/CDVDbin/src/CDVDbin.c | 679 + plugins/cdvd/CDVDbin/src/CDVDbin.def | 29 + plugins/cdvd/CDVDbin/src/CDVDbin.dsp | 139 + plugins/cdvd/CDVDbin/src/CDVDbin.dsw | 29 + plugins/cdvd/CDVDbin/src/CDVDbin.ncb | Bin 0 -> 52224 bytes plugins/cdvd/CDVDbin/src/CDVDbin.rc | 151 + plugins/cdvd/CDVDbin/src/CDVDbin.sln | 21 + plugins/cdvd/CDVDbin/src/CDVDbin.sln.old | 21 + plugins/cdvd/CDVDbin/src/CDVDbin.suo | Bin 0 -> 8704 bytes plugins/cdvd/CDVDbin/src/CDVDbin.vcproj | 178 + plugins/cdvd/CDVDbin/src/CDVDbin.vcproj.old | 164 + plugins/cdvd/CDVDbin/src/CDVDbin_2003.sln | 21 + plugins/cdvd/CDVDbin/src/CDVDbin_2003.vcproj | 178 + .../CDVDbin/src/CDVDbin_vsnet2005beta1.sln | 26 + .../CDVDbin/src/CDVDbin_vsnet2005beta1.vcproj | 428 + plugins/cdvd/CDVDbin/src/CDVDbinro.rc | 141 + plugins/cdvd/CDVDbin/src/PS2Edefs.h | 723 + plugins/cdvd/CDVDbin/src/PS2Etypes.h | 43 + plugins/cdvd/CDVDbin/src/resource.h | 19 + plugins/cdvd/CDVDdraft/Src/AboutBox.cpp | 43 + plugins/cdvd/CDVDdraft/Src/AboutBox.h | 46 + plugins/cdvd/CDVDdraft/Src/Config.cpp | 172 + plugins/cdvd/CDVDdraft/Src/Config.h | 54 + plugins/cdvd/CDVDdraft/Src/PS2Edefs.h | 723 + plugins/cdvd/CDVDdraft/Src/PS2Etypes.h | 43 + plugins/cdvd/CDVDdraft/Src/ReadMe.txt | 66 + plugins/cdvd/CDVDdraft/Src/StdAfx.cpp | 8 + plugins/cdvd/CDVDdraft/Src/StdAfx.h | 41 + plugins/cdvd/CDVDdraft/Src/aspi.cpp | 842 + plugins/cdvd/CDVDdraft/Src/bitmap1.bmp | Bin 0 -> 3726 bytes plugins/cdvd/CDVDdraft/Src/cdvd.cpp | 616 + plugins/cdvd/CDVDdraft/Src/cdvd.h | 252 + plugins/cdvd/CDVDdraft/Src/cdvdcompat.cpp | 194 + plugins/cdvd/CDVDdraft/Src/cdvdcompat.h | 20 + plugins/cdvd/CDVDdraft/Src/cdvddraft.aps | Bin 0 -> 38612 bytes plugins/cdvd/CDVDdraft/Src/cdvddraft.clw | 48 + plugins/cdvd/CDVDdraft/Src/cdvddraft.cpp | 599 + plugins/cdvd/CDVDdraft/Src/cdvddraft.def | 49 + plugins/cdvd/CDVDdraft/Src/cdvddraft.dep | 138 + plugins/cdvd/CDVDdraft/Src/cdvddraft.dsp | 219 + plugins/cdvd/CDVDdraft/Src/cdvddraft.dsw | 29 + plugins/cdvd/CDVDdraft/Src/cdvddraft.h | 56 + plugins/cdvd/CDVDdraft/Src/cdvddraft.opt | Bin 0 -> 65024 bytes plugins/cdvd/CDVDdraft/Src/cdvddraft.plg | 68 + plugins/cdvd/CDVDdraft/Src/cdvddraft.rc | 227 + plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.sln | 21 + .../cdvd/CDVDdraft/Src/cdvddraft_2003.vcproj | 399 + plugins/cdvd/CDVDdraft/Src/cdvdmisc.cpp | 93 + plugins/cdvd/CDVDdraft/Src/cdvdmisc.h | 17 + plugins/cdvd/CDVDdraft/Src/constants.h | 109 + plugins/cdvd/CDVDdraft/Src/ioctl.cpp | 208 + plugins/cdvd/CDVDdraft/Src/res/CVS/Entries | 2 + .../cdvd/CDVDdraft/Src/res/CVS/Entries.Extra | 1 + plugins/cdvd/CDVDdraft/Src/res/CVS/Repository | 1 + plugins/cdvd/CDVDdraft/Src/res/CVS/Root | 1 + plugins/cdvd/CDVDdraft/Src/res/cdvddraft.rc2 | 13 + plugins/cdvd/CDVDdraft/Src/resource.h | 25 + plugins/cdvd/CDVDdraft/Src/typedefs.h | 125 + plugins/cdvd/CDVDdraft/Src/winaspi/scsidefs.h | 279 + plugins/cdvd/CDVDdraft/Src/winaspi/wnaspi32.h | 325 + plugins/cdvd/CDVDdraft/cdvddraft.dll | Bin 0 -> 49152 bytes plugins/cdvd/CDVDiso/ReadMe.txt | 78 + plugins/cdvd/CDVDiso/build.sh | 16 + plugins/cdvd/CDVDiso/src/CDVDiso.c | 341 + plugins/cdvd/CDVDiso/src/CDVDiso.h | 80 + plugins/cdvd/CDVDiso/src/Linux/CDVDiso.glade | 368 + plugins/cdvd/CDVDiso/src/Linux/Config.c | 59 + plugins/cdvd/CDVDiso/src/Linux/Config.h | 20 + plugins/cdvd/CDVDiso/src/Linux/Linux.c | 76 + plugins/cdvd/CDVDiso/src/Linux/Makefile | 34 + plugins/cdvd/CDVDiso/src/Linux/callbacks.c | 98 + plugins/cdvd/CDVDiso/src/Linux/callbacks.h | 46 + plugins/cdvd/CDVDiso/src/Linux/conf.c | 865 + plugins/cdvd/CDVDiso/src/Linux/interface.c | 253 + plugins/cdvd/CDVDiso/src/Linux/interface.h | 5 + plugins/cdvd/CDVDiso/src/Linux/support.c | 162 + plugins/cdvd/CDVDiso/src/Linux/support.h | 38 + plugins/cdvd/CDVDiso/src/PS2Edefs.h | 812 + plugins/cdvd/CDVDiso/src/PS2Etypes.h | 43 + .../CDVDiso/src/Win32/CDVDiso 2005 x64.sln | 17 + .../CDVDiso/src/Win32/CDVDiso 2005 x64.vcproj | 561 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.def | 29 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsp | 111 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsw | 30 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.rc | 134 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.sln | 18 + plugins/cdvd/CDVDiso/src/Win32/CDVDiso.vcproj | 258 + .../cdvd/CDVDiso/src/Win32/CDVDiso_2003.sln | 18 + .../CDVDiso/src/Win32/CDVDiso_2003.vcproj | 300 + .../cdvd/CDVDiso/src/Win32/CDVDiso_2005.sln | 20 + .../CDVDiso/src/Win32/CDVDiso_2005.vcproj | 538 + plugins/cdvd/CDVDiso/src/Win32/Config.c | 45 + plugins/cdvd/CDVDiso/src/Win32/Config.h | 3 + plugins/cdvd/CDVDiso/src/Win32/Makefile | 57 + plugins/cdvd/CDVDiso/src/Win32/Win32.c | 311 + plugins/cdvd/CDVDiso/src/Win32/afxresmw.h | 5 + plugins/cdvd/CDVDiso/src/Win32/plugin.def | 21 + plugins/cdvd/CDVDiso/src/Win32/resource.h | 28 + plugins/cdvd/CDVDiso/src/bzip2/LICENSE | 43 + plugins/cdvd/CDVDiso/src/bzip2/README | 205 + plugins/cdvd/CDVDiso/src/bzip2/blocksort.c | 1094 + plugins/cdvd/CDVDiso/src/bzip2/bzlib.c | 1571 ++ plugins/cdvd/CDVDiso/src/bzip2/bzlib.h | 282 + .../cdvd/CDVDiso/src/bzip2/bzlib_private.h | 503 + plugins/cdvd/CDVDiso/src/bzip2/compress.c | 672 + plugins/cdvd/CDVDiso/src/bzip2/crctable.c | 104 + plugins/cdvd/CDVDiso/src/bzip2/decompress.c | 626 + plugins/cdvd/CDVDiso/src/bzip2/huffman.c | 205 + plugins/cdvd/CDVDiso/src/bzip2/randtable.c | 84 + plugins/cdvd/CDVDiso/src/libiso.c | 908 + plugins/cdvd/CDVDiso/src/libiso.h | 65 + plugins/cdvd/CDVDiso/src/mkiso/Makefile | 26 + plugins/cdvd/CDVDiso/src/mkiso/Makefile.mingw | 31 + plugins/cdvd/CDVDiso/src/mkiso/mkiso.c | 153 + plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsp | 206 + plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsw | 29 + plugins/cdvd/CDVDiso/src/zlib/ChangeLog | 855 + plugins/cdvd/CDVDiso/src/zlib/README | 125 + plugins/cdvd/CDVDiso/src/zlib/adler32.c | 149 + plugins/cdvd/CDVDiso/src/zlib/compress.c | 79 + plugins/cdvd/CDVDiso/src/zlib/crc32.c | 423 + plugins/cdvd/CDVDiso/src/zlib/crc32.h | 441 + plugins/cdvd/CDVDiso/src/zlib/deflate.c | 1736 ++ plugins/cdvd/CDVDiso/src/zlib/deflate.h | 331 + plugins/cdvd/CDVDiso/src/zlib/gvmat32.obj | Bin 0 -> 10137 bytes plugins/cdvd/CDVDiso/src/zlib/gvmat32c.c | 62 + plugins/cdvd/CDVDiso/src/zlib/gvmat64.obj | Bin 0 -> 4215 bytes plugins/cdvd/CDVDiso/src/zlib/gzio.c | 1026 + plugins/cdvd/CDVDiso/src/zlib/infback.c | 623 + plugins/cdvd/CDVDiso/src/zlib/inffas32.obj | Bin 0 -> 14899 bytes plugins/cdvd/CDVDiso/src/zlib/inffas8664.c | 186 + plugins/cdvd/CDVDiso/src/zlib/inffast.c | 318 + plugins/cdvd/CDVDiso/src/zlib/inffast.h | 11 + plugins/cdvd/CDVDiso/src/zlib/inffasx64.obj | Bin 0 -> 5881 bytes plugins/cdvd/CDVDiso/src/zlib/inffixed.h | 94 + plugins/cdvd/CDVDiso/src/zlib/inflate.c | 1368 + plugins/cdvd/CDVDiso/src/zlib/inflate.h | 115 + plugins/cdvd/CDVDiso/src/zlib/inftrees.c | 329 + plugins/cdvd/CDVDiso/src/zlib/inftrees.h | 55 + plugins/cdvd/CDVDiso/src/zlib/trees.c | 1219 + plugins/cdvd/CDVDiso/src/zlib/trees.h | 128 + plugins/cdvd/CDVDiso/src/zlib/uncompr.c | 61 + plugins/cdvd/CDVDiso/src/zlib/zconf.h | 332 + plugins/cdvd/CDVDiso/src/zlib/zlib.h | 1357 + plugins/cdvd/CDVDiso/src/zlib/zutil.c | 318 + plugins/cdvd/CDVDiso/src/zlib/zutil.h | 269 + plugins/cdvd/CDVDisoEFP/ChangeLog.txt | 58 + plugins/cdvd/CDVDisoEFP/build.sh | 16 + plugins/cdvd/CDVDisoEFP/license.txt | 342 + plugins/cdvd/CDVDisoEFP/readme.txt | 55 + plugins/cdvd/CDVDisoEFP/src/Linux/CD.c | 367 + plugins/cdvd/CDVDisoEFP/src/Linux/CD.h | 46 + plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.c | 450 + plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.h | 29 + plugins/cdvd/CDVDisoEFP/src/Linux/DVD.c | 582 + plugins/cdvd/CDVDisoEFP/src/Linux/DVD.h | 45 + plugins/cdvd/CDVDisoEFP/src/Linux/Makefile | 91 + plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.c | 106 + .../cdvd/CDVDisoEFP/src/Linux/aboutbox.glade | 118 + plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.h | 39 + .../cdvd/CDVDisoEFP/src/Linux/actualfile.c | 222 + .../cdvd/CDVDisoEFP/src/Linux/actualfile.h | 50 + .../cdvd/CDVDisoEFP/src/Linux/comparisonbox.c | 415 + .../CDVDisoEFP/src/Linux/comparisonbox.glade | 227 + .../CDVDisoEFP/src/Linux/comparisondummy.c | 24 + plugins/cdvd/CDVDisoEFP/src/Linux/conf.c | 204 + plugins/cdvd/CDVDisoEFP/src/Linux/conf.h | 54 + .../cdvd/CDVDisoEFP/src/Linux/conversionbox.c | 388 + .../CDVDisoEFP/src/Linux/conversionbox.glade | 272 + .../cdvd/CDVDisoEFP/src/Linux/conversionbox.h | 47 + plugins/cdvd/CDVDisoEFP/src/Linux/device.c | 418 + plugins/cdvd/CDVDisoEFP/src/Linux/device.h | 69 + plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.c | 443 + .../cdvd/CDVDisoEFP/src/Linux/devicebox.glade | 345 + plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.h | 50 + plugins/cdvd/CDVDisoEFP/src/Linux/interface.c | 67 + plugins/cdvd/CDVDisoEFP/src/Linux/interface.h | 29 + plugins/cdvd/CDVDisoEFP/src/Linux/logfile.c | 90 + plugins/cdvd/CDVDisoEFP/src/Linux/logfile.h | 35 + plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.c | 324 + .../cdvd/CDVDisoEFP/src/Linux/mainbox.glade | 219 + plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.h | 50 + .../cdvd/CDVDisoEFP/src/Linux/messagebox.c | 113 + .../CDVDisoEFP/src/Linux/messagebox.glade | 76 + .../cdvd/CDVDisoEFP/src/Linux/messagebox.h | 43 + .../cdvd/CDVDisoEFP/src/Linux/progressbox.c | 144 + .../CDVDisoEFP/src/Linux/progressbox.glade | 95 + .../cdvd/CDVDisoEFP/src/Linux/progressbox.h | 55 + .../cdvd/CDVDisoEFP/src/Linux/selectionbox.c | 102 + .../CDVDisoEFP/src/Linux/selectionbox.glade | 44 + .../cdvd/CDVDisoEFP/src/Linux/selectionbox.h | 46 + .../cdvd/CDVDisoEFP/src/Linux/tablerebuild.c | 190 + .../cdvd/CDVDisoEFP/src/Linux/tablerebuild.h | 32 + plugins/cdvd/CDVDisoEFP/src/PS2Edefs.h | 812 + plugins/cdvd/CDVDisoEFP/src/PS2Etypes.h | 75 + plugins/cdvd/CDVDisoEFP/src/Win32/CD.c | 774 + plugins/cdvd/CDVDisoEFP/src/Win32/CD.h | 44 + plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.c | 570 + plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.h | 36 + plugins/cdvd/CDVDisoEFP/src/Win32/DVD.c | 796 + plugins/cdvd/CDVDisoEFP/src/Win32/DVD.h | 37 + .../CDVDisoEFP/src/Win32/Makefile.MinGW32 | 59 + .../CDVDisoEFP/src/Win32/Makefile.MinGW32.bak | 57 + .../cdvd/CDVDisoEFP/src/Win32/actualfile.c | 506 + .../cdvd/CDVDisoEFP/src/Win32/actualfile.h | 104 + plugins/cdvd/CDVDisoEFP/src/Win32/conf.c | 195 + plugins/cdvd/CDVDisoEFP/src/Win32/conf.h | 54 + .../cdvd/CDVDisoEFP/src/Win32/conversionbox.c | 750 + .../cdvd/CDVDisoEFP/src/Win32/conversionbox.h | 40 + plugins/cdvd/CDVDisoEFP/src/Win32/device.c | 586 + plugins/cdvd/CDVDisoEFP/src/Win32/device.h | 64 + plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.c | 818 + plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.h | 41 + plugins/cdvd/CDVDisoEFP/src/Win32/logfile.c | 119 + plugins/cdvd/CDVDisoEFP/src/Win32/logfile.h | 39 + plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.c | 309 + plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.h | 43 + plugins/cdvd/CDVDisoEFP/src/Win32/make.bat | 1 + .../cdvd/CDVDisoEFP/src/Win32/makeming.bat | 1 + plugins/cdvd/CDVDisoEFP/src/Win32/plugin.def | 21 + .../cdvd/CDVDisoEFP/src/Win32/progressbox.c | 340 + .../cdvd/CDVDisoEFP/src/Win32/progressbox.h | 89 + plugins/cdvd/CDVDisoEFP/src/Win32/screens.h | 37 + plugins/cdvd/CDVDisoEFP/src/Win32/screens.rc | 82 + .../cdvd/CDVDisoEFP/src/Win32/tablerebuild.c | 187 + .../cdvd/CDVDisoEFP/src/Win32/tablerebuild.h | 32 + plugins/cdvd/CDVDisoEFP/src/blockv2.c | 612 + plugins/cdvd/CDVDisoEFP/src/blockv2.h | 104 + plugins/cdvd/CDVDisoEFP/src/bzip2/LICENSE | 40 + plugins/cdvd/CDVDisoEFP/src/bzip2/README | 185 + plugins/cdvd/CDVDisoEFP/src/bzip2/blocksort.c | 1141 + plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.c | 1616 ++ plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.h | 323 + .../cdvd/CDVDisoEFP/src/bzip2/bzlib_private.h | 537 + plugins/cdvd/CDVDisoEFP/src/bzip2/compress.c | 716 + plugins/cdvd/CDVDisoEFP/src/bzip2/crctable.c | 144 + .../cdvd/CDVDisoEFP/src/bzip2/decompress.c | 666 + plugins/cdvd/CDVDisoEFP/src/bzip2/huffman.c | 245 + plugins/cdvd/CDVDisoEFP/src/bzip2/randtable.c | 124 + plugins/cdvd/CDVDisoEFP/src/bzip2v2.c | 1052 + plugins/cdvd/CDVDisoEFP/src/bzip2v2.h | 104 + plugins/cdvd/CDVDisoEFP/src/bzip2v3.c | 968 + plugins/cdvd/CDVDisoEFP/src/bzip2v3.h | 104 + plugins/cdvd/CDVDisoEFP/src/convert.c | 118 + plugins/cdvd/CDVDisoEFP/src/convert.h | 50 + plugins/cdvd/CDVDisoEFP/src/ecma119.c | 59 + plugins/cdvd/CDVDisoEFP/src/ecma119.h | 468 + plugins/cdvd/CDVDisoEFP/src/gzipv1.c | 844 + plugins/cdvd/CDVDisoEFP/src/gzipv1.h | 104 + plugins/cdvd/CDVDisoEFP/src/gzipv2.c | 980 + plugins/cdvd/CDVDisoEFP/src/gzipv2.h | 104 + plugins/cdvd/CDVDisoEFP/src/imagetype.c | 306 + plugins/cdvd/CDVDisoEFP/src/imagetype.h | 112 + plugins/cdvd/CDVDisoEFP/src/ini.c | 689 + plugins/cdvd/CDVDisoEFP/src/ini.h | 64 + plugins/cdvd/CDVDisoEFP/src/isocompress.c | 914 + plugins/cdvd/CDVDisoEFP/src/isocompress.h | 158 + plugins/cdvd/CDVDisoEFP/src/isofile.c | 1292 + plugins/cdvd/CDVDisoEFP/src/isofile.h | 246 + plugins/cdvd/CDVDisoEFP/src/multifile.c | 578 + plugins/cdvd/CDVDisoEFP/src/multifile.h | 106 + plugins/cdvd/CDVDisoEFP/src/toc.c | 358 + plugins/cdvd/CDVDisoEFP/src/toc.h | 84 + plugins/cdvd/CDVDisoEFP/src/version.c | 36 + plugins/cdvd/CDVDisoEFP/src/version.h | 43 + plugins/cdvd/CDVDisoEFP/src/zlib/ChangeLog | 722 + plugins/cdvd/CDVDisoEFP/src/zlib/README | 126 + plugins/cdvd/CDVDisoEFP/src/zlib/adler32.c | 74 + plugins/cdvd/CDVDisoEFP/src/zlib/compress.c | 79 + plugins/cdvd/CDVDisoEFP/src/zlib/crc32.c | 311 + plugins/cdvd/CDVDisoEFP/src/zlib/crc32.h | 441 + plugins/cdvd/CDVDisoEFP/src/zlib/deflate.c | 1502 ++ plugins/cdvd/CDVDisoEFP/src/zlib/deflate.h | 326 + plugins/cdvd/CDVDisoEFP/src/zlib/gzio.c | 1005 + plugins/cdvd/CDVDisoEFP/src/zlib/infback.c | 619 + plugins/cdvd/CDVDisoEFP/src/zlib/inffast.c | 305 + plugins/cdvd/CDVDisoEFP/src/zlib/inffast.h | 11 + plugins/cdvd/CDVDisoEFP/src/zlib/inffixed.h | 94 + plugins/cdvd/CDVDisoEFP/src/zlib/inflate.c | 1270 + plugins/cdvd/CDVDisoEFP/src/zlib/inflate.h | 117 + plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.c | 321 + plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.h | 55 + plugins/cdvd/CDVDisoEFP/src/zlib/trees.c | 1215 + plugins/cdvd/CDVDisoEFP/src/zlib/trees.h | 128 + plugins/cdvd/CDVDisoEFP/src/zlib/uncompr.c | 61 + plugins/cdvd/CDVDisoEFP/src/zlib/zconf.h | 323 + plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h | 1200 + plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h.bak | 1200 + plugins/cdvd/CDVDisoEFP/src/zlib/zutil.c | 319 + plugins/cdvd/CDVDisoEFP/src/zlib/zutil.h | 258 + plugins/cdvd/CDVDlinuz/ChangeLog.txt | 43 + plugins/cdvd/CDVDlinuz/License.txt | 342 + plugins/cdvd/CDVDlinuz/Src/Linux/CD.c | 367 + plugins/cdvd/CDVDlinuz/Src/Linux/CD.h | 46 + plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.c | 368 + plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.h | 31 + plugins/cdvd/CDVDlinuz/Src/Linux/DVD.c | 584 + plugins/cdvd/CDVDlinuz/Src/Linux/DVD.h | 45 + plugins/cdvd/CDVDlinuz/Src/Linux/Makefile | 71 + plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.c | 106 + plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.h | 39 + plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.c | 222 + plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.h | 50 + plugins/cdvd/CDVDlinuz/Src/Linux/conf.c | 184 + plugins/cdvd/CDVDlinuz/Src/Linux/conf.h | 57 + plugins/cdvd/CDVDlinuz/Src/Linux/device.c | 420 + plugins/cdvd/CDVDlinuz/Src/Linux/device.h | 69 + plugins/cdvd/CDVDlinuz/Src/Linux/interface.c | 57 + plugins/cdvd/CDVDlinuz/Src/Linux/logfile.c | 90 + plugins/cdvd/CDVDlinuz/Src/Linux/logfile.h | 35 + plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.c | 187 + plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.h | 41 + plugins/cdvd/CDVDlinuz/Src/PS2Edefs.h | 812 + plugins/cdvd/CDVDlinuz/Src/PS2Etypes.h | 43 + plugins/cdvd/CDVDlinuz/Src/Win32/CD.c | 387 + plugins/cdvd/CDVDlinuz/Src/Win32/CD.h | 44 + plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.c | 434 + plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.h | 40 + plugins/cdvd/CDVDlinuz/Src/Win32/DVD.c | 398 + plugins/cdvd/CDVDlinuz/Src/Win32/DVD.h | 37 + .../cdvd/CDVDlinuz/Src/Win32/Makefile.MinGW32 | 43 + plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.c | 253 + plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.h | 52 + plugins/cdvd/CDVDlinuz/Src/Win32/conf.c | 175 + plugins/cdvd/CDVDlinuz/Src/Win32/conf.h | 49 + plugins/cdvd/CDVDlinuz/Src/Win32/device.c | 583 + plugins/cdvd/CDVDlinuz/Src/Win32/device.h | 64 + plugins/cdvd/CDVDlinuz/Src/Win32/logfile.c | 119 + plugins/cdvd/CDVDlinuz/Src/Win32/logfile.h | 39 + plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.c | 173 + plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.h | 42 + plugins/cdvd/CDVDlinuz/Src/Win32/make.bat | 1 + plugins/cdvd/CDVDlinuz/Src/Win32/plugin.def | 21 + plugins/cdvd/CDVDlinuz/Src/Win32/screens.h | 9 + plugins/cdvd/CDVDlinuz/Src/Win32/screens.rc | 29 + plugins/cdvd/CDVDlinuz/Src/buffer.c | 525 + plugins/cdvd/CDVDlinuz/Src/buffer.h | 67 + plugins/cdvd/CDVDlinuz/Src/convert.c | 118 + plugins/cdvd/CDVDlinuz/Src/convert.h | 50 + plugins/cdvd/CDVDlinuz/Src/ini.c | 689 + plugins/cdvd/CDVDlinuz/Src/ini.h | 64 + plugins/cdvd/CDVDlinuz/Src/version.c | 36 + plugins/cdvd/CDVDlinuz/Src/version.h | 43 + plugins/cdvd/CDVDlinuz/build.sh | 16 + plugins/cdvd/CDVDlinuz/readme.txt | 37 + plugins/cdvd/CDVDnull/CDVDnull.dll | Bin 0 -> 49152 bytes plugins/cdvd/CDVDnull/ReadMe.txt | 39 + plugins/cdvd/CDVDnull/Src/CDVD.c | 146 + plugins/cdvd/CDVDnull/Src/CDVD.h | 11 + plugins/cdvd/CDVDnull/Src/CDVDnull.def | 29 + plugins/cdvd/CDVDnull/Src/CDVDnull.dsp | 90 + plugins/cdvd/CDVDnull/Src/CDVDnull.dsw | 29 + plugins/cdvd/CDVDnull/Src/CDVDnull.opt | Bin 0 -> 53760 bytes plugins/cdvd/CDVDnull/Src/CDVDnull.plg | 34 + plugins/cdvd/CDVDnull/Src/CDVDnull.sln | 18 + plugins/cdvd/CDVDnull/Src/CDVDnull.vcproj | 101 + plugins/cdvd/CDVDnull/Src/CDVDnull_2003.sln | 18 + .../cdvd/CDVDnull/Src/CDVDnull_2003.vcproj | 109 + .../cdvd/CDVDnull/Src/CDVDnull_2005_x64.sln | 17 + .../CDVDnull/Src/CDVDnull_2005_x64.vcproj | 607 + .../CDVDnull/Src/CDVDnull_vsnet2005beta1.sln | 17 + .../Src/CDVDnull_vsnet2005beta1.vcproj | 418 + plugins/cdvd/CDVDnull/Src/Makefile | 50 + plugins/cdvd/CDVDnull/Src/PS2Edefs.h | 827 + plugins/cdvd/CDVDnull/Src/PS2Etypes.h | 76 + plugins/cdvd/CDVDnull/Src/plugin.def | 21 + plugins/cdvd/CDVDnull/build.sh | 12 + plugins/cdvd/CDVDpeops/CDVDiso.c | 822 + plugins/cdvd/CDVDpeops/CDVDiso.h | 131 + plugins/cdvd/CDVDpeops/CDVDisodrv.c | 264 + plugins/cdvd/CDVDpeops/CDVDisodrv.h | 22 + plugins/cdvd/CDVDpeops/CDVDlib.h | 189 + plugins/cdvd/CDVDpeops/CLEAN.BAT | 3 + plugins/cdvd/CDVDpeops/Cdr.c | 856 + plugins/cdvd/CDVDpeops/Cdr.c.bak | 848 + plugins/cdvd/CDVDpeops/Cfg.c | 527 + plugins/cdvd/CDVDpeops/CheckDiskType.c | 41 + plugins/cdvd/CDVDpeops/Ioctrl.c | 383 + plugins/cdvd/CDVDpeops/Makefile.win | 72 + plugins/cdvd/CDVDpeops/PS2Edefs.h | 789 + plugins/cdvd/CDVDpeops/PS2Etypes.h | 43 + plugins/cdvd/CDVDpeops/ReadMe.txt | 37 + plugins/cdvd/CDVDpeops/Scsi.c | 1134 + plugins/cdvd/CDVDpeops/StdAfx.c | 8 + plugins/cdvd/CDVDpeops/StdAfx.h | 82 + plugins/cdvd/CDVDpeops/build.sh | 16 + plugins/cdvd/CDVDpeops/cdda.c | 80 + plugins/cdvd/CDVDpeops/cdda.h | 28 + plugins/cdvd/CDVDpeops/cdr.h | 27 + plugins/cdvd/CDVDpeops/cdvdPeops.aps | Bin 0 -> 38376 bytes plugins/cdvd/CDVDpeops/cdvdPeops.c | 89 + plugins/cdvd/CDVDpeops/cdvdPeops.def | 30 + plugins/cdvd/CDVDpeops/cdvdPeops.def.bak | 30 + plugins/cdvd/CDVDpeops/cdvdPeops.dev | 418 + plugins/cdvd/CDVDpeops/cdvdPeops.dsp | 251 + plugins/cdvd/CDVDpeops/cdvdPeops.dsw | 29 + plugins/cdvd/CDVDpeops/cdvdPeops.h | 25 + plugins/cdvd/CDVDpeops/cdvdPeops.layout | 238 + plugins/cdvd/CDVDpeops/cdvdPeops.opt | Bin 0 -> 50688 bytes plugins/cdvd/CDVDpeops/cdvdPeops.plg | 96 + plugins/cdvd/CDVDpeops/cdvdPeops.rc | 235 + plugins/cdvd/CDVDpeops/cdvdPeops.sln | 21 + plugins/cdvd/CDVDpeops/cdvdPeops.suo | Bin 0 -> 13312 bytes plugins/cdvd/CDVDpeops/cdvdPeops.vcproj | 489 + plugins/cdvd/CDVDpeops/cdvdPeops_2005.sln | 19 + plugins/cdvd/CDVDpeops/cdvdPeops_2005.vcproj | 647 + plugins/cdvd/CDVDpeops/cdvdPeops_private.h | 23 + plugins/cdvd/CDVDpeops/cdvdPeops_private.rc | 4 + plugins/cdvd/CDVDpeops/cdvdPeops_private.res | Bin 0 -> 4584 bytes plugins/cdvd/CDVDpeops/cfg.h | 47 + plugins/cdvd/CDVDpeops/changelog.txt | 19 + plugins/cdvd/CDVDpeops/defines.h | 212 + plugins/cdvd/CDVDpeops/defines.h.bak | 213 + plugins/cdvd/CDVDpeops/externals.h | 177 + plugins/cdvd/CDVDpeops/externals.h.bak | 175 + plugins/cdvd/CDVDpeops/filemap.txt | 52 + plugins/cdvd/CDVDpeops/generic.c | 378 + plugins/cdvd/CDVDpeops/generic.c.bak | 377 + plugins/cdvd/CDVDpeops/generic.h | 41 + plugins/cdvd/CDVDpeops/i386.asm | 32 + plugins/cdvd/CDVDpeops/ioctrl.h | 35 + plugins/cdvd/CDVDpeops/libiso.c | 733 + plugins/cdvd/CDVDpeops/libiso.h | 59 + plugins/cdvd/CDVDpeops/license.txt | 282 + plugins/cdvd/CDVDpeops/macros.inc | 40 + plugins/cdvd/CDVDpeops/mingw/afxres.h | 2 + plugins/cdvd/CDVDpeops/ppf.c | 353 + plugins/cdvd/CDVDpeops/ppf.h | 32 + plugins/cdvd/CDVDpeops/read.c | 910 + plugins/cdvd/CDVDpeops/read.h | 41 + plugins/cdvd/CDVDpeops/readme_1_2.txt | 198 + plugins/cdvd/CDVDpeops/resource.h | 56 + plugins/cdvd/CDVDpeops/scsi.h | 55 + plugins/cdvd/CDVDpeops/scsidefs.h | 579 + plugins/cdvd/CDVDpeops/sub.c | 321 + plugins/cdvd/CDVDpeops/sub.h | 30 + plugins/cdvd/CDVDpeops/toc.c | 105 + plugins/cdvd/CDVDpeops/toc.h | 28 + plugins/cdvd/CDVDpeops/version_1_2.txt | 61 + plugins/cdvd/CDVDpeops/wnaspi32.h | 354 + plugins/cdvd/build.sh | 39 + plugins/dev9/DEV9linuz/DEV9.c | 1267 + plugins/dev9/DEV9linuz/DEV9.h | 1144 + plugins/dev9/DEV9linuz/Linux/Config.c | 45 + plugins/dev9/DEV9linuz/Linux/Config.h | 2 + plugins/dev9/DEV9linuz/Linux/Linux.c | 76 + plugins/dev9/DEV9linuz/Linux/Makefile | 37 + plugins/dev9/DEV9linuz/Linux/callbacks.c | 34 + plugins/dev9/DEV9linuz/Linux/callbacks.h | 14 + plugins/dev9/DEV9linuz/Linux/conf.c | 165 + plugins/dev9/DEV9linuz/Linux/dev9linuz.glade | 300 + plugins/dev9/DEV9linuz/Linux/dev9net.c | 194 + plugins/dev9/DEV9linuz/Linux/interface.c | 219 + plugins/dev9/DEV9linuz/Linux/interface.h | 6 + plugins/dev9/DEV9linuz/Linux/socks.c | 73 + plugins/dev9/DEV9linuz/Linux/socks.h | 22 + plugins/dev9/DEV9linuz/Linux/support.c | 162 + plugins/dev9/DEV9linuz/Linux/support.h | 38 + plugins/dev9/DEV9linuz/PS2Edefs.h | 684 + plugins/dev9/DEV9linuz/PS2Etypes.h | 31 + plugins/dev9/DEV9linuz/Win32/Config.c | 52 + plugins/dev9/DEV9linuz/Win32/Config.h | 2 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.def | 29 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsp | 107 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsw | 29 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.ncb | Bin 0 -> 150528 bytes plugins/dev9/DEV9linuz/Win32/DEV9linuz.opt | Bin 0 -> 48640 bytes plugins/dev9/DEV9linuz/Win32/DEV9linuz.plg | 53 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.rc | 135 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln | 18 + .../dev9/DEV9linuz/Win32/DEV9linuz.sln.old | 18 + plugins/dev9/DEV9linuz/Win32/DEV9linuz.suo | Bin 0 -> 13312 bytes plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj | 165 + .../DEV9linuz/Win32/DEV9linuz.vcproj.7.10.old | 133 + .../Win32/DEV9linuz.vcproj.FLORIN.Florin.user | 37 + plugins/dev9/DEV9linuz/Win32/Devioctl.h | 90 + plugins/dev9/DEV9linuz/Win32/Makefile | 52 + plugins/dev9/DEV9linuz/Win32/Ntddndis.h | 1400 + plugins/dev9/DEV9linuz/Win32/Packet.lib | Bin 0 -> 8180 bytes plugins/dev9/DEV9linuz/Win32/Packet32.h | 450 + plugins/dev9/DEV9linuz/Win32/Win32.c | 132 + plugins/dev9/DEV9linuz/Win32/afxresmw.h | 5 + plugins/dev9/DEV9linuz/Win32/libpacket.a | Bin 0 -> 23732 bytes plugins/dev9/DEV9linuz/Win32/plugin.def | 24 + plugins/dev9/DEV9linuz/Win32/resource.h | 25 + plugins/dev9/DEV9linuz/Win32/socks.c | 191 + plugins/dev9/DEV9linuz/Win32/socks.h | 12 + plugins/dev9/DEV9linuz/flash.c | 283 + plugins/dev9/build.sh | 14 + plugins/dev9/dev9null/DEV9null.dll | Bin 0 -> 40960 bytes plugins/dev9/dev9null/ReadMe.txt | 32 + plugins/dev9/dev9null/build.sh | 9 + plugins/dev9/dev9null/src/DEV9.h | 17 + plugins/dev9/dev9null/src/DEV9null.dsp | 89 + plugins/dev9/dev9null/src/DEV9null.dsw | 29 + plugins/dev9/dev9null/src/Dev9null.ncb | Bin 0 -> 68608 bytes plugins/dev9/dev9null/src/Dev9null.sln | 18 + plugins/dev9/dev9null/src/Dev9null.suo | Bin 0 -> 9216 bytes plugins/dev9/dev9null/src/Dev9null.vcproj | 100 + .../dev9null/src/Dev9null_vsnet2005beta1.sln | 26 + .../src/Dev9null_vsnet2005beta1.vcproj | 414 + plugins/dev9/dev9null/src/Makefile | 23 + plugins/dev9/dev9null/src/Makefile.mingw | 51 + plugins/dev9/dev9null/src/PS2Edefs.h | 684 + plugins/dev9/dev9null/src/PS2Etypes.h | 31 + plugins/dev9/dev9null/src/dev9null.c | 152 + plugins/dev9/dev9null/src/dev9null.def | 27 + plugins/dev9/dev9null/src/plugin.def | 22 + plugins/fw/FWlinuz/FW.c | 285 + plugins/fw/FWlinuz/FW.h | 62 + plugins/fw/FWlinuz/License.txt | 342 + plugins/fw/FWlinuz/Linux/Config.c | 51 + plugins/fw/FWlinuz/Linux/Config.h | 20 + plugins/fw/FWlinuz/Linux/Linux.c | 75 + plugins/fw/FWlinuz/Linux/Makefile | 34 + plugins/fw/FWlinuz/Linux/callbacks.c | 34 + plugins/fw/FWlinuz/Linux/callbacks.h | 14 + plugins/fw/FWlinuz/Linux/conf.c | 136 + plugins/fw/FWlinuz/Linux/firewire.glade | 300 + plugins/fw/FWlinuz/Linux/interface.c | 219 + plugins/fw/FWlinuz/Linux/interface.h | 6 + plugins/fw/FWlinuz/Linux/support.c | 162 + plugins/fw/FWlinuz/Linux/support.h | 38 + plugins/fw/FWlinuz/PS2Edefs.h | 724 + plugins/fw/FWlinuz/PS2Etypes.h | 43 + plugins/fw/FWlinuz/ReadMe.txt | 25 + plugins/fw/FWlinuz/Win32/Config.c | 45 + plugins/fw/FWlinuz/Win32/FWlinuz.def | 19 + plugins/fw/FWlinuz/Win32/FWlinuz.rc | 123 + plugins/fw/FWlinuz/Win32/FWlinuz.sln | 18 + plugins/fw/FWlinuz/Win32/FireWireNull.ncb | Bin 0 -> 60416 bytes plugins/fw/FWlinuz/Win32/FireWireNull.sln | 18 + plugins/fw/FWlinuz/Win32/FireWireNull.suo | Bin 0 -> 8192 bytes plugins/fw/FWlinuz/Win32/FireWireNull.vcproj | 109 + plugins/fw/FWlinuz/Win32/Makefile | 52 + plugins/fw/FWlinuz/Win32/Win32.c | 80 + plugins/fw/FWlinuz/Win32/afxresmw.h | 5 + plugins/fw/FWlinuz/Win32/plugin.def | 15 + plugins/fw/FWlinuz/Win32/resource.h | 21 + plugins/fw/FWnull/FW.c | 147 + plugins/fw/FWnull/FW.h | 59 + plugins/fw/FWnull/License.txt | 342 + plugins/fw/FWnull/Linux/Config.c | 51 + plugins/fw/FWnull/Linux/Config.h | 20 + plugins/fw/FWnull/Linux/Linux.c | 75 + plugins/fw/FWnull/Linux/Makefile | 35 + plugins/fw/FWnull/Linux/callbacks.c | 34 + plugins/fw/FWnull/Linux/callbacks.h | 14 + plugins/fw/FWnull/Linux/conf.c | 136 + plugins/fw/FWnull/Linux/firewire.glade | 300 + plugins/fw/FWnull/Linux/interface.c | 219 + plugins/fw/FWnull/Linux/interface.h | 6 + plugins/fw/FWnull/Linux/support.c | 162 + plugins/fw/FWnull/Linux/support.h | 38 + plugins/fw/FWnull/PS2Edefs.h | 724 + plugins/fw/FWnull/PS2Etypes.h | 31 + plugins/fw/FWnull/ReadMe.txt | 34 + plugins/fw/FWnull/Win32/Config.c | 51 + plugins/fw/FWnull/Win32/FireWireNull.def | 19 + plugins/fw/FWnull/Win32/FireWireNull.dsp | 139 + plugins/fw/FWnull/Win32/FireWireNull.dsw | 29 + plugins/fw/FWnull/Win32/FireWireNull.ncb | Bin 0 -> 52224 bytes plugins/fw/FWnull/Win32/FireWireNull.rc | 123 + plugins/fw/FWnull/Win32/FireWireNull.sln | 18 + plugins/fw/FWnull/Win32/FireWireNull.suo | Bin 0 -> 7168 bytes plugins/fw/FWnull/Win32/FireWireNull.vcproj | 112 + .../Win32/FireWireNull_vsnet2005beta1.sln | 26 + .../Win32/FireWireNull_vsnet2005beta1.vcproj | 431 + plugins/fw/FWnull/Win32/Makefile | 29 + plugins/fw/FWnull/Win32/PS2Edefs.h | 651 + plugins/fw/FWnull/Win32/Win32.c | 81 + plugins/fw/FWnull/Win32/afxresmw.h | 5 + plugins/fw/FWnull/Win32/plugin.def | 15 + plugins/fw/FWnull/Win32/resource.h | 21 + plugins/fw/FWnull/build.sh | 15 + plugins/fw/build.sh | 13 + plugins/gs/GSsoft/License.txt | 342 + plugins/gs/GSsoft/ReadMe.txt | 109 + plugins/gs/GSsoft/Src/Cache.c | 201 + plugins/gs/GSsoft/Src/Cache.h | 30 + plugins/gs/GSsoft/Src/Color.c | 1271 + plugins/gs/GSsoft/Src/Color.h | 40 + plugins/gs/GSsoft/Src/Draw.c | 530 + plugins/gs/GSsoft/Src/Draw.h | 36 + plugins/gs/GSsoft/Src/GS.c | 825 + plugins/gs/GSsoft/Src/GS.h | 575 + plugins/gs/GSsoft/Src/Linux-SDL/Conf.c | 65 + plugins/gs/GSsoft/Src/Linux-SDL/X11.c | 279 + plugins/gs/GSsoft/Src/Linux/Conf.c | 88 + plugins/gs/GSsoft/Src/Linux/Linux.c | 320 + plugins/gs/GSsoft/Src/Linux/Linux.h | 24 + plugins/gs/GSsoft/Src/Linux/Makefile | 46 + plugins/gs/GSsoft/Src/Linux/callbacks.c | 58 + plugins/gs/GSsoft/Src/Linux/callbacks.h | 26 + plugins/gs/GSsoft/Src/Linux/gssoft.glade | 791 + plugins/gs/GSsoft/Src/Linux/interface.c | 517 + plugins/gs/GSsoft/Src/Linux/interface.h | 7 + plugins/gs/GSsoft/Src/Linux/support.c | 162 + plugins/gs/GSsoft/Src/Linux/support.h | 38 + plugins/gs/GSsoft/Src/Mem.c | 174 + plugins/gs/GSsoft/Src/Mem.h | 59 + plugins/gs/GSsoft/Src/PS2Edefs.h | 696 + plugins/gs/GSsoft/Src/PS2Etypes.h | 43 + plugins/gs/GSsoft/Src/Page.c | 354 + plugins/gs/GSsoft/Src/Page.h | 33 + plugins/gs/GSsoft/Src/Prim.c | 390 + plugins/gs/GSsoft/Src/Rec.c | 285 + plugins/gs/GSsoft/Src/Rec.h | 27 + plugins/gs/GSsoft/Src/Regs.c | 1159 + plugins/gs/GSsoft/Src/Regs.h | 24 + plugins/gs/GSsoft/Src/SDL.c | 396 + plugins/gs/GSsoft/Src/SDL_gfxPrimitives.c | 2561 ++ plugins/gs/GSsoft/Src/SDL_gfxPrimitives.h | 125 + .../gs/GSsoft/Src/SDL_gfxPrimitives_font.h | 2567 ++ plugins/gs/GSsoft/Src/Soft.c | 1504 ++ plugins/gs/GSsoft/Src/Soft.h | 107 + plugins/gs/GSsoft/Src/System.h | 29 + plugins/gs/GSsoft/Src/Texts.c | 544 + plugins/gs/GSsoft/Src/Texts.h | 28 + plugins/gs/GSsoft/Src/Transfer.c | 1328 + plugins/gs/GSsoft/Src/Transfer.h | 27 + plugins/gs/GSsoft/Src/Win32/Conf.c | 110 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.def | 33 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsp | 202 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsw | 29 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.ncb | Bin 0 -> 273408 bytes plugins/gs/GSsoft/Src/Win32/GSsoftdx.rc | 174 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.sln | 18 + plugins/gs/GSsoft/Src/Win32/GSsoftdx.suo | Bin 0 -> 8192 bytes plugins/gs/GSsoft/Src/Win32/GSsoftdx.vcproj | 339 + plugins/gs/GSsoft/Src/Win32/Makefile | 58 + plugins/gs/GSsoft/Src/Win32/SDL.c | 225 + plugins/gs/GSsoft/Src/Win32/Win32.c | 274 + plugins/gs/GSsoft/Src/Win32/Win32.h | 4 + plugins/gs/GSsoft/Src/Win32/afxresmw.h | 5 + plugins/gs/GSsoft/Src/Win32/plugin.def | 31 + plugins/gs/GSsoft/Src/Win32/plugin.h | 18 + plugins/gs/GSsoft/Src/Win32/resource.h | 42 + plugins/gs/GSsoft/Src/avcodec.h | 1688 ++ plugins/gs/GSsoft/Src/common.h | 1142 + plugins/gs/GSsoft/Src/ffmpeg/avformat.h | 544 + plugins/gs/GSsoft/Src/ffmpeg/avio.h | 169 + plugins/gs/GSsoft/Src/ffmpeg/rtp.h | 40 + plugins/gs/GSsoft/Src/ffmpeg/rtsp.h | 90 + plugins/gs/GSsoft/Src/ffmpeg/rtspcodes.h | 11 + plugins/gs/GSsoft/Src/scale2x.c | 141 + plugins/gs/GSsoft/Src/scale2x.h | 17 + plugins/gs/GSsoft/Src/x86/ix86.h | 1020 + plugins/gs/GSsoft/Src/x86/ix86_cpudetect.c | 510 + plugins/gs/build.sh | 10 + plugins/gs/zerogs/build.sh | 31 + plugins/gs/zerogs/opengl/GS.h | 840 + plugins/gs/zerogs/opengl/GSmain.cpp | 1370 + plugins/gs/zerogs/opengl/Linux/Conf.cpp | 104 + plugins/gs/zerogs/opengl/Linux/Linux.cpp | 305 + plugins/gs/zerogs/opengl/Linux/Linux.h | 24 + plugins/gs/zerogs/opengl/Linux/Makefile.am | 6 + plugins/gs/zerogs/opengl/Linux/buildgui.sh | 9 + plugins/gs/zerogs/opengl/Linux/callbacks.c | 34 + plugins/gs/zerogs/opengl/Linux/callbacks.h | 14 + plugins/gs/zerogs/opengl/Linux/interface.c | 291 + plugins/gs/zerogs/opengl/Linux/interface.h | 6 + plugins/gs/zerogs/opengl/Linux/support.c | 144 + plugins/gs/zerogs/opengl/Linux/support.h | 69 + plugins/gs/zerogs/opengl/Linux/zerogs.glade | 598 + plugins/gs/zerogs/opengl/Makefile.am | 48 + plugins/gs/zerogs/opengl/Mem.cpp | 892 + plugins/gs/zerogs/opengl/Mem.h | 487 + plugins/gs/zerogs/opengl/PS2Edefs.h | 815 + plugins/gs/zerogs/opengl/PS2Etypes.h | 76 + plugins/gs/zerogs/opengl/Regs.cpp | 981 + plugins/gs/zerogs/opengl/Regs.h | 101 + plugins/gs/zerogs/opengl/Win32/Conf.cpp | 100 + plugins/gs/zerogs/opengl/Win32/Win32.cpp | 233 + plugins/gs/zerogs/opengl/Win32/Win32.h | 9 + plugins/gs/zerogs/opengl/Win32/aviUtil.h | 484 + .../gs/zerogs/opengl/Win32/copytopcsx2.bat | 4 + plugins/gs/zerogs/opengl/Win32/jconfig.h | 52 + plugins/gs/zerogs/opengl/Win32/jmorecfg.h | 363 + plugins/gs/zerogs/opengl/Win32/jpeglib.h | 1099 + plugins/gs/zerogs/opengl/Win32/libjpeg.lib | Bin 0 -> 470518 bytes plugins/gs/zerogs/opengl/Win32/libjpeg64.lib | Bin 0 -> 1010392 bytes plugins/gs/zerogs/opengl/Win32/ps2hw.dat | Bin 0 -> 106682 bytes plugins/gs/zerogs/opengl/Win32/resource.h | 45 + plugins/gs/zerogs/opengl/Win32/resrc1.h | 73 + plugins/gs/zerogs/opengl/Win32/zerogs.bmp | Bin 0 -> 921656 bytes plugins/gs/zerogs/opengl/Win32/zerogs.def | 35 + plugins/gs/zerogs/opengl/Win32/zerogs.rc | 218 + .../gs/zerogs/opengl/Win32/zerogsogl.vcproj | 437 + .../zerogs/opengl/Win32/zerogsogl_2005.vcproj | 579 + .../opengl/Win32/zerogsogl_2005_x64.vcproj | 874 + plugins/gs/zerogs/opengl/Win32/zlib/adler32.c | 74 + .../gs/zerogs/opengl/Win32/zlib/compress.c | 79 + plugins/gs/zerogs/opengl/Win32/zlib/crc32.c | 311 + plugins/gs/zerogs/opengl/Win32/zlib/crc32.h | 441 + plugins/gs/zerogs/opengl/Win32/zlib/deflate.c | 1502 ++ plugins/gs/zerogs/opengl/Win32/zlib/deflate.h | 326 + plugins/gs/zerogs/opengl/Win32/zlib/gzio.c | 1005 + plugins/gs/zerogs/opengl/Win32/zlib/infback.c | 619 + plugins/gs/zerogs/opengl/Win32/zlib/inffast.c | 305 + plugins/gs/zerogs/opengl/Win32/zlib/inffast.h | 11 + .../gs/zerogs/opengl/Win32/zlib/inffixed.h | 94 + plugins/gs/zerogs/opengl/Win32/zlib/inflate.c | 1270 + plugins/gs/zerogs/opengl/Win32/zlib/inflate.h | 117 + .../gs/zerogs/opengl/Win32/zlib/inftrees.c | 321 + .../gs/zerogs/opengl/Win32/zlib/inftrees.h | 55 + plugins/gs/zerogs/opengl/Win32/zlib/trees.c | 1215 + plugins/gs/zerogs/opengl/Win32/zlib/trees.h | 128 + plugins/gs/zerogs/opengl/Win32/zlib/uncompr.c | 61 + plugins/gs/zerogs/opengl/Win32/zlib/zconf.h | 323 + plugins/gs/zerogs/opengl/Win32/zlib/zlib.h | 1200 + plugins/gs/zerogs/opengl/Win32/zlib/zutil.c | 319 + plugins/gs/zerogs/opengl/Win32/zlib/zutil.h | 258 + .../zerogs/opengl/ZeroGSShaders/Makefile.am | 2 + .../gs/zerogs/opengl/ZeroGSShaders/ZLib.lib | Bin 0 -> 101154 bytes .../opengl/ZeroGSShaders/ZeroGSShaders.vcproj | 191 + .../ZeroGSShaders/ZeroGSShaders_2005.sln | 23 + .../ZeroGSShaders/ZeroGSShaders_2005.vcproj | 335 + .../opengl/ZeroGSShaders/copytozerogs.bat | 1 + .../opengl/ZeroGSShaders/zerogsshaders.cpp | 337 + .../opengl/ZeroGSShaders/zerogsshaders.h | 89 + .../zerogs/opengl/ZeroGSShaders/zlib/crc32.h | 441 + .../opengl/ZeroGSShaders/zlib/deflate.h | 331 + .../opengl/ZeroGSShaders/zlib/inffast.h | 11 + .../opengl/ZeroGSShaders/zlib/inffixed.h | 94 + .../opengl/ZeroGSShaders/zlib/inflate.h | 115 + .../opengl/ZeroGSShaders/zlib/inftrees.h | 55 + .../zerogs/opengl/ZeroGSShaders/zlib/trees.h | 128 + .../zerogs/opengl/ZeroGSShaders/zlib/zconf.h | 332 + .../opengl/ZeroGSShaders/zlib/zconf.in.h | 332 + .../zerogs/opengl/ZeroGSShaders/zlib/zlib.h | 1357 + .../zerogs/opengl/ZeroGSShaders/zlib/zutil.h | 269 + .../gs/zerogs/opengl/ZeroGSShaders/zpipe.cpp | 115 + .../gs/zerogs/opengl/ZeroGSShaders/zpipe.h | 7 + plugins/gs/zerogs/opengl/buildshaders.bat | 3 + plugins/gs/zerogs/opengl/common.h | 1142 + plugins/gs/zerogs/opengl/compile | 1 + plugins/gs/zerogs/opengl/configure | 5631 ++++ plugins/gs/zerogs/opengl/configure.ac | 148 + plugins/gs/zerogs/opengl/depcomp | 529 + plugins/gs/zerogs/opengl/glprocs.c | 17864 ++++++++++++ plugins/gs/zerogs/opengl/glprocs.h | 2213 ++ plugins/gs/zerogs/opengl/install-sh | 323 + plugins/gs/zerogs/opengl/memcpy_amd.cpp | 479 + plugins/gs/zerogs/opengl/missing | 360 + plugins/gs/zerogs/opengl/mkinstalldirs | 158 + plugins/gs/zerogs/opengl/rasterfont.cpp | 147 + plugins/gs/zerogs/opengl/rasterfont.h | 22 + plugins/gs/zerogs/opengl/targets.cpp | 3501 +++ plugins/gs/zerogs/opengl/targets.h | 160 + plugins/gs/zerogs/opengl/x86-32.S | 1002 + plugins/gs/zerogs/opengl/x86-32.asm | 652 + plugins/gs/zerogs/opengl/x86-64.S | 903 + plugins/gs/zerogs/opengl/x86-64.asm | 1094 + plugins/gs/zerogs/opengl/x86.cpp | 571 + plugins/gs/zerogs/opengl/x86.h | 182 + plugins/gs/zerogs/opengl/zerogs.cpp | 5908 ++++ plugins/gs/zerogs/opengl/zerogs.h | 544 + plugins/gs/zerogs/opengl/zerogsmath.h | 900 + plugins/gs/zerogs/opengl/zpipe.cpp | 115 + plugins/gs/zerogs/opengl/zpipe.h | 7 + plugins/pad/PADwin/ReadMe.txt | 89 + plugins/pad/PADwin/Src/Conf.c | 98 + plugins/pad/PADwin/Src/Linux.c | 210 + plugins/pad/PADwin/Src/Makefile | 25 + plugins/pad/PADwin/Src/Makefile.mingw | 29 + plugins/pad/PADwin/Src/PAD.c | 528 + plugins/pad/PADwin/Src/PAD.h | 107 + plugins/pad/PADwin/Src/PADwinKeyb.def | 22 + plugins/pad/PADwin/Src/PADwinKeyb.dsp | 114 + plugins/pad/PADwin/Src/PADwinKeyb.dsw | 29 + plugins/pad/PADwin/Src/PADwinKeyb.sln | 18 + plugins/pad/PADwin/Src/PADwinKeyb.suo | Bin 0 -> 9216 bytes plugins/pad/PADwin/Src/PADwinKeyb.vcproj | 125 + .../PADwin/Src/PADwinKeyb_vsnet2005beta1.sln | 26 + .../Src/PADwinKeyb_vsnet2005beta1.vcproj | 385 + plugins/pad/PADwin/Src/PADwnKeyb.rc | 150 + plugins/pad/PADwin/Src/PS2Edefs.h | 812 + plugins/pad/PADwin/Src/PS2Etypes.h | 75 + plugins/pad/PADwin/Src/Win32.c | 549 + plugins/pad/PADwin/Src/afxresmw.h | 5 + plugins/pad/PADwin/Src/callbacks.c | 58 + plugins/pad/PADwin/Src/callbacks.h | 26 + plugins/pad/PADwin/Src/controller.bmp | Bin 0 -> 490056 bytes plugins/pad/PADwin/Src/interface.c | 483 + plugins/pad/PADwin/Src/interface.h | 6 + plugins/pad/PADwin/Src/mingw/Makefile.win | 43 + plugins/pad/PADwin/Src/mingw/PADwinKeyb.dev | 156 + .../pad/PADwin/Src/mingw/PADwinKeyb.layout | 56 + plugins/pad/PADwin/Src/mingw/afxres.h | 5 + plugins/pad/PADwin/Src/plugin.def | 17 + plugins/pad/PADwin/Src/ps2pad.bmp | Bin 0 -> 320918 bytes plugins/pad/PADwin/Src/resource.h | 70 + plugins/pad/PADwin/Src/support.c | 162 + plugins/pad/PADwin/Src/support.h | 38 + plugins/pad/PADwin/build.sh | 15 + plugins/pad/SSSPSXPAD/PadSSSPSX.cpp | 1041 + plugins/pad/SSSPSXPAD/PadSSSPSX.def | 22 + plugins/pad/SSSPSXPAD/PadSSSPSX.h | 45 + plugins/pad/SSSPSXPAD/PadSSSPSX.rc | 152 + plugins/pad/SSSPSXPAD/PadSSSPSX.vcproj | 213 + .../pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.sln | 26 + .../SSSPSXPAD/PadSSSPSX_vc2005beta2.vcproj | 488 + plugins/pad/SSSPSXPAD/PadSSSPSXres.h | 59 + plugins/pad/SSSPSXPAD/licence.txt | 1 + plugins/pad/SSSPSXPAD/readmewip.txt | 48 + plugins/pad/build.sh | 23 + plugins/pad/zeropad/Makefile.am | 29 + plugins/pad/zeropad/PS2Edefs.h | 827 + plugins/pad/zeropad/PS2Etypes.h | 75 + plugins/pad/zeropad/Windows/ZeroPAD.def | 17 + plugins/pad/zeropad/Windows/ZeroPAD.rc | 136 + plugins/pad/zeropad/Windows/ZeroPAD.vcproj | 164 + .../pad/zeropad/Windows/ZeroPAD_2005.vcproj | 236 + .../zeropad/Windows/ZeroPAD_2005_x64.vcproj | 394 + plugins/pad/zeropad/Windows/resource.h | 70 + plugins/pad/zeropad/Windows/win.cpp | 315 + plugins/pad/zeropad/build.sh | 28 + plugins/pad/zeropad/callbacks.h | 22 + plugins/pad/zeropad/compile | 1 + plugins/pad/zeropad/configure.ac | 102 + plugins/pad/zeropad/depcomp | 529 + plugins/pad/zeropad/install-sh | 323 + plugins/pad/zeropad/interface.c | 570 + plugins/pad/zeropad/interface.h | 6 + plugins/pad/zeropad/linux.cpp | 370 + plugins/pad/zeropad/missing | 360 + plugins/pad/zeropad/mkinstalldirs | 158 + plugins/pad/zeropad/support.c | 144 + plugins/pad/zeropad/support.h | 69 + plugins/pad/zeropad/zeropad.cpp | 492 + plugins/pad/zeropad/zeropad.glade | 1034 + plugins/pad/zeropad/zeropad.h | 115 + plugins/spu2/PeopsSPU2/Filemap.txt | 49 + plugins/spu2/PeopsSPU2/Makefile | 75 + plugins/spu2/PeopsSPU2/Makefile.win | 79 + plugins/spu2/PeopsSPU2/_bsc.txt | 17 + plugins/spu2/PeopsSPU2/adsr.c | 672 + plugins/spu2/PeopsSPU2/adsr.h | 28 + plugins/spu2/PeopsSPU2/alsa.c | 206 + plugins/spu2/PeopsSPU2/alsa.h | 30 + plugins/spu2/PeopsSPU2/build.sh | 16 + plugins/spu2/PeopsSPU2/cfg.c | 266 + plugins/spu2/PeopsSPU2/cfg.h | 36 + plugins/spu2/PeopsSPU2/clean.bat | 3 + plugins/spu2/PeopsSPU2/debug.c | 442 + plugins/spu2/PeopsSPU2/debug.h | 34 + plugins/spu2/PeopsSPU2/dma.c | 339 + plugins/spu2/PeopsSPU2/dma.h | 28 + plugins/spu2/PeopsSPU2/dsound.c | 268 + plugins/spu2/PeopsSPU2/dsound.h | 2357 ++ plugins/spu2/PeopsSPU2/dsoundoss.h | 36 + plugins/spu2/PeopsSPU2/externals.h | 362 + plugins/spu2/PeopsSPU2/freeze.c | 246 + plugins/spu2/PeopsSPU2/gauss_i.h | 162 + plugins/spu2/PeopsSPU2/mingw/afxres.h | 2 + plugins/spu2/PeopsSPU2/oss.c | 190 + plugins/spu2/PeopsSPU2/oss.h | 37 + plugins/spu2/PeopsSPU2/psemu.c | 0 plugins/spu2/PeopsSPU2/psemuxa.h | 28 + plugins/spu2/PeopsSPU2/record.c | 184 + plugins/spu2/PeopsSPU2/record.h | 12 + plugins/spu2/PeopsSPU2/registers.c | 1230 + plugins/spu2/PeopsSPU2/registers.h | 806 + plugins/spu2/PeopsSPU2/regs.h | 43 + plugins/spu2/PeopsSPU2/res/spu2PeopsSound.rc2 | 13 + plugins/spu2/PeopsSPU2/resource.h | 161 + plugins/spu2/PeopsSPU2/reverb.c | 420 + plugins/spu2/PeopsSPU2/reverb.h | 33 + plugins/spu2/PeopsSPU2/spu.c | 1323 + plugins/spu2/PeopsSPU2/spu.h | 33 + plugins/spu2/PeopsSPU2/spu2PeopsSound.aps | Bin 0 -> 51024 bytes plugins/spu2/PeopsSPU2/spu2PeopsSound.c | 44 + plugins/spu2/PeopsSPU2/spu2PeopsSound.def | 34 + plugins/spu2/PeopsSPU2/spu2PeopsSound.dev | 478 + plugins/spu2/PeopsSPU2/spu2PeopsSound.dsp | 282 + plugins/spu2/PeopsSPU2/spu2PeopsSound.dsw | 29 + plugins/spu2/PeopsSPU2/spu2PeopsSound.layout | 284 + plugins/spu2/PeopsSPU2/spu2PeopsSound.opt | Bin 0 -> 54784 bytes plugins/spu2/PeopsSPU2/spu2PeopsSound.plg | 81 + plugins/spu2/PeopsSPU2/spu2PeopsSound.rc | 415 + plugins/spu2/PeopsSPU2/spu2PeopsSound.sln | 21 + plugins/spu2/PeopsSPU2/spu2PeopsSound.vcproj | 476 + .../spu2/PeopsSPU2/spu2PeopsSound_2005.sln | 19 + .../spu2/PeopsSPU2/spu2PeopsSound_2005.vcproj | 620 + .../PeopsSPU2/spu2PeopsSound_2005_x64.sln | 20 + .../PeopsSPU2/spu2PeopsSound_2005_x64.vcproj | 1078 + .../spu2/PeopsSPU2/spu2PeopsSound_private.h | 23 + .../spu2/PeopsSPU2/spu2PeopsSound_private.rc | 5 + .../spu2/PeopsSPU2/spu2PeopsSound_private.res | Bin 0 -> 10492 bytes plugins/spu2/PeopsSPU2/spunew.c | 1272 + plugins/spu2/PeopsSPU2/stdafx.c | 8 + plugins/spu2/PeopsSPU2/stdafx.h | 86 + plugins/spu2/PeopsSPU2/xa.c | 363 + plugins/spu2/PeopsSPU2/xa.h | 29 + plugins/spu2/SPU2null/License.txt | 342 + plugins/spu2/SPU2null/ReadMe.txt | 39 + plugins/spu2/SPU2null/Src/Changelog.txt | 30 + plugins/spu2/SPU2null/Src/Config.cpp | 51 + plugins/spu2/SPU2null/Src/Makefile | 25 + plugins/spu2/SPU2null/Src/Makefile.mingw | 51 + plugins/spu2/SPU2null/Src/PS2Edefs.h | 812 + plugins/spu2/SPU2null/Src/PS2Etypes.h | 76 + plugins/spu2/SPU2null/Src/SPU2.cpp | 1185 + plugins/spu2/SPU2null/Src/SPU2.h | 278 + plugins/spu2/SPU2null/Src/SPU2null.def | 31 + plugins/spu2/SPU2null/Src/SPU2null.ncb | Bin 0 -> 109568 bytes plugins/spu2/SPU2null/Src/SPU2null.rc | 132 + plugins/spu2/SPU2null/Src/SPU2null.sln | 21 + plugins/spu2/SPU2null/Src/SPU2null.vcproj | 164 + plugins/spu2/SPU2null/Src/SPU2null_2005.sln | 20 + .../spu2/SPU2null/Src/SPU2null_2005.vcproj | 234 + .../spu2/SPU2null/Src/SPU2null_2005_x64.sln | 20 + .../SPU2null/Src/SPU2null_2005_x64.vcproj | 398 + plugins/spu2/SPU2null/Src/Win32.cpp | 80 + plugins/spu2/SPU2null/Src/mingw/Makefile.win | 43 + plugins/spu2/SPU2null/Src/mingw/SPU2null.dev | 148 + plugins/spu2/SPU2null/Src/mingw/afxres.h | 5 + plugins/spu2/SPU2null/Src/mingw/plugin.def | 22 + plugins/spu2/SPU2null/Src/resource.h | 21 + plugins/spu2/SPU2null/build.sh | 12 + plugins/spu2/build.sh | 23 + plugins/usb/USBlinuz/License.txt | 342 + plugins/usb/USBlinuz/Linux/Config.c | 51 + plugins/usb/USBlinuz/Linux/Config.h | 20 + plugins/usb/USBlinuz/Linux/Linux.c | 75 + plugins/usb/USBlinuz/Linux/Makefile | 33 + plugins/usb/USBlinuz/Linux/callbacks.c | 34 + plugins/usb/USBlinuz/Linux/callbacks.h | 14 + plugins/usb/USBlinuz/Linux/conf.c | 136 + plugins/usb/USBlinuz/Linux/interface.c | 219 + plugins/usb/USBlinuz/Linux/interface.h | 6 + plugins/usb/USBlinuz/Linux/support.c | 162 + plugins/usb/USBlinuz/Linux/support.h | 38 + plugins/usb/USBlinuz/Linux/usblinuz.glade | 300 + plugins/usb/USBlinuz/PS2Edefs.h | 684 + plugins/usb/USBlinuz/PS2Etypes.h | 31 + plugins/usb/USBlinuz/ReadMe.txt | 36 + plugins/usb/USBlinuz/USB.c | 446 + plugins/usb/USBlinuz/USB.h | 197 + plugins/usb/USBlinuz/Win32/Config.c | 51 + plugins/usb/USBlinuz/Win32/USBlinuz.def | 27 + plugins/usb/USBlinuz/Win32/USBlinuz.dsp | 99 + plugins/usb/USBlinuz/Win32/USBlinuz.dsw | 29 + plugins/usb/USBlinuz/Win32/USBlinuz.rc | 120 + plugins/usb/USBlinuz/Win32/USBlinuz.sln | 18 + plugins/usb/USBlinuz/Win32/USBlinuz.suo | Bin 0 -> 8704 bytes plugins/usb/USBlinuz/Win32/USBlinuz.vcproj | 118 + .../usb/USBlinuz/Win32/USBlinuz_vc2002.sln | 21 + .../usb/USBlinuz/Win32/USBlinuz_vc2002.vcproj | 150 + .../usb/USBlinuz/Win32/USBlinuz_vc2003.ncb | Bin 0 -> 52224 bytes .../usb/USBlinuz/Win32/USBlinuz_vc2003.sln | 21 + .../usb/USBlinuz/Win32/USBlinuz_vc2003.suo | Bin 0 -> 8704 bytes .../usb/USBlinuz/Win32/USBlinuz_vc2003.vcproj | 164 + .../USBlinuz/Win32/USBlinuz_vc2005beta1.sln | 32 + .../Win32/USBlinuz_vc2005beta1.vcproj | 566 + plugins/usb/USBlinuz/Win32/Win32.c | 81 + plugins/usb/USBlinuz/Win32/resource.h | 21 + plugins/usb/USBnull/License.txt | 342 + plugins/usb/USBnull/Linux/Config.c | 59 + plugins/usb/USBnull/Linux/Config.h | 20 + plugins/usb/USBnull/Linux/Linux.c | 74 + plugins/usb/USBnull/Linux/Makefile | 35 + plugins/usb/USBnull/Linux/callbacks.c | 34 + plugins/usb/USBnull/Linux/callbacks.h | 14 + plugins/usb/USBnull/Linux/conf.c | 128 + plugins/usb/USBnull/Linux/interface.c | 219 + plugins/usb/USBnull/Linux/interface.h | 6 + plugins/usb/USBnull/Linux/support.c | 162 + plugins/usb/USBnull/Linux/support.h | 38 + plugins/usb/USBnull/Linux/usbnull.glade | 300 + plugins/usb/USBnull/PS2Edefs.h | 684 + plugins/usb/USBnull/PS2Etypes.h | 31 + plugins/usb/USBnull/ReadMe.txt | 34 + plugins/usb/USBnull/USB.c | 170 + plugins/usb/USBnull/USB.h | 66 + plugins/usb/USBnull/Win32/Config.c | 51 + plugins/usb/USBnull/Win32/Makefile | 53 + plugins/usb/USBnull/Win32/USBnull.def | 27 + plugins/usb/USBnull/Win32/USBnull.dsp | 85 + plugins/usb/USBnull/Win32/USBnull.dsw | 29 + plugins/usb/USBnull/Win32/USBnull.rc | 121 + plugins/usb/USBnull/Win32/USBnull_vc2003.sln | 21 + .../usb/USBnull/Win32/USBnull_vc2003.vcproj | 164 + .../usb/USBnull/Win32/USBnull_vc2005beta1.sln | 32 + .../USBnull/Win32/USBnull_vc2005beta1.vcproj | 527 + plugins/usb/USBnull/Win32/Win32.c | 80 + plugins/usb/USBnull/Win32/afxresmw.h | 5 + plugins/usb/USBnull/Win32/mingw/Makefile.win | 43 + plugins/usb/USBnull/Win32/mingw/USBnull.dev | 138 + .../usb/USBnull/Win32/mingw/USBnull.layout | 50 + plugins/usb/USBnull/Win32/mingw/afxres.h | 5 + plugins/usb/USBnull/Win32/plugin.def | 22 + plugins/usb/USBnull/Win32/resource.h | 21 + plugins/usb/USBnull/build.sh | 20 + plugins/usb/build.sh | 15 + test.bat | 3 + test.cfg | 2 + test.sh | 28 + test_readme.txt | 6 + 2235 files changed, 781748 insertions(+) create mode 100644 INSTALL create mode 100644 bin/.pixmaps/pcsxAbout.bmp create mode 100644 bin/A39517AB.xml create mode 100644 bin/Langs/ar_AR/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/bg_BG/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/cz_CZ/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/de_DE/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/du_DU/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/el_EL/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/es_ES/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/fr_FR/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/hb_HB/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/it_IT/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/ja_JA/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/pe_PE/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/pl_PL/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/po_BR/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/po_PO/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/ro_RO/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/ru_RU/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/sh_SH/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/sw_SW/LC_MESSAGES/other.po create mode 100644 bin/Langs/sw_SW/LC_MESSAGES/pcsx2.mo create mode 100644 bin/Langs/tc_TC/LC_MESSAGES/Pcsx2.mo create mode 100644 bin/Langs/tr_TR/LC_MESSAGES/pcsx2.mo create mode 100644 bin/compat_list/compat_list.html create mode 100644 bin/compat_list/h_console.jpg create mode 100644 bin/compat_list/h_region.jpg create mode 100644 bin/compat_list/h_serial.jpg create mode 100644 bin/compat_list/h_status.jpg create mode 100644 bin/compat_list/h_title.jpg create mode 100644 bin/compat_list/h_version.jpg create mode 100644 bin/compat_list/sq_ingame.jpg create mode 100644 bin/compat_list/sq_intro.jpg create mode 100644 bin/compat_list/sq_menus.jpg create mode 100644 bin/compat_list/sq_nothing.jpg create mode 100644 bin/compat_list/sq_playable.jpg create mode 100644 bin/inis/pcsx2.ini create mode 100644 bin/patches/013E349D.pnach create mode 100644 bin/patches/015314A2.pnach create mode 100644 bin/patches/034836F8.pnach create mode 100644 bin/patches/0442B1BD.pnach create mode 100644 bin/patches/05177ECE.pnach create mode 100644 bin/patches/0518D274.pnach create mode 100644 bin/patches/0518D275.pnach create mode 100644 bin/patches/07AD79C9.pnach create mode 100644 bin/patches/0838D766.pnach create mode 100644 bin/patches/08901101.pnach create mode 100644 bin/patches/08FB9DCF.pnach create mode 100644 bin/patches/0999F9DB.pnach create mode 100644 bin/patches/0A342A88.pnach create mode 100644 bin/patches/0B359BBF.pnach create mode 100644 bin/patches/0C370E94.pnach create mode 100644 bin/patches/0F6B6315.pnach create mode 100644 bin/patches/1025D50A.pnach create mode 100644 bin/patches/116154AD.pnach create mode 100644 bin/patches/1248FE3A.pnach create mode 100644 bin/patches/129C8600.pnach create mode 100644 bin/patches/12AFF4D4.pnach create mode 100644 bin/patches/1468C474.pnach create mode 100644 bin/patches/1510E1D1.pnach create mode 100644 bin/patches/1629D655.pnach create mode 100644 bin/patches/163F0461.pnach create mode 100644 bin/patches/1738A5B0.pnach create mode 100644 bin/patches/19D145D7.pnach create mode 100644 bin/patches/1CAC8A56.pnach create mode 100644 bin/patches/1D2818AF.pnach create mode 100644 bin/patches/200BC0E6.pnach create mode 100644 bin/patches/2088950A.pnach create mode 100644 bin/patches/21068223.pnach create mode 100644 bin/patches/27E54B37.pnach create mode 100644 bin/patches/280DAC56.pnach create mode 100644 bin/patches/295D2F96.pnach create mode 100644 bin/patches/29D80A23.pnach create mode 100644 bin/patches/2B2E1535.pnach create mode 100644 bin/patches/2C728173.pnach create mode 100644 bin/patches/2CFFFA50.pnach create mode 100644 bin/patches/2D919421.pnach create mode 100644 bin/patches/2F56CBC9.pnach create mode 100644 bin/patches/302797DF.pnach create mode 100644 bin/patches/304C115C.pnach create mode 100644 bin/patches/32629F36.pnach create mode 100644 bin/patches/339A0B8C.pnach create mode 100644 bin/patches/33F7D21A.pnach create mode 100644 bin/patches/36FEEE3A.pnach create mode 100644 bin/patches/37BA81B1.pnach create mode 100644 bin/patches/37C07E96.pnach create mode 100644 bin/patches/38F29E28.pnach create mode 100644 bin/patches/3BD85DA4.pnach create mode 100644 bin/patches/3CFE3B37.pnach create mode 100644 bin/patches/3DB65A75.pnach create mode 100644 bin/patches/3E0A256D.pnach create mode 100644 bin/patches/3E68955A.pnach create mode 100644 bin/patches/3F0452DE.pnach create mode 100644 bin/patches/3FB69323.pnach create mode 100644 bin/patches/4043F228.pnach create mode 100644 bin/patches/41A3191C.pnach create mode 100644 bin/patches/4321A427.pnach create mode 100644 bin/patches/4334E17D.pnach create mode 100644 bin/patches/44A61C8F.pnach create mode 100644 bin/patches/4691F6F7.pnach create mode 100644 bin/patches/46A7ECA4.pnach create mode 100644 bin/patches/472C9E70.pnach create mode 100644 bin/patches/48FE0C71.pnach create mode 100644 bin/patches/49DA19CE.pnach create mode 100644 bin/patches/4B6DDB6B.pnach create mode 100644 bin/patches/4C4D7072.pnach create mode 100644 bin/patches/4C9EE7DF.pnach create mode 100644 bin/patches/4D6DBB75.pnach create mode 100644 bin/patches/4DAC50C2.pnach create mode 100644 bin/patches/4F3D3CF0.pnach create mode 100644 bin/patches/506644B3.pnach create mode 100644 bin/patches/5162BCCA.pnach create mode 100644 bin/patches/51D8A6A9.pnach create mode 100644 bin/patches/53A803AF.pnach create mode 100644 bin/patches/53DF159B.pnach create mode 100644 bin/patches/54A548B4.pnach create mode 100644 bin/patches/54AD76D7.pnach create mode 100644 bin/patches/54D6BEE3.pnach create mode 100644 bin/patches/582EED0D.pnach create mode 100644 bin/patches/586EA828.pnach create mode 100644 bin/patches/58EE1AFA.pnach create mode 100644 bin/patches/5A7635C1.pnach create mode 100644 bin/patches/5BBC2F40.pnach create mode 100644 bin/patches/5BC8C9E8.pnach create mode 100644 bin/patches/5BE3F481.pnach create mode 100644 bin/patches/5CCA0737.pnach create mode 100644 bin/patches/5DFBE144.pnach create mode 100644 bin/patches/5E115FB6.pnach create mode 100644 bin/patches/5EB127E7.pnach create mode 100644 bin/patches/5F2A0E36.pnach create mode 100644 bin/patches/60013EBD.pnach create mode 100644 bin/patches/60FA8C69.pnach create mode 100644 bin/patches/624F11F1.pnach create mode 100644 bin/patches/625AF967.pnach create mode 100644 bin/patches/627B8252.pnach create mode 100644 bin/patches/62F6F886.pnach create mode 100644 bin/patches/63F6B523.pnach create mode 100644 bin/patches/68EAF48F.pnach create mode 100644 bin/patches/6926B199.pnach create mode 100644 bin/patches/692CBA8E.pnach create mode 100644 bin/patches/6A4EFE60.pnach create mode 100644 bin/patches/6ADBC24B.pnach create mode 100644 bin/patches/6BA2F6B9.pnach create mode 100644 bin/patches/6D70F0E0.pnach create mode 100644 bin/patches/6EA9DDA9.pnach create mode 100644 bin/patches/7098BE76.pnach create mode 100644 bin/patches/7130C553.pnach create mode 100644 bin/patches/71584BAC.pnach create mode 100644 bin/patches/722BBD62.pnach create mode 100644 bin/patches/7377BC6F.pnach create mode 100644 bin/patches/763D3BF9.pnach create mode 100644 bin/patches/78168525.pnach create mode 100644 bin/patches/789D6B71.pnach create mode 100644 bin/patches/78E20421.pnach create mode 100644 bin/patches/78FFA39F.pnach create mode 100644 bin/patches/7ABDBB5E.pnach create mode 100644 bin/patches/7BA0128E.pnach create mode 100644 bin/patches/7CD1CDCD.pnach create mode 100644 bin/patches/7D8F539A.pnach create mode 100644 bin/patches/7FD7A1B9.pnach create mode 100644 bin/patches/83261085.pnach create mode 100644 bin/patches/83584608.pnach create mode 100644 bin/patches/83D0CE43.pnach create mode 100644 bin/patches/844B58EE.pnach create mode 100644 bin/patches/85AE91B3.pnach create mode 100644 bin/patches/85E92C92.pnach create mode 100644 bin/patches/8BC79F96.pnach create mode 100644 bin/patches/8BC95883.pnach create mode 100644 bin/patches/8BE3D7B2.pnach create mode 100644 bin/patches/8DC64680.pnach create mode 100644 bin/patches/8FDE8E16.pnach create mode 100644 bin/patches/93223BE4.pnach create mode 100644 bin/patches/934F9081.pnach create mode 100644 bin/patches/941BB7D9.pnach create mode 100644 bin/patches/94C56923.pnach create mode 100644 bin/patches/950241D3.pnach create mode 100644 bin/patches/951555A0.pnach create mode 100644 bin/patches/95BB1901.pnach create mode 100644 bin/patches/96B2F56D.pnach create mode 100644 bin/patches/96B76E56.pnach create mode 100644 bin/patches/96C20D6F.pnach create mode 100644 bin/patches/9AAC5309.pnach create mode 100644 bin/patches/9AAC530D.pnach create mode 100644 bin/patches/9AC65D6A.pnach create mode 100644 bin/patches/9B1EE9EB.pnach create mode 100644 bin/patches/9BE3F92D.pnach create mode 100644 bin/patches/9D6F46F0.pnach create mode 100644 bin/patches/A029B109.pnach create mode 100644 bin/patches/A1B752C7.pnach create mode 100644 bin/patches/A36CFF6C.pnach create mode 100644 bin/patches/A39517AB.pnach create mode 100644 bin/patches/A3ACF3C7.pnach create mode 100644 bin/patches/A4E2C043.pnach create mode 100644 bin/patches/A5BF36A8.pnach create mode 100644 bin/patches/A63C896C.pnach create mode 100644 bin/patches/A719D130.pnach create mode 100644 bin/patches/A74F99CD.pnach create mode 100644 bin/patches/A7A2F7C5.pnach create mode 100644 bin/patches/A88ACA28.pnach create mode 100644 bin/patches/A929A697.pnach create mode 100644 bin/patches/A9759015.pnach create mode 100644 bin/patches/AC7E88D9.pnach create mode 100644 bin/patches/ACB1989A.pnach create mode 100644 bin/patches/AD9D2B54.pnach create mode 100644 bin/patches/ADAA1256.pnach create mode 100644 bin/patches/AE0E098F.pnach create mode 100644 bin/patches/AE3EAA05.pnach create mode 100644 bin/patches/AE9EB9A0.pnach create mode 100644 bin/patches/AEDAEE99.pnach create mode 100644 bin/patches/AFAC88EF.pnach create mode 100644 bin/patches/B0AE1898.pnach create mode 100644 bin/patches/B1BE3E51.pnach create mode 100644 bin/patches/B234036E.pnach create mode 100644 bin/patches/B2BDE9F3.pnach create mode 100644 bin/patches/B338676A.pnach create mode 100644 bin/patches/B34DA141.pnach create mode 100644 bin/patches/B36EE21E.pnach create mode 100644 bin/patches/B590CE04.pnach create mode 100644 bin/patches/B82E4C4B.pnach create mode 100644 bin/patches/B99379B7.pnach create mode 100644 bin/patches/BB3D833A.pnach create mode 100644 bin/patches/BD3DBCF9.pnach create mode 100644 bin/patches/BF5D9AEC.pnach create mode 100644 bin/patches/C04FB5FD.pnach create mode 100644 bin/patches/C1625F14.pnach create mode 100644 bin/patches/C1767D64.pnach create mode 100644 bin/patches/C1B141D6.pnach create mode 100644 bin/patches/C220951A.pnach create mode 100644 bin/patches/C3D28EB9.pnach create mode 100644 bin/patches/C4467D30.pnach create mode 100644 bin/patches/C488EC04.pnach create mode 100644 bin/patches/C4A60986.pnach create mode 100644 bin/patches/C502AD6E.pnach create mode 100644 bin/patches/C5DEFEA0.pnach create mode 100644 bin/patches/C9246E9C.pnach create mode 100644 bin/patches/C9C145BF.pnach create mode 100644 bin/patches/CA295E61.pnach create mode 100644 bin/patches/CA6243B9.pnach create mode 100644 bin/patches/CB4EBD11.pnach create mode 100644 bin/patches/CBBC2E7F.pnach create mode 100644 bin/patches/CC4B9CDE.pnach create mode 100644 bin/patches/CC6AA742.pnach create mode 100644 bin/patches/CDE7C999.pnach create mode 100644 bin/patches/CF11CD83.pnach create mode 100644 bin/patches/CFB873AD.pnach create mode 100644 bin/patches/D03BEF2A.pnach create mode 100644 bin/patches/D08648B6.pnach create mode 100644 bin/patches/D0E17D26.pnach create mode 100644 bin/patches/D1ACD489.pnach create mode 100644 bin/patches/D4781770.pnach create mode 100644 bin/patches/D48A92E1.pnach create mode 100644 bin/patches/D4FB6049.pnach create mode 100644 bin/patches/D79F697A.pnach create mode 100644 bin/patches/DAC14B26.pnach create mode 100644 bin/patches/DB719F5C.pnach create mode 100644 bin/patches/DC85FC8F.pnach create mode 100644 bin/patches/DCC4EEEA.pnach create mode 100644 bin/patches/DDA2FA6A.pnach create mode 100644 bin/patches/E0127F2D.pnach create mode 100644 bin/patches/E0426FC6.pnach create mode 100644 bin/patches/E0DADD1A.pnach create mode 100644 bin/patches/E138094A.pnach create mode 100644 bin/patches/E1C5F607.pnach create mode 100644 bin/patches/E2F1DB6B.pnach create mode 100644 bin/patches/E4A275B2.pnach create mode 100644 bin/patches/E677B8F1.pnach create mode 100644 bin/patches/E7A35274.pnach create mode 100644 bin/patches/E906EA37.pnach create mode 100644 bin/patches/EAD76247.pnach create mode 100644 bin/patches/EADE437E.pnach create mode 100644 bin/patches/EDD7E0FF.pnach create mode 100644 bin/patches/EE838B5C.pnach create mode 100644 bin/patches/EEC3B310.pnach create mode 100644 bin/patches/EF5B6AAD.pnach create mode 100644 bin/patches/EF9E43EF.pnach create mode 100644 bin/patches/F1370E83.pnach create mode 100644 bin/patches/F22CDDAF.pnach create mode 100644 bin/patches/F4992CC1.pnach create mode 100644 bin/patches/F52FB2BE.pnach create mode 100644 bin/patches/F56C7948.pnach create mode 100644 bin/patches/F5C7B45F.pnach create mode 100644 bin/patches/F6DC728D.pnach create mode 100644 bin/patches/F758234F.pnach create mode 100644 bin/patches/F9E575D0.pnach create mode 100644 bin/patches/FAC64195.pnach create mode 100644 bin/patches/FB0E6D72.pnach create mode 100644 bin/patches/FC618D82.pnach create mode 100644 bin/patches/FEA030CB.pnach create mode 100644 bin/patches/FF920E90.pnach create mode 100644 bin/patches/default.xml create mode 100644 branches/pcsx2_0.9.1/CDVD.c create mode 100644 branches/pcsx2_0.9.1/CDVD.h create mode 100644 branches/pcsx2_0.9.1/CDVDiso.c create mode 100644 branches/pcsx2_0.9.1/CDVDiso.h create mode 100644 branches/pcsx2_0.9.1/CDVDisodrv.c create mode 100644 branches/pcsx2_0.9.1/CDVDisodrv.h create mode 100644 branches/pcsx2_0.9.1/CDVDlib.h create mode 100644 branches/pcsx2_0.9.1/COP0.c create mode 100644 branches/pcsx2_0.9.1/COP0.h create mode 100644 branches/pcsx2_0.9.1/Cache.c create mode 100644 branches/pcsx2_0.9.1/Cache.h create mode 100644 branches/pcsx2_0.9.1/CdRom.c create mode 100644 branches/pcsx2_0.9.1/CdRom.h create mode 100644 branches/pcsx2_0.9.1/Common.h create mode 100644 branches/pcsx2_0.9.1/Counters.c create mode 100644 branches/pcsx2_0.9.1/Counters.h create mode 100644 branches/pcsx2_0.9.1/DebugTools/Debug.h create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisASM.h create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisR3000A.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisR3000asm.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisR5900.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisR5900asm.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisVU0Micro.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisVU1Micro.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisVUmicro.h create mode 100644 branches/pcsx2_0.9.1/DebugTools/DisVUops.h create mode 100644 branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.c create mode 100644 branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.h create mode 100644 branches/pcsx2_0.9.1/Decode_XA.c create mode 100644 branches/pcsx2_0.9.1/Decode_XA.h create mode 100644 branches/pcsx2_0.9.1/Docs/BetaTesters.txt create mode 100644 branches/pcsx2_0.9.1/Docs/ChangeLog.txt create mode 100644 branches/pcsx2_0.9.1/Docs/License.txt create mode 100644 branches/pcsx2_0.9.1/Docs/PS2Edefs.txt create mode 100644 branches/pcsx2_0.9.1/Docs/Readme.txt create mode 100644 branches/pcsx2_0.9.1/Docs/RemoteDebugging.txt create mode 100644 branches/pcsx2_0.9.1/Docs/RunCDVD.txt create mode 100644 branches/pcsx2_0.9.1/Docs/ToDo.txt create mode 100644 branches/pcsx2_0.9.1/Docs/Translating.txt create mode 100644 branches/pcsx2_0.9.1/Docs/What_Is_Host.txt create mode 100644 branches/pcsx2_0.9.1/Docs/WhatsNew.txt create mode 100644 branches/pcsx2_0.9.1/Docs/devblog.txt create mode 100644 branches/pcsx2_0.9.1/Docs/efpchangesv0.9linux.txt create mode 100644 branches/pcsx2_0.9.1/Docs/pcsx2_faq.txt create mode 100644 branches/pcsx2_0.9.1/Docs/specs.tex create mode 100644 branches/pcsx2_0.9.1/Docs/threads.txt create mode 100644 branches/pcsx2_0.9.1/EEregs.h create mode 100644 branches/pcsx2_0.9.1/Elfheader.c create mode 100644 branches/pcsx2_0.9.1/Elfheader.h create mode 100644 branches/pcsx2_0.9.1/FPU.c create mode 100644 branches/pcsx2_0.9.1/FPU2.cpp create mode 100644 branches/pcsx2_0.9.1/FiFo.c create mode 100644 branches/pcsx2_0.9.1/GS.c create mode 100644 branches/pcsx2_0.9.1/GS.h create mode 100644 branches/pcsx2_0.9.1/Gte.c create mode 100644 branches/pcsx2_0.9.1/Gte.h create mode 100644 branches/pcsx2_0.9.1/Hw.c create mode 100644 branches/pcsx2_0.9.1/Hw.h create mode 100644 branches/pcsx2_0.9.1/IPU/IPU.c create mode 100644 branches/pcsx2_0.9.1/IPU/IPU.h create mode 100644 branches/pcsx2_0.9.1/IPU/idct_mmx.obj create mode 100644 branches/pcsx2_0.9.1/IPU/mpeg2lib/Idct.c create mode 100644 branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.c create mode 100644 branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.h create mode 100644 branches/pcsx2_0.9.1/IPU/mpeg2lib/Vlc.h create mode 100644 branches/pcsx2_0.9.1/IPU/yuv2rgb.c create mode 100644 branches/pcsx2_0.9.1/IPU/yuv2rgb.h create mode 100644 branches/pcsx2_0.9.1/InterTables.c create mode 100644 branches/pcsx2_0.9.1/InterTables.h create mode 100644 branches/pcsx2_0.9.1/Interpreter.c create mode 100644 branches/pcsx2_0.9.1/Linux/.pixmaps/pcsxAbout.xpm create mode 100644 branches/pcsx2_0.9.1/Linux/Config.c create mode 100644 branches/pcsx2_0.9.1/Linux/GladeCalls.c create mode 100644 branches/pcsx2_0.9.1/Linux/GladeCalls.h create mode 100644 branches/pcsx2_0.9.1/Linux/GladeFuncs.c create mode 100644 branches/pcsx2_0.9.1/Linux/GladeFuncs.h create mode 100644 branches/pcsx2_0.9.1/Linux/GladeGui.c create mode 100644 branches/pcsx2_0.9.1/Linux/GladeGui.h create mode 100644 branches/pcsx2_0.9.1/Linux/GtkGui.c create mode 100644 branches/pcsx2_0.9.1/Linux/Linux.h create mode 100644 branches/pcsx2_0.9.1/Linux/LnxMain.c create mode 100644 branches/pcsx2_0.9.1/Linux/Makefile create mode 100644 branches/pcsx2_0.9.1/Linux/Makefile.cfg.in create mode 100644 branches/pcsx2_0.9.1/Linux/configure.in create mode 100644 branches/pcsx2_0.9.1/Linux/pcsx2.glade create mode 100644 branches/pcsx2_0.9.1/MMI.c create mode 100644 branches/pcsx2_0.9.1/Mdec.c create mode 100644 branches/pcsx2_0.9.1/Mdec.h create mode 100644 branches/pcsx2_0.9.1/Memory.c create mode 100644 branches/pcsx2_0.9.1/Memory.h create mode 100644 branches/pcsx2_0.9.1/Misc.c create mode 100644 branches/pcsx2_0.9.1/Misc.h create mode 100644 branches/pcsx2_0.9.1/PS2Edefs.h create mode 100644 branches/pcsx2_0.9.1/PS2Etypes.h create mode 100644 branches/pcsx2_0.9.1/Patch.c create mode 100644 branches/pcsx2_0.9.1/Patch.h create mode 100644 branches/pcsx2_0.9.1/Plugins.c create mode 100644 branches/pcsx2_0.9.1/Plugins.h create mode 100644 branches/pcsx2_0.9.1/PsxBios.c create mode 100644 branches/pcsx2_0.9.1/PsxBios.h create mode 100644 branches/pcsx2_0.9.1/PsxBios2.h create mode 100644 branches/pcsx2_0.9.1/PsxCommon.h create mode 100644 branches/pcsx2_0.9.1/PsxCounters.c create mode 100644 branches/pcsx2_0.9.1/PsxCounters.h create mode 100644 branches/pcsx2_0.9.1/PsxDma.c create mode 100644 branches/pcsx2_0.9.1/PsxDma.h create mode 100644 branches/pcsx2_0.9.1/PsxGPU.c create mode 100644 branches/pcsx2_0.9.1/PsxGPU.h create mode 100644 branches/pcsx2_0.9.1/PsxHw.c create mode 100644 branches/pcsx2_0.9.1/PsxHw.h create mode 100644 branches/pcsx2_0.9.1/PsxInterpreter.c create mode 100644 branches/pcsx2_0.9.1/PsxMem.c create mode 100644 branches/pcsx2_0.9.1/PsxMem.h create mode 100644 branches/pcsx2_0.9.1/PsxSio2.c create mode 100644 branches/pcsx2_0.9.1/PsxSio2.h create mode 100644 branches/pcsx2_0.9.1/R3000A.c create mode 100644 branches/pcsx2_0.9.1/R3000A.h create mode 100644 branches/pcsx2_0.9.1/R5900.c create mode 100644 branches/pcsx2_0.9.1/R5900.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2.txt create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_dbgp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_dbgp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_dcmp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_dcmp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_drfp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_drfp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_iloadp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_iloadp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_netmp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_netmp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_ttyp.c create mode 100644 branches/pcsx2_0.9.1/RDebug/deci2_ttyp.h create mode 100644 branches/pcsx2_0.9.1/RDebug/iloadp.txt create mode 100644 branches/pcsx2_0.9.1/SPR.c create mode 100644 branches/pcsx2_0.9.1/SPR.h create mode 100644 branches/pcsx2_0.9.1/Sif.c create mode 100644 branches/pcsx2_0.9.1/Sif.h create mode 100644 branches/pcsx2_0.9.1/Sifcmd.h create mode 100644 branches/pcsx2_0.9.1/Sio.c create mode 100644 branches/pcsx2_0.9.1/Sio.h create mode 100644 branches/pcsx2_0.9.1/Stats.c create mode 100644 branches/pcsx2_0.9.1/Stats.h create mode 100644 branches/pcsx2_0.9.1/System.h create mode 100644 branches/pcsx2_0.9.1/VU.h create mode 100644 branches/pcsx2_0.9.1/VU0.c create mode 100644 branches/pcsx2_0.9.1/VU0.h create mode 100644 branches/pcsx2_0.9.1/VU0micro.c create mode 100644 branches/pcsx2_0.9.1/VU1micro.c create mode 100644 branches/pcsx2_0.9.1/VUflags.c create mode 100644 branches/pcsx2_0.9.1/VUflags.h create mode 100644 branches/pcsx2_0.9.1/VUmicro.h create mode 100644 branches/pcsx2_0.9.1/VUops.c create mode 100644 branches/pcsx2_0.9.1/VUops.h create mode 100644 branches/pcsx2_0.9.1/Vif.c create mode 100644 branches/pcsx2_0.9.1/Vif.h create mode 100644 branches/pcsx2_0.9.1/VifDma.c create mode 100644 branches/pcsx2_0.9.1/VifDma.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Arit.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Arit.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Branch.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Branch.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Jump.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Jump.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Move.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Move.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.h create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Shift.c create mode 100644 branches/pcsx2_0.9.1/ix86-32/iR5900Shift.h create mode 100644 branches/pcsx2_0.9.1/memcpy_amd.cpp create mode 100644 branches/pcsx2_0.9.1/pcl/pcl.c create mode 100644 branches/pcsx2_0.9.1/pcl/pcl.h create mode 100644 branches/pcsx2_0.9.1/pcl/pcl_config.h create mode 100644 branches/pcsx2_0.9.1/pcsxAbout.bmp create mode 100644 branches/pcsx2_0.9.1/windows/AboutDlg.c create mode 100644 branches/pcsx2_0.9.1/windows/AboutDlg.h create mode 100644 branches/pcsx2_0.9.1/windows/Cdrom02.ico create mode 100644 branches/pcsx2_0.9.1/windows/ConfigDlg.c create mode 100644 branches/pcsx2_0.9.1/windows/CpuDlg.c create mode 100644 branches/pcsx2_0.9.1/windows/DebugMemory.c create mode 100644 branches/pcsx2_0.9.1/windows/Debugger.c create mode 100644 branches/pcsx2_0.9.1/windows/Debugger.h create mode 100644 branches/pcsx2_0.9.1/windows/Debugreg.c create mode 100644 branches/pcsx2_0.9.1/windows/Makefile create mode 100644 branches/pcsx2_0.9.1/windows/McdsDlg.c create mode 100644 branches/pcsx2_0.9.1/windows/McdsDlg.h create mode 100644 branches/pcsx2_0.9.1/windows/PatchBrowser.c create mode 100644 branches/pcsx2_0.9.1/windows/RDebugger.c create mode 100644 branches/pcsx2_0.9.1/windows/RDebugger.h create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.sln create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.vcproj create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.sln create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.vcproj create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.sln create mode 100644 branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj create mode 100644 branches/pcsx2_0.9.1/windows/Win32.h create mode 100644 branches/pcsx2_0.9.1/windows/WinMain.c create mode 100644 branches/pcsx2_0.9.1/windows/afxresmw.h create mode 100644 branches/pcsx2_0.9.1/windows/ini.c create mode 100644 branches/pcsx2_0.9.1/windows/libs/gnu_gettext.lib create mode 100644 branches/pcsx2_0.9.1/windows/libs/libintlmsc.h create mode 100644 branches/pcsx2_0.9.1/windows/libs/pthread.h create mode 100644 branches/pcsx2_0.9.1/windows/libs/pthreadVC2.lib create mode 100644 branches/pcsx2_0.9.1/windows/libs/sched.h create mode 100644 branches/pcsx2_0.9.1/windows/libs/semaphore.h create mode 100644 branches/pcsx2_0.9.1/windows/mingw/Makefile.win create mode 100644 branches/pcsx2_0.9.1/windows/mingw/afxres.h create mode 100644 branches/pcsx2_0.9.1/windows/mingw/pcsx2.dev create mode 100644 branches/pcsx2_0.9.1/windows/mingw/pcsx2.layout create mode 100644 branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.h create mode 100644 branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.rc create mode 100644 branches/pcsx2_0.9.1/windows/pcsx2.rc create mode 100644 branches/pcsx2_0.9.1/windows/ps2_silver.bmp create mode 100644 branches/pcsx2_0.9.1/windows/pthreadVC2.lib create mode 100644 branches/pcsx2_0.9.1/windows/resource.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Arit.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Arit.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900AritImm.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900AritImm.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Branch.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Branch.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Jump.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Jump.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Move.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Move.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.h create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Shift.c create mode 100644 branches/pcsx2_0.9.1/x86-64/iR5900Shift.h create mode 100644 branches/pcsx2_0.9.1/x86/iCP0.c create mode 100644 branches/pcsx2_0.9.1/x86/iCP0.h create mode 100644 branches/pcsx2_0.9.1/x86/iCore.cpp create mode 100644 branches/pcsx2_0.9.1/x86/iCore.h create mode 100644 branches/pcsx2_0.9.1/x86/iFPU.c create mode 100644 branches/pcsx2_0.9.1/x86/iFPU.h create mode 100644 branches/pcsx2_0.9.1/x86/iMMI.c create mode 100644 branches/pcsx2_0.9.1/x86/iMMI.h create mode 100644 branches/pcsx2_0.9.1/x86/iR3000A.cpp create mode 100644 branches/pcsx2_0.9.1/x86/iR3000A.h create mode 100644 branches/pcsx2_0.9.1/x86/iR3000Atables.cpp create mode 100644 branches/pcsx2_0.9.1/x86/iR5900.c create mode 100644 branches/pcsx2_0.9.1/x86/iR5900.h create mode 100644 branches/pcsx2_0.9.1/x86/iVU0micro.c create mode 100644 branches/pcsx2_0.9.1/x86/iVU0micro.h create mode 100644 branches/pcsx2_0.9.1/x86/iVU1micro.c create mode 100644 branches/pcsx2_0.9.1/x86/iVU1micro.h create mode 100644 branches/pcsx2_0.9.1/x86/iVUmicro.c create mode 100644 branches/pcsx2_0.9.1/x86/iVUmicro.h create mode 100644 branches/pcsx2_0.9.1/x86/iVUops.h create mode 100644 branches/pcsx2_0.9.1/x86/iVUzerorec.cpp create mode 100644 branches/pcsx2_0.9.1/x86/iVUzerorec.h create mode 100644 branches/pcsx2_0.9.1/x86/ir5900tables.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86.h create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86_3dnow.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86_cpudetect.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86_fpu.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86_mmx.c create mode 100644 branches/pcsx2_0.9.1/x86/ix86/ix86_sse.c create mode 100644 branches/pcsx2_0.9.1/x86/recCOP2.c create mode 100644 branches/pcsx2_0.9.1/zlib/ChangeLog create mode 100644 branches/pcsx2_0.9.1/zlib/README create mode 100644 branches/pcsx2_0.9.1/zlib/adler32.c create mode 100644 branches/pcsx2_0.9.1/zlib/compress.c create mode 100644 branches/pcsx2_0.9.1/zlib/crc32.c create mode 100644 branches/pcsx2_0.9.1/zlib/crc32.h create mode 100644 branches/pcsx2_0.9.1/zlib/deflate.c create mode 100644 branches/pcsx2_0.9.1/zlib/deflate.h create mode 100644 branches/pcsx2_0.9.1/zlib/gzio.c create mode 100644 branches/pcsx2_0.9.1/zlib/infback.c create mode 100644 branches/pcsx2_0.9.1/zlib/inffast.c create mode 100644 branches/pcsx2_0.9.1/zlib/inffast.h create mode 100644 branches/pcsx2_0.9.1/zlib/inffixed.h create mode 100644 branches/pcsx2_0.9.1/zlib/inflate.c create mode 100644 branches/pcsx2_0.9.1/zlib/inflate.h create mode 100644 branches/pcsx2_0.9.1/zlib/inftrees.c create mode 100644 branches/pcsx2_0.9.1/zlib/inftrees.h create mode 100644 branches/pcsx2_0.9.1/zlib/trees.c create mode 100644 branches/pcsx2_0.9.1/zlib/trees.h create mode 100644 branches/pcsx2_0.9.1/zlib/uncompr.c create mode 100644 branches/pcsx2_0.9.1/zlib/zconf.h create mode 100644 branches/pcsx2_0.9.1/zlib/zlib.h create mode 100644 branches/pcsx2_0.9.1/zlib/zutil.c create mode 100644 branches/pcsx2_0.9.1/zlib/zutil.h create mode 100644 branches/pcsx2_0.9.2/CDVD.c create mode 100644 branches/pcsx2_0.9.2/CDVD.h create mode 100644 branches/pcsx2_0.9.2/CDVDiso.c create mode 100644 branches/pcsx2_0.9.2/CDVDiso.h create mode 100644 branches/pcsx2_0.9.2/CDVDisodrv.c create mode 100644 branches/pcsx2_0.9.2/CDVDisodrv.h create mode 100644 branches/pcsx2_0.9.2/CDVDlib.h create mode 100644 branches/pcsx2_0.9.2/COP0.c create mode 100644 branches/pcsx2_0.9.2/COP0.h create mode 100644 branches/pcsx2_0.9.2/Cache.c create mode 100644 branches/pcsx2_0.9.2/Cache.h create mode 100644 branches/pcsx2_0.9.2/CdRom.c create mode 100644 branches/pcsx2_0.9.2/CdRom.h create mode 100644 branches/pcsx2_0.9.2/Common.h create mode 100644 branches/pcsx2_0.9.2/Counters.c create mode 100644 branches/pcsx2_0.9.2/Counters.h create mode 100644 branches/pcsx2_0.9.2/DebugTools/Debug.h create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisASM.h create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisR3000A.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisR3000asm.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisR5900.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisR5900asm.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisVU0Micro.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisVU1Micro.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisVUmicro.h create mode 100644 branches/pcsx2_0.9.2/DebugTools/DisVUops.h create mode 100644 branches/pcsx2_0.9.2/DebugTools/Makefile.am create mode 100644 branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.c create mode 100644 branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.h create mode 100644 branches/pcsx2_0.9.2/Decode_XA.c create mode 100644 branches/pcsx2_0.9.2/Decode_XA.h create mode 100644 branches/pcsx2_0.9.2/Docs/BetaTesters.txt create mode 100644 branches/pcsx2_0.9.2/Docs/ChangeLog.txt create mode 100644 branches/pcsx2_0.9.2/Docs/License.txt create mode 100644 branches/pcsx2_0.9.2/Docs/PS2Edefs.txt create mode 100644 branches/pcsx2_0.9.2/Docs/Readme.txt create mode 100644 branches/pcsx2_0.9.2/Docs/RemoteDebugging.txt create mode 100644 branches/pcsx2_0.9.2/Docs/RunCDVD.txt create mode 100644 branches/pcsx2_0.9.2/Docs/ToDo.txt create mode 100644 branches/pcsx2_0.9.2/Docs/Translating.txt create mode 100644 branches/pcsx2_0.9.2/Docs/What_Is_Host.txt create mode 100644 branches/pcsx2_0.9.2/Docs/WhatsNew.txt create mode 100644 branches/pcsx2_0.9.2/Docs/devblog.txt create mode 100644 branches/pcsx2_0.9.2/Docs/efpchangesv0.9linux.txt create mode 100644 branches/pcsx2_0.9.2/Docs/pcsx2_faq.txt create mode 100644 branches/pcsx2_0.9.2/Docs/specs.tex create mode 100644 branches/pcsx2_0.9.2/Docs/threads.txt create mode 100644 branches/pcsx2_0.9.2/EEregs.h create mode 100644 branches/pcsx2_0.9.2/Elfheader.c create mode 100644 branches/pcsx2_0.9.2/Elfheader.h create mode 100644 branches/pcsx2_0.9.2/FPU.c create mode 100644 branches/pcsx2_0.9.2/FPU2.cpp create mode 100644 branches/pcsx2_0.9.2/FiFo.c create mode 100644 branches/pcsx2_0.9.2/GS.cpp create mode 100644 branches/pcsx2_0.9.2/GS.h create mode 100644 branches/pcsx2_0.9.2/Gte.h create mode 100644 branches/pcsx2_0.9.2/Hw.c create mode 100644 branches/pcsx2_0.9.2/Hw.h create mode 100644 branches/pcsx2_0.9.2/INSTALL.txt create mode 100644 branches/pcsx2_0.9.2/IPU/IPU.c create mode 100644 branches/pcsx2_0.9.2/IPU/IPU.h create mode 100644 branches/pcsx2_0.9.2/IPU/Makefile.am create mode 100644 branches/pcsx2_0.9.2/IPU/idct_mmx.obj create mode 100644 branches/pcsx2_0.9.2/IPU/mpeg2lib/Idct.c create mode 100644 branches/pcsx2_0.9.2/IPU/mpeg2lib/Makefile.am create mode 100644 branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.c create mode 100644 branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.h create mode 100644 branches/pcsx2_0.9.2/IPU/mpeg2lib/Vlc.h create mode 100644 branches/pcsx2_0.9.2/IPU/yuv2rgb.asm create mode 100644 branches/pcsx2_0.9.2/IPU/yuv2rgb.c create mode 100644 branches/pcsx2_0.9.2/IPU/yuv2rgb.h create mode 100644 branches/pcsx2_0.9.2/InterTables.c create mode 100644 branches/pcsx2_0.9.2/InterTables.h create mode 100644 branches/pcsx2_0.9.2/Interpreter.c create mode 100644 branches/pcsx2_0.9.2/Linux/.pixmaps/pcsxAbout.xpm create mode 100644 branches/pcsx2_0.9.2/Linux/Config.c create mode 100644 branches/pcsx2_0.9.2/Linux/GladeCalls.c create mode 100644 branches/pcsx2_0.9.2/Linux/GladeCalls.h create mode 100644 branches/pcsx2_0.9.2/Linux/GladeFuncs.c create mode 100644 branches/pcsx2_0.9.2/Linux/GladeFuncs.h create mode 100644 branches/pcsx2_0.9.2/Linux/GladeGui.c create mode 100644 branches/pcsx2_0.9.2/Linux/GladeGui.h create mode 100644 branches/pcsx2_0.9.2/Linux/GtkGui.c create mode 100644 branches/pcsx2_0.9.2/Linux/Linux.h create mode 100644 branches/pcsx2_0.9.2/Linux/LnxMain.c create mode 100644 branches/pcsx2_0.9.2/Linux/Makefile.am create mode 100644 branches/pcsx2_0.9.2/MMI.c create mode 100644 branches/pcsx2_0.9.2/Makefile.am create mode 100644 branches/pcsx2_0.9.2/Mdec.c create mode 100644 branches/pcsx2_0.9.2/Mdec.h create mode 100644 branches/pcsx2_0.9.2/Memory.c create mode 100644 branches/pcsx2_0.9.2/Memory.h create mode 100644 branches/pcsx2_0.9.2/Misc.c create mode 100644 branches/pcsx2_0.9.2/Misc.h create mode 100644 branches/pcsx2_0.9.2/PS2Edefs.h create mode 100644 branches/pcsx2_0.9.2/PS2Etypes.h create mode 100644 branches/pcsx2_0.9.2/Patch.c create mode 100644 branches/pcsx2_0.9.2/Patch.h create mode 100644 branches/pcsx2_0.9.2/Plugins.c create mode 100644 branches/pcsx2_0.9.2/Plugins.h create mode 100644 branches/pcsx2_0.9.2/PsxBios.c create mode 100644 branches/pcsx2_0.9.2/PsxBios.h create mode 100644 branches/pcsx2_0.9.2/PsxBios2.h create mode 100644 branches/pcsx2_0.9.2/PsxCommon.h create mode 100644 branches/pcsx2_0.9.2/PsxCounters.c create mode 100644 branches/pcsx2_0.9.2/PsxCounters.h create mode 100644 branches/pcsx2_0.9.2/PsxDma.c create mode 100644 branches/pcsx2_0.9.2/PsxDma.h create mode 100644 branches/pcsx2_0.9.2/PsxGPU.c create mode 100644 branches/pcsx2_0.9.2/PsxGPU.h create mode 100644 branches/pcsx2_0.9.2/PsxHw.c create mode 100644 branches/pcsx2_0.9.2/PsxHw.h create mode 100644 branches/pcsx2_0.9.2/PsxInterpreter.c create mode 100644 branches/pcsx2_0.9.2/PsxMem.c create mode 100644 branches/pcsx2_0.9.2/PsxMem.h create mode 100644 branches/pcsx2_0.9.2/PsxSio2.c create mode 100644 branches/pcsx2_0.9.2/PsxSio2.h create mode 100644 branches/pcsx2_0.9.2/R3000A.c create mode 100644 branches/pcsx2_0.9.2/R3000A.h create mode 100644 branches/pcsx2_0.9.2/R5900.c create mode 100644 branches/pcsx2_0.9.2/R5900.h create mode 100644 branches/pcsx2_0.9.2/RDebug/Makefile.am create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2.txt create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_dbgp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_dbgp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_dcmp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_dcmp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_drfp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_drfp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_iloadp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_iloadp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_netmp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_netmp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_ttyp.c create mode 100644 branches/pcsx2_0.9.2/RDebug/deci2_ttyp.h create mode 100644 branches/pcsx2_0.9.2/RDebug/iloadp.txt create mode 100644 branches/pcsx2_0.9.2/SPR.c create mode 100644 branches/pcsx2_0.9.2/SPR.h create mode 100644 branches/pcsx2_0.9.2/Sif.c create mode 100644 branches/pcsx2_0.9.2/Sif.h create mode 100644 branches/pcsx2_0.9.2/Sifcmd.h create mode 100644 branches/pcsx2_0.9.2/Sio.c create mode 100644 branches/pcsx2_0.9.2/Sio.h create mode 100644 branches/pcsx2_0.9.2/Stats.c create mode 100644 branches/pcsx2_0.9.2/Stats.h create mode 100644 branches/pcsx2_0.9.2/System.h create mode 100644 branches/pcsx2_0.9.2/VU.h create mode 100644 branches/pcsx2_0.9.2/VU0.c create mode 100644 branches/pcsx2_0.9.2/VU0.h create mode 100644 branches/pcsx2_0.9.2/VU0micro.c create mode 100644 branches/pcsx2_0.9.2/VU1micro.c create mode 100644 branches/pcsx2_0.9.2/VUflags.c create mode 100644 branches/pcsx2_0.9.2/VUflags.h create mode 100644 branches/pcsx2_0.9.2/VUmicro.h create mode 100644 branches/pcsx2_0.9.2/VUops.c create mode 100644 branches/pcsx2_0.9.2/VUops.h create mode 100644 branches/pcsx2_0.9.2/Vif.c create mode 100644 branches/pcsx2_0.9.2/Vif.h create mode 100644 branches/pcsx2_0.9.2/VifDma.c create mode 100644 branches/pcsx2_0.9.2/VifDma.h create mode 100644 branches/pcsx2_0.9.2/cheatscpp.h create mode 100644 branches/pcsx2_0.9.2/configure.ac create mode 100644 branches/pcsx2_0.9.2/depcomp create mode 100644 branches/pcsx2_0.9.2/install-sh create mode 100644 branches/pcsx2_0.9.2/memcpy_amd.cpp create mode 100644 branches/pcsx2_0.9.2/missing create mode 100644 branches/pcsx2_0.9.2/mkinstalldirs create mode 100644 branches/pcsx2_0.9.2/pcl/Makefile.am create mode 100644 branches/pcsx2_0.9.2/pcl/pcl.c create mode 100644 branches/pcsx2_0.9.2/pcl/pcl.h create mode 100644 branches/pcsx2_0.9.2/pcl/pcl_config.h create mode 100644 branches/pcsx2_0.9.2/pcsxAbout.bmp create mode 100644 branches/pcsx2_0.9.2/tinyxml/Makefile.am create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinystr.cpp create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinystr.h create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinyxml.cpp create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinyxml.h create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinyxmlerror.cpp create mode 100644 branches/pcsx2_0.9.2/tinyxml/tinyxmlparser.cpp create mode 100644 branches/pcsx2_0.9.2/tinyxml/xmlpatchloader.cpp create mode 100644 branches/pcsx2_0.9.2/windows/AboutDlg.c create mode 100644 branches/pcsx2_0.9.2/windows/AboutDlg.h create mode 100644 branches/pcsx2_0.9.2/windows/Cdrom02.ico create mode 100644 branches/pcsx2_0.9.2/windows/ConfigDlg.c create mode 100644 branches/pcsx2_0.9.2/windows/CpuDlg.c create mode 100644 branches/pcsx2_0.9.2/windows/DebugMemory.c create mode 100644 branches/pcsx2_0.9.2/windows/Debugger.c create mode 100644 branches/pcsx2_0.9.2/windows/Debugger.h create mode 100644 branches/pcsx2_0.9.2/windows/Debugreg.c create mode 100644 branches/pcsx2_0.9.2/windows/McdsDlg.c create mode 100644 branches/pcsx2_0.9.2/windows/McdsDlg.h create mode 100644 branches/pcsx2_0.9.2/windows/PatchBrowser.c create mode 100644 branches/pcsx2_0.9.2/windows/RDebugger.c create mode 100644 branches/pcsx2_0.9.2/windows/RDebugger.h create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.sln create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.vcproj create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.sln create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.vcproj create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.sln create mode 100644 branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj create mode 100644 branches/pcsx2_0.9.2/windows/Win32.h create mode 100644 branches/pcsx2_0.9.2/windows/WinMain.c create mode 100644 branches/pcsx2_0.9.2/windows/afxresmw.h create mode 100644 branches/pcsx2_0.9.2/windows/cheats/browser.cpp create mode 100644 branches/pcsx2_0.9.2/windows/cheats/cheats.cpp create mode 100644 branches/pcsx2_0.9.2/windows/cheats/cheats.h create mode 100644 branches/pcsx2_0.9.2/windows/ini.c create mode 100644 branches/pcsx2_0.9.2/windows/libs/gnu_gettext.lib create mode 100644 branches/pcsx2_0.9.2/windows/libs/libintlmsc.h create mode 100644 branches/pcsx2_0.9.2/windows/libs/pthread.h create mode 100644 branches/pcsx2_0.9.2/windows/libs/pthreadVC2.lib create mode 100644 branches/pcsx2_0.9.2/windows/libs/sched.h create mode 100644 branches/pcsx2_0.9.2/windows/libs/semaphore.h create mode 100644 branches/pcsx2_0.9.2/windows/mingw/Makefile.win create mode 100644 branches/pcsx2_0.9.2/windows/mingw/afxres.h create mode 100644 branches/pcsx2_0.9.2/windows/mingw/pcsx2.dev create mode 100644 branches/pcsx2_0.9.2/windows/mingw/pcsx2.layout create mode 100644 branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.h create mode 100644 branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.rc create mode 100644 branches/pcsx2_0.9.2/windows/pcsx2.rc create mode 100644 branches/pcsx2_0.9.2/windows/ps2_silver.bmp create mode 100644 branches/pcsx2_0.9.2/windows/pthreadVC2.lib create mode 100644 branches/pcsx2_0.9.2/windows/resource.h create mode 100644 branches/pcsx2_0.9.2/x86/Makefile.am create mode 100644 branches/pcsx2_0.9.2/x86/iCP0.c create mode 100644 branches/pcsx2_0.9.2/x86/iCP0.h create mode 100644 branches/pcsx2_0.9.2/x86/iCore.cpp create mode 100644 branches/pcsx2_0.9.2/x86/iCore.h create mode 100644 branches/pcsx2_0.9.2/x86/iFPU.c create mode 100644 branches/pcsx2_0.9.2/x86/iFPU.h create mode 100644 branches/pcsx2_0.9.2/x86/iMMI.c create mode 100644 branches/pcsx2_0.9.2/x86/iMMI.h create mode 100644 branches/pcsx2_0.9.2/x86/iR3000A.cpp create mode 100644 branches/pcsx2_0.9.2/x86/iR3000A.h create mode 100644 branches/pcsx2_0.9.2/x86/iR3000Atables.cpp create mode 100644 branches/pcsx2_0.9.2/x86/iR5900-32.S create mode 100644 branches/pcsx2_0.9.2/x86/iR5900.c create mode 100644 branches/pcsx2_0.9.2/x86/iR5900.h create mode 100644 branches/pcsx2_0.9.2/x86/iVU0micro.c create mode 100644 branches/pcsx2_0.9.2/x86/iVU0micro.h create mode 100644 branches/pcsx2_0.9.2/x86/iVU1micro.c create mode 100644 branches/pcsx2_0.9.2/x86/iVU1micro.h create mode 100644 branches/pcsx2_0.9.2/x86/iVUmicro.c create mode 100644 branches/pcsx2_0.9.2/x86/iVUmicro.h create mode 100644 branches/pcsx2_0.9.2/x86/iVUops.h create mode 100644 branches/pcsx2_0.9.2/x86/iVUzerorec.cpp create mode 100644 branches/pcsx2_0.9.2/x86/iVUzerorec.h create mode 100644 branches/pcsx2_0.9.2/x86/iVif.S create mode 100644 branches/pcsx2_0.9.2/x86/iVif.cpp create mode 100644 branches/pcsx2_0.9.2/x86/ir5900tables.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/Makefile.am create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/Makefile.am create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86/Makefile.am create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86.h create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86_3dnow.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86_cpudetect.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86_fpu.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86_mmx.c create mode 100644 branches/pcsx2_0.9.2/x86/ix86/ix86_sse.c create mode 100644 branches/pcsx2_0.9.2/x86/recCOP2.c create mode 100644 branches/pcsx2_0.9.2/zlib/ChangeLog create mode 100644 branches/pcsx2_0.9.2/zlib/Makefile.am create mode 100644 branches/pcsx2_0.9.2/zlib/README create mode 100644 branches/pcsx2_0.9.2/zlib/adler32.c create mode 100644 branches/pcsx2_0.9.2/zlib/compress.c create mode 100644 branches/pcsx2_0.9.2/zlib/crc32.c create mode 100644 branches/pcsx2_0.9.2/zlib/crc32.h create mode 100644 branches/pcsx2_0.9.2/zlib/deflate.c create mode 100644 branches/pcsx2_0.9.2/zlib/deflate.h create mode 100644 branches/pcsx2_0.9.2/zlib/gzio.c create mode 100644 branches/pcsx2_0.9.2/zlib/infback.c create mode 100644 branches/pcsx2_0.9.2/zlib/inffast.c create mode 100644 branches/pcsx2_0.9.2/zlib/inffast.h create mode 100644 branches/pcsx2_0.9.2/zlib/inffixed.h create mode 100644 branches/pcsx2_0.9.2/zlib/inflate.c create mode 100644 branches/pcsx2_0.9.2/zlib/inflate.h create mode 100644 branches/pcsx2_0.9.2/zlib/inftrees.c create mode 100644 branches/pcsx2_0.9.2/zlib/inftrees.h create mode 100644 branches/pcsx2_0.9.2/zlib/trees.c create mode 100644 branches/pcsx2_0.9.2/zlib/trees.h create mode 100644 branches/pcsx2_0.9.2/zlib/uncompr.c create mode 100644 branches/pcsx2_0.9.2/zlib/zconf.h create mode 100644 branches/pcsx2_0.9.2/zlib/zlib.h create mode 100644 branches/pcsx2_0.9.2/zlib/zutil.c create mode 100644 branches/pcsx2_0.9.2/zlib/zutil.h create mode 100644 build.sh create mode 100644 pcsx2/CDVD.c create mode 100644 pcsx2/CDVD.h create mode 100644 pcsx2/CDVDiso.c create mode 100644 pcsx2/CDVDiso.h create mode 100644 pcsx2/CDVDisodrv.c create mode 100644 pcsx2/CDVDisodrv.h create mode 100644 pcsx2/CDVDlib.h create mode 100644 pcsx2/COP0.c create mode 100644 pcsx2/COP0.h create mode 100644 pcsx2/Cache.c create mode 100644 pcsx2/Cache.h create mode 100644 pcsx2/CdRom.c create mode 100644 pcsx2/CdRom.h create mode 100644 pcsx2/Common.h create mode 100644 pcsx2/Counters.c create mode 100644 pcsx2/Counters.h create mode 100644 pcsx2/DebugTools/Debug.h create mode 100644 pcsx2/DebugTools/DisASM.h create mode 100644 pcsx2/DebugTools/DisR3000A.c create mode 100644 pcsx2/DebugTools/DisR3000asm.c create mode 100644 pcsx2/DebugTools/DisR5900.c create mode 100644 pcsx2/DebugTools/DisR5900asm.c create mode 100644 pcsx2/DebugTools/DisVU0Micro.c create mode 100644 pcsx2/DebugTools/DisVU1Micro.c create mode 100644 pcsx2/DebugTools/DisVUmicro.h create mode 100644 pcsx2/DebugTools/DisVUops.h create mode 100644 pcsx2/DebugTools/Makefile.am create mode 100644 pcsx2/DebugTools/cpuopsDebug.c create mode 100644 pcsx2/DebugTools/cpuopsDebug.h create mode 100644 pcsx2/Decode_XA.c create mode 100644 pcsx2/Decode_XA.h create mode 100644 pcsx2/Docs/BetaTesters.txt create mode 100644 pcsx2/Docs/ChangeLog.txt create mode 100644 pcsx2/Docs/License.txt create mode 100644 pcsx2/Docs/PS2Edefs.txt create mode 100644 pcsx2/Docs/Readme.txt create mode 100644 pcsx2/Docs/RemoteDebugging.txt create mode 100644 pcsx2/Docs/RunCDVD.txt create mode 100644 pcsx2/Docs/Translating.txt create mode 100644 pcsx2/Docs/What_Is_Host.txt create mode 100644 pcsx2/Docs/WhatsNew.txt create mode 100644 pcsx2/Docs/devblog.txt create mode 100644 pcsx2/Docs/pcsx2_faq.txt create mode 100644 pcsx2/Docs/specs.tex create mode 100644 pcsx2/EEregs.h create mode 100644 pcsx2/Elfheader.c create mode 100644 pcsx2/Elfheader.h create mode 100644 pcsx2/FPU.c create mode 100644 pcsx2/FPU2.cpp create mode 100644 pcsx2/FiFo.c create mode 100644 pcsx2/GS.cpp create mode 100644 pcsx2/GS.h create mode 100644 pcsx2/Hw.c create mode 100644 pcsx2/Hw.h create mode 100644 pcsx2/IPU/IPU.c create mode 100644 pcsx2/IPU/IPU.h create mode 100644 pcsx2/IPU/Makefile.am create mode 100644 pcsx2/IPU/acoroutine.S create mode 100644 pcsx2/IPU/acoroutine.asm create mode 100644 pcsx2/IPU/coroutine.c create mode 100644 pcsx2/IPU/coroutine.h create mode 100644 pcsx2/IPU/idct_mmx.obj create mode 100644 pcsx2/IPU/mpeg2lib/Idct.c create mode 100644 pcsx2/IPU/mpeg2lib/Makefile.am create mode 100644 pcsx2/IPU/mpeg2lib/Mpeg.c create mode 100644 pcsx2/IPU/mpeg2lib/Mpeg.h create mode 100644 pcsx2/IPU/mpeg2lib/Vlc.h create mode 100644 pcsx2/IPU/yuv2rgb.asm create mode 100644 pcsx2/IPU/yuv2rgb.c create mode 100644 pcsx2/IPU/yuv2rgb.h create mode 100644 pcsx2/InterTables.c create mode 100644 pcsx2/InterTables.h create mode 100644 pcsx2/Interpreter.c create mode 100644 pcsx2/Linux/.pixmaps/pcsxAbout.xpm create mode 100644 pcsx2/Linux/Config.c create mode 100644 pcsx2/Linux/GtkGui.c create mode 100644 pcsx2/Linux/Linux.h create mode 100644 pcsx2/Linux/LnxMain.c create mode 100644 pcsx2/Linux/Makefile.am create mode 100644 pcsx2/Linux/buildgui.sh create mode 100644 pcsx2/Linux/callbacks.h create mode 100644 pcsx2/Linux/interface.c create mode 100644 pcsx2/Linux/interface.h create mode 100644 pcsx2/Linux/pcsx2.glade create mode 100644 pcsx2/Linux/support.c create mode 100644 pcsx2/Linux/support.h create mode 100644 pcsx2/MMI.c create mode 100644 pcsx2/Makefile.am create mode 100644 pcsx2/Mdec.c create mode 100644 pcsx2/Mdec.h create mode 100644 pcsx2/Memory.c create mode 100644 pcsx2/Memory.h create mode 100644 pcsx2/Misc.c create mode 100644 pcsx2/Misc.h create mode 100644 pcsx2/PS2Edefs.h create mode 100644 pcsx2/PS2Etypes.h create mode 100644 pcsx2/Patch.c create mode 100644 pcsx2/Patch.h create mode 100644 pcsx2/Plugins.c create mode 100644 pcsx2/Plugins.h create mode 100644 pcsx2/PsxBios.c create mode 100644 pcsx2/PsxBios.h create mode 100644 pcsx2/PsxBios2.h create mode 100644 pcsx2/PsxCommon.h create mode 100644 pcsx2/PsxCounters.c create mode 100644 pcsx2/PsxCounters.h create mode 100644 pcsx2/PsxDma.c create mode 100644 pcsx2/PsxDma.h create mode 100644 pcsx2/PsxHw.c create mode 100644 pcsx2/PsxHw.h create mode 100644 pcsx2/PsxInterpreter.c create mode 100644 pcsx2/PsxMem.c create mode 100644 pcsx2/PsxMem.h create mode 100644 pcsx2/PsxSio2.c create mode 100644 pcsx2/PsxSio2.h create mode 100644 pcsx2/R3000A.c create mode 100644 pcsx2/R3000A.h create mode 100644 pcsx2/R5900.c create mode 100644 pcsx2/R5900.h create mode 100644 pcsx2/RDebug/Makefile.am create mode 100644 pcsx2/RDebug/deci2.c create mode 100644 pcsx2/RDebug/deci2.h create mode 100644 pcsx2/RDebug/deci2.txt create mode 100644 pcsx2/RDebug/deci2_dbgp.c create mode 100644 pcsx2/RDebug/deci2_dbgp.h create mode 100644 pcsx2/RDebug/deci2_dcmp.c create mode 100644 pcsx2/RDebug/deci2_dcmp.h create mode 100644 pcsx2/RDebug/deci2_drfp.c create mode 100644 pcsx2/RDebug/deci2_drfp.h create mode 100644 pcsx2/RDebug/deci2_iloadp.c create mode 100644 pcsx2/RDebug/deci2_iloadp.h create mode 100644 pcsx2/RDebug/deci2_netmp.c create mode 100644 pcsx2/RDebug/deci2_netmp.h create mode 100644 pcsx2/RDebug/deci2_ttyp.c create mode 100644 pcsx2/RDebug/deci2_ttyp.h create mode 100644 pcsx2/RDebug/iloadp.txt create mode 100644 pcsx2/SPR.c create mode 100644 pcsx2/SPR.h create mode 100644 pcsx2/Sif.c create mode 100644 pcsx2/Sif.h create mode 100644 pcsx2/Sifcmd.h create mode 100644 pcsx2/Sio.c create mode 100644 pcsx2/Sio.h create mode 100644 pcsx2/Stats.c create mode 100644 pcsx2/Stats.h create mode 100644 pcsx2/System.h create mode 100644 pcsx2/VU.h create mode 100644 pcsx2/VU0.c create mode 100644 pcsx2/VU0.h create mode 100644 pcsx2/VU0micro.c create mode 100644 pcsx2/VU1micro.c create mode 100644 pcsx2/VUflags.c create mode 100644 pcsx2/VUflags.h create mode 100644 pcsx2/VUmicro.h create mode 100644 pcsx2/VUops.c create mode 100644 pcsx2/VUops.h create mode 100644 pcsx2/Vif.c create mode 100644 pcsx2/Vif.h create mode 100644 pcsx2/VifDma.c create mode 100644 pcsx2/VifDma.h create mode 100644 pcsx2/build.sh create mode 100644 pcsx2/cheatscpp.h create mode 100644 pcsx2/configure.ac create mode 100644 pcsx2/depcomp create mode 100644 pcsx2/install-sh create mode 100644 pcsx2/missing create mode 100644 pcsx2/mkinstalldirs create mode 100644 pcsx2/pcsxAbout.bmp create mode 100644 pcsx2/tinyxml/Makefile.am create mode 100644 pcsx2/tinyxml/tinystr.cpp create mode 100644 pcsx2/tinyxml/tinystr.h create mode 100644 pcsx2/tinyxml/tinyxml.cpp create mode 100644 pcsx2/tinyxml/tinyxml.h create mode 100644 pcsx2/tinyxml/tinyxmlerror.cpp create mode 100644 pcsx2/tinyxml/tinyxmlparser.cpp create mode 100644 pcsx2/windows/AboutDlg.c create mode 100644 pcsx2/windows/AboutDlg.h create mode 100644 pcsx2/windows/Cdrom02.ico create mode 100644 pcsx2/windows/ConfigDlg.c create mode 100644 pcsx2/windows/CpuDlg.c create mode 100644 pcsx2/windows/DebugMemory.c create mode 100644 pcsx2/windows/Debugger.c create mode 100644 pcsx2/windows/Debugger.h create mode 100644 pcsx2/windows/Debugreg.c create mode 100644 pcsx2/windows/McdsDlg.c create mode 100644 pcsx2/windows/McdsDlg.h create mode 100644 pcsx2/windows/PatchBrowser.c create mode 100644 pcsx2/windows/RDebugger.c create mode 100644 pcsx2/windows/RDebugger.h create mode 100644 pcsx2/windows/VCprojects/pcsx2_2003.sln create mode 100644 pcsx2/windows/VCprojects/pcsx2_2003.vcproj create mode 100644 pcsx2/windows/VCprojects/pcsx2_2005.sln create mode 100644 pcsx2/windows/VCprojects/pcsx2_2005.vcproj create mode 100644 pcsx2/windows/VCprojects/pcsx2_2005_x64.sln create mode 100644 pcsx2/windows/VCprojects/pcsx2_2005_x64.vcproj create mode 100644 pcsx2/windows/Win32.h create mode 100644 pcsx2/windows/WinMain.c create mode 100644 pcsx2/windows/afxresmw.h create mode 100644 pcsx2/windows/cheats/browser.cpp create mode 100644 pcsx2/windows/cheats/cheats.cpp create mode 100644 pcsx2/windows/cheats/cheats.h create mode 100644 pcsx2/windows/ini.c create mode 100644 pcsx2/windows/libs/gnu_gettext.lib create mode 100644 pcsx2/windows/libs/libintlmsc.h create mode 100644 pcsx2/windows/libs/pthread.h create mode 100644 pcsx2/windows/libs/pthreadVC2.lib create mode 100644 pcsx2/windows/libs/sched.h create mode 100644 pcsx2/windows/libs/semaphore.h create mode 100644 pcsx2/windows/mingw/Makefile.win create mode 100644 pcsx2/windows/mingw/afxres.h create mode 100644 pcsx2/windows/mingw/pcsx2.dev create mode 100644 pcsx2/windows/mingw/pcsx2.layout create mode 100644 pcsx2/windows/mingw/pcsx2_private.h create mode 100644 pcsx2/windows/mingw/pcsx2_private.rc create mode 100644 pcsx2/windows/pcsx2.rc create mode 100644 pcsx2/windows/ps2_silver.bmp create mode 100644 pcsx2/windows/pthreadVC2.lib create mode 100644 pcsx2/windows/resource.h create mode 100644 pcsx2/x86/Makefile.am create mode 100644 pcsx2/x86/README create mode 100644 pcsx2/x86/aR3000A.S create mode 100644 pcsx2/x86/aVUzerorec.S create mode 100644 pcsx2/x86/aVif.S create mode 100644 pcsx2/x86/aVif.asm create mode 100644 pcsx2/x86/fast_routines.S create mode 100644 pcsx2/x86/fast_routines.cpp create mode 100644 pcsx2/x86/iCOP2.c create mode 100644 pcsx2/x86/iCP0.c create mode 100644 pcsx2/x86/iCP0.h create mode 100644 pcsx2/x86/iCore.cpp create mode 100644 pcsx2/x86/iCore.h create mode 100644 pcsx2/x86/iFPU.c create mode 100644 pcsx2/x86/iFPU.h create mode 100644 pcsx2/x86/iGS.cpp create mode 100644 pcsx2/x86/iHw.c create mode 100644 pcsx2/x86/iMMI.c create mode 100644 pcsx2/x86/iMMI.h create mode 100644 pcsx2/x86/iPsxHw.c create mode 100644 pcsx2/x86/iPsxMem.c create mode 100644 pcsx2/x86/iR3000A.cpp create mode 100644 pcsx2/x86/iR3000A.h create mode 100644 pcsx2/x86/iR3000Atables.cpp create mode 100644 pcsx2/x86/iR5900.h create mode 100644 pcsx2/x86/iR5900Arit.h create mode 100644 pcsx2/x86/iR5900AritImm.h create mode 100644 pcsx2/x86/iR5900Branch.h create mode 100644 pcsx2/x86/iR5900Jump.h create mode 100644 pcsx2/x86/iR5900LoadStore.h create mode 100644 pcsx2/x86/iR5900Move.h create mode 100644 pcsx2/x86/iR5900MultDiv.h create mode 100644 pcsx2/x86/iR5900Shift.h create mode 100644 pcsx2/x86/iVU0micro.c create mode 100644 pcsx2/x86/iVU0micro.h create mode 100644 pcsx2/x86/iVU1micro.c create mode 100644 pcsx2/x86/iVU1micro.h create mode 100644 pcsx2/x86/iVUmicro.c create mode 100644 pcsx2/x86/iVUmicro.h create mode 100644 pcsx2/x86/iVUops.h create mode 100644 pcsx2/x86/iVUzerorec.cpp create mode 100644 pcsx2/x86/iVUzerorec.h create mode 100644 pcsx2/x86/iVif.cpp create mode 100644 pcsx2/x86/ir5900tables.c create mode 100644 pcsx2/x86/ix86-32/aR5900-32.S create mode 100644 pcsx2/x86/ix86-32/aVif_proc-32.asm create mode 100644 pcsx2/x86/ix86-32/iCore-32.cpp create mode 100644 pcsx2/x86/ix86-32/iR5900-32.c create mode 100644 pcsx2/x86/ix86-32/iR5900Arit.c create mode 100644 pcsx2/x86/ix86-32/iR5900AritImm.c create mode 100644 pcsx2/x86/ix86-32/iR5900Branch.c create mode 100644 pcsx2/x86/ix86-32/iR5900Jump.c create mode 100644 pcsx2/x86/ix86-32/iR5900LoadStore.c create mode 100644 pcsx2/x86/ix86-32/iR5900Move.c create mode 100644 pcsx2/x86/ix86-32/iR5900MultDiv.c create mode 100644 pcsx2/x86/ix86-32/iR5900Shift.c create mode 100644 pcsx2/x86/ix86-64/aR3000A-64.asm create mode 100644 pcsx2/x86/ix86-64/aR5900-64.S create mode 100644 pcsx2/x86/ix86-64/aR5900-64.asm create mode 100644 pcsx2/x86/ix86-64/aVUzerorec-64.asm create mode 100644 pcsx2/x86/ix86-64/aVif_proc-64.asm create mode 100644 pcsx2/x86/ix86-64/fast_routines-64.asm create mode 100644 pcsx2/x86/ix86-64/iCore-64.cpp create mode 100644 pcsx2/x86/ix86-64/iR5900-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900Arit-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900AritImm-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900Branch-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900Jump-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900LoadStore-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900Move-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900MultDiv-64.c create mode 100644 pcsx2/x86/ix86-64/iR5900Shift-64.c create mode 100644 pcsx2/x86/ix86/Makefile.am create mode 100644 pcsx2/x86/ix86/ix86.c create mode 100644 pcsx2/x86/ix86/ix86.h create mode 100644 pcsx2/x86/ix86/ix86_3dnow.c create mode 100644 pcsx2/x86/ix86/ix86_cpudetect.c create mode 100644 pcsx2/x86/ix86/ix86_fpu.c create mode 100644 pcsx2/x86/ix86/ix86_mmx.c create mode 100644 pcsx2/x86/ix86/ix86_sse.c create mode 100644 pcsx2/xmlpatchloader.cpp create mode 100644 pcsx2/zlib/ChangeLog create mode 100644 pcsx2/zlib/Makefile.am create mode 100644 pcsx2/zlib/README create mode 100644 pcsx2/zlib/adler32.c create mode 100644 pcsx2/zlib/compress.c create mode 100644 pcsx2/zlib/crc32.c create mode 100644 pcsx2/zlib/crc32.h create mode 100644 pcsx2/zlib/deflate.c create mode 100644 pcsx2/zlib/deflate.h create mode 100644 pcsx2/zlib/gzio.c create mode 100644 pcsx2/zlib/infback.c create mode 100644 pcsx2/zlib/inffast.c create mode 100644 pcsx2/zlib/inffast.h create mode 100644 pcsx2/zlib/inffixed.h create mode 100644 pcsx2/zlib/inflate.c create mode 100644 pcsx2/zlib/inflate.h create mode 100644 pcsx2/zlib/inftrees.c create mode 100644 pcsx2/zlib/inftrees.h create mode 100644 pcsx2/zlib/trees.c create mode 100644 pcsx2/zlib/trees.h create mode 100644 pcsx2/zlib/uncompr.c create mode 100644 pcsx2/zlib/zconf.h create mode 100644 pcsx2/zlib/zlib.h create mode 100644 pcsx2/zlib/zutil.c create mode 100644 pcsx2/zlib/zutil.h create mode 100644 plugins/build.sh create mode 100644 plugins/cdvd/CDVDbin/CDVDbin.dll create mode 100644 plugins/cdvd/CDVDbin/CDVDbin.ro.dll create mode 100644 plugins/cdvd/CDVDbin/CDVDbinA64.dll create mode 100644 plugins/cdvd/CDVDbin/readme.ps1.txt create mode 100644 plugins/cdvd/CDVDbin/readme.txt create mode 100644 plugins/cdvd/CDVDbin/src/CDVD.h create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.c create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.def create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.dsp create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.dsw create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.ncb create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.rc create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.sln create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.sln.old create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.suo create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.vcproj create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin.vcproj.old create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin_2003.sln create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin_2003.vcproj create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.sln create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.vcproj create mode 100644 plugins/cdvd/CDVDbin/src/CDVDbinro.rc create mode 100644 plugins/cdvd/CDVDbin/src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDbin/src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDbin/src/resource.h create mode 100644 plugins/cdvd/CDVDdraft/Src/AboutBox.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/AboutBox.h create mode 100644 plugins/cdvd/CDVDdraft/Src/Config.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/Config.h create mode 100644 plugins/cdvd/CDVDdraft/Src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDdraft/Src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDdraft/Src/ReadMe.txt create mode 100644 plugins/cdvd/CDVDdraft/Src/StdAfx.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/StdAfx.h create mode 100644 plugins/cdvd/CDVDdraft/Src/aspi.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/bitmap1.bmp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvd.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvd.h create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvdcompat.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvdcompat.h create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.aps create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.clw create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.def create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.dep create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.dsp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.dsw create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.h create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.opt create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.plg create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft.rc create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.sln create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.vcproj create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvdmisc.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/cdvdmisc.h create mode 100644 plugins/cdvd/CDVDdraft/Src/constants.h create mode 100644 plugins/cdvd/CDVDdraft/Src/ioctl.cpp create mode 100644 plugins/cdvd/CDVDdraft/Src/res/CVS/Entries create mode 100644 plugins/cdvd/CDVDdraft/Src/res/CVS/Entries.Extra create mode 100644 plugins/cdvd/CDVDdraft/Src/res/CVS/Repository create mode 100644 plugins/cdvd/CDVDdraft/Src/res/CVS/Root create mode 100644 plugins/cdvd/CDVDdraft/Src/res/cdvddraft.rc2 create mode 100644 plugins/cdvd/CDVDdraft/Src/resource.h create mode 100644 plugins/cdvd/CDVDdraft/Src/typedefs.h create mode 100644 plugins/cdvd/CDVDdraft/Src/winaspi/scsidefs.h create mode 100644 plugins/cdvd/CDVDdraft/Src/winaspi/wnaspi32.h create mode 100644 plugins/cdvd/CDVDdraft/cdvddraft.dll create mode 100644 plugins/cdvd/CDVDiso/ReadMe.txt create mode 100644 plugins/cdvd/CDVDiso/build.sh create mode 100644 plugins/cdvd/CDVDiso/src/CDVDiso.c create mode 100644 plugins/cdvd/CDVDiso/src/CDVDiso.h create mode 100644 plugins/cdvd/CDVDiso/src/Linux/CDVDiso.glade create mode 100644 plugins/cdvd/CDVDiso/src/Linux/Config.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/Config.h create mode 100644 plugins/cdvd/CDVDiso/src/Linux/Linux.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/Makefile create mode 100644 plugins/cdvd/CDVDiso/src/Linux/callbacks.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/callbacks.h create mode 100644 plugins/cdvd/CDVDiso/src/Linux/conf.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/interface.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/interface.h create mode 100644 plugins/cdvd/CDVDiso/src/Linux/support.c create mode 100644 plugins/cdvd/CDVDiso/src/Linux/support.h create mode 100644 plugins/cdvd/CDVDiso/src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDiso/src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.sln create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.vcproj create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.def create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsp create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsw create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.rc create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.sln create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso.vcproj create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.sln create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.vcproj create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.sln create mode 100644 plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.vcproj create mode 100644 plugins/cdvd/CDVDiso/src/Win32/Config.c create mode 100644 plugins/cdvd/CDVDiso/src/Win32/Config.h create mode 100644 plugins/cdvd/CDVDiso/src/Win32/Makefile create mode 100644 plugins/cdvd/CDVDiso/src/Win32/Win32.c create mode 100644 plugins/cdvd/CDVDiso/src/Win32/afxresmw.h create mode 100644 plugins/cdvd/CDVDiso/src/Win32/plugin.def create mode 100644 plugins/cdvd/CDVDiso/src/Win32/resource.h create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/LICENSE create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/README create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/blocksort.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/bzlib.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/bzlib.h create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/bzlib_private.h create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/compress.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/crctable.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/decompress.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/huffman.c create mode 100644 plugins/cdvd/CDVDiso/src/bzip2/randtable.c create mode 100644 plugins/cdvd/CDVDiso/src/libiso.c create mode 100644 plugins/cdvd/CDVDiso/src/libiso.h create mode 100644 plugins/cdvd/CDVDiso/src/mkiso/Makefile create mode 100644 plugins/cdvd/CDVDiso/src/mkiso/Makefile.mingw create mode 100644 plugins/cdvd/CDVDiso/src/mkiso/mkiso.c create mode 100644 plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsp create mode 100644 plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsw create mode 100644 plugins/cdvd/CDVDiso/src/zlib/ChangeLog create mode 100644 plugins/cdvd/CDVDiso/src/zlib/README create mode 100644 plugins/cdvd/CDVDiso/src/zlib/adler32.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/compress.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/crc32.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/crc32.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/deflate.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/deflate.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/gvmat32.obj create mode 100644 plugins/cdvd/CDVDiso/src/zlib/gvmat32c.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/gvmat64.obj create mode 100644 plugins/cdvd/CDVDiso/src/zlib/gzio.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/infback.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffas32.obj create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffas8664.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffast.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffast.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffasx64.obj create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inffixed.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inflate.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inflate.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inftrees.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/inftrees.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/trees.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/trees.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/uncompr.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/zconf.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/zlib.h create mode 100644 plugins/cdvd/CDVDiso/src/zlib/zutil.c create mode 100644 plugins/cdvd/CDVDiso/src/zlib/zutil.h create mode 100644 plugins/cdvd/CDVDisoEFP/ChangeLog.txt create mode 100644 plugins/cdvd/CDVDisoEFP/build.sh create mode 100644 plugins/cdvd/CDVDisoEFP/license.txt create mode 100644 plugins/cdvd/CDVDisoEFP/readme.txt create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/CD.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/CD.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/DVD.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/DVD.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/Makefile create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/comparisondummy.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/conf.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/conf.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/device.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/device.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/interface.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/interface.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/logfile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/logfile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.glade create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/CD.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/CD.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/DVD.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/DVD.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32 create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32.bak create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/conf.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/conf.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/device.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/device.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/logfile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/logfile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/make.bat create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/makeming.bat create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/plugin.def create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/screens.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/screens.rc create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/blockv2.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/blockv2.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/LICENSE create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/README create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/blocksort.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib_private.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/compress.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/crctable.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/decompress.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/huffman.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2/randtable.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2v2.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2v2.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2v3.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/bzip2v3.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/convert.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/convert.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/ecma119.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/ecma119.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/gzipv1.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/gzipv1.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/gzipv2.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/gzipv2.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/imagetype.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/imagetype.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/ini.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/ini.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/isocompress.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/isocompress.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/isofile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/isofile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/multifile.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/multifile.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/toc.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/toc.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/version.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/version.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/ChangeLog create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/README create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/adler32.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/compress.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/crc32.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/crc32.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/deflate.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/deflate.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/gzio.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/infback.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inffast.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inffast.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inffixed.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inflate.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inflate.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/trees.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/trees.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/uncompr.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/zconf.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h.bak create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/zutil.c create mode 100644 plugins/cdvd/CDVDisoEFP/src/zlib/zutil.h create mode 100644 plugins/cdvd/CDVDlinuz/ChangeLog.txt create mode 100644 plugins/cdvd/CDVDlinuz/License.txt create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/CD.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/CD.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/DVD.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/DVD.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/Makefile create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/conf.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/conf.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/device.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/device.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/interface.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/logfile.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/logfile.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/CD.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/CD.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/DVD.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/DVD.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/Makefile.MinGW32 create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/conf.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/conf.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/device.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/device.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/logfile.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/logfile.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/make.bat create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/plugin.def create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/screens.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/Win32/screens.rc create mode 100644 plugins/cdvd/CDVDlinuz/Src/buffer.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/buffer.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/convert.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/convert.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/ini.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/ini.h create mode 100644 plugins/cdvd/CDVDlinuz/Src/version.c create mode 100644 plugins/cdvd/CDVDlinuz/Src/version.h create mode 100644 plugins/cdvd/CDVDlinuz/build.sh create mode 100644 plugins/cdvd/CDVDlinuz/readme.txt create mode 100644 plugins/cdvd/CDVDnull/CDVDnull.dll create mode 100644 plugins/cdvd/CDVDnull/ReadMe.txt create mode 100644 plugins/cdvd/CDVDnull/Src/CDVD.c create mode 100644 plugins/cdvd/CDVDnull/Src/CDVD.h create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.def create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.dsp create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.dsw create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.opt create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.plg create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.sln create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull.vcproj create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_2003.sln create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_2003.vcproj create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.sln create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.vcproj create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.sln create mode 100644 plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.vcproj create mode 100644 plugins/cdvd/CDVDnull/Src/Makefile create mode 100644 plugins/cdvd/CDVDnull/Src/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDnull/Src/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDnull/Src/plugin.def create mode 100644 plugins/cdvd/CDVDnull/build.sh create mode 100644 plugins/cdvd/CDVDpeops/CDVDiso.c create mode 100644 plugins/cdvd/CDVDpeops/CDVDiso.h create mode 100644 plugins/cdvd/CDVDpeops/CDVDisodrv.c create mode 100644 plugins/cdvd/CDVDpeops/CDVDisodrv.h create mode 100644 plugins/cdvd/CDVDpeops/CDVDlib.h create mode 100644 plugins/cdvd/CDVDpeops/CLEAN.BAT create mode 100644 plugins/cdvd/CDVDpeops/Cdr.c create mode 100644 plugins/cdvd/CDVDpeops/Cdr.c.bak create mode 100644 plugins/cdvd/CDVDpeops/Cfg.c create mode 100644 plugins/cdvd/CDVDpeops/CheckDiskType.c create mode 100644 plugins/cdvd/CDVDpeops/Ioctrl.c create mode 100644 plugins/cdvd/CDVDpeops/Makefile.win create mode 100644 plugins/cdvd/CDVDpeops/PS2Edefs.h create mode 100644 plugins/cdvd/CDVDpeops/PS2Etypes.h create mode 100644 plugins/cdvd/CDVDpeops/ReadMe.txt create mode 100644 plugins/cdvd/CDVDpeops/Scsi.c create mode 100644 plugins/cdvd/CDVDpeops/StdAfx.c create mode 100644 plugins/cdvd/CDVDpeops/StdAfx.h create mode 100644 plugins/cdvd/CDVDpeops/build.sh create mode 100644 plugins/cdvd/CDVDpeops/cdda.c create mode 100644 plugins/cdvd/CDVDpeops/cdda.h create mode 100644 plugins/cdvd/CDVDpeops/cdr.h create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.aps create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.c create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.def create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.def.bak create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.dev create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.dsp create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.dsw create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.h create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.layout create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.opt create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.plg create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.rc create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.sln create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.suo create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops.vcproj create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops_2005.sln create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops_2005.vcproj create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops_private.h create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops_private.rc create mode 100644 plugins/cdvd/CDVDpeops/cdvdPeops_private.res create mode 100644 plugins/cdvd/CDVDpeops/cfg.h create mode 100644 plugins/cdvd/CDVDpeops/changelog.txt create mode 100644 plugins/cdvd/CDVDpeops/defines.h create mode 100644 plugins/cdvd/CDVDpeops/defines.h.bak create mode 100644 plugins/cdvd/CDVDpeops/externals.h create mode 100644 plugins/cdvd/CDVDpeops/externals.h.bak create mode 100644 plugins/cdvd/CDVDpeops/filemap.txt create mode 100644 plugins/cdvd/CDVDpeops/generic.c create mode 100644 plugins/cdvd/CDVDpeops/generic.c.bak create mode 100644 plugins/cdvd/CDVDpeops/generic.h create mode 100644 plugins/cdvd/CDVDpeops/i386.asm create mode 100644 plugins/cdvd/CDVDpeops/ioctrl.h create mode 100644 plugins/cdvd/CDVDpeops/libiso.c create mode 100644 plugins/cdvd/CDVDpeops/libiso.h create mode 100644 plugins/cdvd/CDVDpeops/license.txt create mode 100644 plugins/cdvd/CDVDpeops/macros.inc create mode 100644 plugins/cdvd/CDVDpeops/mingw/afxres.h create mode 100644 plugins/cdvd/CDVDpeops/ppf.c create mode 100644 plugins/cdvd/CDVDpeops/ppf.h create mode 100644 plugins/cdvd/CDVDpeops/read.c create mode 100644 plugins/cdvd/CDVDpeops/read.h create mode 100644 plugins/cdvd/CDVDpeops/readme_1_2.txt create mode 100644 plugins/cdvd/CDVDpeops/resource.h create mode 100644 plugins/cdvd/CDVDpeops/scsi.h create mode 100644 plugins/cdvd/CDVDpeops/scsidefs.h create mode 100644 plugins/cdvd/CDVDpeops/sub.c create mode 100644 plugins/cdvd/CDVDpeops/sub.h create mode 100644 plugins/cdvd/CDVDpeops/toc.c create mode 100644 plugins/cdvd/CDVDpeops/toc.h create mode 100644 plugins/cdvd/CDVDpeops/version_1_2.txt create mode 100644 plugins/cdvd/CDVDpeops/wnaspi32.h create mode 100644 plugins/cdvd/build.sh create mode 100644 plugins/dev9/DEV9linuz/DEV9.c create mode 100644 plugins/dev9/DEV9linuz/DEV9.h create mode 100644 plugins/dev9/DEV9linuz/Linux/Config.c create mode 100644 plugins/dev9/DEV9linuz/Linux/Config.h create mode 100644 plugins/dev9/DEV9linuz/Linux/Linux.c create mode 100644 plugins/dev9/DEV9linuz/Linux/Makefile create mode 100644 plugins/dev9/DEV9linuz/Linux/callbacks.c create mode 100644 plugins/dev9/DEV9linuz/Linux/callbacks.h create mode 100644 plugins/dev9/DEV9linuz/Linux/conf.c create mode 100644 plugins/dev9/DEV9linuz/Linux/dev9linuz.glade create mode 100644 plugins/dev9/DEV9linuz/Linux/dev9net.c create mode 100644 plugins/dev9/DEV9linuz/Linux/interface.c create mode 100644 plugins/dev9/DEV9linuz/Linux/interface.h create mode 100644 plugins/dev9/DEV9linuz/Linux/socks.c create mode 100644 plugins/dev9/DEV9linuz/Linux/socks.h create mode 100644 plugins/dev9/DEV9linuz/Linux/support.c create mode 100644 plugins/dev9/DEV9linuz/Linux/support.h create mode 100644 plugins/dev9/DEV9linuz/PS2Edefs.h create mode 100644 plugins/dev9/DEV9linuz/PS2Etypes.h create mode 100644 plugins/dev9/DEV9linuz/Win32/Config.c create mode 100644 plugins/dev9/DEV9linuz/Win32/Config.h create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.def create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsp create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsw create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.ncb create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.opt create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.plg create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.rc create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln.old create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.suo create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.7.10.old create mode 100644 plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.FLORIN.Florin.user create mode 100644 plugins/dev9/DEV9linuz/Win32/Devioctl.h create mode 100644 plugins/dev9/DEV9linuz/Win32/Makefile create mode 100644 plugins/dev9/DEV9linuz/Win32/Ntddndis.h create mode 100644 plugins/dev9/DEV9linuz/Win32/Packet.lib create mode 100644 plugins/dev9/DEV9linuz/Win32/Packet32.h create mode 100644 plugins/dev9/DEV9linuz/Win32/Win32.c create mode 100644 plugins/dev9/DEV9linuz/Win32/afxresmw.h create mode 100644 plugins/dev9/DEV9linuz/Win32/libpacket.a create mode 100644 plugins/dev9/DEV9linuz/Win32/plugin.def create mode 100644 plugins/dev9/DEV9linuz/Win32/resource.h create mode 100644 plugins/dev9/DEV9linuz/Win32/socks.c create mode 100644 plugins/dev9/DEV9linuz/Win32/socks.h create mode 100644 plugins/dev9/DEV9linuz/flash.c create mode 100644 plugins/dev9/build.sh create mode 100644 plugins/dev9/dev9null/DEV9null.dll create mode 100644 plugins/dev9/dev9null/ReadMe.txt create mode 100644 plugins/dev9/dev9null/build.sh create mode 100644 plugins/dev9/dev9null/src/DEV9.h create mode 100644 plugins/dev9/dev9null/src/DEV9null.dsp create mode 100644 plugins/dev9/dev9null/src/DEV9null.dsw create mode 100644 plugins/dev9/dev9null/src/Dev9null.ncb create mode 100644 plugins/dev9/dev9null/src/Dev9null.sln create mode 100644 plugins/dev9/dev9null/src/Dev9null.suo create mode 100644 plugins/dev9/dev9null/src/Dev9null.vcproj create mode 100644 plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.sln create mode 100644 plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.vcproj create mode 100644 plugins/dev9/dev9null/src/Makefile create mode 100644 plugins/dev9/dev9null/src/Makefile.mingw create mode 100644 plugins/dev9/dev9null/src/PS2Edefs.h create mode 100644 plugins/dev9/dev9null/src/PS2Etypes.h create mode 100644 plugins/dev9/dev9null/src/dev9null.c create mode 100644 plugins/dev9/dev9null/src/dev9null.def create mode 100644 plugins/dev9/dev9null/src/plugin.def create mode 100644 plugins/fw/FWlinuz/FW.c create mode 100644 plugins/fw/FWlinuz/FW.h create mode 100644 plugins/fw/FWlinuz/License.txt create mode 100644 plugins/fw/FWlinuz/Linux/Config.c create mode 100644 plugins/fw/FWlinuz/Linux/Config.h create mode 100644 plugins/fw/FWlinuz/Linux/Linux.c create mode 100644 plugins/fw/FWlinuz/Linux/Makefile create mode 100644 plugins/fw/FWlinuz/Linux/callbacks.c create mode 100644 plugins/fw/FWlinuz/Linux/callbacks.h create mode 100644 plugins/fw/FWlinuz/Linux/conf.c create mode 100644 plugins/fw/FWlinuz/Linux/firewire.glade create mode 100644 plugins/fw/FWlinuz/Linux/interface.c create mode 100644 plugins/fw/FWlinuz/Linux/interface.h create mode 100644 plugins/fw/FWlinuz/Linux/support.c create mode 100644 plugins/fw/FWlinuz/Linux/support.h create mode 100644 plugins/fw/FWlinuz/PS2Edefs.h create mode 100644 plugins/fw/FWlinuz/PS2Etypes.h create mode 100644 plugins/fw/FWlinuz/ReadMe.txt create mode 100644 plugins/fw/FWlinuz/Win32/Config.c create mode 100644 plugins/fw/FWlinuz/Win32/FWlinuz.def create mode 100644 plugins/fw/FWlinuz/Win32/FWlinuz.rc create mode 100644 plugins/fw/FWlinuz/Win32/FWlinuz.sln create mode 100644 plugins/fw/FWlinuz/Win32/FireWireNull.ncb create mode 100644 plugins/fw/FWlinuz/Win32/FireWireNull.sln create mode 100644 plugins/fw/FWlinuz/Win32/FireWireNull.suo create mode 100644 plugins/fw/FWlinuz/Win32/FireWireNull.vcproj create mode 100644 plugins/fw/FWlinuz/Win32/Makefile create mode 100644 plugins/fw/FWlinuz/Win32/Win32.c create mode 100644 plugins/fw/FWlinuz/Win32/afxresmw.h create mode 100644 plugins/fw/FWlinuz/Win32/plugin.def create mode 100644 plugins/fw/FWlinuz/Win32/resource.h create mode 100644 plugins/fw/FWnull/FW.c create mode 100644 plugins/fw/FWnull/FW.h create mode 100644 plugins/fw/FWnull/License.txt create mode 100644 plugins/fw/FWnull/Linux/Config.c create mode 100644 plugins/fw/FWnull/Linux/Config.h create mode 100644 plugins/fw/FWnull/Linux/Linux.c create mode 100644 plugins/fw/FWnull/Linux/Makefile create mode 100644 plugins/fw/FWnull/Linux/callbacks.c create mode 100644 plugins/fw/FWnull/Linux/callbacks.h create mode 100644 plugins/fw/FWnull/Linux/conf.c create mode 100644 plugins/fw/FWnull/Linux/firewire.glade create mode 100644 plugins/fw/FWnull/Linux/interface.c create mode 100644 plugins/fw/FWnull/Linux/interface.h create mode 100644 plugins/fw/FWnull/Linux/support.c create mode 100644 plugins/fw/FWnull/Linux/support.h create mode 100644 plugins/fw/FWnull/PS2Edefs.h create mode 100644 plugins/fw/FWnull/PS2Etypes.h create mode 100644 plugins/fw/FWnull/ReadMe.txt create mode 100644 plugins/fw/FWnull/Win32/Config.c create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.def create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.dsp create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.dsw create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.ncb create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.rc create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.sln create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.suo create mode 100644 plugins/fw/FWnull/Win32/FireWireNull.vcproj create mode 100644 plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.sln create mode 100644 plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.vcproj create mode 100644 plugins/fw/FWnull/Win32/Makefile create mode 100644 plugins/fw/FWnull/Win32/PS2Edefs.h create mode 100644 plugins/fw/FWnull/Win32/Win32.c create mode 100644 plugins/fw/FWnull/Win32/afxresmw.h create mode 100644 plugins/fw/FWnull/Win32/plugin.def create mode 100644 plugins/fw/FWnull/Win32/resource.h create mode 100644 plugins/fw/FWnull/build.sh create mode 100644 plugins/fw/build.sh create mode 100644 plugins/gs/GSsoft/License.txt create mode 100644 plugins/gs/GSsoft/ReadMe.txt create mode 100644 plugins/gs/GSsoft/Src/Cache.c create mode 100644 plugins/gs/GSsoft/Src/Cache.h create mode 100644 plugins/gs/GSsoft/Src/Color.c create mode 100644 plugins/gs/GSsoft/Src/Color.h create mode 100644 plugins/gs/GSsoft/Src/Draw.c create mode 100644 plugins/gs/GSsoft/Src/Draw.h create mode 100644 plugins/gs/GSsoft/Src/GS.c create mode 100644 plugins/gs/GSsoft/Src/GS.h create mode 100644 plugins/gs/GSsoft/Src/Linux-SDL/Conf.c create mode 100644 plugins/gs/GSsoft/Src/Linux-SDL/X11.c create mode 100644 plugins/gs/GSsoft/Src/Linux/Conf.c create mode 100644 plugins/gs/GSsoft/Src/Linux/Linux.c create mode 100644 plugins/gs/GSsoft/Src/Linux/Linux.h create mode 100644 plugins/gs/GSsoft/Src/Linux/Makefile create mode 100644 plugins/gs/GSsoft/Src/Linux/callbacks.c create mode 100644 plugins/gs/GSsoft/Src/Linux/callbacks.h create mode 100644 plugins/gs/GSsoft/Src/Linux/gssoft.glade create mode 100644 plugins/gs/GSsoft/Src/Linux/interface.c create mode 100644 plugins/gs/GSsoft/Src/Linux/interface.h create mode 100644 plugins/gs/GSsoft/Src/Linux/support.c create mode 100644 plugins/gs/GSsoft/Src/Linux/support.h create mode 100644 plugins/gs/GSsoft/Src/Mem.c create mode 100644 plugins/gs/GSsoft/Src/Mem.h create mode 100644 plugins/gs/GSsoft/Src/PS2Edefs.h create mode 100644 plugins/gs/GSsoft/Src/PS2Etypes.h create mode 100644 plugins/gs/GSsoft/Src/Page.c create mode 100644 plugins/gs/GSsoft/Src/Page.h create mode 100644 plugins/gs/GSsoft/Src/Prim.c create mode 100644 plugins/gs/GSsoft/Src/Rec.c create mode 100644 plugins/gs/GSsoft/Src/Rec.h create mode 100644 plugins/gs/GSsoft/Src/Regs.c create mode 100644 plugins/gs/GSsoft/Src/Regs.h create mode 100644 plugins/gs/GSsoft/Src/SDL.c create mode 100644 plugins/gs/GSsoft/Src/SDL_gfxPrimitives.c create mode 100644 plugins/gs/GSsoft/Src/SDL_gfxPrimitives.h create mode 100644 plugins/gs/GSsoft/Src/SDL_gfxPrimitives_font.h create mode 100644 plugins/gs/GSsoft/Src/Soft.c create mode 100644 plugins/gs/GSsoft/Src/Soft.h create mode 100644 plugins/gs/GSsoft/Src/System.h create mode 100644 plugins/gs/GSsoft/Src/Texts.c create mode 100644 plugins/gs/GSsoft/Src/Texts.h create mode 100644 plugins/gs/GSsoft/Src/Transfer.c create mode 100644 plugins/gs/GSsoft/Src/Transfer.h create mode 100644 plugins/gs/GSsoft/Src/Win32/Conf.c create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.def create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsp create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsw create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.ncb create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.rc create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.sln create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.suo create mode 100644 plugins/gs/GSsoft/Src/Win32/GSsoftdx.vcproj create mode 100644 plugins/gs/GSsoft/Src/Win32/Makefile create mode 100644 plugins/gs/GSsoft/Src/Win32/SDL.c create mode 100644 plugins/gs/GSsoft/Src/Win32/Win32.c create mode 100644 plugins/gs/GSsoft/Src/Win32/Win32.h create mode 100644 plugins/gs/GSsoft/Src/Win32/afxresmw.h create mode 100644 plugins/gs/GSsoft/Src/Win32/plugin.def create mode 100644 plugins/gs/GSsoft/Src/Win32/plugin.h create mode 100644 plugins/gs/GSsoft/Src/Win32/resource.h create mode 100644 plugins/gs/GSsoft/Src/avcodec.h create mode 100644 plugins/gs/GSsoft/Src/common.h create mode 100644 plugins/gs/GSsoft/Src/ffmpeg/avformat.h create mode 100644 plugins/gs/GSsoft/Src/ffmpeg/avio.h create mode 100644 plugins/gs/GSsoft/Src/ffmpeg/rtp.h create mode 100644 plugins/gs/GSsoft/Src/ffmpeg/rtsp.h create mode 100644 plugins/gs/GSsoft/Src/ffmpeg/rtspcodes.h create mode 100644 plugins/gs/GSsoft/Src/scale2x.c create mode 100644 plugins/gs/GSsoft/Src/scale2x.h create mode 100644 plugins/gs/GSsoft/Src/x86/ix86.h create mode 100644 plugins/gs/GSsoft/Src/x86/ix86_cpudetect.c create mode 100644 plugins/gs/build.sh create mode 100644 plugins/gs/zerogs/build.sh create mode 100644 plugins/gs/zerogs/opengl/GS.h create mode 100644 plugins/gs/zerogs/opengl/GSmain.cpp create mode 100644 plugins/gs/zerogs/opengl/Linux/Conf.cpp create mode 100644 plugins/gs/zerogs/opengl/Linux/Linux.cpp create mode 100644 plugins/gs/zerogs/opengl/Linux/Linux.h create mode 100644 plugins/gs/zerogs/opengl/Linux/Makefile.am create mode 100644 plugins/gs/zerogs/opengl/Linux/buildgui.sh create mode 100644 plugins/gs/zerogs/opengl/Linux/callbacks.c create mode 100644 plugins/gs/zerogs/opengl/Linux/callbacks.h create mode 100644 plugins/gs/zerogs/opengl/Linux/interface.c create mode 100644 plugins/gs/zerogs/opengl/Linux/interface.h create mode 100644 plugins/gs/zerogs/opengl/Linux/support.c create mode 100644 plugins/gs/zerogs/opengl/Linux/support.h create mode 100644 plugins/gs/zerogs/opengl/Linux/zerogs.glade create mode 100644 plugins/gs/zerogs/opengl/Makefile.am create mode 100644 plugins/gs/zerogs/opengl/Mem.cpp create mode 100644 plugins/gs/zerogs/opengl/Mem.h create mode 100644 plugins/gs/zerogs/opengl/PS2Edefs.h create mode 100644 plugins/gs/zerogs/opengl/PS2Etypes.h create mode 100644 plugins/gs/zerogs/opengl/Regs.cpp create mode 100644 plugins/gs/zerogs/opengl/Regs.h create mode 100644 plugins/gs/zerogs/opengl/Win32/Conf.cpp create mode 100644 plugins/gs/zerogs/opengl/Win32/Win32.cpp create mode 100644 plugins/gs/zerogs/opengl/Win32/Win32.h create mode 100644 plugins/gs/zerogs/opengl/Win32/aviUtil.h create mode 100644 plugins/gs/zerogs/opengl/Win32/copytopcsx2.bat create mode 100644 plugins/gs/zerogs/opengl/Win32/jconfig.h create mode 100644 plugins/gs/zerogs/opengl/Win32/jmorecfg.h create mode 100644 plugins/gs/zerogs/opengl/Win32/jpeglib.h create mode 100644 plugins/gs/zerogs/opengl/Win32/libjpeg.lib create mode 100644 plugins/gs/zerogs/opengl/Win32/libjpeg64.lib create mode 100644 plugins/gs/zerogs/opengl/Win32/ps2hw.dat create mode 100644 plugins/gs/zerogs/opengl/Win32/resource.h create mode 100644 plugins/gs/zerogs/opengl/Win32/resrc1.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogs.bmp create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogs.def create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogs.rc create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogsogl.vcproj create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogsogl_2005.vcproj create mode 100644 plugins/gs/zerogs/opengl/Win32/zerogsogl_2005_x64.vcproj create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/adler32.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/compress.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/crc32.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/crc32.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/deflate.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/deflate.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/gzio.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/infback.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inffast.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inffast.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inffixed.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inflate.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inflate.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inftrees.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/inftrees.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/trees.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/trees.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/uncompr.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/zconf.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/zlib.h create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/zutil.c create mode 100644 plugins/gs/zerogs/opengl/Win32/zlib/zutil.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/Makefile.am create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/ZLib.lib create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders.vcproj create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/copytozerogs.bat create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.cpp create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/crc32.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/deflate.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffast.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffixed.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inflate.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inftrees.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/trees.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.in.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zlib.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zutil.h create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.cpp create mode 100644 plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.h create mode 100644 plugins/gs/zerogs/opengl/buildshaders.bat create mode 100644 plugins/gs/zerogs/opengl/common.h create mode 100644 plugins/gs/zerogs/opengl/compile create mode 100644 plugins/gs/zerogs/opengl/configure create mode 100644 plugins/gs/zerogs/opengl/configure.ac create mode 100644 plugins/gs/zerogs/opengl/depcomp create mode 100644 plugins/gs/zerogs/opengl/glprocs.c create mode 100644 plugins/gs/zerogs/opengl/glprocs.h create mode 100644 plugins/gs/zerogs/opengl/install-sh create mode 100644 plugins/gs/zerogs/opengl/memcpy_amd.cpp create mode 100644 plugins/gs/zerogs/opengl/missing create mode 100644 plugins/gs/zerogs/opengl/mkinstalldirs create mode 100644 plugins/gs/zerogs/opengl/rasterfont.cpp create mode 100644 plugins/gs/zerogs/opengl/rasterfont.h create mode 100644 plugins/gs/zerogs/opengl/targets.cpp create mode 100644 plugins/gs/zerogs/opengl/targets.h create mode 100644 plugins/gs/zerogs/opengl/x86-32.S create mode 100644 plugins/gs/zerogs/opengl/x86-32.asm create mode 100644 plugins/gs/zerogs/opengl/x86-64.S create mode 100644 plugins/gs/zerogs/opengl/x86-64.asm create mode 100644 plugins/gs/zerogs/opengl/x86.cpp create mode 100644 plugins/gs/zerogs/opengl/x86.h create mode 100644 plugins/gs/zerogs/opengl/zerogs.cpp create mode 100644 plugins/gs/zerogs/opengl/zerogs.h create mode 100644 plugins/gs/zerogs/opengl/zerogsmath.h create mode 100644 plugins/gs/zerogs/opengl/zpipe.cpp create mode 100644 plugins/gs/zerogs/opengl/zpipe.h create mode 100644 plugins/pad/PADwin/ReadMe.txt create mode 100644 plugins/pad/PADwin/Src/Conf.c create mode 100644 plugins/pad/PADwin/Src/Linux.c create mode 100644 plugins/pad/PADwin/Src/Makefile create mode 100644 plugins/pad/PADwin/Src/Makefile.mingw create mode 100644 plugins/pad/PADwin/Src/PAD.c create mode 100644 plugins/pad/PADwin/Src/PAD.h create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.def create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.dsp create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.dsw create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.sln create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.suo create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb.vcproj create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.sln create mode 100644 plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.vcproj create mode 100644 plugins/pad/PADwin/Src/PADwnKeyb.rc create mode 100644 plugins/pad/PADwin/Src/PS2Edefs.h create mode 100644 plugins/pad/PADwin/Src/PS2Etypes.h create mode 100644 plugins/pad/PADwin/Src/Win32.c create mode 100644 plugins/pad/PADwin/Src/afxresmw.h create mode 100644 plugins/pad/PADwin/Src/callbacks.c create mode 100644 plugins/pad/PADwin/Src/callbacks.h create mode 100644 plugins/pad/PADwin/Src/controller.bmp create mode 100644 plugins/pad/PADwin/Src/interface.c create mode 100644 plugins/pad/PADwin/Src/interface.h create mode 100644 plugins/pad/PADwin/Src/mingw/Makefile.win create mode 100644 plugins/pad/PADwin/Src/mingw/PADwinKeyb.dev create mode 100644 plugins/pad/PADwin/Src/mingw/PADwinKeyb.layout create mode 100644 plugins/pad/PADwin/Src/mingw/afxres.h create mode 100644 plugins/pad/PADwin/Src/plugin.def create mode 100644 plugins/pad/PADwin/Src/ps2pad.bmp create mode 100644 plugins/pad/PADwin/Src/resource.h create mode 100644 plugins/pad/PADwin/Src/support.c create mode 100644 plugins/pad/PADwin/Src/support.h create mode 100644 plugins/pad/PADwin/build.sh create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX.cpp create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX.def create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX.h create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX.rc create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX.vcproj create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.sln create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.vcproj create mode 100644 plugins/pad/SSSPSXPAD/PadSSSPSXres.h create mode 100644 plugins/pad/SSSPSXPAD/licence.txt create mode 100644 plugins/pad/SSSPSXPAD/readmewip.txt create mode 100644 plugins/pad/build.sh create mode 100644 plugins/pad/zeropad/Makefile.am create mode 100644 plugins/pad/zeropad/PS2Edefs.h create mode 100644 plugins/pad/zeropad/PS2Etypes.h create mode 100644 plugins/pad/zeropad/Windows/ZeroPAD.def create mode 100644 plugins/pad/zeropad/Windows/ZeroPAD.rc create mode 100644 plugins/pad/zeropad/Windows/ZeroPAD.vcproj create mode 100644 plugins/pad/zeropad/Windows/ZeroPAD_2005.vcproj create mode 100644 plugins/pad/zeropad/Windows/ZeroPAD_2005_x64.vcproj create mode 100644 plugins/pad/zeropad/Windows/resource.h create mode 100644 plugins/pad/zeropad/Windows/win.cpp create mode 100644 plugins/pad/zeropad/build.sh create mode 100644 plugins/pad/zeropad/callbacks.h create mode 100644 plugins/pad/zeropad/compile create mode 100644 plugins/pad/zeropad/configure.ac create mode 100644 plugins/pad/zeropad/depcomp create mode 100644 plugins/pad/zeropad/install-sh create mode 100644 plugins/pad/zeropad/interface.c create mode 100644 plugins/pad/zeropad/interface.h create mode 100644 plugins/pad/zeropad/linux.cpp create mode 100644 plugins/pad/zeropad/missing create mode 100644 plugins/pad/zeropad/mkinstalldirs create mode 100644 plugins/pad/zeropad/support.c create mode 100644 plugins/pad/zeropad/support.h create mode 100644 plugins/pad/zeropad/zeropad.cpp create mode 100644 plugins/pad/zeropad/zeropad.glade create mode 100644 plugins/pad/zeropad/zeropad.h create mode 100644 plugins/spu2/PeopsSPU2/Filemap.txt create mode 100644 plugins/spu2/PeopsSPU2/Makefile create mode 100644 plugins/spu2/PeopsSPU2/Makefile.win create mode 100644 plugins/spu2/PeopsSPU2/_bsc.txt create mode 100644 plugins/spu2/PeopsSPU2/adsr.c create mode 100644 plugins/spu2/PeopsSPU2/adsr.h create mode 100644 plugins/spu2/PeopsSPU2/alsa.c create mode 100644 plugins/spu2/PeopsSPU2/alsa.h create mode 100644 plugins/spu2/PeopsSPU2/build.sh create mode 100644 plugins/spu2/PeopsSPU2/cfg.c create mode 100644 plugins/spu2/PeopsSPU2/cfg.h create mode 100644 plugins/spu2/PeopsSPU2/clean.bat create mode 100644 plugins/spu2/PeopsSPU2/debug.c create mode 100644 plugins/spu2/PeopsSPU2/debug.h create mode 100644 plugins/spu2/PeopsSPU2/dma.c create mode 100644 plugins/spu2/PeopsSPU2/dma.h create mode 100644 plugins/spu2/PeopsSPU2/dsound.c create mode 100644 plugins/spu2/PeopsSPU2/dsound.h create mode 100644 plugins/spu2/PeopsSPU2/dsoundoss.h create mode 100644 plugins/spu2/PeopsSPU2/externals.h create mode 100644 plugins/spu2/PeopsSPU2/freeze.c create mode 100644 plugins/spu2/PeopsSPU2/gauss_i.h create mode 100644 plugins/spu2/PeopsSPU2/mingw/afxres.h create mode 100644 plugins/spu2/PeopsSPU2/oss.c create mode 100644 plugins/spu2/PeopsSPU2/oss.h create mode 100644 plugins/spu2/PeopsSPU2/psemu.c create mode 100644 plugins/spu2/PeopsSPU2/psemuxa.h create mode 100644 plugins/spu2/PeopsSPU2/record.c create mode 100644 plugins/spu2/PeopsSPU2/record.h create mode 100644 plugins/spu2/PeopsSPU2/registers.c create mode 100644 plugins/spu2/PeopsSPU2/registers.h create mode 100644 plugins/spu2/PeopsSPU2/regs.h create mode 100644 plugins/spu2/PeopsSPU2/res/spu2PeopsSound.rc2 create mode 100644 plugins/spu2/PeopsSPU2/resource.h create mode 100644 plugins/spu2/PeopsSPU2/reverb.c create mode 100644 plugins/spu2/PeopsSPU2/reverb.h create mode 100644 plugins/spu2/PeopsSPU2/spu.c create mode 100644 plugins/spu2/PeopsSPU2/spu.h create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.aps create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.c create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.def create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.dev create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.dsp create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.dsw create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.layout create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.opt create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.plg create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.rc create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.sln create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound.vcproj create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.sln create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.vcproj create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.sln create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.vcproj create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_private.h create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_private.rc create mode 100644 plugins/spu2/PeopsSPU2/spu2PeopsSound_private.res create mode 100644 plugins/spu2/PeopsSPU2/spunew.c create mode 100644 plugins/spu2/PeopsSPU2/stdafx.c create mode 100644 plugins/spu2/PeopsSPU2/stdafx.h create mode 100644 plugins/spu2/PeopsSPU2/xa.c create mode 100644 plugins/spu2/PeopsSPU2/xa.h create mode 100644 plugins/spu2/SPU2null/License.txt create mode 100644 plugins/spu2/SPU2null/ReadMe.txt create mode 100644 plugins/spu2/SPU2null/Src/Changelog.txt create mode 100644 plugins/spu2/SPU2null/Src/Config.cpp create mode 100644 plugins/spu2/SPU2null/Src/Makefile create mode 100644 plugins/spu2/SPU2null/Src/Makefile.mingw create mode 100644 plugins/spu2/SPU2null/Src/PS2Edefs.h create mode 100644 plugins/spu2/SPU2null/Src/PS2Etypes.h create mode 100644 plugins/spu2/SPU2null/Src/SPU2.cpp create mode 100644 plugins/spu2/SPU2null/Src/SPU2.h create mode 100644 plugins/spu2/SPU2null/Src/SPU2null.def create mode 100644 plugins/spu2/SPU2null/Src/SPU2null.ncb create mode 100644 plugins/spu2/SPU2null/Src/SPU2null.rc create mode 100644 plugins/spu2/SPU2null/Src/SPU2null.sln create mode 100644 plugins/spu2/SPU2null/Src/SPU2null.vcproj create mode 100644 plugins/spu2/SPU2null/Src/SPU2null_2005.sln create mode 100644 plugins/spu2/SPU2null/Src/SPU2null_2005.vcproj create mode 100644 plugins/spu2/SPU2null/Src/SPU2null_2005_x64.sln create mode 100644 plugins/spu2/SPU2null/Src/SPU2null_2005_x64.vcproj create mode 100644 plugins/spu2/SPU2null/Src/Win32.cpp create mode 100644 plugins/spu2/SPU2null/Src/mingw/Makefile.win create mode 100644 plugins/spu2/SPU2null/Src/mingw/SPU2null.dev create mode 100644 plugins/spu2/SPU2null/Src/mingw/afxres.h create mode 100644 plugins/spu2/SPU2null/Src/mingw/plugin.def create mode 100644 plugins/spu2/SPU2null/Src/resource.h create mode 100644 plugins/spu2/SPU2null/build.sh create mode 100644 plugins/spu2/build.sh create mode 100644 plugins/usb/USBlinuz/License.txt create mode 100644 plugins/usb/USBlinuz/Linux/Config.c create mode 100644 plugins/usb/USBlinuz/Linux/Config.h create mode 100644 plugins/usb/USBlinuz/Linux/Linux.c create mode 100644 plugins/usb/USBlinuz/Linux/Makefile create mode 100644 plugins/usb/USBlinuz/Linux/callbacks.c create mode 100644 plugins/usb/USBlinuz/Linux/callbacks.h create mode 100644 plugins/usb/USBlinuz/Linux/conf.c create mode 100644 plugins/usb/USBlinuz/Linux/interface.c create mode 100644 plugins/usb/USBlinuz/Linux/interface.h create mode 100644 plugins/usb/USBlinuz/Linux/support.c create mode 100644 plugins/usb/USBlinuz/Linux/support.h create mode 100644 plugins/usb/USBlinuz/Linux/usblinuz.glade create mode 100644 plugins/usb/USBlinuz/PS2Edefs.h create mode 100644 plugins/usb/USBlinuz/PS2Etypes.h create mode 100644 plugins/usb/USBlinuz/ReadMe.txt create mode 100644 plugins/usb/USBlinuz/USB.c create mode 100644 plugins/usb/USBlinuz/USB.h create mode 100644 plugins/usb/USBlinuz/Win32/Config.c create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.def create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.dsp create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.dsw create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.rc create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.sln create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.suo create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz.vcproj create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.sln create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.vcproj create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.ncb create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.sln create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.suo create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.vcproj create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.sln create mode 100644 plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.vcproj create mode 100644 plugins/usb/USBlinuz/Win32/Win32.c create mode 100644 plugins/usb/USBlinuz/Win32/resource.h create mode 100644 plugins/usb/USBnull/License.txt create mode 100644 plugins/usb/USBnull/Linux/Config.c create mode 100644 plugins/usb/USBnull/Linux/Config.h create mode 100644 plugins/usb/USBnull/Linux/Linux.c create mode 100644 plugins/usb/USBnull/Linux/Makefile create mode 100644 plugins/usb/USBnull/Linux/callbacks.c create mode 100644 plugins/usb/USBnull/Linux/callbacks.h create mode 100644 plugins/usb/USBnull/Linux/conf.c create mode 100644 plugins/usb/USBnull/Linux/interface.c create mode 100644 plugins/usb/USBnull/Linux/interface.h create mode 100644 plugins/usb/USBnull/Linux/support.c create mode 100644 plugins/usb/USBnull/Linux/support.h create mode 100644 plugins/usb/USBnull/Linux/usbnull.glade create mode 100644 plugins/usb/USBnull/PS2Edefs.h create mode 100644 plugins/usb/USBnull/PS2Etypes.h create mode 100644 plugins/usb/USBnull/ReadMe.txt create mode 100644 plugins/usb/USBnull/USB.c create mode 100644 plugins/usb/USBnull/USB.h create mode 100644 plugins/usb/USBnull/Win32/Config.c create mode 100644 plugins/usb/USBnull/Win32/Makefile create mode 100644 plugins/usb/USBnull/Win32/USBnull.def create mode 100644 plugins/usb/USBnull/Win32/USBnull.dsp create mode 100644 plugins/usb/USBnull/Win32/USBnull.dsw create mode 100644 plugins/usb/USBnull/Win32/USBnull.rc create mode 100644 plugins/usb/USBnull/Win32/USBnull_vc2003.sln create mode 100644 plugins/usb/USBnull/Win32/USBnull_vc2003.vcproj create mode 100644 plugins/usb/USBnull/Win32/USBnull_vc2005beta1.sln create mode 100644 plugins/usb/USBnull/Win32/USBnull_vc2005beta1.vcproj create mode 100644 plugins/usb/USBnull/Win32/Win32.c create mode 100644 plugins/usb/USBnull/Win32/afxresmw.h create mode 100644 plugins/usb/USBnull/Win32/mingw/Makefile.win create mode 100644 plugins/usb/USBnull/Win32/mingw/USBnull.dev create mode 100644 plugins/usb/USBnull/Win32/mingw/USBnull.layout create mode 100644 plugins/usb/USBnull/Win32/mingw/afxres.h create mode 100644 plugins/usb/USBnull/Win32/plugin.def create mode 100644 plugins/usb/USBnull/Win32/resource.h create mode 100644 plugins/usb/USBnull/build.sh create mode 100644 plugins/usb/build.sh create mode 100644 test.bat create mode 100644 test.cfg create mode 100644 test.sh create mode 100644 test_readme.txt diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..0672c91 --- /dev/null +++ b/INSTALL @@ -0,0 +1,66 @@ + Pcsx2 Compilation Guide + +Linux Users +----------- + +Make sure you have these libraries: gtk2, OpenGL, Cg (for the GS plugins) + +When first building, the Pcsx2 programs need to configure the Makefiles for your specific OS. type: + +# sh build.sh all + +The program and all plugins will be installed in the pcsx2 bin dir. After that, just launch pcsx2 (make sure you have a PS2 bios dump in the bios directory). + +To rebuild any changes to the source code type: +# sh build.sh install + +Typeing sh build.sh without the install will just build the programs without copying them to the bin dirctory (bin/plugins for all plugins). + +To clean all object files type: +# sh build.sh clean + +If there is a plugin that is giving you errors and you want to skip it, modify the corresponding build.sh to skip it (otherwise execution of the script will stop until the error is resolved). + +Special Options (modify PCSX2OPTIONS in build.sh) + +--enable-debug {Build with symbols and no optimizations} +--enable-devbuild {Build with extra tests} +--disable-recbuild {Disables all architecture dependent recompilation code} +--enable-sse2 {Enables x86 SSE2 extensions} + +For plugin authors: Your Makefile should support the 'install' option. + +Windows Users +------------- + +Make sure you have: Cg (for ZeroGS) + +Open the corresponding Visual Studio sln files for all projects, compile, and move the executables appropriately. Pcsx2 and some plugins require masm to assemble (ml for win32, ml64 for win64). + +At the moment, MinGW is not supported, however there's a good chance the cygwin toolset will work. + + +email zerofrog@gmail.com for any compilation/linking issues in any Linux/Windows distribution. + +Global defines +-------------- + +Pcsx2 uses global defines to detect the OS, architecture, and different compilation options. They are: + +_MSC_VER - used to detect Visual Studio's cl compiler + +_WIN32 - used to detect windows compilation + +__LINUX__ - used to detect linux compilation (a lot of times it is assumed that linux is running when _WIN32 is missing) + +__x86_64__ - defined for x86-64 architectures only. + +PCSX2_DEVBUILD - used to enable runtime debugging and developer specific features of pcsx2 (disabled on releases) + +PCSX2_VIRTUAL_MEM - switches the way pcsx2 handles memory. VM enabled builds are valid for both windows and linux and they speed up games. However, there are less stable than TLB builds. + +PCSX2_NORECBUILD - ignore all recompiler code so that Pcsx2 can be built for different architectures. Note that there are a couple of places that use asm code even in interpreter (coroutines in IPU). + +_DEBUG - build with debug information + +ZEROGS_SSE2 - controls sse2 usage in zerogs diff --git a/bin/.pixmaps/pcsxAbout.bmp b/bin/.pixmaps/pcsxAbout.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da33bb08f4a3c365d835b0972a7dfbc43f8b01a2 GIT binary patch literal 251192 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
#6CXrR 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%0A&bFGJ^?ZxKwaSay%~z|BlTbA{G+_QCqA8wMysG zNBmkaG?Qec=8{KE0&-&-zL^liQ8Il^%VQ1e!gWZ5KN9>w@R>a?M1GcO{8xfMO2vH1crY3BCnGl!;cJP|r9|L-B5)?*KNa^L z2OPz_569T@iQj06bv6Q{V%KY9*I@s+qgN_pSK)k>iU}0GxEJ^XlZjohuOsKa0{)N- zcE*H&J`5rLOeWBKVZxucL%<(Ip)C_gTrk3)j0uE;u$KZbgeVpb2zrhI=V1i8y;U24 zHr+rQf|~glKA;Bwmje}W=V4JVL8L3>;#9eW9z4V6Q>yW-oy@kK^K54}fHlJzCQY?o zJCSEj)@HEu2%i^7ZLKU-(uC=QXcmRG5?*4ZL^qeK(~{4UH2c<43xSr!?T6X+b7KoNqVPa|^v#V#1! zI=EnnLNf#bf0PSGQJ^EQkrhPg_i)6>1;g_{&Cil~Q**DkYNJ9MxKThGhFm|Q=y-Ub z0*?IBkZTzy5QI65KXm>=-hDX&t#e@|;#@eh&+{kQo@cw%@P#m!B9pUY6;m(Sh^4l2 zBcHSMrY%EcB#m<38@c`AQZOl5TMN}$65!*jdx*j30S2G@DNtYg1E7#!fQZ8NNOvRo zYwq%Swvuh>-t2SV=5wv}Rj%>jxgb2#t_&yazy%a3(rClGQGkd6M-`C(%LoAh5QIWl zN68^LG#6`N!& zJ^};D?26L5YFFzqm!`!LJ0o>R(4hNl>#>DL(*F;QUq|B$7kb*@P|(cVf+yI;8}68g8a4j zBKd0gp>aSEEFzVFLR%FU0gkF~NAd!ZC~fps-Ri4a4_xw9uJi(za0*Wc@%RJ*p%WWC zgf^1c3S#iV<9}okVTtF3D-rcA$c3QHFtcZ}Wr?1#d?HJ7plNBWZdK5;I#|6DPyQtE zvPu0C4LezqtkBjbw4LY68w4{IjZ8kr6lp@CpT5it%BVF(Ht{W*O_31hQmW@%+B!$0 z?JA({%YtFxPX!`@w1SclV(s2PkHDv7Ue~_q!Nb4p8FJEnPMYv%AeHV-r-49;R5Awq zNs;FT{OQ&v(A7i`_;UflpSb@tyI{w}1w-&T-qjjI2*|i#Yy!pT2&_DM1tt(hp`(}f zMlbGW7fkR+MWM+AQh^|O5C{kH@6wrj+e`kYANgwU^&(JQfhaMd4Iq>b-QY&yz^-yB za3+Y4JiAv>UWGSzD6zGJB4y;j)L}249yk#Q!mndTs}?6b1wC~IefVlh6W@k8|6a}B z{_hew+eTexEsefAzJ1+I6+?`+4Za&ct7D_;^pW%R5Rx&0{B>gg*e1|D3_*AK$o>%s zBJlAN@(B2B@w$;V`>H7chy;tg?oDK=R&69ua;@jI4px)5a<#W&IiSf~Ug#}f;wxWF zK_`TR7@ZiP=BH~G68;?Eo=c7muL#V5JtEMOcxEy(=2C&?_b>2=6P^{UdjQ}A`zPHuobDMQ`zPI#N(%l& zQi)J1?oYFd2ud4xxkU+YrU?u-4(04OBY-#ntNgA?903H2o@V*E(~e{x+g!XM*;G5(y7`_IPxrxN~??1Hr;3LWn{7{76VPr(`x zg^uzm7`tFDvVzDFV-&iuJACFdI%;qKoxkOIU)}w*@hD1+=Nn;W<2}>GfSLfT8uyxD z_1a+dx{zmmsCq46hZ2wn<_!UkU=EBNl>#m?hw$Uqg|X_TiJHQmy2Ad3!l9<@#WKq( z(`#~>Ln#$zhQq4~rYQv>mxh@oY^_K}Os^3*CXqs0xlQYJm$syeYQ@?)M!z9MhAy?3 ztwHpdQmJJGxIaFAKFSCCM_EA>1p@wXf+NPUXn;?x#vekVyS!utvH#^^69~D7Trhzk z?TEn&QuxD88Nf&555T8NnL|JxPV2mtEAj90M#=oEdkKO%N(y=|e(W4vP5%qbFl8*} z5`>*psh(%MD4#adl3(;~9N7%Kb|j|TG94q1Eh7TbPcF(*ZkOskBh{hM=p3P|T9uL! zJ=xl%ArfFdi0>qvJ*Ao6nkGb{Rx8RO){2(_@i33ZpYjC=m2{QN?;`v`ngjDV-P@NY z`-feyp8j+i!DsxD36zY7arl*r`BO2tV4cbE^<-E~Ah=*>aS9gqolN+Sa|nn|!3cuL z3j+$#gFvy4+St`f7&&;h2Z1I$oC9+UXwzN3)JsoO&-0eDVdGjJsKU|1`jF>VP8%pE z*jX2Z3npHe5B5(zPQfG)4gZUyK!6~GfG7$CxUsh^!#b?OxbF z)v$t;3+Ag<_+v~U#vg&8^*;P30t68Xt@Bo`Lyiz1>>o<|=iexq*IBwO?K?Dh{tsjV zwJy!V8GC(EWRmc0VVgF!ggIi7kue0sMw86v=W~pne-$B3n1&1?`f+JEh8V5se=2~A zB9kL&nA!YzHT-Bi0EVY5ki)uI0Pw-nFI|-8b(JnkMmu^26#k@o`Vj(3r8oqXh$RsM zf(u6Y0~3f&!4l!C3FU&}6pS7L;>59N9K?4vBF=+gGS1Bd2VOw*lF+8Cu$x{P!=rtR ze0cB`kHxyz1w9)=HJfw-y&+h=K1hxg899tOaJ6)*S{Wdl2d>tNuzPvTvpiV~Z+&Th zjRv4l|ij#fTXqUsVn#NAlY*O&IWWHvubxo$M88{8JP zYj;DKRyWK5sX0l~oR*~OmVBlO-JdKCmaz0+S5Ma9nJ$12B_Bc1LZAVI4*`+FpFzeS zgn;A-j6y(3J_VBy5TAm@yo^E;i@r`F=tu? z_)wmWK|oFI=1|?1aNU+r?QNl2APK(2 zb<2AjmiIR;!;6Gu+hE`{8+vkNW@NlHCt5&=3}0^#nje#R-b^jw%LIyArCj87iy1M| zDNCklY0*}q^qaP%liW|$J<(wFOHp>Cra!16%B34dxh-I1jHHx8m^j=4DN=mhG?%jd zL-<1n@j40w6A1W2;FE(t881vhkgtZUAg{t7vVs6UI*B2)iK5Vy7=JPlbgR#;O(4di zZrV<4|6tRW%n8&#&>OolaP4!a1%YUcWf>3uz#WQ1y zK$ubxIms?H)fH2>B2}c+R%Nqq>5YvPqNL98Tn?o(idZOBO#r(D8ny>)4C!xE0);wS;m&LV%sLT?%252Mh0EN;SoyeA8P`VoaD zD=6KASTr5SCnE5_;BCRY!K2GTpbg?So;&g1inj+8E+)gKYLy>`P0ekgy4yo_cZBP= zf(U~K@(AE)%;BgGV8>2m_C#t{$Nmp<@8KQSapVjCSKm2%zW3HE$zqa7f;s0*D(7fP zRi%h*7j$6*SpS=B{3prf&d8;BtZfsNCKD~Ff$nB{(e=}UAOO@0Z4mI>*4h2 zQ(axD>-POkci%gMx@E+xvq#`%!;HaI-1u%v;?9p zSR)_^TQHmjVHXDc;b-v{f_Mv7hZ<)=TVuQg0{F;5kXs1JDu_>k@Dz*-mO!pJ2%^Q$ zs@MrG-Y#tP%lk$Mf4+r!!%4dSYQvoHk%NItk3J9T1HB!lsSXeaO zf>T+1LlDSA5QGBEvFjgP)<6G0`Jtl|#$XEu6rzn-c?KsxIAq3QPWI~W(q}(Nv_6Rm zHj2gY*NaBK{1;l-;5QadEKi*kCUt5h6>P7h zKDh!%%9+{~+1dxk>K-UHE}LjxI@P>*u5GcK9vBn=M=zxe)*ri$ktOX66nPa>LWO-h zeyp_<$S1avGqzgs{+E0G{N-kRLYaU{6?&9c%;I#it}_yFe0P05RnMUd)SCC&%LF3 ze65f0hjw9K-;-{_OR9?*g8ujLpZ_U0@VinWf$wnT2LFuL{1UB?)7yQ=_+^Z*?u*gF z=E20tRmr;bsfMlT#_gHL9hs&bX#h^+)-+)bRy){L(IO{Ri>=n`v@6s+wJLS0CR1CJ zt6Mo%zr57=z(n)1nbswYHhe`ico_(qGC-*#8PHzgs|+>gPeLdmVKLu=FDCYVj&I+O zFk&InBs=V}lJ6TAT4k(CwNN1=VgV5rQ?qI<;DjUby^yuQ4&%>3-i7fgG%bN-{evwS zK~S&@BM9R44?hmW5=d7;yb#(Hucd>a7$ArW&Vsn`aWuaaw1$s^R>w~Qh_Lv|&Td^&@~ z7n_j`I{^tmTtsS$gu_$5#wL!0uXIFMwUqFOsk+*$91&A~wCRN;u0sNn&qbz_2Pn0g z@(GEyeR1yOy>a|>*q8sD@7y+X>y3$l=f`>u0El8=-y6es3~{;n)h}AuoUBRKu1hs+ zNdsq^ciTdM1LWD3ZrCIns}una%G#8a+O@Rv;5wde;`S68 zt02Z7LZ01N1-XOh9dY1~LJ;r5uo2_4XuJ`GLij@mLA3z{@e{Fi@l&!F!$JrUWOrfl zliqPOfC%sZe0k3ZEq?C75(tk=3fF!=nIAAc+v)VrMlOTW3C0ACMLA6SW7i}^2~lyi z7zq@^21E8W246;)k$Q>EGr6uN9C0Tx1aYd05D{zI>p2Y!DidN(J!;umsG`N{o!F-= zD%9bdarfezaUf92jrUJ9-9OX1Xch-1R&j~xWK*t2FMdWc)3|zS=#{CVS0@KwoE&&= zqW`JV`6HQ@?dhgn=_WwU-b~BBOv_%zoLy-`8=%k@x5&Xd$CeboWCga}8?> zjjKw{D<@kXoM~G&OK2nBb;v@<=%jX>&`7K1vr>!i+#q%81(GVvL||O_kW?4SQFZQx z*+9#20$)|NoCQ@B!ZsIFAKS-B%iInoReY)2sL+M#iWk)uxQgjn1Z5dzqm7!XvZ^rn_a_brH!0 ztpyj+nYDJb>C}BkBBLB7RM+PyGw`+8h8lFi9UL(~&~+T)Ls*N*__cOfo8m%pLW+~k zi?S#0lZz6=tLaDavnpKU_eqZ3i;_NZU*^Pp`Py%f)qcCwaQ|e}qDg`#I$bF@FP$8C ze)`rM0H2Ag&zAe28o&5hq33X>bsvx?-Lx~^v^|4D8!H^?XxWsiw}nrY*XJA86`EF$ zx719wE}w3DV6J@`kH`&^hU2m=!vV)1W2FFzRVGan#nyZa(JVRpfst?kV&7_MS2VX? zkj|roidwwOxGY_5n1KK+L>x)8a+od*4N{y2>XHYiu3~mL+$#}kU`m9B?BbDLDM0flH6#t^h# z_F{k_UI@u?5J6B(mO$8ufjGV#$TNb)57pnoiBLIxelpo=I+xKEi43!IX>ey@;3U8t z5wrACVu~&iBH)RUq6j!^zI>%w$#B$^GbntuAnNMEws9 zJ27c$uMm~#QY{t$h7{`Q*RbPX-%B3{RPF^Wu!EYghzowP1ccO%b1xJ#C+;2V+(s*( z!57Q@Pmf=EywGz9fJ5sXDtw-UBOOhebMyW2!)UpP8^XDY~&Z^s!|n@UIwX!^xxszFlG+2sNwNpbC25RS^rD5xn~ z&WH#Ey=+IstWC#JU8~|xROgqHBgLCSke4D|0WD#39g=YzjY@k1UCx7V(8(lQ@V@{a zPPIN7uir+9L65Z7kK(Kt+bCJg5U`+ZiP^(vAP*Ko3_(=8$6<9i4hlA6*oE;+LG~cX zLD1S5?Zxa8h>n2Vc5L+60}gz!{`nTxQ4{&W>5(t!VW_=c-tZUZU}z#Bgsq*r_Es9H z+EtYa-4184(oR*5Z^x&r3M;eH%L2OERY?Q}U2>G8#AzDTcq4ug0RR2!-uTh`06TsG zhkhc73j~x-;vc9*nuJdG;FsUVFFp?ZDP4Fp+qRodb((OV3={(LV5^0vS8KBMHKpbi zIJ%jowarq47^LWZq2Wacj8TUf=~}oM(TX&otCsyPq5V4IMYY6&-|O4)`IVB9UKQ{y z_;jVba75-#BaN*P` zhHyE(Y^r5(?i4M162};MzLuIHh!#RraE6TDB>qXAkB& z_N3_P)w)z29#Jh%o>-Ek-yQuntI$3UPO~S!jgqguzgWMh+_V_K3OLoW1jjpb03`uo z3`dGY?vIZ0pcg{(5J{kpR|K?IbhXzJWM55z>C;Ze=FpQ2MWte_TeU016c@fDrIiqy zXgW?PPRFFcm=4(&rZ1xrs@Vu3DiN`&O*N}Tg&2aVjK|#Z-`q6b-I$vmnJM+mlscvh z_2t+v%fmk{5C3bS|J8i&6S;GbWjgmJ8#kjQ8t^)F4HZ1^I8ifdU-+@FAda3`jlx?n z*@&%i_;cUr*LVx)f2Hvs*)qLzy$4Mvp1fd0Ua<++*(ifj0Y78mE>W~eaPrC&7izqU zM@Ac~F1dB~11<6HVk5re1O}NSDuJSt3~@L}YecZl_v_Ot$%Nh)(3Rqcp)Q1Q&9VAL zfRvbp9l8*NIjDuOYoU8$c(9I_e6ZjFfCz?IBw;LKCP9;hseADYOUV=X))j;quWZfW z!@}soPf)TcFu5?k2|s<}+nJO1XHVTvNhF= ze*lNaWUJz*R#IV%8pZo&U&&ObGtXS_d*;&fZt;UqWrCr01daLuz6xF~sZhSA!gAcS zQ6s_+Ou3w>fX%JUC~+h*UL+x5pYPn+sC*-yn8r+Y)CFjfcf*7jNqUMjIu^5p>k=^) z7DcT^g?c^vYyrQ+&uH^)!JOFFmSFtBbIJcb^5s8|9$S)X-k~{W_C|=PFn*Ccs?O*HU*JofI`M6YF)l3{t6NlTSX^pcJlV2zs&(lsPK{)A zL4G7NoGaVq=PI0GNt7fNH zWrzp|={pq_k&!U${9%>Al!oW{Vlz#_I&iKf99@lLlPy9a?I9=<9Lk_-~A*YVw#AgpbFJem>H(&e*tiT45JVM zkt0-*Oj$9DRMeFKGy$gYYq}>E6&rEJC5xg+qAHs~210jkFtwmkRi-L4Vt+mv=F6=* z@3izkZX#y==6o(hrfP3BCfzc3Zq}E)6WSRMd2!6Y4u8tVWQ`d$wD`GbOt&$u#?%>e z)R;e;so$CMZ%pAACJXTSY$o>U^eDjR0|p;j2$ct3E%gI@UMyaEzIf@mLf?qbh0yuz_`x%0$ ziDgf=`<2w}E+De+&MM7&BsEP z>#voszEtjiu5|IKQs3i+-iM044;OkL9Xt2XSogtf+vZHuTHsH*adoP`rr5H=oL)|2 zmx5u^K)j~pFv3ych`ibf1j17;;5#pYWhd#&C@n1D+9t|j^nT{34~>=7V|~L0o48R+u9F8&IdOzH!-zXIDx*dpEs3PLX1nZQc^f746~M_gm+z3 zn1c5%oQy?{NUtqmlpJBl!cEYDa5xW93v9~jvVGEZ zHf;j^rZ4Yk$csm7$7_-)E#Azrmc^Ho5B#cS4ql9_7a`PRz*qZX(AAO(l80HZwj2#l z!yu=4V-R;PLy)Z%g0TK6Ui;1LB=9FWH#9>HCsI8b9ch^_CL@ZErx|Z*>0x^z< zntI)x!N7>bEV{l0@LdTEvVa)0(@b4>GgB2IV|CR&1%PK-TJR(u1x?iYH>Z>ViTxM; zm+mcNuDbP43-7(lluM);m_Mx{4oAJQ?mGTxX^Q8?9AR==gwTm z)?C|W#-H{1men(z0H5VNRoqB}$c2Njt9CtTwP>1Yal*<}LS?`arr+h$B3UUze70XH ztj7O3!bJ-$*qqO-{PNhtQBZ2u$a=N0}RDnOo7L6W7p@mI(^wivBipo?T=Rc{I zgE$ltRPo>iFya*lJM#z#MtSnSZkUdTo8pCWiO>n_B?y3^r)*Rf0d``?77zVp(bYcz zxE4>hGX#b56Ha*5oXEA9uS@xUCVkph7vaj9h)~&b7L$8$wU!J)3%GAv_C$GOs$aD4iiK{P^FF%c)SMmJAW9N?GtB85RpB*^% zq0LvzhEn^Qxzj6nqyj;p9YHZOZO6z>aHJ@+lJK>J_G^(>84!NaUR9A^_2LVQOw}$h zRZ?i>R5roUqVB}F@51N!v>FrwU6CTjRi%Q+)i0s-58vsi33*Tx0p{YVbQi6ECew4% zV{_BRRP*l9qxV_-aVogwL-=#tH60xvwy<##hK#c&;1huz1s}nm>AA_t@!@j1vpD>9{?fl@&%Tjr zIgqHwuR=XAiZ3q{N$raD)fE;lhi=qM=8a8tYHC4Y+By2w-7HRqhg^mbBnkrw(S572L%7?C_fjie(%_X3xjUoD9r z=i|f^G&c&3OTEh>iS^UF(wsrjnIO#tINBwIYj%ThbQNoUmq%CELNF?`(pVYcp!T|m z_Bo;`0ujD%QwFPI+*RF+7?Bv%Ld3G#@d>Ah@W`@wR0|PeCEkC)yFI+@0eaYi+kXTv zJU48gDGd|;Ol9Y0%F~6bu@g%fH0ff3)J zM~5T@mz+VGldgyuI5VC8e3Mjo`3YS?3JBrzBLaTY7iJYZQPq(OgAifY6-fFpqz}Qb|AorYdjU10I1Hp~D)R)Nl6Wk8@9>xZGW5ki5B&MQ%YR&a_3O<; z^^c95ekXPL*ZG?#r^W`eXI_jQyN@Tpl1$w)7np{@goKCM#_16uhro!DI0%317Q{V;rbKKo9ct_#cK z`Qs?A`|%|fe27>y^7VbOQ!5G=U!E)X(c#Z@!OTrhB$`K$eVZo(=7SWO8%h%bFdSI{ z2TdyP6FRSy8F1n!h$*%Ba>%26^2J??S&W*#Ji1b+@bTv^r6gy*6e(YcNCK5Fgf`W_ zPuy15SC0s5GvWwMpCe7-sEQB~NibDRiHJ&N)0Y(5=lC`wv^F8HiVi{yoGl{f>Uay@)tfF!7|Ct z&n2^`IgIWagF>-!t%UGHHOpwgw#z9})6qN%GAJAn$`OLRINS?*ojNIcDk3RNGU#-D z88XOPT3e4!SUgIvbcu@6La0q`s)|pDu5h$IQ!~}EqR@n23&gK@Ed^aABnYd=Kv9ri zj?%K{zR}~$ay^gCq#NnZmKT@@3#pdE^+bte`>F znm`QKoz_TNJ8WS*v05S^Ger3oaF)h=j?gCnL~PSdDz;Bd;(Ln9VgAxot>BN#hNQyg zyfPcUn17+&#ic31GPVvk)vU^hJE`rZteB0J{6NdaU}gO2D#3GLBp;R}`7kH2$-=%t zKRo4wkb+*HkY>R2#Kg{gbzqPKL$e!S&cY;->A?#dTJWIUgZY!FUzcpzo9%vi?BXZm zH~&1DIz3amg%bcifsWu!w23FSj6aynG#jToB^9gq+DQ(*dcJ@c;Gbdj1q32pkpF8{ zA{IhT9!QAe*{|wInM!nfMgpcct_ZV-TuinT?4)X!0e0di>3+n%sX7E{co93wR{{b( zfS^^0dRhhH(x*H2OvZm~CjVl}pA-1xe`B)0oXh-bHh;9x|9#qe^DR#}bKK$#(>#$* z&_%Z(W8uYN5djFW!YdFUCf6287*EuK*K2JmM`cKzEC}ETZD;j~rTNAOY1W}&m|Aq~ z!uOlEr5DcU!o9aO{#Ob3zI=KCBUQz!GGSyszSv*5cRm@?3T8gghA!*L2a`=ZGpC=< zU-+PO{l6w+wbNr)ao%_*P!ok7ZkJ=V4u6*78AKWH_VkET)J)hWX1)t15b*B7Ad{XL zNlI~&;HVvRRW^kgXgO#n(b@`h3f@0|bDV zT9&8lEbI{S@Lf!IIuprL%O*QkauU3lZAkt=*rUyc7Ii%+1O>!0;&@$7U|AAK#bBibkct4xD+#7UfMYo_WC9#F{G~C< zL!izXupG&c_99Cq$qB|NDfJUB1D~%JNxcvx=B8yph*_C7nsASZIHjf-ai+wJgctbo z4SLs0gnbnWUKAthK2vEBDrSl3d~*?cQ`c7!8nu+ja5R~LfXhZD2f}yf5AW*7PT@!9 zF>RIsg7S^a1N=e26r_I@z=;$V2$)_IqtG#00Zl0z(X>R>S&`J;r6&QgtW3X4L-J&- zuIsAe%XO)7UncPGi-Cp<@uIYC&UUTBZA-V_Nx;ssk>g8IKnTqQ-;aDtBHIM@;#z#c ztR=jm5yvY*RI6~ACOcM)oqxiV{%DGSFxg*?_kRap5GLd~1?0ijkC6w2KusNCi-Q`* z89^JuA{JJafa6&ZJ6t<-!m^51R?_4(6%C&Xe?3`f!khr00yrW*7ZC&g(ApcHeUuX| zGImb2W+{|^?($QlX$(@Q)>K#s<;xZ1+G;t;z$pt$Zy+NUT#zDcRoH^1)w0NIS2aGy z?rR09aD3`zMd=b@pBYjYNjJ5un5rwGfz3zUE&RbNipiFJILXA3^~mvMnFip`8e3$5 zX!=R;=>@ucv4!nKj6|B1c9c_95=`YQp(=kbLM?klxqT&m695>FG;$66ArxZ#A&zv( z{TMs>0Pf0(cDKTh1m>Bghq5&^b z6V5R0H-+if)p~ioBmku~V-YJdg0XSJIx6G{1*S9xX(npvmlJ?FsHFg`Xqj~KfyvIA z`A0h6eZhP`KRz8vm)`~2Z!VPNd0a=-Bfk8mFDbOo@g*bl9g0Eg&Ltx*B2Czt&(z&n z|G;Xx-I<1Rgz#CJAr)0x!(L`Hgv*2r1c=R{?k zfbxAJ7?f|2y^ENHN_A!7Fvx-%0#y9Kq#1P~!p>db#p8&tyM{lx^Y4w|@jc%Z@l!N& zP|6+rVI=WTy*9WLLj!b!6{bki7+oH$1*h)w0~KdPgnb!xElg5b8#NwuiBr#)hE0kU zy`pF%^aMm$gRzRWN$>E2DKDG5EG0xj(Ot2(UZ$ZPAmr^6>oiMat-F( zM$?Vm2ggu3K#foX)&QuBrwWL3Zr~t<7O|c+bKR?F&#a!Mm)qCObgc$bO?Iwwc(t+s zylP#UZ(bo_m2F(kctv1^L7^tRs#~5U*jWymp-h@2BTWJ*o;jjId~UJ;+i^`25VLg; z!qIqJ4PtX+_mWIQ;}PkoH4h;IGE(IF>Q#2x@N?zUAtO##n7)|Mk=kztD&d(484*)Q zs-=99u}vO@a8xBkxM2n!Wx{xMU`m+bB-ma~tWU#W&~(;_<3fVKUHdBx{Cos&DxQ2W zb_(|e3V$@8r1?{7tC{O|Vc4rIN#Imd9%O*R^d)`TsRY6c_Uga`dG%7M2#yx#$Xa0G zfUXd;_F2ptQAc9R?^0`3>`Zs9#vN+$#{rIoAjKl#Bg3awNWtzb*Yo1+WZaZ`P2Yag zgA*Y!uHGd8H!cd;FMhAmLZDUxDuPZ9mtaINN?=NAYnior)(~EuA-uxSCOTIEuTaVz ztBS2PD23LQW6dkEvO>u_HhmeUL(^L&RjiVT_)>wYy3)&aXf8om zyOdB1)rioIv-YmRj~O35F^Vq(o>~s@xrKjkfp2hFAi}3PKKL+CR?T+H)D6c;^VTcp z)&)(WE2q}&Ro3xmw`W#ez$O_)&5qQR5+dn0MbfumW&BXXzI=66oR6>}tsQS)6|W`q zX3U|yF_IJEP)K@FBhM?O;HBln$wisAJ=0@-rhML9e%SP2Bj&{;gVj+i5S!m6^59T$ z=~A;1W<=5Ix>SpnRZ)X%RtKe{H#P7Ik^J(ld4~lIJG3xx_u&X z)XZEp1JChB%;m%mgqxQ35(|!>Nk1eRyI+$q-!;CN&@w3L)dAY3OSs<~$auYCUyVy{ zr3qS79T5{#G75=SRMednaQA!Q+U3NTw07Jur70fOjVJyo*&(NYyjIfGE5_qrL z8xdXyFR6x=NZN>i57ju{k);mPj7tnnz;l34jX+SMZe_BbvYM=0mTFivG5TL-s>|GX zm5vSNlih~okB;feBt%oXpbDw`0y3gXPIRR6r_0x6I*8EgvVNUFAmcmok;*X!9xLS+FwXa2pzG2FPQVoP3L^{4kh&L%SPN`wTGXr(+T{qV6%kmtS#4Z_ zcMeQLx@-6|H!(b1w-w;i|HabFpD)F^DB%x*kF9|`xM%scU4i=rw;RpFUKyI!Al5sk z%SpiDUYZY5AW%WTAlXFmdWGZH*0nDw?u292%NGu1JGSBQA%SBVfG1&2P%uE;`?=&s_Ksj*Bu45}U29`?HN&S?jhw2%s)kVrYav1&obyOiYeAmT+L~Bx4N?l= zLQ3)DCpg_jDGt16OothHi%ylTFUf|BQ}PDa;+(972(R9^PqgmDn|T- za{v;IN=nlj@rBj6ge^6Prxv2aVHLHEUXt`w0xwR|T5v9^SayD;D~Pce`m`4_tZ6)foyy4hB9Z_XOE`Byc*1df6`R+xGe~CLJP|FcD*`a6g(cDa`~1mI zBjVQ)^JeabnYm)7&d;R(W3+zF(AN)K`t#DEqqO(|@-PHh0=Fuc6^Z(l@j6}t*_bz& z-VMS02Q9@W*$q~*f!eO?n2#nEsJN>GLb5$yt;Wed`xOhmJn`4fUD#f@_D13Q+xg2c zB%ATC6=@ggK>;v<28glbnpe&C$hG#y5_054MSQO*etXxCcdos4YSr+m)x))`M^3HM z<7M^eh!ubxyZB-JA=u%PYN%ldqK8U_i!aPg{L#eTGUqTBK)s|(#_Q7Mhf$dX&5sfy zFG(Y&Hwqn8q}MmA@=8REpee-{sFWd_&U-+FGp}}3I0(#L^eUFUF0~*83A?RMQ9bhA&3gqE`T7~a8B%SM9lMR6`i`8(g1{`VOT34wX~r?jhhs(L-@lrnwh2=x-}#Zp;7a2G@mj$)MwX~x;EoC74u!Ya;-QjsmZsj zDz>lDQtrf2j58>Nq)06&p?oEzD`+Bn>n8gS@kQ#)H zF5A3n?ySxqHw5+Q6M+{N)8@Gixz@GAwQEpD>eh_Z0)i-w)))D$8Le9rYuFfX+!U)@ zOU>F<@J_J9Mes-JMD4Qt*(1~WU(AiZ&C`QF-TW}3LtZduRg`E^Yf(EsM`+dZiK<;u zrn?<m(o_`?ewVKzT~Y5Y6~5Mdv~S#(k;uuH7bMX-G`*vpI}I$P;(En6 zY9#`Bmht&QFCc&}U&g0Zt144^r3-aLCel<>>h5pEAN(?+{1!d_7Z{KS{|M}inQb-` zM@{kbx%}^DGyge$?XAn7FB|;o!FXK__7QaN(8sjYxKnC?IfOz4K{Zk)yVjZW8-pq2 zN2@dh&Tp9RUY~8QNpk&Q^jl?Frc6mE(x0Q#NIpP9}6|)E9cCsJjIS-;~fk$5)K-{iaWgN`#|L zAy6v^w?H+f2>gxsgDjH)`1C!OLw)i2c=KlX z3JUJix|#`#X>5e-IGZv*l>@#{+u7?}_imUyzdhIYOy=C9sg6Cd2Hfe`_0YJ20Wxhl z_`k081hDvNeOlC!Wn48E1De*CyZRy5QL%j6`gr5|L=zPdSnV+EY>hWbu_z=Egft4~ zr11aL8df1uC`5C?p-{SIL!tkL$-x)r&TpltG&ac$#mS-i39&McZ?z6y;tBg&WR1I2MtfDo#>T@0(+>c&?RECGH$=E#e5O_Of{%Dq0pd$> z?$AZO61fY>HaGr_@IyaZFZhGS5B>{tFaIOd7Bh9q6h5C#|L4T5pX4t*JA9H>J0n>3 zP+2ts2%?%G2z9Ium?Nb|@CWrw&jxd06VE^wza*JQf!Vi)iPSs)$)DsV+RH zL150TCW^YMja1U5HhnQ+`rf5iWu!|j2w^=|OknH6CB&NIILVIiz2U2IlH^`%L7JW< z1XNgLtfVjF{HhUB@q(nL$I+(G1pT-F;eRpXf1zHRo9><|9h*%3qBQh={`|A4_Pz0@ zO@IR0jPU*FAV}~B$bd`uaphUxJf*>qr8n7G!BGnW-um$5BYK_Q&Nar_|Pp`*K zB*OTVPoLhGyZmzQ(o4C^FXb-1nC#p~D<5q17=i$9L~t|Pvc}qsB*D6H`B#qt5#$i- z2N)!?bso+zy3+G0yZ8aYh4D6Z;rUGecheVMn7XhhI;g-!c(CU;n`p5D<{E}=d#Y(~&6m?If()+xwB?i`2`?nF+u$dq&2_Vc5jA(C|uI(53?fg+Yd9VI}(|QZltMpD)|w270tgAf97UN zGo>37$;Q%+U*|7<2vHt~> z0)fx7Kp`pl-iOnzn*?X<%7?K?Xsy$2Tk>c2OrG0L2p`RWy97Z_JWjyWfwKg@C&VS8s({$hu7&Vt4*&9CrZ_ke zuP8_^|t-Iq5Yh(CQ0KSxs?^B#wK7wNq{=2-E7aBKR*M?Nnnq(u2e3}yh;TXcG!%_+h9t1!eJ@Lgr5%?u0 z&YBulPh%IRsgnyWNf0LL5aC_W3!4ia>tF|#6YaZ`T?g$LX|O?o05>TNtb#_Hwxln< zoa+0|*oDU|tceTpLRU~OlN)K@HgoBKx$=w|e9c^Y-IdqO)n|y0<6>4XcW+KLugBgK zX7O*=idSAN_CF8sp>oOL&&8(;m!8I6EYqt8DaisFv z6q~-HazKb8)t(EXrPmttM(V4p7Ko5Fj>k9a+YDJ|#gNTNFm7n-OF|;!PBP@$8;HpG zVFbD^;DF=C7;!{iT$dUYEeSwtFoQoro9W_Unb77}xxV*OosTA(x5e?ZABWYb#g zvuN3KMHWB6A71*oDWlUAt4wYaQSOKtzyExU`m`X)P8@rLHY5CoVaZ z7LJYL6oTtuAj%XKG+kD0N|i6hML@M&Gi1*p2t7?E6ykzM$%#f3UjH<#ne5(V`Y28ucK|WK$Bl+N zg&+t7*NMheSo~lck~;lZ_QLzc8^0@D|Ib+CWdfIeobg7l zj%VLq!L8=feslfp;M2gTz(+6b&RDT;%iQ_RC7gyethV?yEo=Zaj5gTd z;N3QY9Y!8Hv7vj4YdOHtCYU~7nvNr2#m7DXA6oy=3oVL5iMCyMc0*5g8i6xw=X$ry z_HG{QSkJISoKOKwQCWx0VCmKu_=-L7b39&OPPSzGJ{+wBAn-Db98t6km_n}}ZQPJN zeQ@qPHZsVVtR=kE3CFM9)hV6ch-Xi!?jwMmv1{*)U4OT5^J5V4_T9AbnTDs)V zJtX)uMk}AE2!Adx_?&+%-}^}Z{G++Ehth4Ed9}mf;~>c5PxCq^)}>n3=Q}nM1i=v% zM@Yar@q#c|OoszPx7$<&!=O2c1{j~=HIJ5^3J z0EJR#o+St(*s(>xlks!)X!Ew@nIrZtwi$D&(;O<_^VgFV48VaCCLHnahXF&5r`i z@hR{xG5*jJ$eYi7TM-_f@28sAWzX!zf`=DBPvmLY^B4+{2M5u%oIRXw--;YUSRkDU z0wM=Kj>xsGpXuEkfRCRXL{8g4Z$!j#u;Y)5#FX!;kbGEO?fZOXDxr!h7Iha*PLN(0 zsnoLJd0i@|!s=ZJiXjreHx^%5Er9UjRGA3Bs*DQzges~F?Tv7xxq#(}yx0NLD$W!6 zeD0JFf{b{HQb&Pt!SJn&GiwQjxX__4-#CmCgcSlQ+>}KNwiV3hdmJ|!{tc++~Hi$ zflTL4$}moZfHp1b8GL|0uCx#Vbjo&YpTRo=lppm)j$EmXUoxh(NJ>*Jh?dqqp^{Y< zBg{&JVoLcU?>E(cL{gf5uhOEfMuac&+7;=I@X?GEUtJAW5)reiCDueSdrX=W5cO`p-I*T?Ovzrde$3_)w-&07kC zKOY}GiCq{ifv^ipwT%t_oPDjKfe7qy4VBT3gXP{mv>L%ZD+SYo?qAJ`G`-%wt=Nww zvG{4h-BIJ}WO%Mt2=digoKmPO|HW#;7%x4XF`^>p5`F46Pmg_#CE1%rChjM3+ zpFM=bYAy#dr+21Wv7-dkPDK4tv6H}`@mO6s(S%h{ruX%c z+6PByBeu$-5Fn^&6P`xV>%N)_xt+DvyW1mXdVx7u{1Euq(zYdY=0JY%?ZVAZ3b#HT zyYUf_2Wy`E;5%6VHUUOxod(#Ul@GwjB2Tt^KMtZ%vS;?;9cdf~Iq(7CU#h}(osEW1V za%&^xCUq&_h38ucdR=~~my3w0KuF6IP(BEvbqMh5Xpw=bzHJN|v>O642!IHxfR-YB zZAOSlZ$uZuSn2?FaNv_TeRyo}gQ>CK8FSK@6K494vzeckuD+7)IwhA{B0YMwFHJNj-(k_f3s1~O{rEIvX<2a==c)=LkuI=geZCX-*pzeb>f5!TU!RP(4Ywr^HTzw1 zdAx~@w*+y6&*H56l0PS-_Puy^nEoT?);#zFe*Z(}(k{~n{M^BDG6A}xO!scfwgEG@ z0B30Dbr##ML)q>F*)u>M0iV4%EXthT1sU2}Qo#WiqY&dyx@~Kw>yg6gEfjo({b&G` zG#7@1r%fSz0dTabgvv)oM*g>}K7mv^lbxHHHgJ^9kAs7A9j=8?=xsFY^Nr68p;15tpO8Yi~ zpdP^K+jQ)6`K4^{6PcceGF^MI@StrPmKH4=OWnACJzsV%$)(||OubIv(oRB{`S54t z$7bLe5&%X~sU(Dd#9Vm@W$yBk(%Jp#&VAV)96mpZk~{Z!?%ZR!vv?4O@(7ilhf%U; z4y8MG18{J??@GMP&sj3@R!d zBEaV^5~z^50#gUg<-O+8ZiBQ)iX@Y00)!Dy{~<$SzOJ})oTzK&hnV09A5@7qp z!Pq69T@()@vBAi-LlYtG4MMU;pm@YwK432GBY}$;h&T7df^w+o%-Sgd4i6SdfDwv8 zqLmu49i}{>*UIy}QnRGHm!6qY+BuSd&`YDH{41rxb}o4qG{Yhj(E{@jj~7QAoF$s@ zC^9ZL&+U-4xns0py%dI*^`njJ1$G?M_F6HVqTqLL2yFsMmbZL9Va6tFb)x-HuK!=L z6q%dBcf{~Z9Z7ssjDM!1(->gUabvzTQ@@|h{AF)D7& zgWvnI%nkA8jVS0PnMRyr@4+iT0zuQI8?td38~8u**4;oJDXE^vXYi#4z0g9?wbT4C zt(;3cCeCi9#ZTuBLKUu4?GA!?MU*+co0mq|nr&g&0a5{`w&6<+>9$R?_|65qs3V~x zP4Q05opiU(hd-$=3?S&%rzCL4W$M~T#r_Wp{T~$ve(1^%iUZ$ADO~-O%9T$F{U46? zeK&LFk#zeG+Gz^@bR7nEVee@!@1fay?Im;bT{@e(W7q#9NgTEhy=?}brTKgjx4g?C z5xXg#!I#X9e^fj-KcR<`h-dIQiU&v{@z5oc$+L_2=!Fa@s%O6t)kO#~ed_YJrR*~ltpy}#U=K323G58^A zY=3ux67_+({#|qRQFCce@WCO&jMPD>J4P5u06Ta+hH48e02wL_M*#sDW>Os%!0}Ga za9vHjbyxPnyA!EaGXu=gKP*V(XM*re`E$m!o0+es(myWrKZpA_(Xv8HvY?&nG)M<=tr;&L+AmuNp6Z`+?}KZt@gShffI7hF^R zJf-35WMHN?gITe&(6xmC=kzYdpPc~^2_n&2h!;ie+wc;gTOASp0JTcpc%Mh+r}HJ= z#Sv;ak}!l=7=JX8cZV3i`JdUY!?e=FDyVH!ru$JG{>)+d-M`-qzGx;#?~dCAt&Vk= zfv3%7UOd=z;ZEOAVEB#2^As&A^a>JzmCrsi@RUKcRsZIuP3CJe^akCPki=D{%k9^$ zsq;Z*1r}7mmg}#WGXCF(qZ>M(*+P7!AA1~lVam0^_H1wvK zs(MZDa#Y3h=Gx1AbIGm;3FMW=|3&dgNO)`gWrJuJ_$zeMa%JGj@Nm2-foUK!fojII ztB+CUvnR|Pe&}zWKU^2c1UI`F>SwGK4vs1#m#v(t^j_bOeN70h%fO-k2sn+&*rm|A5V%nfPy0{%`D>pWSZyvHm|~ZhX&7 zV+Z{Y|0`WI*IzaL2lxPr^Mj9d97ElF=bMY?6&sIUO6+~E9HdnWqFwlJ;wEjMuVE91 zqa^H@WJEgUcruV#HVE{%`MxQhTi7J!0apjt$QtB{1R4u1Z2GY7`bPe+v%B&z4MZTw z-eQqkfbToLM@F%DXxvB$(?qp}Af~0u&2W7UWRhJ^6>k1C+`p?WhHf*@Yrxc!t}?eM}zmN%{z{D}i|AkzW}+BAySq)+cJ$N!!7 zbf%3@wolUG_S|30>=$P04<`GW8N`NERwFuUM@Vu6C6vCrYwqICT<6yG={=b<`{-2p zG(ixZ_H^#TV!nFAY@n;11^F$iQ z&Yc+V;dIBYX{_H6(l>m+ze;zv++38a{|n*)df?8It48;i;LoeK#~<7$GX;Z*di^DH z6^AxB9A-Oq0`Tbi_fW#GJ#R*TY9?-XXTc!w2WSixH6>ZH_;d6&_vT&d#%Cz-M?;eN zPl4%d578qGKByIiKu{qFqMC??b;GpU*_b@@RN?xsrp7KCY-|_!1MFnJGB@8gR}M_{ zY)rSU$Egk@4=@KO44acESo5H?RN@TaMbE zfhnBx?LWC?V1`F-2M$$wFYRKG*@V~g zTmj&05+=jW>Jfa8pyNpH%8#br;1Inf=J3bSSoYw1<&R9H|77T=U;F5%?+x&$m7lBuf{vT9pP0c%7KC-lkz8 z)UkDz7C&N~Yl}JR&N&hp?Zx%NRr`kaUlZ}8#S72ibeWlwKkg`vJd8D)Vfe+q4@V#PD#5Oa-ko?VolvylH4i;xXXHt?ZlRTo z4>bTE=J1*an6pI)#vE=k5RKwp=(Zh&>z~a{oi%2N@dwYmx*314|7tZ;f8u2iZ>YUt zhM>lW9g)$xf6v^--E^4TeK33WNT%ly2wnxrLP&s!(S|VxOCwvl_TU|%QV*UPIY1-A zr}-+VBSD^^xyKAV`c2`_T>2=@*eiI?1or}CGS&Qvj63BUIsd`w2Of0+e-H-JDDhzZ zL+8(_=nVV^v`d$0-D2Z$HxvQ`2M?hNJ%3#YwetzNDI9;ac{9Nd)f<61Blsd%+ulsyd*wvEyvR3i zO6JB*vB!*j#;^m-A=rVt*-N{}&TPj{L<){XlorD7rvz>63I}jx3n7my@z$+E6M@s7 zruCWL=cn>m;oynzO=GSYgL6MTdI0{QG@Hz4W&rP6;IIn=_irWdp0Wd1j^qb5%U{_G zC3gP&*5o_i>J_Am-V&;cxj(zF+&?HHGR*>0gh?59;w=QfO;5^nDo--X^pt~V;P zm*(Nf52|N-rf8;fgaiMhk~6SV^)GuYz@H$neY7K(4}Y+gz;ogMQ9SbvCu4ADAtXG1 z7f7TTi)8Mjdkyz&v6p|MZ9et?2_GrK-eo7`8R^2Z36ew%BOK1kSEr%Bh~v|z|QQ{ zg6rG4vMHT4I7u7C>lrw5-$u*zD>egD7k1$`OgQjK0(=O6qy{2cJaMQ(m}6;2pb4~L zM@ULe&_7!jZY;FesZX?OyGidPd4hes-^zAj{e>68l1YskF;~?zC_(TYRL*HoN1EMUxRE{6`>eya7yMs-M_lg)K zB=V&KDua(vyhZ~2`C;XZAx`QK1WoveM8T60U;@=u31K<`RRICxuv7KV;*V?x5S0sT z0sO&-HI7Md;q^A>D-;r#QZyc)Bf)!JG%gW%mv($N-k>`R-tkec!GO5B-wZrL5Om`$ z60<5*EsH^Qr1l{!OwrPmGIQipllaf-$1f55p{QJzuqqpTk`9(}>tT&_<4rUCvB}mh z^ypl!!rY{p28QR%tpBoH)hlEObw~cy+<2Q_M}!wV^v9|R8&XM;ox=zTkO=&Fo&db^ z58#6V0`%l6gc=8e`;V#%T33GrS&!ph*;~6 z)VbI2%N4hKm^EW2uHs=9UHyLSZU8%YWyRUKvUl$C-a^j~APj?#2Ri~m?H-s|sM#8m z~SdnGzmH;zcZg4;~F*=LP)1`sa$7X*0?1o2z(Gi}zJ{ zN+2pN!ClXx5+4`Hg&n|@?VawUNA0-__z9gSDj1-|#; zQe+d0knm>jVS*-zK_#SB5eCV4Oo^mY#mYQFcQo!z07B)T#UBL5A<<>!LYEa8!w+{K zqQC|a*h6OE2}(}<7k{6lDl9eeG7pdkpZGMQBQ`%*alNo*))XNOxoQXJ#UBi9xRul{VO$-w348205!zN2$ zCzu#CT_-Q#NOpTd);R#Yv~b4p&9Rrj8dI^Wx8ObNxj+k0li@ zA-^sR8mx;d2*$}n(T1vVdR>$*24_EGIy5osd#|*wGD?WYkd}HpKnRcHi>i2wjTH`C z2pA!cXuU#LlZ{ZEZoIfjuf0HMhNGVU$=_6*_8M4M(5H{fb}$?-3>y+65&St`#Vv-0 z0m2jkro_y3V34nfj8Vtp_v%PN2)}wS0+R{PbKcGs<bDbEt_-wAI)OXMPDDoM-o;(IQGHf2PZ!_%~ZRIeL#`W?$5;&BD^>QzA}Z-CRxA| zF59&$fAQI|%P-_FK9dU|=ut)?90wiAo}-fMeb|*pXkT`E$1FCy_-GCsRSij)m15xF z7y=kZYH@5qtwPVCQzKL8V)g<^VRT59BXjz69XsaFngKBg+(Ie|w-C|GPr z!CFY^2vONp$qB0f-dnVwm$LO%o!yx?RRXb|CD-nufXnv7c{k{4-Pchp&s~PSRT+ zbkv3&4R5k2=dRFQhA~o^zPKmbwIkWS9XJCBLLvNdM4}yFVgZK;q!qxAL^}jfF`FUOiJx!}1{DeCn2jN7B%6XJWbG?r;^HH2U^Ww+mq#^($ z--Q>-VT6zM$rB6W59W+qT-k%brhi$b$&RXy8oJk>Fry3L4;C|rqgNU0@ZovZ1DM{l z{$Ul(p}5vz1_TdQ#3=dh8d<`nLYg8F=(<4>AINir4_okk&ll*%L<~b*Ku~$XHMvWB zArqmssahazeAmSOPxbFx0e^13VR1kPLW7manV|4^4p8LGC!FM?p_^~g4&n~q>X91} zd#=ov^akBE?76%oi)-@bawxRAhEqI(!Fa3U4;~p{fEXr?n$tx&lw2_(iLzZ)6B|yl zl@}w=)1?^{sFch|DqMavR80{G`X8ocGm|uh7CPj_=PWRXUfKGt9tIp>j=+vZAzBV?2c!tFP|XMv!WqFF>9WGxV=bHFZQI8Ne>^vZMGn3-hGh?S zUb5}N;%C@QG?|gN?1?wRqk%|xt`;VZ)J02#Cu#YP>5Vbpy(@p|`NF_!g)84FTzM%^ z5cFKG4-oXE?8OLh@VllL9>?hrmA)sj7Rq$(oWstDlEdi|`$5gFBLQeH2um~m%!d!) z1D)vZ6EEz}>bmQqHZ=_4XkZKB&k35bI9MPT5-{|?ciCF)C~??ae}>-B%X~p+R=CB2a>Ap**QOAWrYb6*RdThaaGKr{ zto$SVd6RA~iA{40LW;yMd}Shs1BYn8GxV|<{h`58#-04((HO>f<2AY&>9hyuJe(Qd zI3-rElpg~Uh%CKW9e*%13@~3C&Xs0E2+fI~I%WF8$`s;jllmR6*04(SFEL*}8G>d> zM>Jk%;#l6}g-nK>tMc&*buKbwp{Y>z3b2-IMO z(}pg~w+kM}8Kpz%O{t!zCo=eTAS`=OfIPD70rJGm>?M=_8C?!+xHL8$lz%x~oPii| zbb2!_98Yrk(q5b=7q7ip9DJh)2)arTL>sY7&*d*#2m;{bFFu8%Au1Q2L5=qkfy34j ztl4z&+_1)d+GW-AOS+_mJ^Pbp^t0;I6ZnH(z0<9VULen`CIp1iGe=ht#k>|i5#kS6K~-y4fn6pjqx5n6=c_WZ~HjbCQ`dBlTg z4OK_MIhV}ae{7S%hY`jBOAP-R zSuls-$fK1B0?VHE-Nl=D^Bl__K_2{G2Ve&qF4Q+o=_oy3zamdyU4#g1o*;=oUze|? zVgmX<3OShQfkN+ufn-R$+km-ti;yCCj zbL)F1^Lh0L?szpicY+3pQzINSA^(;3l_RMOCD6GWe8}8*nO1<`$RGAlSZObuB^?C_ z48b1@(OO(D%gkKfj~$9251#lWfkF&KL}S_0u_NBTBY+wYUhu|pjEWCF!a@n+{iPf4jNkgO zbmQIP^|t{*g#m(~v3}l&VK3JI0~w-KX6KgD-l|nRO@gK@_ulh_1N9M*8=?EtAN04z?^Uz9Sf= zi6LXLBZ3iYr+filJ=m4RSG);%sDPky+Ja9d!Y~{$&RAU95hFriiipvc&56?oN+ZAG zpGL$w2R~hi7kjR80nu*?f1t5o*+W5cBtf*^04eP*exYsCsYtU@#&IV5_GB+SQ6Bw4 zdE}Gvn;%3Vh*m)aI4|Q|s5tNnt&0X;!zw6qX7?<+-NnwA&j(FSG3#Ow{F%=_K6Y_Hfx``}r6J9aKUPIPro+jXYZTPZ zngr>GS}8*uCojD+7StF5@Nfk9Q|3 zrh5v5!bi`(xq-*>J%l_Kc1}lWi!+QZf-qFK17~&$LC~ZeyB4Ao>CDAfr;GS9g}h9N zD{_TjX-0j;Og7Lt^8j!XyBl{Qsst$kYwgcopD9-#mqwT(7Bq`}k7L_4k@%5?pj#h~ z-^51jdxdLnVii;zcol$y9a-_(>&3y>X?J$*jm)`+O0@V_^q74ETaS5f?TgZaCDdmLv3n_Ays)e23<3pw1y-|1~nt^Jr2L$iho^Itumf z6MiJhugcWkFk!D6?+53Lr+VW4eq5}7EdI!N5g~>U8AZ6MVOudg3&TP5OD6UcGl@lh z#UI{yiT|6q@d|A-34+*BU_?A>W_({h4KEMV)%?cr2Xhtp6PXo$ggOK!237tv zdzkhVl>ty-IyBCJ%J`R3Wt5PZMO|p>k{n_PPtJ>n)d%+X4TW|3C$4`-WaWz^A zJ~Sd^5&((__)jL*pJQ7 zGc+qCA(9QPt1#U>LB>SP5=TrCKk8))L%&RRY)KOM>;?pZpwhWZaYhJ&mky8Fu}e`1 zd`q`&1D(72#_R+Zhv)c9qxk6zlrBq;|K1FLhu1vV>~mm#O?O9_sR3*7G(Z`VS4WIU z)9N0Yx%P4?(OQb*U&;T1ASm&piP#UzBcG1n`e^*-`vN$?9Bj(4C<15v)(6@1kCo2j z8xt}W!yysVag^|xLTivV44e#L{WA|f$Th`hB6KSY4VjB}X*1|LLbGB%`*`Dv)<5_< zgR>7sI;_C`{;`>v~|!X5Ts&zbZ*-}Uo--3{8GtCi6zC%EDqGsTa@YHkmjq3X5MGkOApawvsnB$nEt=m%P9-YYifBZu|_^pf0rK9HiaVw)riFNN%i#@ zz7w7N58A&VSAWm)BNO{qT6EofjnEidRGVruiKlsMnpr?697(m^!pRBA54t?fa=%} z@kV0l{Qe-qARZ3e#vmE?J$mjSqhglEGt&j}2fZ{2s|By=5}VetN`he53)rVO-d{1- zfj_DGphzED&|KHrTKgU%i=lwTR zsY+47*ai&35AcIE%YwlemW4nJEVhAVvw>{Y2J*{hlT?vxYN>1zY>Xem56QM{$<`Tetf3>BrZ7&gnV#&diU2C) zZHgZW$vjilLesnOiPadchPD@1SO-F|2!Ze-$izV=@tvO?e$92bSj4@B`+TiTSn063 zhkw$+&xb>v%|$J5xtWmQ*Jn?eB0`ASs5F%Xm$AG_7(^?*+w+OvwH+#u@YWYFYp#}Q z;fjtRMdvAJ0Xlto+ue~Z*!E1Ee0BWGzpy>e@rSMQ{4Xj`xj#ng+IOzg*EhB>n0aIUh6polX~V9f!?uP(-3 zHWgh^H-k8wGy3TKsjW9hk1TgSTbcdk%IwkGo%e2c-dUM`*N^vbUA8iP6gP!#e6!^) zzGAA}CJSzarfAkeaN{NTjDcO{8Pmz@Pv`yCA+>pUb&uT;pyhZrBU}+V5MqdYqo1&O z*y(Y7r}|?qWDUy)^{2;rrwaBzRFM{Z@emAg42I{#h&=0R!sOFhR5TTY@O01mgYWcS zd)^kEZOLFfAJ77AATz-(a?BljeP|MsbtY?-l8!%u*FYFE2Sp|-2A1%|OLon*`k-H! zv}>`?ysqvkuHe!yCyn_rM>*RBAQ&kw4?*!VQZ|iN>>)WROWvz&m?M`-1ipp!ynTtf z^@TZ%xoTcKA*MniLZ$aCKuO78*>?Nf*0Dc6H1h9%iJIfZ=V5GMV)0=u0+ak^X)@ve zerWpm=3ChI%zsiWe_kwoRxIQA$71=nc3%2TF^hk8!}gMuhaod3nKtk-kZMzaMNqzW zj=hntiCx}yZ}icHvro=n`e3Q^`Rd%qtFuQ@aF(Y&!1L{wu7A8Z{;P$N*XK??zIYa! zpDMy;GdhZNlmwrX!I-#bxTokr0wW?aBaD((W|~Bd z3wL{Pt9f5>{q^GJzijlHt94w!#I@M1|FWukZNKfoN-*-+1j8jGfxd*o7tt#Z6tGR* zb{qQs^~Z3AmCK|E)*TP%E9-1_w1!Y73tfA7by?LmdtP$YT5LP!ocrPn!xlz_1peB#Va z>m`#$YP6Vvh>?O$7F^)U6Zb|?f`;ZVf3!IH+r^2$!&kEBFCCd5dF$r6mv0X5TR6QH z#pfRG16R@*!Bh=GEZR@aEMFP{2lb(M{h9f=7{`OHaB;EcL63cA0d`tnws}A?QT+iP zKl-e9{Gs-BJSYsm*?eF~JrwPF;c2^aLCs9p9ZVxq^h`1NR*&ni?-|b+o-l?=izCmm zG_n}+AwvtyKyKN1)>4g`{{Yuqt)l}bzM6>lpz)Vd!p#w~wA0?cu5bDn)?(lqt9nK~ktT|=n z@e&j(Pon+q(Dd=G3!^XGnLT#*#>Z>jkJh@syxaZoZui*Q+_AfJ?-kd7>Ui++N_MTP zQjV#2flpv2;Nwme$yWrp_JbsKsZ!dZccLot1<0!F@ws)m+L;S|)!pGG*pFsJyi8`TCkZ;8j! z*th-w&z$3tS%489Bi=8Y=CRhS31^N;y?izAcv!w5ACz3 zJNWhDdM|tszwk#}$jkUcnYDGKaV>^B*wY_*6z>;Phl}g4Sb0$iDp8^M?6gay$v5m9 zWsFp*P~c3I(q%cxNvP4(RWAk|L*MKEGlYT4YPDyHsF<$SGbDAG%99JHH(&Ykk%_OL zoB8IMDctk%`oj{``D&9L;P~0gk(DOaDAX&^-Lt#!QPJwmk=2=_e!Rchd1tkA_|Ej< zHGHM;DsJU@ZrhXEjJ#AUkRo$kS`kUI$x#=HJ_6OQF)3F0F|l=ey*-%vgXdk~{T&}Xm5`7k;2BUoY{7#pVe^Aq^sm@s=QsXBoxx7# zI-Z}52khV@s$I5Wn0Td_{j|U)XXCFs-D2`h+a;DMA|%|O!TsR@{r)1=pE!{?op8qL zXfBW-IX1L5vTge0Q!~Sdx+6z$%zpdo)K{CWyjTf(1SN=7$P1B*(!;1i-Lp^Qms7W| z<0n*a+cELR627xHc5rFz>byt(6FsB%Qu*k2o5{aL=? z_m^-Zh(m_+km2e4?O^Jm@E|Q|C>@g3pVtcXZt#WY`^|o0`<83Ck>a~4n_b(BYj{%P zi}nVD|L)x23;R-3W7K4hnoz+kcC#4MfxM>i6B6uy@+?ZIe3glg1SPdt#)cNZeYA68 z8#X`P(W59qGpC?rO_fIO~fUb-cxS@nPgG~!+4zg`=aZb9aiRbO2Z1H4N>Pe&ipcgQrmDEHS`%t}Kf1?k|}uLpM%s?ws6(OE8q6xr^^kf3wT3v#=5J666~p(3?8P zH{Uq77hj2CS}9+X(G1C!%~zAo%oaNtfZ>J%I7oa( zIk5c(>d()7opL?^5;h3~-2VuVQUqWq(YQsA-?ML^{-CNLnYc14i%-sTn#1_i9uElG zUrfDe-|k!Yjx_5J#;BZ)J_83{f3Bhac$RFoJESz{Nmn^nk;BMGbNkw*CudGPGIQqn z?#QvZk)v}L-o}o|iqG-Qs5z`cv!|X~xO8C2_dGb`$vO5^it~Ht&+lFudFCFzBp|1< zABjie0J3YdNm~vJ2jbg5hi&oF4Uhv-T(Q*_dobNH!QBJ zfV9W&|KJI|KllqD31MG>tCAAZ{{uX+blAY5VxazD|8u@yf>23r{#!BihSe5Sm@*=t zEtLragF9^|z-ITK*0~*oOF7(~v-*=q4W?|=@Q4rWfAIT)LA+*;_9%({ z7P#Kw;u4-IJpX4vc<|{h>LGR)95owF&`;ZgVt}^S3%8W#e&e-tUvUk$nq3{bX)**N zO$O{jaRX?WyS>sd`Ia?gF#Hhli zm=&#t&6=2+AQFv_ak1DB+O_}kIor?wK*#xF=~OXu)aMN94@ZY-2PAy61@EMPD3*uq z7V8fL>4Gii8=n^wKe45R#VAz3bN$8Q)*lKy4daK$Gwyge12t-P#q<+H3(R#$7i=`~ zbs!Wd)DvuM%2=v1sy2CS@nS4?Td-Kp_;4Tlt4i`Q7Q>bY2p}h1>@bp0;mbdMFA*bK zSNvY*75*6dq|IT>WW&$7be_Tz=h;pBH$? zPX{@X51PFs)C7}aJj(+4I{(b>UD)c_@9*rs|EUZFt_ASh?H7v4S2LKJL3$K362c&N z6h<>1k?AxbO}eBJgKSW{LE9Zxyy zIJlUHyA3U5fV>P1TCZ7d@jMw*#LkDKjBpeY>DZKv8%J#!|FIddDIrK6-Q*#AYe*>~ z66qpKP~6|97^7CCO=fEs0EkaILPG3__kh2VF<8b$Y>H7(#op&(_?rcIm0< z6I&*~+A@9e$+JH;lYj1aW@6B^~HuAG8mo!h@h^3d-ssskEQYE}8jtKYb zV5E+G23^s>DLOherj}AhQj?5L&{FS3P(Er=Qo1R1Jxn$6K%Khjj94&gyQ~giQsKZm zCJCdRllbg)fykF|lYkhHnuR0@k9ZIDWGbi>m!lfTN5i{IFircB(+iTqSqBUw-Cd01 zfjJpcOfsNaiZUL>CBGsfsz^&f1bP8a2qjz!WIVO$0bq7uzX4Q`$wNa6Xd-nsta(`} zBH7Wzps6@3Eb5&9WH5s?N5}v!1~FmsR40;T*%dXH6j5o1d9F?j^eW^?SRh$GS;!pn zDPU)Zq`Aa+g-}tGumC-KCKis=n>e>G4&6F8^xcIW-<=;?yfCyf^3=-c_Ej90cHSM^ zbq`;^RNyqyYBSnTbaqX5wKHT&7?iA{ZOY3#x@Jrz^c}gRh8I8x@$T!&GsJXB%hTz~C zW8ws;0@>_RAc+9Bpa^;#7rZrQtyz_i>K0V>FwVN_>k3qDCKu~!^%v;hOOH_|(9JLb zsg+sF#s-ngl!$gat!ar&$GlM^3NRC;A~>0O-$v~dQ1AT`!J3)%!zxVRmjx#?O95~~ zQKBTyJW3-jh9(s$W^*;GOHy5u6o+%0e9E&6=SU=hY&@-q3?MnmNMtiH$Y9+9Es%1xQH+ZZUUJu!-*Wia4)o0n#x@?Qn5o+ zN@fO=B-vZ@;?|Oj4ANrEbj5qt1+&JtDBM)3%cktpW;QGPBxtZSn;q3{2ER}ghUC5J zOM&E^NW};TLqdE70#1_2gg7MZ+LlKAOktfx5NA?xQ|uC-gq_`>6ip?#5Fe7#H5naQ zxa3qNzjGA5rnGExH0sjC^37ZPep zu{2e~#>~4%Vl!QjC8<=qO3NNKWuzht_ zQAD$Zlz?Rym8R^|b(<05H(x=f1S1PX*k&Plqw3cvB#m zir5;)WdwxiCP;FUK+Q;m>If_93OtHAQ}CkMh=H`7qpoNtqP+Yj6<3r%BC@*p6|J1B zdT-W}aE+k6oh8{TpL8KHrozv4r-51Ns#$I`1$apXUsb}V8^Md3O(KdtAl>Fmj{4i& zxL8dRO&(^y3ZTD7_0|lEABm<+lN06J=?8*WH`T+4;R#)WC!%5}NQzHMoZD42i-K;H z6fHuQTZs*dQMbQvuU_zZv;v5hqlHK}71=8p5j9Ehdv(<$`!u74NcT}e7bT;-Xc0{d zeY)zxIW(y7s0(PS01UppfNwhaL4q9dOD3#ku_z-NMiT9Q%cl5!)n&&p2NlxET3eTd zqeswX6MuRugR&qZOO`Sc&Ruc=qE)N{(q;OH$r@$Wm0U+4Mi-FFOCmzN^{zI+>p0Dh zTE$wKa*AFa;*g+LOIIJ{J-TQrniZY8py+wCW-!vKC}xwWg%Fz(j!eNw%-}l0XsX-? zC(nmo0LX9YC71{)k8yBUz%(1rkg+aUa3jK#-1Rmkfl`;I9948dIyuTRVhVu4sOrjvtVJV~ zk6rAId|4pDE;0KzV?vUovJ{|3r%f*rOlc%1fx0Q@%zsF@bj_^021iCn$FsbPDGnVa yT^R{P!VvN=U0F-&j tag is the traditional comment tag which displays in the console output, you can put + anything here, though it's recommended that the Author / Source Authors (eg; Cheat Author) names + are placed here. + + XML COMMENT: + You may notice that this piece of text is contained within XML comment tags, you can use these freely + to add notes, disable areas (so they don't show in the GUI) etc + + GROUP: + Acts as a 'folder', to contain groups, multi liner grouped patches and single line patches. A + allows you to enable or disable everything contained within it. If you wrap a around + -untitled- entries, it causes the grouped 'es to act as one - aka 'multi liner grouped' + (eg; patches that write multiple values to memory, but have one effect, such as 4 values to raise + character X's MP). + title="" + Gives the groups name that will be displayed in the GUI. + enabled="" + All patches are off by default, until turned on via the GUI via a tickbox, however by setting + enabled="true" in the patch, this overrides the default state, usefull for "Emulation Fixes" that + force the game to work! + + PATCH: + The core reason this whole thing exists! + title="" + If the patch only requires one address for data to be written to, the patch must have a name! This + allows it to show up in the GUI as "whatever title you gave it" and can be toggled on and off via + the GUI. If the patch needs multiple addresses it must have -no- title="" text and be wrapped in a + so that all enties are enabled at once. + applymode="" + Has two values "startup"/"vsync", exactly the same as the old patch=0/1, if set to "startup" the + patch will be applied when the ELF boots (or once if game is already running), if set to "vsync" + the patch is applied every vsync (50/60 + times per second). + Startup: is best used when the address only needs to be patched once and isn't effected anywhere by + the game. + Vsync: is best used when the value could be altered by the game, eg; INF money, INF HP etc. + address="FFFFFFFF" + Where are you putting the 'value'? + size="" + This can be set to 8,16,32,64 + 8 (Byte): Address can have any ending. Max 8bit value FF. + 16 (Short): Address must end with 0, 2, 4, 6, 8, a, c, e. Max 16bit value FFFF. + 32 (Word): Address must end with 0, 4, 8, c. Max 32bit value FFFFFFFF. + 64 (Double): Address must end with 0, 8. Max 64bit value FFFFFFFFFFFFFFFF. + value="FFFFFFFF" + What are you writing to 'address'? --> + + + patches by CKemu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/Langs/ar_AR/LC_MESSAGES/pcsx2.mo b/bin/Langs/ar_AR/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..ba54bcc53bebba601078989d2c1978128ba26874 GIT binary patch literal 6197 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/de_DE/LC_MESSAGES/pcsx2.mo b/bin/Langs/de_DE/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..9852dd0c6092222ad23ce5a03e6604eecacff5fe GIT binary patch literal 11840 zcmb7}dvGLIb;jG+fElm@wh1<`+$HRIg;&~@)=y!B^%y-^Jti7yZES*R&Gd}gn&}>Q z_h@#7O^Cq>U;>zghao&-h>26Ck}3$PPyv#npr}eJkdUMb2yFgXs641ZLS+MFspR+F zzB8JY_hGtp=IeX=KF>M#+;fh;bJ<1j@pvAEUI;Bb)$@*n_ZIl!`SB&5cP01}@EPD` zm*)6FP)&;9FM^}s)4@4cUk0B>`A(1_y>(FiH(WV!<)f~AKX@_U-vV9)KIFc?*M0ve z$e;J9tN#;F?Y{s%2mFe|Z-VOoeejv!e}bC-XQ0+|;VfjPd{|{V-VJQ-m~-Z zF9m;@;tL$U65K<%>hJ+q{|SeGCu79^Zm|%TJHwP*1Q&|`Q89NAACP3zJ3bS`acU^4}KApJbvoxFS;V{e+h^R zcrONzg2SNtKkB}J(v?3CYP>Ij;@{u6`o9OYo^OE~|DVBI!G8nAmusGz_d5iRQN9_J zTw{m#fzrnZ!By~mpvL(=sCAqKuLFMuJ_S4kGhm5#y~BA>a(xYm2)qU;z8nLm!MA}^ z;8#KE+2t@-;~oUn?*>ronFJ@mvitsSP~$udO27XQ)c*ez)V}@#)H=TcYCV4kYP|1) z{CPj*N9(y5p{oA*pxW&P*@|}~sBxAY9&z|uhjoV$D1L9b^1Tk<3~K(jgBtI>uKscG z1(ZJxir-%Yb?z=iNe+QypysWEl3N67ohhhwKLFkUeh9n}{0Hy=_zkcDJ_9AY8obBh z!{AFP|0VcK;P+hlX)I!i@-?8jfO9XT{6T~uKK?l?HQ(z%?RV3a?*rBUEuiG{5Ga0r+|_>; z)Or6RsQzCEwVv;|`tO3`<9|E+DX8)O&y_EJao+C|Q1w@W()T^Cei-CPdN+dF?*hot z@$Lk#2iu_J_z6&a`6ej-p8z$^vtYXTaV4mI8iymG`rYg>1~uLz;I-g4z?;BJO^$P* z^y7YT6#NV*e*6n4{rg`~>%0J?tNlI~ycK*tsCC>4ia!ld`%J)L@b#ejJ?8Lp?)%?@ z+UGYx+4Ubdyc}b#{oMfW1@8i120q~Mk3s3%w?O`EXCq*c8E_g@`9bg%;Nzh9^Y5VK z{v%NRpUMxf-pfGoZOP$lK%JMnLGk-xQ2Y59sQ!APgiZ34qHQr<3Q^8NU@}GgPru;=vwC!IM?mT0C&32zIZ*xf z!Zgi03f=`-ne*Fep;4r;$!;Kkq@K}?bNR#4v`0kx0MfI9bI2BmM`24!!52x?tF z1J(XgltAOW#Njm#uXT8f!x>QgU3TR)ut52>ASTQULCyCj@EPC-K&|WJ;6dU0?Sbxsu7eCDo?-g!S)2hcfmR_s0rXzzcc3>ybI@-?&xGCv>Hd;z^q|h( zN1>-fdbS~snzap*@9yWhRAkWI(49~ndNVZmYz-7z?)}g}-3IShxbhKD`nU=CkYxTa zbQrn^(xZFw($`xdRLon3Lg*T31>%~p zPl;dYOJq_<(01RYv5a;+n^@&KIolL5$Zk1czF}_ zBIqh;3c3)|^U@rw&fo9eb?(a0<*xiZ@U2i4ddSuN26z$l9Owqf@a$*F8EQS<2U%S!2J4cG+2dRx?XWHXjT2BM(f2et$M}fb`Y7;!i>oWTh2Cu z#4fSyXVr~>cI70l25D-_Nf;-r%qy-0tvCyeT}3|hN++Va6Pc;$1Jg&Qy<)}RVgZ%7 z6S0Cy=4Xs#x1axNhKa;q53Al}7^mK3r`hn6(2u;SVr{FI#4TRpC`;mIGe}Yj?T$Ca z$YB&_CJ=XFY0aA|ubE0afRTDT5=6B)@uvLf>dZ3VT)j8FdcWx=F;Xa3#!6<3(ZV<~ z`}Q6+du}m%j}E!!vG`Djp|+2yBfc)Xg>icdYEliFf+)_6-)zQJGg~o`d9m;=}=_YO=cYBa-? z2_mf`KdX)WP~~PpM^2hEAb0QdF9Xuv^`$T4UG;s*?y4V<=M%s5B(&?xfb4dC*^!w0 zV2=VC&Td*5h2)s4m&8KYzO64X*0FNGNfASJL$z6K=Eb3Q67cK#=@jat4x&8cYUX(kP~1JmlHnOP6awTIU^n8nYAT{4X{ z+u*HM;8QDX9`k0X#>~<*Y&H#t5}Rn)Ld%aBF^mG^_l&l+6IwKLwUfA!_^oleB|-5v ze(YQCg*Brw&Z2oUv<$HEEo)+2v9cMqQNj7h#7Pa^VU0e_3bq0h#Yqc=Pi5=U{e?89 zcU@zoEC#;Nv&|azN%x0F3N!80)WWpg^p8UvN1Dw8Q9UD%HTk!8?xiGw z^a3GDol-cAJEP{^IN8*h(Oxj5cDQqN+1)&Bj~k4M^s^RAnwwGFHC;`Dy2u?13e7+) z#|d1=+1m70JISVYxK^x8dR$MtT6Q1>x5YVQntMQXu`zdE=6s>M5%pOPgZ zR)uBCkYkaOV5BgSWMSQ}!sZtC*4}vBl_{}8-p3kH&QR{|j4;nZ_|AHQeA5(q9*n$M zKAR5LGVMms-EK5*cUKipR=&z&P~Gs41bE!JmtyZtogi-0exs!$i)Z?7FYLH(QZzz- z_lC@Fl3SOI`;<$$;IVJNhE3Gf_A9e$KHt>b9A+~V%*66tK@cSnlmqJb=g zyDsiV^j}zB-7_RhaW~Tq&)0@owcP!2Q=XVQJTY4`M@lP|`Q@cTd6_f89iT-GPvZuR zo3VojuN&6iO=k4a_~`Y+2M--QNW_SC6$>Y!)2N4sgAP(aR0eNib};OwCQKR7$Hm zEwvhAli^ZSjb-x2&5i3}R`3*$&IB9sZP$aaWfqW0WVR4bFH)V4>ah$$v6OTJj$M)w z2m10itYcM+ z?F27J;i{Hl*6Wc5nXvb) zz5R+VkS!OJczYm_J(006)`f3wiZekHZFd?;Sg+f7HG$WJ+%}pu_Lf(fP!si|=}u_t zYSQckGkW4%{$r!t6xV7nzE!y&;3|OVxq}L_wKhesy(l-AkPUPDU(Kq&$z9xQZ06AK zEKrQ>9p*;QW7mi^690;u`>_s9X62Gn^y`kpVDxLd)k30q31@Hs6r)nbPYT!ZkUFVj zEgtv8I$j`SM){o59o(oDSp;{n;S1NDf3t z{ixV%YLofsjlk~EbOU^4bc`+oVbhcCB41q|`tCsVJTu`JqryLDryY4eA;dn}>XHur815nZ6&=_Y8x~%%DB}M{9&|08Z0l;>iJ z)>b?E)YHT#(X^*}XKgyDYiDh=qg;bc;8mhTp0%#I-H_=YWZ1k*DWq0Hmboi^4~N(c z&GDOr^M0pJ1l><8m`>}oVfuVea*JoP4Ea2J@WKOA(R~*+l9R^+JIQ1q=WIPqk6~$B zIAfjTHkMtdo|Hs{LG0$$6&1ioix6p<~=_0Ztr{)x=J8kQN zXN~*Zu_tpO5zLe;W+Gz!Y-{_(Mw67Q@_O3bU^hCt!LSfYW%$wd$<$f}m(LiG#B|Wf zm_->4IUlpgl+=o9l+-wp+mgAM@|w+S=*w*Zw~dd5(q>y`metlwjf>`VoiOYfW+=hY zNaEuxE7u`n4y=te?fdD*Sm;hhV!>rRNOfrzoAt17j@|SbW(v!Cnu{SW(}QZCi|=H* zwPJb@*CPW)moX)47S+z3A?bTI>=rlZ3|SJgtTNR$O~Uee5<}-?o~L`+Sdt|LQt_YW zKoVQpG#2@K*b|whfV>^)66lM$CJLzxT=}=09~2vJzgKaMnWk=WEp?n4n(BZnGMVCy8F zm}2WZ$6`OjiQa)Ai5C$BIfsTEoxHhI*>;|7IoD*QSk5t5@9WPom8{z4j?+#kpSx9L zWpXXelQC$P)zs5UX5VDurz1nS)5x;#n-1*9o)F!*BSvj@>~`+=#HeZCtIM73{sM}3 zbdpomP2!tvOx=PsTY-x5Ha6W8Zz>(MnVEVg!oP~6{QAb>;<6@_94ST^H`dg0mU_N@Df{mnihj1;pJCt}0Eim(lf4l1^J;NF# zm~O;o$=J^ZjzOc|<4r5nV>YPnE0$l7TkFzcL>lIWLB_*&Xd``Ie`Nv5+;Sgs| zHETEmm44>R9viI1Hl_jf`zJXySSq}l)F!UrcCHnqskS@yQ`Xt(a+NAoEZ#C>X>LVA SBc0hu{TBKXCbd07-v0w{)hjpv literal 0 HcmV?d00001 diff --git a/bin/Langs/du_DU/LC_MESSAGES/pcsx2.mo b/bin/Langs/du_DU/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..47541b89cb8c7c0dd7c3a47e001e1da7a1e12a94 GIT binary patch literal 11583 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 m*MQD8vP5+DNuENo>})+r*6J=mvu;-tG1 literal 0 HcmV?d00001 diff --git a/bin/Langs/el_EL/LC_MESSAGES/pcsx2.mo b/bin/Langs/el_EL/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..1de54a1232dfd4db9b180817500212cd9ebd5c47 GIT binary patch literal 11225 zcmeI03vgW3d4LZwA)q8AJX#3kah$|!J6N(M8v_at%hJkLkStXznMYD!wYriPul6qY z?pih_Bq5LxNE<>62}wz4nv$WDOgob_NtsSkW1NEH)~0q!X!PhJFY;=4S*^6PA!9N9 z{(Fxe7B0@TblOaNN58&%9``){|3CjZXNS){{UOEkIPzYk`K?Ngz&k4V$MecNmAVkV z3eSS)p6&C!P^tvr@4{;MHn`d3x4|<=e;m@J>VooppGi9=y~CvMf@e~GFFYN7*_1zQ z${&OLsmD$J-$1GVQ+N)1#_(UEe4mGJhb1We&p;W^l6U#ztbme#E|hjIgi^i~%J(av zjJML1Uk2YndV?u%f#;HLhf>diq7NHZ!Q0^n;S*5W-3LX#2chU`!tfP{YL$Ao-~QR~ zLnJRYyap~M9WlJem_Vz&0-#?lBLr})^D=6*%8{7cLq3Gq3-|@d&3u{PU3B|6q;U}T^J^-+u{Z{y%~;ufK;f&S#*E=bxdpmx27L3I54=&cvvae-V^= z%OF!xmqTf1i{Vzon+$sl<52Xy-K6g@yc6@KLw~{sOLsFTh@S7EZPt-e&j+{4nWV@B{EAlRkq%Y$1IK z)TgoTAwyAL#|YwYKY-HTZYcWs6~sj9C6k_kqVF@`=hr_6%D6R@{1t}PCcoCCH$q%b zU2F1hfzn@}DIYN9pEl`-48H*xy7~^JYxR`LAAz#ok3i}F6)5&l@AuPZKpFqpQ2gjU zCVx2;{jN6U>!6JL8Yup>8A|<5D1H%vGVbkA>~TL7yFCgee(i(Oe-X;~jzQ`7e3UNv zAAsTy%c0~~Ly4DH8r}jWUfyl^xXFLUFmL#7?f1715-QYnQ0BW0$~bR>GOxQ~6Z`^{ z@`F(3_X3phya>f_#-Z5tB03j8t%g#*35uV#LR?F2GrR|iUwqT>M<##2Vb*X7N)dm0 zAC&s*q4@0VNFV($_ZeZ2!^iJx2mWt{||=<`M>^Xi6T zmwqVidH{|0l4A{C|Kl zuBv4|uYwXUn_&!I52e37Q2N;quZF*bZ-EyCe7jv_SP5mm8=$vNpp5$#*Z^;X_3(#K z{Os3I+Pz@8@2?t4{VG@ouYqU4&zSssp{$ojpp5GYQ~rG@{XPlBkM=-m=a-P7sw@b_3&-*M#C<{TMZq<+u`Zdy9=HPKX3Q|l>Q%q;)mac(%zF${O~DQ z1BaokyK`15wGM88XTlVecJGAZ2cL!FcMn1FyYImzFay`aEc_DGAMwlo+VBX(q)K1n z$IBp;v<0`o``~FXfyi?s(ut&yKSORn95t-BD$inCIB(66ZHyO$tw8L5r304@(E<|BfgPDZbd$h^dNU53!m)^68+{~V#e&#$IJO9u@$}**@lD> z%m0ql^hf5H7KI}tX1@AKNYhW94o=IN-zko!LFPps2!PAj*kULG@#fE=jSO>2} zHX$EG{s>w4RGP#$;1`iUMRu6HTi}KAzRa!FLC3Kj9kavT(Rix8g~P>+SwTI2rAV#-hocx;g6lb?fbTPqbHxg(=5Ufd;E9MNVTh zMq-l_PV_}1G_cuSyM)9tA^*{Qg$Z&=;1 zwLt|!;q43{WT)bcAe0OzX~~kT{6a9q^~y0>>bc0Vt6 zJn7i6nB}-65-C+r%h7l=sV&hiD(zPFZJj!luu!DDZMEXvwxjC9@#RTR`Fi;>cljzk z;MiE9EmRZK+i5Lo$MuS3JM_}4^s*f*O?6xJ(1Sv~Z*&jl8(_95ZfS*7iC8f~+)nCn zEM`aarjT~TxLv899?OwB$#6_2Fgt!@E-Y%3J8L|ddA*&Ab?YrOB^E+wTN`v+EQKn) z&OK*YRHq@h^@>x~X}s=KH5l_L`f00csQwM=)SRkLsIBvqbvi>EU*Ak3rH#Wk1gz~> zD4F;oqc?c@sc?*%j-^}dZcDFds9&iobxSJJr+dO~(sD3NQrq#^PQ5)Gi+1aQXtGbY zbZiQ#h7_Kyf`J`YB$c$}C7M*hV7nEe1sx2oZfb4Qjul}!;t!5q5y!!FOUw1EL!sbG z6^w_wa1&XNuFV3RP0ucvV7xaLb?G23qwv>iufM4LupmoLJZFL3)rlnwti7mY&c=)K z=PbJ@e}O$;UovZSJ59b=EQ;E1ml70fRJlsKm?6?9 zxk+0$iG~u6#eegitU@W2h3G8#le&wHDFVa#}piD;^knies>-wQD&8QK<2 z;DSwYZ9Cog4r2_XENi=^&DTBBhRa~k3tuJ}!wT{Jl~omu30HSV z-9#+BliUblIO)z+GT$X_yNZsjIE!IZXp#OlS@aiIb9>7s$FjDm%~qFV4XDl0-afTC z6*nQfsmD`;HzpM65?)1P*ev1)%sw^)v6g2;ca@aJS&t}JR#t^-B63RX|5!K?j$5v! zJiVZaM%#(Z%@b{$pamW6K|{8;+^ZB8#{INs7fjic1DeUU%M8w@uL()x#o#aZj#TwAw@>g3t zI~g#8IwrZmPG}p$(r?)H#w|?Pt{WwyRH@c$m8{oArXZ_kaaMik`WhW<>8wy*w>q%V zu?Ji~$e5hQsB|UUO&f#7LTts%JDk)z?UWwCGGU!^@nv1#+Sur=xT?7~7gZ;9oyj8muaG6OvmX{dQ$SH#u+)hRhmh59Sx|G`Z zy*Oig3bVjaWj*mq#v^fYks;)mV=N!C!Va5HFKbfAkKbd{)sEZI+86YG++@0`c%i< z96CB~Xsgv5y)%opISuv1I2Cr_$l@s-eNp^U4nfd6>ga^{4mo~V!at=rmiPrm6nApb zFvl6GK43fBWX;H22&7(fZ}7?D>d{24CYXqScH3gjZE<@*4@f7tiyX(SikKxT=MdP% zVQZV}NIBbNhMj@XM#c8D$UdF^Ud`8i;m9_L<;&btv>j(H{+W5KSSy4&gr6Ktfu3G5+p3s(GcKl)29r&BqnB%LTx zg<(n{Cn7mkRYjeXjP`^hsJWkb>+N{#l`eM${~IrWvWEQQP8I#ELGO&m@+VDV_5>rR zS&DUvZJB!2Z(Oh1uXl5VldPOoTC7N4c&o*U+drjv`=+cQcGI~^Teh~GtlZnM?H=vo z5pwSCld$Xf(Iv@#%BEbQn0L6Fm?+y@gkuBh2*=%+cXHOvogHE~KjN+!;HJ~(?;S3l ziw80g_BwkY&iBo&9ZOeAq_~ytDx1118MPeuYjs;){k3(Qf_iJPJ=D~?rJ}8sHNhSr zgQ{%c7*MNg)~va-QvR;c)oW|3*H^AtyJig)E8DH@QEA20yCGQDUfI%G*-)o9x7M~a zU2kVE%olPIkj;E(a(lo_@^Xc)@^b`sh(~E|Gs5JC)HqZFY3tNeQ^*#97l$Zav z$BMM^%#f$DS;givYW`IQva6JSQD*O5gP$r+=SBxh3}F5q{CpsjEoG<5!zEO+CoqwD zIa3-f_=!2(WZ&c~@~-ijl9-j2y^Z6fcVw|+E?toM z&R&z}9mV*GC}q**cfm#J|NI5nXz2v|zVS_Y-_Vib;o>B&J&`NU=mXQG;X-=$!hE2Z zo6)1CvC(4bILn}@)4ANB&L1xnb%s@0KCbf_T`n%XI3Efa&;N1YWoh^gug=Fxne5<8 znQ}Tie}Udpz=Mku#gVb8F&)@jEKD8GvD{9~o?V~2Mn`kvFMCF&yje_@iv>LwO48+5 z%fsgG`2W{x*^}8z-;`_hkA2&|IT!2w+415in+Or?`E)5gULKQ(CT3;hn8=NlUYjc8 zX4y%dDU^%3p-DZOO^e&5y%;`(H%^p}vjgPw>66~C50qY`_VaU*vZxMZO4%a4Et9z!*04L^Yu0(Hs{Ppf%)e%qv_lXVTPPCiZWjo zXR4HJ;%T#o>*^Der@FxBO@Lcr?(p;BY)nsO^x^EpOlho8oSu}Md}eN69GYCE(-Y}z zIWt0Tx{w(kA1O#klA(FW&6VmOhl=KUx7T-#<7)N=|M|NdPCD-y^F}{DRTS@?A4pLj zo-S}eDyaQ?|I>GTF~!*E7(2i0k-w$ad^Q~8SjAGgh(8RyB*&ct3se8S*Zp0EbYY02 ziuR7Klj^zRbbb(DPpjuRxq(pS-fY1i)=94X90QLGk7uT7z%zlOy_bf|;y4Mp@#9m+ zHTx%F2Io3f$Q~wG)T*a5;`k@VC{|OhI6Cb867ckJPR4XJJwBAf|GeYiqCE4ffZ|BW zzFBQpW4P9Eo#Ca*JAghrg=>3}wm3b;(RNTBnxEeP=3fI2j^#5WsH9f!D(J(Rf_{0Z zByp!aA~AckH24as3ho5n)=|{snZj{(s5o63mr4H5{T|@O1p*xLkBtTUvYX^5(jx?* zg3i3W+}o6jGYftecoGjW$E@XZyVRJsN%8Z5cOdijo%9hR6>~S6&>$BJ&1RIHnv$bi zx~gJoyf{5Ea+u93KT$0CmHo(@$sbJ@hD~Ef*z&x1ydXX;`1v5S@OUP%aKR4=-nKke g@P16l7Yl=j)6B#C?C_g?SFO!=bH5z?w*9>D?}JDh2><{9 literal 0 HcmV?d00001 diff --git a/bin/Langs/es_ES/LC_MESSAGES/pcsx2.mo b/bin/Langs/es_ES/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..d88a28cb79dca85584f1539e07df164d2ad7b303 GIT binary patch literal 10632 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/fr_FR/LC_MESSAGES/pcsx2.mo b/bin/Langs/fr_FR/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..113d30e1a514e7ea937adf9f5b9f6f020a0559f9 GIT binary patch literal 6176 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 ODR#E&oDUj0q5cQ(6W*Z! literal 0 HcmV?d00001 diff --git a/bin/Langs/hb_HB/LC_MESSAGES/pcsx2.mo b/bin/Langs/hb_HB/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..58bcfc6d0f7031218bef1ddbb690801405047be6 GIT binary patch literal 6302 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/it_IT/LC_MESSAGES/pcsx2.mo b/bin/Langs/it_IT/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..4f929ba5646ddb889baaafe00900cca1e0c6ca81 GIT binary patch literal 5411 zcma);Ta08y8OIAng>exY0VTarH&h%VhdS>kI883ur&FPw+a!;RX z&ZTE(B_RsNn8<@B1Vel<24hGFUJ^xPf|nRcP(w_N#AwWl@kKEaAB-Cx^!J^vxh%%Z zNmu_))v4?EeO3SZ?d2Cfs(98&?7HA+1QA9x*qJg48F)WvW+@F935`9~l>^#p$- z@F^(uo`KTz2OR(%dMN!)z}LfL zkgDpAP+o`p)II#k_coM%?+vt2=IO)tGf>)p99{xH4G+M_pwxQ;PQkB28TXHYe}QA< z{{}CGnn8pUQ2ILoFNgC`)_X6M`FsS@M0MdY*oSY1Ux8wWZ^P5@IVkl{FbUxtly*x{ z=JEbeejk+nJCG*IK^Z@TQvYM{2z(f};WJR`9l)5<@0IXocny?!v_g3YQdOOTVwV9F zyF3h~-_JrB=W!_geF;kar{LS*Gf@2aLMZJWrVe;Fs3!j9e@G>STJP!2*N*O5r_yk6k{yqoa0>1#I{A*C=`+X?u`3V$z z`~u2+ejWJxQ2wXDze0ZM9Dma9MRX?Xx*W=SZ-CPN7AW=Zg3|9&C|?cv`yeJz9Vqqs zQ0(y_l=h#5EKNNUzCR9So=*mTBb0v^O1HQs@~=bb=Q~j15_mXNPiNSG_ zJmQb5$~UE!19u=A_P&r2Ki|3Y0ZRO>lHNlSA2moj&voHt49YpSM!JnuCB6DtpkRq4 zaVF0kX|#OX`#Z?1=!e9FJa?1kNq0#`o=R=q7y0=3IB%VSNg~@(m1*DWo7}Ct*yY=L z(PhI5(>~d7UHL35QmZO+sp)UJC{vYr8~0UZ(Inl%bosLA4LvRTEmdi_EK-%_zD;y} zaaPZ|nD5K^rcKLnS5hC@EYmBg^C<(WO4IgyZuN{^FS=cqFl4hx%0E3lb9iQLMpas7 zKqoCQ$)E@k*H9oJH`?jm)vh`T0rCQ;KXtGd;8frN(Wc%oS#DFkUgX**@wOhA*md-l z%QtnSJ=an*MILRcdgZjsRlVM{5e;>{et2PdMW;5x@|Y*p2NUM08;uVfZnf%Ts-Bqj z*lIC-<}u$+e#OumORp#0*k$ya$l#Ts<%agH%Sf}P=i+TOYfX;dGKCLf?GlX>G-LKm z($TR?tTt)4=-DLC^oCEh$7f8VpZacUdQ&t@vs{djr#@zyYL;S4g!Ei4ei~+5r(B;^ zEhO5f9j23eZK6$Q2UaIO?P0o1ypSCl$vmw$q>qe|tBGMYq!CAeCg(K)hOcJVZ_v$4ilVf>0TKR;_0!GauuxKC%Pj6 z6A>_n=i6e=C_99=?=KwA(ETVoeS~b5n=~I&OLj|_epO4QwE~z~4X5q17Hh`5jBD@~ z1{3yumN`OYT$Nqu%B+)062B|H43QO|=0&%V74N<3lTFpM8_Z!7Z)Uk_dJHM%X%=({ zTh-}J0)$qw^}+;O)}+LISArmsKaP!Pb4s-cWFl%`ptNjkqg*$l4j*%U()mo!u=*(X z>2_JP5*O_C^GeIz-NHQ*+N~{1C~T_s?nK&HOcvI5{VBb$p|^dZJ3blB^{K>f>8(wZ zOYCiNsMwL%%Cuds*V*Q$RJ%w|NpEYbnmrhHT^4NY`?C8(NHW{?ZQZdO24_qC5Z*0W zFBTu&3;NMR<-X5ThgTU{B9(|p?f6J7&E1BH2;UxINSD|OYqQgaZMI}XQaC(5#u;Y< z<1imP-1+;C2HBW=)C+D=W9#Rfl5>DkrAMZHvO)b;K4Mr~p7L~UlKS#P!Or0P&O zs%^_bqZeySbE`79+ZPv4#BSWD-8)Ab3yu2T>?g-3MkK&6VYR*8XR^6Hoge0`aLH{t z+B9iq^E;;JYt2@@y;oCavtiR}J&AmWGiyrUy6*B3+((i7jY>QTMXj^V|4~9E-Vo-*%GJWs(CWA+SB4u}(fkOvX@^8xhxn-5x?q5m~t_Vfwbk1CbY< zEh8P7C09pfy&`~(T1~p#?xbo^S?W5|@3U1XD}{Erz$%g4^J(*&*FV9mFMX%%IoAh!o>}ja5EeXoEK-6I*k4neqhd1U>hXZ zavrzY3~tXjJLVl~u{*5ylfK_81NG?7fOA z*KoB@6I05vL5}Iqm#R$kl!B~Vw%3ncB+AUT4>KPQ67+aqm}R9jmw_glEWyj>7|JqH z6mbQ??50#`(dGSRL84VSS5W3|;@JePfdqsN^N}NCV8Zs#92ZkR#T*IHgea6S%Z$#V z)C~xck=U?jOzicbkP{7E#u`mGl;mNMpt(c4Tg{Q+`{jn?XdqNw55vmsU;Ov)8okQF zOB3#1=c_cq6_rk)RTSw0_nvP5pDiZUzW_W4B?kZi literal 0 HcmV?d00001 diff --git a/bin/Langs/ja_JA/LC_MESSAGES/pcsx2.mo b/bin/Langs/ja_JA/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..a8a4c5e87e8570439585ce4d8b22bdb6e3ceb492 GIT binary patch literal 15213 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 C8_nzh literal 0 HcmV?d00001 diff --git a/bin/Langs/pe_PE/LC_MESSAGES/pcsx2.mo b/bin/Langs/pe_PE/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..b0cec5a54a53bcc6769b0b065c27e9d423eb89fd GIT binary patch literal 11165 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 BIPm}g literal 0 HcmV?d00001 diff --git a/bin/Langs/po_BR/LC_MESSAGES/pcsx2.mo b/bin/Langs/po_BR/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..bad7bf6ca21b1cd4408f8d07d3c0d3da3debd6b9 GIT binary patch literal 11024 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/po_PO/LC_MESSAGES/pcsx2.mo b/bin/Langs/po_PO/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..752871e7c843d6a7072ecc84acf67731a5dc874f GIT binary patch literal 11385 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/ro_RO/LC_MESSAGES/pcsx2.mo b/bin/Langs/ro_RO/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..bf318427d371b7e14b6c7848ee3f26f393d4db71 GIT binary patch literal 11443 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 E0hxca;s5{u literal 0 HcmV?d00001 diff --git a/bin/Langs/ru_RU/LC_MESSAGES/pcsx2.mo b/bin/Langs/ru_RU/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..ee50ae6b15e3bd4824b3fa44bebc77eef0f1007a GIT binary patch literal 11125 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 literal 0 HcmV?d00001 diff --git a/bin/Langs/sh_SH/LC_MESSAGES/pcsx2.mo b/bin/Langs/sh_SH/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..33b36e000c948e93fa85f58b5b8659669cbe4f12 GIT binary patch literal 9723 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\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "%s: Error loading %s: %s" +msgstr "%s: Kan ej ladda %s: %s" + +msgid "&About..." +msgstr "&Om..." + +msgid "&Arguments" +msgstr "&Argument" + +msgid "&Config" +msgstr "&Konfiguration" + +msgid "&Configure" +msgstr "&Konfigurera" + +msgid "&Debug" +msgstr "&Debug" + +msgid "&File" +msgstr "&Arkiv" + +msgid "&Graphics" +msgstr "&Grafik" + +msgid "&Help" +msgstr "&Hjlp" + +msgid "&Language" +msgstr "&Sprk" + +msgid "&Load" +msgstr "&Ladda" + +msgid "&Logging" +msgstr "&Loggar" + +msgid "&Low" +msgstr "&Lg" + +msgid "&Memcards" +msgstr "&Minneskort" + +msgid "&Misc" +msgstr "&vrigt" + +msgid "&Open ELF File" +msgstr "&ppna ELF fil" + +msgid "&Other..." +msgstr "&Annat..." + +msgid "&Patches" +msgstr "&Patchar" + +msgid "&Process Priority" +msgstr "&Process Prioritet" + +msgid "&Remote Debugging" +msgstr "&Fjrrstyrd Debug" + +msgid "&Run" +msgstr "&Kr" + +msgid "&Run CD" +msgstr "&Kr CD" + +msgid "&Save" +msgstr "&Spara" + +msgid "&Sound" +msgstr "&Ljud" + +msgid "&States" +msgstr "Sparpunkter" + +msgid "*PCSX2*: Error Loading State %d" +msgstr "*PCSX2*: Kan inte ladda sparpunkt %d" + +msgid "*PCSX2*: Error Loading State %s" +msgstr "*PCSX2*: Kan inte ladda sparpunkt %s" + +msgid "*PCSX2*: Error Saving State %d" +msgstr "*PCSX2*: Kan inte spara sparpunkt %d" + +msgid "*PCSX2*: Error Saving State %s" +msgstr "*PCSX2*: Kan inte spara sparpunkt %s" + +msgid "*PCSX2*: Loaded State %d" +msgstr "*PCSX2*: Sparpunkt laddad %d" + +msgid "*PCSX2*: Loaded State %s" +msgstr "*PCSX2*: Sparpunkt laddad %s" + +msgid "*PCSX2*: Saving State %d" +msgstr "*PCSX2*: Sparar punkt %d" + +msgid "*PCSX2*: Saving State %s" +msgstr "*PCSX2*: Sparar punkt %s" + +msgid "0x" +msgstr "0x" + +msgid "About" +msgstr "Om" + +msgid "About PCSX2" +msgstr "Om PCSX2" + +msgid "About..." +msgstr "Om..." + +msgid "Address " +msgstr "Address" + +msgid "All Files" +msgstr "Alla Filer" + +msgid "Arabic" +msgstr "Arabiska" + +msgid "Arguments" +msgstr "Argument" + +msgid "Bios" +msgstr "BIOS" + +msgid "Bios Log" +msgstr "BIOS Log" + +msgid "Bulgarian" +msgstr "Bulgariska" + +msgid "C&dvdrom" +msgstr "C&DVDROM" + +msgid "C&ontrollers" +msgstr "K&ontroller" + +msgid "C&pu" +msgstr "C&PU" + +msgid "CDVDinit error: %d" +msgstr "CDVD Initieringsfel: %d" + +msgid "Cancel" +msgstr "Avbryt" + +msgid "Cannot load '%s', wrong PS2E version (%x != %x)" +msgstr "Kan inte ladda '%s',Fel PS2E version (%x != %x)" + +msgid "Catalan" +msgstr "Kataloniska" + +msgid "Cdr Log" +msgstr "CDR Log" + +msgid "Cdvdrom" +msgstr "CDVDROM" + +msgid "Clear BPs" +msgstr "Rensa BPs" + +msgid "Close" +msgstr "Stng" + +msgid "Conf" +msgstr "Konfiguration" + +msgid "Configuration" +msgstr "Konfiguration" + +msgid "Configure" +msgstr "Konfigurera" + +msgid "Configure..." +msgstr "Konfigurera" + +msgid "Controllers" +msgstr "Kontroller" + +msgid "Cop0 Log" +msgstr "COP0 Log" + +msgid "Could Not Load CDVD Plugin '%s': %s" +msgstr "Kunde inte ladda CDVD Plugin '%s': %s" + +msgid "Could Not Load DEV9 Plugin '%s': %s" +msgstr "Kunde inte ladda DEV9 Plugin '%s': %s" + +msgid "Could Not Load FW Plugin '%s': %s" +msgstr "Kunde inte ladda Firewire Plugin '%s': %s" + +msgid "Could Not Load GS Plugin '%s': %s" +msgstr "Kunde inte ladda Grafik Plugin '%s': %s" + +msgid "Could Not Load PAD1 Plugin '%s': %s" +msgstr "Kunde inte ladda PAD1 Plugin '%s': %s" + +msgid "Could Not Load PAD2 Plugin '%s': %s" +msgstr "Kunde inte ladda PAD2 Plugin '%s': %s" + +msgid "Could Not Load SPU2 Plugin '%s': %s" +msgstr "Kunde inte ladda SPU2 Plugin '%s': %s" + +msgid "Could Not Load USB Plugin '%s': %s" +msgstr "Kunde inte ladda USB Plugin '%s': %s" + +msgid "Could not create threads or event" +msgstr "Kunde inte skapa trdar eller hndelse." + +msgid "Could not open '%s' directory" +msgstr "Kunde inte ppna mappen '%s'" + +msgid "Couldn't find pixmap file: %s" +msgstr "Kunde inte hitta pixmap filen: %s" + +msgid "Cpu" +msgstr "CPU" + +msgid "Cpu Config" +msgstr "CPU Konfiguration" + +msgid "Cpu Log" +msgstr "CPU Log" + +msgid "D&ev9" +msgstr "D&ev9" + +msgid "DEV9init error: %d" +msgstr "DEV9 Initieringsfel: %d" + +msgid "Data " +msgstr "Data" + +msgid "Debug" +msgstr "Debug" + +msgid "Dev9" +msgstr "Dev9" + +msgid "Disable Recompiler" +msgstr "Avaktivera Omkompilerare" + +msgid "Disable VUs recompilation" +msgstr "Inaktivera VUs omkompilation" + +msgid "Dma Log" +msgstr "DMA Log" + +msgid "Dump File = \"dump.txt\"" +msgstr "Dumpa Fil = \"dump.txt\"" + +msgid "Dump code" +msgstr "Dumpa kod" + +msgid "Dutch" +msgstr "Hollendska" + +msgid "E&xecute" +msgstr "K&r" + +msgid "E&xit" +msgstr "&Avsluta" + +msgid "EE Debug Mode" +msgstr "EE Debug Lge" + +msgid "EE Logs" +msgstr "EE Logs" + +msgid "Elf Log" +msgstr "ELF Log" + +msgid "Emulator" +msgstr "Emulator" + +msgid "Enable Console Output" +msgstr "Aktivera konsol" + +msgid "Enable Patches" +msgstr "Aktivera patcher" + +msgid "Enable Reg Caching" +msgstr "Aktivera Reg Cachning" + +msgid "English" +msgstr "Engelska" + +msgid "Enter &Debugger..." +msgstr "Starta &Debugger..." + +msgid "Enter Debugger ..." +msgstr "Starta &Debugger" + +msgid "Error Loading Symbol" +msgstr "Kunde inte ladda symbol" + +msgid "Error Opening CDVD Plugin" +msgstr "Kunde inte ppna CD-ROM Plugin" + +msgid "Error Opening DEV9 Plugin" +msgstr "Kunde inte ppna DEV9 Plugin" + +msgid "Error Opening FW Plugin" +msgstr "Kunde inte ppna Firewire Plugin" + +msgid "Error Opening GS Plugin" +msgstr "Kunde inte ppna Grafik Plugin" + +msgid "Error Opening PAD1 Plugin" +msgstr "Kunde inte ppna PAD1 Plugin" + +msgid "Error Opening PAD2 Plugin" +msgstr "Kunde inte ppna PAD2 Plugin" + +msgid "Error Opening SPU2 Plugin" +msgstr "Kunde inte ppna SPU2 Plugin" + +msgid "Error Opening USB Plugin" +msgstr "Kunde inte ppna USB Plugin" + +msgid "Error allocating memory" +msgstr "Kunde inte allokollera minne" + +msgid "Error initializing Recompiler, switching to Interpreter" +msgstr "Kunde inte initiera omkompilerare, gr till Interpreter" + +msgid "Error loading pixmap file: %s" +msgstr "Kunde inte ppna pixmap Fil: %s" + +msgid "Exit" +msgstr "Avsluta" + +msgid "FW" +msgstr "Firewire" + +msgid "FWinit error: %d" +msgstr "Firewire Initieringsfel: %d" + +msgid "Failed loading MemCard %s" +msgstr "Kunde inte ladda minneskort: %s" + +msgid "File" +msgstr "Arkiv" + +msgid "Fill in the command line arguments for opened program:" +msgstr "Fyll i kommando rads argumenten fr det ppnade programmet:" + +msgid "Fire&Wire" +msgstr "Fire&Wire" + +msgid "First Controller" +msgstr "Frsta kontrollern" + +msgid "Fpu Log" +msgstr "FPU Log" + +msgid "French" +msgstr "Franska" + +msgid "From 0x" +msgstr "Frn 0x" + +msgid "GIF Log" +msgstr "GIF Log" + +msgid "GPU Log" +msgstr "GPU Log" + +msgid "GSinit error: %d" +msgstr "Grafiska Syncen kunde inte initieras: %d" + +msgid "German" +msgstr "Tyska" + +msgid "Go" +msgstr "Starta" + +msgid "Graphics" +msgstr "Grafik" + +msgid "Greek" +msgstr "Grekiska" + +msgid "Greets to:" +msgstr "Hlsningar till:" + +msgid "" +"Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" +"Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" +"Seta-San, Skarmeth, blackd_wd, _Demo_\n" +"Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n" +"Some betatester/support dudes: bositman, Seta-san, falcon4ever, jegHegy, Razorblade, CKemu, Belmont, parotaku, crushtest, ChaosCode" +msgstr "" +"Hlsningar till: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" +"Danke an: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" +"Seta-San, Skarmeth, blackd_wd, _Demo_\n" +"Meriten: Hiryu && Sjeep fr Ihre libcdvd (ISO Parsing und Filesystem Treiber Code)\n" +"Einige Betatester/Hilfskrfte: bositman, Seta-san, falcon4ever, jegHegy, Razorblade, CKemu" + +msgid "Gte Log" +msgstr "GTE Log" + +msgid "Help" +msgstr "Hjlp" + +msgid "High" +msgstr "Hg" + +msgid "Hw Log" +msgstr "Hrdvaru Log" + +msgid "IOP Debug Mode" +msgstr "IOP Debug lge" + +msgid "IOP Log" +msgstr "IOP Log" + +msgid "IOP Logs" +msgstr "IOP Log" + +msgid "IPU Log" +msgstr "IPU Log" + +msgid "If you don't know what to write leave it blank" +msgstr "Om du inte vet vad du ska skriva, lmna den tom" + +msgid "" +"In debugger:\n" +"Put EE in stop state\n" +"and IOP in run state" +msgstr "" +"I Debugger: \n" +"Stt EE i stoppad status\n" +"och IOP i pgende status" + +msgid "" +"In debugger:\n" +"Put IOP in stop state\n" +"and EE in run state" +msgstr "" +"I Debugger: \n" +"Stt IOP i stoppad status\n" +"och EE i pgende status" + +msgid "Interpreter -The slowest but the most compatible cpu core" +msgstr "Interpreter -Den lngsammaste men mest kompitabla cpu krnan" + +msgid "Italian" +msgstr "Italienska" + +msgid "Japanese" +msgstr "Japanska" + +msgid "Language" +msgstr "Sprk" + +msgid "Load" +msgstr "Ladda" + +msgid "Load Elf" +msgstr "Ladda Elf" + +msgid "Log" +msgstr "Log" + +msgid "Log On/Off" +msgstr "Loggning P/Av" + +msgid "Log to STDOUT" +msgstr "Logga till STDOUT" + +msgid "Logging" +msgstr "Loggning" + +msgid "MMI Log" +msgstr "MMI Log" + +msgid "Mem Log" +msgstr "Minnes Log" + +msgid "Memcard Manager" +msgstr "Minneskorts Sktare" + +msgid "Memory Card 1" +msgstr "Minneskort 1" + +msgid "Memory Card 2" +msgstr "Minneskort 2" + +msgid "Memory Dump" +msgstr "Minnesdump" + +msgid "" +"Nah, you have to be in\n" +"Interpreter Mode to debug" +msgstr "" +"Nej, du mste vara i\n" +"Interpreter lge fr att debugga" + +msgid "New Patch" +msgstr "Ny Patch" + +msgid "Normal" +msgstr "Normal" + +msgid "Not enough params for inicommand\n" +msgstr "Inte tillrckligt med parametrar fr inikommando\n" + +msgid "Note: this is intented for developers only." +msgstr "Notera: detta r endast menat fr utvecklare." + +msgid "Notice on debugging EE" +msgstr "Notis p EE debug" + +msgid "Notice on debugging IOP" +msgstr "Notis p IOP debug" + +msgid "OK" +msgstr "Ok" + +msgid "Ok" +msgstr "Ok" + +msgid "Options" +msgstr "Alternativ" + +msgid "Other..." +msgstr "Annat..." + +msgid "PAD1init error: %d" +msgstr "Kunde inte initiera Pad1: %d" + +msgid "PAD2init error: %d" +msgstr "Kunde inte initiera pad2: %d" + +msgid "PCSX" +msgstr "PCSX" + +msgid "" +"PCSX2\r\r\r\n" +"Version x.x" +msgstr "" +"PCSX2\r\r\r\n" +"Version x.x" + +msgid "PCSX2 %s Compile Date - %s %s" +msgstr "PCSX2 %s Kompilerat: %s %s" + +msgid "PCSX2 Debugger" +msgstr "PCSX2 Debugger" + +msgid "PCSX2 EMU\n" +msgstr "PCSX2 Emulator\n" + +msgid "" +"PCSX2 For Linux\n" +"Version %s" +msgstr "" +"PCSX2 Fr Linux\n" +"Version %s" + +msgid "PCSX2 Msg" +msgstr "PCSX2 Meddelande" + +msgid "PCSX2 Quitting\n" +msgstr "PCSX2 Stnger\n" + +msgid "PCSX2 State Format" +msgstr "PCSX2 Sparpunktsformat" + +msgid "" +"PCSX2 a ps2 emulator\n" +"\n" +"written by:\n" +"linuzappz, shadow, florin,\n" +"alexey silinov, asadr, goldfinger,\n" +"nachbrenner, auMatt, loser\n" +"\n" +"Webmaster: Thorgal" +msgstr "" +"PCSX2 - En PS2 Emulator\n" +"\n" +"Skriven av:\n" +"linuzappz, shadow, florin,\n" +"alexey silinov, saqibakhtar, goldfinger,\n" +"Nachbrenner, auMatt, loser\n" +"\n" +"Webmaster: Thorgal" + +msgid "Pad Log" +msgstr "PAD Log" + +msgid "Patches Browser" +msgstr "Patch Utforskare" + +msgid "Pcsx About" +msgstr "PCSX om" + +msgid "Pcsx2 Msg" +msgstr "PCSX2 Meddelande" + +msgid "Pcsx2 needs to be configured" +msgstr "PCSX2 mste konfigureras" + +msgid "Plugins & Bios" +msgstr "Plugins & BIOS" + +msgid "Portuguese" +msgstr "Portugisiska" + +msgid "Processor doesn't supports MMX, can't run recompiler without that" +msgstr "Processorn r inte kompitabel med MMX, kan inte kra omkompilerare utan det." + +msgid "Program arguments" +msgstr "ProgramArgument" + +msgid "Ps2 Memory Card (*.ps2)" +msgstr "PS2 Minneskort (*.ps2)" + +msgid "Ps2 Output" +msgstr "PS2 Konsol" + +msgid "RPC Log" +msgstr "RPC Log" + +msgid "Raw Dump" +msgstr "Rdata dump" + +msgid "Re&set" +msgstr "&Starta om" + +msgid "Ready" +msgstr "Redo" + +msgid "Recompiler - Much faster than Intepreter(Needs MMX)" +msgstr "Omkompilerare - Mycket snabbare n Interpreter(Krver MMX)" + +msgid "Recompiler Options" +msgstr "Omkompilerarens alternativ" + +msgid "Recompiler+VuRecs - The fastest setting (Needs SSE,SSE2)" +msgstr "Omkompilerare + VuRecs - Snabbaste alternativer (Krver SSE,SSE2)" + +msgid "Refresh List" +msgstr "Uppdatera Lista" + +msgid "Reset" +msgstr "Starta om" + +msgid "Resetting..." +msgstr "Startar om..." + +msgid "Romanian" +msgstr "Rumenska" + +msgid "Run" +msgstr "Kr" + +msgid "Run CD" +msgstr "Kr CD" + +msgid "Russian" +msgstr "Ryska" + +msgid "SPR Log" +msgstr "SPR Log" + +msgid "SPU2init error: %d" +msgstr "Kunde inte initiera SPU2: %d" + +msgid "SYMs Log" +msgstr "SYMs Log" + +msgid "Save" +msgstr "Spara" + +msgid "Save Patch" +msgstr "Spara Patch" + +msgid "Search game name patch:" +msgstr "Sk efter spelpatch:" + +msgid "Second Controller" +msgstr "Andra kontrollern" + +msgid "Select Bios Dir" +msgstr "Vlj BIOS mapp" + +msgid "Select Bios Directory" +msgstr "Vlj BIOS mapp" + +msgid "Select Mcd" +msgstr "Vlj Mcd" + +msgid "Select Plugins Dir" +msgstr "Vlj plugin mapp" + +msgid "Select Plugins Directory" +msgstr "Vlj pluginmapp" + +msgid "Select Psx Elf File" +msgstr "Vlj PSX Elf Fil" + +msgid "Select State File" +msgstr "Vlj sparpunktsfil" + +msgid "Set BP Addr" +msgstr "Set BP Address" + +msgid "Set BP Count" +msgstr "Set BP Rknare" + +msgid "Set Bios Directory" +msgstr "Set BIOS mapp" + +msgid "Set Dump Addr (in Hex):" +msgstr "Set Dump Address (i hexadecimalt tal):" + +msgid "Set New BP Address (in Hex):" +msgstr "Set ny BP Address (i hexadecimalt tal)" + +msgid "Set New BP Count (in Hex):" +msgstr "Set ny BP rkning (i hexadecimalt tal):" + +msgid "Set New PC Address (in Hex):" +msgstr "Set ny PC address (i hexadecimalt tal):" + +msgid "Set PC" +msgstr "Set PC" + +msgid "Set Plugins Directory" +msgstr "Set Plugin Mapp" + +msgid "SetBreakPoint Addr" +msgstr "Set BP Address" + +msgid "SetPCDlg" +msgstr "Set PC Dialog" + +msgid "Sif Log" +msgstr "SIF Log" + +msgid "Skip" +msgstr "Skippa" + +msgid "Slot &1" +msgstr "Slot &1" + +msgid "Slot &2" +msgstr "Slot &2" + +msgid "Slot &3" +msgstr "Slot &3" + +msgid "Slot &4" +msgstr "Slot &4" + +msgid "Slot &5" +msgstr "Slot &5" + +msgid "Slot 1" +msgstr "Slot 1" + +msgid "Slot 2" +msgstr "Slot 2" + +msgid "Slot 3" +msgstr "Slot 3" + +msgid "Slot 4" +msgstr "Slot 4" + +msgid "Slot 5" +msgstr "Slot 5" + +msgid "Sound" +msgstr "Ljud" + +msgid "Spanish" +msgstr "Spanska" + +msgid "States" +msgstr "Sparpunkter" + +msgid "Step" +msgstr "Steg" + +msgid "Test" +msgstr "Test" + +msgid "Test..." +msgstr "Test" + +msgid "This plugin reports that should not work correctly" +msgstr "Denna plugin rapporterar att den funkar bra" + +msgid "This plugin reports that should work correctly" +msgstr "Denna plugin rapporterar att den funkar bra" + +msgid "" +"Tip: If you don't know what to write\n" +"leave it blank" +msgstr "" +"Tips: Om du inte vet vad du ska skriva\n" +"lmna den tom" + +msgid "To 0x" +msgstr "Till 0x" + +msgid "Turkish" +msgstr "Turkiska" + +msgid "U&SB" +msgstr "U&SB" + +msgid "USBinit error: %d" +msgstr "Kunde inte initiera Usb: %d" + +msgid "Unable to hack in %s%s\n" +msgstr "" +"Kunde inte hacka %s%s \n" +"\n" + +msgid "Unable to load bios: '%s', PCSX2 can't run without that" +msgstr "Kunde inte ladda BIOS: '%s', PCSX2 Kan inte funka utan det!" + +msgid "Unrecoverable error while running recompiler" +msgstr "Ireparabelt fel under omkompilerarens krning" + +msgid "Usb" +msgstr "USB" + +msgid "VU Micro Log" +msgstr "VU Micro Log" + +msgid "VU0 Log" +msgstr "VU0 Log" + +msgid "Vif Log" +msgstr "VIF Log" + +msgid "button69" +msgstr "Knapp 69" + +msgid "button70" +msgstr "Knapp70" + +msgid "memWrite32" +msgstr "memWrite32" + +msgid "patch file for this game not found. Can't apply any patches\n" +msgstr "Hittade ingen patch fr detta spel. Kan inte applicera patch. \n" + +msgid "written by..." +msgstr "Skrivet av..." + diff --git a/bin/Langs/sw_SW/LC_MESSAGES/pcsx2.mo b/bin/Langs/sw_SW/LC_MESSAGES/pcsx2.mo new file mode 100644 index 0000000000000000000000000000000000000000..d53edb0f45554734ad5bb87a03002253bd47420b GIT binary patch literal 10929 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

Pxox&d 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

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
The Compatibility List Contains 1403 Titles
+ + 132 + + 226 + + 118 + + 466 + 461
0 Story SLPM 65002 JPS2Playable
0.9.2
18 Wheeler - American Pro Trucker SLES 50214 EPS2Ingame
0.9.2
18 Wheeler - American Pro Trucker SLUS 20210 UPS2Nothing
0.9.2
187 Ride or Die SLUS 21116 UPS2Intro
0.9.2
24 - The Game SLUS 21268 UPS2Ingame
0.9.2
25 To Life SLUS 21016 UPS2Ingame
0.9.2
4x4 Evolution SLUS 20091 UPS2Playable
0.9.2
7 Sins SLES 53280 EPS2Intro
0.9.2
7 Sins SLES 53297 EPS2Nothing
0.9.2
Ace Combat 4 - Shattered Skies PBPX 95201 JPS2Ingame
0.9.2
Ace Combat 4 - Shattered Skies SLUS 20152 UPS2Menus
0.9.2
Ace Combat 5 - The Unsung War SLUS 20851 UPS2Intro
0.9.2
Ace Combat Zero - The Belkan War SLUS 21346 UPS2Intro
0.9.2
Action Girlz Racing SLES 52956 EPS2Ingame
0.9.2
Activision Anthology PBPX 95201 JPS2Playable
0.9.2
Aeon Flux SLUS 21205 UPS2Playable
0.9.2
AFL Live 2003 SLES 51168 EPS2Playable
0.9.2
Age of Empires II - The Age of Kings SLES 50282 EPS2Ingame
0.9.2
Aggressive Inline SLUS 20327 UPS2Playable
0.9.2
Air Blade SCES 50246 EPS2Ingame
0.9.2
Airborne Troops Countdown To DDay SLUS 21125 UPS2Menus
0.9.2
Akai ito SLPM 65732 JPS2Ingame
0.9.2
Akira Psycho Ball SLES 50919 EPS2Playable
0.9.2
Alex Ferguson's Player Manager 2001 SLES 50429 EPS2Menus
0.9.2
Alfa Romeo Racing Italiano SLUS 21321 UPS2Nothing
0.9.2
Alias SLUS 20673 UPS2Ingame
0.9.2
Alien Hominid SLES 53139 EPS2Playable
0.9.2
Alien Hominid SLUS 21090 UPS2Playable
0.9.2
Aliens VS Predator - Extinction SLUS 20147 UPS2Ingame
0.9.2
All Star Pro Wrestling 3 SLPM 65300 JPS2Intro
0.9.2
Alone in the Dark 4 SLES 50185 EPS2Ingame
0.9.2
Alpine Racer 3 SCES 50887 EPS2Playable
0.9.2
American Chopper 2 SLUS 21288 UPS2Ingame
0.9.2
AMF Xtreme Bowling SLUS 21347 UPS2Ingame
0.9.2
Amplitude SCES 51706 EPS2Nothing
0.9.2
Amplitude SCUS 97258 UPS2Intro
0.9.2
And1 Streetball SLUS 21237 UPS2Ingame
0.9.2
Animaniacs - The Great Edgar Hunt SLES 52729 EPS2Intro
0.9.2
Another Century's Episode 2 SLPS 25623 JPS2Ingame
0.9.2
Ant Bully, The SLUS 21415 UPS2Menus
0.9.2
Anubis 2 SLES 53571 EPS2Playable
0.9.2
Ape Escape - Million Monkeys SCPS 15115 JPS2Ingame
0.9.2
Ape Escape - Pumped and Primed SLUS 21096 UPS2Intro
0.9.2
Ape Escape 3 SCUS 97501 UPS2Nothing
0.9.2
Aqua Aqua - Wetrix 2 SLES 50053 EPS2Ingame
0.9.2
Arc The Lad - End of Darkness SLUS 21165 UPS2Nothing
0.9.2
Arc the Lad - Twilight of the Spirits SCES 51910 EPS2Ingame
0.9.2
Arc the Lad - Twilight of the Spirits SCUS 97231 UPS2Ingame
0.9.2
Arcade, The SLES 52778 EPS2Playable
0.9.2
Arctic Thunder SLUS 20217 UPS2Intro
0.9.2
Area 51 SLES 52570 EPS2Intro
0.9.2
Area 51 SLUS 20595 UPS2Intro
0.9.2
Argos no Senshi SLPS 25178 JPS2Ingame
0.9.2
Armored Core - Last Raven SLUS 21338 UPS2Playable
0.9.2
Armored Core - Nine Breaker SLUS 21200 UPS2Ingame
0.9.2
Armored Core 2 - Another Age SLPS 25040 JPS2Playable
0.9.2
Armored Core 2 SLUS 20014 UPS2Playable
0.9.2
Armored Core 3 SLPS 25112 JPS2Playable
0.9.2
Army Men - Major Malfunction SLES 53996 EPS2Menus
0.9.2
Army Men - Sarge's Heroes 2 SLES 50192 EPS2Menus
0.9.2
Artic Thunder SLUS 20217 UPS2Ingame
0.9.2
Asterix And Obelix - Kick Buttix SLUS 20866 UPS2Intro
0.9.2
Astro Boy SLUS 20867 UPS2Playable
0.9.2
Atelier Iris - Eternal Mana SLUS 21113 UPS2Playable
0.9.2
Atelier Iris - Grand Phantasm SLPM 66436 JPS2Menus
0.9.2
Atelier Iris 2 - Azoth Of Destiny SLUS 21327 UPS2Playable
0.9.2
ATV Offroad Fury 2 SCUS 97369 UPS2Nothing
0.9.2
ATV Offroad Fury 3 SCUS 97405 UPS2Ingame
0.9.2
ATV Offroad Fury 4 SCUS 97479 UPS2Ingame
0.9.2
Auto Modellista SLES 51191 EPS2Playable
0.9.2
Auto Modellista SLUS 20642 UPS2Playable
0.9.2
Avatar - The Last Airbender SLUS 21395 UPS2Playable
0.9.2
Ayumi Hamasaki - A Visual Mix SLPM 65086 JPS2Intro
0.9.2
Backyard Football 2006 SLUS 20876 UPS2Nothing
0.9.2
Backyard Wrestling SLUS 20638 UPS2Intro
0.9.2
Bad Boys - Miami Takedown SLUS 20982 UPS2Ingame
0.9.2
Baldurs Gate - Dark Alliance SLUS 20035 UPS2Menus
0.9.2
Baphomets Fluch - Der Schlafende Drache SLES 51978 GPS2Playable
0.9.2
Barbarian SLES 50972 EPS2Playable
0.9.2
Barnyard SLUS 21277 UPS2Intro
0.9.2
Bass Strike SLUS 20325 UPS2Menus
0.9.2
Batman - Rise Of Sin Tzu SLUS 20709 UPS2Intro
0.9.2
Batman Begins SLUS 21198 UPS2Intro
0.9.2
Batman Vengeance SLUS 20226 UPS2Intro
0.9.2
Battle Stadium SLPS 25675 JPS2Playable
0.9.2
Battlefield 2 - Modern Combat SLUS 21026 UPS2Ingame
0.9.2
Battlestar Galactica SLUS 20421 UPS2Ingame
0.9.2
Beach King Stunts Racer SLES 51383 EPS2Playable
0.9.2
Beatdown - Fist of Vengeance SLUS 21150 UPS2Playable
0.9.2
Beatmania IIDX 9th Style SLPM 65946 JPS2Playable
0.9.2
Beatmania SLUS 21239 UPS2Playable
0.9.2
Beyond Good and Evil SLUS 20763 UPS2Intro
0.9.2
Big Mutha Truckers SLES 51355 EPS2Menus
0.9.2
Bike Street Vert Dirt SLUS 20310 UPS2Ingame
0.9.2
Billiard Xciting SLES 51859 EPS2Nothing
0.9.2
Biohazard 4 SLPM 66213 JPS2Ingame
0.9.2
Biohazard Code - Veronica SLPM 65022 JPS2Ingame
0.9.2
Black and Bruised SLUS 20506 UPS2Ingame
0.9.2
Black Matrix 2 SLPS 20187 JPS2Ingame
0.9.2
Black SLES 53886 EPS2Nothing
0.9.2
Black SLUS 21376 UPS2Nothing
0.9.2
Blade 2 SLUS 20360 UPS2Intro
0.9.2
Blitz - The League SLUS 21128 UPS2Intro
0.9.2
Blood - Souyoku Battle Rinbukyoku SCPS 15112 JPS2Nothing
0.9.2
Blood Omen 2 SLUS 20024 UPS2Nothing
0.9.2
Blood the Last Vampire - First Volume SCPS 15007 JPS2Ingame
0.9.2
Blood the Last Vampire - Second Volume SCPS 15008 JPS2Ingame
0.9.2
BloodRayne 2 SLES 53831 EPS2Playable
0.9.2
BloodRayne 2 SLUS 20862 UPS2Playable
0.9.2
Bloodrayne SLUS 20461 UPS2Playable
0.9.2
Bloody Roar 3 SLES 50203 EPS2Ingame
0.9.2
Bloody Roar 3 SLPM 62055 JPS2Ingame
0.9.2
Bloody Roar 4 SLES 51877 EPS2Ingame
0.9.2
Bloody Roar 4 SLUS 20795 UPS2Playable
0.9.2
Blowout SLUS 20850 UPS2Playable
0.9.2
BMX XXX SLES 50880 EPS2Playable
0.9.2
BMX XXX SLUS 20415 UPS2Playable
0.9.2
Boku to Mao SCPS 11008 JPS2Playable
0.9.2
Bombastic SLES 51966 EPS2Menus
0.9.2
Bombastic SLUS 20764 UPS2Menus
0.9.2
Bomberman Hardball SLES 53301 EPS2Playable
0.9.2
Bomberman Kart SLPM 62118 JPS2Playable
0.9.2
Bouncer, The SCES 50241 EPS2Ingame
0.9.2
Bouncer, The SLUS 20069 UPS2Ingame
0.9.2
Bravo Music SCPS 11013 JPS2Ingame
0.9.2
Breath of Fire - Dragon Quarter SLUS 20499 UPS2Ingame
0.9.2
Brian Lara Cricket 2005 SLES 52717 EPS2Ingame
0.9.2
Britney's Dance Beat SLUS 20402 UPS2Intro
0.9.2
Brothers In Arms - Earned In Blood SLUS 21310 UPS2Menus
0.9.2
Brothers In Arms - Road To Hill 30 SLUS 21163 UPS2Ingame
0.9.2
Buffy - Chaos Bleeds SLES 51890 EPS2Playable
0.9.2
Buffy The Vampire Slayer - Chaos Bleeds SLUS 20566 UPS2Intro
0.9.2
Bujingai - The Forsaken City SLUS 20895 UPS2Playable
0.9.2
Bully SLUS 21269 UPS2Ingame
0.9.2
Burnout - Revenge SLES 53506 EPS2Nothing
0.9.2
Burnout - Revenge SLUS 21242 UPS2Intro
0.9.2
Burnout 2 SLUS 20497 UPS2Playable
0.9.2
Burnout 3 - Takedown SLUS 21050 UPS2Intro
0.9.2
Burnout SLES 50445 EPS2Playable
0.9.2
Burnout SLUS 20307 UPS2Playable
0.9.2
Bust A Bloc SLES 51713 EPS2Ingame
0.9.2
Buzz - The Big Quiz SCES 53925 EPS2Intro
0.9.2
Cabelas - African Safari SLUS 21379 UPS2Ingame
0.9.2
Cabelas - Alaskan Adventures SLUS 21384 UPS2Ingame
0.9.2
Cabelas - Dangerous Hunts 2 SLUS 21350 UPS2Playable
0.9.2
Call Of Duty - Finest Hour SLUS 20725 UPS2Intro
0.9.2
Call Of Duty 2 - Big Red One SLUS 21228 UPS2Intro
0.9.2
Call Of Duty 3 SLUS 21426 UPS2Intro
0.9.2
Capcom Fighting Jam SLES 52854 EPS2Playable
0.9.2
Capcom Fighting Jam SLPM 65794 JPS2Playable
0.9.2
Capcom VS. SNK 2 PBPX 95201 JPS2Playable
0.9.2
Card Captor Sakura SLPS 20408 JPS2Ingame
0.9.2
Carmen Sandiego - The Secret of The Stolen Drums SLES 52143 EPS2Ingame
0.9.2
CART Fury Championship Racing SLUS 20141 UPS2Ingame
0.9.2
Casper - Spirit Dimensions SLUS 20205 UPS2Ingame
0.9.2
Castle Shikigami 2 SLUS 20962 UPS2Nothing
0.9.2
Castlevania - Curse of Darkness SLES 53755 EPS2Playable
0.9.2
Castlevania - Curse of Darkness SLUS 21168 UPS2Playable
0.9.2
Castlevania - Lament of Innocence SLUS 20733 UPS2Playable
0.9.2
Castlevania SLES 52118 EPS2Menus
0.9.2
Castlevania SLPM 65444 JPS2Playable
0.9.2
Castleween SLES 51249 EPS2Ingame
0.9.2
Catwoman SLUS 20992 UPS2Menus
0.9.2
Celebrity Deathmatch SLUS 20604 UPS2Playable
0.9.2
Champions of Norrath - Realms of Everquest SLUS 20565 UPS2Ingame
0.9.2
Chaos Legion SLUS 20695 UPS2Menus
0.9.2
Charlie and The Chocolate Factory SLES 53386 EPS2Playable
0.9.2
Charlie and The Chocolate Factory SLUS 21246 UPS2Ingame
0.9.2
Charlie's Angels SLES 51750 EPS2Ingame
0.9.2
Chess Challenger SLES 51630 EPS2Playable
0.9.2
Chessmasters SLUS 20637 UPS2Nothing
0.9.2
Choro Q SLUS 20930 UPS2Ingame
0.9.2
Chronicles of Narnia, The - The Lion, The Witch and The Wardrobe SLES 53706 EPS2Intro
0.9.2
Chulip SLPS 20230 JPS2Playable
0.9.2
Clock Tower 3 SLES 51619 EPS2Playable
0.9.2
Clock Tower 3 SLPM 65221 JPS2Playable
0.9.2
Codename: Kids Next Door - Operation V.I.D.E.O.G.A.M.E SLES 53685 EPS2Ingame
0.9.2
Cold Fear SLES 53158 EPS2Intro
0.9.2
Cold Fear SLUS 21047 UPS2Playable
0.9.2
Cold Winter SLUS 20845 UPS2Nothing
0.9.2
Colin McRae 2005 SLES 52636 EPS2Ingame
0.9.2
College Hoops 2006 SLUS 21232 UPS2Intro
0.9.2
Colosseum - Road To Freedom SLUS 21179 UPS2Playable
0.9.2
Commandos - Strike Force SLUS 21103 UPS2Intro
0.9.2
Commandos 2 SLUS 20086 UPS2Ingame
0.9.2
Conflict - Desert Storm SLUS 20549 UPS2Ingame
0.9.2
Conflict - Global Terror SLUS 21172 UPS2Ingame
0.9.2
Constantine SLUS 21142 UPS2Ingame
0.9.2
Contra - Shattered Soldier SLUS 20306 UPS2Playable
0.9.2
Cool Shot SLES 51785 EPS2Playable
0.9.2
Cool Shot SLPS 20256 JPS2Playable
0.9.2
Corvette Evolution GT SLUS 21499 UPS2Nothing
0.9.2
Corvette SLUS 20858 UPS2Playable
0.9.2
Crash Bandicoot - The Wrath of Cortex SLUS 20238 UPS2Nothing
0.9.2
Crash N Burn SLES 52339 EPS2Ingame
0.9.2
Crash Tag Team Racing SLUS 21191 UPS2Nothing
0.9.2
Crash Twinsanity SLES 52568 EPS2Ingame
0.9.2
Crash Twinsanity SLUS 20909 UPS2Playable
0.9.2
Crazy Frog Racer SLES 53869 EPS2Nothing
0.9.2
Crazy Taxi SLES 50215 EPS2Playable
0.9.2
Crazy Taxi SLUS 20202 UPS2Ingame
0.9.2
Crimson Sea 2 SLUS 20877 UPS2Intro
0.9.2
Crimson Tears SLPM 65575 JPS2Ingame
0.9.2
Crimson Tears SLUS 20948 UPS2Playable
0.9.2
Crouching Tiger Hidden Dragon SLUS 20523 UPS2Playable
0.9.2
Culdcept SLUS 20774 UPS2Playable
0.9.2
Cy Girls SLUS 20697 UPS2Ingame
0.9.2
Cyclone Circus - Power Sail Racing SLES 52684 EPS2Nothing
0.9.2
D1 Grand Prix SLUS 21416 UPS2Ingame
0.9.2
Da Vinci Code, The SLUS 21443 UPS2Ingame
0.9.2
Dakar 2 SLES 50879 EPS2Ingame
0.9.2
Dance Dance Revolution - Extreme 2 SLUS 21174 UPS2Ingame
0.9.2
Dance Dance Revolution - Extreme SLUS 20916 UPS2Playable
0.9.2
Dance Dance Revolution - Supernova SLUS 21377 UPS2Ingame
0.9.2
Dance Factory SLUS 21296 UPS2Menus
0.9.2
Dancing Stage Fever MegaMix SLES 51510 EPS2Playable
0.9.2
Dancing Stage Fever SLES 51757 EPS2Playable
0.9.2
Dancing Stage Fusion SLES 52598 EPS2Playable
0.9.2
Dark Angel - Vampire Apocalypse SLUS 20131 UPS2Ingame
0.9.2
Dark Chronicle SCES 51190 EPS2Ingame
0.9.2
Dark Cloud 2 SCUS 97213 UPS2Ingame
0.9.2
Dark Cloud SCES 50295 EPS2Playable
0.9.2
Dark Cloud SCUS 97111 UPS2Ingame
0.9.2
Darkwatch SLUS 21042 UPS2Ingame
0.9.2
Dave Mira Freestyle BMX 2 SLUS 20159 UPS2Ingame
0.9.2
DDR Festival SLPM 65775 JPS2Playable
0.9.2
DDR Max 2 SLPM 65277 JPS2Playable
0.9.2
DDR Max SLPM 62154 JPS2Playable
0.9.2
DDR Party Collection SLPM 62427 JPS2Ingame
0.9.2
DDR Strike SLPM 66242 JPS2Ingame
0.9.2
DDRmax1 - Dance Dance Revolution SLUS 20437 UPS2Playable
0.9.2
DDRmax2 - Dance Dance Revolution SLUS 20711 UPS2Playable
0.9.2
Dead or Alive 2 - Hardcore PBPX 95201 JPS2Nothing
0.9.2
Dead or Alive 2 - Hardcore SLUS 20071 UPS2Nothing
0.9.2
Dead or Alive 2 SCES 50003 EPS2Nothing
0.9.2
Dead or Alive 2 SLPS 25002 JPS2Nothing
0.9.2
Dead To Rights 2 SLUS 20843 UPS2Ingame
0.9.2
Dead To Rights SLES 51581 EPS2Playable
0.9.2
Dead To Rights SLUS 20220 UPS2Intro
0.9.2
Death By Degrees SLUS 20934 UPS2Nothing
0.9.2
Delta Force - Black Hawk Down SLUS 21124 UPS2Intro
0.9.2
Demento SLPM 65913 JPS2Playable
0.9.2
Demolition Girl SLES 53403 EPS2Ingame
0.9.2
Demonstone SLES 52669 EPS2Playable
0.9.2
Destroy All Humans 2 - Make War Not Love SLUS 21439 UPS2Ingame
0.9.2
Destroy All Humans SLUS 20945 UPS2Ingame
0.9.2
Destruction Derby Arenas SCES 50781 EPS2Ingame
0.9.2
Destruction Derby Arenas SLUS 20855 UPS2Ingame
0.9.2
Detonator SLES 52041 EPS2Ingame
0.9.2
Devil Kings SLUS 21297 UPS2Playable
0.9.2
Devil May Cry 2 SLES 82011 EPS2Ingame
0.9.2
Devil May Cry 2 SLUS 20484 UPS2Ingame
0.9.2
Devil May Cry 3 - Special Edition SLUS 21361 UPS2Playable
0.9.2
Devil May Cry 3 SLES 53038 EPS2Playable
0.9.2
Devil May Cry 3 SLPM 65880 JPS2Playable
0.9.2
Devil May Cry 3 SLUS 20964 UPS2Intro
0.9.2
Devil May Cry SLES 50358 EPS2Intro
0.9.2
Devil May Cry SLPM 65038 JPS2Menus
0.9.2
Devil May Cry SLUS 20216 UPS2Intro
0.9.2
Dice SLUS 21181 UPS2Playable
0.9.2
Die Hard - Vendetta SLES 51347 EPS2Ingame
0.9.2
Die Hard - Vendetta SLES 51348 EPS2Ingame
0.9.2
Digimon World 4 SLUS 20836 UPS2Playable
0.9.2
Dino Crisis - Gun Survivor 3 SLPS 25026 JPS2Menus
0.9.2
Dino Stalker SLUS 20485 UPS2Nothing
0.9.2
Dirge Of Cerberus - Final Fantasy VII SLPM 66271 JPS2Intro
0.9.2
Dirge Of Cerberus - Final Fantasy VII SLUS 21419 UPS2Intro
0.9.2
Disaster Report SLUS 20561 UPS2Nothing
0.9.2
Disgaea - Hour of Darkness SLUS 20666 UPS2Playable
0.9.2
Disgaea 2 - Cursed Memories SLPS 25608 JPS2Playable
0.9.2
Disgaea 2 - Cursed Memories SLUS 21397 UPS2Playable
0.9.2
Disney Golf SLUS 20532 UPS2Menus
0.9.2
Disney Pixar - Cars SLES 53624 EPS2Playable
0.9.2
Disneys Pixar Cars SLUS 21151 UPS2Ingame
0.9.2
DNA Dark Native Apostle SLES 50202 EPS2Nothing
0.9.2
Dodgeball SLES 53367 EPS2Playable
0.9.2
Dog's Life SLUS 21018 UPS2Intro
0.9.2
Donald Duck Phantomias Platyrhynchos Kineticus SLES 50773 EPS2Ingame
0.9.2
Donald Duck Quack Attack SLES 50048 EPS2Intro
0.9.2
Dot Hack - Infection Part 1 SLUS 20267 UPS2Ingame
0.9.2
Dot Hack - Mutation Part 2 SLES 52467 EPS2Ingame
0.9.2
Dot Hack - Mutation Part 2 SLUS 20562 UPS2Ingame
0.9.2
Dot Hack - Outbreak Part 3 SLUS 20563 UPS2Ingame
0.9.2
Dot Hack - Quarantine Part 4 SLES 52468 EPS2Ingame
0.9.2
Dot Hack GU Volume 1 - Rebirth - Terminal Disc SLUS 21480 UPS2Playable
0.9.2
Dot Hack GU Volume 1 - Rebirth SLUS 21258 UPS2Ingame
0.9.2
Downforce SLES 50842 EPS2Ingame
0.9.2
Downhill Domination SCUS 97177 UPS2Playable
0.9.2
Dr. Muto SLUS 20458 UPS2Intro
0.9.2
Dragon Quest VIII - Journey of the Cursed King SLES 53974 EPS2Playable
0.9.2
Dragon Quest VIII SLUS 21207 UPS2Playable
0.9.2
Dragonball Z Budokai 2 SLES 51839 EPS2Playable
0.9.2
Dragonball Z Budokai 3 SLES 52730 EPS2Playable
0.9.2
Dragonball Z Budokai Tenkaichi 2 SLUS 21441 UPS2Ingame
0.9.2
Dragonball Z Budokai Tenkaichi SLES 53200 EPS2Playable
0.9.2
Dragonball Z Budokai Tenkaichi SLUS 21227 UPS2Playable
0.9.2
Dragonball Z Budokai SLES 51233 EPS2Playable
0.9.2
Dragonball Z Budokai SLUS 20591 UPS2Playable
0.9.2
Dragonball Z Sagas SLUS 20874 UPS2Ingame
0.9.2
Drakan - The Ancients Gate SCUS 97128 UPS2Intro
0.9.2
Drakengard 2 SLUS 21373 UPS2Playable
0.9.2
DreamMix TV - World Fighters SLPM 65384 JPS2Ingame
0.9.2
Driver - Parallel Lines SLUS 21271 UPS2Intro
0.9.2
Driver 3 SLUS 20587 UPS2Intro
0.9.2
Driving Emotion Type-S SLPS 20007 JPS2Ingame
0.9.2
Drome Racers SLUS 20577 UPS2Intro
0.9.2
Dropship - United Peace Force SCES 50459 EPS2Intro
0.9.2
Dropship - United Peace Force SLUS 20463 UPS2Menus
0.9.2
DT Racer SLUS 21095 UPS2Intro
0.9.2
DTM Race Driver 2 SLES 52638 EPS2Ingame
0.9.2
DTM Race Driver SLES 50816 EPS2Playable
0.9.2
Dual Hearts SLUS 20475 UPS2Menus
0.9.2
Dukes of Hazard SLUS 20959 UPS2Intro
0.9.2
Dynasty Tactics 2 SLUS 20761 UPS2Intro
0.9.2
Dynasty Warriors 3 SLES 50641 EPS2Playable
0.9.2
Dynasty Warriors 3 SLUS 20277 UPS2Ingame
0.9.2
Dynasty Warriors 4 - Empires SLUS 20653 UPS2Playable
0.9.2
Dynasty Warriors 4 Xtreme Legends SLUS 20812 UPS2Playable
0.9.2
Dynasty Warriors 4 SLUS 20653 UPS2Playable
0.9.2
Dynasty Warriors 5 - Empires SLUS 21398 UPS2Ingame
0.9.2
Dynasty Warriors 5 Xtreme Legends SLUS 21299 UPS2Playable
0.9.2
Dynasty Warriors 5 SLUS 21153 UPS2Ingame
0.9.2
EA Arena Football SLUS 21337 UPS2Intro
0.9.2
EA Sports cricket 2004 SLES 52123 EPS2Ingame
0.9.2
Eagle Eye Golf SLUS 21486 UPS2Ingame
0.9.2
Ecco the Dolphin - Defender of the Future SCES 50499 EPS2Intro
0.9.2
Ecco the Dolphin - Defender of the Future SLUS 20394 UPS2Intro
0.9.2
Echo Night Beyond SLUS 20928 UPS2Ingame
0.9.2
Eggomania SLES 51101 EPS2Playable
0.9.2
Endgame SLUS 20389 UPS2Nothing
0.9.2
Energy Airforce SLPM 65177 JPS2Playable
0.9.2
Enter The Matrix SLES 51203 EPS2Menus
0.9.2
Enter The Matrix SLUS 20454 UPS2Intro
0.9.2
Enthusia Professional Racing SLUS 20967 UPS2Ingame
0.9.2
Ephemeral Fantasia SLUS 20169 UPS2Playable
0.9.2
Ephemeral Phantasia SLES 50110 EPS2Ingame
0.9.2
Eragon SLUS 21322 UPS2Ingame
0.9.2
Escape From Monkey Island SLUS 20181 UPS2Ingame
0.9.2
Espgaluda SLPS 25352 JPS2Playable
0.9.2
ESPN NBA 2Night SLUS 20261 UPS2Menus
0.9.2
ESPN NFL 2K5 SLUS 20919 UPS2Nothing
0.9.2
ESPN NHL Hockey SLUS 20728 UPS2Menus
0.9.2
Eternal Quest SLES 51624 EPS2Playable
0.9.2
Eternal Ring SLUS 20015 UPS2Ingame
0.9.2
Eureka Seven Volume 1 - The New Wave SLUS 21353 UPS2Ingame
0.9.2
Euro Rally Champion SLES 52378 EPS2Ingame
0.9.2
Everblue 2 SLUS 20598 UPS2Intro
0.9.2
Everblue SLES 50639 EPS2Playable
0.9.2
Everblue SLPM 62081 JPS2Playable
0.9.2
Evergrace SLES 50050 EPS2Playable
0.9.2
Evergrace SLUS 20016 UPS2Ingame
0.9.2
Everquest Online Adventures SCES 51725 EPS2Menus
0.9.2
Evil Dead - A Fistful of Boomstick SLUS 20403 UPS2Menus
0.9.2
Evil Dead - Regeneration SLUS 21048 UPS2Ingame
0.9.2
Evil Twin - Cyprien's Chronicles SLES 50201 EPS2Playable
0.9.2
Evil Twin PBPX 95201 EPS2Playable
0.9.2
Extermination SCUS 97112 UPS2Playable
0.9.2
Eyetoy - Kinetic SCES 52883 EPS2Intro
0.9.2
EyeToy - Monkey Mania SCES 52930 EPS2Intro
0.9.2
Eyetoy - Play 2 SCES 52748 EPS2Intro
0.9.2
Eyetoy - Sega Superstars SLES 52834 EPS2Nothing
0.9.2
Eyetoy Play 2 SCUS 97468 UPS2Intro
0.9.2
Eyetoy Play SCUS 97319 UPS2Intro
0.9.2
F1 2001 SLES 50423 EPS2Intro
0.9.2
F1 Career Challenge SLES 51584 EPS2Menus
0.9.2
F1 Championship Season 2000 SLES 50017 EPS2Playable
0.9.2
F1 Championship Season 2000 SLUS 20103 UPS2Ingame
0.9.2
F1 Racing Championship SLES 50046 EPS2Ingame
0.9.2
Family Feud SLUS 21446 UPS2Nothing
0.9.2
Family Guy SLUS 21560 UPS2Ingame
0.9.2
Fantastic 4 SLUS 20615 UPS2Ingame
0.9.2
Fantavision SCPS 11002 JPS2Ingame
0.9.2
Fantavision SLUS 97015 UPS2Playable
0.9.2
Fast and The Furious, The SLUS 21449 UPS2Ingame
0.9.2
Fatal Frame 2 SLUS 20766 UPS2Menus
0.9.2
Fatal Frame 3 SLUS 21244 UPS2Intro
0.9.2
Fatal Frame SLUS 20388 UPS2Ingame
0.9.2
Fatal Fury - Battle Archives 1 SLPS 25664 JPS2Playable
0.9.2
FC Barcelona Club Football SLES 51078 EPS2Menus
0.9.2
Ferrari F355 Challenge SCES 50956 EPS2Playable
0.9.2
Fifa 2002 SLUS 20280 UPS2Intro
0.9.2
Fifa 2005 SLUS 21051 UPS2Intro
0.9.2
FIFA Football 2003 SLES 51197 EPS2Ingame
0.9.2
Fifa Street SLES 53064 EPS2Nothing
0.9.2
Fifa World Cup 2002 SLES 50798 EPS2Intro
0.9.2
Fight Club SLUS 20857 UPS2Intro
0.9.2
Fight Night - Round 3 SLUS 21383 UPS2Playable
0.9.2
Fighter Maker 2 SLUS 20524 UPS2Playable
0.9.2
Fighting Angels SLES 53408 EPS2Ingame
0.9.2
Final Fantasy X - International Version SLPS 25088 JPS2Playable
0.9.2
Final Fantasy X SCES 50490 EPS2Playable
0.9.2
Final Fantasy X SCES 50492 GPS2Playable
0.9.2
Final Fantasy X SLPS 25050 JPS2Ingame
0.9.2
Final Fantasy X SLUS 20312 UPS2Playable
0.9.2
Final Fantasy X-2 SLES 51815 EPS2Playable
0.9.2
Final Fantasy X-2 SLES 51817 GPS2Ingame
0.9.2
Final Fantasy X-2 SLUS 20672 UPS2Playable
0.9.2
Final Fantasy XI SCUS 97266 UPS2Nothing
0.9.2
Final Fantasy XI SLPS 25200 JPS2Menus
0.9.2
Final Fantasy XII SLPM 66320 JPS2Ingame
0.9.2
Final Fantasy XII SLUS 20963 UPS2Ingame
0.9.2
Final Fight - Streetwise SLUS 21238 UPS2Intro
0.9.2
Finny The Fish & The Seven Waters SLUS 21072 UPS2Playable
0.9.2
Fire Pro Wrestling Z SLPM 62342 JPS2Playable
0.9.2
Fireblade SLUS 20198 UPS2Ingame
0.9.2
Firefighter F.D. 18 SLUS 20724 UPS2Ingame
0.9.2
Fisherman's Challenge SLES 51418 EPS2Nothing
0.9.2
Fishermans Bass Club SLUS 20428 UPS2Menus
0.9.2
Flatout 2 SLES 54002 EPS2Ingame
0.9.2
Flatout 2 SLUS 21251 UPS2Ingame
0.9.2
Flatout SLUS 20901 UPS2Intro
0.9.2
Flipnic SCPS 15050 JPS2Nothing
0.9.2
Flipnic SLUS 21157 UPS2Intro
0.9.2
Flow - Urban Dance Uprising SLES 53848 EPS2Intro
0.9.2
Flow - Urban Dance Uprising SLUS 21319 UPS2Intro
0.9.2
Flucht von Monkey Island SLES 50227 GPS2Ingame
0.9.2
Flushed Away SLUS 21484 UPS2Ingame
0.9.2
Forbidden Siren SCES 52328 GPS2Ingame
0.9.2
Ford Mustang - The Legend Lives SLES 53296 EPS2Ingame
0.9.2
Forever Kingdom SLUS 20343 UPS2Menus
0.9.2
Forgotten Realms - Demon Stone SLUS 20804 UPS2Ingame
0.9.2
Formula 1 2006 SCES 53950 EPS2Intro
0.9.2
Formula One 2001 SCES 50004 EPS2Ingame
0.9.2
Formula One 2003 SCES 51592 EPS2Ingame
0.9.2
Formula One 2005 SCES 53033 EPS2Intro
0.9.2
Freak Out SLES 50310 EPS2Menus
0.9.2
Freedom Fighters SLUS 20658 UPS2Intro
0.9.2
Freestyle SLUS 20367 UPS2Intro
0.9.2
Frequency SCES 50791 EPS2Ingame
0.9.2
Frequency SCUS 97125 UPS2Ingame
0.9.2
Friends - The One With All The Trivia SLUS 21313 UPS2Menus
0.9.2
Frogger - Ancient Shadows SLUS 21098 UPS2Nothing
0.9.2
Froggers Adventures - The Rescue SLUS 20734 UPS2Ingame
0.9.2
Front Mission 4 SLUS 20888 UPS2Menus
0.9.2
Fu-Un Bakumatsu-Den SLPM 65813 JPS2Menus
0.9.2
Fugitive Hunter - War On Terror SLUS 20464 UPS2Ingame
0.9.2
Full Metal Alchemist 2 - Curse of the Crimson Elixir SLUS 21166 UPS2Intro
0.9.2
Full Metal Alchemist and The Broken Angel SLUS 20994 UPS2Playable
0.9.2
Full Spectrum Warriors - Ten Hammers SLUS 21250 UPS2Menus
0.9.2
Fur Fighters - Viggos Revenge SLUS 20088 UPS2Playable
0.9.2
Futurama SLUS 20439 UPS2Playable
0.9.2
Galerians - Ash SLUS 20560 UPS2Ingame
0.9.2
Gantz SLPM 65950 JPS2Playable
0.9.2
Gauntlet - Dark Legacy SLES 50211 EPS2Ingame
0.9.2
Gauntlet - Seven Sorrows SLUS 21077 UPS2Intro
0.9.2
Gegege no Kitaro SLPM 65337 JPS2Ingame
0.9.2
Gekibo 2 SLPS 20091 JPS2Playable
0.9.2
Genji - Dawn of The Samurai SCUS 97471 UPS2Nothing
0.9.2
Getaway - Black Monday, The SCUS 97408 UPS2Ingame
0.9.2
Getaway, The SCES 51159 EPS2Menus
0.9.2
Ghost In The Shell - Stand Alone Complex SLUS 21006 UPS2Ingame
0.9.2
Ghost Recon - Advanced Warfighter SLUS 21422 UPS2Intro
0.9.2
Ghosthunter SCES 51463 EPS2Ingame
0.9.2
Ghosthunter SLUS 20993 UPS2Ingame
0.9.2
Gift SLES 50296 EPS2Ingame
0.9.2
Girl Zone SLES 53190 EPS2Playable
0.9.2
Gitaroo Man SLPM 65012 JPS2Ingame
0.9.2
Gitaroo Man SLUS 20294 UPS2Ingame
0.9.2
Gladiator - Sword of Vengeance SLUS 20793 UPS2Intro
0.9.2
Gladius SLUS 20490 UPS2Playable
0.9.2
Glass Rose SLPM 65373 JPS2Menus
0.9.2
God Hand SLPM 66550 JPS2Nothing
0.9.2
God Hand SLUS 21503 UPS2Nothing
0.9.2
God of War SCES 53133 EPS2Ingame
0.9.2
God of War SCUS 97399 UPS2Ingame
0.9.2
GoDai Elemental Force SLES 50704 EPS2Ingame
0.9.2
Godfather, The SLUS 21385 UPS2Nothing
0.9.2
Godzilla - Save The Earth SLUS 20809 UPS2Nothing
0.9.2
Goemon SLPM 65014 JPS2Nothing
0.9.2
Gradius 3 & 4 SLES 50038 EPS2Playable
0.9.2
Gradius 3 & 4 SLPM 62007 JPS2Ingame
0.9.2
Gradius 3 & 4 SLUS 20040 UPS2Playable
0.9.2
Gradius 5 SLPM 62462 JPS2Playable
0.9.2
Gradius 5 SLUS 20712 UPS2Playable
0.9.2
Graffiti Kingdom SLUS 21136 UPS2Playable
0.9.2
Gran Turismo 3 A-spec SCES 50294 EPS2Ingame
0.9.2
Gran Turismo 3 A-spec SCUS 97102 UPS2Ingame
0.9.2
Gran Turismo 4 First Preview PCPX 96649 JPS2Menus
0.9.2
Gran Turismo 4 Prologue Chinese PBPX 95524 JPS2Menus
0.9.2
Gran Turismo 4 Prologue SCES 52438 EPS2Intro
0.9.2
Gran Turismo 4 SCAJ 30007 JPS2Ingame
0.9.2
Gran Turismo 4 SCES 51719 EPS2Ingame
0.9.2
Gran Turismo 4 SCUS 97328 UPS2Intro
0.9.2
Gran Turismo Concept 2001 Tokyo SCPS 15010 JPS2Ingame
0.9.2
Gran Turismo Concept 2002 Tokyo-Geneva SCES 50858 EPS2Intro
0.9.2
Grand Prix Challenge SLES 51296 EPS2Nothing
0.9.2
Grand Theft Auto - Liberty City Stories SLUS 21423 UPS2Intro
0.9.2
Grand Theft Auto - San Andreas SLES 52541 EPS2Ingame
0.9.2
Grand Theft Auto - San Andreas SLUS 20946 UPS2Ingame
0.9.2
Grand Theft Auto - Vice City SLES 51061-T EPS2Intro
0.9.2
Grand Theft Auto - Vice City SLES 51061 EPS2Intro
0.9.2
Grand Theft Auto - Vice City SLUS 20552 UPS2Intro
0.9.2
Grand Theft Auto III SLES 50330-T EPS2Ingame
0.9.2
Grand Theft Auto III SLUS 20062 UPS2Intro
0.9.2
Grand Tour Racing 400 SLES 52045 EPS2Ingame
0.9.2
Grandia 3 SLUS 21334 UPS2Playable
0.9.2
Grandia II SLUS 20194 UPS2Ingame
0.9.2
Grandia III SLPM 65976 JPS2Playable
0.9.2
Grandia Xtreme SLUS 20417 UPS2Playable
0.9.2
Great Escape, The SLES 51315 EPS2Ingame
0.9.2
Greg Hastings Tournament Paintball Max'd SLUS 21539 UPS2Intro
0.9.2
Gretzky NHL 06 SCUS 97466 UPS2Ingame
0.9.2
GT Racers SLES 52602 EPS2Ingame
0.9.2
GTC Africa SLES 50472 EPS2Playable
0.9.2
Guilty Gear Isuka SLES 53284 EPS2Playable
0.9.2
Guilty Gear X Plus "By Your Side" SLPM 64525 JPS2Playable
0.9.2
Guilty Gear X2 Reload SLES 52967 EPS2Playable
0.9.2
Guilty Gear X2 SLUS 20436 UPS2Playable
0.9.2
Guilty Gear XX - Slash Midnight Carnival SLPM 66333 JPS2Intro
0.9.2
Guilty Gear XX SLPS 25184 JPS2Playable
0.9.2
Guitar Freak 3 & Drummania 2 SLPM 65011 JPS2Playable
0.9.2
Guitar Freak 4 & Drummania 3 SLPM 65052 JPS2Playable
0.9.2
Guitar Freak and Drummania - Masterpiece Silver SLPM 66484 JPS2Ingame
0.9.2
Guitar Hero II SLUS 21447 UPS2Ingame
0.9.2
Guitar Hero SLES 54132 EPS2Ingame
0.9.2
Guitar Hero SLUS 21224 UPS2Ingame
0.9.2
Gumball 3000 SLES 50984 EPS2Menus
0.9.2
Gun SLUS 21139 UPS2Intro
0.9.2
Gunbird 1 & 2 SLPM 62469 JPS2Playable
0.9.2
Gunbird Special Edition SLES 53021 EPS2Playable
0.9.2
Gungrave Overdose SLUS 21020 UPS2Playable
0.9.2
Gungrave SLUS 20493 UPS2Intro
0.9.2
Gungriffon Blaze SLUS 20080 UPS2Playable
0.9.2
Guy Game, The SLUS 21074 UPS2Ingame
0.9.2
Habitrail Hamster Ball SLES 52749 EPS2Playable
0.9.2
Half Life SLUS 20066 UPS2Ingame
0.9.2
Half-Life SLES 50504 EPS2Ingame
0.9.2
Half-Life SLES 50505 GPS2Playable
0.9.2
Happy Feet SLUS 21455 UPS2Intro
0.9.2
Harvest Fishing SLES 53282 EPS2Playable
0.9.2
Harvest Moon - A Wonderful Life SLUS 21171 UPS2Ingame
0.9.2
Harvest Moon - Save The Homeland SLUS 20251 UPS2Playable
0.9.2
Haunted Mansion SLUS 20681 UPS2Intro
0.9.2
Haunting Ground SLUS 21075 UPS2Ingame
0.9.2
Haven - Call of The King SLES 51209 EPS2Intro
0.9.2
Haven - Call of The King SLUS 20517 UPS2Intro
0.9.2
Headhunter - Redemption SLUS 20817 UPS2Ingame
0.9.2
Heavy Metal Thunder SLPM 66030 JPS2Ingame
0.9.2
Herdy Gerdy SLES 50751 EPS2Ingame
0.9.2
Herdy Gerdy SLUS 20231 UPS2Ingame
0.9.2
History Channel's Civil War - The Game - Great Battles SLUS 21474 UPS2Intro
0.9.2
Hitman - Blood Money SLUS 21108 UPS2Intro
0.9.2
Hitman - Contracts SLUS 20882 UPS2Intro
0.9.2
Hitman 2 - Silent Assassin SLES 50992 EPS2Intro
0.9.2
Hitman 2 - Silent Assassin SLUS 20374 UPS2Intro
0.9.2
Hobbit, The SLUS 20655 UPS2Intro
0.9.2
Homura SLPM 62685 JPS2Ingame
0.9.2
Hot Shots Golf - Fore! SCUS 97401 UPS2Menus
0.9.2
Hot Shots Golf 3 SCUS 97130 UPS2Menus
0.9.2
Hot Wheels - Stunt Track Challenge SLUS 20954 UPS2Ingame
0.9.2
Hummer Badlands SLUS 21357 UPS2Ingame
0.9.2
Hungry Ghosts SCPS 15046 JPS2Ingame
0.9.2
Hustle, The - Detroit Streets SLUS 21335 UPS2Ingame
0.9.2
I-Ninja SLUS 20705 UPS2Ingame
0.9.2
Ice Age 2 - The Meltdown SLUS 21307 UPS2Intro
0.9.2
Ico SCES 50760 EPS2Intro
0.9.2
Ico SCPS 11003 JPS2Ingame
0.9.2
Ico SCUS 97113 UPS2Intro
0.9.2
IGPX SLUS 21430 UPS2Ingame
0.9.2
IHRA Motor Sports Drag Racing 2 SLUS 20586 UPS2Menus
0.9.2
Ikusa Gami SLKA 25320 KPS2Intro
0.9.2
In The Groove SLUS 21177 UPS2Playable
0.9.2
Incredible Hulk, The - Ultimate Destruction SLUS 20941 UPS2Intro
0.9.2
Incredibles, The - Rise of The Underminers SLUS 21217 UPS2Menus
0.9.2
Indiana Jones and The Emporers Tomb SLUS 20508 UPS2Intro
0.9.2
Indiana Jones und die Legende der Kaisergruft SLES 50838 GPS2Menus
0.9.2
Indigo Prophecy SLUS 21196 UPS2Nothing
0.9.2
IndyCar Series SLUS 20641 UPS2Ingame
0.9.2
Inspector Gadget - Mad Robots Invasion SLES 51247 EPS2Playable
0.9.2
International Track and Field PBPX 95201 EPS2Playable
0.9.2
Inuyasha - Feudal Combat SLUS 21193 UPS2Intro
0.9.2
Inuyasha: Secret of The Cursed Mask SLUS 20913 UPS2Playable
0.9.2
ISS Pro 2000 PBPX 95201 UPS2Ingame
0.9.2
Itudaki Street Special SLPM 65797 JPS2Nothing
0.9.2
Jade Cocoon 2 SLES 50735 EPS2Playable
0.9.2
Jade Cocoon 2 SLUS 20309 UPS2Playable
0.9.2
Jak 1 - The Precursor Legacy SCUS 97124 UPS2Intro
0.9.2
Jak 2 SCUS 97265 UPS2Intro
0.9.2
Jak 3 SCUS 97330 UPS2Intro
0.9.2
Jak and Daxter: the Precursor Legacy SCES 50361 EPS2Intro
0.9.2
Jak X Combat Racing SCUS 97429 UPS2Nothing
0.9.2
James Bond 007 - Agent Under Fire SLUS 20265 UPS2Intro
0.9.2
James Bond 007 - Everything or Nothing SLES 52005 EPS2Intro
0.9.2
James Bond 007 - Everything or Nothing SLUS 20751 UPS2Ingame
0.9.2
James Bond 007 - From Russia With Love SLUS 21282 UPS2Nothing
0.9.2
James Bond 007 Nightfire SLES 51260 EPS2Ingame
0.9.2
James Cameron's Dark Angel SLES 51333 EPS2Ingame
0.9.2
James Pond - Codename Robocod SLES 53682 EPS2Playable
0.9.2
Jaws Unleashed SLUS 21062 UPS2Intro
0.9.2
Jikkyou Powerful Pro Yakyuu 13 SLPM 66450 JPS2Playable
0.9.2
Judge Dredd - Dredd VS Death SLUS 20869 UPS2Ingame
0.9.2
Juiced SLES 53044 EPS2Playable
0.9.2
Juiced SLUS 20872 UPS2Ingame
0.9.2
Junior Board Games SLES 52776 EPS2Intro
0.9.2
Just Cause SLUS 21436 UPS2Intro
0.9.2
Justice League Heroes SLUS 21304 UPS2Ingame
0.9.2
Ka SCPS 11009 JPS2Ingame
0.9.2
Kaena SLPS 25295 JPS2Ingame
0.9.2
Kamen Rider 555 SLPS 20329 JPS2Ingame
0.9.2
Kamen Rider Blade SLPS 20402 JPS2Ingame
0.9.2
Kao The Kangaroo - Round 2 SLUS 20296 UPS2Playable
0.9.2
Karaoke Revolution - Love and Ballad SLPM 62382 JPS2Ingame
0.9.2
Karry House Coco Ichibanya SLPS 20367 JPS2Playable
0.9.2
Katamari Damacy SLPS 25360 JPS2Intro
0.9.2
Katamari Damacy SLUS 21008 UPS2Intro
0.9.2
Kelly Slater Pro Surfer SLUS 20334 UPS2Playable
0.9.2
Kengo - Master of Bushido SLES 50114 EPS2Playable
0.9.2
Kengo - Master of Bushido SLUS 20021 UPS2Playable
0.9.2
Kengo 2 SLPS 25107 JPS2Playable
0.9.2
Kensetsu Juuki Kenka Battle - Buchigire Kongou!! SLPS 25004 JPS2Ingame
0.9.2
Keroro Gunsou: MeroMero Battle Royale Z SLPS 25575 JPS2Intro
0.9.2
Kessen 2 SLUS 20275 UPS2Playable
0.9.2
Kessen 3 SLES 53121 GPS2Nothing
0.9.2
Kessen 3 SLUS 21119 UPS2Playable
0.9.2
Kessen SLUS 20098 UPS2Playable
0.9.2
Kill Switch SLUS 20706 UPS2Nothing
0.9.2
Killer 7 SLUS 21154 UPS2Playable
0.9.2
Killzone SCUS 97402 UPS2Ingame
0.9.2
King Kong SLUS 21311 UPS2Ingame
0.9.2
King of Colosseum II SLPM 65602 JPS2Ingame
0.9.2
King of Fighters - Maximum Impact SLUS 20923 UPS2Playable
0.9.2
King of Fighters - Neowave SLPS 25525 JPS2Playable
0.9.2
King of Fighters 2000 SLUS 20834 UPS2Playable
0.9.2
King of Fighters 2001, The SLUS 20839 UPS2Playable
0.9.2
King of Fighters 2006 SLUS 21365 UPS2Ingame
0.9.2
King of Fighters XI, The SLPS 25660 JPS2Playable
0.9.2
King's Field 4 SLES 50920 EPS2Playable
0.9.2
Kingdom Hearts - Final Mix SLPS 25198 JPS2Ingame
0.9.2
Kingdom Hearts II SLES 54114 EPS2Ingame
0.9.2
Kingdom Hearts II SLPM 66233 JPS2Ingame
0.9.2
Kingdom Hearts II SLUS 21005 UPS2Ingame
0.9.2
Kingdom Hearts SCES 50967 EPS2Playable
0.9.2
Kingdom Hearts SCES 50968 FPS2Playable
0.9.2
Kingdom Hearts SCES 50969 GPS2Playable
0.9.2
Kingdom Hearts SLUS 20370 UPS2Ingame
0.9.2
Klonoa 2 - Lunatea's Veil SCES 50354 EPS2Ingame
0.9.2
Klonoa 2 - Lunatea's Veil SLUS 20151 UPS2Ingame
0.9.2
Knight Rider 2 SLES 52836 EPS2Playable
0.9.2
Knight Rider SLES 51011 EPS2Ingame
0.9.2
Knights of the Temple II SLES 53645 EPS2Menus
0.9.2
Knockout Kings 2002 SLUS 20369 UPS2Ingame
0.9.2
Konohana 4 SLPM 65690 JPS2Playable
0.9.2
Kunoichi SLPM 65447 JPS2Nothing
0.9.2
Kuon SLPS 25329 JPS2Playable
0.9.2
Kuon SLUS 21007 UPS2Playable
0.9.2
Kuri Kuri Mix SLES 50224 EPS2Playable
0.9.2
Kya - Dark Lineage SLUS 20440 UPS2Ingame
0.9.2
L.A. Rush SLUS 21112 UPS2Ingame
0.9.2
La Petite Princess - Twinkle Star Spirits SLPS 25534 JPS2Intro
0.9.2
La Pucelle Tactics SLUS 20847 UPS2Playable
0.9.2
Lake Masters EX SLES 50351 EPS2Playable
0.9.2
Lara Croft Tomb Raider - The Angel of Darkness SLES 51227 EPS2Ingame
0.9.2
Last Blade 1 & 2 SLPS 25503 JPS2Playable
0.9.2
Le Mans 24 Hours SLES 50131 EPS2Playable
0.9.2
League Series Baseball SLES 51718 EPS2Playable
0.9.2
Legaia 2 - Duel Saga SLUS 20414 UPS2Nothing
0.9.2
Legend of Kay, The SLES 52931 EPS2Menus
0.9.2
Legend of Kay, The SLUS 21248 UPS2Ingame
0.9.2
Legend of Spyro - A New Beginning SLUS 21372 UPS2Ingame
0.9.2
Legion - Legend of Excalibur SLUS 20048 UPS2Playable
0.9.2
Lego Star Wars SLUS 21083 UPS2Nothing
0.9.2
Leisure Suit Larry SLUS 20956 UPS2Playable
0.9.2
Lemmings SCES 54145 EPS2Ingame
0.9.2
Lifeline SLUS 20848 UPS2Intro
0.9.2
London Racer 2 SLES 50955 EPS2Ingame
0.9.2
Looney Tunes Back in Action SLES 51794 EPS2Ingame
0.9.2
Lord of the Rings - The Return of the King SLES 52017 EPS2Intro
0.9.2
Lord of the Rings - The Return of the King SLPM 65503 JPS2Ingame
0.9.2
Lord of the Rings - The Two Towers SLES 51252 EPS2Ingame
0.9.2
Lord of the Rings - The Two Towers SLPS 29004 JPS2Intro
0.9.2
Lotus Challenge SLES 50230 EPS2Ingame
0.9.2
Love Com - Punch de Court SLPM 66470 JPS2Nothing
0.9.2
Lowrider SLUS 20676 UPS2Ingame
0.9.2
Mace Griffin - Bounty Hunter SLUS 20505 UPS2Ingame
0.9.2
Madagascar SLES 53226 EPS2Intro
0.9.2
Madden NFL 2005 SLUS 21000 UPS2Ingame
0.9.2
Madden NFL 2006 SLUS 21213 UPS2Ingame
0.9.2
Madden NFL 2007 SLUS 21476 UPS2Ingame
0.9.2
Mafia SLUS 20671 UPS2Nothing
0.9.2
Magic Pengel - The Quest for Color SLUS 20593 UPS2Playable
0.9.2
Magna Carta - Tears of Blood SLUS 21221 UPS2Ingame
0.9.2
Mahjong Party: Swim Suit Beauty SCAJ 10010 JPS2Playable
0.9.2
Makai Kingdom SLUS 21170 UPS2Playable
0.9.2
Malice SLES 52413 EPS2Menus
0.9.2
Manhunt SLUS 20827 UPS2Menus
0.9.2
Marc Ecko's Getting Up - Contents Under Pressure SLUS 21032 UPS2Ingame
0.9.2
Marvel - Ultimate Alliance SLUS 21374 UPS2Playable
0.9.2
Marvel Nemesis - Rise of the Imperfects SLES 53585 EPS2Menus
0.9.2
Marvel Nemesis - Rise of the Imperfects SLUS 21281 UPS2Intro
0.9.2
Marvel vs Capcom 2 SLPM 62227 JPS2Playable
0.9.2
Marvel vs Capcom 2 SLUS 20486 UPS2Playable
0.9.2
Master Chess SLES 52295 EPS2Playable
0.9.2
Masters of The Universe - He-Man - Defender of Grayskull SLES 53035 EPS2Menus
0.9.2
Matching Maker SLPS 20469 JPS2Nothing
0.9.2
Matrix, The - Path of Neo SLUS 21273 UPS2Menus
0.9.2
Matt Hoffmane - Pro BMX 2 SLUS 20335 UPS2Playable
0.9.2
Max Payne 2 - The Fall of Max Payne SLES 52336 EPS2Ingame
0.9.2
Max Payne 2 - The Fall of Max Payne SLUS 20814 UPS2Intro
0.9.2
Max Payne SLES 50325 EPS2Ingame
0.9.2
Max Payne SLUS 20230 UPS2Ingame
0.9.2
Maximo - Ghosts To Glory SLUS 20017 UPS2Intro
0.9.2
Maximo Machine Monster no Yabou SLPM 65367 JPS2Intro
0.9.2
Maximo Vs Army of Zin SLUS 20722 UPS2Intro
0.9.2
Maximo SLPM 62127 JPS2Intro
0.9.2
Medal Of Honor - European Assault SLUS 21199 UPS2Intro
0.9.2
Medal of Honor - Frontline SLUS 20368 UPS2Intro
0.9.2
Medal Of Honor - Rising Sun SLES 51873 EPS2Intro
0.9.2
Medal Of Honor - Rising Sun SLUS 20753 UPS2Intro
0.9.2
Megaman Anniversary Collection SLUS 20833 UPS2Playable
0.9.2
Megaman X - Command Mission SLUS 20903 UPS2Playable
0.9.2
Megaman X Collection SLUS 21370 UPS2Playable
0.9.2
Megaman X7 SLUS 20487 UPS2Intro
0.9.2
Megaman X8 SLUS 20960 UPS2Playable
0.9.2
Meiwaku Seijin - Panic Maker SLPM 65642 JPS2Playable
0.9.2
Mercenaries - Playground of Destruction SLUS 20932 UPS2Intro
0.9.2
Metal Gear Sold 2, Document of SLES 82010 EPS2Playable
0.9.2
Metal Gear Sold 2, Document of SLUS 20543 UPS2Ingame
0.9.2
Metal Gear Solid 2 - Sons of Liberty SLES 50383 EPS2Ingame
0.9.2
Metal Gear Solid 2 - Sons of Liberty SLUS 20144 UPS2Ingame
0.9.2
Metal Gear Solid 2 - Substance SLES 82009 EPS2Nothing
0.9.2
Metal Gear Solid 2 - Substance SLUS 20554 UPS2Nothing
0.9.2
Metal Gear Solid 3 - Snake Eater SLES 82013 EPS2Nothing
0.9.2
Metal Gear Solid 3 - Snake Eater SLUS 20915 UPS2Nothing
0.9.2
Metal Gear Solid 3 - Subsistence SLUS 21359 UPS2Nothing
0.9.2
Metal Saga SLUS 21293 UPS2Playable
0.9.2
Metal Slug 3 SLPS 25209 JPS2Playable
0.9.2
Metal Slug 4 SLPS 25376 JPS2Playable
0.9.2
Metal Slug 4 SLUS 20971 UPS2Playable
0.9.2
Metal Slug 5 SLES 53383 EPS2Playable
0.9.2
Metal Slug 5 SLPS 25495 JPS2Playable
0.9.2
Metal Slug 5 SLUS 20990 UPS2Playable
0.9.2
Metal Slug 6 SLPS 25674 JPS2Playable
0.9.2
Metal Slug SLPS 25650 JPS2Playable
0.9.2
Micro Machines V4 SLUS 21402 UPS2Intro
0.9.2
Midnight Club 3 Dub Edition Remix SLUS 21355 UPS2Ingame
0.9.2
Midnight Club 3 Dub Edition SLUS 21029 UPS2Ingame
0.9.2
Midnight Club II SLES 51054 EPS2Menus
0.9.2
Midnight Club II SLUS 20209 UPS2Intro
0.9.2
Minna Daisuki Katamari Damacy SLPS 25467 JPS2Intro
0.9.2
Minority Report - Everybody Runs SLUS 20331 UPS2Playable
0.9.2
Mister Mosquito SLUS 20375 UPS2Intro
0.9.2
Mobile Suit Gundam Seed - Never Ending Tomorrow SLUS 21140 UPS2Ingame
0.9.2
Mobile Suit Gundam Zeonic Front SLUS 20233 UPS2Playable
0.9.2
Mojib-ribon SCPS 11033 JPS2Intro
0.9.2
Mojo! SLES 52111 EPS2Ingame
0.9.2
Monopoly Party SLUS 20348 UPS2Ingame
0.9.2
Monster House SLUS 21400 UPS2Intro
0.9.2
Monster Hunter G SLPM 65869 JPS2Playable
0.9.2
Monster Rancher EVO SLUS 21330 UPS2Playable
0.9.2
Mortal Kombat - Armageddon SLUS 21410 UPS2Ingame
0.9.2
Mortal Kombat - Deadly Alliance SLUS 20423 UPS2Playable
0.9.2
Mortal Kombat - Deception SLUS 20881 UPS2Ingame
0.9.2
Mortal Kombat - Shaolin Monks SLUS 21087 UPS2Menus
0.9.2
Mortal Kombat 1 - Deception Premium Pack Bonus Disc SLUS 21081 UPS2Playable
0.9.2
Motocross Mania 3 SLUS 21229 UPS2Nothing
0.9.2
MotoGP 2 SLUS 20285 UPS2Ingame
0.9.2
MotoGP 3 SCES 50982 EPS2Ingame
0.9.2
MotoGP 4 SCES 52892 EPS2Ingame
0.9.2
MotoGP 4 SLUS 21159 UPS2Playable
0.9.2
MotoGP SCES 50034 EPS2Ingame
0.9.2
MotorBike King SLES 52518 JPS2Playable
0.9.2
Mouse Police, The SLES 52370 EPS2Playable
0.9.2
MS Saga - A New Dawn SLUS 21270 UPS2Playable
0.9.2
Mummy Returns, The SLES 50510 EPS2Ingame
0.9.2
Musashi Samurai Legend SLUS 20983 UPS2Intro
0.9.2
Mushihimesama SLPM 66056 JPS2Playable
0.9.2
MX 2002 SLUS 20072 UPS2Playable
0.9.2
MX VS ATV Unleashed SLUS 21104 UPS2Playable
0.9.2
Mystic Heroes SLUS 20521 UPS2Menus
0.9.2
Namco Museum - 50th Anniversary SLUS 20273 UPS2Playable
0.9.2
Namco Museum SLUS 20273 UPS2Playable
0.9.2
Namco X Capcom SLPS 25505 JPS2Playable
0.9.2
Nano Breaker SLKA 25263 JPS2Ingame
0.9.2
Nano Breaker SLUS 21010 UPS2Menus
0.9.2
Narc SLUS 20730 UPS2Menus
0.9.2
Naruto - Narutimett Hero SLPS 25293 JPS2Playable
0.9.2
Naruto - Ultimate Ninja SLUS 21358 UPS2Playable
0.9.2
Naruto Uzumaki Ninden SLPS 25542 JPS2Ingame
0.9.2
NASCAR 2001 SLUS 20101 UPS2Nothing
0.9.2
Nascar 2006 - Total Team Control SLUS 21266 UPS2Ingame
0.9.2
Nascar 2007 SLUS 21461 UPS2Playable
0.9.2
NASCAR Thunder 2002 SLUS 20266 UPS2Ingame
0.9.2
NBA Street 2 SLES 51481 EPS2Playable
0.9.2
Need For Speed - Carbon SLUS 21493 UPS2Menus
0.9.2
Need For Speed - Hot Pursuit 2 SLES 50731 EPS2Intro
0.9.2
Need For Speed - Most Wanted Black Edition SLUS 21351 UPS2Ingame
0.9.2
Need For Speed - Most Wanted SLES 53557 EPS2Ingame
0.9.2
Need For Speed - Most Wanted SLUS 21267 UPS2Ingame
0.9.2
Need For Speed Underground 2 SLES 52725 EPS2Ingame
0.9.2
Need For Speed Underground 2 SLUS 21065 UPS2Nothing
0.9.2
Need For Speed Underground SLES 51967 EPS2Ingame
0.9.2
Need For Speed Underground SLUS 20811 UPS2Nothing
0.9.2
Neo Contra SLES 52510 EPS2Ingame
0.9.2
Neo Contra SLUS 20961 UPS2Ingame
0.9.2
NeoGeo Online Collection Vol. 2 - Last Blade 1 & 2 SLPS 25503 JPS2Intro
0.9.2
Neon Genesis Evangelion - The Iron Maiden 2nd SLPM 65867 JPS2Playable
0.9.2
Neopets - The Darkest Faerie SCUS 97367 UPS2Ingame
0.9.2
NFL GameDay 2002 SCUS 97131 UPS2Ingame
0.9.2
NFL Headcoach SLUS 21407 UPS2Ingame
0.9.2
NHL 2006 SLUS 21241 UPS2Nothing
0.9.2
NHL 2007 SLUS 21458 UPS2Nothing
0.9.2
NHL 2K6 SLUS 21234 UPS2Intro
0.9.2
NHL 2K7 SLUS 21425 UPS2Intro
0.9.2
NHRA Championship Drag Racing SLUS 21114 UPS2Ingame
0.9.2
Nicktoons - Battle For Volcano Island SLUS 21469 UPS2Menus
0.9.2
Nightmare Before Christmas - Oogie's Revenge SLPM 65739 JPS2Ingame
0.9.2
Nightmare Before Christmas - Oogie's Revenge SLUS 20860 UPS2Playable
0.9.2
Nightmare of Druaga - Fushigino Dungeon SLUS 21071 UPS2Playable
0.9.2
Nightshade SLUS 20810 UPS2Nothing
0.9.2
Ninja Assault SLUS 20492 UPS2Menus
0.9.2
Ninjabread Man SLES 53570 EPS2Ingame
0.9.2
Nocturne SLUS 20911 UPS2Nothing
0.9.2
NRA Gun Club SLUS 21432 UPS2Intro
0.9.2
Obscure SLES 52738 EPS2Playable
0.9.2
Obscure SLUS 20777 UPS2Playable
0.9.2
Off-Road Wide Open SLES 50232 EPS2Playable
0.9.2
Okage Shadow King SCUS 97129 UPS2Ingame
0.9.2
Okami SLPM 66375 JPS2Ingame
0.9.2
Okami SLUS 21115 UPS2Nothing
0.9.2
One Piece - Grand Adventure SLUS 21435 UPS2Ingame
0.9.2
One Piece - Grand Battle 3 SLPS 25315 JPS2Playable
0.9.2
One Piece - Grand Battle SLUS 20975 UPS2Ingame
0.9.2
One Piece - Pirates Carnival SLUS 21364 UPS2Playable
0.9.2
Oni PBPX 95201 UPS2Intro
0.9.2
Oni SLES 50177 GPS2Ingame
0.9.2
Onimusha - Dawn of Dreams SLPM 66275 JPS2Ingame
0.9.2
Onimusha - Dawn of Dreams SLUS 21180 UPS2Playable
0.9.2
Onimusha - Warlords SLES 50247 EPS2Menus
0.9.2
Onimusha 2 - Samurai's Destiny SLES 50978 EPS2Playable
0.9.2
Onimusha 3 - Demon Siege SLES 51914 EPS2Playable
0.9.2
Onimusha 3 - Demon Siege SLUS 20694 UPS2Ingame
0.9.2
Onimusha SLPM 65010 JPS2Menus
0.9.2
Onimusha SLUS 20018 UPS2Ingame
0.9.2
Open Season SLUS 21467 UPS2Intro
0.9.2
Operation Winback SLES 50155 EPS2Ingame
0.9.2
Oretachi Geasen Zoku Sono 15: Akumajou Dracula SLPM 62729 JPS2Playable
0.9.2
Otostaz SCPS 11024 JPS2Ingame
0.9.2
Outlaw Golf 2 SLES 52965 EPS2Menus
0.9.2
Outlaw Golf 2 SLUS 21030 UPS2Menus
0.9.2
Outlaw Tennis SLUS 21190 UPS2Ingame
0.9.2
Outlaw Volleyball Remix SLUS 21049 UPS2Menus
0.9.2
Outrun 2006 - Coast 2 Coast SLUS 21274 UPS2Ingame
0.9.2
Over the Hedge SLUS 21300 UPS2Intro
0.9.2
Pac Man World 2 SLUS 20224 UPS2Playable
0.9.2
Pac Man World 3 SLUS 21219 UPS2Ingame
0.9.2
Pacman Fever SLUS 20197 UPS2Ingame
0.9.2
Pacman World Rally SLUS 21328 UPS2Ingame
0.9.2
Paparazzi SLES 53489 EPS2Playable
0.9.2
Parappa The Rapper 2 SCES 50408 EPS2Playable
0.9.2
Parappa The Rapper 2 SCUS 97167 UPS2Playable
0.9.2
Paris-Dakar Rally SLES 50212 EPS2Menus
0.9.2
Party Girls SLES 53406 EPS2Ingame
0.9.2
PC Genjin SLPM 62418 JPS2Playable
0.9.2
Persona 3 SLMP 66445 JPS2Ingame
0.9.2
Phantasy Star Universe SLUS 21194 UPS2Intro
0.9.2
Phantom Brave SLES 52951 EPS2Playable
0.9.2
Phantom Brave SLUS 20955 UPS2Playable
0.9.2
Pinball Hall of Fame SLES 52863 EPS2Playable
0.9.2
Pink Pong SLES 52519 EPS2Intro
0.9.2
Pirates - Legend of The Black Buccaneer SLUS 21478 UPS2Ingame
0.9.2
Pirates - The Legend of Black Cat SLES 50680 EPS2Ingame
0.9.2
Pirates of the Caribbean - The Legend of Jack Sparrow SLES 54237 EPS2Ingame
0.9.2
Pirates of The Caribbean - The Legend of Jack Sparrow SLUS 21110 UPS2Ingame
0.9.2
Pitfall - The Lost Expedition SLUS 20408 UPS2Intro
0.9.2
Play it Pinball SLES 51555 EPS2Ingame
0.9.2
Playboy: The Mansion SLUS 20988 UPS2Ingame
0.9.2
Pochi to Nyaa SLPS 20323 JPS2Playable
0.9.2
Police 24-7 SLES 50285 EPS2Ingame
0.9.2
Pool Master SLES 50052 EPS2Menus
0.9.2
Pool Paradise SLES 52246 EPS2Playable
0.9.2
Pool Paradise SLUS 20987 UPS2Ingame
0.9.2
Pop'n Music 12 SLPM 66314 JPS2Playable
0.9.2
Pop'n Taisen Puzzle-Dama Online SLPM 62464 JPS2Playable
0.9.2
Portal Runner SLUS 20003 UPS2Playable
0.9.2
Power Smash 2 SLPM 62236 JPS2Ingame
0.9.2
Powerpuff Girls, The - Relish Rampage SLES 51134 EPS2Ingame
0.9.2
PowerShot Pinball SLES 54084 EPS2Ingame
0.9.2
Predator - Concrete Jungle SLUS 20875 UPS2Playable
0.9.2
Primal SCES 51135 EPS2Ingame
0.9.2
Primal SCUS 97142 UPS2Ingame
0.9.2
Prince of Persia - The Two Thrones SLES 53777 EPS2Ingame
0.9.2
Prince of Persia - The Two Thrones SLUS 21287 UPS2Menus
0.9.2
Prince of Persia - Warrior Within SLUS 21022 UPS2Menus
0.9.2
Pro Evolution Soccer 4 SLES 52760 EPS2Playable
0.9.2
Pro Evolution Soccer 5 SLES 53544 EPS2Intro
0.9.2
Pro Rally 2002 SLES 50637 EPS2Playable
0.9.2
Pro Stroke Golf - World Tour 2007 SLUS 21496 UPS2Menus
0.9.2
Project Altered Beast SLES 53024 EPS2Playable
0.9.2
Project Eden SLES 50553 EPS2Playable
0.9.2
Project Eden SLUS 20164 UPS2Intro
0.9.2
Project Zero 3 - Shisei No Koe SLPS 25544 JPS2Menus
0.9.2
Project Zero II - Akai Chou SLPS 25303 JPS2Menus
0.9.2
Project Zero II - Crimson Butterfly SLES 52384 EPS2Menus
0.9.2
Project Zero SLES 50821 EPS2Ingame
0.9.2
Project Zero SLPS 25074 JPS2Menus
0.9.2
Pryzm - Chapter One - The Dark Unicorn SLES 50721 EPS2Playable
0.9.2
Psi-Ops - The Mindgate Conspiracy SLUS 20688 UPS2Ingame
0.9.2
Psychonauts SLUS 21120 UPS2Nothing
0.9.2
Psyvariar Complete Edition SLPM 62139 JPS2Playable
0.9.2
Psyvariar Revision SLPM 62371 JPS2Ingame
0.9.2
Punisher, The SLUS 20864 UPS2Ingame
0.9.2
Puzzle Challenge - Crosswords and More SLUS 21339 UPS2Playable
0.9.2
Quake 3 - Revolution PBPX 95201 UPS2Intro
0.9.2
R-type Final SLPS 25247 JPS2Nothing
0.9.2
R-Type Final SLUS 20780 UPS2Nothing
0.9.2
R: Racing Evolution SLUS 20721 UPS2Intro
0.9.2
R: Racing SLES 52309 EPS2Menus
0.9.2
Radiata Stories SLUS 21262 UPS2Nothing
0.9.2
Radirgy Precious SLPM 66405 JPS2Playable
0.9.2
Raiden III SLES 53829 EPS2Playable
0.9.2
Rakugaki Onkoku SLPM 65097 JPS2Playable
0.9.2
Rally Championship SLES 50763 EPS2Playable
0.9.2
Rampage - Total Destruction SLUS 21323 UPS2Nothing
0.9.2
Ratchet - Deadlocked SCUS 97465 UPS2Ingame
0.9.2
Ratchet And Clank 3 - Up Your Arsenal SCUS 97353 UPS2Ingame
0.9.2
Rayman 3 - Hoodlum Havoc SLUS 20601 UPS2Intro
0.9.2
Rayman M SLES 50457 EPS2Playable
0.9.2
Ready To Rumble - Round 2 SLUS 20054 UPS2Ingame
0.9.2
Real Fishing 3 SLUS 20555 UPS2Menus
0.9.2
Red Card Soccer 2003 SLUS 20354 UPS2Playable
0.9.2
Red Dead Revolver SLUS 20500 UPS2Nothing
0.9.2
Red Faction 2 SLUS 20442 UPS2Menus
0.9.2
Red Faction II SLES 51133 EPS2Ingame
0.9.2
Red Faction SLES 50279 GPS2Playable
0.9.2
Red Ninja - End of Honor SLUS 20714 UPS2Intro
0.9.2
Reservoir Dogs SLUS 21479 UPS2Ingame
0.9.2
Resident Evil - Code Veronica X SLES 50306 EPS2Ingame
0.9.2
Resident Evil - Code Veronica X SLUS 20184 UPS2Playable
0.9.2
Resident Evil 4 SLES 53702 EPS2Playable
0.9.2
Resident Evil 4 SLUS 21134 UPS2Playable
0.9.2
Resident Evil Dead Aim SLUS 20669 UPS2Playable
0.9.2
Resident Evil Outbreak 2 SLUS 20984 UPS2Playable
0.9.2
Resident Evil Outbreak SLUS 20765 UPS2Playable
0.9.2
Resident Evil Survivor 2: Code Veronica SLES 50650 UPS2Ingame
0.9.2
Resident Evil: Dead Aim SLUS 20669 UPS2Playable
0.9.2
Rez SLPM 62101 JPS2Ingame
0.9.2
Rez SLUS 20344 UPS2Playable
0.9.2
Ridge Racer 5 SCES 50000 EPS2Ingame
0.9.2
Ridge Racer 5 SLUS 20002 UPS2Ingame
0.9.2
Riding Spirits II SLES 52277 EPS2Playable
0.9.2
Riding Spirits SLUS 20429 UPS2Playable
0.9.2
Rig Racer 2 SLES 53572 EPS2Ingame
0.9.2
Ring Of Red SLUS 20145 UPS2Nothing
0.9.2
Rise of the Kasai SCUS 97416 UPS2Ingame
0.9.2
Rise To Honor SCUS 97279 UPS2Ingame
0.9.2
River King - A Wonderful Journey SLUS 21275 UPS2Playable
0.9.2
Roadkill SLUS 20687 UPS2Ingame
0.9.2
Robocop SLES 51374 EPS2Playable
0.9.2
Robot Alchemic Drive SLUS 20445 UPS2Ingame
0.9.2
Rocket Power Beach Bandits SLUS 20473 UPS2Intro
0.9.2
Rockman 7 SLES 51885 EPS2Playable
0.9.2
Rocky Legends SLES 52761 EPS2Playable
0.9.2
Rocky SLUS 20559 UPS2Ingame
0.9.2
Rogue Trooper SLUS 21320 UPS2Intro
0.9.2
Roland Garros 2005 SCES 53310 EPS2Intro
0.9.2
Romance of The Three Kingdoms IX SLUS 20879 UPS2Intro
0.9.2
Romance of The Three Kingdoms VII SLUS 20720 UPS2Playable
0.9.2
Romance of The Three Kingdoms X SLUS 21202 UPS2Intro
0.9.2
Romancing Saga SLUS 21263 UPS2Menus
0.9.2
RPG Maker 3 SLUS 21178 UPS2Playable
0.9.2
RPM Tuning SLES 52190 EPS2Intro
0.9.2
RTX Red Rock SLES 51071 EPS2Ingame
0.9.2
Ruff Trigger - The Vanocore Conspiracy SLUS 21314 UPS2Nothing
0.9.2
Rule of Rose SCPS 15093 JPS2Nothing
0.9.2
Rule of Rose SLUS 21448 UPS2Intro
0.9.2
Rumble Fish, The SLPM 65919 JPS2Playable
0.9.2
Rumble Racing SLES 50120 EPS2Intro
0.9.2
Rumble Roses SLES 52535 EPS2Playable
0.9.2
Rumble Roses SLUS 20970 UPS2Playable
0.9.2
Rune - Viking Warlord SLUS 20109 UPS2Intro
0.9.2
Rygar - Legendary Adventure SLUS 20471 UPS2Ingame
0.9.2
Saikyou Toudai Shogi Special SLPS 20161 JPS2Playable
0.9.2
Saint Seiya Chapter Sanctuary SLES 53201 EPS2Playable
0.9.2
Samurai Champloo - Sidetracked SLUS 21343 UPS2Intro
0.9.2
Samurai Showdown V SLES 53059 EPS2Playable
0.9.2
Samurai Spirits Tenkaichi Kenkakuten SLPS 25559 JPS2Playable
0.9.2
Samurai Warriors 2 SLUS 21462 UPS2Menus
0.9.2
Samurai Warriors Xtreme Legends SLUS 21080 UPS2Playable
0.9.2
Samurai Warriors SLUS 20878 UPS2Playable
0.9.2
Samurai Western SLES 53234 EPS2Playable
0.9.2
Samurai Western SLUS 21187 UPS2Playable
0.9.2
Saru Gechu 2 SCPS 15025 JPS2Ingame
0.9.2
Scaler SLES 52917 EPS2Menus
0.9.2
Scaler SLUS 20957 UPS2Ingame
0.9.2
Scarface - The World Is Yours SLUS 21111 UPS2Intro
0.9.2
School Rumble 2 SLPS 25669 JPS2Intro
0.9.2
Scooby Doo - Unmasked SLUS 21091 UPS2Intro
0.9.2
Second Sight SLES 52670 EPS2Ingame
0.9.2
Seek And Destroy SLUS 20606 UPS2Playable
0.9.2
SEGA Ages 2500 - Vol. 11 - Fist of the North Star SLPM 62462 JPS2Intro
0.9.2
Sega Ages 2500 Volume 01 - Phantasy Star generation:1 SLPM 62362 JPS2Playable
0.9.2
Sega Ages 2500 Volume 03 - Fantasy Zone SLPM 62366 JPS2Nothing
0.9.2
Sega Ages 2500 Volume 05 - Golden Axe SLPM 62385 JPS2Playable
0.9.2
Sega Ages 2500 Volume 06 - Bonanza Bros SLPM 62433 JPS2Playable
0.9.2
Sega Ages 2500 Volume 07 - Columns SLPM 62425 JPS2Playable
0.9.2
Sega Ages 2500 Volume 08 - Virtua Racing - Flat Out SLPM 62443 JPS2Menus
0.9.2
Sega Ages 2500 Volume 09 - Gain Ground SLPM 62445 JPS2Playable
0.9.2
Sega Ages 2500 Volume 10 - After Burner II SLPM 62446 JPS2Playable
0.9.2
Sega Ages 2500 Volume 16 - Virtua Fighter 2 SLPM 62547 JPS2Playable
0.9.2
Sega Ages 2500 Volume 17 - Phantasy Star Generation 2 SLPM 62553 JPS2Playable
0.9.2
Sega Ages 2500 Volume 20 - Space Harrier SLPM 62691 JPS2Menus
0.9.2
Sega Classics Collection SLES 53461 EPS2Ingame
0.9.2
Sega Genesis Collection SLUS 21542 UPS2Playable
0.9.2
Sega Rally 2006 SLPM 66212 JPS2Playable
0.9.2
Sega Rally 95 SLPM 62703 JPS2Nothing
0.9.2
Sega Soccer Slam SLUS 20509 UPS2Menus
0.9.2
Sega Sports Tennis SLUS 20480 UPS2Playable
0.9.2
Seitoushi Seiya Seiiki Juunikyuu Hen SLPS 25476 JPS2Playable
0.9.2
Sengoku Basara 2 SLPM 66447 JPS2Playable
0.9.2
Sensible Soccer 2006 SLES 53810 UPS2Ingame
0.9.2
Serious Sam - Next Encounter SLUS 20907 UPS2Nothing
0.9.2
Seven - Molmorth no Kiheitai SLPS 25025 JPS2Ingame
0.9.2
Seven Samurai SLUS 20621 UPS2Ingame
0.9.2
Shadow Hearts - Covenant SLUS 21041 UPS2Nothing
0.9.2
Shadow Hearts - From The New World SLPM 66071 JPS2Ingame
0.9.2
Shadow Hearts - From The New World SLUS 21326 UPS2Ingame
0.9.2
Shadow Hearts SLES 50677 EPS2Ingame
0.9.2
Shadow Hearts SLUS 20347 UPS2Ingame
0.9.2
Shadow Of Destiny SLUS 20146 UPS2Ingame
0.9.2
Shadow of Memories SLPM 65013 JPS2Ingame
0.9.2
Shadow of Rome SLUS 20902 UPS2Playable
0.9.2
Shadow of The Colossus SCES 53326 EPS2Ingame
0.9.2
Shadow of The Colossus SCUS 97472 UPS2Ingame
0.9.2
Shadow The Hedgehog SLUS 21261 UPS2Nothing
0.9.2
Shadow Tower Abyss SLPS 25217 JPS2Ingame
0.9.2
Shadowman - The Second Coming SLES 50446 EPS2Nothing
0.9.2
Shark Tales SLUS 20925 UPS2Intro
0.9.2
Shikigami no Shiro 2 SLPM 62461 JPS2Ingame
0.9.2
Shikigami no Shiro Nanayozuki Genshou Kyoku SLPM 66069 JPS2Menus
0.9.2
Shikigami no Shiro SLPM 62165 JPS2Playable
0.9.2
Shin Megami Tensei - Digital Devil Saga 2 SLUS 21152 UPS2Nothing
0.9.2
Shin Megami Tensei - Digital Devil Saga SLES 53458 EPS2Playable
0.9.2
Shin Megami Tensei - Digital Devil Saga SLUS 20974 UPS2Nothing
0.9.2
Shin Megami Tensei - Nocturne SLUS 20911 UPS2Nothing
0.9.2
Shin Sangoku Musou 2 SLPM 65053 JPS2Playable
0.9.2
Shining Force Neo SLUS 21206 UPS2Playable
0.9.2
Shining Tears SLUS 21063 UPS2Playable
0.9.2
Shinobi SLUS 20459 UPS2Nothing
0.9.2
Shinobido - Way of The Ninja SCES 53931 EPS2Ingame
0.9.2
Shougi, The SLPM 62180 JPS2Playable
0.9.2
Shox SLES 51144 EPS2Intro
0.9.2
Shox SLES 51250 EPS2Intro
0.9.2
Shrek 2 SLUS 20745 UPS2Intro
0.9.2
Shrek Superslam SLUS 21197 UPS2Playable
0.9.2
Silent Hill 2 - Saigo no Uta SLPM 65098 JPS2Nothing
0.9.2
Silent Hill 2 SLPM 65051 JPS2Nothing
0.9.2
Silent Hill 3 SLPM 65257 JPS2Nothing
0.9.2
Silent Hill 3 SLUS 20622 UPS2Intro
0.9.2
Silent Hill 4 - The Room SLES 52445 EPS2Playable
0.9.2
Silent Hill 4 - The Room SLPM 65574 JPS2Ingame
0.9.2
Silent Hill 4 - The Room SLUS 20873 UPS2Playable
0.9.2
Silent Line - Armored Core SLES 52203 EPS2Playable
0.9.2
Silent Scope 2 SLUS 20243 UPS2Nothing
0.9.2
Silpheed - The Lost Planet SLES 50193 EPS2Ingame
0.9.2
Silpheed the Lost Planet SLPM 62015 JPS2Playable
0.9.2
Simple 2000 Series - Vol. 81 - The Chikyuu Boueigun 2 SLPM 62652 JPS2Nothing
0.9.2
Simple 2000 Series - Vol.69 - The Board Games Collection SLPM 62580 JPS2Playable
0.9.2
Simple 2000 Series ULTIMATE - Vol. 22: Stylish Mahjongg SLPM 62571 JPS2Playable
0.9.2
Simple Series 2000 - Vol. 16 - The Sniper 2 SLPM 62459 JPS2Playable
0.9.2
Simple Series 2000 - Vol. 55 - The Catfight - Joneko Densetsu SLPM 62494 JPS2Ingame
0.9.2
Simple Series 2000 - Vol. 59 - The Uchuujin to Hanashi Sou! SLPM 62524 JPS2Playable
0.9.2
Simple Series 2000 - Vol. 60 - The Tokusatsu Henshin Hero SLPM 62510 JPS2Ingame
0.9.2
Simple Series 2000 - Vol. 61 - The Oane Chapara SLPM 62525 JPS2Ingame
0.9.2
Simple Series 2000 - Vol. 63 - The Suieitaikai SLPM 62534 JPS2Ingame
0.9.2
Simple Series 2000 - Vol. 64 - The Splatter Action SLPM 62545 JPS2Menus
0.9.2
Simple Series 2000 - Vol. 91 - The ALL STAR Fighting SLPS 20430 JPS2Intro
0.9.2
Simple Series 2000 - Vol. 99 - The Genshijin SLPS 20461 JPS2Nothing
0.9.2
Simple Series 2000 - Vol.106 - The Block Kuzushi Quest SLPS 20468 JPS2Playable
0.9.2
Simply... The Best For Less - Vol. 6 Ultimate Casino SLES 52515 EPS2Ingame
0.9.2
Simpsons Hit & Run, The SLES 51897 EPS2Nothing
0.9.2
Simpsons Hit & Run, The SLUS 20624 UPS2Nothing
0.9.2
Simpsons Road Rage, The SLUS 20305 UPS2Nothing
0.9.2
Simpsons Skateboarding SLUS 20114 UPS2Playable
0.9.2
Sims - Bustin' Out, The SLUS 20842 UPS2Intro
0.9.2
Sims - The Urbz, The SLES 52908 EPS2Playable
0.9.2
Sims 2 SLUS 21265 UPS2Ingame
0.9.2
Sims 2: Pets SLUS 21536 UPS2Nothing
0.9.2
Sims Bustin Out, The SLES 52047 EPS2Playable
0.9.2
Sims SLUS 20573 UPS2Intro
0.9.2
Singstar Anthems SCES 54131 EPS2Menus
0.9.2
Siren 2 SCPS 15106 JPS2Nothing
0.9.2
Siren SCPS 15053 JPS2Playable
0.9.2
Skygunner SCPS 11006 JPS2Ingame
0.9.2
Skygunner SLUS 20384 UPS2Playable
0.9.2
Slotter Up Core 4 SLPS 20378 JPS2Nothing
0.9.2
Sly 2 - Band of Thieves SCES 52529 EPS2Playable
0.9.2
Sly 2 - Band of Thieves SCUS 97316 UPS2Menus
0.9.2
Sly 3 - Honor Among Thieves SCUS 97464 UPS2Ingame
0.9.2
Sly Cooper And The Thievious Raccoonus SCUS 97198 UPS2Playable
0.9.2
Smackdown - Just Bring It SLUS 20316 UPS2Playable
0.9.2
Smackdown - Shut Your Mouth SLUS 20483 UPS2Playable
0.9.2
Smuggler's Run SLES 50061 EPS2Playable
0.9.2
Sniper Elite SLUS 21231 UPS2Intro
0.9.2
SNK vs Capcom - SVC Chaos SLES 53065 EPS2Playable
0.9.2
SNK vs Capcom - SVC Chaos SLPS 25316 JPS2Playable
0.9.2
Snoopy Vs The Red Baron SLUS 21380 UPS2Menus
0.9.2
Socom - US Navy Seals 2 SCUS 97275 UPS2Menus
0.9.2
Socom - US Navy Seals 3 SCUS 97474 UPS2Intro
0.9.2
Socom US Navy Seals - Combined Assault SCUS 97545 UPS2Menus
0.9.2
Soldier of Fortune 2 SLUS 20084 UPS2Ingame
0.9.2
Sonic Gems Collection SLES 53350 EPS2Playable
0.9.2
Sonic Gems Collection SLPM 66074 JPS2Playable
0.9.2
Sonic Heroes SLUS 20718 UPS2Intro
0.9.2
Sonic Mega Collection Plus SLES 52998 EPS2Playable
0.9.2
Sonic Mega Collection SLUS 20917 UPS2Playable
0.9.2
Sonic Riders SLES 53560 EPS2Playable
0.9.2
Sonic Riders SLUS 21331 UPS2Playable
0.9.2
Sopranos - Road To Respect SLUS 21388 UPS2Ingame
0.9.2
Soul Calibur II SLES 51799 EPS2Ingame
0.9.2
Soul Calibur II SLPS 25230 JPS2Ingame
0.9.2
Soul Calibur II SLUS 20643 UPS2Ingame
0.9.2
Soul Calibur III SCES 53312 EPS2Intro
0.9.2
Soul Calibur III SLPS 25577 JPS2Intro
0.9.2
Soul Calibur III SLUS 21216 UPS2Intro
0.9.2
Space Channel 5 - Special Edition SLUS 20806 UPS2Playable
0.9.2
Space Channel 5 Part 2 SLPM 65096 JPS2Playable
0.9.2
Space Fishermen SCPS 11025 JPS2Ingame
0.9.2
Space Invaders - Invasion Day SLES 51746 EPS2Playable
0.9.2
Spartan - Total Warrior SLUS 21212 UPS2Menus
0.9.2
Spawn - Armageddon SLUS 20707 UPS2Playable
0.9.2
Spider-Man SLES 50814 GPS2Playable
0.9.2
Spiderman 2 SLUS 20776 UPS2Menus
0.9.2
Spiderman SLUS 20336 UPS2Playable
0.9.2
Splinter Cell - Chaos Theory SLUS 21137 UPS2Menus
0.9.2
Splinter Cell - Double Agent SLUS 21356 UPS2Intro
0.9.2
Splinter Cell - Pandora Tomorrow SLUS 20958 UPS2Ingame
0.9.2
Spongebob Schwammkopf - Schlacht um Bikini Bottom SLES 51970 GPS2Playable
0.9.2
Spongebob Squarepants - Creature From The Krusty Krab SLUS 21391 UPS2Ingame
0.9.2
Spongebob Squarepants - Revenge of the Flying Dutchman SLES 51285 EPS2Menus
0.9.2
Spongebob Squarepants - Revenge of the Flying Dutchman SLUS 20425 UPS2Intro
0.9.2
Sprint Cars - The Road to Knoxville SLUS 21418 UPS2Ingame
0.9.2
Spy Fiction SLUS 20856 UPS2Playable
0.9.2
Spy Hunter - Nowhere To Run SLUS 21421 UPS2Playable
0.9.2
Spy Hunter 2 SLUS 20590 UPS2Intro
0.9.2
Spy VS Spy SLES 53078 EPS2Ingame
0.9.2
Spyro - A Hero's Tale SLES 52569 EPS2Playable
0.9.2
Spyro - A Hero's Tale SLUS 20884 UPS2Playable
0.9.2
SSX - On Tour SLUS 21278 UPS2Ingame
0.9.2
SSX 3 SLUS 20772 UPS2Ingame
0.9.2
SSX PBPX 95201 UPS2Playable
0.9.2
Stacked SLUS 21259 UPS2Intro
0.9.2
Star Ocean - Till the End of Time SLUS 20488 UPS2Nothing
0.9.2
Star Trek - Encounters SLUS 21396 UPS2Playable
0.9.2
Star Trek - Shattered Universe SLUS 20112 UPS2Ingame
0.9.2
Star Trek Voyager - Elite Force SLES 50738 EPS2Nothing
0.9.2
Star Wars - Battlefront 2 SLUS 21240 UPS2Ingame
0.9.2
Star Wars - Bounty Hunter SLUS 20420 UPS2Playable
0.9.2
Star Wars - Clone Wars SLUS 20510 UPS2Ingame
0.9.2
Star Wars - Racer Revenge SLUS 20268 UPS2Playable
0.9.2
Star Wars - Starfighter SLUS 20044 UPS2Ingame
0.9.2
Star Wars - Super Bombad Racing PBPX 95201 UPS2Nothing
0.9.2
Star Wars Episode 3 - Revenge of the Sith SLES 53155 EPS2Ingame
0.9.2
Star Wars Episode 3 - Revenge of The Sith SLUS 21143 UPS2Ingame
0.9.2
Starsky & Hutch SLES 51783 EPS2Ingame
0.9.2
State of Emergency 2 SLUS 20966 UPS2Ingame
0.9.2
State of Emergency SLUS 20214 UPS2Menus
0.9.2
Steambot Chronicles SLUS 21344 UPS2Nothing
0.9.2
Steamboy SLPS 25502 JPS2Playable
0.9.2
Steel Lancer Arena International SLUS 20969 UPS2Playable
0.9.2
Stella Deus SLUS 21132 UPS2Playable
0.9.2
Stitch - Experiment 626 SCUS 97145 UPS2Playable
0.9.2
Stock Car Crash SLES 53972 EPS2Ingame
0.9.2
Stolen SLES 52882 EPS2Intro
0.9.2
Stolen SLUS 21099 UPS2Menus
0.9.2
Street Fighter - Alpha Anthology SLUS 21317 UPS2Ingame
0.9.2
Street Fighter EX3 PBPX 95201 UPS2Playable
0.9.2
Street Fighter EX3 SLES 50072 EPS2Ingame
0.9.2
Street Fighter EX3 SLUS 20130 UPS2Playable
0.9.2
Street Fighter Zero - Fighters Generation SLPM 66409 JPS2Playable
0.9.2
Street Racing Syndicate SLES 53045 EPS2Ingame
0.9.2
Street Racing Syndicate SLUS 20582 UPS2Nothing
0.9.2
Strikers 1945 I & II SLPM 62515 JPS2Playable
0.9.2
Strikers 1945 III SLKA 15005 JPS2Playable
0.9.2
Stuntman SLES 50288 EPS2Ingame
0.9.2
Suffering, The - Ties That Bind SLUS 21189 UPS2Intro
0.9.2
Suffering, The SLUS 20636 UPS2Intro
0.9.2
Suikoden III SLUS 20387 UPS2Playable
0.9.2
Suikoden IV SLES 52913 EPS2Playable
0.9.2
Suikoden IV SLUS 20979 UPS2Ingame
0.9.2
Suikoden Tactics SLUS 21245 UPS2Ingame
0.9.2
Suikoden V SLUS 21291 UPS2Ingame
0.9.2
Sum of All Fears, The SLES 51180 EPS2Playable
0.9.2
Summer Heat Beach Volleyball SLES 51778 EPS2Ingame
0.9.2
Summer Heat Beach Volleyball SLUS 20634 UPS2Ingame
0.9.2
Summoner 1 SLES 82005 GPS2Ingame
0.9.2
Summoner 1 SLUS 20074 UPS2Ingame
0.9.2
Summoner 2 SLES 51142 GPS2Playable
0.9.2
Super Bust-A-Move 2 SLUS 20460 UPS2Playable
0.9.2
Super Bust-A-Move PBPX 95201 UPS2Playable
0.9.2
Super Bust-A-Move SLES 50076 EPS2Playable
0.9.2
Super Bust-A-Move SLUS 20115 UPS2Playable
0.9.2
Super Dimensional Fortress Macross SLPM 65405 JPS2Nothing
0.9.2
Super Dragon Ball Z SLUS 21442 UPS2Playable
0.9.2
Super Monkey Ball Adventure SLUS 21272 UPS2Ingame
0.9.2
Super Puzzle Bobble SLPM 62016 JPS2Playable
0.9.2
Super Robot Wars 3 SLPS 25537 JPS2Playable
0.9.2
Super Shanghai 2005 SLPM 62552 JPS2Playable
0.9.2
Super Trucks SLES 50897 EPS2Ingame
0.9.2
Superior Defender Gundam Force Showdown! SLUS 20698 UPS2Ingame
0.9.2
Superman - Shadow of Apokolips SLUS 20235 UPS2Ingame
0.9.2
Suzuki TT Superbikes SLUS 20912 UPS2Ingame
0.9.2
Sven Göran Eriksson's World Manager 2002 SLES 50794 EPS2Menus
0.9.2
SWAT - Global Strike Team SLES 52097 EPS2Ingame
0.9.2
SWAT - Global Strike Team SLUS 20433 UPS2Ingame
0.9.2
Switch SLPM 65121 JPS2Playable
0.9.2
Sword of Etheria SLES 53768 EPS2Ingame
0.9.2
Sword of The Berserk - Gut's Rage SLPM 65688 JPS2Playable
0.9.2
Swords of Destiny SLES 53699 EPS2Playable
0.9.2
SX Superstars SLES 51495 EPS2Ingame
0.9.2
Syberia SLES 51393 EPS2Ingame
0.9.2
Syphon Filter - The Omega Strain SCES 52033 EPS2Ingame
0.9.2
Syphon Filter - The Omega Strain SCUS 97264 UPS2Menus
0.9.2
Taisho Mononoke Ibunroku SLPM 65228 JPS2Playable
0.9.2
Taito Legends SLES 53438 EPS2Playable
0.9.2
Tak - The Great Juju Challenge SLUS 21218 UPS2Ingame
0.9.2
Tales of Legendia SLPS 25533 JPS2Ingame
0.9.2
Tales of Legendia SLUS 21201 UPS2Ingame
0.9.2
Tales of The Abyss SLUS 21386 UPS2Playable
0.9.2
Taz Wanted SLES 50649 EPS2Playable
0.9.2
TD overdrive - The Brotherhood Of Speed SLES 50778 EPS2Intro
0.9.2
Teen Titans SLUS 21183 UPS2Menus
0.9.2
Teenage Mutant Ninja Turtles 2 - Battle Nemesis SLUS 20981 UPS2Ingame
0.9.2
Teenage Mutant Ninja Turtles SLES 51931 EPS2Playable
0.9.2
Tekken 4 SCES 50878 EPS2Playable
0.9.2
Tekken 4 SLUS 20328 UPS2Nothing
0.9.2
Tekken 5 SCES 53202 EPS2Intro
0.9.2
Tekken 5 SLPS 25510 JPS2Ingame
0.9.2
Tekken 5 SLUS 21059 UPS2Intro
0.9.2
Tekken Tag Tournament SCES 50001 EPS2Ingame
0.9.2
Tekken Tag Tournament SLPS 20015 JPS2Ingame
0.9.2
Tenchu - Fatal Shadows SLUS 21129 UPS2Ingame
0.9.2
Tenchu - Wrath of Heaven SLES 51402 GPS2Ingame
0.9.2
Tenchu - Wrath of Heaven SLUS 20397 UPS2Menus
0.9.2
Tennis Court Smash SLES 51860 EPS2Menus
0.9.2
Terminator 3 - The Redemption SLUS 20852 UPS2Intro
0.9.2
Terminator, The - Dawn Of Fate SLUS 20391 UPS2Ingame
0.9.2
Test Drive - Eve of Destruction SLUS 20910 UPS2Ingame
0.9.2
Tetris Worlds SLUS 20247 UPS2Playable
0.9.2
Theme Park World SLES 50032 EPS2Playable
0.9.2
Thing, The SLUS 20371 UPS2Nothing
0.9.2
Tiger Woods PGA Tour 2005 SLUS 21002 UPS2Ingame
0.9.2
Tiger Woods PGA Tour 2006 SLUS 21264 UPS2Intro
0.9.2
Tiger Woods PGA Tour 2007 SLUS 21483 UPS2Intro
0.9.2
Time Crisis - Crisis Zone SLUS 20927 UPS2Playable
0.9.2
Time Crisis 2 SLUS 20219 UPS2Nothing
0.9.2
Timesplitters 2 SLES 50877 EPS2Nothing
0.9.2
Timesplitters 3 SLUS 21148 UPS2Ingame
0.9.2
Timesplitters PBPX 95201 UPS2Menus
0.9.2
Timesplitters SLES 50078 EPS2Playable
0.9.2
Timesplitters SLUS 20090 UPS2Menus
0.9.2
Toca Race Driver 3 SLUS 21182 UPS2Menus
0.9.2
Tokimeki Memorial 3 SLPM 65080 JPS2Nothing
0.9.2
Tokobot Plus - Mysteries Of The Karakuri SLUS 21471 UPS2Ingame
0.9.2
Tokyo Extreme Racer 3 SLUS 20831 UPS2Ingame
0.9.2
Tokyo Extreme Racer Drift SLUS 21236 UPS2Intro
0.9.2
Tokyo Road Race SLES 50954 EPS2Ingame
0.9.2
Tom Clancy's Rainbow Six - Lockdown SLUS 21144 UPS2Intro
0.9.2
Tom Clancy's Splinter Cell Chaos Theory SLES 53007 EPS2Ingame
0.9.2
Tomb Raider - Angel of Darkness SLUS 20467 UPS2Nothing
0.9.2
Tomb Raider Legend SLES 53908 EPS2Ingame
0.9.2
Tomb Raider Legend SLUS 21203 UPS2Ingame
0.9.2
Tony Hawk's American Wasteland SLUS 21208 UPS2Intro
0.9.2
Tony Hawk's Pro Skater 3 SLUS 20013 UPS2Intro
0.9.2
Tony Hawk's Underground 2 SLUS 20965 UPS2Intro
0.9.2
Tony Hawk's Underground SLES 51852 GPS2Intro
0.9.2
Tony Hawks Project 8 SLUS 21444 UPS2Intro
0.9.2
Tony Hawks Underground SLUS 20731 UPS2Intro
0.9.2
Top Spin SLUS 21222 UPS2Intro
0.9.2
Torino 2006 SLES 53901 EPS2Ingame
0.9.2
Total Immersion Racing SLES 51128 EPS2Playable
0.9.2
Total Immersion Racing SLUS 20409 UPS2Ingame
0.9.2
Total Overdose - A Gunslinger's Tale In Mexico SLUS 21283 UPS2Ingame
0.9.2
Tourist Trophy - Real Riding Simulator SCAJ 20170 JPS2Intro
0.9.2
Tourist Trophy SCUS 97502 UPS2Intro
0.9.2
Transformers SLES 52388 EPS2Intro
0.9.2
Transformers SLUS 20668 UPS2Intro
0.9.2
Transworld Surf SLUS 20356 UPS2Playable
0.9.2
Trapt SLUS 21255 UPS2Ingame
0.9.2
Tribes Aerial Assault SLUS 20149 UPS2Intro
0.9.2
Triggerman SLUS 20931 UPS2Nothing
0.9.2
True Crime - New York City SLUS 21106 UPS2Intro
0.9.2
True Crimes - Streets Of L.A. SLUS 20550 UPS2Menus
0.9.2
Tsugunai Atonement SLUS 20292 UPS2Nothing
0.9.2
Tsukiyo Ni Saraba SLPM 65826 JPS2Ingame
0.9.2
Turok - Evolution SLES 51124 GPS2Ingame
0.9.2
Turok - Evolution SLUS 20333 UPS2Ingame
0.9.2
Twenty 2 Party SLES 53369 EPS2Playable
0.9.2
Twin Caliber SLES 51226 EPS2Playable
0.9.2
Twisted Metal - Black SCUS 97101 UPS2Playable
0.9.2
Ty The Tasmanian Tiger SLUS 20571 UPS2Nothing
0.9.2
Ty The Tazmanian Tiger 3 SLUS 21253 UPS2Ingame
0.9.2
UFC - Sudden Impact SLUS 20596 UPS2Intro
0.9.2
UFC Throwdown SLUS 20252 UPS2Ingame
0.9.2
Ultimate Board Game Collection SLUS 21366 UPS2Nothing
0.9.2
Ultimate Spiderman SLUS 20870 UPS2Menus
0.9.2
Unison SLPS 25010 JPS2Ingame
0.9.2
Unlimited Saga SLUS 20678 UPS2Menus
0.9.2
Unreal Tournament SLES 50074 EPS2Playable
0.9.2
Unrun Quest SLPM 66028 JPS2Menus
0.9.2
Urban Chaos - Riot Response SLUS 21390 UPS2Ingame
0.9.2
Urban Reign SCES 53688 EPS2Nothing
0.9.2
Urban Reign SLUS 21209 UPS2Ingame
0.9.2
V-Rally 3 SLES 50725 EPS2Ingame
0.9.2
Valkyrie Profile 2 - Silmeria SLPM 66419 JPS2Nothing
0.9.2
Valkyrie Profile 2 - Slimeria SLUS 21452 UPS2Nothing
0.9.2
Vampire Darkstalkers Collection SLPM 65998 JPS2Ingame
0.9.2
Vampire Night SCES 50411 EPS2Playable
0.9.2
Vampire Night SLPS 25077 JPS2Playable
0.9.2
Vampire Night SLUS 20221 UPS2Playable
0.9.2
Van Helsing SLUS 20738 UPS2Ingame
0.9.2
Venus & Braves SLPS 25195 JPS2Ingame
0.9.2
Vexx SLES 50481 EPS2Menus
0.9.2
Vexx SLUS 20383 UPS2Ingame
0.9.2
Vietcong - Purple Haze SLUS 21068 UPS2Ingame
0.9.2
Viewtiful Joe 2 SLPM 65824 JPS2Playable
0.9.2
Viewtiful Joe SLPM 65699 JPS2Playable
0.9.2
Viewtiful Joe SLUS 20951 UPS2Playable
0.9.2
Virtua Cop Elite Edition SLES 51229 EPS2Playable
0.9.2
Virtua Cop Re-Birth SLPM 62205 JPS2Playable
0.9.2
Virtua Fighter 4 - Evolution SLES 51616 EPS2Playable
0.9.2
Virtua Fighter 4 - Evolution SLUS 20616 UPS2Playable
0.9.2
Virtua Fighter 4 SCES 50759 EPS2Playable
0.9.2
Virtua Fighter 4 SLPM 62130 JPS2Playable
0.9.2
Virtua Fighter 4 SLUS 20323 UPS2Playable
0.9.2
Virtua Quest SLUS 20977 UPS2Ingame
0.9.2
Virtua Tennis 2 SLES 51232 EPS2Playable
0.9.2
Virtual On - Mars SLUS 20674 UPS2Playable
0.9.2
Volleyball Xciting SLES 51765 EPS2Playable
0.9.2
WakuWaku Volley 2 SLPM 62285 JPS2Playable
0.9.2
Wallace & Gromit in Project Zoo SLES 51989 EPS2Ingame
0.9.2
Wallace & Grommit in Projekt Zoo SLES 52026 GPS2Ingame
0.9.2
Wanda to Kyozou SCPS 15097 JPS2Ingame
0.9.2
Warriors, The SLUS 21215 UPS2Ingame
0.9.2
Warship Gunner 2 SLUS 21387 UPS2Nothing
0.9.2
Way of The Samurai SLUS 20407 UPS2Nothing
0.9.2
Way of The Samurai 2 SLES 52275 EPS2Playable
0.9.2
Way of The Samurai 2 SLUS 20893 UPS2Playable
0.9.2
We Love Katamari SLUS 21230 UPS2Intro
0.9.2
Wheel of Fortune SLUS 20790 UPS2Ingame
0.9.2
Whiplash SLES 51958 EPS2Ingame
0.9.2
Whiplash SLUS 20684 UPS2Ingame
0.9.2
Wild Arms 3 SCUS 97203 UPS2Ingame
0.9.2
Wild Arms 4 SLUS 21292 UPS2Nothing
0.9.2
Wild Arms Alter Code - F SLUS 20937 UPS2Playable
0.9.2
Wild Wild Racing SLES 50009 EPS2Playable
0.9.2
Winback 2 - Project Poseidon SLUS 20947 UPS2Ingame
0.9.2
Winning Eleven 10 SLPM 66374 JPS2Intro
0.9.2
Winning Eleven 6 SLPM 62268 JPS2Playable
0.9.2
Winning Eleven 7 SLPM 62356 JPS2Playable
0.9.2
Winning Eleven 9 International SLUS 21220 UPS2Intro
0.9.2
Winning Eleven 9 SLPM 66009 JPS2Ingame
0.9.2
WipEout Fusion SCES 50005 EPS2Playable
0.9.2
Wipeout Fusion SLUS 20462 UPS2Intro
0.9.2
Without Warning SLUS 21156 UPS2Nothing
0.9.2
Woody Woodpecker PBPX 95201 JPS2Playable
0.9.2
Worimagesoundplay SLPM 65484 JPS2Ingame
0.9.2
World Championship Poker - All In SLUS 21412 UPS2Playable
0.9.2
World Championship Pool 2004 SLUS 20760 UPS2Playable
0.9.2
World Poker Tour SLUS 21333 UPS2Ingame
0.9.2
World Rally Championship 3 SLPM 65583 JPS2Ingame
0.9.2
World Rally Championship 4 SCES 52389 EPS2Ingame
0.9.2
World Rally Championship SCES 50139 EPS2Nothing
0.9.2
World Series of Poker - Tournament of Champions SLUS 21491 UPS2Intro
0.9.2
World Series Of Poker SLUS 21301 UPS2Playable
0.9.2
Worms 4 - Mayhem SLES 53096 EPS2Ingame
0.9.2
Worms Forts Under Seige SLES 52342 EPS2Playable
0.9.2
WRC Rally Evolved SCES 53247 EPS2Ingame
0.9.2
Wrestle Kingdom SLPM 66401 JPS2Nothing
0.9.2
WTA Tennis Tour USA SLPM 62046 JPS2Playable
0.9.2
WWE Smackdown VS Raw 2006 SLES 53676 EPS2Ingame
0.9.2
WWE Smackdown VS Raw 2006 SLUS 21286 UPS2Playable
0.9.2
WWE Smackdown VS Raw 2007 SLUS 21427 UPS2Menus
0.9.2
WWE Smackdown VS Raw SLUS 21060 UPS2Menus
0.9.2
WWE Smackdown! Here Comes the Pain SLUS 20787 UPS2Playable
0.9.2
X-Files, The - Resist or Serve SLUS 20179 UPS2Ingame
0.9.2
X-Men 3 - The Official Game SLUS 21107 UPS2Menus
0.9.2
X-Men Legends 2 - Rise of The Apocalypse SLUS 21138 UPS2Playable
0.9.2
X-Men Legends SLUS 20656 UPS2Playable
0.9.2
X-Treme Quads SLES 53141 EPS2Intro
0.9.2
X2 - Wolverine's Revenge SLUS 20337 UPS2Menus
0.9.2
Xenosaga Episode 3 - Also Sprach Zarathustra SLPS 25640 JPS2Ingame
0.9.2
Xenosaga Episode I - Der Wille zur Macht SLUS 20469 UPS2Nothing
0.9.2
Xenosaga Episode II - Jenseits von Gut und Bose SLUS 20892 UPS2Ingame
0.9.2
Xenosaga Episode III - Also Sprach Zarathustra SLUS 21389 UPS2Ingame
0.9.2
XGIII - Extreme G Racing SLES 50210 EPS2Playable
0.9.2
XIII SLES 51244 EPS2Ingame
0.9.2
XIII SLUS 20677 UPS2Menus
0.9.2
Yakuza SLES 54171 EPS2Menus
0.9.2
Yakuza SLUS 21348 UPS2Ingame
0.9.2
Yoshinoya SLPM 62489 JPS2Playable
0.9.2
Ys: Ark Of Napishtim SLUS 20980 UPS2Playable
0.9.2
Yu-Gi-Oh! Capsule Monster Coliseum SLUS 20940 UPS2Playable
0.9.2
Yu-Gi-Oh! The Duelists of the Roses SLUS 20515 UPS2Playable
0.9.2
Zatch Bell - Mamodo Battles SLUS 21254 UPS2Ingame
0.9.2
Zatch Bell - Mamodo Fury SLUS 21363 UPS2Nothing
0.9.2
Zathura SLES 53696 EPS2Playable
0.9.2
Zathura SLUS 21336 UPS2Ingame
0.9.2
Zettai Zetsumei Toshi SLPS 25113 JPS2Nothing
0.9.2
Zone Of The Enders - The 2nd Runner SLES 51113 EPS2Playable
0.9.2
Zone Of The Enders - The 2nd Runner SLUS 20545 UPS2Nothing
0.9.2
Zone of the Enders SLPM 65019 JPS2Ingame
0.9.2
Zone of The Enders SLUS 20148 UPS2Ingame
0.9.2
Zooo SLPM 62466 JPS2Ingame
0.9.2
+
+ \ No newline at end of file diff --git a/bin/compat_list/h_console.jpg b/bin/compat_list/h_console.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c589631fae6448736182f3030663a4d8a1e89ab6 GIT binary patch literal 544 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMov=hM7^2fk}{&S&;Gn5r#wt zMj!yX5)N3Inb=W9KvDt>j4X`IKq;6yMkZz!RzU_KVMP%(Wl_V#LM5XhRY4S!KuZ7L zV&GwB1lq?e$Y9U#rbNHO>4Cv&%_Whd`ct(gE2@E z^lsi($k3Bv| zmQ^@8P%Qeq!?fCkv!(tsgzS3U$*H>|=452h#);P*`e)n=^KXrNW0`9$;-kB7tJQ1Y p^wxClXy*!fU&fky`fq=}ORR4Dll%USMa9S8>2+`ZY?1$e69BBKj57cL literal 0 HcmV?d00001 diff --git a/bin/compat_list/h_region.jpg b/bin/compat_list/h_region.jpg new file mode 100644 index 0000000000000000000000000000000000000000..515ea4f33bd96e9647997e24ca7ff5716ccda75f GIT binary patch literal 486 zcmex=iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMouVpP5mRfk}{&S&;Gn5r!BB z24+T}Bar|z3p*p45Cek%0}~S?Gczk(9U~Jn3oC=5p`xR3qL7jZn;?dk|F;-;fMzoZ zG7B=;GhEAhv}O+1)7%wN`##0p30t#ug3VDzfsGNCFVD;EV#@q@+;XBM=WEvJOWKw1 zV%h>F5-%pVKinXbp>f*3MKb%fYDZ(p$}eGOX9pZhGE~|BcppDvdLD8NV@C-q!s8CIFiF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMouVmzhzJfk}{&S&;Gn5r!BB zMn*=UBN2d=g&j=(86|xzpEk#(7^*NiglYP$GKP&f>X|vZ8ImwR;oSJ>OX* z>5_Q(aB}+>2ipvx*}}={^Y&;Q7o9c1J-m6|-5r5_tx?g3{GKx3-t&TgtMxw3w<~SV zbw4^TIrZo|z4vXC9$k8WB0h7$qHEg9U3S-duj+CF)G)|FS0F%uS*@ZR!oxuE%7 c{`tPu2R{XVud+5iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMov=l$lYGfk}{&S&;Gn5r#yd zvzZxzu7m?tW)?PfMie2CoB#t86B8pd6FW?Xk%^f_kX495QP_~pG0@0KSwxgw5GDyX z?f)$X9-#S5g3N*p_6#rYZ+4qfIjt)Ex%>M=Umt2u`XSN7>a)U@ZF}j0YxX-!JHi6C z-#UFOFsYO$$l!E?4C`U}?Xs-WRo2sMk8WyP6X?t8vZiC3Zd7}RVU>Q%yvXBqu`EK_ z4`=`RC);u?xQgY$q&1g%m{XcKc$mv9-e1t&Y_&c=*JS^cs|%tod!iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMouVg_%*1fk}{&S&;Gn5r#wt z1}0{pBN2d+iJ6t1kr5#PVF@rWurf2Tvckm~1(}#xgoIfcL<}88*~AnR3yp#VF|_@^ z#lXYN2(*t`kinkeUQMy^)7@Tix8H0x`!2-w_Ena3`{C)lOj^vs8zrBobaxlY>^#-8 zWY^=84h0swF3$<=j2B#f8yHH+=sel6P3X@Izq6%zJ2nU`aCI_WnIgAm3-g}h87Dt% ze0O--<&91W+kRbnz1E~GOl9j9(T17~t@ma7{cX?aEsPA_eiF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgMov=f|*f}fk}{&S&;Gn5r#wt zMj!yX5)N3InAuT9KvDt>jLb}|ER3u$b&O2REP|{IibBGohDIV{g-XiBs%(NNCV`ax zzs11A%m}oPS&+e=;q9FXU+cI}*d30wQ(L@0_V20ikIz3gXg+^?>}R1k`(u`6#hqb) zPWJ4Q=8{z1R@cRNnPKv^nc~)8963&~p^lrGC#*{|Iuah`_Pj$Ms78)xHD+_xMmO}6f{xlvyyu!Lz1fq@K zV_^6OhG#D30lApXXCMb?Y+#;H)BSpT0D%D*S@l9PX?Cj(n${XJcO1bPV;$<9{de}j}@5dr8q%6u@?(|r=(D-L0eILYcK`qY literal 0 HcmV?d00001 diff --git a/bin/compat_list/sq_intro.jpg b/bin/compat_list/sq_intro.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e7b8a3cc44c0567642c30c47ce6498590faeeb71 GIT binary patch literal 305 zcma)$O$x#=5QX2^G^uIYCZvU81ur6qAmYz0w60vZa^c>Cb>SiWS?B@8E5zVJP&a;$ zf#Dk%o;$i5^lUsGgIYlC19yiRZI|mE2n;~qs|V6yy;-bKH{OuDU=Pk13mFeX-sXPd zi1R2`QpQp$tzKxAW;#oiwRvuBx2mdc?+pnd5|xx%mz}~Co%iA2#WgSyd;&6P843)! g1LnT=CxYlpaiPBqV1A4{Lj~kN2L=O-Cdt*Eo}fV{4FCWD literal 0 HcmV?d00001 diff --git a/bin/compat_list/sq_menus.jpg b/bin/compat_list/sq_menus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f2defa6a2a5eabf284222fb90b9f35d91ba33a1 GIT binary patch literal 305 zcma)$Jqp4=5QX2E{fV13?y?3#B8c}8M38`b3yqb9m4&?rOW`5>X*_^|tI)W+{I zFnj~U^Cy3UnOCz4)B@@d_&e-$x7zGMU;suzJ&;c7?Q)H}35NU?2MER(XM%Il7GaWD zh&a(oB}!?dUl^TsO*hrf^?J_r%d+eb-jI~CqdU1Vd6C(ycpv^SyCVn;z|g1{qH(=nZ&5eKkiO#t&KPqTcO2g1 zW&)3MFA%;T_`Z$;%`b1Cy8Q(4g+{#|qn<-x=z1xt~w gNT0DVwZGv+J;hwvGl2Rr`UYW>`D`nUu|Gjy-+QDbpa1{> literal 0 HcmV?d00001 diff --git a/bin/inis/pcsx2.ini b/bin/inis/pcsx2.ini new file mode 100644 index 0000000..3de13e5 --- /dev/null +++ b/bin/inis/pcsx2.ini @@ -0,0 +1,32 @@ +[Interface] +Bios= +Lang=en_US +PluginsDir=plugins/ +BiosDir=bios/ +Ps2Out=1 +ThPriority=0 +Mcd1=memcards/Mcd001.ps2 +Mcd2=memcards/Mcd002.ps2 +[Plugins] +GS=ZeroGS KOSMOS 0.96 sse2.dll +SPU2=spu2PeopsSound.dll +CDVD=CDVDiso.dll +PAD1=PadSSSPSX.dll +PAD2=PadSSSPSX.dll +DEV9=DEV9null.dll +USB=USBnull.dll +FW=FWnull.dll +[Cpu Options] +Cpu=0 +Vurec=0 +Regcache=0 +SafeCnts=0 +InterlaceHack=0 +SPU2Hack=0 +Multithreading=0 +GSMulti=0 +Options=496 +[Misc] +Patch=1 +PadHack=0 +varLog=0 diff --git a/bin/patches/013E349D.pnach b/bin/patches/013E349D.pnach new file mode 100644 index 0000000..d6b538c --- /dev/null +++ b/bin/patches/013E349D.pnach @@ -0,0 +1,4 @@ +gametitle= Resident Evil 4 [SLUS 21134] (U) +comment= +//ZeroGS Patch - GAME_NOTARGETCLUT +zerogs=00001000 \ No newline at end of file diff --git a/bin/patches/015314A2.pnach b/bin/patches/015314A2.pnach new file mode 100644 index 0000000..a03a6a2 --- /dev/null +++ b/bin/patches/015314A2.pnach @@ -0,0 +1,4 @@ +gametitle= Sims - The Urbz, The [SLES 52908] (E) +comment= +//ZeroGS Patch - GAME_NOQUICKRESOLVE +zerogs=00000800 \ No newline at end of file diff --git a/bin/patches/034836F8.pnach b/bin/patches/034836F8.pnach new file mode 100644 index 0000000..6bbc24d --- /dev/null +++ b/bin/patches/034836F8.pnach @@ -0,0 +1,13 @@ +gametitle=Driving Emotion Type-S [SLPS 20007] (J) +comment= patches by Nachbrenner +//Skip OP_MOVIE +//patch=0,EE,001c1818,word,1000000c +//MTGS: fix GS_CSR in "sceGsExecStoreImage" +patch=0,EE,00276ad0,word,34420002 +patch=0,EE,00276aa0,word,34630002 +//MTGS: fix GS_CSR in custom function +patch=0,EE,00251ac4,word,00000000 +//disable BGM +patch=0,EE,00221914,word,24020000 +patch=0,EE,002218c8,word,03e00008 +patch=0,EE,002218cc,word,00000000 \ No newline at end of file diff --git a/bin/patches/0442B1BD.pnach b/bin/patches/0442B1BD.pnach new file mode 100644 index 0000000..2d7a18a --- /dev/null +++ b/bin/patches/0442B1BD.pnach @@ -0,0 +1,4 @@ +gametitle=Samurai Warriors Xtreme Legends +comment=Skips Videos by bositman +//Skip Videos +patch=0,EE,00126bb0,word,24020001 \ No newline at end of file diff --git a/bin/patches/05177ECE.pnach b/bin/patches/05177ECE.pnach new file mode 100644 index 0000000..ea287ab --- /dev/null +++ b/bin/patches/05177ECE.pnach @@ -0,0 +1,4 @@ +gametitle=Tomb Raider Legend [SLES 53908] (E) [05177ECE] +comment=Patch by CKemu +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00369988,word,24020001 \ No newline at end of file diff --git a/bin/patches/0518D274.pnach b/bin/patches/0518D274.pnach new file mode 100644 index 0000000..3899dfd --- /dev/null +++ b/bin/patches/0518D274.pnach @@ -0,0 +1,4 @@ +gametitle=Need For Speed Most Wanted Black Edition(SLUS_213.51) +comment=Skips Video - deny file By General Plot +//Skip Videos +patch=0,EE,00242418,word,00000000 \ No newline at end of file diff --git a/bin/patches/0518D275.pnach b/bin/patches/0518D275.pnach new file mode 100644 index 0000000..14bcd13 --- /dev/null +++ b/bin/patches/0518D275.pnach @@ -0,0 +1,4 @@ +gametitle=Need For Speed Most Wanted (SLUS_212.67) +comment=Skips Video - deny file By General Plot +//Skip Videos +patch=0,EE,00242414,word,00000000 \ No newline at end of file diff --git a/bin/patches/07AD79C9.pnach b/bin/patches/07AD79C9.pnach new file mode 100644 index 0000000..74fa495 --- /dev/null +++ b/bin/patches/07AD79C9.pnach @@ -0,0 +1,4 @@ +gametitle=Yu-Gi-Oh The Duelists Of The Roses (U) +comment= +//Skip Videos +patch=0,EE,0018ee60,word,24020001 \ No newline at end of file diff --git a/bin/patches/0838D766.pnach b/bin/patches/0838D766.pnach new file mode 100644 index 0000000..5f8c6d6 --- /dev/null +++ b/bin/patches/0838D766.pnach @@ -0,0 +1,6 @@ +gametitle=Raiden III [SLES 53829] (E) +comment=patches by Nachbrenner, made with Phaste 1.20 +//Infinite Lives +patch=1,EE,002d7458,byte,08 +//Infinite Bombs +patch=1,EE,002d74bc,byte,08 \ No newline at end of file diff --git a/bin/patches/08901101.pnach b/bin/patches/08901101.pnach new file mode 100644 index 0000000..9041aa2 --- /dev/null +++ b/bin/patches/08901101.pnach @@ -0,0 +1,13 @@ +gametitle=Neo Contra [SLUS 20961] (U) +comment= Patches By Nachbrenner +//disable BGM (for blockdump) +// patch=0,EE,0012bf20,word,03e00008 +// patch=0,EE,0012bf24,word,00000000 +//fix IPU busy! ingame +patch=0,EE,003a9538,word,03e00008 +patch=0,EE,003a953c,word,00000000 +patch=0,EE,003a9460,word,03e00008 +patch=0,EE,003a9464,word,00000000 +// +//no 3D = no DMA error +// patch=0,EE,00122b60,word,00000000 \ No newline at end of file diff --git a/bin/patches/08FB9DCF.pnach b/bin/patches/08FB9DCF.pnach new file mode 100644 index 0000000..ac07a94 --- /dev/null +++ b/bin/patches/08FB9DCF.pnach @@ -0,0 +1,9 @@ +gametitle= Card Captor Sakura [SLPS 20408] (J) +comment=patches by Nachbrenner +//skip eyetoy check +patch=0,EE,013385b0,word,00000000 +//skip MC & Start screen +patch=0,EE,01337c20,word,00000000 +//activate 1st for food scene, both for telephone scene +// patch=0,EE,01337c2c,word,00000000 // food scene +// patch=0,EE,01337c3c,word,00000000 // telephone scene \ No newline at end of file diff --git a/bin/patches/0999F9DB.pnach b/bin/patches/0999F9DB.pnach new file mode 100644 index 0000000..6492054 --- /dev/null +++ b/bin/patches/0999F9DB.pnach @@ -0,0 +1,13 @@ +gametitle=Rally Championship [SLES 50763] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,001ADE48,word,03E00008 +patch=0,EE,001CC840,word,24020001 +//Skip sceGsExecStoreImage +patch=0,EE,001c4af0,word,03e00008 +patch=0,EE,001c4af4,word,00000000 +//Begin New Career With Loads Of Money +patch=0,EE,001A05C0,word,3C0505F5 +patch=0,EE,001A05DC,word,34A5E0FF +//Enable Cheat (ASM) +patch=0,EE,0018DEB8,word,24020001 \ No newline at end of file diff --git a/bin/patches/0A342A88.pnach b/bin/patches/0A342A88.pnach new file mode 100644 index 0000000..5d3ae4f --- /dev/null +++ b/bin/patches/0A342A88.pnach @@ -0,0 +1,4 @@ +gametitle=Futurama ( U ) +comment=patch by Refraction +//skip movies +patch=0,EE,002fc474,word,00000000 \ No newline at end of file diff --git a/bin/patches/0B359BBF.pnach b/bin/patches/0B359BBF.pnach new file mode 100644 index 0000000..d3fd069 --- /dev/null +++ b/bin/patches/0B359BBF.pnach @@ -0,0 +1,5 @@ +gametitle= Kamen Rider 555 [SLPS 20329] (J) +comment=patches by Nachbrenner +//skip "PlayMpeg" +patch=0,EE,0022f590,word,03e00008 +patch=0,EE,0022f594,word,00000000 \ No newline at end of file diff --git a/bin/patches/0C370E94.pnach b/bin/patches/0C370E94.pnach new file mode 100644 index 0000000..4e9ba42 --- /dev/null +++ b/bin/patches/0C370E94.pnach @@ -0,0 +1,4 @@ +gametitle=Simple Series 2000 - Vol.106 - The Block Kuzushi Quest (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,0019a880,word,24020001 \ No newline at end of file diff --git a/bin/patches/0F6B6315.pnach b/bin/patches/0F6B6315.pnach new file mode 100644 index 0000000..6152a34 --- /dev/null +++ b/bin/patches/0F6B6315.pnach @@ -0,0 +1,4 @@ +gametitle= Kingdom Hearts [SLUS 20370] (U) +comment= +//ZeroGS Patch - GAME_QUICKRESOLVE1 +zerogs=00000400 \ No newline at end of file diff --git a/bin/patches/1025D50A.pnach b/bin/patches/1025D50A.pnach new file mode 100644 index 0000000..f705d0d --- /dev/null +++ b/bin/patches/1025D50A.pnach @@ -0,0 +1,7 @@ +gametitle= Godzilla - Save The Earth [SLUS 20809] (U) +comment=patches by nachbrenner +//EEREC fix: borked memory write +patch=0,EE,0028b2d0,word,00000000 +//DMA fix menus +patch=0,EE,0022c568,word,00000000 +patch=0,EE,0022c540,word,00000000 \ No newline at end of file diff --git a/bin/patches/116154AD.pnach b/bin/patches/116154AD.pnach new file mode 100644 index 0000000..356b315 --- /dev/null +++ b/bin/patches/116154AD.pnach @@ -0,0 +1,8 @@ +gametitle=CART Fury Championship Racing [SLUS 20141] (U) +comment=patches by Nachbrenner +//skip PSX2_Mpeg_PlayFile__FPc +patch=0,EE,00107a00,word,03e00008 +patch=0,EE,00107a04,word,24020001 +//skip SuperSync__Fi +patch=0,EE,00100eb0,word,03e00008 +patch=0,EE,00100eb4,word,24020001 \ No newline at end of file diff --git a/bin/patches/1248FE3A.pnach b/bin/patches/1248FE3A.pnach new file mode 100644 index 0000000..0ebca0f --- /dev/null +++ b/bin/patches/1248FE3A.pnach @@ -0,0 +1,6 @@ +gametitle=Baphomets Fluch - Der Schlafende Drache [SLES 51978] (G) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,00243fa0,word,24020001 +//Fix obscure infinite loop +patch=0,EE,00216764,word,00000000 \ No newline at end of file diff --git a/bin/patches/129C8600.pnach b/bin/patches/129C8600.pnach new file mode 100644 index 0000000..6c5e010 --- /dev/null +++ b/bin/patches/129C8600.pnach @@ -0,0 +1,8 @@ +gametitle=DTM Race Driver [SLES 50816] (E) +comment=patches by nachbrenner +//Skip Videos +patch=0,EE,003876c8,word,24020001 +//All Boni unlocked +patch=1,EE,0046a120,word,0000ffff +patch=0,EE,00306e5c,word,3445ffff +patch=0,EE,00306e94,word,3446ffff \ No newline at end of file diff --git a/bin/patches/12AFF4D4.pnach b/bin/patches/12AFF4D4.pnach new file mode 100644 index 0000000..376621e --- /dev/null +++ b/bin/patches/12AFF4D4.pnach @@ -0,0 +1,23 @@ +gametitle= Gunbird 1 & 2 [SLPM 62469] (J) +comment=patches by nachbrenner +//Disable Autosave (001E5AF2) +//patch=0,EE,00107f6c,word,a4400012 +// +//Gunbird 1 Codes +// +//Infinite Lives +patch=0,EE,0018b06c,word,24020005 +//Infinite Bombs +patch=0,EE,0018AF30,word,24020006 +//Invincible +patch=0,EE,0018AF60,word,340203E8 +patch=0,EE,00199b78,word,00000000 +// +//Gunbird 2 Codes +// +//Infinite Lives +patch=0,EE,00134900,word,34020008 +//Infinite Bombs +patch=0,EE,00133db4,word,34020009 +//Invincible +patch=0,EE,00133a60,word,340303E7 \ No newline at end of file diff --git a/bin/patches/1468C474.pnach b/bin/patches/1468C474.pnach new file mode 100644 index 0000000..48e1348 --- /dev/null +++ b/bin/patches/1468C474.pnach @@ -0,0 +1,4 @@ +gametitle=Madagascar +comment=Keep thread alive +//Sleepthread syscall +patch=0,EE,002f8e44,word,00000000 \ No newline at end of file diff --git a/bin/patches/1510E1D1.pnach b/bin/patches/1510E1D1.pnach new file mode 100644 index 0000000..2210ccb --- /dev/null +++ b/bin/patches/1510E1D1.pnach @@ -0,0 +1,7 @@ +gametitle=Crash Twinsanity [SLES 52568] (E) +comment= patches by Nachbrenner +//Skip Videos +patch=0,EE,002b85d0,word,24020001 +// fix VU0REC 17.10.06 (obsolete) +//patch=0,EE,00189ab4,word,00000000 +//patch=0,EE,00189b78,word,00000000 \ No newline at end of file diff --git a/bin/patches/1629D655.pnach b/bin/patches/1629D655.pnach new file mode 100644 index 0000000..a4555a1 --- /dev/null +++ b/bin/patches/1629D655.pnach @@ -0,0 +1,20 @@ +gametitle=Red Faction II [SLES 51133] (E) +comment=comment=patches by Nachbrenner +//Skip Videos +//patch=0,EE,001afbc8,word,24020001 +//Boot Language Modifier (use only one of these) +//English +//patch=0,EE,0015bca8,word,24020001 +//Français +//patch=0,EE,0015bca8,word,24020002 +//Deutsch +//patch=0,EE,0015bca8,word,24020004 +//obsolete: +//skip borked VU0 stuff +//patch=0,EE,0020a464,word,00000000 +//patch=0,EE,00180eb0,word,03e00008 //slerp_src +//patch=0,EE,00180eb4,word,00000000 +//new VU0 fix: ctc2 t0, CMSAR0 -> li t0,0 +//patch=0,EE,00180df8,word,24080000 +//patch=0,EE,00181738,word,24080000 +//patch=0,EE,001811ac,word,24080000 diff --git a/bin/patches/163F0461.pnach b/bin/patches/163F0461.pnach new file mode 100644 index 0000000..4acce85 --- /dev/null +++ b/bin/patches/163F0461.pnach @@ -0,0 +1,18 @@ +gametitle=V-Rally 3 [SLES 50725] (E) +comment= patches by Nachbrenner +// skip network check (obsolete) +//patch=0,EE,002a4278,word,00103528 // GameInit_edNet__Fv +//IPU DMA fix +patch=0,EE,0012655c,word,00000000 // gcc2_compiled. +//Skip Videos (obsolete) +//patch=0,EE,00267810,word,00000000 // FE_MovieRefresh__Fv +//patch=0,EE,002677d0,word,00000000 // FE_MovieInstall__Fv +//patch=0,EE,002677f0,word,00000000 // FE_MovieInit__Fv +// disable menu music ( Vr3SoundMidiInstall__FP10_vr3_midi_) +patch=0,EE,002698fc,word,00000000 +//skip edSoundFlush__Fv +patch=0,EE,00197530,word,03e00008 +patch=0,EE,00197534,word,00000000 +//skip edDspSetCommand__Fii +patch=0,EE,001ab6b0,word,03e00008 +patch=0,EE,001ab6b4,word,00000000 \ No newline at end of file diff --git a/bin/patches/1738A5B0.pnach b/bin/patches/1738A5B0.pnach new file mode 100644 index 0000000..4a8e83d --- /dev/null +++ b/bin/patches/1738A5B0.pnach @@ -0,0 +1,13 @@ +gametitle=Super Shanghai 2005 [SLPM 62552] (J) +comment=patches by Nachbrenner +//Infinite time +patch=1,EE,00AADAD8,word,0000face +//Skip STAR.PSS +//patch=0,EE,001064c8,word,00000000 +//Skip TITLDEMO.PSS +//patch=0,EE,0010d01c,word,00000000 +//boot with BGM off +patch=0,EE,0011fdac,word,adcf0008 +//Skip BGM Start +patch=0,EE,00116d58,word,03e00008 +patch=0,EE,00116d5c,word,00000000 \ No newline at end of file diff --git a/bin/patches/19D145D7.pnach b/bin/patches/19D145D7.pnach new file mode 100644 index 0000000..63413cb --- /dev/null +++ b/bin/patches/19D145D7.pnach @@ -0,0 +1,12 @@ +gametitle=Kuri Kuri Mix [SLES 50224] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,001f41b4,word,00000000 +//Start with 600 seconds +patch=0,EE,0012cc60,word,24027530 +//Freeze countdown timer +patch=0,EE,0012d1f8,word,00000000 +//Don't lose time on getting hurt +patch=0,EE,0012e86c,word,00000000 +//Low total time +patch=0,EE,0012d1fc,word,24030001 \ No newline at end of file diff --git a/bin/patches/1CAC8A56.pnach b/bin/patches/1CAC8A56.pnach new file mode 100644 index 0000000..96760c8 --- /dev/null +++ b/bin/patches/1CAC8A56.pnach @@ -0,0 +1,4 @@ +gametitle=Venus & braves NTSC-J +comment= +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,003e86a0,word,24020001 \ No newline at end of file diff --git a/bin/patches/1D2818AF.pnach b/bin/patches/1D2818AF.pnach new file mode 100644 index 0000000..9a4c6c0 --- /dev/null +++ b/bin/patches/1D2818AF.pnach @@ -0,0 +1,13 @@ +gametitle=Need For Speed - Hot Pursuit 2 [SLES 50731] (E) +comment=patches by Nachbrenner +//for blockdump: +//disable sound streaming +patch=0,EE,00274080,word,03e00008 +patch=0,EE,00274084,word,00000000 +//Skip Logo and Intro AVI +patch=0,EE,0016f094,word,00000000 +//Skip AVI streaming +patch=0,EE,0016ce30,word,03e00008 +patch=0,EE,0016ce34,word,00000000 +//American Mode (Skip language select menu) +patch=0,EE,0012EF78,word,00000000 \ No newline at end of file diff --git a/bin/patches/200BC0E6.pnach b/bin/patches/200BC0E6.pnach new file mode 100644 index 0000000..76492e1 --- /dev/null +++ b/bin/patches/200BC0E6.pnach @@ -0,0 +1,4 @@ +gametitle=XIII [SLES 51244] (E) +comment=patches by nachbrenner +//Skip Videos (sceMpegIsEnd) +patch=0,EE,001114a0,word,24020001 \ No newline at end of file diff --git a/bin/patches/2088950A.pnach b/bin/patches/2088950A.pnach new file mode 100644 index 0000000..d040b71 --- /dev/null +++ b/bin/patches/2088950A.pnach @@ -0,0 +1,4 @@ +gametitle= Xenosaga Episode III - Also Sprach Zarathustra [SLUS 21389] (U) +comment= +//ZeroGS Patch - GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE +zerogs=0001C000 \ No newline at end of file diff --git a/bin/patches/21068223.pnach b/bin/patches/21068223.pnach new file mode 100644 index 0000000..d7bc59a --- /dev/null +++ b/bin/patches/21068223.pnach @@ -0,0 +1,3 @@ +gametitle=Okami [SLUS 21115] (U) +//ZeroGS Patch - GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE +zerogs=0005C000 \ No newline at end of file diff --git a/bin/patches/27E54B37.pnach b/bin/patches/27E54B37.pnach new file mode 100644 index 0000000..5768df2 --- /dev/null +++ b/bin/patches/27E54B37.pnach @@ -0,0 +1,16 @@ +gametitle=Syphon Filter - The Omega Strain [SCES 52033] (G) +comment= patches by Nachbrenner +//Skip FMV (for blockdump) +patch=0,EE,0041743c,word,00000000 +patch=0,EE,00417444,word,00000000 +//Boot Language Fix +patch=0,EE,0042020c,word,24020004 //german +// Playername = PCSX2 +patch=1,EE,008b945c,word,58534350 +patch=1,EE,008b9460,word,00000032 +// +//brute force fix GS_CSR (obsolete) +//patch=0,EE,0039ca3c,word,00000000 +//patch=0,EE,0039caec,word,00000000 +//brute force fix VIF1_STAT (obsolete) +//patch=0,EE,0039c8e0,word,10000019 \ No newline at end of file diff --git a/bin/patches/280DAC56.pnach b/bin/patches/280DAC56.pnach new file mode 100644 index 0000000..2150708 --- /dev/null +++ b/bin/patches/280DAC56.pnach @@ -0,0 +1,16 @@ +gametitle=Super Trucks [SLES 50897] (E) +comment=patches by nachbrenner +//Skip Intro Video +patch=0,EE,00100060,word,00000000 +//always use music "BUG.SPU" (for blockdumping) +patch=0,EE,001b5308,word,00209460 +patch=0,EE,001b530c,word,00209460 +patch=0,EE,001b5310,word,00209460 +patch=0,EE,001b5314,word,00209460 +patch=0,EE,001b5318,word,00209460 +patch=0,EE,001b531c,word,00209460 +patch=0,EE,001b5320,word,00209460 +// Disable "PAD_CheckForUSBDevices" +//patch=0,EE,00135118,word,00000000 +//Disable "lgDevInit" +//patch=0,EE,001339fc,word,00000000 \ No newline at end of file diff --git a/bin/patches/295D2F96.pnach b/bin/patches/295D2F96.pnach new file mode 100644 index 0000000..b2f9716 --- /dev/null +++ b/bin/patches/295D2F96.pnach @@ -0,0 +1,6 @@ +gametitle=Spider-Man [SLES 50814] (G) +comment=patches by Nachbrenner +//Skip Videos +//patch=0,EE,0039A9D0,word,03E00008 +//patch=0,EE,0039A9D4,word,00000000 +//patch=0,EE,004a3540,word,24020001 \ No newline at end of file diff --git a/bin/patches/29D80A23.pnach b/bin/patches/29D80A23.pnach new file mode 100644 index 0000000..db78303 --- /dev/null +++ b/bin/patches/29D80A23.pnach @@ -0,0 +1,9 @@ +gametitle=Sidewinder V [SLPS 25271] (J) +comment=patches by Nachbrenner +//Language = English +patch=1,EE,0039b484,word,00000001 +//Skip Videos (sceMpegIsEnd) +//patch=0,EE,00280398,word,24020001 +//Skip DualBgmOn +//patch=0,EE,002439f8,word,03e00008 +//patch=0,EE,002439fc,word,00000000 \ No newline at end of file diff --git a/bin/patches/2B2E1535.pnach b/bin/patches/2B2E1535.pnach new file mode 100644 index 0000000..bb73e07 --- /dev/null +++ b/bin/patches/2B2E1535.pnach @@ -0,0 +1,5 @@ + +gametitle=Arc the Lad +comment=Skips Video by Rudy_x +//Skip introVideo(s) +patch=0,EE,001d7df8,word,24020001 diff --git a/bin/patches/2C728173.pnach b/bin/patches/2C728173.pnach new file mode 100644 index 0000000..5ad7fc6 --- /dev/null +++ b/bin/patches/2C728173.pnach @@ -0,0 +1,4 @@ +gametitle=Fast and The Furious +comment= Skip Videos By Refraction +//Skip Videos +patch=0,EE,003d2570,word,24020001 \ No newline at end of file diff --git a/bin/patches/2CFFFA50.pnach b/bin/patches/2CFFFA50.pnach new file mode 100644 index 0000000..e513700 --- /dev/null +++ b/bin/patches/2CFFFA50.pnach @@ -0,0 +1,9 @@ +gametitle=Buffy: Chaos Bleeds [SLES 51890] (E) +comment= patches by Nachbrenner +//Skip Videos +// patch=0,EE,002A3960,word,24020001 +//Video modifier (use only one of these) +//INTRO1 -> SPIKE_VO +//patch=0,EE,002efb70,word,002efab0 +//INTRO1 -> OUTTAKES +//patch=0,EE,002efb70,word,002efaf0 \ No newline at end of file diff --git a/bin/patches/2D919421.pnach b/bin/patches/2D919421.pnach new file mode 100644 index 0000000..2c75478 --- /dev/null +++ b/bin/patches/2D919421.pnach @@ -0,0 +1,15 @@ +Gametitle=Charlie's Angels [SLES 51750] (E) +comment=patches by nachbrenner +//Skip Delay on Screen 1+2 0x00208818 +patch=0,EE,001915b4,word,ad608818 +patch=0,EE,00191604,word,ac600100 +patch=0,EE,001916ac,word,ac408818 +patch=0,EE,001916c8,word,24020000 +patch=0,EE,0019592c,word,ae000100 +//Skip Videos +patch=0,EE,00191320,word,03E00008 +patch=0,EE,00191324,word,00000000 +patch=0,EE,001aa810,word,24020001 +//Unlock All Boni +patch=0,EE,00194a68,word,2401FFFF +patch=0,EE,00194a6c,word,FCE10148 \ No newline at end of file diff --git a/bin/patches/2F56CBC9.pnach b/bin/patches/2F56CBC9.pnach new file mode 100644 index 0000000..c9e2bc1 --- /dev/null +++ b/bin/patches/2F56CBC9.pnach @@ -0,0 +1,4 @@ +gametitle= Klonoa 2 - Lunatea's Veil [SLUS 20151] (U) +comment=patches by nachbrenner +//Skip sceIpuSync +patch=0,EE,00305b90,word,03e00008 \ No newline at end of file diff --git a/bin/patches/302797DF.pnach b/bin/patches/302797DF.pnach new file mode 100644 index 0000000..3c0a714 --- /dev/null +++ b/bin/patches/302797DF.pnach @@ -0,0 +1,5 @@ +gametitle=CYGirls +comment= +//patches by Refraction +//Skip Videos +patch=0,EE,00135130,word,00000000 \ No newline at end of file diff --git a/bin/patches/304C115C.pnach b/bin/patches/304C115C.pnach new file mode 100644 index 0000000..e529493 --- /dev/null +++ b/bin/patches/304C115C.pnach @@ -0,0 +1,4 @@ +gametitle= Harvest Moon - A Wonderful Life [SLUS 21171] (U) +comment= +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/32629F36.pnach b/bin/patches/32629F36.pnach new file mode 100644 index 0000000..fea149d --- /dev/null +++ b/bin/patches/32629F36.pnach @@ -0,0 +1,9 @@ +gametitle=Oni [SLES 50177] (G) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,001c67d8,word,03e00008 +patch=0,EE,001c67dc,word,00000000 +//skip "branch if copro 0 condition false" +patch=0,EE,001cef7c,word,00000000 // bc0f $001cef7c +//skip sceGsExecStoreImage +patch=0,EE,001d4454,word,00000000 \ No newline at end of file diff --git a/bin/patches/339A0B8C.pnach b/bin/patches/339A0B8C.pnach new file mode 100644 index 0000000..fb3ab5e --- /dev/null +++ b/bin/patches/339A0B8C.pnach @@ -0,0 +1,4 @@ +gametitle= Fatal Frame [SLUS 20388] (U) NTSC +comment= Video Skip by Refraction +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00232f00,word,24020001 \ No newline at end of file diff --git a/bin/patches/33F7D21A.pnach b/bin/patches/33F7D21A.pnach new file mode 100644 index 0000000..866a752 --- /dev/null +++ b/bin/patches/33F7D21A.pnach @@ -0,0 +1,14 @@ +gametitle= Dirge Of Cerberus - Final Fantasy VII [SLES 54185] (E) +comment=patches by nachbrenner +//Fix "**** SQTHREAD ERROR : BAD LOCK STATE" +patch=0,EE,0042d768,word,00000000 +//Skip mcDelayThread (calls SleepThread) +patch=0,EE,00458008,word,00000000 +//Skip Videos (for blockdump) +patch=0,EE,00241bac,word,00000000 +//override sceScfGetLanguage +//patch=0,EE,002486d8,word,24020000 //japanese +patch=0,EE,002486d8,word,24020001 //english +//patch=0,EE,002486d8,word,24020004 //german +//intro 3D - fix DMA0 vs. VU0REC +patch=0,EE,0026f960,word,10000020 \ No newline at end of file diff --git a/bin/patches/36FEEE3A.pnach b/bin/patches/36FEEE3A.pnach new file mode 100644 index 0000000..a29efec --- /dev/null +++ b/bin/patches/36FEEE3A.pnach @@ -0,0 +1,19 @@ +gametitle=Knockout Kings 2002 [SLUS 20369] (U) +comment= patches by Nachbrenner +//fix DMA loop +patch=0,EE,001d8020,word,1000000f +//VU0 crash fix (obsolete) +//patch=0,EE,001fb144,word,00000000 +// +// for blockdump: +// +//Skip MPC videos +patch=0,EE,0018c0a8,word,03e00008 +patch=0,EE,0018c0ac,word,24020001 +//Fight commentary off +patch=1,EE,00273380,word,00000000 +//Music vol.=0 +patch=1,EE,002721A4,word,00000000 +//Skip sound streaming +patch=0,EE,00138b68,word,03e00008 +patch=0,EE,00138b6c,word,00000000 \ No newline at end of file diff --git a/bin/patches/37BA81B1.pnach b/bin/patches/37BA81B1.pnach new file mode 100644 index 0000000..888d349 --- /dev/null +++ b/bin/patches/37BA81B1.pnach @@ -0,0 +1,4 @@ +gametitle= Kamen Rider Blade [SLPS 20402] (J) +comment=patches by Nachbrenner +//skip "PlayMpeg" +patch=0,EE,00158dec,word,00000000 \ No newline at end of file diff --git a/bin/patches/37C07E96.pnach b/bin/patches/37C07E96.pnach new file mode 100644 index 0000000..68919ed --- /dev/null +++ b/bin/patches/37C07E96.pnach @@ -0,0 +1,3 @@ +gametitle=Simple2000 Vol.91 : The ALL STAR fighting [SLPS 20430] (J) +//Skip Movies +patch=0,EE,0010b720,word,24020001 \ No newline at end of file diff --git a/bin/patches/38F29E28.pnach b/bin/patches/38F29E28.pnach new file mode 100644 index 0000000..920844b --- /dev/null +++ b/bin/patches/38F29E28.pnach @@ -0,0 +1,4 @@ +gametitle=7 cavalry of molmoth NTSC JAPAN +comment=skips pss intro +//Skip Videos +patch=0,EE,00284b58,word,24020001 \ No newline at end of file diff --git a/bin/patches/3BD85DA4.pnach b/bin/patches/3BD85DA4.pnach new file mode 100644 index 0000000..34e39f5 --- /dev/null +++ b/bin/patches/3BD85DA4.pnach @@ -0,0 +1,7 @@ +gametitle=Ghosthunter [SCES 51463] (E) +comment=patches by nachbrenner +//fix VU0/DMA crap +patch=0,EE,003e8928,word,03e00008 +patch=0,EE,003e892c,word,00000000 +patch=0,EE,003831c8,word,00000000 +patch=0,EE,003831d4,word,00000000 \ No newline at end of file diff --git a/bin/patches/3CFE3B37.pnach b/bin/patches/3CFE3B37.pnach new file mode 100644 index 0000000..4edde5e --- /dev/null +++ b/bin/patches/3CFE3B37.pnach @@ -0,0 +1,6 @@ +gametitle=Powershot Pinball [SLES 54084] (E) +comment=patches by auMatt +//Skip Video +patch=0,EE,0029c990,word,24020001 +//ZeroGS Patch - GAME_AUTORESET +zerogs=00000002 \ No newline at end of file diff --git a/bin/patches/3DB65A75.pnach b/bin/patches/3DB65A75.pnach new file mode 100644 index 0000000..3fc6279 --- /dev/null +++ b/bin/patches/3DB65A75.pnach @@ -0,0 +1,5 @@ +gametitle=Megaman Anniversary Collection [SLUS 20833] (U) +//fix GS_CSR +//patch=0,EE,0012d938,word,00000000 +//Skip videos +//patch=0,EE,0014e548,word,24020001 \ No newline at end of file diff --git a/bin/patches/3E0A256D.pnach b/bin/patches/3E0A256D.pnach new file mode 100644 index 0000000..1cb94b5 --- /dev/null +++ b/bin/patches/3E0A256D.pnach @@ -0,0 +1,4 @@ +//skip FMV (sceMpegIsEnd) +patch=0,EE,001eccc8,word,24020001 +//fix AudioReset (Peops SPU2 4.11.06) +patch=0,EE,00120a94,word,00000000 \ No newline at end of file diff --git a/bin/patches/3E68955A.pnach b/bin/patches/3E68955A.pnach new file mode 100644 index 0000000..4264e4a --- /dev/null +++ b/bin/patches/3E68955A.pnach @@ -0,0 +1,4 @@ +gametitle= Kingdom Hearts - Final Mix [SLPS 25198] (J) +comment= +//ZeroGS Patch - GAME_QUICKRESOLVE1 +zerogs=00000400 \ No newline at end of file diff --git a/bin/patches/3F0452DE.pnach b/bin/patches/3F0452DE.pnach new file mode 100644 index 0000000..24e78de --- /dev/null +++ b/bin/patches/3F0452DE.pnach @@ -0,0 +1,4 @@ +gametitle= FlatOut 2 [SLES 54002] (E) +comment= Video Skip by Refraction +//Skip Videos (sceMpegIsEnd) +patch=0,EE,003dd1d0,word,24020001 \ No newline at end of file diff --git a/bin/patches/3FB69323.pnach b/bin/patches/3FB69323.pnach new file mode 100644 index 0000000..83b25e9 --- /dev/null +++ b/bin/patches/3FB69323.pnach @@ -0,0 +1,8 @@ +gametitle=Gran Turismo 4 Prologue [SCES 52438] (E) +//fix IPU DMA +patch=1,EE,00175018,word,00000000 +patch=1,EE,0046bba8,word,00000000 +patch=1,EE,0046bbe4,word,00000000 +//Skip Videos +patch=1,EE,0020c790,word,03e00008 +patch=1,EE,0020c794,word,00000000 \ No newline at end of file diff --git a/bin/patches/4043F228.pnach b/bin/patches/4043F228.pnach new file mode 100644 index 0000000..c0198bd --- /dev/null +++ b/bin/patches/4043F228.pnach @@ -0,0 +1,4 @@ +gametitle= PC Genjin [SLPM 62418] (J) [4043F228] +comment= +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,0020f9e0,word,24020001 \ No newline at end of file diff --git a/bin/patches/41A3191C.pnach b/bin/patches/41A3191C.pnach new file mode 100644 index 0000000..ed24080 --- /dev/null +++ b/bin/patches/41A3191C.pnach @@ -0,0 +1,4 @@ +gametitle=Simple Series 2000 - Vol. 99 - The Genshijin [SLPS 20461] (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00109e40,word,24020001 \ No newline at end of file diff --git a/bin/patches/4321A427.pnach b/bin/patches/4321A427.pnach new file mode 100644 index 0000000..1e9c02f --- /dev/null +++ b/bin/patches/4321A427.pnach @@ -0,0 +1,5 @@ +gametitle=World Soccer Winning Eleven 10 [SLPM 66374] (J) +comment=patches by fullcodes +//Skip PSS +// patch=0,EE,00131260,word,03e00008 +// patch=0,EE,00131264,word,00000000 \ No newline at end of file diff --git a/bin/patches/4334E17D.pnach b/bin/patches/4334E17D.pnach new file mode 100644 index 0000000..d945558 --- /dev/null +++ b/bin/patches/4334E17D.pnach @@ -0,0 +1,4 @@ +gametitle=Disgaea 2 - Cursed Memories [SLPS 25608] (J) +comment= +//ZeroGS Patch - GAME_NODEPTHRESOLVE +zerogs=00008000 \ No newline at end of file diff --git a/bin/patches/44A61C8F.pnach b/bin/patches/44A61C8F.pnach new file mode 100644 index 0000000..cf21334 --- /dev/null +++ b/bin/patches/44A61C8F.pnach @@ -0,0 +1,4 @@ +gametitle=Gran Turismo 4 [SCES 51719] (E) [44A61C8F] +comment=patches by nachbrenner +//skip Videos +patch=1,EE,00100D84,word,24100001 diff --git a/bin/patches/4691F6F7.pnach b/bin/patches/4691F6F7.pnach new file mode 100644 index 0000000..e974348 --- /dev/null +++ b/bin/patches/4691F6F7.pnach @@ -0,0 +1,4 @@ +gametitle=The Sum Of All Fears [SLES 51180] (E) +comment= patches by Nachbrenner +//Skip sceIpuSync +//patch=0,EE,002aa098,word,03e00008 \ No newline at end of file diff --git a/bin/patches/46A7ECA4.pnach b/bin/patches/46A7ECA4.pnach new file mode 100644 index 0000000..fc630c4 --- /dev/null +++ b/bin/patches/46A7ECA4.pnach @@ -0,0 +1,4 @@ +gametitle=Guilty Gear Isuka [SLES 53284] (E) [46A7ECA4] +comment=Patch By CKemu +//Skip Videos +patch=0,EE,00107f10,word,24020001 \ No newline at end of file diff --git a/bin/patches/472C9E70.pnach b/bin/patches/472C9E70.pnach new file mode 100644 index 0000000..a63e3a8 --- /dev/null +++ b/bin/patches/472C9E70.pnach @@ -0,0 +1,6 @@ +gametitle=Kengo: Master Of Bushido [SLES 50114] (E) +comment=patches by nachbrenner +//start with 5 minutes time limit +patch=0,EE,002999b8,word,00003A98 //single_game_time_limit_table +//skip videos +patch=0,EE,0018d738,word,24020001 \ No newline at end of file diff --git a/bin/patches/48FE0C71.pnach b/bin/patches/48FE0C71.pnach new file mode 100644 index 0000000..b88f875 --- /dev/null +++ b/bin/patches/48FE0C71.pnach @@ -0,0 +1,20 @@ +gametitle=FFX-2 US +comment= +// InvalidDCache | SyncDCache +patch=0,EE,003498b0,word,03e00008 +patch=0,EE,003498b4,word,00000000 +//skip "INIT SOUND" +patch=0,EE,00132868,word,00000000 +//skip "INIT VOICE" +patch=0,EE,0013287c,word,00000000 +//skip AC3+PCM start (NOPs whole subroutine) +patch=0,EE,0017ac70,word,00000000 +//Skip Videos +//patch=0,EE,003338e0,word,24020001 +//skip "decode MPEG2" +patch=0,EE,0017aaa0,word,03e00008 +patch=0,EE,0017aaa4,word,00000000 +patch=0,EE,0017a9e8,word,03e00008 +patch=0,EE,0017a9ec,word,00000000 +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/49DA19CE.pnach b/bin/patches/49DA19CE.pnach new file mode 100644 index 0000000..872ef01 --- /dev/null +++ b/bin/patches/49DA19CE.pnach @@ -0,0 +1,4 @@ +gametitle=Carmen Sandiego-The Secret Of The Stolen Drums [SLES52143] (E) +comment= patches by Nachbrenner +//Skip MpegPlay +patch=0,EE,0011efd0,word,03e00008 \ No newline at end of file diff --git a/bin/patches/4B6DDB6B.pnach b/bin/patches/4B6DDB6B.pnach new file mode 100644 index 0000000..8ef0074 --- /dev/null +++ b/bin/patches/4B6DDB6B.pnach @@ -0,0 +1,3 @@ +gametitle=Guilty Gear XX NTSC JPN +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,00245418,word,24020001 \ No newline at end of file diff --git a/bin/patches/4C4D7072.pnach b/bin/patches/4C4D7072.pnach new file mode 100644 index 0000000..202d920 --- /dev/null +++ b/bin/patches/4C4D7072.pnach @@ -0,0 +1,11 @@ +gametitle=Tom Clancy's Splinter Cell Chaos Theory [SLES 53007] (E) +comment=patches by Nachbrenner +//fix sceIpuStopDMA +patch=0,EE,0020b884,word,00000000 +// +// load SC3_OFF.ELF manually to go ingame +// d7a4b7af.pnach +// gametitle=Tom Clancy's Splinter Cell Chaos Theory [SC3_OFF.ELF] (E) +// Skip sceIpuRestartDMA +// patch=1,EE,001116e0,word,03e00008 +// patch=1,EE,001116e4,word,00000000 \ No newline at end of file diff --git a/bin/patches/4C9EE7DF.pnach b/bin/patches/4C9EE7DF.pnach new file mode 100644 index 0000000..ef6746e --- /dev/null +++ b/bin/patches/4C9EE7DF.pnach @@ -0,0 +1,20 @@ +gametitle=Crazy Taxi [SLUS 20202] (U) +comment= patches by Nachbrenner +//skip movie "PlaySega" +patch=0,EE,001a1950,word,03e00008 +patch=0,EE,001a1954,word,00000000 +//skip movie "PlayAcclaim" +patch=0,EE,001a1ae8,word,03e00008 +patch=0,EE,001a1aec,word,00000000 +//skip music.str (for blockdump) +// patch=0,EE,001a0bb0,word,0000000 +//skip voice.str (for blockdump) +// patch=0,EE,001a0b9c,word,0000000 +//Infinite arcade time +patch=1,EE,002F0C64,word,00000e00 +//Japanese mode +//patch=0,EE,00118514,word,af8095a4 +//controller setting B +patch=1,EE,002152DF,byte,01 +//skip nlWaitVSync / TaxiBlankInterrupt (obsolete) +//patch=0,EE,0019a590,word,03e00008 \ No newline at end of file diff --git a/bin/patches/4D6DBB75.pnach b/bin/patches/4D6DBB75.pnach new file mode 100644 index 0000000..1fe7989 --- /dev/null +++ b/bin/patches/4D6DBB75.pnach @@ -0,0 +1,4 @@ +gametitle=bloody roar 3 NTSC JAPAN +comment=skips intro +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,001dc9f8,word,24020001 \ No newline at end of file diff --git a/bin/patches/4DAC50C2.pnach b/bin/patches/4DAC50C2.pnach new file mode 100644 index 0000000..648401b --- /dev/null +++ b/bin/patches/4DAC50C2.pnach @@ -0,0 +1,5 @@ +gametitle=Starsky & Hutch DE/FR [SLES 51783] (E) +comment=patches by Nachbrenner +//Skip videos +//patch=1,EE,0021FAC4,word,00000000 +//patch=1,EE,00151750,word,24020001 \ No newline at end of file diff --git a/bin/patches/4F3D3CF0.pnach b/bin/patches/4F3D3CF0.pnach new file mode 100644 index 0000000..36fa809 --- /dev/null +++ b/bin/patches/4F3D3CF0.pnach @@ -0,0 +1,5 @@ +gametitle=Simply... The Best For Less - Vol. 6 Ultimate Casino [SLES 52515] (E) +comment=patches by Nachbrenner +//Skip logo.pss +patch=0,EE,00115778,word,24020001 +patch=0,EE,0012eb90,word,00000000 \ No newline at end of file diff --git a/bin/patches/506644B3.pnach b/bin/patches/506644B3.pnach new file mode 100644 index 0000000..ea628e2 --- /dev/null +++ b/bin/patches/506644B3.pnach @@ -0,0 +1,5 @@ +gametitle=Big Mutha Truckers [SLES 51355] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,002d1438,word,24020001 //sceMpegIsEnd +patch=0,EE,001ca00c,word,00000000 //sceMpegGetPicture \ No newline at end of file diff --git a/bin/patches/5162BCCA.pnach b/bin/patches/5162BCCA.pnach new file mode 100644 index 0000000..692831f --- /dev/null +++ b/bin/patches/5162BCCA.pnach @@ -0,0 +1,5 @@ + +gametitle=Beach King Stunts Racer +comment=Skips Video by Rudy_x(sceMpegIsEnd) +//Skip Video +patch=0,EE,00197988,word,24020001 diff --git a/bin/patches/51D8A6A9.pnach b/bin/patches/51D8A6A9.pnach new file mode 100644 index 0000000..cd5c2b3 --- /dev/null +++ b/bin/patches/51D8A6A9.pnach @@ -0,0 +1,20 @@ +gametitle=GTC Africa [SLES 50472] (E) +comment=since beta 01/MAR/2004 PLAYABLE!!! +//Unlock All Challenges +patch=0,EE,0010a8bc,word,ac23a588 +patch=0,EE,0010a8d4,word,ac23a588 +//Unlock All Championships +//patch=0,EE,0010a8dc,word,ac23a594 +//Unlock All Single Races +patch=0,EE,0010a8e4,word,ac23a598 +//"-no_music" +//patch=0,EE,0010a7e4,word,ac20a534 +//@1234 PlayMPEGFile +patch=0,EE,0010a824,word,ac20a554 +//@1242 DrawDebugText +patch=0,EE,0010a87c,word,ac20a578 +//Disable HUDRender +patch=0,EE,001996c0,word,03e00008 +patch=0,EE,001996c4,word,00000000 +//wm: fix VIF0_STAT (obsolete) +//patch=0,EE,001f027c,word,00000000 \ No newline at end of file diff --git a/bin/patches/53A803AF.pnach b/bin/patches/53A803AF.pnach new file mode 100644 index 0000000..f1247c1 --- /dev/null +++ b/bin/patches/53A803AF.pnach @@ -0,0 +1,4 @@ +gametitle=Kessen 2 [SLUS 20275] (U) +comment=Skips Video (sceMpegIsEnd) +//Skip Videos by General Plot +patch=0,EE,00108970,word,24020001 \ No newline at end of file diff --git a/bin/patches/53DF159B.pnach b/bin/patches/53DF159B.pnach new file mode 100644 index 0000000..2e1120a --- /dev/null +++ b/bin/patches/53DF159B.pnach @@ -0,0 +1,16 @@ +gametitle=Max Payne MAIN_P.RUN [SLES 50325] (E) +comment=load ELF MAIN_P.RUN manually! +//deny video ELFs +patch=0,EE,0014BF5C,word,00000000 +patch=0,EE,0014E718,word,00000000 +//obsolete: +// don't flood console with bad VIF1_MARK messages +//patch=0,EE,0052f40c,word,00000000 +//WM: fix DMA1 +//patch=0,EE,00542ca8,word,1000000f +//skip bc0f +//patch=0,EE,00542e48,word,00000000 +//patch=0,EE,00542e74,word,00000000 +//WM: fix DMA9 +//patch=0,EE,005272e4,word,00000000 +//patch=0,EE,00527780,word,00000000 \ No newline at end of file diff --git a/bin/patches/54A548B4.pnach b/bin/patches/54A548B4.pnach new file mode 100644 index 0000000..90b6203 --- /dev/null +++ b/bin/patches/54A548B4.pnach @@ -0,0 +1,6 @@ +gametitle= Crash N Burn +comment= Mpegisend +//Skip Videos +//patch=0,EE,0039fd50,word,24020001 +//ZeroGS Patch - GAME_EXACTCOLOR +zerogs=00000020 \ No newline at end of file diff --git a/bin/patches/54AD76D7.pnach b/bin/patches/54AD76D7.pnach new file mode 100644 index 0000000..533d66f --- /dev/null +++ b/bin/patches/54AD76D7.pnach @@ -0,0 +1,8 @@ +gametitle=Lara Croft Tomb Raider - The Angel of Darkness [SLES 51227] (E) +comment= patches by nachbrenner +//Skip videos +patch=0,EE,00104de0,word,03E00008 +patch=0,EE,00104de4,word,24020001 +patch=0,EE,00104d60,word,03E00008 +patch=0,EE,00104d64,word,24020001 +patch=0,EE,0021bf68,word,24020001 \ No newline at end of file diff --git a/bin/patches/54D6BEE3.pnach b/bin/patches/54D6BEE3.pnach new file mode 100644 index 0000000..9ec605a --- /dev/null +++ b/bin/patches/54D6BEE3.pnach @@ -0,0 +1,4 @@ +gametitle=Swords of Destiny [SLES 53699] (E) +comment=patch by Refraction +//skip movies - brute force +patch=0,EE,00235440,word,10000003 diff --git a/bin/patches/582EED0D.pnach b/bin/patches/582EED0D.pnach new file mode 100644 index 0000000..d5ab484 --- /dev/null +++ b/bin/patches/582EED0D.pnach @@ -0,0 +1,8 @@ +gametitle=Contra - Shattered Soldier [SLUS 20306] (U) +comment=patches by nachbrenner +//skip FMV (sceMpegIsEnd) +patch=0,EE,0063d950,word,24020001 +//suppress message "Gifstat write value = 4" +//patch=0,EE,0041be6c,word,00000000 +//suppress message "Gifstat write value = 0" +//patch=0,EE,0041bf1c,word,00000000 \ No newline at end of file diff --git a/bin/patches/586EA828.pnach b/bin/patches/586EA828.pnach new file mode 100644 index 0000000..83aaf31 --- /dev/null +++ b/bin/patches/586EA828.pnach @@ -0,0 +1,7 @@ +gametitle=MotoGP 2 [SLUS 20285] (U) +comment=patches by nachbrenner +//skip FMV +//patch=0,EE,00171fe8,word,24020001 +//All challenges complete +patch=0,EE,00133e54,word,20020002 +patch=0,EE,00133e58,word,a0a20000 \ No newline at end of file diff --git a/bin/patches/58EE1AFA.pnach b/bin/patches/58EE1AFA.pnach new file mode 100644 index 0000000..233a55a --- /dev/null +++ b/bin/patches/58EE1AFA.pnach @@ -0,0 +1,4 @@ +gametitle=Breath Of Fire V: Drangon Quarter USA +comment=Skips videos +//Skip Videos +patch=0,EE,0010a758,word,24020001 \ No newline at end of file diff --git a/bin/patches/5A7635C1.pnach b/bin/patches/5A7635C1.pnach new file mode 100644 index 0000000..84224a5 --- /dev/null +++ b/bin/patches/5A7635C1.pnach @@ -0,0 +1,4 @@ +gametitle=NRA Gun Club SLUS 21432 (U) +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,001091c0,word,24020001 \ No newline at end of file diff --git a/bin/patches/5BBC2F40.pnach b/bin/patches/5BBC2F40.pnach new file mode 100644 index 0000000..9e869fe --- /dev/null +++ b/bin/patches/5BBC2F40.pnach @@ -0,0 +1,20 @@ +gametitle=Ridge Racer V [SCES 50000] (E) +comment= patches by Nachbrenner +// disable foreground 3D on car selection +//patch=0,EE,00201e3c,word,00000000 +// disable background 3D on car selection +//patch=0,EE,00227254,word,00000000 +//patch=0,EE,0027fac0,word,00000000 +//patch=0,EE,0027fbf4,word,00000000 +// +//skip VU0 Matrices (3D car select) +//patch=0,EE,0025a728,word,03e00008 +//patch=0,EE,0025a72c,word,00000000 +//patch=0,EE,0025aab8,word,03e00008 +//patch=0,EE,0025aabc,word,00000000 +//patch=0,EE,0025a6f8,word,03e00008 +//patch=0,EE,0025a6fc,word,00000000 +//patch=0,EE,00201540,word,03e00008 // ingame +//patch=0,EE,00201544,word,00000000 +//skip FlushCache before VU0 Sub/Scale/Copy Vector +//patch=0,EE,002a1298,word,00000000 \ No newline at end of file diff --git a/bin/patches/5BC8C9E8.pnach b/bin/patches/5BC8C9E8.pnach new file mode 100644 index 0000000..a2c5166 --- /dev/null +++ b/bin/patches/5BC8C9E8.pnach @@ -0,0 +1,3 @@ +gametitle= Marvel Vs. Capcom 2 NTSC-J +comment= +fastmemory \ No newline at end of file diff --git a/bin/patches/5BE3F481.pnach b/bin/patches/5BE3F481.pnach new file mode 100644 index 0000000..efa32a8 --- /dev/null +++ b/bin/patches/5BE3F481.pnach @@ -0,0 +1,4 @@ +gametitle=James Cameron's Dark Angel [SLES 51333] (E) +comment= patches by Nachbrenner +//Skip FMV +// patch=0,EE,0021CC24,word,00000000 \ No newline at end of file diff --git a/bin/patches/5CCA0737.pnach b/bin/patches/5CCA0737.pnach new file mode 100644 index 0000000..5e64e74 --- /dev/null +++ b/bin/patches/5CCA0737.pnach @@ -0,0 +1,7 @@ +gametitle=Barbarian [SLES 50972] (E) +comment=patches by Nachbrenner +//Skip SAMPLE.PSS +patch=0,EE,0010afc8,word,00000000 +//skip audio streams +//patch=0,EE,0016fb40,word,03e00008 +//patch=0,EE,0016fb44,word,00000000 \ No newline at end of file diff --git a/bin/patches/5DFBE144.pnach b/bin/patches/5DFBE144.pnach new file mode 100644 index 0000000..4ebdb28 --- /dev/null +++ b/bin/patches/5DFBE144.pnach @@ -0,0 +1,8 @@ +gametitle=The Getaway [SCES 51159] (E) +comment= patches by Nachbrenner +//skip IPU videos (for blockdump) +patch=0,EE,00296c14,word,00000000 +patch=0,EE,00223bc8,word,03e00008 +patch=0,EE,00223bcc,word,00000000 +patch=0,EE,002218a8,word,03e00008 +patch=0,EE,002218ac,word,00000000 \ No newline at end of file diff --git a/bin/patches/5E115FB6.pnach b/bin/patches/5E115FB6.pnach new file mode 100644 index 0000000..698ac21 --- /dev/null +++ b/bin/patches/5E115FB6.pnach @@ -0,0 +1,3 @@ +gametitle=GTA3 +//Skip Intro Videos ("InitMPEGPlayer__Fv") +patch=0,EE,0027ef00,word,1000000b \ No newline at end of file diff --git a/bin/patches/5EB127E7.pnach b/bin/patches/5EB127E7.pnach new file mode 100644 index 0000000..42304fd --- /dev/null +++ b/bin/patches/5EB127E7.pnach @@ -0,0 +1,4 @@ +gametitle= Gradius 3 & 4 [SLPM 62007] (J) +comment= +//ZeroGS Patch - GAME_INTERLACE2X +zerogs=00000004 \ No newline at end of file diff --git a/bin/patches/5F2A0E36.pnach b/bin/patches/5F2A0E36.pnach new file mode 100644 index 0000000..5e72933 --- /dev/null +++ b/bin/patches/5F2A0E36.pnach @@ -0,0 +1,7 @@ +gametitle= Armored Core 2 - Another Age [SLPS 25040] (J) +//Skip Videos (sceMpegIsEnd) +// patch=0,EE,002c8a10,word,24020001 +// Skip Intros +// patch=0,EE,00100230,word,00000000 +// Lots of credits +// patch=1,EE,00319f00,word,00C0FFEE \ No newline at end of file diff --git a/bin/patches/60013EBD.pnach b/bin/patches/60013EBD.pnach new file mode 100644 index 0000000..4cb37e9 --- /dev/null +++ b/bin/patches/60013EBD.pnach @@ -0,0 +1,5 @@ +gametitle= Gran Turismo Concept 2002 Tokyo-Geneva [SCES 50858] (E) +comment= patches by Nachbrenner +//Skip Video +patch=1,EE,00129600,word,03e00008 +patch=1,EE,00129604,word,00000000 \ No newline at end of file diff --git a/bin/patches/60FA8C69.pnach b/bin/patches/60FA8C69.pnach new file mode 100644 index 0000000..02fd6cf --- /dev/null +++ b/bin/patches/60FA8C69.pnach @@ -0,0 +1,4 @@ +gametitle=Biohazard 4 [SLPM 66213] (J) +comment= +//ZeroGS Patch - GAME_NOTARGETCLUT +zerogs=00001000 \ No newline at end of file diff --git a/bin/patches/624F11F1.pnach b/bin/patches/624F11F1.pnach new file mode 100644 index 0000000..ef96786 --- /dev/null +++ b/bin/patches/624F11F1.pnach @@ -0,0 +1,5 @@ +gametitle=Star Trek Voyager - Elite Force [SLES 50738] (E) +//Skip Videos +patch=0,EE,002945E8,word,24020001 +//suppress message: SPR0 stall 1 +patch=0,EE,0027fd18,byte,49 // 0027fd20: sw v0, $0000(v1) (D_CTRL) \ No newline at end of file diff --git a/bin/patches/625AF967.pnach b/bin/patches/625AF967.pnach new file mode 100644 index 0000000..06e2467 --- /dev/null +++ b/bin/patches/625AF967.pnach @@ -0,0 +1,4 @@ +gametitle= Nightmare Before Christmas - Oogie's Revenge [SLPM 65739] (J) +comment= +//ZeroGS Patch - GAME_TEXAHACK +zerogs=00000008 \ No newline at end of file diff --git a/bin/patches/627B8252.pnach b/bin/patches/627B8252.pnach new file mode 100644 index 0000000..9941c79 --- /dev/null +++ b/bin/patches/627B8252.pnach @@ -0,0 +1,9 @@ +gametitle=Garfield 2 - Tale of Two Kitties [SLES 54172] (E) +comment=patches by Nachbrenner +fastmemory +//Skip Videos (for blockdump) +patch=0,EE,00225bc0,word,03e00008 +patch=0,EE,00225bc4,word,00000000 +//Skip Music (for blockdump) +patch=0,EE,0033e270,word,03e00008 +patch=0,EE,0033e274,word,00000000 \ No newline at end of file diff --git a/bin/patches/62F6F886.pnach b/bin/patches/62F6F886.pnach new file mode 100644 index 0000000..3578760 --- /dev/null +++ b/bin/patches/62F6F886.pnach @@ -0,0 +1,4 @@ +gametitle=Die Hard - Vendetta Germany&Australia [SLES 51348] (E) +comment= patches by Nachbrenner +//Skip Videos +patch=0,EE,002570FC,word,00000000 \ No newline at end of file diff --git a/bin/patches/63F6B523.pnach b/bin/patches/63F6B523.pnach new file mode 100644 index 0000000..6b4e3e6 --- /dev/null +++ b/bin/patches/63F6B523.pnach @@ -0,0 +1,4 @@ +gametitle=Yu Gi Oh! Capsule Monster Coliseum (U) +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,00280f30,word,24020001 \ No newline at end of file diff --git a/bin/patches/68EAF48F.pnach b/bin/patches/68EAF48F.pnach new file mode 100644 index 0000000..6b3c4b1 --- /dev/null +++ b/bin/patches/68EAF48F.pnach @@ -0,0 +1,8 @@ +gametitle=Clock tower 3 NTSC japan +comment= +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,01818cb8,word,24020001 +//skip MovieEndCheck +//patch=0,EE,019415c8,word,70001428 +//skip MoviePlayCheck +//patch=0,EE,019415cc,word,70001428 \ No newline at end of file diff --git a/bin/patches/6926B199.pnach b/bin/patches/6926B199.pnach new file mode 100644 index 0000000..a17be64 --- /dev/null +++ b/bin/patches/6926B199.pnach @@ -0,0 +1,4 @@ +gametitle=7 Sins [SLES 53280] (E) +comment=patch by Nachbrenner & Refraction +//fix "SleepThread vs. RTFSSIOP.IRX" +patch=0,EE,004afc7c,word,00000000 \ No newline at end of file diff --git a/bin/patches/692CBA8E.pnach b/bin/patches/692CBA8E.pnach new file mode 100644 index 0000000..4958322 --- /dev/null +++ b/bin/patches/692CBA8E.pnach @@ -0,0 +1,4 @@ +gametitle=Need For Speed Most Wanted (SLES_535.57) +comment=Skips Video - deny file By Refraction +//Skip Videos +patch=0,EE,00242414,word,00000000 \ No newline at end of file diff --git a/bin/patches/6A4EFE60.pnach b/bin/patches/6A4EFE60.pnach new file mode 100644 index 0000000..99b4ad0 --- /dev/null +++ b/bin/patches/6A4EFE60.pnach @@ -0,0 +1,4 @@ +gametitle= Final Fantasy X [SLPS 25050] (J) +comment= +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/6ADBC24B.pnach b/bin/patches/6ADBC24B.pnach new file mode 100644 index 0000000..f39a15a --- /dev/null +++ b/bin/patches/6ADBC24B.pnach @@ -0,0 +1,6 @@ +gametitle=Gradius III & IV [SLES 50038] (E) +comment=patches by nachbrenner +//Skip videos +patch=0,EE,001009e4,word,00000000 +//ZeroGS Patch - GAME_INTERLACE2X +zerogs=00000004 \ No newline at end of file diff --git a/bin/patches/6BA2F6B9.pnach b/bin/patches/6BA2F6B9.pnach new file mode 100644 index 0000000..03e241c --- /dev/null +++ b/bin/patches/6BA2F6B9.pnach @@ -0,0 +1,4 @@ +gametitle=Resident Evil 4 [SLES 53702] (E) +comment= +//ZeroGS Patch - GAME_NOTARGETCLUT +zerogs=00001000 \ No newline at end of file diff --git a/bin/patches/6D70F0E0.pnach b/bin/patches/6D70F0E0.pnach new file mode 100644 index 0000000..105934e --- /dev/null +++ b/bin/patches/6D70F0E0.pnach @@ -0,0 +1,4 @@ +gametitle=Anubis 2 [SLES 53571] (E) [6D70F0E0] +comment=Patch by CKemu +//Skip Videos (scempegisend) +patch=0,EE,002DAFD0,word,24020001 \ No newline at end of file diff --git a/bin/patches/6EA9DDA9.pnach b/bin/patches/6EA9DDA9.pnach new file mode 100644 index 0000000..7a0d5c8 --- /dev/null +++ b/bin/patches/6EA9DDA9.pnach @@ -0,0 +1,4 @@ +gametitle= Resident Evil: Code Veronica X [SLES 50306] (E) +comment= patches by Nachbrenner +//Skip Videos (sceMpegIsEnd) +//patch=0,EE,00109d48,word,24020001 \ No newline at end of file diff --git a/bin/patches/7098BE76.pnach b/bin/patches/7098BE76.pnach new file mode 100644 index 0000000..82add33 --- /dev/null +++ b/bin/patches/7098BE76.pnach @@ -0,0 +1,6 @@ +gametitle=Nano Breaker [SLKA 25263] (J) +comment=patches by Nachbrenner +//Skip Videos (sceMpegIsEnd) +patch=0,EE,0010a330,word,24020001 +//fix psxUNK crash: skip RotateThreadReadyQueue +patch=0,EE,0019f708,word,00000000 \ No newline at end of file diff --git a/bin/patches/7130C553.pnach b/bin/patches/7130C553.pnach new file mode 100644 index 0000000..2a8454c --- /dev/null +++ b/bin/patches/7130C553.pnach @@ -0,0 +1,5 @@ +gametitle=Guitaroo man +comment=Skip Videos +roundmode=DOWN,CHOP +//Skip Videos +patch=0,EE,0012aa28,word,24020001 \ No newline at end of file diff --git a/bin/patches/71584BAC.pnach b/bin/patches/71584BAC.pnach new file mode 100644 index 0000000..eaa141a --- /dev/null +++ b/bin/patches/71584BAC.pnach @@ -0,0 +1,4 @@ +gametitle=Blowout [SLUS 20850] (U) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,002c4a18,word,03e00008 \ No newline at end of file diff --git a/bin/patches/722BBD62.pnach b/bin/patches/722BBD62.pnach new file mode 100644 index 0000000..f627600 --- /dev/null +++ b/bin/patches/722BBD62.pnach @@ -0,0 +1,4 @@ +gametitle=FIFA Football 2003 [SLES 51197] (E) +comment=patches by nachbrenner +// fix WaitForDMACompletion__Q212EAGLInternal6DmaMgr +patch=0,EE,0037b310,word,00000000 \ No newline at end of file diff --git a/bin/patches/7377BC6F.pnach b/bin/patches/7377BC6F.pnach new file mode 100644 index 0000000..1bb1c19 --- /dev/null +++ b/bin/patches/7377BC6F.pnach @@ -0,0 +1,4 @@ +gametitle= Naruto Ultimate Ninja [SLUS 21358] (U) +comment= Video Skip by Refraction +//Skip Videos (sceMpegIsEnd) +patch=0,EE,0011bbb0,word,24020001 diff --git a/bin/patches/763D3BF9.pnach b/bin/patches/763D3BF9.pnach new file mode 100644 index 0000000..500291d --- /dev/null +++ b/bin/patches/763D3BF9.pnach @@ -0,0 +1,8 @@ +gametitle=Spongebob Schwammkopf - Schlacht um Bikini Bottom German [SLES 51970] (E) +comment= patches by Nachbrenner +// skip FMV (sceMpegIsEnd) +patch=0,EE,001284a0,word,24020001 +//Have All Tasks Completed +patch=0,EE,0019D9F8,word,8D810020 +patch=0,EE,0019D9FC,word,24060002 +patch=0,EE,00194A04,word,A4260014 \ No newline at end of file diff --git a/bin/patches/78168525.pnach b/bin/patches/78168525.pnach new file mode 100644 index 0000000..fd4758e --- /dev/null +++ b/bin/patches/78168525.pnach @@ -0,0 +1,3 @@ +gametitle=Off-Road Wide Open [SLES 50232] (E) +//skip FMV +patch=0,EE,002953f0,word,24020001 \ No newline at end of file diff --git a/bin/patches/789D6B71.pnach b/bin/patches/789D6B71.pnach new file mode 100644 index 0000000..a3db4c0 --- /dev/null +++ b/bin/patches/789D6B71.pnach @@ -0,0 +1,4 @@ +gametitle=The Thing/Das Ding [SLES 50976] (G) +comment= patches by nachbrenner +//Skip videos (for blockdump) +patch=0,EE,006ef130,word,03e00008 \ No newline at end of file diff --git a/bin/patches/78E20421.pnach b/bin/patches/78E20421.pnach new file mode 100644 index 0000000..6ca4472 --- /dev/null +++ b/bin/patches/78E20421.pnach @@ -0,0 +1,7 @@ +gametitle=Crimson Tears [SLPM 65575] (J) +comment=patches by Nachbrenner, ported from CMX' US codes +//Funds Increase When Buying Items From Shop +patch=0,EE,0029b8fc,word,00641821 +//Infinite Health +patch=0,EE,0028581c,word,C60101FC +patch=0,EE,00285820,word,E6010200 \ No newline at end of file diff --git a/bin/patches/78FFA39F.pnach b/bin/patches/78FFA39F.pnach new file mode 100644 index 0000000..220ade0 --- /dev/null +++ b/bin/patches/78FFA39F.pnach @@ -0,0 +1,10 @@ +gametitle= Shox [SLES 51144] (E) +comment=patches by nachbrenner +//fix IPU DMA +patch=0,EE,0022d754,word,00000000 +//Skip MPC Movies +//patch=0,EE,00150724,word,00000000 +//patch=0,EE,002b0d68,word,03E00008 +//patch=0,EE,002b0d6c,word,00000000 +//patch=0,EE,002b07e8,word,03E00008 +//patch=0,EE,002b07ec,word,00000000 \ No newline at end of file diff --git a/bin/patches/7ABDBB5E.pnach b/bin/patches/7ABDBB5E.pnach new file mode 100644 index 0000000..8335357 --- /dev/null +++ b/bin/patches/7ABDBB5E.pnach @@ -0,0 +1,4 @@ +gametitle=Gran Turismo 4 Chinese [SCAJ 30007] (J) +comment=patches by nachbrenner +//skip Videos +patch=1,EE,00100D84,word,24100001 \ No newline at end of file diff --git a/bin/patches/7BA0128E.pnach b/bin/patches/7BA0128E.pnach new file mode 100644 index 0000000..7c20610 --- /dev/null +++ b/bin/patches/7BA0128E.pnach @@ -0,0 +1,3 @@ +gametitle=play it - Chess Challenger [SLES 51630] (E) +comment=patches by nachbrenner +//skip "cdrom0:\DATA\FW_LOGO.PSS \ No newline at end of file diff --git a/bin/patches/7CD1CDCD.pnach b/bin/patches/7CD1CDCD.pnach new file mode 100644 index 0000000..d582740 --- /dev/null +++ b/bin/patches/7CD1CDCD.pnach @@ -0,0 +1,12 @@ +gametitle=Simple 2000 Series - Vol. 81 - The Chikyuu Boueigun 2 [SLPM 62652] (J) +comment= patches by Nachbrenner +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,0015f990,word,24020001 +//fix "utPs2HgsControl::SynchronizeDma(Timeout...)" +patch=0,EE,0012d114,word,10000012 +//skip IPU dither +patch=0,EE,00131f30,word,00000000 +// skip sceIpuSync +patch=0,EE,00164570,word,03e00008 +// fix infinite loop (iFlushCache / D_STAT related) +patch=0,EE,00126b30,word,00000000 \ No newline at end of file diff --git a/bin/patches/7D8F539A.pnach b/bin/patches/7D8F539A.pnach new file mode 100644 index 0000000..eee8a07 --- /dev/null +++ b/bin/patches/7D8F539A.pnach @@ -0,0 +1,7 @@ +gametitle=Devil May Cry PAL [SLES 50358] (U) [7D8F539A] +comment= +//Skip Videos +patch=0,EE,0015BC78,word,00000000 +patch=0,EE,001CE340,word,03E00008 +patch=0,EE,001CE344,word,00000000 +patch=0,EE,001CE8EC,word,70001428 \ No newline at end of file diff --git a/bin/patches/7FD7A1B9.pnach b/bin/patches/7FD7A1B9.pnach new file mode 100644 index 0000000..87fad75 --- /dev/null +++ b/bin/patches/7FD7A1B9.pnach @@ -0,0 +1,8 @@ +gametitle=Jade Cocoon 2 [SLES 50735] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,00118110,word,24020001 +//Music off +patch=0,EE,00290eac,byte,00 +//Start new game with 10000 Yen +patch=0,EE,00291258,word,24022710 \ No newline at end of file diff --git a/bin/patches/83261085.pnach b/bin/patches/83261085.pnach new file mode 100644 index 0000000..f7d0488 --- /dev/null +++ b/bin/patches/83261085.pnach @@ -0,0 +1,15 @@ +gametitle=Tenchu - Wrath Of Heaven [SLES 51402] (G) +comment= patches by Nachbrenner +//fix _waitIpuIdle for intro videos +patch=0,EE,00107a10,word,00000000 +//fix D3_CHCR for tutorial's mini-videos +patch=0,EE,00310dc4,word,00000000 +// +//obsolete: +//Skip sceIpuSync +//patch=0,EE,0010c810,word,03e00008 +//Skip sceDmaSendI | sceDmaSendN +//patch=0,EE,00176824,word,24020001 +//Skip Videos +//patch=0,EE,0010B288,word,24020001 //sceMpegIsEnd +//patch=0,EE,002fe2f0,word,00000000 //xref of sceMpegGetPicture \ No newline at end of file diff --git a/bin/patches/83584608.pnach b/bin/patches/83584608.pnach new file mode 100644 index 0000000..92ff18f --- /dev/null +++ b/bin/patches/83584608.pnach @@ -0,0 +1,12 @@ +gametitle=Air Blade [SCES 50246] (E) +comment=patches by nachbrenner +//Skip Videos +//patch=0,EE,00107f28,word,24020001 +//patch=0,EE,0016f4c0,word,03e00008 +//patch=0,EE,0016f4c4,word,00000000 +//obsolete: +//VU0 fix: TsCollisionLineTriTest +//patch=0,EE,0017ecc4,word,00000000 +//VU0 fix: Skip RpHAnimHierarchyUpdateMatrices +//patch=0,EE,001ffac0,word,03e00008 +//patch=0,EE,001ffac4,word,00000000 \ No newline at end of file diff --git a/bin/patches/83D0CE43.pnach b/bin/patches/83D0CE43.pnach new file mode 100644 index 0000000..d766b0e --- /dev/null +++ b/bin/patches/83D0CE43.pnach @@ -0,0 +1,7 @@ +gametitle=Haven - Call of the King [SLES 51209] (E) +comment= patches by Nachbrenner +//disable 3D for menus and mashed music +patch=1,EE,00114c90,word,03e00008 +patch=1,EE,00114c94,word,00000000 +patch=1,EE,0010a980,word,03e00008 +patch=1,EE,0010a984,word,00000000 \ No newline at end of file diff --git a/bin/patches/844B58EE.pnach b/bin/patches/844B58EE.pnach new file mode 100644 index 0000000..792dc2a --- /dev/null +++ b/bin/patches/844B58EE.pnach @@ -0,0 +1,4 @@ +gametitle=Tekken Tag Tournament (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,004b7220,word,24020001 \ No newline at end of file diff --git a/bin/patches/85AE91B3.pnach b/bin/patches/85AE91B3.pnach new file mode 100644 index 0000000..99915ba --- /dev/null +++ b/bin/patches/85AE91B3.pnach @@ -0,0 +1,5 @@ +gametitle= Gran Turismo 3 A-spec [SCUS 97102] (U) +comment=patches by nachbrenner +//Skip Opening Video +patch=1,EE,001287a8,word,03e00008 +patch=1,EE,001287ac,word,00000000 \ No newline at end of file diff --git a/bin/patches/85E92C92.pnach b/bin/patches/85E92C92.pnach new file mode 100644 index 0000000..29e792e --- /dev/null +++ b/bin/patches/85E92C92.pnach @@ -0,0 +1,9 @@ +gametitle=The uchuujin NTSC J +comment= +//Skip Videos ("sceMpegIsEnd") +//patch=0,EE,00108fa0,word,24020001 +//Skip videos (custom) +patch=0,EE,001b4cd8,word,00000000 +//Skip videos (custom) +patch=0,EE,001b4c90,word,03e00008 +patch=0,EE,001b4c94,word,00000000 \ No newline at end of file diff --git a/bin/patches/8BC79F96.pnach b/bin/patches/8BC79F96.pnach new file mode 100644 index 0000000..125fb2b --- /dev/null +++ b/bin/patches/8BC79F96.pnach @@ -0,0 +1,9 @@ +gametitle=Formula One 2001 [SCES 50004] (E) +comment=patches by Nachbrenner +//Skip F1_Intro Video +//patch=0,EE,0010A1EC,word,00000000 +//Skip Credits Video +//patch=0,EE,0021A038,word,00000000 +//Skip FIA/ANIM256.FLC +//patch=0,EE,00162570,word,03e00008 +//patch=0,EE,00162574,word,00000000 \ No newline at end of file diff --git a/bin/patches/8BC95883.pnach b/bin/patches/8BC95883.pnach new file mode 100644 index 0000000..0e86a0c --- /dev/null +++ b/bin/patches/8BC95883.pnach @@ -0,0 +1,4 @@ +gametitle= Sly 3 - Honor Among Thieves [SCUS 97464] (U) [8BC95883] +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,002aa040,word,24020001 \ No newline at end of file diff --git a/bin/patches/8BE3D7B2.pnach b/bin/patches/8BE3D7B2.pnach new file mode 100644 index 0000000..4038bd5 --- /dev/null +++ b/bin/patches/8BE3D7B2.pnach @@ -0,0 +1,4 @@ +gametitle= Shadow Hearts [SLUS 20347] (U) +comment= +//ZeroGS Patch - GAME_NODEPTHUPDATE|GAME_AUTORESET|GAME_NOQUICKRESOLVE +zerogs=00000A02 \ No newline at end of file diff --git a/bin/patches/8DC64680.pnach b/bin/patches/8DC64680.pnach new file mode 100644 index 0000000..2660e81 --- /dev/null +++ b/bin/patches/8DC64680.pnach @@ -0,0 +1,30 @@ +gametitle=Red Faction 1 [SLES 50279] (G) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,0024b488,word,24020001 +patch=0,EE,002044d0,word,03e00008 +patch=0,EE,002044d4,word,24020001 +// skip IDEC error +patch=0,EE,002146b8,word,00000000 +//patch=0,EE,001b1d78,word,24020001 +//Skip THQ Logo +patch=0,EE,001B0A78,word,24020001 +//Skip RF Trailer +patch=0,EE,0027D19C,word,24020001 +// Unendlich Gesundheit (Inf. health) +patch=0,EE,200C0220,word,3C0142C8 +patch=0,EE,200C0224,word,44810000 +patch=0,EE,200C0228,word,03E00008 +patch=0,EE,200C022C,word,E6000034 +patch=0,EE,2016937C,word,0C030088 +// Unendlich Schutzanzug (Inf. flak jacket) +patch=0,EE,200C0230,word,3C0142C8 +patch=0,EE,200C0234,word,44811000 +patch=0,EE,200C0238,word,03E00008 +patch=0,EE,200C023C,word,E6020038 +patch=0,EE,201693E0,word,0C03008C +// Unendlich Munition (Inf. Ammo) +patch=0,EE,20154854,word,24630000 +patch=0,EE,20154890,word,24630000 +// Unendlich Sprengladungen (Inf. Explosives) +patch=0,EE,201A19BC,word,24420000 \ No newline at end of file diff --git a/bin/patches/8FDE8E16.pnach b/bin/patches/8FDE8E16.pnach new file mode 100644 index 0000000..7a12023 --- /dev/null +++ b/bin/patches/8FDE8E16.pnach @@ -0,0 +1,6 @@ +gametitle= Spongebob Squarepants - Revenge of the Flying Dutchman [SLES 51285] (E) +comment=patches by Nachbrenner +//skip "SBPlayLogoMovie" +//patch=0,EE,004531bc,word,00000000 +//skip "SBPlayDemoMovie" +//patch=0,EE,004531e0,word,00000000 \ No newline at end of file diff --git a/bin/patches/93223BE4.pnach b/bin/patches/93223BE4.pnach new file mode 100644 index 0000000..42abd09 --- /dev/null +++ b/bin/patches/93223BE4.pnach @@ -0,0 +1,7 @@ +gametitle=Formula 1 2003 [SCES 51592] (E) +comment=patches by Nachbrenner +//skip sceIpuSync +patch=0,EE,00379f78,word,03e00008 +//skip Videos +patch=0,EE,00376f80,word,03e00008 +patch=0,EE,00376f84,word,00000000 \ No newline at end of file diff --git a/bin/patches/934F9081.pnach b/bin/patches/934F9081.pnach new file mode 100644 index 0000000..f507833 --- /dev/null +++ b/bin/patches/934F9081.pnach @@ -0,0 +1,4 @@ +gametitle= Neopets - The Darkest Faerie [SCUS 97367] (U) +comment= +//ZeroGS Patch - GAME_RESOLVEPROMOTED|GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE +zerogs=0003C000 \ No newline at end of file diff --git a/bin/patches/941BB7D9.pnach b/bin/patches/941BB7D9.pnach new file mode 100644 index 0000000..653d697 --- /dev/null +++ b/bin/patches/941BB7D9.pnach @@ -0,0 +1,29 @@ +gametitle=Final Fantasy X Deutsch [SCES 50492] (G) +comment=patches by Nachbrenner +//crash fix: sceDmaSend +patch=0,EE,002dbacc,word,00000000 +patch=0,EE,002dbab8,word,00000000 +//fix DMA error: 0c0f0f00 - ipu1dma NULL! +patch=0,EE,0015ff68,word,00000000 +//Skip Videos +patch=0,EE,0015d1c0,word,100000b2 +//Skip sceIpuSync +//patch=0,EE,002e2530,word,03e00008 +//Use american savegames +//patch=0,EE,0024144c,word,24a56e60 +// +//Max GIL +patch=0,EE,201BE554,word,ACA3D218 +//Max HP +patch=0,EE,201C97B8,word,2402270F +patch=0,EE,201C97BC,word,AC620290 +//Max MP +patch=0,EE,201C97CC,word,2402270F +patch=0,EE,201C97D0,word,AC620294 +//No random battles +patch=0,EE,001be880,byte,00 +patch=0,EE,001bf2bc,byte,00 +//Hypermode +patch=0,EE,001164d0,word,3c014280 +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/94C56923.pnach b/bin/patches/94C56923.pnach new file mode 100644 index 0000000..dbe4189 --- /dev/null +++ b/bin/patches/94C56923.pnach @@ -0,0 +1,4 @@ +gametitle=Spyro: A Hero's Tale [SLUS 20884] (U) +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,003faaf0,word,24020001 \ No newline at end of file diff --git a/bin/patches/950241D3.pnach b/bin/patches/950241D3.pnach new file mode 100644 index 0000000..47a2ade --- /dev/null +++ b/bin/patches/950241D3.pnach @@ -0,0 +1,4 @@ +gametitle=Fu-Un Bakumatsu-Den [SLPM 65813] (J) +comment= patches by nachbrenner +//Skip Videos +// patch=0,EE,00112f20,word,24020001 \ No newline at end of file diff --git a/bin/patches/951555A0.pnach b/bin/patches/951555A0.pnach new file mode 100644 index 0000000..d54d9c6 --- /dev/null +++ b/bin/patches/951555A0.pnach @@ -0,0 +1,4 @@ +gametitle=Disgaea 2 - Cursed Memories [SLUS 21397] (U) +comment= +//ZeroGS Patch - GAME_NODEPTHRESOLVE +zerogs=00008000 \ No newline at end of file diff --git a/bin/patches/95BB1901.pnach b/bin/patches/95BB1901.pnach new file mode 100644 index 0000000..f9f3163 --- /dev/null +++ b/bin/patches/95BB1901.pnach @@ -0,0 +1,3 @@ +gametitle= MX VS ATV Unleashed [SLUS 21104] (U) +//Skip Movies +patch=0,EE,00339bc0,word,24020001 \ No newline at end of file diff --git a/bin/patches/96B2F56D.pnach b/bin/patches/96B2F56D.pnach new file mode 100644 index 0000000..a585027 --- /dev/null +++ b/bin/patches/96B2F56D.pnach @@ -0,0 +1,7 @@ +gametitle=Devil May Cry [SLPM 65038] (J) +comment=Skips Movies +//skip Movie_Set +patch=0,EE,001cdea0,word,03e00008 +patch=0,EE,001cdea4,word,03e00008 +//skip MovieEndCheck +patch=0,EE,001ce44c,word,70001428 \ No newline at end of file diff --git a/bin/patches/96B76E56.pnach b/bin/patches/96B76E56.pnach new file mode 100644 index 0000000..219d549 --- /dev/null +++ b/bin/patches/96B76E56.pnach @@ -0,0 +1,9 @@ +gametitle=SX Superstars [SLES 51495](E) +comment= patches by Nachbrenner +//Skip Intro Movies (for blockdump) +patch=0,EE,002f1088,word,03e00008 +patch=0,EE,002f108c,word,00000000 +//No ingame music (for blockdump) +patch=0,EE,00223cac,word,00000000 +//fix IPU DMA for "MAINMENU.IPU" (enable to go ingame) +patch=0,EE,003befe4,word,001003e0 \ No newline at end of file diff --git a/bin/patches/96C20D6F.pnach b/bin/patches/96C20D6F.pnach new file mode 100644 index 0000000..e3fdf32 --- /dev/null +++ b/bin/patches/96C20D6F.pnach @@ -0,0 +1,4 @@ +gametitle=Dynasty Warriors 4 Xtreme Legends +comment=Skips Videos by bositman +//Skip Videos +patch=0,EE,0010ab70,word,24020001 diff --git a/bin/patches/9AAC5309.pnach b/bin/patches/9AAC5309.pnach new file mode 100644 index 0000000..5b0e191 --- /dev/null +++ b/bin/patches/9AAC5309.pnach @@ -0,0 +1,4 @@ +gametitle=Final Fantasy X-2 [SLES 51815] (E) +comment= +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/9AAC530D.pnach b/bin/patches/9AAC530D.pnach new file mode 100644 index 0000000..6a7d91c --- /dev/null +++ b/bin/patches/9AAC530D.pnach @@ -0,0 +1,6 @@ +gametitle=Final Fantasy X-2 [SLES 51817] (G) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,0017e1e4,word,1000000d +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/9AC65D6A.pnach b/bin/patches/9AC65D6A.pnach new file mode 100644 index 0000000..536ad77 --- /dev/null +++ b/bin/patches/9AC65D6A.pnach @@ -0,0 +1,4 @@ +gametitle=Atelier Iris 2 +comment=Skips Video by bositman +//Skip Videos +patch=0,EE,002bdbb8,word,24020001 \ No newline at end of file diff --git a/bin/patches/9B1EE9EB.pnach b/bin/patches/9B1EE9EB.pnach new file mode 100644 index 0000000..f4047b5 --- /dev/null +++ b/bin/patches/9B1EE9EB.pnach @@ -0,0 +1,4 @@ +gametitle=DNA - Dark Native Apostle [SLES 50202] (E) +comment=patches by Nachbrenner +//Skip PSSPLAY.ELF +patch=1,EE,001691F0,word,00000000 \ No newline at end of file diff --git a/bin/patches/9BE3F92D.pnach b/bin/patches/9BE3F92D.pnach new file mode 100644 index 0000000..1bec0f4 --- /dev/null +++ b/bin/patches/9BE3F92D.pnach @@ -0,0 +1,4 @@ +gametitle=Psyvariar Complete Edition [SLPM62139] (J) +comment=patch by Nachbrenner +//skip movie +patch=0,EE,0010019c,word,00000000 \ No newline at end of file diff --git a/bin/patches/9D6F46F0.pnach b/bin/patches/9D6F46F0.pnach new file mode 100644 index 0000000..848d09f --- /dev/null +++ b/bin/patches/9D6F46F0.pnach @@ -0,0 +1,4 @@ +gametitle=GoDai Elemental Force [SLES 50704] (E) +comment= patches by Nachbrenner +//Skip Videos +patch=0,EE,00211c90,word,24020001 \ No newline at end of file diff --git a/bin/patches/A029B109.pnach b/bin/patches/A029B109.pnach new file mode 100644 index 0000000..f55485a --- /dev/null +++ b/bin/patches/A029B109.pnach @@ -0,0 +1,12 @@ +gametitle=Grand Prix Challenge [SLES 51296] (E) +comment=patches by Nachbrenner +//g_dmaMaximumWaitTime (default=40400000) +patch=0,EE,00484f88,word,00000000 +// +//for blockdump: +//Don't stream videos (press 3 times X after FIA logo) +patch=0,EE,003a6fc0,word,03e00008 // UpdateInternal__12fmvStreamPS2Fv +patch=0,EE,003a6fc4,word,00000000 +//skip Play__13slMusicStreamFv +patch=0,EE,002ea300,word,03e00008 +patch=0,EE,002ea304,word,00000000 \ No newline at end of file diff --git a/bin/patches/A1B752C7.pnach b/bin/patches/A1B752C7.pnach new file mode 100644 index 0000000..e5e65c9 --- /dev/null +++ b/bin/patches/A1B752C7.pnach @@ -0,0 +1,4 @@ +gametitle=Sensible Soccer 2006 +comment=Patch By Refraction +//Skip Videos +patch=0,EE,0036b0a0,word,24020001 \ No newline at end of file diff --git a/bin/patches/A36CFF6C.pnach b/bin/patches/A36CFF6C.pnach new file mode 100644 index 0000000..7a37c56 --- /dev/null +++ b/bin/patches/A36CFF6C.pnach @@ -0,0 +1,3 @@ +gametitle=Castlevania NTSC JPN +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,007296b0,word,24020001 \ No newline at end of file diff --git a/bin/patches/A39517AB.pnach b/bin/patches/A39517AB.pnach new file mode 100644 index 0000000..ecd2924 --- /dev/null +++ b/bin/patches/A39517AB.pnach @@ -0,0 +1,16 @@ +gametitle=Final Fantasy X [SCES 50490] (E) [A39517AB] +comment=Patch By CKemu +// +//Emulation Fixes +//Skip Videos [No longer required: 0.9.2-0715-i] +//patch=0,EE,0015d1c0,word,100000b2 +//Kill INIT SOUND [No longer required: 0.9.2-0715-i] +//patch=0,EE,00126074,word,00000000 +//Kill INIT VOICE [No longer required: 0.9.2-0715-i] +//patch=0,EE,00126088,word,00000000 +// +//Misc Patches +//Use (U) gamesaves [SLUS 20312] +//patch=0,EE,00241434,word,24a56e60 +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/A3ACF3C7.pnach b/bin/patches/A3ACF3C7.pnach new file mode 100644 index 0000000..4760ded --- /dev/null +++ b/bin/patches/A3ACF3C7.pnach @@ -0,0 +1,8 @@ +gametitle=Project Eden [SLES 50553] (E) +comment=patches by Nachbrenner +//Skip EC_LOGO Video +patch=0,EE,0013af54,word,00000000 +patch=0,EE,0013af60,word,00000000 +//Skip INTRO Video +patch=0,EE,0013b060,word,00000000 +patch=0,EE,0013b06c,word,00000000 \ No newline at end of file diff --git a/bin/patches/A4E2C043.pnach b/bin/patches/A4E2C043.pnach new file mode 100644 index 0000000..e29021c --- /dev/null +++ b/bin/patches/A4E2C043.pnach @@ -0,0 +1,8 @@ +gametitle=Homura [SLPM 62685] (J) +comment=patches by Nachbrenner +//Infinite Lives 00310758 +patch=0,EE,00225714,word,24030005 +//Infinite Health +patch=0,EE,00213884,word,00000000 +//Infinite Bombs 0031075C +patch=0,EE,00227174,word,24030005 \ No newline at end of file diff --git a/bin/patches/A5BF36A8.pnach b/bin/patches/A5BF36A8.pnach new file mode 100644 index 0000000..07eb857 --- /dev/null +++ b/bin/patches/A5BF36A8.pnach @@ -0,0 +1,3 @@ +gametitle=Paris-Dakar Rally [SLES 50212] (E) +//Skip Videos +patch=0,EE,001098e8,word,24020001 \ No newline at end of file diff --git a/bin/patches/A63C896C.pnach b/bin/patches/A63C896C.pnach new file mode 100644 index 0000000..c9ff6f7 --- /dev/null +++ b/bin/patches/A63C896C.pnach @@ -0,0 +1,6 @@ +gametitle=Tsukyo Ni Saraba [SLPM 65826] (J) +comment=patches by Nachbrenner +//infinite ammo +patch=0,EE,003620b4,word,24040000 +//crash fix (nukes AI) +patch=0,EE,0025328c,word,00000000 \ No newline at end of file diff --git a/bin/patches/A719D130.pnach b/bin/patches/A719D130.pnach new file mode 100644 index 0000000..927ce3c --- /dev/null +++ b/bin/patches/A719D130.pnach @@ -0,0 +1,4 @@ +gametitle=Dynasty Warriors 5 +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,0011a240,word,24020001 \ No newline at end of file diff --git a/bin/patches/A74F99CD.pnach b/bin/patches/A74F99CD.pnach new file mode 100644 index 0000000..9022547 --- /dev/null +++ b/bin/patches/A74F99CD.pnach @@ -0,0 +1,4 @@ +gametitle=Psyvariar Revision [SLPM 62371] (J) +comment= +//Skip Videos +patch=0,EE,00155938,word,00000000 \ No newline at end of file diff --git a/bin/patches/A7A2F7C5.pnach b/bin/patches/A7A2F7C5.pnach new file mode 100644 index 0000000..6b64734 --- /dev/null +++ b/bin/patches/A7A2F7C5.pnach @@ -0,0 +1,16 @@ +gametitle=Disney's Stitch: Experiment 626 [SCES 50960] (E) +comment=patches by Nachbrenner +//Skip Videos +//patch=0,EE,001edbe4,word,00000000 +//Skip music +patch=0,EE,001d1de0,word,03e00008 +patch=0,EE,001d1de4,word,00000000 +patch=1,EE,00A02FAC,word,00000000 +//MTGS vs. GS_CSR +//patch=0,EE,00269e00,word,00000000 +//patch=0,EE,00269de4,word,00000000 +//patch=0,EE,002e3d54,word,00000000 +//patch=0,EE,00269fdc,word,00000000 +//patch=0,EE,0026a018,word,00000000 +//sceGsExecStoreImage +//patch=0,EE,002e22ec,word,00000000 \ No newline at end of file diff --git a/bin/patches/A88ACA28.pnach b/bin/patches/A88ACA28.pnach new file mode 100644 index 0000000..e238e20 --- /dev/null +++ b/bin/patches/A88ACA28.pnach @@ -0,0 +1,9 @@ +gametitle=Codename: Kids Next Door - Operation V.I.D.E.O.G.A.M.E [SLES 53685] (E) +comment=patches by nachbrenner +// MMI fix: replace PINTH with PINTEH (obsolete) +//patch=0,EE,0037eef8,word,700212a9 +// skip SFD movies +patch=0,EE,00208220,word,03e00008 +patch=0,EE,00208224,word,00000000 +patch=0,EE,00208190,word,03e00008 +patch=0,EE,00208194,word,00000000 \ No newline at end of file diff --git a/bin/patches/A929A697.pnach b/bin/patches/A929A697.pnach new file mode 100644 index 0000000..fcd8217 --- /dev/null +++ b/bin/patches/A929A697.pnach @@ -0,0 +1,3 @@ +gametitle=Turok: Evolution [SLES 51124] (G) +//Skip Videos (sceMpegIsEnd) +patch=0,EE,001cf280,word,24020001 \ No newline at end of file diff --git a/bin/patches/A9759015.pnach b/bin/patches/A9759015.pnach new file mode 100644 index 0000000..6ac48fa --- /dev/null +++ b/bin/patches/A9759015.pnach @@ -0,0 +1,9 @@ +gametitle=Flucht von Monkey Island [SLES 50227] (G) +comment=patches by nachbrenner +//Skip Videos +//patch=0,EE,001c5220,word,24020001 +//patch=0,EE,0018b850,word,03E00008 +//patch=0,EE,0018b854,word,00000000 +//fix MTGS loop at GS_CSR in sceGsExecStoreImage +//patch=0,EE,001bb858,word,34630002 +//patch=0,EE,001bb888,word,34420002 \ No newline at end of file diff --git a/bin/patches/AC7E88D9.pnach b/bin/patches/AC7E88D9.pnach new file mode 100644 index 0000000..6946863 --- /dev/null +++ b/bin/patches/AC7E88D9.pnach @@ -0,0 +1,18 @@ +gametitle=Silpheed - The Lost Planet [SLES 50193] (E) +comment=patches by Nachbrenner +//default player name = PCSX2 +patch=0,EE,008c7a48,word,58534350 +patch=0,EE,008c7a4c,word,00000032 +//Skip SOLONT.PSS +patch=0,EE,0019561c,word,00000000 +//Skip ?PART.MOV +patch=0,EE,0019556c,word,00000000 +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,0025c3f8,word,24020001 +//Have All Weapons +patch=0,EE,0015a488,word,340201ff +patch=0,EE,0015b2f4,word,340201ff +// Inf. Shield (ASM) +patch=0,EE,0013DA0C,word,00000000 +//BGM off (for blockdump) +//patch=0,EE,008ac334,word,00000000 diff --git a/bin/patches/ACB1989A.pnach b/bin/patches/ACB1989A.pnach new file mode 100644 index 0000000..b7bc883 --- /dev/null +++ b/bin/patches/ACB1989A.pnach @@ -0,0 +1,10 @@ +gametitle=Midnight Club II [SLES 51054] (E) +comment=patches by Nachbrenner +//skip videos (for blockdump) +//patch=0,EE,0013DB58,word,00000000 +//skip network check "BT_ok_to_initialize_networking" +//patch=0,EE,00123efc,word,00000000 +//music off (for blockdump) +//patch=1,EE,004ABB1C,word,00000000 +//crash fix SVN november (obsolete) +//patch=0,EE,0016c9a4,word,10000068 \ No newline at end of file diff --git a/bin/patches/AD9D2B54.pnach b/bin/patches/AD9D2B54.pnach new file mode 100644 index 0000000..7316db8 --- /dev/null +++ b/bin/patches/AD9D2B54.pnach @@ -0,0 +1,4 @@ +gametitle=worldtvfighters NTSC JPN +comment=skip intro pss +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,002d8df8,word,24020001 \ No newline at end of file diff --git a/bin/patches/ADAA1256.pnach b/bin/patches/ADAA1256.pnach new file mode 100644 index 0000000..a4bc9e0 --- /dev/null +++ b/bin/patches/ADAA1256.pnach @@ -0,0 +1,8 @@ +gametitle=Steel Dragon EX [SLES 52482] (E) +comment=patches by Nachbrenner +//Disable BGM +//patch=0,EE,0015bcf8,word,00000000 +//Disable SE +//patch=0,EE,0015bcf0,word,00000000 +//Skip Memory Card check +patch=0,EE,0015bd00,word,00000000 \ No newline at end of file diff --git a/bin/patches/AE0E098F.pnach b/bin/patches/AE0E098F.pnach new file mode 100644 index 0000000..0f363aa --- /dev/null +++ b/bin/patches/AE0E098F.pnach @@ -0,0 +1,6 @@ +gametitle=Indiana Jones und die Legende der Kaisergruft [SLES 50838] (G) +comment=patches by Nachbrenner +//Skip Videos +//patch=1,EE,00100624,word,24020000 // legal.pss +//patch=1,EE,0012c414,word,24020000 // leclogo.pss +//patch=1,EE,00100674,word,24020000 // cslogo.pss \ No newline at end of file diff --git a/bin/patches/AE3EAA05.pnach b/bin/patches/AE3EAA05.pnach new file mode 100644 index 0000000..839d020 --- /dev/null +++ b/bin/patches/AE3EAA05.pnach @@ -0,0 +1,13 @@ +gametitle=Kingdom Hearts German [SCES 50969] (G) +comment=patches by Nachbrenner +//Size modifier +// default = 1 (3f800000) +// patch=0,EE,001243BC,word,3c014000 //double size +//Hypermode +// default = 1.2 (3f999999) +// max =5 (40a00000) +//Don't use "Hypermode" in cutscenes. +//patch=0,EE,0011007c,word,3c0140a0 +//patch=0,EE,00110080,word,34210000 +//ZeroGS Patch - GAME_QUICKRESOLVE1 +zerogs=00000400 \ No newline at end of file diff --git a/bin/patches/AE9EB9A0.pnach b/bin/patches/AE9EB9A0.pnach new file mode 100644 index 0000000..ce1dc32 --- /dev/null +++ b/bin/patches/AE9EB9A0.pnach @@ -0,0 +1,4 @@ +gametitle=TD overdrive - The Brotherhood Of Speed [SLES 50778] (E) +comment= patches by Nachbrenner +// skip FMV sceMpegIsEnd +// patch=1,EE,0030aad0,word,24020001 \ No newline at end of file diff --git a/bin/patches/AEDAEE99.pnach b/bin/patches/AEDAEE99.pnach new file mode 100644 index 0000000..6430aa7 --- /dev/null +++ b/bin/patches/AEDAEE99.pnach @@ -0,0 +1,3 @@ +gametitle=GodHand [SLPM 66550] (J) +//fix DMA loop +patch=0,EE,002bdd28,word,24020001 \ No newline at end of file diff --git a/bin/patches/AFAC88EF.pnach b/bin/patches/AFAC88EF.pnach new file mode 100644 index 0000000..1252550 --- /dev/null +++ b/bin/patches/AFAC88EF.pnach @@ -0,0 +1,14 @@ +gametitle= Dirge Of Cerberus - Final Fantasy VII [SLPM 66271] (J) +comment=patches by Nachbrenner +//Fix "**** SQTHREAD ERROR : BAD LOCK STATE" +patch=0,EE,0047d228,word,00000000 +//Skip Videos +// patch=0,EE,00255264,word,00000000 +//fix ingame DMA0 +patch=0,EE,00283060,word,10000020 +//fix ingame DMA8 +//patch=0,EE,0031d714,word,00000000 +//fix ingame VIF1_STAT +//patch=0,EE,004a184c,word,00000000 +//Skip mcDelayThread +//patch=0,EE,004b7c88,word,00000000 \ No newline at end of file diff --git a/bin/patches/B0AE1898.pnach b/bin/patches/B0AE1898.pnach new file mode 100644 index 0000000..40e6b68 --- /dev/null +++ b/bin/patches/B0AE1898.pnach @@ -0,0 +1,6 @@ +gametitle=smackdown shut your mouth +comment=patched by prafull +//skip sceipusync +patch=0,EE,0010b880,word,00000000 +patch=0,EE,0010b798,word,00000000 +patch=0,EE,0010b7c8,word,00000000 \ No newline at end of file diff --git a/bin/patches/B1BE3E51.pnach b/bin/patches/B1BE3E51.pnach new file mode 100644 index 0000000..47cf390 --- /dev/null +++ b/bin/patches/B1BE3E51.pnach @@ -0,0 +1,6 @@ +gametitle=Whiplash [SLES 51958] (E) +comment=patches by nachbrenner +//Skip error printing +//patch=0,EE,00252d88,word,00000000 +//fix jalr crash +patch=0,EE,0040db84,word,0010c370 \ No newline at end of file diff --git a/bin/patches/B234036E.pnach b/bin/patches/B234036E.pnach new file mode 100644 index 0000000..c8d3f50 --- /dev/null +++ b/bin/patches/B234036E.pnach @@ -0,0 +1,4 @@ +gametitle=Guilty Gear X2 Reload [SLES 52967] (E) [B234036E] +comment=Patch By CKemu +//Skip Videos +patch=0,EE,00250418,word,24020001 \ No newline at end of file diff --git a/bin/patches/B2BDE9F3.pnach b/bin/patches/B2BDE9F3.pnach new file mode 100644 index 0000000..b3053be --- /dev/null +++ b/bin/patches/B2BDE9F3.pnach @@ -0,0 +1,6 @@ +gametitle=Hisshou Pachinko Pachi-Slot Kouryoku Series Vol. 7 - Fever Powerful Zero [SLPS 25697] (J) +//Skip sceIpuSync +patch=0,EE,00100dd8,word,03e00008 +//IPU VQ fix +patch=0,EE,0021b2cc,word,00000000 // ? +patch=0,EE,0021b08c,word,00000000 // _pictureData0 \ No newline at end of file diff --git a/bin/patches/B338676A.pnach b/bin/patches/B338676A.pnach new file mode 100644 index 0000000..015616c --- /dev/null +++ b/bin/patches/B338676A.pnach @@ -0,0 +1,6 @@ +gametitle=Summoner 2 [SLES 51142] (G) +comment=patches by Nachbrenner +//skip FMV (sceMpegIsEnd) +// patch=0,EE,001c6638,word,24020001 +//brute force fix GS_CSR +// patch=0,EE,00188604,word,fc620000 // sd v0, $0000(v1) diff --git a/bin/patches/B34DA141.pnach b/bin/patches/B34DA141.pnach new file mode 100644 index 0000000..b6bfb87 --- /dev/null +++ b/bin/patches/B34DA141.pnach @@ -0,0 +1,8 @@ +gametitle=The Mouse Police [SLES 52370] (E) +comment=patches by Nachbrenner +//Skip LOGO.PSS +//patch=0,EE,0012945c,word,24020001 +//Skip INTRO.PSS +//patch=0,EE,001293f8,word,24020001 +//Skip DALAMATIO.PSS +//patch=0,EE,0012a69c,word,00000000 \ No newline at end of file diff --git a/bin/patches/B36EE21E.pnach b/bin/patches/B36EE21E.pnach new file mode 100644 index 0000000..3bb63f7 --- /dev/null +++ b/bin/patches/B36EE21E.pnach @@ -0,0 +1,5 @@ +gametitle=IndyCar Series [SLUS 20641] (U) +//skip BjMediaVideoPlay +patch=0,EE,00204b38,word,24020001 +patch=0,EE,001ea500,word,03e00008 +patch=0,EE,001ea504,word,00000000 \ No newline at end of file diff --git a/bin/patches/B590CE04.pnach b/bin/patches/B590CE04.pnach new file mode 100644 index 0000000..09d3d14 --- /dev/null +++ b/bin/patches/B590CE04.pnach @@ -0,0 +1,5 @@ +gametitle=Gran Turismo 3 A-Spec [SCES 50294] (E) [B590CE04] +comment= patches by Nachbrenner +//Skip Intro Videos +patch=1,EE,00128c60,word,03e00008 +patch=1,EE,00128c64,word,00000000 \ No newline at end of file diff --git a/bin/patches/B82E4C4B.pnach b/bin/patches/B82E4C4B.pnach new file mode 100644 index 0000000..6fe99e4 --- /dev/null +++ b/bin/patches/B82E4C4B.pnach @@ -0,0 +1,4 @@ +gametitle=Play it Pinball (E) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,002b29d0,word,24020001 \ No newline at end of file diff --git a/bin/patches/B99379B7.pnach b/bin/patches/B99379B7.pnach new file mode 100644 index 0000000..d30bb15 --- /dev/null +++ b/bin/patches/B99379B7.pnach @@ -0,0 +1,4 @@ +gametitle=Erementar Gerad [SLPM 62623] (J) +comment=patches by Nachbrenner +//Skip Videos (sceMpegIsEnd) +patch=0,EE,002861c8,word,24020001 \ No newline at end of file diff --git a/bin/patches/BB3D833A.pnach b/bin/patches/BB3D833A.pnach new file mode 100644 index 0000000..bdf191f --- /dev/null +++ b/bin/patches/BB3D833A.pnach @@ -0,0 +1,4 @@ +gametitle= Final Fantasy X [SLUS 20312] (U) +comment= +//ZeroGS Patch - GAME_FFXHACK +zerogs=00000080 \ No newline at end of file diff --git a/bin/patches/BD3DBCF9.pnach b/bin/patches/BD3DBCF9.pnach new file mode 100644 index 0000000..169e6b5 --- /dev/null +++ b/bin/patches/BD3DBCF9.pnach @@ -0,0 +1,4 @@ +gametitle=Dynasty Warriors 4 - Empires +comment=Skips Video +//Skip Video +patch=0,EE,00211544,word,00000000 \ No newline at end of file diff --git a/bin/patches/BF5D9AEC.pnach b/bin/patches/BF5D9AEC.pnach new file mode 100644 index 0000000..94f6564 --- /dev/null +++ b/bin/patches/BF5D9AEC.pnach @@ -0,0 +1,4 @@ +gametitle=Gungrave US/C NTSC +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,001c07b0,word,24020001 \ No newline at end of file diff --git a/bin/patches/C04FB5FD.pnach b/bin/patches/C04FB5FD.pnach new file mode 100644 index 0000000..640b1bb --- /dev/null +++ b/bin/patches/C04FB5FD.pnach @@ -0,0 +1,4 @@ +gametitle=Superior Defender Gundam Force Showdown! [SLUS 20698] (U) +comment= Captain Gundam The Secret Defender Of Neotopia +//Skip Videos +patch=0,EE,0010c660,word,24020001 \ No newline at end of file diff --git a/bin/patches/C1625F14.pnach b/bin/patches/C1625F14.pnach new file mode 100644 index 0000000..44adb21 --- /dev/null +++ b/bin/patches/C1625F14.pnach @@ -0,0 +1,9 @@ +gametitle=Midnight Club II [SLUS20209] (U) +comment=patches by Nachbrenner +//skip videos +patch=0,EE,0013D5E0,word,00000000 +//skip sceIpuSync +patch=0,EE,003ef4e8,word,03e00008 +patch=0,EE,003ef4ec,word,00000000 +//skip network check "BT_ok_to_initialize_networking" +patch=0,EE,00123c70,word,00000000 \ No newline at end of file diff --git a/bin/patches/C1767D64.pnach b/bin/patches/C1767D64.pnach new file mode 100644 index 0000000..3498d7e --- /dev/null +++ b/bin/patches/C1767D64.pnach @@ -0,0 +1,5 @@ +gametitle=Gitaroo man (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,0012ea48,word,24020001 +roundmode=DOWN,CHOP \ No newline at end of file diff --git a/bin/patches/C1B141D6.pnach b/bin/patches/C1B141D6.pnach new file mode 100644 index 0000000..560adcc --- /dev/null +++ b/bin/patches/C1B141D6.pnach @@ -0,0 +1,7 @@ +gametitle= 25 To Life [SLUS 21016] (U) +comment=patches by Nachbrenner and Refraction +//Skip Videos (for blockdump) +// patch=0,EE,0040ade4,word,00000000 +//fix EEREC: LQ qw align +// patch=0,EE,0043b31c,word,78c40020 // intro (fixed) +patch=0,EE,0022d3d0,word,79050020 // ingame (still borked) \ No newline at end of file diff --git a/bin/patches/C220951A.pnach b/bin/patches/C220951A.pnach new file mode 100644 index 0000000..64923c4 --- /dev/null +++ b/bin/patches/C220951A.pnach @@ -0,0 +1,5 @@ +gametitle= Gran Turismo Concept 2001 Tokyo [SCPS 15010] (J) +comment= patches by Nachbrenner +//Skip Video +patch=1,EE,001295b8,word,03e00008 +patch=1,EE,001295bc,word,00000000 \ No newline at end of file diff --git a/bin/patches/C3D28EB9.pnach b/bin/patches/C3D28EB9.pnach new file mode 100644 index 0000000..3155b69 --- /dev/null +++ b/bin/patches/C3D28EB9.pnach @@ -0,0 +1,4 @@ +gametitle=Shadow Hearts - From The New World +comment=Skips Video,by bositman +//Skip Videos +patch=0,EE,00208b68,word,24020001 \ No newline at end of file diff --git a/bin/patches/C4467D30.pnach b/bin/patches/C4467D30.pnach new file mode 100644 index 0000000..35049d9 --- /dev/null +++ b/bin/patches/C4467D30.pnach @@ -0,0 +1,4 @@ +gametitle=World Rally Championship 3 [SLPM 65583] (J) +comment= patch by Nachbrenner +//Skip sceIpuSync +patch=1,EE,0027c808,word,03e00008 \ No newline at end of file diff --git a/bin/patches/C488EC04.pnach b/bin/patches/C488EC04.pnach new file mode 100644 index 0000000..3be542c --- /dev/null +++ b/bin/patches/C488EC04.pnach @@ -0,0 +1,8 @@ +gametitle=Ninjabread Man [SLES 53570] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,00169e78,word,03e00008 +//Skip Music (for blockdumps) +//patch=0,EE,00106d6c,word,00000000 +//patch=0,EE,0014352c,word,00000000 +//patch=0,EE,00151738,word,00000000 \ No newline at end of file diff --git a/bin/patches/C4A60986.pnach b/bin/patches/C4A60986.pnach new file mode 100644 index 0000000..76e3f13 --- /dev/null +++ b/bin/patches/C4A60986.pnach @@ -0,0 +1,4 @@ +gametitle=Sega Ages 2500 Volume 01 - Phantasy Star generation:1 (J) +comment=patches by Nachbrenner +//Get money for buying wares +patch=0,EE,0010e690,word,00a2282d \ No newline at end of file diff --git a/bin/patches/C502AD6E.pnach b/bin/patches/C502AD6E.pnach new file mode 100644 index 0000000..ee561af --- /dev/null +++ b/bin/patches/C502AD6E.pnach @@ -0,0 +1,8 @@ +gametitle=Wallace & Grommit in Projekt Zoo [SLES 52026] (G) +comment=patches by Nachbrenner +//skip FMV (for blockdump) +//patch=0,EE,0046bf70,word,24020001 +//skip sceIpuSync +patch=0,EE,00472c78,word,03e00008 +//Disable Music & Speech (for blockdump) +//patch=0,EE,005767ac,word,001001d0 \ No newline at end of file diff --git a/bin/patches/C5DEFEA0.pnach b/bin/patches/C5DEFEA0.pnach new file mode 100644 index 0000000..eac5319 --- /dev/null +++ b/bin/patches/C5DEFEA0.pnach @@ -0,0 +1,5 @@ +gametitle=Okami [SLPM 66375] (J) +//fix sceSifDmaStat loop +patch=0,EE,00212a78,word,24020001 +//ZeroGS Patch - GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE +zerogs=0005C000 \ No newline at end of file diff --git a/bin/patches/C9246E9C.pnach b/bin/patches/C9246E9C.pnach new file mode 100644 index 0000000..b55731c --- /dev/null +++ b/bin/patches/C9246E9C.pnach @@ -0,0 +1,4 @@ +gametitle=Tetris Worlds NTSC +comment=Skips videos +//Skip Videos +patch=0,EE,002cea30,word,24020001 \ No newline at end of file diff --git a/bin/patches/C9C145BF.pnach b/bin/patches/C9C145BF.pnach new file mode 100644 index 0000000..da2733e --- /dev/null +++ b/bin/patches/C9C145BF.pnach @@ -0,0 +1,10 @@ +gametitle=Crazy Taxi [SLES 50215] (E) +comment= patches by Nachbrenner +//skip movie "PlaySega" +patch=0,EE,001a42d0,word,03e00008 +patch=0,EE,001a42d4,word,00000000 +//skip movie "PlayAcclaim" +patch=0,EE,001a4468,word,03e00008 +patch=0,EE,001a446c,word,00000000 +//skip nlWaitVSync / TaxiBlankInterrupt +//patch=0,EE,0019cf10,word,03e00008 \ No newline at end of file diff --git a/bin/patches/CA295E61.pnach b/bin/patches/CA295E61.pnach new file mode 100644 index 0000000..01f5470 --- /dev/null +++ b/bin/patches/CA295E61.pnach @@ -0,0 +1,4 @@ +gametitle= Atelier Iris Grand Phantasm [SLPM 66436] (J) +comment= Video Skip before MCD screen by Refraction +//Nop out IPU routine +patch=0,EE,00135cdc,word,00000000 \ No newline at end of file diff --git a/bin/patches/CA6243B9.pnach b/bin/patches/CA6243B9.pnach new file mode 100644 index 0000000..83ae220 --- /dev/null +++ b/bin/patches/CA6243B9.pnach @@ -0,0 +1,9 @@ +gametitle=Gran Turismo 4 Prologue China [PBPX 95524] (J) +comment=patches by Nachbrenner +//fix IPU DMA +patch=1,EE,00166814,word,00000000 +patch=1,EE,003a36b8,word,00000000 +patch=1,EE,003a36f4,word,00000000 +//Skip Videos +patch=1,EE,001e3718,word,03e00008 +patch=1,EE,001e371c,word,00000000 diff --git a/bin/patches/CB4EBD11.pnach b/bin/patches/CB4EBD11.pnach new file mode 100644 index 0000000..ec94b28 --- /dev/null +++ b/bin/patches/CB4EBD11.pnach @@ -0,0 +1,7 @@ +gametitle=Dakar 2 [SLES 50879] (E) +comment= patches by Nachbrenner +//Skip Intro Videos +patch=0,EE,00139188,word,10000029 +//KOSMOS fix +patch=0,EE,00171874,word,00000000 // D1_CHCR +patch=0,EE,001718c4,word,00000000 // GS_CSR \ No newline at end of file diff --git a/bin/patches/CBBC2E7F.pnach b/bin/patches/CBBC2E7F.pnach new file mode 100644 index 0000000..9b587c3 --- /dev/null +++ b/bin/patches/CBBC2E7F.pnach @@ -0,0 +1,15 @@ +gametitle= WRC Rally Evolved [SCES 53247] (E) +comment=patches by Nachbrenner +//fix delay slot violation (obsolete) +//patch=1,EE,003cc890,word,19c0004d +//patch=1,EE,003cc894,word,01ad6826 +//patch=1,EE,003cbc78,word,01ce7026 +//patch=1,EE,003cbc7c,word,19a0006c +//patch=1,EE,003cc528,word,01ce7026 +//patch=1,EE,003cc52c,word,19a0000c +//patch=1,EE,003cc46c,word,01ce7026 +//patch=1,EE,003cc470,word,19a0000f +//patch=1,EE,003cc704,word,01ce7026 +//patch=1,EE,003cc708,word,19a0000f +//patch=1,EE,003ccbb4,word,01ce7026 +//patch=1,EE,003ccbb8,word,19a00011 \ No newline at end of file diff --git a/bin/patches/CC4B9CDE.pnach b/bin/patches/CC4B9CDE.pnach new file mode 100644 index 0000000..2fd8ebe --- /dev/null +++ b/bin/patches/CC4B9CDE.pnach @@ -0,0 +1,4 @@ +gametitle=Samurai Warriors 2 [SLUS 21462] (U) +comment=Skips Video (sceMpegIsEnd) +//Skip Videos +patch=0,EE,0013CD10,word,24020001 \ No newline at end of file diff --git a/bin/patches/CC6AA742.pnach b/bin/patches/CC6AA742.pnach new file mode 100644 index 0000000..5f5e248 --- /dev/null +++ b/bin/patches/CC6AA742.pnach @@ -0,0 +1,4 @@ +gametitle=FIFA Soccer 2004 [SLKA 25087] (J) +comment=patches by Nachbrenner +//boot with english texts +patch=0,EE,00329b7c,word,24709430 \ No newline at end of file diff --git a/bin/patches/CDE7C999.pnach b/bin/patches/CDE7C999.pnach new file mode 100644 index 0000000..d44a0fe --- /dev/null +++ b/bin/patches/CDE7C999.pnach @@ -0,0 +1,22 @@ +gametitle= World Rally Championship 4 [SCES 52389] (E) +comment=patches by Nachbrenner +//fix caching issue +patch=1,EE,004007e0,word,0080f809 +// +//skip STR videos (for blockdump) +patch=1,EE,00354850,word,00000000 +//Skip sceIpuSync +patch=1,EE,003811f0,word,03e00008 +//Disable video rendering (for speedy menus) +//patch=1,EE,00353960,word,00000000 +//fix delay slot violations (obsolete) +//patch=1,EE,002d8328,word,01ce7026 +//patch=1,EE,002d832c,word,19a0006c +//patch=1,EE,002d8c8c,word,01ce7026 +//patch=1,EE,002d8c90,word,19a0000f +//patch=1,EE,002d8f14,word,01ce7026 +//patch=1,EE,002d8f18,word,19a0000f +//patch=1,EE,002d8d48,word,01ce7026 +//patch=1,EE,002d8d4c,word,19a0000c +//patch=1,EE,002d9770,word,01ce7026 +//patch=1,EE,002d9774,word,19a00011 \ No newline at end of file diff --git a/bin/patches/CF11CD83.pnach b/bin/patches/CF11CD83.pnach new file mode 100644 index 0000000..1c394e5 --- /dev/null +++ b/bin/patches/CF11CD83.pnach @@ -0,0 +1,6 @@ +gametitle=Samurai Warriors +comment=Skips Video,by bositman +//Skip Videos +patch=0,EE,00126af0,word,24020001 +//ZeroGS patch - GAME_AUTORESET +zerogs=00000002 \ No newline at end of file diff --git a/bin/patches/CFB873AD.pnach b/bin/patches/CFB873AD.pnach new file mode 100644 index 0000000..a1f4bfc --- /dev/null +++ b/bin/patches/CFB873AD.pnach @@ -0,0 +1,6 @@ +gametitle=Need For Speed Underground 2 [SLES52725] (E) +comment= patches by Nachbrenner +//Skip videos +patch=0,EE,0042b400,word,24020001 +//skip "RCMPDecodeBuffer" causing cputlbmiss +patch=0,EE,0025a970,word,00000000 \ No newline at end of file diff --git a/bin/patches/D03BEF2A.pnach b/bin/patches/D03BEF2A.pnach new file mode 100644 index 0000000..f7d3ae2 --- /dev/null +++ b/bin/patches/D03BEF2A.pnach @@ -0,0 +1,13 @@ +gametitle=Max Payne 2 - The Fall Of Max Payne [SLES 52336] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,002c8650,word,03e00008 +patch=0,EE,002c8654,word,00000000 +//fix obscure inf. loop +patch=0,EE,001aa610,word,03e00008 +patch=0,EE,001aa614,word,24020000 +//Language Modifier (sceScfGetLanguage) +patch=0,EE,00445ce4,word,24020001 // english +//patch=0,EE,00445ce4,word,24020004 // deutsch +//fix "SleepThread vs. RTFSSIOP.IRX" +patch=0,EE,001b3208,word,00000000 \ No newline at end of file diff --git a/bin/patches/D08648B6.pnach b/bin/patches/D08648B6.pnach new file mode 100644 index 0000000..dd70819 --- /dev/null +++ b/bin/patches/D08648B6.pnach @@ -0,0 +1,3 @@ +gametitle=Robocop [SLES 51374] (E) +//Skip Videos +patch=0,EE,002ebf70,word,24020001 \ No newline at end of file diff --git a/bin/patches/D0E17D26.pnach b/bin/patches/D0E17D26.pnach new file mode 100644 index 0000000..054c61e --- /dev/null +++ b/bin/patches/D0E17D26.pnach @@ -0,0 +1,4 @@ +gametitle=rtype final japan +comment= +//Skip Videos ("sceMpegIsEnd") +patch=0,EE,00116b88,word,24020001 \ No newline at end of file diff --git a/bin/patches/D1ACD489.pnach b/bin/patches/D1ACD489.pnach new file mode 100644 index 0000000..f571d8e --- /dev/null +++ b/bin/patches/D1ACD489.pnach @@ -0,0 +1,5 @@ +gametitle=Syberia [SLES 51393] (E) +//Skip Videos +// patch=0,EE,0013E608,word,24020001 +//skip video "INTRO_MICROIDS.BIK" +// patch=0,EE,00297780,word,00000000 \ No newline at end of file diff --git a/bin/patches/D4781770.pnach b/bin/patches/D4781770.pnach new file mode 100644 index 0000000..349fdae --- /dev/null +++ b/bin/patches/D4781770.pnach @@ -0,0 +1,6 @@ +gametitle=Donald Duck Phantomias Platyrhynchos Kineticus [SLES 50773] (E) +comment=patches by Nachbrenner +//Skip Videos +// patch=0,EE,00108ef0,word,24020001 // (sceMpegIsEnd) +//fix inf. loop on video playback +patch=0,EE,002d8b94,word,00000000 \ No newline at end of file diff --git a/bin/patches/D48A92E1.pnach b/bin/patches/D48A92E1.pnach new file mode 100644 index 0000000..18b0cf3 --- /dev/null +++ b/bin/patches/D48A92E1.pnach @@ -0,0 +1,10 @@ +gametitle=Lotus Challenge [SLES 50230] (E) +comment=patches by nachbrenner +//skip Videos +//patch=0,EE,001cc5dc,word,00000000 +//recheck_wheel_connection__10cPauseMenuFv +patch=0,EE,001fef50,word,03e00008 +patch=0,EE,001fef54,word,00000000 +//getClosestPoint__FP11sGameSplineP8sVector4PiPScPi +patch=0,EE,00198d40,word,03e00008 +patch=0,EE,00198d44,word,00000000 \ No newline at end of file diff --git a/bin/patches/D4FB6049.pnach b/bin/patches/D4FB6049.pnach new file mode 100644 index 0000000..ecbe60f --- /dev/null +++ b/bin/patches/D4FB6049.pnach @@ -0,0 +1,3 @@ +gametitle=Pryzm - Chapter One: The Dark Unicorn PAL +//Skip Videos +patch=0,EE,0036aa60,word,24020001 \ No newline at end of file diff --git a/bin/patches/D79F697A.pnach b/bin/patches/D79F697A.pnach new file mode 100644 index 0000000..d34434a --- /dev/null +++ b/bin/patches/D79F697A.pnach @@ -0,0 +1,4 @@ +gametitle=Capcom VS. SNK 2 [PBPX 95201] (J) [D79F697A] +comment= +//Fix for PCSX2 VM Build Speed Issue +fastmemory \ No newline at end of file diff --git a/bin/patches/DAC14B26.pnach b/bin/patches/DAC14B26.pnach new file mode 100644 index 0000000..7b3786a --- /dev/null +++ b/bin/patches/DAC14B26.pnach @@ -0,0 +1,7 @@ +gametitle=SWAT - Global Strike Team Germany/Australia [SLES 52097] (E) +comment=patches by nachbrenner +//multi-ELF fix / skip videos +patch=0,EE,004721B4,word,00100100 +patch=0,EE,004738C4,word,00100100 +//Enable Gore +patch=0,EE,00274AAC,word,24040001 \ No newline at end of file diff --git a/bin/patches/DB719F5C.pnach b/bin/patches/DB719F5C.pnach new file mode 100644 index 0000000..3f1c3ff --- /dev/null +++ b/bin/patches/DB719F5C.pnach @@ -0,0 +1,7 @@ +gametitle=Gumball 3000 [SLES 50984] (E) +comment=patches by Nachbrenner +//skip FMV +// patch=0,EE,00209c00,word,03e00008 +// patch=0,EE,00209c04,word,00000000 +//go ingame w/o 3D +//patch=0,EE,00167da0,word,00000000 \ No newline at end of file diff --git a/bin/patches/DC85FC8F.pnach b/bin/patches/DC85FC8F.pnach new file mode 100644 index 0000000..bc4c173 --- /dev/null +++ b/bin/patches/DC85FC8F.pnach @@ -0,0 +1,4 @@ +gametitle=Worms 4 - Mayhem [SLES 53096] (E) [DC85FC8F] +comment=Patch by CKemu +//Skip SceMpegIsEnd +patch=0,EE,00520d40,word,24020001 \ No newline at end of file diff --git a/bin/patches/DCC4EEEA.pnach b/bin/patches/DCC4EEEA.pnach new file mode 100644 index 0000000..b6d0b32 --- /dev/null +++ b/bin/patches/DCC4EEEA.pnach @@ -0,0 +1,10 @@ +gametitle=Primal [SCES 51135] (E) +comment=patches by Nachbrenner +//Skip Videos +patch=0,EE,003ec7d4,word,00000000 +patch=0,EE,003ec4e0,word,00000000 +//Skip custom IPU routine +patch=0,EE,003c44ac,word,00000000 +patch=0,EE,003c4568,word,00000000 +//fix VU wm 25.06.06 +patch=0,EE,00391efc,word,00000000 \ No newline at end of file diff --git a/bin/patches/DDA2FA6A.pnach b/bin/patches/DDA2FA6A.pnach new file mode 100644 index 0000000..04e525e --- /dev/null +++ b/bin/patches/DDA2FA6A.pnach @@ -0,0 +1,4 @@ +gametitle=Rayman M [SLES 50457] (E) [DDA2FA6A] +comment=Patch by CKemu +//Kill '002FA6A0 1060FFFA: beq v1, zero, 0x002FA68C' (IPU) +patch=0,EE,002FA6A0,word,00000000 \ No newline at end of file diff --git a/bin/patches/E0127F2D.pnach b/bin/patches/E0127F2D.pnach new file mode 100644 index 0000000..a0549a5 --- /dev/null +++ b/bin/patches/E0127F2D.pnach @@ -0,0 +1,5 @@ +gametitle=Flatout +comment=Skip Videos sceMpegIsEnd +//patch by refraction +//Skip Videos +patch=0,EE,002b2490,word,24020001 \ No newline at end of file diff --git a/bin/patches/E0426FC6.pnach b/bin/patches/E0426FC6.pnach new file mode 100644 index 0000000..4610a47 --- /dev/null +++ b/bin/patches/E0426FC6.pnach @@ -0,0 +1,8 @@ +gametitle=Okage Shadow King [SCUS 97129](U) +comment= patches by Nachbrenner +// kill menu 3D (obsolete) +//patch=0,EE,00100fb8,word,24030000 +//LP=99 +patch=1,EE,005c1be0,word,00000063 +//Lots of Money +patch=1,EE,005c1b6c,word,07F819A0 \ No newline at end of file diff --git a/bin/patches/E0DADD1A.pnach b/bin/patches/E0DADD1A.pnach new file mode 100644 index 0000000..c1ad2d8 --- /dev/null +++ b/bin/patches/E0DADD1A.pnach @@ -0,0 +1,5 @@ + +gametitle=ESPN NBA 2night +comment=Skips Video by Rudy_x (sceMpegIsEnd) +//Skip Videos +patch=0,EE,00129c60,word,24020001 diff --git a/bin/patches/E138094A.pnach b/bin/patches/E138094A.pnach new file mode 100644 index 0000000..383f714 --- /dev/null +++ b/bin/patches/E138094A.pnach @@ -0,0 +1,7 @@ +gametitle=F1 Championship Season 2000 [SLUS 20103] (U) +comment=patches by nachbrenner +//Skip Intro Videos +patch=0,EE,00221a14,word,00000000 +//Skip All Videos +patch=0,EE,00241bc0,word,03E00008 +patch=0,EE,00241bc4,word,00000000 \ No newline at end of file diff --git a/bin/patches/E1C5F607.pnach b/bin/patches/E1C5F607.pnach new file mode 100644 index 0000000..1d50d09 --- /dev/null +++ b/bin/patches/E1C5F607.pnach @@ -0,0 +1,6 @@ +gametitle= Pirates of the Caribbean +comment=by Refraction +//"Data/Movies/%s" +patch=0,EE,0031ed84,word,00000000 +//"Data/Movies/%s/%s" +patch=0,EE,0031edac,word,00000000 diff --git a/bin/patches/E2F1DB6B.pnach b/bin/patches/E2F1DB6B.pnach new file mode 100644 index 0000000..7c1ad23 --- /dev/null +++ b/bin/patches/E2F1DB6B.pnach @@ -0,0 +1,6 @@ +gametitle=GT Racers [SLES 52602] (E) +comment=patches by nachbrenner +//Skip INTRO.PSS +patch=0,EE,00160a2c,word,00000000 +//fix "sound end command" +patch=0,EE,00167f14,word,00000000 \ No newline at end of file diff --git a/bin/patches/E4A275B2.pnach b/bin/patches/E4A275B2.pnach new file mode 100644 index 0000000..ac9dfe5 --- /dev/null +++ b/bin/patches/E4A275B2.pnach @@ -0,0 +1,4 @@ +gametitle=Glass rose (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,0010c1c0,word,24020001 diff --git a/bin/patches/E677B8F1.pnach b/bin/patches/E677B8F1.pnach new file mode 100644 index 0000000..7a4406b --- /dev/null +++ b/bin/patches/E677B8F1.pnach @@ -0,0 +1,7 @@ +gametitle=Pirates - The Legend Of Black Cat [SLES 50680] (E) +comment= patches by Nachbrenner +//skip MPC videos +//patch=0,EE,00101504,word,24020000 // intro videos +//patch=0,EE,00100aa4,word,10000013 // amulett video +//fix IPU Wait Time Out +//patch=0,EE,001a7854,word,00000000 \ No newline at end of file diff --git a/bin/patches/E7A35274.pnach b/bin/patches/E7A35274.pnach new file mode 100644 index 0000000..7c214b0 --- /dev/null +++ b/bin/patches/E7A35274.pnach @@ -0,0 +1,4 @@ +gametitle=WE7 +comment= patch by Prafull +//skip movie "WE7_OP" +patch=0,EE,012ba4a0,word,00000000 \ No newline at end of file diff --git a/bin/patches/E906EA37.pnach b/bin/patches/E906EA37.pnach new file mode 100644 index 0000000..097dfd2 --- /dev/null +++ b/bin/patches/E906EA37.pnach @@ -0,0 +1,7 @@ +gametitle=Gran Turismo 4 First Preview [PCPX 96649] (J) +comment=patches by mdr61 +//Timelimit counter stop +patch=0,EE,002EF740,word,00000000 +//Pause counter stop +patch=0,EE,002C7394,word,00000000 +patch=0,EE,002F1F40,word,00000000 \ No newline at end of file diff --git a/bin/patches/EAD76247.pnach b/bin/patches/EAD76247.pnach new file mode 100644 index 0000000..28d8035 --- /dev/null +++ b/bin/patches/EAD76247.pnach @@ -0,0 +1,19 @@ +gametitle= Transformers [SLES 52388] (E) +comment=patches by Nachbrenner +//skip loops: DMA1 vs. VIF1_FBRST vs. mfc0 v0, Count +patch=0,EE,0025d660,word,00000000 +patch=0,EE,0025d7bc,word,00000000 +patch=0,EE,0025d75c,word,00000000 +//skip loop at "warp gate animation" (cop2 BC2T called) +patch=0,EE,0026eee8,word,00000000 +// +//skip FMV (for blockdump) +patch=0,EE,00134070,word,24020001 +patch=0,EE,0034d630,word,00000000 +//skip sound streaming partially (for blockdump) +patch=0,EE,002e75c0,word,03e00008 +patch=0,EE,002e75c4,word,00000000 +patch=0,EE,00281780,word,03e00008 +patch=0,EE,00281784,word,00000000 +patch=0,EE,001f05f8,word,00000000 +patch=1,EE,008F9AC0,word,00000000 \ No newline at end of file diff --git a/bin/patches/EADE437E.pnach b/bin/patches/EADE437E.pnach new file mode 100644 index 0000000..8f339ed --- /dev/null +++ b/bin/patches/EADE437E.pnach @@ -0,0 +1,4 @@ +//fix inf. $GP loop +//patch=0,EE,00165068,word,24020000 +//fix GS_IMR crash = no 3D gfx +//patch=0,EE,00174360,word,3403ff00 \ No newline at end of file diff --git a/bin/patches/EDD7E0FF.pnach b/bin/patches/EDD7E0FF.pnach new file mode 100644 index 0000000..a300789 --- /dev/null +++ b/bin/patches/EDD7E0FF.pnach @@ -0,0 +1,4 @@ +gametitle=F1 Racing Championship DE/FR [SLES 50046] (E) +comment= patches by Nachbrenner +//Skip Videos +patch=0,EE,0024ddc0,word,24020001 \ No newline at end of file diff --git a/bin/patches/EE838B5C.pnach b/bin/patches/EE838B5C.pnach new file mode 100644 index 0000000..c16a57f --- /dev/null +++ b/bin/patches/EE838B5C.pnach @@ -0,0 +1,7 @@ +gametitle= Boku to mao (aka Okage Shadow King) [SCPS 11008] (J) +comment= patches by Nachbrenner +// ee838b5c.pnach +//Skip OP.PSS +patch=0,EE,001d6258,word,24020001 +// Money=9999 +patch=0,EE,00124bf4,word,2403270f \ No newline at end of file diff --git a/bin/patches/EEC3B310.pnach b/bin/patches/EEC3B310.pnach new file mode 100644 index 0000000..7248440 --- /dev/null +++ b/bin/patches/EEC3B310.pnach @@ -0,0 +1,9 @@ +gametitle=Shin Sangoku Musou 2 [SLPM 65053] (J) +comment=patches by nachbrenner +//Skip Videos +patch=0,EE,0019d360,word,24020001 +//Skip Intro +patch=0,EE,00160ac0,word,03E00008 +patch=0,EE,00160ac4,word,00000000 +//GS_CSR fix +patch=0,EE,0017647c,word,34840001 diff --git a/bin/patches/EF5B6AAD.pnach b/bin/patches/EF5B6AAD.pnach new file mode 100644 index 0000000..dea85d3 --- /dev/null +++ b/bin/patches/EF5B6AAD.pnach @@ -0,0 +1,4 @@ +gametitle= Graffiti Kingdom [SLUS 21136] (U) +comment= Video Skip by Refraction +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00108590,word,24020001 \ No newline at end of file diff --git a/bin/patches/EF9E43EF.pnach b/bin/patches/EF9E43EF.pnach new file mode 100644 index 0000000..0c266c0 --- /dev/null +++ b/bin/patches/EF9E43EF.pnach @@ -0,0 +1,5 @@ +gametitle= Ys: Ark Of Napishtim [SLUS 20980] (U) +comment=Skips Videos +//patches by Refraction +//Skip Videos +patch=0,EE,00224620,word,00000000 \ No newline at end of file diff --git a/bin/patches/F1370E83.pnach b/bin/patches/F1370E83.pnach new file mode 100644 index 0000000..9c02d65 --- /dev/null +++ b/bin/patches/F1370E83.pnach @@ -0,0 +1,4 @@ +gametitle=Enter the matrix +comment=Skips Video (sceMpegIsEnd)/bored +//Skip Videos +patch=0,EE,003d07c0,word,24020001 \ No newline at end of file diff --git a/bin/patches/F22CDDAF.pnach b/bin/patches/F22CDDAF.pnach new file mode 100644 index 0000000..a11dc4d --- /dev/null +++ b/bin/patches/F22CDDAF.pnach @@ -0,0 +1,4 @@ +gametitle= Gradius 3 & 4 [SLUS 20040] (U) +comment= +//ZeroGS Patch - GAME_INTERLACE2X +zerogs=00000004 \ No newline at end of file diff --git a/bin/patches/F4992CC1.pnach b/bin/patches/F4992CC1.pnach new file mode 100644 index 0000000..dc79ad2 --- /dev/null +++ b/bin/patches/F4992CC1.pnach @@ -0,0 +1,4 @@ +gametitle=switch (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00108ce8,word,24020001 \ No newline at end of file diff --git a/bin/patches/F52FB2BE.pnach b/bin/patches/F52FB2BE.pnach new file mode 100644 index 0000000..1cf249e --- /dev/null +++ b/bin/patches/F52FB2BE.pnach @@ -0,0 +1,4 @@ +gametitle=Kingdom Hearts [SCES 50967] (E) +comment= +//ZeroGS Patch - GAME_QUICKRESOLVE1 +zerogs=00000400 \ No newline at end of file diff --git a/bin/patches/F56C7948.pnach b/bin/patches/F56C7948.pnach new file mode 100644 index 0000000..830b3ec --- /dev/null +++ b/bin/patches/F56C7948.pnach @@ -0,0 +1,4 @@ +gametitle=heavy metal thunder (J) +comment= patch by parotaku +//Skip Videos (sceMpegIsEnd) +patch=0,EE,00108890,word,24020001 diff --git a/bin/patches/F5C7B45F.pnach b/bin/patches/F5C7B45F.pnach new file mode 100644 index 0000000..7bff741 --- /dev/null +++ b/bin/patches/F5C7B45F.pnach @@ -0,0 +1,4 @@ +gametitle=Need For Speed Underground 2 +comment=Video Skip by Refraction +//Skip videos +patch=0,EE,00293538,word,00000000 \ No newline at end of file diff --git a/bin/patches/F6DC728D.pnach b/bin/patches/F6DC728D.pnach new file mode 100644 index 0000000..5241c62 --- /dev/null +++ b/bin/patches/F6DC728D.pnach @@ -0,0 +1,4 @@ +gametitle= Kingdom Hearts [SCES 50968] (F) +comment= +//ZeroGS Patch - GAME_QUICKRESOLVE1 +zerogs=00000400 \ No newline at end of file diff --git a/bin/patches/F758234F.pnach b/bin/patches/F758234F.pnach new file mode 100644 index 0000000..a791dff --- /dev/null +++ b/bin/patches/F758234F.pnach @@ -0,0 +1,7 @@ +//skip BGM (for blockdump) +patch=0,EE,002cc1f0,word,03e00008 +patch=0,EE,002cc1f4,word,00000000 +patch=0,EE,002cc610,word,03e00008 +patch=0,EE,002cc614,word,00000000 +patch=0,EE,002cc430,word,03e00008 +patch=0,EE,002cc434,word,00000000 \ No newline at end of file diff --git a/bin/patches/F9E575D0.pnach b/bin/patches/F9E575D0.pnach new file mode 100644 index 0000000..54c3edc --- /dev/null +++ b/bin/patches/F9E575D0.pnach @@ -0,0 +1,4 @@ +gametitle=Die Hard - Vendetta [SLES 51348] (E) +comment= patches by Nachbrenner +//Skip Videos +patch=0,EE,002570FC,word,00000000 \ No newline at end of file diff --git a/bin/patches/FAC64195.pnach b/bin/patches/FAC64195.pnach new file mode 100644 index 0000000..19cd26f --- /dev/null +++ b/bin/patches/FAC64195.pnach @@ -0,0 +1,3 @@ +gametitle=Dead To Rights [SLES 51581] (E) +//Skip Movies +// patch=0,EE,002201a0,word,24020001 \ No newline at end of file diff --git a/bin/patches/FB0E6D72.pnach b/bin/patches/FB0E6D72.pnach new file mode 100644 index 0000000..600a838 --- /dev/null +++ b/bin/patches/FB0E6D72.pnach @@ -0,0 +1,6 @@ +gametitle=God Of War [SCES 53133] (E) +comment=patches by Nachbrenner +//D_STAT fix for Kosmos 0.95.7+ +patch=0,EE,0026dce8,word,00000000 +//crash fix ingame (breaks hero's legs) +patch=0,EE,00111604,word,24060000 \ No newline at end of file diff --git a/bin/patches/FC618D82.pnach b/bin/patches/FC618D82.pnach new file mode 100644 index 0000000..feec7d2 --- /dev/null +++ b/bin/patches/FC618D82.pnach @@ -0,0 +1,8 @@ +gametitle=Energy Airforce [SLPM 65177] (J) +comment=patches by Nachbrenner +//Skip Videos +//patch=0,EE,00109f48,word,24020001 +//Lots of fuel +patch=0,EE,002ef328,word,47110000 +//Infinite fuel +patch=0,EE,00195964,word,00000000 \ No newline at end of file diff --git a/bin/patches/FEA030CB.pnach b/bin/patches/FEA030CB.pnach new file mode 100644 index 0000000..70dc28e --- /dev/null +++ b/bin/patches/FEA030CB.pnach @@ -0,0 +1,23 @@ +gametitle=Le Mans 24 Hours (24 Heures Du Mans) [SLES 50131] (E) +comment=patches by Nachbrenner +//Skip Video Mode Menu +patch=0,EE,00248238,word,24020000 +//Skip Videos +patch=0,EE,001152c8,word,24020001 +//g_showOnScreenRenderStats (debug mode) +//patch=0,EE,0024875c,word,24020001 +//RenderFrameRateIndicator__Fv +//patch=0,EE,0033d35c,word,00000000 +//g_ps2RenderTestPattern +//patch=1,EE,004123d4,word,00000001 +//Boot Language Modifier (use only one of these) +//English +patch=0,EE,001fe060,word,24020001 +//Francais +//patch=0,EE,001fe060,word,24020002 +//Espanol +//patch=0,EE,001fe060,word,24020003 +//Deutsch +//patch=0,EE,001fe060,word,24020004 +//Italiano +//patch=0,EE,001fe060,word,24020005 \ No newline at end of file diff --git a/bin/patches/FF920E90.pnach b/bin/patches/FF920E90.pnach new file mode 100644 index 0000000..ac5e9e7 --- /dev/null +++ b/bin/patches/FF920E90.pnach @@ -0,0 +1,8 @@ +gametitle=Pro Rally 2002 [SLES 50637] (E) +comment= patches by nachbrenner +//Skip Videos (sceMpegIsEnd) +//patch=0,EE,0010cbd0,word,24020001 +//Skip sceIpuSync +//patch=1,EE,0010e174,word,00000000 +//Skip "HX sound" IOP modules (obsolete) +// patch=1,EE,002029e0,word,00000000 \ No newline at end of file diff --git a/bin/patches/default.xml b/bin/patches/default.xml new file mode 100644 index 0000000..e69de29 diff --git a/branches/pcsx2_0.9.1/CDVD.c b/branches/pcsx2_0.9.1/CDVD.c new file mode 100644 index 0000000..ab47202 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVD.c @@ -0,0 +1,1806 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PsxCommon.h" +#include "CDVDiso.h" + +cdvdStruct cdvd; + +char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"}; + +char *nCmdName[0x100]= { + "CdSync", "CdNop", "CdStandby", "CdStop", + "CdPause", "CdSeek", "CdRead", "CdReadAudio", + "DvdRead", "CdGetToc", "", "", + "CdReadKey", "", "", "", +}; + +char *sCmdName[0x100]= { + "", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands",//sceCdGetMecaconVersion, read/write console id, read renewal date + "", "sceCdTrayState", "sceCdTrayCtrl", "", + "sceCdReadClock", "sceCdWriteClock", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdSetHDMode", "", "", "sceCdPowerOff", + "", "", "sceCdReadILinkID", "sceCdWriteILinkID", /*10*/ + "sceAudioDigitalOut", "sceForbidDVD", "sceAutoAdjustCtrl", "sceCdReadModelNumber", + "sceWriteModelNumber", "sceCdForbidCD", "sceCdBootCertify", "sceCdCancelPOffRdy", + "sceCdBlueLEDCtl", "", "sceRemote2Read", "sceRemote2_7", + "sceRemote2_6", "sceCdWriteWakeUpTime", "sceCdReadWakeUpTime", "", /*20*/ + "sceCdRcBypassCtl", "", "", "", + "sceCdNoticeGameStart", "sceCdXBSPowerCtl", "sceCdXLEDCtl", "sceCdBuzzerCtl", + "", "", "", "", + "", "sceCdSetMediumRemoval", "sceCdGetMediumRemoval", "sceCdXDVRPReset", /*30*/ + "", "", "__sceCdGetOSDVER", "", + "", "", "", "", + "", "", "", "", + "sceCdOpenConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdCloseConfig", /*40*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*50*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*60*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*70*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "mechacon_auth_0x80", "mechacon_auth_0x81", "mechacon_auth_0x82", "mechacon_auth_0x83", /*80*/ + "", "", "", "", + "", "", "", "", + "sceMgWriteData", "sceMgReadData", "", "mechacon_auth_0x8F", + "sceMgWriteHeaderStart", "sceMgReadBITLength", "sceMgWriteDatainLength", "sceMgWriteDataoutLength", /*90*/ + "sceMgReadKbit", "sceMgReadKbit2", "sceMgReadKcon", "sceMgReadKcon2", + "sceMgReadIcvPs2", "", "", "", + "", "", "", "", + /*A0, no sCmds above?*/ +}; + +// NVM (eeprom) layout info +typedef struct { + u32 biosVer; // bios version that this eeprom layout is for + s32 config1; // offset of 1st config block + s32 config2; // offset of 2nd config block + s32 consoleId; // offset of console id (?) + s32 ilinkId; // offset of ilink id (ilink mac address) + s32 modelNum; // offset of ps2 model number (eg "SCPH-70002") + s32 osdver; // offset of OSDVER for PStwo +} NVMLayout; + +#define NVM_FORMAT_MAX 2 +NVMLayout nvmlayouts[NVM_FORMAT_MAX] = +{ + {0x000, 0x280, 0x300, 0x1C8, 0x1C0, 0x1A0, 0x180}, // eeproms from bios v0.00 and up + {0x160, 0x270, 0x2B0, 0x1C8, 0x1E0, 0x1B0, 0x180}, // eeproms from bios v1.60 and up +}; + + +unsigned long cdvdReadTime=0; + +#define CDVDREAD_INT(eCycle) PSX_INT(19, eCycle) + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +#define SetResultSize(size) \ + cdvd.ResultC = size; cdvd.ResultP = 0; \ + cdvd.sDataIn&=~0x40; + + +/* is cdvd.Status only for NCMDS? (linuzappz) */ +enum cdvdStatus { + CDVD_STATUS_NONE = 0x00, // not sure ;) + CDVD_STATUS_SEEK_COMPLETE = 0x0A, +}; + +static int mg_BIToffset(u8 *buffer); + +FILE *_cdvdOpenMechaVer() { + char *ptr; + int i; + char file[256]; + char Bios[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the mecha ver file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "MEC"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenMechaVer: Error creating %s", file); + exit(1); + } + fputc(0x03, fd); + fputc(0x06, fd); + fputc(0x02, fd); + fputc(0x00, fd); + } + return fd; +} +s32 cdvdGetMechaVer(u8* ver) +{ + FILE* fd = _cdvdOpenMechaVer(); + if (fd == NULL) return 1; + fseek(fd, 0, SEEK_SET); + fread(ver, 1, 4, fd); + fclose(fd); + return 0; +} + +FILE *_cdvdOpenNVM() { + char *ptr; + int i; + char Bios[256]; + char file[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the nvm file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "NVM"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenNVM: Error creating %s", file); + exit(1); + } + for (i=0; i<1024; i++) fputc(0, fd); + } + return fd; +} + +// +// the following 'cdvd' functions all return 0 if successful +// + +s32 cdvdReadNVM(u8 *dst, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fread(dst, 1, bytes, fd); + fclose(fd); + return 0; +} +s32 cdvdWriteNVM(const u8 *src, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fwrite(src, 1, bytes, fd); + fclose(fd); + return 0; +} + +#define GET_NVM_DATA(buff, offset, size, fmtOffset) getNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) +#define SET_NVM_DATA(buff, offset, size, fmtOffset) setNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) + +s32 getNvmData(u8* buffer, s32 offset, s32 size, u32 biosVersion, s32 fmtOffset) +{ + // find the correct bios version + NVMLayout* nvmLayout = NULL; + s32 nvmIdx; + for(nvmIdx=0; nvmIdx= cdvd.CNumBlocks) + return 1; + else if(cdvd.CBlockIndex >= 4) + { + memcpy(config, 0, 16); + return 0; + } + + // get config data + if(cdvd.COffset == 0) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); + else + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); +} +s32 cdvdWriteConfig(const u8* config) +{ + // make sure its in write mode + if(cdvd.CReadWrite != 1) + return 1; + // check if block index is in bounds + else if(cdvd.CBlockIndex >= cdvd.CNumBlocks) + return 1; + else if(cdvd.CBlockIndex >= 4) + return 0; + + // get config data + if(cdvd.COffset == 0) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); + else + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); +} + + +void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { + char str[256]; + int numbers; + int letters; + unsigned int key_0_3; + unsigned char key_4; + unsigned char key_14; + char exeName[12]; + + // get main elf name + GetPS2ElfName(str); + sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); + SysPrintf("exeName = %s\n",exeName); + + // convert the number characters to a real 32bit number + numbers = ((((exeName[5] - '0'))*10000) + + (((exeName[ 6] - '0'))*1000) + + (((exeName[ 7] - '0'))*100) + + (((exeName[ 9] - '0'))*10) + + (((exeName[10] - '0'))*1) ); + + // combine the lower 7 bits of each char + // to make the 4 letters fit into a single u32 + letters = (int)((exeName[3]&0x7F)<< 0) | + (int)((exeName[2]&0x7F)<< 7) | + (int)((exeName[1]&0x7F)<<14) | + (int)((exeName[0]&0x7F)<<21); + + // calculate magic numbers + key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 + key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07 + key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03 + + // clear key values + memset(key, 0, 16); + + // store key values + key[ 0] = (key_0_3&0x000000FF)>> 0; + key[ 1] = (key_0_3&0x0000FF00)>> 8; + key[ 2] = (key_0_3&0x00FF0000)>>16; + key[ 3] = (key_0_3&0xFF000000)>>24; + key[ 4] = key_4; + + if(arg2 == 75) + { + key[14] = key_14; + key[15] = 0x05; + } + else if(arg2 == 3075) + { + key[15] = 0x01; + } + else if(arg2 == 4246) + { + // 0x0001F2F707 = sector 0x0001F2F7 dec 0x07 + key[ 0] = 0x07; + key[ 1] = 0xF7; + key[ 2] = 0xF2; + key[ 3] = 0x01; + key[ 4] = 0x00; + key[15] = 0x01; + } + else + { + key[15] = 0x01; + } + + SysPrintf("CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X\n",cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15]); +} + +s32 cdvdGetToc(void* toc) { + s32 ret = CDVDgetTOC(toc); + if(ret == -1) ret = 0x80; + return ret; +/* + cdvdTN diskInfo; + cdvdTD trackInfo; + u8 _time[3]; + u32 type; + int i, err; + + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + type = CDVDgetDiskType(); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + if (type == CDVD_TYPE_CDDA) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x01; + } else + if (type == CDVD_TYPE_PS2DVD) { + if (trackInfo.lsn >= (2048*1024)) { // dual sided + PSXMu8(HW_DMA3_MADR+ 0) = 0x24; + } else { + PSXMu8(HW_DMA3_MADR+ 0) = 0x04; + } + } else + if (type == CDVD_TYPE_PS2CD) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x41; + } + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x04) { + PSXMu8(HW_DMA3_MADR+ 1) = 0x02; + PSXMu8(HW_DMA3_MADR+ 2) = 0xF2; + PSXMu8(HW_DMA3_MADR+ 3) = 0x00; + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x20) { + PSXMu8(HW_DMA3_MADR+ 4) = 0x41; + PSXMu8(HW_DMA3_MADR+ 5) = 0x95; + } else { + PSXMu8(HW_DMA3_MADR+ 4) = 0x86; + PSXMu8(HW_DMA3_MADR+ 5) = 0x72; + } + PSXMu8(HW_DMA3_MADR+ 6) = 0x00; + PSXMu8(HW_DMA3_MADR+ 7) = 0x00; + PSXMu8(HW_DMA3_MADR+ 8) = 0x00; + PSXMu8(HW_DMA3_MADR+ 9) = 0x00; + PSXMu8(HW_DMA3_MADR+10) = 0x00; + PSXMu8(HW_DMA3_MADR+11) = 0x00; + + PSXMu8(HW_DMA3_MADR+12) = 0x00; + PSXMu8(HW_DMA3_MADR+13) = 0x00; + PSXMu8(HW_DMA3_MADR+14) = 0x00; + PSXMu8(HW_DMA3_MADR+15) = 0x00; + + PSXMu8(HW_DMA3_MADR+16) = 0x00; + PSXMu8(HW_DMA3_MADR+17) = 0x03; + PSXMu8(HW_DMA3_MADR+18) = 0x00; + PSXMu8(HW_DMA3_MADR+19) = 0x00; + + } else { + PSXMu8(HW_DMA3_MADR+ 1) = 0x00; + PSXMu8(HW_DMA3_MADR+ 2) = 0xA0; + PSXMu8(HW_DMA3_MADR+ 7) = itob(diskInfo.strack);//Number of FirstTrack + + PSXMu8(HW_DMA3_MADR+12) = 0xA1; + PSXMu8(HW_DMA3_MADR+17) = itob(diskInfo.etrack);//Number of LastTrack + + PSXMu8(HW_DMA3_MADR+22) = 0xA2;//DiskLength + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+27) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+28) = itob(_time[1]); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) { + err=CDVDgetTD(i, &trackInfo); + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+i*10+30) = trackInfo.type; + PSXMu8(HW_DMA3_MADR+i*10+32) = err == -1 ? 0 : itob(i); //number + PSXMu8(HW_DMA3_MADR+i*10+37) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+i*10+38) = itob(_time[1]); + PSXMu8(HW_DMA3_MADR+i*10+39) = itob(_time[0]); + } + } +*/ +} + +s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq) +{ + s32 ret = CDVDreadSubQ(lsn, subq); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayOpen() +{ + s32 ret = CDVDctrlTrayOpen(); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayClose() +{ + s32 ret = CDVDctrlTrayClose(); + if(ret == -1) ret = 0x80; + return ret; +} + +// Modified by (efp) - 16/01/2006 +// checks if tray was opened since last call to this func +s32 cdvdGetTrayStatus() +{ + s32 ret = CDVDgetTrayStatus(); + // get current tray state + if (cdCaseopen) return(CDVD_TRAY_OPEN); + + + if (ret == -1) return(CDVD_TRAY_CLOSE); + return(ret); +} +// Note: Is tray status being kept as a var here somewhere? +// cdvdNewDiskCB() can update it's status as well... + +// Modified by (efp) - 16/01/2006 +s32 cdvdGetDiskType() { + // defs 0.9.0 + if(CDVDnewDiskCB) return(cdvd.Type); + + // defs.0.8.1 + if(cdvdGetTrayStatus() == CDVD_TRAY_OPEN) return(CDVD_TYPE_NODISC); + // Note: Hmmm. Need to modify cdvd.Type as well? + // or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway. + + cdvd.Type = CDVDgetDiskType(); + if (cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if (GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? + return(cdvd.Type); +} // END cdvdGetDiskType() + + +// check whether disc is single or dual layer +// if its dual layer, check what the disctype is and what sector number +// layer1 starts at +// +// args: gets value for dvd type (0=single layer, 1=ptp, 2=otp) +// gets value for start lsn of layer1 +// returns: 1 if on dual layer disc +// 0 if not on dual layer disc +s32 cdvdReadDvdDualInfo(s32* dualType, u32* layer1Start) +{ + u8 toc[2064]; + *dualType = 0; + *layer1Start = 0; + + // if error getting toc, settle for single layer disc ;) + if(cdvdGetToc(toc)) + return 0; + if(toc[14] & 0x60) + { + if(toc[14] & 0x10) + { + // otp dvd + *dualType = 2; + *layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1; + } + else + { + // ptp dvd + *dualType = 1; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + } + else + { + // single layer dvd + *dualType = 0; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + + return 1; +} + + +void cdvdReset() { + memset(&cdvd, 0, sizeof(cdvd)); + cdvd.sDataIn = 0x40; + cdvd.Ready = 0x4e; + cdCaseopen = 0; + cdvd.Speed = 4; + cdvd.BlockSize = 2064; + cdvdReadTimeRcnt(0); +} +void cdvdReadTimeRcnt(int mode){ // Mode 0 is DVD, Mode 1 is CD + int readsize = 0; // 1 Sector size + int amount = 0; // Total bytes transfered at 1x speed + //if(mode) amount = 153600; + //else + amount = 1280000; + + readsize = amount / cdvd.BlockSize; // Time taken for 1 sector to be read + cdvdReadTime = ((PSXCLK / readsize) / BIAS) / cdvd.Speed; +} + +int cdvdFreeze(gzFile f, int Mode) { + gzfreeze(&cdvd, sizeof(cdvd)); + if (Mode == FREEZE_LOAD) { + if (cdvd.Reading) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + } + } + + return 0; +} + +int cdvdInterrupt() { + return 1; +} + +// Modified by (efp) - 16/01/2006 +void cdvdNewDiskCB() { + cdvd.Type = CDVDgetDiskType(); + if(cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if(GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? +} // END cdvdNewDiskCB() + +void mechaDecryptBytes(unsigned char* buffer, int size) +{ + int i; + + int shiftAmount = (cdvd.decSet>>4) & 7; + int doXor = (cdvd.decSet) & 1; + int doShift = (cdvd.decSet) & 2; + unsigned char key = cdvd.Key[4]; + + for(i=0; i>shiftAmount) | (buffer[i]<<(8-shiftAmount)); + } +} + +int cdvdReadSector() { + s32 bcr; + +#ifdef CDR_LOG + CDR_LOG("SECTOR %d (BCR %x;%x)\n", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16); +#endif + bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4; + if (bcr < cdvd.BlockSize) { + //SysPrintf("*PCSX2*: cdvdReadSector: bcr < cdvd.BlockSize; %x < %x\n", bcr, cdvd.BlockSize); + if (HW_DMA3_CHCR & 0x01000000) { + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + } + return -1; + } + + // if raw dvd sector 'fill in the blanks' + if (cdvd.BlockSize == 2064) { + // get info on dvd type and layer1 start + u32 layer1Start; + s32 dualType; + s32 layerNum; + u32 lsn = cdvd.Sector; + cdvdReadDvdDualInfo(&dualType, &layer1Start); + + if((dualType == 1) && (lsn >= layer1Start)) { + // dual layer ptp disc + layerNum = 1; + lsn = lsn-layer1Start + 0x30000; + } else if((dualType == 2) && (lsn >= layer1Start)) { + // dual layer otp disc + layerNum = 1; + lsn = ~(layer1Start+0x30000 - 1); + } else { + // single layer disc + // or on first layer of dual layer disc + layerNum = 0; + lsn += 0x30000; + } // ENDLONGIF- Assumed the other dualType is 0. + + PSXMu8(HW_DMA3_MADR+0) = 0x20 | layerNum; + PSXMu8(HW_DMA3_MADR+1) = (u8)(lsn >> 16); + PSXMu8(HW_DMA3_MADR+2) = (u8)(lsn >> 8); + PSXMu8(HW_DMA3_MADR+3) = (u8)(lsn ); + + // sector IED (not calculated at present) + PSXMu8(HW_DMA3_MADR+4) = 0; + PSXMu8(HW_DMA3_MADR+5) = 0; + + // sector CPR_MAI (not calculated at present) + PSXMu8(HW_DMA3_MADR+ 6) = 0; + PSXMu8(HW_DMA3_MADR+ 7) = 0; + PSXMu8(HW_DMA3_MADR+ 8) = 0; + PSXMu8(HW_DMA3_MADR+ 9) = 0; + PSXMu8(HW_DMA3_MADR+10) = 0; + PSXMu8(HW_DMA3_MADR+11) = 0; + + // normal 2048 bytes of sector data + memcpy_amd(PSXM(HW_DMA3_MADR+12), cdr.pTransfer, 2048); + + // 4 bytes of edc (not calculated at present) + PSXMu8(HW_DMA3_MADR+2060) = 0; + PSXMu8(HW_DMA3_MADR+2061) = 0; + PSXMu8(HW_DMA3_MADR+2062) = 0; + PSXMu8(HW_DMA3_MADR+2063) = 0; + } else { + // normal read + memcpy_amd(PSXM(HW_DMA3_MADR), cdr.pTransfer, cdvd.BlockSize); + } + // decrypt sector's bytes + if(cdvd.decSet) + mechaDecryptBytes(PSXM(HW_DMA3_MADR), cdvd.BlockSize); + +// SysPrintf("sector %x;%x;%x\n", PSXMu8(HW_DMA3_MADR+0), PSXMu8(HW_DMA3_MADR+1), PSXMu8(HW_DMA3_MADR+2)); + + HW_DMA3_BCR_H16-= (cdvd.BlockSize / (HW_DMA3_BCR_L16*4)); + HW_DMA3_MADR+= cdvd.BlockSize; + //FreezeMMXRegs(0); + + return 0; +} + +int cdvdReadInterrupt() { + + //SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); + if (cdvd.Readed == 0) { + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + cdvd.Readed = 1; + cdvd.Status = CDVD_STATUS_SEEK_COMPLETE; + + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + if (cdvd.Reading == 1) { + if (cdvd.RErr == 0) { + cdr.pTransfer = CDVDgetBuffer(); + } else cdr.pTransfer = NULL; + if (cdr.pTransfer == NULL) { + cdvd.RetryCntP++; + SysPrintf("READ ERROR %d\n", cdvd.Sector); + if (cdvd.RetryCntP <= cdvd.RetryCnt) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + } + cdvd.Reading = 0; + } + if (cdvdReadSector() == -1) { + assert( (int)cdvdReadTime > 0 ); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + cdvd.Sector++; + + if (--cdvd.nSectors <= 0) { + psxHu32(0x1070)|= 0x4; + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + return 1; + } + + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdr.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; +} + +void cdvdVsync() { + cdvd.RTCcount++; + if (cdvd.RTCcount < 60) return; + cdvd.RTCcount = 0; + + cdvd.RTC.second++; + if (cdvd.RTC.second < 60) return; + cdvd.RTC.second = 0; + + cdvd.RTC.minute++; + if (cdvd.RTC.minute < 60) return; + cdvd.RTC.minute = 0; + + cdvd.RTC.hour++; + if (cdvd.RTC.hour < 24) return; + cdvd.RTC.hour = 0; + + cdvd.RTC.day++; + if (cdvd.RTC.day < 30) return; + cdvd.RTC.day = 0; + + cdvd.RTC.month++; + if (cdvd.RTC.month < 12) return; + cdvd.RTC.month = 0; + + cdvd.RTC.year++; +} + + +u8 cdvdRead04(void) { // NCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead04(NCMD) %x\n", cdvd.nCommand); +#endif + return cdvd.nCommand; +} + +u8 cdvdRead05(void) { // N-READY +#ifdef CDR_LOG + CDR_LOG("cdvdRead05(NReady) %x\n", cdvd.Ready); +#endif + return cdvd.Ready; +} + +u8 cdvdRead06(void) { // ERROR +#ifdef CDR_LOG + CDR_LOG("cdvdRead06(Error) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead07(void) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdRead07(Break) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead08(void) { // PWOFF +#ifdef CDR_LOG + CDR_LOG("cdvdRead08(PowerOff) %x\n", cdvd.PwOff); +#endif + return cdvd.PwOff; +} + +u8 cdvdRead0A(void) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdRead0A(Status) %x\n", cdvd.Status); +#endif + return cdvd.Status; +} + +u8 cdvdRead0B(void) { // TRAY-STATE (if tray has been opened) + u8 tray = cdvdGetTrayStatus(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0B(Tray) %x\n", tray); +#endif + return tray; +} + +u8 cdvdRead0C(void) { // CRT MINUTE +#ifdef CDR_LOG + CDR_LOG("cdvdRead0C(Min) %x\n", itob((u8)(cdvd.Sector/(60*75)))); +#endif + return itob((u8)(cdvd.Sector/(60*75))); +} + +u8 cdvdRead0D(void) { // CRT SECOND +#ifdef CDR_LOG + CDR_LOG("cdvdRead0D(Sec) %x\n", itob((u8)((cdvd.Sector/75)%60)+2)); +#endif + return itob((u8)((cdvd.Sector/75)%60)+2); +} + +u8 cdvdRead0E(void) { // CRT FRAME +#ifdef CDR_LOG + CDR_LOG("cdvdRead0E(Frame) %x\n", itob((u8)(cdvd.Sector%75))); +#endif + return itob((u8)(cdvd.Sector%75)); +} + +u8 cdvdRead0F(void) { // TYPE + u8 type = cdvdGetDiskType(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0F(Disc Type) %x\n", type); +#endif + return type; +} + +u8 cdvdRead13(void) { // UNKNOWN +#ifdef CDR_LOG + CDR_LOG("cdvdRead13(Unknown) %x\n", 4); +#endif + return 4; +} + +u8 cdvdRead15(void) { // RSV +#ifdef CDR_LOG + CDR_LOG("cdvdRead15(RSV)\n"); +#endif + return 0x01; // | 0x80 for ATAPI mode +} + +u8 cdvdRead16(void) { // SCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead16(SCMD) %x\n", cdvd.sCommand); +#endif + return cdvd.sCommand; +} + +u8 cdvdRead17(void) { // SREADY +#ifdef CDR_LOG + CDR_LOG("cdvdRead17(SReady) %x\n", cdvd.sDataIn); +#endif + return cdvd.sDataIn; +} + +u8 cdvdRead18(void) { // SDATAOUT + u8 ret=0; + + if ((cdvd.sDataIn & 0x40) == 0) { + if (cdvd.ResultP < cdvd.ResultC) { + cdvd.ResultP++; + if (cdvd.ResultP >= cdvd.ResultC) cdvd.sDataIn|= 0x40; + ret = cdvd.Result[cdvd.ResultP-1]; + } + } + +#ifdef CDR_LOG + CDR_LOG("cdvdRead18(SDataOut) %x (ResultC=%d, ResultP=%d)\n", ret, cdvd.ResultC, cdvd.ResultP); +#endif + + return ret; +} + +u8 cdvdRead20(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead20(Key0) %x\n", cdvd.Key[0]); +#endif + return cdvd.Key[0]; +} + +u8 cdvdRead21(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead21(Key1) %x\n", cdvd.Key[1]); +#endif + return cdvd.Key[1]; +} + +u8 cdvdRead22(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead22(Key2) %x\n", cdvd.Key[2]); +#endif + return cdvd.Key[2]; +} + +u8 cdvdRead23(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead23(Key3) %x\n", cdvd.Key[3]); +#endif + return cdvd.Key[3]; +} + +u8 cdvdRead24(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead24(Key4) %x\n", cdvd.Key[4]); +#endif + return cdvd.Key[4]; +} + +u8 cdvdRead28(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead28(Key5) %x\n", cdvd.Key[5]); +#endif + return cdvd.Key[5]; +} + +u8 cdvdRead29(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead29(Key6) %x\n", cdvd.Key[6]); +#endif + return cdvd.Key[6]; +} + +u8 cdvdRead2A(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2A(Key7) %x\n", cdvd.Key[7]); +#endif + return cdvd.Key[7]; +} + +u8 cdvdRead2B(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2B(Key8) %x\n", cdvd.Key[8]); +#endif + return cdvd.Key[8]; +} + +u8 cdvdRead2C(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2C(Key9) %x\n", cdvd.Key[9]); +#endif + return cdvd.Key[9]; +} + +u8 cdvdRead30(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead30(Key10) %x\n", cdvd.Key[10]); +#endif + return cdvd.Key[10]; +} + +u8 cdvdRead31(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead31(Key11) %x\n", cdvd.Key[11]); +#endif + return cdvd.Key[11]; +} + +u8 cdvdRead32(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead32(Key12) %x\n", cdvd.Key[12]); +#endif + return cdvd.Key[12]; +} + +u8 cdvdRead33(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead33(Key13) %x\n", cdvd.Key[13]); +#endif + return cdvd.Key[13]; +} + +u8 cdvdRead34(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead34(Key14) %x\n", cdvd.Key[14]); +#endif + return cdvd.Key[14]; +} + +u8 cdvdRead38(void) { // valid parts of key data (first and last are valid) +#ifdef CDR_LOG + CDR_LOG("cdvdRead38(KeysValid) %x\n", cdvd.Key[15]); +#endif + return cdvd.Key[15]; +} + +u8 cdvdRead39(void) { // KEY-XOR +#ifdef CDR_LOG + CDR_LOG("cdvdRead39(KeyXor) %x\n", cdvd.KeyXor); +#endif + return cdvd.KeyXor; +} + +u8 cdvdRead3A(void) { // DEC_SET +#ifdef CDR_LOG + CDR_LOG("cdvdRead3A(DecSet) %x\n", cdvd.decSet); +#endif + SysPrintf("DecSet Read: %02X\n", cdvd.decSet); + return cdvd.decSet; +} + + + +void cdvdWrite04(u8 rt) { // NCOMMAND + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)\n", nCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.nCommand = rt; + cdvd.Status = CDVD_STATUS_NONE; + switch (rt) { + case 0x00: // CdNop + case 0x01: // CdNop_ + psxHu32(0x1070)|= 0x4; + break; + + // from an emulation point of view there is not much need to do anything for these + case 0x02: // CdStandby + case 0x03: // CdStop + case 0x04: // CdPause + psxHu32(0x1070)|= 0x4; + break; + // should we change the sector location here? + case 0x05: // CdSeek + cdvd.Sector = *(int*)(cdvd.Param+0); + psxHu32(0x1070)|= 0x4; + break; + + case 0x06: // CdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; // CD + case 0x02: cdvd.Speed = 2; break; // CD + case 0x03: cdvd.Speed = 4; break; // CD + case 0x04: cdvd.Speed = 12; break; // CD + default: cdvd.Speed = 24; break; // CD + } + switch (cdvd.Param[10]) { + case 2: cdvd.ReadMode = CDVD_MODE_2340; cdvd.BlockSize = 2340; break; + case 1: cdvd.ReadMode = CDVD_MODE_2328; cdvd.BlockSize = 2328; break; + case 0: default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break; + } + if(cdvd.Speed > 4) cdvdReadTimeRcnt(1); + else cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "CdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + CDVDREAD_INT(1); + + break; + + case 0x07: // CdReadAudio + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; + case 0x02: cdvd.Speed = 2; break; + case 0x03: cdvd.Speed = 4; break; + case 0x04: cdvd.Speed = 12; break; + default: cdvd.Speed = 24; break; + } + switch (cdvd.Param[10]) { + case 1: cdvd.ReadMode = CDVD_MODE_2368; cdvd.BlockSize = 2368; break; + case 2: + case 0: cdvd.ReadMode = CDVD_MODE_2352; cdvd.BlockSize = 2352; break; + } + cdvdReadTimeRcnt(1); + SysPrintf("CdAudioRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + CDVDREAD_INT(1); + break; + + case 0x08: // DvdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + cdvd.Speed = 4; + cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2064; // Why oh why was it 2064 + cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "DvdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.Readed = 0; + CDVDREAD_INT(1); + break; + + case 0x09: // CdGetToc & cdvdman_call19 + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + cdvdGetToc(PSXM(HW_DMA3_MADR)); + psxHu32(0x1070)|= 0x4; + break; + + case 0x0C: // CdReadKey + { + unsigned char arg0 = cdvd.Param[0]; + unsigned short arg1 = cdvd.Param[1] | (cdvd.Param[2]<<8); + unsigned int arg2 = cdvd.Param[3] | (cdvd.Param[4]<<8) | (cdvd.Param[5]<<16) | (cdvd.Param[6]<<24); + SysPrintf("cdvdReadKey(%d, %d, %d)\n", arg0, arg1, arg2); + cdvdReadKey(arg0, arg1, arg2, cdvd.Key); + cdvd.KeyXor = 0x00; + psxHu32(0x1070)|= 0x4; + break; + } + default: + SysPrintf("NCMD Unknown %x\n", rt); + psxHu32(0x1070)|= 0x4; + break; + } + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite05(u8 rt) { // NDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite05(NDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite06(u8 rt) { // HOWTO +#ifdef CDR_LOG + CDR_LOG("cdvdWrite06(HowTo) %x\n", rt); +#endif + cdvd.HowTo = rt; +} + +void cdvdWrite07(u8 rt) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdWrite07(Break) %x\n", rt); +#endif + SysPrintf("*PCSX2*: CDVD BREAK %x\n" , rt); +} + +void cdvdWrite08(u8 rt) { // PWOFF +#ifdef CDR_LOG + CDR_LOG("cdvdWrite08(PowerOff) %x\n", rt); +#endif +} + +void cdvdWrite0A(u8 rt) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0A(Status) %x\n", rt); +#endif +} + +void cdvdWrite0F(u8 rt) { // TYPE +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0F(Type) %x\n", rt); +#endif +SysPrintf("*PCSX2*: CDVD TYPE %x\n", rt); +} + +void cdvdWrite14(u8 rt) { // PS1 MODE?? + u32 cycle = psxRegs.cycle; + psxReset(); + psxHu32(0x1f801450) = 0x8; + psxHu32(0x1f801078) = 1; + psxRegs.cycle = cycle; + +#ifdef PCSX2_DEVBUILD + varLog|= 0x10000000;// | 0x00400000;// | 0x1fe00000; +#endif +} + +void cdvdWrite16(u8 rt) { // SCOMMAND +// cdvdTN diskInfo; +// cdvdTD trackInfo; +// int i, lbn, type, min, sec, frm, address; + int address; + u8 tmp; + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)\n", sCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.sCommand = rt; + switch (rt) { + +// case 0x01: // GetDiscType - from cdvdman (0:1) +// SetResultSize(1); +// cdvd.Result[0] = 0; +// break; + + case 0x02: // CdReadSubQ (0:11) + SetResultSize(11); + cdvd.Result[0] = cdvdReadSubQ(cdvd.Sector, (cdvdSubQ*)&cdvd.Result[1]); + break; + + case 0x03: // Mecacon-command + if(cdvd.Param[0]==0x00) { + // get mecha version (1:4) + SetResultSize(4); + cdvdGetMechaVer(&cdvd.Result[0]); + } + else if(cdvd.Param[0]==0x44) { + // write console ID (9:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConsoleID(&cdvd.Param[1]); + } + else if(cdvd.Param[0]==0x45) { + // read console ID (1:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadConsoleID(&cdvd.Result[1]); + } + else if(cdvd.Param[0]==0xFD) { + // _sceCdReadRenewalDate (1:6) BCD + SetResultSize(6); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0x04;//year + cdvd.Result[2] = 0x12;//month + cdvd.Result[3] = 0x10;//day + cdvd.Result[4] = 0x01;//hour + cdvd.Result[5] = 0x30;//min + } else { + SetResultSize(1); + cdvd.Result[0] = 0x80; + SysPrintf("*Unknown Mecacon Command param[0]=%02X\n", cdvd.Param[0]); + } + break; + + case 0x05: // CdTrayReqState (0:1) - resets the tray open detection + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x06: // CdTrayCtrl (1:1) + SetResultSize(1); + if(cdvd.Param[0] == 0) + cdvd.Result[0] = cdvdCtrlTrayOpen(); + else + cdvd.Result[0] = cdvdCtrlTrayClose(); + break; + + case 0x08: // CdReadRTC (0:8) + SetResultSize(8); + memcpy_amd(cdvd.Result, (u8*)&cdvd.RTC, 8); + /* do not uncomment this by now, it kinda makes + things a bit more random for debugging (linuz) */ +/* + { + time_t sysTime; + struct tm* utcTime; + time(&sysTime); + utcTime = gmtime(&sysTime); + cdvd.RTC.second =itob((u8)utcTime->tm_sec); + cdvd.RTC.minute =itob((u8)utcTime->tm_min); + cdvd.RTC.hour =itob((u8)utcTime->tm_hour); // add 8 to the hours (the ps2 wants it this way) + cdvd.RTC.day =itob((u8)utcTime->tm_mday); + cdvd.RTC.month =itob((u8)utcTime->tm_mon); + cdvd.RTC.year =itob((u8)(utcTime->tm_year+100)); + cdvd.RTC.pad =0; + } +*/ + break; + + case 0x09: // sceCdWriteRTC (7:1) + SetResultSize(1); + cdvd.Result[0] = 0; + memcpy_amd((u8*)&cdvd.RTC, cdvd.Param, 7); + cdvd.RTC.pad = 0; + break; + + case 0x0A: // sceCdReadNVM (2:3) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + if (address < 512) { + SetResultSize(3); + cdvd.Result[0] = cdvdReadNVM(&cdvd.Result[1], address*2, 2); + // swap bytes around + tmp = cdvd.Result[1]; + cdvd.Result[1] = cdvd.Result[2]; + cdvd.Result[2] = tmp; + } else { + SetResultSize(1); + cdvd.Result[0] = 0xff; + } + break; + + case 0x0B: // sceCdWriteNVM (4:1) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + SetResultSize(1); + if (address < 512) { + // swap bytes around + tmp = cdvd.Param[2]; + cdvd.Param[2] = cdvd.Param[3]; + cdvd.Param[3] = tmp; + cdvd.Result[0] = cdvdWriteNVM(&cdvd.Param[2], address*2, 2); + } else { + cdvd.Result[0] = 0xff; + } + break; + +// case 0x0C: // sceCdSetHDMode (1:1) +// break; + + + case 0x0F: // sceCdPowerOff (0:1)- Call74 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x12: // sceCdReadILinkId (0:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadILinkID(&cdvd.Result[1]); + break; + + case 0x13: // sceCdWriteILinkID (8:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteILinkID(&cdvd.Param[1]); + break; + + case 0x14: // CdCtrlAudioDigitalOut (1:1) + //parameter can be 2, 0, ... + SetResultSize(1); + cdvd.Result[0] = 0; //8 is a flag; not used + break; + + case 0x15: // sceCdForbidDVDP (0:1) + //SysPrintf("sceCdForbidDVDP\n"); + SetResultSize(1); + cdvd.Result[0] = 5; + break; + + case 0x16: // AutoAdjustCtrl - from cdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x17: // CdReadModelNumber (1:9) - from xcdvdman + SetResultSize(9); + cdvd.Result[0] = cdvdReadModelNumber(&cdvd.Result[1], cdvd.Param[0]); + break; + + case 0x18: // CdWriteModelNumber (9:1) - from xcdvdman + SetResultSize(1); + cdvd.Result[0] = cdvdWriteModelNumber(&cdvd.Param[1], cdvd.Param[0]); + break; + +// case 0x19: // sceCdForbidRead (0:1) - from xcdvdman +// break; + + case 0x1A: // sceCdBootCertify (4:1) + SetResultSize(1);//on imput there are 4 bytes: 1;?10;J;C for 18000; 1;60;E;C for 39002 from ROMVER + cdvd.Result[0]=1;//i guess that means okay + break; + + case 0x1B: // sceCdCancelPOffRdy (0:1) - Call73 from Xcdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x1C: // sceCdBlueLEDCtl (1:1) - Call72 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x1D: // cdvdman_call116 (0:5) - In V10 Bios +// break; + + case 0x1E: // sceRemote2Read (0:5) - // 00 14 AA BB CC -> remote key code + SetResultSize(5); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x14; + cdvd.Result[2] = 0x00; + cdvd.Result[3] = 0x00; + cdvd.Result[4] = 0x00; + break; + +// case 0x1F: // sceRemote2_7 (2:1) - cdvdman_call117 +// break; + + case 0x20: // sceRemote2_6 (0:3) // 00 01 00 + SetResultSize(3); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x01; + cdvd.Result[2] = 0x00; + break; + +// case 0x21: // sceCdWriteWakeUpTime (8:1) +// break; + + case 0x22: // sceCdReadWakeUpTime (0:10) + SetResultSize(10); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0; + cdvd.Result[2] = 0; + cdvd.Result[3] = 0; + cdvd.Result[4] = 0; + cdvd.Result[5] = 0; + cdvd.Result[6] = 0; + cdvd.Result[7] = 0; + cdvd.Result[8] = 0; + cdvd.Result[9] = 0; + break; + + case 0x24: // sceCdRCBypassCtrl (1:1) - In V10 Bios + // FIXME: because PRId<0x23, the bit 0 of sio2 don't get updated 0xBF808284 + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x25: // cdvdman_call120 (1:1) - In V10 Bios +// break; + +// case 0x26: // cdvdman_call128 (0,3) - In V10 Bios +// break; + +// case 0x27: // cdvdman_call148 (0:13) - In V10 Bios +// break; + +// case 0x28: // cdvdman_call150 (1:1) - In V10 Bios +// break; + +// case 0x29: //sceCdNoticeGameStart (1:1) +// break; + +// case 0x2C: //sceCdXBSPowerCtl (2:2) +// break; + +// case 0x2D: //sceCdXLEDCtl (2:2) +// break; + +// case 0x2E: //sceCdBuzzerCtl (0:1) +// break; + +// case 0x2F: //cdvdman_call167 (16:1) +// break; + +// case 0x30: //cdvdman_call169 (1:9) +// break; + + case 0x31: //sceCdSetMediumRemoval (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x32: //sceCdGetMediumRemoval (0:2) + SetResultSize(2); + cdvd.Result[0] = 0; + cdvd.Result[0] = 0; + break; + +// case 0x33: //sceCdXDVRPReset (1:1) +// break; + + case 0x36: //cdvdman_call189 [__sceCdGetOSDVER - made up name] (0:15) + SetResultSize(15); + cdvd.Result[0] = cdvdReadOSDVER(&cdvd.Result[3]); + cdvd.Result[1] = 0;//0x10 + cdvd.Result[2] = 0; + cdvd.Result[11] = 0; + cdvd.Result[12] = 0; + cdvd.Result[13] = 0;//0xFF + cdvd.Result[14] = 0; + SysPrintf("OSDVer = %s\n",&cdvd.Result[3]); + break; + + case 0x3E: //[__sceCdSetOSDVER - made up name] (15:1) [Florin: hum, i was expecting 14:1] + SetResultSize(1); + cdvd.Result[0] = cdvdWriteOSDVER(&cdvd.Param[2]); + break; + + case 0x40: // CdOpenConfig (3:1) + cdvd.CReadWrite = cdvd.Param[0]; + cdvd.COffset = cdvd.Param[1]; + cdvd.CNumBlocks = cdvd.Param[2]; + cdvd.CBlockIndex= 0; + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x41: // CdReadConfig (0:16) + SetResultSize(16); + cdvdReadConfig(&cdvd.Result[0]); + break; + + case 0x42: // CdWriteConfig (16:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConfig(&cdvd.Param[0]); + break; + + case 0x43: // CdCloseConfig (0:1) + cdvd.CReadWrite = 0; + cdvd.COffset = 0; + cdvd.CNumBlocks = 0; + cdvd.CBlockIndex= 0; + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x80: // secrman: __mechacon_auth_0x80 + cdvd.mg_datatype = 0;//data + SetResultSize(1);//in:1 + cdvd.Result[0] = 0; + break; + + case 0x81: // secrman: __mechacon_auth_0x81 + cdvd.mg_datatype = 0;//data + SetResultSize(1);//in:1 + cdvd.Result[0] = 0; + break; + + case 0x82: // secrman: __mechacon_auth_0x82 + SetResultSize(1);//in:16 + cdvd.Result[0] = 0; + break; + + case 0x83: // secrman: __mechacon_auth_0x83 + SetResultSize(1);//in:8 + cdvd.Result[0] = 0; + break; + + case 0x84: // secrman: __mechacon_auth_0x84 + SetResultSize(1+8+4);//in:0 + cdvd.Result[0] = 0; + + cdvd.Result[1] = 0x21; + cdvd.Result[2] = 0xdc; + cdvd.Result[3] = 0x31; + cdvd.Result[4] = 0x96; + cdvd.Result[5] = 0xce; + cdvd.Result[6] = 0x72; + cdvd.Result[7] = 0xe0; + cdvd.Result[8] = 0xc8; + + cdvd.Result[9] = 0x69; + cdvd.Result[10] = 0xda; + cdvd.Result[11] = 0x34; + cdvd.Result[12] = 0x9b; + break; + + case 0x85: // secrman: __mechacon_auth_0x85 + SetResultSize(1+4+8);//in:0 + cdvd.Result[0] = 0; + + cdvd.Result[1] = 0xeb; + cdvd.Result[2] = 0x01; + cdvd.Result[3] = 0xc7; + cdvd.Result[4] = 0xa9; + + cdvd.Result[ 5] = 0x3f; + cdvd.Result[ 6] = 0x9c; + cdvd.Result[ 7] = 0x5b; + cdvd.Result[ 8] = 0x19; + cdvd.Result[ 9] = 0x31; + cdvd.Result[10] = 0xa0; + cdvd.Result[11] = 0xb3; + cdvd.Result[12] = 0xa3; + break; + + case 0x86: // secrman: __mechacon_auth_0x86 + SetResultSize(1);//in:16 + cdvd.Result[0] = 0; + break; + + case 0x87: // secrman: __mechacon_auth_0x87 + SetResultSize(1);//in:8 + cdvd.Result[0] = 0; + break; + + case 0x8D: // sceMgWriteData + SetResultSize(1);//in:length<=16 + if (cdvd.mg_size + cdvd.ParamC > cdvd.mg_maxsize) + cdvd.Result[0] = 0x80; + else{ + memcpy(cdvd.mg_buffer + cdvd.mg_size, cdvd.Param, cdvd.ParamC); + cdvd.mg_size += cdvd.ParamC; + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + } + break; + + case 0x8E: // sceMgReadData + SetResultSize(min(16, cdvd.mg_size)); + memcpy_amd(cdvd.Result, cdvd.mg_buffer, cdvd.ResultC); + cdvd.mg_size -= cdvd.ResultC; + memcpy_amd(cdvd.mg_buffer, cdvd.mg_buffer+cdvd.ResultC, cdvd.mg_size); + break; + + case 0x88: // secrman: __mechacon_auth_0x88 //for now it is the same; so, fall;) + case 0x8F: // secrman: __mechacon_auth_0x8F + SetResultSize(1);//in:0 + if (cdvd.mg_datatype == 1){// header data + int bit_ofs, i; + + if (cdvd.mg_maxsize != cdvd.mg_size) goto fail_pol_cal; + if (cdvd.mg_size < 0x20) goto fail_pol_cal; + if (cdvd.mg_size != *(u16*)&cdvd.mg_buffer[0x14]) goto fail_pol_cal; + SysPrintf("[MG] ELF_size=0x%X Hdr_size=0x%X unk=0x%X flags=0x%X count=%d zones=", + *(u32*)&cdvd.mg_buffer[0x10], *(u16*)&cdvd.mg_buffer[0x14], *(u16*)&cdvd.mg_buffer[0x16], + *(u16*)&cdvd.mg_buffer[0x18], *(u16*)&cdvd.mg_buffer[0x1A]); + for (i=0; i<8; i++) + if (cdvd.mg_buffer[0x1C] & (1<> 0) & 0xFF; + cdvd.Result[2] = (cdvd.mg_size >> 8) & 0xFF; + break; + + case 0x92: // sceMgWriteDatainLength + cdvd.mg_size = 0; + cdvd.mg_datatype = 0;//data (encrypted) + cdvd.mg_maxsize = cdvd.Param[0] | (((int)cdvd.Param[1])<<8); + SetResultSize(1);//in:2 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + + case 0x93: // sceMgWriteDataoutLength + SetResultSize(1);//in:2 + if (((cdvd.Param[0] | (((int)cdvd.Param[1])<<8)) == cdvd.mg_size) && (cdvd.mg_datatype == 0)){ + cdvd.mg_maxsize = 0; // don't allow any write + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + }else + cdvd.Result[0] = 0x80; + break; + + case 0x94: // sceMgReadKbit - read first half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit, 8); + break; + + case 0x95: // sceMgReadKbit2 - read second half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit+8, 8); + break; + + case 0x96: // sceMgReadKcon - read first half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon, 8); + break; + + case 0x97: // sceMgReadKcon2 - read second half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon+8, 8); + break; + + default: + // fake a 'correct' command + SysPrintf("SCMD Unknown %x\n", rt); + SetResultSize(1); //in:0 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + } + //SysPrintf("SCMD - %x\n", rt); + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite17(u8 rt) { // SDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite17(SDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite18(u8 rt) { // SDATAOUT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite18(SDataOut) %x\n", rt); +#endif +} + +void cdvdWrite3A(u8 rt) { // DEC-SET +#ifdef CDR_LOG + CDR_LOG("cdvdWrite3A(DecSet) %x\n", rt); +#endif + cdvd.decSet = rt; + SysPrintf("DecSet Write: %02X\n", cdvd.decSet); +} + +static int mg_BIToffset(u8 *buffer){ + int i, ofs = 0x20; for (i=0; i<*(u16*)&buffer[0x1A]; i++)ofs+=0x10; + if (*(u16*)&buffer[0x18] & 1)ofs+=buffer[ofs]; + if ((*(u16*)&buffer[0x18] & 0xF000)==0)ofs+=8; + return ofs + 0x20; +} diff --git a/branches/pcsx2_0.9.1/CDVD.h b/branches/pcsx2_0.9.1/CDVD.h new file mode 100644 index 0000000..60e201c --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVD.h @@ -0,0 +1,144 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#include "PsxCommon.h" + +typedef struct { + u8 status; + u8 second; + u8 minute; + u8 hour; + u8 pad; + u8 day; + u8 month; + u8 year; +} cdvdRTC; + +typedef struct { + u8 nCommand; + u8 Ready; + u8 Error; + u8 PwOff; + u8 Status; + u8 Type; + u8 sCommand; + u8 sDataIn; + u8 sDataOut; + u8 HowTo; + + u8 Param[32]; + u8 Result[32]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + + u8 CBlockIndex; + u8 COffset; + u8 CReadWrite; + u8 CNumBlocks; + + int RTCcount; + cdvdRTC RTC; + + u32 Sector; + int nSectors; + int Readed; + int Reading; + int ReadMode; + int BlockSize; + int Speed; + int RetryCnt; + int RetryCntP; + int RErr; + int SpindlCtrl; + + u8 Key[16]; + u8 KeyXor; + u8 decSet; + + u8 mg_buffer[65536]; + int mg_size; + int mg_maxsize; + int mg_datatype;//0-data(encrypted); 1-header + u8 mg_kbit[16];//last BIT key 'seen' + u8 mg_kcon[16];//last content key 'seen' +// char Unused[4096]; +} cdvdStruct; + +extern cdvdStruct cdvd; + +void cdvdReset(); +void cdvdReadTimeRcnt(); +void cdvdVsync(); +int cdvdInterrupt(); +int cdvdFreeze(gzFile f, int Mode); +int cdvdReadInterrupt(); +void cdvdNewDiskCB(); +u8 cdvdRead04(void); +u8 cdvdRead05(void); +u8 cdvdRead06(void); +u8 cdvdRead07(void); +u8 cdvdRead08(void); +u8 cdvdRead0A(void); +u8 cdvdRead0B(void); +u8 cdvdRead0C(void); +u8 cdvdRead0D(void); +u8 cdvdRead0E(void); +u8 cdvdRead0F(void); +u8 cdvdRead13(void); +u8 cdvdRead15(void); +u8 cdvdRead16(void); +u8 cdvdRead17(void); +u8 cdvdRead18(void); +u8 cdvdRead20(void); +u8 cdvdRead21(void); +u8 cdvdRead22(void); +u8 cdvdRead23(void); +u8 cdvdRead24(void); +u8 cdvdRead28(void); +u8 cdvdRead29(void); +u8 cdvdRead2A(void); +u8 cdvdRead2B(void); +u8 cdvdRead2C(void); +u8 cdvdRead30(void); +u8 cdvdRead31(void); +u8 cdvdRead32(void); +u8 cdvdRead33(void); +u8 cdvdRead34(void); +u8 cdvdRead38(void); +u8 cdvdRead39(void); +u8 cdvdRead3A(void); +void cdvdWrite04(u8 rt); +void cdvdWrite05(u8 rt); +void cdvdWrite06(u8 rt); +void cdvdWrite07(u8 rt); +void cdvdWrite08(u8 rt); +void cdvdWrite0A(u8 rt); +void cdvdWrite0F(u8 rt); +void cdvdWrite14(u8 rt); +void cdvdWrite16(u8 rt); +void cdvdWrite17(u8 rt); +void cdvdWrite18(u8 rt); +void cdvdWrite3A(u8 rt); + +#endif /* __CDVD_H__ */ diff --git a/branches/pcsx2_0.9.1/CDVDiso.c b/branches/pcsx2_0.9.1/CDVDiso.c new file mode 100644 index 0000000..4f8ac87 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVDiso.c @@ -0,0 +1,834 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + * Fixed CdRead by linuzappz + */ + +#include +#ifdef __LINUX__ +#define strnicmp strncasecmp +#endif + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +struct dir_toc_data{ + unsigned int start_LBA; + unsigned int num_sectors; + unsigned int num_entries; + unsigned int current_entry; + unsigned int current_sector; + unsigned int current_sector_offset; + unsigned int inc_dirs; + unsigned char extension_list[128+1]; +}; + +//static u8 cdVolDescriptor[2048]; +static struct dir_toc_data getDirTocData; +static struct cdVolDesc CDVolDesc; + +void _splitpath2(const char *constpath, char *dir, char *fname){ + // 255 char max path-length is an ISO9660 restriction + // we must change this for Joliet or relaxed iso restriction support + static char pathcopy[1024+1]; + + char* slash; + + strncpy(pathcopy, constpath, 1024); + + slash = strrchr (pathcopy, '/'); + + // if the path doesn't contain a '/' then look for a '\' + if (!slash) + slash = strrchr (pathcopy, (int)'\\'); + + // if a slash was found + if (slash != NULL) + { + // null terminate the path + slash[0] = 0; + // and copy the path into 'dir' + strncpy(dir, pathcopy, 1024); + dir[255]=0; + + // copy the filename into 'fname' + strncpy(fname, slash+1, 128); + fname[128]=0; + } + else + { + dir[0] = 0; + + strncpy(fname, pathcopy, 128); + fname[128]=0; + } + +} + +// Used in findfile +int tolower(int c); +int strcasecmp(const char *s1, const char *s2){ + while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +// Copy a TOC Entry from the CD native format to our tidier format +void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){ + int i; + int filenamelen; + + tocEntry->fileSize = internalTocEntry->fileSize; + tocEntry->fileLBA = internalTocEntry->fileLBA; + tocEntry->fileProperties = internalTocEntry->fileProperties; + memcpy(tocEntry->date, internalTocEntry->dateStamp, 7); + + if (CDVolDesc.filesystemType == 2){ + // This is a Joliet Filesystem, so use Unicode to ISO string copy + + filenamelen = internalTocEntry->filenameLength/2; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + for (i=0; i < filenamelen; i++) + tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1]; + + tocEntry->filename[filenamelen] = 0; + } + else{ + filenamelen = internalTocEntry->filenameLength; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + // use normal string copy + strncpy(tocEntry->filename,internalTocEntry->filename,128); + tocEntry->filename[filenamelen] = 0; + } +} + +// Check if a TOC Entry matches our extension list +int TocEntryCompare(char* filename, char* extensions){ + static char ext_list[129]; + + char* token; + + char* ext_point; + + strncpy(ext_list,extensions,128); + ext_list[128]=0; + + token = strtok( ext_list, " ," ); + while( token != NULL ) + { + // if 'token' matches extension of 'filename' + // then return a match + ext_point = strrchr(filename,'.'); + + if (strnicmp(ext_point, token, strlen(token)) == 0) + return (TRUE); + + /* Get next token: */ + token = strtok( NULL, " ," ); + } + + // If not match found then return FALSE + return (FALSE); + +} + +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + int rmode; + + switch (mode->datapattern) { + case CdSecS2048: + rmode = CDVD_MODE_2048; break; + case CdSecS2328: + rmode = CDVD_MODE_2328; break; + case CdSecS2340: + rmode = CDVD_MODE_2340; break; + default: + return 0; + } + + for (i=0; idatapattern){ + case CdSecS2048: + memcpy((void*)((uptr)buf+2048*i), buff, 2048);break;//only data + case CdSecS2328: + memcpy((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub + case CdSecS2340: + memcpy((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync + } + } + return 1; +} + +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + + for (i=lsn; i<(lsn+sectors); i++){ + if (CDVDreadTrack(i, CDVD_MODE_2048)==-1) + return 0; + buff = CDVDgetBuffer(); + if (buff==NULL) return 0; + +// switch (mode->datapattern){ +// case CdSecS2064: + ((u32*)buf)[0] = i + 0x30000; + memcpy((u8*)buf+12, buff, 2048); + (u8*)buf+= 2064; break; +// default: +// return 0; +// } + } + + return 1; +} + +/************************************************************** +* The functions below are not exported for normal file-system * +* operations, but are used by the file-system operations, and * +* may also be exported for use via RPC * +**************************************************************/ + +int CDVD_GetVolumeDescriptor(void){ + // Read until we find the last valid Volume Descriptor + int volDescSector; + + static struct cdVolDesc localVolDesc; + +#ifdef DEBUG + printf("CDVD_GetVolumeDescriptor called\n"); +#endif + + for (volDescSector = 16; volDescSector<20; volDescSector++) + { + CdRead(volDescSector,1,&localVolDesc,&cdReadMode); +// CdSync(0x00); + + // If this is still a volume Descriptor + if (strncmp(localVolDesc.volID, "CD001", 5) == 0) + { + if ((localVolDesc.filesystemType == 1) || + (localVolDesc.filesystemType == 2)) + { + memcpy(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc)); + } + } + else + break; + } + +#ifdef DEBUG + if (CDVolDesc.filesystemType == 1) + printf("CD FileSystem is ISO9660\n"); + else if (CDVolDesc.filesystemType == 2) + printf("CD FileSystem is Joliet\n"); + else printf("Could not detect CD FileSystem type\n"); +#endif +// CdStop(); + + return TRUE; +} + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry){ + static char filename[128+1]; + static char pathname[1024+1]; + static char toc[2048]; + char* dirname; + + + static struct TocEntry localTocEntry; // used for internal checking only + + int found_dir; + + int num_dir_sectors; + int current_sector; + + int dir_lba; + + struct dirTocEntry* tocEntryPointer; + +#ifdef DEBUG + printf("CDVD_findfile called\n"); +#endif + + //make sure we have good cdReadMode + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; + + _splitpath2(fname, pathname, filename); + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + + while( dirname != NULL ) + { + found_dir = FALSE; +/* + while(tocEntryPointer->length > 0) + { + // while there are still more directory entries then search through + // for the one we want + + if (tocEntryPointer->fileProperties & 0x02) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcasecmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } +*/ + while(1) + { + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) + { + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else + { + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + + if (tocEntryPointer->fileProperties & 0x02) + { + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + { + printf("CDVD_findfile: could not find dir\n"); + return -1; + } + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + +#ifdef DEBUG + printf("CDVD_findfile: found dir, now looking for file\n"); +#endif + + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + dir_lba = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + while (num_dir_sectors > 0) + { + while(tocEntryPointer->length != 0) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) || + ((filename[strlen(filename)-2] == ';') && + (localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') && + (strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0))) + { + // if the filename matches then copy the toc Entry + tocEntry->fileLBA = localTocEntry.fileLBA; + tocEntry->fileProperties = localTocEntry.fileProperties; + tocEntry->fileSize = localTocEntry.fileSize; + + strcpy(tocEntry->filename, localTocEntry.filename); + memcpy(tocEntry->date, localTocEntry.date, 7); + +#ifdef DEBUG + printf("CDVD_findfile: found file\n"); +#endif + + return TRUE; + } + + (char*)tocEntryPointer += tocEntryPointer->length; + } + + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + dir_lba++; + + if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){ + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + } + +#ifdef DEBUG + printf("CDVD_findfile: could not find file\n"); +#endif + + return FALSE; +} + +// This is the RPC-ready function which takes the request to start the tocEntry retrieval +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){ +// int dir_depth = 1; + static char toc[2048]; + char* dirname; + int found_dir; + int num_dir_sectors; + unsigned int toc_entry_num; + struct dirTocEntry* tocEntryPointer; + static struct TocEntry localTocEntry; + int current_sector; + + // store the extension list statically for the retrieve function + strncpy(getDirTocData.extension_list, extensions, 128); + getDirTocData.extension_list[128]=0; + + getDirTocData.inc_dirs = inc_dirs; + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname); +#endif + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + // use strtok to get the next dir name + + // if there isnt one, then assume we want the LBA + // for the current one, and exit the while loop + + // if there is another dir name then increment dir_depth + // and look through dir table entries until we find the right name + // if we dont find the right name + // before finding an entry at a higher level (lower num), then return nothing + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + while( dirname != NULL ){ + found_dir = FALSE; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) { + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else{ + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + if (tocEntryPointer->fileProperties & 0x02){ + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0){ + // if the name matches then we've found the directory + found_dir = TRUE; +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector); + RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA); +#endif + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + return -1; + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // We know how much data we need to read in from the DirTocHeader + // but we need to read in at least 1 sector before we can get this value + + // Now we need to COUNT the number of entries (dont do anything with info at this point) + // so set the tocEntryPointer to point to the first actual file entry + + // This is a bit of a waste of reads since we're not actually copying the data out yet, + // but we dont know how big this TOC might be, so we cant allocate a specific size + + (char*)tocEntryPointer = toc; + + // Need to STORE the start LBA and number of Sectors, for use by the retrieve func. + getDirTocData.start_LBA = localTocEntry.fileLBA; + getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11; + getDirTocData.num_entries = 0; + getDirTocData.current_entry = 0; + getDirTocData.current_sector = getDirTocData.start_LBA; + getDirTocData.current_sector_offset = 0; + + num_dir_sectors = getDirTocData.num_sectors; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + toc_entry_num=0; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){ + // decrease the number of dirs remaining + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + +// continue; + } + else{ + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + return (toc_entry_num); + } + } + + // We've found a file/dir in this directory + // now check if it matches our extension list (if there is one) + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if (localTocEntry.fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs){ + toc_entry_num++; + } + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + } + else{ + toc_entry_num++; + } + } + + (char*)tocEntryPointer += tocEntryPointer->length; + + } + + + // THIS SHOULD BE UNREACHABLE - + // since we are trying to count ALL matching entries, rather than upto a limit + + + // STORE total number of TOC entries + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + + + // we've reached the toc entry limit, so return how many we've done + return (toc_entry_num); + +} + +// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries +// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){ + static char toc[2048]; + int toc_entry_num; + + struct dirTocEntry* tocEntryPointer; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + if (getDirTocData.current_entry == 0){ + // if this is the first read then make sure we point to the first real entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc; + } + else{ + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + + if (req_entries > 128) + req_entries = 128; + + for (toc_entry_num=0; toc_entry_num < req_entries;){ + if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){ + // decrease the number of dirs remaining + getDirTocData.num_sectors--; + + if (getDirTocData.num_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + getDirTocData.current_sector_offset = 0; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + +// continue; + } + else{ + return (toc_entry_num); + } + } + + // This must be incremented even if the filename doesnt match extension list + getDirTocData.current_entry++; + + // We've found a file in this directory + // now check if it matches our extension list (if there is one) + + // Copy the entry regardless, as it makes the comparison easier + // if it doesn't match then it will just be overwritten + TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer); + + if (tocEntry[toc_entry_num].fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs) { + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + + } + else{ + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + } +/* + if (strlen(getDirTocData.extension_list) > 0) + { + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE) + { + + // increment this here, rather than in the main for loop + // since this should count the number of matching entries + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else + { + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } +*/ + } + return (toc_entry_num); +} diff --git a/branches/pcsx2_0.9.1/CDVDiso.h b/branches/pcsx2_0.9.1/CDVDiso.h new file mode 100644 index 0000000..72b0552 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVDiso.h @@ -0,0 +1,131 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISO_H__ +#define __CDVDISO_H__ + +#include "CDVDlib.h" + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs); +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries); + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTableEntry +{ + u8 dirNameLength; + u8 reserved; + u32 dirTOCLBA; + u16 dirDepth; + u8 dirName[32]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTocEntry +{ + short length; + unsigned int fileLBA; + unsigned int fileLBA_bigend; + unsigned int fileSize; + unsigned int fileSize_bigend; + unsigned char dateStamp[6]; + unsigned char reserved1; + unsigned char fileProperties; + unsigned char reserved2[6]; + unsigned char filenameLength; + unsigned char filename[128]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif // This is the internal format on the CD +// TocEntry structure contains only the important stuff needed for export + +#if defined(__WIN32__) +#pragma pack() +#endif + +#endif//__CDVDISO_H__ diff --git a/branches/pcsx2_0.9.1/CDVDisodrv.c b/branches/pcsx2_0.9.1/CDVDisodrv.c new file mode 100644 index 0000000..a415367 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVDisodrv.c @@ -0,0 +1,263 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#include + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +CdRMode cdReadMode; + +struct fdtable{ +//int fd; + int fileSize; + int LBA; + int filePos; +}; + +static struct fdtable fd_table[16]; +static int fd_used[16]; +static int files_open=0; +static int inited=FALSE; + +/************************************************************* +* The functions below are the normal file-system operations, * +* used to provide a standard filesystem interface * +*************************************************************/ + +////////////////////////////////////////////////////////////////////// +// CDVDFS_init +// called by 80000592 sceCdInit() +////////////////////////////////////////////////////////////////////// +void CDVDFS_init(){ + + if (inited) return;//might change in the future as a param; forceInit/Reset + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00\n"); + RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n"); + RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.\n", "cdfs"); +#endif + + //CdInit(0); already called by plugin loading system ;) + + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; //isofs driver only needs + //2KB sectors + + memset(fd_table, 0, sizeof(fd_table)); + memset(fd_used, 0, 16*sizeof(int)); + + inited = TRUE; + + return; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_open +// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_open(char *name, int mode){ + register int j; + static struct TocEntry tocEntry; + + // check if the file exists + if (CDVD_findfile(name, &tocEntry) != TRUE) + return -1; + + if(mode != 1) return -2; //SCE_RDONLY + + // set up a new file descriptor + for(j=0; j < 16; j++) if(fd_used[j] == 0) break; + if(j >= 16) return -3; + + fd_used[j] = 1; + files_open++; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:open] internal fd=%d\n", j); +#endif + + fd_table[j].fileSize = tocEntry.fileSize; + fd_table[j].LBA = tocEntry.fileLBA; + fd_table[j].filePos = 0; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d\n",tocEntry.fileSize); +#endif + + return j; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_lseek +// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_lseek(int fd, int offset, int whence){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + switch(whence){ + case SEEK_SET: + fd_table[fd].filePos = offset; + break; + + case SEEK_CUR: + fd_table[fd].filePos += offset; + break; + + case SEEK_END: + fd_table[fd].filePos = fd_table[fd].fileSize + offset; + break; + + default: + return -1; + } + + if (fd_table[fd].filePos < 0) + fd_table[fd].filePos = 0; + + if (fd_table[fd].filePos > fd_table[fd].fileSize) + fd_table[fd].filePos = fd_table[fd].fileSize; + + return fd_table[fd].filePos; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_read +// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_read( int fd, char *buffer, int size ){ +// int start_sector; + int off_sector; +// int num_sectors; + + //static char local_buffer[2024*2048]; //4MB + static char lb[2048]; //2KB + //Start, Aligned, End + int ssector, asector, esector; + int ssize=0, asize, esize; + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + // A few sanity checks + if (fd_table[fd].filePos > fd_table[fd].fileSize){ + // We cant start reading from past the beginning of the file + return 0; // File exists but we couldnt read anything from it + } + + if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize) + size = fd_table[fd].fileSize - fd_table[fd].filePos; + + // Now work out where we want to start reading from + asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + if (off_sector){ + ssize = min(2048 - off_sector, size); + size -= ssize; + asector++; + } + asize = size & 0xFFFFF800; + esize = size & 0x000007FF; + esector=asector + (asize >> 11); + size += ssize; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n", ssector, esector-(esize==0)); +#endif + + if (ssize){ if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer, lb + off_sector, ssize); + } + if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + if (esize){ if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer+ssize+asize, lb, esize); + } +/*********************** + // Now work out where we want to start reading from + start_sector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + num_sectors = ((off_sector + size) >> 11) + 1; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n",start_sector,start_sector+num_sectors); +#endif + + // Read the data (we only ever get 16KB max request at once) + if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + //RPC_LOG("sector = %d, start sector = %d\n",sector,start_sector); + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + //CdSync(0); hm, a wait function maybe... + + memcpy(buffer,local_buffer+off_sector,size); +**************************/ + fd_table[fd].filePos += size; + + return (size); +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_write +// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:" +// hehe, this ain't a CD writing option :D +////////////////////////////////////////////////////////////////////// +int CDVDFS_write( int fd, char * buffer, int size ){ + if(size == 0) return 0; + else return -1; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_close +// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_close( int fd){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] internal fd %d\n", fd); +#endif + + fd_used[fd] = 0; + files_open--; + + return 0; +} + diff --git a/branches/pcsx2_0.9.1/CDVDisodrv.h b/branches/pcsx2_0.9.1/CDVDisodrv.h new file mode 100644 index 0000000..dcf8545 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVDisodrv.h @@ -0,0 +1,22 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISODRV_H__ +#define __CDVDISODRV_H__ + +//#include "Common.h" +#include "CDVDlib.h" + +extern CdRMode cdReadMode; + +/* Filing-system exported functions */ +void CDVDFS_init(); +int CDVDFS_open(char *name, int mode); +int CDVDFS_lseek(int fd, int offset, int whence); +int CDVDFS_read( int fd, char * buffer, int size ); +int CDVDFS_write( int fd, char * buffer, int size ); +int CDVDFS_close( int fd); + +#endif//__CDVDISODRV_H__ diff --git a/branches/pcsx2_0.9.1/CDVDlib.h b/branches/pcsx2_0.9.1/CDVDlib.h new file mode 100644 index 0000000..f451981 --- /dev/null +++ b/branches/pcsx2_0.9.1/CDVDlib.h @@ -0,0 +1,185 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Linux kernel headers + * Modified by Florin for PCSX2 emu + */ + +#ifndef _CDVDLIB_H +#define _CDVDLIB_H + +#include "Common.h" + +// Macros for READ Data pattan +#define CdSecS2048 0 // sector size 2048 +#define CdSecS2328 1 // sector size 2328 +#define CdSecS2340 2 // sector size 2340 + +//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ + +/* + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + * 2340, or 2352 bytes long. + * Sector types of the standard CD-ROM data formats: + * + * format sector type user data size (bytes) + * ----------------------------------------------------------------------------- + * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW) + * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE) + * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0) + * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE) + * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + * + * + * The layout of the standard CD-ROM data formats: + * ----------------------------------------------------------------------------- + * - audio (red): | audio_sample_bytes | + * | 2352 | + * + * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + * | 12 - 4 - 2048 - 4 - 8 - 276 | + * + * - data (yellow, mode2): | sync - head - data | + * | 12 - 4 - 2336 | + * + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + * | 12 - 4 - 8 - 2048 - 4 - 276 | + * + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + * | 12 - 4 - 8 - 2324 - 4 | + * + */ + +// Macros for Spindle control +#define CdSpinMax 0 +#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. +#define CdSpinStm 0 // Recommended stream rotation speed. + +// Macros for TrayReq +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 + +/* + * Macros for sceCdGetDiskType() //comments translated from japanese;) + */ +#define SCECdIllgalMedia 0xff + /* ILIMEDIA (Illegal Media) + A non-PS / non-PS2 Disc. */ +#define SCECdDVDV 0xfe + /* DVDV (DVD Video) + A non-PS / non-PS2 Disc, but a DVD Video Disc */ +#define SCECdCDDA 0xfd + /* CDDA (CD DA) + A non-PS / non-PS2 Disc that include a DA track */ +#define SCECdPS2DVD 0x14 + /* PS2DVD PS2 consumer DVD. */ +#define SCECdPS2CDDA 0x13 + /* PS2CDDA PS2 consumer CD that includes a DA track */ +#define SCECdPS2CD 0x12 + /* PS2CD PS2 consumer CD that does not include a DA track */ +#define SCECdPSCDDA 0x11 + /* PSCDDA PS CD that includes a DA track */ +#define SCECdPSCD 0x10 + /* PSCD PS CD that does not include a DA track */ +#define SCECdDETCT 0x01 + /* DETCT (Detecting) Disc distinction action */ +#define SCECdNODISC 0x00 + /* NODISC (No disc) No disc entered */ + +/* + * Media mode + */ +#define SCECdCD 1 +#define SCECdDVD 2 + +typedef struct { + u8 stat; // 0: normal. Any other: error + u8 second; // second (BCD value) + u8 minute; // minute (BCD value) + u8 hour; // hour (BCD value) + u8 week; // week (BCD value) + u8 day; // day (BCD value) + u8 month; // month (BCD value) + u8 year; // year (BCD value) +} CdCLOCK; + +typedef struct { + u32 lsn; // Logical sector number of file + u32 size; // File size (in bytes) + char name[16]; // Filename + u8 date[8]; // 1th: Seconds + // 2th: Minutes + // 3th: Hours + // 4th: Date + // 5th: Month + // 6th 7th: Year (4 digits) +} CdlFILE; + +typedef struct { + u8 minute; // Minutes + u8 second; // Seconds + u8 sector; // Sector + u8 track; // Track number +} CdlLOCCD; + +typedef struct { + u8 trycount; // Read try count (No. of error retries + 1) (0 - 255) + u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed. + // SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. + u8 datapattern; // SCECdSecS2048: Data size 2048 bytes + // SCECdSecS2328: 2328 bytes + // SCECdSecS2340: 2340 bytes + u8 pad; // Padding data produced by alignment. +} CdRMode; + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct TocEntry +{ + u32 fileLBA; + u32 fileSize; + u8 fileProperties; + u8 padding1[3]; + u8 filename[128+1]; + u8 date[7]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +#if defined(__WIN32__) +#pragma pack() +#endif + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +/* +int CdBreak(void); +int CdCallback( void (*func)() ); +int CdDiskReady(int mode); +int CdGetDiskType(void); +int CdGetError(void); +u32 CdGetReadPos(void); +int CdGetToc(u8 *toc); +int CdInit(int init_mode); +CdlLOCCD *CdIntToPos(int i, CdlLOCCD *p); +int CdPause(void); +int CdPosToInt(CdlLOCCD *p);*/ +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +/*int CdReadClock(CdCLOCK *rtc); +int CdSearchFile (CdlFILE *fp, const char *name); +int CdSeek(u32 lsn); +int CdStandby(void); +int CdStatus(void); +int CdStop(void); +int CdSync(int mode); +int CdTrayReq(int mode, u32 *traycnt); +*/ +#endif // _CDVDLIB_H diff --git a/branches/pcsx2_0.9.1/COP0.c b/branches/pcsx2_0.9.1/COP0.c new file mode 100644 index 0000000..53f67b9 --- /dev/null +++ b/branches/pcsx2_0.9.1/COP0.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +extern BOOL bExecBIOS; + +void COP0() { + Int_COP0PrintTable[_Rs_](); +} + +void COP0_BC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03](); +} + +void COP0_Func() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0C0PrintTable[_Funct_](); +} + +void COP0_Unknown() { +#ifdef CPU_LOG + CPU_LOG("COP0 Unknown opcode called\n"); +#endif +} + +void UpdateCP0Status() { + u32 value = cpuRegs.CP0.n.Status.val; + + if (value & 0x06 || + (value & 0x18) == 0) { // Kernel Mode (KSU = 0 | EXL = 1 | ERL = 1)*/ + memSetKernelMode(); // Kernel memory always + } else { // User Mode + memSetUserMode(); + } + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)cpuTestHwInts(); +} + +void WriteCP0Status(u32 value) { + cpuRegs.CP0.n.Status.val = value; + UpdateCP0Status(); +} + +extern u32 s_iLastCOP0Cycle; + +void MFC0() { + if (!_Rt_) return; +#ifdef COP0_LOG + if (_Rd_ != 9) { COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); } +#endif + + if( _Rd_ == 9 ) { + // update + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + } + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.CP0.r[_Rd_]; +} + +void MTC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + switch (_Rd_) { + case 12: WriteCP0Status(cpuRegs.GPR.r[_Rt_].UL[0]); break; + case 9: s_iLastCOP0Cycle = cpuRegs.cycle; cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + default: cpuRegs.CP0.r[_Rd_] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + } +} + +int CPCOND0() { + if(((psHu16(DMAC_STAT) & psHu16(DMAC_PCR)) & 0x3ff) == (psHu16(DMAC_PCR) & 0x3ff)) return 1; + else return 0; +} + +//#define CPCOND0 1 + +#define BC0(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC0F() { + BC0(== 0); +} + +void BC0T() { + BC0(== 1); +} + +#define BC0L(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC0FL() { + BC0L(== 0); +} + +void BC0TL() { + BC0L(== 1); +} + +void TLBR() { +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + int i = cpuRegs.CP0.n.Index&0x1f; + +// if( !bExecBIOS ) +// __Log("TLBR %d\n", cpuRegs.CP0.n.Index&0x1f); + + SysPrintf("COP0_TLBR\n"); + cpuRegs.CP0.n.PageMask = tlb[i].PageMask; + cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi&~(tlb[i].PageMask|0x1f00); + cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0&~1)|((tlb[i].EntryHi>>12)&1); + cpuRegs.CP0.n.EntryLo1 =(tlb[i].EntryLo1&~1)|((tlb[i].EntryHi>>12)&1); +} + +void ClearTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void WriteTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + tlb[i].PageMask = cpuRegs.CP0.n.PageMask; + tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi; + tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0; + tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1; + + tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff; + tlb[i].nMask = (~tlb[i].Mask) & 0xfff; + tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13; + tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff; + tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1; + tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN0|= (0x80000000); + tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN1|= (0x80000000); + if (tlb[i].VPN2 == 0x70000000) return; + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void TLBWI() { + int j = cpuRegs.CP0.n.Index & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWI %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWI %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBWR() { + int j = cpuRegs.CP0.n.Random & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWR %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBP() { + int i; + + + union { + struct { + u32 VPN2:19; + u32 VPN2X:2; + u32 G:3; + u32 ASID:8; + } s; + u32 u; + } EntryHi32; + + if( !bExecBIOS ) + __Log("TLBP %x\n", cpuRegs.CP0.n.EntryHi); + + EntryHi32.u=cpuRegs.CP0.n.EntryHi; + + cpuRegs.CP0.n.Index=0xFFFFFFFF; + for(i=0;i<48;i++){ + if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2)) + &&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { + cpuRegs.CP0.n.Index=i; + break; + } + } + if(cpuRegs.CP0.n.Index == 0xFFFFFFFF) cpuRegs.CP0.n.Index = 0x80000000; +} + +void ERET() { + if (cpuRegs.CP0.n.Status.b.ERL) { + cpuRegs.pc = cpuRegs.CP0.n.ErrorEPC; + cpuRegs.CP0.n.Status.b.ERL = 0; + } else { + cpuRegs.pc = cpuRegs.CP0.n.EPC; + cpuRegs.CP0.n.Status.b.EXL = 0; + } + UpdateCP0Status(); + intSetBranch(); +} + +void DI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 0; + UpdateCP0Status(); + } +} + +void EI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 1; + UpdateCP0Status(); + } +} + diff --git a/branches/pcsx2_0.9.1/COP0.h b/branches/pcsx2_0.9.1/COP0.h new file mode 100644 index 0000000..30ad063 --- /dev/null +++ b/branches/pcsx2_0.9.1/COP0.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COP0_H__ +#define __COP0_H__ + +void WriteCP0Status(u32 value); +void UpdateCP0Status(); +void WriteTLB(int i); +void ClearTLB(int i); + +#endif /* __COP0_H__ */ diff --git a/branches/pcsx2_0.9.1/Cache.c b/branches/pcsx2_0.9.1/Cache.c new file mode 100644 index 0000000..305a666 --- /dev/null +++ b/branches/pcsx2_0.9.1/Cache.c @@ -0,0 +1,355 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "Cache.h" + +/*_cacheS pCache[64]; +int getFreeCache(u32 mem, int mode, int * way) { + u8 * out; + u32 paddr; + u32 taddr[2]; + u8 * t; + int number; + int i = (mem >> 6) & 0x3F; + + paddr = memLUTR[mem >> 12]; + taddr[0] = memLUTW[pCache[i].tag[0]>>12]; + taddr[1] = memLUTW[pCache[i].tag[1]>>12]; + + if (taddr[0] == paddr && (pCache[i].tag[0] & 0x20)) + { + *way = 0; + return i; + }else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20)) + { + *way = 1; + return i; + } + + number = ((pCache[i].tag[0]>>4) & 1) ^ ((pCache[i].tag[1]>>4) & 1); + + if(pCache[i].tag[number] & 0x60) // Valid Dirty + { + t = (char *)(taddr[number]); + out = (u8*)(t + (mem & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[i].data[number][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[i].data[number][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[i].data[number][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[i].data[number][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[i].data[number][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[i].data[number][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[i].data[number][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[i].data[number][3].b8._8)[1]; + } + + + + if(mode == 1) + { + pCache[i].tag[number] |= 0x40; // Set Dirty Bit if mode == write + } + + pCache[i].tag[number] &= ~(0xFFFFF000); + pCache[i].tag[number] |= ((mem>>12) & 0xFFFFF) << 12; + + + t = (u8 *)paddr; + out= (u8*)(t + (mem & 0xFC0)); + ((u64*)pCache[i].data[number][0].b8._8)[0] = ((u64*)out)[0]; + ((u64*)pCache[i].data[number][0].b8._8)[1] = ((u64*)out)[1]; + ((u64*)pCache[i].data[number][1].b8._8)[0] = ((u64*)out)[2]; + ((u64*)pCache[i].data[number][1].b8._8)[1] = ((u64*)out)[3]; + ((u64*)pCache[i].data[number][2].b8._8)[0] = ((u64*)out)[4]; + ((u64*)pCache[i].data[number][2].b8._8)[1] = ((u64*)out)[5]; + ((u64*)pCache[i].data[number][3].b8._8)[0] = ((u64*)out)[6]; + ((u64*)pCache[i].data[number][3].b8._8)[1] = ((u64*)out)[7]; + + if(pCache[i].tag[number] & 0x10) pCache[i].tag[number] &= ~(0x10); + else pCache[i].tag[number] |= 0x10; + + pCache[i].tag[number] |= 0x20; + *way = number; + return i; +} + +void writeCache8(u32 mem, u8 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)] = value; +} + +void writeCache16(u32 mem, u16 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u16*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache32(u32 mem, u32 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + *(u32*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache64(u32 mem, u64 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u64*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache128(u32 mem, u64 *value) { + int i, number; + + i = getFreeCache(mem,1,&number); + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[0] = value[0]; + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[1] = value[1]; +} + +u8 *readCache(u32 mem) { + int i, number; + + i = getFreeCache(mem,0,&number); + + return pCache[i].data[number][(mem>>4) & 0x3].b8._8; +} + +void CACHE() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + switch (_Rt_) { + case 0x1a: + { + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTR[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + case 0x18: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x1c: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } +#ifdef GTE_LOG + GTE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x40); + break; + } + case 0x16: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; +#ifdef GTE_LOG + GTE_LOG("CACHE DXIN addr %x, index %d, way %d, flag %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x11: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + cpuRegs.CP0.r[28] = *(u32 *)(out+(addr&0xf)); +#ifdef GTE_LOG + GTE_LOG("CACHE DXLDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x10: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + + cpuRegs.CP0.r[28] = 0; + cpuRegs.CP0.r[28] = pCache[index].tag[way]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXLTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x13: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + *(u32*)(&pCache[index].data[way][(addr>>4) & 0x3].b8._8[(addr&0xf)]) = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x12: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + pCache[index].tag[way] = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28] & 0x6F); +#endif + break; + } + case 0x14: + { + + u8 * out; + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + +#ifdef GTE_LOG + GTE_LOG("CACHE DXWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Dirty + { + u32 paddr = memLUTW[pCache[index].tag[way] >> 12]; + char * t = (char *)(paddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + } +}*/ + +void CACHE() { +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/Cache.h b/branches/pcsx2_0.9.1/Cache.h new file mode 100644 index 0000000..07ed623 --- /dev/null +++ b/branches/pcsx2_0.9.1/Cache.h @@ -0,0 +1,34 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "Common.h" + +void freeCache(int i); +int getFreeCache(); + +void writeCache8(u32 mem, u8 value); +void writeCache16(u32 mem, u16 value); +void writeCache32(u32 mem, u32 value); +void writeCache64(u32 mem, u64 value); +void writeCache128(u32 mem, u64 *value); +u8 *readCache(u32 mem); + +#endif /* __CACHE_H__ */ diff --git a/branches/pcsx2_0.9.1/CdRom.c b/branches/pcsx2_0.9.1/CdRom.c new file mode 100644 index 0000000..2f3f1be --- /dev/null +++ b/branches/pcsx2_0.9.1/CdRom.c @@ -0,0 +1,1078 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +//THIS ALL IS FOR THE CDROM REGISTERS HANDLING +#include "PsxCommon.h" + +#define CdlSync 0 +#define CdlNop 1 +#define CdlSetloc 2 +#define CdlPlay 3 +#define CdlForward 4 +#define CdlBackward 5 +#define CdlReadN 6 +#define CdlStandby 7 +#define CdlStop 8 +#define CdlPause 9 +#define CdlInit 10 +#define CdlMute 11 +#define CdlDemute 12 +#define CdlSetfilter 13 +#define CdlSetmode 14 +#define CdlGetmode 15 +#define CdlGetlocL 16 +#define CdlGetlocP 17 +#define Cdl18 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlTest 25 +#define CdlID 26 +#define CdlReadS 27 +#define CdlReset 28 +#define CdlReadToc 30 + +#define AUTOPAUSE 249 +#define READ_ACK 250 +#define READ 251 +#define REPPLAY_ACK 252 +#define REPPLAY 253 +#define ASYNC 254 +/* don't set 255, it's reserved */ + +char *CmdName[0x100]= { + "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", + "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", + "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, + NULL, "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +u8 Test04[] = { 0 }; +u8 Test05[] = { 0 }; +u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; +u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; +u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) +//#define cdReadTime ((PSXCLK / 75) / BIAS) +unsigned long cdReadTime;// = ((PSXCLK / 75) / BIAS); + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +/*static struct CdrStat stat; +static struct SubQ *subq;*/ + +#define CDR_INT(eCycle) PSX_INT(17, eCycle) +#define CDREAD_INT(eCycle) PSX_INT(18, eCycle) + +#define StartReading(type) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, 0x800); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt&=~0x40000; \ + } \ +} + +#define StopCdda() { \ + if (cdr.Play) { \ +/* if (!Config.Cdda) CDR_stop();*/ \ + cdr.StatP&=~0x80; \ + cdr.Play = 0; \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + lsn += 150; + Time[2] = lsn / 4500; // minuten + lsn = lsn - Time[2] * 4500; // minuten rest + Time[1] = lsn / 75; // sekunden + Time[0] = lsn - Time[1] * 75; // sekunden rest +} + +void ReadTrack() { + cdr.Prev[0] = itob(cdr.SetSector[0]); + cdr.Prev[1] = itob(cdr.SetSector[1]); + cdr.Prev[2] = itob(cdr.SetSector[2]); + +#ifdef CDR_LOG + CDR_LOG("KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2352); +} + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +void AddIrqQueue(u8 irq, unsigned long ecycle) { + cdr.Irq = irq; + if (cdr.Stat) { + cdr.eCycle = ecycle; + } else { + CDR_INT(ecycle); + } +} + +int cdrInterrupt() { + cdvdTD trackInfo; + int i; + u8 Irq = cdr.Irq; + + if (cdr.Stat) { + CDR_INT(0x800); + return 0; + } + + cdr.Irq = 0xff; + cdr.Ctrl&=~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +/* i = stat.Status; + if (CDR_getStatus(&stat) != -1) { + if (stat.Type == 0xff) cdr.Stat = DiskError; + if (stat.Status & 0x10) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x11; + cdr.Result[0]&=~0x02; + } + else if (i & 0x10) { + cdr.StatP |= 0x2; + cdr.Result[0]|= 0x2; + CheckCdrom(); + } + }*/ + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + cdr.StatP|= 0x82; +// if ((cdr.Mode & 0x5) == 0x5) AddIrqQueue(REPPLAY, cdReadTime); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP&=~0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlPause + 0x20, 0x800); + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +// if (!cdr.Init) { + AddIrqQueue(CdlInit + 0x20, 0x800); +// } + break; + + case CdlInit + 0x20: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Init = 1; + break; + + case CdlMute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = cdr.Mode; + cdr.Result[2] = cdr.File; + cdr.Result[3] = cdr.Channel; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocL: + SetResultSize(8); +// for (i=0; i<8; i++) cdr.Result[i] = itob(cdr.Transfer[i]); + for (i=0; i<8; i++) cdr.Result[i] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + SetResultSize(8); +/* subq = (struct SubQ*) CDR_getBufferSub(); + if (subq != NULL) { + cdr.Result[0] = subq->TrackNumber; + cdr.Result[1] = subq->IndexNumber; + memcpy(cdr.Result+2, subq->TrackRelativeAddress, 3); + memcpy(cdr.Result+5, subq->AbsoluteAddress, 3); + } else { +*/ cdr.Result[0] = 1; + cdr.Result[1] = 1; + cdr.Result[2] = cdr.Prev[0]; + cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); + cdr.Result[4] = cdr.Prev[2]; + memcpy(cdr.Result+5, cdr.Prev, 3); +// } + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + if (CDVDgetTN(&cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + cdr.Stat = Acknowledge; + cdr.Result[1] = itob(cdr.ResultTN.strack); + cdr.Result[2] = itob(cdr.ResultTN.etrack); + } + break; + + case CdlGetTD: + cdr.CmdProcess = 0; + cdr.Track = btoi(cdr.Param[0]); + SetResultSize(4); + cdr.StatP|= 0x2; + if (CDVDgetTD(cdr.Track, &trackInfo) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + LSNtoMSF(cdr.ResultTD, trackInfo.lsn); + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = itob(cdr.ResultTD[0]); + cdr.Result[2] = itob(cdr.ResultTD[1]); + cdr.Result[3] = itob(cdr.ResultTD[2]); + } + break; + + case CdlSeekL: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekL + 0x20, 0x800); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, 0x800); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlTest: + cdr.Stat = Acknowledge; + switch (cdr.Param[0]) { + case 0x20: // System Controller ROM Version + SetResultSize(4); + memcpy(cdr.Result, Test20, 4); + break; + case 0x22: + SetResultSize(8); + memcpy(cdr.Result, Test22, 4); + break; + case 0x23: case 0x24: + SetResultSize(8); + memcpy(cdr.Result, Test23, 4); + break; + } + break; + + case CdlID: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlID + 0x20, 0x800); + break; + + case CdlID + 0x20: + SetResultSize(8); +// if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player + cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD +/* } + else { + if (stat.Type == 2) { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + } + else { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x00; + } + }*/ + if (!LoadCdBios) cdr.Result[1] |= 0x80; + + cdr.Result[2] = 0x00; + cdr.Result[3] = 0x00; + strncpy((char *)&cdr.Result[4], "PCSX", 4); + cdr.Stat = Complete; + break; + + case CdlReset: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case AUTOPAUSE: + cdr.OCUP = 0; +/* SetResultSize(1); + StopCdda(); + StopReading(); + cdr.OCUP = 0; + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = DataEnd; +*/ AddIrqQueue(CdlPause, 0x400); + break; + + case READ_ACK: + if (!cdr.Reading) return 1; + + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + ReadTrack(); + + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + + break; + + case REPPLAY_ACK: + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + SetResultSize(1); + AddIrqQueue(REPPLAY, cdReadTime); + break; + + case REPPLAY: + if ((cdr.Mode & 5) != 5) break; +/* if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } else memcpy(cdr.Result, &stat.Track, 8); + cdr.Stat = 1; + SetResultSize(8); + AddIrqQueue(REPPLAY_ACK, cdReadTime); +*/ break; + + case 0xff: + return 1; + + default: + cdr.Stat = Complete; + break; + } + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4; + +#ifdef CDR_LOG + CDR_LOG("Cdr Interrupt %x\n", Irq); +#endif + return 1; +} + +int cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) return 1; + + if (cdr.Stat) { + CDREAD_INT(0x800); + return 0; + } + +#ifdef CDR_LOG + CDR_LOG("KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP|= 0x22; + cdr.Result[0] = cdr.StatP; + + SysMessage("Reading From CDR"); + buf = CDVDgetBuffer(); + if (buf == NULL) cdr.RErr = -1; + + if (cdr.RErr == -1) { +#ifdef CDR_LOG + fprintf(emuLog, " err\n"); +#endif + memset(cdr.Transfer, 0, 2340); + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return 0; + } + + memcpy(cdr.Transfer, buf+12, 2340); + cdr.Stat = DataReady; + +#ifdef CDR_LOG + fprintf(emuLog, " %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); +#endif + +/* if ((cdr.Muted == 1) && (cdr.Mode & 0x40) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + if ((cdr.Transfer[4+2] & 0x4) && + ((cdr.Mode&0x8) ? (cdr.Transfer[4+1] == cdr.Channel) : 1) && + (cdr.Transfer[4+0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + } + else cdr.FirstSector = -1; + } + }*/ + + cdr.SetSector[2]++; + if (cdr.SetSector[2] == 75) { + cdr.SetSector[2] = 0; + cdr.SetSector[1]++; + if (cdr.SetSector[1] == 60) { + cdr.SetSector[1] = 0; + cdr.SetSector[0]++; + } + } + + cdr.Readed = 0; + + if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF +#ifdef CDR_LOG + CDR_LOG("AutoPausing Read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x800); + AddIrqQueue(CdlPause, 0x800); + } + else { + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + } + + psxHu32(0x1070)|=0x4; + return 0; +} + +/* +cdrRead0: + bit 0 - 0 REG1 command send / 1 REG1 data read + bit 1 - 0 data transfer finish / 1 data transfer ready/in progress + bit 2 - unknown + bit 3 - unknown + bit 4 - unknown + bit 5 - 1 result ready + bit 6 - 1 dma ready + bit 7 - 1 command being processed +*/ + +u8 cdrRead0(void) { + if (cdr.ResultReady) cdr.Ctrl|= 0x20; + else cdr.Ctrl&=~0x20; + + if (cdr.OCUP) cdr.Ctrl|= 0x40; + else cdr.Ctrl&=~0x40; + + // what means the 0x10 and the 0x08 bits? i only saw it used by the bios + cdr.Ctrl|=0x18; + +#ifdef CDR_LOG + CDR_LOG("CD0 Read: %x\n", cdr.Ctrl); +#endif + return psxHu8(0x1800) = cdr.Ctrl; +} + +/* +cdrWrite0: + 0 - to send a command / 1 - to get the result +*/ + +void cdrWrite0(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD0 write: %x\n", rt); +#endif + cdr.Ctrl = rt | (cdr.Ctrl & ~0x3); + + if (rt == 0) { + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + } +} + +u8 cdrRead1(void) { + if (cdr.ResultReady && cdr.Ctrl & 0x1) { + psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; + if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0; + } else psxHu8(0x1801) = 0; +#ifdef CDR_LOG + CDR_LOG("CD1 Read: %x\n", psxHu8(0x1801)); +#endif + return psxHu8(0x1801); +} + +void cdrWrite1(u8 rt) { + int i; + +#ifdef CDR_LOG + CDR_LOG("CD1 write: %x (%s)\n", rt, CmdName[rt]); +#endif +// psxHu8(0x1801) = rt; + cdr.Cmd = rt; + cdr.OCUP = 0; + +#ifdef CDRCMD_DEBUG + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); + if (cdr.ParamC) { + SysPrintf(" Param[%d] = {", cdr.ParamC); + for (i=0;i cdr.ResultTN[1]) cdr.CurTrack = cdr.ResultTN[1]; + if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) { + int tmp = cdr.ResultTD[2]; + cdr.ResultTD[2] = cdr.ResultTD[0]; + cdr.ResultTD[0] = tmp; + if (!Config.Cdda) CDR_play(cdr.ResultTD); + } + } + } + else if (!Config.Cdda) CDR_play(cdr.SetSector); +*/ cdr.Play = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlForward: + if (cdr.CurTrack < 0xaa) cdr.CurTrack++; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlBackward: + if (cdr.CurTrack > 1) cdr.CurTrack--; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadN: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(1); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x40000); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = 0; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlDemute: + cdr.Muted = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetfilter: + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetmode: +#ifdef CDR_LOG + CDR_LOG("Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetmode: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTN: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTD: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekP: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlTest: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlID: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadS: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(2); + break; + + case CdlReadToc: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4; +} + +u8 cdrRead2(void) { + u8 ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = *cdr.pTransfer++; + } + +#ifdef CDR_LOG + CDR_LOG("CD2 Read: %x\n", ret); +#endif + return ret; +} + +void cdrWrite2(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD2 write: %x\n", rt); +#endif + if (cdr.Ctrl & 0x1) { + switch (rt) { + case 0x07: + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + cdr.Ctrl = 0; + break; + + default: + cdr.Reg2 = rt; + break; + } + } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { + cdr.Param[cdr.ParamP++] = rt; + cdr.ParamC++; + } +} + +u8 cdrRead3(void) { + if (cdr.Stat) { + if (cdr.Ctrl & 0x1) psxHu8(0x1803) = cdr.Stat | 0xE0; + else psxHu8(0x1803) = 0xff; + } else psxHu8(0x1803) = 0; +#ifdef CDR_LOG + CDR_LOG("CD3 Read: %x\n", psxHu8(0x1803)); +#endif + return psxHu8(0x1803); +} + +void cdrWrite3(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD3 write: %x\n", rt); +#endif + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { cdr.Irq = 0; return; } + if (cdr.Irq) { + CDR_INT(cdr.eCycle); + }/* else if (cdr.Reading) { + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + }*/ + return; + } + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.pTransfer = cdr.Transfer; + + switch (cdr.Mode&0x30) { + case 0x10: + case 0x00: cdr.pTransfer+=12; break; + default: break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** NOT READY\n"); +#endif + return; + } + + cdsize = (bcr & 0xffff) * 4; + + memcpy((u8*)PSXM(madr), cdr.pTransfer, cdsize); + psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=cdsize; + + break; + case 0x41000200: + //SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr); + // size = 16 * 32 * 4 (one sector) +/* PSXMu8(madr+0) = 0x10; + PSXMu8(madr+1) = 0x00; + PSXMu8(madr+2) = 0x03; + PSXMu8(madr+3) = 0x00;*/ + return; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown cddma %lx\n", chcr); +#endif + break; + } + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack=1; + cdr.File=1; cdr.Channel=1; + cdReadTime = (PSXCLK / 1757) * BIAS; + //DVD is 4x (PSXCLK / 75) CD is 24x on the PS2, so that would mean CD = (PSXCLK / 450) + // 75/4 = 18.75 x 24 = 450 remember its faster than the PS1 ;) Refraction + + // with the timing set to 60 Gran Turismo works + // anybody knows why it doesn't with 75? + // 75 is the correct cdrom timing +// if (Config.CdTiming) +// cdReadTime = (PSXCLK / 60) / BIAS; + // this seems to be the most compatible + // let's leave like this until we know why + // 75 is buggy with some games +} + +int cdrFreeze(gzFile f, int Mode) { + int tmp; + + gzfreeze(&cdr, sizeof(cdr)); + + if (Mode == 1) tmp = cdr.pTransfer - cdr.Transfer; + gzfreezel(&tmp); + if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp; + + return 0; +} + diff --git a/branches/pcsx2_0.9.1/CdRom.h b/branches/pcsx2_0.9.1/CdRom.h new file mode 100644 index 0000000..569909e --- /dev/null +++ b/branches/pcsx2_0.9.1/CdRom.h @@ -0,0 +1,92 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#include "PsxCommon.h" +#include "Decode_XA.h" +#include "PS2Edefs.h" + +typedef struct { + u8 OCUP; + u8 Reg1Mode; + u8 Reg2; + u8 CmdProcess; + u8 Ctrl; + u8 Stat; + + u8 StatP; + + u8 Transfer[2352]; + u8 *pTransfer; + + u8 Prev[4]; + u8 Param[8]; + u8 Result[8]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + u8 ResultReady; + u8 Cmd; + u8 Readed; + unsigned long Reading; + + cdvdTN ResultTN; + u8 ResultTD[4]; + u8 SetSector[4]; + u8 SetSectorSeek[4]; + u8 Track; + int Play; + int CurTrack; + int Mode, File, Channel, Muted; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + u8 Irq; + unsigned long eCycle; + + char Unused[4087]; +} cdrStruct; + +cdrStruct cdr; + +s32 MSFtoLSN(u8 *Time); +void LSNtoMSF(u8 *Time, s32 lsn); + +void cdrReset(); +int cdrInterrupt(); +int cdrReadInterrupt(); +u8 cdrRead0(void); +u8 cdrRead1(void); +u8 cdrRead2(void); +u8 cdrRead3(void); +void cdrWrite0(u8 rt); +void cdrWrite1(u8 rt); +void cdrWrite2(u8 rt); +void cdrWrite3(u8 rt); +int cdrFreeze(gzFile f, int Mode); + +#endif /* __CDROM_H__ */ diff --git a/branches/pcsx2_0.9.1/Common.h b/branches/pcsx2_0.9.1/Common.h new file mode 100644 index 0000000..f4d674a --- /dev/null +++ b/branches/pcsx2_0.9.1/Common.h @@ -0,0 +1,260 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include +#if defined(__WIN32__) + +#include + +typedef struct { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; +} AppData; + +extern AppData gApp; +#define pthread_mutex__unlock pthread_mutex_unlock + +#elif defined (__LINUX__) + +#include +#include // posix_memalign() +#define BOOL int + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +#define strnicmp strncasecmp +#define stricmp strcasecmp + +// Definitions added Feb 16, 2006 by efp +#define __declspec(x) +#define __forceinline inline +#define _aligned_malloc(x,y) posix_memalign(y,x) +#define _aligned_free(x) free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#endif + +#if defined(__MINGW32__) +#include +#include +#define BOOL int +#include // posix_memalign() +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +//#define max(a,b) (((a) > (b)) ? (a) : (b)) +//#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define __declspec(x) +#define __assume(x) ; +#define strnicmp strncasecmp +#define stricmp strcasecmp +#include +//#pragma intrinsic (InterlockedAnd) +// Definitions added Feb 16, 2006 by efp +//#define __declspec(x) +#include +#define __forceinline inline +#define _aligned_malloc(x,y) __mingw_aligned_malloc(x,y) +#define _aligned_free(x) __mingw_aligned_free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#define fpusqrtf sqrtf +#define fpufabsf fabsf +#define fpusinf sinf +#define fpucosf cosf +#define fpuexpf expf +#define fpuatanf atanf +#define fpuatan2f atan2f + +#endif +#ifdef ENABLE_NLS + +#ifdef __MSCW32__ +#include "libintlmsc.h" +#else +#include "libintl.h" +#endif + +#undef _ +#define _(String) dgettext (PACKAGE, String) +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif + +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +#include "PS2Etypes.h" + +#ifdef PCSX2_DEVBUILD + +typedef struct _TESTRUNARGS +{ + u8 enabled; + u8 jpgcapture; + int frame; // if < 0, frame is unlimited (run until crash). + int numimages; + int curimage; + u32 autopad; // mask for auto buttons + int efile; + int snapdone; + + char* ptitle; + char* pimagename; + char* plogname; + char* pgsdll, *pcdvddll, *pspudll; + +} TESTRUNARGS; + +extern TESTRUNARGS g_TestRun; + +#endif + +#define BIAS 2 // Bus is half of the actual ps2 speed +//#define PS2CLK 36864000 /* 294.912 mhz */ +//#define PSXCLK 9216000 /* 36.864 Mhz */ +//#define PSXCLK 186864000 /* 36.864 Mhz */ +#define PS2CLK 294912000 /* 294.912 mhz */ +#define PSXCLK 36864000 /* 36.864 Mhz */ + + +/* Config.PsxType == 1: PAL: + VBlank interlaced 50.00 Hz + VBlank non-interlaced 49.76 Hz + HBlank 15.625 KHz + Config.PsxType == 0: NSTC + VBlank interlaced 59.94 Hz + VBlank non-interlaced 59.82 Hz + HBlank 15.73426573 KHz */ +#define PS2VBLANK_NTSC_INT ((int)(PS2CLK / 59.94)) +#define PS2VBLANK_NTSC ((int)(PS2CLK / 59.82)) +#define PS2VBLANK_PAL_INT ((int)(PS2CLK / 50.00)) +#define PS2VBLANK_PAL ((int)(PS2CLK / 49.76)) +#define VBLANK_NTSC ((Config.PsxType & 2) ? 59.94 : 59.82) +#define VBLANK_PAL ((Config.PsxType & 2) ? 50.00 : 49.76) +#define HBLANK_NTSC (15734.26573) +#define HBLANK_PAL (15625) + +#define PS2HBLANK_NTSC ((int)(PS2CLK / HBLANK_NTSC)) +#define PS2HBLANK_PAL ((int)(PS2CLK / HBLANK_PAL)) +#define PS2HBLANK ((int)((Config.PsxType & 1) ? PS2HBLANK_PAL : PS2HBLANK_NTSC)) +#define PSXVBLANK_NTSC ((int)(PSXCLK / VBLANK_NTSC)) +#define PSXVBLANK_PAL ((int)(PSXCLK / VBLANK_PAL)) +#define PSXVBLANK ((int)((Config.PsxType & 1) ? PSXVBLANK_PAL : PSXVBLANK_NTSC)) +#define PSXHBLANK_NTSC ((int)(PSXCLK / HBLANK_NTSC)) +#define PSXHBLANK_PAL ((int)(PSXCLK / HBLANK_PAL)) +#define PSXHBLANK ((int)((Config.PsxType & 1) ? PSXHBLANK_PAL : PSXHBLANK_NTSC)) +#define PSXPIXEL ((int)(PSXCLK / 13500000)) +#define PSXSOUNDCLK ((int)(48000)) + +#define COLOR_BLACK "\033[30m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[32m" +#define COLOR_YELLOW "\033[33m" +#define COLOR_BLUE "\033[34m" +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" +#define COLOR_WHITE "\033[37m" +#define COLOR_RESET "\033[0m" + +#include // sync functions + +#include "R5900.h" +#include "Debug.h" +#include "System.h" +#include "Memory.h" +#include "Elfheader.h" +#include "Hw.h" +#include "GS.h" +#include "Vif.h" +#include "SPR.h" +#include "Sif.h" +#include "Plugins.h" +#include "PS2Edefs.h" +#include "Counters.h" +#include "IPU.h" +#include "Misc.h" +#include "Patch.h" +#include "Stats.h" +#include "COP0.h" +#include "VifDma.h" +#if (defined(__i386__) || defined(__x86_64__)) +#include "ix86/ix86.h" +#endif + +#define gzfreeze(ptr, size) \ + if (Mode == 1) gzwrite(f, ptr, size); \ + else if (Mode == 0) gzread(f, ptr, size); + +#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr)) + +int cdCaseopen; + +extern void __Log(char *fmt, ...); +extern u16 logProtocol; +extern u8 logSource; +#define PCSX2_VERSION "0.9.1" + +#ifdef __MSCW32__ +// C++ code for sqrtf +void InitFPUOps(); +extern float (*fpusqrtf)(float fval); +extern float (*fpufabsf)(float fval); +extern float (*fpusinf)(float fval); +extern float (*fpucosf)(float fval); +extern float (*fpuexpf)(float fval); +extern float (*fpuatanf)(float fval); +extern float (*fpuatan2f)(float fvalx, float fvaly); +#endif +// Added Feb 16, 2006 by efp +#ifdef __LINUX__ +#include // EBUSY +#endif /* __LINUX__ */ + +#define DESTROY_MUTEX(mutex) { \ + int err = pthread_mutex_destroy(&mutex); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#mutex"\n"); \ +} \ + +#define DESTROY_COND(cond) { \ + int err = pthread_cond_destroy(&cond); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#cond"\n"); \ +} \ + +#endif /* __COMMON_H__ */ diff --git a/branches/pcsx2_0.9.1/Counters.c b/branches/pcsx2_0.9.1/Counters.c new file mode 100644 index 0000000..36fad2f --- /dev/null +++ b/branches/pcsx2_0.9.1/Counters.c @@ -0,0 +1,493 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" + +int gates = 0; +u8 eehblankgate = 0; +int cnts = 5; +extern u8 psxhblankgate; +int hblankend = 1; +Counter counters[6]; +u32 nextCounter, nextsCounter; + +void rcntUpdTarget(int index) { + counters[index].sCycleT = cpuRegs.cycle; + counters[index].CycleT = (counters[index].target - rcntRcount(index)) * counters[index].rate; +} + +void rcntUpd(int index) { + counters[index].sCycle = cpuRegs.cycle; + counters[index].Cycle = (0xffff - (rcntRcount(index)&0xffff)) * counters[index].rate; + rcntUpdTarget(index); +} + +void rcntReset(int index) { + counters[index].count = 0; + counters[index].mode&= ~0x00400C00; + rcntUpd(index); +} + +void rcntSet() { + u32 c; + int i; + + nextCounter = 0xffff; + nextsCounter = cpuRegs.cycle; + + for (i = 0; i < 4; i++) { + if ((counters[i].mode & 0x380) < 0x80) continue; // Stopped + + if (counters[i].mode & 0x200){ + c = (0xffff - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + } + if ((counters[i].mode & 0x500) == 0x100){ + c = (counters[i].target - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + } + } + //Calculate HBlank + c = counters[4].CycleT - (cpuRegs.cycle - counters[4].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } + c = counters[5].CycleT - (cpuRegs.cycle - counters[5].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } +} + +void rcntInit() { + int i; + + memset(counters, 0, sizeof(counters)); + + for (i=0; i<4; i++) { + counters[i].rate = 2; + counters[i].target = 0xffff; + } + counters[0].interrupt = 9; + counters[1].interrupt = 10; + counters[2].interrupt = 11; + counters[3].interrupt = 12; + + counters[4].mode = 0x3c0; // The VSync counter mode + //counters[4].count = 0; + counters[5].mode = 0x3c0; + UpdateVSyncRate(); + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate; + counters[4].Cycle = counters[4].rate; + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate; + counters[5].Cycle = counters[5].rate; + for (i=0; i<4; i++) rcntUpd(i); + rcntSet(); +} + +void UpdateVSyncRate() { + if (Config.PsxType & 1) { + counters[4].rate = PS2HBLANK_PAL; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_PAL_INT; + else counters[5].rate = PS2VBLANK_PAL; + } else { + counters[4].rate = PS2HBLANK_NTSC; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_NTSC_INT; + else counters[5].rate = PS2VBLANK_NTSC; + } +} + + +#define NOSTATS + +// debug code, used for stats +int g_nCounters[4]; +extern u32 s_lastvsync[2]; +LARGE_INTEGER lfreq; +static int iFrame = 0; + +void FrameLimiter() +{ + static u32 dwStartTime = 0, dwEndTime = 0; + + // do over 4 frames instead of 1 + if( (iFrame&3) == 0 ) { + u32 frames = (Config.PsxType&1) ? (4000 / 50 -1) : (4000 / 60 - 1); + dwEndTime = timeGetTime(); + + if( dwEndTime < dwStartTime + frames ) { + Sleep(frames-(dwEndTime-dwStartTime)); + } + + dwStartTime = timeGetTime(); + } +} + +extern u32 CSRw; +extern u32 SuperVUGetRecTimes(int clear); +extern u32 vu0time; + +#include "VU.h" +void VSync() { + + //QueryPerformanceFrequency(&lfreq); + + if (counters[5].mode & 0x10000) { // VSync End (22 hsyncs) + + // swap the vsync field + u32 newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000; + *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; + iFrame++; + + // wait until GS stops + if( CHECK_MULTIGS ) { + GSRingBufVSync(newfield); + } + else { +#ifdef GSCAPTURE + extern u32 g_gstransnum; + g_gstransnum = 0; +#endif + GSvsync(newfield); + } + + //SysPrintf("c: %x, %x\n", cpuRegs.cycle, *(u32*)&VU1.Micro[16]); + //if( (iFrame%20) == 0 ) SysPrintf("svu time: %d\n", SuperVUGetRecTimes(1)); +// if( (iFrame%10) == 0 ) { +// SysPrintf("vu0 time: %d\n", vu0time); +// vu0time = 0; +// } + + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled && g_TestRun.frame > 0 ) { + if( iFrame > g_TestRun.frame ) { + // take a snapshot + if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) { + if( g_TestRun.snapdone ) { + g_TestRun.curimage++; + g_TestRun.snapdone = 0; + g_TestRun.frame += 20; + if( g_TestRun.curimage >= g_TestRun.numimages ) { + // exit + SysClose(); + exit(0); + } + } + else { + // query for the image + GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture); + } + } + else { + // exit + SysClose(); + exit(0); + } + } + } +#endif + + if( CHECK_FRAMELIMIT ) FrameLimiter(); + + counters[5].mode&= ~0x10000; + //UpdateVSyncRate(); + GSCSRr |= 8; // signal + if (CSRw & 0x8){ + CSRw &= ~8; + if (!(GSIMR&0x800) ) + gsIrq(); + } + hwIntcIrq(3); + psxVSyncEnd(); +#ifndef NOSTATS + statsVSync(); +#endif + if(gates)rcntEndGate(0x8); + SysUpdate(); + } else { // VSync Start (240 hsyncs) + //UpdateVSyncRateEnd(); + + //SysPrintf("ctrs: %d %d %d %d\n", g_nCounters[0], g_nCounters[1], g_nCounters[2], g_nCounters[3]); + //SysPrintf("vif: %d\n", (((LARGE_INTEGER*)g_nCounters)->QuadPart * 1000000) / lfreq.QuadPart); + //memset(g_nCounters, 0, 16); + counters[5].mode|= 0x10000; + //GSCSRr|= 0x8; + hwIntcIrq(2); + psxVSyncStart(); + + if(Config.Patch) applypatch(1); + if(gates)rcntStartGate(0x8); + +// __Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]); +// s_lastvsync[0] = timeGetTime(); +// s_lastvsync[1] = cpuRegs.cycle; + } +} + + + +void rcntUpdate() { + int i; + + for (i=0; i<=3; i++) { + if ((counters[i].mode & 0x380) < 0x80) continue; // Stopped + + + + if (rcntCycle(i) >= counters[i].target) { // Target interrupt + if ((counters[i].mode & 0x500) == 0x100) { // 0x400 == 0 so target interrupt hasnt happened + counters[i].mode|= 0x0400; // Target flag + //counters[i].mode&= ~0x800; + + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] target interrupt (%x)\n", i, cpuRegs.cycle); + } + if (counters[i].mode & 0x40) { // Reset on target + counters[i].count = 0; + rcntUpd(i); + } + } + + + + if (rcntCycle(i) >= 0xffff) { + if (counters[i].mode & 0x0200) { // Overflow interrupt + counters[i].mode|= 0x0800; // Overflow flag + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle); + } + counters[i].count = 0; + rcntUpd(i); + } + + } + + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT / 2 && hblankend == 0){ + GSCSRr |= 4; // signal + if (CSRw & 0x4){ + CSRw &= ~4; + if (!(GSIMR&0x400) ) + gsIrq(); + } + if(eehblankgate)rcntEndGate(0); + if(psxhblankgate)psxCheckEndGate(0); + hblankend = 1; + } + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT) { + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate; + counters[4].Cycle = counters[4].rate; + + + if(gates)rcntStartGate(0); + psxCheckStartGate(0); + hblankend = 0; + } + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT / 2 && (counters[5].mode & 0x10000)) VSync(); + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) { + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate; + counters[5].Cycle = counters[5].rate; + VSync(); + } + rcntSet(); +} + +void rcntWcount(int index, u32 value) { + //SysPrintf ("writeCcount[%d] = %x\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE count write %d count %x eecycle %x\n", index, counters[index].count, cpuRegs.eCycle); +#endif + + //counters[index].mode &= ~0x00400C00; + counters[index].count = value; + rcntUpd(index); + rcntSet(); +} + +void rcntWmode(int index, u32 value) { +// SysPrintf ("writeCmode[%ld] = %lx\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE counter set %d mode %x\n", index, counters[index].mode); +#endif + if (value & 0xc00) { + counters[index].mode &= ~(value & 0xc00); + } + /*if ((counters[index].mode & 0x37F) == (value & 0x37f)){ //Stop Counting + if((counters[index].mode & 0x80) != (value & 0x80)){ + SysPrintf("EE Counter %x %s\n", index, (counters[index].mode & 0x80) ? "stopped" : "started"); + if(counters[index].mode & 0x80) counters[index].count = rcntRcount(index); + counters[index].mode ^= 0x80; + rcntUpd(index); + } + rcntSet(); + return; + }*/ + if(!(value & 0x80)){ + counters[index].count = rcntRcount(index); + rcntUpd(index); + } + +counters[index].mode = (value & 0x3ff) | (counters[index].mode & 0xc00); + + + switch (value & 0x3) { //Clock rate divisers *2, they use BUSCLK speed not PS2CLK + case 0: counters[index].rate = 2; break; + case 1: counters[index].rate = 32; break; + case 2: counters[index].rate = 512; break; + case 3: counters[index].rate = PS2HBLANK; break; + } + + if((counters[index].mode & 0xF) == 0x7) { + gates &= ~(1<> 4){ + case 0x0: //Count When Signal is low (off) + counters[i].count = rcntRcount(i); + //rcntUpd(i); + counters[i].mode &= ~0x80; + break; + case 0x1: //Reset and start counting on Vsync start + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x2: //Reset and start counting on Vsync end + //Do Nothing + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntEndGate(int mode){ + int i; + + for(i=0; i <=3; i++){ //Gates for counters + if(!(gates & (1<> 4){ + case 0x0: //Count When Signal is low (off) + rcntUpd(i); + counters[i].mode |= 0x80; + break; + case 0x1: //Reset and start counting on Vsync start + //Do Nothing + break; + case 0x2: //Reset and start counting on Vsync end + rcntReset(i); + counters[i].mode |= 0x80; + break; + case 0x3: //Reset and start counting on Vsync start and end + rcntReset(i); + counters[i].mode |= 0x80; + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntWtarget(int index, u32 value) { + //SysPrintf ("writeCtarget[%ld] = %lx\n", index, value); +#ifdef PSXCNT_LOG + PSXCNT_LOG("EE target write %d target %x eecycle %x\n", index, counters[index].target, cpuRegs.eCycle); +#endif + counters[index].target = value; + //counters[index].mode &= ~0x00400400; + counters[index].CycleT = (counters[index].target - rcntRcount(index)) * counters[index].rate; + //rcntUpdTarget(index); + rcntSet(); +} + +void rcntWhold(int index, u32 value) { + //SysPrintf ("writeChold[%ld] = %lx\n", index, value); + counters[index].hold = value; + //rcntUpd(index); + //rcntSet(); +} + +u16 rcntRcount(int index) { + u16 ret; + if ((counters[index].mode & 0x80)) { + ret = counters[index].count + ((cpuRegs.cycle - counters[index].sCycle) / counters[index].rate); + }else{ + ret = counters[index].count; + } +// SysPrintf("rcntRcount[%d] %x\n", index, ret); + return (u16)ret; +} + +u32 rcntCycle(int index) { + + if ((counters[index].mode & 0x80)) { + return counters[index].count + ((cpuRegs.cycle - counters[index].sCycle) / counters[index].rate); + }else{ + return counters[index].count; + } +} + +int rcntFreeze(gzFile f, int Mode) { + gzfreezel(counters); + gzfreeze(&nextCounter, sizeof(nextCounter)); + gzfreeze(&nextsCounter, sizeof(nextsCounter)); + + return 0; +} + diff --git a/branches/pcsx2_0.9.1/Counters.h b/branches/pcsx2_0.9.1/Counters.h new file mode 100644 index 0000000..8db0188 --- /dev/null +++ b/branches/pcsx2_0.9.1/Counters.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COUNTERS_H__ +#define __COUNTERS_H__ + +typedef struct { + u32 count, mode, target, hold; + u32 rate, interrupt; + u32 Cycle, sCycle; + u32 CycleT, sCycleT; +} Counter; + +extern Counter counters[6]; +extern u32 nextCounter, nextsCounter; + +void rcntInit(); +void rcntUpdate(); +void rcntStartGate(int mode); +void rcntEndGate(int mode); +void rcntWcount(int index, u32 value); +void rcntWmode(int index, u32 value); +void rcntWtarget(int index, u32 value); +void rcntWhold(int index, u32 value); +u16 rcntRcount(int index); +u32 rcntCycle(int index); +int rcntFreeze(gzFile f, int Mode); + +void UpdateVSyncRate(); + +#endif /* __COUNTERS_H__ */ diff --git a/branches/pcsx2_0.9.1/DebugTools/Debug.h b/branches/pcsx2_0.9.1/DebugTools/Debug.h new file mode 100644 index 0000000..d597533 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/Debug.h @@ -0,0 +1,135 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "Common.h" + +FILE *emuLog; + +char* disR5900F(u32 code, u32 pc); +char* disR5900Fasm(u32 code, u32 pc); +char* disR3000Fasm(u32 code, u32 pc); + +void disR5900AddSym(u32 addr, char *name); +char* disR5900GetSym(u32 addr); +char* disR5900GetUpperSym(u32 addr); +void disR5900FreeSyms(); + +char* disVU0MicroUF(u32 code, u32 pc); +char* disVU0MicroLF(u32 code, u32 pc); +char* disVU1MicroUF(u32 code, u32 pc); +char* disVU1MicroLF(u32 code, u32 pc); + +char* disR3000AF(u32 code, u32 pc); + +extern char *CP2VFnames[]; +extern char *disRNameCP2f[]; +extern char *disRNameCP2i[]; + +//that way is slower but you now not need to compile every time ;P +#ifdef PCSX2_DEVBUILD + +int Log; +u32 varLog; + +//memcars has the same number as PAD_LOG +#define MEMCARDS_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log + +#define CPU_LOG if (varLog & 0x00000001) {logProtocol=1; logSource='E';} if (varLog & 0x00000001) __Log +#define MEM_LOG if (varLog & 0x00000002) {logProtocol=6; logSource='E';} if (varLog & 0x00000002) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000002) __Log +#define HW_LOG if (varLog & 0x00000004) {logProtocol=6; logSource='E';} if (varLog & 0x00000004) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000004) __Log +#define DMA_LOG if (varLog & 0x00000008) {logProtocol=5; logSource='E';} if (varLog & 0x00000008) __Log +#define BIOS_LOG if (varLog & 0x00000010) {logProtocol=0; logSource='E';} if (varLog & 0x00000010) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000010) __Log +#define ELF_LOG if (varLog & 0x00000020) {logProtocol=7; logSource='E';} if (varLog & 0x00000020) __Log +#define FPU_LOG if (varLog & 0x00000040) {logProtocol=1; logSource='E';} if (varLog & 0x00000040) __Log +#define MMI_LOG if (varLog & 0x00000080) {logProtocol=1; logSource='E';} if (varLog & 0x00000080) __Log +#define VU0_LOG if (varLog & 0x00000100) {logProtocol=2; logSource='E';} if (varLog & 0x00000100) __Log +#define COP0_LOG if (varLog & 0x00000200) {logProtocol=1; logSource='E';} if (varLog & 0x00000200) __Log +#define VIF_LOG if (varLog & 0x00000400) {logProtocol=3; logSource='E';} if (varLog & 0x00000400) __Log +#define SPR_LOG if (varLog & 0x00000800) {logProtocol=7; logSource='E';} if (varLog & 0x00000800) __Log +#define GIF_LOG if (varLog & 0x00001000) {logProtocol=4; logSource='E';} if (varLog & 0x00001000) __Log +#define SIF_LOG if (varLog & 0x00002000) {logProtocol=9; logSource='E';} if (varLog & 0x00002000) __Log +#define IPU_LOG if (varLog & 0x00004000) {logProtocol=8; logSource='E';} if (varLog & 0x00004000) __Log +#define VUM_LOG if (varLog & 0x00008000) {logProtocol=2; logSource='E';} if (varLog & 0x00008000) __Log +#define RPC_LOG if (varLog & 0x00010000) {logProtocol=9; logSource='E';} if (varLog & 0x00010000) __Log + +#define PSXCPU_LOG if (varLog & 0x00100000) {logProtocol=1; logSource='I';} if (varLog & 0x00100000) __Log +#define PSXMEM_LOG if (varLog & 0x00200000) {logProtocol=6; logSource='I';} if (varLog & 0x00200000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00200000) __Log +#define PSXHW_LOG if (varLog & 0x00400000) {logProtocol=2; logSource='I';} if (varLog & 0x00400000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00400000) __Log +#define PSXBIOS_LOG if (varLog & 0x00800000) {logProtocol=0; logSource='I';} if (varLog & 0x00800000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00800000) __Log +#define PSXDMA_LOG if (varLog & 0x01000000) {logProtocol=5; logSource='I';} if (varLog & 0x01000000) __Log + +#define PAD_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log +#define GTE_LOG if (varLog & 0x04000000) {logProtocol=3; logSource='I';} if (varLog & 0x04000000) __Log +#define CDR_LOG if (varLog & 0x08000000) {logProtocol=8; logSource='I';} if (varLog & 0x08000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x08000000) __Log +#define GPU_LOG if (varLog & 0x10000000) {logProtocol=4; logSource='I';} if (varLog & 0x10000000) __Log +#define PSXCNT_LOG if (varLog & 0x20000000) {logProtocol=0; logSource='I';} if (varLog & 0x20000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x20000000) __Log + +#if defined (CPU_LOG) || defined(MEM_LOG) || defined(HW_LOG) || defined(DMA_LOG) || \ + defined(BIOS_LOG) || defined(ELF_LOG) || defined(FPU_LOG) || defined(MMI_LOG) || \ + defined(VU0_LOG) || defined(COP0_LOG) || defined(VIF_LOG) || defined(SPR_LOG) || \ + defined(GIF_LOG) || defined(SIF_LOG) || defined(IPU_LOG) || defined(VUM_log) || \ + defined(PSXCPU_LOG) || defined(PSXMEM_LOG)|| defined(IOPBIOS_LOG)|| defined(IOPHW_LOG)|| \ + defined(PAD_LOG) || defined(GTE_LOG) || defined(CDR_LOG) || defined(GPU_LOG) || \ + defined(MEMCARDS_LOG)|| defined(PSXCNT_LOG) +#define EMU_LOG __Log +#endif + +#else // PCSX2_DEVBUILD + +#define varLog 0 +#define Log 0 + +#define CPU_LOG 0&& +#define MEM_LOG 0&& +#define HW_LOG 0&& +#define DMA_LOG 0&& +#define BIOS_LOG 0&& +#define ELF_LOG 0&& +#define FPU_LOG 0&& +#define MMI_LOG 0&& +#define VU0_LOG 0&& +#define COP0_LOG 0&& +#define VIF_LOG 0&& +#define SPR_LOG 0&& +#define GIF_LOG 0&& +#define SIF_LOG 0&& +#define IPU_LOG 0&& +#define VUM_LOG 0&& +#define RPC_LOG 0&& + +#define PSXCPU_LOG 0&& +#define PSXMEM_LOG 0&& +#define PSXHW_LOG 0&& +#define PSXBIOS_LOG 0&& +#define PSXDMA_LOG 0&& + +#define PAD_LOG 0&& +#define GTE_LOG 0&& +#define CDR_LOG 0&& +#define GPU_LOG 0&& +#define PSXCNT_LOG 0&& + +#define EMU_LOG 0&& + +#endif + +#endif /* __DEBUG_H__ */ diff --git a/branches/pcsx2_0.9.1/DebugTools/DisASM.h b/branches/pcsx2_0.9.1/DebugTools/DisASM.h new file mode 100644 index 0000000..ceb5917 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisASM.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "R5900.h" + +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +///******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) + +//IOP + +#define DECODE_RD_IOP ((psxRegs.code >> 11) & 0x1F) +#define DECODE_RT_IOP ((psxRegs.code >> 16) & 0x1F) +#define DECODE_RS_IOP ((psxRegs.code >> 21) & 0x1F) +#define DECODE_IMMED_IOP ( psxRegs.code & 0xFFFF) +#define DECODE_SA_IOP ((psxRegs.code >> 6) & 0x1F) +#define DECODE_FS_IOP (DECODE_RD_IOP) + diff --git a/branches/pcsx2_0.9.1/DebugTools/DisR3000A.c b/branches/pcsx2_0.9.1/DebugTools/DisR3000A.c new file mode 100644 index 0000000..d0dad71 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisR3000A.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Debug.h" + +char ostr[256]; + +// Names of registers +static char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"}; + +static char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + + +// Type deffinition of our functions + +typedef char* (*TdisR3000AF)(u32 code, u32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; } +#define MakeDisF(fn, b) \ + static char* fn(u32 code, u32 pc) { \ + sprintf (ostr, "%8.8lx %8.8lx:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + + +#include "R3000A.h" + +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ +#undef _Target_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i]) +#define dCP0(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i]) +#define dHI() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.hi, "hi") +#define dLO() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.lo, "lo") +#define dImm() sprintf(ostr, "%s %4.4lx (%ld),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8lx,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2lx (%ld),", ostr, _Sa_, _Sa_) +#define dOfB() sprintf(ostr, "%s %4.4lx (%8.8lx (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8lx,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8lx,", ostr, (code >> 6) & 0xffffff) + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();) +MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();) +MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, dName("BREAK")) +MakeDisF(disRFE, dName("RFE")) +MakeDisF(disSYSCALL, dName("SYSCALL")) + + + +MakeDisF(disRTPS, dName("RTPS")) +MakeDisF(disOP , dName("OP")) +MakeDisF(disNCLIP, dName("NCLIP")) +MakeDisF(disDPCS, dName("DPCS")) +MakeDisF(disINTPL, dName("INTPL")) +MakeDisF(disMVMVA, dName("MVMVA")) +MakeDisF(disNCDS , dName("NCDS")) +MakeDisF(disCDP , dName("CDP")) +MakeDisF(disNCDT , dName("NCDT")) +MakeDisF(disNCCS , dName("NCCS")) +MakeDisF(disCC , dName("CC")) +MakeDisF(disNCS , dName("NCS")) +MakeDisF(disNCT , dName("NCT")) +MakeDisF(disSQR , dName("SQR")) +MakeDisF(disDCPL , dName("DCPL")) +MakeDisF(disDPCT , dName("DPCT")) +MakeDisF(disAVSZ3, dName("AVSZ3")) +MakeDisF(disAVSZ4, dName("AVSZ4")) +MakeDisF(disRTPT , dName("RTPT")) +MakeDisF(disGPF , dName("GPF")) +MakeDisF(disGPL , dName("GPL")) +MakeDisF(disNCCT , dName("NCCT")) + +MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);) +MakeDisF(disMTC2, dName("MTC2")) +MakeDisF(disCTC2, dName("CTC2")) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget();) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR(_Rs_);) +MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_)) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disNULL , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/branches/pcsx2_0.9.1/DebugTools/DisR3000asm.c b/branches/pcsx2_0.9.1/DebugTools/DisR3000asm.c new file mode 100644 index 0000000..d2e0612 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisR3000asm.c @@ -0,0 +1,361 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "R3000A.h" +#include "DisASM.h" + +unsigned long IOP_opcode_addr; + +char *GPR_IOP_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_IOP_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +void IOPD_SPECIAL(char *buf); +void IOPD_REGIMM(char *buf); +void IOPD_J(char *buf); +void IOPD_JAL(char *buf); +void IOPD_BEQ(char *buf); +void IOPD_BNE(char *buf); +void IOPD_BLEZ(char *buf); +void IOPD_BGTZ(char *buf); +void IOPD_ADDI(char *buf); +void IOPD_ADDIU(char *buf); +void IOPD_SLTI(char *buf); +void IOPD_SLTIU(char *buf); +void IOPD_ANDI(char *buf); +void IOPD_ORI(char *buf); +void IOPD_XORI(char *buf); +void IOPD_LUI(char *buf); +void IOPD_COP0(char *buf); +void IOPD_COP2(char *buf); +void IOPD_LB(char *buf); +void IOPD_LH(char *buf); +void IOPD_LWL(char *buf); +void IOPD_LW(char *buf); +void IOPD_LBU(char *buf); +void IOPD_LHU(char *buf); +void IOPD_LWR(char *buf); +void IOPD_SB(char *buf); +void IOPD_SH(char *buf); +void IOPD_SWL(char *buf); +void IOPD_SW(char *buf); +void IOPD_SWR(char *buf); +void IOPD_LWC2(char *buf); +void IOPD_SWC2(char *buf); + +void IOPD_SLL(char *buf); +void IOPD_SRL(char *buf); +void IOPD_SRA(char *buf); +void IOPD_SLLV(char *buf); +void IOPD_SRLV(char *buf); +void IOPD_SRAV(char *buf); +void IOPD_JR(char *buf); +void IOPD_JALR(char *buf); +void IOPD_SYSCALL(char *buf); +void IOPD_BREAK(char *buf); +void IOPD_MFHI(char *buf); +void IOPD_MTHI(char *buf); +void IOPD_MFLO(char *buf); +void IOPD_MTLO(char *buf); +void IOPD_MULT(char *buf); +void IOPD_MULTU(char *buf); +void IOPD_DIV(char *buf); +void IOPD_DIVU(char *buf); +void IOPD_ADD(char *buf); +void IOPD_ADDU(char *buf); +void IOPD_SUB(char *buf); +void IOPD_SUBU(char *buf); +void IOPD_AND(char *buf); +void IOPD_OR(char *buf); +void IOPD_XOR(char *buf); +void IOPD_NOR(char *buf); +void IOPD_SLT(char *buf); +void IOPD_SLTU(char *buf); + + +void IOPD_BLTZ(char *buf); +void IOPD_BGEZ(char *buf); +void IOPD_BLTZAL(char *buf); +void IOPD_BGEZAL(char *buf); + + + +void IOPD_MFC0(char *buf); +void IOPD_CFC0(char *buf); +void IOPD_MTC0(char *buf); +void IOPD_CTC0(char *buf); +void IOPD_RFE(char *buf); + + + +void IOPD_BASIC(char *buf); +void IOPD_RTPS(char *buf); +void IOPD_NCLIP(char *buf); +void IOPD_OP(char *buf); +void IOPD_DPCS(char *buf); +void IOPD_INTPL(char *buf); +void IOPD_MVMVA(char *buf); +void IOPD_NCDS(char *buf); +void IOPD_CDP(char *buf); +void IOPD_NCDT(char *buf); +void IOPD_NCCS(char *buf); +void IOPD_CC(char *buf); +void IOPD_NCS(char *buf); +void IOPD_NCT(char *buf); +void IOPD_SQR(char *buf); +void IOPD_DCPL(char *buf); +void IOPD_DPCT(char *buf); +void IOPD_AVSZ3(char *buf); +void IOPD_AVSZ4(char *buf); +void IOPD_RTPT(char *buf); +void IOPD_GPF(char *buf); +void IOPD_GPL(char *buf); +void IOPD_NCCT(char *buf); + + + +void IOPD_MFC2(char *buf); +void IOPD_CFC2(char *buf); +void IOPD_MTC2(char *buf); +void IOPD_CTC2(char *buf); +void IOPD_NULL(char *buf); + + + + void (*IOP_DEBUG_BSC[64])(char *buf) = { + IOPD_SPECIAL, IOPD_REGIMM, IOPD_J , IOPD_JAL , IOPD_BEQ , IOPD_BNE , IOPD_BLEZ, IOPD_BGTZ, + IOPD_ADDI , IOPD_ADDIU , IOPD_SLTI, IOPD_SLTIU, IOPD_ANDI, IOPD_ORI , IOPD_XORI, IOPD_LUI , + IOPD_COP0 , IOPD_NULL , IOPD_COP2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_LB , IOPD_LH , IOPD_LWL , IOPD_LW , IOPD_LBU , IOPD_LHU , IOPD_LWR , IOPD_NULL, + IOPD_SB , IOPD_SH , IOPD_SWL , IOPD_SW , IOPD_NULL, IOPD_NULL, IOPD_SWR , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_LWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_SWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + + +void (*IOP_DEBUG_SPC[64])(char *buf) = { + IOPD_SLL , IOPD_NULL , IOPD_SRL , IOPD_SRA , IOPD_SLLV , IOPD_NULL , IOPD_SRLV, IOPD_SRAV, + IOPD_JR , IOPD_JALR , IOPD_NULL, IOPD_NULL, IOPD_SYSCALL, IOPD_BREAK, IOPD_NULL, IOPD_NULL, + IOPD_MFHI, IOPD_MTHI , IOPD_MFLO, IOPD_MTLO, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_MULT, IOPD_MULTU, IOPD_DIV , IOPD_DIVU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_ADD , IOPD_ADDU , IOPD_SUB , IOPD_SUBU, IOPD_AND , IOPD_OR , IOPD_XOR , IOPD_NOR , + IOPD_NULL, IOPD_NULL , IOPD_SLT , IOPD_SLTU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_REG[32])(char *buf) = { + IOPD_BLTZ , IOPD_BGEZ , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_BLTZAL, IOPD_BGEZAL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP0[32])(char *buf) = { + IOPD_MFC0, IOPD_NULL, IOPD_CFC0, IOPD_NULL, IOPD_MTC0, IOPD_NULL, IOPD_CTC0, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_RFE , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP2[64])(char *buf) = { + IOPD_BASIC, IOPD_RTPS , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NCLIP, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_OP , IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_DPCS , IOPD_INTPL, IOPD_MVMVA, IOPD_NCDS, IOPD_CDP , IOPD_NULL , IOPD_NCDT , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NCCS, IOPD_CC , IOPD_NULL , IOPD_NCS , IOPD_NULL, + IOPD_NCT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_SQR , IOPD_DCPL , IOPD_DPCT , IOPD_NULL, IOPD_NULL, IOPD_AVSZ3, IOPD_AVSZ4, IOPD_NULL, + IOPD_RTPT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_GPF , IOPD_GPL , IOPD_NCCT +}; + +void (*IOP_DEBUG_CP2BSC[32])(char *buf) = { + IOPD_MFC2, IOPD_NULL, IOPD_CFC2, IOPD_NULL, IOPD_MTC2, IOPD_NULL, IOPD_CTC2, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +static char dbuf2[1024]; +static char obuf2[1024]; + +char *disR3000Fasm(u32 code, u32 pc) { + u32 scode = psxRegs.code; + IOP_opcode_addr = pc; + psxRegs.code = code; + IOP_DEBUG_BSC[(code) >> 26](dbuf2); + + sprintf(obuf2, "%08lX:\t%s", pc, dbuf2); + + psxRegs.code = scode; + return obuf2; +} +char *IOP_jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = (IOP_opcode_addr & 0xf0000000)|((psxRegs.code&0x3ffffff)<<2); + sprintf(buf, "0x%08lX", addr); + return buf; +} +char *IOP_offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = ((((short)( psxRegs.code & 0xFFFF) * 4) + IOP_opcode_addr + 4)); + sprintf(buf, "0x%08lX", addr); + return buf; +} +//basic table +void IOPD_SPECIAL(char *buf){IOP_DEBUG_SPC[((psxRegs.code) & 0x3F)](buf);} +void IOPD_REGIMM(char *buf){IOP_DEBUG_REG[DECODE_RT_IOP](buf);} +void IOPD_J(char *buf) { sprintf(buf, "j\t%s", IOP_jump_decode());} +void IOPD_JAL(char *buf){sprintf(buf, "jal\t%s", IOP_jump_decode());} +void IOPD_BEQ(char *buf){sprintf(buf, "beq\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BNE(char *buf){sprintf(buf, "bne\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BLEZ(char *buf){sprintf(buf, "blez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGTZ(char *buf){sprintf(buf, "bgtz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_ADDI(char *buf){sprintf(buf, "addi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ADDIU(char *buf){sprintf(buf, "addiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTI(char *buf){sprintf(buf, "slti\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTIU(char *buf){sprintf(buf, "sltiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ANDI(char *buf){sprintf(buf, "andi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ORI(char *buf){sprintf(buf, "ori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_XORI(char *buf){sprintf(buf, "xori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_LUI(char *buf){sprintf(buf, "lui\t%s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP); } +void IOPD_COP0(char *buf){IOP_DEBUG_CP0[DECODE_RS_IOP](buf);} +void IOPD_COP2(char *buf){IOP_DEBUG_CP2[((psxRegs.code) & 0x3F)](buf);} +void IOPD_LB(char *buf){sprintf(buf, "lb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LH(char *buf){sprintf(buf, "lh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWL(char *buf){sprintf(buf, "lwl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LW(char *buf){sprintf(buf, "lw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LBU(char *buf){sprintf(buf, "lbu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LHU(char *buf){sprintf(buf, "lhu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWR(char *buf){sprintf(buf, "lwr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SB(char *buf){sprintf(buf, "sb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SH(char *buf){sprintf(buf, "sh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWL(char *buf){sprintf(buf, "swl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SW(char *buf){sprintf(buf, "sw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWR(char *buf){sprintf(buf, "swr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_LWC2(char *buf){strcpy(buf, "lwc2");} +void IOPD_SWC2(char *buf){strcpy(buf, "swc2");} +//special table +void IOPD_SLL(char *buf) +{ + if (psxRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); +} +void IOPD_SRL(char *buf){sprintf(buf, "srl\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); } +void IOPD_SRA(char *buf){sprintf(buf, "sra\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP);} +void IOPD_SLLV(char *buf){sprintf(buf, "sllv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SRLV(char *buf){sprintf(buf, "srlv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SRAV(char *buf){sprintf(buf, "srav\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_JR(char *buf){sprintf(buf, "jr\t%s", GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_JALR(char *buf) +{ + int rd = DECODE_RD_IOP; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_IOP_REG[DECODE_RS_IOP]); + else + sprintf(buf, "jalr\t%s, %s", GPR_IOP_REG[rd], GPR_IOP_REG[DECODE_RS_IOP]); +} + +void IOPD_SYSCALL(char *buf){strcpy(buf, "syscall");} +void IOPD_BREAK(char *buf){strcpy(buf, "break");} +void IOPD_MFHI(char *buf){sprintf(buf, "mfhi\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTHI(char *buf){sprintf(buf, "mthi\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MFLO(char *buf){sprintf(buf, "mflo\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTLO(char *buf){sprintf(buf, "mtlo\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MULT(char *buf){sprintf(buf, "mult\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_MULTU(char *buf){sprintf(buf, "multu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIV(char *buf){sprintf(buf, "div\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIVU(char *buf){sprintf(buf, "divu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } + +void IOPD_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +//regimm + +void IOPD_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } + +//cop0 + +void IOPD_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CFC0(char *buf){ sprintf(buf, "cfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CTC0(char *buf){ sprintf(buf, "ctc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_RFE(char *buf){strcpy(buf, "rfe");} +//cop2 +void IOPD_BASIC(char *buf){IOP_DEBUG_CP2BSC[DECODE_RS_IOP](buf);} +void IOPD_RTPS(char *buf){strcpy(buf, "rtps");} +void IOPD_NCLIP(char *buf){strcpy(buf, "nclip");} +void IOPD_OP(char *buf){strcpy(buf, "op");} +void IOPD_DPCS(char *buf){strcpy(buf, "dpcs");} +void IOPD_INTPL(char *buf){strcpy(buf, "intpl");} +void IOPD_MVMVA(char *buf){strcpy(buf, "mvmva");} +void IOPD_NCDS(char *buf){strcpy(buf, "ncds");} +void IOPD_CDP(char *buf){strcpy(buf, "cdp");} +void IOPD_NCDT(char *buf){strcpy(buf, "ncdt");} +void IOPD_NCCS(char *buf){strcpy(buf, "nccs");} +void IOPD_CC(char *buf){strcpy(buf, "cc");} +void IOPD_NCS(char *buf){strcpy(buf, "ncs");} +void IOPD_NCT(char *buf){strcpy(buf, "nct");} +void IOPD_SQR(char *buf){strcpy(buf, "sqr");} +void IOPD_DCPL(char *buf){strcpy(buf, "dcpl");} +void IOPD_DPCT(char *buf){strcpy(buf, "dpct");} +void IOPD_AVSZ3(char *buf){strcpy(buf, "avsz3");} +void IOPD_AVSZ4(char *buf){strcpy(buf, "avsz4");} +void IOPD_RTPT(char *buf){strcpy(buf, "rtpt");} +void IOPD_GPF(char *buf){strcpy(buf, "gpf");} +void IOPD_GPL(char *buf){strcpy(buf, "gpl");} +void IOPD_NCCT(char *buf){strcpy(buf, "ncct");} +//cop2 basic +void IOPD_MFC2(char *buf){strcpy(buf, "mfc2");} +void IOPD_CFC2(char *buf){strcpy(buf, "cfc2");} +void IOPD_MTC2(char *buf){strcpy(buf, "mtc2");} +void IOPD_CTC2(char *buf){strcpy(buf, "ctc2");} +//null +void IOPD_NULL(char *buf){strcpy(buf, "????");} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/DebugTools/DisR5900.c b/branches/pcsx2_0.9.1/DebugTools/DisR5900.c new file mode 100644 index 0000000..28ef02c --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisR5900.c @@ -0,0 +1,993 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VU.h" + +long jumpMode; +char ostr[1024]; + +// Names of registers +char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra", "hi", "lo"}; // lo,hi used in rec + +char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0" , "EntryLo1", "Context" , "PageMask" , "Wired" , "*RES*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID", + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "*RES*" , "*RES*" , "*RES*" , "Debug", + "DEPC" , "PerfCnt" , "ErrCtl" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "DESAVE"}; + +char *disRNameCP1[] = { + "FPR0" , "FPR1" , "FPR2" , "FPR3" , "FPR4" , "FPR5" , "FPR6" , "FPR7", + "FPR8" , "FPR9" , "FPR10", "FPR11", "FPR12", "FPR13", "FPR14", "FPR15", + "FPR16", "FPR17", "FPR18", "FPR19", "FPR20", "FPR21", "FPR22", "FPR23", + "FPR24", "FPR25", "FPR26", "FPR27", "FPR28", "FPR29", "FPR30", "FPR31"}; + +char *disRNameCP1c[] = { + "FRevID", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "FStatus"}; + +char *disRNameCP2f[] = { + "VF00", "VF01", "VF02", "VF03", "VF04", "VF05", "VF06", "VF07", + "VF08", "VF09", "VF10", "VF11", "VF12", "VF13", "VF14", "VF15", + "VF16", "VF17", "VF18", "VF19", "VF20", "VF21", "VF22", "VF23", + "VF24", "VF25", "VF26", "VF27", "VF28", "VF29", "VF30", "VF31"}; + +char *disRNameCP2i[] = { + "VI00", "VI01", "VI02", "VI03", "VI04", "VI05", "VI06", "VI07", + "VI08", "VI09", "VI10", "VI11", "VI12", "VI13", "VI14", "VI15", + "Status", "MAC", "Clip", "*RES*", "R", "I", "Q", "*RES*", + "*RES*", "*RES*", "TPC", "CMSAR0", "FBRST", "VPU-STAT", "*RES*", "CMSAR1"}; + +char *CP2VFnames[] = { "x", "y", "z", "w" }; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +#undef _Target_ +#undef _Branch_ +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + + +#define _rRs_ cpuRegs.GPR.r[_Rs_].UL[1], cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt_ cpuRegs.GPR.r[_Rt_].UL[1], cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd_ cpuRegs.GPR.r[_Rd_].UL[1], cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa_ cpuRegs.GPR.r[_Sa_].UL[1], cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + +#define _rFs_ cpuRegs.CP0.r[_Rd_] // Fs register + +#define _rRs32_ cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt32_ cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd32_ cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa32_ cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + + +#define _nRs_ _rRs_, disRNameGPR[_Rs_] +#define _nRt_ _rRt_, disRNameGPR[_Rt_] +#define _nRd_ _rRd_, disRNameGPR[_Rd_] +#define _nSa_ _rSa_, disRNameGPR[_Sa_] +#define _nRd0_ _rFs_, disRNameCP0[_Rd_] + +#define _nRs32_ _rRs32_, disRNameGPR[_Rs_] +#define _nRt32_ _rRt32_, disRNameGPR[_Rt_] +#define _nRd32_ _rRd32_, disRNameGPR[_Rd_] +#define _nSa32_ _rSa32_, disRNameGPR[_Sa_] + +#define _I_ _Im_, _Im_ +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR128(i) sprintf(ostr, "%s %8.8x_%8.8x_%8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64U(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], disRNameGPR[i]) +#define dGPR32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) + +#define dCP032(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.CP0.r[i], disRNameCP0[i]) + +#define dCP132(i) sprintf(ostr, "%s %f (%s),", ostr, fpuRegs.fpr[i].f, disRNameCP1[i]) +#define dCP1c32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, fpuRegs.fprc[i], disRNameCP1c[i]) +#define dCP1acc() sprintf(ostr, "%s %f (ACC),", ostr, fpuRegs.ACC.f) + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) + +#define dHI64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.HI.UL[1], cpuRegs.HI.UL[0], "hi") +#define dLO64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], "lo") +#define dImm() sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8x,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_) +#define dSa32() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_+32, _Sa_+32) +#define dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, cpuRegs.GPR.r[_Rs_].UL[0], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff) +#define dSaR() sprintf(ostr, "%s %8.8x,", ostr, cpuRegs.sa) + +typedef struct { + u32 addr; + char name[32]; +} sSymbol; + +static sSymbol *dSyms = NULL; +static int nSyms = 0; + +void disR5900AddSym(u32 addr, char *name) { + dSyms = (sSymbol*)realloc(dSyms, sizeof(sSymbol) * (nSyms+1)); + if (dSyms == NULL) return; + dSyms[nSyms].addr = addr; + strncpy(dSyms[nSyms].name, name, 32); + nSyms++; +} + +void disR5900FreeSyms() { + if (dSyms != NULL) { free(dSyms); dSyms = NULL; } + nSyms = 0; +} + +char *disR5900GetSym(u32 addr) { + int i; + + if (dSyms == NULL) return NULL; + for (i=0; i laddr) { + laddr = dSyms[i].addr; + j = i; + } + } + if (j == -1) return NULL; + return dSyms[j].name; +} + +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(ostr, "%s %s", ostr, str); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDI, dName("DADDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDIU, dName("DADDIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDADD, dName("DADD"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDADDU, dName("DADDU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDSUB, dName("DSUB"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDSUBU, dName("DSDBU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget(); dFindSym(_Target_);) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR32(31); dFindSym(_Target_);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR32(_Rs_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) +MakeDisF(disJALR, dName("JALR"); dGPR32(_Rs_); dGPR32(_Rd_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR64(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR64(_Rd_); dHI64();) +MakeDisF(disMFLO, dName("MFLO"); dGPR64(_Rd_); dLO64();) + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI64(); dGPR64(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO64(); dGPR64(_Rs_);) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disDSLL, dName("DSLL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSLL32, dName("DSLL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRA, dName("SRA"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRA, dName("DSRA"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRA32, dName("DSRA32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRL, dName("SRL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRL, dName("DSRL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRL32, dName("DSRL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSLLV, dName("DSLLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRAV, dName("DSRAV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRLV, dName("DSRLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWU, dName("LWU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLD, dName("LD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDL, dName("LDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDR, dName("LDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLQ, dName("LQ"); dGPR128(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSD, dName("SD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDL, dName("SDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDR, dName("SDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSQ, dName("SQ"); dGPR128(_Rt_); dOfB();) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, rd * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR32(_Rt_); dCP032(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP032(_Rd_); dGPR32(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +MakeDisF(disBGEZ, dName("BGEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + + +MakeDisF(disBEQL, dName("BEQL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNEL, dName("BNEL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBLEZL, dName("BLEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZL, dName("BGTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZL, dName("BLTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZL, dName("BGEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZALL, dName("BLTZALL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZALL, dName("BGEZALL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +MakeDisF(disBC0F, dName("BC0F"); dOffset();) +MakeDisF(disBC0T, dName("BC0T"); dOffset();) +MakeDisF(disBC0FL, dName("BC0FL"); dOffset();) +MakeDisF(disBC0TL, dName("BC0TL"); dOffset();) + +MakeDisF(disTLBR, dName("TLBR");) +MakeDisF(disTLBWI, dName("TLBWI");) +MakeDisF(disTLBWR, dName("TLBWR");) +MakeDisF(disTLBP, dName("TLBP");) +MakeDisF(disERET, dName("ERET");) +MakeDisF(disEI, dName("EI");) +MakeDisF(disDI, dName("DI");) + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +MakeDisF(disMFC1, dName("MFC1"); dGPR64(_Rt_); dCP132(_Fs_);) +MakeDisF(disCFC1, dName("CFC1"); dGPR64(_Rt_); dCP1c32(_Fs_);) +MakeDisF(disMTC1, dName("MTC1"); dCP132(_Fs_); dGPR64(_Rt_);) +MakeDisF(disCTC1, dName("CTC1"); dCP1c32(_Fs_); dGPR64(_Rt_);) + +MakeDisF(disBC1F, dName("BC1F");) +MakeDisF(disBC1T, dName("BC1T");) +MakeDisF(disBC1FL, dName("BC1FL");) +MakeDisF(disBC1TL, dName("BC1TL");) + +MakeDisF(disADDs, dName("ADDs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBs, dName("SUBs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULs, dName("MULs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disDIVs, dName("DIVs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSQRTs, dName("SQRTs"); dCP132(_Fd_); dCP132(_Ft_);) +MakeDisF(disABSs, dName("ABSs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMOVs, dName("MOVs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disNEGs, dName("NEGs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disRSQRTs, dName("RSQRTs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disADDAs, dName("ADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBAs, dName("SUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULAs, dName("MULAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDs, dName("MADDs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBs, dName("MSUBs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDAs, dName("MADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBAs, dName("MSUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCVTWs, dName("CVTWs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMAXs, dName("MAXs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMINs, dName("MINs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCFs, dName("CFs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCEQs, dName("CEQs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLTs, dName("CLTs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLEs, dName("CLEs"); dCP132(_Fs_); dCP132(_Ft_);) + +MakeDisF(disCVTSw, dName("CVTSw"); dCP132(_Fd_); dCP132(_Fs_);) + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +MakeDisF(disLWC1, dName("LWC1"); dCP132(_Rt_); dOffset();) +MakeDisF(disSWC1, dName("SWC1"); dCP132(_Rt_); dOffset();) + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +MakeDisF(disMOVZ, dName("MOVZ"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disMOVN, dName("MOVN"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ + +MakeDisF(disMULT1, dName("MULT1");) +MakeDisF(disMULTU1, dName("MULTU1");) + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADDW, dName("PADDW");) +MakeDisF(disPADDH, dName("PADDH");) +MakeDisF(disPADDB, dName("PADDB");) + +MakeDisF(disPADDSW, dName("PADDSW");) +MakeDisF(disPADDSH, dName("PADDSH");) +MakeDisF(disPADDSB, dName("PADDSB");) + +MakeDisF(disPSUBW, dName("PSUBW");) +MakeDisF(disPSUBH, dName("PSUBH");) +MakeDisF(disPSUBB, dName("PSUBB");) + +MakeDisF(disPSUBSW, dName("PSUBSW");) +MakeDisF(disPSUBSH, dName("PSUBSH");) +MakeDisF(disPSUBSB, dName("PSUBSB");) + +MakeDisF(disPCGTW, dName("PCGTW");) +MakeDisF(disPCGTH, dName("PCGTH");) +MakeDisF(disPCGTB, dName("PCGTB");) + +MakeDisF(disPMAXW, dName("PMAXW");) +MakeDisF(disPMAXH, dName("PMAXH");) + +MakeDisF(disPEXTLW, dName("PEXTLW"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLH, dName("PEXTLH"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLB, dName("PEXTLB");) +MakeDisF(disPEXTS, dName("PEXTS");) + +MakeDisF(disPPACW, dName("PPACW");) +MakeDisF(disPPACH, dName("PPACH");) +MakeDisF(disPPACB, dName("PPACB");) +MakeDisF(disPPACS, dName("PPACS");) + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADSBH, dName("PADSBH");) + +MakeDisF(disPABSW, dName("PABSW");) +MakeDisF(disPABSH, dName("PABSH");) + +MakeDisF(disPCEQW, dName("PCEQW");) +MakeDisF(disPCEQH, dName("PCEQH");) +MakeDisF(disPCEQB, dName("PCEQB");) + +MakeDisF(disPMINW, dName("PMINW");) +MakeDisF(disPMINH, dName("PMINH");) + +MakeDisF(disPADDUW, dName("PADDUW");) +MakeDisF(disPADDUH, dName("PADDUH");) +MakeDisF(disPADDUB, dName("PADDUB");) + +MakeDisF(disPSUBUW, dName("PSUBUW");) +MakeDisF(disPSUBUH, dName("PSUBUH");) +MakeDisF(disPSUBUB, dName("PSUBUB");) + +MakeDisF(disPEXTUW, dName("PEXTUW"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUH, dName("PEXTUH"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUB, dName("PEXTUB");) + +MakeDisF(disQFSRV, dName("QFSRV");) + +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDW, dName("PMADDW");) +MakeDisF(disPMADDH, dName("PMADDH");) + +MakeDisF(disPSLLVW, dName("PSLLVW");) +MakeDisF(disPSRLVW, dName("PSRLVW");) + +MakeDisF(disPMFHI, dName("PMFHI");) +MakeDisF(disPMFLO, dName("PMFLO");) + +MakeDisF(disPINTH, dName("PINTH");) + +MakeDisF(disPMULTW, dName("PMULTW");) +MakeDisF(disPMULTH, dName("PMULTH");) + +MakeDisF(disPDIVW, dName("PDIVW");) +MakeDisF(disPDIVH, dName("PDIVH");) + +MakeDisF(disPCPYLD, dName("PCPYLD"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPAND, dName("PAND"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPXOR, dName("PXOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPMSUBW, dName("PMSUBW");) +MakeDisF(disPMSUBH, dName("PMSUBH");) + +MakeDisF(disPHMADH, dName("PHMADH");) +MakeDisF(disPHMSBH, dName("PHMSBH");) + +MakeDisF(disPEXEW, dName("PEXEW");) +MakeDisF(disPEXEH, dName("PEXEH");) + +MakeDisF(disPREVH, dName("PREVH");) + +MakeDisF(disPDIVBW, dName("PDIVBW");) + +MakeDisF(disPROT3W, dName("PROT3W");) + +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDUW, dName("PMADDUW");) + +MakeDisF(disPSRAVW, dName("PSRAVW");) + +MakeDisF(disPMTHI, dName("PMTHI");) +MakeDisF(disPMTLO, dName("PMTLO");) + +MakeDisF(disPINTEH, dName("PINTEH");) + +MakeDisF(disPMULTUW, dName("PMULTUW");) +MakeDisF(disPDIVUW, dName("PDIVUW");) + +MakeDisF(disPCPYUD, dName("PCPYUD"); dGPR128(_Rd_); dGPR128(_Rt_); dGPR128(_Rs_);) + +MakeDisF(disPOR, dName("POR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPNOR, dName("PNOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPEXCH, dName("PEXCH");) +MakeDisF(disPEXCW, dName("PEXCW");) + +MakeDisF(disPCPYH, dName("PCPYH"); dGPR128(_Rd_); dGPR128(_Rt_);) + +/********************************************************* +* COP2 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X code>>24 +#define _Y code>>23 +#define _Z code>>22 +#define _W code>>21 + +MakeDisF(disLQC2, dName("LQC2"); dCP2128f(_Rt_); dOfB();) +MakeDisF(disSQC2, dName("SQC2"); dCP2128f(_Rt_); dOfB();) + +MakeDisF(disQMFC2, dName("QMFC2");) +MakeDisF(disQMTC2, dName("QMTC2");) +MakeDisF(disCFC2, dName("CFC2"); dGPR32(_Rt_); dCP232i(_Fs_);) +MakeDisF(disCTC2, dName("CTC2"); dCP232i(_Fs_); dGPR32(_Rt_);) + +MakeDisF(disBC2F, dName("BC2F");) +MakeDisF(disBC2T, dName("BC2T");) +MakeDisF(disBC2FL, dName("BC2FL");) +MakeDisF(disBC2TL, dName("BC2TL");) + +// SPEC1 +MakeDisF(disVADD, dName("VADD");) +MakeDisF(disVADDx, dName("VADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDy, dName("VADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDz, dName("VADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDw, dName("VADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDq, dName("VADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) +MakeDisF(disVADDi, dName("VADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) +MakeDisF(disVSUB, dName("VSUB");) +MakeDisF(disVSUBx, dName("VSUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBy, dName("VSUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBz, dName("VSUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBw, dName("VSUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBq, dName("VSUBq");) +MakeDisF(disVSUBi, dName("VSUBi");) +MakeDisF(disVMADD, dName("VMADD");) +MakeDisF(disVMADDx, dName("VMADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDy, dName("VMADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDz, dName("VMADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDw, dName("VMADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDq, dName("VMADDq");) +MakeDisF(disVMADDi, dName("VMADDi");) +MakeDisF(disVMSUB, dName("VMSUB");) +MakeDisF(disVMSUBx, dName("VMSUBx");) +MakeDisF(disVMSUBy, dName("VMSUBy");) +MakeDisF(disVMSUBz, dName("VMSUBz");) +MakeDisF(disVMSUBw, dName("VMSUBw");) +MakeDisF(disVMSUBq, dName("VMSUBq");) +MakeDisF(disVMSUBi, dName("VMSUBi");) +MakeDisF(disVMAX, dName("VMAX");) +MakeDisF(disVMAXx, dName("VMAXx");) +MakeDisF(disVMAXy, dName("VMAXy");) +MakeDisF(disVMAXz, dName("VMAXz");) +MakeDisF(disVMAXw, dName("VMAXw");) +MakeDisF(disVMAXi, dName("VMAXi");) +MakeDisF(disVMINI, dName("VMINI");) +MakeDisF(disVMINIx, dName("VMINIx");) +MakeDisF(disVMINIy, dName("VMINIy");) +MakeDisF(disVMINIz, dName("VMINIz");) +MakeDisF(disVMINIw, dName("VMINIw");) +MakeDisF(disVMINIi, dName("VMINIi");) +MakeDisF(disVMUL, dName("VMUL");) +MakeDisF(disVMULx, dName("VMULx");) +MakeDisF(disVMULy, dName("VMULy");) +MakeDisF(disVMULz, dName("VMULz");) +MakeDisF(disVMULw, dName("VMULw");) +MakeDisF(disVMULq, dName("VMULq");) +MakeDisF(disVMULi, dName("VMULi");) +MakeDisF(disVIADD, dName("VIADD");) +MakeDisF(disVIADDI, dName("VIADDI");) +MakeDisF(disVISUB, dName("VISUB");) +MakeDisF(disVIAND, dName("VIAND");) +MakeDisF(disVIOR, dName("VIOR");) +MakeDisF(disVOPMSUB, dName("VOPMSUB");) +MakeDisF(disVCALLMS, dName("VCALLMS");) +MakeDisF(disVCALLMSR, dName("VCALLMSR");) + +// SPEC2 +MakeDisF(disVADDA, dName("VADDA");) +MakeDisF(disVADDAx, dName("VADDAx");) +MakeDisF(disVADDAy, dName("VADDAy");) +MakeDisF(disVADDAz, dName("VADDAz");) +MakeDisF(disVADDAw, dName("VADDAw");) +MakeDisF(disVADDAq, dName("VADDAq");) +MakeDisF(disVADDAi, dName("VADDAi");) +MakeDisF(disVMADDA, dName("VMADDA");) +MakeDisF(disVMADDAx, dName("VMADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDAy, dName("VMADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDAz, dName("VMADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDAw, dName("VMADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDAq, dName("VMADDAq");) +MakeDisF(disVMADDAi, dName("VMADDAi");) +MakeDisF(disVSUBAx, dName("VSUBAx");) +MakeDisF(disVSUBAy, dName("VSUBAy");) +MakeDisF(disVSUBAz, dName("VSUBAz");) +MakeDisF(disVSUBAw, dName("VSUBAw");) +MakeDisF(disVMSUBAx, dName("VMSUBAx");) +MakeDisF(disVMSUBAy, dName("VMSUBAy");) +MakeDisF(disVMSUBAz, dName("VMSUBAz");) +MakeDisF(disVMSUBAw, dName("VMSUBAw");) +MakeDisF(disVITOF0, dName("VITOF0");) +MakeDisF(disVITOF4, dName("VITOF4");) +MakeDisF(disVITOF12, dName("VITOF12");) +MakeDisF(disVITOF15, dName("VITOF15");) +MakeDisF(disVFTOI0, dName("VFTOI0");) +MakeDisF(disVFTOI4, dName("VFTOI4");) +MakeDisF(disVFTOI12, dName("VFTOI12");) +MakeDisF(disVFTOI15, dName("VFTOI15");) +MakeDisF(disVMULA, dName("VMULA");) +MakeDisF(disVMULAx, dName("VMULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMULAy, dName("VMULAy");) +MakeDisF(disVMULAz, dName("VMULAz");) +MakeDisF(disVMULAw, dName("VMULAw");) +MakeDisF(disVMOVE, dName("VMOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_);) +MakeDisF(disVMR32, dName("VMR32");) +MakeDisF(disVDIV, dName("VDIV");) +MakeDisF(disVSQRT, dName("VSQRT"); dCP232f(_Ft_, _Ftf_);) +MakeDisF(disVRSQRT, dName("VRSQRT");) +MakeDisF(disVRNEXT, dName("VRNEXT");) +MakeDisF(disVRGET, dName("VRGET");) +MakeDisF(disVRINIT, dName("VRINIT");) +MakeDisF(disVRXOR, dName("VRXOR");) +MakeDisF(disVWAITQ, dName("VWAITQ");) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +MakeDisF(disSYNC, dName("SYNC");) +MakeDisF(disBREAK, dName("BREAK");) +MakeDisF(disSYSCALL, dName("SYSCALL"); dCode();) +MakeDisF(disCACHE, sprintf(ostr, "%s %-7s, %x,", ostr, "CACHE", _Rt_); dOfB();) +MakeDisF(disPREF, dName("PREF");) + +MakeDisF(disMFSA, dName("MFSA"); dGPR64(_Rd_); dSaR();) +MakeDisF(disMTSA, dName("MTSA"); dGPR64(_Rs_); dSaR();) + +MakeDisF(disMTSAB, dName("MTSAB");dGPR64(_Rs_); dImm();) +MakeDisF(disMTSAH, dName("MTSAH");dGPR64(_Rs_); dImm();) + +MakeDisF(disTGE, dName("TGE"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTGEU, dName("TGEU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLT, dName("TLT"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLTU, dName("TLTU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTEQ, dName("TEQ"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTNE, dName("TNE"); dGPR64(_Rs_); dGPR64(_Rt_);) + +MakeDisF(disTGEI, dName("TGEI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTGEIU, dName("TGEIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTI, dName("TLTI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTIU, dName("TLTIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTEQI, dName("TEQI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTNEI, dName("TNEI"); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + +TdisR5900F disR5900_MMI0[] = { // Subset of disMMI0 + disPADDW, disPSUBW, disPCGTW, disPMAXW, + disPADDH, disPSUBH, disPCGTH, disPMAXH, + disPADDB, disPSUBB, disPCGTB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDSW, disPSUBSW, disPEXTLW, disPPACW, + disPADDSH, disPSUBSH, disPEXTLH, disPPACH, + disPADDSB, disPSUBSB, disPEXTLB, disPPACB, + disNULL, disNULL, disPEXTS, disPPACS}; + +MakeDisF(disMMI0, disR5900_MMI0[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI1[] = { // Subset of disMMI1 + disNULL, disPABSW, disPCEQW, disPMINW, + disPADSBH, disPABSH, disPCEQH, disPMINH, + disNULL, disNULL, disPCEQB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDUW, disPSUBUW, disPEXTUW, disNULL, + disPADDUH, disPSUBUH, disPEXTUH, disNULL, + disPADDUB, disPSUBUB, disPEXTUB, disQFSRV, + disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI1, disR5900_MMI1[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI2[] = { // Subset of disMMI2 + disPMADDW, disNULL, disPSLLVW, disPSRLVW, + disPMSUBW, disNULL, disNULL, disNULL, + disPMFHI, disPMFLO, disPINTH, disNULL, + disPMULTW, disPDIVW, disPCPYLD, disNULL, + disPMADDH, disPHMADH, disPAND, disPXOR, + disPMSUBH, disPHMSBH, disNULL, disNULL, + disNULL, disNULL, disPEXEH, disPREVH, + disPMULTH, disPDIVBW, disPEXEW, disPROT3W}; + +MakeDisF(disMMI2, disR5900_MMI2[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI3[] = { // Subset of disMMI3 + disPMADDUW, disNULL, disNULL, disPSRAVW, + disNULL, disNULL, disNULL, disNULL, + disPMTHI, disPMTLO, disPINTEH, disNULL, + disPMULTUW, disPDIVUW, disPCPYUD, disNULL, + disNULL, disNULL, disPOR, disPNOR, + disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disPEXCH, disPCPYH, + disNULL, disNULL, disPEXCW, disNULL}; + +MakeDisF(disMMI3, disR5900_MMI3[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI[] = { // Subset of disMMI + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI0, disMMI2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMULT1, disMULTU1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI1, disMMI3, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI, disR5900_MMI[_Funct_] DisFInterfaceN) + + +TdisR5900F disR5900_COP0_BC0[] = { //subset of disCOP0 BC + disBC0F, disBC0T, disBC0FL, disBC0TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP0_BC0, disR5900_COP0_BC0[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP0_Func[] = { //subset of disCOP0 Function + disNULL, disTLBR, disTLBWI, disNULL, disNULL, disNULL, disTLBWR, disNULL, + disTLBP, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disERET, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disEI , disDI , disNULL , disNULL, disNULL, disNULL, disNULL , disNULL +}; +MakeDisF(disCOP0_Func, disR5900_COP0_Func[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disNULL, disNULL, disMTC0, disNULL, disNULL, disNULL, + disCOP0_BC0, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP0_Func, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR5900_COP0[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_S[] = { //subset of disCOP1 S + disADDs, disSUBs, disMULs, disDIVs, disSQRTs, disABSs, disMOVs, disNEGs, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disRSQRTs, disNULL, + disADDAs, disSUBAs, disMULAs, disNULL, disMADDs, disMSUBs, disMADDAs, disMSUBAs, + disNULL, disNULL, disNULL, disNULL, disCVTWs, disNULL, disNULL, disNULL, + disMINs, disMAXs, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCFs, disNULL, disCEQs, disNULL, disCLTs, disNULL, disCLEs, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_S, disR5900_COP1_S[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_W[] = { //subset of disCOP1 W + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCVTSw, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_W, disR5900_COP1_W[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_BC1[] = { //subset of disCOP1 BC + disBC1F, disBC1T, disBC1FL, disBC1TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_BC1, disR5900_COP1_BC1[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP1[] = { // Subset of disCOP1 + disMFC1, disNULL, disCFC1, disNULL, disMTC1, disNULL, disCTC1, disNULL, + disCOP1_BC1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP1_S, disNULL, disNULL, disNULL, disCOP1_W, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP1, disR5900_COP1[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC2[] = { //subset of disCOP2 SPEC2 + disVADDAx, disVADDAy, disVADDAz, disVADDAw, disVSUBAx, disVSUBAy, disVSUBAz, disVSUBAw, + disVMADDAx, disVMADDAy, disVMADDAz, disVMADDAw, disVMSUBAx, disVMSUBAy, disVMSUBAz, disVMSUBAw, + disVITOF0, disVITOF4, disVITOF12, disVITOF15, disVFTOI0, disVFTOI4, disVFTOI12, disVFTOI15, + disVMULAx, disVMULAy, disVMULAz, disVMULAw, disNULL, disNULL, disNULL, disNULL, + disVADDAq, disVMADDAq, disVADDAi, disVMADDAi, disNULL, disNULL, disNULL, disNULL, + disVADDA, disVMADDA, disVMULA, disNULL, disNULL, disNULL, disNULL, disNULL, + disVMOVE, disVMR32, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disVDIV, disVSQRT, disVRSQRT, disVWAITQ, disNULL, disNULL, disNULL, disNULL, + disVRNEXT, disVRGET, disVRINIT, disVRXOR, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_SPEC2, disR5900_COP2_SPEC2[(code & 0x3) | ((code >> 4) & 0x7c)] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC1[] = { //subset of disCOP2 SPEC1 + disVADDx, disVADDy, disVADDz, disVADDw, disVSUBx, disVSUBy, disVSUBz, disVSUBw, + disVMADDx, disVMADDy, disVMADDz, disVMADDw, disVMSUBx, disVMSUBy, disVMSUBz, disVMSUBw, + disVMAXx, disVMAXy, disVMAXz, disVMAXw, disVMINIx, disVMINIy, disVMINIz, disVMINIw, + disVMULx, disVMULy, disVMULz, disVMULw, disVMULq, disVMAXi, disVMULi, disVMINIi, + disVADDq, disVMADDq, disVADDi, disVMADDi, disVSUBq, disVMSUBq, disVSUBi, disVMSUBi, + disVADD, disVMADD, disVMUL, disVMAX, disVSUB, disVMSUB, disVOPMSUB, disVMINI, + disVIADD, disVISUB, disVIADDI, disNULL, disVIAND, disVIOR, disNULL, disNULL, + disVCALLMS, disVCALLMSR, disNULL, disNULL, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, +}; + +MakeDisF(disCOP2_SPEC1, disR5900_COP2_SPEC1[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_BC2[] = { //subset of disCOP2 BC + disBC2F, disBC2T, disBC2FL, disBC2TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_BC2, disR5900_COP2_BC2[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP2[] = { // Subset of disCOP2 + disNULL, disQMFC2, disCFC2, disNULL, disNULL, disQMTC2, disCTC2, disNULL, + disCOP2_BC2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1}; + +MakeDisF(disCOP2, disR5900_COP2[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_REGIMM[] = { // Subset of disREGIMM + disBLTZ, disBGEZ, disBLTZL, disBGEZL, disNULL, disNULL, disNULL, disNULL, + disTGEI, disTGEIU, disTLTI, disTLTIU, disTEQI, disNULL, disTNEI, disNULL, + disBLTZAL, disBGEZAL, disBLTZALL, disBGEZALL, disNULL, disNULL, disNULL, disNULL, + disMTSAB, disMTSAH , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disREGIMM, disR5900_REGIMM[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_SPECIAL[] = { + disSLL, disNULL, disSRL, disSRA, disSLLV, disNULL, disSRLV, disSRAV, + disJR, disJALR, disMOVZ, disMOVN, disSYSCALL, disBREAK,disNULL, disSYNC, + disMFHI, disMTHI, disMFLO, disMTLO, disDSLLV, disNULL, disDSRLV, disDSRAV, + disMULT, disMULTU,disDIV, disDIVU, disNULL, disNULL, disNULL, disNULL, + disADD, disADDU, disSUB, disSUBU, disAND, disOR, disXOR, disNOR, + disMFSA , disMTSA, disSLT, disSLTU, disDADD, disDADDU,disDSUB, disDSUBU, + disTGE, disTGEU, disTLT, disTLTU, disTEQ, disNULL, disTNE, disNULL, + disDSLL, disNULL, disDSRL, disDSRA, disDSLL32, disNULL, disDSRL32,disDSRA32 }; + +MakeDisF(disSPECIAL, disR5900_SPECIAL[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900[] = { + disSPECIAL, disREGIMM, disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI, disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disCOP1 , disCOP2, disNULL , disBEQL, disBNEL, disBLEZL, disBGTZL, + disDADDI , disDADDIU, disLDL , disLDR , disMMI , disNULL, disLQ , disSQ , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disLWU , + disSB , disSH , disSWL , disSW , disSDL , disSDR , disSWR , disCACHE, + disNULL , disLWC1 , disNULL, disPREF , disNULL, disNULL, disLQC2 , disLD , + disNULL , disSWC1 , disNULL, disNULL , disNULL, disNULL, disSQC2 , disSD }; + +MakeDisF(disR5900F, disR5900[code >> 26] DisFInterfaceN) + diff --git a/branches/pcsx2_0.9.1/DebugTools/DisR5900asm.c b/branches/pcsx2_0.9.1/DebugTools/DisR5900asm.c new file mode 100644 index 0000000..8ba326f --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisR5900asm.c @@ -0,0 +1,1679 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PS2Etypes.h" +#include "Debug.h" +#include "R5900.h" +#include "DisASM.h" + +unsigned long opcode_addr; + +/* +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +/// ******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) +*/ +/*************************CPUS REGISTERS**************************/ +char *GPR_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +//floating point cop1 Floating point reg +char *COP1_REG_FP[32] ={ + "f00","f01","f02","f03","f04","f05","f06","f07", + "f08","f09","f10","f11","f12","f13","f14","f15", + "f16","f17","f18","f19","f20","f21","f21","f23", + "f24","f25","f26","f27","f28","f29","f30","f31" +}; +//floating point cop1 control registers +char *COP1_REG_FCR[32] ={ + "fcr00","fcr01","fcr02","fcr03","fcr04","fcr05","fcr06","fcr07", + "fcr08","fcr09","fcr10","fcr11","fcr12","fcr13","fcr14","fcr15", + "fcr16","fcr17","fcr18","fcr19","fcr20","fcr21","fcr21","fcr23", + "fcr24","fcr25","fcr26","fcr27","fcr28","fcr29","fcr30","fcr31" +}; + +//floating point cop2 reg +char *COP2_REG_FP[32] ={ + "vf00","vf01","vf02","vf03","vf04","vf05","vf06","vf07", + "vf08","vf09","vf10","vf11","vf12","vf13","vf14","vf15", + "vf16","vf17","vf18","vf19","vf20","vf21","vf21","vf23", + "vf24","vf25","vf26","vf27","vf28","vf29","vf30","vf31" +}; +//cop2 control registers + +char *COP2_REG_CTL[32] ={ + "vi00","vi01","vi02","vi03","vi04","vi05","vi06","vi07", + "vi08","vi09","vi10","vi11","vi12","vi13","vi14","vi15", + "Status","MACflag","ClipFlag","c2c19","R","I","Q","c2c23", + "c2c24","c2c25","TPC","CMSAR0","FBRST","VPU-STAT","c2c30","CMSAR1" +}; + + + + + +//**************************************************************** +void P_SpecialOpcode(char *buf); +void P_REGIMMOpcode(char *buf); +void P_UnknownOpcode(char *buf); +void P_COP0(char *buf); +void P_COP1(char *buf); +void P_COP2(char *buf); +void P_MMI_Unknown(char *buf); +void P_MMI(char *buf); +void P_MMI0(char *buf); +void P_MMI1(char *buf); +void P_MMI2(char *buf); +void P_MMI3(char *buf); +void P_COP0_Unknown(char *buf); +void P_COP0_BC0(char *buf); +void P_COP0_Func(char *buf); +void P_COP1_BC1(char *buf); +void P_COP1_S(char *buf); +void P_COP1_W(char *buf); +void P_COP1_Unknown(char *buf); +void P_COP2_BC2(char *buf); +void P_COP2_SPECIAL(char *buf); +void P_COP2_Unknown(char *buf); +void P_COP2_SPECIAL2(char *buf); + +// **********************Standard Opcodes************************** +void P_J(char *buf); +void P_JAL(char *buf); +void P_BEQ(char *buf); +void P_BNE(char *buf); +void P_BLEZ(char *buf); +void P_BGTZ(char *buf); +void P_ADDI(char *buf); +void P_ADDIU(char *buf); +void P_SLTI(char *buf); +void P_SLTIU(char *buf); +void P_ANDI(char *buf); +void P_ORI(char *buf); +void P_XORI(char *buf); +void P_LUI(char *buf); +void P_BEQL(char *buf); +void P_BNEL(char *buf); +void P_BLEZL(char *buf); +void P_BGTZL(char *buf); +void P_DADDI(char *buf); +void P_DADDIU(char *buf); +void P_LDL(char *buf); +void P_LDR(char *buf); +void P_LB(char *buf); +void P_LH(char *buf); +void P_LWL(char *buf); +void P_LW(char *buf); +void P_LBU(char *buf); +void P_LHU(char *buf); +void P_LWR(char *buf); +void P_LWU(char *buf); +void P_SB(char *buf); +void P_SH(char *buf); +void P_SWL(char *buf); +void P_SW(char *buf); +void P_SDL(char *buf); +void P_SDR(char *buf); +void P_SWR(char *buf); +void P_CACHE(char *buf); +void P_LWC1(char *buf); +void P_PREF(char *buf); +void P_LQC2(char *buf); +void P_LD(char *buf); +void P_SQC2(char *buf); +void P_SD(char *buf); +void P_LQ(char *buf); +void P_SQ(char *buf); +void P_SWC1(char *buf); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void P_SLL(char *buf); +void P_SRL(char *buf); +void P_SRA(char *buf); +void P_SLLV(char *buf); +void P_SRLV(char *buf); +void P_SRAV(char *buf); +void P_JR(char *buf); +void P_JALR(char *buf); +void P_SYSCALL(char *buf); +void P_BREAK(char *buf); +void P_SYNC(char *buf); +void P_MFHI(char *buf); +void P_MTHI(char *buf); +void P_MFLO(char *buf); +void P_MTLO(char *buf); +void P_DSLLV(char *buf); +void P_DSRLV(char *buf); +void P_DSRAV(char *buf); +void P_MULT(char *buf); +void P_MULTU(char *buf); +void P_DIV(char *buf); +void P_DIVU(char *buf); +void P_ADD(char *buf); +void P_ADDU(char *buf); +void P_SUB(char *buf); +void P_SUBU(char *buf); +void P_AND(char *buf); +void P_OR(char *buf); +void P_XOR(char *buf); +void P_NOR(char *buf); +void P_SLT(char *buf); +void P_SLTU(char *buf); +void P_DADD(char *buf); +void P_DADDU(char *buf); +void P_DSUB(char *buf); +void P_DSUBU(char *buf); +void P_TGE(char *buf); +void P_TGEU(char *buf); +void P_TLT(char *buf); +void P_TLTU(char *buf); +void P_TEQ(char *buf); +void P_TNE(char *buf); +void P_DSLL(char *buf); +void P_DSRL(char *buf); +void P_DSRA(char *buf); +void P_DSLL32(char *buf); +void P_DSRL32(char *buf); +void P_DSRA32(char *buf); +void P_MOVZ(char *buf); +void P_MOVN(char *buf); +void P_MFSA(char *buf); +void P_MTSA(char *buf); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void P_BLTZ(char *buf); +void P_BGEZ(char *buf); +void P_BLTZL(char *buf); +void P_BGEZL(char *buf); +void P_TGEI(char *buf); +void P_TGEIU(char *buf); +void P_TLTI(char *buf); +void P_TLTIU(char *buf); +void P_TEQI(char *buf); +void P_TNEI(char *buf); +void P_BLTZAL(char *buf); +void P_BGEZAL(char *buf); +void P_BLTZALL(char *buf); +void P_BGEZALL(char *buf); +void P_MTSAB(char *buf); +void P_MTSAH(char *buf); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void P_MADD(char *buf); +void P_MADDU(char *buf); +void P_PLZCW(char *buf); +void P_MADD1(char *buf); +void P_MADDU1(char *buf); +void P_MFHI1(char *buf); +void P_MTHI1(char *buf); +void P_MFLO1(char *buf); +void P_MTLO1(char *buf); +void P_MULT1(char *buf); +void P_MULTU1(char *buf); +void P_DIV1(char *buf); +void P_DIVU1(char *buf); +void P_PMFHL(char *buf); +void P_PMTHL(char *buf); +void P_PSLLH(char *buf); +void P_PSRLH(char *buf); +void P_PSRAH(char *buf); +void P_PSLLW(char *buf); +void P_PSRLW(char *buf); +void P_PSRAW(char *buf); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf); +void P_PSUBW(char *buf); +void P_PCGTW(char *buf); +void P_PMAXW(char *buf); +void P_PADDH(char *buf); +void P_PSUBH(char *buf); +void P_PCGTH(char *buf); +void P_PMAXH(char *buf); +void P_PADDB(char *buf); +void P_PSUBB(char *buf); +void P_PCGTB(char *buf); +void P_PADDSW(char *buf); +void P_PSUBSW(char *buf); +void P_PEXTLW(char *buf); +void P_PPACW(char *buf); +void P_PADDSH(char *buf); +void P_PSUBSH(char *buf); +void P_PEXTLH(char *buf); +void P_PPACH(char *buf); +void P_PADDSB(char *buf); +void P_PSUBSB(char *buf); +void P_PEXTLB(char *buf); +void P_PPACB(char *buf); +void P_PEXT5(char *buf); +void P_PPAC5(char *buf); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf); +void P_PCEQW(char *buf); +void P_PMINW(char *buf); +void P_PADSBH(char *buf); +void P_PABSH(char *buf); +void P_PCEQH(char *buf); +void P_PMINH(char *buf); +void P_PCEQB(char *buf); +void P_PADDUW(char *buf); +void P_PSUBUW(char *buf); +void P_PEXTUW(char *buf); +void P_PADDUH(char *buf); +void P_PSUBUH(char *buf); +void P_PEXTUH(char *buf); +void P_PADDUB(char *buf); +void P_PSUBUB(char *buf); +void P_PEXTUB(char *buf); +void P_QFSRV(char *buf); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf); +void P_PSLLVW(char *buf); +void P_PSRLVW(char *buf); +void P_PMSUBW(char *buf); +void P_PMFHI(char *buf); +void P_PMFLO(char *buf); +void P_PINTH(char *buf); +void P_PMULTW(char *buf); +void P_PDIVW(char *buf); +void P_PCPYLD(char *buf); +void P_PMADDH(char *buf); +void P_PHMADH(char *buf); +void P_PAND(char *buf); +void P_PXOR(char *buf); +void P_PMSUBH(char *buf); +void P_PHMSBH(char *buf); +void P_PEXEH(char *buf); +void P_PREVH(char *buf); +void P_PMULTH(char *buf); +void P_PDIVBW(char *buf); +void P_PEXEW(char *buf); +void P_PROT3W(char *buf); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf); +void P_PSRAVW(char *buf); +void P_PMTHI(char *buf); +void P_PMTLO(char *buf); +void P_PINTEH(char *buf); +void P_PMULTUW(char *buf); +void P_PDIVUW(char *buf); +void P_PCPYUD(char *buf); +void P_POR(char *buf); +void P_PNOR(char *buf); +void P_PEXCH(char *buf); +void P_PCPYH(char *buf); +void P_PEXCW(char *buf); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf); +void P_MTC0(char *buf); +void P_BC0F(char *buf); +void P_BC0T(char *buf); +void P_BC0FL(char *buf); +void P_BC0TL(char *buf); +void P_TLBR(char *buf); +void P_TLBWI(char *buf); +void P_TLBWR(char *buf); +void P_TLBP(char *buf); +void P_ERET(char *buf); +void P_DI(char *buf); +void P_EI(char *buf); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf); +void P_CFC1(char *buf); +void P_MTC1(char *buf); +void P_CTC1(char *buf); +void P_BC1F(char *buf); +void P_BC1T(char *buf); +void P_BC1FL(char *buf); +void P_BC1TL(char *buf); +void P_ADD_S(char *buf); +void P_SUB_S(char *buf); +void P_MUL_S(char *buf); +void P_DIV_S(char *buf); +void P_SQRT_S(char *buf); +void P_ABS_S(char *buf); +void P_MOV_S(char *buf); +void P_NEG_S(char *buf); +void P_RSQRT_S(char *buf); +void P_ADDA_S(char *buf); +void P_SUBA_S(char *buf); +void P_MULA_S(char *buf); +void P_MADD_S(char *buf); +void P_MSUB_S(char *buf); +void P_MADDA_S(char *buf); +void P_MSUBA_S(char *buf); +void P_CVT_W(char *buf); +void P_MAX_S(char *buf); +void P_MIN_S(char *buf); +void P_C_F(char *buf); +void P_C_EQ(char *buf); +void P_C_LT(char *buf); +void P_C_LE(char *buf); + void P_CVT_S(char *buf); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf); +void P_CFC2(char *buf); +void P_QMTC2(char *buf); +void P_CTC2(char *buf); +void P_BC2F(char *buf); +void P_BC2T(char *buf); +void P_BC2FL(char *buf); +void P_BC2TL(char *buf); +//*****************SPECIAL 1 VUO TABLE******************************* +void P_VADDx(char *buf); +void P_VADDy(char *buf); +void P_VADDz(char *buf); +void P_VADDw(char *buf); +void P_VSUBx(char *buf); +void P_VSUBy(char *buf); +void P_VSUBz(char *buf); +void P_VSUBw(char *buf); +void P_VMADDx(char *buf); +void P_VMADDy(char *buf); +void P_VMADDz(char *buf); +void P_VMADDw(char *buf); +void P_VMSUBx(char *buf); +void P_VMSUBy(char *buf); +void P_VMSUBz(char *buf); +void P_VMSUBw(char *buf); +void P_VMAXx(char *buf); +void P_VMAXy(char *buf); +void P_VMAXz(char *buf); +void P_VMAXw(char *buf); +void P_VMINIx(char *buf); +void P_VMINIy(char *buf); +void P_VMINIz(char *buf); +void P_VMINIw(char *buf); +void P_VMULx(char *buf); +void P_VMULy(char *buf); +void P_VMULz(char *buf); +void P_VMULw(char *buf); +void P_VMULq(char *buf); +void P_VMAXi(char *buf); +void P_VMULi(char *buf); +void P_VMINIi(char *buf); +void P_VADDq(char *buf); +void P_VMADDq(char *buf); +void P_VADDi(char *buf); +void P_VMADDi(char *buf); +void P_VSUBq(char *buf); +void P_VMSUBq(char *buf); +void P_VSUbi(char *buf); +void P_VMSUBi(char *buf); +void P_VADD(char *buf); +void P_VMADD(char *buf); +void P_VMUL(char *buf); +void P_VMAX(char *buf); +void P_VSUB(char *buf); +void P_VMSUB(char *buf); +void P_VOPMSUB(char *buf); +void P_VMINI(char *buf); +void P_VIADD(char *buf); +void P_VISUB(char *buf); +void P_VIADDI(char *buf); +void P_VIAND(char *buf); +void P_VIOR(char *buf); +void P_VCALLMS(char *buf); +void P_CALLMSR(char *buf); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf); +void P_VADDAy(char *buf); +void P_VADDAz(char *buf); +void P_VADDAw(char *buf); +void P_VSUBAx(char *buf); +void P_VSUBAy(char *buf); +void P_VSUBAz(char *buf); +void P_VSUBAw(char *buf); +void P_VMADDAx(char *buf); +void P_VMADDAy(char *buf); +void P_VMADDAz(char *buf); +void P_VMADDAw(char *buf); +void P_VMSUBAx(char *buf); +void P_VMSUBAy(char *buf); +void P_VMSUBAz(char *buf); +void P_VMSUBAw(char *buf); +void P_VITOF0(char *buf); +void P_VITOF4(char *buf); +void P_VITOF12(char *buf); +void P_VITOF15(char *buf); +void P_VFTOI0(char *buf); +void P_VFTOI4(char *buf); +void P_VFTOI12(char *buf); +void P_VFTOI15(char *buf); +void P_VMULAx(char *buf); +void P_VMULAy(char *buf); +void P_VMULAz(char *buf); +void P_VMULAw(char *buf); +void P_VMULAq(char *buf); +void P_VABS(char *buf); +void P_VMULAi(char *buf); +void P_VCLIPw(char *buf); +void P_VADDAq(char *buf); +void P_VMADDAq(char *buf); +void P_VADDAi(char *buf); +void P_VMADDAi(char *buf); +void P_VSUBAq(char *buf); +void P_VMSUBAq(char *buf); +void P_VSUBAi(char *buf); +void P_VMSUBAi(char *buf); +void P_VADDA(char *buf); +void P_VMADDA(char *buf); +void P_VMULA(char *buf); +void P_VSUBA(char *buf); +void P_VMSUBA(char *buf); +void P_VOPMULA(char *buf); +void P_VNOP(char *buf); +void P_VMONE(char *buf); +void P_VMR32(char *buf); +void P_VLQI(char *buf); +void P_VSQI(char *buf); +void P_VLQD(char *buf); +void P_VSQD(char *buf); +void P_VDIV(char *buf); +void P_VSQRT(char *buf); +void P_VRSQRT(char *buf); +void P_VWAITQ(char *buf); +void P_VMTIR(char *buf); +void P_VMFIR(char *buf); +void P_VILWR(char *buf); +void P_VISWR(char *buf); +void P_VRNEXT(char *buf); +void P_VRGET(char *buf); +void P_VRINIT(char *buf); +void P_VRXOR(char *buf); +//************************************END OF SPECIAL2 VUO TABLE**************************** + + +/* + CPU: Instructions encoded by opcode field. + 31---------26---------------------------------------------------0 + | opcode | | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | +001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | +010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | +011 | DADDI |DADDIU | LDL | LDR | *6 | --- | LQ | SQ | +100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | +101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | +110 | --- | LWC1 | --- | PREF | --- | --- | LQC2 | LD | +111 | --- | SWC1 | --- | --- | --- | --- | SQC2 | SD | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = SPECIAL, see SPECIAL list *2 = REGIMM, see REGIMM list + *3 = COP0 *4 = COP1 + *5 = COP2 *6 = MMI table +*/ +void (*OpcodePrintTable[64])(char *buf) = { + P_SpecialOpcode, P_REGIMMOpcode, P_J, P_JAL, P_BEQ, P_BNE, P_BLEZ, P_BGTZ, + P_ADDI, P_ADDIU, P_SLTI, P_SLTIU, P_ANDI, P_ORI, P_XORI, P_LUI, + P_COP0, P_COP1, P_COP2, P_UnknownOpcode, P_BEQL, P_BNEL, P_BLEZL, P_BGTZL, + P_DADDI, P_DADDIU, P_LDL, P_LDR, P_MMI, P_UnknownOpcode, P_LQ, P_SQ, + P_LB, P_LH, P_LWL, P_LW, P_LBU, P_LHU, P_LWR, P_LWU, + P_SB, P_SH, P_SWL, P_SW, P_SDL, P_SDR, P_SWR, P_CACHE, + P_UnknownOpcode, P_LWC1, P_UnknownOpcode, P_PREF, P_UnknownOpcode,P_UnknownOpcode, P_LQC2, P_LD, + P_UnknownOpcode, P_SWC1, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode,P_UnknownOpcode, P_SQC2, P_SD +}; + + + /* + SPECIAL: Instr. encoded by function field when opcode field = SPECIAL + 31---------26------------------------------------------5--------0 + | = SPECIAL | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | +001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | +010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | +011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | +100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | +101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | +110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | +111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ + +void (*SpecialPrintTable[64])(char *buf) = { + P_SLL, P_UnknownOpcode, P_SRL, P_SRA, P_SLLV, P_UnknownOpcode, P_SRLV, P_SRAV, + P_JR, P_JALR, P_MOVZ, P_MOVN, P_SYSCALL, P_BREAK, P_UnknownOpcode, P_SYNC, + P_MFHI, P_MTHI, P_MFLO, P_MTLO, P_DSLLV, P_UnknownOpcode, P_DSRLV, P_DSRAV, + P_MULT, P_MULTU, P_DIV, P_DIVU, P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode, + P_ADD, P_ADDU, P_SUB, P_SUBU, P_AND, P_OR, P_XOR, P_NOR, + P_MFSA , P_MTSA , P_SLT, P_SLTU, P_DADD, P_DADDU, P_DSUB, P_DSUBU, + P_TGE, P_TGEU, P_TLT, P_TLTU, P_TEQ, P_UnknownOpcode, P_TNE, P_UnknownOpcode, + P_DSLL, P_UnknownOpcode, P_DSRL, P_DSRA, P_DSLL32, P_UnknownOpcode, P_DSRL32, P_DSRA32 +}; + +/* + REGIMM: Instructions encoded by the rt field when opcode field = REGIMM. + 31---------26----------20-------16------------------------------0 + | = REGIMM | | rt | | + ------6---------------------5------------------------------------ + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | + 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | + 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | + 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*REGIMMPrintTable[32])(char *buf) = { + P_BLTZ, P_BGEZ, P_BLTZL, P_BGEZL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_TGEI, P_TGEIU, P_TLTI, P_TLTIU, P_TEQI, P_UnknownOpcode, P_TNEI, P_UnknownOpcode, + P_BLTZAL, P_BGEZAL, P_BLTZALL, P_BGEZALL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_MTSAB, P_MTSAH , P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, +}; +/* + MMI: Instr. encoded by function field when opcode field = MMI + 31---------26------------------------------------------5--------0 + | = MMI | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | MADD | MADDU | --- | --- | PLZCW | --- | --- | --- | +001 | *1 | *2 | --- | --- | --- | --- | --- | --- | +010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | --- | --- | --- | --- | +011 | MULT1 | MULTU1| DIV1 | DIVU1 | --- | --- | --- | --- | +100 | MADD1 | MADDU1| --- | --- | --- | --- | --- | --- | +101 | *3 | *4 | --- | --- | --- | --- | --- | --- | +110 | PMFHL | PMTHL | --- | --- | PSLLH | --- | PSRLH | PSRAH | +111 | --- | --- | --- | --- | PSLLW | --- | PSRLW | PSRAW | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + + *1 = see MMI0 table *2 = see MMI2 Table + *3 = see MMI1 table *4 = see MMI3 Table +*/ +void (*MMIPrintTable[64])(char *buf) = { + P_MADD, P_MADDU, P_MMI_Unknown, P_MMI_Unknown, P_PLZCW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI0, P_MMI2, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MFHI1, P_MTHI1, P_MFLO1, P_MTLO1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MULT1, P_MULTU1, P_DIV1, P_DIVU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MADD1, P_MADDU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI1 , P_MMI3, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHL, P_PMTHL, P_MMI_Unknown, P_MMI_Unknown, P_PSLLH, P_MMI_Unknown, P_PSRLH, P_PSRAH, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_PSLLW, P_MMI_Unknown, P_PSRLW, P_PSRAW, +}; +/* + MMI0: Instr. encoded by function field when opcode field = MMI & MMI0 + + 31---------26------------------------------10--------6-5--------0 + | | |function | MMI0 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PADDW | PSUBW | PCGTW | PMAXW | +001 |PADDH | PSUBH | PCGTH | PMAXH | +010 |PADDB | PSUBB | PCGTB | --- | +011 | --- | --- | --- | --- | +100 |PADDSW |PSUBSW |PEXTLW | PPACW | +101 |PADDSH |PSUBSH |PEXTLH | PPACH | +110 |PADDSB |PSUBSB |PEXTLB | PPACB | +111 | --- | --- | PEXT5 | PPAC5 | + hi |-------|-------|-------|-------| +*/ +void (*MMI0PrintTable[32])(char *buf) = { + P_PADDW, P_PSUBW, P_PCGTW, P_PMAXW, + P_PADDH, P_PSUBH, P_PCGTH, P_PMAXH, + P_PADDB, P_PSUBB, P_PCGTB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDSW, P_PSUBSW, P_PEXTLW, P_PPACW, + P_PADDSH, P_PSUBSH, P_PEXTLH, P_PPACH, + P_PADDSB, P_PSUBSB, P_PEXTLB, P_PPACB, + P_MMI_Unknown, P_MMI_Unknown, P_PEXT5, P_PPAC5, +}; +/* + MMI1: Instr. encoded by function field when opcode field = MMI & MMI1 + + 31---------26------------------------------------------5--------0 + | | |function | MMI1 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 | --- | PABSW | PCEQW | PMINW | +001 |PADSBH | PABSH | PCEQH | PMINH | +010 | --- | --- | PCEQB | --- | +011 | --- | --- | --- | --- | +100 |PADDUW |PSUBUW |PEXTUW | --- | +101 |PADDUH |PSUBUH |PEXTUH | --- | +110 |PADDUB |PSUBUB |PEXTUB | QFSRV | +111 | --- | --- | --- | --- | + hi |-------|-------|-------|-------| +*/ +void (*MMI1PrintTable[32])(char *buf) = { + P_MMI_Unknown, P_PABSW, P_PCEQW, P_PMINW, + P_PADSBH, P_PABSH, P_PCEQH, P_PMINH, + P_MMI_Unknown, P_MMI_Unknown, P_PCEQB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDUW, P_PSUBUW, P_PEXTUW, P_MMI_Unknown, + P_PADDUH, P_PSUBUH, P_PEXTUH, P_MMI_Unknown, + P_PADDUB, P_PSUBUB, P_PEXTUB, P_QFSRV, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, +}; + +/* + MMI2: Instr. encoded by function field when opcode field = MMI & MMI2 + + 31---------26------------------------------------------5--------0 + | | |function | MMI2 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDW | --- |PSLLVW |PSRLVW | +001 |PMSUBW | --- | --- | --- | +010 |PMFHI |PMFLO |PINTH | --- | +011 |PMULTW |PDIVW |PCPYLD | --- | +100 |PMADDH |PHMADH | PAND | PXOR | +101 |PMSUBH |PHMSBH | --- | --- | +110 | --- | --- | PEXEH | PREVH | +111 |PMULTH |PDIVBW | PEXEW |PROT3W | + hi |-------|-------|-------|-------| +*/ +void (*MMI2PrintTable[32])(char *buf) = { + P_PMADDW, P_MMI_Unknown, P_PSLLVW, P_PSRLVW, + P_PMSUBW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHI, P_PMFLO, P_PINTH, P_MMI_Unknown, + P_PMULTW, P_PDIVW, P_PCPYLD, P_MMI_Unknown, + P_PMADDH, P_PHMADH, P_PAND, P_PXOR, + P_PMSUBH, P_PHMSBH, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXEH, P_PREVH, + P_PMULTH, P_PDIVBW, P_PEXEW, P_PROT3W, +}; +/* + MMI3: Instr. encoded by function field when opcode field = MMI & MMI3 + 31---------26------------------------------------------5--------0 + | | |function | MMI3 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDUW| --- | --- |PSRAVW | +001 | --- | --- | --- | --- | +010 |PMTHI | PMTLO |PINTEH | --- | +011 |PMULTUW| PDIVUW|PCPYUD | --- | +100 | --- | --- | POR | PNOR | +101 | --- | --- | --- | --- | +110 | --- | --- | PEXCH | PCPYH | +111 | --- | --- | PEXCW | --- | + hi |-------|-------|-------|-------| + */ +void (*MMI3PrintTable[32])(char *buf) = { + P_PMADDUW, P_MMI_Unknown, P_MMI_Unknown, P_PSRAVW, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMTHI, P_PMTLO, P_PINTEH, P_MMI_Unknown, + P_PMULTUW, P_PDIVUW, P_PCPYUD, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_POR, P_PNOR, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCH, P_PCPYH, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCW, P_MMI_Unknown, +}; +/* + COP0: Instructions encoded by the rs field when opcode = COP0. + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=BC See BC0 list *2 = TLB instr, see TLB list +*/ +void (*COP0PrintTable[32])(char *buf) = { + P_MFC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_MTC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_BC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Func, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + BC0: Instructions encoded by the rt field when opcode = COP0 & rs field=BC0 + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0BC0PrintTable[32])(char *buf) = { + P_BC0F, P_BC0T, P_BC0FL, P_BC0TL, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + C0=Instructions encode by function field when Opcode field=COP0 & rs field=C0 + 31---------26------------------------------------------5--------0 + | | | | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | +001 | TLBP | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | ERET | --- | --- | --- | --- | --- | --- | --- | +100 | --- | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | EI | DI | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0C0PrintTable[64])(char *buf) = { + P_COP0_Unknown, P_TLBR, P_TLBWI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_TLBWR, P_COP0_Unknown, + P_TLBP, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_ERET, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_EI, P_DI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown +}; +/* + COP1: Instructions encoded by the fmt field when opcode = COP1. + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC1 | --- | CFC1 | --- | MTC1 | --- | CTC1 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC1 list *2 = S instr, see FPU list + *3 = W instr, see FPU list +*/ +void (*COP1PrintTable[32])(char *buf) = { + P_MFC1, P_COP1_Unknown, P_CFC1, P_COP1_Unknown, P_MTC1, P_COP1_Unknown, P_CTC1, P_COP1_Unknown, + P_COP1_BC1, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_S, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_W, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + BC1: Instructions encoded by the rt field when opcode = COP1 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1BC1PrintTable[32])(char *buf) = { + P_BC1F, P_BC1T, P_BC1FL, P_BC1TL, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = S + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = S | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S| ABS.S | MOV.S | NEG.S | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- |RSQRT.S| --- | +011 | ADDA.S| SUBA.S| MULA.S| --- | MADD.S| MSUB.S|MADDA.S|MSUBA.S| +100 | --- | --- | --- | --- | CVT.W | --- | --- | --- | +101 | MAX.S | MIN.S | --- | --- | --- | --- | --- | --- | +110 | C.F | --- | C.EQ | --- | C.LT | --- | C.LE | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1SPrintTable[64])(char *buf) = { +P_ADD_S, P_SUB_S, P_MUL_S, P_DIV_S, P_SQRT_S, P_ABS_S, P_MOV_S, P_NEG_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_RSQRT_S, P_COP1_Unknown, +P_ADDA_S, P_SUBA_S, P_MULA_S, P_COP1_Unknown,P_MADD_S, P_MSUB_S, P_MADDA_S, P_MSUBA_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_CVT_W, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_MAX_S, P_MIN_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_C_F, P_COP1_Unknown,P_C_EQ, P_COP1_Unknown,P_C_LT, P_COP1_Unknown,P_C_LE, P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = W + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = W | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | --- | --- | --- | --- | --- | --- | --- | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | --- | --- | --- | --- | --- | --- | --- | --- | +100 | CVT.S | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1WPrintTable[64])(char *buf) = { +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_CVT_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; + +//************************************************************* +//COP2 TABLES :) +//************************************************************* +/* + COP2: Instructions encoded by the fmt field when opcode = COP2. + 31--------26-25------21 ----------------------------------------0 + | = COP2 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | --- | QMFC2 | CFC2 | --- | --- | QMTC2 | CTC2 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC2 list *2 =see special1 table +*/ +void (*COP2PrintTable[32])(char *buf) = { + P_COP2_Unknown, P_QMFC2, P_CFC2, P_COP2_Unknown, P_COP2_Unknown, P_QMTC2, P_CTC2, P_COP2_Unknown, + P_COP2_BC2, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + + +}; +/* + BC2: Instructions encoded by the rt field when opcode = COP2 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP2 | rs=BC2| | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + */ +void (*COP2BC2PrintTable[32])(char *buf) = { + P_BC2F, P_BC2T, P_BC2FL, P_BC2TL, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, +}; +/* + Special1 table : instructions encode by function field when opcode=COP2 & rs field=Special1 + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 |VADDx |VADDy |VADDz |VADDw |VSUBx |VSUBy |VSUBz |VSUBw | +001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw | +010 |VMAXx |VMAXy |VMAXz |VMAXw |VMINIx |VMINIy |VMINIz |VMINIw | +011 |VMULx |VMULy |VMULz |VMULw |VMULq |VMAXi |VMULi |VMINIi | +100 |VADDq |VMADDq |VADDi |VMADDi |VSUBq |VMSUBq |VSUbi |VMSUBi | +101 |VADD |VMADD |VMUL |VMAX |VSUB |VMSUB |VOPMSUB|VMINI | +110 |VIADD |VISUB |VIADDI | --- |VIAND |VIOR | --- | --- | +111 |VCALLMS|CALLMSR| --- | --- | *1 | *1 | *1 | *1 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=see special2 table +*/ +void (*COP2SPECIAL1PrintTable[64])(char *buf) = +{ + P_VADDx, P_VADDy, P_VADDz, P_VADDw, P_VSUBx, P_VSUBy, P_VSUBz, P_VSUBw, + P_VMADDx, P_VMADDy, P_VMADDz, P_VMADDw, P_VMSUBx, P_VMSUBy, P_VMSUBz, P_VMSUBw, + P_VMAXx, P_VMAXy, P_VMAXz, P_VMAXw, P_VMINIx, P_VMINIy, P_VMINIz, P_VMINIw, + P_VMULx, P_VMULy, P_VMULz, P_VMULw, P_VMULq, P_VMAXi, P_VMULi, P_VMINIi, + P_VADDq, P_VMADDq, P_VADDi, P_VMADDi, P_VSUBq, P_VMSUBq, P_VSUbi, P_VMSUBi, + P_VADD, P_VMADD, P_VMUL, P_VMAX, P_VSUB, P_VMSUB, P_VOPMSUB, P_VMINI, + P_VIADD, P_VISUB, P_VIADDI, P_COP2_Unknown,P_VIAND, P_VIOR, P_COP2_Unknown, P_COP2_Unknown, + P_VCALLMS, P_CALLMSR, P_COP2_Unknown,P_COP2_Unknown,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2, + +}; +/* + Special2 table : instructions encode by function field when opcode=COp2 & rs field=Special2 + + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special2 | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +0000 |VADDAx |VADDAy |VADDAz |VADDAw |VSUBAx |VSUBAy |VSUBAz |VSUBAw | +0001 |VMADDAx|VMADDAy|VMADDAz|VMADDAw|VMSUBAx|VMSUBAy|VMSUBAz|VMSUBAw| +0010 |VITOF0 |VITOF4 |VITOF12|VITOF15|VFTOI0 |VFTOI4 |VFTOI12|VFTOI15| +0011 |VMULAx |VMULAy |VMULAz |VMULAw |VMULAq |VABS |VMULAi |VCLIPw | +0100 |VADDAq |VMADDAq|VADDAi |VMADDAi|VSUBAq |VMSUBAq|VSUBAi |VMSUBAi| +0101 |VADDA |VMADDA |VMULA | --- |VSUBA |VMSUBA |VOPMULA|VNOP | +0110 |VMONE |VMR32 | --- | --- |VLQI |VSQI |VLQD |VSQD | +0111 |VDIV |VSQRT |VRSQRT |VWAITQ |VMTIR |VMFIR |VILWR |VISWR | +1000 |VRNEXT |VRGET |VRINIT |VRXOR | --- | --- | --- | --- | +1001 | --- | --- | --- | --- | --- | --- | --- | --- | +1010 | --- | --- | --- | --- | --- | --- | --- | --- | +1011 | --- | --- | --- | --- | --- | --- | --- | --- | +1100 | --- | --- | --- | --- | --- | --- | --- | --- | +1101 | --- | --- | --- | --- | --- | --- | --- | --- | +1110 | --- | --- | --- | --- | --- | --- | --- | --- | +1111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP2SPECIAL2PrintTable[128])(char *buf) = +{ + P_VADDAx ,P_VADDAy ,P_VADDAz ,P_VADDAw ,P_VSUBAx ,P_VSUBAy ,P_VSUBAz ,P_VSUBAw, + P_VMADDAx ,P_VMADDAy ,P_VMADDAz ,P_VMADDAw ,P_VMSUBAx ,P_VMSUBAy ,P_VMSUBAz ,P_VMSUBAw, + P_VITOF0 ,P_VITOF4 ,P_VITOF12 ,P_VITOF15 ,P_VFTOI0 ,P_VFTOI4 ,P_VFTOI12 ,P_VFTOI15, + P_VMULAx ,P_VMULAy ,P_VMULAz ,P_VMULAw ,P_VMULAq ,P_VABS ,P_VMULAi ,P_VCLIPw, + P_VADDAq ,P_VMADDAq ,P_VADDAi ,P_VMADDAi ,P_VSUBAq ,P_VMSUBAq ,P_VSUBAi ,P_VMSUBAi, + P_VADDA ,P_VMADDA ,P_VMULA ,P_COP2_Unknown,P_VSUBA ,P_VMSUBA ,P_VOPMULA ,P_VNOP, + P_VMONE ,P_VMR32 ,P_COP2_Unknown,P_COP2_Unknown,P_VLQI ,P_VSQI ,P_VLQD ,P_VSQD, + P_VDIV ,P_VSQRT ,P_VRSQRT ,P_VWAITQ ,P_VMTIR ,P_VMFIR ,P_VILWR ,P_VISWR, + P_VRNEXT ,P_VRGET ,P_VRINIT ,P_VRXOR ,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, +}; + +//**************************TABLES CALLS*********************** + +static char dbuf[1024]; +static char obuf[1024]; + +char *disR5900Fasm(u32 code, u32 pc) { + u32 scode = cpuRegs.code; + opcode_addr = pc; + cpuRegs.code = code; + OpcodePrintTable[(code) >> 26](dbuf); + + sprintf(obuf, "%08X:\t%s", pc, dbuf); + + cpuRegs.code = scode; + return obuf; +} + +void P_SpecialOpcode(char *buf) +{ + SpecialPrintTable[DECODE_FUNCTION](buf); +} +void P_REGIMMOpcode(char *buf) +{ + REGIMMPrintTable[DECODE_RT](buf); +} + +//***********COP0 TABLE CALLS******************************** + +void P_COP0(char *buf) +{ + COP0PrintTable[DECODE_RS](buf); +} +void P_COP0_BC0(char *buf) +{ + + COP0BC0PrintTable[DECODE_C0BC](buf); +} +void P_COP0_Func(char *buf) +{ + + COP0C0PrintTable[DECODE_FUNCTION](buf); +} + +//*****************MMI TABLES CALLS************************** +void P_MMI(char *buf) +{ + + MMIPrintTable[DECODE_FUNCTION](buf); +} +void P_MMI0(char *buf) +{ + MMI0PrintTable[DECODE_SA](buf); +} +void P_MMI1(char *buf) +{ + MMI1PrintTable[DECODE_SA](buf); +} +void P_MMI2(char *buf) +{ + MMI2PrintTable[DECODE_SA](buf); +} +void P_MMI3(char *buf) +{ + MMI3PrintTable[DECODE_SA](buf); +} +//****************END OF MMI TABLES CALLS********************** +//COP1 TABLECALLS******************************************* +void P_COP1(char *buf) +{ + + COP1PrintTable[DECODE_RS](buf); +} +void P_COP1_BC1(char *buf) +{ + COP1BC1PrintTable[DECODE_C1BC](buf); +} +void P_COP1_S(char *buf) +{ + COP1SPrintTable[DECODE_FUNCTION](buf); +} +void P_COP1_W(char *buf) +{ + COP1WPrintTable[DECODE_FUNCTION](buf); +} +//**********************END OF COP1 TABLE CALLS + +//************************************************************* +//************************COP2********************************** +void P_COP2(char *buf) +{ + + COP2PrintTable[DECODE_RS](buf); +} +void P_COP2_BC2(char *buf) +{ + COP2BC2PrintTable[DECODE_C2BC](buf); +} +void P_COP2_SPECIAL(char *buf) +{ + COP2SPECIAL1PrintTable[DECODE_FUNCTION ](buf); + +} +void P_COP2_SPECIAL2(char *buf) +{ + + COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](buf); + +} + +//**************************UNKNOWN**************************** +void P_UnknownOpcode(char *buf) +{ + strcpy(buf, "?????"); +} +void P_COP0_Unknown(char *buf) +{ + strcpy(buf, "COP0 ??"); +} +void P_COP1_Unknown(char *buf) +{ + strcpy(buf, "COP1 ??"); +} +void P_COP2_Unknown(char *buf) +{ + strcpy(buf,"COP2 ??"); +} + +void P_MMI_Unknown(char *buf) +{ + strcpy(buf,"MMI ??"); +} + + + +//************************************************************* + +//*****************SOME DECODE STUFF*************************** +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(buf, "%s %s", buf, str); \ +} + +char *jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_JUMP; + sprintf(buf, "0x%08X", addr); + + dFindSym(addr); + return buf; +} + +char *offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_OFFSET; + sprintf(buf, "0x%08X", addr); + dFindSym(addr); + return buf; +} + +//*********************END OF DECODE ROUTINES****************** + +//********************* Standard Opcodes*********************** +void P_J(char *buf) { sprintf(buf, "j\t%s", jump_decode());} +void P_JAL(char *buf) { sprintf(buf, "jal\t%s", jump_decode());} +void P_BEQ(char *buf) { sprintf(buf, "beq\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNE(char *buf) { sprintf(buf, "bne\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZ(char *buf) { sprintf(buf, "blez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZ(char *buf) { sprintf(buf, "bgtz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_ADDI(char *buf) { sprintf(buf, "addi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ADDIU(char *buf) { sprintf(buf, "addiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_SLTI(char *buf) { sprintf(buf, "slti\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_SLTIU(char *buf) { sprintf(buf, "sltiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_ANDI(char *buf) { sprintf(buf, "andi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ORI(char *buf) { sprintf(buf, "ori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_XORI(char *buf) { sprintf(buf, "xori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LUI(char *buf) { sprintf(buf, "lui\t%s, 0x%04X", GPR_REG[DECODE_RT], DECODE_IMMED); } +void P_BEQL(char *buf) { sprintf(buf, "beql\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNEL(char *buf) { sprintf(buf, "bnel\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZL(char *buf) { sprintf(buf, "blezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZL(char *buf) { sprintf(buf, "bgtzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_DADDI(char *buf) { sprintf(buf, "daddi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_DADDIU(char *buf) { sprintf(buf, "daddiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LDL(char *buf) { sprintf(buf, "ldl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LDR(char *buf) { sprintf(buf, "ldr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LB(char *buf) { sprintf(buf, "lb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LH(char *buf) { sprintf(buf, "lh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWL(char *buf) { sprintf(buf, "lwl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LW(char *buf) { sprintf(buf, "lw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LBU(char *buf) { sprintf(buf, "lbu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LHU(char *buf) { sprintf(buf, "lhu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWR(char *buf) { sprintf(buf, "lwr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWU(char *buf) { sprintf(buf, "lwu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SB(char *buf) { sprintf(buf, "sb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SH(char *buf) { sprintf(buf, "sh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWL(char *buf) { sprintf(buf, "swl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SW(char *buf) { sprintf(buf, "sw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDL(char *buf) { sprintf(buf, "sdl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDR(char *buf) { sprintf(buf, "sdr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWR(char *buf) { sprintf(buf, "swr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LD(char *buf) { sprintf(buf, "ld\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SD(char *buf) { sprintf(buf, "sd\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQ(char *buf) { sprintf(buf, "lq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQ(char *buf) { sprintf(buf, "sq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWC1(char *buf) { sprintf(buf, "swc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQC2(char *buf) { sprintf(buf, "sqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_PREF(char *buf) { strcpy(buf, "pref ---");/*sprintf(buf, "PREF\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[RS]); */} +void P_LWC1(char *buf) { sprintf(buf, "lwc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQC2(char *buf) { sprintf(buf, "lqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +//********************END OF STANDARD OPCODES************************* + +void P_SLL(char *buf) +{ + if (cpuRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); +} + +void P_SRL(char *buf) { sprintf(buf, "srl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SRA(char *buf) { sprintf(buf, "sra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SLLV(char *buf) { sprintf(buf, "sllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_SRLV(char *buf) { sprintf(buf, "srlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]);} +void P_SRAV(char *buf) { sprintf(buf, "srav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_JR(char *buf) { sprintf(buf, "jr\t%s", GPR_REG[DECODE_RS]); } + +void P_JALR(char *buf) +{ + int rd = DECODE_RD; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_REG[DECODE_RS]); + else + sprintf(buf, "jalr\t%s, %s", GPR_REG[rd], GPR_REG[DECODE_RS]); +} + + +void P_SYNC(char *buf) { sprintf(buf, "SYNC");} +void P_MFHI(char *buf) { sprintf(buf, "mfhi\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI(char *buf) { sprintf(buf, "mthi\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO(char *buf) { sprintf(buf, "mflo\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO(char *buf) { sprintf(buf, "mtlo\t%s", GPR_REG[DECODE_RS]); } +void P_DSLLV(char *buf) { sprintf(buf, "dsllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRLV(char *buf) { sprintf(buf, "dsrlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRAV(char *buf) { sprintf(buf, "dsrav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_MULT(char *buf) { sprintf(buf, "mult\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_MULTU(char *buf) { sprintf(buf, "multu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV(char *buf) { sprintf(buf, "div\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU(char *buf) { sprintf(buf, "divu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADD(char *buf) { sprintf(buf, "dadd\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADDU(char *buf) { sprintf(buf, "daddu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUB(char *buf) { sprintf(buf, "dsub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUBU(char *buf) { sprintf(buf, "dsubu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGE(char *buf) { sprintf(buf, "tge\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGEU(char *buf) { sprintf(buf, "tgeu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLT(char *buf) { sprintf(buf, "tlt\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLTU(char *buf) { sprintf(buf, "tltu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TEQ(char *buf) { sprintf(buf, "teq\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TNE(char *buf) { sprintf(buf, "tne\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSLL(char *buf) { sprintf(buf, "dsll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL(char *buf) { sprintf(buf, "dsrl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA(char *buf) { sprintf(buf, "dsra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSLL32(char *buf) { sprintf(buf, "dsll32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL32(char *buf) { sprintf(buf, "dsrl32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA32(char *buf) { sprintf(buf, "dsra32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_MOVZ(char *buf) { sprintf(buf, "movz\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MOVN(char *buf) { sprintf(buf, "movn\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFSA(char *buf) { sprintf(buf, "mfsa\t%s", GPR_REG[DECODE_RD]);} +void P_MTSA(char *buf) { sprintf(buf, "mtsa\t%s", GPR_REG[DECODE_RS]);} +//*** unsupport (yet) cpu opcodes +void P_SYSCALL(char *buf) { strcpy(buf, "syscall ---");/*sprintf(buf, "syscall\t0x%05X", DECODE_SYSCALL);*/} +void P_BREAK(char *buf) { strcpy(buf, "break ---");/*sprintf(buf, "break\t0x%05X", DECODE_BREAK); */} +void P_CACHE(char *buf) { strcpy(buf, "cache ---");/*sprintf(buf, "cache\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); */} +//************************REGIMM OPCODES*************************** +void P_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZL(char *buf) { sprintf(buf, "bltzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZL(char *buf) { sprintf(buf, "bgezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_TGEI(char *buf) { sprintf(buf, "tgei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TGEIU(char *buf) { sprintf(buf, "tgeiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTI(char *buf) { sprintf(buf, "tlti\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTIU(char *buf) { sprintf(buf, "tltiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TEQI(char *buf) { sprintf(buf, "teqi\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TNEI(char *buf) { sprintf(buf, "tnei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZALL(char *buf) { sprintf(buf, "bltzall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZALL(char *buf) { sprintf(buf, "bgezall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_MTSAB(char *buf) { sprintf(buf, "mtsab\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_MTSAH(char *buf) { sprintf(buf, "mtsah\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} + + +//***************************SPECIAL 2 CPU OPCODES******************* +const char* pmfhl_sub[] = { "lw", "uw", "slw", "lh", "sh" }; + +void P_MADD(char *buf) { sprintf(buf, "madd\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU(char *buf) { sprintf(buf, "maddu\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_PLZCW(char *buf) { sprintf(buf, "plzcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS]); } +void P_MADD1(char *buf) { sprintf(buf, "madd1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU1(char *buf) { sprintf(buf, "maddu1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFHI1(char *buf) { sprintf(buf, "mfhi1\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI1(char *buf) { sprintf(buf, "mthi1\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO1(char *buf) { sprintf(buf, "mflo1\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO1(char *buf) { sprintf(buf, "mtlo1\t%s", GPR_REG[DECODE_RS]); } +void P_MULT1(char *buf) { sprintf(buf, "mult1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MULTU1(char *buf) { sprintf(buf, "multu1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV1(char *buf) { sprintf(buf, "div1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU1(char *buf) { sprintf(buf, "divu1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//that have parametres that i haven't figure out how to display... +void P_PMFHL(char *buf) { sprintf(buf, "pmfhl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RD]); } +void P_PMTHL(char *buf) { sprintf(buf, "pmthl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RS]); } +void P_PSLLH(char *buf) { sprintf(buf, "psllh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_PSRLH(char *buf) { sprintf(buf, "psrlh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAH(char *buf) { sprintf(buf, "psrah \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSLLW(char *buf) { sprintf(buf, "psllw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRLW(char *buf) { sprintf(buf, "psrlw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAW(char *buf) { sprintf(buf, "psraw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +//***************************END OF SPECIAL OPCODES****************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf){ sprintf(buf, "paddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBW(char *buf){ sprintf(buf, "psubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTW(char *buf){ sprintf(buf, "pcgtw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXW(char *buf){ sprintf(buf, "pmaxw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDH(char *buf){ sprintf(buf, "paddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBH(char *buf){ sprintf(buf, "psubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTH(char *buf){ sprintf(buf, "pcgth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXH(char *buf){ sprintf(buf, "pmaxh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDB(char *buf){ sprintf(buf, "paddb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBB(char *buf){ sprintf(buf, "psubb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTB(char *buf){ sprintf(buf, "pcgtb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSW(char *buf){ sprintf(buf, "paddsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSW(char *buf){ sprintf(buf, "psubsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLW(char *buf){ sprintf(buf, "pextlw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACW(char *buf) { sprintf(buf, "ppacw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSH(char *buf){ sprintf(buf, "paddsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSH(char *buf){ sprintf(buf, "psubsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLH(char *buf){ sprintf(buf, "pextlh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACH(char *buf) { sprintf(buf, "ppach\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSB(char *buf){ sprintf(buf, "paddsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSB(char *buf){ sprintf(buf, "psubsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLB(char *buf){ sprintf(buf, "pextlb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACB(char *buf) { sprintf(buf, "ppacb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXT5(char *buf) { sprintf(buf, "pext5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PPAC5(char *buf) { sprintf(buf, "ppac5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//**********END OF MMI0 OPCODES********************************* +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf){ sprintf(buf, "pabsw%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQW(char *buf){ sprintf(buf, "pceqw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINW(char *buf){ sprintf(buf, "pminw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADSBH(char *buf){ sprintf(buf, "padsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PABSH(char *buf){ sprintf(buf, "pabsh%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQH(char *buf){ sprintf(buf, "pceqh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINH(char *buf){ sprintf(buf, "pminh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCEQB(char *buf){ sprintf(buf, "pceqb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUW(char *buf){ sprintf(buf, "padduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUW(char *buf){ sprintf(buf, "psubuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUW(char *buf){ sprintf(buf, "pextuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUH(char *buf){ sprintf(buf, "padduh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUH(char *buf){ sprintf(buf, "psubuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUH(char *buf){ sprintf(buf, "pextuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUB(char *buf){ sprintf(buf, "paddub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUB(char *buf){ sprintf(buf, "psubub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUB(char *buf){ sprintf(buf, "pextub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_QFSRV(char *buf) { sprintf(buf, "qfsrv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf){ sprintf(buf, "pmaddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSLLVW(char *buf){ sprintf(buf, "psllvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSRLVW(char *buf){ sprintf(buf, "psrlvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBW(char *buf){ sprintf(buf, "msubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMFHI(char *buf){ sprintf(buf, "pmfhi\t%s", GPR_REG[DECODE_RD]); } +void P_PMFLO(char *buf){ sprintf(buf, "pmflo\t%s", GPR_REG[DECODE_RD]); } +void P_PINTH(char *buf){ sprintf(buf, "pinth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTW(char *buf){ sprintf(buf, "pmultw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVW(char *buf){ sprintf(buf, "pdivw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYLD(char *buf){ sprintf(buf, "pcpyld\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMADDH(char *buf){ sprintf(buf, "pmaddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMADH(char *buf){ sprintf(buf, "phmadh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PAND(char *buf){ sprintf(buf, "pand\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PXOR(char *buf){ sprintf(buf, "pxor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBH(char *buf){ sprintf(buf, "pmsubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMSBH(char *buf){ sprintf(buf, "phmsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEH(char *buf){ sprintf(buf, "pexeh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PREVH(char *buf){ sprintf(buf, "prevh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PMULTH(char *buf){ sprintf(buf, "pmulth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVBW(char *buf){ sprintf(buf, "pdivbw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEW(char *buf){ sprintf(buf, "pexew\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PROT3W(char *buf){ sprintf(buf, "prot3w\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf){ sprintf(buf, "pmadduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PSRAVW(char *buf){ sprintf(buf, "psravw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PMTHI(char *buf){ sprintf(buf, "pmthi\t%s", GPR_REG[DECODE_RS]); } +void P_PMTLO(char *buf){ sprintf(buf, "pmtlo\t%s", GPR_REG[DECODE_RS]); } +void P_PINTEH(char *buf){ sprintf(buf, "pinteh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTUW(char *buf){ sprintf(buf, "pmultuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVUW(char *buf){ sprintf(buf, "pdivuw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYUD(char *buf){ sprintf(buf, "pcpyud\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_POR(char *buf){ sprintf(buf, "por\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PNOR(char *buf){ sprintf(buf, "pnor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXCH(char *buf){ sprintf(buf, "pexch\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PCPYH(char *buf){ sprintf(buf, "pcpyh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PEXCW(char *buf){ sprintf(buf, "pexcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_BC0F(char *buf){ sprintf(buf, "bc0f\t%s", offset_decode()); } +void P_BC0T(char *buf){ sprintf(buf, "bc0t\t%s", offset_decode()); } +void P_BC0FL(char *buf){ sprintf(buf, "bc0fl\t%s", offset_decode()); } +void P_BC0TL(char *buf){ sprintf(buf, "bc0tl\t%s", offset_decode()); } +void P_TLBR(char *buf){ strcpy(buf,"tlbr");} +void P_TLBWI(char *buf){ strcpy(buf,"tlbwi");} +void P_TLBWR(char *buf){ strcpy(buf,"tlbwr");} +void P_TLBP(char *buf){ strcpy(buf,"tlbp");} +void P_ERET(char *buf){ strcpy(buf,"eret");} +void P_DI(char *buf){ strcpy(buf,"di");} +void P_EI(char *buf){ strcpy(buf,"ei");} +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf){ sprintf(buf, "mfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CFC1(char *buf){ sprintf(buf, "cfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_MTC1(char *buf){ sprintf(buf, "mtc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CTC1(char *buf){ sprintf(buf, "ctc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_BC1F(char *buf){ sprintf(buf, "bc1f\t%s", offset_decode()); } +void P_BC1T(char *buf){ sprintf(buf, "bc1t\t%s", offset_decode()); } +void P_BC1FL(char *buf){ sprintf(buf, "bc1fl\t%s", offset_decode()); } +void P_BC1TL(char *buf){ sprintf(buf, "bc1tl\t%s", offset_decode()); } +void P_ADD_S(char *buf){ sprintf(buf, "add.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_SUB_S(char *buf){ sprintf(buf, "sub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MUL_S(char *buf){ sprintf(buf, "mul.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_DIV_S(char *buf){ sprintf(buf, "div.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SQRT_S(char *buf){ sprintf(buf, "sqrt.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FT]); } +void P_ABS_S(char *buf){ sprintf(buf, "abs.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MOV_S(char *buf){ sprintf(buf, "mov.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_NEG_S(char *buf){ sprintf(buf, "neg.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]);} +void P_RSQRT_S(char *buf){sprintf(buf, "rsqrt.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_ADDA_S(char *buf){ sprintf(buf, "adda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SUBA_S(char *buf){ sprintf(buf, "suba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MULA_S(char *buf){ sprintf(buf, "mula.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADD_S(char *buf){ sprintf(buf, "madd.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUB_S(char *buf){ sprintf(buf, "msub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADDA_S(char *buf){sprintf(buf, "madda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUBA_S(char *buf){sprintf(buf, "msuba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_W(char *buf){ sprintf(buf, "cvt.w.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MAX_S(char *buf){ sprintf(buf, "max.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MIN_S(char *buf){ sprintf(buf, "min.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_C_F(char *buf){ sprintf(buf, "c.f.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_EQ(char *buf){ sprintf(buf, "c.eq.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LT(char *buf){ sprintf(buf, "c.lt.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LE(char *buf){ sprintf(buf, "c.le.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_S(char *buf){ sprintf(buf, "cvt.s.w\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf){ sprintf(buf, "qmfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CFC2(char *buf){ sprintf(buf, "cfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_QMTC2(char *buf){ sprintf(buf, "qmtc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CTC2(char *buf){ sprintf(buf, "ctc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_BC2F(char *buf){ sprintf(buf, "bc2f\t%s", offset_decode()); } +void P_BC2T(char *buf){ sprintf(buf, "bc2t\t%s", offset_decode()); } +void P_BC2FL(char *buf){ sprintf(buf, "bc2fl\t%s", offset_decode()); } +void P_BC2TL(char *buf){ sprintf(buf, "bc2tl\t%s", offset_decode()); } +//******************************SPECIAL 1 VUO TABLE**************************************** +#define _X ((cpuRegs.code>>24) & 1) +#define _Y ((cpuRegs.code>>23) & 1) +#define _Z ((cpuRegs.code>>22) & 1) +#define _W ((cpuRegs.code>>21) & 1) + +const char *dest_string(void) +{ + static char str[5]; + int i; + i = 0; + if(_X) str[i++] = 'x'; + if(_Y) str[i++] = 'y'; + if(_Z) str[i++] = 'z'; + if(_W) str[i++] = 'w'; + str[i++] = 0; + return (const char *)str; +} + +char dest_fsf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>21)&3]; +} + +char dest_ftf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>23)&3]; +} + +void P_VADDx(char *buf){sprintf(buf, "vaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDy(char *buf){sprintf(buf, "vaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDz(char *buf){sprintf(buf, "vaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDw(char *buf){sprintf(buf, "vaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBx(char *buf){sprintf(buf, "vsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBy(char *buf){sprintf(buf, "vsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBz(char *buf){sprintf(buf, "vsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBw(char *buf){sprintf(buf, "vsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDx(char *buf){sprintf(buf, "vmaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDy(char *buf){sprintf(buf, "vmaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDz(char *buf){sprintf(buf, "vmaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDw(char *buf){sprintf(buf, "vmaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBx(char *buf){sprintf(buf, "vmsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBy(char *buf){sprintf(buf, "vmsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBz(char *buf){sprintf(buf, "vmsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBw(char *buf){sprintf(buf, "vmsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXx(char *buf){sprintf(buf, "vmaxx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXy(char *buf){sprintf(buf, "vmaxy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXz(char *buf){sprintf(buf, "vmaxz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXw(char *buf){sprintf(buf, "vmaxw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIx(char *buf){sprintf(buf, "vminix.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIy(char *buf){sprintf(buf, "vminiy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); ;} +void P_VMINIz(char *buf){sprintf(buf, "vminiz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIw(char *buf){sprintf(buf, "vminiw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULx(char *buf){sprintf(buf,"vmulx.%s %s,%s,%sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULy(char *buf){sprintf(buf,"vmuly.%s %s,%s,%sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULz(char *buf){sprintf(buf,"vmulz.%s %s,%s,%sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULw(char *buf){sprintf(buf,"vmulw.%s %s,%s,%sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULq(char *buf){sprintf(buf,"vmulq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMAXi(char *buf){sprintf(buf,"vmaxi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMULi(char *buf){sprintf(buf,"vmuli.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMINIi(char *buf){sprintf(buf,"vminii.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDq(char *buf){sprintf(buf,"vaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDq(char *buf){sprintf(buf,"vmaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDi(char *buf){sprintf(buf,"vaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDi(char *buf){sprintf(buf,"vmaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUBq(char *buf){sprintf(buf,"vsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBq(char *buf){sprintf(buf,"vmsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUbi(char *buf){sprintf(buf,"vsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBi(char *buf){sprintf(buf,"vmsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADD(char *buf){sprintf(buf, "vadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADD(char *buf){sprintf(buf, "vmadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMUL(char *buf){sprintf(buf, "vmul.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAX(char *buf){sprintf(buf, "vmax.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUB(char *buf){sprintf(buf, "vsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUB(char *buf){sprintf(buf, "vmsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMSUB(char *buf){sprintf(buf, "vopmsub.xyz %s, %s, %s", COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINI(char *buf){sprintf(buf, "vmini.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VIADD(char *buf){strcpy(buf,"viadd");} +void P_VISUB(char *buf){strcpy(buf,"visub");} +void P_VIADDI(char *buf){strcpy(buf,"viaddi");} +void P_VIAND(char *buf){strcpy(buf,"viand");} +void P_VIOR(char *buf){strcpy(buf,"vior");} +void P_VCALLMS(char *buf){strcpy(buf,"vcallms");} +void P_CALLMSR(char *buf){strcpy(buf,"callmsr");} +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf){sprintf(buf,"vaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAy(char *buf){sprintf(buf,"vadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAz(char *buf){sprintf(buf,"vaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAw(char *buf){sprintf(buf,"vaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAx(char *buf){sprintf(buf,"vsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAy(char *buf){sprintf(buf,"vsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAz(char *buf){sprintf(buf,"vsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAw(char *buf){sprintf(buf,"vsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAx(char *buf){sprintf(buf,"vmaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAy(char *buf){sprintf(buf,"vmadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAz(char *buf){sprintf(buf,"vmaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAw(char *buf){sprintf(buf,"vmaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAx(char *buf){sprintf(buf,"vmsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAy(char *buf){sprintf(buf,"vmsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAz(char *buf){sprintf(buf,"vmsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAw(char *buf){sprintf(buf,"vmsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VITOF0(char *buf){sprintf(buf, "vitof0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF4(char *buf){sprintf(buf, "vitof4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF12(char *buf){sprintf(buf, "vitof12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF15(char *buf){sprintf(buf, "vitof15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI0(char *buf) {sprintf(buf, "vftoi0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI4(char *buf) {sprintf(buf, "vftoi4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI12(char *buf){sprintf(buf, "vftoi12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI15(char *buf){sprintf(buf, "vftoi15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VMULAx(char *buf){sprintf(buf,"vmulax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAy(char *buf){sprintf(buf,"vmulay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAz(char *buf){sprintf(buf,"vmulaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAw(char *buf){sprintf(buf,"vmulaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAq(char *buf){sprintf(buf,"vmulaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VABS(char *buf){sprintf(buf, "vabs.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]);} +void P_VMULAi(char *buf){sprintf(buf,"vmulaq.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VCLIPw(char *buf){sprintf(buf,"vclip %sxyz, %sw", COP2_REG_FP[DECODE_FS], COP2_REG_FP[DECODE_FT]);} +void P_VADDAq(char *buf){sprintf(buf,"vaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAq(char *buf){sprintf(buf,"vmaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDAi(char *buf){sprintf(buf,"vaddai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAi(char *buf){sprintf(buf,"vmaddai.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAq(char *buf){sprintf(buf,"vsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAq(char *buf){sprintf(buf,"vmsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAi(char *buf){sprintf(buf,"vsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAi(char *buf){sprintf(buf,"vmsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDA(char *buf){sprintf(buf,"vadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDA(char *buf){sprintf(buf,"vmadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULA(char *buf){sprintf(buf,"vmula.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBA(char *buf){sprintf(buf,"vsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBA(char *buf){sprintf(buf,"vmsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMULA(char *buf){sprintf(buf,"vopmula.xyz %sxyz, %sxyz" ,COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VNOP(char *buf){strcpy(buf,"vnop");} +void P_VMONE(char *buf){sprintf(buf,"vmove.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VMR32(char *buf){sprintf(buf,"vmr32.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VLQI(char *buf){sprintf(buf,"vlqi %s%s, (%s++)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQI(char *buf){sprintf(buf,"vsqi %s%s, (%s++)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VLQD(char *buf){sprintf(buf,"vlqd %s%s, (--%s)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQD(char *buf){sprintf(buf,"vsqd %s%s, (--%s)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VDIV(char *buf){sprintf(buf,"vdiv Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VSQRT(char *buf){sprintf(buf,"vsqrt Q, %s%c", COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VRSQRT(char *buf){sprintf(buf,"vrsqrt Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VWAITQ(char *buf){sprintf(buf,"vwaitq");} +void P_VMTIR(char *buf){sprintf(buf,"vmtir %s, %s%c", COP2_REG_CTL[DECODE_FT], COP2_REG_FP[DECODE_FS], dest_fsf());} +void P_VMFIR(char *buf){sprintf(buf,"vmfir %s%c, %s", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VILWR(char *buf){sprintf(buf,"vilwr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VISWR(char *buf){sprintf(buf,"viswr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRNEXT(char *buf){sprintf(buf,"vrnext %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRGET(char *buf){sprintf(buf,"vrget %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRINIT(char *buf){sprintf(buf,"vrinit R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRXOR(char *buf){sprintf(buf,"vrxor R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +//************************************END OF SPECIAL2 VUO TABLE**************************** diff --git a/branches/pcsx2_0.9.1/DebugTools/DisVU0Micro.c b/branches/pcsx2_0.9.1/DebugTools/DisVU0Micro.c new file mode 100644 index 0000000..f5d36dc --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisVU0Micro.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dNameU(i) { char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); sprintf(ostr, "%s %-7s,", ostr, op); } + + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) +#define dImm5() sprintf(ostr, "%s %d,", ostr, (code >> 6) & 0x1f) +#define dImm11() sprintf(ostr, "%s %d,", ostr, code & 0x7ff) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" +#include "VU.h" + +_disVUOpcodes(VU0); +_disVUTables(VU0); + diff --git a/branches/pcsx2_0.9.1/DebugTools/DisVU1Micro.c b/branches/pcsx2_0.9.1/DebugTools/DisVU1Micro.c new file mode 100644 index 0000000..fec3f27 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisVU1Micro.c @@ -0,0 +1,123 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VUmicro.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + if( !CHECK_VU1REC ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + else ostr[0] = 0; \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-12s", ostr, i); \ + +#define dNameU(i) { \ + char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); \ + sprintf(ostr, "%s %-12s", ostr, op); \ +} + +#define dCP2128f(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%8.8x) z=%f (%8.8x) y=%f (%8.8xl) x=%f (%8.8x) (%s),", ostr, VU1.VF[i].f.w, VU1.VF[i].UL[3], VU1.VF[i].f.z, VU1.VF[i].UL[2], VU1.VF[i].f.y, VU1.VF[i].UL[1], VU1.VF[i].f.x, VU1.VF[i].UL[0], disRNameCP2f[i]); \ +} \ + +#define dCP232x(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s x=%f (%s),", ostr, VU1.VF[i].f.x, disRNameCP2f[i]); \ +} \ + +#define dCP232y(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s y=%f (%s),", ostr, VU1.VF[i].f.y, disRNameCP2f[i]); \ +} \ + +#define dCP232z(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s z=%f (%s),", ostr, VU1.VF[i].f.z, disRNameCP2f[i]); \ +} + +#define dCP232w(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%s),", ostr, VU1.VF[i].f.w, disRNameCP2f[i]); \ +} + +#define dCP2ACCf() { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s ACC,", ostr); \ + else sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU1.ACC.f.w, VU1.ACC.f.z, VU1.ACC.f.y, VU1.ACC.f.x); \ +} \ + +#define dCP232i(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %8.8x (%s),", ostr, VU1.VI[i].UL, disRNameCP2i[i]); \ +} + +#define dCP232iF(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %f (%s),", ostr, VU1.VI[i].F, disRNameCP2i[i]); \ +} + +#define dCP232f(i, j) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \ + else sprintf(ostr, "%s %s=%f (%s),", ostr, CP2VFnames[j], VU1.VF[i].F[j], disRNameCP2f[i]); \ +} + +#define dImm5() sprintf(ostr, "%s %d,", ostr, (s16)((code >> 6) & 0x10 ? 0xfff0 | ((code >> 6) & 0xf) : (code >> 6) & 0xf)) +#define dImm11() sprintf(ostr, "%s %d,", ostr, (s16)(code & 0x400 ? 0xfc00 | (code & 0x3ff) : code & 0x3ff)) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" + +_disVUOpcodes(VU1); +_disVUTables(VU1); + diff --git a/branches/pcsx2_0.9.1/DebugTools/DisVUmicro.h b/branches/pcsx2_0.9.1/DebugTools/DisVUmicro.h new file mode 100644 index 0000000..7915cde --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisVUmicro.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUTables(VU) \ + \ +/****************/ \ +/* LOWER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##LowerOP_T3_00_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MOVE , dis##VU##MI_LQI , dis##VU##MI_DIV , dis##VU##MI_MTIR, \ + dis##VU##MI_RNEXT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_MFP , dis##VU##MI_XTOP , dis##VU##MI_XGKICK, \ + dis##VU##MI_ESADD , dis##VU##MI_EATANxy, dis##VU##MI_ESQRT, dis##VU##MI_ESIN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_01_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MR32 , dis##VU##MI_SQI , dis##VU##MI_SQRT , dis##VU##MI_MFIR, \ + dis##VU##MI_RGET , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , dis##VU##MI_XITOP, disNULL , \ + dis##VU##MI_ERSADD, dis##VU##MI_EATANxz, dis##VU##MI_ERSQRT, dis##VU##MI_EATAN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_10_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_LQD , dis##VU##MI_RSQRT, dis##VU##MI_ILWR, \ + dis##VU##MI_RINIT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ELENG , dis##VU##MI_ESUM , dis##VU##MI_ERCPR, dis##VU##MI_EEXP, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_11_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_SQD , dis##VU##MI_WAITQ, dis##VU##MI_ISWR, \ + dis##VU##MI_RXOR , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ERLENG, disNULL , dis##VU##MI_WAITP, disNULL , \ +}; \ + \ +MakeDisF(dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_00_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_01_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_10_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_11, dis##VU##LowerOP_T3_11_OPCODE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##LowerOP_OPCODE[64] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x20 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_IADD , dis##VU##MI_ISUB , dis##VU##MI_IADDI, disNULL , /* 0x30 */ \ + dis##VU##MI_IAND , dis##VU##MI_IOR , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_11, \ +}; \ + \ +MakeDisF(dis##VU##LowerOP, dis##VU##LowerOP_OPCODE[code & 0x3f] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroL[] = { \ + dis##VU##MI_LQ , dis##VU##MI_SQ , disNULL , disNULL, \ + dis##VU##MI_ILW , dis##VU##MI_ISW , disNULL , disNULL, \ + dis##VU##MI_IADDIU, dis##VU##MI_ISUBIU, disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##MI_FCEQ , dis##VU##MI_FCSET , dis##VU##MI_FCAND, dis##VU##MI_FCOR, /* 0x10 */ \ + dis##VU##MI_FSEQ , dis##VU##MI_FSSET , dis##VU##MI_FSAND, dis##VU##MI_FSOR, \ + dis##VU##MI_FMEQ , disNULL , dis##VU##MI_FMAND, dis##VU##MI_FMOR, \ + dis##VU##MI_FCGET , disNULL , disNULL , disNULL, \ + dis##VU##MI_B , dis##VU##MI_BAL , disNULL , disNULL, /* 0x20 */ \ + dis##VU##MI_JR , dis##VU##MI_JALR , disNULL , disNULL, \ + dis##VU##MI_IBEQ , dis##VU##MI_IBNE , disNULL , disNULL, \ + dis##VU##MI_IBLTZ , dis##VU##MI_IBGTZ , dis##VU##MI_IBLEZ, dis##VU##MI_IBGEZ, \ + disNULL , disNULL , disNULL , disNULL, /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##LowerOP , disNULL , disNULL , disNULL, /* 0x40*/ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x50 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x60 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x70 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroLF, dis##VU##MicroL[code >> 25] DisFInterfaceN) \ + \ + \ +/****************/ \ +/* UPPER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##_UPPER_FD_00_TABLE[32] = { \ + dis##VU##MI_ADDAx, dis##VU##MI_SUBx , dis##VU##MI_MADDAx, dis##VU##MI_MSUBAx, \ + dis##VU##MI_ITOF0, dis##VU##MI_FTOI0, dis##VU##MI_MULAx , dis##VU##MI_MULAq , \ + dis##VU##MI_ADDAq, dis##VU##MI_SUBAq, dis##VU##MI_ADDA , dis##VU##MI_SUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_01_TABLE[32] = { \ + dis##VU##MI_ADDAy , dis##VU##MI_SUBy , dis##VU##MI_MADDAy, dis##VU##MI_MSUBAy, \ + dis##VU##MI_ITOF4 , dis##VU##MI_FTOI4 , dis##VU##MI_MULAy , dis##VU##MI_ABS , \ + dis##VU##MI_MADDAq, dis##VU##MI_MSUBAq, dis##VU##MI_MADDA , dis##VU##MI_MSUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_10_TABLE[32] = { \ + dis##VU##MI_ADDAz , dis##VU##MI_SUBz , dis##VU##MI_MADDAz, dis##VU##MI_MSUBAz, \ + dis##VU##MI_ITOF12, dis##VU##MI_FTOI12, dis##VU##MI_MULAz , dis##VU##MI_MULAi , \ + dis##VU##MI_MADDAi, dis##VU##MI_SUBAi , dis##VU##MI_MULA , dis##VU##MI_OPMULA, \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_11_TABLE[32] = { \ + dis##VU##MI_ADDAw , dis##VU##MI_SUBw , dis##VU##MI_MADDAw, dis##VU##MI_MSUBAw, \ + dis##VU##MI_ITOF15, dis##VU##MI_FTOI15, dis##VU##MI_MULAw , dis##VU##MI_CLIP , \ + dis##VU##MI_MADDAi, dis##VU##MI_MSUBAi, disNULL , dis##VU##MI_NOP , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +MakeDisF(dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_00_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_01_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_10_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_11, dis##VU##_UPPER_FD_11_TABLE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroU[] = { \ + dis##VU##MI_ADDx , dis##VU##MI_ADDy , dis##VU##MI_ADDz , dis##VU##MI_ADDw, \ + dis##VU##MI_SUBx , dis##VU##MI_SUBy , dis##VU##MI_SUBz , dis##VU##MI_SUBw, \ + dis##VU##MI_MADDx , dis##VU##MI_MADDy , dis##VU##MI_MADDz , dis##VU##MI_MADDw, \ + dis##VU##MI_MSUBx , dis##VU##MI_MSUBy , dis##VU##MI_MSUBz , dis##VU##MI_MSUBw, \ + dis##VU##MI_MAXx , dis##VU##MI_MAXy , dis##VU##MI_MAXz , dis##VU##MI_MAXw, /* 0x10 */ \ + dis##VU##MI_MINIx , dis##VU##MI_MINIy , dis##VU##MI_MINIz , dis##VU##MI_MINIw, \ + dis##VU##MI_MULx , dis##VU##MI_MULy , dis##VU##MI_MULz , dis##VU##MI_MULw, \ + dis##VU##MI_MULq , dis##VU##MI_MAXi , dis##VU##MI_MULi , dis##VU##MI_MINIi, \ + dis##VU##MI_ADDq , dis##VU##MI_MADDq , dis##VU##MI_ADDi , dis##VU##MI_MADDi, /* 0x20 */ \ + dis##VU##MI_SUBq , dis##VU##MI_MSUBq , dis##VU##MI_SUBi , dis##VU##MI_MSUBi, \ + dis##VU##MI_ADD , dis##VU##MI_MADD , dis##VU##MI_MUL , dis##VU##MI_MAX, \ + dis##VU##MI_SUB , dis##VU##MI_MSUB , dis##VU##MI_OPMSUB, dis##VU##MI_MINI, \ + disNULL , disNULL , disNULL , disNULL , /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_11, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroUF, dis##VU##MicroU[code & 0x3f] DisFInterfaceN) \ + diff --git a/branches/pcsx2_0.9.1/DebugTools/DisVUops.h b/branches/pcsx2_0.9.1/DebugTools/DisVUops.h new file mode 100644 index 0000000..40cf978 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/DisVUops.h @@ -0,0 +1,197 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUOpcodes(VU) \ + \ +/*****************/ \ +/* LOWER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_DIV, dName("DIV"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_SQRT, dName("SQRT"); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_RSQRT, dName("RSQRT"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_IADDI, dName("IADDI"); dCP232i(_Ft_); dCP232i(_Fs_); dImm5();) \ +MakeDisF(dis##VU##MI_IADDIU, dName("IADDIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_IADD, dName("IADD"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IAND, dName("IAND"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IOR, dName("IOR"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUB, dName("ISUB"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUBIU, dName("ISUBIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_MOVE, if (_Fs_ == 0 && _Ft_ == 0) { dNameU("NOP"); } else { dNameU("MOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_); }) \ +MakeDisF(dis##VU##MI_MFIR, dNameU("MFIR"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_MTIR, dNameU("MTIR"); dCP232i(_Ft_); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_MR32, dNameU("MR32"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_LQ, dNameU("LQ"); dCP2128f(_Ft_); dCP232i(_Fs_); dImm11();) \ +MakeDisF(dis##VU##MI_LQD, dNameU("LQD"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LQI, dNameU("LQI"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_SQ, dNameU("SQ"); dCP2128f(_Fs_); dCP232i(_Ft_); dImm11(); ) \ +MakeDisF(dis##VU##MI_SQD, dNameU("SQD"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_SQI, dNameU("SQI"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ILW, dNameU("ILW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISW, dNameU("ISW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ILWR, dNameU("ILWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISWR, dNameU("ISWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LOI, dName("LOI"); ) \ +MakeDisF(dis##VU##MI_RINIT, dNameU("RINIT"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_RGET, dNameU("RGET"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RNEXT, dNameU("RNEXT"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RXOR, dNameU("RXOR"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_WAITQ, dName("WAITQ"); ) \ +MakeDisF(dis##VU##MI_FSAND, dName("FSAND"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff); ) \ +MakeDisF(dis##VU##MI_FSEQ, dName("FSEQ"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSOR, dName("FSOR"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSSET, dName("FSSET"); dCP232i(REG_STATUS_FLAG);) \ +MakeDisF(dis##VU##MI_FMAND, dName("FMAND"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMEQ, dName("FMEQ"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMOR, dName("FMOR"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FCAND, dName("FCAND"); dCP232i(1); sprintf(ostr, "%s %8.8x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCEQ, dName("FCEQ"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCOR, dName("FCOR"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCSET, dName("FCSET"); dCP232i(REG_CLIP_FLAG); sprintf(ostr, "%s %.6x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCGET, dName("FCGET"); dCP232i(_Ft_); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_IBEQ, dName("IBEQ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGEZ, dName("IBEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGTZ, dName("IBGTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLEZ, dName("IBLEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLTZ, dName("IBLTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBNE, dName("IBNE"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_B, dName("B"); dImm11();) \ +MakeDisF(dis##VU##MI_BAL, dName("BAL"); dImm11(); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_JR, dName("JR"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_JALR, dName("JALR"); dCP232i(_Ft_); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_MFP, dNameU("MFP"); dCP2128f(_Ft_); dCP232i(REG_P);) \ +MakeDisF(dis##VU##MI_WAITP, dName("WAITP"); ) \ +MakeDisF(dis##VU##MI_ESADD, dName("ESADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ERSADD, dName("ERSADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ELENG, dName("ELENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERLENG, dName("ERLENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_EATANxy, dName("EATANxy"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_EATANxz, dName("EATANxz"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ESUM, dName("ESUM"); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERCPR, dName("ERCPR"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESQRT, dName("ESQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ERSQRT, dName("ERSQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESIN, dName("ESIN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EATAN, dName("EATAN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EEXP, dName("EEXP"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_XITOP, dName("XITOP"); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_XGKICK, dName("XGKICK"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_XTOP, dName("XTOP"); dCP232i(_Ft_);) \ + \ + \ +/*****************/ \ +/* UPPER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_ABS, dNameU("ABS"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ADD, dNameU("ADD"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDi, dNameU("ADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDq, dNameU("ADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDx, dNameU("ADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDy, dNameU("ADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDz, dNameU("ADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDw, dNameU("ADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDA, dNameU("ADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAi, dNameU("ADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDAq, dNameU("ADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDAx, dNameU("ADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAy, dNameU("ADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAz, dNameU("ADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAw, dNameU("ADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUB, dNameU("SUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBi, dNameU("SUBi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBq, dNameU("SUBq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBx, dNameU("SUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBy, dNameU("SUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBz, dNameU("SUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBw, dNameU("SUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBA, dNameU("SUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAi, dNameU("SUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBAq, dNameU("SUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBAx, dNameU("SUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAy, dNameU("SUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAz, dNameU("SUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAw, dNameU("SUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MUL, dNameU("MUL"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULi, dNameU("MULi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULq, dNameU("MULq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULx, dNameU("MULx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULy, dNameU("MULy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULz, dNameU("MULz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULw, dNameU("MULw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MULA, dNameU("MULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAi, dNameU("MULAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULAq, dNameU("MULAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULAx, dNameU("MULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAy, dNameU("MULAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAz, dNameU("MULAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAw, dNameU("MULAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADD, dNameU("MADD"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDi, dNameU("MADDi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDq, dNameU("MADDq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDx, dNameU("MADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDy, dNameU("MADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDz, dNameU("MADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDw, dNameU("MADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDA, dNameU("MADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAi, dNameU("MADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDAq, dNameU("MADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDAx, dNameU("MADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAy, dNameU("MADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAz, dNameU("MADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAw, dNameU("MADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUB, dNameU("MSUB"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBi, dNameU("MSUBi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBq, dNameU("MSUBq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBx, dNameU("MSUBx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBy, dNameU("MSUBy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBz, dNameU("MSUBz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBw, dNameU("MSUBw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBA, dNameU("MSUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAi, dNameU("MSUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBAq, dNameU("MSUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBAx, dNameU("MSUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAy, dNameU("MSUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAz, dNameU("MSUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAw, dNameU("MSUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MAX, dNameU("MAX"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXi, dNameU("MAXi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MAXx, dNameU("MAXx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXy, dNameU("MAXy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXz, dNameU("MAXz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXw, dNameU("MAXw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MINI, dNameU("MINI"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIi, dNameU("MINIi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MINIx, dNameU("MINIx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIy, dNameU("MINIy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIz, dNameU("MINIz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIw, dNameU("MINIw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMULA, dNameU("OPMULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMSUB, dNameU("OPMSUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_NOP, dName("NOP");) \ +MakeDisF(dis##VU##MI_FTOI0, dNameU("FTOI0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI4, dNameU("FTOI4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI12, dNameU("FTOI12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI15, dNameU("FTOI15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF0, dNameU("ITOF0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF4, dNameU("ITOF4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF12, dNameU("ITOF12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF15, dNameU("ITOF15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_CLIP, dNameU("CLIP"); dCP2128f(_Fs_); dCP232w(_Ft_);) \ + diff --git a/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.c b/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.c new file mode 100644 index 0000000..99d6baf --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.c @@ -0,0 +1,1063 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "cpuopsDebug.h" + +void UpdateR5900op() +{ + FILE *fp; + fp=fopen("cpuops.txt", "wt"); + fprintf(fp, "------------\n"); + fprintf(fp, "--R5900ops--\n"); + fprintf(fp, "------------\n"); + if(L_ADD>0) fprintf(fp, "Add %d\n", L_ADD); + if(L_ADDI>0) fprintf(fp, "Addi %d\n", L_ADDI); + if(L_ADDIU>0) fprintf(fp, "Addiu %d\n", L_ADDIU); + if(L_ADDU>0) fprintf(fp, "Addu %d\n", L_ADDU); + if(L_AND>0) fprintf(fp, "And %d\n", L_AND); + if(L_ANDI>0) fprintf(fp, "Andi %d\n", L_ANDI); + if(L_BEQ>0) fprintf(fp, "Beq %d\n", L_BEQ); + if(L_BEQL>0) fprintf(fp, "Beql %d\n", L_BEQL); + if(L_BGEZ>0) fprintf(fp, "Bgez %d\n", L_BGEZ); + if(L_BGEZAL>0) fprintf(fp, "Bgezal %d\n", L_BGEZAL); + if(L_BGEZALL>0) fprintf(fp, "Bgezall %d\n", L_BGEZALL); + if(L_BGEZL>0) fprintf(fp, "Bgezl %d\n", L_BGEZL); + if( L_BGTZ>0) fprintf(fp, "Bgtz %d\n", L_BGTZ); + if( L_BGTZL>0) fprintf(fp, "Bgtzl %d\n", L_BGTZL); + if(L_BLEZ>0) fprintf(fp, "Blez %d\n", L_BLEZ); + if(L_BLEZL>0) fprintf(fp, "blezl %d\n", L_BLEZL); + if(L_BLTZ>0) fprintf(fp, "bltz %d\n", L_BLTZ); + if(L_BLTZAL>0) fprintf(fp, "bltzal %d\n", L_BLTZAL); + if(L_BLTZALL>0) fprintf(fp, "bltzall %d\n", L_BLTZALL); + if(L_BLTZL>0) fprintf(fp, "bltzl %d\n", L_BLTZL); + if(L_BNE>0) fprintf(fp, "bne %d\n", L_BNE); + if(L_BNEL>0) fprintf(fp, "bnel %d\n", L_BNEL); + if(L_BREAK>0) fprintf(fp, "break %d\n", L_BREAK); + if(L_CACHE>0) fprintf(fp, "cache %d\n", L_CACHE); + if(L_DADD>0) fprintf(fp, "dadd %d\n", L_DADD); + if(L_DADDI>0) fprintf(fp, "daddi %d\n", L_DADDI); + if(L_DADDIU>0) fprintf(fp, "daddiu %d\n", L_DADDIU); + if(L_DADDU>0) fprintf(fp, "daddu %d\n", L_DADDU); + if(L_DIV>0) fprintf(fp, "div %d\n", L_DIV); + if(L_DIVU>0) fprintf(fp, "divu %d\n", L_DIVU); + if(L_DSLL>0) fprintf(fp, "dsll %d\n", L_DSLL); + if(L_DSLL32>0) fprintf(fp, "dsll32 %d\n", L_DSLL32); + if(L_DSLLV>0) fprintf(fp, "dsllv %d\n", L_DSLLV); + if(L_DSRA>0) fprintf(fp, "dsra %d\n", L_DSRA); + if(L_DSRA32>0) fprintf(fp, "dsra32 %d\n", L_DSRA32); + if(L_DSRAV>0) fprintf(fp, "dsrav %d\n", L_DSRAV); + if(L_DSRL>0) fprintf(fp, "dsrl %d\n", L_DSRL); + if(L_DSRL32>0) fprintf(fp, "dsr32 %d\n", L_DSRL32); + if(L_DSRLV>0) fprintf(fp, "dsrlv %d\n", L_DSRLV); + if(L_DSUB>0) fprintf(fp, "dsub %d\n", L_DSUB); + if(L_DSUBU>0) fprintf(fp, "dsubu %d\n", L_DSUBU); + if(L_J>0) fprintf(fp, "j %d\n", L_J); + if(L_JAL>0) fprintf(fp, "jal %d\n", L_JAL); + if(L_JALR>0) fprintf(fp, "jalr %d\n", L_JALR); + if(L_JR>0) fprintf(fp, "jr %d\n", L_JR); + if(L_LB>0) fprintf(fp, "lb %d\n", L_LB); + if(L_LBU>0) fprintf(fp, "lbu %d\n", L_LBU); + if(L_LD>0) fprintf(fp, "ld %d\n", L_LD); + if(L_LDL>0) fprintf(fp, "ldl %d\n", L_LDL); + if(L_LDR>0) fprintf(fp, "ldr %d\n", L_LDR); + if(L_LH>0) fprintf(fp, "lh %d\n", L_LH); + if(L_LHU>0) fprintf(fp, "lhu %d\n", L_LHU); + if(L_LQ>0) fprintf(fp, "lq %d\n", L_LQ); + if(L_LUI>0) fprintf(fp, "lui %d\n", L_LUI); + if(L_LW>0) fprintf(fp, "lw %d\n", L_LW); + if(L_LWL>0) fprintf(fp, "lwl %d\n", L_LWL); + if(L_LWR>0) fprintf(fp, "lwr %d\n", L_LWR); + if(L_LWU>0) fprintf(fp, "lwu %d\n", L_LWU); + if(L_MFHI>0) fprintf(fp, "mfhi %d\n", L_MFHI); + if(L_MFLO>0) fprintf(fp, "mflo %d\n", L_MFLO); + if(L_MFSA>0) fprintf(fp, "mfsa %d\n", L_MFSA); + if(L_MOVN>0) fprintf(fp, "movn %d\n", L_MOVN); + if(L_MOVZ>0) fprintf(fp, "movz %d\n", L_MOVZ); + if(L_MTHI>0) fprintf(fp, "mthi %d\n", L_MTHI); + if(L_MTLO>0) fprintf(fp, "mtlo %d\n", L_MTLO); + if(L_MTSA>0) fprintf(fp, "mtsa %d\n", L_MTSA); + if(L_MTSAB>0) fprintf(fp, "mtsab %d\n", L_MTSAB); + if(L_MTSAH>0) fprintf(fp, "mtsah %d\n", L_MTSAH); + if(L_MULT>0) fprintf(fp, "mult %d\n", L_MULT); + if(L_MULTU>0) fprintf(fp, "multu %d\n", L_MULTU); + if(L_NOR>0) fprintf(fp, "nor %d\n", L_NOR); + if(L_OR>0) fprintf(fp, "or %d\n", L_OR); + if(L_ORI>0) fprintf(fp, "ori %d\n", L_ORI); + if(L_PREF>0) fprintf(fp, "pref %d\n", L_PREF); + if(L_SB>0) fprintf(fp, "sb %d\n", L_SB); + if(L_SD>0) fprintf(fp, "sd %d\n", L_SD); + if(L_SDL>0) fprintf(fp, "sdl %d\n", L_SDL); + if(L_SDR>0) fprintf(fp, "sdr %d\n", L_SDR); + if(L_SH>0) fprintf(fp, "sh %d\n", L_SH); + if(L_SLL>0) fprintf(fp, "sll %d\n", L_SLL); + if(L_SLLV>0) fprintf(fp, "sllv %d\n", L_SLLV); + if(L_SLT>0) fprintf(fp, "slt %d\n", L_SLT); + if(L_SLTI>0) fprintf(fp, "slti %d\n", L_SLTI); + if(L_SLTIU>0) fprintf(fp, "sltiu %d\n", L_SLTIU); + if(L_SLTU>0) fprintf(fp, "sltu %d\n", L_SLTU); + if(L_SQ>0) fprintf(fp, "sq %d\n", L_SQ); + if(L_SRA>0) fprintf(fp, "sra %d\n", L_SRA); + if(L_SRAV>0) fprintf(fp, "srav %d\n", L_SRAV); + if(L_SRL>0) fprintf(fp, "srl %d\n", L_SRL); + if(L_SRLV>0) fprintf(fp, "srlv %d\n", L_SRLV); + if(L_SUB>0) fprintf(fp, "sub %d\n", L_SUB); + if(L_SUBU>0) fprintf(fp, "subu %d\n", L_SUBU); + if(L_SW>0) fprintf(fp, "sw %d\n", L_SW); + if(L_SWL>0) fprintf(fp, "swl %d\n", L_SWL); + if(L_SWR>0) fprintf(fp, "swr %d\n", L_SWR); + if(L_SYNC>0) fprintf(fp, "sync %d\n", L_SYNC); + if(L_SYSCALL>0) fprintf(fp, "syscall %d\n", L_SYSCALL); + if(L_TEQ>0) fprintf(fp, "teq %d\n", L_TEQ); + if(L_TEQI>0) fprintf(fp, "teqi %d\n", L_TEQI); + if(L_TGE>0) fprintf(fp, "tge %d\n", L_TGE); + if(L_TGEI>0) fprintf(fp, "tgei %d\n", L_TGEI); + if(L_TGEIU>0) fprintf(fp, "tgeiu %d\n", L_TGEIU); + if(L_TGEU>0) fprintf(fp, "tgeu %d\n", L_TGEU); + if(L_TLT>0) fprintf(fp, "tlt %d\n", L_TLT); + if(L_TLTI>0) fprintf(fp, "tlti %d\n", L_TLTI); + if(L_TLTIU>0) fprintf(fp, "tltiu %d\n", L_TLTIU); + if(L_TLTU>0) fprintf(fp, "tltu %d\n", L_TLTU); + if(L_TNE>0) fprintf(fp, "tne %d\n", L_TNE); + if(L_TNEI>0) fprintf(fp, "tnei %d\n", L_TNEI); + if(L_XOR>0) fprintf(fp, "xor %d\n", L_XOR); + if(L_XORI>0) fprintf(fp, "xori %d\n", L_XORI); + fprintf(fp, "------------\n"); + fprintf(fp, "--MMI ops--\n"); + fprintf(fp, "------------\n"); + if(L_DIV1>0) fprintf(fp, "div1 %d\n", L_DIV1); + if(L_DIVU1>0) fprintf(fp, "divu1 %d\n", L_DIVU1); + if(L_MADD>0) fprintf(fp, "madd %d\n", L_MADD); + if(L_MADD1>0) fprintf(fp, "madd1 %d\n", L_MADD1); + if(L_MADDU>0) fprintf(fp, "maddu %d\n", L_MADDU); + if(L_MADDU1>0) fprintf(fp, "maddu1 %d\n", L_MADDU1); + if(L_MFHI1>0) fprintf(fp, "mfhi1 %d\n", L_MFHI1); + if(L_MFLO1>0) fprintf(fp, "mflo1 %d\n", L_MFLO1); + if(L_MTHI1>0) fprintf(fp, "mthi1 %d\n", L_MTHI1); + if(L_MTLO1>0) fprintf(fp, "mtlo1 %d\n", L_MTLO1); + if(L_MULT1>0) fprintf(fp, "mult1 %d\n", L_MULT1); + if(L_MULTU1>0) fprintf(fp, "multu1 %d\n", L_MULTU1); + if(L_PABSH>0) fprintf(fp, "pabsh %d\n", L_PABSH); + if(L_PABSW>0) fprintf(fp, "pabsw %d\n", L_PABSW); + if(L_PADDB>0) fprintf(fp, "paddb %d\n", L_PADDB); + if(L_PADDH>0) fprintf(fp, "paddh %d\n", L_PADDH); + if(L_PADDSB>0) fprintf(fp, "paddsb %d\n", L_PADDSB); + if(L_PADDSH>0) fprintf(fp, "paddsh %d\n", L_PADDSH); + if(L_PADDSW>0) fprintf(fp, "paddsw %d\n", L_PADDSW); + if(L_PADDUB>0) fprintf(fp, "paddub %d\n", L_PADDUB); + if(L_PADDUH>0) fprintf(fp, "padduh %d\n", L_PADDUH); + if(L_PADDUW>0) fprintf(fp, "padduw %d\n", L_PADDUW); + if(L_PADDW>0) fprintf(fp, "paddw %d\n", L_PADDW); + if(L_PADSBH>0) fprintf(fp, "padsbh %d\n", L_PADSBH); + if(L_PAND>0) fprintf(fp, "pand %d\n", L_PAND); + if(L_PCEQB>0) fprintf(fp, "pceqb %d\n", L_PCEQB); + if(L_PCEQH>0) fprintf(fp, "pceqh %d\n", L_PCEQH); + if(L_PCEQW>0) fprintf(fp, "pceqw %d\n", L_PCEQW); + if(L_PCGTB>0) fprintf(fp, "pcgtb %d\n", L_PCGTB); + if(L_PCGTH>0) fprintf(fp, "pcgth %d\n", L_PCGTH); + if(L_PCGTW>0) fprintf(fp, "pcgtw %d\n", L_PCGTW); + if(L_PCPYH>0) fprintf(fp, "pcpyh %d\n", L_PCPYH); + if(L_PCPYLD>0) fprintf(fp, "pcpyld %d\n", L_PCPYLD); + if(L_PCPYUD>0) fprintf(fp, "pcpyud %d\n", L_PCPYUD); + if(L_PDIVBW>0) fprintf(fp, "pdivbw %d\n", L_PDIVBW); + if(L_PDIVUW>0) fprintf(fp, "pdivuw %d\n", L_PDIVUW); + if(L_PDIVW>0) fprintf(fp, "pdivw %d\n", L_PDIVW); + if(L_PEXCH>0) fprintf(fp, "pexch %d\n", L_PEXCH); + if(L_PEXCW>0) fprintf(fp, "pexcw %d\n", L_PEXCW); + if(L_PEXEH>0) fprintf(fp, "pexeh %d\n", L_PEXEH); + if(L_PEXEW>0) fprintf(fp, "pexew %d\n", L_PEXEW); + if(L_PEXT5>0) fprintf(fp, "pext5 %d\n", L_PEXT5); + if(L_PEXTLB>0) fprintf(fp, "pextlb %d\n", L_PEXTLB); + if(L_PEXTLH>0) fprintf(fp, "pextlh %d\n", L_PEXTLH); + if(L_PEXTLW>0) fprintf(fp, "pextlw %d\n", L_PEXTLW); + if(L_PEXTUB>0) fprintf(fp, "pextub %d\n", L_PEXTUB); + if(L_PEXTUH>0) fprintf(fp, "pextuh %d\n", L_PEXTUH); + if(L_PEXTUW>0) fprintf(fp, "pextuw %d\n", L_PEXTUW); + if(L_PHMADH>0) fprintf(fp, "phmadh %d\n", L_PHMADH); + if(L_PHMSBH>0) fprintf(fp, "phmsbh %d\n", L_PHMSBH); + if(L_PINTEH>0) fprintf(fp, "pinteh %d\n", L_PINTEH); + if(L_PINTH>0) fprintf(fp, "pinth %d\n", L_PINTH); + if(L_PLZCW>0) fprintf(fp, "plzcw %d\n", L_PLZCW); + if(L_PMADDH>0) fprintf(fp, "pmaddh %d\n", L_PMADDH); + if(L_PMADDUW>0) fprintf(fp, "pmadduw %d\n", L_PMADDUW); + if(L_PMADDW>0) fprintf(fp, "pmaddw %d\n", L_PMADDW); + if(L_PMAXH>0) fprintf(fp, "pmaxh %d\n", L_PMAXH); + if(L_PMAXW>0) fprintf(fp, "pmaxw %d\n", L_PMAXW); + if(L_PMFHI>0) fprintf(fp, "pmfhi %d\n", L_PMFHI); + if(L_PMFHL>0) fprintf(fp, "pmfhl %d\n", L_PMFHL); + if(L_PMFLO>0) fprintf(fp, "pmflo %d\n", L_PMFLO); + if(L_PMINH>0) fprintf(fp, "pminh %d\n", L_PMINH); + if(L_PMINW>0) fprintf(fp, "pminw %d\n", L_PMINW); + if(L_PMSUBH>0) fprintf(fp, "pmsubh %d\n", L_PMSUBH); + if(L_PMSUBW>0) fprintf(fp, "pmsubw %d\n", L_PMSUBW); + if(L_PMTHI>0) fprintf(fp, "pmthi %d\n", L_PMTHI); + if(L_PMTHL>0) fprintf(fp, "pmthl %d\n", L_PMTHL); + if(L_PMTLO>0) fprintf(fp, "pmtlo %d\n", L_PMTLO); + if(L_PMULTH>0) fprintf(fp, "pmulth %d\n", L_PMULTH); + if(L_PMULTUW>0) fprintf(fp, "pmultuw %d\n", L_PMULTUW); + if(L_PMULTW>0) fprintf(fp, "pmultw %d\n", L_PMULTW); + if(L_PNOR>0) fprintf(fp, "pnor %d\n", L_PNOR); + if(L_POR>0) fprintf(fp, "por %d\n", L_POR); + if(L_PPAC5>0) fprintf(fp, "ppac5 %d\n", L_PPAC5); + if(L_PPACB>0) fprintf(fp, "ppacb %d\n", L_PPACB); + if(L_PPACH>0) fprintf(fp, "ppach %d\n", L_PPACH); + if(L_PPACW>0) fprintf(fp, "ppacw %d\n", L_PPACW); + if(L_PREVH>0) fprintf(fp, "prevh %d\n", L_PREVH); + if(L_PROT3W>0) fprintf(fp, "prot3w %d\n", L_PROT3W); + if(L_PSLLH>0) fprintf(fp, "psllh %d\n", L_PSLLH); + if(L_PSLLVW>0) fprintf(fp, "psllvw %d\n", L_PSLLVW); + if(L_PSLLW>0) fprintf(fp, "psllw %d\n", L_PSLLW); + if(L_PSRAH>0) fprintf(fp, "psrah %d\n", L_PSRAH); + if(L_PSRAVW>0) fprintf(fp, "psravw %d\n", L_PSRAVW); + if(L_PSRAW>0) fprintf(fp, "psraw %d\n", L_PSRAW); + if(L_PSRLH>0) fprintf(fp, "psrlh %d\n", L_PSRLH); + if(L_PSRLVW>0) fprintf(fp, "psrlvw %d\n", L_PSRLVW); + if(L_PSRLW>0) fprintf(fp, "psrlw %d\n", L_PSRLW); + if(L_PSUBB>0) fprintf(fp, "psubb %d\n", L_PSUBB); + if(L_PSUBH>0) fprintf(fp, "psubh %d\n", L_PSUBH); + if(L_PSUBSB>0) fprintf(fp, "psubsb %d\n", L_PSUBSB); + if(L_PSUBSH>0) fprintf(fp, "psubsh %d\n", L_PSUBSH); + if(L_PSUBSW>0) fprintf(fp, "psubsw %d\n", L_PSUBSW); + if(L_PSUBUB>0) fprintf(fp, "psubub %d\n", L_PSUBUB); + if(L_PSUBUH>0) fprintf(fp, "psubuh %d\n", L_PSUBUH); + if(L_PSUBUW>0) fprintf(fp, "psubuw %d\n", L_PSUBUW); + if(L_PSUBW>0) fprintf(fp, "psubw %d\n", L_PSUBW); + if(L_PXOR>0) fprintf(fp, "pxor %d\n", L_PXOR); + if(L_QFSRV>0) fprintf(fp, "qfsrv %d\n", L_QFSRV); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP0 ops--\n"); + fprintf(fp, "------------\n"); + if(L_BC0F>0) fprintf(fp, "bc0f %d\n", L_BC0F); + if(L_BC0FL>0) fprintf(fp, "bc0fl %d\n", L_BC0FL); + if(L_BC0T>0) fprintf(fp, "bc0t %d\n", L_BC0T); + if(L_BC0TL>0) fprintf(fp, "bc0tl %d\n", L_BC0TL); + if(L_DI>0) fprintf(fp, "di %d\n", L_DI); + if(L_EI>0) fprintf(fp, "ei %d\n", L_EI); + if(L_ERET>0) fprintf(fp, "eret %d\n", L_ERET); + if(L_MTC0>0) fprintf(fp, "mtc0 %d\n", L_MTC0); + if(L_TLBP>0) fprintf(fp, "tlbp %d\n", L_TLBP); + if(L_TLBR>0) fprintf(fp, "tlbr %d\n", L_TLBR); + if(L_TLBWI>0) fprintf(fp, "tlbwi %d\n", L_TLBWI); + if(L_TLBWR>0) fprintf(fp, "tlbwr %d\n", L_TLBWR); + if(L_MFC0>0) fprintf(fp, "mfc0 %d\n", L_MFC0); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP1 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LWC1>0) fprintf(fp, "lwc1 %d\n", L_LWC1); + if(L_SWC1>0) fprintf(fp, "swc1 %d\n", L_SWC1); + if(L_ABS_S>0) fprintf(fp, "abs_s %d\n", L_ABS_S); + if(L_ADD_S>0) fprintf(fp, "add_s %d\n", L_ADD_S); + if(L_ADDA_S>0) fprintf(fp, "adda_s %d\n", L_ADDA_S); + if(L_BC1F>0) fprintf(fp, "bc1f %d\n", L_BC1F); + if(L_BC1FL>0) fprintf(fp, "bc1fl %d\n", L_BC1FL); + if(L_BC1T>0) fprintf(fp, "bc1t %d\n", L_BC1T); + if(L_BC1TL>0) fprintf(fp, "bc1tl %d\n", L_BC1TL); + if(L_C_EQ>0) fprintf(fp, "c_eq %d\n", L_C_EQ); + if(L_C_F>0) fprintf(fp, "c_f %d\n", L_C_F); + if(L_C_LE>0) fprintf(fp, "c_le %d\n", L_C_LE); + if(L_C_LT>0) fprintf(fp, "c_lt %d\n", L_C_LT); + if(L_CFC1>0) fprintf(fp, "cfc1 %d\n", L_CFC1); + if(L_CTC1>0) fprintf(fp, "ctc1 %d\n", L_CTC1); + if(L_CVT_S>0) fprintf(fp, "cvt_s %d\n", L_CVT_S); + if(L_CVT_W>0) fprintf(fp, "cvt_w %d\n", L_CVT_W); + if(L_DIV_S>0) fprintf(fp, "div_s %d\n", L_DIV_S); + if(L_MADD_S>0) fprintf(fp, "madd_s %d\n", L_MADD_S); + if(L_MADDA_S>0) fprintf(fp, "madda_s %d\n", L_MADDA_S); + if(L_MAX_S>0) fprintf(fp, "max_s %d\n", L_MAX_S); + if(L_MFC1>0) fprintf(fp, "mfc1 %d\n", L_MFC1); + if(L_MIN_S>0) fprintf(fp, "min_s %d\n", L_MIN_S); + if(L_MOV_S>0) fprintf(fp, "mov_s %d\n", L_MOV_S); + if(L_MSUB_S>0) fprintf(fp, "msub_s %d\n", L_MSUB_S); + if(L_MSUBA_S>0) fprintf(fp, "msuba_s %d\n", L_MSUBA_S); + if(L_MTC1>0) fprintf(fp, "mtc1 %d\n", L_MTC1); + if(L_MUL_S>0) fprintf(fp, "mul_s %d\n", L_MUL_S); + if(L_MULA_S>0) fprintf(fp, "mula_s %d\n", L_MULA_S); + if(L_NEG_S>0) fprintf(fp, "neg_s %d\n", L_NEG_S); + if(L_RSQRT_S>0) fprintf(fp, "rsqrt_s %d\n", L_RSQRT_S); + if(L_SQRT_S>0) fprintf(fp, "sqrt_s %d\n", L_SQRT_S); + if(L_SUB_S>0) fprintf(fp, "sub_s %d\n", L_SUB_S); + if(L_SUBA_S>0) fprintf(fp, "suba_s %d\n", L_SUBA_S); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP2 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LQC2>0) fprintf(fp, "lqc2 %d\n", L_LQC2); + if(L_SQC2>0) fprintf(fp, "sqc2 %d\n", L_SQC2); + if(L_BC2F>0) fprintf(fp, "bc2f %d\n", L_BC2F); + if(L_BC2FL>0) fprintf(fp, "bc2fl %d\n", L_BC2FL); + if(L_BC2T>0) fprintf(fp, "bc2t %d\n", L_BC2T); + if(L_BC2TL>0) fprintf(fp, "bc2tl %d\n", L_BC2TL); + if(L_CFC2>0) fprintf(fp, "cfc2 %d\n", L_CFC2); + if(L_CTC2>0) fprintf(fp, "ctc2 %d\n", L_CTC2); + if(L_QMFC2>0) fprintf(fp, "qmfc2 %d\n", L_QMFC2); + if(L_QMTC2>0) fprintf(fp, "qmtc2 %d\n", L_QMTC2); + if(L_VABS>0) fprintf(fp, "vabs %d\n", L_VABS); + if(L_VADD>0) fprintf(fp, "vadd %d\n", L_VADD); + if(L_VADDA>0) fprintf(fp, "vadda %d\n", L_VADDA); + if(L_VADDAi>0) fprintf(fp, "vaddai %d\n", L_VADDAi); + if(L_VADDAq>0) fprintf(fp, "vaddaq %d\n", L_VADDAq); + if(L_VADDAw>0) fprintf(fp, "vaddaw %d\n", L_VADDAw); + if(L_VADDAx>0) fprintf(fp, "vaddax %d\n", L_VADDAx); + if(L_VADDAy>0) fprintf(fp, "vadday %d\n", L_VADDAy); + if(L_VADDAz>0) fprintf(fp, "vaddaz %d\n", L_VADDAz); + if(L_VADDi>0) fprintf(fp, "vaddi %d\n", L_VADDi); + if(L_VADDq>0) fprintf(fp, "vaddq %d\n", L_VADDq); + if(L_VADDw>0) fprintf(fp, "vaddw %d\n", L_VADDw); + if(L_VADDx>0) fprintf(fp, "vaddx %d\n", L_VADDx); + if(L_VADDy>0) fprintf(fp, "vaddy %d\n", L_VADDy); + if(L_VADDz>0) fprintf(fp, "vaddz %d\n", L_VADDz); + if(L_VCALLMS>0) fprintf(fp, "vcallms %d\n", L_VCALLMS); + if(L_VCALLMSR>0) fprintf(fp, "vcallmsr %d\n", L_VCALLMSR); + if(L_VCLIPw>0) fprintf(fp, "vclip %d\n", L_VCLIPw); + if(L_VDIV>0) fprintf(fp, "vdiv %d\n", L_VDIV); + if(L_VFTOI0>0) fprintf(fp, "vftoi0 %d\n", L_VFTOI0); + if(L_VFTOI12>0) fprintf(fp, "vftoi12 %d\n", L_VFTOI12); + if(L_VFTOI15>0) fprintf(fp, "vftoi15 %d\n", L_VFTOI15); + if(L_VFTOI4>0) fprintf(fp, "vftoi14 %d\n", L_VFTOI4); + if(L_VIADD>0) fprintf(fp, "viadd %d\n", L_VIADD); + if(L_VIADDI>0) fprintf(fp, "viaddi %d\n", L_VIADDI); + if(L_VIAND>0) fprintf(fp, "viand %d\n", L_VIAND); + if(L_VILWR>0) fprintf(fp, "vilwr %d\n", L_VILWR); + if(L_VIOR>0) fprintf(fp, "vior %d\n", L_VIOR); + if(L_VISUB>0) fprintf(fp, "visub %d\n", L_VISUB); + if(L_VISWR>0) fprintf(fp, "viswr %d\n", L_VISWR); + if(L_VITOF0>0) fprintf(fp, "vitof0 %d\n", L_VITOF0); + if(L_VITOF12>0) fprintf(fp, "vitof12 %d\n", L_VITOF12); + if(L_VITOF15>0) fprintf(fp, "vitof15 %d\n", L_VITOF15); + if(L_VITOF4>0) fprintf(fp, "vitof4 %d\n", L_VITOF4); + if(L_VLQD>0) fprintf(fp, "vlqd %d\n", L_VLQD); + if(L_VLQI>0) fprintf(fp, "vlqi %d\n", L_VLQI); + if(L_VMADD>0) fprintf(fp, "vmadd %d\n", L_VMADD); + if(L_VMADDA>0) fprintf(fp, "vmadda %d\n", L_VMADDA); + if(L_VMADDAi>0) fprintf(fp, "vmaddai %d\n", L_VMADDAi); + if(L_VMADDAq>0) fprintf(fp, "vmaddaq %d\n", L_VMADDAq); + if(L_VMADDAw>0) fprintf(fp, "vmaddaw %d\n", L_VMADDAw); + if(L_VMADDAx>0) fprintf(fp, "vmaddax %d\n", L_VMADDAx); + if(L_VMADDAy>0) fprintf(fp, "vmadday %d\n", L_VMADDAy); + if(L_VMADDAz>0) fprintf(fp, "vmaddaz %d\n", L_VMADDAz); + if(L_VMADDi>0) fprintf(fp, "vmaddi %d\n", L_VMADDi); + if(L_VMADDq>0) fprintf(fp, "vmaddq %d\n", L_VMADDq); + if(L_VMADDw>0) fprintf(fp, "vmaddw %d\n", L_VMADDw); + if(L_VMADDx>0) fprintf(fp, "vmaddx %d\n", L_VMADDx); + if(L_VMADDy>0) fprintf(fp, "vmaddy %d\n", L_VMADDy); + if(L_VMADDz>0) fprintf(fp, "vmaddz %d\n", L_VMADDz); + if(L_VMAX>0) fprintf(fp, "vmax %d\n", L_VMAX); + if(L_VMAXi>0) fprintf(fp, "vmaxi %d\n", L_VMAXi); + if(L_VMAXw>0) fprintf(fp, "vmaxw %d\n", L_VMAXw); + if(L_VMAXx>0) fprintf(fp, "vmaxx %d\n", L_VMAXx); + if(L_VMAXy>0) fprintf(fp, "vmaxy %d\n", L_VMAXy); + if(L_VMAXz>0) fprintf(fp, "vmaxz %d\n", L_VMAXz); + if(L_VMFIR>0) fprintf(fp, "vmfir %d\n", L_VMFIR); + if(L_VMINI>0) fprintf(fp, "vmini %d\n", L_VMINI); + if(L_VMINIi>0) fprintf(fp, "vminii %d\n", L_VMINIi); + if(L_VMINIw>0) fprintf(fp, "vminiw %d\n", L_VMINIw); + if(L_VMINIx>0) fprintf(fp, "vminix %d\n", L_VMINIx); + if(L_VMINIy>0) fprintf(fp, "vminiy %d\n", L_VMINIy); + if(L_VMINIz>0) fprintf(fp, "vminiz %d\n", L_VMINIz); + if(L_VMOVE>0) fprintf(fp, "vmove %d\n", L_VMOVE); + if(L_VMR32>0) fprintf(fp, "vmr32 %d\n", L_VMR32); + if(L_VMSUB>0) fprintf(fp, "vmsub %d\n", L_VMSUB); + if(L_VMSUBA>0) fprintf(fp, "vmsuba %d\n", L_VMSUBA); + if(L_VMSUBAi>0) fprintf(fp, "vmsubai %d\n", L_VMSUBAi); + if(L_VMSUBAq>0) fprintf(fp, "vmsubaq %d\n", L_VMSUBAq); + if(L_VMSUBAw>0) fprintf(fp, "vmsubaw %d\n", L_VMSUBAw); + if(L_VMSUBAx>0) fprintf(fp, "vmsubax %d\n", L_VMSUBAx); + if(L_VMSUBAy>0) fprintf(fp, "vmsubay %d\n", L_VMSUBAy); + if(L_VMSUBAz>0) fprintf(fp, "vmsubaz %d\n", L_VMSUBAz); + if(L_VMSUBi>0) fprintf(fp, "vmsubi %d\n", L_VMSUBi); + if(L_VMSUBq>0) fprintf(fp, "vmsubq %d\n", L_VMSUBq); + if(L_VMSUBw>0) fprintf(fp, "vmsubw %d\n", L_VMSUBw); + if(L_VMSUBx>0) fprintf(fp, "vmsubx %d\n", L_VMSUBx); + if(L_VMSUBy>0) fprintf(fp, "vmsuby %d\n", L_VMSUBy); + if(L_VMSUBz>0) fprintf(fp, "vmsubz %d\n", L_VMSUBz); + if(L_VMTIR>0) fprintf(fp, "vmtir %d\n", L_VMTIR); + if(L_VMUL>0) fprintf(fp, "vmul %d\n", L_VMUL); + if(L_VMULA>0) fprintf(fp, "vmula %d\n", L_VMULA); + if(L_VMULAi>0) fprintf(fp, "vmulai %d\n", L_VMULAi); + if(L_VMULAq>0) fprintf(fp, "vmulaq %d\n", L_VMULAq); + if(L_VMULAw>0) fprintf(fp, "vmulaw %d\n", L_VMULAw); + if(L_VMULAx>0) fprintf(fp, "vmulax %d\n", L_VMULAx); + if(L_VMULAy>0) fprintf(fp, "vmulay %d\n", L_VMULAy); + if(L_VMULAz>0) fprintf(fp, "vmulaz %d\n", L_VMULAz); + if(L_VMULi>0) fprintf(fp, "vmuli %d\n", L_VMULi); + if(L_VMULq>0) fprintf(fp, "vmulq %d\n", L_VMULq); + if(L_VMULw>0) fprintf(fp, "vmulw %d\n", L_VMULw); + if(L_VMULx>0) fprintf(fp, "vmulx %d\n", L_VMULx); + if(L_VMULy>0) fprintf(fp, "vmuly %d\n", L_VMULy); + if(L_VMULz>0) fprintf(fp, "vmulz %d\n", L_VMULz); + if(L_VNOP>0) fprintf(fp, "vnop %d\n", L_VNOP); + if(L_VOPMSUB>0) fprintf(fp, "vopmsub %d\n", L_VOPMSUB); + if(L_VOPMULA>0) fprintf(fp, "vopmula %d\n", L_VOPMULA); + if(L_VRGET>0) fprintf(fp, "vrget %d\n", L_VRGET); + if(L_VRINIT>0) fprintf(fp, "vrinit %d\n", L_VRINIT); + if(L_VRNEXT>0) fprintf(fp, "vrnext %d\n", L_VRNEXT); + if(L_VRSQRT>0) fprintf(fp, "vrsqrt %d\n", L_VRSQRT); + if(L_VRXOR>0) fprintf(fp, "vrxor %d\n", L_VRXOR); + if(L_VSQD>0) fprintf(fp, "vsqd %d\n", L_VSQD); + if(L_VSQI>0) fprintf(fp, "vsqi %d\n", L_VSQI); + if(L_VSQRT>0) fprintf(fp, "vsqrt %d\n", L_VSQRT ); + if(L_VSUB>0) fprintf(fp, "vsub %d\n", L_VSUB); + if(L_VSUBA>0) fprintf(fp, "vsuba %d\n", L_VSUBA); + if(L_VSUBAi>0) fprintf(fp, "vsubai %d\n", L_VSUBAi); + if(L_VSUBAq>0) fprintf(fp, "vsubaq %d\n", L_VSUBAq); + if(L_VSUBAw>0) fprintf(fp, "vsubaw %d\n", L_VSUBAw); + if(L_VSUBAx>0) fprintf(fp, "vsubax %d\n", L_VSUBAx); + if(L_VSUBAy>0) fprintf(fp, "vsubay %d\n", L_VSUBAy); + if(L_VSUBAz>0) fprintf(fp, "vsubaz %d\n", L_VSUBAz); + if(L_VSUBi>0) fprintf(fp, "vsubi %d\n", L_VSUBi); + if(L_VSUBq>0) fprintf(fp, "vsubq %d\n", L_VSUBq); + if(L_VSUBw>0) fprintf(fp, "vsubw %d\n", L_VSUBw); + if(L_VSUBx>0) fprintf(fp, "vsubx %d\n", L_VSUBx); + if(L_VSUBy>0) fprintf(fp, "vsuby %d\n", L_VSUBy); + if(L_VSUBz>0) fprintf(fp, "vsubz %d\n", L_VSUBz); + if(L_VWAITQ>0) fprintf(fp, "vwaitq %d\n", L_VWAITQ); + + fclose(fp); + +} + + + + + + + + + + + +/***************/ +//R5900 +void LT_SPECIAL() {LT_SpecialPrintTable[_Funct_]();} +void LT_REGIMM() {LT_REGIMMPrintTable[_Rt_](); } +void LT_UnknownOpcode() {} +void LT_ADDI() { L_ADDI++;} +void LT_ADDIU() { L_ADDIU++;} +void LT_DADDI() { L_DADDI++;} +void LT_DADDIU(){ L_DADDIU++;} +void LT_ANDI() { L_ANDI++;} +void LT_ORI() { L_ORI++;} +void LT_XORI() {L_XORI++;} +void LT_SLTI() {L_SLTI++;} +void LT_SLTIU() {L_SLTIU++;} +void LT_ADD() { L_ADD++;} +void LT_ADDU() { L_ADDU++;} +void LT_DADD() { L_DADD++;} +void LT_DADDU() { L_DADDU++;} +void LT_SUB() { L_SUB++;} +void LT_SUBU() { L_SUBU++;} +void LT_DSUB() { L_DSUB++;} +void LT_DSUBU() { L_DSUBU++;} +void LT_AND() { L_AND++;} +void LT_OR() { L_OR++;} +void LT_XOR() { L_XOR++;} +void LT_NOR() { L_NOR++;} +void LT_SLT() { L_SLT++;} +void LT_SLTU() { L_SLTU++;} +void LT_J() { L_J++;} +void LT_JAL() { L_JAL++;} +void LT_JR() { L_JR++;} +void LT_JALR() { L_JALR++;} +void LT_DIV() { L_DIV++;} +void LT_DIVU() { L_DIVU++;} +void LT_MULT() { L_MULT++;} +void LT_MULTU() { L_MULTU++;} +void LT_LUI() { L_LUI++;} +void LT_MFHI() { L_MFHI++;} +void LT_MFLO() { L_MFLO++;} +void LT_MTHI() { L_MTHI++;} +void LT_MTLO() { L_MTLO++;} +void LT_SLL() { L_SLL++;} +void LT_DSLL() { L_DSLL++;} +void LT_DSLL32(){ L_DSLL32++;} +void LT_SRA() { L_SRA++;} +void LT_DSRA() { L_DSRA++;} +void LT_DSRA32(){ L_DSRA32++;} +void LT_SRL() { L_SRL++;} +void LT_DSRL() { L_DSRL++;} +void LT_DSRL32(){ L_DSRL32++;} +void LT_SLLV() { L_SLLV++;} +void LT_SRAV() { L_SRAV++;} +void LT_SRLV() { L_SRLV++;} +void LT_DSLLV() { L_DSLLV++;} +void LT_DSRAV() { L_DSRAV++;} +void LT_DSRLV() { L_DSRLV++;} +void LT_BEQ() { L_BEQ++;} +void LT_BNE() { L_BNE++;} +void LT_BGEZ() { L_BGEZ++;} +void LT_BGEZAL(){ L_BGEZAL++;} +void LT_BGTZ() { L_BGTZ++;} +void LT_BLEZ() { L_BLEZ++;} +void LT_BLTZ() { L_BLTZ++;} +void LT_BLTZAL(){ L_BLTZAL++;} +void LT_BEQL() { L_BEQL++;} +void LT_BNEL() { L_BNEL++;} +void LT_BLEZL() { L_BLEZL++;} +void LT_BGTZL() { L_BGTZL++;} +void LT_BLTZL() { L_BLTZL++;} +void LT_BGEZL() { L_BGEZL++;} +void LT_BLTZALL(){ L_BLTZALL++;} +void LT_BGEZALL(){ L_BGEZALL++;} +void LT_LB() {L_LB++;} +void LT_LBU() {L_LBU++;} +void LT_LH() {L_LH++;} +void LT_LHU() {L_LHU++;} +void LT_LW() {L_LW++;} +void LT_LWU() {L_LWU++;} +void LT_LWL() {L_LWL++;} +void LT_LWR() {L_LWR++;} +void LT_LD() {L_LD++;} +void LT_LDL() {L_LDL++;} +void LT_LDR() {L_LDR++;} +void LT_LQ() {L_LQ++;} +void LT_SB() {L_SB++;} +void LT_SH() {L_SH++;} +void LT_SW() {L_SW++;} +void LT_SWL() {L_SWL++;} +void LT_SWR() {L_SWR++;} +void LT_SD() {L_SD++;} +void LT_SDL() {L_SDL++;} +void LT_SDR() {L_SDR++;} +void LT_SQ() {L_SQ++;} +void LT_MOVZ() {L_MOVZ++;} +void LT_MOVN() {L_MOVN++;} +void LT_SYSCALL() {L_SYSCALL++;} +void LT_BREAK() {L_BREAK++;} +void LT_CACHE() {L_CACHE++;} +void LT_MFSA() {L_MFSA++;} +void LT_MTSA() {L_MTSA++;} +void LT_SYNC() {L_SYNC++;} +void LT_PREF() {L_PREF++;} +void LT_TGE() {L_TGE++;} +void LT_TGEU() {L_TGEU++;} +void LT_TLT() {L_TLT++;} +void LT_TLTU() {L_TLTU++;} +void LT_TEQ() {L_TEQ++;} +void LT_TNE() {L_TNE++;} +void LT_TGEI() {L_TGEI++;} +void LT_TGEIU() {L_TGEIU++;} +void LT_TLTI() {L_TLTI++;} +void LT_TLTIU() {L_TLTIU++;} +void LT_TEQI() {L_TEQI++;} +void LT_TNEI() {L_TNEI++;} +void LT_MTSAB() {L_MTSAB++;} +void LT_MTSAH() {L_MTSAH++;} +//cop0 +void LT_COP0(){ LT_COP0PrintTable[_Rs_]();} +void LT_COP0_BC0() {LT_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03]();} +void LT_COP0_Func() { LT_COP0C0PrintTable[_Funct_](); } +void LT_COP0_Unknown() { } +void LT_MFC0() {L_MFC0++;} +void LT_MTC0() {L_MTC0++;} +void LT_BC0F() {L_BC0F++;} +void LT_BC0T() {L_BC0T++;} +void LT_BC0FL(){L_BC0FL++;} +void LT_BC0TL(){L_BC0TL++;} +void LT_TLBR() {L_TLBR++;} +void LT_TLBWI(){L_TLBWI++;} +void LT_TLBWR(){L_TLBWR++;} +void LT_TLBP() {L_TLBP++;} +void LT_ERET() {L_ERET++;} +void LT_DI() {L_DI++;} +void LT_EI() {L_EI++;} +//mmi +void LT_MMI() {LT_MMIPrintTable[_Funct_]();} +void LT_MMI0() {LT_MMI0PrintTable[_Sa_]();} +void LT_MMI1() {LT_MMI1PrintTable[_Sa_]();} +void LT_MMI2() {LT_MMI2PrintTable[_Sa_]();} +void LT_MMI3() {LT_MMI3PrintTable[_Sa_]();} +void LT_MMI_Unknown() {} +void LT_MADD() {L_MADD++;} +void LT_MADDU(){L_MADDU++;} +void LT_PLZCW(){L_PLZCW++;} +void LT_MADD1(){L_MADD1++;} +void LT_MADDU1(){L_MADDU1++;} +void LT_MFHI1(){L_MFHI1++;} +void LT_MTHI1(){L_MTHI1++;} +void LT_MFLO1(){L_MFLO1++;} +void LT_MTLO1(){L_MTLO1++;} +void LT_MULT1(){L_MULT1++;} +void LT_MULTU1(){L_MULTU1++;} +void LT_DIV1(){L_DIV1++;} +void LT_DIVU1(){L_DIVU1++;} +void LT_PMFHL(){L_PMFHL++;} +void LT_PMTHL(){L_PMTHL++;} +void LT_PSLLH(){L_PSLLH++;} +void LT_PSRLH(){L_PSRLH++;} +void LT_PSRAH(){L_PSRAH++;} +void LT_PSLLW(){L_PSLLW++;} +void LT_PSRLW(){L_PSRLW++;} +void LT_PSRAW(){L_PSRAW++;} +void LT_PADDW(){L_PADDW++;} +void LT_PSUBW(){L_PSUBW++;} +void LT_PCGTW(){L_PCGTW++;} +void LT_PMAXW(){L_PMAXW++;} +void LT_PADDH(){L_PADDH++;} +void LT_PSUBH(){L_PSUBH++;} +void LT_PCGTH(){L_PCGTH++;} +void LT_PMAXH(){L_PMAXH++;} +void LT_PADDB(){L_PADDB++;} +void LT_PSUBB(){L_PSUBB++;} +void LT_PCGTB(){L_PCGTB++;} +void LT_PADDSW(){L_PADDSW++;} +void LT_PSUBSW(){L_PSUBSW++;} +void LT_PEXTLW(){L_PEXTLW++;} +void LT_PPACW(){L_PPACW++;} +void LT_PADDSH(){L_PADDSH++;} +void LT_PSUBSH(){L_PSUBSH++;} +void LT_PEXTLH(){L_PEXTLH++;} +void LT_PPACH(){L_PPACH++;} +void LT_PADDSB(){L_PADDSB++;} +void LT_PSUBSB(){L_PSUBSB++;} +void LT_PEXTLB(){L_PEXTLB++;} +void LT_PPACB(){L_PPACB++;} +void LT_PEXT5(){L_PEXT5++;} +void LT_PPAC5(){L_PPAC5++;} +void LT_PABSW(){L_PABSW++;} +void LT_PCEQW(){L_PCEQW++;} +void LT_PMINW(){L_PMINW++;} +void LT_PADSBH(){L_PADSBH++;} +void LT_PABSH(){L_PABSH++;} +void LT_PCEQH(){L_PCEQH++;} +void LT_PMINH(){L_PMINH++;} +void LT_PCEQB(){L_PCEQB++;} +void LT_PADDUW(){L_PADDUW++;} +void LT_PSUBUW(){L_PSUBUW++;} +void LT_PEXTUW(){L_PEXTUW++;} +void LT_PADDUH(){L_PADDUH++;} +void LT_PSUBUH(){L_PSUBUH++;} +void LT_PEXTUH(){L_PEXTUH++;} +void LT_PADDUB(){L_PADDUB++;} +void LT_PSUBUB(){L_PSUBUB++;} +void LT_PEXTUB(){L_PEXTUB++;} +void LT_QFSRV(){L_QFSRV++;} +void LT_PMADDW(){L_PMADDW++;} +void LT_PSLLVW(){L_PSLLVW++;} +void LT_PSRLVW(){L_PSRLVW++;} +void LT_PMSUBW(){L_PMSUBW++;} +void LT_PMFHI(){L_PMFHI++;} +void LT_PMFLO(){L_PMFLO++;} +void LT_PINTH(){L_PINTH++;} +void LT_PMULTW(){L_PMULTW++;} +void LT_PDIVW(){L_PDIVW++;} +void LT_PCPYLD(){L_PCPYLD++;} +void LT_PMADDH(){L_PMADDH++;} +void LT_PHMADH(){L_PHMADH++;} +void LT_PAND(){L_PAND++;} +void LT_PXOR(){L_PXOR++;} +void LT_PMSUBH(){L_PMSUBH++;} +void LT_PHMSBH(){L_PHMSBH++;} +void LT_PEXEH(){L_PEXEH++;} +void LT_PREVH(){L_PREVH++;} +void LT_PMULTH(){L_PMULTH++;} +void LT_PDIVBW(){L_PDIVBW++;} +void LT_PEXEW(){L_PEXEW++;} +void LT_PROT3W(){L_PROT3W++;} +void LT_PMADDUW(){L_PMADDUW++;} +void LT_PSRAVW(){L_PSRAVW++;} +void LT_PMTHI(){L_MTHI++;} +void LT_PMTLO(){L_PMTLO++;} +void LT_PINTEH(){L_PINTEH++;} +void LT_PMULTUW(){L_PMULTUW++;} +void LT_PDIVUW(){L_PDIVUW++;} +void LT_PCPYUD(){L_PCPYUD++;} +void LT_POR(){L_POR++;} +void LT_PNOR(){L_PNOR++;} +void LT_PEXCH(){L_PEXCH++;} +void LT_PCPYH(){L_PCPYH++;} +void LT_PEXCW(){L_PEXCW++;} +//COP1 +void LT_COP1() {LT_COP1PrintTable[_Rs_]();} +void LT_LWC1() {L_LWC1++;} +void LT_SWC1() {L_SWC1++;} +void LT_COP1_BC1() {LT_COP1BC1PrintTable[_Rt_]();} +void LT_COP1_S() {LT_COP1SPrintTable[_Funct_]();} +void LT_COP1_W() {LT_COP1WPrintTable[_Funct_]();} +void LT_COP1_Unknown() {} +void LT_MFC1(){L_MFC1++;} +void LT_CFC1(){L_CFC1++;} +void LT_MTC1(){L_MTC1++;} +void LT_CTC1(){L_CTC1++;} +void LT_BC1F(){L_BC1F++;} +void LT_BC1T(){L_BC1T++;} +void LT_BC1FL(){L_BC1FL++;} +void LT_BC1TL(){L_BC1TL++;} +void LT_ADD_S(){L_ADD_S++;} +void LT_SUB_S(){L_SUB_S++;} +void LT_MUL_S(){L_MUL_S++;} +void LT_DIV_S(){L_DIV_S++;} +void LT_SQRT_S(){L_SQRT_S++;} +void LT_ABS_S(){L_ABS_S++;} +void LT_MOV_S(){L_MOV_S++;} +void LT_NEG_S(){L_NEG_S++;} +void LT_RSQRT_S(){L_RSQRT_S++;} +void LT_ADDA_S(){L_ADDA_S++;} +void LT_SUBA_S(){L_SUBA_S++;} +void LT_MULA_S(){L_MULA_S++;} +void LT_MADD_S(){L_MADD_S++;} +void LT_MSUB_S(){L_MSUB_S++;} +void LT_MADDA_S(){L_MADDA_S++;} +void LT_MSUBA_S(){L_MSUBA_S++;} +void LT_CVT_W(){L_CVT_W++;} +void LT_MAX_S(){L_MAX_S++;} +void LT_MIN_S(){L_MIN_S++;} +void LT_C_F(){L_C_F++;} +void LT_C_EQ(){L_C_EQ++;} +void LT_C_LT(){L_C_LT++;} +void LT_C_LE(){L_C_LE++;} +void LT_CVT_S(){L_CVT_S++;} +//cop2 + +void LT_LQC2() {L_LQC2++;} +void LT_SQC2() {L_SQC2++;} +void LT_COP2() {LT_COP2PrintTable[_Rs_]();} +void LT_COP2_BC2() {LT_COP2BC2PrintTable[_Rt_]();} +void LT_COP2_SPECIAL() { LT_COP2SPECIAL1PrintTable[_Funct_]();} +void LT_COP2_SPECIAL2() {LT_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)]();} +void LT_COP2_Unknown(){} +void LT_QMFC2(){L_QMFC2++;} +void LT_CFC2(){L_CFC2++;} +void LT_QMTC2(){L_QMTC2++;} +void LT_CTC2(){L_CTC2++;} +void LT_BC2F(){L_BC2F++;} +void LT_BC2T(){L_BC2T++;} +void LT_BC2FL(){L_BC2FL++;} +void LT_BC2TL(){L_BC2TL++;} +void LT_VADDx(){L_VADDx++;} +void LT_VADDy(){L_VADDy++;} +void LT_VADDz(){L_VADDz++;} +void LT_VADDw(){L_VADDw++;} +void LT_VSUBx(){L_VSUBx++;} +void LT_VSUBy(){L_VSUBy++;} +void LT_VSUBz(){L_VSUBz++;} +void LT_VSUBw(){L_VSUBw++;} +void LT_VMADDx(){L_VMADDx++;} +void LT_VMADDy(){L_VMADDy++;} +void LT_VMADDz(){L_VMADDz++;} +void LT_VMADDw(){L_VMADDw++;} +void LT_VMSUBx(){L_VMSUBx++;} +void LT_VMSUBy(){L_VMSUBy++;} +void LT_VMSUBz(){L_VMSUBz++;} +void LT_VMSUBw(){L_VMSUBw++;} +void LT_VMAXx(){L_VMAXx++;} +void LT_VMAXy(){L_VMAXy++;} +void LT_VMAXz(){L_VMAXz++;} +void LT_VMAXw(){L_VMAXw++;} +void LT_VMINIx(){L_VMINIx++;} +void LT_VMINIy(){L_VMINIy++;} +void LT_VMINIz(){L_VMINIz++;} +void LT_VMINIw(){L_VMINIw++;} +void LT_VMULx(){L_VMULx++;} +void LT_VMULy(){L_VMULy++;} +void LT_VMULz(){L_VMULz++;} +void LT_VMULw(){L_VMULw++;} +void LT_VMULq(){L_VMULq++;} +void LT_VMAXi(){L_VMAXi++;} +void LT_VMULi(){L_VMULi++;} +void LT_VMINIi(){L_VMINIi++;} +void LT_VADDq(){L_VADDq++;} +void LT_VMADDq(){L_VMADDq++;} +void LT_VADDi(){L_VADDi++;} +void LT_VMADDi(){L_VMADDi++;} +void LT_VSUBq(){L_VSUBq++;} +void LT_VMSUBq(){L_VMSUBq++;} +void LT_VSUBi(){L_VSUBi++;} +void LT_VMSUBi(){L_VMSUBi++;} +void LT_VADD(){L_VADD++;} +void LT_VMADD(){L_VMADD++;} +void LT_VMUL(){L_VMUL++;} +void LT_VMAX(){L_VMAX++;} +void LT_VSUB(){L_VSUB++;} +void LT_VMSUB(){L_VMSUB++;} +void LT_VOPMSUB(){L_VOPMSUB++;} +void LT_VMINI(){L_VMINI++;} +void LT_VIADD(){L_VIADD++;} +void LT_VISUB(){L_VISUB++;} +void LT_VIADDI(){L_VIADDI++;} +void LT_VIAND(){L_VIAND++;} +void LT_VIOR(){L_VIOR++;} +void LT_VCALLMS(){L_VCALLMS++;} +void LT_VCALLMSR(){L_VCALLMSR++;} +void LT_VADDAx(){L_VADDAx++;} +void LT_VADDAy(){L_VADDAy++;} +void LT_VADDAz(){L_VADDAz++;} +void LT_VADDAw(){L_VADDAw++;} +void LT_VSUBAx(){L_VSUBAx++;} +void LT_VSUBAy(){L_VSUBAy++;} +void LT_VSUBAz(){L_VSUBAz++;} +void LT_VSUBAw(){L_VSUBAw++;} +void LT_VMADDAx(){L_VMADDAx++;} +void LT_VMADDAy(){L_VMADDAy++;} +void LT_VMADDAz(){L_VMADDAz++;} +void LT_VMADDAw(){L_VMADDAw++;} +void LT_VMSUBAx(){L_VMSUBAx++;} +void LT_VMSUBAy(){L_VMSUBAy++;} +void LT_VMSUBAz(){L_VMSUBAz++;} +void LT_VMSUBAw(){L_VMSUBAw++;} +void LT_VITOF0(){L_VITOF0++;} +void LT_VITOF4(){L_VITOF4++;} +void LT_VITOF12(){L_VITOF12++;} +void LT_VITOF15(){L_VITOF15++;} +void LT_VFTOI0(){L_VFTOI0++;} +void LT_VFTOI4(){L_VFTOI4++;} +void LT_VFTOI12(){L_VFTOI12++;} +void LT_VFTOI15(){L_VFTOI15++;} +void LT_VMULAx(){L_VMULAx++;} +void LT_VMULAy(){L_VMULAy++;} +void LT_VMULAz(){L_VMULAz++;} +void LT_VMULAw(){L_VMULAw++;} +void LT_VMULAq(){L_VMULAq++;} +void LT_VABS(){L_VABS++;} +void LT_VMULAi(){L_VMULAi++;} +void LT_VCLIPw(){L_VCLIPw++;} +void LT_VADDAq(){L_VADDAq++;} +void LT_VMADDAq(){L_VMADDAq++;} +void LT_VADDAi(){L_VADDAi++;} +void LT_VMADDAi(){L_VMADDAi++;} +void LT_VSUBAq(){L_VSUBAq++;} +void LT_VMSUBAq(){L_VMSUBAq++;} +void LT_VSUBAi(){L_VSUBAi++;} +void LT_VMSUBAi(){L_VMSUBAi++;} +void LT_VADDA(){L_VADDA++;} +void LT_VMADDA(){L_VMADDA++;} +void LT_VMULA(){L_VMULA++;} +void LT_VSUBA(){L_VSUBA++;} +void LT_VMSUBA(){L_VMSUBA++;} +void LT_VOPMULA(){L_VOPMULA++;} +void LT_VNOP(){L_VNOP++;} +void LT_VMOVE(){L_VMOVE++;} +void LT_VMR32(){L_VMR32++;} +void LT_VLQI(){L_VLQI++;} +void LT_VSQI(){L_VSQI++;} +void LT_VLQD(){L_VLQD++;} +void LT_VSQD(){L_VSQD++;} +void LT_VDIV(){L_VDIV++;} +void LT_VSQRT(){L_VSQRT++;} +void LT_VRSQRT(){L_VRSQRT++;} +void LT_VWAITQ(){L_VWAITQ++;} +void LT_VMTIR(){L_VMTIR++;} +void LT_VMFIR(){L_VMFIR++;} +void LT_VILWR(){L_VILWR++;} +void LT_VISWR(){L_VISWR++;} +void LT_VRNEXT(){L_VRNEXT++;} +void LT_VRGET(){L_VRGET++;} +void LT_VRINIT(){L_VRINIT++;} +void LT_VRXOR(){L_VRXOR++;} + +void (*LT_OpcodePrintTable[64])() = +{ + LT_SPECIAL, LT_REGIMM, LT_J, LT_JAL, LT_BEQ, LT_BNE, LT_BLEZ, LT_BGTZ, + LT_ADDI, LT_ADDIU, LT_SLTI, LT_SLTIU, LT_ANDI, LT_ORI, LT_XORI, LT_LUI, + LT_COP0, LT_COP1, LT_COP2, LT_UnknownOpcode, LT_BEQL, LT_BNEL, LT_BLEZL, LT_BGTZL, + LT_DADDI, LT_DADDIU, LT_LDL, LT_LDR, LT_MMI, LT_UnknownOpcode, LT_LQ, LT_SQ, + LT_LB, LT_LH, LT_LWL, LT_LW, LT_LBU, LT_LHU, LT_LWR, LT_LWU, + LT_SB, LT_SH, LT_SWL, LT_SW, LT_SDL, LT_SDR, LT_SWR, LT_CACHE, + LT_UnknownOpcode, LT_LWC1, LT_UnknownOpcode, LT_PREF, LT_UnknownOpcode,LT_UnknownOpcode, LT_LQC2, LT_LD, + LT_UnknownOpcode, LT_SWC1, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode,LT_UnknownOpcode, LT_SQC2, LT_SD +}; + + +void (*LT_SpecialPrintTable[64])() = +{ + LT_SLL, LT_UnknownOpcode, LT_SRL, LT_SRA, LT_SLLV, LT_UnknownOpcode, LT_SRLV, LT_SRAV, + LT_JR, LT_JALR, LT_MOVZ, LT_MOVN, LT_SYSCALL, LT_BREAK, LT_UnknownOpcode, LT_SYNC, + LT_MFHI, LT_MTHI, LT_MFLO, LT_MTLO, LT_DSLLV, LT_UnknownOpcode, LT_DSRLV, LT_DSRAV, + LT_MULT, LT_MULTU, LT_DIV, LT_DIVU, LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode, + LT_ADD, LT_ADDU, LT_SUB, LT_SUBU, LT_AND, LT_OR, LT_XOR, LT_NOR, + LT_MFSA , LT_MTSA , LT_SLT, LT_SLTU, LT_DADD, LT_DADDU, LT_DSUB, LT_DSUBU, + LT_TGE, LT_TGEU, LT_TLT, LT_TLTU, LT_TEQ, LT_UnknownOpcode, LT_TNE, LT_UnknownOpcode, + LT_DSLL, LT_UnknownOpcode, LT_DSRL, LT_DSRA, LT_DSLL32, LT_UnknownOpcode, LT_DSRL32, LT_DSRA32 +}; + +void (*LT_REGIMMPrintTable[32])() = { + LT_BLTZ, LT_BGEZ, LT_BLTZL, LT_BGEZL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_TGEI, LT_TGEIU, LT_TLTI, LT_TLTIU, LT_TEQI, LT_UnknownOpcode, LT_TNEI, LT_UnknownOpcode, + LT_BLTZAL, LT_BGEZAL, LT_BLTZALL, LT_BGEZALL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_MTSAB, LT_MTSAH , LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, +}; +void (*LT_MMIPrintTable[64])() = +{ + LT_MADD, LT_MADDU, LT_MMI_Unknown, LT_MMI_Unknown, LT_PLZCW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI0, LT_MMI2, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MFHI1, LT_MTHI1, LT_MFLO1, LT_MTLO1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MULT1, LT_MULTU1, LT_DIV1, LT_DIVU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MADD1, LT_MADDU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI1 , LT_MMI3, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHL, LT_PMTHL, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLH, LT_MMI_Unknown, LT_PSRLH, LT_PSRAH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLW, LT_MMI_Unknown, LT_PSRLW, LT_PSRAW, +}; + +void (*LT_MMI0PrintTable[32])() = +{ + LT_PADDW, LT_PSUBW, LT_PCGTW, LT_PMAXW, + LT_PADDH, LT_PSUBH, LT_PCGTH, LT_PMAXH, + LT_PADDB, LT_PSUBB, LT_PCGTB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDSW, LT_PSUBSW, LT_PEXTLW, LT_PPACW, + LT_PADDSH, LT_PSUBSH, LT_PEXTLH, LT_PPACH, + LT_PADDSB, LT_PSUBSB, LT_PEXTLB, LT_PPACB, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXT5, LT_PPAC5, +}; + +void (*LT_MMI1PrintTable[32])() = +{ + LT_MMI_Unknown, LT_PABSW, LT_PCEQW, LT_PMINW, + LT_PADSBH, LT_PABSH, LT_PCEQH, LT_PMINH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PCEQB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDUW, LT_PSUBUW, LT_PEXTUW, LT_MMI_Unknown, + LT_PADDUH, LT_PSUBUH, LT_PEXTUH, LT_MMI_Unknown, + LT_PADDUB, LT_PSUBUB, LT_PEXTUB, LT_QFSRV, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, +}; + + +void (*LT_MMI2PrintTable[32])() = +{ + LT_PMADDW, LT_MMI_Unknown, LT_PSLLVW, LT_PSRLVW, + LT_PMSUBW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHI, LT_PMFLO, LT_PINTH, LT_MMI_Unknown, + LT_PMULTW, LT_PDIVW, LT_PCPYLD, LT_MMI_Unknown, + LT_PMADDH, LT_PHMADH, LT_PAND, LT_PXOR, + LT_PMSUBH, LT_PHMSBH, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXEH, LT_PREVH, + LT_PMULTH, LT_PDIVBW, LT_PEXEW, LT_PROT3W, +}; + +void (*LT_MMI3PrintTable[32])() = +{ + LT_PMADDUW, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSRAVW, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMTHI, LT_PMTLO, LT_PINTEH, LT_MMI_Unknown, + LT_PMULTUW, LT_PDIVUW, LT_PCPYUD, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_POR, LT_PNOR, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCH, LT_PCPYH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCW, LT_MMI_Unknown, +}; + +void (*LT_COP0PrintTable[32])() = +{ + LT_MFC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_MTC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_BC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Func, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0BC0PrintTable[32])() = +{ + LT_BC0F, LT_BC0T, LT_BC0FL, LT_BC0TL, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0C0PrintTable[64])() = { + LT_COP0_Unknown, LT_TLBR, LT_TLBWI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_TLBWR, LT_COP0_Unknown, + LT_TLBP, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_ERET, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_EI, LT_DI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown +}; + + +void (*LT_COP1PrintTable[32])() = { + LT_MFC1, LT_COP1_Unknown, LT_CFC1, LT_COP1_Unknown, LT_MTC1, LT_COP1_Unknown, LT_CTC1, LT_COP1_Unknown, + LT_COP1_BC1, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_S, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_W, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1BC1PrintTable[32])() = { + LT_BC1F, LT_BC1T, LT_BC1FL, LT_BC1TL, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1SPrintTable[64])() = { +LT_ADD_S, LT_SUB_S, LT_MUL_S, LT_DIV_S, LT_SQRT_S, LT_ABS_S, LT_MOV_S, LT_NEG_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_RSQRT_S, LT_COP1_Unknown, +LT_ADDA_S, LT_SUBA_S, LT_MULA_S, LT_COP1_Unknown,LT_MADD_S, LT_MSUB_S, LT_MADDA_S, LT_MSUBA_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_CVT_W, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_MAX_S, LT_MIN_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_C_F, LT_COP1_Unknown,LT_C_EQ, LT_COP1_Unknown,LT_C_LT, LT_COP1_Unknown,LT_C_LE, LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP1WPrintTable[64])() = { +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_CVT_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP2PrintTable[32])() = { + LT_COP2_Unknown, LT_QMFC2, LT_CFC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_QMTC2, LT_CTC2, LT_COP2_Unknown, + LT_COP2_BC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, +}; + +void (*LT_COP2BC2PrintTable[32])() = { + LT_BC2F, LT_BC2T, LT_BC2FL, LT_BC2TL, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, +}; + +void (*LT_COP2SPECIAL1PrintTable[64])() = +{ + LT_VADDx, LT_VADDy, LT_VADDz, LT_VADDw, LT_VSUBx, LT_VSUBy, LT_VSUBz, LT_VSUBw, + LT_VMADDx, LT_VMADDy, LT_VMADDz, LT_VMADDw, LT_VMSUBx, LT_VMSUBy, LT_VMSUBz, LT_VMSUBw, + LT_VMAXx, LT_VMAXy, LT_VMAXz, LT_VMAXw, LT_VMINIx, LT_VMINIy, LT_VMINIz, LT_VMINIw, + LT_VMULx, LT_VMULy, LT_VMULz, LT_VMULw, LT_VMULq, LT_VMAXi, LT_VMULi, LT_VMINIi, + LT_VADDq, LT_VMADDq, LT_VADDi, LT_VMADDi, LT_VSUBq, LT_VMSUBq, LT_VSUBi, LT_VMSUBi, + LT_VADD, LT_VMADD, LT_VMUL, LT_VMAX, LT_VSUB, LT_VMSUB, LT_VOPMSUB, LT_VMINI, + LT_VIADD, LT_VISUB, LT_VIADDI, LT_COP2_Unknown,LT_VIAND, LT_VIOR, LT_COP2_Unknown, LT_COP2_Unknown, + LT_VCALLMS, LT_VCALLMSR, LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2, +}; + +void (*LT_COP2SPECIAL2PrintTable[128])() = +{ + LT_VADDAx ,LT_VADDAy ,LT_VADDAz ,LT_VADDAw ,LT_VSUBAx ,LT_VSUBAy ,LT_VSUBAz ,LT_VSUBAw, + LT_VMADDAx ,LT_VMADDAy ,LT_VMADDAz ,LT_VMADDAw ,LT_VMSUBAx ,LT_VMSUBAy ,LT_VMSUBAz ,LT_VMSUBAw, + LT_VITOF0 ,LT_VITOF4 ,LT_VITOF12 ,LT_VITOF15 ,LT_VFTOI0 ,LT_VFTOI4 ,LT_VFTOI12 ,LT_VFTOI15, + LT_VMULAx ,LT_VMULAy ,LT_VMULAz ,LT_VMULAw ,LT_VMULAq ,LT_VABS ,LT_VMULAi ,LT_VCLIPw, + LT_VADDAq ,LT_VMADDAq ,LT_VADDAi ,LT_VMADDAi ,LT_VSUBAq ,LT_VMSUBAq ,LT_VSUBAi ,LT_VMSUBAi, + LT_VADDA ,LT_VMADDA ,LT_VMULA ,LT_COP2_Unknown,LT_VSUBA ,LT_VMSUBA ,LT_VOPMULA ,LT_VNOP, + LT_VMOVE ,LT_VMR32 ,LT_COP2_Unknown,LT_COP2_Unknown,LT_VLQI ,LT_VSQI ,LT_VLQD ,LT_VSQD, + LT_VDIV ,LT_VSQRT ,LT_VRSQRT ,LT_VWAITQ ,LT_VMTIR ,LT_VMFIR ,LT_VILWR ,LT_VISWR, + LT_VRNEXT ,LT_VRGET ,LT_VRINIT ,LT_VRXOR ,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, +}; diff --git a/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.h b/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.h new file mode 100644 index 0000000..3422693 --- /dev/null +++ b/branches/pcsx2_0.9.1/DebugTools/cpuopsDebug.h @@ -0,0 +1,456 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void UpdateR5900op(); +extern void (*LT_OpcodePrintTable[64])(); +extern void (*LT_SpecialPrintTable[64])(); +extern void (*LT_REGIMMPrintTable[32])(); +extern void (*LT_MMIPrintTable[64])(); +extern void (*LT_MMI0PrintTable[32])(); +extern void (*LT_MMI1PrintTable[32])(); +extern void (*LT_MMI2PrintTable[32])(); +extern void (*LT_MMI3PrintTable[32])(); +extern void (*LT_COP0PrintTable[32])(); +extern void (*LT_COP0BC0PrintTable[32])(); +extern void (*LT_COP0C0PrintTable[64])(); +extern void (*LT_COP1PrintTable[32])(); +extern void (*LT_COP1BC1PrintTable[32])(); +extern void (*LT_COP1SPrintTable[64])(); +extern void (*LT_COP1WPrintTable[64])(); +extern void (*LT_COP2PrintTable[32])(); +extern void (*LT_COP2BC2PrintTable[32])(); +extern void (*LT_COP2SPECIAL1PrintTable[64])(); +extern void (*LT_COP2SPECIAL2PrintTable[128])(); +// **********************Standard Opcodes************************** +int L_ADD=0; +int L_ADDI=0; +int L_ADDIU=0; +int L_ADDU=0; +int L_AND=0; +int L_ANDI=0; +int L_BEQ=0; +int L_BEQL=0; +int L_BGEZ=0; +int L_BGEZAL=0; +int L_BGEZALL=0; +int L_BGEZL=0; +int L_BGTZ=0; +int L_BGTZL=0; +int L_BLEZ=0; +int L_BLEZL=0; +int L_BLTZ=0; +int L_BLTZAL=0; +int L_BLTZALL=0; +int L_BLTZL=0; +int L_BNE=0; +int L_BNEL=0; +int L_BREAK=0; +int L_CACHE=0; +int L_DADD=0; +int L_DADDI=0; +int L_DADDIU=0; +int L_DADDU=0; +int L_DIV=0; +int L_DIVU=0; +int L_DSLL=0; +int L_DSLL32=0; +int L_DSLLV=0; +int L_DSRA=0; +int L_DSRA32=0; +int L_DSRAV=0; +int L_DSRL=0; +int L_DSRL32=0; +int L_DSRLV=0; +int L_DSUB=0; +int L_DSUBU=0; +int L_J=0; +int L_JAL=0; +int L_JALR=0; +int L_JR=0; +int L_LB=0; +int L_LBU=0; +int L_LD=0; +int L_LDL=0; +int L_LDR=0; +int L_LH=0; +int L_LHU=0; +int L_LQ=0; +int L_LQC2=0; +int L_LUI=0; +int L_LW=0; +int L_LWC1=0; +int L_LWL=0; +int L_LWR=0; +int L_LWU=0; +int L_MFHI=0; +int L_MFLO=0; +int L_MFSA=0; +int L_MOVN=0; +int L_MOVZ=0; +int L_MTHI=0; +int L_MTLO=0; +int L_MTSA=0; +int L_MTSAB=0; +int L_MTSAH=0; +int L_MULT=0; +int L_MULTU=0; +int L_NOR=0; +int L_OR=0; +int L_ORI=0; +int L_PREF=0; +int L_SB=0; +int L_SD=0; +int L_SDL=0; +int L_SDR=0; +int L_SH=0; +int L_SLL=0; +int L_SLLV=0; +int L_SLT=0; +int L_SLTI=0; +int L_SLTIU=0; +int L_SLTU=0; +int L_SQ=0; +int L_SQC2=0; +int L_SRA=0; +int L_SRAV=0; +int L_SRL=0; +int L_SRLV=0; +int L_SUB=0; +int L_SUBU=0; +int L_SW=0; +int L_SWC1=0; +int L_SWL=0; +int L_SWR=0; +int L_SYNC=0; +int L_SYSCALL=0; +int L_TEQ=0; +int L_TEQI=0; +int L_TGE=0; +int L_TGEI=0; +int L_TGEIU=0; +int L_TGEU=0; +int L_TLT=0; +int L_TLTI=0; +int L_TLTIU=0; +int L_TLTU=0; +int L_TNE=0; +int L_TNEI=0; +int L_XOR=0; +int L_XORI=0; + + + + +//*****************MMI OPCODES********************************* +int L_MADD=0; +int L_MADDU=0; +int L_PLZCW=0; +int L_MADD1=0; +int L_MADDU1=0; +int L_MFHI1=0; +int L_MTHI1=0; +int L_MFLO1=0; +int L_MTLO1=0; +int L_MULT1=0; +int L_MULTU1=0; +int L_DIV1=0; +int L_DIVU1=0; +int L_PMFHL=0; +int L_PMTHL=0; +int L_PSLLH=0; +int L_PSRLH=0; +int L_PSRAH=0; +int L_PSLLW=0; +int L_PSRLW=0; +int L_PSRAW=0; +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +int L_PADDW=0; +int L_PSUBW=0; +int L_PCGTW=0; +int L_PMAXW=0; +int L_PADDH=0; +int L_PSUBH=0; +int L_PCGTH=0; +int L_PMAXH=0; +int L_PADDB=0; +int L_PSUBB=0; +int L_PCGTB=0; +int L_PADDSW=0; +int L_PSUBSW=0; +int L_PEXTLW=0; +int L_PPACW=0; +int L_PADDSH=0; +int L_PSUBSH=0; +int L_PEXTLH=0; +int L_PPACH=0; +int L_PADDSB=0; +int L_PSUBSB=0; +int L_PEXTLB=0; +int L_PPACB=0; +int L_PEXT5=0; +int L_PPAC5=0; +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +int L_PABSW=0; +int L_PCEQW=0; +int L_PMINW=0; +int L_PADSBH=0; +int L_PABSH=0; +int L_PCEQH=0; +int L_PMINH=0; +int L_PCEQB=0; +int L_PADDUW=0; +int L_PSUBUW=0; +int L_PEXTUW=0; +int L_PADDUH=0; +int L_PSUBUH=0; +int L_PEXTUH=0; +int L_PADDUB=0; +int L_PSUBUB=0; +int L_PEXTUB=0; +int L_QFSRV=0; +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +int L_PMADDW=0; +int L_PSLLVW=0; +int L_PSRLVW=0; +int L_PMSUBW=0; +int L_PMFHI=0; +int L_PMFLO=0; +int L_PINTH=0; +int L_PMULTW=0; +int L_PDIVW=0; +int L_PCPYLD=0; +int L_PMADDH=0; +int L_PHMADH=0; +int L_PAND=0; +int L_PXOR=0; +int L_PMSUBH=0; +int L_PHMSBH=0; +int L_PEXEH=0; +int L_PREVH=0; +int L_PMULTH=0; +int L_PDIVBW=0; +int L_PEXEW=0; +int L_PROT3W=0; +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +int L_PMADDUW=0; +int L_PSRAVW=0; +int L_PMTHI=0; +int L_PMTLO=0; +int L_PINTEH=0; +int L_PMULTUW=0; +int L_PDIVUW=0; +int L_PCPYUD=0; +int L_POR=0; +int L_PNOR=0; +int L_PEXCH=0; +int L_PCPYH=0; +int L_PEXCW=0; +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +int L_MFC0=0; +int L_MTC0=0; +int L_BC0F=0; +int L_BC0T=0; +int L_BC0FL=0; +int L_BC0TL=0; +int L_TLBR=0; +int L_TLBWI=0; +int L_TLBWR=0; +int L_TLBP=0; +int L_ERET=0; +int L_DI=0; +int L_EI=0; +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +int L_MFC1=0; +int L_CFC1=0; +int L_MTC1=0; +int L_CTC1=0; +int L_BC1F=0; +int L_BC1T=0; +int L_BC1FL=0; +int L_BC1TL=0; +int L_ADD_S=0; +int L_SUB_S=0; +int L_MUL_S=0; +int L_DIV_S=0; +int L_SQRT_S=0; +int L_ABS_S=0; +int L_MOV_S=0; +int L_NEG_S=0; +int L_RSQRT_S=0; +int L_ADDA_S=0; +int L_SUBA_S=0; +int L_MULA_S=0; +int L_MADD_S=0; +int L_MSUB_S=0; +int L_MADDA_S=0; +int L_MSUBA_S=0; +int L_CVT_W=0; +int L_MAX_S=0; +int L_MIN_S=0; +int L_C_F=0; +int L_C_EQ=0; +int L_C_LT=0; +int L_C_LE=0; + int L_CVT_S=0; +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +int L_QMFC2=0; +int L_CFC2=0; +int L_QMTC2=0; +int L_CTC2=0; +int L_BC2F=0; +int L_BC2T=0; +int L_BC2FL=0; +int L_BC2TL=0; +int L_VADDx=0; +int L_VADDy=0; +int L_VADDz=0; +int L_VADDw=0; +int L_VSUBx=0; +int L_VSUBy=0; +int L_VSUBz=0; +int L_VSUBw=0; +int L_VMADDx=0; +int L_VMADDy=0; +int L_VMADDz=0; +int L_VMADDw=0; +int L_VMSUBx=0; +int L_VMSUBy=0; +int L_VMSUBz=0; +int L_VMSUBw=0; +int L_VMAXx=0; +int L_VMAXy=0; +int L_VMAXz=0; +int L_VMAXw=0; +int L_VMINIx=0; +int L_VMINIy=0; +int L_VMINIz=0; +int L_VMINIw=0; +int L_VMULx=0; +int L_VMULy=0; +int L_VMULz=0; +int L_VMULw=0; +int L_VMULq=0; +int L_VMAXi=0; +int L_VMULi=0; +int L_VMINIi=0; +int L_VADDq=0; +int L_VMADDq=0; +int L_VADDi=0; +int L_VMADDi=0; +int L_VSUBq=0; +int L_VMSUBq=0; +int L_VSUBi=0; +int L_VMSUBi=0; +int L_VADD=0; +int L_VMADD=0; +int L_VMUL=0; +int L_VMAX=0; +int L_VSUB=0; +int L_VMSUB=0; +int L_VOPMSUB=0; +int L_VMINI=0; +int L_VIADD=0; +int L_VISUB=0; +int L_VIADDI=0; +int L_VIAND=0; +int L_VIOR=0; +int L_VCALLMS=0; +int L_VCALLMSR=0; +int L_VADDAx=0; +int L_VADDAy=0; +int L_VADDAz=0; +int L_VADDAw=0; +int L_VSUBAx=0; +int L_VSUBAy=0; +int L_VSUBAz=0; +int L_VSUBAw=0; +int L_VMADDAx=0; +int L_VMADDAy=0; +int L_VMADDAz=0; +int L_VMADDAw=0; +int L_VMSUBAx=0; +int L_VMSUBAy=0; +int L_VMSUBAz=0; +int L_VMSUBAw=0; +int L_VITOF0=0; +int L_VITOF4=0; +int L_VITOF12=0; +int L_VITOF15=0; +int L_VFTOI0=0; +int L_VFTOI4=0; +int L_VFTOI12=0; +int L_VFTOI15=0; +int L_VMULAx=0; +int L_VMULAy=0; +int L_VMULAz=0; +int L_VMULAw=0; +int L_VMULAq=0; +int L_VABS=0; +int L_VMULAi=0; +int L_VCLIPw=0; +int L_VADDAq=0; +int L_VMADDAq=0; +int L_VADDAi=0; +int L_VMADDAi=0; +int L_VSUBAq=0; +int L_VMSUBAq=0; +int L_VSUBAi=0; +int L_VMSUBAi=0; +int L_VADDA=0; +int L_VMADDA=0; +int L_VMULA=0; +int L_VSUBA=0; +int L_VMSUBA=0; +int L_VOPMULA=0; +int L_VNOP=0; +int L_VMOVE=0; +int L_VMR32=0; +int L_VLQI=0; +int L_VSQI=0; +int L_VLQD=0; +int L_VSQD=0; +int L_VDIV=0; +int L_VSQRT=0; +int L_VRSQRT=0; +int L_VWAITQ=0; +int L_VMTIR=0; +int L_VMFIR=0; +int L_VILWR=0; +int L_VISWR=0; +int L_VRNEXT=0; +int L_VRGET=0; +int L_VRINIT=0; +int L_VRXOR=0; diff --git a/branches/pcsx2_0.9.1/Decode_XA.c b/branches/pcsx2_0.9.1/Decode_XA.c new file mode 100644 index 0000000..3bd53f4 --- /dev/null +++ b/branches/pcsx2_0.9.1/Decode_XA.c @@ -0,0 +1,305 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ +//=== Modified by linuzappz +//============================================ + +#include + +#include "Decode_XA.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#endif + +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned long U32; + +#define NOT(_X_) (!(_X_)) +#define CLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} + +//============================================ +//=== ADPCM DECODING ROUTINES +//============================================ + +static double K0[4] = { + 0.0, + 0.9375, + 1.796875, + 1.53125 +}; + +static double K1[4] = { + 0.0, + 0.0, + -0.8125, + -0.859375 +}; + +#define BLKSIZ 28 /* block size (32 - 4 nibbles) */ + +//=========================================== +void ADPCM_InitDecode( ADPCM_Decode_t *decp ) +{ + decp->y0 = 0; + decp->y1 = 0; +} + +//=========================================== +#define SH 4 +#define SHC 10 + +#define IK0(fid) ((int)((-K0[fid]) * (1<> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + long y; + long x0, x1, x2, x3; + + y = *blockp++; + x3 = (short)( y & 0xf000) >> range; x3 <<= SH; + x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; + x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; + x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; + + x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; + x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; + x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; + x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; + + CLAMP( x0, -32768<> SH; destp += inc; + CLAMP( x1, -32768<> SH; destp += inc; + CLAMP( x2, -32768<> SH; destp += inc; + CLAMP( x3, -32768<> SH; destp += inc; + } + decp->y0 = fy0; + decp->y1 = fy1; +} + +static int headtable[4] = {0,2,8,10}; + +//=========================================== +static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { + const U8 *sound_groupsp; + const U8 *sound_datap, *sound_datap2; + int i, j, k, nbits; + U16 data[4096], *datap; + short *destp; + + destp = xdp->pcm; + nbits = xdp->nbits == 4 ? 4 : 2; + + if (xdp->stereo) { // stereo + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } + else { // mono + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } +} + +//============================================ +//=== XA SPECIFIC ROUTINES +//============================================ +typedef struct { +U8 filenum; +U8 channum; +U8 submode; +U8 coding; + +U8 filenum2; +U8 channum2; +U8 submode2; +U8 coding2; +} xa_subheader_t; + +#define SUB_SUB_EOF (1<<7) // end of file +#define SUB_SUB_RT (1<<6) // real-time sector +#define SUB_SUB_FORM (1<<5) // 0 form1 1 form2 +#define SUB_SUB_TRIGGER (1<<4) // used for interrupt +#define SUB_SUB_DATA (1<<3) // contains data +#define SUB_SUB_AUDIO (1<<2) // contains audio +#define SUB_SUB_VIDEO (1<<1) // contains video +#define SUB_SUB_EOR (1<<0) // end of record + +#define AUDIO_CODING_GET_STEREO(_X_) ( (_X_) & 3) +#define AUDIO_CODING_GET_FREQ(_X_) (((_X_) >> 2) & 3) +#define AUDIO_CODING_GET_BPS(_X_) (((_X_) >> 4) & 3) +#define AUDIO_CODING_GET_EMPHASIS(_X_) (((_X_) >> 6) & 1) + +#define SUB_UNKNOWN 0 +#define SUB_VIDEO 1 +#define SUB_AUDIO 2 + +//============================================ +static int parse_xa_audio_sector( xa_decode_t *xdp, + xa_subheader_t *subheadp, + unsigned char *sectorp, + int is_first_sector ) { + if ( is_first_sector ) { + switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { + case 0: xdp->freq = 37800; break; + case 1: xdp->freq = 18900; break; + default: xdp->freq = 0; break; + } + switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { + case 0: xdp->nbits = 4; break; + case 1: xdp->nbits = 8; break; + default: xdp->nbits = 0; break; + } + switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { + case 0: xdp->stereo = 0; break; + case 1: xdp->stereo = 1; break; + default: xdp->stereo = 0; break; + } + + if ( xdp->freq == 0 ) + return -1; + + ADPCM_InitDecode( &xdp->left ); + ADPCM_InitDecode( &xdp->right ); + + xdp->nsamples = 18 * 28 * 8; + if (xdp->stereo == 1) xdp->nsamples /= 2; + } + xa_decode_data( xdp, sectorp ); + + return 0; +} + +//================================================================ +//=== THIS IS WHAT YOU HAVE TO CALL +//=== xdp - structure were all important data are returned +//=== sectorp - data in input +//=== pcmp - data in output +//=== is_first_sector - 1 if it's the 1st sector of the stream +//=== - 0 for any other successive sector +//=== return -1 if error +//================================================================ +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, int is_first_sector ) { + if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) + return -1; + + return 0; +} + +/* EXAMPLE: +"nsamples" is the number of 16 bit samples +every sample is 2 bytes in mono and 4 bytes in stereo + +xa_decode_t xa; + + sectorp = read_first_sector(); + xa_decode_sector( &xa, sectorp, 1 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + + while ( --n_sectors ) + { + sectorp = read_next_sector(); + xa_decode_sector( &xa, sectorp, 0 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + } +*/ diff --git a/branches/pcsx2_0.9.1/Decode_XA.h b/branches/pcsx2_0.9.1/Decode_XA.h new file mode 100644 index 0000000..d363fb4 --- /dev/null +++ b/branches/pcsx2_0.9.1/Decode_XA.h @@ -0,0 +1,26 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct { + long y0, y1; +} ADPCM_Decode_t; + +typedef struct { + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/branches/pcsx2_0.9.1/Docs/BetaTesters.txt b/branches/pcsx2_0.9.1/Docs/BetaTesters.txt new file mode 100644 index 0000000..3d15fb1 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/BetaTesters.txt @@ -0,0 +1,13 @@ +Current PCSX2 Beta-Testers-Slaves :P : + +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever +Seta-San +Nave diff --git a/branches/pcsx2_0.9.1/Docs/ChangeLog.txt b/branches/pcsx2_0.9.1/Docs/ChangeLog.txt new file mode 100644 index 0000000..3f34e35 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/ChangeLog.txt @@ -0,0 +1,2742 @@ +[ Legend: ] +[ + Added feature ] +[ * Improved/changed feature ] +[ - Bug fixed (we hope) ] +[ ! Attention (Notes) ] + +ChangeLog: + v0.9: + * 06/28/06:[+] MAJOR CHANGE: All recompilers and memory code rewritten. + eeRec now does block analysis, constant propagation, liveness + analysis, mmx/xmm reg caching, etc. + vuRec is about 10x faster than older vurec. Both VU0 and + VU1 recs work and share the same code. + iopRec - does same as eeRec, except is simpler + Altogether, 3D scenes are 2-4x faster than 0.9 release. + (zerofrog) + + * 02/04/06:[+] VU0 Rec added, still buggy + [*] VU1 Speedups and fixes, needs more testing but seems better + [*] CDVD Timing Improved wait times for commands reduced. + [-] Misc eeRec bug fixes made + [*] Vif stalls greatly improved loads more games now work! + [*] Counters modified with gates and improved accuracy + [*] Cycle counting in EE/IOP done on branches to cut download + 2D speed up by over double! + [-] Misc VIF unpack fixes + [-] GIF Stalls should now work correctly + [+] Virtual Memory for Windows XP users, quicker than TLB + [*] Difference CPU options can be mixed and matched by users choice + [-] SIF communication fixed, games can now be booted via the bios (in most cases) + [!] Lots of other fixes have been made by due to lazyness we didnt document! :D + [!] This is the FINAL code for 0.9 enjoy! + (Refraction, ZeroFrog, Saqib) + * 15/02/06:[+] Multithreaded GS/Dual Core Support + (zerofrog) + * 17/01/06:[-] Some changes in CDVD tray status + (efp) + + * 16/01/06:[-] Fixed sticky flags. + [*] Implemented/Fixed a lot of vu functions in vurec. VuRec now properly checks for underflow/overflow + (zerofrog) + * 15/01/06:[-] Bug fixes in VU rec/interp (Ebit, xgkick). Added 24bit precision for VUs. + [*] Changed all math functions to use the C++ floating point versions. + (zerofrog) + * 14/01/06:[-] VU Flag fixes + double removal (it needed doing) from zerofrog + [-] Disabled an old PSX Counter hack that i left in some how! + [*] Changed SIF reg code to something simpler and less time consuming + (Refraction) + * 13/01/06:[*] Fixed mac update flags for vu interpreter. + (zerofrog) + + * 12/01/06:[-] Changed IPU.c, thread syncing issue fixed by zerofrog + [*] Altered SBUS so it is triggered on PSX dma + [*] Removed a load of IOP hacks, should improve compatability in some cases + [!] A lot of changes have been made since 05/09/05 but weve lost track, whoops + (Refraction Saqib zerofrog) + + * 05/01/06:[*] Added GSreadFIFO2 for faster reads from GS. + [-] Fixed the multi-threaded IPU and added sync primitives for interrupts and DMA. + The green squares should be gone too. + (zerofrog) + + * 05/09/05:[-] Fixed VU-Rec crash if the pc overflowed the vumem, thanks to fumofumo! + [*] New Icon for 0.9 made by CKemu + [+] Vsync rate now selectable, current Vsync speed is default but less compatable in + some cases, option selects real vsync speed, syncs sound correctly. + (Refraction) + + * 03/09/05:[-] IOP rec & VU0rec fix, x86ptr being set in the wrong place, also a couple of vu-rec op fixes + thanks to fumofumo on irc. + [-] Slowed VSync down to actual speed, so sound isnt half the speed of the graphics, + a few more changes to counters as well, BOR works again, just slower ;p + (Refraction) + + * 30/08/05:[-] Few more changes to the counters, seems much better again, last fix killed stuff + [-] VSync rate now actually changes between PAL and NTSC, before it was stuck in NTSC + [-] Couple of changes in VIF + * 24/08/05:[-] Readded setting of Done on VIF1 TTE, added the same on VIF0 + [-] Applied VIF1 FBRST fix to VIF0 too + [-] Fixed problem causing Beats Of Rage to skip and altered slow sound prob again. + (Refraction) + + * 23/08/05:[-] Did some more timing fixes, they should be a LOT more compatable now + [-] Small change to FBRST, was causing crashes if VIF was finished. + [+] Added counter copy to hold on SBUS interrupt + (Refraction) + + * 21/08/05:[-] Few fixes in the eeRec, shouldnt crash on Kingdom Hearts now, Thanks to fumofumo! + [-] Fixed a bug in FBRST and Vif1, altho theres still an interrupting problem somewhere :/ + [-] Int VU now uses Single Precision (its faster) with no loss of graphics. + [-] Made sure MAC, CLIP and STATUS flags are all located on VU0. + [*] Enabled linuz's SSE unpack code, gives a nice little speed boost, works ok :) + [-] VU execute blocks limited to 128, seems a little faster, no loss of graphics, seems + to fix a few looping infinately issues (VU not breaking) (GiGaHeRz) + [-] Hack removed on TLBP, should hopefully work ok, doesnt seem to break anything (GiGaHeRz) + [+] Added SPU2 hack, should fix some games, not compatable with videos tho. removed fast dvd + [-] More counter stuff, also added gating to IOP counters, not totally sure on it. + [-] Added a couple of checks in VU & eeRec to make sure the constant registers werent overwritten + [-] Temp fix for the dma alignment error on GIF + [-] modified dma timings, qwc / BIAS could mess up if qwc = 1 + [-] Singled out some problematic VU-Rec ops that cause FFX to hang and borkey graphics. + (Refraction) + + * 12/08/05:[*] Few more timing things, music shouldnt be slow anymore on games and cleaned up + counters a bit. + [+] Added SBUS register logging on IOP side + [-] Temp fixed a MAC flag problem in vu-rec till linuz sorts it properly + [*] Committed new logo, nice job CKEmu ;) + [*] Vu-Rec now supports non SSE2 processors thanks to kekko for the changes! + (refraction) + + * 05/08/05:[+] Added faster Cd/DVD reads to the Advanced options (Refraction) + [-] The previous DVD/CD change by ref was just a hack, so i commited the old + version again + [-] I've commented out RECOMPILE_VUMI_LOADSTORE on iVUmicro.h, instead + of commenting it out in iVU1micro.c as ref did on last update, + that way is better until i fix the real problem + [*] Improved vuDIV for .x to .x cases + [+] Added PEXTRW/PINSRW + (linuzappz) + + * 05/08/05:[-] Fixed a couple of VU-Rec ops, swapped some over to the interpreter to fix 2d + (thanks to fumofumo for the tipoff) + [-] Yes more timing stuff :P think its as compatable as its going to get now. + [*] DVD/CD reads now considerably faster, some loading times down by 1600%!!! + Compatability still good :) + [-] Fixed a bug in 128bit hardware reads + [-] Fixed a bug i made in VU which messed graphics up eg Frequency and Sega Tennis + (refraction) + + * 04/08/05:[-] More IOP/EE timing fixes, Thanks for the info linuz + [-] Vsync speeds shouldnt be as insane as they were, the target was set as 1/4 the rate + instead of 1/2! + [!] 32bit timer interrupt checks arent working properly eg. overflow only works + when checking if they are equal, on target only works on overflow :/ but the checking + method which was used in SafeIOP is more accurate. + (refraction) + + * 03/08/05:[-] Fixed FTOX in VUrec + (linuzappz) + + * 31/07/05:[-] Reverted to old Branchtarget's, seems to stop the RecUNKs + [-] Fixed the timing a bit between IOP & EE, shouldn't need SafeIOP anymore :D + [-] Removed Pointless While loops on GIF & SPR, also fixed condition where SPR0 + couldn't use destination chain mode + [!] Gating on the IOP needs checking/completing, i have no docs on it so + i can't check the values for it, they seem different to EE :/ + [-] Removed GS Stall checking on GIF, could have caused it not to send data. + [*] Added code for faster V4-32 unpacks when CL == WL + [*] x86 code kept in int format for rec instead of U8 to INT conversion (GiGaHeRz) + (refraction) + + * 21/07/05:[-] Fixed setting of the Double Buffer + [-] Fixed the Branchtarget's for R3000A and R5900 + [*] Altered some stuff in vuflags, seems to give a speed boost :P + (refraction) + + * 18/07/05:[-] Removed some useless & 0xffff on Hw.c + [-] Reverted Sif changes to the old code, + gotta speak about this with refraction + [+] Added VIF1_STAT at vif1Write32, to handled the FDR bit + [-] VIF1 now clears qwc with "from memory" transfer + (linuzappz) + + * 17/07/05:[-] Fixed a bug in VIF where done could be unset + [-] Fixed a couple of bugs in VU + [*] Rewrote SIF0, seems to be a bit more compatable as well + as more readable + [-] Altered the loops for vu(1/0)exec, seems to fix some graphics + without comprimising compatability + (refraction) + + * 12/07/05:[-] Fixed VIF stop on stall occurance (refraction) + [-] Added two common funcs for source chain dmas + [-] Fixed REFE and END (even once again) in dmas + [-] Fixed interrupt i bit issue in Vif1 (on multiple i bits) + (linuzappz) + + * 08/07/05:[-] MFIFO now wraps around the ring buffer when it's full, + in both GIF/VIF1 + (linuzappz) + + * 06/07/05:[-] Bug in DIRECT/HL caused vif errors + [-] Recomitted old VIF0 IRQ stuff, seemed to cause problems + (Refraction) + + * 05/07/05:[-] Fixed IRQ setting for VIF0 transfers (Refraction) + [*] Removed Call/Ret from SPR1, not used (Refraction) + [+] Added some more comments to DMA stuff (Refraction) + [-] Reimplemented the old vifunpack code, since saqib's one + had problems 'in pieces' transfers + [-] ElfHeader now loads the data though the program headers only + [-] Removed tadr+= 16 on refe/end on dmas + [!] I'll start commenting more the code from now on, so it'll + be easier for us to understand every part of pcsx2, others + pls do the same kthx + (Refraction-linuzappz) + + * 02/07/05:[-] Added saqib vif fixes + [-] Fixed Stall canceling stat bits (VIF_STAT_INT) + [-] Fixed Stall bits clearing + (Refraction-saqib-linuzappz) + + * 29/06/05:[*] iR3000A now has defines same as iR5900.c + [+] Added PSXCNT_LOG + (linuzappz) + + * 28/06/05:[+] Added InterlaceHack (usefull for Dinasty Warriors 3) + [+] Added SafeCnts flag, which makes very accurate iop counters, + but they make pcsx2 slower + [+] Added FastIopClk which sets the PsxClk to 86864000 + [!] There are sorta hacks and will go away in time when i figure + out how to really fix them + (linuzappz) + + * 28/06/05:[+] Added SIO plugin specs. Should be followed by compatible plugins :P + (Florin) + + * 22/06/05:[-] Console supports colors ;) + (linuzappz) + + * 19/06/05:[-] Fixed D/T flags (added interrupts) at VU0/1 + (linuzappz) + + * 18/06/05:[-] Rather small fixes to last update in vif, replaced cyclenum + with _vif->cl, also fixed a timing issue in vif0 + (linuzappz) + + * 14/06/05:[-] Alot of bugs fixed in VIF. Masking was not correct so was + filling write. VIF0 was incorrect. The VIF0 Fifo was always being set to 0. + [-] dmaSPR1 now handles Transfer Tag option. + (saqib and Refraction) + + * 31/05/05:[-] Fixed UNPACK's with masking + (linuzappz) + + * 29/05/05:[-] Fixed a few small timing issues with VIF1 + [-] Refixed end source chain tag to add 16 to tadr + (linuzappz) + + * 28/05/05:[*] Uncommented GS dma irq code + [-] Fixed some switch cases at iVUmicro.c + [-] Tested/Fixed DIS_S/MAX_S/MIN_S at iFPU.c + (linuzappz) + + * 28/05/05:[*] removed CVT_S regcaching from iFPU.c. That doesn't seem to work properly :~ + [*] Added MAX_S , MIN_S to reg caching iFPU.c . Not tested but should work + (shadow) + + * 28/05/05:[+] Added PNOR and impoved a few more MMI opcodes + [+] Few more opcodes to ix86_sse.c as well + (shadow) + + * 26/05/05:[+] added emulated hardware cd/dvd sector decryption routines + (should make the playstation2 logo display correctly now amoung other things) + [-] fixed cdvdReadKey to get correct args sent to it, also behaves a little differently depending on args + (loser) + + * 26/05/05:[*] fixed a silly bug in iMMI.c pmaxh,pminh opcodes + [*] optimized PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + [*] few more addes to ix86_sse.c . Linuz seemed to discovered new opcodes :P + (shadow) + + * 25/05/05:[+] Few opcodes added in ix86_sse.c .Few of them still needs recheck (shadow- Gabest) + [*] Added the following SSE,SSE2 opcodes to iMMI.c . + paddub,padduh,paddh,pcpyld,pmaxh,pminh,paddsb,paddsh,psubsb,psubsw,paddb,paddw,psubsb,psubsh + psubb,psubb,psubh,psubw + [*] More opcodes in SSE2 . PCPYUD,PSRLW,PSRLH,PSRAH,PSRAW,PSLLH ,PSLLW ,PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + (shadow) + + * 24/05/05:[*] PSXCLK now can be changed at the ini, defaults + to the right value (36864000) if it's 0 anyways + [-] Fixed bug at Interpreter.c for sstates + (linuzappz) + + * 23/05/05:[-] fixed a bug in iMMi.c PADDSD,PSUBSD doesn't exist in ix86 (who added them?) + [*] Added a new prefix in ix86_SSE opcodes, it is now more clear to understand what each opcode do + that also helped to find that linuz had added an SSE2 instruction in iFPU.c bad linuz ;P + [-] PSMAXSW,PSMINSW was writing to a XMM register (the SSE version writes to MMX register) fixed.. + [+] a few more SSE2 instructions needed for iMMI.c added in ix86_sse.c . + Linuz code them properly pls ;) + (shadow) + + * 23/05/05:[+] Added Devc++ 4.9.9.2 project files for compiling mingw32 with IDE :) + [-] Added a few missing defines + [!] still my project file can't make as fast exe as linuz's sse build. can't figure why yet + the problem should me around Makefile.win :~ + (shadow) + + * 21/05/05:[-] More PS1 compat fixes + [!] Seems the GPU->GS is done by the PS1DRV, gotta find out more + (linuzappz) + + * 19/05/05:[+] PS1 games kinda boot now as well ;) + (linuzappz) + + * 16/05/05:[-] Misc GUI fixes + (linuzappz) + + * 15/05/05:[-] More FPU regcaching stuff + [!] Finally changed version to 0.9 :D + (linuzappz) + + v0.8: + * 10/05/05:[-] Added some more code for FPU regcaching, still unused + [!] Code is closed today until release, only bugfixes now + (linuzappz) + + * 08/05/05:[-] More fixes/improvemets to VUrec/iFPU + (linuzappz) + + * 07/05/05:[-] COP2 now is recompiled when VUrec is enabled + (linuzappz) + + * 05/05/05:[-] Fixed a rather small bug in VIF1 unpack + [-] VU random functions are more correct now, thx goes to _Riff_ and saqib + [-] Sio arranged better for sstates + [*] Modified "FireWire" syms to "FW" + (linuzappz) + + * 04/05/05:[-] Timings in VIF1 should be more accurate now + [-] Fixed bug in the elf loading filter + (linuzappz) + + * 02/05/05:[*] recommited the old reccop2.c (shadow) + + * 02/05/05:[-] Fixed bug in REF/REFS dma at VIF1/GS MFIFO + (saqib) + + * 02/05/05:[*] Cpudialog will disable the checkboxes if the requested features not found + (shadow) + + * 01/05/05:[*] Created a new <> folder to clean up some stuff in the existing interface + Folders became better now and included project files only for vcnet2003 so far... + [*] Moved all patchbrowser source to patchbrowser.c and added language support for it + [*] CpuDialog is now At CpuDlg.c . Redone the Dialog a lotta better ;) + [*] The remaining console,thread,patches configure are now part of the main menu + [*] Organize cpudetection code a bit better. Cpudetection is now done in winmain.c + (shadow) + * 01/05/05:[*] Even more VUrec stuff + [+] Added some more Stats.c info per frame + [-] Fixed some MFIFO bugs remaining + (linuzappz) + + * 30/04/05:[*] More work on VUrec, flags are somehow implemented, PSHUFD is now + used to unpack XYZW/IQ stuff and bug fixes as well :) + (linuzappz) + + * 29/04/05:[-] Updated VIF0 code as VIF1 + [-] VIF1 doens't clears str on MFIFO (saqib) + [-] Fixed some MFIFO bugs in both GS/VIF1(saqib) + [*] Cleaned up dma## functions + (linuzappz) + + * 28/04/05:[-] end source chain tag seems not to touch tadr + [-] Vif1 dmaIrq seems ok, need to test it more tough + (linuzappz) + + * 26/04/05:[+] Added BC1 ops at rec + [+] Started some optimizations for UNPACK + [-] Skipping vif mode was still a bit buggy, seems ok now + (linuzappz) + + * 25/04/05:[*] VIF1 dma is kinda more asynchonous now + (linuzappz) + + * 22/04/05:[+] Added some cache code, not used by default, + it's just for testing atm + (linuzappz) + + * 21/04/05:[-] Readded SysPrintf for Cd/DvdReads + [-] Fixed NReady busy stuff, thx to loser + (linuzappz) + + * 19/04/05:[-] More VUrec refixing/work + (linuzappz) + + * 18/04/05:[+] added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose + to the cdvd plugin definitions + [*] changed CDVDgetType to CDVDgetDiskType + [-] fixed NVM (eeprom) access from cdvd stuff + [+] added reading of mecha version from an external file + [-] fixed raw dvd sector readng for dvd9 discs (otp and ptp) + [+] added hw-reg read/write for DecSet register 0x1f40203A + [+] made cdSeek change the current cdvd sector + [*] incremented cdvd plugin version and brought cdvd plugins in cvs up to date + (loser) + [-] __WIN32__ should not be used over PS2Etypes.h, + __MSCW32__ or __MINGW32__ must be used there + (linuzappz) + + * 16/04/05:[-] xyzw stalls was kinda wrong ;P seems ok now + [-] Fixed a bit vurecs + (linuzappz) + + * 16/04/05:[+] Added GSsetCSR + (saqib-linuzappz) + + * 14/04/05:[-] Fixed some small bugs over VUops.c for the regsNum stuff, + thx goes to saqib + [-] Really fixed skipping vif this time :P + [-] Fixed DIV/RSQRT exceptions (saqib-linuzappz) + (linuzappz) + + * 13/04/05:[-] Fixed skipping write mode at Vif + [-] Fixed unpack overflowing + (linuzappz) + [-] updated all visual studio project files to have the correct source/lib/includes + also removed unused dirs and files. now even 'debug config' will build ok :) + (loser) + + * 10/04/05:[-] Fixed stalls for VF regs, xyzw must be handled separatedly + (linuzappz) + + * 04/04/05:[-] Kinda reworked VU MAC flags, also fixed RSQRT neg prob, thx to Riff/saqib + [-] Fixes to VifDma cl/wl stuff + (linuzappz) + + * 03/04/05:[*] Modified a bit how branch works on VUs + (linuzappz) + + * 02/04/05:[-] Some fixes to VU flags/pipelines + (linuzappz) + + * 30/03/05:[*] Cleaned up a bit writes to VIFX regs + [-] Fixed a small bug in vif1 stalls + [-] Commented readclock win32 code at CDVD.c + [-] Fixed two small issues with branches in interp + (linuzappz) + + * 29/03/05:[*] Added some fixes from LDChen to hConsole/WM_PAINT stuff + [*] Modified GetToc stuff in cdvd to support dvds + [*] cdvdTD uses lsn now + (linuzappz) + + * 28/03/05:[+] Added placetopatch == 1, which means patches will be applied every vsync ;) + (linuzappz) + + * 27/03/05:[*] Improved cpu detection for Amd's 64 using BrandID. Most of the models should be + detected correct now (at least my cpu does ;P) (shadow) + + * 24/03/05:[-] Fixed ISUBIU :D + [-] Some fixes to flags, status was fecked, now seems better + [-] Commented the GS dma IRQ again, seems to cause more probs, will + fix it later + (linuzappz) + + * 21/03/05:[-] Fixed VIFX_CODE reg + [+] Added previous normal vu fixes to vurec + [*] Added EFU pipeline to VUmicro, kinda untested + [-] Hopefully fixed GS dma IRQ + (linuzappz) + + * 21/03/05:[-] Fixed cdReadKey function to emulate correctly. Now games should boot using + Execute with non Modded Bios. + (auMatt & Loser) + + * 20/03/05:[-] Started reg caching for VUrec ;D + [*] Rearrenged a bit rec32/64, added a common 'x86' dir + (linuzappz) + + * 18/03/05:[-] VU1micro was being executed instead of VU0, bad linuz bad :P + [-] Fixed VU's JR/JALR/BAL :D + (linuzappz) + + * 17/03/05:[-] Cleanup/speedup/fixup from last fixes :P + [-] VIF0 has no from mode ;) + (linuzappz) + + * 16/03/05:[*] Added some more debug info to CDVD + (auMatt) + + * 15/03/05:[*] Added an evil vuDouble function to convert from vu float format + to ieee 754 format ;) + [-] Reworked MAX/MINI + [+] Added experimental work for VU pipelines + (linuzappz) + + * 14/03/05:[-] Added the pipelines VU1 bug to VU0 + (linuzappz) + + * 12/03/05:[-] Fixed some pipelines bug within VU1 + (linuzappz) + + * 10/03/05:[-] Fixed small bug over VIF1 dma FIFO + (linuzappz) + + * 08/03/05:[-] Fixed vu flushing over vuExecMicro + (linuzappz) + + * 06/03/05:[-] Fixed UNPACK V4_5 with mask + (linuzappz) + + * 04/03/05:[-] Small fixes to VUrec + (linuzappz) + + * 01/03/05:[+] Added new VS2005 sln and .vcproj to build the 32bit version of + pcsx2 in VS2005 Beta1 (You have to use different projects to build) + [*] Changed some of the files to make them compile in VS2005. + (GoldFinger) + + * 23/02/05:[-] Commented hack at VSync + [+] Added interleave mode for SPR + (linuzappz) + + * 20/02/05:[*] Changed IRQ defines to functions + [-] VIF irq by vifcode seems ok now + [+] Added offset/difference with mask UNPACK modes in vif + [-] SPR1 was transfer /4 the size it should have :/ + (linuzappz) + + * 16/02/05:[-] Fixed some VPU-STAT related issues + [+] 'sstates' dir is now created at init + (linuzappz) + + * 15/02/05:[+] Another DNAS by nachbrenner + (linuzappz) + + * 14/02/05:[+] Added offset/difference UNPACK modes in vif + (linuzappz) + + * 14/02/05:[*] 64bit rec back to x86-64 better this way + [*] Updated vsnet2005beta1 project files to compile with x86-64 dir + [*] Added a few pragma warnings disable to a few files to correct some silly vsnet2005beta1 + warnings (blah MS deprecated stdio pffff) (shadow) + + * 10/02/05:[-] Fixed bug in CDVD_findfile + (linuzappz) + + * 09/02/05:[*] GSvsync is now called on the vsync start + (linuzappz) + + * 08/02/05:[*] QWC is set to 0 after a normal transfer in GS/SPR1/VIF1 + and MADR is increased qwc*16 as well + (linuzappz) + + * 07/02/05:[*] Changed a bit the CPU dialog. Now it is better i guess :) . Linuz update the pcsx2.po again pls :D + [*] Added a __VCNET2005__ definition cause vcnet2005beta1 doesn't support inline asm.. + That only effects Cpudetection.c and Gte.c (not much since it has c code instead to use). + Cpudetection must be written on ml64 to be useable on vcnet2005. + [*] Added prelimary vcnet2005beta1 project files. gettext disabled cause we still doesn't have a + 64bit version for it + [*] Small fixes around and wholaaa i produced the first buggy pcsx2_64bit.exe :) (shadow) + + + * 07/02/05:[+] Added another DNAS version thx to Nachbrenner + [-] Fixed SPR0 chain mode + [-] Fixed intc/dmac interrupts that gets cleared right away + [-] Cleaned up langs a bit, only spanish works so far now + [+] Added 1f402007 reg, "BREAK", still not really handled ;P, + thx to matt + (linuzappz) + + * 31/01/05:[-] Disabled recompile functions recBGEZ() and recBLEZ() from iR3000.c . That will make + recompiler not to crash after the players selection screen in Virtua Fighter 4. Thanks + to JayteeMaster for bug tracing it ;) (shadow) + + * 30/01/05:[-] Fixed some more bugs in IPU, some streams had a few problems, now they are ok. + Quality of ipu playback also improved(thanks JayteeMaster for pointing it out) + (asadr aka saqib) + + * 26/01/05;[*] Merged a big part of linuz's amd64 rec to the normal rec (shadow) + + * 25/01/05:[-] Finally fixed IPU. Mpegs and IPU streams run + so do PSS files.Some fixes to MMI and Interpreter (asadr) + + * 23/01/05:[-] Fixed vurec crash on pcs that doesn't support SSE2 + [*] General cleanup on ix86-32 rec. Goldrec removed since no progress has been made + lately (shadow) + + * 20/01/05:[+] Added x86-64 rec, still unclean, but i'll leave for holidays this + saturday, so ^^ + (linuzappz) + + * 19/01/05:[-] Fix for end chain mode at vif, still gotta check it + (linuzappz) + + * 16/01/05:[-] Lots of fixes to VUmicro, thx to Refraction for pointig out + some bugs ^^ + [*] Commited ix86 changes for x64 + (linuzappz) + + * 13/01/05:[-] WriteNVM now takes address in param[1], thx to auMatt + (linuzappz) + + * 06/01/05:[-] Fixed long types at VU.h + [-] Removed memLUT decl + [!] Notice long is 8bytes long in amd64, so we should + stick to the u32/s32 types instead of using long pls :) + (linuzappz) + + * 06/01/05:[-] Fixed SBUS IRQ at iop + [-] dmaGetAddr now uses memLUTR + (linuzappz) + + * 05/01/05:[*] Changed some stuff for amd64, still more to come + [+] Added more memRead/Write funcs for speed + [-] Fixed some iVUmicro bugs + [-] Fixed QFSRV/MTSAH/MTSAB + (linuzappz) + + * 03/01/05:[+] Implemented MFLAG for VU0 + [-] Vsync is now genereted on boths cpus at the same time + (linuzappz) + + * 03/01/05:[-] Commented dma irq stuff, fecks some games, gotta recheck that + (linuzappz) + + * 22/12/04:[-] Fixed bug in branch address in vus + (linuzappz) + + v0.7: + * 18/12/04:[*] Added GSread8/16/GSwrite8/16, GSgifTransfer1 now has two args, + added the addr and pMem points to the VU1 mem + (linuzappz) + + * 16/12/04:[*] Pofis improved his Patchbrowser (shadow) + + * 06/12/04:[-] Fixed Langs support for win32 + (linuzappz) + + * 06/12/04:[*] Added support for 1.90 Bios NVM. + (auMatt) + + * 06/12/04:[+] Added Patch Browser for win32 . Made by Pofis (shadow) + + * 05/12/04:[*] NVM always loads rom %Bios%.NVM + [*] Cd/Dvd Reads are now again displayed on console, + that is very helpfull for testing :) + (linuzappz) + + * 28/11/04:[-] BC2T/F/TL/FL also check for VU1 to be stopped + [-] VU1 memory is masked on micro load/store instructions, + dunno yet about VU0, gotta test ;) + (linuzappz) + + * 26/11/04:[-] VU D/T flags are handled now (kindaof :P). + (linuzappz) + + * 20/11/04:[-] RTC timezone fixed (gigaherz) + + * 19/11/04:[-] Fixed vu branch negative overflows + (linuzappz) + + * 17/11/04:[*] Fixed some stuff in logging so now + -Memcards sysprintf messages Are now MEMCARDS_LOG define and enable with PAD_LOG + -Cdreads Dvdreads are now in CDR_LOG + -Vus Overflow enable from CPU_LOG + That means less logs at runtime and no more complains from nasty betatesters :D (shadow) + + + * 17/11/04:[*] fixed linuz bug in naming the memcards different in 2 different places + Memcards now are Mcd001.ps2 and Mcd002.ps2 in emu and McdDialog (shadow) + + * 16/11/04:[-] Fixed NVM File Load and Creation. Defaults to BIOS name als now. + (auMatt) + + * 15/11/04:[+] Added another DNAS at Misc.c. + (nachbrenner) + + * 14/11/04:[-] VU0/1 reset shouldn't reset the micro memory. + [*] Commented the LT_OpcodePrintTable call on Interpreter.c, + for speed :) + (linuzappz) + + * 12/11/04:[-] Second MCD works fine now. + (linuzappz) + + * 11/11/04:[-] Finally fixed SIF1 bug :D:D + (linuzappz) + + * 10/11/04:[+] Added MingW32 support ;). + (linuzappz) + + * 10/11/04:[-] Fixed NVM loading/reading/writing and also fixed v12 NVM issues. + (auMatt) + + * 09/11/04:[+] Added BiosVersion var. + [*] Sif stuff now gets saved over sstates. + (linuzappz) + + * 09/11/04:[-] Fixed bug in ModelID code in CDVD + (florin-auMatt) + + * 07/11/04:[-] Fixed bug that caused to interrupt twice before + handling the first interrupt. + (linuzappz) + + * 05/11/04:[-] Small fix for broken elfs. + (linuzappz) + + * 04/11/04:[-] CDVD was interrupting dma too much :P. + (linuzappz) + + * 03/11/04:[*] Added FREEZE_SIZE. + (gabest-linuzappz) + + * 03/11/04:[+] Added a couple of DNAS at Misc.c. + (nachbrenner) + + * 02/11/04:[+] Added hack for QFC in GS ;). + (linuzappz) + + * 01/11/04:[+] Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2. + (linuzappz) + + * 31/10/04:[-] Fixed v12 bios running. + (auMatt) + + * 30/10/04:[-] Fixed v9-v10 bios running. + (auMatt) + + * 28/10/04:[-] Really fixed SIF SMFLAG/MSFLAG :P:D + (linuzappz) + + * 28/10/04:[-] Fixed MCDS :D + (asadr) + + * 26/10/04:[*] Added rom2/erom support + (auMatt/linuzappz) + + * 23/10/04:[*] Added/Fixed Model Number Reading + (auMatt/Florin) + + * 18/10/04:[-] Fixed SIF SMFLAG/MSFLAG, needs testing tho + (linuzappz) + + * 06/10/04:[*] More BIOS detection added.(auMatt) + + * 04/10/04:[-] Fixed EXL bug + [-] Fixed SIF0/1 when fifo got filled up + (linuzappz) + + * 01/10/04:[-] CdReadConfig/CdWriteConfig now uses NVM ^^ + [!] Bios configurations now gets saved/loaded from NVM (nvm.raw) + (linuzappz) + + * 1/10/04:[+] Started coding the memcard manager. Far from finish but will be better soon :D + [*] Change settings . Default memcard is now a ps2 memcard. (shadow) + + * 30/09/04:[-] Newer bios will now work with pcsx2. Pads fixed, more + compatibility. (asadr) + + * 27/09/04:[-] VU0/1 Reset hopefull fixed + (linuzappz) + + * 16/09/04:[*] NVM now is readed/written from nvm.raw. + [-] ReadILink/GetMecaconVersion are really implemented ^^ + (auMatt-linuzappz) + + * 15/09/04:[*] Rewritten LoadConfig-SaveConfig to use ini instead of registry. + [*] Removed DeleteRegistry button. For obvious reasons :D (shadow) + + * 15/09/04:[-] Pads finally fixed - Fixed PADwin Plugin Required! + Updated stuff at PsxSio2.c and Sio.c (Pad Hack still + there but won't be used) asadr + + * 13/09/04:[+] Added an option for setting the main thread priority, usefull at work :P + (linuzappz) + + * 13/09/04:[*] Fixes to SCMD's (auMatt) + * 02/09/04:[*] Finally commited asadr's IPU changes + [-] Fixed small bug in memory dump for win32 + (linuzappz) + + * 30/08/04:[*] Added Deci2 Call back into the Interpreter.c for printf.(auMatt) + + * 18/08/04:[*] fixed finaly the IOP disasm. Should be correct now... + [+] for stuff for amd64 porting.notice that pcsx2_2003_amd64 project just check for 64bit + portability.Can't produce 64bit exe yet.. (shadow) + + * 15/08/04:[-] fixed the IOP-EE disasm problem.(for ppl with vc != 2003 you must include + DisR3000asm.c and DismAsm.h in your project files) + [!] Still have to finish the correct IOP disasm :D + [+] Added small framework for x86-64. Still nothing that useable :D (shadow) + + * 04/08/04:[-] PadHack now works again :) + [-] Sio2 now supports states again + (linuzappz) + + * 02/08/04:[*] F2 will print the selected state on the console + [*] Added overflow messages for ISW/ILW/ILWR/ISWR + [*] FBRST should reset the vus when VU0 Reset/VU1 Reset + bits are set, but i don't really know have much it's + resetted :P + (linuzappz) + + * 30/07/04:[-] Vif1 MPG lacked a flush + (linuzappz) + + * 28/06/04:[+] Added GSprintf, GSgetDriverInfo and PADgsDriverInfo + [+] Deci2Call 0x10 gets printed ;) + [-] Some fixes to CDVD reading + (linuzappz) + + * 24/06/04:[-] Fixed some bugs over interrupts and + exceptions + (linuzappz) + + * 22/06/04:[-] Couple of bugs fixed over IPU1 dma + [-] psHu32(INTC_STAT) changed to INTC_IRQ + (asadr-linuzappz) + + * 16/06/04:[-] Counters regs are returned in 16 bits + [+] Also added them for hwRead16 + [-] Counter only resets when writing to the mode reg + when the value & 0x3ff differs from the actual mode + [-] Fixed BCR interrupting for CDVD ;) + (linuzappz) + + * 14/06/04:[*] Enabled SSE Vif at i386.asm + [*] Added florin's work over mcds, still needs + a cleanup :) + (linuzappz) + + * 10/06/04:[*] CSRr is OR'd with 0x8 always over VSyncEnd + (linuzappz) + + * 08/06/04:[*] VU pointer gets aligned now + (linuzappz) + + * 07/06/04:[*] vuJALR now uses _Fs_*8 + [*] VSync now interrupt for INTC_STAT & 0x1 + [!] Based of debugging Aura for Laura :) + (linuzappz) + + * 07/06/04:[*] Detection for Chinese Bios. + (auMatt) + + * 04/06/04:[-] Cleaned a bit VIF1transfer, and now when + DIRECT/DIRECTHL cmd is misaligned it skips it + [*] Added USBirqHandler, USB specs v2 now + (linuzappz) + + * 04/06/04:[-] VU1 regs now are mapped to VU0 mem + (linuzappz) + + * 02/06/06:[*] finished most of the iops disasm works :P + [*] increase the firewire reg size . seems there are more regs ;p (shadow) + + * 25/05/04:[-] Fixed big stupid bug in counters ;P + Now they're accurate + (linuzappz) + + * 25/05/04:[*] Included new BIOS detection 'P'. For Free and Public BIOS Images. + (auMatt) + + * 20/05/04:[*] BCR now decrements for each cdvdReadSector, thx to Roor + (linuzappz) + + * 18/05/04:[*] Removed PsxBios2.c/h, and cleaned Irx funcs from ElfHeader.c/h + [+] Added cpuTestHwInts/cpuTestINTCInts/cpuTestDMACInts + [+] More work over mcds + [!] Now cpuBranchTest doesn't checks for irqs + (linuzappz) + + * 17/05/04:[-] Fixed bug psx counters, thx gold + (linuzappz) + + * 15/05/04:[+] Added IOP disasm in the debugger... + [!] Not yet finished and i disasm using R5900disasm atm. I will code it correctly soon (shadow) + + * 12/05/04:[*] More optimizations to the FPU rec + [*] BIAS was commented over Counters.c :/ lol + [-] Disabled EMMS_TRACE, it's buggy, dunno why tho + (linuzappz) + + * 11/05/04:[*] Now Saving/Loading FPU CW only for the ops that really need it + [*] Added some optimizations to jumps over rec + [*] Added LQC2/SQC2 + (linuzappz) + + * 08/05/04:[-] Fixed states loading/saving from the menu + (linuzappz) + + * 03/05/04:[*] Uncommented the sio2 1d100 hack + (linuzappz) + + * 3/05/04:[+] started reorganize the src. Lotta unneccesary stuff removed(like HLE) and lotta + organized. still needs a lot of work to clean but it's a start (shadow) + + * 02/05/04:[+] Added D3/D4 defines at Hw.h + (linuzappz) + + * 1/05/04:[+] Added a Delete Registry Button. It deletes pcsx2,gssoft settings + (shadow) + + * 30/04/04:[-] Small bugfix for cpu speed detection, thx to Rainer Aglas + (linuzappz) + + * 27/04/04:[+] Implemented ReadNVM/WriteNVM, untested though + (linuzappz) + + * 15/04/04:[-] SPUdma timings changed to 80, thx _Riff_ + (linuzappz) + + * 13/04/04:[*] Several changes for IPU + [+] IsBIOS now belongs to Misc.c + (asadr-linuzappz) + + [*] Dev9Null/USBLinuz/FireWire Plugins Configure now shows + Message. + [*] Configure Menu Shows USB and FireWire Options. + (auMatt) + + * 12/04/04:[-] Fixed SPU2async cycle, was getting reseted wrongly, + thx _Riff_ + [+] Added SPU2irqCallback + (linuzappz) + + * 08/04/04:[-] Unhacked sio2 for 1d100 recv1 mode + (linuzappz) + + * 07/04/04:[+] FireWire IRQ is implemented ok now + [-] Forgot dev9Interrupt over R3000A.c + (linuzappz) + + * 05/04/04:[+] Added Firewire plugin protocol. (shadow) + + * 02/04/04:[-] VIF-FIFO transfers seems to work better ;) need testing + [+] Added GSreadFIFO + (linuzappz) + + * 30/03/04:[*] sstates now use CRC as well :) + [*] emuLog.txt now goes at 'logs' dir + (linuzappz) + + * 29/03/04:[*] GSdma now waits qwords transferred cycles + before clearing CHCR and triggering, + OPH and APATH are handled as well now. + (linuzappz) + + * 25/03/04:[*] Some rewritte over Sio.c + (linuzappz) + + * 24/03/04:[-] ostr size is now 1024 in Dis*.c + [!] Finally v0.7 :D + (linuzappz) + + v0.6: + * 21/03/04:[-] About dialog was cropping the testers, thx CK :) + (linuzappz) + + * 19/03/04:[+] Added a PadHack option at the cpu dialog + [-] Couple of fixes for release + (linuzappz) + + * 16/03/04:[-] CRC had a bug, now it's ok, sorry :) + [-] Fixed bug in memInit, thx gold :) + [-] LoadState now loads the tlbs + (linuzappz) + + * 16/03/04:[-] Fixed another silly bug in loadElfFile ;) + (linuzappz) + + * 15/03/04:[+] Added texts on the console Title to make patch makers life easier :P (shadow) + + * 15/03/04:[-] Fixed a free in loadElfFile + (linuzappz) + + * 14/03/04:[*] loadElfFile now reads the whole file first + [-] DMA4/7 interrupt timings are more accurate now + (linuzappz) + + * 12/03/04:[+] Added i386.asm, only used on linux so far, + compiles using nasm, it replaces the inline + assembling for Vif + [-] Fixed bug in UNPACK for skipping write + (linuzappz) + + * 11/03/04:[*] Patches names are now using crc, + instead of ie.: + Ridge Racer V PAL was SCES_500.00.pnach, + now it is 5BBC2F40.pnach + this way games with the same code + will not get confused + [-] Fixed bug in disR5900GetUpperSym + (linuzappz) + + * 10/03/04:[+] Added SQ/LQ over iVUmicro + (linuzappz) + + * 09/03/04:[-] sio2Reset was missing from psxHwReset + [-] Fixed sio pad swaps for 0x1100 mode + (linuzappz) + + * 08/03/04:[*] Modified the DEV9irq stuff + (linuzappz) + + * 05/03/04:[-] DEV9irq now issues a SBUS_IRQ + [*] malloc memory is now aligned to 16bytes + (linuzappz) + + * 02/03/04:[-] Added presaving for MMI ops that needed that + [-] vuJR/vuJALR now masks Fs with ~0x7 + (linuzappz) + + * 02/03/04:[+] stats.txt now dumps the Cpu mode + (linuzappz) + + * 01/03/04:[-] dmaGetAddr now uses memLUT + [+] Finally added USB plugins ;) + (linuzappz) + + * 26/02/04:[-] Fixed VUops that didn't have presaving + (linuzappz) + + * 22/02/04:[+] More ops at DisVUops.h + [-] VifDma.c is cleaner now, also fixed some + stuff for savestates + [-] Added some remaining vars at cpuBranchTest + to cpuRegs for savestates + (linuzappz) + + * 21/02/04:[-] Fixed ITOF0 + (linuzappz) + + * 20/02/04:[-] Fixed savestates ;) + (linuzappz) + + * 19/02/04:[*] VUflags now should handle overflow/userflow ok + (linuzappz) + + * 17/02/04:[*] Improved and fixed sio2 stuff + [-] Fixed _vuMFIR + (linuzappz) + + * 16/02/04:[-] DIV could crash when divisor == 0.0, + as well as ERSADD + (linuzappz) + + * 13/02/04:[-] Fixed FCAND over VU1ops.c + [*] Merged VU1ops/VU0ops/Vops to VUops + [*] Cleaned up VUflags.c + [-] hackedRecv now defaults to 0x1100 + (linuzappz) + + * 09/02/04:[-] VifDma.c MPG now clears the VU0/1 Mem though Cpu->ClearVU0/1 + (linuzappz) + + * 09/02/04:[-] More SCMD functions added. Still require working code for them. :) + (auMatt) + + * 06/02/04:[-] More iVUmicro.c opcodes, fixes, and stuff :) + (linuzappz) + + * 06/02/04:[-] Fixed Bios Detection for HK Bios. + (auMatt) + + * 06/02/04:[-] Fixed CdRom/CDVD Interrupt for 0x41000200 chcr, + now it interrupts after the read ends + (linuzappz) + + * 05/02/04:[+] Added FALSE/TRUE in GRecCommon.h + [+] Added more 16bit ops to x86.c/h + [+] Fixed SQD/SQI and implemented IOR/IAND over iVUmicro + [-] BIAS is now 2 again + [+] Now only MARK is writable at Hw.c, for vif0/1Regs + (linuzappz) + + * 03/02/04:[-] Fixed FALSE to GREC_FALSE in GRecMain.c + [-] Added break to F5 ;) + [-] Commented 'ERL Set' SysPrintf + (linuzappz) + + * 02/02/04:[-] Included stdarg.h in GRecCommon.h + [+] Added some scmds to CDVD.c (auMatt) + [+] cdvd.Status now changes to CDVD_STATUS_SEEK_COMPLETE, + after a CdRead CMD + (linuzappz) + + * 16/01/04:[+] Added LQI/LQD/SQI/SQD over Recompiler + [-] Updated EE BIAS to 8, need to test this + [!] SQI/SQD are diabled still, because they are still buggy + and i don't have more time... vacations :D:D + (linuzappz) + + * 15/01/04:[+] Added code for dma interrupts, for IPU FDEC, still commented + (linuzappz) + + * 14/01/04:[+] Temporary fix for PADS. F5 now change the pad mode on the fly. if your game doesn't work + switch it from there. (shadow) + + * 12/01/04:[*] FIFO is now really 128bit as it should be :) + (linuzappz) + + * 09/01/04:[-] Fixed VU->VI[0] != 0 bug in VU1, VU0, Macromode, JALR, BAL, LQI, LQD, SQI, SQD were setting VU->VI[0]. + Address in VCALLMS was incorrect, was causing crash in VF4. + (asadr) + + * 09/01/04:[*] Start to convert VIF stuff to functions instead of macros, right now I just converted + them duplicating the code for VIF0/1 and it is working but it is not the best yet, + commiting just so others can debug VIF while I finish the work, did some minor fixes + on VIF too. + [*] The only major function needed to be reduced to one is VIF0transfer/VIF1transfer, all + others are ok (I think). + (GoldFinger) + + * 09/01/04:[-] Fixed LQC2 for _Fs_ == 0 + [*] Fixed several SIF bugs (NoComp) + (linuzappz) + + * 06/01/04:[-] Fixed UNPACK modes in VIF.c, the Indeterminate fields are now set to 1 by default. (asadr) + + * 04/01/04:[-] Fixed a bug in LQD and LQI when _Ft_ was 0. + (GoldFinger) + + * 04/01/04:[*] Modified the VIFregister structure, both VIFs(0,1) have the exactly same + structure, just VIF0 does not use some of the registers, so I unified the + structures for easy reading and less bugs. + (GoldFinger) + + * 31/12/03:[-] Added USB API at PS2Edefs.h ;) + [+] More ops at DisVUops.h + [*] UNPACK now flushes the VU micro + (linuzappz) + + * 30/12/03:[-] Fixed savestates in Misc.c and added fixed VIFdma.h + (asadr) + + * 29/12/03:[-] Fixed bug for new vu code in savestates + (linuzappz) + + * 27/12/03:[-] Fixed bug in my last update for R5900.c + (linuzappz) + + * 26/12/03:[*] VUflags are now updated when Rd == 0 as well, changed only + at VU1ops.c + [*] VU1Regs/VU0Regs is now VURegs + [!] I think we should merge VU1ops/VU0ops/Vops + (linuzappz) + + * 24/12/03:[-] Fixed DMA8 for PsxDma.c + [*] LUI is now as it was before asadr's update + [*] readded 'if Log' over debugI at Interpreter.c + (linuzappz) + + * 18/12/03:[*] Restructured VU code and VIF. Fixed stuff in Interpreter + and added CTC2 VU1 Microinstruction caller. + (asadr) + + * 18/12/03:[*] Improvements to TLB code. + (linuzappz) + + * 17/12/03:[-] Fixed iCP0.h define to __ICP0__ + [+] Added disR5900GetUpperSym + (linuzappz) + + * 08/12/03:[+] SSE recompile of vus started. Some opcodes works some yet not. + Missing flags that i gonna add soon. Gives some speed boost :) + (shadow) + + * 05/12/03:[-] Fixed bug in GS for CSR stuff + (linuzappz) + + * 03/12/03:[+] Added Interlock for CFC2/CTC2 + [-] Fixed CFC2/CTC2/LQC2/SQC2, they now + check for zero registers + [!] This should fix the 'R0 is not zero' + and the 'VU memory overflow' hopefully ;) + (linuzappz) + + * 03/12/03:[+] You now disable vu0 macromode too when you disable vu recs by the + checkbox iR5900.c + [-] corrected some more bugg0rs of linuzappz sse instructions ix86_sse.c + [!] careful linuzappz's code. Don't ever trust him cause he is a lazy bugg0r + His mind is only for pampita!:) (shadow) + + * 02/12/03:[+] Added UNPCKLPSRtoR and MOVLHPSRtoR, there you go expert :) + (linuzappz) + + * 01/12/03:[-] Fixed savestates + (linuzappz) + + * 30/11/03:[+] a few sse instructions in sse.c + a much cleaner code in reccop2.c (shadow) + + * 28/11/03:[-] Recommited old VUops.h with asadr's EATANxy/EATANxz bugfixes + [!] asadr, the VUops.h you commited was in html format, + and some opcodes you change were only to slow down things, + commit other ones that need fixes. + (linuzappz) + + * 28/11/03:[-] Fixed alot of bugs in VUops.h, hopefully some stuff will now + work as it should (asadr) + + * 27/11/03:[*] fixed some stuff in recCOP2.c (shadow) + + * 25/11/03:[-] Fixed bug in Vif.c, masks hopefully are ok now ;) + (linuzappz) + + * 25/11/03:[-] Fixed Interpreter.c ix86.h include + [-] Added to GRecBasic.h a newline at end of file, linux + complains else ;P + (linuzappz) + + * 24/11/03:[+] Added cpu detection in interpeter.c too so now you can use SSE,MMX code in + interpreter too without the fear that your pc doesn't support it ;P (shadow) + + * 22/11/03:[+] By Nachbrenner request i added a memory patcher in Debugger.Now you can make patches + while pcsx2 is running. It is not yet finished as it can only patch 32bit data but + all the patches so far are 32bit so no problem ;P (shadow) + [!] Update Common.h . We are up to pcsx2 0.6 now! :) + + v0.5: + * 21/11/03:[-] Fixed Vif.c bugs :) + [!] Source code closed for release 0.5, + only bugfixes con be submitted + (linuzappz) + + * 21/11/03:[*] Started optimizing vif.c but I find so many strange stuff (problably bugs), please + linuz, check the comments I added on the vif.c file, and tell me what to do. + (GoldFinger) + + * 20/11/03:[*] Reorganize the cpu dialog a bit and added a new option. Disable vu recompiler + with disable the recompile of vu and will save some games from freeze when + vu memory overflows (quite often) :P . This will be removed when vu problems will + solve :P (shadow) + + * 19/11/03:[-] Fixed bug in savestates + (linuzappz) + + * 18/11/03:[*] Removed the old reg caching code including the sources, so now the only rec + that works is the normal one. + [*] GoldRec is progressing, I did lots of changes to make the progress better, + right now nothing works. + (GoldFinger) + + * 14/11/03:[*] Modified GSfreezeData, now it's plugin dependant + [+] Added SPU2freeze/DEV9freeze + [-] Fixed bug in inifile_read, hi shadow bugg0r :P + [-] Fixed bug in Sio2 + (linuzappz) + + * 14/11/03:[*] change pcsx2 patch system to use *.pnach files.Now you need a patches dir in your + pcsx2. (shadow) + [!] Am i the only one that write a changelog here?? (shadow) + + * 13/11/03:[-] fixed savestate naming in win32 and linux (shadow) + + * 06/11/03:[+] cleaned up a bit rec vu and enabled vu0 micro (shadow) + + * 06/11/03:[-] Workaround in VifDma.h for FiFo transfer ;) + (linuzappz) + + * 04/11/03:[*] Changed the way we handle SPR TTE transfers, also + MFIFO_VIFtransfer transfer always the ptag+2 + [-] Unhacked Sio.c for PADs ;) + [!] Now you gotta use the PADwinKeyb from PADwin at cvs + (linuzappz) + + * 03/11/03:[-] Fixed ba8R16 bug in Memory.c + [*] Enabled VU1 micro recompilation + [*] dmaGetAddr goes though memLUTR now + (linuzappz) + + * 02/11/03:[-] Fixed MSUBA had the same problem as MSUB, iFPU.c + A = A - B * C != A = B * C - A :) + (GoldFinger) + + * 01/11/03:[+] Addded cpu speed detection in cpu detection code + [!] Linuz fix the cpu_detection.c to work with linux pls ;p + [!] Goldfinger was right.Police 24/7 is okay with MSUB now :) (shadow) + + + * 01/11/03:[-] Fixed MSUB (MADD was ok), iFPU.c + Expert, please try in Police 24/7... :) + (GoldFinger) + + * 31/10/03:[-] Fixed PCPYLD, MMI.c + (linuzappz) + + * 30/10/03:[-] disable MADD,MSUB from iFPU. that ops was causing bugs in police 24/7. + Can't figure why, can someone? (shadow) + + * 29/10/03:[-] Commented D/T flags for VUmicro + (linuzappz) + + * 28/10/03:[-] Fixed memory rec issue, blah, shadow was right again :P + (linuzappz) + + * 27/10/03:[-] More fixes to memory stuff, hwregs for 128bit + [-] Fixed vifNum == 0 for UNPACKs + [-] DEV9_R_DEV now goes though DEV9read16 :) + [+] FiFo VIF1 can read data now ;) + [-] Fixed rec mem limit, shadow was right ;P + [!] Try Make Your Dream Home now ;) + (linuzappz) + + * 26/10/03:[-] Fixed Memory stuff, now it works ok :) + (linuzappz) + + * 25/10/03:[*] Some changes to memory cards. It's not what you all expect:P + (Florin) + + * 25/10/03:[*] Improved more the cpudetection routine at the Supporting Instruction sets features + [-] Improved a bit the MMI and fixed some bugs that prevent PII cpus to work (shadow) + + * 23/10/03:[-] Fixed a bug in Memory, untested actually ;), should fix + the loader rec bug + (linuzappz) + + * 24/10/03:[*] Improved the cpudetection routine in goldrec.Now more info appears :) + (shadow) + + * 23/10/03:[*] Improved VIF for transfers in parts + [-] Fixed some bugs in DisVUops.h ;) + [-] Fixed a bug in Memory, VU1.Mem was twice, thx shadow :D + (linuzappz) + + * 21/10/03:[-] Scratchpad memory was set bigger that it really is + [-] Uncommented a few tlb related printfs just in case ;) + (linuzappz) + + * 20/10/03:[*] Rewritten several Memory.c code, it's very untested, so far + i only tested bios, so tell me what's broken now :) + (linuzappz) + + * 18/10/03:[*] Fixed the rec for use with the tlb code, but this is a no go, slow as hell we must + change the whole tlb stuff, please linuz, lets think better before implementing this. + (GoldFinger) + + * 14/10/03:[*] Modified the memRead functions, now they're better for tlbs + misses, but note that they have one more arg, so gold, you'll + have to update the rec + (linuzappz) + + * 12/10/03:[*] Removed the new module in cvs called GoldRec. Now GoldRec is a directory under ix86-32. + (GoldFinger) + + * 10/10/03:[*] Removed the new recompiler from the main project and removed its dependencies, now there + is a new module in cvs called GoldRec, you must check it out. + (GoldFinger) + + * 10/10/03:[*] Improved TLB stuff a lot ;) + (linuzappz) + + * 07/10/03:[-] Fixed bug for recompiler in psx writes from Memory.c + (linuzappz) + + * 06/10/03:[*] VU0/1 now uses the VURegs struct + [+] Added the possibility to load the System.map from ps2linux + [+] Added TLB exceptions + [-] Fixed psxM accesses from Memory.c + (linuzappz) + + * 04/10/03:[*] rewrote the recompiled vu micro startup code and separate it + [-] remove the 3dnow code for reccop2 as it created more problems that it actually solved + [+] qmf2,qmtc2 is now done in SSE too . (shadow) + + * 01/10/03:[+] Handle for the EDI flag at ERET, a guess actually ;) + (linuzappz) + + * 30/09/03:[*] Reg caching works with bios and almost everything as normal rec does, need to + check better what does not work. + [*] Splitted iR5900.c into several .c files for easy navigation and for sanity + purposes as iR5900.c was HUGE. + [-] Fix LOTS of reg caching bugs, the main one was the comparission of 64bits registers. + (GoldFinger) + + * 30/09/03:[*] Added a base interrupt delay for the dma7 (spu2) + [*] More improvements to VifDma.h + (linuzappz) + + * 29/09/03:[-] Reimplemented Interrupt latency over R5900.c + [-] Fixed load/store unsigned addr to signed one over VUops.h + (linuzappz) + + * 28/09/03:[-] Fixed dmaIrq's for Source Chain mode + (linuzappz) + + * 26/09/03:[-] Fix the speed optimization problem that was in softCall function in Bios.c, + added a #pragma to disable optimization just to that function and everything + is working again as it should (linuz, please check if this pragma will interfere + with linux) + [*] The win32 project is back like before, the new Recompiler project was removed and + everything is working. + (GoldFinger) + + * 26/09/03:[+] Added two keys (F11, F12) for Opening/Closing the CDVD tray, + only for linux so far. + (linuzappz) + + * 25/09/03:[*] Sio2 fixes. Now the mcs are 'seen' as PS2 cards but unformated(able:P) + (Florin) + + * 25/09/03:[*] Modified the project structure under win32, I separated the recompiler from + the main project into a static lib, so now I can work with two projects instead + of one and enable optimizations. Now register caching works much better as I + enable speed optimizations in the Recompiler project but had to disable it in + the main project, the real problem is the global optimizations, this way I am + proving that the problem is not on my code... :) + [-] Fix lots of reg caching bugs and commented some of the reg caching instructions + that are buggy. Lots of demos work now, P51, colors, colors15 and maybe some others. + (GoldFinger) + + * 23/09/03:[-] Changed the MessageBox in recFunctions.c to SysMessage + [+] FIFO for VIF0/1 now works :) + (linuzappz) + + * 23/09/03:[*] Splitted the bios files so the code is the .c files and not on the .h files + [-] Fixed several bugs in reg caching and improved the routines + [!] Visual Studio .NET (dont know the others) speed optimizations are + messing with the code so it is recommended to build release mode + without Speed optimizations + (GoldFinger) + + * 23/09/03:[-] Commented the Syms in BiosInit.h, since they are only + for scph10000 + [-] Fixed ret DMA op + [+] Added iVUmicro, for recompiler + (linuzappz) + + * 22/09/03:[*] Added ExecuteVU0/VU1Block in R5900cpu, R5900.c + [+] Destination Chain for SPR0 dma and added Vif masking + [!] Gold, please merge the beta changes i sent you for + the iVUmicro.c/h + (linuzappz) + + * 20/09/03:[*] Now pad2 works in lle mode [tested with bios browser] + [+] New SCMDs and MC commands + [-] Fixes in sio, sio2, cdvd, etc. + [!] Now mcs appear as not inserted, but they are wip:P + SecrCardAuth() works fine;) + (Florin) + + * 19/09/03:[-] Small bugfix in Hw.h, u32 qwc -> u16 qwc; u16 pad; + [+] Small hack in Memory.c for ba000006 + (linuzappz) + + * 17/09/03:[-] Corrected a unpack bug i forgot ;) + [+] Implemented mskpath3 / m3r flags + [-] Fixed rom1.bin lookup for linux + (linuzappz) + + * 16/09/03:[-] Linuz fixed the macro bug hanging Visual Studio + (Gold-linuz) + + * 16/09/03:[-] More bugfixes/additions to Vif/VUs + (linuzappz) + + * 15/09/03:[-] Fixes lots of bugs in Reg Caching, now other demos work. + (GoldFinger) + + * 13/09/03:[-] Some fixes to the subq in cdvd.c (Florin) + + * 13/09/03:[-] Fixed the reg caching bug in tut1. + [*] Changed the DEFINE for reg caching for the config expert put on the CPU + screen, now we have both way to test. Thanks Expert. + (GoldFinger) + + * 13/09/03:[+] Added an option for enable regcaching or not.Now goldfinger should make + support for that!! (shadow) + + * 12/09/03:[-] Fixed the normal rec bug + [+] Added lots of new instructions for reg caching now all tutorials work + (demo 1 is strange), 3stars work also. + (GoldFinger) + + * 12/09/03:[-] Small bugfixes to Vif/VUs + (linuzappz) + + * 10/09/03:[*] More work on ipu (Florin) + + * 10/09/03:[-] New recompiler code wasn't compiling over linux, now it's ok + [-] Fixed VU memory64 writes masks + [+] Added Stats.c/h, it will create a stats.txt with some stats info, + if you define a NOSTATS in Common.h that will not be used + (linuzappz) + + * 09/09/03:[*] Improved the filter of ELF loading in GUI + [*] Register caching started to work, tutorial demo2a is working, others are coming. + [*] Commied ix86.c again with previous fix as linuz removed it. + (GoldFinger) + + * 09/09/03:[-] Fixed __int64 to u64 in Misc.c + [-] Fixed small bug in Vif.h + [-] Fixed bug in GS.c, bios is ok now + [+] Implemented INTC_STAT/MASK and DMAC_STAT for 64bits + [!] I commited the last ix86.c/h, afaik you only + reformatted it gold, please don't reformat my + code + (linuzappz) + + * 09/09/03:[-] Disabled host support for bios as it is buggy. + [*] Added/fixed SCMDs (2,3,1A) in cdvd.c (Florin) + + * 08/09/03:[+] Vif0/1 regs are now mapped to hardware + (linuzappz) + + * 08/09/03:[-] fixed bug in cpu ops debugger. Now all opcodes should appear .(For you goldfinger!) + (shadow) + + * 07/09/03:[+] Completed phase 1/2 of adding host support for bios. (Florin) + + * 06/09/03:[-] Fixed bug in rec when using ezmpeg + * 06/09/03:[*] Re-structuring the whole recompiler to make it easier for + debug and for the sake of understanding + (GoldFinger) + + * 06/09/03:[*] Many things fixed/changed in ipu files (Florin) + + * 05/09/03:[+] Hot keys for savestates in win32 + F1 -> savestate + F2 -> change the slot + F3 -> loadstate + [+] checkbox for enable the patches in cpu dialog + (shadow) + + * 05/09/03:[+] Some more VUmicro debugging + (linuzappz) + + * 05/09/03:[+] Added VDEC & BDEC; now m2v files work but ipu files do not + (Florin) + + * 05/09/03:[-] bug fixed in ifpu.h (shadow) + + * 04/09/03:[+] Added Init of Plugins before Loading of + savestates. + [-] LoadOthers in WinMain.c had a plugin init + missing fixed that. + [!] Fixed GSsoft aswell. And increased vRam size from 4*1024*1024 + to 2*4*1024*1024 as OpenGL doesn't handle wrapping around in + memory. + (asadr) + + * 04/09/03:[+] HSync stuff, and better CSR/IMR handling + [+] Few more FPU insts in ix86.c/h + [!] Please tell me if something is now screwed :) + (linuzappz) + + * 04/09/03:[-] ipu fixes to dmas and vdec (Florin) + + * 02/09/03:[-] fixed the patch system + (goldfinger) + + * 02/09/03:[*] working savestates in win32 :) + (shadow) + + * 01/09/03:[*] Working savestates for linux :) + (linuzappz) + + * 02/09/03:[-] Bug fixes in IPU.c (still hacky when returning BP) + Now ezmpeg gets to VDEC;) (Florin) + + * 01/09/03:[-] Fixed old bug in Sio.c/CdRom.c + (linuzappz) + + * 30/08/03:[+] sceCdReadSubQ <- that is a bad name; it look more like + a gettoc entry (SCMD2) (Florin) + + * 29/08/03:[+] Started the register caching implementation, not ready to test yet + some new x86 opcodes to x86.c and .h iR5900.c is completely changed + a new define for iR5900.c is used to enable reg caching. + (GoldFinger) + + * 29/08/03:[-] Removed 3DNOW code is the FPU since 3DNOW is 64bits, + and FPU is 32bits + [+] Workaround in ElfHeader.c for pukklink, so it will + load ok with Run Cd + [+] Savestates :D + [-] Maybe fixed patches, blah :P + (linuzappz) + + * 27/08/03:[+] CdGetToc + CdReadSubQ + [*] Changed PS2Edefs specs 0.4.3 / CDVD v3 + [*] Changed back the CDVDgetTD function to have a 2nd param: cdvdTD + (Florin) + + * 26/08/03:[-] Fixed patching bug in BiosInit.h that was used only for scph10000 + (Florin) + + * 26/08/03:[*] SPR address in DMAs are now masked with 0x0fffffff + (linuzappz) + + * 25/08/03:[-] Fixed patch stuff + (shadow-linuzappz) + + * 25/08/03:[-] Fixed IDEC bitstream decoding. Now, all *.ipu files + should work fine (Florin) + + * 25/08/03:[-] Fixed VIF Transfers to include MARK reg in VIF0 aswell. + (asadr) + + * 22/08/03:[*] Changed the SSE opcodes to Macro mode (thanks Linuz) and linuz added some more + (GoldFinger) + + * 22/08/03:[-] Changed DEV9 stuff to use DEV9 plugins + (linuzappz) + + * 21/08/03:[+] Added SSE instructions ADDPSRtoR, ADDPSMtoR, SUBPSRtoR, SUBPSMtoR, MULPSRtoR, + MULPSMtoR, MINPSRtoR, MINPSMtoR, MAXPSRtoR, MAXPSMtoR, SQRTPSRtoR, SQRTPSMtoR, + RSQRTPSRtoR, RSQRTPSMtoR, RCPPSRtoR, RCPPSMtoR, CVTPS2PIRtoR, CVTPS2PIMtoR, + CVTPIPS2RtoR, CVTPIPS2MtoR, CMPEQPSRtoR, CMPEQPSMtoR, CMPLTPSRtoR, + CMPLTPSMtoR, CMPLEPSRtoR, CMPLEPSMtoR to ix86.c ( need to compile and check ) :P + (GoldFinger) + + * 21/08/03:[+] Added Patch.c + (shadow-linuzappz) + + * 19/08/03:[+] Fixed bug in PsxHw.h, thanks to psycho_tr + (linuzappz) + + * 15/08/03:[+] More to SMAP + (linuzappz) + + * 14/08/03:[-] Fixed Debugger/RDebugger + [!] There is still one bug left i saw in the RDebugger, + that's the threads are not ended ok, but i'll leave + that to you florin :) + (linuzappz) + + * 12/08/03:[*] Changed the time in CDVD.c and some WIN32 defines to __WIN32__ + (Florin) + + * 08/08/03:[+] Started SMAP/DEV9 stuff + (linuzappz) + + * 06/08/03:[-] Fixed MFIFO for GS dma + (linuzappz) + + v0.41: + * 05/08/03:[-] Uncommented some sif WIP stuff :) + [*] Addeded 0x00100008 PC for cpuExecuteBios as well + [-] Fixed silly bug in CDVD.c for DvdReads + (linuzappz) + + v0.4: + * 29/07/03:[-] Fixed bug in Sif code ;) + (linuzappz) + + * 26/07/03:[-] Fixed the dma memory checking for the scratchpad, + and implemented it over the remaining dmas + (linuzappz) + + * 25/07/03:[-] GSdma now ends when a transfer is outside the memory + [-] Bugfix to Sif1 dma + [-] Some changes in the ICFG write code, and + when D5_CHCR == 0, psxSu32(0x30) = 0x40000; + (linuzappz) + + * 22/07/03:[-] Counters fixes/improvements + [*] Improvements on CdRead/DvdRead + [*] Better Sif1/0 handling + (linuzappz) + + * 22/07/03:[+] New PS2Edefs 0.4.0 :) + (linuzappz) + + * 20/07/03:[-] DvdRead was really 2064 :P + (linuzappz) + + * 19/07/03:[-] Fixed BIG stupid bug in FiFo.c that i left there:P + [!] I'm ashamed:( + [*] Fixed getBits function with back buffer;) + [!] I'm proud of that B-) (Florin) + + * 18/07/03:[-] Fixed includes for Mpeg.c/yuv2rgb.c + [-] Modified DvdRead, uses 2048 blocksize, experimental ;) + [-] CDVDgetTD had to return s32, not u32 + [*] Some reorganization for the rec + (linuzappz) + + * 18/07/03:[-] Fixed some memory allocation bug in IPU.c + [i think there are more, searching...:P] (Florin) + + * 17/07/03:[-] Fixed another Sio bug ;) + [-] Fixed MULT1/MULTU1, s64 was really s32 + [-] Commented out the interrupt delay thingy ;), was causing + troubles with Kengo 2 + [+] Implemented DvdRead + (linuzappz) + + * 17/07/03:[-] Fixed bug in FiFo.c that caused flickering between movies + [*] Fixed color conversion (Florin) + + * 16/07/03:[-] Now we can boot games though bios :) + [-] Fixed 32bits shifts in Interpreter.c + (linuzappz) + + * 16/07/03:[*] Fixed (somehow:P) IDEC so that .ipu files works a bit (Florin) + + * 15/07/03:[*] Changed cdvdLoc stuff to lsn + [-] PsxDma10 now will just return if bcr < 4 + [-] Corrections to IPU1/0 dma transfers, untested but should be fine ;) + [!] Breaks compat with current cdvd plugs + (linuzappz) + + * 15/07/03:[+] CSC + PACK ipu commands Fixes to bitstream decoding (Florin) + + * 14/07/03:[-] Really implemented MFIFO now ;P + [!] mfifo.elf works just fine now, also tekkentag reaches a bit further + (linuzappz) + + * 14/07/03:[+] Some more work on IntraDECoding for IPU (florin) + + * 14/07/03:[-] Some cleaning over Sif.c + [+] MFIFO implemented in both GS/VIF + [-] Fixes to xpadman + (linuzappz) + + * 13/07/03:[*] VUmicro code now can run in "async mode" + [-] Fixed TTE in SPR1 dma + (linuzappz) + + * 10/07/03:[-] Fixed bug in R5900.c when HLE mode was on + [-] fileio ain't crashing anymore when the file is not there + [-] Fixed interrupts on VifDma.h + (linuzappz) + + * 09/07/03:[-] Fixed bug in GS dma transfers when TTE is enabled. + Was passing wrong size of qword now it is GSgifTransfer3(ptag+2, 4) + + * 08/07/03:[*] In Win32 cdvdReadRTC gets correct time. (Florin) + + * 08/07/03:[-] Fixed stupid bug in SPR1 dma, thanks florin :) + (linuzappz) + + * 07/07/03:[-] Fixed bug in Vif UNPACK cmd, tops was *16 ;) + [*] GSgifTransfer/2 => GSgifTransfer1/2/3 (PATH1/2/3) + [*] Updated GS.c with VifDma.h asadr changes, commented the TTE + transfer by now + [*] Updated as well the SPR1 dma + [!] Note that now all vu1 demos work :D + (linuzappz) + + * 06/07/03:[+] Implemented cdvdReadKey + (linuzappz) + + * 05/07/03:[+] VCALLMS/VCALLMSR now are implemented + [*] SPU dma4 now has a delay base of 0x10000 + [-] VifDma.h is now mostly as before asadr rewrote it + last time, since that way had problems with the TTE chcr + flag, now go check the bios Browser ;) + (linuzappz) + + * 04/07/03:[-] IOP won't die now after cpuRegs.cycle overflows :), R5900.c + (linuzappz) + + * 03/07/03:[-] Fixed WriteRTC and bug in Sio.c + (linuzappz) + + * 03/07/03:[+] Some IPU commands (BCLR,FDEC,SETIQ,SETVQ,SETTH) & IPU fifo + (Florin) + + * 02/07/03:[-] Cleaned a bit VifDma.h + [*] Modified the DmaExec macros, now the Dmas take care + to interrupt and to clear the STR bit + (linuzappz) + + * 30/06/03:[*] Usb hack ;), PsxHw.c + (linuzappz) + + * 29/06/03:[*] Modified Iop DMAs for async processing, only for spu/spu2 by now + [-] Vif dma refe/end now sets the tadr to 0, tek4 loops else, but + now is crashing after ;) + [!] sven shows one screen now, and others want to ;) + (linuzappz) + + * 29/06/03:[-] Removed the experimental code i added yesterday from CDVD.c/h + [*] Improved EE/IOP Rcnts + (linuzappz) + + * 28/06/03:[*] More on iop rcnts rewrite + [+] Experimental code in CdRead, now if the lsn sector is + the same than the last one readed it will add nSectors + to it, ie. it readed 2 sectors from 0:2:16; and then + it issues another cdread with the same lsn, it will read + from 0:2:18. + (linuzappz) + + * 27/06/03:[*] Started iop rcnts rewrite, untested and more to come ;) (linuzappz) + + * 27/06/03:[-] Some fixes on iop rcnts + [+] Implemented the SPU2async func + (linuzappz) + + * 26/06/03:[-] Really fixed HLE mode ;). (linuzappz) + + * 26/06/03:[-] Small CDVD.c corrections. (linuzappz) + + * 24/06/03:[*] Fixed elf loader at least not to crash at bad elfs. (Florin) + + * 23/06/03:[*] Added "rom1.bin" as a valid file for rom1 filesystem. (Florin) + + * 23/06/03:[-] Small fix to CDVD.c, maybe fixed a time out problem + with some cdvdman versions. + (linuzappz) + + * 20/06/03:[+] Some mcds work, PsxSio2.c, Sio.c + (linuzappz) + + * 17/06/03:[+] SPU dmas now call the correct funcs, PsxDma.c + (linuzappz) + + * 17/06/03:[-] Fixed Sio2, PADs are working :D, Sio.c, PsxSio2.c + [-] Fixed language in CDVD.c, now's english again :) + (linuzappz) + + * 16/06/03:[-] Better error handling over CDVD.c + [+] ROM1 stuff, Memory.c/h, PsxMem.c, iR3000A.c, iR5900.c + [!] PCSX2 now detects the rom1 in this way: ie. + you use scph10000.bin, then you must have + in the same dir scph10000.bin.rom1 or scph10000.rom1 + (linuzappz) + + * 16/06/03:[-] Rewrote the VIFtransfer and VIFdma again. Better speed and + compatibility this time (asadr). + + * 16/06/03:[*] Reoverwritten CDVD.c/h with my CDVD.c/h, + this is simpler, more direct and faster, + CdRom.c, PsxHw.c, R3000A.c, PsxCounters.c, + Memory.c + [-] Kinda workaround i think in the ICFG reg + (1450), PsxHw.c + [-] Removed VSyncHack at least ;), WinMain.c, + Common.h, ini.c + [!] Games start showing something :D:D + (linuzappz) + + * 15/06/03:[+] More dummy cdvd scmd (Florin) + + * 14/06/03:[-] Fixed SIF0 transfers, PsxDma.c, PsxHw.c/h. + [*] Cleaned up SIF1, R3000A.c, Sif.c + [+] Added a Run CD menuitem, WinMain.c, resource.h + [!] Bios shows something :D:D + (linuzappz) + + * 12/06/03:[-] Fixed bug in release version (unsafe compiler optimizations:P) + (Florin) + + * 11/06/03:[+] More functions on lle cdrom (cdread) (Florin) + + * 10/06/03:[+] Rudely overwritten linuzappz work in CDVD.c/.h + [!] Sorry man, i think i did the best...i created a framework + with names and so on. Also we have to talk about;) (Florin) + + * 10/06/03:[+] Started CDVD.c/h, moved old CDVD.h to CDVDlib.h, + PsxMem.c, PsxCommon.h (linuzappz) + + * 10/06/03:[*] Added new SPU2 dma functions plugin.c + [*] New PS2 plugins specifications 0.3.2 (shadow) + + * 09/06/03:[+] Add SPU2read/SPU2write to PsxMem.c + [-] Few fixes to PsxCounters.c + [+] Added PsxDma7, PsxHw.c, PsxDma.c (linuzappz) + + * 09/06/03:[-] Sif0 chaining fix (Florin) + + * 08/06/03:[+] Started with SIO2... (Florin) + + * 07/06/03:[-] Fixes to SIF0/SIF1 :D + [!] Now OSDSYS loads ok, and so does several modules in iop, + bios now gets stuck in a Deci2Call (reqsend) + (linuzappz) + + * 07/06/03:[-] Fixes0, Fixes1 (Florin;) + + * 06/06/03:[*] Fixed and improved the VIF Dma transfers and rewrote the VIF_Transfer. It's far + more compatible and fast ( all vu1 demos work:D ). (asadr) + + * 06/06/03:[*] Fixed sif1 (...waiting for a better solution;) (Florin) + + * 05/06/03:[-] Sif1 flags fixes (still buggy?) (Florin) + + * 04/06/03:[*] Some adjustments to PsxInterpreter.c (Florin) + + * 03/06/03:[-] Set the PSXCLK to 36.864 Mhz, by now, later PSXCLK should be + a variable, Common.h + [*] Improved iop hw maps, added DMA9/10, PsxDma.c/h, R3000A.c, PsxMem.c + [+] Added RCNT3/4/5 in PsxCounters.c/h, PsxBios.c, PsxHw.c/h + [+] Added a bit more of loggin in PsxInterpreter.c + [-] 0xba000006 now returns 1, for some bioses, Memory.c + [*] Improved dmaSIF1, SIF.c, and cleaned dmaSPR1, SPR.c + [!] Finally my name is on the v0.4 :P + (linuzappz) + + * 03/06/03:[-] Fixed GetPS2ElfName in Misc.c (Florin) + + * 22/05/03:[+] new flags code based in nsx2 flag code. vuflags.c vuflags.h + [*] vuops.h rewrote almost all the vu opcodes with new flags code Upper Instructions + should be okay but might still are some issues with the Lower instructions. + [-] added proper reset in vu1micro.c + [*] added the new vcnet files for compile properly with vuflags + (shadow) + + * 21/05/03:[-] Fully fixed of recSQ in iR5900.c. + [-] Fixed EMMS_TRACING on none 3DNOW machines, EMMS_TRACING now turned on again. + [*] Added CPU autodetection to iR5900.c + [!] #define CPU_3DNOW is not used now. + (Alexey Silinov) + + * 20/05/03:[-] Dummy fix of recSQ in iR5900.c. Recompiler back to work again. + (Alexey Silinov) + + * 10/05/03:[*] Improved fpu.c, just code optimizing in cvt_s, cvt_w, all branches opcodes and + some code organizing. + (GoldFinger) + + * 02/05/03:[+] Added some ioprps to Misc.c (Florin) + + * 02/05/03:[+] Some more work on Padman module 800100Xpadman.c , 800100Xpadman.h (shadow) + + * 30/04/03:[+] Added 2 more syscalls in BiosSysc.h (Florin) + + * 29/04/03:[+] More threads functions. (see threads.txt) + [!] To see threads switching, comment the 3 instructions + at the top of _ThreadHandler function (Bios.c) + (Florin) + + v0.3: + * 01/05/03:[-] Fixed dvd iso issue (roundup of numsectors ...+2047/2048) + in CDVDiso.c (Florin) + + * 30/04/03:[-] Fixed bug in CFC1, Fpu.c + [-] Fixed branches isns on VUops.h, US was instead of SS + [-] Added newline at oef for MMI.c, *mtapman.c + [-] Included in *loadfile.c + [*] Few changes over languages, Misc.c/h, WinMain.c + (linuzappz) + + * 29/04/03:[-] Added a workaround for the interrupt latency in the rec, + R5900.c + (linuzappz) + + * 28/04/03:[-] Fixed a bug in BiosInit.h, instead of 16 dmas there was 15 + [-] Counters 0,1,2 had interruption disabled, Counters.c + (linuzappz) + + * 27/04/03 [-] WinMain.c now only calls GetPS2Elf if on HLE mode + [-] parseCommandLine had a bug when not using HLE, ElfHeader.c + [*] Implemented memRead/Write128, Memory.c/h, iR5900.c + [*] Implemented a better way to count opcodes in iR5900.c + [*] Rewrote AddIntc/DmacHandler, RemoveIntc/DmacHandler, Bios* + (linuzappz) + + * 24/04/03:[*] More threads functions. (see threads.txt) (Florin) + + + * 23/04/03 [-] Undo the "VU0/1 control/integer regs are now the same" update, + VU*, DebugReg.c, (goldfinger-linuzappz) + [+] Implemented latency interrupt thingy ;), R5900.c/h + (linuzappz) + + * 21/04/03 [-] DMAC interrupt wasn't setting the cause in a0, Bios.c + [+] DMACTable is now being used with DefaultDmacHandler, Bios.c/h, + BiosInit.h, HLE.c + [+] Added dummy handles for mtapman901/3, Rpc_services.h, *mtapman* + [*] VIF0 code is now shared with VIF1 code, Vif.c, VifDma.h + (linuzappz) + + * 23/04/03:[*] Fixed RFU061_InitHeap, EndOfHeap, CreateThread, InitThreads + (Florin) + + * 21/04/03:[+] Started threads update (Bios.c/BiosInit.h/BiosSync.h/ + deci2_dbgp.c/ElfHeader.c/.h) (Florin) + [-] Fixed fifos a bit:) (FiFo.c/Hw.h) (Florin) + [*] Fixed VIF1 regs display in Hw.c. I know that those were handeled + but now is more clear (Asad-Florin) + + * 20/04/03:[-] Fixed a bug in WinMain.c. In case of the debuggers with HLE bios, + cpuExecuteBios() was not called, so the tlbs and all stuff + were not inited properly. (Florin) + + * 20/04/03:[-] Fixed a bug in VUmicro.h + [+] VIF1dma now handles 'from Memory' transfers, Vif.c + [-] F11 now un/sets Log, F12 un/sets symbol logging, WinMain.c + (linuzappz) + + * 19/04/03:[-] Fixed a bug in Interpreter.c + [-] VU0/1 control/integer regs are now the same, VU*, DebugReg.c + [*] Cleaned a bit GS.c + (linuzappz) + + * 17/04/03:[-] gsRead32 wasn't calling GSread32, lol :), GS.c + [+] Implemented more syscalls, as dummy for now, Bios.c/h, BiosSysc.h, + HLE.c + [*] Removed the CSR revision/intelace bits over GS.c + [+] Added GSirqCallback to PS2Edefs.h, GS.c, Plugins.c + [+] VIF1 cmd now handles the i bit, still not 100% correct, Vif.c + [-] Fixed several VIF1 bugs, Vif.c + (linuzappz) + + * 16/04/03:[*] biosInit is now called at hle_bootstrap, Bios.c, HLE.c, WinMain.c + [+] Added _TlbInit at biosInit, Bios.c + [*] Deci2Call is now better coded, Bios.c, BiosSysc.h + [-] Fixed some bugs over AddIntcHandler/AddDmacHandler, BiosSysc.h + [+] bios_SetSYSCALL is now implemented, BiosSysc.h + (linuzappz) + + * 17/04/03:[+] Breakpoint support for debugging bios. (Florin) + + * 16/04/03:[-] Readded an update that linuzappz missed in his src, + that was then used by many pcsx2 team members. [it is about my 16/03/2003's] + [+] sceCdReadIOPm in 80000595.c + (Florin) + + * 14/04/03:[*] Memory access bug in deci2 that made pcsx2 to crash. hi linuzappz + [+] MC functions fixes/dummies over 80000400mcserv.c + (Florin) + + * 12/04/03:[*] CP0Count now adds 2 every opcode, instead of 4 + (linuzappz) + + * 12/04/03:[-] Bios VSyncSetFlag is now fixed ok, Bios.c + [*] Started to implement new Bios code, Bios.c/h, BiosInit.h + BiosSysc.h, EEregs.h, HLE.c, R5900.c/h + [!] Please tell me if this update creates some incompatibility, + or something else works now, since the INTC/Exceptions code is + much better now :). + (linuzappz) + + * 08/04/03:[-] DMAC_STAT CIS? bits are now set after a DmaExec, Hw.c + [-] Fixed bug when a plugin returned -1, WinMain.c + [*] Cleaned a bit GSdma, GS.c + [-] Fixed bug in INTC interrupts, Bios.c + (linuzappz) + + * 07/04/03:[+] Added cpu opcodes debugger. Use the CPU ops button in the debugger + and it will create a cpuops.txt with the opcodes that used. + Debugger.c pcsx2.rc, cpuopdebug.c cpuopdebug.h . Now works only in + interpreter. (shadow) + + * 04/04/03:[+] Added LabelGreets/LabelAuthors to Misc.c/h, AboutDlg.c + [*] Languages code over pcsx2 is a bit better, WinMain.c + [+] Added Log to STDOUT over Logging dialog, pcsx2.rc, + Misc.c, resource.h + [+] Now we're emulating the VSync Start and the VSync End, Counters.c + (linuzappz) + + * 26/03/03:[*] Optimized PLZCW in mmi.c (GoldFinger) + [-] fixed MADD1 and MADDU1 in mmi.c (GoldFinger) + [-] PSLLH, PSRLH and PSRAH (sa needed to be the first 4 bits only), + mmi.c (GoldFinger) + [-] PADDSW, the manual seems to be wrong (well it is) so I tryed + to fix it, mmi.c (GoldFinger) + [-] PADDSB, PSUBSB, the comparision was wrong, mmi.c (GoldFinger) + [-] PADDSW, PSUBSW, PADDSH, PSUBSH, PADDSB, PSUBSB, PADDUW, PSUBUW, PADDUH, + PSUBUH, PADDUB, PSUBUB, the sum and sub need a conversion to the higher + value(s16,s32 and s64), mmi.c (GoldFinger) + [-] PMINH, the comparision needs to be signed, mmi.c (GoldFinger) + [-] PHMSBH, was wrong, fixed, mmi.c (GoldFinger) + [-] PEXEH, PREVH, was using _Rs_ when only _Rt_ should be, mmi.c (GoldFinger) + + * 26/03/03:[*] fixed fpu bugs. Hi linuzappz :) . Tmip is correct in interpreter mode finally + fpu.c (shadow) + + * 24/03/03:[+] Fixed Trap instructions, hi shadow :), also cleaned + up a bit the Interpreter.c (linuzappz) + + * 22/03/03:[+] Fixed the 'Load ELF File' issue, added the Memory Dump menu, + WinMain.c (Florin-linuzappz) + [!] I forgot the changelog entry in the last update, + please read it (linuzappz) + [!] I've updated again the pcsx2.po, florin sent one without the + linux port messages since i've never updated u the linux port ;) + + * 20/03/03:[+] Added GSsetWindowInfo, WinMain.c, PS2Edefs.h, Plugins.c + [+] Added MiltuLingual support, using gettext, WinMain.c, Plugins.c, + AboutDlg.c, ConfigDlg.c, pcsx2.rc, Memory.c, iR5900.c, iR3000A.c, + pcsx2.dsp, Sio.c, R5900.c, PsxMem.c, Hw.c, Common.h, ini.c, + resource.h, Win32.h + [-] Fixed IPU.c when IPU_LOG is not defined + [-] Fixed padman/loadfile.c when RPC_LOG is not defined + [*] Removed dummy memory area, Memory.c/h, PsxMem.c/h + (linuzappz) + + * 17/03/03:[*] add some more stuff to DisR5900asm.c . win debugger is better now (shadow) + [-] fix a bug in rec table (visubiu not exist) in macromode .. recCop2.c (shadow) + [!] recheck vu micromode tables. Hmm they seem correct (shadow) + + * 16/03/03:[+] Added "next" (aka "step over") support for deci2 debugging + [+] Added TTYP support (log redirection) (buggy;have to test more) + (Florin) + + * 15/03/03:[*] move loadfile to rpc using florins protocol hi florin;p (shadow) + + * 15/03/03:[*] Fixes to breakpoints in deci2 stuff (Florin) + + * 13/03/03:[+] More deci2 dbgp stuff (BREAK/CONTINUE/RUN) + [!] It is not fully tested. This is EXPERIMENTAL code. + [!] It may contain many bugs and there are also "known issues". + [*] changed names of shadow's padman files and made the according + changes to rpc_services.h & bios.c (Florin) + + * 12/03/03:[*] rewrote padman+xpadman according to florins protocol on RPC folder + [*] removed code from bios.c according to pad handling.. + [+] Add fix that make analog mode to work partially ;) (try turnip) (shadow) + + * 10/03/03:[+] Added more mem mappings to PsxMem.c & Memory.c in order + not to crash the emu when read from a not-covered area (Florin) + + * 10/03/03:[-] fix small bug in winmain that didn't let console to close winmain.c (shadow) + + * 04/03/03:[+] Added remaining UNPAKs and cleaned a bit, Vif.c/h (linuzappz) + + * 03/03/03:[*] replace console writes of IPU with IPU_LOG Ipu.c (Shadow) + + * 01/03/03:[-] Fixed partially FIFO bug; (unlogged change:P) + [!] I haven't fixed it all because is very messed up. + [+] Added a small fix to PsxMem.c in order to allow sifman to stay resident. + (Florin) + + * 28/02/03:[+] Added support for remote debugging with tcp/ip deci2 protocol. + [!] Not finished nor fully tested + [!] There's an issue on Win98 with winsock2 closing [have 2 check that] + [!] New src dir (rdebug\*.*), Win32\RDebugger.c/.h; + [!] also added ws2_32.lib to link libraries + (Florin) + + * 25/02/03:[+] Added 8bit DMAs to Hw.c + [+] More UNPACK cases to Vif.c (linuzappz) + + * 23/02/03:[+] Added BC0s in COP0.c + [!] the BC0s are still fake, but they should be ok ;) (linuzappz) + + * 22/02/03:[*] Now if the Recompiler fails to initialize it'll switch to interpreter (linuzappz) + + v0.2: + * 18/02/03:[-] Small fix in winmain.c in SysInit() causing a crash (shadow) + + * 12/02/03:[+] Added new DMA transfer codes to VIF.c, GS.c + [+] Added the new clipping code to the VU + [*] Fixed most of the VU ops. Better compatibility + [!] The new dma transfer code is 4-5% faster than the last one. :) + + * 12/02/03:[*] Fixed iR5900.c to include iR5900.h, moved some stuff from + ix86.h to iR5900.h + [-] Fixed CPU_LOG flags over iR5900.c/recCOP2.c + [+] Added some SysPrintfs over iR5900.c after x86Init + (linuzappz) + + * 26/01/03:[+] Added some defines in Hw.h (linuzappz) + + * 26/01/03:[-] Fixed include in IPU.c, 'common.h' for 'Common.h', + SJdata.c, 'rpc/...' '...' (linuzappz) + + * 04/02/03:[+] ix86.c: Added CPUID for linux. + SSE is autodetected now (linuzappz) + + * 28/01/03:[+] ix86.c: CPUID added. It will work if u don't change CPU on the FLY. :) + [*] ir5900.c: recompiler changed for CPUID. + [*] recCOP2.c: recompiler changed for CPUID. + (Alexey Silinov) + + * 27/01/03:[+] ir5900.c: recompile of DSRAV,PMINW,PMAXW added. + [!] I'am not sure in this code.Need find demos that use it. + [+] ix86.c: PANDNRtoR,PANDMRtoR added. + (Alexey Silinov) + + * 25/01/03:[-] ir5900.c: Some fpu opcodes for non 3DNOW version fixed with EMMS_TRACE on. + After Linuzappz request:memory opcodes + [-] (LB,LBU,LH,LHU,LW,LWU,.....,SB,SH,SW,...) fixed for version with EMMS_TRACE on. + [-] recCOP2.c: Bugfixed for non 3DNOW version(added another recCOP2SPECIAL1t,recCOP2SPECIAL2t tables). + + [!] Now EMMS_TRACE will work much better. + (Alexey Silinov) + + * 24/01/03:[+] ir5900.c: DSRA,DSRA32 recompilation added. + [*] shifts by _Imm_=0,_Rs_=0 optimized. + [+] PMFHI,PMFLO,PAND,PXOR,PMTHI,PMTLO,POR,PAND now can recompiled to SSE instructions. + [-] JUMPS bugfixed by putting SET_FPUSTATE before it, + because cpuBranchTest use FPU. Pillgen now ok with EMMS_TRACE. + [!] #define CPU_SSE in ix86.h if you have Pentium3/4 or Duron7/AthlonXP. + (Alexey Silinov) + + * 24/01/03: Fixed iR5900.c to compile without 3DNOW (linuzappz) + + * 24/01/03: Moved the emms's in Hw.c, GS.c, Memory.c to iR5900.c (linuzappz) + + * 24/01/03: Rewrote ini.c, same code as Pcsx now :) (linuzappz) + + * 24/01/03: Removed the browse info option over pcsx2.dsp (linuzappz) + + * 24/01/03: Some fixes in Hw.c, missings #ifdef HW_LOG/#endif, + reordered the ipu address and the IPU1 dma was wrong. (linuzappz) + + * 21/01/03: remove the fpu flags reorganize fpu.c a bit. Send code for using it + as reference to all the pcsx2 members. + + * 21/01/03:recCOP2.c + 75% of COP2 ops recompiled used 3DNOW. + only sign MAC flags updated. + Zero,Sticky will be done later. + (Alexey Silinov) + * 19/01/03: + ir5900.c: + Fixed recompiling of RSQRT_S for3DNOW,recPCPYUD(tskin.elf now ok), + recC_LE for x87 FPU(untitled.elf last part now ok). + Optimizing recompile of recADDI,recADDIU,recDADDI,recDADDIU, + recANDI,recORI,recXORI,... (check _Rs_,_Rt_= =0,!=0). + Optimiing recMOVZ,recMOVN only one JMP CC,.. needed. + Added #define EMMS_TRACE to. + Added #define ARITHMETICIMM_RECOMPILE,ARITHMETIC_RECOMPILE,etc. + (Alexey Silinov) + * 18/01/03: ir5900.c:Many recompiler opcodes fixed. + IPU DMA logging update. + (Alexey Silinov) + + * 18/01/03: Fixed fileio_lseek function in 80000001fileio.c. (Florin) + + * 16/01/03: Rewrite fpu and added two version of it. One with flags and + one without. The no flags version is much faster. + fpu.c ,r5900.h,common.h,r5900.c,ini, resources , winmain.c (shadow) + + * 15/01/03: Added memory mapping of IPU_CMD,IPU_CTRL,IPU_TOP,IPU_BP. + Added parsing of IPU commands. + (Alexey Silinov) + * 14/01/03: recMAX_S,recMIN_S,recC_F,recC_EQ,recC_LE,recC_LT-added. + recABS_S,recNEG_S-now don't use FPU. + ix86.c - 3DNOW opcodes added. + #ifdef CPU_3DNOW then FPU recompiled using 3DNOW instruction set. + Now we are ready TODO FPU register cache on CPU_3DNOW. + gs.c add emms before GS read,write. + (Alexey Silinov) + + * 14/01/03: Fixed stupid bug in 80000001fileio.c (Florin) + + * 13/01/03: Fixed some issues in CDVDiso.c & 80000597cdvdfsv.c (Florin) + + * 11/01/03: Fixed fileio [important] functions up to ioprp255 (Florin) + + * 11/01/03 some more MMI opcodes in rec (alexey silinov) + + * 10/01/03 recPADDUB-changed,recPADDUH-added (Alexey Silinov) + + + * 09/01/03 + My copy&paste bugs in recPCPYUD,recPAND,recPXOR fixed. + Now EMMS() instruction writing only before FPU commands if FPU state is MMX.With it size of recompiled code is reduced. + !!Added macros SET_FPUSTATE,SET_MMXSTATE it's must before MMX or FPU instruction. + Fixed many ops.ExtSign32to64() don't used anymore. it's faster and smaller to do CDQ(). + recLUI,recPCPYLD optimized. + Added recompilation of PMAXH,PMINH,PCGTB,PCGTH,PCGTW,PCEQB,PCEQH,PCEQW,PEXTLW,PEXTUW. + ir5900.c,ix86.c, ix86.h + (Alexey Silinov) + + + * 07/01/03: Fixed MADD, MADDA, MSUB, MSUBA opcodes in FPU.c ( asadr ) + + * 07/01/03: added MTSAB,MTSAH in interpreter.c (asadr) + + * 07/01/03: Added Flags in FPU.c, fixed SQRT, DIV, RSQRT opcodes in FPU.c ( asadr ) + + * 07/01/03: add some opcodes in interpreter.c (shadow) + + * 07/01/03: small fix in mult1,multu1 in MMI.c (shadow) + + * 07/01/03: more addes in recompiler iR5900.c (Alexey Silinov) + + * 07/01/03: fixed MULT,MULTU,MULT1,MULTU1 in rec and added DIV1,DIVU1 iR5900.c + (Alexey Silinov) + + * 07/01/03: add several MMI opcodes to recompiler iR5900.c ix86.c ix86.h + (Alexey Silinov) + + * 07/01/03: Fixed libpad version issues; added scePadInit2 support in Bios.c (Florin) + + * 06/01/03: Added sceDvdRead function to 80000595cdvdfsv.c, CDVDiso.h/.c + Moved sifcall_cdvdfsvA from Bios.c to 80000592cdvdfsv.c (Florin) + + * 05/01/03: Fixed libmc version 80000400mcserv.c + Added support for cdrom device in LoadHeap function 80000003sysmem.c (Florin) + + * 05/01/03: Added D and I Flag checking in vuDiv and SQRT opcodes and some more fixes ( asadr ) + + * 05/01/03: Merge all the vu code fixes to the better possible one vuops.h (shadow) + + * 05/01/03: Several vu fixes vuops.h (Alexey Silinov) + + * 04/01/03: Added temporary fix to vuDIV, vuRSQRT, vuERSADD, vuERCPR, ERSQRT ( asadr ) + + * 04/01/03: Added vuERCPRL, vuESUM , vuEATANxz, vuESIN, vuEATAN, vuEEXP, vuRXOR ( asadr ) + + * 04/01/03: Fixed GetPS2ElfName Misc.c + Romanian version pcsx2ro.rc & spell fixes in pcsx2.rc (Florin) + + * 03/01/03: Added callback support in Bios.c + Added function name display support (if you know other places, plz add...) + (Florin) + + * 02/01/03: Fixed sceCdRead (cdvdfsv1.4 and more?) 80000595cdvdfsv.c (Florin) + sceCdSeek, sceCdPause, sceCdStop, sceCdStatus + + * 02/01/03: Added SLTI,SLTIU,SLT,SLTU iR5900.c ( Alexey Silinov) + + * 02/01/03: Added SETS8R ix86.c ix86.h ( Alexey Silinov) + + * 01/01/03: YAH HAPPY NEW YEAR :) + + * 30/12/02: Added Dump memory button in Debug dialog over Debugger.c (Florin) + + * 29/12/02: Start work on Savestates Common.h, Misc.c. Need to include zlib.lib in project (shadow) + + * 29/12/02: Fix small bug In ERET. COP0.c (shadow) + + * 29/12/02: Some more Vu opcodes in the vuops.h (shadow) + + * 29/12/02: Added BC2F,BC2T,BC2TL,BC2FL not sure if i check the right bit althought Vu0.c (shadow) + + * 29/12/02: Added HLE opcode over DisR5900.c (linuzappz) + + * 29/12/02: Fixed some bugs on rec mode, Memory.c, PsxMem.c, + ix86.c/h, iR3000A.c, iR5900.c (linuzappz) + + * 29/12/02: Fixed JALR in Interpreter.c (linuzappz) + + * 28/12/02: Fixed stupid old bug in iR5900.c (linuzappz) + + * 26/12/02: Added compiler detection code (Win32/WinMain.c) (Florin) + + * 20/12/02: Refixed new Threads code, a bit hacky still ;), Bios.c/h, HLE.c (linuzappz) + + * 20/12/02: Refixed Counters.c, GS.c (linuzappz) + + * 20/12/02: Changed some cop0 names over DisR5900.c (linuzappz) + + * 20/12/02: Fixed EXL bit on cpuException, R5900.c (linuzappz) + + * 20/12/02: Fixed ERET, COP0.c, Interpreter.c, R5900.h (linuzappz) + + * 19/12/02: fix bugs in fileio system 80000001fileio.c (florin) + + * 19/12/02: rewrite MMI mmi.c (linuzappz) + + v0.1: + * 17/12/02: Small cleaning for release (linuzappz) + + * 17/12/02: Fixed a comment in CDVD.h (linuzappz) + + v0.046: + * 17/12/02: FIXED THAT BASTARD BUG with interpreter + R5900.c (shadow) + + * 16/12/02: Fixed CDVDFS_read function (CDVDisodrv.c). (Florin) + + * 07/12/02: Added support for SjDATA filesystem (SJdata.c/.h). + Small fixes in 80000003sysmem code. + Moved OpenPlugins call from debugger.c to WinMain.c + Added support for 0B001337cdvd rpc driver. (Florin) + + * 06/12/02: Fixed RPCVER for games that load ioprp.img. + Moved related code Bios.c to Misc.c. (Florin) + + * 05/12/02: Placed a guard in CDVDFS_init/CDVDisodrv.c + Added support for reading from cdvd in Elfheader.c/.h + Implemented RunCD option WinMain.c, GtkGui.c, Misc.c/.h (Florin) + + * 01/12/02: Made fileio_open more compatible with games (up to 2.0F/ioprp255) (Florin) + + * 30/11/02: Add test opcodes TGE,TGEU,TLT,TLTU,TEQ,TNE Intepreter.c (shadow) + + * 30/11/02: Add exceptions defines in R5900.h (shadow) + + * 01/12/02: Removed old VU0 code over VU0.c (linuzappz) + + * 31/11/02: Implemented CheckCdrom/LoadCdrom, still unfinished, Misc.c (linuzappz) + + v0.045: + * 31/11/02: Changed memRead32 for PSMu32 over Interpreter.c (linuzappz) + + * 31/11/02: Fixed CdRead, CDVDiso.c (linuzappz) + +// * 30/11/02: Added irqs for rcnt2/3, started thread HLE code rewrite, +// Bios.c, Counters.c (linuzappz) + + * 28/11/02: Fixed win32 fileio path, and some more small issues (linuzappz) + + * 27/11/02: Added BD0000X0 connection to 1000F0X0 and BC000000 ee memmap, + implemented direct rec clears, and added some more counters stuff, PsxMem.c/h, + Memory.c/h, iR3000A.c, iR5900.c, Counters.c/h, Hw.c, PsxHw.c (linuzappz) + + v0.044: + * 26/11/02: Added RPC handler for 80000595cdvdfsv + Fixes in iso handling system (read function can read more than 16KB) + Fixed issue with deci2call no.3 (junk re-printing) (Florin) + * 20/11/02: Automatic setting of RPCVER + (problems: 1. SDK samples do not load an ioprp; default is "2000";) + 2. starwars game load a ioprp.img; so RPCVER="0000") + Fixed bug in CDVDiso.c/CdRead(); check for null pointer + Fixed issue with the Joliet filesystem (Florin) + * 09/11/02: Added iso parsing & filesystem driver from libcdvd library by Hiryu & Sjeep + Added credits (Hiryu&Sjeep) to Aboutbox & Readme.txt + Changed the order of opening of plugins in Plugins.c/OpenPlugins() + Added (or moved code from bios.c) to handle RPC user & standard code + -works (or should work; needs intensive testing): + 014D704Enaplink, 80000001fileio, + 80000003sysmem, 80000592cdvdfsv, + 80000597cdvdfsv + -dummy (to be implemented; only params display): + 0B0110C5sjpcm, 0badca11amigamod(shadow), + 80000400mcserv,80000596cdvdfsv, + 80000601osdsnd + Added RPC_LOG logging stuff to debug.h, pcsx2.rc & resource.h + Added kputs handling for scePrintf in Deci2Call syscall in bios.c + (Florin) + + v0.043: + * 06/11/02: add some work for amigamod.irx HLE based on Florin + RPC code (shadow) + + * 21/10/02: implement some more opcodes for VU + flags in many opcodes + (shadow) + + * 19/10/02: Added more opcodes to VUops.h (from VU0.c), and started the implementation of flags, + VUflags.h, VU* (shadow-linuzappz) + * 12/10/02: Added fix for several bioses, Hw.c, removed hack for 30002R.bin R5900.c (linuzappz) + + * 06/10/02: Added 0xb2000000 map area as a 0x12000000 mirror, Memory.c (linuzappz) + + * 06/10/02: Added/Fixed some VIF1 unpack cases, Vif.c (linuzappz) + + * 06/10/02: Started Rewrite of SetGsCrt, Bios.c (linuzappz) + + * 05/10/02: Improved gsReads/Writes GS.c (linuzappz) + + * 28/09/02: Added iop HLE code for exceptions in PsxBios.c (linuzappz) + + * 24/09/02: Added ps2 bios check for config dialog in ConfigDlg.c/GtkGui.c (Florin) + + * 23/09/02: Added command line parsing for main's argc, argv in ElfHeader.c (Florin) + + * 14/09/02: Fixed small issue in PsxBios2.c/h, Bios.c (linuzappz) + + * 13/09/02: Fixed bug in Bios.c for sif_call (linuzappz) + + v0.042: + * 25/08/02: Fixed VU SQRT/RSQRT, also added ERSQRT, VUops.h (linuzappz) + + * 24/08/02: Added several stuff for IOP hle (linuzappz) + + * 09/08/02: Added: PADDSW, PSUBSW, PPACW, PADDSH, PSUBSH, PEXTLH, PPACH, PADDSB, PSUBSB, + PPACB, PEXT5, PPAC5, PABSW, PCEQW, PMINW, PADSBH, PABSH, PCEQH, PMINH, + PCEQB, PSUBUW, PADDUH, PSUBUH, PSUBUB, PEXTUB, QFSRV, PSLLVW, PSRLVW, + PINTH, PROT3W, PSRAVW, PEXCW, PEXCH, PINTEH, PMTHI, PMTLO, PEXEW, + PREVH, PEXEH, in MMI.c (GoldFinger) + + * 09/08/02: Changed: PADDUB to conform to defines (GoldFinger) + + v0.041: + * 11/08/02: More to VUops.h (shadow) + + * 10/08/02: Rewrote L/R Stores/Loads (linuzappz) + + * 05/08/02: Add some more opcodes to VUops.h some demos works again(shadow) + + * 04/08/02: Added VUops.h, VU0.c/h, still uncomplete (linuzappz) + + * 04/08/02: Added GSgifTransfer2 for PATH1, VU1micro.c, PS2Edefs.h, Plugins.c (linuzappz) + + * 03/08/02: Added unpack v4-32, Vif.c (linuzappz) + + * 02/08/02: Rewrote partially VUmicrocode, structures and stuff, VU1/0micro.c, VUmicro.h (linuzappz) + + * 02/08/02: Small change on Misc.c (linuzappz) + + * 01/08/02: cpuExecuteBios is now called before the LoadElf, WinMain.c (linuzappz) + + * 01/08/02: Added a couple of HW_LOGS in Hw.c (linuzappz) + + * 01/08/02: Fixed MFC2/CFC2 in DisR3000A.c (linuzappz) + + * 01/08/02: Added small hack on R3000A.c (linuzappz) + + * 01/08/02: Fixed bug in StartThread Bios.c (linuzappz) + + v0.040: + * 31/07/02: Small change in PsxInterpreter.c and PsxHw.c (linuzappz) + + * 31/07/02: Added CDVDgetTN and CDVDgetTD, PS2Edefs.h, Plugins.c, CdRom.c/h (linuzappz) + + * 30/07/02: Fixed Gte.c, now includes PsxCommon.h (linuzappz) + + * 30/07/02: Added GPU_LOG to Debug.h (linuzappz) + + * 30/07/02: IOP now has vsyncs, PsxCounters.c/h (linuzappz) + + * 30/07/02: Added PsxGPU.c/h, moved the GPU_xx stuff from PsxBios.c, PsxDma.c (linuzappz) + + * 24/07/02: Added psxSIF1transfer to R3000A.c,, Sif.c, still not working (linuzappz) + + * 24/07/02: Added a couple of address more to PsxHw.c (linuzappz) + + * 24/07/02: Added zeroEx func to trace writes to stdout, PsxInterpreter.c (linuzappz) + + * 24/07/02: Improved bios_write, PsxBios.c (linuzappz) + + * 24/07/02: PsxMem.c now handles the full 4mb of the bios mem (linuzappz) + + * 24/07/02: Hack for 30002R bios, R5900.c (linuzappz) + + * 24/07/02: Fixed BNEL, BEQL in disR5900.c (linuzappz) + + * 22/07/02: Remove biosCall, now use only biosException, Bios.c/h, Interpreter.c, + R5900.c (linuzappz) + + * 21/07/02: Intialaze of VU1 vu1microc,vumicro.h,R5900.c (shadow) + + * 21/07/02: implement VIF0transfer same way as VIF1transfer vif.c (shadow) + + * 20/07/02: Add debug logs in vu0,vu1 micromode + vu0 execute vu0micro.c, + vu1micro.c,vumicro.h (shadow) + + * 18/07/02: Clean up vu0 macromode vu0.c (shadow) + + * 19/07/02: PsxMem.c now handles 0xbf80xxxx hw addresses (linuzappz) + + * 17/07/02: IOP PRid is 0x1f (not 0x2), R3000A.c (linuzappz) + + * 17/07/02: More to VU1micro.c (shadow) + + * 14/07/02: Added psxMemRLUT/psxMemWLUT instead of only psxMemLUT, PsxMem.c/h (linuzappz) + + * 11/07/02: Added MADD1, MADDU1, PMFHL, PCGTW, PMAXW, PADDH, PSUBH, PCGTH, + PMAXH, PADDB, PCGTB, MMI.c (goldfinger) + + v0.039: + * 08/07/02: Commented the 0xe000 hw dma test, for jasper, Hw.c (linuzappz) + + * 08/07/02: Changed PADreadStatus for PADstartPoll/PADpoll, Plugins.c, PS2Edefs.h, Bios.c, + PsxBios.c, Sio.c (linuzappz) + + * 07/07/02: More to Vif1 dma and added vu1ExecMicro, Vif.c, VU1micro.c/h (linuzappz) + + * 06/07/02: Rewritten/updated iop code, CdRom.c/h, Common.h, Iop*, Psx*, Debug.h, + Decode_XA.c/h, DisR3000A.c, ElfHeader.c, Gte.c/h, Mdec.c/h, R3000A.c, + R5900.c/h, Sio.c/h, iR3000A.c, Bios.c, pcsx2.dsp (linuzappz) + + * 05/07/02: Added CDVDreadTrack/getBuffer and now we're using CDVD plugin, PS2Edefs.h, + Plugins.c, ConfigDlg.c, ini.c pcsx2.rc (linuzappz) + + * 05/07/02: Optimized recANDI and completed the mmi rec tables, iR5900.c,ix86.c/h (linuzappz) + + * 06/07/02: Add VU opcodes tables vu1micro.c,vu0micro.c,vumicro.h (shadow) + + * 03/07/02: Added MADDU, PMTHL, PLZCW, PSLLH, PSRLH, PSRAH, PSLLW, PSRLW, PSRAW in MMI.c(goldfinger) + + * 03/07/02: Small change in MULT1, MULTU1 for speed, MMI.c(goldfinger) + + * 03/07/02: Fixed MADD, PLZCW in MMI.c(goldfinger) + + * 03/07/02: Fixed signed extend in DIVU, SLL, SLLV, Interpreter.c(goldfinger) + + * 03/07/02: Fixed C_F, FPU.c(goldfinger) + + * 04/07/02: Fixed silly bug on Bios.c, also added a workaround on Counters.c (linuzappz) + + * 04/07/02: Refixed CVT_W/S, FPU.c (linuzappz) + + * 03/07/02: Fixed DIV/DIVU and implemented MOVZ/MOVN in iR5900.c (linuzappz) + + v0.038: + * 02/07/02: Small change on CVT_W, FPU.c (linuzappz) + + * 01/07/02: Changed a bit IPU.c/h, added the dmaIPUs on Hw.c and added IPU_LOG, Debug.h, + resource.h, pcsx2.rc, Common.h (linuzappz) + + * 30/06/02: Add the remaining vif regs in the structure vif.h (shadow) + + * 30/06/02: Framework for IPU ipu.c,ipu.h (shadow) + + v0.037: + * 30/06/02: Added a couple of MMI opcodes to iR5900.c, ix86.c/h, also added one more cdvd server, + Bios.c (linuzappz) + + * 29/06/02: Added most of the FPU opcodes on the recompiler, fixed DSRLV/DSLLV, and also added + LQ, SQ, MFHI, MFLO, MTLO, MTHI, iR5900.c, ix86.c/h (linuzappz) + + * 28/06/02: Refixed LDL,LDR,SDL,SDR, Interpreter.c (linuzappz) + + * 27/06/02: Fixed bug in ABS, FPU.c and completed more fpu opcodes on DisR5900.c + fix to vu0 (vu0.c) + (shadow-linuzappz) + + * 27/06/02: Fixed fileio for dummy files, Bios.c (linuzappz) + + * 26/06/02: Changes/(fixes?) to some opcodes in interpreter.c SRA,DSRA,MULT,MULTU + ,SDL,SDR,LDR,LDL.At least cubemastah is correct now!(GoldFinger) + + * 20/06/02: Fixed the new Logging, modified the files on the last entry + WinMain.c (linuzappz) + + * 18/06/02: Realtime Logging Debugger.c,resource.h,pcsx2.rc,ini.c, + Common.h,debug.h (you must enable it!)(need to fixed) (shadow) + + * 18/06/02: Add some work for sjpcm module on Bios.c (shadow) + + v0.36: + * 13/06/02: Fix basic3d on Bios.c (linuzappz) + + * 09/06/02: Fix for call/ret dma in GS.c (shadow) + + * 06/06/02: Started CDVD plugin API on PS2Edefs.h (linuzappz) + + * 06/06/02: Started HLE.c/h, Interpreter.c, Common.h, iR5900.c, InterTables.c/h (linuzappz) + + * 04/06/02: Added some more syscalls on Bios.c (linuzappz) + + * 02/06/02: Fixed some bugs on SPR.c, Sif.c, Vif.c (linuzappz) + + * 02/06/02: More work on DisR5900asm.c (shadow) + + * 02/06/02: More stuff on Vif.c/h and SPR.c (linuzappz) + + * 01/06/02: Started SIFdmas Hw.c, Sif.c/h, Common.h, added SIF_LOG to Debug.h, + also removed the BREAK code since the bios doesn't handles that, Interpreter.c (linuzappz) + + * 01/06/02: Added PLZCW to MMI.c (linuzappz) + + * 01/06/02: RFU060 is now as before, added INTC and DMAC stuff, added INTC regs 0x1000f000 and + 0x1000f010, and DMAC 0x1000e010, Hw.c/h, Bios.c, Counters.c, R5900.c/h (linuzappz) + + * 31/05/02: Thread stuff is better now, added RFU061 and fixed RFU060, Bios.c (linuzappz) + + * 30/05/02: VU0 stuff is almost complete on DisR5900asm.c (shadow) + + * 30/05/02: Set gp on ElfHeader.c (linuzappz) + + * 30/05/02: Renamed _LOG to EMU_LOG, Debug.h, WinMain.c (linuzappz) + + * 28/05/02: Implemented GetCop0/iGetCop0 bios calls, Bios.c (linuzappz) + + * 28/05/02: Added names to GPR/COP0 regs, R5900.h, COP0.c, Bios.c, Interpreter.c, + FPU.c, DisR5900.c, R5900.c, VU0.c, MMI.c, iR5900.c, ElfHeader.c (linuzappz) + + * 28/05/02: Fixed PSUBW, PSUBB, added PADDW, PEXTLB, PEXTUH, MMI.c, PERF + on Interpreter.c, and TLBWR, TLBR to COP0.c (linuzappz) + + * 28/05/02: disasm.c/h is now DisR5900asm.c, Debugger.c, Debug.h, also added symbols + support for it (linuzappz) + + v0.35: + * 27/05/02: INCREASE VERSION ON 0.036! WinMain.c (shadow) + + * 27/05/02: add partialy support for VU0 in Win32 disasm.fix a bug in tables for MMI + disasm.c disasm.h (shadow) + + * 27/05/02: add VU1 register debugger. resource.h, pcsx2.rc,debugger.h, debugreg.c (shadow) + + * 27/05/02: Started real threads stuff on Bios.c (linuzappz) + + * 27/05/02: Rewrote dmaGIF/dmaVIF1, GS.c/h, Vif.c/h, Hw.c/h (linuzappz) + + * 27/05/02: add Macros for VU0Mem + Some new VU0 opcodes VISWR,VILWR, (shadow - [TyRaNiD] ) + + * 27/05/02: add some new Defines (_Id_ _Is_ _It_ _Imm5_) and some new opcodes + VIADD,VISUB,VIOR,VIAND,VIADDDI,VFOI12,VFOI15,VABS (shadow) + + * 26/05/02: Added support for Symbols on DisR5900.c, ElfHeader.c, Debug.h, + also refixed the qwc on SPR.c (linuzappz) + + * 26/05/02: Added some cdvdfsv stuff on Bios.c, also set the gs revision to 3 in + CSR, GS.c (linuzappz) + + * 25/05/02: CTC2/CFC2 to DisR5900.c (linuzappz) + + * 25/05/02: Added BREAK opcode on Interpreter.c (linuzappz) + + * 25/05/02: Now the b0000000 to b2000000 address are handled as a 10000000 mirror, + Hw.c, Memory.c (linuzappz) + + * 25/05/02: Removed some old code on R5900.c, rewrote a bit the ElfHeader.c (linuzappz) + + * 24/05/02: Add gsWrite... on bios_SetGsCrt (tyranid) + + * 24/05/02: MULT1/MULTU1 are now ok MMI.c (linuzappz) + + * 24/05/02: Added 1000f000 addr on hwRead32, Hw.c (linuzappz) + + * 23/05/02: add VU0 opcodes VSUBi,VSUBq,VMULA,VMULAi,VMULAq,VMSUB,VMSUBi, + VMSUBq,VMADDA,VMAX,VMINI,VADDA,VADDAi,VADDAq,VADDAx,VADDAy, + VADDAz,VADDAw,VSUBA,VSUBAi,VSUBAq,VSUBAx,VSUBAy,VSUBAz,VSUBAw, + VMSUBA,VMSUBAx,VMSUBAy,VMSUVAz,VMSUBAw,VMSUBAi,VMSUBAq (shadow) + + * 23/05/02: add VU0-1 status. (vu0.h , vumicro.h) (shadow) + + * 23/05/02: Added VU0/1micro.c/VUmicro.h (shadow) + + * 23/05/02: Fixed bios_isceSifDmaStat (return -1), also started some work on the + zero-exception stuff, Bios.c, IopBios.c, R5900.c (linuzappz) + + * 23/05/02: VRNEXT should be fine now, VU0.c (linuzappz) + + * 23/05/02: Small addition on Bios.c, 0x80000003 cmd on bios_isceSifSetDma (linuzappz) + + * 22/05/02: Added define __VU0_H__ on VU0.h (linuzappz) + + * 22/05/02: Rewritten GSdma/dmaGIF stuff, now only GSgifTransfer exists, added dmaGIF to GS.c, also added + GIF_LOG to Debug.h, Plugins.c/h (linuzappz) + + * 21/05/02: Fixed one bug in WinMain.c, now can rerun a elf ok (linuzappz) + + * 21/05/02: More stuff to Vif.c (linuzappz) + + * 20/05/02: Fixed one bug in biosException (linuzappz) + + * Started SPRdmas, SPR.c/h, Hw.c, Common.h, also added SPR_LOG, Debug.h (linuzappz) + + * 'call' dmaChain mode in dmaVIF1 should be right now (linuzappz) + + * More changes to the GS plugin API, GSdmaGIF/GSdma, PS2Edefs.h, Plugins.c, Hw.c, Vif.c, + also fixed little bug in SPU2init (linuzappz) + + * Small change in GSmakeSnapshot, now pass char *path (linuzappz) + + v0.34: + + * add more opcodes to Disasm DisR5900.c (shadow) + + * correct MTSA in interpreter interpreter.c (_Rs_ and not _Rd_) (shadow) + + * fixed FPU register debugger debugreg.c .Now registers appears float (shadow) + + * Some more stuff on Bios.c/Counters.c, timer1 intc, fixed bug in CreateSema (semaid stuff), + and added iSignalSema (linuzappz) + + * Added some VU0 opcodes to DisR5900.c (linuzappz) + + * Fixed bug in FPU.c, BC1XX branch delay (linuzappz) + + * Started Vif0/1 dmas, Hw.c, Vif.c/h, Common.h, added VIF_LOG to Debug.h (linuzappz) + + * Fixed VSUBx, VMULz, renamed VMONE to VMOVE, VU0.c (linuzappz) + + * Moved COP2 from Interpreter.c to VU0.c, and MMI to MMI.c (linuzappz) + + * fixed VU0 register debugger debugreg.c (Linuzappz-shadow) + + * Added ExecuteBlock and removed ExecuteBios on R5900cpu, R59000.h, Interpreter.c + and iR5900.c, also added psxExecuteBios, R5900.c, WndMain.c (linuzappz) + + * Some fixes to VU0.c, _Rd_ == 0, not _Rd_ != 0 (linuzappz) + + * Added MTHI1/MTLO1, MMI.c (linuzappz) + + * Rewrote Memory.c (linuzappz) + + * Improved iR5900.c branchs, and updated ix86.c/h (linuzappz) + + * Fixed bug in MULTU, (u64) stuff (linuzappz) + + * Interrupt Exception code was wrong, 0 -> 0x400 (linuzappz) + + * Started ChangeLog + diff --git a/branches/pcsx2_0.9.1/Docs/License.txt b/branches/pcsx2_0.9.1/Docs/License.txt new file mode 100644 index 0000000..7d1f860 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/branches/pcsx2_0.9.1/Docs/PS2Edefs.txt b/branches/pcsx2_0.9.1/Docs/PS2Edefs.txt new file mode 100644 index 0000000..5442da8 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/PS2Edefs.txt @@ -0,0 +1,443 @@ + PS2E Definitions v0.3.0 (beta) + ------------------------------ + + Author: linuzappz@pcsx.net + +Note: Refer to PS2Edefs.h for more info. + +1) API Funcs +2) FAQs +3) Notes + +1) API Funcs: + --------- + + Common stuff: + ------------ + +// u32 CALLBACK PS2EgetLibType(void); + +Gets the plugin type, from the following defines: + +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +Note that the types can be ORed so you can make an +ie. GS/PAD plugin in one dll. + +// u32 CALLBACK PS2EgetLibVersion(void); + +Will get the plugin version: + +const unsigned char version = 1; // GS library v1 +const unsigned char revision = VERSION; +const unsigned char build = BUILD; // increase that with each version + +return version<<16|revision<<8|build; + +'version' is the GS plugin API version, as this is beta, +it should be 1. +'revision' and 'build' are plugin defined values. + +// char* CALLBACK PS2EgetLibName(void); + +Get the LibName, ie. "GSsoftdx Driver"; + + + + GS plugin API: + ------------- + +Basic funcs +----------- + +// s32 CALLBACK GSinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK GSopen(void *pDsp, char *Title); + +Opens the plugin, return 0 on success, else -1. +The plugin must fill the 'pDsp' arg (32bit) that'll be +passed to other plugins (*1), this is OS dependant (*2). + +On Win32: pass a HWND value, ie: + *(long*)pDsp = (long)GShwnd; +On Linux: pass a Display value, ie: + *(long*)pDsp = (long)display; + +*1 Even if this value is passed to every plugin, this +may not be used by the plugins. + +*2 This could change anyways, ie. maybe you can code a +GS/PAD plugin for a speacial library, so the pDsp +will be a value that you need to communicate between +them (if you need to do this). + +// void CALLBACK GSclose(); + +Close the plugin. + +// void CALLBACK GSshutdown(); + +Shutdown the plugin. + +// void CALLBACK GSvsync(); + +Called on every VSync. + +// void CALLBACK GSgifTransfer(u32 *pMem, u32 size); + +Transfer 'size' qwords (128bit) from 'pMem' to the Gif. + +// void CALLBACK GSgifTransfer2(u32 *pMem); + +Transfer a qwords (128bit) block from 'pMem' to the Gif. + +// void CALLBACK GSwrite32(u32 mem, u32 value); + +Writes to address 'mem' data 'value', 32bit. +Addresses can range from 0x12000000 to 0x14000000. + +// void CALLBACK GSwrite64(u32 mem, u64 value); + +Writes to address 'mem' data 'value', 64bit. +Addresses can range from 0x12000000 to 0x14000000. + +// u32 CALLBACK GSread32(u32 mem); + +Returns 32bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +// u64 CALLBACK GSread64(u32 mem); + +Returns 64bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +Extended funcs +-------------- + +// void CALLBACK GSkeyEvent(keyEvent *ev); + +Gets called when there is a keyEvent from the PAD plugin + +// void CALLBACK GSmakeSnapshot(char *path); + +Makes an snapshot of the vRam, can be a with the full +vRam or just the view area (as you prefer), to the dir +'path'. + + +// #ifdef __WIN32__ +// s32 CALLBACK GSsetWindowInfo(winInfo *info); +// #endif + +Windows only function, will pass the info struct to the +GS plugin, if the plugin will use this info it should +return 1 (TRUE), else the emu will destroy the window +handle and let the plugin take care of that. +This function must be called before the GSopen. +Note that the emu should hide the hMenu and the hStatusWnd +if it they are set. +The position and size of the window is not specified and +should be reset by the plugin, but the window passed should +be in a normal state, not maximized nor minimized. +After a GSclose the emu must destroy the window and +recreate it. + +// void CALLBACK GSconfigure(); + +Configure the plugin. + +// void CALLBACK GSabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK GStest(); + +Returns 0 if the plugin should work ok, else -1. + + + + PAD plugin API: -=[ OBSOLETE ]=- + -------------- + +Basic funcs +----------- + +// s32 CALLBACK PADinit(u32 flags); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK PADopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK PADclose(); + +Close the plugin. + +// void CALLBACK PADshutdown(); + +Shutdown the plugin. + +// keyEvent* CALLBACK PADkeyEvent(); + +Called every vsync, return NULL if no event happened. + +// u8 CALLBACK PADstartPoll(int pad); + +Starts polling data from the PAD, 'pad' can be 1 (pad1) +or 2 (pad2). +Returns first byte from buffer; + +// u8 CALLBACK PADpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt" or "padmem.txt", +for info about value/buffer data. + +// u32 CALLBACK PADquery(); + +returns: 1 if supported pad1 + 2 if supported pad2 + 3 if both are supported + +Extended funcs +-------------- + +// void CALLBACK PADconfigure(); + +Configure the plugin. + +// void CALLBACK PADabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK PADtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SIO plugin API: + -------------- + +Basic funcs +----------- + +// s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); + +Inits the plugin, return 0 on success, else -1. +port/slot combination will be used to load the corresponding + configuration data from ini. It's like an id for the instance. +'f' is a callback function that is used by SIO_TYPE_MTAP capable + plugins to change active slot in emulator (since sio is emu-controled). + +// s32 CALLBACK SIOopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK SIOclose(); + +Close the plugin. + +// void CALLBACK SIOshutdown(); + +Shutdown the plugin. + +// u8 CALLBACK SIOstartPoll(u8 value); + +Starts polling data from the SIO, 'value' is + 0x01, 0x21, 0x61 and 0x81 corresponding to pad, mtap, rm and mc. +Returns first byte from buffer; + +// u8 CALLBACK SIOpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt", "padmem.txt" or + "padspecs.txt" (http://ps2dev.ps2-scene.org/padspecs.txt), +for info about value/buffer data. + +// u32 CALLBACK SIOquery(); + +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +returns: ORed value of SIO_TYPE_xxxx - the capabilities of the plugin +eg. a remote control plugin will return SIO_TYPE_PAD | SIO_TYPE_RM + +Extended funcs +-------------- + +// void CALLBACK SIOconfigure(); + +Configure the plugin. + +// void CALLBACK SIOabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK SIOtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SPU2 plugin API: + --------------- + +TODO :) + +Basic funcs +----------- + +// s32 CALLBACK SPU2init(); +// s32 CALLBACK SPU2open(void *pDsp); +// void CALLBACK SPU2close(); +// void CALLBACK SPU2shutdown(); +// void CALLBACK SPU2update(); +// void CALLBACK SPU2dma(u32 *dmaAddr, char *pRam); +// void CALLBACK SPU2write(u32 mem, u16 value); +// u16 CALLBACK SPU2read(u32 mem); + +Extended funcs +-------------- + +// void CALLBACK SPU2configure(); +// void CALLBACK SPU2about(); +// s32 CALLBACK SPU2test(); + + + + CDVD plugin API: + --------------- + +Basic funcs +----------- + +// s32 CALLBACK CDVDinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK CDVDopen(); + +Opens the plugin, return 0 on success, else -1. + +// void CALLBACK CDVDclose(); + +Close the plugin. + +// void CALLBACK CDVDshutdown(); + +Shutdown the plugin. + +// s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +Starts reading from the specified 'lsn' sector location, +return 0 on success, else -1. + +// u8* CALLBACK CDVDgetBuffer(); + +Gets a pointer to the buffer with the sector data +readed by a previously CDVDreadTrack call. +The buffer size depends on the mode used for readTrack. + +note: return can be NULL (for async modes) + +// s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq); + +Read subq data from disc at 'lsn' location (only cds have subq data), +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); + +Get the the cdvdTN data for the currect CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTD(u8 Track, cdvdLoc *Buffer); + +Get the the cdvdTD data for the 'Track' track in the current CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTOC(void* toc); + +Get ps2 style toc from disc, return 0 on success, else -1. +(ps2 toc isnt quite the same as a normal disc toc, +especially for dvds) + +// s32 CALLBACK CDVDgetDiskType(); + +Returns disktype in the format CDVD_TYPE_xxxx + +// s32 CALLBACK CDVDgetTrayStatus(); + +Returns tray status in the format CDVD_TRAY_xxxx + +// s32 CALLBACK CDVDctrlTrayOpen(); + +Opens disc tray, return 0 on success, else -1. + +// s32 CALLBACK CDVDctrlTrayClose(); + +Closes disc tray, return 0 on success, else -1. + + +Extended funcs +-------------- + +// void CALLBACK CDVDconfigure(); + +Configure the plugin. + +// void CALLBACK CDVDabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK CDVDtest(); + +Returns 0 if the plugin should work ok, else -1. + + +2) FAQs + + * What's the right open/close sequence? + 1. CDVD + 2. GS + 3. PAD1/2 + 4. SPU2 + + * Where to start coding a plugin? + Get an open source plugin, mine are all open source, + so you can freely base on them. + + * Why GSgifTransfer2 exists? + GSgifTransfer2 is used by the XGKICK VU1 opcode, and + it doesn't has a size, the GSgifTransfer is used by he GIF + and the VIF dmas, and it has a size, so that's why :). + +3) Notes + + * CDVDgetBuffer should be used after CDVDreadTrack, + like this: + CDVDreadTrack(time); + ptr = CDVDgetBuffer(); + + but not like this; + ptr = CDVDgetBuffer(); + CDVDreadTrack(time); + + * Errors should be checked for both CDVDreadTrack and CDVDgetBuffer, + and not only CDVDreadTrack. + diff --git a/branches/pcsx2_0.9.1/Docs/Readme.txt b/branches/pcsx2_0.9.1/Docs/Readme.txt new file mode 100644 index 0000000..20d2c18 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/Readme.txt @@ -0,0 +1,196 @@ + + + + +PCSX2 - A PS2 EMU +------------------ +Here it is. A first try for an ps2 emulator... +Of course it isn't very advance now but there are some stuff here... + + + +Overview +-------- +Well i will try to catch up some questions. +First of all pcsx2 don't run Ps2 games yet! +And of course it is far from doing this. +So pcsx2 don't run GT3, get it? :) +So what pcsx2 is? pcsx2 is a try to emulate sony's beast. +Of course it isn't so easy as it might seems. +So far you can consider pcsx2 as a develop tool althought +i suggest don't use pcsx2 as a tool for writing your ps2dev +stuff :). Consider the opinion that pcsx2 have bugs and we +wrote this emu by reverse enginnering ps2 demos that might +have bugs too :) +Hope you enjoy pcsx2.. + +The Pcsx2 team.. + + +Configuration +------------- + +Cpu Options: + + +Misc Options: + + * Enable Console Output: + Displays the psx text output. + + + * Enable patches + Enable the patches for games.(if they exist). + Might fix some stuff might screw some stuff. + Enable it at your own risk. + + * Enable pad hack. + if your pads doesn't seem to work if you enable that much fix the pads for the specific game. + Warning!! not leave that option checked might broke some other games as well + +Recompiler options: + +* Disable Recompiler (default). It will run with interpreter if it is ON. + Slower but more compatible. + +* Disable Vu recompiler (default). Will disable the vu recompile + (of course if recompile mode is used). More compatible recompiler but slower. + + * Enable reg caching (disabled in 0.6) + Enable the reg caching recompiler (you must have enable interpeter cpu off!) + It is more faster than the default recompiler + + + +Quick Keys: + F1: Save state + F2: Change slot (0-5) + F3: Load State + F8: Makes a Snapshot + + (debugger keys) +---------------- + F11 un/sets Log + F12 un/sets symbol logging + +Status +------ + +Most part of ps2 have been emulate. + +Things that are still missing or uncomplete + +IPU : decoding almost done. Pcsx2 can play *.ipu or *.m2v files but no pss yet +VU : there are several issues with graphics ingames. Still we are not sure if it is GS, VIF or VU problems + but we are looking for it +recompiler: planning for fast reg cache core and recompile of vus . Soon :P + + +and of course a million other bugs that exists and we hope they will be fixed ;0 + + + + + +How you can help +---------------- +If you have any info you think we can use email us, but always ask before +sending files. If you want to help in some other way also email us. + + + +The Team +-------- +Nickname | Real Name | Place | Occupation | e-mail | Comments +--------------------------------------------------------------------------------------------------------------- +Linuzappz | | Argentina | Main coder | linuzappz@pcsx.net | Master of The GS emulation and so many others.. +Shadow | George Moralis | Greece | co-coder-webmaster| shadowpcsx2@yahoo.gr | Master of cpu, master of bugs, general coding... +florin | Florin Sasu | Romania | co-coder | florin@pcsx2.net | Master of HLE. Master of cd code and bios HLE.. +asadr | | Pakistan | co-coder | | Fixing bugs around (FPU, Interpreter, VUs...) +Goldfinger | | Brazil | co-coder | | MMI,FPU and general stuff +Nachnbrenner| | Germany | co-coder | | patch freak :P +aumatt | | co-coder | | a bit of all mostly handles CDVD cmds +loser | | Australia | co-coder | loser@internalreality.com | obscure cdvd related stuff +refraction | Alex Brown | England | co-coder | refraction@gmail.com | General Coding DMA/VIF etc + +ex-coders: +basara -co-coder . Recompiler programmer. general coding +[TyRaNiD] -co-coder . GS programmer.General coding +Roor -co-coder . General coding + + +Additional coding: + +F|RES +Pofis +Gigaherz +nocomp + + +BETA testers +------------ +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever + + +Team like to thanks the Follow people +------------------------------------- +Duke of NAPALM - for the 3d stars demo. The first demo that worked in pcsx2 :) +Tony Saveski (dreamtime) - for his great ps2tutorials!! +F|res - You will learn more about him soon. but a big thanks from shadow.. +Now3d - The guy that helped me at my first steps.. +Keith - Who believed in us.. +Bobbi - Thorgal: for hosting us, for design or page and some many other +Sjeep - Help and info +BGnome - Help testing stuff +Dixon - Design the new pcsx2 page, and the pcsx2.net domain +bositman - pcsx2 beta tester :) (gia sou bositman pare ta credits sou ) +No-Reccess- nice guy and great demo coder :) +nsx2 team - for help to vu ;) +razorblade - for the new pcsx2 logo,icon. +snake - he knows what for :P +ector - awesome emu :) +zezu - a good guy. good luck with your emu :P + + + + +Credits +-------------- +Hiryu & Sjeep - for their libcdvd (iso parsing and filesystem driver code) +Sjeep - for SjDATA filesystem driver +F|res - for the original DECI2 implementation +libmpeg2 - for mpeg2 decoding routines +aumatt - for applying fixes to pcsx2 +Microsoft - for vc.net 2003 :p (really faster than vc6) :P +NASM team - for nasm +CKemu - logos/design + + +and probably to a few more.. + +Special Shadow's thanks go to... +-------------------------------- +My friends : Dimitris, james, thodoris, thanasis and probably to a few more.. +and of course to a lady somewhere out there.... + + + + + +Log off/ +Linuzappz/ shadow / florin / asad/ goldfinger / nachbrenner (others???) + + + + + + + diff --git a/branches/pcsx2_0.9.1/Docs/RemoteDebugging.txt b/branches/pcsx2_0.9.1/Docs/RemoteDebugging.txt new file mode 100644 index 0000000..339b400 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/RemoteDebugging.txt @@ -0,0 +1,105 @@ +ͻ +NOTE: 1. this is an internal pcsx2 team document, for developers ONLY + 2. lamers/gamers are excluded + 3. DECI2 will not run your games:P +ͼ + +RemoteDebugging +=============== + +This is a new feature available for debugging applications within pcsx2 emu. + Using a remote debugger is not wellcomed unless it is more featured. + Fortunately, there are such debuggers. Currently added support is for win32 + target only; also, only TCP/IP remote connection and only for Sony's DECI2 + app-level protocol. Future addition could be GNU debugger remote support. + +Anyway, pcsx2 has a new menu item that allows one to start a debugging session + by specifying the listen port [default for DECI2 is 8510]. Pcsx2 will act like + a server for the remote debugger. It is set to accept connections on any IP. + For local debugging sessions, use IP=127.0.0.1 aka IP=localhost. On the + other hand, if a pcsx2 would be listening on an active IP in the Internet, + anyone could connect to it;) Only one connection is supported. After the + connection is closed by the client/remote tool, the only thing to do is to + "admire" the log window and then close it/restart the emu. + +So, to start a debug session: + - first start the emu [quite reasonable; because it will be the server]. There + are some issues if you start the client first or if you didn't close ALL the + client subprograms in the last debugging session. + - choose from the menu, Debug->Remote Debugging. A dialog will pop asking for + the port to use. Also, if you have a non-HLE bios selected in the Config box, + ie. a true bios, there will be also an option weather to debug the bios. You + have 2 choices: + -not checked=Run Bios + before any debug is performed a bios run. ie. the emu + will run the bios up to the shell loading or a bit + further, to the moment when all the iop modules are + loaded. You will have then a full environment loaded. + -checked=Debug Bios + nothing is done further and the PC=0xBFC00000. + - after that a connection log window will be shown and you can follow the + connection data exchange. First, the emu is placed in a wait state. + - this is the moment you have to run the client. It will open the connection. + The emu accepts the connection and the DECI2 protocol is on;) + You'll see how the client queries for registers values & memory areas. + - the situation gets complicated since you can do many things from now on: + +Debug bios: + - start with a bios selected and the check box checked (see above). + - PC=0xBFC00000 and you can trace the bios now. Anyway, there is no breakpoints + support for the bios as the client "thinks" you are debugging the real PS2, + so you cannot write to bios area. BTW: the breakpoints are implemented by + patching the code with a BREAK instruction. Since you cannot write such instr + you cannot put a breakpoint on the bios, cannot run to address and so on... +Run bios: + - start with a bios selected and the check box not checked (see above). + - wait till the emu runs the bios...it will take some time. After THAT the + connection log window will be displayed. + - PC=0x82000 or smth like that...you can check the environment set up while + running the bios. The modules window for instance. And various memory + structures. Also, this is the entrypoint of the shell loading. Try to trace + it;) +Debug an application: + - start with HLEbios selected (see above) + - since the debugger (the client) does debug whatever you want to. You can + load the elf to debug with pcsx2 loader (ie. with File->Load ELF file or + from the CDVD). But you will need to know the entrypoint to force it in + remote debugger (set PC to cursor or to address). This way is not recomended. + I like to use the loader of the debugger since it knows to load the source + also if available and does not cause troubles with setting the PC. Also, if + the ELF has symbols, it can run it to main;) + - now, you're on your own. Use step by step, step over, breakpoints, run to + cursor, run to address etc. HAPPY DEBUGGING! + +KNOWN ISSUES and NOTES +====================== + - use CDVDnull or another plugin as you like to have or not a src for cdvd + loading;) + - pcsx2 does not have support to debug the IOP. You can do this now but it is + a hard job. That is due to the fact that PS2 can run every processor + independently (ie. one can be stopped) and pcsx2 cannot. The emu runs either + all the procs or nothing. So, in the debugger, the debugged processor is on + stop and others are "running". When there will be added support for debugging + the IOP, also only one processor will run. + - do not step through the program very fast. Because of the communication speed + and a reentrancy issue, this will get the debugger in a FALSE run state. That + means that the debugger "thinks" that the PS2 (ie. pcsx2;)) is running, + although it is not. The simple solution to this is to press STOP/BREAK button + in the debugger. Notice also that some run states might be also true! When + you are stepping over a big loop...that might take some time, so if you stop + the emu you will get in the middle of the loop:P + - you can also notice the low speed that can also be met in the pcsx2 debugger. + That's because Cpu->Step() is used. + - also, notice that you cannot debug in recompiler mode! ONLY interpreter mode + works! + - IOP modules loading is not supported and the files loaded from host directory + are also loaded in pcsx2 way, ie. from host\ directory; not through remote + debugger. + - if you try to debug the bios and the code is not displayed...scroll down + in order to have only valid addresses on the screen; ie. the top address + to be 0xBFC00000 and in emu communication log there will be no ADDRESS ERROR. + + +=============================== +Florin (florinsasu@yahoo.com) +2003/04/17 diff --git a/branches/pcsx2_0.9.1/Docs/RunCDVD.txt b/branches/pcsx2_0.9.1/Docs/RunCDVD.txt new file mode 100644 index 0000000..abcede5 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/RunCDVD.txt @@ -0,0 +1,86 @@ + +RunCDVD - New feature explained +=============================== + +Q: What CDVD stands for? + +A: It is a short form for CD/DVD i.e. CD or DVD. + +---------------------------------------------------- + +Q: Can I run games? + +A: What do you mean by games? + There are two types of games: commercial ones and homebrew ones. + There are also two types of demos: from magazines and homebrew. + Homebrew SW will run first as they are simpler and are open-source sometimes. + +---------------------------------------------------- + +Q: Can I run commercial games? + +A: Yes, but this answer is not good for you:P + You cannot play them... + Technicaly, the game starts but it does not go very far, + because this is only the beginning... + +---------------------------------------------------- + +Q: So, what's the deal then? Is there any game that run? more? + +A: Yes, but as far as we know, not any comercial game. + Homebrew iso version of PSMS runs ok. + Also we cannot test with all the games as we don't have them all:P + +---------------------------------------------------- + +Q: When can I play game X ? + +A: Dunno, only time can say that... + We only added the CDVD loading option for now. + You will have to wait for another version of the emu to see any screenshot. + +---------------------------------------------------- + +Q: How do I run a CD/DVD game or iso/bin? + +A: You need a CDVD plugin. + Get the CDVDbin for Windows & CDVDlinuz for Linux + from http://pcsx2.ngemu.com (Download section) or from http://www.ngemu.com + Place it in Plugins directory. Run the emu and in configure dialog choose + that plugin. Then Run->Execute. When using the CDVDbin plugin + you will be promted to choose a file to use. + Select the iso or the bin of the game you own. + (To test that use psms.iso) + +---------------------------------------------------- + +Q: I have the game X on CD/DVD. What's the iso/bin stuff anyway? + +A: Well, if you have a game on CD/DVD and a bad CD/DVD drive, + you can backup it on the harddisk with a CD/DVD recording program or a simple + iso/bin ripper. That program will make an image of the CD/DVD disc + on the harddisk and you can use that image with the CDVDbin plugin. + +---------------------------------------------------- + +Q: What's the difference between .iso and .bin formats? + +A: Bin is an image with raw sectors of 2352 bytes. + Iso contains only the data part from a CD sector; ie. 2048 bytes + +---------------------------------------------------- + +Q: I have more questions. Where are the answers? + +A: First of all, think twice before asking a question. + It might be already answered or the answer is toooooo simple. + Also, there can be more questions that i missed. Use the PCSX2 forum + on http://www.ngemu.com for that. Thank you! + + +=============================== +Florin (florin@ngemu.com) + + + diff --git a/branches/pcsx2_0.9.1/Docs/ToDo.txt b/branches/pcsx2_0.9.1/Docs/ToDo.txt new file mode 100644 index 0000000..a8a595c --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/ToDo.txt @@ -0,0 +1,22 @@ +To do for Pcsx2: + * Fix threads, semas & events (linuzappz, Florin) + * Deci2: iop debug (since pcsx2 cannot run only one processor) (Florin) + tty notifications + * Continue RunCDVD option for PS1 exes loading. + * Continue Bios emulation. (linuzappz) + * Continue Recompiler. (linuzappz, basara) + * Fix bios execution. (linuzappz) + * Recheck TLBS. + * Continue HW stuff. (linuzappz) + * Fix VU code. (shadow) + * Check MMI.c. + * Check FPU code. + * Implement remaining COP0 opcodes. + * Deci2: + -speed up execution with Cpu->ExecuteBlock(); + -fix reentrancy problem with threads (if pressed step button to soon, + you get a false run state: the emu is on pause, but the debugger + thinks that it is running) (solution: critical zones) + -add drfp support [i guess this will not be done as it is not really needed] + -add iop files load&run support (iloadp; not a priority also) + (Florin) diff --git a/branches/pcsx2_0.9.1/Docs/Translating.txt b/branches/pcsx2_0.9.1/Docs/Translating.txt new file mode 100644 index 0000000..b936bb0 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/Translating.txt @@ -0,0 +1,24 @@ + Translating PCSX2 + ----------------- + +Just some small notes for translators. + +PCSX2 translations are based on the gettext library: +http://www.gnu.org/software/gettext. + +The main file to translate is pcsx2.po located at the +'Intl' dir, note that you must place the translated +strings over the msgstr and leave untouched the msgid. + +To test the translation use the msgfmt.exe utility to +convert the translated pcsx2.po file to a pcsx2.mo file +with this command: 'msgfmt pcsx2.po -o pcsx2.mo', after translating +the file please send it to us and please ask before +translating it, maybe someone has already started it +for your language. + +If you have any problems contact us and we'll try to +help you. + + linuzappz + diff --git a/branches/pcsx2_0.9.1/Docs/What_Is_Host.txt b/branches/pcsx2_0.9.1/Docs/What_Is_Host.txt new file mode 100644 index 0000000..5671a49 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/What_Is_Host.txt @@ -0,0 +1,45 @@ + +I will try to explain in sorta how HOST is working.. +----------------------------------------------------- + +Ps2 have the ability to use loader also other than cd-rom. +That is done through special syscall. Of course the file that +you load must support that.. + +Basically we wrote that for PSMS1.2 + +As you can see in the psms1.2 zip there is a file called psms-naplink.elf. +Well that is basically created from sjeep (hi sjeep) for be able to +use psms through your USB naplink to your ps2. (so no need to burn a cd) +Well pcsx2 does exactly that. Emulate Host +client (host is your pc, +client is your ps2). + +So how is work? +--------------- +Imagine that HOst is your cd-rom . +For psms e.g +place FILES.TXT + roms in folders that specificate in files.txt and you are +ready.. + +e.g + +Host +FILES.TXT +-ROMS1 +--Alienstorm.sms +--IamLamer.sms + +I think you get the Idea... +For more questions mail me..(shadow@pcsx.net) + +About +----- +This doc has been written from shadow... +Host support was added kindly to pcsx2 by Linuzappz +Thanks to sjeep for his psms1.2 emu and his support.. +Also thanks to Keith,bobbi,thorgal,akumax,now3d and probably to some more... + +Log off +shadow/linuzappz + + diff --git a/branches/pcsx2_0.9.1/Docs/WhatsNew.txt b/branches/pcsx2_0.9.1/Docs/WhatsNew.txt new file mode 100644 index 0000000..fb4178a --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/WhatsNew.txt @@ -0,0 +1,598 @@ + ********************************* + *What's new in pcsx2 v0.8 * 13th release + ********************************* + +General +------- +Compatibility has been increased since last release. More games go ingame now and 3d is okay in most of +them. Vurecs improved and speeded up a lot (buggy in many causes so use the simple rec for compatibility) +and IPU should work in some cases.(e.g VF4) + +CPUs +---- +Fixed QFSRV/MTSAH/MTSAB +Fixed SBUS IRQ at iop +Fix for end chain mode at vif +Fixed SPR0 chain mode +Fixed intc/dmac interrupts that gets cleared right away +Added offset/difference UNPACK modes in vif +VIF irq by vifcode seems ok now +Added interleave mode for SPR +Fixed UNPACK V4_5 with mask +Fixed small bug over VIF1 dma FIFO +VIF1 doens't clears str on MFIFO +Fixed some MFIFO bugs in both GS/VIF1 +Fixed bug in REF/REFS dma at VIF1/GS MFIFO + +IPU +--- +Finally fixed IPU. Mpegs and IPU streams run so do PSS files +Quality of ipu playback improved + +PLUGINS +------- +Added GSsetCSR +added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose to cdvd + +CDVD +---- +Added some more debug info to CDVD +Fixed cdReadKey function to emulate correctly. +Modified GetToc stuff in cdvd to support dvds +cdvdTD uses lsn now +Fixed NVM (eeprom) access from cdvd stuff +Added reading of mecha version from an external file +Fixed raw dvd sector readng for dvd9 discs (otp and ptp) +Added hw-reg read/write for DecSet register 0x1f40203A +Made cdSeek change the current cdvd sector +Fixed NReady busy stuff + +Memory +------ +Added more memRead/Write funcs for speed + +VUS +--- +Fixed bug in branch address in vus +Implemented MFLAG for VU0 +Fixed some iVUmicro bugs +Fixed some VPU-STAT related issues +Fixed vu flushing over vuExecMicro +Fixed some pipelines bug within VU1,VU0 +Reworked MAX/MINI +Fixed VU's JR/JALR/BAL,ISUBIU +Added EFU pipeline to VUmicro +Fixed DIV/RSQRT exceptions + +GUI +--- +Some improvements on interface. +Added placetopatch == 1, which means patches will be applied every vsync + + + ********************************* + *What's new in pcsx2 v0.7 * 12th release + ********************************* + +GENERAL +------- +Memcards and pads should work okay now. More compatibility earned since so many things +have been fixed from previous release :) + +VIF-VUS +------- +VIF-FIFO transfers seems to work better +VU1 regs now are mapped to VU0 mem +Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2 +Fixed vu branch negative overflows +VU D/T flags are handled now +VU pointer gets aligned now + +PLUGINS +------- + +Added Firewire plugin protocol + +SPU2 +---- +Fixed SPU2async cycle +SPUdma timings changed to 80 + +CDVD +---- +Implemented ReadNVM/WriteNVM +BCR now decrements for each cdvdReadSector +Fixes to SCMD's +ReadILink/GetMecaconVersion are really implemented +CdReadConfig/CdWriteConfig now uses NVM + +Interface +--------- +sstates now use CRC +Added IOP disasm in the debugger +Added rom2/erom support +Added Patch Browser for win32 + +IPU +--- +Several changes for IPU + + +HARDWARE +-------- +Fixed bug IOP counters +Fixed some bugs over interrupts and exceptions +Newer bios will now work with pcsx2. Pads fixed, more compatibility +Fixed SIF0/1 when fifo got filled up +Fixed EXL bug +Fixed SIF SMFLAG/MSFLAG +Fixed MCDS + + + + ********************************* + *What's new in pcsx2 v0.6 * 11th release + ********************************* + +General +------- +pcsx2 is 3 years old. Happy birthday pcsx2 :) +Now you can run even more games. some 3d games should work too . so enjoy :) + + +CPUS +---- +Recompiled VUs. Needs work but some stuff might work okay now +Fixed bug in Vif.c, masks hopefully are ok +Fixed alot of bugs in VUs, hopefully some stuff will now work as it should +Added Interlock for CFC2/CTC2 +Improvements to TLB code +Restructured VU code and VIF. Fixed stuff in Interpreter and added CTC2 VU1 Microinstruction caller +Fixed UNPACK modes in VIF, the Indeterminate fields are now set to 1 by default +VUflags now should handle overflow/userflow ok + +Hardware +-------- +Fixed DMA8 +Fixed bug in GS for CSR stuff +Fixed savestates +Fixed several SIF bugs +FIFO is now really 128bit as it should be +Added code for dma interrupts +Added some scmds to CDVD +Improved and fixed sio2 stuff +Modified the DEV9irq stuff +loadElfFile now reads the whole file first +DMA4/7 interrupt timings are more accurate now +Patches names are now using crc + +GUI +--- +Memory patcher (supports only 32bit patches so far) +Fixed Bios Detection for HK Bios + +PLUGINS +------- +ADDED usb plugins + + + ********************************* + *What's new in pcsx2 v0.5 * 10th release + ********************************* + +General +------- +A release that make you look things more promising. Several games can boot now and plenty of them can reach even ingame. +There are still big issues with graphics but many improvements have done from 0.41. Some games that now can reach ingame +are: +wild wild racing PAL (with patches) +Street fighter ex3 PAL (with patches) +Le Mans 24 Hours (24 Heures Du Mans) PAL (with patches) +V-rally 3 pal (with patches) + +and probably a lot more :) + + + +CPUs +--- +Fixes to VUs +Handle for the EDI flag at ERET(cop0) +New improved cpu detection routine +Commented D/T flags for VUmicro +fixed some FPU bugs in recompiler +fixed PCPYLD in interpreter +Add compiler blocks for vu0, vu1 and few instructions +Several other fixes in cpu cores +Reg caching recompiler (not enable in 0.5 ) + +Debugger +-------- +Fixed Debugger/rdebugger (there are still some issues) + +Memory +------ +Added TLB exceptions +Fixed IOP mem accesses from EE Memory +New memory routines + +VIF +--- +Fixed VIF Transfers to include MARK reg in VIF0 aswell. +FIFO for VIF0/1 now works +More improvements to VifDma +Improved VIF for transfers in parts +FiFo VIF1 can read data now + +IPU +--- +Fixed IDEC bitstream decoding. Now, all *.ipu files should work fine +bug fixes to IPU + + +Hardware +-------- +Fixed clock in bios +Fixed MFIFO for GS dma +CDVDgetTD function need a 2nd parametre (new cdvd plugins needed!!) +cdgetTOC + cdReadSubq +HSync stuff, and better CSR/IMR handling +Implemented mskpath3 / m3r flags +Fixed VU memory64 writes masks +Implemented INTC_STAT/MASK and DMAC_STAT for 64bits +Added/fixed SCMDs (2,3,1A) in cdvd +Vif0/1 regs are now mapped to hardware +Fixes in sio, sio2 +Destination Chain for SPR0 dma and added Vif masking +Now pad2 works in lle mode [tested with bios browser] +New SCMDs and MC commands +Fixed dmaIrq's for Source Chain mode +Fixed ret DMA op +Added a base interrupt delay for the dma7 (spu2) +Fixed pads. Now it should work okay most of the times +Changed the way we handle SPR TTE transfers + +MISC +---- +Added the possibility to load the System.map from ps2linux +Added patching system. *pnach files are used now +Added dev9 plugins +Savestates + + + ********************************* + *What's new in pcsx2 v0.41 * 9th release ( Update ) + ********************************* + +General +------- +This release fixes a minor issue with the DVD iso's not booting, as of now DVD iso booting +is fixed so please try all your games again !:) + +Hardware (lle) +-------- +Fixed bug in CDVD code for DvdReads, now DVD iso's should boot just fine. + + + ********************************* + *What's new in pcsx2 v0.4 * 9th release + ********************************* + +General +------- +This release is how we wanted the first pcsx2 release to be. Finally bios is working so +many things can happend from now on. Also "Bust a Move" seems to work and other games +like Kengo 2 goes much further. All of course is done in LLE now :) . + +CPUS +---- +fix the recompiler bug that made recompiler not to work in pcsx2 0.3 +new vu code. VU0 macromode should be perfect now. +new optimaze code for fpu +Rewrote VIF once again +bug fixes to MMI +reorganize recompiler + + +DMAS +---- +Improved SIF0,SIF1,SRP1 +Added IPU0,IP1 dmas + +IPU +--- +Added decoding and commands. Some samples are working. NO pss support yet! + +IOP +--- +improved the IOP stuff.IOP is functional under bios execution :) + +HLE +--- +more WIP in Threads .Much better now +more WIP in padman. + + +Hardware (lle) +-------- +ADDED SPU2 functions. SPU2 is now possible if someone implement a SPU2 plugin. +Changed a bit the GS protocol. Gs plugins need to modificate in order to work with 0.4 +SIO2 added .Pads seems to work . Memcard partial functional +CDVD emulation added. +IOP rootcounters fixed +IOP dmas implemented +MFIFO implemented + + + +General +------ +Fixed elf loader + + + ********************************* + *What's new in pcsx2 v0.3 * 8th release + ********************************* + + + +General +------- +This version of pcsx is the first that shows ingame progress from 1 game "Sven Goran's World Manager 2002".IT is the first +ps2 emu that reaches ingame :) . Also this version have Deci2 support (usefull only for developers althought) and several +bugs have been fixed. Enjoy ;) + + + +GUI +--- +-Added MiltuLingual support( English,Catalan,German,greek,italiano,romanian,spanish) + +CPUS +---- +-Fake BC0 opcodes in cop0 +-Trap instructions fixed in interpreter +-Fixed some fpu bugs in interpreter +-Fixed MMI bugs in interpreter +-VIF1 cmd now handles the i bit, still not 100% correct +-VIF1dma now handles 'from Memory' transfers +-More Unpack case in vif +-fixed several VIF1 bugs +-VIF0 fixed also + +Hardware +-------- +-8 bit DMAS +-mem128 read/write routines +-Implemented latency interrupt thingy +-Fixes to rootcounters +-FIFO fix +-IOPmem fix +-optimaze gs dma + +Debugging +--------- +-DECI 2 Protocol !! +-fix some stuff in pcsx2 debugger +-add cpu ops debug in debugger +-Logging to STDOUT added +-add more memory mapping for EE and IOP + +HLE +--- +-rewrote of HLE code for pads (padman-xpadman). This will solve some pad problems +-rewrote the HLE code for Loadmodule +-New INTC handling in HLE bios +-Implement VSyncSetFlag in HLE bios +-Added memory dummies in mcserv. Now memcards wil be appear as functional. +-sceCDReadIOPm in CDVD HLE +-Added dummy handles for mtapman901/3 +-new Threads at BIOS HLE. Still not finished + + + + ********************************* + *What's new in pcsx2 v0.2 * 7th release + ********************************* +General +------- +pcsx2 have now a more speedy recompiler using 3dnow-3dnow2-sse instructions. Vu macromode +have been recompiled with 3d now instructions so you can see more speed there if you have a +cpu that supports 3d now. The most speed is possible with an Athlon XP cpu or a Althon 4 mobile +More support for sse or probably for sse2 soon :) + + + +rewrite of MMI +fix bugs in fileio +fix counters +new thread HLE code +fixes to CDVD HLE code +fixes-adds to VU code More vu opcodes +add some more cpu opcodes +more ipu code +add 3dnow-3dnow2-sse instructions to recompiler + + + ********************************* + *What's new in pcsx2 v0.1 * 6th release + ********************************* + +General +------- +PSMS cd version seems to work. Pgen starts to work also.. (no roms seems to working althought) +and some games might boot now... This is the first ps2 emu that boots cds :) + +GUI +--- +Added command line parsing for main's argc +Added ps2 bios check for config dialog + + +Memory +------ +Some more adds to memory maps + +CPUS +---- +Implement VU flags + some more vu0-vu1 opcodes +Fix some VIF unpack cases +Some more opcodes to R5900 + +HLE +--- +better HLE + + +RPC services for +014D704Enaplink +0B001337cdvd +80000001fileio +80000003sysmem +80000592cdvdfsv +80000597cdvdfsv +80000595cdvdfsv ++for some more but mostly dummies + +CDVD iso parser (thanks Sjeep - hiryu) +support for SJDATA file system + + + ********************************* + *What's new in pcsx2 v0.042 * 5th release + ********************************* + +GENERAL COMMENTS +---------------- +Micromode works at the release. Also some more macromode demo should +work on this release.Enjoy ;) +NOTE: Logging has been disable from the release. If you need it +Mail me ( shadow@ngemu.com) + + +GUI +--- +-ADD CDVD plugin (partially) +-change a bit the controller plugin protocol +-change a bit the GS plugin protocol (for the VUmicromode transfers) + + +CPUS +---- +-FIXES to R5900 +-FIXES to FPU +-More work in recompiler +-ADDS+fixes opcodes for MMI +-Rewritten/updated iop code +-More work to micromode (vu0-vu1) + + + +DMA +--- +-More to VIFS DMA +-More to SIFS DMA + + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.038 * 4th release + ********************************* + + +GENERAL COMMENTS +---------------- +Vu0 appears functional now. (Most of the causes ) + + +CPUS +---- +Fixes to main R5900.Many opcodes fixed ( thanks Goldfinger) +Fixes to FPU +Add some Framework for the IPU +Add some more opcodes to the recompiler including FPU opcodes + + +Debugger +-------- +Logging system + + +BIOS HLE +-------- +some support for sjpcm.irx +Fixed fileio for dummy files + + +----------------------------------------------------------------------- + + ********************************* + *What's new in pcsx2 v0.036 * 3rd release + ********************************* + + +Debugger +------- +-Add VU0 - VU1 register window +-Add VU0 macromode in disasm (still not finished) +-Added support for Symbols + +GUI +--- +-Add SPU2 interface (very partial) +-change GS specifications a bit + +CPUS +---- +-Fixed some bugs in R5900.c +-Improve recompiler +-Add VIF0 - VIF1 (very partial) +-Add more VU0 macromode instructions +-Add IOP proccesor (partial) +-Add More opcodes in MMI +-better COP0 emulation (more tlbs) + +DMA +--- +-add Stratchpad DMAS +-add VIF dmas +-add SIF dmas (very partial) + +Memory +------ +-Total rewrite to support more HW + +BIOS HLE +-------- +Many more syscall is hle now. Compatibility increase a lot + + + +General +------ +Many stuff that we are not able to explain them in details :) + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.031 * 2nd release + ********************************* +-New icon +-New logo +-Some startup work on VU0.Many VUO macromode opcodes +-Some more opcodes in the main cpu. MFSA,MTSA,SQC2,LQC2 +-More opcodes to the MMI. +-Finished R5900 FPU. +-pad emulation using HLE.. both pad1 + pad2 +-more fixes to Recompiler (still far from finish) +-add the 4 Couters(partial) +-add FIFO registers +-Add support for HOST + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.026 * 1st release + ********************************* + +FIRST RELEASE ALL ARE NEW :) + diff --git a/branches/pcsx2_0.9.1/Docs/devblog.txt b/branches/pcsx2_0.9.1/Docs/devblog.txt new file mode 100644 index 0000000..de2b9a4 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/devblog.txt @@ -0,0 +1,272 @@ +Developers Blog +=============== + +This file is mainly an R&D document containing developers findings. The aim is + to have it as much accurate as possible. Each item has to contain a number(ID), + the name of developer, revisions history and a short description. +Also, this document will serve as a pinboard - will contain coding rules, + explanations on implementation of different parts of the emulator, suggestions, + questions and ideas. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 4 +[name] Florin +[desc] PS2 info dumping project +[hist] 2006-05-08 initial version + +The emulator needs some information from a Playstation2 console. +We used to require the 'bios' software. In order to get better results + more and more information was needed. So here are some guidelines + on what we need and what we don't need from the console. +Also, a new dumper and handling of these infos in the emu are in work. + +a. The so-called 'bios', is actualy rom0 found in consoles, devkits, + test-kits and PSX at address 0xBFC00000 on both EE and IOP. + [!] Note that on 75xxx the EE side bios mismatch zone fields, + so it is recomended to make a IOP side dump. +b. Rom1 and Erom contain DvdPlayer related software and are located + starting with 0xBE000000 on PS2s from 18000 and up. Over various + versions, the size of rom1 and size and position of erom changed. + They used to be dumped separately, the new dumper will simplify this, + there'll only one file containing both rom1 and erom (2M or 4M). + [!] Note that on 70xxx and 75xxx (PStwo's) the dumping of erom from EE + is not possible, the correct dump is done only from IOP! + [!] rom1 and erom are identical for same generation for all zones. + In order to be able to run the dvdplayer code in the emulator, it needs + to be pre-decrypted. EROMDRV and DVDELF will have some 'decrypt' patches. +c. NVM (Non Volatile Memory) is 1K of code and provide valuable info about + console model and region. 10000 and 15000 don't contain the model name. + PStwo's contain the zone codes making possible to have a single version + of the rom for all zones. +d. Rom2 is found only in Chinese PS2s (50009, 70009...) and contains + a font file: GB18030. It is located at 0xBE400000. It was (w/o + justification) assumed that it is as big as rom1. There is no need to + dump it on any other console than chinese. The size is to be calculated + from the filesystem (as rom0 and rom1, it has romfs). +e. BBA (BroadBand Adapter) info is not needed to be dumped. At least not + for the emulator itself, maybe for the DEV9 plugin. Anyway, it's just + a MAC address that can be made up. +f. The current dumper is reading CDVD Mecha version. This will be replaced + by a more complete information file that will contain the following info: + from [EE] + CPU revision - revision code from COP0->PRId register + easier read from (u16)GetCop0(15) + high byte is 0x2E for EE + low byte is: high nibble major, low nibble minor of revision + FPU revision - revision code from COP1->control register 0 + same description as for cpu PRId + VUs revision - hum, i'm not aware of any revision for them :( + VUs memory - local and micro memory sizes are not detected + GS revision - upper halfword in CSR register + high byte is ID = 0x55 + low bytes is major.minor (per nibbles) + GS mem - is 4M + IPU revision - hum, i'm not aware of any revision for IPU :( + Caches - instruction and data cache sizes are read from + COP0->Config register + easier read from GetCop0(16). + MEM - total RAM available + easier read with Syscall +127 - GetMemorySize() + the values are: 32M for console and test-kits, + 128M for devkits and 64M for PSX + the size is not roughly detected. As devkits have multiple + boot modes (128M or 64M). + from [IOP] + CPU revision - revision code from COP0->PRId register + high byte seems to be 0 + low byte is major.minor (per nibbles) + initial japs have major=1, + most of the consoles have major=2, + 75xxx have a new IOP processor with major=3 + Caches - are known to be 4K-I$; 1K-D$ + 0xFFFE0130 is CACHE_CONFIG register... + MEM - total RAM available + easier to read with QueryMemSize() + the values are: 2M for consoles and test-kits, + 8M for devkits and PSX + again, the size is incorrectly read :) + SPU mem - 2M (any method of detection?) + CDVD mecha - version of CDVD controller + Scmd 0x03 with subcode 0x00 (outsize=4) + the first byte is the MG-encryption code + second is major, third is minor, fourth is [2b completed] + meka - i don't know; not supported on early consoles + Scmd 0x03 with subcode 0x90 (outsize=1+1) + DEV9 revision- type of DEV9 device: 0x2x for PCMCIA, 0x3x for EXPBAY + *(vu16*)BF80146E + USB OHCI rev - Hc_revision of the OHCI controller + *(vu32*)0xBF801600 + ILINK rev/id - I'm not sure of this one, on ps2's that don't have + firewire anymore, the value is 0xFF; on 10000 is random + *(vu32*)0xBF808480 and *(vu32*)0xBF808500 (looks like mirror) + +g. The dumper will sign the dumped content, so John Doe cannot play easily + with the bios data ;) The emu works correctly with good data/food. + +h. I'm thinking of a method to check for modified content (dumps made with a + chipped console). Probably, it will be done in the emu and presented as a + warrning. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 3 +[name] auMatt +[desc] PS2 NVM Data not 100% +[hist] 2006-05-07 initial version + + v0-v11 v12- Bits Bytes +͹ +͹ +PS1 Disc Spd 0x300 0x2c0 +PS1 Texture 0x300 0x2c0 +Video Output 0x300 0x2c0 +SPDIF 0x310 0x2c0 0 +A/R 0x310 0x2c0 1 & 2 +Language 0x311 0x2c1 All +TimeZone 0x312 0x2c2 +Summer Time 0x312 0x2c2 3 +Time Format 0x312 0x2c2 5 +DateNotation 0x312 0x2c2 6 & 7 +TimeZone 0x313 0x2c3 All +TimeZone 0x315 0x2c5 All +Model Number 0x1a0 0x1b0 16 +Console ID 0x1c8 0x1f0 8 +ILink ID 0x1c0 0x1e0 8 +Date Stamp 0x180 16 +Date Stamp 0x1e0 16 +Date Stamp 0x1f0 16 +Rem. Control 0x2c4 5 +Checksum 0x31f 0x2cf All + +Checksum is calculated by the previous 15 bytes added together, then ANDed with 0xFF + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 2 +[name] Florin +[desc] PS2 bios versioning +[hist] 2006-04-30 initial version + +MG zone - the MagicGate decryption zone. You can find the code as one of the bits + in the byte at offset +1C in MagicGate encrypted files +PS1 drv - the letter for PS1VERx files in PStwo rom0 +ROMVER - has the following format VVvvZTYYYYMMDD in 14 bytes + VV, vv are the version of the bios in BCD + Z is zone code, see below + T is type of the console: C - consumer console, D - devkit/test console + YYYYMMDD is date of the bios + - BxDATA-SYSTEM, BxEXEC-SYSTEM, BxEXEC-DVDPLAYER uses Z code in place of 'x' + I: default, Japan; A: Usa, Asia; E: Europe, Oceania, Russia; C: China +VERSTR - the code from that file in rom0 +OSDVER - VVvvZlng is the format of the file for scph5xxxx. in PStwo the last 4 letters + are read from NVM, offset +180 7 chars (ROMVER:1|OSDVER:4|VERSTR:1|DVDID:1) +mecha - version read from CDVD SCmd 0x03:0x00 + +The following table is far from complete... + + Japan USA AusNz UK EuropeKorea HK TaiwanRussiaChina Mexic +͹ +͹ +MG zone 0/J 1/U 3/O 2/E 2/E 4/A 4/A 4/A 5/R 6/C 7/M +PS1 drv J A E E E H H H E C A +ROMVER 0 J 1 A 2 E 2 E 2 E 1 H 1 H 1 H 2 E 3 C 1 A +VERSTR J A E E E J J J E J A +OSDVER 0 Jjpn1 Aeng2 Eeng2 Eeng2 Eeng5 Kkor6 Htch6 Htch4 Rrus3 Csch Aspa? +Ķ +v0 scph10000 Ķ + mecha0.12.0Ķ + ver0100JCĶ + date000117Ķ + scph15000 Ķ + mecha0.18.0Ķ + ver0101JCĶ + date000217Ķ + scph18000 Ķ + mecha0.22.0Ķ + ver0120JCĶ + date001027Ķ +͹ +v1 scph30000 30001 Ķ +v2 30000 30001 Ķ +v3 30000 30001 30002 30003 30004 Ķ +͹ +v4 scph30000 30001 30002 30003 30004 Ķ + mecha Ķ + ver 0120EC Ķ + date 000902 Ķ + 35000 35001 35002 35003 35004 35005 Ķ +͹ +v5 30000 30001 30002 30003 30004 30005 Ķ + scph30000R30001R30002R30003R30004R30005R30006R30007RĶ + mecha0.32.0 2.32.0 Ķ + ver0160JC 0160EC0160EC Ķ + date011004 011004011004 Ķ +v6 Ķ +͹ +v7 scph37000 Ķ + 39000 39001 39002 39003 39004 39005 39006 39007 39008 Ķ + mecha 1.36.0 Ķ + ver 0160AC Ķ + date 020207 Ķ + Ĵ39001NĴ39010N +Ķ +v8 scph39000 Ĵ39006 Ķ + mecha0.38.0 + ver0160JC + date020426 +͹ +v9 scph50000 50001 50002 50003 50004 50005N50006 50007 50008 50009 Ķ + Ĵ50001NĴ50010N + 55000 Ĵ55005N55006 55007 Ķ +Ķ +v10 scph 50001 50002 50003 50004 50006 50007 50009 50010 + mecha 4.54.04.??.0 6.??.0 + ver 0190EC 0190HC0190HC 0190CC + date 030623 030623030623 030623 +v11 50004 Mexic USA +ͻ +v12 scph70000 Ĵ70002 70003 70004 70005 70006 70007 70008 70009 Ĵ70011 70012 + mecha Ĵ3.62.02.62.02.??.0 4.64.0 5.??.0 Ĵ 1.60.0 + ver0200JCĴ0200EC0200EC0200EC 0200HC 0200EC Ĵ 0200AC + date040614Ĵ040614040614040614 040614 040614 Ĵ 040614 +v13 scph 70001 70002 70003 70004 ͼ +͹ +v14 scph75000 75001 75002 75003 75004 75005 75006 75007 75008 Ĵ75010 + mecha 1.66.03.66.0 Ĵ + ver 0220AC0220EC Ĵ + date 050620050620 Ĵ +Ľ + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 1 +[name] Florin +[desc] CVS management rules +[hist] 2006-04-30 initial version + +Please do not commit on CVS temporary files or those made by development tools + (IDEs). Eg: *.suo/aps/opt/plg/ncb/exp +Keep it clean and before commiting a new module see the previous structure and + naming rules. If unsure about how to do any opperation please ASK. please ASK! +There's no rush ;) +Also, I'm considering switching to SVN, as CVS seems to be *abandoned* by + sourceforge.net +Any change to sources has to be commited to the public CVS. The risk of + stealing is faced by any open-source developer - the difference is the + quality! The original will always stand up ;) +Try not to break the source by your patches. Although linux and 64-bit versions + are not maintained atm, your changes should be done with all versions in mind. +Happy coding :) diff --git a/branches/pcsx2_0.9.1/Docs/efpchangesv0.9linux.txt b/branches/pcsx2_0.9.1/Docs/efpchangesv0.9linux.txt new file mode 100644 index 0000000..f32471b --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/efpchangesv0.9linux.txt @@ -0,0 +1,112 @@ +Changes made to make v0.9 work in Linux: + +Common.h - PCSX2_MULTICORE undefined. + In my version of linux, spinlocks are bleeding edge calls, and not +implemented as standard. There may be a #define that can be used, but +as it would likely include either a kernel rebuild or thread library, +I hadn't bothered. + +Misc.c - SYNC_LOGGING undefined + I suspect because of PCSX2_MULTICORE being undefined, "g_mtxLog" +didn't get defined either. + +Interpreter.c - all "_controlfp" calls commented out. + I suspect a .h file is missing for the above call. + +Vif.c - Control of MMX, SSE, SSE2 (and SSE3) instructions. + Presence of the above CPU intrinsic calls can be detected using +__MMX__, __SSE__, __SSE2__, and __SSE3__. Header dependancies are +as follows: + __MMX__ can stand alone. + __SSE__ needs __MMX__. + __SSE2__ needs __SSE__ (which needs __MMX__) + __SSE3__ needs __SSE2__ and __SSE__ (which needs __MMX__) + Each of these flags can be used to load their own set of functions +as well as loading all functions in the dependant headers... + __MMX__ - #include + __SSE__ - #include + __SSE2__ - #include + __SSE3__ - #include + Since no tests for the above flags were conducted before loading +emmintrin.h, I blocked out that section of code with an "#if 0" line. + +IPU/IPU.c - After finding out that a dozen mutexes were set here without + PCSX2_MULTICORE blocking, I went back to Common.h and turned back on +PCSX2_MULTICORE. I knew now I would have to hunt down all instances of +spinlocks and replace them with straight mutexes. + R5900.h lines 150-167 - Spinlock defines commented out. + R5900.c lines 32-38 - Spinlock define commented out. + +IPU/IPU.c - invalid initializer - NULL on pthread_mutex_t / pthread_cond_t + Separated the variables initialized. Hunted up valid initializers in +pthread documentation in Linux. + __declspec() - In Common.h, I told Linux to ignore all references to this +function. #pragma pack(16) and/or __attribute__ ((?)) might be a better +choice for this. A couple of compiler flags also control byte alignment. +For dynamically allocatable blocks, memalign() might work. + Note: for 64 bit compiles (like athlon64), 16 byte alignment is assumed. + EBUSY undeclared - This relates to the define DESTROY_MUTEX in Common.h. +Included in Common.h so EBUSY is defined. + __forceinline - placed "#define __forceinline inline" in Common.h as Linux +has no equivlent (that I know of) to this. + +IPU/Idct.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +IPU/Mpeg.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +VifDma.c - See Vif.c for complaints about __SSE__ detection. + +Linux/Config.c - no member "PadHack" + Seems it was removed from the "Config" structure. Commented out the +set/get commands for it. + +x86/iVU0micro.c line 494 - too many arguments in 'vurecAnalyzeBlock' + This might be leftover code from a testrun. I removed the extra 'old' +variables. + +x86/iVU1micro.c - all "_controlfp" commands commented out. + See Interpreter.c above for details. + +Then I finally got to the Link portion of the compiler... + +Hw.o: + _aligned_malloc() is not defined in Linux. memalign() was obsoleted. +POSIX now recommends posix_memalign(boundary, size) from +for accurate boundary allocation... and working free() calls. + _aligned_free(), companion to the call above, is also not defined in +Linux. Fortunately, posix_memalign() only needs a free() call. + Both of the above was defined in Common.h + +IPU/IPU.o: + couldn't find pthread_... calls. Added -lpthread to $(LIBS) in Makefile + +FPU.o: + Certain math calls were added from . FPU2.cpp compiles those +calls... and adds a C interface to get to them. Included FPU2.o in the +object list in the Makefile. + +R5900.o: + pthread_mutex__unlock()? I thought it was just 1 underline there. Didn't +take any chances, though. Put in a define in Common.h to change it to +pthread_mutex_unlock(). + +Left to fix: + +x86/iVUmicro.o: + __assume(0): I don't know what this is used for. + +R5900.o: + InterlockedAnd(), InterlockedExchange(): Are these grouped mutex calls? + +VifDma.o: + SetNewMask(), g_vif1Masks(), g_vif0Masks(): + These were sliced off when I cut SSE off. Some work could bring them +back in, if they're needed for non-MMX/SSE/SSE2/SSE3 refrencing... + + +This doesn't even guarentee that once just these problems are fixed, the +compiled program will run. I only looked at compiling/linking. + +efp - Feb 16, 2006 diff --git a/branches/pcsx2_0.9.1/Docs/pcsx2_faq.txt b/branches/pcsx2_0.9.1/Docs/pcsx2_faq.txt new file mode 100644 index 0000000..4b8cdb8 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/pcsx2_faq.txt @@ -0,0 +1,229 @@ + + PPPP CCCC SSS X X 2222 + P P C C S S X X 2 2 + P P C S X X 2 + P P C S X X 2 + P P C S X X 2 + P P C SSS X 2 + PPPP C S X X 2 + P C S X X 2 + P C S X X 2 + P C C S S X X 2 + P CCCC SSS X X 2222222 + +**************** +*PCSX2 FAQ v0.1* +**************** + +This FAQ has been written for PCSX2 v0.6 + +FAQ Written by: CKemu & shadow +_________________________________________________________ + +Q: What is PCSX2? + +A: PCSX2 is a WIP PS2 (PlayStation 2) emulator, written by +linuzappz, shadow, florin. basara, asadr, goldfinger. PCSX2 is +constantly WIP (work in progress), and is in the early +stages of development (so don't expect much yet ;) ). + +Q: Why doesn't XYZ game work? + +A: PCSX2 is able to get many games to show 'screens'. Some of the games can reach ingame +and less more can be consider playable. Speed is too slow on many of them so 'viewable' is +a beter way to describe it :) + + +Q: Why don't these games work? + +A: PCSX2 is in the early stages of development. It can run some games (many of them without glitches) +but the speed issue prevent us of making the emu more compatible. + +Q: Where abouts do I find these demos? + +A:You can find some demos at http://pcsx2.ngemu.com or +http://ps2dev.livemedia.com.au. There are proberbly more +sites with PS2 homebrew demos. + +Q: Does PCSX2 require a 'real' PS2 BIOS. + +A: PCSX2 can use a 'real' BIOS, and is preferable to HLE +BIOS as it is more compatible. But HLE does work well +with many homebrew demos. + +Q: Why not use HLE? + +A: HLE is a difficult thing to do for a PS2. Game +developers use their own modules for each game. That +would mean we would have to HLE each module. This would +be a massive task, and not a good idea, as emulating +the real BIOS will mean compatibility with all released +games. + +Q: Where do I get a BIOS? + +A: You can dump the BIOS from your own PS2, DO NOT ask us +or anyone else for a BIOS, the BIOS is copyright of SONY +and is illegal to download, so we won't help you with +that. + +Q: I try to run a game, or the BIOS, but nothing happens! + +A: If no BIOS screen shows from attempting to run a +CD/DVD, your BIOS maybe incorrect. Go to +'config>configure', and under the BIOS menu, check that +firstly you haven't got the HLE BIOS selected, if you do +change to a 'real' BIOS. If you have a 'real' BIOS +selected and it still doesn't work, check that NO +percentage is written next to the BIOS, if it is for +instance "40%", your BIOS is to small (by 60%), or +corrupt (by 60%), you may need to redump it. Also if no +'real' BIOS is listed, check its not compressed 'eg +*.zip / *.rar' and extract it to the BIOS dir (note +sub-folders NOT supported, it must be in /BIOS/). + +If that is not the case, your BIOS isn't an actual PS2 +BIOS. To ensure that doesn't happen, dump your own ;) + +Q: I see lots of glitches with games/demos, why? + +A: Incomplete emulation of the GS, Vector Units etc, this +is a WIP emulator, and will have many bugs for some time, +until more is known about the PS2 hardware. Things +generally improve with each release, so you never know, +it may be fixed in the next release. + +Q: How can I help fix these bugs? + +A: Report these bugs to us, post at the offical PCSX2 +forums at http://www.ngemu.com. Make a post describing +the bug/glitch, perhaps with a screenshot showing it, +and details on your system setup, what plugins your +using etc. + +If you find any other bugs, with regards to the debugger, +plugins, or differences between what you see in the +emulator and a real PS2, feel free to email us. + +Q: How can I help develop for PCSX2? + +A: You can find the open-source plugins at +http://pcsx2.ngemu.com , coding a GS plugin or and SPU2 +plugin would help us greatly. Also if you have any +technical information on the PS2, please email us, +anyhelp is greatly appreciated. + +Q: Your emulator sucks!! I don't want to use it! + +A: Then don't, buy a real PS2. If you don't like it, +just don't and there is no need to tell us you don't +like it, the PCSX2 team put alot of hardwork into this +emulator, and don't care to know. + +Q: Can you give me some more 'technical' answers? + +A: A technical FAQ would be massive, and take months to +write. Instead email shadow / linuz with your questions. + +Q: When is the next release? + +A: The next release will happen when there is something +to show, internal changes, and technical changes don't +mean anything to the user, if they don't see something. +Pestering us will make no difference :P + +Q: GSsoft is s..l..o..w!! + +A: Then use one of the OpenGL plugins found at our site +http://pcsx2.ngemu.com or the GStaris plugin +( http://gstaris.ngemu.com ). + +Q: The emulator even with GStaris / GSmax is slow! Why? + +A: First of all, the PS2 is a powerfull piece of +hardware, and will require a powerfull machine to achive +NEAR correct speeds, + +Given that PCSX2 does not run any 'complex' commercial +games, it is hard to judge the system requirements that +will be eventually needed. Plugins and Emulator will get +faster as new releases are made, but you can improve +preformance by turning OFF "Enable Console Output" and +"Enable Interpreter CPU" under 'config>CPU>' in the menu. + +Q: Do I need a DVD drive? + +A: Yes, if you want to read a DVDrom you will need a DVD + drive, many PS2 games are written to CDrom, so its not +essential, unless you have a DVD based game you wish to +try. + +You can also use 'Linuz's CDVD ISO' plugin to run PS2 +games in ISO / BIN format from your HDD. Note only +NTFS Format drives (eg not FAT32) can store greater than +4GB in a single file. + +Q: I hear no sound! + +A: SPU2 Plugins are being worked on by a few coders, but +as of now the only SPU2 plugin is nullSPU, which outputs +no sound, If you are a coder, and feel you can help with +SPU2, please email us. + +Q: Where can I get help!!! + +A: You can get help from the people over at +http://www.ngemu.com or on IRC. Using an IRC client, log +onto #PCSX2 or #NGEMU (EFnet). You can politly ask for +help there (No BIOS / ROM / ISO requests, or you shall be +banned). If you cannot get help there, email the PCSX2 +team. + +_________________________________________________________ + +This FAQ was based on shadow's original FAQ, so thanks to +him. This was written to clear up some of the basic +questions you may have, and I hope it was of help. + +Written with very little sleep and too much coffee, so +please excuse the mistakes, they will be fixed shortly :D + +************ +*Thanks to:* +************ + +The PCSX2 team for making me a betatester, and providing us +with a fantastic PS2 emulator, and the opportinity for me to +work on SPU2 (highly WIP :P ) + +shadow, Linuzappz, Absolute0, [Tyranid], F|res, Roor, +Goldfinger, Florin, basara, asadr, CpUmaster, snake785, +mike9010, bositman, DWatcher, Keith, Martin64.....and many +more I am sure :D + +My lady, Lucy. Without her I would be lost. + +Coffee, where would we be without coffee :D + +********** +*Contact:* +********** + +If you think I should add something to this FAQ, or you +spotted a bug, you can contact me (CKemu) via IRC in +the #PCSX2 (EFnet) channel. + +You can contact the authors via: +http://pcsx2.ngemu.com (homepage) +http://www.pcsx2.net (homepage) +http://www.ngemu.com (offical forums) + +or on IRC: + +#PCSX2 (EFnet) + +Enjoy PCSX2!! + +Best Regards CKemu ( http://www.ckemu.com ). + +/EOF/ \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/Docs/specs.tex b/branches/pcsx2_0.9.1/Docs/specs.tex new file mode 100644 index 0000000..aca2581 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/specs.tex @@ -0,0 +1,159 @@ +\documentclass[10pt]{article} + +\begin{document} +\section{...stuff...} +-order the plugins are started\\ +-platform dependent stuff, calling convention\\ + +\section{Generic functions} +The following three functions will be present in all the plugin libraries, + in order to be recognized as valid PS2E plugins. They will help + the emulator to find a plugin capabilities. + +\subsection{PS2EgetLibType} +\begin{quote}\texttt{unsigned int} PS2EgetLibType(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibType] returns the type of the plugin. + In fact it indicates the APIs supported by the dynamic library. + The returned value can be one of: +\begin{itemize} +\item PS2E\_LT\_GS 0x01 +\item PS2E\_LT\_PAD 0x02 +\item PS2E\_LT\_SPU2 0x04 +\item PS2E\_LT\_CDVD 0x08 +\item PS2E\_LT\_DEV9 0x10 +\end{itemize} +Currently, these are the only plugin types supported. Note that the values + can be ORed. +\end{description} + + + +\subsection{PS2EgetLibVersion2} +\begin{quote}\texttt{unsigned int} PS2EgetLibVersion2(\texttt{unsigned int} + type);\end{quote} + +\begin{description} +\item[PS2EgetLibVersion2] returns a combination of version numbers. +Parameter \emph{type} is used to select the functions set for which + the emulator requests version information. See \texttt{PS2EgetLibType} + for the values of this parameter. + +The 5 APIs and their corresponding specs have changed over time. + In order to prevent crashes and incompatibilities, a spec version have + been introduced as the highest 16 bits of the returned value. +\begin{itemize} +\item PS2E\_GS\_VERSION 0x0002 +\item PS2E\_PAD\_VERSION 0x0002 +\item PS2E\_SPU2\_VERSION 0x0002 +\item PS2E\_CDVD\_VERSION 0x0003 +\item PS2E\_DEV9\_VERSION 0x0001 +\end{itemize} +Notice that when the specs do change \texttt{and} the compatibility is broken, + this version number is increased. The emulator loading code will support + only one version for a certain library type at a time. If the internal + version and plugin API version does not match, the plugin + will not be loaded nor used. + +The low half of the returned value reflects the version of the plugin itself. + A major.minor versioning scheme is used on the two bytes like this: +\begin{verbatim} +...//code +return (PS2E_CDVD_VERSION<<16) | (0<<8) | (67); //version 0.67 +\end{verbatim} +\end{description} + + + +\subsection{PS2EgetLibName} +\begin{quote}\texttt{char*} PS2EgetLibName(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibName] returns a string that contains a short\footnote{ +less then 30 chars in one line} name. The string is stored + in the plugin and will be used to represent the plugin in a config dialog. +\end{description} + + + + + +\section{CDVD functions} +This section describes the functions that corresponds to CDVD\footnote{short for CD/DVD} +API - type PS2E\_LT\_CDVD(0x08). + These specs are for PS2E\_CDVD\_VERSION(0x0003). + +\subsection{CDVDinit} +\begin{quote}\texttt{int} CDVDinit(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDinit] does the initialization of the CDVD interface. + It is the first function called; so, it can be used to do all the + init stuff such as reading saved configuration, one-time hardware init and + preparing the internal structures, tables, etc\ldots + If an error is found the function will return -1, otherwise 0. +\end{description} + + + +\subsection{CDVDshutdown} +\begin{quote}\texttt{void} CDVDshutdown(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDshutdown] is called when the emulator is closed. Do now the freeing + operations. DO NOT FORGET TO FREE the resources used. The OS will probably + free the garbage left, but some pieces of hardware might need a + ``deinitialization'' procedure in order to work next time the emulator + is run. Imagine that the user will choose another plugin to run with + next time instead of yours, do not cause troubles. +\end{description} + + + +\subsection{CDVDopen} +\begin{quote}\texttt{int} CDVDopen(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDopen] is called when the emulation starts. + It is recommended that functions called from now on (until + \texttt{CDVDclose} is met) to spend few processing time. Avoid calling + blocking functions and if you do, the user should be notified visualy. + Report errors by return value and warrings using a log. + If an error is found the function will return -1 and the emulation stops, + otherwise 0. + +Do not report errors using message boxes while the emu runs, the GS plugin + might use a display mode that can cause troubles to windowing system + in showing your message. +\end{description} + + + +\subsection{CDVDclose} +\begin{quote}\texttt{void} CDVDclose(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDclose] is called when the emulation is stopped. Some of the + resources that you aquired with \texttt{CDVDstart} have to be released now + in order that other programs to use them. If you locked the CD/DVD tray, + unlock it so the user can change the disc. +\end{description} + + + +\subsection{CDVDreadTrack} +\begin{quote}\texttt{int} CDVDreadTrack(\texttt{unsigned int} + lsn, \texttt{int} mode);\end{quote} + +\begin{description} +\item[CDVDreadTrack] is the function that performs the read of \texttt{a} + sector from the CD/DVD. Parameter \emph{lsn} specifies the absolute value + of the sector number in linear addressing mode without \emph{lead-in}\footnote{i.e.\ +without leading 150 sectors == 2 seconds}. Usualy, the plugin will read + a full sector of 2352 bytes in its internal buffer. + The second parameter tells what port of ... +\end{description} + +\end{document} + diff --git a/branches/pcsx2_0.9.1/Docs/threads.txt b/branches/pcsx2_0.9.1/Docs/threads.txt new file mode 100644 index 0000000..1da8358 --- /dev/null +++ b/branches/pcsx2_0.9.1/Docs/threads.txt @@ -0,0 +1,34 @@ + OK -> done & tested +---- -> not applicable +xxxx -> dummy +32CreateThread OK ---- +33DeleteThread ---- +34StartThread ---- OK +35ExitThread ---- +36ExitDeleteThread ---- +37TerminateThread ---- +38iTerminateThread +39DisableDispatchThread xxxxxxxx +40EnableDispatchThread xxxxxxxx +41ChangeThreadPriority ---- OK +42iChangeThreadPriority OK ---- +43RotateThreadReadyQueue ---- +44iRotateThreadReadyQueue +45ReleaseWaitThread ---- +46iReleaseWaitThread +47GetThreadId OK ---- +48ReferThreadStatus ͻ OK ---- +49iReferThreadStatus ͼ OK ---- +50SleepThread ---- +51WakeupThread ---- +52iWakeupThread +53CancelWakeupThread ͻ done---- +54iCancelWakeupThread ͼ done---- +55SuspendThread ͻ +56iSuspendThread ͼ +57ResumeThread ---- +58iResumeThread +59JoinThread xxxxxxxx +60RFU060_InitializeMainThread OK ---- +61RFU061_InitializeHeapArea OK ---- +62EndOfHeap OK ---- \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/EEregs.h b/branches/pcsx2_0.9.1/EEregs.h new file mode 100644 index 0000000..a25b709 --- /dev/null +++ b/branches/pcsx2_0.9.1/EEregs.h @@ -0,0 +1,40 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EEREGS_H__ +#define __EEREGS_H__ + +#define at cpuRegs.GPR.n.at +#define k0 cpuRegs.GPR.n.k0 +#define k1 cpuRegs.GPR.n.k1 +#define v0 cpuRegs.GPR.n.v0 +#define v1 cpuRegs.GPR.n.v1 +#define a0 cpuRegs.GPR.n.a0 +#define a1 cpuRegs.GPR.n.a1 +#define a2 cpuRegs.GPR.n.a2 +#define a3 cpuRegs.GPR.n.a3 +#define t0 cpuRegs.GPR.n.t0 +#define s0 cpuRegs.GPR.n.s0 +#define gp cpuRegs.GPR.n.gp +#define fp cpuRegs.GPR.n.s8 +#define sp cpuRegs.GPR.n.sp +#define ra cpuRegs.GPR.n.ra + +#define pc0 cpuRegs.pc + +#endif /* __EEREGS_H__ */ diff --git a/branches/pcsx2_0.9.1/Elfheader.c b/branches/pcsx2_0.9.1/Elfheader.c new file mode 100644 index 0000000..35c74b9 --- /dev/null +++ b/branches/pcsx2_0.9.1/Elfheader.c @@ -0,0 +1,631 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include //2002-09-28 (Florin) +#include + +#include "Common.h" +#include "CDVDisodrv.h" + +typedef struct { + u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) + u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE + u16 e_machine; //Processor: 8=MIPS R3000 + u32 e_version; //Version: 1=current + u32 e_entry; //Entry point address + u32 e_phoff; //Start of program headers (offset from file start) + u32 e_shoff; //Start of section headers (offset from file start) + u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips + u16 e_ehsize; //ELF header size (0x34 = 52 bytes) + u16 e_phentsize; //Program headers entry size + u16 e_phnum; //Number of program headers + u16 e_shentsize; //Section headers entry size + u16 e_shnum; //Number of section headers + u16 e_shstrndx; //Section header stringtable index +} ELF_HEADER; + +typedef struct { + u32 p_type; //see notes1 + u32 p_offset; //Offset from file start to program segment. + u32 p_vaddr; //Virtual address of the segment + u32 p_paddr; //Physical address of the segment + u32 p_filesz; //Number of bytes in the file image of the segment + u32 p_memsz; //Number of bytes in the memory image of the segment + u32 p_flags; //Flags for segment + u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment +} ELF_PHR; + +/* +notes1 +------ +0=Inactive +1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 +2=Dynamic linking +3=Interpreter. The array element must specify a path name +4=Note. The array element must specify the location and size of aux. info +5=reserved +6=The array element must specify location and size of the program header table. +*/ + +typedef struct { + u32 sh_name; //No. to the index of the Section header stringtable index + u32 sh_type; //See notes2 + u32 sh_flags; //see notes3 + u32 sh_addr; //Section start address + u32 sh_offset; //Offset from start of file to section + u32 sh_size; //Size of section + u32 sh_link; //Section header table index link + u32 sh_info; //Info + u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. + u32 sh_entsize; //Fixed size entries. +} ELF_SHR; +/* +notes 2 +------- +Type: +0=Inactive +1=PROGBITS +2=SYMTAB symbol table +3=STRTAB string table +4=RELA relocation entries +5=HASH hash table +6=DYNAMIC dynamic linking information +7=NOTE +8=NOBITS +9=REL relocation entries +10=SHLIB +0x70000000=LOPROC processor specifc +0x7fffffff=HIPROC +0x80000000=LOUSER lower bound +0xffffffff=HIUSER upper bound + +notes 3 +------- +Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) +1=Write section contains data the is be writeable during execution. +2=Alloc section occupies memory during execution +4=Exec section contains executable instructions +0xf0000000=Mask bits processor-specific +*/ + +typedef struct { + u32 st_name; + u32 st_value; + u32 st_size; + u8 st_info; + u8 st_other; + u16 st_shndx; +} Elf32_Sym; + +#define ELF32_ST_TYPE(i) ((i)&0xf) + +typedef struct { + u32 r_offset; + u32 r_info; +} Elf32_Rel; + +//unfinished!!!! + +char *sections_names; + +ELF_HEADER *elfHeader; +ELF_PHR *elfProgH; +ELF_SHR *elfSectH; +char *name; +u8 *elfdata; +u32 elfsize; + +struct stat sbuf; +struct TocEntry toc; + +//2002-09-19 (Florin) +char args[256]="ez.m2v"; //to be accessed by other files +unsigned int args_ptr; //a big value; in fact, it is an address + +//in a0 is passed the address of the command line args, +//i.e. a pointer to an area like this: +//+00 unknown/unused +//+04 argc; number of arguments +//+08 argv[0]; address of the first parameter - program name (char*) - +//+08 argv[1]; address of the second parameter (char*) | +//+0C argv[2]; and so on | +//........ | +//+08+4*argc the program name(first param) <-- +//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args' +// see above 'char args[256];' +unsigned int parseCommandLine( char *filename ) +{ + if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) ) + { // 4 + 4 + 256 + char * p; + int argc, + i; + + args_ptr -= 256; + if ( args_ptr < 0 ) + { + return 0; + } + args[ 255 ] = 0; + memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 ); //params 1, 2, etc copied + memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) ); +#ifdef __WIN32__ + p = strrchr( filename, '\\' ); +#else //linux + p = strrchr( filename, '/' ); +#endif + if ( p ) + { + p++; + } + else + { + p = filename; + } + args_ptr -= strlen( p ) + 1; + if ( args_ptr < 0 ) + { + return 0; + } + strcpy( &PS2MEM_BASE[ args_ptr ], p ); //fill param 0; i.e. name of the program + + for ( i = strlen( p ) + 1 + 256, argc = 0; i > 0; i-- ) + { + while ( i && ( ( PS2MEM_BASE[ args_ptr + i ] == 0 ) || ( PS2MEM_BASE[ args_ptr + i ] == 32 ) ) ) + { + i--; + } + if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ' ) + { + PS2MEM_BASE[ args_ptr + i + 1 ] = 0; + } + while ( i && ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i] != 32 ) ) + { + i--; + } + if ( ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i ] != 32 ) ) + { //i==0 + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i; + } + else + { + if ( ( PS2MEM_BASE[ args_ptr + i + 1 ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i + 1 ] != 32 ) ) + { + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1; + } + } + } + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all + + return ( args_ptr - argc * 4 - 8 ); + } + + return 0; +} +//--------------- + +int readFile( char *Exepath, char *ptr, u32 offset, int size ) { + FILE *f; + int fi; + + if ((strnicmp( Exepath, "cdrom0:", strlen("cdrom0:")) == 0) || + (strnicmp( Exepath, "cdrom1:", strlen("cdrom0:")) == 0)) { + if ((u32)offset >= toc.fileSize) return -1; + fi = CDVDFS_open(Exepath + strlen("cdromN:"), 1);//RDONLY + if (fi < 0) return -1; + CDVDFS_lseek(fi, offset, SEEK_SET); + size = CDVDFS_read(fi, ptr, size); + CDVDFS_close(fi ); + } else { + f = fopen(Exepath, "rb"); + if (f == NULL) return -1; + if ( offset >= (u64)sbuf.st_size) return -1; + fseek(f, offset, SEEK_SET); + size = fread(ptr, 1, size, f); + fclose(f); + } + + return size; +} + +int loadHeaders( char *Exepath ) { + elfHeader = (ELF_HEADER*)elfdata; + + if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) { + SysMessage( "size of section header not standard\n" ); + } + + if((elfHeader->e_shnum * elfHeader->e_shentsize) != 0) { + elfSectH = (ELF_SHR *) malloc( elfHeader->e_shnum * elfHeader->e_shentsize ); + } else { + elfSectH = NULL; + } + + if ( ( elfHeader->e_phnum * elfHeader->e_phentsize ) != 0 ) { + elfProgH = (ELF_PHR *) malloc( elfHeader->e_phnum * elfHeader->e_phentsize ); + } else { + elfProgH = NULL; + } + +#ifdef ELF_LOG + ELF_LOG( "type: " ); +#endif + switch( elfHeader->e_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", elfHeader->e_type ); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG( "no file type" ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG( "relocatable" ); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG( "executable" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG( "\n" ); + ELF_LOG( "machine: " ); +#endif + switch ( elfHeader->e_machine ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown" ); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG( "mips_rs3000" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("version: %d\n",elfHeader->e_version); + ELF_LOG("entry: %08x\n",elfHeader->e_entry); + ELF_LOG("flags: %08x\n",elfHeader->e_flags); + ELF_LOG("eh size: %08x\n",elfHeader->e_ehsize); + ELF_LOG("ph off: %08x\n",elfHeader->e_phoff); + ELF_LOG("ph entsiz: %08x\n",elfHeader->e_phentsize); + ELF_LOG("ph num: %08x\n",elfHeader->e_phnum); + ELF_LOG("sh off: %08x\n",elfHeader->e_shoff); + ELF_LOG("sh entsiz: %08x\n",elfHeader->e_shentsize); + ELF_LOG("sh num: %08x\n",elfHeader->e_shnum); + ELF_LOG("sh strndx: %08x\n",elfHeader->e_shstrndx); + + ELF_LOG("\n"); +#endif + + return TRUE; +} + + +BOOL loadProgramHeaders( char *Exepath ) +{ + int i; + + if ( elfHeader->e_phnum == 0 ) + { + return TRUE; + } + + // is this critical, or warning? + if ( elfHeader->e_phentsize != sizeof( ELF_PHR ) ) + { + SysMessage( "size of program header not standard\n" ); + } + + elfProgH = (ELF_PHR*)&elfdata[elfHeader->e_phoff]; + + for ( i = 0 ; i < elfHeader->e_phnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Program Header\n" ); + ELF_LOG( "type: " ); +#endif + switch ( elfProgH[ i ].p_type ) { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", (int)elfProgH[ i ].p_type ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("load"); +#endif + if (elfProgH[ i ].p_offset < elfsize) { + int size; + + if ((elfProgH[ i ].p_filesz + elfProgH[ i ].p_offset) > elfsize) { + size = elfsize - elfProgH[ i ].p_offset; + } else { + size = elfProgH[ i ].p_filesz; + } + memcpy(&PS2MEM_BASE[elfProgH[ i ].p_paddr & 0x1ffffff], + &elfdata[elfProgH[ i ].p_offset], + size); +#ifdef ELF_LOG + ELF_LOG("\t*LOADED*"); +#endif + } + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset); + ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr); + ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr); + ELF_LOG("file size: %08x\n",elfProgH[i].p_filesz); + ELF_LOG("mem size: %08x\n",elfProgH[i].p_memsz); + ELF_LOG("flags: %08x\n",elfProgH[i].p_flags); + ELF_LOG("palign: %08x\n",elfProgH[i].p_align); + ELF_LOG("\n"); +#endif + } + + return TRUE; +} + + +BOOL loadSectionHeaders( char * Exepath ) +{ + int i; + int i_st = -1; + int i_dt = -1; + + if (elfHeader->e_shnum == 0 || + elfHeader->e_shoff > elfsize) { + return TRUE; + } + + elfSectH = (ELF_SHR*)&elfdata[elfHeader->e_shoff]; + + if ( elfHeader->e_shstrndx < elfHeader->e_shnum ) { + sections_names = (char *)&elfdata[elfSectH[ elfHeader->e_shstrndx ].sh_offset]; + } + + for ( i = 0 ; i < elfHeader->e_shnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ elfSectH[ i ].sh_name ] ); +#endif + if ( elfSectH[i].sh_flags & 0x2 ) { + //2002-09-19 (Florin) + args_ptr = min( args_ptr, elfSectH[ i ].sh_addr & 0x1ffffff ); + //--------------- +/* if (elfSectH[i].sh_offset < elfsize) { + int size; + + if ((elfSectH[i].sh_size + elfSectH[i].sh_offset) > elfsize) { + size = elfsize - elfSectH[i].sh_offset; + } else { + size = elfSectH[i].sh_size; + } + memcpy(&PS2MEM_BASE[ elfSectH[ i ].sh_addr &0x1ffffff ], + &elfdata[elfSectH[i].sh_offset], + size); + } +#ifdef ELF_LOG + ELF_LOG( "\t*LOADED*" ); +#endif*/ + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("type: "); +#endif + switch ( elfSectH[ i ].sh_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG("unknown %08x",elfSectH[i].sh_type); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG("null"); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("progbits"); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG("symtab"); +#endif + break; + + case 0x3: +#ifdef ELF_LOG + ELF_LOG("strtab"); +#endif + break; + + case 0x4: +#ifdef ELF_LOG + ELF_LOG("rela"); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG("no bits"); +#endif + break; + + case 0x9: +#ifdef ELF_LOG + ELF_LOG("rel"); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("flags: %08x\n", elfSectH[i].sh_flags); + ELF_LOG("addr: %08x\n", elfSectH[i].sh_addr); + ELF_LOG("offset: %08x\n", elfSectH[i].sh_offset); + ELF_LOG("size: %08x\n", elfSectH[i].sh_size); + ELF_LOG("link: %08x\n", elfSectH[i].sh_link); + ELF_LOG("info: %08x\n", elfSectH[i].sh_info); + ELF_LOG("addralign: %08x\n", elfSectH[i].sh_addralign); + ELF_LOG("entsize: %08x\n", elfSectH[i].sh_entsize); +#endif + // dump symbol table + + if ( elfSectH[ i ].sh_type == 0x02 ) + { + i_st = i; + i_dt = elfSectH[i].sh_link; + } + } + + if ( ( i_st >= 0 ) && ( i_dt >= 0 ) ) + { + char * SymNames; + Elf32_Sym * eS; + + SymNames = (char*)&elfdata[elfSectH[ i_dt ].sh_offset]; + eS = (Elf32_Sym*)&elfdata[elfSectH[ i_st ].sh_offset]; + SysPrintf("found %d symbols\n", elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym )); + + for ( i = 1; i < (int)( elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym ) ); i++ ) { + if ( ( eS[ i ].st_value != 0 ) && ( ELF32_ST_TYPE( eS[ i ].st_info ) == 2 ) ) { +// SysPrintf("%x:%s\n", eS[i].st_value, &SymNames[eS[i].st_name]); + disR5900AddSym( eS[i].st_value, &SymNames[ eS[ i ].st_name ] ); +/* if (!strcmp(&SymNames[eS[i].st_name], "sceSifCheckStatRpc")) { + psMu32(eS[i].st_value & 0x1ffffff) = (0x3b << 26) | 1; + SysPrintf("found sceSifCheckStatRpc!!\n"); + }*/ + } + } + } + + return TRUE; +} + + +int loadElfFile(char *filename) { + char str[256]; + char str2[256]; + u32 crc; + u32 i; + + SysPrintf("loadElfFile: %s\n", filename); + if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) && + strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) { + if ( stat( filename, &sbuf ) != 0 ) + return -1; + elfsize = sbuf.st_size; + } else { + CDVDFS_init( ); + if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 ) + return -1; + elfsize = toc.fileSize; + } + + SysPrintf("loadElfFile: %d\n", elfsize); + elfdata = (u8*)malloc(elfsize); + if (elfdata == NULL) return -1; + readFile(filename, elfdata, 0, elfsize); + +/* { + FILE *f = fopen("game.elf", "wb"); + fwrite(elfdata, 1, elfsize, f); + fclose(f); + }*/ + + //2002-09-19 (Florin) + args_ptr = 0xFFFFFFFF; //big value, searching for minimum + //------------------- + loadHeaders( filename ); + cpuRegs.pc = elfHeader->e_entry; //set pc to proper place + loadProgramHeaders( filename ); + loadSectionHeaders( filename ); + +#ifdef ELF_LOG + ELF_LOG( "PC set to: %8.8lx\n", cpuRegs.pc ); +#endif + cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; + cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok + + //2002-09-19 (Florin) + cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); + //--------------- + + for ( i = 0; i < 0x100000; i++ ) { + if ( strcmp( "rom0:OSDSYS", PSM( i ) ) == 0 ) { + strcpy( PSM( i ), filename ); + SysPrintf( "addr %x \"%s\" -> \"%s\"\n", i, "rom0:OSDSYS", filename ); + } + } + + //CRC + for (i=0, crc=0; i +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +// Helper Macros +//**************************************************************** +#define _Ft_ ( ( cpuRegs.code >> 16 ) & 0x1F ) +#define _Fs_ ( ( cpuRegs.code >> 11 ) & 0x1F ) +#define _Fd_ ( ( cpuRegs.code >> 6 ) & 0x1F ) + +#define _FtValf_ fpuRegs.fpr[ _Ft_ ].f +#define _FsValf_ fpuRegs.fpr[ _Fs_ ].f +#define _FdValf_ fpuRegs.fpr[ _Fd_ ].f +#define _FAValf_ fpuRegs.ACC.f + +#define _ContVal_ fpuRegs.fprc[ 31 ] + +// Testing +#define _FtValUl_ fpuRegs.fpr[ _Ft_ ].UL +#define _FsValUl_ fpuRegs.fpr[ _Fs_ ].UL +#define _FdValUl_ fpuRegs.fpr[ _Fd_ ].UL +#define _FAValUl_ fpuRegs.ACC.UL + +//**************************************************************** + +void COP1() { +#ifdef FPU_LOG + FPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP1PrintTable[_Rs_](); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + + + +void LWC1() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);// ((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memRead32(addr, &fpuRegs.fpr[_Rt_].UL); +} + +void SWC1() { + s32 addr; + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);//((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memWrite32(addr, fpuRegs.fpr[_Rt_].UL); +} + +void COP1_BC1() { + Int_COP1BC1PrintTable[_Rt_](); +} + +void COP1_S() { + Int_COP1SPrintTable[_Funct_](); +} + +void COP1_W() { + Int_COP1WPrintTable[_Funct_](); +} + +void COP1_Unknown() { +#ifdef FPU_LOG + FPU_LOG("Unknown FPU opcode called\n"); +#endif +} + + + +void MFC1() { + if ( !_Rt_ ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)_FsValUl_; +} + +void CFC1() { + if ( !_Rt_ || ( _Fs_ != 0 && _Fs_ != 31 ) ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)fpuRegs.fprc[_Fs_]; +} + +void MTC1() { + _FsValUl_ = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +void CTC1() { + if(_Fs_!=31) return; + fpuRegs.fprc[_Fs_] = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +#define C_cond_S(cond) \ + _ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \ + ( _ContVal_ | 0x00800000 ) : \ + ( _ContVal_ & ~0x00800000 ); + +void C_F() { _ContVal_ &= ~0x00800000;} //clears C regardless +void C_EQ() { C_cond_S(==); } +void C_LT() { C_cond_S(<); } +void C_LE() { C_cond_S(<=); } + +#define BC1(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } +void BC1F() { BC1(==); } +void BC1T() { BC1(!=); } + +#define BC1L(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } else cpuRegs.pc += 4; +void BC1FL() { BC1L(==); } // Equal to 0 +void BC1TL() { BC1L(!=); } // different from 0 + + +void ADD_S() { _FdValf_ = _FsValf_ + _FtValf_; } +void SUB_S() { _FdValf_ = _FsValf_ - _FtValf_; } +void MUL_S() { _FdValf_ = _FsValf_ * _FtValf_; } +void MOV_S() { _FdValf_ = _FsValf_; } +void NEG_S() { _FdValf_ = -_FsValf_; } +void ADDA_S() { _FAValf_ = _FsValf_ + _FtValf_; } +void SUBA_S() { _FAValf_ = _FsValf_ - _FtValf_; } +void MULA_S() { _FAValf_ = _FsValf_ * _FtValf_; } +void MADD_S() { _FdValf_ = _FAValf_ + ( _FsValf_ * _FtValf_ ); } +void MSUB_S() { _FdValf_ = _FAValf_ - ( _FsValf_ * _FtValf_ ); } +void MADDA_S() { _FAValf_ += _FsValf_ * _FtValf_; } +void MSUBA_S() { _FAValf_ -= _FsValf_ * _FtValf_; } +void ABS_S() { _FdValf_ = fpufabsf(_FsValf_); } +void MAX_S() { _FdValf_ = max( _FsValf_, _FtValf_ ); } +void MIN_S() { _FdValf_ = min( _FsValf_, _FtValf_ ); } +void DIV_S() { if ( _FtValf_ ) { _FdValf_ = _FsValf_ / _FtValf_; } } +void SQRT_S() { + //if ( _FtValf_ >= 0.0f ) { _FdValf_ = fpusqrtf( _FtValf_ ); } + //else { + _FdValf_ = fpusqrtf(fpufabsf(_FtValf_)); + //} +} +void CVT_S() { _FdValf_ = (float)(s32)_FsValUl_; } +void CVT_W() { + if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValUl_ = (s32)(float)_FsValf_; } + else if ( _FsValUl_ & 0x80000000 ) { _FdValUl_ = 0x80000000; } + else { _FdValUl_ = 0x7fffffff; } +} + +void RSQRT_S() { + if ( _FtValf_ >= 0.0f ) { + float tmp = fpusqrtf( _FtValf_ ); + if ( tmp != 0 ) { _FdValf_ = _FsValf_ / tmp; } + } +} + +//3322 2222 2222 1111 1111 1100 0000 0000 +//1098 7654 3210 9876 5432 1098 7654 3210 +//0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/branches/pcsx2_0.9.1/FPU2.cpp b/branches/pcsx2_0.9.1/FPU2.cpp new file mode 100644 index 0000000..a7f3974 --- /dev/null +++ b/branches/pcsx2_0.9.1/FPU2.cpp @@ -0,0 +1,25 @@ +#include + +// sqrtf only defined in C++ +extern "C" { + +float (*fpusqrtf)(float fval) = 0; +float (*fpufabsf)(float fval) = 0; +float (*fpusinf)(float fval) = 0; +float (*fpucosf)(float fval) = 0; +float (*fpuexpf)(float fval) = 0; +float (*fpuatanf)(float fval) = 0; +float (*fpuatan2f)(float fvalx, float fvaly) = 0; + +void InitFPUOps() +{ + fpusqrtf = sqrtf; + fpufabsf = fabsf; + fpusinf = sinf; + fpucosf = cosf; + fpuexpf = expf; + fpuatanf = atanf; + fpuatan2f = atan2f; +} + +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/FiFo.c b/branches/pcsx2_0.9.1/FiFo.c new file mode 100644 index 0000000..8dc218f --- /dev/null +++ b/branches/pcsx2_0.9.1/FiFo.c @@ -0,0 +1,181 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//well that might need a recheck :P +//(shadow bug0r work :P) + +//plz, change this file according to FIFO defs in hw.h +/* u64 VIF0[0x1000]; + u64 VIF1[0x1000]; + u64 GIF[0x1000]; + u64 IPU_out_FIFO[0x160]; // 128bit + u64 IPU_in_FIFO[0x160]; // 128bit +*/ + +#include +#include +#include + +#include "Common.h" +#include "Hw.h" + +#include + +////////////////////////////////////////////////////////////////////////// +/////////////////////////// Quick & dirty FIFO :D //////////////////////// +////////////////////////////////////////////////////////////////////////// +extern int fifo_wwrite(u32* pMem, int size); +extern void fifo_wread1(void *value); + +extern int g_nIPU0Data; +extern u8* g_pIPU0Pointer; + +// NOTE: cannot use XMM/MMX regs +void ReadFIFO(u32 mem, u64 *out) { + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("ReadFIFO VIF0 0x%08X\n", mem); +#endif + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else + if ((mem >= 0x10005000) && (mem < 0x10006000)) { + +#ifdef PCSX_DEVBUILD + VIF_LOG("ReadFIFO VIF1 0x%08X\n", mem); + + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("reading from vif1 fifo when stalled\n"); + } +#endif + + if (vif1Regs->stat & 0x800000) { + if (--psHu32(D1_QWC) == 0) { + vif1Regs->stat&= ~0x1f000000; + } else { + } + } + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else if( (mem&0xfffff010) == 0x10007000) { + + if( g_nIPU0Data > 0 ) { + out[0] = *(u64*)(g_pIPU0Pointer); + out[1] = *(u64*)(g_pIPU0Pointer+8); + g_nIPU0Data--; + g_pIPU0Pointer += 16; + } + return; + }else if ( (mem&0xfffff010) == 0x10007010) { + fifo_wread1((void*)out); + return; + } + SysPrintf("ReadFIFO Unknown %x\n", mem); +} + +void ConstReadFIFO(u32 mem) +{ + // not done +} + +extern HANDLE g_hGsEvent; + +void WriteFIFO(u32 mem, u64 *value) { + int ret; + + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF0 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + ret = VIF0transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10005000) && (mem < 0x10006000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF1 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + if(vif1Regs->stat & VIF1_STAT_FDR) + SysPrintf("writing to fifo when fdr is set!\n"); + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("writing to vif1 fifo when stalled\n"); + } +#endif + ret = VIF1transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10006000) && (mem < 0x10007000)) { + u64* data; +#ifdef GIF_LOG + GIF_LOG("WriteFIFO GIF 0x%08X\n", mem); +#endif + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + + if( CHECK_MULTIGS ) { + data = (u64*)GSRingBufCopy(NULL, 16, GS_RINGTYPE_P3); + + data[0] = value[0]; + data[1] = value[1]; + GSgifTransferDummy(2, (u32*)data, 1); + GSRINGBUF_DONECOPY(data, 16); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); + } + else { + FreezeXMMRegs(1); +#ifdef GSCAPTURE + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; + + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { + GSgifTransfer3((u32*)value, 1-GSgifTransferDummy(2, (u32*)value, 1)); + } +#else + GSgifTransfer3((u32*)value, 1); +#endif + FreezeXMMRegs(0); + } + + } else + if ((mem&0xfffff010) == 0x10007010) { +#ifdef IPU_LOG + IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n", (mem - 0x10007010)/8, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + //commiting every 16 bytes + while( fifo_wwrite((void*)value, 1) == 0 ) { + SysPrintf("IPU sleeping\n"); + Sleep(1); + } + } else { + SysPrintf("WriteFIFO Unknown %x\n", mem); + } +} + +void ConstWriteFIFO(u32 mem) { +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/GS.c b/branches/pcsx2_0.9.1/GS.c new file mode 100644 index 0000000..27c6049 --- /dev/null +++ b/branches/pcsx2_0.9.1/GS.c @@ -0,0 +1,1707 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// rewritten by zerofrog to add multithreading/gs caching to GS and VU1 + +#include "Common.h" + +#include + +#include +#include "ir5900.h" +#include "VUmicro.h" + +#ifdef WIN32_VIRTUAL_MEM +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +#else +#define gif ((DMACh*)&psH[0xA000]) +#endif + +#define ENABLE_GS_CACHING_SIZE 0x4000 // min size +//#define _RINGBUF_DEBUG + +#ifdef WIN32_VIRTUAL_MEM +#define PS2GS_BASE(mem) ((PS2MEM_BASE+0x12000000)+(mem&0x13ff)) +#else +u8 g_RealGSMem[0x2000]; +#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) +#endif + +#ifdef GSCAPTURE +u32 g_loggs = 0; +u32 g_gstransnum = 0; +u32 g_gslimit = 0; +u32 g_gsfinalnum = 0; +#endif + +// dummy GS for processing SIGNAL, FINISH, and LABEL commands +typedef struct +{ + u32 nloop : 15; + u32 eop : 1; + u32 dummy0 : 16; + u32 dummy1 : 14; + u32 pre : 1; + u32 prim : 11; + u32 flg : 2; + u32 nreg : 4; + u32 regs[2]; + u32 curreg; +} GIFTAG; + +static GIFTAG g_path[3]; +__declspec(align(16)) static BYTE s_byRegs[3][16]; + +// could convert to pthreads easily, just don't have the time +HANDLE g_hGsEvent = NULL, // set when path3 is ready to be processed + g_hVuGSExit = NULL; // set when thread needs to exit +HANDLE g_hGSOpen = NULL, g_hGSDone = NULL; +HANDLE g_hVuGSThread = NULL; +u32 CSRw; + +HANDLE g_hAllGsReady[3] = {NULL}; + +DWORD WINAPI VuGSThreadProc(LPVOID lpParam); + +// g_pGSRingPos == g_pGSWritePos => fifo is empty +u8* g_pGSRingPos = NULL, // cur pos ring is at + *g_pGSWritePos = NULL; // cur pos ee thread is at +u8 *g_pGSTempWritePos = NULL, *g_pGSTempReadPos = NULL; // cur pos ee thread is at + +extern int g_nCounters[]; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +CRITICAL_SECTION g_PageAddrSection; +u32 *g_pGSCurFreePages = NULL, *g_pGSWriteFreePages = NULL; + +void gsInit() +{ + if( VirtualAlloc(GS_PAGEADDRS, GSPAGES_STRIDE*(0x10000000>>GS_SHIFT), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) != GS_PAGEADDRS ) { + MessageBox(NULL, "Cannot alloc GS page buffer\n", "Error", MB_OK); + exit(0); + } + memset(GS_PAGEADDRS, 0, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT)); + + if( CHECK_MULTIGS ) { + g_hGsEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + g_hVuGSExit = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSOpen = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSDone = CreateEvent(NULL, FALSE, FALSE, NULL); + + SysPrintf("gsInit\n"); + + g_pGSRingPos = VirtualAlloc(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if( g_pGSRingPos != GS_RINGBUFFERBASE ) { + MessageBox(NULL, "Cannot alloc GS ring buffer\n", "Error", MB_OK); + exit(0); + } + + g_pGSTempReadPos = g_pGSTempWritePos = VirtualAlloc(GS_RINGTEMPBASE, GS_RINGTEMPSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if( g_pGSTempWritePos != GS_RINGTEMPBASE ) { + MessageBox(NULL, "Cannot alloc GS RingTemp buffer\n", "Error", MB_OK); + exit(0); + } + + InitializeCriticalSection(&g_PageAddrSection); + + InterlockedExchangePointer(&g_pGSWritePos, GS_RINGBUFFERBASE); + g_hVuGSThread = CreateThread(NULL, 0, VuGSThreadProc, NULL, 0, NULL); + } +} + +void gsWaitGS() +{ + while( g_pGSRingPos != g_pGSWritePos ) + Sleep(1); +} + +void gsShutdown() +{ + VirtualFree(GS_PAGEADDRS, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT), MEM_DECOMMIT|MEM_RELEASE); + + if( CHECK_MULTIGS ) { + + SetEvent(g_hVuGSExit); + SysPrintf("Closing gs thread\n"); + WaitForSingleObject(g_hVuGSThread, INFINITE); + CloseHandle(g_hVuGSThread); + CloseHandle(g_hGsEvent); + CloseHandle(g_hVuGSExit); + CloseHandle(g_hGSOpen); + CloseHandle(g_hGSDone); + + g_pGSWriteFreePages = g_pGSCurFreePages = NULL; + g_pGSTempReadPos = NULL; + + DeleteCriticalSection(&g_PageAddrSection); + + VirtualFree(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_DECOMMIT|MEM_RELEASE); + VirtualFree(GS_RINGTEMPBASE, GS_RINGTEMPSIZE, MEM_DECOMMIT|MEM_RELEASE); + } + else GSclose(); +} + +static void GSRingTempReserve(u32 size) +{ + u8* writepos = g_pGSTempWritePos; + assert( size <= GS_RINGTEMPSIZE ); + + // there always has to be memory + if( g_pGSTempWritePos + size > GS_RINGTEMPEND ) { + if( writepos < g_pGSTempReadPos ) { + do { + SetEvent(g_hGsEvent); + Sleep(1); + } while( writepos < g_pGSTempReadPos ); + } + + // notify GS + writepos = GS_RINGTEMPBASE; + } + + if( writepos < g_pGSTempReadPos && writepos+size >= g_pGSTempReadPos ) { + do { + SetEvent(g_hGsEvent); + Sleep(1); + } while( writepos < g_pGSTempReadPos && writepos+size >= g_pGSTempReadPos ); + } + + g_pGSTempWritePos = writepos; +} + +static u8* GSRingTempCopy(u32 size) +{ + u8* writepos; + assert( size <= GS_RINGTEMPSIZE ); + //GSRingTempReserve(size); + + writepos = g_pGSTempWritePos; + g_pGSTempWritePos += size; + assert( g_pGSTempWritePos <= GS_RINGTEMPEND ); + + //SysPrintf("writepos copy: %x %d\n", writepos, size); + return writepos; +} + +typedef u8* PU8; + +u8* GSRingBufCopy(void* mem, u32 size, u32 type) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + assert( size < 0x10000*16 ); + assert( writepos < GS_RINGBUFFEREND ); + assert( ((u32)writepos & 15) == 0 ); + assert( (size&15) == 0); + + size += 16; + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos + size > GS_RINGBUFFEREND ) { + + // skip to beginning + while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + + // notify GS + if( writepos != GS_RINGBUFFEREND ) { + *(u32*)writepos = GS_RINGTYPE_RESTART; + } + + writepos = GS_RINGBUFFERBASE; + } + + while( writepos < tempbuf && (writepos+size >= g_pGSRingPos || (writepos+size == GS_RINGBUFFEREND && g_pGSRingPos == GS_RINGBUFFERBASE)) ) { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + +#ifdef WIN32_VIRTUAL_MEM + if( ENABLE_GS_CACHING && size >= ENABLE_GS_CACHING_SIZE && mem != NULL && (u8*)mem < PS2MEM_BASE+0x10000000 ) { + u32 val; + u32 i; + u32* page = GS_PAGEADDRS+(((u32)((u8*)mem-PS2MEM_BASE)&0x01ffffff)>>GS_SHIFT)*(GSPAGES_MEMADDRS+1); + u32 numpages = (((u32)mem+size-1)>>GS_SHIFT) - ((u32)mem>>GS_SHIFT)+1; + + // inc all pages + for(i = 0; i < numpages; ++i) { + if( (u8)page[0] >= GSPAGES_MEMADDRS ) + break; + + val = InterlockedExchangeAdd(page, 0x40000001); + + assert( (u8)val < GSPAGES_MEMADDRS ); + + // upper 2 bits are index + page[(val>>30)+1] = (u32)writepos; + page += GSPAGES_MEMADDRS+1; + } + + if( i == numpages ) { + // succeeded, so fill necessary data + *(u32*)writepos = GS_RINGTYPE_MEMREF|type|(((size-16)>>4)<<16); + *(u32*)(writepos+4) = (u32)mem; + *(u32*)(writepos+8) = (u32)(page-(GSPAGES_MEMADDRS+1)*numpages); + *(u32*)(writepos+12) = (u32)numpages; + + writepos += 16; + +#ifndef _RINGBUF_DEBUG + if( writepos == GS_RINGBUFFEREND ) writepos = GS_RINGBUFFERBASE; + InterlockedExchangePointer(&g_pGSWritePos, writepos); + +// SetEvent(g_hGsEvent); +// while( g_pGSWritePos != g_pGSRingPos ) Sleep(1); + + return NULL; +#else + return writepos; +#endif + } + + SysPrintf("not enough pages %x, %d\n", mem, size); + + // BUG, the interlocked exchange add should be done in a crit section! + // dec the current pages + while(i-- > 0) { + page -= GSPAGES_MEMADDRS+1; + InterlockedExchangeAdd(page, -0x40000001); + } + + // don't have enough mem, so fall through + } +#endif + + // just copy + *(u32*)writepos = type|(((size-16)>>4)<<16); + return writepos+16; +} + +void GSRingBufVSync(int field) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + + assert( writepos + 16 <= GS_RINGBUFFEREND ); + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos < tempbuf && writepos+16 >= tempbuf ) { + + do { + SetEvent(g_hGsEvent); + Sleep(1); + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } while(writepos < tempbuf && writepos+16 >= tempbuf ); + } + + *(u32*)writepos = GS_RINGTYPE_VSYNC; + *(int*)(writepos+4) = field; + + writepos += 16; + if( writepos == GS_RINGBUFFEREND ) writepos = GS_RINGBUFFERBASE; + InterlockedExchangePointer(&g_pGSWritePos, writepos); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); +} + +// called from gs thread or exception handler +static void GSFreeRingBuf(u8* pringbuf) +{ + u32 mem = *(u32*)(pringbuf+4) & ~0xfff; + u32* pageaddr = *(u32**)(pringbuf+8); + u32 pages = *(u32*)(pringbuf+12); + u32 val, index; + + mem &= ~0xfff; + + while(pages-- > 0 ) { + + val = pageaddr[0]; + assert( (val&0xff) > 0 ); + + index = (((val>>30)-(val&7))&3); + + if( pageaddr[ index + 1 ] != (u32)pringbuf ) { + // deleting before others, so remove it from the entry + for(val = 1; val < 5; ++val ) { + if( pageaddr[val] == (u32)pringbuf ) { + + val--; + + // shift the rest + while(index != val) { + pageaddr[1+(val)%GSPAGES_MEMADDRS] = pageaddr[(val-1)%GSPAGES_MEMADDRS+1]; + val = (val-1)%GSPAGES_MEMADDRS; + } + + break; + } + } + } + + InterlockedExchangeAdd(pageaddr, -1); + mem += 0x1000; + pageaddr += GSPAGES_MEMADDRS+1; + } +} + +void GSFreePage(u32* page) +{ + u32 indices, num; + u32 gssize; + u8* gsmem, *ringmem; + + num = *(u32*)page; + + // count approximately the size needed to be allocated + indices = ((num>>30)-(num&0xff))&3; + num &= 0xff; + gssize = 0; + + while(num-- > 0) { + // first copy to a new memory + ringmem = *(u8**)(page + 1 + indices); + gssize += (*(u32*)ringmem >> 16) << 4; + // go to the next index + indices = (indices+1)%GSPAGES_MEMADDRS; + } + + GSRingTempReserve(gssize); + + // lock section to start freeing + EnterCriticalSection(&g_PageAddrSection); + + // check again since could have changed + num = *(u32*)page; + if( (u8)num ) { + // note that values might be different + indices = ((num>>30)-(num&0xff))&3; + num &= 0xff; + + while(num-- > 0) { + // first copy to a new memory + ringmem = *(u8**)(page + 1 + indices); + + assert( !(*(u32*)ringmem & GS_RINGTYPE_MEMNOFREE) ); + + gssize = (*(u32*)ringmem >> 16) << 4; + gsmem = GSRingTempCopy(gssize); + memcpy(gsmem, *(u8**)(ringmem+4), gssize); + + GSFreeRingBuf(ringmem); + + // indicate that using different mem + *(u8**)(ringmem+4) = gsmem; + *(u32*)ringmem |= GS_RINGTYPE_MEMNOFREE; + + // go to the next index + indices = (indices+1)%GSPAGES_MEMADDRS; + } + } + + LeaveCriticalSection(&g_PageAddrSection); +} + +void gsReset() +{ + SysPrintf("GIF reset\n"); + + // GSDX crashes + //if( GSreset ) GSreset(); + memset(GS_PAGEADDRS, 0, GSPAGES_STRIDE*(0x02000000>>GS_SHIFT)); + + if( CHECK_MULTIGS ) { + ResetEvent(g_hGsEvent); + ResetEvent(g_hVuGSExit); + + g_pGSRingPos = g_pGSWritePos; + g_pGSCurFreePages = g_pGSWriteFreePages; + g_pGSTempReadPos = g_pGSTempWritePos = GS_RINGTEMPBASE; + } + + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void gsGIFReset() +{ + memset(g_path, 0, sizeof(g_path)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); +// else +// GSreset(); + + GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void CSRwrite(u32 value) +{ + GSwriteCSR(value); + + GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f); + + if( value & 0x100 ) { // FLUSH + //SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr); + } + + CSRw |= value & ~0x60; + if (value & 0x200) { // resetGS + //GSCSRr = 0x400E; // The host FIFO neeeds to be empty too or GSsync will fail (saqib) + //GSIMR = 0xff00; + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); + else GSreset(); + + GSCSRr = 0x551B4002; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) + //Since when!! Refraction, since 4/21/06 (zerofrog) + GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 + + // and this too (fixed megaman ac) + GSwriteCSR(GSCSRr); + } +} + +static void IMRwrite(u32 value) { + GSIMR = (value & 0x1f00)|0x6000; +} + +void gsWrite8(u32 mem, u8 value) { + switch (mem) { + case 0x12001000: // GS_CSR + CSRwrite((CSRw & ~0x000000ff) | value); break; + case 0x12001001: // GS_CSR + CSRwrite((CSRw & ~0x0000ff00) | (value << 8)); break; + case 0x12001002: // GS_CSR + CSRwrite((CSRw & ~0x00ff0000) | (value << 16)); break; + case 0x12001003: // GS_CSR + CSRwrite((CSRw & ~0xff000000) | (value << 24)); break; + default: + *PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 8 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void gsConstWrite8(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12001000: // GS_CSR + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xff<<(mem&3)*8); + AND32ItoR(ECX, ~(0xff<<(mem&3)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + default: + _eeWriteConstMem8( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +extern void UpdateVSyncRate(); + +void gsWrite16(u32 mem, u16 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u16*)PS2GS_BASE(mem) = value; + UpdateVSyncRate(); + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u16*)PS2GS_BASE(mem) = value; + break; + + case 0x12001000: // GS_CSR + CSRwrite( (CSRw&0xffff0000) | value); + break; + case 0x12001002: // GS_CSR + CSRwrite( (CSRw&0xffff) | ((u32)value<<16)); + break; + case 0x12001010: // GS_IMR + SysPrintf("writing to IMR 16\n"); + IMRwrite(value); + break; + + default: + *(u16*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 16 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void recSetSMODE1() +{ + iFlushCall(0); + AND32ItoR(EAX, 0x6000); + CMP32ItoR(EAX, 0x6000); + j8Ptr[5] = JNE8(0); + + // PAL + OR32ItoM( (u32)&Config.PsxType, 1); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // NTSC + AND32ItoM( (u32)&Config.PsxType, ~1 ); + + x86SetJ8( j8Ptr[6] ); + CALLFunc((u32)UpdateVSyncRate); +} + +void recSetSMODE2() +{ + TEST32ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // Interlaced + OR32ItoM( (u32)&Config.PsxType, 2); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // Non-Interlaced + AND32ItoM( (u32)&Config.PsxType, ~2 ); + + x86SetJ8( j8Ptr[6] ); +} + +void gsConstWrite16(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12000010: // GS_SMODE1 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + + assert( !(mem&2) ); + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xffff<<(mem&2)*8); + AND32ItoR(ECX, ~(0xffff<<(mem&2)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +void gsWrite32(u32 mem, u32 value) +{ + assert( !(mem&3)); + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u32*)PS2GS_BASE(mem) = value; + UpdateVSyncRate(); + break; + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u32*)PS2GS_BASE(mem) = value; + break; + + case 0x12001000: // GS_CSR + CSRwrite(value); + break; + + case 0x12001010: // GS_IMR + IMRwrite(value); + break; + default: + *(u32*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 32 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +// (value&0x1f00)|0x6000 +void gsConstWriteIMR(int mmreg) +{ + const u32 mem = 0x12001010; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_M32((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_MMXTAG ) { + SetMMXstate(); + MOVDMMXtoM((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_EECONSTTAG ) { + MOV32ItoM( (u32)PS2GS_BASE(mem), (g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x1f00)|0x6000); + } + else { + AND32ItoR(mmreg, 0x1f00); + OR32ItoR(mmreg, 0x6000); + MOV32RtoM( (u32)PS2GS_BASE(mem), mmreg ); + } +} +void gsConstWrite32(u32 mem, int mmreg) { + + switch (mem) { + + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + default: + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + break; + } +} + +void gsWrite64(u32 mem, u64 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + UpdateVSyncRate(); + *(u64*)PS2GS_BASE(mem) = value; + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u64*)PS2GS_BASE(mem) = value; + break; + case 0x12001000: // GS_CSR + CSRwrite((u32)value); + break; + + case 0x12001010: // GS_IMR + IMRwrite((u32)value); + break; + + default: + *(u64*)PS2GS_BASE(mem) = value; + } + +#ifdef HW_LOG + HW_LOG("GS write 64 at %8.8lx with data %8.8lx_%8.8lx\n", mem, ((u32*)&value)[1], (u32)value); +#endif +} + +void gsConstWrite64(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + break; + } +} + +void gsConstWrite128(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + recSetSMODE1(); + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + recSetSMODE2(); + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + // (value&0x1f00)|0x6000 + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + break; + } +} + +u8 gsRead8(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 8 %8.8lx, at %8.8lx\n", *(u8*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u8*)PS2GS_BASE(mem); +} + +int gsConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + _eeReadConstMem8(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u16 gsRead16(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 16 %8.8lx, at %8.8lx\n", *(u16*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u16*)PS2GS_BASE(mem); +} + +int gsConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + _eeReadConstMem16(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u32 gsRead32(u32 mem) { + +#ifdef HW_LOG + //HW_LOG("GS read 32 %8.8lx, at %8.8lx\n", *(u32*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + return *(u32*)PS2GS_BASE(mem); +} + +int gsConstRead32(u32 x86reg, u32 mem) +{ + _eeReadConstMem32(x86reg, (u32)PS2GS_BASE(mem)); + return 0; +} + +u64 gsRead64(u32 mem) +{ +#ifdef HW_LOG + //HW_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", *(u64*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u64*)PS2GS_BASE(mem); +} + +void gsConstRead64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PS2GS_BASE(mem)); + else { + MOVQMtoR(mmreg, (u32)PS2GS_BASE(mem)); + SetMMXstate(); + } +} + +void gsConstRead128(u32 mem, int xmmreg) +{ + _eeReadConstMem128( xmmreg, (u32)PS2GS_BASE(mem)); +} + + +void gsIrq() { + hwIntcIrq(0); +} + +static void GSRegHandlerSIGNAL(u32* data) +{ + GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + + if (CSRw & 0x1) { + GSCSRr |= 1; // signal + //CSRw &= ~1; + } + if (!(GSIMR&0x100) ) + gsIrq(); +} + +static void GSRegHandlerFINISH(u32* data) +{ + if (CSRw & 0x2) { + //CSRw &= ~2; + GSCSRr |= 2; // finish + } + if (!(GSIMR&0x200) ) + gsIrq(); +} + +static void GSRegHandlerLABEL(u32* data) +{ + GSSIGLBLID->LBLID = (GSSIGLBLID->LBLID&~data[1])|(data[0]&data[1]); +} + +typedef void (*GIFRegHandler)(u32* data); +static GIFRegHandler s_GSHandlers[3] = { GSRegHandlerSIGNAL, GSRegHandlerFINISH, GSRegHandlerLABEL }; + +// ffx pal, ntsc, jap +#define GSHACK_FFX (ElfCRC==0xbb3d833a||ElfCRC==0xa39517ab||ElfCRC==0x6A4EFE60) + +// simulates a GIF tag +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size) +{ + int nreg, i, nloop; + u32 curreg; + u32 tempreg; + GIFTAG* ptag = &g_path[path]; + +#ifdef GSCAPTURE + u32 tempcount = 0; +#endif + + if( path == 0 ) { + nloop = 0; + } + else { + nloop = ptag->nloop; + curreg = ptag->curreg; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + } + + while(size > 0) + { + if(nloop == 0) { + + ptag = (GIFTAG*)pMem; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + +#ifdef GSCAPTURE + if( g_loggs && g_gstransnum == 19 && tempcount++ > g_gslimit ) { + break; + } +#endif + + pMem+= 4; + size--; + + if(ptag->nloop == 0 ) { + if( path == 0 ) { + // ffx hack + if( GSHACK_FFX ) + continue; + } + + g_path[path].nloop = 0; + + // motogp graphics show + if( !ptag->eop ) + continue; + + return size; + } + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + s_byRegs[path][i] = tempreg&0xf; + } + + nloop = ptag->nloop; + curreg = 0; + } + + switch(ptag->flg) + { + case 0: // PACKED + { + for(; size > 0; size--, pMem += 4) + { + if( s_byRegs[path][curreg] == 0xe && (pMem[2]&0xff) >= 0x60 ) { + if( (pMem[2]&0xff) < 0x64 ) + s_GSHandlers[pMem[2]&0x3](pMem); + } + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 4; + break; + } + } + } + + if( nloop > 0 ) { + assert(size == 0); + g_path[path] = *ptag; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 1: // REGLIST + { + size *= 2; + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + assert( (tempreg&0xf) < 0x64 ); + s_byRegs[path][i] = tempreg&0xf; + } + + for(; size > 0; pMem+= 2, size--) + { + if( s_byRegs[path][curreg] >= 0x60 ) + s_GSHandlers[s_byRegs[path][curreg]&3](pMem); + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + + if( nloop > 0 ) { + assert(size == 0); + g_path[path] = *ptag; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 2: // GIF_IMAGE (FROM_VFRAM) + case 3: + { + // simulate + if( (int)size < nloop ) { + g_path[path] = *ptag; + g_path[path].nloop = nloop-size; + return 0; + } + else { + pMem += nloop*4; + size -= nloop; + nloop = 0; + } + break; + } + } + + if( path == 0 && ptag->eop ) { + g_path[0].nloop = 0; + return size; + } + } + + g_path[path] = *ptag; + g_path[path].curreg = curreg; + g_path[path].nloop = nloop; + return size; +} + +int gsInterrupt() { +#ifdef GS_LOG + GS_LOG("gsInterrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(gif->qwc > 0) { + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("gs dma masked\n"); + return 0; + } + + dmaGIF(); + return 0; + } + + gif->chcr &= ~0x100; + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 + hwDmacIrq(DMAC_GIF); + + return 1; +} + +#ifdef GSCAPTURE +#define WRITINGDMA_TRANSFER(pMem, qwc) \ + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; \ + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { \ + GSgifTransfer3(pMem, qwc-GSgifTransferDummy(2, pMem, qwc)); \ + } \ + +#else +#define WRITINGDMA_TRANSFER(pMem, qwc) GSgifTransfer3(pMem, qwc); +#endif + +#define WRITERING_DMA(pMem, qwc) { \ + if( CHECK_MULTIGS) { \ + u8* pgsmem = GSRingBufCopy(pMem, (qwc)<<4, GS_RINGTYPE_P3); \ + if( pgsmem != NULL ) { \ + memcpy_amd(pgsmem, pMem, (qwc)<<4); \ + \ + pgsmem += (qwc)<<4; \ + assert( pgsmem <= GS_RINGBUFFEREND ); \ + if( pgsmem == GS_RINGBUFFEREND ) pgsmem = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer(&g_pGSWritePos, pgsmem); \ + GSgifTransferDummy(2, pMem, qwc); \ + } \ + \ + if( !CHECK_DUALCORE ) SetEvent(g_hGsEvent); \ + } \ + else { \ + FreezeMMXRegs(1); \ + FreezeXMMRegs(1); \ + WRITINGDMA_TRANSFER(pMem, qwc); \ + } \ +} \ + +int _GIFchain() { + u32 qwc = gif->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) { + // reset path3, fixes dark cloud 2 + if( GSgifSoftReset != NULL ) + GSgifSoftReset(4); + + SysPrintf("NULL GIFchain\n"); + return -1; + } + + WRITERING_DMA(pMem, qwc); + + gif->madr+= qwc*16; + gif->qwc = 0; + return (qwc)*BIAS; +} + +#define GIFchain() \ + if (gif->qwc) { \ + cycles+= _GIFchain(); /* guessing */ \ + } + +int gscount = 0; +static int prevcycles = 0; +static u32* prevtag = NULL; + +void dmaGIF() { + u32 *ptag; + int done=0; + int cycles=prevcycles; + u32 id; + + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC/* && + (gif->tadr == psHu32(0xe050))*/) { // GIF MFIFO + return; + } + if( (psHu32(GIF_CTRL) & 8) ) { + // temporarily stop + SysPrintf("Gif dma temp paused?\n"); + return; + } + +#ifdef GIF_LOG + GIF_LOG("dmaGIF chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + gif->chcr, gif->madr, gif->qwc, + gif->tadr, gif->asr0, gif->asr1); +#endif + + if (psHu32(GIF_MODE) & 0x4) { + } else + if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) { + gif->chcr &= ~0x100; + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + hwDmacIrq(2); + return; + } + + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + //SysPrintf("GS Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); + + if( gif->madr >= psHu32(DMAC_STADR) ) { + return; + } + } + + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x8000; //FIFO full + psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3 + psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) + + if( prevcycles != 0 ) { + assert( prevtag != NULL ); + + ptag = prevtag; + // transfer interrupted, so continue + GIFchain(); + + if (gif->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + done = 1; + + } + } + + // Transfer Dn_QWC from Dn_MADR to GIF + if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode + //gscount++; + GIFchain(); + } + else { + // Chain Mode + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + cycles+=1; // Add 1 cycles from the QW read for the tag + // Transfer dma tag if tte is set + if (gif->chcr & 0x40) { + //u32 temptag[4]; +#ifdef GIF_LOG + //SysPrintf("GIF TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + +// temptag[2] = ptag[2]; +// temptag[3] = ptag[3]; +// GSgifTransfer3(temptag, 1); + } + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr); +#endif + + done = hwDmacSrcChainWithStack(gif, id); + + if (!done && (psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( gif->madr >= psHu32(DMAC_STADR) ) { + // stalled + psHu32(GIF_STAT)&= ~0x1f000E00; // OPH=0 | APATH=0 + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + prevcycles = cycles; + prevtag = ptag; + hwDmacIrq(13); + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return; + } + } + + GIFchain(); //Transfers the data set by the switch + + if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("GIF TIE\n"); + + // SysPrintf("GSdmaIrq Set\n"); + done = 1; + //gif->qwc = 0; + break; + } + } + } + + prevtag = NULL; + prevcycles = 0; + INT(2, cycles); + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +static int mfifocycles; + +int mfifoGIFrbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((gif->madr+gif->qwc*16) > (maddr+msize)) { + int s1 = (maddr+msize) - gif->madr; + int s2 = gif->qwc*16 - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + WRITERING_DMA(src, s1&~15); + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + WRITERING_DMA(src, s2&~15); + + } else { + /* it doesn't, so just transfer 'qwc*16' words + from 'gif->madr' to GS */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + + WRITERING_DMA(src, gif->qwc); + } + + gif->madr+= gif->qwc*16; + //gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + + return 0; +} + +int mfifoGIFchain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (gif->qwc == 0) return 0; + + if (gif->madr >= maddr && + gif->madr < (maddr+msize)) { + if (mfifoGIFrbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) return -1; + + WRITERING_DMA(pMem, gif->qwc); + gif->madr+= gif->qwc*16; + } + + mfifocycles+= (gif->qwc) * BIAS; /* guessing */ + gif->qwc = 0; + + return 0; +} + +void mfifoGIFtransfer(int qwc) { + u32 *ptag; + int id; + int done = 0; + mfifocycles = 0; +#ifdef GIF_LOG + GIF_LOG("mfifoGIFtransfer qwc=0x%x\n", qwc); +#endif + if((gif->chcr & 0x100) == 0)SysPrintf("MFIFO GIF not ready %x\n", gif->chcr); + + while (qwc > 0 && done == 0) { // Loop while Dn_CHCR.STR is 1 + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(gif->tadr); + + id = (ptag[0] >> 28) & 0x7; + gif->qwc = (u16)ptag[0]; + gif->madr = ptag[1]; + mfifocycles += 2; + +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr); +#endif + +// if(gif->chcr & 0x40) +// GSgifTransfer3(ptag, 1); + + switch (id) { + case 0: // refe + gif->tadr += 16; + qwc = 0; + INT(11,mfifocycles); + done = 1; + break; + + case 1: // cnt + gif->madr = gif->tadr + 16; + qwc-= gif->qwc + 1; + // Set the taddr to the next tag + gif->tadr += 16 + (gif->qwc * 16); + break; + + case 3: // ref + case 4: // refs + gif->tadr += 16; + qwc--; + break; + + case 7: // end + gif->madr = gif->tadr + 16; + gif->tadr = gif->madr + (gif->qwc * 16); + qwc = 0; + INT(11,mfifocycles); + done = 1; + break; + } + + if (mfifoGIFchain() == -1) { + break; + } + + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + INT(11,mfifocycles); + //SysPrintf("mfifoGIFTransfer: dmaIrq Set\n"); + //qwc = 0; + + done = 1; + } + } + if(done == 0 && qwc == 0)hwDmacIrq(14); + /*if(qwc == 0 && gif->chcr & 0x100) { + hwDmacIrq(14); + return; + }*/ + //INT(11,cycles); + //hwDmacIrq(2); + +} + +int gifMFIFOInterrupt() { + mfifocycles = 0; + gif->chcr &= ~0x100; + hwDmacIrq(DMAC_GIF); + + return 1; +} + +extern long pDsp; +DWORD WINAPI VuGSThreadProc(LPVOID lpParam) +{ + HANDLE handles[2] = { g_hGsEvent, g_hVuGSExit }; + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + u8* writepos; + u32 tag; + u32 counter = 0; + + { + int ret; + HANDLE openhandles[2] = { g_hGSOpen, g_hVuGSExit }; + if( WaitForMultipleObjects(2, openhandles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + return 0; + } + ret = GSopen((void *)&pDsp, "PCSX2", 1); + GSCSRr = 0x551B4000; // 0x55190000 + SysPrintf("gsOpen done\n"); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); return -1; } + SetEvent(g_hGSDone); + } + + SysPrintf("Starting GS thread\n"); + + while(1) { + + if( !CHECK_DUALCORE ) { + if( WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + GSclose(); + return 0; + } + } + else if( (counter++ & 0xffff) == 0 ) { + if( WaitForSingleObject(g_hVuGSExit, 0) == WAIT_OBJECT_0 ) { + GSclose(); + return 0; + } + } + + if( g_pGSRingPos != g_pGSWritePos ) { + + do { + writepos = *(volatile PU8*)&g_pGSWritePos; + + while( g_pGSRingPos != writepos ) { + + assert( g_pGSRingPos < GS_RINGBUFFEREND ); + // process until writepos + tag = *(u32*)g_pGSRingPos; + + switch( tag&0xffff ) { + case GS_RINGTYPE_RESTART: + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( GS_RINGBUFFERBASE == writepos ) + goto ExitGS; + + continue; + + case GS_RINGTYPE_P1: + GSgifTransfer1((u32*)(g_pGSRingPos+16), 0); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + + case GS_RINGTYPE_P2: + GSgifTransfer2((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_P3: + GSgifTransfer3((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_VSYNC: + GSvsync(*(int*)(g_pGSRingPos+4)); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + +#ifdef GS_ENABLE_CACHING + case GS_RINGTYPE_P2|GS_RINGTYPE_MEMREF: + case GS_RINGTYPE_P2|GS_RINGTYPE_MEMREF|GS_RINGTYPE_MEMNOFREE: + EnterCriticalSection(&g_PageAddrSection); + + // read again since could have changed + tag = *(u32*)g_pGSRingPos; + + GSgifTransfer2(*(u32**)(g_pGSRingPos+4), tag>>16); + + if( ENABLE_GS_CACHING ) { + if( !(tag & GS_RINGTYPE_MEMNOFREE) ) { + GSFreeRingBuf(g_pGSRingPos); + } + else { + // using temp memory, so release + g_pGSTempReadPos = *(u8**)(g_pGSRingPos+4) + ((tag>>16)<<4); + } + } + + LeaveCriticalSection(&g_PageAddrSection); + +#ifdef _RINGBUF_DEBUG + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); +#else + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); +#endif + + break; + case GS_RINGTYPE_P3|GS_RINGTYPE_MEMREF: + case GS_RINGTYPE_P3|GS_RINGTYPE_MEMREF|GS_RINGTYPE_MEMNOFREE: + + EnterCriticalSection(&g_PageAddrSection); + + // read again since could have changed + tag = *(u32*)g_pGSRingPos; + +#ifdef _RINGBUF_DEBUG + assert( memcmp(*(u32**)(g_pGSRingPos+4), g_pGSRingPos+16, (tag>>16)*16) == 0 ); +#endif + GSgifTransfer3(*(u32**)(g_pGSRingPos+4), tag>>16); + + if( ENABLE_GS_CACHING ) { + if( !(tag & GS_RINGTYPE_MEMNOFREE) ) { + GSFreeRingBuf(g_pGSRingPos); + } + else { + // using temp memory, so release + g_pGSTempReadPos = *(u8**)(g_pGSRingPos+4) + ((tag>>16)<<4); + } + } + + LeaveCriticalSection(&g_PageAddrSection); + +#ifdef _RINGBUF_DEBUG + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); +#else + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); +#endif + break; + +#endif // end GS_ENABLE_CACHING + + case GS_RINGTYPE_VIFFIFO: + { + u64* pMem; + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + pMem = (u64*)dmaGetAddr(vif1ch->madr); + + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + break; + } + GSreadFIFO2(pMem, tag>>16); + + // set incase read + psHu64(0x5000) = pMem[2*(tag>>16)-2]; + psHu64(0x5008) = pMem[2*(tag>>16)-1]; + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + tag = (tag>>16) - (cpuRegs.cycle- *(u32*)(g_pGSRingPos+8)); + if( tag & 0x80000000 ) tag = 0; + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + + INT(1, tag); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + } + + default: + + SysPrintf("VsGSThreadProc, bad packet\n"); + g_pGSRingPos = g_pGSWritePos; + //flushall(); + } + + assert( g_pGSRingPos <= GS_RINGBUFFEREND ); + if( g_pGSRingPos == GS_RINGBUFFEREND ) + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( g_pGSRingPos == g_pGSWritePos ) { + break; + } + } +ExitGS: + ; + } while(g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos); + } + + // process vu1 + } + + return 0; +} + +int gsFreeze(gzFile f, int Mode) { + + gzfreeze(PS2MEM_GS, 0x2000); + gzfreeze(&CSRw, sizeof(CSRw)); + gzfreeze(g_path, sizeof(g_path)); + gzfreeze(s_byRegs, sizeof(s_byRegs)); + + return 0; +} + +#undef GIFchain \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/GS.h b/branches/pcsx2_0.9.1/GS.h new file mode 100644 index 0000000..e08eb11 --- /dev/null +++ b/branches/pcsx2_0.9.1/GS.h @@ -0,0 +1,126 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +#include "Common.h" + +typedef struct +{ + u32 SIGID; + u32 LBLID; +} GSRegSIGBLID; + +#ifdef WIN32_VIRTUAL_MEM +#define GSCSRr *((u64*)(PS2MEM_GS+0x1000)) +#define GSIMR *((u32*)(PS2MEM_GS+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(PS2MEM_GS+0x1080)) +#else +extern u8 g_RealGSMem[0x2000]; +#define GSCSRr *((u64*)(g_RealGSMem+0x1000)) +#define GSIMR *((u32*)(g_RealGSMem+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(g_RealGSMem+0x1080)) +#endif + +#define GS_RINGBUFFERBASE (u8*)(0x10200000) +#define GS_RINGBUFFERSIZE 0x00200000 // 2Mb +#define GS_RINGBUFFEREND (u8*)(GS_RINGBUFFERBASE+GS_RINGBUFFERSIZE) + +#define GS_RINGTEMPBASE (u8*)(0x10400000) +#define GS_RINGTEMPSIZE 0x00100000 // 1Mb +#define GS_RINGTEMPEND (u8*)(GS_RINGTEMPBASE+GS_RINGTEMPSIZE) + +#define GS_SHIFT 12 +#define ENABLE_GS_CACHING 0 // set to 0 to disable + +// mem addrs to support +#define GSPAGES_MEMADDRS 4 +#define GSPAGES_STRIDE ((1+GSPAGES_MEMADDRS)*4) +#define GS_PAGEADDRS_ 0x10500000 +#define GS_PAGEADDRS (u32*)(GS_PAGEADDRS_) + +#define GS_RINGTYPE_RESTART 0 +#define GS_RINGTYPE_P1 1 +#define GS_RINGTYPE_P2 2 +#define GS_RINGTYPE_P3 3 +#define GS_RINGTYPE_VSYNC 4 +#define GS_RINGTYPE_VIFFIFO 5 // GSreadFIFO2 +#define GS_RINGTYPE_MEMREF 0x10 // if bit set, memory is preserved (only valid for p2/p3) +#define GS_RINGTYPE_MEMNOFREE 0x20 // if bit set, don't free or mem + +// if returns NULL, don't copy (memory is preserved) +u8* GSRingBufCopy(void* mem, u32 size, u32 type); +void GSRingBufVSync(int field); +void GSFreePage(u32* pGSPage); + +extern u8* g_pGSWritePos; + +// mem and size are the ones from GSRingBufCopy +#define GSRINGBUF_DONECOPY(mem, size) { \ + u8* temp = (u8*)(mem) + (size); \ + if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer(&g_pGSWritePos, temp); \ +} + +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size); + +void gsInit(); +void gsShutdown(); +void gsReset(); + +// used for resetting GIF fifo +void gsGIFReset(); + +void gsWrite8(u32 mem, u8 value); +void gsConstWrite8(u32 mem, int mmreg); + +void gsWrite16(u32 mem, u16 value); +void gsConstWrite16(u32 mem, int mmreg); + +void gsWrite32(u32 mem, u32 value); +void gsConstWrite32(u32 mem, int mmreg); + +void gsWrite64(u32 mem, u64 value); +void gsConstWrite64(u32 mem, int mmreg); + +void gsConstWrite128(u32 mem, int mmreg); + +u8 gsRead8(u32 mem); +int gsConstRead8(u32 x86reg, u32 mem, u32 sign); + +u16 gsRead16(u32 mem); +int gsConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 gsRead32(u32 mem); +int gsConstRead32(u32 x86reg, u32 mem); + +u64 gsRead64(u32 mem); +void gsConstRead64(u32 mem, int mmreg); + +void gsConstRead128(u32 mem, int xmmreg); + +void gsIrq(); +int gsInterrupt(); +void dmaGIF(); +void mfifoGIFtransfer(int qwc); +int gsFreeze(gzFile f, int Mode); +int _GIFchain(); +int gifMFIFOInterrupt(); + +#endif diff --git a/branches/pcsx2_0.9.1/Gte.c b/branches/pcsx2_0.9.1/Gte.c new file mode 100644 index 0000000..d4e75c4 --- /dev/null +++ b/branches/pcsx2_0.9.1/Gte.c @@ -0,0 +1,2846 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Gte.h" +#include "PsxCommon.h" + +#ifdef GTE_DUMP +#define G_OP(name,delay) fprintf(gteLog, "* : %08X : %02d : %s\n", psxRegs.code, delay, name); +#define G_SD(reg) fprintf(gteLog, "+D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_SC(reg) fprintf(gteLog, "+C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#define G_GD(reg) fprintf(gteLog, "-D%02d : %08X\n", reg, psxRegs.CP2D.r[reg]); +#define G_GC(reg) fprintf(gteLog, "-C%02d : %08X\n", reg, psxRegs.CP2C.r[reg]); +#else +#define G_OP(name,delay) +#define G_SD(reg) +#define G_SC(reg) +#define G_GD(reg) +#define G_GC(reg) +#endif + +#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000; + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define gteVX0 ((s16*)psxRegs.CP2D.r)[0] +#define gteVY0 ((s16*)psxRegs.CP2D.r)[1] +#define gteVZ0 ((s16*)psxRegs.CP2D.r)[2] +#define gteVX1 ((s16*)psxRegs.CP2D.r)[4] +#define gteVY1 ((s16*)psxRegs.CP2D.r)[5] +#define gteVZ1 ((s16*)psxRegs.CP2D.r)[6] +#define gteVX2 ((s16*)psxRegs.CP2D.r)[8] +#define gteVY2 ((s16*)psxRegs.CP2D.r)[9] +#define gteVZ2 ((s16*)psxRegs.CP2D.r)[10] +#define gteRGB psxRegs.CP2D.r[6] +#define gteOTZ ((s16*)psxRegs.CP2D.r)[7*2] +#define gteIR0 ((s32*)psxRegs.CP2D.r)[8] +#define gteIR1 ((s32*)psxRegs.CP2D.r)[9] +#define gteIR2 ((s32*)psxRegs.CP2D.r)[10] +#define gteIR3 ((s32*)psxRegs.CP2D.r)[11] +#define gteSX0 ((s16*)psxRegs.CP2D.r)[12*2] +#define gteSY0 ((s16*)psxRegs.CP2D.r)[12*2+1] +#define gteSX1 ((s16*)psxRegs.CP2D.r)[13*2] +#define gteSY1 ((s16*)psxRegs.CP2D.r)[13*2+1] +#define gteSX2 ((s16*)psxRegs.CP2D.r)[14*2] +#define gteSY2 ((s16*)psxRegs.CP2D.r)[14*2+1] +#define gteSXP ((s16*)psxRegs.CP2D.r)[15*2] +#define gteSYP ((s16*)psxRegs.CP2D.r)[15*2+1] +#define gteSZx ((u16*)psxRegs.CP2D.r)[16*2] +#define gteSZ0 ((u16*)psxRegs.CP2D.r)[17*2] +#define gteSZ1 ((u16*)psxRegs.CP2D.r)[18*2] +#define gteSZ2 ((u16*)psxRegs.CP2D.r)[19*2] +#define gteRGB0 psxRegs.CP2D.r[20] +#define gteRGB1 psxRegs.CP2D.r[21] +#define gteRGB2 psxRegs.CP2D.r[22] +#define gteMAC0 psxRegs.CP2D.r[24] +#define gteMAC1 ((s32*)psxRegs.CP2D.r)[25] +#define gteMAC2 ((s32*)psxRegs.CP2D.r)[26] +#define gteMAC3 ((s32*)psxRegs.CP2D.r)[27] +#define gteIRGB psxRegs.CP2D.r[28] +#define gteORGB psxRegs.CP2D.r[29] +#define gteLZCS psxRegs.CP2D.r[30] +#define gteLZCR psxRegs.CP2D.r[31] + +#define gteR ((u8 *)psxRegs.CP2D.r)[6*4] +#define gteG ((u8 *)psxRegs.CP2D.r)[6*4+1] +#define gteB ((u8 *)psxRegs.CP2D.r)[6*4+2] +#define gteCODE ((u8 *)psxRegs.CP2D.r)[6*4+3] +#define gteC gteCODE + +#define gteR0 ((u8 *)psxRegs.CP2D.r)[20*4] +#define gteG0 ((u8 *)psxRegs.CP2D.r)[20*4+1] +#define gteB0 ((u8 *)psxRegs.CP2D.r)[20*4+2] +#define gteCODE0 ((u8 *)psxRegs.CP2D.r)[20*4+3] +#define gteC0 gteCODE0 + +#define gteR1 ((u8 *)psxRegs.CP2D.r)[21*4] +#define gteG1 ((u8 *)psxRegs.CP2D.r)[21*4+1] +#define gteB1 ((u8 *)psxRegs.CP2D.r)[21*4+2] +#define gteCODE1 ((u8 *)psxRegs.CP2D.r)[21*4+3] +#define gteC1 gteCODE1 + +#define gteR2 ((u8 *)psxRegs.CP2D.r)[22*4] +#define gteG2 ((u8 *)psxRegs.CP2D.r)[22*4+1] +#define gteB2 ((u8 *)psxRegs.CP2D.r)[22*4+2] +#define gteCODE2 ((u8 *)psxRegs.CP2D.r)[22*4+3] +#define gteC2 gteCODE2 + + + +#define gteR11 ((s16*)psxRegs.CP2C.r)[0] +#define gteR12 ((s16*)psxRegs.CP2C.r)[1] +#define gteR13 ((s16*)psxRegs.CP2C.r)[2] +#define gteR21 ((s16*)psxRegs.CP2C.r)[3] +#define gteR22 ((s16*)psxRegs.CP2C.r)[4] +#define gteR23 ((s16*)psxRegs.CP2C.r)[5] +#define gteR31 ((s16*)psxRegs.CP2C.r)[6] +#define gteR32 ((s16*)psxRegs.CP2C.r)[7] +#define gteR33 ((s16*)psxRegs.CP2C.r)[8] +#define gteTRX ((s32*)psxRegs.CP2C.r)[5] +#define gteTRY ((s32*)psxRegs.CP2C.r)[6] +#define gteTRZ ((s32*)psxRegs.CP2C.r)[7] +#define gteL11 ((s16*)psxRegs.CP2C.r)[16] +#define gteL12 ((s16*)psxRegs.CP2C.r)[17] +#define gteL13 ((s16*)psxRegs.CP2C.r)[18] +#define gteL21 ((s16*)psxRegs.CP2C.r)[19] +#define gteL22 ((s16*)psxRegs.CP2C.r)[20] +#define gteL23 ((s16*)psxRegs.CP2C.r)[21] +#define gteL31 ((s16*)psxRegs.CP2C.r)[22] +#define gteL32 ((s16*)psxRegs.CP2C.r)[23] +#define gteL33 ((s16*)psxRegs.CP2C.r)[24] +#define gteRBK ((s32*)psxRegs.CP2C.r)[13] +#define gteGBK ((s32*)psxRegs.CP2C.r)[14] +#define gteBBK ((s32*)psxRegs.CP2C.r)[15] +#define gteLR1 ((s16*)psxRegs.CP2C.r)[32] +#define gteLR2 ((s16*)psxRegs.CP2C.r)[33] +#define gteLR3 ((s16*)psxRegs.CP2C.r)[34] +#define gteLG1 ((s16*)psxRegs.CP2C.r)[35] +#define gteLG2 ((s16*)psxRegs.CP2C.r)[36] +#define gteLG3 ((s16*)psxRegs.CP2C.r)[37] +#define gteLB1 ((s16*)psxRegs.CP2C.r)[38] +#define gteLB2 ((s16*)psxRegs.CP2C.r)[39] +#define gteLB3 ((s16*)psxRegs.CP2C.r)[40] +#define gteRFC ((s32*)psxRegs.CP2C.r)[21] +#define gteGFC ((s32*)psxRegs.CP2C.r)[22] +#define gteBFC ((s32*)psxRegs.CP2C.r)[23] +#define gteOFX ((s32*)psxRegs.CP2C.r)[24] +#define gteOFY ((s32*)psxRegs.CP2C.r)[25] +#define gteH ((u16*)psxRegs.CP2C.r)[52] +#define gteDQA ((s16*)psxRegs.CP2C.r)[54] +#define gteDQB ((s32*)psxRegs.CP2C.r)[28] +#define gteZSF3 ((s16*)psxRegs.CP2C.r)[58] +#define gteZSF4 ((s16*)psxRegs.CP2C.r)[60] +#define gteFLAG psxRegs.CP2C.r[31] + +__inline unsigned long MFC2(int reg) { + switch(reg) { + case 29: + gteORGB = (gteIR1 ) | + (gteIR2 << 5) | + (gteIR3 << 10); +// gteORGB = ((gteIR1 & 0xf80)>>7) | +// ((gteIR2 & 0xf80)>>2) | +// ((gteIR3 & 0xf80)<<3); + return gteORGB; + + default: + return psxRegs.CP2D.r[reg]; + } +} + +__inline void MTC2(unsigned long value, int reg) { + int a; + + switch(reg) { + case 8: case 9: case 10: case 11: + psxRegs.CP2D.r[reg] = (short)value; + break; + + case 15: + psxRegs.CP2D.r[12] = psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13] = psxRegs.CP2D.r[14]; + psxRegs.CP2D.r[14] = value; + psxRegs.CP2D.r[15] = value; + break; + + case 16: case 17: case 18: case 19: + psxRegs.CP2D.r[reg] = (value & 0xffff); + break; + + case 28: + psxRegs.CP2D.r[28] = value; + gteIR1 = (value ) & 0x1f; + gteIR2 = (value >> 5) & 0x1f; + gteIR3 = (value >> 10) & 0x1f; +// gteIR1 = ((value ) & 0x1f) << 4; +// gteIR2 = ((value >> 5) & 0x1f) << 4; +// gteIR3 = ((value >> 10) & 0x1f) << 4; + break; + + case 30: + psxRegs.CP2D.r[30] = value; + + a = psxRegs.CP2D.r[30]; +#if defined(__MSCW32__) && !defined(__VCNET2005__) + if (a > 0) { + __asm { + mov eax, a; + bsr eax, eax; + mov a, eax; + } + psxRegs.CP2D.r[31] = 31 - a; + } else if (a < 0) { + __asm { + mov eax, a; + xor eax, 0xffffffff; + bsr eax, eax; + mov a, eax; + } + psxRegs.CP2D.r[31] = 31 - a; + } else { + psxRegs.CP2D.r[31] = 32; + } +#elif defined(__GNUC__) + if (a > 0) { + __asm__ ("bsrl %1, %0\n" : "=r"(a) : "r"(a) ); + psxRegs.CP2D.r[31] = 31 - a; + } else if (a < 0) { + a^= 0xffffffff; + __asm__ ("bsrl %1, %0\n" : "=r"(a) : "r"(a) ); + psxRegs.CP2D.r[31] = 31 - a; + } else { + psxRegs.CP2D.r[31] = 32; + } +#else + if (a > 0) { + int i; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else if (a < 0) { + int i; + a^= 0xffffffff; + for (i=31; (a & (1 << i)) == 0 && i >= 0; i--); + psxRegs.CP2D.r[31] = 31 - i; + } else { + psxRegs.CP2D.r[31] = 32; + } +#endif + break; + + default: + psxRegs.CP2D.r[reg] = value; + } +} + +void gteMFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = MFC2(_Rd_); +} + +void gteCFC2() { + if (!_Rt_) return; + psxRegs.GPR.r[_Rt_] = psxRegs.CP2C.r[_Rd_]; +} + +void gteMTC2() { + MTC2(psxRegs.GPR.r[_Rt_], _Rd_); +} + +void gteCTC2() { + psxRegs.CP2C.r[_Rd_] = psxRegs.GPR.r[_Rt_]; +} + +#define _oB_ (psxRegs.GPR.r[_Rs_] + _Imm_) + +void gteLWC2() { + MTC2(psxMemRead32(_oB_), _Rt_); +} + +void gteSWC2() { + psxMemWrite32(_oB_, MFC2(_Rt_)); +} + +/////LIMITATIONS AND OTHER STUFF************************************ +#define MAC2IR() \ +{ \ + if (gteMAC1 < (long)(-32768)) { gteIR1=(long)(-32768); gteFLAG|=1<<24;} \ + else \ + if (gteMAC1 > (long)( 32767)) { gteIR1=(long)( 32767); gteFLAG|=1<<24;} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)(-32768)) { gteIR2=(long)(-32768); gteFLAG|=1<<23;} \ + else \ + if (gteMAC2 > (long)( 32767)) { gteIR2=(long)( 32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)(-32768)) { gteIR3=(long)(-32768); gteFLAG|=1<<22;} \ + else \ + if (gteMAC3 > (long)( 32767)) { gteIR3=(long)( 32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + + +#define MAC2IR1() \ +{ \ + if (gteMAC1 < (long)0) { gteIR1=(long)0; gteFLAG|=1<<24;} \ + else if (gteMAC1 > (long)(32767)) { gteIR1=(long)(32767); gteFLAG|=1<<24;} \ + else gteIR1=(long)gteMAC1; \ + if (gteMAC2 < (long)0) { gteIR2=(long)0; gteFLAG|=1<<23;} \ + else if (gteMAC2 > (long)(32767)) { gteIR2=(long)(32767); gteFLAG|=1<<23;} \ + else gteIR2=(long)gteMAC2; \ + if (gteMAC3 < (long)0) { gteIR3=(long)0; gteFLAG|=1<<22;} \ + else if (gteMAC3 > (long)(32767)) { gteIR3=(long)(32767); gteFLAG|=1<<22;} \ + else gteIR3=(long)gteMAC3; \ +} + + + +/* +#define MAGIC (((65536. * 65536. * 16) + (65536.*.5)) * 65536.) + +static __inline long float2int(double d) +{ + double dtemp = MAGIC + d; + return (*(long *)&dtemp)-0x80000000; +}*/ +__inline double NC_OVERFLOW1(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<29;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<26;} + + return x; +} + +__inline double NC_OVERFLOW2(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<28;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<25;} + + return x; +} + +__inline double NC_OVERFLOW3(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<27;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<24;} + + return x; +} + +__inline double NC_OVERFLOW4(double x) +{ + if (x<-2147483648.0) {gteFLAG |= 1<<16;} + else + if (x> 2147483647.0) {gteFLAG |= 1<<15;} + + return x; +} +/* +__inline double EDETEC1(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<30; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<27; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC2(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<29; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<26; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC3(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<28; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<25; return (double) 2147483647;} + + else return data; +} + +__inline double EDETEC4(double data) +{ + if (data<(double)-2147483647) {gteFLAG|=1<<16; return (double)-2147483647;} + else + if (data>(double) 2147483647) {gteFLAG|=1<<15; return (double) 2147483647;} + + else return data; +}*/ +/* +double LimitAU(double fraction,unsigned long bitIndex) { + if (fraction < 0.0) { fraction = 0.0; gteFLAG |= (1< 32767.0) { fraction = 32767.0; gteFLAG |= (1< 32767.0) { fraction = 32767.0; gteFLAG |= (1< 255.0) { fraction = 255.0; gteFLAG |= (1< 65535.0) { fraction = 65535.0; gteFLAG |= (1< 1023.0) { fraction = 1023.0; gteFLAG |= (1< 1023.0) { fraction = 1023.0; gteFLAG |= (1<MAX) {gteFLAG|=1<MAX) return MAX; + + else return data; +} + +double OLIMIT(double data) +{ + data=(data); + + if (data<(double)-2147483647) {return (double)-2147483647;} + else + if (data>(double) 2147483647) {return (double) 2147483647;} + + else return data; +}*/ + +double limA1S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<24); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<24); } return (x); +} + +double limA2S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<23); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<23); } return (x); +} + +double limA3S(double x) { + + if (x <-32768.0) { x =-32768.0; gteFLAG |= (1<<22); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<22); } return (x); +} + +double limA1U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<24); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<24); } return (x); +} + +double limA2U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<23); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<23); } return (x); +} + +double limA3U(double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<22); } else + if (x > 32767.0) { x = 32767.0; gteFLAG |= (1<<22); } return (x); +} + +double limB1 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<21); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<21); } return (x); +} + +double limB2 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<20); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<20); } return (x); +} + +double limB3 (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<19); } else + if (x > 255.0) { x = 255.0; gteFLAG |= (1<<19); } return (x); +} + +double limC (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<18); } else + if (x > 65535.0) { x = 65535.0; gteFLAG |= (1<<18); } return (x); +} + +double limD1 (double x) { + + if (x < 1024.0) { x = 1024.0; gteFLAG |= (1<<14); } else + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<14); } return (x); +} + +double limD2 (double x) { + + if (x < 1024.0) { x = 1024.0; gteFLAG |= (1<<13); } else + if (x > 1023.0) { x = 1023.0; gteFLAG |= (1<<13); } return (x); +} + +double limE (double x) { + + if (x < 0.0) { x = 0.0; gteFLAG |= (1<<12); } else + if (x > 4095.0) { x = 4095.0; gteFLAG |= (1<<12); } return (x); +} + +double limG1(double x) { + + if (x > 2147483647.0f) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0f) { gteFLAG |= (1<<15); } + + if (x > 1023.0f) { x = 1023.0f; gteFLAG |= (1<<14); } else + if (x < -1024.0f) { x = -1024.0f; gteFLAG |= (1<<14); } return (x); +} + +double limG2(double x) { + + if (x > 2147483647.0f) { gteFLAG |= (1<<16); } else + if (x <-2147483648.0f) { gteFLAG |= (1<<15); } + + if (x > 1023.0f) { x = 1023.0f; gteFLAG |= (1<<13); } else + if (x < -1024.0f) { x = -1024.0f; gteFLAG |= (1<<13); } return (x); +} + +//********END OF LIMITATIONS**********************************/ + +void gteRTPS() { +// double SSX0,SSY0,SSZ0; +// double SZ; + double DSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPS", 14); + G_SD(0); + G_SD(1); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0*gteR11) + (double)(gteVY0*gteR12) + (double)(gteVZ0*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0*gteR21) + (double)(gteVY0*gteR22) + (double)(gteVZ0*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0*gteR31) + (double)(gteVY0*gteR32) + (double)(gteVZ0*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; + gteSZ2 = gteSZx; + gteSZx = (unsigned short)float2int(SZ); + + psxRegs.CP2D.r[12]= psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13]= psxRegs.CP2D.r[14]; + + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1024,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1024,13)); + + gteMAC1 = (signed long)(SSX0); + gteMAC2 = (signed long)(SSY0); + gteMAC3 = (signed long)(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + gteSZx = gteSZ0; + gteSZ0 = gteSZ1; + gteSZ1 = gteSZ2; + gteSZ2 = limC(gteMAC3); + + psxRegs.CP2D.r[12]= psxRegs.CP2D.r[13]; + psxRegs.CP2D.r[13]= psxRegs.CP2D.r[14]; + + DSZ = (double)gteH / gteSZ2; + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ) * 4096.0); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(12); + //G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteRTPT() { +// double SSX0,SSY0,SSZ0; +// double SZ; + double DSZ; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_RTPT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("RTPT", 22); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + + G_SD(16); // Store original fifo + G_SD(17); + G_SD(18); + G_SD(19); + + G_SC(0); + G_SC(1); + G_SC(2); + G_SC(3); + G_SC(4); + G_SC(5); + G_SC(6); + G_SC(7); + + G_SC(24); + G_SC(25); + G_SC(26); + G_SC(27); + G_SC(28); + } +#endif +/* gteFLAG = 0; + + gteSZ0 = gteSZx; + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX0 * gteR11) + (double)(gteVY0 * gteR12) + (double)(gteVZ0 * gteR13)) / 4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX0 * gteR21) + (double)(gteVY0 * gteR22) + (double)(gteVZ0 * gteR23)) / 4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX0 * gteR31) + (double)(gteVY0 * gteR32) + (double)(gteVZ0 * gteR33)) / 4096.0); + + SZ = LIMIT(SSZ0, (double)0, (double)65535, 18); + DSZ = ((double)gteH / SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ1 = (unsigned short)float2int(SZ); + gteSX0 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY0 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX1*gteR11) + (double)(gteVY1*gteR12) + (double)(gteVZ1*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX1*gteR21) + (double)(gteVY1*gteR22) + (double)(gteVZ1*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX1*gteR31) + (double)(gteVY1*gteR32) + (double)(gteVZ1*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZ2 = (unsigned short)float2int(SZ); + gteSX1 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY1 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + SSX0 = NC_OVERFLOW1((double)gteTRX + ((double)(gteVX2*gteR11) + (double)(gteVY2*gteR12) + (double)(gteVZ2*gteR13))/4096.0); + SSY0 = NC_OVERFLOW2((double)gteTRY + ((double)(gteVX2*gteR21) + (double)(gteVY2*gteR22) + (double)(gteVZ2*gteR23))/4096.0); + SSZ0 = NC_OVERFLOW3((double)gteTRZ + ((double)(gteVX2*gteR31) + (double)(gteVY2*gteR32) + (double)(gteVZ2*gteR33))/4096.0); + + SZ = LIMIT(SSZ0,(double)0,(double)65535,18); + DSZ = ((double)gteH/SZ); + + if ((DSZ>(double)2147483647)) {DSZ=(double)2; gteFLAG|=1<<17;} + + gteSZx = (unsigned short)float2int(SZ); + gteSX2 = (signed short)float2int(LIMIT((double)(gteOFX)/65536.0f + (LimitAS(SSX0,24)*DSZ),(double)-1024,(double)1023,14)); + gteSY2 = (signed short)float2int(LIMIT((double)(gteOFY)/65536.0f + (LimitAS(SSY0,23)*DSZ),(double)-1024,(double)1023,13)); + + gteMAC1 = (signed long)float2int(SSX0); + gteMAC2 = (signed long)float2int(SSY0); + gteMAC3 = (signed long)float2int(SSZ0); + + MAC2IR(); + + gteMAC0 = (signed long)float2int(OLIMIT((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*16777216)); + gteIR0 = (signed long)float2int(LIMIT(((((double)gteDQB/(double)16777216) + (((double)gteDQA/(double)256)*DSZ))*4096),(double)0,(double)4095,12)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + /* NC: old + gteFLAG = 0; + + gteSZ0 = gteSZx; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ1 = limC(gteMAC3); + + gteSX0 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY0 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX1 + gteR12*gteVY1 + gteR13*gteVZ1)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX1 + gteR22*gteVY1 + gteR23*gteVZ1)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX1 + gteR32*gteVY1 + gteR33*gteVZ1)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ2 = limC(gteMAC3); + + gteSX1 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY1 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX2 + gteR12*gteVY2 + gteR13*gteVZ2)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX2 + gteR22*gteVY2 + gteR23*gteVZ2)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX2 + gteR32*gteVY2 + gteR33*gteVZ2)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); if (DSZ > 2147483647.0f) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZx = gteSZ2; + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 4096.0f); + */ + + gteFLAG = 0; + + gteSZx = gteSZ2; + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX0 + gteR12*gteVY0 + gteR13*gteVZ0)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX0 + gteR22*gteVY0 + gteR23*gteVZ0)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX0 + gteR32*gteVY0 + gteR33*gteVZ0)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ0 = limC(gteMAC3); + + gteSX0 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ)); + gteSY0 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ)); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX1 + gteR12*gteVY1 + gteR13*gteVZ1)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX1 + gteR22*gteVY1 + gteR23*gteVZ1)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX1 + gteR32*gteVY1 + gteR33*gteVZ1)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ1 = limC(gteMAC3); + + gteSX1 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY1 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + gteMAC1 = NC_OVERFLOW1(((signed long)(gteR11*gteVX2 + gteR12*gteVY2 + gteR13*gteVZ2)>>12) + gteTRX); + gteMAC2 = NC_OVERFLOW2(((signed long)(gteR21*gteVX2 + gteR22*gteVY2 + gteR23*gteVZ2)>>12) + gteTRY); + gteMAC3 = NC_OVERFLOW3(((signed long)(gteR31*gteVX2 + gteR32*gteVY2 + gteR33*gteVZ2)>>12) + gteTRZ); + + DSZ = gteH / limC(gteMAC3); + if (DSZ > 2.0) { DSZ = 2.0f; gteFLAG |= 1<<17; } +// if (DSZ > 2147483647.0f) { DSZ = 2.0f; gteFLAG |= 1<<17; } + + gteSZ2 = limC(gteMAC3); + + gteSX2 = limG1(gteOFX/65536.0 + (limA1S(gteMAC1) * DSZ )); + gteSY2 = limG2(gteOFY/65536.0 + (limA2S(gteMAC2) * DSZ )); + + MAC2IR(); + + gteMAC0 = (gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 16777216.0; + gteIR0 = limE((gteDQB/16777216.0 + (gteDQA/256.0) * DSZ ) * 4096.0f); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(8); + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(12); + G_GD(13); + G_GD(14); + + G_GD(16); + G_GD(17); + G_GD(18); + G_GD(19); + + G_GD(24); + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gte_C11 gteLR1 +#define gte_C12 gteLR2 +#define gte_C13 gteLR3 +#define gte_C21 gteLG1 +#define gte_C22 gteLG2 +#define gte_C23 gteLG3 +#define gte_C31 gteLB1 +#define gte_C32 gteLB2 +#define gte_C33 gteLB3 + +#define _MVMVA_FUNC(_v0, _v1, _v2, mx) { \ + SSX = (_v0) * mx##11 + (_v1) * mx##12 + (_v2) * mx##13; \ + SSY = (_v0) * mx##21 + (_v1) * mx##22 + (_v2) * mx##23; \ + SSZ = (_v0) * mx##31 + (_v1) * mx##32 + (_v2) * mx##33; \ +} + +void gteMVMVA() { + double SSX, SSY, SSZ; + +#ifdef GTE_LOG + GTE_LOG("GTE_MVMVA %lx\n", psxRegs.code & 0x1ffffff); +#endif + + switch (psxRegs.code & 0x78000) { + case 0x00000: // V0 * R + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteR); break; + case 0x08000: // V1 * R + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteR); break; + case 0x10000: // V2 * R + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteR); break; + case 0x18000: // IR * R + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteR); + break; + case 0x20000: // V0 * L + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gteL); break; + case 0x28000: // V1 * L + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gteL); break; + case 0x30000: // V2 * L + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gteL); break; + case 0x38000: // IR * L + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gteL); break; + case 0x40000: // V0 * C + _MVMVA_FUNC(gteVX0, gteVY0, gteVZ0, gte_C); break; + case 0x48000: // V1 * C + _MVMVA_FUNC(gteVX1, gteVY1, gteVZ1, gte_C); break; + case 0x50000: // V2 * C + _MVMVA_FUNC(gteVX2, gteVY2, gteVZ2, gte_C); break; + case 0x58000: // IR * C + _MVMVA_FUNC((short)gteIR1, (short)gteIR2, (short)gteIR3, gte_C); break; + default: + SSX = SSY = SSZ = 0; + } + + if (psxRegs.code & 0x80000) { + SSX /= 4096.0; SSY /= 4096.0; SSZ /= 4096.0; + } + + switch (psxRegs.code & 0x6000) { + case 0x0000: // Add TR + SSX+= gteTRX; + SSY+= gteTRY; + SSZ+= gteTRZ; + break; + case 0x2000: // Add BK + SSX+= gteRBK; + SSY+= gteGBK; + SSZ+= gteBBK; + break; + case 0x4000: // Add FC + SSX+= gteRFC; + SSY+= gteGFC; + SSZ+= gteBFC; + break; + } + + gteFLAG = 0; + //gteMAC1 = (long)SSX; + //gteMAC2 = (long)SSY; + //gteMAC3 = (long)SSZ;//okay the follow lines are correct?? + gteMAC1=NC_OVERFLOW1(SSX); + gteMAC2=NC_OVERFLOW2(SSY); + gteMAC3=NC_OVERFLOW3(SSZ); + if (psxRegs.code & 0x400) + MAC2IR1() + else MAC2IR() + + SUM_FLAG; +} + +void gteNCLIP() { +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCLIP\n"); +#endif + + //gteLog + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCLIP", 8); + G_SD(12); + G_SD(13); + G_SD(14); + } +#endif + +/* gteFLAG = 0; + + gteMAC0 = (signed long)float2int(EDETEC4( + ((double)gteSX0*((double)gteSY1-(double)gteSY2))+ + ((double)gteSX1*((double)gteSY2-(double)gteSY0))+ + ((double)gteSX2*((double)gteSY0-(double)gteSY1)))); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + + gteMAC0 = gteSX0 * (gteSY1 - gteSY2) + + gteSX1 * (gteSY2 - gteSY0) + + gteSX2 * (gteSY0 - gteSY1); + + //gteMAC0 = (gteSX0 - gteSX1) * (gteSY0 - gteSY2) - (gteSX0 - gteSX2) * (gteSY0 - gteSY1); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ3() { +// unsigned long SS; +// double SZ1,SZ2,SZ3; +// double ZSF3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ3\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ3", 5); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[29] & 0xffff; ZSF3 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ1+SZ2+SZ3)*ZSF3))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ1+SZ2+SZ3)*ZSF3),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + + + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ1 + gteSZ2 + gteSZx) * (gteZSF3)); + + gteOTZ = limC((double)(gteMAC0 >> 12));*/ + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF3)) >> 12; + + gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteAVSZ4() { +// unsigned long SS; +// double SZ0,SZ1,SZ2,SZ3; +// double ZSF4; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_AVSZ4\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("AVSZ4", 6); + G_SD(16); + G_SD(17); + G_SD(18); + G_SD(19); + G_SC(29); + G_SC(30); + } +#endif + +/* gteFLAG = 0; + + SS = psxRegs.CP2D.r[16] & 0xffff; SZ0 = (double)SS; + SS = psxRegs.CP2D.r[17] & 0xffff; SZ1 = (double)SS; + SS = psxRegs.CP2D.r[18] & 0xffff; SZ2 = (double)SS; + SS = psxRegs.CP2D.r[19] & 0xffff; SZ3 = (double)SS; + SS = psxRegs.CP2C.r[30] & 0xffff; ZSF4 = (double)SS/(double)4096; + + psxRegs.CP2D.r[24] = (signed long)float2int(EDETEC4(((SZ0+SZ1+SZ2+SZ3)*ZSF4))); + psxRegs.CP2D.r[7] = (unsigned short)float2int(LimitC(((SZ0+SZ1+SZ2+SZ3)*ZSF4),18)); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + /* NC: OLD + gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4/4096.0f)); + + gteOTZ = limC((double)gteMAC0); + */ +/* gteMAC0 = ((gteSZ0 + gteSZ1 + gteSZ2 + gteSZx) * (gteZSF4)); + + gteOTZ = limC((double)(gteMAC0 >> 12)); +*/ + gteMAC0 = ((gteSZx + gteSZ0 + gteSZ1 + gteSZ2) * (gteZSF4))>> 12; + + gteOTZ = limC((double)gteMAC0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(7); + G_GD(24); + G_GC(31); + } +#endif +} + +void gteSQR() { + //double SSX0,SSY0,SSZ0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_SQR %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("SQR", 5); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif + +/* gteFLAG = 0; + + SSX0 = (double)gteIR1 * gteIR1; + SSY0 = (double)gteIR2 * gteIR2; + SSZ0 = (double)gteIR3 * gteIR3; + + if (psxRegs.code & 0x80000) { + SSX0 /= 4096.0; SSY0 /= 4096.0; SSZ0 /= 4096.0; + } + + gteMAC1 = (long)SSX0; + gteMAC2 = (long)SSY0; + gteMAC3 = (long)SSZ0; + + MAC2IR1(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1((gteIR1 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR2 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR3 * gteIR3) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteIR1 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR2 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR3 * gteIR3); + } + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + G_GD(25); + G_GD(26); + G_GD(27); + G_GC(31); + } +#endif +} +/* +#define GTE_NCCS(vn) { \ + RR0 = ((double)gteL11 * gteVX##vn + (double)gteL12 * gteVY##vn + (double)gteL13 * gteVZ##vn)/4096.0; \ + GG0 = ((double)gteL21 * gteVX##vn + (double)gteL22 * gteVY##vn + (double)gteL23 * gteVZ##vn)/4096.0; \ + BB0 = ((double)gteL31 * gteVX##vn + (double)gteL32 * gteVY##vn + (double)gteL33 * gteVZ##vn)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3)/4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3)/4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3)/4096.0; \ + t1 = LimitAU(RR0,24); \ + t2 = LimitAU(GG0,23); \ + t3 = LimitAU(BB0,22); \ + \ + RR0 = ((double)gteR * t1)/256.0; \ + GG0 = ((double)gteG * t2)/256.0; \ + BB0 = ((double)gteB * t3)/256.0; \ + \ + gteIR1 = (long)LimitAU(RR0,24); \ + gteIR2 = (long)LimitAU(GG0,23); \ + gteIR3 = (long)LimitAU(BB0,22); \ + \ + gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE; \ + gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +/* +__forceinline double ncLIM1(double x) +{ + if(x > 8796093022207.0) + { + return 8796093022207.0; + } +} +*/ + + + +/* NC: OLD +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = gteR*gte_RRLT;\ +gte_GG0 = gteG*gte_GGLT;\ +gte_BB0 = gteB*gte_BBLT;\ +gteIR1 = (long)limA1U(gte_RR0);\ +gteIR2 = (long)limA2U(gte_GG0);\ +gteIR3 = (long)limA3U(gte_BB0);\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);\ +gteMAC1 = (long)gte_RR0;\ +gteMAC2 = (long)gte_GG0;\ +gteMAC3 = (long)gte_BB0;\ +*/ + +#define GTE_NCCS(vn)\ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gteMAC1 = (long)(gteR*gte_RRLT*16);\ +gteMAC2 = (long)(gteG*gte_GGLT*16);\ +gteMAC3 = (long)(gteB*gte_BBLT*16);\ +gteIR1 = (long)limA1U(gteMAC1);\ +gteIR2 = (long)limA2U(gteMAC2);\ +gteIR3 = (long)limA3U(gteMAC3);\ +gte_RR0 = gteMAC1>>4;\ +gte_GG0 = gteMAC2>>4;\ +gte_BB0 = gteMAC3>>4;\ +gteCODE0 = gteCODE1; gteCODE1 = gteCODE2; gteCODE2 = gteCODE;\ +gteR0 = gteR1; gteR1 = gteR2; gteR2 = (unsigned char)limB1(gte_RR0);\ +gteG0 = gteG1; gteG1 = gteG2; gteG2 = (unsigned char)limB2(gte_GG0);\ +gteB0 = gteB1; gteB1 = gteB2; gteB2 = (unsigned char)limB3(gte_BB0);\ + +void gteNCCS() { +// double RR0,GG0,BB0; +// double t1, t2, t3; + + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCS\n"); +#endif + +/* + gteFLAG = 0; + + GTE_NCCS(0); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCS", 17); + G_SD(0); + G_SD(1); + G_SD(6); + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCCT() { +// double RR0,GG0,BB0; +// double t1, t2, t3; + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCCT\n"); +#endif + + + /*gteFLAG = 0; + + GTE_NCCS(0); + GTE_NCCS(1); + GTE_NCCS(2); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCCT", 39); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif + + gteFLAG = 0; + + GTE_NCCS(0); + GTE_NCCS(1); + GTE_NCCS(2); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + //G_GD(24); Doc must be wrong. PSX does not touch it. + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define GTE_NCDS(vn) \ +gte_LL1 = limA1U((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/16777216.0f);\ +gte_LL2 = limA2U((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/16777216.0f);\ +gte_LL3 = limA3U((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/16777216.0f);\ +gte_RRLT= limA1U(gteRBK/4096.0f + (gteLR1/4096.0f*gte_LL1 + gteLR2/4096.0f*gte_LL2 + gteLR3/4096.0f*gte_LL3));\ +gte_GGLT= limA2U(gteGBK/4096.0f + (gteLG1/4096.0f*gte_LL1 + gteLG2/4096.0f*gte_LL2 + gteLG3/4096.0f*gte_LL3));\ +gte_BBLT= limA3U(gteBBK/4096.0f + (gteLB1/4096.0f*gte_LL1 + gteLB2/4096.0f*gte_LL2 + gteLB3/4096.0f*gte_LL3));\ +gte_RR0 = (gteR*gte_RRLT) + (gteIR0/4096.0f * limA1S(gteRFC/16.0f - (gteR*gte_RRLT)));\ +gte_GG0 = (gteG*gte_GGLT) + (gteIR0/4096.0f * limA2S(gteGFC/16.0f - (gteG*gte_GGLT)));\ +gte_BB0 = (gteB*gte_BBLT) + (gteIR0/4096.0f * limA3S(gteBFC/16.0f - (gteB*gte_BBLT)));\ +gteMAC1= (long)(gte_RR0 * 16.0f); gteIR1 = (long)limA1U(gte_RR0*16.0f);\ +gteMAC2= (long)(gte_GG0 * 16.0f); gteIR2 = (long)limA2U(gte_GG0*16.0f);\ +gteMAC3= (long)(gte_BB0 * 16.0f); gteIR3 = (long)limA3U(gte_BB0*16.0f);\ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = limB1(gte_RR0); \ +gteG2 = limB2(gte_GG0); \ +gteB2 = limB3(gte_BB0); gteCODE2 = gteCODE; + +void gteNCDS() { +/* double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B; */ + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDS\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDS", 19); + G_SD(0); + G_SD(1); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCDT() { + /*double tRLT,tRRLT; + double tGLT,tGGLT; + double tBLT,tBBLT; + double tRR0,tL1,tLL1; + double tGG0,tL2,tLL2; + double tBB0,tL3,tLL3; + unsigned long C,R,G,B;*/ + double gte_LL1, gte_RR0, gte_RRLT; + double gte_LL2, gte_GG0, gte_GGLT; + double gte_LL3, gte_BB0, gte_BBLT; + +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_NCDT\n"); +#endif + +/* gteFLAG = 0; + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX0/4096.0) + (gteL12/4096.0 * gteVY0/4096.0) + (gteL13/4096.0 * gteVZ0/4096.0); + tLL2 = (gteL21/4096.0 * gteVX0/4096.0) + (gteL22/4096.0 * gteVY0/4096.0) + (gteL23/4096.0 * gteVZ0/4096.0); + tLL3 = (gteL31/4096.0 * gteVX0/4096.0) + (gteL32/4096.0 * gteVY0/4096.0) + (gteL33/4096.0 * gteVZ0/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX1/4096.0) + (gteL12/4096.0 * gteVY1/4096.0) + (gteL13/4096.0 * gteVZ1/4096.0); + tLL2 = (gteL21/4096.0 * gteVX1/4096.0) + (gteL22/4096.0 * gteVY1/4096.0) + (gteL23/4096.0 * gteVZ1/4096.0); + tLL3 = (gteL31/4096.0 * gteVX1/4096.0) + (gteL32/4096.0 * gteVY1/4096.0) + (gteL33/4096.0 * gteVZ1/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + tLL1 = (gteL11/4096.0 * gteVX2/4096.0) + (gteL12/4096.0 * gteVY2/4096.0) + (gteL13/4096.0 * gteVZ2/4096.0); + tLL2 = (gteL21/4096.0 * gteVX2/4096.0) + (gteL22/4096.0 * gteVY2/4096.0) + (gteL23/4096.0 * gteVZ2/4096.0); + tLL3 = (gteL31/4096.0 * gteVX2/4096.0) + (gteL32/4096.0 * gteVY2/4096.0) + (gteL33/4096.0 * gteVZ2/4096.0); + + tL1 = LimitAU(tLL1,24); + tL2 = LimitAU(tLL2,23); + tL3 = LimitAU(tLL3,22); + + tRRLT = gteRBK/4096.0 + (gteLR1/4096.0 * tL1) + (gteLR2/4096.0 * tL2) + (gteLR3/4096.0 * tL3); + tGGLT = gteGBK/4096.0 + (gteLG1/4096.0 * tL1) + (gteLG2/4096.0 * tL2) + (gteLG3/4096.0 * tL3); + tBBLT = gteBBK/4096.0 + (gteLB1/4096.0 * tL1) + (gteLB2/4096.0 * tL2) + (gteLB3/4096.0 * tL3); + + tRLT = LimitAU(tRRLT,24); + tGLT = LimitAU(tGGLT,23); + tBLT = LimitAU(tBBLT,22); + + tRR0 = (R * tRLT) + (gteIR0/4096.0 * LimitAS(gteRFC/16.0 - (R * tRLT),24)); + tGG0 = (G * tGLT) + (gteIR0/4096.0 * LimitAS(gteGFC/16.0 - (G * tGLT),23)); + tBB0 = (B * tBLT) + (gteIR0/4096.0 * LimitAS(gteBFC/16.0 - (B * tBLT),22)); + + gteMAC1 = (long)(tRR0 * 16.0); gteIR1 = (long)LimitAU((tRR0*16.0),24); + gteMAC2 = (long)(tGG0 * 16.0); gteIR2 = (long)LimitAU((tGG0*16.0),23); + gteMAC3 = (long)(tBB0 * 16.0); gteIR3 = (long)LimitAU((tBB0*16.0),22); + + R = (unsigned long)LimitB(tRR0,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(tGG0,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(tBB0,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCDT", 44); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + G_SD(8); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + GTE_NCDS(0); + GTE_NCDS(1); + GTE_NCDS(2); + + SUM_FLAG; + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +#define gteD1 (*(short *)>eR11) +#define gteD2 (*(short *)>eR22) +#define gteD3 (*(short *)>eR33) + +void gteOP() { +// double SSX0=0,SSY0=0,SSZ0=0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif + +#ifdef GTE_LOG + GTE_LOG("GTE_OP %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("OP", 6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(0); + G_SC(2); + G_SC(4); + } +#endif +/* gteFLAG=0; + + switch (psxRegs.code & 0x1ffffff) { + case 0x178000C://op12 + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)/(double)4096); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)/(double)4096); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)/(double)4096); + break; + case 0x170000C: + SSX0 = EDETEC1((gteR22*(short)gteIR3 - gteR33*(short)gteIR2)); + SSY0 = EDETEC2((gteR33*(short)gteIR1 - gteR11*(short)gteIR3)); + SSZ0 = EDETEC3((gteR11*(short)gteIR2 - gteR22*(short)gteIR1)); + break; + } + + gteMAC1 = (long)float2int(SSX0); + gteMAC2 = (long)float2int(SSY0); + gteMAC3 = (long)float2int(SSZ0); + + MAC2IR(); + + if (gteIR1<0) gteIR1=0; + if (gteIR2<0) gteIR2=0; + if (gteIR3<0) gteIR3=0; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1((gteD2 * gteIR3 - gteD3 * gteIR2) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteD3 * gteIR1 - gteD1 * gteIR3) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteD1 * gteIR2 - gteD2 * gteIR1) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteD2 * gteIR3 - gteD3 * gteIR2); + gteMAC2 = NC_OVERFLOW2(gteD3 * gteIR1 - gteD1 * gteIR3); + gteMAC3 = NC_OVERFLOW3(gteD1 * gteIR2 - gteD2 * gteIR1); + } + + /* NC: old + MAC2IR1(); + */ + MAC2IR(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDCPL() { +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DCPL\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DCPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* R = ((gteRGB)&0xff); + G = ((gteRGB>> 8)&0xff); + B = ((gteRGB>>16)&0xff); + C = ((gteRGB>>24)&0xff); + + gteMAC1 = (signed long)((double)(R*gteIR1) + (double)(gteIR0*LimitAS(gteRFC-(double)(R*gteIR1),24))/4096.0); + gteMAC2 = (signed long)((double)(G*gteIR2) + (double)(gteIR0*LimitAS(gteGFC-(double)(G*gteIR2),23))/4096.0); + gteMAC3 = (signed long)((double)(B*gteIR3) + (double)(gteIR0*LimitAS(gteBFC-(double)(B*gteIR3),22))/4096.0); + + MAC2IR() + + R = (unsigned long)LimitB(gteMAC1,21); if (R>255) R=255; else if (R<0) R=0; + G = (unsigned long)LimitB(gteMAC2,20); if (G>255) G=255; else if (G<0) G=0; + B = (unsigned long)LimitB(gteMAC3,19); if (B>255) B=255; else if (B<0) B=0; + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = R|(G<<8)|(B<<16)|(C<<24); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * gteIR1) / 256.0f + (gteIR0 * limA1S(gteRFC - ((gteR * gteIR1) / 256.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * gteIR1) / 256.0f + (gteIR0 * limA2S(gteGFC - ((gteG * gteIR1) / 256.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * gteIR1) / 256.0f + (gteIR0 * limA3S(gteBFC - ((gteB * gteIR1) / 256.0f))) / 4096.0f); + */ +/* gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>6; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>6; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>6;*/ + + gteMAC1 = ( (signed long)(gteR)*gteIR1 + (gteIR0*(signed short)limA1S(gteRFC - ((gteR*gteIR1)>>12) )) ) >>8; + gteMAC2 = ( (signed long)(gteG)*gteIR2 + (gteIR0*(signed short)limA2S(gteGFC - ((gteG*gteIR2)>>12) )) ) >>8; + gteMAC3 = ( (signed long)(gteB)*gteIR3 + (gteIR0*(signed short)limA3S(gteBFC - ((gteB*gteIR3)>>12) )) ) >>8; + + gteFLAG=0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPF() { +// double ipx, ipy, ipz; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPF %lx\n", psxRegs.code & 0x1ffffff); +#endif +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPF", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + } +#endif +/* gteFLAG = 0; + + ipx = (double)((short)gteIR0) * ((short)gteIR1); + ipy = (double)((short)gteIR0) * ((short)gteIR2); + ipz = (double)((short)gteIR0) * ((short)gteIR3); + + // same as mvmva + if (psxRegs.code & 0x80000) { + ipx /= 4096.0; ipy /= 4096.0; ipz /= 4096.0; + } + + gteMAC1 = (long)ipx; + gteMAC2 = (long)ipy; + gteMAC3 = (long)ipz; + + gteIR1 = (long)LimitAS(ipx,24); + gteIR2 = (long)LimitAS(ipy,23); + gteIR3 = (long)LimitAS(ipz,22); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteC2 = gteCODE; + gteR2 = (unsigned char)LimitB(ipx,21); + gteG2 = (unsigned char)LimitB(ipy,20); + gteB2 = (unsigned char)LimitB(ipz,19);*/ + + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + gteMAC1 = NC_OVERFLOW1((gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteIR0 * gteIR3) / 4096.0f); + } else { + gteMAC1 = NC_OVERFLOW1(gteIR0 * gteIR1); + gteMAC2 = NC_OVERFLOW2(gteIR0 * gteIR2); + gteMAC3 = NC_OVERFLOW3(gteIR0 * gteIR3); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteGPL() { + // double IPX=0,IPY=0,IPZ=0; +// unsigned long C,R,G,B; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_GPL %lx\n", psxRegs.code & 0x1ffffff); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("GPL", 5); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SD(25); + G_SD(26); + G_SD(27); + } +#endif + +/* gteFLAG=0; + switch(psxRegs.code & 0x1ffffff) { + case 0x1A8003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)/4096.0f); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)/4096.0f); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)/4096.0f); + break; + + case 0x1A0003E: + IPX = EDETEC1((double)gteMAC1 + ((double)gteIR0*(double)gteIR1)); + IPY = EDETEC2((double)gteMAC2 + ((double)gteIR0*(double)gteIR2)); + IPZ = EDETEC3((double)gteMAC3 + ((double)gteIR0*(double)gteIR3)); + break; + } + gteIR1 = (short)float2int(LimitAS(IPX,24)); + gteIR2 = (short)float2int(LimitAS(IPY,23)); + gteIR3 = (short)float2int(LimitAS(IPZ,22)); + + gteMAC1 = (int)float2int(IPX); + gteMAC2 = (int)float2int(IPY); + gteMAC3 = (int)float2int(IPZ); + + C = gteRGB & 0xff000000; + R = float2int(ALIMIT(IPX,0,255)); + G = float2int(ALIMIT(IPY,0,255)); + B = float2int(ALIMIT(IPZ,0,255)); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + gteRGB2 = C|R|(G<<8)|(B<<16);*/ + gteFLAG = 0; + + if (psxRegs.code & 0x80000) { + + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1) / 4096.0f); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2) / 4096.0f); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3) / 4096.0f); + } else { + + gteMAC1 = NC_OVERFLOW1(gteMAC1 + (gteIR0 * gteIR1)); + gteMAC2 = NC_OVERFLOW2(gteMAC2 + (gteIR0 * gteIR2)); + gteMAC3 = NC_OVERFLOW3(gteMAC3 + (gteIR0 * gteIR3)); + } + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_DPCS() { \ + RR0 = (double)R + (gteIR0*LimitAS((double)(gteRFC - R),24))/4096.0; \ + GG0 = (double)G + (gteIR0*LimitAS((double)(gteGFC - G),23))/4096.0; \ + BB0 = (double)B + (gteIR0*LimitAS((double)(gteBFC - B),22))/4096.0; \ + \ + gteIR1 = (long)LimitAS(RR0,24); \ + gteIR2 = (long)LimitAS(GG0,23); \ + gteIR3 = (long)LimitAS(BB0,22); \ + \ + gteRGB0 = gteRGB1; \ + gteRGB1 = gteRGB2; \ + gteC2 = C; \ + gteR2 = (unsigned char)LimitB(RR0/16.0,21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0,20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0,19); \ + \ + gteMAC1 = (long)RR0; \ + gteMAC2 = (long)GG0; \ + gteMAC3 = (long)BB0; \ +} +*/ +void gteDPCS() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCS", 8); + G_SD(6); + G_SD(8); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + +/* gteFLAG = 0; + + C = gteCODE; + R = gteR * 16.0; + G = gteG * 16.0; + B = gteB * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR * 16.0f) + (gteIR0 * limA1S(gteRFC - (gteR * 16.0f))) / 4096.0f); + gteMAC2 = NC_OVERFLOW2((gteG * 16.0f) + (gteIR0 * limA2S(gteGFC - (gteG * 16.0f))) / 4096.0f); + gteMAC3 = NC_OVERFLOW3((gteB * 16.0f) + (gteIR0 * limA3S(gteBFC - (gteB * 16.0f))) / 4096.0f); + */ + gteMAC1 = (gteR<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR<<4)) ) >>12); + gteMAC2 = (gteG<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG<<4)) ) >>12); + gteMAC3 = (gteB<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB<<4)) ) >>12); + + gteFLAG = 0; + MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteDPCT() { +// unsigned long C,R,G,B; +// double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_DPCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("DPCT", 17); + G_SD(8); + + G_SD(20); + G_SD(21); + G_SD(22); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif +/* gteFLAG = 0; + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + C = gteCODE0; + R = gteR0 * 16.0; + G = gteG0 * 16.0; + B = gteB0 * 16.0; + + GTE_DPCS(); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ +/* gteFLAG = 0; + + gteMAC1 = NC_OVERFLOW1((gteR0 * 16.0f) + gteIR0 * limA1S(gteRFC - (gteR0 * 16.0f))); + gteMAC2 = NC_OVERFLOW2((gteG0 * 16.0f) + gteIR0 * limA2S(gteGFC - (gteG0 * 16.0f))); + gteMAC3 = NC_OVERFLOW3((gteB0 * 16.0f) + gteIR0 * limA3S(gteBFC - (gteB0 * 16.0f))); + */ + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); +// MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + gteMAC1 = (gteR0<<4) + ( (gteIR0*(signed short)limA1S(gteRFC-(gteR0<<4)) ) >>12); + gteMAC2 = (gteG0<<4) + ( (gteIR0*(signed short)limA2S(gteGFC-(gteG0<<4)) ) >>12); + gteMAC3 = (gteB0<<4) + ( (gteIR0*(signed short)limA3S(gteBFC-(gteB0<<4)) ) >>12); + gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +/* +#define GTE_NCS(vn) { \ + RR0 = ((double)gteVX##vn * gteL11 + (double)gteVY##vn * (double)gteL12 + (double)gteVZ##vn * gteL13) / 4096.0; \ + GG0 = ((double)gteVX##vn * gteL21 + (double)gteVY##vn * (double)gteL22 + (double)gteVZ##vn * gteL23) / 4096.0; \ + BB0 = ((double)gteVX##vn * gteL31 + (double)gteVY##vn * (double)gteL32 + (double)gteVZ##vn * gteL33) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + RR0 = (double)gteRBK + ((double)gteLR1 * t1 + (double)gteLR2 * t2 + (double)gteLR3 * t3) / 4096.0; \ + GG0 = (double)gteGBK + ((double)gteLG1 * t1 + (double)gteLG2 * t2 + (double)gteLG3 * t3) / 4096.0; \ + BB0 = (double)gteBBK + ((double)gteLB1 * t1 + (double)gteLB2 * t2 + (double)gteLB3 * t3) / 4096.0; \ + t1 = LimitAU(RR0, 24); \ + t2 = LimitAU(GG0, 23); \ + t3 = LimitAU(BB0, 22); \ + \ + gteRGB0 = gteRGB1; gteRGB1 = gteRGB2; \ + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); \ + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); \ + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); \ + gteCODE2=gteCODE0; \ +}*/ + +#define LOW(a) (((a) < 0) ? 0 : (a)) + +#define GTE_NCS(vn) \ +RR0 = LOW((gteL11*gteVX##vn + gteL12*gteVY##vn + gteL13*gteVZ##vn)/4096.0f); \ +GG0 = LOW((gteL21*gteVX##vn + gteL22*gteVY##vn + gteL23*gteVZ##vn)/4096.0f); \ +BB0 = LOW((gteL31*gteVX##vn + gteL32*gteVY##vn + gteL33*gteVZ##vn)/4096.0f); \ +gteMAC1 = gteRBK + (gteLR1*RR0 + gteLR2*GG0 + gteLR3*BB0)/4096.0f; \ +gteMAC2 = gteGBK + (gteLG1*RR0 + gteLG2*GG0 + gteLG3*BB0)/4096.0f; \ +gteMAC3 = gteBBK + (gteLB1*RR0 + gteLB2*GG0 + gteLB3*BB0)/4096.0f; \ +gteRGB0 = gteRGB1; \ +gteRGB1 = gteRGB2; \ +gteR2 = limB1(gteMAC1 / 16.0f); \ +gteG2 = limB2(gteMAC2 / 16.0f); \ +gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + +void gteNCS() { + double RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_NCS\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCS", 14); + G_SD(0); + G_SD(1); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* gteFLAG = 0; + + GTE_NCS(0); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteNCT() { + double RR0,GG0,BB0; +// double t1, t2, t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_NCT\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("NCT", 30); + G_SD(0); + G_SD(1); + G_SD(2); + G_SD(3); + G_SD(4); + G_SD(5); + G_SD(6); + + G_SC(8); + G_SC(9); + G_SC(10); + G_SC(11); + G_SC(12); + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + } +#endif +/* + gteFLAG = 0; + +//V0 + GTE_NCS(0); +//V1 + GTE_NCS(1); +//V2 + GTE_NCS(2); + + gteMAC1=(long)RR0; + gteMAC2=(long)GG0; + gteMAC3=(long)BB0; + + gteIR1=(long)t1; + gteIR2=(long)t2; + gteIR3=(long)t3; + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + GTE_NCS(0); + GTE_NCS(1); + GTE_NCS(2); + + MAC2IR1(); + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + G_GD(20); + G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCC() { + double RR0,GG0,BB0; +// double t1,t2,t3; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_CC\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CC", 11); + G_SD(6); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + } +#endif +/* gteFLAG = 0; + + RR0 = (double)gteRBK + ((double)gteLR1 * gteIR1 + (double)gteLR2 * gteIR2 + (double)gteLR3 * gteIR3) / 4096.0; + GG0 = (double)gteGBK + ((double)gteLG1 * gteIR1 + (double)gteLG2 * gteIR2 + (double)gteLG3 * gteIR3) / 4096.0; + BB0 = (double)gteBBK + ((double)gteLB1 * gteIR1 + (double)gteLB2 * gteIR2 + (double)gteLB3 * gteIR3) / 4096.0; + t1 = LimitAU(RR0, 24); + t2 = LimitAU(GG0, 23); + t3 = LimitAU(BB0, 22); + + RR0=((double)gteR * t1)/256.0; + GG0=((double)gteG * t2)/256.0; + BB0=((double)gteB * t3)/256.0; + gteIR1 = (long)LimitAU(RR0,24); + gteIR2 = (long)LimitAU(GG0,23); + gteIR3 = (long)LimitAU(BB0,22); + + gteCODE0=gteCODE1; gteCODE1=gteCODE2; + gteC2 = gteCODE0; + gteR2 = (unsigned char)LimitB(RR0/16.0, 21); + gteG2 = (unsigned char)LimitB(GG0/16.0, 20); + gteB2 = (unsigned char)LimitB(BB0/16.0, 19); + + if (gteFLAG & 0x7f87e000) gteFLAG|=0x80000000;*/ + gteFLAG = 0; + + RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 + gteLR2*gteIR2 + gteLR3*gteIR3) / 4096.0f); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 + gteLG2*gteIR2 + gteLG3*gteIR3) / 4096.0f); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 + gteLB2*gteIR2 + gteLB3*gteIR3) / 4096.0f); + + gteMAC1 = gteR * RR0 / 256.0f; + gteMAC2 = gteG * GG0 / 256.0f; + gteMAC3 = gteB * BB0 / 256.0f; + + MAC2IR1(); + + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteINTPL() { //test opcode +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_INTP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("INTPL", 8); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + /* NC: old + gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*limA1S(gteRFC-gteIR1); + gteMAC2 = gteIR2 + gteIR0*limA2S(gteGFC-gteIR2); + gteMAC3 = gteIR3 + gteIR0*limA3S(gteBFC-gteIR3); + //gteFLAG = 0; + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + */ + +/* gteFLAG=0; + gteMAC1 = gteIR1 + gteIR0*(gteRFC-gteIR1)/4096.0; + gteMAC2 = gteIR2 + gteIR0*(gteGFC-gteIR2)/4096.0; + gteMAC3 = gteIR3 + gteIR0*(gteBFC-gteIR3)/4096.0; + + //gteMAC3 = (int)((((psxRegs).CP2D).n).ir3+(((psxRegs).CP2D).n).ir0 * ((((psxRegs).CP2C).n).bfc-(((psxRegs).CP2D).n).ir3)/4096.0); + + if(gteMAC3 > gteIR1 && gteMAC3 > gteBFC) + { + gteMAC3 = gteMAC3; + } + //gteFLAG = 0;*/ + //NEW CODE + gteMAC1 = gteIR1 + ((gteIR0*(signed short)limA1S(gteRFC-gteIR1))>>12); + gteMAC2 = gteIR2 + ((gteIR0*(signed short)limA2S(gteGFC-gteIR2))>>12); + gteMAC3 = gteIR3 + ((gteIR0*(signed short)limA3S(gteBFC-gteIR3))>>12); + gteFLAG = 0; + + MAC2IR(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} + +void gteCDP() { //test opcode + double RR0,GG0,BB0; +#ifdef GTE_DUMP + static int sample = 0; sample++; +#endif +#ifdef GTE_LOG + GTE_LOG("GTE_CDP\n"); +#endif + +#ifdef GTE_DUMP + if(sample < 100) + { + G_OP("CDP", 13); + G_SD(6); + G_SD(8); + G_SD(9); + G_SD(10); + G_SD(11); + + G_SC(13); + G_SC(14); + G_SC(15); + G_SC(16); + G_SC(17); + G_SC(18); + G_SC(19); + G_SC(20); + G_SC(21); + G_SC(22); + G_SC(23); + } +#endif + + gteFLAG = 0; + + RR0 = NC_OVERFLOW1(gteRBK + (gteLR1*gteIR1 +gteLR2*gteIR2 + gteLR3*gteIR3)); + GG0 = NC_OVERFLOW2(gteGBK + (gteLG1*gteIR1 +gteLG2*gteIR2 + gteLG3*gteIR3)); + BB0 = NC_OVERFLOW3(gteBBK + (gteLB1*gteIR1 +gteLB2*gteIR2 + gteLB3*gteIR3)); + gteMAC1 = gteR*RR0 + gteIR0*limA1S(gteRFC-gteR*RR0); + gteMAC2 = gteG*GG0 + gteIR0*limA2S(gteGFC-gteG*GG0); + gteMAC3 = gteB*BB0 + gteIR0*limA3S(gteBFC-gteB*BB0); + MAC2IR1(); + gteRGB0 = gteRGB1; + gteRGB1 = gteRGB2; + + gteR2 = limB1(gteMAC1 / 16.0f); + gteG2 = limB2(gteMAC2 / 16.0f); + gteB2 = limB3(gteMAC3 / 16.0f); gteCODE2 = gteCODE; + + SUM_FLAG + +#ifdef GTE_DUMP + if(sample < 100) + { + G_GD(9); + G_GD(10); + G_GD(11); + + //G_GD(20); + //G_GD(21); + G_GD(22); + + G_GD(25); + G_GD(26); + G_GD(27); + + G_GC(31); + } +#endif +} diff --git a/branches/pcsx2_0.9.1/Gte.h b/branches/pcsx2_0.9.1/Gte.h new file mode 100644 index 0000000..eaffa88 --- /dev/null +++ b/branches/pcsx2_0.9.1/Gte.h @@ -0,0 +1,52 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GTE_H__ +#define __GTE_H__ + +void gteMFC2(); +void gteCFC2(); +void gteMTC2(); +void gteCTC2(); +void gteLWC2(); +void gteSWC2(); + +void gteRTPS(); +void gteOP(); +void gteNCLIP(); +void gteDPCS(); +void gteINTPL(); +void gteMVMVA(); +void gteNCDS(); +void gteNCDT(); +void gteCDP(); +void gteNCCS(); +void gteCC(); +void gteNCS(); +void gteNCT(); +void gteSQR(); +void gteDCPL(); +void gteDPCT(); +void gteAVSZ3(); +void gteAVSZ4(); +void gteRTPT(); +void gteGPF(); +void gteGPL(); +void gteNCCT(); + +#endif /* __GTE_H__ */ diff --git a/branches/pcsx2_0.9.1/Hw.c b/branches/pcsx2_0.9.1/Hw.c new file mode 100644 index 0000000..48f31fb --- /dev/null +++ b/branches/pcsx2_0.9.1/Hw.c @@ -0,0 +1,2620 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include + +#include "Common.h" +#include "ir5900.h" +#include "VUmicro.h" +#include "PsxMem.h" +#include "IPU.h" + +#include + + +int hwInit() { + +#ifndef WIN32_VIRTUAL_MEM + psH = (u8*)_aligned_malloc(0x00010000, 16); + if (psH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } +#endif + + gsInit(); + vif0Init(); + vif1Init(); + vifDmaInit(); + sifInit(); + sprInit(); + ipuInit(); + + return 0; +} + +void hwShutdown() { +#ifndef WIN32_VIRTUAL_MEM + if (psH == NULL) return; + _aligned_free(psH); psH = NULL; +#endif + ipuShutdown(); +} + +void hwReset() { + +#ifdef WIN32_VIRTUAL_MEM + + memset(PS2MEM_HW+0x2000, 0, 0x0000e000); + psHu32(0xf520) = 0x1201; + psHu32(0xf260) = 0x1D000060; +#else + memset(psH, 0, 0x00010000); +#endif + // i guess this is kinda a version, it's used by some bioses + psHu32(0xf590) = 0x1201; + + gsReset(); + ipuReset(); +} + +u8 hwRead8(u32 mem) +{ + u8 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(mem)); +#endif + + switch (mem) { + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem); + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u8)ret; + } + + if (mem < 0x10010000) + { + ret = psHu8(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 8 at %x\n",mem); +#endif + break; + } + + return ret; +} + +int hwConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + //psHu32(mem) &= ~0x4000; + return 0; + } + } + + if (mem < 0x10010000) + { + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; +} + +u16 hwRead16(u32 mem) +{ + u16 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 16bit at %lx, ret %lx\n", mem, psHu16(mem)); +#endif + switch (mem) { + case 0x10000000: ret = (u16)rcntRcount(0); break; + case 0x10000010: ret = (u16)counters[0].mode; break; + case 0x10000020: ret = (u16)counters[0].target; break; + case 0x10000030: ret = (u16)counters[0].hold; break; + + case 0x10000800: ret = (u16)rcntRcount(1); break; + case 0x10000810: ret = (u16)counters[1].mode; break; + case 0x10000820: ret = (u16)counters[1].target; break; + case 0x10000830: ret = (u16)counters[1].hold; break; + + case 0x10001000: ret = (u16)rcntRcount(2); break; + case 0x10001010: ret = (u16)counters[2].mode; break; + case 0x10001020: ret = (u16)counters[2].target; break; + + case 0x10001800: ret = (u16)rcntRcount(3); break; + case 0x10001810: ret = (u16)counters[3].mode; break; + case 0x10001820: ret = (u16)counters[3].target; break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu16(mem) | 0x0102; + psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u16)ret; + } + if (mem < 0x10010000) { + ret = psHu16(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 16 at %x\n",mem); +#endif + break; + } + + return ret; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +static u32 s_regreads[3] = {0x010200000, 0xbfff0000, 0xF0000102}; +int hwConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: + PUSH32I(0); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000020: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000030: + _eeReadConstMem16(x86reg, (u32)&counters[0].hold, sign); + return 0; + + case 0x10000800: + PUSH32I(1); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10000810: + _eeReadConstMem16(x86reg, (u32)&counters[1].mode, sign); + return 0; + + case 0x10000820: + _eeReadConstMem16(x86reg, (u32)&counters[1].target, sign); + return 0; + + case 0x10000830: + _eeReadConstMem16(x86reg, (u32)&counters[1].hold, sign); + return 0; + + case 0x10001000: + PUSH32I(2); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001010: + _eeReadConstMem16(x86reg, (u32)&counters[2].mode, sign); + return 0; + + case 0x10001020: + _eeReadConstMem16(x86reg, (u32)&counters[2].target, sign); + return 0; + + case 0x10001800: + PUSH32I(3); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001810: + _eeReadConstMem16(x86reg, (u32)&counters[3].mode, sign); + return 0; + + case 0x10001820: + _eeReadConstMem16(x86reg, (u32)&counters[3].target, sign); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff] - 2); + PORMtoR(x86reg&0xf, (u32)&s_regreads[0]); + PANDMtoR(x86reg&0xf, (u32)&s_regreads[1]); + } + else { + if( sign ) MOVSX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + else MOVZX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + + OR32ItoR(x86reg, 0x0102); + AND32ItoR(x86reg, ~0x4000); + } + return 0; + } + } + if (mem < 0x10010000) { + _eeReadConstMem16(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +static int b440; + +extern BOOL bExecBIOS; +static int b440table[] = { + 0, 31, 31, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0 }; + +#ifdef WIN32_VIRTUAL_MEM +__declspec(naked) void recCheckF440() +{ + __asm { + add b440, 1 + mov eax, b440 + sub eax, 3 + mov edx, 31 + + cmp eax, 27 + ja WriteVal + shl eax, 2 + mov edx, dword ptr [eax+b440table] + +WriteVal: + mov eax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [eax], edx + ret + } +} + +void iMemRead32Check() +{ + // test if 0xf440 + if( bExecBIOS ) { + u8* ptempptr[2]; + CMP32ItoR(ECX, 0x1000f440); + ptempptr[0] = JNE8(0); + +// // increment and test +// INC32M((int)&b440); +// MOV32MtoR(EAX, (int)&b440); +// SUB32ItoR(EAX, 3); +// MOV32ItoR(EDX, 31); +// +// CMP32ItoR(EAX, 27); +// +// // look up table +// ptempptr[1] = JA8(0); +// SHL32ItoR(EAX, 2); +// ADD32ItoR(EAX, (int)b440table); +// MOV32RmtoR(EDX, EAX); +// +// x86SetJ8( ptempptr[1] ); +// +// MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + CALLFunc((u32)recCheckF440); + + x86SetJ8( ptempptr[0] ); + } +} + +#endif + +u32 hwRead32(u32 mem) { + u32 ret; + +#ifdef SPR_LOG + SPR_LOG("Hardware read 32bit at %lx, ret %lx\n", mem, psHu32(mem)); +#endif + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead32(mem); + } + + // gauntlen uses 0x1001xxxx + switch (mem) { + case 0x10000000: return (u16)rcntRcount(0); + case 0x10000010: return (u16)counters[0].mode; + case 0x10000020: return (u16)counters[0].target; + case 0x10000030: return (u16)counters[0].hold; + + case 0x10000800: return (u16)rcntRcount(1); + case 0x10000810: return (u16)counters[1].mode; + case 0x10000820: return (u16)counters[1].target; + case 0x10000830: return (u16)counters[1].hold; + + case 0x10001000: return (u16)rcntRcount(2); + case 0x10001010: return (u16)counters[2].mode; + case 0x10001020: return (u16)counters[2].target; + + case 0x10001800: return (u16)rcntRcount(3); + case 0x10001810: return (u16)counters[3].mode; + case 0x10001820: return (u16)counters[3].target; + +#ifdef PCSX2_DEVBUILD + case 0x1000A000: + ret = psHu32(mem);//dma2 chcr + HW_LOG("Hardware read DMA2_CHCR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A010: + ret = psHu32(mem);//dma2 madr + HW_LOG("Hardware read DMA2_MADR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A020: + ret = psHu32(mem);//dma2 qwc + HW_LOG("Hardware readDMA2_QWC 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A030: + ret = psHu32(mem);//dma2 taddr + HW_LOG("Hardware read DMA2_TADDR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A040: + ret = psHu32(mem);//dma2 asr0 + HW_LOG("Hardware read DMA2_ASR0 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A050: + ret = psHu32(mem);//dma2 asr1 + HW_LOG("Hardware read DMA2_ASR1 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A080: + ret = psHu32(mem);//dma2 saddr + HW_LOG("Hardware read DMA2_SADDR 32 at %lx, ret %lx\n", mem, ret); + break; + case 0x1000B400: // dma4 chcr + ret = ((DMACh *)&PS2MEM_HW[0xb400])->chcr; + SPR_LOG("Hardware read IPU1_CHCR 32 at %lx, ret %x\n", mem, ret); + break; + + case 0x1000e010: // DMAC_STAT + HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); + return psHu32(0xe010); + case 0x1000f000: // INTC_STAT +// HW_LOG("INTC_STAT Read 32bit %x\n", psHu32(0xf000)); + return psHu32(0xf000); + case 0x1000f010: // INTC_MASK + HW_LOG("INTC_MASK Read 32bit %x\n", psHu32(0xf010)); + return psHu32(0xf010); +#endif + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + ret = 0; + break; + + case 0x1000f440: + + b440++; + switch (b440) { + case 3: case 6: case 9: case 10: + case 13: case 14: + case 17: case 18: + case 21: case 22: + case 25: case 26: + case 29: case 30: + ret = 0; break; + default: + ret = 0x1f; break; + } + break; + + case 0x1000f520: // DMAC_ENABLER +#ifdef HW_LOG + HW_LOG("DMAC_ENABLER Read 32bit %lx\n", psHu32(0xf590)); +#endif + return psHu32(0xf590); + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + // SIF Control Registers + /*1D000020 (word) - EE -> IOP status flag ( set to 0x10000 always ready ) + 1D000030 (word) - IOP -> EE status flag + 1D000040 (word) - See psxMem.c ( Initially set to 0xF00042 and reset to + to this value if 0x20 is written ) + 1D000060 (word) - used to detect whether the SIF interface exists + read must be 0x1D000060, or the top 20 bits must be zero + */ + // note, any changes you make in here, also make on recMemRead32 + if(mem ==0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem) | 0xF0000102; + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); +//#ifdef HW_LOG +// SysPrintf("sif %x(%x) Read 32bit %x\n", mem, 0xbd000000 | (mem & 0xf0),ret); +//#endif } + break; + + } + else if (mem < 0x10010000) { + ret = psHu32(mem); + } + else { + SysPrintf("32bit HW read of address 0x%x\n", mem); + ret = 0; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 32 at %lx, ret %lx\n", mem, ret); +#endif + break; + } + + return ret; +} + +int hwConstRead32(u32 x86reg, u32 mem) +{ + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuConstRead32(x86reg, mem); + } + + switch (mem) { + case 0x10000000: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem32(x86reg, (u32)&counters[0].mode); + return 0; + case 0x10000020: + _eeReadConstMem32(x86reg, (u32)&counters[0].target); + return 0; + case 0x10000030: + _eeReadConstMem32(x86reg, (u32)&counters[0].hold); + return 0; + + case 0x10000800: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000810: + _eeReadConstMem32(x86reg, (u32)&counters[1].mode); + return 0; + case 0x10000820: + _eeReadConstMem32(x86reg, (u32)&counters[1].target); + return 0; + case 0x10000830: + _eeReadConstMem32(x86reg, (u32)&counters[1].hold); + return 0; + + case 0x10001000: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10001010: + _eeReadConstMem32(x86reg, (u32)&counters[2].mode); + return 0; + case 0x10001020: + _eeReadConstMem32(x86reg, (u32)&counters[2].target); + return 0; + case 0x10001030: + _eeReadConstMem32(x86reg, (u32)&counters[2].hold); + return 0; + + case 0x10001800: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10001810: + _eeReadConstMem32(x86reg, (u32)&counters[3].mode); + return 0; + case 0x10001820: + _eeReadConstMem32(x86reg, (u32)&counters[3].target); + return 0; + case 0x10001830: + _eeReadConstMem32(x86reg, (u32)&counters[3].hold); + return 0; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + + case 0x1000f440: + //iMemRead32Check(); + // increment and test + INC32M((int)&b440); + MOV32MtoR(EAX, (int)&b440); + SUB32ItoR(EAX, 3); + MOV32ItoR(EDX, 31); + + CMP32ItoR(EAX, 27); + + // look up table + j8Ptr[8] = JA8(0); + SHL32ItoR(EAX, 2); + ADD32ItoR(EAX, (int)b440table); + MOV32RmtoR(EDX, EAX); + + x86SetJ8( j8Ptr[8] ); + + MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + + if( IS_XMMREG(x86reg) ) SSE2_MOVD_R_to_XMM(x86reg&0xf, EDX); + else if( IS_MMXREG(x86reg) ) MOVD32RtoMMX(x86reg&0xf, EDX); + else MOV32RtoR(x86reg, EDX); + + return 0; + + case 0x1000f520: // DMAC_ENABLER + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[0xf590]); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_XMMREG(x86reg) ) { + SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + SSEX_POR_M128_to_XMM(x86reg&0xf, (u32)&s_regreads[2]); + } + else if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + PORMtoR(x86reg&0xf, (u32)&s_regreads[2]); + } + else { + MOV32MtoR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + OR32ItoR(x86reg, 0xF0000102); + } + return 0; + } + } + + if (mem < 0x10010000) { + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + } + else { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +u64 hwRead64(u32 mem) { + u64 ret; + + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead64(mem); + } + + switch (mem) { + default: + if (mem < 0x10010000) { + ret = psHu64(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 64 at %x\n",mem); +#endif + break; + } + + return ret; +} + +void hwConstRead64(u32 mem, int mmreg) { + if ((mem>=0x10002000) && (mem<0x10003000)) { + ipuConstRead64(mem, mmreg); + return; + } + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PSM(mem)); + else { + MOVQMtoR(mmreg, (u32)PSM(mem)); + SetMMXstate(); + } +} + +void hwRead128(u32 mem, u64 *out) { + if (mem >= 0x10004000 && mem < 0x10008000) { + ReadFIFO(mem, out); return; + } + + if (mem < 0x10010000) { + out[0] = psHu64(mem); + out[1] = psHu64(mem+8); + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 128 at %x\n",mem); +#endif +} + +__declspec(align(16)) u32 s_TempFIFO[4]; +void hwConstRead128(u32 mem, int xmmreg) { + if (mem >= 0x10004000 && mem < 0x10008000) { + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)ReadFIFO); + ADD32ItoR(ESP, 8); + _eeReadConstMem128( xmmreg, (u32)&s_TempFIFO[0]); + return; + } + + _eeReadConstMem128( xmmreg, (u32)PSM(mem)); +} + +// dark cloud2 uses it +#define DmaExec8(name, num) { \ + psHu8(mem) = (u8)value; \ + if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { \ + /*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/ \ + dma##name(); \ + } \ +} + +// when writing imm +#define recDmaExecI8(name, num) { \ + MOV8ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec8(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI8(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem8((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 1); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +char sio_buffer[1024]; +static int sio_count; + +void hwWrite8(u32 mem, u8 value) { + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite8 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case 0x1000f180: + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +// SysPrintf("%c", value); + break; + + case 0x10008001: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 +#ifdef DMA_LOG + DMA_LOG("VIF1dma %lx\n", value); +#endif + DmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value); +#endif + DmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + psHu8(0xf592) = value; + psHu8(0xf522) = value; + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu8(mem) = value; + break; + case 0x40: + if(!(value & 0x100)) psHu32(mem) &= ~0x100; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + psHu8(mem) = value; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value); +#endif + break; + } +} + +static void PrintDebug(u8 value) +{ + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +} + +#define CONSTWRITE_CALLTIMER(name, index, bit) { \ + if( !IS_CONSTREG(mmreg) ) { \ + if( bit == 8 ) MOVZX32R8toR(mmreg&0xf, mmreg&0xf); \ + else if( bit == 16 ) MOVZX32R16toR(mmreg&0xf, mmreg&0xf); \ + } \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + PUSH32I(index); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 8); \ +} \ + +#define CONSTWRITE_TIMERS(bit) \ + case 0x10000000: CONSTWRITE_CALLTIMER(rcntWcount, 0, bit); break; \ + case 0x10000010: CONSTWRITE_CALLTIMER(rcntWmode, 0, bit); break; \ + case 0x10000020: CONSTWRITE_CALLTIMER(rcntWtarget, 0, bit); break; \ + case 0x10000030: CONSTWRITE_CALLTIMER(rcntWhold, 0, bit); break; \ + \ + case 0x10000800: CONSTWRITE_CALLTIMER(rcntWcount, 1, bit); break; \ + case 0x10000810: CONSTWRITE_CALLTIMER(rcntWmode, 1, bit); break; \ + case 0x10000820: CONSTWRITE_CALLTIMER(rcntWtarget, 1, bit); break; \ + case 0x10000830: CONSTWRITE_CALLTIMER(rcntWhold, 1, bit); break; \ + \ + case 0x10001000: CONSTWRITE_CALLTIMER(rcntWcount, 2, bit); break; \ + case 0x10001010: CONSTWRITE_CALLTIMER(rcntWmode, 2, bit); break; \ + case 0x10001020: CONSTWRITE_CALLTIMER(rcntWtarget, 2, bit); break; \ + \ + case 0x10001800: CONSTWRITE_CALLTIMER(rcntWcount, 3, bit); break; \ + case 0x10001810: CONSTWRITE_CALLTIMER(rcntWmode, 3, bit); break; \ + case 0x10001820: CONSTWRITE_CALLTIMER(rcntWtarget, 3, bit); break; \ + +void hwConstWrite8(u32 mem, int mmreg) +{ + switch (mem) { + CONSTWRITE_TIMERS(8) + + case 0x1000f180: + _recPushReg(mmreg); \ + iFlushCall(0); + CALLFunc((u32)PrintDebug); + ADD32ItoR(ESP, 4); + break; + + case 0x10008001: // dma0 - vif0 + recDmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 + recDmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif + recDmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU + recDmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU + recDmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 + recDmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 + recDmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR + recDmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR + recDmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf522], mmreg ); + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf592], mmreg ); + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem8( (u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JNZ8(0); + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + x86SetJ8(j8Ptr[5]); + } + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem8((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } + + break; + } +} + +#define DmaExec16(name, num) { \ + psHu16(mem) = (u16)value; \ + if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + SysPrintf("16bit DMA Start\n"); \ + dma##name(); \ + } \ +} + +#define recDmaExecI16(name, num) { \ + MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec16(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI16(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite16(u32 mem, u16 value) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite16 to %x\n", mem); +#endif + switch(mem) { + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec16(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec16(VIF1, 1); + break; + +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec16(GIF, 2); + break; +#ifdef HW_LOG + + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec16(IPU0, 3); + break; + +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec16(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec16(SIF0, 5); + break; + + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec16(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec16(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + psHu16(0xf592) = value; + psHu16(0xf522) = value; + break; + case 0x1000f130: + case 0x1000f132: + case 0x1000f410: + case 0x1000f412: + case 0x1000f430: + case 0x1000f432: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu16(mem) = value; + break; + case 0x20: + psHu16(mem) |= value; + break; + case 0x30: + psHu16(mem) &= ~value; + break; + case 0x40: + assert( (mem&2)==0); + if(!(value & 0x100)) psHu16(mem) &= ~0x100; + else psHu16(mem) |= 0x100; + break; + case 0x60: + psHu16(mem) = 0; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + +#ifndef WIN32_VIRTUAL_MEM + if (mem < 0x10010000) +#endif + { + psHu16(mem) = value; + } + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value); +#endif +} + +void hwConstWrite16(u32 mem, int mmreg) +{ + switch(mem&~3) { + case 0x10008000: // dma0 - vif0 + recDmaExec16(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec16(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec16(GIF, 2); + break; + case 0x1000b000: // dma3 - fromIPU + recDmaExec16(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec16(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec16(SIF0, 5); + break; + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 + recDmaExec16(SIF1, 6); + break; + case 0x1000c800: // dma7 - sif2 + recDmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR + recDmaExec16(SPR0, 8); + break; + case 0x1000d400: // dma9 - toSPR + recDmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf522], mmreg); + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf592], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem16OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + if( IS_CONSTREG(mmreg) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else { + NOT32R(mmreg&0xf); + AND16RtoM((u32)&PS2MEM_HW[mem&0xffff], mmreg&0xf); + } + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + } + else { + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } +} + +#define DmaExec(name, num) { \ + /* why not allowing tags on sif0/sif2? */ \ + if(mem!= 0x1000c000/* && mem != 0x1000c400*/ && mem != 0x1000c800) \ + psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; \ + else \ + psHu32(mem) = (u32)value; \ + if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + dma##name(); \ + } \ +} + +// when writing an Imm +#define recDmaExecI(name, num) { \ + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \ + if(mem!= 0x1000c000 && mem != 0x1000c800) MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + else MOV32ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + if( c & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + if(mem!= 0x1000c000 && mem != 0x1000c800) { \ + if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \ + MOV16RtoM((u32)&PS2MEM_HW[(mem) & 0xffff], EAX); \ + } \ + else { \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + } \ + } \ + else _eeWriteConstMem32((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST16ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST32ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite32(u32 mem, u32 value) { + int i; + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuWrite32(mem,value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case GIF_CTRL: + //SysPrintf("GIF_CTRL write %x\n", value); + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + return; + + case GIF_MODE: + // need to set GIF_MODE (hamster ball) + psHu32(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + SysPrintf("Gifstat write value = %x\n", value); + return; + + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec(VIF1, 1); + break; +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; +#ifdef HW_LOG + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec(IPU0, 3); + break; +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec(SPR1, 9); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 32bit %x\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 32bit %x\n", value); +#endif + psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 + value = value >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (value & (1<=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuConstWrite32(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x10000000: CONSTWRITE_CALLTIMER32(rcntWcount, 0, bit); break; + case 0x10000010: CONSTWRITE_CALLTIMER32(rcntWmode, 0, bit); break; + case 0x10000020: CONSTWRITE_CALLTIMER32(rcntWtarget, 0, bit); break; + case 0x10000030: CONSTWRITE_CALLTIMER32(rcntWhold, 0, bit); break; + + case 0x10000800: CONSTWRITE_CALLTIMER32(rcntWcount, 1, bit); break; + case 0x10000810: CONSTWRITE_CALLTIMER32(rcntWmode, 1, bit); break; + case 0x10000820: CONSTWRITE_CALLTIMER32(rcntWtarget, 1, bit); break; + case 0x10000830: CONSTWRITE_CALLTIMER32(rcntWhold, 1, bit); break; + + case 0x10001000: CONSTWRITE_CALLTIMER32(rcntWcount, 2, bit); break; + case 0x10001010: CONSTWRITE_CALLTIMER32(rcntWmode, 2, bit); break; + case 0x10001020: CONSTWRITE_CALLTIMER32(rcntWtarget, 2, bit); break; + + case 0x10001800: CONSTWRITE_CALLTIMER32(rcntWcount, 3, bit); break; + case 0x10001810: CONSTWRITE_CALLTIMER32(rcntWmode, 3, bit); break; + case 0x10001820: CONSTWRITE_CALLTIMER32(rcntWtarget, 3, bit); break; + + case GIF_CTRL: + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + return; + + case GIF_STAT: // stat is readonly + return; + + case 0x10008000: // dma0 - vif0 + recDmaExec(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000b000: // dma3 - fromIPU + recDmaExec(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 + recDmaExec(SIF1, 6); + break; + + case 0x1000c800: // dma7 - sif2 + recDmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR + recDmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR + recDmaExec(SPR1, 9); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[0xf000], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + return; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + else { + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST32ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + MOV32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + break; + } +} + +void hwWrite64(u32 mem, u64 value) { + u32 val32; + int i; + + if ((mem>=0x10002000) && (mem<=0x10002030)) { + ipuWrite64(mem, value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case GIF_CTRL: +#ifdef PCSX2_DEVBUILD + SysPrintf("GIF_CTRL write 64\n", value); +#endif + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + + return; + + case GIF_MODE: + psHu64(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 64bit %x\n", value); + psHu64(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 64bit %x\n", value); +#endif + val32 = (u32)value; + psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 + val32 = val32 >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (val32 & (1<=0x10002000) && (mem<=0x10002030)) { + ipuConstWrite64(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case GIF_CTRL: + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + + break; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + + _eeWriteConstMem64((u32)PSM(mem), mmreg); + break; + } +} + +void hwWrite128(u32 mem, u64 *value) { + if (mem >= 0x10004000 && mem < 0x10008000) { + WriteFIFO(mem, value); return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + psHu32(0xf590) = *(u32*)value; + psHu32(0xf520) = *(u32*)value; + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status); +#endif + break; + } +} + +void hwConstWrite128(u32 mem, int mmreg) +{ + if (mem >= 0x10004000 && mem < 0x10008000) { + _eeWriteConstMem128((u32)&s_TempFIFO[0], mmreg); + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)WriteFIFO); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + +#ifdef WIN32_VIRTUAL_MEM + _eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg); +#else + if (mem < 0x10010000) + _eeWriteConstMem128((u32)&PS2MEM_HW[mem&0xffff], mmreg); +#endif + break; + } +} + +int intcInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu32(INTC_STAT)) == 0) { + SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); + return 1; + } + if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("intcInterrupt %x\n", psHu32(INTC_STAT) & psHu32(INTC_MASK)); +#endif + if(psHu32(INTC_STAT) & 0x2){ + counters[0].hold = rcntRcount(0); + counters[1].hold = rcntRcount(1); + } + + cpuException(0x400, cpuRegs.branch); + + return 1; +} + +int dmacTestInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + return 1; +} + +int dmacInterrupt() +{ +if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("dmacInterrupt %x\n", (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)); +#endif + + cpuException(0x800, cpuRegs.branch); + return 1; +} + +void hwIntcIrq(int n) { + //if( psHu32(INTC_MASK) & (1< (maddr+msize)) { +// int s1 = (maddr+msize) - addr; +// int s2 = size - s1; +// +// /* it does, so first copy 's1' bytes from 'addr' to 'data' */ +// src = PSM(addr); +// if (src == NULL) return -1; +// memcpy_amd(data, src, s1); +// +// /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ +// src = PSM(maddr); +// if (src == NULL) return -1; +// memcpy(&data[s1], src, s2); +// } else { +// //u32 * tempptr, * tempptr2; +// /* it doesn't, so just copy 'size' bytes from 'addr' to 'data' */ +// src = PSM(addr); +// if (src == NULL) return -1; +// //tempptr = (u32*)src; +// //tempptr2 = (u32*)data; +// +// memcpy(data, src, size); +// } +// +// return 0; +//} + +/* Write 'size' bytes to memory address 'addr' from 'data'. */ +int hwMFIFOWrite(u32 addr, u8 *data, int size) { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u8 *dst; + + addr = psHu32(DMAC_RBOR) + (addr & psHu32(DMAC_RBSR)); + /* Check if the transfer should wrap around the ring buffer */ + if ((addr+size) > (maddr+msize)) { + int s1 = (maddr+msize) - addr; + int s2 = size - s1; + + /* it does, so first copy 's1' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, s1/4); + memcpy(dst, data, s1); + + /* and second copy 's2' bytes from '&data[s1]' to 'maddr' */ + dst = PSM(maddr); + if (dst == NULL) return -1; + Cpu->Clear(maddr, s2/4); + memcpy(dst, &data[s1], s2); + } else { + //u32 * tempptr, * tempptr2; + + /* it doesn't, so just copy 'size' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, size/4); + memcpy_amd(dst, data, size); + } + + return 0; +} + + +int hwDmacSrcChainWithStack(DMACh *dma, int id) { + u32 temp,finalAddress; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + //dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 5: // Call - Transfer QWC following the tag, save succeeding tag + temp = dma->madr; //Temporarily Store ADDR + finalAddress = dma->tadr + 16 + (dma->qwc << 4); //Store Address of Succeeding tag + + if (dma->asr0 == 0) //Check if ASR0 is empty + dma->asr0 = finalAddress; //If yes store Succeeding tag + else + dma->asr1 = finalAddress; //If no store Succeeding tag in ASR1 + + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + dma->tadr = temp; //Set TADR to temporarily stored ADDR + return 0; + + case 6: // Ret - Transfer QWC following the tag, load next tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + if (dma->asr1 != 0) { //If ASR1 is NOT equal to 0 (Contains address) + dma->tadr = dma->asr1; //Read ASR1 as next tag + dma->asr1 = 0; //Clear ASR1 + } else { //If ASR1 is empty (No address held) + if(dma->asr0 != 0) { //Check if ASR0 is NOT equal to 0 (Contains address) + dma->tadr = dma->asr0; //Read ASR0 as next tag + dma->asr0 = 0; //Clear ASR0 + } else { //Else if ASR1 and ASR0 are empty + dma->tadr = 0; //Clear tag address + return 1; //End Transfer + } + } + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //comment out tadr fixes lemans + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} + +int hwDmacSrcChain(DMACh *dma, int id) { + u32 temp; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + //dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} diff --git a/branches/pcsx2_0.9.1/Hw.h b/branches/pcsx2_0.9.1/Hw.h new file mode 100644 index 0000000..0f5f032 --- /dev/null +++ b/branches/pcsx2_0.9.1/Hw.h @@ -0,0 +1,400 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __HW_H__ +#define __HW_H__ + +//#include "Common.h" +#include "PS2Etypes.h" +#include + +#ifndef WIN32_VIRTUAL_MEM +u8 *psH; // hw mem +u16 *psHW; +u32 *psHL; +u64 *psHD; +#endif + +#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff]) + +extern u32 g_nextBranchCycle; + +#define INT(n, ecycle) { \ + g_nextBranchCycle = min(g_nextBranchCycle, cpuRegs.cycle+ecycle); \ + cpuRegs.interrupt|= 1 << n; \ + cpuRegs.sCycle[n] = cpuRegs.cycle; \ + cpuRegs.eCycle[n] = ecycle; \ +} + +// VIF0 -- 0x10004000 -- psH[0x4000] +// VIF1 -- 0x10005000 -- psH[0x5000] +// GIF -- 0x10006000 -- psH[0x6000] +// IPUout -- 0x10007000 -- psH[0x7000] +// IPUin -- 0x10007010 -- psH[0x7010] + +void ReadFIFO(u32 mem, u64 *out); +void ConstReadFIFO(u32 mem); + +void WriteFIFO(u32 mem, u64 *value); +void ConstWriteFIFO(u32 mem); + + +// +// --- DMA --- +// + +typedef struct { + u32 chcr; + u32 null0[3]; + u32 madr; + u32 null1[3]; + u16 qwc; u16 pad; + u32 null2[3]; + u32 tadr; + u32 null3[3]; + u32 asr0; + u32 null4[3]; + u32 asr1; + u32 null5[11]; + u32 sadr; +} DMACh; + +int sifenabled[2]; + +// HW defines + +#define RCNT0_COUNT 0x10000000 +#define RCNT0_MODE 0x10000010 +#define RCNT0_TARGET 0x10000020 +#define RCNT0_HOLD 0x10000030 + +#define RCNT1_COUNT 0x10000800 +#define RCNT1_MODE 0x10000810 +#define RCNT1_TARGET 0x10000820 +#define RCNT1_HOLD 0x10000830 + +#define RCNT2_COUNT 0x10001000 +#define RCNT2_MODE 0x10001010 +#define RCNT2_TARGET 0x10001020 + +#define RCNT3_COUNT 0x10001800 +#define RCNT3_MODE 0x10001810 +#define RCNT3_TARGET 0x10001820 + +#define IPU_CMD 0x10002000 +#define IPU_CTRL 0x10002010 +#define IPU_BP 0x10002020 +#define IPU_TOP 0x10002030 + +#define GIF_CTRL 0x10003000 +#define GIF_MODE 0x10003010 +#define GIF_STAT 0x10003020 +#define GIF_TAG0 0x10003040 +#define GIF_TAG1 0x10003050 +#define GIF_TAG2 0x10003060 +#define GIF_TAG3 0x10003070 +#define GIF_CNT 0x10003080 +#define GIF_P3CNT 0x10003090 +#define GIF_P3TAG 0x100030A0 + +#define GIF_FIFO 0x10006000 + +#define IPUout_FIFO 0x10007000 +#define IPUin_FIFO 0x10007010 + +//VIF0 +#define D0_CHCR 0x10008000 +#define D0_MADR 0x10008010 +#define D0_QWC 0x10008020 + +//VIF1 +#define D1_CHCR 0x10009000 +#define D1_MADR 0x10009010 +#define D1_QWC 0x10009020 +#define D1_TADR 0x10009030 + +//GS +#define D2_CHCR 0x1000A000 +#define D2_MADR 0x1000A010 +#define D2_QWC 0x1000A020 +#define D2_TADR 0x1000A030 + +//fromIPU +#define D3_CHCR 0x1000B000 +#define D3_MADR 0x1000B010 +#define D3_QWC 0x1000B020 + +//toIPU +#define D4_CHCR 0x1000B400 +#define D4_MADR 0x1000B410 +#define D4_QWC 0x1000B420 +#define D4_TADR 0x1000B430 + +//SIF0 +#define D5_CHCR 0x1000C000 +#define D5_MADR 0x1000C010 +#define D5_QWC 0x1000C020 + +//SIF1 +#define D6_CHCR 0x1000C400 +#define D6_MADR 0x1000C410 +#define D6_QWC 0x1000C420 + +//SIF2 +#define D7_CHCR 0x1000C800 +#define D7_MADR 0x1000C810 +#define D7_QWC 0x1000C820 + +//fromSPR +#define D8_CHCR 0x1000D000 +#define D8_MADR 0x1000D010 +#define D8_QWC 0x1000D020 +#define D8_SADR 0x1000D080 + + +#define DMAC_CTRL 0x1000E000 +#define DMAC_STAT 0x1000E010 +#define DMAC_PCR 0x1000E020 +#define DMAC_SQWC 0x1000E030 +#define DMAC_RBSR 0x1000E040 +#define DMAC_RBOR 0x1000E050 +#define DMAC_STADR 0x1000E060 + +#define INTC_STAT 0x1000F000 +#define INTC_MASK 0x1000F010 + +#define SBUS_F220 0x1000F220 +#define SBUS_SMFLG 0x1000F230 +#define SBUS_F240 0x1000F240 + +#define DMAC_ENABLER 0x1000F520 +#define DMAC_ENABLEW 0x1000F590 + +#define SBFLG_IOPALIVE 0x10000 +#define SBFLG_IOPSYNC 0x40000 + +#define GS_PMODE 0x12000000 +#define GS_SMODE1 0x12000010 +#define GS_SMODE2 0x12000020 +#define GS_SRFSH 0x12000030 +#define GS_SYNCH1 0x12000040 +#define GS_SYNCH2 0x12000050 +#define GS_SYNCV 0x12000060 +#define GS_DISPFB1 0x12000070 +#define GS_DISPLAY1 0x12000080 +#define GS_DISPFB2 0x12000090 +#define GS_DISPLAY2 0x120000A0 +#define GS_EXTBUF 0x120000B0 +#define GS_EXTDATA 0x120000C0 +#define GS_EXTWRITE 0x120000D0 +#define GS_BGCOLOR 0x120000E0 +#define GS_CSR 0x12001000 +#define GS_IMR 0x12001010 +#define GS_BUSDIR 0x12001040 +#define GS_SIGLBLID 0x12001080 + +#define INTC_GS 0 +#define INTC_SBUS 1 +#define INTC_VBLANK_S 2 +#define INTC_VBLANK_E 3 +#define INTC_VIF0 4 +#define INTC_VIF1 5 +#define INTC_VU0 6 +#define INTC_VU1 7 +#define INTC_IPU 8 +#define INTC_TIM0 9 +#define INTC_TIM1 10 +#define INTC_TIM2 11 +#define INTC_TIM3 12 + +#define DMAC_VIF0 0 +#define DMAC_VIF1 1 +#define DMAC_GIF 2 +#define DMAC_FROM_IPU 3 +#define DMAC_TO_IPU 4 +#define DMAC_SIF0 5 +#define DMAC_SIF1 6 +#define DMAC_SIF2 7 +#define DMAC_FROM_SPR 8 +#define DMAC_TO_SPR 9 +#define DMAC_ERROR 15 + +#define VIF0_STAT_VPS_W (1) +#define VIF0_STAT_VPS_D (2) +#define VIF0_STAT_VPS_T (3) +#define VIF0_STAT_VPS (3) +#define VIF0_STAT_VEW (1<<2) +#define VIF0_STAT_MRK (1<<6) +#define VIF0_STAT_DBF (1<<7) +#define VIF0_STAT_VSS (1<<8) +#define VIF0_STAT_VFS (1<<9) +#define VIF0_STAT_VIS (1<<10) +#define VIF0_STAT_INT (1<<11) +#define VIF0_STAT_ER0 (1<<12) +#define VIF0_STAT_ER1 (1<<13) + +#define VIF1_STAT_VPS_W (1) +#define VIF1_STAT_VPS_D (2) +#define VIF1_STAT_VPS_T (3) +#define VIF1_STAT_VPS (3) +#define VIF1_STAT_VEW (1<<2) +#define VIF1_STAT_VGW (1<<3) +#define VIF1_STAT_MRK (1<<6) +#define VIF1_STAT_DBF (1<<7) +#define VIF1_STAT_VSS (1<<8) +#define VIF1_STAT_VFS (1<<9) +#define VIF1_STAT_VIS (1<<10) +#define VIF1_STAT_INT (1<<11) +#define VIF1_STAT_ER0 (1<<12) +#define VIF1_STAT_ER1 (1<<13) +#define VIF1_STAT_FDR (1<<23) + +//DMA interrupts & masks +#define BEISintr (0x8000) +#define VIF0intr (0x10001) +#define VIF1intr (0x20002) +#define GIFintr (0x40004) +#define IPU0intr (0x80008) +#define IPU1intr (0x100010) +#define SIF0intr (0x200020) +#define SIF1intr (0x400040) +#define SIF2intr (0x800080) +#define SPR0intr (0x1000100) +#define SPR1intr (0x2000200) +#define SISintr (0x20002000) +#define MEISintr (0x40004000) + +#define DMAend(dma, num) { \ + dma->chcr &= ~0x100; \ + psHu32(DMAC_STAT)|= 1<>12 ].aPFNs == NULL ) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", mem); + return NULL; + } +#endif + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + return p; +} + +#else + +__forceinline void *dmaGetAddr(u32 addr) { + u8 *ptr; + +/*#ifdef DMA_LOG + if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x\n", addr); } +#endif*/ + if (addr & 0x80000000) { // teh sux why the f00k 0xE0000000 + return (void*)&psS[addr & 0x3ff0]; + } + + ptr = (u8*)memLUTR[addr >> 12]; + if (ptr == NULL) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", addr); + return NULL; + } + return (void*)(ptr + (addr & 0xff0)); +} + +#endif + +int hwInit(); +void hwReset(); +void hwShutdown(); + +// hw read functions +u8 hwRead8 (u32 mem); +int hwConstRead8 (u32 x86reg, u32 mem, u32 sign); + +u16 hwRead16(u32 mem); +int hwConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 hwRead32(u32 mem); +int hwConstRead32(u32 x86reg, u32 mem); + +u64 hwRead64(u32 mem); +void hwConstRead64(u32 mem, int mmreg); + +void hwRead128(u32 mem, u64 *out); +void hwConstRead128(u32 mem, int xmmreg); + +// hw write functions +void hwWrite8 (u32 mem, u8 value); +void hwConstWrite8 (u32 mem, int mmreg); + +void hwWrite16(u32 mem, u16 value); +void hwConstWrite16(u32 mem, int mmreg); + +void hwWrite32(u32 mem, u32 value); +void hwConstWrite32(u32 mem, int mmreg); + +void hwWrite64(u32 mem, u64 value); +void hwConstWrite64(u32 mem, int mmreg); + +void hwWrite128(u32 mem, u64 *value); +void hwConstWrite128(u32 mem, int xmmreg); + +void hwIntcIrq(int n); +void hwDmacIrq(int n); + +int hwMFIFORead(u32 addr, u8 *data, int size); +int hwMFIFOWrite(u32 addr, u8 *data, int size); + +int hwDmacSrcChainWithStack(DMACh *dma, int id); +int hwDmacSrcChain(DMACh *dma, int id); + +int intcInterrupt(); +int dmacInterrupt(); + +#endif /* __HW_H__ */ diff --git a/branches/pcsx2_0.9.1/IPU/IPU.c b/branches/pcsx2_0.9.1/IPU/IPU.c new file mode 100644 index 0000000..4915cd7 --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/IPU.c @@ -0,0 +1,1865 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "IPU.h" +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +#include +#include + +#include +#include + +#include "ir5900.h" +#include "pcl.h" + +#ifdef __WIN32__ +#define FASTCALL __fastcall +#else +#define FASTCALL +#endif + +#ifndef WIN32_VIRTUAL_MEM +IPUregisters g_ipuRegsReal; +#endif + +#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000]) +#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400]) + +#define IPU_DMA_GIFSTALL 1 +#define IPU_DMA_TIE0 2 +#define IPU_DMA_TIE1 4 +#define IPU_DMA_ACTV1 8 +#define IPU_DMA_DOTIE1 16 +#define IPU_DMA_FIREINT0 32 +#define IPU_DMA_FIREINT1 64 + +static int g_nDMATransfer = 0; +int g_nIPU0Data = 0; // data left to transfer +u8* g_pIPU0Pointer = NULL; +int g_nCmdPos[2] = {0}, g_nCmdIndex = 0; +static int ipuCurCmd = 0xffffffff; + +// returns number of qw read +int fifo_wread(void *value, int size); +int fifo_wread1(void *value); +int fifo_wwrite(u32* pMem, int size); +void fifo_wclear(); + +static int readwpos = 0, writewpos = 0; +__declspec(align(16)) u32 fifo_input[32]; + +void ReorderBitstream(); +u8 FillInternalBuffer(u32 * pointer, u32 advance); + +// the BP doesn't advance and returns -1 if there is no data to be read +tIPU_BP g_BP; +static coroutine_t s_routine; // used for executing BDEC/IDEC +static int s_RoutineDone = 0; +static u32 s_tempstack[0x1000]; // 16k + +void IPUCMD_WRITE(u32 val); +void IPUWorker(); +int IPU0dma(const void* pMem, int size); +int IPU1dma(); + +#define BigEndian _byteswap_ulong +//__forceinline u32 FASTCALL BigEndian(u32 a){ +// return ((((a >> 24) & 0xFF) << 0) + (((a >> 16) & 0xFF) << 8) + +// (((a >> 8) & 0xFF) << 16) + (((a >> 0) & 0xFF) << 24)); +//} + +// Color conversion stuff +char convert_data_buffer[0x1C]; +convert_init_t convert_init={convert_data_buffer, 0x1C}; +convert_t *convert; + +// Quantization matrix +static u8 niq[64], //non-intraquant matrix + iq[64]; //intraquant matrix +u16 vqclut[16]; //clut conversion table +static u8 s_thresh[2]; //thresholds for color conversions +int coded_block_pattern=0; +__declspec(align(16)) struct macroblock_8 mb8; +__declspec(align(16)) struct macroblock_16 mb16; +__declspec(align(16)) struct macroblock_rgb32 rgb32; +__declspec(align(16)) struct macroblock_rgb16 rgb16; + +u8 indx4[16*16/2]; +u32 mpeg2_inited; //mpeg2_idct_init() must be called only once +u8 PCT[]={'r', 'I', 'P', 'B', 'D', '-', '-', '-'}; +decoder_t g_decoder; //static, only to place it in bss +decoder_t tempdec; + +extern u8 mpeg2_scan_norm[64]; +extern u8 mpeg2_scan_alt[64]; + +__declspec(align(16)) u8 _readbits[80]; //local buffer (ring buffer) +u8* readbits = _readbits; // always can decrement by one 1qw + +#define SATURATE_4BITS(val) ((val)>15 ? 15 : (val)) + +void IPUProcessInterrupt() +{ + if( ipuRegs->ctrl.BUSY ) { + IPUWorker(); + } +} + +///////////////////////////////////////////////////////// +// Register accesses (run on EE thread) +int ipuInit() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + memset(&g_BP, 0, sizeof(g_BP)); + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + return 0; +} + +void ipuReset() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + g_nDMATransfer = 0; +} + +void ipuShutdown() +{ +} + +int ipuFreeze(gzFile f, int Mode) { + IPUProcessInterrupt(); + + gzfreeze(ipuRegs, sizeof(IPUregisters)); + gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer)); + gzfreeze(&readwpos, sizeof(readwpos)); + gzfreeze(&writewpos, sizeof(writewpos)); + gzfreeze(fifo_input, sizeof(fifo_input)); + gzfreeze(&g_BP, sizeof(g_BP)); + gzfreeze(niq, sizeof(niq)); + gzfreeze(iq, sizeof(niq)); + gzfreeze(vqclut, sizeof(vqclut)); + gzfreeze(s_thresh, sizeof(s_thresh)); + gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern)); + gzfreeze(&g_decoder, sizeof(g_decoder)); + gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm)); + gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt)); + gzfreeze(g_nCmdPos, sizeof(g_nCmdPos)); + gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex)); + gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd)); + + gzfreeze(_readbits, sizeof(_readbits)); + + if( Mode == 0 ) { + int temp = readbits-_readbits; + gzfreeze(&temp, sizeof(temp)); + } + else { + int temp; + gzfreeze(&temp, sizeof(temp)); + readbits = _readbits; + } + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + + return 0; +} + +BOOL ipuCanFreeze() +{ + return ipuCurCmd == 0xffffffff; +} + +u32 ipuRead32(u32 mem) +{ + IPUProcessInterrupt(); + + switch (mem){ + + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl.IFC = g_BP.IFC; + ipuRegs->ctrl.OFC = min(g_nIPU0Data, 8); // check if transfering to ipu0 + ipuRegs->ctrl.CBP = coded_block_pattern; + +#ifdef IPU_LOG + if( !ipuRegs->ctrl.BUSY ) { + IPU_LOG("Ipu read32: IPU_CTRL=0x%08X %x\n", ipuRegs->ctrl._u32, cpuRegs.pc); + } +#endif + return ipuRegs->ctrl._u32; + + case 0x10002020: // IPU_BP + + ipuRegs->ipubp = g_BP.BP & 0x7f; + ipuRegs->ipubp |= g_BP.IFC<<8; + ipuRegs->ipubp |= (g_BP.FP+g_BP.bufferhasnew) << 16; + +#ifdef IPU_LOG + IPU_LOG("Ipu read32: IPU_BP=0x%08X\n", *(u32*)&g_BP); +#endif + return ipuRegs->ipubp; + } + + return *(u32*)(((u8*)ipuRegs)+(mem&0xff)); // ipu repeats every 0x100 +} + +int ipuConstRead32(u32 x86reg, u32 mem) +{ + int workingreg, tempreg, tempreg2; + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + +// if( !(x86reg&(MEM_XMMTAG|MEM_MMXTAG)) ) { +// if( x86reg == EAX ) { +// tempreg = ECX; +// tempreg2 = EDX; +// } +// else if( x86reg == ECX ) { +// tempreg = EAX; +// tempreg2 = EDX; +// } +// else if( x86reg == EDX ) { +// tempreg = EAX; +// tempreg2 = ECX; +// } +// +// workingreg = x86reg; +// } +// else { + workingreg = EAX; + tempreg = ECX; + tempreg2 = EDX; +// } + + switch (mem){ + + case 0x10002010: // IPU_CTRL + + MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(workingreg, ~0x3fff); + MOV32MtoR(tempreg, (u32)&g_nIPU0Data); + MOV8MtoR(workingreg, (u32)&g_BP.IFC); + + CMP32ItoR(tempreg, 8); + j8Ptr[5] = JLE8(0); + MOV32ItoR(tempreg, 8); + x86SetJ8( j8Ptr[5] ); + SHL32ItoR(tempreg, 4); + + OR8MtoR(EAX+4, (u32)&coded_block_pattern); // or ah, mem + OR8RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ctrl._u32, workingreg); +#endif + // NOTE: not updating ipuRegs->ctrl +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + return 1; + + case 0x10002020: // IPU_BP + + assert( (u32)&g_BP.FP + 1 == (u32)&g_BP.bufferhasnew ); + + MOVZX32M8toR(workingreg, (u32)&g_BP.BP); + MOVZX32M8toR(tempreg, (u32)&g_BP.FP); + AND8ItoR(workingreg, 0x7f); + ADD8MtoR(tempreg, (u32)&g_BP.bufferhasnew); + MOV8MtoR(workingreg+4, (u32)&g_BP.IFC); + + SHL32ItoR(tempreg, 16); + OR32RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ipubp, workingreg); +#endif + // NOTE: not updating ipuRegs->ipubp +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + + return 1; + + default: + // ipu repeats every 0x100 + _eeReadConstMem32(x86reg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + return 0; + } + + return 0; +} + +u64 ipuRead64(u32 mem) +{ + IPUProcessInterrupt(); + +#ifdef PCSX2_DEVBUILD + if( mem == 0x10002010 ) { + SysPrintf("reading 64bit IPU ctrl\n"); + } + if( mem == 0x10002020 ) { + SysPrintf("reading 64bit IPU top\n"); + } +#endif + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + //if(!ipuRegs->cmd.BUSY){ + if( ipuRegs->cmd.DATA&0xffffff ) { + IPU_LOG("Ipu read64: IPU_CMD=BUSY=%x, DATA=%08X\n", ipuRegs->cmd.BUSY?1:0,ipuRegs->cmd.DATA); + } +#endif + //return *(u64*)&ipuRegs->cmd; + break; + + case 0x10002030: // IPU_TOP +#ifdef IPU_LOG + IPU_LOG("Ipu read64: IPU_TOP=%x, bp = %d\n",ipuRegs->top,g_BP.BP); +#endif + //return *(u64*)&ipuRegs->top; + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu read64: Unknown=%x\n", mem); +#endif + break; + + } + return *(u64*)(((u8*)ipuRegs)+(mem&0xff)); +} + +void ipuConstRead64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)(((u8*)ipuRegs)+(mem&0xff))); + else { + MOVQMtoR(mmreg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + SetMMXstate(); + } +} + +void ipuSoftReset() +{ + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + fifo_wclear(); + coded_block_pattern = 0; + + ipuRegs->ctrl._u32 = 0; + g_BP.BP = 0; + g_BP.IFC = 0; + g_BP.FP = 0; + g_BP.bufferhasnew = 0; + ipuRegs->top = 0; + g_nCmdIndex = 0; + ipuCurCmd = 0xffffffff; + g_nCmdPos[0] = 0; g_nCmdPos[1] = 0; +} + +void ipuWrite32(u32 mem,u32 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE(value); + break; + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl._u32 = (value&0x47f30000)|(ipuRegs->ctrl._u32&0x8000ffff); + if (ipuRegs->ctrl.RST & 0x1) { // RESET + ipuSoftReset(); + } + +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CTRL=0x%08X\n",value); +#endif + + break; + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write32: Unknown=%x\n", mem); +#endif + *(u32*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite32(u32 mem, int mmreg) +{ + iFlushCall(0); + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) PUSH32R(mmreg); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: // IPU_CMD + if( (mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + case 0x10002010: // IPU_CTRL + if( mmreg & MEM_EECONSTTAG ) { + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x47f30000; + + if( c & 0x40000000 ) { + CALLFunc((u32)ipuSoftReset); + } + else { + AND32ItoM((u32)&ipuRegs->ctrl._u32, 0x8000ffff); + OR32ItoM((u32)&ipuRegs->ctrl._u32, c); + } + } + else { + if( mmreg & MEM_XMMTAG ) SSE2_MOVD_XMM_to_R(EAX, mmreg&0xf); + else if( mmreg & MEM_MMXTAG ) MOVD32MMXtoR(EAX, mmreg&0xf); + else POP32R(EAX); + + MOV32MtoR(ECX, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(EAX, 0x47f30000); + AND32ItoR(ECX, 0x8000ffff); + OR32RtoR(EAX, ECX); + MOV32RtoM((u32)&ipuRegs->ctrl._u32, EAX); + + TEST32ItoR(EAX, 0x40000000); + j8Ptr[5] = JZ8(0); + + // reset + CALLFunc((u32)ipuSoftReset); + + x86SetJ8( j8Ptr[5] ); + } + + break; + default: + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) POP32R(mmreg); + _eeWriteConstMem32((u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +void ipuWrite64(u32 mem, u64 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE((u32)value); + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: Unknown=%x\n", mem); +#endif + *(u64*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: + _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem64( (u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +/////////////////////////////////////////// +// IPU Commands (exec on worker thread only) + +static void ipuBCLR(u32 val) { + fifo_wclear(); + g_BP.BP = val & 0x7F; + g_BP.FP = 0; + g_BP.IFC = 0; +#ifdef IPU_LOG + IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X\n", g_BP.BP); +#endif +} + +static BOOL ipuIDEC(u32 val) +{ + tIPU_CMD_IDEC idec={0, 0, 0, 0, 0, 0, 0, 0, 0}; + + *(u32*)&idec=val; +#ifdef IPU_LOG + IPU_LOG("IPU IDEC command.\n"); + if (idec.FB){ IPU_LOG(" Skip %d bits.",idec.FB);} + IPU_LOG(" Quantizer step code=0x%X.",idec.QSC); + if (idec.DTD==0){ IPU_LOG(" Does not decode DT."); + }else{ IPU_LOG(" Decodes DT.");} + if (idec.SGN==0){ IPU_LOG(" No bias."); + }else{ IPU_LOG(" Bias=128.");} + if (idec.DTE==1){ IPU_LOG(" Dither Enabled.");} + if (idec.OFM==0){ IPU_LOG(" Output format is RGB32."); + }else{ IPU_LOG(" Output format is RGB16.");} + IPU_LOG("\n"); +#endif + g_BP.BP+= idec.FB;//skip FB bits + //from IPU_CTRL + ipuRegs->ctrl.PCT = I_TYPE; //Intra DECoding;) + g_decoder.coding_type =ipuRegs->ctrl.PCT; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from IDEC value + g_decoder.quantizer_scale =idec.QSC; + g_decoder.frame_pred_frame_dct=!idec.DTD; + g_decoder.sgn =idec.SGN; + g_decoder.dte =idec.DTE; + g_decoder.ofm =idec.OFM; + //other stuff + g_decoder.dcr =1;//resets DC prediction value + + s_routine = co_create(mpeg2sliceIDEC, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuBDEC(u32 val) +{ + tIPU_CMD_BDEC bdec={0, 0, 0, 0, 0, 0, 0, 0}; + *(u32*)&bdec=val; + +#ifdef IPU_LOG + IPU_LOG("IPU BDEC(macroblock decode) command.\n"); + if (bdec.FB){ IPU_LOG(" Skip 0x%X bits.", bdec.FB);} + if (bdec.MBI){ IPU_LOG(" Intra MB.");} + else{ IPU_LOG(" Non-intra MB.");} + if (bdec.DCR){ IPU_LOG(" Resets DC prediction value.");} + else{ IPU_LOG(" Doesn't reset DC prediction value.");} + if (bdec.DT){ IPU_LOG(" Use field DCT.");} + else{ IPU_LOG(" Use frame DCT.");} + IPU_LOG(" Quantiser step=0x%X\n",bdec.QSC); +#endif + g_BP.BP+= bdec.FB;//skip FB bits + g_decoder.coding_type = I_TYPE; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from BDEC value + /* JayteeMaster: the quantizer (linear/non linear) depends on the q_scale_type */ + g_decoder.quantizer_scale =g_decoder.q_scale_type?non_linear_quantizer_scale [bdec.QSC]:bdec.QSC<<1; + g_decoder.macroblock_modes =bdec.DT ? DCT_TYPE_INTERLACED : 0; + g_decoder.dcr =bdec.DCR; + g_decoder.macroblock_modes|=bdec.MBI ? MACROBLOCK_INTRA : MACROBLOCK_PATTERN; + + memset(&mb8, 0, sizeof(struct macroblock_8)); + memset(&mb16, 0, sizeof(struct macroblock_16)); + + s_routine = co_create(mpeg2_slice, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuVDEC(u32 val) { + + switch( g_nCmdPos[0] ) { + case 0: + ipuRegs->cmd.DATA = 0; + if( !getBits32((u8*)&g_decoder.bitstream_buf, 0) ) + return FALSE; + + g_decoder.bitstream_bits = -16; + g_decoder.bitstream_buf=BigEndian(g_decoder.bitstream_buf); + + //value = BigEndian(value); + switch((val >> 26) & 3){ + case 0://Macroblock Address Increment + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + ipuRegs->cmd.DATA = get_macroblock_address_increment(&g_decoder); + break; + case 1://Macroblock Type //known issues: no error detected + g_decoder.frame_pred_frame_dct=1;//prevent DCT_TYPE_INTERLACED + g_decoder.coding_type =ipuRegs->ctrl.PCT; + ipuRegs->cmd.DATA=get_macroblock_modes(&g_decoder); + break; + case 2://Motion Code //known issues: no error detected + ipuRegs->cmd.DATA=get_motion_delta(&g_decoder,0); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + case 3://DMVector + ipuRegs->cmd.DATA=get_dmv(&g_decoder); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + } + + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + g_BP.BP+=(g_decoder.bitstream_bits+16); + if((int)g_BP.BP < 0) { + g_BP.BP += 128; + ReorderBitstream(); + } + + ipuRegs->cmd.DATA = (ipuRegs->cmd.DATA & 0xFFFF) | ((g_decoder.bitstream_bits+16) << 16); + ipuRegs->ctrl.ECD = (ipuRegs->cmd.DATA==0); + + case 1: + if( !FillInternalBuffer(&g_BP.BP,1) ) { + g_nCmdPos[0] = 1; + return FALSE; + } + + case 2: + + if( !getBits32((u8*)&ipuRegs->top, 0) ) { + g_nCmdPos[0] = 2; + return FALSE; + } + + ipuRegs->top = BigEndian(ipuRegs->top); + +#ifdef IPU_LOG + IPU_LOG("IPU VDEC command data 0x%x(0x%x). Skip 0x%X bits/Table=%d (%s), pct %d\n", + ipuRegs->cmd.DATA,ipuRegs->cmd.DATA >> 16,val & 0x3f, (val >> 26) & 3, (val >> 26) & 1 ? + ((val >> 26) & 2 ? "DMV" : "MBT") : (((val >> 26) & 2 ? "MC" : "MBAI")),ipuRegs->ctrl.PCT); +#endif + + return TRUE; + } + + assert(0); + return FALSE; +} + +static BOOL ipuFDEC(u32 val) +{ + if( !getBits32((u8*)&ipuRegs->cmd.DATA, 0) ) + return FALSE; + + ipuRegs->cmd.DATA = BigEndian(ipuRegs->cmd.DATA); + ipuRegs->top = ipuRegs->cmd.DATA; + return TRUE; +} + +static BOOL ipuSETIQ(u32 val) +{ + int i; + + if ((val >> 27) & 1){ + g_nCmdPos[0] += getBits((u8*)niq + g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); // 8*8*8 + +#ifdef IPU_LOG + IPU_LOG("Read non-intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + niq[i*8+0], niq[i*8+1], niq[i*8+2], niq[i*8+3], + niq[i*8+4], niq[i*8+5], niq[i*8+6], niq[i*8+7]); + } +#endif + }else{ + g_nCmdPos[0] += getBits((u8*)iq+8*g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); +#ifdef IPU_LOG + IPU_LOG("Read intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + iq[i*8+0], iq[i*8+1], iq[i*8+2], iq[i*8+3], + iq[i*8+4], iq[i*8+5], iq[i*8+6], iq[i*8+7]); + } +#endif + } + + return g_nCmdPos[0] == 64; +} + +static BOOL ipuSETVQ(u32 val) +{ + g_nCmdPos[0] += getBits((u8*)vqclut+g_nCmdPos[0], 256-8*g_nCmdPos[0], 1); // 16*2*8 + + if( g_nCmdPos[0] == 32 ) { +#ifdef IPU_LOG + IPU_LOG("IPU SETVQ command.\nRead VQCLUT table from IPU FIFO.\n"); + IPU_LOG( + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n" + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n", + vqclut[0] >> 10, (vqclut[0] >> 5) & 0x1F, vqclut[0] & 0x1F, + vqclut[1] >> 10, (vqclut[1] >> 5) & 0x1F, vqclut[1] & 0x1F, + vqclut[2] >> 10, (vqclut[2] >> 5) & 0x1F, vqclut[2] & 0x1F, + vqclut[3] >> 10, (vqclut[3] >> 5) & 0x1F, vqclut[3] & 0x1F, + vqclut[4] >> 10, (vqclut[4] >> 5) & 0x1F, vqclut[4] & 0x1F, + vqclut[5] >> 10, (vqclut[5] >> 5) & 0x1F, vqclut[5] & 0x1F, + vqclut[6] >> 10, (vqclut[6] >> 5) & 0x1F, vqclut[6] & 0x1F, + vqclut[7] >> 10, (vqclut[7] >> 5) & 0x1F, vqclut[7] & 0x1F, + vqclut[8] >> 10, (vqclut[8] >> 5) & 0x1F, vqclut[8] & 0x1F, + vqclut[9] >> 10, (vqclut[9] >> 5) & 0x1F, vqclut[9] & 0x1F, + vqclut[10] >> 10, (vqclut[10] >> 5) & 0x1F, vqclut[10] & 0x1F, + vqclut[11] >> 10, (vqclut[11] >> 5) & 0x1F, vqclut[11] & 0x1F, + vqclut[12] >> 10, (vqclut[12] >> 5) & 0x1F, vqclut[12] & 0x1F, + vqclut[13] >> 10, (vqclut[13] >> 5) & 0x1F, vqclut[13] & 0x1F, + vqclut[14] >> 10, (vqclut[14] >> 5) & 0x1F, vqclut[14] & 0x1F, + vqclut[15] >> 10, (vqclut[15] >> 5) & 0x1F, vqclut[15] & 0x1F); +#endif + } + + return g_nCmdPos[0] == 32; +} + +// IPU Transfers are split into 8Qwords so we need to send ALL the data +static BOOL ipuCSC(u32 val) +{ + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + *(u32*)&csc=val; + +#ifdef IPU_LOG + IPU_LOG("IPU CSC(Colorspace conversion from YCbCr) command (%d).\n",csc.MBC); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is RGB32. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } +#endif + //SysPrintf("CSC\n"); + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 3072/8 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 3072-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 3072/8 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + if (csc.OFM){ + ipu_dither(&mb8, &rgb16, csc.DTE); + } + } + + if (csc.OFM){ + g_nCmdPos[1] += IPU0dma(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += IPU0dma(((u32*)&rgb32)+4*g_nCmdPos[1], 64-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 64 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +// Todo - Need to add the same stop and start code as CSC +static BOOL ipuPACK(u32 val) { + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + + *(u32*)&csc=val; +#ifdef IPU_LOG + IPU_LOG("IPU PACK (Colorspace conversion from RGB32) command.\n"); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is INDX4. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } + IPU_LOG("Number of macroblocks to be converted: %d\n", csc.MBC); +#endif + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 512 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 64 ) + return FALSE; + + ipu_dither(&mb8, &rgb16, csc.DTE); + if (csc.OFM){ + ipu_vq(&rgb16, indx4); + } + } + + if (csc.OFM) { + g_nCmdPos[1] += IPU0dma(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += IPU0dma(((u32*)indx4)+4*g_nCmdPos[1], 8-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 8 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +static void ipuSETTH(u32 val) { + s_thresh[0] = (val & 0xff); + s_thresh[1] = ((val>>16) & 0xff); +#ifdef IPU_LOG + IPU_LOG("IPU SETTH (Set threshold value)command %x.\n", val&0xff00ff); +#endif +} + +/////////////////////// +// IPU Worker Thread // +/////////////////////// +#define IPU_INTERRUPT(dma) { \ + if( (cpuRegs.interrupt & (1<ctrl.BUSY ) { + // wait for thread + SysPrintf("IPU BUSY!\n"); + } + + ipuRegs->ctrl.ECD = 0; + ipuRegs->ctrl.SCD = 0; //clear ECD/SCD + ipuRegs->cmd.DATA = val; + g_nCmdPos[0] = 0; + + switch (ipuRegs->cmd.CMD) { + case SCE_IPU_BCLR: + ipuBCLR(val); + IPU_INTERRUPT(DMAC_TO_IPU); + return; + + case SCE_IPU_VDEC: + + g_BP.BP+= val & 0x3F; + + // check if enough data in queue + if( ipuVDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_FDEC: + +#ifdef IPU_LOG + IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X bytes, BP 0x%X, FP %d, CHCR 0x%x\n", + val & 0x3f,g_BP.IFC,(int)g_BP.BP,g_BP.FP,((DMACh*)&PS2MEM_HW[0xb400])->chcr); +#endif + + g_BP.BP+= val & 0x3F; + + if( ipuFDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_SETTH: + ipuSETTH(val); + hwIntcIrq(INTC_IPU); + return; + + case SCE_IPU_SETIQ: +#ifdef IPU_LOG + IPU_LOG("IPU SETIQ command.\n"); +#endif +#ifdef IPU_LOG + if (val & 0x3f){ + IPU_LOG("Skip %d bits.\n", val & 0x3f); + } +#endif + g_BP.BP+= val & 0x3F; + + if( ipuSETIQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( ipuSETVQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_CSC: + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuCSC(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + case SCE_IPU_PACK: + + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuPACK(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + if( ipuIDEC(val) ) { + // idec done, ipu0 done too + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + FreezeMMXRegs(0); + + break; + + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + if( ipuBDEC(val) ) { + // bdec done, wait for ipu0 + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + FreezeMMXRegs(0); + + break; + } + + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; +} + +void IPUWorker() +{ + assert( ipuRegs->ctrl.BUSY ); + + switch (ipuCurCmd) { + case SCE_IPU_VDEC: + if( !ipuVDEC(ipuRegs->cmd.DATA) ) + return; + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_FDEC: + if( !ipuFDEC(ipuRegs->cmd.DATA) ) + return; + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_SETIQ: + if( !ipuSETIQ(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_SETVQ: + if( !ipuSETVQ(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_CSC: + if( !ipuCSC(ipuRegs->cmd.DATA) ) + return; + + break; + case SCE_IPU_PACK: + if( !ipuPACK(ipuRegs->cmd.DATA) ) + return; + + break; + + case SCE_IPU_BDEC: + case SCE_IPU_IDEC: + + FreezeMMXRegs(1); + co_call(s_routine); + if( !s_RoutineDone ) { + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + + default: + SysPrintf("Unknown IPU command: %x\n", ipuRegs->cmd.CMD); + break; + } + + // success + ipuRegs->ctrl.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_TO_IPU); +} + +///////////////// +// Buffer reader + +// move the readbits queue +__forceinline void inc_readbits() +{ + readbits += 16; + if( readbits >= _readbits+64 ) { + + // move back + *(u64*)(_readbits) = *(u64*)(_readbits+64); + *(u64*)(_readbits+8) = *(u64*)(_readbits+72); + readbits = _readbits; + } +} + +// returns the pointer of readbits moved by 1 qword +__forceinline u8* next_readbits() +{ + return readbits + 16; +} + +// returns the pointer of readbits moved by 1 qword +u8* prev_readbits() +{ + if( readbits < _readbits+16 ) { + return _readbits+48-(readbits-_readbits); + } + + return readbits-16; +} + +void ReorderBitstream() +{ + readbits = prev_readbits(); + g_BP.bufferhasnew = 1; + //g_BP.FP++; +} + +// IPU has a 2qword internal buffer whose status is pointed by FP. +// If FP is 1, there's 1 qword in buffer. Second qword is only loaded +// incase there are less than 32bits available in the first qword. +// \return Number of bits available (clamps at 16 bits) +u8 FillInternalBuffer(u32 * pointer, u32 advance) +{ + if(g_BP.FP == 0) + { + if( fifo_wread1(next_readbits()) == 0 ) + return 0; + + g_BP.bufferhasnew = 0; + inc_readbits(); + g_BP.FP = 1; + } + else if(g_BP.FP < 2 && g_BP.bufferhasnew == 0 ) + { + // in reality, need only > 96, but IPU reads ahead + if( *(int*)pointer > 96) { + if( !fifo_wread1(next_readbits()) ) + return 0; + g_BP.FP += 1; + } + } + + if(*(int*)pointer >= 128) + { + assert( g_BP.FP >= 1 || g_BP.bufferhasnew); + inc_readbits(); + + if(advance) + { + // Incase BDEC reorders bits, we need to make sure we have the old + // data backed up. So we store the last read qword into the 2nd slot + // of the internal buffer. After that we copy the new qword read in + // the 2nd slot to the 1st slot to be read. + if( !g_BP.bufferhasnew ) + g_BP.FP--; + g_BP.bufferhasnew = 0; + } + + *pointer &= 127; + } + + return (g_BP.FP+g_BP.bufferhasnew) == 1 ? g_BP.FP*128-pointer[0] : 128; +} + +// whenever reading fractions of bytes. The low bits always come from the next byte +// while the high bits come from the current byte +u8 getBits32(u8 *address, u32 advance) +{ + register u32 mask, shift=0; + u8* readpos; + + // Check if the current BP has exceeded or reached the limit of 128 + if( FillInternalBuffer(&g_BP.BP,1) < 32 ) + return 0; + + readpos = readbits+(int)g_BP.BP/8; + + if (g_BP.BP & 7) { + + shift = g_BP.BP&7; + mask = (0xff>>shift); + mask = mask|(mask<<8)|(mask<<16)|(mask<<24); + + *(u32*)address = ((~mask&*(u32*)(readpos+1))>>(8-shift)) | (((mask)&*(u32*)readpos)<>shift); + mask = mask|(mask<<8); + + *(u16*)address = ((~mask&*(u16*)(readpos+1))>>(8-shift)) | (((mask)&*(u16*)readpos)<>shift); + + *(u8*)address = (((~mask)&readpos[1])>>(8-shift)) | (((mask)&*readpos)<> (pointer&7)) << + (8-howmuch-(pointer&7))) & 0xFF; + mask &= readbits[((pointer)>>3)]; + mask >>= 8-howmuch-(pointer&7); + pointer += howmuch; + size -= howmuch; + shift -= howmuch; + *address |= mask << shift; + } + + ++address; + } + else + { + u8* readmem; + while (size) + { + if( FillInternalBuffer(&pointer,advance) < 8 ) + return address-oldaddr; + + howmuch = min(128-pointer, size); + size -= howmuch; + + readmem = readbits + (pointer>>3); + pointer += howmuch; + howmuch >>= 3; + + while(howmuch >= 4) { + *(u32*)address = *(u32*)readmem; + howmuch -= 4; + address += 4; + readmem += 4; + } + + switch(howmuch) { + case 3: address[2] = readmem[2]; + case 2: address[1] = readmem[1]; + case 1: address[0] = readmem[0]; + case 0: + break; + default: __assume(0); + } + + address += howmuch; + } + } + + // If not advance then reset the Reading buffer value + if(advance) g_BP.BP = pointer; + else readbits = oldbits; // restore the last pointer + + return address-oldaddr; +} + +///////////////////// CORE FUNCTIONS ///////////////// +void Skl_YUV_To_RGB32_MMX(u8 *RGB, const int Dst_BpS, const u8 *Y, const u8 *U, const u8 *V, + const int Src_BpS, const int Width, const int Height); + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn){ + int i; + u8* p = (u8*)rgb32; + + convert_init.start(convert_init.id, (u8*)rgb32, CONVERT_FRAME); + convert_init.copy(convert_init.id, (u8*)mb8->Y, (u8*)mb8->Cr, (u8*)mb8->Cb, 0); + + // do alpha processing +// if( cpucaps.hasStreamingSIMD2Extensions ) { +// int i; +// u8* p = (u8*)rgb32; +// +// __asm { +// movaps xmm6, s_thresh +// pshufd xmm7, xmm6, 0xee +// pshufd xmm6, xmm6, 0x44 +// pxor xmm5, xmm5 +// } +// +// for(i = 0; i < 64; i += 4, p += 64) { +// // process 2 qws at a time +// __asm { +// // extract 8 dwords +// mov edi, p +// movaps xmm0, qword ptr [edi] +// movaps xmm1, qword ptr [edi+16] +// movaps xmm2, qword ptr [edi+32] +// movaps xmm3, qword ptr [edi+48] +// +// +// } + // fixes suikoden5 + if( s_thresh[0] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + if( p[0] < s_thresh[0] && p[1] < s_thresh[0] && p[2] < s_thresh[0] ) + *(u32*)p = 0; + else + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else if( s_thresh[1] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else { + for(i = 0; i < 64; i++, p += 16) { + p[3] = p[7] = p[11] = p[15] = 0x80; + } + } +} + +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte){ + SysPrintf("IPU: Dither not implemented"); +} + +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4){ + SysPrintf("IPU: VQ not implemented"); +} + +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16){ + unsigned char *s=(unsigned char*)mb8; + signed short *d=(signed short*)mb16; + int i; + for (i=0; i< 256; i++) *d++ = *s++; //Y bias - 16 + for (i=0; i< 64; i++) *d++ = *s++; //Cr bias - 128 + for (i=0; i< 64; i++) *d++ = *s++; //Cb bias - 128 + /*for(i = 0; i < 384/(16*6); ++i, s += 16*4, d += 16*4) { + __m128i r0, r1, r2, r3, r4, r5, r6, r7; + + r0 = _mm_load_si128((__m128i*)s); + r2 = _mm_load_si128((__m128i*)s+1); + r4 = _mm_load_si128((__m128i*)s+2); + r6 = _mm_load_si128((__m128i*)s+3); + + // signed shift + r1 = _mm_srai_epi16(_mm_unpackhi_epi8(r0, r0), 8); + r0 = _mm_srai_epi16(_mm_unpacklo_epi8(r0, r0), 8); + r3 = _mm_srai_epi16(_mm_unpackhi_epi8(r2, r2), 8); + r2 = _mm_srai_epi16(_mm_unpacklo_epi8(r2, r2), 8); + r5 = _mm_srai_epi16(_mm_unpackhi_epi8(r4, r4), 8); + r4 = _mm_srai_epi16(_mm_unpacklo_epi8(r4, r4), 8); + r7 = _mm_srai_epi16(_mm_unpackhi_epi8(r6, r6), 8); + r6 = _mm_srai_epi16(_mm_unpacklo_epi8(r6, r6), 8); + + _mm_store_si128((__m128i*)d, r0); + _mm_store_si128((__m128i*)d+1, r1); + _mm_store_si128((__m128i*)d+2, r2); + _mm_store_si128((__m128i*)d+3, r3); + _mm_store_si128((__m128i*)d+4, r4); + _mm_store_si128((__m128i*)d+5, r5); + _mm_store_si128((__m128i*)d+6, r6); + _mm_store_si128((__m128i*)d+7, r7); + }*/ +} + +///////////////////// IPU DMA //////////////////////// +void fifo_wclear() +{ + //assert( g_BP.IFC == 0 ); + //memset(fifo_input,0,sizeof(fifo_input)); + g_BP.IFC = 0; + readwpos = 0; + writewpos = 0; +} + +int fifo_wread(void *value, int size) +{ + int transsize, firstsize; + + transsize = size; + + // transfer what is left in fifo + firstsize = min((int)g_BP.IFC, size); + g_BP.IFC -= firstsize; + size -= firstsize; + + while( firstsize-- > 0) { + + // transfer firstsize qwords, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + value = (u32*)value + 4; + } + + if(size > 0) { + + // fifo is too small, so have to get from DMA + while( IPU1dma() > 0 ) { + + firstsize = min(size, (int)g_BP.IFC); + size -= firstsize; + g_BP.IFC -= firstsize; + + while( firstsize-- > 0) { + + // transfer firstsize qwords, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + value = (u32*)value + 4; + } + + if( size == 0 ) + return transsize; + } + } + + return transsize-size; +} + +int fifo_wread1(void *value) +{ + // wait until enough data + if( g_BP.IFC == 0 ) { + if( IPU1dma() == 0 ) + return 0; + + assert( g_BP.IFC > 0 ); + } + + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_input[readwpos]; + ((u32*)value)[1] = fifo_input[readwpos+1]; + ((u32*)value)[2] = fifo_input[readwpos+2]; + ((u32*)value)[3] = fifo_input[readwpos+3]; + readwpos = (readwpos + 4) & 31; + g_BP.IFC--; + return 1; +} + +int fifo_wwrite(u32* pMem, int size) +{ + int transsize; + int firsttrans = min(size, 8-(int)g_BP.IFC); + + g_BP.IFC+=firsttrans; + transsize = firsttrans; + + while(transsize-- > 0) { + fifo_input[writewpos] = pMem[0]; + fifo_input[writewpos+1] = pMem[1]; + fifo_input[writewpos+2] = pMem[2]; + fifo_input[writewpos+3] = pMem[3]; + writewpos = (writewpos+4)&31; + pMem +=4; + } + + return firsttrans; +} + +#define IPU1chain() { \ + int qwc = ipu1dma->qwc; \ + pMem = (u32*)dmaGetAddr(ipu1dma->madr); \ + if (pMem == NULL) { SysPrintf("ipu1dma NULL!\n"); return totalqwc; } \ + qwc = fifo_wwrite(pMem, qwc); \ + ipu1dma->madr += qwc<< 4; \ + ipu1dma->qwc -= qwc; \ + totalqwc += qwc; \ + if( ipu1dma->qwc > 0 ) { \ + g_nDMATransfer |= IPU_DMA_ACTV1; \ + return totalqwc; \ + } \ +} + +int IPU1dma() +{ + u32 *ptag, *pMem; + int done=0; + int ipu1cycles = 0; + int totalqwc = 0; + + assert( !(ipu1dma->chcr&0x40) ); + + if( !(ipu1dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc > 0 ) { + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer&IPU_DMA_DOTIE1)) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + + if( (ipu1dma->chcr&0xc) == 0 ) { + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + else { + u32 tag = ipu1dma->chcr; // upper bits describe current tag + + if ((ipu1dma->chcr & 0x80) && (tag&0x80000000)) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(tag&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); +#ifdef IPU_LOG + IPU_LOG("dmaIrq Set\n"); +#endif + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + switch( tag&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + } + } + + if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) { // Normal Mode + //SysPrintf("ipu1 normal empty qwc?\n"); + return totalqwc; + } + + // Transfer Dn_QWC from Dn_MADR to GIF + if( ipu1dma->qwc > 0 ) { + IPU1chain(); + } + if ((ipu1dma->chcr & 0xc) == 0 ) { // Normal Mode + } + else { + // Chain Mode + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + ipu1cycles+=1; // Add 1 cycles from the QW read for the tag + + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + ipu1dma->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + //ipu1dma->madr = ptag[1]; //MADR = ADDR field + +#ifdef IPU_LOG + IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x\n", + ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); +#endif + + //done = hwDmacSrcChainWithStack(ipu1dma, id); + switch(ptag[0] & 0x70000000) { + case 0x00000000: // refe + // do not change tadr + ipu1dma->madr = ptag[1]; + done = 1; + break; + + case 0x10000000: // cnt + ipu1dma->madr = ipu1dma->tadr + 16; + // Set the taddr to the next tag + ipu1dma->tadr += 16 + (ipu1dma->qwc << 4); + break; + + case 0x20000000: // next + ipu1dma->madr = ipu1dma->tadr + 16; + ipu1dma->tadr = ptag[1]; + break; + + case 0x30000000: // ref + ipu1dma->madr = ptag[1]; + ipu1dma->tadr += 16; + break; + + case 0x70000000: // end + // do not change tadr + ipu1dma->madr = ipu1dma->tadr + 16; + done = 1; + break; + + default: + #ifdef IPU_LOG + IPU_LOG("ERROR: different transfer mode!, Please report to PCSX2 Team\n"); + #endif + break; + } + + if( ptag[0] & 0x80000000 ) + g_nDMATransfer |= IPU_DMA_DOTIE1; + else + g_nDMATransfer &= ~IPU_DMA_DOTIE1; + + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (ptag[0]&0x80000000) ) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + if( done ) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(ptag[0]&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + } + + switch( ptag[0]&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + return totalqwc; +} + +int IPU0dma(const void* ptr, int size) +{ + int readsize; + void* pMem; + + if( !(ipu0dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc == 0) + return 0; + + assert( !(ipu0dma->chcr&0x40) ); + +#ifdef IPU_LOG + IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx, ipuout_fifo.count=%x\n", + ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc, size); +#endif + + assert((ipu0dma->chcr & 0xC) == 0 ); + pMem = (u32*)dmaGetAddr(ipu0dma->madr); + + readsize = min(ipu0dma->qwc, size); + + memcpy_amd(pMem, ptr, readsize<<4); + ipu0dma->madr += readsize<< 4; + ipu0dma->qwc -= readsize; // note: qwc is u16 + + if(ipu0dma->qwc == 0) { + if ((psHu32(DMAC_CTRL) & 0x30) == 0x30) { // STS == fromIPU + psHu32(DMAC_STADR) = ipu0dma->madr; + switch (psHu32(DMAC_CTRL) & 0xC0) { + case 0x80: // GIF + g_nDMATransfer |= IPU_DMA_GIFSTALL; + break; + } + } + + INT(DMAC_FROM_IPU, (readsize*BIAS)); + } + + return readsize; +} + +void dmaIPU0() // fromIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +void dmaIPU1() // toIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +int ipu0Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu0Interrupt:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT0 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT0; + } + + if( g_nDMATransfer & IPU_DMA_GIFSTALL ) { + // gif + g_nDMATransfer &= ~IPU_DMA_GIFSTALL; + dmaGIF(); + } + + if( g_nDMATransfer & IPU_DMA_TIE0 ) { + g_nDMATransfer &= ~IPU_DMA_TIE0; + hwDmacIrq(DMAC_FROM_IPU); + } + else { + ipu0dma->chcr &= ~0x100; + hwDmacIrq(DMAC_FROM_IPU); + } + + return 1; +} + +int ipu1Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu1Interrupt:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT1 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT1; + } + + if( g_nDMATransfer & IPU_DMA_TIE1 ) { + g_nDMATransfer &= ~IPU_DMA_TIE1; + hwDmacIrq(DMAC_TO_IPU); + } + else { + ipu1dma->chcr &= ~0x100; + hwDmacIrq(DMAC_TO_IPU); + } + + return 1; +} diff --git a/branches/pcsx2_0.9.1/IPU/IPU.h b/branches/pcsx2_0.9.1/IPU/IPU.h new file mode 100644 index 0000000..2f05c5f --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/IPU.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IPU_H__ +#define __IPU_H__ + +#include "Common.h" + +#ifdef __WIN32__ +#pragma pack(1) +#endif + +// +// Bitfield Structure +// +typedef union { + struct { + u32 OPTION : 28; // VDEC decoded value + u32 CMD : 4; // last command + u32 _BUSY; + }; + struct { + u32 DATA; + u32 BUSY; + }; +} tIPU_CMD; + +#define IPU_CTRL_IFC_M (0x0f<< 0) +#define IPU_CTRL_OFC_M (0x0f<< 4) +#define IPU_CTRL_CBP_M (0x3f<< 8) +#define IPU_CTRL_ECD_M (0x01<<14) +#define IPU_CTRL_SCD_M (0x01<<15) +#define IPU_CTRL_IDP_M (0x03<<16) +#define IPU_CTRL_AS_M (0x01<<20) +#define IPU_CTRL_IVF_M (0x01<<21) +#define IPU_CTRL_QST_M (0x01<<22) +#define IPU_CTRL_MP1_M (0x01<<23) +#define IPU_CTRL_PCT_M (0x07<<24) +#define IPU_CTRL_RST_M (0x01<<30) +#define IPU_CTRL_BUSY_M (0x01<<31) + +#define IPU_CTRL_IFC_O ( 0) +#define IPU_CTRL_OFC_O ( 4) +#define IPU_CTRL_CBP_O ( 8) +#define IPU_CTRL_ECD_O (14) +#define IPU_CTRL_SCD_O (15) +#define IPU_CTRL_IDP_O (16) +#define IPU_CTRL_AS_O (20) +#define IPU_CTRL_IVF_O (21) +#define IPU_CTRL_QST_O (22) +#define IPU_CTRL_MP1_O (23) +#define IPU_CTRL_PCT_O (24) +#define IPU_CTRL_RST_O (30) +#define IPU_CTRL_BUSY_O (31) + + +// +// Bitfield Structure +// +typedef union { + struct { + u32 IFC : 4; // Input FIFO counter + u32 OFC : 4; // Output FIFO counter + u32 CBP : 6; // Coded block pattern + u32 ECD : 1; // Error code pattern + u32 SCD : 1; // Start code detected + u32 IDP : 2; // Intra DC precision + u32 resv0 : 2; + u32 AS : 1; // Alternate scan + u32 IVF : 1; // Intra VLC format + u32 QST : 1; // Q scale step + u32 MP1 : 1; // MPEG1 bit strea + u32 PCT : 3; // Picture Type + u32 resv1 : 3; + u32 RST : 1; // Reset + u32 BUSY : 1; // Busy + }; + u32 _u32; +} tIPU_CTRL; + +#define IPU_BP_BP_M (0x7f<< 0) +#define IPU_BP_IFC_M (0x0f<< 8) +#define IPU_BP_FP_M (0x03<<16) + +#define IPU_BP_BP_O ( 0) +#define IPU_BP_IFC_O ( 8) +#define IPU_BP_FP_O (16) + + +// +// Bitfield Structure +// +typedef struct { + u32 BP; // Bit stream point + u16 IFC; // Input FIFO counter + u8 FP; // FIFO point + u8 bufferhasnew; +} tIPU_BP; + +#ifdef __WIN32__ +#pragma pack() +#endif + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 3; + u32 DTD : 1; + u32 SGN : 1; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_IDEC; + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 4; + u32 DT : 1; + u32 DCR : 1; + u32 MBI : 1; + u32 cmd : 4; +} tIPU_CMD_BDEC; + +typedef struct { + u32 MBC :11; + u32 UN2 :15; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_CSC; + +#define SCE_IPU_BCLR 0x0 +#define SCE_IPU_IDEC 0x1 +#define SCE_IPU_BDEC 0x2 +#define SCE_IPU_VDEC 0x3 +#define SCE_IPU_FDEC 0x4 +#define SCE_IPU_SETIQ 0x5 +#define SCE_IPU_SETVQ 0x6 +#define SCE_IPU_CSC 0x7 +#define SCE_IPU_PACK 0x8 +#define SCE_IPU_SETTH 0x9 + +typedef struct _IPUregisters { + tIPU_CMD cmd; + u32 dummy0[2]; + tIPU_CTRL ctrl; + u32 dummy1[3]; + u32 ipubp; + u32 dummy2[3]; + u32 top; + u32 topbusy; + u32 dummy3[2]; +} IPUregisters; + +#ifdef WIN32_VIRTUAL_MEM +#define ipuRegs ((IPUregisters*)(PS2MEM_HW+0x2000)) +#else +extern IPUregisters g_ipuRegsReal; +#define ipuRegs (&g_ipuRegsReal) +#endif + +void dmaIPU0(); +void dmaIPU1(); + +int ipuInit(); +void ipuReset(); +void ipuShutdown(); +int ipuFreeze(gzFile f, int Mode); +BOOL ipuCanFreeze(); + +u32 ipuRead32(u32 mem); +int ipuConstRead32(u32 x86reg, u32 mem); + +u64 ipuRead64(u32 mem); +void ipuConstRead64(u32 mem, int mmreg); + +void ipuWrite32(u32 mem,u32 value); +void ipuConstWrite32(u32 mem, int mmreg); + +void ipuWrite64(u32 mem,u64 value); +void ipuConstWrite64(u32 mem, int mmreg); + +int ipu0Interrupt(); +int ipu1Interrupt(); + +u8 getBits32(u8 *address, u32 advance); +u8 getBits16(u8 *address, u32 advance); +u8 getBits8(u8 *address, u32 advance); +int getBits(u8 *address, u32 size, u32 advance); + +#endif diff --git a/branches/pcsx2_0.9.1/IPU/idct_mmx.obj b/branches/pcsx2_0.9.1/IPU/idct_mmx.obj new file mode 100644 index 0000000000000000000000000000000000000000..9f7d3136085bf4a54addc94ef8f77313e62d4963 GIT binary patch literal 11510 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 HNu%)(hlkEg literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.1/IPU/mpeg2lib/Idct.c b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Idct.c new file mode 100644 index 0000000..6529956 --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Idct.c @@ -0,0 +1,302 @@ +/* + * idct.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//#include +#include "Common.h" +#include "ix86/ix86.h" + +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ +#define clp(val,res) res = (val < 0) ? 0 : ((val > 255) ? 255 : val); +#define clp2(val,res) res = (val < -255) ? -255 : ((val > 255) ? 255 : val); +/* idct main entry point */ +void (* mpeg2_idct_copy) (s16 * block, u8 * dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16 * dest, int stride); + +/* + * In legal streams, the IDCT output should be between -384 and +384. + * In corrupted streams, it is possible to force the IDCT output to go + * to +-3826 - this is the worst case for a column IDCT where the + * column inputs are 16-bit values. + */ +static u8 clip_lut[1024]; +#define CLIP(i) ((clip_lut+384)[(i)]) + +#if 0 +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + t0 = W0*d0 + W1*d1; \ + t1 = W0*d1 - W1*d0; \ +} while (0) +#else +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + int tmp = W0 * (d0 + d1); \ + t0 = tmp + (W1 - W0) * d1; \ + t1 = tmp - (W1 + W0) * d0; \ +} while (0) +#endif + +static void idct_row (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + /* shortcut */ + if (!(block[1] | ((s32 *)block)[1] | ((s32 *)block)[2] | + ((s32 *)block)[3])) { + u32 tmp = (u16) (block[0] << 3); + tmp |= tmp << 16; + ((s32 *)block)[0] = tmp; + ((s32 *)block)[1] = tmp; + ((s32 *)block)[2] = tmp; + ((s32 *)block)[3] = tmp; + return; + } + + d0 = (block[0] << 11) + 128; + d1 = block[1]; + d2 = block[2] << 11; + d3 = block[3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[4]; + d1 = block[5]; + d2 = block[6]; + d3 = block[7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) * 181) >> 8; + b2 = ((t0 - t1) * 181) >> 8; + + block[0] = (a0 + b0) >> 8; + block[1] = (a1 + b1) >> 8; + block[2] = (a2 + b2) >> 8; + block[3] = (a3 + b3) >> 8; + block[4] = (a3 - b3) >> 8; + block[5] = (a2 - b2) >> 8; + block[6] = (a1 - b1) >> 8; + block[7] = (a0 - b0) >> 8; +} + +static void idct_col (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + d0 = (block[8*0] << 11) + 65536; + d1 = block[8*1]; + d2 = block[8*2] << 11; + d3 = block[8*3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[8*4]; + d1 = block[8*5]; + d2 = block[8*6]; + d3 = block[8*7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 = (t0 - t2) >> 8; + t1 = (t1 - t3) >> 8; + b1 = (t0 + t1) * 181; + b2 = (t0 - t1) * 181; + + block[8*0] = (a0 + b0) >> 17; + block[8*1] = (a1 + b1) >> 17; + block[8*2] = (a2 + b2) >> 17; + block[8*3] = (a3 + b3) >> 17; + block[8*4] = (a3 - b3) >> 17; + block[8*5] = (a2 - b2) >> 17; + block[8*6] = (a1 - b1) >> 17; + block[8*7] = (a0 - b0) >> 17; +} + +static void mpeg2_idct_copy_c (s16 * block, u8 * dest, + const int stride) +{ + int i; + + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = CLIP (block[0]); + dest[1] = CLIP (block[1]); + dest[2] = CLIP (block[2]); + dest[3] = CLIP (block[3]); + dest[4] = CLIP (block[4]); + dest[5] = CLIP (block[5]); + dest[6] = CLIP (block[6]); + dest[7] = CLIP (block[7]); + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void mpeg2_idct_add_c (const int last, s16 * block, + /*u8*/s16 * dest, const int stride) +{ + int i; + + if (last != 129 || (block[0] & 7) == 4) { + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = block[0]; + dest[1] = block[1]; + dest[2] = block[2]; + dest[3] = block[3]; + dest[4] = block[4]; + dest[5] = block[5]; + dest[6] = block[6]; + dest[7] = block[7]; + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); + } else { + int DC; + + DC = (block[0] + 4) >> 3; + block[0] = block[63] = 0; + i = 8; + do { + dest[0] = DC; + dest[1] = DC; + dest[2] = DC; + dest[3] = DC; + dest[4] = DC; + dest[5] = DC; + dest[6] = DC; + dest[7] = DC; + dest += stride; + } while (--i); + } +} + +u8 mpeg2_scan_norm[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +u8 mpeg2_scan_alt[64] = { + /* Alternate scan pattern */ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* idct_mmx.c */ +void mpeg2_idct_copy_mmxext (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmxext (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_copy_mmx (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmx (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_mmx_init (void); + +void mpeg2_idct_init() +{ +#ifndef __VCNET2005__ + int i, j; + +/* if(hasMultimediaExtensions == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmx; + mpeg2_idct_add = mpeg2_idct_add_mmx; + mpeg2_idct_mmx_init (); + }else if(hasMultimediaExtensionsExt == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmxext; + mpeg2_idct_add = mpeg2_idct_add_mmxext; + mpeg2_idct_mmx_init (); + }else*/ + { + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } + } + +#else //blah vcnet2005 idiocity :D + int i,j; + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } +#endif +} diff --git a/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.c b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.c new file mode 100644 index 0000000..67024e7 --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.c @@ -0,0 +1,1252 @@ +/* + * Mpeg.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Mpeg.h" +#include "Vlc.h" + +#define BigEndian _byteswap_ulong + +extern void (* mpeg2_idct_copy) (s16 * block, u8* dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +extern void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16* dest, int stride); + +extern int IPU0dma(const void* pMem, int size); + +/* JayteeMaster: remove static attribute */ +/*static */int non_linear_quantizer_scale [] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +extern tIPU_BP g_BP; + +/* Bitstream and buffer needs to be realocated inorder for sucessful + reading of the old data. Here the old data stored in the 2nd slot + of the internal buffer is copied to 1st slot, and the new data read + into 1st slot is copied to the 2nd slot. Which will later be copied + back to the 1st slot when 128bits have been read. +*/ +extern void ReorderBitstream(); + +int get_macroblock_modes (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int macroblock_modes; + const MBtab * tab; + + switch (decoder->coding_type) { + case I_TYPE: + + macroblock_modes = UBITS (bit_buf, 2); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_I + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if ((! (decoder->frame_pred_frame_dct)) && + (decoder->picture_structure == FRAME_PICTURE)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes; + + case P_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_P + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case B_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + tab = MB_B + macroblock_modes; + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (! (macroblock_modes & MACROBLOCK_INTRA)) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_INTRA) + goto intra; + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + intra: + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case D_TYPE: + + macroblock_modes = UBITS (bit_buf, 1); + if( macroblock_modes == 0 ) + return 0; // error + DUMPBITS (bit_buf, bits, 1); + return MACROBLOCK_INTRA; + + default: + return 0; + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_quantizer_scale (decoder_t * const decoder) +{ + int quantizer_scale_code; + + quantizer_scale_code = UBITS (decoder->bitstream_buf, 5); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 5); + + if (decoder->q_scale_type) return non_linear_quantizer_scale [quantizer_scale_code]; + else return quantizer_scale_code << 1; +} + +static int get_coded_block_pattern (decoder_t * const decoder) +{ + const CBPtab * tab; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + if (decoder->bitstream_buf >= 0x20000000) { + tab = CBP_7 + (UBITS (decoder->bitstream_buf, 7) - 16); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; + } + + tab = CBP_9 + UBITS (decoder->bitstream_buf, 9); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; +} + +static int get_luma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_lum_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 3); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_chroma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 2); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define SATURATE(val) \ +do { \ + if (((u32)(val + 2048) > 4095)) \ + val = SBITS (val, 1) ^ 2047; \ +} while (0) + +static void get_intra_block_B14 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static void get_intra_block_B15 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x04000000) { + + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) { + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + /* if (i >= 128) break; */ /* end of block */ + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check against buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + } else if (bit_buf >= 0x02000000) { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>28) != 0x6 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_non_intra_block (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + s16 * dest; + + i = -1; + mismatch = 1; + dest = decoder->DCTblock; + + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void get_mpeg1_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = 0; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_mpeg1_non_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = -1; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + val = 2 * (val + SBITS (val, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +} + +static void slice_intra_DCT (decoder_t * const decoder, const int cc, + u8 * const dest, const int stride) +{ + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + /* Get the intra DC coefficient and inverse quantize it */ + if (cc == 0) decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); + else decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[cc] << (3 - decoder->intra_dc_precision); + + if (decoder->mpeg1) get_mpeg1_intra_block (decoder); + else if (decoder->intra_vlc_format){ + get_intra_block_B15 (decoder); + }else{ + get_intra_block_B14 (decoder); + } + + mpeg2_idct_copy (decoder->DCTblock, dest, stride); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void slice_non_intra_DCT (decoder_t * const decoder, + /*u8*/s16 * const dest, const int stride){ + int last; + memset(decoder->DCTblock,0,sizeof(decoder->DCTblock)); + if (decoder->mpeg1) last = get_mpeg1_non_intra_block (decoder); + else last = get_non_intra_block (decoder); + + mpeg2_idct_add (last, decoder->DCTblock, dest, stride); +} + +extern int coded_block_pattern; +extern u8 FillInternalBuffer(u32 * pointer, u32 advance); +extern decoder_t g_decoder; +extern int g_nIPU0Data; // or 0x80000000 whenever transferring +extern u8* g_pIPU0Pointer; + +void mpeg2sliceIDEC(void* pdone) +{ + u32 read; + decoder_t * decoder = &g_decoder; + + *(int*)pdone = 0; + bitstream_init(decoder); + + decoder->dc_dct_pred[0] = + decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + decoder->mbc=0; + + if (UBITS (decoder->bitstream_buf, 2) == 0) + { + ipuRegs->ctrl.SCD = 0; + }else{ + while (1) { + int DCT_offset, DCT_stride; + int mba_inc; + const MBAtab * mba; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + decoder->macroblock_modes = get_macroblock_modes (decoder); + + /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ + if (decoder->macroblock_modes & MACROBLOCK_QUANT)//only IDEC + decoder->quantizer_scale = get_quantizer_scale (decoder); + + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + } + + // Send The MacroBlock via DmaIpuFrom + if (decoder->ofm==0){ + ipu_csc(decoder->mb8, decoder->rgb32, decoder->sgn); + + g_nIPU0Data = 64; + g_pIPU0Pointer = (u8*)decoder->rgb32; + while(g_nIPU0Data > 0) { + read = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + co_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + else{ + ipu_dither(decoder->mb8, decoder->rgb16, decoder->dte); + + g_nIPU0Data = 32; + g_pIPU0Pointer = (u8*)decoder->rgb16; + while(g_nIPU0Data > 0) { + read = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + co_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + decoder->mbc++; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + mba_inc = 0; + while (1) { + if (decoder->bitstream_buf >= 0x10000000) { + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + break; + } else if (decoder->bitstream_buf >= 0x03000000) { + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + break; + } else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + mba_inc += 33; + /* pass through */ + case 15: /* macroblock_stuffing (MPEG1 only) */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + continue; + default: /* end of slice/frame, or error? */ + { + int i; + ipuRegs->ctrl.SCD = 1; + ipuRegs->ctrl.ECD=0; + coded_block_pattern=decoder->coded_block_pattern; + + for (i=0; i<2; i++) { + u8 byte; + while(!getBits8(&byte, 0)) + co_resume(); + if (byte == 0) break; + g_BP.BP+= 8; + } + g_BP.BP-=32;//bitstream_init takes 32 bits + + while(!FillInternalBuffer(&g_BP.BP,1)) + co_resume(); + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + *(int*)pdone = 1; + co_exit(); + } + } + } + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + mba_inc += mba->mba; + + if (mba_inc) { + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + do { + decoder->mbc++; + } while (--mba_inc); + } + } + } + + ipuRegs->ctrl.ECD=!ipuRegs->ctrl.SCD; + + coded_block_pattern=decoder->coded_block_pattern; + + g_BP.BP-=32;//bitstream_init takes 32 bits + + while(!FillInternalBuffer(&g_BP.BP,1)) + co_resume(); + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + *(int*)pdone = 1; + co_exit(); +} + +void mpeg2_slice(void* pdone) +{ + int DCT_offset, DCT_stride; + u8 bit8=0; + u32 fp = g_BP.FP; + u32 bp; + decoder_t * decoder = &g_decoder; + u32 size = 0; + + *(int*)pdone = 0; + ipuRegs->ctrl.ECD = 0; + + bitstream_init (decoder); + + if (decoder->dcr) + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + ipu_copy(decoder->mb8,decoder->mb16); + } else { + if (decoder->macroblock_modes & MACROBLOCK_PATTERN) { + decoder->coded_block_pattern = get_coded_block_pattern (decoder); + /* JayteeMaster: changed from mb8 to mb16 and from u8 to s16 */ + if (decoder->coded_block_pattern & 0x20) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y, DCT_stride); + if (decoder->coded_block_pattern & 0x10) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x08) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset, DCT_stride); + if (decoder->coded_block_pattern & 0x04) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x2) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cb, decoder->stride>>1); + if (decoder->coded_block_pattern & 0x1) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cr, decoder->stride>>1); + + } + } + + //Send The MacroBlock via DmaIpuFrom + size = 0; // Reset + + ipuRegs->ctrl.SCD=0; + coded_block_pattern=decoder->coded_block_pattern; + + //FillInternalBuffer(&g_BP.BP, 1); + + bp = g_BP.BP; + g_BP.BP+=decoder->bitstream_bits-16; + + // BP goes from 0 to 128, so negative values mean to read old buffer + // so we minus from 128 to get the correct BP + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + g_nIPU0Data = 48; + g_pIPU0Pointer = (u8*)decoder->mb16; + while(g_nIPU0Data > 0) { + size = IPU0dma(g_pIPU0Pointer,g_nIPU0Data); + if( size == 0 ) + co_resume(); + else { + g_pIPU0Pointer += size*16; + g_nIPU0Data -= size; + } + } + + IPU_LOG("BDEC %x, %d\n",g_BP.BP,g_BP.FP); + + while( !getBits8((u8*)&bit8, 0) ) + co_resume(); + if (bit8==0) ipuRegs->ctrl.SCD = 1; + + while(!getBits32((u8*)&ipuRegs->top, 0)) + co_resume(); + ipuRegs->top = BigEndian(ipuRegs->top); + + *(int*)pdone = 1; + co_exit(); +} + +int get_motion_delta (decoder_t * const decoder, + const int f_code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int delta; + int sign; + const MVtab * tab; + + if ( (bit_buf & 0x80000000) ) { + DUMPBITS (bit_buf, bits, 1); + return 0x00010000; + } else if ( (bit_buf & 0xf0000000) || ((bit_buf & 0xfc000000)==0x0c000000) ) { + + tab = MV_4 + UBITS (bit_buf, 4); + delta = (tab->delta << f_code) + 1; + bits += tab->len + f_code + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + delta += UBITS (bit_buf, f_code); + bit_buf <<= f_code; + + return (delta ^ sign) - sign; + + } else { + + tab = MV_10 + UBITS (bit_buf, 10); + delta = (tab->delta << f_code) + 1; + bits += tab->len + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) { + NEEDBITS (bit_buf, bits, bit_ptr); + delta += UBITS (bit_buf, f_code); + DUMPBITS (bit_buf, bits, f_code); + } + + return (delta ^ sign) - sign; + + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_dmv (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DMVtab * tab; + + tab = DMV_2 + UBITS (bit_buf, 2); + DUMPBITS (bit_buf, bits, tab->len); + return tab->dmv; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_macroblock_address_increment(decoder_t * const decoder){ + const MBAtab *mba; + + if (decoder->bitstream_buf >= 0x10000000) + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + else if (decoder->bitstream_buf >= 0x03000000) + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x23; + case 15: /* macroblock_stuffing (MPEG1 only) */ + if (decoder->mpeg1){ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x22; + } + default: + return 0;//error + } + + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + return mba->mba + 1; +} diff --git a/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.h b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.h new file mode 100644 index 0000000..e866bfe --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Mpeg.h @@ -0,0 +1,185 @@ +/* + * Mpeg.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MPEG_H__ +#define __MPEG_H__ + +#include "Common.h" + +/* macroblock modes */ +#define MACROBLOCK_INTRA 1 +#define MACROBLOCK_PATTERN 2 +#define MACROBLOCK_MOTION_BACKWARD 4 +#define MACROBLOCK_MOTION_FORWARD 8 +#define MACROBLOCK_QUANT 16 +#define DCT_TYPE_INTERLACED 32 +/* motion_type */ +#define MOTION_TYPE_SHIFT 6 +#define MOTION_TYPE_MASK (3*64) +#define MOTION_TYPE_BASE 64 +#define MC_FIELD (1*64) +#define MC_FRAME (2*64) +#define MC_16X8 (2*64) +#define MC_DMV (3*64) + +/* picture structure */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +/* picture coding type */ +#define I_TYPE 1 +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +struct macroblock_8{ + unsigned char Y[16][16]; //0 + unsigned char Cb[8][8]; //1 + unsigned char Cr[8][8]; //2 +}; + +struct macroblock_16{ + short Y[16][16]; //0 + short Cb[8][8]; //1 + short Cr[8][8]; //2 +}; + +struct rgb32{ + unsigned char r, g, b, a; +}; + +struct macroblock_rgb32{ + struct rgb32 c[16][16]; +}; + +struct rgb16{ + unsigned short r:5, g:5, b:5, a:1; +}; + +struct macroblock_rgb16{ + struct rgb16 c[16][16]; +}; + +struct decoder_s { + /* first, state that carries information from one macroblock to the */ + /* next inside a slice, and is never used outside of mpeg2_slice() */ + + /* DCT coefficients - should be kept aligned ! */ + s16 DCTblock[64]; + + /* bit parsing stuff */ + u32 bitstream_buf; /* current 32 bit working set */ + int bitstream_bits; /* used bits in working set */ + u8 * bitstream_ptr; /* buffer with stream data; 128 bits buffer */ + + struct macroblock_8 *mb8; + struct macroblock_16 *mb16; + struct macroblock_rgb32 *rgb32; + struct macroblock_rgb16 *rgb16; + + int stride; + + /* predictor for DC coefficients in intra blocks */ + s16 dc_dct_pred[3]; + + int quantizer_scale; /* remove */ + int dmv_offset; /* remove */ + + /* now non-slice-specific information */ + + /* sequence header stuff */ + u8 *intra_quantizer_matrix; + u8 *non_intra_quantizer_matrix; + + /* picture header stuff */ + + /* what type of picture this is (I, P, B, D) */ + int coding_type; + + /* picture coding extension stuff */ + + /* quantization factor for intra dc coefficients */ + int intra_dc_precision; + /* top/bottom/both fields */ + int picture_structure; + /* bool to indicate all predictions are frame based */ + int frame_pred_frame_dct; + /* bool to indicate whether intra blocks have motion vectors */ + /* (for concealment) */ + int concealment_motion_vectors; + /* bit to indicate which quantization table to use */ + int q_scale_type; + /* bool to use different vlc tables */ + int intra_vlc_format; + /* used for DMV MC */ + int top_field_first; + // Pseudo Sign Offset + int sgn; + // Dither Enable + int dte; + // Output Format + int ofm; + // Macroblock count + int mbc; + // Macroblock type + int macroblock_modes; + // DC Reset + int dcr; + // Coded block pattern + int coded_block_pattern; + + /* stuff derived from bitstream */ + + /* pointer to the zigzag scan we're supposed to be using */ + const u8 * scan; + + int second_field; + + int mpeg1; +}; + +typedef struct decoder_s decoder_t; + +#define IDEC 0 +#define BDEC 1 +void mpeg2sliceIDEC(void* pdone); +void mpeg2_slice(void* pdone); +int get_macroblock_address_increment(decoder_t * const decoder); +int get_macroblock_modes (decoder_t * const decoder); +int get_motion_delta (decoder_t * const decoder, + const int f_code); +int get_dmv (decoder_t * const decoder); +int non_linear_quantizer_scale[]; // JayteeMaster: it is needed in Ipu.c + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn); +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte); +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4); +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16); + +int slice (decoder_t * const decoder, u8 * buffer); +/* idct.c */ +void mpeg2_idct_init (); + +#endif//__MPEG_H__ diff --git a/branches/pcsx2_0.9.1/IPU/mpeg2lib/Vlc.h b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Vlc.h new file mode 100644 index 0000000..ef8f43e --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/mpeg2lib/Vlc.h @@ -0,0 +1,441 @@ +/* + * vlc.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VLC_H__ +#define __VLC_H__ + +#include "IPU.h" +#include "pcl.h" + +static u8 data[2]; +static u8 dword[4]; +static void GETWORD(u32 * bit_buf,int bits) +{ + while(!getBits16(data,1)) + co_resume(); + *bit_buf |= ((data[0] << 8) | data[1]) << (bits); +} + +static void bitstream_init (decoder_t * decoder){ + decoder->bitstream_bits = -16; + + while( !getBits32(dword, 1) ) + co_resume(); + + decoder->bitstream_buf = (dword[0] << 24) | (dword[1] << 16) | + (dword[2] << 8) |dword[3]; +} + +/* make sure that there are at least 16 valid bits in bit_buf */ +#define NEEDBITS(bit_buf,bits,bit_ptr) \ +do { \ + if (bits > 0) { \ + GETWORD(&bit_buf,bits); \ + bits -= 16; \ + } \ +} while (0) + +/* remove num valid bits from bit_buf */ +#define DUMPBITS(bit_buf,bits,num) \ +do { \ + /*IPU_LOG("DUMPBITS %d\n",num);*/ \ + bit_buf <<= (num); \ + bits += (num); \ +} while (0) + +/* take num bits from the high part of bit_buf and zero extend them */ +#define UBITS(bit_buf,num) (((u32)(bit_buf)) >> (32 - (num))) + +/* take num bits from the high part of bit_buf and sign extend them */ +#define SBITS(bit_buf,num) (((s32)(bit_buf)) >> (32 - (num))) + +typedef struct { + u8 modes; + u8 len; +} MBtab; + +typedef struct { + u8 delta; + u8 len; +} MVtab; + +typedef struct { + s8 dmv; + u8 len; +} DMVtab; + +typedef struct { + u8 cbp; + u8 len; +} CBPtab; + +typedef struct { + u8 size; + u8 len; +} DCtab; + +typedef struct { + u8 run; + u8 level; + u8 len; +} DCTtab; + +typedef struct { + u8 mba; + u8 len; +} MBAtab; + + +#define INTRA MACROBLOCK_INTRA +#define QUANT MACROBLOCK_QUANT + +static const MBtab MB_I [] = { + {INTRA|QUANT, 2}, {INTRA, 1} +}; + +#define MC MACROBLOCK_MOTION_FORWARD +#define CODED MACROBLOCK_PATTERN + +static const MBtab MB_P [] = { + {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, + {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} +}; + +#define FWD MACROBLOCK_MOTION_FORWARD +#define BWD MACROBLOCK_MOTION_BACKWARD +#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD + +static const MBtab MB_B [] = { + {0, 0}, {INTRA|QUANT, 6}, + {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, + {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, + {INTRA, 5}, {INTRA, 5}, + {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, + {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} +}; + +#undef INTRA +#undef QUANT +#undef MC +#undef CODED +#undef FWD +#undef BWD +#undef INTER + + +static const MVtab MV_4 [] = { + { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} +}; + +static const MVtab MV_10 [] = { + { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, + { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, + {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, + { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, + { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, + { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} +}; + + +static const DMVtab DMV_2 [] = { + { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} +}; + + +static const CBPtab CBP_7 [] = { + {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7}, + {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7}, + {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6}, + {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6}, + {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, + {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, + {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, + {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, + {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, + {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, + {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, + {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, + {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, + {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, + {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, + {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3} +}; + +static const CBPtab CBP_9 [] = { + {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9}, + {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9}, + {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8}, + {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8}, + {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8}, + {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8}, + {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8}, + {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8}, + {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8}, + {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8}, + {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8}, + {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8}, + {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8}, + {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8}, + {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8}, + {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8} +}; + +static const DCtab DC_lum_5 [] = { + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} +}; + +static const DCtab DC_chrom_5 [] = { + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} +}; + +static const DCtab DC_long [] = { + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} +}; + + +static const DCTtab DCT_16 [] = { + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, + { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, + { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, + { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} +}; + +static const DCTtab DCT_15 [] = { + { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, + { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, + { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, + { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, + { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, + { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, + { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, + { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, + { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, + { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, + { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, + { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} +}; + +static const DCTtab DCT_13 [] = { + { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, + { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, + { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, + { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, + { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, + { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, + { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, + { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, + { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, + { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, + { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, + { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} +}; + +static const DCTtab DCT_B14_10 [] = { + { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, + { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} +}; + +static const DCTtab DCT_B14_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, + { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, + { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, + { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, + { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} +}; + +static const DCTtab DCT_B14AC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} +}; + +static const DCTtab DCT_B14DC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} +}; + +static const DCTtab DCT_B15_10 [] = { + { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, + { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} +}; + +static const DCTtab DCT_B15_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, + { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, + { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, + { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, + { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, + { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, + { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, + { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} +}; + + +static const MBAtab MBA_5 [] = { + {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} +}; + +static const MBAtab MBA_11 [] = { + {32, 11}, {31, 11}, {30, 11}, {29, 11}, + {28, 11}, {27, 11}, {26, 11}, {25, 11}, + {24, 11}, {23, 11}, {22, 11}, {21, 11}, + {20, 10}, {20, 10}, {19, 10}, {19, 10}, + {18, 10}, {18, 10}, {17, 10}, {17, 10}, + {16, 10}, {16, 10}, {15, 10}, {15, 10}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} +}; +#endif//__VLC_H__ diff --git a/branches/pcsx2_0.9.1/IPU/yuv2rgb.c b/branches/pcsx2_0.9.1/IPU/yuv2rgb.c new file mode 100644 index 0000000..17d6c0c --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/yuv2rgb.c @@ -0,0 +1,510 @@ +/* + * yuv2rgb.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +//#include "convert_internal.h" //START +typedef struct { + u8 * rgb_ptr; + int width; + int uv_stride, uv_stride_frame; + int rgb_stride, rgb_stride_frame; + void (* yuv2rgb) (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); +} convert_rgb_t; + +typedef void yuv2rgb_copy (void * id, u8 * const * src, + unsigned int v_offset); + +yuv2rgb_copy * yuv2rgb_init_mmxext (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mmx (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mlib (int bpp, int mode); +//#include "convert_internal.h" //END + +static u32 matrix_coefficients = 6; + +const s32 Inverse_Table_6_9[8][4] = { + {117504, 138453, 13954, 34903}, /*0 no sequence_display_extension */ + {117504, 138453, 13954, 34903}, /*1 ITU-R Rec. 709 (1990) */ + {104597, 132201, 25675, 53279}, /*2 unspecified */ + {104597, 132201, 25675, 53279}, /*3 reserved */ + {104448, 132798, 24759, 53109}, /*4 FCC */ + {104597, 132201, 25675, 53279}, /*5 ITU-R Rec. 624-4 System B, G */ + {104597, 132201, 25675, 53279}, /*6 SMPTE 170M */ + {117579, 136230, 16907, 35559} /*7 SMPTE 240M (1987) */ +}; + +typedef void yuv2rgb_c_internal (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); + +void * table_rV[256]; +void * table_gU[256]; +int table_gV[256]; +void * table_bU[256]; + +#define _RGB(type,i) \ + U = pu[i]; \ + V = pv[i]; \ + r = (type *) table_rV[V]; \ + g = (type *) (((u8 *)table_gU[U]) + table_gV[V]); \ + b = (type *) table_bU[U]; + +#define DST(py,dst,i) \ + Y = py[2*i]; \ + dst[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py[2*i+1]; \ + dst[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DSTRGB(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y]; + +#define DSTBGR(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y]; + +static void yuv2rgb_c_32 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u32 * r, * g, * b; + u32 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u32 *) _dst_1; + dst_2 = (u32 *) _dst_2; + + do { + _RGB (u32, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u32, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u32, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u32, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +/* This is very near from the yuv2rgb_c_32 code */ +static void yuv2rgb_c_24_rgb (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTRGB (py_1, dst_1, 0); + DSTRGB (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTRGB (py_2, dst_2, 1); + DSTRGB (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTRGB (py_1, dst_1, 2); + DSTRGB (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTRGB (py_2, dst_2, 3); + DSTRGB (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* only trivial mods from yuv2rgb_c_24_rgb */ +static void yuv2rgb_c_24_bgr (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTBGR (py_1, dst_1, 0); + DSTBGR (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTBGR (py_2, dst_2, 1); + DSTBGR (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTBGR (py_1, dst_1, 2); + DSTBGR (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTBGR (py_2, dst_2, 3); + DSTBGR (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void yuv2rgb_c_16 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u16 * r, * g, * b; + u16 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u16 *) _dst_1; + dst_2 = (u16 *) _dst_2; + + do { + _RGB (u16, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u16, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u16, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u16, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +static int div_round (int dividend, int divisor) +{ + if (dividend > 0) + return (dividend + (divisor>>1)) / divisor; + else + return -((-dividend + (divisor>>1)) / divisor); +} + +static yuv2rgb_c_internal * yuv2rgb_c_init (int order, int bpp) +{ + int i; + u8 table_Y[1024]; + u32 * table_32 = 0; + u16 * table_16 = 0; + u8 * table_8 = 0; + int entry_size = 0; + void * table_r = 0; + void * table_g = 0; + void * table_b = 0; + yuv2rgb_c_internal * yuv2rgb; + + int crv = Inverse_Table_6_9[matrix_coefficients][0]; + int cbu = Inverse_Table_6_9[matrix_coefficients][1]; + int cgu = -Inverse_Table_6_9[matrix_coefficients][2]; + int cgv = -Inverse_Table_6_9[matrix_coefficients][3]; + + for (i = 0; i < 1024; i++) { + int j; + + j = (76309 * (i - 384 - 16) + 32768) >> 16; + j = (j < 0) ? 0 : ((j > 255) ? 255 : j); + table_Y[i] = j; + } + + switch (bpp) { + case 32: + yuv2rgb = yuv2rgb_c_32; + + table_32 = (u32 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u32)); + + entry_size = sizeof (u32); + table_r = table_32 + 197; + table_b = table_32 + 197 + 685; + table_g = table_32 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) + ((u32 *) table_r)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 16 : 0); + for (i = -132; i < 256+132; i++) + ((u32 *) table_g)[i] = table_Y[i+384] << 8; + for (i = -232; i < 256+232; i++) + ((u32 *) table_b)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 0 : 16); + break; + + case 24: + yuv2rgb = (order == CONVERT_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; + + table_8 = (u8 *) malloc ((256 + 2*232) * sizeof (u8)); + + entry_size = sizeof (u8); + table_r = table_g = table_b = table_8 + 232; + + for (i = -232; i < 256+232; i++) + ((u8 * )table_b)[i] = table_Y[i+384]; + break; + + case 15: + case 16: + yuv2rgb = yuv2rgb_c_16; + + table_16 = (u16 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u16)); + + entry_size = sizeof (u16); + table_r = table_16 + 197; + table_b = table_16 + 197 + 685; + table_g = table_16 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_r)[i] = j; + } + for (i = -132; i < 256+132; i++) { + int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3); + + ((u16 *)table_g)[i] = j << 5; + } + for (i = -232; i < 256+232; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_b)[i] = j; + } + break; + + default: + fprintf (stderr, "%ibpp not supported by yuv2rgb\n", bpp); + exit (1); + } + + for (i = 0; i < 256; i++) { + table_rV[i] = (((u8 *)table_r) + + entry_size * div_round (crv * (i-128), 76309)); + table_gU[i] = (((u8 *)table_g) + + entry_size * div_round (cgu * (i-128), 76309)); + table_gV[i] = entry_size * div_round (cgv * (i-128), 76309); + table_bU[i] = (((u8 *)table_b) + + entry_size * div_round (cbu * (i-128), 76309)); + } + + return yuv2rgb; +} + +static void convert_yuv2rgb_c (void * _id, u8 * Y, u8 * Cr, u8 * Cb, + unsigned int v_offset) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + u8 * dst; + u8 * py; + u8 * pu; + u8 * pv; + int loop; + + dst = id->rgb_ptr + id->rgb_stride * v_offset; + py = Y; pu = Cr; pv = Cb; + + loop = 8; + do { + id->yuv2rgb (py, py + (id->uv_stride << 1), pu, pv, + dst, dst + id->rgb_stride, id->width); + py += id->uv_stride << 2; + pu += id->uv_stride; + pv += id->uv_stride; + dst += 2 * id->rgb_stride; + } while (--loop); +} + +static void convert_start (void * _id, u8 * dest, int flags) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + id->rgb_ptr = dest; + switch (flags) { + case CONVERT_BOTTOM_FIELD: + id->rgb_ptr += id->rgb_stride_frame; + /* break thru */ + case CONVERT_TOP_FIELD: + id->uv_stride = id->uv_stride_frame << 1; + id->rgb_stride = id->rgb_stride_frame << 1; + break; + default: + id->uv_stride = id->uv_stride_frame; + id->rgb_stride = id->rgb_stride_frame; + } +} + +static void convert_internal (int order, int bpp, int width, int height, + u32 accel, void * arg, + convert_init_t * result) +{ + convert_rgb_t * id = (convert_rgb_t *) result->id; + + if (!id) { + result->id_size = sizeof (convert_rgb_t); + } else { + id->width = width; + id->uv_stride_frame = width >> 1; + id->rgb_stride_frame = ((bpp + 7) >> 3) * width; + + result->buf_size[0] = id->rgb_stride_frame * height; + result->buf_size[1] = result->buf_size[2] = 0; + result->start = convert_start; + + result->copy = NULL; +#ifdef ARCH_X86 + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMXEXT)) { + result->copy = yuv2rgb_init_mmxext (order, bpp); + } + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMX)) { + result->copy = yuv2rgb_init_mmx (order, bpp); + } +#endif +#ifdef LIBVO_MLIB + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_MLIB)) { + result->copy = yuv2rgb_init_mlib (order, bpp); + } +#endif + if (result->copy == NULL) { + result->copy = convert_yuv2rgb_c; + id->yuv2rgb = yuv2rgb_c_init (order, bpp); + } + } +} + +void convert_rgb32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 32, width, height, accel, arg, result); +} + +void convert_rgb24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 24, width, height, accel, arg, result); +} + +void convert_rgb16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 16, width, height, accel, arg, result); +} + +void convert_rgb15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 15, width, height, accel, arg, result); +} + +void convert_bgr32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 32, width, height, accel, arg, result); +} + +void convert_bgr24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 24, width, height, accel, arg, result); +} + +void convert_bgr16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 16, width, height, accel, arg, result); +} + +void convert_bgr15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 15, width, height, accel, arg, result); +} + +convert_t* convert_rgb (int order, int bpp) +{ + if (order == CONVERT_RGB || order == CONVERT_BGR) + switch (bpp) { + case 32: return (order == CONVERT_RGB) ? convert_rgb32 : convert_bgr32; + case 24: return (order == CONVERT_RGB) ? convert_rgb24 : convert_bgr24; + case 16: return (order == CONVERT_RGB) ? convert_rgb16 : convert_bgr16; + case 15: return (order == CONVERT_RGB) ? convert_rgb15 : convert_bgr15; + } + return NULL; +} diff --git a/branches/pcsx2_0.9.1/IPU/yuv2rgb.h b/branches/pcsx2_0.9.1/IPU/yuv2rgb.h new file mode 100644 index 0000000..d9d4d9c --- /dev/null +++ b/branches/pcsx2_0.9.1/IPU/yuv2rgb.h @@ -0,0 +1,57 @@ +/* + * yuv2rgb.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef YUV2RGB_H +#define YUV2RGB_H + +#define CONVERT_FRAME 0 +#define CONVERT_TOP_FIELD 1 +#define CONVERT_BOTTOM_FIELD 2 +#define CONVERT_BOTH_FIELDS 3 + +typedef struct convert_init_s { + void * id; + int id_size; + int buf_size[3]; + void (* start) (void * id, u8 * dest, int flags); + void (* copy) (void * id, u8 * Y, u8 * Cr, u8 * Cb, unsigned int v_offset); +} convert_init_t; + +typedef void convert_t (int width, int height, u32 accel, void * arg, + convert_init_t * result); + +convert_t convert_rgb32; +convert_t convert_rgb24; +convert_t convert_rgb16; +convert_t convert_rgb15; +convert_t convert_bgr32; +convert_t convert_bgr24; +convert_t convert_bgr16; +convert_t convert_bgr15; + +#define CONVERT_RGB 0 +#define CONVERT_BGR 1 +convert_t * convert_rgb (int order, int bpp); + +#endif /* YUV2RGB_H */ diff --git a/branches/pcsx2_0.9.1/InterTables.c b/branches/pcsx2_0.9.1/InterTables.c new file mode 100644 index 0000000..5f79905 --- /dev/null +++ b/branches/pcsx2_0.9.1/InterTables.c @@ -0,0 +1,224 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//all tables for R5900 are define here.. + +#include "InterTables.h" + +void (*Int_OpcodePrintTable[64])() = +{ + SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, + ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, + COP0, COP1, COP2, UnknownOpcode, BEQL, BNEL, BLEZL, BGTZL, + DADDI, DADDIU, LDL, LDR, MMI, UnknownOpcode, LQ, SQ, + LB, LH, LWL, LW, LBU, LHU, LWR, LWU, + SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, + UnknownOpcode, LWC1, UnknownOpcode, PREF, UnknownOpcode,UnknownOpcode, LQC2, LD, + UnknownOpcode, SWC1, UnknownOpcode, UnknownOpcode, UnknownOpcode,UnknownOpcode, SQC2, SD +}; + + +void (*Int_SpecialPrintTable[64])() = +{ + SLL, UnknownOpcode, SRL, SRA, SLLV, UnknownOpcode, SRLV, SRAV, + JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, UnknownOpcode, SYNC, + MFHI, MTHI, MFLO, MTLO, DSLLV, UnknownOpcode, DSRLV, DSRAV, + MULT, MULTU, DIV, DIVU, UnknownOpcode,UnknownOpcode,UnknownOpcode,UnknownOpcode, + ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, + MFSA , MTSA , SLT, SLTU, DADD, DADDU, DSUB, DSUBU, + TGE, TGEU, TLT, TLTU, TEQ, UnknownOpcode, TNE, UnknownOpcode, + DSLL, UnknownOpcode, DSRL, DSRA, DSLL32, UnknownOpcode, DSRL32, DSRA32 +}; + +void (*Int_REGIMMPrintTable[32])() = { + BLTZ, BGEZ, BLTZL, BGEZL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + TGEI, TGEIU, TLTI, TLTIU, TEQI, UnknownOpcode, TNEI, UnknownOpcode, + BLTZAL, BGEZAL, BLTZALL, BGEZALL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + MTSAB, MTSAH , UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, +}; + +void (*Int_MMIPrintTable[64])() = +{ + MADD, MADDU, MMI_Unknown, MMI_Unknown, PLZCW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI0, MMI2, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MFHI1, MTHI1, MFLO1, MTLO1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MULT1, MULTU1, DIV1, DIVU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MADD1, MADDU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI1 , MMI3, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHL, PMTHL, MMI_Unknown, MMI_Unknown, PSLLH, MMI_Unknown, PSRLH, PSRAH, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, PSLLW, MMI_Unknown, PSRLW, PSRAW, +}; + +void (*Int_MMI0PrintTable[32])() = +{ + PADDW, PSUBW, PCGTW, PMAXW, + PADDH, PSUBH, PCGTH, PMAXH, + PADDB, PSUBB, PCGTB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDSW, PSUBSW, PEXTLW, PPACW, + PADDSH, PSUBSH, PEXTLH, PPACH, + PADDSB, PSUBSB, PEXTLB, PPACB, + MMI_Unknown, MMI_Unknown, PEXT5, PPAC5, +}; + +void (*Int_MMI1PrintTable[32])() = +{ + MMI_Unknown, PABSW, PCEQW, PMINW, + PADSBH, PABSH, PCEQH, PMINH, + MMI_Unknown, MMI_Unknown, PCEQB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDUW, PSUBUW, PEXTUW, MMI_Unknown, + PADDUH, PSUBUH, PEXTUH, MMI_Unknown, + PADDUB, PSUBUB, PEXTUB, QFSRV, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, +}; + + +void (*Int_MMI2PrintTable[32])() = +{ + PMADDW, MMI_Unknown, PSLLVW, PSRLVW, + PMSUBW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHI, PMFLO, PINTH, MMI_Unknown, + PMULTW, PDIVW, PCPYLD, MMI_Unknown, + PMADDH, PHMADH, PAND, PXOR, + PMSUBH, PHMSBH, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXEH, PREVH, + PMULTH, PDIVBW, PEXEW, PROT3W, +}; + +void (*Int_MMI3PrintTable[32])() = +{ + PMADDUW, MMI_Unknown, MMI_Unknown, PSRAVW, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMTHI, PMTLO, PINTEH, MMI_Unknown, + PMULTUW, PDIVUW, PCPYUD, MMI_Unknown, + MMI_Unknown, MMI_Unknown, POR, PNOR, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXCH, PCPYH, + MMI_Unknown, MMI_Unknown, PEXCW, MMI_Unknown, +}; + +void (*Int_COP0PrintTable[32])() = +{ + MFC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, MTC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_BC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Func, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0BC0PrintTable[32])() = +{ + BC0F, BC0T, BC0FL, BC0TL, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0C0PrintTable[64])() = { + COP0_Unknown, TLBR, TLBWI, COP0_Unknown, COP0_Unknown, COP0_Unknown, TLBWR, COP0_Unknown, + TLBP, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + ERET, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + EI, DI, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown +}; + +void (*Int_COP1PrintTable[32])() = { + MFC1, COP1_Unknown, CFC1, COP1_Unknown, MTC1, COP1_Unknown, CTC1, COP1_Unknown, + COP1_BC1, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_S, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_W, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1BC1PrintTable[32])() = { + BC1F, BC1T, BC1FL, BC1TL, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1SPrintTable[64])() = { +ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,RSQRT_S, COP1_Unknown, +ADDA_S, SUBA_S, MULA_S, COP1_Unknown,MADD_S, MSUB_S, MADDA_S, MSUBA_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,CVT_W, COP1_Unknown,COP1_Unknown,COP1_Unknown, +MAX_S, MIN_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +C_F, COP1_Unknown,C_EQ, COP1_Unknown,C_LT, COP1_Unknown,C_LE, COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + +void (*Int_COP1WPrintTable[64])() = { +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +CVT_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + + +void (*Int_COP2PrintTable[32])() = { + COP2_Unknown, QMFC2, CFC2, COP2_Unknown, COP2_Unknown, QMTC2, CTC2, COP2_Unknown, + COP2_BC2, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, +}; + +void (*Int_COP2BC2PrintTable[32])() = { + BC2F, BC2T, BC2FL, BC2TL, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, +}; + +void (*Int_COP2SPECIAL1PrintTable[64])() = +{ + VADDx, VADDy, VADDz, VADDw, VSUBx, VSUBy, VSUBz, VSUBw, + VMADDx, VMADDy, VMADDz, VMADDw, VMSUBx, VMSUBy, VMSUBz, VMSUBw, + VMAXx, VMAXy, VMAXz, VMAXw, VMINIx, VMINIy, VMINIz, VMINIw, + VMULx, VMULy, VMULz, VMULw, VMULq, VMAXi, VMULi, VMINIi, + VADDq, VMADDq, VADDi, VMADDi, VSUBq, VMSUBq, VSUBi, VMSUBi, + VADD, VMADD, VMUL, VMAX, VSUB, VMSUB, VOPMSUB, VMINI, + VIADD, VISUB, VIADDI, COP2_Unknown,VIAND, VIOR, COP2_Unknown, COP2_Unknown, + VCALLMS, VCALLMSR, COP2_Unknown,COP2_Unknown,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2, +}; + +void (*Int_COP2SPECIAL2PrintTable[128])() = +{ + VADDAx ,VADDAy ,VADDAz ,VADDAw ,VSUBAx ,VSUBAy ,VSUBAz ,VSUBAw, + VMADDAx ,VMADDAy ,VMADDAz ,VMADDAw ,VMSUBAx ,VMSUBAy ,VMSUBAz ,VMSUBAw, + VITOF0 ,VITOF4 ,VITOF12 ,VITOF15 ,VFTOI0 ,VFTOI4 ,VFTOI12 ,VFTOI15, + VMULAx ,VMULAy ,VMULAz ,VMULAw ,VMULAq ,VABS ,VMULAi ,VCLIPw, + VADDAq ,VMADDAq ,VADDAi ,VMADDAi ,VSUBAq ,VMSUBAq ,VSUBAi ,VMSUBAi, + VADDA ,VMADDA ,VMULA ,COP2_Unknown,VSUBA ,VMSUBA ,VOPMULA ,VNOP, + VMOVE ,VMR32 ,COP2_Unknown,COP2_Unknown,VLQI ,VSQI ,VLQD ,VSQD, + VDIV ,VSQRT ,VRSQRT ,VWAITQ ,VMTIR ,VMFIR ,VILWR ,VISWR, + VRNEXT ,VRGET ,VRINIT ,VRXOR ,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, +}; diff --git a/branches/pcsx2_0.9.1/InterTables.h b/branches/pcsx2_0.9.1/InterTables.h new file mode 100644 index 0000000..5788826 --- /dev/null +++ b/branches/pcsx2_0.9.1/InterTables.h @@ -0,0 +1,491 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef INTERTABLES_H +#define INTERTABLES_H + +extern void (*Int_OpcodePrintTable[64])(); +extern void (*Int_SpecialPrintTable[64])(); +extern void (*Int_REGIMMPrintTable[32])(); +extern void (*Int_MMIPrintTable[64])(); +extern void (*Int_MMI0PrintTable[32])(); +extern void (*Int_MMI1PrintTable[32])(); +extern void (*Int_MMI2PrintTable[32])(); +extern void (*Int_MMI3PrintTable[32])(); +extern void (*Int_COP0PrintTable[32])(); +extern void (*Int_COP0BC0PrintTable[32])(); +extern void (*Int_COP0C0PrintTable[64])(); +extern void (*Int_COP1PrintTable[32])(); +extern void (*Int_COP1BC1PrintTable[32])(); +extern void (*Int_COP1SPrintTable[64])(); +extern void (*Int_COP1WPrintTable[64])(); +extern void (*Int_COP2PrintTable[32])(); +extern void (*Int_COP2BC2PrintTable[32])(); +extern void (*Int_COP2SPECIAL1PrintTable[64])(); +extern void (*Int_COP2SPECIAL2PrintTable[128])(); + +void SPECIAL(); +void REGIMM(); +void UnknownOpcode(); +void COP0(); +void COP1(); +void COP2(); +void MMI_Unknown(); +void MMI(); +void MMI0(); +void MMI1(); +void MMI2(); +void MMI3(); +void COP0_Unknown(); +void COP0_BC0(); +void COP0_Func(); +void COP1_BC1(); +void COP1_S(); +void COP1_W(); +void COP1_Unknown(); +void COP2_BC2(); +void COP2_SPECIAL(); +void COP2_Unknown(); +void COP2_SPECIAL2(); + +// **********************Standard Opcodes************************** +void J(); +void JAL(); +void BEQ(); +void BNE(); +void BLEZ(); +void BGTZ(); +void ADDI(); +void ADDIU(); +void SLTI(); +void SLTIU(); +void ANDI(); +void ORI(); +void XORI(); +void LUI(); +void BEQL(); +void BNEL(); +void BLEZL(); +void BGTZL(); +void DADDI(); +void DADDIU(); +void LDL(); +void LDR(); +void LB(); +void LH(); +void LWL(); +void LW(); +void LBU(); +void LHU(); +void LWR(); +void LWU(); +void SB(); +void SH(); +void SWL(); +void SW(); +void SDL(); +void SDR(); +void SWR(); +void CACHE(); +void LWC1(); +void PREF(); +void LQC2(); +void LD(); +void SQC2(); +void SD(); +void LQ(); +void SQ(); +void SWC1(); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void SLL(); +void SRL(); +void SRA(); +void SLLV(); +void SRLV(); +void SRAV(); +void JR(); +void JALR(); +void SYSCALL(); +void BREAK(); +void SYNC(); +void MFHI(); +void MTHI(); +void MFLO(); +void MTLO(); +void DSLLV(); +void DSRLV(); +void DSRAV(); +void MULT(); +void MULTU(); +void DIV(); +void DIVU(); +void ADD(); +void ADDU(); +void SUB(); +void SUBU(); +void AND(); +void OR(); +void XOR(); +void NOR(); +void SLT(); +void SLTU(); +void DADD(); +void DADDU(); +void DSUB(); +void DSUBU(); +void TGE(); +void TGEU(); +void TLT(); +void TLTU(); +void TEQ(); +void TNE(); +void DSLL(); +void DSRL(); +void DSRA(); +void DSLL32(); +void DSRL32(); +void DSRA32(); +void MOVZ(); +void MOVN(); +void MFSA(); +void MTSA(); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void BLTZ(); +void BGEZ(); +void BLTZL(); +void BGEZL(); +void TGEI(); +void TGEIU(); +void TLTI(); +void TLTIU(); +void TEQI(); +void TNEI(); +void BLTZAL(); +void BGEZAL(); +void BLTZALL(); +void BGEZALL(); +void MTSAB(); +void MTSAH(); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void MADD(); +void MADDU(); +void PLZCW(); +void MADD1(); +void MADDU1(); +void MFHI1(); +void MTHI1(); +void MFLO1(); +void MTLO1(); +void MULT1(); +void MULTU1(); +void DIV1(); +void DIVU1(); +void PMFHL(); +void PMTHL(); +void PSLLH(); +void PSRLH(); +void PSRAH(); +void PSLLW(); +void PSRLW(); +void PSRAW(); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void PADDW(); +void PSUBW(); +void PCGTW(); +void PMAXW(); +void PADDH(); +void PSUBH(); +void PCGTH(); +void PMAXH(); +void PADDB(); +void PSUBB(); +void PCGTB(); +void PADDSW(); +void PSUBSW(); +void PEXTLW(); +void PPACW(); +void PADDSH(); +void PSUBSH(); +void PEXTLH(); +void PPACH(); +void PADDSB(); +void PSUBSB(); +void PEXTLB(); +void PPACB(); +void PEXT5(); +void PPAC5(); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void PABSW(); +void PCEQW(); +void PMINW(); +void PADSBH(); +void PABSH(); +void PCEQH(); +void PMINH(); +void PCEQB(); +void PADDUW(); +void PSUBUW(); +void PEXTUW(); +void PADDUH(); +void PSUBUH(); +void PEXTUH(); +void PADDUB(); +void PSUBUB(); +void PEXTUB(); +void QFSRV(); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void PMADDW(); +void PSLLVW(); +void PSRLVW(); +void PMSUBW(); +void PMFHI(); +void PMFLO(); +void PINTH(); +void PMULTW(); +void PDIVW(); +void PCPYLD(); +void PMADDH(); +void PHMADH(); +void PAND(); +void PXOR(); +void PMSUBH(); +void PHMSBH(); +void PEXEH(); +void PREVH(); +void PMULTH(); +void PDIVBW(); +void PEXEW(); +void PROT3W(); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void PMADDUW(); +void PSRAVW(); +void PMTHI(); +void PMTLO(); +void PINTEH(); +void PMULTUW(); +void PDIVUW(); +void PCPYUD(); +void POR(); +void PNOR(); +void PEXCH(); +void PCPYH(); +void PEXCW(); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void MFC0(); +void MTC0(); +void BC0F(); +void BC0T(); +void BC0FL(); +void BC0TL(); +void TLBR(); +void TLBWI(); +void TLBWR(); +void TLBP(); +void ERET(); +void DI(); +void EI(); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void MFC1(); +void CFC1(); +void MTC1(); +void CTC1(); +void BC1F(); +void BC1T(); +void BC1FL(); +void BC1TL(); +void ADD_S(); +void SUB_S(); +void MUL_S(); +void DIV_S(); +void SQRT_S(); +void ABS_S(); +void MOV_S(); +void NEG_S(); +void RSQRT_S(); +void ADDA_S(); +void SUBA_S(); +void MULA_S(); +void MADD_S(); +void MSUB_S(); +void MADDA_S(); +void MSUBA_S(); +void CVT_W(); +void MAX_S(); +void MIN_S(); +void C_F(); +void C_EQ(); +void C_LT(); +void C_LE(); + void CVT_S(); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void QMFC2(); +void CFC2(); +void QMTC2(); +void CTC2(); +void BC2F(); +void BC2T(); +void BC2FL(); +void BC2TL(); +//*****************SPECIAL 1 VUO TABLE******************************* +void VADDx(); +void VADDy(); +void VADDz(); +void VADDw(); +void VSUBx(); +void VSUBy(); +void VSUBz(); +void VSUBw(); +void VMADDx(); +void VMADDy(); +void VMADDz(); +void VMADDw(); +void VMSUBx(); +void VMSUBy(); +void VMSUBz(); +void VMSUBw(); +void VMAXx(); +void VMAXy(); +void VMAXz(); +void VMAXw(); +void VMINIx(); +void VMINIy(); +void VMINIz(); +void VMINIw(); +void VMULx(); +void VMULy(); +void VMULz(); +void VMULw(); +void VMULq(); +void VMAXi(); +void VMULi(); +void VMINIi(); +void VADDq(); +void VMADDq(); +void VADDi(); +void VMADDi(); +void VSUBq(); +void VMSUBq(); +void VSUBi(); +void VMSUBi(); +void VADD(); +void VMADD(); +void VMUL(); +void VMAX(); +void VSUB(); +void VMSUB(); +void VOPMSUB(); +void VMINI(); +void VIADD(); +void VISUB(); +void VIADDI(); +void VIAND(); +void VIOR(); +void VCALLMS(); +void VCALLMSR(); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void VADDAx(); +void VADDAy(); +void VADDAz(); +void VADDAw(); +void VSUBAx(); +void VSUBAy(); +void VSUBAz(); +void VSUBAw(); +void VMADDAx(); +void VMADDAy(); +void VMADDAz(); +void VMADDAw(); +void VMSUBAx(); +void VMSUBAy(); +void VMSUBAz(); +void VMSUBAw(); +void VITOF0(); +void VITOF4(); +void VITOF12(); +void VITOF15(); +void VFTOI0(); +void VFTOI4(); +void VFTOI12(); +void VFTOI15(); +void VMULAx(); +void VMULAy(); +void VMULAz(); +void VMULAw(); +void VMULAq(); +void VABS(); +void VMULAi(); +void VCLIPw(); +void VADDAq(); +void VMADDAq(); +void VADDAi(); +void VMADDAi(); +void VSUBAq(); +void VMSUBAq(); +void VSUBAi(); +void VMSUBAi(); +void VADDA(); +void VMADDA(); +void VMULA(); +void VSUBA(); +void VMSUBA(); +void VOPMULA(); +void VNOP(); +void VMOVE(); +void VMR32(); +void VLQI(); +void VSQI(); +void VLQD(); +void VSQD(); +void VDIV(); +void VSQRT(); +void VRSQRT(); +void VWAITQ(); +void VMTIR(); +void VMFIR(); +void VILWR(); +void VISWR(); +void VRNEXT(); +void VRGET(); +void VRINIT(); +void VRXOR(); +//************************************END OF SPECIAL2 ************ +#endif diff --git a/branches/pcsx2_0.9.1/Interpreter.c b/branches/pcsx2_0.9.1/Interpreter.c new file mode 100644 index 0000000..10d4aa8 --- /dev/null +++ b/branches/pcsx2_0.9.1/Interpreter.c @@ -0,0 +1,1072 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "ix86/ix86.h" + +#include + +extern u32 maxrecmem; + +char *bios[256]={ +//0x00 + "RFU000_FullReset", "ResetEE", "SetGsCrt", "RFU003", + "Exit", "RFU005", "LoadExecPS2", "ExecPS2", + "RFU008", "RFU009", "AddSbusIntcHandler", "RemoveSbusIntcHandler", + "Interrupt2Iop", "SetVTLBRefillHandler", "SetVCommonHandler", "SetVInterruptHandler", +//0x10 + "AddIntcHandler", "RemoveIntcHandler", "AddDmacHandler", "RemoveDmacHandler", + "_EnableIntc", "_DisableIntc", "_EnableDmac", "_DisableDmac", + "_SetAlarm", "_ReleaseAlarm", "_iEnableIntc", "_iDisableIntc", + "_iEnableDmac", "_iDisableDmac", "_iSetAlarm", "_iReleaseAlarm", +//0x20 + "CreateThread", "DeleteThread", "StartThread", "ExitThread", + "ExitDeleteThread", "TerminateThread", "iTerminateThread", "DisableDispatchThread", + "EnableDispatchThread", "ChangeThreadPriority", "iChangeThreadPriority", "RotateThreadReadyQueue", + "iRotateThreadReadyQueue", "ReleaseWaitThread", "iReleaseWaitThread", "GetThreadId", +//0x30 + "ReferThreadStatus","iReferThreadStatus", "SleepThread", "WakeupThread", + "_iWakeupThread", "CancelWakeupThread", "iCancelWakeupThread", "SuspendThread", + "iSuspendThread", "ResumeThread", "iResumeThread", "JoinThread", + "RFU060", "RFU061", "EndOfHeap", "RFU063", +//0x40 + "CreateSema", "DeleteSema", "SignalSema", "iSignalSema", + "WaitSema", "PollSema", "iPollSema", "ReferSemaStatus", + "iReferSemaStatus", "RFU073", "SetOsdConfigParam", "GetOsdConfigParam", + "GetGsHParam", "GetGsVParam", "SetGsHParam", "SetGsVParam", +//0x50 + "RFU080_CreateEventFlag", "RFU081_DeleteEventFlag", + "RFU082_SetEventFlag", "RFU083_iSetEventFlag", + "RFU084_ClearEventFlag", "RFU085_iClearEventFlag", + "RFU086_WaitEventFlag", "RFU087_PollEventFlag", + "RFU088_iPollEventFlag", "RFU089_ReferEventFlagStatus", + "RFU090_iReferEventFlagStatus", "RFU091_GetEntryAddress", + "EnableIntcHandler_iEnableIntcHandler", + "DisableIntcHandler_iDisableIntcHandler", + "EnableDmacHandler_iEnableDmacHandler", + "DisableDmacHandler_iDisableDmacHandler", +//0x60 + "KSeg0", "EnableCache", "DisableCache", "GetCop0", + "FlushCache", "RFU101", "CpuConfig", "iGetCop0", + "iFlushCache", "RFU105", "iCpuConfig", "sceSifStopDma", + "SetCPUTimerHandler", "SetCPUTimer", "SetOsdConfigParam2", "SetOsdConfigParam2", +//0x70 + "GsGetIMR_iGsGetIMR", "GsGetIMR_iGsPutIMR", "SetPgifHandler", "SetVSyncFlag", + "RFU116", "print", "sceSifDmaStat_isceSifDmaStat", "sceSifSetDma_isceSifSetDma", + "sceSifSetDChain_isceSifSetDChain", "sceSifSetReg", "sceSifGetReg", "ExecOSD", + "Deci2Call", "PSMode", "MachineType", "GetMemorySize", +}; + +extern void (*LT_OpcodePrintTable[64])(); +int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef CPU_LOG +#define debugI() \ + if (Log) { CPU_LOG("%s\n", disR5900F(cpuRegs.code, pc)); } \ + if (cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1]) SysPrintf("R0 is not zero!!!!\n"); +#else +#define debugI() +#endif +#define addcycles() + /*EEsCycle += cpuRegs.cycle - EEoCycle; \ + EEoCycle = cpuRegs.cycle;*/ + +extern void ExecuteIOP(); +u32 IOPtimer = 0; + +void execI() { + u32 pc = cpuRegs.pc; + + + //////////////////////////////////////////////////////// + /*if(IOPtimer >= 8) { + ExecuteIOP(); + IOPtimer = 0; + } + + IOPtimer++; + */ + /////////////////////////////////////////////////////// + + cpuRegs.cycle++; + //cpuRegs.CP0.n.Count++; /*count every cycles.*/ + + if (memRead32(cpuRegs.pc, &cpuRegs.code) == -1) return; + + debugI(); + cpuRegs.pc+= 4; + Int_OpcodePrintTable[cpuRegs.code >> 26](); +} + +__inline void doBranch(u32 tar) { + branch2 = cpuRegs.branch = 1; + branchPC = tar; + execI(); + cpuRegs.branch = 0; + cpuRegs.pc = branchPC; + + addcycles(); + cpuBranchTest(); +} + +void intDoBranch(u32 target) { + doBranch(target); +} + +void intSetBranch() { + branch2 = 1; +} + +void SPECIAL() {Int_SpecialPrintTable[_Funct_]();} +void REGIMM() {Int_REGIMMPrintTable[_Rt_](); } + + +void UnknownOpcode() { +#ifdef CPU_LOG + CPU_LOG("%8.8lx: Unknown opcode called\n", cpuRegs.pc); +#endif +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void ADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed!!!! +void ADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed !!! +void DADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void DADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void ANDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & (s64)_ImmU_; } // Rt = Rs And Im +void ORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | (s64)_ImmU_; } // Rt = Rs Or Im +void XORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ (s64)_ImmU_; } // Rt = Rs Xor Im +void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_); } // Rt = Rs < Im (signed) +void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_); } // Rt = Rs < Im (unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void ADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt (Exception on Integer Overflow) +void ADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt +void DADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void DADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void SUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs - Rt (Exception on Integer Overflow) +void SUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0]; } // Rd = Rs - Rt +void DSUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0];} +void DSUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0]; } +void AND() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs And Rt +void OR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Or Rt +void XOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Xor Rt +void NOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] =~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); }// Rd = Rs Nor Rt +void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]; } // Rd = Rs < Rt (signed) +void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs < Rt (unsigned) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void J() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +void JAL() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + _SetLink(31); doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void JR() { +#ifdef EMU_LOG + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; + u32 pc = cpuRegs.pc; + int rs = _Rs_; +#endif + doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); + if (rs == 31) JumpCheckSymRet(pc); +#endif +} + +void JALR() { + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; +#ifdef EMU_LOG + u32 pc = cpuRegs.pc; +#endif + + if (_Rd_) { _SetLink(_Rd_); } + doBranch(temp); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void DIV() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +void MULT() { //different in ps2... + s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +void MULTU() { //different in ps2.. + u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void LUI() { + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void MFHI() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; } // Rd = Hi +void MFLO() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void MTHI() { cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Hi = Rs +void MTLO() { cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Lo = Rs + + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void SLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << _Sa_); } // Rd = Rt << sa +void DSLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << _Sa_); } +void DSLL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (_Sa_+32));} +void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) +void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_); } +void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32));} +void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) +void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_); } +void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32));} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void SLLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt << rs +void SRAV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (arithmetic) +void SRLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (logical) +void DSLLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRAV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) \ + if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \ + else {addcycles(); cpuBranchTest();} + + +void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else addcycles(); cpuBranchTest(); + +#define RepZBranchLinki32(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else addcycles(); cpuBranchTest(); + +void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + +#define RepZBranchLinki32Likely(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + +#define RepBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; addcycles(); cpuBranchTest(); } + + +void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt +void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt +void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0 +void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0 +void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0 +void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0 +void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link +void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void LB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead8RS(addr, &dummy); + } +} + +void LBU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead8RU(addr, &dummy); + } +} + +void LH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead16RS(addr, &dummy); + } +} + +void LHU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead16RU(addr, &dummy); + } +} + +void LW() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RS(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead32RS(addr, &dummy); + } +} + +void LWU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RU(addr, &cpuRegs.GPR.r[_Rt_].SD[0]); + } else { + u64 dummy; + memRead32RU(addr, &dummy); + } +} + +u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void LWL() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWL_MASK[shift]) | + (mem << LWL_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + */ +} + +u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 }; +u32 LWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void LWR() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWR_MASK[shift]) | + (mem >> LWR_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + */ +} + +void LD() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead64(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead64(addr, &dummy); + } +} + +u64 LDL_MASK[8] = { 0x00ffffffffffffff, 0x0000ffffffffffff, 0x000000ffffffffff, 0x00000000ffffffff, + 0x0000000000ffffff, 0x000000000000ffff, 0x00000000000000ff, 0x0000000000000000 }; +u32 LDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void LDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDL_MASK[shift]) | + (mem << LDL_SHIFT[shift]); +} + +u64 LDR_MASK[8] = { 0x0000000000000000, 0xff00000000000000, 0xffff000000000000, 0xffffff0000000000, + 0xffffffff00000000, 0xffffffffff000000, 0xffffffffffff0000, 0xffffffffffffff00 }; +u32 LDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void LDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDR_MASK[shift]) | + (mem >> LDR_SHIFT[shift]); +} + +void LQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + + if (_Rt_) { + memRead128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +void SB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); +} + +void SH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); +} + +void SW(){ + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); +} + +u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000 }; +u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void SWL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] >> SWL_SHIFT[shift]) | + ( mem & SWL_MASK[shift]) ); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + */ +} + +u32 SWR_MASK[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; +u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void SWR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] << SWR_SHIFT[shift]) | + ( mem & SWR_MASK[shift]) ); + + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + */ +} + +void SD() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite64(addr,cpuRegs.GPR.r[_Rt_].UD[0]); +} + +u64 SDL_MASK[8] = { 0xffffffffffffff00, 0xffffffffffff0000, 0xffffffffff000000, 0xffffffff00000000, + 0xffffff0000000000, 0xffff000000000000, 0xff00000000000000, 0x0000000000000000 }; +u32 SDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void SDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] >> SDL_SHIFT[shift]) | + ( mem & SDL_MASK[shift]) ); +} + +u64 SDR_MASK[8] = { 0x0000000000000000, 0x00000000000000ff, 0x000000000000ffff, 0x0000000000ffffff, + 0x00000000ffffffff, 0x000000ffffffffff, 0x0000ffffffffffff, 0x00ffffffffffffff }; +u32 SDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void SDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] << SDR_SHIFT[shift]) | + ( mem & SDR_MASK[shift]) ); +} + +void SQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + memWrite128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); +} + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +void MOVZ() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} +void MOVN() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] != 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +#include "Sifcmd.h" +/* +int __Deci2Call(int call, u32 *addr); +*/ +u32 *deci2addr = NULL; +u32 deci2handler; +char deci2buffer[256]; + +/* + * int Deci2Call(int, u_int *); + */ + +int __Deci2Call(int call, u32 *addr) { + if (call > 0x10) { + return -1; + } + + switch (call) { + case 1: // open + + deci2addr = (u32*)PSM(addr[1]); +#ifdef BIOS_LOG + BIOS_LOG("deci2open: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + deci2handler = addr[2]; + + return 1; + + case 2: // close + return 1; + + case 3: // reqsend + +#ifdef BIOS_LOG + BIOS_LOG("deci2reqsend: %x,%x,%x,%x: deci2addr: %x,%x,%x,buf=%x %x,%x,len=%x,%x\n", + addr[3], addr[2], addr[1], addr[0], + deci2addr[7], deci2addr[6], deci2addr[5], deci2addr[4], + deci2addr[3], deci2addr[2], deci2addr[1], deci2addr[0]); +#endif +// cpuRegs.pc = deci2handler; +// SysPrintf("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc)); + if (deci2addr == NULL) return 1; + if (deci2addr[1]>0xc){ + u8* pdeciaddr = dmaGetAddr(deci2addr[4]+0xc); + if( pdeciaddr == NULL ) pdeciaddr = PSM(deci2addr[4]+0xc); + else pdeciaddr += (deci2addr[4]+0xc)%16; + memcpy(deci2buffer, pdeciaddr, deci2addr[1]-0xc); + deci2buffer[deci2addr[1]-0xc>=255?255:deci2addr[1]-0xc]='\0'; + SysPrintf(deci2buffer); + } + deci2addr[3] = 0; + return 1; + + case 4: // poll +#ifdef BIOS_LOG + BIOS_LOG("deci2poll: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + return 1; + + case 5: // exrecv + return 1; + + case 6: // exsend + return 1; + + case 0x10://kputs + SysPrintf("%s", PSM(*addr)); + return 1; + } + + return 0; +} + + +void SYSCALL() { +#ifdef BIOS_LOG + u8 call; + + if (cpuRegs.GPR.n.v1.SL[0] < 0) + call = (u8)(-cpuRegs.GPR.n.v1.SL[0]); + else call = cpuRegs.GPR.n.v1.UC[0]; + BIOS_LOG("Bios call: %s (%x)\n", bios[call], call); + if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) { + SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0]))); + } else + //if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0])); + if (call == 0x77) { + struct t_sif_dma_transfer *dmat; +// struct t_sif_cmd_header *hdr; +// struct t_sif_rpc_bind *bind; +// struct t_rpc_server_data *server; + int n_transfer; + u32 addr; +// int sid; + + n_transfer = cpuRegs.GPR.n.a1.UL[0] - 1; + if (n_transfer >= 0) { + addr = cpuRegs.GPR.n.a0.UL[0] + n_transfer * sizeof(struct t_sif_dma_transfer); + dmat = (struct t_sif_dma_transfer*)PSM(addr); + +#ifdef BIOS_LOG + BIOS_LOG("bios_%s: n_transfer=%d, size=%x, attr=%x, dest=%x, src=%x\n", + bios[cpuRegs.GPR.n.v1.UC[0]], n_transfer, + dmat->size, dmat->attr, + dmat->dest, dmat->src); +#endif + } +//Log=1; + } +#endif +// if (cpuRegs.GPR.n.v1.UD[0] == 0x77) Log=1; + cpuRegs.pc -= 4; + cpuException(0x20, cpuRegs.branch); +} + +void BREAK(void) { + cpuRegs.pc -= 4; + cpuException(0x24, cpuRegs.branch); +} + +void MFSA( void ) { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = (s64)cpuRegs.sa; +} + +void MTSA( void ) { + cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; +} + +void SYNC( void ) +{ +} + +void PREF( void ) +{ +} + + + +/********************************************************* +* Register trap * +* Format: OP rs, rt * +*********************************************************/ + +void TGE() { + if (cpuRegs.GPR.r[_Rs_].SD[0]>= cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEU() { + if (cpuRegs.GPR.r[_Rs_].UD[0]>= cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLT() { + if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQ() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNE() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Trap with immediate operand * +* Format: OP rs, rt * +*********************************************************/ + +void TGEI() { + + if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] >= _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTI() { + if(cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNEI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Sa intructions * +* Format: OP rs, rt * +*********************************************************/ + +void MTSAB() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3; +} + +void MTSAH() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4; +} + + + +/////////////////////////////////////////// + +int intInit() { + //detect cpu for use the optimaze asm code + return 0; +} + +void intReset() { + cpuRegs.branch = 0; + branch2 = 0; +} + +void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + + +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); +extern u32 vudump; + +void intExecuteVU0Block() { +int i; + +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) + break; + +#ifdef _DEBUG + prevbranch = VU0.branch; +#endif + vu0Exec(&VU0); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + } + + if( i < 0 && (VU0.branch || VU0.ebit) ) { + // execute one more + vu0Exec(&VU0); + } +} + +void intExecuteVU1Block() { + + int i; +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) + break; + +#ifdef _DEBUG + prevbranch = VU1.branch; +#endif + vu1Exec(&VU1); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + } + + if( i < 0 && (VU1.branch || VU1.ebit) ) { + // execute one more + vu1Exec(&VU1); + } +} + + +void intEnableVU0micro(int enable) { +} + +void intEnableVU1micro(int enable) { +} + +void intStep() { + execI(); +} + +void intClear(u32 Addr, u32 Size) { +} + +void intVU0Clear(u32 Addr, u32 Size) { +} + +void intVU1Clear(u32 Addr, u32 Size) { +} + +void intShutdown() { +} + +R5900cpu intCpu = { + intInit, + intReset, + intStep, + intExecute, + intExecuteBlock, + intExecuteVU0Block, + intExecuteVU1Block, + intEnableVU0micro, + intEnableVU1micro, + intClear, + intVU0Clear, + intVU1Clear, + intShutdown +}; + diff --git a/branches/pcsx2_0.9.1/Linux/.pixmaps/pcsxAbout.xpm b/branches/pcsx2_0.9.1/Linux/.pixmaps/pcsxAbout.xpm new file mode 100644 index 0000000..2ebc445 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/.pixmaps/pcsxAbout.xpm @@ -0,0 +1,334 @@ +/* XPM */ +static char *pcsxAbout[] = { +/* columns rows colors chars-per-pixel */ +"314 176 152 2", +" c #252d42", +". c #282e45", +"X c #282f48", +"o c #273046", +"O c #283046", +"+ c #2a334b", +"@ c #2d3650", +"# c #2e3853", +"$ c #303651", +"% c #303955", +"& c #333d5b", +"* c #383f57", +"= c #383e5d", +"- c #35405e", +"; c #39415d", +": c #364161", +"> c #384465", +", c #3a4668", +"< c #3e4866", +"1 c #3c496c", +"2 c #3e4b70", +"3 c #40475b", +"4 c #41485d", +"5 c #404767", +"6 c #424a63", +"7 c #434c6c", +"8 c #484f61", +"9 c #464e70", +"0 c #44506f", +"q c #4c5263", +"w c #465071", +"e c #495273", +"r c #4d5679", +"t c #4e5974", +"y c #4e587b", +"u c #515665", +"i c #535866", +"p c #545968", +"a c #595d69", +"s c #50577b", +"d c #505a75", +"f c #51597d", +"g c #5c606a", +"h c #55617f", +"j c #5a637b", +"k c #64666d", +"l c #65686e", +"z c #666870", +"x c #6b6d71", +"c c #6e7073", +"v c #767676", +"b c #545d81", +"n c #566085", +"m c #586185", +"M c #5b648a", +"N c #5e6883", +"B c #5e688d", +"V c #666d84", +"C c #606a8b", +"Z c #686f86", +"A c #626b93", +"S c #656f98", +"D c #687085", +"F c #6a738c", +"G c #667097", +"H c #667098", +"J c #6d7691", +"K c #6b749d", +"L c #6e7893", +"P c #72788c", +"I c #757d93", +"U c #6d76a0", +"Y c #6e78a1", +"T c #717ba4", +"R c #747ea8", +"E c #7c8397", +"W c #79829a", +"Q c #7680ab", +"! c #7a84ae", +"~ c #7c85b1", +"^ c #7e88b3", +"/ c #808080", +"( c #80838f", +") c #888888", +"_ c #808799", +"` c #82899d", +"' c gray57", +"] c gray60", +"[ c #858da3", +"{ c #858eba", +"} c #8d93a5", +"| c #8f95a8", +" . c #8690bc", +".. c #8891bd", +"X. c #9096a9", +"o. c #999ead", +"O. c #9aa0af", +"+. c #9ca2b4", +"@. c #a2a2a2", +"#. c #aaaaaa", +"$. c #a5a9b6", +"%. c #a7acba", +"&. c #a8adbc", +"*. c #aab0bf", +"=. c #bababa", +"-. c #8e96c3", +";. c #8e98c4", +":. c #9099c6", +">. c #959dca", +",. c #96a0cc", +"<. c #98a0cd", +"1. c #9ca5d1", +"2. c #a4add9", +"3. c #aab0c0", +"4. c #b3b6c2", +"5. c #b4b8c4", +"6. c #b6bbc8", +"7. c #adb5e1", +"8. c #b0b7e3", +"9. c #b0b8e3", +"0. c #bec2cb", +"q. c #bfc7ef", +"w. c #bfc7f0", +"e. c #c2c2c2", +"r. c #c0c3cd", +"t. c gray80", +"y. c #c2c6d1", +"u. c #ccced6", +"i. c #cdd0d7", +"p. c #ced1d9", +"a. c #d0d2d7", +"s. c #d4d5d9", +"d. c #dddddd", +"f. c #c0c7f0", +"g. c #c3cbf2", +"h. c #c8cef4", +"j. c #cad0f5", +"k. c #d9dbe1", +"l. c #d2d8f6", +"z. c #dbdff8", +"x. c #dce0f8", +"c. c gray90", +"v. c #e5e7eb", +"b. c #e6e8ec", +"n. c #eeeeee", +"m. c #e1e5f9", +"M. c #ebeefb", +"N. c #eff1fc", +"B. c #f2f3f5", +"V. c #f0f1fc", +"C. c #f7f8fd", +"Z. c #fefefe", +/* pixels */ +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 2 , , , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , > , > > , > , , : , , : , : , : , : > > > > : > > , : : : : > : : > : : : : : : : - : : - : - - : - - - - - - & - - & - - & & & & & & : & & & & & & & & & & & & & # # # # # & & # & # & # # & # # # # # # & # # & # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ X @ @ + @ @ + @ + @ + @ + + @ + + @ + + @ + + + + + + + + + + + + + + o + + o + + + o + X o X X + o o O O O O O X X O . . . . . . . . . o o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , , , 2 1 , 1 , , , , , 1 , , , , , , , , , , , , > , , , > , > : , , : : , , : , : , : > > , : : > > : : : , : : : : > : : : : : : : : : - : - - - : - - - - - - & - - & - - & : & : & : & & & & & & & & & # & & # & & & & & : & # # & # & # & & # # & & # & # # # # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + + @ + + + + + + + + + + + + + + + o X + + o o + o + o + X X + + + o X o X X O O O O o o O X O . . . o o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 , 2 , 1 1 1 , 1 1 1 1 , , 1 , 1 1 , 1 1 , 1 , 1 , , , , , , , , , , , > , , > , , > , , , : , : : , : , > : , > > : : > > : > : : > : : : : : > - : : - : - - : : : - : - - - - - & - & & - & - & & & & & & & & & & & & & & & & & # & # : # # # & & & & & # & # # & & # & # # # # # # # # & # # % # @ # # @ # # @ % @ @ @ @ @ @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + @ + + + + + + + + + + + + + + + + o + + + + X + o + + o + o o @ + X + X o o o X + X O O O O X X . . . o o . . o . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 2 , 2 2 1 1 1 1 , , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , , > , , > , > , > , > : , , > , , , : , : > > : > > > : > : > : : > : : : : : : : : - : : - : : - - - - - - - - - - - - - - - - & : & & : & & & & & & & & & # & & & & & & & # & : # & # # & # # & # # & # # # & & & # # & # # # # # # # # # # @ # @ @ # @ % @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ + + @ + + @ + + + @ + + + + + + + X + + + + + X + o + + o + o o X X X o o + o X O O O O X O O O O . . . o . o . . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 2 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , > , : , : : : , : , > : , , : , : > > , : > : : , : , : : : : > : : : : : : : : - - - - - - - - - : & & - - - & & & : & & & & & & & & & & & & & & & & : # # & & # # & # & # & # & & # # & # # # # & # # & # # # # @ # % % # # # # @ # @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ @ + @ @ + @ + + @ + + @ + + + + + + + + + + + + + + + + + + o o @ X o + o + o + o + + X X O O + O O O . . O . . . o o o o o . o o . . . . ", +"9 2 2 2 w 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 , 1 , 1 , 1 , , , 1 1 1 , 1 , , , , , , , , , , , , > , > > , , , > , , , : , : , , : : , : > > : : : , : : : : : : > : : : : : : - : : : - : : - - - - - - - & - : - & - & - & & & & & & & & & & & & & & & # & : # # # : # & & # & # & # & # # & # & # & # & # # # # # # # # % # @ # # # @ # # @ # @ @ @ @ @ # @ @ @ @ X @ @ @ + + @ @ @ + + + + + @ + @ + + + @ + + + + + + + X + X + o + o X + + o o + o o o + o o o o o o O O O O O O O . . O . o . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , , 1 1 , 1 , 1 , 1 , , 1 , , , , , , , , , : , > , , , , > , > > , , , : , , : , : : > , : , : > > : , : : : > : : : : : : : : : : : : - : - : : : - - : - - - : & & - & - - - & : & & : & & & & & & & & & & & # & : & & : # : & & # & # & # & # & # # # # # # # # # # # # # # # # # # # @ @ # @ @ # @ # @ @ @ # @ @ @ @ @ X @ @ @ + + + @ + @ @ + @ + + + + + + @ + + + + + + + + + o + o + X + o + + + X o + + o o + o o + o O O O O O O . . O . o . . o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , , , , > , > , > , , > : , , > > , , : , > > > : > : > : : > : > : : > : : : : : : : : - : : - : - - - - - - - - - & : - - & - & & & : & & & & & : & & & & & & & & & & # # & # # & # & & # & # # & & # & # & # & # # & & # # # # & # # # # # # # # @ # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + X + o + o @ + o o + o o + o X + O O O O O O O O o o . . o o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 2 , , , , , 1 , , 1 , , , , , , , , , , , , , , > , , > , , , , , , : , , : , , : > > , > > > > , : : , : : , : > : : : : : : > : : : - : - - : - - - - - - - - - : & & & & : & & : & & & & & & & & & & & & & # & # & # & # & & & # & # & # & # & # # & & # % # # & # # % @ & & @ & @ @ @ # @ @ # # @ @ @ @ @ @ @ @ # @ @ @ @ @ + @ + + @ @ + @ + @ @ + + @ + @ + + + + + + + + + + + o + + o + o + + + O + + O + + + X X o o o O O O O O X X O O O O O O . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 2 2 , 2 , , , , , , 1 , , , , , , , , , , , , , , , > , : , : , : , : , , : , > > : > : : > : : , : , : : : : > : : : : : : : : : : - : - : - - : - - - - - : & & : : & & : & & : & & & & & & & & & & & & & & & & & & & & # & # # & # & # & # & # # # % % # # # # # % @ @ @ @ @ % @ # # @ # @ # @ # # @ # @ X @ # X X # @ @ @ @ @ @ @ + + + @ + + + + + + + + + + + + + + + o + + + + o + + X + O O + + o O o X X X + o O X X X O O O O X . o O O O X o O . . o o o o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 1 1 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 , , 2 , 2 , 1 1 1 , 2 , , 1 , , , , , , , , , , , , , > , : : , , , : , , : : , > > : , : : : , , : : : , : > : , : , : : : : : - : : - : - : - - - - - - - & & : & : & & & & & & & : & & & & & & & & & & & & # & # & & & # & & # # & # # & & # # & # & # & # # # & & @ @ @ % @ @ % # @ @ @ # @ # @ @ @ # @ # X # # @ @ X @ @ @ @ @ + @ + @ + + @ + @ + + + + + + + + + + + + + + + X + X + + + o + o X o + X X X + o + + o O + O O O O O O X o o O O o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 2 , 1 , , , , , , , , , , , 1 , , , , , , , , , > , , > , , , , : , , , : , , > , : , : , , : : : : , : : : : : : : : : : : : : : - : : - : - : - - - - - - : : : & & : & : & : & & & & & & # & & & & & & & & & & & & # & & # & & & # & & # # & & # # # # # & # # # @ @ & @ @ % # @ # # # @ @ # @ @ @ @ @ @ # # # @ @ @ @ @ + @ + + @ + + @ + @ + @ + + + @ + + + @ + + + + + + + + + + + + O + + + O + + X + o X X O O o o O O O O O O X X O X O O O o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 , , 1 , 2 1 , , , , , 1 , , , , , > , , , , , , > , : , , , , : , , : : , > > , : , : : > , : , : : : : : : : , : : : : : : : : : : : : - - - - - - - - & : & : & - & & & : & : & & & & & & & & & & & & & & & & # # & # & # & # & & & & # # # & # % & # & # # # # & # # & & @ % @ @ % @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + X + + + o + + X + + O + X + X + + O + O O O O O O O O O O O O . X O O o . o O . . o . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 2 1 , 1 , 1 1 , , , 1 1 , , , , , , , , , , , , , > , , , , , : , : , : , , , : > > : , : , > > : > > : , : , : : : : : : : : : : : : : : : - : : - : - - - - - & : & & & : : & & & & & & & & : & & & & & & # & # & & & & & # & & & & # # # # & & # & # # # # # # # # # # # @ @ % @ @ @ @ @ & @ @ # # @ @ @ @ @ @ @ @ @ X @ X @ @ + + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + + + + + O + + o X + + o O O O O O + O O O O O O O o O . O O . . O . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , : , : , , : , , : , , : , , > > , : > , : : : > > : , : , : : : : : : : : : : : : : : : - - : : - - - - - - : : & : : : & & : & & & : & & & # & & & & & & # & & & & & # & # & # # & & # & # & # # & # & # # & # # # # # # & @ @ @ % # # # # # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ + + @ + + @ + + @ @ + + + + + + + + + + + o + + + o + + o o + + o O + + O + X O + O O O O O O O O O X O o O O O X o . . . . . o . . . o ", +"e 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , , , , 1 , , 1 , , , , , , , , > , , , , , , , : , , , : , : , > > : > , : : , , : > > : : : : : , > : : : : : : : : : : : : : - - - - - - - - : & & - & & : & & & : & & & & & & & & & & & & & & & & # & & & & & # & & # & # & # & # # # & % & # # & # # # # # @ & % @ # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ + + @ + + + @ + + @ + + + + + + + + + + o + + X + + + + X X + X X + O O O + + O O O O O O O . X O . . . . . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , 1 , 1 1 1 1 , , 1 > , 1 > , , 1 , , , , , , , , , , , , , , , , : : , , : > > > > > , > > > : : , : > : : > : > : > : : : : : : : - : - - - - - - - - - & - - : & & & & : - & & : & & & & : & & & & & & # & & & # & & & # & # & # & # & # & & # # # & # % % % % % % % % @ # # # # # @ @ @ # # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X X @ + + @ + + @ + + + + + + + + + + + O + + + o + o + + O + O O O + O + X O O + O + X O X o O . . . . o o . . . . o . O O O O ", +"2 2 2 2 2 2 2 e 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 1 1 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 1 1 1 , , 1 1 , , 1 , , , , , , , , , : , , , , : , , : , , , , : , > > > > : : > : , : > : : : , : : > : : : : : : : : - : : : - : : : - : - - - - - - & : : : & & - - & & : & & & & & & & & & & & & & & & & # & & & # % & # & # & # # # & # & # # % % % @ % @ % % @ % @ # # @ % # @ @ # @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X @ X @ X @ @ + @ + + + + + + + + + + + + + + + + + O X + + o + X o O O O + O O O O O O X X O O O O O O . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 1 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , , , 1 , , , 1 , , , , , , , , , , : , : : , : , : , , : , : > > > > > > > > > > : > : : : : : : : : : > : : : : : : - : : - - - : - - - - - & : & & & : : & & - - & & & & - & & # : & & & & & & & & & # # & & & & # & # & # # & & # % # # # @ % % % @ % % @ % # # # @ % # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ + @ + + + + + + + + + + + + O + + + + O + O O + + O + o + O + O + O o O + O O O O O O O X . . . o . . O O . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , , 2 , , 1 , , 1 , 1 , , > 1 , , , , , , , , , , , , , , , , , , > , : , , , : > > > > > > > : : : , : > , : > > : > : : : : : : : : : : : - : : - - - - : - - - - : & : & & & - & & & & & & & & & & & # : # & # & & & & & & # # & % & & # # & % # & # # & % & % % % @ % % % # # # # # @ # @ # # @ @ # @ # @ @ @ @ @ @ @ @ X @ @ @ X @ @ @ X @ + @ + + + + + @ @ + + + X + + + + + + + O + + + + + o + + o + X + O O O O O X O O O O O X X . . . . o . X O o . . o O . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , , 2 , 1 , 1 , , 1 , 1 , 1 , , , , , , , , , > , , , : , : , , : , > , : , > , , , > > > > > > > > : > > : : > : > : > : : : : : : > - : > - : : - - : - - - - - - - & - & & & : & & & & - & & & & & & & & & # & & & & & # & & & # # & & & & # # # % % & % # % # # % # @ % % # # % % @ % @ # # # $ # @ # @ @ @ @ @ @ @ @ @ @ # @ @ + @ @ @ X @ X @ @ + @ @ + + + + + + + + + + + + + + X + + + O O + O O + O O + o O + O + O O O O + X O O O O O . o . . . . o . O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , 1 , , , , , , , , , , , , , , > , , , , > , > > > , : > > > > : > > > > > : > > : : : : > : > : : > : - - : - : - - : : - - - - - - - - - - : : & & : & - - & - & - & & & & & & : & & & # & & # & & & & # # # # & & & & % % % % % % # % % @ % % # % @ # # @ % # # @ # @ # @ @ # @ @ @ @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + + @ @ + + + + + + + + + + + + + + + + + + + + + + O + o + + O O O O + O O O O X O o O O . o O . o . . o O O O O O . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , , , , : , , , , : , > > > > > > > > > > : > > > > : > : , : : : : > : : : : - > > - - - : - - : : - - - - - & : & : : & & : : & & & & & & & & & & & # & & # & & & & & & # & & & & # & # & # % % % % # # % & # % % % # # # # @ % # # # # # @ @ # # @ # @ @ @ @ @ # X @ @ @ @ @ @ @ X + @ X @ + @ @ + + + + + + + + + + + + + o + O + + O + O O + O O + + o o O + O O O + + O O O O O O X O . o . o o . . . . O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , : , , , : , : , : , , > > > > > > > > > > : : > > > : > : : > : : : : > : : > - - - - : - : : - - : - - - - : & : & & & : & & & - & & & : & & & & & & & & & & # & & # & # & & # & # & & # & % % % % & # % # % # % % % % # # % @ % @ $ # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ X @ + @ @ X @ + @ + + @ + @ + + + @ + + + + + + + + + + O + + + O + O + o X + O X + O O O O O O O O O O O . O o o . o o . . O O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , , 1 1 , 1 > 1 1 > 1 , , , , > , , , , , : , , : , , , , , > , > > > : , > > > > > > > > : > : , : , > : : : > : : : - : : : - : - : - : : - - - - - & : & : & & : & & & & & & : & & & & & : & & & : & & : & & & & # # & & # & # & # # & % % % % % % % # # # % % # # # % # @ % @ @ % @ # @ # @ # @ # @ @ @ @ # @ @ @ @ @ @ + + @ + + + @ + + + + + + @ + + @ + + + + X + + X + + O + + X X X + O + O O + + o o O O O O O O O O O X . . . o . . o . o . . . o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 1 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 1 > 1 > , , 1 , , , , , , , , , , , , , , > : , > > > > > , : , > : : > : > : > : : : : : > : : : : : : > : : : : : : - : - : - - - - - : & : & & : & & & : : & & & & & & & & # & & & & # & # # # & # & & # # & # & # & & % % % % % # % % % % # # # % # # @ @ % # # # # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + + @ @ + + @ @ + @ + + @ @ + + + + + + + + + + + + + X + + + + + + + X + O X O X X + O O O + O X O O O O O O . . o . o . O o O . o O O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 > 1 1 > , 1 , , , , , > , , , , , , > , : , > , > , > , , : , : > > : > > : > : , : , : : : > : : : : : : - : : : - - - - - - - - - - - : : & : : & : & & & & - & : & & & & & & & & : # & & & & # & & & & & & & & # & # # % % % % % % % # # # % % # # # # % @ # @ # # @ # # # @ @ # @ @ @ @ @ @ # # @ @ @ @ @ + + @ @ X + @ + + @ X + + + + + + + + + + + + + O + + + X X + X X O + O + O O X X O O O O X O O O O X o O . . o . . o . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , 1 1 , 1 1 > 1 , , , , , , , , : , , , : , : , , , > > > > > > > > > > > > > > > > : , : : : : , : : : > : : : : : : : - : : : : - - : - - - - & & : & & & : & : & & & & & & & & & & : # # # # & & # & & & # & # & # # # & # & # & % % % % % % % % # % % % % # # # % # # # @ # @ # @ @ @ @ @ @ @ # X @ # X @ @ X + @ @ @ + @ @ @ + @ + + + @ + + + + + + + + + + + + + + + X + O O + + O X X + + O + X O O + O X + O O O O o O . O . . . . o . o . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , 1 , , , 1 > , , , , , , > , , , , , , , , , , , > : > > > > : , > , : : > , : > > : : : , : : : : : : : : : : : : : - - : - : - - - - - - - : : & : : & - & & & - & : & & & & & & & & & & & & : & & & & # & & # & & & # % % % % % % % % % % % % % % # # # % % # % # % # # # # # @ # @ @ @ @ @ @ @ @ @ @ X # @ @ @ + @ + @ + + + @ + + + + @ + + + + + + + + + + O + + + O + + + + O + O + O O O O O + O + X O X O O O O O O O o o o o o . . . . . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , , , , , , , , , 1 , , , , , , , , , , , : , : : , , , , , > , > > , > : : , , : : , : > : : , : : : : , : : : : : : : : : : : - - - : - - - - - - & & : & & - : & : & & & & & & & & & & & & # & & & # # # & # & & % % & # % & % % % & % % % % % % # % # # # # # # # # # @ @ @ % @ # @ @ @ @ # @ @ @ @ @ X @ @ @ @ @ @ @ @ + @ @ X + @ + @ @ + + + + + + + + + + + + + + + O O + + + O O + O + O + + + O X O O O X O O O O O O O . O o o o . . . o . . . o o o o O ", +"2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , , , 1 , 1 , , , , , , , , , , , , , , , > , , , > , : , , , > > , > : , , > > > , : : : > > : : : : : : : : : : : : : : : : - : : : - - - - - - - - : & : & : & & & & & & & & & & & & & & & & & & & & # & & & & # & % & % & % & % & % % % % % % % % % # % # # % # # % @ # # @ # @ @ @ # # # @ @ @ @ @ @ @ @ @ @ @ # + + @ + @ @ + @ @ @ + + + @ + + + + + + + + + + + + + + + + + O + O + O O X + O O O O + O O O O O O O O O O O o O . . . o . . o o o . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , > , , > , , , > : , , > > , > > > > : > > > : > : , > : , : , : , : : : : : : , : : : - : - - : : - - : - - - - & : & : & - & : : & & : & & & & & & & & & & & & : # & & # : # # & % & # & # % % % & % % % % % % % # # % # # # # $ # # # @ % % # @ @ @ @ @ @ @ @ @ @ @ @ X # @ X @ @ @ + @ + @ + + + @ + + + + @ + @ + + + + + + + + O O + + + O + + O + + + O O + O + O O + O O O O O O O O O O . . O . . . o . . . . o o O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , > , , , > > > > > , > , > > , : , : , : > : : > > > > > : : > : : > : : : : : : : : : : : : : & : & & : - - : - & : & : # : : : # : : & & & : & @ - - - # - - - @ - - @ # - # # - - # # - # # # # % % - # # % % # # # # # # # # # # % # # @ % # # @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + + @ + + + + @ + @ + + + + + + + + + + + + + X X + + + + X + o + O + O O O + X O X o O + O O O O O O . . . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , , 1 1 1 1 , , , , 1 , , 1 , , , , , , , , , , , , > 1 > 1 > 1 > > , > > , , : , > > : , , : : > : > : > : > > : : : : : : : : & : : : : : : : : : : - : & : : & : & : : : # # : : # # : : # - - # - @ - @ - - @ @ - - # - # # % # - # # % - - % % % # % # % % # & # # # # # # # # # # # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ + @ @ # + @ @ + @ # @ @ + @ + + @ + @ + + + + + + + + + + + + X + + + o X + + O O + O O o o + o o o O O O O + O X X . . . o . . o . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 2 2 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , > , , , 1 > > 1 > > > > , : : , > > , : , : , , > > > > > : : : : > > : > : : : : : : - & : : : : : - & : & : & : & & : : # : : : # : : & : & & # - - - - - # - - - - - # - - # # - - # # - # - # % % % % % % % & # # # % # & # % @ % % # # # # @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ + + + + + + + @ + + + + + + + + + + + o + + + + o X + o + O + X o + o + + + O O O O O O O X o X O . o o . O X O . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , 1 1 , , 1 1 , , 1 , , , , , , , , , > > > > > > > , > , , , : > , : > : , : : : > > > : > > : : : : : : : > : : : : : : : : : : & : : & : & : : & : & : : # & : : & & # : # & - - # # - # - # @ # - @ # - # - - # - # # - # % # % % % % % % % # # # & # # # # @ % @ % # @ @ # # @ @ @ # @ @ @ @ @ @ @ @ + @ + + # @ @ + @ + @ + @ + @ + @ + + + + + + + + + + + + + + o + + X + + X + + X + + O + o o O O + O O O O O X o O . . o . X . X . o o . o O O O O ", +"2 2 2 2 2 2 0 2 2 2 2 2 1 2 2 1 2 1 2 2 2 1 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 1 , , , , 1 , , 1 1 , , , , 1 , , , , , , > > 1 > > > > , , > , : > > , , : , > , : > , > > > : : > : > : : > : : : : : : : : : : & : & : : : & & : - - & : & & : & : & & : : # : # : # @ - - - - # - - - @ - # - # - # # % # - # # # % & % % % % % % % # % # # # % # % % # # # # # # @ # @ # @ # @ @ @ @ @ @ @ @ @ @ @ # + # + + @ + + # @ + + + + + + + + + + + + + + + + + + + + + o + X + + + o o X O O O X O O O O O + X O O . X X . . O o . . . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , 1 , , , , , , , , , > , , , , , , , > , 1 : > > > , > , : : , : , > > : : > : : > > : > : : > : : : : : : : : : = : : : : & : & : : : & : : & : & & : & & : : # : & : : : - - @ - - - # @ - - # - - # # # - % - # # - - % % % % % % % % % % % % # # # % # # # # # @ # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ + @ + # # + @ + @ + + + + @ + # @ + + + + + + + + + o + + o X + + + + X X + o + + X + + O + O O O O O O O X . O o O O . o o . O . o o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 1 , 1 1 1 , , , 1 , , 1 , , , , , , , , > > , > > > 1 > , , : , , , > > , : : , : > , > > > > : : > : > : : > : > : : : : : : : : : : & & : : : - & - : & : & : : : & : # : & & & & # : - - @ - # - - - # - # @ # - # - # - # # # # - % % % % % % % % % # # # % % # # # # @ % @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ @ + @ + @ + + @ + + + + + + + + + + + + + + + + + X + + + + + X X X X + o X + O + + O + O O O O O O O O . O O o o . O . X o o . . o . . O O O O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , , , , 1 , , 1 , 1 , , , , , , , , , , , > , , , , , 1 > > > , : , > > : , > , : > > > > : : : : > > > : > : > > : : : : : : : : : : : : : : : : : & : & : & : & & : & & & & # : : # : & & & # - - - - # # - - # - - - # - # - # # - - # # # % & % % % % # % % % % % % # # # # # @ % # # % @ # @ # @ @ @ @ + @ @ @ @ @ @ + @ + @ @ @ @ + @ # + + + # + @ + @ + + + + + + + + + + + + + X o + + + X + X + + o + X O O O O + O O O O O O O O O . . . . O O . . . . . O O ", +"2 2 2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 1 1 2 1 2 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 1 , , , 1 1 , , , 1 , , , , , , > , > , , > > , , , : , : , : : , : , : > : > , > > > : > : : : : : : : : : : : : : : - : - : - : - - - - - & : : & : & : : : : : : & : # & # : # - - - # - - # - - # - - # - # # & & # # & # & % % & # # & # # # # # - # # % # + - - + - + + - # @ @ @ # @ # @ @ + # # @ + @ + @ + + @ @ + @ + + + # + @ + + + + + + + + + + + o + + o + o + + + O O + O + O X X O X O O O + X O O O O O O X . . . . . o . . . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 1 2 1 2 1 1 1 2 1 2 1 1 1 2 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , , 1 , , , , , 1 , , , , , , , , , , , , , > > 1 > : , , , , , , , : , , , > , > : > : : > > : > : : > : > : > : : : : : - - : - : - : - : - - : : & : & & & : # # : # : # : : : # - - # - - # - # @ # - # # - # # & # & & & # & # % & # & # % # % # # # # # # # # @ + + - O - + $ # # @ # @ @ @ @ # + @ + @ # @ @ + + # + @ + @ @ @ + + + @ + + + @ + + + + + + + + + + + + + + o + + + O + O + + + O + O X O X X O + O O O X O O . . . o o o . . . . . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 2 , 1 1 1 , , 1 1 1 1 , , 1 , 1 , , , 1 , , , , , , , , , , , > , , , > , > > , , : : , , : , : , : : > , : > : > : > > > : > > > : : > : : : : : : : : : : : - : - - : - & : & : & & : : # : : : : & : & : & & # - - # # # - - - # # - - # # - & # & # # & # & & & # # # & % % # # + - # # # # - + + + - O o + @ @ @ @ @ @ @ @ # # @ @ @ @ + @ # + @ @ @ + @ + + + @ + + @ + @ + + + + + + + + + + + + + + + o X + + X O + O O X + O + o o X X O O O O O X O O . . . o . . . . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , 1 , , , , , , , > , > , , , , > , , > , , : , , , : , , : , : , : > > : : : > : : > : : : : > : - : : : - : - : - : - - - - & : & : : & : : : # # : & & # : # : - - # - - - - # - - - - # - - # # & & # & # & # # % & # # % % # - # # # # # % # - @ - @ O - - + # @ # @ @ @ @ @ + @ @ # + # # @ + @ @ + + @ + @ # + + @ + + + + @ + + + + + + + + + o + + o + + + O X + O O + + O O O O X + X X O O O O + X O X O O o . . . o o o . o . o . o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 1 1 , 1 1 , 1 1 , , , 1 1 1 , 1 , , 1 1 , 1 , , , , , , , , , , > , > , , , > > > , : > , : , , : : , : , : : > : : , , : > > : : : : > : : : : : : : : : : - : - - - : - - - - - : & : & # : : : : # & : : : & # - # - - - @ @ - @ + - - # - # - & & & # # & # & # & # # % % % & - + # # - @ + - + - + @ + + - - # # # @ @ # @ @ # @ + + + @ @ @ @ @ + o @ @ @ @ + # + + + + + @ + + + + + + + + + + + + + + + o + + X O + O + O O O O O + + O + + + + O O + O O O O X X . . O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 2 2 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , , , 1 1 , , , , , , , , , , , , > , , , , , , , : , : , : , : : , : , > : : > > : : > > : : : : : : : : : : = : : - : : - - - - - - & & : : & : : # : : : & : & & : : - # - # - - - - - - - @ - # - # & # # & & # & # # # & & % # # # # + - + + + - @ @ @ + - - + + + @ # + # @ @ @ @ # + # @ # # + + + + # @ @ o + o + @ + + @ + + + + + + + + + + + + + o + o + + + O + X + O O O O + O + + + + + + + $ $ $ + $ + + + O O O O . . . . . . . o ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , , > , > , , > , > , , : : , , : , : , : , , : > : > : : : : > > : : : : : : : : : - : : : : : : - - : - - - - - - : & & : # : : # & # : # & & & & - - # - # - - # @ - - @ # - # - # & & # # & % & & # % % & % # % + - - + @ # + @ + - @ @ - + + - # @ # @ # @ @ @ + # + # @ + + @ @ + @ @ + @ @ + + + + + + + + + + @ + + + + + + + + o + + + o o + O O + O + O O + O + + @ + % % $ * # * * @ $ + + + O O O O o o o o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 2 1 1 1 1 1 1 1 1 1 2 1 , 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , 1 , , , , , , , , , > , , , , , , > , > > , : , , , > > , : , : , : : , : , : , , : : : : : : : > : : : : : : : : - : - : - - : : - - - : & & : : & : & : : : : # : & : # & # - - - @ - - # - - @ - - # - - & # & & & # & # # & % # # # # & - @ + - + - - O - @ + - + - + + @ # # # + @ @ @ @ @ # # + # # @ + # @ @ + + @ @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + O + + O + O + + + + + + % # * ; ; > : ; ; = * $ $ + + + O . . . . . o . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 2 2 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , 1 1 , 1 , , 1 1 , , , , , , , , , > , , , > , : , , , : , , : : , : , : , > : > : : , : > > : : : : : > : : : : : : : - : - : - - - - - - & - & : & : & & & : # : & & # : : & & & & & # & & & - 8 4 4 4 8 < 4 , , , < 4 4 4 8 4 4 4 4 4 4 4 4 4 4 4 4 8 4 4 - $ @ $ - + + - o # @ @ @ @ @ + @ + # @ + @ + # + @ @ + @ @ + @ + + + @ + + + @ + @ + + + + + + + + + + O + + + O + + X + + o + + + + + # = ; 5 7 2 e e e 1 7 < = # @ + + + O X . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 , 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , , , , , , , , , , , , , , > , > > , , : : , , : , , : , : , : > , : , > : : > : > : : : : : : : : : : - : : : : - : - - : - - : - : & : & & : & & & : & : & & & & & & & & & & & & 4 v v v v v v v v c v v v v v v v v v v v v v v v v v v v v v v k ; - + + - - $ # # @ # # @ # # @ @ @ @ @ @ + @ + @ @ + + @ @ + @ + @ + + @ + + + + + + O + + + + + + + O O + + O + X + o + O + + @ * * > 7 e s n M M m n f e 7 > * # + + O . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 > 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , , > , , , , , , : : , , : > , : > , : : , : > , : > : , : : : : : : : - : : : : : - : - : - - : - : & : : & : : & : & & & & : : & & & & & & & & & & # 4 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k $ @ O - $ @ # @ @ @ @ @ @ @ # @ # @ # # @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + + O + + X + o + o + + $ # * > w f M S U T R T K S m f 9 : * % + + O X . . . X . . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 , 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 , 1 , 1 , 1 1 , 1 , , 1 , , , , , , > > , , , : , , , : : , , , , : > > , : , : : , > : > : : : : : : : , : : : : : > - : - - - : - : - : - - : & : & & : & & & : & : & & & & & & & & & & & & & & & 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x ; - + O # @ @ # @ @ @ # @ + @ + + + # + @ + @ @ + @ + @ + + @ + + @ + + + + + + + + O + + X + O + + + + + + + X + + + @ $ ; > 0 f C K ! ..;.;.;. .~ Y B f 7 : * $ + O . . . . . X X X X X X X X X . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 > 1 1 , , 1 > 1 > 1 , , , , , , , , , , , , , > > , , , : , , , : , > , > : , > > : > : : > : : > > : : : : , : : : - - : : : - : - - : - : & : & - : & : & & & : & & & & : & & & : & & & & & & # & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v l - # @ @ @ @ @ # @ @ @ @ @ + @ # + @ + @ @ + @ + @ + @ @ + + + + @ + @ + + + + + + + + + + O + + + O O X + + o X + + $ # ; 7 y A R { <.2.7.9.7.2.>.{ R A r 7 = $ $ + X O . O X + X X $ + + + X X X X ", +"2 2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , 1 1 1 1 > 1 1 , , , , 1 , 1 > , , , , , , , > > , , : , , , > : , : , : , , > , : , , : > : > : > , : : > : : : > : > : : : : > : : : - : - > - - : - : & : - : : & & : & : & & : : # & : # & & & & & & & & & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k # $ # @ # @ @ @ @ @ @ @ @ @ @ @ @ # + @ @ + @ + @ + @ + @ + + + + @ + + + @ + + + + + + + + O + + + O + + O + + + % = , e M K ..1.9.w.j.j.j.w.7.1.{ Y M w 5 * $ + + O O . + + + $ $ $ $ $ * $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 > 1 1 , , 1 , , , 1 , , 1 , , , , , , , , , , > , , , , > : , , , , : > : > > : , , : : , , , : : , : : > , : : : : : : : - : : - : : : - : : - - : - - - & : & : : - & & & & & : : & & & # & & & & & & # 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 $ # @ @ @ # # # @ @ @ @ @ @ + @ + + # @ @ + @ @ + + + + + @ + @ + + + + + + + + + + + + + + + O + + + O + + + + # ; 7 f S ~ <.9.g.l.x.x.x.l.h.9.>.! G r 6 & $ + + O O + + + % * * = = 3 * * = $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , , 1 , 1 , 1 > , 1 > , , , , , , , , , , , , > > > , , , : , > > , , > > > : : , : > : : : , : : > : > : : : > : : : : : : : : : - - - - : - & : : & : & : & & & : & & : & & : # : # : & & & & & & & 0 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v c # # @ # # @ + @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + @ + @ @ + + + + + + @ + + + + + + + + O + O + + O + o + o + + @ % : 7 n U ..2.w.l.m.M.N.M.m.l.w.2.{ Y b 9 = $ + + + + + $ % = > 6 7 9 9 9 7 5 5 = ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , 1 , , , , , 1 , , , , , > , > > , , , , , > , > , : , , : , : , : , : : > > : , : : > : : : : : : : : : : : - : - - - : : : & : & & & & : & & : - & : & # : : # : & : & & & & & & & & , D c v c v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 # @ @ # # @ # @ @ @ @ + @ @ @ + @ + @ @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + O + + + + + * > e m T :.8.h.z.M.C.C.C.M.z.j.7.;.T M w ; $ $ X + $ $ * ; 7 w r b m M m b s 9 5 = % $ X $ . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > > > , , > > > , : : , : , : , : : , : > , : : : : > : > : > : : : : : - : - : > - & & : : : : : : & : & : : # - & & - & & : : # : & & & & & & & # : h l l l l l l l l l l l l l l l l l l l l l l v v v v v v v v v v v v v v v c @ # @ @ @ @ # + @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + @ + + + + @ + + + + + + # + @ @ + $ + + + + O + X + X + + $ & ; e C R :.9.h.m.V.Z.Z.Z.V.x.j.7.:.T M e 5 $ $ + + $ * : 7 r b S K T T T K A m s 7 3 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 2 1 2 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 , , , , 1 , , , , 1 , 1 , , , , 1 , , , , , , , > , > > , > , , > , , > , > , , : , : , : > , : > : : > : > : > : > : : : : > : : > - : - > - : : & : & : : & : & : & - - : & : & & & & # & : & & & & & & & & & & - & & # & # - # - - # & - % # - # # # & % % # g v v v v v v v v v v v v v v - - # @ @ @ @ @ @ @ @ @ @ @ + @ @ + + @ + @ + + @ X + @ + + + + @ + + + @ % # # # @ % $ % + + + + X + X + + + & > e M R ;.7.h.m.M.C.C.C.M.x.h.7.;.T M w ; * $ + $ * ; 7 s A T R ..-.-.-.{ ! K B s 7 3 $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , , , , , , , , , , , , , > > , > , > , > > , > > , > , : > , : , : , > : , : > : > > : : : : : : : : : : : - - : - : - - & : : : & : : & & - - - - & & - & & & : : : # # & & & & & # & & & & & & & & # & # - # # - # # # # # # & % % # # # @ g v v v v v v v v v v v v v i o @ @ # @ # @ @ + @ @ @ @ + @ + @ @ + @ + @ + @ @ + @ + @ + @ + @ @ # % # % % = # * * * @ # % $ + + + + + @ * ; w b K { 2.q.l.m.M.V.M.m.l.w.2.{ K b 7 ; $ $ $ $ = 6 r C R { >.2.2.8.7.2.>.{ Y C s 4 * * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , > , , > , , , : , : > , : : , : : > : : , : : > : : : > > : : > : : : : : - : : : > - - > : : & : : : & : : - : & : # - & & : # : & : : & & & & & & & & & # & # & & # & # - # # - # # % % & # # # & # & # # # - v v v v v v v v v v v v v c @ @ @ + # # @ # + + # @ @ @ @ @ + @ @ @ + @ + + X @ + + @ X + + @ $ % & = = : < < > : ; = # @ $ + + + + + $ # = 7 b S ~ <.9.h.l.z.x.x.l.h.9.>.~ G s 7 * % $ $ % 3 e m K { 1.8.f.h.j.h.f.8.1.{ U b r ; * . . . ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , , 1 1 1 , , , , , , , , , , , > , , , : , , > : > , > , > , > , : , > > > , : : , > > > > : : : > : : > : : : : : - : - - - - - : & : & : : & : & & : : : & & & & : & # & : # & & & & & & # & & & & & & & & # # - - # # - # - & % & % & # % # # # # p v v v v v v v v v v v v v - @ @ @ # + # + # # # @ + @ + @ + + @ @ @ + + + @ + @ + + @ @ @ # * = : 5 7 e e e e e 7 5 > = $ $ $ + + + + $ & , e b Y { 1.9.w.g.j.j.w.9.1.{ K M e : % % $ % = 7 s G R <.8.h.l.z.m.z.l.h.8.>.R A s 5 * + . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 1 2 1 1 2 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , , 1 , 1 1 , , , , 1 1 , , , , , , , > , , > , > > , > , , , , > > > > > , , > , > : > > > : : > > : : : > : : : > : : : : : - > - > - - : - : - & : : & & : & : & # : : : & : & : # : & & & & & & & & & # & & & & & & & # - # # # # - % # & # % # # & % - # # ; v v v v v v v v v v v v v < @ @ @ @ @ # # # # + + @ @ + @ @ + @ + @ + @ + + + @ + @ + $ % % : 5 7 r b b M M M m f r 7 < = # $ + + + + $ % = 7 y A T { >.2.7.7.7.2.>.{ T A r 7 = * + % % = 7 b K .2.f.l.m.M.M.M.m.l.g.2...K b 7 . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 1 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , , , , , > , > , > > , > > : : , : > , : , : , : : > > : : > : > : : : : : : : : - - - : - - & : : : : & : : & : # - : - & & & # : : & # : & & & & & & & & & & & # # & # & - # # - - # # # % # & # # % # # # # # # l v v v v v v v v v v v v q - @ @ @ @ @ @ @ + @ # @ @ @ + @ @ @ + + @ + @ @ + + @ + $ % & : 5 w f M K K R Q R K S M b 9 5 = & $ + + + $ $ = > 7 b A Y ~ -.;.:.-.-.~ Y C f 9 > * $ + $ % : w b Y ;.8.h.z.M.C.C.C.M.z.j.2.-.T b 9 ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 2 , 2 , , 1 , 1 , , , 1 , 1 , , , , , , , , , , , , , , > > > , , > > > > > > : , > : , : > > > > : > > : > > : : : > > : : : : : : : : : : : & : : & : : - & - - & & & : & E u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.v.u.} 6 % & & # & & # # # & % % % % % # # % # % # * i v v v v v v v v v v v v a - o - O + + + - + + + + + @ @ + @ @ + @ # + + + @ + $ @ @ # = < e f G Y ^ ..:.>.;...^ K S b 9 < = @ + + + + $ % = : 9 s M S K T R T K A m s 7 : * $ $ + $ $ ; e C T :.8.h.m.N.C.Z.C.N.x.h.8.:.T N w ; $ + O . . ", +"2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 2 , , 1 , 1 , , 1 , , , , , , , 1 , , , , , > , > , > , > , > > , > , > , > , : > : : , , : > : > : > : : : : : : : : : : : : : : : : & : : : : & : : & : & = - - : & & : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.E % & & # # & & & # & % % % % % % % % # # # q v v v v v v v v v v v v k o - @ @ - + + O - + - O - + @ + @ + + + + + @ + + @ @ @ $ ; ; 0 f A R .<.2.7.9.7.2.<...R C f 7 : # $ $ + + + $ % * 3 7 e s m M M m m f w 7 > * % $ + + + * ; w b T ;.8.g.z.M.C.Z.C.M.z.h.7...T b 9 * $ + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , > , > , > > > > > > > > : > : > , : : , > > > > > > : > : : : > : : : : : : : : : - & : & : & : : & : : : & : & : & & +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.E # & # & & # & # % % % % % % % % % % $ # 3 v v v v v v v v v v v v k - o O @ + O - - O @ + + + + + # @ @ # + # @ + + + @ + # % ; < r M Y .1.9.w.j.j.j.q.9.1...K M e 7 = $ + + + + + $ % = : < 5 w w e w 7 5 5 ; * % + + + + + $ ; 7 b K { 2.f.l.m.M.N.N.m.l.f.2.{ K b 9 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , 1 , 1 1 , , , , , 1 , , , , , , , , , > , , , , , , > > 1 > > > , > , , > , > : : , : : > : : : : > : : > : : : : : : : : : : : : : - : : : & & : : & & : & : & : & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.m & & & # & # & & % % % % % % % % # # # 4 v v v v v v v v v v v v k o - - @ @ - O + + @ - o - + + # + + + @ + + @ # + + @ @ ; ; 0 f S ^ <.9.j.l.x.x.x.l.j.9.<.^ S s 7 = $ $ + + + + + $ @ # = = ; > ; ; ; = * % + + + + O + + $ * 7 r A { >.8.g.l.z.x.z.l.g.8.>.R S s 6 * $ O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 2 , 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 1 , , , 1 , 1 1 , , 1 , , , , , , , , > , , , , > , > 1 > , > > > > > , : , : , , : , > : > > > : > : > : : > : : : : : : : : : : - : : : & : : & & : : & : & : & & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.k.# & & % % % # % % % % % % % % % # # # 4 v v v v v v v v v v v v k + O $ - + + + + # + + - + + @ @ + + + + + + + @ + + @ # ; ; w n Y ..2.g.l.m.M.N.M.m.l.f.2. .K m w ; * + + + + O + + O $ $ % % $ * % * $ $ $ + + O O O O + $ % 5 r b K { 1.8.f.g.h.h.f.8.1.{ Y b w : $ $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 2 2 2 , 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , 1 1 1 1 1 , , 1 , , , , , , , , , , , , , > , , , > > , > , > > > , , > > > : , : , : : , : > > : > : > : > > : > : : : : : : : - : - : : - : & : : & : : & & : & : & = : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.L & # & % & & % % % % % % % % % % # % 4 v v v v v v v v v v v v k - O - + - + + - + # + + @ + + @ @ @ @ @ @ @ # + @ @ # # - > e M Q :.7.j.x.N.C.Z.C.M.x.h.8.:.Y B e > * % + + + X + + + + + + $ $ + $ + + + + + O X O O + + % = 5 s C U { >.2.8.8.8.2.>.{ T C s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , > > > > , > > > > > > , : , : , : : , > : > > : > : : : : : : : : : : : : : : : : : & : : : & : : : : & : & : : & & t D V V V N D V N V V V x V V V o.Z.Z.Z.Z.Z.Z.Z.Z.Z.0.# & & % % % % % % % % % % & % # % # 4 v v v v v v v v v v v v k - - o + + + @ @ + # # + + # + @ @ @ @ + @ + + @ + + # # - < r B Q :.9.j.x.N.C.Z.Z.B.m.j.9.>.Q B e > # @ + + X O + X X + + + + + + + O + O O O X X X O X O + $ % ; 7 f C K ! { ;.:.-.{ R Y C s 7 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 , 2 1 1 1 1 1 1 1 2 , 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 , , 1 , , , 1 1 , , , , , , > , , > , , , , , > , , > > , , > , > : , : , : , : : > > : : > : > : : > > : > : : : : : : : - : : : & : : : : & & : : & : & & : & & & - & & & - - - & & - & & & % # } Z.Z.Z.Z.Z.Z.Z.Z.Z.< # % & % & % % % % % % % # % % % % 8 v v v v v v v v v v v v k o O + - - o @ @ @ # + o - + @ @ + + + @ + @ + + @ @ # # - < e M Q ;.7.h.x.N.C.C.C.N.x.h.9.:.R M e > * + + + + O O O O X O + O O + O O O X O X O O O O O O + $ % 5 7 f b S K T T Y K S b s 7 > = $ + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 1 2 , 2 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , > , , > , > , , > > , > > > > > > , , > > > > > > > > : > : > : > > - > : : : : : - : : : - - - : : - - - : & : : & : & : & : & : & - & & & & & & & & & # & & & & = v.Z.Z.Z.Z.Z.Z.Z.Z.P # % % & # # # # # & # # # # % # # i v v v v v v v v v v v v k @ @ - + @ @ @ @ @ @ + @ @ + @ @ + @ @ + @ + + + + $ + % = < w n Y ..2.f.l.m.N.B.N.x.l.f.2...U b 9 : # @ + + O O O O O O O O O O O O O O o . O O X O O O O O X + $ * ; 6 e r b m M b b r e 7 3 * $ + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 , , 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , , , 1 , , , , , , , , , , , , > , > , > , > , > , > , : : > : > , : : : > > > : > : : > : : > : : : : : : : > - > : & - : - : & & & & : : & & & & & & - & - & & & & & & & & & & & & # } Z.Z.Z.Z.Z.Z.Z.Z.o.& & # & # & & & # # & & # % # # # l v v v v v v v v v v v v u # @ + o - @ @ @ @ @ @ @ o - + @ @ + @ + + + @ @ + @ + % % ; 9 b H ^ <.9.h.l.x.x.x.l.g.8.<.! S b 7 = % @ + X O + + O + O O O + O O O X X o o O O X O O X + + $ * ; : 6 9 w e e 7 6 : * $ $ + X . ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 : , & 1 : 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , , , > , , > , , , , > > > > , > > > > , > > > , : : > > > > > > : > : > : > : : : : : : : : - : - - - : : - : : : : : & & & : & : & : - & & - - & & - & & & & & & & % & j Z.Z.Z.Z.Z.Z.Z.Z.u.% & % % & # # & # # # # # % % # - v v v v v v v v v v v v v q - o + @ @ @ @ @ @ @ @ + + @ + @ @ + + @ + @ + @ + + % # % ; 1 r M Y .1.9.f.j.j.j.q.9.2...K M r < = # @ + + O O O O O X + O O O O O O O X X O O o O . . X X + $ $ $ ; ; ; = = * * * $ + + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 L J J L J W W W W W W B Q L L L C 7 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , , , C J F J J F F L F F J J F J , , , , , > , , , > 9 F F F F F F F F F C F F F 2 , : > > > : : F D F D D D F 7 : : : - - : : : Z F Z Z Z Z Z - & : & & : : : & : & - & & & - & & - & & & & & & & & & & # & Z.Z.Z.Z.Z.Z.Z.Z.u.# # & % # # & # & # & # & % # % u v v v v v v v v v v v v v ; @ @ o - @ @ @ @ @ + @ @ @ @ @ @ + @ @ + @ + + + + + + $ % = > 1 b A R ..<.2.9.9.9.2.<. .R A f 1 ; * % + O + + O + O O + O O O O O O O X o o O O O O X . . X . X + + + + $ $ $ $ * $ $ + + + X . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.m.C.C.Z.Z.Z.Z.Z.b.J 1 1 1 1 1 1 1 1 , , 1 , 1 1 I b.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.> , , , , > , > w &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F : , : > : > > 6.Z.Z.Z.Z.Z.Z.` : : : > : : : I Z.Z.Z.Z.Z.Z.u.& : & & : : & : & & & & & - & & & & & & & & & & & & & & % & & B.Z.Z.Z.Z.Z.Z.Z.B.# & & # % & # & # # % % # # # - c v v v v v v v v v v v v v + + - # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ + @ + + @ + @ % # ; < w b A K ^ ..;.>.;...^ Y A f e < = @ + + + + O + O + O O O O O + O O O . O O O . o . . . . . . + + + + + + $ + + + O . . + . . O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.N.V.Z.Z.Z.Z.Z.Z.Z.Z.I 1 1 1 1 1 1 1 1 1 1 1 , [ Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , > , , , , k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F > : > > > : > D Z.Z.Z.Z.Z.Z.r.: > : : : : > 6.Z.Z.Z.Z.Z.Z.I : : - : : & - & : & : & : & - - & & & - & & & & & & & & & % & u.Z.Z.Z.Z.Z.Z.Z.Z.& % % # & # & # % & % # # # @ a v v v v v v v v v v v v v k - - O @ @ - o @ @ @ @ + @ @ + + @ @ + + @ + @ + @ + + @ + @ % # ; 5 w b B S Y Y Q R Y S M s w < * % @ @ O O O + O O O + X + O O O O O O O o . O X O O o o . o . . . . . . O O O . + O O O O + + + + + + + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 , 1 , 1 1 1 H Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , , &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.F > , : > : : > > v.Z.Z.Z.Z.Z.Z.7 : : : : : 7 Z.Z.Z.Z.Z.Z.v.: : & & : & : - - & & : - & & & & & - & & & & & & & & & & & & & B.Z.Z.Z.Z.Z.Z.Z.B.# & % & # # # % # # # # # % i v v v v v v v v v v v v v v 4 - O + @ @ @ @ @ @ @ @ @ @ @ + + @ + @ @ + @ + @ + @ + + @ + # % = - > 7 r f m B B M n b e 7 > = % @ + + + O O O + O O O X O O O O O O O O O o . o o . . . . X . . . . . . X . . X . O + O X $ $ $ $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.3.1 1 1 1 1 1 1 1 , , p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , > y Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.C.F > : , : , : > : | Z.Z.Z.Z.Z.Z.` : : : : : ` Z.Z.Z.Z.Z.Z.o.: & : : & : : & - & : & : & - & - - & & & & & & & & # & & & # & Z.Z.Z.Z.Z.Z.Z.Z.s.i i i p p p i p i p p a k v v v v v v v v v v v v v v v c $ + + - # @ @ + @ @ @ @ + @ @ @ @ @ @ @ + @ + @ + @ + + @ + @ + % # = = > < 7 e e e e e 7 , > ; # $ @ + + O + + O X X + O + O O O O O O O O O O o X O . . O . . . o X . . O + + $ $ % * * 3 * 3 * * $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.k.L L L L L L +.Z.Z.Z.Z.Z.Z.B.1 1 1 1 , 2 , 1 1 C Z.Z.Z.Z.Z.Z.Z.+.J J J J P F F J J F , , , > , , &.Z.Z.Z.Z.Z.Z.k.W F F F F F F F F F 2 > > > : > : : : 0 B.Z.Z.Z.Z.Z.r.: : : : : k.Z.Z.Z.Z.Z.Z.7 : - : - - - : & : & - - - & - - - & = & & : & & & & # - # - & V Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v v v a - + @ @ - @ @ @ + @ @ o + # # @ @ @ @ + @ + @ + + @ + + @ + + @ $ $ % & = * : : < < > : ; * # % $ $ + + + O O O + X X O O X O X O + X O O X O O O O O . . o . X O o X X X X X $ % & 3 5 9 9 9 e 7 5 ; = % $ X X ", +"2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 1 2 +.Z.Z.Z.Z.Z.Z.W 1 1 1 1 1 1 1 1 &.Z.Z.Z.Z.Z.Z.+., , , , , , 1 , , , , , , , , , , b.Z.Z.Z.Z.Z.B.9 > > , > > > > > > > > > > : > > > > : > 5.Z.Z.Z.Z.Z.Z.7 : : : d Z.Z.Z.Z.Z.Z.4.- : - - - - - & : & : & - & & & & & & & & & & - & & & & & - # 8 0.Z.Z.Z.Z.Z.Z.Z.Z.e.v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ + O - O @ @ @ + - + - # + + @ @ + + + @ + @ @ + @ @ + @ @ @ + $ $ $ % % % = & & * * * # % % $ + + + O + O + X O + + O O + X X O O X X O X O O O O . O . o o O o X + + $ * = 5 9 s b b b b b s 9 7 = * $ O X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 2 e Z.Z.Z.Z.Z.Z.+.1 1 1 , 1 1 1 , p.Z.Z.Z.Z.Z.Z.w , 1 , , 1 , , , , , , , , , , , d Z.Z.Z.Z.Z.Z.&.> > > , > > > > > > > > > > > > : > > > : N Z.Z.Z.Z.Z.Z.` > - : %.Z.Z.Z.Z.Z.Z.C = - - - - - - & : & : - & - - & & : & : & & & & & & = & - & q / B.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v v u # - - O + - + @ @ @ + @ @ @ @ + # @ @ @ @ @ + o + @ + @ $ @ # # % # # $ # % # # * $ % # % $ $ $ + + + + X + X + O O O O O + X X + O O O O O O X O o X X o . . X X o O X O + $ * = 7 r b C S T T T K A b s 7 : * + X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 1 1 1 2 1 2 0.Z.Z.Z.Z.Z.p., 1 1 1 1 , , 1 Z.Z.Z.Z.Z.Z.0., 1 1 , , , , 1 , , , , , > , , , F Z.Z.Z.Z.Z.Z.F , > > > > , > > > > > > > : > > > - > > : : k.Z.Z.Z.Z.Z.u.- - - v.Z.Z.Z.Z.Z.k.- - - : - - - - : & : & - & & & & - & & & & & & & & & % & # 8 v t.Z.Z.Z.Z.Z.Z.Z.Z.Z.) v v v v v v v v v v v v v v v v v v v v v v v v v v l * @ + + - O + O - @ @ @ @ @ + # # + @ o @ @ + @ + @ @ + $ # # % = = = ; * = & & & # $ @ + $ + + + + X + O + + O O O + O + O o X o o O O O O X X O O O O . o . . O O X X + + * = 7 s C Y { { -.-.-.{ ! K C s 7 * % $ O ", +"2 2 2 2 9 2 2 2 2 2 2 1 2 2 1 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 2 1 1 2 1 2 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , > , +.Z.Z.Z.Z.Z.Z.9 , > , > > , > > > > : > > > > > : > : - > > W Z.Z.Z.Z.Z.Z.t > I Z.Z.Z.Z.Z.Z._ - : - - - - - - & : & : & & - - - 5 V V V V V V V V V V V V =.d.Z.Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v c ; # # + - - @ + + - + + + + + + + + + # + # + @ + @ @ @ # # # ; - > , < , 5 > : = = # % $ @ + + + + O O + X O O + + + + O O O O o O o O O O X O O X O O O O X o o . O . o O O + $ * 7 s C T { >.2.2.8.8.2.>.{ Y M s 7 * $ + ", +"2 2 2 2 2 2 2 2 2 2 9 2 2 1 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 7 1 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 , 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , > , , , , +.Z.Z.Z.Z.Z.Z., > > , > > > > > > > > > > : > > > > : > > > : B.Z.Z.Z.Z.Z.} - 6.Z.Z.Z.Z.Z.B.7 - - : - - - - - : & : & & : - e 4.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ # % + + O O - O - + - + - o + - + + + @ + + + @ # @ $ # = = > 7 1 9 e e e w 7 < : = # % @ + + + + O + + + + O O O O O + O + + O O O O O + X O o X X . X o o o . . O o o o O O O $ * : e m K { 1.8.f.h.j.h.f.8.1.{ K m 9 ; $ + ", +"2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 2 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , 1 , , 1 , , , , , , , , , +.Z.Z.Z.Z.Z.Z., , > > , , > > > > > > > > > > > : - > > - - > %.Z.Z.Z.Z.Z.k.1 Z.Z.Z.Z.Z.Z.5.- : - - - - - - - & : & : : - j B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.c.v v v v v v v v v v v v v v v v v v v v v v v v v k * % % $ # - + + - O - O + # @ - + - o - + @ @ + # # + + - # = : , 7 t b n M A M M b r 7 5 = % $ @ + + + + X + O O + O + O O + O O O O O O O O O O o O O O . o . . . . o . . X X X + $ * 5 r C ! >.8.h.l.z.z.z.l.g.9.>.~ C r 5 * + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 , 1 1 , Z.Z.Z.Z.Z.Z.+., , , , , , , , , , , , , , , , , +.Z.Z.Z.Z.Z.Z.F > > , > > > > > > > > > > > > > > > > > > > : t Z.Z.Z.Z.Z.Z.+.Z.Z.Z.Z.Z.Z.r : - : - - - - - - : & - & & e B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.' v v v v v v v v v v v v v v v v v v v v v v v k 8 $ % $ $ @ + @ @ + - + + + - @ + o o - + + + # + # + + + @ @ & ; 7 e b M H Y R R R K S M b w , = * $ + + + O + X O + + O O + O O + O O + O O O O O O . o o O o o . o o . o . . o O + + = 7 f K .2.f.l.m.M.V.M.m.l.q.2.{ K f 7 = $ ", +"2 e 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 W Z.Z.Z.Z.Z.Z.1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , 1 , , , , 1 , , , , , , , I Z.Z.Z.Z.Z.Z.%., > , > > > > > > > : > : > > > : > : : > > > : u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- : - - : - - - - - - = - - = u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v c a p p q t p i p p u i i i u u u p u 6 4 & # # # # # # # # @ O @ @ - + + + - - O + + + + + + # + + @ @ @ - ; < 0 n A Y ^ -.:.>.:...^ T C f e < = @ + + + + + O + X + O + O O + + X O O O O O O O O O O O O . . o . . . o o . . . . . O + $ ; 9 m T ;.7.h.z.N.C.Z.C.M.z.h.7...T m 9 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+.1 1 1 , , , , , , , , , , , , , , N Z.Z.Z.Z.Z.Z.B.w > , , , > > > > , : > > > > > > : , > : - > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z._ : - - & - - - - - - - - & - V Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.n.' v v c - & % & # & % # % % # % % # % % # # $ % @ % # # # # # @ # @ @ - - @ + O - O o + + @ + - - + # + # @ $ # # ; ; 0 f A Q ..<.2.7.9.9.2.<. .Q A f 1 : * % @ + + X + X + O + O O O O O X O O O + O O O O O O o . o . . o . . . . . o . O O % ; e m T -.8.h.z.N.Z.Z.C.N.x.h.8.:.T m 9 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 1 1 2 2 1 1 1 p.Z.Z.Z.Z.Z.p.1 1 , 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., , 1 , 1 , , 1 , 1 , , , > , , > , B.Z.Z.Z.Z.Z.Z.k.I F D F F F F N > : > : > : > : , : : > > : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: - : : : : : : - - - - & - - 0.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.u.u.u.u.s.d.d.d.d.d.d.t.=.O.v v v v ; % # % # % % % % % & % % % % # & # # % @ % % # # # # @ # @ # @ @ O @ + - O - + @ - + + + + @ @ @ + @ $ # - ; 1 t B Y .1.9.w.j.j.j.f.9.1. .T M r < = % + + + + O + O + O O + + O + X + X X X O O O O O O O X . . . . . o . . . X o . . . O $ $ = 9 m T ;.7.h.l.M.C.C.C.M.x.h.7.;.K m 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 2 1 n Z.Z.Z.Z.Z.Z.&.1 1 1 1 1 1 , , Z.Z.Z.Z.Z.Z.+.1 , , , , , , , , , , , , , , , , , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.v.W > > > > : , : : > : : > > : O.Z.Z.Z.Z.Z.Z.Z.Z.Z.O.- : - : & : & - - - - - - - 5 Z.Z.Z.Z.Z.Z.Z.Z.Z.4.= & & & ; c v v v v v v v v v v v v k - & & # & % & % % % % % % # % # # & % % % % @ # # # # @ # # @ - O - @ + - + + @ @ @ + + - + + + @ @ @ @ # - ; 1 n H ^ 1.9.j.l.x.x.x.l.j.9.,.^ S b 7 ; % $ + + O + + O O + + O O + X O o X X + O O O O O O X X . . . . . . o . O O O + $ = 7 b K .2.f.l.m.M.N.M.m.l.f.2. .K h 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 1 2 2 2 1 0.Z.Z.Z.Z.Z.Z.W 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , 1 1 1 , , 1 , , , , , , , , , > d Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.! ; > > : : : > , : : : : : d Z.Z.Z.Z.Z.Z.Z.Z.Z.d : - : : & : : & : : : - - - I Z.Z.Z.Z.Z.Z.Z.Z.B.< & & & & - v v v v v v v v v v v v v q % % % % & % % % % & % % % % # & # # # # # # # # # # # # @ # # + + - O @ @ - + @ @ @ + - O + + @ @ @ @ @ # - ; e m Y -.2.q.l.x.M.N.M.m.l.q.2...Y m w : % % + O + + X + O O + + O O O O O + o o X X O O O O . O . . o o . . o o . . o . . O + $ * 6 s S R >.8.h.l.z.x.z.l.g.8.>.! S r 5 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.[ +.+.+.+.+.p.Z.Z.Z.Z.Z.Z.B.1 1 1 1 1 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , > , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.t > > , > , : : > : , > : : 6.Z.Z.Z.Z.Z.Z.Z.6.: - : - : : : & : : & & - & & o.Z.Z.Z.Z.Z.Z.Z.Z.4.& & & & & 4 v v v v v v v v v v v v v ; % % & % & % % & % # % % % % % # # # # # & # # # # # # # # @ @ @ @ @ @ - @ + O @ @ @ @ @ + - + @ + + @ # # - < e B Q ;.7.h.x.N.C.Z.C.M.x.j.7.;.R M e < ; # + + + X + O + X O O + + O + O X O O + O O o O O . O . . o o . . . . . . . . . O X $ * ; e b Y { <.8.f.g.j.h.f.7.<.{ Y b w ; $ + . ", +"2 2 2 r 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.+., 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , , , , , , , , 0 k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.0.> > , : : : : > : : : , : 4.Z.Z.Z.Z.Z.Z.Z.4.: - - : & - : : & - & : - - & 0.Z.Z.Z.Z.Z.Z.Z.Z.E & & & & & q v v v v v v v v v v v v v - # & % % % % % % % % % & % % % # & & # # # # # # # # # # @ # @ - @ @ @ O O @ - + + @ @ + + + + @ + @ @ # @ ; < r B Q >.9.j.x.N.C.Z.Z.N.x.j.9.>.Q B e < = + @ + O + O + O + O + O O O O O O O + O O O O O O . . o . . o . . . . O . . O X + $ = 7 s C U .>.2.7.9.7.2.>.{ Y M r 5 * $ O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 7 2 2 1 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 1 , 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , 1 1 , 1 , , , , , , , , , > , , , , w 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.B.> - : : , : , : > : : : 7 B.Z.Z.Z.Z.Z.Z.Z.B.7 : : - : : & & : : : & & : & p.Z.Z.Z.Z.Z.Z.Z.Z.D - & & & * i v v v v v v v v v v v v z # & % % % & % % % % % % # # % % # # # # # # # # # # # # # # # @ + @ - O + - @ @ - + + # - + - o + @ @ @ $ - ; ; t B R ;.9.h.x.N.C.Z.C.N.x.j.7.:.Y M e < * # # + + + O X + O + O O + O + O O O O O O O o O O . . . . . o . . . . o . o X X X $ % = 7 f C K ! .;.:.;.{ ! K C s 7 ; % + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.V 1 1 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , 1 , , , , , > , , , > , > , , 0 F F F F F F W 5.Z.Z.Z.Z.Z.Z.Z.I : > > : > > : > > : > | Z.Z.Z.Z.Z.Z.Z.Z.Z.} : : = : : - - : : & : : & : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & # a v v v v v v v v v v v v z - # & # & # - # # # & # % % % % # % # # % % # # # # # # # # # # @ # # @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ + @ * & < 9 M U -.2.w.l.m.M.N.N.x.l.g.2...K M w : = $ + + + + + O O + O O + O X O O X X X O O O O X O o o o o o . o . . . . . o o . O + $ * 3 7 r b S K T R K K A b r 7 * ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.B.6.n 1 1 1 1 1 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , , , , , , ; , , , > > > > > > , I Z.Z.Z.Z.Z.Z.+.> : > : > : > : : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: : : : & - - : & : & : - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & - & - & p v v v v v v v v v v v v z # # # & # & # # & # & # % % % % # % % % # # # # # @ # # @ % # # # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ # # > 2 b H ^ 1.9.j.l.x.x.x.l.h.9.,.^ S f 7 ; = + + + O O O + + X + X + O + O O + o + O O O O X O X X o o X o . . . o o o . . . X O + + $ % = 5 w r b m M m f r e 6 ; * ", +"2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 , 1 1 , , , , , , , , , , > , , > > ; , , , , > > , > > > > b.Z.Z.Z.Z.Z.0.> : > > : > : : > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.I : : : & : - & : : & & = : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & g v v v v v v v v v v v v g # - # & & # - - # # # & % % % % % % % # % # % # # % # # # % @ # @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ # * ; 1 r B T ..1.9.q.h.j.j.q.9.1. .Y M r < = $ + + + O + + O O + O + O + O O O O X o O O O O O O O O O . o o . . . X . X . O O O X $ % * ; 7 7 7 9 9 8 5 ; * + + ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , , , , 1 , , , 1 , , , , , > , , , > , > > , > , > > , > 5.Z.Z.Z.Z.Z.p.> > > : > : > > : : p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- - : : = : : : & : - - & p.Z.Z.Z.Z.Z.Z.Z.Z.V & - & & - p v v v v v v v v v v v v p - # - # # & # # & & # # % % % % % # # % % % # # # # # $ # @ @ $ @ # # @ @ # @ @ @ @ @ + @ @ @ @ # + @ + @ % # = , w f A Q ..1.2.7.9.9.2.<. .Q A b 7 ; = # + + + + O + + + O + O O O O + + O O O O X O O X O O X X O . O . . . o . . . . . O O X $ + % % % = ; ; * * * $ % ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , 1 1 , 1 , , , , , , , , > , > , , > , > , , > , : > > +.Z.Z.Z.Z.Z.u.: > > > > : > : : d Z.Z.Z.Z.Z.Z.u.Z.Z.Z.Z.Z.Z.t - : : & : : & : & & - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p - # - - & # - # # & & # & % % % % % % # # # # % % @ # @ % @ % @ # @ @ # @ # @ @ @ @ @ @ @ @ @ + + + @ + + # % # - < w n A R ^ ..>.>.>...^ Y A f 9 < = # % + + + O + O + O + + O + + O O O + X o X O O O O O O X . . o o . . . . O . . . + + $ $ $ $ $ $ $ $ $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 7 1 1 1 2 2 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , , , , , > , > > > > > > , > > +.Z.Z.Z.Z.Z.p.> > : : > > : > , %.Z.Z.Z.Z.Z.Z.j v.Z.Z.Z.Z.Z.4.- : & : : - - : - - - - u.Z.Z.Z.Z.Z.Z.Z.Z.Z & & - & & p v v v v v v v v v v v v p # # # # # & # % & # # # % % % % # # # % # % # % # # # % @ # @ # @ # # @ # @ @ @ @ @ @ @ @ + @ + @ @ + # @ # # % = - 1 e f B H Y Y Q Y Y S M y e 5 ; # % + + + O O + + O O X O O O O O + O O o + X X O O O O O X O O o . . o . o . o o X o X . . . O X X O + + + + O X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , , 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , , 1 , , , , , , , , , , , , , , > , > , , > > > , : , +.Z.Z.Z.Z.Z.u.: > > : > > > : 1 B.Z.Z.Z.Z.Z.b.: %.Z.Z.Z.Z.Z.B.7 : : : & - - - - : & : p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p # - & % - # % % # # & & % % % % % % % # # # # # # # @ % % @ @ $ @ @ @ @ @ @ @ @ @ # @ @ @ @ + @ # + # + @ + @ % # = ; < 0 t f m B B B m f r w < = % % % + + + + + O + + + + O X O O + O + O o o O + O O O O O O X o o . . o . . . o X X . . X X . . X . O . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.&., 1 , 1 1 , , , , 1 , , , , , , , , > , , , > , > > , , > > , , u.Z.Z.Z.Z.Z.%.> : > > : : : : ` Z.Z.Z.Z.Z.Z.| : d Z.Z.Z.Z.Z.Z.} : & & : - - : & - - & u.Z.Z.Z.Z.Z.Z.Z.Z.F & & & & & p v v v v v v v v v v v v p # - # # - # & % # & # # % % % % % # # # % # % # $ # % @ @ % @ % @ @ + - @ @ @ @ @ @ @ + @ @ @ # + # + @ + @ + + # % & ; > 7 0 w e r e e 1 < - ; * % + + + + O + + + O + + O + + O + O O O O O O O O O O O X X O X o . . o . X O . . . O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 b.Z.Z.Z.Z.Z.k., 1 1 , , , , , , , , , , , > , , , , , : , , : , > , > > > > 0 Z.Z.Z.Z.Z.Z.| , > : : > : > : v.Z.Z.Z.Z.Z.Z.t : : k.Z.Z.Z.Z.Z.v.: : & : : & : : - : & p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v i = % % & # % & # - - @ - + - + - % % % % # % # # % # # # # # # % @ @ # @ # @ @ @ @ @ @ + @ @ @ + # + @ @ + + @ @ @ # # # - - ; > , > < > - ; % # # @ + + + + + + + + + + $ + + X + O + O O X O O X O O O O O O O . X O O X X X X X O + + X X X X X . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.f.1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.Z.Z.Z.Z.Z.Z.J , , , , 1 , , 1 , , , , , , , , , , , , , , , > , > , > > , X.Z.Z.Z.Z.Z.Z.h > > > > > > , D Z.Z.Z.Z.Z.Z.k.: : : } Z.Z.Z.Z.Z.Z.I : : & & : & & - & - u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p % # & # # & # & + + - + - + - + % # % # # % # # # # # # # @ + # - # @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + # @ + + @ @ @ # # # # # - ; & ; % * # $ @ $ + + $ + + + $ + $ % $ + @ $ + @ + + O X + O + X + O O O X X . O O O X X O X O + + + $ + + + O O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 [ Z.Z.Z.Z.Z.Z.k.e , 1 1 , , , , , , , , , , , , , , , , , , , , > , > > > m B.Z.Z.Z.Z.Z.v.> > > > > : : > r.Z.Z.Z.Z.Z.Z.X.: : : d Z.Z.Z.Z.Z.Z.u.& : : : : & : & - & p.Z.Z.Z.Z.Z.Z.Z.Z.k.u.u.u.u.u.s.d.d.d.d.d.d.d.d.d.d.d.d.s.u.$.% & & # & # - + + - + - + - % # # # % % # # # # # # # # % # + @ @ @ @ @ @ @ # @ @ @ + # + # # + @ + @ @ @ + + + + # # @ @ # # # @ $ # $ @ @ + + + + + # @ $ * # * = & * * @ @ + + + + O O O O O O O O O O O . . O O O O + + $ $ $ * $ * $ $ $ + + . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 1 1 1 , 1 e B.Z.Z.Z.Z.Z.Z.B.p.p.p.p.p.p.i.i.i.i., , , , , : N i.i.i.i.i.u.p.u.p.p.p.Z.Z.Z.Z.Z.Z.Z.O.: > > : : > > t Z.Z.Z.Z.Z.Z.Z.7 : : : - k.Z.Z.Z.Z.Z.Z.e : & : & : : - : & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.& % # & # & + - - + - @ - + % % # % # # % # % # # # # @ @ @ @ @ @ @ # @ # @ @ @ + @ # + # + + # + @ + + + @ @ @ + @ @ @ @ @ @ @ @ + @ + + + + + + @ @ @ * = ; > : 5 : ; = & # # % + + + O O O O O O X O O o . O O O + + $ % * * * ; = = = * * $ $ + O X . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , F Z.C.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.M.1 : > > > > : > %.Z.Z.Z.Z.Z.Z.r.: : : : : ` Z.Z.Z.Z.Z.Z.4.- - : : & & - : & p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.% % - - - - - @ - + O $ - - % % # # & % # # # # # # @ # @ # @ @ - # @ @ @ @ @ @ @ @ @ @ + @ + @ + + @ + @ + + + @ + + @ @ + $ + + $ + + + + + + + # * ; > 5 7 e w e e 9 7 5 : * * + + + + X O O O O O O O O O O + + $ $ % = : 5 9 9 e 9 9 5 ; * * @ X X X ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 e k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , > , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : : > > : > > 7 B.Z.Z.Z.Z.Z.Z.` : : : : : 7 Z.Z.Z.Z.Z.Z.B.7 - & : & : - & & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.% % + $ + O @ - + - - + - + # # # # # # # # # # # % # # # @ @ @ + @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ @ + @ + @ @ + + + + + + + + + + + + + + + @ # $ % = > 0 e f m M M C b f e 9 : & $ $ + + X O O O O O X X O O O + + $ = = 6 e r b b C b b f e 6 ; & $ $ X ", +"2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 2 1 1 1 , 1 , 2 1 1 1 , 1 1 1 , , C k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , > , , , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : , : , : > : > ` Z.Z.Z.Z.Z.Z.B.7 : : : : : : r.Z.Z.Z.Z.Z.Z.} - & : : & - & - p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.- ; - - ; - - - - @ ; - - $ % # # # # # # # % % # # @ # # # - + @ @ # # @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ + @ + + @ + @ + + + + + + + + + @ $ * = < e s B G U R R T K G M s 9 5 = $ $ + O X X O X O O O X O + + $ * > 9 s m S K T T T K G m r 7 ; * $ X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 p.p.p.p.p.p.3.1 2 2 1 2 1 1 1 1 1 1 1 2 2 1 , 1 1 1 1 1 1 1 , 1 1 , [ 0.p.p.p.p.p.p.p.p.p.p.p.p.p., , , , , > N p.p.p.u.u.u.p.u.p.u.p.p.p.p.&.d , , : , : > > > : %.u.p.u.p.u.p.+.: : : : : : - I u.u.u.p.u.u.4.- : : & : - - & I B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.; 4 3 ; 3 3 ; 4 8 ; 4 4 ; 4 , > 4 4 4 4 4 < 3 3 3 3 3 3 3 3 - + @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ @ + + + # + # + + + + $ + + + + + + + @ # ; > 0 f A K ! { ;.>.:...! Y A f w : * $ + + + O O O O O O O O + $ * : 7 s M Y ! .;.:.-.{ R Y C s 7 = % $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 2 1 , 2 , 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , 1 , , > , , , , , , , , , , , , > , > , > > > > > , > : , , : , > , : : > > : : : , : : : > : : : : : : : : : : : - : : - : : & : & : - - - - - & V D V V V V V V V N V V E ] ] ] ] ] ] ] ] ] ] ] ] ] ] ' v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; O - o O - O O + $ O + - + - O @ @ + @ + @ + @ + + + @ + + @ + + @ + + + + + % + = : 7 f S T ..<.2.8.9.7.2.<.{ R B y 7 : * + + O O O O O X O + + + # : 7 s A Y { >.2.8.8.8.2.>.{ T A s 5 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 , 1 2 , , 1 1 , 2 , 1 , 1 , , , , 1 , 1 , , 1 , , , , , , , , , > , , > , , , > > , > , > > > > , : : > , : : , : > > : : > : : > : : : > : : : : : : : - - - : : & & : & : : & - - & - & - & - - & & - & - - & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - o - - + + - O - - $ O + - + + @ @ + @ + + @ @ + @ + + + + + + + + + + + + + * = 5 e M K .1.9.g.h.h.j.q.9.1.{ Y M e > & @ + + O O O O O O O + @ * : e b U { <.7.f.h.h.h.f.8.1.{ K b e ; % X X . . ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 , , , , , , , , , , , , , , , , , , > , > > , > , > , > > > > > , , , : : > > : > : > : > : : , : > : : : : : : > : : : : - : - : : : : : & : : - - - - - - - & - & & - - & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ - o - O O - + + - + + @ O + + @ + @ @ + @ + + @ + + @ + + + + + + + + + + % # : 7 b S ! <.9.h.l.x.m.x.l.g.9.>.~ A b 7 = % + + X O O O O O O + % = 5 s S ! >.8.h.l.z.m.z.l.h.8.>.R S s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 2 1 2 1 1 1 1 1 1 2 2 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 1 1 , , , 1 , , , , , , > , , , , , , , > > , : , > , > > : , : : , : : , > > > : : > : : : : > : : : > : : : : : : : - : : & : & : & : & & - & - - & & & & & & - & & & & & ; i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 O o - O - + O - o o + @ @ @ + @ @ + + + @ + @ + + @ + + + # + + + + + + + + # * > e m Y ..2.g.l.m.M.V.M.m.l.w.2.-.U b 7 ; % $ + O O O O O O + $ $ : 7 b U { 2.f.l.m.M.N.M.m.l.f.2.{ K b 7 * $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , > , > , , > , , > > > > > , > , > , > : , , : > : > > > : > > : > : : : > > : : : : - : : : : & : : & : : & : : : - - - & - & - - : & & & - & & & & & p v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ O - o - O - @ @ @ @ @ - O + + @ @ @ @ + @ + # + + @ + + + + + @ + + + + # $ & 5 e M T :.8.h.x.M.C.C.C.N.x.h.8.:.T m w : * $ + + O O O O X + + $ : w b R -.8.h.z.N.C.Z.C.M.z.h.7...T b e ; * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , > , > , , , , , , > > > > : , , > : , : , > > : > : : > : > : : : : : : : : : : : : - : : : : : & - : & & - - - - & - - & & - & - & & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - - O + o O - @ @ @ @ @ + @ @ @ + + @ + @ @ + @ + + # + + @ + + + + + + + @ % & > r M R >.9.h.x.V.C.Z.C.N.m.h.9.:.R M e > $ + + O O O O X O + + * 3 w M R ;.9.h.m.B.C.Z.C.N.z.j.8.:.R b e ; % + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 1 1 2 , 1 1 1 , 1 1 , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , > > , , , , > > , > > , > > > , : : , : , : : : > : > > : : : : : : : : : : : : : - : : : : - : & : : : : : & & - - - - & & - & & & - & & & & - & u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 o - - - - O O + - @ @ O - + @ @ @ @ + + @ + @ + + + + + + + + + @ + + + $ + @ = 5 e M R :.8.h.x.N.C.Z.C.M.x.j.7.;.T C e > * + + O O O O O O + + % ; w b R -.8.h.z.M.C.C.C.M.x.h.7.-.T b e = $ + . . ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , , > > , , > > , > > > , : , , : , : , : > : : , : : : , > > : > : : : : : : : : : - : - : & : & : & : & - - - & - - & & - - - & - & - & % - ; v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 - o O O + + - + O @ @ + + @ @ + + @ @ @ + @ + + @ @ + @ + @ + + + + + + + + @ * : e b K ..2.w.l.m.M.V.N.m.l.q.2. .K m 9 : # $ O O O X O O X O $ $ ; 7 b Y { 2.f.l.m.M.B.M.m.l.f.2.{ K f 9 * $ + . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , , , , , 1 , > , , , , > , , , , > , > > , > > > > : , , > : > > : > > > : > > > : : > > : : : : : : : : : - : : & : : - : - : : & : - & : & : - & : & - & & & & - & & & & - u p g z l l l l l l l l g l l k g l k k k k k k k k k k l l k l k k k k k k k k k k k k ; @ # @ # @ @ @ - + + - O O + @ @ @ + + @ + + @ @ + + + + + + + + + + + + + + % % : 7 f S ~ <.9.h.l.z.m.z.l.g.8.>.! G f 7 = $ + O O O O X O X + + $ * 7 s S ! >.8.h.l.z.z.z.l.h.8.>.! A s 5 % $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , , > , > > > , > > > , > > , > : : , , : > > : > > : : : > : : : > : : > : : : : : : : : : : & - : : & : : & - - & : & & : & - & & - & - & & & & & & & & & & & - & & & % % & - # - - - - @ - - @ - @ - @ - # @ - + - # - @ + + - + - # + # @ @ # @ @ @ @ @ @ + + + O + - - + @ + @ @ + @ + @ + @ + @ @ @ + + + + + + + + + @ $ = 5 r M T ..1.9.q.h.h.h.f.9.1. .T m e 5 * @ + + O O O O X + O + $ & : e M Y { 1.8.f.h.h.h.f.8.1.{ U b 9 5 * $ ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 2 1 1 2 2 1 1 1 1 1 , 1 1 1 1 , , 1 1 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , , , > , > > , , , > , , > > > > > , > , : : , , : > : > > > > > > : : : : : : : : : : : : & : : : : : & : : & : : : & : - : & & & - & & & & - & & & - & & & & - # % & % % & & & # - @ - @ + + - @ @ - + - + - - @ - + - # + - - + - + + + - - + + - O @ # # @ @ @ - - o - @ @ O + @ @ + @ @ @ + + + @ + + + + + @ + + + @ + + + # $ * : 9 f A T ..<.2.8.8.8.2.>.{ T A s 7 = * $ + O O O O O O O O + $ $ = 7 r A Y { >.2.8.8.7.2.>.{ T C s 5 = $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 2 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 , 1 1 , , 1 1 1 , , 1 , , , , , , , , , , , , , > > , > > , , > > , : , : , > > : > > > > : : : : : > > : : : : : > : : : - : : : : & : : & : - & & & : & & & & : & & - - & & & & & - # & - # & - # & & & & & # & & # - @ - - - + - - + - @ - + # + + - + # - @ + - @ + - - + + + - $ @ @ # @ @ @ @ + + + @ @ + @ @ + @ @ + @ + + @ + + @ + + @ + + @ + + + + + + + $ % = 5 e f A K ! ..;.>.;.{ { Y A f 9 5 = # + O O O O X O O X O O X $ & ; 7 s C U ! { ;.:.;. .! U C s 7 ; % $ X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , > > , > , , > > > > > , : : , : , > > > : > > : : : : : : : : : > : : : : : : : & : : : : : & : & & : - - - : - & & - - & & - - & & & & - - & & & & - & # % & # & # & - @ - @ - @ - # @ - + - @ # # - # - + - + @ + - - + + @ - + + + @ # @ # @ @ @ @ @ @ @ + + @ @ @ @ + @ @ + @ + @ + @ + + @ + + + + + + + + + + + @ $ # = 5 9 s M S K T R T U S M f w 5 * @ + + + O O O X O O o O O + + % * : 7 s m A K T T T K A m s 7 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , > > , , , > , , > > > > , > > : , , : > : : , > > : > > > > : : : : : : : : : - : : : : : : & : & : : : : : : - & - & & : - & & - & & & & & & - # - # # & & # & & & & & & & # @ - @ - @ - @ @ - + @ @ - # - + # # # # @ - # + @ + - + + + - - @ $ - @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + @ + + @ + + + @ + @ + + + + + + + $ % % = 5 9 e b m M C C b f e 7 : = $ @ + O O O O O + O X O X X + + $ = ; 7 e s b b m m b r e 6 = * $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 1 1 1 1 , 1 , , , , , 1 , , , , , , , , , , , > , , , , > > > > , , > > > , , , : > , , : : > > : > : : > > > : > > : > : : : : : : : : & : : & : - : & : & - & & - - & & - & - & - - & & & & & - & & & & & & & # & & # & % - @ - @ - + @ - # @ - @ - @ - # # # + # - # - + + - - @ - + + + - @ + + @ @ @ @ @ - @ @ + O @ + @ + @ + @ + + @ @ + @ + + @ + + + @ + + + + + + + + @ $ % = : 5 7 e e e e w 7 5 ; * # % + + + O O O O O O O O X X O O + $ $ * = 5 6 9 e w w 9 6 3 * * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , , , 1 , , 1 , , , , 1 , , , , , , , , , > , > , , > > , > > , > > > , : : , : : , : : > : > > : : > : > : : : : : : : : : : : : : : : : : & & : & : & : - - & - - & - & & & & & & - & & - # & & & & # & & & & & % & @ - @ - # - - @ - - + - # # @ @ - # - # + # # # - + + + - + - + + # @ # # @ @ @ + O @ @ @ - + @ @ + @ @ + @ + @ + @ + + + + @ + + + + + + + + + + + + @ @ % * & : 3 : > : : * = & $ $ + + O + O O O X O O O O O . X O O X + + % & * = = = ; = = * $ . $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 1 , , 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , : > > > > , , : : , : , : > > , : : > : > : : : : : : : : : : : : : : : : - : : - & : - : : & : & & : & & & : & - & & & - & - & & & & & & & & & & # & & & & # & # & # & & & # & # # & & @ # & @ # @ & @ @ & @ & @ @ @ @ @ @ @ & @ @ @ @ @ # @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + + @ + @ + + + + @ + + + + + + + + + + @ + @ @ # % % & % & & # @ @ @ + + + X X + O O O O X O O O O O O O O + + $ $ $ * $ * $ + $ + O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 1 1 2 2 2 1 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , : , , , : , , : > > , : , > : , > , , : : : : : > > > > > > : > > : : > : : > : - : : - - : - & : : & & - - : & : : & & : & & - & & & & & & & & & & & & & & # & & & & # & & & & # # & # # # & # & # # # # & @ & # % # # % & @ # # @ & # @ # # @ @ @ @ @ # @ @ @ @ # X @ @ @ @ @ + @ + @ + + @ @ + + + @ + + + + + + + + + + + + + + + o @ @ @ @ # # # @ @ + @ + + + X o o o o O O O O O O X X O O X X O O + + + + + + + + + + O O . . ", +"2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , , 1 1 , , 1 , , , , 1 , , , , , , , , , , , , , : , > , , , > > , : : , : , , : , : , , > > : : > : > : : : : : : : : : : : : : : : - : : : - : : & - & : & : : & : : & - & - & & & & & & & & & & & & # & & & & & & # & # & & & & & # # # & & # @ & @ & @ @ # @ % # @ @ @ @ # # # @ @ @ & # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ + + + @ + + + @ @ + @ + @ + + + + + + + + + o + + X + + + @ + + + @ + + + + + + X o O O o X X O O O O O O O O O O . X O O . O O + + . O + . O o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , , 1 1 , 1 , , 1 , , , , , , , , , , , , : , , , > , , , > , , , , : , : : : , , : : > : > > : > : > : > : > : : : : : : : : : - : - - : : - : : : : & : & & : & : & & & - & & - & - & & & & & & & & # & # & # & # & & & # # & # & # & # & # & @ & # # & # & # # # # & # # @ & @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ + @ @ @ @ @ + @ + + @ + + + + + + @ + + + + + + + @ o @ + + X o o + + o + + X + X X + o + O + X X + X O O O O X O O X X O . o O O . . . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , > , : : , , , : , , , : : , , : : > > : : > > > : > > : : : : : : : : : : : : : - : : - - - - & : & & & : & & & & : & & - & & & & & & & & & & & & & & & & & & & & # # # & & & # & # # # & # # & & @ & # # # % # # % @ # # # # @ @ & @ @ @ @ @ @ @ @ @ @ X @ @ # @ @ @ @ + @ @ + @ + @ + + @ + + + + + + + + + + + + + + + o + o + o + + o + X + + o O O O O O o o o O O O O O O O o o O O X O X o . . . . . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 2 2 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 1 , 1 , 1 , , 1 1 , 1 , , , , , , , : , , : , , > , , > , , , : , , , : : , , : , : , , : , , : : : > : : > > : : : : : - : - : : : - - - : - : : : : & : : & : : & : & : & - & & - & & & & & & & & & & & & # & & # & & & & & # # & # & # & # & & @ # @ @ @ & % # % # # & # # # # @ @ # @ @ @ @ @ @ @ @ @ # # @ @ X # X @ + @ + + @ + @ @ + @ + + + @ + + @ + + + + o + X @ + + + + + + + o + + + o o X + + O + o + O X O X O O O O O X o o X O O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , , 1 , 1 1 , , 1 , , , , , , , , , , , , , , > , : , , : , : , : : > , : : , : : : , : : > : > : : > : : > : : : : : : : : - : : - - - - : & : & : & : & : & & & - & & : & - & & & & & & & & & & & # & # # & # & & # & # & # & # & # % # @ # # & % # % @ # % # # # # # # @ # # @ @ & @ @ @ # @ @ @ @ # @ # X @ @ + @ + @ @ + @ + + @ + + @ @ + + + + + + + + + + + o o @ + + + X + + o o X o + + O O O O o + + o O O O O O O O X O O O O o X o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 , 1 , 1 , 1 1 , , , 1 , , , , , , , , , , , , , , : , > , , > , , , , : > , > , , , : , : , , : : > > : > : > : : : > : : : : : : : - - : - - : - : - & : & : & : & : & & : & & - & & & & - & & & & & & & & # & & & & & & & # & # & & # & # # # & & # & @ & # % % % % # # # % @ # # # # # @ # @ @ @ @ @ @ @ @ @ @ # X # & X @ @ @ @ + @ @ + @ @ + @ + + + + + + @ + + + + + + + X @ o + X + X + o + + + X o + O + + O O X o o O O O O X O X o o O X . . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , , , , 1 , , , , , , , , , , , , , , , : , : , > > > > > > > > > , : , : : > : : > : > : : : > : : : : : : : - : - : : : : & : & : & : & : & - - & - & - & - - & & & & & & & & & & & & & # & & & # & & # & & # # # & # & @ & # # @ & # # % # @ # # # # # @ # # # @ @ # # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ + + + + + + + + + + + X + + + + + X + + X + + + + + X + O O O O O + + X X O O O O O O X O . o . . X O O O O . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 1 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , 1 , , 1 1 , , , , , , , , , , , , : , , : , , , , , , , , , : > > > > : > : , : > > > > > > : : > : : : : : : : : : : : - : - & - - : & : : & & : : & & & - & - & & & & & & & & & & & # & & # & # & & & # & & & # # & & & & # & # & @ & & # # % % & # & # # % @ % # # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ # X # # X + @ + + + @ + @ + + + + + @ + @ + + + + + + + + + + + + + + X + + X o O O + X o + O O O O O + o O O O O O O X X . o o . o . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 1 1 2 1 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , > , , , , , > > : > > : , > > > > : , : : > > : : > : : : : : : > : : : : : : : - - : - : : : : & : : & : & : & : & : & : & & - & & & & & & & & & & & & & % & & & & & # & # & & # # # # & # # # & @ & & @ & # @ # # # % % @ & & X @ @ @ @ @ @ @ # @ # @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + @ + @ @ + + + @ + + + + + + + o + X + X + o + o X + + + O + o O O + + o + o O O O X + X O O o O O o o . . . O O . . o o O . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 , 1 , 1 , , , , , 1 , , 1 , , , , , , : , , , : , : , , : , > , > , > > > > : : , : > : > > > : > > > : : : : : : : : - : : : : - : & : : : : & : & : & : & & : & & : - & & - & - & & & & & & & & & & & # & # & # & & & # & & & & # # & & @ & @ @ & # @ & # # % @ @ @ @ @ & & @ @ @ # # @ # @ @ @ @ @ @ @ @ X @ @ @ @ @ + + @ + + @ @ + + @ + + + @ + + + + + + + + + + + + + + + + + + o + o + + + O + O O X O X O O O X O X X O O . O . o o . . . O . . o o ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , : , > , > > , : , , > > > > > > > > > > : : > > > : : > : : : : : : : : : : : - : : - : & : & - - : & & : : & : & & & & & & & : & & & & & & & & & & & & & & # & & & # & & # & & # & & # # & # & @ # # # # # # # # # # @ & & @ @ @ @ & @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + + + @ + + @ + + + + + + + + + + + + + + o + + o + + o O O + O X O O O O + O O O O O O O O O O O O O X X . . O o . o . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , > > , , > , > , > , , , : , : > > > > : > > : > > > : : : : > : : > : > : : : : : : : : - - : : & : : - - - - : & & : & : : & : & & & & & & - & & & & & & # & & & & & & # # & # & & # # & # # & # & # @ & & @ @ & & # & # % # @ @ @ @ @ @ @ @ # @ # # @ @ @ @ X @ @ @ @ @ @ @ + @ + @ @ + @ @ + @ @ + + + + + + + @ + + + + + + + + + + + + + O + + O + O + X + + O O o O O + O O O O O O O O O O O O O X o O o . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , 1 , 1 , , 1 , 1 , , , , , , , , , : , , , , , , > , > , > : , : , > > > > > > > > > > > > > : > > : > : : > : : : : : : : - : - : - - : - - - - & - & : & & & : & & & : & - & - & & & & & & & & & # # & # & & # & & # & # & & # & # # & # & # @ & # # # # # @ # % # @ @ @ @ & @ & @ @ @ # @ @ @ @ @ # @ @ @ @ @ X @ @ + @ + @ + @ + @ + + + @ + + + @ + + + + + + + + + o + + o + o + + O + O + O + O O O + O O O O O O O O O O O X o O O . O . X O o o o o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , , , , > , , > , , > , > , > , , , : > > > > > > > > : : : > > : > : : : > : : : : : : : : : - : - : : - - : - - : - : & : & : & & : & & & & & & & & & & & & & & & & & & & & & & & # & # & & # & # & # # & # & # @ # & @ & @ # # # # & @ & @ @ @ @ @ # @ # @ # @ @ @ @ @ @ # X @ @ @ @ @ + @ + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + + + O O + O + O + O O + O + O + O O O O O X O X O O O . . O o O o . . . . . ", +"2 2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , , 1 , 1 , 1 1 , 1 1 , 1 , , , , , , , , , , , , , , : , , : , , : , , : , , , > , > > > : , : > > > : > : > : : > : : : > : : : : : > : : : : : - - - : : - - : - - - & : & & & : : - & - - & - & & & & & & & & & # & & & & # & # & # & & # & # & # & # # & # & # & & & # # & # # # # # # # # # # @ # # @ @ @ @ @ # @ @ @ @ X @ @ @ @ @ @ @ @ X @ X @ + @ + @ + + @ + + + @ + + + + + + O + + + + + + + + X O + O O O + O + O O o X O O O O O O O o o o X X o O X . O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 1 , 2 1 1 1 , 1 , 1 1 , , 1 , 1 , 1 1 , , 1 , , , , , , , , , , , , , , , , , > , : , : > , : , > , > > > > > > : > > : > : > : : > : : : : : : : : : : - - - - - - & : : & : & : : & & & & & & & - & & & & & & & & & & & & & # & & & & & & # & & # & # & # & # & # # # @ # # # # # # & # # # # # # # # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ X @ @ X @ + @ + + + @ + + @ + + + X + + + + + + + + + X o + O + + O + + O + O O O X + O o O O O O O O o O O O O o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 , , 1 1 1 1 , 1 , , 1 , 1 , , 1 , 1 , , , , , , , , : , , , , , : > , : , , : , : : , > > > : > > > : > : > : > : : > : > > : : : : : : : - - : : : - - : & : - - & : - & : & : & - & & & & & & & & & & & & & & & & & # # & & # & & # # & # & # & & # # & & # # & # # # # # # # # # # # @ @ # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ X @ @ @ + + + + + + + + + + + + + + + + + + + O o + + + + O + O O O O o O O O + + O O O O O O O O X O O X O o o O . O O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 , 1 , 1 1 1 , 1 , , 1 , 1 , , , , 1 , , , , , , , , , , , , , , , , : , , , , , , : , > , , : , : > > > : : > > > : > : > : : : : : : : : : : : : : : : - - - - : - - - - : & : & & : & & & - - & & - & & & & & & & & & # & & & & & # & & & # & # & # & # # # & @ # & # # & # # # & # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ @ X @ + @ @ + @ + @ + + + + + + + + O + + + O + + X + o + + o + + + O + O O o O + O O X O O O O O X O O X O O O O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , > , , > , , > : , : , > : , , : , : > > > : : > : > > : : > : : : : : : : - : : : - : - : - : - - - - - & : & & - & : : & - & & & & & & & & & & # & & & & & & & # # & & & # & & # & # & & # # & # # # # # & # # # & # # # # # & # # @ @ @ @ # @ # @ @ # @ @ @ X @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ @ + + + + + + + + + + + + X + + O + O + o + + X + O O O O O O O O + X O O O O O O O . . o . O O O O o O O o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , > , , > , , : , > , , , : , : , : > > > > > > > > > > : > : > : : : : : : : : : : - : : - - - : - - - - - - : & & : & : & & - & & & - & - & & & & & & & & & & & # & & & & # # & # & & # & # & # & # # & # # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ X + X @ @ X @ + + + + + + + + + + + + + + + + + + + + o + o + X + O + o O + X X + + O O O O O O X X O O O . X O . o . o o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , , , > , > > > , , : , : , , : > , > > > > > > : > > : : > : > : : : > : > : : : : : : - : : - - : - - - - - - : & : & & & : & & & & & - & & - & & & & & & & & & & & # & & # & # & & # & # # & & & # # # # # & # % & # # # # # # # # # # @ # # @ # # @ @ @ @ @ @ @ @ X @ @ @ @ @ X + @ X @ @ X @ + + @ + @ + + + + + + + + X + + + + O + + + + + + O + + O + X O O O O O + + O O O O O O O O . . o . o o . O o O o O O o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 , 1 , 1 1 , , , , , , , , , , , , , , > > , , , > , : , , , : , : , , : > > > > > : > > : > > : : : : > : > : : : : : : : : - : : - : - - : - - - - & : & : : & & & : - & - & & & & & & & & & & # & & # & & # & # & & & # & # & & # # # # & & # & # % % # # # # # # # # # # # # @ @ # # @ @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + + + + + @ + + + + + + + + + + + + + X + o + X + O o O + o + O + O O O O O O O O O O O . . O X . . . . o o o O O o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , : , , , , > , , > , , , : > , : : , : > > , > > : > > > > : : > : > : > : : : : : : : : : : : - : : : & : : & : : & : & : & : : & & & & - & - & & & & & & & & & & & & & & # & & & # & & # & & @ & # & # # # # & # & % # # % # # # & # # # # # # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + @ + @ X + @ + + + @ + + @ + + + + + + O @ O + O + + + O + + X + O O + O O O O O X + X O O O O O X X o O O . . o . . . O o . . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , , 1 , 1 , 1 , , 1 , 1 , , , , , , , > , , > , > , > : , , , , , , : , > > > > > > > : : > > > > : : : : > : : : > : : : : : : : - : : : & : : : & : & : & : & & : & : & & & & & & & & & & & & & & # # & & & & # & & # & & # # & # & & # & & & & # # & # % # # # # @ # # # # @ # @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X X @ @ @ @ + @ + @ + + + + + + + + @ + + + + + + + + O + o + + + O + X + O O O + O X + X O X O O O O O O O o . . . o . . . . o o o . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , > , , , , > : , : , > : , , > > , : > > > > > : > : > : : > > : : > : : : : : : - : - - : - : : : & : & & : : & : : & : & & - & - & & & & & & & & & & # & & & # & & & & # & & # & # & # & # # # # # # # # # # % # # # % # # # # # # # @ # @ # @ @ @ # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ + + @ + @ + + + @ + + + + + + + + + X + + + + + O + + O + O O + X O + + O + X o + + o O O O X O X X o . O o . o o o o . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , : , , > , , , , > , > > , : : > > > > > > > > : > : > > : > : : > : : : : - : : : : - - : & & - : : - : & : & & & & & : & & - & & : & & & & & & & & & & & & & # & # & & & # & & # & # & & # & # # & & # # # # & & # # # # # # # # # # @ @ @ # @ @ @ @ @ @ X @ @ @ @ X @ @ X @ @ @ X @ + @ + + @ + + @ + + + + + + + + + + + O + + + + O O + + X + O + O O O + X O O O O O O O X O O X o o . . . . o . o . o . o . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , , , 1 , , , , 1 , , , , , , , , , , , , , : , , : : , > , > , : , : > : > > : : > > > : > : : > : : : : : : : : : - : : : : : : : : : & : & : : & : : & : & & & & & & - & & & & & & & & & & & & & & # # & & # & & # & # & # & & # & & # # # # # # % # % # # # # # # @ # # # # @ @ @ # @ @ # @ @ @ @ @ X X @ + @ + @ @ + + @ + + + + + @ + + + + + + + + + + + X + + + + + X + + X O O + O O O O O O O + o O O O + O O . . O . o o . . . . . . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 , , , , 1 , , , , , , , , , , , , , , , , , : , , : , : > : , : , > > > : > > : : > : > : : : > : : : : : : : : : : : - : : & : & : & & : & & : & : & & & & - : & & & & & & & & & & & # & & & # # & & & # & # # & & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ # @ # # @ @ @ @ @ @ @ @ # @ @ + @ @ @ + @ @ + + @ @ + + + @ + + + + + + + + + + + + O + X + + + X O + + O + X + + O + O O + X O O O O O . O . O . . o o . . . o o . . . O O ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 , 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 1 , , , , , , 1 , , , , , , , : , : , : , , , : , > > > : > , : > > > > > > > : : : > : > : : > : : : : : : : : & : : & : & : - : & : & & : : & : & : & - & & - - & & & & & & & & & & & & # & & & & & # & & & & # & & # & # & # & # # & & # % # # # % % # # # # # @ @ @ # # @ @ @ @ @ @ @ X # @ @ @ X @ @ @ @ + @ + @ @ @ @ + + + + @ + @ + + + + + + + + + + + + O + + O + + O O + + O O O + O O O o O O O O O O O . . o o . . . . . o o o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , 1 , , , 1 , , , , , , , , , , : , , , , , , > > , , > , , > , , : , > > > : > : > > > > : : > : > : : > : : : : : : : : : : : : - - : & : - : & & : & : & & - & & & - & & & & & & & # & & & & & & & # # & & # & # # & # # # & # & # # # & # # # # % % % % @ # # # # # # # # @ # @ # @ @ @ @ @ @ @ # @ @ # @ @ + + @ + @ + + + + @ + @ + + + + + + + + + + + + + + X + + O + + + O + + O O + O + O O O O O o O O O O O O . o . O . O o . . . o . o o O O ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 1 2 1 2 , 1 1 1 1 1 , 2 2 , 1 1 1 , 1 1 , , 1 1 , , 1 1 , , , , , 1 , , , , , , , , > , , > , > , > , : > , : , > : : , : > > > > > > : > > : : > : : : > : : : > : : : : : : - : - : - : & & : - & : : : & : & & : : & & & & & & : & & & & & & & & # & & & # & # & & & & # & # & # # & # # # & # & # # & # # # # # # # # # # # # @ @ - @ @ @ @ o - + o - @ @ @ @ @ @ @ + @ + + @ @ + @ + @ + @ + @ + + + + + + + + + + + + + + + + o + + X X + O + + X + + O O o O O O O O X X O X O X O o o O o O X X O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 1 2 1 1 2 1 2 1 1 2 , , 1 1 1 , 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , > , > , , , , , , : , , , > , > , : , > : > > : > > : > : : > : > : : : : : : : : : - : - - : : : : - : : & & & : : : & & : & : & & & & & & & & & & & & & & & & & & & & # # & & # & # & # # & & # # # & # # # # # & # # # # # # # # @ @ # + # @ o @ - o @ @ + @ @ @ + @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + X + + + o + o + + O + O O X X O O O + O O O O O + O O o X O O O O X O O X O o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 1 1 2 , 2 1 2 1 1 1 2 , 1 , , 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , , , , , , , , 1 , , , , > , , , > , > > , : , : : , , : > : , : : > > > > : > : > > : : : > : : : : : : : : : : : - : - : - : : & & : & & : & : & & & & & & : & & & & & & & & & & & & & & & # & & # # & & & # & # & # & & & # & & # # # # & # & # # # & # # # # # # # # + @ @ - @ - o @ @ @ @ @ @ @ + @ + @ @ + @ @ + + @ + @ + + + + + @ + + + + + + + + X X + + + + + + o o + O O O o + o X O O O + O O O O O O O X X o o O X o O X o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 2 1 1 1 1 2 1 1 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , 1 , 1 , , , , , , , , , , , > , , , > , , , > , , > > , > > : , > > > > > > : > : : > > : : > : : > : : : : : - : : - : : : & : : - : & : & : & : & : : & & & & & & & & & & & & & & # & # & & & # & & & # & # & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ + - @ @ @ o - + @ @ @ @ @ + o - + @ + @ @ + @ + + @ + + + @ @ + + + + + + + + + + + + + X + o + o + + O + + O + X + + o O O O O O O O O O O X X . . . . o O o O X . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 1 1 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , , , > > , , : , , , : > > , > , : > > : > > : > > : > > : > : : : : : : > : : - : : : - : & : : & : & : & : & : & & : & & & & & & : & & & & & & & & & # & & & & & & # # & & & # & # & # & # & # # # # # & & # # # & # # # # # # # # # # @ + + - o + + @ o + @ @ + @ @ + + @ @ + @ @ + + @ @ @ + + + @ + + + + + + + + + + + X + + + + + X + X + O + O o O X + O O O O O O O O O O X O o . o O . . o o o . o . X O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 , , 1 1 1 1 1 , , 1 , 1 , , , , 1 1 , 1 1 1 , , , , , , , , , , : , , , > , , : , > , > , : : , : > > : > > > > : > > : : > : > > > : : : & : : : - : - - : - & : - - - : : & & : : & : & & : & & & & & & & & & # & & & & & & # & & & & & & # & & & # & # # # & & # & # # # # # # # # # # # # # # # # @ # - + o - - @ @ - - o @ @ @ + @ @ @ + + @ @ + @ + + + + @ + + + + + + + + + + + + + + + + X + X + X + O + O + + o O O + + + O + O O O O O o X O . X o o O o O X O o . . O . O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 1 1 1 1 2 1 2 , 1 1 1 2 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , 1 , , , , , , , , , , , , , , , : , > , , > > > > , > , > : , : : , : , , : : > > : : : : > : > : : : : : : : : : : : - : : - : : & : & : & & & : & & : & & : & & : & : & & & & & & & & & & # & # & # & # # # # & # # & & & & # # # & # & # & # & # # # # # # # # # # @ # # @ + @ @ @ @ @ @ o - @ @ @ @ + @ + @ @ + @ + @ + @ + @ + + @ + + + @ + + + + + + + X + + + + + X + O + O + o + + + X O O O + O O O O O O X O X . . . . o X O X . o . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 2 1 2 1 1 1 1 1 2 , 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , 1 , , , , , , > , , , , > , , , , , , , , , : , : > , > , , : , > : > > > : > > > > : : : : : : : > : : : : : : : : - : : - : - : - - & : : & & & : & : & & & & & & & & & & & & & & & & & & & & & & & & & # & & # # # # & & # # & # # # # # # # # # & # # # # # # @ # @ - @ @ @ @ @ @ @ @ + @ @ @ @ @ # + @ @ @ + + @ + @ + + + + @ + + + + + + + + + + + + + o + + + X + O + O + o X O O + O O O O O O O O O O O O o . o . O o X . . . . O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 1 1 1 1 2 1 2 , 1 2 1 2 , 1 1 2 , 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , 1 1 , , , , , , , , , , > , > , , , > > > , : , , , > , > : , , : > : , > > : > : > > > : : : : > > : : : : : : : : & : & : : & : - - - - & : & : & : - & & & : & & & & & & & & & & & # & & # & & & # & # # & & # # & # & & # # & # # # # # # # # # # # # # # # # # # # # - o # @ @ @ @ @ + @ @ @ @ + @ + + @ @ @ + + + + @ + + + + + @ + + @ + + + + + + + + o + o + + + O + X + O O + + O + O + O + O O O O O O O O O O X . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 , 2 , 1 , , 1 1 , 1 1 , 1 , , 1 , , , , , , , 1 , 1 , , , , , , , , , > , , , > , , , : > , : > , : : , > > : > > : > : : : : > > > : : : : : : : : : : : : : : : : - : - - - - - & : & & & - - : & & & & & & & & & & & & & & & & & & # & & & & & # & & & # & # & # & # # & & # & # & # # # # # # # # # # @ # # - @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ + + @ + @ + + + + + + + + + + + + + + + + + o + X + + + + O O + O O O O O O O O O O X O O O X O X . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 2 2 , 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 1 , 1 , , 1 1 , 1 , , , , , , , , > , , , > > > > > : , : , > , , > , > > : : , > > > > : > > > : : : : > : : : : : : : : : : : & : : & - : & : - - - : : & - & & - & & & & - & & - & & & & & # & & & & & & # & # & & # & # # & # & # & # # & # # # # # & # & # # # # # # # # @ # @ o @ @ # # @ @ @ @ @ @ @ @ + @ @ + @ @ + @ + + + + + + + + + + + + + + + + + + o + + + o o + o + + O + O + O O O X + X + + O O + O O X O O O X O O X o o o o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 1 2 1 2 1 2 1 2 1 1 1 1 2 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , , > , , : , , > , : : , : , : , > : , : > : > : > : : > : > : > : : : : : : : : : : : : : : : & : : & - : & & : & : & - & : & : & & & & & & & & & & & & # & & # & & & & & & & # & # # & & # # & # # & # & # # # # # # # # # # # # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ @ @ + @ @ + @ @ @ + @ + + + + + + + + + + + + + + + + + X + O + O + + + O O O O O O O X O O O O O O O X X O . . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , , 1 , 1 , 1 , , , , 1 , , , , , , , , > , > > > , , , : , , : , > : , > , : > > > : > : > > : > : : > : > : : > : : : : : : : & : & & : : & : & & - & : & : - & - & - & - & & - & & & & & & & & # & & & & # & & # & # & & # & # & # # & & # # # # & # # & # # # & # # # # # # # # # # @ # @ # @ @ @ @ @ @ + @ @ @ @ @ # @ + + + @ + + + + + + + + @ + @ @ + + + + + + + + o + + + X + + O + + O + O + O + O O X O X O O O X o o O O o O O X o . o . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , , , , , , , , , , , , > , > , , : , , , > , : , : , > > : , > : : > : : > > : : : : : : : : : : : : : : : : : : : : - : : : : & : & - & & - & - & & & & & & & & & & & & & & & & & & & # & # & # # & # & # & & & # # & # # # # & # # & # # # # # # # # # @ @ @ # @ @ @ @ @ @ @ + @ @ @ @ + + @ + @ @ + @ + @ @ @ @ + + @ + + + + + + + + + + + o + + + o + + X O + O O + O O O O O O O + O O O O O O O o O O O o o o . o . . . . . ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 2 1 2 2 2 1 1 1 2 , 2 1 1 1 1 1 1 2 , 1 1 , 1 1 1 1 1 1 , 1 1 , , , , , 1 , , , , , , , , , , , , , , , , > , , : , > , : : , , : , : : , , : : > > > > : > : : > : > > : : : : : : : : : & & : : & & : - - & : & & & - - & - & - & & & - & & & & & & & & & & # & & # & & & # # & & # & # & # # # & # # # & # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + @ @ + @ + + + @ + @ + + + + + + + + + + + + + + + + + + + X + + + X O O + + O X O O O + X O X O O O O O O O O O O . . o o . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 2 1 1 1 1 , 1 , , , 1 , , , 1 , 1 , , , , , , , , , , > , , > , > > , , > , , > , > > , , : , : > > : , : > > : : > > : > : : : : : : : : : : : - : : : : & : : : & : - - : : & : & - - - & & - - & & & & & & & & & & & & & & & & & # & # & # & & # & # & # # & # # # & # # # & # # # # # # # # # # # # # # @ @ # @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + o + + o + o + + X X + O + O + O + O + O X O O O O O O O O O O O . o . . . . . o o " +}; diff --git a/branches/pcsx2_0.9.1/Linux/Config.c b/branches/pcsx2_0.9.1/Linux/Config.c new file mode 100644 index 0000000..3f65524 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/Config.c @@ -0,0 +1,137 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "Linux.h" + +#define GetValue(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%s", var); \ + } + +#define GetValuel(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%x", &var); \ + } + +#define SetValue(name, var) \ + fprintf (f,"%s = %s\n", name, var); + +#define SetValuel(name, var) \ + fprintf (f,"%s = %x\n", name, var); + +int LoadConfig(PcsxConfig *Conf) { + struct stat buf; + FILE *f; + int size; + char *data,*tmp; + + if (stat(cfgfile, &buf) == -1) return -1; + size = buf.st_size; + + f = fopen(cfgfile,"r"); + if (f == NULL) return -1; + + data = (char*)malloc(size); + if (data == NULL) return -1; + + fread(data, 1, size, f); + fclose(f); + + GetValue("Bios", Config.Bios); + GetValue("GS", Config.GS); + GetValue("PAD1", Config.PAD1); + GetValue("PAD2", Config.PAD2); + GetValue("SPU2", Config.SPU2); + GetValue("CDVD", Config.CDVD); + GetValue("DEV9", Config.DEV9); + GetValue("USB", Config.USB); + GetValue("FW", Config.FW); + GetValue("Mcd1", Config.Mcd1); + GetValue("Mcd2", Config.Mcd2); + GetValue("PluginsDir", Config.PluginsDir); + GetValue("BiosDir", Config.BiosDir); + GetValuel("Cpu", Config.Cpu); + GetValuel("PsxOut", Config.PsxOut); + GetValuel("RegCaching", Config.Regcaching); + GetValuel("Patch", Config.Patch); + GetValuel("VUrec", Config.VUrec); +// GetValuel("PadHack", Config.PadHack); + GetValuel("varLog", varLog); + Config.Lang[0] = 0; + GetValue("Lang", Config.Lang); + + free(data); + +#ifdef ENABLE_NLS + if (Config.Lang[0]) { + extern int _nl_msg_cat_cntr; + + setenv("LANGUAGE", Config.Lang, 1); + ++_nl_msg_cat_cntr; + } +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + FILE *f; + + f = fopen(cfgfile,"w"); + if (f == NULL) return; + + SetValue("Bios", Config.Bios); + SetValue("GS", Config.GS); + SetValue("PAD1", Config.PAD1); + SetValue("PAD2", Config.PAD2); + SetValue("SPU2", Config.SPU2); + SetValue("CDVD", Config.CDVD); + SetValue("DEV9", Config.DEV9); + SetValue("USB", Config.USB); + SetValue("FW", Config.FW); + SetValue("Mcd1", Config.Mcd1); + SetValue("Mcd2", Config.Mcd2); + SetValue("PluginsDir", Config.PluginsDir); + SetValue("BiosDir", Config.BiosDir); + SetValuel("Cpu", Config.Cpu); + SetValuel("PsxOut", Config.PsxOut); + SetValuel("RegCaching", Config.Regcaching); + SetValuel("Patch", Config.Patch); + SetValuel("VUrec", Config.VUrec); +// SetValuel("PadHack", Config.PadHack); + SetValuel("varLog", varLog); + SetValue("Lang", Config.Lang); + + fclose(f); + + return; +} diff --git a/branches/pcsx2_0.9.1/Linux/GladeCalls.c b/branches/pcsx2_0.9.1/Linux/GladeCalls.c new file mode 100644 index 0000000..d8fa54e --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeCalls.c @@ -0,0 +1,828 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + + +void +OnDestroy (GtkObject *object, + gpointer user_data) +{ + +} + + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_Close (GtkButton *button, + gpointer user_data) +{ + +} + + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + + return FALSE; +} + + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Step (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Go (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Log (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/branches/pcsx2_0.9.1/Linux/GladeCalls.h b/branches/pcsx2_0.9.1/Linux/GladeCalls.h new file mode 100644 index 0000000..8c1a3db --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeCalls.h @@ -0,0 +1,411 @@ +#include + + +void +OnDestroy (GtkObject *object, + gpointer user_data); + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data); + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data); + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_Close (GtkButton *button, + gpointer user_data); + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_Step (GtkButton *button, + gpointer user_data); + +void +OnDebug_Go (GtkButton *button, + gpointer user_data); + +void +OnDebug_Log (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data); + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data); + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data); + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data); + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data); + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data); + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data); + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data); + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data); + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data); + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data); diff --git a/branches/pcsx2_0.9.1/Linux/GladeFuncs.c b/branches/pcsx2_0.9.1/Linux/GladeFuncs.c new file mode 100644 index 0000000..c6ccdbe --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeFuncs.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "GladeFuncs.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists (".pixmaps", filename); + } + + if (!found_filename) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning (_("Error loading pixmap file: %s"), found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/branches/pcsx2_0.9.1/Linux/GladeFuncs.h b/branches/pcsx2_0.9.1/Linux/GladeFuncs.h new file mode 100644 index 0000000..86a3134 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeFuncs.h @@ -0,0 +1,61 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/branches/pcsx2_0.9.1/Linux/GladeGui.c b/branches/pcsx2_0.9.1/Linux/GladeGui.c new file mode 100644 index 0000000..e01cf7f --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeGui.c @@ -0,0 +1,3008 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +GtkWidget* +create_MainWindow (void) +{ + GtkWidget *MainWindow; + GtkWidget *vbox1; + GtkWidget *GtkMenuBar_Menu; + GtkWidget *GtkMenuItem_File; + GtkWidget *GtkMenuItem_File_menu; + GtkAccelGroup *GtkMenuItem_File_menu_accels; + GtkWidget *run_cd1; + GtkWidget *GtkMenuItem_LoadElf; + GtkWidget *separator2; + GtkWidget *states1; + GtkWidget *states1_menu; + GtkAccelGroup *states1_menu_accels; + GtkWidget *load1; + GtkWidget *load1_menu; + GtkAccelGroup *load1_menu_accels; + GtkWidget *slot_1; + GtkWidget *slot_3; + GtkWidget *slot_4; + GtkWidget *slot_5; + GtkWidget *slot_2; + GtkWidget *other1; + GtkWidget *save1; + GtkWidget *save1_menu; + GtkAccelGroup *save1_menu_accels; + GtkWidget *slot_6; + GtkWidget *slot_7; + GtkWidget *slot_8; + GtkWidget *slot_9; + GtkWidget *slot_10; + GtkWidget *other2; + GtkWidget *GtkMenuItem_Exit; + GtkWidget *GtkMenuItem_Emulator; + GtkWidget *GtkMenuItem_Emulator_menu; + GtkAccelGroup *GtkMenuItem_Emulator_menu_accels; + GtkWidget *GtkMenuItem_Run; + GtkWidget *GtkMenuItem_Reset; + GtkWidget *GtkMenuItem_Arguments; + GtkWidget *GtkMenuItem_Configuration; + GtkWidget *GtkMenuItem_Configuration_menu; + GtkAccelGroup *GtkMenuItem_Configuration_menu_accels; + GtkWidget *GtkMenuItem_PluginsBios; + GtkWidget *separator3; + GtkWidget *GtkMenuItem_Graphics; + GtkWidget *GtkMenuItem_Controllers; + GtkWidget *GtkMenuItem_Sound; + GtkWidget *GtkMenuItem_Cdvdrom; + GtkWidget *GtkMenuItem_Dev9; + GtkWidget *separator4; + GtkWidget *GtkMenuItem_Cpu; + GtkWidget *GtkMenuItem_Language; + GtkWidget *GtkMenuItem_Debug; + GtkWidget *GtkMenuItem_Debug_menu; + GtkAccelGroup *GtkMenuItem_Debug_menu_accels; + GtkWidget *GtkMenuItem_EnterDebugger; + GtkWidget *GtkMenuItem_Logging; + GtkWidget *GtkMenuItem_Help; + GtkWidget *GtkMenuItem_Help_menu; + GtkAccelGroup *GtkMenuItem_Help_menu_accels; + GtkWidget *GtkMenuItem_About; + + MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (MainWindow), "MainWindow", MainWindow); + gtk_widget_set_usize (MainWindow, -2, 200); + gtk_window_set_title (GTK_WINDOW (MainWindow), _("PCSX")); + gtk_window_set_position (GTK_WINDOW (MainWindow), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MainWindow), FALSE, FALSE, FALSE); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (MainWindow), vbox1); + + GtkMenuBar_Menu = gtk_menu_bar_new (); + gtk_widget_ref (GtkMenuBar_Menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuBar_Menu", GtkMenuBar_Menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuBar_Menu); + gtk_box_pack_start (GTK_BOX (vbox1), GtkMenuBar_Menu, FALSE, FALSE, 0); + + GtkMenuItem_File = gtk_menu_item_new_with_label (_("File")); + gtk_widget_ref (GtkMenuItem_File); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File", GtkMenuItem_File, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_File); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_File); + + GtkMenuItem_File_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_File_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File_menu", GtkMenuItem_File_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_File), GtkMenuItem_File_menu); + GtkMenuItem_File_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_File_menu)); + + run_cd1 = gtk_menu_item_new_with_label (_("Run CD")); + gtk_widget_ref (run_cd1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "run_cd1", run_cd1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (run_cd1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), run_cd1); + + GtkMenuItem_LoadElf = gtk_menu_item_new_with_label (_("Load Elf")); + gtk_widget_ref (GtkMenuItem_LoadElf); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_LoadElf", GtkMenuItem_LoadElf, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_LoadElf); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_LoadElf); + + separator2 = gtk_menu_item_new (); + gtk_widget_ref (separator2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator2", separator2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator2); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), separator2); + gtk_widget_set_sensitive (separator2, FALSE); + + states1 = gtk_menu_item_new_with_label (_("States")); + gtk_widget_ref (states1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1", states1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (states1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), states1); + + states1_menu = gtk_menu_new (); + gtk_widget_ref (states1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1_menu", states1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (states1), states1_menu); + states1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (states1_menu)); + + load1 = gtk_menu_item_new_with_label (_("Load")); + gtk_widget_ref (load1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1", load1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (load1); + gtk_container_add (GTK_CONTAINER (states1_menu), load1); + + load1_menu = gtk_menu_new (); + gtk_widget_ref (load1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1_menu", load1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (load1), load1_menu); + load1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (load1_menu)); + + slot_1 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_1", slot_1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_1); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_1); + + slot_3 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_3", slot_3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_3); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_3); + + slot_4 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_4", slot_4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_4); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_4); + + slot_5 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_5); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_5", slot_5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_5); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_5); + + slot_2 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_2", slot_2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_2); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_2); + + other1 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other1", other1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other1); + gtk_container_add (GTK_CONTAINER (load1_menu), other1); + + save1 = gtk_menu_item_new_with_label (_("Save")); + gtk_widget_ref (save1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1", save1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (save1); + gtk_container_add (GTK_CONTAINER (states1_menu), save1); + + save1_menu = gtk_menu_new (); + gtk_widget_ref (save1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1_menu", save1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (save1), save1_menu); + save1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (save1_menu)); + + slot_6 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_6); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_6", slot_6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_6); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_6); + + slot_7 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_7); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_7", slot_7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_7); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_7); + + slot_8 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_8); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_8", slot_8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_8); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_8); + + slot_9 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_9", slot_9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_9); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_9); + + slot_10 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_10); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_10", slot_10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_10); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_10); + + other2 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other2", other2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other2); + gtk_container_add (GTK_CONTAINER (save1_menu), other2); + + GtkMenuItem_Exit = gtk_menu_item_new_with_label (_("Exit")); + gtk_widget_ref (GtkMenuItem_Exit); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Exit", GtkMenuItem_Exit, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Exit); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_Exit); + + GtkMenuItem_Emulator = gtk_menu_item_new_with_label (_("Emulator")); + gtk_widget_ref (GtkMenuItem_Emulator); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator", GtkMenuItem_Emulator, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Emulator); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Emulator); + + GtkMenuItem_Emulator_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Emulator_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator_menu", GtkMenuItem_Emulator_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Emulator), GtkMenuItem_Emulator_menu); + GtkMenuItem_Emulator_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Emulator_menu)); + + GtkMenuItem_Run = gtk_menu_item_new_with_label (_("Run")); + gtk_widget_ref (GtkMenuItem_Run); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Run", GtkMenuItem_Run, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Run); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Run); + + GtkMenuItem_Reset = gtk_menu_item_new_with_label (_("Reset")); + gtk_widget_ref (GtkMenuItem_Reset); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Reset", GtkMenuItem_Reset, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Reset); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Reset); + + GtkMenuItem_Arguments = gtk_menu_item_new_with_label (_("Arguments")); + gtk_widget_ref (GtkMenuItem_Arguments); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Arguments", GtkMenuItem_Arguments, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Arguments); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Arguments); + + GtkMenuItem_Configuration = gtk_menu_item_new_with_label (_("Configuration")); + gtk_widget_ref (GtkMenuItem_Configuration); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration", GtkMenuItem_Configuration, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Configuration); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Configuration); + + GtkMenuItem_Configuration_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Configuration_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration_menu", GtkMenuItem_Configuration_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Configuration), GtkMenuItem_Configuration_menu); + GtkMenuItem_Configuration_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Configuration_menu)); + + GtkMenuItem_PluginsBios = gtk_menu_item_new_with_label (_("Plugins & Bios")); + gtk_widget_ref (GtkMenuItem_PluginsBios); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_PluginsBios", GtkMenuItem_PluginsBios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_PluginsBios); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_PluginsBios); + + separator3 = gtk_menu_item_new (); + gtk_widget_ref (separator3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator3", separator3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator3); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator3); + gtk_widget_set_sensitive (separator3, FALSE); + + GtkMenuItem_Graphics = gtk_menu_item_new_with_label (_("Graphics")); + gtk_widget_ref (GtkMenuItem_Graphics); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Graphics", GtkMenuItem_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Graphics); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Graphics); + + GtkMenuItem_Controllers = gtk_menu_item_new_with_label (_("Controllers")); + gtk_widget_ref (GtkMenuItem_Controllers); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Controllers", GtkMenuItem_Controllers, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Controllers); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Controllers); + + GtkMenuItem_Sound = gtk_menu_item_new_with_label (_("Sound")); + gtk_widget_ref (GtkMenuItem_Sound); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Sound", GtkMenuItem_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Sound); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Sound); + + GtkMenuItem_Cdvdrom = gtk_menu_item_new_with_label (_("Cdvdrom")); + gtk_widget_ref (GtkMenuItem_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cdvdrom", GtkMenuItem_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cdvdrom); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cdvdrom); + + GtkMenuItem_Dev9 = gtk_menu_item_new_with_label (_("Dev9")); + gtk_widget_ref (GtkMenuItem_Dev9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Dev9", GtkMenuItem_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Dev9); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Dev9); + + separator4 = gtk_menu_item_new (); + gtk_widget_ref (separator4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator4", separator4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator4); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator4); + gtk_widget_set_sensitive (separator4, FALSE); + + GtkMenuItem_Cpu = gtk_menu_item_new_with_label (_("Cpu")); + gtk_widget_ref (GtkMenuItem_Cpu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cpu", GtkMenuItem_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cpu); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cpu); + + GtkMenuItem_Language = gtk_menu_item_new_with_label (_("Language")); + gtk_widget_ref (GtkMenuItem_Language); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Language", GtkMenuItem_Language, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Language); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Language); + + GtkMenuItem_Debug = gtk_menu_item_new_with_label (_("Debug")); + gtk_widget_ref (GtkMenuItem_Debug); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug", GtkMenuItem_Debug, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Debug); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Debug); + + GtkMenuItem_Debug_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Debug_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug_menu", GtkMenuItem_Debug_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Debug), GtkMenuItem_Debug_menu); + GtkMenuItem_Debug_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Debug_menu)); + + GtkMenuItem_EnterDebugger = gtk_menu_item_new_with_label (_("Enter Debugger ...")); + gtk_widget_ref (GtkMenuItem_EnterDebugger); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_EnterDebugger", GtkMenuItem_EnterDebugger, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_EnterDebugger); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_EnterDebugger); + + GtkMenuItem_Logging = gtk_menu_item_new_with_label (_("Logging")); + gtk_widget_ref (GtkMenuItem_Logging); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Logging", GtkMenuItem_Logging, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Logging); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_Logging); + + GtkMenuItem_Help = gtk_menu_item_new_with_label (_("Help")); + gtk_widget_ref (GtkMenuItem_Help); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help", GtkMenuItem_Help, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Help); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Help); + + GtkMenuItem_Help_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Help_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help_menu", GtkMenuItem_Help_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Help), GtkMenuItem_Help_menu); + GtkMenuItem_Help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Help_menu)); + + GtkMenuItem_About = gtk_menu_item_new_with_label (_("About PCSX2")); + gtk_widget_ref (GtkMenuItem_About); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_About", GtkMenuItem_About, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_About); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Help_menu), GtkMenuItem_About); + + gtk_signal_connect (GTK_OBJECT (MainWindow), "destroy", + GTK_SIGNAL_FUNC (OnDestroy), + NULL); + gtk_signal_connect (GTK_OBJECT (run_cd1), "activate", + GTK_SIGNAL_FUNC (OnFile_RunCD), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_LoadElf), "activate", + GTK_SIGNAL_FUNC (OnFile_LoadElf), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_1), "activate", + GTK_SIGNAL_FUNC (OnStates_Load1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_3), "activate", + GTK_SIGNAL_FUNC (OnStates_Load2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_4), "activate", + GTK_SIGNAL_FUNC (OnStates_Load3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_5), "activate", + GTK_SIGNAL_FUNC (OnStates_Load4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_2), "activate", + GTK_SIGNAL_FUNC (OnStates_Load5), + NULL); + gtk_signal_connect (GTK_OBJECT (other1), "activate", + GTK_SIGNAL_FUNC (OnStates_LoadOther), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_6), "activate", + GTK_SIGNAL_FUNC (OnStates_Save1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_7), "activate", + GTK_SIGNAL_FUNC (OnStates_Save2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_8), "activate", + GTK_SIGNAL_FUNC (OnStates_Save3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_9), "activate", + GTK_SIGNAL_FUNC (OnStates_Save4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_10), "activate", + GTK_SIGNAL_FUNC (OnStates_Save5), + NULL); + gtk_signal_connect (GTK_OBJECT (other2), "activate", + GTK_SIGNAL_FUNC (OnStates_SaveOther), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Exit), "activate", + GTK_SIGNAL_FUNC (OnFile_Exit), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Run), "activate", + GTK_SIGNAL_FUNC (OnEmu_Run), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Reset), "activate", + GTK_SIGNAL_FUNC (OnEmu_Reset), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Arguments), "activate", + GTK_SIGNAL_FUNC (OnEmu_Arguments), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_PluginsBios), "activate", + GTK_SIGNAL_FUNC (OnConf_Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Graphics), "activate", + GTK_SIGNAL_FUNC (OnConf_Gs), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Controllers), "activate", + GTK_SIGNAL_FUNC (OnConf_Pads), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Sound), "activate", + GTK_SIGNAL_FUNC (OnConf_Spu2), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cdvdrom), "activate", + GTK_SIGNAL_FUNC (OnConf_Cdvd), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Dev9), "activate", + GTK_SIGNAL_FUNC (OnConf_Dev9), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cpu), "activate", + GTK_SIGNAL_FUNC (OnConf_Cpu), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_EnterDebugger), "activate", + GTK_SIGNAL_FUNC (OnDebug_Debugger), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Logging), "activate", + GTK_SIGNAL_FUNC (OnDebug_Logging), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_About), "activate", + GTK_SIGNAL_FUNC (OnHelp_About), + NULL); + + return MainWindow; +} + +GtkWidget* +create_AboutDlg (void) +{ + GtkWidget *AboutDlg; + GtkWidget *vbox2; + GtkWidget *packer1; + GtkWidget *hbox1; + GtkWidget *vbox4; + GtkWidget *GtkAbout_LabelVersion; + GtkWidget *frame1; + GtkWidget *vbox6; + GtkWidget *GtkAbout_LabelAuthors; + GtkWidget *pixmap1; + GtkWidget *frame2; + GtkWidget *vbox5; + GtkWidget *GtkAbout_LabelGreets; + GtkWidget *hbuttonbox1; + GtkWidget *GtkButton_Ok; + + AboutDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (AboutDlg), "AboutDlg", AboutDlg); + gtk_container_set_border_width (GTK_CONTAINER (AboutDlg), 10); + gtk_window_set_title (GTK_WINDOW (AboutDlg), _("Pcsx About")); + gtk_window_set_position (GTK_WINDOW (AboutDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (AboutDlg), FALSE, FALSE, FALSE); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (AboutDlg), vbox2); + + packer1 = gtk_packer_new (); + gtk_widget_ref (packer1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "packer1", packer1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (packer1); + gtk_box_pack_start (GTK_BOX (vbox2), packer1, FALSE, FALSE, 0); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox4); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox4", vbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox4); + gtk_box_pack_start (GTK_BOX (hbox1), vbox4, TRUE, TRUE, 0); + + GtkAbout_LabelVersion = gtk_label_new (_("PCSX2\r\r\r\nVersion x.x")); + gtk_widget_ref (GtkAbout_LabelVersion); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelVersion", GtkAbout_LabelVersion, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelVersion); + gtk_box_pack_start (GTK_BOX (vbox4), GtkAbout_LabelVersion, FALSE, FALSE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_ref (frame1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame1", frame1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox4), frame1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame1), 5); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox6); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox6", vbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (frame1), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + GtkAbout_LabelAuthors = gtk_label_new (_("written by...")); + gtk_widget_ref (GtkAbout_LabelAuthors); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelAuthors", GtkAbout_LabelAuthors, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelAuthors); + gtk_box_pack_start (GTK_BOX (vbox6), GtkAbout_LabelAuthors, FALSE, FALSE, 0); + + pixmap1 = create_pixmap (AboutDlg, "pcsxAbout.xpm"); + gtk_widget_ref (pixmap1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "pixmap1", pixmap1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (pixmap1); + gtk_box_pack_start (GTK_BOX (hbox1), pixmap1, TRUE, TRUE, 0); + + frame2 = gtk_frame_new (NULL); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox2), frame2, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame2), 5); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox5); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox5", vbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (frame2), vbox5); + gtk_container_set_border_width (GTK_CONTAINER (vbox5), 5); + + GtkAbout_LabelGreets = gtk_label_new (_("greets to...")); + gtk_widget_ref (GtkAbout_LabelGreets); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelGreets", GtkAbout_LabelGreets, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelGreets); + gtk_box_pack_start (GTK_BOX (vbox5), GtkAbout_LabelGreets, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox1, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnHelpAbout_Ok), + NULL); + + return AboutDlg; +} + +GtkWidget* +create_ConfDlg (void) +{ + GtkWidget *ConfDlg; + GtkWidget *vbox12; + GtkWidget *table2; + GtkWidget *GtkCombo_Pad1; + GtkWidget *combo_entry4; + GtkWidget *GtkCombo_Pad2; + GtkWidget *combo_entry5; + GtkWidget *hbuttonbox6; + GtkWidget *GtkButton_PAD2configure; + GtkWidget *GtkButton_PAD2test; + GtkWidget *GtkButton_PAD2about; + GtkWidget *hbuttonbox7; + GtkWidget *GtkButton_PAD1configure; + GtkWidget *GtkButton_PAD1test; + GtkWidget *GtkButton_PAD1about; + GtkWidget *hbuttonbox8; + GtkWidget *GtkButton_GSconfigure; + GtkWidget *GtkButton_GStest; + GtkWidget *GtkButton_GSabout; + GtkWidget *GtkLabel_Graphics; + GtkWidget *GtkLabel_FirstController; + GtkWidget *GtkLabel_SecondController; + GtkWidget *GtkCombo_Gs; + GtkWidget *combo_entry2; + GtkWidget *GtkLabel_Sound; + GtkWidget *GtkCombo_Spu2; + GtkWidget *entry1; + GtkWidget *hbuttonbox12; + GtkWidget *GtkButton_SPU2configure; + GtkWidget *GtkButton_SPU2test; + GtkWidget *GtkButton_SPU2about; + GtkWidget *GtkCombo_Dev9; + GtkWidget *entry3; + GtkWidget *hbuttonbox21; + GtkWidget *GtkButton_DEV9configure; + GtkWidget *GtkButton_DEV9test; + GtkWidget *GtkButton_DEV9about; + GtkWidget *label23; + GtkWidget *GtkLabel_Cdvdrom; + GtkWidget *GtkCombo_Cdvd; + GtkWidget *entry2; + GtkWidget *hbuttonbox13; + GtkWidget *GtkButton_CDVDconfigure; + GtkWidget *GtkButton_CDVDtest; + GtkWidget *GtkButton_CDVDabout; + GtkWidget *label29; + GtkWidget *GtkCombo_Usb; + GtkWidget *entry4; + GtkWidget *hbuttonbox23; + GtkWidget *GtkButton_USBconfigure; + GtkWidget *GtkButton_USBtest; + GtkWidget *GtkButton_USBabout; + GtkWidget *GtkCombo_Bios; + GtkWidget *combo_entry7; + GtkWidget *GtkCombo_FW; + GtkWidget *entry5; + GtkWidget *hbuttonbox24; + GtkWidget *GtkButton_FWconfigure; + GtkWidget *GtkButton_FWtest; + GtkWidget *GtkButton_FWabout; + GtkWidget *label30; + GtkWidget *GtkLabel_Bios; + GtkWidget *hbox5; + GtkWidget *hbuttonbox11; + GtkWidget *GtkButton_SelectPluginsDir; + GtkWidget *GtkButton_SelectBiosDir; + GtkWidget *hbuttonbox10; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + ConfDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (ConfDlg), "ConfDlg", ConfDlg); + gtk_container_set_border_width (GTK_CONTAINER (ConfDlg), 10); + gtk_window_set_title (GTK_WINDOW (ConfDlg), _("Conf")); + gtk_window_set_position (GTK_WINDOW (ConfDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (ConfDlg), FALSE, FALSE, FALSE); + + vbox12 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "vbox12", vbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox12); + gtk_container_add (GTK_CONTAINER (ConfDlg), vbox12); + + table2 = gtk_table_new (14, 2, FALSE); + gtk_widget_ref (table2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "table2", table2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (vbox12), table2, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table2), 15); + + GtkCombo_Pad1 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad1", GtkCombo_Pad1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad1); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad1, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry4 = GTK_COMBO (GtkCombo_Pad1)->entry; + gtk_widget_ref (combo_entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry4", combo_entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry4); + + GtkCombo_Pad2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad2", GtkCombo_Pad2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad2, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry5 = GTK_COMBO (GtkCombo_Pad2)->entry; + gtk_widget_ref (combo_entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry5", combo_entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry5); + + hbuttonbox6 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox6); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox6", hbuttonbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox6); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox6, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox6), 0); + + GtkButton_PAD2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2configure", GtkButton_PAD2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2configure, GTK_CAN_DEFAULT); + + GtkButton_PAD2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2test", GtkButton_PAD2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2test, GTK_CAN_DEFAULT); + + GtkButton_PAD2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2about", GtkButton_PAD2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2about, GTK_CAN_DEFAULT); + + hbuttonbox7 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox7", hbuttonbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox7); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox7, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox7), 0); + + GtkButton_PAD1configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD1configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1configure", GtkButton_PAD1configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1configure, GTK_CAN_DEFAULT); + + GtkButton_PAD1test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD1test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1test", GtkButton_PAD1test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1test); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1test, GTK_CAN_DEFAULT); + + GtkButton_PAD1about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD1about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1about", GtkButton_PAD1about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1about); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1about, GTK_CAN_DEFAULT); + + hbuttonbox8 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox8); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox8", hbuttonbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox8); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox8, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox8), 0); + + GtkButton_GSconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_GSconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSconfigure", GtkButton_GSconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_GSconfigure, GTK_CAN_DEFAULT); + + GtkButton_GStest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_GStest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GStest", GtkButton_GStest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GStest); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GStest); + GTK_WIDGET_SET_FLAGS (GtkButton_GStest, GTK_CAN_DEFAULT); + + GtkButton_GSabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_GSabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSabout", GtkButton_GSabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSabout); + GTK_WIDGET_SET_FLAGS (GtkButton_GSabout, GTK_CAN_DEFAULT); + + GtkLabel_Graphics = gtk_label_new (_("Graphics")); + gtk_widget_ref (GtkLabel_Graphics); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Graphics", GtkLabel_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Graphics); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Graphics, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Graphics), 0, 0.5); + + GtkLabel_FirstController = gtk_label_new (_("First Controller")); + gtk_widget_ref (GtkLabel_FirstController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_FirstController", GtkLabel_FirstController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_FirstController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_FirstController, 0, 1, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_FirstController), 0, 0.5); + + GtkLabel_SecondController = gtk_label_new (_("Second Controller")); + gtk_widget_ref (GtkLabel_SecondController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_SecondController", GtkLabel_SecondController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_SecondController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_SecondController, 1, 2, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_SecondController), 0, 0.5); + + GtkCombo_Gs = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Gs); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Gs", GtkCombo_Gs, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Gs); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Gs, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry2 = GTK_COMBO (GtkCombo_Gs)->entry; + gtk_widget_ref (combo_entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry2", combo_entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry2); + + GtkLabel_Sound = gtk_label_new (_("Sound")); + gtk_widget_ref (GtkLabel_Sound); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Sound", GtkLabel_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Sound); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Sound, 1, 2, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Sound), 0, 0.5); + + GtkCombo_Spu2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Spu2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Spu2", GtkCombo_Spu2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Spu2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Spu2, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry1 = GTK_COMBO (GtkCombo_Spu2)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox12 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox12", hbuttonbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox12); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox12, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox12), 0); + + GtkButton_SPU2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_SPU2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2configure", GtkButton_SPU2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2configure, GTK_CAN_DEFAULT); + + GtkButton_SPU2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_SPU2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2test", GtkButton_SPU2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2test); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2test, GTK_CAN_DEFAULT); + + GtkButton_SPU2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_SPU2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2about", GtkButton_SPU2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2about); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2about, GTK_CAN_DEFAULT); + + GtkCombo_Dev9 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Dev9); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Dev9", GtkCombo_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Dev9); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Dev9, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry3 = GTK_COMBO (GtkCombo_Dev9)->entry; + gtk_widget_ref (entry3); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry3", entry3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry3); + + hbuttonbox21 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox21); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox21", hbuttonbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox21); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox21, 0, 1, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox21), 0); + + GtkButton_DEV9configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_DEV9configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9configure", GtkButton_DEV9configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9configure); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9configure, GTK_CAN_DEFAULT); + + GtkButton_DEV9test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_DEV9test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9test", GtkButton_DEV9test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9test); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9test); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9test, GTK_CAN_DEFAULT); + + GtkButton_DEV9about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_DEV9about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9about", GtkButton_DEV9about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9about); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9about); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9about, GTK_CAN_DEFAULT); + + label23 = gtk_label_new (_("Dev9")); + gtk_widget_ref (label23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label23", label23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label23); + gtk_table_attach (GTK_TABLE (table2), label23, 0, 1, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label23), 0, 0.5); + + GtkLabel_Cdvdrom = gtk_label_new (_("Cdvdrom")); + gtk_widget_ref (GtkLabel_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Cdvdrom", GtkLabel_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Cdvdrom); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Cdvdrom, 1, 2, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Cdvdrom), 0, 0.5); + + GtkCombo_Cdvd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Cdvd); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Cdvd", GtkCombo_Cdvd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Cdvd); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Cdvd, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry2 = GTK_COMBO (GtkCombo_Cdvd)->entry; + gtk_widget_ref (entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry2", entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry2); + + hbuttonbox13 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox13); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox13", hbuttonbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox13); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox13, 1, 2, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox13), 0); + + GtkButton_CDVDconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_CDVDconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDconfigure", GtkButton_CDVDconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDconfigure, GTK_CAN_DEFAULT); + + GtkButton_CDVDtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_CDVDtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDtest", GtkButton_CDVDtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDtest); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDtest, GTK_CAN_DEFAULT); + + GtkButton_CDVDabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_CDVDabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDabout", GtkButton_CDVDabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDabout); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDabout, GTK_CAN_DEFAULT); + + label29 = gtk_label_new (_("Usb")); + gtk_widget_ref (label29); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label29", label29, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label29); + gtk_table_attach (GTK_TABLE (table2), label29, 0, 1, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label29), 0, 0.5); + + GtkCombo_Usb = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Usb); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Usb", GtkCombo_Usb, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Usb); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Usb, 0, 1, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry4 = GTK_COMBO (GtkCombo_Usb)->entry; + gtk_widget_ref (entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry4", entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry4); + + hbuttonbox23 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox23", hbuttonbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox23); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox23, 0, 1, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox23), 0); + + GtkButton_USBconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_USBconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBconfigure", GtkButton_USBconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_USBconfigure, GTK_CAN_DEFAULT); + + GtkButton_USBtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_USBtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBtest", GtkButton_USBtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBtest); + GTK_WIDGET_SET_FLAGS (GtkButton_USBtest, GTK_CAN_DEFAULT); + + GtkButton_USBabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_USBabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBabout", GtkButton_USBabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBabout); + GTK_WIDGET_SET_FLAGS (GtkButton_USBabout, GTK_CAN_DEFAULT); + + GtkCombo_Bios = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Bios", GtkCombo_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Bios, 1, 2, 13, 14, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry7 = GTK_COMBO (GtkCombo_Bios)->entry; + gtk_widget_ref (combo_entry7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry7", combo_entry7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry7); + + GtkCombo_FW = gtk_combo_new (); + gtk_widget_ref (GtkCombo_FW); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_FW", GtkCombo_FW, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_FW); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_FW, 1, 2, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry5 = GTK_COMBO (GtkCombo_FW)->entry; + gtk_widget_ref (entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry5", entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry5); + + hbuttonbox24 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox24); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox24", hbuttonbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox24); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox24, 1, 2, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox24), 0); + + GtkButton_FWconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_FWconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWconfigure", GtkButton_FWconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_FWconfigure, GTK_CAN_DEFAULT); + + GtkButton_FWtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_FWtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWtest", GtkButton_FWtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWtest); + GTK_WIDGET_SET_FLAGS (GtkButton_FWtest, GTK_CAN_DEFAULT); + + GtkButton_FWabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_FWabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWabout", GtkButton_FWabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWabout); + GTK_WIDGET_SET_FLAGS (GtkButton_FWabout, GTK_CAN_DEFAULT); + + label30 = gtk_label_new (_("FW")); + gtk_widget_ref (label30); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label30", label30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label30); + gtk_table_attach (GTK_TABLE (table2), label30, 1, 2, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label30), 0, 0.5); + + GtkLabel_Bios = gtk_label_new (_("Bios")); + gtk_widget_ref (GtkLabel_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Bios", GtkLabel_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Bios, 1, 2, 12, 13, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Bios), 0, 0.5); + + hbox5 = gtk_hbox_new (FALSE, 14); + gtk_widget_ref (hbox5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbox5", hbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox5); + gtk_box_pack_start (GTK_BOX (vbox12), hbox5, TRUE, TRUE, 0); + + hbuttonbox11 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox11); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox11", hbuttonbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox11); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox11, FALSE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox11), GTK_BUTTONBOX_START); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox11), 0); + + GtkButton_SelectPluginsDir = gtk_button_new_with_label (_("Select Plugins Dir")); + gtk_widget_ref (GtkButton_SelectPluginsDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectPluginsDir", GtkButton_SelectPluginsDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectPluginsDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectPluginsDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectPluginsDir, GTK_CAN_DEFAULT); + + GtkButton_SelectBiosDir = gtk_button_new_with_label (_("Select Bios Dir")); + gtk_widget_ref (GtkButton_SelectBiosDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectBiosDir", GtkButton_SelectBiosDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectBiosDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectBiosDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectBiosDir, GTK_CAN_DEFAULT); + + hbuttonbox10 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox10); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox10", hbuttonbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox10); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox10, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox10), 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GStest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectPluginsDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_PluginsPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectBiosDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_BiosPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Cancel), + NULL); + + return ConfDlg; +} + +GtkWidget* +create_CpuDlg (void) +{ + GtkWidget *CpuDlg; + GtkWidget *vbox8; + GtkWidget *hbox20; + GtkWidget *GtkFrame_Options; + GtkWidget *vbox15; + GtkWidget *GtkCheckButton_PsxOut; + GtkWidget *GtkCheckButton_Patches; + GtkWidget *frame6; + GtkWidget *vbox26; + GtkWidget *GtkCheckButton_Cpu; + GtkWidget *GtkCheckButton_RegCaching; + GtkWidget *GtkCheckButton_VUrec; + GtkWidget *hbuttonbox3; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + CpuDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CpuDlg), "CpuDlg", CpuDlg); + gtk_container_set_border_width (GTK_CONTAINER (CpuDlg), 5); + gtk_window_set_title (GTK_WINDOW (CpuDlg), _("Cpu")); + gtk_window_set_position (GTK_WINDOW (CpuDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (CpuDlg), FALSE, FALSE, FALSE); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox8); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox8", vbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (CpuDlg), vbox8); + + hbox20 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox20); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbox20", hbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox20); + gtk_box_pack_start (GTK_BOX (vbox8), hbox20, TRUE, TRUE, 0); + + GtkFrame_Options = gtk_frame_new (_("Options")); + gtk_widget_ref (GtkFrame_Options); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkFrame_Options", GtkFrame_Options, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkFrame_Options); + gtk_box_pack_start (GTK_BOX (hbox20), GtkFrame_Options, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (GtkFrame_Options), 5); + + vbox15 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox15); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox15", vbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox15); + gtk_container_add (GTK_CONTAINER (GtkFrame_Options), vbox15); + gtk_container_set_border_width (GTK_CONTAINER (vbox15), 5); + + GtkCheckButton_PsxOut = gtk_check_button_new_with_label (_("Enable Console Output")); + gtk_widget_ref (GtkCheckButton_PsxOut); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_PsxOut", GtkCheckButton_PsxOut, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_PsxOut); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_PsxOut, FALSE, FALSE, 0); + + GtkCheckButton_Patches = gtk_check_button_new_with_label (_("Enable Patches")); + gtk_widget_ref (GtkCheckButton_Patches); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Patches", GtkCheckButton_Patches, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Patches); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_Patches, FALSE, FALSE, 0); + + frame6 = gtk_frame_new (_("Recompiler Options")); + gtk_widget_ref (frame6); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "frame6", frame6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox8), frame6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame6), 5); + + vbox26 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox26); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox26", vbox26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox26); + gtk_container_add (GTK_CONTAINER (frame6), vbox26); + gtk_container_set_border_width (GTK_CONTAINER (vbox26), 5); + + GtkCheckButton_Cpu = gtk_check_button_new_with_label (_("Disable Recompiler")); + gtk_widget_ref (GtkCheckButton_Cpu); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Cpu", GtkCheckButton_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Cpu); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_Cpu, FALSE, FALSE, 0); + + GtkCheckButton_RegCaching = gtk_check_button_new_with_label (_("Enable Reg Caching")); + gtk_widget_ref (GtkCheckButton_RegCaching); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_RegCaching", GtkCheckButton_RegCaching, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_RegCaching); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_RegCaching, FALSE, FALSE, 0); + + GtkCheckButton_VUrec = gtk_check_button_new_with_label (_("Disable VUs recompilation")); + gtk_widget_ref (GtkCheckButton_VUrec); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_VUrec", GtkCheckButton_VUrec, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_VUrec); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_VUrec, FALSE, FALSE, 0); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbuttonbox3", hbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox8), hbuttonbox3, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Cancel), + NULL); + + return CpuDlg; +} + +GtkWidget* +create_DebugWnd (void) +{ + GtkWidget *DebugWnd; + GtkWidget *vbox16; + GtkWidget *hbox16; + GSList *Debug_group = NULL; + GtkWidget *GtkRadioButton_EE; + GtkWidget *GtkRadioButton_IOP; + GtkWidget *hbox6; + GtkWidget *hbox7; + GtkWidget *scrolledwindow1; + GtkWidget *viewport1; + GtkWidget *GtkList_DisView; + GtkWidget *GtkVScrollbar_VList; + GtkWidget *vbox22; + GtkWidget *vbuttonbox2; + GtkWidget *button52; + GtkWidget *button53; + GtkWidget *button65; + GtkWidget *button64; + GtkWidget *vbuttonbox3; + GtkWidget *button58; + GtkWidget *button59; + GtkWidget *button60; + GtkWidget *button61; + GtkWidget *vbuttonbox1; + GtkWidget *button39; + GtkWidget *button40; + GtkWidget *button41; + GtkWidget *vbuttonbox4; + GtkWidget *button68; + GtkWidget *button69; + GtkWidget *button70; + + DebugWnd = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (DebugWnd), "DebugWnd", DebugWnd); + gtk_container_set_border_width (GTK_CONTAINER (DebugWnd), 5); + gtk_window_set_title (GTK_WINDOW (DebugWnd), _("PCSX2 Debugger")); + gtk_window_set_position (GTK_WINDOW (DebugWnd), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DebugWnd), FALSE, FALSE, FALSE); + + vbox16 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox16", vbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox16); + gtk_container_add (GTK_CONTAINER (DebugWnd), vbox16); + gtk_container_set_border_width (GTK_CONTAINER (vbox16), 5); + + hbox16 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox16", hbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox16); + gtk_box_pack_start (GTK_BOX (vbox16), hbox16, TRUE, TRUE, 0); + + GtkRadioButton_EE = gtk_radio_button_new_with_label (Debug_group, _("EE Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_EE)); + gtk_widget_ref (GtkRadioButton_EE); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_EE", GtkRadioButton_EE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_EE); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_EE, FALSE, FALSE, 0); + + GtkRadioButton_IOP = gtk_radio_button_new_with_label (Debug_group, _("IOP Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_IOP)); + gtk_widget_ref (GtkRadioButton_IOP); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_IOP", GtkRadioButton_IOP, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_IOP); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_IOP, FALSE, FALSE, 0); + + hbox6 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox6); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox6", hbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox16), hbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox6), 5); + + hbox7 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox7); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox7", hbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox7); + gtk_box_pack_start (GTK_BOX (hbox6), hbox7, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_ref (scrolledwindow1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "scrolledwindow1", scrolledwindow1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (scrolledwindow1); + gtk_box_pack_start (GTK_BOX (hbox7), scrolledwindow1, TRUE, TRUE, 0); + gtk_widget_set_usize (scrolledwindow1, 320, -2); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER); + + viewport1 = gtk_viewport_new (NULL, NULL); + gtk_widget_ref (viewport1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "viewport1", viewport1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (viewport1); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); + + GtkList_DisView = gtk_list_new (); + gtk_widget_ref (GtkList_DisView); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkList_DisView", GtkList_DisView, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkList_DisView); + gtk_container_add (GTK_CONTAINER (viewport1), GtkList_DisView); + + GtkVScrollbar_VList = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 412, 1, 20, 2))); + gtk_widget_ref (GtkVScrollbar_VList); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkVScrollbar_VList", GtkVScrollbar_VList, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkVScrollbar_VList); + gtk_box_pack_start (GTK_BOX (hbox7), GtkVScrollbar_VList, TRUE, TRUE, 0); + + vbox22 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox22); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox22", vbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox22); + gtk_box_pack_start (GTK_BOX (hbox6), vbox22, TRUE, TRUE, 0); + + vbuttonbox2 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox2", vbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox2, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox2), 0); + + button52 = gtk_button_new_with_label (_("Step")); + gtk_widget_ref (button52); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button52", button52, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button52); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button52); + GTK_WIDGET_SET_FLAGS (button52, GTK_CAN_DEFAULT); + + button53 = gtk_button_new_with_label (_("Skip")); + gtk_widget_ref (button53); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button53", button53, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button53); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button53); + GTK_WIDGET_SET_FLAGS (button53, GTK_CAN_DEFAULT); + + button65 = gtk_button_new_with_label (_("Go")); + gtk_widget_ref (button65); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button65", button65, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button65); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button65); + GTK_WIDGET_SET_FLAGS (button65, GTK_CAN_DEFAULT); + + button64 = gtk_button_new_with_label (_("Log On/Off")); + gtk_widget_ref (button64); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button64", button64, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button64); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button64); + GTK_WIDGET_SET_FLAGS (button64, GTK_CAN_DEFAULT); + + vbuttonbox3 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox3", vbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox3, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox3), 0); + + button58 = gtk_button_new_with_label (_("Set PC")); + gtk_widget_ref (button58); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button58", button58, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button58); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button58); + GTK_WIDGET_SET_FLAGS (button58, GTK_CAN_DEFAULT); + + button59 = gtk_button_new_with_label (_("Set BP Addr")); + gtk_widget_ref (button59); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button59", button59, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button59); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button59); + GTK_WIDGET_SET_FLAGS (button59, GTK_CAN_DEFAULT); + + button60 = gtk_button_new_with_label (_("Set BP Count")); + gtk_widget_ref (button60); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button60", button60, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button60); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button60); + GTK_WIDGET_SET_FLAGS (button60, GTK_CAN_DEFAULT); + + button61 = gtk_button_new_with_label (_("Clear BPs")); + gtk_widget_ref (button61); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button61", button61, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button61); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button61); + GTK_WIDGET_SET_FLAGS (button61, GTK_CAN_DEFAULT); + + vbuttonbox1 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox1", vbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox1), 0); + + button39 = gtk_button_new_with_label (_("Dump code")); + gtk_widget_ref (button39); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button39", button39, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button39); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button39); + GTK_WIDGET_SET_FLAGS (button39, GTK_CAN_DEFAULT); + + button40 = gtk_button_new_with_label (_("Raw Dump")); + gtk_widget_ref (button40); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button40", button40, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button40); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button40); + GTK_WIDGET_SET_FLAGS (button40, GTK_CAN_DEFAULT); + + button41 = gtk_button_new_with_label (_("Close")); + gtk_widget_ref (button41); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button41", button41, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button41); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button41); + GTK_WIDGET_SET_FLAGS (button41, GTK_CAN_DEFAULT); + + vbuttonbox4 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox4); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox4", vbuttonbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox4); + gtk_box_pack_start (GTK_BOX (hbox6), vbuttonbox4, TRUE, TRUE, 0); + + button68 = gtk_button_new_with_label (_("memWrite32")); + gtk_widget_ref (button68); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button68", button68, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button68); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button68); + GTK_WIDGET_SET_FLAGS (button68, GTK_CAN_DEFAULT); + + button69 = gtk_button_new_with_label (_("button69")); + gtk_widget_ref (button69); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button69", button69, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button69); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button69); + GTK_WIDGET_SET_FLAGS (button69, GTK_CAN_DEFAULT); + + button70 = gtk_button_new_with_label (_("button70")); + gtk_widget_ref (button70); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button70", button70, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button70); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button70); + GTK_WIDGET_SET_FLAGS (button70, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_EE), "toggled", + GTK_SIGNAL_FUNC (OnDebug_EEMode), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_IOP), "toggled", + GTK_SIGNAL_FUNC (OnDebug_IOPMode), + NULL); + gtk_signal_connect (GTK_OBJECT (button52), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Step), + NULL); + gtk_signal_connect (GTK_OBJECT (button53), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Skip), + NULL); + gtk_signal_connect (GTK_OBJECT (button65), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Go), + NULL); + gtk_signal_connect (GTK_OBJECT (button64), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Log), + NULL); + gtk_signal_connect (GTK_OBJECT (button58), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button59), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPA), + NULL); + gtk_signal_connect (GTK_OBJECT (button60), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button61), "clicked", + GTK_SIGNAL_FUNC (OnDebug_ClearBPs), + NULL); + gtk_signal_connect (GTK_OBJECT (button39), "clicked", + GTK_SIGNAL_FUNC (OnDebug_DumpCode), + NULL); + gtk_signal_connect (GTK_OBJECT (button40), "clicked", + GTK_SIGNAL_FUNC (OnDebug_RawDump), + NULL); + gtk_signal_connect (GTK_OBJECT (button41), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Close), + NULL); + gtk_signal_connect (GTK_OBJECT (button68), "clicked", + GTK_SIGNAL_FUNC (OnDebug_memWrite32), + NULL); + + return DebugWnd; +} + +GtkWidget* +create_SetPCDlg (void) +{ + GtkWidget *SetPCDlg; + GtkWidget *vbox17; + GtkWidget *label9; + GtkWidget *hbox8; + GtkWidget *label10; + GtkWidget *GtkEntry_dPC; + GtkWidget *hbuttonbox14; + GtkWidget *button42; + GtkWidget *button43; + + SetPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetPCDlg), "SetPCDlg", SetPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetPCDlg), _("SetPCDlg")); + gtk_window_set_position (GTK_WINDOW (SetPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetPCDlg), FALSE, FALSE, FALSE); + + vbox17 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox17); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "vbox17", vbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox17); + gtk_container_add (GTK_CONTAINER (SetPCDlg), vbox17); + gtk_container_set_border_width (GTK_CONTAINER (vbox17), 5); + + label9 = gtk_label_new (_("Set New PC Address (in Hex):")); + gtk_widget_ref (label9); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label9", label9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label9); + gtk_box_pack_start (GTK_BOX (vbox17), label9, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label9), 0.1, 0.5); + + hbox8 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox8); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbox8", hbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox8); + gtk_box_pack_start (GTK_BOX (vbox17), hbox8, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox8), 5); + + label10 = gtk_label_new (_("0x")); + gtk_widget_ref (label10); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label10", label10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label10); + gtk_box_pack_start (GTK_BOX (hbox8), label10, FALSE, FALSE, 0); + + GtkEntry_dPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_dPC); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "GtkEntry_dPC", GtkEntry_dPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dPC); + gtk_box_pack_start (GTK_BOX (hbox8), GtkEntry_dPC, TRUE, TRUE, 0); + + hbuttonbox14 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox14); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbuttonbox14", hbuttonbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox14); + gtk_box_pack_start (GTK_BOX (vbox17), hbuttonbox14, TRUE, TRUE, 0); + + button42 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button42); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button42", button42, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button42); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button42); + GTK_WIDGET_SET_FLAGS (button42, GTK_CAN_DEFAULT); + + button43 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button43); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button43", button43, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button43); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button43); + GTK_WIDGET_SET_FLAGS (button43, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button42), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button43), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Cancel), + NULL); + + return SetPCDlg; +} + +GtkWidget* +create_SetBPADlg (void) +{ + GtkWidget *SetBPADlg; + GtkWidget *vbox18; + GtkWidget *label11; + GtkWidget *hbox9; + GtkWidget *label12; + GtkWidget *GtkEntry_BPA; + GtkWidget *hbuttonbox15; + GtkWidget *button44; + GtkWidget *button45; + + SetBPADlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPADlg), "SetBPADlg", SetBPADlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPADlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPADlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPADlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPADlg), FALSE, FALSE, FALSE); + + vbox18 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox18); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "vbox18", vbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox18); + gtk_container_add (GTK_CONTAINER (SetBPADlg), vbox18); + gtk_container_set_border_width (GTK_CONTAINER (vbox18), 5); + + label11 = gtk_label_new (_("Set New BP Address (in Hex):")); + gtk_widget_ref (label11); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label11", label11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox18), label11, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label11), 0.1, 0.5); + + hbox9 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox9); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbox9", hbox9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox9); + gtk_box_pack_start (GTK_BOX (vbox18), hbox9, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox9), 5); + + label12 = gtk_label_new (_("0x")); + gtk_widget_ref (label12); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label12", label12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label12); + gtk_box_pack_start (GTK_BOX (hbox9), label12, FALSE, FALSE, 0); + + GtkEntry_BPA = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPA); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "GtkEntry_BPA", GtkEntry_BPA, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPA); + gtk_box_pack_start (GTK_BOX (hbox9), GtkEntry_BPA, TRUE, TRUE, 0); + + hbuttonbox15 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox15); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbuttonbox15", hbuttonbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox15); + gtk_box_pack_start (GTK_BOX (vbox18), hbuttonbox15, TRUE, TRUE, 0); + + button44 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button44); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button44", button44, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button44); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button44); + GTK_WIDGET_SET_FLAGS (button44, GTK_CAN_DEFAULT); + + button45 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button45); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button45", button45, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button45); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button45); + GTK_WIDGET_SET_FLAGS (button45, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button44), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button45), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Cancel), + NULL); + + return SetBPADlg; +} + +GtkWidget* +create_SetBPCDlg (void) +{ + GtkWidget *SetBPCDlg; + GtkWidget *vbox19; + GtkWidget *label13; + GtkWidget *hbox10; + GtkWidget *label14; + GtkWidget *GtkEntry_BPC; + GtkWidget *hbuttonbox16; + GtkWidget *button46; + GtkWidget *button47; + + SetBPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPCDlg), "SetBPCDlg", SetBPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPCDlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPCDlg), FALSE, FALSE, FALSE); + + vbox19 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox19); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "vbox19", vbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox19); + gtk_container_add (GTK_CONTAINER (SetBPCDlg), vbox19); + gtk_container_set_border_width (GTK_CONTAINER (vbox19), 5); + + label13 = gtk_label_new (_("Set New BP Count (in Hex):")); + gtk_widget_ref (label13); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label13", label13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label13); + gtk_box_pack_start (GTK_BOX (vbox19), label13, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label13), 0.1, 0.5); + + hbox10 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox10); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbox10", hbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox10); + gtk_box_pack_start (GTK_BOX (vbox19), hbox10, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox10), 5); + + label14 = gtk_label_new (_("0x")); + gtk_widget_ref (label14); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label14", label14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label14); + gtk_box_pack_start (GTK_BOX (hbox10), label14, FALSE, FALSE, 0); + + GtkEntry_BPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPC); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "GtkEntry_BPC", GtkEntry_BPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPC); + gtk_box_pack_start (GTK_BOX (hbox10), GtkEntry_BPC, TRUE, TRUE, 0); + + hbuttonbox16 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox16); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbuttonbox16", hbuttonbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox16); + gtk_box_pack_start (GTK_BOX (vbox19), hbuttonbox16, TRUE, TRUE, 0); + + button46 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button46); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button46", button46, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button46); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button46); + GTK_WIDGET_SET_FLAGS (button46, GTK_CAN_DEFAULT); + + button47 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button47); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button47", button47, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button47); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button47); + GTK_WIDGET_SET_FLAGS (button47, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button46), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button47), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Cancel), + NULL); + + return SetBPCDlg; +} + +GtkWidget* +create_DumpCDlg (void) +{ + GtkWidget *DumpCDlg; + GtkWidget *vbox20; + GtkWidget *label15; + GtkWidget *hbox11; + GtkWidget *label16; + GtkWidget *GtkEntry_DumpCF; + GtkWidget *hbox12; + GtkWidget *label17; + GtkWidget *GtkEntry_DumpCT; + GtkWidget *label21; + GtkWidget *hbuttonbox17; + GtkWidget *button48; + GtkWidget *button49; + + DumpCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpCDlg), "DumpCDlg", DumpCDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpCDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpCDlg), _("Dump code")); + gtk_window_set_position (GTK_WINDOW (DumpCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpCDlg), FALSE, FALSE, FALSE); + + vbox20 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox20); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "vbox20", vbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox20); + gtk_container_add (GTK_CONTAINER (DumpCDlg), vbox20); + gtk_container_set_border_width (GTK_CONTAINER (vbox20), 5); + + label15 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label15); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label15", label15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label15); + gtk_box_pack_start (GTK_BOX (vbox20), label15, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label15), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label15), 0.1, 0.5); + + hbox11 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox11); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox11", hbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox11); + gtk_box_pack_start (GTK_BOX (vbox20), hbox11, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox11), 5); + + label16 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label16); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label16", label16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label16); + gtk_box_pack_start (GTK_BOX (hbox11), label16, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label16), TRUE); + + GtkEntry_DumpCF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCF); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCF", GtkEntry_DumpCF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCF); + gtk_box_pack_start (GTK_BOX (hbox11), GtkEntry_DumpCF, TRUE, TRUE, 0); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox12); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox12", hbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox12); + gtk_box_pack_start (GTK_BOX (vbox20), hbox12, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox12), 5); + + label17 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label17", label17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label17); + gtk_box_pack_start (GTK_BOX (hbox12), label17, FALSE, FALSE, 0); + gtk_widget_set_usize (label17, 45, -2); + + GtkEntry_DumpCT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCT); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCT", GtkEntry_DumpCT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCT); + gtk_box_pack_start (GTK_BOX (hbox12), GtkEntry_DumpCT, TRUE, TRUE, 0); + + label21 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label21); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label21", label21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label21); + gtk_box_pack_start (GTK_BOX (vbox20), label21, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label21), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label21), 0.1, 0.5); + + hbuttonbox17 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbuttonbox17", hbuttonbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox17); + gtk_box_pack_start (GTK_BOX (vbox20), hbuttonbox17, TRUE, TRUE, 0); + + button48 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button48); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button48", button48, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button48); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button48); + GTK_WIDGET_SET_FLAGS (button48, GTK_CAN_DEFAULT); + + button49 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button49); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button49", button49, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button49); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button49); + GTK_WIDGET_SET_FLAGS (button49, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button48), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button49), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Cancel), + NULL); + + return DumpCDlg; +} + +GtkWidget* +create_DumpRDlg (void) +{ + GtkWidget *DumpRDlg; + GtkWidget *vbox21; + GtkWidget *label18; + GtkWidget *hbox13; + GtkWidget *label19; + GtkWidget *GtkEntry_DumpRF; + GtkWidget *hbox14; + GtkWidget *label20; + GtkWidget *GtkEntry_DumpRT; + GtkWidget *label22; + GtkWidget *hbuttonbox18; + GtkWidget *button50; + GtkWidget *button51; + + DumpRDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpRDlg), "DumpRDlg", DumpRDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpRDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpRDlg), _("Raw Dump")); + gtk_window_set_position (GTK_WINDOW (DumpRDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpRDlg), FALSE, FALSE, FALSE); + + vbox21 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox21); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "vbox21", vbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox21); + gtk_container_add (GTK_CONTAINER (DumpRDlg), vbox21); + gtk_container_set_border_width (GTK_CONTAINER (vbox21), 5); + + label18 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label18", label18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label18); + gtk_box_pack_start (GTK_BOX (vbox21), label18, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label18), 0.1, 0.5); + + hbox13 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox13); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox13", hbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox13); + gtk_box_pack_start (GTK_BOX (vbox21), hbox13, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox13), 5); + + label19 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label19); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label19", label19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label19); + gtk_box_pack_start (GTK_BOX (hbox13), label19, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label19), TRUE); + + GtkEntry_DumpRF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRF); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRF", GtkEntry_DumpRF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRF); + gtk_box_pack_start (GTK_BOX (hbox13), GtkEntry_DumpRF, TRUE, TRUE, 0); + + hbox14 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox14); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox14", hbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox14); + gtk_box_pack_start (GTK_BOX (vbox21), hbox14, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox14), 5); + + label20 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label20); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label20", label20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label20); + gtk_box_pack_start (GTK_BOX (hbox14), label20, FALSE, FALSE, 0); + gtk_widget_set_usize (label20, 45, -2); + gtk_label_set_justify (GTK_LABEL (label20), GTK_JUSTIFY_LEFT); + + GtkEntry_DumpRT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRT); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRT", GtkEntry_DumpRT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRT); + gtk_box_pack_start (GTK_BOX (hbox14), GtkEntry_DumpRT, TRUE, TRUE, 0); + + label22 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label22); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label22", label22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (vbox21), label22, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label22), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label22), 0.1, 0.5); + + hbuttonbox18 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbuttonbox18", hbuttonbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox18); + gtk_box_pack_start (GTK_BOX (vbox21), hbuttonbox18, TRUE, TRUE, 0); + + button50 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button50); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button50", button50, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button50); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button50); + GTK_WIDGET_SET_FLAGS (button50, GTK_CAN_DEFAULT); + + button51 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button51); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button51", button51, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button51); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button51); + GTK_WIDGET_SET_FLAGS (button51, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button50), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button51), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Cancel), + NULL); + + return DumpRDlg; +} + +GtkWidget* +create_Logging (void) +{ + GtkWidget *Logging; + GtkWidget *vbox23; + GtkWidget *hbox15; + GtkWidget *frame4; + GtkWidget *table3; + GtkWidget *Log0; + GtkWidget *Log1; + GtkWidget *Log2; + GtkWidget *Log3; + GtkWidget *Log4; + GtkWidget *Log5; + GtkWidget *Log6; + GtkWidget *Log7; + GtkWidget *Log8; + GtkWidget *Log9; + GtkWidget *Log10; + GtkWidget *Log11; + GtkWidget *Log12; + GtkWidget *Log13; + GtkWidget *Log15; + GtkWidget *Log14; + GtkWidget *Log16; + GtkWidget *Log31; + GtkWidget *Log; + GtkWidget *Log30; + GtkWidget *frame5; + GtkWidget *table4; + GtkWidget *Log27; + GtkWidget *Log26; + GtkWidget *Log25; + GtkWidget *Log24; + GtkWidget *Log23; + GtkWidget *Log22; + GtkWidget *Log21; + GtkWidget *Log20; + GtkWidget *Log28; + GtkWidget *hbuttonbox19; + GtkWidget *button66; + GtkWidget *button67; + + Logging = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (Logging), "Logging", Logging); + gtk_container_set_border_width (GTK_CONTAINER (Logging), 5); + gtk_window_set_title (GTK_WINDOW (Logging), _("Logging")); + gtk_window_set_position (GTK_WINDOW (Logging), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (Logging), FALSE, FALSE, FALSE); + + vbox23 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "vbox23", vbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox23); + gtk_container_add (GTK_CONTAINER (Logging), vbox23); + gtk_container_set_border_width (GTK_CONTAINER (vbox23), 5); + + hbox15 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbox15", hbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox15); + gtk_box_pack_start (GTK_BOX (vbox23), hbox15, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox15), 5); + + frame4 = gtk_frame_new (_("EE Logs")); + gtk_widget_ref (frame4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame4", frame4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (hbox15), frame4, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame4), 5); + + table3 = gtk_table_new (8, 3, FALSE); + gtk_widget_ref (table3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table3", table3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (frame4), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 5); + gtk_table_set_row_spacings (GTK_TABLE (table3), 5); + gtk_table_set_col_spacings (GTK_TABLE (table3), 5); + + Log0 = gtk_check_button_new_with_label (_("Cpu Log")); + gtk_widget_ref (Log0); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log0", Log0, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log0); + gtk_table_attach (GTK_TABLE (table3), Log0, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log1 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log1); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log1", Log1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log1); + gtk_table_attach (GTK_TABLE (table3), Log1, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log2 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log2); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log2", Log2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log2); + gtk_table_attach (GTK_TABLE (table3), Log2, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log3 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log3", Log3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log3); + gtk_table_attach (GTK_TABLE (table3), Log3, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log4 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log4", Log4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log4); + gtk_table_attach (GTK_TABLE (table3), Log4, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log5 = gtk_check_button_new_with_label (_("Elf Log")); + gtk_widget_ref (Log5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log5", Log5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log5); + gtk_table_attach (GTK_TABLE (table3), Log5, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log6 = gtk_check_button_new_with_label (_("Fpu Log")); + gtk_widget_ref (Log6); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log6", Log6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log6); + gtk_table_attach (GTK_TABLE (table3), Log6, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log7 = gtk_check_button_new_with_label (_("MMI Log")); + gtk_widget_ref (Log7); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log7", Log7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log7); + gtk_table_attach (GTK_TABLE (table3), Log7, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log8 = gtk_check_button_new_with_label (_("VU0 Log")); + gtk_widget_ref (Log8); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log8", Log8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log8); + gtk_table_attach (GTK_TABLE (table3), Log8, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log9 = gtk_check_button_new_with_label (_("Cop0 Log")); + gtk_widget_ref (Log9); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log9", Log9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log9); + gtk_table_attach (GTK_TABLE (table3), Log9, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log10 = gtk_check_button_new_with_label (_("Vif Log")); + gtk_widget_ref (Log10); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log10", Log10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log10); + gtk_table_attach (GTK_TABLE (table3), Log10, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log11 = gtk_check_button_new_with_label (_("SPR Log")); + gtk_widget_ref (Log11); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log11", Log11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log11); + gtk_table_attach (GTK_TABLE (table3), Log11, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log12 = gtk_check_button_new_with_label (_("GIF Log")); + gtk_widget_ref (Log12); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log12", Log12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log12); + gtk_table_attach (GTK_TABLE (table3), Log12, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log13 = gtk_check_button_new_with_label (_("Sif Log")); + gtk_widget_ref (Log13); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log13", Log13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log13); + gtk_table_attach (GTK_TABLE (table3), Log13, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log15 = gtk_check_button_new_with_label (_("VU Micro Log")); + gtk_widget_ref (Log15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log15", Log15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log15); + gtk_table_attach (GTK_TABLE (table3), Log15, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log14 = gtk_check_button_new_with_label (_("IPU Log")); + gtk_widget_ref (Log14); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log14", Log14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log14); + gtk_table_attach (GTK_TABLE (table3), Log14, 1, 2, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log16 = gtk_check_button_new_with_label (_("RPC Log")); + gtk_widget_ref (Log16); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log16", Log16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log16); + gtk_table_attach (GTK_TABLE (table3), Log16, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log31 = gtk_check_button_new_with_label (_("Log to STDOUT")); + gtk_widget_ref (Log31); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log31", Log31, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log31); + gtk_table_attach (GTK_TABLE (table3), Log31, 2, 3, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log = gtk_check_button_new_with_label (_("Log")); + gtk_widget_ref (Log); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log", Log, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log); + gtk_table_attach (GTK_TABLE (table3), Log, 2, 3, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log30 = gtk_check_button_new_with_label (_("SYMs Log")); + gtk_widget_ref (Log30); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log30", Log30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log30); + gtk_table_attach (GTK_TABLE (table3), Log30, 2, 3, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + frame5 = gtk_frame_new (_("IOP Logs")); + gtk_widget_ref (frame5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame5", frame5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (hbox15), frame5, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame5), 5); + + table4 = gtk_table_new (8, 2, FALSE); + gtk_widget_ref (table4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table4", table4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (frame5), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 5); + gtk_table_set_row_spacings (GTK_TABLE (table4), 5); + gtk_table_set_col_spacings (GTK_TABLE (table4), 5); + + Log27 = gtk_check_button_new_with_label (_("Cdr Log")); + gtk_widget_ref (Log27); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log27", Log27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log27); + gtk_table_attach (GTK_TABLE (table4), Log27, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log26 = gtk_check_button_new_with_label (_("Gte Log")); + gtk_widget_ref (Log26); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log26", Log26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log26); + gtk_table_attach (GTK_TABLE (table4), Log26, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log25 = gtk_check_button_new_with_label (_("Pad Log")); + gtk_widget_ref (Log25); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log25", Log25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log25); + gtk_table_attach (GTK_TABLE (table4), Log25, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log24 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log24); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log24", Log24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log24); + gtk_table_attach (GTK_TABLE (table4), Log24, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log23 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log23", Log23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log23); + gtk_table_attach (GTK_TABLE (table4), Log23, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log22 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log22); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log22", Log22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log22); + gtk_table_attach (GTK_TABLE (table4), Log22, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log21 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log21); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log21", Log21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log21); + gtk_table_attach (GTK_TABLE (table4), Log21, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log20 = gtk_check_button_new_with_label (_("IOP Log")); + gtk_widget_ref (Log20); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log20", Log20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log20); + gtk_table_attach (GTK_TABLE (table4), Log20, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log28 = gtk_check_button_new_with_label (_("GPU Log")); + gtk_widget_ref (Log28); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log28", Log28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log28); + gtk_table_attach (GTK_TABLE (table4), Log28, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + hbuttonbox19 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox19); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbuttonbox19", hbuttonbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox19); + gtk_box_pack_start (GTK_BOX (vbox23), hbuttonbox19, TRUE, TRUE, 0); + + button66 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button66); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button66", button66, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button66); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button66); + GTK_WIDGET_SET_FLAGS (button66, GTK_CAN_DEFAULT); + + button67 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button67); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button67", button67, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button67); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button67); + GTK_WIDGET_SET_FLAGS (button67, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button66), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button67), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Cancel), + NULL); + + return Logging; +} + +GtkWidget* +create_CmdLine (void) +{ + GtkWidget *CmdLine; + GtkWidget *vbox24; + GtkWidget *GtkLabel_Text; + GtkWidget *hbox17; + GtkWidget *GtkEntry_dCMDLINE; + GtkWidget *GtkLabel_Note; + GtkWidget *hbuttonbox20; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + CmdLine = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CmdLine), "CmdLine", CmdLine); + gtk_container_set_border_width (GTK_CONTAINER (CmdLine), 5); + gtk_window_set_title (GTK_WINDOW (CmdLine), _("Program arguments")); + gtk_window_set_position (GTK_WINDOW (CmdLine), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (CmdLine), TRUE); + gtk_window_set_policy (GTK_WINDOW (CmdLine), FALSE, FALSE, FALSE); + + vbox24 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox24); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "vbox24", vbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox24); + gtk_container_add (GTK_CONTAINER (CmdLine), vbox24); + gtk_container_set_border_width (GTK_CONTAINER (vbox24), 5); + + GtkLabel_Text = gtk_label_new (_("Fill in the command line arguments for opened program:")); + gtk_widget_ref (GtkLabel_Text); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Text", GtkLabel_Text, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Text); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Text, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Text), 0.1, 0.5); + + hbox17 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox17); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbox17", hbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox17); + gtk_box_pack_start (GTK_BOX (vbox24), hbox17, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox17), 5); + + GtkEntry_dCMDLINE = gtk_entry_new_with_max_length (255); + gtk_widget_ref (GtkEntry_dCMDLINE); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkEntry_dCMDLINE", GtkEntry_dCMDLINE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dCMDLINE); + gtk_box_pack_start (GTK_BOX (hbox17), GtkEntry_dCMDLINE, TRUE, TRUE, 0); + gtk_tooltips_set_tip (tooltips, GtkEntry_dCMDLINE, _("If you don't know what to write leave it blank"), NULL); + + GtkLabel_Note = gtk_label_new (_("Note: this is intented for developers only.")); + gtk_widget_ref (GtkLabel_Note); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Note", GtkLabel_Note, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Note); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Note, FALSE, FALSE, 0); + + hbuttonbox20 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox20); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbuttonbox20", hbuttonbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox20); + gtk_box_pack_start (GTK_BOX (vbox24), hbuttonbox20, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Cancel), + NULL); + + gtk_object_set_data (GTK_OBJECT (CmdLine), "tooltips", tooltips); + + return CmdLine; +} + +GtkWidget* +create_MemWrite32 (void) +{ + GtkWidget *MemWrite32; + GtkWidget *vbox25; + GtkWidget *hbox18; + GtkWidget *label27; + GtkWidget *label25; + GtkWidget *GtkEntry_Mem; + GtkWidget *hbox19; + GtkWidget *label28; + GtkWidget *label26; + GtkWidget *GtkEntry_Data; + GtkWidget *hbuttonbox22; + GtkWidget *button71; + GtkWidget *button72; + + MemWrite32 = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (MemWrite32), "MemWrite32", MemWrite32); + gtk_container_set_border_width (GTK_CONTAINER (MemWrite32), 5); + gtk_window_set_title (GTK_WINDOW (MemWrite32), _("memWrite32")); + gtk_window_set_position (GTK_WINDOW (MemWrite32), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MemWrite32), FALSE, FALSE, FALSE); + + vbox25 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "vbox25", vbox25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox25); + gtk_container_add (GTK_CONTAINER (MemWrite32), vbox25); + gtk_container_set_border_width (GTK_CONTAINER (vbox25), 5); + + hbox18 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox18); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox18", hbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox18); + gtk_box_pack_start (GTK_BOX (vbox25), hbox18, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + label27 = gtk_label_new (_("Address ")); + gtk_widget_ref (label27); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label27", label27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label27); + gtk_box_pack_start (GTK_BOX (hbox18), label27, FALSE, FALSE, 0); + + label25 = gtk_label_new (_("0x")); + gtk_widget_ref (label25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label25", label25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label25); + gtk_box_pack_start (GTK_BOX (hbox18), label25, FALSE, FALSE, 0); + + GtkEntry_Mem = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Mem); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Mem", GtkEntry_Mem, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Mem); + gtk_box_pack_start (GTK_BOX (hbox18), GtkEntry_Mem, TRUE, TRUE, 0); + + hbox19 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox19); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox19", hbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox19); + gtk_box_pack_start (GTK_BOX (vbox25), hbox19, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox19), 5); + + label28 = gtk_label_new (_("Data ")); + gtk_widget_ref (label28); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label28", label28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label28); + gtk_box_pack_start (GTK_BOX (hbox19), label28, FALSE, FALSE, 0); + + label26 = gtk_label_new (_("0x")); + gtk_widget_ref (label26); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label26", label26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label26); + gtk_box_pack_start (GTK_BOX (hbox19), label26, FALSE, FALSE, 0); + + GtkEntry_Data = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Data); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Data", GtkEntry_Data, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Data); + gtk_box_pack_start (GTK_BOX (hbox19), GtkEntry_Data, TRUE, TRUE, 0); + + hbuttonbox22 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox22); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbuttonbox22", hbuttonbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox22); + gtk_box_pack_start (GTK_BOX (vbox25), hbuttonbox22, TRUE, TRUE, 0); + + button71 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button71); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button71", button71, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button71); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button71); + GTK_WIDGET_SET_FLAGS (button71, GTK_CAN_DEFAULT); + + button72 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button72); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button72", button72, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button72); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button72); + GTK_WIDGET_SET_FLAGS (button72, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button71), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button72), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Cancel), + NULL); + + return MemWrite32; +} + diff --git a/branches/pcsx2_0.9.1/Linux/GladeGui.h b/branches/pcsx2_0.9.1/Linux/GladeGui.h new file mode 100644 index 0000000..111115a --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GladeGui.h @@ -0,0 +1,17 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_MainWindow (void); +GtkWidget* create_AboutDlg (void); +GtkWidget* create_ConfDlg (void); +GtkWidget* create_CpuDlg (void); +GtkWidget* create_DebugWnd (void); +GtkWidget* create_SetPCDlg (void); +GtkWidget* create_SetBPADlg (void); +GtkWidget* create_SetBPCDlg (void); +GtkWidget* create_DumpCDlg (void); +GtkWidget* create_DumpRDlg (void); +GtkWidget* create_Logging (void); +GtkWidget* create_CmdLine (void); +GtkWidget* create_MemWrite32 (void); diff --git a/branches/pcsx2_0.9.1/Linux/GtkGui.c b/branches/pcsx2_0.9.1/Linux/GtkGui.c new file mode 100644 index 0000000..134cc45 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/GtkGui.c @@ -0,0 +1,1481 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Linux.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +static int needreset = 1; +int confret; +int confplug=0; + +_PS2EgetLibType PS2EgetLibType = NULL; +_PS2EgetLibVersion2 PS2EgetLibVersion2 = NULL; +_PS2EgetLibName PS2EgetLibName = NULL; + +// Helper Functions +void FindPlugins(); + +// Functions Callbacks +void OnFile_LoadElf(); +void OnFile_Exit(); +void OnEmu_Run(); +void OnEmu_Reset(); +void OnEmu_Arguments(); +void OnConf_Gs(); +void OnConf_Pads(); +void OnConf_Cpu(); +void OnConf_Conf(); +void OnLanguage(GtkMenuItem *menuitem, gpointer user_data); +void OnHelp_Help(); +void OnHelp_About(); + +GtkWidget *Window; +GtkWidget *CmdLine; //2002-09-28 (Florin) +GtkWidget *ConfDlg; +GtkWidget *AboutDlg; +GtkWidget *DebugWnd; +GtkWidget *LogDlg; +GtkWidget *FileSel; + +GtkAccelGroup *AccelGroup; + +typedef struct { + GtkWidget *Combo; + GList *glist; + char plist[255][255]; + int plugins; +} PluginConf; + +PluginConf GSConfS; +PluginConf PAD1ConfS; +PluginConf PAD2ConfS; +PluginConf SPU2ConfS; +PluginConf CDVDConfS; +PluginConf DEV9ConfS; +PluginConf USBConfS; +PluginConf FWConfS; +PluginConf BiosConfS; + +void StartGui() { + GtkWidget *Menu; + GtkWidget *Item; + int i; + + Window = create_MainWindow(); + gtk_window_set_title(GTK_WINDOW(Window), "PCSX2 v" PCSX2_VERSION); + +#ifndef NEW_LOGGING + Item = lookup_widget(Window, "GtkMenuItem_Logging"); + gtk_widget_set_sensitive(Item, FALSE); +#endif + + Item = lookup_widget(Window, "GtkMenuItem_Language"); + Menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(Item), Menu); + + for (i=0; iExecute(); +} + +void OnFile_RunCD() { + efile = 2; + RunExecute(1); +} + +void OnRunElf_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(elfname, File); + gtk_widget_destroy(FileSel); + needreset = 1; + efile = 1; + RunExecute(1); +} + +void OnRunElf_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnFile_LoadElf() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Psx Elf File")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnFile_Exit() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256]; + + // with this the problem with plugins that are linked with the pthread + // library is solved + + dir = opendir(Config.PluginsDir); + if (dir != NULL) { + while ((ent = readdir(dir)) != NULL) { + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) continue; + } + } + + printf(_("PCSX2 Quitting\n")); + if (UseGui) gtk_main_quit(); + SysClose(); + if (UseGui) gtk_exit(0); + else exit(0); +} + +void OnEmu_Run() { + RunExecute(1); +} + +void OnEmu_Reset() { + needreset = 1; +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + GtkWidget *Item; + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "GtkMenuItem_LoadSlot%d", i+1); + Item = lookup_widget(Window, str); + if (Slots[i] == -1) + gtk_widget_set_sensitive(Item, FALSE); + else + gtk_widget_set_sensitive(Item, TRUE); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "sstates/%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %d"), num+1); + else sprintf (Text, _("*PCSX*: Error Saving State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnStates_Load1() { States_Load(0); } +void OnStates_Load2() { States_Load(1); } +void OnStates_Load3() { States_Load(2); } +void OnStates_Load4() { States_Load(3); } +void OnStates_Load5() { States_Load(4); } + +void OnLoadOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + + efile = 2; + RunExecute(0); + + ret = LoadState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Loaded State %s"), str); + else sprintf (Text, _("*PCSX*: Error Loading State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnLoadOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_LoadOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +void OnSaveOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + RunExecute(0); + + ret = SaveState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %s"), str); + else sprintf (Text, _("*PCSX*: Error Saving State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnSaveOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_SaveOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +//2002-09-28 (Florin) +void OnArguments_Ok() { + GtkWidget *widgetCmdLine; + char *str; + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + str = gtk_entry_get_text(GTK_ENTRY(widgetCmdLine)); + memcpy(args, str, 256); + + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnArguments_Cancel() { + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnEmu_Arguments() { + GtkWidget *widgetCmdLine; + + CmdLine = create_CmdLine(); + gtk_window_set_title(GTK_WINDOW(CmdLine), _("Program arguments")); + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + gtk_entry_set_text(GTK_ENTRY(widgetCmdLine), args); + //args exported by ElfHeader.h + gtk_widget_show_all(CmdLine); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} +//------------------- + +void OnConf_Gs() { + gtk_widget_set_sensitive(Window, FALSE); + GSconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Pads() { + gtk_widget_set_sensitive(Window, FALSE); + PAD1configure(); + if (strcmp(Config.PAD1, Config.PAD2)) PAD2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Spu2() { + gtk_widget_set_sensitive(Window, FALSE); + SPU2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Cdvd() { + gtk_widget_set_sensitive(Window, FALSE); + CDVDconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Dev9() { + gtk_widget_set_sensitive(Window, FALSE); + DEV9configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Usb() { + gtk_widget_set_sensitive(Window, FALSE); + USBconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Fw() { + gtk_widget_set_sensitive(Window, FALSE); + FWconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +GtkWidget *CpuDlg; + +void OnCpu_Ok() { + GtkWidget *Btn; + long t; + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + Config.Regcaching = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + Config.Patch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + t = Config.Cpu; + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (t != Config.Cpu) { + cpuRestartCPU(); + } + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + Config.VUrec = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + Config.PsxOut = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + gtk_widget_destroy(CpuDlg); + + SaveConfig(); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnCpu_Cancel() { + gtk_widget_destroy(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + + +void OnConf_Cpu() { + GtkWidget *Btn; + + CpuDlg = create_CpuDlg(); + gtk_window_set_title(GTK_WINDOW(CpuDlg), _("Configuration")); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Cpu); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.PsxOut); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Regcaching); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.VUrec); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Patch); + +#ifndef CPU_LOG + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_widget_set_sensitive(Btn, FALSE); + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_widget_set_sensitive(Btn, FALSE); +#endif + + gtk_widget_show_all(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +#define FindComboText(combo,list,conf) \ + if (strlen(conf) > 0) { \ + int i; \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(conf, list[i-2])) { \ + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), list[i-1]); \ + break; \ + } \ + } \ + } + +#define GetComboText(combo,list,conf) \ + { \ + int i; \ + char *tmp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(tmp, list[i-1])) { \ + strcpy(conf, list[i-2]); \ + break; \ + } \ + } \ + } + +void OnConfConf_Ok() { + GetComboText(GSConfS.Combo, GSConfS.plist, Config.GS) + GetComboText(PAD1ConfS.Combo, PAD1ConfS.plist, Config.PAD1); + GetComboText(PAD2ConfS.Combo, PAD2ConfS.plist, Config.PAD2); + GetComboText(SPU2ConfS.Combo, SPU2ConfS.plist, Config.SPU2); + GetComboText(CDVDConfS.Combo, CDVDConfS.plist, Config.CDVD); + GetComboText(DEV9ConfS.Combo, DEV9ConfS.plist, Config.DEV9); + GetComboText(USBConfS.Combo, USBConfS.plist, Config.USB); + GetComboText(FWConfS.Combo, FWConfS.plist, Config.FW); + GetComboText(BiosConfS.Combo, BiosConfS.plist, Config.Bios); + + SaveConfig(); + + if (confplug == 0) { + ReleasePlugins(); + LoadPlugins(); + } + + needreset = 1; + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 1; +} + +void OnConfConf_Cancel() { + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 0; +} + +#define ConfPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) conf(); \ + SysCloseLibrary(drv); + +#define TestPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + int ret = 0; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) { \ + ret = conf(); \ + if (ret == 0) \ + SysMessage(_("This plugin reports that should work correctly")); \ + else SysMessage(_("This plugin reports that should not work correctly")); \ + } \ + SysCloseLibrary(drv); + +void OnConfConf_GsConf() { + ConfPlugin(_GSconfigure, GSConfS, Config.GS, "GSconfigure"); +} + +void OnConfConf_GsTest() { + TestPlugin(_GStest, GSConfS, Config.GS, "GStest"); +} + +void OnConfConf_GsAbout() { + ConfPlugin(_GSabout, GSConfS, Config.GS, "GSabout"); +} + +void OnConfConf_Pad1Conf() { + ConfPlugin(_PADconfigure, PAD1ConfS, Config.PAD1, "PADconfigure"); +} + +void OnConfConf_Pad1Test() { + TestPlugin(_PADtest, PAD1ConfS, Config.PAD1, "PADtest"); +} + +void OnConfConf_Pad1About() { + ConfPlugin(_PADabout, PAD1ConfS, Config.PAD1, "PADabout"); +} + +void OnConfConf_Pad2Conf() { + ConfPlugin(_PADconfigure, PAD2ConfS, Config.PAD2, "PADconfigure"); +} + +void OnConfConf_Pad2Test() { + TestPlugin(_PADtest, PAD2ConfS, Config.PAD2, "PADtest"); +} + +void OnConfConf_Pad2About() { + ConfPlugin(_PADabout, PAD2ConfS, Config.PAD2, "PADabout"); +} + +void OnConfConf_Spu2Conf() { + ConfPlugin(_SPU2configure, SPU2ConfS, Config.SPU2, "SPU2configure"); +} + +void OnConfConf_Spu2Test() { + TestPlugin(_SPU2test, SPU2ConfS, Config.SPU2, "SPU2test"); +} + +void OnConfConf_Spu2About() { + ConfPlugin(_SPU2about, SPU2ConfS, Config.SPU2, "SPU2about"); +} + +void OnConfConf_CdvdConf() { + ConfPlugin(_CDVDconfigure, CDVDConfS, Config.CDVD, "CDVDconfigure"); +} + +void OnConfConf_CdvdTest() { + TestPlugin(_CDVDtest, CDVDConfS, Config.CDVD, "CDVDtest"); +} + +void OnConfConf_CdvdAbout() { + ConfPlugin(_CDVDabout, CDVDConfS, Config.CDVD, "CDVDabout"); +} + +void OnConfConf_Dev9Conf() { + ConfPlugin(_DEV9configure, DEV9ConfS, Config.DEV9, "DEV9configure"); +} + +void OnConfConf_Dev9Test() { + TestPlugin(_DEV9test, DEV9ConfS, Config.DEV9, "DEV9test"); +} + +void OnConfConf_Dev9About() { + ConfPlugin(_DEV9about, DEV9ConfS, Config.DEV9, "DEV9about"); +} + +void OnConfConf_UsbConf() { + ConfPlugin(_USBconfigure, USBConfS, Config.USB, "USBconfigure"); +} + +void OnConfConf_UsbTest() { + TestPlugin(_USBtest, USBConfS, Config.USB, "USBtest"); +} + +void OnConfConf_UsbAbout() { + ConfPlugin(_USBabout, USBConfS, Config.USB, "USBabout"); +} + +void OnConfConf_FWConf() { + ConfPlugin(_FWconfigure, FWConfS, Config.FW, "FWconfigure"); +} + +void OnConfConf_FWTest() { + TestPlugin(_FWtest, FWConfS, Config.FW, "FWtest"); +} + +void OnConfConf_FWAbout() { + ConfPlugin(_FWabout, FWConfS, Config.FW, "FWabout"); +} + +#define ConfCreatePConf(name, type) \ + type##ConfS.Combo = lookup_widget(ConfDlg, "GtkCombo_" name); \ + gtk_combo_set_popdown_strings(GTK_COMBO(type##ConfS.Combo), type##ConfS.glist); \ + FindComboText(type##ConfS.Combo, type##ConfS.plist, Config.type); \ + +void UpdateConfDlg() { + FindPlugins(); + + ConfCreatePConf("Gs", GS); + ConfCreatePConf("Pad1", PAD1); + ConfCreatePConf("Pad2", PAD2); + ConfCreatePConf("Spu2", SPU2); + ConfCreatePConf("Cdvd", CDVD); + ConfCreatePConf("Dev9", DEV9); + ConfCreatePConf("Usb", USB); + ConfCreatePConf("FW", FW); + ConfCreatePConf("Bios", Bios); +} + +void OnPluginsPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.PluginsDir, File); + if (Config.PluginsDir[strlen(Config.PluginsDir)-1] != '/') + strcat(Config.PluginsDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnPluginsPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_PluginsPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Plugins Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnBiosPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.BiosDir, File); + if (Config.BiosDir[strlen(Config.BiosDir)-1] != '/') + strcat(Config.BiosDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnBiosPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_BiosPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Bios Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnConf_Conf() { + FindPlugins(); + + ConfDlg = create_ConfDlg(); + gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configuration")); + + UpdateConfDlg(); + + gtk_widget_show_all(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +GtkWidget *CmdLine; +GtkWidget *ListDV; +GtkWidget *SetPCDlg, *SetPCEntry; +GtkWidget *SetBPADlg, *SetBPAEntry; +GtkWidget *SetBPCDlg, *SetBPCEntry; +GtkWidget *DumpCDlg, *DumpCTEntry, *DumpCFEntry; +GtkWidget *DumpRDlg, *DumpRTEntry, *DumpRFEntry; +GtkWidget *MemWriteDlg, *MemEntry, *DataEntry; +GtkAdjustment *DebugAdj; +static u32 dPC; +static u32 dBPA = -1; +static u32 dBPC = -1; +static char nullAddr[256]; +int DebugMode; // 0 - EE | 1 - IOP + +#include "R3000A.h" +#include "PsxMem.h" + +void UpdateDebugger() { + GtkWidget *item; + char *str; + int i; + GList *list = NULL; + u32 pc; + + DebugAdj->value = (gfloat)dPC/4; + + gtk_list_clear_items(GTK_LIST(ListDV), 0, 23); + + for (i=0; i<23; i++) { + u32 *mem; + pc = dPC + i*4; + if (DebugMode) { + mem = (u32*)PSXM(pc); + } else + mem = PSM(pc); + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", pc); str = nullAddr; } + else str = disR5900Fasm(*mem, pc); + item = gtk_list_item_new_with_label(str); + gtk_widget_show(item); + list = g_list_append(list, item); + } + gtk_list_append_items(GTK_LIST(ListDV), list); +} + +void OnDebug_Close() { + ClosePlugins(); + gtk_widget_destroy(DebugWnd); + gtk_main_quit(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnDebug_ScrollChange(GtkAdjustment *adj) { + dPC = (u32)adj->value*4; + dPC&= ~0x3; + + UpdateDebugger(); +} + +void OnSetPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetPCEntry)); + + sscanf(str, "%lx", &dPC); + dPC&= ~0x3; + + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetPC_Cancel() { + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetPC() { + SetPCDlg = create_SetPCDlg(); + + SetPCEntry = lookup_widget(SetPCDlg, "GtkEntry_dPC"); + + gtk_widget_show_all(SetPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPA_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPAEntry)); + + sscanf(str, "%lx", &dBPA); + dBPA&= ~0x3; + + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPA_Cancel() { + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPA() { + SetBPADlg = create_SetBPADlg(); + + SetBPAEntry = lookup_widget(SetBPADlg, "GtkEntry_BPA"); + + gtk_widget_show_all(SetBPADlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPCEntry)); + + sscanf(str, "%lx", &dBPC); + + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPC_Cancel() { + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPC() { + SetBPCDlg = create_SetBPCDlg(); + + SetBPCEntry = lookup_widget(SetBPCDlg, "GtkEntry_BPC"); + + gtk_widget_show_all(SetBPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_ClearBPs() { + dBPA = -1; + dBPC = -1; +} + +void OnDumpC_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpCFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpCTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", addrf); str = nullAddr; } + else str = disR5900Fasm(*mem, addrf); + + fprintf(f, "%s\n", str); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpC_Cancel() { + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_DumpCode() { + DumpCDlg = create_DumpCDlg(); + + DumpCFEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCF"); + DumpCTEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCT"); + + gtk_widget_show_all(DumpCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDumpR_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpRFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpRTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + u32 out; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) out = 0; + else out = *mem; + + fwrite(&out, 4, 1, f); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpR_Cancel() { + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_RawDump() { + DumpRDlg = create_DumpRDlg(); + + DumpRFEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRF"); + DumpRTEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRT"); + + gtk_widget_show_all(DumpRDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_Step() { + Cpu->Step(); + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Skip() { + cpuRegs.pc+= 4; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +int HasBreakPoint(u32 pc) { + if (pc == dBPA) return 1; + if (DebugMode == 0) { + if ((cpuRegs.cycle - 10) <= dBPC && + (cpuRegs.cycle + 10) >= dBPC) return 1; + } else { + if ((psxRegs.cycle - 100) <= dBPC && + (psxRegs.cycle + 100) >= dBPC) return 1; + } + return 0; +} + +void OnDebug_Go() { + for (;;) { + if (HasBreakPoint(cpuRegs.pc)) break; + Cpu->Step(); + } + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Log() { + Log = 1 - Log; +} + +void OnDebug_EEMode() { + DebugMode = 0; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_IOPMode() { + DebugMode = 1; + dPC = psxRegs.pc; + UpdateDebugger(); +} + +void OnMemWrite32_Ok() { + char *mem = gtk_entry_get_text(GTK_ENTRY(MemEntry)); + char *data = gtk_entry_get_text(GTK_ENTRY(DataEntry)); + + printf("memWrite32: %s, %s\n", mem, data); + memWrite32(strtol(mem, (char**)NULL, 0), strtol(data, (char**)NULL, 0)); + + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnMemWrite32_Cancel() { + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_memWrite32() { + MemWriteDlg = create_MemWrite32(); + + MemEntry = lookup_widget(MemWriteDlg, "GtkEntry_Mem"); + DataEntry = lookup_widget(MemWriteDlg, "GtkEntry_Data"); + + gtk_widget_show_all(MemWriteDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); + + UpdateDebugger(); +} + +void OnDebug_Debugger() { + GtkWidget *scroll; + + if (OpenPlugins() == -1) return; + if (needreset) { SysReset(); needreset = 0; } + + if (!efile) + efile=GetPS2ElfName(elfname); + if (efile) + loadElfFile(elfname); + efile=0; + + dPC = cpuRegs.pc; + + DebugWnd = create_DebugWnd(); + + ListDV = lookup_widget(DebugWnd, "GtkList_DisView"); + scroll = lookup_widget(DebugWnd, "GtkVScrollbar_VList"); + + DebugAdj = GTK_RANGE(scroll)->adjustment; + DebugAdj->lower = (gfloat)0x00000000/4; + DebugAdj->upper = (gfloat)0xffffffff/4; + DebugAdj->step_increment = (gfloat)1; + DebugAdj->page_increment = (gfloat)20; + DebugAdj->page_size = (gfloat)23; + + gtk_signal_connect(GTK_OBJECT(DebugAdj), + "value_changed", GTK_SIGNAL_FUNC(OnDebug_ScrollChange), + NULL); + + UpdateDebugger(); + + gtk_widget_show_all(DebugWnd); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +void OnLogging_Ok() { + GtkWidget *Btn; + char str[32]; + int i, ret; + + for (i=0; i<17; i++) { + sprintf(str, "Log%d", i); + Btn = lookup_widget(LogDlg, str); + ret = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (ret) varLog|= 1<d_name); \ + type##ConfS.glist = g_list_append(type##ConfS.glist, type##ConfS.plist[type##ConfS.plugins-1]); \ +} + +void FindPlugins() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256],name[256]; + + GSConfS.plugins = 0; CDVDConfS.plugins = 0; DEV9ConfS.plugins = 0; + PAD1ConfS.plugins = 0; PAD2ConfS.plugins = 0; SPU2ConfS.plugins = 0; + USBConfS.plugins = 0; FWConfS.plugins = 0; BiosConfS.plugins = 0; + GSConfS.glist = NULL; CDVDConfS.glist = NULL; DEV9ConfS.glist = NULL; + PAD1ConfS.glist = NULL; PAD2ConfS.glist = NULL; SPU2ConfS.glist = NULL; + USBConfS.glist = NULL; FWConfS.glist = NULL; BiosConfS.glist = NULL; + + dir = opendir(Config.PluginsDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.PluginsDir); + return; + } + while ((ent = readdir(dir)) != NULL) { + u32 version; + u32 type; + + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) { + printf("%s\n", dlerror()); continue; + } + + PS2EgetLibType = (_PS2EgetLibType) dlsym(Handle, "PS2EgetLibType"); + PS2EgetLibName = (_PS2EgetLibName) dlsym(Handle, "PS2EgetLibName"); + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) dlsym(Handle, "PS2EgetLibVersion2"); + if (PS2EgetLibType == NULL || PS2EgetLibName == NULL || PS2EgetLibVersion2 == NULL) + continue; + type = PS2EgetLibType(); + + if (type & PS2E_LT_GS) { + version = PS2EgetLibVersion2(PS2E_LT_GS); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_GS_VERSION) { + ComboAddPlugin(GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)dlsym(Handle, "PADquery"); + version = PS2EgetLibVersion2(PS2E_LT_PAD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(PAD1); + if (query() & 0x2) + ComboAddPlugin(PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2EgetLibVersion2(PS2E_LT_SPU2); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_SPU2_VERSION) { + ComboAddPlugin(SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2EgetLibVersion2(PS2E_LT_CDVD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_CDVD_VERSION) { + ComboAddPlugin(CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2EgetLibVersion2(PS2E_LT_DEV9); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_DEV9_VERSION) { + ComboAddPlugin(DEV9); + } else SysPrintf("DEV9Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2EgetLibVersion2(PS2E_LT_USB); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_USB_VERSION) { + ComboAddPlugin(USB); + } else SysPrintf("USBPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2EgetLibVersion2(PS2E_LT_FW); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_FW_VERSION) { + ComboAddPlugin(FW); + } else SysPrintf("FWPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_FW_VERSION); + } + } + closedir(dir); + + dir = opendir(Config.BiosDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.BiosDir); + return; + } + + while ((ent = readdir(dir)) != NULL) { + struct stat buf; + char description[50]; //2002-09-28 (Florin) + + sprintf (plugin, "%s%s", Config.BiosDir, ent->d_name); + if (stat(plugin, &buf) == -1) continue; +// if (buf.st_size < (1024*512)) continue; + if (buf.st_size > (1024*4096)) continue; //2002-09-28 (Florin) + if (!IsBIOS(ent->d_name, description)) continue;//2002-09-28 (Florin) + + BiosConfS.plugins+=2; + sprintf(description, "%s (%s)", description, ent->d_name); + strcpy(BiosConfS.plist[BiosConfS.plugins-1], description);//2002-09-28 (Florin) modified + strcpy(BiosConfS.plist[BiosConfS.plugins-2], ent->d_name); + BiosConfS.glist = g_list_append(BiosConfS.glist, BiosConfS.plist[BiosConfS.plugins-1]); + } + closedir(dir); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + if (!UseGui) { printf("%s\n",msg); return; } + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), _("PCSX2 Msg")); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label(_("Ok")); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} diff --git a/branches/pcsx2_0.9.1/Linux/Linux.h b/branches/pcsx2_0.9.1/Linux/Linux.h new file mode 100644 index 0000000..cc966bb --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/Linux.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + +#include "Common.h" + +typedef struct { + char lang[256]; +} _langs; + +_langs *langs; +unsigned int langsMax; + +extern int UseGui; +char cfgfile[256]; + +int LoadConfig(); +void SaveConfig(); + +void StartGui(); +void RunGui(); + +int Pcsx2Configure(); + +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); + +#endif /* __LINUX_H__ */ diff --git a/branches/pcsx2_0.9.1/Linux/LnxMain.c b/branches/pcsx2_0.9.1/Linux/LnxMain.c new file mode 100644 index 0000000..ac8e48c --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/LnxMain.c @@ -0,0 +1,327 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "Linux.h" + + +static char Pcsx2Help[] = { + "Pcsx2 " PCSX2_VERSION "\n" + " pcsx2 [options] [file]\n" + "\toptions:\n" + "\t-nogui\t\tDon't open GtkGui\n" + "\t-cfg FILE\tLoads desired configuration file (def:Pcsx2.cfg)\n" + "\t-psxout\t\tEnable psx output\n" + "\t-h -help\tThis help\n" + "\tfile\t\tLoads file\n" +}; + +int UseGui = 1; +int needReset = 1; + + +int main(int argc, char *argv[]) { + char *file = NULL; + char elfname[256]; + char *lang; + int runcd=0; + int efile; + int i; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, "Langs"); + textdomain(PACKAGE); +#endif + + strcpy(cfgfile, "Pcsx2.cfg"); + + for (i=1; iExecute(); + + return 0; +} + +DIR *dir; + +void InitLanguages() { + dir = opendir("Langs"); +} + +char *GetLanguageNext() { + struct dirent *ent; + + if (dir == NULL) return NULL; + for (;;) { + ent = readdir(dir); + if (ent == NULL) return NULL; + + if (!strcmp(ent->d_name, ".")) continue; + if (!strcmp(ent->d_name, "..")) continue; + break; + } + + return ent->d_name; +} + +void CloseLanguages() { + if (dir) closedir(dir); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +int StatesC = 0; + +void KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case XK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Saved State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Saving State %d"), StatesC+1); + GPU_displayText(Text); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F2: + if (StatesC < 4) StatesC++; + else StatesC = 0; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); +/* GPU_freeze(2, (GPUFreeze_t *)&StatesC); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Loaded State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Loading State %d"), StatesC+1); + GPU_displayText(Text);*/ + break; + case XK_F5: +// if (sio2.hackedRecv==0x1D100) sio2.hackedRecv=0x1100; +// else sio2.hackedRecv=0x1D100; +// SysPrintf("hackedRecv : %x\n", sio2.hackedRecv); + break; + + case XK_F8: + GSmakeSnapshot("snap/"); + break; +#ifdef CPU_LOG + case XK_F9: + Log = 1 - Log; + SysPrintf("Log : %d\n", Log); + break; + case XK_F10: +/* if (varLog & 0x40000000) varLog&=~0x40000000; + else varLog|= 0x40000000; + SysPrintf("varLog %x\n", varLog);*/ + SysPrintf("hack\n"); + psxSu32(0x30) = 0x20000; +// psMu32(0x8010c904) = 0; + break; +#endif + case XK_F11: + SysPrintf("Open\n"); + cdCaseopen = 1; + break; + case XK_F12: + SysPrintf("Close\n"); + cdCaseopen = 0; + break; + case XK_Escape: + signal(SIGINT, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + ClosePlugins(); + if (!UseGui) exit(0); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +int SysInit() { + mkdir("sstates", 0755); + mkdir("memcards", 0755); + + cpuInit(); + while (LoadPlugins() == -1) { + if (Pcsx2Configure() == 0) exit(1); + } + + return 0; +} + +void SysReset() { + cpuReset(); +} + +void SysClose() { + cpuShutdown(); + ReleasePlugins(); + + if (emuLog != NULL) fclose(emuLog); +} + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (Config.PsxOut) { printf("%s", msg); fflush(stdout); } +#ifdef EMU_LOG + fprintf(emuLog, "%s", msg); +#endif +} + +void *SysLoadLibrary(char *lib) { + return dlopen(lib, RTLD_NOW); +} + +void *SysLoadSym(void *lib, char *sym) { + return dlsym(lib, sym); +} + +char *SysLibError() { + return dlerror(); +} + +void SysCloseLibrary(void *lib) { + dlclose(lib); +} + +void SysUpdate() { + KeyEvent(PAD1keyEvent()); + KeyEvent(PAD1keyEvent()); +} + +void SysRunGui() { + RunGui(); +} + +void *SysMmap(uptr base, u32 size) { + return mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +} + +void SysMunmap(uptr base, u32 size) { + munmap((uptr*)base, size); +} + diff --git a/branches/pcsx2_0.9.1/Linux/Makefile b/branches/pcsx2_0.9.1/Linux/Makefile new file mode 100644 index 0000000..b970e83 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/Makefile @@ -0,0 +1,106 @@ +# +# PCSX2 Makefile for Linux +# + + +all: pcsx2 + +CPU = i386 +#CPU = x86_64 + +PCSX2 = pcsx2 + +CC = gcc +RM = rm -f +AR = ar +STRIP = strip + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +SSEOPTIMIZE = -O4 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 + +FLAGS = -D__LINUX__ -DENABLE_NLS -DPACKAGE=\"pcsx2\" +# this includes the option -rdynamic and we don't want that +LIBST = $(shell gtk-config --libs) +LIBS = $(subst -rdynamic,,${LIBST}) -lz -lpthread + +OBJS = ../Counters.o ../DebugTools/DisR5900.o ../Elfheader.o \ + ../Hw.o ../Memory.o ../Misc.o ../GS.o ../FiFo.o ../Sif.o\ + ../Plugins.o ../R5900.o ../InterTables.o ../Interpreter.o \ + ../COP0.o ../FPU.o ../VU0.o ../VU0micro.o ../VU1micro.o ../VUflags.o \ + ../MMI.o ../Vif.o ../SPR.o ../DebugTools/DisR5900asm.o ../IPU/IPU.o \ + ../DebugTools/DisVU0Micro.o ../DebugTools/DisVU1Micro.o ../CDVDiso.o ../CDVDisodrv.o \ + ../DebugTools/cpuopsDebug.o ../IPU/yuv2rgb.o \ + ../IPU/mpeg2lib/Idct.o ../IPU/mpeg2lib/Mpeg.o \ + ../Patch.o ../Stats.o ../VUops.o ../Cache.o ../VifDma.o ../FPU2.o +OBJS+= ../R3000A.o ../DebugTools/DisR3000A.o ../PsxBios.o \ + ../PsxMem.o ../PsxInterpreter.o ../PsxCounters.o ../PsxHw.o \ + ../PsxDma.o ../Gte.o ../Sio.o ../CdRom.o ../Mdec.o \ + ../Decode_XA.o ../PsxGPU.o ../PsxSio2.o ../CDVD.o + +OBJS+= LnxMain.o Config.o GtkGui.o +OBJS+= GladeGui.o GladeFuncs.o + +ifeq (${CPU}, i386) + OBJS+= ../x86/iR5900.o ../ix86-32/iR5900Arit.o ../ix86-32/iR5900AritImm.o \ + ../ix86-32/iR5900Branch.o ../ix86-32/iR5900Jump.o ../ix86-32/iR5900LoadStore.o \ + ../ix86-32/iR5900Move.o ../ix86-32/iR5900MultDiv.o ../ix86-32/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o + FLAGS+= -I../ix86-32 -I../x86 +endif + +ifeq (${CPU}, x86_64) + OBJS+= ../x86/iR5900.o ../x86-64/iR5900Arit.o ../x86-64/iR5900AritImm.o \ + ../x86-64/iR5900Branch.o ../x86-64/iR5900Jump.o ../x86-64/iR5900LoadStore.o \ + ../x86-64/iR5900Move.o ../x86-64/iR5900MultDiv.o ../x86-64/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o + FLAGS+= -I../x86-64 -I../x86 +endif + +DEPS:= $(OBJS:.o=.d) +ROBJS:= $(OBJS:.o=.ro) +RSOBJS:= $(OBJS:.o=.rso) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I../IPU -I../DebugTools ${FLAGS} +CSSEFLAGS = -Wall ${SSEOPTIMIZE} -I. -I.. -I../IPU -I../DebugTools ${FLAGS} +CFLAGS+= $(shell gtk-config --cflags) +CSSEFLAGS+= $(shell gtk-config --cflags) + +pcsx2: ${OBJS} + ${CC} ${CFLAGS} ${OBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +release: ${ROBJS} + ${CC} ${CFLAGS} ${ROBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +release-sse: ${RSOBJS} + ${CC} ${CSSEFLAGS} ${RSOBJS} -o pcsx2 ${LIBS} +# ${STRIP} pcsx2 + +.PHONY: clean pcsx2 release release-sse + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} ${ROBJS} ${RSOBJS} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.ro: %.c + ${CC} ${CFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.rso: %.c + ${CC} ${CSSEFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} + + diff --git a/branches/pcsx2_0.9.1/Linux/Makefile.cfg.in b/branches/pcsx2_0.9.1/Linux/Makefile.cfg.in new file mode 100644 index 0000000..e53cbd5 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/Makefile.cfg.in @@ -0,0 +1,6 @@ + +CC = @CC@ +LIBS = @LIBS@ @GTK_LIBS@ +CFLAGS = @CFLAGS@ @GTK_CFLAGS@ +STRIP = @STRIP@ +RM = @RM@ diff --git a/branches/pcsx2_0.9.1/Linux/configure.in b/branches/pcsx2_0.9.1/Linux/configure.in new file mode 100644 index 0000000..fecf117 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/configure.in @@ -0,0 +1,33 @@ +dnl Process this file with autoconf to produce a configure script. +dnl by Linuzappz +dnl autoconf version 2.13 + +AC_INIT(LnxMain.c) +AM_INIT_AUTOMAKE(PCSX2, 0.9) +AM_MAINTAINTER_MODE +AC_PROG_CC +AC_CHECK_PROG(STRIP, strip, strip) +AC_CHECK_PROG(RM, rm, rm) + +CFLAGS="" + +dnl check for libraries + +dnl gtk2=yes + +AC_MSG_CHECKING(gtk+) + +AC_CHECK_PROG(GTK-CONFIG, gtk-config, gtk-config) + +dnl end + +AC_SUBST(CFLAGS) +AC_SUBST(OBJS) +AC_SUBST(LIBS) +AC_SUBST(STRIP) +AC_SUBST(RM) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) + +AC_OUTPUT(Makefile.cfg) + diff --git a/branches/pcsx2_0.9.1/Linux/pcsx2.glade b/branches/pcsx2_0.9.1/Linux/pcsx2.glade new file mode 100644 index 0000000..d8fb948 --- /dev/null +++ b/branches/pcsx2_0.9.1/Linux/pcsx2.glade @@ -0,0 +1,4413 @@ + + + + + Pcsx2 + pcsx2 + + + .pixmaps + C + False + True + False + False + False + GladeGui.c + GladeGui.h + GladeCalls.c + GladeCalls.h + GladeFuncs.c + GladeFuncs.h + + + + GtkWindow + MainWindow + 200 + + destroy + OnDestroy + Tue, 19 Feb 2002 22:15:57 GMT + + PCSX + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox1 + False + 0 + + + GtkMenuBar + GtkMenuBar_Menu + GTK_SHADOW_OUT + + 0 + False + False + + + + GtkMenuItem + GtkMenuItem_File + + False + + + GtkMenu + GtkMenuItem_File_menu + + + GtkMenuItem + run_cd1 + + activate + OnFile_RunCD + Tue, 17 Jun 2003 17:35:02 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_LoadElf + + activate + OnFile_LoadElf + Fri, 05 Apr 2002 19:47:01 GMT + + + False + + + + GtkMenuItem + separator2 + False + + + + GtkMenuItem + states1 + + False + + + GtkMenu + states1_menu + + + GtkMenuItem + load1 + + False + + + GtkMenu + load1_menu + + + GtkMenuItem + slot_1 + + activate + OnStates_Load1 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_3 + + activate + OnStates_Load2 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_4 + + activate + OnStates_Load3 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_5 + + activate + OnStates_Load4 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_2 + + activate + OnStates_Load5 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + other1 + + activate + OnStates_LoadOther + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + + + GtkMenuItem + save1 + + False + + + GtkMenu + save1_menu + + + GtkMenuItem + slot_6 + + activate + OnStates_Save1 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_7 + + activate + OnStates_Save2 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_8 + + activate + OnStates_Save3 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_9 + + activate + OnStates_Save4 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + slot_10 + + activate + OnStates_Save5 + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + GtkMenuItem + other2 + + activate + OnStates_SaveOther + Fri, 20 Feb 2004 14:16:44 GMT + + + False + + + + + + + + GtkMenuItem + GtkMenuItem_Exit + + activate + OnFile_Exit + Thu, 06 Dec 2001 03:20:01 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Emulator + + False + + + GtkMenu + GtkMenuItem_Emulator_menu + + + GtkMenuItem + GtkMenuItem_Run + + activate + OnEmu_Run + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Reset + + activate + OnEmu_Reset + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Arguments + + activate + OnEmu_Arguments + Sun, 29 Sep 2002 04:59:42 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Configuration + + False + + + GtkMenu + GtkMenuItem_Configuration_menu + + + GtkMenuItem + GtkMenuItem_PluginsBios + + activate + OnConf_Conf + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + separator3 + False + + + + GtkMenuItem + GtkMenuItem_Graphics + + activate + OnConf_Gs + Fri, 05 Apr 2002 23:41:41 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Controllers + + activate + OnConf_Pads + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Sound + + activate + OnConf_Spu2 + Sat, 06 Jul 2002 05:35:47 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Cdvdrom + + activate + OnConf_Cdvd + Sat, 06 Jul 2002 05:35:47 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Dev9 + + activate + OnConf_Dev9 + Tue, 02 Sep 2003 17:41:31 GMT + + + False + + + + GtkMenuItem + separator4 + False + + + + GtkMenuItem + GtkMenuItem_Cpu + + activate + OnConf_Cpu + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Language + + False + + + + GtkMenuItem + GtkMenuItem_Debug + + False + + + GtkMenu + GtkMenuItem_Debug_menu + + + GtkMenuItem + GtkMenuItem_EnterDebugger + + activate + OnDebug_Debugger + Mon, 27 May 2002 04:44:12 GMT + + + False + + + + GtkMenuItem + GtkMenuItem_Logging + + activate + OnDebug_Logging + Wed, 26 Jun 2002 05:04:32 GMT + + + False + + + + + + GtkMenuItem + GtkMenuItem_Help + + False + + + GtkMenu + GtkMenuItem_Help_menu + + + GtkMenuItem + GtkMenuItem_About + + activate + OnHelp_About + Thu, 06 Dec 2001 03:37:32 GMT + + + False + + + + + + + + + GtkWindow + AboutDlg + 10 + Pcsx About + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox2 + False + 0 + + + GtkPacker + packer1 + 0 + 0 + 0 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox1 + False + 0 + + 0 + True + True + + + + GtkVBox + vbox4 + False + 0 + + 0 + True + True + + + + GtkLabel + GtkAbout_LabelVersion + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkFrame + frame1 + 5 + 0 + GTK_SHADOW_ETCHED_IN + + 0 + False + False + + + + GtkVBox + vbox6 + 5 + False + 0 + + + GtkLabel + GtkAbout_LabelAuthors + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + + + + GtkPixmap + pixmap1 + pcsxAbout.xpm + 0.5 + 0.5 + 0 + 0 + True + + 0 + True + True + + + + + + GtkFrame + frame2 + 5 + 0 + GTK_SHADOW_ETCHED_IN + + 0 + False + False + + + + GtkVBox + vbox5 + 5 + False + 0 + + + GtkLabel + GtkAbout_LabelGreets + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnHelpAbout_Ok + Thu, 06 Dec 2001 03:47:23 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + ConfDlg + 10 + Conf + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox12 + False + 0 + + + GtkTable + table2 + 14 + 2 + False + 0 + 15 + + 0 + True + True + + + + GtkCombo + GtkCombo_Pad1 + False + True + False + True + False + + + 0 + 1 + 4 + 5 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry4 + True + True + True + 0 + + + + + + GtkCombo + GtkCombo_Pad2 + False + True + False + True + False + + + 1 + 2 + 4 + 5 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry5 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox6 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 5 + 6 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_PAD2configure + True + True + + clicked + OnConfConf_Pad2Conf + Tue, 25 Dec 2001 05:40:52 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD2test + True + True + + clicked + OnConfConf_Pad2Test + Tue, 25 Dec 2001 05:41:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD2about + True + True + + clicked + OnConfConf_Pad2About + Tue, 25 Dec 2001 05:41:18 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox7 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_PAD1configure + True + True + + clicked + OnConfConf_Pad1Conf + Tue, 25 Dec 2001 05:38:17 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD1test + True + True + + clicked + OnConfConf_Pad1Test + Tue, 25 Dec 2001 05:39:35 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_PAD1about + True + True + + clicked + OnConfConf_Pad1About + Tue, 25 Dec 2001 05:39:58 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox8 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 2 + 3 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_GSconfigure + True + True + + clicked + OnConfConf_GsConf + Fri, 05 Apr 2002 23:40:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_GStest + True + True + + clicked + OnConfConf_GsTest + Fri, 05 Apr 2002 23:40:08 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_GSabout + True + True + + clicked + OnConfConf_GsAbout + Fri, 05 Apr 2002 23:40:14 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + GtkLabel_Graphics + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_FirstController + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_SecondController + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 3 + 4 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Gs + False + True + False + True + False + + + 0 + 1 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry2 + True + True + True + 0 + + + + + + GtkLabel + GtkLabel_Sound + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Spu2 + False + True + False + True + False + + + 1 + 2 + 1 + 2 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox12 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_SPU2configure + True + True + + clicked + OnConfConf_Spu2Conf + Sat, 20 Apr 2002 16:13:27 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SPU2test + True + True + + clicked + OnConfConf_Spu2Test + Sat, 20 Apr 2002 16:14:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SPU2about + True + True + + clicked + OnConfConf_Spu2About + Sat, 20 Apr 2002 16:14:16 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkCombo + GtkCombo_Dev9 + False + True + False + True + False + + + 0 + 1 + 7 + 8 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry3 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox21 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 8 + 9 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_DEV9configure + True + True + + clicked + OnConfConf_Dev9Conf + Thu, 21 Aug 2003 18:36:30 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_DEV9test + True + True + + clicked + OnConfConf_Dev9Test + Thu, 21 Aug 2003 18:36:38 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_DEV9about + True + True + + clicked + OnConfConf_Dev9About + Thu, 21 Aug 2003 18:36:48 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label23 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_Cdvdrom + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 6 + 7 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Cdvd + False + True + False + True + False + + + 1 + 2 + 7 + 8 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry2 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox13 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 8 + 9 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_CDVDconfigure + True + True + + clicked + OnConfConf_CdvdConf + Fri, 05 Jul 2002 21:44:43 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_CDVDtest + True + True + + clicked + OnConfConf_CdvdTest + Fri, 05 Jul 2002 21:44:30 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_CDVDabout + True + True + + clicked + OnConfConf_CdvdAbout + Fri, 05 Jul 2002 21:44:07 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label29 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 9 + 10 + 0 + 0 + False + False + False + False + False + False + + + + + GtkCombo + GtkCombo_Usb + False + True + False + True + False + + + 0 + 1 + 10 + 11 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry4 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox23 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + 1 + 11 + 12 + 0 + 0 + False + True + False + False + True + True + + + + GtkButton + GtkButton_USBconfigure + True + True + + clicked + OnConfConf_UsbConf + Mon, 01 Mar 2004 14:21:01 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_USBtest + True + True + + clicked + OnConfConf_UsbTest + Mon, 01 Mar 2004 14:21:09 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_USBabout + True + True + + clicked + OnConfConf_UsbAbout + Mon, 01 Mar 2004 14:21:14 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkCombo + GtkCombo_Bios + False + True + False + True + False + + + 1 + 2 + 13 + 14 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry7 + True + True + True + 0 + + + + + + GtkCombo + GtkCombo_FireWire + False + True + False + True + False + + + 1 + 2 + 10 + 11 + 0 + 0 + True + False + False + False + True + False + + + + GtkEntry + GtkCombo:entry + entry5 + True + True + True + 0 + + + + + + GtkHButtonBox + hbuttonbox24 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 1 + 2 + 11 + 12 + 0 + 0 + False + False + False + False + True + True + + + + GtkButton + GtkButton_FWconfigure + True + True + + clicked + OnConfConf_FWConf + Wed, 17 Nov 2004 03:59:27 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_FWtest + True + True + + clicked + OnConfConf_FWTest + Wed, 17 Nov 2004 03:59:33 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_FireWireabout + True + True + + clicked + OnConfConf_FWAbout + Wed, 17 Nov 2004 04:00:56 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkLabel + label30 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 9 + 10 + 0 + 0 + False + False + False + False + False + False + + + + + GtkLabel + GtkLabel_Bios + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 1 + 2 + 12 + 13 + 0 + 0 + False + False + False + False + False + False + + + + + + GtkHBox + hbox5 + False + 14 + + 0 + True + True + + + + GtkHButtonBox + hbuttonbox11 + GTK_BUTTONBOX_START + 0 + 85 + 27 + 7 + 0 + + 0 + False + True + + + + GtkButton + GtkButton_SelectPluginsDir + True + True + + clicked + OnConfConf_PluginsPath + Mon, 14 Jan 2002 19:18:13 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_SelectBiosDir + True + True + + clicked + OnConfConf_BiosPath + Mon, 14 Jan 2002 19:12:02 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox10 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnConfConf_Ok + Tue, 25 Dec 2001 05:19:01 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnConfConf_Cancel + Tue, 25 Dec 2001 05:19:16 GMT + + + GTK_RELIEF_NORMAL + + + + + + + + GtkWindow + CpuDlg + 5 + Cpu + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox8 + False + 0 + + + GtkHBox + hbox20 + False + 0 + + 0 + True + True + + + + GtkFrame + GtkFrame_Options + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox15 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_PsxOut + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_Patches + True + + False + True + + 0 + False + False + + + + + + + + GtkFrame + frame6 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox26 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_Cpu + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_RegCaching + True + + False + True + + 0 + False + False + + + + + GtkCheckButton + GtkCheckButton_VUrec + True + + False + True + + 0 + False + False + + + + + + + GtkHButtonBox + hbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnCpu_Ok + Fri, 07 Dec 2001 04:34:39 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnCpu_Cancel + Fri, 07 Dec 2001 04:34:55 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DebugWnd + 5 + PCSX2 Debugger + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox16 + 5 + False + 0 + + + GtkHBox + hbox16 + False + 5 + + 0 + True + True + + + + GtkRadioButton + GtkRadioButton_EE + True + + toggled + OnDebug_EEMode + Wed, 26 Jun 2002 22:06:10 GMT + + + False + True + Debug + + 0 + False + False + + + + + GtkRadioButton + GtkRadioButton_IOP + True + + toggled + OnDebug_IOPMode + Wed, 26 Jun 2002 22:06:29 GMT + + + False + True + Debug + + 0 + False + False + + + + + + GtkHBox + hbox6 + 5 + False + 0 + + 0 + True + True + + + + GtkHBox + hbox7 + False + 0 + + 0 + True + True + + + + GtkScrolledWindow + scrolledwindow1 + 320 + GTK_POLICY_ALWAYS + GTK_POLICY_NEVER + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkViewport + viewport1 + GTK_SHADOW_IN + + + GtkList + GtkList_DisView + GTK_SELECTION_SINGLE + + + + + + GtkVScrollbar + GtkVScrollbar_VList + GTK_UPDATE_CONTINUOUS + 0 + 0 + 412 + 1 + 20 + 2 + + 0 + True + True + + + + + + GtkVBox + vbox22 + False + 0 + + 0 + True + True + + + + GtkVButtonBox + vbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button52 + True + True + + clicked + OnDebug_Step + Mon, 27 May 2002 19:06:08 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button53 + True + True + + clicked + OnDebug_Skip + Mon, 03 Jun 2002 04:34:40 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button65 + True + True + + clicked + OnDebug_Go + Mon, 27 May 2002 19:06:18 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button64 + True + True + + clicked + OnDebug_Log + Mon, 27 May 2002 19:06:29 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkVButtonBox + vbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button58 + True + True + + clicked + OnDebug_SetPC + Mon, 27 May 2002 18:53:12 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button59 + True + True + + clicked + OnDebug_SetBPA + Mon, 27 May 2002 19:17:57 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button60 + True + True + + clicked + OnDebug_SetBPC + Thu, 30 May 2002 19:08:00 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button61 + True + True + + clicked + OnDebug_ClearBPs + Fri, 31 May 2002 03:26:43 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkVButtonBox + vbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button39 + True + True + + clicked + OnDebug_DumpCode + Fri, 31 May 2002 03:29:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button40 + True + True + + clicked + OnDebug_RawDump + Fri, 31 May 2002 03:30:44 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button41 + True + True + + clicked + OnDebug_Close + Mon, 27 May 2002 04:56:26 GMT + + + GTK_RELIEF_NORMAL + + + + + + GtkVButtonBox + vbuttonbox4 + GTK_BUTTONBOX_DEFAULT_STYLE + 10 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button68 + True + True + + clicked + OnDebug_memWrite32 + Sat, 01 Nov 2003 04:23:51 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button69 + True + True + + GTK_RELIEF_NORMAL + + + + GtkButton + button70 + True + True + + GTK_RELIEF_NORMAL + + + + + + + + GtkWindow + SetPCDlg + 5 + SetPCDlg + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox17 + 5 + False + 5 + + + GtkLabel + label9 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox8 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label10 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_dPC + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox14 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button42 + True + True + + clicked + OnSetPC_Ok + Mon, 27 May 2002 18:45:45 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button43 + True + True + + clicked + OnSetPC_Cancel + Mon, 27 May 2002 18:45:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + SetBPADlg + 5 + SetBreakPoint Addr + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox18 + 5 + False + 5 + + + GtkLabel + label11 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox9 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label12 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_BPA + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox15 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button44 + True + True + + clicked + OnSetBPA_Ok + Mon, 27 May 2002 19:09:57 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button45 + True + True + + clicked + OnSetBPA_Cancel + Mon, 27 May 2002 19:11:00 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + SetBPCDlg + 5 + SetBreakPoint Addr + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox19 + 5 + False + 5 + + + GtkLabel + label13 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox10 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label14 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_BPC + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox16 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button46 + True + True + + clicked + OnSetBPC_Ok + Fri, 31 May 2002 03:58:44 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button47 + True + True + + clicked + OnSetBPC_Cancel + Fri, 31 May 2002 03:58:38 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DumpCDlg + 5 + Dump code + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox20 + 5 + False + 5 + + + GtkLabel + label15 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox11 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label16 + + GTK_JUSTIFY_CENTER + True + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpCF + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox12 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label17 + 45 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpCT + True + True + True + 8 + + + 0 + True + True + + + + + + GtkLabel + label21 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox17 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button48 + True + True + + clicked + OnDumpC_Ok + Fri, 31 May 2002 03:37:47 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button49 + True + True + + clicked + OnDumpC_Cancel + Fri, 31 May 2002 03:37:40 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + DumpRDlg + 5 + Raw Dump + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox21 + 5 + False + 5 + + + GtkLabel + label18 + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox13 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label19 + + GTK_JUSTIFY_CENTER + True + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpRF + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox14 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label20 + 45 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_DumpRT + True + True + True + 8 + + + 0 + True + True + + + + + + GtkLabel + label22 + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox18 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button50 + True + True + + clicked + OnDumpR_Ok + Fri, 31 May 2002 03:53:48 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button51 + True + True + + clicked + OnDumpR_Cancel + Fri, 31 May 2002 03:54:09 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + Logging + 5 + Logging + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox23 + 5 + False + 5 + + + GtkHBox + hbox15 + 5 + False + 5 + + 0 + True + True + + + + GtkFrame + frame4 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkTable + table3 + 5 + 8 + 3 + False + 5 + 5 + + + GtkCheckButton + Log0 + True + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log1 + True + + False + True + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log2 + True + + False + True + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log3 + True + + False + True + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log4 + True + + False + True + + 0 + 1 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log5 + True + + False + True + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log6 + True + + False + True + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log7 + True + + False + True + + 0 + 1 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log8 + True + + False + True + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log9 + True + + False + True + + 1 + 2 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log10 + True + + False + True + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log11 + True + + False + True + + 1 + 2 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log12 + True + + False + True + + 1 + 2 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log13 + True + + False + True + + 1 + 2 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log15 + True + + False + True + + 1 + 2 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log14 + True + + False + True + + 1 + 2 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log16 + True + + False + True + + 2 + 3 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log31 + True + + False + True + + 2 + 3 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log + True + + False + True + + 2 + 3 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log30 + True + + False + True + + 2 + 3 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + + + GtkFrame + frame5 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkTable + table4 + 5 + 8 + 2 + False + 5 + 5 + + + GtkCheckButton + Log27 + True + + False + True + + 0 + 1 + 7 + 8 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log26 + True + + False + True + + 0 + 1 + 6 + 7 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log25 + True + + False + True + + 0 + 1 + 5 + 6 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log24 + True + + False + True + + 0 + 1 + 4 + 5 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log23 + True + + False + True + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log22 + True + + False + True + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log21 + True + + False + True + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log20 + True + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + Log28 + True + + False + True + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + + + + GtkHButtonBox + hbuttonbox19 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button66 + True + True + + clicked + OnLogging_Ok + Wed, 26 Jun 2002 05:20:00 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button67 + True + True + + clicked + OnLogging_Cancel + Wed, 26 Jun 2002 05:20:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + CmdLine + 5 + Program arguments + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + True + False + False + False + + + GtkVBox + vbox24 + 5 + False + 5 + + + GtkLabel + GtkLabel_Text + + GTK_JUSTIFY_CENTER + False + 0.1 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHBox + hbox17 + 5 + False + 2 + + 0 + False + False + + + + GtkEntry + GtkEntry_dCMDLINE + If you don't know what to write leave it blank + True + True + True + 255 + + + 0 + True + True + + + + + + GtkLabel + GtkLabel_Note + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox20 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Ok + True + True + + clicked + OnArguments_Ok + Sat, 28 Sep 2002 13:54:37 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Cancel + True + True + + clicked + OnArguments_Cancel + Sat, 28 Sep 2002 13:54:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + MemWrite32 + 5 + memWrite32 + GTK_WINDOW_DIALOG + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox25 + 5 + False + 5 + + + GtkHBox + hbox18 + 5 + False + 2 + + 0 + False + False + + + + GtkLabel + label27 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label25 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_Mem + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHBox + hbox19 + 5 + False + 2 + + 0 + True + True + + + + GtkLabel + label28 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label26 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_Data + True + True + True + 8 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox22 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button71 + True + True + + clicked + OnMemWrite32_Ok + Sat, 01 Nov 2003 04:38:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button72 + True + True + + clicked + OnMemWrite32_Cancel + Sat, 01 Nov 2003 04:36:57 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/branches/pcsx2_0.9.1/MMI.c b/branches/pcsx2_0.9.1/MMI.c new file mode 100644 index 0000000..662f324 --- /dev/null +++ b/branches/pcsx2_0.9.1/MMI.c @@ -0,0 +1,1475 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" + + +void MMI() { +#ifdef MMI_LOG + MMI_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_MMIPrintTable[_Funct_](); +} + +void MMI0() { + Int_MMI0PrintTable[_Sa_](); +} + +void MMI1() { + Int_MMI1PrintTable[_Sa_](); +} + +void MMI2() { + Int_MMI2PrintTable[_Sa_](); +} + +void MMI3() { + Int_MMI3PrintTable[_Sa_](); +} + +void MMI_Unknown() { + SysPrintf ("Unknown MMI opcode called\n"); +} + +//*****************MMI OPCODES********************************* + +void MADD() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[0] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +void MADDU() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[0] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +#define _PLZCW(n) { \ + sign = cpuRegs.GPR.r[_Rs_].UL[n] >> 31; \ + for (i=30; i>=0; i--) { \ + if (((cpuRegs.GPR.r[_Rs_].UL[n] >> i) & 0x1) != sign) { \ + break; \ + } \ + } \ + cpuRegs.GPR.r[_Rd_].UL[n] = 30 - i; \ +} + +void PLZCW() { + int i; + u32 sign; + + if (!_Rd_) return; + + _PLZCW (0); + _PLZCW (1); +} + +void MADD1() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[1] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MADDU1() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MFHI1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[1]; +} + +void MFLO1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MTHI1() { + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MTLO1() { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MULT1() { + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[1] = (s64)(s32)(temp & 0xffffffff); + cpuRegs.HI.UD[1] = (s64)(s32)(temp >> 32); + + /* Modified a bit . asadr */ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MULTU1() { + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.UD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void DIV1() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU1() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +#define PMFHL_CLAMP(dst, src) \ + if ((int)src > (int)0x00007fff) dst = 0x7fff; \ + else \ + if ((int)src < (int)0xffff8000) dst = 0x8000; \ + else dst = (u16)src; + +void PMFHL() { + if (!_Rd_) return; + + switch (_Sa_) { + case 0x00: // LW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + break; + + case 0x01: // UW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[3]; + break; + + case 0x02: // SLW + { + u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; + if (TempU64 >= 0x000000007fffffff) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffff; + } else if (TempU64 <= 0xffffffff80000000) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000; + } else { + cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0]; + } + + TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; + if (TempU64 >= 0x000000007fffffff) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffff; + } else if (TempU64 <= 0xffffffff80000000) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000; + } else { + cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2]; + } + } + break; + + case 0x03: // LH + cpuRegs.GPR.r[_Rd_].US[0] = cpuRegs.LO.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = cpuRegs.LO.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = cpuRegs.HI.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = cpuRegs.HI.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = cpuRegs.LO.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = cpuRegs.LO.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = cpuRegs.HI.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = cpuRegs.HI.US[6]; + break; + + case 0x04: // SH + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[0], cpuRegs.LO.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[1], cpuRegs.LO.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[2], cpuRegs.HI.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[3], cpuRegs.HI.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[4], cpuRegs.LO.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[5], cpuRegs.LO.UL[3]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[6], cpuRegs.HI.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[7], cpuRegs.HI.UL[3]); + break; + } +} + +void PMTHL() { + if (_Sa_ != 0) return; + + cpuRegs.LO.UL[0] = cpuRegs.GPR.r[_Rs_].UL[0]; + cpuRegs.HI.UL[0] = cpuRegs.GPR.r[_Rs_].UL[1]; + cpuRegs.LO.UL[2] = cpuRegs.GPR.r[_Rs_].UL[2]; + cpuRegs.HI.UL[2] = cpuRegs.GPR.r[_Rs_].UL[3]; +} + +#define _PSLLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] << ( _Sa_ & 0xf ); + +void PSLLH() { + if (!_Rd_) return; + + _PSLLH(0); _PSLLH(1); _PSLLH(2); _PSLLH(3); + _PSLLH(4); _PSLLH(5); _PSLLH(6); _PSLLH(7); +} + +#define _PSRLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] >> ( _Sa_ & 0xf ); + +void PSRLH () { + if (!_Rd_) return; + + _PSRLH(0); _PSRLH(1); _PSRLH(2); _PSRLH(3); + _PSRLH(4); _PSRLH(5); _PSRLH(6); _PSRLH(7); +} + +#define _PSRAH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n] >> ( _Sa_ & 0xf ); + +void PSRAH() { + if (!_Rd_) return; + + _PSRAH(0); _PSRAH(1); _PSRAH(2); _PSRAH(3); + _PSRAH(4); _PSRAH(5); _PSRAH(6); _PSRAH(7); +} + +#define _PSLLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] << _Sa_; + +void PSLLW() { + if (!_Rd_) return; + + _PSLLW(0); _PSLLW(1); _PSLLW(2); _PSLLW(3); +} + +#define _PSRLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] >> _Sa_; + +void PSRLW() { + if (!_Rd_) return; + + _PSRLW(0); _PSRLW(1); _PSRLW(2); _PSRLW(3); +} + +#define _PSRAW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n] >> _Sa_; + +void PSRAW() { + if (!_Rd_) return; + + _PSRAW(0); _PSRAW(1); _PSRAW(2); _PSRAW(3); +} + +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +#define _PADDW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] + cpuRegs.GPR.r[_Rt_].UL[n]; + +void PADDW() { + if (!_Rd_) return; + + _PADDW(0); _PADDW(1); _PADDW(2); _PADDW(3); +} + +#define _PSUBW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] - cpuRegs.GPR.r[_Rt_].UL[n]; + +void PSUBW() { + if (!_Rd_) return; + + _PSUBW(0); _PSUBW(1); _PSUBW(2); _PSUBW(3); +} + +#define _PCGTW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCGTW() { + if (!_Rd_) return; + + _PCGTW(0); _PCGTW(1); _PCGTW(2); _PCGTW(3); +} + +#define _PMAXW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].UL[n] : cpuRegs.GPR.r[_Rt_].UL[n]; + +void PMAXW() { + if (!_Rd_) return; + + _PMAXW(0); _PMAXW(1); _PMAXW(2); _PMAXW(3); +} + +#define _PADDH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] + cpuRegs.GPR.r[_Rt_].US[n]; + +void PADDH() { + if (!_Rd_) return; + + _PADDH(0); _PADDH(1); _PADDH(2); _PADDH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PSUBH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] - cpuRegs.GPR.r[_Rt_].US[n]; + +void PSUBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PSUBH(4); _PSUBH(5); _PSUBH(6); _PSUBH(7); +} + +#define _PCGTH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + 0xFFFF : 0x0000; + +void PCGTH() { + if (!_Rd_) return; + + _PCGTH(0); _PCGTH(1); _PCGTH(2); _PCGTH(3); + _PCGTH(4); _PCGTH(5); _PCGTH(6); _PCGTH(7); +} + +#define _PMAXH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMAXH() { + if (!_Rd_) return; + + _PMAXH(0); _PMAXH(1); _PMAXH(2); _PMAXH(3); + _PMAXH(4); _PMAXH(5); _PMAXH(6); _PMAXH(7); +} + +#define _PADDB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] + cpuRegs.GPR.r[_Rt_].SC[n]; + +void PADDB() { + if (!_Rd_) return; + + _PADDB(0); _PADDB(1); _PADDB(2); _PADDB(3); + _PADDB(4); _PADDB(5); _PADDB(6); _PADDB(7); + _PADDB(8); _PADDB(9); _PADDB(10); _PADDB(11); + _PADDB(12); _PADDB(13); _PADDB(14); _PADDB(15); +} + +#define _PSUBB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] - cpuRegs.GPR.r[_Rt_].SC[n]; + +void PSUBB() { + if (!_Rd_) return; + + _PSUBB(0); _PSUBB(1); _PSUBB(2); _PSUBB(3); + _PSUBB(4); _PSUBB(5); _PSUBB(6); _PSUBB(7); + _PSUBB(8); _PSUBB(9); _PSUBB(10); _PSUBB(11); + _PSUBB(12); _PSUBB(13); _PSUBB(14); _PSUBB(15); +} + +#define _PCGTB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].SC[n] > cpuRegs.GPR.r[_Rt_].SC[n]) ? \ + 0xFF : 0x00; + +void PCGTB() { + if (!_Rd_) return; + + _PCGTB(0); _PCGTB(1); _PCGTB(2); _PCGTB(3); + _PCGTB(4); _PCGTB(5); _PCGTB(6); _PCGTB(7); + _PCGTB(8); _PCGTB(9); _PCGTB(10); _PCGTB(11); + _PCGTB(12); _PCGTB(13); _PCGTB(14); _PCGTB(15); +} + +#define _PADDSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].SL[n] + (s64)cpuRegs.GPR.r[_Rt_].SL[n]; \ + if (sTemp64 > 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000) && (sTemp64 >= 0x100000000)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PADDSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PADDSW(0); _PADDSW(1); _PADDSW(2); _PADDSW(3); +} + +#define _PSUBSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 >= 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000) && (sTemp64 >= 0x100000000)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PSUBSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBSW(0); _PSUBSW(1); _PSUBSW(2); _PSUBSW(3); +} + +void PEXTLW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[1]; +} + +void PPACW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[2]; +} + +#define _PADDSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] + (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 > 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = (s16)sTemp32; \ + } + +void PADDSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDSH(0); _PADDSH(1); _PADDSH(2); _PADDSH(3); + _PADDSH(4); _PADDSH(5); _PADDSH(6); _PADDSH(7); +} + +#define _PSUBSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] - (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 >= 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (s16)sTemp32; \ + } + +void PSUBSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBSH(0); _PSUBSH(1); _PSUBSH(2); _PSUBSH(3); + _PSUBSH(4); _PSUBSH(5); _PSUBSH(6); _PSUBSH(7); +} + +void PEXTLH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[1]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[3]; +} + +void PPACH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[4] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PADDSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] + (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 > 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PADDSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PADDSB(0); _PADDSB(1); _PADDSB(2); _PADDSB(3); + _PADDSB(4); _PADDSB(5); _PADDSB(6); _PADDSB(7); + _PADDSB(8); _PADDSB(9); _PADDSB(10); _PADDSB(11); + _PADDSB(12); _PADDSB(13); _PADDSB(14); _PADDSB(15); +} + +#define _PSUBSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] - (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 >= 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PSUBSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBSB(0); _PSUBSB(1); _PSUBSB(2); _PSUBSB(3); + _PSUBSB(4); _PSUBSB(5); _PSUBSB(6); _PSUBSB(7); + _PSUBSB(8); _PSUBSB(9); _PSUBSB(10); _PSUBSB(11); + _PSUBSB(12); _PSUBSB(13); _PSUBSB(14); _PSUBSB(15); +} + +void PEXTLB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[1]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[1]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[3]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[3]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[5]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[5]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[7]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[7]; +} + +void PPACB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rt.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rt.UC[14]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[14]; +} + +#define _PEXT5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16); + +void PEXT5() { + if (!_Rd_) return; + + _PEXT5(0); _PEXT5(1); _PEXT5(2); _PEXT5(3); +} + +#define _PPAC5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000); + +void PPAC5() { + if (!_Rd_) return; + + _PPAC5(0); _PPAC5(1); _PPAC5(2); _PPAC5(3); +} + +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** + +#define _PABSW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]); + +void PABSW() { + if (!_Rd_) return; + + _PABSW(0); _PABSW(1); _PABSW(2); _PABSW(3); +} + +#define _PCEQW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].UL[n] == cpuRegs.GPR.r[_Rt_].UL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCEQW() { + if (!_Rd_) return; + + _PCEQW(0); _PCEQW(1); _PCEQW(2); _PCEQW(3); +} + +#define _PMINW(n) \ + cpuRegs.GPR.r[_Rd_].SL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] < cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].SL[n] : cpuRegs.GPR.r[_Rt_].SL[n]; + +void PMINW() { + if (!_Rd_) return; + + _PMINW(0); _PMINW(1); _PMINW(2); _PMINW(3); +} + +void PADSBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PABSH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]); + +void PABSH() { + if (!_Rd_) return; + + _PABSH(0); _PABSH(1); _PABSH(2); _PABSH(3); + _PABSH(4); _PABSH(5); _PABSH(6); _PABSH(7); +} + +#define _PCEQH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].US[n] == cpuRegs.GPR.r[_Rt_].US[n]) ? 0xFFFF : 0x0000; + +void PCEQH() { + if (!_Rd_) return; + + _PCEQH(0); _PCEQH(1); _PCEQH(2); _PCEQH(3); + _PCEQH(4); _PCEQH(5); _PCEQH(6); _PCEQH(7); +} + +#define _PMINH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] < cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMINH() { + if (!_Rd_) return; + + _PMINH(0); _PMINH(1); _PMINH(2); _PMINH(3); + _PMINH(4); _PMINH(5); _PMINH(6); _PMINH(7); +} + +#define _PCEQB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].UC[n] == \ + cpuRegs.GPR.r[_Rt_].UC[n]) ? 0xFF : 0x00; + +void PCEQB() { + if (!_Rd_) return; + + _PCEQB(0); _PCEQB(1); _PCEQB(2); _PCEQB(3); + _PCEQB(4); _PCEQB(5); _PCEQB(6); _PCEQB(7); + _PCEQB(8); _PCEQB(9); _PCEQB(10); _PCEQB(11); + _PCEQB(12); _PCEQB(13); _PCEQB(14); _PCEQB(15); +} + +#define _PADDUW(n) \ + tmp = (s64)cpuRegs.GPR.r[_Rs_].UL[n] + (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (tmp > 0xffffffff) \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0xffffffff; \ + else cpuRegs.GPR.r[_Rd_].UL[n] = (u32)tmp; + +void PADDUW () { + s64 tmp; + + if (!_Rd_) return; + + _PADDUW(0); _PADDUW(1); _PADDUW(2); _PADDUW(3); +} + +#define _PSUBUW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (u32)sTemp64; \ + } + +void PSUBUW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBUW(0); _PSUBUW(1); _PSUBUW(2); _PSUBUW(3); +} + +void PEXTUW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[3]; +} + +#define _PADDUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] + (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 > 0xFFFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0xFFFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PADDUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDUH(0); _PADDUH(1); _PADDUH(2); _PADDUH(3); + _PADDUH(4); _PADDUH(5); _PADDUH(6); _PADDUH(7); +} + +#define _PSUBUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] - (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PSUBUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBUH(0); _PSUBUH(1); _PSUBUH(2); _PSUBUH(3); + _PSUBUH(4); _PSUBUH(5); _PSUBUH(6); _PSUBUH(7); +} + +void PEXTUH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PADDUB(n) \ + Temp16 = (u16)cpuRegs.GPR.r[_Rs_].UC[n] + (u16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (Temp16 > 0xFF) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0xFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)Temp16; \ + } + +void PADDUB() { + u16 Temp16; + + if (!_Rd_) return; + + _PADDUB(0); _PADDUB(1); _PADDUB(2); _PADDUB(3); + _PADDUB(4); _PADDUB(5); _PADDUB(6); _PADDUB(7); + _PADDUB(8); _PADDUB(9); _PADDUB(10); _PADDUB(11); + _PADDUB(12); _PADDUB(13); _PADDUB(14); _PADDUB(15); +} + +#define _PSUBUB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].UC[n] - (s16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (sTemp16 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)sTemp16; \ + } + +void PSUBUB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBUB(0); _PSUBUB(1); _PSUBUB(2); _PSUBUB(3); + _PSUBUB(4); _PSUBUB(5); _PSUBUB(6); _PSUBUB(7); + _PSUBUB(8); _PSUBUB(9); _PSUBUB(10); _PSUBUB(11); + _PSUBUB(12); _PSUBUB(13); _PSUBUB(14); _PSUBUB(15); +} + +void PEXTUB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[15]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[15]; +} + +void QFSRV() { // JayteeMaster: changed a bit to avoid screw up + GPR_reg Rd; + if (!_Rd_) return; + + if (cpuRegs.sa == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; + } else { + if (cpuRegs.sa < 64) { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } else { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } + } +} + +//********END OF MMI1 OPCODES*********************************** + +//*********MMI2 OPCODES*************************************** + +#define _PMADDW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) + \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMADDW() { + _PMADDW(0, 0); + _PMADDW(1, 2); +} + +void PSLLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (s32)(cpuRegs.GPR.r[_Rt_].UL[2] << + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PSRLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].UL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +#define _PMSUBW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) - \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMSUBW() { + _PMSUBW(0, 0); + _PMSUBW(1, 2); +} + +void PMFHI() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.HI.UD[1]; +} + +void PMFLO() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.LO.UD[1]; +} + +void PINTH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PMULTW(dd, ss) { \ + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ + } \ +} + +void PMULTW() { + _PMULTW(0, 0); + _PMULTW(1, 2); +} + +#define _PDIVW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss]; \ + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss]; \ + } + +void PDIVW() { + _PDIVW(0, 0); + _PDIVW(1, 2); +} + +void PCPYLD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; +} + +void PMADDH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp; */ + + temp = cpuRegs.LO.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp; */ + + temp = cpuRegs.HI.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp; */ + + temp = cpuRegs.LO.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp; */ + + temp = cpuRegs.HI.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } + +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMADH(hlr, dd, n) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[n] = temp; */\ +} + +void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3 + _PHMADH(LO, 0, 0); + _PHMADH(HI, 0, 2); + _PHMADH(LO, 2, 4); + _PHMADH(HI, 2, 6); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PAND() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] & cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PXOR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] ^ cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = cpuRegs.LO.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = cpuRegs.HI.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = cpuRegs.LO.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = cpuRegs.HI.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMSBH(hlr, dd, n, rdd) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[rdd] = temp;*/ \ +} + +void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up + _PHMSBH(LO, 0, 0, 0); + _PHMSBH(HI, 0, 2, 1); + _PHMSBH(LO, 2, 4, 2); + _PHMSBH(HI, 2, 6, 3); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PEXEH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PREVH () { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PMULTH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +#define _PDIVBW(n) \ + cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]); \ + cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]); \ + +void PDIVBW() { + if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return; + + _PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3); +} + +void PEXEW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +void PROT3W() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//*****END OF MMI2 OPCODES*********************************** + +//*************************MMI3 OPCODES************************ + +#define _PMADDUW(dd, ss) { \ + u64 tempu = (u64)((u64)cpuRegs.LO.UL[ss] | ((u64)cpuRegs.HI.UL[ss] << 32)) + \ + ((u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ +} + +void PMADDUW() { + _PMADDUW(0, 0); + _PMADDUW(1, 2); +} + +void PSRAVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].SL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].SL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PMTHI() { + cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PMTLO() { + cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PINTEH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PMULTUW(dd, ss) { \ + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ + } \ +} + +void PMULTUW() { + _PMULTUW(0, 0); + _PMULTUW(1, 2); +} + +#define _PDIVUW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] / (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + cpuRegs.HI.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] % (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + } + +void PDIVUW() { + _PDIVUW(0, 0); + _PDIVUW(1, 2); +} + +void PCPYUD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[1]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void POR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PNOR () { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = ~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); + cpuRegs.GPR.r[_Rd_].UD[1] = ~(cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]); +} + +void PEXCH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PCPYH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PEXCW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//**********************END OF MMI3 OPCODES******************** + +// obs: +// QFSRV not verified + diff --git a/branches/pcsx2_0.9.1/Mdec.c b/branches/pcsx2_0.9.1/Mdec.c new file mode 100644 index 0000000..babc7a9 --- /dev/null +++ b/branches/pcsx2_0.9.1/Mdec.c @@ -0,0 +1,521 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This code was based on the FPSE v0.08 Mdec decoder*/ + +#include +#include + +#include "PsxCommon.h" +#include "Mdec.h" + +#define FIXED + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define FIX_1_082392200 (277) +#define FIX_1_414213562 (362) +#define FIX_1_847759065 (473) +#define FIX_2_613125930 (669) + +#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS)) + +#define DEQUANTIZE(coef,quantval) (coef) + +#define DESCALE(x,n) ((x)>>(n)) +#define RANGE(n) (n) + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +static void idct1(int *block) +{ + int val = RANGE(DESCALE(block[0], PASS1_BITS+3)); + int i; + for(i=0;i>16)*(bcr&0xffff); + + if (cmd==0x60000000) { + } else + if (cmd==0x40000001) { + u8 *p = (u8*)PSXM(adr); + iqtab_init(iq_y,p); + iqtab_init(iq_uv,p+64); + } else + if ((cmd&0xf5ff0000)==0x30000000) { + mdec.rl = (u16*)PSXM(adr); + } + else { + } + + HW_DMA0_CHCR &= ~0x01000000; + psxDmaInterrupt(0); +} + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DCTSIZE2*6]; + unsigned short *image; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command); +#endif + + if (chcr!=0x01000200) return; + + size = (bcr>>16)*(bcr&0xffff); + image = (u16*)PSXM(adr); + if (mdec.command&0x08000000) { + for (;size>0;size-=(16*16)/2,image+=(16*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb15(blk,image); + } + } else { + for (;size>0;size-=(24*16)/2,image+=(24*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb24(blk,(u8 *)image); + } + } + + HW_DMA1_CHCR &= ~0x01000000; + psxDmaInterrupt(1); +} + + +#define RUNOF(a) ((a)>>10) +#define VALOF(a) (((int)(a)<<(32-10))>>(32-10)) + +static int zscan[DCTSIZE2] = { + 0 ,1 ,8 ,16,9 ,2 ,3 ,10, + 17,24,32,25,18,11,4 ,5 , + 12,19,26,33,40,48,41,34, + 27,20,13,6 ,7 ,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static int aanscales[DCTSIZE2] = { + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +void iqtab_init(int *iqtab,unsigned char *iq_y) +{ +#define CONST_BITS14 14 +#define IFAST_SCALE_BITS 2 + int i; + + for(i=0;i>(CONST_BITS14-IFAST_SCALE_BITS); + } +} + +#define NOP 0xfe00 +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) { + int i,k,q_scale,rl; + int *iqtab; + + memset (blk, 0, 6*DCTSIZE2*4); + iqtab = iq_uv; + for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i>1) iqtab = iq_y; + + // zigzag transformation + rl = *mdec_rl++; + q_scale = RUNOF(rl); + blk[0] = iqtab[0]*VALOF(rl); + for(k = 0;;) { + rl = *mdec_rl++; + if (rl==NOP) break; + k += RUNOF(rl)+1; // skip level zero-coefficients + if (k > 63) break; + blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16; + } +// blk[0] = (blk[0] * iq_t[0] * 8) / 16; +// for(int j=1;j<64;j++) +// blk[j] = blk[j] * iq_t[j] * q_scale; + + // idct + idct(blk,k+1); + + blk+=DCTSIZE2; + } + return mdec_rl; +} + +#ifdef FIXED +#define MULR(a) ((((int)0x0000059B) * (a)) >> 10) +#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10) +#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10) +#define MULB(a) ((((int)0x00000716) * (a)) >> 10) +#else +#define MULR(a) ((int)((float)1.40200 * (a))) +#define MULG(a) ((int)((float)-0.3437 * (a))) +#define MULG2(a) ((int)((float)-0.7143 * (a))) +#define MULB(a) ((int)((float)1.77200 * (a))) +#endif + +#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) ) +#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff] +/*#define ROUND(c) round(c+128) +int round(int r) { + if (r<0) return 0; + if (r>255) return 255; + return r; +}*/ + +#define RGB15(n, Y) \ + image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B)); + +#define RGB15BW(n, Y) \ + image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y)); + +#define RGB24(n, Y) \ + image[n+2] = ROUND(Y + R); \ + image[n+1] = ROUND(Y + G); \ + image[n+0] = ROUND(Y + B); + +#define RGB24BW(n, Y) \ + image[n+2] = ROUND(Y); \ + image[n+1] = ROUND(Y); \ + image[n+0] = ROUND(Y); + +unsigned char roundtbl[256*3]; + +void round_init(void) { + int i; + for(i=0;i<256;i++) { + roundtbl[i]=0; + roundtbl[i+256]=i; + roundtbl[i+512]=255; + } +} + +void yuv2rgb15(int *blk,unsigned short *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(0, Yblk[0]); + RGB15(1, Yblk[1]); + RGB15(16, Yblk[8]); + RGB15(17, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(8, Yblk[DCTSIZE2+0]); + RGB15(9, Yblk[DCTSIZE2+1]); + RGB15(24, Yblk[DCTSIZE2+8]); + RGB15(25, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Yblk+=2) { + RGB15BW(0, Yblk[0]); + RGB15BW(1, Yblk[1]); + RGB15BW(16, Yblk[8]); + RGB15BW(17, Yblk[9]); + + RGB15BW(8, Yblk[DCTSIZE2+0]); + RGB15BW(9, Yblk[DCTSIZE2+1]); + RGB15BW(24, Yblk[DCTSIZE2+8]); + RGB15BW(25, Yblk[DCTSIZE2+9]); + } + } +} + +void yuv2rgb24(int *blk,unsigned char *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(0, Yblk[0]); + RGB24(1*3, Yblk[1]); + RGB24(16*3, Yblk[8]); + RGB24(17*3, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(8*3, Yblk[DCTSIZE2+0]); + RGB24(9*3, Yblk[DCTSIZE2+1]); + RGB24(24*3, Yblk[DCTSIZE2+8]); + RGB24(25*3, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Yblk+=2) { + RGB24BW(0, Yblk[0]); + RGB24BW(1*3, Yblk[1]); + RGB24BW(16*3, Yblk[8]); + RGB24BW(17*3, Yblk[9]); + + RGB24BW(8*3, Yblk[DCTSIZE2+0]); + RGB24BW(9*3, Yblk[DCTSIZE2+1]); + RGB24BW(24*3, Yblk[DCTSIZE2+8]); + RGB24BW(25*3, Yblk[DCTSIZE2+9]); + } + } +} + +int mdecFreeze(gzFile f, int Mode) { + + gzfreeze(&mdec, sizeof(mdec)); + + gzfreezel(iq_y); + + gzfreezel(iq_uv); + + + + return 0; + +} + + + + diff --git a/branches/pcsx2_0.9.1/Mdec.h b/branches/pcsx2_0.9.1/Mdec.h new file mode 100644 index 0000000..33690c9 --- /dev/null +++ b/branches/pcsx2_0.9.1/Mdec.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MDEC_H__ +#define __MDEC_H__ + +void mdecInit(); +void mdecWrite0(u32 data); +void mdecWrite1(u32 data); +u32 mdecRead0(); +u32 mdecRead1(); +void psxDma0(u32 madr, u32 bcr, u32 chcr); +void psxDma1(u32 madr, u32 bcr, u32 chcr); +int mdecFreeze(gzFile f, int Mode); + +#endif /* __MDEC_H__ */ diff --git a/branches/pcsx2_0.9.1/Memory.c b/branches/pcsx2_0.9.1/Memory.c new file mode 100644 index 0000000..6386e2c --- /dev/null +++ b/branches/pcsx2_0.9.1/Memory.c @@ -0,0 +1,3097 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + +RAM +--- +0x00100000-0x01ffffff this is the physical address for the ram.its cached there +0x20100000-0x21ffffff uncached +0x30100000-0x31ffffff uncached & acceleretade +0xa0000000-0xa1ffffff MIRROR might...??? +0x80000000-0x81ffffff MIRROR might... ???? + +scratch pad +---------- +0x70000000-0x70003fff scratch pad + +BIOS +---- +0x1FC00000 - 0x1FFFFFFF un-cached +0x9FC00000 - 0x9FFFFFFF cached +0xBFC00000 - 0xBFFFFFFF un-cached +*/ + +////////// +// Rewritten by zerofrog(@gmail.com) to add os virtual memory +////////// + + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#pragma warning(disable:4799) // No EMMS at end of function + +#include +#include +#include +#include + +#include "Common.h" +#include "ir5900.h" +#include "PsxMem.h" +#include "R3000A.h" +#include "psxhw.h" +#include "VUmicro.h" + +#include + +extern u32 maxrecmem; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +//#define FULLTLB +int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode + +#if ENABLE_GS_CACHING + +// addr can belong to locked GS memory +#define CHECK_GSMEM(addr) { \ + if( (addr) < 0x10000000 ) { \ + u32* page = GS_PAGEADDRS+((addr)>>GS_SHIFT)*(GSPAGES_MEMADDRS+1); \ + if( *(u8*)page) GSFreePage(page); \ + } \ +} \ + +#define CHECK_GSMEM_ASM() \ +{ \ + __asm cmp edx, 0x10000000 /* make sure not scratch mem*/ \ + __asm jae RegularRead \ + __asm mov edx, ecx \ + __asm shr edx, GS_SHIFT \ + __asm imul edx, (GSPAGES_MEMADDRS+1)*4 \ + __asm cmp byte ptr [edx+GS_PAGEADDRS_], 0 \ + __asm je RegularRead \ + __asm add edx, GS_PAGEADDRS_ \ + __asm sub esp, 12 \ + __asm mov dword ptr [esp+0], edx \ + __asm mov dword ptr [esp+4], eax \ + __asm mov dword ptr [esp+8], ecx \ + __asm call GSFreePage \ + __asm mov eax, dword ptr [esp+4] \ + __asm mov ecx, dword ptr [esp+8] \ + __asm add esp, 12 \ + } \ +RegularRead: \ + +//#define CHECK_GSMEM_ASM_REC() // rec everything above + +#else +#define CHECK_GSMEM(mem) +#define CHECK_GSMEM_ASM() +#define CHECK_GSMEM_ASM_REC(mem) +#endif + +u16 ba0R16(u32 mem) { +#ifdef MEM_LOG + //MEM_LOG("ba00000 Memory read16 address %x\n", mem); +#endif + +#ifdef WIN32_VIRTUAL_MEM + if (mem == 0x1a000006) { +#else + if (mem == 0xba000006) { +#endif + static int ba6; + ba6++; + if (ba6 == 3) ba6 = 0; + return ba6; + } + return 0; +} + +///////////////////////////// +// VIRTUAL MEM START +///////////////////////////// +#ifdef WIN32_VIRTUAL_MEM + +//#define VM_RETRANSLATE(mem) (PS2MEM_BASE_+mem) + +// Some games read/write between different addrs but same physical memory +// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog) +u32 VM_RETRANSLATE(u32 mem) +{ + u8* p, *pbase; + if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem + return PS2MEM_BASE_+mem; + + p = (u8*)dmaGetAddrBase(mem), *pbase; + + // do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often + if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) { + return PS2MEM_BASE_+mem; + } + + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + + return (u32)p; +} + +PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs) +{ + PSMEMORYMAP m; + m.aPFNs = aPFNs; + m.aVFNs = aVFNs; + return m; +} + +// only do vm hack for release +#ifndef PCSX2_DEVBUILD +#define VM_HACK +#endif + +static int XmmExtendedRegOffset = 160; + +// virtual memory blocks +PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0}; +PSMEMORYMAP *memLUT = NULL; + +#define PHYSICAL_ALLOC(ptr, size, block) { \ + if(SysPhysicalAlloc(size, &block) == -1 ) \ + goto eCleanupAndExit; \ + if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \ + goto eCleanupAndExit; \ +} \ + +#define VIRTUAL_ALLOC(base, size, Protection) { \ + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \ + if( lpMemReserved == NULL || base != lpMemReserved ) \ + { \ + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \ + goto eCleanupAndExit; \ + } \ +} \ + +#define PHYSICAL_FREE(ptr, size, block) { \ + SysVirtualFree(ptr, size); \ + SysPhysicalFree(&block); \ +} \ + +#define VIRTUAL_FREE(ptr, size) { \ + VirtualFree(ptr, size, MEM_DECOMMIT); \ + VirtualFree(ptr, 0, MEM_RELEASE); \ +} \ + +static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 }; + +INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata) +{ + int i; + u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters; + + assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + XmmExtendedRegOffset = 160; + + for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) { + if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) { + XmmExtendedRegOffset = i*4; + break; + } + } + + pexdata->ContextRecord->Eip += 7; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +#if _MSC_VER < 1400 +#define VC_HANDLER _except_handler3 +#else +#define VC_HANDLER _except_handler4 +#endif + +//C's default exception handler +EXCEPTION_DISPOSITION VC_HANDLER( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +char cpp_handler_instructions[5]; +BOOL saved_handler_instructions = FALSE; + +//Exception handler that replaces C's default handler. +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +#pragma pack(1) +typedef struct _jmp_instr +{ + unsigned char jmp; + DWORD offset; +} jmp_instr; +#pragma pack() + +BOOL WriteMemory(void * loc, void * buffer, int size) +{ + DWORD o2; + HANDLE hProcess = GetCurrentProcess(); + + //change the protection of pages containing range of memory + //[loc, loc+size] to READ WRITE + DWORD old_protection; + + BOOL ret; + ret = VirtualProtectEx(hProcess, loc, size, + PAGE_READWRITE, &old_protection); + if(ret == FALSE) + return FALSE; + + ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL); + + //restore old protection + VirtualProtectEx(hProcess, loc, size, old_protection, &o2); + + return (ret == TRUE); +} + +BOOL ReadMemory(void *loc, void *buffer, DWORD size) +{ + HANDLE hProcess = GetCurrentProcess(); + DWORD bytes_read = 0; + BOOL ret; + ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read); + return (ret == TRUE && bytes_read == size); +} + +BOOL install_my_handler() +{ + void * my_hdlr = SysPageFaultExceptionFilter; + void * cpp_hdlr = VC_HANDLER; + + jmp_instr jmp_my_hdlr; + jmp_my_hdlr.jmp = 0xE9; + + //We actually calculate the offset from __CxxFrameHandler+5 + //as the jmp instruction is 5 byte length. + jmp_my_hdlr.offset = (char*)(my_hdlr) - + ((char*)(cpp_hdlr) + 5); + + if(!saved_handler_instructions) + { + if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, + sizeof(cpp_handler_instructions))) + return FALSE; + saved_handler_instructions = TRUE; + } + + return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr)); +} + +BOOL restore_cpp_handler() +{ + if(!saved_handler_instructions) + return FALSE; + else + { + void *loc = VC_HANDLER; + return WriteMemory(loc, cpp_handler_instructions, + sizeof(cpp_handler_instructions)); + } +} + +int memInit() { + + int i; + LPVOID pExtraMem = NULL; + + // release the previous reserved mem + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); + + // allocate all virtual memory + PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY); + PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM); + PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS); + + VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE); + + // reserve the left over 224Mb, don't map + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x02000000 ) + goto eCleanupAndExit; + + // reserve left over psx mem + pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_PSX+0x00200000 ) + goto eCleanupAndExit; + + // reserve gs mem + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x20000000 ) + goto eCleanupAndExit; + + // special addrs mmap + VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE); + + // alloc virtual mappings + memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16); + memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000); + for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]); + for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]); + for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]); + for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]); + + for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]); + + // map to other modes + memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + + if (psxInit() == -1) + goto eCleanupAndExit; + + // figure out xmm reg offset +// __asm movups xmm0, s_testmem +// __try { +// u8* p = 0; +// __asm { +// mov eax, dword ptr [p] +// } +// } +// __except( FindXmmOffsetException( GetExceptionInformation() ) ) { +// } + + if( !install_my_handler() ) { + SysPrintf("Failed to install custom exception handler!\n"); + return -1; + } + + return 0; + +eCleanupAndExit: + if( pExtraMem != NULL ) + VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE); + memShutdown(); + return -1; +} + +void memShutdown() +{ + VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE); + + PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_FREE(PS2MEM_ROM, 0x00400000); + VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000); + VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000); + VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000); + PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM); + PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs + + VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000); + VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000); + VIRTUAL_FREE(PS2MEM_GS, 0x00010000); + VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000); + + VIRTUAL_FREE(PS2MEM_B80, 0x00010000); + VIRTUAL_FREE(PS2MEM_BA0, 0x00010000); + + VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE); + + _aligned_free(memLUT); memLUT = NULL; + + // reserve mem + VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { + + PSMEMORYMAP* pmap; + + if( vaddr == paddr ) + return; + + if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) { + pmap = &memLUT[vaddr >> 12]; + + if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs || + pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) { + + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + pmap->aVFNs[0] = 0; + } + + *pmap = memLUT[paddr >> 12]; + } +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + +// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) { +// Cpu->Clear(vaddr&~0xfff, 0x1000/4); +// if( memLUT[vaddr>>12].aVFNs != NULL ) { +// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL ); +// memLUT[vaddr>>12].aVFNs = NULL; +// memLUT[vaddr>>12].aPFNs = NULL; +// } +// } +} + +#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7)) +#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4))) + +//NOTE: A lot of the code reading depends on the registers being less than 8 +// MOV8 88/8A +// MOV16 6689 +// MOV32 89/8B +// SSEMtoR64 120f +// SSERtoM64 130f +// SSEMtoR128 280f +// SSERtoM128 290f + +#define SKIP_WRITE(pexdata) { \ + switch(code&0xff) { \ + case 0x88: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + break; \ + case 0x66: \ + assert( code&0x800000 ); \ + assert( (code&0xffff) == 0x8966 ); \ + ContextRecord->Eip += 7; \ + break; \ + case 0x89: \ + assert( code&0x8000 ); \ + ContextRecord->Eip += 6; \ + break; \ + case 0x0f: /* 130f, 230f*/ \ + assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \ + assert( code&0x800000 ); \ + ContextRecord->Eip += 7; \ + break; \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +#define SKIP_READ(pexdata) { \ + switch(code&0xff) { \ + case 0x8A: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x66: \ + if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \ + else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \ + rd = (code>>(24+3))&7; \ + break; \ + case 0x8B: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x0f: { \ + assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \ + if( !(code&0x800000) ) goto DefaultHandler; \ + ContextRecord->Eip += 7; \ + rd = (code>>(16+3))&7; \ + break; } \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ) +{ + u32 addr; + + C_ASSERT(sizeof(ContextRecord->Eax) == 4); + + // If the exception is not a page fault, exit. + if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + { + // call old handler + EXCEPTION_DISPOSITION d; + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // get bad virtual address + addr = (u32)ExceptionRecord->ExceptionInformation[1]; + + if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) { + PSMEMORYMAP* pmap; + + pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12]; + + if( pmap->aPFNs == NULL ) { + // NOTE: this is a hack because the address is truncated and there's no way + // to tell what it's upper bits are (due to OS limitations). + pmap += 0x80000; + if( pmap->aPFNs == NULL ) { + pmap += 0x20000; + } + //else addr += 0x20000000; + } + + if( pmap->aPFNs != NULL ) { + LPVOID pnewaddr; + DWORD oldaddr = pmap->aVFNs[0]; + + if( pmap->aVFNs[0] != 0 ) { + // delete the current mapping + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + } + + assert( pmap->aPFNs[0] != 0 ); + + pmap->aVFNs[0] = addr&~0xfff; + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + // try allocing the virtual mem + pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n", + addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]); + } + } + else { + // check if vumem + + if( (addr&0xffff4000) == 0x11000000 ) { + // vu0mem + SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL); + + s_psVuMem.aVFNs[1] = addr&~0xfff; + SysMapUserPhysicalPages((void*)addr, 1, &s_psVuMem.aPFNs[1]); + + return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION; + } + } + + { + // call old handler + EXCEPTION_DISPOSITION d; + +#ifdef VM_HACK + u32 code = *(u32*)ExceptionRecord->ExceptionAddress; + u32 rd = 0; + + if( ExceptionRecord->ExceptionInformation[0] ) { + //SKIP_WRITE(ptrs); + // shouldn't be writing + } + else { + SysPrintf("vmhack "); + SKIP_READ(ptrs); + //((u32*)&ContextRecord->Eax)[rd] = 0; + return ExceptionContinueExecution; + } + +DefaultHandler: +#endif + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // continue execution + return EXCEPTION_CONTINUE_EXECUTION; +} + +u8 recMemRead8() +{ + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&~0xffff) ) { + case 0x1f400000: return psxHw4Read8(mem); + case 0x10000000: return hwRead8(mem); + case 0x1f800000: return psxHwRead8(mem); + case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00)); + case 0x14000000: + { + u32 ret = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u8*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +void _eeReadConstMem8(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-3); + assert(0); + } + else { + if( sign ) MOVSX32M8toR(mmreg, mem); + else MOVZX32M8toR(mmreg, mem); + } +} + +void _eeReadConstMem16(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-2); + assert(0); + } + else { + if( sign ) MOVSX32M16toR(mmreg, mem); + else MOVZX32M16toR(mmreg, mem); + } +} + +void _eeReadConstMem32(int mmreg, u32 mem) +{ + if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem); + } + else MOV32MtoR(mmreg, mem); +} + +void _eeReadConstMem128(int mmreg, u32 mem) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQMtoR((mmreg>>4)&0xf, mem+8); + MOVQMtoR(mmreg&0xf, mem); + } + else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem); +} + +void _eeWriteConstMem8(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV8RtoM(mem, mmreg); +} + +void _eeWriteConstMem16(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV16RtoM(mem, mmreg); +} + +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + switch(op) { + case 0: // and + if( IS_CONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else AND16RtoM(mem, mmreg); + break; + case 1: // and + if( IS_CONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else OR16RtoM(mem, mmreg); + break; + default: assert(0); + } +} + +void _eeWriteConstMem32(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV32RtoM(mem, mmreg); +} + +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op) +{ + switch(op) { + case 0: // and + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_PAND_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PANDMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + AND32RtoM(mem, mmreg&0xf); + } + break; + + case 1: // or + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_POR_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PORMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + OR32RtoM(mem, mmreg&0xf); + } + break; + + case 2: // not and + if( mmreg & MEM_XMMTAG ) { + _deleteEEreg(mmreg>>16, 1); + SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem); + SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + _deleteEEreg(mmreg>>16, 1); + PANDNMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + NOT32R(mmreg&0xf); + AND32RtoM(mem, mmreg&0xf); + } + break; + + default: assert(0); + } +} + +void _eeWriteConstMem64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + } + else assert(0); +} + +void _eeWriteConstMem128(u32 mem, int mmreg) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + MOVQRtoM(mem+8, (mmreg>>4)&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + SetMMXstate(); + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + MOVQRtoM(mem+8, mmreg&0xf); + } + else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf); +} + +void _eeMoveMMREGtoR(x86IntRegType to, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVD32MMXtoR(to, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else if( mmreg != to ) MOV32RtoR(to, mmreg); +} + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign); + case 0x1000: return hwConstRead8(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead8(x86reg, mem, sign); + case 0x1200: return gsConstRead8(x86reg, mem, sign); + case 0x1400: + { + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + return 1; + } + + default: + _eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +u16 recMemRead16() { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( mem>>16 ) { + case 0x1000: return hwRead16(mem); + case 0x1f80: return psxHwRead16(mem); + case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00)); + case 0x1800: return 0; + case 0x1a00: return ba0R16(mem); + case 0x1f90: + case 0x1f00: + return SPU2read(mem); + case 0x1400: + { + u32 ret = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u16*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: return hwConstRead16(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead16(x86reg, mem, sign); + case 0x1200: return gsConstRead16(x86reg, mem, sign); + case 0x1800: + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + case 0x1a00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)ba0R16); + ADD32ItoR(ESP, 4); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f90: + case 0x1f00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1400: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + default: + _eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +__declspec(naked) +u32 recMemRead32() { + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwread + cmp dx, 0x1f80 + je psxhwread + cmp dx, 0x1200 + je gsread + cmp dx, 0x1400 + je devread + + // default read + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +hwread: + { + __asm { + cmp ecx, 0x10002000 + jb counterread + + cmp ecx, 0x1000f260 + je hwsifpresetread + cmp ecx, 0x1000f240 + je hwsifsyncread + + cmp ecx, 0x10003000 + jb hwdefread2 + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + + // ipu +hwdefread2: + push ecx + call ipuRead32 + add esp, 4 + ret + + // sif +hwsifpresetread: + mov eax, 0 + ret +hwsifsyncread: + mov eax, dword ptr [0x1000F240+PS2MEM_BASE_] + or eax, 0xF0000102 + ret + } + +counterread: + { + static u32 mem, index; + + // counters + __asm mov mem, ecx + index = (mem>>11)&3; + + if( (mem&0x7ff) == 0 ) { + __asm { + push index + call rcntRcount + add esp, 4 + and eax, 0xffff + ret + } + } + + index = (u32)&counters[index] + ((mem>>2)&0xc); + + __asm { + mov eax, index + mov eax, dword ptr [eax] + movzx eax, ax + ret + } + } + } + +psxhwread: + __asm { + push ecx + call psxHwRead32 + add esp, 4 + ret + } + +gsread: + __asm { + and ecx, 0xfffff3ff + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +devread: + __asm { + and ecx, 0xfbffffff + push ecx + call DEV9read32 + add esp, 4 + ret + } +} + +int recMemConstRead32(u32 x86reg, u32 mem) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&~0xffff) ) { + case 0x10000000: return hwConstRead32(x86reg, mem); + case 0x1f800000: return psxHwConstRead32(x86reg, mem); + case 0x12000000: return gsConstRead32(x86reg, mem); + case 0x14000000: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read32); + return 1; + + default: + _eeReadConstMem32(x86reg, VM_RETRANSLATE(mem)); + return 0; + } +} + +void recMemRead64(u64 *out) +{ + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: *out = hwRead64(mem); return; + case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return; + case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return; + + default: + //assert(0); + *out = *(u64*)(PS2MEM_BASE+mem); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead64(mem, mmreg); return; + case 0x12000000: gsConstRead64(mem, mmreg); return; + default: + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem)); + else { + MOVQMtoR(mmreg, VM_RETRANSLATE(mem)); + SetMMXstate(); + } + return; + } +} + +void recMemRead128(u64 *out) { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: + hwRead128(mem, out); + return; + case 0x12000000: + out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); + out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8); + return; + case 0x11000000: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + default: + //assert(0); + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead128(u32 mem, int xmmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead128(mem, xmmreg); return; + case 0x12000000: gsConstRead128(mem, xmmreg); return; + default: + _eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem)); + return; + } +} + +void errwrite() +{ + int i, bit, tempeax; + __asm mov i, ecx + __asm mov tempeax, eax + __asm mov bit, edx + SysPrintf("Error write%d at %x\n", bit, i); + assert(0); + __asm mov eax, tempeax + __asm mov ecx, i +} + +void recMemWrite8() +{ + register u32 mem; + register u8 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, al + + switch( mem>>16 ) { + case 0x1f40: psxHw4Write8(mem, value); return; + case 0x1000: hwWrite8(mem, value); return; + case 0x1f80: psxHwWrite8(mem, value); return; + case 0x1200: gsWrite8(mem, value); return; + case 0x1400: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + CHECK_GSMEM(mem); + *(u8*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite8(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0; + case 0x1000: hwConstWrite8(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0; + case 0x1200: gsConstWrite8(mem, mmreg); return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write8); + return 0; + + case 0x1100: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +void recMemWrite16() { + + register u32 mem; + register u16 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, ax + + switch( mem>>16 ) { + case 0x1000: hwWrite16(mem, value); return; + case 0x1f80: psxHwWrite16(mem, value); return; + case 0x1200: gsWrite16(mem, value); return; + case 0x1f90: + case 0x1f00: SPU2write(mem, value); return; + case 0x1400: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + CHECK_GSMEM(mem); + *(u16*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite16(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: hwConstWrite16(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0; + case 0x1200: gsConstWrite16(mem, mmreg); return 0; + case 0x1f90: + case 0x1f00: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write16); + return 0; + + case 0x1100: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +__declspec(naked) +void recMemWrite32() +{ + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1f80 + je psxwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1400 + je devwrite + cmp dx, 0x1100 + je vuwrite + } + + CHECK_GSMEM_ASM(); + + __asm { + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + ret + +hwwrite: + push eax + push ecx + call hwWrite32 + add esp, 8 + ret +psxwrite: + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret +gswrite: + push eax + push ecx + call gsWrite32 + add esp, 8 + ret +devwrite: + and ecx, 0xfbffffff + push eax + push ecx + call DEV9write32 + add esp, 8 + ret +vuwrite: + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite32(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem&0xffff0000 ) { + case 0x10000000: hwConstWrite32(mem, mmreg); return 0; + case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0; + case 0x12000000: gsConstWrite32(mem, mmreg); return 0; + case 0x1f900000: + case 0x1f000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x14000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1100: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) void recMemWrite64() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov edx, 64 + call errwrite + +hwwrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call hwWrite64 + add esp, 12 + ret + +gswrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call gsWrite64 + add esp, 12 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem>>16) ) { + case 0x1000: hwConstWrite64(mem, mmreg); return 0; + case 0x1200: gsConstWrite64(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) +void recMemWrite128() +{ + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + mov edx, 128 + call errwrite + +hwwrite: + + push eax + push ecx + call hwWrite128 + add esp, 8 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov edi, dword ptr [eax+8] + mov eax, dword ptr [eax+12] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + mov dword ptr [ecx+PS2MEM_BASE_+8], edi + mov dword ptr [ecx+PS2MEM_BASE_+12], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + + // default write + //movaps xmm7, qword ptr [eax] + + // removes possible exceptions and saves on remapping memory + // *might* be faster for certain games, no way to tell +// cmp ecx, 0x20000000 +// jb Write128 +// +// // look for better mapping +// mov edx, ecx +// shr edx, 12 +// shl edx, 3 +// add edx, memLUT +// mov edx, dword ptr [edx + 4] +// cmp edx, 0 +// je Write128 +// mov edx, dword ptr [edx] +// cmp edx, 0 +// je Write128 +// and ecx, 0xfff +// movaps qword ptr [ecx+edx], xmm7 +// jmp CheckOverwrite +//Write128: + //movaps qword ptr [ecx+PS2MEM_BASE_], xmm7 + ret + +gswrite: + sub esp, 8 + movlps xmm7, qword ptr [eax] + movlps qword ptr [esp], xmm7 + push ecx + call gsWrite64 + + // call again for upper 8 bytes + movlps xmm7, qword ptr [eax+8] + movlps qword ptr [esp+4], xmm7 + add [esp], 8 + call gsWrite64 + add esp, 12 + ret + } +} + +int recMemConstWrite128(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstWrite128(mem, mmreg); return 0; + case 0x12000000: gsConstWrite128(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + CHECK_GSMEM_ASM_REC(mem); + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +int memRead8 (u32 mem, u8 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = psxHw4Read8(mem); return 0; + case 0x10000000: *out = hwRead8(mem); return 0; + case 0x1f800000: *out = psxHwRead8(mem); return 0; + case 0x12000000: *out = gsRead8(mem); return 0; + case 0x14000000: + *out = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (s8)hwRead8(mem); return 0; + case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (s8)gsRead8(mem); return 0; + case 0x14000000: + *out = (s8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (u8)hwRead8(mem); return 0; + case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (u8)gsRead8(mem); return 0; + case 0x14000000: + *out = (u8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead16(mem); return 0; + case 0x1f800000: *out = psxHwRead16(mem); return 0; + case 0x12000000: *out = gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = SPU2read(mem); return 0; + break; + case 0x14000000: + *out = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s16)hwRead16(mem); return 0; + case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0; + case 0x12000000: *out = (s16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (s16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (s16)SPU2read(mem); return 0; + break; + case 0x14000000: + *out = (s16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u16)hwRead16(mem ); return 0; + case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0; + case 0x12000000: *out = (u16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (u16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (u16)SPU2read(mem ); return 0; + break; + case 0x14000000: + *out = (u16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead32(mem); return 0; + case 0x1f800000: *out = psxHwRead32(mem); return 0; + case 0x12000000: *out = gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s32)hwRead32(mem); return 0; + case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (s32)gsRead32(mem); return 0; + case 0x14000000: + *out = (s32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u32)hwRead32(mem); return 0; + case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (u32)gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead64(mem); return 0; + case 0x12000000: *out = gsRead64(mem); return 0; + + default: + *out = *(u64*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: + hwRead128(mem, out); + return 0; + case 0x12000000: + out[0] = gsRead64(mem); + out[1] = gsRead64(mem + 8); + return 0; + + default: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: psxHw4Write8(mem, value); return; + case 0x10000000: hwWrite8(mem, value); return; + case 0x1f800000: psxHwWrite8(mem, value); return; + case 0x12000000: gsWrite8(mem, value); return; + case 0x14000000: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + + default: + CHECK_GSMEM(mem); + + *(u8*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite16(mem, value); return; + case 0x1f800000: psxHwWrite16(mem, value); return; + case 0x12000000: gsWrite16(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + + default: + CHECK_GSMEM(mem); + + *(u16*)(PS2MEM_BASE+mem) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite32(mem, value); return; + case 0x1f800000: psxHwWrite32(mem, value); return; + case 0x12000000: gsWrite32(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write32(mem & ~0x4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value); + return; + + default: + CHECK_GSMEM(mem); + *(u32*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite64(mem, value); return; + case 0x12000000: gsWrite64(mem, value); return; + + default: + CHECK_GSMEM(mem); + *(u64*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite128(mem, value); return; + case 0x12000000: + gsWrite64(mem, value[0]); + gsWrite64(mem + 8, value[1]); + return; + + default: + + CHECK_GSMEM(mem); + + *(u64*)(PS2MEM_BASE+mem) = value[0]; + *(u64*)(PS2MEM_BASE+mem+8) = value[1]; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +#else + +u8 *psM; //32mb Main Ram +u8 *psR; //4mb rom area +u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +u8 *psR2; // 0x00080000 +u8 *psER; // 0x001C0000 +u8 *psS; //0.015 mb, scratch pad + +uptr *memLUTR; +uptr *memLUTW; +uptr *memLUTRK; +uptr *memLUTWK; +uptr *memLUTRU; +uptr *memLUTWU; + +///////////////////////////// +// REGULAR MEM START +///////////////////////////// + +void memMapMem(u32 base) { + int i; + + for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure) + + for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure) +} + +void memMapKernelMem() { + memMapMem(0xa0000); + memMapMem(0x80000); + memMapMem(0x00000); +} + +void memMapSupervisorMem() { +} + +void memMapUserMem() { +} + +int memInit() { + int i; + + memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + + psM = (char*)_aligned_malloc(0x02000010, 16); + psR = (char*)_aligned_malloc(0x00400010, 16); + psR1 = (char*)_aligned_malloc(0x00080010, 16); + psR2 = (char*)_aligned_malloc(0x00080010, 16); + psER = (char*)_aligned_malloc(0x001C0010, 16); + psS = (char*)_aligned_malloc(0x00004010, 16); + if (memLUTRK == NULL || memLUTWK == NULL || + memLUTRU == NULL || memLUTWU == NULL || + psM == NULL || psR == NULL || psR1 == NULL || + psR2 == NULL || psER == NULL || psS == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(memLUTRK, 0, 0x100000 * 4); + memset(memLUTWK, 0, 0x100000 * 4); + memset(memLUTRU, 0, 0x100000 * 4); + memset(memLUTWU, 0, 0x100000 * 4); + + memset(psM, 0, 0x02000010); + memset(psR, 0, 0x00400010); + memset(psR1, 0, 0x00080010); + memset(psR2, 0, 0x00080010); + memset(psER, 0, 0x001C0010); + memset(psS, 0, 0x00004010); + + if (psxInit() == -1) return -1; + + for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12]; + + for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12]; + + + memMapKernelMem(); + memMapSupervisorMem(); + memMapUserMem(); + + memSetKernelMode(); + + return 0; +} + +void memShutdown() { + FREE(psM); + FREE(psR); + FREE(psR1); + FREE(psR2); + FREE(psER); + FREE(psS); + FREE(memLUTRK); + FREE(memLUTWK); + FREE(memLUTRU); + FREE(memLUTWU); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { +// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr); + + memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12]; + + memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12]; +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + memLUTRU[vaddr >> 12] = 0; + memLUTWU[vaddr >> 12] = 0; + +#ifdef FULLTLB + memLUTRK[vaddr >> 12] = 0; + memLUTWK[vaddr >> 12] = 0; +#endif +} + +int memRead8 (u32 mem, u8 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = ba0R16(mem); return 0; + case 6: // gsm + *out = gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (s16)ba0R16(mem); return 0; + case 6: // gsm + *out = (s16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (s16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (u16)ba0R16(mem); return 0; + case 6: // gsm + *out = (u16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (u16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + assert( (int)p < 8 ); + + switch ((int)p) { + case 1: // hwm + *out = hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u64*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u64*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead64(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead64(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u64 *tmp = (u64*)readCache(mem); + out[0] = tmp[0]; + out[1] = tmp[1]; + return 0; + } +#endif + p+= mem & 0xfff; + out[0] = ((u64*)p)[0]; + out[1] = ((u64*)p)[1]; + return 0; + } + + switch ((int)p) { + case 1: // hwm + hwRead128(mem & ~0xa0000000, out); return 0; + case 6: // gsm + out[0] = gsRead64((mem ) & ~0xa0000000); + out[1] = gsRead64((mem+8) & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache8(mem, value); + return; + } +#endif + *(u8 *)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&(~3)); +// PSXREC_CLEARM(mem & 0x1ffffc); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite8(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite8(mem & ~0xa0000000, value); return; + case 3: // psh4 + psxHw4Write8(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite8(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write8(mem & ~0xa4000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value); + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache16(mem, value); + return; + } +#endif + *(u16*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~1); + //PSXREC_CLEARM(mem & 0x1ffffe); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite16(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite16(mem & ~0xa0000000, value); return; + case 5: // ba0 +#ifdef MEM_LOG + MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value); +#endif + return; + case 6: // gsm + gsWrite16(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write16(mem & ~0xa4000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value); + return; + case 8: // spu2 + SPU2write(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + char *p; + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache32(mem, value); + return; + } +#endif + *(u32*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); +// PSXREC_CLEARM(mem & 0x1fffff); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite32(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite32(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite32(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write32(mem & ~0xa4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value); + return; + } +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { + #ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache64(mem, value); + return; + } + #endif + /* __asm __volatile ( + "movq %1, %%mm0\n" + "movq %%mm0, %0\n" + "emms\n" + : "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value) + );*/ + *(u64*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + + + switch ((int)p) { + case 1: // hwm + hwWrite64(mem & ~0xa0000000, value); + return; + case 6: // gsm + gsWrite64(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache128(mem, value); + return; + } +#endif + p+= mem & 0xfff; + ((u64*)p)[0] = value[0]; + ((u64*)p)[1] = value[1]; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + +/* PSXREC_CLEARM((mem) & 0x1fffff); + PSXREC_CLEARM((mem+4) & 0x1fffff); + PSXREC_CLEARM((mem+8) & 0x1fffff); + PSXREC_CLEARM((mem+12) & 0x1fffff);*/ + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite128(mem & ~0xa0000000, value); + return; + case 6: // gsm + mem &= ~0xa0000000; + gsWrite64(mem, value[0]); + gsWrite64(mem+8, value[1]); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + + +#endif // WIN32_VIRTUAL_MEM + +void loadBiosRom(char *ext, u8 *dest) { + struct stat buf; + char Bios1[256]; + char Bios[256]; + FILE *fp; + char *ptr; + int i; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + sprintf(Bios1, "%s.%s", Bios, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s", Bios); + ptr = Bios1; i = strlen(Bios1); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = 0; + strcat(Bios1, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + SysPrintf("\n\n\n"); + SysPrintf("**************\n"); + SysPrintf("%s NOT FOUND\n", ext); + SysPrintf("**************\n\n\n"); +} + +void memReset() { + struct stat buf; + char Bios[256]; + FILE *fp; + +#ifdef WIN32_VIRTUAL_MEM + DWORD OldProtect; + memset(PS2MEM_BASE, 0, 0x02000000); + memset(PS2MEM_SCRATCH, 0, 0x00004000); +#else + memset(psM, 0, 0x02000000); + memset(psS, 0, 0x00004000); +#endif + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + if (stat(Bios, &buf) == -1) { + SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios); + return; + } + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + fp = fopen(Bios, "rb"); + fread(PS2MEM_ROM, 1, buf.st_size, fp); + fclose(fp); + + BiosVersion = GetBiosVersion(); + SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff); + + //injectIRX("host.irx"); //not fully tested; still buggy + + // reset memLUT + + loadBiosRom("rom1", PS2MEM_ROM1); + loadBiosRom("rom2", PS2MEM_ROM2); + loadBiosRom("erom", PS2MEM_EROM); + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif +} + +void memSetKernelMode() { +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRK; + memLUTW = memLUTWK; +#endif + MemMode = 0; +} + +void memSetSupervisorMode() { +} + +void memSetUserMode() { +#ifdef FULLTLB +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRU; + memLUTW = memLUTWU; +#endif + MemMode = 2; +#endif +} diff --git a/branches/pcsx2_0.9.1/Memory.h b/branches/pcsx2_0.9.1/Memory.h new file mode 100644 index 0000000..36ed71f --- /dev/null +++ b/branches/pcsx2_0.9.1/Memory.h @@ -0,0 +1,263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +////////// +// Rewritten by zerofrog to add os virtual memory +////////// + +#ifndef __MEMORY_H__ +#define __MEMORY_H__ + +//#define ENABLECACHE + +#ifdef WIN32_VIRTUAL_MEM + +typedef struct _PSMEMORYMAP +{ + ULONG_PTR* aPFNs, *aVFNs; +} PSMEMORYMAP; + +#define TRANSFORM_ADDR(memaddr) ( ((u32)(memaddr)>=0x40000000) ? ((memaddr)&~0xa0000000) : (memaddr) ) + +//new memory model +#define PS2MEM_BASE_ 0x18000000 +#define PS2MEM_PSX_ (PS2MEM_BASE_+0x1c000000) + +#define PS2MEM_BASE ((u8*)PS2MEM_BASE_) +#define PS2MEM_HW ((u8*)((u32)PS2MEM_BASE+0x10000000)) +#define PS2MEM_ROM ((u8*)((u32)PS2MEM_BASE+0x1fc00000)) +#define PS2MEM_ROM1 ((u8*)((u32)PS2MEM_BASE+0x1e000000)) +#define PS2MEM_ROM2 ((u8*)((u32)PS2MEM_BASE+0x1e400000)) +#define PS2MEM_EROM ((u8*)((u32)PS2MEM_BASE+0x1e040000)) +#define PS2MEM_PSX ((u8*)PS2MEM_PSX_) +#define PS2MEM_SCRATCH ((u8*)((u32)PS2MEM_BASE+0x50000000)) +#define PS2MEM_VU0MICRO ((u8*)((u32)PS2MEM_BASE+0x11000000)) +#define PS2MEM_VU0MEM ((u8*)((u32)PS2MEM_BASE+0x11004000)) +#define PS2MEM_VU1MICRO ((u8*)((u32)PS2MEM_BASE+0x11008000)) +#define PS2MEM_VU1MEM ((u8*)((u32)PS2MEM_BASE+0x1100c000)) + +// function for mapping memory +#define PS2MEM_PSXHW ((u8*)((u32)PS2MEM_BASE+0x1f800000)) +#define PS2MEM_PSXHW4 ((u8*)((u32)PS2MEM_BASE+0x1f400000)) +#define PS2MEM_GS ((u8*)((u32)PS2MEM_BASE+0x12000000)) +#define PS2MEM_DEV9 ((u8*)((u32)PS2MEM_BASE+0x14000000)) +#define PS2MEM_SPU2 ((u8*)((u32)PS2MEM_BASE+0x1f900000)) +#define PS2MEM_SPU2_ ((u8*)((u32)PS2MEM_BASE+0x1f000000)) // ? +#define PS2MEM_B80 ((u8*)((u32)PS2MEM_BASE+0x18000000)) +#define PS2MEM_BA0 ((u8*)((u32)PS2MEM_BASE+0x1a000000)) + +#define PSM(mem) (PS2MEM_BASE + TRANSFORM_ADDR(mem)) + +#else + +extern u8 *psM; //32mb Main Ram +extern u8 *psR; //4mb rom area +extern u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +extern u8 *psR2; // 0x00080000 +extern u8 *psER; // 0x001C0000 +extern u8 *psS; //0.015 mb, scratch pad + +#define PS2MEM_BASE psM +#define PS2MEM_HW psH +#define PS2MEM_ROM psR +#define PS2MEM_ROM1 psR1 +#define PS2MEM_ROM2 psR2 +#define PS2MEM_EROM psER +#define PS2MEM_SCRATCH psS + +extern u8 g_RealGSMem[0x2000]; +#define PS2MEM_GS g_RealGSMem + +//#define _PSM(mem) (memLUTR[(mem) >> 12] == 0 ? NULL : (void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define PSM(mem) ((void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define FREE(ptr) _aligned_free(ptr) + +extern uptr *memLUTR; +extern uptr *memLUTW; +extern uptr *memLUTRK; +extern uptr *memLUTWK; +extern uptr *memLUTRU; +extern uptr *memLUTWU; + +#endif + +#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs64(mem) (*(s64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu8(mem) (*(u8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu16(mem) (*(u16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu32(mem) (*(u32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu64(mem) (*(u64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) + +#define psRs8(mem) (*(s8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs16(mem) (*(s16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs32(mem) (*(s32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs64(mem) (*(s64*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu8(mem) (*(u8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu16(mem) (*(u16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu32(mem) (*(u32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu64(mem) (*(u64*)&PS2MEM_ROM[(mem) & 0x3fffff]) + +#define psR1s8(mem) (*(s8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s16(mem) (*(s16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s32(mem) (*(s32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s64(mem) (*(s64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u8(mem) (*(u8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u16(mem) (*(u16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u32(mem) (*(u32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u64(mem) (*(u64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) + +#define psR2s8(mem) (*(s8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s16(mem) (*(s16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s32(mem) (*(s32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s64(mem) (*(s64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u8(mem) (*(u8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u16(mem) (*(u16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u32(mem) (*(u32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u64(mem) (*(u64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) + +#define psERs8(mem) (*(s8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs16(mem) (*(s16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs32(mem) (*(s32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs64(mem) (*(s64*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu8(mem) (*(u8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu16(mem) (*(u16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff]) + +#define psSs8(mem) (*(s8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs16(mem) (*(s16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs32(mem) (*(s32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs64(mem) (*(s64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu8(mem) (*(u8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu16(mem) (*(u16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) + +#define PSMs8(mem) (*(s8 *)PSM(mem)) +#define PSMs16(mem) (*(s16*)PSM(mem)) +#define PSMs32(mem) (*(s32*)PSM(mem)) +#define PSMs64(mem) (*(s64*)PSM(mem)) +#define PSMu8(mem) (*(u8 *)PSM(mem)) +#define PSMu16(mem) (*(u16*)PSM(mem)) +#define PSMu32(mem) (*(u32*)PSM(mem)) +#define PSMu64(mem) (*(u64*)PSM(mem)) + +int memInit(); +void memReset(); +void memSetKernelMode(); +void memSetSupervisorMode(); +void memSetUserMode(); +void memSetPageAddr(u32 vaddr, u32 paddr); +void memClearPageAddr(u32 vaddr); +void memShutdown(); + +int memRead8(u32 mem, u8 *out); +int memRead8RS(u32 mem, u64 *out); +int memRead8RU(u32 mem, u64 *out); +int memRead16(u32 mem, u16 *out); +int memRead16RS(u32 mem, u64 *out); +int memRead16RU(u32 mem, u64 *out); +int memRead32(u32 mem, u32 *out); +int memRead32RS(u32 mem, u64 *out); +int memRead32RU(u32 mem, u64 *out); +int memRead64(u32 mem, u64 *out); +int memRead128(u32 mem, u64 *out); +void memWrite8 (u32 mem, u8 value); +void memWrite16(u32 mem, u16 value); +void memWrite32(u32 mem, u32 value); +void memWrite64(u32 mem, u64 value); +void memWrite128(u32 mem, u64 *value); + +// recMemConstRead8, recMemConstRead16, recMemConstRead32 return 1 if a call was made, 0 otherwise +u8 recMemRead8(); +u16 recMemRead16(); +u32 recMemRead32(); +void recMemRead64(u64 *out); +void recMemRead128(u64 *out); + +// returns 1 if mem should be cleared +void recMemWrite8(); +void recMemWrite16(); +void recMemWrite32(); +void recMemWrite64(); +void recMemWrite128(); + +// VM only functions +#ifdef WIN32_VIRTUAL_MEM + +void _eeReadConstMem8(int mmreg, u32 mem, int sign); +void _eeReadConstMem16(int mmreg, u32 mem, int sign); +void _eeReadConstMem32(int mmreg, u32 mem); +void _eeReadConstMem128(int mmreg, u32 mem); +void _eeWriteConstMem8(u32 mem, int mmreg); +void _eeWriteConstMem16(u32 mem, int mmreg); +void _eeWriteConstMem32(u32 mem, int mmreg); +void _eeWriteConstMem64(u32 mem, int mmreg); +void _eeWriteConstMem128(u32 mem, int mmreg); +void _eeMoveMMREGtoR(int to, int mmreg); + +// extra ops +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op); +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op); + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead32(u32 x86reg, u32 mem); +void recMemConstRead64(u32 mem, int mmreg); +void recMemConstRead128(u32 mem, int xmmreg); + +int recMemConstWrite8(u32 mem, int mmreg); +int recMemConstWrite16(u32 mem, int mmreg); +int recMemConstWrite32(u32 mem, int mmreg); +int recMemConstWrite64(u32 mem, int mmreg); +int recMemConstWrite128(u32 mem, int xmmreg); + +#else + +#define _eeReadConstMem8 0&& +#define _eeReadConstMem16 0&& +#define _eeReadConstMem32 0&& +#define _eeReadConstMem128 0&& +#define _eeWriteConstMem8 0&& +#define _eeWriteConstMem16 0&& +#define _eeWriteConstMem32 0&& +#define _eeWriteConstMem64 0&& +#define _eeWriteConstMem128 0&& +#define _eeMoveMMREGtoR 0&& + +// extra ops +#define _eeWriteConstMem16OP 0&& +#define _eeWriteConstMem32OP 0&& + +#define recMemConstRead8 0&& +#define recMemConstRead16 0&& +#define recMemConstRead32 0&& +#define recMemConstRead64 0&& +#define recMemConstRead128 0&& + +#define recMemConstWrite8 0&& +#define recMemConstWrite16 0&& +#define recMemConstWrite32 0&& +#define recMemConstWrite64 0&& +#define recMemConstWrite128 0&& + +#endif + +#endif diff --git a/branches/pcsx2_0.9.1/Misc.c b/branches/pcsx2_0.9.1/Misc.c new file mode 100644 index 0000000..6cc8abc --- /dev/null +++ b/branches/pcsx2_0.9.1/Misc.c @@ -0,0 +1,816 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "CDVDisodrv.h" +#include "VUmicro.h" +#ifdef __WIN32__ +#include "RDebug/deci2.h" +#endif + +DWORD dwSaveVersion = 0x7a30000c; +extern u32 s_iLastCOP0Cycle; +extern int g_psxWriteOk; + +PcsxConfig Config; +u32 BiosVersion; +char CdromId[12]; + +char *LabelAuthors = { N_( + "PCSX2 a PS2 emulator\n\n" + "written by:\n" + "saqib, refraction, zerofrog,\n" + "shadow, linuzappz, florin,\n" + "nachbrenner, auMatt, loser, \n" + "alexey silinov, goldfinger,\n" + "\n" + "Webmasters: CKemu, Falcon4ever") +}; + +char *LabelGreets = { N_( + "Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" + "Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" + "Seta-San, Skarmeth, blackd_wd, _Demo_\n" + "\n" + "Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n" + "\n" + "Some betatester/support dudes: Belmont, bositman, ChaosCode, CKemu, crushtest," + "falcon4ever, GeneralPlot, jegHegy, parotaku, Prafull, Razorblade, Rudy_X, Seta-san") +}; + +static struct { + char *name; + u32 size; +} ioprps[]={ + {"IOPRP14", 43845}, + {"IOPRP142", 48109}, + {"IOPRP143", 58317}, + {"IOPRP144", 58525}, + {"IOPRP15", 82741}, + {"IOPRP151", 82917}, + {"IOPRP153", 82949}, + {"IOPRP16", 91909}, + {"IOPRP165", 98901}, + {"IOPRP20", 109809}, + {"IOPRP202", 110993}, + {"IOPRP205", 119797}, + {"IOPRP21", 126857}, + {"IOPRP211", 129577}, + {"IOPRP213", 129577}, + {"IOPRP214", 140945}, + {"IOPRP22", 199257}, + {"IOPRP221", 196937}, + {"IOPRP222", 198233}, + {"IOPRP224", 201065}, + {"IOPRP23", 230329}, + {"IOPRP234", 247641}, + {"IOPRP24", 251065}, + {"IOPRP241", 251049}, + {"IOPRP242", 252409}, + {"IOPRP243", 253201}, + {"IOPRP250", 264897}, + {"IOPRP252", 265233}, + {"IOPRP253", 267217}, + {"IOPRP254", 264449}, + {"IOPRP255", 264449}, + {"IOPRP260", 248945}, + {"IOPRP270", 249121}, + {"IOPRP271", 266817}, + {"IOPRP280", 269889}, + {"IOPRP300", 275345}, + {"DNAS280", 272753}, + {"DNAS270", 251729}, + {"DNAS271", 268977}, + {"DNAS300", 278641}, + {"DNAS280", 272705}, + {"DNAS255", 264945}, + {NULL, 0} +}; + +void GetRPCVersion(char *ioprp, char *rpcver){ + char *p=ioprp; int i; + struct TocEntry te; + + if (p && (CDVD_findfile(p+strlen("cdromN:"), &te) != -1)){ + for (i=0; ioprps[i].size>0; i++) + if (te.fileSize==ioprps[i].size) + break; + if (ioprps[i].size>0) + p=ioprps[i].name; + } + if (p && (p=strstr(p, "IOPRP")+strlen("IOPRP"))){ + for (i=0;(i<4) && p && (*p>='0') && (*p<='9');i++, p++) rpcver[i]=*p; + for ( ; i<4 ;i++ ) rpcver[i]='0'; + } +} + +u32 GetBiosVersion() { + unsigned int fileOffset=0; + char *ROMVER; + char vermaj[8]; + char vermin[8]; + struct romdir *rd; + u32 version; + int i; + + for (i=0; i<512*1024; i++) { + rd = (struct romdir*)&psRu8(i); + if (strncmp(rd->fileName, "RESET", 5) == 0) + break; /* found romdir */ + } + if (i == 512*1024) return -1; + + while(strlen(rd->fileName) > 0){ + if (strcmp(rd->fileName, "ROMVER") == 0){ // found romver + ROMVER = &psRu8(fileOffset); + + strncpy(vermaj, ROMVER+ 0, 2); vermaj[2] = 0; + strncpy(vermin, ROMVER+ 2, 2); vermin[2] = 0; + version = strtol(vermaj, (char**)NULL, 0) << 8; + version|= strtol(vermin, (char**)NULL, 0); + + return version; + } + + if ((rd->fileSize % 0x10)==0) + fileOffset += rd->fileSize; + else + fileOffset += (rd->fileSize + 0x10) & 0xfffffff0; + + rd++; + } + + return -1; +} + +//2002-09-22 (Florin) +int IsBIOS(char *filename, char *description){ + struct stat buf; + char Bios[260], ROMVER[14+1], zone[12+1]; + FILE *fp; + unsigned int fileOffset=0, found=FALSE; + struct romdir rd; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, filename); + + if (stat(Bios, &buf) == -1) return FALSE; + + fp = fopen(Bios, "rb"); + if (fp == NULL) return FALSE; + + while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1)) + if (strcmp(rd.fileName, "RESET") == 0) + break; /* found romdir */ + + if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) { + fclose(fp); + return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img + } + + while(strlen(rd.fileName) > 0){ + if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver + unsigned int filepos=ftell(fp); + fseek(fp, fileOffset, SEEK_SET); + if (fread(&ROMVER, 14, 1, fp) == 0) break; + fseek(fp, filepos, SEEK_SET);//go back + + switch(ROMVER[4]){ + case 'T':sprintf(zone, "T10K "); break; + case 'X':sprintf(zone, "Test ");break; + case 'J':sprintf(zone, "Japan "); break; + case 'A':sprintf(zone, "USA "); break; + case 'E':sprintf(zone, "Europe"); break; + case 'H':sprintf(zone, "HK "); break; + case 'P':sprintf(zone, "Free "); break; + case 'C':sprintf(zone, "China "); break; + default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show + } + sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone, + ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); + strncpy(description+ 8, ROMVER+ 0, 2);//ver major + strncpy(description+11, ROMVER+ 2, 2);//ver minor + strncpy(description+14, ROMVER+12, 2);//day + strncpy(description+17, ROMVER+10, 2);//month + strncpy(description+20, ROMVER+ 6, 4);//year + found = TRUE; + } + + if ((rd.fileSize % 0x10)==0) + fileOffset += rd.fileSize; + else + fileOffset += (rd.fileSize + 0x10) & 0xfffffff0; + + if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break; + } + fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize; + + fclose(fp); + + if (found) { + char percent[6]; + + if (buf.st_size<(int)fileOffset){ + sprintf(percent, " %d%%", buf.st_size*100/(int)fileOffset); + strcat(description, percent);//we force users to have correct bioses, + //not that lame scph10000 of 513KB ;-) + } + return TRUE; + } + + return FALSE; //fail quietly +} + +// LOAD STUFF + +#define ISODCL(from, to) (to - from + 1) + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +#define READTRACK(lsn) \ + if (CDVDreadTrack(lsn, CDVD_MODE_2352) == -1) return -1; \ + buf = CDVDgetBuffer(); if (buf == NULL) return -1; + +int LoadCdrom() { + return 0; +} + +int CheckCdrom() { + u8 *buf; + + READTRACK(16); + strncpy(CdromId, buf+52, 10); + + return 0; +} + +int GetPS2ElfName(char *name){ + FILE *fp; + int f; + char buffer[256];//if a file is longer...it should be shorter :D + char *pos; + static struct TocEntry tocEntry; + int i; + + CDVDFS_init(); + + // check if the file exists + if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){ + SysPrintf("SYSTEM.CNF not found\n"); + return 0;//could not find; not a PS/PS2 cdvd + } + + f=CDVDFS_open("SYSTEM.CNF;1", 1); + CDVDFS_read(f, buffer, 256); + CDVDFS_close(f); + + buffer[tocEntry.fileSize]='\0'; + +// SysPrintf( +// "---------------------SYSTEM.CNF---------------------\n" +// "%s" +// "----------------------------------------------------\n", buffer); + pos=strstr(buffer, "BOOT2"); + if (pos==NULL){ + pos=strstr(buffer, "BOOT"); + if (pos==NULL) { + SysPrintf("This is not a PS2 game!\n"); + return 0; + } + return 1; + } + pos+=strlen("BOOT2"); + while (pos && *pos && pos<=&buffer[255] + && (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z')) + pos++; + if (!pos || *pos==0) + return 0; + + sscanf(pos, "%s", name); + //SysPrintf("ELF name: '%s'\n", name); + + if (strncmp("cdrom0:\\", name, 8) == 0) { + strncpy(CdromId, name+8, 11); CdromId[11] = 0; + } + +// inifile_read(CdromId); + + fp = fopen("System.map", "r"); + if (fp) { + u32 addr; + + SysPrintf("Loading System.map\n", fp); + while (!feof(fp)) { + fseek(fp, 8, SEEK_CUR); + buffer[0] = '0'; buffer[1] = 'x'; + for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0; + addr = strtoul(buffer, (char**)NULL, 0); + fseek(fp, 3, SEEK_CUR); + for (i=0; i<256; i++) { + buffer[i] = fgetc(fp); + if (buffer[i] == '\n' || buffer[i] == 0) break; + } + if (buffer[i] == 0) break; + buffer[i] = 0; + + disR5900AddSym(addr, buffer); + } + fclose(fp); + } + + return 2; +} + +/*#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +static int PSXGetFileType(FILE *f) { + unsigned long current; + unsigned long mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + + strcpy(CdromId, "SLUS_999.99"); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { SysMessage("Error opening file: %s", ExePath); return 0; } + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile); + fclose(tmpFile); + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.s_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + break; + case CPE_EXE: + SysMessage("Pcsx found that you wanna use a CPE file. CPE files not support yet"); + break; + case COFF_EXE: + SysMessage("Pcsx found that you wanna use a COFF file.COFF files not support yet"); + break; + case INVALID_EXE: + SysMessage("This file is not a psx file"); + break; + } + return 1; +} +*/ + +u16 logProtocol; +u8 logSource; +int connected=0; + +#define SYNC_LOGGING + +void __Log(char *fmt, ...) { +#ifdef EMU_LOG + va_list list; + static char tmp[2024]; //hm, should be enough + + va_start(list, fmt); +#ifdef __WIN32__ + if (connected && logProtocol>=0 && logProtocol<0x10){ + vsprintf(tmp, fmt, list); + sendTTYP(logProtocol, logSource, tmp); + }//else //!!!!! is disabled, so the text goes to ttyp AND log +#endif + { +#ifndef LOG_STDOUT + if (varLog & 0x80000000) { + vsprintf(tmp, fmt, list); + SysPrintf(tmp); + } else if( emuLog != NULL ) { + vfprintf(emuLog, fmt, list); + } +#else //i assume that this will not be used (Florin) + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + } + va_end(list); +#endif +} + +// STATES + +#define STATE_VERSION "STv6" +const char Pcsx2Header[32] = STATE_VERSION " PCSX2 v" PCSX2_VERSION; + +#define _PS2Esave(type) \ + if (type##freeze(FREEZE_SIZE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + fP.data = malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + \ + if (type##freeze(FREEZE_SAVE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + \ + gzwrite(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + gzwrite(f, fP.data, fP.size); \ + free(fP.data); \ + } + +#define _PS2Eload(type) \ + gzread(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + gzread(f, fP.data, fP.size); \ + } \ + if (type##freeze(FREEZE_LOAD, &fP) == -1) { \ + if (fP.size) free(fP.data); \ + gzclose(f); \ + return -1; \ + } \ + if (fP.size) free(fP.data); + + +extern void gsWaitGS(); + +extern u32 g_nextBranchCycle, g_psxNextBranchCycle; + +int SaveState(char *file) { + + gzFile f; + freezeData fP; + + gsWaitGS(); + + SysPrintf("SaveState: %s\n", file); + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, &dwSaveVersion, 4); + + gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + + gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory + + gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs] + gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzwrite(f, &EEsCycle, sizeof(EEsCycle)); + gzwrite(f, &EEoCycle, sizeof(EEoCycle)); + gzwrite(f, &IOPoCycle, sizeof(IOPoCycle)); + gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + //gzwrite(f, (void*)&ipuRegs, sizeof(IPUregisters)); // ipu regs + //hope didn't forgot any cpu.... + + rcntFreeze(f, 1); + gsFreeze(f, 1); + vu0Freeze(f, 1); + vu1Freeze(f, 1); + vif0Freeze(f, 1); + vif1Freeze(f, 1); + sifFreeze(f, 1); + ipuFreeze(f, 1); + + // iop now + gzwrite(f, psxM, 0x00200000); // 2 MB main memory + //gzwrite(f, psxP, 0x00010000); // pralell memory + gzwrite(f, psxH, 0x00010000); // hardware memory + //gzwrite(f, psxS, 0x00010000); // sif memory + + sioFreeze(f, 1); + cdrFreeze(f, 1); + cdvdFreeze(f, 1); + psxRcntFreeze(f, 1); + //mdecFreeze(f, 1); + sio2Freeze(f, 1); + + SysPrintf("Saving GS\n"); + _PS2Esave(GS); + SysPrintf("Saving SPU2\n"); + _PS2Esave(SPU2); + SysPrintf("Saving DEV9\n"); + _PS2Esave(DEV9); + SysPrintf("Saving USB\n"); + _PS2Esave(USB); + SysPrintf("Saving ok\n"); + + gzclose(f); + + return 0; +} + +extern u32 dumplog; +extern u32 s_vucount; + +int LoadState(char *file) { + + gzFile f; + freezeData fP; + int i; + DWORD OldProtect; + DWORD dwVer; + +#ifdef _DEBUG + s_vucount = 0; + //dumplog |= 2; +#endif + + SysPrintf("LoadState: %s\n", file); + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, &dwVer, 4); + + if( dwVer != dwSaveVersion ) { + gzclose(f); + MessageBox(NULL, "Save state wrong version", "Error", MB_OK); + return 0; + } + + // stop and reset the system first + gsWaitGS(); + + for (i=0; i<48; i++) ClearTLB(i); + + Cpu->Reset(); + recResetVU0(); + recResetVU1(); + psxCpu->Reset(); + + SysPrintf("Loading memory\n"); + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif + + gzread(f, PS2MEM_HW, 0x00010000); // hardware memory + + SysPrintf("Loading structs\n"); + gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs + gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzread(f, &EEsCycle, sizeof(EEsCycle)); + gzread(f, &EEoCycle, sizeof(EEoCycle)); + gzread(f, &IOPoCycle, sizeof(IOPoCycle)); + gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + rcntFreeze(f, 0); + gsFreeze(f, 0); + vu0Freeze(f, 0); + vu1Freeze(f, 0); + vif0Freeze(f, 0); + vif1Freeze(f, 0); + sifFreeze(f, 0); + ipuFreeze(f, 0); + + // iop now + SysPrintf("Loading iop mem\n"); + gzread(f, psxM, 0x00200000); // 2 MB main memory + //gzread(f, psxP, 0x00010000); // pralell memory + gzread(f, psxH, 0x00010000); // hardware memory + //gzread(f, psxS, 0x00010000); // sif memory + + SysPrintf("Loading iop stuff\n"); + sioFreeze(f, 0); + cdrFreeze(f, 0); + cdvdFreeze(f, 0); + psxRcntFreeze(f, 0); + //mdecFreeze(f, 0); + sio2Freeze(f, 0); + + SysPrintf("Loading GS\n"); + _PS2Eload(GS); + SysPrintf("Loading SPU2\n"); + _PS2Eload(SPU2); + SysPrintf("Loading DEV9\n"); + _PS2Eload(DEV9); + SysPrintf("Loading USB\n"); + _PS2Eload(USB); + + SysPrintf("Loading ok\n"); + + gzclose(f); + + //dumplog |= 4; + WriteCP0Status(cpuRegs.CP0.n.Status.val); + for (i=0; i<48; i++) WriteTLB(i); + + return 0; +} + +int CheckState(char *file) { + gzFile f; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, 32); + + gzclose(f); + + if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1; + + return 0; +} + + +typedef struct { + char id[8]; + char name[64]; +} LangDef; + +LangDef sLangs[] = { + { "ar_AR", N_("Arabic") }, + { "bg_BG", N_("Bulgarian") }, + { "ca_CA", N_("Catalan") }, + { "du_DU", N_("Dutch") }, + { "de_DE", N_("German") }, + { "el_EL", N_("Greek") }, + { "en_US", N_("English") }, + { "fr_FR", N_("French") }, + { "hb_HB" , N_("Hebrew") }, + { "hu_HU", N_("Hungarian") }, + { "it_IT", N_("Italian") }, + { "ja_JA", N_("Japanese") }, + { "po_PO", N_("Portuguese") }, + { "pl_PL" , N_("Polish") }, + { "ro_RO", N_("Romanian") }, + { "ru_RU", N_("Russian") }, + { "es_ES", N_("Spanish") }, + { "sh_SH" , N_("S-Chinese") }, + { "tc_TC", N_("T-Chinese") }, + { "tr_TR", N_("Turkish") }, + { "", "" }, +}; + + +char *ParseLang(char *id) { + int i=0; + + while (sLangs[i].id[0] != 0) { + if (!strcmp(id, sLangs[i].id)) + return _(sLangs[i].name); + i++; + } + + return id; +} + +void injectIRX(char *filename){ + struct stat buf; + char path[260], name[260], *p, *q; + struct romdir *rd; + int iROMDIR=-1, iIOPBTCONF=-1, iBLANK=-1, i, filesize; + FILE *fp; + + strcpy(name, filename); + for (i=0; name[i] && name[i]!='.' && i<10; i++) name[i]=toupper(name[i]);name[i]=0; + + //phase 1: find ROMDIR in bios + for (p=PS2MEM_ROM; pq){*((u64*)p)=*((u64*)p-4);*((u64*)p+1)=*((u64*)p-3);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iIOPBTCONF].fileSize+=DIRENTRY_SIZE; + + q=PS2MEM_ROM;for (i=0; i<=iROMDIR; i++) q+=(rd[i].fileSize+0xF)&(~0xF); + while (p >q){*((u64*)p)=*((u64*)p-2);*((u64*)p+1)=*((u64*)p-1);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iROMDIR].fileSize+=DIRENTRY_SIZE; + + //phase 3: add the name to the end of IOPBTCONF + p=PS2MEM_ROM;for (i=0; i +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2DMA4irqCallback(void (*callback)()); +void CALLBACK SPU2DMA7irqCallback(void (*callback)()); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2DMA4irqCallback)(void (*callback)()); +typedef void (CALLBACK* _SPU2DMA7irqCallback)(void (*callback)()); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2DMA4irqCallback SPU2DMA4irqCallback; +_SPU2DMA7irqCallback SPU2DMA7irqCallback; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/branches/pcsx2_0.9.1/PS2Etypes.h b/branches/pcsx2_0.9.1/PS2Etypes.h new file mode 100644 index 0000000..2700c92 --- /dev/null +++ b/branches/pcsx2_0.9.1/PS2Etypes.h @@ -0,0 +1,47 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/branches/pcsx2_0.9.1/Patch.c b/branches/pcsx2_0.9.1/Patch.c new file mode 100644 index 0000000..f20d41f --- /dev/null +++ b/branches/pcsx2_0.9.1/Patch.c @@ -0,0 +1,322 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Includes +// +#include +#include + +#include "PsxCommon.h" + +// +// Defines +// +#define MAX_PATCH 1024 + +#define IFIS(x,str) if(!strnicmp(x,str,sizeof(str)-1)) + +#define GETNEXT_PARAM() \ + while ( *param && ( *param != ',' ) ) param++; \ + if ( *param ) param++; \ + while ( *param && ( *param == ' ' ) ) param++; \ + if ( *param == 0 ) { SysPrintf( _( "Not enough params for inicommand\n" ) ); return; } + +// +// Typedefs +// +typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 ); + +typedef struct +{ + char * text; + int code; + PATCHTABLEFUNC func; +} PatchTextTable; + +typedef struct +{ + int type; + int cpu; + int placetopatch; + u32 addr; + u32 data; +} IniPatch; + +// +// Function prototypes +// +void patchFunc_comment( char * text1, char * text2 ); +void patchFunc_gametitle( char * text1, char * text2 ); +void patchFunc_patch( char * text1, char * text2 ); + +void inifile_trim( char * buffer ); + +// +// Variables +// +PatchTextTable commands[] = +{ + { "comment", 1, patchFunc_comment }, + { "gametitle", 2, patchFunc_gametitle }, + { "patch", 3, patchFunc_patch }, + { "", 0, NULL } +}; + +PatchTextTable dataType[] = +{ + { "byte", 1, NULL }, + { "word", 2, NULL }, + { "", 0, NULL } +}; + +PatchTextTable cpuCore[] = +{ + { "EE", 1, NULL }, + { "IOP", 2, NULL }, + { "", 0, NULL } +}; + +IniPatch patch[ MAX_PATCH ]; +int patchnumber; + + +// +// Function Implementations +// + +int PatchTableExecute( char * text1, char * text2, PatchTextTable * Table ) +{ + int i = 0; + + while ( Table[ i ].text[ 0 ] ) + { + if ( !strcmp( Table[ i ].text, text1 ) ) + { + if ( Table[ i ].func ) + { + Table[ i ].func( text1, text2 ); + } + break; + } + i++; + } + + return Table[ i ].code; +} + +void _applypatch(int place, IniPatch *p) { + if (p->placetopatch != place) return; + + if (p->cpu == 1) { //EE + if (p->type == 1) { //byte + memWrite8(p->addr, p->data); + } else + if (p->type == 2) { //word + memWrite32(p->addr, p->data); + } + } else + if (p->cpu == 2) { //IOP + if (p->type == 1) { //byte + psxMemWrite8(p->addr, p->data); + } else + if (p->type == 2) { //word + psxMemWrite32(p->addr, p->data); + } + } +} + +//this is for apply patches directly to memory +void applypatch(int place) { + int i; + + if (place == 0) { + SysPrintf(" patchnumber: %d\n", patchnumber); + } + + for ( i = 0; i < patchnumber; i++ ) { + _applypatch(place, &patch[i]); + } +} + +void patchFunc_comment( char * text1, char * text2 ) +{ + SysPrintf( "comment: %s \n", text2 ); +} + +void patchFunc_gametitle( char * text1, char * text2 ) +{ + char str2[256]; + SysPrintf( "gametitle: %s \n", text2 ); +#ifdef __WIN32__ + sprintf(str2,"Running Game %s",text2); + if (gApp.hConsole) SetConsoleTitle(str2); +#endif +} + +void patchFunc_patch( char * cmd, char * param ) +{ + //patch=placetopatch,cpucore,address,type,data + char * pText; + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached: %s=%s\n", cmd, param ); + return; + } + + pText = strtok( param, "," ); + pText = param; +// inifile_trim( pText ); + + patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].cpu = PatchTableExecute( pText, NULL, cpuCore ); + if ( patch[ patchnumber ].cpu == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].addr ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].type = PatchTableExecute( pText, NULL, dataType ); + if ( patch[ patchnumber ].type == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].data ); + + patchnumber++; +} + +//this routine is for execute the commands of the ini file +void inifile_command( char * cmd ) +{ + int code; + char command[ 256 ]; + char parameter[ 256 ]; + + // extract param part (after '=') + char * pEqual = strchr( cmd, '=' ); + + if ( ! pEqual ) + { + SysPrintf( "Ini file ERROR: unknow line: %s \n", cmd ); + return; + } + + memset( command, 0, sizeof( command ) ); + memset( parameter, 0, sizeof( parameter ) ); + + strncpy( command, cmd, pEqual - cmd ); + strncpy( parameter, pEqual + 1, sizeof( parameter ) ); + + inifile_trim( command ); + inifile_trim( parameter ); + + code = PatchTableExecute( command, parameter, commands ); +} + +void inifile_trim( char * buffer ) +{ + char * pInit = buffer; + char * pEnd = NULL; + + while ( ( *pInit == ' ' ) || ( *pInit == '\t' ) ) //skip space + { + pInit++; + } + if ( ( pInit[ 0 ] == '/' ) && ( pInit[ 1 ] == '/' ) ) //remove comment + { + buffer[ 0 ] = '\0'; + return; + } + pEnd = pInit + strlen( pInit ) - 1; + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + while ( ( *pEnd == '\r' ) || ( *pEnd == '\n' ) || + ( *pEnd == ' ' ) || ( *pEnd == '\t' ) ) + { + pEnd--; + } + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + memmove( buffer, pInit, pEnd - pInit + 1 ); + buffer[ pEnd - pInit + 1 ] = '\0'; +} + +void inisection_process( FILE * f1 ) +{ + char buffer[ 1024 ]; + while( fgets( buffer, sizeof( buffer ), f1 ) ) + { + inifile_trim( buffer ); + if ( buffer[ 0 ] ) + { + inifile_command( buffer ); + } + } +} + +//this routine is for reading the ini file + +void inifile_read( char * name ) +{ + FILE * f1; + char buffer[ 1024 ]; + + patchnumber = 0; +#ifdef __WIN32__ + sprintf( buffer, "patches\\%s.pnach", name ); +#else + sprintf( buffer, "patches/%s.pnach", name ); +#endif + + f1 = fopen( buffer, "rt" ); + if( !f1 ) + { + SysPrintf( _( "patch file for this game not found. Can't apply any patches\n" ) ); + return; + } + + inisection_process( f1 ); + + fclose( f1 ); +} + +void resetpatch( void ) +{ + patchnumber = 0; +} diff --git a/branches/pcsx2_0.9.1/Patch.h b/branches/pcsx2_0.9.1/Patch.h new file mode 100644 index 0000000..6ffd220 --- /dev/null +++ b/branches/pcsx2_0.9.1/Patch.h @@ -0,0 +1,10 @@ +#ifndef __PATCH_H__ +#define __PATCH_H__ + +void applypatch( int place ); +void inifile_read( char * name ); +void inifile_command( char * cmd ); +void resetpatch( void ); + +#endif /* __PATCH_H__ */ + diff --git a/branches/pcsx2_0.9.1/Plugins.c b/branches/pcsx2_0.9.1/Plugins.c new file mode 100644 index 0000000..cf41c33 --- /dev/null +++ b/branches/pcsx2_0.9.1/Plugins.c @@ -0,0 +1,603 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define CheckErr(func) \ + err = SysLibError(); \ + if (err != NULL) { SysMessage (_("%s: Error loading %s: %s"), filename, func, err); return -1; } + +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, name); if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } + +#define TestPS2Esyms(type) { \ + _PS2EgetLibVersion2 PS2EgetLibVersion2; \ + SysLoadSym(drv, "PS2EgetLibType"); CheckErr("PS2EgetLibType"); \ + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) SysLoadSym(drv, "PS2EgetLibVersion2"); CheckErr("PS2EgetLibVersion2"); \ + SysLoadSym(drv, "PS2EgetLibName"); CheckErr("PS2EgetLibName"); \ + if( ((PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff) != PS2E_##type##_VERSION) { \ + SysMessage (_("Can't load '%s', wrong PS2E version (%x != %x)"), filename, (PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff, PS2E_##type##_VERSION); return -1; \ + } \ +} + +static char *err; +static int errval; + +void *GSplugin; + +void CALLBACK GS_printf(int timeout, char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + SysPrintf(msg); +} + +s32 CALLBACK GS_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK GS_keyEvent(keyEvent *ev) {} +void CALLBACK GS_makeSnapshot(char *path) {} +void CALLBACK GS_irqCallback(void (*callback)()) {} +void CALLBACK GS_configure() {} +void CALLBACK GS_about() {} +long CALLBACK GS_test() { return 0; } + +#define LoadGSsym1(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 1); + +#define LoadGSsym0(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); \ + if (GS##dest == NULL) GS##dest = (_GS##dest) GS_##dest; + +#define LoadGSsymN(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); + +int LoadGSplugin(char *filename) { + void *drv; + + GSplugin = SysLoadLibrary(filename); + if (GSplugin == NULL) { SysMessage (_("Could Not Load GS Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = GSplugin; + TestPS2Esyms(GS); + LoadGSsym1(init, "GSinit"); + LoadGSsym1(shutdown, "GSshutdown"); + LoadGSsym1(open, "GSopen"); + LoadGSsym1(close, "GSclose"); + LoadGSsym1(gifTransfer1, "GSgifTransfer1"); + LoadGSsym1(gifTransfer2, "GSgifTransfer2"); + LoadGSsym1(gifTransfer3, "GSgifTransfer3"); + LoadGSsym1(readFIFO, "GSreadFIFO"); + LoadGSsymN(readFIFO2, "GSreadFIFO2"); // optional + LoadGSsym1(vsync, "GSvsync"); + + LoadGSsym0(keyEvent, "GSkeyEvent"); + LoadGSsymN(changeSaveState, "GSchangeSaveState"); + LoadGSsymN(gifSoftReset, "GSgifSoftReset"); + LoadGSsym0(makeSnapshot, "GSmakeSnapshot"); + LoadGSsym0(irqCallback, "GSirqCallback"); + LoadGSsym0(printf, "GSprintf"); + LoadGSsym1(setBaseMem, "GSsetBaseMem"); + LoadGSsym1(reset, "GSreset"); + LoadGSsym1(writeCSR, "GSwriteCSR"); + LoadGSsymN(makeSnapshot2,"GSmakeSnapshot2"); + LoadGSsymN(getDriverInfo,"GSgetDriverInfo"); +#ifdef __WIN32__ + LoadGSsymN(setWindowInfo,"GSsetWindowInfo"); +#endif + LoadGSsym0(freeze, "GSfreeze"); + LoadGSsym0(configure, "GSconfigure"); + LoadGSsym0(about, "GSabout"); + LoadGSsym0(test, "GStest"); + + return 0; +} + +void *PAD1plugin; + +void CALLBACK PAD1_configure() {} +void CALLBACK PAD1_about() {} +long CALLBACK PAD1_test() { return 0; } + +#define LoadPAD1sym1(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 1); + +#define LoadPAD1sym0(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); \ + if (PAD1##dest == NULL) PAD1##dest = (_PAD##dest) PAD1_##dest; + +#define LoadPAD1symN(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); + +int LoadPAD1plugin(char *filename) { + void *drv; + + PAD1plugin = SysLoadLibrary(filename); + if (PAD1plugin == NULL) { SysMessage (_("Could Not Load PAD1 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD1plugin; + TestPS2Esyms(PAD); + LoadPAD1sym1(init, "PADinit"); + LoadPAD1sym1(shutdown, "PADshutdown"); + LoadPAD1sym1(open, "PADopen"); + LoadPAD1sym1(close, "PADclose"); + LoadPAD1sym1(keyEvent, "PADkeyEvent"); + LoadPAD1sym1(startPoll, "PADstartPoll"); + LoadPAD1sym1(poll, "PADpoll"); + LoadPAD1sym1(query, "PADquery"); + + LoadPAD1symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD1sym0(configure, "PADconfigure"); + LoadPAD1sym0(about, "PADabout"); + LoadPAD1sym0(test, "PADtest"); + + return 0; +} + +void *PAD2plugin; + +void CALLBACK PAD2_configure() {} +void CALLBACK PAD2_about() {} +long CALLBACK PAD2_test() { return 0; } + +#define LoadPAD2sym1(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 1); + +#define LoadPAD2sym0(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); \ + if (PAD2##dest == NULL) PAD2##dest = (_PAD##dest) PAD2_##dest; + +#define LoadPAD2symN(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); + +int LoadPAD2plugin(char *filename) { + void *drv; + + PAD2plugin = SysLoadLibrary(filename); + if (PAD2plugin == NULL) { SysMessage (_("Could Not Load PAD2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD2plugin; + TestPS2Esyms(PAD); + LoadPAD2sym1(init, "PADinit"); + LoadPAD2sym1(shutdown, "PADshutdown"); + LoadPAD2sym1(open, "PADopen"); + LoadPAD2sym1(close, "PADclose"); + LoadPAD2sym1(keyEvent, "PADkeyEvent"); + LoadPAD2sym1(startPoll, "PADstartPoll"); + LoadPAD2sym1(poll, "PADpoll"); + LoadPAD2sym1(query, "PADquery"); + + LoadPAD2symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD2sym0(configure, "PADconfigure"); + LoadPAD2sym0(about, "PADabout"); + LoadPAD2sym0(test, "PADtest"); + + return 0; +} + +void *SPU2plugin; + +s32 CALLBACK SPU2_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK SPU2_configure() {} +void CALLBACK SPU2_about() {} +s32 CALLBACK SPU2_test() { return 0; } + +#define LoadSPU2sym1(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 1); + +#define LoadSPU2sym0(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); \ + if (SPU2##dest == NULL) SPU2##dest = (_SPU2##dest) SPU2_##dest; + +#define LoadSPU2symN(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); + +int LoadSPU2plugin(char *filename) { + void *drv; + + SPU2plugin = SysLoadLibrary(filename); + if (SPU2plugin == NULL) { SysMessage (_("Could Not Load SPU2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = SPU2plugin; + TestPS2Esyms(SPU2); + LoadSPU2sym1(init, "SPU2init"); + LoadSPU2sym1(shutdown, "SPU2shutdown"); + LoadSPU2sym1(open, "SPU2open"); + LoadSPU2sym1(close, "SPU2close"); + LoadSPU2sym1(write, "SPU2write"); + LoadSPU2sym1(read, "SPU2read"); + LoadSPU2sym1(readDMA4Mem, "SPU2readDMA4Mem"); + LoadSPU2sym1(writeDMA4Mem, "SPU2writeDMA4Mem"); + LoadSPU2sym1(interruptDMA4,"SPU2interruptDMA4"); + LoadSPU2sym1(readDMA7Mem, "SPU2readDMA7Mem"); + LoadSPU2sym1(writeDMA7Mem, "SPU2writeDMA7Mem"); + LoadSPU2sym1(interruptDMA7,"SPU2interruptDMA7"); + LoadSPU2sym1(DMA4irqCallback, "SPU2DMA4irqCallback"); + LoadSPU2sym1(DMA7irqCallback, "SPU2DMA7irqCallback"); + LoadSPU2sym1(irqCallback, "SPU2irqCallback"); + + LoadSPU2sym0(freeze, "SPU2freeze"); + LoadSPU2sym0(configure, "SPU2configure"); + LoadSPU2sym0(about, "SPU2about"); + LoadSPU2sym0(test, "SPU2test"); + LoadSPU2symN(async, "SPU2async"); + + return 0; +} + +void *CDVDplugin; + +void CALLBACK CDVD_configure() {} +void CALLBACK CDVD_about() {} +long CALLBACK CDVD_test() { return 0; } + +#define LoadCDVDsym1(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 1); + +#define LoadCDVDsym0(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + if (CDVD##dest == NULL) CDVD##dest = (_CDVD##dest) CDVD_##dest; + +#define LoadCDVDsymN(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + +int LoadCDVDplugin(char *filename) { + void *drv; + + CDVDplugin = SysLoadLibrary(filename); + if (CDVDplugin == NULL) { SysMessage (_("Could Not Load CDVD Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = CDVDplugin; + TestPS2Esyms(CDVD); + LoadCDVDsym1(init, "CDVDinit"); + LoadCDVDsym1(shutdown, "CDVDshutdown"); + LoadCDVDsym1(open, "CDVDopen"); + LoadCDVDsym1(close, "CDVDclose"); + LoadCDVDsym1(readTrack, "CDVDreadTrack"); + LoadCDVDsym1(getBuffer, "CDVDgetBuffer"); + LoadCDVDsym1(readSubQ, "CDVDreadSubQ"); + LoadCDVDsym1(getTN, "CDVDgetTN"); + LoadCDVDsym1(getTD, "CDVDgetTD"); + LoadCDVDsym1(getTOC, "CDVDgetTOC"); + LoadCDVDsym1(getDiskType, "CDVDgetDiskType"); + LoadCDVDsym1(getTrayStatus, "CDVDgetTrayStatus"); + LoadCDVDsym1(ctrlTrayOpen, "CDVDctrlTrayOpen"); + LoadCDVDsym1(ctrlTrayClose, "CDVDctrlTrayClose"); + + LoadCDVDsym0(configure, "CDVDconfigure"); + LoadCDVDsym0(about, "CDVDabout"); + LoadCDVDsym0(test, "CDVDtest"); + LoadCDVDsymN(newDiskCB, "CDVDnewDiskCB"); + + return 0; +} + +void *DEV9plugin; + +s32 CALLBACK DEV9_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK DEV9_configure() {} +void CALLBACK DEV9_about() {} +long CALLBACK DEV9_test() { return 0; } + +#define LoadDEV9sym1(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 1); + +#define LoadDEV9sym0(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 0); \ + if (DEV9##dest == NULL) DEV9##dest = (_DEV9##dest) DEV9_##dest; + +int LoadDEV9plugin(char *filename) { + void *drv; + + DEV9plugin = SysLoadLibrary(filename); + if (DEV9plugin == NULL) { SysMessage (_("Could Not Load DEV9 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = DEV9plugin; + TestPS2Esyms(DEV9); + LoadDEV9sym1(init, "DEV9init"); + LoadDEV9sym1(shutdown, "DEV9shutdown"); + LoadDEV9sym1(open, "DEV9open"); + LoadDEV9sym1(close, "DEV9close"); + LoadDEV9sym1(read8, "DEV9read8"); + LoadDEV9sym1(read16, "DEV9read16"); + LoadDEV9sym1(read32, "DEV9read32"); + LoadDEV9sym1(write8, "DEV9write8"); + LoadDEV9sym1(write16, "DEV9write16"); + LoadDEV9sym1(write32, "DEV9write32"); + LoadDEV9sym1(readDMA8Mem, "DEV9readDMA8Mem"); + LoadDEV9sym1(writeDMA8Mem, "DEV9writeDMA8Mem"); + LoadDEV9sym1(irqCallback, "DEV9irqCallback"); + LoadDEV9sym1(irqHandler, "DEV9irqHandler"); + + LoadDEV9sym0(freeze, "DEV9freeze"); + LoadDEV9sym0(configure, "DEV9configure"); + LoadDEV9sym0(about, "DEV9about"); + LoadDEV9sym0(test, "DEV9test"); + + return 0; +} + +void *USBplugin; + +s32 CALLBACK USB_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK USB_configure() {} +void CALLBACK USB_about() {} +long CALLBACK USB_test() { return 0; } + +#define LoadUSBsym1(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 1); + +#define LoadUSBsym0(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 0); \ + if (USB##dest == NULL) USB##dest = (_USB##dest) USB_##dest; + +int LoadUSBplugin(char *filename) { + void *drv; + + USBplugin = SysLoadLibrary(filename); + if (USBplugin == NULL) { SysMessage (_("Could Not Load USB Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = USBplugin; + TestPS2Esyms(USB); + LoadUSBsym1(init, "USBinit"); + LoadUSBsym1(shutdown, "USBshutdown"); + LoadUSBsym1(open, "USBopen"); + LoadUSBsym1(close, "USBclose"); + LoadUSBsym1(read8, "USBread8"); + LoadUSBsym1(read16, "USBread16"); + LoadUSBsym1(read32, "USBread32"); + LoadUSBsym1(write8, "USBwrite8"); + LoadUSBsym1(write16, "USBwrite16"); + LoadUSBsym1(write32, "USBwrite32"); + LoadUSBsym1(irqCallback, "USBirqCallback"); + LoadUSBsym1(irqHandler, "USBirqHandler"); + LoadUSBsym1(setRAM, "USBsetRAM"); + + LoadUSBsym0(freeze, "USBfreeze"); + LoadUSBsym0(configure, "USBconfigure"); + LoadUSBsym0(about, "USBabout"); + LoadUSBsym0(test, "USBtest"); + + return 0; +} +void *FWplugin; + +s32 CALLBACK FW_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK FW_configure() {} +void CALLBACK FW_about() {} +long CALLBACK FW_test() { return 0; } + +#define LoadFWsym1(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 1); + +#define LoadFWsym0(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 0); \ + if (FW##dest == NULL) FW##dest = (_FW##dest) FW_##dest; + +int LoadFWplugin(char *filename) { + void *drv; + + FWplugin = SysLoadLibrary(filename); + if (FWplugin == NULL) { SysMessage (_("Could Not Load FW Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = FWplugin; + TestPS2Esyms(FW); + LoadFWsym1(init, "FWinit"); + LoadFWsym1(shutdown, "FWshutdown"); + LoadFWsym1(open, "FWopen"); + LoadFWsym1(close, "FWclose"); + LoadFWsym1(read32, "FWread32"); + LoadFWsym1(write32, "FWwrite32"); + LoadFWsym1(irqCallback, "FWirqCallback"); + + LoadFWsym0(freeze, "FWfreeze"); + LoadFWsym0(configure, "FWconfigure"); + LoadFWsym0(about, "FWabout"); + LoadFWsym0(test, "FWtest"); + + return 0; +} +static int loadp=0; + +int InitPlugins() { + int ret; + + if( GSsetBaseMem ) GSsetBaseMem(PS2MEM_GS); + + ret = GSinit(); + if (ret != 0) { SysMessage (_("GSinit error: %d"), ret); return -1; } + ret = PAD1init(1); + if (ret != 0) { SysMessage (_("PAD1init error: %d"), ret); return -1; } + ret = PAD2init(2); + if (ret != 0) { SysMessage (_("PAD2init error: %d"), ret); return -1; } + ret = SPU2init(); + if (ret != 0) { SysMessage (_("SPU2init error: %d"), ret); return -1; } + ret = CDVDinit(); + if (ret != 0) { SysMessage (_("CDVDinit error: %d"), ret); return -1; } + ret = DEV9init(); + if (ret != 0) { SysMessage (_("DEV9init error: %d"), ret); return -1; } + ret = USBinit(); + if (ret != 0) { SysMessage (_("USBinit error: %d"), ret); return -1; } + ret = FWinit(); + if (ret != 0) { SysMessage (_("FWinit error: %d"), ret); return -1; } + return 0; +} + +void ShutdownPlugins() { + GSshutdown(); + PAD1shutdown(); + PAD2shutdown(); + SPU2shutdown(); + CDVDshutdown(); + DEV9shutdown(); + USBshutdown(); + FWshutdown(); +} + +int LoadPlugins() { + char Plugin[256]; + + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.GS); + if (LoadGSplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD1); + if (LoadPAD1plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD2); + if (LoadPAD2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.SPU2); + if (LoadSPU2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.CDVD); + if (LoadCDVDplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.DEV9); + if (LoadDEV9plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.USB); + if (LoadUSBplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.FW); + if (LoadFWplugin(Plugin) == -1) return -1; + if (InitPlugins() == -1) return -1; + + loadp=1; + + return 0; +} + +long pDsp; +static pluginsopened = 0; +extern void spu2DMA4Irq(); +extern void spu2DMA7Irq(); +extern void spu2Irq(); +extern HANDLE g_hGSOpen, g_hGSDone; +int OpenPlugins() { + GSdriverInfo info; + int ret; + + if (loadp == 0) return -1; + + //first we need the data + if (CDVDnewDiskCB) CDVDnewDiskCB(cdvdNewDiskCB); + ret = CDVDopen(); + if (ret != 0) { SysMessage (_("Error Opening CDVD Plugin")); return -1; } + cdvdNewDiskCB(); + + //video + GSirqCallback(gsIrq); + + // make sure only call open once per instance + if( !pluginsopened ) { + if( CHECK_MULTIGS ) { + SetEvent(g_hGSOpen); + WaitForSingleObject(g_hGSDone, INFINITE); + } + else { + ret = GSopen((void *)&pDsp, "PCSX2", 0); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); return -1; } + } + } + + //then the user input + if (GSgetDriverInfo) { + GSgetDriverInfo(&info); + if (PAD1gsDriverInfo) PAD1gsDriverInfo(&info); + if (PAD2gsDriverInfo) PAD2gsDriverInfo(&info); + } + ret = PAD1open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD1 Plugin")); return -1; } + ret = PAD2open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD2 Plugin")); return -1; } + + //the sound + SysPrintf("SPU2open\n"); + + SPU2DMA4irqCallback(spu2DMA4Irq); + SPU2DMA7irqCallback(spu2DMA7Irq); + SPU2irqCallback(spu2Irq); + ret = SPU2open((void*)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening SPU2 Plugin")); return -1; } + + //and last the dev9 + DEV9irqCallback(dev9Irq); + dev9Handler = DEV9irqHandler(); + ret = DEV9open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening DEV9 Plugin")); return -1; } + + USBirqCallback(usbIrq); + usbHandler = USBirqHandler(); + USBsetRAM(psxM); + ret = USBopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening USB Plugin")); return -1; } + + FWirqCallback(fwIrq); + ret = FWopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening FW Plugin")); return -1; } + +#ifndef NOSTATS + statsOpen(); // for lack of a better place ;) +#endif + + pluginsopened = 1; + return 0; +} + +extern void gsWaitGS(); + +void ClosePlugins() { +#ifndef NOSTATS + statsClose(); // for lack of a better place ;) +#endif + + gsWaitGS(); + + CDVDclose(); + DEV9close(); + USBclose(); + FWclose(); + SPU2close(); + PAD1close(); + PAD2close(); +} + +void ResetPlugins() { + gsWaitGS(); + + ShutdownPlugins(); + InitPlugins(); +} + +void ReleasePlugins() { + if (loadp == 0) return; + + if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL || + SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL || + USBplugin == NULL || FWplugin == NULL) return; + + ShutdownPlugins(); + + SysCloseLibrary(GSplugin); GSplugin = NULL; + SysCloseLibrary(PAD1plugin); PAD1plugin = NULL; + SysCloseLibrary(PAD2plugin); PAD2plugin = NULL; + SysCloseLibrary(SPU2plugin); SPU2plugin = NULL; + SysCloseLibrary(CDVDplugin); CDVDplugin = NULL; + SysCloseLibrary(DEV9plugin); DEV9plugin = NULL; + SysCloseLibrary(USBplugin); USBplugin = NULL; + SysCloseLibrary(FWplugin); FWplugin = NULL; + loadp=0; +} diff --git a/branches/pcsx2_0.9.1/Plugins.h b/branches/pcsx2_0.9.1/Plugins.h new file mode 100644 index 0000000..0f282f2 --- /dev/null +++ b/branches/pcsx2_0.9.1/Plugins.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PLUGINS_H__ +#define __PLUGINS_H__ + +#define PLUGINtypedefs +#define PLUGINfuncs +#include "PS2Edefs.h" + +int LoadPlugins(); +void ReleasePlugins(); +int OpenPlugins(); +void ClosePlugins(); +void ResetPlugins(); + +#endif /* __PLUGINS_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxBios.c b/branches/pcsx2_0.9.1/PsxBios.c new file mode 100644 index 0000000..2e1495e --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxBios.c @@ -0,0 +1,300 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "PsxCommon.h" + +char *biosA0n[256] = { +// 0x00 + "open", "lseek", "read", "write", + "close", "ioctl", "exit", "sys_a0_07", + "getc", "putc", "todigit", "atof", + "strtoul", "strtol", "abs", "labs", +// 0x10 + "atoi", "atol", "atob", "setjmp", + "longjmp", "strcat", "strncat", "strcmp", + "strncmp", "strcpy", "strncpy", "strlen", + "index", "rindex", "strchr", "strrchr", +// 0x20 + "strpbrk", "strspn", "strcspn", "strtok", + "strstr", "toupper", "tolower", "bcopy", + "bzero", "bcmp", "memcpy", "memset", + "memmove", "memcmp", "memchr", "rand", +// 0x30 + "srand", "qsort", "strtod", "malloc", + "free", "lsearch", "bsearch", "calloc", + "realloc", "InitHeap", "_exit", "getchar", + "putchar", "gets", "puts", "printf", +// 0x40 + "sys_a0_40", "LoadTest", "Load", "Exec", + "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram", + "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets", + "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f", +// 0x50 + "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53", + "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57", + "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init", + "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open", +// 0x60 + "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile", + "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write", + "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase", + "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f", +// 0x70 + "_bu_init", "_96_init", "_96_remove", "sys_a0_73", + "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77", + "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b", + "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f", +// 0x80 + "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83", + "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87", + "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b", + "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f", +// 0x90 + "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93", + "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide", + "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b", + "SetConf", "GetConf", "sys_a0_9e", "SetMem", +// 0xa0 + "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr", + "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0", + "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info", + "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af", +// 0xb0 + "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3", + "?? sub_function", +}; + +char *biosB0n[256] = { +// 0x00 + "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03", + "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent", + "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent", + "EnableEvent", "DisableEvent", "OpenTh", "CloseTh", +// 0x10 + "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD", + "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption", + "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b", + "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f", +// 0x20 + "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23", + "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27", + "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b", + "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f", +// 0x30 + "sys_b0_30", "sys_b0_31", "open", "lseek", + "read", "write", "close", "ioctl", + "exit", "sys_b0_39", "getc", "putc", + "getchar", "putchar", "gets", "puts", +// 0x40 + "cd", "format", "firstfile", "nextfile", + "rename", "delete", "undelete", "AddDevice", + "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD", + "StopCARD", "sys_b0_4d", "_card_write", "_card_read", +// 0x50 + "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53", + "_get_errno", "_get_error", "GetC0Table", "GetB0Table", + "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD", + "_card_status", "_card_wait", +}; + +char *biosC0n[256] = { +// 0x00 + "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP", + "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler", + "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError", + "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f", +// 0x10 + "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut", + "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc", + "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect", + "PatchAOTable", +}; + +//#define r0 (psxRegs.GPR.n.r0) +#define at (psxRegs.GPR.n.at) +#define v0 (psxRegs.GPR.n.v0) +#define v1 (psxRegs.GPR.n.v1) +#define a0 (psxRegs.GPR.n.a0) +#define a1 (psxRegs.GPR.n.a1) +#define a2 (psxRegs.GPR.n.a2) +#define a3 (psxRegs.GPR.n.a3) +#define t0 (psxRegs.GPR.n.t0) +#define t1 (psxRegs.GPR.n.t1) +#define t2 (psxRegs.GPR.n.t2) +#define t3 (psxRegs.GPR.n.t3) +#define t4 (psxRegs.GPR.n.t4) +#define t5 (psxRegs.GPR.n.t5) +#define t6 (psxRegs.GPR.n.t6) +#define t7 (psxRegs.GPR.n.t7) +#define s0 (psxRegs.GPR.n.s0) +#define s1 (psxRegs.GPR.n.s1) +#define s2 (psxRegs.GPR.n.s2) +#define s3 (psxRegs.GPR.n.s3) +#define s4 (psxRegs.GPR.n.s4) +#define s5 (psxRegs.GPR.n.s5) +#define s6 (psxRegs.GPR.n.s6) +#define s7 (psxRegs.GPR.n.s7) +#define t8 (psxRegs.GPR.n.t6) +#define t9 (psxRegs.GPR.n.t7) +#define k0 (psxRegs.GPR.n.k0) +#define k1 (psxRegs.GPR.n.k1) +#define gp (psxRegs.GPR.n.gp) +#define sp (psxRegs.GPR.n.sp) +#define fp (psxRegs.GPR.n.s8) +#define ra (psxRegs.GPR.n.ra) +#define pc0 (psxRegs.pc) + +#define Ra0 ((char*)PSXM(a0)) +#define Ra1 ((char*)PSXM(a1)) +#define Ra2 ((char*)PSXM(a2)) +#define Ra3 ((char*)PSXM(a3)) +#define Rv0 ((char*)PSXM(v0)) +#define Rsp ((char*)PSXM(sp)) + +void bios_write() { // 0x35/0x03 + + + if (a0 == 1) { // stdout + char *ptr = Ra1; + + while (a2 > 0) { + SysPrintf(COLOR_RED "%c" COLOR_RESET, *ptr++); a2--; + } + pc0 = ra; return; + } +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("bios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2); +#endif + + v0 = -1; + + pc0 = ra; +} + +void bios_printf() { // 3f + char tmp[1024]; + char tmp2[1024]; + unsigned long save[4]; + char *ptmp = tmp; + int n=1, i=0, j; + + memcpy(save, (char*)PSXM(sp), 4*4); + psxMu32(sp) = a0; + psxMu32(sp + 4) = a1; + psxMu32(sp + 8) = a2; + psxMu32(sp + 12) = a3; + + while (Ra0[i]) { + switch (Ra0[i]) { + case '%': + j = 0; + tmp2[j++] = '%'; +_start: + switch (Ra0[++i]) { + case '.': + case 'l': + tmp2[j++] = Ra0[i]; goto _start; + default: + if (Ra0[i] >= '0' && Ra0[i] <= '9') { + tmp2[j++] = Ra0[i]; + goto _start; + } + break; + } + tmp2[j++] = Ra0[i]; + tmp2[j] = 0; + + switch (Ra0[i]) { + case 'f': case 'F': + ptmp+= sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break; + case 'a': case 'A': + case 'e': case 'E': + case 'g': case 'G': + ptmp+= sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break; + case 'p': + case 'i': + case 'd': case 'D': + case 'o': case 'O': + case 'x': case 'X': + ptmp+= sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break; + case 'c': + ptmp+= sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break; + case 's': + ptmp+= sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break; + case '%': + *ptmp++ = Ra0[i]; break; + } + i++; + break; + default: + *ptmp++ = Ra0[i++]; + } + } + *ptmp = 0; + + memcpy((char*)PSXM(sp), save, 4*4); + + SysPrintf(COLOR_RED "%s" COLOR_RESET, tmp); + + pc0 = ra; +} + +void bios_putchar () { // 3d + char tmp[12]; + + sprintf (tmp,"%c",(char)a0); + SysPrintf(tmp); + + pc0 = ra; +} + +void bios_puts () { // 3e/3f + SysPrintf(Ra0); + + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +void psxBiosInit() { + int i; + + for(i = 0; i < 256; i++) { + biosA0[i] = NULL; + biosB0[i] = NULL; + biosC0[i] = NULL; + } + biosA0[0x3e] = bios_puts; + biosA0[0x3f] = bios_printf; + + biosB0[0x3d] = bios_putchar; + biosB0[0x3f] = bios_puts; + +} + +void psxBiosShutdown() { +} + diff --git a/branches/pcsx2_0.9.1/PsxBios.h b/branches/pcsx2_0.9.1/PsxBios.h new file mode 100644 index 0000000..1ac0fe7 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxBios.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +extern char *biosA0n[256]; +extern char *biosB0n[256]; +extern char *biosC0n[256]; + +void psxBiosInit(); +void psxBiosShutdown(); +void psxBiosException(); +void psxBiosFreeze(int Mode); + +extern void (*biosA0[256])(); +extern void (*biosB0[256])(); +extern void (*biosC0[256])(); + +#endif /* __PSXBIOS_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxBios2.h b/branches/pcsx2_0.9.1/PsxBios2.h new file mode 100644 index 0000000..a0c6640 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxBios2.h @@ -0,0 +1,94 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/***** sysmem imageInfo +00000800: 00 16 00 00 70 14 00 00 01 01 00 00 01 00 00 00 +0000 next: .word ? //00001600 +0004 name: .word ? //00001470 +0008 version: .half ? //0101 +000A flags: .half ? //---- +000C index: .half ? //0001 +000E field_E: .half ? //---- +00000810: 90 08 00 00 A0 94 00 00 30 08 00 00 40 0C 00 00 +0010 entry: .word ? //00000890 +0014 gp_value: .word ? //000094A0 +0018 p1_vaddr: .word ? //00000830 +001C text_size: .word ? //00000C40 +00000820: 40 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 +0020 data_size: .word ? //00000040 +0024 bss_size: .word ? //00000010 +0028 field_28: .word ? //-------- +002C field_2C: .word ? //-------- +*****/ + +#ifndef __PSX_BIOS_H__ +#define __PSX_BIOS_H__ + +typedef struct { + u32 next, //+00 + name; //+04 + u16 version, //+08 + flags, //+0A + index, //+0C + _unkE; //+0E + u32 entry, //+10 + _gp, //+14 + vaddr, //+18 + text_size, //+1C + data_size, //+20 + bss_size, //+24 + _pad28, //+28 + _pad2C; //+2C +} irxImageInfo; //=30 + +typedef struct { + int active; + u32 server; + u32 fhandler; +} _sifServer; + +#define SIF_SERVERS 32 + +_sifServer sifServer[SIF_SERVERS]; + +// max modules/funcs + +#define IRX_MODULES 64 +#define IRX_FUNCS 256 + +typedef struct { + u32 num; + u32 entry; +} irxFunc; + +typedef struct { + int active; + u32 name[2]; + irxFunc funcs[IRX_FUNCS]; +} irxModule; + +irxModule irxMod[IRX_MODULES]; + + +void iopModulesInit(); +int iopSetImportFunc(u32 *ptr); +int iopSetExportFunc(u32 *ptr); +void sifServerCall(u32 server, u32 num, char *bin, int insize, char *bout, int outsize); +void sifAddServer(u32 server, u32 fhandler); + +#endif diff --git a/branches/pcsx2_0.9.1/PsxCommon.h b/branches/pcsx2_0.9.1/PsxCommon.h new file mode 100644 index 0000000..36b0e73 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxCommon.h @@ -0,0 +1,50 @@ +/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#include +#include "PS2Etypes.h" + +//#include "Common.h" +#include "System.h" +#include + +long LoadCdBios; +int cdOpenCase; + +#include "Plugins.h" +#include "R3000A.h" +#include "PsxMem.h" +#include "PsxHw.h" +#include "PsxBios.h" +#include "PsxDma.h" +#include "PsxCounters.h" +//#include "Mdec.h" +#include "CdRom.h" +#include "Sio.h" +//#include "Spu.h" +//#include "Decode_XA.h" +//#include "Misc.h" +#include "Debug.h" +//#include "Gte.h" +//#include "PsxGPU.h" +#include "PsxSio2.h" +#include "CDVD.h" + +#endif /* __PSXCOMMON_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxCounters.c b/branches/pcsx2_0.9.1/PsxCounters.c new file mode 100644 index 0000000..f8d2d82 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxCounters.c @@ -0,0 +1,642 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "PsxCommon.h" + +psxCounter psxCounters[8]; +u32 psxNextCounter, psxNextsCounter; +static int cnts = 6; +u8 psxhblankgate = 0; + +static void psxRcntUpd16(u32 index) { + psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle; + + psxCounters[index].Cycle = (0xffff - (psxRcntRcount16(index)&0xffff)) * psxCounters[index].rate; + psxCounters[index].CycleT = (psxCounters[index].target - psxRcntRcount16(index)) * psxCounters[index].rate; +} + +static void psxRcntUpd32(u32 index) { + psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle; + + psxCounters[index].Cycle = (0xffffffff - ((u32)psxRcntRcount32(index)&0xffffffff)) * psxCounters[index].rate; + psxCounters[index].CycleT = (psxCounters[index].target - (u32)psxRcntRcount32(index)) * psxCounters[index].rate; +} + +static void psxRcntReset16(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd16(index); +} + +static void psxRcntReset32(u32 index) { + psxCounters[index].count = 0; + //psxCounters[index].otarget = 0x10000; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd32(index); +} + +static void psxRcntSet() { + u32 c; + int i; + + /*if (Config.SafeCnts) { + psxNextCounter = 0; + psxNextsCounter = 0; + return; + }*/ + + psxNextCounter = 0xffffffff; + psxNextsCounter = psxRegs.cycle; + + for (i=0; i<3; i++) { + c = (u32)(0xffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + if(psxCounters[i].mode & 0x08000000) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + for (i=3; i<7; i++) { + c = (u32)(0xffffffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + if(psxCounters[i].mode & 0x08000000) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + +// SysPrintf("psxRcntSet: %x (cycle)\n", psxNextCounter, psxRegs.cycle); +} + + +void psxRcntInit() { + int i; + + memset(psxCounters, 0, sizeof(psxCounters)); + + for (i=0; i<3; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0xffff; + } + for (i=3; i<6; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0xffffffff; + } + + psxCounters[0].interrupt = 0x10; + psxCounters[1].interrupt = 0x20; + psxCounters[2].interrupt = 0x40; + + psxCounters[3].interrupt = 0x04000; + psxCounters[4].interrupt = 0x08000; + psxCounters[5].interrupt = 0x10000; + + if (SPU2async != NULL) { + cnts = 7; + + psxCounters[6].rate = 1; + psxCounters[6].target = 768*64; + psxCounters[6].mode = 0x8; + } else cnts = 6; + + for (i=0; i<3; i++) + psxRcntUpd16(i); + for (i=3; i<6; i++) + psxRcntUpd32(i); + for (i=6; i> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + //Do nothing + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntUpd16(i); //Gate Starts counting from here + break; + case 0x3: //GATE_ON_Start + //Do Nothing, already started and counting + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + //Do nothing + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntUpd32(i); //Gate Starts counting from here + break; + case 0x3: //GATE_ON_Start + //Do Nothing, already started and counting + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} +void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts + int i = counter; + + if(counter < 3){ //Gates for 16bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + if(counter == 0) psxhblankgate |= 1; + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd16(i); + break; + case 0x1: //GATE_ON_ClearStart + psxRcntReset16(i); + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset16(i); + break; + case 0x3: //GATE_ON_Start + if(psxCounters[i].mode & 0x10000000)psxCounters[i].count += (u16)psxRcntRcount16(i); //Save the count if not first cycle + psxRcntUpd16(i); + psxCounters[i].mode |= 0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + break; + case 0x1: //GATE_ON_ClearStart + psxRcntReset32(i); + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + break; + case 0x3: //GATE_ON_Start + if(psxCounters[i].mode & 0x10000000)psxCounters[i].count += (u32)psxRcntRcount32(i); //Save the count if not first cycle + psxRcntUpd32(i); + psxCounters[i].mode |= 0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} + +void _testRcnt16target(int i) { + psxCounters[i].mode|= 0x0800; // Target flag +if (!(psxCounters[i].mode & 0x08000000) && psxCounters[i].mode & 0x10) { // Target interrupt + +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount16(i), psxCounters[i].target); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + } + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd16(i);//psxRcntReset16(i); + //psxCounters[i].mode|= 0x0C00; // Interrupt flag + } + if(!(psxCounters[i].mode & 0x40)) psxCounters[i].mode|= 0x08000000; + else { + psxRcntWtarget16(i, psxRcntRcount16(i) + psxCounters[i].target); //Repeat Interrupt + } +} + +void _testRcnt16overflow(int i) { + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + + psxCounters[i].count = 0; + psxRcntUpd16(i);//psxRcntReset16(i); + //psxCounters[i].mode|= 0x1400; // Overflow flag +} + +void _testRcnt32target(int i) { + psxCounters[i].mode|= 0x0800; // Target flag + if (!(psxCounters[i].mode & 0x08000000) && psxCounters[i].mode & 0x10) { // Target interrupt +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount32(i), psxCounters[i].target); +#endif*/ + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + } + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd32(i); + //psxCounters[i].mode|= 0x0C00; // Interrupt flag + } + if(!(psxCounters[i].mode & 0x40))psxCounters[i].mode|= 0x08000000; + else { + psxRcntWtarget32(i, psxRcntRcount32(i) + psxCounters[i].target); //Repeat Interrupt + } +} + +void _testRcnt32overflow(int i) { + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] overflow 0x%x >= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount32(i), psxCounters[i].count); +#endif + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80)psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxRcntUpd32(i);//psxRcntReset32(i); + //psxCounters[i].mode|= 0x1400; // Overflow flag +} + +void _testRcnt16(int i) { + //if(!(psxCounters[i].mode & 0x08000000)) { + if (psxRcntCycles(i) >= psxCounters[i].target) + _testRcnt16target(i); + //} + + if (psxRcntCycles(i) >= 0xffff) { + _testRcnt16overflow(i); + psxCounters[i].count = 0; + psxRcntUpd16(i); + } + + /* mode & 0x08000000 means target interrupt already happened, + if so don't retest the target */ + //return; + + +} + +void _testRcnt32(int i) { + + //if (!(psxCounters[i].mode & 0x08000000)) { + + if (psxRcntCycles(i) >= psxCounters[i].target) + _testRcnt32target(i); + + //} + + if (psxRcntCycles(i) >= 0xffffffff) { + _testRcnt32overflow(i); + psxCounters[i].count = 0; + psxRcntUpd32(i); + } + + + /* mode & 0x08000000 means target interrupt already happened, + if so don't retest the target */ + +} + +void psxRcntUpdate() { + _testRcnt16(0); + _testRcnt16(1); + _testRcnt16(2); + _testRcnt32(3); + _testRcnt32(4); + _testRcnt32(5); + + if (cnts >= 7) { + if (psxRcntCycles(6) >= psxCounters[6].target) { + SPU2async((u32)(psxRegs.cycle - psxCounters[6].sCycleT)); + psxRcntReset16(6); + } + } + + psxRcntSet(); +} + +void psxRcntWcount16(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif +#ifdef PCSX2_DEVBUILD + //SysPrintf("Write to 16bit count reg counter %x\n", index); +#endif + //psxCounters[index].mode &= ~0x08001C00; + psxCounters[index].count = 0; + psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWcount32(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif +#ifdef PCSX2_DEVBUILD + //SysPrintf("Write to 32bit count reg counter %x\n", index); +#endif + //psxCounters[index].mode &= ~0x08001C00; + psxCounters[index].count = 0; + psxRcntUpd32(index); + psxRcntSet(); +} + +void psxRcnt0Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 0 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[0].mode & 0x3ff)) { + return; + }*/ + psxCounters[0].mode = value; + psxCounters[0].mode|= 0x0400; + //psxCounters[0].count = psxRcntRcount16(0); + psxCounters[0].rate = 1; + + + if(value & 0x100) psxCounters[0].rate = PSXPIXEL; + // Need to set a rate and target + /*if(psxCounters[0].mode & 0x1){ + // psxCounters[0].mode &= ~0x18101C00; + psxRcntReset16(0); + } else {*/ + psxCounters[0].count = 0; + psxRcntUpd16(0); + psxRcntSet(); + //} +} + +void psxRcnt1Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[1] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 1 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[1].mode & 0x3ff)) { + return; + }*/ + psxCounters[1].mode = value; + psxCounters[1].mode|= 0x0400; + //psxCounters[1].count = psxRcntRcount16(1); + psxCounters[1].rate = 1; + + if(value & 0x100)psxCounters[1].rate = PSXHBLANK; + + /*if(psxCounters[1].mode & 0x1){ + //psxCounters[1].mode &= ~0x18101C00; + psxRcntReset16(1); + } else {*/ + psxCounters[1].count = 0; + psxRcntUpd16(1); + psxRcntSet(); + //} +} + +void psxRcnt2Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[2] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 2 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[2].mode & 0x3ff)) { + return; + }*/ + + psxCounters[2].mode = value; + psxCounters[2].mode|= 0x0400; + //psxCounters[2].count = psxRcntRcount16(2); + switch(value & 0x200){ + case 0x200: + psxCounters[2].rate = 8; + break; + case 0x000: + psxCounters[2].rate = 1; + break; + } + +if(psxCounters[2].mode & 0x1){ + SysPrintf("Gate set on IOP C2, disabling\n"); + psxCounters[2].mode|= 0x1000000; +} + // Need to set a rate and target + psxCounters[2].count = 0; + psxRcntUpd16(2); + psxRcntSet(); +} + +void psxRcnt3Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[3] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 3 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[3].mode & 0x3ff)) { + return; + }*/ + psxCounters[3].mode = value; + //psxCounters[3].count = psxRcntRcount32(3); + psxCounters[3].rate = 1; + psxCounters[3].mode|= 0x0400; + if(value & 0x100)psxCounters[3].rate = PSXHBLANK; + + /*if(psxCounters[3].mode & 0x1){ + //psxCounters[3].mode &= ~0x18101C00; + psxRcntReset32(3); + } else {*/ + psxCounters[3].count = 0; + psxRcntUpd32(3); + psxRcntSet(); + //} +} + +void psxRcnt4Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[4] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 4 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[4].mode & 0x3ff)) { + return; + }*/ + psxCounters[4].mode = value; + psxCounters[4].mode|= 0x0400; + //psxCounters[4].count = psxRcntRcount32(4); + switch(value & 0x6000){ + case 0x0000: + psxCounters[4].rate = 1; + break; + case 0x2000: + psxCounters[4].rate = 8; + break; + case 0x4000: + psxCounters[4].rate = 16; + break; + case 0x6000: + psxCounters[4].rate = 256; + break; + } + // Need to set a rate and target +if(psxCounters[4].mode & 0x1){ + SysPrintf("Gate set on IOP C4, disabling\n"); + psxCounters[4].mode|= 0x1000000; +} + psxCounters[4].count = 0; + psxRcntUpd32(4); + psxRcntSet(); +} + +void psxRcnt5Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[5] = %lx\n", value); +#endif + if (value & 0x1c00) { + //SysPrintf("Counter 5 Value write %x\n", value & 0x1c00); + } + /*if ((value & 0x3ff) == (psxCounters[5].mode & 0x3ff)) { + return; + }*/ +#ifdef PCSX2_DEVBUILD + //SysPrintf("IOP writeCmode[5] = %lx\n", value); +#endif + psxCounters[5].mode = value; + psxCounters[5].mode|= 0x0400; + //psxCounters[5].count = psxRcntRcount32(5); + switch(value & 0x6000){ + case 0x0000: + psxCounters[5].rate = 1; + break; + case 0x2000: + psxCounters[5].rate = 8; + break; + case 0x4000: + psxCounters[5].rate = 16; + break; + case 0x6000: + psxCounters[5].rate = 256; + break; + } + // Need to set a rate and target +if(psxCounters[5].mode & 0x1){ + SysPrintf("Gate set on IOP C5, disabling\n"); + psxCounters[5].mode|= 0x1000000; +} + psxCounters[5].count = 0; + psxRcntUpd32(5); + psxRcntSet(); +} + +void psxRcntWtarget16(int index, u32 value) { +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget[%ld] = %lx\n", index, value); +#endif*/ + psxCounters[index].target = value; + //psxCounters[index].mode &= ~0x08000800; + //psxCounters[index].sCycleT = psxRegs.cycle; + psxCounters[index].CycleT = ((psxCounters[index].target - psxRcntRcount16(index)) * psxCounters[index].rate); +// psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWtarget32(int index, u32 value) { + psxCounters[index].target = value; + //psxCounters[index].mode &= ~0x08000800; + //psxCounters[index].sCycleT = psxRegs.cycle; + psxCounters[index].CycleT = ((psxCounters[index].target - (u32)psxRcntRcount32(index)) * psxCounters[index].rate); +/*#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x\n", + index, value, psxRcntRcount32(index), psxCounters[index].sCycleT, psxCounters[index].CycleT); +#endif*/ +// psxRcntUpd32(index); + psxRcntSet(); +} + +u16 psxRcntRcount16(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u16)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +u32 psxRcntRcount32(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u32)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +u64 psxRcntCycles(int index) { + if(psxCounters[index].mode & 0x1000000) return 0; + return (u64)(psxCounters[index].count + ((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); +} + +int psxRcntFreeze(gzFile f, int Mode) { + gzfreezel(psxCounters); + + return 0; +} diff --git a/branches/pcsx2_0.9.1/PsxCounters.h b/branches/pcsx2_0.9.1/PsxCounters.h new file mode 100644 index 0000000..9bbe67b --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxCounters.h @@ -0,0 +1,56 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOUNTERS_H__ +#define __PSXCOUNTERS_H__ + +typedef struct { + u32 count, mode, target; + u32 rate, interrupt, otarget; + u32 sCycle, Cycle; + u32 sCycleT, CycleT; +} psxCounter; + +psxCounter psxCounters[8]; + +u32 psxNextCounter, psxNextsCounter; + +void psxRcntInit(); +void psxRcntUpdate(); +void cntspu2async(); +void psxRcntWcount16(int index, u32 value); +void psxRcntWcount32(int index, u32 value); +void psxRcnt0Wmode(u32 value); +void psxRcnt1Wmode(u32 value); +void psxRcnt2Wmode(u32 value); +void psxRcnt3Wmode(u32 value); +void psxRcnt4Wmode(u32 value); +void psxRcnt5Wmode(u32 value); +void psxRcntWtarget16(int index, u32 value); +void psxRcntWtarget32(int index, u32 value); +u16 psxRcntRcount16(int index); +u32 psxRcntRcount32(int index); +u64 psxRcntCycles(int index); +int psxRcntFreeze(gzFile f, int Mode); + +void psxVSyncStart(); +void psxVSyncEnd(); +void psxCheckStartGate(int counter); +void psxCheckEndGate(int counter); + +#endif /* __PSXCOUNTERS_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxDma.c b/branches/pcsx2_0.9.1/PsxDma.c new file mode 100644 index 0000000..7931978 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxDma.c @@ -0,0 +1,254 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "PsxCommon.h" +// Dma0/1 in Mdec.c +// Dma3 in CdRom.c +// Dma8 in PsxSpd.c +// Dma11/12 in PsxSio2.c +//static int spudmaenable[2]; +void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + switch (chcr) { + case 0x01000201: //cpu to spu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2writeDMA4Mem((u16 *)PSXM(madr), size); + HW_DMA4_MADR += size; + break; + case 0x01000200: //spu to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2readDMA4Mem((u16 *)PSXM(madr), size); + psxCpu->Clear(HW_DMA4_MADR, size); + HW_DMA4_MADR += size; + break; + + default: + SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + //spudmaenable[0] = size; +} + +int psxDma4Interrupt() { + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + psxHu32(0x1070)|= 1<<9; + return 1; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU + HW_DMA2_CHCR &= ~0x01000000; + psxDmaInterrupt(2); +} + +void psxDma6(u32 madr, u32 bcr, u32 chcr) { + u32 *mem = (u32 *)PSXM(madr); + +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr == 0x11000002) { + while (bcr--) { + *mem-- = (madr - 4) & 0xffffff; + madr -= 4; + } + mem++; *mem = 0xffffff; + } else { + // Unknown option +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + } + HW_DMA6_CHCR &= ~0x01000000; + psxDmaInterrupt(6); +} + +void psxDma7(u32 madr, u32 bcr, u32 chcr) { + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 7 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 7 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 7 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + switch (chcr) { + case 0x01000201: //cpu to spu2 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2writeDMA7Mem((u16 *)PSXM(madr), size); + HW_DMA7_MADR += size; + break; + case 0x01000200: //spu2 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2readDMA7Mem((u16 *)PSXM(madr), size); + psxCpu->Clear(HW_DMA7_MADR, size); + HW_DMA7_MADR += size; + break; + default: + SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } +} + +int psxDma7Interrupt() { + + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + return 1; + +} + +void psxDma9(u32 madr, u32 bcr, u32 chcr) { + + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc000]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR); +#endif + + psHu32(0x1000F240) |= 0x2000; + if (dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void psxDma10(u32 madr, u32 bcr, u32 chcr) { + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc400]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx\n", chcr, madr, bcr); +#endif + + psHu32(0x1000F240) |= 0x4000; + if (dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void psxDma8(u32 madr, u32 bcr, u32 chcr) { + int size; + + switch (chcr & 0x01000201) { + case 0x01000201: //cpu to dev9 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9writeDMA8Mem((u32*)PSXM(madr), size*8); + break; + case 0x01000200: //dev9 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9readDMA8Mem((u32*)PSXM(madr), size*8); + break; +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + HW_DMA8_CHCR &= ~0x01000000; + psxDmaInterrupt2(1); +} + +int dev9Interrupt() { + if (dev9Handler == NULL) goto irq; + if (dev9Handler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<13; + return 1; +} + +void dev9Irq(int cycles) { + PSX_INT(20, (PSXCLK/cycles)); +} + +int usbInterrupt() { + if (usbHandler == NULL) goto irq; + if (usbHandler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<22; + return 1; +} + +void usbIrq(int cycles) { + PSX_INT(21, (PSXCLK/cycles)); +} + +void fwIrq() { + psxHu32(0x1070)|= 1<<24; +} + +void spu2DMA4Irq() { + //SysPrintf("IRQ DMA 4\n"); + SPU2interruptDMA4(); + //if(SPU2read(0x1f90019a) & 0xff) PSX_INT(4, (spudmaenable[0] * PSXSOUNDCLK) / BIAS); + HW_DMA4_BCR = 0; + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + //psxHu32(0x1070)|= 1<<9; + +} + +void spu2DMA7Irq() { + //SysPrintf("IRQ DMA 7\n"); + SPU2interruptDMA7(); + //if(SPU2read(0x1f90059a) & 0xff) PSX_INT(7, (spudmaenable[1] * PSXSOUNDCLK) / BIAS); + + HW_DMA7_BCR = 0; + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + //psxHu32(0x1070)|= 1<<9; +} + +void spu2Irq() { + psxHu32(0x1070)|= 1<<9; +} diff --git a/branches/pcsx2_0.9.1/PsxDma.h b/branches/pcsx2_0.9.1/PsxDma.h new file mode 100644 index 0000000..9db6f17 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxDma.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXDMA_H__ +#define __PSXDMA_H__ + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void psxDma3(u32 madr, u32 bcr, u32 chcr); +void psxDma4(u32 madr, u32 bcr, u32 chcr); +void psxDma6(u32 madr, u32 bcr, u32 chcr); +void psxDma7(u32 madr, u32 bcr, u32 chcr); +void psxDma8(u32 madr, u32 bcr, u32 chcr); +void psxDma9(u32 madr, u32 bcr, u32 chcr); +void psxDma10(u32 madr, u32 bcr, u32 chcr); + +int psxDma4Interrupt(); +int psxDma7Interrupt(); +int dev9Interrupt(); +DEV9handler dev9Handler; +void dev9Irq(int cycles); +int usbInterrupt(); +USBhandler usbHandler; +void usbIrq(int cycles); +void fwIrq(); +void spu2Irq(); + +#endif /* __PSXDMA_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxGPU.c b/branches/pcsx2_0.9.1/PsxGPU.c new file mode 100644 index 0000000..7bbf1d0 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxGPU.c @@ -0,0 +1,1067 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + + +u32 gpuStatus = 0x14802000; +int gpuMode = 0; +u8 gpuCmd; +int gpuDataC = 0; +int gpuDataP; +u32 gpuDataRet; +u32 gpuData[256]; +u32 gpuInfo[8] = {0, 0, 0, 0, 0, 0, 0, 2}; +int imageTransfer; +s16 imTX, imTXc, imTY, imTYc; +s16 imageX0, imageX1; +s16 imageY0, imageY1; + +// Draw Primitives + +void primPolyF3(unsigned char * baseAddr) { +/* PolyF3 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, prim.x2, prim.y2, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyFT3(unsigned char * baseAddr) { +/* PolyFT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c = MAKERGB24(prim.r, prim.g, prim.b); + c = ((prim.r*2 + prim.g*2 + prim.b*2) / 3); if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MIN(prim.u1, prim.u2)), + MAX(prim.v0, MIN(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog ("PolyFT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyF4(unsigned char *baseAddr) { +/* PolyF4 prim; + unsigned int c; + int point[8]; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + point[0] = prim.x0; point[1] = prim.y0; + point[2] = prim.x1; point[3] = prim.y1; + point[4] = prim.x3; point[5] = prim.y3; + point[6] = prim.x2; point[7] = prim.y2; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + polygon(drawvram, 4, point, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyFT4(unsigned char * baseAddr) { +/* PolyFT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c, id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c = MAKERGB24(prim.r,prim.g,prim.b); + c = (prim.r*2 + prim.g*2 + prim.b*2) / 3; if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyFT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d) c=%x", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0,c);*/ +} + +void primPolyG3(unsigned char *baseAddr) { +/* PolyG3 prim; + V3D_f v[3]; + unsigned int c0,c1,c2; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[2]); + + pslog("polyG3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyGT3(unsigned char *baseAddr) { +/* PolyGT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c0,c1,c2,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); +// c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); +// c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MAX(prim.u1, prim.u2)), + MAX(prim.v0, MAX(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog("polyGT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyG4(unsigned char * baseAddr) { +/* PolyG4 prim; + V3D_f v[4]; + unsigned int c0,c1,c2,c3; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); + c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); + c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); + c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; v[3].c = c3; + + if (prim.code & 2) return; + quad3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyG4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyGT4(unsigned char *baseAddr) { +/* PolyGT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c0,c1,c2,c3,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); +// c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); +// c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); +// c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + c3 = (prim.r3*2 + prim.g3*2 + prim.b3*2) / 3; if (c3 > 0xff) c3 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c3; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyGT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primLineF2(unsigned char *baseAddr) { +/* LineF2 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineF2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + line(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF2 : %d,%d - %d,%d : color = %x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c);*/ +} + +void primLineF(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + + c = MAKERGB15(baseAddr[0], baseAddr[1], baseAddr[2]); + + if (baseAddr[3] & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + } + + if (baseAddr[3] & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF vert = %d : color = %x\n", + i,c);*/ +} + +void primLineG2(unsigned char *baseAddr) { +/* LineG2 prim; + V3D_f v[2]; + unsigned int c0,c1; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineG2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[1]); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineG2 : %d,%d - %d,%d : color = %x,%x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c0,c1);*/ +} + +void primLineG(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0,lc=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + i/=2; + + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + lc = c; + } + + pslog ("LineG vert = %d\n", + i);*/ +} + +void primTileS(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, ((short*)baseAddr)[4], ((short*)baseAddr)[5]);*/ +} + +void primSprtS(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, ((short*)baseAddr)[6], ((short*)baseAddr)[7]);*/ +} + +void primTile1(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 1, 1);*/ +} + +void primTile8(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 8, 8);*/ +} + +void primSprt8(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite((SprtWH *)baseAddr, 8, 8);*/ +} + +void primTile16(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 16, 16);*/ +} + +void primSprt16(unsigned char * baseAddr) { +/* SprtWH prim; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, 16, 16);*/ +} + +// Command Primitives + +void primVoid(unsigned char * baseAddr) { +} + +void primClrCache(unsigned char * baseAddr) { +} + +void primBlkFill(unsigned char * baseAddr) { +/* Rect prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(Rect)); + + if ((prim.x > 1023) | (prim.y > 511)) return; + if (((prim.w + prim.x) > 1024) | ((prim.y + prim.h) > 512)) return; + if (prim.x < 0) prim.x = 0; + if (prim.y < 0) prim.y = 0; + if (prim.w > 1023) prim.w = 1023; + if (prim.h > 511) prim.h = 511; + + c = MAKERGB15(baseAddr[0],baseAddr[1],baseAddr[2]); + + pslog ("BlkFill %d,%d;%d,%d ,c=%x", + prim.x,prim.y,prim.w,prim.h,c); + + set_clip(drawvram, 0, 0, 1023, 511); + rectfill(drawvram, prim.x, prim.y, prim.w + prim.x - 1, prim.h + prim.y - 1, c); + SetClip();*/ +} + +void primMoveImage(unsigned char * baseAddr) { +/* short *gpuData = ((unsigned short *) baseAddr); + short imageSX,imageSY,imageDX,imageDY,imageW,imageH; + + imageSX = gpuData[2] & 0x3ff; + imageSY = gpuData[3] & 0x1ff; + + imageDX = gpuData[4] & 0x3ff; + imageDY = gpuData[5] & 0x1ff; + + imageW = gpuData[6] & 0xffff; + imageH = gpuData[7] & 0xffff; + + if((imageSY+imageH)>512) imageH=512-imageSY; + if((imageDY+imageH)>512) imageH=512-imageDY; + if((imageSX+imageW)>1024) imageW=1024-imageSX; + if((imageDX+imageW)>1024) imageW=1024-imageDX; + + pslog("MoveImage %d,%d %d,%d %d,%d\n", + imageSX, imageSY, imageDX, imageDY, imageW, imageH); + + UnsetClip(); + blit(vram, vram, imageSX, imageSY, imageDX, imageDY, imageW, imageH); + SetClip();*/ +} + +void primLoadImage(unsigned char * baseAddr) { + u32 gifTag[16]; + unsigned short *gpuData = ((unsigned short *) baseAddr); + + imageX0 = gpuData[2] & 0x3ff; + imageY0 = gpuData[3] & 0x1ff; + imageX1 = gpuData[4]; + imageY1 = gpuData[5]; + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imageTransfer = 2; + +#ifdef GPU_LOG + GPU_LOG ("LoadImage %d,%d %d,%d\n", imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1); +#endif + + gifTag[0] = 3; // nloop = 3 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 0; + gifTag[9] = (imageY0 << 16) | imageX0; + gifTag[10] = 0x51; // trxpos + + gifTag[12] = imageX1; + gifTag[13] = imageY1; + gifTag[14] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 4); +} + +void primStoreImage(unsigned char * baseAddr) { +/* unsigned long *gpuData = ((unsigned long *) baseAddr); + + imageX0 = (short)(gpuData[1] & 0x3ff); + imageY0 = (short)(gpuData[1]>>16) & 0x1ff; + imageX1 = (short)(gpuData[2] & 0xffff); + imageY1 = (short)((gpuData[2]>>16) & 0xffff); + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imSize=imageY1*imageX1/2; + + imageTransfer = 3; + GpuStatus|=0x08000000; + + pslog ("StoreImage %d,%d %d,%d\n" + ,imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1);*/ +} + +// Enviroment Primitives + +void primTPage(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + TPage = (short)(gdata & 0x7ff); + textAddrX = (gdata&0xf)<<6; + textAddrY = (((gdata)<<4)&0x100)+(((gdata)>>2)&0x200); + textTP = (gdata & 0x180) >> 7; + textABR = (gdata >> 5) & 0x3; + textREST = (gdata&0x00ffffff)>>9; + + GpuStatus = (GpuStatus & ~0x7ff) | (TPage);*/ +} + +void primTWindow(unsigned char *baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + tWinW = gdata&0xf; + tWinH = (gdata>>4)&0xf; + tWinX = (gdata>>8)&0xf; + tWinY = (gdata>>12)&0xf; + + pslog("primTWindow %d,%d %d,%d\n", tWinX, tWinY, tWinW, tWinH);*/ +} + +void primAreaStart(unsigned char * baseAddr) { +/* unsigned int gdata = ((unsigned int *)baseAddr)[0]; + + clipX = gdata & 0x3ff; + clipY = (gdata>>10) & 0x1ff; + SetClip(); + pslog("primAreaStart %dx%d\n", clipX, clipY); + GpuInfo[3] = gdata & 0xffffff;*/ +} + +void primAreaEnd(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + clipW = (short)(gdata & 0x3ff); + clipH = (short)((gdata>>10) & 0x1ff); + SetClip(); + pslog("primAreaEnd %dx%d\n", clipW, clipH); + GpuInfo[4] = gdata & 0xffffff;*/ +} + +void primDrawOffset(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + offsX = (short)(gdata & 0x3ff); + offsY = (short)((gdata >> 11) & 0x1ff); + pslog("primDrawOffset %dx%d\n", offsX, offsY); + GpuInfo[5] = gdata & 0xffffff;*/ +} + +void primMask(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + md = gdata & 1; + me = gdata & 2; + GpuStatus = (GpuStatus & ~(3<<11)) | ((gdata&3)<<11);*/ +} + +// Drawing Helper Functions +/* +void drawSprite(SprtWH *prim, short w, short h) { + Cache *sprt; + unsigned int id; + + prim->x+=offsX; + prim->y+=offsY; + + id = (prim->clut << 16) | TPage; +// sprt = CacheGet(id, prim->u, prim->v, w + prim->u, h + prim->v); + sprt = CacheGet(id, 0, 0, 256, 256); + + if ((prim->r >= 0x80) & (prim->g >= 0x80) & (prim->b >= 0x80) & (!(prim->code & 2))) { + masked_blit(sprt->tex, drawvram, prim->u, prim->v, prim->x, prim->y, w, h); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,0x808080,prim->u,prim->v,(prim->code&2)!=0,id); + } + else { + V3D_f v[4]; + unsigned int c; + +// c = MAKERGB24(prim->r*2,prim->g*2,prim->b*2); + c = (prim->r*2 + prim->g*2 + prim->b*2) / 3; if (c > 0xff) c = 0xff; + + v[0].x = prim->x; v[0].y = prim->y; v[0].z = 0; + v[0].u = prim->u; v[0].v = prim->v; v[0].c = c; + v[1].x = prim->x; v[1].y = prim->y + h; v[1].z = 0; + v[1].u = prim->u; v[1].v = prim->v + h; v[1].c = c; + v[2].x = prim->x + w; v[2].y = prim->y; v[2].z = 0; + v[2].u = prim->u + w; v[2].v = prim->v; v[2].c = c; + v[3].x = prim->x + w; v[3].y = prim->y + h; v[3].z = 0; + v[3].u = prim->u + w; v[3].v = prim->v + h; v[3].c = c; + + if (prim->code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,c,prim->u,prim->v,(prim->code&2)!=0,id); + } + +} + +void drawRect(RectWH *prim, short w, short h) { + unsigned int c; + + prim->x+=offsX; + prim->y+=offsY; + + c = MAKERGB15(prim->r,prim->g,prim->b); + + if (prim->code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + rectfill(drawvram, prim->x, prim->y, w + prim->x - 1, h + prim->y - 1, c); + if (prim->code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("Rectangle %d,%d %dx%d (semi-transparency=%d) c=%x", + prim->x,prim->y,w,h,(prim->code & 2)!=0,c); +}*/ + +// + +void primNI(unsigned char *bA) { +// if (bA[3]) pslog("PRIM: *NI* %02x",bA[3]); +} + + +unsigned char primTableC[256] = { + 1,1,3,0,0,0,0,0, // 00 + 0,0,0,0,0,0,0,0, // 08 + 0,0,0,0,0,0,0,0, // 10 + 0,0,0,0,0,0,0,0, // 18 + 4,4,4,4,7,7,7,7, // 20 + 5,5,5,5,9,9,9,9, // 28 + 6,6,6,6,9,9,9,9, // 30 + 8,8,8,8,12,12,12,12, // 38 + 3,3,3,3,0,0,0,0, // 40 + 5,5,5,5,6,6,6,6, // 48 + 4,4,4,4,0,0,0,0, // 50 + 7,7,7,7,9,9,9,9, // 58 + 3,3,3,3,4,4,4,4, // 60 + 2,2,2,2,0,0,0,0, // 68 + 2,2,2,2,3,3,3,3, // 70 + 2,2,2,2,3,3,3,3, // 78 + 4,0,0,0,0,0,0,0, // 80 + 0,0,0,0,0,0,0,0, // 88 + 0,0,0,0,0,0,0,0, // 90 + 0,0,0,0,0,0,0,0, // 98 + 3,0,0,0,0,0,0,0, // a0 + 0,0,0,0,0,0,0,0, // a8 + 0,0,0,0,0,0,0,0, // b0 + 0,0,0,0,0,0,0,0, // b8 + 3,0,0,0,0,0,0,0, // c0 + 0,0,0,0,0,0,0,0, // c8 + 0,0,0,0,0,0,0,0, // d0 + 0,0,0,0,0,0,0,0, // d8 + 0,1,1,1,1,1,1,0, // e0 + 0,0,0,0,0,0,0,0, // e8 + 0,0,0,0,0,0,0,0, // f0 + 0,0,0,0,0,0,0,0 // f8 +}; + +void (*primTableJ[256])(unsigned char *) = { + // 00 + primVoid,primClrCache,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineF,primLineF,primLineF,primLineF,primNI,primNI,primNI,primNI, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineG,primLineG,primLineG,primLineG,primNI,primNI,primNI,primNI, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,primTPage,primTWindow,primAreaStart,primAreaEnd,primDrawOffset,primMask,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +u32 cd[4]; +int cdC = 0; + +__inline void writePixel(short x, short y, u16 p) { + u32 gifTag[16]; + + cd[cdC] = ((p & 0x7c00) << 9) | + ((p & 0x03e0) << 6) | + ((p & 0x001f) << 3); + cdC++; + if (cdC < 4) return; + cdC = 0; + + gifTag[0] = 1; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); + GSgifTransfer3(cd, 1); +} + +void GPU_writeData(u32 data) { + gpuDataRet = data; + + if (imageTransfer == 2) { + // image transfer to VRAM + if (imTYc>0 && imTXc>0) { + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)data); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)(data>>16)); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + return; + } + else imageTransfer = 0; + } + +#ifdef GPU_LOG + GPU_LOG("!GPU! DATA = %08x\n", data); +#endif + + if (gpuDataC == 0) { + gpuCmd = (u8)(data >> 24); + gpuDataC = primTableC[gpuCmd]; + if (gpuDataC) { + gpuData[0] = data; + gpuDataP = 1; + } else { +#ifdef GPU_LOG + GPU_LOG("GPU ERROR CMD: %x, data=%x\n", gpuCmd, data); +#endif + return; + } + } else { + if (gpuDataP >= 256) return; + gpuData[gpuDataP++] = data; + } + + if (gpuDataP == gpuDataC) { + gpuDataP = gpuDataC = 0; +#ifdef GPU_LOG + GPU_LOG("Gpu(writeData) Command %x\n", gpuCmd); +#endif + primTableJ[gpuCmd]((u8*)gpuData); + } +} + +void GPU_writeStatus(u32 data) { +// u32 gifTag[16]; + + switch (data >> 24) { + case 0x00: +/* gifTag[0] = 2; // nloop = 2 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 320; + gifTag[9] = 240; + gifTag[10] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 3);*/ + GSwrite64(0x12000070, (1024/64) << 9); + break; + + case 0x10: + switch (data&7) { + case 3: + case 4: + case 5: + case 7: + gpuDataRet = gpuInfo[data&7]; + break; + default: +#ifdef GPU_LOG + GPU_LOG("GPU INFO UNK: %x\n", data); +#endif + break; + } + break; + } +} + +u32 GPU_readData() { + return gpuDataRet; +} + +u32 GPU_readStatus() { + gpuStatus^= 0x80000000; + return gpuStatus; +} + +void GPU_writeDataMem(u32 *pMem, int iSize) { +/* u32 gifTag[16]; + int i; + u16 *ptr = (u16*)pMem;*/ + +#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + while (iSize) { + GPU_writeData(*pMem); + pMem++; iSize--; + } + +/*#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + if (iSize > 0x7fff) { + } else { + gifTag[0] = iSize & 0x7fff; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); +// GSgifTransfer3(pMem, iSize); + GSgifTransfer3(ptr1, iSize); + } + imageTransfer = 0;*/ +} + +void GPU_readDataMem(u32 *pMem, int iSize) { +} + +void GPU_dmaChain(u32 *baseAddrL, u32 addr) { + unsigned long dmaMem; + unsigned char * baseAddrB; + unsigned char count; + unsigned char cmd; + + baseAddrB = (unsigned char*) baseAddrL; + + for (;;) { + count = baseAddrB[addr+3]; + dmaMem = addr+4; + while (count) { + if (imageTransfer == 2) { + GPU_writeData(baseAddrL[dmaMem/4]); + dmaMem+=4; + count--; + continue; + } + cmd = baseAddrB[dmaMem+3]; + if (primTableC[cmd] == 0) { + dmaMem+=4; + count--; + } else { +#ifdef GPU_LOG + GPU_LOG("Gpu(DmaChain) Command %x : %x\n", cmd, baseAddrL[dmaMem/4]); +#endif + primTableJ[cmd]((u8*)baseAddrL + dmaMem); + dmaMem+=(primTableC[cmd]*4); + count-=primTableC[cmd]; + } + } + addr = baseAddrL[addr/4]&0xffffff; + if (addr <= 0 || addr == 0xffffff) break; + addr&=0x7fffff; + } +} diff --git a/branches/pcsx2_0.9.1/PsxGPU.h b/branches/pcsx2_0.9.1/PsxGPU.h new file mode 100644 index 0000000..0126298 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxGPU.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXGPU_H__ +#define __PSXGPU_H__ + +#include "PS2Etypes.h" + +void GPU_writeData(u32 data); +void GPU_writeStatus(u32 data); +u32 GPU_readData(); +u32 GPU_readStatus(); +void GPU_writeDataMem(u32 *pMem, int iSize); +void GPU_readDataMem(u32 *pMem, int iSize); +void GPU_dmaChain(u32 *baseAddrL, u32 addr); + +#endif /* __PSXGPU_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxHw.c b/branches/pcsx2_0.9.1/PsxHw.c new file mode 100644 index 0000000..46f1299 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxHw.c @@ -0,0 +1,2850 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +#include "ir5900.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// NOTE: Any modifications to read/write fns should also go into their const counterparts + +void psxHwReset() { +/* if (Config.Sio) psxHu32(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu32(0x1070) |= 0x200;*/ + + memset(psxH, 0, 0x10000); + +// mdecInit(); //intialize mdec decoder + cdrReset(); + cdvdReset(); + psxRcntInit(); + sioInit(); +// sio2Reset(); +} + +u8 psxHwRead8(u32 add) { + u8 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread8(add); + } + + switch (add) { + case 0x1f801040: hard = sioRead8();break; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + return DEV9read8(add); + + case 0x1f801800: hard = cdrRead0(); break; + case 0x1f801801: hard = cdrRead1(); break; + case 0x1f801802: hard = cdrRead2(); break; + case 0x1f801803: hard = cdrRead3(); break; + + case 0x1f803100: // PS/EE/IOP conf related + hard = 0x10; // Dram 2M + break; + + case 0x1F808264: + hard = sio2_fifoOut();//sio2 serial data feed/fifo_out +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read8 DATAOUT %08X\n", hard); +#endif + return hard; + + default: + hard = psxHu8(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD8_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R8toR(EAX, EAX); \ + else MOVZX32R8toR(EAX, EAX); \ +} \ + +static u32 s_16 = 0x10; + +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign) { + + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD8_CALL(USBread8); + // since calling from different dll, esp already changed + return 1; + } + + switch (add) { + case 0x1f801040: + CONSTREAD8_CALL(sioRead8); + return 1; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD8_CALL(DEV9read8); + return 1; + + case 0x1f801800: CONSTREAD8_CALL(cdrRead0); return 1; + case 0x1f801801: CONSTREAD8_CALL(cdrRead1); return 1; + case 0x1f801802: CONSTREAD8_CALL(cdrRead2); return 1; + case 0x1f801803: CONSTREAD8_CALL(cdrRead3); return 1; + + case 0x1f803100: // PS/EE/IOP conf related + if( IS_XMMREG(x86reg) ) SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&s_16); + else if( IS_MMXREG(x86reg) ) MOVDMtoMMX(x86reg&0xf, (u32)&s_16); + else MOV32ItoR(x86reg, 0x10); + return 0; + + case 0x1F808264: //sio2 serial data feed/fifo_out + CONSTREAD8_CALL(sio2_fifoOut); + return 1; + + default: + _eeReadConstMem8(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } +} + +u16 psxHwRead16(u32 add) { + u16 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread16(add); + } + + switch (add) { +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070)); + return psxHu16(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074)); + return psxHu16(0x1074); +#endif + + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801044: + hard = sio.StatReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801048: + hard = sio.ModeReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104a: + hard = sio.CtrlReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104e: + hard = sio.BaudReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + + //Serial port stuff not support now ;P + // case 0x1f801050: hard = serial_read16(); break; + // case 0x1f801054: hard = serial_status_read(); break; + // case 0x1f80105a: hard = serial_control_read(); break; + // case 0x1f80105e: hard = serial_baud_read(); break; + + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; + psxCounters[0].mode&= ~0x1800; + psxCounters[0].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; + psxCounters[1].mode&= ~0x1800; + psxCounters[1].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; + psxCounters[2].mode&= ~0x1800; + psxCounters[2].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read16: %x\n", hard); +#endif + return hard; + + case 0x1f80146e: // DEV9_R_REV + return DEV9read16(add); + + case 0x1f801480: + hard = (u16)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = psxCounters[3].mode; + psxCounters[3].mode&= ~0x1800; + psxCounters[3].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u16)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = psxCounters[4].mode; + psxCounters[4].mode&= ~0x1800; + psxCounters[4].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u16)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = psxCounters[5].mode; + psxCounters[5].mode&= ~0x1800; + psxCounters[5].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read16: %lx\n", hard); +#endif + return hard; + + case 0x1f801504: + hard = psxHu16(0x1504); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit read %lx\n", hard); +#endif + return hard; + case 0x1f801506: + hard = psxHu16(0x1506); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit read %lx\n", hard); +#endif + return hard; + //case 0x1f802030: hard = //int_2000???? + //case 0x1f802040: hard =//dip switches...?? + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + hard = SPU2read(add); + } else { + hard = psxHu16(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 16bit read at address %lx\n", add); +#endif + } + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +void psxConstReadCounterMode16(int x86reg, int index, int sign) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode - 2); + } + else { + if( sign ) MOVSX32M16toR(ECX, (u32)&psxCounters[index].mode); + else MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + + MOV32RtoR(x86reg, ECX); + } + + AND16ItoR(ECX, ~0x1800); + OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign) { + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD16_CALL(USBread16); + return 1; + } + + switch (add) { + + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + PUSH32R(EAX); + CALLFunc((u32)sioRead8); + POP32R(ECX); + AND32ItoR(ECX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoR(EAX, ECX); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f801044: + _eeReadConstMem16(x86reg, (u32)&sio.StatReg, sign); + return 0; + + case 0x1f801048: + _eeReadConstMem16(x86reg, (u32)&sio.ModeReg, sign); + return 0; + + case 0x1f80104a: + _eeReadConstMem16(x86reg, (u32)&sio.CtrlReg, sign); + return 0; + + case 0x1f80104e: + _eeReadConstMem16(x86reg, (u32)&sio.BaudReg, sign); + return 0; + + // counters[0] + case 0x1f801100: + PUSH32I(0); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode16(x86reg, 0, sign); + return 0; + + case 0x1f801108: + _eeReadConstMem16(x86reg, (u32)&psxCounters[0].target, sign); + return 0; + + // counters[1] + case 0x1f801110: + PUSH32I(1); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode16(x86reg, 1, sign); + return 0; + + case 0x1f801118: + _eeReadConstMem16(x86reg, (u32)&psxCounters[1].target, sign); + return 0; + + // counters[2] + case 0x1f801120: + PUSH32I(2); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode16(x86reg, 2, sign); + return 0; + + case 0x1f801128: + _eeReadConstMem16(x86reg, (u32)&psxCounters[2].target, sign); + return 0; + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD16_CALL(DEV9read16); + return 1; + + // counters[3] + case 0x1f801480: + PUSH32I(3); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode16(x86reg, 3, sign); + return 0; + + case 0x1f801488: + _eeReadConstMem16(x86reg, (u32)&psxCounters[3].target, sign); + return 0; + + // counters[4] + case 0x1f801490: + PUSH32I(4); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode16(x86reg, 4, sign); + return 0; + + case 0x1f801498: + _eeReadConstMem16(x86reg, (u32)&psxCounters[4].target, sign); + return 0; + + // counters[5] + case 0x1f8014a0: + PUSH32I(5); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode16(x86reg, 5, sign); + return 0; + + case 0x1f8014a8: + _eeReadConstMem16(x86reg, (u32)&psxCounters[5].target, sign); + return 0; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + + PUSH32I(add); + CONSTREAD16_CALL(SPU2read); + return 1; + } else { + _eeReadConstMem16(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } + } +} + +u32 psxHwRead32(u32 add) { + u32 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread32(add); + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + return FWread32(add); + } + + switch (add) { + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; + hard|= sioRead8() << 16; + hard|= sioRead8() << 24; +#ifdef PAD_LOG + PAD_LOG("sio read32 ;ret = %lx\n", hard); +#endif + return hard; + + // case 0x1f801050: hard = serial_read32(); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size read %lx\n", psxHu32(0x1060)); + return psxHu32(0x1060); +#endif +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070)); + return psxHu32(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074)); + return psxHu32(0x1074); +#endif + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + hard = psxHu32(0x1078); + psxHu32(0x1078) = 0; + return hard; + +/* case 0x1f801810: +// hard = GPU_readData(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit read %lx\n", hard); +#endif + return hard;*/ +/* case 0x1f801814: + hard = GPU_readStatus(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit read %lx\n", hard); +#endif + return hard; +*/ +/* case 0x1f801820: hard = mdecRead0(); break; + case 0x1f801824: hard = mdecRead1(); break; +*/ +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit read %lx\n", psxHu32(0x10a0)); + return HW_DMA2_MADR; + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit read %lx\n", psxHu32(0x10a4)); + return HW_DMA2_BCR; + case 0x1f8010a8: + PSXHW_LOG("DMA2 CHCR 32bit read %lx\n", psxHu32(0x10a8)); + return HW_DMA2_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit read %lx\n", psxHu32(0x10b0)); + return HW_DMA3_MADR; + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit read %lx\n", psxHu32(0x10b4)); + return HW_DMA3_BCR; + case 0x1f8010b8: + PSXHW_LOG("DMA3 CHCR 32bit read %lx\n", psxHu32(0x10b8)); + return HW_DMA3_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit read %lx\n", HW_DMA9_MADR); + return HW_DMA9_MADR; + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit read %lx\n", HW_DMA9_BCR); + return HW_DMA9_BCR; + case 0x1f801528: + PSXHW_LOG("DMA9 CHCR 32bit read %lx\n", HW_DMA9_CHCR); + return HW_DMA9_CHCR; + case 0x1f80152C: + PSXHW_LOG("DMA9 TADR 32bit read %lx\n", HW_DMA9_TADR); + return HW_DMA9_TADR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit read %lx\n", HW_DMA10_MADR); + return HW_DMA10_MADR; + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit read %lx\n", HW_DMA10_BCR); + return HW_DMA10_BCR; + case 0x1f801538: + PSXHW_LOG("DMA10 CHCR 32bit read %lx\n", HW_DMA10_CHCR); + return HW_DMA10_CHCR; +#endif + +// case 0x1f8010f0: PSXHW_LOG("DMA PCR 32bit read " << psxHu32(0x10f0)); +// return HW_DMA_PCR; // dma rest channel +#ifdef PSXHW_LOG + case 0x1f8010f4: + PSXHW_LOG("DMA ICR 32bit read %lx\n", HW_DMA_ICR); + return HW_DMA_ICR; +#endif +//SSBus registers + case 0x1f801000: + hard = psxHu32(0x1000); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801004: + hard = psxHu32(0x1004); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8 (T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801008: + hard = psxHu32(0x1008); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80100C: + hard = psxHu32(0x100C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801010: + hard = psxHu32(0x1010); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS GIF(SIF2) (T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801014: + hard = psxHu32(0x1014); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T1) spu_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801018: + hard = psxHu32(0x1018); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80101C: + hard = psxHu32(0x101C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801020: + hard = psxHu32(0x1020); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS Config 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801400: + hard = psxHu32(0x1400); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801404: + hard = psxHu32(0x1404); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801408: + hard = psxHu32(0x1408); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80140C: + hard = psxHu32(0x140C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801410: + hard = psxHu32(0x1410); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T2) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801414: + hard = psxHu32(0x1414); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801418: + hard = psxHu32(0x1418); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF1(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80141C: + hard = psxHu32(0x141C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T1) 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801420: + hard = psxHu32(0x1420); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2out(T1) 32bit read %lx\n", hard); +#endif + return hard; + + case 0x1f8010f0: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR 32bit read %lx\n", HW_DMA_PCR); +#endif + return HW_DMA_PCR; + + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit read %lx\n", HW_DMA4_CHCR); +#endif + return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) + + // time for rootcounters :) + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801104: + hard = (u16)psxCounters[0].mode; + psxCounters[0].mode&= ~0x1800; + psxCounters[0].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801114: + hard = (u16)psxCounters[1].mode; + psxCounters[1].mode&= ~0x1800; + psxCounters[1].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801124: + hard = (u16)psxCounters[2].mode; + psxCounters[2].mode&= ~0x1800; + psxCounters[2].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801480: + hard = (u32)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = (u16)psxCounters[3].mode; + psxCounters[3].mode&= ~0x1800; + psxCounters[3].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u32)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = (u16)psxCounters[4].mode; + psxCounters[4].mode&= ~0x1800; + psxCounters[4].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u32)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = (u16)psxCounters[5].mode; + psxCounters[5].mode&= ~0x1800; + psxCounters[5].mode|= 0x400; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801450: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("%08X ICFG 32bit read %x\n", psxRegs.pc, hard); +#endif + return hard; + + + case 0x1f801500: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 MADR 32bit read %lx\n", HW_DMA7_MADR); +#endif + return HW_DMA7_MADR; // DMA7 madr + case 0x1f801504: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR 32bit read %lx\n", HW_DMA7_BCR); +#endif + return HW_DMA7_BCR; // DMA7 bcr + + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit read %lx\n", HW_DMA7_CHCR); +#endif + return HW_DMA7_CHCR; // DMA7 chcr (SPU2) + + case 0x1f801570: + hard = psxHu32(0x1570); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit read %lx\n", hard); +#endif + return hard; +#ifdef PSXHW_LOG + case 0x1f801574: + PSXHW_LOG("DMA ICR2 32bit read %lx\n", HW_DMA_ICR2); + return HW_DMA_ICR2; +#endif + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + hard=sio2_getSend3((add-0x1F808200)/4); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read param[%d] (%lx)\n", (add-0x1F808200)/4, hard); +#endif + return hard; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + hard=sio2_getSend1((add-0x1F808240)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send1[%d] (%lx)\n", (add-0x1F808240)/8, hard); +#endif + return hard; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + hard=sio2_getSend2((add-0x1F808244)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send2[%d] (%lx)\n", (add-0x1F808244)/8, hard); +#endif + return hard; + + case 0x1F808268: + hard=sio2_getCtrl(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read CTRL (%lx)\n", hard); +#endif + return hard; + + case 0x1F80826C: + hard=sio2_getRecv1(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv1 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808270: + hard=sio2_getRecv2(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv2 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808274: + hard=sio2_getRecv3(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv3 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808278: + hard=sio2_get8278(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [8278] (%lx)\n", hard); +#endif + return hard; + + case 0x1F80827C: + hard=sio2_get827C(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [827C] (%lx)\n", hard); +#endif + return hard; + + case 0x1F808280: + hard=sio2_getIntr(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read INTR (%lx)\n", hard); +#endif + return hard; + + default: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; +} + +void psxConstReadCounterMode32(int x86reg, int index) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode); + } + else { + MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + MOV32RtoR(x86reg, ECX); + } + + AND16ItoR(ECX, ~0x1800); + OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +static u32 s_tempsio; +int psxHwConstRead32(u32 x86reg, u32 add) { + if (add >= 0x1f801600 && add < 0x1f801700) { + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBread32); + return 1; + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWread32); + return 1; + } + + switch (add) { + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&s_tempsio, EAX); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoM((u32)&s_tempsio, EAX); + + // 3rd + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 16); + OR32RtoM((u32)&s_tempsio, EAX); + + // 4th + CALLFunc((u32)sioRead8); + SHL32ItoR(EAX, 24); + OR32MtoR(EAX, (u32)&s_tempsio); + return 1; + + //case 0x1f801050: hard = serial_read32(); break;//serial port + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + _eeReadConstMem32(x86reg, (u32)&psxH[add&0xffff]); + MOV32ItoM((u32)&psxH[add&0xffff], 0); + return 0; + + // counters[0] + case 0x1f801100: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode32(x86reg, 0); + return 0; + + case 0x1f801108: + _eeReadConstMem32(x86reg, (u32)&psxCounters[0].target); + return 0; + + // counters[1] + case 0x1f801110: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode32(x86reg, 1); + return 0; + + case 0x1f801118: + _eeReadConstMem32(x86reg, (u32)&psxCounters[1].target); + return 0; + + // counters[2] + case 0x1f801120: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode32(x86reg, 2); + return 0; + + case 0x1f801128: + _eeReadConstMem32(x86reg, (u32)&psxCounters[2].target); + return 0; + + // counters[3] + case 0x1f801480: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode32(x86reg, 3); + return 0; + + case 0x1f801488: + _eeReadConstMem32(x86reg, (u32)&psxCounters[3].target); + return 0; + + // counters[4] + case 0x1f801490: + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode32(x86reg, 4); + return 0; + + case 0x1f801498: + _eeReadConstMem32(x86reg, (u32)&psxCounters[4].target); + return 0; + + // counters[5] + case 0x1f8014a0: + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode32(x86reg, 5); + return 0; + + case 0x1f8014a8: + _eeReadConstMem32(x86reg, (u32)&psxCounters[5].target); + return 0; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_getSend3); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_getSend1); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_getSend2); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808268: + iFlushCall(0); + CALLFunc((u32)sio2_getCtrl); + return 1; + + case 0x1F80826C: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv1); + return 1; + + case 0x1F808270: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv2); + return 1; + + case 0x1F808274: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv3); + return 1; + + case 0x1F808278: + iFlushCall(0); + CALLFunc((u32)sio2_get8278); + return 1; + + case 0x1F80827C: + iFlushCall(0); + CALLFunc((u32)sio2_get827C); + return 1; + + case 0x1F808280: + iFlushCall(0); + CALLFunc((u32)sio2_getIntr); + return 1; + + default: + _eeReadConstMem32(x86reg, (u32)&psxH[(add) & 0xffff]); + return 0; + } +} + +static int pbufi; +static s8 pbuf[1024]; + +#define DmaExec(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite8(u32 add, u8 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite8(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0xa) SysPrintf("8bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: sioWrite8(value); break; + // case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 8bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu8(0x1450) = value; + return; + + case 0x1f801800: cdrWrite0(value); break; + case 0x1f801801: cdrWrite1(value); break; + case 0x1f801802: cdrWrite2(value); break; + case 0x1f801803: cdrWrite3(value); break; + + case 0x1f80380c: + if (value == '\r') break; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); break; + } + pbuf[pbufi++] = value; + break; + + case 0x1F808260: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write8 DATAIN <- %08X\n", value); +#endif + sio2_fifoIn(value);return;//serial data feed/fifo + + default: + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +#define CONSTWRITE_CALL(name) { \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void Write8PrintBuffer(u8 value) +{ + if (value == '\r') return; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); return; + } + pbuf[pbufi++] = value; +} + +void psxHwConstWrite8(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite8); + return; + } + + switch (add) { + case 0x1f801040: + CONSTWRITE_CALL(sioWrite8); break; + //case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801800: CONSTWRITE_CALL(cdrWrite0); break; + case 0x1f801801: CONSTWRITE_CALL(cdrWrite1); break; + case 0x1f801802: CONSTWRITE_CALL(cdrWrite2); break; + case 0x1f801803: CONSTWRITE_CALL(cdrWrite3); break; + case 0x1f80380c: CONSTWRITE_CALL(Write8PrintBuffer); break; + case 0x1F808260: CONSTWRITE_CALL(sio2_fifoIn); break; + + default: + _eeWriteConstMem8((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +void psxHwWrite16(u32 add, u16 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite16(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)(value>>8)); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801044: +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801048: + sio.ModeReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104a: // control register + sioWriteCtrl16(value); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104e: // baudrate register + sio.BaudReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + + //serial port ;P + // case 0x1f801050: serial_write16(value); break; + // case 0x1f80105a: serial_control_write(value);break; + // case 0x1f80105e: serial_baud_write(value); break; + // case 0x1f801054: serial_status_write(value); break; + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 16bit write %x\n", value); +#endif +// if (Config.Sio) psxHu16(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; + psxHu16(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value); + psxHu16(0x1074) = value; + return; +#endif + + case 0x1f8010c4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); +#endif + psxHu16(0x10c4) = value; return; // DMA4 bcr_size + + case 0x1f8010c6: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); +#endif + psxHu16(0x10c6) = value; return; // DMA4 bcr_count + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(0, value); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(0, value); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(1, value); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(1, value); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(2, value); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 16bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu16(0x1450) = value/* & (~0x8)*/; + return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 16bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 16bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 16bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f801504: + psxHu16(0x1504) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit write %lx\n", value); +#endif + return; + case 0x1f801506: + psxHu16(0x1506) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit write %lx\n", value); +#endif + return; + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + SPU2write(add, value); + return; + } + + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 16bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHwConstWrite16(u32 add, int mmreg) { + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite16); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 3); + return; + case 0x1f801044: + return; + case 0x1f801048: + _eeWriteConstMem16((u32)&sio.ModeReg, mmreg); + return; + case 0x1f80104a: // control register + CONSTWRITE_CALL(sioWriteCtrl16); + return; + case 0x1f80104e: // baudrate register + _eeWriteConstMem16((u32)&sio.BaudReg, mmreg); + return; + + case 0x1f801070: + _eeWriteConstMem16OP((u32)&psxH[(add) & 0xffff], mmreg, 0); + return; + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)SPU2write); + // leave esp alone + return; + } + + _eeWriteConstMem16((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +#define DmaExec2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite32(u32 add, u32 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite32(add, value); return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + FWwrite32(add, value); return; + } + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)((value&0xff) >> 8)); + sioWrite8((u8)((value&0xff) >> 16)); + sioWrite8((u8)((value&0xff) >> 24)); +#ifdef PAD_LOG + PAD_LOG("sio write32 %lx\n", value); +#endif + return; + // case 0x1f801050: serial_write32(value); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size write %lx\n", value); + psxHu32(add) = value; + return; // Ram size +#endif + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 32bit write %lx\n", value); +#endif +// if (Config.Sio) psxHu32(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu32(0x1070) |= 0x200; + psxHu32(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: + PSXHW_LOG("IMASK 32bit write %lx\n", value); + psxHu32(0x1074) = value; + return; + + case 0x1f801078: + PSXHW_LOG("ICTRL 32bit write %lx\n", value); +// SysPrintf("ICTRL 32bit write %lx\n", value); + psxHu32(0x1078) = value; + return; +#endif + + //SSBus registers + case 0x1f801000: + psxHu32(0x1000) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801004: + psxHu32(0x1004) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8 (T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801008: + psxHu32(0x1008) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECin (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80100C: + psxHu32(0x100C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801010: + psxHu32(0x1010) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS GIF(SIF2) (T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801014: + psxHu32(0x1014) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T1) spu_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801018: + psxHu32(0x1018) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80101C: + psxHu32(0x101C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 8(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801020: + psxHu32(0x1020) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS Config 32bit write %lx\n", value); +#endif + return; + case 0x1f801400: + psxHu32(0x1400) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS MDECout(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801404: + psxHu32(0x1404) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SPU(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801408: + psxHu32(0x1408) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS PIO(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f80140C: + psxHu32(0x140C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801410: + psxHu32(0x1410) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T2) 32bit write %lx\n", value); +#endif + return; + case 0x1f801414: + psxHu32(0x1414) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF0(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801418: + psxHu32(0x1418) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIF1(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f80141C: + psxHu32(0x141C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2in(T1) 32bit write %lx\n", value); +#endif + return; + case 0x1f801420: + psxHu32(0x1420) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS SIO2out(T1) 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f801080: + PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); + HW_DMA0_MADR = value; return; // DMA0 madr + case 0x1f801084: + PSXHW_LOG("DMA0 BCR 32bit write %lx\n", value); + HW_DMA0_BCR = value; return; // DMA0 bcr +#endif + case 0x1f801088: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA0 CHCR 32bit write %lx\n", value); +#endif + HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +// DmaExec(0); + return; + +#ifdef PSXHW_LOG + case 0x1f801090: + PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); + HW_DMA1_MADR = value; return; // DMA1 madr + case 0x1f801094: + PSXHW_LOG("DMA1 BCR 32bit write %lx\n", value); + HW_DMA1_BCR = value; return; // DMA1 bcr +#endif + case 0x1f801098: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA1 CHCR 32bit write %lx\n", value); +#endif + HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +// DmaExec(1); + return; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); + HW_DMA2_MADR = value; return; // DMA2 madr + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit write %lx\n", value); + HW_DMA2_BCR = value; return; // DMA2 bcr +#endif + case 0x1f8010a8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA2 CHCR 32bit write %lx\n", value); +#endif + HW_DMA2_CHCR = value; // DMA2 chcr (GPU DMA) + DmaExec(2); + return; + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); + HW_DMA3_MADR = value; return; // DMA3 madr + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit write %lx\n", value); + HW_DMA3_BCR = value; return; // DMA3 bcr +#endif + case 0x1f8010b8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA3 CHCR 32bit write %lx\n", value); +#endif + HW_DMA3_CHCR = value; // DMA3 chcr (CDROM DMA) + DmaExec(3); + + return; + +#ifdef PSXHW_LOG + case 0x1f8010c0: + PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); + HW_DMA4_MADR = value; return; // DMA4 madr + case 0x1f8010c4: + PSXHW_LOG("DMA4 BCR 32bit write %lx\n", value); + HW_DMA4_BCR = value; return; // DMA4 bcr +#endif + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit write %lx\n", value); +#endif + HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) + DmaExec(4); + return; + +#if 0 + case 0x1f8010d0: break; //DMA5write_madr(); + case 0x1f8010d4: break; //DMA5write_bcr(); + case 0x1f8010d8: break; //DMA5write_chcr(); // Not yet needed?? +#endif + +#ifdef PSXHW_LOG + case 0x1f8010e0: + PSXHW_LOG("DMA6 MADR 32bit write %lx\n", value); + HW_DMA6_MADR = value; return; // DMA6 madr + case 0x1f8010e4: + PSXHW_LOG("DMA6 BCR 32bit write %lx\n", value); + HW_DMA6_BCR = value; return; // DMA6 bcr +#endif + case 0x1f8010e8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA6 CHCR 32bit write %lx\n", value); +#endif + HW_DMA6_CHCR = value; // DMA6 chcr (OT clear) + DmaExec(6); + return; + +#ifdef PSXHW_LOG + case 0x1f801500: + PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); + HW_DMA7_MADR = value; return; // DMA7 madr + case 0x1f801504: + PSXHW_LOG("DMA7 BCR 32bit write %lx\n", value); + HW_DMA7_BCR = value; return; // DMA7 bcr +#endif + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit write %lx\n", value); +#endif + HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) + DmaExec2(7); + return; + +#ifdef PSXHW_LOG + case 0x1f801510: + PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); + HW_DMA8_MADR = value; return; // DMA8 madr + case 0x1f801514: + PSXHW_LOG("DMA8 BCR 32bit write %lx\n", value); + HW_DMA8_BCR = value; return; // DMA8 bcr +#endif + case 0x1f801518: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA8 CHCR 32bit write %lx\n", value); +#endif + HW_DMA8_CHCR = value; // DMA8 chcr (DEV9) + DmaExec2(8); + return; + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); + HW_DMA9_MADR = value; return; // DMA9 madr + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit write %lx\n", value); + HW_DMA9_BCR = value; return; // DMA9 bcr +#endif + case 0x1f801528: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA9 CHCR 32bit write %lx\n", value); +#endif + HW_DMA9_CHCR = value; // DMA9 chcr (SIF0) + DmaExec2(9); + return; +#ifdef PSXHW_LOG + case 0x1f80152c: + PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value); + HW_DMA9_TADR = value; return; // DMA9 tadr +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); + HW_DMA10_MADR = value; return; // DMA10 madr + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit write %lx\n", value); + HW_DMA10_BCR = value; return; // DMA10 bcr +#endif + case 0x1f801538: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA10 CHCR 32bit write %lx\n", value); +#endif + HW_DMA10_CHCR = value; // DMA10 chcr (SIF1) + DmaExec2(10); + return; + +#ifdef PSXHW_LOG + case 0x1f801540: + PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); + HW_DMA11_MADR = value; return; + + case 0x1f801544: + PSXHW_LOG("DMA11 SIO2in BCR 32bit write %lx\n", value); + HW_DMA11_BCR = value; return; +#endif + case 0x1f801548: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA11 SIO2in CHCR 32bit write %lx\n", value); +#endif + HW_DMA11_CHCR = value; // DMA11 chcr (SIO2 in) + DmaExec2(11); + return; + +#ifdef PSXHW_LOG + case 0x1f801550: + PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); + HW_DMA12_MADR = value; return; + + case 0x1f801554: + PSXHW_LOG("DMA12 SIO2out BCR 32bit write %lx\n", value); + HW_DMA12_BCR = value; return; +#endif + case 0x1f801558: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA12 SIO2out CHCR 32bit write %lx\n", value); +#endif + HW_DMA12_CHCR = value; // DMA12 chcr (SIO2 out) + DmaExec2(12); + return; + + case 0x1f801570: + psxHu32(0x1570) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit write %lx\n", value); + HW_DMA_PCR = value; + return; +#endif + + case 0x1f8010f4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR; + HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + + case 0x1f801574: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR2; + HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + +/* case 0x1f801810: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit write %lx\n", value); +#endif + GPU_writeData(value); return; + case 0x1f801814: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit write %lx\n", value); +#endif + GPU_writeStatus(value); return; +*/ +/* case 0x1f801820: + mdecWrite0(value); break; + case 0x1f801824: + mdecWrite1(value); break; +*/ + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(0, value ); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 32bit write %lx\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(0, value ); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(1, value ); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 32bit write %lx\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(1, value ); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(2, value ); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 32bit write %lx\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 32bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 32bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 32bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f8014c0: +#ifdef PSXHW_LOG + PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); +#endif + SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value); + break; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 32bit write %lx\n", psxRegs.pc, value); } +#endif +/* if (value && + psxSu32(0x20) == 0x20000 && + (psxSu32(0x30) == 0x20000 || + psxSu32(0x30) == 0x40000)) { // don't ask me why :P + psxSu32(0x20) = 0x10000; + psxSu32(0x30) = 0x10000; + }*/ + psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; + return; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write param[%d] <- %lx\n", (add-0x1F808200)/4, value); +#endif + sio2_setSend3((add-0x1F808200)/4, value); return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send1[%d] <- %lx\n", (add-0x1F808240)/8, value); +#endif + sio2_setSend1((add-0x1F808240)/8, value); return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send2[%d] <- %lx\n", (add-0x1F808244)/8, value); +#endif + sio2_setSend2((add-0x1F808244)/8, value); return; + + case 0x1F808268: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write CTRL <- %lx\n", value); +#endif + sio2_setCtrl(value); return; + + case 0x1F808278: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [8278] <- %lx\n", value); +#endif + sio2_set8278(value); return; + + case 0x1F80827C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [827C] <- %lx\n", value); +#endif + sio2_set827C(value); return; + + case 0x1F808280: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write INTR <- %lx\n", value); +#endif + sio2_setIntr(value); return; + + default: + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); +#endif + return; + } + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit write at address %lx value %lx\n", add, value); +#endif +} + +#define recDmaExec(n) { \ + iFlushCall(0); \ + if( n > 6 ) \ + TEST32ItoM((u32)&HW_DMA_PCR2, 8 << ((n-7) * 4)); \ + else \ + TEST32ItoM((u32)&HW_DMA_PCR, 8 << (n * 4)); \ + j8Ptr[5] = JZ8(0); \ + MOV32MtoR(EAX, (u32)&HW_DMA##n##_CHCR); \ + TEST32ItoR(EAX, 0x01000000); \ + j8Ptr[6] = JZ8(0); \ + \ + PUSH32R(EAX); \ + PUSH32M((u32)&HW_DMA##n##_BCR); \ + PUSH32M((u32)&HW_DMA##n##_MADR); \ + CALLFunc((u32)psxDma##n); \ + ADD32ItoR(ESP, 12); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ +} \ + +#define CONSTWRITE_CALL32(name) { \ + iFlushCall(0); \ + _recPushReg(mmreg); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void psxHwConstWrite32(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite32); + return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWwrite32); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + return; + + case 0x1f801070: + _eeWriteConstMem32OP((u32)&psxH[(add) & 0xffff], mmreg, 0); // and + return; + +// case 0x1f801088: +// HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +//// DmaExec(0); +// return; + +// case 0x1f801098: +// HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +//// DmaExec(1); +// return; + + case 0x1f8010a8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(2); + return; + + case 0x1f8010b8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(3); + return; + + case 0x1f8010c8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(4); + return; + + case 0x1f8010e8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(6); + return; + + case 0x1f801508: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(7); + return; + + case 0x1f801518: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(8); + return; + + case 0x1f801528: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(9); + return; + + case 0x1f801538: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(10); + return; + + case 0x1f801548: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(11); + return; + + case 0x1f801558: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(12); + return; + + case 0x1f8010f4: + case 0x1f801574: + { + // u32 tmp = (~value) & HW_DMA_ICR; + _eeMoveMMREGtoR(EAX, mmreg); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND32MtoR(ECX, (u32)&psxH[(add) & 0xffff]); + + // HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + XOR32RtoR(EAX, ECX); + AND32ItoR(EAX, 0xffffff); + XOR32RtoR(EAX, ECX); + MOV32RtoM((u32)&psxH[(add) & 0xffff], EAX); + return; + } + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL32(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL32(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL32(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL32(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL32(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL32(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014c0: + SysPrintf("RTC_HOLDMODE 32bit write\n"); + break; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_setSend3); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_setSend1); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_setSend2); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808268: CONSTWRITE_CALL32(sio2_setCtrl); return; + case 0x1F808278: CONSTWRITE_CALL32(sio2_set8278); return; + case 0x1F80827C: CONSTWRITE_CALL32(sio2_set827C); return; + case 0x1F808280: CONSTWRITE_CALL32(sio2_setIntr); return; + + default: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +u8 psxHw4Read8(u32 add) { + u8 hard; + + switch (add) { + case 0x1f402004: return cdvdRead04(); + case 0x1f402005: return cdvdRead05(); + case 0x1f402006: return cdvdRead06(); + case 0x1f402007: return cdvdRead07(); + case 0x1f402008: return cdvdRead08(); + case 0x1f40200A: return cdvdRead0A(); + case 0x1f40200B: return cdvdRead0B(); + case 0x1f40200C: return cdvdRead0C(); + case 0x1f40200D: return cdvdRead0D(); + case 0x1f40200E: return cdvdRead0E(); + case 0x1f40200F: return cdvdRead0F(); + case 0x1f402013: return cdvdRead13(); + case 0x1f402015: return cdvdRead15(); + case 0x1f402016: return cdvdRead16(); + case 0x1f402017: return cdvdRead17(); + case 0x1f402018: return cdvdRead18(); + case 0x1f402020: return cdvdRead20(); + case 0x1f402021: return cdvdRead21(); + case 0x1f402022: return cdvdRead22(); + case 0x1f402023: return cdvdRead23(); + case 0x1f402024: return cdvdRead24(); + case 0x1f402028: return cdvdRead28(); + case 0x1f402029: return cdvdRead29(); + case 0x1f40202A: return cdvdRead2A(); + case 0x1f40202B: return cdvdRead2B(); + case 0x1f40202C: return cdvdRead2C(); + case 0x1f402030: return cdvdRead30(); + case 0x1f402031: return cdvdRead31(); + case 0x1f402032: return cdvdRead32(); + case 0x1f402033: return cdvdRead33(); + case 0x1f402034: return cdvdRead34(); + case 0x1f402038: return cdvdRead38(); + case 0x1f402039: return cdvdRead39(); + case 0x1f40203A: return cdvdRead3A(); + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + return 0; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + + return hard; +} + +int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) { + switch (add) { + case 0x1f402004: CONSTREAD8_CALL((u32)cdvdRead04); return 1; + case 0x1f402005: CONSTREAD8_CALL((u32)cdvdRead05); return 1; + case 0x1f402006: CONSTREAD8_CALL((u32)cdvdRead06); return 1; + case 0x1f402007: CONSTREAD8_CALL((u32)cdvdRead07); return 1; + case 0x1f402008: CONSTREAD8_CALL((u32)cdvdRead08); return 1; + case 0x1f40200A: CONSTREAD8_CALL((u32)cdvdRead0A); return 1; + case 0x1f40200B: CONSTREAD8_CALL((u32)cdvdRead0B); return 1; + case 0x1f40200C: CONSTREAD8_CALL((u32)cdvdRead0C); return 1; + case 0x1f40200D: CONSTREAD8_CALL((u32)cdvdRead0D); return 1; + case 0x1f40200E: CONSTREAD8_CALL((u32)cdvdRead0E); return 1; + case 0x1f40200F: CONSTREAD8_CALL((u32)cdvdRead0F); return 1; + case 0x1f402013: CONSTREAD8_CALL((u32)cdvdRead13); return 1; + case 0x1f402015: CONSTREAD8_CALL((u32)cdvdRead15); return 1; + case 0x1f402016: CONSTREAD8_CALL((u32)cdvdRead16); return 1; + case 0x1f402017: CONSTREAD8_CALL((u32)cdvdRead17); return 1; + case 0x1f402018: CONSTREAD8_CALL((u32)cdvdRead18); return 1; + case 0x1f402020: CONSTREAD8_CALL((u32)cdvdRead20); return 1; + case 0x1f402021: CONSTREAD8_CALL((u32)cdvdRead21); return 1; + case 0x1f402022: CONSTREAD8_CALL((u32)cdvdRead22); return 1; + case 0x1f402023: CONSTREAD8_CALL((u32)cdvdRead23); return 1; + case 0x1f402024: CONSTREAD8_CALL((u32)cdvdRead24); return 1; + case 0x1f402028: CONSTREAD8_CALL((u32)cdvdRead28); return 1; + case 0x1f402029: CONSTREAD8_CALL((u32)cdvdRead29); return 1; + case 0x1f40202A: CONSTREAD8_CALL((u32)cdvdRead2A); return 1; + case 0x1f40202B: CONSTREAD8_CALL((u32)cdvdRead2B); return 1; + case 0x1f40202C: CONSTREAD8_CALL((u32)cdvdRead2C); return 1; + case 0x1f402030: CONSTREAD8_CALL((u32)cdvdRead30); return 1; + case 0x1f402031: CONSTREAD8_CALL((u32)cdvdRead31); return 1; + case 0x1f402032: CONSTREAD8_CALL((u32)cdvdRead32); return 1; + case 0x1f402033: CONSTREAD8_CALL((u32)cdvdRead33); return 1; + case 0x1f402034: CONSTREAD8_CALL((u32)cdvdRead34); return 1; + case 0x1f402038: CONSTREAD8_CALL((u32)cdvdRead38); return 1; + case 0x1f402039: CONSTREAD8_CALL((u32)cdvdRead39); return 1; + case 0x1f40203A: CONSTREAD8_CALL((u32)cdvdRead3A); return 1; + default: + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + XOR32RtoR(x86reg, x86reg); + return 0; + } +} + +void psxHw4Write8(u32 add, u8 value) { + switch (add) { + case 0x1f402004: cdvdWrite04(value); return; + case 0x1f402005: cdvdWrite05(value); return; + case 0x1f402006: cdvdWrite06(value); return; + case 0x1f402007: cdvdWrite07(value); return; + case 0x1f402008: cdvdWrite08(value); return; + case 0x1f40200A: cdvdWrite0A(value); return; + case 0x1f40200F: cdvdWrite0F(value); return; + case 0x1f402014: cdvdWrite14(value); return; + case 0x1f402016: + cdvdWrite16(value); + FreezeMMXRegs(0); + return; + case 0x1f402017: cdvdWrite17(value); return; + case 0x1f402018: cdvdWrite18(value); return; + case 0x1f40203A: cdvdWrite3A(value); return; + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value); + return; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHw4ConstWrite8(u32 add, int mmreg) { + switch (add) { + case 0x1f402004: CONSTWRITE_CALL(cdvdWrite04); return; + case 0x1f402005: CONSTWRITE_CALL(cdvdWrite05); return; + case 0x1f402006: CONSTWRITE_CALL(cdvdWrite06); return; + case 0x1f402007: CONSTWRITE_CALL(cdvdWrite07); return; + case 0x1f402008: CONSTWRITE_CALL(cdvdWrite08); return; + case 0x1f40200A: CONSTWRITE_CALL(cdvdWrite0A); return; + case 0x1f40200F: CONSTWRITE_CALL(cdvdWrite0F); return; + case 0x1f402014: CONSTWRITE_CALL(cdvdWrite14); return; + case 0x1f402016: + _freeMMXregs(); + CONSTWRITE_CALL(cdvdWrite16); + return; + case 0x1f402017: CONSTWRITE_CALL(cdvdWrite17); return; + case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; + case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; + default: + SysPrintf("*Unknown 8bit write at address %lx\n", add); + return; + } +} + +void psxDmaInterrupt(int n) { + if (HW_DMA_ICR & (1 << (16 + n))) { + HW_DMA_ICR|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (9 + n); + psxHu32(0x1070) |= 8; + //hwIntcIrq(INTC_SBUS); + + } +} + +void psxDmaInterrupt2(int n) { + if (HW_DMA_ICR2 & (1 << (16 + n))) { +/* if (HW_DMA_ICR2 & (1 << (24 + n))) { + SysPrintf("*PCSX2*: HW_DMA_ICR2 n=%d already set\n", n); + } + if (psxHu32(0x1070) & 8) { + SysPrintf("*PCSX2*: psxHu32(0x1070) 8 already set (n=%d)\n", n); + }*/ + HW_DMA_ICR2|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (16 + n); + psxHu32(0x1070) |= 8; + //hwIntcIrq(INTC_SBUS); + } +} diff --git a/branches/pcsx2_0.9.1/PsxHw.h b/branches/pcsx2_0.9.1/PsxHw.h new file mode 100644 index 0000000..c0f4b64 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxHw.h @@ -0,0 +1,117 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXHW_H__ +#define __PSXHW_H__ + +#define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA +#define HW_DMA0_BCR (psxHu32(0x1084)) +#define HW_DMA0_CHCR (psxHu32(0x1088)) + +#define HW_DMA1_MADR (psxHu32(0x1090)) // MDEC out DMA +#define HW_DMA1_BCR (psxHu32(0x1094)) +#define HW_DMA1_CHCR (psxHu32(0x1098)) + +#define HW_DMA2_MADR (psxHu32(0x10a0)) // GPU DMA +#define HW_DMA2_BCR (psxHu32(0x10a4)) +#define HW_DMA2_CHCR (psxHu32(0x10a8)) +#define HW_DMA2_TADR (psxHu32(0x10ac)) + +#define HW_DMA3_MADR (psxHu32(0x10b0)) // CDROM DMA +#define HW_DMA3_BCR (psxHu32(0x10b4)) +#define HW_DMA3_BCR_L16 (psxHu16(0x10b4)) +#define HW_DMA3_BCR_H16 (psxHu16(0x10b6)) +#define HW_DMA3_CHCR (psxHu32(0x10b8)) + +#define HW_DMA4_MADR (psxHu32(0x10c0)) // SPU DMA +#define HW_DMA4_BCR (psxHu32(0x10c4)) +#define HW_DMA4_CHCR (psxHu32(0x10c8)) +#define HW_DMA4_TADR (psxHu32(0x10cc)) + +#define HW_DMA6_MADR (psxHu32(0x10e0)) // GPU DMA (OT) +#define HW_DMA6_BCR (psxHu32(0x10e4)) +#define HW_DMA6_CHCR (psxHu32(0x10e8)) + +#define HW_DMA7_MADR (psxHu32(0x1500)) // SPU2 DMA +#define HW_DMA7_BCR (psxHu32(0x1504)) +#define HW_DMA7_CHCR (psxHu32(0x1508)) + +#define HW_DMA8_MADR (psxHu32(0x1510)) // DEV9 DMA +#define HW_DMA8_BCR (psxHu32(0x1514)) +#define HW_DMA8_CHCR (psxHu32(0x1518)) + +#define HW_DMA9_MADR (psxHu32(0x1520)) // SIF0 DMA +#define HW_DMA9_BCR (psxHu32(0x1524)) +#define HW_DMA9_CHCR (psxHu32(0x1528)) +#define HW_DMA9_TADR (psxHu32(0x152c)) + +#define HW_DMA10_MADR (psxHu32(0x1530)) // SIF1 DMA +#define HW_DMA10_BCR (psxHu32(0x1534)) +#define HW_DMA10_CHCR (psxHu32(0x1538)) + +#define HW_DMA11_MADR (psxHu32(0x1540)) // SIO2 in +#define HW_DMA11_BCR (psxHu32(0x1544)) +#define HW_DMA11_CHCR (psxHu32(0x1548)) + +#define HW_DMA12_MADR (psxHu32(0x1550)) // SIO2 out +#define HW_DMA12_BCR (psxHu32(0x1554)) +#define HW_DMA12_CHCR (psxHu32(0x1558)) + +#define HW_DMA_PCR (psxHu32(0x10f0)) +#define HW_DMA_ICR (psxHu32(0x10f4)) + +#define HW_DMA_PCR2 (psxHu32(0x1570)) +#define HW_DMA_ICR2 (psxHu32(0x1574)) + +#define PSX_INT(n, ecycle) \ + psxRegs.interrupt|= 1 << n; \ + g_psxNextBranchCycle = min(g_psxNextBranchCycle, psxRegs.cycle+ecycle); \ + psxRegs.sCycle[n] = psxRegs.cycle; \ + psxRegs.eCycle[n] = ecycle; + + +void psxHwReset(); +u8 psxHwRead8 (u32 add); +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign); + +u16 psxHwRead16(u32 add); +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign); + +u32 psxHwRead32(u32 add); +int psxHwConstRead32(u32 x86reg, u32 add); + +void psxHwWrite8 (u32 add, u8 value); +void psxHwConstWrite8(u32 add, int mmreg); + +void psxHwWrite16(u32 add, u16 value); +void psxHwConstWrite16(u32 add, int mmreg); + +void psxHwWrite32(u32 add, u32 value); +void psxHwConstWrite32(u32 add, int mmreg); + +u8 psxHw4Read8 (u32 add); +int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign); + +void psxHw4Write8(u32 add, u8 value); +void psxHw4ConstWrite8(u32 add, int mmreg); + +int psxHwFreeze(gzFile f, int Mode); +void psxDmaInterrupt(int n); +void psxDmaInterrupt2(int n); + +#endif /* __PSXHW_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxInterpreter.c b/branches/pcsx2_0.9.1/PsxInterpreter.c new file mode 100644 index 0000000..ebd9739 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxInterpreter.c @@ -0,0 +1,782 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +//#include "PsxBios2.h" + +static int branch = 0; +static int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef PSXCPU_LOG +#define debugI() \ + if (Log) { \ + PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); \ + } +#else +#define debugI() +#endif + +#define execI() { \ + psxRegs.code = PSXMu32(psxRegs.pc); \ + \ + debugI(); \ + psxRegs.pc+= 4; \ + psxRegs.cycle++; \ + \ + psxBSC[psxRegs.code >> 26](); \ + EEsCycle-= (psxRegs.cycle - IOPoCycle) << 3; \ + IOPoCycle = psxRegs.cycle; \ +} + +#define doBranch(tar) { \ + branch2 = branch = 1; \ + branchPC = tar; \ + execI(); \ + branch = 0; \ + psxRegs.pc = branchPC; \ + \ + psxBranchTest(); \ +} + +// Subsets +void (*psxBSC[64])(); +void (*psxSPC[64])(); +void (*psxREG[32])(); +void (*psxCP0[32])(); +void (*psxCP2[64])(); +void (*psxCP2BSC[32])(); + +extern void bios_write(); +extern void bios_printf(); + +typedef struct { + char name[8]; + char names[64][32]; + int maxn; +} irxlib; + +#define IRXLIBS 14 +irxlib irxlibs[32] = { +/*00*/ { { "sysmem" } , + { "start", "init_memory", "retonly", "return_addr_of_memsize", + "AllocSysMemory", "FreeSysMemory", "QueryMemSize", "QueryMaxFreeMemSize", + "QueryTotalFreeMemSize", "QueryBlockTopAddress", "QueryBlockSize", "retonly", + "retonly", "retonly", "Kprintf", "set_Kprintf" } , + 16 }, +/*01*/ { { "loadcore" } , + { "start", "retonly", "retonly_", "return_LibraryEntryTable", + "FlushIcache", "FlushDcache", "RegisterLibraryEntries", "ReleaseLibraryEntries", + "findFixImports", "restoreImports", "RegisterNonAutoLinkEntries", "QueryLibraryEntryTable", + "QueryBootMode", "RegisterBootMode", "setFlag", "resetFlag", + "linkModule", "unlinkModule", "retonly_", "retonly_", + "registerFunc", "jumpA0001B34", "read_header", "load_module", + "findImageInfo" }, + 25 }, +/*02*/ { { "excepman" } , + { "start", "reinit", "deinit", "getcommon", + "RegisterExceptionHandler", "RegisterPriorityExceptionHandler", + "RegisterDefaultExceptionHandler", "ReleaseExceptionHandler", + "ReleaseDefaultExceptionHandler" } , + 9 }, +/*03_4*/{ { "intrman" } , + { "start", "return_0", "deinit", "call3", + "RegisterIntrHandler", "ReleaseIntrHandler", "EnableIntr", "DisableIntr", + "CpuDisableIntr", "CpuEnableIntr", "syscall04", "syscall08", + "resetICTRL", "setICTRL", "syscall0C", "call15", + "call16", "CpuSuspendIntr", "CpuResumeIntr", "CpuSuspendIntr", + "CpuResumeIntr", "syscall10", "syscall14", "QueryIntrContext", + "QueryIntrStack", "iCatchMultiIntr", "retonly", "call27", + "set_h1", "reset_h1", "set_h2", "reset_h2" } , + 0x20 }, +/*05*/ { { "ssbusc" } , + { "start", "retonly", "return_0", "retonly", + "setTable1", "getTable1", "setTable2", "getTable2", + "setCOM_DELAY_1st", "getCOM_DELAY_1st", "setCOM_DELAY_2nd", "getCOM_DELAY_2nd", + "setCOM_DELAY_3rd", "getCOM_DELAY_3rd", "setCOM_DELAY_4th", "getCOM_DELAY_4th", + "setCOM_DELAY", "getCOM_DELAY" } , + 18 }, +/*06*/ { { "dmacman" } , + { "start", "retonly", "deinit", "retonly", + "SetD_MADR", "GetD_MADR", "SetD_BCR", "GetD_BCR", + "SetD_CHCR", "GetD_CHCR", "SetD_TADR", "GetD_TADR", + "Set_4_9_A", "Get_4_9_A", "SetDPCR", "GetDPCR", + "SetDPCR2", "GetDPCR2", "SetDPCR3", "GetDPCR3", + "SetDICR", "GetDICR", "SetDICR2", "GetDICR2", + "SetBF80157C", "GetBF80157C", "SetBF801578", "GetBF801578", + "SetDMA", "SetDMA_chainedSPU_SIF0", "SetDMA_SIF0", "SetDMA_SIF1", + "StartTransfer", "SetVal", "EnableDMAch", "DisableDMAch" } , + 36 }, +/*07_8*/{ { "timrman" } , + { "start", "retonly", "retonly", "call3", + "AllocHardTimer", "ReferHardTimer", "FreeHardTimer", "SetTimerMode", + "GetTimerStatus", "SetTimerCounter", "GetTimerCounter", "SetTimerCompare", + "GetTimerCompare", "SetHoldMode", "GetHoldMode", "GetHoldReg", + "GetHardTimerIntrCode" } , + 17 }, +/*09*/ { { "sysclib" } , + { "start", "reinit", "retonly", "retonly", + "setjmp", "longjmp", "toupper", "tolower", + "look_ctype_table", "get_ctype_table", "memchr", "memcmp", + "memcpy", "memmove", "memset", "bcmp", + "bcopy", "bzero", "prnt", "sprintf", + "strcat", "strchr", "strcmp", "strcpy", + "strcspn", "index", "rindex", "strlen", + "strncat", "strncmp", "strncpy", "strpbrk", + "strrchr", "strspn", "strstr", "strtok", + "strtol", "atob", "strtoul", "wmemcopy", + "wmemset", "vsprintf" } , + 0x2b }, +/*0A*/ { { "heaplib" } , + { "start", "retonly", "retonly", "retonly", + "CreateHeap", "DestroyHeap", "HeapMalloc", "HeapFree", + "HeapSize", "retonly", "retonly", "call11", + "call12", "call13", "call14", "call15", + "retonly", "retonly" } , + 18 }, +/*13*/ { { "stdio" } , + { "start", "unknown", "unknown", "unknown", + "printf" } , + 5 }, +/*14*/ { { "sifman" } , + { "start", "retonly", "deinit", "retonly", + "sceSif2Init", "sceSifInit", "sceSifSetDChain", "sceSifSetDma", + "sceSifDmaStat", "sceSifSend", "sceSifSendSync", "sceSifIsSending", + "sceSifSetSIF0DMA", "sceSifSendSync0", "sceSifIsSending0", "sceSifSetSIF1DMA", + "sceSifSendSync1", "sceSifIsSending1", "sceSifSetSIF2DMA", "sceSifSendSync2", + "sceSifIsSending2", "getEEIOPflags", "setEEIOPflags", "getIOPEEflags", + "setIOPEEflags", "getEErcvaddr", "getIOPrcvaddr", "setIOPrcvaddr", + "call28", "sceSifCheckInit", "setSif0CB", "resetSif0CB", + "retonly", "retonly", "retonly", "retonly" } , + 36 }, +/*16*/ { { "sifcmd" } , + { "start", "retonly", "deinit", "retonly", + "sceSifInitCmd", "sceSifExitCmd", "sceSifGetSreg", "sceSifSetSreg", + "sceSifSetCmdBuffer", "sceSifSetSysCmdBuffer", + "sceSifAddCmdHandler", "sceSifRemoveCmdHandler", + "sceSifSendCmd", "isceSifSendCmd", "sceSifInitRpc", "sceSifBindRpc", + "sceSifCallRpc", "sceSifRegisterRpc", + "sceSifCheckStatRpc", "sceSifSetRpcQueue", + "sceSifGetNextRequest", "sceSifExecRequest", + "sceSifRpcLoop", "sceSifGetOtherData", + "sceSifRemoveRpc", "sceSifRemoveRpcQueue", + "setSif1CB", "resetSif1CB", + "retonly", "retonly", "retonly", "retonly" } , + 32 }, +/*19*/ { { "cdvdman" } , + { "start", "retonly", "retonly", "retonly", + "sceCdInit", "sceCdStandby", "sceCdRead", "sceCdSeek", + "sceCdGetError", "sceCdGetToc", "sceCdSearchFile", "sceCdSync", + "sceCdGetDiskType", "sceCdDiskReady", "sceCdTrayReq", "sceCdStop", + "sceCdPosToInt", "sceCdIntToPos", "retonly", "call19", + "sceDvdRead", "sceCdCheckCmd", "_sceCdRI", "sceCdWriteILinkID", + "sceCdReadClock", "sceCdWriteRTC", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdStatus", "sceCdApplySCmd", "setHDmode", "sceCdOpenConfig", + "sceCdCloseConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdReadKey", + "sceCdDecSet", "sceCdCallback", "sceCdPause", "sceCdBreak", + "call40", "sceCdReadConsoleID", "sceCdWriteConsoleID", "sceCdGetMecaconVersion", + "sceCdGetReadPos", "AudioDigitalOut", "sceCdNop", "_sceGetFsvRbuf", + "_sceCdstm0Cb", "_sceCdstm1Cb", "_sceCdSC", "_sceCdRC", + "sceCdForbidDVDP", "sceCdReadSubQ", "sceCdApplyNCmd", "AutoAdjustCtrl", + "sceCdStInit", "sceCdStRead", "sceCdStSeek", "sceCdStStart", + "sceCdStStat", "sceCdStStop" } , + 62 }, +/*??*/ { { "sio2man" } , + { "start", "retonly", "deinit", "retonly", + "set8268_ctrl", "get8268_ctrl", "get826C_recv1", "call7_send1", + "call8_send1", "call9_send2", "call10_send2", "get8270_recv2", + "call12_set_params", "call13_get_params", "get8274_recv3", "set8278", + "get8278", "set827C", "get827C", "set8260_datain", + "get8264_dataout", "set8280_intr", "get8280_intr", "signalExchange1", + "signalExchange2", "packetExchange" } , + 26 } +}; + +#define Ra0 ((char*)PSXM(psxRegs.GPR.n.a0)) +#define Ra1 ((char*)PSXM(psxRegs.GPR.n.a1)) +#define Ra2 ((char*)PSXM(psxRegs.GPR.n.a2)) +#define Ra3 ((char*)PSXM(psxRegs.GPR.n.a3)) + +char* intrname[]={ +"INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00 +"INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04 +"INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08 +"INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C +"INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10 +"INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14 +"INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18 +"INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C +"INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20 +"INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24 +"INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28 +"INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C +"INT_30", "INT_31", "INT_32", "INT_33", //30 +"INT_34", "INT_35", "INT_36", "INT_37", //34 +"INT_38", "INT_39", "INT_3A", "INT_3B", //38 +"INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C +"INT_MAX" //40 +}; + +void zeroEx() { + u32 pc; + u32 code; + char *lib; + char *fname = NULL; + int i; + + if (!Config.PsxOut) return; + + pc = psxRegs.pc; + while (PSXMu32(pc) != 0x41e00000) pc-=4; + + lib = (char*)PSXM(pc+12); + code = PSXMu32(psxRegs.pc - 4) & 0xffff; + + for (i=0; i= (u32)irxlibs[i].maxn) break; + + fname = irxlibs[i].names[code]; break; + } + } + +#ifdef PSXBIOS_LOG + {char libz[9]; memcpy(libz, lib, 8); libz[8]=0; + PSXBIOS_LOG("%s: %s (%x)" + " (%x, %x, %x, %x)" //comment this line to disable param showing + , libz, fname == NULL ? "unknown" : fname, code, + psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + } +#endif + +// Log=0; +// if (!strcmp(lib, "intrman") && code == 0x11) Log=1; +// if (!strcmp(lib, "sifman") && code == 0x5) Log=1; +// if (!strcmp(lib, "sifcmd") && code == 0x4) Log=1; +// if (!strcmp(lib, "thbase") && code == 0x6) Log=1; +/* + if (!strcmp(lib, "sifcmd") && code == 0xe) { + branchPC = psxRegs.GPR.n.ra; + psxRegs.GPR.n.v0 = 0; + return; + } +*/ + if (!strncmp(lib, "ioman", 5) && code == 7) { + if (psxRegs.GPR.n.a0 == 1) { + pc = psxRegs.pc; + bios_write(); + psxRegs.pc = pc; + } + } + + if (!strncmp(lib, "sysmem", 6) && code == 0xe) { + bios_printf(); + psxRegs.pc = psxRegs.GPR.n.ra; + } + + if (!strncmp(lib, "loadcore", 8) && code == 6) { + SysPrintf("loadcore RegisterLibraryEntries (%x): %8.8s\n", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12)); + } + + if (!strncmp(lib, "intrman", 7) && code == 4) { + SysPrintf("intrman RegisterIntrHandler (%x): intr %s, handler %x\n", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2); + } + + if (!strncmp(lib, "sifcmd", 6) && code == 17) { + SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1); + } + +#ifdef PSXBIOS_LOG + if (!strncmp(lib, "sysclib", 8)) { + switch (code) { + case 0x16: // strcmp + if (varLog & 0x00800000) EMU_LOG(" \"%s\": \"%s\"", Ra0, Ra1); + break; + + case 0x1e: // strncpy + if (varLog & 0x00800000) EMU_LOG(" \"%s\"", Ra1); + break; + } + } +#endif + +#ifdef PSXBIOS_LOG + if (varLog & 0x00800000) EMU_LOG("\n"); +#endif + +/* psxRegs.pc = branchPC; + pc = psxRegs.GPR.n.ra; + while (psxRegs.pc != pc) psxCpu->ExecuteBlock(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("%s: %s (%x) END\n", lib, fname == NULL ? "unknown" : fname, code); +#endif*/ +} +/*/==========================================CALL LOG +char* getName(char *file, u32 addr){ + FILE *f; u32 a; + static char name[100]; + + f=fopen(file, "r"); + if (!f) + name[0]=0; + else{ + while (!feof(f)){ + fscanf(f, "%08X %s\r\n", &a, name); + if (a==addr)break; + } + fclose(f); + } + return name; +} + +void spyFunctions(){ + register irxImageInfo *iii; + if (psxRegs.pc >= 0x200000) return; + for (iii=(irxImageInfo*)PSXM(0x800); iii && iii->text_size; + iii=iii->next ? (irxImageInfo*)PSXM(iii->next) : NULL) + if (iii->vaddr<=psxRegs.pc && psxRegs.pcvaddr+iii->text_size+iii->data_size+iii->bss_size){ + if (strcmp("secrman_for_cex", PSXM(iii->name))==0){ + char *name=getName("secrman.fun", psxRegs.pc-iii->vaddr); + if (strncmp("__push_params", name, 13)==0){ + PAD_LOG(PSXM(psxRegs.GPR.n.a0), psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + }else{ + PAD_LOG("secrman: %s (ra=%06X cycle=%d)\n", name, psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}}else + if (strcmp("mcman", PSXM(iii->name))==0){ + PAD_LOG("mcman: %s (ra=%06X cycle=%d)\n", getName("mcman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("padman", PSXM(iii->name))==0){ + PAD_LOG("padman: %s (ra=%06X cycle=%d)\n", getName("padman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("sio2man", PSXM(iii->name))==0){ + PAD_LOG("sio2man: %s (ra=%06X cycle=%d)\n", getName("sio2man.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);} + break; + } +} +*/ +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow) +void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im +void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im +void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im +void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im +void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed) +void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow) +void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt +void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow) +void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt +void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt +void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt +void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt +void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt +void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed) +void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void psxDIV() { + if (_rRt_ != 0) { + _rLo_ = _i32(_rRs_) / _i32(_rRt_); + _rHi_ = _i32(_rRs_) % _i32(_rRt_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi +void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs +void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +void psxBREAK() { + // Break exception - psx rom doens't handles this + psxRegs.pc -= 4; + psxException(0x24, branch); +} + +void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); + +} + +void psxRFE() { +// SysPrintf("RFE\n"); + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +// Log=0; +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_); + +void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +void psxJ() { doBranch(_JumpTarget_); } +void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); /*spyFunctions();*/ } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void psxJR() { doBranch(_u32(_rRs_)); } +void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); } + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +void psxLB() { + if (_Rt_) { + _rRt_ = (s8 )psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + if (_Rt_) { + _rRt_ = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + if (_Rt_) { + _rRt_ = (s16)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + if (_Rt_) { + _rRt_ = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + if (_Rt_) { + _rRt_ = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +void psxLWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) | + ( mem << (24 - shift) ); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + + */ +} + +void psxLWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) | + ( mem >> shift ); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + + */ +} + +void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +void psxSWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) | + ( mem & (0xffffff00 << shift) )); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + + */ +} + +void psxSWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) | + (mem & (0x00ffffff >> (24 - shift)) ) ) ); + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } +void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } + +void psxMTC0() { _rFs_ = _u32(_rRt_); } +void psxCTC0() { _rFs_ = _u32(_rRt_); } + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +void psxNULL() { +SysPrintf("psx: Unimplemented op %x\n", psxRegs.code); +} + +void psxSPECIAL() { + psxSPC[_Funct_](); +} + +void psxREGIMM() { + psxREG[_Rt_](); +} + +void psxCOP0() { + psxCP0[_Rs_](); +} + +void psxCOP2() { + psxCP2[_Funct_](); +} + +void psxBASIC() { + psxCP2BSC[_Rs_](); +} + + +void (*psxBSC[64])() = { + psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, + psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , + psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL +}; + + +void (*psxSPC[64])() = { + psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV, + psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL, + psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL, + psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL, + psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR , + psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL +}; + +void (*psxREG[32])() = { + psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP0[32])() = { + psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP2[64])() = { + psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08 + psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38 +}; + +void (*psxCP2BSC[32])() = { + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + + +/////////////////////////////////////////// + +static int intInit() { + return 0; +} + +static void intReset() { +} + +static void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + while (EEsCycle > 0){ + branch2 = 0; + while (!branch2) + execI(); + } +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; diff --git a/branches/pcsx2_0.9.1/PsxMem.c b/branches/pcsx2_0.9.1/PsxMem.c new file mode 100644 index 0000000..9cae17e --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxMem.c @@ -0,0 +1,1605 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" +#include "VU.h" +#include "iCore.h" +#include "ir3000A.h" + +extern u32 g_psxMaxRecMem; +int g_psxWriteOk=1; +static u32 writectrl; + +#ifdef WIN32_VIRTUAL_MEM + +int psxMemInit() +{ + // all mem taken care by memInit + return 0; +} + +void psxMemReset() +{ + memset(psxM, 0, 0x00200000); +} + +void psxMemShutdown() +{ +} + +#ifdef _DEBUG + +#define ASSERT_WRITEOK \ +{ \ + __asm cmp g_psxWriteOk, 1 \ + __asm je WriteOk \ + __asm int 10 \ +} \ +WriteOk: \ + +#else +#define ASSERT_WRITEOK +#endif + +u8 psxMemRead8(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + break; + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + mem &= 0x1fffffff; + return psxHw4Read8(mem); + + case 0x1000: return DEV9read8(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u8*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f40 + je hw4read + cmp dx, 0x1000 + je devread + cmp dx, 0x1f00 + je spuread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead8 + add esp, 4 + ret + +hw4read: + push ecx + call psxHw4Read8 + add esp, 4 + ret + +devread: + push ecx + call DEV9read8 + // stack already incremented + ret + +spuread: + push ecx + call SPU2read + // stack already incremented + ret + } +} + +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + return psxHwConstRead8(x86reg, mem&0x1fffffff, sign); + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + return psxHw4ConstRead8(x86reg, mem&0x1fffffff, sign); + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(x86reg, EAX); + else MOVZX32R8toR(x86reg, EAX); + return 0; + + default: + _eeReadConstMem8(x86reg, (u32)PSXM(mem), sign); + return 0; + } +} + +u16 psxMemRead16(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu16(0x1000F240) | 0x0002; + case 0x60: return 0; + default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1f90: + return SPU2read(mem & 0x1FFFFFFF); + case 0x1000: + return DEV9read16(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u16*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f90 + je spuread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead16 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 2 + jmp End +Sif60: + xor eax, eax + jmp End + +spuread: + push ecx + call SPU2read + // stack already incremented + +End: + ret + +devread: + push ecx + call DEV9read16 + // stack already incremented + ret + } +} + +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead16(x86reg, mem&0x1fffffff, sign); + + case 0x1d00: + + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xF240, sign); + OR32ItoR(x86reg, 0x0002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0), sign); + break; + } + return 0; + + case 0x1f90: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + default: + assert( g_psxWriteOk ); + _eeReadConstMem16(x86reg, (u32)PSXM(mem), sign); + return 0; + } + + return 0; +} + +u32 psxMemRead32(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu32(0x1000F240) | 0xF0000002; + case 0x60: return 0; + default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1fff: return g_psxWriteOk; + case 0x1000: + return DEV9read32(mem & 0x1FFFFFFF); + + default: + assert(g_psxWriteOk); + if( mem == 0xfffe0130 ) + return writectrl; + else if( mem == 0xffffffff ) + return writectrl; + else if( g_psxWriteOk ) + return *(u32*)PSXM(mem); + else return 0; + } +} + +__declspec(naked) void psxRecMemRead32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + cmp ecx, 0x1ffe0130 + je WriteCtrlRead + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead32 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + // do the read from ps2 mem + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 0xf0000002 + jmp End +Sif60: + xor eax, eax +End: + ret + +devread: + push ecx + call DEV9read32 + // stack already incremented + ret + +WriteCtrlRead: + mov eax, writectrl + ret + } +} + +int psxRecMemConstRead32(u32 x86reg, u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead32(x86reg, mem&0x1fffffff); + + case 0x1d00: + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xF240); + OR32ItoR(x86reg, 0xf0000002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0)); + break; + } + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read32); + return 1; + + default: + if( mem == 0xfffe0130 ) + MOV32MtoR(x86reg, (u32)&writectrl); + else { + XOR32RtoR(x86reg, x86reg); + CMP32ItoM((u32)&g_psxWriteOk, 0); + CMOVNE32MtoR(x86reg, (u32)PSXM(mem)); + } + + return 0; + } +} + +void psxMemWrite8(u32 mem, u8 value) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + break; + + case 0x1f40: + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + break; + + case 0x1d00: + SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + *(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value; + break; + + case 0x1000: + DEV9write8(mem & 0x1fffffff, value); + return; + + default: + assert(g_psxWriteOk); + *(u8 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f40 + je hw4write + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov byte ptr [ecx+PS2MEM_BASE_], al + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite8 + add esp, 8 + ret + +hw4write: + push eax + push ecx + call psxHw4Write8 + add esp, 8 + ret + +devwrite: + push eax + push ecx + call DEV9write8 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite8(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + psxHwConstWrite8(mem&0x1fffffff, mmreg); + return 0; + case 0x1f40: + psxHw4ConstWrite8(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + assert(0); + _eeWriteConstMem8((u32)(PS2MEM_HW+0xf200+(mem&0xff)), mmreg); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write8); + return 0; + + default: + _eeWriteConstMem8((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite16(u32 mem, u16 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + default: + assert(0); + } + return; + + case 0x1f90: + SPU2write(mem & 0x1FFFFFFF, value); return; + + case 0x1000: + DEV9write16(mem & 0x1fffffff, value); return; + default: + assert( g_psxWriteOk ); + *(u16 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f90 + je spuwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov word ptr [ecx+PS2MEM_BASE_], ax + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite16 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif60: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +spuwrite: + push eax + push ecx + call SPU2write + // stack alwritey incremented + ret + +devwrite: + push eax + push ecx + call DEV9write16 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite16(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite16(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem16((u32)(PS2MEM_HW+0xf210), mmreg); + return 0; + case 0x40: + { + // delete x86reg + _eeMoveMMREGtoR(EAX, mmreg); + + assert( mmreg != EBX ); + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1f90: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2write); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write16); + return 0; + + default: + _eeWriteConstMem16((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite32(u32 mem, u32 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + default: + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + } + + return; + + case 0x1000: + DEV9write32(mem & 0x1fffffff, value); + return; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + g_psxWriteOk = 0; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + g_psxWriteOk = 1; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + break; + + default: + + if( g_psxWriteOk ) { + *(u32 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + } + + break; + } +} + +__declspec(naked) void psxRecMemWrite32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + cmp dx, 0x1ffe + je WriteCtrl + } + + __asm { + // rom writes, has to be PS2MEM_BASE_ + test g_psxWriteOk, 1 + jz endwrite + +memwrite: + mov dword ptr [ecx+PS2MEM_BASE_], eax +endwrite: + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + cmp dl, 0x30 + je Sif30 + cmp dl, 0x20 + je Sif20 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif30: + or dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif20: + not eax + and dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif60: + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +devwrite: + push eax + push ecx + call DEV9write32 + // stack alwritey incremented + ret + +WriteCtrl: + cmp ecx, 0x1ffe0130 + jne End + + mov writectrl, eax + + cmp eax, 0x800 + je SetWriteNotOk + cmp eax, 0x804 + je SetWriteNotOk + cmp eax, 0xc00 + je SetWriteNotOk + cmp eax, 0xc04 + je SetWriteNotOk + cmp eax, 0xcc0 + je SetWriteNotOk + cmp eax, 0xcc4 + je SetWriteNotOk + cmp eax, 0x0c4 + je SetWriteNotOk + + // test ok + cmp eax, 0x1e988 + je SetWriteOk + cmp eax, 0x1edd8 + je SetWriteOk + +End: + ret + +SetWriteNotOk: + mov g_psxWriteOk, 0 + ret +SetWriteOk: + mov g_psxWriteOk, 1 + ret + } +} + +int psxRecMemConstWrite32(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite32(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem32((u32)PS2MEM_HW+0xf210, mmreg); + return 0; + case 0x20: + // write to ps2 mem + // delete x86reg + if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM((u32)PS2MEM_HW+0xf220, ~g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else { + NOT32R(mmreg); + AND32RtoM((u32)PS2MEM_HW+0xf220, mmreg); + } + return 0; + case 0x30: + // write to ps2 mem + _eeWriteConstMem32OP((u32)PS2MEM_HW+0xf230, mmreg, 1); + return 0; + case 0x40: + { + // delete x86reg + assert( mmreg != EBX ); + + _eeMoveMMREGtoR(EAX, mmreg); + + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + u8* ptrs[9]; + + _eeWriteConstMem32((u32)&writectrl, mmreg); + + if( IS_PSXCONSTREG(mmreg) ) { + switch (g_psxConstRegs[(mmreg>>16)&0x1f]) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + MOV32ItoM((u32)&g_psxWriteOk, 0); + break; + case 0x1e988: + case 0x1edd8: + MOV32ItoM((u32)&g_psxWriteOk, 1); + break; + default: + assert(0); + } + } + else { + // not ok + CMP32ItoR(mmreg, 0x800); + ptrs[0] = JE8(0); + CMP32ItoR(mmreg, 0x804); + ptrs[1] = JE8(0); + CMP32ItoR(mmreg, 0xc00); + ptrs[2] = JE8(0); + CMP32ItoR(mmreg, 0xc04); + ptrs[3] = JE8(0); + CMP32ItoR(mmreg, 0xcc0); + ptrs[4] = JE8(0); + CMP32ItoR(mmreg, 0xcc4); + ptrs[5] = JE8(0); + CMP32ItoR(mmreg, 0x0c4); + ptrs[6] = JE8(0); + + // ok + CMP32ItoR(mmreg, 0x1e988); + ptrs[7] = JE8(0); + CMP32ItoR(mmreg, 0x1edd8); + ptrs[8] = JE8(0); + + x86SetJ8(ptrs[0]); + x86SetJ8(ptrs[1]); + x86SetJ8(ptrs[2]); + x86SetJ8(ptrs[3]); + x86SetJ8(ptrs[4]); + x86SetJ8(ptrs[5]); + x86SetJ8(ptrs[6]); + MOV32ItoM((u32)&g_psxWriteOk, 0); + ptrs[0] = JMP8(0); + + x86SetJ8(ptrs[7]); + x86SetJ8(ptrs[8]); + MOV32ItoM((u32)&g_psxWriteOk, 1); + + x86SetJ8(ptrs[0]); + } + } + return 0; + + default: + TEST8ItoM((u32)&g_psxWriteOk, 1); + j8Ptr[0] = JZ8(0); + _eeWriteConstMem32((u32)PSXM(mem), mmreg); + x86SetJ8(j8Ptr[0]); + return 1; + } +} + +#else + +// TLB functions + +s8 *psxM; +s8 *psxP; +s8 *psxH; +s8 *psxS; +uptr *psxMemWLUT; +uptr *psxMemRLUT; + +int psxMemInit() +{ + int i; + + psxMemRLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + memset(psxMemRLUT, 0, 0x10000 * sizeof(uptr)); + memset(psxMemWLUT, 0, 0x10000 * sizeof(uptr)); + + psxM = (char*)_aligned_malloc(0x00200000,16); + psxP = (char*)_aligned_malloc(0x00010000,16); + psxH = (char*)_aligned_malloc(0x00010000,16); + psxS = (char*)_aligned_malloc(0x00010000,16); + if (psxMemRLUT == NULL || psxMemWLUT == NULL || + psxM == NULL || psxP == NULL || psxH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + memset(psxH, 0, 0x00010000); + memset(psxS, 0, 0x00010000); + + +// MemR + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x9fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0xbfc0] = (uptr)&PS2MEM_ROM[i << 16]; + + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x9e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0xbe00] = (uptr)&PS2MEM_ROM1[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + +// MemW + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + +// for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16]; + +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + + return 0; +} + +void psxMemReset() { + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + //memset(psxS, 0, 0x00010000); +} + +void psxMemShutdown() +{ + _aligned_free(psxM); + _aligned_free(psxP); + _aligned_free(psxH); + _aligned_free(psxMemRLUT); + _aligned_free(psxMemWLUT); +} + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + return psxHw4Read8(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + return *(u8 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lb %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u16 psxMemRead16(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u16 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu16(0x1000F200); + break; + case 0x10: + ret= psHu16(0x1000F210); + break; + case 0x40: + ret= psHu16(0x1000F240) | 0x0002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu16(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u16 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1F90) + return SPU2read(mem & 0x1FFFFFFF); + if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lh %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u32 psxMemRead32(u32 mem) { + char *p; + u32 t; + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + //see also Hw.c + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u32 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu32(0x1000F200); + break; + case 0x10: + ret= psHu32(0x1000F210); + break; + case 0x20: + ret= psHu32(0x1000F220); + break; + case 0x30: // EE Side + ret= psHu32(0x1000F230); + break; + case 0x40: + ret= psHu32(0x1000F240) | 0xF0000002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu32(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u32 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); + + if (mem != 0xfffe0130) { +#ifdef PSXMEM_LOG + if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); +#endif + } else { + return writectrl; + } + return 0; + } + } +} + +void psxMemWrite8(u32 mem, u8 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u8 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + if (t == 0x1d00) { + psxSu8(mem) = value; return; + } + if (t == 0x1000) { + DEV9write8(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite16(u32 mem, u16 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); + *(u16 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (t == 0x1d00) { + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu16(mem) = value; return; + } + if (t == 0x1F90) { + SPU2write(mem & 0x1FFFFFFF, value); return; + } + if (t == 0x1000) { + DEV9write16(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite32(u32 mem, u32 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + } else { + //see also Hw.c + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u32 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (mem != 0xfffe0130) { + if (t == 0x1d00) { +#ifdef MEM_LOG + MEM_LOG("iop Sif reg write %x value %x\n", mem, value); +#endif + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu32(mem) = value; + + // write to ps2 mem + if( (mem & 0xf0) != 0x60 ) + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + return; + } + if (t == 0x1000) { + DEV9write32(mem & 0x1fffffff, value); return; + } + + //if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); +#ifdef PSXMEM_LOG + if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } +#endif + } else { + int i; + + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + if (g_psxWriteOk == 0) break; + g_psxWriteOk = 0; + memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(uptr)); +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + if (g_psxWriteOk == 1) break; + g_psxWriteOk = 1; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + } + } +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/PsxMem.h b/branches/pcsx2_0.9.1/PsxMem.h new file mode 100644 index 0000000..b9d861b --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxMem.h @@ -0,0 +1,113 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#ifdef WIN32_VIRTUAL_MEM + +// VM +#define psxM PS2MEM_PSX +#define psxH PS2MEM_PSXHW + +#define PSXM(mem) ((mem&0x10000000)?PSM(mem):(PS2MEM_PSX+(mem&0x1fffff))) +#define _PSXM(mem) PSXM(mem) + +#else + +// TLB +extern s8 *psxM; +extern s8 *psxP; +extern s8 *psxH; +extern s8 *psxS; +extern uptr *psxMemWLUT; +extern uptr *psxMemRLUT; + +#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) +#define _PSXM(mem) ((void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) + +#define psxSs8(mem) psxS[(mem) & 0xffff] +#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) +#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) +#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) +#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) +#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) + +#endif + +#define psxMs8(mem) psxM[(mem) & 0x1fffff] +#define psxMs16(mem) (*(s16*)&psxM[(mem) & 0x1fffff]) +#define psxMs32(mem) (*(s32*)&psxM[(mem) & 0x1fffff]) +#define psxMu8(mem) (*(u8*) &psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (*(u16*)&psxM[(mem) & 0x1fffff]) +#define psxMu32(mem) (*(u32*)&psxM[(mem) & 0x1fffff]) +#define psxMu64(mem) (*(u64*)&psxM[(mem) & 0x1fffff]) + +#define psxPs8(mem) psxP[(mem) & 0xffff] +#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) +#define psxPs32(mem) (*(s32*)&psxP[(mem) & 0xffff]) +#define psxPu8(mem) (*(u8*) &psxP[(mem) & 0xffff]) +#define psxPu16(mem) (*(u16*)&psxP[(mem) & 0xffff]) +#define psxPu32(mem) (*(u32*)&psxP[(mem) & 0xffff]) + +#define psxHs8(mem) psxH[(mem) & 0xffff] +#define psxHs16(mem) (*(s16*)&psxH[(mem) & 0xffff]) +#define psxHs32(mem) (*(s32*)&psxH[(mem) & 0xffff]) +#define psxHu8(mem) (*(u8*) &psxH[(mem) & 0xffff]) +#define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff]) +#define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff]) + +#define PSXMs8(mem) (*(s8 *)_PSXM(mem)) +#define PSXMs16(mem) (*(s16*)_PSXM(mem)) +#define PSXMs32(mem) (*(s32*)_PSXM(mem)) +#define PSXMu8(mem) (*(u8 *)_PSXM(mem)) +#define PSXMu16(mem) (*(u16*)_PSXM(mem)) +#define PSXMu32(mem) (*(u32*)_PSXM(mem)) + +int psxMemInit(); +void psxMemReset(); +void psxMemShutdown(); + +u8 psxMemRead8 (u32 mem); +u16 psxMemRead16(u32 mem); +u32 psxMemRead32(u32 mem); +void psxMemWrite8 (u32 mem, u8 value); +void psxMemWrite16(u32 mem, u16 value); +void psxMemWrite32(u32 mem, u32 value); + +// x86reg and mmreg are always x86 regs +void psxRecMemRead8(); +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead16(); +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead32(); +int psxRecMemConstRead32(u32 x86reg, u32 mem); + +void psxRecMemWrite8(); +int psxRecMemConstWrite8(u32 mem, int mmreg); + +void psxRecMemWrite16(); +int psxRecMemConstWrite16(u32 mem, int mmreg); + +void psxRecMemWrite32(); +int psxRecMemConstWrite32(u32 mem, int mmreg); + + +#endif /* __PSXMEMORY_H__ */ diff --git a/branches/pcsx2_0.9.1/PsxSio2.c b/branches/pcsx2_0.9.1/PsxSio2.c new file mode 100644 index 0000000..6f83c10 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxSio2.c @@ -0,0 +1,249 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + +/* +w [8268]=0x3bc sio2_start/sio2man +r [8270] padman_start/padman + padman->7480[00]=bit4; + padman->7480[13]=bit5; + packetExchange(&703F8); +w [8268]|=0x0C; +........ +w [8268]|=0x01; + +only recv2 & dataout influences padman +*/ + +// 0xBF808200,0xBF808204,0xBF808208,0xBF80820C, +// 0xBF808210,0xBF808214,0xBF808218,0xBF80821C, packet->sendArray3 +// 0xBF808220,0xBF808224,0xBF808228,0xBF80822C, call12/13_s/getparams +// 0xBF808230,0xBF808234,0xBF808238,0xBF80823C, + +// 0xBF808240,0xBF808248,0xBF808250,0xBF808258, packet->sendArray1/call_7/8 +// 0xBF808244,0xBF80824C,0xBF808254,0xBF80825C, packet->sendArray2/call_9/10 + +// 0xBF808260, serial data/fifo in/out s/get8260_datain/out packet->sendbuf(nomem!) +// 0xBF808268, ctrl s/get8268_ctrl + +// 0xBF80826C, packet->recv1/2/3 get826C_recv1, get8270_recv2, get8274_recv3 +// 0xBF808270,0xBF808274, + +// 0xBF808278,0xBF80827C, s/get8278, s/get827C +// 0xBF808280 interrupt related s/get8280_intr + + +void sio2Reset() { + SysPrintf("Sio2 init\n"); + memset(&sio2, 0, sizeof(sio2)); + sio2.packet.recvVal1 = 0x1D100; // Nothing is connected at start +} + +u32 sio2_getRecv1() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv1 = %x\n",sio2.packet.recvVal1); +#endif + return sio2.packet.recvVal1; +} + +u32 sio2_getRecv2() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv2 = %x\n",0xF); +#endif + return 0xF; +}//0, 0x10, 0x20, 0x10 | 0x20; bits 4 & 5 + +u32 sio2_getRecv3() { + if(sio2.packet.recvVal3 == 0x8C || sio2.packet.recvVal3 == 0x8b || + sio2.packet.recvVal3 == 0x83) + { +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio2.packet.recvVal3); +#endif + sio.packetsize = sio2.packet.recvVal3; + sio2.packet.recvVal3 = 0; // Reset + return sio.packetsize; + }else{ +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio.packetsize << 16); +#endif + return sio.packetsize << 16; + } +} + +void sio2_setSend1(u32 index, u32 value){sio2.packet.sendArray1[index]=value;} //0->3 +u32 sio2_getSend1(u32 index){return sio2.packet.sendArray1[index];} //0->3 +void sio2_setSend2(u32 index, u32 value){sio2.packet.sendArray2[index]=value;} //0->3 +u32 sio2_getSend2(u32 index){return sio2.packet.sendArray2[index];} //0->3 +void sio2_setSend3(u32 index, u32 value) {int i; +/* if (index == 0) { + printf("value: %x\n", value); + }*/ + sio2.packet.sendArray3[index]=value; +#ifdef PAD_LOG + if (index==15){ + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray1[i]);}PAD_LOG("\n"); + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray2[i]);}PAD_LOG("\n"); + for (i=0; i<8; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + for ( ; i<16; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + } +#endif +} //0->15 + +u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //0->15 + +void sio2_setCtrl(u32 value){ + sio2.ctrl=value; + if (sio2.ctrl & 1){ //recv packet + //handle data that had been sent + + //trigger interupt for SIO2 + psxHu32(0x1070)|=0x20000; + sio2.recvIndex=0; + sio2.ctrl &= ~1; + } else { // send packet + //clean up + sio2.packet.sendSize=0; //reset size + sio2.cmdport=0; + sio2.cmdlength=0; + sioWriteCtrl16(SIO_RESET); + } +} +u32 sio2_getCtrl(){return sio2.ctrl;} + +void sio2_setIntr(u32 value){sio2.intr=value;} +u32 sio2_getIntr(){ + return sio2.intr; +} + +void sio2_set8278(u32 value){sio2._8278=value;} +u32 sio2_get8278(){return sio2._8278;} +void sio2_set827C(u32 value){sio2._827C=value;} +u32 sio2_get827C(){return sio2._827C;} + +void sio2_fifoIn(u8 value){ + u16 ctrl=0x0002; + if (sio2.packet.sendArray3[sio2.cmdport] && (sio2.cmdlength==0)){//else do nothing! + + sio2.cmdlength=(sio2.packet.sendArray3[sio2.cmdport] >> 8) & 0x1FF; + ctrl &= ~0x2000; + ctrl |= (sio2.packet.sendArray3[sio2.cmdport] & 1) << 13;//it is correct this way:P; what did you want to do? + //sioWriteCtrl16(SIO_RESET); + sioWriteCtrl16(ctrl); +#ifdef PSXDMA_LOG + PSXDMA_LOG("sio2_fifoIn: ctrl = %x, cmdlength = %x, cmdport = %d (%x)\n", ctrl, sio2.cmdlength, sio2.cmdport, sio2.packet.sendArray3[sio2.cmdport]); +#endif + sio2.cmdport++;//position in sendArray3 + } + if (sio2.cmdlength) sio2.cmdlength--; + +// sioWriteCtrl16(ctrl); + + sioWrite8(value); + if (sio2.packet.sendSize > BUFSIZE) {//asadr + SysPrintf("*PCSX2*: sendSize >= %d\n", BUFSIZE); + } else { + sio2.buf[sio2.packet.sendSize] = sioRead8(); + sio2.packet.sendSize++; + } +} + +u8 sio2_fifoOut(){ + u8 value=0; + + if (sio2.recvIndex <= sio2.packet.sendSize){ + value = sio2.buf[sio2.recvIndex++]; + } else { + SysPrintf("*PCSX2*: buffer overrun\n"); + } + return value; //no data +} + +///////////////////////////////////////////////// +//////////////////////////////////////////// DMA +///////////////////////////////////////////////// + +void psxDma11(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 11 - SIO2 in *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x01000201) return; + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + PSX_INT(11,(bcr>>2)); + while (bcr > 0) { + sio2_fifoIn(PSXMu8(madr)); + bcr--; madr++; + if(sio2.packet.sendSize == BUFSIZE) break; + } + HW_DMA11_MADR = madr; + HW_DMA11_BCR = bcr; + +} + +int psxDMA11Interrupt() +{ + HW_DMA11_CHCR &= ~0x01000000; + psxDmaInterrupt2(4); + return 1; +} + +void psxDma12(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 12 - SIO2 out *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x41000200) return; + + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + sio2.recvIndex = 0; // Set To start asadr + PSX_INT(12,(bcr>>2)); + while (bcr > 0) { + PSXMu8(madr) = sio2_fifoOut(); + bcr--; madr++; + if(sio2.recvIndex == sio2.packet.sendSize) break; + } + HW_DMA12_MADR = madr; + HW_DMA12_BCR = bcr; + PSX_INT(12,(bcr>>2)); + +} + +int psxDMA12Interrupt() +{ + HW_DMA12_CHCR &= ~0x01000000; + psxDmaInterrupt2(5); + return 1; +} + +int sio2Freeze(gzFile f, int Mode) { + gzfreeze(&sio2, sizeof(sio2)); + + return 0; +} + diff --git a/branches/pcsx2_0.9.1/PsxSio2.h b/branches/pcsx2_0.9.1/PsxSio2.h new file mode 100644 index 0000000..6f5aea8 --- /dev/null +++ b/branches/pcsx2_0.9.1/PsxSio2.h @@ -0,0 +1,98 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXSIO2_H__ +#define __PSXSIO2_H__ + + +#define BUFSIZE 1024 + +//from sio2man.c + +struct SIO2_packet { + unsigned int recvVal1; // 0x00 + unsigned int sendArray1[4]; // 0x04-0x10 + unsigned int sendArray2[4]; // 0x14-0x20 + + unsigned int recvVal2; // 0x24 + + unsigned int sendArray3[16]; // 0x28-0x64 + + unsigned int recvVal3; // 0x68 + + int sendSize; // 0x6C + int recvSize; // 0x70 + + unsigned char *sendBuf; // 0x74 + unsigned char *recvBuf; // 0x78 + + unsigned int dmacAddress1; + unsigned int dmacSize1; + unsigned int dmacCount1; + unsigned int dmacAddress2; + unsigned int dmacSize2; + unsigned int dmacCount2; +}; + +typedef struct { + struct SIO2_packet packet; + u32 ctrl; + u32 intr; + u32 _8278, _827C; + int recvIndex; + u32 hackedRecv; + int cmdport; + int cmdlength; //length of a command sent to a port + //is less_equal than the dma send size + u8 buf[BUFSIZE]; +} sio2Struct; + +sio2Struct sio2; + +void sio2Reset(); +u32 sio2_getRecv1(); +u32 sio2_getRecv2(); +u32 sio2_getRecv3(); +void sio2_setSend1(u32 index, u32 value); //0->3 +u32 sio2_getSend1(u32 index); //0->3 +void sio2_setSend2(u32 index, u32 value); //0->3 +u32 sio2_getSend2(u32 index); //0->3 +void sio2_setSend3(u32 index, u32 value); //0->15 +u32 sio2_getSend3(u32 index); //0->15 + +void sio2_setCtrl(u32 value); +u32 sio2_getCtrl(); +void sio2_setIntr(u32 value); +u32 sio2_getIntr(); +void sio2_set8278(u32 value); +u32 sio2_get8278(); +void sio2_set827C(u32 value); +u32 sio2_get827C(); + +void sio2_fifoIn(u8 value); +u8 sio2_fifoOut(); + +void psxDma11(u32 madr, u32 bcr, u32 chcr); +void psxDma12(u32 madr, u32 bcr, u32 chcr); + +int psxDMA11Interrupt(); +int psxDMA12Interrupt(); +int sio2Freeze(gzFile f, int Mode); + +#endif /* __PSXSIO2_H__ */ + diff --git a/branches/pcsx2_0.9.1/R3000A.c b/branches/pcsx2_0.9.1/R3000A.c new file mode 100644 index 0000000..7e9d442 --- /dev/null +++ b/branches/pcsx2_0.9.1/R3000A.c @@ -0,0 +1,214 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" + +// used for constant propagation +R3000Acpu *psxCpu; +u32 g_psxConstRegs[32]; +u32 g_psxHasConstReg, g_psxFlushedConstReg; + +__declspec(align(16)) psxRegisters psxRegs; + +int psxInit() +{ + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + +#ifdef PCSX2_DEVBUILD + Log=0; +#endif + + if (psxMemInit() == -1) return -1; + + return psxCpu->Init(); +} + +void psxReset() { + + psxCpu->Reset(); + + psxMemReset(); + + memset(&psxRegs, 0, sizeof(psxRegs)); + + psxRegs.pc = 0xbfc00000; // Start in bootstrap + + psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1 + psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A + + psxHwReset(); + psxBiosInit(); + psxExecuteBios(); +} + +void psxShutdown() { + psxMemShutdown(); + psxBiosShutdown(); + + psxCpu->Shutdown(); +} + +void psxException(u32 code, u32 bd) { +// PSXCPU_LOG("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); +// SysPrintf("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); + // Set the Cause + psxRegs.CP0.n.Cause &= ~0x7f; + psxRegs.CP0.n.Cause |= code; + +#ifdef PSXCPU_LOG + if (bd) { PSXCPU_LOG("bd set\n"); } +#endif + // Set the EPC & PC + if (bd) { + psxRegs.CP0.n.Cause|= 0x80000000; + psxRegs.CP0.n.EPC = (psxRegs.pc - 4); + } else + psxRegs.CP0.n.EPC = (psxRegs.pc); + + if (psxRegs.CP0.n.Status & 0x400000) + psxRegs.pc = 0xbfc00180; + else + psxRegs.pc = 0x80000080; + + // Set the Status + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) | + ((psxRegs.CP0.n.Status & 0xf) << 2); + + /*if ((((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) { + // "hokuto no ken" / "Crash Bandicot 2" ... fix + PSXMu32(psxRegs.CP0.n.EPC)&= ~0x02000000; + }*/ + + if (Config.PsxOut && !CHECK_EEREC) { + u32 call = psxRegs.GPR.n.t1 & 0xff; + switch (psxRegs.pc & 0x1fffff) { + case 0xa0: +#ifdef PSXBIOS_LOG + if (call != 0x28 && call != 0xe) { + PSXBIOS_LOG("Bios call a0: %s (%x) %x,%x,%x,%x\n", biosA0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosA0[call]) + biosA0[call](); + break; + case 0xb0: +#ifdef PSXBIOS_LOG + if (call != 0x17 && call != 0xb) { + PSXBIOS_LOG("Bios call b0: %s (%x) %x,%x,%x,%x\n", biosB0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosB0[call]) + biosB0[call](); + break; + case 0xc0: +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("Bios call c0: %s (%x) %x,%x,%x,%x\n", biosC0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); +#endif + if (biosC0[call]) + biosC0[call](); + break; + } + } + + /*if (psxRegs.CP0.n.Cause == 0x400 && (!(psxHu32(0x1450) & 0x8))) { + hwIntcIrq(1); + }*/ +} + +#define PSX_TESTINT(n, callback) \ + if (psxRegs.interrupt & (1 << n)) { \ + if ((int)(psxRegs.cycle - psxRegs.sCycle[n]) >= psxRegs.eCycle[n]) { \ + if (callback() == 1) { \ + psxRegs.interrupt&= ~(1 << n); \ + } \ + } \ + else if( (int)(g_psxNextBranchCycle - psxRegs.sCycle[n]) > psxRegs.eCycle[n] ) \ + g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n]; \ + } + +static void _psxTestInterrupts() { + PSX_TESTINT(4, psxDma4Interrupt); + PSX_TESTINT(7, psxDma7Interrupt); + + PSX_TESTINT(11, psxDMA11Interrupt); // SIO2 + PSX_TESTINT(12, psxDMA12Interrupt); // SIO2 + PSX_TESTINT(16, sioInterrupt); + PSX_TESTINT(17, cdrInterrupt); + PSX_TESTINT(18, cdrReadInterrupt); + PSX_TESTINT(19, cdvdReadInterrupt); + PSX_TESTINT(20, dev9Interrupt); + PSX_TESTINT(21, usbInterrupt); +} + +#define IOP_WAIT_CYCLE 64 + +void psxBranchTest() +{ + EEsCycle -= (psxRegs.cycle - IOPoCycle) << 3; + IOPoCycle = psxRegs.cycle; + if( EEsCycle > 0 ) + g_psxNextBranchCycle = psxRegs.cycle + min(IOP_WAIT_CYCLE, (EEsCycle>>3)); + else + g_psxNextBranchCycle = psxRegs.cycle; + + if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + _psxTestInterrupts(); + } + +// if( (int)psxRegs.cycle-(int)g_psxNextBranchCycle > 0 ) +// g_psxNextBranchCycle = psxRegs.cycle+1; +// else + if( (int)(g_psxNextBranchCycle-psxNextsCounter) >= (u32)psxNextCounter ) + g_psxNextBranchCycle = (u32)psxNextsCounter+(u32)psxNextCounter; + + if (psxHu32(0x1078)) { + if(psxHu32(0x1070) & psxHu32(0x1074)){ + if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) { +//#ifdef PSXCPU_LOG +// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); +//#endif + psxException(0, 0); + } + } + } +} + +void psxExecuteBios() { +/* while (psxRegs.pc != 0x80030000) + psxCpu->ExecuteBlock(); +#ifdef PSX_LOG + PSX_LOG("*BIOS END*\n"); +#endif*/ +} + +void psxRestartCPU() +{ + psxCpu->Shutdown(); + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + + if (psxCpu->Init() == -1) { + SysClose(); + exit(1); + } + psxCpu->Reset(); +} diff --git a/branches/pcsx2_0.9.1/R3000A.h b/branches/pcsx2_0.9.1/R3000A.h new file mode 100644 index 0000000..be1f7f4 --- /dev/null +++ b/branches/pcsx2_0.9.1/R3000A.h @@ -0,0 +1,213 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#include + +extern u32 g_psxNextBranchCycle; + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*Clear)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R3000Acpu; + +extern R3000Acpu *psxCpu; +extern R3000Acpu psxInt; +extern R3000Acpu psxRec; + +typedef union { + struct { + u32 r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra, hi, lo; // hi needs to be at index 32! don't change + } n; + u32 r[34]; /* Lo, Hi in r[33] and r[32] */ +} GPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} CP0Regs; + +typedef struct { + short x, y; +} SVector2D; + +typedef struct { + short z, pad; +} SVector2Dz; + +typedef struct { + short x, y, z, pad; +} SVector3D; + +typedef struct { + short x, y, z, pad; +} LVector3D; + +typedef struct { + unsigned char r, g, b, c; +} CBGR; + +typedef struct { + short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad; +} SMatrix3D; + +typedef union { + struct { + SVector3D v0, v1, v2; + CBGR rgb; + s32 otz; + s32 ir0, ir1, ir2, ir3; + SVector2D sxy0, sxy1, sxy2, sxyp; + SVector2Dz sz0, sz1, sz2, sz3; + CBGR rgb0, rgb1, rgb2; + s32 reserved; + s32 mac0, mac1, mac2, mac3; + u32 irgb, orgb; + s32 lzcs, lzcr; + } n; + u32 r[32]; +} CP2Data; + +typedef union { + struct { + SMatrix3D rMatrix; + s32 trX, trY, trZ; + SMatrix3D lMatrix; + s32 rbk, gbk, bbk; + SMatrix3D cMatrix; + s32 rfc, gfc, bfc; + s32 ofx, ofy; + s32 h; + s32 dqa, dqb; + s32 zsf3, zsf4; + s32 flag; + } n; + u32 r[32]; +} CP2Ctrl; + +typedef struct { + GPRRegs GPR; /* General Purpose Registers */ + CP0Regs CP0; /* Coprocessor0 Registers */ + CP2Data CP2D; /* Cop2 data registers */ + CP2Ctrl CP2C; /* Cop2 control registers */ + u32 pc; /* Program counter */ + u32 code; /* The instruction */ + u32 cycle; + u32 interrupt; + u32 sCycle[64]; + u32 eCycle[64]; + u32 _msflag[32]; + u32 _smflag[32]; +} psxRegisters; + +extern psxRegisters psxRegs; + +#define PSX_IS_CONST1(reg) ((reg)<32 && (g_psxHasConstReg&(1<<(reg)))) +#define PSX_IS_CONST2(reg1, reg2) ((g_psxHasConstReg&(1<<(reg1)))&&(g_psxHasConstReg&(1<<(reg2)))) +#define PSX_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_psxHasConstReg |= (1<<(reg)); \ + g_psxFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define PSX_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_psxHasConstReg &= ~(1<<(reg)); \ +} + +extern u32 g_psxConstRegs[32]; +extern u32 g_psxHasConstReg, g_psxFlushedConstReg; + +#ifndef _PC_ + +#define _i32(x) (s32)x +#define _u32(x) x + +#define _i16(x) (short)x +#define _u16(x) (unsigned short)x + +#define _i8(x) (char)x +#define _u8(x) (unsigned char)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ psxRegs.pc // The next PC to be executed + +#define _Funct_ ((psxRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((psxRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((psxRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((psxRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((psxRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((unsigned short)psxRegs.code) // The immediate part of the instruction register +#define _Target_ (psxRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((short)psxRegs.code) // sign-extended immediate +#define _ImmU_ (psxRegs.code&0xffff) // zero-extended immediate + +#define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register +#define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register +#define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register +#define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register +#define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register + +#define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register +#define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register +#define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register +#define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register + +#define _rHi_ psxRegs.GPR.n.hi // The HI register +#define _rLo_ psxRegs.GPR.n.lo // The LO register + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Imm_ * 4) + _PC_) // Calculates the target during a branch instruction +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((short)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; + +#endif + +int psxInit(); +void psxReset(); +void psxShutdown(); +void psxException(u32 code, u32 step); +void psxBranchTest(); +void psxExecuteBios(); +void psxRestartCPU(); + +#endif /* __R3000A_H__ */ diff --git a/branches/pcsx2_0.9.1/R5900.c b/branches/pcsx2_0.9.1/R5900.c new file mode 100644 index 0000000..db6738e --- /dev/null +++ b/branches/pcsx2_0.9.1/R5900.c @@ -0,0 +1,506 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "Hw.h" +#include "Debug.h" +#include "R3000A.h" +#include "VUmicro.h" + +static int inter; + +__declspec(align(16)) cpuRegisters cpuRegs; +__declspec(align(16)) fpuRegisters fpuRegs; +__declspec(align(16)) tlbs tlb[48]; +__declspec(align(16)) GPR_reg64 g_cpuConstRegs[32] = {0}; +u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0; +R5900cpu *Cpu; + +int EEsCycle; +u32 EEoCycle, IOPoCycle; + +void ExecuteIOP() +{ + psxCpu->ExecuteBlock(); +} + +int cpuInit() +{ + int ret; + extern DWORD dwSaveVersion; + + SysPrintf("PCSX2 v" PCSX2_VERSION " save ver: %x\n", dwSaveVersion); + SysPrintf("Color Legend: White - PCSX2 message\n"); + SysPrintf(COLOR_GREEN " Green - EE sio2 printf\n" COLOR_RESET); + SysPrintf(COLOR_RED " Red - IOP printf\n" COLOR_RESET); + + InitFPUOps(); + cpudetectInit(); + + if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC; + else Config.Options &= ~PCSX2_COP2REC; + + cpuRegs.constzero = 0; + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + ret = Cpu->Init(); + if (ret == -1 && CHECK_EEREC) { + SysMessage(_("Error initializing Recompiler, switching to Interpreter")); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC); + Cpu = &intCpu; + ret = Cpu->Init(); + } + +#ifdef WIN32_VIRTUAL_MEM + if (memInit() == -1) { + PROCESS_INFORMATION pi; + STARTUPINFO si; + char strdir[255], strexe[255]; + if( MessageBox(NULL, "Failed to allocate enough physical memory to run pcsx2. Try closing\n" + "down background programs, restarting windows, or buying more memory.\n\n" + "Launch TLB version of pcsx2 (pcsx2t.exe)?", "Memory Allocation Error", MB_YESNO) == IDYES ) { + + GetCurrentDirectory(ARRAYSIZE(strdir), strdir); + _snprintf(strexe, ARRAYSIZE(strexe), "%s\\pcsx2t.exe", strdir); + + memset(&si, 0, sizeof(si)); + + if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) { + _snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe); + MessageBox(NULL, strdir, "Failure", MB_OK); + } + else { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + } + + return -1; + } +#endif + if (hwInit() == -1) return -1; + if (vu0Init() == -1) return -1; + if (vu1Init() == -1) return -1; +#ifndef WIN32_VIRTUAL_MEM + if (memInit() == -1) return -1; +#endif + +#ifdef PCSX2_DEVBUILD + Log = 0; +#endif + + return ret; +} + +void cpuReset() { + Cpu->Reset(); + + memReset(); + + memset(&cpuRegs, 0, sizeof(cpuRegs)); + memset(&fpuRegs, 0, sizeof(fpuRegs)); + memset(&tlb, 0, sizeof(tlb)); + + cpuRegs.pc = 0xbfc00000; ///set pc reg to stack + + cpuRegs.CP0.n.Status.val = 0x70400004; //0x10900000 <-- wrong; // COP0 enabled | BEV = 1 | TS = 1 + cpuRegs.CP0.n.PRid = 0x00002e20; // PRevID = Revision ID, same as R5900 + fpuRegs.fprc[0] = 0x00002e00; // fpu Revision.. + fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control + + vu0Reset(); + vu1Reset(); + hwReset(); + vif0Reset(); + vif1Reset(); + rcntInit(); + psxReset(); +} + +void cpuShutdown() +{ + hwShutdown(); +// biosShutdown(); + psxShutdown(); + vu0Shutdown(); + vu1Shutdown(); + memShutdown(); + gsShutdown(); + disR5900FreeSyms(); + + Cpu->Shutdown(); +} + +void cpuException(u32 code, u32 bd) { + u32 offset; + cpuRegs.CP0.n.Cause = code & 0xffff; + + if(cpuRegs.CP0.n.Status.b.ERL == 0){ //Error Level 0-1 + if(((code & 0x7C) >= 0x8) && ((code & 0x7C) <= 0xC)) offset = 0x0; //TLB Refill + else if ((code & 0x7C) == 0x0) offset = 0x200; //Interrupt + else offset = 0x180; // Everything else + + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.BEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } else { //Error Level 2 + SysPrintf("FIX ME: Level 2 cpuException\n"); + if((code & 0x38000) <= 0x8000 ) { //Reset / NMI + cpuRegs.pc = 0xBFC00000; + SysPrintf("Reset request\n"); + UpdateCP0Status(); + return; + } else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter + else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug + else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code); + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.DEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } + UpdateCP0Status(); +} + +void cpuTlbMiss(u32 addr, u32 bd, u32 excode) { + SysPrintf("cpuTlbMiss %x, %x, status=%x, code=%x\n", cpuRegs.pc, cpuRegs.cycle, cpuRegs.CP0.n.Status.val, excode); + if (bd) { + SysPrintf("branch delay!!\n"); + } + cpuRegs.CP0.n.BadVAddr = addr; + cpuRegs.CP0.n.Context &= 0xFF80000F; + cpuRegs.CP0.n.Context |= (addr >> 9) & 0x007FFFF0; + cpuRegs.CP0.n.EntryHi = (addr & 0xFFFFE000) | (cpuRegs.CP0.n.EntryHi & 0x1FFF); + + cpuRegs.CP0.n.Cause = excode; + if (!(cpuRegs.CP0.n.Status.val & 0x2)) { // EXL bit + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + } + + if ((cpuRegs.CP0.n.Status.val & 0x1) == 0) { + cpuRegs.pc = 0x80000000; + } else { + cpuRegs.pc = 0x80000180; + } + + cpuRegs.CP0.n.Status.b.EXL = 1; + UpdateCP0Status(); +// Log=1; varLog|= 0x40000000; +} + +void cpuTlbMissR(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBL); +} + +void cpuTlbMissW(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBS); +} + +void JumpCheckSym(u32 addr, u32 pc) { +#if 0 +// if (addr == 0x80051770) { SysPrintf("Log!: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); Log=1; varLog|= 0x40000000; } + if (addr == 0x8002f150) { SysPrintf("printk: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (addr == 0x8002aba0) return; + if (addr == 0x8002f450) return; + if (addr == 0x800dd520) return; +// if (addr == 0x80049300) SysPrintf("register_blkdev: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (addr == 0x8013cb70) { SysPrintf("change_root: %x\n", cpuRegs.GPR.n.a0.UL[0]); } +// if (addr == 0x8013d1e8) { SysPrintf("Log!\n"); Log++; if (Log==2) exit(0); varLog|= 0x40000000; } +// if (addr == 0x00234e88) { SysPrintf("StoreImage\n"); Log=1; /*psMu32(0x234e88) = 0x03e00008; psMu32(0x234e8c) = 0;*/ } +#endif +/* if ((pc >= 0x00131D50 && + pc < 0x00132454) || + (pc >= 0x00786a90 && + pc < 0x00786ac8))*/ + if (varLog & 0x40000000) { + char *str; + char *strf; + + str = disR5900GetSym(addr); + if (str != NULL) { + strf = disR5900GetUpperSym(pc); + if (strf) { + SysPrintf("Func %8.8x: %s (called by %8.8x: %s)\n", addr, str, pc, strf); + } else { + SysPrintf("Func %8.8x: %s (called by %x)\n", addr, str, pc); + } + if (!strcmp(str, "printf")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (!strcmp(str, "printk")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + } + } +} + +void JumpCheckSymRet(u32 addr) { + if (varLog & 0x40000000) { + char *str; + str = disR5900GetUpperSym(addr); + if (str != NULL) { + SysPrintf("Return : %s, v0=%8.8x\n", str, cpuRegs.GPR.n.v0.UL[0]); + } + } +} + +__inline void _cpuTestMissingINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 && + psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + SysPrintf("*PCSX2*: Error, missing INTC Interrupt\n"); + } + } +} + +__inline void _cpuTestMissingDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 && + (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)) { + if ((cpuRegs.interrupt & (1 << 31)) == 0) { + SysPrintf("*PCSX2*: Error, missing DMAC Interrupt\n"); + } + } +} + +void cpuTestMissingHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestMissingINTC(); + _cpuTestMissingDMAC(); +// _cpuTestTIMR(); + } +} + +#define TESTINT(n, callback) { \ + if ( (cpuRegs.interrupt & (1 << n)) ) { \ + if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \ + if (callback() == 1) { \ + cpuRegs.interrupt &= ~(1 << n); \ + } \ + } \ + else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \ + g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \ + } \ + } \ +} \ + +void _cpuTestInterrupts() { + + inter = cpuRegs.interrupt; + /* These are 'pcsx2 interrupts', they handle asynchronous stuff + that depends on the cycle timings */ + + TESTINT(0, vif0Interrupt); + TESTINT(10, vifMFIFOInterrupt); + TESTINT(1, vif1Interrupt); + TESTINT(11, gifMFIFOInterrupt); + TESTINT(2, gsInterrupt); + TESTINT(3, ipu0Interrupt); + TESTINT(4, ipu1Interrupt); + TESTINT(5, EEsif0Interrupt); + TESTINT(6, EEsif1Interrupt); + TESTINT(8, SPRFROMinterrupt); + TESTINT(9, SPRTOinterrupt); + + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + TESTINT(30, intcInterrupt); + TESTINT(31, dmacInterrupt); +} + +u32 s_iLastCOP0Cycle = 0; +static void _cpuTestTIMR() { + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + + if ( (cpuRegs.CP0.n.Status.val & 0x8000) && + cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { + SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); + cpuException(0x808000, cpuRegs.branch); + } +} + +#define EE_WAIT_CYCLE 512 + +// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates +u32 g_nextBranchCycle = 0; +u32 s_lastvsync[2]; +extern u8 g_globalXMMSaved, g_globalMMXSaved; +u32 loaded = 0; + +void cpuBranchTest() +{ + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 0; + +// if( !loaded && cpuRegs.cycle > 0x06000000 ) { +// char strstate[255]; +// sprintf(strstate, "sstates/%8.8x.000", ElfCRC); +// LoadState(strstate); +// loaded = 1; +// } + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + // don't need in svurec +// if (VU0.VI[REG_VPU_STAT].UL & 0x100) { +// Cpu->ExecuteVU1Block(); +// } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 1; +} + +static void _cpuTestINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 ){ + if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + INT(30,4); + } + } + } +} + +static void _cpuTestDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 ){ + if (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) { + if ( (cpuRegs.interrupt & (1 << 31)) == 0) { + INT(31, 4); + } + } + } +} + +void cpuTestHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + _cpuTestINTC(); + _cpuTestDMAC(); + _cpuTestTIMR(); +} + +void cpuTestINTCInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestINTC(); + } +} + +void cpuTestDMACInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestDMAC(); + } +} + +void cpuTestTIMRInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestTIMR(); + } +} + +extern BOOL bExecBIOS; +void cpuExecuteBios() { + SysPrintf("* PCSX2 *: ExecuteBios\n"); + + bExecBIOS = TRUE; + while (cpuRegs.pc != 0x00200008 && + cpuRegs.pc != 0x00100008) { + Cpu->ExecuteBlock(); + } + + bExecBIOS = FALSE; +// REC_CLEARM(0x00200008); +// REC_CLEARM(0x00100008); +// REC_CLEARM(cpuRegs.pc); + if( CHECK_EEREC ) Cpu->Reset(); + + SysPrintf("* PCSX2 *: ExecuteBios Complete\n"); + GSprintf(5, "PCSX2 v" PCSX2_VERSION "\nExecuteBios Complete\n"); +} + +void cpuRestartCPU() +{ + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + // restart vus + if (Cpu->Init() == -1) { + SysClose(); + exit(1); + } + + vu0Init(); + vu1Init(); + Cpu->Reset(); + psxRestartCPU(); +} + diff --git a/branches/pcsx2_0.9.1/R5900.h b/branches/pcsx2_0.9.1/R5900.h new file mode 100644 index 0000000..5834023 --- /dev/null +++ b/branches/pcsx2_0.9.1/R5900.h @@ -0,0 +1,276 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R5900_H__ +#define __R5900_H__ + +#include + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Step)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*ExecuteVU0Block)(); /* executes up to a jump */ + void (*ExecuteVU1Block)(); /* executes up to a jump */ + void (*EnableVU0micro)(int enable); + void (*EnableVU1micro)(int enable); + void (*Clear)(u32 Addr, u32 Size); + void (*ClearVU0)(u32 Addr, u32 Size); + void (*ClearVU1)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R5900cpu; + +extern R5900cpu *Cpu; +extern R5900cpu intCpu; +extern R5900cpu recCpu; + +typedef union { // Declare union type GPR register + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} GPR_reg; + +typedef union { + struct { + GPR_reg r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra; + } n; + GPR_reg r[32]; +} GPRregs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare; + union { + struct { + int IE:1; + int EXL:1; + int ERL:1; + int KSU:2; + int unused0:3; + int IM:8; + int EIE:1; + int _EDI:1; + int CH:1; + int unused1:3; + int BEV:1; + int DEV:1; + int unused2:2; + int FR:1; + int unused3:1; + int CU:4; + } b; + u32 val; + } Status; + u32 Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Debug, + DEPC, PerfCnt, ErrCtl, CacheErr, + TagLo, TagHi, ErrorEPC, DESAVE; + } n; + u32 r[32]; +} CP0regs; + +typedef struct { + GPRregs GPR; // GPR regs + // NOTE: don't change order since recompiler uses it + GPR_reg HI; + GPR_reg LO; // hi & log 128bit wide + CP0regs CP0; // is COP0 32bit? + u32 sa; // shift amount (32bit), needs to be 16 byte aligned + u32 constzero; // always 0, for MFSA + u32 pc; // Program counter + u32 code; // The instruction + u32 eCycle[32]; + u32 sCycle[32]; // for internal counters + u32 cycle; // calculate cpucycles.. + u32 interrupt; + int branch; + int opmode; // operating mode + u32 tempcycles; +} cpuRegisters; + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; +extern cpuRegisters cpuRegs; + +// used for optimization +typedef union { + u64 UD[1]; //64 bits + s64 SD[1]; + u32 UL[2]; + s32 SL[3]; + u16 US[4]; + s16 SS[4]; + u8 UC[8]; + s8 SC[8]; +} GPR_reg64; + +#define GPR_IS_CONST1(reg) ((reg)<32 && (g_cpuHasConstReg&(1<<(reg)))) +#define GPR_IS_CONST2(reg1, reg2) ((g_cpuHasConstReg&(1<<(reg1)))&&(g_cpuHasConstReg&(1<<(reg2)))) +#define GPR_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_cpuHasConstReg |= (1<<(reg)); \ + g_cpuFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define GPR_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_cpuHasConstReg &= ~(1<<(reg)); \ +} + +extern GPR_reg64 g_cpuConstRegs[32]; +extern u32 g_cpuHasConstReg, g_cpuFlushedConstReg; + +typedef union { + float f; + u32 UL; +} FPRreg; + +typedef struct { + FPRreg fpr[32]; // 32bit floating point registers + u32 fprc[32]; // 32bit floating point control registers + FPRreg ACC; // 32 bit accumulator +} fpuRegisters; + +extern fpuRegisters fpuRegs; + + +typedef struct { + u32 PageMask,EntryHi; + u32 EntryLo0,EntryLo1; + u32 Mask, nMask; + u32 G; + u32 ASID; + u32 VPN2; + u32 PFN0; + u32 PFN1; +} tlbs; + +extern tlbs tlb[48]; + +#ifndef _PC_ + +#define _i64(x) (s64)x +#define _u64(x) (u64)x + +#define _i32(x) (s32)x +#define _u32(x) (u32)x + +#define _i16(x) (s16)x +#define _u16(x) (u16)x + +#define _i8(x) (s8)x +#define _u8(x) (u8)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ cpuRegs.pc // The next PC to be executed + +#define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((u16)cpuRegs.code) // The immediate part of the instruction register +#define _Target_ (cpuRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((s16)cpuRegs.code) // sign-extended immediate +#define _ImmU_ (cpuRegs.code&0xffff) // zero-extended immediate + + +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) cpuRegs.GPR.r[x].UD[0] = _PC_ + 4; // Sets the return address in the link register + +#endif + +int cpuInit(); +void cpuReset(); +void cpuShutdown(); +void cpuException(u32 code, u32 bd); +void cpuTlbMissR(u32 addr, u32 bd); +void cpuTlbMissW(u32 addr, u32 bd); +void cpuBranchTest(); +void cpuTestHwInts(); +void cpuTestINTCInts(); +void cpuTestDMACInts(); +void cpuTestTIMRInts(); +void _cpuTestInterrupts(); +void cpuExecuteBios(); +void cpuRestartCPU(); + +u32 VirtualToPhysicalR(u32 addr); +u32 VirtualToPhysicalW(u32 addr); + +void intDoBranch(u32 target); +void intSetBranch(); +void intExecuteVU0Block(); +void intExecuteVU1Block(); + +void JumpCheckSym(u32 addr, u32 pc); +void JumpCheckSymRet(u32 addr); + +// check to see if needs freezing +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs ) { FreezeXMMRegs_(save); } + +//exception code +#define EXC_CODE(x) ((x)<<2) + +#define EXC_CODE_Int EXC_CODE(0) +#define EXC_CODE_Mod EXC_CODE(1) /* TLB Modification exception */ +#define EXC_CODE_TLBL EXC_CODE(2) /* TLB Miss exception (load or instruction fetch) */ +#define EXC_CODE_TLBS EXC_CODE(3) /* TLB Miss exception (store) */ +#define EXC_CODE_AdEL EXC_CODE(4) +#define EXC_CODE_AdES EXC_CODE(5) +#define EXC_CODE_IBE EXC_CODE(6) +#define EXC_CODE_DBE EXC_CODE(7) +#define EXC_CODE_Sys EXC_CODE(8) +#define EXC_CODE_Bp EXC_CODE(9) +#define EXC_CODE_Ri EXC_CODE(10) +#define EXC_CODE_CpU EXC_CODE(11) +#define EXC_CODE_Ov EXC_CODE(12) +#define EXC_CODE_Tr EXC_CODE(13) +#define EXC_CODE_FPE EXC_CODE(15) +#define EXC_CODE_WATCH EXC_CODE(23) +#define EXC_CODE__MASK 0x0000007c +#define EXC_CODE__SHIFT 2 + +#define EXC_TLB_STORE 1 +#define EXC_TLB_LOAD 0 + + +#endif /* __R5900_H__ */ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2.c b/branches/pcsx2_0.9.1/RDebug/deci2.c new file mode 100644 index 0000000..49add6e --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2.c @@ -0,0 +1,26 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +void exchangeSD(DECI2_HEADER *h){ + u8 tmp =h->source; + h->source =h->destination; + h->destination =tmp; +} diff --git a/branches/pcsx2_0.9.1/RDebug/deci2.h b/branches/pcsx2_0.9.1/RDebug/deci2.h new file mode 100644 index 0000000..80cbe13 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2.h @@ -0,0 +1,66 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2_H__ +#define __DECI2_H__ + +#include "Common.h" +#include "deci2_dcmp.h" +#include "deci2_iloadp.h" +#include "deci2_dbgp.h" +#include "deci2_netmp.h" +#include "deci2_ttyp.h" + +#define PROTO_DCMP 0x0001 +#define PROTO_ITTYP 0x0110 +#define PROTO_IDBGP 0x0130 +#define PROTO_ILOADP 0x0150 +#define PROTO_ETTYP 0x0220 +#define PROTO_EDBGP 0x0230 +#define PROTO_NETMP 0x0400 + + +#pragma pack(1) +typedef struct tag_DECI2_HEADER{ + u16 length, //+00 + _pad, //+02 + protocol; //+04 + char source, //+06 + destination;//+07 +} DECI2_HEADER; //=08 + +typedef struct tag_DECI2_DBGP_BRK{ + u32 address, //+00 + count; //+04 +} DECI2_DBGP_BRK; //=08 +#pragma pack() + +#define STOP 0 +#define RUN 1 + +extern DECI2_DBGP_BRK ebrk[32], ibrk[32]; +extern int ebrk_count, ibrk_count; +extern int runStatus, runCode, runCount; +extern HANDLE runEvent; //i don't like this; +extern int connected; + //when add linux code this might change + +int writeData(char *result); +void exchangeSD(DECI2_HEADER *h); + +#endif//__DECI2_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2.txt b/branches/pcsx2_0.9.1/RDebug/deci2.txt new file mode 100644 index 0000000..8cf7221 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2.txt @@ -0,0 +1,27 @@ +pcsx2 log->debugger tty mapping +Ŀ +Bios EE 0 IOP Bios +CPU & MMI & COP0 & FPU EE 1 IOP IOP cpu +VU0 & VUMicro EE 2 IOP HW +VIF EE 3 IOP GTE +GIF EE 4 IOP GPU +DMA EE 5 IOP DMA +HW & Unknown Memory EE 6 IOP Unknown Memory +ELF & Scratch pad EE 7 IOP PAD +IPU EE 8 IOP CDR +SIF & RPC services EE 9 IOP + +SysMessage EEKernelIOP SysMessage + +PRODG: 230,130, 120,121,122,110-119,11F,210-219,21F,410 +CW: 230,130,150,120,121, 210-219,21F,110-119,11F + +0400 PROTO_NETMP +0001 PROTO_DCMP + PROTO_MTWKS +012? PROTO_DRFP (%s) +0230 PROTO_ESDBG +0130 PROTO_ISDBG +011? PROTO_I%dTTY +021? PROTO_E%dTTY + diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.c b/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.c new file mode 100644 index 0000000..5ff8dc5 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.c @@ -0,0 +1,410 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "VUmicro.h" +#include "deci2.h" + +typedef struct tag_DECI2_DBGP_HEADER{ + DECI2_HEADER h; //+00 + u16 id; //+08 + u8 type, //+0A + code, //+0B + result, //+0C + count; //+0D + u16 _pad; //+0E +} DECI2_DBGP_HEADER; //=10 + +typedef struct tag_DECI2_DBGP_CONF{ + u32 major_ver, //+00 + minor_ver, //+04 + target_id, //+08 + _pad, //+0C + mem_align, //+10 + _pad2, //+14 + reg_size, //+18 + nreg, //+1C + nbrkpt, //+20 + ncont, //+24 + nstep, //+28 + nnext, //+2C + mem_limit_align, //+30 + mem_limit_size, //+34 + run_stop_state, //+38 + hdbg_area_addr, //+3C + hdbg_area_size; //+40 +} DECI2_DBGP_CONF; //=44 + +DECI2_DBGP_CONF +cpu={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu0={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu1={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 32, 1, 0x00, 0x00, 0x07, 0x200, 1, 0x0001E670, 0x100}; +//iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 0, 1, 0x00, 0x00, 0x07, 0x200, 0, 0x00006940, 0x100}; + +#pragma pack(2) +typedef struct tag_DECI2_DBGP_EREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u64 value[2]; //+04 +} DECI2_DBGP_EREG; //=14 + +typedef struct tag_DECI2_DBGP_IREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u32 value; //+04 +} DECI2_DBGP_IREG; //=08 + +typedef struct tag_DECI2_DBGP_MEM{ + u8 space, //+00 + align; //+01 + u16 _pad; //+02 + u32 address; //+04 + u32 length; //+08 +} DECI2_DBGP_MEM; //=0C + +typedef struct tag_DECI2_DBGP_RUN{ + u32 entry, //+00 + gp, //+04 + _pad, //+08 + _pad1, //+0C + argc; //+10 + u32 argv[0]; //+14 +} DECI2_DBGP_RUN; //=14 +#pragma pack() + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy){ + DECI2_DBGP_HEADER *in=(DECI2_DBGP_HEADER*)inbuffer, + *out=(DECI2_DBGP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DBGP_HEADER); + DECI2_DBGP_EREG *eregs=(DECI2_DBGP_EREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_IREG *iregs=(DECI2_DBGP_IREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_MEM *mem =(DECI2_DBGP_MEM*) ((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_RUN *run =(DECI2_DBGP_RUN*) ((u8*)in+sizeof(DECI2_DBGP_HEADER)); + static char line[1024]; + int i, s; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + //out->h.length=sizeof(DECI2_DBGP_HEADER); + out->type++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->type){ + case 0x00://ok + sprintf(line, "%s/GETCONF", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I'){ + memcpy(data, &iop, sizeof(DECI2_DBGP_CONF)); + }else + switch(in->id){ + case 0:memcpy(data, &cpu, sizeof(DECI2_DBGP_CONF));break; + case 1:memcpy(data, &vu0, sizeof(DECI2_DBGP_CONF));break; + case 2:memcpy(data, &vu1, sizeof(DECI2_DBGP_CONF));break; + } + break; + case 0x02://ok + sprintf(line, "%s/2", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + break; + case 0x04://ok + sprintf(line, "%s/GETREG count=%d kind[0]=%d number[0]=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:iregs[i].value=psxRegs.GPR.n.lo;break; + case 1:iregs[i].value=psxRegs.GPR.n.hi;break; + } + break; + case 2:iregs[i].value=psxRegs.GPR.r[iregs[i].number]; break; + case 3: + if (iregs[i].number==14) psxRegs.CP0.n.EPC=psxRegs.pc; + iregs[i].value=psxRegs.CP0.r[iregs[i].number]; + break; + case 6:iregs[i].value=psxRegs.CP2D.r[iregs[i].number]; break; + case 7:iregs[i].value=psxRegs.CP2C.r[iregs[i].number]; break; + default: + iregs[0].value++;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(eregs[i].value, &cpuRegs.GPR.r[eregs[i].number], 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(eregs[i].value, &cpuRegs.HI.UD[0], 8);break; + case 1:memcpy(eregs[i].value, &cpuRegs.LO.UD[0], 8);break; + case 2:memcpy(eregs[i].value, &cpuRegs.HI.UD[1], 8);break; + case 3:memcpy(eregs[i].value, &cpuRegs.LO.UD[1], 8);break; + case 4:memcpy(eregs[i].value, &cpuRegs.sa, 4); break; + } + case 2: + if (eregs[i].number==14) cpuRegs.CP0.n.EPC=cpuRegs.pc; + memcpy(eregs[i].value, &cpuRegs.CP0.r[eregs[i].number], 4); + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(eregs[i].value, &fpuRegs.fpr[eregs[i].number], 4);break; + case 6:memcpy(eregs[i].value, &fpuRegs.fprc[eregs[i].number], 4);break; + case 7:memcpy(eregs[i].value, &VU0.VF[eregs[i].number], 16);break; + case 8:memcpy(eregs[i].value, &VU0.VI[eregs[i].number], 4);break; + case 9:memcpy(eregs[i].value, &VU1.VF[eregs[i].number], 16);break; + case 10:memcpy(eregs[i].value, &VU1.VI[eregs[i].number], 4);break; + default: + eregs[0].value[0]++;//dummy; might be assert(0) + } + break; + case 0x06://ok + sprintf(line, "%s/PUTREG count=%d kind[0]=%d number[0]=%d value=%016I64X_%016I64X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number, eregs[0].value[1], eregs[0].value[0]); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:psxRegs.GPR.n.lo=iregs[i].value;break; + case 1:psxRegs.GPR.n.hi=iregs[i].value;break; + } + break; + case 2:psxRegs.GPR.r[iregs[i].number]=iregs[i].value; break; + case 3: + psxRegs.CP0.r[iregs[i].number]=iregs[i].value; + if (iregs[i].number==14) psxRegs.pc=psxRegs.CP0.n.EPC; + break; + case 6:psxRegs.CP2D.r[iregs[i].number]=iregs[i].value; break; + case 7:psxRegs.CP2C.r[iregs[i].number]=iregs[i].value; break; + default: + ;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(&cpuRegs.GPR.r[eregs[i].number], eregs[i].value, 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(&cpuRegs.HI.UD[0], eregs[i].value, 8);break; + case 1:memcpy(&cpuRegs.LO.UD[0], eregs[i].value, 8);break; + case 2:memcpy(&cpuRegs.HI.UD[1], eregs[i].value, 8);break; + case 3:memcpy(&cpuRegs.LO.UD[1], eregs[i].value, 8);break; + case 4:memcpy(&cpuRegs.sa, eregs[i].value, 4); break; + } + break; + case 2: + memcpy(&cpuRegs.CP0.r[eregs[i].number], eregs[i].value, 4); + if (eregs[i].number==14) cpuRegs.pc=cpuRegs.CP0.n.EPC; + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(&fpuRegs.fpr[eregs[i].number], eregs[i].value, 4);break; + case 6:memcpy(&fpuRegs.fprc[eregs[i].number], eregs[i].value, 4);break; + case 7:memcpy(&VU0.VF[eregs[i].number], eregs[i].value, 16);break; + case 8:memcpy(&VU0.VI[eregs[i].number], eregs[i].value, 4);break; + case 9:memcpy(&VU1.VF[eregs[i].number], eregs[i].value, 16);break; + case 10:memcpy(&VU1.VI[eregs[i].number], eregs[i].value, 4);break; + default: + ;//dummy; might be assert(0) + } + break; + case 0x08://ok + sprintf(line, "%s/RDMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)out+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSXM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(data, PSM(mem->address), mem->length); + else + if ((((mem->address & 0x1FFFFFFF)>128*1024*1024) || ((mem->address & 0x1FFFFFFF)<32*1024*1024)) && PSM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(data, &VU0.Mem[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Mem[mem->address & 0x3FFF], mem->length); + break; + case 2: + if (in->id==1) + memcpy(data, &VU0.Micro[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Micro[mem->address & 0x3FFF], mem->length); + break; + } + out->h.length=mem->length+data-(u8*)out; + break; + case 0x0a://ok + sprintf(line, "%s/WRMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)in+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if (mem->length==4 && *(int*)data==0x0000000D) + strcat(line, " BREAKPOINT"); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(PSXM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(PSM(mem->address), data, mem->length); + else + if (PSM(mem->address & 0x1FFFFFFF)) + memcpy(PSM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(&VU0.Mem[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Mem[mem->address & 0x3FFF], data, mem->length); + break; + case 2: + if (in->id==1) + memcpy(&VU0.Micro[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Micro[mem->address & 0x3FFF], data, mem->length); + break; + } + out->h.length=sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM); + break; + case 0x10://ok + sprintf(line, "%s/GETBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I') memcpy(data, ibrk, out->count=ibrk_count); + else memcpy(data, ebrk, out->count=ebrk_count); + out->h.length=sizeof(DECI2_DBGP_HEADER)+out->count*sizeof(DECI2_DBGP_BRK); + break; + case 0x12://ok [does not break on iop brkpts] + sprintf(line, "%s/PUTBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + out->h.length=sizeof(DECI2_DBGP_HEADER); + if (in->count>32){ + out->result=1; + strcat(line, "TOO MANY"); + break; + } + if (in->h.destination=='I') memcpy(ibrk, data, ibrk_count=in->count); + else memcpy(ebrk, data, ebrk_count=in->count); + out->count=0; + break; + case 0x14://ok, [w/o iop] + sprintf(line, "%s/BREAK count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + if (in->h.destination=='I') + ; + else{ + out->result = ( InterlockedExchange(&runStatus, STOP)==STOP ? + 0x20 : 0x21 ); + out->code=0xFF; + Sleep(50); + } + break; + case 0x16://ok, [w/o iop] + sprintf(line, "%s/CONTINUE code=%s count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", + in->code==0?"CONT":in->code==1?"STEP":"NEXT", in->count); + if (in->h.destination=='I') + ; + else{ + InterlockedExchange(&runStatus, STOP); + Sleep(100);//first get the run thread to Wait state + runCount=in->count; + runCode=in->code; + SetEvent(runEvent);//kick it + } + break; + case 0x18://ok [without argc/argv stuff] + sprintf(line, "%s/RUN code=%d count=%d entry=0x%08X gp=0x%08X argc=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->code, in->count, + run->entry, run->gp, run->argc); + cpuRegs.CP0.n.EPC=cpuRegs.pc=run->entry; + cpuRegs.GPR.n.gp.UL[0]=run->gp; +// threads_array[0].argc = run->argc; + for (i=0, s=0; i<(int)run->argc; i++) s+=run->argv[i]; + memcpy(PSM(0), &run->argv[run->argc], s); +// threads_array[0].argstring = 0; + InterlockedExchange(&runStatus, STOP); + Sleep(1000);//first get the run thread to Wait state + runCount=0; + runCode=0xFF; + SetEvent(runEvent);//awake it + out->h.length=sizeof(DECI2_DBGP_HEADER); + break; + default: + sprintf(line, "type=0x%02X code=%d count=%d [unknown]", in->type, in->code, in->count); + } + sprintf(message, "[DBGP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + sprintf(eepc, "%08X", cpuRegs.pc); + sprintf(ioppc, "%08X", psxRegs.pc); + sprintf(eecy, "%d", cpuRegs.cycle); + sprintf(iopcy, "%d", psxRegs.cycle); + writeData(outbuffer); +} + +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count){ + static DECI2_DBGP_HEADER tmp; + tmp.h.length =sizeof(DECI2_DBGP_HEADER); + tmp.h._pad =0; + tmp.h.protocol =( source=='E' ? PROTO_EDBGP : PROTO_IDBGP ); + tmp.h.source =source; + tmp.h.destination='H'; + tmp.id =id; + tmp.type =0x15; + tmp.code =code; + tmp.result =result; + tmp.count =count; + tmp._pad =0; + writeData((char*)&tmp); +} diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.h b/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.h new file mode 100644 index 0000000..ab28c21 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_dbgp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DBGP_H__ +#define __DECI2DBGP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy); +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count); + +#endif//__DECI2DBGP_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.c b/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.c new file mode 100644 index 0000000..9348040 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.c @@ -0,0 +1,83 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +typedef struct tag_DECI2_DCMP_CONNECT{ + u8 result, //+00 + _pad[3];//+01 + u64 EEboot, //+04 + IOPboot;//+0C +} DECI2_DCMP_CONNECT; //=14 + +typedef struct tag_DECI2_DCMP_ECHO{ + u16 identifier, //+00 + sequence; //+02 + u8 data[32]; //+04 +} DECI2_DCMP_ECHO; //=24 + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + DECI2_DCMP_CONNECT *connect=(DECI2_DCMP_CONNECT*)data; + DECI2_DCMP_ECHO *echo =(DECI2_DCMP_ECHO*)data; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ +/* case 0: + sprintf(message, " [DCMP] type=CONNECT code=%s EEboot=0x%I64X IOP=0x%I64X", + in->code==0?"CONNECT":"DISCONNECT", connect->EEboot, connect->IOPboot); + data=(u8*)out+sizeof(DECI2_DCMP_HEADER); + connect=(DECI2_DCMP_CONNECT*)data; + connect->result=0; + break; + case 1: + sprintf(message, " [DCMP] type=ECHO id=%X seq=%X", echo->identifier, echo->sequence); + exchangeSD(&out->h); + break; +// not implemented, not needed? + default: + sprintf(message, " [DCMP] type=%d[unknown]", in->type); +*/ } + out->code++; +} + +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size){ + static char tmp[100]; + ((DECI2_DCMP_HEADER*)tmp)->h.length =sizeof(DECI2_DCMP_HEADER)+size; + ((DECI2_DCMP_HEADER*)tmp)->h._pad =0; + ((DECI2_DCMP_HEADER*)tmp)->h.protocol =protocol; + ((DECI2_DCMP_HEADER*)tmp)->h.source =source; + ((DECI2_DCMP_HEADER*)tmp)->h.destination=destination; + ((DECI2_DCMP_HEADER*)tmp)->type =type; + ((DECI2_DCMP_HEADER*)tmp)->code =code; + ((DECI2_DCMP_HEADER*)tmp)->_pad =0; + memcpy(&tmp[sizeof(DECI2_DCMP_HEADER)], data, size); + writeData(tmp); +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.h b/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.h new file mode 100644 index 0000000..18e2c80 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_dcmp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DCMP_H__ +#define __DECI2DCMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message); +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size); + +#endif//__DECI2DCMP_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_drfp.c b/branches/pcsx2_0.9.1/RDebug/deci2_drfp.c new file mode 100644 index 0000000..dff6076 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_drfp.c @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ + case 4://[OK] + sprintf(message, " [DCMP] code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + break; + default: + sprintf(message, " [DCMP] code=%d[unknown] result=%d", netmp->code, netmp->result); + } + result->code++; + result->result=0; //ok +} diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_drfp.h b/branches/pcsx2_0.9.1/RDebug/deci2_drfp.h new file mode 100644 index 0000000..eb90970 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_drfp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DRFP_H__ +#define __DECI2DRFP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2DRFP_H__ \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.c b/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.c new file mode 100644 index 0000000..d761e8b --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.c @@ -0,0 +1,106 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "PsxBios2.h" +#include "deci2.h" + +typedef struct tag_DECI2_ILOADP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 cmd + action, //+09 + result, //+0A + stamp; //+0B + u32 moduleId; //+0C +} DECI2_ILOADP_HEADER; //=10 + +typedef struct tag_DECI2_ILOADP_INFO{ + u16 version, //+00 + flags; //+02 + u32 module_address, //+04 + text_size, //+08 + data_size, //+0C + bss_size, //+10 + _pad[3]; //+14 +} DECI2_ILOADP_INFO; + +void writeInfo(DECI2_ILOADP_INFO *info, + u16 version, u16 flags, u32 module_address, + u32 text_size, u32 data_size, u32 bss_size){ + info->version =version; + info->flags =flags; + info->module_address=module_address; + info->text_size =text_size; + info->data_size =data_size; + info->bss_size =bss_size; + info->_pad[0]=info->_pad[1]=info->_pad[2]=0; +} + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message){ + DECI2_ILOADP_HEADER *in=(DECI2_ILOADP_HEADER*)inbuffer, + *out=(DECI2_ILOADP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_ILOADP_HEADER); + irxImageInfo *iii; + static char line[1024]; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_ILOADP_HEADER); + out->code++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->code){ + case 0: + sprintf(line, "code=START action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 2: + sprintf(line, "code=REMOVE action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 4: + sprintf(line, "code=LIST action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for (iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0, data+=4) + *(u32*)data=iii->index; + + out->h.length=data-(u8*)out; + break; + case 6: + sprintf(line, "code=INFO action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for(iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0) + if (iii->index==in->moduleId){ + writeInfo((DECI2_ILOADP_INFO*)data, + iii->version, iii->flags, iii->vaddr, iii->text_size, iii->data_size, iii->bss_size); + data+=sizeof(DECI2_ILOADP_INFO); + strcpy(data, PSXM(iii->name)); + data+=strlen(PSXM(iii->name))+4; + data=(char*)((int)data & 0xFFFFFFFC); + break; + + } + out->h.length=data-(u8*)out; + break; + case 8: + sprintf(line, "code=WATCH action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + default: + sprintf(line, "code=%d[unknown]", in->code); + } + sprintf(message, "[ILOADP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + writeData(outbuffer); +} diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.h b/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.h new file mode 100644 index 0000000..a55b046 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_iloadp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2ILOADP_H__ +#define __DECI2ILOADP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2ILOADP_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_netmp.c b/branches/pcsx2_0.9.1/RDebug/deci2_netmp.c new file mode 100644 index 0000000..472dfc5 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_netmp.c @@ -0,0 +1,134 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_NETMP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 + result; //+09 +} DECI2_NETMP_HEADER; //=0A + +typedef struct tag_DECI2_NETMP_CONNECT{ + u8 priority, //+00 + _pad; //+01 + u16 protocol; //+02 +} DECI2_NETMP_CONNECT; //=04 + +char d2_message[100]; +int d2_count=1; +DECI2_NETMP_CONNECT d2_connect[50]={0xFF, 0, 0x400}; + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_NETMP_HEADER *in=(DECI2_NETMP_HEADER*)inbuffer, + *out=(DECI2_NETMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_NETMP_HEADER); + DECI2_NETMP_CONNECT *connect=(DECI2_NETMP_CONNECT*)data; //connect + int i, n; + static char p[100], line[1024]; + u64 EEboot, IOPboot; //reset + u16 node; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_NETMP_HEADER); + out->code++; + out->result=0; //ok + switch(in->code){ + case 0: + n=(in->h.length-sizeof(DECI2_NETMP_HEADER)) / sizeof(DECI2_NETMP_CONNECT); + sprintf(line, "code=CONNECT"); + for (i=0; ih.length=data-(u8*)out; + writeData(outbuffer); + + node=(u16)'I'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=(u16)'E'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=PROTO_ILOADP; + sendDCMP(PROTO_DCMP, 'I', 'H', 2, 1, (char*)&node, sizeof(node)); + + for (i=0; i<10; i++){ + node=PROTO_ETTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + } + node=PROTO_ETTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + break; + case 4://[OK] + sprintf(line, "code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + writeData(outbuffer); + break; + case 6://[ok] + sprintf(line, "code=STATUS"); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER)+2; + /* + memcpy(data, d2_connect, 1*sizeof(DECI2_NETMP_CONNECT)); + data+=1*sizeof(DECI2_NETMP_CONNECT); + *(u32*)data=1;//quite fast;) + data+=4; + memcpy(data, d2_message, strlen(d2_message)); + data+=strlen(d2_message); + *(u32*)data=0;//null end the string on a word boundary + data+=3;data=(u8*)((int)data & 0xFFFFFFFC);*/ + + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + case 8: + sprintf(line, "code=KILL protocol=0x%04X", *(u16*)data); + writeData(outbuffer); + break; + case 10: + sprintf(line, "code=VERSION %s", data); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER); + strcpy(data, "0.2.0");data+=strlen("0.2.0");//emu version;) + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + default: + sprintf(line, "code=%d[unknown] result=%d", in->code, in->result); + writeData(outbuffer); + } + sprintf(message, "[NETMP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); +} diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_netmp.h b/branches/pcsx2_0.9.1/RDebug/deci2_netmp.h new file mode 100644 index 0000000..7440278 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_netmp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2NETMP_H__ +#define __DECI2NETMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2NETMP_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.c b/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.c new file mode 100644 index 0000000..ce66e2f --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.c @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_TTYP_HEADER{ + DECI2_HEADER h; //+00 + u32 flushreq; //+08 + u8 data[0]; //+0C +} DECI2_TTYP_HEADER; //=0C + +void sendTTYP(u16 protocol, u8 source, char *data){ + static char tmp[2048]; + ((DECI2_TTYP_HEADER*)tmp)->h.length =sizeof(DECI2_TTYP_HEADER)+strlen(data); + ((DECI2_TTYP_HEADER*)tmp)->h._pad =0; + ((DECI2_TTYP_HEADER*)tmp)->h.protocol =protocol +(source=='E' ? PROTO_ETTYP : PROTO_ITTYP); + ((DECI2_TTYP_HEADER*)tmp)->h.source =source; + ((DECI2_TTYP_HEADER*)tmp)->h.destination='H'; + ((DECI2_TTYP_HEADER*)tmp)->flushreq =0; + if (((DECI2_TTYP_HEADER*)tmp)->h.length>2048) + SysMessage("TTYP: Buffer overflow"); + else + memcpy(&tmp[sizeof(DECI2_TTYP_HEADER)], data, strlen(data)); + //writeData(tmp); +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.h b/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.h new file mode 100644 index 0000000..8d27146 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/deci2_ttyp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2TTYP_H__ +#define __DECI2TTYP_H__ + +#include "Common.h" +#include "deci2.h" + +//void D2_(char *inbuffer, char *outbuffer, char *message); +void sendTTYP(u16 protocol, u8 source, char *data); + +#endif//__DECI2TTYP_H__ diff --git a/branches/pcsx2_0.9.1/RDebug/iloadp.txt b/branches/pcsx2_0.9.1/RDebug/iloadp.txt new file mode 100644 index 0000000..c8b6c68 --- /dev/null +++ b/branches/pcsx2_0.9.1/RDebug/iloadp.txt @@ -0,0 +1,32 @@ +ILOADP_MODULE_INFO{ + u16 flags Ŀ <Ŀ + u16 version < + u32 addr + u32 sz_text + u32 sz_data + u32 sz_bss + u32 reserved1 + u32 reserved2 + u32 reserved3 + u8* name +}; + +ILOADP_HDR{ + u8 cmd + u8 action + u8 result + u8 stamp + u32 module_id +}; + +ILOADP_START(cmd==00) +------------------------------------------ +ILOADP_HDR_START{ + ILOADP_HDR hdr //+00 + u8* modulename //+10 //asciiz +}; //=10+strlen(modulename)+1 +action 0D(IOP_LOAD_IRX) +modulename host:E:\TEMP2\GCC\share\SIO2D.IRX + +action 02(IOP_RUN) +modulename E:\TEMP2\GCC\share\SIO2D.IRX param diff --git a/branches/pcsx2_0.9.1/SPR.c b/branches/pcsx2_0.9.1/SPR.c new file mode 100644 index 0000000..0b3a7dd --- /dev/null +++ b/branches/pcsx2_0.9.1/SPR.c @@ -0,0 +1,385 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "SPR.h" + +#include "ir5900.h" + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) + +void sprInit() { +} + +//__inline static void SPR0transfer(u32 *data, int size) { +///* while (size > 0) { +//#ifdef SPR_LOG +// SPR_LOG("SPR1transfer: %x\n", *data); +//#endif +// data++; size--; +// }*/ +// size <<= 2; +// if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO +// (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO +// hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } else { +// u32 * p = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; +// //WriteCodeSSE2(p,data,size >> 4); +// memcpy_amd((u8*)data, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } +// spr0->sadr+= size; +//} + +static void TestClearVUs(u32 madr, u32 size) +{ + if( madr >= 0x11000000 ) { + if( madr < 0x11004000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu0\n"); +#endif + Cpu->ClearVU0(madr&0xfff, size); + } + else if( madr >= 0x11008000 && madr < 0x1100c000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu1\n"); +#endif + Cpu->ClearVU1(madr&0x3fff, size); + } + } +} + +int _SPR0chain() { + u32 qwc = spr0->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr0->madr); + if (pMem == NULL) return -1; + + //SPR0transfer(pMem, qwc << 2); + qwc <<= 4; + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr = psHu32(DMAC_RBOR) + ((spr0->madr + qwc) & (psHu32(DMAC_RBSR))); //Wrap MADR + } else { + Cpu->Clear(spr0->madr, qwc>>2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr += qwc; + } + spr0->sadr += qwc; + + spr0->qwc = 0; + return (qwc>>4) * BIAS; // bus is 1/2 the ee speed +} + +#define SPR0chain() \ + if (spr0->qwc) { \ + cycles += _SPR0chain(); \ +/* cycles+= spr0->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR0interleave() { + int qwc = spr0->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + //SysPrintf("dmaSPR0 interleave\n"); + + while (qwc > 0) { + spr0->qwc = min(tqwc, qwc); qwc-= spr0->qwc; + pMem = (u32*)dmaGetAddr(spr0->madr); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } else { + Cpu->Clear(spr0->madr, spr0->qwc<<2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } + cycles += tqwc * BIAS; + spr0->sadr+= spr0->qwc * 16; + spr0->madr+= (sqwc+spr0->qwc)*16; //qwc-= sqwc; + } + + spr0->qwc = 0; + INT(8, cycles); +} + +void _dmaSPR0() { + u32 *ptag; + int id; + int cycles = 0; + int done = 0; + + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR0 stall %d\n", (psHu32(DMAC_CTRL)>>6)&3); + } + + if ((spr0->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR0interleave(); + return; + } + + // Transfer Dn_QWC from SPR to Dn_MADR + SPR0chain(); + + + if ((spr0->chcr & 0xc) == 0) { // Normal Mode + + INT(8, cycles); + + return; + } + + // Destination Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; + spr0->sadr+= 16; + + // Transfer dma tag if tte is set +// if (spr0->chcr & 0x40) SPR0transfer(ptag, 4); + + spr0->chcr = ( spr0->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr0->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR stall control\n"); + } + + switch (id) { + case 0: // CNTS - Transfer QWC following the tag (Stall Control) + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20 ) psHu32(DMAC_STADR) = spr0->madr; //Copy MADR to DMAC_STADR stall addr register + break; + + case 1: // CNT - Transfer QWC following the tag. + break; + + case 7: // End - Transfer QWC following the tag + done = 1; //End Transfer + break; + } + SPR0chain(); + if (spr0->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag + //SysPrintf("SPR0 TIE\n"); + done = 1; + spr0->qwc = 0; + break; + } + + +/* if (spr0->chcr & 0x80 && ptag[0] >> 31) { +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return; + }*/ + } + + INT(8, cycles); + +} + +int SPRFROMinterrupt() +{ + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return 1; +} + +void dmaSPR0() { // fromSPR + int qwc = spr0->qwc; +#ifdef SPR_LOG + SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx\n", + spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); +#endif + + _dmaSPR0(); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) { // GIF MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & (psHu32(DMAC_RBSR))); + mfifoGIFtransfer(qwc); + } else + if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & (psHu32(DMAC_RBSR))); + mfifoVIF1transfer(qwc); + } + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +__inline static void SPR1transfer(u32 *data, int size) { +/* { + int i; + for (i=0; isadr+i*4) & 0x3fff, data[i] ); +#endif + } + }*/ + //Cpu->Clear(spr1->sadr, size); // why? + memcpy_amd(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2); + + spr1->sadr+= size << 2; +} + +int _SPR1chain() { + u32 qwc = spr1->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr1->madr); + if (pMem == NULL) return -1; + + SPR1transfer(pMem, qwc << 2); + spr1->madr+= spr1->qwc << 4; + spr1->qwc = 0; + return (qwc) * BIAS; +} + +#define SPR1chain() \ + if (spr1->qwc) { \ + cycles += _SPR1chain(); \ +/* cycles+= spr1->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR1interleave() { + int qwc = spr1->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + + //SysPrintf("dmaSPR1 interleave\n"); + + while (qwc > 0) { + spr1->qwc = min(tqwc, qwc); qwc-= spr1->qwc; + pMem = (u32*)dmaGetAddr(spr1->madr); + SPR1transfer(pMem, spr1->qwc << 2); + cycles += spr1->qwc * BIAS; + spr1->madr+= (sqwc + spr1->qwc) * 16; //qwc-= sqwc; + } + + spr1->qwc = 0; + INT(9, cycles); + +} + +void dmaSPR1() { // toSPR + u32 *ptag; + int id, done=0; + int cycles = 0; + +#ifdef SPR_LOG + SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" + " tadr = 0x%x, sadr = 0x%x\n", + spr1->chcr, spr1->madr, spr1->qwc, + spr1->tadr, spr1->sadr); +#endif + + if ((spr1->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR1interleave(); + FreezeMMXRegs(0); + return; + } + + // Transfer Dn_QWC from Dn_MADR to SPR1 + SPR1chain(); + + if ((spr1->chcr & 0xc) == 0) { // Normal Mode + + INT(9, cycles); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + + // Transfer dma tag if tte is set + if (spr1->chcr & 0x40) { +#ifdef SPR_LOG + SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + SPR1transfer(ptag, 4); //Transfer Tag + } + + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr1->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr1->qwc, id, spr1->madr); +#endif + + done = hwDmacSrcChain(spr1, id); + SPR1chain(); //Transfers the data set by the switch + + if (spr1->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("SPR1 TIE\n"); + spr1->qwc = 0; + break; + } + } + + + INT(9, cycles); + FreezeMMXRegs(0); +} + +int SPRTOinterrupt() +{ + spr1->chcr &= ~0x100; + hwDmacIrq(9); + return 1; +} + diff --git a/branches/pcsx2_0.9.1/SPR.h b/branches/pcsx2_0.9.1/SPR.h new file mode 100644 index 0000000..7ae0a57 --- /dev/null +++ b/branches/pcsx2_0.9.1/SPR.h @@ -0,0 +1,29 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPR_H__ +#define __SPR_H__ + +#include "Common.h" + +void sprInit(); +void dmaSPR0(); +void dmaSPR1(); +int SPRFROMinterrupt(); +int SPRTOinterrupt(); +#endif /* __SPR_H__ */ diff --git a/branches/pcsx2_0.9.1/Sif.c b/branches/pcsx2_0.9.1/Sif.c new file mode 100644 index 0000000..51701f7 --- /dev/null +++ b/branches/pcsx2_0.9.1/Sif.c @@ -0,0 +1,616 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "Sif.h" +#include "Sifcmd.h" + +#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000]) +#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) +#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) + +#define FIFO_SIF0_W 128 +#define FIFO_SIF1_W 128 + +typedef struct { + u32 fifoData[FIFO_SIF0_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; + struct sifData sifData; +} _sif0; + +typedef struct { + u32 fifoData[FIFO_SIF1_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; +} _sif1; + +_sif0 sif0; +_sif1 sif1; + +int sifInit() { + memset(&sif0, 0, sizeof(sif0)); + memset(&sif1, 0, sizeof(sif1)); + + return 0; +} + +void SIF0write(u32 *from, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoWritePos)) { + int wP0 = (FIFO_SIF0_W-sif0.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif0.fifoData[0], &from[wP0], wP1 << 2); + sif0.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, words << 2); + sif0.fifoWritePos += words; + } + + sif0.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 + %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoWritePos); +#endif + +/* if (sif0.fifoSize == FIFO_SIF0_W) { + Cpu->ExecuteBlock(); + }*/ +} + +void SIF0read(u32 *to, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoReadPos)) + { + int wP0 = (FIFO_SIF0_W-sif0.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif0.fifoData[0], wP1 << 2); + sif0.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], words << 2); + sif0.fifoReadPos += words; + } + + sif0.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 - %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoReadPos); +#endif +} + +void SIF1write(u32 *from, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoWritePos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif1.fifoData[0], &from[wP0], wP1 << 2); + sif1.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, words << 2); + sif1.fifoWritePos += words; + } + + sif1.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 + %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoWritePos); +#endif + +/* if (sif1.fifoSize == FIFO_SIF1_W) { + psxCpu->ExecuteBlock(); + }*/ +} + +void SIF1read(u32 *to, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoReadPos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif1.fifoData[0], wP1 << 2); + sif1.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], words << 2); + sif1.fifoReadPos += words; + } + + sif1.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 - %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoReadPos); +#endif +} + +void SIF0Dma() +{ + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + +#ifdef SIF_LOG + SIF_LOG("SIF0 DMA start...\n"); +#endif + + do + { + notDone = 0; + + if(HW_DMA9_CHCR & 0x01000000) // If EE SIF0 is enabled + { + int size = sif0.counter; //HW_DMA9_BCR >> 16; + + if(size == 0) // If there's no more to transfer + { + // Note.. add normal mode here + if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA + { +#ifdef SIF_LOG + SIF_LOG(" IOP SIF Stopped\n"); +#endif + + // Stop & signal interrupts on IOP + HW_DMA9_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + sif0.sifData.data = 0; + } + else if(FIFO_SIF1_W-sif0.fifoSize >= 2) // Chain mode + { + // Process DMA tag at HW_DMA9_TADR + sif0.sifData = *(struct sifData *)PSXM(HW_DMA9_TADR); + + sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4. + + SIF0write((u32*)PSXM(HW_DMA9_TADR+8), 4); + + //psxCycles += 2; + + HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF; + HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2; + //HW_DMA9_BCR = (sif0.sifData.words << 16) | 1; + sif0.counter = sif0.sifData.words & 0xFFFFFF; + notDone = 1; + +#ifdef SIF_LOG + SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)\n", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.sifData.words, sif0.sifData.data); +#endif + if(sif0.sifData.data & 0x40000000) + { +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + } + else + { +#ifdef SIF_LOG + SIF_LOG(" CNT %08X, %08X\n", sif0.sifData.data, sif0.sifData.words); +#endif + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int wTransfer = sif0.counter; // HW_DMA9_BCR >> 16; + + if (wTransfer > (FIFO_SIF0_W-sif0.fifoSize)) + wTransfer = (FIFO_SIF0_W-sif0.fifoSize); + +#ifdef SIF_LOG + SIF_LOG("+++++++++++ %lX of %lX\n", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/ ); +#endif + + SIF0write((u32*)PSXM(HW_DMA9_MADR), wTransfer); + HW_DMA9_MADR += wTransfer << 2; + //HW_DMA9_BCR = (HW_DMA9_BCR & 0xFFFF) | (((HW_DMA9_BCR >> 16) - wTransfer)<<16); + //psxCycles += (wTransfer / 4) * BIAS; + sif0.counter -= wTransfer; + + notDone = 1; + } + } + + if(sif0dma->chcr & 0x100) // If EE SIF enabled and there's something to transfer + { + int size = sif0dma->qwc; + if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) { // STS == fromSIF0 + SysPrintf("SIF0 stall control\n"); + } + if(size > 0) // If we're reading something continue to do so + { + if(sif0.fifoSize > 0) + { + int readSize = size; + + if(readSize > (sif0.fifoSize/4)) + readSize = (sif0.fifoSize/4); + + //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X\n", readSize, sif0dma->madr); +#ifdef SIF_LOG + SIF_LOG("----------- %lX of %lX\n", readSize << 2, size << 2 ); +#endif + + _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); + + SIF0read((u32*)ptag, readSize*4); + Cpu->Clear(sif0dma->madr, readSize*4); + + //cycles += readSize * BIAS; + sif0dma->qwc -= readSize; + sif0dma->madr += readSize << 4; + + notDone = 1; + } + } + else + { + if(sif0.chain && sif0dma->chcr & 0x80000000) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" EE SIF interrupt\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.end) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" EE SIF end\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.fifoSize >= 4) // Read a tag + { + __declspec(align(16)) static u32 tag[4]; + SIF0read((u32*)&tag[0], 4); // Tag + + sif0dma->qwc = (u16)tag[0]; + sif0dma->madr = tag[1]; + sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000); + +#ifdef SIF_LOG + SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)\n", sif0dma->madr, sif0dma->qwc, (tag[0]>>28)&3, (tag[0]>>31)&1, tag[1], tag[0]); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) != 0)psHu32(DMAC_STADR) = sif0dma->madr; + notDone = 1; + sif0.chain = 1; + if(tag[0] & 0x40000000) + sif0.end = 1; + + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +void SIF1Dma() +{ + int id; + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + + do + { + notDone = 0; + + if(sif1dma->chcr & 0x100) // If EE SIF1 is enabled + { + if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0) { // STS == fromSIF1 + SysPrintf("SIF1 stall control\n"); + } + + if(sif1dma->qwc == 0) // If there's no more to transfer + { + if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA + { + // Stop & signal interrupts on EE + sif1dma->chcr &= ~0x100; + hwDmacIrq(6); + sif1.chain = 0; + sif1.end = 0; + } + else // Chain mode + { + // Process DMA tag at sif1dma->tadr + notDone = 1; + _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); + sif1dma->chcr = ( sif1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); // Copy the tag + sif1dma->qwc = (u16)ptag[0]; + + if (sif1dma->chcr & 0x40) { + SysPrintf("SIF1 TTE\n"); + SIF1write(ptag+2, 2); + } + + sif1.chain = 1; + id = (ptag[0] >> 28) & 0x7; + + switch(id) + { + case 0: // refe +#ifdef SIF_LOG + SIF_LOG(" REFE %08X\n", ptag[1]); +#endif + sif1.end = 1; + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 1: // cnt +#ifdef SIF_LOG + SIF_LOG(" CNT\n"); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + case 2: // next +#ifdef SIF_LOG + SIF_LOG(" NEXT %08X\n", ptag[1]); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = ptag[1]; + break; + + case 3: // ref + case 4: // refs +#ifdef SIF_LOG + SIF_LOG(" REF %08X\n", ptag[1]); +#endif + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 7: // end +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + sif1.end = 1; + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + default: + SysPrintf("Bad addr1 source chain\n"); + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int qwTransfer = sif1dma->qwc; + u32 *data; + + notDone = 1; + + _dmaGetAddr(sif1dma, data, sif1dma->madr, 6); + + if(qwTransfer > (FIFO_SIF1_W-sif1.fifoSize)/4) // Copy part of sif1dma into FIFO + qwTransfer = (FIFO_SIF1_W-sif1.fifoSize)/4; + + SIF1write(data, qwTransfer << 2); + + sif1dma->madr += qwTransfer << 4; + //cycles += qwTransfer * BIAS; + sif1dma->qwc -= qwTransfer; + } + } + + if(HW_DMA10_CHCR & 0x01000000 ) // If IOP SIF enabled and there's something to transfer + { + int size = sif1.counter; + + if(size > 0) // If we're reading something continue to do so + { + if(sif1.fifoSize > 0) + { + int readSize = size; + + if(readSize > sif1.fifoSize) + readSize = sif1.fifoSize; + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF doing transfer %04X to %08X\n", readSize, HW_DMA10_MADR); +#endif + + SIF1read((u32*)PSXM(HW_DMA10_MADR), readSize); + psxCpu->Clear(HW_DMA10_MADR, readSize); + //psxCycles += readSize / 4; + sif1.counter = size-readSize; + HW_DMA10_MADR += readSize << 2; + notDone = 1; + } + } + + if(size <= 0 || sif1.fifoSize == 0) + { + if(sif1.tagMode & 0x80) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" IOP SIF interrupt\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.tagMode & 0x40) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" IOP SIF end\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.fifoSize >= 4) // Read a tag + { + struct sifData d; + + SIF1read((u32*)&d, 4); + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d\n", d.data & 0xffffff, d.words, (d.data>>28)&7, (d.data>>31)&1); +#endif + HW_DMA10_MADR = d.data & 0xffffff; + sif1.counter = d.words; + sif1.tagMode = (d.data >> 24) & 0xFF; + notDone = 1; + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +int sif0Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(9, 0x800); + return 0; + }*/ + + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int sif1Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(10, 0x800); + return 0; + }*/ + + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int EEsif0Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<5)) { + INT(5, 0x800); + return 0; + }*/ + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + + return 1; +} + +int EEsif1Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<6)) { + INT(6, 0x800); + return 0; + }*/ + hwDmacIrq(6); + + return 1; +} + +void dmaSIF0() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr); +#endif + + if (sif0.fifoReadPos != sif0.fifoWritePos) { + SysPrintf("warning, sif0.fifoReadPos != sif0.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x2000; + if(sif0dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + hwIntcIrq(INTC_SBUS); + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void dmaSIF1() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr); +#endif + + if (sif1.fifoReadPos != sif1.fifoWritePos) { + SysPrintf("warning, sif1.fifoReadPos != sif1.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x4000; + if(sif1dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void dmaSIF2() { + +#ifdef SIF_LOG + SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx\n", + sif2dma->chcr, sif2dma->madr, sif2dma->qwc); +#endif + + sif2dma->chcr&= ~0x100; + hwDmacIrq(7); + SysPrintf("*PCSX2*: dmaSIF2\n"); +} + + +int sifFreeze(gzFile f, int Mode) { + gzfreeze(&sif0, sizeof(sif0)); + gzfreeze(&sif1, sizeof(sif1)); + return 0; +} diff --git a/branches/pcsx2_0.9.1/Sif.h b/branches/pcsx2_0.9.1/Sif.h new file mode 100644 index 0000000..e381605 --- /dev/null +++ b/branches/pcsx2_0.9.1/Sif.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIF_H__ +#define __SIF_H__ + +#include "Common.h" + +struct sifData{ + int data, + words, + count, + addr; +}; + +int eeSifTransfer; + +DMACh *sif0ch; +DMACh *sif1ch; +DMACh *sif2ch; + +int sifInit(); +void SIF0Dma(); +void SIF1Dma(); +void dmaSIF0(); +void dmaSIF1(); +void dmaSIF2(); +int EEsif1Interrupt(); +int EEsif0Interrupt(); +int EEsif2Interrupt(); +int sifFreeze(gzFile f, int Mode); + + +#endif /* __SIF_H__ */ diff --git a/branches/pcsx2_0.9.1/Sifcmd.h b/branches/pcsx2_0.9.1/Sifcmd.h new file mode 100644 index 0000000..b953fed --- /dev/null +++ b/branches/pcsx2_0.9.1/Sifcmd.h @@ -0,0 +1,193 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIFCMD_H__ +#define __SIFCMD_H__ + +/* from sifcmd.h */ + +#define SYSTEM_CMD 0x80000000 + +struct t_sif_cmd_header +{ + u32 size; + void *dest; + int command; + u32 unknown; +}; + +struct t_sif_dma_transfer +{ + void *src, + *dest; + int size; + int attr; +}; + +struct t_sif_handler +{ + void (*handler) ( void *a, void *b); + void *buff; +}; + +#define SYSTEM_CMD_CHANGE_SADDR 0x80000000 +#define SYSTEM_CMD_INIT_CMD 0x80000002 +struct t_sif_saddr{ + struct t_sif_cmd_header hdr; //+00 + void *newaddr; //+10 +}; //=14 + +#define SYSTEM_CMD_SET_SREG 0x80000001 +struct t_sif_sreg{ + struct t_sif_cmd_header hdr; //+00 + int index; //+10 + unsigned int value; //+14 +}; //=18 + +#define SYSTEM_CMD_RESET 0x80000003 +struct t_sif_reset{ + struct t_sif_cmd_header hdr; //+00 + int size, //+10 + flag; //+14 + char data[80]; //+18 +}; //=68 + +/* end of sifcmd.h */ + +/* from sifsrpc.h */ + +struct t_sif_rpc_rend +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_client_data *client; /* 7 */ + u32 command; /* 8 */ + struct t_rpc_server_data *server; /* 9 */ + void *buff, /* 10 */ + *buff2; /* 11 */ +}; + +struct t_sif_rpc_other_data +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_receive_data *receive; /* 07 */ + void *src; /* 08 */ + void *dest; /* 09 */ + int size; /* 10 */ +}; + +struct t_sif_rpc_bind +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ +}; + +struct t_sif_rpc_call +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ + int send_size; /* 09 */ + void *receive; /* 10 */ + int rec_size; /* 11 */ + int has_async_ef; /* 12 */ + struct t_rpc_server_data *server; /* 13 */ +}; + +struct t_rpc_server_data +{ + int command; /* 04 00 */ + + void * (*func)(u32, void *, int); /* 05 01 */ + void *buff; /* 06 02 */ + int size; /* 07 03 */ + + void * (*func2)(u32, void *, int); /* 08 04 */ + void *buff2; /* 09 05 */ + int size2; /* 10 06 */ + + struct t_rpc_client_data *client; /* 11 07 */ + void *pkt_addr; /* 12 08 */ + int rpc_number; /* 13 09 */ + + void *receive; /* 14 10 */ + int rec_size; /* 15 11 */ + int has_async_ef; /* 16 12 */ + int rec_id; /* 17 13 */ + + struct t_rpc_server_data *link; /* 18 14 */ + struct r_rpc_server_data *next; /* 19 15 */ + struct t_rpc_data_queue *queued_object; /* 20 16 */ +}; + + +struct t_rpc_header +{ + void *pkt_addr; /* 04 00 */ + u32 rpc_id; /* 05 01 */ + int sema_id; /* 06 02 */ + u32 mode; /* 07 03 */ +}; + + +struct t_rpc_client_data +{ + struct t_rpc_header hdr; + u32 command; /* 04 08 */ + void *buff, /* 05 09 */ + *buff2; /* 06 10 */ + void (*end_function) ( void *); /* 07 11 */ + void *end_param; /* 08 12*/ + struct t_rpc_server_data *server; /* 09 13 */ +}; + +struct t_rpc_receive_data +{ + struct t_rpc_header hdr; + void *src, /* 04 */ + *dest; /* 05 */ + int size; /* 06 */ +}; + +struct t_rpc_data_queue +{ + int thread_id, /* 00 */ + active; /* 01 */ + struct t_rpc_server_data *svdata_ref, /* 02 */ + *start, /* 03 */ + *end; /* 04 */ + struct t_rpc_data_queue *next; /* 05 */ +}; + +/* end of sifrpc.h */ + +#endif//__SIFCMD_H__ diff --git a/branches/pcsx2_0.9.1/Sio.c b/branches/pcsx2_0.9.1/Sio.c new file mode 100644 index 0000000..2104bf9 --- /dev/null +++ b/branches/pcsx2_0.9.1/Sio.c @@ -0,0 +1,566 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "PsxCommon.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + +const unsigned char buf1[] = {0x25, 0x46, 0x01, 0x31, 0x00, 0xA2, 0x11, 0x01, 0xE1};//{0x64, 0x23, 0x2, 0x43, 0x0, 0xa2, 0x11, 0x1, 0xb4}; +const unsigned char buf2[] = {0xC5, 0xBD, 0x66, 0x00, 0x59, 0x44, 0x01, 0x02, 0x00};//{0x6d, 0x21, 0x30, 0x0, 0x55, 0x19, 0x2, 0x2, 0x30}; +const unsigned char buf4[] = {0x02, 0x9A, 0x9E, 0x06, 0x6D, 0x3C, 0xF0, 0x7E, 0xDF};//{0xa3, 0x5d, 0x2f, 0xa2, 0xd8, 0x7c, 0x5b, 0x35, 0xb9}; +const unsigned char buff[] = {0xC2, 0x39, 0x6F, 0x27, 0xC8, 0xDF, 0x2A, 0x23, 0xAD};//{0xf3, 0x9b, 0x32, 0x87, 0x31, 0xda, 0x9d, 0x10, 0xbb}; +const unsigned char buf11[] = {0xA8, 0x42, 0x5D, 0x87, 0x65, 0x32, 0x6F, 0xE8, 0xE0};//{0x39, 0xd2, 0xb9, 0x5c, 0xcf, 0x31, 0x2d, 0x23, 0xfe}; +const unsigned char buf13[] = {0x46, 0x31, 0xFC, 0x97, 0xA8, 0x6D, 0xE2, 0x12, 0x29};//{0x20, 0x2e, 0xd7, 0x99, 0x92, 0x29, 0x4a, 0x12, 0xa3}; + +const unsigned char cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; +struct mc_command_0x26_tag mc_command_0x26= + {'+', 512, 16, 0x4000, 0x52, 'Z'};//sizeof()==11 + +// clk cycle byte +// 4us * 8bits = ((PSXCLK / 1000000) * 32) / BIAS; (linuzappz) +#define SIO_INT() PSX_INT(16, PSXCLK/250000); /*270;*/ + +void _ReadMcd(char *data, u32 adr, int size) { + ReadMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +void _SaveMcd(char *data, u32 adr, int size) { + SaveMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +unsigned char xor(unsigned char *buf, unsigned int length){ + register unsigned char i, x; + + for (x=0, i=0; i>13)+1, value); +#endif + } + sio.mc_command=value; + if (sio.mc_command!=0x21 && sio.mc_command!=0x22 && sio.mc_command!=0x23 && + (sio.mc_command!=0xF0) && (sio.mc_command!=0xF1) && (sio.mc_command!=0xF2)) { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + } + return; + case 99://as is... + sio.packetsize++; + sio.parp++; + switch(sio.mc_command) + { + case 0x21: + case 0x22: + case 0x23: + if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0; + if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8; + if (sio.parp==4)sio.sector|=(value & 0xFF)<<16; + if (sio.parp==5)sio.sector|=(value & 0xFF)<<24; + if (sio.parp==6) + { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X sio.sector 0x%04X\n", + ((sio.CtrlReg&0x2000)>>13)+1, sio.mc_command, sio.sector); +#endif + } + break; + case 0x27: + if(sio.parp==2) { + sio.terminator = value; + sio.buf[4] = value; + } + break; + case 0x28: + if(sio.parp == 2) { + sio.buf[2] = '+'; + if(value == 0) { + sio.buf[4] = 0xFF; + sio.buf[3] = sio.terminator; + }else{ + sio.buf[4] = 0x5A; + sio.buf[3] = sio.terminator; + } + } + break; + case 0x42: + if (sio.parp==2) { + sio.bufcount=5+value; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + sio.buf[sio.bufcount]=sio.terminator; + } else + if ((sio.parp>2) && (sio.parp>13)+1, value, xor(&sio.buf[3], sio.bufcount-5)); +#endif + } + } + break; + case 0x43: + if (sio.parp==2){ + sio.bufcount=value+5; + sio.buf[3]='+'; + _ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value); + if(sio.mode==2) { + int j; + for(j=0; j < value; j++) + sio.buf[4+j] = ~sio.buf[4+j]; + } + sio.k+=value; + sio.buf[sio.bufcount-1]=xor(&sio.buf[4], value); + sio.buf[sio.bufcount]=sio.terminator; + } + break; + case 0x82: + if(sio.parp==2) { + sio.buf[2]='+'; + sio.buf[3]=sio.terminator; + } + break; + case 0xF0: + if (sio.parp==2) + { + u32 flag=0; +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0xF0:0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + switch(value){ + case 1: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf1,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 2: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf2,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 4: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf4,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 6: + case 7: + case 11: + flag=0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + break;//IN + case 15: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buff,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 17: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf11,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 19: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf13,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + default: + sio.bufcount=4; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + } + + if ((sio.bufcount==13) && flag){ + sio.buf[sio.bufcount-1] = 0;//xor value for OUT data + sio.buf[3]='+'; + } + sio.buf[sio.bufcount]=sio.terminator; + } + break; + } + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + return; + } + + switch (sio.mtapst) { + case 0x1: + sio.packetsize++; + sio.parp = 1; + SIO_INT(); + switch(value) { + case 0x12: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x13: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x21: sio.mtapst = 2; sio.bufcount = 6; break; + } + sio.buf[sio.bufcount]='Z'; + sio.buf[sio.bufcount-1]='+'; + return; + case 0x2: + sio.packetsize++; + sio.parp++; + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + SIO_INT(); + return; + } + + switch (value) { + case 0x01: // start pad + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + + switch (sio.CtrlReg&0x2002) { + case 0x0002: sio.buf[0] = PAD1startPoll(1); break; + case 0x2002: sio.buf[0] = PAD2startPoll(2); break; + } + + sio.bufcount = 2; + sio.parp = 0; + sio.padst = 1; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x21: // start mtap + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio.mtapst = 1; + sio2.packet.recvVal1 = 0x1D100; // Mtap is not connected :) + SIO_INT(); + return; + + case 0x61: // start remote control sensor + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x81: // start memcard + sio.StatReg &= ~TX_EMPTY; + sio.StatReg |= RX_RDY; + memcpy(sio.buf, cardh, 4); + sio.parp = 0; + sio.bufcount = 3; + sio.mcdst = 1; + sio.packetsize = 1; + sio.rdwr = 0; + sio2.packet.recvVal1 = 0x1100; // Memcard1 is present + SIO_INT(); + return; + } +} + +void sioWriteCtrl16(unsigned short value) { + sio.CtrlReg = value & ~RESET_ERR; + if (value & RESET_ERR) sio.StatReg &= ~IRQ; + if ((sio.CtrlReg & SIO_RESET) || (!sio.CtrlReg)) { + sio.mtapst = 0; sio.padst = 0; sio.mcdst = 0; sio.parp = 0; + sio.StatReg = TX_RDY | TX_EMPTY; + psxRegs.interrupt&= ~(1<<16); + } +} + +int sioInterrupt() { +#ifdef PAD_LOG + PAD_LOG("Sio Interrupt\n"); +#endif + sio.StatReg|= IRQ; + psxHu32(0x1070)|=0x80; + return 1; +} + +FILE *LoadMcd(int mcd) { + char str[256]; + FILE *f; + + if (mcd == 1) { + strcpy(str, Config.Mcd1); + } else { + strcpy(str, Config.Mcd2); + } + if (*str == 0) sprintf(str, "memcards/Mcd00%d.ps2", mcd); + f = fopen(str, "r+b"); + if (f == NULL) { + CreateMcd(str); + f = fopen(str, "r+b"); + } + if (f == NULL) { + SysMessage (_("Failed loading MemCard %s"), str); return NULL; + } + + return f; +} + +void SeekMcd(FILE *f, u32 adr) { + u32 size; + + fseek(f, 0, SEEK_END); size = ftell(f); + if (size == MCD_SIZE + 64) + fseek(f, adr + 64, SEEK_SET); + else if (size == MCD_SIZE + 3904) + fseek(f, adr + 3904, SEEK_SET); + else + fseek(f, adr, SEEK_SET); +} + +void ReadMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + memset(data, 0, size); + return; + } + SeekMcd(f, adr); + fread(data, 1, size, f); + fclose(f); +} + +void SaveMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + return; + } + SeekMcd(f, adr); + fwrite(data, 1, size, f); + fclose(f); +} + +void CreateMcd(char *mcd) { + FILE *fp; + int i=0, j=0; + int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + + fp = fopen(mcd, "wb"); + if (fp == NULL) return; + for(i=0; i < 16384; i++) + { + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 16; j++) fputc(enc[j],fp); + } + fclose(fp); +} + +int sioFreeze(gzFile f, int Mode) { + gzfreeze(&sio, sizeof(sio)); + + return 0; +} + + diff --git a/branches/pcsx2_0.9.1/Sio.h b/branches/pcsx2_0.9.1/Sio.h new file mode 100644 index 0000000..816bfac --- /dev/null +++ b/branches/pcsx2_0.9.1/Sio.h @@ -0,0 +1,114 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _SIO_H_ +#define _SIO_H_ + +typedef struct { + u16 StatReg; + u16 ModeReg; + u16 CtrlReg; + u16 BaudReg; + + u8 buf[256]; + u32 bufcount; + u32 parp; + u32 mcdst,rdwr; + u8 adrH,adrL; + u32 padst; + u32 mtapst; + u32 packetsize; + + u8 terminator; + u8 mode; + u8 mc_command; + u32 lastsector; + u32 sector; + u32 k; +} _sio; +_sio sio; + +#define MCD_SIZE (1024 * 8 * 16) +#define MC2_SIZE (1024 * 528 * 16) + +// Status Flags +#define TX_RDY 0x0001 +#define RX_RDY 0x0002 +#define TX_EMPTY 0x0004 +#define PARITY_ERR 0x0008 +#define RX_OVERRUN 0x0010 +#define FRAMING_ERR 0x0020 +#define SYNC_DETECT 0x0040 +#define DSR 0x0080 +#define CTS 0x0100 +#define IRQ 0x0200 + +// Control Flags +#define TX_PERM 0x0001 +#define DTR 0x0002 +#define RX_PERM 0x0004 +#define BREAK 0x0008 +#define RESET_ERR 0x0010 +#define RTS 0x0020 +#define SIO_RESET 0x0040 + +int Mcd1Size, Mcd2Size; + +int sioInit(); +void sioShutdown(); +unsigned char sioRead8(); +void sioWrite8(unsigned char value); +void sioWriteCtrl16(unsigned short value); +int sioInterrupt(); +int sioFreeze(gzFile f, int Mode); + +FILE *LoadMcd(int mcd); +void ReadMcd(int mcd, char *data, u32 adr, int size); +void SaveMcd(int mcd, char *data, u32 adr, int size); +void CreateMcd(char *mcd); + +typedef struct { + char Title[48]; + char ID[14]; + char Name[16]; + int IconCount; + short Icon[16*16*3]; + unsigned char Flags; +} McdBlock; + +#ifdef __WIN32__ +#pragma pack(1) +#endif +struct mc_command_0x26_tag{ + u8 field_151; //+02 flags + u16 sectorSize; //+03 divide to it + u16 field_2C; //+05 divide to it + u32 mc_size; //+07 + u8 xor; //+0b don't forget to recalculate it!!! + u8 Z; //+0c +#ifdef __WIN32__ +}; +#pragma pack() +#else +} __attribute__((packed)); +#endif + +void GetMcdBlockInfo(int mcd, int block, McdBlock *info); + +#endif diff --git a/branches/pcsx2_0.9.1/Stats.c b/branches/pcsx2_0.9.1/Stats.c new file mode 100644 index 0000000..1b3d439 --- /dev/null +++ b/branches/pcsx2_0.9.1/Stats.c @@ -0,0 +1,70 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "PsxCommon.h" + +void statsOpen() { + stats.vsyncCount = 0; + stats.vsyncTime = time(NULL); + stats.eeCycles = 0; + stats.eeSCycle = 0; + stats.iopCycles = 0; + stats.iopSCycle = 0; +} + +void statsClose() { + time_t t; + FILE *f; + + t = time(NULL) - stats.vsyncTime; +#ifdef __WIN32__ + f = fopen("logs\\stats.txt", "w"); +#else + f = fopen("logs/stats.txt", "w"); +#endif + if (!f) { SysPrintf("Can't open stats.txt\n"); return; } + fprintf(f, "-- PCSX2 v%s statics--\n\n", PCSX2_VERSION); + fprintf(f, "Ran for %d seconds\n", t); + fprintf(f, "Total VSyncs: %d (%s)\n", stats.vsyncCount, Config.PsxType ? "PAL" : "NTSC"); +#ifndef __x86_64__ + fprintf(f, "VSyncs per Seconds: %g\n", (double)stats.vsyncCount / t); +#endif + fprintf(f, "Total EE Instructions Executed: %lld\n", stats.eeCycles); + fprintf(f, "Total IOP Instructions Executed: %lld\n", stats.iopCycles); + if (!CHECK_EEREC) fprintf(f, "Interpreter Mode\n"); + else fprintf(f, "Recompiler Mode: VUrec1 %s, VUrec0 %s\n", + CHECK_VU1REC ? "Enabled" : "Disabled", CHECK_VU0REC ? "Enabled" : "Disabled"); + fclose(f); +} + +void statsVSync() { + static u64 accum = 0, accumvu1 = 0; + static u32 frame = 0; + + stats.eeCycles+= cpuRegs.cycle - stats.eeSCycle; + stats.eeSCycle = cpuRegs.cycle; + stats.iopCycles+= psxRegs.cycle - stats.iopSCycle; + stats.iopSCycle = psxRegs.cycle; + stats.vsyncCount++; + stats.vif1count = 0; + stats.vu1count = 0; +} diff --git a/branches/pcsx2_0.9.1/Stats.h b/branches/pcsx2_0.9.1/Stats.h new file mode 100644 index 0000000..a914e6b --- /dev/null +++ b/branches/pcsx2_0.9.1/Stats.h @@ -0,0 +1,43 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __STATS_H__ +#define __STATS_H__ + +#include + +typedef struct { + time_t vsyncTime; + u32 vsyncCount; + u32 eeCycles; + u32 eeSCycle; + u32 iopCycles; + u32 iopSCycle; + + u32 ticko; + u32 framecount; + u32 vu1count; + u32 vif1count; +} Stats; +Stats stats; + +void statsOpen(); +void statsClose(); +void statsVSync(); + +#endif /* __STATS_H__ */ diff --git a/branches/pcsx2_0.9.1/System.h b/branches/pcsx2_0.9.1/System.h new file mode 100644 index 0000000..a425b93 --- /dev/null +++ b/branches/pcsx2_0.9.1/System.h @@ -0,0 +1,59 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +int SysInit(); // Init mem and plugins +void SysReset(); // Resets mem +void SysPrintf(char *fmt, ...); // Printf used by bios syscalls +void SysMessage(char *fmt, ...); // Message used to print msg to users +void SysUpdate(); // Called on VBlank (to update i.e. pads) +void SysRunGui(); // Returns to the Gui +void SysClose(); // Close mem and plugins +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void *SysMmap(uptr base, u32 size); +void SysMunmap(uptr base, u32 size); + +#ifdef WIN32_VIRTUAL_MEM +typedef struct _PSMEMORYBLOCK +{ + ULONG_PTR NumberPages; + ULONG_PTR* aPFNs; + ULONG_PTR* aVFNs; // virtual pages that own the physical pages +} PSMEMORYBLOCK; + +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock); +void SysPhysicalFree(PSMEMORYBLOCK* pblock); +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualFree(void* lpMemReserved, u32 size); + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualProtectFree(void* lpMemReserved, u32 size); + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray); + +// call to enable physical page allocation +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); + +#endif + +#endif /* __SYSTEM_H__ */ diff --git a/branches/pcsx2_0.9.1/VU.h b/branches/pcsx2_0.9.1/VU.h new file mode 100644 index 0000000..572222a --- /dev/null +++ b/branches/pcsx2_0.9.1/VU.h @@ -0,0 +1,174 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU_H__ +#define __VU_H__ + +#define REG_STATUS_FLAG 16 +#define REG_MAC_FLAG 17 +#define REG_CLIP_FLAG 18 +#define REG_ACC_FLAG 19 // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) +#define REG_R 20 +#define REG_I 21 +#define REG_Q 22 +#define REG_P 23 //only exists in micromode +#define REG_VF0_FLAG 24 // dummy flag that indicates VF0 is read (nothing to do with VI[24]) +#define REG_TPC 26 +#define REG_CMSAR0 27 +#define REG_FBRST 28 +#define REG_VPU_STAT 29 +#define REG_CMSAR1 31 + +enum VUStatus { + VU_Ready = 0, + VU_Run = 1, + VU_Stop = 2, +}; + +typedef union { + struct { + float x,y,z,w; + } f; + struct { + u32 x,y,z,w; + } i; + + float F[4]; + + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} VECTOR; + +typedef union { + float F; + s32 SL; + u32 UL; + s16 SS[2]; + u16 US[2]; + s8 SC[4]; + u8 UC[4]; +} REG_VI; + +#define VUFLAG_BREAKONMFLAG 0x00000001 +#define VUFLAG_MFLAGSET 0x00000002 + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; + u32 statusflag; +} fdivPipe; + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; +} efuPipe; + +typedef struct { + int enable; + int reg; + int xyzw; + u32 sCycle; + u32 Cycle; + u32 macflag; + u32 statusflag; + u32 clipflag; +} fmacPipe; + +typedef struct { + VECTOR VF[32]; + REG_VI VI[32]; + VECTOR ACC; + REG_VI q; + REG_VI p; + + u32 macflag; + u32 statusflag; + u32 clipflag; + + u32 cycle; + u32 flags; + + void (*vuExec)(void*); + VIFregisters *vifRegs; + + u8 *Mem; + u8 *Micro; + + u32 code; + u32 maxmem; + u32 maxmicro; + + u16 branch; + u16 ebit; + u32 branchpc; + + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + +} VURegs; + +#define VUPIPE_NONE 0 +#define VUPIPE_FMAC 1 +#define VUPIPE_FDIV 2 +#define VUPIPE_EFU 3 +#define VUPIPE_IALU 4 +#define VUPIPE_BRANCH 5 +#define VUPIPE_XGKICK 6 + +#define VUREG_READ 0x1 +#define VUREG_WRITE 0x2 + +typedef struct { + u8 pipe; // if 0xff, COP2 + u8 VFwrite; + u8 VFwxyzw; + u8 VFr0xyzw; + u8 VFr1xyzw; + u8 VFread0; + u8 VFread1; + u32 VIwrite; + u32 VIread; + int cycles; +} _VURegsNum; + +extern VURegs* g_pVU1; +extern VURegs VU0; + +#define VU1 (*g_pVU1) + +__forceinline u32* GET_VU_MEM(VURegs* VU, u32 addr) +{ + if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); + + if( addr >= 0x4200 ) return &VU1.VI[(addr>>2)&0x1f].UL; + + return (u32*)(VU0.Mem+(addr&0x0fff)); +} + +#endif /* __VU_H__ */ diff --git a/branches/pcsx2_0.9.1/VU0.c b/branches/pcsx2_0.9.1/VU0.c new file mode 100644 index 0000000..4e86c33 --- /dev/null +++ b/branches/pcsx2_0.9.1/VU0.c @@ -0,0 +1,383 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO + -Fix the flags Proper as they aren't handle now.. + -Add BC Table opcodes + -Add Interlock in QMFC2,QMTC2,CFC2,CTC2 + -Finish instruction set + -Bug Fixes!!! +*/ + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUops.h" +#include "VUmicro.h" + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X (cpuRegs.code>>24) & 0x1 +#define _Y (cpuRegs.code>>23) & 0x1 +#define _Z (cpuRegs.code>>22) & 0x1 +#define _W (cpuRegs.code>>21) & 0x1 + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) + +#include "VUflags.h" + +__declspec(align(16)) VURegs VU0; + +void COP2() { +#ifdef VU0_LOG + VU0_LOG("%s\n", disR5900Fasm(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP2PrintTable[_Rs_](); +} + +void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} +void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} + +void COP2_SPECIAL2() { + Int_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](); +} + +void COP2_Unknown() +{ +#ifdef CPU_LOG + CPU_LOG("Unknown COP2 opcode called\n"); +#endif +} + +void LQC2() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code; + if (_Ft_) { + memRead128(addr, &VU0.VF[_Ft_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +// Asadr.Changed +void SQC2() { + u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; + memWrite64(addr, VU0.VF[_Ft_].UD[0]); + memWrite64(addr+8,VU0.VF[_Ft_].UD[1]); +} + + +//**************************************************************************** +void _vu0WaitMicro() { + int startcycle; + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) { + return; + } + + startcycle = VU0.cycle; + + VU0.flags|= VUFLAG_BREAKONMFLAG; + VU0.flags&= ~VUFLAG_MFLAGSET; + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU0Block(); + } while ((VU0.VI[REG_VPU_STAT].UL & 0x1) && (VU0.flags & VUFLAG_MFLAGSET) == 0); + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + + //NEW + cpuRegs.cycle += (VU0.cycle-startcycle)*2; + VU0.flags&= ~VUFLAG_BREAKONMFLAG; +} + + +void QMFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UD[0] = VU0.VF[_Fs_].UD[0]; + cpuRegs.GPR.r[_Rt_].UD[1] = VU0.VF[_Fs_].UD[1]; +} + +void QMTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + VU0.VF[_Fs_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + VU0.VF[_Fs_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void CFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UL[0] = VU0.VI[_Fs_].UL; + if(VU0.VI[_Fs_].UL & 0x80000000) + cpuRegs.GPR.r[_Rt_].UL[1] = 0xffffffff; + else + cpuRegs.GPR.r[_Rt_].UL[1] = 0; +} + +void CTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + VU0.VI[REG_FBRST].UL = cpuRegs.GPR.r[_Rt_].UL[0] & 0x0C0C; + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x1) { // VU0 Force Break + SysPrintf("fixme: VU0 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x2) { // VU0 Reset + //SysPrintf("fixme: VU0 Reset\n"); + vu0ResetRegs(); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x100) { // VU1 Force Break + SysPrintf("fixme: VU1 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x200) { // VU1 Reset +// SysPrintf("fixme: VU1 Reset\n"); + vu1ResetRegs(); + } + break; + case REG_CMSAR1: // REG_CMSAR1 + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { + VU1.VI[REG_TPC].UL = cpuRegs.GPR.r[_Rt_].US[0]; + vu1ExecMicro(VU1.VI[REG_TPC].UL); // Execute VU1 Micro SubRoutine + } + break; + default: + VU0.VI[_Fs_].UL = cpuRegs.GPR.r[_Rt_].UL[0]; + break; + } +} + +//--------------------------------------------------------------------------------------- + + +#define SYNCMSFLAGS() VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; VU0.VI[REG_MAC_FLAG].UL = VU0.macflag; +#define SYNCFDIV() VU0.VI[REG_Q].UL = VU0.q.UL; VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; + +void VABS() { VU0.code = cpuRegs.code; _vuABS(&VU0); } +void VADD() { VU0.code = cpuRegs.code; _vuADD(&VU0); SYNCMSFLAGS(); } +void VADDi() { VU0.code = cpuRegs.code; _vuADDi(&VU0); SYNCMSFLAGS(); } +void VADDq() { VU0.code = cpuRegs.code; _vuADDq(&VU0); SYNCMSFLAGS(); } +void VADDx() { VU0.code = cpuRegs.code; _vuADDx(&VU0); SYNCMSFLAGS(); } +void VADDy() { VU0.code = cpuRegs.code; _vuADDy(&VU0); SYNCMSFLAGS(); } +void VADDz() { VU0.code = cpuRegs.code; _vuADDz(&VU0); SYNCMSFLAGS(); } +void VADDw() { VU0.code = cpuRegs.code; _vuADDw(&VU0); SYNCMSFLAGS(); } +void VADDA() { VU0.code = cpuRegs.code; _vuADDA(&VU0); SYNCMSFLAGS(); } +void VADDAi() { VU0.code = cpuRegs.code; _vuADDAi(&VU0); SYNCMSFLAGS(); } +void VADDAq() { VU0.code = cpuRegs.code; _vuADDAq(&VU0); SYNCMSFLAGS(); } +void VADDAx() { VU0.code = cpuRegs.code; _vuADDAx(&VU0); SYNCMSFLAGS(); } +void VADDAy() { VU0.code = cpuRegs.code; _vuADDAy(&VU0); SYNCMSFLAGS(); } +void VADDAz() { VU0.code = cpuRegs.code; _vuADDAz(&VU0); SYNCMSFLAGS(); } +void VADDAw() { VU0.code = cpuRegs.code; _vuADDAw(&VU0); SYNCMSFLAGS(); } +void VSUB() { VU0.code = cpuRegs.code; _vuSUB(&VU0); SYNCMSFLAGS(); } +void VSUBi() { VU0.code = cpuRegs.code; _vuSUBi(&VU0); SYNCMSFLAGS(); } +void VSUBq() { VU0.code = cpuRegs.code; _vuSUBq(&VU0); SYNCMSFLAGS(); } +void VSUBx() { VU0.code = cpuRegs.code; _vuSUBx(&VU0); SYNCMSFLAGS(); } +void VSUBy() { VU0.code = cpuRegs.code; _vuSUBy(&VU0); SYNCMSFLAGS(); } +void VSUBz() { VU0.code = cpuRegs.code; _vuSUBz(&VU0); SYNCMSFLAGS(); } +void VSUBw() { VU0.code = cpuRegs.code; _vuSUBw(&VU0); SYNCMSFLAGS(); } +void VSUBA() { VU0.code = cpuRegs.code; _vuSUBA(&VU0); SYNCMSFLAGS(); } +void VSUBAi() { VU0.code = cpuRegs.code; _vuSUBAi(&VU0); SYNCMSFLAGS(); } +void VSUBAq() { VU0.code = cpuRegs.code; _vuSUBAq(&VU0); SYNCMSFLAGS(); } +void VSUBAx() { VU0.code = cpuRegs.code; _vuSUBAx(&VU0); SYNCMSFLAGS(); } +void VSUBAy() { VU0.code = cpuRegs.code; _vuSUBAy(&VU0); SYNCMSFLAGS(); } +void VSUBAz() { VU0.code = cpuRegs.code; _vuSUBAz(&VU0); SYNCMSFLAGS(); } +void VSUBAw() { VU0.code = cpuRegs.code; _vuSUBAw(&VU0); SYNCMSFLAGS(); } +void VMUL() { VU0.code = cpuRegs.code; _vuMUL(&VU0); SYNCMSFLAGS(); } +void VMULi() { VU0.code = cpuRegs.code; _vuMULi(&VU0); SYNCMSFLAGS(); } +void VMULq() { VU0.code = cpuRegs.code; _vuMULq(&VU0); SYNCMSFLAGS(); } +void VMULx() { VU0.code = cpuRegs.code; _vuMULx(&VU0); SYNCMSFLAGS(); } +void VMULy() { VU0.code = cpuRegs.code; _vuMULy(&VU0); SYNCMSFLAGS(); } +void VMULz() { VU0.code = cpuRegs.code; _vuMULz(&VU0); SYNCMSFLAGS(); } +void VMULw() { VU0.code = cpuRegs.code; _vuMULw(&VU0); SYNCMSFLAGS(); } +void VMULA() { VU0.code = cpuRegs.code; _vuMULA(&VU0); SYNCMSFLAGS(); } +void VMULAi() { VU0.code = cpuRegs.code; _vuMULAi(&VU0); SYNCMSFLAGS(); } +void VMULAq() { VU0.code = cpuRegs.code; _vuMULAq(&VU0); SYNCMSFLAGS(); } +void VMULAx() { VU0.code = cpuRegs.code; _vuMULAx(&VU0); SYNCMSFLAGS(); } +void VMULAy() { VU0.code = cpuRegs.code; _vuMULAy(&VU0); SYNCMSFLAGS(); } +void VMULAz() { VU0.code = cpuRegs.code; _vuMULAz(&VU0); SYNCMSFLAGS(); } +void VMULAw() { VU0.code = cpuRegs.code; _vuMULAw(&VU0); SYNCMSFLAGS(); } +void VMADD() { VU0.code = cpuRegs.code; _vuMADD(&VU0); SYNCMSFLAGS(); } +void VMADDi() { VU0.code = cpuRegs.code; _vuMADDi(&VU0); SYNCMSFLAGS(); } +void VMADDq() { VU0.code = cpuRegs.code; _vuMADDq(&VU0); SYNCMSFLAGS(); } +void VMADDx() { VU0.code = cpuRegs.code; _vuMADDx(&VU0); SYNCMSFLAGS(); } +void VMADDy() { VU0.code = cpuRegs.code; _vuMADDy(&VU0); SYNCMSFLAGS(); } +void VMADDz() { VU0.code = cpuRegs.code; _vuMADDz(&VU0); SYNCMSFLAGS(); } +void VMADDw() { VU0.code = cpuRegs.code; _vuMADDw(&VU0); SYNCMSFLAGS(); } +void VMADDA() { VU0.code = cpuRegs.code; _vuMADDA(&VU0); SYNCMSFLAGS(); } +void VMADDAi() { VU0.code = cpuRegs.code; _vuMADDAi(&VU0); SYNCMSFLAGS(); } +void VMADDAq() { VU0.code = cpuRegs.code; _vuMADDAq(&VU0); SYNCMSFLAGS(); } +void VMADDAx() { VU0.code = cpuRegs.code; _vuMADDAx(&VU0); SYNCMSFLAGS(); } +void VMADDAy() { VU0.code = cpuRegs.code; _vuMADDAy(&VU0); SYNCMSFLAGS(); } +void VMADDAz() { VU0.code = cpuRegs.code; _vuMADDAz(&VU0); SYNCMSFLAGS(); } +void VMADDAw() { VU0.code = cpuRegs.code; _vuMADDAw(&VU0); SYNCMSFLAGS(); } +void VMSUB() { VU0.code = cpuRegs.code; _vuMSUB(&VU0); SYNCMSFLAGS(); } +void VMSUBi() { VU0.code = cpuRegs.code; _vuMSUBi(&VU0); SYNCMSFLAGS(); } +void VMSUBq() { VU0.code = cpuRegs.code; _vuMSUBq(&VU0); SYNCMSFLAGS(); } +void VMSUBx() { VU0.code = cpuRegs.code; _vuMSUBx(&VU0); SYNCMSFLAGS(); } +void VMSUBy() { VU0.code = cpuRegs.code; _vuMSUBy(&VU0); SYNCMSFLAGS(); } +void VMSUBz() { VU0.code = cpuRegs.code; _vuMSUBz(&VU0); SYNCMSFLAGS(); } +void VMSUBw() { VU0.code = cpuRegs.code; _vuMSUBw(&VU0); SYNCMSFLAGS(); } +void VMSUBA() { VU0.code = cpuRegs.code; _vuMSUBA(&VU0); SYNCMSFLAGS(); } +void VMSUBAi() { VU0.code = cpuRegs.code; _vuMSUBAi(&VU0); SYNCMSFLAGS(); } +void VMSUBAq() { VU0.code = cpuRegs.code; _vuMSUBAq(&VU0); SYNCMSFLAGS(); } +void VMSUBAx() { VU0.code = cpuRegs.code; _vuMSUBAx(&VU0); SYNCMSFLAGS(); } +void VMSUBAy() { VU0.code = cpuRegs.code; _vuMSUBAy(&VU0); SYNCMSFLAGS(); } +void VMSUBAz() { VU0.code = cpuRegs.code; _vuMSUBAz(&VU0); SYNCMSFLAGS(); } +void VMSUBAw() { VU0.code = cpuRegs.code; _vuMSUBAw(&VU0); SYNCMSFLAGS(); } +void VMAX() { VU0.code = cpuRegs.code; _vuMAX(&VU0); } +void VMAXi() { VU0.code = cpuRegs.code; _vuMAXi(&VU0); } +void VMAXx() { VU0.code = cpuRegs.code; _vuMAXx(&VU0); } +void VMAXy() { VU0.code = cpuRegs.code; _vuMAXy(&VU0); } +void VMAXz() { VU0.code = cpuRegs.code; _vuMAXz(&VU0); } +void VMAXw() { VU0.code = cpuRegs.code; _vuMAXw(&VU0); } +void VMINI() { VU0.code = cpuRegs.code; _vuMINI(&VU0); } +void VMINIi() { VU0.code = cpuRegs.code; _vuMINIi(&VU0); } +void VMINIx() { VU0.code = cpuRegs.code; _vuMINIx(&VU0); } +void VMINIy() { VU0.code = cpuRegs.code; _vuMINIy(&VU0); } +void VMINIz() { VU0.code = cpuRegs.code; _vuMINIz(&VU0); } +void VMINIw() { VU0.code = cpuRegs.code; _vuMINIw(&VU0); } +void VOPMULA() { VU0.code = cpuRegs.code; _vuOPMULA(&VU0); SYNCMSFLAGS(); } +void VOPMSUB() { VU0.code = cpuRegs.code; _vuOPMSUB(&VU0); SYNCMSFLAGS(); } +void VNOP() { VU0.code = cpuRegs.code; _vuNOP(&VU0); } +void VFTOI0() { VU0.code = cpuRegs.code; _vuFTOI0(&VU0); } +void VFTOI4() { VU0.code = cpuRegs.code; _vuFTOI4(&VU0); } +void VFTOI12() { VU0.code = cpuRegs.code; _vuFTOI12(&VU0); } +void VFTOI15() { VU0.code = cpuRegs.code; _vuFTOI15(&VU0); } +void VITOF0() { VU0.code = cpuRegs.code; _vuITOF0(&VU0); } +void VITOF4() { VU0.code = cpuRegs.code; _vuITOF4(&VU0); } +void VITOF12() { VU0.code = cpuRegs.code; _vuITOF12(&VU0); } +void VITOF15() { VU0.code = cpuRegs.code; _vuITOF15(&VU0); } +void VCLIPw() { VU0.code = cpuRegs.code; _vuCLIP(&VU0); VU0.VI[REG_CLIP_FLAG].UL = VU0.clipflag; } + +void VDIV() { VU0.code = cpuRegs.code; _vuDIV(&VU0); SYNCFDIV(); } +void VSQRT() { VU0.code = cpuRegs.code; _vuSQRT(&VU0); SYNCFDIV(); } +void VRSQRT() { VU0.code = cpuRegs.code; _vuRSQRT(&VU0); SYNCFDIV(); } +void VIADD() { VU0.code = cpuRegs.code; _vuIADD(&VU0); } +void VIADDI() { VU0.code = cpuRegs.code; _vuIADDI(&VU0); } +void VIADDIU() { VU0.code = cpuRegs.code; _vuIADDIU(&VU0); } +void VIAND() { VU0.code = cpuRegs.code; _vuIAND(&VU0); } +void VIOR() { VU0.code = cpuRegs.code; _vuIOR(&VU0); } +void VISUB() { VU0.code = cpuRegs.code; _vuISUB(&VU0); } +void VISUBIU() { VU0.code = cpuRegs.code; _vuISUBIU(&VU0); } +void VMOVE() { VU0.code = cpuRegs.code; _vuMOVE(&VU0); } +void VMFIR() { VU0.code = cpuRegs.code; _vuMFIR(&VU0); } +void VMTIR() { VU0.code = cpuRegs.code; _vuMTIR(&VU0); } +void VMR32() { VU0.code = cpuRegs.code; _vuMR32(&VU0); } +void VLQ() { VU0.code = cpuRegs.code; _vuLQ(&VU0); } +void VLQD() { VU0.code = cpuRegs.code; _vuLQD(&VU0); } +void VLQI() { VU0.code = cpuRegs.code; _vuLQI(&VU0); } +void VSQ() { VU0.code = cpuRegs.code; _vuSQ(&VU0); } +void VSQD() { VU0.code = cpuRegs.code; _vuSQD(&VU0); } +void VSQI() { VU0.code = cpuRegs.code; _vuSQI(&VU0); } +void VILW() { VU0.code = cpuRegs.code; _vuILW(&VU0); } +void VISW() { VU0.code = cpuRegs.code; _vuISW(&VU0); } +void VILWR() { VU0.code = cpuRegs.code; _vuILWR(&VU0); } +void VISWR() { VU0.code = cpuRegs.code; _vuISWR(&VU0); } +void VRINIT() { VU0.code = cpuRegs.code; _vuRINIT(&VU0); } +void VRGET() { VU0.code = cpuRegs.code; _vuRGET(&VU0); } +void VRNEXT() { VU0.code = cpuRegs.code; _vuRNEXT(&VU0); } +void VRXOR() { VU0.code = cpuRegs.code; _vuRXOR(&VU0); } +void VWAITQ() { VU0.code = cpuRegs.code; _vuWAITQ(&VU0); } +void VFSAND() { VU0.code = cpuRegs.code; _vuFSAND(&VU0); } +void VFSEQ() { VU0.code = cpuRegs.code; _vuFSEQ(&VU0); } +void VFSOR() { VU0.code = cpuRegs.code; _vuFSOR(&VU0); } +void VFSSET() { VU0.code = cpuRegs.code; _vuFSSET(&VU0); } +void VFMAND() { VU0.code = cpuRegs.code; _vuFMAND(&VU0); } +void VFMEQ() { VU0.code = cpuRegs.code; _vuFMEQ(&VU0); } +void VFMOR() { VU0.code = cpuRegs.code; _vuFMOR(&VU0); } +void VFCAND() { VU0.code = cpuRegs.code; _vuFCAND(&VU0); } +void VFCEQ() { VU0.code = cpuRegs.code; _vuFCEQ(&VU0); } +void VFCOR() { VU0.code = cpuRegs.code; _vuFCOR(&VU0); } +void VFCSET() { VU0.code = cpuRegs.code; _vuFCSET(&VU0); } +void VFCGET() { VU0.code = cpuRegs.code; _vuFCGET(&VU0); } +void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); } + +#define CP2COND (/*(VU0.VI[REG_VPU_STAT].US[0] & 1) | */((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) + +#define BC2(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC2F() { BC2(== 0);} +void BC2T() { BC2(== 1);} + +#define BC2L(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC2FL() { BC2L(== 0);} +void BC2TL() { BC2L(== 1);} + +void vu0Finish() +{ + if( (VU0.VI[REG_VPU_STAT].UL & 0x1) ) { + int i = 0; + while(i++ < 32) { + Cpu->ExecuteVU0Block(); + if(!(VU0.VI[REG_VPU_STAT].UL & 0x1)) + break; + } + + if(VU0.VI[REG_VPU_STAT].UL & 0x1) { + VU0.VI[REG_VPU_STAT].UL &= ~1; +#ifdef PCSX2_DEVBUILD + SysPrintf("VU0 stall\n"); +#endif + } + } +} + +void VCALLMS() { + + vu0Finish(); + vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void VCALLMSR() { + vu0Finish(); + vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} diff --git a/branches/pcsx2_0.9.1/VU0.h b/branches/pcsx2_0.9.1/VU0.h new file mode 100644 index 0000000..5a8bc6d --- /dev/null +++ b/branches/pcsx2_0.9.1/VU0.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU0_H__ +#define __VU0_H__ + +#include "VU.h" +#define Lcode cpuRegs.code + +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); + +void recResetVU0( void ); + +void vu0Finish(); + +extern VURegs VU0; + +extern char *recMemVU0; /* VU0 blocks */ +extern char *recVU0; /* VU1 mem */ +extern char *recVU0mac; +extern char *recVU0status; +extern char *recVU0clip; +extern char *recVU0Q; +extern char *recVU0cycles; +extern char* recVU0XMMRegs; +extern char *recPtrVU0; + +extern u32 vu0recpcold; + +#endif /* __VU0_H__ */ diff --git a/branches/pcsx2_0.9.1/VU0micro.c b/branches/pcsx2_0.9.1/VU0micro.c new file mode 100644 index 0000000..6dcaa9b --- /dev/null +++ b/branches/pcsx2_0.9.1/VU0micro.c @@ -0,0 +1,712 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +extern PSMEMORYMAP *memLUT; +#endif + +int vu0Init() +{ +#ifdef WIN32_VIRTUAL_MEM + // unmap all vu0 pages + SysMapUserPhysicalPages(PS2MEM_VU0MICRO, 16, NULL); + + // mirror 4 times + VU0.Micro = PS2MEM_VU0MICRO; + memLUT[0x11000].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11000].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11001].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11001].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11002].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11002].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11003].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11003].aVFNs = &s_psVuMem.aVFNs[0]; + + // since vuregisters are mapped in vumem0, go to diff addr, but mapping to same physical addr + VU0.Mem = VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( VU0.Mem != (void*)0x11000000 ) { + SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError()); + return -1; + } + + memLUT[0x11004].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11004].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11005].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11005].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11006].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11006].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11007].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11007].aVFNs = &s_psVuMem.aVFNs[1]; + + // map only registers + SysMapUserPhysicalPages(VU0.Mem+0x4000, 1, &s_psVuMem.aPFNs[2]); +#else + VU0.Mem = (u8*)_aligned_malloc(0x4000+sizeof(VURegs), 16); // for VU1 + VU0.Micro = (u8*)_aligned_malloc(4*1024, 16); + memset(VU0.Mem, 0, 0x4000+sizeof(VURegs)); + memset(VU0.Micro, 0, 4*1024); +#endif + + +// VU0.VF = (VECTOR*)_aligned_malloc(32*sizeof(VECTOR), 16); +// VU0.VI = (REG_VI*)_aligned_malloc(32*sizeof(REG_VI), 16); +// if (VU0.VF == NULL || VU0.VI == NULL) { +// SysMessage(_("Error allocating memory")); return -1; +// } + + /* this is kinda tricky, maxmem is set to 0x4400 here, + tho it's not 100% accurate, since the mem goes from + 0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs), + i guess it shouldn't be a problem, + at least hope so :) (linuz) + */ + VU0.maxmem = 0x4400-4; + VU0.maxmicro = 4*1024-4; + VU0.vuExec = vu0Exec; + VU0.vifRegs = vif0Regs; + + if( CHECK_VU0REC ) { + SuperVUInit(0); + } + + vu0Reset(); + + return 0; +} + +void vu0Shutdown() +{ + if( CHECK_VU0REC ) { + SuperVUDestroy(0); + } + +#ifdef WIN32_VIRTUAL_MEM + if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL) ) + SysPrintf("err releasing vu0 mem %d\n", GetLastError()); + if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 ) + SysPrintf("err freeing vu0 %d\n", GetLastError()); +#else + _aligned_free(VU0.Mem); + _aligned_free(VU0.Micro); +#endif + + VU0.Mem = NULL; + VU0.Micro = NULL; +// _aligned_free(VU0.VF); VU0.VF = NULL; +// _aligned_free(VU0.VI); VU0.VI = NULL; +} + +void vu0ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0 + VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0 + vif0Regs->stat &= ~4; +} + +void vu0Reset() +{ + memset(&VU0.ACC, 0, sizeof(VECTOR)); + memset(VU0.VF, 0, sizeof(VECTOR)*32); + memset(VU0.VI, 0, sizeof(REG_VI)*32); + VU0.VF[0].f.x = 0.0f; + VU0.VF[0].f.y = 0.0f; + VU0.VF[0].f.z = 0.0f; + VU0.VF[0].f.w = 1.0f; + VU0.VI[0].UL = 0; + memset(VU0.Mem, 0, 4*1024); + memset(VU0.Micro, 0, 4*1024); + + recResetVU0(); +} + +void recResetVU0( void ) +{ + if( CHECK_VU0REC ) { + SuperVUReset(0); + } +} + +void vu0Freeze(gzFile f, int Mode) { + gzfreeze(&VU0.ACC, sizeof(VECTOR)); + gzfreeze(&VU0.code, sizeof(u32)); + gzfreeze(VU0.Mem, 4*1024); + gzfreeze(VU0.Micro, 4*1024); + gzfreeze(VU0.VF, 32*sizeof(VECTOR)); + gzfreeze(VU0.VI, 32*sizeof(REG_VI)); +} + + +void VU0MI_XGKICK() { +} + +void VU0MI_XTOP() { +} + +void vu0ExecMicro(u32 addr) { +#ifdef VUM_LOG + VUM_LOG("vu0ExecMicro %x\n", addr); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x1; + VU0.VI[REG_VPU_STAT].UL&= ~0xAE; + if (addr != -1) VU0.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU0); + Cpu->ExecuteVU0Block(); +} + +void _vu0ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU0); + VU0_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu0ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU0); + VU0_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +void _vu0Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){ + #ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + VU->cycle++; + return; + } + + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { + VU->ebit = 2; + } + if (ptr[1] & 0x20000000) { /* M flag */ + VU->flags|= VUFLAG_MFLAGSET; +// SysPrintf("fixme: M flag set\n"); + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x4) { + VU0.VI[REG_VPU_STAT].UL|= 0x2; + hwIntcIrq(INTC_VU0); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x8) { + VU0.VI[REG_VPU_STAT].UL|= 0x4; + hwIntcIrq(INTC_VU0); + } + } + + VU->code = ptr[1]; + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu0ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + memset(&lregs, 0, sizeof(lregs)); + } else { + VU->code = ptr[0]; + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU0.VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu0ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu0ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + + if (!(ptr[1] & 0x80000000)) + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + VU->branch--; + if (VU->branch == 0) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ + vif0Regs->stat&= ~0x4; + } + } +} + +void vu0Exec(VURegs* VU) { +// u32 *ptr; + + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + } else { + _vu0Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU0, VU0); +_vuRegsTables(VU0, VU0regs); + +void VU0unknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU0regsunknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0MI_ABS() { _vuABS(&VU0); } +void VU0MI_ADD() { _vuADD(&VU0); } +void VU0MI_ADDi() { _vuADDi(&VU0); } +void VU0MI_ADDq() { _vuADDq(&VU0); } +void VU0MI_ADDx() { _vuADDx(&VU0); } +void VU0MI_ADDy() { _vuADDy(&VU0); } +void VU0MI_ADDz() { _vuADDz(&VU0); } +void VU0MI_ADDw() { _vuADDw(&VU0); } +void VU0MI_ADDA() { _vuADDA(&VU0); } +void VU0MI_ADDAi() { _vuADDAi(&VU0); } +void VU0MI_ADDAq() { _vuADDAq(&VU0); } +void VU0MI_ADDAx() { _vuADDAx(&VU0); } +void VU0MI_ADDAy() { _vuADDAy(&VU0); } +void VU0MI_ADDAz() { _vuADDAz(&VU0); } +void VU0MI_ADDAw() { _vuADDAw(&VU0); } +void VU0MI_SUB() { _vuSUB(&VU0); } +void VU0MI_SUBi() { _vuSUBi(&VU0); } +void VU0MI_SUBq() { _vuSUBq(&VU0); } +void VU0MI_SUBx() { _vuSUBx(&VU0); } +void VU0MI_SUBy() { _vuSUBy(&VU0); } +void VU0MI_SUBz() { _vuSUBz(&VU0); } +void VU0MI_SUBw() { _vuSUBw(&VU0); } +void VU0MI_SUBA() { _vuSUBA(&VU0); } +void VU0MI_SUBAi() { _vuSUBAi(&VU0); } +void VU0MI_SUBAq() { _vuSUBAq(&VU0); } +void VU0MI_SUBAx() { _vuSUBAx(&VU0); } +void VU0MI_SUBAy() { _vuSUBAy(&VU0); } +void VU0MI_SUBAz() { _vuSUBAz(&VU0); } +void VU0MI_SUBAw() { _vuSUBAw(&VU0); } +void VU0MI_MUL() { _vuMUL(&VU0); } +void VU0MI_MULi() { _vuMULi(&VU0); } +void VU0MI_MULq() { _vuMULq(&VU0); } +void VU0MI_MULx() { _vuMULx(&VU0); } +void VU0MI_MULy() { _vuMULy(&VU0); } +void VU0MI_MULz() { _vuMULz(&VU0); } +void VU0MI_MULw() { _vuMULw(&VU0); } +void VU0MI_MULA() { _vuMULA(&VU0); } +void VU0MI_MULAi() { _vuMULAi(&VU0); } +void VU0MI_MULAq() { _vuMULAq(&VU0); } +void VU0MI_MULAx() { _vuMULAx(&VU0); } +void VU0MI_MULAy() { _vuMULAy(&VU0); } +void VU0MI_MULAz() { _vuMULAz(&VU0); } +void VU0MI_MULAw() { _vuMULAw(&VU0); } +void VU0MI_MADD() { _vuMADD(&VU0); } +void VU0MI_MADDi() { _vuMADDi(&VU0); } +void VU0MI_MADDq() { _vuMADDq(&VU0); } +void VU0MI_MADDx() { _vuMADDx(&VU0); } +void VU0MI_MADDy() { _vuMADDy(&VU0); } +void VU0MI_MADDz() { _vuMADDz(&VU0); } +void VU0MI_MADDw() { _vuMADDw(&VU0); } +void VU0MI_MADDA() { _vuMADDA(&VU0); } +void VU0MI_MADDAi() { _vuMADDAi(&VU0); } +void VU0MI_MADDAq() { _vuMADDAq(&VU0); } +void VU0MI_MADDAx() { _vuMADDAx(&VU0); } +void VU0MI_MADDAy() { _vuMADDAy(&VU0); } +void VU0MI_MADDAz() { _vuMADDAz(&VU0); } +void VU0MI_MADDAw() { _vuMADDAw(&VU0); } +void VU0MI_MSUB() { _vuMSUB(&VU0); } +void VU0MI_MSUBi() { _vuMSUBi(&VU0); } +void VU0MI_MSUBq() { _vuMSUBq(&VU0); } +void VU0MI_MSUBx() { _vuMSUBx(&VU0); } +void VU0MI_MSUBy() { _vuMSUBy(&VU0); } +void VU0MI_MSUBz() { _vuMSUBz(&VU0); } +void VU0MI_MSUBw() { _vuMSUBw(&VU0); } +void VU0MI_MSUBA() { _vuMSUBA(&VU0); } +void VU0MI_MSUBAi() { _vuMSUBAi(&VU0); } +void VU0MI_MSUBAq() { _vuMSUBAq(&VU0); } +void VU0MI_MSUBAx() { _vuMSUBAx(&VU0); } +void VU0MI_MSUBAy() { _vuMSUBAy(&VU0); } +void VU0MI_MSUBAz() { _vuMSUBAz(&VU0); } +void VU0MI_MSUBAw() { _vuMSUBAw(&VU0); } +void VU0MI_MAX() { _vuMAX(&VU0); } +void VU0MI_MAXi() { _vuMAXi(&VU0); } +void VU0MI_MAXx() { _vuMAXx(&VU0); } +void VU0MI_MAXy() { _vuMAXy(&VU0); } +void VU0MI_MAXz() { _vuMAXz(&VU0); } +void VU0MI_MAXw() { _vuMAXw(&VU0); } +void VU0MI_MINI() { _vuMINI(&VU0); } +void VU0MI_MINIi() { _vuMINIi(&VU0); } +void VU0MI_MINIx() { _vuMINIx(&VU0); } +void VU0MI_MINIy() { _vuMINIy(&VU0); } +void VU0MI_MINIz() { _vuMINIz(&VU0); } +void VU0MI_MINIw() { _vuMINIw(&VU0); } +void VU0MI_OPMULA() { _vuOPMULA(&VU0); } +void VU0MI_OPMSUB() { _vuOPMSUB(&VU0); } +void VU0MI_NOP() { _vuNOP(&VU0); } +void VU0MI_FTOI0() { _vuFTOI0(&VU0); } +void VU0MI_FTOI4() { _vuFTOI4(&VU0); } +void VU0MI_FTOI12() { _vuFTOI12(&VU0); } +void VU0MI_FTOI15() { _vuFTOI15(&VU0); } +void VU0MI_ITOF0() { _vuITOF0(&VU0); } +void VU0MI_ITOF4() { _vuITOF4(&VU0); } +void VU0MI_ITOF12() { _vuITOF12(&VU0); } +void VU0MI_ITOF15() { _vuITOF15(&VU0); } +void VU0MI_CLIP() { _vuCLIP(&VU0); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0MI_DIV() { _vuDIV(&VU0); } +void VU0MI_SQRT() { _vuSQRT(&VU0); } +void VU0MI_RSQRT() { _vuRSQRT(&VU0); } +void VU0MI_IADD() { _vuIADD(&VU0); } +void VU0MI_IADDI() { _vuIADDI(&VU0); } +void VU0MI_IADDIU() { _vuIADDIU(&VU0); } +void VU0MI_IAND() { _vuIAND(&VU0); } +void VU0MI_IOR() { _vuIOR(&VU0); } +void VU0MI_ISUB() { _vuISUB(&VU0); } +void VU0MI_ISUBIU() { _vuISUBIU(&VU0); } +void VU0MI_MOVE() { _vuMOVE(&VU0); } +void VU0MI_MFIR() { _vuMFIR(&VU0); } +void VU0MI_MTIR() { _vuMTIR(&VU0); } +void VU0MI_MR32() { _vuMR32(&VU0); } +void VU0MI_LQ() { _vuLQ(&VU0); } +void VU0MI_LQD() { _vuLQD(&VU0); } +void VU0MI_LQI() { _vuLQI(&VU0); } +void VU0MI_SQ() { _vuSQ(&VU0); } +void VU0MI_SQD() { _vuSQD(&VU0); } +void VU0MI_SQI() { _vuSQI(&VU0); } +void VU0MI_ILW() { _vuILW(&VU0); } +void VU0MI_ISW() { _vuISW(&VU0); } +void VU0MI_ILWR() { _vuILWR(&VU0); } +void VU0MI_ISWR() { _vuISWR(&VU0); } +void VU0MI_RINIT() { _vuRINIT(&VU0); } +void VU0MI_RGET() { _vuRGET(&VU0); } +void VU0MI_RNEXT() { _vuRNEXT(&VU0); } +void VU0MI_RXOR() { _vuRXOR(&VU0); } +void VU0MI_WAITQ() { _vuWAITQ(&VU0); } +void VU0MI_FSAND() { _vuFSAND(&VU0); } +void VU0MI_FSEQ() { _vuFSEQ(&VU0); } +void VU0MI_FSOR() { _vuFSOR(&VU0); } +void VU0MI_FSSET() { _vuFSSET(&VU0); } +void VU0MI_FMAND() { _vuFMAND(&VU0); } +void VU0MI_FMEQ() { _vuFMEQ(&VU0); } +void VU0MI_FMOR() { _vuFMOR(&VU0); } +void VU0MI_FCAND() { _vuFCAND(&VU0); } +void VU0MI_FCEQ() { _vuFCEQ(&VU0); } +void VU0MI_FCOR() { _vuFCOR(&VU0); } +void VU0MI_FCSET() { _vuFCSET(&VU0); } +void VU0MI_FCGET() { _vuFCGET(&VU0); } +void VU0MI_IBEQ() { _vuIBEQ(&VU0); } +void VU0MI_IBGEZ() { _vuIBGEZ(&VU0); } +void VU0MI_IBGTZ() { _vuIBGTZ(&VU0); } +void VU0MI_IBLTZ() { _vuIBLTZ(&VU0); } +void VU0MI_IBLEZ() { _vuIBLEZ(&VU0); } +void VU0MI_IBNE() { _vuIBNE(&VU0); } +void VU0MI_B() { _vuB(&VU0); } +void VU0MI_BAL() { _vuBAL(&VU0); } +void VU0MI_JR() { _vuJR(&VU0); } +void VU0MI_JALR() { _vuJALR(&VU0); } +void VU0MI_MFP() { _vuMFP(&VU0); } +void VU0MI_WAITP() { _vuWAITP(&VU0); } +void VU0MI_ESADD() { _vuESADD(&VU0); } +void VU0MI_ERSADD() { _vuERSADD(&VU0); } +void VU0MI_ELENG() { _vuELENG(&VU0); } +void VU0MI_ERLENG() { _vuERLENG(&VU0); } +void VU0MI_EATANxy() { _vuEATANxy(&VU0); } +void VU0MI_EATANxz() { _vuEATANxz(&VU0); } +void VU0MI_ESUM() { _vuESUM(&VU0); } +void VU0MI_ERCPR() { _vuERCPR(&VU0); } +void VU0MI_ESQRT() { _vuESQRT(&VU0); } +void VU0MI_ERSQRT() { _vuERSQRT(&VU0); } +void VU0MI_ESIN() { _vuESIN(&VU0); } +void VU0MI_EATAN() { _vuEATAN(&VU0); } +void VU0MI_EEXP() { _vuEEXP(&VU0); } +void VU0MI_XITOP() { _vuXITOP(&VU0); } + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU0, VUregsn); } +void VU0regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU0, VUregsn); } +void VU0regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU0, VUregsn); } +void VU0regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU0, VUregsn); } +void VU0regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU0, VUregsn); } +void VU0regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU0, VUregsn); } +void VU0regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU0, VUregsn); } +void VU0regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU0, VUregsn); } +void VU0regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU0, VUregsn); } +void VU0regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU0, VUregsn); } +void VU0regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU0, VUregsn); } +void VU0regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU0, VUregsn); } +void VU0regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU0, VUregsn); } +void VU0regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU0, VUregsn); } +void VU0regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU0, VUregsn); } +void VU0regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU0, VUregsn); } +void VU0regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU0, VUregsn); } +void VU0regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU0, VUregsn); } +void VU0regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU0, VUregsn); } +void VU0regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU0, VUregsn); } +void VU0regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU0, VUregsn); } +void VU0regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU0, VUregsn); } +void VU0regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU0, VUregsn); } +void VU0regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU0, VUregsn); } +void VU0regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU0, VUregsn); } +void VU0regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU0, VUregsn); } +void VU0regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU0, VUregsn); } +void VU0regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU0, VUregsn); } +void VU0regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU0, VUregsn); } +void VU0regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU0, VUregsn); } +void VU0regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU0, VUregsn); } +void VU0regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU0, VUregsn); } +void VU0regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU0, VUregsn); } +void VU0regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU0, VUregsn); } +void VU0regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU0, VUregsn); } +void VU0regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU0, VUregsn); } +void VU0regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU0, VUregsn); } +void VU0regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU0, VUregsn); } +void VU0regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU0, VUregsn); } +void VU0regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU0, VUregsn); } +void VU0regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU0, VUregsn); } +void VU0regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU0, VUregsn); } +void VU0regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU0, VUregsn); } +void VU0regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU0, VUregsn); } +void VU0regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU0, VUregsn); } +void VU0regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU0, VUregsn); } +void VU0regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU0, VUregsn); } +void VU0regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU0, VUregsn); } +void VU0regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU0, VUregsn); } +void VU0regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU0, VUregsn); } +void VU0regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU0, VUregsn); } +void VU0regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU0, VUregsn); } +void VU0regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU0, VUregsn); } +void VU0regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU0, VUregsn); } +void VU0regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU0, VUregsn); } +void VU0regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU0, VUregsn); } +void VU0regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU0, VUregsn); } +void VU0regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU0, VUregsn); } +void VU0regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU0, VUregsn); } +void VU0regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU0, VUregsn); } +void VU0regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU0, VUregsn); } +void VU0regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU0, VUregsn); } +void VU0regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU0, VUregsn); } +void VU0regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU0, VUregsn); } +void VU0regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU0, VUregsn); } +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU0, VUregsn); } +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU0, VUregsn); } +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU0, VUregsn); } +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU0, VUregsn); } +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU0, VUregsn); } +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU0, VUregsn); } +void VU0regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU0, VUregsn); } +void VU0regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU0, VUregsn); } +void VU0regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU0, VUregsn); } +void VU0regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU0, VUregsn); } +void VU0regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU0, VUregsn); } +void VU0regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU0, VUregsn); } +void VU0regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU0, VUregsn); } +void VU0regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU0, VUregsn); } +void VU0regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU0, VUregsn); } +void VU0regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU0, VUregsn); } +void VU0regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU0, VUregsn); } +void VU0regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU0, VUregsn); } +void VU0regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU0, VUregsn); } +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU0, VUregsn); } +void VU0regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU0, VUregsn); } +void VU0regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU0, VUregsn); } +void VU0regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU0, VUregsn); } +void VU0regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU0, VUregsn); } +void VU0regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU0, VUregsn); } +void VU0regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU0, VUregsn); } +void VU0regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU0, VUregsn); } +void VU0regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU0, VUregsn); } +void VU0regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU0, VUregsn); } +void VU0regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU0, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU0, VUregsn); } +void VU0regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU0, VUregsn); } +void VU0regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU0, VUregsn); } +void VU0regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU0, VUregsn); } +void VU0regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU0, VUregsn); } +void VU0regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU0, VUregsn); } +void VU0regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU0, VUregsn); } +void VU0regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU0, VUregsn); } +void VU0regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU0, VUregsn); } +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU0, VUregsn); } +void VU0regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU0, VUregsn); } +void VU0regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU0, VUregsn); } +void VU0regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU0, VUregsn); } +void VU0regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU0, VUregsn); } +void VU0regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU0, VUregsn); } +void VU0regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU0, VUregsn); } +void VU0regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU0, VUregsn); } +void VU0regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU0, VUregsn); } +void VU0regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU0, VUregsn); } +void VU0regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU0, VUregsn); } +void VU0regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU0, VUregsn); } +void VU0regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU0, VUregsn); } +void VU0regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU0, VUregsn); } +void VU0regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU0, VUregsn); } +void VU0regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU0, VUregsn); } +void VU0regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU0, VUregsn); } +void VU0regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU0, VUregsn); } +void VU0regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU0, VUregsn); } +void VU0regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU0, VUregsn); } +void VU0regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU0, VUregsn); } +void VU0regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU0, VUregsn); } +void VU0regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU0, VUregsn); } +void VU0regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU0, VUregsn); } +void VU0regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU0, VUregsn); } +void VU0regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU0, VUregsn); } +void VU0regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU0, VUregsn); } +void VU0regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU0, VUregsn); } +void VU0regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU0, VUregsn); } +void VU0regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU0, VUregsn); } +void VU0regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU0, VUregsn); } +void VU0regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU0, VUregsn); } +void VU0regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU0, VUregsn); } +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU0, VUregsn); } +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU0, VUregsn); } +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU0, VUregsn); } +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU0, VUregsn); } +void VU0regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU0, VUregsn); } +void VU0regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU0, VUregsn); } +void VU0regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU0, VUregsn); } +void VU0regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU0, VUregsn); } +void VU0regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU0, VUregsn); } +void VU0regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU0, VUregsn); } +void VU0regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU0, VUregsn); } +void VU0regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU0, VUregsn); } +void VU0regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU0, VUregsn); } +void VU0regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU0, VUregsn); } +void VU0regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU0, VUregsn); } +void VU0regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU0, VUregsn); } +void VU0regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU0, VUregsn); } +void VU0regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU0, VUregsn); } +void VU0regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU0, VUregsn); } +void VU0regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU0, VUregsn); } +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU0, VUregsn); } +void VU0regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU0, VUregsn); } +void VU0regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU0, VUregsn); } +void VU0regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU0, VUregsn); } +void VU0regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU0, VUregsn); } +void VU0regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU0, VUregsn); } +void VU0regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU0, VUregsn); } diff --git a/branches/pcsx2_0.9.1/VU1micro.c b/branches/pcsx2_0.9.1/VU1micro.c new file mode 100644 index 0000000..ca72f87 --- /dev/null +++ b/branches/pcsx2_0.9.1/VU1micro.c @@ -0,0 +1,665 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUops.h" +#include "VUflags.h" +#include "ivu1micro.h" + +#include "iVUzerorec.h" + +VURegs* g_pVU1; + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +#endif + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +int vu1Init() +{ + assert( VU0.Mem != NULL ); + g_pVU1 = (VURegs*)(VU0.Mem + 0x4000); + +#ifdef WIN32_VIRTUAL_MEM + VU1.Mem = PS2MEM_VU1MEM; + VU1.Micro = PS2MEM_VU1MICRO; +#else + VU1.Mem = (u8*)_aligned_malloc(16*1024, 16); + VU1.Micro = (u8*)_aligned_malloc(16*1024, 16); + if (VU1.Mem == NULL || VU1.Micro == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + memset(VU1.Mem, 0,16*1024); + memset(VU1.Micro, 0,16*1024); +#endif + + VU1.maxmem = -1;//16*1024-4; + VU1.maxmicro = 16*1024-4; +// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000); +// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200); + VU1.vuExec = vu1Exec; + VU1.vifRegs = vif1Regs; + + if( CHECK_VU1REC ) { + recVU1Init(); + } + + vu1Reset(); + + return 0; +} + +void vu1Shutdown() { + if( CHECK_VU1REC ) { + recVU1Shutdown(); + } +} + +void vu1ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1 + VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1 + vif1Regs->stat &= ~4; +} + +void vu1Reset() { + memset(&VU1.ACC, 0, sizeof(VECTOR)); + memset(VU1.VF, 0, sizeof(VECTOR)*32); + memset(VU1.VI, 0, sizeof(REG_VI)*32); + VU1.VF[0].f.x = 0.0f; + VU1.VF[0].f.y = 0.0f; + VU1.VF[0].f.z = 0.0f; + VU1.VF[0].f.w = 1.0f; + VU1.VI[0].UL = 0; + memset(VU1.Mem, 0, 16*1024); + memset(VU1.Micro, 0, 16*1024); + + recResetVU1(); +} + +void vu1Freeze(gzFile f, int Mode) { + gzfreeze(&VU1.ACC, sizeof(VECTOR)); + gzfreeze(&VU1.code, sizeof(u32)); + gzfreeze(VU1.Mem, 16*1024); + gzfreeze(VU1.Micro, 16*1024); + gzfreeze(VU1.VF, 32*sizeof(VECTOR)); + gzfreeze(VU1.VI, 32*sizeof(REG_VI)); +} + +static int count; + +void vu1ExecMicro(u32 addr) +{ +#ifdef VUM_LOG + VUM_LOG("vu1ExecMicro %x\n", addr); + VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x100; + VU0.VI[REG_VPU_STAT].UL&= ~0x7E000; + vif1Regs->stat|= 0x4; + if (addr != -1) VU1.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU1); + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + // rec can call vu1ExecMicro + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void _vu1ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU1); + VU1_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu1ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU1); + VU1_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +void _vu1Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU1.VI[REG_TPC].UL >= VU1.maxmicro){ +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { /* E flag */ + VU->ebit = 2; + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x400) { + VU0.VI[REG_VPU_STAT].UL|= 0x200; + hwIntcIrq(INTC_VU1); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x800) { + VU0.VI[REG_VPU_STAT].UL|= 0x400; + hwIntcIrq(INTC_VU1); + } + } + +#ifdef VUM_LOG + if (Log) { + VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)\n", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); + } +#endif + + VU->code = ptr[1]; + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu1ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + } else { + VU->code = ptr[0]; + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU->VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu1ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu1ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + if (VU->branch-- == 1) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + vif1Regs->stat&= ~0x4; + } + } +} + +void vu1Exec(VURegs* VU) { + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + } else { + _vu1Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU1, VU1); +_vuRegsTables(VU1, VU1regs); + +void VU1unknown() { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU1regsunknown() { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1MI_ABS() { _vuABS(&VU1); } +void VU1MI_ADD() { _vuADD(&VU1); } +void VU1MI_ADDi() { _vuADDi(&VU1); } +void VU1MI_ADDq() { _vuADDq(&VU1); } +void VU1MI_ADDx() { _vuADDx(&VU1); } +void VU1MI_ADDy() { _vuADDy(&VU1); } +void VU1MI_ADDz() { _vuADDz(&VU1); } +void VU1MI_ADDw() { _vuADDw(&VU1); } +void VU1MI_ADDA() { _vuADDA(&VU1); } +void VU1MI_ADDAi() { _vuADDAi(&VU1); } +void VU1MI_ADDAq() { _vuADDAq(&VU1); } +void VU1MI_ADDAx() { _vuADDAx(&VU1); } +void VU1MI_ADDAy() { _vuADDAy(&VU1); } +void VU1MI_ADDAz() { _vuADDAz(&VU1); } +void VU1MI_ADDAw() { _vuADDAw(&VU1); } +void VU1MI_SUB() { _vuSUB(&VU1); } +void VU1MI_SUBi() { _vuSUBi(&VU1); } +void VU1MI_SUBq() { _vuSUBq(&VU1); } +void VU1MI_SUBx() { _vuSUBx(&VU1); } +void VU1MI_SUBy() { _vuSUBy(&VU1); } +void VU1MI_SUBz() { _vuSUBz(&VU1); } +void VU1MI_SUBw() { _vuSUBw(&VU1); } +void VU1MI_SUBA() { _vuSUBA(&VU1); } +void VU1MI_SUBAi() { _vuSUBAi(&VU1); } +void VU1MI_SUBAq() { _vuSUBAq(&VU1); } +void VU1MI_SUBAx() { _vuSUBAx(&VU1); } +void VU1MI_SUBAy() { _vuSUBAy(&VU1); } +void VU1MI_SUBAz() { _vuSUBAz(&VU1); } +void VU1MI_SUBAw() { _vuSUBAw(&VU1); } +void VU1MI_MUL() { _vuMUL(&VU1); } +void VU1MI_MULi() { _vuMULi(&VU1); } +void VU1MI_MULq() { _vuMULq(&VU1); } +void VU1MI_MULx() { _vuMULx(&VU1); } +void VU1MI_MULy() { _vuMULy(&VU1); } +void VU1MI_MULz() { _vuMULz(&VU1); } +void VU1MI_MULw() { _vuMULw(&VU1); } +void VU1MI_MULA() { _vuMULA(&VU1); } +void VU1MI_MULAi() { _vuMULAi(&VU1); } +void VU1MI_MULAq() { _vuMULAq(&VU1); } +void VU1MI_MULAx() { _vuMULAx(&VU1); } +void VU1MI_MULAy() { _vuMULAy(&VU1); } +void VU1MI_MULAz() { _vuMULAz(&VU1); } +void VU1MI_MULAw() { _vuMULAw(&VU1); } +void VU1MI_MADD() { _vuMADD(&VU1); } +void VU1MI_MADDi() { _vuMADDi(&VU1); } +void VU1MI_MADDq() { _vuMADDq(&VU1); } +void VU1MI_MADDx() { _vuMADDx(&VU1); } +void VU1MI_MADDy() { _vuMADDy(&VU1); } +void VU1MI_MADDz() { _vuMADDz(&VU1); } +void VU1MI_MADDw() { _vuMADDw(&VU1); } +void VU1MI_MADDA() { _vuMADDA(&VU1); } +void VU1MI_MADDAi() { _vuMADDAi(&VU1); } +void VU1MI_MADDAq() { _vuMADDAq(&VU1); } +void VU1MI_MADDAx() { _vuMADDAx(&VU1); } +void VU1MI_MADDAy() { _vuMADDAy(&VU1); } +void VU1MI_MADDAz() { _vuMADDAz(&VU1); } +void VU1MI_MADDAw() { _vuMADDAw(&VU1); } +void VU1MI_MSUB() { _vuMSUB(&VU1); } +void VU1MI_MSUBi() { _vuMSUBi(&VU1); } +void VU1MI_MSUBq() { _vuMSUBq(&VU1); } +void VU1MI_MSUBx() { _vuMSUBx(&VU1); } +void VU1MI_MSUBy() { _vuMSUBy(&VU1); } +void VU1MI_MSUBz() { _vuMSUBz(&VU1); } +void VU1MI_MSUBw() { _vuMSUBw(&VU1); } +void VU1MI_MSUBA() { _vuMSUBA(&VU1); } +void VU1MI_MSUBAi() { _vuMSUBAi(&VU1); } +void VU1MI_MSUBAq() { _vuMSUBAq(&VU1); } +void VU1MI_MSUBAx() { _vuMSUBAx(&VU1); } +void VU1MI_MSUBAy() { _vuMSUBAy(&VU1); } +void VU1MI_MSUBAz() { _vuMSUBAz(&VU1); } +void VU1MI_MSUBAw() { _vuMSUBAw(&VU1); } +void VU1MI_MAX() { _vuMAX(&VU1); } +void VU1MI_MAXi() { _vuMAXi(&VU1); } +void VU1MI_MAXx() { _vuMAXx(&VU1); } +void VU1MI_MAXy() { _vuMAXy(&VU1); } +void VU1MI_MAXz() { _vuMAXz(&VU1); } +void VU1MI_MAXw() { _vuMAXw(&VU1); } +void VU1MI_MINI() { _vuMINI(&VU1); } +void VU1MI_MINIi() { _vuMINIi(&VU1); } +void VU1MI_MINIx() { _vuMINIx(&VU1); } +void VU1MI_MINIy() { _vuMINIy(&VU1); } +void VU1MI_MINIz() { _vuMINIz(&VU1); } +void VU1MI_MINIw() { _vuMINIw(&VU1); } +void VU1MI_OPMULA() { _vuOPMULA(&VU1); } +void VU1MI_OPMSUB() { _vuOPMSUB(&VU1); } +void VU1MI_NOP() { _vuNOP(&VU1); } +void VU1MI_FTOI0() { _vuFTOI0(&VU1); } +void VU1MI_FTOI4() { _vuFTOI4(&VU1); } +void VU1MI_FTOI12() { _vuFTOI12(&VU1); } +void VU1MI_FTOI15() { _vuFTOI15(&VU1); } +void VU1MI_ITOF0() { _vuITOF0(&VU1); } +void VU1MI_ITOF4() { _vuITOF4(&VU1); } +void VU1MI_ITOF12() { _vuITOF12(&VU1); } +void VU1MI_ITOF15() { _vuITOF15(&VU1); } +void VU1MI_CLIP() { _vuCLIP(&VU1); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1MI_DIV() { _vuDIV(&VU1); } +void VU1MI_SQRT() { _vuSQRT(&VU1); } +void VU1MI_RSQRT() { _vuRSQRT(&VU1); } +void VU1MI_IADD() { _vuIADD(&VU1); } +void VU1MI_IADDI() { _vuIADDI(&VU1); } +void VU1MI_IADDIU() { _vuIADDIU(&VU1); } +void VU1MI_IAND() { _vuIAND(&VU1); } +void VU1MI_IOR() { _vuIOR(&VU1); } +void VU1MI_ISUB() { _vuISUB(&VU1); } +void VU1MI_ISUBIU() { _vuISUBIU(&VU1); } +void VU1MI_MOVE() { _vuMOVE(&VU1); } +void VU1MI_MFIR() { _vuMFIR(&VU1); } +void VU1MI_MTIR() { _vuMTIR(&VU1); } +void VU1MI_MR32() { _vuMR32(&VU1); } +void VU1MI_LQ() { _vuLQ(&VU1); } +void VU1MI_LQD() { _vuLQD(&VU1); } +void VU1MI_LQI() { _vuLQI(&VU1); } +void VU1MI_SQ() { _vuSQ(&VU1); } +void VU1MI_SQD() { _vuSQD(&VU1); } +void VU1MI_SQI() { _vuSQI(&VU1); } +void VU1MI_ILW() { _vuILW(&VU1); } +void VU1MI_ISW() { _vuISW(&VU1); } +void VU1MI_ILWR() { _vuILWR(&VU1); } +void VU1MI_ISWR() { _vuISWR(&VU1); } +void VU1MI_RINIT() { _vuRINIT(&VU1); } +void VU1MI_RGET() { _vuRGET(&VU1); } +void VU1MI_RNEXT() { _vuRNEXT(&VU1); } +void VU1MI_RXOR() { _vuRXOR(&VU1); } +void VU1MI_WAITQ() { _vuWAITQ(&VU1); } +void VU1MI_FSAND() { _vuFSAND(&VU1); } +void VU1MI_FSEQ() { _vuFSEQ(&VU1); } +void VU1MI_FSOR() { _vuFSOR(&VU1); } +void VU1MI_FSSET() { _vuFSSET(&VU1); } +void VU1MI_FMAND() { _vuFMAND(&VU1); } +void VU1MI_FMEQ() { _vuFMEQ(&VU1); } +void VU1MI_FMOR() { _vuFMOR(&VU1); } +void VU1MI_FCAND() { _vuFCAND(&VU1); } +void VU1MI_FCEQ() { _vuFCEQ(&VU1); } +void VU1MI_FCOR() { _vuFCOR(&VU1); } +void VU1MI_FCSET() { _vuFCSET(&VU1); } +void VU1MI_FCGET() { _vuFCGET(&VU1); } +void VU1MI_IBEQ() { _vuIBEQ(&VU1); } +void VU1MI_IBGEZ() { _vuIBGEZ(&VU1); } +void VU1MI_IBGTZ() { _vuIBGTZ(&VU1); } +void VU1MI_IBLTZ() { _vuIBLTZ(&VU1); } +void VU1MI_IBLEZ() { _vuIBLEZ(&VU1); } +void VU1MI_IBNE() { _vuIBNE(&VU1); } +void VU1MI_B() { _vuB(&VU1); } +void VU1MI_BAL() { _vuBAL(&VU1); } +void VU1MI_JR() { _vuJR(&VU1); } +void VU1MI_JALR() { _vuJALR(&VU1); } +void VU1MI_MFP() { _vuMFP(&VU1); } +void VU1MI_WAITP() { _vuWAITP(&VU1); } +void VU1MI_ESADD() { _vuESADD(&VU1); } +void VU1MI_ERSADD() { _vuERSADD(&VU1); } +void VU1MI_ELENG() { _vuELENG(&VU1); } +void VU1MI_ERLENG() { _vuERLENG(&VU1); } +void VU1MI_EATANxy() { _vuEATANxy(&VU1); } +void VU1MI_EATANxz() { _vuEATANxz(&VU1); } +void VU1MI_ESUM() { _vuESUM(&VU1); } +void VU1MI_ERCPR() { _vuERCPR(&VU1); } +void VU1MI_ESQRT() { _vuESQRT(&VU1); } +void VU1MI_ERSQRT() { _vuERSQRT(&VU1); } +void VU1MI_ESIN() { _vuESIN(&VU1); } +void VU1MI_EATAN() { _vuEATAN(&VU1); } +void VU1MI_EEXP() { _vuEEXP(&VU1); } +void VU1MI_XITOP() { _vuXITOP(&VU1); } +void VU1MI_XGKICK() { _vuXGKICK(&VU1); } +void VU1MI_XTOP() { _vuXTOP(&VU1); } + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU1, VUregsn); } +void VU1regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU1, VUregsn); } +void VU1regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU1, VUregsn); } +void VU1regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU1, VUregsn); } +void VU1regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU1, VUregsn); } +void VU1regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU1, VUregsn); } +void VU1regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU1, VUregsn); } +void VU1regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU1, VUregsn); } +void VU1regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU1, VUregsn); } +void VU1regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU1, VUregsn); } +void VU1regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU1, VUregsn); } +void VU1regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU1, VUregsn); } +void VU1regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU1, VUregsn); } +void VU1regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU1, VUregsn); } +void VU1regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU1, VUregsn); } +void VU1regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU1, VUregsn); } +void VU1regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU1, VUregsn); } +void VU1regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU1, VUregsn); } +void VU1regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU1, VUregsn); } +void VU1regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU1, VUregsn); } +void VU1regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU1, VUregsn); } +void VU1regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU1, VUregsn); } +void VU1regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU1, VUregsn); } +void VU1regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU1, VUregsn); } +void VU1regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU1, VUregsn); } +void VU1regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU1, VUregsn); } +void VU1regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU1, VUregsn); } +void VU1regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU1, VUregsn); } +void VU1regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU1, VUregsn); } +void VU1regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU1, VUregsn); } +void VU1regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU1, VUregsn); } +void VU1regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU1, VUregsn); } +void VU1regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU1, VUregsn); } +void VU1regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU1, VUregsn); } +void VU1regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU1, VUregsn); } +void VU1regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU1, VUregsn); } +void VU1regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU1, VUregsn); } +void VU1regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU1, VUregsn); } +void VU1regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU1, VUregsn); } +void VU1regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU1, VUregsn); } +void VU1regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU1, VUregsn); } +void VU1regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU1, VUregsn); } +void VU1regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU1, VUregsn); } +void VU1regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU1, VUregsn); } +void VU1regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU1, VUregsn); } +void VU1regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU1, VUregsn); } +void VU1regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU1, VUregsn); } +void VU1regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU1, VUregsn); } +void VU1regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU1, VUregsn); } +void VU1regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU1, VUregsn); } +void VU1regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU1, VUregsn); } +void VU1regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU1, VUregsn); } +void VU1regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU1, VUregsn); } +void VU1regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU1, VUregsn); } +void VU1regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU1, VUregsn); } +void VU1regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU1, VUregsn); } +void VU1regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU1, VUregsn); } +void VU1regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU1, VUregsn); } +void VU1regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU1, VUregsn); } +void VU1regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU1, VUregsn); } +void VU1regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU1, VUregsn); } +void VU1regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU1, VUregsn); } +void VU1regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU1, VUregsn); } +void VU1regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU1, VUregsn); } +void VU1regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU1, VUregsn); } +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU1, VUregsn); } +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU1, VUregsn); } +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU1, VUregsn); } +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU1, VUregsn); } +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU1, VUregsn); } +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU1, VUregsn); } +void VU1regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU1, VUregsn); } +void VU1regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU1, VUregsn); } +void VU1regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU1, VUregsn); } +void VU1regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU1, VUregsn); } +void VU1regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU1, VUregsn); } +void VU1regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU1, VUregsn); } +void VU1regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU1, VUregsn); } +void VU1regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU1, VUregsn); } +void VU1regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU1, VUregsn); } +void VU1regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU1, VUregsn); } +void VU1regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU1, VUregsn); } +void VU1regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU1, VUregsn); } +void VU1regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU1, VUregsn); } +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU1, VUregsn); } +void VU1regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU1, VUregsn); } +void VU1regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU1, VUregsn); } +void VU1regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU1, VUregsn); } +void VU1regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU1, VUregsn); } +void VU1regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU1, VUregsn); } +void VU1regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU1, VUregsn); } +void VU1regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU1, VUregsn); } +void VU1regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU1, VUregsn); } +void VU1regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU1, VUregsn); } +void VU1regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU1, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU1, VUregsn); } +void VU1regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU1, VUregsn); } +void VU1regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU1, VUregsn); } +void VU1regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU1, VUregsn); } +void VU1regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU1, VUregsn); } +void VU1regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU1, VUregsn); } +void VU1regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU1, VUregsn); } +void VU1regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU1, VUregsn); } +void VU1regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU1, VUregsn); } +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU1, VUregsn); } +void VU1regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU1, VUregsn); } +void VU1regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU1, VUregsn); } +void VU1regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU1, VUregsn); } +void VU1regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU1, VUregsn); } +void VU1regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU1, VUregsn); } +void VU1regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU1, VUregsn); } +void VU1regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU1, VUregsn); } +void VU1regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU1, VUregsn); } +void VU1regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU1, VUregsn); } +void VU1regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU1, VUregsn); } +void VU1regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU1, VUregsn); } +void VU1regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU1, VUregsn); } +void VU1regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU1, VUregsn); } +void VU1regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU1, VUregsn); } +void VU1regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU1, VUregsn); } +void VU1regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU1, VUregsn); } +void VU1regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU1, VUregsn); } +void VU1regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU1, VUregsn); } +void VU1regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU1, VUregsn); } +void VU1regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU1, VUregsn); } +void VU1regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU1, VUregsn); } +void VU1regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU1, VUregsn); } +void VU1regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU1, VUregsn); } +void VU1regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU1, VUregsn); } +void VU1regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU1, VUregsn); } +void VU1regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU1, VUregsn); } +void VU1regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU1, VUregsn); } +void VU1regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU1, VUregsn); } +void VU1regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU1, VUregsn); } +void VU1regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU1, VUregsn); } +void VU1regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU1, VUregsn); } +void VU1regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU1, VUregsn); } +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU1, VUregsn); } +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU1, VUregsn); } +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU1, VUregsn); } +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU1, VUregsn); } +void VU1regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU1, VUregsn); } +void VU1regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU1, VUregsn); } +void VU1regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU1, VUregsn); } +void VU1regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU1, VUregsn); } +void VU1regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU1, VUregsn); } +void VU1regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU1, VUregsn); } +void VU1regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU1, VUregsn); } +void VU1regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU1, VUregsn); } +void VU1regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU1, VUregsn); } +void VU1regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU1, VUregsn); } +void VU1regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU1, VUregsn); } +void VU1regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU1, VUregsn); } +void VU1regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU1, VUregsn); } +void VU1regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU1, VUregsn); } +void VU1regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU1, VUregsn); } +void VU1regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU1, VUregsn); } +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU1, VUregsn); } +void VU1regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU1, VUregsn); } +void VU1regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU1, VUregsn); } +void VU1regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU1, VUregsn); } +void VU1regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU1, VUregsn); } +void VU1regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU1, VUregsn); } +void VU1regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU1, VUregsn); } diff --git a/branches/pcsx2_0.9.1/VUflags.c b/branches/pcsx2_0.9.1/VUflags.c new file mode 100644 index 0000000..637d564 --- /dev/null +++ b/branches/pcsx2_0.9.1/VUflags.c @@ -0,0 +1,96 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +/*****************************************/ +/* NEW FLAGS */ //By asadr. Thnkx F|RES :p +/*****************************************/ + + +__inline void vuUpdateDI(VURegs * VU) { +// u32 Flag_S = 0; +// u32 Flag_I = 0; +// u32 Flag_D = 0; +// +// /* +// FLAG D - I +// */ +// Flag_I = (VU->statusflag >> 4) & 0x1; +// Flag_D = (VU->statusflag >> 5) & 0x1; +// +// VU->statusflag|= (Flag_I | (VU0.VI[REG_STATUS_FLAG].US[0] >> 4)) << 10; +// VU->statusflag|= (Flag_D | (VU0.VI[REG_STATUS_FLAG].US[0] >> 5)) << 11; +} + +#define VU_MAC_UPDATE(name, shift) \ +u32 name(VURegs * VU, float f) { \ + u32 v = *(u32*)&f; \ + int exp = (v >> 23) & 0xff; \ + u32 s = v & 0x80000000; \ + \ + if (s) VU->macflag |= 0x0010<macflag &= ~(0x0010<macflag = (VU->macflag & ~(0x1100<macflag = (VU->macflag&~(0x1000<macflag = (VU->macflag&~(0x0100<macflag = (VU->macflag & ~(0x1101<macflag&= ~(0x1111<macflag & 0x000F) newflag = 0x1; + if (VU->macflag & 0x00F0) newflag |= 0x2; + if (VU->macflag & 0x0F00) newflag |= 0x4; + if (VU->macflag & 0xF000) newflag |= 0x8; + VU->statusflag = (VU->statusflag&0xc30)|newflag|((VU->statusflag&0xf)<<6); +} diff --git a/branches/pcsx2_0.9.1/VUflags.h b/branches/pcsx2_0.9.1/VUflags.h new file mode 100644 index 0000000..37338a5 --- /dev/null +++ b/branches/pcsx2_0.9.1/VUflags.h @@ -0,0 +1,38 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUFLAGS_H__ +#define __VUFLAGS_H__ + +#include "VU.h" + +void vuUpdateDI(VURegs * VU); +u32 VU_MACx_UPDATE(VURegs * VU, float x); +u32 VU_MACy_UPDATE(VURegs * VU, float y); +u32 VU_MACz_UPDATE(VURegs * VU, float z); +u32 VU_MACw_UPDATE(VURegs * VU, float w); +void VU_MACx_CLEAR(VURegs * VU); +void VU_MACy_CLEAR(VURegs * VU); +void VU_MACz_CLEAR(VURegs * VU); +void VU_MACw_CLEAR(VURegs * VU); +void VU_STAT_UPDATE(VURegs * VU); + + +#endif + + diff --git a/branches/pcsx2_0.9.1/VUmicro.h b/branches/pcsx2_0.9.1/VUmicro.h new file mode 100644 index 0000000..56ee73e --- /dev/null +++ b/branches/pcsx2_0.9.1/VUmicro.h @@ -0,0 +1,1263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUMICRO_H__ +#define __VUMICRO_H__ + +#include "VU.h" + +//both for VU0 VU1 micromode + +extern void (*VU0_LOWER_OPCODE[128])(); +extern void (*VU0_UPPER_OPCODE[64])(); + +extern void (*VU0_UPPER_FD_00_TABLE[32])(); +extern void (*VU0_UPPER_FD_01_TABLE[32])(); +extern void (*VU0_UPPER_FD_10_TABLE[32])(); +extern void (*VU0_UPPER_FD_11_TABLE[32])(); + +extern void (*VU0regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU0regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +extern void (*VU1_LOWER_OPCODE[128])(); +extern void (*VU1_UPPER_OPCODE[64])(); + +extern void (*VU1_UPPER_FD_00_TABLE[32])(); +extern void (*VU1_UPPER_FD_01_TABLE[32])(); +extern void (*VU1_UPPER_FD_10_TABLE[32])(); +extern void (*VU1_UPPER_FD_11_TABLE[32])(); + +extern void (*VU1regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU1regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +// VU0 +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); +void vu0ExecMicro(u32 addr); +void vu0Exec(VURegs* VU); +void vu0Finish(); +void recResetVU0( void ); + +// VU1 +int vu1Init(); +void vu1Reset(); +void vu1ResetRegs(); +void recResetVU1( void ); +void vu1Freeze(gzFile f, int Mode); +void vu1Shutdown(); +void vu1ExecMicro(u32 addr); +void vu1Exec(VURegs* VU); + +void VU0_UPPER_FD_00(); +void VU0_UPPER_FD_01(); +void VU0_UPPER_FD_10(); +void VU0_UPPER_FD_11(); + +void VU0LowerOP(); +void VU0LowerOP_T3_00(); +void VU0LowerOP_T3_01(); +void VU0LowerOP_T3_10(); +void VU0LowerOP_T3_11(); + +void VU0unknown(); + +void VU1_UPPER_FD_00(); +void VU1_UPPER_FD_01(); +void VU1_UPPER_FD_10(); +void VU1_UPPER_FD_11(); + +void VU1LowerOP(); +void VU1LowerOP_T3_00(); +void VU1LowerOP_T3_01(); +void VU1LowerOP_T3_10(); +void VU1LowerOP_T3_11(); + +void VU1unknown(); + +void VU0regs_UPPER_FD_00(); +void VU0regs_UPPER_FD_01(); +void VU0regs_UPPER_FD_10(); +void VU0regs_UPPER_FD_11(); + +void VU0regsLowerOP(); +void VU0regsLowerOP_T3_00(); +void VU0regsLowerOP_T3_01(); +void VU0regsLowerOP_T3_10(); +void VU0regsLowerOP_T3_11(); + +void VU0regsunknown(); + +void VU1regs_UPPER_FD_00(); +void VU1regs_UPPER_FD_01(); +void VU1regs_UPPER_FD_10(); +void VU1regs_UPPER_FD_11(); + +void VU1regsLowerOP(); +void VU1regsLowerOP_T3_00(); +void VU1regsLowerOP_T3_01(); +void VU1regsLowerOP_T3_10(); +void VU1regsLowerOP_T3_11(); + +void VU1regsunknown(); + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void VU0MI_ABS(); +void VU0MI_ADD(); +void VU0MI_ADDi(); +void VU0MI_ADDq(); +void VU0MI_ADDx(); +void VU0MI_ADDy(); +void VU0MI_ADDz(); +void VU0MI_ADDw(); +void VU0MI_ADDA(); +void VU0MI_ADDAi(); +void VU0MI_ADDAq(); +void VU0MI_ADDAx(); +void VU0MI_ADDAy(); +void VU0MI_ADDAz(); +void VU0MI_ADDAw(); +void VU0MI_SUB(); +void VU0MI_SUBi(); +void VU0MI_SUBq(); +void VU0MI_SUBx(); +void VU0MI_SUBy(); +void VU0MI_SUBz(); +void VU0MI_SUBw(); +void VU0MI_SUBA(); +void VU0MI_SUBAi(); +void VU0MI_SUBAq(); +void VU0MI_SUBAx(); +void VU0MI_SUBAy(); +void VU0MI_SUBAz(); +void VU0MI_SUBAw(); +void VU0MI_MUL(); +void VU0MI_MULi(); +void VU0MI_MULq(); +void VU0MI_MULx(); +void VU0MI_MULy(); +void VU0MI_MULz(); +void VU0MI_MULw(); +void VU0MI_MULA(); +void VU0MI_MULAi(); +void VU0MI_MULAq(); +void VU0MI_MULAx(); +void VU0MI_MULAy(); +void VU0MI_MULAz(); +void VU0MI_MULAw(); +void VU0MI_MADD(); +void VU0MI_MADDi(); +void VU0MI_MADDq(); +void VU0MI_MADDx(); +void VU0MI_MADDy(); +void VU0MI_MADDz(); +void VU0MI_MADDw(); +void VU0MI_MADDA(); +void VU0MI_MADDAi(); +void VU0MI_MADDAq(); +void VU0MI_MADDAx(); +void VU0MI_MADDAy(); +void VU0MI_MADDAz(); +void VU0MI_MADDAw(); +void VU0MI_MSUB(); +void VU0MI_MSUBi(); +void VU0MI_MSUBq(); +void VU0MI_MSUBx(); +void VU0MI_MSUBy(); +void VU0MI_MSUBz(); +void VU0MI_MSUBw(); +void VU0MI_MSUBA(); +void VU0MI_MSUBAi(); +void VU0MI_MSUBAq(); +void VU0MI_MSUBAx(); +void VU0MI_MSUBAy(); +void VU0MI_MSUBAz(); +void VU0MI_MSUBAw(); +void VU0MI_MAX(); +void VU0MI_MAXi(); +void VU0MI_MAXx(); +void VU0MI_MAXy(); +void VU0MI_MAXz(); +void VU0MI_MAXw(); +void VU0MI_MINI(); +void VU0MI_MINIi(); +void VU0MI_MINIx(); +void VU0MI_MINIy(); +void VU0MI_MINIz(); +void VU0MI_MINIw(); +void VU0MI_OPMULA(); +void VU0MI_OPMSUB(); +void VU0MI_NOP(); +void VU0MI_FTOI0(); +void VU0MI_FTOI4(); +void VU0MI_FTOI12(); +void VU0MI_FTOI15(); +void VU0MI_ITOF0(); +void VU0MI_ITOF4(); +void VU0MI_ITOF12(); +void VU0MI_ITOF15(); +void VU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0MI_DIV(); +void VU0MI_SQRT(); +void VU0MI_RSQRT(); +void VU0MI_IADD(); +void VU0MI_IADDI(); +void VU0MI_IADDIU(); +void VU0MI_IAND(); +void VU0MI_IOR(); +void VU0MI_ISUB(); +void VU0MI_ISUBIU(); +void VU0MI_MOVE(); +void VU0MI_MFIR(); +void VU0MI_MTIR(); +void VU0MI_MR32(); +void VU0MI_LQ(); +void VU0MI_LQD(); +void VU0MI_LQI(); +void VU0MI_SQ(); +void VU0MI_SQD(); +void VU0MI_SQI(); +void VU0MI_ILW(); +void VU0MI_ISW(); +void VU0MI_ILWR(); +void VU0MI_ISWR(); +void VU0MI_LOI(); +void VU0MI_RINIT(); +void VU0MI_RGET(); +void VU0MI_RNEXT(); +void VU0MI_RXOR(); +void VU0MI_WAITQ(); +void VU0MI_FSAND(); +void VU0MI_FSEQ(); +void VU0MI_FSOR(); +void VU0MI_FSSET(); +void VU0MI_FMAND(); +void VU0MI_FMEQ(); +void VU0MI_FMOR(); +void VU0MI_FCAND(); +void VU0MI_FCEQ(); +void VU0MI_FCOR(); +void VU0MI_FCSET(); +void VU0MI_FCGET(); +void VU0MI_IBEQ(); +void VU0MI_IBGEZ(); +void VU0MI_IBGTZ(); +void VU0MI_IBLEZ(); +void VU0MI_IBLTZ(); +void VU0MI_IBNE(); +void VU0MI_B(); +void VU0MI_BAL(); +void VU0MI_JR(); +void VU0MI_JALR(); +void VU0MI_MFP(); +void VU0MI_WAITP(); +void VU0MI_ESADD(); +void VU0MI_ERSADD(); +void VU0MI_ELENG(); +void VU0MI_ERLENG(); +void VU0MI_EATANxy(); +void VU0MI_EATANxz(); +void VU0MI_ESUM(); +void VU0MI_ERCPR(); +void VU0MI_ESQRT(); +void VU0MI_ERSQRT(); +void VU0MI_ESIN(); +void VU0MI_EATAN(); +void VU0MI_EEXP(); +void VU0MI_XGKICK(); +void VU0MI_XTOP(); +void VU0MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn); +void VU0regsMI_ADD(_VURegsNum *VUregsn); +void VU0regsMI_ADDi(_VURegsNum *VUregsn); +void VU0regsMI_ADDq(_VURegsNum *VUregsn); +void VU0regsMI_ADDx(_VURegsNum *VUregsn); +void VU0regsMI_ADDy(_VURegsNum *VUregsn); +void VU0regsMI_ADDz(_VURegsNum *VUregsn); +void VU0regsMI_ADDw(_VURegsNum *VUregsn); +void VU0regsMI_ADDA(_VURegsNum *VUregsn); +void VU0regsMI_ADDAi(_VURegsNum *VUregsn); +void VU0regsMI_ADDAq(_VURegsNum *VUregsn); +void VU0regsMI_ADDAx(_VURegsNum *VUregsn); +void VU0regsMI_ADDAy(_VURegsNum *VUregsn); +void VU0regsMI_ADDAz(_VURegsNum *VUregsn); +void VU0regsMI_ADDAw(_VURegsNum *VUregsn); +void VU0regsMI_SUB(_VURegsNum *VUregsn); +void VU0regsMI_SUBi(_VURegsNum *VUregsn); +void VU0regsMI_SUBq(_VURegsNum *VUregsn); +void VU0regsMI_SUBx(_VURegsNum *VUregsn); +void VU0regsMI_SUBy(_VURegsNum *VUregsn); +void VU0regsMI_SUBz(_VURegsNum *VUregsn); +void VU0regsMI_SUBw(_VURegsNum *VUregsn); +void VU0regsMI_SUBA(_VURegsNum *VUregsn); +void VU0regsMI_SUBAi(_VURegsNum *VUregsn); +void VU0regsMI_SUBAq(_VURegsNum *VUregsn); +void VU0regsMI_SUBAx(_VURegsNum *VUregsn); +void VU0regsMI_SUBAy(_VURegsNum *VUregsn); +void VU0regsMI_SUBAz(_VURegsNum *VUregsn); +void VU0regsMI_SUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MUL(_VURegsNum *VUregsn); +void VU0regsMI_MULi(_VURegsNum *VUregsn); +void VU0regsMI_MULq(_VURegsNum *VUregsn); +void VU0regsMI_MULx(_VURegsNum *VUregsn); +void VU0regsMI_MULy(_VURegsNum *VUregsn); +void VU0regsMI_MULz(_VURegsNum *VUregsn); +void VU0regsMI_MULw(_VURegsNum *VUregsn); +void VU0regsMI_MULA(_VURegsNum *VUregsn); +void VU0regsMI_MULAi(_VURegsNum *VUregsn); +void VU0regsMI_MULAq(_VURegsNum *VUregsn); +void VU0regsMI_MULAx(_VURegsNum *VUregsn); +void VU0regsMI_MULAy(_VURegsNum *VUregsn); +void VU0regsMI_MULAz(_VURegsNum *VUregsn); +void VU0regsMI_MULAw(_VURegsNum *VUregsn); +void VU0regsMI_MADD(_VURegsNum *VUregsn); +void VU0regsMI_MADDi(_VURegsNum *VUregsn); +void VU0regsMI_MADDq(_VURegsNum *VUregsn); +void VU0regsMI_MADDx(_VURegsNum *VUregsn); +void VU0regsMI_MADDy(_VURegsNum *VUregsn); +void VU0regsMI_MADDz(_VURegsNum *VUregsn); +void VU0regsMI_MADDw(_VURegsNum *VUregsn); +void VU0regsMI_MADDA(_VURegsNum *VUregsn); +void VU0regsMI_MADDAi(_VURegsNum *VUregsn); +void VU0regsMI_MADDAq(_VURegsNum *VUregsn); +void VU0regsMI_MADDAx(_VURegsNum *VUregsn); +void VU0regsMI_MADDAy(_VURegsNum *VUregsn); +void VU0regsMI_MADDAz(_VURegsNum *VUregsn); +void VU0regsMI_MADDAw(_VURegsNum *VUregsn); +void VU0regsMI_MSUB(_VURegsNum *VUregsn); +void VU0regsMI_MSUBi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBw(_VURegsNum *VUregsn); +void VU0regsMI_MSUBA(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MAX(_VURegsNum *VUregsn); +void VU0regsMI_MAXi(_VURegsNum *VUregsn); +void VU0regsMI_MAXx(_VURegsNum *VUregsn); +void VU0regsMI_MAXy(_VURegsNum *VUregsn); +void VU0regsMI_MAXz(_VURegsNum *VUregsn); +void VU0regsMI_MAXw(_VURegsNum *VUregsn); +void VU0regsMI_MINI(_VURegsNum *VUregsn); +void VU0regsMI_MINIi(_VURegsNum *VUregsn); +void VU0regsMI_MINIx(_VURegsNum *VUregsn); +void VU0regsMI_MINIy(_VURegsNum *VUregsn); +void VU0regsMI_MINIz(_VURegsNum *VUregsn); +void VU0regsMI_MINIw(_VURegsNum *VUregsn); +void VU0regsMI_OPMULA(_VURegsNum *VUregsn); +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU0regsMI_NOP(_VURegsNum *VUregsn); +void VU0regsMI_FTOI0(_VURegsNum *VUregsn); +void VU0regsMI_FTOI4(_VURegsNum *VUregsn); +void VU0regsMI_FTOI12(_VURegsNum *VUregsn); +void VU0regsMI_FTOI15(_VURegsNum *VUregsn); +void VU0regsMI_ITOF0(_VURegsNum *VUregsn); +void VU0regsMI_ITOF4(_VURegsNum *VUregsn); +void VU0regsMI_ITOF12(_VURegsNum *VUregsn); +void VU0regsMI_ITOF15(_VURegsNum *VUregsn); +void VU0regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn); +void VU0regsMI_SQRT(_VURegsNum *VUregsn); +void VU0regsMI_RSQRT(_VURegsNum *VUregsn); +void VU0regsMI_IADD(_VURegsNum *VUregsn); +void VU0regsMI_IADDI(_VURegsNum *VUregsn); +void VU0regsMI_IADDIU(_VURegsNum *VUregsn); +void VU0regsMI_IAND(_VURegsNum *VUregsn); +void VU0regsMI_IOR(_VURegsNum *VUregsn); +void VU0regsMI_ISUB(_VURegsNum *VUregsn); +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU0regsMI_MOVE(_VURegsNum *VUregsn); +void VU0regsMI_MFIR(_VURegsNum *VUregsn); +void VU0regsMI_MTIR(_VURegsNum *VUregsn); +void VU0regsMI_MR32(_VURegsNum *VUregsn); +void VU0regsMI_LQ(_VURegsNum *VUregsn); +void VU0regsMI_LQD(_VURegsNum *VUregsn); +void VU0regsMI_LQI(_VURegsNum *VUregsn); +void VU0regsMI_SQ(_VURegsNum *VUregsn); +void VU0regsMI_SQD(_VURegsNum *VUregsn); +void VU0regsMI_SQI(_VURegsNum *VUregsn); +void VU0regsMI_ILW(_VURegsNum *VUregsn); +void VU0regsMI_ISW(_VURegsNum *VUregsn); +void VU0regsMI_ILWR(_VURegsNum *VUregsn); +void VU0regsMI_ISWR(_VURegsNum *VUregsn); +void VU0regsMI_LOI(_VURegsNum *VUregsn); +void VU0regsMI_RINIT(_VURegsNum *VUregsn); +void VU0regsMI_RGET(_VURegsNum *VUregsn); +void VU0regsMI_RNEXT(_VURegsNum *VUregsn); +void VU0regsMI_RXOR(_VURegsNum *VUregsn); +void VU0regsMI_WAITQ(_VURegsNum *VUregsn); +void VU0regsMI_FSAND(_VURegsNum *VUregsn); +void VU0regsMI_FSEQ(_VURegsNum *VUregsn); +void VU0regsMI_FSOR(_VURegsNum *VUregsn); +void VU0regsMI_FSSET(_VURegsNum *VUregsn); +void VU0regsMI_FMAND(_VURegsNum *VUregsn); +void VU0regsMI_FMEQ(_VURegsNum *VUregsn); +void VU0regsMI_FMOR(_VURegsNum *VUregsn); +void VU0regsMI_FCAND(_VURegsNum *VUregsn); +void VU0regsMI_FCEQ(_VURegsNum *VUregsn); +void VU0regsMI_FCOR(_VURegsNum *VUregsn); +void VU0regsMI_FCSET(_VURegsNum *VUregsn); +void VU0regsMI_FCGET(_VURegsNum *VUregsn); +void VU0regsMI_IBEQ(_VURegsNum *VUregsn); +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBNE(_VURegsNum *VUregsn); +void VU0regsMI_B(_VURegsNum *VUregsn); +void VU0regsMI_BAL(_VURegsNum *VUregsn); +void VU0regsMI_JR(_VURegsNum *VUregsn); +void VU0regsMI_JALR(_VURegsNum *VUregsn); +void VU0regsMI_MFP(_VURegsNum *VUregsn); +void VU0regsMI_WAITP(_VURegsNum *VUregsn); +void VU0regsMI_ESADD(_VURegsNum *VUregsn); +void VU0regsMI_ERSADD(_VURegsNum *VUregsn); +void VU0regsMI_ELENG(_VURegsNum *VUregsn); +void VU0regsMI_ERLENG(_VURegsNum *VUregsn); +void VU0regsMI_EATANxy(_VURegsNum *VUregsn); +void VU0regsMI_EATANxz(_VURegsNum *VUregsn); +void VU0regsMI_ESUM(_VURegsNum *VUregsn); +void VU0regsMI_ERCPR(_VURegsNum *VUregsn); +void VU0regsMI_ESQRT(_VURegsNum *VUregsn); +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU0regsMI_ESIN(_VURegsNum *VUregsn); +void VU0regsMI_EATAN(_VURegsNum *VUregsn); +void VU0regsMI_EEXP(_VURegsNum *VUregsn); +void VU0regsMI_XGKICK(_VURegsNum *VUregsn); +void VU0regsMI_XTOP(_VURegsNum *VUregsn); +void VU0regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1MI_ABS(); +void VU1MI_ADD(); +void VU1MI_ADDi(); +void VU1MI_ADDq(); +void VU1MI_ADDx(); +void VU1MI_ADDy(); +void VU1MI_ADDz(); +void VU1MI_ADDw(); +void VU1MI_ADDA(); +void VU1MI_ADDAi(); +void VU1MI_ADDAq(); +void VU1MI_ADDAx(); +void VU1MI_ADDAy(); +void VU1MI_ADDAz(); +void VU1MI_ADDAw(); +void VU1MI_SUB(); +void VU1MI_SUBi(); +void VU1MI_SUBq(); +void VU1MI_SUBx(); +void VU1MI_SUBy(); +void VU1MI_SUBz(); +void VU1MI_SUBw(); +void VU1MI_SUBA(); +void VU1MI_SUBAi(); +void VU1MI_SUBAq(); +void VU1MI_SUBAx(); +void VU1MI_SUBAy(); +void VU1MI_SUBAz(); +void VU1MI_SUBAw(); +void VU1MI_MUL(); +void VU1MI_MULi(); +void VU1MI_MULq(); +void VU1MI_MULx(); +void VU1MI_MULy(); +void VU1MI_MULz(); +void VU1MI_MULw(); +void VU1MI_MULA(); +void VU1MI_MULAi(); +void VU1MI_MULAq(); +void VU1MI_MULAx(); +void VU1MI_MULAy(); +void VU1MI_MULAz(); +void VU1MI_MULAw(); +void VU1MI_MADD(); +void VU1MI_MADDi(); +void VU1MI_MADDq(); +void VU1MI_MADDx(); +void VU1MI_MADDy(); +void VU1MI_MADDz(); +void VU1MI_MADDw(); +void VU1MI_MADDA(); +void VU1MI_MADDAi(); +void VU1MI_MADDAq(); +void VU1MI_MADDAx(); +void VU1MI_MADDAy(); +void VU1MI_MADDAz(); +void VU1MI_MADDAw(); +void VU1MI_MSUB(); +void VU1MI_MSUBi(); +void VU1MI_MSUBq(); +void VU1MI_MSUBx(); +void VU1MI_MSUBy(); +void VU1MI_MSUBz(); +void VU1MI_MSUBw(); +void VU1MI_MSUBA(); +void VU1MI_MSUBAi(); +void VU1MI_MSUBAq(); +void VU1MI_MSUBAx(); +void VU1MI_MSUBAy(); +void VU1MI_MSUBAz(); +void VU1MI_MSUBAw(); +void VU1MI_MAX(); +void VU1MI_MAXi(); +void VU1MI_MAXx(); +void VU1MI_MAXy(); +void VU1MI_MAXz(); +void VU1MI_MAXw(); +void VU1MI_MINI(); +void VU1MI_MINIi(); +void VU1MI_MINIx(); +void VU1MI_MINIy(); +void VU1MI_MINIz(); +void VU1MI_MINIw(); +void VU1MI_OPMULA(); +void VU1MI_OPMSUB(); +void VU1MI_NOP(); +void VU1MI_FTOI0(); +void VU1MI_FTOI4(); +void VU1MI_FTOI12(); +void VU1MI_FTOI15(); +void VU1MI_ITOF0(); +void VU1MI_ITOF4(); +void VU1MI_ITOF12(); +void VU1MI_ITOF15(); +void VU1MI_CLIP(); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1MI_DIV(); +void VU1MI_SQRT(); +void VU1MI_RSQRT(); +void VU1MI_IADD(); +void VU1MI_IADDI(); +void VU1MI_IADDIU(); +void VU1MI_IAND(); +void VU1MI_IOR(); +void VU1MI_ISUB(); +void VU1MI_ISUBIU(); +void VU1MI_MOVE(); +void VU1MI_MFIR(); +void VU1MI_MTIR(); +void VU1MI_MR32(); +void VU1MI_LQ(); +void VU1MI_LQD(); +void VU1MI_LQI(); +void VU1MI_SQ(); +void VU1MI_SQD(); +void VU1MI_SQI(); +void VU1MI_ILW(); +void VU1MI_ISW(); +void VU1MI_ILWR(); +void VU1MI_ISWR(); +void VU1MI_LOI(); +void VU1MI_RINIT(); +void VU1MI_RGET(); +void VU1MI_RNEXT(); +void VU1MI_RXOR(); +void VU1MI_WAITQ(); +void VU1MI_FSAND(); +void VU1MI_FSEQ(); +void VU1MI_FSOR(); +void VU1MI_FSSET(); +void VU1MI_FMAND(); +void VU1MI_FMEQ(); +void VU1MI_FMOR(); +void VU1MI_FCAND(); +void VU1MI_FCEQ(); +void VU1MI_FCOR(); +void VU1MI_FCSET(); +void VU1MI_FCGET(); +void VU1MI_IBEQ(); +void VU1MI_IBGEZ(); +void VU1MI_IBGTZ(); +void VU1MI_IBLTZ(); +void VU1MI_IBLEZ(); +void VU1MI_IBNE(); +void VU1MI_B(); +void VU1MI_BAL(); +void VU1MI_JR(); +void VU1MI_JALR(); +void VU1MI_MFP(); +void VU1MI_WAITP(); +void VU1MI_ESADD(); +void VU1MI_ERSADD(); +void VU1MI_ELENG(); +void VU1MI_ERLENG(); +void VU1MI_EATANxy(); +void VU1MI_EATANxz(); +void VU1MI_ESUM(); +void VU1MI_ERCPR(); +void VU1MI_ESQRT(); +void VU1MI_ERSQRT(); +void VU1MI_ESIN(); +void VU1MI_EATAN(); +void VU1MI_EEXP(); +void VU1MI_XGKICK(); +void VU1MI_XTOP(); +void VU1MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn); +void VU1regsMI_ADD(_VURegsNum *VUregsn); +void VU1regsMI_ADDi(_VURegsNum *VUregsn); +void VU1regsMI_ADDq(_VURegsNum *VUregsn); +void VU1regsMI_ADDx(_VURegsNum *VUregsn); +void VU1regsMI_ADDy(_VURegsNum *VUregsn); +void VU1regsMI_ADDz(_VURegsNum *VUregsn); +void VU1regsMI_ADDw(_VURegsNum *VUregsn); +void VU1regsMI_ADDA(_VURegsNum *VUregsn); +void VU1regsMI_ADDAi(_VURegsNum *VUregsn); +void VU1regsMI_ADDAq(_VURegsNum *VUregsn); +void VU1regsMI_ADDAx(_VURegsNum *VUregsn); +void VU1regsMI_ADDAy(_VURegsNum *VUregsn); +void VU1regsMI_ADDAz(_VURegsNum *VUregsn); +void VU1regsMI_ADDAw(_VURegsNum *VUregsn); +void VU1regsMI_SUB(_VURegsNum *VUregsn); +void VU1regsMI_SUBi(_VURegsNum *VUregsn); +void VU1regsMI_SUBq(_VURegsNum *VUregsn); +void VU1regsMI_SUBx(_VURegsNum *VUregsn); +void VU1regsMI_SUBy(_VURegsNum *VUregsn); +void VU1regsMI_SUBz(_VURegsNum *VUregsn); +void VU1regsMI_SUBw(_VURegsNum *VUregsn); +void VU1regsMI_SUBA(_VURegsNum *VUregsn); +void VU1regsMI_SUBAi(_VURegsNum *VUregsn); +void VU1regsMI_SUBAq(_VURegsNum *VUregsn); +void VU1regsMI_SUBAx(_VURegsNum *VUregsn); +void VU1regsMI_SUBAy(_VURegsNum *VUregsn); +void VU1regsMI_SUBAz(_VURegsNum *VUregsn); +void VU1regsMI_SUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MUL(_VURegsNum *VUregsn); +void VU1regsMI_MULi(_VURegsNum *VUregsn); +void VU1regsMI_MULq(_VURegsNum *VUregsn); +void VU1regsMI_MULx(_VURegsNum *VUregsn); +void VU1regsMI_MULy(_VURegsNum *VUregsn); +void VU1regsMI_MULz(_VURegsNum *VUregsn); +void VU1regsMI_MULw(_VURegsNum *VUregsn); +void VU1regsMI_MULA(_VURegsNum *VUregsn); +void VU1regsMI_MULAi(_VURegsNum *VUregsn); +void VU1regsMI_MULAq(_VURegsNum *VUregsn); +void VU1regsMI_MULAx(_VURegsNum *VUregsn); +void VU1regsMI_MULAy(_VURegsNum *VUregsn); +void VU1regsMI_MULAz(_VURegsNum *VUregsn); +void VU1regsMI_MULAw(_VURegsNum *VUregsn); +void VU1regsMI_MADD(_VURegsNum *VUregsn); +void VU1regsMI_MADDi(_VURegsNum *VUregsn); +void VU1regsMI_MADDq(_VURegsNum *VUregsn); +void VU1regsMI_MADDx(_VURegsNum *VUregsn); +void VU1regsMI_MADDy(_VURegsNum *VUregsn); +void VU1regsMI_MADDz(_VURegsNum *VUregsn); +void VU1regsMI_MADDw(_VURegsNum *VUregsn); +void VU1regsMI_MADDA(_VURegsNum *VUregsn); +void VU1regsMI_MADDAi(_VURegsNum *VUregsn); +void VU1regsMI_MADDAq(_VURegsNum *VUregsn); +void VU1regsMI_MADDAx(_VURegsNum *VUregsn); +void VU1regsMI_MADDAy(_VURegsNum *VUregsn); +void VU1regsMI_MADDAz(_VURegsNum *VUregsn); +void VU1regsMI_MADDAw(_VURegsNum *VUregsn); +void VU1regsMI_MSUB(_VURegsNum *VUregsn); +void VU1regsMI_MSUBi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBw(_VURegsNum *VUregsn); +void VU1regsMI_MSUBA(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MAX(_VURegsNum *VUregsn); +void VU1regsMI_MAXi(_VURegsNum *VUregsn); +void VU1regsMI_MAXx(_VURegsNum *VUregsn); +void VU1regsMI_MAXy(_VURegsNum *VUregsn); +void VU1regsMI_MAXz(_VURegsNum *VUregsn); +void VU1regsMI_MAXw(_VURegsNum *VUregsn); +void VU1regsMI_MINI(_VURegsNum *VUregsn); +void VU1regsMI_MINIi(_VURegsNum *VUregsn); +void VU1regsMI_MINIx(_VURegsNum *VUregsn); +void VU1regsMI_MINIy(_VURegsNum *VUregsn); +void VU1regsMI_MINIz(_VURegsNum *VUregsn); +void VU1regsMI_MINIw(_VURegsNum *VUregsn); +void VU1regsMI_OPMULA(_VURegsNum *VUregsn); +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU1regsMI_NOP(_VURegsNum *VUregsn); +void VU1regsMI_FTOI0(_VURegsNum *VUregsn); +void VU1regsMI_FTOI4(_VURegsNum *VUregsn); +void VU1regsMI_FTOI12(_VURegsNum *VUregsn); +void VU1regsMI_FTOI15(_VURegsNum *VUregsn); +void VU1regsMI_ITOF0(_VURegsNum *VUregsn); +void VU1regsMI_ITOF4(_VURegsNum *VUregsn); +void VU1regsMI_ITOF12(_VURegsNum *VUregsn); +void VU1regsMI_ITOF15(_VURegsNum *VUregsn); +void VU1regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn); +void VU1regsMI_SQRT(_VURegsNum *VUregsn); +void VU1regsMI_RSQRT(_VURegsNum *VUregsn); +void VU1regsMI_IADD(_VURegsNum *VUregsn); +void VU1regsMI_IADDI(_VURegsNum *VUregsn); +void VU1regsMI_IADDIU(_VURegsNum *VUregsn); +void VU1regsMI_IAND(_VURegsNum *VUregsn); +void VU1regsMI_IOR(_VURegsNum *VUregsn); +void VU1regsMI_ISUB(_VURegsNum *VUregsn); +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU1regsMI_MOVE(_VURegsNum *VUregsn); +void VU1regsMI_MFIR(_VURegsNum *VUregsn); +void VU1regsMI_MTIR(_VURegsNum *VUregsn); +void VU1regsMI_MR32(_VURegsNum *VUregsn); +void VU1regsMI_LQ(_VURegsNum *VUregsn); +void VU1regsMI_LQD(_VURegsNum *VUregsn); +void VU1regsMI_LQI(_VURegsNum *VUregsn); +void VU1regsMI_SQ(_VURegsNum *VUregsn); +void VU1regsMI_SQD(_VURegsNum *VUregsn); +void VU1regsMI_SQI(_VURegsNum *VUregsn); +void VU1regsMI_ILW(_VURegsNum *VUregsn); +void VU1regsMI_ISW(_VURegsNum *VUregsn); +void VU1regsMI_ILWR(_VURegsNum *VUregsn); +void VU1regsMI_ISWR(_VURegsNum *VUregsn); +void VU1regsMI_LOI(_VURegsNum *VUregsn); +void VU1regsMI_RINIT(_VURegsNum *VUregsn); +void VU1regsMI_RGET(_VURegsNum *VUregsn); +void VU1regsMI_RNEXT(_VURegsNum *VUregsn); +void VU1regsMI_RXOR(_VURegsNum *VUregsn); +void VU1regsMI_WAITQ(_VURegsNum *VUregsn); +void VU1regsMI_FSAND(_VURegsNum *VUregsn); +void VU1regsMI_FSEQ(_VURegsNum *VUregsn); +void VU1regsMI_FSOR(_VURegsNum *VUregsn); +void VU1regsMI_FSSET(_VURegsNum *VUregsn); +void VU1regsMI_FMAND(_VURegsNum *VUregsn); +void VU1regsMI_FMEQ(_VURegsNum *VUregsn); +void VU1regsMI_FMOR(_VURegsNum *VUregsn); +void VU1regsMI_FCAND(_VURegsNum *VUregsn); +void VU1regsMI_FCEQ(_VURegsNum *VUregsn); +void VU1regsMI_FCOR(_VURegsNum *VUregsn); +void VU1regsMI_FCSET(_VURegsNum *VUregsn); +void VU1regsMI_FCGET(_VURegsNum *VUregsn); +void VU1regsMI_IBEQ(_VURegsNum *VUregsn); +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBNE(_VURegsNum *VUregsn); +void VU1regsMI_B(_VURegsNum *VUregsn); +void VU1regsMI_BAL(_VURegsNum *VUregsn); +void VU1regsMI_JR(_VURegsNum *VUregsn); +void VU1regsMI_JALR(_VURegsNum *VUregsn); +void VU1regsMI_MFP(_VURegsNum *VUregsn); +void VU1regsMI_WAITP(_VURegsNum *VUregsn); +void VU1regsMI_ESADD(_VURegsNum *VUregsn); +void VU1regsMI_ERSADD(_VURegsNum *VUregsn); +void VU1regsMI_ELENG(_VURegsNum *VUregsn); +void VU1regsMI_ERLENG(_VURegsNum *VUregsn); +void VU1regsMI_EATANxy(_VURegsNum *VUregsn); +void VU1regsMI_EATANxz(_VURegsNum *VUregsn); +void VU1regsMI_ESUM(_VURegsNum *VUregsn); +void VU1regsMI_ERCPR(_VURegsNum *VUregsn); +void VU1regsMI_ESQRT(_VURegsNum *VUregsn); +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU1regsMI_ESIN(_VURegsNum *VUregsn); +void VU1regsMI_EATAN(_VURegsNum *VUregsn); +void VU1regsMI_EEXP(_VURegsNum *VUregsn); +void VU1regsMI_XGKICK(_VURegsNum *VUregsn); +void VU1regsMI_XTOP(_VURegsNum *VUregsn); +void VU1regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU Micromode Tables/Opcodes defs macros +*****************************************/ + + +#define _vuTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])() = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])() = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])() = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])() = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])() = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])() = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00() { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](); \ +} \ + \ + void PREFIX##_UPPER_FD_01() { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_10() { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_11() { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP() { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](); \ +} \ + \ + void PREFIX##LowerOP_T3_00() { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_01() { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_10() { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_11() { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](); \ +} + +#define _vuRegsTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_01(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_10(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_11(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_00(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_01(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_10(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_11(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} + + +#ifdef VUM_LOG + +#define IdebugUPPER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroUF(VU.code, VU.VI[REG_TPC].UL)); } +#define IdebugLOWER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroLF(VU.code, VU.VI[REG_TPC].UL)); } + +#else + +#define IdebugUPPER(VU) +#define IdebugLOWER(VU) + +#endif + +#ifdef VUM_LOG +#define _vuExecMicroDebug(VU) \ + VUM_LOG("_vuExecMicro: %8.8x\n", VU.VI[REG_TPC].UL); +#else +#define _vuExecMicroDebug(VU) +#endif + +#include "VUops.h" + +#endif + diff --git a/branches/pcsx2_0.9.1/VUops.c b/branches/pcsx2_0.9.1/VUops.c new file mode 100644 index 0000000..3e29ef0 --- /dev/null +++ b/branches/pcsx2_0.9.1/VUops.c @@ -0,0 +1,2945 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU->code>>24) & 0x1) +#define _Y ((VU->code>>23) & 0x1) +#define _Z ((VU->code>>22) & 0x1) +#define _W ((VU->code>>21) & 0x1) + +#define _XYZW ((VU->code>>21) & 0xF) + +#define _Fsf_ ((VU->code >> 21) & 0x03) +#define _Ftf_ ((VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + + +VECTOR RDzero; + +void _vuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } +} + +void _vuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } +#endif + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } +} + +void _vuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing EFU pipe\n"); } +#endif + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } +} + +// called at end of program +void _vuFlushAll(VURegs* VU) +{ + int nRepeat = 1, i; + + do { + nRepeat = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + nRepeat = 1; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } + + if (VU->fdiv.enable ) { + + nRepeat = 1; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { + #ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } + #endif + nRepeat = 1; + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } + } + + if (VU->efu.enable) { + + nRepeat = 1; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { + #ifdef VUM_LOG + // if (Log) { VUM_LOG("flushing EFU pipe\n"); } + #endif + nRepeat = 1; + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } + } + + VU->cycle++; + + } while(nRepeat); +} + +void _vuTestPipes(VURegs * VU) { + _vuFMACflush(VU); + _vuFDIVflush(VU); + _vuEFUflush(VU); +} + +void _vuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + VU->fmac[i].xyzw & xyzw) break; + } + + if (i == 8) return; + + cycle = VU->fmac[i].Cycle - (VU->cycle - VU->fmac[i].sCycle) + 1; // add 1 delay! (fixes segaclassics bad geom) + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; +#ifdef VUM_LOG + if (Log) { VUM_LOG("FMAC[%d] stall %d\n", i, cycle); } +#endif + VU->cycle+= cycle; + _vuTestPipes(VU); +} + +void _vuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { +// SysPrintf("*PCSX2*: error , out of fmacs %d\n", VU->cycle); + } + +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FMAC pipe[%d]; xyzw=%x\n", i, xyzw); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = VU->cycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].reg = reg; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].macflag = VU->macflag; + VU->fmac[i].statusflag = VU->statusflag; + VU->fmac[i].clipflag = VU->clipflag; +} + +void _vuFDIVAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FDIV pipe\n"); } +#endif + VU->fdiv.enable = 1; + VU->fdiv.sCycle = VU->cycle; + VU->fdiv.Cycle = cycles; + VU->fdiv.reg.F = VU->q.F; + VU->fdiv.statusflag = VU->statusflag; +} + +void _vuEFUAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding EFU pipe\n"); } +#endif + VU->efu.enable = 1; + VU->efu.sCycle = VU->cycle; + VU->efu.Cycle = cycles; + VU->efu.reg.F = VU->p.F; +} + +void _vuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (VU->cycle - VU->fdiv.sCycle); +#ifdef VUM_LOG + if (Log) { VUM_LOG("waiting FDIV pipe %d\n", cycle); } +#endif + VU->fdiv.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; +} + +void _vuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (VU->cycle - VU->efu.sCycle); +#ifdef VUM_LOG +// if (Log) { VUM_LOG("waiting EFU pipe %d\n", cycle); } +#endif + VU->efu.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_P].UL = VU->efu.reg.UL; +} + +void _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFread0) { + _vuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _vuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } +} + +void _vuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _vuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { + _vuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _vuFMACAdd(VU, 0, 0); + } +} + +void _vuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushFDIV(VU); +} + +void _vuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_Q)) { + _vuFDIVAdd(VU, VUregsn->cycles); + } +} + + +void _vuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushEFU(VU); +} + +void _vuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_P)) { + _vuEFUAdd(VU, VUregsn->cycles); + } +} + +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + } +} + +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuTestEFUStalls(VU, VUregsn); break; + } +} + +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + } +} + +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuAddEFUStalls(VU, VUregsn); break; + } +} + + +/******************************/ +/* VU Upper instructions */ +/******************************/ +static u32 d; + +static float vuDouble(u32 f) +{ + switch(f & 0x7f800000){ + case 0x0: + f &= 0x80000000; + return *(float*)&f; + break; + case 0x7f800000: + d = (f & 0x80000000)|0x7f7fffff; + return *(float*)&d; + break; + default: + return *(float*)&f; + break; + } +} + +void _vuABS(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X){ VU->VF[_Ft_].f.x = fpufabsf(vuDouble(VU->VF[_Fs_].i.x)); } + if (_Y){ VU->VF[_Ft_].f.y = fpufabsf(vuDouble(VU->VF[_Fs_].i.y)); } + if (_Z){ VU->VF[_Ft_].f.z = fpufabsf(vuDouble(VU->VF[_Fs_].i.z)); } + if (_W){ VU->VF[_Ft_].f.w = fpufabsf(vuDouble(VU->VF[_Fs_].i.w)); } +}/*Reworked from define to function. asadr*/ + + +void _vuADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_I].UL));} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_I].UL));} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_I].UL));} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_I].UL));} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + fty);} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + fty);} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + fty);} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + fty);} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ti); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ti); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ti); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ti); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAq(VURegs * VU) { + float tf = vuDouble(VU->VI[REG_Q].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tf); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tf); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tf); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tf); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + + +void _vuSUBA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuMUL(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave Q reg in ti. asadr */ +void _vuMULAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave X reg in ti. asadr */ +void _vuMULAx(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAy(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAz(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAw(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + + +void _vuMADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +/* No need to presave . asadr */ +void _vuMADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftx)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftx)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftx)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * fty)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * fty)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * fty)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * fty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftz)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftz)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftz)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftw)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftw)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftw)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * ti)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * ti)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * ti)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * ti)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * tq)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * tq)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * tq)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * tq)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 10/05/03 shadow*/ + +void _vuMADDAx(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAy(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAz(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAw(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ti ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ti ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ti ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ti ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tq ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tq ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tq ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tq ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftx ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftx ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftx ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftx ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * fty ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * fty ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * fty ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * fty ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftz ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftz ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftz ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftz ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftw ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftw ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftw ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftw ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAi(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAq(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tx)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tx)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tx)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ty)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ty)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ty)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tz)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tz)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tz)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tw)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tw)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tw)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +u32 _MAX(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? b : a; + } else { // +b + return b; + } + } else { // +a + if (b & 0x80000000) { // -b + return a; + } else { // +b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMAX(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMAXi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMAXx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMAXy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMAXz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMAXw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftw); +} + +u32 _MINI(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? b : a; + } else { // +b + return a; + } + } else { // +a + if (b & 0x80000000) { // -b + return b; + } else { // +b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMINI(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMINIi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMINIx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMINIy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMINIz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMINIw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftw); +} + +void _vuOPMULA(VURegs * VU) { + VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); + VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); + VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuOPMSUB(VURegs * VU) { + VECTOR * dst; + float ftx, fty, ftz; + float fsx, fsy, fsz; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx = vuDouble(VU->VF[_Ft_].i.x); fty = vuDouble(VU->VF[_Ft_].i.y); ftz = vuDouble(VU->VF[_Ft_].i.z); + fsx = vuDouble(VU->VF[_Fs_].i.x); fsy = vuDouble(VU->VF[_Fs_].i.y); fsz = vuDouble(VU->VF[_Fs_].i.z); + dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - fsy * ftz); + dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - fsz * ftx); + dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - fsx * fty); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuNOP(VURegs * VU) { +} + +void _vuFTOI0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)vuDouble(VU->VF[_Fs_].i.x); + if (_Y) VU->VF[_Ft_].SL[1] = (s32)vuDouble(VU->VF[_Fs_].i.y); + if (_Z) VU->VF[_Ft_].SL[2] = (s32)vuDouble(VU->VF[_Fs_].i.z); + if (_W) VU->VF[_Ft_].SL[3] = (s32)vuDouble(VU->VF[_Fs_].i.w); +} + +void _vuFTOI4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int4(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int4(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int4(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int4(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int12(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int12(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int12(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int12(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int15(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int15(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int15(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int15(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuITOF0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = (float)VU->VF[_Fs_].SL[0]; + if (_Y) VU->VF[_Ft_].f.y = (float)VU->VF[_Fs_].SL[1]; + if (_Z) VU->VF[_Ft_].f.z = (float)VU->VF[_Fs_].SL[2]; + if (_W) VU->VF[_Ft_].f.w = (float)VU->VF[_Fs_].SL[3]; +} + +void _vuITOF4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int4_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int4_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int4_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int4_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int12_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int12_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int12_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int12_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int15_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int15_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int15_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int15_to_float(VU->VF[_Fs_].SL[3]); +} + +/* Different type of clipping by presaving w. asadr */ +void _vuCLIP(VURegs * VU) { + float value = fpufabsf(vuDouble(VU->VF[_Ft_].i.w)); + + VU->clipflag <<= 6; + if ( vuDouble(VU->VF[_Fs_].i.x) > +value ) VU->clipflag|= 0x01; + if ( vuDouble(VU->VF[_Fs_].i.x) < -value ) VU->clipflag|= 0x02; + if ( vuDouble(VU->VF[_Fs_].i.y) > +value ) VU->clipflag|= 0x04; + if ( vuDouble(VU->VF[_Fs_].i.y) < -value ) VU->clipflag|= 0x08; + if ( vuDouble(VU->VF[_Fs_].i.z) > +value ) VU->clipflag|= 0x10; + if ( vuDouble(VU->VF[_Fs_].i.z) < -value ) VU->clipflag|= 0x20; + VU->clipflag = VU->clipflag & 0xFFFFFF; + VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; + + +}/*last update 16/07/05 refraction - Needs checking */ + + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuDIV(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft == 0.0) { + if (fs == 0.0) { + VU->statusflag |= 0x10; + } else { + VU->statusflag |= 0x20; + } + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } else { + VU->q.F = fs / ft; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + +void _vuSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + +// _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft < 0.0 ) + VU->statusflag |= 0x10; + VU->q.F = fpusqrtf(fpufabsf(ft)); + VU->q.F = vuDouble(VU->q.UL); +} //last update 15/01/06 zerofrog + + +/* Eminent Bug - Dvisior == 0 Check Missing ( D Flag Not Set ) */ +/* REFIXED....ASADR; rerefixed....zerofrog */ +void _vuRSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + float temp; + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if ( ft == 0.0 ) { + VU->statusflag |= 0x20; + + if( fs != 0 ) { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } + else { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0x80000000; + } else { + VU->q.UL = 0; + } + + VU->statusflag |= 0x10; + } + + } else { + if (ft < 0.0) { + VU->statusflag |= 0x10; + } + + temp = fpusqrtf(fpufabsf(ft)); + VU->q.F = fs / temp; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + + +void _vuIADDI(VURegs * VU) { + s16 imm = ((VU->code >> 6) & 0x1f); + imm = ((imm & 0x10 ? 0xfff0 : 0) | (imm & 0xf)); + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + imm; +}//last checked 17/05/03 shadow NOTE: not quite sure about that + +void _vuIADDIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +}//last checked 17/05/03 shadow + +void _vuIADD(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] + VU->VI[_Ft_].SS[0]; +}//last checked 17/05/03 shadow + +void _vuIAND(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] & VU->VI[_Ft_].US[0]; +}//last checked 17/05/03 shadow + +void _vuIOR(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] | VU->VI[_Ft_].US[0]; +} + +void _vuISUB(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] - VU->VI[_Ft_].SS[0]; +} + +void _vuISUBIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] - (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +} + +void _vuMOVE(VURegs * VU) { + if(_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VF[_Fs_].UL[0]; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VF[_Fs_].UL[1]; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VF[_Fs_].UL[2]; + if (_W) VU->VF[_Ft_].UL[3] = VU->VF[_Fs_].UL[3]; +}//last checked 17/05/03 shadow + +void _vuMFIR(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)VU->VI[_Fs_].SS[0]; + if (_Y) VU->VF[_Ft_].SL[1] = (s32)VU->VI[_Fs_].SS[0]; + if (_Z) VU->VF[_Ft_].SL[2] = (s32)VU->VI[_Fs_].SS[0]; + if (_W) VU->VF[_Ft_].SL[3] = (s32)VU->VI[_Fs_].SS[0]; +} + +// Big bug!!! mov from fs to ft not ft to fs. asadr +void _vuMTIR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = *(u16*)&VU->VF[_Fs_].F[_Fsf_]; +} + +void _vuMR32(VURegs * VU) { + u32 tx; + if (_Ft_ == 0) return; + + tx = VU->VF[_Fs_].i.x; + if (_X) VU->VF[_Ft_].i.x = VU->VF[_Fs_].i.y; + if (_Y) VU->VF[_Ft_].i.y = VU->VF[_Fs_].i.z; + if (_Z) VU->VF[_Ft_].i.z = VU->VF[_Fs_].i.w; + if (_W) VU->VF[_Ft_].i.w = tx; +}//last updated 23/10/03 linuzappz + +void _vuLQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQD( VURegs * VU ) { + u32 addr; + u32 *ptr; + + if (_Fs_ != 0) VU->VI[_Fs_].US[0]--; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQI(VURegs * VU) { + if (_Ft_) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; + } + if (_Fs_ != 0) VU->VI[_Fs_].US[0]++; +} + +/* addr is now signed. Asadr */ +void _vuSQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Ft_].SS[0]) * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQD(VURegs * VU) { + u32 addr; + u32 *ptr; + + if(_Ft_ != 0) VU->VI[_Ft_].US[0]--; + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQI(VURegs * VU) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; + if(_Ft_ != 0) VU->VI[_Ft_].US[0]++; +} + +/* addr now signed. asadr */ +void _vuILW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +void _vuILWR(VURegs * VU) { + u32 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISWR(VURegs * VU) { + u32 addr; + u16 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +/* code contributed by _Riff_ + +The following code implements a Galois form M-series LFSR that can be configured to have a width from 0 to 32. +A Galois field can be represented as G(X) = g_m * X^m + g_(m-1) * X^(m-1) + ... + g_1 * X^1 + g0. +A Galois form M-Series LFSR represents a Galois field where g0 = g_m = 1 and the generated set contains 2^M - 1 values. +In modulo-2 arithmetic, addition is replaced by XOR and multiplication is replaced by AND. +The code is written in such a way that the polynomial lsb (g0) should be set to 0 and g_m is not represented. +As an example for setting the polynomial variable correctly, the 23-bit M-series generating polynomial X^23+X^14 + would be specified as (1 << 14). +*/ + + +//The two-tap 23 stage M-series polynomials are x23+x18 and x23+x14 ((1 << 18) and (1 << 14), respectively). +//The reverse sequences can be generated by x23+x(23-18) and x23+x(23-14) ((1 << 9) and (1 << 5), respectively) +u32 poly = 1 << 5; + +void SetPoly(u32 newPoly) { + poly = poly & ~1; +} + +void AdvanceLFSR(VURegs * VU) { + // code from www.project-fao.org + int x = (VU->VI[REG_R].UL >> 4) & 1; + int y = (VU->VI[REG_R].UL >> 22) & 1; + VU->VI[REG_R].UL <<= 1; + VU->VI[REG_R].UL ^= x ^ y; + VU->VI[REG_R].UL = (VU->VI[REG_R].UL&0x7fffff)|0x3f800000; +} +// old +// u32 lfsr = VU->VI[REG_R].UL & 0x007FFFFF; +// u32 oldlfsr = lfsr; +// lfsr <<= 1; +// if (oldlfsr & 0x00400000) { +// lfsr ^= poly; +// lfsr |= 1; +// } +// +// VU->VI[REG_R].UL = 0x3F800000 | (lfsr & 0x007FFFFF); + +void _vuRINIT(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | (VU->VF[_Fs_].UL[_Fsf_] & 0x007FFFFF); +} + +void _vuRGET(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRNEXT(VURegs * VU) { + if (_Ft_ == 0) return; + AdvanceLFSR(VU); + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRXOR(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | ((VU->VI[REG_R].UL ^ VU->VF[_Fs_].UL[_Fsf_]) & 0x007FFFFF); +} + +void _vuWAITQ(VURegs * VU) { +} + +void _vuFSAND(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) & imm; +} + +void _vuFSEQ(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + if((VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) == imm) VU->VI[_Ft_].US[0] = 1; + else VU->VI[_Ft_].US[0] = 0; +} + +void _vuFSOR(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) | imm; +} + +void _vuFSSET(VURegs * VU) { + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + VU->statusflag = (imm & 0xFC0) | (VU->VI[REG_STATUS_FLAG].US[0] & 0x3F); +} + +void _vuFMAND(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[_Fs_].US[0] & (VU->VI[REG_MAC_FLAG].UL & 0xFFFF); +} + +void _vuFMEQ(VURegs * VU) { + if(_Ft_ == 0) return; + if((VU->VI[REG_MAC_FLAG].UL & 0xFFFF) == VU->VI[_Fs_].US[0]){ + VU->VI[_Ft_].US[0] =1;} else { VU->VI[_Ft_].US[0] =0; } +} + +void _vuFMOR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_MAC_FLAG].UL & 0xFFFF) | VU->VI[_Fs_].US[0]; +} + +void _vuFCAND(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) & (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCEQ(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) == (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCOR(VURegs * VU) { + u32 hold = (VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) | ( VU->code & 0xFFFFFF); + if(hold == 0xFFFFFF) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCSET(VURegs * VU) { + VU->clipflag = (u32) (VU->code & 0xFFFFFF); + VU->VI[REG_CLIP_FLAG].UL = (u32) (VU->code & 0xFFFFFF); +} + +void _vuFCGET(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[REG_CLIP_FLAG].UL & 0x0FFF; +} + +s32 _branchAddr(VURegs * VU) { + s32 bpc = VU->VI[REG_TPC].SL + _Imm11_ * 8; + if (bpc < 0) { + bpc = VU->VI[REG_TPC].SL + _UImm11_ * 8; + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void _setBranch(VURegs * VU, u32 bpc) { + VU->branch = 2; + VU->branchpc = bpc; +// VU->vuExec(VU); +// VU->VI[REG_TPC].UL = bpc; +} + +void _vuIBEQ(VURegs * VU) { + if (VU->VI[_Ft_].US[0] == VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] >= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] > 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] <= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] < 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBNE(VURegs * VU) { + if (VU->VI[_Ft_].US[0] != VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuB(VURegs * VU) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); +} + +void _vuBAL(VURegs * VU) { + s32 bpc = _branchAddr(VU); + + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuJR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + _setBranch(VU, bpc); +} + +void _vuJALR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuMFP(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].i.x = VU->VI[REG_P].UL; + if (_Y) VU->VF[_Ft_].i.y = VU->VI[REG_P].UL; + if (_Z) VU->VF[_Ft_].i.z = VU->VI[REG_P].UL; + if (_W) VU->VF[_Ft_].i.w = VU->VI[REG_P].UL; +} + +void _vuWAITP(VURegs * VU) { +} + +void _vuESADD(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + VU->p.F = p; +} + +void _vuERSADD(VURegs * VU) { + float p = (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x)) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y)) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z)); + if (p != 0.0) + p = 1.0f / p; + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to value being -ve for sqrt *asadr */ +void _vuELENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if(p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERLENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if (p >= 0) { + p = fpusqrtf(p); + if (p != 0) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxy(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.y), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxz(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.z), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +void _vuESUM(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Fs_].i.w); + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERCPR(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p != 0){ + p = 1.0 / p; + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to Value being -ve for sqrt *asadr */ +void _vuESQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERSQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0) { + p = fpusqrtf(p); + if (p) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +void _vuESIN(VURegs * VU) { + float p = fpusinf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEATAN(VURegs * VU) { + float p = fpuatanf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEEXP(VURegs * VU) { + float p = fpuexpf(-(vuDouble(VU->VF[_Fs_].UL[_Fsf_]))); + VU->p.F = p; +} + +void _vuXITOP(VURegs * VU) { + if (_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->vifRegs->itop; +} + +void _vuXGKICK(VURegs * VU) +{ + // flush all pipelines first (in the right order) + _vuFlushAll(VU); + GSgifTransfer1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); +} + +void _vuXTOP(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (u16)VU->vifRegs->top; +} + +#define GET_VF0_FLAG(reg) (((reg)==0)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_I)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_Q)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_I)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_Q)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Ft_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw = 0xff; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0); \ +} + +#define VUREGS_IDISIT(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Fd_; \ + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); \ +} + +#define VUREGS_ITIS(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Ft_; \ + VUregsn->VIread = 1 << _Fs_; \ +} + +#define VUREGS_PFS(OP, _cycles) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_EFU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << REG_P; \ + VUregsn->VIread = GET_VF0_FLAG(_Fs_); \ + VUregsn->cycles = _cycles; \ +} + + + +VUREGS_FTFS(ABS); + +VUREGS_FDFSFT(ADD, 0); +VUREGS_FDFSI(ADDi, 0); +VUREGS_FDFSQ(ADDq, 0); +VUREGS_FDFSFTx(ADDx, 0); +VUREGS_FDFSFTy(ADDy, 0); +VUREGS_FDFSFTz(ADDz, 0); +VUREGS_FDFSFTw(ADDw, 0); + +VUREGS_ACCFSFT(ADDA, 0); +VUREGS_ACCFSI(ADDAi, 0); +VUREGS_ACCFSQ(ADDAq, 0); +VUREGS_ACCFSFTx(ADDAx, 0); +VUREGS_ACCFSFTy(ADDAy, 0); +VUREGS_ACCFSFTz(ADDAz, 0); +VUREGS_ACCFSFTw(ADDAw, 0); + +VUREGS_FDFSFT(SUB, 0); +VUREGS_FDFSI(SUBi, 0); +VUREGS_FDFSQ(SUBq, 0); +VUREGS_FDFSFTx(SUBx, 0); +VUREGS_FDFSFTy(SUBy, 0); +VUREGS_FDFSFTz(SUBz, 0); +VUREGS_FDFSFTw(SUBw, 0); + +VUREGS_ACCFSFT(SUBA, 0); +VUREGS_ACCFSI(SUBAi, 0); +VUREGS_ACCFSQ(SUBAq, 0); +VUREGS_ACCFSFTx(SUBAx, 0); +VUREGS_ACCFSFTy(SUBAy, 0); +VUREGS_ACCFSFTz(SUBAz, 0); +VUREGS_ACCFSFTw(SUBAw, 0); + +#define VUREGS_FDFSFTxyzw_MUL(OP, ACC, xyzw) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + if( _Ft_ == 0 && xyzw > 1 && _XYZW == 0xf ) { /* resetting to 0 */ \ + VUregsn->pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = (ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = GET_VF0_FLAG(_Fs_)|((ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 0; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_NONE; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_FTFS(FTOI0); +VUREGS_FTFS(FTOI4); +VUREGS_FTFS(FTOI12); +VUREGS_FTFS(FTOI15); +VUREGS_FTFS(ITOF0); +VUREGS_FTFS(ITOF4); +VUREGS_FTFS(ITOF12); +VUREGS_FTFS(ITOF15); + +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0x1; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1 << REG_CLIP_FLAG); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFr0xyzw = 0; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw = 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 12; +} + +VUREGS_ITIS(IADDI); +VUREGS_ITIS(IADDIU); +VUREGS_IDISIT(IADD); +VUREGS_IDISIT(IAND); +VUREGS_IDISIT(IOR); +VUREGS_IDISIT(ISUB); +VUREGS_ITIS(ISUBIU); + +VUREGS_FTFS(MOVE); + +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +VUREGS_FTFS(MR32); + +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = (1 << _Ft_); + VUregsn->VIread = (1 << _Fs_); +} + +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = (1 << REG_R)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_STATUS_FLAG; + VUregsn->VIread = 0;//1 << REG_STATUS_FLAG; this kills speed +} + +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = 0; +} + +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_P; +} + +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_EFU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_PFS(ESADD, 10); +VUREGS_PFS(ERSADD, 17); +VUREGS_PFS(ELENG, 17); +VUREGS_PFS(ERLENG, 23); +VUREGS_PFS(EATANxy, 53); +VUREGS_PFS(EATANxz, 53); +VUREGS_PFS(ESUM, 11); +VUREGS_PFS(ERCPR, 11); +VUREGS_PFS(ESQRT, 11); +VUREGS_PFS(ERSQRT, 17); +VUREGS_PFS(ESIN, 28); +VUREGS_PFS(EATAN, 53); +VUREGS_PFS(EEXP, 43); + +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_XGKICK; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} diff --git a/branches/pcsx2_0.9.1/VUops.h b/branches/pcsx2_0.9.1/VUops.h new file mode 100644 index 0000000..0b4a0f9 --- /dev/null +++ b/branches/pcsx2_0.9.1/VUops.h @@ -0,0 +1,393 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU1OPS_H__ +#define __VU1OPS_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include "VU.h" + +#define float_to_int4(x) (s32)((float)x * (1.0f / 0.0625f)) +#define float_to_int12(x) (s32)((float)x * (1.0f / 0.000244140625f)) +#define float_to_int15(x) (s32)((float)x * (1.0f / 0.000030517578125)) + +#define int4_to_float(x) (float)((float)x * 0.0625f) +#define int12_to_float(x) (float)((float)x * 0.000244140625f) +#define int15_to_float(x) (float)((float)x * 0.000030517578125) + +#define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) + +void _vuSetCycleFlags(VURegs * VU); +void _vuFlushFDIV(VURegs * VU); +void _vuFlushEFU(VURegs * VU); +void _vuTestPipes(VURegs * VU); +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuABS(VURegs * VU); +void _vuADD(VURegs * VU); +void _vuADDi(VURegs * VU); +void _vuADDq(VURegs * VU); +void _vuADDx(VURegs * VU); +void _vuADDy(VURegs * VU); +void _vuADDz(VURegs * VU); +void _vuADDw(VURegs * VU); +void _vuADDA(VURegs * VU); +void _vuADDAi(VURegs * VU); +void _vuADDAq(VURegs * VU); +void _vuADDAx(VURegs * VU); +void _vuADDAy(VURegs * VU); +void _vuADDAz(VURegs * VU); +void _vuADDAw(VURegs * VU); +void _vuSUB(VURegs * VU); +void _vuSUBi(VURegs * VU); +void _vuSUBq(VURegs * VU); +void _vuSUBx(VURegs * VU); +void _vuSUBy(VURegs * VU); +void _vuSUBz(VURegs * VU); +void _vuSUBw(VURegs * VU); +void _vuSUBA(VURegs * VU); +void _vuSUBAi(VURegs * VU); +void _vuSUBAq(VURegs * VU); +void _vuSUBAx(VURegs * VU); +void _vuSUBAy(VURegs * VU); +void _vuSUBAz(VURegs * VU); +void _vuSUBAw(VURegs * VU); +void _vuMUL(VURegs * VU); +void _vuMULi(VURegs * VU); +void _vuMULq(VURegs * VU); +void _vuMULx(VURegs * VU); +void _vuMULy(VURegs * VU); +void _vuMULz(VURegs * VU); +void _vuMULw(VURegs * VU); +void _vuMULA(VURegs * VU); +void _vuMULAi(VURegs * VU); +void _vuMULAq(VURegs * VU); +void _vuMULAx(VURegs * VU); +void _vuMULAy(VURegs * VU); +void _vuMULAz(VURegs * VU); +void _vuMULAw(VURegs * VU); +void _vuMADD(VURegs * VU) ; +void _vuMADDi(VURegs * VU); +void _vuMADDq(VURegs * VU); +void _vuMADDx(VURegs * VU); +void _vuMADDy(VURegs * VU); +void _vuMADDz(VURegs * VU); +void _vuMADDw(VURegs * VU); +void _vuMADDA(VURegs * VU); +void _vuMADDAi(VURegs * VU); +void _vuMADDAq(VURegs * VU); +void _vuMADDAx(VURegs * VU); +void _vuMADDAy(VURegs * VU); +void _vuMADDAz(VURegs * VU); +void _vuMADDAw(VURegs * VU); +void _vuMSUB(VURegs * VU); +void _vuMSUBi(VURegs * VU); +void _vuMSUBq(VURegs * VU); +void _vuMSUBx(VURegs * VU); +void _vuMSUBy(VURegs * VU); +void _vuMSUBz(VURegs * VU) ; +void _vuMSUBw(VURegs * VU) ; +void _vuMSUBA(VURegs * VU); +void _vuMSUBAi(VURegs * VU); +void _vuMSUBAq(VURegs * VU); +void _vuMSUBAx(VURegs * VU); +void _vuMSUBAy(VURegs * VU); +void _vuMSUBAz(VURegs * VU); +void _vuMSUBAw(VURegs * VU); +void _vuMAX(VURegs * VU); +void _vuMAXi(VURegs * VU); +void _vuMAXx(VURegs * VU); +void _vuMAXy(VURegs * VU); +void _vuMAXz(VURegs * VU); +void _vuMAXw(VURegs * VU); +void _vuMINI(VURegs * VU); +void _vuMINIi(VURegs * VU); +void _vuMINIx(VURegs * VU); +void _vuMINIy(VURegs * VU); +void _vuMINIz(VURegs * VU); +void _vuMINIw(VURegs * VU); +void _vuOPMULA(VURegs * VU); +void _vuOPMSUB(VURegs * VU); +void _vuNOP(VURegs * VU); +void _vuFTOI0(VURegs * VU); +void _vuFTOI4(VURegs * VU); +void _vuFTOI12(VURegs * VU); +void _vuFTOI15(VURegs * VU); +void _vuITOF0(VURegs * VU) ; +void _vuITOF4(VURegs * VU) ; +void _vuITOF12(VURegs * VU); +void _vuITOF15(VURegs * VU); +void _vuCLIP(VURegs * VU); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuDIV(VURegs * VU); +void _vuSQRT(VURegs * VU); +void _vuRSQRT(VURegs * VU); +void _vuIADDI(VURegs * VU); +void _vuIADDIU(VURegs * VU); +void _vuIADD(VURegs * VU); +void _vuIAND(VURegs * VU); +void _vuIOR(VURegs * VU); +void _vuISUB(VURegs * VU); +void _vuISUBIU(VURegs * VU); +void _vuMOVE(VURegs * VU); +void _vuMFIR(VURegs * VU); +void _vuMTIR(VURegs * VU); +void _vuMR32(VURegs * VU); +void _vuLQ(VURegs * VU) ; +void _vuLQD(VURegs * VU); +void _vuLQI(VURegs * VU); +void _vuSQ(VURegs * VU); +void _vuSQD(VURegs * VU); +void _vuSQI(VURegs * VU); +void _vuILW(VURegs * VU); +void _vuISW(VURegs * VU); +void _vuILWR(VURegs * VU); +void _vuISWR(VURegs * VU); +void _vuLOI(VURegs * VU); +void _vuRINIT(VURegs * VU); +void _vuRGET(VURegs * VU); +void _vuRNEXT(VURegs * VU); +void _vuRXOR(VURegs * VU); +void _vuWAITQ(VURegs * VU); +void _vuFSAND(VURegs * VU); +void _vuFSEQ(VURegs * VU); +void _vuFSOR(VURegs * VU); +void _vuFSSET(VURegs * VU); +void _vuFMAND(VURegs * VU); +void _vuFMEQ(VURegs * VU); +void _vuFMOR(VURegs * VU); +void _vuFCAND(VURegs * VU); +void _vuFCEQ(VURegs * VU); +void _vuFCOR(VURegs * VU); +void _vuFCSET(VURegs * VU); +void _vuFCGET(VURegs * VU); +void _vuIBEQ(VURegs * VU); +void _vuIBGEZ(VURegs * VU); +void _vuIBGTZ(VURegs * VU); +void _vuIBLEZ(VURegs * VU); +void _vuIBLTZ(VURegs * VU); +void _vuIBNE(VURegs * VU); +void _vuB(VURegs * VU); +void _vuBAL(VURegs * VU); +void _vuJR(VURegs * VU); +void _vuJALR(VURegs * VU); +void _vuMFP(VURegs * VU); +void _vuWAITP(VURegs * VU); +void _vuESADD(VURegs * VU); +void _vuERSADD(VURegs * VU); +void _vuELENG(VURegs * VU); +void _vuERLENG(VURegs * VU); +void _vuEATANxy(VURegs * VU); +void _vuEATANxz(VURegs * VU); +void _vuESUM(VURegs * VU); +void _vuERCPR(VURegs * VU); +void _vuESQRT(VURegs * VU); +void _vuERSQRT(VURegs * VU); +void _vuESIN(VURegs * VU); +void _vuEATAN(VURegs * VU); +void _vuEEXP(VURegs * VU); +void _vuXITOP(VURegs * VU); +void _vuXGKICK(VURegs * VU); +void _vuXTOP(VURegs * VU); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuRegsABS(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMUL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAX(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsNOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUBIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMOVE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLOI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsELENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERLENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESUM(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERCPR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESIN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATAN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEEXP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn); + +#endif diff --git a/branches/pcsx2_0.9.1/Vif.c b/branches/pcsx2_0.9.1/Vif.c new file mode 100644 index 0000000..385d145 --- /dev/null +++ b/branches/pcsx2_0.9.1/Vif.c @@ -0,0 +1,2950 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +VIFregisters *_vifRegs; +u32* _vifMaskRegs = NULL; +__declspec(align(16)) u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +u32* _vifRow = NULL; + +vifStruct *_vif; + +static int n; +static int i; + +__inline static int _limit( int a, int max ) +{ + return ( a > max ? max : a ); +} + +#define _UNPACKpart( offnum, func ) \ + if ( ( size > 0 ) && ( _vifRegs->offset == offnum ) ) { \ + func; \ + size--; \ + _vifRegs->offset++; \ + } + +#define _UNPACKpart_nosize( offnum, func ) \ + if ( ( _vifRegs->offset == offnum ) ) { \ + func; \ + _vifRegs->offset++; \ + } + +static void _writeX( u32 *dest, u32 data ) +{ + //int n; + + switch ( _vif->cl ) { + case 0: n = 0; break; + case 1: n = 8; break; + case 2: n = 16; break; + default: n = 24; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeX %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r0; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +#ifdef VIF_LOG + VIF_LOG("_writeX-done : Data %x : Row %x\n", *dest, _vifRegs->r0); +#endif +} + +static void _writeY( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 2; break; + case 1: n = 10; break; + case 2: n = 18; break; + default: n = 26; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeY %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r1; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +#ifdef VIF_LOG + VIF_LOG("_writeY-done : Data %x : Row %x\n", *dest, _vifRegs->r1); +#endif +} + +static void _writeZ( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 4; break; + case 1: n = 12; break; + case 2: n = 20; break; + default: n = 28; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeZ %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r2; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void _writeW( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 6; break; + case 1: n = 14; break; + case 2: n = 22; break; + default: n = 30; break; + } +#ifdef VIF_LOG + VIF_LOG("_writeW %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r3; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void writeX( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeX(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeX %8.8x : Mode %d, r0 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r0,data + _vifRegs->r0); +#endif +} + +static void writeY( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeY(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeY %8.8x : Mode %d, r1 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r1,data + _vifRegs->r1); +#endif +} + +static void writeZ( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeZ(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeZ %8.8x : Mode %d, r2 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r2,data + _vifRegs->r2); +#endif +} + +static void writeW( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeW(dest, data); return; } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } +#ifdef VIF_LOG + VIF_LOG("writeW %8.8x : Mode %d, r3 = %x, writing %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r3,data + _vifRegs->r3); +#endif +} + +void UNPACK_S_32(u32 *dest, u32 *data) { + writeX(dest++, *data); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_S_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data) ); + _UNPACKpart(1, writeY(dest++, *data) ); + _UNPACKpart(2, writeZ(dest++, *data) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)data - (u32)_data; +} + +#define _UNPACK_S_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_S_16s( u32 *dest, u32 *data ) { + _UNPACK_S_16( s16 ); +} + +void UNPACK_S_16u( u32 *dest, u32 *data ) { + _UNPACK_S_16( u16 ); +} + +#define _UNPACK_S_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata) ); \ + _UNPACKpart(1, writeY(dest++, *sdata) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_S_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(s16); +} + +int UNPACK_S_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(u16); +} + +#define _UNPACK_S_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_S_8s(u32 *dest, u32 *data) { + _UNPACK_S_8(s8); +} + +void UNPACK_S_8u(u32 *dest, u32 *data) { + _UNPACK_S_8(u8); +} + +#define _UNPACK_S_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata) ); \ + _UNPACKpart(1, writeY(dest++, *cdata) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_S_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(s8); +} + +int UNPACK_S_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(u8); +} + +void UNPACK_V2_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, 0); + writeW(dest++, 0); + +} + +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++)); + _UNPACKpart(1, writeY(dest++, *data++)); + _UNPACKpart_nosize(2, writeZ(dest++, 0)); + _UNPACKpart_nosize(3, writeW(dest++, 0)); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V2_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, 0); \ + writeW(dest++, 0); \ + + +void UNPACK_V2_16s(u32 *dest, u32 *data) { + _UNPACK_V2_16(s16); +} + +void UNPACK_V2_16u(u32 *dest, u32 *data) { + _UNPACK_V2_16(u16); +} + +#define _UNPACK_V2_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V2_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(s16); +} + +int UNPACK_V2_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(u16); +} + +#define _UNPACK_V2_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, 0); \ + writeW(dest++, 0); + +void UNPACK_V2_8s(u32 *dest, u32 *data) { + _UNPACK_V2_8(s8); +} + +void UNPACK_V2_8u(u32 *dest, u32 *data) { + _UNPACK_V2_8(u8); +} + +#define _UNPACK_V2_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V2_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(s8); +} + +int UNPACK_V2_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(u8); +} + +void UNPACK_V3_32(u32 *dest, u32 *data) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, 0); +} + +int UNPACK_V3_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++); ); + _UNPACKpart(1, writeY(dest++, *data++); ); + _UNPACKpart(2, writeZ(dest++, *data++); ); + _UNPACKpart_nosize(3, writeW(dest++, 0); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V3_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, 0); + +void UNPACK_V3_16s(u32 *dest, u32 *data) { + _UNPACK_V3_16(s16); +} + +void UNPACK_V3_16u(u32 *dest, u32 *data) { + _UNPACK_V3_16(u16); +} + +#define _UNPACK_V3_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart(2, writeZ(dest++, *sdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V3_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(s16); +} + +int UNPACK_V3_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(u16); +} + +#define _UNPACK_V3_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, 0); + +void UNPACK_V3_8s(u32 *dest, u32 *data) { + _UNPACK_V3_8(s8); +} + +void UNPACK_V3_8u(u32 *dest, u32 *data) { + _UNPACK_V3_8(u8); +} + +#define _UNPACK_V3_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart(2, writeZ(dest++, *cdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V3_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(s8); +} + +int UNPACK_V3_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(u8); +} + +void UNPACK_V4_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, *data++); +} + +int UNPACK_V4_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++) ); + _UNPACKpart(1, writeY(dest++, *data++) ); + _UNPACKpart(2, writeZ(dest++, *data++) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V4_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, *sdata++); + +void UNPACK_V4_16s(u32 *dest, u32 *data) { + _UNPACK_V4_16(s16); +} + +void UNPACK_V4_16u(u32 *dest, u32 *data) { + _UNPACK_V4_16(u16); +} + +#define _UNPACK_V4_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++) ); \ + _UNPACKpart(1, writeY(dest++, *sdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata++) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V4_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(s16); +} + +int UNPACK_V4_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(u16); +} + +#define _UNPACK_V4_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, *cdata++); + +void UNPACK_V4_8s(u32 *dest, u32 *data) { + _UNPACK_V4_8(s8); +} + +void UNPACK_V4_8u(u32 *dest, u32 *data) { + _UNPACK_V4_8(u8); +} + +#define _UNPACK_V4_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++) ); \ + _UNPACKpart(1, writeY(dest++, *cdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata++) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V4_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(s8); +} + +int UNPACK_V4_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(u8); +} + +void UNPACK_V4_5(u32 *dest, u32 *data) { + u16 *sdata = (u16*)data; + u32 rgba; + + rgba = *sdata++; + writeX(dest++, (rgba & 0x001f) << 3); + writeY(dest++, (rgba & 0x03e0) >> 2); + writeZ(dest++, (rgba & 0x7c00) >> 7); + writeW(dest++, (rgba & 0x8000) >> 8); +} + +int UNPACK_V4_5part(u32 *dest, u32 *data, int size) { + u16 *sdata = (u16*)data; + u32 rgba; + + while (size > 0) { + rgba = *sdata++; + _UNPACKpart(0, writeX(dest++, (rgba & 0x001f) << 3); ); + _UNPACKpart(1, writeY(dest++, (rgba & 0x03e0) >> 2); ); + _UNPACKpart(2, writeZ(dest++, (rgba & 0x7c00) >> 7); ); + _UNPACKpart(3, writeW(dest++, (rgba & 0x8000) >> 8); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)sdata - (u32)data; +} + +#if (defined(__i386__) || defined(__x86_64__)) + +// sse2 highly optimized vif (~200 separate functions are built) zerofrog(@gmail.com) +#include +#include + +__declspec(align(16)) u32 g_vif1Masks[64], g_vif0Masks[64]; +u32 g_vif1HasMask3[4] = {0}, g_vif0HasMask3[4] = {0}; + +//static const u32 writearr[4] = { 0xffffffff, 0, 0, 0 }; +//static const u32 rowarr[4] = { 0, 0xffffffff, 0, 0 }; +//static const u32 colarr[4] = { 0, 0, 0xffffffff, 0 }; +//static const u32 updatearr[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0 }; + +// arranged in writearr, rowarr, colarr, updatearr +static __declspec(align(16)) s_maskarr[16][4] = { + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff, + 0xffff0000, 0x00000000, 0x0000ffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, + 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff, + 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, + 0x00000000, 0xffff0000, 0x00000000, 0xffff0000, + 0x0000ffff, 0x00000000, 0xffff0000, 0xffffffff, + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x00000000, 0x00000000, 0x0000ffff, + 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, + 0x00000000, 0x00000000, 0x0000ffff, 0x0000ffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +u8 s_maskwrite[256]; +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask) +{ + u32 prev = 0; + FreezeXMMRegs(1); + + for(i = 0; i < 4; ++i, mask >>= 8, oldmask >>= 8, vif1masks += 16) { + + prev |= s_maskwrite[mask&0xff];//((mask&3)==3)||((mask&0xc)==0xc)||((mask&0x30)==0x30)||((mask&0xc0)==0xc0); + hasmask[i] = prev; + + if( (mask&0xff) != (oldmask&0xff) ) { + __m128i r0, r1, r2, r3; + r0 = _mm_load_si128((__m128i*)&s_maskarr[mask&15][0]); + r2 = _mm_unpackhi_epi16(r0, r0); + r0 = _mm_unpacklo_epi16(r0, r0); + + r1 = _mm_load_si128((__m128i*)&s_maskarr[(mask>>4)&15][0]); + r3 = _mm_unpackhi_epi16(r1, r1); + r1 = _mm_unpacklo_epi16(r1, r1); + + _mm_storel_pi((__m64*)&vif1masks[0], *(__m128*)&r0); + _mm_storel_pi((__m64*)&vif1masks[2], *(__m128*)&r1); + _mm_storeh_pi((__m64*)&vif1masks[4], *(__m128*)&r0); + _mm_storeh_pi((__m64*)&vif1masks[6], *(__m128*)&r1); + + _mm_storel_pi((__m64*)&vif1masks[8], *(__m128*)&r2); + _mm_storel_pi((__m64*)&vif1masks[10], *(__m128*)&r3); + _mm_storeh_pi((__m64*)&vif1masks[12], *(__m128*)&r2); + _mm_storeh_pi((__m64*)&vif1masks[14], *(__m128*)&r3); + } + } +} + +// msvc++ +#define VIF_SRC ecx +#define VIF_INC edx +#define VIF_DST edi + +// writing masks +#define UNPACK_Write0_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST+(DEST_OFFSET)], r0 \ +} \ + +#define UNPACK_Write1_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Write0_Mask UNPACK_Write0_Regular +#define UNPACK_Write1_Mask UNPACK_Write1_Regular + +#define UNPACK_Write0_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + /* masked write (dest needs to be in edi) */ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL) + 48] \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, 16 \ +} \ + +#define UNPACK_Write1_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0) + 48] \ + /* masked write (dest needs to be in edi) */ \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Mask_SSE_0(r0) \ +{ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ +} \ + +// once a qword is uncomprssed, applies masks and saves +// note: modifying XMM_WRITEMASK +#define UNPACK_Mask_SSE_1(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_Mask_SSE_2(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write \ + row = row + write (only when mask = 0), otherwise row */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd XMM_ROW, r0 \ + __asm por r0, XMM_ROWCOLMASK \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_WriteMask_SSE_0 UNPACK_Mask_SSE_0 +#define UNPACK_WriteMask_SSE_1 UNPACK_Mask_SSE_1 +#define UNPACK_WriteMask_SSE_2 UNPACK_Mask_SSE_2 + +#define UNPACK_Regular_SSE_0(r0) + +#define UNPACK_Regular_SSE_1(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ +} \ + +#define UNPACK_Regular_SSE_2(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ + __asm movdqa XMM_ROW, r0 \ +} \ + +// setting up masks +#define UNPACK_Setup_Mask_SSE(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_0(CL) UNPACK_Setup_Mask_SSE(CL); +#define UNPACK_Start_Setup_Mask_SSE_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Setup_Mask_SSE_0_1(CL) +#define UNPACK_Setup_Mask_SSE_1_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ +} \ + +#define UNPACK_Setup_Mask_SSE_2_1(CL) { \ + /* ignore CL, since vif.cycle.wl == 1 */ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(0) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(0) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Setup_Mask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) + +// write mask always destroys XMM_WRITEMASK, so 0_0 = 1_0 +#define UNPACK_Setup_WriteMask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_0_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_1_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_2_1(CL) UNPACK_Setup_Mask_SSE_2_1(CL) + +#define UNPACK_Start_Setup_WriteMask_SSE_0(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_1(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_2(CL) UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Start_Setup_Regular_SSE_0(CL) +#define UNPACK_Start_Setup_Regular_SSE_1(CL) +#define UNPACK_Start_Setup_Regular_SSE_2(CL) +#define UNPACK_Setup_Regular_SSE_0_0(CL) +#define UNPACK_Setup_Regular_SSE_1_0(CL) +#define UNPACK_Setup_Regular_SSE_2_0(CL) +#define UNPACK_Setup_Regular_SSE_0_1(CL) +#define UNPACK_Setup_Regular_SSE_1_1(CL) +#define UNPACK_Setup_Regular_SSE_2_1(CL) + +#define UNPACK_INC_DST_0_Regular(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Regular(qw) +#define UNPACK_INC_DST_0_Mask(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Mask(qw) +#define UNPACK_INC_DST_0_WriteMask(qw) +#define UNPACK_INC_DST_1_WriteMask(qw) + +// unpacks for 1,2,3,4 elements (V3 uses this directly) +#define UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ +} \ + +// V3 uses this directly +#define UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ +} \ + +#define UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(2) \ +} \ + +#define UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(1) \ +} \ + +// S-32 +// only when cl==1 +#define UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R3, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_S_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_S_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_S_32SSE_2A UNPACK_S_32SSE_2 + +#define UNPACK_S_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_32SSE_1A UNPACK_S_32SSE_1 + +// S-16 +#define UNPACK_S_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R3, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_S_16SSE_4A UNPACK_S_16SSE_4 + +#define UNPACK_S_16SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R2, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_S_16SSE_3A UNPACK_S_16SSE_3 + +#define UNPACK_S_16SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_16SSE_2A UNPACK_S_16SSE_2 + +#define UNPACK_S_16SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_16SSE_1A UNPACK_S_16SSE_1 + +// S-8 +#define UNPACK_S_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R3, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} + +#define UNPACK_S_8SSE_4A UNPACK_S_8SSE_4 + +#define UNPACK_S_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R2, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_S_8SSE_3A UNPACK_S_8SSE_3 + +#define UNPACK_S_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_8SSE_2A UNPACK_S_8SSE_2 + +#define UNPACK_S_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm inc VIF_SRC \ + } \ +} \ + +#define UNPACK_S_8SSE_1A UNPACK_S_8SSE_1 + +// V2-32 +#define UNPACK_V2_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+24] \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2A UNPACK_V2_32SSE_2 + +#define UNPACK_V2_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_32SSE_1A UNPACK_V2_32SSE_1 + +// V2-16 +#define UNPACK_V2_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, dword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V2-8 +#define UNPACK_V2_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V2_8SSE_4A UNPACK_V2_8SSE_4 + +#define UNPACK_V2_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V2_8SSE_3A UNPACK_V2_8SSE_3 + +#define UNPACK_V2_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_8SSE_2A UNPACK_V2_8SSE_2 + +#define UNPACK_V2_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V2_8SSE_1A UNPACK_V2_8SSE_1 + +// V3-32 +#define UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + __asm movdqu XMM_R3, qword ptr [VIF_SRC+36] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ + } \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V3_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ + } \ + { \ + __asm add VIF_SRC, 36 \ + } \ +} \ + +#define UNPACK_V3_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V3_32SSE_2A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_2(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_32SSE_1A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_1(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqu) + +// V3-16 +#define UNPACK_V3_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm movq XMM_R3, qword ptr [VIF_SRC+18] \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} + +#define UNPACK_V3_16SSE_4A UNPACK_V3_16SSE_4 + +#define UNPACK_V3_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 18 \ + } \ +} \ + +#define UNPACK_V3_16SSE_3A UNPACK_V3_16SSE_3 + +#define UNPACK_V3_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_16SSE_2A UNPACK_V3_16SSE_2 + +#define UNPACK_V3_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_16SSE_1A UNPACK_V3_16SSE_1 + +// V3-8 +#define UNPACK_V3_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R0, XMM_R1 \ + __asm psrldq XMM_R1, 6 \ + __asm punpcklwd XMM_R2, XMM_R3 \ + __asm psrldq XMM_R3, 6 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} + +#define UNPACK_V3_8SSE_4A UNPACK_V3_8SSE_4 + +#define UNPACK_V3_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, word ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm movd XMM_R2, dword ptr [VIF_SRC+6] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 9 \ + } \ +} \ + +#define UNPACK_V3_8SSE_3A UNPACK_V3_8SSE_3 + +#define UNPACK_V3_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R1, XMM_R1 \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_8SSE_2A UNPACK_V3_8SSE_2 + +#define UNPACK_V3_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_V3_8SSE_1A UNPACK_V3_8SSE_1 + +// V4-32 +#define UNPACK_V4_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqa XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqu XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +// V4-16 +#define UNPACK_V4_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + __asm punpckhwd XMM_R3, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +// V4-8 +#define UNPACK_V4_8SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movd XMM_R2, dword ptr [VIF_SRC+8] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V4-5 +__declspec(align(16)) static u32 s_TempDecompress[4] = {0}; + +#define DECOMPRESS_RGBA(OFFSET) { \ + /* R */ \ + __asm mov bl, al \ + __asm shl bl, 3 \ + __asm mov byte ptr [s_TempDecompress+OFFSET], bl \ + /* G */ \ + __asm mov bx, ax \ + __asm shr bx, 2 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+1], bl \ + /* B */ \ + __asm mov bx, ax \ + __asm shr bx, 7 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+2], bl \ + __asm mov bx, ax \ + __asm shr bx, 8 \ + __asm and bx, 0x80 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+3], bl \ +} \ + +#define UNPACK_V4_5SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm mov ax, word ptr [VIF_SRC+6] \ + } \ + DECOMPRESS_RGBA(12); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + __asm psrld XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V4_5SSE_4A UNPACK_V4_5SSE_4 + +#define UNPACK_V4_5SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V4_5SSE_3A UNPACK_V4_5SSE_3 + +#define UNPACK_V4_5SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm movq XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_5SSE_2A UNPACK_V4_5SSE_2 + +#define UNPACK_V4_5SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov ax, word ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm movd XMM_R0, dword ptr [s_TempDecompress] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V4_5SSE_1A UNPACK_V4_5SSE_1 + +#pragma warning(disable:4731) + +#ifdef _DEBUG +#define PUSHESI __asm mov s_saveesi, esi +#define POPESI __asm mov esi, s_saveesi +#else +#define PUSHESI +#define POPESI +#endif + +#define PUSHEDI +#define POPEDI +#define PUSHEBP //__asm mov dword ptr [esp-4], ebp +#define POPEBP //__asm mov ebp, dword ptr [esp-4] + +//__asm mov eax, pr0 \ +///* load row */ \ +//__asm movss XMM_ROW, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_ROW, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_ROW, XMM_R0 \ +//\ +//__asm mov eax, pc0 \ +//__asm movss XMM_R3, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_R3, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_R3, XMM_R0 \ + +#define SAVE_ROW_REG_BASE { \ + { \ + /* save the row reg */ \ + __asm mov eax, _vifRow \ + __asm movdqa qword ptr [eax], XMM_ROW \ + __asm mov eax, _vifRegs \ + __asm movss dword ptr [eax+0x100], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x110], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x120], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x130], XMM_ROW \ + } \ +} \ + +#define SAVE_NO_REG + +extern int g_nCounters[4]; + +static int tempcl = 0, incdest; +static int s_saveesi, s_saveinc; + +// qsize - bytes of compressed size of 1 decompressed qword +#define defUNPACK_SkippingWrite(name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG) \ +int UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType##(u32* dest, u32* data, int dmasize) \ +{ \ + incdest = ((_vifRegs->cycle.cl - _vifRegs->cycle.wl)<<4); \ + \ + switch( _vifRegs->cycle.wl ) { \ + case 1: \ + { \ + /*__asm inc dword ptr [g_nCounters] \ + __asm mov eax, dmasize \ + __asm add dword ptr [g_nCounters+4], eax*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov esi, dmasize \ + } \ + UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ + { \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm mov VIF_INC, incdest \ + __asm add VIF_INC, 16 \ + } \ + \ + /* first align VIF_SRC to 16 bytes */ \ +C1_Align16: \ + { \ + __asm test VIF_SRC, 15 \ + __asm jz C1_UnpackAligned \ + } \ + UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_DoneWithDec \ + __asm sub esi, qsize \ + __asm jmp C1_Align16 \ + } \ +C1_UnpackAligned: \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + __asm cmp esi, (4*qsize) \ + __asm jl C1_Unpack3 \ + __asm prefetchnta [eax + 192] \ + } \ +C1_Unpack4: \ + UNPACK_##name##SSE_4A(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (8*qsize) \ + __asm jl C1_DoneUnpack4 \ + __asm sub esi, (4*qsize) \ + __asm jmp C1_Unpack4 \ + } \ +C1_DoneUnpack4: \ + { \ + __asm sub esi, (4*qsize) \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + /* fall through */ \ + } \ +C1_Unpack3: \ + UNPACK_##name##SSE_3A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack2: \ + UNPACK_##name##SSE_2A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack1: \ + UNPACK_##name##SSE_1A(0, 1, MaskType, ModeType); \ +C1_DoneWithDec: \ + { \ + __asm sub esi, qsize \ + } \ +C1_Done3: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + case 2: \ + { \ + /*__asm inc dword ptr [g_nCounters+4]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (2*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C2_Done3 \ + } \ +C2_Unpack: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (4*qsize) \ + __asm jl C2_Done2 \ + __asm sub esi, (2*qsize) \ + __asm jmp C2_Unpack /* unpack next */ \ + } \ +C2_Done2: \ + { \ + __asm sub esi, (2*qsize) \ + } \ +C2_Done3: \ + { \ + __asm cmp esi, qsize \ + __asm jl C2_Done4 \ + } \ + /* execute left over qw */ \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + } \ +C2_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + case 3: \ + { \ + /*__asm inc dword ptr [g_nCounters+8]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (3*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C3_Done5 \ + } \ +C3_Unpack: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (6*qsize) \ + __asm jl C3_Done2 \ + __asm sub esi, (3*qsize) \ + __asm jmp C3_Unpack /* unpack next */ \ + } \ +C3_Done2: \ + { \ + __asm sub esi, (3*qsize) \ + } \ +C3_Done5: \ + { \ + __asm cmp esi, qsize \ + __asm jl C3_Done4 \ + /* execute left over qw */ \ + __asm cmp esi, (2*qsize) \ + __asm jl C3_Done3 \ + } \ + \ + /* process 2 qws */ \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C3_Done4 \ + } \ + \ +C3_Done3: \ + /* process 1 qw */ \ + { \ + __asm sub esi, qsize \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ +C3_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + default: /* >= 4 */ \ + tempcl = _vifRegs->cycle.wl-3; \ + { \ + /*__asm inc dword ptr [g_nCounters+12]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, tempcl \ + __asm mov s_saveinc, VIF_INC \ + __asm mov esi, dmasize \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + } \ +C4_Unpack: \ + { \ + __asm cmp esi, (3*qsize) \ + __asm jge C4_Unpack3 \ + __asm cmp esi, (2*qsize) \ + __asm jge C4_Unpack2 \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, qsize \ + __asm jmp C4_Done \ + } \ +C4_Unpack2: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C4_Done \ + } \ +C4_Unpack3: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + /* more data left, process 1qw at a time */ \ + __asm mov VIF_INC, s_saveinc \ + } \ +C4_UnpackX: \ + { \ + /* check if any data left */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + \ + } \ + UNPACK_##name##SSE_1(3, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + __asm cmp VIF_INC, 1 \ + __asm je C4_DoneLoop \ + __asm sub VIF_INC, 1 \ + __asm jmp C4_UnpackX \ + } \ +C4_DoneLoop: \ + { \ + __asm add VIF_DST, incdest /* take into account wl */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + __asm jmp C4_Unpack /* unpack next */ \ + } \ +C4_Done: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + } \ + \ + return dmasize; \ +} \ + +//{ \ +// /*__asm inc dword ptr [g_nCounters] \ +// __asm mov eax, dmasize \ +// __asm add dword ptr [g_nCounters+4], eax*/ \ +// PUSHESI \ +// PUSHEDI \ +// __asm mov esi, dmasize \ +// } \ +// UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ +// { \ +// __asm cmp esi, qsize \ +// __asm jl C1_Done3 \ +// \ +// /* move source and dest */ \ +// __asm mov VIF_DST, dest \ +// __asm mov VIF_SRC, data \ +// __asm mov VIF_INC, incdest \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// __asm cmp esi, (3*qsize) \ +// __asm jl C1_Unpack2 \ +// __asm imul VIF_INC, 3 \ +// __asm prefetchnta [eax + 192] \ +// } \ +//C1_Unpack3: \ +// UNPACK_##name##SSE_3(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm cmp esi, (6*qsize) \ +// __asm jl C1_DoneUnpack3 \ +// __asm sub esi, (3*qsize) \ +// __asm jmp C1_Unpack3 \ +// } \ +//C1_DoneUnpack3: \ +// { \ +// __asm sub esi, (3*qsize) \ +// __asm mov VIF_INC, dword ptr [esp] /* restore old ptr */ \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// /* fall through */ \ +// } \ +//C1_Unpack2: \ +// UNPACK_##name##SSE_2(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC \ +// __asm add VIF_DST, VIF_INC \ +// __asm sub esi, (2*qsize) \ +// __asm jmp C1_Done3 \ +// } \ +//C1_Unpack1: \ +// UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm sub esi, qsize \ +// } \ +//C1_Done3: \ +// { \ +// POPEDI \ +// __asm mov dmasize, esi \ +// POPESI \ +// } \ +// SAVE_ROW_REG; \ + +//while(size >= qsize) { +// funcP( dest, (u32*)cdata, chans); +// cdata += ft->qsize; +// size -= ft->qsize; +// +// if (vif->cl >= wl) { +// dest += incdest; +// vif->cl = 0; +// } +// else { +// dest += 4; +// vif->cl++; +// } +//} + +#define UNPACK_RIGHTSHIFT psrld +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_32, 4); +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_32, 8); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_32, 12); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_32, 16); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); +defUNPACK_SkippingWrite2(V4_5, 2); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#define UNPACK_RIGHTSHIFT psrad +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#endif + +static int cycles; + +int mfifoVIF1rbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((vif1ch->madr+(vif1ch->qwc << 4)) > (maddr+msize)) { + int s1 = (maddr+msize) - vif1ch->madr; + int s2 = (vif1ch->qwc << 4) - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s1/4, 0); + assert(ret == 0 ); // vif stall code not implemented + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s2/4, 0); + assert(ret == 0 ); // vif stall code not implemented + } else { + /* it doesn't, so just transfer 'qwc*4' words + from 'vif1ch->madr' to VIF1 */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + ret = VIF1transfer(src, vif1ch->qwc << 2, 0); + assert(ret == 0 ); // vif stall code not implemented + } + + vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->madr = psHu32(DMAC_RBOR) + (vif1ch->madr & psHu32(DMAC_RBSR)); + + return 0; +} + +int mfifoVIF1chain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (vif1ch->qwc == 0) return 0; + + if (vif1ch->madr >= maddr && + vif1ch->madr < (maddr+msize)) { + if (mfifoVIF1rbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) return -1; + ret = VIF1transfer(pMem, vif1ch->qwc << 2, 0); + assert(ret == 0 ); // vif stall code not implemented + + vif1ch->madr+= (vif1ch->qwc << 4); + } + + cycles+= (vif1ch->qwc) * BIAS; /* guessing */ + vif1ch->qwc = 0; + + return 0; +} + +void mfifoVIF1transfer(int qwc) { + u32 *ptag; + int id; + int done = 0, ret; + cycles = 0; + +#ifdef VIF_LOG + VIF_LOG("mfifoVIF1transfer %x\n", vif1ch->chcr); +#endif + if((vif1ch->chcr & 0x100) == 0)SysPrintf("MFIFO VIF1 not ready!\n"); + while (qwc > 0 && done == 0) { + vif1ch->tadr = psHu32(DMAC_RBOR) + (vif1ch->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(vif1ch->tadr); + + id = (ptag[0] >> 28) & 0x7; + vif1ch->qwc = (ptag[0] & 0xffff); + vif1ch->madr = ptag[1]; + cycles += 2; + if(vif1ch->chcr & 0x40) { + ret = VIF1transfer(ptag+2, 2, 1); + assert(ret == 0 ); // vif stall code not implemented + } + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr); +#endif + + switch (id) { + case 0: // refe + vif1ch->tadr += 16; + qwc = 0; + INT(10,cycles); + done = 1; + break; + + case 1: // cnt + vif1ch->madr = vif1ch->tadr + 16; + qwc-= vif1ch->qwc + 1; + // Set the taddr to the next tag + vif1ch->tadr += 16 + (vif1ch->qwc * 16); + break; + + case 3: // ref + case 4: // refs + vif1ch->tadr += 16; + qwc--; + break; + + case 7: // end + vif1ch->madr = vif1ch->tadr + 16; + vif1ch->tadr = vif1ch->madr + (vif1ch->qwc * 16); + qwc = 0; + INT(10,cycles); + done = 1; + break; + } + + if (mfifoVIF1chain() == -1) { + break; + } + + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef VIF_LOG + VIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoVIF1transfer: dmaIrq Set\n"); + qwc = 0; + done = 1; + INT(10,cycles); + } + } + if(done == 0 && qwc == 0)hwDmacIrq(14); + + vif1ch->tadr = psHu32(DMAC_RBOR) + (vif1ch->tadr & (psHu32(DMAC_RBSR))); + //hwDmacIrq(1); + + // restore + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vifMFIFOInterrupt() +{ + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); +// vif1ch->chcr &= ~0x100; +// vif1Regs->stat&= ~0x1F000000; // FQC=0 +// hwDmacIrq(DMAC_VIF1); +// +// if (vif1.irq > 0) { +// vif1.irq--; +// hwIntcIrq(5); // VIF1 Intc +// } + return 1; +} diff --git a/branches/pcsx2_0.9.1/Vif.h b/branches/pcsx2_0.9.1/Vif.h new file mode 100644 index 0000000..749171d --- /dev/null +++ b/branches/pcsx2_0.9.1/Vif.h @@ -0,0 +1,108 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VIF_H__ +#define __VIF_H__ + +typedef struct { + u8 cl, wl; + u8 pad[2]; +} vifCycle; + +typedef struct { + u32 stat; + u32 pad0[3]; + u32 fbrst; + u32 pad1[3]; + u32 err; + u32 pad2[3]; + u32 mark; + u32 pad3[3]; + vifCycle cycle; //data write cycle + u32 pad4[3]; + u32 mode; + u32 pad5[3]; + u32 num; + u32 pad6[3]; + u32 mask; + u32 pad7[3]; + u32 code; + u32 pad8[3]; + u32 itops; + u32 pad9[3]; + u32 base; // Not used in VIF0 + u32 pad10[3]; + u32 ofst; // Not used in VIF0 + u32 pad11[3]; + u32 tops; // Not used in VIF0 + u32 pad12[3]; + u32 itop; + u32 pad13[3]; + u32 top; // Not used in VIF0 + u32 pad14[3]; + u32 mskpath3; + u32 pad15[3]; + u32 r0; // row0 register + u32 pad16[3]; + u32 r1; // row1 register + u32 pad17[3]; + u32 r2; // row2 register + u32 pad18[3]; + u32 r3; // row3 register + u32 pad19[3]; + u32 c0; // col0 register + u32 pad20[3]; + u32 c1; // col1 register + u32 pad21[3]; + u32 c2; // col2 register + u32 pad22[3]; + u32 c3; // col3 register + u32 pad23[3]; + u32 offset; // internal UNPACK offset + u32 addr; +} VIFregisters; + +#define vif0Regs ((VIFregisters*)&PS2MEM_HW[0x3800]) +#define vif1Regs ((VIFregisters*)&PS2MEM_HW[0x3c00]) + +void dmaVIF0(); +void dmaVIF1(); +void mfifoVIF1transfer(int qwc); +int VIF0transfer(u32 *data, int size, int istag); +int VIF1transfer(u32 *data, int size, int istag); +int vifMFIFOInterrupt(); + +#if (defined(__i386__) || defined(__x86_64__)) +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask); +#else +#define SetNewMask 0&& +#endif + +#define XMM_R0 xmm0 +#define XMM_R1 xmm1 +#define XMM_R2 xmm2 +#define XMM_WRITEMASK xmm3 +#define XMM_ROWMASK xmm4 +#define XMM_ROWCOLMASK xmm5 +#define XMM_ROW xmm6 +#define XMM_COL xmm7 + +#define XMM_R3 XMM_COL + + +#endif /* __VIF_H__ */ diff --git a/branches/pcsx2_0.9.1/VifDma.c b/branches/pcsx2_0.9.1/VifDma.c new file mode 100644 index 0000000..a6c75e4 --- /dev/null +++ b/branches/pcsx2_0.9.1/VifDma.c @@ -0,0 +1,1872 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Vif.h" +#include "VUmicro.h" +#include "VifDma.h" + +#include + +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) + +// Extern variables +extern VIFregisters *_vifRegs; +extern vifStruct *_vif; +extern u32* _vifMaskRegs; +extern u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +extern u32* _vifRow; + +extern u32 g_vif1Masks[48], g_vif0Masks[48]; +extern u32 g_vif1HasMask3[4], g_vif0HasMask3[4]; + +#if (defined(__i386__) || defined(__x86_64__)) +#include +#include +#endif + +// Generic constants +static const unsigned int VIF0intc = 4; +static const unsigned int VIF1intc = 5; +static const unsigned int VIF0dmanum = 0; +static const unsigned int VIF1dmanum = 1; + +static int cycles; +extern HANDLE g_hGsEvent; +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +typedef void (*UNPACKFUNCTYPE)( u32 *dest, u32 *data ); +typedef int (*UNPACKPARTFUNCTYPE)( u32 *dest, u32 *data, int size ); + +typedef struct { + UNPACKFUNCTYPE funcU; + UNPACKFUNCTYPE funcS; + UNPACKPARTFUNCTYPE funcUpart; + UNPACKPARTFUNCTYPE funcSpart; + + int bsize; // total byte size of compressed data + int dsize; // byte size of one channel + int gsize; // repeat count + int qsize; // bytes of compressed size of 1 decompressed qword +} VIFUnpackFuncTable; + +/* block size; data size; group size; qword size; */ +#define _UNPACK_TABLE32(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name, UNPACK_##name, \ + UNPACK_##name##part, UNPACK_##name##part, \ + bsize, dsize, gsize, qsize }, + +#define _UNPACK_TABLE(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name##u, UNPACK_##name##s, \ + UNPACK_##name##upart, UNPACK_##name##spart, \ + bsize, dsize, gsize, qsize }, + +// Main table for function unpacking +static const VIFUnpackFuncTable VIFfuncTable[16] = { + _UNPACK_TABLE32(S_32, 12, 4, 4, 4) // 0x0 - S-32 + _UNPACK_TABLE(S_16, 6, 2, 4, 2) // 0x1 - S-16 + _UNPACK_TABLE(S_8, 3, 1, 4, 1) // 0x2 - S-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x3 + + _UNPACK_TABLE32(V2_32, 24, 4, 1, 8) // 0x4 - V2-32 + _UNPACK_TABLE(V2_16, 12, 2, 1, 4) // 0x5 - V2-16 + _UNPACK_TABLE(V2_8, 6, 1, 1, 2) // 0x6 - V2-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x7 + + _UNPACK_TABLE32(V3_32, 36, 4, 1, 12) // 0x8 - V3-32 + _UNPACK_TABLE(V3_16, 18, 2, 1, 6) // 0x9 - V3-16 + _UNPACK_TABLE(V3_8, 9, 1, 1, 3) // 0xA - V3-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0xB + + _UNPACK_TABLE32(V4_32, 48, 4, 1, 16) // 0xC - V4-32 + _UNPACK_TABLE(V4_16, 24, 2, 1, 8) // 0xD - V4-16 + _UNPACK_TABLE(V4_8, 12, 1, 1, 4) // 0xE - V4-8 + _UNPACK_TABLE32(V4_5, 6, 2, 1, 8) // 0xF - V4-5 +}; + +#if (defined(__i386__) || defined(__x86_64__)) + +typedef struct { + // regular 0, 1, 2; mask 0, 1, 2 + UNPACKPARTFUNCTYPE funcU[9], funcS[9]; +} VIFSSEUnpackTable; + +#define DECL_UNPACK_TABLE_SSE(name, sign) \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2(u32* dest, u32* data, int dmasize); \ + +#define _UNPACK_TABLE_SSE(name, sign) \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_2, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_2, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2 \ + +#define _UNPACK_TABLE_SSE_NULL \ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + +// Main table for function unpacking +DECL_UNPACK_TABLE_SSE(S_32, u); +DECL_UNPACK_TABLE_SSE(S_16, u); +DECL_UNPACK_TABLE_SSE(S_8, u); +DECL_UNPACK_TABLE_SSE(S_16, s); +DECL_UNPACK_TABLE_SSE(S_8, s); + +DECL_UNPACK_TABLE_SSE(V2_32, u); +DECL_UNPACK_TABLE_SSE(V2_16, u); +DECL_UNPACK_TABLE_SSE(V2_8, u); +DECL_UNPACK_TABLE_SSE(V2_16, s); +DECL_UNPACK_TABLE_SSE(V2_8, s); + +DECL_UNPACK_TABLE_SSE(V3_32, u); +DECL_UNPACK_TABLE_SSE(V3_16, u); +DECL_UNPACK_TABLE_SSE(V3_8, u); +DECL_UNPACK_TABLE_SSE(V3_16, s); +DECL_UNPACK_TABLE_SSE(V3_8, s); + +DECL_UNPACK_TABLE_SSE(V4_32, u); +DECL_UNPACK_TABLE_SSE(V4_16, u); +DECL_UNPACK_TABLE_SSE(V4_8, u); +DECL_UNPACK_TABLE_SSE(V4_16, s); +DECL_UNPACK_TABLE_SSE(V4_8, s); +DECL_UNPACK_TABLE_SSE(V4_5, u); + +static const VIFSSEUnpackTable VIFfuncTableSSE[16] = { + { _UNPACK_TABLE_SSE(S_32, u), _UNPACK_TABLE_SSE(S_32, u) }, + { _UNPACK_TABLE_SSE(S_16, u), _UNPACK_TABLE_SSE(S_16, s) }, + { _UNPACK_TABLE_SSE(S_8, u), _UNPACK_TABLE_SSE(S_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V2_32, u), _UNPACK_TABLE_SSE(V2_32, u) }, + { _UNPACK_TABLE_SSE(V2_16, u), _UNPACK_TABLE_SSE(V2_16, s) }, + { _UNPACK_TABLE_SSE(V2_8, u), _UNPACK_TABLE_SSE(V2_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V3_32, u), _UNPACK_TABLE_SSE(V3_32, u) }, + { _UNPACK_TABLE_SSE(V3_16, u), _UNPACK_TABLE_SSE(V3_16, s) }, + { _UNPACK_TABLE_SSE(V3_8, u), _UNPACK_TABLE_SSE(V3_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V4_32, u), _UNPACK_TABLE_SSE(V4_32, u) }, + { _UNPACK_TABLE_SSE(V4_16, u), _UNPACK_TABLE_SSE(V4_16, s) }, + { _UNPACK_TABLE_SSE(V4_8, u), _UNPACK_TABLE_SSE(V4_8, s) }, + { _UNPACK_TABLE_SSE(V4_5, u), _UNPACK_TABLE_SSE(V4_5, u) }, +}; + +#endif + + +void vif0FLUSH(); +void vif1FLUSH(); + +void vifDmaInit() { +} + +__inline static int _limit( int a, int max ) { + return ( a > max ? max : a ); +} + +static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdmanum) { + u32 *dest; + unsigned int unpackType; + UNPACKFUNCTYPE func; + UNPACKPARTFUNCTYPE funcP; + const VIFUnpackFuncTable *ft; + vifStruct *vif; + VIFregisters *vifRegs; + VURegs * VU; + u8 *cdata = (u8*)data; + int memsize; + + _mm_prefetch((char*)data, _MM_HINT_NTA); + + if (VIFdmanum == 0) { + VU = &VU0; + vif = &vif0; + vifRegs = vif0Regs; + memsize = 0x1000; + assert( v->addr < 0x4000 ); + v->addr &= 0xfff; + } else { + VU = &VU1; + vif = &vif1; + vifRegs = vif1Regs; + memsize = 0x4000; + v->addr &= 0x3fff; + } + + dest = (u32*)(VU->Mem + v->addr); + +#ifdef VIF_LOG + VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); +#endif + +/* if (vifRegs->cycle.cl > vifRegs->cycle.wl) { + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + }*/ +#ifdef _DEBUG + if (v->size != size) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning v->size != size\n"); +#endif + } + if ((v->addr+size*4) > memsize) { + SysPrintf("*PCSX2*: fixme unpack overflow\n"); + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + } +#endif + + if (size == 0) { + //SysPrintf("*PCSX2*: Unpack with size 0!!\n"); + return; + } + + // The unpack type + unpackType = v->cmd & 0xf; + + if(unpackType == 0xC && vifRegs->mode == 0 && !(vifRegs->code & 0x10000000) && vifRegs->cycle.cl == vifRegs->cycle.wl) { + // v4-32 + memcpy_amd((u8*)dest, cdata, size << 2); + size = 0; + return; + } + + _mm_prefetch((char*)data+128, _MM_HINT_NTA); + _vifRegs = (VIFregisters*)vifRegs; + _vifMaskRegs = VIFdmanum ? g_vif1Masks : g_vif0Masks; + _vif = vif; + _vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; + + // Unpacking + vif->wl = 0; vif->cl = 0; + //memsize = size; + size*= 4; + if (vifRegs->cycle.cl >= vifRegs->cycle.wl) { // skipping write + + if( !(v->addr&0xf) && cpucaps.hasStreamingSIMD2Extensions ) { + const UNPACKPARTFUNCTYPE* pfn; + int writemask; + //static LARGE_INTEGER lbase, lfinal; + //QueryPerformanceCounter(&lbase); + u32 oldcycle = -1; + FreezeXMMRegs(1); + +// u16 tempdata[4] = { 0x8000, 0x7fff, 0x1010, 0xd0d0 }; +// vifRegs->cycle.cl = 4; +// vifRegs->cycle.wl = 1; +// SetNewMask(g_vif1Masks, g_vif1HasMask3, 0x3f, ~0x3f); +// memset(dest, 0xcd, 64*4); +// VIFfuncTableSSE[1].funcS[6](dest, (u32*)tempdata, 8); + + if( VIFdmanum ) { + __asm movaps XMM_ROW, qword ptr [g_vifRow1] + __asm movaps XMM_COL, qword ptr [g_vifCol1] + } + else { + __asm movaps XMM_ROW, qword ptr [g_vifRow0] + __asm movaps XMM_COL, qword ptr [g_vifCol0] + } + + if( vifRegs->cycle.cl == 0 || vifRegs->cycle.wl == 0 || (vifRegs->cycle.cl == vifRegs->cycle.wl && !(vifRegs->code&0x10000000)) ) { + oldcycle = *(u32*)&vifRegs->cycle; + vifRegs->cycle.cl = vifRegs->cycle.wl = 1; + } + + pfn = vif->usn ? VIFfuncTableSSE[unpackType].funcU: VIFfuncTableSSE[unpackType].funcS; + writemask = VIFdmanum ? g_vif1HasMask3[min(vifRegs->cycle.wl-1,3)] : g_vif0HasMask3[min(vifRegs->cycle.wl-1,3)]; + writemask = pfn[(((vifRegs->code & 0x10000000)>>28)<mode](dest, (u32*)cdata, size); + + if( oldcycle != -1 ) *(u32*)&vifRegs->cycle = oldcycle; + + // if size is left over, update the src,dst pointers + if( writemask > 0 ) { + int left; + ft = &VIFfuncTable[ unpackType ]; + left = (size-writemask)/ft->qsize; + cdata += size-writemask; + dest = (u32*)((u8*)dest + ((left/vifRegs->cycle.wl)*vifRegs->cycle.cl + left%vifRegs->cycle.wl)*16); + } + + size = writemask; + + //QueryPerformanceCounter(&lfinal); + //((LARGE_INTEGER*)g_nCounters)->QuadPart += lfinal.QuadPart - lbase.QuadPart; + } + else { + int incdest, wl, chans; + ft = &VIFfuncTable[ unpackType ]; + // Assigning the normal upack function, the part type is assigned later + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + 4; + wl = vifRegs->cycle.wl-1; + chans = (ft->qsize/ft->dsize)*ft->gsize; + + //SysPrintf("slow vif\n"); + + while (size >= ft->qsize) { + funcP( dest, (u32*)cdata, chans); + cdata += ft->qsize; + size -= ft->qsize; + + if (vif->cl >= wl) { + dest += incdest; + vif->cl = 0; + } + else { + dest += 4; + vif->cl++; + } + } + } + + // used for debugging vif +// { +// int i, j; +// u32* curdest = (u32*)(VU->Mem + v->addr); +// FILE* ftemp = fopen("temp.txt", "a+"); +// fprintf(ftemp, "%x %x %x\n", vifRegs->code>>24, vifRegs->mode, *(u32*)&vifRegs->cycle); +// +// +// for(i = 0; i < memsize; ) { +// for(j = 0; j <= ((vifRegs->code>>26)&3); ++j) { +// fprintf(ftemp, "%x ", curdest[j]); +// } +// fprintf(ftemp, "\n"); +// curdest += 4*vifRegs->cycle.cl; +// i += j; +// } +// fclose(ftemp); +// } + +#ifdef VIF_LOG + VIF_LOG("remaining %d\n", size); +#endif + + if( size > 0 ) { +#ifdef VIF_LOG + VIF_LOG("warning, end with size = %d\n", size); +#endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + while (size >= ft->dsize) { + if (vif->cl < vifRegs->cycle.wl) { /* unpack one qword */ + size-= funcP(dest, (u32*)cdata, (size/ft->dsize)*ft->gsize); + break; + } + dest += 4; + vif->cl++; + if (vif->cl == vifRegs->cycle.cl) { + vif->cl = 0; + } + } + } + } else + if (vifRegs->cycle.cl < vifRegs->cycle.wl) { /* filling write */ +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: filling write\n"); +#endif + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + SysPrintf("filling write\n"); + + while (size >= ft->bsize) { + if (vif->wl == vifRegs->cycle.wl) { + vif->wl = 0; + } + func(dest, (u32*)cdata); + if (vif->wl < vifRegs->cycle.cl) { /* unpack one qword */ + cdata += ft->bsize; + size -= ft->bsize; + vif->cl++; + if (vif->cl == vifRegs->cycle.cl) { + vif->cl = 0; + } + } + dest += 4; + vif->wl++; + } + } else { + + // why is this code here? + assert(0); +// while ( size >= ft->bsize ) { +// func(dest, (u32*)cdata); +// dest += 12; +// cdata += ft->bsize; +// size -= ft->bsize; +// vif->cl++; vif->wl++; +// if (vif->cl == vifRegs->cycle.cl) { +// vif->cl = 0; +// } +// if (vif->wl == vifRegs->cycle.wl) { +// vif->wl = 0; +// } +// } +// while (size >= ft->dsize) { +// if (vif->cl < vifRegs->cycle.wl) { /* unpack one qword */ +// funcP(dest, (u32*)cdata, (size/ft->dsize)*ft->gsize); +// break; +// } +// dest += 4; +// vif->cl++; +// if (vif->cl == vifRegs->cycle.cl) { +// vif->cl = 0; +// } +// } + } + + if (size > 0) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning size(%d) > 0 after unpack\n", size); +#endif + } +} + +static void vuExecMicro( u32 addr, const unsigned int VIFdmanum ) { + + VURegs * VU; + //void (*_vuExecMicro)(); + +// MessageBox(NULL, "3d doesn't work\n", "Query", MB_OK); +// return; + + if (VIFdmanum == 0) { + //_vuExecMicro = Cpu->ExecuteVU0Block; + VU = &VU0; + vif0FLUSH(); + } else { + //_vuExecMicro = Cpu->ExecuteVU1Block; + VU = &VU1; + vif1FLUSH(); + } + + VU->vifRegs->itop = VU->vifRegs->itops; + + if (VIFdmanum == 1) { + /* in case we're handling a VIF1 execMicro + set the top with the tops value */ + VU->vifRegs->top = VU->vifRegs->tops; + + /* is DBF flag set in VIF_STAT? */ + if (VU->vifRegs->stat & 0x80) { + /* it is, so set tops with base + ofst + and clear stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base; + VU->vifRegs->stat &= ~0x80; + } else { + /* it is not, so set tops with base + and set the stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; + VU->vifRegs->stat |= 0x80; + } + } + + if (VIFdmanum == 0) { + vu0ExecMicro(addr); + } else { + vu1ExecMicro(addr); + } +} + +void vif0Init() { + u32 i; + extern u8 s_maskwrite[256]; + + for(i = 0; i < 256; ++i ) { + s_maskwrite[i] = ((i&3)==3)||((i&0xc)==0xc)||((i&0x30)==0x30)||((i&0xc0)==0xc0); + } + + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); +} + +void vif0FLUSH() { + int _cycles; + _cycles = VU0.cycle; + + vu0Finish(); + cycles+= (VU0.cycle - _cycles)*BIAS; +} + +void vif0UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + vif0FLUSH(); + + vl = (vif0.cmd ) & 0x3; + vn = (vif0.cmd >> 2) & 0x3; + vif0.tag.addr = (data[0] & 0x3ff) << 4; + vif0.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + + if ( vif0Regs->cycle.wl <= vif0Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) + + _limit( vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl ); + + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + + vif0.tag.cmd = vif0.cmd; + vif0.tag.size = len; + vif0Regs->offset = 0; +} + +void _vif0mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif0mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU0.Micro + addr, data, size << 2)) { + memcpy_amd(VU0.Micro + addr, data, size << 2); + Cpu->ClearVU0(addr, size); + } +} + +int vif0transferData(u32 *data, int size) { + int ret=0; + +#ifdef VIF_LOG + VIF_LOG("VIFtransferData: cmd %x, size %x, vif0.tag.size %x\n", vif0.cmd, size, vif0.tag.size); +#endif + if ((vif0.cmd & 0x60) == 0x60) { // UNPACK +#ifdef VIF_LOG + VIF_LOG("UNPACKData: cmd %x, size %x, vif0.tag.size %x\n", vif0.cmd, size, vif0.tag.size); +#endif + if (size < vif0.tag.size) { + VIFunpack(data, &vif0.tag, size, VIF0dmanum); + // cycles+= size >> 1; + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + ret = size; + } else { + VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + // cycles+= vif0.tag.size >> 1; + ret = vif0.tag.size; + vif0.tag.size = 0; + } + } else { + switch (vif0.cmd) { + case 0x20: // STMASK + SetNewMask(g_vif0Masks, g_vif0HasMask3, data[0], vif0Regs->mask); + vif0Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif0Regs->mask); +#endif + ret = 1; + vif0.tag.size = 0; + break; + + case 0x30: // STROW + { + u32* pmem = &vif0Regs->r0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifRow0+vif0.tag.addr; + assert( vif0.tag.addr < 4 ); + ret = min(4-vif0.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[3] = data[3]; pmem2[3] = data[3]; + case 3: pmem[2] = data[2]; pmem2[2] = data[2]; + case 2: pmem[1] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + break; + } + case 0x31: // STCOL + { + u32* pmem = &vif0Regs->c0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifCol0+vif0.tag.addr; + ret = min(4-vif0.tag.addr, size); + switch(ret) { + case 4: pmem[3] = data[3]; pmem2[3] = data[3]; + case 3: pmem[2] = data[2]; pmem2[2] = data[2]; + case 2: pmem[1] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + break; + } + case 0x4A: // MPG + if (size < vif0.tag.size) { + _vif0mpgTransfer(vif0.tag.addr, data, size); + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + ret = size; + } else { + _vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); + ret = vif0.tag.size; + vif0.tag.size = 0; + } + break; + } + } + if (vif0.tag.size <= 0) { + vif0.cmd = 0; + } + + return ret; +} + +void vif0CMD(u32 *data, int size) { + int vifNum; + + switch ( vif0.cmd & 0x7F ) { + case 0x00: // NOP + vif0.cmd = 0; + break; + + case 0x01: // STCYCL + vif0Regs->cycle.cl = data[0] & 0xff; + vif0Regs->cycle.wl = (data[0] >> 8) & 0xff; + vif0.cmd = 0; + break; + + case 0x04: // ITOP + vif0Regs->itops = data[0] & 0x3ff; + vif0.cmd = 0; + break; + + case 0x05: // STMOD + vif0Regs->mode = data[0] & 0x3; + vif0.cmd = 0; + break; + + case 0x07: // MARK + vif0Regs->mark = (u16)data[0]; + vif0Regs->stat |= VIF0_STAT_MRK; + vif0.cmd = 0; + break; + + case 0x10: // FLUSHE + vif0FLUSH(); + vif0.cmd = 0; + break; + + case 0x14: // MSCAL + case 0x15: // MSCALF + vuExecMicro( (u16)( data[0]) << 3, VIF0dmanum ); + vif0.cmd = 0; + break; + + case 0x17: // MSCNT + vuExecMicro( -1, VIF0dmanum ); + vif0.cmd = 0; + break; + + case 0x20: // STMASK + break; + + case 0x30: // STROW + vif0.tag.addr = 0; + vif0.tag.size = 4; + break; + + case 0x31: // STCOL + vif0.tag.addr = 0; + vif0.tag.size = 4; + break; + + case 0x4A: // MPG + vif0FLUSH(); + vifNum = (data[0] >> 16) & 0xff; + if (vifNum == 0) vifNum = 256; + vif0.tag.addr = (u16)(data[0]) << 3; + vif0.tag.size = vifNum << 1; + break; + + default: + vif0.cmd = 0; + if ((vif0Regs->err & 0x6) == 0) { //Mask Vifcode and DMA tag mismatch errors + SysPrintf( "UNKNOWN VifCmd: %x\n", vif0.cmd ); + vif0Regs->stat |= 1 << 13; + } + break; + } +} + +int VIF0transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif0.vifstalled ? vif0.irqoffset : 0; + +#ifdef VIF_LOG + VIF_LOG( "VIF0transfer: size %x (vif0.cmd %x)\n", size, vif0.cmd ); +#endif + +/* { + int i; + for (i=0; i 0) { + + if (vif0.cmd) { + //vif0Regs->stat |= VIF0_STAT_VPS_T; + ret = vif0transferData(data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif0Regs->stat &= ~VIF0_STAT_VPS_T; + continue; + } + + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + vif0.cmd = (data[0] >> 24); + vif0Regs->code = data[0]; + if(vif0.irq && vif0.cmd != 0x7/* && size > 1*/) { + break; + } + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + + if ((vif0.cmd & 0x80) && !(vif0Regs->err & 0x1)) { //i bit on vifcode and not masked by VIF0_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif0.cmd, psHu32(INTC_MASK) ); +#endif + vif0.irq++; + } + + //vif0Regs->stat |= VIF0_STAT_VPS_D; + if ((vif0.cmd & 0x60) == 0x60) { + vif0UNPACK(data); + } else { + vif0CMD(data, size); + } + //vif0Regs->stat &= ~VIF0_STAT_VPS_D; + if(vif0.tag.size > 0) vif0Regs->stat |= VIF0_STAT_VPS_W; + data++; + size--; + transferred++; + + } + + if( !vif0.cmd ) + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + if (vif0.irq > 0) { + vif0.irq--; + + if( istag ) { + hwIntcIrq(VIF0intc); + vif0Regs->stat|= VIF0_STAT_INT; + return -2; + } + + vif0.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + //SysPrintf("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + hwIntcIrq(VIF0intc); + vif0Regs->stat|= VIF0_STAT_INT; + //if(size > 0) SysPrintf("VIF0 Remaining size %x, data %x_%x_%x_%x\n", size, data[3], data[2], data[1], data[0]); + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + } + + return 0; +} + +int _VIF0chain() { + u32 *pMem; + u32 qwc = vif0ch->qwc; + u32 ret; + + if (vif0ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif0ch->madr); + if (pMem == NULL) { + SysPrintf("VIF0chain bad madr %x", vif0ch->madr); + return -1; + } + + if( vif0.vifstalled ) { + ret = VIF0transfer(pMem+vif0.irqoffset, vif0ch->qwc*4-vif0.irqoffset, 0); + } + else { + ret = VIF0transfer(pMem, vif0ch->qwc*4, 0); + } + cycles+= (qwc-vif0ch->qwc)*BIAS; /* guessing */ + return ret; +} + +int _chainVIF0() { + u32 *ptag; + int id; + int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif0ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif0ch->madr = ptag[1]; //MADR = ADDR field + cycles+=1; // Add 1 cycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[0], ptag[1], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + done |= hwDmacSrcChainWithStack(vif0ch, id); + if (vif0ch->chcr & 0x40) { + ret = VIF0transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) + return -1; //There has been an error + if (ret == -2) { + vif0.vifstalled = 1; + return done; //IRQ set by VIFTransfer + } + } + + ret = _VIF0chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif0.vifstalled = 1; + return done; + } + + //if(id == 7)vif0ch->tadr = vif0ch->madr; + + vif0.vifstalled = 0; + + if ((vif0ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF0 TIE\n"); + //SysPrintf( "VIF0dmaIrq Set\n" ); + vif0ch->qwc = 0; + vif0Regs->stat|= VIF0_STAT_VIS; //Set the Tag Interrupt flag of VIF0_STAT + return 1; //End Transfer + } + return done; //Return Done +} + +int vif0Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif0Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + // need to check DMAC_CTRL + if ((vif0ch->chcr & 0x4) && vif0.done == 0 && vif0.vifstalled == 0 ) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif0 dma masked\n"); + return 0; + } + + cycles = 0; + ret = _chainVIF0(); + if (ret != 0) vif0.done = 1; + INT(0, cycles); + return 0; + } + if(vif0.vifstalled == 1) { + // vif0.done = 0; + return 0; + } + + // hack? + vif0.tag.size = 0; + vif0.cmd = 0; + vif0Regs->stat &= ~VIF0_STAT_VPS; + // hack? + + vif0ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF0); + vif0Regs->stat&= ~0xF000000; // FQC=0 + + return 1; +} + +void dmaVIF0() { +#ifdef VIF_LOG + VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif0ch->chcr, vif0ch->madr, vif0ch->qwc, + vif0ch->tadr, vif0ch->asr0, vif0ch->asr1 ); +#endif + /*if (vif0.irq > 0) { + vif0.irq--; + hwIntcIrq(VIF0intc); + return; + }*/ + + cycles = 0; +// if(vif0ch->qwc > 0) { +// _VIF0chain(); +// INT(0, cycles); +// } + vif0Regs->stat|= 0x8000000; // FQC=8 + + if (!(vif0ch->chcr & 0x4)) { // Normal Mode + _VIF0chain(); + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + return; + } + + if (_VIF0chain() != 0) { + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + vif0.done = 0; + INT(0, cycles); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif0Write32(u32 mem, u32 value) { + if (mem == 0x10003830) { // MARK + vif0Regs->stat&= ~0x40; + vif0Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF0_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + memset(&vif0, 0, sizeof(vif0)); + vif0ch->qwc = 0; + vif0Regs->err = 0; + vif0.done = 1; + //vif0Reset(); + vif0Regs->stat&= ~0x0F000000; // FQC=0 + + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif0Regs->stat |= VIF0_STAT_VFS; + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + + vif0Regs->stat |= VIF0_STAT_VSS; + //dmaVIF0(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif0Regs->stat & (VIF0_STAT_INT|VIF0_STAT_VSS|VIF0_STAT_VIS|VIF0_STAT_VFS)) { + cancel = 1; + } + vif0Regs->stat &= ~(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | + VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); + if (cancel) { + //SysPrintf("VIF0 Stall Resume\n"); + if( vif0.vifstalled ) { + // only reset if no further stalls + if( _VIF0chain() != -2 ) + vif0.vifstalled = 0; + } + } + INT(0,0); + } + } else + if (mem == 0x10003820) { // ERR + vif0Regs->err = value; + } + else if (mem == 0x10003800) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF0_STAT write32 0x%8.8x\n", value); +#endif +// vif0ch->qwc = 0; +// vif0.vifstalled = 0; +// vif0.done = 1; +// vif0Regs->stat&= ~0x0F000000; // FQC=0 + } + else if( mem >= 0x10003900 && mem < 0x10003980 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003940 ) g_vifRow0[(mem>>4)&3] = value; + else g_vifCol0[(mem>>4)&3] = value; + } +} + +void vif0Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif0, 0, sizeof(vif0)); + memset(vif0Regs, 0, sizeof(vif0Regs)); + + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif0Freeze(gzFile f, int Mode) { + gzfreeze(&vif0, sizeof(vif0)); + + if (Mode == 0) + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +void vif1Init() { + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); +} + +void vif1FLUSH() { + int _cycles; + _cycles = VU1.cycle; + + if( VU0.VI[REG_VPU_STAT].UL & 0x100 ) { + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + +// FreezeXMMRegs(0); +// FreezeMMXRegs(0); + + cycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +void vif1UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + vif1FLUSH(); + + vl = (vif1.cmd ) & 0x3; + vn = (vif1.cmd >> 2) & 0x3; + vif1.tag.addr = (data[0] & 0x3ff); + vif1.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + + if ( vif1Regs->cycle.wl <= vif1Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) + + _limit( vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl ); + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + if ( ( data[0] >> 15) & 0x1 ) { + vif1.tag.addr += vif1Regs->tops; + } + + vif1.tag.addr <<= 4; + vif1.tag.addr &= 0x3fff; + vif1.tag.cmd = vif1.cmd; + vif1.tag.size = len; + vif1Regs->offset = 0; +} + +void _vif1mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif1mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU1.Micro + addr, data, size << 2)) { + memcpy_amd(VU1.Micro + addr, data, size << 2); + Cpu->ClearVU1(addr, size); + } +} + +int vif1transferData(u32 *data, int size) { + int ret=0; + +#ifdef VIF_LOG + VIF_LOG("VIFtransferData: cmd %x, size %x, vif1.tag.size %x\n", vif1.cmd, size, vif1.tag.size); +#endif + if ((vif1.cmd & 0x60) == 0x60) { // UNPACK +#ifdef VIF_LOG + VIF_LOG("UNPACKData: cmd %x, size %x, vif1.tag.size %x\n", vif1.cmd, size, vif1.tag.size); +#endif + if (size < vif1.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif1.tag, size, VIF1dmanum); + // cycles+= size >> 1; + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + ret = size; + } else { + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + //cycles+= vif1.tag.size >> 1; + ret = vif1.tag.size; + vif1.tag.size = 0; + } + } else { + switch (vif1.cmd) { + case 0x20: // STMASK + SetNewMask(g_vif1Masks, g_vif1HasMask3, data[0], vif1Regs->mask); + vif1Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif1Regs->mask); +#endif + ret = 1; + vif1.tag.size = 0; + break; + + case 0x30: // STROW + { + u32* pmem = &vif1Regs->r0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifRow1+vif1.tag.addr; + assert( vif1.tag.addr < 4 ); + ret = min(4-vif1.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + break; + } + case 0x31: // STCOL + { + u32* pmem = &vif1Regs->c0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifCol1+vif1.tag.addr; + ret = min(4-vif1.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + break; + } + case 0x4A: // MPG + if (size < vif1.tag.size) { + _vif1mpgTransfer(vif1.tag.addr, data, size); + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + ret = size; + } else { + _vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); + ret = vif1.tag.size; + vif1.tag.size = 0; + } + + break; + + case 0x50: // DIRECT + case 0x51: // DIRECTHL + + if (size < vif1.tag.size) { + vif1.tag.size-= size; + ret = size; + } else { + ret = vif1.tag.size; + vif1.tag.size = 0; + } + + if( CHECK_MULTIGS ) { + u8* gsmem = GSRingBufCopy(data, ret<<2, GS_RINGTYPE_P2); + if( gsmem != NULL ) { + memcpy_amd(gsmem, data, ret<<2); + GSRINGBUF_DONECOPY(gsmem, ret<<2); + GSgifTransferDummy(1, data, ret>>2); + } + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); + } + else { +#ifdef GSCAPTURE + extern u32 g_loggs, g_gstransnum, g_gsfinalnum; + + if( !g_loggs || (g_loggs && g_gstransnum++ < g_gsfinalnum)) { + // call directly + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSgifTransfer2(data, (ret >> 2) - GSgifTransferDummy(1, data, ret>>2)); + } +#else + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSgifTransfer2(data, (ret >> 2)); +#endif + } + + //GSCSRr |= 2; // set finish? + + break; + } + } + if (vif1.tag.size <= 0) { + vif1.cmd = 0; + } + + return ret; +} + +void vif1CMD(u32 *data, int size) { + int vifNum; + int vifImm; + + switch ( vif1.cmd & 0x7F ) { + case 0x00: // NOP + vif1.cmd = 0; + break; + + case 0x01: // STCYCL + vif1Regs->cycle.cl = (u8)data[0]; + vif1Regs->cycle.wl = (u8)(data[0] >> 8); + vif1.cmd = 0; + break; + + case 0x02: // OFFSET + vif1Regs->ofst = data[0] & 0x3ff; + vif1Regs->stat &= ~0x80; + vif1Regs->tops = vif1Regs->base; + vif1.cmd = 0; + break; + + case 0x03: // BASE + vif1Regs->base = data[0] & 0x3ff; + vif1.cmd = 0; + break; + + case 0x04: // ITOP + vif1Regs->itops = data[0] & 0x3ff; + vif1.cmd = 0; + break; + + case 0x05: // STMOD + vif1Regs->mode = data[0] & 0x3; + vif1.cmd = 0; + break; + + case 0x06: // MSKPATH3 + vif1Regs->mskpath3 = (data[0] >> 15) & 0x1; + if ( vif1Regs->mskpath3 ) { + if(gif->qwc) _GIFchain(); // Finish the transfer first + psHu32(GIF_STAT) |= 0x2; + } else { + psHu32(GIF_STAT) &= ~0x2; + if(gif->qwc) _GIFchain(); // Finish the transfer first + } + vif1.cmd = 0; + break; + + case 0x07: // MARK + vif1Regs->mark = (u16)data[0]; + vif1Regs->stat |= VIF1_STAT_MRK; + vif1.cmd = 0; + break; + + case 0x10: // FLUSHE + case 0x11: // FLUSH + case 0x13: // FLUSHA + vif1FLUSH(); + vif1.cmd = 0; + break; + + case 0x14: // MSCAL + case 0x15: // MSCALF + vuExecMicro( (u16)(data[0]) << 3, VIF1dmanum ); + vif1.cmd = 0; + break; + + case 0x17: // MSCNT + vuExecMicro( -1, VIF1dmanum ); + vif1.cmd = 0; + break; + + case 0x20: // STMASK + break; + + case 0x30: // STROW + vif1.tag.addr = 0; + vif1.tag.size = 4; + break; + + case 0x31: // STCOL + vif1.tag.addr = 0; + vif1.tag.size = 4; + break; + + case 0x4A: // MPG + vif1FLUSH(); + vifNum = (u8)(data[0] >> 16); + if (vifNum == 0) vifNum = 256; + vif1.tag.addr = (u16)(data[0]) << 3; + vif1.tag.size = vifNum * 2; + break; + + case 0x50: // DIRECT + case 0x51: // DIRECTHL + vifImm = (u16)data[0]; + if (vifImm == 0) { + vif1.tag.size = 65536 << 2; + } else { + vif1.tag.size = vifImm << 2; + } + break; + + default: + vif1.cmd = 0; + if ((vif1Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif1.cmd ); + vif1Regs->stat |= 1 << 13; + } + break; + } +} + + +int VIF1transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + +#ifdef VIF_LOG + VIF_LOG( "VIF1transfer: size %x (vif1.cmd %x)\n", size, vif1.cmd ); +#endif + + //return 0; + + //vif1.irq = 0; + while (size > 0) { + + if (vif1.cmd) { + //vif1Regs->stat |= VIF1_STAT_VPS_T; + ret = vif1transferData(data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif1Regs->stat &= ~VIF1_STAT_VPS_T; + continue; + } + + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + vif1.cmd = (data[0] >> 24); + vif1Regs->code = data[0]; + if(vif1.irq && vif1.cmd != 0x7/* && size > 1*/) { + break; + } +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + + if ((vif1.cmd & 0x80) && !(vif1Regs->err & 0x1)) { //i bit on vifcode and not masked by VIF1_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif1.cmd, psHu32(INTC_MASK) ); +#endif + + //vif1Regs->stat|= VIF1_STAT_VIS; + vif1.irq++; + } + + //vif1Regs->stat |= VIF1_STAT_VPS_D; + if ((vif1.cmd & 0x60) == 0x60) { + vif1UNPACK(data); + } else { + vif1CMD(data, size); + } + //vif1Regs->stat &= ~VIF1_STAT_VPS_D; + if(vif1.tag.size > 0) vif1Regs->stat |= VIF1_STAT_VPS_W; + data++; + size--; + transferred++; + + } + + if( !vif1.cmd ) + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + if (vif1.irq > 0) { + vif1.irq--; + + if( istag ) { + hwIntcIrq(VIF1intc); + vif1Regs->stat|= VIF1_STAT_INT; + return -2; + } + + // spiderman doesn't break on qw boundaries + vif1.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + hwIntcIrq(VIF1intc); + vif1Regs->stat|= VIF1_STAT_INT; + if(size > 0) { + //SysPrintf("VIF1 Remaining size %x, data %x_%x_%x_%x\n", size, data[3], data[2], data[1], data[0]); + } + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + } + + return 0; +} + +int _VIF1chain() { + u32 *pMem; + u32 qwc = vif1ch->qwc; + u32 ret; + + if (vif1ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) + return -1; + + if( vif1.vifstalled ) { + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + } + else { + ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); + } + /*vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->qwc-= qwc;*/ + cycles+= (qwc-vif1ch->qwc)*BIAS; /* guessing */ + return ret; +} + +int _chainVIF1() { + u32 *ptag; + int id; + int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif1ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif1ch->madr = ptag[1]; //MADR = ADDR field + cycles+=1; // Add 1 cycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + done |= hwDmacSrcChainWithStack(vif1ch, id); + if (vif1ch->chcr & 0x40) { + ret = VIF1transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + vif1.vifstalled = 1; + return done; //IRQ set by VIFTransfer + } + } + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif1ch, id); + ret = _VIF1chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif1.vifstalled = 1; + return done; + } + + //if(id == 7)vif1ch->tadr = vif1ch->madr; + + vif1.vifstalled = 0; + + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF1 TIE\n"); + //SysPrintf( "VIF1dmaIrq Set\n" ); + vif1ch->qwc = 0; + vif1Regs->stat|= VIF1_STAT_VIS; //Set the Tag Interrupt flag of VIF1_STAT + return 1; //End Transfer + } + return done; //Return Done +} + +int _vif1Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(vif1.vifstalled == 1) { + return 1; + } + if (vif1ch->chcr & 0x4 && vif1.done == 0 && vif1.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif1 dma masked\n"); + return 0; + } + + cycles = 0; + ret = _chainVIF1(); + if (ret != 0) vif1.done = 1; + INT(1, cycles); + return 0; + } + + + // hack? + vif1.tag.size = 0; + vif1.cmd = 0; + vif1Regs->stat &= ~VIF1_STAT_VPS; + // hack? + + + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); + vif1Regs->stat&= ~0x1F000000; // FQC=0 + + return 1; +} + +int vif1Interrupt() { + + int ret; + + ret = _vif1Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF1() { +#ifdef VIF_LOG + VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif1ch->chcr, vif1ch->madr, vif1ch->qwc, + vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); +#endif + + /* Check if there is a pending irq */ + /*if (vif1.irq > 0) { + vif1.irq--; + hwIntcIrq(VIF1intc); + return; + }*/ +// if(vif1ch->qwc > 0) { +// _VIF1chain(); +// INT(1, cycles); +// } + + if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO + return; + } + +#ifdef PCSX2_DEVBUILD + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 + SysPrintf("vif1 drain stall %d\n", (psHu32(DMAC_CTRL)>>4)&3); + //return; + } +#endif + + cycles = 0; + vif1Regs->stat|= 0x10000000; // FQC=16 + + if (!(vif1ch->chcr & 0x4)) { // Normal Mode + if ((vif1ch->chcr & 0x1)) { // to Memory + _VIF1chain(); + INT(1, cycles); + } else { // from Memory + + if( CHECK_MULTIGS ) { + u8* pMem = GSRingBufCopy(NULL, 0, GS_RINGTYPE_VIFFIFO); + assert( vif1ch->qwc < 0x10000 ); + *(u32*)(pMem-16) = GS_RINGTYPE_VIFFIFO|(vif1ch->qwc<<16); // hack + *(u32*)(pMem-12) = vif1ch->madr; + *(u32*)(pMem-8) = cpuRegs.cycle; + + GSRINGBUF_DONECOPY(pMem, 0); + SetEvent(g_hGsEvent); + } + else { + + int size; + u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + return; + } + + if( GSreadFIFO2 == NULL ) { + for (size=vif1ch->qwc; size>0; size--) { + if (size > 1) GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, vif1ch->qwc); + + // set incase read + psHu64(0x5000) = pMem[2*vif1ch->qwc-2]; + psHu64(0x5008) = pMem[2*vif1ch->qwc-1]; + } + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, cycles); + } + } + vif1.done = 1; + return; + } + +/* if (_VIF1chain() != 0) { + INT(1, cycles); + return; + }*/ + + // Chain Mode + vif1.done = 0; + INT(1, cycles); +} + +void dmaVIF1() +{ + _dmaVIF1(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif1Write32(u32 mem, u32 value) { + if (mem == 0x10003c30) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF1_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF1_STAT and set mark with 'value' */ + vif1Regs->stat&= ~VIF1_STAT_MRK; + vif1Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF1_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif1 Reset\n"); + memset(&vif1, 0, sizeof(vif1)); + vif1ch->qwc = 0; //? + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->err = 0; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif1Regs->stat |= VIF1_STAT_VFS; + SysPrintf("vif1 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif1Regs->stat |= VIF1_STAT_VSS; + //SysPrintf("Vif1 Stop\n"); + //dmaVIF1(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + cancel = 1; + } + + vif1Regs->stat &= ~(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | + VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1); + if (cancel) { + //SysPrintf("VIF1 Stall Resume\n"); + if( vif1.vifstalled ) { + // loop necessary for spiderman + if ( _VIF1chain() != -2 ) + vif1.vifstalled = 0; + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + } + } + + INT(1, 0); // If vif is stopped/stall cancelled/ or force break, we need to make sure the dma ends. + } + } else + if (mem == 0x10003c20) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF1_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF1_ERR with 'value' */ + vif1Regs->err = value; + } else + if (mem == 0x10003c00) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF1_STAT write32 0x%8.8x\n", value); +#endif + +#ifdef PCSX2_DEVBUILD + /* Only FDR bit is writable, so mask the rest */ + if( (vif1Regs->stat & VIF1_STAT_FDR) ^ (value & VIF1_STAT_FDR) ) { + // different so can't be stalled + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + SysPrintf("changing dir when vif1 fifo stalled\n"); + } + } +#endif + + vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR); + if (vif1Regs->stat & VIF1_STAT_FDR) { + vif1Regs->stat|= 0x01000000; + } else { + vif1ch->qwc = 0; + vif1.vifstalled = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + } + else if( mem >= 0x10003d00 && mem < 0x10003d80 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003d40 ) g_vifRow1[(mem>>4)&3] = value; + else g_vifCol1[(mem>>4)&3] = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif1Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif1, 0, sizeof(vif1)); + memset(vif1Regs, 0, sizeof(vif1Regs)); + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif1Freeze(gzFile f, int Mode) { + gzfreeze(&vif1, sizeof(vif1)); + if (Mode == 0) + SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); + + return 0; +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/VifDma.h b/branches/pcsx2_0.9.1/VifDma.h new file mode 100644 index 0000000..63087c6 --- /dev/null +++ b/branches/pcsx2_0.9.1/VifDma.h @@ -0,0 +1,120 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIFDMA_H__ +#define __VIFDMA_H__ + +typedef struct { + int addr; + int size; + int cmd; + u16 wl; + u16 cl; +} vifCode; + +// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito +typedef struct { + vifCode tag; + int cmd; + int irq; + int cl; + int wl; + u8 usn; + u8 done; + u8 vifstalled; + u8 irqoffset; // 32bit offset where next vif code is +} vifStruct; + +vifStruct vif0; +vifStruct vif1; + +#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000]) +#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000]) + +void UNPACK_S_32( u32 *dest, u32 *data ); +int UNPACK_S_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_S_16u( u32 *dest, u32 *data ); +int UNPACK_S_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_16s( u32 *dest, u32 *data ); +int UNPACK_S_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_S_8u( u32 *dest, u32 *data ); +int UNPACK_S_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_8s( u32 *dest, u32 *data ); +int UNPACK_S_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_32( u32 *dest, u32 *data ); +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_16u( u32 *dest, u32 *data ); +int UNPACK_V2_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_16s( u32 *dest, u32 *data ); +int UNPACK_V2_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_8u( u32 *dest, u32 *data ); +int UNPACK_V2_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_8s( u32 *dest, u32 *data ); +int UNPACK_V2_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_32( u32 *dest, u32 *data ); +int UNPACK_V3_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_16u( u32 *dest, u32 *data ); +int UNPACK_V3_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_16s( u32 *dest, u32 *data ); +int UNPACK_V3_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_8u( u32 *dest, u32 *data ); +int UNPACK_V3_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_8s( u32 *dest, u32 *data ); +int UNPACK_V3_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_32( u32 *dest, u32 *data ); +int UNPACK_V4_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_16u( u32 *dest, u32 *data ); +int UNPACK_V4_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_16s( u32 *dest, u32 *data ); +int UNPACK_V4_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_8u( u32 *dest, u32 *data ); +int UNPACK_V4_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_8s( u32 *dest, u32 *data ); +int UNPACK_V4_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_5( u32 *dest, u32 *data ); +int UNPACK_V4_5part( u32 *dest, u32 *data, int size ); + +// sse1/2 + + +void vifDmaInit(); +void vif0Init(); +void vif1Init(); +int vif0Interrupt(); +int vif1Interrupt(); + +void vif0Write32(u32 mem, u32 value); +void vif1Write32(u32 mem, u32 value); + +void vif0Reset(); +void vif1Reset(); +int vif0Freeze(gzFile f, int Mode); +int vif1Freeze(gzFile f, int Mode); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.c b/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.c new file mode 100644 index 0000000..d692ea8 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.c @@ -0,0 +1,1996 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +// NOTE: The reason ADD/SUB/etc are so large is because they are very commonly +// used and recompiler needs to cover ALL possible usages to minimize code size (zerofrog) + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#elif defined(EE_CONST_PROP) + +//// ADD +void recADD_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0]; +} + +void recADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] ) { + u32* ptempmem; + + ptempmem = _eeGetConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(vreg) ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, mmreg, vreg); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[ creg ].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(vreg) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[creg].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)_eeGetConstReg(creg)); + PADDDMtoR(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == vreg ) { + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( g_cpuConstRegs[ creg ].UL[0] ) + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[0] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +// s is constant +void recADD_consts(int info) +{ + recADD_constv(info, _Rs_, _Rt_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rt_); +} + +// t is constant +void recADD_constt(int info) +{ + recADD_constv(info, _Rt_, _Rs_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); +} + +// nothing is constant +void recADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PADDDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDDRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDDRtoR(EEREC_D, EEREC_S); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PADDDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( _Rd_ == _Rs_ ) { + if( _Rd_ == _Rt_ ) SHL32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 1); // mult by 2 + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + + return; + } + else if( _Rd_ == _Rt_ ) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( _Rs_ != _Rt_ ) ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else SHL32ItoR(EAX, 1); // mult by 2 + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// ADDU +void recADDU( void ) +{ + recADD( ); +} + +//// DADD +void recDADD_const( void ) +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ creg ].UD[0] ) { + + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDQMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + if( g_cpuConstRegs[ creg ].UD[0] ) PADDQMtoR(mmreg, (u32)_eeGetConstReg(creg)); + } + else { + + if( g_cpuConstRegs[ creg ].UL[0] == 0 && g_cpuConstRegs[ creg ].UL[1] == 0 && _hasFreeMMXreg() ) { + // copy + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + if( EEINST_ISLIVE1(_Rd_) ) MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + else { + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + if( _Rd_ == vreg ) { + + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ creg ].UL[ 0 ] || g_cpuConstRegs[ creg ].UL[ 1 ]) ) { + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + ADC32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ creg ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + } + + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32ItoR( EDX, g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDADD_consts(int info) +{ + recDADD_constv(info, _Rs_, _Rt_); +} + +void recDADD_constt(int info) +{ + recDADD_constv(info, _Rt_, _Rs_); +} + +void recDADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PADDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( _Rs_ != _Rt_ ) PADDQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else PSLLQItoR(mmreg, 1); // mult by 2 + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// DADDU +void recDADDU( void ) +{ + recDADD( ); +} + +//// SUB + +void recSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0]; +} + +void recSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rs_ ].UL[0] ) { + + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + } + else { + if( _Rd_ == _Rt_ ) { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) SUB32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rs_ ].UL[ 0 ]); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + NEG32R(EAX); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +void recSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rt_ ].UL[0] ) { + + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(_Rs_) ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, EEREC_S, _Rs_); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[_Rt_].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(_Rs_) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[_Rt_].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PSUBDMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == _Rs_ ) { + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +void recSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PSUBDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + info = (info&~PROCESS_EE_SET_D(0xf))|PROCESS_EE_SET_D(t0reg); + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBDRtoR(EEREC_D, EEREC_T); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_)) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PSUBDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( !EEINST_ISLIVE1(_Rd_) ) { + if( _Rd_ == _Rs_) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SUBU +void recSUBU( void ) +{ + recSUB( ); +} + +//// DSUB +void recDSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rs_ ].UD[0] ) { + + // flush + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (u32)_eeGetConstReg(_Rs_)); + PSUBQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] || g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoR( EDX, g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + else { + + if( _Rd_ == _Rt_ ) { + // negate _Rt_ all in memory + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + NEG32M((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADC32ItoR(EDX, 0); + NEG32R(EDX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + } + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + // take negative of 64bit number + NEG32R(EAX); + + if( EEINST_ISLIVE1(_Rd_) ) { + ADC32ItoR(EDX, 0); + NEG32R(EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rt_ ].UD[0] ) { + + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( g_cpuConstRegs[_Rt_].UD[0] ) PSUBQMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + + if( _Rd_ == _Rs_ ) { + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ]) ) { + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + SBB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ) { + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32ItoR( EDX, g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PSUBQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBQRtoR(EEREC_D, EEREC_T); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[ 0 ]); + PSUBQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( _Rd_ == _Rs_ ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSUBU +void recDSUBU( void ) +{ + recDSUB( ); +} + +//// AND +void recAND_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0]; +} + +void recAND_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PANDMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + PXORRtoR(EEREC_D, EEREC_D); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PANDMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + else { + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + + if( _Rd_ == vreg ) { + AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + AND32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) + AND32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recAND_consts(int info) +{ + recAND_constv(info, _Rs_, _Rt_); +} + +void recAND_constt(int info) +{ + recAND_constv(info, _Rt_, _Rs_); +} + +void recLogicalOp(int info, int op) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( EEREC_D == EEREC_S ) LogicalOpRtoR(EEREC_D, EEREC_T, op); + else if( EEREC_D == EEREC_T ) LogicalOpRtoR(EEREC_D, EEREC_S, op); + else { + MOVQRtoR(EEREC_D, EEREC_S); + LogicalOpRtoR(EEREC_D, EEREC_T, op); + } + } + else if( (g_pCurInstInfo->regs[_Rs_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + int rsreg, rtreg, rdreg; + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + rsreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + rtreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + SetMMXstate(); + + if( rdreg == rsreg ) { + if( rtreg >= 0 ) LogicalOpRtoR(rdreg, rtreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ], op); + } + else { + if( rdreg != rtreg ) { + if( rtreg >= 0 ) MOVQRtoR(rdreg, rtreg); + else MOVQMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ]); + } + + if( rsreg >= 0 ) LogicalOpRtoR(rdreg, rsreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rs_ ], op); + } + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX, op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ] + 4, EDX, op ); + if( op == 3 ) { + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]+4); + } + + if( !EEINST_ISLIVE1(_Rd_) ) EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ] + 4 ); + LogicalOp32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ], op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op ); + + if( op == 3 ) { + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + } + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } +} + +void recAND_(int info) +{ + recLogicalOp(info, 0); +} + +EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// OR +void recOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]; +} + +void recOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recOR_consts(int info) +{ + recOR_constv(info, _Rs_, _Rt_); +} + +void recOR_constt(int info) +{ + recOR_constv(info, _Rt_, _Rs_); +} + +void recOR_(int info) +{ + recLogicalOp(info, 1); +} + +EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// XOR +void recXOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0]; +} + +void recXOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PXORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PXORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) XOR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) XOR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recXOR_consts(int info) +{ + recXOR_constv(info, _Rs_, _Rt_); +} + +void recXOR_constt(int info) +{ + recXOR_constv(info, _Rt_, _Rs_); +} + +void recXOR_(int info) +{ + recLogicalOp(info, 2); +} + +EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// NOR +void recNOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]); +} + +void recNOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + + // take the NOT + PCMPEQDRtoR( t0reg,t0reg); + PXORRtoR( EEREC_D,t0reg); + _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PCMPEQDRtoR( t0reg,t0reg); + if( g_cpuConstRegs[ creg ].UD[0] ) PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + + // take the NOT + PXORRtoR( rdreg,t0reg); + + _freeMMXreg(t0reg); + } + else { + if( _Rd_ == vreg ) { + NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]); + + if( g_cpuConstRegs[creg].UL[0] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], ~g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recNOR_consts(int info) +{ + recNOR_constv(info, _Rs_, _Rt_); +} + +void recNOR_constt(int info) +{ + recNOR_constv(info, _Rt_, _Rs_); +} + +void recNOR_(int info) +{ + recLogicalOp(info, 3); +} + +EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SLT - test with silent hill, lemans +void recSLT_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0]; +} + +static u32 s_sltconst = 0x80000000; +static u32 s_sltconst64[2] = {0, 0x80000000}; +u32 s_sltone = 1; + +void recSLTs_consts(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( g_cpuConstRegs[_Rs_].UL[1] == (g_cpuConstRegs[_Rs_].SL[0]<0?0xffffffff:0) && EEINST_ISSIGNEXT(_Rt_) ) { + // just compare the lower values + if( sign ) { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000; + ptempmem[1] = 0; + + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORMtoR(EEREC_D, (u32)&s_sltconst); + } + + PCMPGTDMtoR(EEREC_D, (u32)ptempmem); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + + // fall through + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + } + } + + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + j8Ptr[1] = JBE8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +// SLT with one operand coming from mem (compares only low 32 bits) +void recSLTmemconstt(int regd, int regs, u32 mem, int sign) +{ + // just compare the lower values + int t0reg; + + if( sign ) { + if( regd == regs ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, mem); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQMtoR(regd, mem); + PCMPGTDRtoR(regd, regs); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + } + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( regd == regs ) { + MOVQMtoR(t0reg, mem); + PXORMtoR(regs, (u32)&s_sltconst); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQRtoR(t0reg, regs); + MOVQMtoR(regd, mem); + PXORMtoR(t0reg, (u32)&s_sltconst); + PCMPGTDRtoR(regd, t0reg); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + _freeMMXreg(t0reg); + } + } +} + +void recSLTs_constt(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( EEINST_ISSIGNEXT(_Rs_) && g_cpuConstRegs[_Rt_].UL[1] == (g_cpuConstRegs[_Rt_].SL[0]<0?0xffffffff:0) ) { + // just compare the lower values + if( sign ) { + recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000; + ptempmem[1] = 0; + + recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + + // fall through + } + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLTs_(int info, int sign) +{ + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLT_consts(int info) +{ + recSLTs_consts(info, 1); +} + +void recSLT_constt(int info) +{ + recSLTs_constt(info, 1); +} + +void recSLT_(int info) +{ + int t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 1); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 1); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + // just compare the lower values + if( EEREC_D == EEREC_S ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + PCMPGTDRtoR(t0reg, EEREC_S); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDRtoR(EEREC_D, EEREC_S); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } +} + +EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +// SLTU - test with silent hill, lemans +void recSLTU_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0]; +} + +void recSLTU_consts(int info) +{ + recSLTs_consts(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_constt(int info) +{ + recSLTs_constt(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_(int info) +{ + int t1reg; + + assert( !(info & PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 0); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 0); + return; + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOVDMtoMMX(t1reg, (u32)&s_sltconst); + + if( EEREC_D == EEREC_S ) { + PXORRtoR(EEREC_S, t1reg); + PXORRtoR(t1reg, EEREC_T); + PCMPGTDRtoR(t1reg, EEREC_S); + + PUNPCKLDQRtoR(t1reg, t1reg); + PSRLQItoR(t1reg, 63); + + // swap regs + mmxregs[t1reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(t1reg, EEREC_S); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORRtoR(EEREC_D, t1reg); + PXORRtoR(t1reg, EEREC_S); + } + + PCMPGTDRtoR(EEREC_D, t1reg); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + + _freeMMXreg(t1reg); + } +} + +EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) +{ + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) +{ + if ( ! _Rd_ ) + { + return; + } + if ( ( _Rt_ == 0 ) || ( _Rs_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PANDRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + +} + +//////////////////////////////////////////////////// +void recOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0x0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0x0 ); + } + else if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PORRtoR( MM0, MM1 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recXOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0x0); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0x0); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recNOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0xffffffff); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0xffffffff); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PORMtoR( MM0,(int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +// test with silent hill, lemans +void recSLT( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JG8( 0 ); + j8Ptr[2] = JL8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) +{ + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JA8( 0 ); + j8Ptr[2] = JB8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.h b/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.h new file mode 100644 index 0000000..5fcd64d --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.c b/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.c new file mode 100644 index 0000000..8a075ae --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.c @@ -0,0 +1,659 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#elif defined(EE_CONST_PROP) + +//// ADDI +void recADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + _Imm_; +} + +void recADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rs_); + + if( info & PROCESS_EE_MMX ) { + if( _Imm_ != 0 ) { + + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDDMtoR(EEREC_T, (u32)ptempmem); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + + if( EEINST_ISLIVE1(_Rt_) ) + _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); + else + EEINST_RESETHASLIVE1(_Rt_); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + if( _Imm_ != 0 ) { + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDDMtoR(rtreg, (u32)ptempmem); + + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + } + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, ADDI); + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + _Imm_; +} + +void recDADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( _Imm_ != 0 ) { + + // flush + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDQMtoR(EEREC_T, (u32)ptempmem); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int rtreg; + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDQMtoR(rtreg, (u32)ptempmem); + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + ADC32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], _Imm_<0?0xffffffff:0); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, DADDI); + +//// DADDIU +void recDADDIU( void ) +{ + recDADDI( ); +} + +//// SLTIU +void recSLTIU_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < (u64)(_Imm_); +} + +extern void recSLTmemconstt(int regd, int regs, u32 mem, int sign); +extern u32 s_sltone; + +void recSLTIU_(int info) +{ + if( info & PROCESS_EE_MMX ) { + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = ((s32)(_Imm_))^0x80000000; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 0); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTIU); + +//// SLTI +void recSLTI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < (s64)(_Imm_); +} + +void recSLTI_(int info) +{ + if( info & PROCESS_EE_MMX) { + + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = _Imm_; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 1); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + // test silent hill if modding + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTI); + +//// ANDI +void recANDI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & (s64)_ImmU_; +} + +extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +extern void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +extern void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoM(u32 to, u32 from, int op); + +void recLogicalOpI(int info, int op) +{ + if( info & PROCESS_EE_MMX ) { + SetMMXstate(); + + if( _ImmU_ != 0 ) { + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + LogicalOpMtoR(EEREC_T, (u32)ptempmem, op); + } + else { + if( op == 0 ) PXORRtoR(EEREC_T, EEREC_T); + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && ((_Rt_ != _Rs_) || (_ImmU_==0)) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + u32* ptempmem; + + SetMMXstate(); + + ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( op == 0 ) { + if ( _ImmU_ != 0 ) { + if( _ImmU_ == 0xffff ) { + // take a shortcut + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] - 2); + PSRLDItoR(rtreg, 16); + } + else { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PANDMtoR(rtreg, (u32)ptempmem); + } + } + else PXORRtoR(rtreg, rtreg); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if ( _ImmU_ != 0 ) LogicalOpMtoR(rtreg, (u32)ptempmem, op); + } + } + else { + if ( _ImmU_ != 0 ) + { + if( _Rt_ == _Rs_ ) { + LogicalOp32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_, op); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + LogicalOp32ItoR( EAX, _ImmU_, op); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + + if( op == 0 ) { + if( EEINST_ISLIVE1(_Rt_ ) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + } + else + { + if( op == 0 ) { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + } + else { + if( _Rt_ != _Rs_ ) { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + } + + if( !EEINST_ISLIVE1(_Rt_) ) EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +void recANDI_(int info) +{ + recLogicalOpI(info, 0); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ANDI); + +//////////////////////////////////////////////////// +void recORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | (s64)_ImmU_; +} + +void recORI_(int info) +{ + recLogicalOpI(info, 1); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ORI); + +//////////////////////////////////////////////////// +void recXORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ (s64)_ImmU_; +} + +void recXORI_(int info) +{ + recLogicalOpI(info, 2); +} + +EERECOMPILE_CODEX(eeRecompileCode1, XORI); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) +{ +#ifdef __x86_64_ + if ( ! _Rt_ ) + { + return; + } + + MOV64MtoR( RAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +#else + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + if ( _Imm_ < 0 ) + { + ADC32ItoR( EDX, 0xffffffff ); + } + else + { + ADC32ItoR( EDX, 0 ); + } + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + return; + + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + return; + + // test silent hill if modding + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recANDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + if ( _ImmU_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } + +} + +//////////////////////////////////////////////////// +static u64 _imm = 0; // temp immediate + +void recORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recXORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PXORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ], MM0 ); + SetMMXstate(); +} + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.h b/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.h new file mode 100644 index 0000000..4bd7a0c --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.c b/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.c new file mode 100644 index 0000000..75faf79 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.c @@ -0,0 +1,1087 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + +#if defined(EE_CONST_PROP) + +void recSetBranchEQ(int info, int bne, int process) +{ + if( info & PROCESS_EE_MMX ) { + int t0reg; + + SetMMXstate(); + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + if( t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + PCMPEQDRtoR(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + PCMPEQDRtoR(t0reg, EEREC_S); + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PCMPEQDRtoR(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + + PMOVMSKBMMXtoR(EAX, t0reg); + + _eeFlushAllUnused(); + + CMP8ItoR( EAX, 0xff ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( info & PROCESS_EE_XMM ) { + int t0reg; + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + + if( t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeXMMreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _eeFlushAllUnused(); + + AND8ItoR(EAX, 3); + CMP8ItoR( EAX, 0x3 ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + + _eeFlushAllUnused(); + + if( bne ) { + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + + x86SetJ8( j8Ptr[0] ); + } + else { + // beq + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +void recSetBranchL(int ltz) +{ + int regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + PXORRtoR(t0reg, t0reg); + PCMPGTDRtoR(t0reg, regs); + PMOVMSKBMMXtoR(EAX, t0reg); + + _freeMMXreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 0x80 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, regs); + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _freeXMMreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 2 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + if( ltz ) j32Ptr[ 0 ] = JGE32( 0 ); + else j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +//// BEQ +void recBEQ_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +void recBEQ_(int info) { recBEQ_process(info, 0); } +void recBEQ_consts(int info) { recBEQ_process(info, PROCESS_CONSTS); } +void recBEQ_constt(int info) { recBEQ_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQ, XMMINFO_READS|XMMINFO_READT); + +//// BNE +void recBNE_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + recSetBranchEQ(info, 1, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBNE_(int info) { recBNE_process(info, 0); } +void recBNE_consts(int info) { recBNE_process(info, PROCESS_CONSTS); } +void recBNE_constt(int info) { recBNE_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNE, XMMINFO_READS|XMMINFO_READT); + +//// BEQL +void recBEQL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBEQL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +void recBEQL_(int info) { recBEQL_process(info, 0); } +void recBEQL_consts(int info) { recBEQL_process(info, PROCESS_CONSTS); } +void recBEQL_constt(int info) { recBEQL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQL, XMMINFO_READS|XMMINFO_READT); + +//// BNEL +void recBNEL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm(branchTo); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBNEL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +void recBNEL_(int info) { recBNEL_process(info, 0); } +void recBNEL_consts(int info) { recBNEL_process(info, PROCESS_CONSTS); } +void recBNEL_constt(int info) { recBNEL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNEL, XMMINFO_READS|XMMINFO_READT); + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +//void recBLTZAL( void ) +//{ +// SysPrintf("BLTZAL\n"); +// _eeFlushAllUnused(); +// MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (int)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (int)BLTZAL ); +// branch = 2; +//} + +//////////////////////////////////////////////////// +void recBLTZAL(int info) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + SysPrintf("BLTZAL\n"); + _eeOnWriteReg(31, 0); + _eeFlushAllUnused(); + + _deleteEEreg(31, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[0], pc+4); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[1], 0); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#endif + +//// BLEZ +void recBLEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//// BGTZ +void recBGTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JL32( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JG32( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.h b/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.h new file mode 100644 index 0000000..3370b8a --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.c b/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.c new file mode 100644 index 0000000..af4cf2b --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.c @@ -0,0 +1,131 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + _deleteEEreg(31, 0); + GPR_SET_CONST(31); + g_cpuConstRegs[31].UL[0] = pc + 4; + g_cpuConstRegs[31].UL[1] = 0; + + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, _Rs_); + // uncomment when there are NO instructions that need to call interpreter +// int mmreg; +// if( GPR_IS_CONST1(_Rs_) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[_Rs_].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + + if ( _Rd_ ) + { + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + g_cpuConstRegs[_Rd_].UL[0] = pc + 4; + g_cpuConstRegs[_Rd_].UL[1] = 0; + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + + SetBranchReg(0xffffffff); +} + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.h b/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.h new file mode 100644 index 0000000..d35f87c --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.c b/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.c new file mode 100644 index 0000000..abb22b2 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.c @@ -0,0 +1,4218 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else + +__declspec(align(16)) u64 retValues[2]; +extern u32 maxrecmem; +static u32 s_bCachingMem = 0; +static u32 s_nAddMemOffset = 0; +static u32 s_tempaddr = 0; + +void _eeOnLoadWrite(int reg) +{ + int regt; + + if( !reg ) return; + + _eeOnWriteReg(reg, 1); + regt = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + if( cpucaps.hasStreamingSIMD2Extensions && (reg != _Rs_) ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(regt, regt); + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + else SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } +} + +#ifdef WIN32_VIRTUAL_MEM + +extern void iMemRead32Check(); + +#define _Imm_co_ (*(s16*)PSM(pc)) + +// perf counters +#ifdef PCSX2_DEVBUILD +extern void StartPerfCounter(); +extern void StopPerfCounter(); +#else +#define StartPerfCounter() +#define StopPerfCounter() +#endif + +//////////////////////////////////////////////////// +//#define REC_SLOWREAD +//#define REC_SLOWWRITE +#define REC_FORCEMMX 0 + +// if sp, always mem write +int _eeIsMemWrite() { return _Rs_==29||_Rs_== 31||_Rs_==26||_Rs_==27; } // sp, ra, k0, k1 +// gp can be 1000a020 (jak1) + +void recTransferX86ToReg(int x86reg, int gprreg, int sign) +{ + //if( !REC_FORCEMMX ) assert( _checkMMXreg(MMX_GPR+gprreg, MODE_WRITE) == -1 ); + if( sign ) { + if( x86reg == EAX && EEINST_ISLIVE1(gprreg) ) CDQ(); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + + if(EEINST_ISLIVE1(gprreg)) { + if( x86reg == EAX ) MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], EDX ); + else { + SAR32ItoR(x86reg, 31); + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], x86reg ); + } + } + else { + EEINST_RESETHASLIVE1(gprreg); + } + } + else { + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + if(EEINST_ISLIVE1(gprreg)) MOV32ItoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(gprreg); + } +} + +#ifdef _DEBUG +void testaddrs() +{ + register int tempaddr; + + __asm mov tempaddr, ecx + //__asm mov incaddr, edx + + assert( (tempaddr < 0x40000000) || (tempaddr&0xd0000000)==0x50000000 || (tempaddr >= 0x80000000 && tempaddr < 0xc0000000) ); + //assert( (tempaddr>>28) == ((tempaddr+incaddr)>>28) ); + + __asm mov ecx, tempaddr +} +#endif + +#define SET_HWLOC() { \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[2]); \ + else x86SetJ8(j8Ptr[0]); \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[3]); \ + else x86SetJ8(j8Ptr[3]); \ + if (x86FpuState==MMX_STATE) { \ + if (cpucaps.has3DNOWInstructionExtensions) FEMMS(); \ + else EMMS(); \ + } \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ + if( s_bCachingMem & 4 ) AND32ItoR(ECX, 0x5fffffff); \ +} \ + +static u16 g_MemMasks0[16] = {0x00f0, 0x80f1, 0x00f2, 0x00f3, + 0x00f1, 0x00f5, 0x00f1, 0x00f5, + 0x00f5, 0x80f5, 0x00f5, 0x80f5, + 0x00f1, 0x00f1, 0x00f1, 0x00f5 }; +static u16 g_MemMasks8[16] = {0x0080, 0x8081, 0x0082, 0x0083, + 0x0081, 0x0085, 0x0081, 0x0085, + 0x0085, 0x8085, 0x0085, 0x8085, + 0x0081, 0x0081, 0x0081, 0x0085 }; +static u16 g_MemMasks16[16] ={0x0000, 0x8001, 0x0002, 0x0003, + 0x0001, 0x0005, 0x0001, 0x0005, + 0x0005, 0x8005, 0x0005, 0x8005, + 0x0001, 0x0001, 0x0001, 0x0005 }; + +void assertmem() +{ + __asm mov s_tempaddr, ecx + __asm mov s_bCachingMem, edx + SysPrintf("%x(%x) not mem write!\n", s_tempaddr, s_bCachingMem); + assert(0); +} + +int _eePrepareReg(int gprreg) +{ + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + + if( mmreg >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + mmreg |= MEM_XMMTAG; + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + if( mmxregs[mmreg].mode&MODE_WRITE ) mmreg |= MEM_MMXTAG; + else { + mmxregs[mmreg].needed = 0; // coX can possibly use all regs + mmreg = 0; + } + } + else { + mmreg = 0; + } + + return mmreg; +} + +int _eePrepareReg_coX(int gprreg, int num) +{ + int mmreg = _eePrepareReg(gprreg); + + if( (mmreg&MEM_MMXTAG) && num == 7 ) { + if( mmxregs[mmreg&0xf].mode & MODE_WRITE ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg], mmreg&0xf); + mmxregs[mmreg&0xf].mode &= ~MODE_WRITE; + mmxregs[mmreg&0xf].needed = 0; + } + } + + return mmreg; +} + +// returns true if should also include harware writes +int recSetMemLocation(int regs, int imm, int mmreg, int msize, int j32) +{ + s_bCachingMem = j32 ? 2 : 0; + s_nAddMemOffset = 0; + + //int num; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_R(ECX, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + MOVD32MMXtoR(ECX, mmreg&0xf); + SetMMXstate(); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ regs ].UL[ 0 ] ); + } + + if ( imm != 0 ) ADD32ItoR( ECX, imm ); + + LoadCW(); + +#ifdef _DEBUG + //CALLFunc((u32)testaddrs); +#endif + + + // 32bit version (faster?) +// MOV32RtoR(EAX, ECX); +// ROR32ItoR(ECX, 28); +// SHR32ItoR(EAX, 28); +// MOV32RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 2); +// AND8RtoR(ECX, EAX); +// ROR32ItoR(ECX, 4); +// // do extra alignment masks here +// OR32RtoR(EAX, EAX); + + if( _eeIsMemWrite() ) { + u8* ptr; + CMP32ItoR(ECX, 0x40000000); + ptr = JB8(0); + if( msize == 1 ) AND32ItoR(ECX, 0x5ffffff8); + else if( msize == 2 ) AND32ItoR(ECX, 0x5ffffff0); + else AND32ItoR(ECX, 0x5fffffff); + x86SetJ8(ptr); + if( msize == 1 ) AND8ItoR(ECX, 0xf8); + else if( msize == 2 ) AND8ItoR(ECX, 0xf0); +#ifdef _DEBUG + MOV32RtoR(EAX, ECX); + SHR32ItoR(EAX, 28); + CMP32ItoR(EAX, 1); + ptr = JNE8(0); + MOV32ItoR(EDX, _Rs_); + CALLFunc((u32)assertmem); + x86SetJ8(ptr); +#endif + return 0; + } + else { + // 16 bit version + MOV32RtoR(EAX, ECX); + ROR32ItoR(ECX, 28); + SHR32ItoR(EAX, 28); + MOV16RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 1); + AND8RtoR(ECX, EAX); + ROR32ItoR(ECX, 4); + + OR16RtoR(EAX, EAX); + + if( s_bCachingMem & 2 ) j32Ptr[2] = j32Ptr[3] = JS32(0); + else j8Ptr[0] = j8Ptr[3] = JS8(0); + } + + return 1; +} + + +void recLoad32(u32 bit, u32 imm, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _eeOnLoadWrite(_Rt_); + if( bit == 32 ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_MMXTAG; + else mmreg = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + mmreg = EAX; + } + + switch(bit) { + case 8: ineax = recMemConstRead8(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); break; + case 16: + assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 2 == 0 ); + ineax = recMemConstRead16(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); + break; + case 32: + // used by LWL/LWR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 4 == 0 ); + ineax = recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm); + break; + } + + if( ineax || !(mmreg&MEM_MMXTAG) ) { + if( mmreg&MEM_MMXTAG ) mmxregs[mmreg&0xf].inuse = 0; + recTransferX86ToReg(EAX, _Rt_, sign); + } + else { + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + + if( REC_FORCEMMX ) mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + else _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, imm, mmregs, 0, 0); + + if( mmreg >= 0 ) { + MOVD32RmOffsettoMMX(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset-(32-bit)/8); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + else { + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + if( mmreg >= 0 ) { + if( EEINST_ISLIVE1(_Rt_) ) MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_]); + else MOVD32RtoMMX(mmreg, EAX); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLoad32_co(u32 bit, u32 sign) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax = 0; + u32 written = 0; + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + + if( bit == 32 ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_MMXTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_MMXTAG; + else mmreg2 = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + mmreg1 = EBX; + mmreg2 = EAX; + } + + // do const processing + switch(bit) { + case 8: + if( recMemConstRead8(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead8(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 16: + if( recMemConstRead16(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead16(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 32: + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + break; + } + + if( !written && _Rt_ ) { + if( mmreg1&MEM_MMXTAG ) { + assert( mmxregs[mmreg1&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg1&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg1&0xf, 32-bit); + } + else recTransferX86ToReg(mmreg1, _Rt_, sign); + } + if( nextrt ) { + g_pCurInstInfo++; + if( !ineax && (mmreg2 & MEM_MMXTAG) ) { + assert( mmxregs[mmreg2&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg2&0xf, nextrt, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg2&0xf, 32-bit); + } + else { + if( mmreg2&MEM_MMXTAG ) mmxregs[mmreg2&0xf].inuse = 0; + recTransferX86ToReg(mmreg2, nextrt, sign); + } + g_pCurInstInfo--; + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + assert( !REC_FORCEMMX ); + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + switch(bit) { + case 8: + if( sign ) { + MOVSX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 16: + if( sign ) { + MOVSX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 32: + MOV32RmtoROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EBX, _Rt_, sign); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + break; + case 16: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + break; + case 32: + MOV32RtoM((u32)&s_tempaddr, ECX); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( nextrt ) { + g_pCurInstInfo++; + recTransferX86ToReg(EAX, nextrt, sign); + g_pCurInstInfo--; + } + } +} + +void recLB( void ) { recLoad32(8, _Imm_, 1); } +void recLB_co( void ) { recLoad32_co(8, 1); } +void recLBU( void ) { recLoad32(8, _Imm_, 0); } +void recLBU_co( void ) { recLoad32_co(8, 0); } +void recLH( void ) { recLoad32(16, _Imm_, 1); } +void recLH_co( void ) { recLoad32_co(16, 1); } +void recLHU( void ) { recLoad32(16, _Imm_, 0); } +void recLHU_co( void ) { recLoad32_co(16, 0); } +void recLW( void ) { recLoad32(32, _Imm_, 1); } +void recLW_co( void ) { recLoad32_co(32, 1); } +void recLWU( void ) { recLoad32(32, _Imm_, 0); } +void recLWU_co( void ) { recLoad32_co(32, 0); } + +//////////////////////////////////////////////////// + +// paired with LWR +void recLWL_co(void) { recLoad32(32, _Imm_-3, 1); } + +void recLWL( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, 24-shift*8); + AND32ItoR(ECX, (0xffffff>>(shift*8))); + OR32RtoR(EAX, ECX); + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) { + // mem << LWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHL32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff); + SAR32CLtoR(EDX); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(EDX, ECX); + + // combine + OR32RtoR(EAX, EDX); + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// + +// paired with LWL +void recLWR_co(void) { recLoad32(32, _Imm_, 1); } + +void recLWR( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, shift*8); + AND32ItoR(ECX, (0xffffff00<<(24-shift*8))); + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + PUSH32R(ECX); + AND32ItoR(ECX, ~3); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) + { + // mem << LWL_SHIFT[shift] + MOV32RtoR(ECX, EDX); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 3); // *8 + SHR32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(EDX, ECX); + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(ECX, EDX); + + // combine + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// +void recLoad64(u32 imm, int align) +{ + int mmreg; + int mask = align ? ~7 : ~0; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // also used by LDL/LDR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 8 == 0 ); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg); + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + if( !_hasFreeMMXreg() && _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ|MODE_WRITE); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, t0reg); + + if( _Rt_ ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UD[0], t0reg); + } + + _freeMMXreg(t0reg); + } + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + MOVQRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + + SetMMXstate(); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + SSE_MOVLPSRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + SSE_MOVLPS_M64_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + } + else { + int t0reg = _Rt_ ? _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE) : -1; + + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + if( t0reg >= 0 ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + SetMMXstate(); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( _Rt_ ) { + //_deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + ADD32ItoR(ESP, 4); + + if( t0reg >= 0 ) MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); +} + +void recLD(void) { recLoad64(_Imm_, 1); } + +void recLD_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLD(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int mmreg1 = -1, mmreg2 = -1, t0reg = -1, t1reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + if( nextrt ) _eeOnWriteReg(nextrt, 0); + + if( _Rt_ ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 < 0 ) { + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg1 >= 0 ) mmreg1 |= 0x8000; + } + + if( mmreg1 < 0 && _hasFreeMMXreg() ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + if( nextrt ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 < 0 ) { + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE|MODE_READ); + if( mmreg2 >= 0 ) mmreg2 |= 0x8000; + } + + if( mmreg2 < 0 && _hasFreeMMXreg() ) mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_WRITE); + } + + if( mmreg1 < 0 || mmreg2 < 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( mmreg1 < 0 && mmreg2 < 0 && _hasFreeMMXreg() ) { + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + else t1reg = t0reg; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 1, 0); + + if( mmreg1 >= 0 ) { + if( mmreg1 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _Rt_ ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], t0reg); + } + } + + if( mmreg2 >= 0 ) { + if( mmreg2 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + else MOVQRmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( nextrt ) { + MOVQRmtoROffset(t1reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ], t1reg); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg1 >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg1 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + if( _Rt_ ) { + _deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + + if( mmreg2 >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + + if( mmreg2 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + else MOVQMtoR(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + } + else { + if( nextrt ) { + _deleteEEreg(nextrt, 0); + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + } + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + if( mmreg1 < 0 || mmreg2 < 0 || !(mmreg1&0x8000) || !(mmreg2&0x8000) ) SetMMXstate(); + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + if( t0reg != t1reg && t1reg >= 0 ) _freeMMXreg(t1reg); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +void recLD_coX( int num ) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLD(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _eeOnWriteReg(nextrts[i], 0); + } + + if( _Rt_ ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg < 0 ) { + mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + } + else mmreg |= MEM_MMXTAG; + } + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckGPRtoMMX(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + if( mmregs[i] < 0 ) { + mmregs[i] = _allocCheckGPRtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE|MODE_READ); + if( mmregs[i] >= 0 ) mmregs[i] |= MEM_XMMTAG; + else mmregs[i] = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_WRITE)|MEM_MMXTAG; + } + else mmregs[i] |= MEM_MMXTAG; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 1, 0); + + if( mmreg >= 0 ) { + if( mmreg & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + u32 off = PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + + if( mmregs[i] >= 0 ) { + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmregs[i]&0xf, ECX, off); + else MOVQRmtoROffset(mmregs[i]&0xf, ECX, off); + } + } + + if( dohw ) { + if( (s_bCachingMem & 2) || num > 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead64 ); + } + + for(i = 0; i < num; ++i ) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( mmregs[i] >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + CALLFunc( (int)recMemRead64 ); + + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + else MOVQMtoR(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + } + else { + MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead64 ); + } + } + + ADD32ItoR(ESP, 4); + + if( (s_bCachingMem & 2) || num > 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +//////////////////////////////////////////////////// +void recLDL_co(void) { + recLoad64(_Imm_-7, 0); } + +void recLDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR_co(void) { recLoad64(_Imm_, 0); } + +void recLDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + int mmreg = -1; +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Rt_ ) { + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_XMM) || !(g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + else { + int t0reg; + _deleteGPRtoXMMreg(_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + mmreg |= t0reg<<4; + } + } + else mmreg = _allocTempXMMreg(XMMT_INT, -1); + + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + if( !_Rt_ ) _freeXMMreg(mmreg); + if( IS_MMXREG(mmreg) ) { + // flush temp + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], (mmreg>>4)&0xf); + _freeMMXreg((mmreg>>4)&0xf); + } + else assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int t0reg = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + // check if can process mmx + if( _hasFreeMMXreg() ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) { + mmreg |= MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg < 0 ) + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg & MEM_MMXTAG ) MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + ADD32ItoR(ESP, 4); + } + } + else { + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQ_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLQ(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int t0reg = -1; + int mmregs = _eePrepareReg(_Rs_); + + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + if( _hasFreeMMXreg() ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) { + mmreg1 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg1 < 0 ) { + mmreg1 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + } + + if( nextrt ) { + _eeOnWriteReg(nextrt, 0); + + if( _hasFreeMMXreg() ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) { + mmreg2 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+nextrt, 2); + + if( mmreg2 < 0 ) { + mmreg2 = _allocGPRtoXMMreg(-1, nextrt, MODE_WRITE); + } + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg1 & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( nextrt ) { + if( mmreg2 & MEM_MMXTAG ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOVQRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((u32)&cpuRegs.GPR.r[nextrt].UL[2], t0reg); + } + else { + SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrt].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead128 ); + + if( _Rt_) { + if( mmreg1 & MEM_MMXTAG ) MOVQMtoR(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + if( nextrt ) { + if( mmreg2 & MEM_MMXTAG ) MOVQMtoR(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ]); + else SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ] ); + } + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } +} + +// coissues more than 2 LQs +void recLQ_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLQ(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + if( _Rt_ ) _deleteMMXreg(MMX_GPR+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + if( nextrts[i] ) _deleteMMXreg(MMX_GPR+nextrts[i], 2); + } + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) { + _eeOnWriteReg(nextrts[i], 0); + mmregs[i] = _allocGPRtoXMMreg(-1, nextrts[i], MODE_WRITE); + } + else mmregs[i] = -1; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 2, 1); + + if( _Rt_ ) SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) SSEX_MOVDQARmtoROffset(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + if( _Rt_) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( nextrts[i] ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead128 ); + if( nextrts[i] ) SSEX_MOVDQA_M128_to_XMM(mmregs[i], (int)&cpuRegs.GPR.r[ nextrts[i] ].UL[ 0 ] ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +extern void recClear64(BASEBLOCK* p); +extern void recClear128(BASEBLOCK* p); + +// check if clearing executable code, size is in dwords +void recMemConstClear(u32 mem, u32 size) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !recLUT[mem>>16] ) + return; + + //iFlushCall(0); // just in case + + // check if mem is executable, and clear it + //CMP32ItoM((u32)&maxrecmem, mem); + //j8Ptr[5] = JBE8(0); + + // can clear now + if( size == 1 ) { + CMP32ItoM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); + } + else if( size == 2 ) { + // need to clear 8 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+8, 0); + j8Ptr[7] = JNE8(0); + + j8Ptr[8] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[6] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear64); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[8] ); + } + else { + assert( size == 4 ); + // need to clear 16 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK), 0); + j8Ptr[7] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*2, 0); + j8Ptr[8] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*3, 0); + j8Ptr[9] = JNE8(0); + + j8Ptr[10] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[8] ); + x86SetJ8( j8Ptr[9] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear128); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[10] ); + } + + //x86SetJ8(j8Ptr[5]); +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear32() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, recLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call recClearMem + add esp, 4 +ClearRet: + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear64() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear64 + ret +Clear64: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check both blocks + cmp dword ptr [edx], 0 + jne DoClear0 + cmp dword ptr [edx+8], 0 + jne DoClear1 + ret + +DoClear1: + add edx, 8 +DoClear0: + sub esp, 4 + mov dword ptr [esp], edx + call recClear64 + add esp, 4 + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear128() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear128 + ret +Clear128: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check all 4 blocks + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + ret + +DoClear: + sub esp, 4 + mov dword ptr [esp], edx + call recClear128 + add esp, 4 + ret + } +} + +void recStore_raw(EEINST* pinst, int bit, int x86reg, int gprreg, u32 offset) +{ + if( bit == 128 ) { + int mmreg; + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + + SetMMXstate(); + } + else { + + if( GPR_IS_CONST1( gprreg ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + SetMMXstate(); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( _hasFreeMMXreg() ) { + int t0reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); +// MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); +// MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset+8); + } + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + } + return; + } + + if( GPR_IS_CONST1( gprreg ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 16: MOV16ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 32: MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 64: + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + break; + } + } + else { + int mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ); + if( mmreg < 0 ) { + mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + if( mmreg >= 0 ) mmreg |= 0x8000; + } + + if( bit == 64 ) { + //sd + if( mmreg >= 0 ) { + if( mmreg & 0x8000 ) { + SSE_MOVLPSRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVQRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + if( (mmreg = _allocCheckGPRtoMMX(pinst, gprreg, MODE_READ)) >= 0 ) { + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_GPR+gprreg, MODE_READ); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + } + } + } + else if( bit == 32 ) { + // sw + if( mmreg >= 0 ) { + if( mmreg & 0x8000) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVD32MMXtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); + } + } + else { + // sb, sh + if( mmreg >= 0) { + if( mmreg & 0x8000) { + if( !(xmmregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + else { + if( !(mmxregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + } + + if( mmreg >= 0) { + if( mmreg & 0x8000 ) SSE2_MOVD_XMM_to_R(x86reg, mmreg&0xf); + else { + MOVD32MMXtoR(x86reg, mmreg&0xf); + SetMMXstate(); + } + } + else { + switch(bit) { + case 8: MOV8MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + + switch(bit) { + case 8: MOV8RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 16: MOV16RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 32: MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + } + } + } +} + +void recStore_call(int bit, int gprreg, u32 offset) +{ + // some type of hardware write + if( GPR_IS_CONST1( gprreg ) ) { + if( bit == 128 ) { + if( gprreg > 0 ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], g_cpuConstRegs[gprreg].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], g_cpuConstRegs[gprreg].UL[1]); + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + if( !(g_cpuFlushedConstReg&(1<= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + // sd + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVLPS_XMM_to_M64((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + SetMMXstate(); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else { + // sb, sh, sw + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + SSE2_MOVD_XMM_to_R(EAX, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE)) { + MOVD32MMXtoR(EAX, mmreg); + SetMMXstate(); + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + } + } + + if( offset != 0 ) ADD32ItoR(ECX, offset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)recMemWrite8 ); break; + case 16: CALLFunc( (int)recMemWrite16 ); break; + case 32: CALLFunc( (int)recMemWrite32 ); break; + case 64: CALLFunc( (int)recMemWrite64 ); break; + case 128: CALLFunc( (int)recMemWrite128 ); break; + } +} + +int _eePrepConstWrite128(int gprreg) +{ + int mmreg = 0; + + if( GPR_IS_CONST1(gprreg) ) { + if( gprreg ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + _freeMMXreg(mmreg); + mmreg |= (gprreg<<16)|MEM_EECONSTTAG; + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(mmreg, mmreg); + _freeXMMreg(mmreg); + mmreg |= MEM_XMMTAG; + } + } + else { + if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + int mmregtemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmregtemp, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + mmreg |= (mmregtemp<<4)|MEM_MMXTAG; + _freeMMXreg(mmregtemp); + } + else mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ)|MEM_XMMTAG; + } + + return mmreg; +} + +void recStore(int bit, u32 imm, int align) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+imm; + int doclear = 0; + StopPerfCounter(); + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite8(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 16: + assert( (addr)%2 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite16(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 32: + // used by SWL/SWR + //assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + break; + case 64: + { + //assert( (addr)%8 == 0 ); + int mask = align ? ~7 : ~0; + + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite64(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else { + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + + if( doclear ) { + recMemConstClear((addr)&~7, 2); + } + + break; + } + case 128: + assert( (addr)%16 == 0 ); + + if( recMemConstWrite128((addr)&~15, _eePrepConstWrite128(_Rt_)) ) { + CMP32ItoM((u32)&maxrecmem, addr); + j8Ptr[0] = JB8(0); + recMemConstClear((addr)&~15, 4); + x86SetJ8(j8Ptr[0]); + } + + break; + } + + StartPerfCounter(); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, imm, mmregs, align ? bit/64 : 0, 0); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[4] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + if( bit < 32 || !align ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[5] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + StopPerfCounter(); + recStore_call(bit, _Rt_, s_nAddMemOffset); + StartPerfCounter(); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recStore_co(int bit, int align) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_; + u32 coaddr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_; + int mmreg, t0reg = -1, mmreg2; + int doclear = 0; + + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite8(addr, EAX); + } + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite8(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite8(coaddr, EAX); + } + break; + case 16: + assert( (addr)%2 == 0 ); + assert( (coaddr)%2 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite16(addr, EAX); + } + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite16(coaddr, EAX); + } + break; + case 32: + assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite32(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_XMMTAG|(nextrt<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_MMXTAG|(nextrt<<16)); + } + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite32(coaddr, EAX); + } + + break; + case 64: + { + int mask = align ? ~7 : ~0; + //assert( (addr)%8 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + + if( GPR_IS_CONST1(nextrt) ) mmreg2 = MEM_EECONSTTAG|(nextrt<<16); + else if( (mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + mmreg2 |= MEM_XMMTAG|(nextrt<<16); + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_READ)|MEM_MMXTAG|(nextrt<<16); + + doclear = recMemConstWrite64((addr)&mask, mmreg); + doclear |= recMemConstWrite64((coaddr)&mask, mmreg2); + doclear <<= 1; + break; + } + case 128: + assert( (addr)%16 == 0 ); + + mmreg = _eePrepConstWrite128(_Rt_); + mmreg2 = _eePrepConstWrite128(nextrt); + doclear = recMemConstWrite128((addr)&~15, mmreg); + doclear |= recMemConstWrite128((coaddr)&~15, mmreg2); + doclear <<= 2; + break; + } + + if( doclear ) { + u8* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+(_Imm_ < _Imm_co_ ? _Imm_ : _Imm_co_)); + ptr = JB8(0); + recMemConstClear((addr)&~(doclear*4-1), doclear); + recMemConstClear((coaddr)&~(doclear*4-1), doclear); + x86SetJ8A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int off = _Imm_co_-_Imm_; + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align ? bit/64 : 0, bit==128); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + recStore_raw(g_pCurInstInfo+1, bit, EBX, nextrt, s_nAddMemOffset+off); + + // clear the writes, do only one camera (with the lowest addr) + if( off < 0 ) ADD32ItoR(ECX, s_nAddMemOffset+off); + else if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( off < 0 ) ADD32ItoR(ECX, -off); + else ADD32ItoR(ECX, off); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(bit, _Rt_, s_nAddMemOffset); + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(bit, nextrt, s_nAddMemOffset+_Imm_co_-_Imm_); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recSB( void ) { recStore(8, _Imm_, 1); } +void recSB_co( void ) { recStore_co(8, 1); } +void recSH( void ) { recStore(16, _Imm_, 1); } +void recSH_co( void ) { recStore_co(16, 1); } +void recSW( void ) { recStore(32, _Imm_, 1); } +void recSW_co( void ) { recStore_co(32, 1); } + +//////////////////////////////////////////////////// +void recSWL_co(void) { recStore(32, _Imm_-3, 0); } + +void recSWL( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0xffffff00<<(shift*8)); + SHR32ItoR(ECX, 24-shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem >> SWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHR32CLtoR(EBX); + + // mov temp and compute _rt_ & SWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +//////////////////////////////////////////////////// +void recSWR_co(void) { recStore(32, _Imm_, 0); } + +void recSWR( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0x00ffffff>>(24-shift*8)); + SHL32ItoR(ECX, shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem << SWR_SHIFT[shift] + MOV32RtoR(ECX, EDX); + SHL32CLtoR(EBX); + + // mov temp and compute _rt_ & SWR_MASK[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0x00ffffff); + SHR32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +void recSD( void ) { recStore(64, _Imm_, 1); } +void recSD_co( void ) { recStore_co(64, 1); } + +// coissues more than 2 SDs +void recSD_coX(int num, int align) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + u32 mask = align ? ~7 : ~0; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&mask, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + if( GPR_IS_CONST1(nextrts[i]) ) mmreg = MEM_EECONSTTAG|(nextrts[i]<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrts[i], MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_READ)|MEM_MMXTAG|(nextrts[i]<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&mask, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~7, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~7, 2); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align, 1); + + recStore_raw(g_pCurInstInfo, 64, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 64, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear64); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear64); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(64, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(64, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +//////////////////////////////////////////////////// +void recSDL_co(void) { recStore(64, _Imm_-7, 0); } + +void recSDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR_co(void) { recStore(64, _Imm_, 0); } + +void recSDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { recStore(128, _Imm_, 1); } +void recSQ_co( void ) { recStore_co(128, 1); } + +// coissues more than 2 SQs +void recSQ_coX(int num) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + mmreg = _eePrepConstWrite128(_Rt_); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + mmreg = _eePrepConstWrite128(nextrts[i]); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+imm)&~15, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~15, 4); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 1); + + recStore_raw(g_pCurInstInfo, 128, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 128, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear128); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear128); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(128, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(128, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + mmreg = EAX; + } + + if( !(mmreg&MEM_XMMTAG) ) + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + else +#endif + { + int dohw; + int regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + + if( regt ) SSE2_MOVD_R_to_XMM(regt, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 written = 0; + int ineax, mmreg1, mmreg2; + + mmreg1 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + else mmreg2 = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_XMMTAG ) xmmregs[mmreg1&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + + if( !written ) { + if( !(mmreg1&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + } + + if( ineax || !(mmreg2 & MEM_XMMTAG) ) { + if( mmreg2&MEM_XMMTAG ) xmmregs[mmreg2&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int regt, regtnext; + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + regtnext = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( regtnext >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regtnext, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32R(ECX); + CALLFunc( (int)recMemRead32 ); + POP32R(ECX); + + if( regt >= 0 ) { + SSE2_MOVD_R_to_XMM(regt, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( regtnext >= 0 ) { + SSE2_MOVD_R_to_XMM(regtnext, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recLWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax; + u32 written = 0; + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + // recompile two at a time + for(i = 0; i < num-1; i += 2) { + nextrts[0] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + nextrts[1] = ((*(u32*)(PSM(pc+i*4+4)) >> 16) & 0x1F); + + written = 0; + mmregs[0] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[0], MODE_WRITE); + if( mmregs[0] >= 0 ) mmregs[0] |= MEM_XMMTAG; + else mmregs[0] = EBX; + + mmregs[1] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+2, nextrts[1], MODE_WRITE); + if( mmregs[1] >= 0 ) mmregs[1] |= MEM_XMMTAG; + else mmregs[1] = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmregs[0], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmregs[0]&MEM_XMMTAG ) xmmregs[mmregs[0]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmregs[1], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4+4))); + + if( !written ) { + if( !(mmregs[0]&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + } + + if( ineax || !(mmregs[1] & MEM_XMMTAG) ) { + if( mmregs[1]&MEM_XMMTAG ) xmmregs[mmregs[1]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[1] ].UL, EAX ); + } + } + + if( i < num ) { + // one left + int nextrt = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrt, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _deleteMMXreg(MMX_FPU+nextrts[i], 2); + } + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead32 ); + + if( mmreg >= 0 ) SSE2_MOVD_R_to_XMM(mmreg, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( mmregs[i] >= 0 ) SSE2_MOVD_R_to_XMM(mmregs[i], EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recSWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrt<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + int mmreg1, mmreg2; + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + assert( _checkMMXreg(MMX_FPU+nextrt, MODE_READ) == -1 ); + + mmreg1 = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if(mmreg1 >= 0 ) { + if( mmreg2 >= 0 ) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + else { + if( mmreg2 >= 0 ) { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32MtoR(EDX, (int)&fpuRegs.fpr[ nextrt ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg1 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg1); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + if( mmreg2 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg2); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recSWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + for(i = 0; i < num; ++i) { + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)), mmreg); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + for(i = 0; i < num; ++i) { + assert( _checkMMXreg(MMX_FPU+nextrts[i], MODE_READ) == -1 ); + mmregs[i] = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmregs[i], PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + if( mmregs[i] >= 0 && (xmmregs[mmregs[i]].mode&MODE_WRITE) ) SSE2_MOVD_XMM_to_R(EAX, mmregs[i]); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + CALLFunc( (int)recMemWrite32 ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else mmreg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + if( !_Ft_ ) _freeXMMreg(mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Ft_ ) { + s8* rawreadptr = x86Ptr; + + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + CALLFunc( (int)recMemRead128 ); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0] ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + else { + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQC2_co( void ) +{ + int mmreg1 = -1, mmreg2 = -1, t0reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg1 >= 0 ? mmreg1 : t0reg); + + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + else if( t0reg < 0 ) t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg2 >= 0 ? mmreg2 : t0reg); + + if( t0reg >= 0 ) _freeXMMreg(t0reg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + if( mmreg1 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + if( mmreg2 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Ft_ ) PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg1 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0] ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&VU0.VF[nextrt].UD[0], 0 ); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg2 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0] ); + + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[1]); + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg); + } + } + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +void recSQC2_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1, mmreg2; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg1); + recMemConstWrite128(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg2); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg1 = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_VFREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( mmreg1 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg1 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg1); + } + else if( _hasFreeMMXreg() ) { + mmreg1 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg1); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( mmreg2 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( _hasFreeXMMreg() ) { + mmreg2 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + _freeXMMreg(mmreg2); + } + else if( _hasFreeMMXreg() ) { + mmreg2 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UL[2]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + SetMMXstate(); + _freeMMXreg(mmreg2); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+4); + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( mmreg1 >= 0) { + if( xmmregs[mmreg1].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg1); + } + } + + MOV32RtoM((u32)&s_tempaddr, ECX); + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + if( mmreg2 >= 0) { + if( xmmregs[mmreg2].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[nextrt].UD[0], mmreg2); + } + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + MOV32ItoR(EAX, (int)&VU0.VF[nextrt].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +#else + +__declspec(align(16)) u32 dummyValue[4]; + +//////////////////////////////////////////////////// +void recLB( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVSX32R8toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLBU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R8toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLH( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOVSX32R16toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLHU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R16toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLW( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWR ); +} + +//////////////////////////////////////////////////// +extern void MOV64RmtoR( x86IntRegType to, x86IntRegType from ); + +void recLD( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead64 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + AND32ItoR( EAX, ~0xf ); + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); + +} + +//////////////////////////////////////////////////// +void recSB( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite8 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite16 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite64 ); + ADD32ItoR( ESP, 12 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + AND32ItoR( EAX, ~0xf ); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +#endif + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.h b/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.h new file mode 100644 index 0000000..fd078b9 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900LoadStore.h @@ -0,0 +1,90 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSDL( void ); +void recSDR( void ); +void recSQ( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +// coissues +#ifdef WIN32_VIRTUAL_MEM +void recLB_co( void ); +void recLBU_co( void ); +void recLH_co( void ); +void recLHU_co( void ); +void recLW_co( void ); +void recLWU_co( void ); +void recLWL_co( void ); +void recLWR_co( void ); +void recLD_co( void ); +void recLDR_co( void ); +void recLDL_co( void ); +void recLQ_co( void ); +void recSB_co( void ); +void recSH_co( void ); +void recSW_co( void ); +void recSWL_co( void ); +void recSWR_co( void ); +void recSD_co( void ); +void recSDL_co( void ); +void recSDR_co( void ); +void recSQ_co( void ); +void recLWC1_co( void ); +void recSWC1_co( void ); +void recLQC2_co( void ); +void recSQC2_co( void ); + +// coissue-X +void recLD_coX(int num); +void recLQ_coX(int num); +void recLWC1_coX(int num); +void recSD_coX(int num); +void recSQ_coX(int num); +void recSWC1_coX(int num); + +#endif + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Move.c b/branches/pcsx2_0.9.1/ix86-32/iR5900Move.c new file mode 100644 index 0000000..0c84c53 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Move.c @@ -0,0 +1,822 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#elif defined(EE_CONST_PROP) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//// LUI +void recLUI(int info) +{ + int mmreg; + if(!_Rt_) return; + + _eeOnWriteReg(_Rt_, 1); + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE)) >= 0 ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + } + + _deleteEEreg(_Rt_, 0); + GPR_SET_CONST(_Rt_); + g_cpuConstRegs[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +//////////////////////////////////////////////////// +void recMFHILO(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + assert( regd != reghi ); + + xmmregs[regd].inuse = 0; + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + else { + SSE_MOVLPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + SSE2_MOVQ_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + reghi = _checkMMXreg(MMX_GPR+xmmhilo, MODE_READ); + + if( reghi >= 0 ) { + + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], regd); + } + xmmregs[regd].inuse = 0; + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + SetMMXstate(); + + if( regd >= 0 ) { + MOVQRtoR(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + else SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 0 ] : (int)&cpuRegs.LO.UL[ 0 ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.UL[ 1 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } +} + +void recMTHILO(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + assert( reghi != regs ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + _deleteGPRtoXMMreg(_Rs_, 0); + SSE2_PUNPCKHQDQ_XMM_to_XMM(reghi, reghi); + SSE2_PUNPCKLQDQ_XMM_to_XMM(regs, reghi); + + // swap regs + xmmregs[regs] = xmmregs[reghi]; + xmmregs[reghi].inuse = 0; + xmmregs[regs].mode |= MODE_WRITE; + } + else { + SSE2EMU_MOVSD_XMM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + if( EEINST_ISLIVE2(xmmhilo) ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64(addrhilo+8, reghi); + } + xmmregs[reghi].inuse = 0; + MOVQRtoM(addrhilo, regs); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + _flushConstReg(_Rs_); + SSE_MOVLPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + } + else { + reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, xmmhilo, MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + //SetMMXstate(); + SSE2_MOVDQ2Q_XMM_to_MM(reghi, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoR(reghi, regs); + } + else { + _flushConstReg(_Rs_); + MOVQMtoR(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + } + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+4, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo, EAX ); + MOV32RtoM( addrhilo+4, EDX ); + } + } + } + } + } +} + +void recMFHI( void ) +{ + recMFHILO(1); +} + +void recMFLO( void ) +{ + recMFHILO(0); +} + +void recMTHI( void ) +{ + recMTHILO(1); +} + +void recMTLO( void ) +{ + recMTHILO(0); +} + +//////////////////////////////////////////////////// +void recMFHILO1(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + SSEX_MOVHLPS_XMM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + _deleteEEreg(_Rd_, 0); + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PUNPCKHQDQ_M128_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + SSE2_PSHUFD_XMM_to_XMM(regd, regd, 0x4e); + } + else { + SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + } + else { + SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + + xmmregs[regd].mode |= MODE_WRITE; + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 2 ] : (int)&cpuRegs.LO.UL[ 2 ]); + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 3 ] : (int)&cpuRegs.LO.UL[ 3 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + } + } +} + +void recMTHILO1(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, xmmhilo, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_XMM_to_XMM(reghi, regs); + else SSE_MOVLHPS_XMM_to_XMM(reghi, regs); + } + else { + _deleteEEreg(_Rs_, 1); + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_M128_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + else SSE_MOVHPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ]); + + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo+8, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo+8, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo+8, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+12, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo+8, EAX ); + MOV32RtoM( addrhilo+12, EDX ); + } + } + } + } +} + +void recMFHI1( void ) +{ + recMFHILO1(1); +} + +void recMFLO1( void ) +{ + recMFHILO1(0); +} + +void recMTHI1( void ) +{ + recMTHILO1(1); +} + +void recMTLO1( void ) +{ + recMTHILO1(0); +} + +//// MOVZ +void recMOVZtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +__declspec(align(16)) static s_zero[4] = {0,0,0xffffffff, 0xffffffff}; + +void recMOVZtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVZtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + if( info & PROCESS_EE_MMX ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + return; + } + + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVZtemp_(int info) +{ + int t0reg = -1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVZtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVZ() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + } + + recMOVZtemp(); +} + +//// MOVN +void recMOVNtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +void recMOVNtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVNtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVNtemp_(int info) +{ + int t0reg=-1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVNtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVN() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + } + + recMOVNtemp(); +} + +#else + +//////////////////////////////////////////////////// +void recLUI( void ) +{ + if(!_Rt_) return; + if ( _Imm_ < 0 ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0xffffffff ); //V + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); //V + } +} + +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Move.h b/branches/pcsx2_0.9.1/ix86-32/iR5900Move.h new file mode 100644 index 0000000..ae501e3 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.c b/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.c new file mode 100644 index 0000000..28c720a --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.c @@ -0,0 +1,949 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC( MULT1 ); +REC_FUNC( MULTU1 ); + +REC_FUNC(DIV); +REC_FUNC(DIVU); +REC_FUNC( DIV1 ); +REC_FUNC( DIVU1 ); + +REC_FUNC( MADD ); +REC_FUNC( MADDU ); +REC_FUNC( MADD1 ); +REC_FUNC( MADDU1 ); + +#elif defined(EE_CONST_PROP) + +// if upper is 1, write in upper 64 bits of LO/HI +void recWritebackHILO(int info, int writed, int upper) +{ + int regd, reglo = -1, reghi, savedlo = 0; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + MOV32RtoR( ECX, EDX ); + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + + _deleteMMXreg(XMMGPR_LO, 2); + + if( (reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ)) >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + + xmmregs[reglo].inuse = 0; + reglo = -1; + } + + CDQ(); + MOV32RtoM( loaddr, EAX ); + MOV32RtoM( loaddr+4, EDX ); + savedlo = 1; + } + + if ( writed && _Rd_ ) + { + _eeOnWriteReg(_Rd_, 1); + + regd = -1; + if( g_pCurInstInfo->regs[_Rd_] & EEINST_MMX ) { + + if( savedlo ) { + regd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + MOVQMtoR(regd, loaddr); + } + } + else if( g_pCurInstInfo->regs[_Rd_] & EEINST_XMM ) { + if( savedlo ) { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE|MODE_READ); + if( regd >= 0 ) { + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + regd |= 0x8000; + } + } + } + + if( regd < 0 ) { + _deleteEEreg(_Rd_, 0); + + if( EEINST_ISLIVE1(_Rd_) && !savedlo ) CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else EEINST_RESETHASLIVE1(_Rd_); + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + _deleteMMXreg(XMMGPR_HI, 2); + + if( (reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ)) >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + else SSE_MOVHPS_XMM_to_M64(hiaddr+8, reghi); + } + + xmmregs[reghi].inuse = 0; + reghi = -1; + } + + MOV32RtoM(hiaddr, ECX ); + SAR32ItoR(ECX, 31); + MOV32RtoM(hiaddr+4, ECX ); + } +} + +void recWritebackHILOMMX(int info, int regsource, int writed, int upper) +{ + int regd, t0reg, t1reg = -1; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + SetMMXstate(); + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, regsource); + PSRADItoR(t0reg, 31); // shift in 0s + + if( (g_pCurInstInfo->regs[XMMGPR_LO] & testlive) || (writed && _Rd_) ) { + if( (g_pCurInstInfo->regs[XMMGPR_HI] & testlive) ) + { + if( !_hasFreeMMXreg() ) { + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t1reg, regsource); + } + + PUNPCKLDQRtoR(regsource, t0reg); + } + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + int reglo; + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + MOVQRtoR(reglo, regsource); + } + else { + reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ); + + MOVQRtoM(loaddr, regsource); + + if( reglo >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + xmmregs[reglo].inuse = 0; + reglo = -1; + } + } + } + + if ( writed && _Rd_ ) + { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + if( regd != regsource ) MOVQRtoR(regd, regsource); + } + else { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ); + + if( regd >= 0 ) { + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + // lo written + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + + xmmregs[regd].inuse = 0; + } + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + int mmreg = -1, reghi; + + if( t1reg >= 0 ) { + PUNPCKHDQRtoR(t1reg, t0reg); + mmreg = t1reg; + } + else { + // can't modify regsource + PUNPCKHDQRtoR(t0reg, regsource); + mmreg = t0reg; + PSHUFWRtoR(t0reg, t0reg, 0x4e); + } + + if( upper ) { + reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ); + if( reghi >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + } + + xmmregs[reghi].inuse = 0; + MOVQRtoM(hiaddr, mmreg); + } + else { + _deleteGPRtoXMMreg(XMMGPR_HI, 2); + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + mmxregs[mmreg].mode = MODE_WRITE; + mmxregs[mmreg].reg = MMX_GPR+MMX_HI; + + if( t1reg >= 0 ) t1reg = -1; + else t0reg = -1; + } + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg&0xf); + if( t1reg >= 0 ) _freeMMXreg(t1reg&0xf); +} + +void recWritebackConstHILO(u64 res, int writed, int upper) +{ + int reglo, reghi; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + MOVQMtoR(reglo, (u32)ptr); + } + else { + reglo = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE|MODE_READ); + + if( reglo >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reglo, (u32)ptr); + } + else { + MOV32ItoM(loaddr, res & 0xffffffff); + MOV32ItoM(loaddr+4, (res&0x80000000)?0xffffffff:0); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + MOVQMtoR(reghi, (u32)ptr); + } + else { + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr); + } + else { + _deleteEEreg(XMMGPR_HI, 0); + MOV32ItoM(hiaddr, res >> 32); + MOV32ItoM(hiaddr+4, (res>>63)?0xffffffff:0); + } + } + } + + if (!writed || !_Rd_) return; + g_cpuConstRegs[_Rd_].UD[0] = (s32)(res & 0xffffffff); //that is the difference +} + +//// MULT +void recMULT_const() +{ + s64 res = (s64)g_cpuConstRegs[_Rs_].SL[0] * (s64)g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process); +void recMULTsuper(int info, int upper, int process) +{ + assert( !(info&PROCESS_EE_MMX) ); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + recWritebackHILO(info, 1, upper); +} + +//void recMULT_process(int info, int process) +//{ +// if( EEINST_ISLIVEMMX(XMMGPR_HI) || !(info&PROCESS_EE_MMX) ) { +// recMULTsuper(info, 0, process); +// } +// else { +// // EEREC_D isn't set +// int mmregd; +// +// if( _Rd_ ) { +// assert(EEREC_D == 0); +// mmregd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); +// +// if( mmregd < 0 ) { +// if( !(process&PROCESS_CONSTS) && ((g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rs_)) ) { +// _freeMMXreg(EEREC_S); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_S].inuse = 1; +// mmxregs[EEREC_S].reg = _Rd_; +// mmxregs[EEREC_S].mode = MODE_WRITE; +// mmregd = EEREC_S; +// } +// else if( !(process&PROCESS_CONSTT) && ((g_pCurInstInfo->regs[_Rt_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rt_)) ) { +// _freeMMXreg(EEREC_T); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_T].inuse = 1; +// mmxregs[EEREC_T].reg = _Rd_; +// mmxregs[EEREC_T].mode = MODE_WRITE; +// mmregd = EEREC_T; +// } +// else mmregd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); +// } +// +// info |= PROCESS_EE_SET_D(mmregd); +// } +// recMULTUsuper(info, 0, process); +// } +// +// // sometimes _Rd_ can be const +// if( _Rd_ ) _eeOnWriteReg(_Rd_, 1); +//} + +void recMULT_(int info) +{ + //recMULT_process(info, 0); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, 0); + } + else recMULTUsuper(info, 0, 0); +} + +void recMULT_consts(int info) +{ + //recMULT_process(info, PROCESS_CONSTS); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTS); + } + else recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULT_constt(int info) +{ + //recMULT_process(info, PROCESS_CONSTT); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTT); + } + else recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't set XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI +EERECOMPILE_CODE0(MULT, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// MULTU +void recMULTU_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process) +{ + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( (info & PROCESS_EE_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + + if( !_Rd_ ) { + // need some temp reg + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + assert( EEREC_D == 0 ); + info |= PROCESS_EE_SET_D(t0reg); + } + + if( process & PROCESS_CONSTS ) { + u32* ptempmem = _eeGetConstReg(_Rs_); + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else if( process & PROCESS_CONSTT ) { + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else { + if( EEREC_D == EEREC_S ) PMULUDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PMULUDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQRtoR(EEREC_D, EEREC_T); + } + } + + recWritebackHILOMMX(info, EEREC_D, 1, upper); + + if( !_Rd_ ) _freeMMXreg(EEREC_D); + return; + } + + if( info & PROCESS_EE_MMX ) { + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_].UL[0], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + _deleteMMXreg(MMX_GPR+_Rd_, 0); + } + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_S); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EAX, EEREC_S); + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + } + + recWritebackHILO(info, 1, upper); +} + +void recMULTU_(int info) +{ + recMULTUsuper(info, 0, 0); +} + +void recMULTU_consts(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULTU_constt(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't specify XMMINFO_WRITELO or XMMINFO_WRITEHI, that is taken care of +EERECOMPILE_CODE0(MULTU, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULT1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULT1_(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, 0); + } + else recMULTUsuper(info, 1, 0); +} + +void recMULT1_consts(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTS); + } + else recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULT1_constt(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTT); + } + else recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULT1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULTU1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULTU1_(int info) +{ + recMULTUsuper(info, 1, 0); +} + +void recMULTU1_consts(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULTU1_constt(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// DIV +void recDIV_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVsuper(int info, int sign, int upper, int process) +{ + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTT ) { + if( !g_cpuConstRegs[_Rt_].UL[0] ) + return; + MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] ); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + } + + if( process & PROCESS_CONSTS ) + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + + if( sign ) { + CDQ(); + IDIV32R( ECX ); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R( ECX ); + } + if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] ); + + // need to execute regardless of bad divide + recWritebackHILO(info, 0, upper); +} + +void recDIV_(int info) +{ + recDIVsuper(info, 1, 0, 0); +} + +void recDIV_consts(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTS); +} + +void recDIV_constt(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +//// DIVU +void recDIVU_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVU_(int info) +{ + recDIVsuper(info, 0, 0, 0); +} + +void recDIVU_consts(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTS); +} + +void recDIVU_constt(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +void recDIV1_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIV1_(int info) +{ + recDIVsuper(info, 1, 1, 0); +} + +void recDIV1_consts(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTS); +} + +void recDIV1_constt(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT); + +void recDIVU1_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIVU1_(int info) +{ + recDIVsuper(info, 0, 1, 0); +} + +void recDIVU1_consts(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTS); +} + +void recDIVU1_constt(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU1, XMMINFO_READS|XMMINFO_READT); + +//do EEINST_SETSIGNEXT +REC_FUNC( MADD, _Rd_ ); + +__declspec(align(16)) static u32 s_MaddMask[] = { 0x80000000, 0, 0x80000000, 0 }; + +void recMADDU() +{ + _eeOnWriteReg(_Rd_, 1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + u64 result = ((u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + + // dadd + MOV32MtoR( EAX, (int)&cpuRegs.LO.UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.HI.UL[ 0 ] ); + ADD32ItoR( EAX, (u32)result&0xffffffff ); + ADC32ItoR( ECX, (u32)(result>>32) ); + CDQ(); + if( _Rd_) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); + return; + } + + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if ( GPR_IS_CONST1(_Rt_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + MOV32RtoR( ECX, EDX ); + ADD32MtoR( EAX, (u32)&cpuRegs.LO.UL[0] ); + ADC32MtoR( ECX, (u32)&cpuRegs.HI.UL[0] ); + CDQ(); + if( _Rd_ ) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); +} + +void recMADD1() +{ + SysPrintf("MADD1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( MADD1, _Rd_ ); +} + +void recMADDU1() +{ + SysPrintf("MADDU1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( MADDU1, _Rd_ ); +} + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MULT1, _Rd_ ); +REC_FUNC( MULTU1, _Rd_ ); +REC_FUNC( DIV1, _Rd_ ); +REC_FUNC( DIVU1, _Rd_ ); + +REC_FUNC( MADD, _Rd_ ); +REC_FUNC( MADDU, _Rd_ ); +REC_FUNC( MADD1, _Rd_ ); +REC_FUNC( MADDU1, _Rd_ ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.h b/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.h new file mode 100644 index 0000000..243fd5c --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.c b/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.c new file mode 100644 index 0000000..51eae74 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.c @@ -0,0 +1,1349 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#elif defined(EE_CONST_PROP) + +//// SLL +void recSLL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << _Sa_); +} + +void recSLLs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( g_pCurInstInfo->regs[_Rd_]&EEINST_MMX ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(rdreg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLL_(int info) +{ + recSLLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SLL); + +//// SRL +void recSRL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> _Sa_); +} + +void recSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + // rdreg already sign extended + PSLLQItoR(rdreg, 32); + PSRLQItoR(rdreg, 32+sa); +// t0reg = _allocMMXreg(-1, MMX_TEMP, 0); +// +// // it is a signed shift +// PSRLDItoR(rdreg, sa); +// MOVQRtoR(t0reg, rdreg); +// PSRADItoR(t0reg, 31); +// +// take lower dword of rdreg and lower dword of t0reg +// PUNPCKLDQRtoR(rdreg, t0reg); +// _freeMMXreg(t0reg); + } +} + +void recSRL_(int info) +{ + recSRLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRL); + +//// SRA +void recSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> _Sa_); +} + +void recSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SAR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(rdreg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(t0reg, rdreg); + + // swap regs + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recSRA_(int info) +{ + recSRAs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRA); + +//////////////////////////////////////////////////// +void recDSLL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << _Sa_); +} + +void recDSLLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa); +} + +void recDSLL_(int info) +{ + recDSLLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL); + +//////////////////////////////////////////////////// +void recDSRL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> _Sa_); +} + +void recDSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa); +} + +void recDSRL_(int info) +{ + recDSRLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL); + +//// DSRA +void recDSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> _Sa_); +} + +void recDSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLQItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + PSRADItoR(t0reg, sa); + PSRLQItoR(rdreg, sa); + + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + } +} + +void recDSRA_(int info) +{ + recDSRAs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA); + +///// DSLL32 +void recDSLL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (_Sa_+32)); +} + +void recDSLL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa+32); +} + +void recDSLL32_(int info) +{ + recDSLL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL32); + +//// DSRL32 +void recDSRL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (_Sa_+32)); +} + +void recDSRL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa+32); +} + +void recDSRL32_(int info) +{ + recDSRL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL32); + +//// DSRA32 +void recDSRA32_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> (_Sa_+32)); +} + +void recDSRA32s_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ( ); + if ( sa != 0 ) SAR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, 31); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + if( sa ) PSRADItoR(rdreg, sa); + PUNPCKHDQRtoR(rdreg, rdreg); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + if( sa ) { + PSRADItoR(rdreg, sa); + PSRADItoR(t0reg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + // better timing + PSRADItoR(rdreg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(t0reg, rdreg); + + // swap + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recDSRA32_(int info) +{ + recDSRA32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA32); + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +__declspec(align(16)) u32 s_sa[4] = {0x1f, 0, 0x3f, 0}; + +int recSetShiftV(int info, int* rsreg, int* rtreg, int* rdreg, int* rstemp, int forcemmx, int shift64) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + *rtreg = EEREC_T; + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_)) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else if( forcemmx || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + *rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + else { + return 0; + } + + if( *rtreg != *rdreg ) MOVQRtoR(*rdreg, *rtreg); + return 1; +} + +void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift64) +{ + if( info & PROCESS_EE_MMX ) { + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_) ) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else { + _addNeededMMXreg(MMX_GPR+_Rd_); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + + _flushConstReg(_Rt_); +} + +void recMoveSignToRd(int info) +{ + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + + if( info & PROCESS_EE_MMX ) { + mmxregs[EEREC_D].inuse = 0; + } +} + +//// SLLV +void recSLLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSLLV_consts(int info) +{ + recSLLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info & PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRLV +void recSRLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRLV_consts(int info) +{ + recSRLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRAV +void recSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRAV_consts(int info) +{ + recSRAs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSLLV +void recDSLLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSLLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSLLs_(info, sa); + else recDSLL32s_(info, sa-32); +} + +void recDSLLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRLV +void recDSRLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRLs_(info, sa); + else recDSRL32s_(info, sa-32); +} + +void recDSRLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRAV +void recDSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s64)(g_cpuConstRegs[_Rt_].SD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRAV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRAs_(info, sa); + else recDSRA32s_(info, sa-32); +} + +void recDSRAV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recDSRA( void ) +{ + if( !_Rd_ ) return; //? + + if ( _Sa_ != 0 ) { + // it is a signed shift + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoR(MM1, MM0); + PSRADItoR(MM0, _Sa_); + PSRLQItoR(MM1, _Sa_); + + PUNPCKHDQRtoR(MM0, MM0); // shift to lower + // take lower dword of MM1 and lower dword of MM0 + + PUNPCKLDQRtoR(MM1, MM0); + + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM1); + } + else { + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSRA32(void) +{ + if( !_Rd_ ) return; //? + + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ(); + + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_ ); + } + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); +} + +//////////////////////////////////////////////////// +void recSLL( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHL32ItoR( EAX, _Sa_ ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHR32ItoR( EAX, _Sa_); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRA( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSLL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSLLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSRLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSLL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSLLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX,(int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSRLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +//////////////////////////////////////////////////// + + +//////////////////////////////////////////////////// +void recSLLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRAV( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +static u64 _sa = 0; +void recDSLLV( void ) +{ + if ( ! _Rd_ ) return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSLLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) +{ + if ( ! _Rd_ ) return; + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSRLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} +//////////////////////////////////////////////////////////////// +void recDSRAV( void ) +{ + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if ( _Rs_ != 0 ) { + PXORRtoR(MM1, MM1); + + // calc high bit + MOVQRtoR(MM2, MM0); + PUNPCKHDQRtoR(MM2, MM2); // shift to lower + PCMPGTDRtoR(MM1, MM2); + + // it is a signed shift + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOVD32RtoMMX(MM2, EAX); // amount to shift + NOT32R(EAX); + ADD32ItoR(EAX, 65); + + // right logical shift + PSRLQRtoR(MM0, MM2); + + // shift highest bit, 64 - eax + MOVD32RtoMMX(MM2, EAX); + PSLLQRtoR(MM1, MM2); // highest bits + + PORRtoR(MM0, MM1); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} +#endif diff --git a/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.h b/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.h new file mode 100644 index 0000000..b7b3592 --- /dev/null +++ b/branches/pcsx2_0.9.1/ix86-32/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/memcpy_amd.cpp b/branches/pcsx2_0.9.1/memcpy_amd.cpp new file mode 100644 index 0000000..1ebd68d --- /dev/null +++ b/branches/pcsx2_0.9.1/memcpy_amd.cpp @@ -0,0 +1,590 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +#include +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +// Inline assembly syntax for use with Visual C++ +extern "C" { + +#ifdef __WIN32__ +#include +#endif + +#include "ps2etypes.h" +#include "misc.h" + +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeXMMRegs_(save); } + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalMMXSaved; + +void checkregs() +{ + assert( !g_globalMMXLocked || g_globalMMXSaved ); +} +#endif + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + FreezeMMXRegs(1); + +#ifdef _DEBUG + __asm call checkregs +#endif + + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +int memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov edi, src1 + mov esi, src2 + mov ebx, ecx + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + + sub ecx, 32 + add esi, 32 + add edi, 32 + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm0, mm1 + pcmpeqd mm4, [edi+32] + pand mm0, mm2 + pcmpeqd mm5, [edi+40] + pand mm0, mm3 + pcmpeqd mm6, [edi+48] + pand mm0, mm4 + pcmpeqd mm7, [edi+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edi, 64 + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pcmpeqd mm3, [edi+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edi, 32 + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pcmpeqd mm2, [edi+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + xor edx, edx + cmp eax, 0xff + cmove eax, edx + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edi] + pcmpeqd mm1, [edi+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + xor edx, edx + cmp eax, 0xff + cmove eax, edx + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov ebx, [esi+4] + cmp eax, [edi] + je Next + mov eax, 1 + jmp End + +Next: + cmp ebx, [edi+4] + je Done + mov eax, 1 + jmp End + +Done: + xor eax, eax + +End: + emms + } +} + + +// returns the xor of all elements, cmpsize has to be mult of 8 +void memxor_mmx(void* dst, const void* src1, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov esi, src1 + mov ebx, ecx + mov edx, dst + + cmp ecx, 64 + jl Setup4 + + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + sub ecx, 64 + add esi, 64 + cmp ecx, 64 + jl End8 + +Cmp8: + pxor mm0, [esi] + pxor mm1, [esi+8] + pxor mm2, [esi+16] + pxor mm3, [esi+24] + pxor mm4, [esi+32] + pxor mm5, [esi+40] + pxor mm6, [esi+48] + pxor mm7, [esi+56] + + sub ecx, 64 + add esi, 64 + cmp ecx, 64 + jge Cmp8 + +End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp ecx, 32 + jl End4 + pxor mm0, [esi] + pxor mm1, [esi+8] + pxor mm2, [esi+16] + pxor mm3, [esi+24] + sub ecx, 32 + add esi, 32 + jmp End4 + +Setup4: + cmp ecx, 32 + jl Setup2 + + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + sub ecx, 32 + add esi, 32 + +End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp ecx, 16 + jl End2 + pxor mm0, [esi] + pxor mm1, [esi+8] + sub ecx, 16 + add esi, 16 + jmp End2 + +Setup2: + cmp ecx, 16 + jl Setup1 + + movq mm0, [esi] + movq mm1, [esi+8] + sub ecx, 16 + add esi, 16 + +End2: + pxor mm0, mm1 + + cmp ecx, 8 + jl End1 + pxor mm0, [esi] +End1: + movq [edx], mm0 + jmp End + +Setup1: + movq mm0, [esi] + movq [edx], mm0 +End: + emms + } +} + +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/pcl/pcl.c b/branches/pcsx2_0.9.1/pcl/pcl.c new file mode 100644 index 0000000..b871909 --- /dev/null +++ b/branches/pcsx2_0.9.1/pcl/pcl.c @@ -0,0 +1,490 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#include +#include +#include "pcl_config.h" +#include "pcl.h" + + +#if defined(CO_USE_UCONEXT) +#include + +typedef ucontext_t co_core_ctx_t; +#else +#include + +typedef jmp_buf co_core_ctx_t; +#endif + +#if defined(CO_USE_SIGCONTEXT) +#include +#endif + + +/* + * The following value must be power of two ( N^2 ). + */ +#define CO_STK_ALIGN 256 +#define CO_STK_COROSIZE ((sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1)) +#define CO_MIN_SIZE (4 * 1024) + + +typedef struct s_co_ctx { + co_core_ctx_t cc; +} co_ctx_t; + +typedef struct s_coroutine { + co_ctx_t ctx; + int alloc; + struct s_coroutine *caller; + struct s_coroutine *restarget; + void (*func)(void *); + void *data; +} coroutine; + + +static coroutine co_main; +static coroutine *co_curr = &co_main; +static coroutine *co_dhelper; + +#if defined(CO_USE_SIGCONTEXT) + +static volatile int ctx_called; +static co_ctx_t *ctx_creating; +static void *ctx_creating_func; +static sigset_t ctx_creating_sigs; +static co_ctx_t ctx_trampoline; +static co_ctx_t ctx_caller; + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + + +static int co_ctx_sdir(unsigned long psp) { + int nav = 0; + unsigned long csp = (unsigned long) &nav; + + return psp > csp ? -1: +1; +} + + +static int co_ctx_stackdir(void) { + int cav = 0; + + return co_ctx_sdir((unsigned long) &cav); +} + + +#if defined(CO_USE_UCONEXT) + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + + if (getcontext(&ctx->cc)) + return -1; + + ctx->cc.uc_link = NULL; + + ctx->cc.uc_stack.ss_sp = stkbase; + ctx->cc.uc_stack.ss_size = stksiz - sizeof(long); + ctx->cc.uc_stack.ss_flags = 0; + + makecontext(&ctx->cc, func, 1); + + return 0; +} + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (swapcontext(&octx->cc, &nctx->cc) < 0) { + fprintf(stderr, "[PCL] Context switch failed: curr=%p\n", + co_curr); + exit(1); + } +} + +#else /* #if defined(CO_USE_UCONEXT) */ + +#if defined(CO_USE_SIGCONTEXT) + +/* + * This code comes from the GNU Pth implementation and uses the + * sigstack/sigaltstack() trick. + * + * The ingenious fact is that this variant runs really on _all_ POSIX + * compliant systems without special platform kludges. But be _VERY_ + * carefully when you change something in the following code. The slightest + * change or reordering can lead to horribly broken code. Really every + * function call in the following case is intended to be how it is, doubt + * me... + * + * For more details we strongly recommend you to read the companion + * paper ``Portable Multithreading -- The Signal Stack Trick for + * User-Space Thread Creation'' from Ralf S. Engelschall. + */ + +static void co_ctx_bootstrap(void) { + co_ctx_t * volatile ctx_starting; + void (* volatile ctx_starting_func)(void); + + /* + * Switch to the final signal mask (inherited from parent) + */ + sigprocmask(SIG_SETMASK, &ctx_creating_sigs, NULL); + + /* + * Move startup details from static storage to local auto + * variables which is necessary because it has to survive in + * a local context until the thread is scheduled for real. + */ + ctx_starting = ctx_creating; + ctx_starting_func = (void (*)(void)) ctx_creating_func; + + /* + * Save current machine state (on new stack) and + * go back to caller until we're scheduled for real... + */ + if (!setjmp(ctx_starting->cc)) + longjmp(ctx_caller.cc, 1); + + /* + * The new thread is now running: GREAT! + * Now we just invoke its init function.... + */ + ctx_starting_func(); + + fprintf(stderr, "[PCL] Hmm, you really shouldn't reach this point: curr=%p\n", + co_curr); + exit(1); +} + + +static void co_ctx_trampoline(int sig) { + /* + * Save current machine state and _immediately_ go back with + * a standard "return" (to stop the signal handler situation) + * to let him remove the stack again. Notice that we really + * have do a normal "return" here, or the OS would consider + * the thread to be running on a signal stack which isn't + * good (for instance it wouldn't allow us to spawn a thread + * from within a thread, etc.) + */ + if (!setjmp(ctx_trampoline.cc)) { + ctx_called = 1; + return; + } + + /* + * Ok, the caller has longjmp'ed back to us, so now prepare + * us for the real machine state switching. We have to jump + * into another function here to get a new stack context for + * the auto variables (which have to be auto-variables + * because the start of the thread happens later). + */ + co_ctx_bootstrap(); +} + + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + struct sigaction sa; + struct sigaction osa; + sigset_t osigs; + sigset_t sigs; +#if defined(CO_HAS_SIGSTACK) + struct sigstack ss; + struct sigstack oss; +#elif defined(CO_HAS_SIGALTSTACK) + struct sigaltstack ss; + struct sigaltstack oss; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Preserve the SIGUSR1 signal state, block SIGUSR1, + * and establish our signal handler. The signal will + * later transfer control onto the signal stack. + */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGUSR1); + sigprocmask(SIG_BLOCK, &sigs, &osigs); + sa.sa_handler = co_ctx_trampoline; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK; + if (sigaction(SIGUSR1, &sa, &osa) != 0) + return -1; + + /* + * Set the new stack. + * + * For sigaltstack we're lucky [from sigaltstack(2) on + * FreeBSD 3.1]: ``Signal stacks are automatically adjusted + * for the direction of stack growth and alignment + * requirements'' + * + * For sigstack we have to decide ourself [from sigstack(2) + * on Solaris 2.6]: ``The direction of stack growth is not + * indicated in the historical definition of struct sigstack. + * The only way to portably establish a stack pointer is for + * the application to determine stack growth direction.'' + */ +#if defined(CO_HAS_SIGALTSTACK) + ss.ss_sp = stkbase; + ss.ss_size = stksiz - sizeof(long); + ss.ss_flags = 0; + if (sigaltstack(&ss, &oss) < 0) + return -1; +#elif defined(CO_HAS_SIGSTACK) + if (co_ctx_stackdir() < 0) + ss.ss_sp = (stkbase + stksiz - sizeof(long)); + else + ss.ss_sp = stkbase; + ss.ss_onstack = 0; + if (sigstack(&ss, &oss) < 0) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Now transfer control onto the signal stack and set it up. + * It will return immediately via "return" after the setjmp() + * was performed. Be careful here with race conditions. The + * signal can be delivered the first time sigsuspend() is + * called. + */ + ctx_called = 0; + kill(getpid(), SIGUSR1); + sigfillset(&sigs); + sigdelset(&sigs, SIGUSR1); + while (!ctx_called) + sigsuspend(&sigs); + + /* + * Inform the system that we are back off the signal stack by + * removing the alternative signal stack. Be careful here: It + * first has to be disabled, before it can be removed. + */ +#if defined(CO_HAS_SIGALTSTACK) + sigaltstack(NULL, &ss); + ss.ss_flags = SS_DISABLE; + if (sigaltstack(&ss, NULL) < 0) + return -1; + sigaltstack(NULL, &ss); + if (!(ss.ss_flags & SS_DISABLE)) + return -1; + if (!(oss.ss_flags & SS_DISABLE)) + sigaltstack(&oss, NULL); +#elif defined(CO_HAS_SIGSTACK) + if (sigstack(&oss, NULL)) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Restore the old SIGUSR1 signal handler and mask + */ + sigaction(SIGUSR1, &osa, NULL); + sigprocmask(SIG_SETMASK, &osigs, NULL); + + /* + * Set creation information. + */ + ctx_creating = ctx; + ctx_creating_func = func; + memcpy(&ctx_creating_sigs, &osigs, sizeof(sigset_t)); + + /* + * Now enter the trampoline again, but this time not as a signal + * handler. Instead we jump into it directly. + */ + if (!setjmp(ctx_caller.cc)) + longjmp(ctx_trampoline.cc, 1); + + return 0; +} + +#else /* #if defined(CO_USE_SIGCONTEXT) */ + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + char *stack; + + stack = stkbase + stksiz - sizeof(long); + + setjmp(ctx->cc); + +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(JB_PC) && defined(JB_SP) + ctx->cc[0].__jmpbuf[JB_PC] = (int) func; + ctx->cc[0].__jmpbuf[JB_SP] = (int) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(__mc68000__) + ctx->cc[0].__jmpbuf[0].__aregs[0] = (long) func; + ctx->cc[0].__jmpbuf[0].__sp = (int *) stack; +#elif defined(__GNU_LIBRARY__) && defined(__i386__) + ctx->cc[0].__jmpbuf[0].__pc = func; + ctx->cc[0].__jmpbuf[0].__sp = stack; +#elif defined(_WIN32) && defined(_MSC_VER) + ((_JUMP_BUFFER *) &ctx->cc)->Eip = (long) func; + ((_JUMP_BUFFER *) &ctx->cc)->Esp = (long) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && (defined(__powerpc64__) || defined(__powerpc__)) + ctx->cc[0].__jmpbuf[JB_LR] = (int) func; + ctx->cc[0].__jmpbuf[JB_GPR1] = (int) stack; +#else +#error "PCL: Unsupported setjmp/longjmp platform. Please report to " +#endif + + return 0; +} + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (!setjmp(octx->cc)) + longjmp(nctx->cc, 1); +} + +#endif /* #if defined(CO_USE_UCONEXT) */ + + +static void co_runner(void) { + coroutine *co = co_curr; + + co->restarget = co->caller; + co->func(co->data); + co_exit(); +} + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size) { + int alloc = 0, r = CO_STK_COROSIZE; + coroutine *co; + + if ((size &= ~(sizeof(long) - 1)) < CO_MIN_SIZE) + return NULL; + if (!stack) { + size = (size + sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1); + stack = malloc(size); + if (!stack) + return NULL; + alloc = size; + } + co = stack; + stack = (char *) stack + CO_STK_COROSIZE; + co->alloc = alloc; + co->func = func; + co->data = data; + if (co_set_context(&co->ctx, co_runner, stack, size - CO_STK_COROSIZE) < 0) { + if (alloc) + free(co); + return NULL; + } + + return (coroutine_t) co; +} + + +void co_delete(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + + if (co == co_curr) { + fprintf(stderr, "[PCL] Cannot delete itself: curr=%p\n", + co_curr); + exit(1); + } + if (co->alloc) + free(co); +} + + +void co_call(coroutine_t coro) { + coroutine *co = (coroutine *) coro, *oldco = co_curr; + + co->caller = co_curr; + co_curr = co; + + co_switch_context(&oldco->ctx, &co->ctx); +} + + +void co_resume(void) { + + co_call(co_curr->restarget); + co_curr->restarget = co_curr->caller; +} + + +static void co_del_helper(void *data) { + coroutine *cdh; + + for (;;) { + cdh = co_dhelper; + co_dhelper = NULL; + co_delete(co_curr->caller); + co_call((coroutine_t) cdh); + if (!co_dhelper) { + fprintf(stderr, "[PCL] Resume to delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + } +} + + +void co_exit_to(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + static coroutine *dchelper = NULL; + static char stk[CO_MIN_SIZE]; + + if (!dchelper && + !(dchelper = co_create(co_del_helper, NULL, stk, sizeof(stk)))) { + fprintf(stderr, "[PCL] Unable to create delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + + co_dhelper = co; + + co_call((coroutine_t) dchelper); + + fprintf(stderr, "[PCL] Stale coroutine called: curr=%p\n", + co_curr); + exit(1); +} + + +void co_exit(void) { + + co_exit_to((coroutine_t) co_curr->restarget); +} + + +coroutine_t co_current(void) { + + return (coroutine_t) co_curr; +} + diff --git a/branches/pcsx2_0.9.1/pcl/pcl.h b/branches/pcsx2_0.9.1/pcl/pcl.h new file mode 100644 index 0000000..122112e --- /dev/null +++ b/branches/pcsx2_0.9.1/pcl/pcl.h @@ -0,0 +1,49 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_H) +#define PCL_H + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef void *coroutine_t; + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size); +void co_delete(coroutine_t coro); +void co_call(coroutine_t coro); +void co_resume(void); +void co_exit_to(coroutine_t coro); +void co_exit(void); +coroutine_t co_current(void); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/branches/pcsx2_0.9.1/pcl/pcl_config.h b/branches/pcsx2_0.9.1/pcl/pcl_config.h new file mode 100644 index 0000000..9c37c64 --- /dev/null +++ b/branches/pcsx2_0.9.1/pcl/pcl_config.h @@ -0,0 +1,60 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_CONFIG_H) +#define PCL_CONFIG_H + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif /* #if defined(HAVE_CONFIG_H) */ + + +#if defined(HAVE_GETCONTEXT) && defined(HAVE_MAKECONTEXT) && defined(HAVE_SWAPCONTEXT) + +/* + * Use this if the system has a working getcontext/makecontext/swapcontext + * implementation. + */ +#define CO_USE_UCONEXT + +#elif defined(HAVE_SIGACTION) + +/* + * Use this to have the generic signal implementation ( not working on + * Windows ). Suggested on generic Unix implementations or on Linux with + * CPU different from x86 family. + */ +#define CO_USE_SIGCONTEXT + +/* + * Use this in conjuction with CO_USE_SIGCONTEXT to use the sigaltstack + * environment ( suggested when CO_USE_SIGCONTEXT is defined ). + */ +#if defined(HAVE_SIGALTSTACK) +#define CO_HAS_SIGALTSTACK +#endif + +#endif + + +#endif + diff --git a/branches/pcsx2_0.9.1/pcsxAbout.bmp b/branches/pcsx2_0.9.1/pcsxAbout.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da33bb08f4a3c365d835b0972a7dfbc43f8b01a2 GIT binary patch literal 251192 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
#6CXrR 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%0A&bFGJ^?ZxKwaSay%~z|BlTbA{G+_QCqA8wMysG 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 yT^R{P!VvN=U0F-&j +#include + +#include "resource.h" +#include "AboutDlg.h" +#include "Common.h" + +#ifdef __MINGW32__ +#define IDC_STATIC (-1) +#endif + +#ifdef __MSCW32__ +#define IDC_STATIC (-1) +#endif + +HWND hW; +HBITMAP hBMP, hSilverBMP; + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); + + hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, + 230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL); + SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP); + + SetWindowText(hDlg, _("About")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_TEXT), _("PCSX2 EMU\n")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_AUTHORS), _(LabelAuthors)); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_GREETS), _(LabelGreets)); + return TRUE; + + case WM_COMMAND: + switch(wParam) { + case IDOK: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/branches/pcsx2_0.9.1/windows/AboutDlg.h b/branches/pcsx2_0.9.1/windows/AboutDlg.h new file mode 100644 index 0000000..1a209be --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/AboutDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_ABOUTDLG_H_ +#define _PCSX2_ABOUTDLG_H_ + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif diff --git a/branches/pcsx2_0.9.1/windows/Cdrom02.ico b/branches/pcsx2_0.9.1/windows/Cdrom02.ico new file mode 100644 index 0000000000000000000000000000000000000000..07588baeaa79ee6acf726e73fb70937a1dadb53e GIT binary patch literal 12862 zcmeHO>(f_d75()kE6fWRf~lFNF^(DOq=`*Kw`shE;~15usFWItiKUlh5G4rAsI13nq&$ zn@r|UCX+?@0X6v}e#pl+Z_Z@GpZM&fNB+m_Vf!fR*u$m*15oqCk91@z8&FR0H|bl| zGOhS`>uYo?WsSjTl)mm*9sL9ASabl@Ael04Q_M%>@V@}*mLN@zp2+#=?`^t{4Us7; z+lSgi@Y9E4*rBgaD%@O2+>rI_S{1<>I|3{31P^gM5+kw5H4z{*$^&HymP&VnVe$ol z30pEQDCf#hy~}MlD35M&SjK$rK~MXj%>+0i0MD9f$Tc=2!L$a93If+qDY1H*pfTXMX2}`~d1=YTogYDW=>WM?bI)WwDBp?>0|YOe@Y9e)8c1*41j8dBA2? zlS#m>^PSAMASpxd>+3_{_A318nYIGy<5#?OMh;4qFY*-^d~mS7AHiYsj!<={!JNuMNXg%|ax_u3h-1fyX5lJ`S$}?Am^yg?B52ct&9imH+&&l&{ zJM-1295POulfRL(t)eH+B$fbsmdxeHpX{wCBrC5305)S z58P=7Rd?6{uY>4d?qHRz<1ylUj4B=@MMx&R(+=Ej`%x zJQ09k;p5yXS;#Ya9Bn;{CnDAzM z`)2kmjY$&xjG9qCrt;SjAR}c|fVXa9z3n{##%X3Se|@f#Jj_+{04l9g0MM+OlSWye zzj>p*xy;_Wkwpx!tN@K;XdfV@hdT!9(~WHw zAd63!)6=WdD?ln8C|D7@ZR)k!dyTz*jqSbG0En;UNJgWtG!EuZB^>gQCT^Hpt=J`V zL8p&bq}Q#&$d))t!L$YW+D}-odl#PW+79NQ{WfiDka+gn=@^6hSAT4%SG>RaBSRG| z9!#tT^MBGLUsnbMi);XeMDicl9@Gz6uS8FP6|oCG>8OMLy=(~MNfb%_uirP;Qq~?- zjP(lJQ9fkY6A2NoLugvWxJQy?yKx2^d)5kiIIh^YRM?^{dG^GkV>dj>MwrBUcAzFU&%gujq(e0k&x4) zmL6$e__nE@50K2q%Qv>oh}Q?d7p`DDWy^#KxVqeSUC#deWvmW6zsnhQZ41U$VqD1q zW8yF*6MQ~|Cu$Qu?GA(axm5M^fs z^J&AfT|5|{k#xd%`IbnJ{oFV0xl6qgXso+d=qjv2yfXkyc21v&$*bzHJgO@<8T z7pv!#;n_=U$0hdcH@pJuzzD2SpfBUetOY?pKkQuOF(hJi%6Ok?pEB{OKOPv&pKix9-@eFD+q|}aJwPzx(V-dT+oniE!4&(Mi|m;TjlC{0 z6~FDGQR0_WcpdT7ducDUr!TOlzZP9U3~;|j`30H`z0q?%b-q3IRo0W|v&tw?b*x7D zn5V9Y%FNDh{fa$_I?uMAR{$^=junG(lrOW@d4S6ZaIS4RxAZON*jAOubGYKx!6^9| zDFS3pG7;>FvyJuTD2->^7BJ$0eHgf$7clr(6>YoME7Jv4Z8fUgXNRkIl2XHqEn5bIAZ?7vL(y1Lml1ldWZ%SEk1~wr-9e;ubjidgn0`fb;@R zzKFGQ4PTcGUFWWEPh=Q^V&05$2*WN|-YVD}Tl)ppI&@(OG&&Em9*Oe=pxMTXo?3aA zzYa^!=lm_k%aaIGzpIcXVJP*)+Rs~4k4`ZVh|E=j!P{nA-vT#VITRAvre3elbDJiQ ze$G&9y$cUADOh_F^{fC~1)jdm!*X?^hf+3p*pL|ibP@{znoj<+Wh)Iv$;ybUis7$N n`PAcpb11c{#lWfW9typ-^%X;YTBH31;@<&$`v3pWzreo$+!n*^ literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.1/windows/ConfigDlg.c b/branches/pcsx2_0.9.1/windows/ConfigDlg.c new file mode 100644 index 0000000..777b109 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/ConfigDlg.c @@ -0,0 +1,499 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include //2002-09-22 (Florin) +#include "common.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +#define ComboAddPlugin(hw, str) { \ + sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \ + lp = (char *)malloc(strlen(FindData.cFileName)+8); \ + sprintf(lp, "%s", FindData.cFileName); \ + i = ComboBox_AddString(hw, tmpStr); \ + ComboBox_SetItemData(hw, i, lp); \ + if (stricmp(str, lp)==0) \ + ComboBox_SetCurSel(hw, i); \ +} + +BOOL OnConfigureDialog(HWND hW) { + WIN32_FIND_DATA FindData; + HANDLE Find; + HANDLE Lib; + _PS2EgetLibType PS2E_GetLibType; + _PS2EgetLibName PS2E_GetLibName; + _PS2EgetLibVersion2 PS2E_GetLibVersion2; + HWND hWC_GS=GetDlgItem(hW,IDC_LISTGS); + HWND hWC_PAD1=GetDlgItem(hW,IDC_LISTPAD1); + HWND hWC_PAD2=GetDlgItem(hW,IDC_LISTPAD2); + HWND hWC_SPU2=GetDlgItem(hW,IDC_LISTSPU2); + HWND hWC_CDVD=GetDlgItem(hW,IDC_LISTCDVD); + HWND hWC_DEV9=GetDlgItem(hW,IDC_LISTDEV9); + HWND hWC_USB=GetDlgItem(hW,IDC_LISTUSB); + HWND hWC_FW=GetDlgItem(hW,IDC_LISTFW); + HWND hWC_BIOS=GetDlgItem(hW,IDC_LISTBIOS); + char tmpStr[256]; + char *lp; + int i; + + strcpy(tmpStr, Config.PluginsDir); + strcat(tmpStr, "*.dll"); + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + sprintf(tmpStr,"%s%s", Config.PluginsDir, FindData.cFileName); + Lib = LoadLibrary(tmpStr); + if (Lib == NULL) { SysPrintf("%s: %d\n", tmpStr, GetLastError()); continue; } + + PS2E_GetLibType = (_PS2EgetLibType) GetProcAddress((HMODULE)Lib,"PS2EgetLibType"); + PS2E_GetLibName = (_PS2EgetLibName) GetProcAddress((HMODULE)Lib,"PS2EgetLibName"); + PS2E_GetLibVersion2 = (_PS2EgetLibVersion2) GetProcAddress((HMODULE)Lib,"PS2EgetLibVersion2"); + + if (PS2E_GetLibType != NULL && PS2E_GetLibName != NULL && PS2E_GetLibVersion2 != NULL) { + u32 version; + long type; + + type = PS2E_GetLibType(); + if (type & PS2E_LT_GS) { + version = PS2E_GetLibVersion2(PS2E_LT_GS); + if ( ((version >> 16)&0xff) == PS2E_GS_VERSION) { + ComboAddPlugin(hWC_GS, Config.GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, 0xff&(version >> 16), PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)GetProcAddress((HMODULE)Lib, "PADquery"); + version = PS2E_GetLibVersion2(PS2E_LT_PAD); + if (((version >> 16)&0xff) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(hWC_PAD1, Config.PAD1); + if (query() & 0x2) + ComboAddPlugin(hWC_PAD2, Config.PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2E_GetLibVersion2(PS2E_LT_SPU2); + if ( ((version >> 16)&0xff) == PS2E_SPU2_VERSION) { + ComboAddPlugin(hWC_SPU2, Config.SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2E_GetLibVersion2(PS2E_LT_CDVD); + if (((version >> 16)&0xff) == PS2E_CDVD_VERSION) { + ComboAddPlugin(hWC_CDVD, Config.CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2E_GetLibVersion2(PS2E_LT_DEV9); + if (((version >> 16)&0xff) == PS2E_DEV9_VERSION) { + ComboAddPlugin(hWC_DEV9, Config.DEV9); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2E_GetLibVersion2(PS2E_LT_USB); + if (((version >> 16)&0xff) == PS2E_USB_VERSION) { + ComboAddPlugin(hWC_USB, Config.USB); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2E_GetLibVersion2(PS2E_LT_FW); + if (((version >> 16)&0xff) == PS2E_FW_VERSION) { + ComboAddPlugin(hWC_FW, Config.FW); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_FW_VERSION); + } + } + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + +// BIOS + + /*lp=(char *)malloc(strlen("HLE") + 1); + sprintf(lp, "HLE"); + i=ComboBox_AddString(hWC_BIOS, _("Internal HLE Bios")); + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, lp)==0) + ComboBox_SetCurSel(hWC_BIOS, i);*/ + + strcpy(tmpStr, Config.BiosDir); + strcat(tmpStr, "*"); + Find=FindFirstFile(tmpStr, &FindData); + + do { + char description[50]; //2002-09-22 (Florin) + if (Find==INVALID_HANDLE_VALUE) break; + if (!strcmp(FindData.cFileName, ".")) continue; + if (!strcmp(FindData.cFileName, "..")) continue; +// if (FindData.nFileSizeLow < 1024 * 512) continue; + if (FindData.nFileSizeLow > 1024 * 4096) continue; //2002-09-22 (Florin) + if (!IsBIOS(FindData.cFileName, description)) continue;//2002-09-22 (Florin) + lp = (char *)malloc(strlen(FindData.cFileName)+8); + sprintf(lp, "%s", (char *)FindData.cFileName); + i = ComboBox_AddString(hWC_BIOS, description); //2002-09-22 (Florin) modified + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, FindData.cFileName)==0) + ComboBox_SetCurSel(hWC_BIOS, i); + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + + if (ComboBox_GetCurSel(hWC_GS) == -1) + ComboBox_SetCurSel(hWC_GS, 0); + if (ComboBox_GetCurSel(hWC_PAD1) == -1) + ComboBox_SetCurSel(hWC_PAD1, 0); + if (ComboBox_GetCurSel(hWC_PAD2) == -1) + ComboBox_SetCurSel(hWC_PAD2, 0); + if (ComboBox_GetCurSel(hWC_SPU2) == -1) + ComboBox_SetCurSel(hWC_SPU2, 0); + if (ComboBox_GetCurSel(hWC_CDVD) == -1) + ComboBox_SetCurSel(hWC_CDVD, 0); + if (ComboBox_GetCurSel(hWC_DEV9) == -1) + ComboBox_SetCurSel(hWC_DEV9, 0); + if (ComboBox_GetCurSel(hWC_USB) == -1) + ComboBox_SetCurSel(hWC_USB, 0); + if (ComboBox_GetCurSel(hWC_FW) == -1) + ComboBox_SetCurSel(hWC_FW, 0); + if (ComboBox_GetCurSel(hWC_BIOS) == -1) + ComboBox_SetCurSel(hWC_BIOS, 0); + + return TRUE; +} + +#define CleanCombo(item) \ + hWC = GetDlgItem(hW, item); \ + iCnt = ComboBox_GetCount(hWC); \ + for (i=0; i +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char cpuspeedc[20]; + char features[256]; + u32 newopts; + + switch(uMsg) { + case WM_INITDIALOG: + SetWindowText(hW, _("Cpu Config")); + SetDlgItemText(hW, IDC_VENDORINPUT,cpuinfo.x86ID ); + SetDlgItemText(hW, IDC_FAMILYINPUT, cpuinfo.x86Fam); + sprintf(cpuspeedc,"%d MHZ",cpuinfo.cpuspeed); + SetDlgItemText(hW, IDC_CPUSPEEDINPUT, cpuspeedc); + //features[0]=':'; + //strcat(features,""); + strcpy(features,""); + if(cpucaps.hasMultimediaExtensions) strcat(features,"MMX"); + if(cpucaps.hasStreamingSIMDExtensions) strcat(features,",SSE"); + if(cpucaps.hasStreamingSIMD2Extensions) strcat(features,",SSE2"); + if(cpucaps.has3DNOWInstructionExtensions) strcat(features,",3DNOW"); + if(cpucaps.has3DNOWInstructionExtensionsExt)strcat(features,",3DNOW+"); + if(cpucaps.hasAMD64BitArchitecture) strcat(features,",x86-64"); + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + if(!cpucaps.hasStreamingSIMDExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILERVU),FALSE);//disable checkbox if no SSE2 found + Config.Options &= (PCSX2_VU0REC|PCSX2_VU1REC);//disable the config just in case + } + if(!cpucaps.hasMultimediaExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILER),FALSE); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC);//return to interpreter mode + + } + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + + CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC); + CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC); + CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC); + + CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS); + CheckDlgButton(hW, IDC_CPU_MULTI, !!CHECK_DUALCORE); + CheckDlgButton(hW, IDC_CPU_FRAMELIMIT, !!CHECK_FRAMELIMIT); + CheckDlgButton(hW, IDC_CPU_FORCEABS, !!CHECK_FORCEABS); + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + + case IDOK: + Cpu->Shutdown(); + vu0Shutdown(); + vu1Shutdown(); + + newopts = 0; + + if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC; + if( SendDlgItemMessage(hW,IDC_CPU_VU0REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU0REC; + if( SendDlgItemMessage(hW,IDC_CPU_VU1REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU1REC; + + if( SendDlgItemMessage(hW,IDC_CPU_GSMULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_GSMULTITHREAD; + if( SendDlgItemMessage(hW,IDC_CPU_MULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_DUALCORE; + if( SendDlgItemMessage(hW,IDC_CPU_FRAMELIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT; + if( SendDlgItemMessage(hW,IDC_CPU_FORCEABS,BM_GETCHECK,0,0) ) newopts |= PCSX2_FORCEABS; + + if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) { + Config.Options = newopts; + SaveConfig(); + MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK); + exit(0); + } + + if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC; + + Config.Options = newopts; + + UpdateVSyncRate(); + SaveConfig(); + + cpuRestartCPU(); + EndDialog(hW, TRUE); + return TRUE; + } + } + return FALSE; +} diff --git a/branches/pcsx2_0.9.1/windows/DebugMemory.c b/branches/pcsx2_0.9.1/windows/DebugMemory.c new file mode 100644 index 0000000..cf79747 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/DebugMemory.c @@ -0,0 +1,239 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "resource.h" + + +unsigned long memory_addr; +BOOL mem_inupdate = FALSE; +HWND memoryhWnd,hWnd_memscroll,hWnd_memorydump; +unsigned long memory_patch; +unsigned long data_patch; + +///MEMORY DUMP +unsigned char Debug_Read8(unsigned long addr)//just for anycase.. +{ +#ifdef __MSCW32__ + __try + { +#endif + u8 val8; + memRead8(addr, &val8); + return val8; +#ifdef __MSCW32__ + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return 0; + } +#endif +} + + +void RefreshMemory(void) +{ + int x, y; + unsigned long addr; + unsigned char b; + + char buf[128], text[32], temp[8]; + + + + addr = memory_addr; + + if (!mem_inupdate) + { + sprintf(buf, "%08X", addr); + SetDlgItemText(memoryhWnd, IDC_MEMORY_ADDR, buf); + } + + SendMessage(hWnd_memorydump, LB_RESETCONTENT, 0, 0); + + for (y = 0; y < 21; y++) + { + memset(text, 0, 32); + sprintf(buf, "%08X: ", addr); + + for (x = 0; x < 16; x++) + { + b = Debug_Read8(addr++); + + sprintf(temp, "%02X ", b); + strcat(buf, temp); + + if (b < 32 || b > 127) b = 32; + sprintf(temp, "%c", b); + strcat(text, temp); + + + if (x == 7) strcat(buf, " "); + } + + strcat(buf, " "); + strcat(buf, text); + + SendMessage(hWnd_memorydump, LB_ADDSTRING, 0, (LPARAM)buf); + } +} + + +BOOL APIENTRY DumpMemProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], buf[128]; + u32 start_pc, end_pc, addr; + u8 data; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMPMEM_START, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_END, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, "dump.raw"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMPMEM_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, fname, 128); + fp = fopen(fname, "wb"); + if (fp == NULL) + { + SysMessage("Can't open file '%s' for writing!\n", fname); + } + else + { + for (addr = start_pc; addr < end_pc; addr ++) { + memRead8( addr, &data ); + fwrite(&data, 1, 1, fp); + } + + fclose(fp); + } + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + + + +BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + char buf[16]; + switch (message) + { + case WM_INITDIALOG: + memory_addr = cpuRegs.pc; + sprintf(buf, "%08X", memory_addr); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + memory_patch= 0; + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf); + data_patch=0; + sprintf(buf, "%08X", data_patch); + SetDlgItemText(hDlg, IDC_DATA_PATCH, buf); + hWnd_memorydump = GetDlgItem(hDlg, IDC_MEMORY_DUMP); + hWnd_memscroll = GetDlgItem(hDlg, IDC_MEM_SCROLL); + + + + SendMessage(hWnd_memorydump, LB_INITSTORAGE, 11, 1280); + SendMessage(hWnd_memscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_memscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + RefreshMemory(); + return TRUE; + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + case SB_LINEDOWN: memory_addr += 0x00000010; RefreshMemory(); break; + case SB_LINEUP: memory_addr -= 0x00000010; RefreshMemory(); break; + case SB_PAGEDOWN: memory_addr += 0x00000150; RefreshMemory(); break; + case SB_PAGEUP: memory_addr -= 0x00000150; RefreshMemory(); break; + } + + return TRUE; + + case WM_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + + + case WM_COMMAND: + if (HIWORD(wParam) == EN_UPDATE) + { + mem_inupdate = TRUE; + GetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf, 9); + buf[8] = 0; + + sscanf(buf, "%x", &memory_addr); + RefreshMemory(); + mem_inupdate = FALSE; + return TRUE; + } + + switch (LOWORD(wParam)) { + case IDC_PATCH: + GetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf, 9);//32bit address + buf[8] = 0; + sscanf(buf, "%x", &memory_patch); + GetDlgItemText(hDlg, IDC_DATA_PATCH, buf, 9);//32 bit data only for far + buf[8] = 0; + sscanf(buf, "%x", &data_patch); + memWrite32( memory_patch, data_patch ); + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + RefreshMemory(); + return TRUE; + + case IDC_DUMPRAW: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMPMEM), hDlg, (DLGPROC)DumpMemProc); + + return TRUE; + + case IDC_MEMORY_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + + return FALSE; +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/windows/Debugger.c b/branches/pcsx2_0.9.1/windows/Debugger.c new file mode 100644 index 0000000..3164c9d --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/Debugger.c @@ -0,0 +1,562 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "Common.h" +#include "win32.h" +#include "PsxMem.h" +#include "R3000A.h" + +extern void (*IOP_DEBUG_BSC[64])(char *buf); +extern void UpdateR5900op(); +void RefreshIOPDebugger(void); +extern int ISR3000A;//for disasm +HWND hWnd_debugdisasm, hWnd_debugscroll,hWnd_IOP_debugdisasm, hWnd_IOP_debugscroll; +unsigned long DebuggerPC = 0; +HWND hRegDlg;//for debug registers.. +HWND debughWnd; +unsigned long DebuggerIOPPC=0; +HWND hIOPDlg;//IOP debugger + + +void RefreshDebugAll()//refresh disasm and register window +{ + RefreshDebugger(); + RefreshIOPDebugger(); + UpdateRegs(); + + +} + +void MakeDebugOpcode(void) +{ + memRead32( opcode_addr, &cpuRegs.code ); +} + +void MakeIOPDebugOpcode(void) +{ + psxRegs.code = PSXMu32( opcode_addr); +} + +BOOL HasBreakpoint() +{ + int t; + + for (t = 0; t < NUM_BREAKPOINTS; t++) + { + switch (bkpt_regv[t].type) { + case 1: // exec + if (cpuRegs.pc == bkpt_regv[t].value) return TRUE; + break; + + case 2: // count + if ((cpuRegs.cycle - 10) <= bkpt_regv[t].value && + (cpuRegs.cycle + 10) >= bkpt_regv[t].value) return TRUE; + break; + } + } + return FALSE; + +} +BOOL APIENTRY JumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + unsigned long temp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_JUMP_PC, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_JUMP_PC, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &temp); + + temp &= 0xFFFFFFFC; + DebuggerPC = temp - 0x00000038; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +extern void EEDumpRegs(FILE * fp); +extern void IOPDumpRegs(FILE * fp); +BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], tmp[128], buf[128]; + unsigned long start_pc, end_pc, temp; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_START, buf); + SetDlgItemText(hDlg, IDC_DUMP_END, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt"); + + sprintf(buf, "%08X", psxRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMP_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAME, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"EE DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + + + opcode_addr=temp; + MakeDebugOpcode(); + OpcodePrintTable[(cpuRegs.code) >> 26](tmp); + if (HasBreakpoint(temp)) + { + sprintf(buf, "*%08X %08X: %s", temp, cpuRegs.code, tmp); + } + else + { + sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp); + } + + fprintf(fp, "%s\n", buf); + } + + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"EE REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + EEDumpRegs(fp); + fclose(fp); + } + + + + GetDlgItemText(hDlg, IDC_DUMP_STARTIOP, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_ENDIOP, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"IOP DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + opcode_addr=temp; + MakeIOPDebugOpcode(); + IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp); + sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp); + fprintf(fp, "%s\n", buf); + } + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"IOP REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + IOPDumpRegs(fp); + fclose(fp); + } + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpexecProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[0].value); + SetDlgItemText(hDlg, IDC_EXECBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_EXECBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[0].value); + bkpt_regv[0].type = 1; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpcntProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[1].value); + SetDlgItemText(hDlg, IDC_CNTBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_CNTBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[1].value); + bkpt_regv[1].type = 2; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} +HINSTANCE m2_hInst; +HWND m2_hWnd; +HWND hIopDlg; + +LRESULT CALLBACK IOP_DISASM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + hWnd_IOP_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM_IOP); + hWnd_IOP_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL_IOP); + + SendMessage(hWnd_IOP_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_IOP_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_IOP_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + RefreshIOPDebugger(); + return (TRUE); + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerIOPPC += 0x00000004; RefreshIOPDebugger(); break; + case SB_LINEUP: DebuggerIOPPC -= 0x00000004; RefreshIOPDebugger(); break; + case SB_PAGEDOWN: DebuggerIOPPC += 0x00000029; RefreshIOPDebugger(); break; + case SB_PAGEUP: DebuggerIOPPC -= 0x00000029; RefreshIOPDebugger(); break; + } + return TRUE; + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +int CreatePropertySheet2(HWND hwndOwner) +{ + PROPSHEETPAGE psp[1]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m2_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_IOP_DEBUG); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)IOP_DISASM; + psp[0].pszTitle = "Iop Disasm"; + psp[0].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m2_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "IOP Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); +} + +BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + FARPROC jmpproc, dumpproc; + FARPROC bpexecproc, bpcntproc; + u32 oldpc = 0; + + switch (message) + { + case WM_INITDIALOG: + // if (OpenPlugins() == -1) return TRUE;//moved to WinMain.c + + ShowCursor(TRUE); + + SetWindowText(hDlg, "R5900 Debugger"); + debughWnd=hDlg; + DebuggerPC = 0; + // Clear all breakpoints. + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + + hWnd_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM); + hWnd_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL); + + SendMessage(hWnd_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + hRegDlg = (HWND)CreatePropertySheet(hDlg); + hIopDlg = (HWND)CreatePropertySheet2(hDlg); + UpdateRegs(); + SetWindowPos(hRegDlg, NULL, 425, 0, 600, 515,0 ); + SetWindowPos(hIopDlg, NULL, 0 ,515,600,230,0); + RefreshDebugger(); + + + + RefreshIOPDebugger(); + return TRUE; + + case WM_VSCROLL: + + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerPC += 0x00000004; RefreshDebugAll(); break; + case SB_LINEUP: DebuggerPC -= 0x00000004; RefreshDebugAll(); break; + case SB_PAGEDOWN: DebuggerPC += 0x00000074; RefreshDebugAll(); break; + case SB_PAGEUP: DebuggerPC -= 0x00000074; RefreshDebugAll(); break; + } + + + + + return TRUE; + + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_DEBUG_STEP: + oldpc = psxRegs.pc; + Cpu->Step(); + while(oldpc == psxRegs.pc) Cpu->Step(); + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_SKIP: + cpuRegs.pc+= 4; + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_GO: + for (;;) { + if (HasBreakpoint()) { + Cpu->Step(); + break; + } + Cpu->Step(); + } + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_LOG: +#ifdef PCSX2_DEVBUILD + Log = 1 - Log; +#endif + return TRUE; + + case IDC_DEBUG_RESETTOPC: + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_JUMP: + jmpproc = MakeProcInstance((FARPROC)JumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_JUMP), debughWnd, (DLGPROC)jmpproc); + FreeProcInstance(jmpproc); + + RefreshDebugAll(); + return TRUE; + case IDC_CPUOP: + + UpdateR5900op(); + return TRUE; + + case IDC_DEBUG_BP_EXEC: + bpexecproc = MakeProcInstance((FARPROC)BpexecProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPEXEC), debughWnd, (DLGPROC)bpexecproc); + FreeProcInstance(bpexecproc); + + return TRUE; + + case IDC_DEBUG_BP_COUNT: + bpcntproc = MakeProcInstance((FARPROC)BpcntProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPCNT), debughWnd, (DLGPROC)bpcntproc); + FreeProcInstance(bpcntproc); + return TRUE; + + case IDC_DEBUG_BP_CLEAR: + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + return TRUE; + + case IDC_DEBUG_DUMP: + dumpproc = MakeProcInstance((FARPROC)DumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMP), debughWnd, (DLGPROC)dumpproc); + FreeProcInstance(dumpproc); + return TRUE; + + case IDC_DEBUG_MEMORY: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), debughWnd, (DLGPROC)MemoryProc); + return TRUE; + + case IDC_DEBUG_CLOSE: + + EndDialog(hRegDlg ,TRUE); + EndDialog(hDlg,TRUE); + EndDialog(hIopDlg,TRUE); + + ClosePlugins(); + + return TRUE; + } + break; + } + + return FALSE; +} + +void RefreshDebugger(void) +{ + unsigned long t; + int cnt; + + + + if (DebuggerPC == 0) + DebuggerPC = cpuRegs.pc; //- 0x00000038; + + SendMessage(hWnd_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerPC, cnt = 0; t < (DebuggerPC + 0x00000074); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 *mem = (u32*)PSM(t); + char *str; + if (mem == NULL) { + char nullAddr[256]; + sprintf(nullAddr, "%8.8lx 00000000: NULL MEMORY", t); str = nullAddr; + } else { + str = disR5900Fasm(*mem, t); + } + SendMessage(hWnd_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} + +void RefreshIOPDebugger(void) +{ + unsigned long t; + int cnt; + + DebuggerIOPPC = psxRegs.pc; //- 0x00000038; + + SendMessage(hWnd_IOP_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerIOPPC, cnt = 0; t < (DebuggerIOPPC + 0x00000029); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 mem = PSXMu32(t); + char *str = disR3000Fasm(mem, t); + SendMessage(hWnd_IOP_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} diff --git a/branches/pcsx2_0.9.1/windows/Debugger.h b/branches/pcsx2_0.9.1/windows/Debugger.h new file mode 100644 index 0000000..d4e3d20 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/Debugger.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define NUM_BREAKPOINTS 8 + +extern void (*OpcodePrintTable[64])(char *buf); + +extern BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + + +extern BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern void RefreshDebugger(void); + +unsigned long opcode_addr; + +typedef struct +{ + int type; + unsigned long value; +} breakpoints; + +breakpoints bkpt_regv[NUM_BREAKPOINTS]; + + + +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +void UpdateRegs(void); +int CreatePropertySheet(HWND hwndOwner); diff --git a/branches/pcsx2_0.9.1/windows/Debugreg.c b/branches/pcsx2_0.9.1/windows/Debugreg.c new file mode 100644 index 0000000..3edc325 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/Debugreg.c @@ -0,0 +1,1483 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 +#include +#include + +#include "resource.h" +#include "Debugger.h" +#include "Debug.h" +#include "R5900.h" +#include "R3000a.h" +#include "VUmicro.h" + +HINSTANCE m_hInst; +HWND m_hWnd; +char text1[256]; + + +/*R3000a registers handle */ +static HWND IOPGPR0Handle=NULL; +static HWND IOPGPR1Handle=NULL; +static HWND IOPGPR2Handle=NULL; +static HWND IOPGPR3Handle=NULL; +static HWND IOPGPR4Handle=NULL; +static HWND IOPGPR5Handle=NULL; +static HWND IOPGPR6Handle=NULL; +static HWND IOPGPR7Handle=NULL; +static HWND IOPGPR8Handle=NULL; +static HWND IOPGPR9Handle=NULL; +static HWND IOPGPR10Handle=NULL; +static HWND IOPGPR11Handle=NULL; +static HWND IOPGPR12Handle=NULL; +static HWND IOPGPR13Handle=NULL; +static HWND IOPGPR14Handle=NULL; +static HWND IOPGPR15Handle=NULL; +static HWND IOPGPR16Handle=NULL; +static HWND IOPGPR17Handle=NULL; +static HWND IOPGPR18Handle=NULL; +static HWND IOPGPR19Handle=NULL; +static HWND IOPGPR20Handle=NULL; +static HWND IOPGPR21Handle=NULL; +static HWND IOPGPR22Handle=NULL; +static HWND IOPGPR23Handle=NULL; +static HWND IOPGPR24Handle=NULL; +static HWND IOPGPR25Handle=NULL; +static HWND IOPGPR26Handle=NULL; +static HWND IOPGPR27Handle=NULL; +static HWND IOPGPR28Handle=NULL; +static HWND IOPGPR29Handle=NULL; +static HWND IOPGPR30Handle=NULL; +static HWND IOPGPR31Handle=NULL; +static HWND IOPGPRPCHandle=NULL; +static HWND IOPGPRHIHandle=NULL; +static HWND IOPGPRLOHandle=NULL; + +/*R5900 registers handle */ +static HWND GPR0Handle=NULL; +static HWND GPR1Handle=NULL; +static HWND GPR2Handle=NULL; +static HWND GPR3Handle=NULL; +static HWND GPR4Handle=NULL; +static HWND GPR5Handle=NULL; +static HWND GPR6Handle=NULL; +static HWND GPR7Handle=NULL; +static HWND GPR8Handle=NULL; +static HWND GPR9Handle=NULL; +static HWND GPR10Handle=NULL; +static HWND GPR11Handle=NULL; +static HWND GPR12Handle=NULL; +static HWND GPR13Handle=NULL; +static HWND GPR14Handle=NULL; +static HWND GPR15Handle=NULL; +static HWND GPR16Handle=NULL; +static HWND GPR17Handle=NULL; +static HWND GPR18Handle=NULL; +static HWND GPR19Handle=NULL; +static HWND GPR20Handle=NULL; +static HWND GPR21Handle=NULL; +static HWND GPR22Handle=NULL; +static HWND GPR23Handle=NULL; +static HWND GPR24Handle=NULL; +static HWND GPR25Handle=NULL; +static HWND GPR26Handle=NULL; +static HWND GPR27Handle=NULL; +static HWND GPR28Handle=NULL; +static HWND GPR29Handle=NULL; +static HWND GPR30Handle=NULL; +static HWND GPR31Handle=NULL; +static HWND GPRPCHandle=NULL; +static HWND GPRHIHandle=NULL; +static HWND GPRLOHandle=NULL; +/*end of r3000a registers handle */ +/*cop0 registers here */ +static HWND COP00Handle=NULL; +static HWND COP01Handle=NULL; +static HWND COP02Handle=NULL; +static HWND COP03Handle=NULL; +static HWND COP04Handle=NULL; +static HWND COP05Handle=NULL; +static HWND COP06Handle=NULL; +static HWND COP07Handle=NULL; +static HWND COP08Handle=NULL; +static HWND COP09Handle=NULL; +static HWND COP010Handle=NULL; +static HWND COP011Handle=NULL; +static HWND COP012Handle=NULL; +static HWND COP013Handle=NULL; +static HWND COP014Handle=NULL; +static HWND COP015Handle=NULL; +static HWND COP016Handle=NULL; +static HWND COP017Handle=NULL; +static HWND COP018Handle=NULL; +static HWND COP019Handle=NULL; +static HWND COP020Handle=NULL; +static HWND COP021Handle=NULL; +static HWND COP022Handle=NULL; +static HWND COP023Handle=NULL; +static HWND COP024Handle=NULL; +static HWND COP025Handle=NULL; +static HWND COP026Handle=NULL; +static HWND COP027Handle=NULL; +static HWND COP028Handle=NULL; +static HWND COP029Handle=NULL; +static HWND COP030Handle=NULL; +static HWND COP031Handle=NULL; +static HWND COP0PCHandle=NULL; +static HWND COP0HIHandle=NULL; +static HWND COP0LOHandle=NULL; +/*end of cop0 registers */ +/*cop1 registers here */ +static HWND COP10Handle=NULL; +static HWND COP11Handle=NULL; +static HWND COP12Handle=NULL; +static HWND COP13Handle=NULL; +static HWND COP14Handle=NULL; +static HWND COP15Handle=NULL; +static HWND COP16Handle=NULL; +static HWND COP17Handle=NULL; +static HWND COP18Handle=NULL; +static HWND COP19Handle=NULL; +static HWND COP110Handle=NULL; +static HWND COP111Handle=NULL; +static HWND COP112Handle=NULL; +static HWND COP113Handle=NULL; +static HWND COP114Handle=NULL; +static HWND COP115Handle=NULL; +static HWND COP116Handle=NULL; +static HWND COP117Handle=NULL; +static HWND COP118Handle=NULL; +static HWND COP119Handle=NULL; +static HWND COP120Handle=NULL; +static HWND COP121Handle=NULL; +static HWND COP122Handle=NULL; +static HWND COP123Handle=NULL; +static HWND COP124Handle=NULL; +static HWND COP125Handle=NULL; +static HWND COP126Handle=NULL; +static HWND COP127Handle=NULL; +static HWND COP128Handle=NULL; +static HWND COP129Handle=NULL; +static HWND COP130Handle=NULL; +static HWND COP131Handle=NULL; +static HWND COP1C0Handle=NULL; +static HWND COP1C1Handle=NULL; +static HWND COP1ACCHandle=NULL; +/*end of cop1 registers */ +/*cop2 floating registers*/ +static HWND VU0F00Handle=NULL; +static HWND VU0F01Handle=NULL; +static HWND VU0F02Handle=NULL; +static HWND VU0F03Handle=NULL; +static HWND VU0F04Handle=NULL; +static HWND VU0F05Handle=NULL; +static HWND VU0F06Handle=NULL; +static HWND VU0F07Handle=NULL; +static HWND VU0F08Handle=NULL; +static HWND VU0F09Handle=NULL; +static HWND VU0F10Handle=NULL; +static HWND VU0F11Handle=NULL; +static HWND VU0F12Handle=NULL; +static HWND VU0F13Handle=NULL; +static HWND VU0F14Handle=NULL; +static HWND VU0F15Handle=NULL; +static HWND VU0F16Handle=NULL; +static HWND VU0F17Handle=NULL; +static HWND VU0F18Handle=NULL; +static HWND VU0F19Handle=NULL; +static HWND VU0F20Handle=NULL; +static HWND VU0F21Handle=NULL; +static HWND VU0F22Handle=NULL; +static HWND VU0F23Handle=NULL; +static HWND VU0F24Handle=NULL; +static HWND VU0F25Handle=NULL; +static HWND VU0F26Handle=NULL; +static HWND VU0F27Handle=NULL; +static HWND VU0F28Handle=NULL; +static HWND VU0F29Handle=NULL; +static HWND VU0F30Handle=NULL; +static HWND VU0F31Handle=NULL; +/*end of cop2 floating registers*/ +/*cop2 control registers */ +static HWND VU0C00Handle=NULL; +static HWND VU0C01Handle=NULL; +static HWND VU0C02Handle=NULL; +static HWND VU0C03Handle=NULL; +static HWND VU0C04Handle=NULL; +static HWND VU0C05Handle=NULL; +static HWND VU0C06Handle=NULL; +static HWND VU0C07Handle=NULL; +static HWND VU0C08Handle=NULL; +static HWND VU0C09Handle=NULL; +static HWND VU0C10Handle=NULL; +static HWND VU0C11Handle=NULL; +static HWND VU0C12Handle=NULL; +static HWND VU0C13Handle=NULL; +static HWND VU0C14Handle=NULL; +static HWND VU0C15Handle=NULL; +static HWND VU0C16Handle=NULL; +static HWND VU0C17Handle=NULL; +static HWND VU0C18Handle=NULL; +static HWND VU0C19Handle=NULL; +static HWND VU0C20Handle=NULL; +static HWND VU0C21Handle=NULL; +static HWND VU0C22Handle=NULL; +static HWND VU0C23Handle=NULL; +static HWND VU0C24Handle=NULL; +static HWND VU0C25Handle=NULL; +static HWND VU0C26Handle=NULL; +static HWND VU0C27Handle=NULL; +static HWND VU0C28Handle=NULL; +static HWND VU0C29Handle=NULL; +static HWND VU0C30Handle=NULL; +static HWND VU0C31Handle=NULL; +static HWND VU0ACCHandle=NULL; +/*end of cop2 control registers */ +/*vu1 floating registers*/ +static HWND VU1F00Handle=NULL; +static HWND VU1F01Handle=NULL; +static HWND VU1F02Handle=NULL; +static HWND VU1F03Handle=NULL; +static HWND VU1F04Handle=NULL; +static HWND VU1F05Handle=NULL; +static HWND VU1F06Handle=NULL; +static HWND VU1F07Handle=NULL; +static HWND VU1F08Handle=NULL; +static HWND VU1F09Handle=NULL; +static HWND VU1F10Handle=NULL; +static HWND VU1F11Handle=NULL; +static HWND VU1F12Handle=NULL; +static HWND VU1F13Handle=NULL; +static HWND VU1F14Handle=NULL; +static HWND VU1F15Handle=NULL; +static HWND VU1F16Handle=NULL; +static HWND VU1F17Handle=NULL; +static HWND VU1F18Handle=NULL; +static HWND VU1F19Handle=NULL; +static HWND VU1F20Handle=NULL; +static HWND VU1F21Handle=NULL; +static HWND VU1F22Handle=NULL; +static HWND VU1F23Handle=NULL; +static HWND VU1F24Handle=NULL; +static HWND VU1F25Handle=NULL; +static HWND VU1F26Handle=NULL; +static HWND VU1F27Handle=NULL; +static HWND VU1F28Handle=NULL; +static HWND VU1F29Handle=NULL; +static HWND VU1F30Handle=NULL; +static HWND VU1F31Handle=NULL; +/*end of vu1 floating registers*/ +/*vu1 control registers */ +static HWND VU1C00Handle=NULL; +static HWND VU1C01Handle=NULL; +static HWND VU1C02Handle=NULL; +static HWND VU1C03Handle=NULL; +static HWND VU1C04Handle=NULL; +static HWND VU1C05Handle=NULL; +static HWND VU1C06Handle=NULL; +static HWND VU1C07Handle=NULL; +static HWND VU1C08Handle=NULL; +static HWND VU1C09Handle=NULL; +static HWND VU1C10Handle=NULL; +static HWND VU1C11Handle=NULL; +static HWND VU1C12Handle=NULL; +static HWND VU1C13Handle=NULL; +static HWND VU1C14Handle=NULL; +static HWND VU1C15Handle=NULL; +static HWND VU1C16Handle=NULL; +static HWND VU1C17Handle=NULL; +static HWND VU1C18Handle=NULL; +static HWND VU1C19Handle=NULL; +static HWND VU1C20Handle=NULL; +static HWND VU1C21Handle=NULL; +static HWND VU1C22Handle=NULL; +static HWND VU1C23Handle=NULL; +static HWND VU1C24Handle=NULL; +static HWND VU1C25Handle=NULL; +static HWND VU1C26Handle=NULL; +static HWND VU1C27Handle=NULL; +static HWND VU1C28Handle=NULL; +static HWND VU1C29Handle=NULL; +static HWND VU1C30Handle=NULL; +static HWND VU1C31Handle=NULL; +static HWND VU1ACCHandle=NULL; +/*end of vu1 control registers */ + +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +//comctl32 lib must add to project.. +int CreatePropertySheet(HWND hwndOwner) +{ + + PROPSHEETPAGE psp[7]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_GPREGS); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)R5900reg; + psp[0].pszTitle = "R5900"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = m_hInst; + psp[1].pszTemplate = MAKEINTRESOURCE( IDD_CP0REGS ); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc =(DLGPROC)COP0reg; + psp[1].pszTitle = "COP0"; + psp[1].lParam = 0; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = PSP_USETITLE; + psp[2].hInstance = m_hInst; + psp[2].pszTemplate = MAKEINTRESOURCE( IDD_CP1REGS ); + psp[2].pszIcon = NULL; + psp[2].pfnDlgProc =(DLGPROC)COP1reg; + psp[2].pszTitle = "COP1"; + psp[2].lParam = 0; + + psp[3].dwSize = sizeof(PROPSHEETPAGE); + psp[3].dwFlags = PSP_USETITLE; + psp[3].hInstance = m_hInst; + psp[3].pszTemplate = MAKEINTRESOURCE( IDD_VU0REGS ); + psp[3].pszIcon = NULL; + psp[3].pfnDlgProc =(DLGPROC)COP2Freg; + psp[3].pszTitle = "COP2F"; + psp[3].lParam = 0; + + psp[4].dwSize = sizeof(PROPSHEETPAGE); + psp[4].dwFlags = PSP_USETITLE; + psp[4].hInstance = m_hInst; + psp[4].pszTemplate = MAKEINTRESOURCE( IDD_VU0INTEGER ); + psp[4].pszIcon = NULL; + psp[4].pfnDlgProc =(DLGPROC)COP2Creg; + psp[4].pszTitle = "COP2C"; + psp[4].lParam = 0; + + psp[5].dwSize = sizeof(PROPSHEETPAGE); + psp[5].dwFlags = PSP_USETITLE; + psp[5].hInstance = m_hInst; + psp[5].pszTemplate = MAKEINTRESOURCE( IDD_VU1REGS ); + psp[5].pszIcon = NULL; + psp[5].pfnDlgProc =(DLGPROC)VU1Freg; + psp[5].pszTitle = "VU1F"; + psp[5].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_VU1INTEGER ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)VU1Creg; + psp[6].pszTitle = "VU1C"; + psp[6].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_IOPREGS ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)R3000reg; + psp[6].pszTitle = "R3000"; + psp[6].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); + +} +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + IOPGPR0Handle=GetDlgItem(hDlg,IDC_IOPGPR0); + IOPGPR1Handle=GetDlgItem(hDlg,IDC_IOPGPR1); + IOPGPR2Handle=GetDlgItem(hDlg,IDC_IOPGPR2); + IOPGPR3Handle=GetDlgItem(hDlg,IDC_IOPGPR3); + IOPGPR4Handle=GetDlgItem(hDlg,IDC_IOPGPR4); + IOPGPR5Handle=GetDlgItem(hDlg,IDC_IOPGPR5); + IOPGPR6Handle=GetDlgItem(hDlg,IDC_IOPGPR6); + IOPGPR7Handle=GetDlgItem(hDlg,IDC_IOPGPR7); + IOPGPR8Handle=GetDlgItem(hDlg,IDC_IOPGPR8); + IOPGPR9Handle=GetDlgItem(hDlg,IDC_IOPGPR9); + IOPGPR10Handle=GetDlgItem(hDlg,IDC_IOPGPR10); + IOPGPR11Handle=GetDlgItem(hDlg,IDC_IOPGPR11); + IOPGPR12Handle=GetDlgItem(hDlg,IDC_IOPGPR12); + IOPGPR13Handle=GetDlgItem(hDlg,IDC_IOPGPR13); + IOPGPR14Handle=GetDlgItem(hDlg,IDC_IOPGPR14); + IOPGPR15Handle=GetDlgItem(hDlg,IDC_IOPGPR15); + IOPGPR16Handle=GetDlgItem(hDlg,IDC_IOPGPR16); + IOPGPR17Handle=GetDlgItem(hDlg,IDC_IOPGPR17); + IOPGPR18Handle=GetDlgItem(hDlg,IDC_IOPGPR18); + IOPGPR19Handle=GetDlgItem(hDlg,IDC_IOPGPR19); + IOPGPR20Handle=GetDlgItem(hDlg,IDC_IOPGPR20); + IOPGPR21Handle=GetDlgItem(hDlg,IDC_IOPGPR21); + IOPGPR22Handle=GetDlgItem(hDlg,IDC_IOPGPR22); + IOPGPR23Handle=GetDlgItem(hDlg,IDC_IOPGPR23); + IOPGPR24Handle=GetDlgItem(hDlg,IDC_IOPGPR24); + IOPGPR25Handle=GetDlgItem(hDlg,IDC_IOPGPR25); + IOPGPR26Handle=GetDlgItem(hDlg,IDC_IOPGPR26); + IOPGPR27Handle=GetDlgItem(hDlg,IDC_IOPGPR27); + IOPGPR28Handle=GetDlgItem(hDlg,IDC_IOPGPR28); + IOPGPR29Handle=GetDlgItem(hDlg,IDC_IOPGPR29); + IOPGPR30Handle=GetDlgItem(hDlg,IDC_IOPGPR30); + IOPGPR31Handle=GetDlgItem(hDlg,IDC_IOPGPR31); + IOPGPRPCHandle=GetDlgItem(hDlg,IDC_IOPGPR_PC); + IOPGPRHIHandle=GetDlgItem(hDlg,IDC_IOPGPR_HI); + IOPGPRLOHandle=GetDlgItem(hDlg,IDC_IOPGPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + GPR0Handle=GetDlgItem(hDlg,IDC_GPR0); + GPR1Handle=GetDlgItem(hDlg,IDC_GPR1); + GPR2Handle=GetDlgItem(hDlg,IDC_GPR2); + GPR3Handle=GetDlgItem(hDlg,IDC_GPR3); + GPR4Handle=GetDlgItem(hDlg,IDC_GPR4); + GPR5Handle=GetDlgItem(hDlg,IDC_GPR5); + GPR6Handle=GetDlgItem(hDlg,IDC_GPR6); + GPR7Handle=GetDlgItem(hDlg,IDC_GPR7); + GPR8Handle=GetDlgItem(hDlg,IDC_GPR8); + GPR9Handle=GetDlgItem(hDlg,IDC_GPR9); + GPR10Handle=GetDlgItem(hDlg,IDC_GPR10); + GPR11Handle=GetDlgItem(hDlg,IDC_GPR11); + GPR12Handle=GetDlgItem(hDlg,IDC_GPR12); + GPR13Handle=GetDlgItem(hDlg,IDC_GPR13); + GPR14Handle=GetDlgItem(hDlg,IDC_GPR14); + GPR15Handle=GetDlgItem(hDlg,IDC_GPR15); + GPR16Handle=GetDlgItem(hDlg,IDC_GPR16); + GPR17Handle=GetDlgItem(hDlg,IDC_GPR17); + GPR18Handle=GetDlgItem(hDlg,IDC_GPR18); + GPR19Handle=GetDlgItem(hDlg,IDC_GPR19); + GPR20Handle=GetDlgItem(hDlg,IDC_GPR20); + GPR21Handle=GetDlgItem(hDlg,IDC_GPR21); + GPR22Handle=GetDlgItem(hDlg,IDC_GPR22); + GPR23Handle=GetDlgItem(hDlg,IDC_GPR23); + GPR24Handle=GetDlgItem(hDlg,IDC_GPR24); + GPR25Handle=GetDlgItem(hDlg,IDC_GPR25); + GPR26Handle=GetDlgItem(hDlg,IDC_GPR26); + GPR27Handle=GetDlgItem(hDlg,IDC_GPR27); + GPR28Handle=GetDlgItem(hDlg,IDC_GPR28); + GPR29Handle=GetDlgItem(hDlg,IDC_GPR29); + GPR30Handle=GetDlgItem(hDlg,IDC_GPR30); + GPR31Handle=GetDlgItem(hDlg,IDC_GPR31); + GPRPCHandle=GetDlgItem(hDlg,IDC_GPR_PC); + GPRHIHandle=GetDlgItem(hDlg,IDC_GPR_HI); + GPRLOHandle=GetDlgItem(hDlg,IDC_GPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP00Handle=GetDlgItem(hDlg,IDC_CP00); + COP01Handle=GetDlgItem(hDlg,IDC_CP01); + COP02Handle=GetDlgItem(hDlg,IDC_CP02); + COP03Handle=GetDlgItem(hDlg,IDC_CP03); + COP04Handle=GetDlgItem(hDlg,IDC_CP04); + COP05Handle=GetDlgItem(hDlg,IDC_CP05); + COP06Handle=GetDlgItem(hDlg,IDC_CP06); + COP07Handle=GetDlgItem(hDlg,IDC_CP07); + COP08Handle=GetDlgItem(hDlg,IDC_CP08); + COP09Handle=GetDlgItem(hDlg,IDC_CP09); + COP010Handle=GetDlgItem(hDlg,IDC_CP010); + COP011Handle=GetDlgItem(hDlg,IDC_CP011); + COP012Handle=GetDlgItem(hDlg,IDC_CP012); + COP013Handle=GetDlgItem(hDlg,IDC_CP013); + COP014Handle=GetDlgItem(hDlg,IDC_CP014); + COP015Handle=GetDlgItem(hDlg,IDC_CP015); + COP016Handle=GetDlgItem(hDlg,IDC_CP016); + COP017Handle=GetDlgItem(hDlg,IDC_CP017); + COP018Handle=GetDlgItem(hDlg,IDC_CP018); + COP019Handle=GetDlgItem(hDlg,IDC_CP019); + COP020Handle=GetDlgItem(hDlg,IDC_CP020); + COP021Handle=GetDlgItem(hDlg,IDC_CP021); + COP022Handle=GetDlgItem(hDlg,IDC_CP022); + COP023Handle=GetDlgItem(hDlg,IDC_CP023); + COP024Handle=GetDlgItem(hDlg,IDC_CP024); + COP025Handle=GetDlgItem(hDlg,IDC_CP025); + COP026Handle=GetDlgItem(hDlg,IDC_CP026); + COP027Handle=GetDlgItem(hDlg,IDC_CP027); + COP028Handle=GetDlgItem(hDlg,IDC_CP028); + COP029Handle=GetDlgItem(hDlg,IDC_CP029); + COP030Handle=GetDlgItem(hDlg,IDC_CP030); + COP031Handle=GetDlgItem(hDlg,IDC_CP031); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP10Handle=GetDlgItem(hDlg,IDC_FP0); + COP11Handle=GetDlgItem(hDlg,IDC_FP1); + COP12Handle=GetDlgItem(hDlg,IDC_FP2); + COP13Handle=GetDlgItem(hDlg,IDC_FP3); + COP14Handle=GetDlgItem(hDlg,IDC_FP4); + COP15Handle=GetDlgItem(hDlg,IDC_FP5); + COP16Handle=GetDlgItem(hDlg,IDC_FP6); + COP17Handle=GetDlgItem(hDlg,IDC_FP7); + COP18Handle=GetDlgItem(hDlg,IDC_FP8); + COP19Handle=GetDlgItem(hDlg,IDC_FP9); + COP110Handle=GetDlgItem(hDlg,IDC_FP10); + COP111Handle=GetDlgItem(hDlg,IDC_FP11); + COP112Handle=GetDlgItem(hDlg,IDC_FP12); + COP113Handle=GetDlgItem(hDlg,IDC_FP13); + COP114Handle=GetDlgItem(hDlg,IDC_FP14); + COP115Handle=GetDlgItem(hDlg,IDC_FP15); + COP116Handle=GetDlgItem(hDlg,IDC_FP16); + COP117Handle=GetDlgItem(hDlg,IDC_FP17); + COP118Handle=GetDlgItem(hDlg,IDC_FP18); + COP119Handle=GetDlgItem(hDlg,IDC_FP19); + COP120Handle=GetDlgItem(hDlg,IDC_FP20); + COP121Handle=GetDlgItem(hDlg,IDC_FP21); + COP122Handle=GetDlgItem(hDlg,IDC_FP22); + COP123Handle=GetDlgItem(hDlg,IDC_FP23); + COP124Handle=GetDlgItem(hDlg,IDC_FP24); + COP125Handle=GetDlgItem(hDlg,IDC_FP25); + COP126Handle=GetDlgItem(hDlg,IDC_FP26); + COP127Handle=GetDlgItem(hDlg,IDC_FP27); + COP128Handle=GetDlgItem(hDlg,IDC_FP28); + COP129Handle=GetDlgItem(hDlg,IDC_FP29); + COP130Handle=GetDlgItem(hDlg,IDC_FP30); + COP131Handle=GetDlgItem(hDlg,IDC_FP31); + COP1C0Handle=GetDlgItem(hDlg,IDC_FCR0); + COP1C1Handle=GetDlgItem(hDlg,IDC_FCR31); + COP1ACCHandle=GetDlgItem(hDlg,IDC_FPU_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0F00Handle=GetDlgItem(hDlg,IDC_VU0_VF00); + VU0F01Handle=GetDlgItem(hDlg,IDC_VU0_VF01); + VU0F02Handle=GetDlgItem(hDlg,IDC_VU0_VF02); + VU0F03Handle=GetDlgItem(hDlg,IDC_VU0_VF03); + VU0F04Handle=GetDlgItem(hDlg,IDC_VU0_VF04); + VU0F05Handle=GetDlgItem(hDlg,IDC_VU0_VF05); + VU0F06Handle=GetDlgItem(hDlg,IDC_VU0_VF06); + VU0F07Handle=GetDlgItem(hDlg,IDC_VU0_VF07); + VU0F08Handle=GetDlgItem(hDlg,IDC_VU0_VF08); + VU0F09Handle=GetDlgItem(hDlg,IDC_VU0_VF09); + VU0F10Handle=GetDlgItem(hDlg,IDC_VU0_VF10); + VU0F11Handle=GetDlgItem(hDlg,IDC_VU0_VF11); + VU0F12Handle=GetDlgItem(hDlg,IDC_VU0_VF12); + VU0F13Handle=GetDlgItem(hDlg,IDC_VU0_VF13); + VU0F14Handle=GetDlgItem(hDlg,IDC_VU0_VF14); + VU0F15Handle=GetDlgItem(hDlg,IDC_VU0_VF15); + VU0F16Handle=GetDlgItem(hDlg,IDC_VU0_VF16); + VU0F17Handle=GetDlgItem(hDlg,IDC_VU0_VF17); + VU0F18Handle=GetDlgItem(hDlg,IDC_VU0_VF18); + VU0F19Handle=GetDlgItem(hDlg,IDC_VU0_VF19); + VU0F20Handle=GetDlgItem(hDlg,IDC_VU0_VF20); + VU0F21Handle=GetDlgItem(hDlg,IDC_VU0_VF21); + VU0F22Handle=GetDlgItem(hDlg,IDC_VU0_VF22); + VU0F23Handle=GetDlgItem(hDlg,IDC_VU0_VF23); + VU0F24Handle=GetDlgItem(hDlg,IDC_VU0_VF24); + VU0F25Handle=GetDlgItem(hDlg,IDC_VU0_VF25); + VU0F26Handle=GetDlgItem(hDlg,IDC_VU0_VF26); + VU0F27Handle=GetDlgItem(hDlg,IDC_VU0_VF27); + VU0F28Handle=GetDlgItem(hDlg,IDC_VU0_VF28); + VU0F29Handle=GetDlgItem(hDlg,IDC_VU0_VF29); + VU0F30Handle=GetDlgItem(hDlg,IDC_VU0_VF30); + VU0F31Handle=GetDlgItem(hDlg,IDC_VU0_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0C00Handle=GetDlgItem(hDlg,IDC_VU0_VI00); + VU0C01Handle=GetDlgItem(hDlg,IDC_VU0_VI01); + VU0C02Handle=GetDlgItem(hDlg,IDC_VU0_VI02); + VU0C03Handle=GetDlgItem(hDlg,IDC_VU0_VI03); + VU0C04Handle=GetDlgItem(hDlg,IDC_VU0_VI04); + VU0C05Handle=GetDlgItem(hDlg,IDC_VU0_VI05); + VU0C06Handle=GetDlgItem(hDlg,IDC_VU0_VI06); + VU0C07Handle=GetDlgItem(hDlg,IDC_VU0_VI07); + VU0C08Handle=GetDlgItem(hDlg,IDC_VU0_VI08); + VU0C09Handle=GetDlgItem(hDlg,IDC_VU0_VI09); + VU0C10Handle=GetDlgItem(hDlg,IDC_VU0_VI10); + VU0C11Handle=GetDlgItem(hDlg,IDC_VU0_VI11); + VU0C12Handle=GetDlgItem(hDlg,IDC_VU0_VI12); + VU0C13Handle=GetDlgItem(hDlg,IDC_VU0_VI13); + VU0C14Handle=GetDlgItem(hDlg,IDC_VU0_VI14); + VU0C15Handle=GetDlgItem(hDlg,IDC_VU0_VI15); + VU0C16Handle=GetDlgItem(hDlg,IDC_VU0_VI16); + VU0C17Handle=GetDlgItem(hDlg,IDC_VU0_VI17); + VU0C18Handle=GetDlgItem(hDlg,IDC_VU0_VI18); + VU0C19Handle=GetDlgItem(hDlg,IDC_VU0_VI19); + VU0C20Handle=GetDlgItem(hDlg,IDC_VU0_VI20); + VU0C21Handle=GetDlgItem(hDlg,IDC_VU0_VI21); + VU0C22Handle=GetDlgItem(hDlg,IDC_VU0_VI22); + VU0C23Handle=GetDlgItem(hDlg,IDC_VU0_VI23); + VU0C24Handle=GetDlgItem(hDlg,IDC_VU0_VI24); + VU0C25Handle=GetDlgItem(hDlg,IDC_VU0_VI25); + VU0C26Handle=GetDlgItem(hDlg,IDC_VU0_VI26); + VU0C27Handle=GetDlgItem(hDlg,IDC_VU0_VI27); + VU0C28Handle=GetDlgItem(hDlg,IDC_VU0_VI28); + VU0C29Handle=GetDlgItem(hDlg,IDC_VU0_VI29); + VU0C30Handle=GetDlgItem(hDlg,IDC_VU0_VI30); + VU0C31Handle=GetDlgItem(hDlg,IDC_VU0_VI31); + VU0ACCHandle=GetDlgItem(hDlg,IDC_VU0_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + + +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1F00Handle=GetDlgItem(hDlg,IDC_VU1_VF00); + VU1F01Handle=GetDlgItem(hDlg,IDC_VU1_VF01); + VU1F02Handle=GetDlgItem(hDlg,IDC_VU1_VF02); + VU1F03Handle=GetDlgItem(hDlg,IDC_VU1_VF03); + VU1F04Handle=GetDlgItem(hDlg,IDC_VU1_VF04); + VU1F05Handle=GetDlgItem(hDlg,IDC_VU1_VF05); + VU1F06Handle=GetDlgItem(hDlg,IDC_VU1_VF06); + VU1F07Handle=GetDlgItem(hDlg,IDC_VU1_VF07); + VU1F08Handle=GetDlgItem(hDlg,IDC_VU1_VF08); + VU1F09Handle=GetDlgItem(hDlg,IDC_VU1_VF09); + VU1F10Handle=GetDlgItem(hDlg,IDC_VU1_VF10); + VU1F11Handle=GetDlgItem(hDlg,IDC_VU1_VF11); + VU1F12Handle=GetDlgItem(hDlg,IDC_VU1_VF12); + VU1F13Handle=GetDlgItem(hDlg,IDC_VU1_VF13); + VU1F14Handle=GetDlgItem(hDlg,IDC_VU1_VF14); + VU1F15Handle=GetDlgItem(hDlg,IDC_VU1_VF15); + VU1F16Handle=GetDlgItem(hDlg,IDC_VU1_VF16); + VU1F17Handle=GetDlgItem(hDlg,IDC_VU1_VF17); + VU1F18Handle=GetDlgItem(hDlg,IDC_VU1_VF18); + VU1F19Handle=GetDlgItem(hDlg,IDC_VU1_VF19); + VU1F20Handle=GetDlgItem(hDlg,IDC_VU1_VF20); + VU1F21Handle=GetDlgItem(hDlg,IDC_VU1_VF21); + VU1F22Handle=GetDlgItem(hDlg,IDC_VU1_VF22); + VU1F23Handle=GetDlgItem(hDlg,IDC_VU1_VF23); + VU1F24Handle=GetDlgItem(hDlg,IDC_VU1_VF24); + VU1F25Handle=GetDlgItem(hDlg,IDC_VU1_VF25); + VU1F26Handle=GetDlgItem(hDlg,IDC_VU1_VF26); + VU1F27Handle=GetDlgItem(hDlg,IDC_VU1_VF27); + VU1F28Handle=GetDlgItem(hDlg,IDC_VU1_VF28); + VU1F29Handle=GetDlgItem(hDlg,IDC_VU1_VF29); + VU1F30Handle=GetDlgItem(hDlg,IDC_VU1_VF30); + VU1F31Handle=GetDlgItem(hDlg,IDC_VU1_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1C00Handle=GetDlgItem(hDlg,IDC_VU1_VI00); + VU1C01Handle=GetDlgItem(hDlg,IDC_VU1_VI01); + VU1C02Handle=GetDlgItem(hDlg,IDC_VU1_VI02); + VU1C03Handle=GetDlgItem(hDlg,IDC_VU1_VI03); + VU1C04Handle=GetDlgItem(hDlg,IDC_VU1_VI04); + VU1C05Handle=GetDlgItem(hDlg,IDC_VU1_VI05); + VU1C06Handle=GetDlgItem(hDlg,IDC_VU1_VI06); + VU1C07Handle=GetDlgItem(hDlg,IDC_VU1_VI07); + VU1C08Handle=GetDlgItem(hDlg,IDC_VU1_VI08); + VU1C09Handle=GetDlgItem(hDlg,IDC_VU1_VI09); + VU1C10Handle=GetDlgItem(hDlg,IDC_VU1_VI10); + VU1C11Handle=GetDlgItem(hDlg,IDC_VU1_VI11); + VU1C12Handle=GetDlgItem(hDlg,IDC_VU1_VI12); + VU1C13Handle=GetDlgItem(hDlg,IDC_VU1_VI13); + VU1C14Handle=GetDlgItem(hDlg,IDC_VU1_VI14); + VU1C15Handle=GetDlgItem(hDlg,IDC_VU1_VI15); + VU1C16Handle=GetDlgItem(hDlg,IDC_VU1_VI16); + VU1C17Handle=GetDlgItem(hDlg,IDC_VU1_VI17); + VU1C18Handle=GetDlgItem(hDlg,IDC_VU1_VI18); + VU1C19Handle=GetDlgItem(hDlg,IDC_VU1_VI19); + VU1C20Handle=GetDlgItem(hDlg,IDC_VU1_VI20); + VU1C21Handle=GetDlgItem(hDlg,IDC_VU1_VI21); + VU1C22Handle=GetDlgItem(hDlg,IDC_VU1_VI22); + VU1C23Handle=GetDlgItem(hDlg,IDC_VU1_VI23); + VU1C24Handle=GetDlgItem(hDlg,IDC_VU1_VI24); + VU1C25Handle=GetDlgItem(hDlg,IDC_VU1_VI25); + VU1C26Handle=GetDlgItem(hDlg,IDC_VU1_VI26); + VU1C27Handle=GetDlgItem(hDlg,IDC_VU1_VI27); + VU1C28Handle=GetDlgItem(hDlg,IDC_VU1_VI28); + VU1C29Handle=GetDlgItem(hDlg,IDC_VU1_VI29); + VU1C30Handle=GetDlgItem(hDlg,IDC_VU1_VI30); + VU1C31Handle=GetDlgItem(hDlg,IDC_VU1_VI31); + VU1ACCHandle=GetDlgItem(hDlg,IDC_VU1_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +void UpdateRegs(void) +{ + + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[0]); + SendMessage(IOPGPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[1]); + SendMessage(IOPGPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[2]); + SendMessage(IOPGPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[3]); + SendMessage(IOPGPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[4]); + SendMessage(IOPGPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[5]); + SendMessage(IOPGPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[6]); + SendMessage(IOPGPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[7]); + SendMessage(IOPGPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[8]); + SendMessage(IOPGPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[9]); + SendMessage(IOPGPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[10]); + SendMessage(IOPGPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[11]); + SendMessage(IOPGPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[12]); + SendMessage(IOPGPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[13]); + SendMessage(IOPGPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[14]); + SendMessage(IOPGPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[15]); + SendMessage(IOPGPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[16]); + SendMessage(IOPGPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[17]); + SendMessage(IOPGPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[18]); + SendMessage(IOPGPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[19]); + SendMessage(IOPGPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[20]); + SendMessage(IOPGPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[21]); + SendMessage(IOPGPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[22]); + SendMessage(IOPGPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[23]); + SendMessage(IOPGPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[24]); + SendMessage(IOPGPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[25]); + SendMessage(IOPGPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[26]); + SendMessage(IOPGPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[27]); + SendMessage(IOPGPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[28]); + SendMessage(IOPGPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[29]); + SendMessage(IOPGPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[30]); + SendMessage(IOPGPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[31]); + SendMessage(IOPGPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",psxRegs.pc ); + SendMessage(IOPGPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[32]); + SendMessage(IOPGPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[33]); + SendMessage(IOPGPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[0].UL[3],cpuRegs.GPR.r[0].UL[2],cpuRegs.GPR.r[0].UL[1],cpuRegs.GPR.r[0].UL[0] ); + SendMessage(GPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[1].UL[3], cpuRegs.GPR.r[1].UL[2],cpuRegs.GPR.r[1].UL[1],cpuRegs.GPR.r[1].UL[0] ); + SendMessage(GPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[2].UL[3],cpuRegs.GPR.r[2].UL[2], cpuRegs.GPR.r[2].UL[1],cpuRegs.GPR.r[2].UL[0]); + SendMessage(GPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[3].UL[3],cpuRegs.GPR.r[3].UL[2], cpuRegs.GPR.r[3].UL[1],cpuRegs.GPR.r[3].UL[0] ); + SendMessage(GPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[4].UL[3],cpuRegs.GPR.r[4].UL[2], cpuRegs.GPR.r[4].UL[1],cpuRegs.GPR.r[4].UL[0] ); + SendMessage(GPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[5].UL[3],cpuRegs.GPR.r[5].UL[2],cpuRegs.GPR.r[5].UL[1], cpuRegs.GPR.r[5].UL[0] ); + SendMessage(GPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[6].UL[3],cpuRegs.GPR.r[6].UL[2], cpuRegs.GPR.r[6].UL[1], cpuRegs.GPR.r[6].UL[0]); + SendMessage(GPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[7].UL[3], cpuRegs.GPR.r[7].UL[2],cpuRegs.GPR.r[7].UL[1],cpuRegs.GPR.r[7].UL[0] ); + SendMessage(GPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[8].UL[3],cpuRegs.GPR.r[8].UL[2],cpuRegs.GPR.r[8].UL[1],cpuRegs.GPR.r[8].UL[0] ); + SendMessage(GPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[9].UL[3],cpuRegs.GPR.r[9].UL[2],cpuRegs.GPR.r[9].UL[1], cpuRegs.GPR.r[9].UL[0] ); + SendMessage(GPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[10].UL[3],cpuRegs.GPR.r[10].UL[2],cpuRegs.GPR.r[10].UL[1],cpuRegs.GPR.r[10].UL[0] ); + SendMessage(GPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[11].UL[3],cpuRegs.GPR.r[11].UL[2],cpuRegs.GPR.r[11].UL[1],cpuRegs.GPR.r[11].UL[0] ); + SendMessage(GPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[12].UL[3],cpuRegs.GPR.r[12].UL[2],cpuRegs.GPR.r[12].UL[1],cpuRegs.GPR.r[12].UL[0] ); + SendMessage(GPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[13].UL[3],cpuRegs.GPR.r[13].UL[2],cpuRegs.GPR.r[13].UL[1],cpuRegs.GPR.r[13].UL[0] ); + SendMessage(GPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[14].UL[3],cpuRegs.GPR.r[14].UL[2],cpuRegs.GPR.r[14].UL[1],cpuRegs.GPR.r[14].UL[0] ); + SendMessage(GPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[15].UL[3],cpuRegs.GPR.r[15].UL[2],cpuRegs.GPR.r[15].UL[1],cpuRegs.GPR.r[15].UL[0] ); + SendMessage(GPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[16].UL[3],cpuRegs.GPR.r[16].UL[2],cpuRegs.GPR.r[16].UL[1],cpuRegs.GPR.r[16].UL[0] ); + SendMessage(GPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[17].UL[3],cpuRegs.GPR.r[17].UL[2],cpuRegs.GPR.r[17].UL[1],cpuRegs.GPR.r[17].UL[0] ); + SendMessage(GPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[18].UL[3],cpuRegs.GPR.r[18].UL[2],cpuRegs.GPR.r[18].UL[1],cpuRegs.GPR.r[18].UL[0] ); + SendMessage(GPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[19].UL[3],cpuRegs.GPR.r[19].UL[2],cpuRegs.GPR.r[19].UL[1],cpuRegs.GPR.r[19].UL[0] ); + SendMessage(GPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[20].UL[3],cpuRegs.GPR.r[20].UL[2],cpuRegs.GPR.r[20].UL[1],cpuRegs.GPR.r[20].UL[0] ); + SendMessage(GPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[21].UL[3],cpuRegs.GPR.r[21].UL[2],cpuRegs.GPR.r[21].UL[1],cpuRegs.GPR.r[21].UL[0] ); + SendMessage(GPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[22].UL[3],cpuRegs.GPR.r[22].UL[2],cpuRegs.GPR.r[22].UL[1],cpuRegs.GPR.r[22].UL[0] ); + SendMessage(GPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[23].UL[3],cpuRegs.GPR.r[23].UL[2],cpuRegs.GPR.r[23].UL[1],cpuRegs.GPR.r[23].UL[0] ); + SendMessage(GPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[24].UL[3],cpuRegs.GPR.r[24].UL[2],cpuRegs.GPR.r[24].UL[1],cpuRegs.GPR.r[24].UL[0] ); + SendMessage(GPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[25].UL[3],cpuRegs.GPR.r[25].UL[2],cpuRegs.GPR.r[25].UL[1],cpuRegs.GPR.r[25].UL[0] ); + SendMessage(GPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[26].UL[3],cpuRegs.GPR.r[26].UL[2],cpuRegs.GPR.r[26].UL[1],cpuRegs.GPR.r[26].UL[0] ); + SendMessage(GPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[27].UL[3],cpuRegs.GPR.r[27].UL[2],cpuRegs.GPR.r[27].UL[1],cpuRegs.GPR.r[27].UL[0] ); + SendMessage(GPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[28].UL[3],cpuRegs.GPR.r[28].UL[2],cpuRegs.GPR.r[28].UL[1],cpuRegs.GPR.r[28].UL[0] ); + SendMessage(GPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[29].UL[3],cpuRegs.GPR.r[29].UL[2],cpuRegs.GPR.r[29].UL[1],cpuRegs.GPR.r[29].UL[0] ); + SendMessage(GPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[30].UL[3],cpuRegs.GPR.r[30].UL[2],cpuRegs.GPR.r[30].UL[1],cpuRegs.GPR.r[30].UL[0] ); + SendMessage(GPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[31].UL[3],cpuRegs.GPR.r[31].UL[2],cpuRegs.GPR.r[31].UL[1],cpuRegs.GPR.r[31].UL[0] ); + SendMessage(GPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.pc ); + SendMessage(GPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2] ,cpuRegs.HI.UL[1] ,cpuRegs.HI.UL[0] ); + SendMessage(GPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0\0",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0] ); + SendMessage(GPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[0] ); + SendMessage(COP00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[1]); + SendMessage(COP01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[2]); + SendMessage(COP02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[3]); + SendMessage(COP03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[4]); + SendMessage(COP04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[5]); + SendMessage(COP05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[6]); + SendMessage(COP06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[7]); + SendMessage(COP07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[8]); + SendMessage(COP08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[9]); + SendMessage(COP09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[10]); + SendMessage(COP010Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[11]); + SendMessage(COP011Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[12]); + SendMessage(COP012Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[13]); + SendMessage(COP013Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[14]); + SendMessage(COP014Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[15]); + SendMessage(COP015Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[16]); + SendMessage(COP016Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[17]); + SendMessage(COP017Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[18]); + SendMessage(COP018Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[19]); + SendMessage(COP019Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[20]); + SendMessage(COP020Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[21]); + SendMessage(COP021Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[22]); + SendMessage(COP022Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[23]); + SendMessage(COP023Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[24]); + SendMessage(COP024Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[25]); + SendMessage(COP025Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[26]); + SendMessage(COP026Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[27]); + SendMessage(COP027Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[28]); + SendMessage(COP028Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[29]); + SendMessage(COP029Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[30]); + SendMessage(COP030Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[31]); + SendMessage(COP031Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f",fpuRegs.fpr[0].f ); + SendMessage(COP10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[1].f); + SendMessage(COP11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[2].f); + SendMessage(COP12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[3].f); + SendMessage(COP13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[4].f); + SendMessage(COP14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[5].f); + SendMessage(COP15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[6].f); + SendMessage(COP16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[7].f); + SendMessage(COP17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[8].f); + SendMessage(COP18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[9].f); + SendMessage(COP19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[10].f); + SendMessage(COP110Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[11].f); + SendMessage(COP111Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[12].f); + SendMessage(COP112Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[13].f); + SendMessage(COP113Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[14].f); + SendMessage(COP114Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[15].f); + SendMessage(COP115Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[16].f); + SendMessage(COP116Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[17].f); + SendMessage(COP117Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[18].f); + SendMessage(COP118Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[19].f); + SendMessage(COP119Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[20].f); + SendMessage(COP120Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[21].f); + SendMessage(COP121Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[22].f); + SendMessage(COP122Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[23].f); + SendMessage(COP123Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[24].f); + SendMessage(COP124Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[25].f); + SendMessage(COP125Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[26].f); + SendMessage(COP126Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[27].f); + SendMessage(COP127Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[28].f); + SendMessage(COP128Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[29].f); + SendMessage(COP129Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[30].f); + SendMessage(COP130Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[31].f); + SendMessage(COP131Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[0]); + SendMessage(COP1C0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[31]); + SendMessage(COP1C1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.ACC.f); + SendMessage(COP1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[0].f.w,VU0.VF[0].f.z,VU0.VF[0].f.y,VU0.VF[0].f.x ); + SendMessage(VU0F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[1].f.w,VU0.VF[1].f.z,VU0.VF[1].f.y,VU0.VF[1].f.x ); + SendMessage(VU0F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[2].f.w,VU0.VF[2].f.z,VU0.VF[2].f.y,VU0.VF[2].f.x ); + SendMessage(VU0F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[3].f.w,VU0.VF[3].f.z,VU0.VF[3].f.y,VU0.VF[3].f.x ); + SendMessage(VU0F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[4].f.w,VU0.VF[4].f.z,VU0.VF[4].f.y,VU0.VF[4].f.x ); + SendMessage(VU0F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[5].f.w,VU0.VF[5].f.z,VU0.VF[5].f.y,VU0.VF[5].f.x); + SendMessage(VU0F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[6].f.w,VU0.VF[6].f.z,VU0.VF[6].f.y,VU0.VF[6].f.x ); + SendMessage(VU0F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[7].f.w,VU0.VF[7].f.z,VU0.VF[7].f.y,VU0.VF[7].f.x ); + SendMessage(VU0F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[8].f.w,VU0.VF[8].f.z,VU0.VF[8].f.y,VU0.VF[8].f.x ); + SendMessage(VU0F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[9].f.w,VU0.VF[9].f.z,VU0.VF[9].f.y,VU0.VF[9].f.x ); + SendMessage(VU0F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[10].f.w,VU0.VF[10].f.z,VU0.VF[10].f.y,VU0.VF[10].f.x ); + SendMessage(VU0F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[11].f.w,VU0.VF[11].f.z,VU0.VF[11].f.y,VU0.VF[11].f.x ); + SendMessage(VU0F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[12].f.w,VU0.VF[12].f.z,VU0.VF[12].f.y,VU0.VF[12].f.x ); + SendMessage(VU0F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[13].f.w,VU0.VF[13].f.z,VU0.VF[13].f.y,VU0.VF[13].f.x ); + SendMessage(VU0F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[14].f.w,VU0.VF[14].f.z,VU0.VF[14].f.y,VU0.VF[14].f.x ); + SendMessage(VU0F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[15].f.w,VU0.VF[15].f.z,VU0.VF[15].f.y,VU0.VF[15].f.x ); + SendMessage(VU0F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[16].f.w,VU0.VF[16].f.z,VU0.VF[16].f.y,VU0.VF[16].f.x ); + SendMessage(VU0F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[17].f.w,VU0.VF[17].f.z,VU0.VF[17].f.y,VU0.VF[17].f.x ); + SendMessage(VU0F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[18].f.w,VU0.VF[18].f.z,VU0.VF[18].f.y,VU0.VF[18].f.x ); + SendMessage(VU0F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[19].f.w,VU0.VF[19].f.z,VU0.VF[19].f.y,VU0.VF[19].f.x ); + SendMessage(VU0F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[20].f.w,VU0.VF[20].f.z,VU0.VF[20].f.y,VU0.VF[20].f.x ); + SendMessage(VU0F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[21].f.w,VU0.VF[21].f.z,VU0.VF[21].f.y,VU0.VF[21].f.x ); + SendMessage(VU0F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[22].f.w,VU0.VF[22].f.z,VU0.VF[22].f.y,VU0.VF[22].f.x ); + SendMessage(VU0F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[23].f.w,VU0.VF[23].f.z,VU0.VF[23].f.y,VU0.VF[23].f.x ); + SendMessage(VU0F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[24].f.w,VU0.VF[24].f.z,VU0.VF[24].f.y,VU0.VF[24].f.x ); + SendMessage(VU0F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[25].f.w,VU0.VF[25].f.z,VU0.VF[25].f.y,VU0.VF[25].f.x ); + SendMessage(VU0F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[26].f.w,VU0.VF[26].f.z,VU0.VF[26].f.y,VU0.VF[26].f.x ); + SendMessage(VU0F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[27].f.w,VU0.VF[27].f.z,VU0.VF[27].f.y,VU0.VF[27].f.x ); + SendMessage(VU0F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[28].f.w,VU0.VF[28].f.z,VU0.VF[28].f.y,VU0.VF[28].f.x ); + SendMessage(VU0F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[29].f.w,VU0.VF[29].f.z,VU0.VF[29].f.y,VU0.VF[29].f.x ); + SendMessage(VU0F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[30].f.w,VU0.VF[30].f.z,VU0.VF[30].f.y,VU0.VF[30].f.x ); + SendMessage(VU0F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[31].f.w,VU0.VF[31].f.z,VU0.VF[31].f.y,VU0.VF[31].f.x ); + SendMessage(VU0F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU0.VI[0] ); + SendMessage(VU0C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[1]); + SendMessage(VU0C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[2]); + SendMessage(VU0C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[3]); + SendMessage(VU0C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[4]); + SendMessage(VU0C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[5]); + SendMessage(VU0C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[6]); + SendMessage(VU0C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[7]); + SendMessage(VU0C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[8]); + SendMessage(VU0C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[9]); + SendMessage(VU0C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[10]); + SendMessage(VU0C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[11]); + SendMessage(VU0C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[12]); + SendMessage(VU0C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[13]); + SendMessage(VU0C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[14]); + SendMessage(VU0C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[15]); + SendMessage(VU0C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[16]); + SendMessage(VU0C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[17]); + SendMessage(VU0C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[18]); + SendMessage(VU0C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[19]); + SendMessage(VU0C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[20]); + SendMessage(VU0C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[21]); + SendMessage(VU0C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[22]); + SendMessage(VU0C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[23]); + SendMessage(VU0C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[24]); + SendMessage(VU0C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[25]); + SendMessage(VU0C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[26]); + SendMessage(VU0C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[27]); + SendMessage(VU0C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[28]); + SendMessage(VU0C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[29]); + SendMessage(VU0C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[30]); + SendMessage(VU0C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[31]); + SendMessage(VU0C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU0.ACC.f.w,VU0.ACC.f.z,VU0.ACC.f.y,VU0.ACC.f.x ); + SendMessage(VU0ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[0].f.w,VU1.VF[0].f.z,VU1.VF[0].f.y,VU1.VF[0].f.x ); + SendMessage(VU1F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[1].f.w,VU1.VF[1].f.z,VU1.VF[1].f.y,VU1.VF[1].f.x ); + SendMessage(VU1F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[2].f.w,VU1.VF[2].f.z,VU1.VF[2].f.y,VU1.VF[2].f.x ); + SendMessage(VU1F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[3].f.w,VU1.VF[3].f.z,VU1.VF[3].f.y,VU1.VF[3].f.x ); + SendMessage(VU1F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[4].f.w,VU1.VF[4].f.z,VU1.VF[4].f.y,VU1.VF[4].f.x ); + SendMessage(VU1F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[5].f.w,VU1.VF[5].f.z,VU1.VF[5].f.y,VU1.VF[5].f.x); + SendMessage(VU1F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[6].f.w,VU1.VF[6].f.z,VU1.VF[6].f.y,VU1.VF[6].f.x ); + SendMessage(VU1F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[7].f.w,VU1.VF[7].f.z,VU1.VF[7].f.y,VU1.VF[7].f.x ); + SendMessage(VU1F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[8].f.w,VU1.VF[8].f.z,VU1.VF[8].f.y,VU1.VF[8].f.x ); + SendMessage(VU1F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[9].f.w,VU1.VF[9].f.z,VU1.VF[9].f.y,VU1.VF[9].f.x ); + SendMessage(VU1F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[10].f.w,VU1.VF[10].f.z,VU1.VF[10].f.y,VU1.VF[10].f.x ); + SendMessage(VU1F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[11].f.w,VU1.VF[11].f.z,VU1.VF[11].f.y,VU1.VF[11].f.x ); + SendMessage(VU1F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[12].f.w,VU1.VF[12].f.z,VU1.VF[12].f.y,VU1.VF[12].f.x ); + SendMessage(VU1F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[13].f.w,VU1.VF[13].f.z,VU1.VF[13].f.y,VU1.VF[13].f.x ); + SendMessage(VU1F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[14].f.w,VU1.VF[14].f.z,VU1.VF[14].f.y,VU1.VF[14].f.x ); + SendMessage(VU1F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[15].f.w,VU1.VF[15].f.z,VU1.VF[15].f.y,VU1.VF[15].f.x ); + SendMessage(VU1F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[16].f.w,VU1.VF[16].f.z,VU1.VF[16].f.y,VU1.VF[16].f.x ); + SendMessage(VU1F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[17].f.w,VU1.VF[17].f.z,VU1.VF[17].f.y,VU1.VF[17].f.x ); + SendMessage(VU1F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[18].f.w,VU1.VF[18].f.z,VU1.VF[18].f.y,VU1.VF[18].f.x ); + SendMessage(VU1F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[19].f.w,VU1.VF[19].f.z,VU1.VF[19].f.y,VU1.VF[19].f.x ); + SendMessage(VU1F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[20].f.w,VU1.VF[20].f.z,VU1.VF[20].f.y,VU1.VF[20].f.x ); + SendMessage(VU1F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[21].f.w,VU1.VF[21].f.z,VU1.VF[21].f.y,VU1.VF[21].f.x ); + SendMessage(VU1F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[22].f.w,VU1.VF[22].f.z,VU1.VF[22].f.y,VU1.VF[22].f.x ); + SendMessage(VU1F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[23].f.w,VU1.VF[23].f.z,VU1.VF[23].f.y,VU1.VF[23].f.x ); + SendMessage(VU1F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[24].f.w,VU1.VF[24].f.z,VU1.VF[24].f.y,VU1.VF[24].f.x ); + SendMessage(VU1F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[25].f.w,VU1.VF[25].f.z,VU1.VF[25].f.y,VU1.VF[25].f.x ); + SendMessage(VU1F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[26].f.w,VU1.VF[26].f.z,VU1.VF[26].f.y,VU1.VF[26].f.x ); + SendMessage(VU1F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[27].f.w,VU1.VF[27].f.z,VU1.VF[27].f.y,VU1.VF[27].f.x ); + SendMessage(VU1F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[28].f.w,VU1.VF[28].f.z,VU1.VF[28].f.y,VU1.VF[28].f.x ); + SendMessage(VU1F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[29].f.w,VU1.VF[29].f.z,VU1.VF[29].f.y,VU1.VF[29].f.x ); + SendMessage(VU1F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[30].f.w,VU1.VF[30].f.z,VU1.VF[30].f.y,VU1.VF[30].f.x ); + SendMessage(VU1F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[31].f.w,VU1.VF[31].f.z,VU1.VF[31].f.y,VU1.VF[31].f.x ); + SendMessage(VU1F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU1.VI[0] ); + SendMessage(VU1C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[1]); + SendMessage(VU1C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[2]); + SendMessage(VU1C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[3]); + SendMessage(VU1C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[4]); + SendMessage(VU1C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[5]); + SendMessage(VU1C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[6]); + SendMessage(VU1C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[7]); + SendMessage(VU1C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[8]); + SendMessage(VU1C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[9]); + SendMessage(VU1C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[10]); + SendMessage(VU1C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[11]); + SendMessage(VU1C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[12]); + SendMessage(VU1C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[13]); + SendMessage(VU1C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[14]); + SendMessage(VU1C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[15]); + SendMessage(VU1C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[16]); + SendMessage(VU1C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[17]); + SendMessage(VU1C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[18]); + SendMessage(VU1C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[19]); + SendMessage(VU1C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[20]); + SendMessage(VU1C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[21]); + SendMessage(VU1C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[22]); + SendMessage(VU1C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[23]); + SendMessage(VU1C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[24]); + SendMessage(VU1C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[25]); + SendMessage(VU1C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[26]); + SendMessage(VU1C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[27]); + SendMessage(VU1C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[28]); + SendMessage(VU1C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[29]); + SendMessage(VU1C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[30]); + SendMessage(VU1C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[31]); + SendMessage(VU1C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU1.ACC.f.w,VU1.ACC.f.z,VU1.ACC.f.y,VU1.ACC.f.x ); + SendMessage(VU1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + +} + + +void EEDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x_%x_%x_%x",cpuRegs.GPR.r[i].UL[3],cpuRegs.GPR.r[i].UL[2],cpuRegs.GPR.r[i].UL[1],cpuRegs.GPR.r[i].UL[0]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",cpuRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2],cpuRegs.HI.UL[1],cpuRegs.HI.UL[0]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + + + for(i = 0; i < 32; i++) + { + sprintf(text1,"0x%x",cpuRegs.CP0.r[i]); + sprintf(text2,"COP0 Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } +} + +void IOPDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x",psxRegs.GPR.r[i]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",psxRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[32]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[33]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); +} diff --git a/branches/pcsx2_0.9.1/windows/Makefile b/branches/pcsx2_0.9.1/windows/Makefile new file mode 100644 index 0000000..01ad783 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/Makefile @@ -0,0 +1,108 @@ +# +# PCSX2 Makefile for MINGW32 +# + + +all: pcsx2 + +CPU = ix86 +PCSX2 = pcsx2.exe + +CC = gcc +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +_OPTIMIZE = -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double +OPTIMIZE = -g -O2 ${_OPTIMIZE} +ROPTIMIZE = -O2 ${_OPTIMIZE} +RSOPTIMIZE = -O3 ${_OPTIMIZE} -mfpmath=sse -march=athlon64 +FLAGS = -D__WIN32__ -D__MINGW32__ -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -lintl -lpthreadGC +RESOBJ = pcsx2.o + +OBJS = ../Counters.o ../DebugTools/DisR5900.o ../Elfheader.o \ + ../Hw.o ../Memory.o ../Misc.o ../GS.o ../FiFo.o ../Sif.o\ + ../Plugins.o ../R5900.o ../InterTables.o ../Interpreter.o \ + ../COP0.o ../FPU.o ../VU0.o ../VU0micro.o ../VU1micro.o ../VUflags.o \ + ../MMI.o ../Vif.o ../SPR.o ../DebugTools/DisR5900asm.o ../IPU/IPU.o \ + ../DebugTools/DisVU0Micro.o ../DebugTools/DisVU1Micro.o ../CDVDiso.o ../CDVDisodrv.o \ + ../DebugTools/cpuopsDebug.o ../IPU/mpeg2lib/Idct.o ../IPU/mpeg2lib/Mpeg.o ../IPU/yuv2rgb.o \ + ../Patch.o ../Stats.o ../VUops.o \ + ../VifDma.o ../Cache.o +OBJS+= ../R3000A.o ../DebugTools/DisR3000A.o ../DebugTools/DisR3000asm.o ../PsxBios.o \ + ../PsxMem.o ../PsxInterpreter.o ../PsxCounters.o ../PsxHw.o \ + ../PsxDma.o ../Gte.o ../Sio.o ../CdRom.o ../Mdec.o \ + ../Decode_XA.o ../PsxGPU.o ../PsxSio2.o ../CDVD.o + +OBJS+= WinMain.o ini.o AboutDlg.o ConfigDlg.o McdsDlg.o PatchBrowser.o \ + DebugMemory.o Debugreg.o RDebugger.o Debugger.o CpuDlg.o ${RESOBJ} \ + ../RDebug/deci2.o ../RDebug/deci2_dbgp.o \ + ../RDebug/deci2_dcmp.o \ + ../RDebug/deci2_iloadp.o ../RDebug/deci2_netmp.o \ + ../RDebug/deci2_ttyp.o +OBJS+= ../zlib/adler32.o ../zlib/compress.o ../zlib/crc32.o ../zlib/gzio.o ../zlib/uncompr.o ../zlib/deflate.o ../zlib/trees.o \ + ../zlib/zutil.o ../zlib/inflate.o ../zlib/infback.o ../zlib/inftrees.o ../zlib/inffast.o +#../RDebug/deci2_drfp.o + +ifeq (${CPU}, ix86) + OBJS+= ../x86/iR5900.o ../ix86-32/iR5900Arit.o ../ix86-32/iR5900AritImm.o \ + ../ix86-32/iR5900Branch.o ../ix86-32/iR5900Jump.o ../ix86-32/iR5900LoadStore.o \ + ../ix86-32/iR5900Move.o ../ix86-32/iR5900MultDiv.o ../ix86-32/iR5900Shift.o \ + ../x86/recCOP2.o ../x86/iCP0.o \ + ../x86/iFPU.o ../x86/iMMI.o ../x86/iVUmicro.o \ + ../x86/iVU0micro.o ../x86/iVU1micro.o ../x86/iR3000A.o + FLAGS+= -I../ix86-32 -I../x86 + OBJS+= ../x86/ix86/ix86.o ../x86/ix86/ix86_fpu.o \ + ../x86/ix86/ix86_3dnow.o ../x86/ix86/ix86_mmx.o \ + ../x86/ix86/ix86_cpudetect.o ../x86/ix86/ix86_sse.o +endif + +DEPS:= $(OBJS:.o=.d) +ROBJS:= $(OBJS:.o=.ro) +RESROBJ:= $(RESOBJ:.o=.ro) +RSOBJS:= $(OBJS:.o=.rso) +RESRSOBJ:= $(RESOBJ:.o=.rso) + +_CFLAGS = -Wall -mwindows -I. -I.. -I../zlib -I../IPU -I../DebugTools -Imingw ${FLAGS} +CFLAGS = ${_CFLAGS} ${OPTIMIZE} +CRFLAGS = ${_CFLAGS} ${ROPTIMIZE} +CRSFLAGS = ${_CFLAGS} ${RSOPTIMIZE} + +pcsx2: ${OBJS} + ${CC} ${CFLAGS} ${OBJS} -o ${PCSX2} ${LIBS} + +release: ${ROBJS} + ${CC} ${CFLAGS} ${ROBJS} -o ${PCSX2} ${LIBS} + ${STRIP} ${PCSX2} + +release-sse: ${RSOBJS} + ${CC} ${CSSEFLAGS} ${RSOBJS} -o ${PCSX2} ${LIBS} + ${STRIP} ${PCSX2} + +.PHONY: clean pcsx2 release release-sse + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} ${ROBJS} ${RSOBJS} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.ro: %.c + ${CC} ${CRFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +%.rso: %.c + ${CC} ${CRSFLAGS} -D_RELEASE -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +${RESROBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +${RESRSOBJ}: pcsx2.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +-include ${DEPS} diff --git a/branches/pcsx2_0.9.1/windows/McdsDlg.c b/branches/pcsx2_0.9.1/windows/McdsDlg.c new file mode 100644 index 0000000..f425919 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/McdsDlg.c @@ -0,0 +1,124 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + + +HWND mcdDlg; + + +void Open_Mcd_Proc(HWND hW, int mcd) { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[1024]; + char *str; + + memset(szFileName, 0, sizeof(szFileName)); + memset(szFileTitle, 0, sizeof(szFileTitle)); + memset(szFilter, 0, sizeof(szFilter)); + + + strcpy(szFilter, _("Ps2 Memory Card (*.ps2)")); + str = szFilter + strlen(szFilter) + 1; + strcpy(str, "*.ps2"); + + str+= strlen(str) + 1; + strcpy(str, _("All Files")); + str+= strlen(str) + 1; + strcpy(str, "*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hW; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = "memcards"; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "MC2"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD1 : IDC_MCD2), szFileName); + } +} + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + mcdDlg = hW; + + SetWindowText(hW, _("Memcard Manager")); + + Button_SetText(GetDlgItem(hW, IDOK), _("OK")); + Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL1), _("Select Mcd")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL2), _("Select Mcd")); + + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1")); + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2")); + + if (!strlen(Config.Mcd1)) strcpy(Config.Mcd1, "memcards\\Mcd001.ps2"); + if (!strlen(Config.Mcd2)) strcpy(Config.Mcd2, "memcards\\Mcd002.ps2"); + Edit_SetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1); + Edit_SetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_MCDSEL1: + Open_Mcd_Proc(hW, 1); + return TRUE; + case IDC_MCDSEL2: + Open_Mcd_Proc(hW, 2); + return TRUE; + case IDCANCEL: + EndDialog(hW,FALSE); + + return TRUE; + case IDOK: + Edit_GetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1, 256); + Edit_GetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2, 256); + + SaveConfig(); + + EndDialog(hW,TRUE); + + return TRUE; + } + case WM_DESTROY: + return TRUE; + } + return FALSE; +} + diff --git a/branches/pcsx2_0.9.1/windows/McdsDlg.h b/branches/pcsx2_0.9.1/windows/McdsDlg.h new file mode 100644 index 0000000..c911430 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/McdsDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MCDSDLG_H__ +#define __MCDSDLG_H__ + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __MCDSDLG_H__ */ diff --git a/branches/pcsx2_0.9.1/windows/PatchBrowser.c b/branches/pcsx2_0.9.1/windows/PatchBrowser.c new file mode 100644 index 0000000..465294a --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/PatchBrowser.c @@ -0,0 +1,352 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************** +* +* patchbrowser.c contains all the src of patchbrowser window +* no interaction with emulation code +***************************/ + +#include +#include +#include "Common.h" +#include "win32.h" +#include "resource.h" + +/* + * TODO: + * - not topmost + * - resize stuff + * - ask to save in exit (check if changed) + */ +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + int tmpi,i; + char fileName[MAX_PATH], *tmpStr; + FILE *fp; + + switch(uMsg) { + + case WM_INITDIALOG: + SetWindowText(hW, _("Patches Browser")); + Button_SetText(GetDlgItem(hW,IDC_REFRESHPATCHLIST), _("Refresh List")); + Button_SetText(GetDlgItem(hW,IDC_NEWPATCH), _("New Patch")); + Button_SetText(GetDlgItem(hW,IDC_SAVEPATCH), _("Save Patch")); + Button_SetText(GetDlgItem(hW,IDC_EXITPB), _("Exit")); + Static_SetText(GetDlgItem(hW,IDC_GAMENAMESEARCH), _("Search game name patch:")); + //List Patches + ListPatches ((HWND) hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + + case IDC_NEWPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"a")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't create the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + fclose(fp); + i = MessageBox(hW,(LPCTSTR)"File created sucessfully.\nClear textbox?",NULL,(UINT)(MB_YESNO|MB_ICONQUESTION)); + if (i==IDYES) SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)""); + + return TRUE; + + case IDC_SAVEPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"w")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't save the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + tmpi = SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_GETLINECOUNT, (WPARAM)NULL, (LPARAM)NULL); + i=0; + for (;tmpi>=0;tmpi--) + i += SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_LINELENGTH, (WPARAM)tmpi, (LPARAM)NULL); + + tmpStr = (char *) malloc(i); + sprintf(tmpStr,""); + SendDlgItemMessage(hW, IDC_PATCHTEXT, WM_GETTEXT, (WPARAM)i, (LPARAM)tmpStr); + + //remove \r + for (i=0,tmpi=0; tmpStr[i]!='\0'; i++) + if (tmpStr[i] != '\r') + tmpStr[tmpi++] = tmpStr[i]; + tmpStr[tmpi] = '\0'; + + fputs(tmpStr,fp); + + fclose(fp); + free(tmpStr); + + MessageBox(hW,(LPCTSTR)"File saved sucessfully.",NULL,(UINT)MB_ICONINFORMATION); + + return TRUE; + + case IDC_REFRESHPATCHLIST: + + //List Patches + ListPatches ((HWND) hW); + + return TRUE; + + case IDC_EXITPB: + + //Close Dialog + EndDialog(hW, FALSE); + + return TRUE; + + case IDC_PATCHCRCLIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + return ReadPatch ((HWND) hW, fileName); + + case IDC_PATCHNAMELIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + //another small hack :p + //eg. SOCOM Demo PAL (7dd01dd9.pnach) + for (i=0;i<(int)strlen(fileName);i++) + if (fileName[i] == '(') tmpi = i; + + sprintf(fileName,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + fileName[tmpi+1],fileName[tmpi+2],fileName[tmpi+3], + fileName[tmpi+4],fileName[tmpi+5],fileName[tmpi+6], + fileName[tmpi+7],fileName[tmpi+8],fileName[tmpi+9], + fileName[tmpi+10],fileName[tmpi+11],fileName[tmpi+12], + fileName[tmpi+13],fileName[tmpi+14]); + + //sanity check + if (fileName[tmpi+15] != ')') return FALSE; + + return ReadPatch ((HWND) hW, fileName); + + case IDC_SEARCHPATCHTEXT: + + //get text + SendDlgItemMessage(hW, IDC_SEARCHPATCHTEXT, EM_GETLINE, 0, (LPARAM)fileName); + //search + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)fileName); + //select match item + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_SETCURSEL, (WPARAM)tmpi, (LPARAM)NULL); + + return TRUE; + } + return TRUE; + + case WM_CLOSE: + EndDialog(hW, FALSE); + break; + + } + return FALSE; +} +void ListPatches (HWND hW) { + + int i, tmpi, filesize, totalPatch=0, totalSize=0; + char tmpStr[MAX_PATH], *fileData; + WIN32_FIND_DATA FindData; + HANDLE Find; + FILE *fp; + + //clear listbox's + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + + //sprintf(tmpStr,"%s*.pnach", Config.PatchDir) + sprintf(tmpStr, "patches\\*.pnach"); + + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + + sprintf(tmpStr,"%s", FindData.cFileName); + + //add file name to crc list + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT) LB_ADDSTRING, (WPARAM)NULL, (LPARAM)tmpStr); + + //sprintf(tmpStr,"%s%s", Config.PatchDir, FindData.cFileName) + sprintf(tmpStr,"patches\\%s", FindData.cFileName); + + fp = fopen(tmpStr, "r"); + if (fp == NULL) break; + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + totalSize += filesize; + fseek(fp, 0, SEEK_SET); + + fileData = (char *) malloc(filesize); + sprintf(fileData,""); + + //read file + while((tmpi=fgetc(fp)) != EOF) + sprintf(fileData,"%s%c",fileData,tmpi); + + //small hack :p + for(i=0;ii;tmpi--) + fileData[tmpi] = fileData[tmpi-1]; + fileData[i] = '\r'; + fileData[i+1] = '\n'; + i++; + } + } + + SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)fileData); + + sprintf(fileData,""); + fclose(fp); + + return TRUE; +} + + +//Left Trim (remove the spaces at the left of a string) +char * lTrim (char *s) { + int count=0,i,tmpi; + + for (i=0;i<(int)strlen(s); i++) { + if (s[i] == ' ') count++; + else { + for (tmpi=0;tmpi<(int)strlen(s);tmpi++) + s[tmpi] = s[tmpi+count]; + break; + } + } + return s; +} + + +BOOL Save_Patch_Proc( char * filename ) { + + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "Patch Files (*.pnach)\0*.pnach\0ALL Files (*.*)\0*.*"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "TXT"; + ofn.Flags = OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + if ( GetSaveFileName( &ofn ) ) { + + strcpy( filename, szFileName ); + + return TRUE; + } + else { + return FALSE; + } +} diff --git a/branches/pcsx2_0.9.1/windows/RDebugger.c b/branches/pcsx2_0.9.1/windows/RDebugger.c new file mode 100644 index 0000000..576cc57 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/RDebugger.c @@ -0,0 +1,375 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "RDebugger.h" +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "../rdebug/deci2.h" + +u32 port=8510; +SOCKET serversocket, remote; +char message[1024]; //message to add to listbox + +int runStatus=STOP, runCode=0, runCount=1; +HANDLE runEvent=NULL; + +DECI2_DBGP_BRK ebrk[32], + ibrk[32]; +int ebrk_count=0, + ibrk_count=0; + +int debuggedCpu=0; //default is to debug EE cpu; IOP=1 +u32 breakAddress=0; //disabled; ie. you cannot use address 0 for a breakpoint +u32 breakCycle=0; //disabled; ie. you cannot stop after 0 cycles + +int CreateSocket(HWND hDlg, int port){ + WSADATA wsadata; + SOCKADDR_IN saServer; + + if (WSAStartup( MAKEWORD(1, 1), &wsadata) || + ((serversocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET)){ + MessageBox(hDlg, "Could not create socket\n[Is TCP/IP installed? WinSock 1.1 or above?]", 0, MB_OK); + return FALSE; + } + sprintf(message, "[PCSX2] %s status=%s", wsadata.szDescription, wsadata.szSystemStatus); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + saServer.sin_family = AF_INET; + saServer.sin_addr.S_un.S_addr = INADDR_ANY; // accept any address + saServer.sin_port = htons(port); // port to listen to + + if (bind(serversocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr))==SOCKET_ERROR){ + sprintf(message, "Could not bind to port %d\n" + "[Is there another server running on that port?]", port); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Port %d is opened", port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + // SOMAXCONN connections in queque? maybe 1 is enough... + if (listen(serversocket, SOMAXCONN) == SOCKET_ERROR){ + sprintf(message, "Listening for a connection failed\n" + "[dunno?]"); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Listening for a connection to establish..."); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + cpuRegs.CP0.n.EPC=cpuRegs.pc; + psxRegs.CP0.n.EPC=psxRegs.pc; + sprintf(message, "%08X", cpuRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), message); + sprintf(message, "%08X", psxRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), message); + sprintf(message, "%d", cpuRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), message); + sprintf(message, "%d", psxRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), message); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGEE), (debuggedCpu==0)); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGIOP), (debuggedCpu==1)); + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAT), 8); //8 hex digits + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAFTER), 10);//10 decimal digits + sprintf(message, "%08X", breakAddress); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAT), message); + sprintf(message, "%d", breakCycle); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), message); + + Button_Enable(GetDlgItem(hDlg, IDC_DEBUGIOP), FALSE);//////////////////////// + + return TRUE; +} + +int readData(char *buffer){ + int r, count=0; + u8 *p=buffer; + + memset(buffer, 0, BUFFERSIZE); + while (((count+= r = recv(remote, p, BUFFERSIZE, 0))!=INVALID_SOCKET) && + (count<*(u16*)buffer)) + p+=r; + + if (r==INVALID_SOCKET) + return 0; + + return count; +} + +int writeData(char *result){ + int r;/*, i; + static char l[300], p[10]; + DECI2_HEADER *header=(DECI2_HEADER*)result; +*/ + r = send(remote, result, *(u16*)result, 0); + if (r==SOCKET_ERROR) + return 0; +/* + sprintf(l, "size=%d, src=%c dst=%c proto=0x%04X ", + header->length-8, header->source, header->destination, header->protocol); + for (i=8; i<*(u16*)result; i++){ + sprintf(p, "%02X ", result[i]); + strcat(l, p); + } + SysMessage(l); +*/ + return r; +} + +DWORD WINAPI ServingFunction(LPVOID lpParam){ + static u8 buffer[BUFFERSIZE], //a big buffer + result[BUFFERSIZE], //a big buffer + eepc[9], ioppc[9], eecy[15], iopcy[15]; + SOCKADDR_IN saClient; + HWND hDlg=(HWND)lpParam; + DWORD size=sizeof(struct sockaddr); + int exit=FALSE; + + if ((remote = accept(serversocket, (struct sockaddr*)&saClient, &size))==INVALID_SOCKET){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Commmunication lost. THE END"); + return FALSE; + } + sprintf(message, "[PCSX2] Connected to %d.%d.%d.%d on remote port %d", + saClient.sin_addr.S_un.S_un_b.s_b1, + saClient.sin_addr.S_un.S_un_b.s_b2, + saClient.sin_addr.S_un.S_un_b.s_b3, + saClient.sin_addr.S_un.S_un_b.s_b4, + saClient.sin_port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Start serving..."); + connected=1;//from this point on, all log stuff goes to ttyp + + //sendBREAK('E', 0, 0xff, 0x21, 1); //do not enable this unless you know what you are doing! + while (!exit && readData(buffer)){ + DECI2_HEADER *header=(DECI2_HEADER*)buffer; + + switch(header->protocol){ + case 0x0000:exit=TRUE; break; + case PROTO_DCMP:D2_DCMP(buffer, result, message); break; +// case 0x0120:D2_DRFP_EE(buffer, result, message); break; +// case 0x0121:D2_DRFP_IOP(buffer, result, message); break; +// case 0x0122:break; + case PROTO_IDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy); break; +// case 0x0140:break; + case PROTO_ILOADP:D2_ILOADP(buffer, result, message); break; + case PROTO_EDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy);break; +// case 0x0240:break; + case PROTO_NETMP:D2_NETMP(buffer, result, message); break; + default: + sprintf(message, "[DECI2 %c->%c/%04X] Protocol=0x%04X", + header->source, header->destination, + header->length, header->protocol); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + continue; + } + if (exit==FALSE){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), eepc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), ioppc); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), eecy); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), iopcy); + } + } + connected=0; + + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Connection closed. THE END"); + return TRUE; +} + +DWORD WINAPI Run2(LPVOID lpParam){ + HWND hDlg=(HWND)lpParam; + static char pc[9]; + int i; + + while (1){ + if (runStatus==RUN){ + if (PSMu32(cpuRegs.pc)==0x0000000D){ + sendBREAK('E', 0, runCode, 0x22, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((runCode==2) && (//next + ((PSMu32(cpuRegs.pc) & 0xFC000000)==0x0C000000) ||//JAL + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x00000009) ||//JALR + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C) //SYSCALL + )){u32 tmppc=cpuRegs.pc, skip=(PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C ? 4 : 8; + while (cpuRegs.pc!=tmppc+skip) + Cpu->Step(); + }else + Cpu->Step(); //use this with breakpoints & step-by-step +// Cpu->ExecuteBlock(); //use this to run faster, but not for stepping +// sprintf(pc, "%08X", cpuRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), pc); +// sprintf(pc, "%08X", psxRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), pc); +// sprintf(pc, "%d", cpuRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), pc); +// sprintf(pc, "%d", psxRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), pc); + if (runCount!=0 && --runCount==0){ + sendBREAK('E', 0, runCode, 0x23, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakAddress) && (breakAddress==cpuRegs.pc)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakCycle) && (breakCycle==cpuRegs.cycle)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + breakCycle=0; + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), "0"); + continue; + } + for (i=0; i +#include +#include + +#define BUFFERSIZE (128*1024) + +extern LRESULT WINAPI RemoteDebuggerParamsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern LRESULT WINAPI RemoteDebuggerProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.sln b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.sln new file mode 100644 index 0000000..78bd7db --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2003.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug TLB = Debug TLB + Release = Release + Release (to Public) = Release (to Public) + Release TLB = Release TLB + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.ActiveCfg = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.Build.0 = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.Build.0 = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).ActiveCfg = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).Build.0 = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.Build.0 = Release TLB|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.vcproj b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.vcproj new file mode 100644 index 0000000..3ec08e4 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2003.vcproj @@ -0,0 +1,1216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.sln b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.sln new file mode 100644 index 0000000..2bd4145 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug TLB|Win32 = Debug TLB|Win32 + Debug|Win32 = Debug|Win32 + Release TLB|Win32 = Release TLB|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.ActiveCfg = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.Build.0 = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.vcproj b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.vcproj new file mode 100644 index 0000000..4c03861 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005.vcproj @@ -0,0 +1,1439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.sln b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.sln new file mode 100644 index 0000000..98a5f30 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005beta1_64bits.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj new file mode 100644 index 0000000..1c3da07 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.1/windows/Win32.h b/branches/pcsx2_0.9.1/windows/Win32.h new file mode 100644 index 0000000..607396d --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/Win32.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIN32_H__ +#define __WIN32_H__ + +extern int needReset; + +AppData gApp; +HWND hStatusWnd; + +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); +void CreateMainWindow(int nCmdShow); +void RunGui(); +int LoadConfig(); +void SaveConfig(); + +BOOL Open_File_Proc(char *filename); +BOOL Pcsx2Configure(HWND hWnd); +void RunExecute(int run); +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); +void OpenConsole(); +void CloseConsole(); +#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text); + +//patch browser window +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +//cpu dialog window +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + diff --git a/branches/pcsx2_0.9.1/windows/WinMain.c b/branches/pcsx2_0.9.1/windows/WinMain.c new file mode 100644 index 0000000..76e96d3 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/WinMain.c @@ -0,0 +1,1849 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "resource.h" +#include "debugger.h" +#include "rdebugger.h" +#include "AboutDlg.h" +#include "McdsDlg.h" + +#include "VU.h" +#include "iCore.h" +#include "iVUzerorec.h" + +#define COMPILEDATE __DATE__ + +static int efile; +char filename[256]; + +static int AccBreak = 0; +int needReset = 1; +unsigned int langsMax; +typedef struct { + char lang[256]; +} _langs; +_langs *langs = NULL; + +void OpenConsole() { + COORD csize; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + SMALL_RECT srect; + + if (gApp.hConsole) return; + AllocConsole(); + SetConsoleTitle(_("Ps2 Output")); + csize.X = 100; + csize.Y = 1024; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + srect = csbiInfo.srWindow; + srect.Right = srect.Left + 99; + srect.Bottom = srect.Top + 64; + SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); + gApp.hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} + +void CloseConsole() { + if (gApp.hConsole == NULL) return; + FreeConsole(); gApp.hConsole = NULL; +} +void strcatz(char *dst, char *src) { + int len = strlen(dst) + 1; + strcpy(dst + len, src); +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def +//------------------- + +void RunExecute(int run) { + SetThreadPriority(GetCurrentThread(), Config.ThPriority); + SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); + + if (needReset == 1) { + SysReset(); + } +#if 0 //weird problem with that comment it for now + if (GSsetWindowInfo != NULL) { + winInfo info; + + info.hWnd = gApp.hWnd; + info.hMenu = gApp.hMenu; + info.hStatusWnd = hStatusWnd; + + if (GSsetWindowInfo(&info) != FALSE) { + SetMenu(gApp.hWnd, NULL); + ShowWindow(hStatusWnd, SW_HIDE); + ShowWindow(gApp.hWnd, SW_NORMAL); + } else { + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + } + } else { +#endif + AccBreak = 1; + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + //} + if (OpenPlugins() == -1) { + CreateMainWindow(SW_SHOWNORMAL); + return; + } + + if (needReset == 1) { + cpuExecuteBios(); + if (efile == 2) + efile=GetPS2ElfName(filename); + if (efile) + loadElfFile(filename); + efile=0; + needReset = 0; + } + if (run) Cpu->Execute(); +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + int i; + + for (i=0; i<5; i++) { + if (Slots[i] == -1) + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED); + else + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf (str, "sstates\\%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); + if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + StatusSet(Text); + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %d"), num+1); + else sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1); + StatusSet(Text); + + RunExecute(1); +} + +void OnStates_LoadOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + ret = LoadState(szFileName); + + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Saving State %s"), szFileName); + StatusSet(Text); + + Cpu->Execute(); + } +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +void OnStates_SaveOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + ret = SaveState(szFileName); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Loaded State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Loading State %s"), szFileName); + StatusSet(Text); + + RunExecute(1); + } +} + +#ifdef PCSX2_DEVBUILD + +TESTRUNARGS g_TestRun; + +static int ParseCommandLine(char* pcmd) +{ + const char* pdelim = " \t\r\n"; + char* token = strtok(pcmd, pdelim); + + g_TestRun.efile = 1; + + while(token != NULL) { + + if( stricmp(token, "-help") == 0) { + MessageBox(NULL, "pcsx2 [-option value]\n" + "\tPcsx2 Team 2003-2006\n\n" + "-help {display this help file}\n" + "-title [name] {run this image/iso/elf}\n" + "-image [name] {path and base name of image (do not include the .ext)}\n" + "-log [name] {log path to save log file in}\n" + "-logopt [hex] {log options in hex (see debug.h) }\n" + "-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n" + "-frame [frame] {game will run up to this frame before exiting}\n" + "-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n" + "-jpg {save images to jpg format}\n" + "-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n" + "-gs [dllpath] {specify the dll load path of the GS plugin}\n" + "-cdvd [dllpath] {specify the dll load path of the CDVD plugin}\n" + "-spu [dllpath] {specify the dll load path of the SPU2 plugin}\n", + "Help", MB_OK); + return -1; + } + else if( stricmp(token, "-title") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.ptitle = token; + } + else if( stricmp(token, "-image") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pimagename = token; + } + else if( stricmp(token, "-log") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.plogname = token; + } + else if( stricmp(token, "-logopt") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + if( token[0] == '0' && token[1] == 'x' ) token += 2; + sscanf(token, "%x", &varLog); + } + } + else if( stricmp(token, "-pad") == 0 ) { + token = strtok(NULL, pdelim); + printf("-pad ignored\n"); + } + else if( stricmp(token, "-frame") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.frame = atoi(token); + } + } + else if( stricmp(token, "-numimages") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.numimages = atoi(token); + } + } + else if( stricmp(token, "-efile") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.efile = atoi(token); + } + } + else if( stricmp(token, "-jpg") == 0 ) { + g_TestRun.jpgcapture = 1; + } + else if( stricmp(token, "-gs") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pgsdll = token; + } + else if( stricmp(token, "-cdvd") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pcdvddll = token; + } + else if( stricmp(token, "-spu") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pspudll = token; + } + else { + printf("invalid args\n"); + return -1; + } + + if( token == NULL ) { + printf("invalid args\n"); + return -1; + } + + token = strtok(NULL, pdelim); + } + + if( g_TestRun.ptitle != NULL ) + g_TestRun.enabled = 1; + + return 0; +} + +#endif + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char *lang; + int i; + +#ifdef WIN32_VIRTUAL_MEM + LPVOID lpMemReserved; + + if( !SysLoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) ) + return 0; + + lpMemReserved = VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); + + if( lpMemReserved == NULL || lpMemReserved!= PS2MEM_BASE ) { + char str[255]; + sprintf(str, "Cannot allocate mem addresses 0x20000000-0x40000000, err: %d", GetLastError()); + MessageBox(NULL, str, "SysError", MB_OK); + return 0; + } +#endif + + gApp.hInstance = hInstance; + gApp.hMenu = NULL; + gApp.hWnd = NULL; + gApp.hConsole = NULL; + +#ifdef ENABLE_NLS + bindtextdomain(PACKAGE, "Langs\\"); + textdomain(PACKAGE); +#endif + + if (LoadConfig() == -1) { + memset(&Config, 0, sizeof(Config)); + //strcpy(Config.Bios, "HLE"); + strcpy(Config.BiosDir, "Bios\\"); + strcpy(Config.PluginsDir, "Plugins\\"); + Config.Patch = 1; + + SysMessage(_("Pcsx2 needs to be configured")); + Pcsx2Configure(NULL); + + return 0; + } + if (Config.Lang[0] == 0) { + strcpy(Config.Lang, "en_US"); + } + + langs = (_langs*)malloc(sizeof(_langs)); + strcpy(langs[0].lang, "en_US"); + InitLanguages(); i=1; + while ((lang = GetLanguageNext()) != NULL) { + langs = (_langs*)realloc(langs, sizeof(_langs)*(i+1)); + strcpy(langs[i].lang, lang); + i++; + } + CloseLanguages(); + langsMax = i; + + if (Config.PsxOut) OpenConsole(); + +#ifdef PCSX2_DEVBUILD + memset(&g_TestRun, 0, sizeof(g_TestRun)); + + if( lpCmdLine == NULL || *lpCmdLine == 0 ) + SysPrintf("-help to see arguments\n"); + else if( ParseCommandLine(lpCmdLine) == -1 ) { + return 2; + } + + if( g_TestRun.pgsdll ) + _snprintf(Config.GS, sizeof(Config.GS), "%s", g_TestRun.pgsdll); + if( g_TestRun.pcdvddll ) + _snprintf(Config.CDVD, sizeof(Config.CDVD), "%s", g_TestRun.pcdvddll); + if( g_TestRun.pspudll ) + _snprintf(Config.SPU2, sizeof(Config.SPU2), "%s", g_TestRun.pspudll); +#endif + + if (SysInit() == -1) return 1; + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled ) { + // run without ui + _snprintf(filename, sizeof(filename), "%s", g_TestRun.ptitle); + needReset = 1; + efile = g_TestRun.efile; + RunExecute(1); + SysClose(); + return 0; // success! + } +#endif + + CreateMainWindow(nCmdShow); + + RunGui(); + +#ifdef WIN32_VIRTUAL_MEM + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); +#endif + + return 0; +} + +void RunGui() { + MSG msg; + + for (;;) { + if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + Sleep(10); + } +} + +#define NUM_STATES 10 +int StatesC = 0; +extern void iDumpRegisters(u32 startpc, u32 temp); + +void CALLBACK KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case VK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); + break; + case VK_F2: + if( (GetKeyState(VK_SHIFT)&0x8000) ) + StatesC = (StatesC+NUM_STATES-1)%NUM_STATES; + else + StatesC = (StatesC+1)%NUM_STATES; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); + if( GSchangeSaveState != NULL ) { + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + GSchangeSaveState(StatesC, Text); + } + break; + case VK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); + break; + // note: VK_F5-VK_F7 are reserved for GS + case VK_F8: + GSmakeSnapshot("snap\\"); + break; + +#ifdef PCSX2_DEVBUILD + case VK_F11: + { + int num; + FILE* f; + BASEBLOCKEX** ppblocks = GetAllBaseBlocks(&num, 0); + + f = fopen("perflog.txt", "w"); + while(num-- > 0 ) { + if( ppblocks[0]->visited > 0 ) { + fprintf(f, "%u %u %u %u\n", ppblocks[0]->startpc, (u32)(ppblocks[0]->ltime.QuadPart / ppblocks[0]->visited), ppblocks[0]->visited, ppblocks[0]->size); + } + ppblocks[0]->visited = 0; + ppblocks[0]->ltime.QuadPart = 0; + ppblocks++; + } + fclose(f); + SysPrintf("perflog.txt written\n"); + break; + } + case VK_F12: + iDumpRegisters(cpuRegs.pc, 0); + SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc); + break; +#endif + + case VK_ESCAPE: + ClosePlugins(); + CreateMainWindow(SW_SHOWNORMAL); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +#ifdef PCSX2_DEVBUILD + +BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { + int i; + switch (message) { + case WM_INITDIALOG: + for (i=0; i<32; i++) + if (varLog & (1<= ID_LANGS && LOWORD(wParam) <= (ID_LANGS + langsMax)) { + AccBreak = 1; + DestroyWindow(gApp.hWnd); + ChangeLanguage(langs[LOWORD(wParam) - ID_LANGS].lang); + CreateMainWindow(SW_NORMAL); + return TRUE; + } + } + break; + case WM_DESTROY: + if (!AccBreak) { + SysClose(); + DeleteObject(hbitmap_background); + PostQuitMessage(0); + exit(0); + } else AccBreak = 0; + return TRUE; + + case WM_QUIT: + if (Config.PsxOut) CloseConsole(); + exit(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + return FALSE; +} + +#define _ADDSUBMENU(menu, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDSUBMENU(menun, string) \ + _ADDSUBMENU(gApp.hMenu, menun, string); + +#define ADDSUBMENUS(submn, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDMENUITEM(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDMENUITEMC(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED | MFS_CHECKED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDSEPARATOR(menun) \ + item.fMask = MIIM_TYPE; \ + item.fType = MFT_SEPARATOR; \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +void CreateMainMenu() { + MENUITEMINFO item; + HMENU submenu[5]; + char buf[256]; + int i; + + item.cbSize = sizeof(MENUITEMINFO); + item.dwTypeData = buf; + item.cch = 256; + + gApp.hMenu = CreateMenu(); + + //submenu = CreatePopupMenu(); + //AppendMenu(gApp.hMenu, MF_STRING | MF_POPUP, (UINT)submenu, _("&File")); + ADDSUBMENU(0, _("&File")); + ADDMENUITEM(0, _("E&xit"), ID_FILE_EXIT); + ADDSEPARATOR(0); + ADDSUBMENUS(0, 1, _("&States")); + ADDSEPARATOR(0); + ADDMENUITEM(0, _("&Open ELF File"), ID_FILEOPEN); + ADDMENUITEM(0, _("&Run CD"), ID_FILE_RUNCD); + ADDSUBMENUS(1, 3, _("&Save")); + ADDSUBMENUS(1, 2, _("&Load")); + ADDMENUITEM(2, _("&Other..."), ID_FILE_STATES_LOAD_OTHER); + ADDMENUITEM(2, _("Slot &5"), ID_FILE_STATES_LOAD_SLOT5); + ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT4); + ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT3); + ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT2); + ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT1); + ADDMENUITEM(3, _("&Other..."), ID_FILE_STATES_SAVE_OTHER); + ADDMENUITEM(3, _("Slot &5"), ID_FILE_STATES_SAVE_SLOT5); + ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT4); + ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT3); + ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT2); + ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT1); + + ADDSUBMENU(0, _("&Run")); + + ADDSUBMENUS(0, 1, _("&Process Priority")); + ADDMENUITEM(1, _("&Low"), ID_PROCESSLOW ); + ADDMENUITEM(1, _("High"), ID_PROCESSHIGH); + ADDMENUITEM(1, _("Normal"), ID_PROCESSNORMAL); + ADDMENUITEM(0,_("&Arguments"), ID_RUN_CMDLINE); + ADDMENUITEM(0,_("Re&set"), ID_RUN_RESET); + ADDMENUITEM(0,_("E&xecute"), ID_RUN_EXECUTE); + + ADDSUBMENU(0,_("&Config")); +#ifdef PCSX2_DEVBUILD + ADDMENUITEM(0,_("&Advanced"), ID_CONFIG_ADVANCED); +#endif + ADDMENUITEM(0,_("&Patches"), ID_PATCHBROWSER); + ADDMENUITEM(0,_("C&pu"), ID_CONFIG_CPU); + ADDMENUITEM(0,_("&Memcards"), ID_CONFIG_MEMCARDS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("Fire&Wire"), ID_CONFIG_FW); + ADDMENUITEM(0,_("U&SB"), ID_CONFIG_USB); + ADDMENUITEM(0,_("D&ev9"), ID_CONFIG_DEV9); + ADDMENUITEM(0,_("C&dvdrom"), ID_CONFIG_CDVDROM); + ADDMENUITEM(0,_("&Sound"), ID_CONFIG_SOUND); + ADDMENUITEM(0,_("C&ontrollers"), ID_CONFIG_CONTROLLERS); + ADDMENUITEM(0,_("&Graphics"), ID_CONFIG_GRAPHICS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("&Configure"), ID_CONFIG_CONFIGURE); + + ADDSUBMENU(0,_("&Language")); + + for (i=langsMax-1; i>=0; i--) { + if (!strcmp(Config.Lang, langs[i].lang)) { + ADDMENUITEMC(0,ParseLang(langs[i].lang), ID_LANGS + i); + } else { + ADDMENUITEM(0,ParseLang(langs[i].lang), ID_LANGS + i); + } + } + +#ifdef PCSX2_DEVBUILD + ADDSUBMENU(0, _("&Debug")); + ADDMENUITEM(0,_("&Logging"), ID_DEBUG_LOGGING); + ADDMENUITEM(0,_("Memory Dump"), ID_DEBUG_MEMORY_DUMP); + ADDMENUITEM(0,_("&Remote Debugging"), ID_DEBUG_REMOTEDEBUGGING); + ADDMENUITEM(0,_("Enter &Debugger..."), ID_DEBUG_ENTERDEBUGGER); +#endif + + ADDSUBMENU(0, _("&Misc")); + ADDMENUITEM(0,("Enable &Patches"), ID_PATCHES); + ADDMENUITEM(0,("Enable &Console"), ID_CONSOLE); + + + ADDSUBMENU(0, _("&Help")); + ADDMENUITEM(0,_("&Compatibility List..."), ID_HELP_HELP); + ADDMENUITEM(0,_("&About..."), ID_HELP_ABOUT); + +#ifndef PCSX2_DEVBUILD + EnableMenuItem(GetSubMenu(gApp.hMenu, 4), ID_DEBUG_LOGGING, MF_GRAYED); +#endif +} + +void CreateMainWindow(int nCmdShow) { + WNDCLASS wc; + HWND hWnd; + char buf[256]; + char COMPILER[20]=""; + BITMAP bm; + RECT rect; + int w, h; + +#ifdef _MSC_VER + sprintf(COMPILER, "(VC%d)", (_MSC_VER+100)/200);//hacky:) works for VC6 & VC.NET +#elif __BORLANDC__ + sprintf(COMPILER, "(BC)"); +#endif + /* Load Background Bitmap from the ressource */ + hbitmap_background = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + + wc.lpszClassName = "PCSX2 Main"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = gApp.hInstance; + wc.hIcon = LoadIcon(gApp.hInstance, MAKEINTRESOURCE(IDI_ICON)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_MENUTEXT); + wc.lpszMenuName = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + + RegisterClass(&wc); + GetObject(hbitmap_background, sizeof(bm), &bm); + + { +#ifdef WIN32_VIRTUAL_MEM + const char* pvm = "VM"; +#else + const char* pvm = "non VM"; +#endif + +#ifdef PCSX2_DEVBUILD + sprintf(buf, _("PCSX2 %s Watermoose - %s Compile Date - %s %s"), PCSX2_VERSION, pvm, COMPILEDATE, COMPILER); +#else + sprintf(buf, _("PCSX2 %s Watermoose - %s"), PCSX2_VERSION, pvm); +#endif + } + + hWnd = CreateWindow("PCSX2 Main", + buf, WS_OVERLAPPED | WS_SYSMENU, + 20, 20, 320, 240, NULL, NULL, + gApp.hInstance, NULL); + + gApp.hWnd = hWnd; + ResetMenuSlots(); + CreateMainMenu(); + + SetMenu(gApp.hWnd, gApp.hMenu); + if(Config.ThPriority==THREAD_PRIORITY_NORMAL) CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_HIGHEST) CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_LOWEST) CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); + if(Config.PsxOut) CheckMenuItem(gApp.hMenu,ID_CONSOLE,MF_CHECKED); + if(Config.Patch) CheckMenuItem(gApp.hMenu,ID_PATCHES,MF_CHECKED); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "PCSX2 %s", PCSX2_VERSION); + StatusSet(buf); + + w = bm.bmWidth; h = bm.bmHeight; + GetWindowRect(hStatusWnd, &rect); + h+= rect.bottom - rect.top; + GetMenuItemRect(hWnd, gApp.hMenu, 0, &rect); + h+= rect.bottom - rect.top; + MoveWindow(hWnd, 20, 20, w, h, TRUE); + + DestroyWindow(hStatusWnd); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot", PCSX2_VERSION); + StatusSet(buf); + ShowWindow(hWnd, nCmdShow); + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} + +BOOL Open_File_Proc(char * filename) { + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "ELF"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) { + struct stat buf; + + if (stat(szFileName, &buf) != 0) { + return FALSE; + } + + strcpy(filename, szFileName); + return TRUE; + } + + return FALSE; +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetWindowText(hDlg, _("Program arguments")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); + Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); + Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); + + SetDlgItemText(hDlg, IDC_CMDLINE, args); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + char tmp[256]; + + GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); + + ZeroMemory(args, 256); + strcpy(args, tmp); + args[255]=0; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +WIN32_FIND_DATA lFindData; +HANDLE lFind; +int lFirst; + +void InitLanguages() { + lFind = FindFirstFile("Langs\\*", &lFindData); + lFirst = 1; +} + +char *GetLanguageNext() { + for (;;) { + if (!strcmp(lFindData.cFileName, ".")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + if (!strcmp(lFindData.cFileName, "..")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + break; + } + if (lFirst == 0) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + } else lFirst = 0; + if (lFind==INVALID_HANDLE_VALUE) return NULL; + + return lFindData.cFileName; +} + +void CloseLanguages() { + if (lFind!=INVALID_HANDLE_VALUE) FindClose(lFind); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +//------------------- + +static int sinit=0; + +int SysInit() { + CreateDirectory("memcards", NULL); + CreateDirectory("sstates", NULL); +#ifdef EMU_LOG + CreateDirectory("logs", NULL); + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.plogname != NULL ) + emuLog = fopen(g_TestRun.plogname, "w"); + if( emuLog == NULL ) + emuLog = fopen("logs\\emuLog.txt","w"); +#endif + + if( emuLog != NULL ) + setvbuf(emuLog, NULL, _IONBF, 0); + +#endif + if (cpuInit() == -1) return -1; + + while (LoadPlugins() == -1) { + if (Pcsx2Configure(NULL) == FALSE) { + exit(1); + } + } + + sinit=1; + + return 0; +} + +void SysReset() { + if (sinit == 0) return; + StatusSet(_("Resetting...")); + cpuReset(); + StatusSet(_("Ready")); +} + + +void SysClose() { + if (sinit == 0) return; + cpuShutdown(); + ReleasePlugins(); + sinit=0; +} + +int concolors[] = { + 0, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_GREEN | FOREGROUND_RED, + FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +}; + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + char *ptr; + DWORD tmp; + int len, s; + int i, j; + + if (Config.PsxOut == 0) return; + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + msg[511] = '\0'; + va_end(list); + + ptr = msg; len = strlen(msg); + for (i=0, j=0; i 0x7ffe) // String is too large + return FALSE; + } + + // Store the string. + pLsaString->Buffer = (WCHAR *)pwszString; + pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR); + pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR); + + return TRUE; +} + +PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucName; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList; + //LSA_TRUST_INFORMATION myDomain; + NTSTATUS ntsResult; + PWCHAR DomainString = NULL; + + // Initialize an LSA_UNICODE_STRING with the name. + if (!InitLsaString(&lucName, AccountName)) + { + wprintf(L"Failed InitLsaString\n"); + return NULL; + } + + ntsResult = LsaLookupNames2( + PolicyHandle, // handle to a Policy object + 0, + 1, // number of names to look up + &lucName, // pointer to an array of names + &lrdlDomainList, // receives domain information + <sTranslatedSID // receives relative SIDs + ); + if (0 != ntsResult) + { + wprintf(L"Failed LsaLookupNames - %lu \n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + + // Get the domain the account resides in. +// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex]; +// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1); +// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length); + + // Display the relative Id. +// wprintf(L"Relative Id is %lu in domain %ws.\n", +// ltsTranslatedSID->RelativeId, +// DomainString); + + LsaFreeMemory(lrdlDomainList); + + return ltsTranslatedSID; +} + +BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucPrivilege; + NTSTATUS ntsResult; + + // Create an LSA_UNICODE_STRING for the privilege name(s). + if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege")) + { + wprintf(L"Failed InitLsaString\n"); + return FALSE; + } + + ntsResult = LsaAddAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID. + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + if (ntsResult == 0) + { + wprintf(L"Privilege added.\n"); + } + else + { + int err = LsaNtStatusToWinError(ntsResult); + char str[255]; + _snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult)); + MessageBox(NULL, str, "Privilege error", MB_OK); + return FALSE; + } + + return TRUE; +} + +#define TARGET_SYSTEM_NAME L"mysystem" +LSA_HANDLE GetPolicyHandle() +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR SystemName[] = TARGET_SYSTEM_NAME; + USHORT SystemNameLength; + LSA_UNICODE_STRING lusSystemName; + NTSTATUS ntsResult; + LSA_HANDLE lsahPolicyHandle; + + // Object attributes are reserved, so initialize to zeroes. + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + //Initialize an LSA_UNICODE_STRING to the server name. + SystemNameLength = wcslen(SystemName); + lusSystemName.Buffer = SystemName; + lusSystemName.Length = SystemNameLength * sizeof(WCHAR); + lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR); + + // Get a handle to the Policy object. + ntsResult = LsaOpenPolicy( + NULL, //Name of the target system. + &ObjectAttributes, //Object attributes. + POLICY_ALL_ACCESS, //Desired access permissions. + &lsahPolicyHandle //Receives the policy handle. + ); + + if (ntsResult != 0) + { + // An error occurred. Display it as a win32 error code. + wprintf(L"OpenPolicy returned %lu\n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + return lsahPolicyHandle; +} + + +/***************************************************************** + LoggedSetLockPagesPrivilege: a function to obtain, if possible, or + release the privilege of locking physical pages. + + Inputs: + + HANDLE hProcess: Handle for the process for which the + privilege is needed + + BOOL bEnable: Enable (TRUE) or disable? + + Return value: TRUE indicates success, FALSE failure. + +*****************************************************************/ +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable) +{ + struct { + u32 Count; + LUID_AND_ATTRIBUTES Privilege [1]; + } Info; + + HANDLE Token; + BOOL Result; + + // Open the token. + + Result = OpenProcessToken ( hProcess, + TOKEN_ADJUST_PRIVILEGES, + & Token); + + if( Result != TRUE ) { + SysPrintf( "Cannot open process token.\n" ); + return FALSE; + } + + // Enable or disable? + + Info.Count = 1; + if( bEnable ) + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + } + else + { + Info.Privilege[0].Attributes = 0; + } + + // Get the LUID. + Result = LookupPrivilegeValue ( NULL, + SE_LOCK_MEMORY_NAME, + &(Info.Privilege[0].Luid)); + + if( Result != TRUE ) + { + SysPrintf( "Cannot get privilege value for %s.\n", SE_LOCK_MEMORY_NAME ); + return FALSE; + } + + // Adjust the privilege. + + Result = AdjustTokenPrivileges ( Token, FALSE, + (PTOKEN_PRIVILEGES) &Info, + 0, NULL, NULL); + + // Check the result. + if( Result != TRUE ) + { + SysPrintf ("Cannot adjust token privileges, error %u.\n", GetLastError() ); + return FALSE; + } + else + { + if( GetLastError() != ERROR_SUCCESS ) + { + + BOOL bSuc = FALSE; + LSA_HANDLE policy; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + + if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) ) + return FALSE; + + policy = GetPolicyHandle(); + + if( policy != NULL ) { + + ltsTranslatedSID = GetSIDInformation(s_szUserName, policy); + + if( ltsTranslatedSID != NULL ) { + bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy); + LsaFreeMemory(ltsTranslatedSID); + } + + LsaClose(policy); + } + + if( bSuc ) { + // Get the LUID. + LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)); + + bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL); + } + + if( bSuc ) { + if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n" + "Log off/on and run pcsx2 again. Do you want to log off?\n", + "Privilege changed query", MB_YESNO) == IDYES ) { + ExitWindows(EWX_LOGOFF, 0); + } + } + else { + MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n" + "Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n" + "Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n" + "Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n" + "(zerofrog)\n", "Virtual Memory Access Denied", MB_OK); + return FALSE; + } + } + } + + CloseHandle( Token ); + + return TRUE; +} + +static u32 s_dwPageSize = 0; +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock) +{ + ULONG_PTR NumberOfPagesInitial; // initial number of pages requested + int PFNArraySize; // memory to request for PFN array + BOOL bResult; + + assert( pblock != NULL ); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); + + if( s_dwPageSize == 0 ) { + SYSTEM_INFO sSysInfo; // useful system information + GetSystemInfo(&sSysInfo); // fill the system information structure + s_dwPageSize = sSysInfo.dwPageSize; + + if( s_dwPageSize != 0x1000 ) { + SysMessage("Error! OS page size must be 4Kb!\n" + "If for some reason the OS cannot have 4Kb pages, then will need\n" + "to add a special translation LUT in pcsx2 (which will slow things down a LOT!)"); + return -1; + } + } + + // Calculate the number of pages of memory to request. + pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize; + PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR); + + pblock->aPFNs = (ULONG_PTR *) HeapAlloc (GetProcessHeap (), 0, PFNArraySize); + + if (pblock->aPFNs == NULL) { + SysPrintf("Failed to allocate on heap.\n"); + goto eCleanupAndExit; + } + + // Allocate the physical memory. + NumberOfPagesInitial = pblock->NumberPages; + bResult = AllocateUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( bResult != TRUE ) + { + SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + if( NumberOfPagesInitial != pblock->NumberPages ) + { + SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial ); + goto eCleanupAndExit; + } + + pblock->aVFNs = (ULONG_PTR*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); + + return 0; + +eCleanupAndExit: + SysPhysicalFree(pblock); + return -1; +} + +void SysPhysicalFree(PSMEMORYBLOCK* pblock) +{ + assert( pblock != NULL ); + + // Free the physical pages. + FreeUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs); + if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); +} + +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + BOOL bResult; + ULONG_PTR i; + + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE ); + if( lpMemReserved == NULL || base != lpMemReserved ) + { + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); + goto eCleanupAndExit; + } + + // Map the physical memory into the window. + bResult = MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); + + for(i = 0; i < pblock->NumberPages; ++i) + pblock->aVFNs[i] = (ULONG_PTR)base + 0x1000*i; + + if( bResult != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to map, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + return 0; + +eCleanupAndExit: + SysVirtualFree(base, size); + return -1; +} + +void SysVirtualFree(void* lpMemReserved, u32 size) +{ + // unmap + if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to unmap, error %u.\n", GetLastError() ); + return; + } + + // Free virtual memory. + VirtualFree( lpMemReserved, 0, MEM_RELEASE ); +} + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + // Reserve the virtual memory. + VirtualProtect( base, size, PAGE_READWRITE, NULL ); + MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); +} + +void SysVirtualProtectFree(void* lpMemReserved, u32 size) +{ + VirtualProtect(lpMemReserved, 0x1000, PAGE_NOACCESS, NULL); + MapUserPhysicalPages( lpMemReserved, size/s_dwPageSize, NULL ); +} + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray) +{ + BOOL bResult = MapUserPhysicalPages(Addr, NumPages, PageArray); + +#ifdef _DEBUG + //if( !bResult ) + //__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError()); +#endif + + return bResult; +} + +#else + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/windows/afxresmw.h b/branches/pcsx2_0.9.1/windows/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/branches/pcsx2_0.9.1/windows/ini.c b/branches/pcsx2_0.9.1/windows/ini.c new file mode 100644 index 0000000..9bc404a --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/ini.c @@ -0,0 +1,173 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* +15-09-2004 : file rewriten for work with inis (shadow) +*/ + +#include +#include +#include +#include "Common.h" +#include "win32.h" +#include + +int LoadConfig() { + FILE *fp; + +#ifdef ENABLE_NLS + char text[256]; + extern int _nl_msg_cat_cntr; +#endif + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return -1; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + fp=fopen("inis\\pcsx2.ini","rt");//check if pcsx2.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + return -1; + } + fclose(fp); + //interface + GetPrivateProfileString("Interface", "Bios", NULL, szValue, 256, szIniFile); + strcpy(Conf->Bios, szValue); + GetPrivateProfileString("Interface", "Lang", NULL, szValue, 256, szIniFile); + strcpy(Conf->Lang, szValue); + GetPrivateProfileString("Interface", "Ps2Out", NULL, szValue, 20, szIniFile); + Conf->PsxOut = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "ThPriority", NULL, szValue, 20, szIniFile); + Conf->ThPriority = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "PluginsDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->PluginsDir, szValue); + GetPrivateProfileString("Interface", "BiosDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->BiosDir, szValue); + GetPrivateProfileString("Interface", "Mcd1", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd1, szValue); + GetPrivateProfileString("Interface", "Mcd2", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd2, szValue); + //plugins + GetPrivateProfileString("Plugins", "GS", NULL, szValue, 256, szIniFile); + strcpy(Conf->GS, szValue); + GetPrivateProfileString("Plugins", "SPU2", NULL, szValue, 256, szIniFile); + strcpy(Conf->SPU2, szValue); + GetPrivateProfileString("Plugins", "CDVD", NULL, szValue, 256, szIniFile); + strcpy(Conf->CDVD, szValue); + GetPrivateProfileString("Plugins", "PAD1", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD1, szValue); + GetPrivateProfileString("Plugins", "PAD2", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD2, szValue); + GetPrivateProfileString("Plugins", "DEV9", NULL, szValue, 256, szIniFile); + strcpy(Conf->DEV9, szValue); + GetPrivateProfileString("Plugins", "USB", NULL, szValue, 256, szIniFile); + strcpy(Conf->USB, szValue); + GetPrivateProfileString("Plugins", "FW", NULL, szValue, 256, szIniFile); + strcpy(Conf->FW, szValue); + //cpu + GetPrivateProfileString("Cpu Options", "Options", NULL, szValue, 20, szIniFile); + Conf->Options= (u32)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Cpu Options", "SafeCnts", NULL, szValue, 20, szIniFile); + Conf->SafeCnts = strtoul(szValue, NULL, 0); + + //Misc + GetPrivateProfileString("Misc", "Patch", NULL, szValue, 20, szIniFile); + Conf->Patch = strtoul(szValue, NULL, 10); + +#ifdef PCSX2_DEVBUILD + GetPrivateProfileString("Misc", "varLog", NULL, szValue, 20, szIniFile); + varLog = strtoul(szValue, NULL, 16); +#endif + +#ifdef ENABLE_NLS + sprintf(text, "LANGUAGE=%s", Conf->Lang); +#ifdef __MSCW32__ + gettext_putenv(text); +#else + putenv(text); +#endif +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + //interface + sprintf(szValue,"%s",Conf->Bios); + WritePrivateProfileString("Interface","Bios",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Lang); + WritePrivateProfileString("Interface","Lang",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PluginsDir); + WritePrivateProfileString("Interface","PluginsDir",szValue,szIniFile); + sprintf(szValue,"%s",Conf->BiosDir); + WritePrivateProfileString("Interface","BiosDir",szValue,szIniFile); + sprintf(szValue,"%u",Conf->PsxOut); + WritePrivateProfileString("Interface","Ps2Out",szValue,szIniFile); + sprintf(szValue,"%u",Conf->ThPriority); + WritePrivateProfileString("Interface","ThPriority",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd1); + WritePrivateProfileString("Interface","Mcd1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd2); + WritePrivateProfileString("Interface","Mcd2",szValue,szIniFile); + //plugins + sprintf(szValue,"%s",Conf->GS); + WritePrivateProfileString("Plugins","GS",szValue,szIniFile); + sprintf(szValue,"%s",Conf->SPU2); + WritePrivateProfileString("Plugins","SPU2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->CDVD); + WritePrivateProfileString("Plugins","CDVD",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD1); + WritePrivateProfileString("Plugins","PAD1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD2); + WritePrivateProfileString("Plugins","PAD2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->DEV9); + WritePrivateProfileString("Plugins","DEV9",szValue,szIniFile); + sprintf(szValue,"%s",Conf->USB); + WritePrivateProfileString("Plugins","USB",szValue,szIniFile); + sprintf(szValue,"%s",Conf->FW); + WritePrivateProfileString("Plugins","FW",szValue,szIniFile); + //cpu + sprintf(szValue,"%u", Conf->Options); + WritePrivateProfileString("Cpu Options","Options",szValue,szIniFile); + sprintf(szValue,"%u",Conf->SafeCnts); + WritePrivateProfileString("Cpu Options","SafeCnts",szValue,szIniFile); + //Misc + sprintf(szValue,"%u",Conf->Patch); + WritePrivateProfileString("Misc","Patch",szValue,szIniFile); + sprintf(szValue,"%x",varLog); + WritePrivateProfileString("Misc","varLog",szValue,szIniFile); + + +} + diff --git a/branches/pcsx2_0.9.1/windows/libs/gnu_gettext.lib b/branches/pcsx2_0.9.1/windows/libs/gnu_gettext.lib new file mode 100644 index 0000000000000000000000000000000000000000..8b3885a56b2f9d31a261c89fbd0e31d15fc51c14 GIT binary patch literal 2916 zcmcIm%}*0S6#s1t6sieCjfr2dB!s{PNNJ%MHH)HwP(D)1#miW_1)4xhuow>{UOD)e zcr=_1C;tEshIsPefwS?z4d2_H*-nSjr35CKop~QSZ{GX8H#7au^1Fr27x7WMzD=dm zQxlV^#6&&Y9+UL=cv8;Z#Q}5!(LtcY0b=_==ds_rW&y7s(nvktEBgVB+)ud+F}JY1 zl+B5m*DJ5GbIZA9XHiX1+<#N( zZ&?ITv(`hx2nds~MvAP4(uZe8SYaqbL%!h8^YZlDhcqK+!%qAzB>!0 z!fxe#WxZ+-Wryv|+~T|^H9xnB!GH1!J}xmY;O!pIFa@Vj+1{Z|pY*li>`d8IX!0&2 zP`*2Wx9?5G@w{YPQN>BJ4lxkuq-q@I5Aa7eULANYDIOwtOW!M3^tDz-B9#j6jf@rX zD&w2CN8Tx{Mw#P!qS{BxoN>kF%=w}SIdbOQTt-|5<0rI}3vaKuku{;GN+La}#m+xf zevt(q@y4y7bc;@VHvo2F&Uu}vjpXl;Ja zaLr~cKDBMK#D|gjZZNQeL5E_QR8SiB9+54Mr>I?I#?olnw`A~$tM~08+2M0W1UIE= z%Amu&QpIg}^?J3lK4TO7^Zk!*F$rj%vLVHS>w*CX+ CYG_^n literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.1/windows/libs/libintlmsc.h b/branches/pcsx2_0.9.1/windows/libs/libintlmsc.h new file mode 100644 index 0000000..fd5f482 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/libs/libintlmsc.h @@ -0,0 +1,116 @@ +/* This file is part of a Windows32 DLL Interface to: + GNU gettext - internationalization aids + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + + This file was written by Franco Bez + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* REPLACEMENT FOR ORIGINAL LIBINTL.H for use with Windows32 */ + +#if !defined(__LIBINTL_H_INCLUDED) +#define __LIBINTL_H_INCLUDED + +#if defined(__cplusplus) +extern "C" { +#endif + +/* See if we allready know what we want static or dll linkage or none at all*/ +#if defined DONT_USE_GETTEXT || ( defined USE_SAFE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) || ( defined USE_GETTEXT_DLL && defined USE_SAFE_GETTEXT_DLL ) || ( defined USE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) +/* TWO IS HARDLY POSSIBLE */ +#undef USE_GETTEXT_DLL +#undef USE_GETTEXT_STATIC +#undefd USE_SAFE_GETTEXT_DLL +#endif /* MORE THAN ONE - OR NONE AT ALL */ + +#if !defined USE_GETTEXT_DLL && !defined USE_SAFE_GETTEXT_DLL && !defined USE_GETTEXT_STATIC && !defined DONT_USE_GETTEXT +/* not explicitly defined so try to guess it - + if GNUC is used - we use static linkage by default + because at the moment this is the only plattform + for which a static lib is available + else we use the DLL built with GNUC */ +# if defined __GNUC__ +# define USE_GETTEXT_STATIC +# else +# define USE_GETTEXT_DLL +# endif /* __GNUC__ */ +#endif /* NONE */ + +/* NOW ONLY ONE OF + DONT_USE_GETTEXT , USE_GETTEXT_DLL , USE_SAFE_GETTEXT_DLL , USE_GETTEXT_STATIC + IS DEFINED */ + +#if defined USE_GETTEXT_DLL +/* exported functions in DLL gnu_gettext.dll + you should link with import library + -lgnu_gettext (for mingw32) OR gnu_gettext.lib (MSVC) */ +__declspec(dllimport) char *gettext(const char *__msgid); +__declspec(dllimport) char *dgettext(const char *__domainname,const char *__msgid); +__declspec(dllimport) char *dcgettext(const char *__domainname,const char *__msgid, int __category); +__declspec(dllimport) char *textdomain(const char *__domainname); +__declspec(dllimport) char *bindtextdomain(const char *__domainname,const char *__dirname); +/* calling _putenv from within the DLL */ +__declspec(dllexport) int gettext_putenv(const char *envstring); +#endif /* DLL */ + +#if defined USE_SAFE_GETTEXT_DLL +/* Uses DLL gnu_gettext.dll ONLY if present, otherwise NO translation will take place + you should link with "safe_gettext_dll.o -lstdc++" see README for safe_gettext_dll for Details */ +/* The safe gettext functions */ +extern char *gettext(const char *szMsgId); +extern char *dgettext(const char *szDomain,const char *szMsgId); +extern char *dcgettext(const char *szDomain,const char *szMsgId,int iCategory); +extern char *textdomain(const char *szDomain); +extern char *bindtextdomain(const char *szDomain,const char *szDirectory); +/* calling _putenv from within the DLL */ +extern int gettext_putenv(const char *envstring); +#endif /* SAFE DLL */ + +#if defined USE_GETTEXT_STATIC +/* exported functions in static library libintl.a + and supporting macros + you should link with -lintl (mingw32) */ +extern char *gettext__(const char *__msgid); +extern char *dgettext__(const char *__domainname,const char *__msgid); +extern char *dcgettext__(const char *__domainname,const char *__msgid, int __category); +extern char *textdomain__(const char *__domainname); +extern char *bindtextdomain__(const char *__domainname,const char *__dirname); +#define gettext(szMsgId) gettext__(szMsgId) +#define dgettext(szDomain,szMsgId) dgettext__(szDomain,szMsgId) +#define dcgettext(szDomain,szMsgId,iCategory) dcgettext__(szDomain,szMsgId,iCategory) +#define textdomain(szDomain) textdomain__(szDomain) +#define bindtextdomain(szDomain,szDirectory) bindtextdomain__(szDomain,szDirectory) +// dummy - for static linkage - calling _putenv from within the DLL +#define gettext_putenv(a) _putenv(a) +#endif /* STATIC */ + +#if defined DONT_USE_GETTEXT +/* DON'T USE GETTEXT AT ALL + MAKROS TO MAKE CODE COMPILE WELL, BUT GETTEXT WILL NOT BE USESD +*/ +# define gettext(Msgid) (Msgid) +# define dgettext(Domainname, Msgid) (Msgid) +# define dcgettext(Domainname, Msgid, Category) (Msgid) +# define textdomain(Domainname) ((char *) Domainname) +# define bindtextdomain(Domainname, Dirname) ((char *) Dirname) +// dummy - for static linkage - calling _putenv from within the DLL +# define gettext_putenv(a) _putenv(a) +#endif /* DON'T USE AT ALL */ + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /*!defined(__LIBINTL_H_INCLUDED)*/ diff --git a/branches/pcsx2_0.9.1/windows/libs/pthread.h b/branches/pcsx2_0.9.1/windows/libs/pthread.h new file mode 100644 index 0000000..a0add29 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/libs/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,7,0,0 +#define PTW32_VERSION_STRING "2, 7, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/branches/pcsx2_0.9.1/windows/libs/pthreadVC2.lib b/branches/pcsx2_0.9.1/windows/libs/pthreadVC2.lib new file mode 100644 index 0000000000000000000000000000000000000000..b447a8b71ec31903598669991dac05f24ace9f25 GIT binary patch literal 29280 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 literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.1/windows/libs/sched.h b/branches/pcsx2_0.9.1/windows/libs/sched.h new file mode 100644 index 0000000..10ecb5d --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/libs/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/branches/pcsx2_0.9.1/windows/libs/semaphore.h b/branches/pcsx2_0.9.1/windows/libs/semaphore.h new file mode 100644 index 0000000..ea42ce3 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/libs/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/branches/pcsx2_0.9.1/windows/mingw/Makefile.win b/branches/pcsx2_0.9.1/windows/mingw/Makefile.win new file mode 100644 index 0000000..7449952 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/Makefile.win @@ -0,0 +1,348 @@ +# Project: pcsx2 +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//pcsx2_private.res +OBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LINKOBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LIBS = -mwindows -Wall -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -s +INCS = -I"../../" -I"C:/Documents and Settings/shadow/Desktop/Npcsx2" -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +CXXINCS = -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +BIN = pcsx2.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -D__WIN32__ -D__MINGW32__ -O3 -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before pcsx2.exe all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o "pcsx2.exe" $(LIBS) + +Obj//AboutDlg.o: ../AboutDlg.c + $(CC) -c ../AboutDlg.c -o Obj//AboutDlg.o $(CFLAGS) + +Obj//ConfigDlg.o: ../ConfigDlg.c + $(CC) -c ../ConfigDlg.c -o Obj//ConfigDlg.o $(CFLAGS) + +Obj//CpuDlg.o: ../CpuDlg.c + $(CC) -c ../CpuDlg.c -o Obj//CpuDlg.o $(CFLAGS) + +Obj//Debugger.o: ../Debugger.c + $(CC) -c ../Debugger.c -o Obj//Debugger.o $(CFLAGS) + +Obj//DebugMemory.o: ../DebugMemory.c + $(CC) -c ../DebugMemory.c -o Obj//DebugMemory.o $(CFLAGS) + +Obj//Debugreg.o: ../Debugreg.c + $(CC) -c ../Debugreg.c -o Obj//Debugreg.o $(CFLAGS) + +Obj//ini.o: ../ini.c + $(CC) -c ../ini.c -o Obj//ini.o $(CFLAGS) + +Obj//McdsDlg.o: ../McdsDlg.c + $(CC) -c ../McdsDlg.c -o Obj//McdsDlg.o $(CFLAGS) + +Obj//PatchBrowser.o: ../PatchBrowser.c + $(CC) -c ../PatchBrowser.c -o Obj//PatchBrowser.o $(CFLAGS) + +Obj//RDebugger.o: ../RDebugger.c + $(CC) -c ../RDebugger.c -o Obj//RDebugger.o $(CFLAGS) + +Obj//WinMain.o: ../WinMain.c + $(CC) -c ../WinMain.c -o Obj//WinMain.o $(CFLAGS) + +Obj//Idct.o: ../../IPU/Idct.c + $(CC) -c ../../IPU/Idct.c -o Obj//Idct.o $(CFLAGS) + +Obj//IPU.o: ../../IPU/IPU.c + $(CC) -c ../../IPU/IPU.c -o Obj//IPU.o $(CFLAGS) + +Obj//Mpeg.o: ../../IPU/Mpeg.c + $(CC) -c ../../IPU/Mpeg.c -o Obj//Mpeg.o $(CFLAGS) + +Obj//yuv2rgb.o: ../../IPU/yuv2rgb.c + $(CC) -c ../../IPU/yuv2rgb.c -o Obj//yuv2rgb.o $(CFLAGS) + +Obj//cpuopsDebug.o: ../../DebugTools/cpuopsDebug.c + $(CC) -c ../../DebugTools/cpuopsDebug.c -o Obj//cpuopsDebug.o $(CFLAGS) + +Obj//DisR3000A.o: ../../DebugTools/DisR3000A.c + $(CC) -c ../../DebugTools/DisR3000A.c -o Obj//DisR3000A.o $(CFLAGS) + +Obj//DisR3000asm.o: ../../DebugTools/DisR3000asm.c + $(CC) -c ../../DebugTools/DisR3000asm.c -o Obj//DisR3000asm.o $(CFLAGS) + +Obj//DisR5900.o: ../../DebugTools/DisR5900.c + $(CC) -c ../../DebugTools/DisR5900.c -o Obj//DisR5900.o $(CFLAGS) + +Obj//DisR5900asm.o: ../../DebugTools/DisR5900asm.c + $(CC) -c ../../DebugTools/DisR5900asm.c -o Obj//DisR5900asm.o $(CFLAGS) + +Obj//DisVU0Micro.o: ../../DebugTools/DisVU0Micro.c + $(CC) -c ../../DebugTools/DisVU0Micro.c -o Obj//DisVU0Micro.o $(CFLAGS) + +Obj//DisVU1Micro.o: ../../DebugTools/DisVU1Micro.c + $(CC) -c ../../DebugTools/DisVU1Micro.c -o Obj//DisVU1Micro.o $(CFLAGS) + +Obj//adler32.o: ../../zlib/adler32.c + $(CC) -c ../../zlib/adler32.c -o Obj//adler32.o $(CFLAGS) + +Obj//compress.o: ../../zlib/compress.c + $(CC) -c ../../zlib/compress.c -o Obj//compress.o $(CFLAGS) + +Obj//crc32.o: ../../zlib/crc32.c + $(CC) -c ../../zlib/crc32.c -o Obj//crc32.o $(CFLAGS) + +Obj//deflate.o: ../../zlib/deflate.c + $(CC) -c ../../zlib/deflate.c -o Obj//deflate.o $(CFLAGS) + +Obj//gzio.o: ../../zlib/gzio.c + $(CC) -c ../../zlib/gzio.c -o Obj//gzio.o $(CFLAGS) + +Obj//infback.o: ../../zlib/infback.c + $(CC) -c ../../zlib/infback.c -o Obj//infback.o $(CFLAGS) + +Obj//inffast.o: ../../zlib/inffast.c + $(CC) -c ../../zlib/inffast.c -o Obj//inffast.o $(CFLAGS) + +Obj//inflate.o: ../../zlib/inflate.c + $(CC) -c ../../zlib/inflate.c -o Obj//inflate.o $(CFLAGS) + +Obj//inftrees.o: ../../zlib/inftrees.c + $(CC) -c ../../zlib/inftrees.c -o Obj//inftrees.o $(CFLAGS) + +Obj//trees.o: ../../zlib/trees.c + $(CC) -c ../../zlib/trees.c -o Obj//trees.o $(CFLAGS) + +Obj//uncompr.o: ../../zlib/uncompr.c + $(CC) -c ../../zlib/uncompr.c -o Obj//uncompr.o $(CFLAGS) + +Obj//zutil.o: ../../zlib/zutil.c + $(CC) -c ../../zlib/zutil.c -o Obj//zutil.o $(CFLAGS) + +Obj//iR5900Arit.o: ../../ix86-32/iR5900Arit.c + $(CC) -c ../../ix86-32/iR5900Arit.c -o Obj//iR5900Arit.o $(CFLAGS) + +Obj//iR5900AritImm.o: ../../ix86-32/iR5900AritImm.c + $(CC) -c ../../ix86-32/iR5900AritImm.c -o Obj//iR5900AritImm.o $(CFLAGS) + +Obj//iR5900Branch.o: ../../ix86-32/iR5900Branch.c + $(CC) -c ../../ix86-32/iR5900Branch.c -o Obj//iR5900Branch.o $(CFLAGS) + +Obj//iR5900Jump.o: ../../ix86-32/iR5900Jump.c + $(CC) -c ../../ix86-32/iR5900Jump.c -o Obj//iR5900Jump.o $(CFLAGS) + +Obj//iR5900LoadStore.o: ../../ix86-32/iR5900LoadStore.c + $(CC) -c ../../ix86-32/iR5900LoadStore.c -o Obj//iR5900LoadStore.o $(CFLAGS) + +Obj//iR5900Move.o: ../../ix86-32/iR5900Move.c + $(CC) -c ../../ix86-32/iR5900Move.c -o Obj//iR5900Move.o $(CFLAGS) + +Obj//iR5900MultDiv.o: ../../ix86-32/iR5900MultDiv.c + $(CC) -c ../../ix86-32/iR5900MultDiv.c -o Obj//iR5900MultDiv.o $(CFLAGS) + +Obj//iR5900Shift.o: ../../ix86-32/iR5900Shift.c + $(CC) -c ../../ix86-32/iR5900Shift.c -o Obj//iR5900Shift.o $(CFLAGS) + +Obj//iCP0.o: ../../x86/iCP0.c + $(CC) -c ../../x86/iCP0.c -o Obj//iCP0.o $(CFLAGS) + +Obj//iFPU.o: ../../x86/iFPU.c + $(CC) -c ../../x86/iFPU.c -o Obj//iFPU.o $(CFLAGS) + +Obj//iMMI.o: ../../x86/iMMI.c + $(CC) -c ../../x86/iMMI.c -o Obj//iMMI.o $(CFLAGS) + +Obj//iR3000A.o: ../../x86/iR3000A.c + $(CC) -c ../../x86/iR3000A.c -o Obj//iR3000A.o $(CFLAGS) + +Obj//iR5900.o: ../../x86/iR5900.c + $(CC) -c ../../x86/iR5900.c -o Obj//iR5900.o $(CFLAGS) + +Obj//iVU0micro.o: ../../x86/iVU0micro.c + $(CC) -c ../../x86/iVU0micro.c -o Obj//iVU0micro.o $(CFLAGS) + +Obj//iVU1micro.o: ../../x86/iVU1micro.c + $(CC) -c ../../x86/iVU1micro.c -o Obj//iVU1micro.o $(CFLAGS) + +Obj//iVUmicro.o: ../../x86/iVUmicro.c + $(CC) -c ../../x86/iVUmicro.c -o Obj//iVUmicro.o $(CFLAGS) + +Obj//recCOP2.o: ../../x86/recCOP2.c + $(CC) -c ../../x86/recCOP2.c -o Obj//recCOP2.o $(CFLAGS) + +Obj//ix86.o: ../../x86/ix86/ix86.c + $(CC) -c ../../x86/ix86/ix86.c -o Obj//ix86.o $(CFLAGS) + +Obj//ix86_3dnow.o: ../../x86/ix86/ix86_3dnow.c + $(CC) -c ../../x86/ix86/ix86_3dnow.c -o Obj//ix86_3dnow.o $(CFLAGS) + +Obj//ix86_cpudetect.o: ../../x86/ix86/ix86_cpudetect.c + $(CC) -c ../../x86/ix86/ix86_cpudetect.c -o Obj//ix86_cpudetect.o $(CFLAGS) + +Obj//ix86_fpu.o: ../../x86/ix86/ix86_fpu.c + $(CC) -c ../../x86/ix86/ix86_fpu.c -o Obj//ix86_fpu.o $(CFLAGS) + +Obj//ix86_mmx.o: ../../x86/ix86/ix86_mmx.c + $(CC) -c ../../x86/ix86/ix86_mmx.c -o Obj//ix86_mmx.o $(CFLAGS) + +Obj//ix86_sse.o: ../../x86/ix86/ix86_sse.c + $(CC) -c ../../x86/ix86/ix86_sse.c -o Obj//ix86_sse.o $(CFLAGS) + +Obj//CDVD.o: ../../CDVD.c + $(CC) -c ../../CDVD.c -o Obj//CDVD.o $(CFLAGS) + +Obj//CDVDiso.o: ../../CDVDiso.c + $(CC) -c ../../CDVDiso.c -o Obj//CDVDiso.o $(CFLAGS) + +Obj//CDVDisodrv.o: ../../CDVDisodrv.c + $(CC) -c ../../CDVDisodrv.c -o Obj//CDVDisodrv.o $(CFLAGS) + +Obj//COP0.o: ../../COP0.c + $(CC) -c ../../COP0.c -o Obj//COP0.o $(CFLAGS) + +Obj//Counters.o: ../../Counters.c + $(CC) -c ../../Counters.c -o Obj//Counters.o $(CFLAGS) + +Obj//Decode_XA.o: ../../Decode_XA.c + $(CC) -c ../../Decode_XA.c -o Obj//Decode_XA.o $(CFLAGS) + +Obj//Elfheader.o: ../../Elfheader.c + $(CC) -c ../../Elfheader.c -o Obj//Elfheader.o $(CFLAGS) + +Obj//FiFo.o: ../../FiFo.c + $(CC) -c ../../FiFo.c -o Obj//FiFo.o $(CFLAGS) + +Obj//FPU.o: ../../FPU.c + $(CC) -c ../../FPU.c -o Obj//FPU.o $(CFLAGS) + +Obj//GS.o: ../../GS.c + $(CC) -c ../../GS.c -o Obj//GS.o $(CFLAGS) + +Obj//Gte.o: ../../Gte.c + $(CC) -c ../../Gte.c -o Obj//Gte.o $(CFLAGS) + +Obj//Hw.o: ../../Hw.c + $(CC) -c ../../Hw.c -o Obj//Hw.o $(CFLAGS) + +Obj//Interpreter.o: ../../Interpreter.c + $(CC) -c ../../Interpreter.c -o Obj//Interpreter.o $(CFLAGS) + +Obj//InterTables.o: ../../InterTables.c + $(CC) -c ../../InterTables.c -o Obj//InterTables.o $(CFLAGS) + +Obj//Mdec.o: ../../Mdec.c + $(CC) -c ../../Mdec.c -o Obj//Mdec.o $(CFLAGS) + +Obj//Memory.o: ../../Memory.c + $(CC) -c ../../Memory.c -o Obj//Memory.o $(CFLAGS) + +Obj//Misc.o: ../../Misc.c + $(CC) -c ../../Misc.c -o Obj//Misc.o $(CFLAGS) + +Obj//MMI.o: ../../MMI.c + $(CC) -c ../../MMI.c -o Obj//MMI.o $(CFLAGS) + +Obj//Patch.o: ../../Patch.c + $(CC) -c ../../Patch.c -o Obj//Patch.o $(CFLAGS) + +Obj//Plugins.o: ../../Plugins.c + $(CC) -c ../../Plugins.c -o Obj//Plugins.o $(CFLAGS) + +Obj//PsxBios.o: ../../PsxBios.c + $(CC) -c ../../PsxBios.c -o Obj//PsxBios.o $(CFLAGS) + +Obj//PsxCounters.o: ../../PsxCounters.c + $(CC) -c ../../PsxCounters.c -o Obj//PsxCounters.o $(CFLAGS) + +Obj//PsxDma.o: ../../PsxDma.c + $(CC) -c ../../PsxDma.c -o Obj//PsxDma.o $(CFLAGS) + +Obj//PsxGPU.o: ../../PsxGPU.c + $(CC) -c ../../PsxGPU.c -o Obj//PsxGPU.o $(CFLAGS) + +Obj//PsxHw.o: ../../PsxHw.c + $(CC) -c ../../PsxHw.c -o Obj//PsxHw.o $(CFLAGS) + +Obj//PsxInterpreter.o: ../../PsxInterpreter.c + $(CC) -c ../../PsxInterpreter.c -o Obj//PsxInterpreter.o $(CFLAGS) + +Obj//PsxMem.o: ../../PsxMem.c + $(CC) -c ../../PsxMem.c -o Obj//PsxMem.o $(CFLAGS) + +Obj//PsxSio2.o: ../../PsxSio2.c + $(CC) -c ../../PsxSio2.c -o Obj//PsxSio2.o $(CFLAGS) + +Obj//R3000A.o: ../../R3000A.c + $(CC) -c ../../R3000A.c -o Obj//R3000A.o $(CFLAGS) + +Obj//R5900.o: ../../R5900.c + $(CC) -c ../../R5900.c -o Obj//R5900.o $(CFLAGS) + +Obj//Sif.o: ../../Sif.c + $(CC) -c ../../Sif.c -o Obj//Sif.o $(CFLAGS) + +Obj//Sio.o: ../../Sio.c + $(CC) -c ../../Sio.c -o Obj//Sio.o $(CFLAGS) + +Obj//SPR.o: ../../SPR.c + $(CC) -c ../../SPR.c -o Obj//SPR.o $(CFLAGS) + +Obj//Stats.o: ../../Stats.c + $(CC) -c ../../Stats.c -o Obj//Stats.o $(CFLAGS) + +Obj//Vif.o: ../../Vif.c + $(CC) -c ../../Vif.c -o Obj//Vif.o $(CFLAGS) + +Obj//VifDma.o: ../../VifDma.c + $(CC) -c ../../VifDma.c -o Obj//VifDma.o $(CFLAGS) + +Obj//VU0.o: ../../VU0.c + $(CC) -c ../../VU0.c -o Obj//VU0.o $(CFLAGS) + +Obj//VU0micro.o: ../../VU0micro.c + $(CC) -c ../../VU0micro.c -o Obj//VU0micro.o $(CFLAGS) + +Obj//VU1micro.o: ../../VU1micro.c + $(CC) -c ../../VU1micro.c -o Obj//VU1micro.o $(CFLAGS) + +Obj//VUflags.o: ../../VUflags.c + $(CC) -c ../../VUflags.c -o Obj//VUflags.o $(CFLAGS) + +Obj//VUops.o: ../../VUops.c + $(CC) -c ../../VUops.c -o Obj//VUops.o $(CFLAGS) + +Obj//Cache.o: ../../Cache.c + $(CC) -c ../../Cache.c -o Obj//Cache.o $(CFLAGS) + +Obj//CdRom.o: ../../CdRom.c + $(CC) -c ../../CdRom.c -o Obj//CdRom.o $(CFLAGS) + +Obj//deci2.o: ../../RDebug/deci2.c + $(CC) -c ../../RDebug/deci2.c -o Obj//deci2.o $(CFLAGS) + +Obj//deci2_dbgp.o: ../../RDebug/deci2_dbgp.c + $(CC) -c ../../RDebug/deci2_dbgp.c -o Obj//deci2_dbgp.o $(CFLAGS) + +Obj//deci2_dcmp.o: ../../RDebug/deci2_dcmp.c + $(CC) -c ../../RDebug/deci2_dcmp.c -o Obj//deci2_dcmp.o $(CFLAGS) + +Obj//deci2_iloadp.o: ../../RDebug/deci2_iloadp.c + $(CC) -c ../../RDebug/deci2_iloadp.c -o Obj//deci2_iloadp.o $(CFLAGS) + +Obj//deci2_netmp.o: ../../RDebug/deci2_netmp.c + $(CC) -c ../../RDebug/deci2_netmp.c -o Obj//deci2_netmp.o $(CFLAGS) + +Obj//deci2_ttyp.o: ../../RDebug/deci2_ttyp.c + $(CC) -c ../../RDebug/deci2_ttyp.c -o Obj//deci2_ttyp.o $(CFLAGS) + +Obj//pcsx2_private.res: pcsx2_private.rc ../pcsx2.rc + $(WINDRES) -i pcsx2_private.rc --input-format=rc -o Obj//pcsx2_private.res -O coff --include-dir ../../ --include-dir ../ --include-dir ../mingw diff --git a/branches/pcsx2_0.9.1/windows/mingw/afxres.h b/branches/pcsx2_0.9.1/windows/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/branches/pcsx2_0.9.1/windows/mingw/pcsx2.dev b/branches/pcsx2_0.9.1/windows/mingw/pcsx2.dev new file mode 100644 index 0000000..db8fafb --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/pcsx2.dev @@ -0,0 +1,2116 @@ +[Project] +FileName=pcsx2.dev +Name=pcsx2 +UnitCount=205 +Type=0 +Ver=1 +ObjFiles= +Includes=../..;../../zlib;../../DebugTools;../../IPU;../../x86;../../ix86-32;..;../RDebug +Libs= +PrivateResource=pcsx2_private.rc +ResourceIncludes=../../;../;..\mingw +MakeIncludes= +Compiler=-v_@@_-D__WIN32___@@_-D__MINGW32__ _@@_-Wall _@@_-O3 ${-fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing} -mfpmath=sse -march=athlon64_@@_ _@@_ +CppCompiler= +Linker=-lcomctl32 _@@_-lwsock32 _@@_-lwinmm _@@_-lgdi32 _@@_-lcomdlg32 _@@__@@_-m128bit-long-double_@@_ +IsCpp=0 +Icon= +ExeOutput=../ +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=pcsx2.exe +HostApplication= +Folders=cpu,DebugTools,DECI2,GUI,Hardware,IOP_CPU,IPU,ix86,ix86/x86,ix86-32,misc,plugins,Sif,zlib +CommandLine= +UseCustomMakefile=0 +CustomMakefile=..\Makefile +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=..\AboutDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\AboutDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\ConfigDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\CpuDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\Debugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\Debugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\DebugMemory.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\Debugreg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\ini.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\McdsDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\McdsDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\PatchBrowser.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\pcsx2.rc +Folder=GUI +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\RDebugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\RDebugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\resource.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\Win32.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\WinMain.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=afxres.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\..\IPU\Idct.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\..\IPU\IPU.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\..\IPU\IPU.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\..\IPU\Mpeg.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\..\IPU\Mpeg.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\..\IPU\Vlc.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\..\IPU\yuv2rgb.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\..\IPU\yuv2rgb.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\..\DebugTools\cpuopsDebug.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\..\DebugTools\cpuopsDebug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\..\DebugTools\Debug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\..\DebugTools\DisASM.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\..\DebugTools\DisR3000A.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\..\DebugTools\DisR3000asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\..\DebugTools\DisR5900.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\..\DebugTools\DisR5900asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\..\DebugTools\DisVU0Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\..\DebugTools\DisVU1Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\..\DebugTools\DisVUmicro.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\..\DebugTools\DisVUops.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\..\zlib\adler32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\..\zlib\compress.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\..\zlib\crc32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=..\..\zlib\crc32.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=..\..\zlib\deflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=..\..\zlib\deflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=..\..\zlib\gzio.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=..\..\zlib\infback.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=..\..\zlib\inffast.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=..\..\zlib\inffast.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=..\..\zlib\inffixed.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=..\..\zlib\inflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=..\..\zlib\inflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit53] +FileName=..\..\zlib\inftrees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=..\..\zlib\inftrees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=..\..\zlib\trees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=..\..\zlib\trees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=..\..\zlib\uncompr.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=..\..\zlib\zconf.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=..\..\zlib\zlib.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=..\..\zlib\zutil.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=..\..\zlib\zutil.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit62] +FileName=..\..\ix86-32\iR5900Arit.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit63] +FileName=..\..\ix86-32\iR5900Arit.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit64] +FileName=..\..\ix86-32\iR5900AritImm.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit65] +FileName=..\..\ix86-32\iR5900AritImm.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit66] +FileName=..\..\ix86-32\iR5900Branch.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit67] +FileName=..\..\ix86-32\iR5900Branch.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit68] +FileName=..\..\ix86-32\iR5900Jump.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit69] +FileName=..\..\ix86-32\iR5900Jump.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit70] +FileName=..\..\ix86-32\iR5900LoadStore.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit71] +FileName=..\..\ix86-32\iR5900LoadStore.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit72] +FileName=..\..\ix86-32\iR5900Move.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit73] +FileName=..\..\ix86-32\iR5900Move.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit74] +FileName=..\..\ix86-32\iR5900MultDiv.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit75] +FileName=..\..\ix86-32\iR5900MultDiv.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit76] +FileName=..\..\ix86-32\iR5900Shift.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=..\..\ix86-32\iR5900Shift.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit78] +FileName=..\..\x86\iCP0.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=..\..\x86\iCP0.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit80] +FileName=..\..\x86\iFPU.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit81] +FileName=..\..\x86\iFPU.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit82] +FileName=..\..\x86\iMMI.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit83] +FileName=..\..\x86\iMMI.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit84] +FileName=..\..\x86\iR3000A.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit85] +FileName=..\..\x86\iR5900.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit86] +FileName=..\..\x86\iR5900.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit87] +FileName=..\..\x86\iVU0micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit88] +FileName=..\..\x86\iVU0micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit89] +FileName=..\..\x86\iVU1micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit90] +FileName=..\..\x86\iVU1micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit91] +FileName=..\..\x86\iVUmicro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit92] +FileName=..\..\x86\iVUmicro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit93] +FileName=..\..\x86\iVUops.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit94] +FileName=..\..\x86\recCOP2.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit95] +FileName=..\..\x86\ix86\ix86.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit96] +FileName=..\..\x86\ix86\ix86.h +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit97] +FileName=..\..\x86\ix86\ix86_3dnow.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit98] +FileName=..\..\x86\ix86\ix86_cpudetect.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit99] +FileName=..\..\x86\ix86\ix86_fpu.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit100] +FileName=..\..\x86\ix86\ix86_mmx.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit101] +FileName=..\..\x86\ix86\ix86_sse.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit102] +FileName=..\..\CDVD.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit103] +FileName=..\..\CDVD.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit104] +FileName=..\..\CDVDiso.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit105] +FileName=..\..\CDVDiso.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit106] +FileName=..\..\CDVDisodrv.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit107] +FileName=..\..\CDVDisodrv.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit108] +FileName=..\..\CDVDlib.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit109] +FileName=..\..\Common.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit110] +FileName=..\..\COP0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit111] +FileName=..\..\COP0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit112] +FileName=..\..\Counters.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit113] +FileName=..\..\Counters.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit114] +FileName=..\..\Decode_XA.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit115] +FileName=..\..\Decode_XA.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit116] +FileName=..\..\EEregs.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit117] +FileName=..\..\Elfheader.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit118] +FileName=..\..\Elfheader.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit119] +FileName=..\..\FiFo.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit120] +FileName=..\..\FPU.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit121] +FileName=..\..\GS.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit122] +FileName=..\..\GS.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit123] +FileName=..\..\Gte.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit124] +FileName=..\..\Gte.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit125] +FileName=..\..\Hw.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit126] +FileName=..\..\Hw.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit127] +FileName=..\..\Interpreter.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit128] +FileName=..\..\InterTables.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit129] +FileName=..\..\InterTables.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit130] +FileName=..\..\Mdec.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit131] +FileName=..\..\Mdec.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit132] +FileName=..\..\Memory.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit133] +FileName=..\..\Memory.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit134] +FileName=..\..\Misc.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit135] +FileName=..\..\Misc.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit136] +FileName=..\..\MMI.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit137] +FileName=..\..\Patch.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit138] +FileName=..\..\Patch.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit139] +FileName=..\..\Plugins.c +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit140] +FileName=..\..\Plugins.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit141] +FileName=..\..\PS2Edefs.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit142] +FileName=..\..\PS2Etypes.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit143] +FileName=..\..\PsxBios2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit144] +FileName=..\..\PsxBios.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit145] +FileName=..\..\PsxBios.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit146] +FileName=..\..\PsxCommon.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit147] +FileName=..\..\PsxCounters.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit148] +FileName=..\..\PsxCounters.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit149] +FileName=..\..\PsxDma.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit150] +FileName=..\..\PsxDma.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit151] +FileName=..\..\PsxGPU.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit152] +FileName=..\..\PsxGPU.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit153] +FileName=..\..\PsxHw.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit154] +FileName=..\..\PsxHw.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit155] +FileName=..\..\PsxInterpreter.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit156] +FileName=..\..\PsxMem.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit157] +FileName=..\..\PsxMem.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit158] +FileName=..\..\PsxSio2.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit159] +FileName=..\..\PsxSio2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit160] +FileName=..\..\R3000A.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit161] +FileName=..\..\R3000A.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit162] +FileName=..\..\R5900.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit163] +FileName=..\..\R5900.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit164] +FileName=..\..\Sif.c +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit165] +FileName=..\..\Sif.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit166] +FileName=..\..\Sifcmd.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit167] +FileName=..\..\Sio.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit168] +FileName=..\..\Sio.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit169] +FileName=..\..\SPR.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit170] +FileName=..\..\SPR.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit171] +FileName=..\..\Stats.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit172] +FileName=..\..\Stats.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit173] +FileName=..\..\System.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit174] +FileName=..\..\Vif.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit175] +FileName=..\..\Vif.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=..\..\VifDma.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit177] +FileName=..\..\VifDma.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit178] +FileName=..\..\VU0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit179] +FileName=..\..\VU0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit180] +FileName=..\..\VU0micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit181] +FileName=..\..\VU1micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit182] +FileName=..\..\VU.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit183] +FileName=..\..\VUflags.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit184] +FileName=..\..\VUflags.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit185] +FileName=..\..\VUmicro.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit186] +FileName=..\..\VUops.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit187] +FileName=..\..\VUops.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit188] +FileName=..\..\Cache.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit189] +FileName=..\..\Cache.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit190] +FileName=..\..\CdRom.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit191] +FileName=..\..\CdRom.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit192] +FileName=..\Cdrom02.ico +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit193] +FileName=..\..\pcsxAbout.bmp +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit194] +FileName=..\..\RDebug\deci2.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit195] +FileName=..\..\RDebug\deci2.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit196] +FileName=..\..\RDebug\deci2_dbgp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit197] +FileName=..\..\RDebug\deci2_dbgp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit198] +FileName=..\..\RDebug\deci2_dcmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit199] +FileName=..\..\RDebug\deci2_dcmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit202] +FileName=..\..\RDebug\deci2_netmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit203] +FileName=..\..\RDebug\deci2_netmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit204] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit205] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit206] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit207] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit200] +FileName=..\..\RDebug\deci2_iloadp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit201] +FileName=..\..\RDebug\deci2_iloadp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/branches/pcsx2_0.9.1/windows/mingw/pcsx2.layout b/branches/pcsx2_0.9.1/windows/mingw/pcsx2.layout new file mode 100644 index 0000000..eb0d940 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/pcsx2.layout @@ -0,0 +1,1424 @@ +[Editor_0] +CursorCol=1 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_1] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_4] +CursorCol=1 +CursorRow=95 +TopLine=54 +LeftChar=1 +Open=1 +Top=1 +[Editor_3] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_6] +CursorCol=2 +CursorRow=239 +TopLine=193 +LeftChar=1 +Open=0 +Top=0 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_9] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_10] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_11] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_12] +CursorCol=1 +CursorRow=19 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_13] +CursorCol=20 +CursorRow=172 +TopLine=132 +LeftChar=1 +Open=0 +Top=0 +[Editor_14] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_15] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_16] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_17] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_2] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_19] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_20] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_22] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_23] +CursorCol=1 +CursorRow=175 +TopLine=146 +LeftChar=1 +Open=0 +Top=0 +[Editor_24] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_25] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_26] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_21] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_27] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_28] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_29] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_31] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_30] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_32] +CursorCol=48 +CursorRow=360 +TopLine=315 +LeftChar=1 +Open=0 +Top=0 +[Editor_33] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_34] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_35] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_36] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_37] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_38] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_39] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_40] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_41] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_42] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_43] +CursorCol=8 +CursorRow=841 +TopLine=812 +LeftChar=1 +Open=0 +Top=0 +[Editor_44] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_45] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_46] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_47] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_48] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_49] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_50] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_51] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_52] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_53] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_54] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_55] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_56] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_57] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_58] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_59] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_60] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_61] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_62] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_63] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_64] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_65] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_66] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_67] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_68] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_69] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_70] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_71] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_72] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_73] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_74] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_75] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_76] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_77] +CursorCol=18 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_78] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_79] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_80] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_81] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_82] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_83] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_84] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_85] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_86] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_87] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_88] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_89] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_90] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_91] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_92] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_93] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_113] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_114] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_189] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_190] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_187] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_188] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_135] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_143] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_126] +CursorCol=1 +CursorRow=515 +TopLine=496 +LeftChar=1 +Open=0 +Top=0 +[Editor_127] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_128] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_133] +CursorCol=1 +CursorRow=684 +TopLine=643 +LeftChar=1 +Open=0 +Top=0 +[Editor_134] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_136] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_137] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_138] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_139] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_140] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_141] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_145] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_144] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_142] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_146] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_147] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_150] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_152] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_154] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_132] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_148] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_149] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_151] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_153] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_155] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_156] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_157] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_158] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_159] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_160] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_161] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_162] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_173] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_174] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_175] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_176] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_181] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_177] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_178] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_179] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_180] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_182] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_183] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_184] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_185] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_186] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_119] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_131] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_124] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_125] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_122] +CursorCol=17 +CursorRow=207 +TopLine=197 +LeftChar=1 +Open=0 +Top=0 +[Editor_123] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_129] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_130] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_163] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_164] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_166] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_167] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_109] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_110] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_192] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_170] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_168] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_169] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_165] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_111] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_112] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_101] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_102] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_103] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_104] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_105] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_106] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_107] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_115] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_116] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_117] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_118] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_120] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_121] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_171] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Focused=-1 +Order=-1 +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_94] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_95] +Open=0 +Top=0 +[Editor_96] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_97] +Open=1 +Top=0 +CursorCol=28 +CursorRow=477 +TopLine=439 +LeftChar=1 +[Editor_98] +Open=0 +Top=0 +[Editor_99] +Open=0 +Top=0 +CursorCol=1 +CursorRow=337 +TopLine=296 +LeftChar=1 +[Editor_100] +Open=0 +Top=0 +[Editor_108] +Open=0 +Top=0 +CursorCol=3 +CursorRow=3 +TopLine=1 +LeftChar=1 +[Editor_172] +Open=0 +Top=0 +[Editor_191] +Open=0 +Top=0 +[Editor_193] +Open=0 +Top=0 +CursorCol=20 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_194] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_195] +Open=0 +Top=0 +CursorCol=1 +CursorRow=349 +TopLine=1 +LeftChar=1 +[Editor_196] +Open=0 +Top=0 +[Editor_197] +Open=0 +Top=0 +CursorCol=6 +CursorRow=42 +TopLine=37 +LeftChar=1 +[Editor_198] +Open=0 +Top=0 +CursorCol=6 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_199] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_200] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_201] +Open=0 +Top=0 +CursorCol=21 +CursorRow=133 +TopLine=89 +LeftChar=1 +[Editor_202] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_203] +Open=0 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_204] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_205] +Open=1 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_206] +Open=0 +Top=0 diff --git a/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.h b/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.h new file mode 100644 index 0000000..38d3841 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef PCSX2_PRIVATE_H +#define PCSX2_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*PCSX2_PRIVATE_H*/ diff --git a/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.rc b/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.rc new file mode 100644 index 0000000..aea0afe --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/mingw/pcsx2_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "../pcsx2.rc" + diff --git a/branches/pcsx2_0.9.1/windows/pcsx2.rc b/branches/pcsx2_0.9.1/windows/pcsx2.rc new file mode 100644 index 0000000..8efabf2 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/pcsx2.rc @@ -0,0 +1,1417 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CMDLINE DIALOG 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Program arguments" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,36,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,99,37,50,14 + CTEXT "Tip: If you don't know what to write\nleave it blank", + IDC_TIP,7,56,172,19,WS_BORDER + EDITTEXT IDC_CMDLINE,7,17,172,14,ES_AUTOHSCROLL + LTEXT "Fill in the command line arguments for opened program:", + IDC_TEXT,7,7,174,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CMDLINE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CP0REGS DIALOG 0, 0, 267, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP0 " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CP00,48,7,51,12,ES_READONLY + LTEXT "Index",-1,7,9,18,8 + EDITTEXT IDC_CP01,48,21,51,12,ES_READONLY + LTEXT "Random",-1,7,23,28,8 + EDITTEXT IDC_CP02,48,35,51,12,ES_READONLY + LTEXT "EntryLo0",-1,7,37,29,8 + EDITTEXT IDC_CP03,48,49,51,12,ES_READONLY + LTEXT "EntryLo1",-1,7,51,29,8 + EDITTEXT IDC_CP04,48,63,51,12,ES_READONLY + LTEXT "Context",-1,7,65,25,8 + EDITTEXT IDC_CP05,48,77,51,12,ES_READONLY + LTEXT "PageMask",-1,7,79,35,8 + EDITTEXT IDC_CP06,48,91,51,12,ES_READONLY + LTEXT "Wired",-1,7,93,20,8 + EDITTEXT IDC_CP07,48,105,51,12,ES_READONLY + EDITTEXT IDC_CP08,48,119,51,12,ES_READONLY + LTEXT "BadVAddr",-1,7,121,33,8 + EDITTEXT IDC_CP09,48,133,52,12,ES_READONLY + LTEXT "Count",-1,7,135,20,8 + EDITTEXT IDC_CP010,48,147,51,12,ES_READONLY + LTEXT "EntryHi",-1,7,149,24,8 + EDITTEXT IDC_CP011,48,161,52,12,ES_READONLY + LTEXT "Compare",-1,7,163,29,8 + EDITTEXT IDC_CP012,48,175,51,12,ES_READONLY + LTEXT "Status",-1,7,177,21,8 + EDITTEXT IDC_CP013,48,189,51,12,ES_READONLY + LTEXT "Cause",-1,7,191,21,8 + EDITTEXT IDC_CP014,48,203,51,12,ES_READONLY + LTEXT "EPC",-1,7,205,15,8 + EDITTEXT IDC_CP015,48,218,51,12,ES_READONLY + LTEXT "PRId",-1,7,219,17,8 + EDITTEXT IDC_CP016,191,7,51,12,ES_READONLY + LTEXT "Config",-1,145,9,21,8 + EDITTEXT IDC_CP017,191,21,51,12,ES_READONLY + EDITTEXT IDC_CP018,191,35,51,12,ES_READONLY + EDITTEXT IDC_CP019,191,49,51,12,ES_READONLY + EDITTEXT IDC_CP020,191,63,51,12,ES_READONLY + EDITTEXT IDC_CP021,191,77,51,12,ES_READONLY + EDITTEXT IDC_CP022,191,91,51,12,ES_READONLY + EDITTEXT IDC_CP023,191,105,51,12,ES_READONLY + EDITTEXT IDC_CP024,191,119,51,12,ES_READONLY + EDITTEXT IDC_CP025,191,133,51,12,ES_READONLY + EDITTEXT IDC_CP026,191,147,51,12,ES_READONLY + LTEXT "Debug",-1,147,122,22,8 + EDITTEXT IDC_CP027,191,161,51,12,ES_READONLY + LTEXT "Perf",-1,149,136,14,8 + EDITTEXT IDC_CP028,191,175,51,12,ES_READONLY + LTEXT "TagLo",-1,145,177,22,8 + EDITTEXT IDC_CP029,191,189,51,12,ES_READONLY + LTEXT "TagHi",-1,145,191,20,8 + EDITTEXT IDC_CP030,191,203,51,12,ES_READONLY + LTEXT "ErrorEPC",-1,145,205,30,8 + EDITTEXT IDC_CP031,191,218,51,12,ES_READONLY +END + +IDD_DEBUG DIALOGEX 0, 0, 281, 297 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Debugger" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM,7,28,198,235,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Close",IDC_DEBUG_CLOSE,223,249,50,14 + PUSHBUTTON "Step",IDC_DEBUG_STEP,223,36,50,14 + PUSHBUTTON "Skip",IDC_DEBUG_SKIP,223,54,50,14 + PUSHBUTTON "Go",IDC_DEBUG_GO,223,19,50,14 + PUSHBUTTON "Bkpt on Exec",IDC_DEBUG_BP_EXEC,223,129,50,14 + SCROLLBAR IDC_DEBUG_SCROLL,205,28,11,235,SBS_VERT + PUSHBUTTON "Jump to ADDR",IDC_DEBUG_JUMP,223,112,50,14 + PUSHBUTTON "Un/Set Log",IDC_DEBUG_LOG,223,71,50,14 + PUSHBUTTON "Bkpt on Count",IDC_DEBUG_BP_COUNT,223,145,50,14 + PUSHBUTTON "Dump code",IDC_DEBUG_DUMP,223,194,50,14 + PUSHBUTTON "Clear Bkpts",IDC_DEBUG_BP_CLEAR,223,162,50,14 + PUSHBUTTON "Dump memory",IDC_DEBUG_MEMORY,223,211,50,14 + PUSHBUTTON "Cpu ops",IDC_CPUOP,223,227,50,14 + PUSHBUTTON "Reset to PC",IDC_DEBUG_RESETTOPC,223,96,50,14 +END + +IDD_DUMP DIALOGEX 0, 0, 386, 96 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump code" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_DUMP_START,73,14,82,13 + EDITTEXT IDC_DUMP_END,73,29,82,13 + EDITTEXT IDC_DUMP_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,87,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,227,73,50,14 + LTEXT "Start PC Address:",IDC_STATIC,19,17,52,8 + LTEXT "End PC Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 + GROUPBOX "EE",IDC_STATIC,14,6,167,64 + EDITTEXT IDC_DUMP_STARTIOP,255,15,82,13 + EDITTEXT IDC_DUMP_ENDIOP,255,30,82,13 + EDITTEXT IDC_DUMP_FNAMEIOP,255,50,82,13,ES_AUTOHSCROLL + LTEXT "Start PC Address:",IDC_STATIC,201,18,52,8 + LTEXT "End PC Address:",IDC_STATIC,201,33,50,8 + LTEXT "Filename:",IDC_STATIC,201,54,31,8 + GROUPBOX "IOP",IDC_STATIC,195,7,167,63 +END + +IDD_GPREGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "R5900 Main registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_GPR0,22,7,166,12,ES_READONLY + LTEXT "R0",-1,7,9,10,8 + EDITTEXT IDC_GPR1,22,21,166,12,ES_READONLY + LTEXT "AT",-1,7,23,10,8 + EDITTEXT IDC_GPR2,22,35,166,12,ES_READONLY + LTEXT "V0",-1,7,37,10,8 + EDITTEXT IDC_GPR3,22,49,166,12,ES_READONLY + LTEXT "V1",-1,7,51,10,8 + EDITTEXT IDC_GPR4,22,63,166,12,ES_READONLY + LTEXT "A0",-1,7,65,10,8 + EDITTEXT IDC_GPR5,22,77,166,12,ES_READONLY + LTEXT "A1",-1,7,79,10,8 + EDITTEXT IDC_GPR6,22,91,166,12,ES_READONLY + LTEXT "A2",-1,7,93,10,8 + EDITTEXT IDC_GPR7,22,105,166,12,ES_READONLY + LTEXT "A3",-1,7,107,10,8 + EDITTEXT IDC_GPR8,22,119,166,12,ES_READONLY + LTEXT "T0",-1,7,121,10,8 + EDITTEXT IDC_GPR9,22,133,166,12,ES_READONLY + LTEXT "T1",-1,7,135,10,8 + EDITTEXT IDC_GPR10,22,147,166,12,ES_READONLY + LTEXT "T2",-1,7,149,10,8 + EDITTEXT IDC_GPR11,22,161,166,12,ES_READONLY + LTEXT "T3",-1,7,163,10,8 + EDITTEXT IDC_GPR12,22,175,166,12,ES_READONLY + LTEXT "T4",-1,7,177,10,8 + EDITTEXT IDC_GPR13,22,189,166,12,ES_READONLY + LTEXT "T5",-1,7,191,10,8 + EDITTEXT IDC_GPR14,22,203,166,12,ES_READONLY + LTEXT "T6",-1,7,205,10,8 + EDITTEXT IDC_GPR15,22,218,166,12,ES_READONLY + LTEXT "T7",-1,7,219,10,8 + EDITTEXT IDC_GPR16,214,7,165,12,ES_READONLY + LTEXT "S0",-1,196,10,10,8 + EDITTEXT IDC_GPR17,214,20,166,12,ES_READONLY + LTEXT "S1",-1,196,22,10,8 + EDITTEXT IDC_GPR18,214,35,166,12,ES_READONLY + LTEXT "S2",-1,196,36,10,8 + EDITTEXT IDC_GPR19,214,49,165,12,ES_READONLY + LTEXT "S3",-1,196,52,10,8 + EDITTEXT IDC_GPR20,214,63,165,12,ES_READONLY + LTEXT "S4",-1,196,66,10,8 + EDITTEXT IDC_GPR21,214,76,165,12,ES_READONLY + LTEXT "S5",-1,196,80,10,8 + EDITTEXT IDC_GPR22,214,91,165,12,ES_READONLY + LTEXT "S6",-1,196,94,10,8 + EDITTEXT IDC_GPR23,214,105,165,12,ES_READONLY + LTEXT "S7",-1,196,108,10,8 + EDITTEXT IDC_GPR24,214,119,165,12,ES_READONLY + LTEXT "T8",-1,196,121,10,8 + EDITTEXT IDC_GPR25,214,132,165,12,ES_READONLY + LTEXT "T9",-1,196,135,10,8 + EDITTEXT IDC_GPR26,214,147,165,12,ES_READONLY + LTEXT "K0",-1,196,149,10,8 + EDITTEXT IDC_GPR27,214,161,165,12,ES_READONLY + LTEXT "K1",-1,196,163,10,8 + EDITTEXT IDC_GPR28,214,175,165,12,ES_READONLY + LTEXT "GP",-1,196,178,11,8 + EDITTEXT IDC_GPR29,214,188,165,12,ES_READONLY + LTEXT "SP",-1,196,190,10,8 + EDITTEXT IDC_GPR30,214,203,165,12,ES_READONLY + LTEXT "S8",-1,196,205,10,8 + EDITTEXT IDC_GPR31,214,217,165,12,ES_READONLY + LTEXT "RA",-1,196,220,11,8 + EDITTEXT IDC_GPR_PC,20,260,57,12,ES_READONLY + LTEXT "PC",-1,7,263,10,8 + EDITTEXT IDC_GPR_HI,21,238,167,12,ES_READONLY + LTEXT "HI",-1,7,241,8,8 + LTEXT "LO",-1,196,241,10,8 + EDITTEXT IDC_GPR_LO,214,238,165,12,ES_READONLY +END + +IDD_JUMP DIALOG 0, 0, 175, 64 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Jump to specific address" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_JUMP_PC,73,14,82,13 + DEFPUSHBUTTON "OK",IDOK,25,43,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14 + LTEXT "Enter new PC Address:",IDC_STATIC,3,18,70,8 +END + +IDD_MEMORY DIALOG 0, 0, 317, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Memory" +FONT 8, "Courier" +BEGIN + EDITTEXT IDC_MEMORY_ADDR,54,7,97,12 + PUSHBUTTON "Close",IDC_MEMORY_CLOSE,266,7,42,14 + LTEXT "Address:",IDC_STATIC,14,8,34,8 + LISTBOX IDC_MEMORY_DUMP,3,29,300,169,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_TABSTOP + SCROLLBAR IDC_MEM_SCROLL,303,29,9,172,SBS_VERT + GROUPBOX "Memory Patch",IDC_STATIC,3,204,307,57 + EDITTEXT IDC_ADDRESS_PATCH,124,220,97,12 + EDITTEXT IDC_DATA_PATCH,124,242,97,12 + LTEXT "Address",IDC_STATIC,84,222,40,8 + LTEXT "Data",IDC_STATIC,85,244,39,8 + PUSHBUTTON "Patch It",IDC_PATCH,238,230,64,16 + PUSHBUTTON "Raw dump",IDC_DUMPRAW,204,7,50,14 +END + +IDD_VU1INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1 Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU1_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU1_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU1_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU1_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU1_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU1_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU1_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU1_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU1_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU1_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU1_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU1_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU1_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU1_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU1_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU1_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU1_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU1_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU1_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU1_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU1_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU1_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU1_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU1_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU1_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU1_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU1_VI27,172,161,89,12,WS_DISABLED + LTEXT "P register",IDC_STATIC,124,108,30,8 + EDITTEXT IDC_VU1_VI28,172,175,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI29,172,189,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU1_VI31,172,218,89,12,WS_DISABLED + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU1_ACC,78,239,166,12,ES_READONLY +END + +IDD_VU0REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU0_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU0_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU0_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU0_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU0_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU0_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU0_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU0_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU0_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU0_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU0_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU0_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU0_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU0_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU0_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU0_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU0_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU0_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU0_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU0_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU0_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU0_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU0_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU0_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU0_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU0_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU0_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU0_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU0_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU0_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU0_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_CP1REGS DIALOG 0, 0, 357, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP1 Registers " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_FP0,29,7,89,12,WS_DISABLED + LTEXT "FP0",IDC_STATIC,7,9,14,8 + EDITTEXT IDC_FP1,29,21,89,12,WS_DISABLED + LTEXT "FP1",IDC_STATIC,7,23,14,8 + EDITTEXT IDC_FP2,29,35,89,12,WS_DISABLED + LTEXT "FP2",IDC_STATIC,7,37,14,8 + EDITTEXT IDC_FP3,29,49,89,12,WS_DISABLED + LTEXT "FP3",IDC_STATIC,7,51,14,8 + EDITTEXT IDC_FP4,29,63,89,12,WS_DISABLED + LTEXT "FP4",IDC_STATIC,7,65,14,8 + EDITTEXT IDC_FP5,29,77,89,12,WS_DISABLED + LTEXT "FP5",IDC_STATIC,7,79,14,8 + EDITTEXT IDC_FP6,29,91,89,12,WS_DISABLED + LTEXT "FP6",IDC_STATIC,7,93,14,8 + EDITTEXT IDC_FP7,29,105,89,12,WS_DISABLED + LTEXT "FP7",IDC_STATIC,7,107,14,8 + EDITTEXT IDC_FP8,29,119,89,12,WS_DISABLED + LTEXT "FP8",IDC_STATIC,7,121,14,8 + EDITTEXT IDC_FP9,29,133,89,12,WS_DISABLED + LTEXT "FP9",IDC_STATIC,7,135,14,8 + EDITTEXT IDC_FP10,29,147,89,12,WS_DISABLED + LTEXT "FP10",IDC_STATIC,7,149,18,8 + EDITTEXT IDC_FP11,29,161,89,12,WS_DISABLED + LTEXT "FP11",IDC_STATIC,7,163,18,8 + EDITTEXT IDC_FP12,29,175,89,12,WS_DISABLED + LTEXT "FP12",IDC_STATIC,7,177,18,8 + EDITTEXT IDC_FP13,29,189,89,12,WS_DISABLED + LTEXT "FP13",IDC_STATIC,7,191,18,8 + EDITTEXT IDC_FP14,29,203,89,12,WS_DISABLED + LTEXT "FP14",IDC_STATIC,7,205,18,8 + EDITTEXT IDC_FP15,29,218,89,12,WS_DISABLED + LTEXT "FP15",IDC_STATIC,7,219,18,8 + EDITTEXT IDC_FP16,145,7,89,12,WS_DISABLED + LTEXT "FP16",IDC_STATIC,123,9,18,8 + EDITTEXT IDC_FP17,145,21,89,12,WS_DISABLED + LTEXT "FP17",IDC_STATIC,123,23,18,8 + EDITTEXT IDC_FP18,145,35,89,12,WS_DISABLED + LTEXT "FP18",IDC_STATIC,123,37,18,8 + EDITTEXT IDC_FP19,145,49,89,12,WS_DISABLED + LTEXT "FP19",IDC_STATIC,123,51,18,8 + EDITTEXT IDC_FP20,145,63,89,12,WS_DISABLED + LTEXT "FP20",IDC_STATIC,123,65,18,8 + EDITTEXT IDC_FP21,145,77,89,12,WS_DISABLED + LTEXT "FP21",IDC_STATIC,123,79,18,8 + EDITTEXT IDC_FP22,145,91,89,12,WS_DISABLED + LTEXT "FP22",IDC_STATIC,123,93,18,8 + EDITTEXT IDC_FP23,145,105,89,12,WS_DISABLED + LTEXT "FP23",IDC_STATIC,123,107,18,8 + EDITTEXT IDC_FP24,145,119,89,12,WS_DISABLED + LTEXT "FP24",IDC_STATIC,123,121,18,8 + EDITTEXT IDC_FP25,145,133,89,12,WS_DISABLED + LTEXT "FP25",IDC_STATIC,123,135,18,8 + EDITTEXT IDC_FP26,145,147,89,12,WS_DISABLED + LTEXT "FP26",IDC_STATIC,123,149,18,8 + EDITTEXT IDC_FP27,145,161,89,12,WS_DISABLED + LTEXT "FP27",IDC_STATIC,123,163,18,8 + EDITTEXT IDC_FP28,145,175,89,12,WS_DISABLED + LTEXT "FP28",IDC_STATIC,123,177,18,8 + EDITTEXT IDC_FP29,145,189,89,12,WS_DISABLED + LTEXT "FP29",IDC_STATIC,123,191,18,8 + EDITTEXT IDC_FP30,145,203,89,12,WS_DISABLED + LTEXT "FP30",IDC_STATIC,123,205,18,8 + EDITTEXT IDC_FP31,145,218,89,12,WS_DISABLED + LTEXT "FP31",IDC_STATIC,123,219,18,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,244,8,1, + 223 + LTEXT "Implementation/Revision Reg",IDC_STATIC,253,9,94,8 + EDITTEXT IDC_FCR0,298,21,50,12,WS_DISABLED + LTEXT "FCR0",IDC_STATIC,253,23,19,8 + LTEXT "Control/Status Register",IDC_STATIC,253,37,74,8 + EDITTEXT IDC_FCR31,298,49,50,12,WS_DISABLED + LTEXT "FCR31",IDC_STATIC,253,51,23,8 + LTEXT "Accumulator",IDC_STATIC,256,68,43,14 + EDITTEXT IDC_FPU_ACC,299,68,49,12,ES_AUTOHSCROLL | WS_DISABLED +END + +IDD_VU0INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU0_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU0_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU0_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU0_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU0_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU0_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU0_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU0_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU0_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU0_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU0_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU0_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU0_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU0_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU0_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU0_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU0_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU0_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU0_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU0_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU0_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU0_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU0_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU0_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU0_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU0_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU0_VI27,172,161,89,12,WS_DISABLED + LTEXT "CMSAR0 reg",IDC_STATIC,123,163,42,8 + EDITTEXT IDC_VU0_VI28,172,175,89,12,WS_DISABLED + LTEXT "FBRST register",IDC_STATIC,123,177,49,8 + EDITTEXT IDC_VU0_VI29,172,189,89,12,WS_DISABLED + LTEXT "VPU-STAT reg",IDC_STATIC,123,191,48,8 + EDITTEXT IDC_VU0_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU0_VI31,172,218,89,12,WS_DISABLED + LTEXT "CMSAR1 reg",IDC_STATIC,123,219,42,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU0_ACC,78,239,166,12,ES_READONLY + LTEXT "P register",IDC_STATIC,124,108,30,8 +END + +IDD_VU1REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU1_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU1_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU1_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU1_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU1_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU1_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU1_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU1_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU1_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU1_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU1_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU1_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU1_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU1_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU1_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU1_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU1_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU1_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU1_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU1_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU1_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU1_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU1_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU1_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU1_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU1_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU1_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU1_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU1_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU1_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU1_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_RDEBUGPARAMS DIALOGEX 0, 0, 174, 58 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,37,50,14 + EDITTEXT IDC_PORT,127,7,40,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Accept connections on TCP/IP port:",IDC_STATIC,7,7,120, + 10 + CONTROL "Debug Bios",IDC_DEBUGBIOS,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | WS_TABSTOP,7,22,50,10 +END + +IDD_RDEBUG DIALOGEX 0, 0, 254, 271 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "E&xit",IDOK,199,251,48,14 + LISTBOX IDC_COMMUNICATION,7,7,240,211,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + PUSHBUTTON "&Clear",IDC_CLEAR,199,229,48,14 + EDITTEXT IDC_EEPC,74,229,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPPC,132,229,52,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "EE pc address:\t IOP pc address:",IDC_STATIC,77,219,113, + 9 + CONTROL "Debug EE",IDC_DEBUGEE,"Button",BS_AUTORADIOBUTTON,77, + 255,48,10 + CONTROL "Debug IOP",IDC_DEBUGIOP,"Button",BS_AUTORADIOBUTTON | + BS_LEFTTEXT,132,254,50,11 + EDITTEXT IDC_STOPAT,7,229,56,13,ES_AUTOHSCROLL + EDITTEXT IDC_STOPAFTER,7,252,56,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Break at (hex addr):",IDC_STATIC,7,219,67,8 + LTEXT "Break after (cycles):",IDC_STATIC,7,243,66,8 + EDITTEXT IDC_EECYCLE,74,241,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPCYCLE,132,241,52,12,ES_AUTOHSCROLL | ES_READONLY +END + +IDD_MCDCONF DIALOG 0, 0, 407, 197 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Memcard Manager" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,285,175,50,14 + PUSHBUTTON "Cancel",IDCANCEL,345,175,50,14 + EDITTEXT IDC_MCD1,10,155,160,14,ES_AUTOHSCROLL + EDITTEXT IDC_MCD2,235,155,160,14,ES_AUTOHSCROLL + PUSHBUTTON "Select Mcd",IDC_MCDSEL1,10,135,50,14 + PUSHBUTTON "Select Mcd",IDC_MCDSEL2,235,135,50,14 + GROUPBOX "Memory Card 2",IDC_FRAMEMCD2,230,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT1,65,135,50,14 + GROUPBOX "Memory Card 1",IDC_FRAMEMCD1,5,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT2,290,135,50,14 + CONTROL "List3",IDC_LIST1,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,15,160,110 + CONTROL "List3",IDC_LIST2,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,235,15,160,110 + PUSHBUTTON "Reload Mcd",IDC_RELOAD1,120,135,50,14 + PUSHBUTTON "Reload Mcd",IDC_RELOAD2,345,135,50,14 + PUSHBUTTON "-> Copy ->",IDC_COPYTO2,180,30,45,14 + PUSHBUTTON "<- Copy <-",IDC_COPYTO1,180,50,45,14 + PUSHBUTTON "Paste",IDC_PASTE,180,70,45,14 + PUSHBUTTON "<- Un/Delete",IDC_DELETE1,180,90,45,14 + PUSHBUTTON "Un/Delete ->",IDC_DELETE2,180,110,45,14 +END + +IDD_DUMPMEM DIALOG 0, 0, 175, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump memory" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DUMPMEM_START,73,14,82,13 + EDITTEXT IDC_DUMPMEM_END,73,29,82,13 + EDITTEXT IDC_DUMPMEM_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,25,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,74,50,14 + LTEXT "Start Address:",IDC_STATIC,19,17,52,8 + LTEXT "End Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 +END + +IDD_DIALOGBAR DIALOGEX 0, 0, 330, 16 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "TODO: layout dialog bar",IDC_STATIC,126,4,77,8 +END + +IDD_IOPREGS DIALOGEX 0, 0, 417, 295 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "IOP Main Registers" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_IOPGPR0,22,20,166,12,ES_READONLY + LTEXT "R0",-1,7,23,10,8 + EDITTEXT IDC_IOPGPR1,22,34,166,12,ES_READONLY + LTEXT "AT",-1,7,36,10,8 + EDITTEXT IDC_IOPGPR2,22,49,166,12,ES_READONLY + LTEXT "V0",-1,7,50,10,8 + EDITTEXT IDC_IOPGPR3,22,63,166,12,ES_READONLY + LTEXT "V1",-1,7,65,10,8 + EDITTEXT IDC_IOPGPR4,22,76,166,12,ES_READONLY + LTEXT "A0",-1,7,79,10,8 + EDITTEXT IDC_IOPGPR5,22,90,166,12,ES_READONLY + LTEXT "A1",-1,7,92,10,8 + EDITTEXT IDC_IOPGPR6,22,105,166,12,ES_READONLY + LTEXT "A2",-1,7,106,10,8 + EDITTEXT IDC_IOPGPR7,22,119,166,12,ES_READONLY + LTEXT "A3",-1,7,121,10,8 + EDITTEXT IDC_IOPGPR8,22,132,166,12,ES_READONLY + LTEXT "T0",-1,7,135,10,8 + EDITTEXT IDC_IOPGPR9,22,146,166,12,ES_READONLY + LTEXT "T1",-1,7,148,10,8 + EDITTEXT IDC_IOPGPR10,22,161,166,12,ES_READONLY + LTEXT "T2",-1,7,162,10,8 + EDITTEXT IDC_IOPGPR11,22,175,166,12,ES_READONLY + LTEXT "T3",-1,7,177,10,8 + EDITTEXT IDC_IOPGPR12,22,188,166,12,ES_READONLY + LTEXT "T4",-1,7,191,10,8 + EDITTEXT IDC_IOPGPR13,22,202,166,12,ES_READONLY + LTEXT "T5",-1,7,204,10,8 + EDITTEXT IDC_IOPGPR14,22,217,166,12,ES_READONLY + LTEXT "T6",-1,7,218,10,8 + EDITTEXT IDC_IOPGPR15,22,231,166,12,ES_READONLY + LTEXT "T7",-1,7,233,10,8 + EDITTEXT IDC_IOPGPR16,214,20,165,12,ES_READONLY + LTEXT "S0",-1,196,23,10,8 + EDITTEXT IDC_IOPGPR17,214,34,166,12,ES_READONLY + LTEXT "S1",-1,196,36,10,8 + EDITTEXT IDC_IOPGPR18,214,49,166,12,ES_READONLY + LTEXT "S2",-1,196,50,10,8 + EDITTEXT IDC_IOPGPR19,214,63,165,12,ES_READONLY + LTEXT "S3",-1,196,66,10,8 + EDITTEXT IDC_IOPGPR20,214,76,165,12,ES_READONLY + LTEXT "S4",-1,196,79,10,8 + EDITTEXT IDC_IOPGPR21,214,90,165,12,ES_READONLY + LTEXT "S5",-1,196,94,10,8 + EDITTEXT IDC_IOPGPR22,214,105,165,12,ES_READONLY + LTEXT "S6",-1,196,108,10,8 + EDITTEXT IDC_IOPGPR23,214,119,165,12,ES_READONLY + LTEXT "S7",-1,196,122,10,8 + EDITTEXT IDC_IOPGPR24,214,132,165,12,ES_READONLY + LTEXT "T8",-1,196,135,10,8 + EDITTEXT IDC_IOPGPR25,214,146,165,12,ES_READONLY + LTEXT "T9",-1,196,148,10,8 + EDITTEXT IDC_IOPGPR26,214,161,165,12,ES_READONLY + LTEXT "K0",-1,196,162,10,8 + EDITTEXT IDC_IOPGPR27,214,175,165,12,ES_READONLY + LTEXT "K1",-1,196,177,10,8 + EDITTEXT IDC_IOPGPR28,214,188,165,12,ES_READONLY + LTEXT "GP",-1,196,191,11,8 + EDITTEXT IDC_IOPGPR29,214,202,165,12,ES_READONLY + LTEXT "SP",-1,196,204,10,8 + EDITTEXT IDC_IOPGPR30,214,217,165,12,ES_READONLY + LTEXT "S8",-1,196,218,10,8 + EDITTEXT IDC_IOPGPR31,214,231,165,12,ES_READONLY + LTEXT "RA",-1,196,234,11,8 + EDITTEXT IDC_IOPGPR_PC,20,272,57,12,ES_READONLY + LTEXT "PC",-1,7,276,10,8 + EDITTEXT IDC_IOPGPR_HI,21,252,167,12,ES_READONLY + LTEXT "HI",-1,7,255,8,8 + LTEXT "LO",-1,196,255,10,8 + EDITTEXT IDC_IOPGPR_LO,214,252,165,12,ES_READONLY +END + +IDD_USERNAME DIALOGEX 0, 0, 186, 79 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Enter User Name" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,58,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,58,50,14 + LTEXT "Pcsx2 needs to allocate physical memory in order to execute faster. Enter the windows username you wish this privilege to be enabled for.", + IDC_STATIC,7,7,172,25 + EDITTEXT IDC_USER_NAME,73,37,106,13,ES_AUTOHSCROLL + LTEXT "User Name:",IDC_STATIC,7,41,38,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DEBUG, DIALOG + BEGIN + BOTTOMMARGIN, 282 + END + + IDD_RDEBUGPARAMS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + END + + IDD_RDEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 247 + TOPMARGIN, 7 + BOTTOMMARGIN, 265 + END + + IDD_MCDCONF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 240 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_DIALOGBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 323 + TOPMARGIN, 7 + BOTTOMMARGIN, 9 + END + + IDD_IOPREGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 410 + TOPMARGIN, 7 + BOTTOMMARGIN, 284 + END + + IDD_USERNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 72 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_PS2SILVER BITMAP "ps2_silver.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUT_DIALOG DIALOGEX 0, 0, 431, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_ACCEPTFILES +CAPTION "About" +FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,250,50,14 + CTEXT "PCSX2 \nVersion x.x",IDC_PCSX_ABOUT_TEXT,55,10,45,15,0, + WS_EX_TRANSPARENT + CTEXT "PCSX2 a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,36, + 135,92,0,WS_EX_TRANSPARENT + CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,88,158,311,77 + GROUPBOX "",IDC_STATIC,5,29,145,113 + GROUPBOX "",IDC_STATIC,77,148,333,91 + CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,0,167,70,74 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + ABOUT_DIALOG, DIALOG + BEGIN + RIGHTMARGIN, 429 + BOTTOMMARGIN, 264 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +SPLASH_LOGO BITMAP "..\\pcsxAbout.bmp" +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 317, 244 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_LISTGS,10,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGGS,10,35,45,12 + PUSHBUTTON "Test...",IDC_TESTGS,60,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTGS,110,35,45,12 + COMBOBOX IDC_LISTSPU2,166,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGSPU2,165,35,45,12 + PUSHBUTTON "Test...",IDC_TESTSPU2,215,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTSPU2,265,35,43,12 + COMBOBOX IDC_LISTCDVD,10,105,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGCDVD,10,125,43,12 + PUSHBUTTON "Test...",IDC_TESTCDVD,60,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTCDVD,110,125,45,12 + COMBOBOX IDC_LISTBIOS,165,196,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,207,223,50,14 + PUSHBUTTON "Cancel",IDCANCEL,260,223,50,14 + RTEXT "Graphics",IDC_GRAPHICS,50,5,41,10,SS_CENTERIMAGE + RTEXT "Sound",IDC_SOUND,200,5,43,10,SS_CENTERIMAGE + RTEXT "Cdvdrom",IDC_CDVDROM,65,95,30,10,SS_CENTERIMAGE + RTEXT "Bios",IDC_BIOS,228,185,15,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD1,10,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD1,10,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD1,60,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD1,110,80,45,12 + RTEXT "Second Controller",IDC_SECONDCONTROLLER,205,50,58,10, + SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD2,166,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD2,165,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD2,215,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD2,265,80,45,12 + CTEXT "First Controller",IDC_FIRSTCONTROLLER,55,50,48,10, + SS_CENTERIMAGE + PUSHBUTTON "Set Bios Directory",IDC_BIOSDIR,90,223,65,14 + PUSHBUTTON "Set Plugins Directory",IDC_PLUGINSDIR,7,223,75,14 + COMBOBOX IDC_LISTDEV9,165,105,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGDEV9,165,125,43,12 + PUSHBUTTON "Test...",IDC_TESTDEV9,215,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTDEV9,265,125,45,12 + CTEXT "Dev9",IDC_DEV9,221,95,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTUSB,10,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGUSB,10,170,43,12 + PUSHBUTTON "Test...",IDC_TESTUSB,60,170,45,12 + PUSHBUTTON "About...",IDC_ABOUTUSB,110,170,45,12 + CTEXT "Usb",IDC_USB,66,140,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTFW,165,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGFW,165,169,43,12 + PUSHBUTTON "Test...",IDC_TESTFW,214,169,45,12 + PUSHBUTTON "About...",IDC_ABOUTFW,265,169,45,12 + LTEXT "FireWire",IDC_STATIC,227,141,39,8 +END + +IDD_BPEXEC DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Exec" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EXECBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Address:",IDC_STATIC,5,13,84,8 +END + +IDD_BPCNT DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Count" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CNTBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Count:",IDC_STATIC,5,13,77,8 +END + +IDD_CPUCONF DIALOGEX 0, 0, 181, 185 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "CPUconfig" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,58,164,50,14 + PUSHBUTTON "Cancel",IDCANCEL,112,164,50,14 + GROUPBOX "Misc Options",IDC_MISCOPTIONS,5,5,155,65 + CONTROL "Enable Console Output",IDC_PSXOUT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,20,89,10 + CONTROL "Enable Patches",IDC_PATCH,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,35,88,12 + GROUPBOX "CPU Options",IDC_RECOPTIONS,5,70,157,65 + COMBOBOX IDC_THPRIORITY,90,50,63,55,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Process Priority",IDC_STATIC,20,50,55,12,SS_CENTERIMAGE + COMBOBOX IDC_CPUOPTION,32,89,106,55,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP +END + +IDD_ADVANCED DIALOGEX 0, 0, 177, 69 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Advanced" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,47,50,14 + PUSHBUTTON "Cancel",IDCANCEL,121,47,50,14 + CONTROL "Enable Reg Caching",IDC_REGCACHING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,15,81,10 + GROUPBOX "",IDC_STATIC,2,7,168,38 + PUSHBUTTON "Reset",IDC_ADVRESET,5,47,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 237 + HORZGUIDE, 169 + END + + IDD_BPEXEC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 6 + BOTTOMMARGIN, 54 + END + + IDD_BPCNT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + IDD_CPUCONF, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 174 + VERTGUIDE, 162 + TOPMARGIN, 7 + BOTTOMMARGIN, 178 + HORZGUIDE, 34 + HORZGUIDE, 46 + END + + IDD_ADVANCED, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "Cdrom02.ico" +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Greek resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ELL) +#ifdef _WIN32 +LANGUAGE LANG_GREEK, SUBLANG_DEFAULT +#pragma code_page(1253) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PATCHBROWSER DIALOGEX 0, 0, 487, 282 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patches Browser" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "New Patch",IDC_NEWPATCH,112,257,60,14 + EDITTEXT IDC_PATCHTEXT,113,95,354,153,ES_MULTILINE | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "Save Patch",IDC_SAVEPATCH,186,257,60,14,WS_DISABLED + PUSHBUTTON "Refresh List",IDC_REFRESHPATCHLIST,21,257,60,14 + LISTBOX IDC_PATCHCRCLIST,19,95,69,153,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_PATCHNAMELIST,17,34,452,50,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Search game name patch:",IDC_GAMENAMESEARCH,17,16,101,9 + EDITTEXT IDC_SEARCHPATCHTEXT,109,14,295,12,ES_AUTOHSCROLL + PUSHBUTTON "Exit",IDC_EXITPB,411,257,59,14 +END + +IDD_LOGGING DIALOGEX 0, 0, 263, 177 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Logging" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,206,156,50,14 + CONTROL "Cpu log",IDC_CPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,5,53,10 + CONTROL "COP0 log",IDC_COP0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,20,59,10 + CONTROL "FPU log",IDC_FPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,35,55,10 + CONTROL "MMI log",IDC_MMILOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,50,55,10 + CONTROL "VUO log",IDC_VU0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,65,56,10 + CONTROL "Bios log",IDC_BIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,80,54,10 + CONTROL "DMA log",IDC_DMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,95,57,10 + CONTROL "HW log",IDC_HWLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 5,110,53,10 + CONTROL "Unknown Memory log",IDC_MEMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,5,84,10 + CONTROL "Elf log",IDC_ELFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,20,35,10 + CONTROL "VIF log",IDC_VIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,35,38,10 + CONTROL "Scratch pad log",IDC_SPRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,50,66,10 + CONTROL "Gif log",IDC_GIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,65,49,10 + CONTROL "SIF log",IDC_SIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,80,51,10 + GROUPBOX "IOP",IDC_STATIC,161,7,95,127 + CONTROL "IOP cpu log",IDC_IOPLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,15,67,10 + CONTROL "HW log",IDC_IOPHWLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,30,53,10 + CONTROL "Bios log",IDC_IOPBIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,45,41,10 + CONTROL "Unknown Memory log",IDC_IOPMEMLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,60,85,10 + CONTROL "IPU log",IDC_IPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,95,39,10 + CONTROL "DMA log",IDC_IOPDMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,75,67,10 + CONTROL "PAD log",IDC_IOPPADLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,90,53,10 + CONTROL "CDR log",IDC_IOPCDRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,104,43,10 + CONTROL "VUMicro log",IDC_VUMICROLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,110,55,10 + CONTROL "RPC services log",IDC_RPCSERVICES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,5,125,67,10 + CONTROL "Log to STDOUT",IDC_STDOUTPUTLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,75,125,68,10 + CONTROL "Log",IDC_LOGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5, + 140,28,10 + CONTROL "Symbols log",IDC_SYMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,140,53,10 + CONTROL "Counters log",IDC_IOPCNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,118,55,10 +END + +IDD_IOP_DEBUG DIALOGEX 0, 0, 358, 107 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Debug" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM_IOP,7,7,330,92,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + SCROLLBAR IDC_DEBUG_SCROLL_IOP,340,7,11,93,SBS_VERT +END + +IDD_CPUDLG DIALOGEX 0, 0, 253, 289 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,268,50,14 + PUSHBUTTON "Cancel",IDCANCEL,82,268,50,14,NOT WS_TABSTOP + LTEXT "CPU vendor ",IDC_VENDORNAME,12,24,54,12 + GROUPBOX "",IDC_STATIC,7,12,239,90 + LTEXT "Family",IDC_FAMILYNAME,12,42,54,12 + LTEXT "Cpu Speed",IDC_CPUSPEEDNAME,12,60,54,12 + LTEXT "Features",IDC_FEATURESNAME,12,78,54,12 + LTEXT "",IDC_VENDORINPUT,72,24,162,12 + LTEXT "",IDC_FAMILYINPUT,72,42,162,12 + LTEXT "",IDC_FEATURESINPUT,71,82,162,12 + LTEXT "",IDC_CPUSPEEDINPUT,72,60,162,12 + CONTROL "Dual Core Mode (DC) - only valid with MTGS", + IDC_CPU_MULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 232,214,13 + CONTROL "Multi threaded GS mode (MTGS)\n (faster on dual core/HT procs, requires pcsx2 restart)", + IDC_CPU_GSMULTI,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,210,208,18 + CONTROL "Frame Limit (FL) - limits speed to normal speeds", + IDC_CPU_FRAMELIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 7,248,188,13 + CONTROL "VU1rec - enable recompiler for VU1 unit",IDC_CPU_VU1REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,154,142,18 + CONTROL "VU0rec - enable recompiler for VU0 unit",IDC_CPU_VU0REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,170,193,18 + CONTROL "EERec - EE/IOP recompiler (need MMX/SSE)", + IDC_CPU_EEREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 110,161,18 + CONTROL "Safe Floating Point (higher compat, removes spiky polys)", + IDC_CPU_FORCEABS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,7,125,239,18 + GROUPBOX "VU Recompilers - All options are set by default", + IDC_STATIC,7,144,189,46 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_LOGGING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 256 + TOPMARGIN, 7 + BOTTOMMARGIN, 170 + END + + IDD_IOP_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 351 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_CPUDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 246 + VERTGUIDE, 39 + VERTGUIDE, 59 + TOPMARGIN, 7 + BOTTOMMARGIN, 282 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Greek resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/branches/pcsx2_0.9.1/windows/ps2_silver.bmp b/branches/pcsx2_0.9.1/windows/ps2_silver.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cb58820cdf1d734c0f8889bde4b6023e9feb4e12 GIT binary patch literal 37974 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 literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.1/windows/resource.h b/branches/pcsx2_0.9.1/windows/resource.h new file mode 100644 index 0000000..296c3d6 --- /dev/null +++ b/branches/pcsx2_0.9.1/windows/resource.h @@ -0,0 +1,640 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pcsx2.rc +// +#define IDR_MENU 101 +#define IDD_CONFIG 101 +#define IDD_MCDCONF 102 +#define IDD_BPEXEC 103 +#define ABOUT_DIALOG 104 +#define IDD_BPCNT 105 +#define IDD_CPUCONF 106 +#define IDD_DEBUG 108 +#define IDI_ICON 108 +#define IDD_MEMORY 110 +#define IDD_VU0REGS 111 +#define IDD_JUMP 112 +#define SPLASH_LOGO 113 +#define IDD_VU0INTEGER 113 +#define IDD_GPREGS 114 +#define IDD_CP0REGS 115 +#define IDD_CP1REGS 116 +#define IDD_VU1INTEGER 117 +#define IDD_VU1REGS 118 +#define IDD_LOGGING 119 +#define IDD_CMDLINE 120 +#define IDD_RDEBUGPARAMS 121 +#define ID_DEBUG_REMOTEDEBUGGING 122 +#define IDD_RDEBUG 123 +#define IDD_DIALOGBAR 124 +#define IDD_IOP_DEBUG 125 +#define IDD_CPUDLG 126 +#define IDD_ADVANCED 127 +#define IDD_IOPREGS 128 +#define IDD_USERNAME 129 +#define IDB_PS2SILVER 132 +#define IDD_DUMP 136 +#define IDD_DUMPMEM 137 +#define IDD_PATCHBROWSER 138 +#define IDC_MEM_SCROLL 1001 +#define IDC_EXECBP 1001 +#define IDC_CNTBP 1002 +#define IDC_MCD2 1004 +#define IDC_VU0_VF00 1005 +#define IDC_MCD1 1005 +#define IDC_VU0_VF01 1006 +#define IDC_MCDSEL1 1006 +#define IDC_VU0_VF02 1007 +#define IDC_MCDSEL2 1007 +#define IDC_VU0_VF03 1008 +#define IDC_VU0_VF04 1009 +#define IDC_DEBUG_DISASM 1010 +#define IDC_VU0_VF05 1010 +#define IDC_VU0_VF06 1011 +#define IDC_VU0_VF07 1012 +#define IDC_VU0_VF08 1013 +#define IDC_PCSX_ABOUT_TEXT 1014 +#define IDC_PSXOUT 1014 +#define IDC_VU0_VF09 1014 +#define IDC_CPU 1015 +#define IDC_VU0_VF10 1015 +#define IDC_VSYNCHACK 1016 +#define IDC_VU0_VF11 1016 +#define IDC_VU0_VF12 1017 +#define IDC_VU0_VF13 1018 +#define IDC_VU0_VF14 1019 +#define IDC_CP07 1020 +#define IDC_VU0_VF15 1020 +#define IDC_VU0_VF16 1021 +#define IDC_VU0_VF17 1022 +#define IDC_VU0_VF18 1023 +#define IDC_VU0_VF19 1024 +#define IDC_VU0_VF20 1025 +#define IDC_VU0_VF21 1026 +#define IDC_VU0_VF22 1027 +#define IDC_VU0_VF23 1028 +#define IDC_DEBUG_CLOSE 1029 +#define IDC_VU0_VF24 1029 +#define IDC_DEBUG_STEP 1030 +#define IDC_VU0_VF25 1030 +#define IDC_DEBUG_SKIP 1031 +#define IDC_VU0_VF26 1031 +#define IDC_DEBUG_GO 1032 +#define IDC_VU0_VF27 1032 +#define IDC_DEBUG_BP_EXEC 1033 +#define IDC_VU0_VF28 1033 +#define IDC_CP021 1034 +#define IDC_DEBUG_SCROLL 1034 +#define IDC_VU0_VF29 1034 +#define IDC_CP022 1035 +#define IDC_DEBUG_RESETTOPC 1035 +#define IDC_VU0_VF30 1035 +#define IDC_CP023 1036 +#define IDC_FPU_ACC 1036 +#define IDC_DEBUG_JUMP 1036 +#define IDC_MEMORY_CLOSE 1036 +#define IDC_VU0_VF31 1036 +#define IDC_CP024 1037 +#define IDC_DEBUG_BREAK 1037 +#define IDC_MEMORY_ADDR 1037 +#define IDC_DEBUG_LOG 1037 +#define IDC_CP025 1038 +#define IDC_MEMORY_DUMP 1038 +#define IDC_DEBUG_BP_COUNT 1038 +#define IDC_VU0_VI00 1038 +#define IDC_DEBUG_L1 1039 +#define IDC_VU0_VI01 1039 +#define IDC_ADDRESS_PATCH 1039 +#define IDC_DEBUG_L2 1040 +#define IDC_VU0_VI02 1040 +#define IDC_DATA_PATCH 1040 +#define IDC_DEBUG_L3 1041 +#define IDC_VU0_VI03 1041 +#define IDC_FRAMEMCD1 1041 +#define IDC_DEBUG_L4 1042 +#define IDC_VU0_VI04 1042 +#define IDC_FRAMEMCD2 1042 +#define IDC_DEBUG_L5 1043 +#define IDC_VU0_VI05 1043 +#define IDC_CP031 1044 +#define IDC_DEBUG_L6 1044 +#define IDC_VU0_VI06 1044 +#define IDC_DEBUG_L7 1045 +#define IDC_VU0_VI07 1045 +#define IDC_DEBUG_L8 1046 +#define IDC_VU0_VI08 1046 +#define IDC_DEBUG_L9 1047 +#define IDC_GPR0 1047 +#define IDC_VU0_VI09 1047 +#define IDC_DEBUG_L10 1048 +#define IDC_GPR1 1048 +#define IDC_VU0_VI10 1048 +#define IDC_DEBUG_L11 1049 +#define IDC_GPR2 1049 +#define IDC_VU0_VI11 1049 +#define IDC_DEBUG_L12 1050 +#define IDC_GPR3 1050 +#define IDC_VU0_VI12 1050 +#define IDC_DEBUG_L13 1051 +#define IDC_GPR4 1051 +#define IDC_VU0_VI13 1051 +#define IDC_DEBUG_L14 1052 +#define IDC_GPR5 1052 +#define IDC_LISTGS 1052 +#define IDC_VU0_VI14 1052 +#define IDC_DEBUG_L15 1053 +#define IDC_GPR6 1053 +#define IDC_LISTSPU 1053 +#define IDC_VU0_VI15 1053 +#define IDC_LISTSPU2 1053 +#define IDC_DEBUG_L16 1054 +#define IDC_GPR7 1054 +#define IDC_LISTCDR 1054 +#define IDC_VU0_VI16 1054 +#define IDC_LISTCDVD 1054 +#define IDC_DEBUG_L17 1055 +#define IDC_GPR8 1055 +#define IDC_LISTBIOS 1055 +#define IDC_VU0_VI17 1055 +#define IDC_DEBUG_L18 1056 +#define IDC_GPR9 1056 +#define IDC_CONFIGGS 1056 +#define IDC_VU0_VI18 1056 +#define IDC_DEBUG_L19 1057 +#define IDC_GPR10 1057 +#define IDC_TESTGS 1057 +#define IDC_VU0_VI19 1057 +#define IDC_DEBUG_L20 1058 +#define IDC_ABOUTGS 1058 +#define IDC_VU0_VI20 1058 +#define IDC_DEBUG_L21 1059 +#define IDC_CONFIGSPU 1059 +#define IDC_VU0_VI21 1059 +#define IDC_CONFIGSPU2 1059 +#define IDC_DEBUG_L22 1060 +#define IDC_TESTSPU 1060 +#define IDC_VU0_VI22 1060 +#define IDC_TESTSPU2 1060 +#define IDC_DEBUG_L23 1061 +#define IDC_ABOUTSPU 1061 +#define IDC_VU0_VI23 1061 +#define IDC_ABOUTSPU2 1061 +#define IDC_DEBUG_L24 1062 +#define IDC_CONFIGCDR 1062 +#define IDC_VU0_VI24 1062 +#define IDC_CONFIGCDVD 1062 +#define IDC_DEBUG_L25 1063 +#define IDC_GPR11 1063 +#define IDC_TESTCDR 1063 +#define IDC_VU0_VI25 1063 +#define IDC_TESTCDVD 1063 +#define IDC_DEBUG_L26 1064 +#define IDC_ABOUTCDR 1064 +#define IDC_VU0_VI26 1064 +#define IDC_ABOUTCDVD 1064 +#define IDC_DEBUG_L27 1065 +#define IDC_VU0_VI27 1065 +#define IDC_LISTDEV9 1065 +#define IDC_DEBUG_L28 1066 +#define IDC_LISTPAD 1066 +#define IDC_LISTPAD1 1066 +#define IDC_VU0_VI28 1066 +#define IDC_DEBUG_L29 1067 +#define IDC_CONFIGPAD 1067 +#define IDC_CONFIGPAD1 1067 +#define IDC_VU0_VI29 1067 +#define IDC_DEBUG_R1 1068 +#define IDC_GPR12 1068 +#define IDC_TESTPAD 1068 +#define IDC_TESTPAD1 1068 +#define IDC_VU0_VI30 1068 +#define IDC_DEBUG_R2 1069 +#define IDC_GPR13 1069 +#define IDC_ABOUTPAD 1069 +#define IDC_ABOUTPAD1 1069 +#define IDC_VU0_VI31 1069 +#define IDC_DEBUG_R3 1070 +#define IDC_GPR14 1070 +#define IDC_LISTPAD2 1070 +#define IDC_VU0_ACC 1070 +#define IDC_DEBUG_R4 1071 +#define IDC_GPR15 1071 +#define IDC_CONFIGPAD2 1071 +#define IDC_VU1_VF00 1071 +#define IDC_DEBUG_R5 1072 +#define IDC_GPR16 1072 +#define IDC_TESTPAD2 1072 +#define IDC_VU1_VF01 1072 +#define IDC_DEBUG_R6 1073 +#define IDC_GPR17 1073 +#define IDC_ABOUTPAD2 1073 +#define IDC_VU1_VF02 1073 +#define IDC_DEBUG_R7 1074 +#define IDC_GPR18 1074 +#define IDC_VU1_VF03 1074 +#define IDC_CONFIGDEV9 1074 +#define IDC_DEBUG_R8 1075 +#define IDC_GPR19 1075 +#define IDC_VU1_VF04 1075 +#define IDC_TESTDEV9 1075 +#define IDC_DEBUG_R9 1076 +#define IDC_GPR20 1076 +#define IDC_VU1_VF05 1076 +#define IDC_ABOUTDEV9 1076 +#define IDC_DEBUG_R10 1077 +#define IDC_GPR21 1077 +#define IDC_VU1_VF06 1077 +#define IDC_LISTUSB 1077 +#define IDC_DEBUG_R11 1078 +#define IDC_GPR22 1078 +#define IDC_VU1_VF07 1078 +#define IDC_CONFIGUSB 1078 +#define IDC_DEBUG_R12 1079 +#define IDC_GPR23 1079 +#define IDC_VU1_VF08 1079 +#define IDC_TESTUSB 1079 +#define IDC_DEBUG_R13 1080 +#define IDC_GPR24 1080 +#define IDC_VU1_VF09 1080 +#define IDC_ABOUTUSB 1080 +#define IDC_DEBUG_R14 1081 +#define IDC_GPR25 1081 +#define IDC_VU1_VF10 1081 +#define IDC_LISTFW 1081 +#define IDC_DEBUG_R15 1082 +#define IDC_GPR26 1082 +#define IDC_VU1_VF11 1082 +#define IDC_CONFIGFW 1082 +#define IDC_DEBUG_R16 1083 +#define IDC_GPR27 1083 +#define IDC_VU1_VF12 1083 +#define IDC_TESTFW 1083 +#define IDC_DEBUG_R17 1084 +#define IDC_GPR28 1084 +#define IDC_VU1_VF13 1084 +#define IDC_ABOUTFW 1084 +#define IDC_DEBUG_R18 1085 +#define IDC_GPR29 1085 +#define IDC_VU1_VF14 1085 +#define IDC_DEBUG_R19 1086 +#define IDC_GPR30 1086 +#define IDC_VU1_VF15 1086 +#define IDC_DEBUG_R20 1087 +#define IDC_GPR31 1087 +#define IDC_VU1_VF16 1087 +#define IDC_DEBUG_R21 1088 +#define IDC_VU1_VF17 1088 +#define IDC_DEBUG_R22 1089 +#define IDC_GPR_PC 1089 +#define IDC_VU1_VF18 1089 +#define IDC_DEBUG_R23 1090 +#define IDC_VU1_VF19 1090 +#define IDC_DEBUG_R24 1091 +#define IDC_GPR_HI 1091 +#define IDC_VU1_VF20 1091 +#define IDC_DEBUG_R25 1092 +#define IDC_GPR_LO 1092 +#define IDC_VU1_VF21 1092 +#define IDC_CP00 1093 +#define IDC_DEBUG_R26 1093 +#define IDC_VU1_VF22 1093 +#define IDC_CP01 1094 +#define IDC_DEBUG_R27 1094 +#define IDC_VU1_VF23 1094 +#define IDC_CP02 1095 +#define IDC_DEBUG_R28 1095 +#define IDC_VU1_VF24 1095 +#define IDC_CP03 1096 +#define IDC_DEBUG_R29 1096 +#define IDC_VU1_VF25 1096 +#define IDC_CP04 1097 +#define IDC_DEBUG_DUMP 1097 +#define IDC_JUMP_PC 1097 +#define IDC_VU1_VF26 1097 +#define IDC_CP05 1098 +#define IDC_DEBUG_DUMPRAW 1098 +#define IDC_DUMP_END 1098 +#define IDC_VU1_VF27 1098 +#define IDC_DEBUG_LOGGING 1098 +#define IDC_DEBUG_MEMORY 1098 +#define IDC_CP06 1099 +#define IDC_DUMP_FNAME 1099 +#define IDC_DEBUG_BP_CLEAR 1099 +#define IDC_VU1_VF28 1099 +#define IDC_CP08 1100 +#define IDC_VU1_VF29 1100 +#define IDC_DUMP_ENDIOP 1100 +#define IDC_CP09 1101 +#define IDC_VU1_VF30 1101 +#define IDC_DUMP_FNAMEIOP 1101 +#define IDC_CP010 1102 +#define IDC_VU1_VF31 1102 +#define IDC_CP011 1103 +#define IDC_VU1_VI00 1103 +#define IDC_CP012 1104 +#define IDC_VU1_VI01 1104 +#define IDC_CP013 1105 +#define IDC_VU1_VI02 1105 +#define IDC_CP014 1106 +#define IDC_VU1_VI03 1106 +#define IDC_CP015 1107 +#define IDC_VU1_VI04 1107 +#define IDC_CP016 1108 +#define IDC_VU1_VI05 1108 +#define IDC_CP017 1109 +#define IDC_VU1_VI06 1109 +#define IDC_CP018 1110 +#define IDC_VU1_VI07 1110 +#define IDC_CP019 1111 +#define IDC_VU1_VI08 1111 +#define IDC_CP020 1112 +#define IDC_VU1_VI09 1112 +#define IDC_CP026 1113 +#define IDC_VU1_VI10 1113 +#define IDC_CP027 1114 +#define IDC_VU1_VI11 1114 +#define IDC_CP028 1115 +#define IDC_VU1_VI12 1115 +#define IDC_CP029 1116 +#define IDC_VU1_VI13 1116 +#define IDC_CP030 1117 +#define IDC_VU1_VI14 1117 +#define IDC_FP0 1118 +#define IDC_VU1_VI15 1118 +#define IDC_FP1 1119 +#define IDC_VU1_VI16 1119 +#define IDC_FP2 1120 +#define IDC_VU1_VI17 1120 +#define IDC_FP3 1121 +#define IDC_VU1_VI18 1121 +#define IDC_FP4 1122 +#define IDC_VU1_VI19 1122 +#define IDC_FP5 1123 +#define IDC_VU1_VI20 1123 +#define IDC_FP6 1124 +#define IDC_VU1_VI21 1124 +#define IDC_FP7 1125 +#define IDC_VU1_VI22 1125 +#define IDC_FP8 1126 +#define IDC_VU1_VI23 1126 +#define IDC_FP9 1127 +#define IDC_VU1_VI24 1127 +#define IDC_FP10 1128 +#define IDC_VU1_VI25 1128 +#define IDC_FP11 1129 +#define IDC_VU1_VI26 1129 +#define IDC_FP12 1130 +#define IDC_VU1_VI27 1130 +#define IDC_FP13 1131 +#define IDC_VU1_VI28 1131 +#define IDC_FP14 1132 +#define IDC_VU1_VI29 1132 +#define IDC_FP15 1133 +#define IDC_VU1_VI30 1133 +#define IDC_FP16 1134 +#define IDC_VU1_VI31 1134 +#define IDC_FP17 1135 +#define IDC_VU1_ACC 1135 +#define IDC_FP18 1136 +#define IDC_FP19 1137 +#define IDC_FP20 1138 +#define IDC_FP21 1139 +#define IDC_FP22 1140 +#define IDC_FP23 1141 +#define IDC_FP24 1142 +#define IDC_FP25 1143 +#define IDC_FP26 1144 +#define IDC_FP27 1145 +#define IDC_FP28 1146 +#define IDC_FP29 1147 +#define IDC_FP30 1148 +#define IDC_FP31 1149 +#define IDC_FCR0 1150 +#define IDC_FCR31 1151 +#define IDC_CMDLINE 1155 +#define IDC_PORT 1157 +#define IDC_COMMUNICATION 1158 +#define IDC_CLEAR 1160 +#define IDC_DEBUGBIOS 1161 +#define IDC_EEPC 1162 +#define IDC_IOPPC 1163 +#define IDC_PCSX_ABOUT_GREETS 1163 +#define IDC_PCSX_ABOUT_AUTHORS 1164 +#define IDC_EECYCLE 1164 +#define IDC_GRAPHICS 1165 +#define IDC_IOPCYCLE 1165 +#define IDC_SOUND 1166 +#define IDC_FIRSTCONTROLLER 1167 +#define IDC_SECONDCONTROLLER 1168 +#define IDC_CDVDROM 1169 +#define IDC_BIOS 1170 +#define IDC_MISCOPTIONS 1171 +#define IDC_DEV9 1171 +#define IDC_DUMP_START 1172 +#define IDC_TIP 1172 +#define IDC_USB 1172 +#define IDC_TEXT 1173 +#define IDC_DUMP_STARTIOP 1173 +#define IDC_CPUOP 1175 +#define IDC_DEBUGEE 1176 +#define IDC_DEBUGIOP 1177 +#define IDC_STOPAT 1178 +#define IDC_STOPAFTER 1179 +#define IDC_PATCH 1180 +#define IDC_REGCACHE 1181 +#define IDC_RECOPTIONS 1182 +#define IDC_PADHACK 1183 +#define IDC_VUREC 1184 +#define IDC_LOGS 1186 +#define IDDELREG 1187 +#define IDC_TAB_DEBUG 1188 +#define IDC_DUMPMEM_FNAME 1188 +#define IDC_DUMPMEM_END 1189 +#define IDC_DUMPMEM_START 1190 +#define IDC_DUMPRAW 1191 +#define IDC_DEBUG_DISASM_IOP 1193 +#define IDC_DEBUG_SCROLL_IOP 1194 +#define IDC_THPRIORITY 1195 +#define IDC_EXITPB 1196 +#define IDC_CPUOPTION 1196 +#define IDC_VENDORNAME 1197 +#define IDC_FAMILYNAME 1198 +#define IDC_CPUSPEEDNAME 1199 +#define IDC_FEATURESNAME 1200 +#define IDC_VENDORINPUT 1201 +#define IDC_FAMILYINPUT 1202 +#define IDC_CPUSPEEDINPUT 1203 +#define IDC_FEATURESINPUT 1204 +#define IDC_RADIOINTEPRETER 1205 +#define IDC_RADIORECOMPILER 1206 +#define IDC_RADIORECOMPILERVU 1207 +#define IDC_REGCACHING 1208 +#define IDC_INTERLACEHACK 1210 +#define IDC_SAFECOUNTERS 1211 +#define IDC_IOPCLK 1213 +#define IDC_ADVRESET 1214 +#define IDC_FASTIOPCLK 1215 +#define IDC_CHECK2 1217 +#define IDC_SPU2HACK 1218 +#define IDC_VSYNCRATE 1219 +#define IDC_IOPGPR0 1220 +#define IDC_IOPGPR1 1221 +#define IDC_IOPGPR2 1222 +#define IDC_IOPGPR16 1223 +#define IDC_IOPGPR17 1224 +#define IDC_IOPGPR18 1225 +#define IDC_IOPGPR19 1226 +#define IDC_IOPGPR20 1227 +#define IDC_IOPGPR21 1228 +#define IDC_IOPGPR22 1229 +#define IDC_IOPGPR23 1230 +#define IDC_IOPGPR24 1231 +#define IDC_IOPGPR25 1232 +#define IDC_IOPGPR26 1233 +#define IDC_IOPGPR27 1234 +#define IDC_IOPGPR28 1235 +#define IDC_IOPGPR29 1236 +#define IDC_IOPGPR30 1237 +#define IDC_IOPGPR31 1238 +#define IDC_IOPGPR_LO 1239 +#define IDC_IOPGPR_HI 1240 +#define IDC_IOPGPR_PC 1241 +#define IDC_IOPGPR15 1242 +#define IDC_IOPGPR14 1243 +#define IDC_IOPGPR13 1244 +#define IDC_IOPGPR12 1245 +#define IDC_IOPGPR11 1246 +#define IDC_IOPGPR10 1247 +#define IDC_IOPGPR9 1248 +#define IDC_IOPGPR8 1249 +#define IDC_IOPGPR7 1250 +#define IDC_IOPGPR6 1251 +#define IDC_IOPGPR5 1252 +#define IDC_IOPGPR4 1253 +#define IDC_BIOSDIR 1254 +#define IDC_IOPGPR3 1254 +#define IDC_PLUGINSDIR 1255 +#define IDC_EDIT2 1256 +#define IDC_BIAS 1256 +#define IDC_USER_NAME 1257 +#define IDC_CPU_MULTI 1258 +#define IDC_CPU_MULTI2 1259 +#define IDC_CPU_GSMULTI 1259 +#define IDC_PS2SILVER_RECT 1259 +#define IDC_CPU_MULTI3 1260 +#define IDC_CPU_FRAMELIMIT 1260 +#define IDC_CPU_FRAMELIMIT2 1261 +#define IDC_CPU_EEREC 1262 +#define IDC_CPU_VU1REC 1263 +#define IDC_CHECK4 1264 +#define IDC_CPU_VU0REC 1264 +#define IDC_CPU_NEWCOP2 1265 +#define IDC_CPU_FORCEABS 1266 +#define IDC_CPU_VU1REC2 1268 +#define IDC_CPU_SVUREC 1268 +#define IDC_LOG 1500 +#define IDC_CPULOG 1500 +#define IDC_MEMLOG 1501 +#define IDC_HWLOG 1502 +#define IDC_DMALOG 1503 +#define IDC_BIOSLOG 1504 +#define IDC_ELFLOG 1505 +#define IDC_FPULOG 1506 +#define IDC_MMILOG 1507 +#define IDC_VU0LOG 1508 +#define IDC_COP0LOG 1509 +#define IDC_VIFLOG 1510 +#define IDC_SPRLOG 1511 +#define IDC_GIFLOG 1512 +#define IDC_SIFLOG 1513 +#define IDC_IPULOG 1514 +#define IDC_VUMICROLOG 1515 +#define IDC_RPCSERVICES 1516 +#define IDC_IOPLOG 1520 +#define IDC_IOPMEMLOG 1521 +#define IDC_IOPHWLOG 1522 +#define IDC_IOPBIOSLOG 1523 +#define IDC_IOPDMALOG 1524 +#define IDC_IOPPADLOG 1525 +#define IDC_IOPGTELOG 1526 +#define IDC_IOPCDRLOG 1527 +#define IDC_IOPGPULOG 1527 +#define IDC_IOPCNTLOG 1529 +#define IDC_SYMLOG 1530 +#define IDC_STDOUTPUTLOG 1531 +#define ID_FILEOPEN 40001 +#define ID_DEBUG_MEMORY_DUMP 40002 +#define ID_FILE_EXIT 40003 +#define ID_RUN_EXECUTE 40004 +#define ID_RUN_RESET 40005 +#define ID_HELP_ABOUT 40006 +#define ID_CONFIG_CONFIGURE 40007 +#define ID_CONFIG_CPU 40008 +#define ID_CONFIG_GRAPHICS 40009 +#define ID_CONFIG_CONTROLLERS 40010 +#define ID_DEBUG_LOGGING 40011 +#define ID_CONFIG_SOUND 40012 +#define ID_CONFIG_CDVDROM 40013 +#define ID_RUN_CMDLINE 40014 +#define ID_FILE_RUNCD 40015 +#define ID_DEBUG_ENTERDEBUGGER 40016 +#define ID_CONFIG_DEV9 40017 +#define ID_FILE_STATES_LOAD_SLOT1 40018 +#define ID_FILE_STATES_LOAD_SLOT2 40019 +#define ID_FILE_STATES_LOAD_SLOT3 40020 +#define ID_FILE_STATES_LOAD_SLOT4 40021 +#define ID_FILE_STATES_LOAD_SLOT5 40022 +#define ID_FILE_STATES_LOAD_OTHER 40023 +#define ID_FILE_STATES_SAVE_SLOT1 40024 +#define ID_FILE_STATES_SAVE_SLOT2 40025 +#define ID_FILE_STATES_SAVE_SLOT3 40026 +#define ID_FILE_STATES_SAVE_SLOT4 40027 +#define ID_FILE_STATES_SAVE_SLOT5 40028 +#define ID_FILE_STATES_SAVE_OTHER 40029 +#define ID_CONFIG_FW 40030 +#define ID_CONFIG_USB 40031 +#define ID_CONFIG_MEMCARDS 40032 +#define IDC_FORMAT1 40033 +#define IDC_FORMAT2 40034 +#define IDC_LIST1 40035 +#define IDC_LIST2 40036 +#define IDC_RELOAD1 40037 +#define IDC_RELOAD2 40038 +#define IDC_COPYTO2 40039 +#define IDC_COPYTO1 40040 +#define IDC_PASTE 40041 +#define IDC_DELETE1 40042 +#define IDC_DELETE2 40043 +#define ID_PATCHBROWSER 40044 +#define ID_NEWPATCH 40045 +#define IDC_NEWPATCH 40045 +#define IDC_PATCHTEXT 40046 +#define IDC_SAVEPATCH 40047 +#define IDC_REFRESHPATCHLIST 40048 +#define IDC_PATCHCRCLIST 40049 +#define IDC_PATCHNAMELIST 40050 +#define IDC_GAMENAMESEARCH 40051 +#define IDC_SEARCHPATCHTEXT 40052 +#define ID_PROCESSLOW 40053 +#define ID_PROCESSNORMAL 40054 +#define ID_PROCESSHIGH 40055 +#define ID_CONSOLE 40056 +#define ID_PATCHES 40057 +#define ID_CONFIG_ADVANCED 40058 +#define ID_INTERLACEHACK 40059 +#define ID_SAFECNTS 40060 +#define ID_SPU2HACK 40061 +#define ID_VSYNCRATE 40062 +#define ID_HELP_HELP 40063 +#define ID_LANGS 50000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 133 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1263 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Arit.c b/branches/pcsx2_0.9.1/x86-64/iR5900Arit.c new file mode 100644 index 0000000..482ce5d --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Arit.c @@ -0,0 +1,542 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rsreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Rt_ != 0) { + ADD32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + ADD64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + ADD64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + SUB32RtoR(t0reg, rdreg); + MOV32RtoR(rdreg, t0reg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) + { + SUB32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV64RtoR(t0reg, rsreg); + SUB64RtoR(t0reg, rdreg); + MOV64RtoR(rdreg, t0reg); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + SUB64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + SUB64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + AND64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + if (_Rt_ == _Rd_) { // Rd&= Rs + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else if (_Rs_ == _Rd_) { // Rd&= Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else { // Rd = Rs & Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) { + XOR64RtoR(RAX, RAX); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[0], RAX ); + } else if ( _Rs_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else if ( _Rt_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recXOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + XOR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + XOR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recNOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + NOT64R(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + NOT64R(RAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recSLT( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SBB64RtoR(EAX, EAX); + NEG64R (EAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Arit.h b/branches/pcsx2_0.9.1/x86-64/iR5900Arit.h new file mode 100644 index 0000000..5fcd64d --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.c b/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.c new file mode 100644 index 0000000..a9d1223 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.c @@ -0,0 +1,314 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV32ItoR(rtreg, _Imm_); + ADD32RtoR(rtreg, rsreg); + SHL64ItoR(rtreg, 32); + SAR64ItoR(rtreg, 32); + } + } + + _clearNeededX86regs(); + +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Imm_ != 0) { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64ItoR(rtreg, _Imm_); + ADD64RtoR(rtreg, rsreg); + } + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETB8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recANDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + AND64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + AND64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if ( _ImmU_ != 0 ) { + if (_Rs_ == _Rt_) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + AND32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_ ); + } else { + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + else + { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } +#endif +} + +//////////////////////////////////////////////////// +void recORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + OR64ItoR(rtreg, _ImmU_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + OR64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if (_Rs_ == _Rt_) { + OR32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], _ImmU_ ); + } else { + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + OR64ItoR( RAX, _ImmU_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + } + +#endif +} + +//////////////////////////////////////////////////// +void recXORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + XOR64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + MOV64RtoR(rtreg, rsreg); + XOR64ItoR(rtreg, _ImmU_); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + XOR64ItoR( RAX, _ImmU_ ); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + +#endif +} + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.h b/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.h new file mode 100644 index 0000000..4bd7a0c --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Branch.c b/branches/pcsx2_0.9.1/x86-64/iR5900Branch.c new file mode 100644 index 0000000..6de85ad --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Branch.c @@ -0,0 +1,341 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + + if ( _Rs_ == _Rt_ ) + { + SetBranchImm( _Imm_ * 4 + pc/*, 1*/ ); + } + else + { + u32 branchTo = _Imm_ * 4 + pc; + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + if ( _Rs_ == _Rt_ ) + { + return; + } + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//#if 0 +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j8Ptr[ 1 ] = JG8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JNZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j8Ptr[ 1 ] = JL8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBLTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLEZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 2 ] ); + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZL ); + branch = 2; +} +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Branch.h b/branches/pcsx2_0.9.1/x86-64/iR5900Branch.h new file mode 100644 index 0000000..3370b8a --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Jump.c b/branches/pcsx2_0.9.1/x86-64/iR5900Jump.c new file mode 100644 index 0000000..d879ec4 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Jump.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 0 ], pc + 4 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 1 ], 0 ); + + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_ ); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + if ( _Rd_ ) { + MOV64ItoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], pc + 4 ); + } + + SetBranchReg( _Rs_ ); +} + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Jump.h b/branches/pcsx2_0.9.1/x86-64/iR5900Jump.h new file mode 100644 index 0000000..d35f87c --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.c b/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.c new file mode 100644 index 0000000..3642530 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.c @@ -0,0 +1,554 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "VU0.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +u64 retValue; +u64 dummyValue[ 4 ]; + +//////////////////////////////////////////////////// +void recLB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead8RS ); +} + +//////////////////////////////////////////////////// +void recLBU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead8RU ); +} + +//////////////////////////////////////////////////// +void recLH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead16RS ); +} + +//////////////////////////////////////////////////// +void recLHU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead16RU ); +} + +void tests() { + SysPrintf("Err\n"); +} + +//////////////////////////////////////////////////// +void recLW( void ) { + int rsreg; + int rtreg; + int t0reg; + int t1reg; + int t2reg; + +#if 0 +//def ENABLE_REGCACHING + + _freeX86regs(); + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + t0reg = _allocTempX86reg(-1); + t1reg = _allocTempX86reg(-1); + t2reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + if (_Imm_ != 0) { + ADD32ItoR(t0reg, _Imm_); + } + MOV32RtoR(t2reg, t0reg); + SHR32ItoR(t0reg, 12); + + MOV64MtoR(t1reg, (u32)&memLUTR); + MOV64RmStoR(t1reg, t1reg, t0reg, 3); + + CMP64ItoR(t1reg, 0x10); + j8Ptr[0] = JL8(0); + + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + AND32ItoR(t2reg, 0xfff); + LogX86(); + MOV64RmStoR(rtreg, t1reg, t2reg, 0); + _clearNeededX86regs(); + _freeX86regs(); + +// j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +// x86SetJ8(j8Ptr[1]); + +#else + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +#endif +} + +//////////////////////////////////////////////////// +void recLWU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RU ); +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWR ); +} + +//////////////////////////////////////////////////// +void recLD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) + { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead64 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + AND32ItoR( EDI, ~0xf ); + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead128 ); +} + +//////////////////////////////////////////////////// +void recSB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite16 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite32 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV64MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite64 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + AND32ItoR( EDI, ~0xf ); + + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite128 ); +} +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, LWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, SWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "LQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (u32)&dummyValue ); + } + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead128 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + if ( Config.Regcaching ) + { + GRecAssert( GREC_FALSE, "SQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite128 ); + ADD32ItoR( ESP, 8 ); + } +} +*/ +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.h b/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.h new file mode 100644 index 0000000..1a5b99e --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900LoadStore.h @@ -0,0 +1,56 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSQ( void ); +void recSDL( void ); +void recSDR( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Move.c b/branches/pcsx2_0.9.1/x86-64/iR5900Move.c new file mode 100644 index 0000000..46302a6 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Move.c @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#else +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLUI( void ) { + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, (s32)(_Imm_ << 16)); + _clearNeededX86regs(); +#else + MOV64ItoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (s32)(_Imm_ << 16)); +#endif +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecLog( "MFHI: PC: 0x%.8X, RD: %d, x86Ptr: 0x%.8x\n", pc, _Rd_, x86Ptr ); + + GRec_Instruction( GREC_INST_MOV64, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.HI.UD[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MFLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} +*/ +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTHI not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +*/ +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVZ: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_Z, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVN: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_NZ, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} +*/ +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Move.h b/branches/pcsx2_0.9.1/x86-64/iR5900Move.h new file mode 100644 index 0000000..ae501e3 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.c b/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.c new file mode 100644 index 0000000..0d84b8e --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.c @@ -0,0 +1,138 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); +} + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.h b/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.h new file mode 100644 index 0000000..243fd5c --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Shift.c b/branches/pcsx2_0.9.1/x86-64/iR5900Shift.c new file mode 100644 index 0000000..3950c07 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Shift.c @@ -0,0 +1,761 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#else + + +//////////////////////////////////////////////////// +void recDSRA( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SAR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRA32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SAR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SAR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHL32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SHR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHR32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRA(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SAR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHL64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHL64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHL64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + + +//////////////////////////////////////////////////// +void recSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHL64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SAR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +#endif + diff --git a/branches/pcsx2_0.9.1/x86-64/iR5900Shift.h b/branches/pcsx2_0.9.1/x86-64/iR5900Shift.h new file mode 100644 index 0000000..b7b3592 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86-64/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86/iCP0.c b/branches/pcsx2_0.9.1/x86/iCP0.c new file mode 100644 index 0000000..9c4043e --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iCP0.c @@ -0,0 +1,245 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iCP0.h" + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +#ifndef CP0_RECOMPILE + +REC_SYS(MFC0); +REC_SYS(MTC0); +REC_SYS(BC0F); +REC_SYS(BC0T); +REC_SYS(BC0FL); +REC_SYS(BC0TL); +REC_SYS(TLBR); +REC_SYS(TLBWI); +REC_SYS(TLBWR); +REC_SYS(TLBP); +REC_SYS(ERET); +REC_SYS(DI); +REC_SYS(EI); + +#else + +//////////////////////////////////////////////////// +//REC_SYS(MTC0); +//////////////////////////////////////////////////// +REC_SYS(BC0F); +//////////////////////////////////////////////////// +REC_SYS(BC0T); +//////////////////////////////////////////////////// +REC_SYS(BC0FL); +//////////////////////////////////////////////////// +REC_SYS(BC0TL); +//////////////////////////////////////////////////// +REC_SYS(TLBR); +//////////////////////////////////////////////////// +REC_SYS(TLBWI); +//////////////////////////////////////////////////// +REC_SYS(TLBWR); +//////////////////////////////////////////////////// +REC_SYS(TLBP); +//////////////////////////////////////////////////// +REC_SYS(ERET); +//////////////////////////////////////////////////// +REC_SYS(DI); +//////////////////////////////////////////////////// +REC_SYS(EI); + +//////////////////////////////////////////////////// +extern u32 s_iLastCOP0Cycle; + +void recMFC0( void ) +{ + int mmreg; + + if ( ! _Rt_ ) return; + + if( _Rd_ == 9 ) { + MOV32MtoR( EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ] ); + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + ADD32RtoR(EAX, ECX); + SUB32MtoR(EAX, (u32)&s_iLastCOP0Cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32RtoM((u32)&cpuRegs.CP0.r[ _Rd_ ], EAX); + + _deleteEEreg(_Rt_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else EEINST_RESETHASLIVE1(_Rt_); + return; + } + + _eeOnWriteReg(_Rt_, 1); + + if( EEINST_ISLIVE1(_Rt_) ) { + _deleteEEreg(_Rt_, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + + if( (mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + SetMMXstate(); + } + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + + if( EEINST_ISLIVE2(_Rt_) ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + } + else { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + } + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + } +} + +void recMTC0() +{ + if( GPR_IS_CONST1(_Rt_) ) { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32ItoM((u32)&cpuRegs.CP0.r[9], g_cpuConstRegs[_Rt_].UL[0]); + break; + default: + MOV32ItoM((u32)&cpuRegs.CP0.r[_Rd_], g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + SUB32ItoR(ESP, 4); + _eeMoveGPRtoRm(ESP, _Rt_); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[9], _Rt_); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + break; + default: + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[_Rd_], _Rt_); + break; + } + } +} + +/*void rec(COP0) { +} + +void rec(BC0F) { +} + +void rec(BC0T) { +} + +void rec(BC0FL) { +} + +void rec(BC0TL) { +} + +void rec(TLBR) { +} + +void rec(TLBWI) { +} + +void rec(TLBWR) { +} + +void rec(TLBP) { +} + +void rec(ERET) { +} +*/ +/* +//////////////////////////////////////////////////// +void recDI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + AND32ItoR(EAX, ~0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} + +//////////////////////////////////////////////////// +void recEI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + OR32ItoR(EAX, 0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} +*/ + +#endif diff --git a/branches/pcsx2_0.9.1/x86/iCP0.h b/branches/pcsx2_0.9.1/x86/iCP0.h new file mode 100644 index 0000000..52e99b7 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iCP0.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ICP0_H__ +#define __ICP0_H__ + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +void recMFC0( void ); +void recMTC0( void ); +void recCOP0( void ); +void recBC0F( void ); +void recBC0T( void ); +void recBC0FL( void ); +void recBC0TL( void ); +void recTLBR( void ); +void recTLBWI( void ); +void recTLBWR( void ); +void recTLBP( void ); +void recERET( void ); +void recDI( void ); +void recEI( void ); + +#endif diff --git a/branches/pcsx2_0.9.1/x86/iCore.cpp b/branches/pcsx2_0.9.1/x86/iCore.cpp new file mode 100644 index 0000000..f4d2578 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iCore.cpp @@ -0,0 +1,2368 @@ +#include +#include +#include +#include + +extern "C" { + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 g_x86AllocCounter = 0; +u16 g_xmmAllocCounter = 0; +u16 g_mmxAllocCounter = 0; + +u16 x86FpuState, iCWstate; +EEINST* g_pCurInstInfo = NULL; + +u32 g_cpuRegHasLive1 = 0, g_cpuPrevRegHasLive1 = 0; // set if upper 32 bits are live +u32 g_cpuRegHasSignExt = 0, g_cpuPrevRegHasSignExt = 0; // set if upper 32 bits are the sign extension of the lower integer + +// used to make sure regs don't get changed while in recompiler +// use FreezeMMXRegs, FreezeXMMRegs +u8 g_globalMMXSaved = 0, g_globalXMMSaved = 0; +u32 g_recWriteback = 0; + +#ifdef _DEBUG +char g_globalMMXLocked = 0, g_globalXMMLocked = 0; +#endif + +_xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +__declspec(align(16)) u64 g_globalMMXData[8]; +__declspec(align(16)) u64 g_globalXMMData[2*XMMREGS]; + +// X86 caching +_x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; +static int s_x86checknext = 0; + +} // end extern "C" + +#include + +void _initX86regs() { + memset(x86regs, 0, sizeof(x86regs)); + g_x86AllocCounter = 0; + s_x86checknext = 0; +} + +__forceinline u32 _x86GetAddr(int type, int reg) +{ + switch(type&~X86TYPE_VU1) { + case X86TYPE_GPR: return (u32)&cpuRegs.GPR.r[reg]; + case X86TYPE_VI: { + //assert( reg < 16 || reg == REG_R ); + return (type&X86TYPE_VU1)?(u32)&VU1.VI[reg]:(u32)&VU0.VI[reg]; + } + case X86TYPE_MEMOFFSET: return 0; + case X86TYPE_VIMEMOFFSET: return 0; + case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.q:(u32)&VU0.q; + case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.p:(u32)&VU0.p; + case X86TYPE_PSX: return (u32)&psxRegs.GPR.r[reg]; + case X86TYPE_PCWRITEBACK: + return (u32)&g_recWriteback; + case X86TYPE_VUJUMP: + return (u32)&g_recWriteback; + default: assert(0); + } + + return 0; +} + +int _getFreeX86reg(int mode) +{ + int i, tempi; + u32 bestcount = 0x10000; + + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + + for (i=0; i= maxreg ) continue; + if( (mode&MODE_NOFRAME) && reg==EBP ) continue; + + if (x86regs[reg].inuse == 0) { + s_x86checknext = (reg+1)%X86REGS; + return reg; + } + } + + tempi = -1; + for (i=1; i= 0 && reg < 32 ); + +// if( X86_ISVI(type) ) +// assert( reg < 16 || reg == REG_R ); + + // don't alloc EAX and ESP,EBP if MODE_NOFRAME + int oldmode = mode; + int noframe = mode&MODE_NOFRAME; + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + mode &= ~(MODE_NOFRAME|MODE_8BITREG); + int readfromreg = -1; + + if( type != X86TYPE_TEMP ) { + + if( maxreg < X86REGS ) { + // make sure reg isn't in the higher regs + + for(i = maxreg; i < X86REGS; ++i) { + if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) continue; + + if( mode & MODE_READ ) { + readfromreg = i; + x86regs[i].inuse = 0; + break; + } + else if( mode & MODE_WRITE ) { + x86regs[i].inuse = 0; + break; + } + } + } + + for (i=1; i= maxreg) ) { + if( x86regs[i].mode & MODE_READ ) + readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + + if( x86reg >= 0 ) { + // requested specific reg, so return that instead + if( i != x86reg ) { + if( x86regs[i].mode & MODE_READ ) readfromreg = i; + //if( x86regs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + } + + if( type != X86TYPE_TEMP && !(x86regs[i].mode & MODE_READ) && (mode&MODE_READ)) { + + if( type == X86TYPE_GPR ) _flushConstReg(reg); + + if( X86_ISVI(type) && reg < 16 ) MOVZX32M16toR(i, _x86GetAddr(type, reg)); + else MOV32MtoR(i, _x86GetAddr(type, reg)); + + x86regs[i].mode |= MODE_READ; + } + + x86regs[i].needed = 1; + x86regs[i].mode|= mode; + return i; + } + } + + if (x86reg == -1) { + x86reg = _getFreeX86reg(oldmode); + } + else { + _freeX86reg(x86reg); + } + + x86regs[x86reg].type = type; + x86regs[x86reg].reg = reg; + x86regs[x86reg].mode = mode; + x86regs[x86reg].needed = 1; + x86regs[x86reg].inuse = 1; + + if( mode & MODE_READ ) { + if( readfromreg >= 0 ) MOV32RtoR(x86reg, readfromreg); + else { + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) { + XOR32RtoR(x86reg, x86reg); + } + else { + _flushConstReg(reg); + _deleteMMXreg(MMX_GPR+reg, 1); + _deleteGPRtoXMMreg(reg, 1); + + _eeMoveGPRtoR(x86reg, reg); + + _deleteMMXreg(MMX_GPR+reg, 0); + _deleteGPRtoXMMreg(reg, 0); + } + } + else { + if( X86_ISVI(type) && reg < 16 ) { + if( reg == 0 ) XOR32RtoR(x86reg, x86reg); + else MOVZX32M16toR(x86reg, _x86GetAddr(type, reg)); + } + else MOV32MtoR(x86reg, _x86GetAddr(type, reg)); + } + } +} + + return x86reg; +} + +int _checkX86reg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 && x86reg < X86REGS ); + + if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { + x86regs[x86reg].mode &= ~MODE_WRITE; + + if( X86_ISVI(x86regs[x86reg].type) && x86regs[x86reg].reg < 16 ) { + MOV16RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + else + MOV32RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + + x86regs[x86reg].inuse = 0; +} + +void _freeX86regs() { + int i; + + for (i=0; i= 0 ) return -1; + + if( poffset ) *poffset = x86regs[i].extra; + return i; +} + +// MMX Caching +_mmxregs mmxregs[8], s_saveMMXregs[8]; +static int s_mmxchecknext = 0; + +void _initMMXregs() +{ + memset(mmxregs, 0, sizeof(mmxregs)); + g_mmxAllocCounter = 0; + s_mmxchecknext = 0; +} + +__forceinline void* _MMXGetAddr(int reg) +{ + assert( reg != MMX_TEMP ); + + if( reg == MMX_LO ) return &cpuRegs.LO; + if( reg == MMX_HI ) return &cpuRegs.HI; + if( reg == MMX_FPUACC ) return &fpuRegs.ACC; + + if( reg >= MMX_GPR && reg < MMX_GPR+32 ) return &cpuRegs.GPR.r[reg&31]; + if( reg >= MMX_FPU && reg < MMX_FPU+32 ) return &fpuRegs.fpr[reg&31]; + if( reg >= MMX_COP0 && reg < MMX_COP0+32 ) return &cpuRegs.CP0.r[reg&31]; + + assert( 0 ); + return NULL; +} + +int _getFreeMMXreg() +{ + int i, tempi; + u32 bestcount = 0x10000; + + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) { + _freeMMXreg(i); + return i; + } + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + _freeMMXreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) { + _freeMMXreg(i); + return i; + } + } + } + + tempi = -1; + for (i=0; i= 0 ) { + if (cpucaps.hasStreamingSIMD2Extensions) { + SSE_MOVHPS_XMM_to_M64((u32)_MMXGetAddr(reg)+8, xmmreg); + if( mode & MODE_READ ) + SSE2_MOVDQ2Q_XMM_to_MM(mmxreg, xmmreg); + + if( xmmregs[xmmreg].mode & MODE_WRITE ) + mmxregs[mmxreg].mode |= MODE_WRITE; + + // don't flush + xmmregs[xmmreg].inuse = 0; + } + else { + _freeXMMreg(xmmreg); + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + + } + } + else { + if( MMX_ISGPR(reg) ) { + if(mode&(MODE_READHALF|MODE_READ)) _flushConstReg(reg-MMX_GPR); + } + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + } + } + + return mmxreg; +} + +int _checkMMXreg(int reg, int mode) +{ + int i; + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !EEINST_ISLIVEMMX(mmxregs[i].reg-MMX_GPR) ) { + return 1; + } + } + } + + // check for dead regs + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + return 1; + } + } + } + + return 0; +} + +void _freeMMXreg(int mmxreg) +{ + assert( mmxreg < MMXREGS ); + if (!mmxregs[mmxreg].inuse) return; + + if (mmxregs[mmxreg].mode & MODE_WRITE ) { + + if( mmxregs[mmxreg].reg >= MMX_GPR && mmxregs[mmxreg].reg < MMX_GPR+32 ) + assert( !(g_cpuHasConstReg & (1<<(mmxregs[mmxreg].reg-MMX_GPR))) ); + + assert( mmxregs[mmxreg].reg != MMX_GPR ); + + if( MMX_IS32BITS(mmxregs[mmxreg].reg) ) + MOVDMMXtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + else + MOVQRtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + + SetMMXstate(); + } + + mmxregs[mmxreg].mode &= ~MODE_WRITE; + mmxregs[mmxreg].inuse = 0; +} + +void _moveMMXreg(int mmxreg) +{ + int i; + if( !mmxregs[mmxreg].inuse ) return; + + for (i=0; iVF[x].UL[0] +#define VU_ACCx_ADDR (u32)&VU->ACC.UL[0] + +static int s_xmmchecknext = 0; + +void _initXMMregs() { + memset(xmmregs, 0, sizeof(xmmregs)); + g_xmmAllocCounter = 0; + s_xmmchecknext = 0; +} + +__forceinline void* _XMMGetAddr(int type, int reg, VURegs *VU) +{ + if (type == XMMTYPE_VFREG ) return (void*)VU_VFx_ADDR(reg); + else if (type == XMMTYPE_ACC ) return (void*)VU_ACCx_ADDR; + else if (type == XMMTYPE_GPRREG) { + if( reg < 32 ) + assert( !(g_cpuHasConstReg & (1<regs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + _freeXMMreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; iregs[xmmregs[i].reg] & EEINST_XMM) ) { + _freeXMMreg(i); + return i; + } + } + } + + tempi = -1; + bestcount = 0xffff; + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + xmmregs[i].needed = 1; + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ) ) { + SSE_MOVAPS_M128_to_XMM(i, VU_VFx_ADDR(vfreg)); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_VFREG; + xmmregs[xmmreg].reg = vfreg; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_VFx_ADDR(xmmregs[xmmreg].reg)); + } + + return xmmreg; +} + +int _checkXMMreg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ)) { + SSE_MOVAPS_M128_to_XMM(i, VU_ACCx_ADDR); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].needed = 1; + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_ACC; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + xmmregs[xmmreg].reg = 0; + + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_ACCx_ADDR); + } + + return xmmreg; +} + +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode) { + int i; + + for (i=0; i= 0 ) { + // transfer + if (cpucaps.hasStreamingSIMD2Extensions ) { + + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(xmmreg, mmxreg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(xmmreg, xmmreg); + SSE2_PUNPCKHQDQ_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + + if( mmxregs[mmxreg].mode & MODE_WRITE ) { + + // instead of setting to write, just flush to mem + if( !(mode & MODE_WRITE) ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], mmxreg); + } + //xmmregs[xmmreg].mode |= MODE_WRITE; + } + + // don't flush + mmxregs[mmxreg].inuse = 0; + } + else { + _freeMMXreg(mmxreg); + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + else { + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + } + else { + _deleteMMXreg(MMX_GPR+gprreg, 0); + } + + return xmmreg; +} + +int _allocFPACCtoXMMreg(int xmmreg, int mode) { + int i; + + for (i=0; iregs[xmmregs[i].reg]&EEINST_USED) ) { + return 1; + } + } + } + return 0; +} + +void _moveXMMreg(int xmmreg) +{ + int i; + if( !xmmregs[xmmreg].inuse ) return; + + for (i=0; i= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) { + SSE2_MOVD_XMM_to_R(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) { + MOVD32MMXtoR(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + } + } +} + +void _eeMoveGPRtoM(u32 to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_M32(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVDMMXtoM(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoM(to, EAX ); + } + } +} + +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_Rm(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVD32MMXtoRm(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoRm(to, EAX ); + } + } +} + +// PSX +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoR( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(to, (int)&psxRegs.GPR.r[ fromgpr ] ); + } +} + +void _psxMoveGPRtoM(u32 to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoM(to, EAX ); + } +} + +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoRm(to, EAX ); + } +} + +void _recPushReg(int mmreg) +{ + if( IS_XMMREG(mmreg) ) { + SUB32ItoR(ESP, 4); + SSEX_MOVD_XMM_to_Rm(ESP, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + SUB32ItoR(ESP, 4); + MOVD32MMXtoRm(ESP, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + PUSH32I(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + PUSH32I(g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else PUSH32R(mmreg); +} + +void _signExtendSFtoM(u32 mem) +{ + LAHF(); + SAR16ItoR(EAX, 15); + CWDE(); + MOV32RtoM(mem, EAX ); +} + +int _signExtendMtoMMX(x86MMXRegType to, u32 mem) +{ + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, mem); + MOVQRtoR(to, t0reg); + PSRADItoR(t0reg, 31); + PUNPCKLDQRtoR(to, t0reg); + _freeMMXreg(t0reg); + return to; +} + +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg) +{ + assert( to >= 0 && from >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + EEINST_RESETHASLIVE1(gprreg); + if( to != from ) MOVQRtoR(to, from); + return to; + } + + if( to == from ) return _signExtendGPRtoMMX(to, gprreg, 0); + if( !(g_pCurInstInfo->regs[gprfromreg]&EEINST_LASTUSE) ) { + if( EEINST_ISLIVEMMX(gprfromreg) ) { + MOVQRtoR(to, from); + return _signExtendGPRtoMMX(to, gprreg, 0); + } + } + + // from is free for use + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + + if( EEINST_ISLIVEMMX(gprfromreg) ) { + _freeMMXreg(from); + } + + MOVQRtoR(to, from); + PSRADItoR(from, 31); + PUNPCKLDQRtoR(to, from); + return to; + } + else { + MOVQRtoR(to, from); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], from); + PSRADItoR(from, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], from); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift) +{ + assert( to >= 0 && shift >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + if( shift > 0 ) PSRADItoR(to, shift); + EEINST_RESETHASLIVE1(gprreg); + return to; + } + + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, to); + PSRADItoR(to, 31); + if( shift > 0 ) PSRADItoR(t0reg, shift); + PUNPCKLDQRtoR(t0reg, to); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[to]; + mmxregs[to].inuse = 0; + return t0reg; + } + else { + // will be used in the future as mmx + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + + // read again + MOVQMtoR(to, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + mmxregs[to].mode &= ~MODE_WRITE; + return to; + } + } + else { + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +__declspec(align(16)) u32 s_zeros[4] = {0}; +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy) +{ + int t0reg; +// if( g_xmmtypes[from] == XMMT_FPS && (!candestroy || _hasFreeXMMreg()) ) { +// // special floating point implementation +// // NOTE: doesn't sign extend 0x80000000 +// xmmregs[from].needed = 1; +// t0reg = _allocTempXMMreg(XMMT_FPS, -1); +// SSE_XORPS_XMM_to_XMM(t0reg, t0reg); +// SSE_MOVSS_XMM_to_M32(to, from); +// SSE_CMPNLESS_XMM_to_XMM(t0reg, from); +// SSE_MOVSS_XMM_to_M32(to+4, t0reg); +// _freeXMMreg(t0reg); +// return 0; +// } +// else { + g_xmmtypes[from] = XMMT_INT; + if( candestroy ) { + if( g_xmmtypes[from] == XMMT_FPS || !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVSS_XMM_to_M32(to, from); + else SSE2_MOVD_XMM_to_M32(to, from); + +// if( g_xmmtypes[from] == XMMT_FPS ) { +// SSE_CMPLTSS_M32_to_XMM(from, (u32)&s_zeros[0]); +// SSE_MOVSS_XMM_to_M32(to+4, from); +// return 1; +// } +// else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to+4, from); + return 1; + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SAR32ItoM(to+4, 31); + return 0; + } +// } + } + else { + // can't destroy and type is int + assert( g_xmmtypes[from] == XMMT_INT ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _hasFreeXMMreg() ) { + xmmregs[from].needed = 1; + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, from); + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to, t0reg); + SSE2_MOVD_XMM_to_M32(to+4, from); + + // swap xmm regs.. don't ask + xmmregs[t0reg] = xmmregs[from]; + xmmregs[from].inuse = 0; + } + else { + SSE2_MOVD_XMM_to_M32(to+4, from); + SSE2_MOVD_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SSE_MOVSS_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + + return 0; + } + //} + + assert(0); +} + +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode) +{ + if( pinst->regs[gprreg] & EEINST_XMM ) return _allocGPRtoXMMreg(-1, gprreg, mode); + + return _checkXMMreg(XMMTYPE_GPRREG, gprreg, mode); +} + +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode) +{ + if( pinst->fpuregs[fpureg] & EEINST_XMM ) return _allocFPtoXMMreg(-1, fpureg, mode); + + return _checkXMMreg(XMMTYPE_FPREG, fpureg, mode); +} + +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode) +{ + if( pinst->regs[reg] & EEINST_MMX ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + + return _checkMMXreg(MMX_GPR+reg, mode); +} + +void _recClearInst(EEINST* pinst) +{ + memset(&pinst->regs[0], EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2, sizeof(pinst->regs)); + memset(&pinst->fpuregs[0], EEINST_LIVE0, sizeof(pinst->fpuregs)); + memset(&pinst->info, 0, sizeof(EEINST)-sizeof(pinst->regs)-sizeof(pinst->fpuregs)); +} + +// returns nonzero value if reg has been written between [startpc, endpc-4] +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == xmmtype && pinst->readReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +void _recFillRegister(EEINST* pinst, int type, int reg, int write) +{ + int i = 0; + if( write ) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == XMMTYPE_TEMP ) { + pinst->writeType[i] = type; + pinst->writeReg[i] = reg; + return; + } + } + assert(0); + } + else { + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == XMMTYPE_TEMP ) { + pinst->readType[i] = type; + pinst->readReg[i] = reg; + return; + } + } + assert(0); + } +} + +// Writebacks // +void _recClearWritebacks() +{ +} + +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent) +{ +} + +EEINSTWRITEBACK* _recCheckWriteBack(int cycle) +{ + return NULL; +} + +__declspec(align(16)) static u32 s_ones[2] = {0xffffffff, 0xffffffff}; + +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op) +{ + switch(op) { + case 0: PANDRtoR(to, from); break; + case 1: PORRtoR(to, from); break; + case 2: PXORRtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op) +{ + switch(op) { + case 0: PANDMtoR(to, from); break; + case 1: PORMtoR(to, from); break; + case 2: PXORMtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND32RtoM(to, from); break; + case 1: OR32RtoM(to, from); break; + case 2: XOR32RtoM(to, from); break; + case 3: OR32RtoM(to, from); break; + } +} + +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32MtoR(to, from); break; + case 1: OR32MtoR(to, from); break; + case 2: XOR32MtoR(to, from); break; + case 3: OR32MtoR(to, from); break; + } +} + +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoR(to, from); break; + case 1: OR32ItoR(to, from); break; + case 2: XOR32ItoR(to, from); break; + case 3: OR32ItoR(to, from); break; + } +} + +void LogicalOp32ItoM(u32 to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoM(to, from); break; + case 1: OR32ItoM(to, from); break; + case 2: XOR32ItoM(to, from); break; + case 3: OR32ItoM(to, from); break; + } +} + +using namespace std; + +struct BASEBLOCKS +{ + // 0 - ee, 1 - iop + inline void Add(BASEBLOCKEX*); + inline void Remove(BASEBLOCKEX*); + inline int Get(u32 startpc); + inline void Reset(); + + inline BASEBLOCKEX** GetAll(int* pnum); + + vector blocks; +}; + +void BASEBLOCKS::Add(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + + switch(blocks.size()) { + case 0: + blocks.push_back(pex); + return; + case 1: + assert( blocks.front()->startpc != pex->startpc ); + + if( blocks.front()->startpc < pex->startpc ) { + blocks.push_back(pex); + } + else blocks.insert(blocks.begin(), pex); + + return; + + default: + { + int imin = 0, imax = blocks.size(), imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > pex->startpc ) imax = imid; + else imin = imid+1; + } + + assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc ); + if( imin > 0 ) assert( blocks[imin-1]->startpc < pex->startpc ); + blocks.insert(blocks.begin()+imin, pex); + + return; + } + } +} + +int BASEBLOCKS::Get(u32 startpc) +{ + switch(blocks.size()) { + case 1: + return 0; + case 2: + return blocks.front()->startpc < startpc; + + default: + { + int imin = 0, imax = blocks.size()-1, imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > startpc ) imax = imid; + else if( blocks[imid]->startpc == startpc ) return imid; + else imin = imid+1; + } + + assert( blocks[imin]->startpc == startpc ); + return imin; + } + } +} + +void BASEBLOCKS::Remove(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + int i = Get(pex->startpc); + assert( blocks[i] == pex ); + blocks.erase(blocks.begin()+i); +} + +void BASEBLOCKS::Reset() +{ + blocks.resize(0); + blocks.reserve(512); +} + +BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum) +{ + assert( pnum != NULL ); + *pnum = blocks.size(); + return &blocks[0]; +} + +static BASEBLOCKS s_vecBaseBlocksEx[2]; + +void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Add(pex); +} + +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu) +{ + return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)]; +} + +void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Remove(pex); +} + +void ResetBaseBlockEx(int cpu) +{ + s_vecBaseBlocksEx[cpu].Reset(); +} + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu) +{ + return s_vecBaseBlocksEx[cpu].GetAll(pnum); +} diff --git a/branches/pcsx2_0.9.1/x86/iCore.h b/branches/pcsx2_0.9.1/x86/iCore.h new file mode 100644 index 0000000..7fdc856 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iCore.h @@ -0,0 +1,416 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_CORE_RECOMPILER_ +#define _PCSX2_CORE_RECOMPILER_ + +#include "ivumicro.h" + +// used to keep block information +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +typedef struct _BASEBLOCK +{ + u32 pFnptr : 28; + u32 uType : 4; + u32 startpc; +} BASEBLOCK; + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +// extra block info (only valid for start of fn) +typedef struct _BASEBLOCKEX +{ + u16 size; // size in dwords + u16 dummy; + u32 startpc; // for debugging? + +#ifdef PCSX2_DEVBUILD + u32 visited; // number of times called + LARGE_INTEGER ltime; // regs it assumes to have set already +#endif + +} BASEBLOCKEX; + +#define GET_BLOCKTYPE(b) ((b)->Type) +#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + +#define FPU_STATE 0 +#define MMX_STATE 1 + +#define X86TYPE_TEMP 0 +#define X86TYPE_GPR 1 +#define X86TYPE_VI 2 +#define X86TYPE_MEMOFFSET 3 +#define X86TYPE_VIMEMOFFSET 4 +#define X86TYPE_VUQREAD 5 +#define X86TYPE_VUPREAD 6 +#define X86TYPE_VUQWRITE 7 +#define X86TYPE_VUPWRITE 8 +#define X86TYPE_PSX 9 +#define X86TYPE_PCWRITEBACK 10 +#define X86TYPE_VUJUMP 12 // jump from random mem (g_recWriteback) + +#define X86TYPE_VU1 0x80 + +#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u8 type; // X86TYPE_ + u16 counter; + u32 extra; // extra info assoc with the reg +} _x86regs; + +extern _x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; + +void _initX86regs(); +int _getFreeX86reg(int mode); +int _allocX86reg(int x86reg, int type, int reg, int mode); +void _deleteX86reg(int type, int reg, int flush); +int _checkX86reg(int type, int reg, int mode); +void _addNeededX86reg(int type, int reg); +void _clearNeededX86regs(); +void _freeX86reg(int x86reg); +void _freeX86regs(); + +void _eeSetLoadStoreReg(int gprreg, u32 offset, int x86reg); +int _eeGeLoadStoreReg(int gprreg, int* poffset); + +void recReset(); + +// when using mmx/xmm regs, use; 0 is load +// freezes no matter the state +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +void SetFPUstate(); +void SetMMXstate(); + +#define MODE_READ 1 +#define MODE_WRITE 2 +#define MODE_READHALF 4 // read only low 64 bits +#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF +#define MODE_VUZ 0x10 // z only doesn't work for now +#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory) +#define MODE_NOFLUSH 0x20 // can't flush reg to mem +#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg +#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx + +// max is 0x7f, when 0x80 is set, need to flush reg +#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index] +#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0; +#define MMX_GPR 0 +#define MMX_HI 32 +#define MMX_LO 33 +#define MMX_FPUACC 34 +#define MMX_FPU 64 +#define MMX_COP0 96 +#define MMX_TEMP 0x7f + +#define MMX_IS32BITS(x) (((x)>=MMX_FPU&&(x)= MMX_GPR && (x) < MMX_GPR+34) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u16 counter; +} _mmxregs; + +void _initMMXregs(); +int _getFreeMMXreg(); +int _allocMMXreg(int MMXreg, int reg, int mode); +void _addNeededMMXreg(int reg); +int _checkMMXreg(int reg, int mode); +void _clearNeededMMXregs(); +void _deleteMMXreg(int reg, int flush); +void _freeMMXreg(int mmxreg); +void _moveMMXreg(int mmxreg); // instead of freeing, moves it to a diff location +void _flushMMXregs(); +u8 _hasFreeMMXreg(); +void _freeMMXregs(); +int _getNumMMXwrite(); + +void _flushCachedRegs(); +void _flushConstRegs(); +void _flushConstReg(int reg); + +// return type: 0 - const, 1 - mmx, 2 - xmm +#define PROCESS_EE_MMX 0x01 +#define PROCESS_EE_XMM 0x02 + +// currently only used in FPU +#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem +#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem + +// not used in VU recs +#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs +#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs +#define PROCESS_EE_LO 0x40 // lo reg is valid +#define PROCESS_EE_HI 0x80 // hi reg is valid +#define PROCESS_EE_ACC 0x40 // acc reg is valid + +// used in VU recs +#define PROCESS_VU_UPDATEFLAGS 0x10 +#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation +#define PROCESS_VU_COP2 0x80 // simple cop2 + +#define EEREC_S (((info)>>8)&0xf) +#define EEREC_T (((info)>>12)&0xf) +#define EEREC_D (((info)>>16)&0xf) +#define EEREC_LO (((info)>>20)&0xf) +#define EEREC_HI (((info)>>24)&0xf) +#define EEREC_ACC (((info)>>20)&0xf) +#define EEREC_TEMP (((info)>>24)&0xf) + +#define PROCESS_EE_SET_S(reg) ((reg)<<8) +#define PROCESS_EE_SET_T(reg) ((reg)<<12) +#define PROCESS_EE_SET_D(reg) ((reg)<<16) +#define PROCESS_EE_SET_LO(reg) ((reg)<<20) +#define PROCESS_EE_SET_HI(reg) ((reg)<<24) +#define PROCESS_EE_SET_ACC(reg) ((reg)<<20) + +#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg) +#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24) + +// special info not related to above flags +#define PROCESS_CONSTS 1 +#define PROCESS_CONSTT 2 + +#define XMM_CONV_VU(VU) (VU==&VU1) + +#define XMMTYPE_TEMP 0 // has to be 0 +#define XMMTYPE_VFREG 1 +#define XMMTYPE_ACC 2 +#define XMMTYPE_FPREG 3 +#define XMMTYPE_FPACC 4 +#define XMMTYPE_GPRREG 5 + +// lo and hi regs +#define XMMGPR_LO MMX_LO +#define XMMGPR_HI MMX_HI +#define XMMFPU_ACC 32 + +typedef struct { + u8 inuse; + u8 reg; + u8 type; + u8 mode; + u8 needed; + u8 VU; // 0 = VU0, 1 = VU1 + u16 counter; +} _xmmregs; + +void _initXMMregs(); +int _getFreeXMMreg(); +int _allocTempXMMreg(XMMSSEType type, int xmmreg); +int _allocVFtoXMMreg(VURegs *VU, int xmmreg, int vfreg, int mode); +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode); +int _allocGPRtoXMMreg(int xmmreg, int gprreg, int mode); +int _allocACCtoXMMreg(VURegs *VU, int xmmreg, int mode); +int _allocFPACCtoXMMreg(int xmmreg, int mode); +int _checkXMMreg(int type, int reg, int mode); +void _addNeededVFtoXMMreg(int vfreg); +void _addNeededACCtoXMMreg(); +void _addNeededFPtoXMMreg(int fpreg); +void _addNeededFPACCtoXMMreg(); +void _addNeededGPRtoXMMreg(int gprreg); +void _clearNeededXMMregs(); +void _deleteVFtoXMMreg(int reg, int vu, int flush); +void _deleteACCtoXMMreg(int vu, int flush); +void _deleteGPRtoXMMreg(int reg, int flush); +void _deleteFPtoXMMreg(int reg, int flush); +void _freeXMMreg(int xmmreg); +void _moveXMMreg(int xmmreg); // instead of freeing, moves it to a diff location +void _flushXMMregs(); +u8 _hasFreeXMMreg(); +void _freeXMMregs(); +int _getNumXMMwrite(); + +// Constants used for controlling iFlushCall, _psxFlushCall +#define FLUSH_CACHED_REGS 1 +#define FLUSH_FLUSH_XMM 2 +#define FLUSH_FREE_XMM 4 // both flushes and frees +#define FLUSH_FLUSH_MMX 8 +#define FLUSH_FREE_MMX 16 // both flushes and frees + +#define FLUSH_EVERYTHING 0xff +// no freeing, used when callee won't destroy mmx/xmm regs +#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX) +// used when regs aren't going to be changed be callee +#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX) + +// Note: All functions with _ee prefix are for EE only + +// finds where the GPR is stored and moves lower 32 bits to EAX +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr); +void _eeMoveGPRtoM(u32 to, int fromgpr); +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr); + +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr); +void _psxMoveGPRtoM(u32 to, int fromgpr); +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); + +// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs +void _recPushReg(int mmreg); + +void _signExtendSFtoM(u32 mem); +int _signExtendMtoMMX(x86MMXRegType to, u32 mem); +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg); + +// returns new index of reg, lower 32 bits already in mmx +// shift is used when the data is in the top bits of the mmx reg to begin with +// a negative shift is for sign extension +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift); +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns true if reg destroyed + +// Defines for passing register info + +// only valid during writes. If write128, then upper 64bits are in an mmxreg +// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f) +#define MEM_EECONSTTAG 0x0100 +#define MEM_PSXCONSTTAG 0x0200 +// mmreg is mmxreg +#define MEM_MMXTAG 0x0800 +// mmreg is xmmreg +#define MEM_XMMTAG 0x8000 + +#define IS_CONSTREG(reg) ((reg)&MEM_EECONSTTAG) +#define IS_PSXCONSTREG(reg) ((reg)&MEM_PSXCONSTTAG) +#define IS_MMXREG(reg) ((reg)&MEM_MMXTAG) +#define IS_XMMREG(reg) ((reg)&MEM_XMMTAG) + +////////////////////// +// Instruction Info // +////////////////////// +#define EEINST_LIVE0 1 // if var is ever used (read or write) +#define EEINST_LIVE1 2 // if cur var's next 32 bits are needed +#define EEINST_LIVE2 4 // if cur var's next 64 bits are needed +#define EEINST_LASTUSE 8 // if var isn't written/read anymore +#define EEINST_MMX 0x10 // var will be used in mmx ops +#define EEINST_XMM 0x20 // var will be used in xmm ops (takes precedence +#define EEINST_USED 0x40 + +#define EEINSTINFO_COP1 1 +#define EEINSTINFO_COP2 2 +#define EEINSTINFO_NOREC 4 // if set, inst is recompiled alone +#define EEINSTINFO_COREC 8 // if set, inst is recompiled with another similar inst +#define EEINSTINFO_MMX EEINST_MMX +#define EEINSTINFO_XMM EEINST_XMM + +typedef struct _EEINST +{ + u8 regs[34]; // includes HI/LO (HI=32, LO=33) + u8 fpuregs[33]; // ACC=32 + u8 info; // extra info, if 1 inst is COP1, 2 inst is COP2. Also uses EEINST_MMX|EEINST_XMM + + // uses XMMTYPE_ flags; if type == XMMTYPE_TEMP, not used + u8 writeType[3], writeReg[3]; // reg written in this inst, 0 if no reg + u8 readType[4], readReg[4]; + + // valid if info & EEINSTINFO_COP2 + int cycle; // cycle of inst (at offset from block) + _VURegsNum vuregs; + + u8 numpeeps; // number of peephole optimizations +} EEINST; + +extern EEINST* g_pCurInstInfo; // info for the cur instruction +void _recClearInst(EEINST* pinst); + +// returns the number of insts + 1 until written (0 if not written) +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg); +// returns the number of insts + 1 until used (0 if not used) +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg); +void _recFillRegister(EEINST* pinst, int type, int reg, int write); + +#define EEINST_ISLIVEMMX(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)) +#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) +#define EEINST_ISLIVE1(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE1) +#define EEINST_ISLIVE2(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE2) + +#define FPUINST_ISLIVE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0) +#define FPUINST_LASTUSE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE) + +// if set, then the variable at this inst really has its upper 32 bits valid +// The difference between EEINST_LIVE1 is that the latter is used in back propagation +// The former is set at recompile time. +#define EEINST_RESETHASLIVE1(reg) { if( (reg) < 32 ) g_cpuRegHasLive1 &= ~(1<<(reg)); } +#define EEINST_HASLIVE1(reg) (g_cpuPrevRegHasLive1&(1<<(reg))) + +#define EEINST_SETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt |= (1<<(reg)); } +#define EEINST_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); } +#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg))) + +// writeback inst (used for cop2) +typedef struct _EEINSTWRITEBACK +{ + int cycle; + u32 viwrite; // mask of written viregs (REG_STATUS_FLAG and REG_MAC_FLAG are treated the same) + EEINST* parent; +} EEINSTWRITEBACK; + +void _recClearWritebacks(); +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent); + +// if cycle == -1, returns the next writeback (used for flushing) +EEINSTWRITEBACK* _recCheckWriteBack(int cycle); + +extern u32 g_recWriteback; // used for jumps +extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1; +extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt; + +extern u16 x86FpuState, iCWstate; +extern u8 g_globalMMXSaved, g_globalXMMSaved; +extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS]; +extern _xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalXMMLocked; +#endif + +// allocates only if later insts use XMM, otherwise checks +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode); +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode); +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode); + +// op = 0, and +// op = 1, or +// op = 2, xor +// op = 3, nor (the 32bit versoins only do OR) +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoM(u32 to, u32 from, int op); + +// 0 - ee, 1 - iop +void AddBaseBlockEx(BASEBLOCKEX*, int cpu); +void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu); +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu); +void ResetBaseBlockEx(int cpu); + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu); + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iFPU.c b/branches/pcsx2_0.9.1/x86/iFPU.c new file mode 100644 index 0000000..8e94d0e --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iFPU.c @@ -0,0 +1,1364 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iFPU.h" + +#define REC_FPUBRANCH(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ + branch = 2; \ +} + +#define REC_FPUFUNC(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ +} + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +extern u32 g_minvals[4], g_maxvals[4]; + +void SetQFromStack(u32 mem) +{ + write16(0xe5d9); + FNSTSWtoAX(); + write8(0x9e); + j8Ptr[0] = JAE8(0); // jnc + + // sign bit is in bit 9 of EAX + FSTP(0); // pop + AND32ItoR(EAX, 0x200); + SHL32ItoR(EAX, 22); + OR32MtoR(EAX, (u32)&g_maxvals[0]); + MOV32RtoM(mem, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + // just pop + FSTP32(mem); + x86SetJ8(j8Ptr[1]); +} + +//////////////////////////////////////////////////// +void recMFC1(void) { + int regt, regs; + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + if( regs >= 0 ) { + _deleteGPRtoXMMreg(_Rt_, 2); + regt = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + + if( regt >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regt, regs); + + if(EEINST_ISLIVE1(_Rt_)) _signExtendGPRtoMMX(regt, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + if(EEINST_ISLIVE1(_Rt_)) { + _signExtendXMMtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs); + } + } + } + else if( (regs = _checkMMXreg(MMX_FPU+_Fs_, MODE_READ)) >= 0 ) { + // convert to mmx reg + mmxregs[regs].reg = MMX_GPR+_Rt_; + mmxregs[regs].mode |= MODE_READ|MODE_WRITE; + _signExtendGPRtoMMX(regs, _Rt_, 0); + } + else { + regt = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } + + _deleteEEreg(MMX_GPR+_Rt_, 0); + + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCFC1(void) +{ + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + MOV32MtoR( EAX, (u32)&fpuRegs.fprc[ _Fs_ ] ); + _deleteEEreg(_Rt_, 0); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } +} + +//////////////////////////////////////////////////// +void recMTC1(void) +{ + if( GPR_IS_CONST1(_Rt_) ) { + _deleteFPtoXMMreg(_Fs_, 0); + MOV32ItoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + if( g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE ) { + // transfer the reg directly + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteFPtoXMMreg(_Fs_, 2); + _allocFPtoXMMreg(mmreg, _Fs_, MODE_WRITE); + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) SSE_MOVSS_XMM_to_XMM(mmreg2, mmreg); + else SSE_MOVSS_XMM_to_M32((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + + if( cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(mmreg2, mmreg); + } + else { + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + _deleteFPtoXMMreg(_Fs_, 0); + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + + if( mmreg2 >= 0 ) SSE_MOVSS_M32_to_XMM(mmreg2, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + MOV32RtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, EAX); + } + } + } +} + +//////////////////////////////////////////////////// +void recCTC1( void ) +{ + if( GPR_IS_CONST1(_Rt_)) { + MOV32ItoM((u32)&fpuRegs.fprc[ _Fs_ ], g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + SSEX_MOVD_XMM_to_M32((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + SetMMXstate(); + } + else { + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&fpuRegs.fprc[ _Fs_ ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCOP1_BC1() +{ + recCP1BC1[_Rt_](); +} + +static u32 _mxcsr = 0x7F80; +static u32 _mxcsrs; +static u32 fpucw = 0x007f; +static u32 fpucws = 0; + +//////////////////////////////////////////////////// +void SaveCW(int type) { + if (iCWstate & type) return; + + if (type == 2) { +// SSE_STMXCSR((u32)&_mxcsrs); +// SSE_LDMXCSR((u32)&_mxcsr); + } else { + FNSTCW( (u32)&fpucws ); + FLDCW( (u32)&fpucw ); + } + iCWstate|= type; +} + +//////////////////////////////////////////////////// +void LoadCW( void ) { + if (iCWstate == 0) return; + + if (iCWstate & 2) { + //SSE_LDMXCSR((u32)&_mxcsrs); + } + if (iCWstate & 1) { + FLDCW( (u32)&fpucws ); + } + iCWstate = 0; +} + +//////////////////////////////////////////////////// +void recCOP1_S( void ) +{ + if( !EE_FPU_REGCACHING || !cpucaps.hasStreamingSIMD2Extensions) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1S[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +void recCOP1_W( void ) +{ + if( !EE_FPU_REGCACHING ) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1W[ _Funct_ ]( ); +} + +#ifndef FPU_RECOMPILE + + +REC_FPUFUNC(ADD_S); +REC_FPUFUNC(SUB_S); +REC_FPUFUNC(MUL_S); +REC_FPUFUNC(DIV_S); +REC_FPUFUNC(SQRT_S); +REC_FPUFUNC(RSQRT_S); +REC_FPUFUNC(ABS_S); +REC_FPUFUNC(MOV_S); +REC_FPUFUNC(NEG_S); +REC_FPUFUNC(ADDA_S); +REC_FPUFUNC(SUBA_S); +REC_FPUFUNC(MULA_S); +REC_FPUFUNC(MADD_S); +REC_FPUFUNC(MSUB_S); +REC_FPUFUNC(MADDA_S); +REC_FPUFUNC(MSUBA_S); +REC_FPUFUNC(CVT_S); +REC_FPUFUNC(CVT_W); +REC_FPUFUNC(MIN_S); +REC_FPUFUNC(MAX_S); +REC_FPUBRANCH(BC1F); +REC_FPUBRANCH(BC1T); +REC_FPUBRANCH(BC1FL); +REC_FPUBRANCH(BC1TL); +REC_FPUFUNC(C_F); +REC_FPUFUNC(C_EQ); +REC_FPUFUNC(C_LE); +REC_FPUFUNC(C_LT); + +#else + +#ifdef EE_FPU_REGCACHING + +// define all FPU ops with XMM +#endif + +//////////////////////////////////////////////////// +void recC_EQ_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + j8Ptr[0] = JZ8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); +} + +void recC_EQ_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[_Fs_].f); + FCOMP32( (u32)&fpuRegs.fpr[_Ft_].f); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004000 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_EQ, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_F() +{ + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); +} + +//////////////////////////////////////////////////// +void recC_LT_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JB8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JBE8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LT_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00000100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[1] ); +} + +FPURECOMPILE_CONSTCODE(C_LT, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_LE_xmm(int info ) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JBE8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JB8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LE_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_LE, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +static void (*recComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_ADDSS_XMM_to_XMM, SSE_MULSS_XMM_to_XMM, SSE_MAXSS_XMM_to_XMM, SSE_MINSS_XMM_to_XMM }; + +static void (*recComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_ADDSS_M32_to_XMM, SSE_MULSS_M32_to_XMM, SSE_MAXSS_M32_to_XMM, SSE_MINSS_M32_to_XMM }; + +void recCommutativeOp(int info, int regd, int op) { + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd == EEREC_S) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + } + break; + case PROCESS_EE_T: + if (regd == EEREC_T) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_T); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + } + break; + default: + if (regd == EEREC_S) { + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + else if (regd == EEREC_T) { + recComOpXMM_to_XMM[op](regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } +} + +static void (*recNonComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_SUBSS_XMM_to_XMM, SSE_DIVSS_XMM_to_XMM }; + +static void (*recNonComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_SUBSS_M32_to_XMM, SSE_DIVSS_M32_to_XMM }; + +int recNonCommutativeOp(int info, int regd, int op) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd != EEREC_S) SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + break; + case PROCESS_EE_T: + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](t0reg, EEREC_T); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_M32_to_XMM(regd, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + default: + if (regd == EEREC_S) { + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } else + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + recNonComOpXMM_to_XMM[op](t0reg, regd); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } + + return regd; +} + +void recADD_S_xmm(int info) { + recCommutativeOp(info, EEREC_D, 0); +} + +void recADD_S_(int info) { + SetFPUstate(); + + SaveCW(1); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(ADD_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recSUB_S_xmm(int info) +{ + recNonCommutativeOp(info, EEREC_D, 0); +} + +void recSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SUB_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recMUL_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 1); +} + +void recMUL_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MUL_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recDIV_S_xmm(int info) +{ + int regd = recNonCommutativeOp(info, EEREC_D, 1); + SSE_MAXSS_M32_to_XMM(regd, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(regd, (u32)&g_maxvals[0]); + +// _freeXMMreg(EEREC_D); +// MOV32MtoR(EAX, (int)&fpuRegs.fpr[_Fd_]); +// AND32ItoR(EAX, 0x7f800000); +// CMP32ItoR(EAX, 0x7f800000); +// j8Ptr[0] = JNE8(0); +// MOV32ItoM((int)&fpuRegs.fpr[_Fd_], 0); +// x86SetJ8(j8Ptr[0]); +} + +void recDIV_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(DIV_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +__declspec(align(16)) static u32 s_neg[4] = { 0x80000000, 0, 0, 0 }; +__declspec(align(16)) static u32 s_pos[4] = { 0x7fffffff, 0, 0, 0 }; + +void recSQRT_S_xmm(int info) +{ + if( info & PROCESS_EE_T ) { + if( CHECK_FORCEABS ) { + if( EEREC_D == EEREC_T ) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&s_pos[0]); + SSE_ANDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( CHECK_FORCEABS ) { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + } + } +} + +void recSQRT_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SQRT_S, XMMINFO_WRITED|XMMINFO_READT); + +void recABS_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + else { + if( _Fs_ == _Fd_ ) { + AND32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x7fffffff); + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode &= ~MODE_WRITE; + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + } +} + +void recABS_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f ); + AND32ItoR( EAX, 0x7fffffff ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(ABS_S, XMMINFO_WRITED|XMMINFO_READS); + +void recMOV_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } +} + +void recMOV_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +} + +FPURECOMPILE_CONSTCODE(MOV_S, XMMINFO_WRITED|XMMINFO_READS); + +void recNEG_S_xmm(int info) { + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&s_neg[0]); +} + +void recNEG_S_(int info) +{ + MOV32MtoR( EAX,(u32)&fpuRegs.fpr[ _Fs_ ].f ); + XOR32ItoR( EAX, 0x80000000 ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(NEG_S, XMMINFO_WRITED|XMMINFO_READS); + +void recRSQRT_S_xmm(int info) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_RSQRTSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + + break; + case PROCESS_EE_T: + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + break; + default: + if( EEREC_D == EEREC_S ) { + int t0reg; + if( g_pCurInstInfo->regs[_Ft_]&EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + } + + SSE_RSQRTSS_XMM_to_XMM(t0reg, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + break; + } + + SSE_MAXSS_M32_to_XMM(EEREC_D, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_D, (u32)&g_maxvals[0]); +} + +void recRSQRT_S_(int info) +{ + static u32 tmp; + + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&tmp ); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&tmp ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); + +// FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); +// FSQRT( ); +// FSTP32( (u32)&tmp ); +// +// MOV32MtoR( EAX, (u32)&tmp ); +// OR32RtoR( EAX, EAX ); +// j8Ptr[ 0 ] = JE8( 0 ); +// FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); +// FDIV32( (u32)&tmp ); +// FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +// x86SetJ8( j8Ptr[ 0 ] ); +} + +FPURECOMPILE_CONSTCODE(RSQRT_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recADDA_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_ACC, 0); +} + +void recADDA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(ADDA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recSUBA_S_xmm(int info) { + recNonCommutativeOp(info, EEREC_ACC, 0); +} + +void recSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(SUBA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMULA_S_xmm(int info) { + recCommutativeOp(info, EEREC_ACC, 1); +} + +void recMULA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MULA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + SSE_MULSS_M32_to_XMM(regd, mreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + default: + if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + } +} + +void recMADD_S_xmm(int info) +{ + recMADDtemp(info, EEREC_D); +} + +void recMADD_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MADD_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDA_S_xmm(int info) +{ + recMADDtemp(info, EEREC_ACC); +} + +void recMADDA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MADDA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + if( !(info&PROCESS_EE_ACC)) { + int regacc = _allocFPACCtoXMMreg(-1, MODE_WRITE|MODE_READ); + info |= PROCESS_EE_SET_ACC(regacc)|PROCESS_EE_ACC; + } + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_M32_to_XMM(regd, mreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + + break; + default: + if (regd == EEREC_S) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if (regd == EEREC_T) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + break; + } +} + +void recMSUB_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_D); +} + +void recMSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MSUB_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBA_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_ACC); +} + +void recMSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MSUBA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recCVT_S_xmm(int info) +{ + if( !(info&PROCESS_EE_S) || (EEREC_D != EEREC_S && !(xmmregs[EEREC_S].mode&MODE_WRITE)) ) { + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + _deleteGPRtoXMMreg(_Fs_, 1); + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + } +} + +void recCVT_S_(int info) +{ + SetFPUstate(); + FILD32( (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(CVT_S, XMMINFO_WRITED|XMMINFO_READS); + +//////////////////////////////////////////////////// +void recCVT_W() +{ + int t0reg; + int regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + + if( regs >= 0 ) { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CVTTSS2SI_XMM_to_R32(EAX, regs); + } + else SSE_CVTTSS2SI_M32_to_R32(EAX, (u32)&fpuRegs.fpr[ _Fs_ ]); + + _deleteFPtoXMMreg(_Fd_, 2); + + CMP32ItoR(EAX, 0x80000000); + j8Ptr[0] = JNE8(0); + + // need to detect if reg is positive + if( regs >= 0 ) { + SSE_UCOMISS_XMM_to_XMM(regs, t0reg); + j8Ptr[2] = JB8(0); + } + else { + TEST32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x80000000); + j8Ptr[2] = JNZ8(0); + } + + MOV32ItoM((u32)&fpuRegs.fpr[_Fd_], 0x7fffffff); + j8Ptr[1] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[2] ); + MOV32RtoM((u32)&fpuRegs.fpr[_Fd_], EAX); + + x86SetJ8( j8Ptr[1] ); + +// MOV32MtoR(EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f); +// MOV32RtoR(ECX, EAX); +// AND32ItoR(ECX, 0x7F800000); +// CMP32ItoR(ECX, 0x4e800000); +// j8Ptr[0] = JA8(0); +// +// // convert +// SSE_CVTTSS2SI_M32_to_R32(EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f); +// MOV32RtoM((u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +// +// j8Ptr[1] = JMP8(0); +// +// x86SetJ8( j8Ptr[0] ); +// +// // check negative, eax = (eax&0x80000000)?0x80000000:0x7fffffff +// AND32ItoR(EAX, 0x80000000); +// SBB32RtoR(EAX, EAX); +// NEG32R(EAX); +// ADD32ItoR(EAX, 0x7fffffff); +// MOV32RtoM((u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX); +// +// x86SetJ8( j8Ptr[1] ); +} + +void recMAX_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 2); +} + +void recMAX_S_(int info) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MAX_S ); +} + +FPURECOMPILE_CONSTCODE(MAX_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recMIN_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 3); +} + +void recMIN_S_(int info) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MIN_S ); +} + +FPURECOMPILE_CONSTCODE(MIN_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recBC1F( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBC1T( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + //j32Ptr[1] = JMP32(0); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + //x86SetJ32(j32Ptr[1]); +} + +//////////////////////////////////////////////////// +void recBC1FL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBC1TL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif diff --git a/branches/pcsx2_0.9.1/x86/iFPU.h b/branches/pcsx2_0.9.1/x86/iFPU.h new file mode 100644 index 0000000..0d94bff --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iFPU.h @@ -0,0 +1,60 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IFPU_H__ +#define __IFPU_H__ + +void recMFC1( void ); +void recCFC1( void ); +void recMTC1( void ); +void recCTC1( void ); +void recCOP1_BC1( void ); +void recCOP1_S( void ); +void recCOP1_W( void ); +void recC_EQ( void ); +void recC_F( void ); +void recC_LT( void ); +void recC_LE( void ); +void recADD_S( void ); +void recSUB_S( void ); +void recMUL_S( void ); +void recDIV_S( void ); +void recSQRT_S( void ); +void recABS_S( void ); +void recMOV_S( void ); +void recNEG_S( void ); +void recRSQRT_S( void ); +void recADDA_S( void ); +void recSUBA_S( void ); +void recMULA_S( void ); +void recMADD_S( void ); +void recMSUB_S( void ); +void recMADDA_S( void ); +void recMSUBA_S( void ); +void recCVT_S( void ); +void recCVT_W( void ); +void recMAX_S( void ); +void recMIN_S( void ); +void recBC1F( void ); +void recBC1T( void ); +void recBC1FL( void ); +void recBC1TL( void ); + +#endif + + diff --git a/branches/pcsx2_0.9.1/x86/iMMI.c b/branches/pcsx2_0.9.1/x86/iMMI.c new file mode 100644 index 0000000..7db5ed4 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iMMI.c @@ -0,0 +1,3337 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* cached MMI opcodes * +* * +*********************************************************/ + +// NOTE: This code is disabled when xmm reg caching is ENABLED (instead use iMMI.c) +// This also means that every change that goes into here has to be repeated in iMMI.c and MMI.c (zerofrog) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" + +#ifndef MMI_RECOMPILE + +REC_FUNC( PLZCW ); + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0 ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1 ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2 ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3 ); + +#endif + +REC_FUNC( PMFHL ); +REC_FUNC( PMTHL ); + +REC_FUNC( PSRLW ); +REC_FUNC( PSRLH ); + +REC_FUNC( PSRAH ); +REC_FUNC( PSRAW ); + +REC_FUNC( PSLLH ); +REC_FUNC( PSLLW ); + +#else + +void recPLZCW() +{ + int regd = -1; + int regs = 0; + + if ( ! _Rd_ ) return; + + if( GPR_IS_CONST1(_Rs_) ) { + _eeOnWriteReg(_Rd_, 0); + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + + for(regs = 0; regs < 2; ++regs) { + u32 val = g_cpuConstRegs[_Rs_].UL[regs]; + + if( val != 0 ) { + u32 setbit = val&0x80000000; + g_cpuConstRegs[_Rd_].UL[regs] = 0; + val <<= 1; + + while((val & 0x80000000) == setbit) { + g_cpuConstRegs[_Rd_].UL[regs]++; + val <<= 1; + } + } + else { + g_cpuConstRegs[_Rd_].UL[regs] = 31; + } + } + return; + } + + _eeOnWriteReg(_Rd_, 0); + + if( (regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE2_MOVD_XMM_to_R(EAX, regs); + regs |= MEM_XMMTAG; + } + else if( (regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVD32MMXtoR(EAX, regs); + SetMMXstate(); + regs |= MEM_MMXTAG; + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + regs = 0; + } + + if( EEINST_ISLIVE1(_Rd_) ) + _deleteEEreg(_Rd_, 0); + else { + if( (regd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) < 0 ) { + _deleteEEreg(_Rd_, 0); + } + } + + // first word + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 31); + } + else { + SetMMXstate(); + PCMPEQDRtoR(regd, regd); + PSRLQItoR(regd, 59); + } + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + else { + SetMMXstate(); + MOVD32RtoMMX(regd, ECX); + } + + x86SetJ8(j8Ptr[1]); + + // second word + if( EEINST_ISLIVE1(_Rd_) ) { + if( regs >= 0 && (regs & MEM_XMMTAG) ) { + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + SSE2_MOVD_XMM_to_R(EAX, regs&0xf); + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + } + else if( regs >= 0 && (regs & MEM_MMXTAG) ) { + PSHUFWRtoR(regs, regs, 0x4e); + MOVD32MMXtoR(EAX, regs&0xf); + PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e); + SetMMXstate(); + } + else MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 31); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX); + x86SetJ8(j8Ptr[1]); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + + GPR_DEL_CONST(_Rd_); +} + +__declspec(align(16)) static u32 s_CmpMasks[] = { + 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPMFHL() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) + + int t0reg; + + switch (_Sa_) { + case 0x00: // LW + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + break; + + case 0x01: // UW + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0xdd); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0xdd); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x02: // SLW + // fall to interp + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + iFlushCall(FLUSH_CACHED_REGS); // since calling CALLFunc + CALLFunc( (u32)PMFHL ); + break; + + case 0x03: // LH + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x04: // SH + if( EEREC_D == EEREC_HI ) { + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x72); + } + else { + if( EEREC_D != EEREC_LO ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_HI); + + // shuffle so a1a0b1b0->a1b1a0b0 + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); + } + break; + default: + SysPrintf("PMFHL??\n"); + assert(0); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMFHL, _Rd_ ); +} + +void recPMTHL() +{ + SysPrintf("PMTHL email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PMTHL, 0 ); +} + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +#define MMX_ALLOC_TEMP1(code) { \ + int t0reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ +} \ + +#define MMX_ALLOC_TEMP2(code) { \ + int t0reg, t1reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ +} \ + +#define MMX_ALLOC_TEMP3(code) { \ + int t0reg, t1reg, t2reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ +} \ + +#define MMX_ALLOC_TEMP4(code) { \ + int t0reg, t1reg, t2reg, t3reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t3reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ + _freeMMXreg(t3reg); \ +} \ + +//////////////////////////////////////////////////// +void recPSRLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLWItoR( t0reg, _Sa_&0xf ); + PSRLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRLW( void ) +{ + if( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLDItoR( t0reg, _Sa_ ); + PSRLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRAWItoR( t0reg, _Sa_&0xf ); + PSRAWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRADItoR( t0reg, _Sa_ ); + PSRADItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLWItoR( t0reg, _Sa_&0xf ); + PSLLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLDItoR( t0reg, _Sa_ ); + PSLLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +/* +void recMADD( void ) +{ +} + +void recMADDU( void ) +{ +} + +void recPLZCW( void ) +{ +} +*/ + +#ifdef MMI0_RECOMPILE + +void recMMI0( void ) +{ + recMMI0t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI1_RECOMPILE + +void recMMI1( void ) +{ + recMMI1t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI2_RECOMPILE + +void recMMI2( void ) +{ + recMMI2t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI3_RECOMPILE + +void recMMI3( void ) +{ + recMMI3t[ _Sa_ ]( ); +} + +#endif + +#endif + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ +#ifndef MMI0_RECOMPILE + +REC_FUNC( PADDB, _Rd_); +REC_FUNC( PADDH, _Rd_); +REC_FUNC( PADDW, _Rd_); +REC_FUNC( PADDSB, _Rd_); +REC_FUNC( PADDSH, _Rd_); +REC_FUNC( PADDSW, _Rd_); +REC_FUNC( PSUBB, _Rd_); +REC_FUNC( PSUBH, _Rd_); +REC_FUNC( PSUBW, _Rd_); +REC_FUNC( PSUBSB, _Rd_); +REC_FUNC( PSUBSH, _Rd_); +REC_FUNC( PSUBSW, _Rd_); + +REC_FUNC( PMAXW, _Rd_); +REC_FUNC( PMAXH, _Rd_); + +REC_FUNC( PCGTW, _Rd_); +REC_FUNC( PCGTH, _Rd_); +REC_FUNC( PCGTB, _Rd_); + +REC_FUNC( PEXTLW, _Rd_); + +REC_FUNC( PPACW, _Rd_); +REC_FUNC( PEXTLH, _Rd_); +REC_FUNC( PPACH, _Rd_); +REC_FUNC( PEXTLB, _Rd_); +REC_FUNC( PPACB, _Rd_); +REC_FUNC( PEXT5, _Rd_); +REC_FUNC( PPAC5, _Rd_); + +#else + +//////////////////////////////////////////////////// +void recPMAXW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMAXW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPACW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(((_Rs_!=0||!cpucaps.hasStreamingSIMD2Extensions)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + + // swap mmx regs.. don't ask + xmmregs[t0reg] = xmmregs[EEREC_D]; + xmmregs[EEREC_D].inuse = 0; + } + } + } + else { + if( EEREC_D != EEREC_S ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x88 ); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x88 ); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); //Copy this one cos it could get overwritten + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], ECX); //This is where we bring it back + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +void recPPACH( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, t0reg, 0x88); + } + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +//////////////////////////////////////////////////// +void recPPACB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, EEREC_D); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(t0reg, 8); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(t0reg, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PPACB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXT5() +{ + SysPrintf("PEXT5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PEXT5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPAC5() +{ + SysPrintf("PPAC5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PPAC5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMAXH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + SSE_PMAXSW_MM_to_MM( t0reg, t1reg ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMAXSW_MM_to_MM( t2reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PCMPGTBRtoR( t0reg, t1reg ); + + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPGTBRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTWRtoR( t0reg, t1reg ); + PCMPGTWRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTW( void ) +{ + //TODO:optimize RS | RT== 0 + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTDRtoR( t0reg, t1reg ); + PCMPGTDRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSBRtoR( t0reg, t2reg); + PADDSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSWRtoR( t0reg, t2reg); + PADDSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + + //SysPrintf("PADDSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PADDSW ); +} + +//////////////////////////////////////////////////// +void recPSUBSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSBRtoR( t0reg, t2reg); + PSUBSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSWRtoR( t0reg, t2reg); + PSUBSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + //SysPrintf("PSUBSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PSUBSW ); +} + +//////////////////////////////////////////////////// +void recPADDB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDBRtoR( t0reg, t2reg ); + PADDBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDWRtoR( t0reg, t2reg ); + PADDWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDDRtoR( t0reg, t2reg ); + PADDDRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBBRtoR( t0reg, t2reg ); + PSUBBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBWRtoR( t0reg, t2reg ); + PSUBWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBDRtoR( t0reg, t2reg); + PSUBDRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPEXTLW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); +} + +void recPEXTLB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + //SysPrintf("PEXTLB\n"); + //Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); +} + +void recPEXTLH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +#endif + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ +#ifndef MMI1_RECOMPILE + +REC_FUNC( PABSW, _Rd_); +REC_FUNC( PABSH, _Rd_); + +REC_FUNC( PMINW, _Rd_); +REC_FUNC( PADSBH, _Rd_); +REC_FUNC( PMINH, _Rd_); +REC_FUNC( PCEQB, _Rd_); +REC_FUNC( PCEQH, _Rd_); +REC_FUNC( PCEQW, _Rd_); + +REC_FUNC( PADDUB, _Rd_); +REC_FUNC( PADDUH, _Rd_); +REC_FUNC( PADDUW, _Rd_); + +REC_FUNC( PSUBUB, _Rd_); +REC_FUNC( PSUBUH, _Rd_); +REC_FUNC( PSUBUW, _Rd_); + +REC_FUNC( PEXTUW, _Rd_); +REC_FUNC( PEXTUH, _Rd_); +REC_FUNC( PEXTUB, _Rd_); +REC_FUNC( QFSRV, _Rd_); + +#else + +//////////////////////////////////////////////////// +__declspec(align(16)) int s_MaskHighBitD[4] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; +__declspec(align(16)) int s_MaskHighBitW[4] = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; + +void recPABSW() +{ + if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPABSH() +{ +if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(t0reg, 15); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPMINW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_S); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMINW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPADSBH() +{ + SysPrintf("PADSBH email zero if abnormal behavior\n"); + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_D); + // reset lower bits to 0s + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 8); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + } + + // t0reg - adds, EEREC_D - subs + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE(PADSBH, _Rd_); +} + +//////////////////////////////////////////////////// +void recPADDUW() +{ +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rt_ == 0 ) { + if( _Rs_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( _Rs_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + int t2reg = _allocTempXMMreg(XMMT_INT, -1); + + if( _hasFreeXMMreg() ) { + int t3reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t3reg, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(t1reg, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t2reg, t0reg); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t3reg, t0reg); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t3reg); + _freeXMMreg(t3reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSE2_PSRLDQ_I8_to_XMM(t2reg, 8); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xE8); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t0reg); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + } + + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, t2reg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t2reg); + SSE2_PCMPGTD_XMM_to_XMM(t1reg, t0reg); + SSEX_POR_XMM_to_XMM(EEREC_D, t1reg); + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + } + +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUW() +{ + SysPrintf("PSUBUW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSUBUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXTUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXTUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recQFSRV() +{ + u8* pshift1, *pshift2, *poldptr, *pnewptr; + + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + + poldptr = x86Ptr; + x86Ptr += 6; + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 0); + pshift1 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + x86Ptr = pnewptr; + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + MOV32ItoR(ECX, 16); + SUB32RtoR(ECX, EAX); + + poldptr = x86Ptr; + x86Ptr += 12; + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 0); + pshift1 = x86Ptr-1; + + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 0); + pshift2 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + MOV8RtoM((u32)pshift2, ECX); + + x86Ptr = pnewptr; + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( QFSRV, _Rd_ ); +} + + +void recPEXTUB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but faster than int + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); +} + +//////////////////////////////////////////////////// +void recPEXTUW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 2 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 2 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 3 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 3 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); +} + +//////////////////////////////////////////////////// +void recPMINH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMINSW_MM_to_MM( t0reg, t2reg ); + SSE_PMINSW_MM_to_MM( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQBRtoR( t0reg, t2reg ); + PCMPEQBRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQWRtoR( t0reg, t2reg ); + PCMPEQWRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t0reg, t2reg ); + PCMPEQDRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rt_ ) { + if( EEREC_D == EEREC_S ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( EEREC_D != EEREC_S ) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSBRtoR( t0reg, t2reg ); + PADDUSBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSWRtoR( t0reg, t2reg ); + PADDUSWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +#endif +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ +#ifndef MMI2_RECOMPILE + +REC_FUNC( PMFHI, _Rd_); +REC_FUNC( PMFLO, _Rd_); +REC_FUNC( PCPYLD, _Rd_); +REC_FUNC( PAND, _Rd_); +REC_FUNC( PXOR, _Rd_); + +REC_FUNC( PMADDW, _Rd_); +REC_FUNC( PSLLVW, _Rd_); +REC_FUNC( PSRLVW, _Rd_); +REC_FUNC( PMSUBW, _Rd_); +REC_FUNC( PINTH, _Rd_); +REC_FUNC( PMULTW, _Rd_); +REC_FUNC( PDIVW, _Rd_); +REC_FUNC( PMADDH, _Rd_); +REC_FUNC( PHMADH, _Rd_); +REC_FUNC( PMSUBH, _Rd_); +REC_FUNC( PHMSBH, _Rd_); +REC_FUNC( PEXEH, _Rd_); +REC_FUNC( PREVH, _Rd_); +REC_FUNC( PMULTH, _Rd_); +REC_FUNC( PDIVBW, _Rd_); +REC_FUNC( PEXEW, _Rd_); +REC_FUNC( PROT3W, _Rd_ ); + +#else + +//////////////////////////////////////////////////// +void recPMADDW() +{ + SysPrintf("PMADDW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMADDW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSLLVW() +{ + SysPrintf("PSLLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSLLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSRLVW() +{ + SysPrintf("PSRLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSRLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBW() +{ + SysPrintf("PMSUBW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) +// int t0reg = _allocTempXMMreg(XMMT_INT, -1); +// +// if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); +// else { +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); +// SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// } +// +// // add from LO/HI +// SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSUBQ_XMM_to_XMM(EEREC_LO, EEREC_D); +// +// // get the signs +// SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +// SSE2_PSRAD_I8_to_XMM(t0reg, 31); +// +// // interleave +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); +// +// SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); +// SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); +// +// _freeXMMreg(t0reg); +//CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTW() +{ + SysPrintf("PMULTW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMULTW, _Rd_ ); +} +//////////////////////////////////////////////////// +void recPDIVW() +{ + SysPrintf("PDIVW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + REC_FUNC_INLINE( PDIVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPDIVBW() +{ + SysPrintf("PDIVBW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PDIVBW, _Rd_ ); //-- +} + +//////////////////////////////////////////////////// +void recPHMADH() +{ + SysPrintf("PHMADH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _Rd_ ? EEREC_D : _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + if( !_Rd_ ) _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMADH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBH() +{ + SysPrintf("PMSUBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPHMSBH() +{ + SysPrintf("PHMSBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMSBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXEH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xc6); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPREVH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x17); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x17); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PREVH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPINTH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_MOVHLPS_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[2], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[4], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[0], EDX); + + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[5]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rs_].US[7]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[5], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[7], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[6], EDX); +} + +void recPEXEW( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPROT3W( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc9); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPMULTH( void ) +{ +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_HI, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_LO, EEREC_HI); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(t0reg, EEREC_HI); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, t0reg, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_HI); + } + + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_LO, t0reg); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(!_Rt_ || !_Rs_) { + MOV32ItoM( (u32)&cpuRegs.LO.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[3], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[3], 0); + + if( _Rd_ ) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], 0); + } + return; + } + + //Done - Refraction + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +void recPMFHI( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_HI); +CPU_SSE_XMMCACHE_END + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.HI.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMFLO( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.LO.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPAND( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PANDMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PANDMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPXOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PXORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PXORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYLD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READS)|XMMINFO_READT) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + else if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + else { + if( EEREC_D == EEREC_T ) SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x44); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t1reg ); + SetMMXstate(); + ) +} + + +void recPMADDH( void ) +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PADDD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(_Rt_ && _Rs_){ + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + } + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +#endif +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ +#ifndef MMI3_RECOMPILE + +REC_FUNC( PMADDUW, _Rd_); +REC_FUNC( PSRAVW, _Rd_); +REC_FUNC( PMTHI, _Rd_); +REC_FUNC( PMTLO, _Rd_); +REC_FUNC( PINTEH, _Rd_); +REC_FUNC( PMULTUW, _Rd_); +REC_FUNC( PDIVUW, _Rd_); +REC_FUNC( PCPYUD, _Rd_); +REC_FUNC( POR, _Rd_); +REC_FUNC( PNOR, _Rd_); +REC_FUNC( PCPYH, _Rd_); +REC_FUNC( PEXCW, _Rd_); +REC_FUNC( PEXCH, _Rd_); + +#else + +//////////////////////////////////////////////////// +REC_FUNC( PSRAVW, _Rd_ ); + +//////////////////////////////////////////////////// +__declspec(align(16)) u32 s_tempPINTEH[4] = {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPINTEH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + int t0reg = -1; + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PAND_M128_to_XMM(EEREC_D, (u32)s_tempPINTEH); + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_S, 0xa0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xa0); + } + else if( EEREC_D == EEREC_T ) { + assert( EEREC_D != EEREC_S ); + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_S) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSRLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + } + + if( t0reg >= 0 ) _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PINTEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTUW() +{ + SysPrintf("PMULTUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PMULTUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMADDUW() +{ + SysPrintf("PMADDUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // add from LO/HI + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + SSE2_PADDQ_XMM_to_XMM(EEREC_D, EEREC_LO); + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +//do EEINST_SETSIGNEXT +REC_FUNC( PDIVUW, _Rd_ ); + +//////////////////////////////////////////////////// +void recPEXCW() +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXCH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPNOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + } + else { + if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + if( _Rt_ != 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + if( EEREC_D == EEREC_S ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + if( EEREC_S != EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg ); + SSEX_PXOR_XMM_to_XMM( EEREC_D, t0reg ); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP3( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t2reg, t2reg ); + PXORRtoR( t0reg, t2reg ); + PXORRtoR( t1reg, t2reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTHI( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITEHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_HI, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTLO( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITELO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_LO, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYUD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READT)|XMMINFO_WRITED) + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + } + else { + if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + //TODO + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + } + else { + if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0xee); + } + else if( EEREC_D == EEREC_T ) { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( _Rs_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + else if( _Rt_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + if( EEREC_S != EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + if ( _Rt_ != 0 ) + { + PORMtoR ( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR ( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + } + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //PUSH32R( EBX ); + MOVZX32M16toR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOV32RtoR( ECX, EAX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EAX, ECX ); + MOVZX32M16toR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOV32RtoR( ECX, EDX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EDX, ECX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], EDX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EDX ); + //POP32R( EBX ); +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iMMI.h b/branches/pcsx2_0.9.1/x86/iMMI.h new file mode 100644 index 0000000..c69b6bc --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iMMI.h @@ -0,0 +1,133 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ +#ifndef __IMMI_H__ +#define __IMMI_H__ + +void recMADD(); +void recMADDU(); +void recPLZCW(); +void recMMI0(); +void recMMI1(); +void recMMI2(); +void recMMI3(); +void recMADD1(); +void recMADDU1(); +void recPMFHL(); +void recPMTHL(); +void recPMAXW(); +void recPMINW(); +void recPPACW(); +void recPEXTLH(); +void recPPACH(); +void recPEXTLB(); +void recPPACB(); +void recPEXT5(); +void recPPAC5(); +void recPABSW(); +void recPADSBH(); +void recPABSH(); +void recPADDUW(); +void recPSUBUW(); +void recPSUBUH(); +void recPEXTUH(); +void recPSUBUB(); +void recPEXTUB(); +void recQFSRV(); +void recPMADDW(); +void recPSLLVW(); +void recPSRLVW(); +void recPMSUBW(); +void recPINTH(); +void recPMULTW(); +void recPDIVW(); +void recPMADDH(); +void recPHMADH(); +void recPMSUBH(); +void recPHMSBH(); +void recPEXEH(); +void recPREVH(); +void recPMULTH(); +void recPDIVBW(); +void recPEXEW(); +void recPROT3W(); +void recPMADDUW(); +void recPSRAVW(); +void recPINTEH(); +void recPMULTUW(); +void recPDIVUW(); +void recPEXCH(); +void recPEXCW(); + +void recPSRLH(); +void recPSRLW(); +void recPSRAH(); +void recPSRAW(); +void recPSLLH(); +void recPSLLW(); +void recMTHI1(); +void recMTLO1(); +void recMFHI1(); +void recMFLO1(); +void recMULT1(); +void recMULTU1(); +void recDIV1(); +void recDIVU1(); +void recPMAXH(); +void recPCGTB(); +void recPCGTH(); +void recPCGTW(); +void recPADDSB(); +void recPADDSH(); +void recPADDSW(); +void recPSUBSB(); +void recPSUBSH(); +void recPSUBSW(); +void recPADDB(); +void recPADDH(); +void recPADDW(); +void recPSUBB(); +void recPSUBH(); +void recPSUBW(); +void recPEXTLW(); +void recPEXTUW(); +void recPMINH(); +void recPCEQB(); +void recPCEQH(); +void recPCEQW(); +void recPADDUB(); +void recPADDUH(); +void recPMFHI(); +void recPMFLO(); +void recPAND(); +void recPXOR(); +void recPCPYLD(); +void recPNOR(); +void recPMTHI(); +void recPMTLO(); +void recPCPYUD(); +void recPOR(); +void recPCPYH(); + +#endif + + diff --git a/branches/pcsx2_0.9.1/x86/iR3000A.cpp b/branches/pcsx2_0.9.1/x86/iR3000A.cpp new file mode 100644 index 0000000..6adb37e --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iR3000A.cpp @@ -0,0 +1,1371 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking Jan06 +// and added reg caching, const propagation, block analysis Jun06 +// zerofrog(@gmail.com) + +#if 1 + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "zlib.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" +#include "PsxCounters.h" + +extern u32 psxNextCounter, psxNextsCounter; +u32 g_psxMaxRecMem = 0; +extern char *disRNameGPR[]; +extern char* disR3000Fasm(u32 code, u32 pc); +} + +#define PSX_NUMBLOCKS (1<<12) +#define MAPBASE 0x48000000 +#define RECMEM_SIZE (8*1024*1024) + +// R3000A statics +uptr *psxRecLUT; +int psxreclog = 0; + +static u32 s_BranchCount = 0; +static char *recMem; // the recompiled blocks will be here +static BASEBLOCK *recRAM; // and the ptr to the blocks here +static BASEBLOCK *recROM; // and here +static BASEBLOCK *recROM1; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr; +u32 psxpc; // recompiler psxpc +int psxbranch; // set for branch +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_psxNextBranchCycle = 0; + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what psxpc the current block ends + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +static u32 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_psxBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch); +void psxRecompileNextInstruction(int delayslot); +static void recRecompile(u32 startpc); + +extern void (*rpsxBSC[64])(); +extern void (*rpsxBSC_co[64])(); +void rpsxpropBSC(EEINST* prev, EEINST* pinst); + +#ifdef _DEBUG +extern "C" u32 psxdump = 0; +#else +#define psxdump 0 +#endif + +#define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) + +#define PSXREC_CLEARM(mem) { \ + if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PSX_GETBLOCK(mem); \ + if( *(u32*)p ) psxRecClearMem(p); \ + } \ +} \ + +BASEBLOCKEX* PSX_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+PSX_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 1); +} + +//////////////////////////////////////////////////// +static void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + u8 used[34]; + int numused, count; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, psxpc, psxRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); +sprintf( filename, "dumps\\psxdump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/psxdump%.8X.txt", startpc); +#endif + + fflush( stdout ); + + f = fopen( filename, "w" ); + assert( f != NULL ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR3000Fasm( *(u32*)PSXM( i ), i ) ); + } + + // write the instruction info + fprintf(f, "\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _psxIsLoadStore(u32 tempcode) +{ + switch(tempcode>>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + return 1; + } + return 0; +} + +void _psxFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( psxpc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && PSX_IS_CONST1(i) ) _psxFlushConstReg(i); + else { + _deleteX86reg(X86TYPE_PSX, i, 1); + } + } +} + +int _psxFlushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_psxHasConstReg & (1< 0 ); + + // make sure right GPR was saved + assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1< 0) { + pblock = PSX_GETBLOCK(psxRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != psxRegs.pc ) { + recRecompile(psxRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + +#ifdef _DEBUG + + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R3000AFNPTR)pblock->pFnptr); + // use call instead of pfn() + __asm call pfn +#endif + } +} + +extern u32 g_psxNextBranchCycle; +u32 g_psxlastpc = 0; +static u32 g_temp; + +// jumped to when invalid psxpc address +__declspec(naked,noreturn) void psxDispatcher() +{ + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == psxRegs.pc + mov ecx, psxRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push psxRegs.pc // psxpc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new psxpc +// and eax, 0x0fffffff +// mov ecx, psxRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void psxDispatcherClear() +{ + // EDX contains the current psxpc + __asm mov psxRegs.pc, edx + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + if( s_pDispatchBlock->startpc == psxRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable psxpc address +__declspec(naked,noreturn) void psxDispatcherReg() +{ + __asm { + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov edx, psxRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, psxRecLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == psxRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +static void recClear(u32 Addr, u32 Size) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + PSXREC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void rpsxMemConstClear(u32 mem) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !psxRecLUT[mem>>16] ) + return; + + CMP32ItoM((u32)PSX_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PSX_GETBLOCK(mem)); + CALLFunc((u32)psxRecClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); +} + +void psxRecClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + psxRecClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)psxDispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PSX_GETBLOCK(p->startpc); + pexblock = PSX_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 1); + pexblock->size = 0; + pexblock->startpc = 0; +} + +void psxSetBranchReg(u32 reg) +{ + psxbranch = 1; + + if( reg != 0xffffffff ) { + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, reg); + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + } + + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void psxSetBranchImm( u32 imm ) +{ + u32* ptr; + psxbranch = 1; + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&psxRegs.pc, imm ); + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(imm, imm <= psxpc); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)psxDispatcher - ( (u32)x86Ptr + 5 )); +} + +#define USE_FAST_BRANCHES 0 + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch) +{ + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&psxRegs.cycle); + ADD32ItoR(ECX, s_psxBlockCycles*17/16); // greater mult factor causes nfsmw to crash + MOV32RtoM((int)&psxRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + return; + } + + SUB32MtoR(ECX, (int)&g_psxNextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + CALLFunc((int)psxBranchTest); + + CMP32ItoM((int)&EEsCycle, 0); + j8Ptr[2] = JG8(0); + RET2(); + x86SetJ8( j8Ptr[2] ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&psxRegs.pc, newpc); + JNE32((u32)psxDispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + +static int *s_pCode; + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("iop code changed! %x\n", pctemp); +} + +void rpsxSYSCALL() +{ + MOV32ItoM( (u32)&psxRegs.code, psxRegs.code ); + MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4); + _psxFlushCall(FLUSH_NODESTROY); + + PUSH32I(psxbranch == 1 ? 1 : 0); + PUSH32I(0x20); + CALLFunc ((int)psxException); + ADD32ItoR(ESP, 8); + + CMP32ItoM((int)&psxRegs.pc, psxpc-4); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&psxRegs.cycle, s_psxBlockCycles); + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + + //if (!psxbranch) psxbranch = 2; +} + +u32 psxRecompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PSX_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( psxpc == pblock->startpc ) + return 0; + } + + return 1; +} + +void psxRecompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + + BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && psxpc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == psxpc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + psxRecClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", psxpc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSXM( psxpc ); + assert(s_pCode); + + psxRegs.code = *(int *)s_pCode; + s_psxBlockCycles++; + psxpc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, psxRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, psxpc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +//#endif + + g_pCurInstInfo++; + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + assert(0); +// recBSC_co[cpuRegs.code>>26](); +// psxpc += 4; +// s_psxBlockCycles++; +// g_pCurInstInfo++; + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + rpsxBSC[ psxRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //_psxFlushUnusedConstReg(); + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + _clearNeededX86regs(); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + + execute(); +} + +extern "C" +void iDumpPsxRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + + __Log("%spsxreg: %x %x\n", pstr, startpc, psxRegs.interrupt); + for(i = 0; i < 34; i+=2) __Log("%spsx%d: %x %x\n", pstr, i, psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); + __Log("%scycle: %x %x %x %x; counters %x %x\n", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, IOPoCycle, + (u32)psxNextsCounter, (u32)psxNextCounter); + + for(i = 0; i < 6; ++i) __Log("%scounter%d: %x %x %x\n", pstr, i, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT); + for(i = 0; i < 32; ++i) { + __Log("int%d: %x %x\n", i, psxRegs.sCycle[i], psxRegs.eCycle[i]); + } +} + +void iDumpPsxRegisters(u32 startpc); + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0; + const int skip = 0; + + if( (psxdump&2) ) {//&& lastrec != g_psxlastpc ) { + curcount++; + + if( curcount > skip ) { + iDumpPsxRegisters(g_psxlastpc, 1); + curcount = 0; + } + + lastrec = g_psxlastpc; + } +} + +u32 s_recblocks[] = {0}; + +static void recRecompile(u32 startpc) +{ + u32 i; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + +#ifdef _DEBUG + //psxdump |= 4; + if( psxdump & 4 ) + iDumpPsxRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + s_pCurBlock = PSX_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + psxRecClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < PSX_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%PSX_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%PSX_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%PSX_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + + psxbranch = 0; + + s_pCurBlock->startpc = startpc; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_psxBlockCycles = 0; + + // reset recomp state variables + psxpc = startpc; + s_saveConstGPRreg = 0; + g_psxHasConstReg = g_psxFlushedConstReg = 1; + + _initX86regs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_psxlastpc, psxpc); + CALLFunc((u32)printfn); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + + while(1) { + BASEBLOCK* pblock = PSX_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + psxRegs.code = *(int *)PSXM(i); + + switch(psxRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ == 0 || _Rt_ == 1 || _Rt_ == 16 || _Rt_ == 17 ) { + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + psxRegs.code = *(int *)PSXM(i-4); + pcur[-1] = pcur[0]; + rpsxpropBSC(pcur-1, pcur); + pcur--; + } + } + + // peephole optimizations // +// { +// g_pCurInstInfo = s_pInstCache; +// +// for(i = startpc; i < s_nEndBlock-4; i += 4) { +// g_pCurInstInfo++; +// if( psxRecompileCodeSafe(i) ) { +// u32 curcode = *(u32*)PSXM(i); +// u32 nextcode = *(u32*)PSXM(i+4); +// if( _psxIsLoadStore(curcode) && _psxIsLoadStore(nextcode) && (curcode>>26) == (nextcode>>26) && rpsxBSC_co[curcode>>26] != NULL ) { +// +// // rs has to be the same, and cannot be just written +// if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_psxLoadWritesRs(curcode) ) { +// +// // good enough +// g_pCurInstInfo[0].info |= EEINSTINFO_COREC; +// g_pCurInstInfo[0].numpeeps = 1; +// g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; +// g_pCurInstInfo++; +// i += 4; +// continue; +// } +// } +// } +// } +// } + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (psxdump & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + g_pCurInstInfo = s_pInstCache; + while (!psxbranch && psxpc < s_nEndBlock) { + psxRecompileNextInstruction(0); + } + + assert( (psxpc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (psxpc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 1); + + if( !(psxpc&0x10000000) ) + g_psxMaxRecMem = max( (psxpc&~0xa0000000), g_psxMaxRecMem ); + + if( psxbranch == 2 ) { + _psxFlushCall(FLUSH_EVERYTHING); + + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( psxbranch != 3 ); + if( psxbranch ) assert( !willbranch3 ); + else ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + + if( willbranch3 ) { + BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock); + assert( psxpc == s_nEndBlock ); + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + } + else if( !psxbranch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&psxRegs.pc, psxpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + //JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+RECMEM_SIZE ); + + recPtr = x86Ptr; + + assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); + + if( !psxbranch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PSX_GETBLOCK(psxpc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != psxpc ) + recRecompile(psxpc); + + // could have reset + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iR3000A.h b/branches/pcsx2_0.9.1/x86/iR3000A.h new file mode 100644 index 0000000..4361628 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iR3000A.h @@ -0,0 +1,99 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _R3000A_SUPERREC_ +#define _R3000A_SUPERREC_ + +extern void __Log(char *fmt, ...); + +// to be consistent with EE +#define PSX_HI MMX_HI +#define PSX_LO MMX_LO + +extern uptr *psxRecLUT; + +u8 _psxLoadWritesRs(u32 tempcode); +u8 _psxIsLoadStore(u32 tempcode); + +void _psxFlushAllUnused(); +int _psxFlushUnusedConstReg(); +void _psxFlushCachedRegs(); +void _psxFlushConstReg(int reg); +void _psxFlushConstRegs(); + +void _psxDeleteReg(int reg, int flush); +void _psxFlushCall(int flushtype); + +void _psxOnWriteReg(int reg); +void PSX_CHECK_SAVE_REG(int reg); + +extern u32 psxpc; // recompiler pc +extern int psxbranch; // set for branch + +void psxSaveBranchState(); +void psxLoadBranchState(); + +void psxSetBranchReg(u32 reg); +void psxSetBranchImm( u32 imm ); +void psxRecompileNextInstruction(int delayslot); + +typedef void (*R3000AFNPTR)(); +typedef void (*R3000AFNPTR_INFO)(int info); + +void psxRecClearMem(BASEBLOCK* p); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define PSXRECOMPILE_CONSTCODE0(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst0(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_); \ +} \ + +// rt = rs op imm16 +#define PSXRECOMPILE_CONSTCODE1(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst1(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// rd = rt op sa +#define PSXRECOMPILE_CONSTCODE2(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst2(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// [lo,hi] = rt op rs +#define PSXRECOMPILE_CONSTCODE3(fn, LOHI) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst3(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_, LOHI); \ +} \ + +// rd = rs op rt +void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode); +// rt = rs op imm16 +void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// rd = rt op sa +void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// [lo,hi] = rt op rs +void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode, int LOHI); + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iR3000Atables.cpp b/branches/pcsx2_0.9.1/x86/iR3000Atables.cpp new file mode 100644 index 0000000..ed898ec --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iR3000Atables.cpp @@ -0,0 +1,2054 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if 1 + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" + +extern void psxLWL(); +extern void psxLWR(); +extern void psxSWL(); +extern void psxSWR(); + +extern int g_psxWriteOk; +extern u32 g_psxMaxRecMem; +} + +// R3000A instruction implementation +#define REC_FUNC(f) \ +void psx##f(); \ +static void rpsx##f() { \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + _psxFlushCall(FLUSH_EVERYTHING); \ + /*MOV32ItoM((u32)&psxRegs.pc, (u32)pc);*/ \ + CALLFunc((u32)psx##f); \ + PSX_DEL_CONST(_Rt_); \ +/* branch = 2; */\ +} + +//// +void rpsxADDIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] + _Imm_; +} + +// adds a constant to sreg and puts into dreg +void rpsxADDconst(int dreg, int sreg, u32 off, int info) +{ + if (sreg) { + if (sreg == dreg) { + ADD32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + if (off) ADD32ItoR(EAX, off); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } +} + +void rpsxADDIU_(int info) +{ + // Rt = Rs + Im + if (!_Rt_) return; + rpsxADDconst(_Rt_, _Rs_, _Imm_, info); +} + +PSXRECOMPILE_CONSTCODE1(ADDIU); + +void rpsxADDI() { rpsxADDIU(); } + +//// SLTI +void rpsxSLTI_const() +{ + g_psxConstRegs[_Rt_] = *(int*)&g_psxConstRegs[_Rs_] < _Imm_; +} + +void rpsxSLTconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETL8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTI_(int info) { rpsxSLTconst(info, _Rt_, _Rs_, _Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTI); + +//// SLTIU +void rpsxSLTIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] < _ImmU_; +} + +void rpsxSLTUconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETB8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTIU_(int info) { rpsxSLTUconst(info, _Rt_, _Rs_, (s32)_Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTIU); + +//// ANDI +void rpsxANDI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] & _ImmU_; +} + +void rpsxANDconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + AND32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + AND32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], 0); + } +} + +void rpsxANDI_(int info) { rpsxANDconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ANDI); + +//// ORI +void rpsxORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] | _ImmU_; +} + +void rpsxORconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + OR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + OR32ItoR (EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxORI_(int info) { rpsxORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ORI); + +void rpsxXORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] ^ _ImmU_; +} + +void rpsxXORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm == 0xffffffff ) { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } + else if (imm) { + + if (sreg == dreg) { + XOR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + XOR32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxXORI_(int info) { rpsxXORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(XORI); + +void rpsxLUI() +{ + if(!_Rt_) return; + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + PSX_SET_CONST(_Rt_); + g_psxConstRegs[_Rt_] = psxRegs.code << 16; +} + +void rpsxADDU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] + g_psxConstRegs[_Rt_]; +} + +void rpsxADDU_consts(int info) { rpsxADDconst(_Rd_, _Rt_, g_psxConstRegs[_Rs_], info); } +void rpsxADDU_constt(int info) +{ + info |= PROCESS_EE_SET_S(EEREC_T); + rpsxADDconst(_Rd_, _Rs_, g_psxConstRegs[_Rt_], info); +} + +void rpsxADDU_(int info) +{ + if (_Rs_ && _Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Rs_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } else if (_Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else { + XOR32RtoR(EAX, EAX); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(ADDU); + +void rpsxADD() { rpsxADDU(); } + + +void rpsxSUBU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] - g_psxConstRegs[_Rt_]; +} + +void rpsxSUBU_consts(int info) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rs_]); + SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSUBU_constt(int info) { rpsxADDconst(_Rd_, _Rs_, -(int)g_psxConstRegs[_Rt_], info); } + +void rpsxSUBU_(int info) +{ + // Rd = Rs - Rt + if (!_Rd_) return; + + if( _Rd_ == _Rs_ ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SUB32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +PSXRECOMPILE_CONSTCODE0(SUBU); + +void rpsxSUB() { rpsxSUBU(); } + +void rpsxLogicalOp(int info, int op) +{ + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[vreg]); + LogicalOp32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX, op); + if( op == 3 ) + NOT32M((u32)&psxRegs.GPR.r[_Rd_]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + LogicalOp32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_], op); + if( op == 3 ) + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX); + } +} + +void rpsxAND_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] & g_psxConstRegs[_Rt_]; +} + +void rpsxAND_consts(int info) { rpsxANDconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxAND_constt(int info) { rpsxANDconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxAND_(int info) { rpsxLogicalOp(info, 0); } + +PSXRECOMPILE_CONSTCODE0(AND); + +void rpsxOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]; +} + +void rpsxOR_consts(int info) { rpsxORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxOR_constt(int info) { rpsxORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxOR_(int info) { rpsxLogicalOp(info, 1); } + +PSXRECOMPILE_CONSTCODE0(OR); + +//// XOR +void rpsxXOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] ^ g_psxConstRegs[_Rt_]; +} + +void rpsxXOR_consts(int info) { rpsxXORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxXOR_constt(int info) { rpsxXORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxXOR_(int info) { rpsxLogicalOp(info, 2); } + +PSXRECOMPILE_CONSTCODE0(XOR); + +//// NOR +void rpsxNOR_const() +{ + g_psxConstRegs[_Rd_] = ~(g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]); +} + +void rpsxNORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm ) { + if( dreg == sreg ) { + OR32ItoM((u32)&psxRegs.GPR.r[dreg], imm); + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + OR32ItoR(ECX, imm); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } + else { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxNOR_consts(int info) { rpsxNORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxNOR_constt(int info) { rpsxNORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxNOR_(int info) { rpsxLogicalOp(info, 3); } + +PSXRECOMPILE_CONSTCODE0(NOR); + +//// SLT +void rpsxSLT_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rs_] < *(int*)&g_psxConstRegs[_Rt_]; +} + +void rpsxSLT_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETG8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLT_constt(int info) { rpsxSLTconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLT_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLT); + +//// SLTU +void rpsxSLTU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] < g_psxConstRegs[_Rt_]; +} + +void rpsxSLTU_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETA8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLTU_constt(int info) { rpsxSLTUconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLTU_(int info) +{ + // Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLTU); + +//// MULT +void rpsxMULT_const() +{ + u64 res = (s64)((s64)*(int*)&g_psxConstRegs[_Rs_] * (s64)*(int*)&g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTsuperconst(int info, int sreg, int imm, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32ItoR(EAX, imm); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[sreg]); + else MUL32M ((uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULTsuper(int info, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + else MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULT_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 1); } +void rpsxMULT_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 1); } +void rpsxMULT_(int info) { rpsxMULTsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(MULT, 1); + +//// MULTU +void rpsxMULTU_const() +{ + u64 res = (u64)((u64)g_psxConstRegs[_Rs_] * (u64)g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTU_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 0); } +void rpsxMULTU_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 0); } +void rpsxMULTU_(int info) { rpsxMULTsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(MULTU, 1); + +//// DIV +void rpsxDIV_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = *(int*)&g_psxConstRegs[_Rs_] / *(int*)&g_psxConstRegs[_Rt_]; + hi = *(int*)&g_psxConstRegs[_Rs_] % *(int*)&g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVsuperconsts(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rs_]; + + if( imm ) { + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32ItoR(EAX, imm); + CDQ(); + + if( sign ) IDIV32R (ECX); + else DIV32R(ECX); + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); + } + else { + XOR32RtoR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxDIVsuperconstt(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rt_]; + + if( imm ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32ItoR(ECX, imm); + CDQ(); + + if( sign ) IDIV32R (ECX); + else DIV32R(ECX); + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + } +} + +void rpsxDIVsuper(int info, int sign) +{ + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); +} + +void rpsxDIV_consts(int info) { rpsxDIVsuperconsts(info, 1); } +void rpsxDIV_constt(int info) { rpsxDIVsuperconstt(info, 1); } +void rpsxDIV_(int info) { rpsxDIVsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(DIV, 1); + +//// DIVU +void rpsxDIVU_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = g_psxConstRegs[_Rs_] / g_psxConstRegs[_Rt_]; + hi = g_psxConstRegs[_Rs_] % g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVU_consts(int info) { rpsxDIVsuperconsts(info, 0); } +void rpsxDIVU_constt(int info) { rpsxDIVsuperconstt(info, 0); } +void rpsxDIVU_(int info) { rpsxDIVsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(DIVU, 1); + +//// LoadStores +#ifdef WIN32_VIRTUAL_MEM + +// VM load store functions (fastest) + +//#define REC_SLOWREAD +//#define REC_SLOWWRITE + +int _psxPrepareReg(int gprreg) +{ + return 0; +} + +static u32 s_nAddMemOffset = 0; + +#define SET_HWLOC() { \ + x86SetJ8(j8Ptr[0]); \ + SHR32ItoR(ECX, 3); \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ +} \ + +int rpsxSetMemLocation(int regs, int mmreg) +{ + s_nAddMemOffset = 0; + MOV32MtoR( ECX, (int)&psxRegs.GPR.r[ regs ] ); + + if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); + + SHL32ItoR(ECX, 3); + j8Ptr[0] = JS8(0); + SHR32ItoR(ECX, 3); + AND32ItoR(ECX, 0x1fffff); // 2Mb + return 1; +} + +void recLoad32(u32 bit, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _psxOnWriteReg(_Rt_); + mmreg = EAX; + + switch(bit) { + case 8: ineax = psxRecMemConstRead8(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); break; + case 16: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 2 == 0 ); + ineax = psxRecMemConstRead16(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); + break; + case 32: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 4 == 0 ); + ineax = psxRecMemConstRead32(mmreg, g_psxConstRegs[_Rs_]+_Imm_); + break; + } + + if( _Rt_ ) MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)psxRecMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)psxRecMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + CALLFunc( (int)psxRecMemRead32 ); + break; + } + + x86SetJ8(j8Ptr[1]); + } + + MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } +} + +void rpsxLB() { recLoad32(8, 1); } +void rpsxLBU() { recLoad32(8, 0); } +void rpsxLH() { recLoad32(16, 1); } +void rpsxLHU() { recLoad32(16, 0); } +void rpsxLW() { recLoad32(32, 0); } + +extern void rpsxMemConstClear(u32 mem); + +// check if mem is executable, and clear it +__declspec(naked) void rpsxWriteMemClear() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, psxRecLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call psxRecClearMem + add esp, 4 +ClearRet: + ret + } +} + +extern u32 s_psxBlockCycles; +void recStore(int bit) +{ +#ifdef REC_SLOWWRITE + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + u8* pjmpok; + u32 addr = g_psxConstRegs[_Rs_]+_Imm_; + int doclear = 0; + + if( !(addr & 0x10000000) ) { + // check g_psxWriteOk + CMP32ItoM((u32)&g_psxWriteOk, 0); + pjmpok = JE8(0); + } + + switch(bit) { + case 8: + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite8(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite8(addr, EAX); + } + + break; + + case 16: + assert( (addr)%2 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite16(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite16(addr, EAX); + } + + break; + + case 32: + assert( (addr)%4 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite32(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite32(addr, EAX); + } + + break; + } + + if( !(addr & 0x10000000) ) { + if( doclear ) rpsxMemConstClear((addr)&~3); + x86SetJ8(pjmpok); + } + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + CMP32ItoM((u32)&g_psxWriteOk, 0); + u8* pjmpok = JE8(0); + + if( PSX_IS_CONST1( _Rt_ ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 16: MOV16ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 32: MOV32ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + } + } + else { + switch(bit) { + case 8: + MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV8RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 16: + MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV16RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 32: + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + } + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&g_psxMaxRecMem); + + j8Ptr[1] = JAE8(0); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + CALLFunc((u32)rpsxWriteMemClear); + + if( dohw ) { + j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( PSX_IS_CONST1(_Rt_) ) { + switch(bit) { + case 8: MOV8ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 16: MOV16ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 32: MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); break; + } + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 16: MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 32: MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + } + } + + if( s_nAddMemOffset != 0 ) ADD32ItoR(ECX, s_nAddMemOffset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)psxRecMemWrite8 ); break; + case 16: CALLFunc( (int)psxRecMemWrite16 ); break; + case 32: CALLFunc( (int)psxRecMemWrite32 ); break; + } + + x86SetJ8(j8Ptr[2]); + } + + x86SetJ8(j8Ptr[1]); + x86SetJ8(pjmpok); + } +} + +void rpsxSB() { recStore(8); } +void rpsxSH() { recStore(16); } +void rpsxSW() { recStore(32); } + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +#else + +// TLB loadstore functions (slower +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +static void rpsxLB() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLBU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLH() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLHU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLW() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + + TEST32ItoR(EAX, 0x10000000); + j8Ptr[0] = JZ8(0); + + PUSH32R (EAX); + CALLFunc((int)psxMemRead32); + if (_Rt_) { + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + // read from psM directly + AND32ItoR(EAX, 0x0fffffff); + ADD32ItoR(EAX, (u32)psxM); + + MOV32RmtoR( EAX, EAX ); + MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], EAX); + + x86SetJ8(j8Ptr[1]); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxSB() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite8); + ADD32ItoR(ESP, 8); +} + +static void rpsxSH() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite16); + ADD32ItoR(ESP, 8); +} + +static void rpsxSW() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite32); + ADD32ItoR(ESP, 8); +} + +#endif // end load store + +//// SLL +void rpsxSLL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << _Sa_; +} + +// shifttype: 0 - sll, 1 - srl, 2 - sra +void rpsxShiftConst(int info, int rdreg, int rtreg, int imm, int shifttype) +{ + imm &= 0x1f; + if (imm) { + if( rdreg == rtreg ) { + switch(shifttype) { + case 0: SHL32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 1: SHR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 2: SAR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + } + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[rtreg]); + switch(shifttype) { + case 0: SHL32ItoR(EAX, imm); break; + case 1: SHR32ItoR(EAX, imm); break; + case 2: SAR32ItoR(EAX, imm); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[rdreg], EAX); + } + } + else { + if( rdreg != rtreg ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[rtreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[rdreg], EAX); + } + } +} + +void rpsxSLL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 0); } +PSXRECOMPILE_CONSTCODE2(SLL); + +//// SRL +void rpsxSRL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 1); } +PSXRECOMPILE_CONSTCODE2(SRL); + +//// SRA +void rpsxSRA_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRA_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 2); } +PSXRECOMPILE_CONSTCODE2(SRA); + +//// SLLV +void rpsxSLLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxShiftVconsts(int info, int shifttype) +{ + rpsxShiftConst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_], shifttype); +} + +void rpsxShiftVconstt(int info, int shifttype) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + switch(shifttype) { + case 0: SHL32CLtoR(EAX); break; + case 1: SHR32CLtoR(EAX); break; + case 2: SAR32CLtoR(EAX); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLLV_consts(int info) { rpsxShiftVconsts(info, 0); } +void rpsxSLLV_constt(int info) { rpsxShiftVconstt(info, 0); } +void rpsxSLLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLLV); + +//// SRLV +void rpsxSRLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRLV_consts(int info) { rpsxShiftVconsts(info, 1); } +void rpsxSRLV_constt(int info) { rpsxShiftVconstt(info, 1); } +void rpsxSRLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRLV); + +//// SRAV +void rpsxSRAV_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRAV_consts(int info) { rpsxShiftVconsts(info, 2); } +void rpsxSRAV_constt(int info) { rpsxShiftVconstt(info, 2); } +void rpsxSRAV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRAV); + +extern void rpsxSYSCALL(); + +void rpsxBREAK() { +} + +void rpsxMFHI() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTHI() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } +} + +void rpsxMFLO() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTLO() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxJ() +{ + // j target + u32 newpc = _Target_ * 4 + (psxpc & 0xf0000000); + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJAL() +{ + u32 newpc = (_Target_ << 2) + ( psxpc & 0xf0000000 ); + _psxDeleteReg(31, 0); + PSX_SET_CONST(31); + g_psxConstRegs[31] = psxpc + 4; + + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJR() +{ + psxSetBranchReg(_Rs_); +} + +void rpsxJALR() +{ + // jalr Rs + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, _Rs_); + + if ( _Rd_ ) + { + _psxDeleteReg(_Rd_, 0); + PSX_SET_CONST(_Rd_); + g_psxConstRegs[_Rd_] = psxpc + 4; + } + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + + psxSetBranchReg(0xffffffff); +} + +//// BEQ +static void* s_pbranchjmp; +static u32 s_do32 = 0; + +#define JUMPVALID(pjmp) (( x86Ptr - (s8*)pjmp ) <= 0x80) + +void rpsxSetBranchEQ(int info, int process) +{ + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rt_ ], g_psxConstRegs[_Rs_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rs_ ], g_psxConstRegs[_Rt_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else { + MOV32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rs_ ] ); + CMP32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rt_ ] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } +} + +void rpsxBEQ_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] == g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + } + else + { + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + psxSaveBranchState(); + + rpsxSetBranchEQ(info, process); + + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + } +} + +void rpsxBEQ_(int info) { rpsxBEQ_process(info, 0); } +void rpsxBEQ_consts(int info) { rpsxBEQ_process(info, PROCESS_CONSTS); } +void rpsxBEQ_constt(int info) { rpsxBEQ_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BEQ, 0); + +//// BNE +void rpsxBNE_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] != g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + return; + } + + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + rpsxSetBranchEQ(info, process); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +void rpsxBNE_(int info) { rpsxBNE_process(info, 0); } +void rpsxBNE_consts(int info) { rpsxBNE_process(info, PROCESS_CONSTS); } +void rpsxBNE_constt(int info) { rpsxBNE_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BNE, 0); + +//// BLTZ +void rpsxBLTZ() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZ +void rpsxBGEZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLTZAL +void rpsxBLTZAL() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + else { + PSX_SET_CONST(_Rt_); + g_psxConstRegs[31] = psxpc+4; + } + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZAL +void rpsxBGEZAL() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + else MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLEZ +void rpsxBLEZ() +{ + // Branch if Rs <= 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] > 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JLE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JLE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +//// BGTZ +void rpsxBGTZ() +{ + // Branch if Rs > 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] <= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JG8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JG32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +void rpsxMFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxCFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxMTC0() +{ + // Cop0->Rd = Rt + if( PSX_IS_CONST1(_Rt_) ) { + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], g_psxConstRegs[_Rt_]); + } + else { + _psxDeleteReg(_Rt_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); + } +} + +void rpsxCTC0() +{ + // Cop0->Rd = Rt + rpsxMTC0(); +} + +void rpsxRFE() +{ + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); +} + +// R3000A tables +extern void (*rpsxBSC[64])(); +extern void (*rpsxSPC[64])(); +extern void (*rpsxREG[32])(); +extern void (*rpsxCP0[32])(); +extern void (*rpsxCP2[64])(); +extern void (*rpsxCP2BSC[32])(); + +static void rpsxSPECIAL() { rpsxSPC[_Funct_](); } +static void rpsxREGIMM() { rpsxREG[_Rt_](); } +static void rpsxCOP0() { rpsxCP0[_Rs_](); } +static void rpsxBASIC() { rpsxCP2BSC[_Rs_](); } + +static void rpsxNULL() { + SysPrintf("psxUNK: %8.8x\n", psxRegs.code); +} + +void (*rpsxBSC[64])() = { + rpsxSPECIAL, rpsxREGIMM, rpsxJ , rpsxJAL , rpsxBEQ , rpsxBNE , rpsxBLEZ, rpsxBGTZ, + rpsxADDI , rpsxADDIU , rpsxSLTI, rpsxSLTIU, rpsxANDI, rpsxORI , rpsxXORI, rpsxLUI , + rpsxCOP0 , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxLB , rpsxLH , rpsxLWL , rpsxLW , rpsxLBU , rpsxLHU , rpsxLWR , rpsxNULL, + rpsxSB , rpsxSH , rpsxSWL , rpsxSW , rpsxNULL, rpsxNULL, rpsxSWR , rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxSPC[64])() = { + rpsxSLL , rpsxNULL, rpsxSRL , rpsxSRA , rpsxSLLV , rpsxNULL , rpsxSRLV, rpsxSRAV, + rpsxJR , rpsxJALR, rpsxNULL, rpsxNULL, rpsxSYSCALL, rpsxBREAK, rpsxNULL, rpsxNULL, + rpsxMFHI, rpsxMTHI, rpsxMFLO, rpsxMTLO, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxMULT, rpsxMULTU, rpsxDIV, rpsxDIVU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxADD , rpsxADDU, rpsxSUB , rpsxSUBU, rpsxAND , rpsxOR , rpsxXOR , rpsxNOR , + rpsxNULL, rpsxNULL, rpsxSLT , rpsxSLTU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL +}; + +void (*rpsxREG[32])() = { + rpsxBLTZ , rpsxBGEZ , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxBLTZAL, rpsxBGEZAL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxCP0[32])() = { + rpsxMFC0, rpsxNULL, rpsxCFC0, rpsxNULL, rpsxMTC0, rpsxNULL, rpsxCTC0, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxRFE , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +// coissued insts +void (*rpsxBSC_co[64] )() = { + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpsxpropSetRead(reg) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpsxpropSetWrite(reg) { \ + prev->regs[reg] &= ~EEINST_LIVE0; \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +void rpsxpropBSC(EEINST* prev, EEINST* pinst); +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst); +void rpsxpropCP0(EEINST* prev, EEINST* pinst); +void rpsxpropCP2(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J , JAL , BEQ , BNE , BLEZ, BGTZ, +//ADDI , ADDIU , SLTI, SLTIU, ANDI, ORI , XORI, LUI , +//COP0 , NULL , COP2, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//LB , LH , LWL , LW , LBU , LHU , LWR , NULL, +//SB , SH , SWL , SW , NULL, NULL, SWR , NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL +void rpsxpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(psxRegs.code >> 26) { + case 0: rpsxpropSPECIAL(prev, pinst); break; + case 1: rpsxpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpsxpropSetWrite(31); + break; + case 4: // beq + case 5: // bne + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 6: // blez + case 7: // bgtz + rpsxpropSetRead(_Rs_); + break; + + case 15: // lui + rpsxpropSetWrite(_Rt_); + break; + + case 16: rpsxpropCP0(prev, pinst); break; + case 18: assert(0); break; + + // stores + case 40: case 41: case 42: case 43: case 46: + rpsxpropSetRead(_Rt_); + rpsxpropSetRead(_Rs_); + break; + + default: + rpsxpropSetWrite(_Rt_); + rpsxpropSetRead(_Rs_); + break; + } +} + +//SLL , NULL, SRL , SRA , SLLV , NULL , SRLV, SRAV, +//JR , JALR, NULL, NULL, SYSCALL, BREAK, NULL, NULL, +//MFHI, MTHI, MFLO, MTLO, NULL , NULL , NULL, NULL, +//MULT, MULTU, DIV, DIVU, NULL , NULL , NULL, NULL, +//ADD , ADDU, SUB , SUBU, AND , OR , XOR , NOR , +//NULL, NULL, SLT , SLTU, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rt_); + break; + + case 8: // JR + rpsxpropSetRead(_Rs_); + break; + case 9: // JALR + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_HI); + break; + case 17: // mthi + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + break; + case 18: // mflo + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_LO); + break; + case 19: // mtlo + rpsxpropSetWrite(PSX_LO); + rpsxpropSetRead(_Rs_); + break; + + case 24: // mult + case 25: // multu + case 26: // div + case 27: // divu + rpsxpropSetWrite(PSX_LO); + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpsxpropSetWrite(_Rd_); + if( _Rs_ ) rpsxpropSetRead(_Rs_); + if( _Rt_ ) rpsxpropSetRead(_Rt_); + break; + + default: + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + } +} + +//BLTZ , BGEZ , NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL, +//BLTZAL, BGEZAL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpsxpropSetRead(_Rs_); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpsxpropSetRead(_Rs_); + break; + + default: + assert(0); + break; + } +} + +//MFC0, NULL, CFC0, NULL, MTC0, NULL, CTC0, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//RFE , NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + case 2: // cfc0 + rpsxpropSetWrite(_Rt_); + break; + + case 4: // mtc0 + case 6: // ctc0 + rpsxpropSetRead(_Rt_); + break; + case 16: // rfe + break; + default: + assert(0); + } +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iR5900.c b/branches/pcsx2_0.9.1/x86/iR5900.c new file mode 100644 index 0000000..2fd708a --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iR5900.c @@ -0,0 +1,3118 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 +// Recompiled completely rewritten to add block level recompilation/reg-caching/ +// liveness analysis/constant propagation Apr06 (zerofrog@gmail.com) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "VU.h" +#include "VUmicro.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +u32 maxrecmem = 0; +uptr *recLUT; + +#define X86 +#define RECSTACK_SIZE 0x00010000 + +#define EE_NUMBLOCKS (1<<14) + +static char *recMem = NULL; // the recompiled blocks will be here +static char* recStack = NULL; // stack mem +static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here +static BASEBLOCK *recROM = NULL; // and here +static BASEBLOCK *recROM1 = NULL; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr = NULL, *recStackPtr = NULL; +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_EEFreezeRegs = 0; // if set, should freeze the regs + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what pc the current block ends +static u32 s_nHasDelay = 0; + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +extern void (*recBSC[64])(); +extern void (*recBSC_co[64])(); +void rpropBSC(EEINST* prev, EEINST* pinst); + +// save states for branches +static u16 s_savex86FpuState, s_saveiCWstate; +static GPR_reg64 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_nBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +void recCOP2RecompileInst(); +int recCOP2AnalyzeBlock(u32 startpc, u32 endpc); +void recCOP2EndBlock(void); + +#ifdef _DEBUG +u32 dumplog = 0; +#else +#define dumplog 0 +#endif + +u32 pc; // recompiler pc +int branch; // set for branch +BOOL bExecBIOS = FALSE; + +#ifdef PCSX2_DEVBUILD +static LARGE_INTEGER lbase = {0}, lfinal = {0}; +static u32 s_startcount = 0; +#endif + +#ifdef __x86_64__ +char *txt0 = "RAX = %x : RDX = %x : RCX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#else +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#endif + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls); // reccop2.c +static void iBranchTest(u32 newpc, u32 cpuBranch); +static void recRecompile( u32 startpc ); +void recCOP22( void ); + +BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 0); +} + +//////////////////////////////////////////////////// +void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + extern char *disRNameGPR[]; + u8 used[34]; + u8 fpuused[33]; + int numused, count, fpunumused; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, pc, cpuRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\dump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/dump%.8X.txt", startpc); +#endif + + fflush( stdout ); +// f = fopen( "dump1", "wb" ); +// fwrite( ptr, 1, (u32)x86Ptr - (u32)ptr, f ); +// fclose( f ); +// +//#ifdef __x86_64__ +// sprintf( command, "objdump -D --target=binary --architecture=i386:x86-64 dump1 > %s", filename ); +//#else +// sprintf( command, "objdump -D --target=binary --architecture=i386 dump1 > %s", filename ); +//#endif +// system( command ); + + f = fopen( filename, "w" ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR5900Fasm( PSMu32( i ), i ) ); + } + + // write the instruction info + + fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memset(fpuused, 0, sizeof(fpuused)); + fpunumused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count>26) { + case 26: // ldl + case 27: // ldr + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 55: // LD + case 30: // lq + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _eeIsLoadStoreCoIssue(u32 firstcode, u32 secondcode) +{ + switch(firstcode>>26) { + case 34: // lwl + return (secondcode>>26)==38; + case 38: // lwr + return (secondcode>>26)==34; + case 42: // swl + return (secondcode>>26)==46; + case 46: // swr + return (secondcode>>26)==42; + case 26: // ldl + return (secondcode>>26)==27; + case 27: // ldr + return (secondcode>>26)==26; + case 44: // sdl + return (secondcode>>26)==45; + case 45: // sdr + return (secondcode>>26)==44; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + case 30: // lq + + // stores + case 31: // sq + case 40: case 41: case 43: + case 63: // sd + case 49: // lwc1 + case 57: // swc1 + case 54: // lqc2 + case 62: // sqc2 + return (secondcode>>26)==(firstcode>>26); + } + return 0; +} + +u8 _eeIsLoadStoreCoX(u32 tempcode) +{ + switch( tempcode>>26 ) { + case 30: case 31: case 49: case 57: case 55: case 63: + return 1; + } + return 0; +} + +void _eeFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( pc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && GPR_IS_CONST1(i) ) _flushConstReg(i); + else { + _deleteMMXreg(MMX_GPR+i, 1); + _deleteGPRtoXMMreg(i, 1); + } + } + + //TODO when used info is done for FPU and VU0 + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse && xmmregs[i].type != XMMTYPE_GPRREG ) + _freeXMMreg(i); + } +} + +u32* _eeGetConstReg(int reg) +{ + assert( GPR_IS_CONST1( reg ) ); + + if( g_cpuFlushedConstReg & (1<regs[xmmregs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, xmmregs[i].reg) ) { + _freeXMMreg(i); + xmmregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushMMXunused() +{ + int i; + for (i=0; iregs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR) ) { + _freeMMXreg(i); + mmxregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_cpuHasConstReg & (1<regs[reg]&EEINST_LASTUSE) ) { + if( mmx ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + return _allocGPRtoXMMreg(-1, reg, mode); + } + + return -1; +} + +#define PROCESS_EE_SETMODES(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo +// core of reg caching +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) +{ + int mmreg1, mmreg2, mmreg3, mmtemp, moded; + + if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; + + if( xmminfo&XMMINFO_WRITED) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( xmminfo & XMMINFO_WRITED ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + } + if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededMMXreg(MMX_GPR+MMX_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededMMXreg(MMX_GPR+MMX_HI); + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_MMX) { +// mmreg1 = _allocMMXreg(-1, MMX_GPR+vreg, MODE_READ); +// _addNeededMMXreg(MMX_GPR+vreg); +// } + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(vreg)) ) { + if( EEINST_ISLIVEMMX(vreg) ) { + _freeMMXreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_MMX; + + // do it all in mmx + if( mmreg1 < 0 ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + // check for last used, if so don't alloc a new MMX reg + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_)) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg2].inuse = 1; + mmxregs[mmreg2].reg = _Rd_; + mmxregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_)) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); + _addNeededGPRtoXMMreg(_Rs_); + _addNeededGPRtoXMMreg(_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { +// mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); +// _addNeededGPRtoXMMreg(vreg); +// } + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { + _freeXMMreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_XMM; + + // do it all in xmm + if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg2].inuse = 1; + xmmregs[mmreg2].reg = _Rd_; + xmmregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2); + + // don't delete, fn will take care of them +// if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { +// _deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0); +// } +// if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { +// _deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0); +// } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rt_ ) return; + + CHECK_SAVE_REG(_Rt_); + _eeProcessHasLive(_Rt_, 0); + EEINST_RESETSIGNEXT(_Rt_); + + if( GPR_IS_CONST1(_Rs_) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _deleteGPRtoXMMreg(_Rt_, 2); + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rt_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rt_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rt_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rt_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rt_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rt_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rd_ ) return; + + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + + if( GPR_IS_CONST1(_Rt_) ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 2); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt op rs +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode) +{ + assert(0); + // for now, don't support xmm + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + multicode(0); +} + +// Simple Code Templates // + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 0); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rt_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rt_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 0); + + if( GPR_IS_CONST1(_Rs_) ) { + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST1(_Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT) +{ + assert(0); + // for now, don't support xmm + if( MULT ) { + CHECK_SAVE_REG(_Rd_); + _deleteGPRtoXMMreg(_Rd_, 0); + } + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTS); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + multicode(0); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); +} + +// EE XMM allocation code +int eeRecompileCodeXMM(int xmminfo) +{ + int info = PROCESS_EE_XMM; + + // save state + if( xmminfo & XMMINFO_WRITED ) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + // flush consts + if( xmminfo & XMMINFO_READT ) { + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + } + if( xmminfo & XMMINFO_READS) { + if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rs_); + } + } + + if( xmminfo & XMMINFO_WRITED ) { + GPR_DEL_CONST(_Rd_); + } + + // add needed + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + _addNeededGPRtoXMMreg(XMMGPR_LO); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + _addNeededGPRtoXMMreg(XMMGPR_HI); + } + if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); + if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); + if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); + + // allocate + if( xmminfo & XMMINFO_READS) { + int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); + } + if( xmminfo & XMMINFO_READT) { + int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); + } + + if( xmminfo & XMMINFO_WRITED ) { + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); + + int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); + + if( regd < 0 ) { + if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(EEREC_T); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_T].inuse = 1; + xmmregs[EEREC_T].reg = _Rd_; + xmmregs[EEREC_T].mode = readd; + regd = EEREC_T; + } + else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(EEREC_S); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_S].inuse = 1; + xmmregs[EEREC_S].reg = _Rd_; + xmmregs[EEREC_S].mode = readd; + regd = EEREC_S; + } + else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); + } + + info |= PROCESS_EE_SET_D(regd); + } + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); + info |= PROCESS_EE_LO; + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); + info |= PROCESS_EE_HI; + } + return info; +} + +// EE COP1(FPU) XMM allocation code +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +// rd = rs op rt +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo) +{ + int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; + + if( EE_FPU_REGCACHING && cpucaps.hasStreamingSIMDExtensions ) { + int info = PROCESS_EE_XMM; + + if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); + if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); + if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); + + if( xmminfo & XMMINFO_READT ) { + if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); + else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); + } + + if( xmminfo & XMMINFO_READS ) { + if( (!(xmminfo&XMMINFO_READT)||mmregt>=0) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) + mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); + } + + if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES(mmregs); + if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET(mmregt); + + if( xmminfo & XMMINFO_READD ) { + assert( xmminfo & XMMINFO_WRITED ); + mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); + } + + if( xmminfo & XMMINFO_READACC ) { + if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); + else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); + } + + if( xmminfo & XMMINFO_WRITEACC ) { + + // check for last used, if so don't alloc a new XMM reg + int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); + + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); + + if( mmregacc < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) _freeXMMreg(mmregt); + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = 0; + xmmregs[mmregt].mode = readacc; + xmmregs[mmregt].type = XMMTYPE_FPACC; + mmregacc = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) _freeXMMreg(mmregs); + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = 0; + xmmregs[mmregs].mode = readacc; + xmmregs[mmregs].type = XMMTYPE_FPACC; + mmregacc = mmregs; + } + else mmregacc = _allocFPACCtoXMMreg(-1, readacc); + } + + xmmregs[mmregacc].mode |= MODE_WRITE; + } + else if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); + + if( mmregd < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) _freeXMMreg(mmregt); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = _Fd_; + xmmregs[mmregt].mode = readd; + mmregd = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) _freeXMMreg(mmregs); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = _Fd_; + xmmregs[mmregs].mode = readd; + mmregd = mmregs; + } + else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { + if( FPUINST_ISLIVE(XMMFPU_ACC) ) _freeXMMreg(mmregacc); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregacc].inuse = 1; + xmmregs[mmregacc].reg = _Fd_; + xmmregs[mmregacc].mode = readd; + xmmregs[mmregacc].type = XMMTYPE_FPREG; + mmregd = mmregacc; + } + else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + } + } + + assert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); + + if( xmminfo & XMMINFO_WRITED ) { + assert( mmregd >= 0 ); + info |= PROCESS_EE_SET_D(mmregd); + } + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { + if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; + else assert( !(xmminfo&XMMINFO_WRITEACC)); + } + + if( xmminfo & XMMINFO_READS ) { + if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; + } + if( xmminfo & XMMINFO_READT ) { + if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; + } + + // at least one must be in xmm + if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { + assert( mmregs >= 0 || mmregt >= 0 ); + } + + xmmcode(info); + _clearNeededXMMregs(); + return; + } + + if( xmminfo & XMMINFO_READS ) _deleteFPtoXMMreg(_Fs_, 0); + if( xmminfo & XMMINFO_READT ) _deleteFPtoXMMreg(_Ft_, 0); + if( xmminfo & (XMMINFO_READD|XMMINFO_WRITED) ) _deleteFPtoXMMreg(_Fd_, 0); + if( xmminfo & (XMMINFO_READACC|XMMINFO_WRITEACC) ) _deleteFPtoXMMreg(XMMFPU_ACC, 0); + fpucode(0); +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +//////////////////////////////////////////////////// +extern u8 g_MACFlagTransform[256]; // for vus + +u32 g_sseMXCSR = 0x9f80; // disable all exception, round to 0, flush to 0 +u32 g_sseVUMXCSR = 0xff80; +void SetCPUState() +{ + // SSE STATE // + // do NOT set Denormals-Are-Zero flag (charlie and chocfac messes up) + g_sseMXCSR = 0x9f80; // changing the rounding mode to 0x2000 (near) kills grandia III! + // changing the rounding mode to 0x0000 or 0x4000 totally kills gitaroo + // so... grandia III wins + + __asm ldmxcsr g_sseMXCSR // set the new sse control + g_sseVUMXCSR = g_sseMXCSR|0x6000; +} + +extern BOOL install_my_handler(); + +int recInit( void ) +{ + int i; + const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + + recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 ); + memset( recLUT, 0, 0x010000 * sizeof(uptr) ); + recMem = (char*)SysMmap(0, 0x00c00000); + + // 32 alignment necessary + recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK)); + recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK)); + recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK)); + recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16); + recStack = (char*)malloc( RECSTACK_SIZE ); + + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize ); + + if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) { + SysMessage( _( "Error allocating memory" ) ); + return -1; + } + + for ( i = 0x0000; i < 0x0200; i++ ) + { + recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0040; i++ ) + { + recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0004; i++ ) + { + recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + } + + memcpy( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); + memcpy( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); + + memset(recMem, 0xcd, 0x00c00000); + memset(recStack, 0, RECSTACK_SIZE); + + // SSE3 detection, manually create the code + x86SetPtr(recMem); + SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0); + RET(); + + cpucaps.hasStreamingSIMD3Extensions = 1; + __try { + __asm call recMem + } + __except(EXCEPTION_EXECUTE_HANDLER) { + cpucaps.hasStreamingSIMD3Extensions = 0; + +#ifdef WIN32_VIRTUAL_MEM + // necessary since can potentially kill the custom handler + install_my_handler(); +#endif + } + + SysPrintf( "x86Init: \n" ); + SysPrintf( "\tCPU vender name = %s\n", cpuinfo.x86ID ); + SysPrintf( "\tFamilyID = %x\n", cpuinfo.x86StepID ); + SysPrintf( "\tx86Family = %s\n", cpuinfo.x86Fam ); + SysPrintf( "\tCPU speed = %d MHZ\n", cpuinfo.cpuspeed); + SysPrintf( "\tx86PType = %s\n", cpuinfo.x86Type ); + SysPrintf( "\tx86Flags = %8.8x\n", cpuinfo.x86Flags ); + SysPrintf( "\tx86EFlags = %8.8x\n", cpuinfo.x86EFlags ); + SysPrintf( "Features: \n" ); + SysPrintf( "\t%sDetected MMX\n", cpucaps.hasMultimediaExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE\n", cpucaps.hasStreamingSIMDExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE2\n", cpucaps.hasStreamingSIMD2Extensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE3\n", cpucaps.hasStreamingSIMD3Extensions ? "" : "Not " ); + + if ( cpuinfo.x86ID[0] == 'A' ) //AMD cpu + { + SysPrintf( " Extented AMD Features: \n" ); + SysPrintf( "\t%sDetected MMX2\n", cpucaps.hasMultimediaExtensionsExt ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW\n", cpucaps.has3DNOWInstructionExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW2\n", cpucaps.has3DNOWInstructionExtensionsExt ? "" : "Not " ); + } + if ( !( cpucaps.hasMultimediaExtensions ) ) + { + SysMessage( _( "Processor doesn't supports MMX, can't run recompiler without that" ) ); + return -1; + } + + x86FpuState = FPU_STATE; + + SuperVUInit(-1); + + for(i = 0; i < 256; ++i) { + g_MACFlagTransform[i] = macarr[i>>4]|(macarr[i&15]<<4); + } + + SetCPUState(); + + return 0; +} + +//////////////////////////////////////////////////// +void recReset( void ) { +#ifdef PCSX2_DEVBUILD + SysPrintf("EE Recompiler data reset\n"); +#endif + + s_nNextBlock = 0; + maxrecmem = 0; + memset( recRAM, 0, sizeof(BASEBLOCK)/4*0x02000000 ); + memset( recROM, 0, sizeof(BASEBLOCK)/4*0x00400000 ); + memset( recROM1, 0, sizeof(BASEBLOCK)/4*0x00040000 ); + memset( recBlocks, 0, sizeof(BASEBLOCKEX)*EE_NUMBLOCKS ); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); + ResetBaseBlockEx(0); + + __asm emms + +#ifdef _DEBUG + // don't clear since save states won't work + //memset(recMem, 0xcd, 0x00c00000); +#endif + + recPtr = recMem; + recStackPtr = recStack; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +void recShutdown( void ) +{ + if ( recMem == NULL ) { + return; + } + + _aligned_free( recLUT ); + SysMunmap((uptr)recMem, 0x00800000); recMem = NULL; + _aligned_free( recRAM ); recRAM = NULL; + _aligned_free( recROM ); recROM = NULL; + _aligned_free( recROM1 ); recROM1 = NULL; + _aligned_free( recBlocks ); recBlocks = NULL; + free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0; + + SuperVUDestroy(-1); + + x86Shutdown( ); +} + +void recEnableVU0micro(int enable) { +} + +void recEnableVU1micro(int enable) { +} + +#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code +static u32 s_uSaveESP = 0, s_uSaveEBP; + +static void execute( void ) +{ +#ifdef _DEBUG + u8* fnptr; + u32 oldesi; +#else + R5900FNPTR pfn; +#endif + BASEBLOCK* pblock = PC_GETBLOCK(cpuRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != cpuRegs.pc ) { + recRecompile(cpuRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + g_EEFreezeRegs = 1; + + // skip the POPs +#ifdef _DEBUG + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + mov s_uSaveEBP, ebp + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R5900FNPTR)pblock->pFnptr); + // use call instead of pfn() + //__asm mov s_uSaveEBP, ebp + __asm call pfn + +#endif + + g_EEFreezeRegs = 0; +} + +void recStep( void ) { +} + +void recExecute( void ) { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);//ABOVE_NORMAL_PRIORITY_CLASS); + if( Config.Options & PCSX2_EEREC ) Config.Options |= PCSX2_COP2REC; + + for (;;) + execute(); +} + +void recExecuteBlock( void ) { + execute(); +} + +//////////////////////////////////////////////////// +extern u32 g_nextBranchCycle; + +u32 g_lastpc = 0; +static u32 g_temp; + +// jumped to when invalid pc address +__declspec(naked,noreturn) void Dispatcher() +{ + // EDX contains the current pc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == cpuRegs.pc + mov ecx, cpuRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push cpuRegs.pc // pc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new pc +// and eax, 0x0fffffff +// mov ecx, cpuRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void DispatcherClear() +{ + // EDX contains the current pc + __asm mov cpuRegs.pc, edx + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + if( s_pDispatchBlock->startpc == cpuRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable pc address +__declspec(naked,noreturn) void DispatcherReg() +{ + __asm { + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov edx, cpuRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == cpuRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +//////////////////////////////////////////////////// +void recClear64(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 16)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); +} + +void recClear128(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 32)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); + if( left > 2 && *(u32*)(p+2) ) recClearMem(p+2); + if( left > 3 && *(u32*)(p+3) ) recClearMem(p+3); +} + +void recClear( u32 Addr, u32 Size ) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + REC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void recClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + recClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PC_GETBLOCK(p->startpc); + pexblock = PC_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 0); + pexblock->size = 0; + pexblock->startpc = 0; +} + +// check for end of bios +void CheckForBIOSEnd() +{ + MOV32MtoR(EAX, (int)&cpuRegs.pc); + + CMP32ItoR(EAX, 0x00200008); + j8Ptr[0] = JE8(0); + + CMP32ItoR(EAX, 0x00100008); + j8Ptr[1] = JE8(0); + + // return + j8Ptr[2] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[1] ); + + // bios end + RET2(); + + x86SetJ8( j8Ptr[2] ); +} + +static int *s_pCode; + +void SetBranchReg( u32 reg ) +{ + branch = 1; + + if( reg != 0xffffffff ) { +// if( GPR_IS_CONST1(reg) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[reg].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+reg, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ reg ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, reg); + + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + } + +// CMP32ItoM((u32)&cpuRegs.pc, 0); +// j8Ptr[5] = JNE8(0); +// CALLFunc((u32)tempfn); +// x86SetJ8( j8Ptr[5] ); + + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void SetBranchImm( u32 imm ) +{ + u32* ptr; + branch = 1; + + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&cpuRegs.pc, imm ); + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(imm, imm <= pc); + if( bExecBIOS ) CheckForBIOSEnd(); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)Dispatcher - ( (u32)x86Ptr + 5 )); +} + +void SaveBranchState() +{ + s_savex86FpuState = x86FpuState; + s_saveiCWstate = iCWstate; + s_savenBlockCycles = s_nBlockCycles; + s_saveConstGPRreg = 0xffffffff; // indicate searching + s_saveHasConstReg = g_cpuHasConstReg; + s_saveFlushedConstReg = g_cpuFlushedConstReg; + s_psaveInstInfo = g_pCurInstInfo; + s_saveRegHasLive1 = g_cpuRegHasLive1; + s_saveRegHasSignExt = g_cpuRegHasSignExt; + + // save all mmx regs + memcpy(s_saveMMXregs, mmxregs, sizeof(mmxregs)); + memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); +} + +void LoadBranchState() +{ + x86FpuState = s_savex86FpuState; + iCWstate = s_saveiCWstate; + s_nBlockCycles = s_savenBlockCycles; + + if( s_saveConstGPRreg != 0xffffffff ) { + assert( s_saveConstGPRreg > 0 ); + + // make sure right GPR was saved + assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<ltime); + CALLFunc((u32)_StopPerfCounter); + } +#endif +} + +#define USE_FAST_BRANCHES 0 + +//void testfpu() +//{ +// int i; +// for(i = 0; i < 32; ++i ) { +// if( fpuRegs.fpr[i].UL== 0x7f800000 || fpuRegs.fpr[i].UL == 0xffc00000) { +// SysPrintf("bad fpu: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// +// if( VU0.VF[i].UL[0] == 0xffc00000 || //(VU0.VF[i].UL[1]&0xffc00000) == 0xffc00000 || +// VU0.VF[i].UL[0] == 0x7f800000) { +// SysPrintf("bad vu0: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// } +//} + +//static void cleanup() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +static void iBranchTest(u32 newpc, u32 cpuBranch) +{ +#ifdef PCSX2_DEVBUILD + if( s_startcount ) { + StopPerfCounter(); + ADD32ItoM( (u32)&s_pCurBlockEx->visited, 1 ); + } +#endif + +#ifdef _DEBUG + //CALLFunc((u32)testfpu); +#endif + + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&cpuRegs.cycle); + ADD32ItoR(ECX, s_nBlockCycles*9/8); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI + MOV32RtoM((int)&cpuRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + return; + } + + SUB32MtoR(ECX, (int)&g_nextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + // has to be in the middle of Save/LoadBranchState + CALLFunc( (int)cpuBranchTest ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&cpuRegs.pc, newpc); + JNE32((u32)DispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + + +//////////////////////////////////////////////////// +#ifndef CP2_RECOMPILE + +REC_SYS(COP2); + +#else + +void recCOP2( void ) +{ +#ifdef CPU_LOG + CPU_LOG( "Recompiling COP2:%s\n", disR5900Fasm( cpuRegs.code, cpuRegs.pc ) ); +#endif + +// if ( !CHECK_COP2REC ) //disable the use of vus better this way :P +// { +// assert( !CHECK_EEREC ); +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// g_cpuHasConstReg = 1; // reset all since COP2 can change regs +// CALLFunc( (u32)COP2 ); +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); +// JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +// x86SetJ8(j8Ptr[0]); +//// branch = 2; +// } +// else + { + recCOP22( ); + } +} + +#endif + +//////////////////////////////////////////////////// +void recSYSCALL( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)SYSCALL ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +void recBREAK( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BREAK ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + RET(); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("code changed! %x\n", pctemp); + assert(0); +} + +void checkpchanged(u32 startpc) +{ + assert(0); +} + +//#ifdef _DEBUG +//#define CHECK_XMMCHANGED() CALLFunc((u32)checkxmmchanged); +//#else +//#define CHECK_XMMCHANGED() +//#endif +// +//static void checkxmmchanged() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +u32 recompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PC_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pc == pblock->startpc ) + return 0; + } + + return 1; +} + +void recompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + int i, count; + + BASEBLOCK* pblock = PC_GETBLOCK(pc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && pc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == pc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + recClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", pc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSM( pc ); + assert(s_pCode); + +#ifdef _DEBUG + MOV32ItoR(EAX, pc); +#endif + + cpuRegs.code = *(int *)s_pCode; + s_nBlockCycles++; + pc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, cpuRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, pc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +// +// if( !delayslot ) { +// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); +// j8Ptr[0] = JB8(0); +// CMP32ItoM((u32)&cpuRegs.pc, pc); +// j8Ptr[1] = JA8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[ 0 ] ); +// x86SetJ8( j8Ptr[ 1 ] ); +// PUSH32I(s_pCurBlockEx->startpc); +// CALLFunc((u32)checkpchanged); +// ADD32ItoR(ESP, 4); +// x86SetJ8( j8Ptr[ 2 ] ); +// } +//#endif + + g_pCurInstInfo++; + + // reorder register priorities +// for(i = 0; i < X86REGS; ++i) { +// if( x86regs[i].inuse ) { +// if( count > 0 ) mmxregs[i].counter = 1000-count; +// else mmxregs[i].counter = 0; +// } +// } + + for(i = 0; i < MMXREGS; ++i) { + if( mmxregs[i].inuse ) { + assert( MMX_ISGPR(mmxregs[i].reg) ); + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR); + if( count > 0 ) mmxregs[i].counter = 1000-count; + else mmxregs[i].counter = 0; + } + } + + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); + if( count > 0 ) xmmregs[i].counter = 1000-count; + else xmmregs[i].counter = 0; + } + } + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + +#ifdef WIN32_VIRTUAL_MEM + if( g_pCurInstInfo->numpeeps > 1 ) { + switch(cpuRegs.code>>26) { + case 30: recLQ_coX(g_pCurInstInfo->numpeeps); break; + case 31: recSQ_coX(g_pCurInstInfo->numpeeps); break; + case 49: recLWC1_coX(g_pCurInstInfo->numpeeps); break; + case 57: recSWC1_coX(g_pCurInstInfo->numpeeps); break; + case 55: recLD_coX(g_pCurInstInfo->numpeeps); break; + case 63: recSD_coX(g_pCurInstInfo->numpeeps); break; + default: + assert(0); + } + + pc += g_pCurInstInfo->numpeeps*4; + s_nBlockCycles += g_pCurInstInfo->numpeeps; + g_pCurInstInfo += g_pCurInstInfo->numpeeps; + } + else { + recBSC_co[cpuRegs.code>>26](); + pc += 4; + s_nBlockCycles++; + g_pCurInstInfo++; + } +#else + assert(0); +#endif + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + + recBSC[ cpuRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //if( !_flushUnusedConstReg() ) { + int flushed = 0; + if( _getNumMMXwrite() > 3 ) flushed = _flushMMXunused(); + if( !flushed && _getNumXMMwrite() > 2 ) _flushXMMunused(); + s_bFlushReg = !flushed; +// } +// else s_bFlushReg = 0; + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + //CHECK_XMMCHANGED(); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +__declspec(naked) void iDummyBlock() +{ +// g_lastpc = cpuRegs.pc; +// +// do { +// cpuRegs.cycle = g_nextBranchCycle; +// cpuBranchTest(); +// } while(g_lastpc == cpuRegs.pc); +// +// __asm jmp DispatcherReg + __asm { +RepDummy: + add cpuRegs.cycle, 9 + call cpuBranchTest + cmp cpuRegs.pc, 0x81fc0 + je RepDummy + jmp DispatcherReg + } +} + +//////////////////////////////////////////////////// +#include "r3000a.h" +#include "PsxCounters.h" +extern tIPU_BP g_BP; + +extern u32 psxdump; +extern u32 psxNextCounter, psxNextsCounter; +extern void iDumpPsxRegisters(u32 startpc, u32 temp); +extern Counter counters[6]; +void iDumpRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + + __Log("%sreg: %x %x\n", pstr, startpc, cpuRegs.interrupt); + for(i = 1; i < 32; ++i) __Log("%s%d: %x_%x_%x_%x\n", pstr, i, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x\n", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x\n", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x\n", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x\n", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + __Log("%svfACC: %x %x %x %x\n", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x\n", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x\n", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("cyc11: %x %x; vu0: %x, vu1: %x\n", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x\n", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x\n", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + } + __Log("ipu %x %x %x %x; bp: %x %x %x %x\n", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x\n", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + for(i = 0; i < ARRAYSIZE(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x\n", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x\n", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x\n", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x\n", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +} + +extern u32 psxdump; + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0, count2 = 0; + const int skip = 0; + static int i; + + assert( !g_globalMMXSaved ); + assert( !g_globalXMMSaved ); + +#ifdef _DEBUG + __asm stmxcsr i + assert( i = g_sseMXCSR ); +#endif + + if( (dumplog&2) ) {//&& lastrec != g_lastpc ) { + + curcount++; + + if( curcount > skip ) { + iDumpRegisters(g_lastpc, 1); + curcount = 0; + } + + lastrec = g_lastpc; + } +} + +u32 s_recblocks[] = {0}; + +void badespfn() { + assert(0); + SysPrintf("Bad esp!\n"); +} + +#define OPTIMIZE_COP2 0//CHECK_VU0REC + +static void recRecompile( u32 startpc ) +{ + u32 i = 0; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + u32 usecop2; + +#ifdef _DEBUG + //dumplog |= 4; + if( dumplog & 4 ) + iDumpRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)recPtr - (uptr)recMem ) >= 0xb92000 || dumplog == 0xffffffff) { + recReset(); + } + if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) { +#ifdef _DEBUG + SysPrintf("stack reset\n"); +#endif + recReset(); + } + + s_pCurBlock = PC_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + recClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < EE_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_pCurBlock->startpc = startpc; + + // slower +// if( startpc == 0x81fc0 ) { +// +// MOV32MtoR(ECX, (u32)&g_nextBranchCycle); +// MOV32RtoM((u32)&cpuRegs.cycle, ECX); +// //ADD32ItoR(ECX, 9); +// //ADD32ItoM((u32)&cpuRegs.cycle, 512); +// CALLFunc((u32)cpuBranchTest); +// CMP32ItoM((u32)&cpuRegs.pc, 0x81fc0); +// JE8(s_pCurBlock->pFnptr - (u32)(x86Ptr+2) ); +// JMP32((u32)DispatcherReg - (u32)(x86Ptr+5)); +// +// pc = startpc + 9*4; +// assert( (pc-startpc)>>2 <= 0xffff ); +// s_pCurBlockEx->size = (pc-startpc)>>2; +// +// for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // don't overwrite if delay slot +// if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // set the block ptr +// AddBaseBlockEx(s_pCurBlockEx, 0); +// +// if( !(pc&0x10000000) ) +// maxrecmem = max( (pc&~0xa0000000), maxrecmem ); +// +// recPtr = x86Ptr; +// return; +// } + + branch = 0; + + // reset recomp state variables + s_nBlockCycles = 0; + pc = startpc; + x86FpuState = FPU_STATE; + iCWstate = 0; + s_saveConstGPRreg = 0; + g_cpuHasConstReg = g_cpuFlushedConstReg = 1; + g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; + g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; + _recClearWritebacks(); + assert( g_cpuConstRegs[0].UD[0] == 0 ); + + _initX86regs(); + _initXMMregs(); + _initMMXregs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_lastpc, pc); + CALLFunc((u32)printfn); + +// CMP32MtoR(EBP, (u32)&s_uSaveEBP); +// j8Ptr[0] = JE8(0); +// CALLFunc((u32)badespfn); +// x86SetJ8(j8Ptr[0]); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + s_nHasDelay = 0; + + while(1) { + BASEBLOCK* pblock = PC_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + cpuRegs.code = *(int *)PSM(i); + + switch(cpuRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + s_nHasDelay = 1; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) { + // branches + if( _Rt_ == 2 && _Rt_ == 3 && _Rt_ == 18 && _Rt_ == 19 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nHasDelay = 1; + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + case 20: case 21: case 22: case 23: + + if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + + case 16: // cp0 + if( _Rs_ == 16 ) { + if( _Funct_ == 24 ) { // eret + s_nEndBlock = i+4; + goto StartRecomp; + } + } + + break; + case 17: // cp1 + case 18: // cp2 + if( _Rs_ == 8 ) { + // BC1F, BC1T, BC1FL, BC1TL + // BC2F, BC2T, BC2FL, BC2TL + if( _Rt_ >= 2 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + break; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + cpuRegs.code = *(int *)PSM(i-4); + pcur[-1] = pcur[0]; + rpropBSC(pcur-1, pcur); + pcur--; + } + } + + // analyze instructions // + { + usecop2 = 0; + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock; i += 4) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(i); + + // cop2 // + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + + if( !usecop2 ) { + // init + if( OPTIMIZE_COP2 ) { + memset(VU0.fmac,0,sizeof(VU0.fmac)); + memset(&VU0.fdiv,0,sizeof(VU0.fdiv)); + memset(&VU0.efu,0,sizeof(VU0.efu)); + } + vucycle = 0; + usecop2 = 1; + } + + VU0.code = cpuRegs.code; + _cop2AnalyzeOp(g_pCurInstInfo, OPTIMIZE_COP2); + continue; + } + + if( usecop2 ) vucycle++; + + // peephole optimizations // +#ifdef WIN32_VIRTUAL_MEM + if( i < s_nEndBlock-4 && recompileCodeSafe(i) ) { + u32 curcode = cpuRegs.code; + u32 nextcode = *(u32*)PSM(i+4); + if( _eeIsLoadStoreCoIssue(curcode, nextcode) && recBSC_co[curcode>>26] != NULL ) { + + // rs has to be the same, and cannot be just written + if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_eeLoadWritesRs(curcode) ) { + + if( _eeIsLoadStoreCoX(curcode) && ((nextcode>>16)&0x1f) != ((curcode>>21)&0x1f) ) { + // see how many stores there are + u32 j; + // use xmmregs since only supporting lwc1,lq,swc1,sq + for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + u32 nncode = *(u32*)PSM(j); + if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || + _eeLoadWritesRs(nncode)) + break; + } + + if( j > i+8 ) { + u32 num = (j-i)>>2; // number of stores that can coissue + assert( num <= XMMREGS ); + + g_pCurInstInfo[0].numpeeps = num-1; + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + + while(i < j-4) { + g_pCurInstInfo++; + g_pCurInstInfo[0].info |= EEINSTINFO_NOREC; + i += 4; + } + + continue; + } + + // fall through + } + + // unaligned loadstores + + // if LWL, check if LWR and that offsets are +3 away + switch(curcode >> 26) { + case 0x22: // LWL + if( (nextcode>>26) != 0x26 || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x26: // LWR + if( (nextcode>>26) != 0x22 || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x2a: // SWL + if( (nextcode>>26) != 0x2e || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x2e: // SWR + if( (nextcode>>26) != 0x2a || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x1a: // LDL + if( (nextcode>>26) != 0x1b || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x1b: // LWR + if( (nextcode>>26) != 0x1aa || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + + case 0x2c: // SWL + if( (nextcode>>26) != 0x2d || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x2d: // SWR + if( (nextcode>>26) != 0x2c || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + } + + // good enough + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + g_pCurInstInfo[0].numpeeps = 1; + g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; + g_pCurInstInfo++; + i += 4; + continue; + } + } + } +#endif // end peephole + } + + if( usecop2 ) { + // add necessary mac writebacks + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock-4; i += 4) { + g_pCurInstInfo++; + + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + } + } + } + } + + // perf counters // +#ifdef PCSX2_DEVBUILD + s_startcount = 0; +// if( pc+32 < s_nEndBlock ) { +// // only blocks with more than 8 insts +// PUSH32I((u32)&lbase); +// CALLFunc((u32)QueryPerformanceCounter); +// s_startcount = 1; +// } +#endif + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + // finally recompile // + g_pCurInstInfo = s_pInstCache; + while (!branch && pc < s_nEndBlock) { + recompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (pc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (pc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 0); +// if( p[1].startpc == p[0].startpc + 4 ) { +// assert( p[1].pFnptr != 0 ); +// // already fn in place, so add to list +// AddBaseBlockEx(s_pCurBlockEx, 0); +// } +// else +// *(BASEBLOCKEX**)(p+1) = pex; +// } + + //PC_SETBLOCKEX(s_pCurBlock, s_pCurBlockEx); + + if( !(pc&0x10000000) ) + maxrecmem = max( (pc&~0xa0000000), maxrecmem ); + + if( branch == 2 ) { + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( branch != 3 ); + if( branch ) assert( !willbranch3 ); + else ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + + if( willbranch3 ) { + BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); + assert( pc == s_nEndBlock ); + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + } + else if( !branch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + + iFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+0x00c00000 ); + assert( recStackPtr < recStack+RECSTACK_SIZE ); + assert( x86FpuState == 0 ); + + recPtr = x86Ptr; + + assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); + + if( !branch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PC_GETBLOCK(pc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != pc ) + recRecompile(pc); + + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R5900cpu recCpu = { + recInit, + recReset, + recStep, + recExecute, + recExecuteBlock, + recExecuteVU0Block, + recExecuteVU1Block, + recEnableVU0micro, + recEnableVU1micro, + recClear, + recClearVU0, + recClearVU1, + recShutdown +}; diff --git a/branches/pcsx2_0.9.1/x86/iR5900.h b/branches/pcsx2_0.9.1/x86/iR5900.h new file mode 100644 index 0000000..848f1c9 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iR5900.h @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900_H__ +#define __IR5900_H__ + +#include "VU.h" +#include "iCore.h" + +// these might not work anymore +#define ARITHMETICIMM_RECOMPILE +#define ARITHMETIC_RECOMPILE +#define MULTDIV_RECOMPILE +#define SHIFT_RECOMPILE +#define BRANCH_RECOMPILE +#define JUMP_RECOMPILE +#define LOADSTORE_RECOMPILE +#define MOVE_RECOMPILE +#define MMI_RECOMPILE +#define MMI0_RECOMPILE +#define MMI1_RECOMPILE +#define MMI2_RECOMPILE +#define MMI3_RECOMPILE +#define FPU_RECOMPILE +#define CP0_RECOMPILE +#define CP2_RECOMPILE + +#define EE_CONST_PROP // rec2 - enables constant propagation (faster) +#define EE_FPU_REGCACHING 1 + +#define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT) + +void recClearMem(BASEBLOCK* p); +#define REC_CLEARM(mem) { \ + if ((mem) < maxrecmem && recLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PC_GETBLOCK(mem); \ + if( *(u32*)p ) recClearMem(p); \ + } \ +} \ + +extern u32 pc; +extern int branch; +extern uptr* recLUT; + +extern u32 pc; // recompiler pc +extern int branch; // set for branch +extern u32 target; // branch target +extern u16 x86FpuState; +extern u16 iCWstate; +extern u32 s_nBlockCycles; // cycles of current block recompiling + +#define REC_FUNC_INLINE( f, delreg ) \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); + +#define REC_FUNC( f, delreg ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); \ + } + +#define REC_SYS( f ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc( (u32)f ); \ + branch = 2; \ + } + +// used when processing branches +void SaveBranchState(); +void LoadBranchState(); + +void recompileNextInstruction(int delayslot); +void SetBranchReg( u32 reg ); +void SetBranchImm( u32 imm ); + +void iFlushCall(int flushtype); +void SaveCW(); +void LoadCW(); + +extern void (*recBSC[64])(); +extern void (*recSPC[64])(); +extern void (*recREG[32])(); +extern void (*recCP0[32])(); +extern void (*recCP0BC0[32])(); +extern void (*recCP0C0[64])(); +extern void (*recCP1[32])(); +extern void (*recCP1BC1[32])(); +extern void (*recCP1S[64])(); +extern void (*recCP1W[64])(); +extern void (*recMMIt[64])(); +extern void (*recMMI0t[32])(); +extern void (*recMMI1t[32])(); +extern void (*recMMI2t[32])(); +extern void (*recMMI3t[32])(); + +u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg + +void _eeFlushAllUnused(); +void _eeOnWriteReg(int reg, int signext); + +// totally deletes from const, xmm, and mmx entries +// if flush is 1, also flushes to memory +// if 0, only flushes if not an xmm reg (used when overwriting lower 64bits of reg) +void _deleteEEreg(int reg, int flush); + +// allocates memory on the instruction size and returns the pointer +void* recAllocStackMem(int size, int align); + +////////////////////////////////////// +// Templates for code recompilation // +////////////////////////////////////// +typedef void (*R5900FNPTR)(); +typedef void (*R5900FNPTR_INFO)(int info); + +#define EERECOMPILE_CODE0(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeRecompileCode0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_, xmminfo); \ +} \ + +#define EERECOMPILE_CODEX(codename, fn) \ +void rec##fn(void) \ +{ \ + codename(rec##fn##_const, rec##fn##_); \ +} \ + +// +// MMX/XMM caching helpers +// + +// rd = rs op rt +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo); +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rt op rs (SPECIAL) +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define EERECOMPILE_CONSTCODE0(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_); \ +} \ + +// rt = rs op imm16 +#define EERECOMPILE_CONSTCODE1(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst1(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op sa +#define EERECOMPILE_CONSTCODE2(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst2(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op rs +#define EERECOMPILE_CONSTCODESPECIAL(fn, mult) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConstSPECIAL(rec##fn##_const, rec##fn##_, mult); \ +} \ + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode); +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT); + +// XMM caching helpers +#define XMMINFO_READLO 0x01 +#define XMMINFO_READHI 0x02 +#define XMMINFO_WRITELO 0x04 +#define XMMINFO_WRITEHI 0x08 +#define XMMINFO_WRITED 0x10 +#define XMMINFO_READD 0x20 +#define XMMINFO_READS 0x40 +#define XMMINFO_READT 0x80 +#define XMMINFO_READD_LO 0x100 // if set and XMMINFO_READD is set, reads only low 64 bits of D +#define XMMINFO_READACC 0x200 +#define XMMINFO_WRITEACC 0x400 + +#define CPU_SSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_SSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_SSE_XMMCACHE_END \ + _clearNeededXMMregs(); \ + return; \ + } \ + +#define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeFPURecompileCode(rec##fn##_xmm, rec##fn##_, xmminfo); \ +} \ + +// rd = rs op rt (all regs need to be in xmm) +int eeRecompileCodeXMM(int xmminfo); +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo); + +#endif // __IR5900_H__ \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iVU0micro.c b/branches/pcsx2_0.9.1/x86/iVU0micro.c new file mode 100644 index 0000000..e723252 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVU0micro.c @@ -0,0 +1,789 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +static VURegs * const VU = (VURegs*)&VU0; + +//u32 vu0time = 0; +//static LARGE_INTEGER vu0base, vu0final; + +#ifdef PCSX2_DEVBUILD +extern u32 vudump; +#endif + +#define VF_VAL(x) ((x==0x80000000)?0:x) +static u32 vuprogcount = 0; +void iDumpVU0Registers() +{ + int i; + for(i = 1; i < 32; ++i) { + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), + VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F); + else if( i == REG_MAC_FLAG ) __Log("%x\n", VU0.VI[i].UL&0xff); + else if( i == REG_STATUS_FLAG ) __Log("%x\n", VU0.VI[i].UL&0x03); + else if( i == REG_CLIP_FLAG ) __Log("0\n"); + else __Log("%x\n", VU0.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); +} + +void recExecuteVU0Block( void ) +{ + //SysPrintf("executeVU0 %x\n", VU0.VI[ REG_TPC ].UL); + //QueryPerformanceCounter(&vu0base); + + assert( VU0.VI[REG_VPU_STAT].UL & 1 ); + +#ifdef _DEBUG + vuprogcount++; + +// __Log("VU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); + + //vudump |= 0x10; + //vudump |= 8; + + if( (vudump&8) && !CHECK_VU0REC ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + + ///while( (VU0.VI[ REG_VPU_STAT ].UL&1) ) { + if( CHECK_VU0REC) { + FreezeXMMRegs(1); + SuperVUExecuteProgram(VU0.VI[ REG_TPC ].UL, 0); + } + else { + intExecuteVU0Block(); + } + //} + +// __Log("eVU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); +// QueryPerformanceCounter(&vu0final); +// vu0time += (u32)(vu0final.QuadPart-vu0final.QuadPart); +} + +void recClearVU0( u32 Addr, u32 Size ) +{ + if( CHECK_VU0REC ) { + SuperVUClear(Addr, Size*4, 0); + } +} + +void (*recVU0_LOWER_OPCODE[128])() = { + recVU0MI_LQ , recVU0MI_SQ , recVU0unknown , recVU0unknown, + recVU0MI_ILW , recVU0MI_ISW , recVU0unknown , recVU0unknown, + recVU0MI_IADDIU, recVU0MI_ISUBIU, recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_FCEQ , recVU0MI_FCSET , recVU0MI_FCAND, recVU0MI_FCOR, /* 0x10 */ + recVU0MI_FSEQ , recVU0MI_FSSET , recVU0MI_FSAND, recVU0MI_FSOR, + recVU0MI_FMEQ , recVU0unknown , recVU0MI_FMAND, recVU0MI_FMOR, + recVU0MI_FCGET , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_B , recVU0MI_BAL , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0MI_JR , recVU0MI_JALR , recVU0unknown , recVU0unknown, + recVU0MI_IBEQ , recVU0MI_IBNE , recVU0unknown , recVU0unknown, + recVU0MI_IBLTZ , recVU0MI_IBGTZ , recVU0MI_IBLEZ, recVU0MI_IBGEZ, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x40*/ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x50 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x60 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x70 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, +}; + +void (*recVU0LowerOP_T3_00_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MOVE , recVU0MI_LQI , recVU0MI_DIV , recVU0MI_MTIR, + recVU0MI_RNEXT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_MFP , recVU0unknown , recVU0unknown, + recVU0MI_ESADD , recVU0MI_EATANxy, recVU0MI_ESQRT, recVU0MI_ESIN, +}; + +void (*recVU0LowerOP_T3_01_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MR32 , recVU0MI_SQI , recVU0MI_SQRT , recVU0MI_MFIR, + recVU0MI_RGET , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0MI_XITOP, recVU0unknown, + recVU0MI_ERSADD, recVU0MI_EATANxz, recVU0MI_ERSQRT, recVU0MI_EATAN, +}; + +void (*recVU0LowerOP_T3_10_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_LQD , recVU0MI_RSQRT, recVU0MI_ILWR, + recVU0MI_RINIT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ELENG , recVU0MI_ESUM , recVU0MI_ERCPR, recVU0MI_EEXP, +}; + +void (*recVU0LowerOP_T3_11_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_SQD , recVU0MI_WAITQ, recVU0MI_ISWR, + recVU0MI_RXOR , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ERLENG, recVU0unknown , recVU0MI_WAITP, recVU0unknown, +}; + +void (*recVU0LowerOP_OPCODE[64])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_IADD , recVU0MI_ISUB , recVU0MI_IADDI, recVU0unknown, /* 0x30 */ + recVU0MI_IAND , recVU0MI_IOR , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP_T3_00, recVU0LowerOP_T3_01, recVU0LowerOP_T3_10, recVU0LowerOP_T3_11, +}; + +void (*recVU0_UPPER_OPCODE[64])() = { + recVU0MI_ADDx , recVU0MI_ADDy , recVU0MI_ADDz , recVU0MI_ADDw, + recVU0MI_SUBx , recVU0MI_SUBy , recVU0MI_SUBz , recVU0MI_SUBw, + recVU0MI_MADDx , recVU0MI_MADDy , recVU0MI_MADDz , recVU0MI_MADDw, + recVU0MI_MSUBx , recVU0MI_MSUBy , recVU0MI_MSUBz , recVU0MI_MSUBw, + recVU0MI_MAXx , recVU0MI_MAXy , recVU0MI_MAXz , recVU0MI_MAXw, /* 0x10 */ + recVU0MI_MINIx , recVU0MI_MINIy , recVU0MI_MINIz , recVU0MI_MINIw, + recVU0MI_MULx , recVU0MI_MULy , recVU0MI_MULz , recVU0MI_MULw, + recVU0MI_MULq , recVU0MI_MAXi , recVU0MI_MULi , recVU0MI_MINIi, + recVU0MI_ADDq , recVU0MI_MADDq , recVU0MI_ADDi , recVU0MI_MADDi, /* 0x20 */ + recVU0MI_SUBq , recVU0MI_MSUBq , recVU0MI_SUBi , recVU0MI_MSUBi, + recVU0MI_ADD , recVU0MI_MADD , recVU0MI_MUL , recVU0MI_MAX, + recVU0MI_SUB , recVU0MI_MSUB , recVU0MI_OPMSUB, recVU0MI_MINI, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0_UPPER_FD_00, recVU0_UPPER_FD_01, recVU0_UPPER_FD_10, recVU0_UPPER_FD_11, +}; + +void (*recVU0_UPPER_FD_00_TABLE[32])() = { + recVU0MI_ADDAx, recVU0MI_SUBAx , recVU0MI_MADDAx, recVU0MI_MSUBAx, + recVU0MI_ITOF0, recVU0MI_FTOI0, recVU0MI_MULAx , recVU0MI_MULAq , + recVU0MI_ADDAq, recVU0MI_SUBAq, recVU0MI_ADDA , recVU0MI_SUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_01_TABLE[32])() = { + recVU0MI_ADDAy , recVU0MI_SUBAy , recVU0MI_MADDAy, recVU0MI_MSUBAy, + recVU0MI_ITOF4 , recVU0MI_FTOI4 , recVU0MI_MULAy , recVU0MI_ABS , + recVU0MI_MADDAq, recVU0MI_MSUBAq, recVU0MI_MADDA , recVU0MI_MSUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_10_TABLE[32])() = { + recVU0MI_ADDAz , recVU0MI_SUBAz , recVU0MI_MADDAz, recVU0MI_MSUBAz, + recVU0MI_ITOF12, recVU0MI_FTOI12, recVU0MI_MULAz , recVU0MI_MULAi , + recVU0MI_MADDAi, recVU0MI_SUBAi , recVU0MI_MULA , recVU0MI_OPMULA, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_11_TABLE[32])() = { + recVU0MI_ADDAw , recVU0MI_SUBAw , recVU0MI_MADDAw, recVU0MI_MSUBAw, + recVU0MI_ITOF15, recVU0MI_FTOI15, recVU0MI_MULAw , recVU0MI_CLIP , + recVU0MI_MADDAi, recVU0MI_MSUBAi, recVU0unknown , recVU0MI_NOP , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void recVU0_UPPER_FD_00( void ) +{ + recVU0_UPPER_FD_00_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_01( void ) +{ + recVU0_UPPER_FD_01_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_10( void ) +{ + recVU0_UPPER_FD_10_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_11( void ) +{ + recVU0_UPPER_FD_11_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP( void ) +{ + recVU0LowerOP_OPCODE[ VU0.code & 0x3f ]( ); +} + +void recVU0LowerOP_T3_00( void ) +{ + recVU0LowerOP_T3_00_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_01( void ) +{ + recVU0LowerOP_T3_01_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_10( void ) +{ + recVU0LowerOP_T3_10_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_11( void ) +{ + recVU0LowerOP_T3_11_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + + +void recVU0unknown( void ) +{ +#ifdef CPU_LOG + CPU_LOG("Unknown VU0 micromode opcode calledn"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +#ifdef RECOMPILE_VUMI_ABS +void recVU0MI_ABS() { recVUMI_ABS(VU, VUREC_INFO); } +#else +void recVU0MI_ABS() { REC_VUOP(VU0, ABS); } +#endif + +#ifdef RECOMPILE_VUMI_ADD +void recVU0MI_ADD() { recVUMI_ADD(VU, VUREC_INFO); } +void recVU0MI_ADDi() { recVUMI_ADDi(VU, VUREC_INFO); } +void recVU0MI_ADDq() { recVUMI_ADDq(VU, VUREC_INFO); } +void recVU0MI_ADDx() { recVUMI_ADDx(VU, VUREC_INFO); } +void recVU0MI_ADDy() { recVUMI_ADDy(VU, VUREC_INFO); } +void recVU0MI_ADDz() { recVUMI_ADDz(VU, VUREC_INFO); } +void recVU0MI_ADDw() { recVUMI_ADDw(VU, VUREC_INFO); } +#else +void recVU0MI_ADD() { REC_VUOP(VU0, ADD); } +void recVU0MI_ADDi() { REC_VUOP(VU0, ADDi); } +void recVU0MI_ADDq() { REC_VUOP(VU0, ADDq); } +void recVU0MI_ADDx() { REC_VUOP(VU0, ADDx); } +void recVU0MI_ADDy() { REC_VUOP(VU0, ADDy); } +void recVU0MI_ADDz() { REC_VUOP(VU0, ADDz); } +void recVU0MI_ADDw() { REC_VUOP(VU0, ADDw); } +#endif + +#ifdef RECOMPILE_VUMI_ADDA +void recVU0MI_ADDA() { recVUMI_ADDA(VU, VUREC_INFO); } +void recVU0MI_ADDAi() { recVUMI_ADDAi(VU, VUREC_INFO); } +void recVU0MI_ADDAq() { recVUMI_ADDAq(VU, VUREC_INFO); } +void recVU0MI_ADDAx() { recVUMI_ADDAx(VU, VUREC_INFO); } +void recVU0MI_ADDAy() { recVUMI_ADDAy(VU, VUREC_INFO); } +void recVU0MI_ADDAz() { recVUMI_ADDAz(VU, VUREC_INFO); } +void recVU0MI_ADDAw() { recVUMI_ADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_ADDA() { REC_VUOP(VU0, ADDA); } +void recVU0MI_ADDAi() { REC_VUOP(VU0, ADDAi); } +void recVU0MI_ADDAq() { REC_VUOP(VU0, ADDAq); } +void recVU0MI_ADDAx() { REC_VUOP(VU0, ADDAx); } +void recVU0MI_ADDAy() { REC_VUOP(VU0, ADDAy); } +void recVU0MI_ADDAz() { REC_VUOP(VU0, ADDAz); } +void recVU0MI_ADDAw() { REC_VUOP(VU0, ADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_SUB +void recVU0MI_SUB() { recVUMI_SUB(VU, VUREC_INFO); } +void recVU0MI_SUBi() { recVUMI_SUBi(VU, VUREC_INFO); } +void recVU0MI_SUBq() { recVUMI_SUBq(VU, VUREC_INFO); } +void recVU0MI_SUBx() { recVUMI_SUBx(VU, VUREC_INFO); } +void recVU0MI_SUBy() { recVUMI_SUBy(VU, VUREC_INFO); } +void recVU0MI_SUBz() { recVUMI_SUBz(VU, VUREC_INFO); } +void recVU0MI_SUBw() { recVUMI_SUBw(VU, VUREC_INFO); } +#else +void recVU0MI_SUB() { REC_VUOP(VU0, SUB); } +void recVU0MI_SUBi() { REC_VUOP(VU0, SUBi); } +void recVU0MI_SUBq() { REC_VUOP(VU0, SUBq); } +void recVU0MI_SUBx() { REC_VUOP(VU0, SUBx); } +void recVU0MI_SUBy() { REC_VUOP(VU0, SUBy); } +void recVU0MI_SUBz() { REC_VUOP(VU0, SUBz); } +void recVU0MI_SUBw() { REC_VUOP(VU0, SUBw); } +#endif + +#ifdef RECOMPILE_VUMI_SUBA +void recVU0MI_SUBA() { recVUMI_SUBA(VU, VUREC_INFO); } +void recVU0MI_SUBAi() { recVUMI_SUBAi(VU, VUREC_INFO); } +void recVU0MI_SUBAq() { recVUMI_SUBAq(VU, VUREC_INFO); } +void recVU0MI_SUBAx() { recVUMI_SUBAx(VU, VUREC_INFO); } +void recVU0MI_SUBAy() { recVUMI_SUBAy(VU, VUREC_INFO); } +void recVU0MI_SUBAz() { recVUMI_SUBAz(VU, VUREC_INFO); } +void recVU0MI_SUBAw() { recVUMI_SUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_SUBA() { REC_VUOP(VU0, SUBA); } +void recVU0MI_SUBAi() { REC_VUOP(VU0, SUBAi); } +void recVU0MI_SUBAq() { REC_VUOP(VU0, SUBAq); } +void recVU0MI_SUBAx() { REC_VUOP(VU0, SUBAx); } +void recVU0MI_SUBAy() { REC_VUOP(VU0, SUBAy); } +void recVU0MI_SUBAz() { REC_VUOP(VU0, SUBAz); } +void recVU0MI_SUBAw() { REC_VUOP(VU0, SUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MUL +void recVU0MI_MUL() { recVUMI_MUL(VU, VUREC_INFO); } +void recVU0MI_MULi() { recVUMI_MULi(VU, VUREC_INFO); } +void recVU0MI_MULq() { recVUMI_MULq(VU, VUREC_INFO); } +void recVU0MI_MULx() { recVUMI_MULx(VU, VUREC_INFO); } +void recVU0MI_MULy() { recVUMI_MULy(VU, VUREC_INFO); } +void recVU0MI_MULz() { recVUMI_MULz(VU, VUREC_INFO); } +void recVU0MI_MULw() { recVUMI_MULw(VU, VUREC_INFO); } +#else +void recVU0MI_MUL() { REC_VUOP(VU0, MUL); } +void recVU0MI_MULi() { REC_VUOP(VU0, MULi); } +void recVU0MI_MULq() { REC_VUOP(VU0, MULq); } +void recVU0MI_MULx() { REC_VUOP(VU0, MULx); } +void recVU0MI_MULy() { REC_VUOP(VU0, MULy); } +void recVU0MI_MULz() { REC_VUOP(VU0, MULz); } +void recVU0MI_MULw() { REC_VUOP(VU0, MULw); } +#endif + +#ifdef RECOMPILE_VUMI_MULA +void recVU0MI_MULA() { recVUMI_MULA(VU, VUREC_INFO); } +void recVU0MI_MULAi() { recVUMI_MULAi(VU, VUREC_INFO); } +void recVU0MI_MULAq() { recVUMI_MULAq(VU, VUREC_INFO); } +void recVU0MI_MULAx() { recVUMI_MULAx(VU, VUREC_INFO); } +void recVU0MI_MULAy() { recVUMI_MULAy(VU, VUREC_INFO); } +void recVU0MI_MULAz() { recVUMI_MULAz(VU, VUREC_INFO); } +void recVU0MI_MULAw() { recVUMI_MULAw(VU, VUREC_INFO); } +#else +void recVU0MI_MULA() { REC_VUOP(VU0, MULA); } +void recVU0MI_MULAi() { REC_VUOP(VU0, MULAi); } +void recVU0MI_MULAq() { REC_VUOP(VU0, MULAq); } +void recVU0MI_MULAx() { REC_VUOP(VU0, MULAx); } +void recVU0MI_MULAy() { REC_VUOP(VU0, MULAy); } +void recVU0MI_MULAz() { REC_VUOP(VU0, MULAz); } +void recVU0MI_MULAw() { REC_VUOP(VU0, MULAw); } +#endif + +#ifdef RECOMPILE_VUMI_MADD +void recVU0MI_MADD() { recVUMI_MADD(VU, VUREC_INFO); } +void recVU0MI_MADDi() { recVUMI_MADDi(VU, VUREC_INFO); } +void recVU0MI_MADDq() { recVUMI_MADDq(VU, VUREC_INFO); } +void recVU0MI_MADDx() { recVUMI_MADDx(VU, VUREC_INFO); } +void recVU0MI_MADDy() { recVUMI_MADDy(VU, VUREC_INFO); } +void recVU0MI_MADDz() { recVUMI_MADDz(VU, VUREC_INFO); } +void recVU0MI_MADDw() { recVUMI_MADDw(VU, VUREC_INFO); } +#else +void recVU0MI_MADD() { REC_VUOP(VU0, MADD); } +void recVU0MI_MADDi() { REC_VUOP(VU0, MADDi); } +void recVU0MI_MADDq() { REC_VUOP(VU0, MADDq); } +void recVU0MI_MADDx() { REC_VUOP(VU0, MADDx); } +void recVU0MI_MADDy() { REC_VUOP(VU0, MADDy); } +void recVU0MI_MADDz() { REC_VUOP(VU0, MADDz); } +void recVU0MI_MADDw() { REC_VUOP(VU0, MADDw); } +#endif + +#ifdef RECOMPILE_VUMI_MADDA +void recVU0MI_MADDA() { recVUMI_MADDA(VU, VUREC_INFO); } +void recVU0MI_MADDAi() { recVUMI_MADDAi(VU, VUREC_INFO); } +void recVU0MI_MADDAq() { recVUMI_MADDAq(VU, VUREC_INFO); } +void recVU0MI_MADDAx() { recVUMI_MADDAx(VU, VUREC_INFO); } +void recVU0MI_MADDAy() { recVUMI_MADDAy(VU, VUREC_INFO); } +void recVU0MI_MADDAz() { recVUMI_MADDAz(VU, VUREC_INFO); } +void recVU0MI_MADDAw() { recVUMI_MADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_MADDA() { REC_VUOP(VU0, MADDA); } +void recVU0MI_MADDAi() { REC_VUOP(VU0, MADDAi); } +void recVU0MI_MADDAq() { REC_VUOP(VU0, MADDAq); } +void recVU0MI_MADDAx() { REC_VUOP(VU0, MADDAx); } +void recVU0MI_MADDAy() { REC_VUOP(VU0, MADDAy); } +void recVU0MI_MADDAz() { REC_VUOP(VU0, MADDAz); } +void recVU0MI_MADDAw() { REC_VUOP(VU0, MADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUB +void recVU0MI_MSUB() { recVUMI_MSUB(VU, VUREC_INFO); } +void recVU0MI_MSUBi() { recVUMI_MSUBi(VU, VUREC_INFO); } +void recVU0MI_MSUBq() { recVUMI_MSUBq(VU, VUREC_INFO); } +void recVU0MI_MSUBx() { recVUMI_MSUBx(VU, VUREC_INFO); } +void recVU0MI_MSUBy() { recVUMI_MSUBy(VU, VUREC_INFO); } +void recVU0MI_MSUBz() { recVUMI_MSUBz(VU, VUREC_INFO); } +void recVU0MI_MSUBw() { recVUMI_MSUBw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUB() { REC_VUOP(VU0, MSUB); } +void recVU0MI_MSUBi() { REC_VUOP(VU0, MSUBi); } +void recVU0MI_MSUBq() { REC_VUOP(VU0, MSUBq); } +void recVU0MI_MSUBx() { REC_VUOP(VU0, MSUBx); } +void recVU0MI_MSUBy() { REC_VUOP(VU0, MSUBy); } +void recVU0MI_MSUBz() { REC_VUOP(VU0, MSUBz); } +void recVU0MI_MSUBw() { REC_VUOP(VU0, MSUBw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUBA +void recVU0MI_MSUBA() { recVUMI_MSUBA(VU, VUREC_INFO); } +void recVU0MI_MSUBAi() { recVUMI_MSUBAi(VU, VUREC_INFO); } +void recVU0MI_MSUBAq() { recVUMI_MSUBAq(VU, VUREC_INFO); } +void recVU0MI_MSUBAx() { recVUMI_MSUBAx(VU, VUREC_INFO); } +void recVU0MI_MSUBAy() { recVUMI_MSUBAy(VU, VUREC_INFO); } +void recVU0MI_MSUBAz() { recVUMI_MSUBAz(VU, VUREC_INFO); } +void recVU0MI_MSUBAw() { recVUMI_MSUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUBA() { REC_VUOP(VU0, MSUBA); } +void recVU0MI_MSUBAi() { REC_VUOP(VU0, MSUBAi); } +void recVU0MI_MSUBAq() { REC_VUOP(VU0, MSUBAq); } +void recVU0MI_MSUBAx() { REC_VUOP(VU0, MSUBAx); } +void recVU0MI_MSUBAy() { REC_VUOP(VU0, MSUBAy); } +void recVU0MI_MSUBAz() { REC_VUOP(VU0, MSUBAz); } +void recVU0MI_MSUBAw() { REC_VUOP(VU0, MSUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MAX +void recVU0MI_MAX() { recVUMI_MAX(VU, VUREC_INFO); } +void recVU0MI_MAXi() { recVUMI_MAXi(VU, VUREC_INFO); } +void recVU0MI_MAXx() { recVUMI_MAXx(VU, VUREC_INFO); } +void recVU0MI_MAXy() { recVUMI_MAXy(VU, VUREC_INFO); } +void recVU0MI_MAXz() { recVUMI_MAXz(VU, VUREC_INFO); } +void recVU0MI_MAXw() { recVUMI_MAXw(VU, VUREC_INFO); } +#else +void recVU0MI_MAX() { REC_VUOP(VU0, MAX); } +void recVU0MI_MAXi() { REC_VUOP(VU0, MAXi); } +void recVU0MI_MAXx() { REC_VUOP(VU0, MAXx); } +void recVU0MI_MAXy() { REC_VUOP(VU0, MAXy); } +void recVU0MI_MAXz() { REC_VUOP(VU0, MAXz); } +void recVU0MI_MAXw() { REC_VUOP(VU0, MAXw); } +#endif + +#ifdef RECOMPILE_VUMI_MINI +void recVU0MI_MINI() { recVUMI_MINI(VU, VUREC_INFO); } +void recVU0MI_MINIi() { recVUMI_MINIi(VU, VUREC_INFO); } +void recVU0MI_MINIx() { recVUMI_MINIx(VU, VUREC_INFO); } +void recVU0MI_MINIy() { recVUMI_MINIy(VU, VUREC_INFO); } +void recVU0MI_MINIz() { recVUMI_MINIz(VU, VUREC_INFO); } +void recVU0MI_MINIw() { recVUMI_MINIw(VU, VUREC_INFO); } +#else +void recVU0MI_MINI() { REC_VUOP(VU0, MINI); } +void recVU0MI_MINIi() { REC_VUOP(VU0, MINIi); } +void recVU0MI_MINIx() { REC_VUOP(VU0, MINIx); } +void recVU0MI_MINIy() { REC_VUOP(VU0, MINIy); } +void recVU0MI_MINIz() { REC_VUOP(VU0, MINIz); } +void recVU0MI_MINIw() { REC_VUOP(VU0, MINIw); } +#endif + +#ifdef RECOMPILE_VUMI_FTOI +void recVU0MI_FTOI0() { recVUMI_FTOI0(VU, VUREC_INFO); } +void recVU0MI_FTOI4() { recVUMI_FTOI4(VU, VUREC_INFO); } +void recVU0MI_FTOI12() { recVUMI_FTOI12(VU, VUREC_INFO); } +void recVU0MI_FTOI15() { recVUMI_FTOI15(VU, VUREC_INFO); } +void recVU0MI_ITOF0() { recVUMI_ITOF0(VU, VUREC_INFO); } +void recVU0MI_ITOF4() { recVUMI_ITOF4(VU, VUREC_INFO); } +void recVU0MI_ITOF12() { recVUMI_ITOF12(VU, VUREC_INFO); } +void recVU0MI_ITOF15() { recVUMI_ITOF15(VU, VUREC_INFO); } +#else +void recVU0MI_FTOI0() { REC_VUOP(VU0, FTOI0); } +void recVU0MI_FTOI4() { REC_VUOP(VU0, FTOI4); } +void recVU0MI_FTOI12() { REC_VUOP(VU0, FTOI12); } +void recVU0MI_FTOI15() { REC_VUOP(VU0, FTOI15); } +void recVU0MI_ITOF0() { REC_VUOP(VU0, ITOF0); } +void recVU0MI_ITOF4() { REC_VUOP(VU0, ITOF4); } +void recVU0MI_ITOF12() { REC_VUOP(VU0, ITOF12); } +void recVU0MI_ITOF15() { REC_VUOP(VU0, ITOF15); } +#endif + +void recVU0MI_OPMULA() { recVUMI_OPMULA(VU, VUREC_INFO); } +void recVU0MI_OPMSUB() { recVUMI_OPMSUB(VU, VUREC_INFO); } +void recVU0MI_NOP() { } +void recVU0MI_CLIP() { recVUMI_CLIP(VU, VUREC_INFO); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +#ifdef RECOMPILE_VUMI_MISC + +void recVU0MI_MTIR() { recVUMI_MTIR(VU, VUREC_INFO); } +void recVU0MI_MR32() { recVUMI_MR32(VU, VUREC_INFO); } +void recVU0MI_MFIR() { recVUMI_MFIR(VU, VUREC_INFO); } +void recVU0MI_MOVE() { recVUMI_MOVE(VU, VUREC_INFO); } +void recVU0MI_WAITQ() { recVUMI_WAITQ(VU, VUREC_INFO); } +void recVU0MI_MFP() { recVUMI_MFP(VU, VUREC_INFO); } +void recVU0MI_WAITP() { SysPrintf("vu0 wait p?\n"); } + +#else + +void recVU0MI_MOVE() { REC_VUOP(VU0, MOVE); } +void recVU0MI_MFIR() { REC_VUOP(VU0, MFIR); } +void recVU0MI_MTIR() { REC_VUOP(VU0, MTIR); } +void recVU0MI_MR32() { REC_VUOP(VU0, MR32); } +void recVU0MI_WAITQ() { } +void recVU0MI_MFP() { REC_VUOP(VU0, MFP); } +void recVU0MI_WAITP() { REC_VUOP(VU0, WAITP); } + +#endif + +#ifdef RECOMPILE_VUMI_MATH + +void recVU0MI_SQRT() { recVUMI_SQRT(VU, VUREC_INFO); } +void recVU0MI_RSQRT() { recVUMI_RSQRT(VU, VUREC_INFO); } +void recVU0MI_DIV() { recVUMI_DIV(VU, VUREC_INFO); } + +#else + +void recVU0MI_DIV() { REC_VUOP(VU0, DIV);} +void recVU0MI_SQRT() { REC_VUOP(VU0, SQRT); } +void recVU0MI_RSQRT() { REC_VUOP(VU0, RSQRT); } + +#endif + +#ifdef RECOMPILE_VUMI_E + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { recVUMI_ELENG(VU, VUREC_INFO); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#else + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { REC_VUOP(VU0, ELENG); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#endif + +#ifdef RECOMPILE_VUMI_X + +void recVU0MI_XITOP() { recVUMI_XITOP(VU, VUREC_INFO); } +void recVU0MI_XGKICK() { recVUMI_XGKICK(VU, VUREC_INFO); } +void recVU0MI_XTOP() { recVUMI_XTOP(VU, VUREC_INFO); } + +#else + +void recVU0MI_XITOP() { REC_VUOP(VU0, XITOP); } +void recVU0MI_XGKICK() { REC_VUOP(VU0, XGKICK);} +void recVU0MI_XTOP() { REC_VUOP(VU0, XTOP);} + +#endif + +#ifdef RECOMPILE_VUMI_RANDOM + +void recVU0MI_RINIT() { recVUMI_RINIT(VU, VUREC_INFO); } +void recVU0MI_RGET() { recVUMI_RGET(VU, VUREC_INFO); } +void recVU0MI_RNEXT() { recVUMI_RNEXT(VU, VUREC_INFO); } +void recVU0MI_RXOR() { recVUMI_RXOR(VU, VUREC_INFO); } + +#else + +void recVU0MI_RINIT() { REC_VUOP(VU0, RINIT); } +void recVU0MI_RGET() { REC_VUOP(VU0, RGET); } +void recVU0MI_RNEXT() { REC_VUOP(VU0, RNEXT); } +void recVU0MI_RXOR() { REC_VUOP(VU0, RXOR); } + +#endif + +#ifdef RECOMPILE_VUMI_FLAG + +void recVU0MI_FSAND() { recVUMI_FSAND(VU, VUREC_INFO); } +void recVU0MI_FSEQ() { recVUMI_FSEQ(VU, VUREC_INFO); } +void recVU0MI_FSOR() { recVUMI_FSOR(VU, VUREC_INFO); } +void recVU0MI_FSSET() { recVUMI_FSSET(VU, VUREC_INFO); } +void recVU0MI_FMEQ() { recVUMI_FMEQ(VU, VUREC_INFO); } +void recVU0MI_FMOR() { recVUMI_FMOR(VU, VUREC_INFO); } +void recVU0MI_FCEQ() { recVUMI_FCEQ(VU, VUREC_INFO); } +void recVU0MI_FCOR() { recVUMI_FCOR(VU, VUREC_INFO); } +void recVU0MI_FCSET() { recVUMI_FCSET(VU, VUREC_INFO); } +void recVU0MI_FCGET() { recVUMI_FCGET(VU, VUREC_INFO); } +void recVU0MI_FCAND() { recVUMI_FCAND(VU, VUREC_INFO); } +void recVU0MI_FMAND() { recVUMI_FMAND(VU, VUREC_INFO); } + +#else + +void recVU0MI_FSAND() { REC_VUOP(VU0, FSAND); } +void recVU0MI_FSEQ() { REC_VUOP(VU0, FSEQ); } +void recVU0MI_FSOR() { REC_VUOP(VU0, FSOR); } +void recVU0MI_FSSET() { REC_VUOP(VU0, FSSET); } +void recVU0MI_FMAND() { REC_VUOP(VU0, FMAND); } +void recVU0MI_FMEQ() { REC_VUOP(VU0, FMEQ); } +void recVU0MI_FMOR() { REC_VUOP(VU0, FMOR); } +void recVU0MI_FCAND() { REC_VUOP(VU0, FCAND); } +void recVU0MI_FCEQ() { REC_VUOP(VU0, FCEQ); } +void recVU0MI_FCOR() { REC_VUOP(VU0, FCOR); } +void recVU0MI_FCSET() { REC_VUOP(VU0, FCSET); } +void recVU0MI_FCGET() { REC_VUOP(VU0, FCGET); } + +#endif + +#ifdef RECOMPILE_VUMI_LOADSTORE + +void recVU0MI_LQ() { recVUMI_LQ(VU, VUREC_INFO); } +void recVU0MI_LQD() { recVUMI_LQD(VU, VUREC_INFO); } +void recVU0MI_LQI() { recVUMI_LQI(VU, VUREC_INFO); } +void recVU0MI_SQ() { recVUMI_SQ(VU, VUREC_INFO); } +void recVU0MI_SQD() { recVUMI_SQD(VU, VUREC_INFO); } +void recVU0MI_SQI() { recVUMI_SQI(VU, VUREC_INFO); } +void recVU0MI_ILW() { recVUMI_ILW(VU, VUREC_INFO); } +void recVU0MI_ISW() { recVUMI_ISW(VU, VUREC_INFO); } +void recVU0MI_ILWR() { recVUMI_ILWR(VU, VUREC_INFO); } +void recVU0MI_ISWR() { recVUMI_ISWR(VU, VUREC_INFO); } + +#else + +void recVU0MI_LQ() { REC_VUOP(VU0, LQ); } +void recVU0MI_LQD() { REC_VUOP(VU0, LQD); } +void recVU0MI_LQI() { REC_VUOP(VU0, LQI); } +void recVU0MI_SQ() { REC_VUOP(VU0, SQ); } +void recVU0MI_SQD() { REC_VUOP(VU0, SQD); } +void recVU0MI_SQI() { REC_VUOP(VU0, SQI); } +void recVU0MI_ILW() { REC_VUOP(VU0, ILW); } +void recVU0MI_ISW() { REC_VUOP(VU0, ISW); } +void recVU0MI_ILWR() { REC_VUOP(VU0, ILWR); } +void recVU0MI_ISWR() { REC_VUOP(VU0, ISWR); } + +#endif + +#ifdef RECOMPILE_VUMI_ARITHMETIC + +void recVU0MI_IADD() { recVUMI_IADD(VU, VUREC_INFO); } +void recVU0MI_IADDI() { recVUMI_IADDI(VU, VUREC_INFO); } +void recVU0MI_IADDIU() { recVUMI_IADDIU(VU, VUREC_INFO); } +void recVU0MI_IOR() { recVUMI_IOR(VU, VUREC_INFO); } +void recVU0MI_ISUB() { recVUMI_ISUB(VU, VUREC_INFO); } +void recVU0MI_IAND() { recVUMI_IAND(VU, VUREC_INFO); } +void recVU0MI_ISUBIU() { recVUMI_ISUBIU(VU, VUREC_INFO); } + +#else + +void recVU0MI_IADD() { REC_VUOP(VU0, IADD); } +void recVU0MI_IADDI() { REC_VUOP(VU0, IADDI); } +void recVU0MI_IADDIU() { REC_VUOP(VU0, IADDIU); } +void recVU0MI_IOR() { REC_VUOP(VU0, IOR); } +void recVU0MI_ISUB() { REC_VUOP(VU0, ISUB); } +void recVU0MI_IAND() { REC_VUOP(VU0, IAND); } +void recVU0MI_ISUBIU() { REC_VUOP(VU0, ISUBIU); } + +#endif + +#ifdef RECOMPILE_VUMI_BRANCH + +void recVU0MI_IBEQ() { recVUMI_IBEQ(VU, VUREC_INFO); } +void recVU0MI_IBGEZ() { recVUMI_IBGEZ(VU, VUREC_INFO); } +void recVU0MI_IBLTZ() { recVUMI_IBLTZ(VU, VUREC_INFO); } +void recVU0MI_IBLEZ() { recVUMI_IBLEZ(VU, VUREC_INFO); } +void recVU0MI_IBGTZ() { recVUMI_IBGTZ(VU, VUREC_INFO); } +void recVU0MI_IBNE() { recVUMI_IBNE(VU, VUREC_INFO); } +void recVU0MI_B() { recVUMI_B(VU, VUREC_INFO); } +void recVU0MI_BAL() { recVUMI_BAL(VU, VUREC_INFO); } +void recVU0MI_JR() { recVUMI_JR(VU, VUREC_INFO); } +void recVU0MI_JALR() { recVUMI_JALR(VU, VUREC_INFO); } + +#else + +void recVU0MI_IBEQ() { REC_VUOP(VU0, IBEQ); } +void recVU0MI_IBGEZ() { REC_VUOP(VU0, IBGEZ); } +void recVU0MI_IBGTZ() { REC_VUOP(VU0, IBGTZ); } +void recVU0MI_IBLTZ() { REC_VUOP(VU0, IBLTZ); } +void recVU0MI_IBLEZ() { REC_VUOP(VU0, IBLEZ); } +void recVU0MI_IBNE() { REC_VUOP(VU0, IBNE); } +void recVU0MI_B() { REC_VUOP(VU0, B); } +void recVU0MI_BAL() { REC_VUOP(VU0, BAL); } +void recVU0MI_JR() { REC_VUOP(VU0, JR); } +void recVU0MI_JALR() { REC_VUOP(VU0, JALR); } + +#endif + diff --git a/branches/pcsx2_0.9.1/x86/iVU0micro.h b/branches/pcsx2_0.9.1/x86/iVU0micro.h new file mode 100644 index 0000000..b5c08c5 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVU0micro.h @@ -0,0 +1,221 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU0MICRO_H__ +#define __IVU0MICRO_H__ + +void recResetVU0(); +void recExecuteVU0Block( void ); +void recClearVU0( u32 Addr, u32 Size ); + +extern void (*recVU0_LOWER_OPCODE[128])(); +extern void (*recVU0_UPPER_OPCODE[64])(); + +extern void (*recVU0_UPPER_FD_00_TABLE[32])(); +extern void (*recVU0_UPPER_FD_01_TABLE[32])(); +extern void (*recVU0_UPPER_FD_10_TABLE[32])(); +extern void (*recVU0_UPPER_FD_11_TABLE[32])(); + +void recVU0_UPPER_FD_00(); +void recVU0_UPPER_FD_01(); +void recVU0_UPPER_FD_10(); +void recVU0_UPPER_FD_11(); + +void recVU0LowerOP(); +void recVU0LowerOP_T3_00(); +void recVU0LowerOP_T3_01(); +void recVU0LowerOP_T3_10(); +void recVU0LowerOP_T3_11(); + +void recVU0unknown(); + + + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void recVU0MI_ABS(); +void recVU0MI_ADD(); +void recVU0MI_ADDi(); +void recVU0MI_ADDq(); +void recVU0MI_ADDx(); +void recVU0MI_ADDy(); +void recVU0MI_ADDz(); +void recVU0MI_ADDw(); +void recVU0MI_ADDA(); +void recVU0MI_ADDAi(); +void recVU0MI_ADDAq(); +void recVU0MI_ADDAx(); +void recVU0MI_ADDAy(); +void recVU0MI_ADDAz(); +void recVU0MI_ADDAw(); +void recVU0MI_SUB(); +void recVU0MI_SUBi(); +void recVU0MI_SUBq(); +void recVU0MI_SUBx(); +void recVU0MI_SUBy(); +void recVU0MI_SUBz(); +void recVU0MI_SUBw(); +void recVU0MI_SUBA(); +void recVU0MI_SUBAi(); +void recVU0MI_SUBAq(); +void recVU0MI_SUBAx(); +void recVU0MI_SUBAy(); +void recVU0MI_SUBAz(); +void recVU0MI_SUBAw(); +void recVU0MI_MUL(); +void recVU0MI_MULi(); +void recVU0MI_MULq(); +void recVU0MI_MULx(); +void recVU0MI_MULy(); +void recVU0MI_MULz(); +void recVU0MI_MULw(); +void recVU0MI_MULA(); +void recVU0MI_MULAi(); +void recVU0MI_MULAq(); +void recVU0MI_MULAx(); +void recVU0MI_MULAy(); +void recVU0MI_MULAz(); +void recVU0MI_MULAw(); +void recVU0MI_MADD(); +void recVU0MI_MADDi(); +void recVU0MI_MADDq(); +void recVU0MI_MADDx(); +void recVU0MI_MADDy(); +void recVU0MI_MADDz(); +void recVU0MI_MADDw(); +void recVU0MI_MADDA(); +void recVU0MI_MADDAi(); +void recVU0MI_MADDAq(); +void recVU0MI_MADDAx(); +void recVU0MI_MADDAy(); +void recVU0MI_MADDAz(); +void recVU0MI_MADDAw(); +void recVU0MI_MSUB(); +void recVU0MI_MSUBi(); +void recVU0MI_MSUBq(); +void recVU0MI_MSUBx(); +void recVU0MI_MSUBy(); +void recVU0MI_MSUBz(); +void recVU0MI_MSUBw(); +void recVU0MI_MSUBA(); +void recVU0MI_MSUBAi(); +void recVU0MI_MSUBAq(); +void recVU0MI_MSUBAx(); +void recVU0MI_MSUBAy(); +void recVU0MI_MSUBAz(); +void recVU0MI_MSUBAw(); +void recVU0MI_MAX(); +void recVU0MI_MAXi(); +void recVU0MI_MAXx(); +void recVU0MI_MAXy(); +void recVU0MI_MAXz(); +void recVU0MI_MAXw(); +void recVU0MI_MINI(); +void recVU0MI_MINIi(); +void recVU0MI_MINIx(); +void recVU0MI_MINIy(); +void recVU0MI_MINIz(); +void recVU0MI_MINIw(); +void recVU0MI_OPMULA(); +void recVU0MI_OPMSUB(); +void recVU0MI_NOP(); +void recVU0MI_FTOI0(); +void recVU0MI_FTOI4(); +void recVU0MI_FTOI12(); +void recVU0MI_FTOI15(); +void recVU0MI_ITOF0(); +void recVU0MI_ITOF4(); +void recVU0MI_ITOF12(); +void recVU0MI_ITOF15(); +void recVU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void recVU0MI_DIV(); +void recVU0MI_SQRT(); +void recVU0MI_RSQRT(); +void recVU0MI_IADD(); +void recVU0MI_IADDI(); +void recVU0MI_IADDIU(); +void recVU0MI_IAND(); +void recVU0MI_IOR(); +void recVU0MI_ISUB(); +void recVU0MI_ISUBIU(); +void recVU0MI_MOVE(); +void recVU0MI_MFIR(); +void recVU0MI_MTIR(); +void recVU0MI_MR32(); +void recVU0MI_LQ(); +void recVU0MI_LQD(); +void recVU0MI_LQI(); +void recVU0MI_SQ(); +void recVU0MI_SQD(); +void recVU0MI_SQI(); +void recVU0MI_ILW(); +void recVU0MI_ISW(); +void recVU0MI_ILWR(); +void recVU0MI_ISWR(); +void recVU0MI_RINIT(); +void recVU0MI_RGET(); +void recVU0MI_RNEXT(); +void recVU0MI_RXOR(); +void recVU0MI_WAITQ(); +void recVU0MI_FSAND(); +void recVU0MI_FSEQ(); +void recVU0MI_FSOR(); +void recVU0MI_FSSET(); +void recVU0MI_FMAND(); +void recVU0MI_FMEQ(); +void recVU0MI_FMOR(); +void recVU0MI_FCAND(); +void recVU0MI_FCEQ(); +void recVU0MI_FCOR(); +void recVU0MI_FCSET(); +void recVU0MI_FCGET(); +void recVU0MI_IBEQ(); +void recVU0MI_IBGEZ(); +void recVU0MI_IBGTZ(); +void recVU0MI_IBLEZ(); +void recVU0MI_IBLTZ(); +void recVU0MI_IBNE(); +void recVU0MI_B(); +void recVU0MI_BAL(); +void recVU0MI_JR(); +void recVU0MI_JALR(); +void recVU0MI_MFP(); +void recVU0MI_WAITP(); +void recVU0MI_ESADD(); +void recVU0MI_ERSADD(); +void recVU0MI_ELENG(); +void recVU0MI_ERLENG(); +void recVU0MI_EATANxy(); +void recVU0MI_EATANxz(); +void recVU0MI_ESUM(); +void recVU0MI_ERCPR(); +void recVU0MI_ESQRT(); +void recVU0MI_ERSQRT(); +void recVU0MI_ESIN(); +void recVU0MI_EATAN(); +void recVU0MI_EEXP(); +void recVU0MI_XITOP(); + +#endif /* __IVU0MICRO_H__ */ diff --git a/branches/pcsx2_0.9.1/x86/iVU1micro.c b/branches/pcsx2_0.9.1/x86/iVU1micro.c new file mode 100644 index 0000000..27d23f9 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVU1micro.c @@ -0,0 +1,201 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VU.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// TODO: there's a bug in spyro start menu where release vurec works but debug vurec breaks + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +#define VU ((VURegs*)&VU1) + +u32 vu1recpcold = -1; +u32 vu1reccountold = -1; + +static _vuopinfo _opinfo[256]; + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU1.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU1.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU1.code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU1.code>>24) & 0x1) +#define _Y ((VU1.code>>23) & 0x1) +#define _Z ((VU1.code>>22) & 0x1) +#define _W ((VU1.code>>21) & 0x1) + +#define _Fsf_ ((VU1.code >> 21) & 0x03) +#define _Ftf_ ((VU1.code >> 23) & 0x03) + + +#define VU1_VFx_ADDR(x) (u32)&VU1.VF[x].UL[0] +#define VU1_VFy_ADDR(x) (u32)&VU1.VF[x].UL[1] +#define VU1_VFz_ADDR(x) (u32)&VU1.VF[x].UL[2] +#define VU1_VFw_ADDR(x) (u32)&VU1.VF[x].UL[3] + +#define VU1_REGR_ADDR (u32)&VU1.VI[REG_R] +#define VU1_REGI_ADDR (u32)&VU1.VI[REG_I] +#define VU1_REGQ_ADDR (u32)&VU1.VI[REG_Q] +#define VU1_REGMAC_ADDR (u32)&VU1.VI[REG_MAC_FLAG] + +#define VU1_VI_ADDR(x) (u32)&VU1.VI[x].UL + +#define VU1_ACCx_ADDR (u32)&VU1.ACC.UL[0] +#define VU1_ACCy_ADDR (u32)&VU1.ACC.UL[1] +#define VU1_ACCz_ADDR (u32)&VU1.ACC.UL[2] +#define VU1_ACCw_ADDR (u32)&VU1.ACC.UL[3] + +static void VU1RecompileBlock(void); + +void recVU1Init() +{ + SuperVUInit(1); +} + +void recVU1Shutdown() +{ + SuperVUDestroy(1); +} + +void recResetVU1( void ) { + + if( CHECK_VU1REC ) { + SuperVUReset(1); + } + + vu1recpcold = 0; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +static void iDumpBlock() +{ + FILE *f; + char filename[ 256 ]; + u32 *mem; + u32 i; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#endif + SysPrintf( "dump1 %x => %x (%s)\n", VU1.VI[ REG_TPC ].UL, pc, filename ); + + f = fopen( filename, "wb" ); + for ( i = VU1.VI[REG_TPC].UL; i < pc; i += 8 ) { + char* pstr; + mem = (u32*)&VU1.Micro[i]; + + pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%x: %-40s ", i, pstr); + + pstr = disVU1MicroLF( mem[0], i ); + fprintf(f, "%s\n", pstr); + } + fclose( f ); +} + +#define VF_VAL(x) ((x==0x80000000)?0:x) + +void iDumpVU1Registers() +{ + int i; + for(i = 1; i < 32; ++i) { + //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), + VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); + //else __Log("%x\n", VU1.VI[i].UL); + else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG)?0:VU1.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); +} + +#ifdef PCSX2_DEVBUILD +static u32 vuprogcount = 0, vutotal = 0; +u32 vudump = 0; +#endif + +extern u32 g_sseMXCSR; +void recExecuteVU1Block(void) +{ +#ifdef _DEBUG + int i; + __asm stmxcsr i + assert( g_sseMXCSR == (i&~0x3f) ); +#endif + + if (CHECK_VU1REC) + { + if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + + assert( (VU1.VI[ REG_TPC ].UL&7) == 0 ); + +#ifdef _DEBUG + vuprogcount++; +#endif + + SuperVUExecuteProgram(VU1.VI[ REG_TPC ].UL, 1); + assert( !(VU0.VI[ REG_VPU_STAT ].UL&0x100) ); + } + else { + intExecuteVU1Block(); + } +} + +void recClearVU1( u32 Addr, u32 Size ) { + assert( (Addr&7) == 0 ); + + if( CHECK_VU1REC ) { + SuperVUClear(Addr, Size*4, 1); + } +} diff --git a/branches/pcsx2_0.9.1/x86/iVU1micro.h b/branches/pcsx2_0.9.1/x86/iVU1micro.h new file mode 100644 index 0000000..cd83b5c --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVU1micro.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU1MICRO_H__ +#define __IVU1MICRO_H__ + +void recVU1Init(); +void recVU1Shutdown(); +void recResetVU1(); +void recExecuteVU1Block( void ); +void recClearVU1( u32 Addr, u32 Size ); + +extern u32 vudump; +void iDumpVU1Registers(); + +#endif /* __IVU1MICRO_H__ */ diff --git a/branches/pcsx2_0.9.1/x86/iVUmicro.c b/branches/pcsx2_0.9.1/x86/iVUmicro.c new file mode 100644 index 0000000..a040a99 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVUmicro.c @@ -0,0 +1,4541 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +int vucycle; +int vucycleold; +_vuopinfo *cinfo = NULL; + +//Lower/Upper instructions can use that.. +#define _Ft_ (( VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ (( VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ (( VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X (( VU->code>>24) & 0x1) +#define _Y (( VU->code>>23) & 0x1) +#define _Z (( VU->code>>22) & 0x1) +#define _W (( VU->code>>21) & 0x1) + +#define _XYZW_SS (_X+_Y+_Z+_W==1) + +#define _Fsf_ (( VU->code >> 21) & 0x03) +#define _Ftf_ (( VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + +#define VU_VFx_ADDR(x) (int)&VU->VF[x].UL[0] +#define VU_VFy_ADDR(x) (int)&VU->VF[x].UL[1] +#define VU_VFz_ADDR(x) (int)&VU->VF[x].UL[2] +#define VU_VFw_ADDR(x) (int)&VU->VF[x].UL[3] + +#define VU_REGR_ADDR (int)&VU->VI[REG_R] +#define VU_REGQ_ADDR (int)&VU->VI[REG_Q] +#define VU_REGMAC_ADDR (int)&VU->VI[REG_MAC_FLAG] + +#define VU_VI_ADDR(x, read) GetVIAddr(VU, x, read, info) + +#define VU_ACCx_ADDR (int)&VU->ACC.UL[0] +#define VU_ACCy_ADDR (int)&VU->ACC.UL[1] +#define VU_ACCz_ADDR (int)&VU->ACC.UL[2] +#define VU_ACCw_ADDR (int)&VU->ACC.UL[3] + +#define _X_Y_Z_W ((( VU->code >> 21 ) & 0xF ) ) + +__declspec(align(16)) float recMult_float_to_int4[4] = { 16.0, 16.0, 16.0, 16.0 }; +__declspec(align(16)) float recMult_float_to_int12[4] = { 4096.0, 4096.0, 4096.0, 4096.0 }; +__declspec(align(16)) float recMult_float_to_int15[4] = { 32768.0, 32768.0, 32768.0, 32768.0 }; + +__declspec(align(16)) float recMult_int_to_float4[4] = { 0.0625f, 0.0625f, 0.0625f, 0.0625f }; +__declspec(align(16)) float recMult_int_to_float12[4] = { 0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625 }; +__declspec(align(16)) float recMult_int_to_float15[4] = { 0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125 }; +static s32 bpc; +_VURegsNum* g_VUregs = NULL; +u8 g_MACFlagTransform[256] = {0}; // used to flip xyzw bits + +static int SSEmovMask[ 16 ][ 4 ] = +{ +{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +{ 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } +}; + +#define VU_SWAPSRC 0xf090 // don't touch + +#define _vuIsRegSwappedWithTemp() (VU_SWAPSRC & (1<<_X_Y_Z_W)) + +// use for allocating vi regs +#define ALLOCTEMPX86(mode) _allocX86reg(-1, X86TYPE_TEMP, 0, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ALLOCVI(vi, mode) _allocX86reg(-1, X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), vi, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ADD_VI_NEEDED(vi) _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), vi); + +// 1 - src, 0 - dest wzyx +void VU_MERGE0(int dest, int src) { // 0000 +} +void VU_MERGE1(int dest, int src) { // 1000 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4); +} +void VU_MERGE2(int dest, int src) { // 0100 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x64); +} +void VU_MERGE3(int dest, int src) { // 1100 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE4(int dest, int src) { // 0010s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE5(int dest, int src) { // 1010 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xd8); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd8); +} +void VU_MERGE6(int dest, int src) { // 0110 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x9c); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x78); +} +void VU_MERGE7(int dest, int src) { // 1110s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE8(int dest, int src) { // 0001 + SSE_MOVSS_XMM_to_XMM(dest, src); +} +void VU_MERGE9(int dest, int src) { // 1001 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc9); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd2); +} +void VU_MERGE10(int dest, int src) { // 0101 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x8d); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x72); +} +void VU_MERGE11(int dest, int src) { // 1101 + SSE_MOVSS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE12(int dest, int src) { // 0011s + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE13(int dest, int src) { // 1011s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0x64); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE14(int dest, int src) { // 0111s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xc4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE15(int dest, int src) { // 1111s + SSE_MOVAPS_XMM_to_XMM(dest, src); +} + +typedef void (*VUMERGEFN)(int dest, int src); +static VUMERGEFN s_VuMerge[16] = { + VU_MERGE0, VU_MERGE1, VU_MERGE2, VU_MERGE3, + VU_MERGE4, VU_MERGE5, VU_MERGE6, VU_MERGE7, + VU_MERGE8, VU_MERGE9, VU_MERGE10, VU_MERGE11, + VU_MERGE12, VU_MERGE13, VU_MERGE14, VU_MERGE15 }; + +#define VU_MERGE_REGS(dest, src) { \ + if( dest != src ) s_VuMerge[_X_Y_Z_W](dest, src); \ +} \ + +#define VU_MERGE_REGS_CUSTOM(dest, src, xyzw) { \ + if( dest != src ) s_VuMerge[xyzw](dest, src); \ +} \ + +void _unpackVF_xyzw(int dstreg, int srcreg, int xyzw) +{ + // don't use pshufd + if( dstreg == srcreg || !cpucaps.hasStreamingSIMD3Extensions) { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + switch (xyzw) { + case 0: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x00); break; + case 1: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); break; + case 2: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xaa); break; + case 3: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); break; + } + } + else { + switch (xyzw) { + case 0: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 1: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 2: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + case 3: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + } + } +} + +void _unpackVFSS_xyzw(int dstreg, int srcreg, int xyzw) +{ + switch (xyzw) { + case 0: + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + break; + case 1: + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); + } + break; + case 2: + SSE_MOVHLPS_XMM_to_XMM(dstreg, srcreg); + break; + case 3: + if( cpucaps.hasStreamingSIMD3Extensions && dstreg != srcreg ) { + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + } + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); + } + break; + } +} + +void _vuFlipRegSS(VURegs * VU, int reg) +{ + assert( _XYZW_SS ); + if( _Y ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xe1); + else if( _Z ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xc6); + else if( _W ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0x27); +} + +void _vuMoveSS(VURegs * VU, int dstreg, int srcreg) +{ + assert( _XYZW_SS ); + if( _Y ) _unpackVFSS_xyzw(dstreg, srcreg, 1); + else if( _Z ) _unpackVFSS_xyzw(dstreg, srcreg, 2); + else if( _W ) _unpackVFSS_xyzw(dstreg, srcreg, 3); + else _unpackVFSS_xyzw(dstreg, srcreg, 0); +} + +void _recvuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((vucycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing FMAC pipe[%d]\n", i); } +#endif + VU->fmac[i].enable = 0; + } + } +} + +void _recvuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((vucycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->fdiv.enable = 0; + } +} + +void _recvuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((vucycle - VU->efu.sCycle) >= VU->efu.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->efu.enable = 0; + } +} + +void _recvuTestPipes(VURegs * VU) { + _recvuFMACflush(VU); + _recvuFDIVflush(VU); + _recvuEFUflush(VU); +} + +void _recvuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + u32 mask = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + (VU->fmac[i].xyzw & xyzw)) break; + } + + if (i == 8) return; + + // do a perchannel delay + // old code + cycle = VU->fmac[i].Cycle - (vucycle - VU->fmac[i].sCycle); + VU->fmac[i].enable = 0; + + // new code +// mask = VU->fmac[i].xyzw & xyzw; +// if( mask & 1 ) mask = 4; // w +// else if( mask & 2 ) mask = 3; // z +// else if( mask & 4 ) mask = 2; // y +// else if( mask & 8 ) mask = 1; // x +// +// assert( (int)VU->fmac[i].sCycle < (int)vucycle ); +// cycle = 0; +// if( vucycle - VU->fmac[i].sCycle < mask ) +// cycle = mask - (vucycle - VU->fmac[i].sCycle); +// +// VU->fmac[i].xyzw &= ~xyzw; +// if( !VU->fmac[i].xyzw ) +// VU->fmac[i].enable = 0; + +// SysPrintf("FMAC stall %d\n", cycle); + vucycle+= cycle; + _recvuTestPipes(VU); +} + +void _recvuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { + SysPrintf("*PCSX2*: error , out of fmacs\n"); + } + +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding FMAC pipe[%d]; reg %d\n", i, reg); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = vucycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].reg = reg; +} + +void _recvuFDIVAdd(VURegs * VU, int cycles) { +// SysPrintf("adding FDIV pipe\n"); + VU->fdiv.enable = 1; + VU->fdiv.sCycle = vucycle; + VU->fdiv.Cycle = cycles; +} + +void _recvuEFUAdd(VURegs * VU, int cycles) { +// SysPrintf("adding EFU pipe\n"); + VU->efu.enable = 1; + VU->efu.sCycle = vucycle; + VU->efu.Cycle = cycles; +} + +void _recvuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + + if( VUregsn->VFread0 && (VUregsn->VFread0 == VUregsn->VFread1) ) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw|VUregsn->VFr1xyzw); + } + else { + if (VUregsn->VFread0) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _recvuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } + } +} + +void _recvuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _recvuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { +// SysPrintf("REG_CLIP_FLAG pipe\n"); + _recvuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _recvuFMACAdd(VU, 0, 0); + } +} + +void _recvuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (vucycle - VU->fdiv.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->fdiv.enable = 0; + vucycle+= cycle; +} + +void _recvuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (vucycle - VU->efu.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->efu.enable = 0; + vucycle+= cycle; +} + +void _recvuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushFDIV(VU); +} + +void _recvuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushEFU(VU); +} + +void _recvuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_Q)) { + _recvuFDIVAdd(VU, VUregsn->cycles); + } +} + +void _recvuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_P)) { + _recvuEFUAdd(VU, VUregsn->cycles); + } +} + +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + } +} + +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuTestEFUStalls(VU, VUregsn); break; + } +} + +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + } +} + +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuAddEFUStalls(VU, VUregsn); break; + } +} + + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs) +{ + _VURegsNum* lregs; + _VURegsNum* uregs; + int *ptr; + + lregs = pCodeRegs; + uregs = pCodeRegs+1; + + ptr = (int*)&VU->Micro[pc]; + pc += 8; + + if (ptr[1] & 0x40000000) { // EOP + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } + + _recvuTestUpperStalls(VU, uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + + if (uregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (uregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + info->cycle = vucycle; + memset(lregs, 0, sizeof(lregs)); + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](lregs); + } + + _recvuTestLowerStalls(VU, lregs); + info->cycle = vucycle; + + if (lregs->pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs->VIwrite & (1 << REG_Q)) { + info->q |= 4; + info->cycles = lregs->cycles; + info->pqinst = (VU->code&2)>>1; // rsqrt is 2 + } + else if (lregs->pipe == VUPIPE_FDIV) { + info->q |= 8|1; + info->pqinst = 0; + } + + if (lregs->VIwrite & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 4; + info->cycles = lregs->cycles; + + switch( VU->code & 0xff ) { + case 0xfd: info->pqinst = 0; break; //eatan + case 0x7c: info->pqinst = 0; break; //eatanxy + case 0x7d: info->pqinst = 0; break; //eatanzy + case 0xfe: info->pqinst = 1; break; //eexp + case 0xfc: info->pqinst = 2; break; //esin + case 0x3f: info->pqinst = 3; break; //erleng + case 0x3e: info->pqinst = 4; break; //eleng + case 0x3d: info->pqinst = 4; break; //ersadd + case 0xbd: info->pqinst = 4; break; //ersqrt + case 0xbe: info->pqinst = 5; break; //ercpr + case 0xbc: info->pqinst = 5; break; //esqrt + case 0x7e: info->pqinst = 5; break; //esum + case 0x3c: info->pqinst = 6; break; //esadd + default: assert(0); + } + } + else if (lregs->pipe == VUPIPE_EFU) { + info->p |= 8|1; + } + + if (lregs->VIread & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_READ; + if (lregs->VIread & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_READ; + + if (lregs->VIwrite & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_WRITE; + if (lregs->VIwrite & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_WRITE; + + if (lregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (lregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + _recvuAddLowerStalls(VU, lregs); + } + _recvuAddUpperStalls(VU, uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs) +{ + int info = 0; + int vfread0=-1, vfread1 = -1, vfwrite = -1, vfacc = -1, vftemp=-1; + + assert( regs != NULL ); + + if( regs->VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<VFread0 ) vfread0 = _allocVFtoXMMreg(VU, -1, regs->VFread0, MODE_READ); + else if( regs->VIread & (1<VFread1 ) vfread1 = _allocVFtoXMMreg(VU, -1, regs->VFread1, MODE_READ); + else if( (regs->VIread & (1<VFr1xyzw != 0xff) vfread1 = _allocVFtoXMMreg(VU, -1, 0, MODE_READ); + + if( regs->VIread & (1<VIwrite&(1<VIwrite & (1<VFwxyzw != 0xf?MODE_READ:0)); + } + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwrite, MODE_WRITE|(regs->VFwxyzw != 0xf?MODE_READ:0)); + } + + if( vfacc>= 0 ) info |= PROCESS_EE_SET_ACC(vfacc); + if( vfwrite >= 0 ) { + if( regs->VFwrite == _Ft_ && vfread1 < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite); + } + else { + assert( regs->VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite); + } + } + + if( vfread0 >= 0 ) info |= PROCESS_EE_SET_S(vfread0); + if( vfread1 >= 0 ) info |= PROCESS_EE_SET_T(vfread1); + + vftemp = _allocTempXMMreg(XMMT_FPS, -1); + info |= PROCESS_VU_SET_TEMP(vftemp); + + if( regs->VIwrite & (1 << REG_CLIP_FLAG) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + int t1reg = _allocTempXMMreg(XMMT_FPS, -1); + int t2reg = _allocTempXMMreg(XMMT_FPS, -1); + + info |= PROCESS_EE_SET_D(t1reg); + info |= PROCESS_EE_SET_ACC(t2reg); + + _freeXMMreg(t1reg); // don't need + _freeXMMreg(t2reg); // don't need + } + else if( regs->VIwrite & (1<statusflag & 1 ) info |= PROCESS_VU_UPDATEFLAGS; + if( cinfo->macflag & 1) info |= PROCESS_VU_UPDATEFLAGS; + + if( regs->pipe == 0xff ) info |= PROCESS_VU_COP2; + + return info; +} + +// returns the correct VI addr +u32 GetVIAddr(VURegs * VU, int reg, int read, int info) +{ + if( info & PROCESS_VU_SUPER ) return SuperVUGetVIAddr(reg, read); + if( info & PROCESS_VU_COP2 ) return (u32)&VU->VI[reg].UL; + + if( read != 1 ) { + if( reg == REG_MAC_FLAG ) return (u32)&VU->macflag; + if( reg == REG_CLIP_FLAG ) return (u32)&VU->clipflag; + if( reg == REG_STATUS_FLAG ) return (u32)&VU->statusflag; + if( reg == REG_Q ) return (u32)&VU->q; + if( reg == REG_P ) return (u32)&VU->p; + } + + return (u32)&VU->VI[reg].UL; +} + +// gets a temp reg that is not EEREC_TEMP +int _vuGetTempXMMreg(int info) +{ + int t1reg = -1; + + if( _hasFreeXMMreg() ) { + t1reg = _allocTempXMMreg(XMMT_FPS, -1); + if( t1reg == EEREC_TEMP && _hasFreeXMMreg() ) { + int t = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t1reg); + t1reg = t; + _freeXMMreg(t1reg); + } + else { + _freeXMMreg(t1reg); + t1reg = -1; + } + } + + return t1reg; +} + +__declspec(align(16)) u32 g_minvals[4] = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}; +__declspec(align(16)) u32 g_maxvals[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}; + +static __declspec(align(16)) int const_clip[] = { + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + +static __declspec(align(16)) u32 s_FloatMinMax[] = { + 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, + 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, + 0, 0, 0, 0 }; + +static __declspec(align(16)) float s_fones[] = { 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f }; +static __declspec(align(16)) u32 s_mask[] = {0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff }; +static __declspec(align(16)) u32 s_expmask[] = {0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000}; + +void CheckForOverflowSS_(int fdreg, int t0reg) +{ + assert( t0reg != fdreg ); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDSS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVSS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNESS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow_(int fdreg, int t0reg) +{ +// SSE_MAXPS_M128_to_XMM(fdreg, (u32)g_minvals); +// SSE_MINPS_M128_to_XMM(fdreg, (u32)g_maxvals); + + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVAPS_M128_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNEPS_M128_to_XMM(t0reg, (u32)s_expmask); +// //SSE_ORPS_M128_to_XMM(t0reg, (u32)g_minvals); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow(int info, int regd) +{ + if( CHECK_FORCEABS && EEREC_TEMP != regd) { + // changing the order produces different results (tektag) + CheckForOverflow_(regd, EEREC_TEMP); + } +} + +// if unordered replaces with 0x7f7fffff (note, loses sign) +void ClampUnordered(int regd, int t0reg, int dosign) +{ + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, regd); + SSE_ANDPS_XMM_to_XMM(regd, t0reg); + SSE_ANDNPS_M128_to_XMM(t0reg, (u32)g_maxvals); + SSE_ORPS_XMM_to_XMM(regd, t0reg); +} + +// VU Flags +// NOTE: flags don't compute under/over flows since it is highly unlikely +// that games used them. Including them will lower performance. +void recUpdateFlags(VURegs * VU, int reg, int info) +{ + u32 flagmask; + u8* pjmp; + u32 macaddr, stataddr, prevstataddr; + int x86macflag, x86newflag, x86oldflag; + const static u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + if( !(info & PROCESS_VU_UPDATEFLAGS) ) + return; + + flagmask = macarr[_X_Y_Z_W]; + macaddr = VU_VI_ADDR(REG_MAC_FLAG, 0); + stataddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + assert( stataddr != 0); + prevstataddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + // 20 insts + x86newflag = ALLOCTEMPX86(MODE_8BITREG); + x86macflag = ALLOCTEMPX86(0); + x86oldflag = ALLOCTEMPX86(0); + + // can do with 8 bits since only computing zero/sign flags + if( EEREC_TEMP != reg ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_CMPEQPS_XMM_to_XMM(EEREC_TEMP, reg); + + MOV32MtoR(x86oldflag, prevstataddr); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + XOR32RtoR(EAX, EAX); + + SSE_ANDNPS_XMM_to_XMM(EEREC_TEMP, reg); // necessary! + + AND32ItoR(x86newflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SSE_MOVMSKPS_XMM_to_R32(x86macflag, EEREC_TEMP); // sign + + SHL32ItoR(x86newflag, 4); + AND32ItoR(x86macflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + OR32RtoR(x86macflag, x86newflag); + } + else { + SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // mask is < 0 (including 80000000) + + MOV32MtoR(x86oldflag, prevstataddr); + XOR32RtoR(EAX, EAX); + + SSE_CMPEQPS_M128_to_XMM(EEREC_TEMP, (u32)&s_FloatMinMax[8]); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + NOT32R(x86newflag); + AND32RtoR(x86macflag, x86newflag); + + AND32ItoR(x86macflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + NOT32R(x86newflag); + + AND32ItoR(x86newflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SHL32ItoR(x86newflag, 4); + OR32RtoR(x86macflag, x86newflag); + } + + // x86macflag - new untransformed mac flag, EAX - new status bits, x86oldflag - old status flag + // x86macflag = zero_wzyx | sign_wzyx + MOV8RmtoROffset(x86newflag, x86macflag, (u32)g_MACFlagTransform); // transform + //MOV16RmSOffsettoR(x86newflag, x86macflag, (u32)g_MACFlagTransform, 1); + MOV32RtoR(x86macflag, x86oldflag); + SHL32ItoR(x86macflag, 6); + MOV8RtoM(macaddr, x86newflag); + OR32RtoR(x86oldflag, x86macflag); + + AND32ItoR(x86oldflag, 0x0c0); + OR32RtoR(x86oldflag, EAX); + MOV32RtoM(stataddr, x86oldflag); + + _freeX86reg(x86macflag); + _freeX86reg(x86newflag); + _freeX86reg(x86oldflag); +} + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +static __declspec(align(16)) int const_abs_table[16][4] = +{ + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, +}; + +void recVUMI_ABS(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_T, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + } +} + +__declspec(align(16)) float s_two[4] = {0,0,0,2}; + +void recVUMI_ADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_two); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_two); + } + } + else { + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_ADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Ft_ == 0 && xyzw < 3 ) { + // just move + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if( _Fs_ == 0 && !_W ) { + // just move + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADDi(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDq(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDx(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 0, info); } +void recVUMI_ADDy(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 1, info); } +void recVUMI_ADDz(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 2, info); } +void recVUMI_ADDw(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 3, info); } + +void recVUMI_ADDA(VURegs *VU, int info) +{ + if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + assert( EEREC_ACC != EEREC_TEMP ); + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_ACC, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( _Fs_ == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_ACC, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDAi(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDAq(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDAx(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 0, info); } +void recVUMI_ADDAy(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 1, info); } +void recVUMI_ADDAz(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 2, info); } +void recVUMI_ADDAw(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 3, info); } + +void recVUMI_SUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Ft_ > 0 || _W ) SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + // neopets works better with this? + //CheckForOverflow(info, EEREC_D); +} + +void recVUMI_SUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if (EEREC_D != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +static __declspec(align(16)) s_unaryminus[4] = {0x80000000, 0, 0, 0}; + +void recVUMI_SUB_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + if( _Fs_ > 0 ) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)s_unaryminus); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } +// else if( _XYZW_SS && xyzw == 0 ) { +// if( EEREC_D == EEREC_S ) { +// if( EEREC_D == EEREC_T ) { +// SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } +// else if( EEREC_D == EEREC_T ) { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_SUBi(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBq(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBx(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 0, info); } +void recVUMI_SUBy(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 1, info); } +void recVUMI_SUBz(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 2, info); } +void recVUMI_SUBw(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 3, info); } + +void recVUMI_SUBA(VURegs *VU, int info) +{ + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_ACC, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_ACC); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBAi(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBAq(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBAx(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 0, info); } +void recVUMI_SUBAy(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 1, info); } +void recVUMI_SUBAz(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 2, info); } +void recVUMI_SUBAw(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 3, info); } + +void recVUMI_MUL_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W == 1 && (_Ft_ == 0 || _Fs_==0) ) { // W + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, _Ft_ ? EEREC_T : EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( _Fd_ == _Fs_ && _Fs_ == _Ft_ && _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_D); + _vuFlipRegSS(VU, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (regd == EEREC_S) SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + } + } +} + +void recVUMI_MUL_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _XYZW_SS ) { + if( regd == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( regd == EEREC_S ) { + _vuFlipRegSS(VU, regd); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, regd); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + if( xyzw < 3 ) { + if (_X_Y_Z_W != 0xf) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + SSE_XORPS_XMM_to_XMM(regd, regd); + } + } + else { + assert(xyzw==3); + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( regd != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MUL_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MUL_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MULi(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULq(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULx(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 0, info); } +void recVUMI_MULy(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 1, info); } +void recVUMI_MULz(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 2, info); } +void recVUMI_MULw(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 3, info); } + +void recVUMI_MULA( VURegs *VU, int info ) +{ + recVUMI_MUL_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_iq(VURegs *VU, int addr, int info) +{ + recVUMI_MUL_iq_toD(VU, addr, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_xyzw(VURegs *VU, int xyzw, int info) +{ + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULAi(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULAq(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULAx(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 0, info); } +void recVUMI_MULAy(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 1, info); } +void recVUMI_MULAz(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 2, info); } +void recVUMI_MULAw(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 3, info); } + +void recVUMI_MADD_toD(VURegs *VU, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } +} + +void recVUMI_MADD_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + if( _Fs_ == 0 ) { + // add addr to w + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + else { + assert( EEREC_TEMP < XMMREGS ); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else if( regd == EEREC_S ) { + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else { + if( _Fs_ == 0 ) { + // add addr to w + if( _W ) { + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + + return; + } + + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + + if( xyzw == 3 ) { + // just add + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_S ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_S); + } + } + else { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_S ) SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_S); + } + } + } + } + else { + // just move acc to regd + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + + return; + } + + if( _X_Y_Z_W == 8 ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if( regd == EEREC_ACC ) { + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + // fixes suikoden 5 chars + CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MADDi(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MADDq(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MADDx(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 0, info); } +void recVUMI_MADDy(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 1, info); } +void recVUMI_MADDz(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 2, info); } +void recVUMI_MADDw(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 3, info); } + +void recVUMI_MADDA( VURegs *VU, int info ) +{ + recVUMI_MADD_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAi( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_VI_ADDR(REG_I, 1), EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAq( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_REGQ_ADDR, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAx( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 0, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAy( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 1, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAz( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 2, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAw( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 3, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUB_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_S ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_T ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_temp_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_iq_toD(VURegs *VU, int regd, int addr, int info) +{ + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB_xyzw_toD(VURegs *VU, int regd, int xyzw, int info) +{ + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_iq_toD(VU, EEREC_D, addr, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(info, EEREC_D); +} + +void recVUMI_MSUBi(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MSUBq(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MSUBx(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 0, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBy(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 1, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBz(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 2, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBw(VURegs *VU, int info) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 3, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBA( VURegs *VU, int info ) +{ + recVUMI_MSUB_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAi( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_VI_ADDR(REG_I, 1), info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAq( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_REGQ_ADDR, info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAx( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 0, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAy( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 1, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAz( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 2, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAw( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 3, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MAX(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MAX_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MAX_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + else if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + } + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + else SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_fones); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } +} + +void recVUMI_MAXi(VURegs *VU, int info) { recVUMI_MAX_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MAXx(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 0, info); } +void recVUMI_MAXy(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 1, info); } +void recVUMI_MAXz(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 2, info); } +void recVUMI_MAXw(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 3, info); } + +void recVUMI_MINI(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_T, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_S, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MINI_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINI_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINIi(VURegs *VU, int info) { recVUMI_MINI_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MINIx(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 0, info); } +void recVUMI_MINIy(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 1, info); } +void recVUMI_MINIz(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 2, info); } +void recVUMI_MINIw(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 3, info); } + +void recVUMI_OPMULA( VURegs *VU, int info ) +{ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xD2); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T ); + + VU_MERGE_REGS_CUSTOM(EEREC_ACC, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_ACC ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_OPMSUB( VURegs *VU, int info ) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM( EEREC_T, EEREC_T, 0xD2 ); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T); + + // negate and add + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS_CUSTOM(EEREC_D, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_D ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_NOP( VURegs *VU, int info ) +{ +} + +void recVUMI_FTOI0(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_FTOIX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if (EEREC_T != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + } +} + +void recVUMI_FTOI4( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int4[0], info); } +void recVUMI_FTOI12( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int12[0], info); } +void recVUMI_FTOI15( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int15[0], info); } + +void recVUMI_ITOF0( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + } + } +} + +void recVUMI_ITOFX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + } +} + +void recVUMI_ITOF4( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float4[0], info); } +void recVUMI_ITOF12( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float12[0], info); } +void recVUMI_ITOF15( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float15[0], info); } + +void recVUMI_CLIP(VURegs *VU, int info) +{ + int t1reg = EEREC_D; + int t2reg = EEREC_ACC; + int x86temp0, x86temp1; + + u32 clipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + u32 prevclipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 2); + + assert( clipaddr != 0 ); + assert( t1reg != t2reg && t1reg != EEREC_TEMP && t2reg != EEREC_TEMP ); + + x86temp1 = ALLOCTEMPX86(MODE_8BITREG); + x86temp0 = ALLOCTEMPX86(0); + + if( _Ft_ == 0 ) { + // all 1s + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)&s_fones[0]); + SSE_MOVAPS_M128_to_XMM(t1reg, (u32)&s_fones[4]); + + MOV32MtoR(EAX, prevclipaddr); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, 3); + SSE_XORPS_XMM_to_XMM(t1reg, t1reg); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)const_clip); + + MOV32MtoR(EAX, prevclipaddr); + + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + } + + SSE_CMPLTPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_CMPNLEPS_XMM_to_XMM(t1reg, EEREC_S); + + SHL32ItoR(EAX, 6); + + SSE_MOVAPS_XMM_to_XMM(t2reg, EEREC_TEMP); + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, t1reg); + SSE_UNPCKHPS_XMM_to_XMM(t2reg, t1reg); + SSE_MOVMSKPS_XMM_to_R32(x86temp0, EEREC_TEMP); // -y,+y,-x,+x + SSE_MOVMSKPS_XMM_to_R32(x86temp1, t2reg); // -w,+w,-z,+z + + AND32ItoR(EAX, 0xffffff); + + AND8ItoR(x86temp1, 0x3); + SHL32ItoR(x86temp1, 4); + OR32RtoR(EAX, x86temp0); + OR32RtoR(EAX, x86temp1); + + MOV32RtoM(clipaddr, EAX); + if( !(info&(PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void recVUMI_DIV(VURegs *VU, int info) +{ + if( _Fs_ == 0 ) { + + if( _Ft_ == 0 ) { + if( _Fsf_ < 3 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0); + else if( _Ftf_ < 0 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x7f7fffff); + else MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x3f800000); + return; + } + + if( _Fsf_ == 3 ) { // = 1 + // don't use RCPSS (very bad precision) + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + if( _Ftf_ == 0 || (xmmregs[EEREC_T].mode & MODE_WRITE) ) { + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + } + } + else { // = 0 + MOV32ItoR(VU_VI_ADDR(REG_Q, 0), 0); + return; + } + } + else { + if( _Fsf_ == 0 ) SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + // revert + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_SQRT( VURegs *VU, int info ) +{ + if( _Ftf_ ) { + if( xmmregs[EEREC_T].mode & MODE_WRITE ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_RSQRT(VURegs *VU, int info) +{ + if( _Ftf_ ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + if( _Fs_ == 0 ) { + if( _Fsf_ == 3 ) SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void _addISIMMtoIT(VURegs *VU, s16 imm, int info) +{ + int fsreg = -1, ftreg; + if (_Ft_ == 0) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32ItoR(ftreg, imm&0xffff); + return; + } + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if (ftreg == fsreg) { + if (imm != 0 ) { + ADD16ItoR(ftreg, imm); + } + } else { + if( imm ) LEA16RtoR(ftreg, fsreg, imm); + else MOV32RtoR(ftreg, fsreg); + } +} + +void recVUMI_IADDI(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code >> 6 ) & 0x1f; + imm = ( imm & 0x10 ? 0xfff0 : 0) | ( imm & 0xf ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADDIU(VURegs *VU, int info) +{ + int imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADD( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else { + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) ADD32RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) ADD32RtoR(fdreg, fsreg); + else LEA16RRtoR(fdreg, fsreg, ftreg); + MOVZX32R16toR(fdreg, fdreg); // neeed since don't know if fdreg's upper bits are 0 + } +} + +void recVUMI_IAND( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Fs_ == 0 ) || ( _Ft_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) AND16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) AND16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, ftreg); + AND32RtoR(fdreg, fsreg); + } +} + +void recVUMI_IOR( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) OR16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) OR16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, fsreg); + OR32RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUB( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + NEG16R(fdreg); + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) SUB16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) { + SUB16RtoR(fdreg, fsreg); + NEG16R(fdreg); + } + else { + MOV32RtoR(fdreg, fsreg); + SUB16RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUBIU( VURegs *VU, int info ) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + imm = -imm; + _addISIMMtoIT(VU, (u32)imm & 0xffff, info); +} + +void recVUMI_MOVE( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_MFIR( VURegs *VU, int info ) +{ + static u32 s_temp; + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, 1); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _XYZW_SS ) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + _vuFlipRegSS(VU, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + SSE2_MOVD_M32_to_XMM(EEREC_T, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_T, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } + else { + MOVSX32M16toR(EAX, VU_VI_ADDR(_Fs_, 1)); + MOV32RtoM((u32)&s_temp, EAX); + + if( _X_Y_Z_W != 0xf ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } +} + +void recVUMI_MTIR( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, 2); + + if( _Fsf_ == 0 ) { + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_S); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_TEMP); + } + + AND32ItoM(VU_VI_ADDR(_Ft_, 0), 0xffff); +} + +void recVUMI_MR32( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x39); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x39); + } +} + +// if x86reg < 0, reads directly from offset +void _loadEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + if( x86reg >= 0 ) { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + + case 8: // X + SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } + else { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_M64_to_XMM(EEREC_T, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + case 8: // X + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_M64_to_XMM(EEREC_T, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_T, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_T, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } +} + +int recVUTransformAddr(int x86reg, VURegs* VU, int vireg, int imm) +{ + u8* pjmp[2]; + if( x86reg == EAX ) { + if (imm) ADD32ItoR(x86reg, imm); + } + else { + if( imm ) LEA32RtoR(EAX, x86reg, imm); + else MOV32RtoR(EAX, x86reg); + } + + if( VU == &VU1 ) { + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0x3fff); + } + else { + // if addr >= 4200, reads integers + CMP32ItoR(EAX, 0x420); + pjmp[0] = JL8(0); + AND32ItoR(EAX, 0x1f); + SHL32ItoR(EAX, 2); + OR32ItoR(EAX, 0x4200); + + pjmp[1] = JMP8(0); + x86SetJ8(pjmp[0]); + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0xfff); // can be removed + + x86SetJ8(pjmp[1]); + } + + return EAX; +} + +void recVUMI_LQ(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)GET_VU_MEM(VU, (u32)imm*16), info); + } else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_LQD( VURegs *VU, int info ) +{ + int fsreg; + + if ( _Fs_ != 0 ) { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + SUB16ItoR( fsreg, 1 ); + } + + if ( _Ft_ == 0 ) return; + + if ( _Fs_ == 0 ) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_LQI(VURegs *VU, int info) +{ + int fsreg; + + if ( _Ft_ == 0 ) { + if( _Fs_ != 0 ) { + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_WRITE|MODE_READ)) >= 0 ) { + ADD16ItoR(fsreg, 1); + } + else { + ADD16ItoM( VU_VI_ADDR( _Fs_, 0 ), 1 ); + } + } + return; + } + + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + ADD16ItoR( fsreg, 1 ); + } +} + +void _saveEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + int t1reg; + + if( _Fs_ == 0 ) { + if( _XYZW_SS ) { + u32 c = _W ? 0x3f800000 : 0; + if( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); + else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c); + } + else { + int zeroreg = (x86reg == EAX) ? ALLOCTEMPX86(0) : EAX; + + XOR32RtoR(zeroreg, zeroreg); + if( x86reg >= 0 ) { + if( _X ) MOV32RtoRmOffset(x86reg, zeroreg, offset); + if( _Y ) MOV32RtoRmOffset(x86reg, zeroreg, offset+4); + if( _Z ) MOV32RtoRmOffset(x86reg, zeroreg, offset+8); + if( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12); + } + else { + if( _X ) MOV32RtoM(offset, zeroreg); + if( _Y ) MOV32RtoM(offset+4, zeroreg); + if( _Z ) MOV32RtoM(offset+8, zeroreg); + if( _W ) MOV32ItoM(offset+12, 0x3f800000); + } + + if( zeroreg != EAX ) _freeX86reg(zeroreg); + } + return; + } + + switch(_X_Y_Z_W) { + case 1: // W + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + break; + case 2: // Z + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + break; + case 3: // ZW + if( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S); + break; + case 4: // Y + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + break; + case 6: // YZ + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xc9); + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xd2); + break; + case 8: // X + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + break; + case 9: // XW + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); + + break; + case 12: // XY + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + break; + + case 14: // XYZ + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) { + SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + } + else { + SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + } + break; + case 15: // XYZW + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + } + break; + default: + + // EEREC_D is a temp reg + // find the first nonwrite reg + t1reg = _vuGetTempXMMreg(info); + + if( t1reg < 0 ) { + for(t1reg = 0; t1reg < XMMREGS; ++t1reg) { + if( xmmregs[t1reg].inuse && !(xmmregs[t1reg].mode&MODE_WRITE) ) break; + } + + if( t1reg == XMMREGS ) t1reg = -1; + else { + if( t1reg != EEREC_S ) _allocTempXMMreg(XMMT_FPS, t1reg); + } + } + + if( t1reg >= 0 ) { + // found a temp reg + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + if( t1reg != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + + VU_MERGE_REGS(EEREC_TEMP, t1reg); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + } + + if( t1reg != EEREC_S ) _freeXMMreg(t1reg); + else { + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + } + else { + // do it with one reg + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + VU_MERGE_REGS(EEREC_TEMP, EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + } + + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + + break; + } +} + +void recVUMI_SQ(VURegs *VU, int info) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if ( _Ft_ == 0 ) { + _saveEAX(VU, -1, (u32)GET_VU_MEM(VU, (int)imm * 16), info); + } + else { + int ftreg = ALLOCVI(_Ft_, MODE_READ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_SQD(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + SUB16ItoR( ftreg, 1 ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_SQI(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + + ADD16ItoR( ftreg, 1 ); + } +} + +void recVUMI_ILW(VURegs *VU, int info) +{ + int ftreg; + s16 imm, off; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (u32)GET_VU_MEM(VU, (int)imm * 16 + off) ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem + off); + } +} + +void recVUMI_ISW( VURegs *VU, int info ) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + + if (_Fs_ == 0) { + u32 off = (u32)GET_VU_MEM(VU, (int)imm * 16); + int ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_X) MOV32RtoM(off, ftreg); + if (_Y) MOV32RtoM(off+4, ftreg); + if (_Z) MOV32RtoM(off+8, ftreg); + if (_W) MOV32RtoM(off+12, ftreg); + } + else { + int x86reg, fsreg, ftreg; + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_ILWR( VURegs *VU, int info ) +{ + int off, ftreg; + + if ( _Ft_ == 0 ) return; + + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (int)VU->Mem + off ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (int)VU->Mem + off); + } +} + +void recVUMI_ISWR( VURegs *VU, int info ) +{ + int ftreg; + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_Fs_ == 0) { + if (_X) MOV32RtoM((int)VU->Mem, ftreg); + if (_Y) MOV32RtoM((int)VU->Mem+4, ftreg); + if (_Z) MOV32RtoM((int)VU->Mem+8, ftreg); + if (_W) MOV32RtoM((int)VU->Mem+12, ftreg); + } + else { + int x86reg; + int fsreg = ALLOCVI(_Fs_, MODE_READ); + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_RINIT(VURegs *VU, int info) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 2); + + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + MOV32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR( rreg, 0x7f << 23 ); + } +} + +void recVUMI_RGET(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + + if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +void recVUMI_RNEXT( VURegs *VU, int info ) +{ + int rreg, x86temp0, x86temp1; + if ( _Ft_ == 0) return; + + rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + x86temp0 = ALLOCTEMPX86(0); + x86temp1 = ALLOCTEMPX86(0); + + // code from www.project-fao.org + MOV32MtoR(rreg, VU_REGR_ADDR); + MOV32RtoR(x86temp0, rreg); + SHR32ItoR(x86temp0, 4); + AND32ItoR(x86temp0, 1); + + MOV32RtoR(x86temp1, rreg); + SHR32ItoR(x86temp1, 22); + AND32ItoR(x86temp1, 1); + + SHL32ItoR(rreg, 1); + XOR32RtoR(x86temp0, x86temp1); + XOR32RtoR(rreg, x86temp0); + AND32ItoR(rreg, 0x7fffff); + OR32ItoR(rreg, 0x3f800000); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); + + recVUMI_RGET(VU, info); +} + +void recVUMI_RXOR( VURegs *VU, int info ) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode & MODE_NOFLUSH) ) { + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_XORPS_M128_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + XOR32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR ( rreg, 0x3f800000 ); + } +} + +void recVUMI_WAITQ( VURegs *VU, int info ) +{ +// if( info & PROCESS_VU_SUPER ) { +// //CALLFunc(waitqfn); +// SuperVUFlush(0, 1); +// } +} + +void recVUMI_FSAND( VURegs *VU, int info ) +{ + int ftreg; + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32MtoR(ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1)); + AND32ItoR( ftreg, 0xFFF&imm ); +} + +void recVUMI_FSEQ( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if ( _Ft_ == 0 ) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + + MOVZX32M16toR( EAX, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + XOR32RtoR(ftreg, ftreg); + AND16ItoR( EAX, 0xFFF ); + + CMP16ItoR(EAX, imm); + SETE8R(ftreg); +} + +void recVUMI_FSOR( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if(_Ft_ == 0) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M16toR( ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + OR16ItoR( ftreg, imm ); +} + +void recVUMI_FSSET(VURegs *VU, int info) +{ + u32 writeaddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + u32 prevaddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + + MOV32MtoR(EAX, prevaddr); + AND32ItoR(EAX, 0x3f); + if ((imm&0xfc0) != 0) OR32ItoR(EAX, imm & 0xFC0); + + MOV32RtoM(writeaddr ? writeaddr : prevaddr, EAX); +} + +void recVUMI_FMAND( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( ftreg != fsreg ) MOVZX32R16toR(ftreg, fsreg); + } + else MOVZX32M16toR(ftreg, VU_VI_ADDR(_Fs_, 1)); + + AND16MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); +} + +void recVUMI_FMEQ( VURegs *VU, int info ) +{ + int ftreg, fsreg; + if ( _Ft_ == 0 ) return; + + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + CMP16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(EAX); + MOVZX32R8toR(ftreg, EAX); + } + else { + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + fsreg = ALLOCVI(_Fs_, MODE_READ); + + XOR32RtoR(ftreg, ftreg); + + CMP16MtoR(fsreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(ftreg); + } +} + +void recVUMI_FMOR( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ); + OR16MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + else { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M16toR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + OR16RtoR( ftreg, fsreg); + } + else { + OR16MtoR( ftreg, VU_VI_ADDR(_Fs_, 1)); + } + } +} + +void recVUMI_FCAND( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + XOR32RtoR(ftreg, ftreg); + AND32ItoR( EAX, VU->code & 0xFFFFFF ); + SETNZ8R(ftreg); +} + +void recVUMI_FCEQ( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + CMP32ItoR( EAX, VU->code&0xffffff ); + SETE8R(ftreg); +} + +void recVUMI_FCOR( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + OR32ItoR( EAX, (VU->code & 0xFFFFFF)|0xff000000 ); + ADD32ItoR(EAX, 1); + + // set to 1 if EAX is 0 + SETZ8R(ftreg); +} + +void recVUMI_FCSET( VURegs *VU, int info ) +{ + u32 addr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + + MOV32ItoM(addr ? addr : VU_VI_ADDR(REG_CLIP_FLAG, 2), VU->code&0xffffff ); + + if( !(info & (PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) + MOV32ItoM( VU_VI_ADDR(REG_CLIP_FLAG, 1), VU->code&0xffffff ); +} + +void recVUMI_FCGET( VURegs *VU, int info ) +{ + int ftreg; + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOV32MtoR(ftreg, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + AND32ItoR(ftreg, 0x0fff); +} + +// SuperVU branch fns are in ivuzerorec.cpp +static s32 _recbranchAddr(VURegs * VU) +{ + bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void recVUMI_IBEQ(VURegs *VU, int info) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBNE( VURegs *VU, int info ) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_B(VURegs *VU, int info) +{ + // supervu will take care of the rest + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + branch |= 3; +} + +void recVUMI_BAL( VURegs *VU, int info ) +{ + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_JR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + branch |= 3; +} + +void recVUMI_JALR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_MFP(VURegs *VU, int info) +{ + if (_Ft_ == 0) return; + + if( _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_T); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +static __declspec(align(16)) float s_tempmem[4]; + +void recVUMI_WAITP(VURegs *VU, int info) +{ +// if( info & PROCESS_VU_SUPER ) +// SuperVUFlush(1, 1); +} + +// in all EFU insts, EEREC_D is a temp reg +void vuSqSumXYZ(int regd, int regs, int regtemp) +{ + SSE_MOVAPS_XMM_to_XMM(regtemp, regs); + SSE_MULPS_XMM_to_XMM(regtemp, regtemp); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(regd, regtemp); + SSE_ADDPS_XMM_to_XMM(regd, regtemp); // regd.z = x+y+z + SSE_MOVHLPS_XMM_to_XMM(regd, regd); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(regd, regtemp); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + SSE_SHUFPS_XMM_to_XMM(regtemp, regtemp, 0x55); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + } +} + +void recVUMI_ESADD( VURegs *VU, int info) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_TEMP, EEREC_S, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERSADD( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + // almost same as vuSqSumXYZ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); // EEREC_D.z = x+y+z + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_D); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + } + + // don't use RCPSS (very bad precision) + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ELENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERLENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_EATANxy( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[1]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[1]); + } + + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATANxz( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[2]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[2]); + } + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_ESUM( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); // y+w, x+z + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); // y+w, y+w, x+z, x+z + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERCPR( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + // don't use RCPSS (very bad precision) + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + // revert + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERSQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESIN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + FSIN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATAN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + } + + FLD1(); + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EEXP( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + FLDL2E(); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FMUL32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FMUL32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + // basically do 2^(log_2(e) * val) + FLD(0); + FRNDINT(); + FXCH(1); + FSUB32Rto0(1); + F2XM1(); + FLD1(); + FADD320toR(1); + FSCALE(); + FSTP(1); + + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_XITOP( VURegs *VU, int info ) +{ + int ftreg; + if (_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->itop ); +} + +void recVUMI_XTOP( VURegs *VU, int info ) +{ + int ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->top ); +} + +extern HANDLE g_hGsEvent; + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) +{ + u32 size; + u8* pmem; + u32* data = (u32*)((u8*)pMem + (addr&0x3fff)); + + size = GSgifTransferDummy(0, data, 0x4000>>4); + + size = 0x4000-(size<<4); + pmem = GSRingBufCopy(NULL, size, GS_RINGTYPE_P1); + assert( pmem != NULL ); + + memcpy_amd(pmem, (u8*)pMem+addr, size); + GSRINGBUF_DONECOPY(pmem, size); + + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + } +} + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 766 ) +// vudump |= 8; +//} + +void recVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + PUSH32R(fsreg); + PUSH32I((int)VU->Mem); + iFlushCall(FLUSH_NOCONST); + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { + CALLFunc((int)GSgifTransfer1); + } +} diff --git a/branches/pcsx2_0.9.1/x86/iVUmicro.h b/branches/pcsx2_0.9.1/x86/iVUmicro.h new file mode 100644 index 0000000..2e38d50 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVUmicro.h @@ -0,0 +1,274 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVUMICRO_H__ +#define __IVUMICRO_H__ + +#define VU0_MEMSIZE 0x1000 +#define VU1_MEMSIZE 0x4000 + +#define RECOMPILE_VUMI_ABS +#define RECOMPILE_VUMI_SUB +#define RECOMPILE_VUMI_SUBA +#define RECOMPILE_VUMI_MADD +#define RECOMPILE_VUMI_MADDA +#define RECOMPILE_VUMI_MSUB +#define RECOMPILE_VUMI_MSUBA + +#define RECOMPILE_VUMI_ADD +#define RECOMPILE_VUMI_ADDA +#define RECOMPILE_VUMI_MUL +#define RECOMPILE_VUMI_MULA +#define RECOMPILE_VUMI_MAX +#define RECOMPILE_VUMI_MINI +#define RECOMPILE_VUMI_FTOI + +#define RECOMPILE_VUMI_MATH +#define RECOMPILE_VUMI_MISC +#define RECOMPILE_VUMI_E +#define RECOMPILE_VUMI_X +#define RECOMPILE_VUMI_RANDOM +#define RECOMPILE_VUMI_FLAG +#define RECOMPILE_VUMI_BRANCH +#define RECOMPILE_VUMI_ARITHMETIC +#define RECOMPILE_VUMI_LOADSTORE + +#ifdef __x86_64__ +#undef RECOMPILE_VUMI_X +#endif + +u32 GetVIAddr(VURegs * VU, int reg, int read, int info); // returns the correct VI addr +void recUpdateFlags(VURegs * VU, int reg, int info); + +void _recvuTestPipes(VURegs * VU); +void _recvuFlushFDIV(VURegs * VU); +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +#define VUOP_READ 2 +#define VUOP_WRITE 4 + +// save on mem +typedef struct { + int cycle; + int cycles; + u8 statusflag; + u8 macflag; + u8 clipflag; + u8 dummy; + u8 q; + u8 p; + u16 pqinst; // bit of instruction specifying index (srec only) +} _vuopinfo; +extern _vuopinfo *cinfo; + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs); + +// allocates all the necessary regs and returns the indices +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs); + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr); // used for MTGS in XGKICK + +extern _VURegsNum* g_VUregs; + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; +#define VUREC_INFO eeVURecompileCode(VU, g_VUregs) + +extern int vucycle; +extern int vucycleold; + + +/***************************************** + VU Micromode Upper instructions +*****************************************/ + +void recVUMI_ABS(VURegs *vuRegs, int info); +void recVUMI_ADD(VURegs *vuRegs, int info); +void recVUMI_ADDi(VURegs *vuRegs, int info); +void recVUMI_ADDq(VURegs *vuRegs, int info); +void recVUMI_ADDx(VURegs *vuRegs, int info); +void recVUMI_ADDy(VURegs *vuRegs, int info); +void recVUMI_ADDz(VURegs *vuRegs, int info); +void recVUMI_ADDw(VURegs *vuRegs, int info); +void recVUMI_ADDA(VURegs *vuRegs, int info); +void recVUMI_ADDAi(VURegs *vuRegs, int info); +void recVUMI_ADDAq(VURegs *vuRegs, int info); +void recVUMI_ADDAx(VURegs *vuRegs, int info); +void recVUMI_ADDAy(VURegs *vuRegs, int info); +void recVUMI_ADDAz(VURegs *vuRegs, int info); +void recVUMI_ADDAw(VURegs *vuRegs, int info); +void recVUMI_SUB(VURegs *vuRegs, int info); +void recVUMI_SUBi(VURegs *vuRegs, int info); +void recVUMI_SUBq(VURegs *vuRegs, int info); +void recVUMI_SUBx(VURegs *vuRegs, int info); +void recVUMI_SUBy(VURegs *vuRegs, int info); +void recVUMI_SUBz(VURegs *vuRegs, int info); +void recVUMI_SUBw(VURegs *vuRegs, int info); +void recVUMI_SUBA(VURegs *vuRegs, int info); +void recVUMI_SUBAi(VURegs *vuRegs, int info); +void recVUMI_SUBAq(VURegs *vuRegs, int info); +void recVUMI_SUBAx(VURegs *vuRegs, int info); +void recVUMI_SUBAy(VURegs *vuRegs, int info); +void recVUMI_SUBAz(VURegs *vuRegs, int info); +void recVUMI_SUBAw(VURegs *vuRegs, int info); +void recVUMI_MUL(VURegs *vuRegs, int info); +void recVUMI_MULi(VURegs *vuRegs, int info); +void recVUMI_MULq(VURegs *vuRegs, int info); +void recVUMI_MULx(VURegs *vuRegs, int info); +void recVUMI_MULy(VURegs *vuRegs, int info); +void recVUMI_MULz(VURegs *vuRegs, int info); +void recVUMI_MULw(VURegs *vuRegs, int info); +void recVUMI_MULA(VURegs *vuRegs, int info); +void recVUMI_MULAi(VURegs *vuRegs, int info); +void recVUMI_MULAq(VURegs *vuRegs, int info); +void recVUMI_MULAx(VURegs *vuRegs, int info); +void recVUMI_MULAy(VURegs *vuRegs, int info); +void recVUMI_MULAz(VURegs *vuRegs, int info); +void recVUMI_MULAw(VURegs *vuRegs, int info); +void recVUMI_MADD(VURegs *vuRegs, int info); +void recVUMI_MADDi(VURegs *vuRegs, int info); +void recVUMI_MADDq(VURegs *vuRegs, int info); +void recVUMI_MADDx(VURegs *vuRegs, int info); +void recVUMI_MADDy(VURegs *vuRegs, int info); +void recVUMI_MADDz(VURegs *vuRegs, int info); +void recVUMI_MADDw(VURegs *vuRegs, int info); +void recVUMI_MADDA(VURegs *vuRegs, int info); +void recVUMI_MADDAi(VURegs *vuRegs, int info); +void recVUMI_MADDAq(VURegs *vuRegs, int info); +void recVUMI_MADDAx(VURegs *vuRegs, int info); +void recVUMI_MADDAy(VURegs *vuRegs, int info); +void recVUMI_MADDAz(VURegs *vuRegs, int info); +void recVUMI_MADDAw(VURegs *vuRegs, int info); +void recVUMI_MSUB(VURegs *vuRegs, int info); +void recVUMI_MSUBi(VURegs *vuRegs, int info); +void recVUMI_MSUBq(VURegs *vuRegs, int info); +void recVUMI_MSUBx(VURegs *vuRegs, int info); +void recVUMI_MSUBy(VURegs *vuRegs, int info); +void recVUMI_MSUBz(VURegs *vuRegs, int info); +void recVUMI_MSUBw(VURegs *vuRegs, int info); +void recVUMI_MSUBA(VURegs *vuRegs, int info); +void recVUMI_MSUBAi(VURegs *vuRegs, int info); +void recVUMI_MSUBAq(VURegs *vuRegs, int info); +void recVUMI_MSUBAx(VURegs *vuRegs, int info); +void recVUMI_MSUBAy(VURegs *vuRegs, int info); +void recVUMI_MSUBAz(VURegs *vuRegs, int info); +void recVUMI_MSUBAw(VURegs *vuRegs, int info); +void recVUMI_MAX(VURegs *vuRegs, int info); +void recVUMI_MAXi(VURegs *vuRegs, int info); +void recVUMI_MAXx(VURegs *vuRegs, int info); +void recVUMI_MAXy(VURegs *vuRegs, int info); +void recVUMI_MAXz(VURegs *vuRegs, int info); +void recVUMI_MAXw(VURegs *vuRegs, int info); +void recVUMI_MINI(VURegs *vuRegs, int info); +void recVUMI_MINIi(VURegs *vuRegs, int info); +void recVUMI_MINIx(VURegs *vuRegs, int info); +void recVUMI_MINIy(VURegs *vuRegs, int info); +void recVUMI_MINIz(VURegs *vuRegs, int info); +void recVUMI_MINIw(VURegs *vuRegs, int info); +void recVUMI_OPMULA(VURegs *vuRegs, int info); +void recVUMI_OPMSUB(VURegs *vuRegs, int info); +void recVUMI_NOP(VURegs *vuRegs, int info); +void recVUMI_FTOI0(VURegs *vuRegs, int info); +void recVUMI_FTOI4(VURegs *vuRegs, int info); +void recVUMI_FTOI12(VURegs *vuRegs, int info); +void recVUMI_FTOI15(VURegs *vuRegs, int info); +void recVUMI_ITOF0(VURegs *vuRegs, int info); +void recVUMI_ITOF4(VURegs *vuRegs, int info); +void recVUMI_ITOF12(VURegs *vuRegs, int info); +void recVUMI_ITOF15(VURegs *vuRegs, int info); +void recVUMI_CLIP(VURegs *vuRegs, int info); + +/***************************************** + VU Micromode Lower instructions +*****************************************/ + +void recVUMI_DIV(VURegs *vuRegs, int info); +void recVUMI_SQRT(VURegs *vuRegs, int info); +void recVUMI_RSQRT(VURegs *vuRegs, int info); +void recVUMI_IADD(VURegs *vuRegs, int info); +void recVUMI_IADDI(VURegs *vuRegs, int info); +void recVUMI_IADDIU(VURegs *vuRegs, int info); +void recVUMI_IAND(VURegs *vuRegs, int info); +void recVUMI_IOR(VURegs *vuRegs, int info); +void recVUMI_ISUB(VURegs *vuRegs, int info); +void recVUMI_ISUBIU(VURegs *vuRegs, int info); +void recVUMI_MOVE(VURegs *vuRegs, int info); +void recVUMI_MFIR(VURegs *vuRegs, int info); +void recVUMI_MTIR(VURegs *vuRegs, int info); +void recVUMI_MR32(VURegs *vuRegs, int info); +void recVUMI_LQ(VURegs *vuRegs, int info); +void recVUMI_LQD(VURegs *vuRegs, int info); +void recVUMI_LQI(VURegs *vuRegs, int info); +void recVUMI_SQ(VURegs *vuRegs, int info); +void recVUMI_SQD(VURegs *vuRegs, int info); +void recVUMI_SQI(VURegs *vuRegs, int info); +void recVUMI_ILW(VURegs *vuRegs, int info); +void recVUMI_ISW(VURegs *vuRegs, int info); +void recVUMI_ILWR(VURegs *vuRegs, int info); +void recVUMI_ISWR(VURegs *vuRegs, int info); +void recVUMI_LOI(VURegs *vuRegs, int info); +void recVUMI_RINIT(VURegs *vuRegs, int info); +void recVUMI_RGET(VURegs *vuRegs, int info); +void recVUMI_RNEXT(VURegs *vuRegs, int info); +void recVUMI_RXOR(VURegs *vuRegs, int info); +void recVUMI_WAITQ(VURegs *vuRegs, int info); +void recVUMI_FSAND(VURegs *vuRegs, int info); +void recVUMI_FSEQ(VURegs *vuRegs, int info); +void recVUMI_FSOR(VURegs *vuRegs, int info); +void recVUMI_FSSET(VURegs *vuRegs, int info); +void recVUMI_FMAND(VURegs *vuRegs, int info); +void recVUMI_FMEQ(VURegs *vuRegs, int info); +void recVUMI_FMOR(VURegs *vuRegs, int info); +void recVUMI_FCAND(VURegs *vuRegs, int info); +void recVUMI_FCEQ(VURegs *vuRegs, int info); +void recVUMI_FCOR(VURegs *vuRegs, int info); +void recVUMI_FCSET(VURegs *vuRegs, int info); +void recVUMI_FCGET(VURegs *vuRegs, int info); +void recVUMI_IBEQ(VURegs *vuRegs, int info); +void recVUMI_IBGEZ(VURegs *vuRegs, int info); +void recVUMI_IBGTZ(VURegs *vuRegs, int info); +void recVUMI_IBLTZ(VURegs *vuRegs, int info); +void recVUMI_IBLEZ(VURegs *vuRegs, int info); +void recVUMI_IBNE(VURegs *vuRegs, int info); +void recVUMI_B(VURegs *vuRegs, int info); +void recVUMI_BAL(VURegs *vuRegs, int info); +void recVUMI_JR(VURegs *vuRegs, int info); +void recVUMI_JALR(VURegs *vuRegs, int info); +void recVUMI_MFP(VURegs *vuRegs, int info); +void recVUMI_WAITP(VURegs *vuRegs, int info); +void recVUMI_ESADD(VURegs *vuRegs, int info); +void recVUMI_ERSADD(VURegs *vuRegs, int info); +void recVUMI_ELENG(VURegs *vuRegs, int info); +void recVUMI_ERLENG(VURegs *vuRegs, int info); +void recVUMI_EATANxy(VURegs *vuRegs, int info); +void recVUMI_EATANxz(VURegs *vuRegs, int info); +void recVUMI_ESUM(VURegs *vuRegs, int info); +void recVUMI_ERCPR(VURegs *vuRegs, int info); +void recVUMI_ESQRT(VURegs *vuRegs, int info); +void recVUMI_ERSQRT(VURegs *vuRegs, int info); +void recVUMI_ESIN(VURegs *vuRegs, int info); +void recVUMI_EATAN(VURegs *vuRegs, int info); +void recVUMI_EEXP(VURegs *vuRegs, int info); +void recVUMI_XGKICK(VURegs *vuRegs, int info); +void recVUMI_XTOP(VURegs *vuRegs, int info); +void recVUMI_XITOP(VURegs *vuRegs, int info); +void recVUMI_XTOP( VURegs *VU , int info); + +#endif /* __IVUMICRO_H__ */ diff --git a/branches/pcsx2_0.9.1/x86/iVUops.h b/branches/pcsx2_0.9.1/x86/iVUops.h new file mode 100644 index 0000000..79d4a78 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVUops.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define REC_VUOP(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUOPFLAGS(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUBRANCH(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(&VU0); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + MOV32ItoM((u32)&VU.VI[REG_TPC].UL, (u32)pc); \ + CALLFunc((u32)VU##MI_##f); \ + branch = 1; \ +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/iVUzerorec.cpp b/branches/pcsx2_0.9.1/x86/iVUzerorec.cpp new file mode 100644 index 0000000..dcade66 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVUzerorec.cpp @@ -0,0 +1,3639 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Common.h" +#include "ix86/ix86.h" +#include "ir5900.h" +#include "iMMI.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// temporary externs +extern u32 vudump; +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include +using namespace std; + +#ifdef __MSCW32__ + +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// SuperVURec options +#define SUPERVU_CACHING // vu programs are saved and queried via CRC (might query the wrong program) + // disable when in doubt +#define SUPERVU_X86CACHING // use x86reg caching (faster) +#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) + +#define VU_EXESIZE 0x00800000 + +#define _Imm11_ ((s32)(vucode & 0x400 ? 0xfffffc00 | (vucode & 0x3ff) : vucode & 0x3ff)&0x3fff) +#define _UImm11_ ((s32)(vucode & 0x7ff)&0x3fff) + +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +static const u32 QWaitTimes[] = { 6, 12 }; +static const u32 PWaitTimes[] = { 53, 43, 28, 23, 17, 11, 10 }; + +static u32 s_vuInfo; // info passed into rec insts + +static const u32 s_MemSize[2] = {VU0_MEMSIZE, VU1_MEMSIZE}; +static char* s_recVUMem = NULL, *s_recVUPtr = NULL; + +// tables +extern void (*recSVU_UPPER_OPCODE[64])(); +extern void (*recSVU_LOWER_OPCODE[128])(); + +#define INST_Q_READ 0x0001 // flush Q +#define INST_P_READ 0x0002 // flush P +#define INST_BRANCH_DELAY 0x0004 +#define INST_CLIP_WRITE 0x0040 // inst writes CLIP in the future +#define INST_STATUS_WRITE 0x0080 +#define INST_MAC_WRITE 0x0100 +#define INST_Q_WRITE 0x0200 +#define INST_DUMMY_ 0x8000 +#define INST_DUMMY 0x83c0 + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +union VURecRegs +{ + struct { + u16 reg; + u16 type; + }; + u32 id; +}; + +class VuBaseBlock; + +struct VuFunctionHeader +{ + struct RANGE + { + u16 start, size; + u32 checksum[2]; // xor of all the code + }; + + VuFunctionHeader() : pprogfunc(NULL), startpc(0xffffffff) {} + + // returns true if the checksum for the current mem is the same as this fn + bool IsSame(void* pmem); + + u32 startpc; + void* pprogfunc; + + vector ranges; +}; + +struct VuBlockHeader +{ + VuBaseBlock* pblock; + u32 delay; +}; + +// one vu inst (lower and upper) +class VuInstruction +{ +public: + VuInstruction() { memset(this, 0, sizeof(VuInstruction)); nParentPc = -1; } + + int nParentPc; // used for syncing with flag writes, -1 for no parent + + _vuopinfo info; + + _VURegsNum regs[2]; // [0] - lower, [1] - upper + u32 livevars[2]; // live variables right before this inst, [0] - inst, [1] - float + u32 addvars[2]; // live variables to add + u32 usedvars[2]; // set if var is used in the future including vars used in this inst + u32 keepvars[2]; + u16 pqcycles; // the number of cycles to stall if function writes to the regs + u16 type; // INST_ + + u32 pClipWrite, pMACWrite, pStatusWrite; // addrs to write the flags + u32 vffree[2]; + s8 vfwrite[2], vfread0[2], vfread1[2], vfacc[2]; + s8 vfflush[2]; // extra flush regs + + int SetCachedRegs(int upper, u32 vuxyz); + void Recompile(list::const_iterator& itinst, u32 vuxyz); +}; + +#define BLOCKTYPE_EOP 0x01 // at least one of the children of the block contains eop (or the block itself) +#define BLOCKTYPE_FUNCTION 0x02 +#define BLOCKTYPE_HASEOP 0x04 // last inst of block is an eop +#define BLOCKTYPE_MACFLAGS 0x08 +#define BLOCKTYPE_ANALYZED 0x40 +#define BLOCKTYPE_IGNORE 0x80 // special for recursive fns +#define BLOCKTYPE_ANALYZEDPARENT 0x100 + +// base block used when recompiling +class VuBaseBlock +{ +public: + typedef list LISTBLOCKS; + + VuBaseBlock(); + + // returns true if the leads to a EOP (ALL VU blocks must ret true) + void AssignVFRegs(); + void AssignVIRegs(int parent); + + // returns true if only xyz of the reg has been used so far + u32 GetModeXYZW(u32 curpc, int vfreg); + + list::iterator GetInstIterAtPc(int instpc) + { + assert( instpc >= 0 ); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + assert( it != insts.end() ); + return it; + } + + VuInstruction* GetInstAtPc(int instpc) { return &(*GetInstIterAtPc(instpc)); } + + void Recompile(); + + u16 type; // BLOCKTYPE_ + u16 id; + u16 startpc; + u16 endpc; // first inst not in block + void* pcode; // x86 code pointer + int cycles; + list insts; + list parents; + LISTBLOCKS blocks; // blocks branches to + u32* pChildJumps[4]; // addrs that need to be filled with the children's start addrs + // if highest bit is set, addr needs to be relational + u32 vuxyz; // corresponding bit is set if reg's xyz channels are used only + u32 vuxy; // corresponding bit is set if reg's xyz channels are used only + + _xmmregs startregs[XMMREGS], endregs[XMMREGS]; + int nStartx86, nEndx86; // indices into s_vecRegArray + + int allocX86Regs; +}; + +VuBaseBlock::VuBaseBlock() +{ + type = 0; endpc = 0; cycles = 0; pcode = NULL; id = 0; + memset(pChildJumps, 0, sizeof(pChildJumps)); + memset(startregs, 0, sizeof(startregs)); + memset(endregs, 0, sizeof(endregs)); + allocX86Regs = nStartx86 = nEndx86 = -1; +} + +#define SUPERVU_STACKSIZE 0x1000 + +static list s_listVUHeaders[2]; +static list* s_plistCachedHeaders[2]; +static VuFunctionHeader** recVUHeaders[2] = {NULL}; +static VuBlockHeader* recVUBlocks[2] = {NULL}; +static u8* recVUStack = NULL, *recVUStackPtr = NULL; +static vector<_x86regs> s_vecRegArray(128); + +static VURegs* VU = NULL; +static list s_listBlocks; +static u32 s_vu = 0; + +// Global functions +static void* SuperVUGetProgram(u32 startpc, int vuindex); +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex); +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc); +static void SuperVUInitLiveness(VuBaseBlock* pblock); +static void SuperVULivenessAnalysis(); +static void SuperVUEliminateDeadCode(); +static void SuperVUAssignRegs(); + +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg); +#define SuperVUFreeXMMreg 0&& +void SuperVUFreeXMMregs(u32* livevars); + +static u32* SuperVUStaticAlloc(u32 size); +static void SuperVURecompile(); + +// allocate VU resources +void SuperVUInit(int vuindex) +{ + if( vuindex < 0 ) { + s_recVUMem = (char*)SysMmap(0, VU_EXESIZE); + memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + recVUStack = new u8[SUPERVU_STACKSIZE * 4]; + } + else { + recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex]/8]; + recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex]/8]; + s_plistCachedHeaders[vuindex] = new list[s_MemSize[vuindex]/8]; + } +} + +// destroy VU resources +void SuperVUDestroy(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUDestroy(0); + SuperVUDestroy(1); + SysMunmap((uptr)s_recVUMem, VU_EXESIZE); + s_recVUPtr = NULL; + delete[] recVUStack; recVUStack = NULL; + } + else { + delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL; + delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL; + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL; + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// reset VU +void SuperVUReset(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUReset(0); + SuperVUReset(1); + + //memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + + memset(recVUStack, 0, SUPERVU_STACKSIZE); + } + else { + if( recVUHeaders[vuindex] ) memset( recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex]/8) ); + if( recVUBlocks[vuindex] ) memset( recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex]/8) ); + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// clear the block and any joining blocks +void SuperVUClear(u32 startpc, u32 size, int vuindex) +{ + vector::iterator itrange; + list::iterator it = s_listVUHeaders[vuindex].begin(); + u32 endpc = startpc+size; + while( it != s_listVUHeaders[vuindex].end() ) { + + // for every fn, check if it has code in the range + FORIT(itrange, (*it)->ranges) { + if( startpc < (u32)itrange->start+itrange->size && itrange->start < endpc ) + break; + } + + if( itrange != (*it)->ranges.end() ) { + recVUHeaders[vuindex][(*it)->startpc/8] = NULL; +#ifdef SUPERVU_CACHING + list* plist = &s_plistCachedHeaders[vuindex][(*it)->startpc/8]; + plist->push_back(*it); + if( plist->size() > 10 ) { + // list is too big, delete + delete plist->front(); + plist->pop_front(); + } + it = s_listVUHeaders[vuindex].erase(it); +#else + delete *it; + it = s_listVUHeaders[vuindex].erase(it); +#endif + } + else ++it; + } +} + +static VuFunctionHeader* s_pFnHeader = NULL; +static VuBaseBlock* s_pCurBlock = NULL; +static VuInstruction* s_pCurInst = NULL; +static u32 s_StatusRead = 0, s_MACRead = 0, s_ClipRead = 0; // read addrs +static u32 s_PrevStatusWrite = 0, s_PrevClipWrite = 0, s_PrevIWrite = 0; +static u32 s_WriteToReadQ = 0; + +int SuperVUGetLiveness(int vfreg) +{ + assert( s_pCurInst != NULL ); + if( vfreg == 32 ) return ((s_pCurInst->livevars[0]&(1<usedvars[0]&(1<livevars[0]&(1<usedvars[0]&(1<livevars[1]&(1<usedvars[1]&(1<pStatusWrite); + assert(!read || addr != 0); + return addr; + } + case REG_MAC_FLAG: + { + return read ? s_MACRead : s_pCurInst->pMACWrite; + } + case REG_CLIP_FLAG: + { + u32 addr = (read==2) ? s_PrevClipWrite : (read ? s_ClipRead : s_pCurInst->pClipWrite); + assert( !read || addr != 0 ); + return addr; + } + case REG_Q: return (read || s_WriteToReadQ) ? (int)&VU->VI[REG_Q] : (u32)(u32)&VU->q; + case REG_P: return read ? (int)&VU->VI[REG_P] : (u32)(u32)&VU->p; + case REG_I: return s_PrevIWrite; + } + + return (u32)&VU->VI[reg]; +} + +void SuperVUDumpBlock(list& blocks, int vuindex) +{ + FILE *f; + char filename[ 256 ], str[256]; + u32 *mem; + u32 i; + static int gid = 0; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#endif + //SysPrintf( "dump1 %x => %s\n", s_pFnHeader->startpc, filename ); + + f = fopen( filename, "w" ); + + fprintf(f, "Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); + fprintf(f, "Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" + "%.2x - mac_write, %.2x -qflush\n", + INST_Q_READ, INST_P_READ, INST_CLIP_WRITE, INST_STATUS_WRITE, INST_MAC_WRITE, INST_Q_WRITE); + fprintf(f, "XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); + + list::iterator itblock; + list::iterator itinst; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + FORIT(itblock, blocks) { + fprintf(f, "block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', + (*itblock)->startpc, (*itblock)->endpc-8); + FORIT(itchild, (*itblock)->blocks) { + fprintf(f, "%x ", (*itchild)->startpc); + } + fprintf(f, "; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], + (*itblock)->vuxy&(*itblock)->insts.front().usedvars[1]); + + itinst = (*itblock)->insts.begin(); + i = (*itblock)->startpc; + while(itinst != (*itblock)->insts.end() ) { + assert( i <= (*itblock)->endpc ); + if( itinst->type & INST_DUMMY ) { + if( itinst->nParentPc >= 0 && !(itinst->type&INST_DUMMY_)) { + // search for the parent + VuInstruction* p = (*itblock)->GetInstAtPc(itinst->nParentPc); + fprintf(f, "writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); + } + } + else { + mem = (u32*)&VU->Micro[i]; + char* pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%.4x: %-40s", i, pstr); + if( mem[1] & 0x80000000 ) fprintf(f, " I=%f(%.8x)\n", *(float*)mem, mem[0]); + else fprintf(f, "%s\n", disVU1MicroLF( mem[0], i )); + i += 8; + } + + ++itinst; + } + + fprintf(f, "\n"); + + _x86regs* pregs; + if( (*itblock)->nStartx86 >= 0 || (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "X86: AX CX DX BX SP BP SI DI\n"); + } + + if( (*itblock)->nStartx86 >= 0 ) { + pregs = &s_vecRegArray[(*itblock)->nStartx86]; + fprintf(f, "STR: "); + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + if( (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "END: "); + pregs = &s_vecRegArray[(*itblock)->nEndx86]; + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + itinst = (*itblock)->insts.begin(); + for ( i = (*itblock)->startpc; i < (*itblock)->endpc; ++itinst ) { + + if( itinst->type & INST_DUMMY ) { + } + else { + sprintf(str, "%.4x:%x f:%.8x_%.8x", i, itinst->type, itinst->livevars[1], itinst->usedvars[1]); + fprintf(f, "%-46s i:%.8x_%.8x c:%d pq:%d\n", str, + itinst->livevars[0], itinst->usedvars[0], (int)itinst->info.cycle, (int)itinst->pqcycles ); + + sprintf(str, "XMM r0:%d r1:%d w:%d a:%d t:%x;", + itinst->vfread0[1], itinst->vfread1[1], itinst->vfwrite[1], itinst->vfacc[1], itinst->vffree[1]); + fprintf(f, "%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, + itinst->vfread0[0], itinst->vfread1[0], itinst->vfwrite[0], itinst->vfacc[0], itinst->vffree[0]); + i += 8; + } + } + + fprintf(f, "\n---------------\n"); + } + + fclose( f ); +} + +static LARGE_INTEGER svubase, svufinal; +static u32 svutime; + +// uncomment to count svu exec time +//#define SUPERVU_COUNT +u32 SuperVUGetRecTimes(int clear) +{ + u32 temp = svutime; + if( clear ) svutime = 0; + return temp; +} + +// Private methods +static void* SuperVUGetProgram(u32 startpc, int vuindex) +{ + assert( startpc < s_MemSize[vuindex] ); + assert( (startpc%8) == 0 ); + assert( recVUHeaders[vuindex] != NULL ); + VuFunctionHeader** pheader = &recVUHeaders[vuindex][startpc/8]; + + if( *pheader == NULL ) { +#ifdef _DEBUG +// if( vuindex ) VU1.VI[REG_TPC].UL = startpc; +// else VU0.VI[REG_TPC].UL = startpc; +// __Log("VU: %x\n", startpc); +// iDumpVU1Registers(); +// vudump |= 2; +#endif + + // measure run time + //QueryPerformanceCounter(&svubase); + +#ifdef SUPERVU_CACHING + void* pmem = (vuindex&1) ? VU1.Micro : VU0.Micro; + // check if program exists in cache + list::iterator it; + FORIT(it, s_plistCachedHeaders[vuindex][startpc/8]) { + if( (*it)->IsSame(pmem) ) { + // found, transfer to regular lists + void* pfn = (*it)->pprogfunc; + recVUHeaders[vuindex][startpc/8] = *it; + s_listVUHeaders[vuindex].push_back(*it); + s_plistCachedHeaders[vuindex][startpc/8].erase(it); + return pfn; + } + } +#endif + + *pheader = SuperVURecompileProgram(startpc, vuindex); + + //QueryPerformanceCounter(&svufinal); + //svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); + + assert( (*pheader)->pprogfunc != NULL ); + } + + assert( (*pheader)->startpc == startpc ); + + return (*pheader)->pprogfunc; +} + +bool VuFunctionHeader::IsSame(void* pmem) +{ +#ifdef SUPERVU_CACHING + u32 checksum[2]; + vector::iterator it; + FORIT(it, ranges) { + memxor_mmx(checksum, (u8*)pmem+it->start, it->size); + if( checksum[0] != it->checksum[0] || checksum[1] != it->checksum[1] ) + return false; + } +#endif + return true; +} + +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex) +{ + assert( vuindex < 2 ); + assert( s_recVUPtr != NULL ); + //SysPrintf("svu%c rec: %x\n", '0'+vuindex, startpc); + + // if recPtr reached the mem limit reset whole mem + if ( ( (u32)s_recVUPtr - (u32)s_recVUMem ) >= VU_EXESIZE-0x40000 ) { + //SysPrintf("SuperVU reset mem\n"); + SuperVUReset(-1); + } + + list::iterator itblock; + + s_vu = vuindex; + VU = s_vu ? &VU1 : &VU0; + s_pFnHeader = new VuFunctionHeader(); + s_listVUHeaders[vuindex].push_back(s_pFnHeader); + s_pFnHeader->startpc = startpc; + + memset( recVUBlocks[s_vu], 0, sizeof(VuBlockHeader) * (s_MemSize[s_vu]/8) ); + + // analyze the global graph + s_listBlocks.clear(); + SuperVUBuildBlocks(NULL, startpc); + + // fill parents + VuBaseBlock::LISTBLOCKS::iterator itchild; + FORIT(itblock, s_listBlocks) { + FORIT(itchild, (*itblock)->blocks) + (*itchild)->parents.push_back(*itblock); + + //(*itblock)->type &= ~(BLOCKTYPE_IGNORE|BLOCKTYPE_ANALYZED); + } + + assert( s_listBlocks.front()->startpc == startpc ); + s_listBlocks.front()->type |= BLOCKTYPE_FUNCTION; + + FORIT(itblock, s_listBlocks) { + SuperVUInitLiveness(*itblock); + } + + SuperVULivenessAnalysis(); + SuperVUEliminateDeadCode(); + SuperVUAssignRegs(); + +#ifdef _DEBUG + if( (s_vu && (vudump&1)) || (!s_vu && (vudump&16)) ) + SuperVUDumpBlock(s_listBlocks, s_vu); +#endif + + // code generation + x86SetPtr(s_recVUPtr); + _initXMMregs(); + branch = 0; + + SuperVURecompile(); + + s_recVUPtr = x86Ptr; + + // set the function's range + VuFunctionHeader::RANGE r; + s_pFnHeader->ranges.reserve(s_listBlocks.size()); + + FORIT(itblock, s_listBlocks) { + r.start = (*itblock)->startpc; + r.size = (*itblock)->endpc-(*itblock)->startpc; +#ifdef SUPERVU_CACHING + memxor_mmx(r.checksum, &VU->Micro[r.start], r.size); +#endif + s_pFnHeader->ranges.push_back(r); + } + + // destroy + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + delete *itblock; + } + s_listBlocks.clear(); + + assert( s_recVUPtr < s_recVUMem+VU_EXESIZE ); + + return s_pFnHeader; +} + +static int _recbranchAddr(u32 vucode) { + u32 bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + bpc &= (s_MemSize[s_vu]-1); + + return bpc; +} + +struct WRITEBACK +{ + void InitInst(VuInstruction* pinst, int cycle) + { + u32 write = viwrite[0]|viwrite[1]; + pinst->type = ((write&(1<nParentPc = nParentPc; + pinst->info.cycle = cycle; + for(int i = 0; i < 2; ++i) { + pinst->regs[i].VIwrite = viwrite[i]; + pinst->regs[i].VIread = viread[i]; + } + } + + static int SortWritebacks(const WRITEBACK& w1, const WRITEBACK& w2) { + return w1.cycle < w2.cycle; + } + + int nParentPc; + int cycle; + u32 viwrite[2]; + u32 viread[2]; +}; + +// return inst that flushes everything +static VuInstruction SuperVUFlushInst() +{ + VuInstruction inst; + // don't need to raed q/p + inst.type = INST_DUMMY_;//|INST_Q_READ|INST_P_READ; + return inst; +} + +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc) +{ + // check if block already exists + VuBlockHeader* pbh = &recVUBlocks[s_vu][startpc/8]; + if( pbh->pblock != NULL ) { + VuBaseBlock* pblock = pbh->pblock; + if( pblock->startpc == startpc ) + return pblock; + + // have to divide the blocks, pnewblock is first block + assert( startpc > pblock->startpc ); + assert( startpc < pblock->endpc ); + + u32 dummyinst = (startpc-pblock->startpc)>>3; + + // count inst non-dummy insts + list::iterator itinst = pblock->insts.begin(); + u32 inst = 0; + while(dummyinst > 0) { + if( itinst->type & INST_DUMMY ) + ++itinst; + else { + ++itinst; + --dummyinst; + } + } + + // NOTE: still leaves insts with their writebacks in different blocks + while( itinst->type & INST_DUMMY ) + ++itinst; + + int cycleoff = itinst->info.cycle; + + // new block + VuBaseBlock* pnewblock = new VuBaseBlock(); + s_listBlocks.push_back(pnewblock); + + pnewblock->startpc = startpc; + pnewblock->endpc = pblock->endpc; + pnewblock->cycles = pblock->cycles-cycleoff; + + pnewblock->blocks.splice(pnewblock->blocks.end(), pblock->blocks); + pnewblock->insts.splice(pnewblock->insts.end(), pblock->insts, itinst, pblock->insts.end()); + pnewblock->type = pblock->type; + + // any writebacks in the next 3 cycles also belong to original block + for(itinst = pnewblock->insts.begin(); itinst != pnewblock->insts.end(); ) { + if( (itinst->type & INST_DUMMY) && itinst->nParentPc >= 0 && itinst->nParentPc < (int)startpc ) { + + if( !(itinst->type & INST_Q_WRITE) ) + pblock->insts.push_back(*itinst); + itinst = pnewblock->insts.erase(itinst); + continue; + } + + ++itinst; + } + + pbh = &recVUBlocks[s_vu][startpc/8]; + for(u32 inst = startpc; inst < pblock->endpc; inst += 8) { + if( pbh->pblock == pblock ) + pbh->pblock = pnewblock; + ++pbh; + } + + FORIT(itinst, pnewblock->insts) + itinst->info.cycle -= cycleoff; + + // old block + pblock->blocks.push_back(pnewblock); + pblock->endpc = startpc; + pblock->cycles = cycleoff; + pblock->type &= BLOCKTYPE_MACFLAGS;; + //pblock->insts.push_back(SuperVUFlushInst()); //don't need + + return pnewblock; + } + + VuBaseBlock* pblock = new VuBaseBlock(); + s_listBlocks.push_back(pblock); + + int i = 0; + branch = 0; + pc = startpc; + pblock->startpc = startpc; + + // clear stalls (might be a prob) + memset(VU->fmac,0,sizeof(VU->fmac)); + memset(&VU->fdiv,0,sizeof(VU->fdiv)); + memset(&VU->efu,0,sizeof(VU->efu)); + vucycle = 0; + + u8 macflags = 0; + + list< WRITEBACK > listWritebacks; + list< WRITEBACK >::iterator itwriteback; + list::iterator itinst; + u32 hasSecondBranch = 0; + u32 needFullStatusFlag = 0; + + // first analysis pass for status flags + while(1) { + u32* ptr = (u32*)&VU->Micro[pc]; + pc += 8; + int prevbranch = branch; + + if( ptr[1] & 0x40000000 ) + branch = 1; + + if( !(ptr[1] & 0x80000000) ) { // not I + switch( ptr[0]>>25 ) { + case 0x24: // jr + case 0x25: // jalr + case 0x20: // B + case 0x21: // BAL + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + branch = 1; + break; + + case 0x14: // fseq + case 0x17: // fsor + //needFullStatusFlag = 2; + break; + + case 0x16: // fsand + if( (ptr[0]&0xc0) ) { + // sometimes full sticky bits are needed (simple series 2000 - oane chapara) + //SysPrintf("needSticky: %x-%x\n", s_pFnHeader->startpc, startpc); + needFullStatusFlag = 2; + } + break; + } + } + + if( prevbranch ) + break; + + assert( pc < s_MemSize[s_vu] ); + } + + // second full pass + pc = startpc; + branch = 0; + + while(1) { + + if( !branch && pbh->pblock != NULL ) { + pblock->blocks.push_back(pbh->pblock); + break; + } + + int prevbranch = branch; + + if( !prevbranch ) { + pbh->pblock = pblock; + } + else assert( prevbranch || pbh->pblock == NULL); + + pblock->insts.push_back(VuInstruction()); + + VuInstruction* pinst = &pblock->insts.back(); + SuperVUAnalyzeOp(VU, &pinst->info, pinst->regs); + + if( prevbranch ) { + if( pinst->regs[0].pipe == VUPIPE_BRANCH ) + hasSecondBranch = 1; + pinst->type |= INST_BRANCH_DELAY; + } + + // check write back + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ) { + if( pinst->info.cycle >= itwriteback->cycle ) { + itinst = pblock->insts.insert(--pblock->insts.end(), VuInstruction()); + itwriteback->InitInst(&(*itinst), pinst->info.cycle); + itwriteback = listWritebacks.erase(itwriteback); + } + else ++itwriteback; + } + + // add new writebacks + WRITEBACK w = {0}; + const u32 allflags = (1<regs[j].VIwrite & allflags; + + if( pinst->info.macflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.statusflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.macflag|pinst->info.statusflag) & VUOP_READ ) + macflags = 1; + if( pinst->regs[0].VIread & ((1<VIwrite |= lregs->VIwrite & (1<info.statusflag&VUOP_WRITE)&&!(pinst->regs[0].VIwrite&(1<regs[j].VIread & allflags; + + if( (pinst->regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIwrite &= ~allflags; + } + + if( pinst->info.macflag & VUOP_READ) w.viread[1] |= 1<info.statusflag & VUOP_READ) w.viread[1] |= 1<info.cycle+4; + listWritebacks.push_back(w); + } + + if( pinst->info.q&VUOP_READ ) pinst->type |= INST_Q_READ; + if( pinst->info.p&VUOP_READ ) pinst->type |= INST_P_READ; + + if( pinst->info.q&VUOP_WRITE ) { + pinst->pqcycles = QWaitTimes[pinst->info.pqinst]; + + memset(&w, 0, sizeof(w)); + w.nParentPc = pc-8; + w.cycle = pinst->info.cycle+pinst->pqcycles+1; + w.viwrite[0] = 1<info.p&VUOP_WRITE ) + pinst->pqcycles = PWaitTimes[pinst->info.pqinst]; + + if( prevbranch ) + break; + + // make sure there is always a branch + if( (s_vu==1 && i >= 0x798) || (s_vu==0 && i >= 0x198) ) { + SysPrintf("VuRec base block doesn't terminate!\n"); + break; + } + + i++; + pbh++; + } + + if( listWritebacks.size() > 0 ) { + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + } + + if( macflags ) + pblock->type |= BLOCKTYPE_MACFLAGS; + + u32 lastpc = pc; + pblock->endpc = lastpc; + + pblock->cycles = vucycle; + + if( !branch ) + return pblock; + + if( branch & 8 ) { + // what if also a jump? + pblock->type |= BLOCKTYPE_EOP|BLOCKTYPE_HASEOP; + + // add an instruction to flush p and q (if written) + pblock->insts.push_back(SuperVUFlushInst()); + return pblock; + } + + // it is a (cond) branch or a jump + u32 vucode = *(u32*)(VU->Micro+lastpc-16); + int bpc = _recbranchAddr(vucode)-8; + + switch(vucode>>25) { + case 0x24: // jr + pblock->type |= BLOCKTYPE_EOP; // jump out of procedure, since not returning, set EOP + pblock->insts.push_back(SuperVUFlushInst()); + break; + + case 0x25: // jalr + { + // linking, so will return to procedure + pblock->insts.push_back(SuperVUFlushInst()); + + VuBaseBlock* pjumpblock = SuperVUBuildBlocks(pblock, lastpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pjumpblock); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + pbranchblock = SuperVUBuildBlocks(pblock, lastpc); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + break; + } + default: + assert(pblock->blocks.size() == 1); + break; + } + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + if( hasSecondBranch ) { + u32 vucode = *(u32*)(VU->Micro+lastpc-8); + pc = lastpc; + int bpc = _recbranchAddr(vucode); + + switch(vucode>>25) { + case 0x24: // jr + SysPrintf("svurec bad jr jump!\n"); + assert(0); + break; + + case 0x25: // jalr + { + SysPrintf("svurec bad jalr jump!\n"); + assert(0); + break; + } + case 0x20: // B + { + assert(0); + pblock->blocks.clear(); + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + assert(0); + pblock->blocks.clear(); + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + pbranchblock = SuperVUBuildBlocks(pblock, lastpc+8); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + break; + } + default: + assert(0); + } + } + + return recVUBlocks[s_vu][startpc/8].pblock; +} + +static void SuperVUInitLiveness(VuBaseBlock* pblock) +{ + list::iterator itinst, itnext; + + assert( pblock->insts.size() > 0 ); + + for(itinst = pblock->insts.begin(); itinst != pblock->insts.end(); ++itinst) { + + if( itinst->type & INST_DUMMY_ ) { + itinst->addvars[0] = itinst->addvars[1] = 0xffffffff; + itinst->livevars[0] = itinst->livevars[1] = 0xffffffff; + itinst->keepvars[0] = itinst->keepvars[1] = 0xffffffff; + itinst->usedvars[0] = itinst->usedvars[1] = 0; + } + else { + itinst->addvars[0] = itinst->regs[0].VIread | itinst->regs[1].VIread; + itinst->addvars[1] = (itinst->regs[0].VFread0 ? (1 << itinst->regs[0].VFread0) : 0) | + (itinst->regs[0].VFread1 ? (1 << itinst->regs[0].VFread1) : 0) | + (itinst->regs[1].VFread0 ? (1 << itinst->regs[1].VFread0) : 0) | + (itinst->regs[1].VFread1 ? (1 << itinst->regs[1].VFread1) : 0); + + // vf0 is not handled by VFread + if( !itinst->regs[0].VFread0 && (itinst->regs[0].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[1].VFread0 && (itinst->regs[1].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[0].VFread1 && (itinst->regs[0].VIread & (1<regs[0].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + if( !itinst->regs[1].VFread1 && (itinst->regs[1].VIread & (1<regs[1].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + + + u32 vfwrite = 0; + if( itinst->regs[0].VFwrite != 0 ) { + if( itinst->regs[0].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[0].VFwrite; + else vfwrite |= 1<regs[0].VFwrite; + } + if( itinst->regs[1].VFwrite != 0 ) { + if( itinst->regs[1].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[1].VFwrite; + else vfwrite |= 1<regs[1].VFwrite; + } + if( (itinst->regs[1].VIwrite & (1<regs[1].VFwxyzw != 0xf ) + itinst->addvars[1] |= 1<regs[0].VIwrite|itinst->regs[1].VIwrite); + + itinst->usedvars[0] = itinst->addvars[0]|viwrite; + itinst->usedvars[1] = itinst->addvars[1]|vfwrite; + +// itinst->addvars[0] &= ~viwrite; +// itinst->addvars[1] &= ~vfwrite; + itinst->keepvars[0] = ~viwrite; + itinst->keepvars[1] = ~vfwrite; + } + } + + itinst = --pblock->insts.end(); + while( itinst != pblock->insts.begin() ) { + itnext = itinst; --itnext; + + itnext->usedvars[0] |= itinst->usedvars[0]; + itnext->usedvars[1] |= itinst->usedvars[1]; + + itinst = itnext; + } +} + +u32 COMPUTE_LIVE(u32 R, u32 K, u32 L) +{ + u32 live = R | ((L)&(K)); + // speciall process mac and status flags + // only propagate liveness if doesn't write to the flag + if( !(L&(1<::reverse_iterator itblock; + list::iterator itinst, itnext; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + u32 livevars[2]; + + do { + changed = FALSE; + for(itblock = s_listBlocks.rbegin(); itblock != s_listBlocks.rend(); ++itblock) { + + u32 newlive; + VuBaseBlock* pb = *itblock; + + // the last inst relies on the neighbor's insts + itinst = --pb->insts.end(); + + if( pb->blocks.size() > 0 ) { + livevars[0] = 0; livevars[1] = 0; + for( itchild = pb->blocks.begin(); itchild != pb->blocks.end(); ++itchild) { + VuInstruction& front = (*itchild)->insts.front(); + livevars[0] |= front.livevars[0]; + livevars[1] |= front.livevars[1]; + } + + newlive = COMPUTE_LIVE(itinst->addvars[0], itinst->keepvars[0], livevars[0]); + if( itinst->livevars[0] != newlive ) { + changed = TRUE; + itinst->livevars[0] = newlive; + } + + newlive = COMPUTE_LIVE(itinst->addvars[1], itinst->keepvars[1], livevars[1]); + if( itinst->livevars[1] != newlive ) { + changed = TRUE; + itinst->livevars[1] = newlive; + } + } + + while( itinst != pb->insts.begin() ) { + + itnext = itinst; --itnext; + + newlive = COMPUTE_LIVE(itnext->addvars[0], itnext->keepvars[0], itinst->livevars[0]); + + if( itnext->livevars[0] != newlive ) { + changed = TRUE; + itnext->livevars[0] = newlive; + itnext->livevars[1] = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + } + else { + newlive = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + if( itnext->livevars[1] != newlive ) { + changed = TRUE; + itnext->livevars[1] = newlive; + } + } + + itinst = itnext; + } + +// if( (livevars[0] | itinst->livevars[0]) != itinst->livevars[0] ) { +// changed = TRUE; +// itinst->livevars[0] |= livevars[0]; +// } +// if( (livevars[1] | itinst->livevars[1]) != itinst->livevars[1] ) { +// changed = TRUE; +// itinst->livevars[1] |= livevars[1]; +// } +// +// while( itinst != pb->insts.begin() ) { +// +// itnext = itinst; --itnext; +// if( (itnext->livevars[0] | (itinst->livevars[0] & itnext->keepvars[0])) != itnext->livevars[0] ) { +// changed = TRUE; +// itnext->livevars[0] |= itinst->livevars[0] & itnext->keepvars[0]; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// else if( (itnext->livevars[1] | (itinst->livevars[1] & itnext->keepvars[1])) != itnext->livevars[1] ) { +// changed = TRUE; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// +// itinst = itnext; +// } + } + + } while(changed); +} + +static void SuperVUEliminateDeadCode() +{ + list::iterator itblock; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itinst, itnext; + + FORIT(itblock, s_listBlocks) { + +#ifdef _DEBUG + u32 startpc = (*itblock)->startpc; + u32 curpc = startpc; +#endif + + itnext = (*itblock)->insts.begin(); + itinst = itnext++; + while(itnext != (*itblock)->insts.end() ) { + if( itinst->type & INST_DUMMY ) { + itinst->regs[0].VIwrite &= itnext->livevars[0]; + itinst->regs[1].VIwrite &= itnext->livevars[0]; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + VuInstruction* parent = (*itblock)->GetInstAtPc(itinst->nParentPc); + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~INST_CLIP_WRITE; + + if( parent->info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; +// parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_MAC_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; +// parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_STATUS_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type == 0 ) { + itnext = (*itblock)->insts.erase(itinst); + itinst = itnext++; + continue; + } + } +#ifdef _DEBUG + else curpc += 8; +#endif + itinst = itnext; + ++itnext; + } + + if( itinst->type & INST_DUMMY ) { + // last inst with the children + u32 mask = 0; + for(itchild = (*itblock)->blocks.begin(); itchild != (*itblock)->blocks.end(); ++itchild) { + mask |= (*itchild)->insts.front().livevars[0]; + } + itinst->regs[0].VIwrite &= mask; + itinst->regs[1].VIwrite &= mask; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + if( itinst->nParentPc >= 0 ) { + VuInstruction* parent = (*itblock)->GetInstAtPc(itinst->nParentPc); + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~INST_CLIP_WRITE; + + if( parent->info.macflag ) { + if( !(viwrite&(1<info.macflag = 0; + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_MAC_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type&INST_STATUS_WRITE) ); + + if( parent->info.statusflag ) { + if( !(viwrite&(1<info.statusflag = 0; + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<type &= ~INST_STATUS_WRITE; + } + else { + parent->regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type&INST_STATUS_WRITE) ); + + if( itinst->type == 0 ) { + (*itblock)->insts.erase(itinst); + } + } + } + } +} + +// assigns xmm/x86 regs to all instructions, ignore mode field +// returns true if changed +bool AlignStartRegsToEndRegs(_xmmregs* startregs, const list& parents) +{ + list::const_iterator itblock, itblock2; + int bestscore; + _xmmregs bestregs; + bool bchanged = false; + + // find the best merge of regs that minimizes writes/reads + for(int i = 0; i < XMMREGS; ++i) { + + bestscore = 1000; + memset(&bestregs, 0, sizeof(bestregs)); + + FORIT(itblock, parents) { + int curscore = 0; + if( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->endregs[i].inuse ) { + int type = (*itblock)->endregs[i].type; + int reg = (*itblock)->endregs[i].reg; + + FORIT(itblock2, parents) { + if( (*itblock2)->type & BLOCKTYPE_ANALYZED ) { + if( (*itblock2)->endregs[i].inuse ) { + if( (*itblock2)->endregs[i].type != type || (*itblock2)->endregs[i].reg != reg ) { + curscore += 1; + } + } + else curscore++; + } + } + } + + if( curscore < 1 && curscore < bestscore ) { + memcpy(&bestregs, &(*itblock)->endregs[i], sizeof(bestregs)); + bestscore = curscore; + } + } + + if( bestscore < 1 ) { + if( startregs[i].inuse == bestregs.inuse ) { + if( bestregs.inuse && (startregs[i].type != bestregs.type || startregs[i].reg != bestregs.reg) ) + bchanged = true; + } + else bchanged = true; + + memcpy(&startregs[i], &bestregs, sizeof(bestregs)); + FORIT(itblock, parents) memcpy(&(*itblock)->endregs[i], &bestregs, sizeof(bestregs)); + } + else { + if( startregs[i].inuse ) bchanged = true; + startregs[i].inuse = 0; + FORIT(itblock, parents) (*itblock)->endregs[i].inuse = 0; + } + } + + return bchanged; +} + +void VuBaseBlock::AssignVFRegs() +{ + int i; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itblock; + list::iterator itinst, itnext, itinst2; + + // init the start regs + if( type & BLOCKTYPE_ANALYZED ) return; // nothing changed + memcpy(xmmregs, startregs, sizeof(xmmregs)); + + if( type & BLOCKTYPE_ANALYZED ) { + // check if changed + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse != startregs[i].inuse ) + break; + if( xmmregs[i].inuse && (xmmregs[i].reg != startregs[i].reg || xmmregs[i].type != startregs[i].type) ) + break; + } + + if( i == XMMREGS ) return; // nothing changed + } + + s8* oldX86 = x86Ptr; + + FORIT(itinst, insts) { + + if( itinst->type & INST_DUMMY ) + continue; + + // reserve, go from upper to lower + for(i = 1; i >= 0; --i) { + _VURegsNum* regs = itinst->regs+i; + + // redo the counters so that the proper regs are released + for(int j = 0; j < XMMREGS; ++j) { + if( xmmregs[j].inuse ) { + if( xmmregs[j].type == XMMTYPE_VFREG ) { + int count = 0; + itinst2 = itinst; + + if( i ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg ) { + itinst2 = insts.end(); + break; + } + else { + ++count; + ++itinst2; + } + } + + while(itinst2 != insts.end() ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg || + itinst2->regs[1].VFread0 == xmmregs[j].reg || itinst2->regs[1].VFread1 == xmmregs[j].reg || itinst2->regs[1].VFwrite == xmmregs[j].reg) + break; + + ++count; + ++itinst2; + } + xmmregs[j].counter = 1000-count; + } + else { + assert( xmmregs[j].type == XMMTYPE_ACC ); + + int count = 0; + itinst2 = itinst; + + if( i ) ++itinst2; // acc isn't used in lower insts + + while(itinst2 != insts.end() ) { + assert( !((itinst2->regs[0].VIread|itinst2->regs[0].VIwrite) & (1<regs[1].VIread|itinst2->regs[1].VIwrite) & (1<VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<vfread0[i] = itinst->vfread1[i] = itinst->vfwrite[i] = itinst->vfacc[i] = -1; + itinst->vfflush[i] = -1; + + if( regs->VFread0 ) itinst->vfread0[i] = _allocVFtoXMMreg(VU, -1, regs->VFread0, 0); + else if( regs->VIread & (1<vfread0[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VFread1 ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, regs->VFread1, 0); + else if( (regs->VIread & (1<VFr1xyzw != 0xff ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VIread & (1<vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + + int reusereg = -1; // 0 - VFwrite, 1 - VFAcc + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwxyzw == 0xf ) { + itinst->vfwrite[i] = _checkXMMreg(XMMTYPE_VFREG, regs->VFwrite, 0); + if( itinst->vfwrite[i] < 0 ) reusereg = 0; + } + else { + itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + else if( regs->VIwrite & (1<VFwxyzw == 0xf ) { + itinst->vfacc[i] = _checkXMMreg(XMMTYPE_ACC, 0, 0); + if( itinst->vfacc[i] < 0 ) reusereg = 1; + } + else { + itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + } + } + + if( reusereg >= 0 ) { + // reuse + itnext = itinst; itnext++; + + u8 type = reusereg ? XMMTYPE_ACC : XMMTYPE_VFREG; + u8 reg = reusereg ? 0 : regs->VFwrite; + + if( itinst->vfacc[i] >= 0 && ((regs->VIread&(1<usedvars[0]&(1<livevars[0]&(1<livevars[0]&(1<vfacc[i]); + xmmregs[itinst->vfacc[i]].inuse = 1; + xmmregs[itinst->vfacc[i]].reg = reg; + xmmregs[itinst->vfacc[i]].type = type; + xmmregs[itinst->vfacc[i]].mode = 0; + itinst->vfwrite[i] = itinst->vfacc[i]; + } + else if( itinst->vfread0[i] >= 0 && (itnext == insts.end() || (regs->VFread0 > 0 && (!(itnext->usedvars[1]&(1<VFread0)) || !(itnext->livevars[1]&(1<VFread0))))) ) { + if(itnext->livevars[1]®s->VFread0) _freeXMMreg(itinst->vfread0[i]); + xmmregs[itinst->vfread0[i]].inuse = 1; + xmmregs[itinst->vfread0[i]].reg = reg; + xmmregs[itinst->vfread0[i]].type = type; + xmmregs[itinst->vfread0[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread0[i]; + else itinst->vfwrite[i] = itinst->vfread0[i]; + } + else if( itinst->vfread1[i] >= 0 && (regs->VFread1 > 0 && (!(itnext->usedvars[1]&(1<VFread1)) || !(itnext->livevars[1]&(1<VFread1)))) ) { + if(itnext->livevars[1]®s->VFread1) _freeXMMreg(itinst->vfread1[i]); + xmmregs[itinst->vfread1[i]].inuse = 1; + xmmregs[itinst->vfread1[i]].reg = reg; + xmmregs[itinst->vfread1[i]].type = type; + xmmregs[itinst->vfread1[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread1[i]; + else itinst->vfwrite[i] = itinst->vfread1[i]; + } + else { + if( reusereg ) itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + else itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + + // always alloc at least 1 temp reg + int free0 = (i||regs->VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<vfwrite[1] >= 0 && (itinst->vfread0[0]==itinst->vfwrite[1]||itinst->vfread1[0]==itinst->vfwrite[1]) ) { + itinst->vfflush[i] = _allocTempXMMreg(XMMT_FPS, -1); + } + + if( i == 1 && (regs->VIwrite & (1<VIwrite & (1<vfflush[i] >= 0 ) _freeXMMreg(itinst->vfflush[i]); + if( free0 >= 0 ) _freeXMMreg(free0); + + itinst->vffree[i] = (free0&0xf)|(free1<<8)|(free2<<16); + + _clearNeededXMMregs(); + } + } + + assert( x86Ptr == oldX86 ); + u32 analyzechildren = !(type&BLOCKTYPE_ANALYZED); + type |= BLOCKTYPE_ANALYZED; + + //memset(endregs, 0, sizeof(endregs)); + + if( analyzechildren ) { + FORIT(itchild, blocks) (*itchild)->AssignVFRegs(); + } +} + +struct MARKOVBLANKET +{ + list parents; + list children; +}; + +static MARKOVBLANKET s_markov; + +void VuBaseBlock::AssignVIRegs(int parent) +{ + const int maxregs = 6; + + if( parent ) { + if( (type&BLOCKTYPE_ANALYZEDPARENT) ) + return; + + type |= BLOCKTYPE_ANALYZEDPARENT; + s_markov.parents.push_back(this); + for(LISTBLOCKS::iterator it = blocks.begin(); it != blocks.end(); ++it) { + (*it)->AssignVIRegs(0); + } + return; + } + + if( (type&BLOCKTYPE_ANALYZED) ) + return; + + // child + assert( allocX86Regs == -1 ); + allocX86Regs = s_vecRegArray.size(); + s_vecRegArray.resize(allocX86Regs+X86REGS); + + _x86regs* pregs = &s_vecRegArray[allocX86Regs]; + memset(pregs, 0, sizeof(_x86regs)*X86REGS); + + assert( parents.size() > 0 ); + + list::iterator itparent; + u32 usedvars = insts.front().usedvars[0]; + u32 livevars = insts.front().livevars[0]; + + if( parents.size() > 0 ) { + u32 usedvars2 = 0xffffffff; + FORIT(itparent, parents) usedvars2 &= (*itparent)->insts.front().usedvars[0]; + usedvars |= usedvars2; + } + + usedvars &= livevars; + + // currently order doesn't matter + int num = 0; + + if( usedvars ) { + for(int i = 1; i < 16; ++i) { + if( usedvars & (1<= maxregs ) break; + } + } + } + + if( num < maxregs) { + livevars &= ~usedvars; + livevars &= insts.back().usedvars[0]; + + if( livevars ) { + for(int i = 1; i < 16; ++i) { + if( livevars & (1<= maxregs) break; + } + } + } + } + + s_markov.children.push_back(this); + type |= BLOCKTYPE_ANALYZED; + FORIT(itparent, parents) { + (*itparent)->AssignVIRegs(1); + } +} + +u32 VuBaseBlock::GetModeXYZW(u32 curpc, int vfreg) +{ + if( vfreg <= 0 ) return false; + + list::iterator itinst = insts.begin(); + advance(itinst, (curpc-startpc)/8); + + u8 mxy = 1; + u8 mxyz = 1; + + while(itinst != insts.end()) { + for(int i = 0; i < 2; ++i ) { + if( itinst->regs[i].VFwrite == vfreg ) { + if( itinst->regs[i].VFwxyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFwxyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread0 == vfreg ) { + if( itinst->regs[i].VFr0xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr0xyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread1 == vfreg ) { + if( itinst->regs[i].VFr1xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr1xyzw != 0xc ) mxy = 0; + } + + if( !mxy && !mxyz ) return 0; + } + ++itinst; + } + + return (mxy?MODE_VUXY:0)|(mxyz?MODE_VUXYZ:0); +} + +static void SuperVUAssignRegs() +{ + list::iterator itblock, itblock2; + + // assign xyz regs +// FORIT(itblock, s_listBlocks) { +// (*itblock)->vuxyz = 0; +// (*itblock)->vuxy = 0; +// +// for(int i = 0; i < 32; ++i) { +// u32 mode = (*itblock)->GetModeXYZW((*itblock)->startpc, i); +// if( mode & MODE_VUXYZ ) { +// if( mode & MODE_VUZ ) (*itblock)->vuxyz |= 1<vuxy |= 1<type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->AssignVFRegs(); + + // VI assignments, find markov blanket for each node in the graph + // then allocate regs based on the commonly used ones +#ifdef SUPERVU_X86CACHING + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~(BLOCKTYPE_ANALYZED|BLOCKTYPE_ANALYZEDPARENT); + s_vecRegArray.resize(0); + u8 usedregs[16]; + + // note: first block always has to start with no alloc regs + bool bfirst = true; + + FORIT(itblock, s_listBlocks) { + + if( !((*itblock)->type & BLOCKTYPE_ANALYZED) ) { + + if( (*itblock)->parents.size() == 0 ) { + (*itblock)->type |= BLOCKTYPE_ANALYZED; + bfirst = false; + continue; + } + + s_markov.children.clear(); + s_markov.parents.clear(); + (*itblock)->AssignVIRegs(0); + + // assign the regs + int regid = s_vecRegArray.size(); + s_vecRegArray.resize(regid+X86REGS); + + _x86regs* mergedx86 = &s_vecRegArray[regid]; + memset(mergedx86, 0, sizeof(_x86regs)*X86REGS); + + if( !bfirst ) { + *(u32*)usedregs = *((u32*)usedregs+1) = *((u32*)usedregs+2) = *((u32*)usedregs+3) = 0; + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->allocX86Regs >= 0 ); + _x86regs* pregs = &s_vecRegArray[(*itblock2)->allocX86Regs]; + for(int i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse && pregs[i].reg < 16) { + //assert( pregs[i].reg < 16); + usedregs[pregs[i].reg]++; + } + } + } + + int num = 1; + for(int i = 0; i < 16; ++i) { + if( usedregs[i] == s_markov.children.size() ) { + // use + mergedx86[num].inuse = 1; + mergedx86[num].reg = i; + mergedx86[num].type = (s_vu?X86TYPE_VU1:0)|X86TYPE_VI; + mergedx86[num].mode = MODE_READ; + if( ++num >= X86REGS ) + break; + if( num == ESP ) + ++num; + } + } + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->nStartx86 == -1 ); + (*itblock2)->nStartx86 = regid; + } + + FORIT(itblock2, s_markov.parents) { + assert( (*itblock2)->nEndx86 == -1 ); + (*itblock2)->nEndx86 = regid; + } + } + + bfirst = false; + } + } +#endif +} + +////////////////// +// Recompilation +////////////////// +static u32 s_TotalVUCycles; // total cycles since start of program execution + +// cycles in which the last Q,P regs were finished (written to VU->VI[]) +// the write occurs before the instruction is executed at that cycle +// compare with s_TotalVUCycles +// if less than 0, already flushed +static int s_writeQ, s_writeP; +static int s_recWriteQ, s_recWriteP; // wait times during recompilation +static int s_needFlush; // first bit - Q, second bit - P, third bit - Q has been written, fourth bit - P has been written + +static u32 s_vu1ebp, s_vu1esp, s_vu1esi, s_callstack;//, s_vu1esp +static u32 s_ssecsr; +static int s_JumpX86; + +//extern "C" u32 g_sseVUMXCSR; + +// entry point of all vu programs from emulator calls +__declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svubase); +#endif + __asm { + mov eax, dword ptr [esp] + add esp, 4 + mov s_callstack, eax + call SuperVUGetProgram + + // save cpu state + mov s_vu1ebp, ebp + mov s_vu1esi, esi // have to save even in Release + } +#ifdef _DEBUG + __asm { + mov s_vu1esp, esp + } +#endif + + __asm { +// stmxcsr s_ssecsr +// ldmxcsr g_sseVUMXCSR + + // init vars + xor ecx, ecx + mov s_writeQ, 0xffffffff + mov s_writeP, 0xffffffff + mov s_TotalVUCycles, ecx + + jmp eax + } +} + +static void SuperVUCleanupProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +#endif + +#ifdef _DEBUG + assert( s_vu1esp == 0 ); +#endif + + VU = vuindex ? &VU1 : &VU0; + VU->cycle += s_TotalVUCycles; + if( (int)s_writeQ > 0 ) VU->VI[REG_Q] = VU->q; + if( (int)s_writeP > 0 ) { + assert(VU == &VU1); + VU1.VI[REG_P] = VU1.p; // only VU1 + } +} + +// exit point of all vu programs +__declspec(naked) static void SuperVUEndProgram() +{ + __asm { + // restore cpu state + //ldmxcsr s_ssecsr + + mov ebp, s_vu1ebp + mov esi, s_vu1esi + } + +#ifdef _DEBUG + __asm { + sub s_vu1esp, esp + } +#endif + + __asm { + call SuperVUCleanupProgram + jmp s_callstack // so returns correctly + } +} + +// Flushes P/Q regs +void SuperVUFlush(int p, int wait) +{ + u8* pjmp[3]; + if( !(s_needFlush&(1<info.cycle < recwait ) return; + + if( recwait == 0 ) { + // write didn't happen this block + MOV32MtoR(EAX, p ? (u32)&s_writeP : (u32)&s_writeQ); + OR32RtoR(EAX, EAX); + pjmp[0] = JS8(0); + + if( s_pCurInst->info.cycle ) SUB32ItoR(EAX, s_pCurInst->info.cycle); + + // if writeQ <= total+offset + if( !wait ) { // only write back if time is up + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[1] = JG8(0); + } + else { + // add (writeQ-total-offset) to s_TotalVUCycles + // necessary? + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[2] = JLE8(0); + MOV32RtoM((u32)&s_TotalVUCycles, EAX); + x86SetJ8(pjmp[2]); + } + } + else if( wait && s_pCurInst->info.cycle < recwait ) { + MOV32ItoM((u32)&s_TotalVUCycles, recwait); + } + + MOV32MtoR(EAX, SuperVUGetVIAddr(p?REG_P:REG_Q, 0)); + MOV32ItoM(p ? (u32)&s_writeP : (u32)&s_writeQ, 0x80000000); + MOV32RtoM(SuperVUGetVIAddr(p?REG_P:REG_Q, 1), EAX); + + if( recwait == 0 ) { + if( !wait ) x86SetJ8(pjmp[1]); + x86SetJ8(pjmp[0]); + } + + if( wait || (!p && recwait == 0 && s_pCurInst->info.cycle >= 12) || (!p && recwait > 0 && s_pCurInst->info.cycle >= recwait ) ) + s_needFlush &= ~(1<::iterator itblock; + + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->Recompile(); + // make sure everything compiled + FORIT(itblock, s_listBlocks) assert( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->pcode != NULL ); + + // link all blocks + FORIT(itblock, s_listBlocks) { + VuBaseBlock::LISTBLOCKS::iterator itchild; + + assert( (*itblock)->blocks.size() <= ARRAYSIZE((*itblock)->pChildJumps) ); + + int i = 0; + FORIT(itchild, (*itblock)->blocks) { + + if( (u32)(*itblock)->pChildJumps[i] == 0xffffffff ) + continue; + + if( (*itblock)->pChildJumps[i] == NULL ) { + VuBaseBlock* pchild = *itchild; + + if( pchild->type & BLOCKTYPE_HASEOP) { + assert( pchild->blocks.size() == 0); + + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + + MOV32ItoM((u32)&VU->VI[REG_TPC], pchild->endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + // only other case is when there are two branches + else assert( (*itblock)->insts.back().regs[0].pipe == VUPIPE_BRANCH ); + + continue; + } + + if( (u32)(*itblock)->pChildJumps[i] & 0x80000000 ) { + // relative + *(u32*)&(*itblock)->pChildJumps[i] &= 0x7fffffff; + *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode - ((u32)(*itblock)->pChildJumps[i] + 4); + } + else *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode; + + ++i; + } + } + + s_pFnHeader->pprogfunc = s_listBlocks.front()->pcode; +} + +static u32 s_svulast = 0, s_vufnheader; +extern "C" u32 s_vucount = 0; +static u32 lastrec = 0; +static u32 s_saveecx, s_saveedx, s_saveebx, s_saveesi, s_saveedi, s_saveebp; +static u32 badaddrs[][2] = {0,0 }; + +__declspec(naked) static void svudispfn() +{ + static u32 i; + static u32 curvu; + + __asm { + mov curvu, eax + mov s_saveecx, ecx + mov s_saveedx, edx + mov s_saveebx, ebx + mov s_saveesi, esi + mov s_saveedi, edi + mov s_saveebp, ebp + } + +// for(i = 1; i < 32; ++i) { +// if( (VU1.VF[i].UL[3]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[3] &= 0xff7fffff; +// if( (VU1.VF[i].UL[2]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[2] &= 0xff7fffff; +// if( (VU1.VF[i].UL[1]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[1] &= 0xff7fffff; +// if( (VU1.VF[i].UL[0]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[0] &= 0xff7fffff; +// } + + if( (vudump&8) ) { //&& lastrec != g_vu1last ) { + + for(i = 0; i < ARRAYSIZE(badaddrs); ++i) { + if( s_svulast == badaddrs[i][1] && lastrec == badaddrs[i][0] ) + break; + } + + if( i == ARRAYSIZE(badaddrs) ) + { + __Log("tVU: %x\n", s_svulast); + if( curvu ) iDumpVU1Registers(); + else iDumpVU0Registers(); + s_vucount++; + } + + lastrec = s_svulast; + } + + __asm { + mov ecx, s_saveecx + mov edx, s_saveedx + mov ebx, s_saveebx + mov esi, s_saveesi + mov edi, s_saveedi + mov ebp, s_saveebp + ret + } +} + +// frees an xmmreg depending on the liveness info of hte current inst +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg) +//{ +// if( !xmmregs[xmmreg].inuse ) return; +// if( xmmregs[xmmreg].type == xmmtype && xmmregs[xmmreg].reg == reg ) return; +// +// if( s_pNextInst == NULL ) { +// // last inst, free +// _freeXMMreg(xmmreg); +// return; +// } +// +// if( xmmregs[xmmreg].type == XMMTYPE_VFREG ) { +// if( (s_pCurInst->livevars[1]|s_pNextInst->livevars[1]) & (1<livevars[0]|s_pNextInst->livevars[0]) & (1<VF[xmmregs[i].reg] : (u32)&VU->ACC; + + if( xmmregs[i].mode & MODE_VUZ ) { + SSE_MOVHPS_XMM_to_M64(addr, (x86SSERegType)i); + SSE_SHUFPS_M128_to_XMM((x86SSERegType)i, addr, 0xc4); + } + else SSE_MOVHPS_M64_to_XMM((x86SSERegType)i, addr+8); + + xmmregs[i].mode &= ~MODE_VUXYZ; + } + + _freeXMMreg(i); + } + } + } + + //_freeXMMregs(); +} + +//void timeout() { SysPrintf("VU0 timeout\n"); } +void SuperVUTestVU0Condition(u32 incstack) +{ + if( s_vu ) return; // vu0 only + + CMP32ItoM((u32)&s_TotalVUCycles, 512); // sometimes games spin on vu0, so be careful with this value + // woody hangs if too high + + if( incstack ) { + u8* ptr = JB8(0); + + if( incstack ) ADD32ItoR(ESP, incstack); + //CALLFunc((u32)timeout); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + + x86SetJ8(ptr); + } + else { + JAE32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 6 ) ); + } +} + +void VuBaseBlock::Recompile() +{ + if( type & BLOCKTYPE_ANALYZED ) return; + + x86Align(16); + pcode = x86Ptr; + +#ifdef _DEBUG + MOV32ItoM((u32)&s_vufnheader, s_pFnHeader->startpc); + MOV32ItoM((u32)&VU->VI[REG_TPC], startpc); + MOV32ItoM((u32)&s_svulast, startpc); + MOV32ItoR(EAX, s_vu); + CALLFunc((u32)svudispfn); +#endif + + s_pCurBlock = this; + s_needFlush = 3; + pc = startpc; + branch = 0; + s_recWriteQ = s_recWriteP = 0; + + s_ClipRead = s_PrevClipWrite = (u32)&VU->VI[REG_CLIP_FLAG]; + s_StatusRead = s_PrevStatusWrite = (u32)&VU->VI[REG_STATUS_FLAG]; + s_PrevIWrite = (u32)&VU->VI[REG_I]; + s_MACRead = (u32)&VU->VI[REG_MAC_FLAG]; + s_JumpX86 = 0; + + memcpy(xmmregs, startregs, sizeof(xmmregs)); +#ifdef SUPERVU_X86CACHING + if( nStartx86 >= 0 ) + memcpy(x86regs, &s_vecRegArray[nStartx86], sizeof(x86regs)); + else _initX86regs(); +#else + _initX86regs(); +#endif + + list::iterator itinst; + FORIT(itinst, insts) { + s_pCurInst = &(*itinst); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + itinst->Recompile(itinst, vuxyz); + } + assert( pc == endpc ); + + // flush flags + if( s_ClipRead != (u32)&VU->VI[REG_CLIP_FLAG] ) { + MOV32MtoR(EAX, s_ClipRead); + MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + } + if( s_StatusRead != (u32)&VU->VI[REG_STATUS_FLAG] ) { + MOV32MtoR(EAX, s_StatusRead); + MOV32RtoM((u32)&VU->VI[REG_STATUS_FLAG], EAX); + } + if( s_MACRead != (u32)&VU->VI[REG_MAC_FLAG] ) { + MOV32MtoR(EAX, s_MACRead); + MOV32RtoM((u32)&VU->VI[REG_MAC_FLAG], EAX); + } + if( s_PrevIWrite != (u32)&VU->VI[REG_I] ) { + MOV32ItoM((u32)&VU->VI[REG_I], *(u32*)s_PrevIWrite); // never changes + } + + ADD32ItoM((u32)&s_TotalVUCycles, cycles); + + // compute branches, jumps, eop + if( type & BLOCKTYPE_HASEOP ) { + // end + _freeXMMregs(); + _freeX86regs(); + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + if( !branch ) MOV32ItoM((u32)&VU->VI[REG_TPC], endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + else { + + u32 livevars[2] = {0}; + + list::iterator lastinst = GetInstIterAtPc(endpc-8); + lastinst++; + + if( lastinst != insts.end() ) { + livevars[0] = lastinst->livevars[0]; + livevars[1] = lastinst->livevars[1]; + } + else { + // take from children + if( blocks.size() > 0 ) { + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + livevars[0] |= (*itchild)->insts.front().livevars[0]; + livevars[1] |= (*itchild)->insts.front().livevars[1]; + } + } + else { + livevars[0] = ~0; + livevars[1] = ~0; + } + } + + SuperVUFreeXMMregs(livevars); + + // get rid of any writes, otherwise _freeX86regs will write + x86regs[s_JumpX86].mode &= ~MODE_WRITE; + + if( branch == 1 ) { + if( !x86regs[s_JumpX86].inuse ) { + assert( x86regs[s_JumpX86].type == X86TYPE_VUJUMP ); + s_JumpX86 = 0xffffffff; // notify to jump from g_recWriteback + } + } + + // align VI regs +#ifdef SUPERVU_X86CACHING + if( nEndx86 >= 0 ) { + _x86regs* endx86 = &s_vecRegArray[nEndx86]; + for(int i = 0; i < X86REGS; ++i) { + if( endx86[i].inuse ) { + + if( s_JumpX86 == i && x86regs[s_JumpX86].inuse ) { + x86regs[s_JumpX86].inuse = 0; + x86regs[EAX].inuse = 1; + MOV32RtoR(EAX, s_JumpX86); + s_JumpX86 = EAX; + } + + if( x86regs[i].inuse ) { + if( x86regs[i].type == endx86[i].type && x86regs[i].reg == endx86[i].reg ) { + _freeX86reg(i); + // will continue to use it + continue; + } + + if( x86regs[i].type == (X86TYPE_VI|(s_vu?X86TYPE_VU1:0)) ) { +#ifdef SUPERVU_INTERCACHING + if( livevars[0] & (1<Recompile(); + } +} + +#define GET_VUXYZMODE(reg) 0//((vuxyz&(1<<(reg)))?MODE_VUXYZ:0) + +int VuInstruction::SetCachedRegs(int upper, u32 vuxyz) +{ + if( vfread0[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread0[upper], XMMTYPE_VFREG, regs[upper].VFread0); + _allocVFtoXMMreg(VU, vfread0[upper], regs[upper].VFread0, MODE_READ|GET_VUXYZMODE(regs[upper].VFread0)); + } + if( vfread1[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread1[upper], XMMTYPE_VFREG, regs[upper].VFread1); + _allocVFtoXMMreg(VU, vfread1[upper], regs[upper].VFread1, MODE_READ|GET_VUXYZMODE(regs[upper].VFread1)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIread&(1<= 0 ) { + assert( regs[upper].VFwrite > 0); + SuperVUFreeXMMreg(vfwrite[upper], XMMTYPE_VFREG, regs[upper].VFwrite); + _allocVFtoXMMreg(VU, vfwrite[upper], regs[upper].VFwrite, + MODE_WRITE|(regs[upper].VFwxyzw != 0xf?MODE_READ:0)|GET_VUXYZMODE(regs[upper].VFwrite)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIwrite&(1<= 0 ) info |= PROCESS_EE_SET_S(vfread0[upper]); + if( vfread1[upper] >= 0 ) info |= PROCESS_EE_SET_T(vfread1[upper]); + if( vfacc[upper] >= 0 ) info |= PROCESS_VU_SET_ACC(vfacc[upper]); + if( vfwrite[upper] >= 0 ) { + if( regs[upper].VFwrite == _Ft_ && vfread1[upper] < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite[upper]); + } + else { + assert( regs[upper].VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite[upper]); + } + } + + if( (vffree[upper]&0xf) < XMMREGS ) { + SuperVUFreeXMMreg(vffree[upper]&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vffree[upper]&0xf); + } + info |= PROCESS_VU_SET_TEMP(vffree[upper]&0xf); + + if( vfflush[upper] >= 0 ) { + SuperVUFreeXMMreg(vfflush[upper], XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vfflush[upper]); + } + + if( upper && (regs[upper].VIwrite & (1 << REG_CLIP_FLAG)) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + assert( vfwrite[upper] == -1 ); + SuperVUFreeXMMreg((vffree[upper]>>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + + SuperVUFreeXMMreg((vffree[upper]>>16)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>16)&0xf); + info |= PROCESS_EE_SET_ACC((vffree[upper]>>16)&0xf); + + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + _freeXMMreg((vffree[upper]>>16)&0xf); // don't need anymore + } + else if( regs[upper].VIwrite & (1<>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + } + + if( vfflush[upper] >= 0 ) _freeXMMreg(vfflush[upper]); + if( (vffree[upper]&0xf) < XMMREGS ) _freeXMMreg(vffree[upper]&0xf); // don't need anymore + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<::const_iterator& itinst, u32 vuxyz) +{ + __declspec(align(16)) static VECTOR _VF, _VFc; + u32 *ptr; + u8* pjmp; + int vfregstore=0, viregstore=0; + + assert( s_pCurInst == this); + s_WriteToReadQ = 0; + + ptr = (u32*)&VU->Micro[ pc ]; + + if( type & INST_Q_READ ) + SuperVUFlush(0, (ptr[0] == 0x800003bf)||!!(regs[0].VIwrite & (1<GetInstAtPc(nParentPc); + s_ClipRead = parent->pClipWrite; + } + + // before modifying, check if they will ever be read + if( s_pCurBlock->type & BLOCKTYPE_MACFLAGS ) { + if( type & INST_STATUS_WRITE ) { + parent = s_pCurBlock->GetInstAtPc(nParentPc); + s_StatusRead = parent->pStatusWrite; + } + if( type & INST_MAC_WRITE ) { + parent = s_pCurBlock->GetInstAtPc(nParentPc); + s_MACRead = parent->pMACWrite; + } + } + + assert( s_ClipRead != 0 ); + assert( s_MACRead != 0 ); + assert( s_StatusRead != 0 ); + return; + } + +#ifdef _DEBUG +// CMP32ItoM((u32)ptr, ptr[0]); +// j8Ptr[0] = JNE8(0); +// CMP32ItoM((u32)(ptr+1), ptr[1]); +// j8Ptr[1] = JNE8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[0] ); +// x86SetJ8( j8Ptr[1] ); +// PUSH32I(ptr[0]); +// PUSH32I(s_vu); +// PUSH32I(pc); +// CALLFunc((u32)checkvucodefn); +// ADD32ItoR(ESP, 12); +// x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoR(EAX, pc); +#endif + + assert( !(type & (INST_CLIP_WRITE|INST_STATUS_WRITE|INST_MAC_WRITE)) ); + pc += 8; + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<type & BLOCKTYPE_MACFLAGS ) { + pMACWrite = (u32)SuperVUStaticAlloc(4); + pStatusWrite = (u32)SuperVUStaticAlloc(4); + } + else { + assert( s_StatusRead == (u32)&VU->VI[REG_STATUS_FLAG] ); + assert( s_MACRead == (u32)&VU->VI[REG_MAC_FLAG] ); + pMACWrite = s_MACRead; + pStatusWrite = s_StatusRead; + } + } + + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<::const_iterator itinst2; + +#ifdef SUPERVU_X86CACHING + // redo the counters so that the proper regs are released + for(int j = 0; j < X86REGS; ++j) { + if( x86regs[j].inuse && X86_ISVI(x86regs[j].type) ) { + int count = 0; + itinst2 = itinst; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( (itinst2->regs[0].VIread|itinst2->regs[0].VIwrite|itinst2->regs[1].VIread|itinst2->regs[1].VIwrite) && (1<flags, VUFLAG_MFLAGSET); + } + if (ptr[1] & 0x10000000) { // D flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x400:0x004); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x200:0x002); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + if (ptr[1] & 0x08000000) { // T flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x800:0x008); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x400:0x004); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + + assert( !(regs[0].VIwrite & ((1<code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + + s_PrevIWrite = (u32)ptr; + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + else { + if( regs[0].VIwrite & (1<insts.end()); + u32* codeptr2 = ptr+2; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( !(itinst2->type & INST_DUMMY) && ((itinst2->regs[0].VIwrite&(1<type & INST_Q_WRITE) && itinst2->nParentPc == pc-8 ) { + break; + } + if( itinst2->type & INST_Q_READ ) { + cacheq = 1; + break; + } + if( itinst2->type & INST_DUMMY ) { + ++itinst2; + continue; + } + codeptr2 += 2; + ++itinst2; + } + + if( itinst2 == s_pCurBlock->insts.end() ) + cacheq = 1; + + int x86temp = -1; + if( cacheq ) + x86temp = _allocX86reg(-1, X86TYPE_TEMP, 0, 0); + + // new is written so flush old + // if type & INST_Q_READ, already flushed + if( !(type & INST_Q_READ) && s_recWriteQ == 0 ) MOV32MtoR(EAX, (u32)&s_writeQ); + + if( cacheq ) + MOV32MtoR(x86temp, (u32)&s_TotalVUCycles); + + if( !(type & INST_Q_READ) ) { + if( s_recWriteQ == 0 ) { + OR32RtoR(EAX, EAX); + pjmp = JS8(0); + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + x86SetJ8(pjmp); + } + else if( s_needFlush & 1 ) { + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + s_needFlush &= ~1; + } + } + + // write new Q + if( cacheq ) { + assert(s_pCurInst->pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeQ, x86temp); + s_needFlush |= 1; + } + else { + // won't be writing back + s_WriteToReadQ = 1; + s_needFlush &= ~1; + MOV32ItoM((u32)&s_writeQ, 0x80000001); + } + + s_recWriteQ = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + if( x86temp >= 0 ) + _freeX86reg(x86temp); + } + + if( regs[0].VIwrite & (1<pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeP, x86temp); + s_needFlush |= 2; + + s_recWriteP = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + _freeX86reg(x86temp); + } + + if( ptr[0] == 0x800003bf ) // waitq + SuperVUFlush(0, 1); + + if( ptr[0] == 0x800007bf ) // waitp + SuperVUFlush(1, 1); + +#ifdef PCSX2_DEVBUILD + if ( regs[1].VIread & regs[0].VIwrite & ~((1<startpc); + } +#endif + + u32 modewrite = 0; + if( xmmregs[vfwrite[1]].inuse && xmmregs[vfwrite[1]].type == XMMTYPE_VFREG && xmmregs[vfwrite[1]].reg == regs[1].VFwrite ) + modewrite = xmmregs[vfwrite[1]].mode & MODE_WRITE; + + VU->code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + + if (vfwrite[1] >= 0) { + assert( regs[1].VFwrite > 0 ); + + if (vfwrite[0] == vfwrite[1]) { + //SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle %x\n", s_pCurBlock->startpc); + } + + if (vfread0[0] == vfwrite[1] || vfread1[0] == vfwrite[1] ) { + assert( regs[0].VFread0 == regs[1].VFwrite || regs[0].VFread1 == regs[1].VFwrite ); + assert( vfflush[0] >= 0 ); + if( modewrite ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[regs[1].VFwrite], (x86SSERegType)vfwrite[1]); + } + vfregstore = 1; + } + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + + VU->code = ptr[0]; + s_vuInfo = SetCachedRegs(0, vuxyz); + + if( vfregstore ) { + // load + SSE_MOVAPS_M128_to_XMM(vfflush[0], (u32)&VU->VF[regs[1].VFwrite]); + + assert( xmmregs[vfwrite[1]].mode & MODE_WRITE ); + + // replace with vfflush + if( _Fs_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_S(0xf); + s_vuInfo |= PROCESS_EE_SET_S(vfflush[0]); + } + if( _Ft_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_T(0xf); + s_vuInfo |= PROCESS_EE_SET_T(vfflush[0]); + } + + xmmregs[vfflush[0]].mode |= MODE_NOFLUSH|MODE_WRITE; // so that lower inst doesn't flush + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + + recSVU_LOWER_OPCODE[ VU->code >> 25 ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + + // clip is always written so ok + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<code); + int curjump = 0; + + if( s_pCurInst->type & INST_BRANCH_DELAY ) { + assert( (branch&7)!=2 && (branch&7)!=4 ); // no jump handlig for now + + if( (branch & 0x7) == 3 ) { + // previous was a direct jump + curjump = 1; + } + else if( branch & 1 ) curjump = 2; + } + + assert( s_JumpX86 > 0 ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr-1; + + if( !(s_pCurInst->type & INST_BRANCH_DELAY) ) { + j8Ptr[1] = JMP8(0); + x86SetJ8( j8Ptr[ 0 ] ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), pc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr-1; + + x86SetJ8( j8Ptr[ 1 ] ); + } + else + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +// supervu specific insts +void recSVUMI_IBQ_prep() +{ + int fsreg, ftreg; + + if( _Fs_ == 0 ) { + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( ftreg >= 0 ) { + CMP16ItoR( ftreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Ft_, 1), 0); + } + else if( _Ft_ == 0 ) { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR( fsreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Fs_, 1), 0); + } + else { + _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_); + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + if( ftreg >= 0 ) { + CMP16RtoR( fsreg, ftreg ); + } + else CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + else if( ftreg >= 0 ) { + CMP16MtoR(ftreg, SuperVUGetVIAddr(_Fs_, 1)); + } + else { + fsreg = _allocX86reg(-1, X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + } +} + +void recSVUMI_IBEQ() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JNE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + } + + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JLE8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JG8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JNS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBNE() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_B() +{ + // supervu will take care of the rest + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[0] = (u32*)x86Ptr-1; + } + + branch |= 3; +} + +void recSVUMI_BAL() +{ + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[0] = (u32*)x86Ptr-1; + } + + branch |= 3; +} + +void recSVUMI_JR() +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + branch |= 2; +} + +void recSVUMI_JALR() +{ + _addNeededX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_); + + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); // necessary, charlie and chocolate factory gives bad addrs, but graphics are ok + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + + branch |= 4; +} + +#ifdef SUPERVU_COUNT +void StopSVUCounter() +{ + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +} + +void StartSVUCounter() +{ + QueryPerformanceCounter(&svubase); +} +#endif + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 766 ) { +// vudump |= 8; +// } +//} + +void recSVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + _freeX86regs(); + _freeXMMregs(); + + PUSH32R(fsreg); + PUSH32I((int)VU->Mem); + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StopSVUCounter); +#endif + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { + CALLFunc((int)GSgifTransfer1); + } + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StartSVUCounter); +#endif +} + +// upper inst +void recSVUMI_ABS() { recVUMI_ABS(VU, s_vuInfo); } + +void recSVUMI_ADD() { recVUMI_ADD(VU, s_vuInfo); } +void recSVUMI_ADDi() { recVUMI_ADDi(VU, s_vuInfo); } +void recSVUMI_ADDq() { recVUMI_ADDq(VU, s_vuInfo); } +void recSVUMI_ADDx() { recVUMI_ADDx(VU, s_vuInfo); } +void recSVUMI_ADDy() { recVUMI_ADDy(VU, s_vuInfo); } +void recSVUMI_ADDz() { recVUMI_ADDz(VU, s_vuInfo); } +void recSVUMI_ADDw() { recVUMI_ADDw(VU, s_vuInfo); } + +void recSVUMI_ADDA() { recVUMI_ADDA(VU, s_vuInfo); } +void recSVUMI_ADDAi() { recVUMI_ADDAi(VU, s_vuInfo); } +void recSVUMI_ADDAq() { recVUMI_ADDAq(VU, s_vuInfo); } +void recSVUMI_ADDAx() { recVUMI_ADDAx(VU, s_vuInfo); } +void recSVUMI_ADDAy() { recVUMI_ADDAy(VU, s_vuInfo); } +void recSVUMI_ADDAz() { recVUMI_ADDAz(VU, s_vuInfo); } +void recSVUMI_ADDAw() { recVUMI_ADDAw(VU, s_vuInfo); } + +void recSVUMI_SUB() { recVUMI_SUB(VU, s_vuInfo); } +void recSVUMI_SUBi() { recVUMI_SUBi(VU, s_vuInfo); } +void recSVUMI_SUBq() { recVUMI_SUBq(VU, s_vuInfo); } +void recSVUMI_SUBx() { recVUMI_SUBx(VU, s_vuInfo); } +void recSVUMI_SUBy() { recVUMI_SUBy(VU, s_vuInfo); } +void recSVUMI_SUBz() { recVUMI_SUBz(VU, s_vuInfo); } +void recSVUMI_SUBw() { recVUMI_SUBw(VU, s_vuInfo); } + +void recSVUMI_SUBA() { recVUMI_SUBA(VU, s_vuInfo); } +void recSVUMI_SUBAi() { recVUMI_SUBAi(VU, s_vuInfo); } +void recSVUMI_SUBAq() { recVUMI_SUBAq(VU, s_vuInfo); } +void recSVUMI_SUBAx() { recVUMI_SUBAx(VU, s_vuInfo); } +void recSVUMI_SUBAy() { recVUMI_SUBAy(VU, s_vuInfo); } +void recSVUMI_SUBAz() { recVUMI_SUBAz(VU, s_vuInfo); } +void recSVUMI_SUBAw() { recVUMI_SUBAw(VU, s_vuInfo); } + +void recSVUMI_MUL() { recVUMI_MUL(VU, s_vuInfo); } +void recSVUMI_MULi() { recVUMI_MULi(VU, s_vuInfo); } +void recSVUMI_MULq() { recVUMI_MULq(VU, s_vuInfo); } +void recSVUMI_MULx() { recVUMI_MULx(VU, s_vuInfo); } +void recSVUMI_MULy() { recVUMI_MULy(VU, s_vuInfo); } +void recSVUMI_MULz() { recVUMI_MULz(VU, s_vuInfo); } +void recSVUMI_MULw() { recVUMI_MULw(VU, s_vuInfo); } + +void recSVUMI_MULA() { recVUMI_MULA(VU, s_vuInfo); } +void recSVUMI_MULAi() { recVUMI_MULAi(VU, s_vuInfo); } +void recSVUMI_MULAq() { recVUMI_MULAq(VU, s_vuInfo); } +void recSVUMI_MULAx() { recVUMI_MULAx(VU, s_vuInfo); } +void recSVUMI_MULAy() { recVUMI_MULAy(VU, s_vuInfo); } +void recSVUMI_MULAz() { recVUMI_MULAz(VU, s_vuInfo); } +void recSVUMI_MULAw() { recVUMI_MULAw(VU, s_vuInfo); } + +void recSVUMI_MADD() { recVUMI_MADD(VU, s_vuInfo); } +void recSVUMI_MADDi() { recVUMI_MADDi(VU, s_vuInfo); } +void recSVUMI_MADDq() { recVUMI_MADDq(VU, s_vuInfo); } +void recSVUMI_MADDx() { recVUMI_MADDx(VU, s_vuInfo); } +void recSVUMI_MADDy() { recVUMI_MADDy(VU, s_vuInfo); } +void recSVUMI_MADDz() { recVUMI_MADDz(VU, s_vuInfo); } +void recSVUMI_MADDw() { recVUMI_MADDw(VU, s_vuInfo); } + +void recSVUMI_MADDA() { recVUMI_MADDA(VU, s_vuInfo); } +void recSVUMI_MADDAi() { recVUMI_MADDAi(VU, s_vuInfo); } +void recSVUMI_MADDAq() { recVUMI_MADDAq(VU, s_vuInfo); } +void recSVUMI_MADDAx() { recVUMI_MADDAx(VU, s_vuInfo); } +void recSVUMI_MADDAy() { recVUMI_MADDAy(VU, s_vuInfo); } +void recSVUMI_MADDAz() { recVUMI_MADDAz(VU, s_vuInfo); } +void recSVUMI_MADDAw() { recVUMI_MADDAw(VU, s_vuInfo); } + +void recSVUMI_MSUB() { recVUMI_MSUB(VU, s_vuInfo); } +void recSVUMI_MSUBi() { recVUMI_MSUBi(VU, s_vuInfo); } +void recSVUMI_MSUBq() { recVUMI_MSUBq(VU, s_vuInfo); } +void recSVUMI_MSUBx() { recVUMI_MSUBx(VU, s_vuInfo); } +void recSVUMI_MSUBy() { recVUMI_MSUBy(VU, s_vuInfo); } +void recSVUMI_MSUBz() { recVUMI_MSUBz(VU, s_vuInfo); } +void recSVUMI_MSUBw() { recVUMI_MSUBw(VU, s_vuInfo); } + +void recSVUMI_MSUBA() { recVUMI_MSUBA(VU, s_vuInfo); } +void recSVUMI_MSUBAi() { recVUMI_MSUBAi(VU, s_vuInfo); } +void recSVUMI_MSUBAq() { recVUMI_MSUBAq(VU, s_vuInfo); } +void recSVUMI_MSUBAx() { recVUMI_MSUBAx(VU, s_vuInfo); } +void recSVUMI_MSUBAy() { recVUMI_MSUBAy(VU, s_vuInfo); } +void recSVUMI_MSUBAz() { recVUMI_MSUBAz(VU, s_vuInfo); } +void recSVUMI_MSUBAw() { recVUMI_MSUBAw(VU, s_vuInfo); } + +void recSVUMI_MAX() { recVUMI_MAX(VU, s_vuInfo); } +void recSVUMI_MAXi() { recVUMI_MAXi(VU, s_vuInfo); } +void recSVUMI_MAXx() { recVUMI_MAXx(VU, s_vuInfo); } +void recSVUMI_MAXy() { recVUMI_MAXy(VU, s_vuInfo); } +void recSVUMI_MAXz() { recVUMI_MAXz(VU, s_vuInfo); } +void recSVUMI_MAXw() { recVUMI_MAXw(VU, s_vuInfo); } + +void recSVUMI_MINI() { recVUMI_MINI(VU, s_vuInfo); } +void recSVUMI_MINIi() { recVUMI_MINIi(VU, s_vuInfo); } +void recSVUMI_MINIx() { recVUMI_MINIx(VU, s_vuInfo); } +void recSVUMI_MINIy() { recVUMI_MINIy(VU, s_vuInfo); } +void recSVUMI_MINIz() { recVUMI_MINIz(VU, s_vuInfo); } +void recSVUMI_MINIw() { recVUMI_MINIw(VU, s_vuInfo); } + +void recSVUMI_FTOI0() { recVUMI_FTOI0(VU, s_vuInfo); } +void recSVUMI_FTOI4() { recVUMI_FTOI4(VU, s_vuInfo); } +void recSVUMI_FTOI12() { recVUMI_FTOI12(VU, s_vuInfo); } +void recSVUMI_FTOI15() { recVUMI_FTOI15(VU, s_vuInfo); } +void recSVUMI_ITOF0() { recVUMI_ITOF0(VU, s_vuInfo); } +void recSVUMI_ITOF4() { recVUMI_ITOF4(VU, s_vuInfo); } +void recSVUMI_ITOF12() { recVUMI_ITOF12(VU, s_vuInfo); } +void recSVUMI_ITOF15() { recVUMI_ITOF15(VU, s_vuInfo); } + +void recSVUMI_OPMULA() { recVUMI_OPMULA(VU, s_vuInfo); } +void recSVUMI_OPMSUB() { recVUMI_OPMSUB(VU, s_vuInfo); } +void recSVUMI_NOP() { } +void recSVUMI_CLIP() { recVUMI_CLIP(VU, s_vuInfo); } + +// lower inst +void recSVUMI_MTIR() { recVUMI_MTIR(VU, s_vuInfo); } +void recSVUMI_MR32() { recVUMI_MR32(VU, s_vuInfo); } +void recSVUMI_MFIR() { recVUMI_MFIR(VU, s_vuInfo); } +void recSVUMI_MOVE() { recVUMI_MOVE(VU, s_vuInfo); } +void recSVUMI_WAITQ() { recVUMI_WAITQ(VU, s_vuInfo); } +void recSVUMI_MFP() { recVUMI_MFP(VU, s_vuInfo); } +void recSVUMI_WAITP() { recVUMI_WAITP(VU, s_vuInfo); } + +void recSVUMI_SQRT() { recVUMI_SQRT(VU, s_vuInfo); } +void recSVUMI_RSQRT() { recVUMI_RSQRT(VU, s_vuInfo); } +void recSVUMI_DIV() { recVUMI_DIV(VU, s_vuInfo); } + +void recSVUMI_ESADD() { recVUMI_ESADD(VU, s_vuInfo); } +void recSVUMI_ERSADD() { recVUMI_ERSADD(VU, s_vuInfo); } +void recSVUMI_ELENG() { recVUMI_ELENG(VU, s_vuInfo); } +void recSVUMI_ERLENG() { recVUMI_ERLENG(VU, s_vuInfo); } +void recSVUMI_EATANxy() { recVUMI_EATANxy(VU, s_vuInfo); } +void recSVUMI_EATANxz() { recVUMI_EATANxz(VU, s_vuInfo); } +void recSVUMI_ESUM() { recVUMI_ESUM(VU, s_vuInfo); } +void recSVUMI_ERCPR() { recVUMI_ERCPR(VU, s_vuInfo); } +void recSVUMI_ESQRT() { recVUMI_ESQRT(VU, s_vuInfo); } +void recSVUMI_ERSQRT() { recVUMI_ERSQRT(VU, s_vuInfo); } +void recSVUMI_ESIN() { recVUMI_ESIN(VU, s_vuInfo); } +void recSVUMI_EATAN() { recVUMI_EATAN(VU, s_vuInfo); } +void recSVUMI_EEXP() { recVUMI_EEXP(VU, s_vuInfo); } + +void recSVUMI_XITOP() { recVUMI_XITOP(VU, s_vuInfo); } +void recSVUMI_XGKICK() { recSVUMI_XGKICK(VU, s_vuInfo); } +void recSVUMI_XTOP() { recVUMI_XTOP(VU, s_vuInfo); } + +void recSVUMI_RINIT() { recVUMI_RINIT(VU, s_vuInfo); } +void recSVUMI_RGET() { recVUMI_RGET(VU, s_vuInfo); } +void recSVUMI_RNEXT() { recVUMI_RNEXT(VU, s_vuInfo); } +void recSVUMI_RXOR() { recVUMI_RXOR(VU, s_vuInfo); } + +void recSVUMI_FSAND() { recVUMI_FSAND(VU, s_vuInfo); } +void recSVUMI_FSEQ() { recVUMI_FSEQ(VU, s_vuInfo); } +void recSVUMI_FSOR() { recVUMI_FSOR(VU, s_vuInfo); } +void recSVUMI_FSSET() { recVUMI_FSSET(VU, s_vuInfo); } +void recSVUMI_FMEQ() { recVUMI_FMEQ(VU, s_vuInfo); } +void recSVUMI_FMOR() { recVUMI_FMOR(VU, s_vuInfo); } +void recSVUMI_FCEQ() { recVUMI_FCEQ(VU, s_vuInfo); } +void recSVUMI_FCOR() { recVUMI_FCOR(VU, s_vuInfo); } +void recSVUMI_FCSET() { recVUMI_FCSET(VU, s_vuInfo); } +void recSVUMI_FCGET() { recVUMI_FCGET(VU, s_vuInfo); } +void recSVUMI_FCAND() { recVUMI_FCAND(VU, s_vuInfo); } +void recSVUMI_FMAND() { recVUMI_FMAND(VU, s_vuInfo); } + +void recSVUMI_LQ() { recVUMI_LQ(VU, s_vuInfo); } +void recSVUMI_LQD() { recVUMI_LQD(VU, s_vuInfo); } +void recSVUMI_LQI() { recVUMI_LQI(VU, s_vuInfo); } +void recSVUMI_SQ() { recVUMI_SQ(VU, s_vuInfo); } +void recSVUMI_SQD() { recVUMI_SQD(VU, s_vuInfo); } +void recSVUMI_SQI() { recVUMI_SQI(VU, s_vuInfo); } +void recSVUMI_ILW() { recVUMI_ILW(VU, s_vuInfo); } +void recSVUMI_ISW() { recVUMI_ISW(VU, s_vuInfo); } +void recSVUMI_ILWR() { recVUMI_ILWR(VU, s_vuInfo); } +void recSVUMI_ISWR() { recVUMI_ISWR(VU, s_vuInfo); } + +void recSVUMI_IADD() { recVUMI_IADD(VU, s_vuInfo); } +void recSVUMI_IADDI() { recVUMI_IADDI(VU, s_vuInfo); } +void recSVUMI_IADDIU() { recVUMI_IADDIU(VU, s_vuInfo); } +void recSVUMI_IOR() { recVUMI_IOR(VU, s_vuInfo); } +void recSVUMI_ISUB() { recVUMI_ISUB(VU, s_vuInfo); } +void recSVUMI_IAND() { recVUMI_IAND(VU, s_vuInfo); } +void recSVUMI_ISUBIU() { recVUMI_ISUBIU(VU, s_vuInfo); } + +void recSVU_UPPER_FD_00( void ); +void recSVU_UPPER_FD_01( void ); +void recSVU_UPPER_FD_10( void ); +void recSVU_UPPER_FD_11( void ); +void recSVULowerOP( void ); +void recSVULowerOP_T3_00( void ); +void recSVULowerOP_T3_01( void ); +void recSVULowerOP_T3_10( void ); +void recSVULowerOP_T3_11( void ); +void recSVUunknown( void ); + +void (*recSVU_LOWER_OPCODE[128])() = { + recSVUMI_LQ , recSVUMI_SQ , recSVUunknown , recSVUunknown, + recSVUMI_ILW , recSVUMI_ISW , recSVUunknown , recSVUunknown, + recSVUMI_IADDIU, recSVUMI_ISUBIU, recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_FCEQ , recSVUMI_FCSET , recSVUMI_FCAND, recSVUMI_FCOR, /* 0x10 */ + recSVUMI_FSEQ , recSVUMI_FSSET , recSVUMI_FSAND, recSVUMI_FSOR, + recSVUMI_FMEQ , recSVUunknown , recSVUMI_FMAND, recSVUMI_FMOR, + recSVUMI_FCGET , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_B , recSVUMI_BAL , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUMI_JR , recSVUMI_JALR , recSVUunknown , recSVUunknown, + recSVUMI_IBEQ , recSVUMI_IBNE , recSVUunknown , recSVUunknown, + recSVUMI_IBLTZ , recSVUMI_IBGTZ , recSVUMI_IBLEZ, recSVUMI_IBGEZ, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x40*/ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x50 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x60 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x70 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, +}; + +void (*recSVULowerOP_T3_00_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MOVE , recSVUMI_LQI , recSVUMI_DIV , recSVUMI_MTIR, + recSVUMI_RNEXT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_MFP , recSVUMI_XTOP , recSVUMI_XGKICK, + recSVUMI_ESADD , recSVUMI_EATANxy, recSVUMI_ESQRT, recSVUMI_ESIN, +}; + +void (*recSVULowerOP_T3_01_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MR32 , recSVUMI_SQI , recSVUMI_SQRT , recSVUMI_MFIR, + recSVUMI_RGET , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUMI_XITOP, recSVUunknown, + recSVUMI_ERSADD, recSVUMI_EATANxz, recSVUMI_ERSQRT, recSVUMI_EATAN, +}; + +void (*recSVULowerOP_T3_10_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_LQD , recSVUMI_RSQRT, recSVUMI_ILWR, + recSVUMI_RINIT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ELENG , recSVUMI_ESUM , recSVUMI_ERCPR, recSVUMI_EEXP, +}; + +void (*recSVULowerOP_T3_11_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_SQD , recSVUMI_WAITQ, recSVUMI_ISWR, + recSVUMI_RXOR , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ERLENG, recSVUunknown , recSVUMI_WAITP, recSVUunknown, +}; + +void (*recSVULowerOP_OPCODE[64])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_IADD , recSVUMI_ISUB , recSVUMI_IADDI, recSVUunknown, /* 0x30 */ + recSVUMI_IAND , recSVUMI_IOR , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP_T3_00, recSVULowerOP_T3_01, recSVULowerOP_T3_10, recSVULowerOP_T3_11, +}; + +void (*recSVU_UPPER_OPCODE[64])() = { + recSVUMI_ADDx , recSVUMI_ADDy , recSVUMI_ADDz , recSVUMI_ADDw, + recSVUMI_SUBx , recSVUMI_SUBy , recSVUMI_SUBz , recSVUMI_SUBw, + recSVUMI_MADDx , recSVUMI_MADDy , recSVUMI_MADDz , recSVUMI_MADDw, + recSVUMI_MSUBx , recSVUMI_MSUBy , recSVUMI_MSUBz , recSVUMI_MSUBw, + recSVUMI_MAXx , recSVUMI_MAXy , recSVUMI_MAXz , recSVUMI_MAXw, /* 0x10 */ + recSVUMI_MINIx , recSVUMI_MINIy , recSVUMI_MINIz , recSVUMI_MINIw, + recSVUMI_MULx , recSVUMI_MULy , recSVUMI_MULz , recSVUMI_MULw, + recSVUMI_MULq , recSVUMI_MAXi , recSVUMI_MULi , recSVUMI_MINIi, + recSVUMI_ADDq , recSVUMI_MADDq , recSVUMI_ADDi , recSVUMI_MADDi, /* 0x20 */ + recSVUMI_SUBq , recSVUMI_MSUBq , recSVUMI_SUBi , recSVUMI_MSUBi, + recSVUMI_ADD , recSVUMI_MADD , recSVUMI_MUL , recSVUMI_MAX, + recSVUMI_SUB , recSVUMI_MSUB , recSVUMI_OPMSUB, recSVUMI_MINI, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVU_UPPER_FD_00, recSVU_UPPER_FD_01, recSVU_UPPER_FD_10, recSVU_UPPER_FD_11, +}; + +void (*recSVU_UPPER_FD_00_TABLE[32])() = { + recSVUMI_ADDAx, recSVUMI_SUBAx , recSVUMI_MADDAx, recSVUMI_MSUBAx, + recSVUMI_ITOF0, recSVUMI_FTOI0, recSVUMI_MULAx , recSVUMI_MULAq , + recSVUMI_ADDAq, recSVUMI_SUBAq, recSVUMI_ADDA , recSVUMI_SUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_01_TABLE[32])() = { + recSVUMI_ADDAy , recSVUMI_SUBAy , recSVUMI_MADDAy, recSVUMI_MSUBAy, + recSVUMI_ITOF4 , recSVUMI_FTOI4 , recSVUMI_MULAy , recSVUMI_ABS , + recSVUMI_MADDAq, recSVUMI_MSUBAq, recSVUMI_MADDA , recSVUMI_MSUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_10_TABLE[32])() = { + recSVUMI_ADDAz , recSVUMI_SUBAz , recSVUMI_MADDAz, recSVUMI_MSUBAz, + recSVUMI_ITOF12, recSVUMI_FTOI12, recSVUMI_MULAz , recSVUMI_MULAi , + recSVUMI_MADDAi, recSVUMI_SUBAi , recSVUMI_MULA , recSVUMI_OPMULA, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_11_TABLE[32])() = { + recSVUMI_ADDAw , recSVUMI_SUBAw , recSVUMI_MADDAw, recSVUMI_MSUBAw, + recSVUMI_ITOF15, recSVUMI_FTOI15, recSVUMI_MULAw , recSVUMI_CLIP , + recSVUMI_MADDAi, recSVUMI_MSUBAi, recSVUunknown , recSVUMI_NOP , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void recSVU_UPPER_FD_00( void ) +{ + recSVU_UPPER_FD_00_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_01( void ) +{ + recSVU_UPPER_FD_01_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_10( void ) +{ + recSVU_UPPER_FD_10_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_11( void ) +{ + recSVU_UPPER_FD_11_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP( void ) +{ + recSVULowerOP_OPCODE[ VU->code & 0x3f ]( ); +} + +void recSVULowerOP_T3_00( void ) +{ + recSVULowerOP_T3_00_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_01( void ) +{ + recSVULowerOP_T3_01_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_10( void ) +{ + recSVULowerOP_T3_10_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_11( void ) +{ + recSVULowerOP_T3_11_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVUunknown( void ) +{ + SysPrintf("Unknown SVU micromode opcode called\n"); +} diff --git a/branches/pcsx2_0.9.1/x86/iVUzerorec.h b/branches/pcsx2_0.9.1/x86/iVUzerorec.h new file mode 100644 index 0000000..1592252 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/iVUzerorec.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#ifndef VU1_SUPER_RECOMPILER +#define VU1_SUPER_RECOMPILER + +#ifdef __cplusplus +extern "C" { +#endif + +void SuperVUInit(int vuindex); // if vuindex is -1, inits the global VU resources +void SuperVUDestroy(int vuindex); // if vuindex is -1, destroys everything +void SuperVUReset(int vuindex); // if vuindex is -1, resets everything + +void SuperVUExecuteProgram(u32 startpc, int vuindex); +void SuperVUClear(u32 startpc, u32 size, int vuindex); + +u32 SuperVUGetRecTimes(int clear); + +// read = 0, will write to reg +// read = 1, will read from reg +// read = 2, addr of previously written reg (used for status and clip flags) +u32 SuperVUGetVIAddr(int reg, int read); + +// if p == 0, flush q else flush p; if wait is != 0, waits for p/q +void SuperVUFlush(int p, int wait); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.1/x86/ir5900tables.c b/branches/pcsx2_0.9.1/x86/ir5900tables.c new file mode 100644 index 0000000..293abe7 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ir5900tables.c @@ -0,0 +1,1362 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Holds instruction tables for the r5900 recompiler + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" + +//////////////////////////////////////////////////// +static void recNULL( void ) +{ + SysPrintf("EE: Unimplemented op %x\n", cpuRegs.code); +} + +//////////////////////////////////////////////////// +static void recREGIMM( void ) +{ + recREG[ _Rt_ ]( ); +} + +//////////////////////////////////////////////////// +static void recSPECIAL( void ) +{ + recSPC[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0( void ) +{ + recCP0[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0BC0( void ) +{ + recCP0BC0[ ( cpuRegs.code >> 16 ) & 0x03 ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0C0( void ) +{ + recCP0C0[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP1( void ) { + recCP1[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recMMI( void ) +{ + recMMIt[ _Funct_ ]( ); +} + + +/********************************************************** +* UNHANDLED YET OPCODES +* +**********************************************************/ + +//////////////////////////////////////////////////// +//REC_SYS(PREF); +//////////////////////////////////////////////////// +//REC_SYS(MFSA); +//////////////////////////////////////////////////// +//REC_SYS(MTSA); +//////////////////////////////////////////////////// +REC_SYS(TGE); +//////////////////////////////////////////////////// +REC_SYS(TGEU); +//////////////////////////////////////////////////// +REC_SYS(TLT); +//////////////////////////////////////////////////// +REC_SYS(TLTU); +//////////////////////////////////////////////////// +REC_SYS(TEQ); +//////////////////////////////////////////////////// +REC_SYS(TNE); +//////////////////////////////////////////////////// +REC_SYS(TGEI); +//////////////////////////////////////////////////// +REC_SYS(TGEIU); +//////////////////////////////////////////////////// +REC_SYS(TLTI); +//////////////////////////////////////////////////// +REC_SYS(TLTIU); +//////////////////////////////////////////////////// +REC_SYS(TEQI); +//////////////////////////////////////////////////// +REC_SYS(TNEI); +//////////////////////////////////////////////////// +//REC_SYS(MTSAB); +//////////////////////////////////////////////////// +//REC_SYS(MTSAH); + + +//////////////////////////////////////////////////// +static void recCACHE( void ) { +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (u32)CACHE ); +// //branch = 2; +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// RET(); +// x86SetJ8(j8Ptr[0]); +} + + +static void recPREF( void ) +{ +} + + + +//////////////////////////////////////////////////// +static void recSYNC( void ) +{ +} + +static void recMFSA( void ) +{ + int mmreg; + if (!_Rd_) return; + + mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + if( mmreg >= 0 ) { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.sa); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.sa); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + _deleteEEreg(_Rd_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + } +} + +static void recMTSA( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + } + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.sa, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&cpuRegs.sa, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } + } +} + +/* +void recTGE( void ) +{ +} + +void recTGEU( void ) +{ +} + +void recTLT( void ) +{ +} + +void recTLTU( void ) +{ +} + +void recTEQ( void ) +{ +} + +void recTNE( void ) +{ +} + +void recTGEI( void ) +{ +} + +void recTGEIU( void ) +{ +} + +void recTLTI( void ) +{ +} + +void recTLTIU( void ) +{ +} + +void recTEQI( void ) +{ +} + +void recTNEI( void ) +{ +} + +*/ +static void recMTSAB( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0xF); + MOV32ItoR(ECX, _Imm_); + AND32ItoR(ECX, 0xF); + XOR32RtoR(EAX, ECX); + SHL32ItoR(EAX, 3); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +static void recMTSAH( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0x7); + MOV32ItoR(ECX, _Imm_); + AND32ItoR(ECX, 0x7); + XOR32RtoR(EAX, ECX); + SHL32ItoR(EAX, 4); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +///////////////////////////////// +// Foward-Prob Function Tables // +///////////////////////////////// +extern void recCOP2( void ); +extern void recSYSCALL( void ); +extern void recBREAK( void ); + +void (*recBSC[64] )() = { + recSPECIAL, recREGIMM, recJ, recJAL, recBEQ, recBNE, recBLEZ, recBGTZ, + recADDI, recADDIU, recSLTI, recSLTIU, recANDI, recORI, recXORI, recLUI, + recCOP0, recCOP1, recCOP2, recNULL, recBEQL, recBNEL, recBLEZL, recBGTZL, + recDADDI, recDADDIU, recLDL, recLDR, recMMI, recNULL, recLQ, recSQ, + recLB, recLH, recLWL, recLW, recLBU, recLHU, recLWR, recLWU, + recSB, recSH, recSWL, recSW, recSDL, recSDR, recSWR, recCACHE, + recNULL, recLWC1, recNULL, recPREF, recNULL, recNULL, recLQC2, recLD, + recNULL, recSWC1, recNULL, recNULL, recNULL, recNULL, recSQC2, recSD +}; + +#ifdef WIN32_VIRTUAL_MEM +// coissued insts +void (*recBSC_co[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recLDL_co, recLDR_co, recNULL, recNULL, recLQ_co, recSQ_co, + recLB_co, recLH_co, recLWL_co, recLW_co, recLBU_co, recLHU_co, recLWR_co, recLWU_co, + recSB_co, recSH_co, recSWL_co, recSW_co, recSDL_co, recSDR_co, recSWR_co, recNULL, + recNULL, recLWC1_co, recNULL, recNULL, recNULL, recNULL, recLQC2_co, recLD_co, + recNULL, recSWC1_co, recNULL, recNULL, recNULL, recNULL, recSQC2_co, recSD_co +}; +#endif + +void (*recSPC[64] )() = { + recSLL, recNULL, recSRL, recSRA, recSLLV, recNULL, recSRLV, recSRAV, + recJR, recJALR, recMOVZ, recMOVN, recSYSCALL, recBREAK, recNULL, recSYNC, + recMFHI, recMTHI, recMFLO, recMTLO, recDSLLV, recNULL, recDSRLV, recDSRAV, + recMULT, recMULTU, recDIV, recDIVU, recNULL, recNULL, recNULL, recNULL, + recADD, recADDU, recSUB, recSUBU, recAND, recOR, recXOR, recNOR, + recMFSA, recMTSA, recSLT, recSLTU, recDADD, recDADDU, recDSUB, recDSUBU, + recTGE, recTGEU, recTLT, recTLTU, recTEQ, recNULL, recTNE, recNULL, + recDSLL, recNULL, recDSRL, recDSRA, recDSLL32, recNULL, recDSRL32, recDSRA32 +}; + +void (*recREG[32] )() = { + recBLTZ, recBGEZ, recBLTZL, recBGEZL, recNULL, recNULL, recNULL, recNULL, + recTGEI, recTGEIU, recTLTI, recTLTIU, recTEQI, recNULL, recTNEI, recNULL, + recBLTZAL, recBGEZAL, recBLTZALL, recBGEZALL, recNULL, recNULL, recNULL, recNULL, + recMTSAB, recMTSAH, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0[32] )() = { + recMFC0, recNULL, recNULL, recNULL, recMTC0, recNULL, recNULL, recNULL, + recCOP0BC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP0C0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0BC0[32] )() = { + recBC0F, recBC0T, recBC0FL, recBC0TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0C0[64] )() = { + recNULL, recTLBR, recTLBWI, recNULL, recNULL, recNULL, recTLBWR, recNULL, + recTLBP, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recERET, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recEI, recDI, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1[32] )() = { + recMFC1, recNULL, recCFC1, recNULL, recMTC1, recNULL, recCTC1, recNULL, + recCOP1_BC1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP1_S, recNULL, recNULL, recNULL, recCOP1_W, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1BC1[32] )() = { + recBC1F, recBC1T, recBC1FL, recBC1TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1S[64] )() = { + recADD_S, recSUB_S, recMUL_S, recDIV_S, recSQRT_S, recABS_S, recMOV_S, recNEG_S, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recRSQRT_S, recNULL, + recADDA_S, recSUBA_S, recMULA_S, recNULL, recMADD_S, recMSUB_S, recMADDA_S, recMSUBA_S, + recNULL, recNULL, recNULL, recNULL, recCVT_W, recNULL, recNULL, recNULL, + recMAX_S, recMIN_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recC_F, recNULL, recC_EQ, recNULL, recC_LT, recNULL, recC_LE, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1W[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCVT_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMIt[64] )() = { + recMADD, recMADDU, recNULL, recNULL, recPLZCW, recNULL, recNULL, recNULL, + recMMI0, recMMI2, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMFHI1, recMTHI1, recMFLO1, recMTLO1, recNULL, recNULL, recNULL, recNULL, + recMULT1, recMULTU1, recDIV1, recDIVU1, recNULL, recNULL, recNULL, recNULL, + recMADD1, recMADDU1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMMI1 , recMMI3, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recPMFHL, recPMTHL, recNULL, recNULL, recPSLLH, recNULL, recPSRLH, recPSRAH, + recNULL, recNULL, recNULL, recNULL, recPSLLW, recNULL, recPSRLW, recPSRAW, +}; + +void (*recMMI0t[32] )() = { + recPADDW, recPSUBW, recPCGTW, recPMAXW, + recPADDH, recPSUBH, recPCGTH, recPMAXH, + recPADDB, recPSUBB, recPCGTB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDSW, recPSUBSW, recPEXTLW, recPPACW, + recPADDSH, recPSUBSH, recPEXTLH, recPPACH, + recPADDSB, recPSUBSB, recPEXTLB, recPPACB, + recNULL, recNULL, recPEXT5, recPPAC5, +}; + +void (*recMMI1t[32] )() = { + recNULL, recPABSW, recPCEQW, recPMINW, + recPADSBH, recPABSH, recPCEQH, recPMINH, + recNULL, recNULL, recPCEQB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDUW, recPSUBUW, recPEXTUW, recNULL, + recPADDUH, recPSUBUH, recPEXTUH, recNULL, + recPADDUB, recPSUBUB, recPEXTUB, recQFSRV, + recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMI2t[32] )() = { + recPMADDW, recNULL, recPSLLVW, recPSRLVW, + recPMSUBW, recNULL, recNULL, recNULL, + recPMFHI, recPMFLO, recPINTH, recNULL, + recPMULTW, recPDIVW, recPCPYLD, recNULL, + recPMADDH, recPHMADH, recPAND, recPXOR, + recPMSUBH, recPHMSBH, recNULL, recNULL, + recNULL, recNULL, recPEXEH, recPREVH, + recPMULTH, recPDIVBW, recPEXEW, recPROT3W, +}; + +void (*recMMI3t[32] )() = { + recPMADDUW, recNULL, recNULL, recPSRAVW, + recNULL, recNULL, recNULL, recNULL, + recPMTHI, recPMTLO, recPINTEH, recNULL, + recPMULTUW, recPDIVUW, recPCPYUD, recNULL, + recNULL, recNULL, recPOR, recPNOR, + recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recPEXCH, recPCPYH, + recNULL, recNULL, recPEXCW, recNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpropSetRead(reg, mask) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpropSetWrite0(reg, mask, live) { \ + prev->regs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +#define rpropSetWrite(reg, mask) { \ + rpropSetWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +#define rpropSetFast(write1, read1, read2, mask) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ +} \ + +#define rpropSetLOHI(write1, read1, read2, mask, lo, hi) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( (lo) & MODE_WRITE ) { rpropSetWrite(XMMGPR_LO, mask); } \ + if( (hi) & MODE_WRITE ) { rpropSetWrite(XMMGPR_HI, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ + if( (lo) & MODE_READ ) { rpropSetRead(XMMGPR_LO, mask); } \ + if( (hi) & MODE_READ ) { rpropSetRead(XMMGPR_HI, mask); } \ +} \ + +// FPU regs +#define rpropSetFPURead(reg, mask) { \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + prev->fpuregs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0); \ +} \ + +#define rpropSetFPUWrite0(reg, mask, live) { \ + prev->fpuregs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + prev->fpuregs[reg] |= EEINST_USED; \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 1); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 1); \ +} + +#define rpropSetFPUWrite(reg, mask) { \ + rpropSetFPUWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +void rpropBSC(EEINST* prev, EEINST* pinst); +void rpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpropREGIMM(EEINST* prev, EEINST* pinst); +void rpropCP0(EEINST* prev, EEINST* pinst); +void rpropCP1(EEINST* prev, EEINST* pinst); +void rpropCP2(EEINST* prev, EEINST* pinst); +void rpropMMI(EEINST* prev, EEINST* pinst); +void rpropMMI0(EEINST* prev, EEINST* pinst); +void rpropMMI1(EEINST* prev, EEINST* pinst); +void rpropMMI2(EEINST* prev, EEINST* pinst); +void rpropMMI3(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, +//ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, +//COP0, COP1, COP2, NULL, BEQL, BNEL, BLEZL, BGTZL, +//DADDI, DADDIU, LDL, LDR, MMI, NULL, LQ, SQ, +//LB, LH, LWL, LW, LBU, LHU, LWR, LWU, +//SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, +//NULL, LWC1, NULL, PREF, NULL, NULL, LQC2, LD, +//NULL, SWC1, NULL, NULL, NULL, NULL, SQC2, SD +void rpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(cpuRegs.code >> 26) { + case 0: rpropSPECIAL(prev, pinst); break; + case 1: rpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpropSetWrite(31, EEINST_LIVE1); + break; + case 4: // beq + case 5: // bne + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_XMM|EEINST_MMX):0); + break; + + case 20: // beql + case 21: // bnel + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_XMM|EEINST_MMX):0); + break; + + case 6: // blez + case 7: // bgtz + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 22: // blezl + case 23: // bgtzl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // daddi + case 25: // daddiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|((_Rs_!=0&&cpucaps.hasStreamingSIMD2Extensions)?EEINST_MMX:0)); + break; + + case 8: // addi + case 9: // addiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + break; + + case 10: // slti + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + case 11: // sltiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 12: // andi + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, (_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 13: // ori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 14: // xori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 15: // lui + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 16: rpropCP0(prev, pinst); break; + case 17: rpropCP1(prev, pinst); break; + case 18: rpropCP2(prev, pinst); break; + + // loads + case 34: // lwl + case 38: // lwr + case 26: // ldl + case 27: // ldr + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 28: rpropMMI(prev, pinst); break; + + case 30: // lq + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 31: // sq + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + rpropSetRead(_Rt_, 0); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 44: // sdl + case 45: // sdr + case 63: // sd + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX|EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 49: // lwc1 + rpropSetFPUWrite(_Rt_, EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 57: // swc1 + rpropSetFPURead(_Rt_, EEINST_XMM); + rpropSetRead(_Rs_, 0); + break; + + case 54: // lqc2 + case 62: // sqc2 + rpropSetRead(_Rs_, 0); + break; + + default: + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=0?EEINST_MMX:0)); + break; + } +} + +//SLL, NULL, SRL, SRA, SLLV, NULL, SRLV, SRAV, +//JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, NULL, SYNC, +//MFHI, MTHI, MFLO, MTLO, DSLLV, NULL, DSRLV, DSRAV, +//MULT, MULTU, DIV, DIVU, NULL, NULL, NULL, NULL, +//ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, +//MFSA, MTSA, SLT, SLTU, DADD, DADDU, DSUB, DSUBU, +//TGE, TGEU, TLT, TLTU, TEQ, NULL, TNE, NULL, +//DSLL, NULL, DSRL, DSRA, DSLL32, NULL, DSRL32, DSRA32 +void rpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 4: // sllv + case 6: // srlv + case 7: // srav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 8: // JR + rpropSetRead(_Rs_, 0); + break; + case 9: // JALR + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 10: // movz + case 11: // movn + // do not write _Rd_! + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rd_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + _recFillRegister(pinst, XMMTYPE_GPRREG, _Rd_, 1); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_XMM)|EEINST_LIVE1); + break; + case 17: // mthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_XMM)|EEINST_LIVE1); + break; + case 19: // mtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 20: // dsllv + case 22: // dsrlv + case 23: // dsrav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + + case 24: // mult + // can do unsigned mult only if HI isn't used + //temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE0|EEINST_LIVE1))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + temp = 0; + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 26: // div + case 27: // divu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_XMM|EEINST_MMX; + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ ) rpropSetRead(_Rs_, 0); + if( _Rt_ ) rpropSetRead(_Rt_, 0); + pinst->info |= EEINST_MMX; + break; + + case 36: // and + case 37: // or + case 38: // xor + case 39: // nor + // if rd == rs or rt, keep live1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + break; + + case 40: // mfsa + rpropSetWrite(_Rd_, EEINST_LIVE1); + break; + case 41: // mtsa + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + break; + + case 42: // slt + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 43: // sltu + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 44: // dadd + case 45: // daddu + case 46: // dsub + case 47: // dsubu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ == 0 || _Rt_ == 0 ) { + // just a copy, so don't force mmx + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + } + else { + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + } + pinst->info |= EEINST_MMX; + break; + + // traps + case 48: case 49: case 50: case 51: case 52: case 54: + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + break; + + case 56: // dsll + case 58: // dsrl + case 59: // dsra + case 62: // dsrl32 + case 63: // dsra32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 60: // dsll32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + default: + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + } +} + +//BLTZ, BGEZ, BLTZL, BGEZL, NULL, NULL, NULL, NULL, +//TGEI, TGEIU, TLTI, TLTIU, TEQI, NULL, TNEI, NULL, +//BLTZAL, BGEZAL, BLTZALL, BGEZALL, NULL, NULL, NULL, NULL, +//MTSAB, MTSAH, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + case 2: // bltzl + case 3: // bgezl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX|EEINST_XMM; + break; + + // traps + case 8: + case 9: + case 10: + case 11: + case 12: + case 14: + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 18: // bltzall + case 19: // bgezall + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mtsab + case 25: // mtsah + rpropSetRead(_Rs_, 0); + break; + default: + assert(0); + break; + } +} + +//MFC0, NULL, NULL, NULL, MTC0, NULL, NULL, NULL, +//COP0BC0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//COP0C0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 4: + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 8: // cop0bc0 + _recClearInst(prev); + prev->info = 0; + break; + case 16: // cop0c0 + _recClearInst(prev); + prev->info = 0; + break; + } +} + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +//ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, RSQRT_S, NULL, +//ADDA_S, SUBA_S, MULA_S, NULL, MADD_S, MSUB_S, MADDA_S, MSUBA_S, +//NULL, NULL, NULL, NULL, CVT_W, NULL, NULL, NULL, +//MAX_S, MIN_S, NULL, NULL, NULL, NULL, NULL, NULL, +//C_F, NULL, C_EQ, NULL, C_LT, NULL, C_LE, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP1(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + case 2: // cfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_XMM|EEINST_MMX); + break; + case 4: // mtc1 + rpropSetFPUWrite(_Fs_, EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 6: // ctc1 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM|EEINST_MMX); + break; + case 8: // bc1 + break; + case 16: + // floating point ops + pinst->info |= EEINST_XMM; + switch( _Funct_ ) { + case 0: // add.s + case 1: // sub.s + case 2: // mul.s + case 3: // div.s + case 22: // rsqrt.s + case 40: // max.s + case 41: // min.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 4: // sqrt.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 5: // abs.s + case 6: // mov.s + case 7: // neg.s + case 36: // cvt.w + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + case 24: // adda.s + case 25: // suba.s + case 26: // mula.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + case 28: // madd.s + case 29: // msub.s + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + + case 30: // madda.s + case 31: // msuba.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + + case 48: // c.f + case 50: // c.eq + case 52: // c.lt + case 54: // c.le + rpropSetFPURead(_Fs_, EEINST_XMM); + rpropSetFPURead(_Ft_, EEINST_XMM); + break; + default: assert(0); + } + break; + case 20: + assert( _Funct_ == 32 ); // CVT.S.W + rpropSetFPUWrite(_Fd_, EEINST_XMM); + rpropSetFPURead(_Fs_, EEINST_XMM); + break; + default: + assert(0); + } +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +void rpropCP2(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 1: // qmfc2 + rpropSetWrite(_Rt_, EEINST_LIVE2|EEINST_LIVE1); + break; + + case 2: // cfc2 + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 5: // qmtc2 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 6: // ctc2 + rpropSetRead(_Rt_, 0); + break; + + case 8: // bc2 + break; + + default: + // vu macro mode insts + pinst->info |= 2; + break; + } +} + +//MADD, MADDU, NULL, NULL, PLZCW, NULL, NULL, NULL, +//MMI0, MMI2, NULL, NULL, NULL, NULL, NULL, NULL, +//MFHI1, MTHI1, MFLO1, MTLO1, NULL, NULL, NULL, NULL, +//MULT1, MULTU1, DIV1, DIVU1, NULL, NULL, NULL, NULL, +//MADD1, MADDU1, NULL, NULL, NULL, NULL, NULL, NULL, +//MMI1 , MMI3, NULL, NULL, NULL, NULL, NULL, NULL, +//PMFHL, PMTHL, NULL, NULL, PSLLH, NULL, PSRLH, PSRAH, +//NULL, NULL, NULL, NULL, PSLLW, NULL, PSRLW, PSRAW, +void rpropMMI(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(cpuRegs.code&0x3f) { + case 0: // madd + case 1: // maddu + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 4: // plzcw + rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1); + break; + case 8: rpropMMI0(prev, pinst); break; + case 9: rpropMMI2(prev, pinst); break; + + case 16: // mfhi1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_XMM))?EEINST_MMX:EEINST_XMM); + rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2); + break; + case 17: // mthi1 + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_XMM))?EEINST_MMX:EEINST_XMM); + rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2); + break; + case 19: // mtlo1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mult1 + temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE2))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 26: // div1 + case 27: // divu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_XMM|EEINST_MMX; + break; + + case 32: // madd1 + case 33: // maddu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2); + break; + + case 40: rpropMMI1(prev, pinst); break; + case 41: rpropMMI3(prev, pinst); break; + + case 48: // pmfhl + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 49: // pmthl + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +//recPADDW, PSUBW, PCGTW, PMAXW, +//PADDH, PSUBH, PCGTH, PMAXH, +//PADDB, PSUBB, PCGTB, NULL, +//NULL, NULL, NULL, NULL, +//PADDSW, PSUBSW, PEXTLW, PPACW, +//PADDSH, PSUBSH, PEXTLH, PPACH, +//PADDSB, PSUBSB, PEXTLB, PPACB, +//NULL, NULL, PEXT5, PPAC5, +void rpropMMI0(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 16: // paddsw + case 17: // psubsw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextlw + case 22: // pextlh + case 26: // pextlb + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + + case 30: // pext5 + case 31: // ppac5 + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI1(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 1: // pabsw + case 5: // pabsh + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 17: // psubuw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextuw + case 22: // pextuh + case 26: // pextub + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI2(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmaddw + case 4: // pmsubw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 2: // psllvw + case 3: // psllvw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + case 8: // pmfhi + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 9: // pmflo + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 10: // pinth + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 12: // pmultw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyld + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_XMM); + break; + case 16: // pmaddh + case 17: // phmadh + case 20: // pmsubh + case 21: // phmsbh + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + + case 26: // pexeh + case 27: // prevh + case 30: // pexew + case 31: // prot3w + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + case 28: // pmulth + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_WRITE, MODE_WRITE); + break; + case 29: // pdivbw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} + +void rpropMMI3(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmadduw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 3: // psravw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + + case 8: // pmthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 9: // pmtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + case 12: // pmultuw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivuw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyud + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_XMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_XMM); + break; + + case 26: // pexch + case 27: // pcpyh + case 30: // pexcw + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_XMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_XMM); + break; + } +} diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86.c b/branches/pcsx2_0.9.1/x86/ix86/ix86.c new file mode 100644 index 0000000..4cde925 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86.c @@ -0,0 +1,3086 @@ +/* + * ix86 core v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +#include +#include +#include +#include "ix86.h" + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +extern void SysPrintf(char *fmt, ...); + +// This function is just for rec debugging purposes +void CheckX86Ptr( void ) +{ +} + +void write64( u64 val ) +{ +#ifdef _DEBUG + CheckX86Ptr( ); +#endif + + *(u64*)x86Ptr = val; + x86Ptr += 8; +} + +void Rex( int w, int r, int x, int b ) +{ + assert(0); + write8( 0x40 | (w << 3) | (r << 2) | (x << 1) | (b) ); +} + +void ModRM( int mod, int rm, int reg ) +{ + write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) ); +} + +void SibSB( int ss, int rm, int index ) +{ + write8( ( ss << 6 ) | ( rm << 3 ) | ( index ) ); +} + +void SET8R( int cc, int to ) +{ + write8( 0x0F ); + write8( cc ); + write8( 0xC0 | ( to ) ); +} + +u8* J8Rel( int cc, int to ) +{ + write8( cc ); + write8( to ); + return x86Ptr - 1; +} + +u16* J16Rel( int cc, u32 to ) +{ + write16( 0x0F66 ); + write8( cc ); + write16( to ); + return (u16*)( x86Ptr - 2 ); +} + +u32* J32Rel( int cc, u32 to ) +{ + write8( 0x0F ); + write8( cc ); + write32( to ); + return (u32*)( x86Ptr - 4 ); +} + +void CMOV32RtoR( int cc, int to, int from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 3, to, from ); +} + +void CMOV32MtoR( int cc, int to, u32 from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////////////////////// +void x86SetPtr( char* ptr ) +{ + x86Ptr = ptr; +} + +//////////////////////////////////////////////////// +void x86Shutdown( void ) +{ +} + +//////////////////////////////////////////////////// +void x86SetJ8( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + + if( ((u32)x86Ptr&0xf) > 4 ) { + + u32 newjump = jump + 16-((u32)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +void x86SetJ16( u16 *j16 ) +{ + // doesn't work + u32 jump = ( x86Ptr - (s8*)j16 ) - 2; + + if ( jump > 0x7fff ) { + assert(0); + SysPrintf( "j16 greater than 0x7fff!!\n" ); + } + *j16 = (u16)jump; +} + +void x86SetJ16A( u16 *j16 ) +{ + if( ((u32)x86Ptr&0xf) > 4 ) { + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + x86SetJ16(j16); +} + +//////////////////////////////////////////////////// +void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (s8*)j32 ) - 4; +} + +void x86SetJ32A( u32* j32 ) +{ + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + x86SetJ32(j32); +} + +//////////////////////////////////////////////////// +void x86Align( int bytes ) +{ + // fordward align + x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) ); +} + +/********************/ +/* IX86 intructions */ +/********************/ + +void STC( void ) +{ + write8( 0xF9 ); +} + +void CLC( void ) +{ + write8( 0xF8 ); +} + +//////////////////////////////////// +// mov instructions / +//////////////////////////////////// + +/* mov r64 to r64 */ +void MOV64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r64 to m64 */ +void MOV64RtoM( u64 to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( (u32)MEMADDR(to, 4) ); +} + +/* mov m64 to r64 */ +void MOV64MtoR( x86IntRegType to, u64 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( (u32)MEMADDR(from, 4) ); +} + +/* mov imm32 to m64 */ +void MOV64ItoM(u32 to, u32 from ) +{ + Rex(1, 0, 0, 0); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* mov imm32 to r64 */ +void MOV32Ito64R( x86IntRegType to, s32 from ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xC7 ); + ModRM( 0, 0, to ); + write32( from ); +} + +/* mov imm64 to r64 */ +void MOV64ItoR( x86IntRegType to, u64 from ) { + Rex(1, 0, 0, to >> 3); + write8( 0xB8 | (to & 0x7) ); + write64( from ); +} + +/* mov [r64] to r64 */ +void MOV64RmtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +/* mov [r64][r64*scale] to r64 */ +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov r64 to [r64] */ +void MOV64RtoRm( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov r64 to [r64][r64*scale] */ +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + + +/* mov r32 to r32 */ +void MOV32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r32 to m32 */ +void MOV32RtoM( u32 to, x86IntRegType from ) +{ + if (from > 7) { + Rex(0, from >> 3, 0, 0); + } + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m32 to r32 */ +void MOV32MtoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r32 */ +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + if (from == ESP) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x8B ); + ModRM( 0, to, from ); + } +} + +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + + write8( 0x8B ); + + if( offset == 0 ) { + if (from == ESP) { + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 0, to, from ); + } + } + else if( offset < 128 ) { + if (from == ESP) { + ModRM( 1, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 1, to, from ); + } + write8(offset); + } + else { + if (from == ESP) { + ModRM( 2, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 2, to, from ); + } + write32(offset); + } +} + +/* mov [r32][r32*scale] to r32 */ +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +/* mov r32 to [r32] */ +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + if (to == ESP) { + write8( 0x89 ); + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x89 ); + ModRM( 0, from, to ); + } +} + +/* mov r32 to [r32][r32*scale] */ +void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov imm32 to r32 */ +void MOV32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB8 | (to & 0x7) ); + write32( from ); +} + +/* mov imm32 to m32 */ +void MOV32ItoM(u32 to, u32 from ) +{ + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// mov imm32 to [r32+off] +void MOV32ItoRmOffset( x86IntRegType to, u32 from, u32 offset) +{ + write8( 0xC7 ); + + if( to == ESP ) { + + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 ) { + ModRM( 1, 0, 4 ); + ModRM( 0, ESP, 4 ); + write8(offset); + } + else { + ModRM( 2, 0, 4 ); + ModRM( 0, ESP, 4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, 0, to ); + } + else if( offset < 128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } + + write32(from); +} + +// mov r32 to [r32+off] +void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x89 ); + + if (to == ESP) { + if( offset == 0 ) { + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + else if( offset < 128 ) { + ModRM( 1, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write8(offset); + } + else { + ModRM( 2, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + } + else { + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +/* mov r16 to m16 */ +void MOV16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m16 to r16 */ +void MOV16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOV16RmtoR( x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 2, to, from ); + write32( offset ); +} + +void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write16( 0x8B66 ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +void MOV16RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov imm16 to m16 */ +void MOV16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write16( 0xB866 | ((to & 0x7)<<8) ); + write16( from ); +} + +// mov imm16 to [r16+off] +void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset) +{ + assert( to != ESP ); + write16( 0xC766 ); + ModRM( 2, 0, to ); + write32(offset); + write16(from); +} + +// mov r16 to [r16+off] +void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write16( 0x8966 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* mov r8 to m8 */ +void MOV8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x88 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m8 to r8 */ +void MOV8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x8A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r8 */ +void MOV8RmtoR(x86IntRegType to, x86IntRegType from) +{ + write8( 0x8A ); + ModRM( 0, to, from ); +} + +void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x8A ); + ModRM( 2, to, from ); + write32(offset); +} + +void MOV8RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x88 ); + ModRM( 0, from, to ); +} + +/* mov imm8 to m8 */ +void MOV8ItoM( u32 to, u8 from ) +{ + write8( 0xC6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +// mov imm8 to r8 +void MOV8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB0 | (to & 0x7) ); + write8( from ); +} + +// mov imm8 to [r8+off] +void MOV8ItoRmOffset( x86IntRegType to, u8 from, u32 offset) +{ + assert( to != ESP ); + write8( 0xC6 ); + ModRM( 2, 0, to ); + write32(offset); + write8(from); +} + +// mov r8 to [r8+off] +void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write8( 0x88 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movsx r8 to r32 */ +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBE0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m8 to r32 */ +void MOVSX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movsx r16 to r32 */ +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBF0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m16 to r32 */ +void MOVSX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r8 to r32 */ +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB60F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m8 to r32 */ +void MOVZX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xB60F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r16 to r32 */ +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB70F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m16 to r32 */ +void MOVZX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xB70F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// mov r32+off to r32 +void MOV32RmOffsettoR( x86IntRegType to, x86IntRegType from, u32 offset) +{ + if( offset == 0 ) { + MOV32RtoR(to, from); + return; + } + + write8(0x8d); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8( offset ); + } + else { + ModRM( 2, to, from ); + write32( offset ); + } +} + +// mov r32+r32 to r32 +void MOV32Rm2toR( x86IntRegType to, x86IntRegType from1, x86IntRegType from2) +{ + write8(0x8d); + ModRM( 0, to, 4 ); + ModRM( 0, from1, from2 ); +} + +/* cmovbe r32 to r32 */ +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x46, to, from ); +} + +/* cmovbe m32 to r32*/ +void CMOVBE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x46, to, from ); +} + +/* cmovb r32 to r32 */ +void CMOVB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x42, to, from ); +} + +/* cmovb m32 to r32*/ +void CMOVB32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x42, to, from ); +} + +/* cmovae r32 to r32 */ +void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x43, to, from ); +} + +/* cmovae m32 to r32*/ +void CMOVAE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x43, to, from ); +} + +/* cmova r32 to r32 */ +void CMOVA32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x47, to, from ); +} + +/* cmova m32 to r32*/ +void CMOVA32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x47, to, from ); +} + +/* cmovo r32 to r32 */ +void CMOVO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x40, to, from ); +} + +/* cmovo m32 to r32 */ +void CMOVO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x40, to, from ); +} + +/* cmovp r32 to r32 */ +void CMOVP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4A, to, from ); +} + +/* cmovp m32 to r32 */ +void CMOVP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4A, to, from ); +} + +/* cmovs r32 to r32 */ +void CMOVS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x48, to, from ); +} + +/* cmovs m32 to r32 */ +void CMOVS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x48, to, from ); +} + +/* cmovno r32 to r32 */ +void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x41, to, from ); +} + +/* cmovno m32 to r32 */ +void CMOVNO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x41, to, from ); +} + +/* cmovnp r32 to r32 */ +void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4B, to, from ); +} + +/* cmovnp m32 to r32 */ +void CMOVNP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4B, to, from ); +} + +/* cmovns r32 to r32 */ +void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x49, to, from ); +} + +/* cmovns m32 to r32 */ +void CMOVNS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x49, to, from ); +} + +/* cmovne r32 to r32 */ +void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x45, to, from ); +} + +/* cmovne m32 to r32*/ +void CMOVNE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x45, to, from ); +} + +/* cmove r32 to r32*/ +void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x44, to, from ); +} + +/* cmove m32 to r32*/ +void CMOVE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x44, to, from ); +} + +/* cmovg r32 to r32*/ +void CMOVG32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4F, to, from ); +} + +/* cmovg m32 to r32*/ +void CMOVG32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4F, to, from ); +} + +/* cmovge r32 to r32*/ +void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4D, to, from ); +} + +/* cmovge m32 to r32*/ +void CMOVGE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4D, to, from ); +} + +/* cmovl r32 to r32*/ +void CMOVL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4C, to, from ); +} + +/* cmovl m32 to r32*/ +void CMOVL32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4C, to, from ); +} + +/* cmovle r32 to r32*/ +void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4E, to, from ); +} + +/* cmovle m32 to r32*/ +void CMOVLE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4E, to, from ); +} + +//////////////////////////////////// +// arithmetic instructions / +//////////////////////////////////// + +/* add imm32 to r64 */ +void ADD64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX) { + write8( 0x05 ); + } else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add m64 to r64 */ +void ADD64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* add r64 to r64 */ +void ADD64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add imm32 to r32 */ +void ADD32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add imm32 to m32 */ +void ADD32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* add r32 to r32 */ +void ADD32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add r32 to m32 */ +void ADD32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m32 to r32 */ +void ADD32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ) +{ + write16( 0x0366 ); + ModRM( 3, to, from ); +} + +/* add imm16 to r16 */ +void ADD16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +/* add imm16 to m16 */ +void ADD16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* add r16 to m16 */ +void ADD16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m16 to r16 */ +void ADD16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x02 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* adc imm32 to r32 */ +void ADC32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x15 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 2, to ); + } + write32( from ); +} + +/* adc imm32 to m32 */ +void ADC32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* adc r32 to r32 */ +void ADC32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 3, from, to ); +} + +/* adc m32 to r32 */ +void ADC32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x13 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// adc r32 to m32 +void ADC32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r32 */ +void INC32R( x86IntRegType to ) +{ + write8( 0x40 + to ); +} + +/* inc m32 */ +void INC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r16 */ +void INC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x40 + to ); +} + +/* inc m16 */ +void INC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* sub imm32 to r64 */ +void SUB64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub r64 to r64 */ +void SUB64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m64 to r64 */ +void SUB64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sub imm32 to r32 */ +void SUB32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub imm32 to m32 */ +void SUB32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sub r32 to r32 */ +void SUB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m32 to r32 */ +void SUB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// sub r32 to m32 +void SUB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x29 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ) +{ + write16( 0x2b66 ); + ModRM( 3, to, from ); +} + +/* sub imm16 to r16 */ +void SUB16ItoR( x86IntRegType to, u16 from ) { + write8( 0x66 ); + if ( to == EAX ) { + write8( 0x2D ); + } else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write16( from ); +} + +/* sub imm16 to m16 */ +void SUB16ItoM( u32 to, u16 from ) { + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* sub m16 to r16 */ +void SUB16MtoR( x86IntRegType to, u32 from ) { + write8( 0x66 ); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r64 to r64 */ +void SBB64RtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, to >> 3, 0, from >> 3); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR( x86IntRegType to, u32 from ) { + if ( to == EAX ) { + write8( 0x1D ); + } else { + write8( 0x81 ); + ModRM( 3, 3, to ); + } + write32( from ); +} + +/* sbb imm32 to m32 */ +void SBB32ItoM( u32 to, u32 from ) { + write8( 0x81 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sbb r32 to r32 */ +void SBB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb m32 to r32 */ +void SBB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x1B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r32 to m32 */ +void SBB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* dec r32 */ +void DEC32R( x86IntRegType to ) +{ + write8( 0x48 + to ); +} + +/* dec m32 */ +void DEC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* dec r16 */ +void DEC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x48 + to ); +} + +/* dec m16 */ +void DEC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 4, from ); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 5, from ); +} + +/* mul eax by m32 to edx:eax */ +void MUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xAF0F ); + ModRM( 3, to, from ); +} + +/* div eax by r32 to edx:eax */ +void DIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 6, from ); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 7, from ); +} + +/* div eax by m32 to edx:eax */ +void DIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r64 */ +void SHL64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 4, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl cl to r64 */ +void SHL64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +/* shr imm8 to r64 */ +void SHR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 5, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); +} + +/* shr cl to r64 */ +void SHR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +/* shl imm8 to r32 */ +void SHL32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl imm8 to m32 */ +void SHL32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shl cl to r32 */ +void SHL32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write16( 0xD166 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write16( 0xC166 ); + ModRM( 3, 4, to ); + write8( from ); +} + +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC0 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shr imm8 to r32 */ +void SHR32ItoR( x86IntRegType to, u8 from ) { + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* shr imm8 to m32 */ +void SHR32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shr cl to r32 */ +void SHR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC0 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* sar imm8 to r64 */ +void SAR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar cl to r64 */ +void SAR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +/* sar imm8 to r32 */ +void SAR32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar imm8 to m32 */ +void SAR32ItoM( u32 to, u8 from ) +{ + write8( 0xC1 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* sar cl to r32 */ +void SAR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write16( 0xD166 ); + ModRM( 3, 7, to ); + return; + } + write16( 0xC166 ); + ModRM( 3, 7, to ); + write8( from ); +} + +void ROR32ItoR( x86IntRegType to,u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xc8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xc8 | to ); + write8( from ); + } +} + +void RCR32ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xd8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xd8 | to ); + write8( from ); + } +} + +// shld imm8 to r32 +void SHLD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xA4 ); + ModRM( 3, from, to ); + write8( shift ); +} + +// shrd imm8 to r32 +void SHRD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xAC ); + ModRM( 3, from, to ); + write8( shift ); +} + +//////////////////////////////////// +// logical instructions / +//////////////////////////////////// + +/* or imm32 to r32 */ +void OR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x0D ); + } else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or m64 to r64 */ +void OR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* or r64 to r64 */ +void OR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x09 ); + ModRM( 3, from, to ); +} + + +/* or imm32 to r32 */ +void OR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or imm32 to m32 */ +void OR32ItoM(u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* or r32 to r32 */ +void OR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 3, from, to ); +} + +/* or r32 to m32 */ +void OR32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* or m32 to r32 */ +void OR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 3, from, to ); +} + +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x0D66 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 1, to ); + } + write16( from ); +} + +// or imm16 to m316 +void OR16ItoM( u32 to, u16 from ) +{ + write16( 0x8166 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* or m16 to r16 */ +void OR16MtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0B66 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to m16 +void OR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 3, from, to ); +} + +// or r8 to m8 +void OR8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or imm8 to m8 +void OR8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// or m8 to r8 +void OR8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r64 */ +void XOR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x35 ); + } else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor r64 to r64 */ +void XOR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor m64 to r64 */ +void XOR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r32 */ +void XOR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor imm32 to m32 */ +void XOR32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* xor r32 to r32 */ +void XOR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r16 to r16 */ +void XOR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r32 to m32 */ +void XOR32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* xor m32 to r32 */ +void XOR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x3566 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 6, to ); + } + write16( from ); +} + +// xor r16 to m16 +void XOR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x3166 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and imm32 to r64 */ +void AND64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and m64 to r64 */ +void AND64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* and r64 to m64 */ +void AND64RtoM( u32 to, x86IntRegType from ) +{ + Rex(1, 0, 0, 0); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and r64 to r64 */ +void AND64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and imm32 to r32 */ +void AND32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and sign ext imm8 to r32 */ +void AND32I8toR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0x83 ); + ModRM( 3, 0x4, to ); + write8( from ); +} + +/* and imm32 to m32 */ +void AND32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* and sign ext imm8 to m32 */ +void AND32I8toM( u32 to, u8 from ) +{ + write8( 0x83 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* and r32 to r32 */ +void AND32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and r32 to m32 */ +void AND32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m32 to r32 */ +void AND32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x2366 ); + ModRM( 3, to, from ); +} + +/* and imm16 to r16 */ +void AND16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write16( 0x2566 ); + } else { + write16( 0x8166 ); + ModRM( 3, 0x4, to ); + } + write16( from ); +} + +/* and imm16 to m16 */ +void AND16ItoM( u32 to, u16 from ) +{ + write8( 0x8166 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* and r16 to m16 */ +void AND16RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m16 to r16 */ +void AND16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* and imm8 to r8 */ +void AND8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x24 ); + } else { + write8( 0x80 ); + ModRM( 3, 0x4, to ); + } + write8( from ); +} + +/* and imm8 to m8 */ +void AND8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x22 ); + ModRM( 3, to, from ); +} + +/* and r8 to m8 */ +void AND8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x20 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m8 to r8 */ +void AND8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x22 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* not r64 */ +void NOT64R( x86IntRegType from ) +{ + Rex(1, 0, 0, from >> 3); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +/* not r32 */ +void NOT32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +// not m32 +void NOT32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r64 */ +void NEG64R( x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +/* neg r32 */ +void NEG32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +void NEG32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r16 */ +void NEG16R( x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +u8* JMP( u32 to ) { + u32 jump = ( x86Ptr - (s8*)to ) - 1; + + if ( jump > 0x7f ) { + return (u8*)JMP32( to ); + } else { + return (u8*)JMP8( to ); + } +} + +/* jmp rel8 */ +u8* JMP8( u8 to ) +{ + write8( 0xEB ); + write8( to ); + return x86Ptr - 1; +} + +/* jmp rel32 */ +u32* JMP32( u32 to ) +{ + write8( 0xE9 ); + write32( to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32 */ +void JMP32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +// jmp m32 +void JMP32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4)); +} + +/* jmp r64 */ +void JMP64R( x86IntRegType to ) { + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +/* jp rel8 */ +u8* JP8( u8 to ) { + return J8Rel( 0x7A, to ); +} + +/* jnp rel8 */ +u8* JNP8( u8 to ) { + return J8Rel( 0x7B, to ); +} + +/* je rel8 */ +u8* JE8( u8 to ) { + return J8Rel( 0x74, to ); +} + +/* jz rel8 */ +u8* JZ8( u8 to ) +{ + return J8Rel( 0x74, to ); +} + +/* js rel8 */ +u8* JS8( u8 to ) +{ + return J8Rel( 0x78, to ); +} + +/* jns rel8 */ +u8* JNS8( u8 to ) +{ + return J8Rel( 0x79, to ); +} + +/* jg rel8 */ +u8* JG8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jge rel8 */ +u8* JGE8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jl rel8 */ +u8* JL8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* ja rel8 */ +u8* JA8( u8 to ) +{ + return J8Rel( 0x77, to ); +} + +u8* JAE8( u8 to ) +{ + return J8Rel( 0x73, to ); +} + +/* jb rel8 */ +u8* JB8( u8 to ) +{ + return J8Rel( 0x72, to ); +} + +/* jbe rel8 */ +u8* JBE8( u8 to ) +{ + return J8Rel( 0x76, to ); +} + +/* jle rel8 */ +u8* JLE8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jne rel8 */ +u8* JNE8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jnz rel8 */ +u8* JNZ8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jng rel8 */ +u8* JNG8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jnge rel8 */ +u8* JNGE8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* jnl rel8 */ +u8* JNL8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jnle rel8 */ +u8* JNLE8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jo rel8 */ +u8* JO8( u8 to ) +{ + return J8Rel( 0x70, to ); +} + +/* jno rel8 */ +u8* JNO8( u8 to ) +{ + return J8Rel( 0x71, to ); +} + +// jb rel8 +u16* JB16( u16 to ) +{ + return J16Rel( 0x82, to ); +} + +// jb rel32 +u32* JB32( u32 to ) +{ + return J32Rel( 0x82, to ); +} + +/* je rel32 */ +u32* JE32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jz rel32 */ +u32* JZ32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jg rel32 */ +u32* JG32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jge rel32 */ +u32* JGE32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jl rel32 */ +u32* JL32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jle rel32 */ +u32* JLE32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jae rel32 */ +u32* JAE32( u32 to ) +{ + return J32Rel( 0x83, to ); +} + +/* jne rel32 */ +u32* JNE32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jnz rel32 */ +u32* JNZ32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jng rel32 */ +u32* JNG32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jnge rel32 */ +u32* JNGE32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jnl rel32 */ +u32* JNL32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jnle rel32 */ +u32* JNLE32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jo rel32 */ +u32* JO32( u32 to ) +{ + return J32Rel( 0x80, to ); +} + +/* jno rel32 */ +u32* JNO32( u32 to ) +{ + return J32Rel( 0x81, to ); +} + +// js rel32 +u32* JS32( u32 to ) +{ + return J32Rel( 0x88, to ); +} + + +/* call func */ +void CALLFunc( u32 func ) +{ + CALL32( func - ( (u32)x86Ptr + 5 ) ); +} + +/* call rel32 */ +void CALL32( u32 to ) +{ + write8( 0xE8 ); + write32( to ); +} + +/* call r32 */ +void CALL32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call r64 */ +void CALL64R( x86IntRegType to ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call m32 */ +void CALL32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r64 */ +void CMP64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp m64 to r64 */ +void CMP64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* cmp imm32 to r32 */ +void CMP32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp imm32 to m32 */ +void CMP32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* cmp r32 to r32 */ +void CMP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m32 to r32 */ +void CMP32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, to ); + write8(from); +} + +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) +{ + assert( to != ESP ); + write8( 0x83 ); + ModRM( 1, 7, to ); + write8(off); + write8(from); +} + +// cmp imm8 to [r32] +void CMP32I8toM( u32 to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* cmp imm16 to r16 */ +void CMP16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write16( from ); +} + +/* cmp imm16 to m16 */ +void CMP16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* cmp r16 to r16 */ +void CMP16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m16 to r16 */ +void CMP16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0x3C ); + } + else + { + write8( 0x80 ); + ModRM( 3, 7, to ); + } + write8( from ); +} + +/* test imm32 to r32 */ +void TEST32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +void TEST32ItoM( u32 to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* test r32 to r32 */ +void TEST32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, to ); + write32(from); +} + +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) + { + write16( 0xA966 ); + } + else + { + write16( 0xF766 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x8566 ); + ModRM( 3, from, to ); +} + +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0xA8 ); + } + else + { + write8( 0xF6 ); + ModRM( 3, 0, to ); + } + write8( from ); +} + +// test imm8 to r8 +void TEST8ItoM( u32 to, u8 from ) +{ + write8( 0xF6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* sets r8 */ +void SETS8R( x86IntRegType to ) +{ + SET8R( 0x98, to ); +} + +/* setl r8 */ +void SETL8R( x86IntRegType to ) +{ + SET8R( 0x9C, to ); +} + +// setge r8 +void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); } +// setg r8 +void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); } +// seta r8 +void SETA8R( x86IntRegType to ) { SET8R(0x97, to); } +// setae r8 +void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); } +/* setb r8 */ +void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); } +/* setb r8 */ +void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); } +// setz r8 +void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); } +// sete r8 +void SETE8R( x86IntRegType to ) { SET8R(0x94, to); } + +/* push r32 */ +void PUSH32R( x86IntRegType from ) +{ + write8( 0x50 | from ); +} + +/* push m32 */ +void PUSH32M( u32 from ) +{ + write8( 0xFF ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* push imm32 */ +void PUSH32I( u32 from ) +{ + write8( 0x68 ); + write32( from ); +} + +/* pop r32 */ +void POP32R( x86IntRegType from ) +{ + write8( 0x58 | from ); +} + +/* pushad */ +void PUSHA32( void ) +{ + write8( 0x60 ); +} + +/* popad */ +void POPA32( void ) +{ + write8( 0x61 ); +} + +/* pushfd */ +void PUSHFD( void ) +{ + write8( 0x9C ); +} + +/* popfd */ +void POPFD( void ) +{ + write8( 0x9D ); +} + +void RET( void ) { write8( 0xC3 ); } +void RET2( void ) { write16( 0xc3f3 ); } + +void CBW( void ) { write16( 0x9866 ); } +void CWD( void ) { write8( 0x98 ); } +void CDQ( void ) { write8( 0x99 ); } +void CWDE() { write8(0x98); } + +void LAHF() { write8(0x9f); } +void SAHF() { write8(0x9e); } + +void BT32ItoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBA0F ); + write8( 0xE0 | to ); + write8( from ); +} + +void BSRRtoR(x86IntRegType to, x86IntRegType from) +{ + write16( 0xBD0F ); + ModRM( 3, from, to ); +} + +void BSWAP32R( x86IntRegType to ) +{ + write8( 0x0F ); + write8( 0xC8 + to ); +} + +// to = from + offset +void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) +{ + write8(0x66); + LEA32RtoR(to, from, offset); +} + +void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8(0x8d); + + if( from == ESP ) { + if( offset == 0 ) { + ModRM(1, to, from); + write8(0x24); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(0x24); + write8(offset); + } + else { + ModRM(2, to, from); + write8(0x24); + write32(offset); + } + } + else { + if( offset == 0 && from != EBP && from!=ESP ) { + ModRM(0, to, from); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(offset); + } + else { + ModRM(2, to, from); + write32(offset); + } + } +} + +// to = from0 + from1 +void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x66); + LEA32RRtoR(to, from0, from1); +} + +void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x8d); + if( from0 == EBP || from1 == EBP ) { + + if( from0 == EBP ) SWAP(from0, from1); + ModRM(1, to, 4); + ModRM(0, from0, from1); + write8(0); + } + else { + ModRM(0, to, 4); + ModRM(0, from0, from1); + } +} + +// to = from << scale (max is 3) +void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + write8(0x66); + LEA32RStoR(to, from, scale); +} + +void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + if( to == from ) { + SHL32ItoR(to, scale); + return; + } + + if( from != ESP ) { + write8(0x8d); + ModRM(0, to, 4); + ModRM(scale, from, 5); + write32(0); + } + else { + MOV32RtoR(to, from); + LEA32RStoR(to, to, scale); + } +} diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86.h b/branches/pcsx2_0.9.1/x86/ix86/ix86.h new file mode 100644 index 0000000..4fbdd20 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86.h @@ -0,0 +1,1637 @@ +/* + * ix86 definitions v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "PS2Etypes.h" // Basic types header + +#ifdef __x86_64__ +#define XMMREGS 16 +#define X86REGS 16 +#else +#define XMMREGS 8 +#define X86REGS 8 +#endif + +#define MMXREGS 8 + +#define SIB 4 +#define DISP32 5 + +// general types +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 +#define RAX 0 +#define RBX 3 +#define RCX 1 +#define RDX 2 +#define RSI 6 +#define RDI 7 +#define RBP 5 +#define RSP 4 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +typedef int x86IntRegType; + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; + +typedef enum +{ + XMMT_INT = 0, // integer (sse2 only) + XMMT_FPS = 1, // floating point + //XMMT_FPD = 3, // double +} XMMSSEType; + +extern XMMSSEType g_xmmtypes[XMMREGS]; + +void cpudetectInit( void );//this is all that needs to be called and will fill up the below structs + +//cpu capabilities structure +typedef struct { + u32 hasFloatingPointUnit; + u32 hasVirtual8086ModeEnhancements; + u32 hasDebuggingExtensions; + u32 hasPageSizeExtensions; + u32 hasTimeStampCounter; + u32 hasModelSpecificRegisters; + u32 hasPhysicalAddressExtension; + u32 hasCOMPXCHG8BInstruction; + u32 hasAdvancedProgrammableInterruptController; + u32 hasSEPFastSystemCall; + u32 hasMemoryTypeRangeRegisters; + u32 hasPTEGlobalFlag; + u32 hasMachineCheckArchitecture; + u32 hasConditionalMoveAndCompareInstructions; + u32 hasFGPageAttributeTable; + u32 has36bitPageSizeExtension; + u32 hasProcessorSerialNumber; + u32 hasCFLUSHInstruction; + u32 hasDebugStore; + u32 hasACPIThermalMonitorAndClockControl; + u32 hasMultimediaExtensions; + u32 hasFastStreamingSIMDExtensionsSaveRestore; + u32 hasStreamingSIMDExtensions; + u32 hasStreamingSIMD2Extensions; + u32 hasSelfSnoop; + u32 hasHyperThreading; + u32 hasThermalMonitor; + u32 hasIntel64BitArchitecture; + u32 hasStreamingSIMD3Extensions; + //that is only for AMDs + u32 hasMultimediaExtensionsExt; + u32 hasAMD64BitArchitecture; + u32 has3DNOWInstructionExtensionsExt; + u32 has3DNOWInstructionExtensions; +} CAPABILITIES; + +extern CAPABILITIES cpucaps; + +typedef struct { + + u32 x86Family; // Processor Family + u32 x86Model; // Processor Model + u32 x86PType; // Processor Type + u32 x86StepID; // Stepping ID + u32 x86Flags; // Feature Flags + u32 x86EFlags; // Extended Feature Flags + //all the above returns hex values + s8 x86ID[16]; // Vendor ID //the vendor creator (in %s) + s8 x86Type[20]; //cpu type in char format //the cpu type (in %s) + s8 x86Fam[50]; // family in char format //the original cpu name string (in %s) + u32 cpuspeed; // speed of cpu //this will give cpu speed (in %d) +} CPUINFO; + +extern CPUINFO cpuinfo; + +extern s8 *x86Ptr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + + +#ifdef __x86_64__ +#define MEMADDR(addr, oplen) ((addr) - ((u64)x86Ptr + ((u64)oplen))) +#else +#define MEMADDR(addr, oplen) (addr) +#endif + + + +void write8( int val ); +void write16( int val ); +void write32( u32 val ); +void write64( u64 val ); + + +void x86SetPtr( char *ptr ); +void x86Shutdown( void ); + +void x86SetJ8( u8 *j8 ); +void x86SetJ8A( u8 *j8 ); +void x86SetJ16( u16 *j16 ); +void x86SetJ16A( u16 *j16 ); +void x86SetJ32( u32 *j32 ); +void x86SetJ32A( u32 *j32 ); + +void x86Align( int bytes ); +u64 GetCPUTick( void ); + +// General Helper functions + +void Rex( int w, int r, int x, int b ); +void ModRM( int mod, int rm, int reg ); +void SibSB( int ss, int rm, int index ); +void SET8R( int cc, int to ); +u8* J8Rel( int cc, int to ); +u32* J32Rel( int cc, u32 to ); +void CMOV32RtoR( int cc, int to, int from ); +void CMOV32MtoR( int cc, int to, u32 from ); + +//****************** +// IX86 intructions +//****************** + +// +// * scale values: +// * 0 - *1 +// * 1 - *2 +// * 2 - *4 +// * 3 - *8 +// + +void STC( void ); +void CLC( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r64 to r64 +void MOV64RtoR( x86IntRegType to, x86IntRegType from ); +// mov r64 to m64 +void MOV64RtoM( u64 to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, u64 from ); +// mov imm32 to m64 +void MOV64ItoM( u32 to, u32 from ); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( u32 to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, u32 from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ); +// mov [r32][r32< subtract ST(0) from ST(1), store in ST(1) and POP stack +void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +void FDIV320toR( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src), pop stack, store in ST(src) +void FDIV320toRP( x86IntRegType src ); + +// fadd m32 to fpu reg stack +void FADD32( u32 from ); +// fsub m32 to fpu reg stack +void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +void FDIV32( u32 from ); +// fcomi st, st( i) +void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +void FCOM32( u32 from ); +// fabs fpu reg stack +void FABS( void ); +// fsqrt fpu reg stack +void FSQRT( void ); +// ftan fpu reg stack +void FPATAN( void ); +// fsin fpu reg stack +void FSIN( void ); +// fchs fpu reg stack +void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +void FCMOVNU32( x86IntRegType from ); +void FCOMP32( u32 from ); +void FNSTSWtoAX( void ); + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, u32 from ); +// movq r64 to m64 +void MOVQRtoM( u32 to, x86MMXRegType from ); + +// pand r64 to r64 +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +void PANDMtoR( x86MMXRegType to, u32 from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, u32 from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, u32 from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, u32 from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, u32 from ); +// psllq imm8 to r64 +void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +void PSRLQMtoR( x86MMXRegType to, u32 from ); +// psrlq imm8 to r64 +void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +void PADDUSBMtoR( x86MMXRegType to, u32 from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, u32 from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, u32 from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, u32 from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, u32 from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ); +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDMtoR( x86MMXRegType to, u32 from ); + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ); +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ); +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDMtoR( x86MMXRegType to, u32 from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDMtoR( x86MMXRegType to, u32 from ); +void PSRLWItoR( x86MMXRegType to, u8 from ); +void PSRLDItoR( x86MMXRegType to, u8 from ); +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSLLWItoR( x86MMXRegType to, u8 from ); +void PSLLDItoR( x86MMXRegType to, u8 from ); +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSRAWItoR( x86MMXRegType to, u8 from ); +void PSRADItoR( x86MMXRegType to, u8 from ); +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ); +void MOVQ64ItoR( x86MMXRegType reg, u64 i ); //Prototype.Todo add all consts to end of block.not after jr $+8 +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void MOVDMtoMMX( x86MMXRegType to, u32 from ); +void MOVDMMXtoM( u32 to, x86MMXRegType from ); +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ); +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8); +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8); +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from); + +// emms +void EMMS( void ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word 64bits +//********************************************************************************** +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from); +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from); + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from); + +//********************* +// SSE instructions * +//********************* +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ); +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ); + +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPSRtoRm( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ); + +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ); +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ); + +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ); + +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ); +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from); +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from); +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ); +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +// VectorPath +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE_STMXCSR( u32 from ); +void SSE_LDMXCSR( u32 from ); + + +//********************* +// SSE 2 Instructions* +//********************* +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +// mult by half words +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from); + + +//**********************************************************************************/ +//PMOVMSKB: Create 16bit mask from signs of 8bit integers +//********************************************************************************** +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ); +void SSE_PINSRW_R32_to_XMM(x86SSERegType from, x86IntRegType to, u8 imm8 ); + + +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ); +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ); + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from); +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from); +//********************* +// SSE-X - uses both SSE,SSE2 code and tries to keep consistensies between the data +// Uses g_xmmtypes to infer the correct type. +//********************* +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, u32 from ); +void PFCMPGTMtoR( x86IntRegType to, u32 from ); +void PFCMPGEMtoR( x86IntRegType to, u32 from ); +void PFADDMtoR( x86IntRegType to, u32 from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, u32 from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, u32 from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, u32 from ); +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PF2IDMtoR( x86IntRegType to, u32 from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, u32 from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, u32 from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, u32 from ); +void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from); +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +/* SSE2 emulated functions for SSE CPU's by kekko*/ + +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); + +//////////////////////////////////////////////////// +#ifdef _DEBUG +#define WRITECHECK() CheckX86Ptr() +#else +#define WRITECHECK() +#endif + +#define write8(val ) { \ + *(u8*)x86Ptr = (u8)val; \ + x86Ptr++; \ +} \ + +#define write16(val ) \ +{ \ + *(u16*)x86Ptr = (u16)val; \ + x86Ptr += 2; \ +} \ + +#define write32( val ) \ +{ \ + *(u32*)x86Ptr = val; \ + x86Ptr += 4; \ +} \ + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86_3dnow.c b/branches/pcsx2_0.9.1/x86/ix86/ix86_3dnow.c new file mode 100644 index 0000000..df56fd0 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86_3dnow.c @@ -0,0 +1,184 @@ + +#include "ix86.h" + +/**********************/ +/* 3DNOW instructions */ +/**********************/ + +/* femms */ +void FEMMS( void ) +{ + write16( 0x0E0F ); +} + +void PFCMPEQMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB0 ); +} + +void PFCMPGTMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA0 ); +} + +void PFCMPGEMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x90 ); +} + +void PFADDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9E ); +} + +void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9E ); +} + +void PFSUBMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9A ); +} + +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9A ); +} + +void PFMULMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB4 ); +} + +void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB4 ); +} + +void PFRCPMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x96 ); +} + +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x96 ); +} + +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA6 ); +} + +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB6 ); +} + +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x97 ); +} + +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA7 ); +} + +void PF2IDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x1D ); +} + +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x1D ); +} + +void PI2FDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x0D ); +} + +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x0D ); +} + +void PFMAXMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA4 ); +} + +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA4 ); +} + +void PFMINMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x94 ); +} + +void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x94 ); +} diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86_cpudetect.c b/branches/pcsx2_0.9.1/x86/ix86/ix86_cpudetect.c new file mode 100644 index 0000000..5d32ebf --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86_cpudetect.c @@ -0,0 +1,482 @@ +/* Cpudetection lib + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if defined (__WIN32__) + +#include + +#endif + +#include +#include + +#include "ix86.h" + +#if defined (__VCNET2005__) + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +CAPABILITIES cpucaps; +CPUINFO cpuinfo; + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag; + +#if defined (__VCNET2005__) + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (__MSCW32__) && !defined(__x86_64__) + __asm + { + push ebx; + push edi; + + pushfd; + pop eax; + mov edx, eax; + xor eax, 1 << 21; + push eax; + popfd; + pushfd; + pop eax; + xor eax, edx; + mov flag, eax; + } + if ( ! flag ) + { + return -1; + } + + __asm + { + mov eax, cmd; + cpuid; + mov edi, [regs] + mov [edi], eax; + mov [edi+4], ebx; + mov [edi+8], ecx; + mov [edi+12], edx; + + pop edi; + pop ebx; + } + + return 0; + + +#else + + __asm__ __volatile__ ( +#ifdef __x86_64__ + "sub $0x18, %%rsp\n" +#endif + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%edx\n" + "xor $0x200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%eax\n" + "mov %%eax, %0\n" +#ifdef __x86_64__ + "add $0x18, %%rsp\n" +#endif + : "=r"(flag) : + ); + + if ( ! flag ) + { + return -1; + } + + __asm__ __volatile__ ( + "mov %4, %%eax\n" + "cpuid\n" + "mov %%eax, %0\n" + "mov %%ebx, %1\n" + "mov %%ecx, %2\n" + "mov %%edx, %3\n" + : "=m" (regs[0]), "=m" (regs[1]), + "=m" (regs[2]), "=m" (regs[3]) + : "m"(cmd) + : "eax", "ebx", "ecx", "edx" + ); + + return 0; +#endif +} + +u64 GetCPUTick( void ) +{ +#if defined (__VCNET2005__) + + return __rdtsc(); + +#elif defined(__MSCW32__) && !defined(__x86_64__) + + __asm rdtsc; + +#else + + u32 _a, _d; + __asm__ __volatile__ ("rdtsc" : "=a"(_a), "=d"(_d)); + return (u64)_a | ((u64)_d << 32); + +#endif +} + +#if defined __LINUX__ + +#include +#include + +u32 timeGetTime( void ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#endif + +s64 CPUSpeedHz( unsigned int time ) +{ + s64 timeStart, + timeStop; + s64 startTick, + endTick; + s64 overhead; + + if( ! cpucaps.hasTimeStampCounter ) + { + return 0; //check if function is supported + } + + overhead = GetCPUTick() - GetCPUTick(); + + timeStart = timeGetTime( ); + while( timeGetTime( ) == timeStart ) + { + timeStart = timeGetTime( ); + } + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > time ) + { + endTick = GetCPUTick( ); + break; + } + } + + return (s64)( ( endTick - startTick ) + ( overhead ) ); +} + +//////////////////////////////////////////////////// +void cpudetectInit( void ) +{ + u32 regs[ 4 ]; + u32 cmds; + u32 AMDspeed; + s8 AMDspeedString[10]; + int cputype=0; // Cpu type + //AMD 64 STUFF + u32 x86_64_8BITBRANDID; + u32 x86_64_12BITBRANDID; + memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) ); + cpuinfo.x86Family = 0; + cpuinfo.x86Model = 0; + cpuinfo.x86PType = 0; + cpuinfo.x86StepID = 0; + cpuinfo.x86Flags = 0; + cpuinfo.x86EFlags = 0; + + if ( iCpuId( 0, regs ) == -1 ) return; + + cmds = regs[ 0 ]; + ((u32*)cpuinfo.x86ID)[ 0 ] = regs[ 1 ]; + ((u32*)cpuinfo.x86ID)[ 1 ] = regs[ 3 ]; + ((u32*)cpuinfo.x86ID)[ 2 ] = regs[ 2 ]; + if ( cmds >= 0x00000001 ) + { + if ( iCpuId( 0x00000001, regs ) != -1 ) + { + cpuinfo.x86StepID = regs[ 0 ] & 0xf; + cpuinfo.x86Model = (regs[ 0 ] >> 4) & 0xf; + cpuinfo.x86Family = (regs[ 0 ] >> 8) & 0xf; + cpuinfo.x86PType = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[1] & 0xff; + cpuinfo.x86Flags = regs[ 3 ]; + } + } + if ( iCpuId( 0x80000000, regs ) != -1 ) + { + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + if ( iCpuId( 0x80000001, regs ) != -1 ) + { + x86_64_12BITBRANDID = regs[1] & 0xfff; + cpuinfo.x86EFlags = regs[ 3 ]; + + } + } + } + switch(cpuinfo.x86PType) + { + case 0: + strcpy( cpuinfo.x86Type, "Standard OEM"); + break; + case 1: + strcpy( cpuinfo.x86Type, "Overdrive"); + break; + case 2: + strcpy( cpuinfo.x86Type, "Dual"); + break; + case 3: + strcpy( cpuinfo.x86Type, "Reserved"); + break; + default: + strcpy( cpuinfo.x86Type, "Unknown"); + break; + } + if ( cpuinfo.x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p + if ( cpuinfo.x86ID[ 0 ] == 'A' ){ cputype=1;} + + if ( cputype == 0 ) //intel cpu + { + if( ( cpuinfo.x86Family >= 7 ) && ( cpuinfo.x86Family < 15 ) ) + { + strcpy( cpuinfo.x86Fam, "Intel P6 family (Not PIV and Higher then PPro" ); + } + else + { + switch( cpuinfo.x86Family ) + { + // Start at 486 because if it's below 486 there is no cpuid instruction + case 4: + strcpy( cpuinfo.x86Fam, "Intel 486" ); + break; + case 5: + switch( cpuinfo.x86Model ) + { + case 4: + case 8: // 0.25 m + strcpy( cpuinfo.x86Fam, "Intel Pentium (MMX)"); + break; + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium" ); + } + break; + case 6: + switch( cpuinfo.x86Model ) + { + case 0: // Pentium pro (P6 A-Step) + case 1: // Pentium pro + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro" ); + break; + + case 2: // 66 MHz FSB + case 5: // Xeon/Celeron (0.25 m) + case 6: // Internal L2 cache + strcpy( cpuinfo.x86Fam, "Intel Pentium II" ); + break; + + case 7: // Xeon external L2 cache + case 8: // Xeon/Celeron with 256 KB on-die L2 cache + case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache + case 11: // Xeon/Celeron with Tualatin core, on-die cache + strcpy( cpuinfo.x86Fam, "Intel Pentium III" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro (Unknown)" ); + } + break; + case 15: + switch( cpuinfo.x86Model ) + { + case 0: // Willamette (A-Step) + case 1: // Willamette + strcpy( cpuinfo.x86Fam, "Willamette Intel Pentium IV" ); + break; + case 2: // Northwood + strcpy( cpuinfo.x86Fam, "Northwood Intel Pentium IV" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium IV (Unknown)" ); + break; + } + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown Intel CPU" ); + } + } + } + else if ( cputype == 1 ) //AMD cpu + { + if( cpuinfo.x86Family >= 7 ) + { + if((x86_64_12BITBRANDID !=0) || (x86_64_8BITBRANDID !=0)) + { + if(x86_64_8BITBRANDID == 0 ) + { + switch((x86_64_12BITBRANDID >>6)& 0x3f) + { + case 4: + strcpy(cpuinfo.x86Fam,"AMD Athlon(tm) 64 Processor"); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 12: + strcpy(cpuinfo.x86Fam,"AMD Opteron(tm) Processor"); + break; + default: + strcpy(cpuinfo.x86Fam,"Unknown AMD 64 proccesor"); + + } + } + else //8bit brand id is non zero + { + strcpy(cpuinfo.x86Fam,"Unsupported yet AMD64 cpu"); + } + } + else + { + strcpy( cpuinfo.x86Fam, "AMD K7+" ); + } + } + else + { + switch ( cpuinfo.x86Family ) + { + case 4: + switch( cpuinfo.x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( cpuinfo.x86Fam, "AMD 5x86" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( cpuinfo.x86Fam, "AMD 486" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown" ); + + } + break; + + case 5: + switch( cpuinfo.x86Model) + { + case 0: // SSA 5 (75, 90 and 100 Mhz) + case 1: // 5k86 (PR 120 and 133 MHz) + case 2: // 5k86 (PR 166 MHz) + case 3: // K5 5k86 (PR 200 MHz) + strcpy( cpuinfo.x86Fam, "AMD K5" ); + break; + + case 6: + case 7: // (0.25 m) + case 8: // K6-2 + case 9: // K6-III + case 14: // K6-2+ / K6-III+ + strcpy( cpuinfo.x86Fam, "AMD K6" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown" ); + } + break; + case 6: + strcpy( cpuinfo.x86Fam, "AMD K7" ); + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown AMD CPU" ); + } + } + } + //capabilities + cpucaps.hasFloatingPointUnit = ( cpuinfo.x86Flags >> 0 ) & 1; + cpucaps.hasVirtual8086ModeEnhancements = ( cpuinfo.x86Flags >> 1 ) & 1; + cpucaps.hasDebuggingExtensions = ( cpuinfo.x86Flags >> 2 ) & 1; + cpucaps.hasPageSizeExtensions = ( cpuinfo.x86Flags >> 3 ) & 1; + cpucaps.hasTimeStampCounter = ( cpuinfo.x86Flags >> 4 ) & 1; + cpucaps.hasModelSpecificRegisters = ( cpuinfo.x86Flags >> 5 ) & 1; + cpucaps.hasPhysicalAddressExtension = ( cpuinfo.x86Flags >> 6 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 7 ) & 1; + cpucaps.hasCOMPXCHG8BInstruction = ( cpuinfo.x86Flags >> 8 ) & 1; + cpucaps.hasAdvancedProgrammableInterruptController = ( cpuinfo.x86Flags >> 9 ) & 1; + cpucaps.hasSEPFastSystemCall = ( cpuinfo.x86Flags >> 11 ) & 1; + cpucaps.hasMemoryTypeRangeRegisters = ( cpuinfo.x86Flags >> 12 ) & 1; + cpucaps.hasPTEGlobalFlag = ( cpuinfo.x86Flags >> 13 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 14 ) & 1; + cpucaps.hasConditionalMoveAndCompareInstructions = ( cpuinfo.x86Flags >> 15 ) & 1; + cpucaps.hasFGPageAttributeTable = ( cpuinfo.x86Flags >> 16 ) & 1; + cpucaps.has36bitPageSizeExtension = ( cpuinfo.x86Flags >> 17 ) & 1; + cpucaps.hasProcessorSerialNumber = ( cpuinfo.x86Flags >> 18 ) & 1; + cpucaps.hasCFLUSHInstruction = ( cpuinfo.x86Flags >> 19 ) & 1; + cpucaps.hasDebugStore = ( cpuinfo.x86Flags >> 21 ) & 1; + cpucaps.hasACPIThermalMonitorAndClockControl = ( cpuinfo.x86Flags >> 22 ) & 1; + cpucaps.hasMultimediaExtensions = ( cpuinfo.x86Flags >> 23 ) & 1; //mmx + cpucaps.hasFastStreamingSIMDExtensionsSaveRestore = ( cpuinfo.x86Flags >> 24 ) & 1; + cpucaps.hasStreamingSIMDExtensions = ( cpuinfo.x86Flags >> 25 ) & 1; //sse + cpucaps.hasStreamingSIMD2Extensions = ( cpuinfo.x86Flags >> 26 ) & 1; //sse2 + cpucaps.hasSelfSnoop = ( cpuinfo.x86Flags >> 27 ) & 1; + cpucaps.hasHyperThreading = ( cpuinfo.x86Flags >> 28 ) & 1; + cpucaps.hasThermalMonitor = ( cpuinfo.x86Flags >> 29 ) & 1; + cpucaps.hasIntel64BitArchitecture = ( cpuinfo.x86Flags >> 30 ) & 1; + //that is only for AMDs + cpucaps.hasMultimediaExtensionsExt = ( cpuinfo.x86EFlags >> 22 ) & 1; //mmx2 + cpucaps.hasAMD64BitArchitecture = ( cpuinfo.x86EFlags >> 29 ) & 1; //64bit cpu + cpucaps.has3DNOWInstructionExtensionsExt = ( cpuinfo.x86EFlags >> 30 ) & 1; //3dnow+ + cpucaps.has3DNOWInstructionExtensions = ( cpuinfo.x86EFlags >> 31 ) & 1; //3dnow + cpuinfo.cpuspeed = (u32 )(CPUSpeedHz( 1000 ) / 1000000); +} diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86_fpu.c b/branches/pcsx2_0.9.1/x86/ix86/ix86_fpu.c new file mode 100644 index 0000000..98034a5 --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86_fpu.c @@ -0,0 +1,269 @@ +#include +#include +#include "ix86.h" + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fld m32 to fpu reg stack */ +void FLD32( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// fld st(i) +void FLD(int st) { write16(0xc0d9+(st<<8)); } + +void FLD1() { write16(0xe8d9); } +void FLDL2E() { write16(0xead9); } + +/* fst m32 from fpu reg stack */ +void FST32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// fstp st(i) +void FSTP(int st) { write16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +void FLDCW( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x7, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void FNSTSWtoAX( void ) +{ + write16( 0xE0DF ); +} + +void FXAM() +{ + write16(0xe5d9); +} + +void FDECSTP() { write16(0xf6d9); } +void FRNDINT() { write16(0xfcd9); } +void FXCH(int st) { write16(0xc8d9+(st<<8)); } +void F2XM1() { write16(0xf0d9); } +void FSCALE() { write16(0xfdd9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +void FADD32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +void FADD320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +void FSUB32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +void FSUB320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +void FSUBP( void ) +{ + write8( 0xDE ); + write8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +void FMUL32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +void FMUL320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +void FDIV32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +void FDIV320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xF8 + src ); +} + +void FDIV320toRP( x86IntRegType src ) +{ + write8( 0xDE ); + write8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +void FADD32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x1, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fabs fpu reg stack */ +void FABS( void ) +{ + write16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +void FSQRT( void ) +{ + write16( 0xFAD9 ); +} + +void FPATAN(void) { write16(0xf3d9); } +void FSIN(void) { write16(0xfed9); } + +/* fchs fpu reg stack */ +void FCHS( void ) +{ + write16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +void FCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +void FCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +void FUCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +void FUCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +void FCOM32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fcomp m32 to fpu reg stack */ +void FCOMP32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +#define FCMOV32( low, high ) \ + { \ + write8( low ); \ + write8( high + from ); \ + } + +void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86_mmx.c b/branches/pcsx2_0.9.1/x86/ix86/ix86_mmx.c new file mode 100644 index 0000000..0f484ba --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86_mmx.c @@ -0,0 +1,632 @@ + +#include "ix86.h" + +#include + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6F0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movq r64 to m64 */ +void MOVQRtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7F0F ); + ModRM( 0, from, DISP32 ); + write32(MEMADDR(to, 4)); +} + +/* pand r64 to r64 */ +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDB0F ); + ModRM( 3, to, from ); +} + +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDF0F ); + ModRM( 3, to, from ); +} + +/* por r64 to r64 */ +void PORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEB0F ); + ModRM( 3, to, from ); +} + +/* pxor r64 to r64 */ +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEF0F ); + ModRM( 3, to, from ); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF30F ); + ModRM( 3, to, from ); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 6, to); + write8( from ); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD30F ); + ModRM( 3, to, from ); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 2, to); + write8( from ); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDC0F ); + ModRM( 3, to, from ); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDD0F ); + ModRM( 3, to, from ); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddb r64 to r64 */ +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFC0F ); + ModRM( 3, to, from ); +} + +/* paddb m64 to r64 */ +void PADDBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddw r64 to r64 */ +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFD0F ); + ModRM( 3, to, from ); +} + +/* paddw m64 to r64 */ +void PADDWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddd r64 to r64 */ +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFE0F ); + ModRM( 3, to, from ); +} + +/* paddd m64 to r64 */ +void PADDDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* emms */ +void EMMS( void ) +{ + write16( 0x770F ); +} + +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEC0F ); + ModRM( 3, to, from ); +} + +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xED0F ); + ModRM( 3, to, from ); +} + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD40F ); + ModRM( 3, to, from ); +} + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE80F ); + ModRM( 3, to, from ); +} + +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE90F ); + ModRM( 3, to, from ); +} + + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF80F ); + ModRM( 3, to, from ); +} + +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF90F ); + ModRM( 3, to, from ); +} + +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFA0F ); + ModRM( 3, to, from ); +} + +void PSUBDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFA0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD80F ); + ModRM( 3, to, from ); +} + +void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD90F ); + ModRM( 3, to, from ); +} + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFB0F ); + ModRM( 3, to, from ); +} + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF40F ); + ModRM( 3, to, from ); +} + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x740F ); + ModRM( 3, to, from ); +} + +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x750F ); + ModRM( 3, to, from ); +} + +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x760F ); + ModRM( 3, to, from ); +} + +void PCMPEQDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x760F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x640F ); + ModRM( 3, to, from ); +} + +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x650F ); + ModRM( 3, to, from ); +} + +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x660F ); + ModRM( 3, to, from ); +} + +void PCMPGTDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x660F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSRLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD20F ); + ModRM( 3, to, from ); +} + +void PSLLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF20F ); + ModRM( 3, to, from ); +} + +void PSRAWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE20F ); + ModRM( 3, to, from ); +} + +/* por m64 to r64 */ +void PORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pxor m64 to r64 */ +void PXORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pand m64 to r64 */ +void PANDMtoR( x86MMXRegType to, u32 from ) +{ + //u64 rip = (u64)x86Ptr + 7; + write16( 0xDB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PANDNMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6A0F ); + ModRM( 3, to, from ); +} + +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6A0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x620F ); + ModRM( 3, to, from ); +} + +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x620F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOVQ64ItoR( x86MMXRegType reg, u64 i ) +{ + MOVQMtoR( reg, ( u32 )(x86Ptr) + 2 + 7 ); + JMP8( 8 ); + write64( i ); +} + +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6F0F ); + ModRM( 3, to, from ); +} + +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6F0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7F0F ); + + if( offset < 128 ) { + ModRM( 1, from , to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movd m32 to r64 */ +void MOVDMtoMMX( x86MMXRegType to, u32 from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movd r64 to m32 */ +void MOVDMMXtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 3, to, from ); +} + +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, from ); +} + +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6E0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 3, from, to ); +} + +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, to ); + if( to >= 4 ) { + // no idea why + assert( to == ESP ); + write8(0x24); + } + +} + +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7E0F ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///* movd r32 to r64 */ +//void MOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x6E0F ); +// ModRM( 3, to, from ); +//} +// +///* movq r64 to r32 */ +//void MOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x7E0F ); +// ModRM( 3, from, to ); +//} + +// untested +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x630F ); + ModRM( 3, to, from ); +} + +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x6B0F ); + ModRM( 3, to, from ); +} + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) +{ + write16( 0xD70F ); + ModRM( 3, to, from ); +} + +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) +{ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0xc40f ); + ModRM( 3, to, from ); + write8( imm8 ); +} + +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) +{ + write16(0x700f); + ModRM( 3, to, from ); + write8(imm8); +} + +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8) +{ + write16( 0x700f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); + write8(imm8); +} + +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) +{ + write16(0xf70f); + ModRM( 3, to, from ); +} diff --git a/branches/pcsx2_0.9.1/x86/ix86/ix86_sse.c b/branches/pcsx2_0.9.1/x86/ix86/ix86_sse.c new file mode 100644 index 0000000..249f08b --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/ix86/ix86_sse.c @@ -0,0 +1,1540 @@ + +#include "ix86.h" +__declspec(align(16)) unsigned int p[4],p2[4]; +__declspec(align(16)) float f[4]; + + +XMMSSEType g_xmmtypes[XMMREGS] = {0}; + +/********************/ +/* SSE instructions */ +/********************/ + +#define SSEMtoR( code, overb ) \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSERtoM( code, overb ) \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSE_SS_MtoR( code, overb ) \ + write8( 0xf3 ); \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSE_SS_RtoM( code, overb ) \ + write8( 0xf3 ); \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSERtoR( code ) \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define SSEMtoR66( code ) \ + write8( 0x66 ); \ + SSEMtoR( code, 0 ); + +#define SSERtoM66( code ) \ + write8( 0x66 ); \ + SSERtoM( code, 0 ); + +#define SSERtoR66( code ) \ + write8( 0x66 ); \ + SSERtoR( code ); + +#define _SSERtoR66( code ) \ + write8( 0x66 ); \ + if (to > 7 || from > 7) Rex(1, from >> 3, 0, to >> 3); \ + write16( code ); \ + ModRM( 3, from, to ); + +#define SSE_SS_RtoR( code ) \ + write8( 0xf3 ); \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define CMPPSMtoR( op ) \ + SSEMtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPPSRtoR( op ) \ + SSERtoR( 0xc20f ); \ + write8( op ); + +#define CMPSSMtoR( op ) \ + SSE_SS_MtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPSSRtoR( op ) \ + SSE_SS_RtoR( 0xc20f ); \ + write8( op ); + + + + + +/* movups [r32][r32*scale] to xmm1 */ +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups xmm1 to [r32][r32*scale] */ +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups [r32] to r32 */ +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, from ); +} + +/* movups r32 to [r32] */ +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x110f ); + ModRM( 0, from, to ); +} + +/* movlps [r32] to r32 */ +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 0, to, from ); +} + +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movaps r32 to [r32] */ +void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 0, from, to ); +} + +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 2, from, to ); + write32(offset); +} + +/* movaps [r32][r32*scale] to xmm1 */ +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movaps xmm1 to [r32][r32*scale] */ +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +// movaps [r32+offset] to r32 +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x280f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movaps r32 to [r32+offset] +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x290f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movdqa [r32+offset] to r32 +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write8(0x66); + write16( 0x6f0f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movdqa r32 to [r32+offset] +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write8(0x66); + write16( 0x7f0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movups [r32+offset] to r32 +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movups r32 to [r32+offset] +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x110f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +//**********************************************************************************/ +//MOVAPS: Move aligned Packed Single Precision FP values * +//********************************************************************************** +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x280f, 0 ); } +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); } +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x280f ); } + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x100f, 0 ); } +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVSD_XMM_to_XMM(to, from); + else { + write8(0xf2); + SSERtoR( 0x100f); + } +} + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from); + else { + write8(0xf3); SSEMtoR( 0x7e0f, 0); + } +} + +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from); + else { + write8(0xf3); SSERtoR( 0x7e0f); + } +} + +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from); + else { + SSERtoM66(0xd60f); + } +} + +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVDQ2Q_XMM_to_MM(to, from); + else { + write8(0xf2); + SSERtoR( 0xd60f); + } +} +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ2DQ_MM_to_XMM(to, from); + else { + write8(0xf3); + SSERtoR( 0xd60f); + } +} + +//**********************************************************************************/ +//MOVSS: Move Scalar Single-Precision FP value * +//********************************************************************************** +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x100f, 0 ); } +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); } +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0xf3); write16(0x110f); + ModRM(0, from, to); +} + +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x100f ); } + +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0xf3); write16( 0x100f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write8(0xf3); write16(0x110f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); } +//**********************************************************************************/ +//MOVLPS: Move low Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x120f, 0 ); } +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); } + +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x120f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write16(0x130f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHPS: Move High Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x160f, 0 ); } +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); } + +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x160f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write16(0x170f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVLHPS: Moved packed Single-Precision FP low to high * +//********************************************************************************** +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHLPS: Moved packed Single-Precision FP High to Low * +//********************************************************************************** +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDPS: Logical Bit-wise AND for Single FP * +//********************************************************************************** +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x540f, 0 ); } +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x540f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDNPS : Logical Bit-wise AND NOT of Single-precision FP values * +//********************************************************************************** +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x550f, 0 ); } +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x550f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RCPPS : Packed Single-Precision FP Reciprocal * +//********************************************************************************** +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x530f ); } +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x530f, 0 ); } + +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x530f); } +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR(0x530f, 0); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ORPS : Bit-wise Logical OR of Single-Precision FP Data * +//********************************************************************************** +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x560f, 0 ); } +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x560f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//XORPS : Bitwise Logical XOR of Single-Precision FP Values * +//********************************************************************************** +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x570f, 0 ); } +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x570f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDPS : ADD Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x580f, 0 ); } +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x580f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDSS : ADD Scalar Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x580f, 0 ); } +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x580f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBPS: Packed Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5c0f, 0 ); } +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5c0f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBSS : Scalar Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5c0f, 0 ); } +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5c0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULPS : Packed Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x590f, 0 ); } +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULSS : Scalar Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x590f, 0 ); } +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Packed Single-Precission FP compare (CMPccPS) * +//********************************************************************************** +//missing SSE_CMPPS_I8_to_XMM +// SSE_CMPPS_M32_to_XMM +// SSE_CMPPS_XMM_to_XMM +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 0 ); } +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 1 ); } +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 2 ); } +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 3 ); } +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 4 ); } +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 5 ); } +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 6 ); } +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 7 ); } +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 7 ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Scalar Single-Precission FP compare (CMPccSS) * +//********************************************************************************** +//missing SSE_CMPSS_I8_to_XMM +// SSE_CMPSS_M32_to_XMM +// SSE_CMPSS_XMM_to_XMM +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 0 ); } +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 1 ); } +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 2 ); } +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 3 ); } +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 4 ); } +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 5 ); } +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 6 ); } +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 7 ); } +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ) +{ + write16( 0x2e0f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + write16( 0x2e0f ); + ModRM( 3, to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x520f, 0 ); } +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x520f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTSS : Scalar Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x520f, 0 ); } +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x520f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTPS : Packed Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x510f, 0 ); } +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x510f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTSS : Scalar Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x510f, 0 ); } +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x510f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXPS: Return Packed Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5f0f, 0 ); } +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXSS: Return Scalar Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * +//********************************************************************************** +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x2a0f, 0 ); } +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPS2PI: Packed Single FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ) { SSEMtoR( 0x2d0f, 0 ); } +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } + +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from) { write8(0xf3); SSEMtoR(0x2c0f, 0); } +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) +{ + write8(0xf3); + write16(0x2c0f); + ModRM(3, to, from); +} + +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x2a0f, 0); } +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) +{ + write8(0xf3); + write16(0x2a0f); + ModRM(3, to, from); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * +//********************************************************************************** +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5b0f, 0 ); } +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); } + +//**********************************************************************************/ +//CVTPS2DQ: Packed Single Precision FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0x5b0f ); } +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINPS: Return Packed Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5d0f, 0 ); } +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5d0f ); } + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINSS: Return Scalar Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMAXSW: Packed Signed Integer Word Maximum * +//********************************************************************************** +//missing + // SSE_PMAXSW_M64_to_MM +// SSE2_PMAXSW_M128_to_XMM +// SSE2_PMAXSW_XMM_to_XMM +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEE0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMINSW: Packed Signed Integer Word Minimum * +//********************************************************************************** +//missing + // SSE_PMINSW_M64_to_MM +// SSE2_PMINSW_M128_to_XMM +// SSE2_PMINSW_XMM_to_XMM +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEA0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SHUFPS: Shuffle Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8( imm8 ); } +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } + +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ) +{ + write16(0xc60f); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } + write8(imm8); +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSHUFD: Shuffle Packed DoubleWords * +//********************************************************************************** +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_PSHUFD_XMM_to_XMM(to, from, imm8); + } + else { + SSERtoR66( 0x700F ); + write8( imm8 ); + } +} +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR66( 0x700F ); write8( imm8 ); } + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF2); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF2); SSEMtoR(0x700F, 1); write8(imm8); } +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF3); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF3); SSEMtoR(0x700F, 1); write8(imm8); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x140f, 0); } +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x140F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKHPS: Unpack and Interleave High Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x150f, 0); } +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x150F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVPS : Packed Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5e0F, 0 ); } +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5e0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVSS : Scalar Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5e0F, 0 ); } +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5e0F ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//STMXCSR : Store Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_STMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//LDMXCSR : Load Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_LDMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PADDB,PADDW,PADDD : Add Packed Integers * +//********************************************************************************** +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); } +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFC0F ); } +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFD0F ); } +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFE0F ); } + +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ) { SSEMtoR66( 0xD40F ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x640F ); } +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x640F ); } +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x650F ); } +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x660F ); } +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x740F ); } +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x750F ); } +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_XMM_to_XMM(to, from); + } + else { + SSERtoR66( 0x760F ); + } +} + +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_M128_to_XMM(to, from); + } + else { + SSEMtoR66( 0x760F ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); } +void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); } +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF80F ); } +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF90F ); } +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFA0F ); } +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFB0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66(0x6E0F); } +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_R_to_XMM(to, from); + } + else { + SSERtoR66(0x6E0F); + } +} + +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0x6e0f ); + ModRM( 0, to, from ); +} + +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + + write16( 0x6e0f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); } +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_R(to, from); + } + else { + _SSERtoR66(0x7E0F); + } +} + +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0x66); + write16( 0x7e0f ); + ModRM( 0, from, to ); +} + +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset); + } + else { + write8(0x66); + write16( 0x7e0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xEB0F ); } + +// logical and to &= from +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDB0F ); } +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDB0F ); } + +// to = (~to) & from +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDF0F ); } +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDF0F ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PXOR : SSE Bitwise XOR * +//********************************************************************************** +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEF0F ); } +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEF0F ) }; +/////////////////////////////////////////////////////////////////////////////////////// + +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from) {SSEMtoR66(0x6F0F); } +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ){SSERtoM66(0x7F0F);} +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSERtoR66(0x6F0F); } + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xF3); SSEMtoR(0x6F0F, 0); } +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from) { write8(0xF3); SSERtoM(0x7F0F, 0); } +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { write8(0xF3); SSERtoR(0x6F0F); } + +// shift right logical + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD10F); } +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); } +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD20F); } +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); } +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD30F); } +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 3 , to ); + write8( imm8 ); +} + +// shift right arithmetic + +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); } +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE10F); } +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE20F); } +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE20F); } +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +// shift left logical + +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); } +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF10F); } +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); } +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF20F); } +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); } +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF30F); } +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 7 , to ); + write8( imm8 ); +} + +// + +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEE0F ); } +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEE0F ); } + +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); } +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDE0F ); } + +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); } +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEA0F ); } + +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); } +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDA0F ); } + +// + +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); } +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEC0F ); } + +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); } +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xED0F ); } + +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); } +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE80F ); } + +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); } +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE90F ); } + +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD80F ); } +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD90F ); } + +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDC0F ); } +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDD0F ); } + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x630F ); } +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x630F ); } +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6B0F ); } + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x670F ); } + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x600F ); } +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x600F ); } + +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x680F ); } + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x610F ); } +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x690F ); } + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x620F ); } +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6A0F ); } + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6C0F ); } + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6D0F ); } + +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xD50F ); } +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xE50F ); } + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xF40F ); } + +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); } + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); } +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); } + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf2); SSERtoR( 0x7c0f ); } +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from){ write8(0xf2); SSEMtoR( 0x7c0f, 0 ); } + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x120f); } +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x120f, 0); } +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x160f); } +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x160f, 0); } + +// SSE-X +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset); + else SSE_MOVAPSRmtoROffset(to, from, offset); +} + +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset); + else SSE_MOVAPSRtoRmOffset(to, from, offset); +} + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); + else SSE_MOVSS_M32_to_XMM(to, from); +} + +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); + else SSE_MOVSS_XMM_to_M32(to, from); +} + +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from); + else SSE_MOVSS_XMM_to_Rm(to, from); +} + +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset); + else SSE_MOVSS_RmOffset_to_XMM(to, from, offset); +} + +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset); + else SSE_MOVSS_XMM_to_RmOffset(to, from, offset); +} + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); + else SSE_ORPS_M128_to_XMM(to, from); +} + +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); + else SSE_ORPS_XMM_to_XMM(to, from); +} + +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); + else SSE_XORPS_M128_to_XMM(to, from); +} + +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); + else SSE_XORPS_XMM_to_XMM(to, from); +} + +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); + else SSE_ANDPS_M128_to_XMM(to, from); +} + +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); + else SSE_ANDPS_XMM_to_XMM(to, from); +} + +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); + else SSE_ANDNPS_M128_to_XMM(to, from); +} + +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); + else SSE_ANDNPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); + else SSE_UNPCKLPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); + else SSE_UNPCKLPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); + else SSE_UNPCKHPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); + else SSE_UNPCKHPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); + if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); + } + else { + SSE_MOVHLPS_XMM_to_XMM(to, from); + } +} + +// SSE2 emulation +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_SHUFPS_XMM_to_XMM(to, from, 0x4e); + SSE_SHUFPS_XMM_to_XMM(to, to, 0x4e); +} + +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE_MOVLPS_M64_to_XMM(to, from); +} + +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE2EMU_MOVSD_XMM_to_XMM(to, from); +} + +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + MOV32RmtoROffset(EAX, from, offset); + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, EAX); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} + +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ) +{ + SSE_MOVSS_XMM_to_M32((u32)p, from); + MOV32MtoR(EAX, (u32)p); + MOV32RtoRmOffset(to, EAX, offset); +} + +extern void SetMMXstate(); + +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + SSE_MOVLPS_XMM_to_M64((u32)p, from); + MOVQMtoR(to, (u32)p); + SetMMXstate(); +} + +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + MOVQRtoM((u32)p, from); + SSE_MOVLPS_M64_to_XMM(to, (u32)p); + SetMMXstate(); +} + +/****************************************************************************/ +/* SSE2 Emulated functions for SSE CPU's by kekko */ +/****************************************************************************/ +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { + MOV32ItoR(EAX, (u32)&p); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + MOV32ItoR(ECX, (u32)imm8); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 2); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 4); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 6); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + SUB32ItoR(EBX, 12); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + MOV32ItoR(to, (u32)&p); + SSE_MOVUPSRtoRm(to, from); + MOV32RmtoR(to, to); +} + + +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&f); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + FLD32((u32)&f[0]); + FISTP32((u32)&p2[0]); + FLD32((u32)&f[1]); + FISTP32((u32)&p2[1]); + FLD32((u32)&f[2]); + FISTP32((u32)&p2[2]); + FLD32((u32)&f[3]); + FISTP32((u32)&p2[3]); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { + MOV32ItoR(EAX, (u32)&from); + MOV32ItoR(EBX, (u32)&f); + + FILD32((u32)from); + FSTP32((u32)&f[0]); + FILD32((u32)from+4); + FSTP32((u32)&f[1]); + FILD32((u32)from+8); + FSTP32((u32)&f[2]); + FILD32((u32)from+12); + FSTP32((u32)&f[3]); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&p); + SSE_MOVUPSRtoRm(EAX, from); + MOV32RmtoR(EAX, EAX); + MOV32RtoM(to, EAX); +} + +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, from); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} diff --git a/branches/pcsx2_0.9.1/x86/recCOP2.c b/branches/pcsx2_0.9.1/x86/recCOP2.c new file mode 100644 index 0000000..3e7334d --- /dev/null +++ b/branches/pcsx2_0.9.1/x86/recCOP2.c @@ -0,0 +1,739 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "iVU0micro.h" +#include "iVUmicro.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// cycle cycles statusflag macflag clipflag +_vuopinfo g_cop2info = {0, 0, 1, 1, 1, 0, 0}; + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) +#define _Cc_ (cpuRegs.code & 0x03) + +#define REC_COP2_FUNC(f, delreg) \ + void f(); \ + void rec##f() { \ + SysPrintf("cop2 "#f" called\n"); \ + SetFPUstate(); \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_NOCONST); \ + CALLFunc((u32)f); \ + _freeX86regs(); \ + branch = 2; \ +} + +#define INTERPRETATE_COP2_FUNC(f) \ +void recV##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)V##f); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0MS(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0CLIP(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + + +void rec_C2UNK() +{ + SysPrintf("Cop2 bad opcode:%x\n",cpuRegs.code); +} + +void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) +{ + SysPrintf("Cop2 bad _vuRegs code:%x\n",cpuRegs.code); +} + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn); + +void (*recCOP2t[32])(); +void (*recCOP2_BC2t[32])(); +void (*recCOP2SPECIAL1t[64])(); +void (*recCOP2SPECIAL2t[128])(); + +void recCOP2(); +void recCOP2_SPECIAL(); +void recCOP2_BC2(); +void recCOP2_SPECIAL2(); + +extern void _vu0WaitMicro(); + +static void recCFC2() +{ + int mmreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteGPRtoXMMreg(_Rt_, 2); + + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE)) >= 0 ) { + + if( _Fs_ >= 16 ) { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + + if( EEINST_ISLIVE1(_Rt_) ) { + _signExtendGPRtoMMX(mmreg, _Rt_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + else { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + } + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&VU0.VI[ _Fs_ ].UL); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // no sign extending + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1],0); + } + else { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + + _eeOnWriteReg(_Rt_, 1); +} + +static void recCTC2() +{ + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( GPR_IS_CONST1(_Rt_) ) { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + if( g_cpuConstRegs[_Rt_].UL[0] & 2 ) { + CALLFunc((u32)vu0ResetRegs); + } + + if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 ) { + CALLFunc((u32)vu1ResetRegs); + } + + MOV16ItoM((u32)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c); + break; + + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + MOV32ItoM((u32)&VU1.VI[REG_TPC].UL, g_cpuConstRegs[_Rt_].UL[0]&0xffff); + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]&0xffff); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + MOV32ItoM((u32)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + _eeMoveGPRtoR(EAX, _Rt_); + + TEST32ItoR(EAX,0x2); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu0ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX,0x200); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu1ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EAX,0x0C0C); + MOV16RtoM((u32)&VU0.VI[REG_FBRST].UL,EAX); + break; + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + _eeMoveGPRtoR(EAX, _Rt_); + MOV16RtoM((u32)&VU1.VI[REG_TPC].UL,EAX); + + PUSH32R(EAX); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + _eeMoveGPRtoM((u32)&VU0.VI[_Fs_].UL,_Rt_); + break; + } + } +} + +static void recQMFC2(void) +{ + int t0reg, fsreg; + _xmmregs temp; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + + // could 'borrow' the reg + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ); + + if( fsreg >= 0 ) { + if( xmmregs[fsreg].mode & MODE_WRITE ) { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg); + + // change regs + temp = xmmregs[t0reg]; + xmmregs[t0reg] = xmmregs[fsreg]; + xmmregs[fsreg] = temp; + } + else { + // swap regs + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + + xmmregs[fsreg] = xmmregs[t0reg]; + xmmregs[t0reg].inuse = 0; + } + } + else { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSE_MOVAPS_M128_to_XMM( t0reg, (u32)&VU0.VF[_Fs_].UD[0]); + } + + _clearNeededXMMregs(); +} + +static void recQMTC2() +{ + int mmreg, fsreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg); + } + else { + // swap regs + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + xmmregs[mmreg] = xmmregs[fsreg]; + xmmregs[mmreg].mode = MODE_WRITE; + xmmregs[fsreg].inuse = 0; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + // swap regs + xmmregs[mmreg].type = XMMTYPE_VFREG; + xmmregs[mmreg].VU = 0; + xmmregs[mmreg].reg = _Fs_; + xmmregs[mmreg].mode = MODE_WRITE; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE); + + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg); + SSE_MOVHPS_M64_to_XMM(fsreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + } + else { + + if( GPR_IS_CONST1( _Rt_ ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 ); + _flushConstReg(_Rt_); + } + + SSE_MOVAPS_M128_to_XMM(fsreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + } + } + + _clearNeededXMMregs(); +} + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls) +{ + _vuRegsCOP22(&VU0, &pinst->vuregs); + if( !dostalls ) return; + + _recvuTestLowerStalls(&VU0, &pinst->vuregs); + + switch(VU0.code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU0.code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + pinst->vuregs.VIwrite |= (1<vuregs.VIwrite |= (1<vuregs.VIwrite & (1 << REG_CLIP_FLAG)) { + _recAddWriteBack(vucycle+4, 1<vuregs.VIwrite & (1 << REG_Q)) { + _recAddWriteBack(vucycle+pinst->vuregs.cycles, 1<cycle = vucycle; + _recvuAddLowerStalls(&VU0, &pinst->vuregs); + _recvuTestPipes(&VU0); + + vucycle++; +} + +////////////////////////////////////////////////////////////////////////// +// BC2: Instructions +////////////////////////////////////////////////////////////////////////// +REC_COP2_FUNC(BC2F, 0); +REC_COP2_FUNC(BC2T, 0); +REC_COP2_FUNC(BC2FL, 0); +REC_COP2_FUNC(BC2TL, 0); + +////////////////////////////////////////////////////////////////////////// +// Special1 instructions +////////////////////////////////////////////////////////////////////////// +//TODO: redirect all the opcodes to the ivu0micro same functions +REC_COP2_VU0(IADD); +REC_COP2_VU0(IADDI); +REC_COP2_VU0(ISUB); +REC_COP2_VU0(IOR); +REC_COP2_VU0(IAND); +REC_COP2_VU0MS(OPMSUB); +REC_COP2_VU0MS(MADDq); +REC_COP2_VU0MS(MADDi); +REC_COP2_VU0MS(MSUBq); +REC_COP2_VU0MS(MSUBi); +REC_COP2_VU0MS(SUBi); +REC_COP2_VU0MS(SUBq); +REC_COP2_VU0MS(MULi); +REC_COP2_VU0MS(MULq); +REC_COP2_VU0(MAXi); +REC_COP2_VU0(MINIi); +REC_COP2_VU0MS(MUL); +REC_COP2_VU0(MAX); +REC_COP2_VU0MS(MADD); +REC_COP2_VU0MS(MSUB); + +REC_COP2_VU0(MINIx); +REC_COP2_VU0(MINIy); +REC_COP2_VU0(MINIz); +REC_COP2_VU0(MINIw); + +REC_COP2_VU0(MAXx); +REC_COP2_VU0(MAXy); +REC_COP2_VU0(MAXz); +REC_COP2_VU0(MAXw); + +REC_COP2_VU0MS(MULx); +REC_COP2_VU0MS(MULy); +REC_COP2_VU0MS(MULz); +REC_COP2_VU0MS(MULw); + +REC_COP2_VU0MS(ADD); +REC_COP2_VU0MS(ADDi); +REC_COP2_VU0MS(ADDq); +REC_COP2_VU0MS(ADDx); +REC_COP2_VU0MS(ADDy); +REC_COP2_VU0MS(ADDz); +REC_COP2_VU0MS(ADDw); + +REC_COP2_VU0MS(SUBx); +REC_COP2_VU0MS(SUBy); +REC_COP2_VU0MS(SUBz); +REC_COP2_VU0MS(SUBw); + +REC_COP2_VU0MS(MADDx); +REC_COP2_VU0MS(MADDy); +REC_COP2_VU0MS(MADDz); +REC_COP2_VU0MS(MADDw); + +REC_COP2_VU0MS(MSUBx); +REC_COP2_VU0MS(MSUBy); +REC_COP2_VU0MS(MSUBz); +REC_COP2_VU0MS(MSUBw); + +REC_COP2_VU0MS(SUB); +REC_COP2_VU0(MINI); + +////////////////////////////////////////////////////////////////////////// +// Special2 instructions +////////////////////////////////////////////////////////////////////////// + +REC_COP2_VU0CLIP(CLIP); +REC_COP2_VU0(LQI); +REC_COP2_VU0(SQI); +REC_COP2_VU0(LQD); +REC_COP2_VU0(SQD); +REC_COP2_VU0(MTIR); +REC_COP2_VU0(MFIR); +REC_COP2_VU0(ILWR); +REC_COP2_VU0(ISWR); +REC_COP2_VU0(RINIT); +REC_COP2_VU0(RXOR); +REC_COP2_VU0(RNEXT); +REC_COP2_VU0(RGET); + +REC_COP2_VU0(ITOF0); +REC_COP2_VU0(ITOF4); +REC_COP2_VU0(ITOF12); +REC_COP2_VU0(ITOF15); +REC_COP2_VU0(FTOI0); +REC_COP2_VU0(FTOI4); +REC_COP2_VU0(FTOI12); +REC_COP2_VU0(FTOI15); +REC_COP2_VU0MS(MADDA); +REC_COP2_VU0MS(MSUBA); +REC_COP2_VU0MS(MADDAi); +REC_COP2_VU0MS(MADDAq); +REC_COP2_VU0MS(MADDAx); +REC_COP2_VU0MS(MADDAy); +REC_COP2_VU0MS(MADDAz); +REC_COP2_VU0MS(MADDAw); +REC_COP2_VU0MS(MSUBAi); +REC_COP2_VU0MS(MSUBAq); +REC_COP2_VU0MS(MSUBAx); +REC_COP2_VU0MS(MSUBAy); +REC_COP2_VU0MS(MSUBAz); +REC_COP2_VU0MS(MSUBAw); +REC_COP2_VU0MS(ADDAi); +REC_COP2_VU0MS(ADDA); +REC_COP2_VU0MS(SUBA); +REC_COP2_VU0MS(MULA); +REC_COP2_VU0MS(ADDAq); +REC_COP2_VU0MS(ADDAx); +REC_COP2_VU0MS(ADDAy); +REC_COP2_VU0MS(ADDAz); +REC_COP2_VU0MS(ADDAw); +REC_COP2_VU0MS(SUBAi); +REC_COP2_VU0MS(SUBAq); +REC_COP2_VU0MS(SUBAx); +REC_COP2_VU0MS(SUBAy); +REC_COP2_VU0MS(SUBAz); +REC_COP2_VU0MS(SUBAw); +REC_COP2_VU0MS(MULAi); +REC_COP2_VU0MS(MULAq); +REC_COP2_VU0MS(MULAx); +REC_COP2_VU0MS(MULAy); +REC_COP2_VU0MS(MULAz); +REC_COP2_VU0MS(MULAw); +REC_COP2_VU0MS(OPMULA); +REC_COP2_VU0(MOVE); +REC_COP2_VU0MS(DIV); +REC_COP2_VU0MS(SQRT); +REC_COP2_VU0MS(RSQRT); +REC_COP2_VU0(MR32); +REC_COP2_VU0(ABS); + +void recVNOP(){} +void recVWAITQ(){} +INTERPRETATE_COP2_FUNC(CALLMS); +INTERPRETATE_COP2_FUNC(CALLMSR); + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn); + +// information +void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xf; +} + +void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIread = 1<<_Fs_; +} + +void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFwrite = _Fs_; + VUregsn->VFwxyzw= 0xf; +} + +void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIwrite = 1<<_Fs_; +} + +void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, +}; + +void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw, + _vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw, + _vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw, + _vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi, + _vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi, + _vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI, + _vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2, +}; + +void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw, + _vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw, + _vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15, + _vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP, + _vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi, + _vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP, + _vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD, + _vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR, + _vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, +}; + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2t[_Rs_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn) +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + _vuRegsCOP2SPECIAL2t[opc](VU, VUregsn); +} + +// recompilation +void (*recCOP2t[32])() = { + rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, + recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, +}; + +void (*recCOP2_BC2t[32])() = { + recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, +}; + +void (*recCOP2SPECIAL1t[64])() = { + recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, + recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, + recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, + recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, + recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, + recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, + recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, + recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2, +}; + +void (*recCOP2SPECIAL2t[128])() = { + recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw, + recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw, + recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15, + recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP, + recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi, + recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP, + recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD, + recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR, + recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, +}; + +void recCOP22() +{ + cinfo = &g_cop2info; + g_VUregs = &g_pCurInstInfo->vuregs; + VU0.code = cpuRegs.code; + g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2 + recCOP2t[_Rs_](); + _freeX86regs(); +} + +void recCOP2_SPECIAL() +{ + recCOP2SPECIAL1t[_Funct_](); +} + +void recCOP2_BC2() +{ + recCOP2_BC2t[_Rt_](); +} + +void recCOP2_SPECIAL2() +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + recCOP2SPECIAL2t[opc](); +} diff --git a/branches/pcsx2_0.9.1/zlib/ChangeLog b/branches/pcsx2_0.9.1/zlib/ChangeLog new file mode 100644 index 0000000..85b8253 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Lvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/branches/pcsx2_0.9.1/zlib/README b/branches/pcsx2_0.9.1/zlib/README new file mode 100644 index 0000000..718aab2 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/branches/pcsx2_0.9.1/zlib/adler32.c b/branches/pcsx2_0.9.1/zlib/adler32.c new file mode 100644 index 0000000..bc0842f --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/branches/pcsx2_0.9.1/zlib/compress.c b/branches/pcsx2_0.9.1/zlib/compress.c new file mode 100644 index 0000000..e7ea2c5 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/branches/pcsx2_0.9.1/zlib/crc32.c b/branches/pcsx2_0.9.1/zlib/crc32.c new file mode 100644 index 0000000..aa8b984 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/branches/pcsx2_0.9.1/zlib/crc32.h b/branches/pcsx2_0.9.1/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/branches/pcsx2_0.9.1/zlib/deflate.c b/branches/pcsx2_0.9.1/zlib/deflate.c new file mode 100644 index 0000000..efe7b63 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/branches/pcsx2_0.9.1/zlib/deflate.h b/branches/pcsx2_0.9.1/zlib/deflate.h new file mode 100644 index 0000000..26775e9 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/branches/pcsx2_0.9.1/zlib/gzio.c b/branches/pcsx2_0.9.1/zlib/gzio.c new file mode 100644 index 0000000..4cfd64f --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/branches/pcsx2_0.9.1/zlib/infback.c b/branches/pcsx2_0.9.1/zlib/infback.c new file mode 100644 index 0000000..5cf5d22 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/branches/pcsx2_0.9.1/zlib/inffast.c b/branches/pcsx2_0.9.1/zlib/inffast.c new file mode 100644 index 0000000..63aa440 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/branches/pcsx2_0.9.1/zlib/inffast.h b/branches/pcsx2_0.9.1/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/branches/pcsx2_0.9.1/zlib/inffixed.h b/branches/pcsx2_0.9.1/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/branches/pcsx2_0.9.1/zlib/inflate.c b/branches/pcsx2_0.9.1/zlib/inflate.c new file mode 100644 index 0000000..71fe3cc --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/branches/pcsx2_0.9.1/zlib/inflate.h b/branches/pcsx2_0.9.1/zlib/inflate.h new file mode 100644 index 0000000..b696512 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/branches/pcsx2_0.9.1/zlib/inftrees.c b/branches/pcsx2_0.9.1/zlib/inftrees.c new file mode 100644 index 0000000..55fd27b --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/branches/pcsx2_0.9.1/zlib/inftrees.h b/branches/pcsx2_0.9.1/zlib/inftrees.h new file mode 100644 index 0000000..1dbfe53 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/branches/pcsx2_0.9.1/zlib/trees.c b/branches/pcsx2_0.9.1/zlib/trees.c new file mode 100644 index 0000000..d0bce9f --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/branches/pcsx2_0.9.1/zlib/trees.h b/branches/pcsx2_0.9.1/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/branches/pcsx2_0.9.1/zlib/uncompr.c b/branches/pcsx2_0.9.1/zlib/uncompr.c new file mode 100644 index 0000000..82ebef7 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/branches/pcsx2_0.9.1/zlib/zconf.h b/branches/pcsx2_0.9.1/zlib/zconf.h new file mode 100644 index 0000000..b073c9e --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/branches/pcsx2_0.9.1/zlib/zlib.h b/branches/pcsx2_0.9.1/zlib/zlib.h new file mode 100644 index 0000000..d54ac94 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/branches/pcsx2_0.9.1/zlib/zutil.c b/branches/pcsx2_0.9.1/zlib/zutil.c new file mode 100644 index 0000000..db137f8 --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/branches/pcsx2_0.9.1/zlib/zutil.h b/branches/pcsx2_0.9.1/zlib/zutil.h new file mode 100644 index 0000000..e300f7c --- /dev/null +++ b/branches/pcsx2_0.9.1/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/branches/pcsx2_0.9.2/CDVD.c b/branches/pcsx2_0.9.2/CDVD.c new file mode 100644 index 0000000..8f0e6c5 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVD.c @@ -0,0 +1,1852 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PsxCommon.h" +#include "CDVDiso.h" + +cdvdStruct cdvd; + +char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"}; + +char *nCmdName[0x100]= { + "CdSync", "CdNop", "CdStandby", "CdStop", + "CdPause", "CdSeek", "CdRead", "CdReadCDDA", + "CdReadDVDV", "CdGetToc", "", "NCMD_B", + "CdReadKey", "", "sceCdReadXCDDA", "sceCdChgSpdlCtrl", +}; + +char *sCmdName[0x100]= { + "", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands",//sceCdGetMecaconVersion, read/write console id, read renewal date + "", "sceCdTrayState", "sceCdTrayCtrl", "", + "sceCdReadClock", "sceCdWriteClock", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdSetHDMode", "", "", "sceCdPowerOff", + "", "", "sceCdReadILinkID", "sceCdWriteILinkID", /*10*/ + "sceAudioDigitalOut", "sceForbidDVDP", "sceAutoAdjustCtrl", "sceCdReadModelNumber", + "sceWriteModelNumber", "sceCdForbidCD", "sceCdBootCertify", "sceCdCancelPOffRdy", + "sceCdBlueLEDCtl", "", "sceRemote2Read", "sceRemote2_7", + "sceRemote2_6", "sceCdWriteWakeUpTime", "sceCdReadWakeUpTime", "", /*20*/ + "sceCdRcBypassCtl", "", "", "", + "", "sceCdNoticeGameStart", "", "", + "sceCdXBSPowerCtl", "sceCdXLEDCtl", "sceCdBuzzerCtl", "", + "", "sceCdSetMediumRemoval", "sceCdGetMediumRemoval", "sceCdXDVRPReset", /*30*/ + "", "", "__sceCdGetOSDVER", "", + "", "", "", "", + "", "", "", "", + "sceCdOpenConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdCloseConfig", /*40*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*50*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*60*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*70*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "mechacon_auth_0x80", "mechacon_auth_0x81", "mechacon_auth_0x82", "mechacon_auth_0x83", /*80*/ + "mechacon_auth_0x84", "mechacon_auth_0x85", "mechacon_auth_0x86", "mechacon_auth_0x87", + "mechacon_auth_0x88", "", "", "", + "", "sceMgWriteData", "sceMgReadData", "mechacon_auth_0x8F", + "sceMgWriteHeaderStart", "sceMgReadBITLength", "sceMgWriteDatainLength", "sceMgWriteDataoutLength", /*90*/ + "sceMgReadKbit", "sceMgReadKbit2", "sceMgReadKcon", "sceMgReadKcon2", + "sceMgReadIcvPs2", "", "", "", + "", "", "", "", + /*A0, no sCmds above?*/ +}; + +// NVM (eeprom) layout info +typedef struct { + u32 biosVer; // bios version that this eeprom layout is for + s32 config0; // offset of 1st config block + s32 config1; // offset of 2nd config block + s32 config2; // offset of 3rd config block + s32 consoleId; // offset of console id (?) + s32 ilinkId; // offset of ilink id (ilink mac address) + s32 modelNum; // offset of ps2 model number (eg "SCPH-70002") + s32 osdver; // offset of OSDVER for PStwo +} NVMLayout; + +#define NVM_FORMAT_MAX 2 +NVMLayout nvmlayouts[NVM_FORMAT_MAX] = +{ + {0x000, 0x280, 0x300, 0x200, 0x1C8, 0x1C0, 0x1A0, 0x180}, // eeproms from bios v0.00 and up + {0x146, 0x270, 0x2B0, 0x200, 0x1C8, 0x1E0, 0x1B0, 0x180}, // eeproms from bios v1.70 and up +}; + + +unsigned long cdvdReadTime=0; + +#define CDVDREAD_INT(eCycle) PSX_INT(19, eCycle) + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +#define SetResultSize(size) \ + cdvd.ResultC = size; cdvd.ResultP = 0; \ + cdvd.sDataIn&=~0x40; + + +/* is cdvd.Status only for NCMDS? (linuzappz) */ +enum cdvdStatus { + CDVD_STATUS_NONE = 0x00, // not sure ;) + CDVD_STATUS_SEEK_COMPLETE = 0x0A, +}; + +static int mg_BIToffset(u8 *buffer); + +FILE *_cdvdOpenMechaVer() { + char *ptr; + int i; + char file[256]; + char Bios[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the mecha ver file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "MEC"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenMechaVer: Error creating %s", file); + exit(1); + } + fputc(0x03, fd); + fputc(0x06, fd); + fputc(0x02, fd); + fputc(0x00, fd); + } + return fd; +} +s32 cdvdGetMechaVer(u8* ver) +{ + FILE* fd = _cdvdOpenMechaVer(); + if (fd == NULL) return 1; + fseek(fd, 0, SEEK_SET); + fread(ver, 1, 4, fd); + fclose(fd); + return 0; +} + +FILE *_cdvdOpenNVM() { + char *ptr; + int i; + char Bios[256]; + char file[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the nvm file + sprintf(file, "%s", Bios); + ptr = file; i = strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "NVM"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenNVM: Error creating %s", file); + exit(1); + } + for (i=0; i<1024; i++) fputc(0, fd); + } + return fd; +} + +// +// the following 'cdvd' functions all return 0 if successful +// + +s32 cdvdReadNVM(u8 *dst, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fread(dst, 1, bytes, fd); + fclose(fd); + return 0; +} +s32 cdvdWriteNVM(const u8 *src, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fwrite(src, 1, bytes, fd); + fclose(fd); + return 0; +} + +#define GET_NVM_DATA(buff, offset, size, fmtOffset) getNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) +#define SET_NVM_DATA(buff, offset, size, fmtOffset) setNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) + +s32 getNvmData(u8* buffer, s32 offset, s32 size, u32 biosVersion, s32 fmtOffset) +{ + // find the correct bios version + NVMLayout* nvmLayout = NULL; + s32 nvmIdx; + for(nvmIdx=0; nvmIdx= cdvd.CNumBlocks) + return 1; + else if( + ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))|| + ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))|| + ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7)) + ) + { + memcpy(config, 0, 16); + return 0; + } + + // get config data + if(cdvd.COffset == 0) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config0); else + if(cdvd.COffset == 2) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); + else + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); +} +s32 cdvdWriteConfig(const u8* config) +{ + // make sure its in write mode + if(cdvd.CReadWrite != 1) + return 1; + // check if block index is in bounds + else if(cdvd.CBlockIndex >= cdvd.CNumBlocks) + return 1; + else if( + ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))|| + ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))|| + ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7)) + ) + return 0; + + // get config data + if(cdvd.COffset == 0) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config0); else + if(cdvd.COffset == 2) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); + else + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); +} + + +void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { + char str[256]; + int numbers; + int letters; + unsigned int key_0_3; + unsigned char key_4; + unsigned char key_14; + char exeName[12]; + + // get main elf name + GetPS2ElfName(str); + sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); + SysPrintf("exeName = %s\n",exeName); + + // convert the number characters to a real 32bit number + numbers = ((((exeName[5] - '0'))*10000) + + (((exeName[ 6] - '0'))*1000) + + (((exeName[ 7] - '0'))*100) + + (((exeName[ 9] - '0'))*10) + + (((exeName[10] - '0'))*1) ); + + // combine the lower 7 bits of each char + // to make the 4 letters fit into a single u32 + letters = (int)((exeName[3]&0x7F)<< 0) | + (int)((exeName[2]&0x7F)<< 7) | + (int)((exeName[1]&0x7F)<<14) | + (int)((exeName[0]&0x7F)<<21); + + // calculate magic numbers + key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 + key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07 + key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03 + + // clear key values + memset(key, 0, 16); + + // store key values + key[ 0] = (key_0_3&0x000000FF)>> 0; + key[ 1] = (key_0_3&0x0000FF00)>> 8; + key[ 2] = (key_0_3&0x00FF0000)>>16; + key[ 3] = (key_0_3&0xFF000000)>>24; + key[ 4] = key_4; + + if(arg2 == 75) + { + key[14] = key_14; + key[15] = 0x05; + } + else if(arg2 == 3075) + { + key[15] = 0x01; + } + else if(arg2 == 4246) + { + // 0x0001F2F707 = sector 0x0001F2F7 dec 0x07 + key[ 0] = 0x07; + key[ 1] = 0xF7; + key[ 2] = 0xF2; + key[ 3] = 0x01; + key[ 4] = 0x00; + key[15] = 0x01; + } + else + { + key[15] = 0x01; + } + + SysPrintf("CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X\n",cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15]); +} + +s32 cdvdGetToc(void* toc) { + s32 ret = CDVDgetTOC(toc); + if(ret == -1) ret = 0x80; + return ret; +/* + cdvdTN diskInfo; + cdvdTD trackInfo; + u8 _time[3]; + u32 type; + int i, err; + + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + type = CDVDgetDiskType(); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + if (type == CDVD_TYPE_CDDA) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x01; + } else + if (type == CDVD_TYPE_PS2DVD) { + if (trackInfo.lsn >= (2048*1024)) { // dual sided + PSXMu8(HW_DMA3_MADR+ 0) = 0x24; + } else { + PSXMu8(HW_DMA3_MADR+ 0) = 0x04; + } + } else + if (type == CDVD_TYPE_PS2CD) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x41; + } + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x04) { + PSXMu8(HW_DMA3_MADR+ 1) = 0x02; + PSXMu8(HW_DMA3_MADR+ 2) = 0xF2; + PSXMu8(HW_DMA3_MADR+ 3) = 0x00; + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x20) { + PSXMu8(HW_DMA3_MADR+ 4) = 0x41; + PSXMu8(HW_DMA3_MADR+ 5) = 0x95; + } else { + PSXMu8(HW_DMA3_MADR+ 4) = 0x86; + PSXMu8(HW_DMA3_MADR+ 5) = 0x72; + } + PSXMu8(HW_DMA3_MADR+ 6) = 0x00; + PSXMu8(HW_DMA3_MADR+ 7) = 0x00; + PSXMu8(HW_DMA3_MADR+ 8) = 0x00; + PSXMu8(HW_DMA3_MADR+ 9) = 0x00; + PSXMu8(HW_DMA3_MADR+10) = 0x00; + PSXMu8(HW_DMA3_MADR+11) = 0x00; + + PSXMu8(HW_DMA3_MADR+12) = 0x00; + PSXMu8(HW_DMA3_MADR+13) = 0x00; + PSXMu8(HW_DMA3_MADR+14) = 0x00; + PSXMu8(HW_DMA3_MADR+15) = 0x00; + + PSXMu8(HW_DMA3_MADR+16) = 0x00; + PSXMu8(HW_DMA3_MADR+17) = 0x03; + PSXMu8(HW_DMA3_MADR+18) = 0x00; + PSXMu8(HW_DMA3_MADR+19) = 0x00; + + } else { + PSXMu8(HW_DMA3_MADR+ 1) = 0x00; + PSXMu8(HW_DMA3_MADR+ 2) = 0xA0; + PSXMu8(HW_DMA3_MADR+ 7) = itob(diskInfo.strack);//Number of FirstTrack + + PSXMu8(HW_DMA3_MADR+12) = 0xA1; + PSXMu8(HW_DMA3_MADR+17) = itob(diskInfo.etrack);//Number of LastTrack + + PSXMu8(HW_DMA3_MADR+22) = 0xA2;//DiskLength + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+27) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+28) = itob(_time[1]); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) { + err=CDVDgetTD(i, &trackInfo); + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+i*10+30) = trackInfo.type; + PSXMu8(HW_DMA3_MADR+i*10+32) = err == -1 ? 0 : itob(i); //number + PSXMu8(HW_DMA3_MADR+i*10+37) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+i*10+38) = itob(_time[1]); + PSXMu8(HW_DMA3_MADR+i*10+39) = itob(_time[0]); + } + } +*/ +} + +s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq) +{ + s32 ret = CDVDreadSubQ(lsn, subq); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayOpen() +{ + s32 ret = CDVDctrlTrayOpen(); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayClose() +{ + s32 ret = CDVDctrlTrayClose(); + if(ret == -1) ret = 0x80; + return ret; +} + +// Modified by (efp) - 16/01/2006 +// checks if tray was opened since last call to this func +s32 cdvdGetTrayStatus() +{ + s32 ret = CDVDgetTrayStatus(); + // get current tray state + if (cdCaseopen) return(CDVD_TRAY_OPEN); + + + if (ret == -1) return(CDVD_TRAY_CLOSE); + return(ret); +} +// Note: Is tray status being kept as a var here somewhere? +// cdvdNewDiskCB() can update it's status as well... + +// Modified by (efp) - 16/01/2006 +s32 cdvdGetDiskType() { + // defs 0.9.0 + if(CDVDnewDiskCB) return(cdvd.Type); + + // defs.0.8.1 + if(cdvdGetTrayStatus() == CDVD_TRAY_OPEN) return(CDVD_TYPE_NODISC); + // Note: Hmmm. Need to modify cdvd.Type as well? + // or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway. + + cdvd.Type = CDVDgetDiskType(); + if (cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if (GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? + return(cdvd.Type); +} // END cdvdGetDiskType() + + +// check whether disc is single or dual layer +// if its dual layer, check what the disctype is and what sector number +// layer1 starts at +// +// args: gets value for dvd type (0=single layer, 1=ptp, 2=otp) +// gets value for start lsn of layer1 +// returns: 1 if on dual layer disc +// 0 if not on dual layer disc +s32 cdvdReadDvdDualInfo(s32* dualType, u32* layer1Start) +{ + u8 toc[2064]; + *dualType = 0; + *layer1Start = 0; + + // if error getting toc, settle for single layer disc ;) + if(cdvdGetToc(toc)) + return 0; + if(toc[14] & 0x60) + { + if(toc[14] & 0x10) + { + // otp dvd + *dualType = 2; + *layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1; + } + else + { + // ptp dvd + *dualType = 1; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + } + else + { + // single layer dvd + *dualType = 0; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + + return 1; +} + + +void cdvdReset() { + memset(&cdvd, 0, sizeof(cdvd)); + cdvd.sDataIn = 0x40; + cdvd.Ready = 0x4e; + cdCaseopen = 0; + cdvd.Speed = 4; + cdvd.BlockSize = 2064; + cdvdReadTimeRcnt(0); +} +void cdvdReadTimeRcnt(int mode){ // Mode 0 is DVD, Mode 1 is CD + int readsize = 0; // 1 Sector size + int amount = 0; // Total bytes transfered at 1x speed + //if(mode) amount = 153600; + //else + amount = 1280000; + + readsize = amount / cdvd.BlockSize; // Time taken for 1 sector to be read + cdvdReadTime = ((PSXCLK / readsize) / BIAS) / cdvd.Speed; +} + +int cdvdFreeze(gzFile f, int Mode) { + gzfreeze(&cdvd, sizeof(cdvd)); + if (Mode == FREEZE_LOAD) { + if (cdvd.Reading) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + } + } + + return 0; +} + +int cdvdInterrupt() { + return 1; +} + +// Modified by (efp) - 16/01/2006 +void cdvdNewDiskCB() { + cdvd.Type = CDVDgetDiskType(); + if(cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if(GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? +} // END cdvdNewDiskCB() + +void mechaDecryptBytes(unsigned char* buffer, int size) +{ + int i; + + int shiftAmount = (cdvd.decSet>>4) & 7; + int doXor = (cdvd.decSet) & 1; + int doShift = (cdvd.decSet) & 2; + unsigned char key = cdvd.Key[4]; + + for(i=0; i>shiftAmount) | (buffer[i]<<(8-shiftAmount)); + } +} + +int cdvdReadSector() { + s32 bcr; + +#ifdef CDR_LOG + CDR_LOG("SECTOR %d (BCR %x;%x)\n", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16); +#endif + bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4; + if (bcr < cdvd.BlockSize) { + //SysPrintf("*PCSX2*: cdvdReadSector: bcr < cdvd.BlockSize; %x < %x\n", bcr, cdvd.BlockSize); + if (HW_DMA3_CHCR & 0x01000000) { + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + } + return -1; + } + + // if raw dvd sector 'fill in the blanks' + if (cdvd.BlockSize == 2064) { + // get info on dvd type and layer1 start + u32 layer1Start; + s32 dualType; + s32 layerNum; + u32 lsn = cdvd.Sector; + cdvdReadDvdDualInfo(&dualType, &layer1Start); + + if((dualType == 1) && (lsn >= layer1Start)) { + // dual layer ptp disc + layerNum = 1; + lsn = lsn-layer1Start + 0x30000; + } else if((dualType == 2) && (lsn >= layer1Start)) { + // dual layer otp disc + layerNum = 1; + lsn = ~(layer1Start+0x30000 - 1); + } else { + // single layer disc + // or on first layer of dual layer disc + layerNum = 0; + lsn += 0x30000; + } // ENDLONGIF- Assumed the other dualType is 0. + + PSXMu8(HW_DMA3_MADR+0) = 0x20 | layerNum; + PSXMu8(HW_DMA3_MADR+1) = (u8)(lsn >> 16); + PSXMu8(HW_DMA3_MADR+2) = (u8)(lsn >> 8); + PSXMu8(HW_DMA3_MADR+3) = (u8)(lsn ); + + // sector IED (not calculated at present) + PSXMu8(HW_DMA3_MADR+4) = 0; + PSXMu8(HW_DMA3_MADR+5) = 0; + + // sector CPR_MAI (not calculated at present) + PSXMu8(HW_DMA3_MADR+ 6) = 0; + PSXMu8(HW_DMA3_MADR+ 7) = 0; + PSXMu8(HW_DMA3_MADR+ 8) = 0; + PSXMu8(HW_DMA3_MADR+ 9) = 0; + PSXMu8(HW_DMA3_MADR+10) = 0; + PSXMu8(HW_DMA3_MADR+11) = 0; + + // normal 2048 bytes of sector data + memcpy_amd(PSXM(HW_DMA3_MADR+12), cdr.pTransfer, 2048); + + // 4 bytes of edc (not calculated at present) + PSXMu8(HW_DMA3_MADR+2060) = 0; + PSXMu8(HW_DMA3_MADR+2061) = 0; + PSXMu8(HW_DMA3_MADR+2062) = 0; + PSXMu8(HW_DMA3_MADR+2063) = 0; + } else { + // normal read + memcpy_amd(PSXM(HW_DMA3_MADR), cdr.pTransfer, cdvd.BlockSize); + } + // decrypt sector's bytes + if(cdvd.decSet) + mechaDecryptBytes((unsigned char*)PSXM(HW_DMA3_MADR), cdvd.BlockSize); + +// SysPrintf("sector %x;%x;%x\n", PSXMu8(HW_DMA3_MADR+0), PSXMu8(HW_DMA3_MADR+1), PSXMu8(HW_DMA3_MADR+2)); + + HW_DMA3_BCR_H16-= (cdvd.BlockSize / (HW_DMA3_BCR_L16*4)); + HW_DMA3_MADR+= cdvd.BlockSize; + //FreezeMMXRegs(0); + + return 0; +} + +int cdvdReadInterrupt() { + + //SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); + if (cdvd.Readed == 0) { + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + cdvd.Readed = 1; + cdvd.Status = CDVD_STATUS_SEEK_COMPLETE; + + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + if (cdvd.Reading == 1) { + if (cdvd.RErr == 0) { + cdr.pTransfer = CDVDgetBuffer(); + } else cdr.pTransfer = NULL; + if (cdr.pTransfer == NULL) { + cdvd.RetryCntP++; + SysPrintf("READ ERROR %d\n", cdvd.Sector); + if (cdvd.RetryCntP <= cdvd.RetryCnt) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + } + cdvd.Reading = 0; + } + if (cdvdReadSector() == -1) { + assert( (int)cdvdReadTime > 0 ); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + cdvd.Sector++; + + if (--cdvd.nSectors <= 0) { + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + return 1; + } + + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdr.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; +} + +void cdvdVsync() { + cdvd.RTCcount++; + if (cdvd.RTCcount < 60) return; + cdvd.RTCcount = 0; + + cdvd.RTC.second++; + if (cdvd.RTC.second < 60) return; + cdvd.RTC.second = 0; + + cdvd.RTC.minute++; + if (cdvd.RTC.minute < 60) return; + cdvd.RTC.minute = 0; + + cdvd.RTC.hour++; + if (cdvd.RTC.hour < 24) return; + cdvd.RTC.hour = 0; + + cdvd.RTC.day++; + if (cdvd.RTC.day < 30) return; + cdvd.RTC.day = 0; + + cdvd.RTC.month++; + if (cdvd.RTC.month < 12) return; + cdvd.RTC.month = 0; + + cdvd.RTC.year++; +} + + +u8 cdvdRead04(void) { // NCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead04(NCMD) %x\n", cdvd.nCommand); +#endif + return cdvd.nCommand; +} + +u8 cdvdRead05(void) { // N-READY +#ifdef CDR_LOG + CDR_LOG("cdvdRead05(NReady) %x\n", cdvd.Ready); +#endif + return cdvd.Ready; +} + +u8 cdvdRead06(void) { // ERROR +#ifdef CDR_LOG + CDR_LOG("cdvdRead06(Error) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead07(void) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdRead07(Break) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead08(void) { // INTR_STAT +#ifdef CDR_LOG + CDR_LOG("cdvdRead08(IntrReason) %x\n", cdvd.PwOff); +#endif + return cdvd.PwOff; +} + +u8 cdvdRead0A(void) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdRead0A(Status) %x\n", cdvd.Status); +#endif + return cdvd.Status; +} + +u8 cdvdRead0B(void) { // TRAY-STATE (if tray has been opened) + u8 tray = cdvdGetTrayStatus(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0B(Tray) %x\n", tray); +#endif + return tray; +} + +u8 cdvdRead0C(void) { // CRT MINUTE +#ifdef CDR_LOG + CDR_LOG("cdvdRead0C(Min) %x\n", itob((u8)(cdvd.Sector/(60*75)))); +#endif + return itob((u8)(cdvd.Sector/(60*75))); +} + +u8 cdvdRead0D(void) { // CRT SECOND +#ifdef CDR_LOG + CDR_LOG("cdvdRead0D(Sec) %x\n", itob((u8)((cdvd.Sector/75)%60)+2)); +#endif + return itob((u8)((cdvd.Sector/75)%60)+2); +} + +u8 cdvdRead0E(void) { // CRT FRAME +#ifdef CDR_LOG + CDR_LOG("cdvdRead0E(Frame) %x\n", itob((u8)(cdvd.Sector%75))); +#endif + return itob((u8)(cdvd.Sector%75)); +} + +u8 cdvdRead0F(void) { // TYPE + u8 type = cdvdGetDiskType(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0F(Disc Type) %x\n", type); +#endif + return type; +} + +u8 cdvdRead13(void) { // UNKNOWN +#ifdef CDR_LOG + CDR_LOG("cdvdRead13(Unknown) %x\n", 4); +#endif + return 4; +} + +u8 cdvdRead15(void) { // RSV +#ifdef CDR_LOG + CDR_LOG("cdvdRead15(RSV)\n"); +#endif + return 0x01; // | 0x80 for ATAPI mode +} + +u8 cdvdRead16(void) { // SCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead16(SCMD) %x\n", cdvd.sCommand); +#endif + return cdvd.sCommand; +} + +u8 cdvdRead17(void) { // SREADY +#ifdef CDR_LOG + CDR_LOG("cdvdRead17(SReady) %x\n", cdvd.sDataIn); +#endif + return cdvd.sDataIn; +} + +u8 cdvdRead18(void) { // SDATAOUT + u8 ret=0; + + if ((cdvd.sDataIn & 0x40) == 0) { + if (cdvd.ResultP < cdvd.ResultC) { + cdvd.ResultP++; + if (cdvd.ResultP >= cdvd.ResultC) cdvd.sDataIn|= 0x40; + ret = cdvd.Result[cdvd.ResultP-1]; + } + } + +#ifdef CDR_LOG + CDR_LOG("cdvdRead18(SDataOut) %x (ResultC=%d, ResultP=%d)\n", ret, cdvd.ResultC, cdvd.ResultP); +#endif + + return ret; +} + +u8 cdvdRead20(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead20(Key0) %x\n", cdvd.Key[0]); +#endif + return cdvd.Key[0]; +} + +u8 cdvdRead21(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead21(Key1) %x\n", cdvd.Key[1]); +#endif + return cdvd.Key[1]; +} + +u8 cdvdRead22(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead22(Key2) %x\n", cdvd.Key[2]); +#endif + return cdvd.Key[2]; +} + +u8 cdvdRead23(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead23(Key3) %x\n", cdvd.Key[3]); +#endif + return cdvd.Key[3]; +} + +u8 cdvdRead24(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead24(Key4) %x\n", cdvd.Key[4]); +#endif + return cdvd.Key[4]; +} + +u8 cdvdRead28(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead28(Key5) %x\n", cdvd.Key[5]); +#endif + return cdvd.Key[5]; +} + +u8 cdvdRead29(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead29(Key6) %x\n", cdvd.Key[6]); +#endif + return cdvd.Key[6]; +} + +u8 cdvdRead2A(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2A(Key7) %x\n", cdvd.Key[7]); +#endif + return cdvd.Key[7]; +} + +u8 cdvdRead2B(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2B(Key8) %x\n", cdvd.Key[8]); +#endif + return cdvd.Key[8]; +} + +u8 cdvdRead2C(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2C(Key9) %x\n", cdvd.Key[9]); +#endif + return cdvd.Key[9]; +} + +u8 cdvdRead30(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead30(Key10) %x\n", cdvd.Key[10]); +#endif + return cdvd.Key[10]; +} + +u8 cdvdRead31(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead31(Key11) %x\n", cdvd.Key[11]); +#endif + return cdvd.Key[11]; +} + +u8 cdvdRead32(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead32(Key12) %x\n", cdvd.Key[12]); +#endif + return cdvd.Key[12]; +} + +u8 cdvdRead33(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead33(Key13) %x\n", cdvd.Key[13]); +#endif + return cdvd.Key[13]; +} + +u8 cdvdRead34(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead34(Key14) %x\n", cdvd.Key[14]); +#endif + return cdvd.Key[14]; +} + +u8 cdvdRead38(void) { // valid parts of key data (first and last are valid) +#ifdef CDR_LOG + CDR_LOG("cdvdRead38(KeysValid) %x\n", cdvd.Key[15]); +#endif + return cdvd.Key[15]; +} + +u8 cdvdRead39(void) { // KEY-XOR +#ifdef CDR_LOG + CDR_LOG("cdvdRead39(KeyXor) %x\n", cdvd.KeyXor); +#endif + return cdvd.KeyXor; +} + +u8 cdvdRead3A(void) { // DEC_SET +#ifdef CDR_LOG + CDR_LOG("cdvdRead3A(DecSet) %x\n", cdvd.decSet); +#endif + SysPrintf("DecSet Read: %02X\n", cdvd.decSet); + return cdvd.decSet; +} + + + +void cdvdWrite04(u8 rt) { // NCOMMAND + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)\n", nCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.nCommand = rt; + cdvd.Status = CDVD_STATUS_NONE; + switch (rt) { + case 0x00: // CdNop + case 0x01: // CdNop_ + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + // from an emulation point of view there is not much need to do anything for these + case 0x02: // CdStandby + case 0x03: // CdStop + case 0x04: // CdPause + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + // should we change the sector location here? + case 0x05: // CdSeek + cdvd.Sector = *(int*)(cdvd.Param+0); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + case 0x06: // CdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; // CD + case 0x02: cdvd.Speed = 2; break; // CD + case 0x03: cdvd.Speed = 4; break; // CD + case 0x04: cdvd.Speed = 12; break; // CD + default: cdvd.Speed = 24; break; // CD + } + switch (cdvd.Param[10]) { + case 2: cdvd.ReadMode = CDVD_MODE_2340; cdvd.BlockSize = 2340; break; + case 1: cdvd.ReadMode = CDVD_MODE_2328; cdvd.BlockSize = 2328; break; + case 0: default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break; + } + if(cdvd.Speed > 4) cdvdReadTimeRcnt(1); + else cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "CdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + + break; + + case 0x07: // CdReadCDDA + case 0x0E: // CdReadXCDDA + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; + case 0x02: cdvd.Speed = 2; break; + case 0x03: cdvd.Speed = 4; break; + case 0x04: cdvd.Speed = 12; break; + default: cdvd.Speed = 24; break; + } + switch (cdvd.Param[10]) { + case 1: cdvd.ReadMode = CDVD_MODE_2368; cdvd.BlockSize = 2368; break; + case 2: + case 0: cdvd.ReadMode = CDVD_MODE_2352; cdvd.BlockSize = 2352; break; + } + cdvdReadTimeRcnt(1); + SysPrintf("CdAudioRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + break; + + case 0x08: // DvdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + cdvd.Speed = 4; + cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2064; // Why oh why was it 2064 + cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "DvdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + break; + + case 0x09: // CdGetToc & cdvdman_call19 + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + cdvdGetToc(PSXM(HW_DMA3_MADR)); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + break; + + case 0x0C: // CdReadKey + { + unsigned char arg0 = cdvd.Param[0]; + unsigned short arg1 = cdvd.Param[1] | (cdvd.Param[2]<<8); + unsigned int arg2 = cdvd.Param[3] | (cdvd.Param[4]<<8) | (cdvd.Param[5]<<16) | (cdvd.Param[6]<<24); + SysPrintf("cdvdReadKey(%d, %d, %d)\n", arg0, arg1, arg2); + cdvdReadKey(arg0, arg1, arg2, cdvd.Key); + cdvd.KeyXor = 0x00; + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + } + + case 0x0F: // CdChgSpdlCtrl + SysPrintf("sceCdChgSpdlCtrl(%d)\n", cdvd.Param[0]); + cdvd.PwOff = 1;//cmdcmplt + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + default: + SysPrintf("NCMD Unknown %x\n", rt); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + } + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite05(u8 rt) { // NDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite05(NDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite06(u8 rt) { // HOWTO +#ifdef CDR_LOG + CDR_LOG("cdvdWrite06(HowTo) %x\n", rt); +#endif + cdvd.HowTo = rt; +} + +void cdvdWrite07(u8 rt) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdWrite07(Break) %x\n", rt); +#endif + SysPrintf("*PCSX2*: CDVD BREAK %x\n" , rt); +} + +void cdvdWrite08(u8 rt) { // INTR_STAT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite08(IntrReason) = ACK(%x)\n", rt); +#endif + cdvd.PwOff &= ~rt; +} + +void cdvdWrite0A(u8 rt) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0A(Status) %x\n", rt); +#endif +} + +void cdvdWrite0F(u8 rt) { // TYPE +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0F(Type) %x\n", rt); +#endif +SysPrintf("*PCSX2*: CDVD TYPE %x\n", rt); +} + +void cdvdWrite14(u8 rt) { // PS1 MODE?? + u32 cycle = psxRegs.cycle; + psxReset(); + psxHu32(0x1f801450) = 0x8; + psxHu32(0x1f801078) = 1; + psxRegs.cycle = cycle; + +#ifdef PCSX2_DEVBUILD + varLog|= 0x10000000;// | 0x00400000;// | 0x1fe00000; +#endif +} + +void cdvdWrite16(u8 rt) { // SCOMMAND +// cdvdTN diskInfo; +// cdvdTD trackInfo; +// int i, lbn, type, min, sec, frm, address; + int address; + u8 tmp; + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)\n", sCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.sCommand = rt; + switch (rt) { + +// case 0x01: // GetDiscType - from cdvdman (0:1) +// SetResultSize(1); +// cdvd.Result[0] = 0; +// break; + + case 0x02: // CdReadSubQ (0:11) + SetResultSize(11); + cdvd.Result[0] = cdvdReadSubQ(cdvd.Sector, (cdvdSubQ*)&cdvd.Result[1]); + break; + + case 0x03: // Mecacon-command + if(cdvd.Param[0]==0x00) { + // get mecha version (1:4) + SetResultSize(4); + cdvdGetMechaVer(&cdvd.Result[0]); + } + else if(cdvd.Param[0]==0x44) { + // write console ID (9:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConsoleID(&cdvd.Param[1]); + } + else if(cdvd.Param[0]==0x45) { + // read console ID (1:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadConsoleID(&cdvd.Result[1]); + } + else if(cdvd.Param[0]==0xFD) { + // _sceCdReadRenewalDate (1:6) BCD + SetResultSize(6); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0x04;//year + cdvd.Result[2] = 0x12;//month + cdvd.Result[3] = 0x10;//day + cdvd.Result[4] = 0x01;//hour + cdvd.Result[5] = 0x30;//min + } else { + SetResultSize(1); + cdvd.Result[0] = 0x80; + SysPrintf("*Unknown Mecacon Command param[0]=%02X\n", cdvd.Param[0]); + } + break; + + case 0x05: // CdTrayReqState (0:1) - resets the tray open detection + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x06: // CdTrayCtrl (1:1) + SetResultSize(1); + if(cdvd.Param[0] == 0) + cdvd.Result[0] = cdvdCtrlTrayOpen(); + else + cdvd.Result[0] = cdvdCtrlTrayClose(); + break; + + case 0x08: // CdReadRTC (0:8) + SetResultSize(8); + memcpy_amd(cdvd.Result, (u8*)&cdvd.RTC, 8); + /* do not uncomment this by now, it kinda makes + things a bit more random for debugging (linuz) */ +/* + { + time_t sysTime; + struct tm* utcTime; + time(&sysTime); + utcTime = gmtime(&sysTime); + cdvd.RTC.second =itob((u8)utcTime->tm_sec); + cdvd.RTC.minute =itob((u8)utcTime->tm_min); + cdvd.RTC.hour =itob((u8)utcTime->tm_hour); // add 8 to the hours (the ps2 wants it this way) + cdvd.RTC.day =itob((u8)utcTime->tm_mday); + cdvd.RTC.month =itob((u8)utcTime->tm_mon); + cdvd.RTC.year =itob((u8)(utcTime->tm_year+100)); + cdvd.RTC.pad =0; + } +*/ + break; + + case 0x09: // sceCdWriteRTC (7:1) + SetResultSize(1); + cdvd.Result[0] = 0; + memcpy_amd((u8*)&cdvd.RTC, cdvd.Param, 7); + cdvd.RTC.pad = 0; + break; + + case 0x0A: // sceCdReadNVM (2:3) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + if (address < 512) { + SetResultSize(3); + cdvd.Result[0] = cdvdReadNVM(&cdvd.Result[1], address*2, 2); + // swap bytes around + tmp = cdvd.Result[1]; + cdvd.Result[1] = cdvd.Result[2]; + cdvd.Result[2] = tmp; + } else { + SetResultSize(1); + cdvd.Result[0] = 0xff; + } + break; + + case 0x0B: // sceCdWriteNVM (4:1) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + SetResultSize(1); + if (address < 512) { + // swap bytes around + tmp = cdvd.Param[2]; + cdvd.Param[2] = cdvd.Param[3]; + cdvd.Param[3] = tmp; + cdvd.Result[0] = cdvdWriteNVM(&cdvd.Param[2], address*2, 2); + } else { + cdvd.Result[0] = 0xff; + } + break; + +// case 0x0C: // sceCdSetHDMode (1:1) +// break; + + + case 0x0F: // sceCdPowerOff (0:1)- Call74 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x12: // sceCdReadILinkId (0:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadILinkID(&cdvd.Result[1]); + break; + + case 0x13: // sceCdWriteILinkID (8:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteILinkID(&cdvd.Param[1]); + break; + + case 0x14: // CdCtrlAudioDigitalOut (1:1) + //parameter can be 2, 0, ... + SetResultSize(1); + cdvd.Result[0] = 0; //8 is a flag; not used + break; + + case 0x15: // sceCdForbidDVDP (0:1) + //SysPrintf("sceCdForbidDVDP\n"); + SetResultSize(1); + cdvd.Result[0] = 5; + break; + + case 0x16: // AutoAdjustCtrl - from cdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x17: // CdReadModelNumber (1:9) - from xcdvdman + SetResultSize(9); + cdvd.Result[0] = cdvdReadModelNumber(&cdvd.Result[1], cdvd.Param[0]); + break; + + case 0x18: // CdWriteModelNumber (9:1) - from xcdvdman + SetResultSize(1); + cdvd.Result[0] = cdvdWriteModelNumber(&cdvd.Param[1], cdvd.Param[0]); + break; + +// case 0x19: // sceCdForbidRead (0:1) - from xcdvdman +// break; + + case 0x1A: // sceCdBootCertify (4:1)//(4:16 in psx?) + SetResultSize(1);//on input there are 4 bytes: 1;?10;J;C for 18000; 1;60;E;C for 39002 from ROMVER + cdvd.Result[0]=1;//i guess that means okay + break; + + case 0x1B: // sceCdCancelPOffRdy (0:1) - Call73 from Xcdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x1C: // sceCdBlueLEDCtl (1:1) - Call72 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x1D: // cdvdman_call116 (0:5) - In V10 Bios +// break; + + case 0x1E: // sceRemote2Read (0:5) - // 00 14 AA BB CC -> remote key code + SetResultSize(5); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x14; + cdvd.Result[2] = 0x00; + cdvd.Result[3] = 0x00; + cdvd.Result[4] = 0x00; + break; + +// case 0x1F: // sceRemote2_7 (2:1) - cdvdman_call117 +// break; + + case 0x20: // sceRemote2_6 (0:3) // 00 01 00 + SetResultSize(3); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x01; + cdvd.Result[2] = 0x00; + break; + +// case 0x21: // sceCdWriteWakeUpTime (8:1) +// break; + + case 0x22: // sceCdReadWakeUpTime (0:10) + SetResultSize(10); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0; + cdvd.Result[2] = 0; + cdvd.Result[3] = 0; + cdvd.Result[4] = 0; + cdvd.Result[5] = 0; + cdvd.Result[6] = 0; + cdvd.Result[7] = 0; + cdvd.Result[8] = 0; + cdvd.Result[9] = 0; + break; + + case 0x24: // sceCdRCBypassCtrl (1:1) - In V10 Bios + // FIXME: because PRId<0x23, the bit 0 of sio2 don't get updated 0xBF808284 + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x25: // cdvdman_call120 (1:1) - In V10 Bios +// break; + +// case 0x26: // cdvdman_call128 (0,3) - In V10 Bios +// break; + +// case 0x27: // cdvdman_call148 (0:13) - In V10 Bios +// break; + +// case 0x28: // cdvdman_call150 (1:1) - In V10 Bios +// break; + + case 0x29: //sceCdNoticeGameStart (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x2C: //sceCdXBSPowerCtl (2:2) +// break; + +// case 0x2D: //sceCdXLEDCtl (2:2) +// break; + +// case 0x2E: //sceCdBuzzerCtl (0:1) +// break; + +// case 0x2F: //cdvdman_call167 (16:1) +// break; + +// case 0x30: //cdvdman_call169 (1:9) +// break; + + case 0x31: //sceCdSetMediumRemoval (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x32: //sceCdGetMediumRemoval (0:2) + SetResultSize(2); + cdvd.Result[0] = 0; + cdvd.Result[0] = 0; + break; + +// case 0x33: //sceCdXDVRPReset (1:1) +// break; + + case 0x36: //cdvdman_call189 [__sceCdGetOSDVER - made up name] (0:15) + SetResultSize(15); + cdvd.Result[0] = cdvdReadOSDVER(&cdvd.Result[3]); + cdvd.Result[1] = 0;//0x10 - encryption zone == (1< cdvd.mg_maxsize) + cdvd.Result[0] = 0x80; + else{ + memcpy(cdvd.mg_buffer + cdvd.mg_size, cdvd.Param, cdvd.ParamC); + cdvd.mg_size += cdvd.ParamC; + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + } + break; + + case 0x8E: // sceMgReadData + SetResultSize(min(16, cdvd.mg_size)); + memcpy_amd(cdvd.Result, cdvd.mg_buffer, cdvd.ResultC); + cdvd.mg_size -= cdvd.ResultC; + memcpy_amd(cdvd.mg_buffer, cdvd.mg_buffer+cdvd.ResultC, cdvd.mg_size); + break; + + case 0x88: // secrman: __mechacon_auth_0x88 //for now it is the same; so, fall;) + case 0x8F: // secrman: __mechacon_auth_0x8F + SetResultSize(1);//in:0 + if (cdvd.mg_datatype == 1){// header data + int bit_ofs, i; + + if (cdvd.mg_maxsize != cdvd.mg_size) goto fail_pol_cal; + if (cdvd.mg_size < 0x20) goto fail_pol_cal; + if (cdvd.mg_size != *(u16*)&cdvd.mg_buffer[0x14]) goto fail_pol_cal; + SysPrintf("[MG] ELF_size=0x%X Hdr_size=0x%X unk=0x%X flags=0x%X count=%d zones=", + *(u32*)&cdvd.mg_buffer[0x10], *(u16*)&cdvd.mg_buffer[0x14], *(u16*)&cdvd.mg_buffer[0x16], + *(u16*)&cdvd.mg_buffer[0x18], *(u16*)&cdvd.mg_buffer[0x1A]); + for (i=0; i<8; i++) + if (cdvd.mg_buffer[0x1C] & (1<> 0) & 0xFF; + cdvd.Result[2] = (cdvd.mg_size >> 8) & 0xFF; + break; + + case 0x92: // sceMgWriteDatainLength + cdvd.mg_size = 0; + cdvd.mg_datatype = 0;//data (encrypted) + cdvd.mg_maxsize = cdvd.Param[0] | (((int)cdvd.Param[1])<<8); + SetResultSize(1);//in:2 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + + case 0x93: // sceMgWriteDataoutLength + SetResultSize(1);//in:2 + if (((cdvd.Param[0] | (((int)cdvd.Param[1])<<8)) == cdvd.mg_size) && (cdvd.mg_datatype == 0)){ + cdvd.mg_maxsize = 0; // don't allow any write + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + }else + cdvd.Result[0] = 0x80; + break; + + case 0x94: // sceMgReadKbit - read first half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit, 8); + break; + + case 0x95: // sceMgReadKbit2 - read second half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kbit+8, 8); + break; + + case 0x96: // sceMgReadKcon - read first half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon, 8); + break; + + case 0x97: // sceMgReadKcon2 - read second half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + memcpy(cdvd.Result+1, cdvd.mg_kcon+8, 8); + break; + + default: + // fake a 'correct' command + SysPrintf("SCMD Unknown %x\n", rt); + SetResultSize(1); //in:0 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + } + //SysPrintf("SCMD - %x\n", rt); + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite17(u8 rt) { // SDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite17(SDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite18(u8 rt) { // SDATAOUT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite18(SDataOut) %x\n", rt); +#endif + SysPrintf("*PCSX2* SDATAOUT\n"); +} + +void cdvdWrite3A(u8 rt) { // DEC-SET +#ifdef CDR_LOG + CDR_LOG("cdvdWrite3A(DecSet) %x\n", rt); +#endif + cdvd.decSet = rt; + SysPrintf("DecSet Write: %02X\n", cdvd.decSet); +} + +static int mg_BIToffset(u8 *buffer){ + int i, ofs = 0x20; for (i=0; i<*(u16*)&buffer[0x1A]; i++)ofs+=0x10; + if (*(u16*)&buffer[0x18] & 1)ofs+=buffer[ofs]; + if ((*(u16*)&buffer[0x18] & 0xF000)==0)ofs+=8; + return ofs + 0x20; +} diff --git a/branches/pcsx2_0.9.2/CDVD.h b/branches/pcsx2_0.9.2/CDVD.h new file mode 100644 index 0000000..c1dec54 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVD.h @@ -0,0 +1,144 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#include "PsxCommon.h" + +typedef struct { + u8 status; + u8 second; + u8 minute; + u8 hour; + u8 pad; + u8 day; + u8 month; + u8 year; +} cdvdRTC; + +typedef struct { + u8 nCommand; + u8 Ready; + u8 Error; + u8 PwOff; + u8 Status; + u8 Type; + u8 sCommand; + u8 sDataIn; + u8 sDataOut; + u8 HowTo; + + u8 Param[32]; + u8 Result[32]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + + u8 CBlockIndex; + u8 COffset; + u8 CReadWrite; + u8 CNumBlocks; + + int RTCcount; + cdvdRTC RTC; + + u32 Sector; + int nSectors; + int Readed; + int Reading; + int ReadMode; + int BlockSize; + int Speed; + int RetryCnt; + int RetryCntP; + int RErr; + int SpindlCtrl; + + u8 Key[16]; + u8 KeyXor; + u8 decSet; + + u8 mg_buffer[65536]; + int mg_size; + int mg_maxsize; + int mg_datatype;//0-data(encrypted); 1-header + u8 mg_kbit[16];//last BIT key 'seen' + u8 mg_kcon[16];//last content key 'seen' +// char Unused[4096]; +} cdvdStruct; + +extern cdvdStruct cdvd; + +void cdvdReset(); +void cdvdReadTimeRcnt(int mode); +void cdvdVsync(); +int cdvdInterrupt(); +int cdvdFreeze(gzFile f, int Mode); +int cdvdReadInterrupt(); +void cdvdNewDiskCB(); +u8 cdvdRead04(void); +u8 cdvdRead05(void); +u8 cdvdRead06(void); +u8 cdvdRead07(void); +u8 cdvdRead08(void); +u8 cdvdRead0A(void); +u8 cdvdRead0B(void); +u8 cdvdRead0C(void); +u8 cdvdRead0D(void); +u8 cdvdRead0E(void); +u8 cdvdRead0F(void); +u8 cdvdRead13(void); +u8 cdvdRead15(void); +u8 cdvdRead16(void); +u8 cdvdRead17(void); +u8 cdvdRead18(void); +u8 cdvdRead20(void); +u8 cdvdRead21(void); +u8 cdvdRead22(void); +u8 cdvdRead23(void); +u8 cdvdRead24(void); +u8 cdvdRead28(void); +u8 cdvdRead29(void); +u8 cdvdRead2A(void); +u8 cdvdRead2B(void); +u8 cdvdRead2C(void); +u8 cdvdRead30(void); +u8 cdvdRead31(void); +u8 cdvdRead32(void); +u8 cdvdRead33(void); +u8 cdvdRead34(void); +u8 cdvdRead38(void); +u8 cdvdRead39(void); +u8 cdvdRead3A(void); +void cdvdWrite04(u8 rt); +void cdvdWrite05(u8 rt); +void cdvdWrite06(u8 rt); +void cdvdWrite07(u8 rt); +void cdvdWrite08(u8 rt); +void cdvdWrite0A(u8 rt); +void cdvdWrite0F(u8 rt); +void cdvdWrite14(u8 rt); +void cdvdWrite16(u8 rt); +void cdvdWrite17(u8 rt); +void cdvdWrite18(u8 rt); +void cdvdWrite3A(u8 rt); + +#endif /* __CDVD_H__ */ diff --git a/branches/pcsx2_0.9.2/CDVDiso.c b/branches/pcsx2_0.9.2/CDVDiso.c new file mode 100644 index 0000000..a69de25 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVDiso.c @@ -0,0 +1,835 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + * Fixed CdRead by linuzappz + */ + +#include + +//#ifndef strnicmp +//#define strnicmp strncasecmp +//#endif + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +struct dir_toc_data{ + unsigned int start_LBA; + unsigned int num_sectors; + unsigned int num_entries; + unsigned int current_entry; + unsigned int current_sector; + unsigned int current_sector_offset; + unsigned int inc_dirs; + unsigned char extension_list[128+1]; +}; + +//static u8 cdVolDescriptor[2048]; +static struct dir_toc_data getDirTocData; +static struct cdVolDesc CDVolDesc; + +void _splitpath2(const char *constpath, char *dir, char *fname){ + // 255 char max path-length is an ISO9660 restriction + // we must change this for Joliet or relaxed iso restriction support + static char pathcopy[1024+1]; + + char* slash; + + strncpy(pathcopy, constpath, 1024); + + slash = strrchr (pathcopy, '/'); + + // if the path doesn't contain a '/' then look for a '\' + if (!slash) + slash = strrchr (pathcopy, (int)'\\'); + + // if a slash was found + if (slash != NULL) + { + // null terminate the path + slash[0] = 0; + // and copy the path into 'dir' + strncpy(dir, pathcopy, 1024); + dir[255]=0; + + // copy the filename into 'fname' + strncpy(fname, slash+1, 128); + fname[128]=0; + } + else + { + dir[0] = 0; + + strncpy(fname, pathcopy, 128); + fname[128]=0; + } + +} + +// Used in findfile +int tolower(int c); +int strcasecmp(const char *s1, const char *s2){ + while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +// Copy a TOC Entry from the CD native format to our tidier format +void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){ + int i; + int filenamelen; + + tocEntry->fileSize = internalTocEntry->fileSize; + tocEntry->fileLBA = internalTocEntry->fileLBA; + tocEntry->fileProperties = internalTocEntry->fileProperties; + memcpy(tocEntry->date, internalTocEntry->dateStamp, 7); + + if (CDVolDesc.filesystemType == 2){ + // This is a Joliet Filesystem, so use Unicode to ISO string copy + + filenamelen = internalTocEntry->filenameLength/2; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + for (i=0; i < filenamelen; i++) + tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1]; + + tocEntry->filename[filenamelen] = 0; + } + else{ + filenamelen = internalTocEntry->filenameLength; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + // use normal string copy + strncpy(tocEntry->filename,internalTocEntry->filename,128); + tocEntry->filename[filenamelen] = 0; + } +} + +// Check if a TOC Entry matches our extension list +int TocEntryCompare(char* filename, char* extensions){ + static char ext_list[129]; + + char* token; + + char* ext_point; + + strncpy(ext_list,extensions,128); + ext_list[128]=0; + + token = strtok( ext_list, " ," ); + while( token != NULL ) + { + // if 'token' matches extension of 'filename' + // then return a match + ext_point = strrchr(filename,'.'); + + if (strnicmp(ext_point, token, strlen(token)) == 0) + return (TRUE); + + /* Get next token: */ + token = strtok( NULL, " ," ); + } + + // If not match found then return FALSE + return (FALSE); + +} + +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + int rmode; + + switch (mode->datapattern) { + case CdSecS2048: + rmode = CDVD_MODE_2048; break; + case CdSecS2328: + rmode = CDVD_MODE_2328; break; + case CdSecS2340: + rmode = CDVD_MODE_2340; break; + default: + return 0; + } + + for (i=0; idatapattern){ + case CdSecS2048: + memcpy((void*)((uptr)buf+2048*i), buff, 2048);break;//only data + case CdSecS2328: + memcpy((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub + case CdSecS2340: + memcpy((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync + } + } + return 1; +} + +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + + for (i=lsn; i<(lsn+sectors); i++){ + if (CDVDreadTrack(i, CDVD_MODE_2048)==-1) + return 0; + buff = CDVDgetBuffer(); + if (buff==NULL) return 0; + +// switch (mode->datapattern){ +// case CdSecS2064: + ((u32*)buf)[0] = i + 0x30000; + memcpy((u8*)buf+12, buff, 2048); + (u8*)buf+= 2064; break; +// default: +// return 0; +// } + } + + return 1; +} + +/************************************************************** +* The functions below are not exported for normal file-system * +* operations, but are used by the file-system operations, and * +* may also be exported for use via RPC * +**************************************************************/ + +int CDVD_GetVolumeDescriptor(void){ + // Read until we find the last valid Volume Descriptor + int volDescSector; + + static struct cdVolDesc localVolDesc; + +#ifdef DEBUG + printf("CDVD_GetVolumeDescriptor called\n"); +#endif + + for (volDescSector = 16; volDescSector<20; volDescSector++) + { + CdRead(volDescSector,1,&localVolDesc,&cdReadMode); +// CdSync(0x00); + + // If this is still a volume Descriptor + if (strncmp(localVolDesc.volID, "CD001", 5) == 0) + { + if ((localVolDesc.filesystemType == 1) || + (localVolDesc.filesystemType == 2)) + { + memcpy(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc)); + } + } + else + break; + } + +#ifdef DEBUG + if (CDVolDesc.filesystemType == 1) + printf("CD FileSystem is ISO9660\n"); + else if (CDVolDesc.filesystemType == 2) + printf("CD FileSystem is Joliet\n"); + else printf("Could not detect CD FileSystem type\n"); +#endif +// CdStop(); + + return TRUE; +} + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry){ + static char filename[128+1]; + static char pathname[1024+1]; + static char toc[2048]; + char* dirname; + + + static struct TocEntry localTocEntry; // used for internal checking only + + int found_dir; + + int num_dir_sectors; + int current_sector; + + int dir_lba; + + struct dirTocEntry* tocEntryPointer; + +#ifdef DEBUG + printf("CDVD_findfile called\n"); +#endif + + //make sure we have good cdReadMode + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; + + _splitpath2(fname, pathname, filename); + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + + while( dirname != NULL ) + { + found_dir = FALSE; +/* + while(tocEntryPointer->length > 0) + { + // while there are still more directory entries then search through + // for the one we want + + if (tocEntryPointer->fileProperties & 0x02) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcasecmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } +*/ + while(1) + { + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) + { + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else + { + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + + if (tocEntryPointer->fileProperties & 0x02) + { + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + { + printf("CDVD_findfile: could not find dir\n"); + return -1; + } + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + +#ifdef DEBUG + printf("CDVD_findfile: found dir, now looking for file\n"); +#endif + + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + dir_lba = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + while (num_dir_sectors > 0) + { + while(tocEntryPointer->length != 0) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) || + ((filename[strlen(filename)-2] == ';') && + (localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') && + (strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0))) + { + // if the filename matches then copy the toc Entry + tocEntry->fileLBA = localTocEntry.fileLBA; + tocEntry->fileProperties = localTocEntry.fileProperties; + tocEntry->fileSize = localTocEntry.fileSize; + + strcpy(tocEntry->filename, localTocEntry.filename); + memcpy(tocEntry->date, localTocEntry.date, 7); + +#ifdef DEBUG + printf("CDVD_findfile: found file\n"); +#endif + + return TRUE; + } + + (char*)tocEntryPointer += tocEntryPointer->length; + } + + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + dir_lba++; + + if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){ + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + } + +#ifdef DEBUG + printf("CDVD_findfile: could not find file\n"); +#endif + + return FALSE; +} + +// This is the RPC-ready function which takes the request to start the tocEntry retrieval +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){ +// int dir_depth = 1; + static char toc[2048]; + char* dirname; + int found_dir; + int num_dir_sectors; + unsigned int toc_entry_num; + struct dirTocEntry* tocEntryPointer; + static struct TocEntry localTocEntry; + int current_sector; + + // store the extension list statically for the retrieve function + strncpy(getDirTocData.extension_list, extensions, 128); + getDirTocData.extension_list[128]=0; + + getDirTocData.inc_dirs = inc_dirs; + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname); +#endif + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + // use strtok to get the next dir name + + // if there isnt one, then assume we want the LBA + // for the current one, and exit the while loop + + // if there is another dir name then increment dir_depth + // and look through dir table entries until we find the right name + // if we dont find the right name + // before finding an entry at a higher level (lower num), then return nothing + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + while( dirname != NULL ){ + found_dir = FALSE; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) { + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else{ + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + if (tocEntryPointer->fileProperties & 0x02){ + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0){ + // if the name matches then we've found the directory + found_dir = TRUE; +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector); + RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA); +#endif + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + return -1; + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // We know how much data we need to read in from the DirTocHeader + // but we need to read in at least 1 sector before we can get this value + + // Now we need to COUNT the number of entries (dont do anything with info at this point) + // so set the tocEntryPointer to point to the first actual file entry + + // This is a bit of a waste of reads since we're not actually copying the data out yet, + // but we dont know how big this TOC might be, so we cant allocate a specific size + + (char*)tocEntryPointer = toc; + + // Need to STORE the start LBA and number of Sectors, for use by the retrieve func. + getDirTocData.start_LBA = localTocEntry.fileLBA; + getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11; + getDirTocData.num_entries = 0; + getDirTocData.current_entry = 0; + getDirTocData.current_sector = getDirTocData.start_LBA; + getDirTocData.current_sector_offset = 0; + + num_dir_sectors = getDirTocData.num_sectors; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + toc_entry_num=0; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){ + // decrease the number of dirs remaining + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + +// continue; + } + else{ + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + return (toc_entry_num); + } + } + + // We've found a file/dir in this directory + // now check if it matches our extension list (if there is one) + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if (localTocEntry.fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs){ + toc_entry_num++; + } + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + } + else{ + toc_entry_num++; + } + } + + (char*)tocEntryPointer += tocEntryPointer->length; + + } + + + // THIS SHOULD BE UNREACHABLE - + // since we are trying to count ALL matching entries, rather than upto a limit + + + // STORE total number of TOC entries + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + + + // we've reached the toc entry limit, so return how many we've done + return (toc_entry_num); + +} + +// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries +// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){ + static char toc[2048]; + int toc_entry_num; + + struct dirTocEntry* tocEntryPointer; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + if (getDirTocData.current_entry == 0){ + // if this is the first read then make sure we point to the first real entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc; + } + else{ + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + + if (req_entries > 128) + req_entries = 128; + + for (toc_entry_num=0; toc_entry_num < req_entries;){ + if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){ + // decrease the number of dirs remaining + getDirTocData.num_sectors--; + + if (getDirTocData.num_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + getDirTocData.current_sector_offset = 0; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + +// continue; + } + else{ + return (toc_entry_num); + } + } + + // This must be incremented even if the filename doesnt match extension list + getDirTocData.current_entry++; + + // We've found a file in this directory + // now check if it matches our extension list (if there is one) + + // Copy the entry regardless, as it makes the comparison easier + // if it doesn't match then it will just be overwritten + TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer); + + if (tocEntry[toc_entry_num].fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs) { + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + + } + else{ + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + } +/* + if (strlen(getDirTocData.extension_list) > 0) + { + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE) + { + + // increment this here, rather than in the main for loop + // since this should count the number of matching entries + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else + { + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } +*/ + } + return (toc_entry_num); +} diff --git a/branches/pcsx2_0.9.2/CDVDiso.h b/branches/pcsx2_0.9.2/CDVDiso.h new file mode 100644 index 0000000..72b0552 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVDiso.h @@ -0,0 +1,131 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISO_H__ +#define __CDVDISO_H__ + +#include "CDVDlib.h" + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs); +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries); + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTableEntry +{ + u8 dirNameLength; + u8 reserved; + u32 dirTOCLBA; + u16 dirDepth; + u8 dirName[32]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTocEntry +{ + short length; + unsigned int fileLBA; + unsigned int fileLBA_bigend; + unsigned int fileSize; + unsigned int fileSize_bigend; + unsigned char dateStamp[6]; + unsigned char reserved1; + unsigned char fileProperties; + unsigned char reserved2[6]; + unsigned char filenameLength; + unsigned char filename[128]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif // This is the internal format on the CD +// TocEntry structure contains only the important stuff needed for export + +#if defined(__WIN32__) +#pragma pack() +#endif + +#endif//__CDVDISO_H__ diff --git a/branches/pcsx2_0.9.2/CDVDisodrv.c b/branches/pcsx2_0.9.2/CDVDisodrv.c new file mode 100644 index 0000000..a415367 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVDisodrv.c @@ -0,0 +1,263 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#include + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +CdRMode cdReadMode; + +struct fdtable{ +//int fd; + int fileSize; + int LBA; + int filePos; +}; + +static struct fdtable fd_table[16]; +static int fd_used[16]; +static int files_open=0; +static int inited=FALSE; + +/************************************************************* +* The functions below are the normal file-system operations, * +* used to provide a standard filesystem interface * +*************************************************************/ + +////////////////////////////////////////////////////////////////////// +// CDVDFS_init +// called by 80000592 sceCdInit() +////////////////////////////////////////////////////////////////////// +void CDVDFS_init(){ + + if (inited) return;//might change in the future as a param; forceInit/Reset + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00\n"); + RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n"); + RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.\n", "cdfs"); +#endif + + //CdInit(0); already called by plugin loading system ;) + + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; //isofs driver only needs + //2KB sectors + + memset(fd_table, 0, sizeof(fd_table)); + memset(fd_used, 0, 16*sizeof(int)); + + inited = TRUE; + + return; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_open +// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_open(char *name, int mode){ + register int j; + static struct TocEntry tocEntry; + + // check if the file exists + if (CDVD_findfile(name, &tocEntry) != TRUE) + return -1; + + if(mode != 1) return -2; //SCE_RDONLY + + // set up a new file descriptor + for(j=0; j < 16; j++) if(fd_used[j] == 0) break; + if(j >= 16) return -3; + + fd_used[j] = 1; + files_open++; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:open] internal fd=%d\n", j); +#endif + + fd_table[j].fileSize = tocEntry.fileSize; + fd_table[j].LBA = tocEntry.fileLBA; + fd_table[j].filePos = 0; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d\n",tocEntry.fileSize); +#endif + + return j; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_lseek +// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_lseek(int fd, int offset, int whence){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + switch(whence){ + case SEEK_SET: + fd_table[fd].filePos = offset; + break; + + case SEEK_CUR: + fd_table[fd].filePos += offset; + break; + + case SEEK_END: + fd_table[fd].filePos = fd_table[fd].fileSize + offset; + break; + + default: + return -1; + } + + if (fd_table[fd].filePos < 0) + fd_table[fd].filePos = 0; + + if (fd_table[fd].filePos > fd_table[fd].fileSize) + fd_table[fd].filePos = fd_table[fd].fileSize; + + return fd_table[fd].filePos; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_read +// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_read( int fd, char *buffer, int size ){ +// int start_sector; + int off_sector; +// int num_sectors; + + //static char local_buffer[2024*2048]; //4MB + static char lb[2048]; //2KB + //Start, Aligned, End + int ssector, asector, esector; + int ssize=0, asize, esize; + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + // A few sanity checks + if (fd_table[fd].filePos > fd_table[fd].fileSize){ + // We cant start reading from past the beginning of the file + return 0; // File exists but we couldnt read anything from it + } + + if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize) + size = fd_table[fd].fileSize - fd_table[fd].filePos; + + // Now work out where we want to start reading from + asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + if (off_sector){ + ssize = min(2048 - off_sector, size); + size -= ssize; + asector++; + } + asize = size & 0xFFFFF800; + esize = size & 0x000007FF; + esector=asector + (asize >> 11); + size += ssize; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n", ssector, esector-(esize==0)); +#endif + + if (ssize){ if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer, lb + off_sector, ssize); + } + if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + if (esize){ if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer+ssize+asize, lb, esize); + } +/*********************** + // Now work out where we want to start reading from + start_sector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + num_sectors = ((off_sector + size) >> 11) + 1; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n",start_sector,start_sector+num_sectors); +#endif + + // Read the data (we only ever get 16KB max request at once) + if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + //RPC_LOG("sector = %d, start sector = %d\n",sector,start_sector); + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + //CdSync(0); hm, a wait function maybe... + + memcpy(buffer,local_buffer+off_sector,size); +**************************/ + fd_table[fd].filePos += size; + + return (size); +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_write +// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:" +// hehe, this ain't a CD writing option :D +////////////////////////////////////////////////////////////////////// +int CDVDFS_write( int fd, char * buffer, int size ){ + if(size == 0) return 0; + else return -1; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_close +// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_close( int fd){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] internal fd %d\n", fd); +#endif + + fd_used[fd] = 0; + files_open--; + + return 0; +} + diff --git a/branches/pcsx2_0.9.2/CDVDisodrv.h b/branches/pcsx2_0.9.2/CDVDisodrv.h new file mode 100644 index 0000000..dcf8545 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVDisodrv.h @@ -0,0 +1,22 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISODRV_H__ +#define __CDVDISODRV_H__ + +//#include "Common.h" +#include "CDVDlib.h" + +extern CdRMode cdReadMode; + +/* Filing-system exported functions */ +void CDVDFS_init(); +int CDVDFS_open(char *name, int mode); +int CDVDFS_lseek(int fd, int offset, int whence); +int CDVDFS_read( int fd, char * buffer, int size ); +int CDVDFS_write( int fd, char * buffer, int size ); +int CDVDFS_close( int fd); + +#endif//__CDVDISODRV_H__ diff --git a/branches/pcsx2_0.9.2/CDVDlib.h b/branches/pcsx2_0.9.2/CDVDlib.h new file mode 100644 index 0000000..f451981 --- /dev/null +++ b/branches/pcsx2_0.9.2/CDVDlib.h @@ -0,0 +1,185 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Linux kernel headers + * Modified by Florin for PCSX2 emu + */ + +#ifndef _CDVDLIB_H +#define _CDVDLIB_H + +#include "Common.h" + +// Macros for READ Data pattan +#define CdSecS2048 0 // sector size 2048 +#define CdSecS2328 1 // sector size 2328 +#define CdSecS2340 2 // sector size 2340 + +//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ + +/* + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + * 2340, or 2352 bytes long. + * Sector types of the standard CD-ROM data formats: + * + * format sector type user data size (bytes) + * ----------------------------------------------------------------------------- + * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW) + * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE) + * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0) + * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE) + * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + * + * + * The layout of the standard CD-ROM data formats: + * ----------------------------------------------------------------------------- + * - audio (red): | audio_sample_bytes | + * | 2352 | + * + * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + * | 12 - 4 - 2048 - 4 - 8 - 276 | + * + * - data (yellow, mode2): | sync - head - data | + * | 12 - 4 - 2336 | + * + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + * | 12 - 4 - 8 - 2048 - 4 - 276 | + * + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + * | 12 - 4 - 8 - 2324 - 4 | + * + */ + +// Macros for Spindle control +#define CdSpinMax 0 +#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. +#define CdSpinStm 0 // Recommended stream rotation speed. + +// Macros for TrayReq +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 + +/* + * Macros for sceCdGetDiskType() //comments translated from japanese;) + */ +#define SCECdIllgalMedia 0xff + /* ILIMEDIA (Illegal Media) + A non-PS / non-PS2 Disc. */ +#define SCECdDVDV 0xfe + /* DVDV (DVD Video) + A non-PS / non-PS2 Disc, but a DVD Video Disc */ +#define SCECdCDDA 0xfd + /* CDDA (CD DA) + A non-PS / non-PS2 Disc that include a DA track */ +#define SCECdPS2DVD 0x14 + /* PS2DVD PS2 consumer DVD. */ +#define SCECdPS2CDDA 0x13 + /* PS2CDDA PS2 consumer CD that includes a DA track */ +#define SCECdPS2CD 0x12 + /* PS2CD PS2 consumer CD that does not include a DA track */ +#define SCECdPSCDDA 0x11 + /* PSCDDA PS CD that includes a DA track */ +#define SCECdPSCD 0x10 + /* PSCD PS CD that does not include a DA track */ +#define SCECdDETCT 0x01 + /* DETCT (Detecting) Disc distinction action */ +#define SCECdNODISC 0x00 + /* NODISC (No disc) No disc entered */ + +/* + * Media mode + */ +#define SCECdCD 1 +#define SCECdDVD 2 + +typedef struct { + u8 stat; // 0: normal. Any other: error + u8 second; // second (BCD value) + u8 minute; // minute (BCD value) + u8 hour; // hour (BCD value) + u8 week; // week (BCD value) + u8 day; // day (BCD value) + u8 month; // month (BCD value) + u8 year; // year (BCD value) +} CdCLOCK; + +typedef struct { + u32 lsn; // Logical sector number of file + u32 size; // File size (in bytes) + char name[16]; // Filename + u8 date[8]; // 1th: Seconds + // 2th: Minutes + // 3th: Hours + // 4th: Date + // 5th: Month + // 6th 7th: Year (4 digits) +} CdlFILE; + +typedef struct { + u8 minute; // Minutes + u8 second; // Seconds + u8 sector; // Sector + u8 track; // Track number +} CdlLOCCD; + +typedef struct { + u8 trycount; // Read try count (No. of error retries + 1) (0 - 255) + u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed. + // SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. + u8 datapattern; // SCECdSecS2048: Data size 2048 bytes + // SCECdSecS2328: 2328 bytes + // SCECdSecS2340: 2340 bytes + u8 pad; // Padding data produced by alignment. +} CdRMode; + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct TocEntry +{ + u32 fileLBA; + u32 fileSize; + u8 fileProperties; + u8 padding1[3]; + u8 filename[128+1]; + u8 date[7]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +#if defined(__WIN32__) +#pragma pack() +#endif + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +/* +int CdBreak(void); +int CdCallback( void (*func)() ); +int CdDiskReady(int mode); +int CdGetDiskType(void); +int CdGetError(void); +u32 CdGetReadPos(void); +int CdGetToc(u8 *toc); +int CdInit(int init_mode); +CdlLOCCD *CdIntToPos(int i, CdlLOCCD *p); +int CdPause(void); +int CdPosToInt(CdlLOCCD *p);*/ +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +/*int CdReadClock(CdCLOCK *rtc); +int CdSearchFile (CdlFILE *fp, const char *name); +int CdSeek(u32 lsn); +int CdStandby(void); +int CdStatus(void); +int CdStop(void); +int CdSync(int mode); +int CdTrayReq(int mode, u32 *traycnt); +*/ +#endif // _CDVDLIB_H diff --git a/branches/pcsx2_0.9.2/COP0.c b/branches/pcsx2_0.9.2/COP0.c new file mode 100644 index 0000000..ef3351e --- /dev/null +++ b/branches/pcsx2_0.9.2/COP0.c @@ -0,0 +1,363 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +extern BOOL bExecBIOS; + +void COP0() { + Int_COP0PrintTable[_Rs_](); +} + +void COP0_BC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03](); +} + +void COP0_Func() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0C0PrintTable[_Funct_](); +} + +void COP0_Unknown() { +#ifdef CPU_LOG + CPU_LOG("COP0 Unknown opcode called\n"); +#endif +} + +void UpdateCP0Status() { + u32 value = cpuRegs.CP0.n.Status.val; + + if (value & 0x06 || + (value & 0x18) == 0) { // Kernel Mode (KSU = 0 | EXL = 1 | ERL = 1)*/ + memSetKernelMode(); // Kernel memory always + } else { // User Mode + memSetUserMode(); + } + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)cpuTestHwInts(); +} + +void WriteCP0Status(u32 value) { + cpuRegs.CP0.n.Status.val = value; + UpdateCP0Status(); +} + +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; + +void MFC0() { + if (!_Rt_) return; +#ifdef COP0_LOG + if (_Rd_ != 9) { COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); } +#endif + + //if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MFC0 _Rd_ %x = %x\n", _Rd_, cpuRegs.CP0.r[_Rd_]); + switch (_Rd_) { + + case 12: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)(cpuRegs.CP0.r[_Rd_] & 0xf0c79c1f); break; + case 25: + switch(_Imm_ & 0x3F){ + case 0: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pccr; break; + case 1: + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) { + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + } + + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pcr0; + break; + case 3: + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) { + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + s_iLastPERFCycle[1] = cpuRegs.cycle; + } + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pcr1; + break; + } + /*SysPrintf("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/ + break; + case 9: + // update + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + default: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.CP0.r[_Rd_]; + } +} + +void MTC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + //if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MTC0 _Rd_ %x = %x\n", _Rd_, cpuRegs.CP0.r[_Rd_]); + switch (_Rd_) { + case 25: + /*if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/ + switch(_Imm_ & 0x3F){ + case 0: + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + cpuRegs.PERF.n.pccr = cpuRegs.GPR.r[_Rt_].UL[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + s_iLastPERFCycle[1] = cpuRegs.cycle; + break; + case 1: cpuRegs.PERF.n.pcr0 = cpuRegs.GPR.r[_Rt_].UL[0]; s_iLastPERFCycle[0] = cpuRegs.cycle; break; + case 3: cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0]; s_iLastPERFCycle[1] = cpuRegs.cycle; break; + } + break; + case 12: WriteCP0Status(cpuRegs.GPR.r[_Rt_].UL[0]); break; + case 9: s_iLastCOP0Cycle = cpuRegs.cycle; cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + default: cpuRegs.CP0.r[_Rd_] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + } +} + +int CPCOND0() { + if(((psHu16(DMAC_STAT) & psHu16(DMAC_PCR)) & 0x3ff) == (psHu16(DMAC_PCR) & 0x3ff)) return 1; + else return 0; +} + +//#define CPCOND0 1 + +#define BC0(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC0F() { + BC0(== 0); +} + +void BC0T() { + BC0(== 1); +} + +#define BC0L(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC0FL() { + BC0L(== 0); +} + +void BC0TL() { + BC0L(== 1); +} + +void TLBR() { +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + int i = cpuRegs.CP0.n.Index&0x1f; + +// if( !bExecBIOS ) +// __Log("TLBR %d\n", cpuRegs.CP0.n.Index&0x1f); + + SysPrintf("COP0_TLBR\n"); + cpuRegs.CP0.n.PageMask = tlb[i].PageMask; + cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi&~(tlb[i].PageMask|0x1f00); + cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0&~1)|((tlb[i].EntryHi>>12)&1); + cpuRegs.CP0.n.EntryLo1 =(tlb[i].EntryLo1&~1)|((tlb[i].EntryHi>>12)&1); +} + +void ClearTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void WriteTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + tlb[i].PageMask = cpuRegs.CP0.n.PageMask; + tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi; + tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0; + tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1; + + tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff; + tlb[i].nMask = (~tlb[i].Mask) & 0xfff; + tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13; + tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff; + tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1; + tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN0|= (0x80000000); + tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN1|= (0x80000000); + if (tlb[i].VPN2 == 0x70000000) return; + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void TLBWI() { + int j = cpuRegs.CP0.n.Index & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWI %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWI %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBWR() { + int j = cpuRegs.CP0.n.Random & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWR %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBP() { + int i; + + + union { + struct { + u32 VPN2:19; + u32 VPN2X:2; + u32 G:3; + u32 ASID:8; + } s; + u32 u; + } EntryHi32; + + if( !bExecBIOS ) + __Log("TLBP %x\n", cpuRegs.CP0.n.EntryHi); + + EntryHi32.u=cpuRegs.CP0.n.EntryHi; + + cpuRegs.CP0.n.Index=0xFFFFFFFF; + for(i=0;i<48;i++){ + if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2)) + &&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { + cpuRegs.CP0.n.Index=i; + break; + } + } + if(cpuRegs.CP0.n.Index == 0xFFFFFFFF) cpuRegs.CP0.n.Index = 0x80000000; +} + +void ERET() { + if (cpuRegs.CP0.n.Status.b.ERL) { + cpuRegs.pc = cpuRegs.CP0.n.ErrorEPC; + cpuRegs.CP0.n.Status.b.ERL = 0; + } else { + cpuRegs.pc = cpuRegs.CP0.n.EPC; + cpuRegs.CP0.n.Status.b.EXL = 0; + } + UpdateCP0Status(); + intSetBranch(); +} + +void DI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 0; + UpdateCP0Status(); + } +} + +void EI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 1; + UpdateCP0Status(); + } +} + diff --git a/branches/pcsx2_0.9.2/COP0.h b/branches/pcsx2_0.9.2/COP0.h new file mode 100644 index 0000000..30ad063 --- /dev/null +++ b/branches/pcsx2_0.9.2/COP0.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COP0_H__ +#define __COP0_H__ + +void WriteCP0Status(u32 value); +void UpdateCP0Status(); +void WriteTLB(int i); +void ClearTLB(int i); + +#endif /* __COP0_H__ */ diff --git a/branches/pcsx2_0.9.2/Cache.c b/branches/pcsx2_0.9.2/Cache.c new file mode 100644 index 0000000..305a666 --- /dev/null +++ b/branches/pcsx2_0.9.2/Cache.c @@ -0,0 +1,355 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "Cache.h" + +/*_cacheS pCache[64]; +int getFreeCache(u32 mem, int mode, int * way) { + u8 * out; + u32 paddr; + u32 taddr[2]; + u8 * t; + int number; + int i = (mem >> 6) & 0x3F; + + paddr = memLUTR[mem >> 12]; + taddr[0] = memLUTW[pCache[i].tag[0]>>12]; + taddr[1] = memLUTW[pCache[i].tag[1]>>12]; + + if (taddr[0] == paddr && (pCache[i].tag[0] & 0x20)) + { + *way = 0; + return i; + }else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20)) + { + *way = 1; + return i; + } + + number = ((pCache[i].tag[0]>>4) & 1) ^ ((pCache[i].tag[1]>>4) & 1); + + if(pCache[i].tag[number] & 0x60) // Valid Dirty + { + t = (char *)(taddr[number]); + out = (u8*)(t + (mem & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[i].data[number][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[i].data[number][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[i].data[number][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[i].data[number][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[i].data[number][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[i].data[number][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[i].data[number][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[i].data[number][3].b8._8)[1]; + } + + + + if(mode == 1) + { + pCache[i].tag[number] |= 0x40; // Set Dirty Bit if mode == write + } + + pCache[i].tag[number] &= ~(0xFFFFF000); + pCache[i].tag[number] |= ((mem>>12) & 0xFFFFF) << 12; + + + t = (u8 *)paddr; + out= (u8*)(t + (mem & 0xFC0)); + ((u64*)pCache[i].data[number][0].b8._8)[0] = ((u64*)out)[0]; + ((u64*)pCache[i].data[number][0].b8._8)[1] = ((u64*)out)[1]; + ((u64*)pCache[i].data[number][1].b8._8)[0] = ((u64*)out)[2]; + ((u64*)pCache[i].data[number][1].b8._8)[1] = ((u64*)out)[3]; + ((u64*)pCache[i].data[number][2].b8._8)[0] = ((u64*)out)[4]; + ((u64*)pCache[i].data[number][2].b8._8)[1] = ((u64*)out)[5]; + ((u64*)pCache[i].data[number][3].b8._8)[0] = ((u64*)out)[6]; + ((u64*)pCache[i].data[number][3].b8._8)[1] = ((u64*)out)[7]; + + if(pCache[i].tag[number] & 0x10) pCache[i].tag[number] &= ~(0x10); + else pCache[i].tag[number] |= 0x10; + + pCache[i].tag[number] |= 0x20; + *way = number; + return i; +} + +void writeCache8(u32 mem, u8 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)] = value; +} + +void writeCache16(u32 mem, u16 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u16*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache32(u32 mem, u32 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + *(u32*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache64(u32 mem, u64 value) { + int i, number; + + i = getFreeCache(mem,1,&number); + + *(u64*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache128(u32 mem, u64 *value) { + int i, number; + + i = getFreeCache(mem,1,&number); + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[0] = value[0]; + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[1] = value[1]; +} + +u8 *readCache(u32 mem) { + int i, number; + + i = getFreeCache(mem,0,&number); + + return pCache[i].data[number][(mem>>4) & 0x3].b8._8; +} + +void CACHE() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + switch (_Rt_) { + case 0x1a: + { + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTR[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + case 0x18: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef GTE_LOG + GTE_LOG("CACHE DHWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x1c: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } +#ifdef GTE_LOG + GTE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x40); + break; + } + case 0x16: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; +#ifdef GTE_LOG + GTE_LOG("CACHE DXIN addr %x, index %d, way %d, flag %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + break; + } + case 0x11: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + cpuRegs.CP0.r[28] = *(u32 *)(out+(addr&0xf)); +#ifdef GTE_LOG + GTE_LOG("CACHE DXLDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x10: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + + cpuRegs.CP0.r[28] = 0; + cpuRegs.CP0.r[28] = pCache[index].tag[way]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXLTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x13: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + *(u32*)(&pCache[index].data[way][(addr>>4) & 0x3].b8._8[(addr&0xf)]) = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x12: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + pCache[index].tag[way] = cpuRegs.CP0.r[28]; +#ifdef GTE_LOG + GTE_LOG("CACHE DXSTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28] & 0x6F); +#endif + break; + } + case 0x14: + { + + u8 * out; + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + +#ifdef GTE_LOG + GTE_LOG("CACHE DXWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Dirty + { + u32 paddr = memLUTW[pCache[index].tag[way] >> 12]; + char * t = (char *)(paddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + break; + } + } +}*/ + +void CACHE() { +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/Cache.h b/branches/pcsx2_0.9.2/Cache.h new file mode 100644 index 0000000..07ed623 --- /dev/null +++ b/branches/pcsx2_0.9.2/Cache.h @@ -0,0 +1,34 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "Common.h" + +void freeCache(int i); +int getFreeCache(); + +void writeCache8(u32 mem, u8 value); +void writeCache16(u32 mem, u16 value); +void writeCache32(u32 mem, u32 value); +void writeCache64(u32 mem, u64 value); +void writeCache128(u32 mem, u64 *value); +u8 *readCache(u32 mem); + +#endif /* __CACHE_H__ */ diff --git a/branches/pcsx2_0.9.2/CdRom.c b/branches/pcsx2_0.9.2/CdRom.c new file mode 100644 index 0000000..2f3f1be --- /dev/null +++ b/branches/pcsx2_0.9.2/CdRom.c @@ -0,0 +1,1078 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +//THIS ALL IS FOR THE CDROM REGISTERS HANDLING +#include "PsxCommon.h" + +#define CdlSync 0 +#define CdlNop 1 +#define CdlSetloc 2 +#define CdlPlay 3 +#define CdlForward 4 +#define CdlBackward 5 +#define CdlReadN 6 +#define CdlStandby 7 +#define CdlStop 8 +#define CdlPause 9 +#define CdlInit 10 +#define CdlMute 11 +#define CdlDemute 12 +#define CdlSetfilter 13 +#define CdlSetmode 14 +#define CdlGetmode 15 +#define CdlGetlocL 16 +#define CdlGetlocP 17 +#define Cdl18 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlTest 25 +#define CdlID 26 +#define CdlReadS 27 +#define CdlReset 28 +#define CdlReadToc 30 + +#define AUTOPAUSE 249 +#define READ_ACK 250 +#define READ 251 +#define REPPLAY_ACK 252 +#define REPPLAY 253 +#define ASYNC 254 +/* don't set 255, it's reserved */ + +char *CmdName[0x100]= { + "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", + "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", + "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, + NULL, "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +u8 Test04[] = { 0 }; +u8 Test05[] = { 0 }; +u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; +u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; +u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) +//#define cdReadTime ((PSXCLK / 75) / BIAS) +unsigned long cdReadTime;// = ((PSXCLK / 75) / BIAS); + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +/*static struct CdrStat stat; +static struct SubQ *subq;*/ + +#define CDR_INT(eCycle) PSX_INT(17, eCycle) +#define CDREAD_INT(eCycle) PSX_INT(18, eCycle) + +#define StartReading(type) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, 0x800); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt&=~0x40000; \ + } \ +} + +#define StopCdda() { \ + if (cdr.Play) { \ +/* if (!Config.Cdda) CDR_stop();*/ \ + cdr.StatP&=~0x80; \ + cdr.Play = 0; \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + lsn += 150; + Time[2] = lsn / 4500; // minuten + lsn = lsn - Time[2] * 4500; // minuten rest + Time[1] = lsn / 75; // sekunden + Time[0] = lsn - Time[1] * 75; // sekunden rest +} + +void ReadTrack() { + cdr.Prev[0] = itob(cdr.SetSector[0]); + cdr.Prev[1] = itob(cdr.SetSector[1]); + cdr.Prev[2] = itob(cdr.SetSector[2]); + +#ifdef CDR_LOG + CDR_LOG("KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2352); +} + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +void AddIrqQueue(u8 irq, unsigned long ecycle) { + cdr.Irq = irq; + if (cdr.Stat) { + cdr.eCycle = ecycle; + } else { + CDR_INT(ecycle); + } +} + +int cdrInterrupt() { + cdvdTD trackInfo; + int i; + u8 Irq = cdr.Irq; + + if (cdr.Stat) { + CDR_INT(0x800); + return 0; + } + + cdr.Irq = 0xff; + cdr.Ctrl&=~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +/* i = stat.Status; + if (CDR_getStatus(&stat) != -1) { + if (stat.Type == 0xff) cdr.Stat = DiskError; + if (stat.Status & 0x10) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x11; + cdr.Result[0]&=~0x02; + } + else if (i & 0x10) { + cdr.StatP |= 0x2; + cdr.Result[0]|= 0x2; + CheckCdrom(); + } + }*/ + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + cdr.StatP|= 0x82; +// if ((cdr.Mode & 0x5) == 0x5) AddIrqQueue(REPPLAY, cdReadTime); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP&=~0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlPause + 0x20, 0x800); + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +// if (!cdr.Init) { + AddIrqQueue(CdlInit + 0x20, 0x800); +// } + break; + + case CdlInit + 0x20: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Init = 1; + break; + + case CdlMute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = cdr.Mode; + cdr.Result[2] = cdr.File; + cdr.Result[3] = cdr.Channel; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocL: + SetResultSize(8); +// for (i=0; i<8; i++) cdr.Result[i] = itob(cdr.Transfer[i]); + for (i=0; i<8; i++) cdr.Result[i] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + SetResultSize(8); +/* subq = (struct SubQ*) CDR_getBufferSub(); + if (subq != NULL) { + cdr.Result[0] = subq->TrackNumber; + cdr.Result[1] = subq->IndexNumber; + memcpy(cdr.Result+2, subq->TrackRelativeAddress, 3); + memcpy(cdr.Result+5, subq->AbsoluteAddress, 3); + } else { +*/ cdr.Result[0] = 1; + cdr.Result[1] = 1; + cdr.Result[2] = cdr.Prev[0]; + cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); + cdr.Result[4] = cdr.Prev[2]; + memcpy(cdr.Result+5, cdr.Prev, 3); +// } + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + if (CDVDgetTN(&cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + cdr.Stat = Acknowledge; + cdr.Result[1] = itob(cdr.ResultTN.strack); + cdr.Result[2] = itob(cdr.ResultTN.etrack); + } + break; + + case CdlGetTD: + cdr.CmdProcess = 0; + cdr.Track = btoi(cdr.Param[0]); + SetResultSize(4); + cdr.StatP|= 0x2; + if (CDVDgetTD(cdr.Track, &trackInfo) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + LSNtoMSF(cdr.ResultTD, trackInfo.lsn); + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = itob(cdr.ResultTD[0]); + cdr.Result[2] = itob(cdr.ResultTD[1]); + cdr.Result[3] = itob(cdr.ResultTD[2]); + } + break; + + case CdlSeekL: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekL + 0x20, 0x800); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, 0x800); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlTest: + cdr.Stat = Acknowledge; + switch (cdr.Param[0]) { + case 0x20: // System Controller ROM Version + SetResultSize(4); + memcpy(cdr.Result, Test20, 4); + break; + case 0x22: + SetResultSize(8); + memcpy(cdr.Result, Test22, 4); + break; + case 0x23: case 0x24: + SetResultSize(8); + memcpy(cdr.Result, Test23, 4); + break; + } + break; + + case CdlID: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlID + 0x20, 0x800); + break; + + case CdlID + 0x20: + SetResultSize(8); +// if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player + cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD +/* } + else { + if (stat.Type == 2) { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + } + else { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x00; + } + }*/ + if (!LoadCdBios) cdr.Result[1] |= 0x80; + + cdr.Result[2] = 0x00; + cdr.Result[3] = 0x00; + strncpy((char *)&cdr.Result[4], "PCSX", 4); + cdr.Stat = Complete; + break; + + case CdlReset: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case AUTOPAUSE: + cdr.OCUP = 0; +/* SetResultSize(1); + StopCdda(); + StopReading(); + cdr.OCUP = 0; + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = DataEnd; +*/ AddIrqQueue(CdlPause, 0x400); + break; + + case READ_ACK: + if (!cdr.Reading) return 1; + + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + ReadTrack(); + + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + + break; + + case REPPLAY_ACK: + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + SetResultSize(1); + AddIrqQueue(REPPLAY, cdReadTime); + break; + + case REPPLAY: + if ((cdr.Mode & 5) != 5) break; +/* if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } else memcpy(cdr.Result, &stat.Track, 8); + cdr.Stat = 1; + SetResultSize(8); + AddIrqQueue(REPPLAY_ACK, cdReadTime); +*/ break; + + case 0xff: + return 1; + + default: + cdr.Stat = Complete; + break; + } + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4; + +#ifdef CDR_LOG + CDR_LOG("Cdr Interrupt %x\n", Irq); +#endif + return 1; +} + +int cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) return 1; + + if (cdr.Stat) { + CDREAD_INT(0x800); + return 0; + } + +#ifdef CDR_LOG + CDR_LOG("KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP|= 0x22; + cdr.Result[0] = cdr.StatP; + + SysMessage("Reading From CDR"); + buf = CDVDgetBuffer(); + if (buf == NULL) cdr.RErr = -1; + + if (cdr.RErr == -1) { +#ifdef CDR_LOG + fprintf(emuLog, " err\n"); +#endif + memset(cdr.Transfer, 0, 2340); + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return 0; + } + + memcpy(cdr.Transfer, buf+12, 2340); + cdr.Stat = DataReady; + +#ifdef CDR_LOG + fprintf(emuLog, " %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); +#endif + +/* if ((cdr.Muted == 1) && (cdr.Mode & 0x40) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + if ((cdr.Transfer[4+2] & 0x4) && + ((cdr.Mode&0x8) ? (cdr.Transfer[4+1] == cdr.Channel) : 1) && + (cdr.Transfer[4+0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + } + else cdr.FirstSector = -1; + } + }*/ + + cdr.SetSector[2]++; + if (cdr.SetSector[2] == 75) { + cdr.SetSector[2] = 0; + cdr.SetSector[1]++; + if (cdr.SetSector[1] == 60) { + cdr.SetSector[1] = 0; + cdr.SetSector[0]++; + } + } + + cdr.Readed = 0; + + if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF +#ifdef CDR_LOG + CDR_LOG("AutoPausing Read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x800); + AddIrqQueue(CdlPause, 0x800); + } + else { + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + } + + psxHu32(0x1070)|=0x4; + return 0; +} + +/* +cdrRead0: + bit 0 - 0 REG1 command send / 1 REG1 data read + bit 1 - 0 data transfer finish / 1 data transfer ready/in progress + bit 2 - unknown + bit 3 - unknown + bit 4 - unknown + bit 5 - 1 result ready + bit 6 - 1 dma ready + bit 7 - 1 command being processed +*/ + +u8 cdrRead0(void) { + if (cdr.ResultReady) cdr.Ctrl|= 0x20; + else cdr.Ctrl&=~0x20; + + if (cdr.OCUP) cdr.Ctrl|= 0x40; + else cdr.Ctrl&=~0x40; + + // what means the 0x10 and the 0x08 bits? i only saw it used by the bios + cdr.Ctrl|=0x18; + +#ifdef CDR_LOG + CDR_LOG("CD0 Read: %x\n", cdr.Ctrl); +#endif + return psxHu8(0x1800) = cdr.Ctrl; +} + +/* +cdrWrite0: + 0 - to send a command / 1 - to get the result +*/ + +void cdrWrite0(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD0 write: %x\n", rt); +#endif + cdr.Ctrl = rt | (cdr.Ctrl & ~0x3); + + if (rt == 0) { + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + } +} + +u8 cdrRead1(void) { + if (cdr.ResultReady && cdr.Ctrl & 0x1) { + psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; + if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0; + } else psxHu8(0x1801) = 0; +#ifdef CDR_LOG + CDR_LOG("CD1 Read: %x\n", psxHu8(0x1801)); +#endif + return psxHu8(0x1801); +} + +void cdrWrite1(u8 rt) { + int i; + +#ifdef CDR_LOG + CDR_LOG("CD1 write: %x (%s)\n", rt, CmdName[rt]); +#endif +// psxHu8(0x1801) = rt; + cdr.Cmd = rt; + cdr.OCUP = 0; + +#ifdef CDRCMD_DEBUG + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); + if (cdr.ParamC) { + SysPrintf(" Param[%d] = {", cdr.ParamC); + for (i=0;i cdr.ResultTN[1]) cdr.CurTrack = cdr.ResultTN[1]; + if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) { + int tmp = cdr.ResultTD[2]; + cdr.ResultTD[2] = cdr.ResultTD[0]; + cdr.ResultTD[0] = tmp; + if (!Config.Cdda) CDR_play(cdr.ResultTD); + } + } + } + else if (!Config.Cdda) CDR_play(cdr.SetSector); +*/ cdr.Play = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlForward: + if (cdr.CurTrack < 0xaa) cdr.CurTrack++; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlBackward: + if (cdr.CurTrack > 1) cdr.CurTrack--; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadN: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(1); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x40000); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = 0; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlDemute: + cdr.Muted = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetfilter: + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetmode: +#ifdef CDR_LOG + CDR_LOG("Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetmode: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTN: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTD: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekP: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlTest: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlID: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadS: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(2); + break; + + case CdlReadToc: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4; +} + +u8 cdrRead2(void) { + u8 ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = *cdr.pTransfer++; + } + +#ifdef CDR_LOG + CDR_LOG("CD2 Read: %x\n", ret); +#endif + return ret; +} + +void cdrWrite2(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD2 write: %x\n", rt); +#endif + if (cdr.Ctrl & 0x1) { + switch (rt) { + case 0x07: + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + cdr.Ctrl = 0; + break; + + default: + cdr.Reg2 = rt; + break; + } + } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { + cdr.Param[cdr.ParamP++] = rt; + cdr.ParamC++; + } +} + +u8 cdrRead3(void) { + if (cdr.Stat) { + if (cdr.Ctrl & 0x1) psxHu8(0x1803) = cdr.Stat | 0xE0; + else psxHu8(0x1803) = 0xff; + } else psxHu8(0x1803) = 0; +#ifdef CDR_LOG + CDR_LOG("CD3 Read: %x\n", psxHu8(0x1803)); +#endif + return psxHu8(0x1803); +} + +void cdrWrite3(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD3 write: %x\n", rt); +#endif + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { cdr.Irq = 0; return; } + if (cdr.Irq) { + CDR_INT(cdr.eCycle); + }/* else if (cdr.Reading) { + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + }*/ + return; + } + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.pTransfer = cdr.Transfer; + + switch (cdr.Mode&0x30) { + case 0x10: + case 0x00: cdr.pTransfer+=12; break; + default: break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** NOT READY\n"); +#endif + return; + } + + cdsize = (bcr & 0xffff) * 4; + + memcpy((u8*)PSXM(madr), cdr.pTransfer, cdsize); + psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=cdsize; + + break; + case 0x41000200: + //SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr); + // size = 16 * 32 * 4 (one sector) +/* PSXMu8(madr+0) = 0x10; + PSXMu8(madr+1) = 0x00; + PSXMu8(madr+2) = 0x03; + PSXMu8(madr+3) = 0x00;*/ + return; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown cddma %lx\n", chcr); +#endif + break; + } + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack=1; + cdr.File=1; cdr.Channel=1; + cdReadTime = (PSXCLK / 1757) * BIAS; + //DVD is 4x (PSXCLK / 75) CD is 24x on the PS2, so that would mean CD = (PSXCLK / 450) + // 75/4 = 18.75 x 24 = 450 remember its faster than the PS1 ;) Refraction + + // with the timing set to 60 Gran Turismo works + // anybody knows why it doesn't with 75? + // 75 is the correct cdrom timing +// if (Config.CdTiming) +// cdReadTime = (PSXCLK / 60) / BIAS; + // this seems to be the most compatible + // let's leave like this until we know why + // 75 is buggy with some games +} + +int cdrFreeze(gzFile f, int Mode) { + int tmp; + + gzfreeze(&cdr, sizeof(cdr)); + + if (Mode == 1) tmp = cdr.pTransfer - cdr.Transfer; + gzfreezel(&tmp); + if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp; + + return 0; +} + diff --git a/branches/pcsx2_0.9.2/CdRom.h b/branches/pcsx2_0.9.2/CdRom.h new file mode 100644 index 0000000..569909e --- /dev/null +++ b/branches/pcsx2_0.9.2/CdRom.h @@ -0,0 +1,92 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#include "PsxCommon.h" +#include "Decode_XA.h" +#include "PS2Edefs.h" + +typedef struct { + u8 OCUP; + u8 Reg1Mode; + u8 Reg2; + u8 CmdProcess; + u8 Ctrl; + u8 Stat; + + u8 StatP; + + u8 Transfer[2352]; + u8 *pTransfer; + + u8 Prev[4]; + u8 Param[8]; + u8 Result[8]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + u8 ResultReady; + u8 Cmd; + u8 Readed; + unsigned long Reading; + + cdvdTN ResultTN; + u8 ResultTD[4]; + u8 SetSector[4]; + u8 SetSectorSeek[4]; + u8 Track; + int Play; + int CurTrack; + int Mode, File, Channel, Muted; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + u8 Irq; + unsigned long eCycle; + + char Unused[4087]; +} cdrStruct; + +cdrStruct cdr; + +s32 MSFtoLSN(u8 *Time); +void LSNtoMSF(u8 *Time, s32 lsn); + +void cdrReset(); +int cdrInterrupt(); +int cdrReadInterrupt(); +u8 cdrRead0(void); +u8 cdrRead1(void); +u8 cdrRead2(void); +u8 cdrRead3(void); +void cdrWrite0(u8 rt); +void cdrWrite1(u8 rt); +void cdrWrite2(u8 rt); +void cdrWrite3(u8 rt); +int cdrFreeze(gzFile f, int Mode); + +#endif /* __CDROM_H__ */ diff --git a/branches/pcsx2_0.9.2/Common.h b/branches/pcsx2_0.9.2/Common.h new file mode 100644 index 0000000..1d2dacc --- /dev/null +++ b/branches/pcsx2_0.9.2/Common.h @@ -0,0 +1,277 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +#include +#include + +#if defined(__WIN32__) + +#include + +typedef struct { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; +} AppData; + +extern AppData gApp; +#define pthread_mutex__unlock pthread_mutex_unlock + +#elif defined(__MINGW32__) + +#include +#include +#define BOOL int +#include // posix_memalign() +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +//#define max(a,b) (((a) > (b)) ? (a) : (b)) +//#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define __declspec(x) +#define __assume(x) ; +#define strnicmp strncasecmp +#define stricmp strcasecmp +#include +//#pragma intrinsic (InterlockedAnd) +// Definitions added Feb 16, 2006 by efp +//#define __declspec(x) +#include +#define __forceinline inline +#define _aligned_malloc(x,y) __mingw_aligned_malloc(x,y) +#define _aligned_free(x) __mingw_aligned_free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#define fpusqrtf sqrtf +#define fpufabsf fabsf +#define fpusinf sinf +#define fpucosf cosf +#define fpuexpf expf +#define fpuatanf atanf +#define fpuatan2f atan2f + +#else + +#include +#include // posix_memalign() +#define BOOL int + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef strnicmp +#define strnicmp strncasecmp +#endif + +#ifndef stricmp +#define stricmp strcasecmp +#endif + +// Definitions added Feb 16, 2006 by efp +#ifndef __declspec +#define __declspec(x) +#endif + +#define pthread_mutex__unlock pthread_mutex_unlock + +#endif + +#ifdef ENABLE_NLS + +#ifdef __MSCW32__ +#include "libintlmsc.h" +#else +#include "libintl.h" +#endif + +#undef _ +#define _(String) dgettext (PACKAGE, String) +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif + +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +#include "PS2Etypes.h" + +#ifdef PCSX2_DEVBUILD + +typedef struct _TESTRUNARGS +{ + u8 enabled; + u8 jpgcapture; + + int frame; // if < 0, frame is unlimited (run until crash). + int numimages; + int curimage; + u32 autopad; // mask for auto buttons + int efile; + int snapdone; + + char* ptitle; + char* pimagename; + char* plogname; + char* pgsdll, *pcdvddll, *pspudll; + +} TESTRUNARGS; + +extern TESTRUNARGS g_TestRun; + +#endif + +#define BIAS 2 // Bus is half of the actual ps2 speed +//#define PS2CLK 36864000 /* 294.912 mhz */ +//#define PSXCLK 9216000 /* 36.864 Mhz */ +//#define PSXCLK 186864000 /* 36.864 Mhz */ +#define PS2CLK 294912000 /* 294.912 mhz */ +#define PSXCLK 36864000 /* 36.864 Mhz */ + + +/* Config.PsxType == 1: PAL: + VBlank interlaced 50.00 Hz + VBlank non-interlaced 49.76 Hz + HBlank 15.625 KHz + Config.PsxType == 0: NSTC + VBlank interlaced 59.94 Hz + VBlank non-interlaced 59.82 Hz + HBlank 15.73426573 KHz */ +#define PS2VBLANK_NTSC_INT ((int)(PS2CLK / 59.94)) +#define PS2VBLANK_NTSC ((int)(PS2CLK / 59.82)) +#define PS2VBLANK_PAL_INT ((int)(PS2CLK / 50.00)) +#define PS2VBLANK_PAL ((int)(PS2CLK / 49.76)) +#define VBLANK_NTSC ((Config.PsxType & 2) ? 59.94 : 59.82) +#define VBLANK_PAL ((Config.PsxType & 2) ? 50.00 : 49.76) +#define HBLANK_NTSC (15734.26573) +#define HBLANK_PAL (15625) +#define PS2HBLANKEND_PAL (386*8) +#define PS2HBLANKEND_NTSC (371*8) +#define PS2VBLANKPAL ((Config.PsxType & 2) ? 312.5 : 314) +#define PS2VBLANKNTSC ((Config.PsxType & 2) ? 262.5 : 263) +#define PS2VBLANKEND_PAL ((int)(PS2HBLANK_PAL*6)) +#define PS2VBLANKEND_NTSC ((int)(PS2HBLANK_NTSC*6)) + +#define PS2HBLANK_NTSC ((int)(PS2CLK / HBLANK_NTSC)) +#define PS2HBLANK_PAL ((int)(PS2CLK / HBLANK_PAL)) +#define PS2HBLANK ((int)((Config.PsxType & 1) ? PS2HBLANK_PAL : PS2HBLANK_NTSC)) +#define PS2HBLANKEND ((int)((Config.PsxType & 1) ? PS2HBLANKEND_PAL : PS2HBLANKEND_NTSC)) +#define PS2VBLANKEND ((int)((Config.PsxType & 1) ? PS2VBLANKEND_PAL : PS2VBLANKEND_NTSC)) +#define PSXVBLANK_NTSC ((int)(PSXCLK / VBLANK_NTSC)) +#define PSXVBLANK_PAL ((int)(PSXCLK / VBLANK_PAL)) +#define PSXVBLANK ((int)((Config.PsxType & 1) ? PSXVBLANK_PAL : PSXVBLANK_NTSC)) +#define PSXHBLANK_NTSC ((int)(PSXCLK / HBLANK_NTSC)) +#define PSXHBLANK_PAL ((int)(PSXCLK / HBLANK_PAL)) +#define PSXHBLANK ((int)((Config.PsxType & 1) ? PSXHBLANK_PAL : PSXHBLANK_NTSC)) +#define PSXPIXEL ((int)(PSXCLK / 13500000)) +#define PSXSOUNDCLK ((int)(48000)) + +#define COLOR_BLACK "\033[30m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[32m" +#define COLOR_YELLOW "\033[33m" +#define COLOR_BLUE "\033[34m" +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" +#define COLOR_WHITE "\033[37m" +#define COLOR_RESET "\033[0m" + +#include // sync functions + +#include "R5900.h" +#include "DebugTools/Debug.h" +#include "System.h" +#include "Memory.h" +#include "Elfheader.h" +#include "Hw.h" +//#include "GS.h" +#include "Vif.h" +#include "SPR.h" +#include "Sif.h" +#include "Plugins.h" +#include "PS2Edefs.h" +#include "Counters.h" +#include "IPU/IPU.h" +#include "Misc.h" +#include "Patch.h" +#include "COP0.h" +#include "VifDma.h" +#if (defined(__i386__) || defined(__x86_64__)) +#include "x86/ix86/ix86.h" +#endif + +int cdCaseopen; + +extern void __Log(char *fmt, ...); +extern u16 logProtocol; +extern u8 logSource; +#define PCSX2_VERSION "0.9.2" + +// C++ code for sqrtf +void InitFPUOps(); +extern float (*fpusqrtf)(float fval); +extern float (*fpufabsf)(float fval); +extern float (*fpusinf)(float fval); +extern float (*fpucosf)(float fval); +extern float (*fpuexpf)(float fval); +extern float (*fpuatanf)(float fval); +extern float (*fpuatan2f)(float fvalx, float fvaly); + +// Added Feb 16, 2006 by efp +#ifdef __LINUX__ +#include // EBUSY +#endif /* __LINUX__ */ + +#define DESTROY_MUTEX(mutex) { \ + int err = pthread_mutex_destroy(&mutex); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#mutex"\n"); \ +} \ + +#define DESTROY_COND(cond) { \ + int err = pthread_cond_destroy(&cond); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#cond"\n"); \ +} \ + +#endif /* __COMMON_H__ */ diff --git a/branches/pcsx2_0.9.2/Counters.c b/branches/pcsx2_0.9.2/Counters.c new file mode 100644 index 0000000..fcae50a --- /dev/null +++ b/branches/pcsx2_0.9.2/Counters.c @@ -0,0 +1,654 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "GS.h" + +int gates = 0; +extern u8 psxhblankgate; +int hblankend = 0; +Counter counters[6]; +u32 nextCounter, nextsCounter; + +// its so it doesnt keep triggering an interrupt once its reached its target +// if it doesnt reset the counter it needs stopping +u32 eecntmask = 0; + +void rcntUpdTarget(int index) { + counters[index].sCycleT = cpuRegs.cycle - (cpuRegs.cycle % counters[index].rate); +} + +void rcntUpd(int index) { + counters[index].sCycle = cpuRegs.cycle - (cpuRegs.cycle % counters[index].rate); + rcntUpdTarget(index); +} + +void rcntReset(int index) { + counters[index].count = 0; + counters[index].mode&= ~0x00400C00; + rcntUpd(index); +} + +void rcntSet() { + u32 c; + int i; + + nextCounter = 0xffffffff; + nextsCounter = cpuRegs.cycle; + + for (i = 0; i < 4; i++) { + if (!(counters[i].mode & 0x80)) continue; // Stopped + + c = (0xffff - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + + // the + 10 is just in case of overflow + if(eecntmask & (1< 0 ) { + if( iFrame > g_TestRun.frame ) { + // take a snapshot + if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) { + if( g_TestRun.snapdone ) { + g_TestRun.curimage++; + g_TestRun.snapdone = 0; + g_TestRun.frame += 20; + if( g_TestRun.curimage >= g_TestRun.numimages ) { + // exit + SysClose(); + exit(0); + } + } + else { + // query for the image + GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture); + } + } + else { + // exit + SysClose(); + exit(0); + } + } + } + + GSVSYNC(); + + if( g_SaveGSStream == 1 ) { + freezeData fP; + + g_SaveGSStream = 2; + gsFreeze(g_fGSSave, 1); + + if (GSfreeze(FREEZE_SIZE, &fP) == -1) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + fP.data = (s8*)malloc(fP.size); + if (fP.data == NULL) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + if (GSfreeze(FREEZE_SAVE, &fP) == -1) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + gzwrite(g_fGSSave, &fP.size, sizeof(fP.size)); + if (fP.size) { + gzwrite(g_fGSSave, fP.data, fP.size); + free(fP.data); + } + } + } + } + } + else if( g_SaveGSStream == 2 ) { + + if( --g_nLeftGSFrames <= 0 ) { + gzclose(g_fGSSave); + g_fGSSave = NULL; + g_SaveGSStream = 0; + SysPrintf("Done saving GS stream\n"); + } + } +#endif + + // used to limit frames + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_LIMIT: + FrameLimiter(); + break; + + case PCSX2_FRAMELIMIT_SKIP: + case PCSX2_FRAMELIMIT_VUSKIP: + { + // the 6 was after trial and error + static u32 uPrevTimes[6] = {0}, uNextFrame = 0, uNumFrames = 0, uTotalTime = 0; + static u32 uLastTime = 0; + static int nConsecutiveSkip = 0, nConsecutiveRender = 0; + extern u32 g_bVUSkip; + static int changed = 0; + static int nNoSkipFrames = 0; + + u32 uExpectedTime; + u32 uCurTime = timeGetTime(); + u32 uDeltaTime = uCurTime - uLastTime; + + assert( GSsetFrameSkip != NULL ); + + if( uLastTime > 0 ) { + + if( uNumFrames == ARRAYSIZE(uPrevTimes) ) + uTotalTime -= uPrevTimes[uNextFrame]; + + uPrevTimes[uNextFrame] = uDeltaTime; + uNextFrame = (uNextFrame + 1) % ARRAYSIZE(uPrevTimes); + uTotalTime += uDeltaTime; + + if( uNumFrames < ARRAYSIZE(uPrevTimes) ) + ++uNumFrames; + } + + uExpectedTime = (Config.PsxType&1) ? (ARRAYSIZE(uPrevTimes) * 1000 / 50 -1) : (ARRAYSIZE(uPrevTimes) * 1000 / 60 - 1); + + if( nNoSkipFrames > 0 ) + --nNoSkipFrames; + + // hmm... this might be more complicated than it needs to be + if( changed != 0 ) { + if( changed > 0 ) { + ++nConsecutiveRender; + --changed; + + if( nConsecutiveRender > 20 && uTotalTime + 1 < uExpectedTime ) { + Sleep(uExpectedTime-uTotalTime); + nNoSkipFrames = ARRAYSIZE(uPrevTimes); + } + } + else { + ++nConsecutiveSkip; + ++changed; + } + } + else { + if( nNoSkipFrames == 0 && nConsecutiveRender > 3 && nConsecutiveSkip < 20 && + (CHECK_MULTIGS? (uTotalTime >= uExpectedTime + uDeltaTime/4 && (uTotalTime >= uExpectedTime + uDeltaTime*3/4 || nConsecutiveSkip==0)) : + (uTotalTime >= uExpectedTime + (uDeltaTime/4))) ) { + + if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP ) { + Cpu->ExecuteVU1Block = DummyExecuteVU1Block; + } + + if( nConsecutiveSkip == 0 ) { + if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 1, 0, 0); + else GSsetFrameSkip(1); + } + + changed = -3; + nConsecutiveSkip++; + } + else { + + if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP ) { + Cpu->ExecuteVU1Block = recExecuteVU1Block; + } + + if( nConsecutiveSkip ) { + if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0); + else GSsetFrameSkip(0); + + nConsecutiveRender = 0; + } + + changed = 3; + nConsecutiveRender++; + nConsecutiveSkip = 0; + + if( nConsecutiveRender > 20 && uTotalTime + 1 < uExpectedTime ) { + Sleep(uExpectedTime-uTotalTime); + nNoSkipFrames = ARRAYSIZE(uPrevTimes); + } + } + } + + uLastTime = uCurTime; + + break; + } + } + + //counters[5].mode&= ~0x10000; + //UpdateVSyncRate(); + + //SysPrintf("ctrs: %d %d %d %d\n", g_nCounters[0], g_nCounters[1], g_nCounters[2], g_nCounters[3]); + //SysPrintf("vif: %d\n", (((LARGE_INTEGER*)g_nCounters)->QuadPart * 1000000) / lfreq.QuadPart); + //memset(g_nCounters, 0, 16); + counters[5].mode|= 0x10000; + + if (!(GSCSRr & 0x8)){ + GSCSRr|= 0x8; + + } + if (!(GSIMR&0x800) ) + gsIrq(); + hwIntcIrq(2); + psxVSyncStart(); + + if(Config.Patch) applypatch(1); + if(gates)rcntStartGate(0x8); + +// __Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]); +// s_lastvsync[0] = timeGetTime(); +// s_lastvsync[1] = cpuRegs.cycle; + } +} + + +void rcntUpdate() +{ + int i; + for (i=0; i<=3; i++) { + if (!(counters[i].mode & 0x80)) continue; // Stopped + counters[i].count += (int)((cpuRegs.cycle - counters[i].sCycleT) / counters[i].rate); + counters[i].sCycleT = cpuRegs.cycle - (cpuRegs.cycle % counters[i].rate); + } + for (i=0; i<=3; i++) { + if (!(counters[i].mode & 0x80)) continue; // Stopped + + + if ((counters[i].count & ~0x3) == (counters[i].target & ~0x3)) { // Target interrupt + /*if (rcntCycle(i) != counters[i].target){ + SysPrintf("rcntcycle = %d, target = %d, cyclet = %d\n", rcntCycle(i), counters[i].target, counters[i].sCycleT); + counters[i].sCycleT += (rcntCycle(i) - counters[i].target) * counters[i].rate; + SysPrintf("rcntcycle = %d, target = %d, cyclet = %d\n", rcntCycle(i), counters[i].target, counters[i].sCycleT); + }*/ + //if ((eecntmask & (1 << i)) == 0) { + counters[i].mode|= 0x0400; // Target flag + if(counters[i].mode & 0x100) { + hwIntcIrq(counters[i].interrupt); + + } + //eecntmask |= (1 << i); + //} + if (counters[i].mode & 0x40) { // Reset on target + counters[i].count = 0; + eecntmask &= ~(1 << i); + //rcntUpd(i); + } + + } + + + if (counters[i].count >= 0xffff) { + eecntmask &= ~(1 << i); + counters[i].mode|= 0x0800; // Overflow flag + if (counters[i].mode & 0x0200) { // Overflow interrupt + + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle); + } + counters[i].count = 0; + //rcntUpd(i); + } + // rcntUpd(i); + } + + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT && hblankend == 1){ + + if (!(GSCSRr & 0x4)){ + GSCSRr |= 4; // signal + + } + if (!(GSIMR&0x400) ) + gsIrq(); + if(gates)rcntEndGate(0); + if(psxhblankgate)psxCheckEndGate(0); + hblankend = 0; + counters[4].CycleT = counters[4].rate; + } + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT) { + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate-PS2HBLANKEND; + counters[4].Cycle = counters[4].rate; + counters[4].count = 0; + + if(gates)rcntStartGate(0); + if(psxhblankgate)psxCheckStartGate(0); + hblankend = 1; + } + + if ((cpuRegs.cycle - counters[5].sCycleT) + >= counters[5].CycleT && (counters[5].mode & 0x10000)){ + counters[5].CycleT = counters[5].rate; + VSync(); + } + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) { + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate-PS2VBLANKEND; + counters[5].Cycle = counters[5].rate; + counters[5].count = 0; + VSync(); + } + rcntSet(); +} + +void rcntWcount(int index, u32 value) { + //SysPrintf ("writeCcount[%d] = %x\n", index, value); +#ifdef EECNT_LOG + EECNT_LOG("EE count write %d count %x with %x target %x eecycle %x\n", index, counters[index].count, value, counters[index].target, cpuRegs.eCycle); +#endif + //if((u16)value < counters[index].target) + //eecntmask &= ~(1 << index); + counters[index].count = value & 0xffff; + rcntUpd(index); + rcntSet(); +} + +void rcntWmode(int index, u32 value) +{ + + + if (value & 0xc00) { //Clear status flags, the ps2 only clears what is given in the value + eecntmask &= ~(1 << index); + counters[index].mode &= ~((value & 0xc00)); + } + + + //if((value & 0x3ff) != (counters[index].mode & 0x3ff))eecntmask &= ~(1 << index); + counters[index].mode = (counters[index].mode & 0xc00) | (value & 0x3ff); + +#ifdef EECNT_LOG + EECNT_LOG("EE counter set %d mode %x\n", index, counters[index].mode); +#endif + + switch (value & 0x3) { //Clock rate divisers *2, they use BUSCLK speed not PS2CLK + case 0: counters[index].rate = 2; break; + case 1: counters[index].rate = 32; break; + case 2: counters[index].rate = 512; break; + case 3: counters[index].rate = PS2HBLANK; break; + } + + if((counters[index].mode & 0xF) == 0x7) { + gates &= ~(1<> 4); + switch((counters[i].mode & 0x30) >> 4){ + case 0x0: //Count When Signal is low (off) + counters[i].count = rcntRcount(i); + rcntUpd(i); + counters[i].mode &= ~0x80; + break; + case 0x1: //Reset and start counting on Vsync start + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x2: //Reset and start counting on Vsync end + //Do Nothing + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntEndGate(int mode){ + int i; + + for(i=0; i <=3; i++){ //Gates for counters + if(!(gates & (1<> 4); + switch((counters[i].mode & 0x30) >> 4){ + case 0x0: //Count When Signal is low (off) + rcntUpd(i); + counters[i].mode |= 0x80; + break; + case 0x1: //Reset and start counting on Vsync start + //Do Nothing + break; + case 0x2: //Reset and start counting on Vsync end + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntWtarget(int index, u32 value) { + + eecntmask &= ~(1 << index); + counters[index].target = value & 0xffff; + +#ifdef EECNT_LOG + EECNT_LOG("EE target write %d target %x value %x\n", index, counters[index].target, value); +#endif + rcntSet(); +} + +void rcntWhold(int index, u32 value) { +#ifdef EECNT_LOG + EECNT_LOG("EE hold write %d value %x\n", index, value); +#endif + counters[index].hold = value; +} + +u16 rcntRcount(int index) { + u16 ret; + + if ((counters[index].mode & 0x80)) { + ret = counters[index].count + (int)((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); + }else{ + ret = counters[index].count; + } + + return (u16)ret; +} + +u32 rcntCycle(int index) { + + if ((counters[index].mode & 0x80)) { + return (u32)counters[index].count + (int)((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); + }else{ + return (u32)counters[index].count; + } +} + +int rcntFreeze(gzFile f, int Mode) { + gzfreezel(counters); + gzfreeze(&nextCounter, sizeof(nextCounter)); + gzfreeze(&nextsCounter, sizeof(nextsCounter)); + + return 0; +} + diff --git a/branches/pcsx2_0.9.2/Counters.h b/branches/pcsx2_0.9.2/Counters.h new file mode 100644 index 0000000..8db0188 --- /dev/null +++ b/branches/pcsx2_0.9.2/Counters.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COUNTERS_H__ +#define __COUNTERS_H__ + +typedef struct { + u32 count, mode, target, hold; + u32 rate, interrupt; + u32 Cycle, sCycle; + u32 CycleT, sCycleT; +} Counter; + +extern Counter counters[6]; +extern u32 nextCounter, nextsCounter; + +void rcntInit(); +void rcntUpdate(); +void rcntStartGate(int mode); +void rcntEndGate(int mode); +void rcntWcount(int index, u32 value); +void rcntWmode(int index, u32 value); +void rcntWtarget(int index, u32 value); +void rcntWhold(int index, u32 value); +u16 rcntRcount(int index); +u32 rcntCycle(int index); +int rcntFreeze(gzFile f, int Mode); + +void UpdateVSyncRate(); + +#endif /* __COUNTERS_H__ */ diff --git a/branches/pcsx2_0.9.2/DebugTools/Debug.h b/branches/pcsx2_0.9.2/DebugTools/Debug.h new file mode 100644 index 0000000..6df5ba1 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/Debug.h @@ -0,0 +1,137 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "Common.h" + +FILE *emuLog; + +char* disR5900F(u32 code, u32 pc); +char* disR5900Fasm(u32 code, u32 pc); +char* disR3000Fasm(u32 code, u32 pc); + +void disR5900AddSym(u32 addr, char *name); +char* disR5900GetSym(u32 addr); +char* disR5900GetUpperSym(u32 addr); +void disR5900FreeSyms(); + +char* disVU0MicroUF(u32 code, u32 pc); +char* disVU0MicroLF(u32 code, u32 pc); +char* disVU1MicroUF(u32 code, u32 pc); +char* disVU1MicroLF(u32 code, u32 pc); + +char* disR3000AF(u32 code, u32 pc); + +extern char *CP2VFnames[]; +extern char *disRNameCP2f[]; +extern char *disRNameCP2i[]; + +//that way is slower but you now not need to compile every time ;P +#ifdef PCSX2_DEVBUILD + +int Log; +u32 varLog; + +//memcars has the same number as PAD_LOG +#define MEMCARDS_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log + +#define CPU_LOG if (varLog & 0x00000001) {logProtocol=1; logSource='E';} if (varLog & 0x00000001) __Log +#define MEM_LOG if (varLog & 0x00000002) {logProtocol=6; logSource='E';} if (varLog & 0x00000002) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000002) __Log +#define HW_LOG if (varLog & 0x00000004) {logProtocol=6; logSource='E';} if (varLog & 0x00000004) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000004) __Log +#define DMA_LOG if (varLog & 0x00000008) {logProtocol=5; logSource='E';} if (varLog & 0x00000008) __Log +#define BIOS_LOG if (varLog & 0x00000010) {logProtocol=0; logSource='E';} if (varLog & 0x00000010) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000010) __Log +#define ELF_LOG if (varLog & 0x00000020) {logProtocol=7; logSource='E';} if (varLog & 0x00000020) __Log +#define FPU_LOG if (varLog & 0x00000040) {logProtocol=1; logSource='E';} if (varLog & 0x00000040) __Log +#define MMI_LOG if (varLog & 0x00000080) {logProtocol=1; logSource='E';} if (varLog & 0x00000080) __Log +#define VU0_LOG if (varLog & 0x00000100) {logProtocol=2; logSource='E';} if (varLog & 0x00000100) __Log +#define COP0_LOG if (varLog & 0x00000200) {logProtocol=1; logSource='E';} if (varLog & 0x00000200) __Log +#define VIF_LOG if (varLog & 0x00000400) {logProtocol=3; logSource='E';} if (varLog & 0x00000400) __Log +#define SPR_LOG if (varLog & 0x00000800) {logProtocol=7; logSource='E';} if (varLog & 0x00000800) __Log +#define GIF_LOG if (varLog & 0x00001000) {logProtocol=4; logSource='E';} if (varLog & 0x00001000) __Log +#define SIF_LOG if (varLog & 0x00002000) {logProtocol=9; logSource='E';} if (varLog & 0x00002000) __Log +#define IPU_LOG if (varLog & 0x00004000) {logProtocol=8; logSource='E';} if (varLog & 0x00004000) __Log +#define VUM_LOG if (varLog & 0x00008000) {logProtocol=2; logSource='E';} if (varLog & 0x00008000) __Log +#define RPC_LOG if (varLog & 0x00010000) {logProtocol=9; logSource='E';} if (varLog & 0x00010000) __Log + +#define PSXCPU_LOG if (varLog & 0x00100000) {logProtocol=1; logSource='I';} if (varLog & 0x00100000) __Log +#define PSXMEM_LOG if (varLog & 0x00200000) {logProtocol=6; logSource='I';} if (varLog & 0x00200000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00200000) __Log +#define PSXHW_LOG if (varLog & 0x00400000) {logProtocol=2; logSource='I';} if (varLog & 0x00400000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00400000) __Log +#define PSXBIOS_LOG if (varLog & 0x00800000) {logProtocol=0; logSource='I';} if (varLog & 0x00800000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00800000) __Log +#define PSXDMA_LOG if (varLog & 0x01000000) {logProtocol=5; logSource='I';} if (varLog & 0x01000000) __Log + +#define PAD_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log +#define GTE_LOG if (varLog & 0x04000000) {logProtocol=3; logSource='I';} if (varLog & 0x04000000) __Log +#define CDR_LOG if (varLog & 0x08000000) {logProtocol=8; logSource='I';} if (varLog & 0x08000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x08000000) __Log +#define GPU_LOG if (varLog & 0x10000000) {logProtocol=4; logSource='I';} if (varLog & 0x10000000) __Log +#define PSXCNT_LOG if (varLog & 0x20000000) {logProtocol=0; logSource='I';} if (varLog & 0x20000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x20000000) __Log +#define EECNT_LOG if (varLog & 0x40000000) {logProtocol=0; logSource='I';} if (varLog & 0x40000000) __Log("%8.8lx %8.8lx: ", cpuRegs.pc, cpuRegs.cycle); if (varLog & 0x40000000) __Log + +#if defined (CPU_LOG) || defined(MEM_LOG) || defined(HW_LOG) || defined(DMA_LOG) || \ + defined(BIOS_LOG) || defined(ELF_LOG) || defined(FPU_LOG) || defined(MMI_LOG) || \ + defined(VU0_LOG) || defined(COP0_LOG) || defined(VIF_LOG) || defined(SPR_LOG) || \ + defined(GIF_LOG) || defined(SIF_LOG) || defined(IPU_LOG) || defined(VUM_log) || \ + defined(PSXCPU_LOG) || defined(PSXMEM_LOG)|| defined(IOPBIOS_LOG)|| defined(IOPHW_LOG)|| \ + defined(PAD_LOG) || defined(GTE_LOG) || defined(CDR_LOG) || defined(GPU_LOG) || \ + defined(MEMCARDS_LOG)|| defined(PSXCNT_LOG) || defined(EECNT_LOG) +#define EMU_LOG __Log +#endif + +#else // PCSX2_DEVBUILD + +#define varLog 0 +#define Log 0 + +#define CPU_LOG 0&& +#define MEM_LOG 0&& +#define HW_LOG 0&& +#define DMA_LOG 0&& +#define BIOS_LOG 0&& +#define ELF_LOG 0&& +#define FPU_LOG 0&& +#define MMI_LOG 0&& +#define VU0_LOG 0&& +#define COP0_LOG 0&& +#define VIF_LOG 0&& +#define SPR_LOG 0&& +#define GIF_LOG 0&& +#define SIF_LOG 0&& +#define IPU_LOG 0&& +#define VUM_LOG 0&& +#define RPC_LOG 0&& + +#define PSXCPU_LOG 0&& +#define PSXMEM_LOG 0&& +#define PSXHW_LOG 0&& +#define PSXBIOS_LOG 0&& +#define PSXDMA_LOG 0&& + +#define PAD_LOG 0&& +#define GTE_LOG 0&& +#define CDR_LOG 0&& +#define GPU_LOG 0&& +#define PSXCNT_LOG 0&& +#define EECNT_LOG 0&& + +#define EMU_LOG 0&& + +#endif + +#endif /* __DEBUG_H__ */ diff --git a/branches/pcsx2_0.9.2/DebugTools/DisASM.h b/branches/pcsx2_0.9.2/DebugTools/DisASM.h new file mode 100644 index 0000000..ceb5917 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisASM.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "R5900.h" + +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +///******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) + +//IOP + +#define DECODE_RD_IOP ((psxRegs.code >> 11) & 0x1F) +#define DECODE_RT_IOP ((psxRegs.code >> 16) & 0x1F) +#define DECODE_RS_IOP ((psxRegs.code >> 21) & 0x1F) +#define DECODE_IMMED_IOP ( psxRegs.code & 0xFFFF) +#define DECODE_SA_IOP ((psxRegs.code >> 6) & 0x1F) +#define DECODE_FS_IOP (DECODE_RD_IOP) + diff --git a/branches/pcsx2_0.9.2/DebugTools/DisR3000A.c b/branches/pcsx2_0.9.2/DebugTools/DisR3000A.c new file mode 100644 index 0000000..d0dad71 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisR3000A.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Debug.h" + +char ostr[256]; + +// Names of registers +static char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"}; + +static char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + + +// Type deffinition of our functions + +typedef char* (*TdisR3000AF)(u32 code, u32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; } +#define MakeDisF(fn, b) \ + static char* fn(u32 code, u32 pc) { \ + sprintf (ostr, "%8.8lx %8.8lx:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + + +#include "R3000A.h" + +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ +#undef _Target_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i]) +#define dCP0(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i]) +#define dHI() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.hi, "hi") +#define dLO() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.lo, "lo") +#define dImm() sprintf(ostr, "%s %4.4lx (%ld),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8lx,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2lx (%ld),", ostr, _Sa_, _Sa_) +#define dOfB() sprintf(ostr, "%s %4.4lx (%8.8lx (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8lx,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8lx,", ostr, (code >> 6) & 0xffffff) + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();) +MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();) +MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, dName("BREAK")) +MakeDisF(disRFE, dName("RFE")) +MakeDisF(disSYSCALL, dName("SYSCALL")) + + + +MakeDisF(disRTPS, dName("RTPS")) +MakeDisF(disOP , dName("OP")) +MakeDisF(disNCLIP, dName("NCLIP")) +MakeDisF(disDPCS, dName("DPCS")) +MakeDisF(disINTPL, dName("INTPL")) +MakeDisF(disMVMVA, dName("MVMVA")) +MakeDisF(disNCDS , dName("NCDS")) +MakeDisF(disCDP , dName("CDP")) +MakeDisF(disNCDT , dName("NCDT")) +MakeDisF(disNCCS , dName("NCCS")) +MakeDisF(disCC , dName("CC")) +MakeDisF(disNCS , dName("NCS")) +MakeDisF(disNCT , dName("NCT")) +MakeDisF(disSQR , dName("SQR")) +MakeDisF(disDCPL , dName("DCPL")) +MakeDisF(disDPCT , dName("DPCT")) +MakeDisF(disAVSZ3, dName("AVSZ3")) +MakeDisF(disAVSZ4, dName("AVSZ4")) +MakeDisF(disRTPT , dName("RTPT")) +MakeDisF(disGPF , dName("GPF")) +MakeDisF(disGPL , dName("GPL")) +MakeDisF(disNCCT , dName("NCCT")) + +MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);) +MakeDisF(disMTC2, dName("MTC2")) +MakeDisF(disCTC2, dName("CTC2")) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget();) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR(_Rs_);) +MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_)) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disNULL , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/branches/pcsx2_0.9.2/DebugTools/DisR3000asm.c b/branches/pcsx2_0.9.2/DebugTools/DisR3000asm.c new file mode 100644 index 0000000..d2e0612 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisR3000asm.c @@ -0,0 +1,361 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "R3000A.h" +#include "DisASM.h" + +unsigned long IOP_opcode_addr; + +char *GPR_IOP_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_IOP_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +void IOPD_SPECIAL(char *buf); +void IOPD_REGIMM(char *buf); +void IOPD_J(char *buf); +void IOPD_JAL(char *buf); +void IOPD_BEQ(char *buf); +void IOPD_BNE(char *buf); +void IOPD_BLEZ(char *buf); +void IOPD_BGTZ(char *buf); +void IOPD_ADDI(char *buf); +void IOPD_ADDIU(char *buf); +void IOPD_SLTI(char *buf); +void IOPD_SLTIU(char *buf); +void IOPD_ANDI(char *buf); +void IOPD_ORI(char *buf); +void IOPD_XORI(char *buf); +void IOPD_LUI(char *buf); +void IOPD_COP0(char *buf); +void IOPD_COP2(char *buf); +void IOPD_LB(char *buf); +void IOPD_LH(char *buf); +void IOPD_LWL(char *buf); +void IOPD_LW(char *buf); +void IOPD_LBU(char *buf); +void IOPD_LHU(char *buf); +void IOPD_LWR(char *buf); +void IOPD_SB(char *buf); +void IOPD_SH(char *buf); +void IOPD_SWL(char *buf); +void IOPD_SW(char *buf); +void IOPD_SWR(char *buf); +void IOPD_LWC2(char *buf); +void IOPD_SWC2(char *buf); + +void IOPD_SLL(char *buf); +void IOPD_SRL(char *buf); +void IOPD_SRA(char *buf); +void IOPD_SLLV(char *buf); +void IOPD_SRLV(char *buf); +void IOPD_SRAV(char *buf); +void IOPD_JR(char *buf); +void IOPD_JALR(char *buf); +void IOPD_SYSCALL(char *buf); +void IOPD_BREAK(char *buf); +void IOPD_MFHI(char *buf); +void IOPD_MTHI(char *buf); +void IOPD_MFLO(char *buf); +void IOPD_MTLO(char *buf); +void IOPD_MULT(char *buf); +void IOPD_MULTU(char *buf); +void IOPD_DIV(char *buf); +void IOPD_DIVU(char *buf); +void IOPD_ADD(char *buf); +void IOPD_ADDU(char *buf); +void IOPD_SUB(char *buf); +void IOPD_SUBU(char *buf); +void IOPD_AND(char *buf); +void IOPD_OR(char *buf); +void IOPD_XOR(char *buf); +void IOPD_NOR(char *buf); +void IOPD_SLT(char *buf); +void IOPD_SLTU(char *buf); + + +void IOPD_BLTZ(char *buf); +void IOPD_BGEZ(char *buf); +void IOPD_BLTZAL(char *buf); +void IOPD_BGEZAL(char *buf); + + + +void IOPD_MFC0(char *buf); +void IOPD_CFC0(char *buf); +void IOPD_MTC0(char *buf); +void IOPD_CTC0(char *buf); +void IOPD_RFE(char *buf); + + + +void IOPD_BASIC(char *buf); +void IOPD_RTPS(char *buf); +void IOPD_NCLIP(char *buf); +void IOPD_OP(char *buf); +void IOPD_DPCS(char *buf); +void IOPD_INTPL(char *buf); +void IOPD_MVMVA(char *buf); +void IOPD_NCDS(char *buf); +void IOPD_CDP(char *buf); +void IOPD_NCDT(char *buf); +void IOPD_NCCS(char *buf); +void IOPD_CC(char *buf); +void IOPD_NCS(char *buf); +void IOPD_NCT(char *buf); +void IOPD_SQR(char *buf); +void IOPD_DCPL(char *buf); +void IOPD_DPCT(char *buf); +void IOPD_AVSZ3(char *buf); +void IOPD_AVSZ4(char *buf); +void IOPD_RTPT(char *buf); +void IOPD_GPF(char *buf); +void IOPD_GPL(char *buf); +void IOPD_NCCT(char *buf); + + + +void IOPD_MFC2(char *buf); +void IOPD_CFC2(char *buf); +void IOPD_MTC2(char *buf); +void IOPD_CTC2(char *buf); +void IOPD_NULL(char *buf); + + + + void (*IOP_DEBUG_BSC[64])(char *buf) = { + IOPD_SPECIAL, IOPD_REGIMM, IOPD_J , IOPD_JAL , IOPD_BEQ , IOPD_BNE , IOPD_BLEZ, IOPD_BGTZ, + IOPD_ADDI , IOPD_ADDIU , IOPD_SLTI, IOPD_SLTIU, IOPD_ANDI, IOPD_ORI , IOPD_XORI, IOPD_LUI , + IOPD_COP0 , IOPD_NULL , IOPD_COP2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_LB , IOPD_LH , IOPD_LWL , IOPD_LW , IOPD_LBU , IOPD_LHU , IOPD_LWR , IOPD_NULL, + IOPD_SB , IOPD_SH , IOPD_SWL , IOPD_SW , IOPD_NULL, IOPD_NULL, IOPD_SWR , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_LWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_SWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + + +void (*IOP_DEBUG_SPC[64])(char *buf) = { + IOPD_SLL , IOPD_NULL , IOPD_SRL , IOPD_SRA , IOPD_SLLV , IOPD_NULL , IOPD_SRLV, IOPD_SRAV, + IOPD_JR , IOPD_JALR , IOPD_NULL, IOPD_NULL, IOPD_SYSCALL, IOPD_BREAK, IOPD_NULL, IOPD_NULL, + IOPD_MFHI, IOPD_MTHI , IOPD_MFLO, IOPD_MTLO, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_MULT, IOPD_MULTU, IOPD_DIV , IOPD_DIVU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_ADD , IOPD_ADDU , IOPD_SUB , IOPD_SUBU, IOPD_AND , IOPD_OR , IOPD_XOR , IOPD_NOR , + IOPD_NULL, IOPD_NULL , IOPD_SLT , IOPD_SLTU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_REG[32])(char *buf) = { + IOPD_BLTZ , IOPD_BGEZ , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_BLTZAL, IOPD_BGEZAL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP0[32])(char *buf) = { + IOPD_MFC0, IOPD_NULL, IOPD_CFC0, IOPD_NULL, IOPD_MTC0, IOPD_NULL, IOPD_CTC0, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_RFE , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP2[64])(char *buf) = { + IOPD_BASIC, IOPD_RTPS , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NCLIP, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_OP , IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_DPCS , IOPD_INTPL, IOPD_MVMVA, IOPD_NCDS, IOPD_CDP , IOPD_NULL , IOPD_NCDT , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NCCS, IOPD_CC , IOPD_NULL , IOPD_NCS , IOPD_NULL, + IOPD_NCT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_SQR , IOPD_DCPL , IOPD_DPCT , IOPD_NULL, IOPD_NULL, IOPD_AVSZ3, IOPD_AVSZ4, IOPD_NULL, + IOPD_RTPT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_GPF , IOPD_GPL , IOPD_NCCT +}; + +void (*IOP_DEBUG_CP2BSC[32])(char *buf) = { + IOPD_MFC2, IOPD_NULL, IOPD_CFC2, IOPD_NULL, IOPD_MTC2, IOPD_NULL, IOPD_CTC2, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +static char dbuf2[1024]; +static char obuf2[1024]; + +char *disR3000Fasm(u32 code, u32 pc) { + u32 scode = psxRegs.code; + IOP_opcode_addr = pc; + psxRegs.code = code; + IOP_DEBUG_BSC[(code) >> 26](dbuf2); + + sprintf(obuf2, "%08lX:\t%s", pc, dbuf2); + + psxRegs.code = scode; + return obuf2; +} +char *IOP_jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = (IOP_opcode_addr & 0xf0000000)|((psxRegs.code&0x3ffffff)<<2); + sprintf(buf, "0x%08lX", addr); + return buf; +} +char *IOP_offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = ((((short)( psxRegs.code & 0xFFFF) * 4) + IOP_opcode_addr + 4)); + sprintf(buf, "0x%08lX", addr); + return buf; +} +//basic table +void IOPD_SPECIAL(char *buf){IOP_DEBUG_SPC[((psxRegs.code) & 0x3F)](buf);} +void IOPD_REGIMM(char *buf){IOP_DEBUG_REG[DECODE_RT_IOP](buf);} +void IOPD_J(char *buf) { sprintf(buf, "j\t%s", IOP_jump_decode());} +void IOPD_JAL(char *buf){sprintf(buf, "jal\t%s", IOP_jump_decode());} +void IOPD_BEQ(char *buf){sprintf(buf, "beq\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BNE(char *buf){sprintf(buf, "bne\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BLEZ(char *buf){sprintf(buf, "blez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGTZ(char *buf){sprintf(buf, "bgtz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_ADDI(char *buf){sprintf(buf, "addi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ADDIU(char *buf){sprintf(buf, "addiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTI(char *buf){sprintf(buf, "slti\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTIU(char *buf){sprintf(buf, "sltiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ANDI(char *buf){sprintf(buf, "andi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ORI(char *buf){sprintf(buf, "ori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_XORI(char *buf){sprintf(buf, "xori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_LUI(char *buf){sprintf(buf, "lui\t%s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP); } +void IOPD_COP0(char *buf){IOP_DEBUG_CP0[DECODE_RS_IOP](buf);} +void IOPD_COP2(char *buf){IOP_DEBUG_CP2[((psxRegs.code) & 0x3F)](buf);} +void IOPD_LB(char *buf){sprintf(buf, "lb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LH(char *buf){sprintf(buf, "lh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWL(char *buf){sprintf(buf, "lwl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LW(char *buf){sprintf(buf, "lw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LBU(char *buf){sprintf(buf, "lbu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LHU(char *buf){sprintf(buf, "lhu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWR(char *buf){sprintf(buf, "lwr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SB(char *buf){sprintf(buf, "sb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SH(char *buf){sprintf(buf, "sh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWL(char *buf){sprintf(buf, "swl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SW(char *buf){sprintf(buf, "sw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWR(char *buf){sprintf(buf, "swr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_LWC2(char *buf){strcpy(buf, "lwc2");} +void IOPD_SWC2(char *buf){strcpy(buf, "swc2");} +//special table +void IOPD_SLL(char *buf) +{ + if (psxRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); +} +void IOPD_SRL(char *buf){sprintf(buf, "srl\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); } +void IOPD_SRA(char *buf){sprintf(buf, "sra\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP);} +void IOPD_SLLV(char *buf){sprintf(buf, "sllv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SRLV(char *buf){sprintf(buf, "srlv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SRAV(char *buf){sprintf(buf, "srav\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_JR(char *buf){sprintf(buf, "jr\t%s", GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_JALR(char *buf) +{ + int rd = DECODE_RD_IOP; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_IOP_REG[DECODE_RS_IOP]); + else + sprintf(buf, "jalr\t%s, %s", GPR_IOP_REG[rd], GPR_IOP_REG[DECODE_RS_IOP]); +} + +void IOPD_SYSCALL(char *buf){strcpy(buf, "syscall");} +void IOPD_BREAK(char *buf){strcpy(buf, "break");} +void IOPD_MFHI(char *buf){sprintf(buf, "mfhi\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTHI(char *buf){sprintf(buf, "mthi\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MFLO(char *buf){sprintf(buf, "mflo\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTLO(char *buf){sprintf(buf, "mtlo\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MULT(char *buf){sprintf(buf, "mult\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_MULTU(char *buf){sprintf(buf, "multu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIV(char *buf){sprintf(buf, "div\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIVU(char *buf){sprintf(buf, "divu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } + +void IOPD_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +//regimm + +void IOPD_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } + +//cop0 + +void IOPD_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CFC0(char *buf){ sprintf(buf, "cfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CTC0(char *buf){ sprintf(buf, "ctc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_RFE(char *buf){strcpy(buf, "rfe");} +//cop2 +void IOPD_BASIC(char *buf){IOP_DEBUG_CP2BSC[DECODE_RS_IOP](buf);} +void IOPD_RTPS(char *buf){strcpy(buf, "rtps");} +void IOPD_NCLIP(char *buf){strcpy(buf, "nclip");} +void IOPD_OP(char *buf){strcpy(buf, "op");} +void IOPD_DPCS(char *buf){strcpy(buf, "dpcs");} +void IOPD_INTPL(char *buf){strcpy(buf, "intpl");} +void IOPD_MVMVA(char *buf){strcpy(buf, "mvmva");} +void IOPD_NCDS(char *buf){strcpy(buf, "ncds");} +void IOPD_CDP(char *buf){strcpy(buf, "cdp");} +void IOPD_NCDT(char *buf){strcpy(buf, "ncdt");} +void IOPD_NCCS(char *buf){strcpy(buf, "nccs");} +void IOPD_CC(char *buf){strcpy(buf, "cc");} +void IOPD_NCS(char *buf){strcpy(buf, "ncs");} +void IOPD_NCT(char *buf){strcpy(buf, "nct");} +void IOPD_SQR(char *buf){strcpy(buf, "sqr");} +void IOPD_DCPL(char *buf){strcpy(buf, "dcpl");} +void IOPD_DPCT(char *buf){strcpy(buf, "dpct");} +void IOPD_AVSZ3(char *buf){strcpy(buf, "avsz3");} +void IOPD_AVSZ4(char *buf){strcpy(buf, "avsz4");} +void IOPD_RTPT(char *buf){strcpy(buf, "rtpt");} +void IOPD_GPF(char *buf){strcpy(buf, "gpf");} +void IOPD_GPL(char *buf){strcpy(buf, "gpl");} +void IOPD_NCCT(char *buf){strcpy(buf, "ncct");} +//cop2 basic +void IOPD_MFC2(char *buf){strcpy(buf, "mfc2");} +void IOPD_CFC2(char *buf){strcpy(buf, "cfc2");} +void IOPD_MTC2(char *buf){strcpy(buf, "mtc2");} +void IOPD_CTC2(char *buf){strcpy(buf, "ctc2");} +//null +void IOPD_NULL(char *buf){strcpy(buf, "????");} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/DebugTools/DisR5900.c b/branches/pcsx2_0.9.2/DebugTools/DisR5900.c new file mode 100644 index 0000000..28ef02c --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisR5900.c @@ -0,0 +1,993 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VU.h" + +long jumpMode; +char ostr[1024]; + +// Names of registers +char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra", "hi", "lo"}; // lo,hi used in rec + +char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0" , "EntryLo1", "Context" , "PageMask" , "Wired" , "*RES*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID", + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "*RES*" , "*RES*" , "*RES*" , "Debug", + "DEPC" , "PerfCnt" , "ErrCtl" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "DESAVE"}; + +char *disRNameCP1[] = { + "FPR0" , "FPR1" , "FPR2" , "FPR3" , "FPR4" , "FPR5" , "FPR6" , "FPR7", + "FPR8" , "FPR9" , "FPR10", "FPR11", "FPR12", "FPR13", "FPR14", "FPR15", + "FPR16", "FPR17", "FPR18", "FPR19", "FPR20", "FPR21", "FPR22", "FPR23", + "FPR24", "FPR25", "FPR26", "FPR27", "FPR28", "FPR29", "FPR30", "FPR31"}; + +char *disRNameCP1c[] = { + "FRevID", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "FStatus"}; + +char *disRNameCP2f[] = { + "VF00", "VF01", "VF02", "VF03", "VF04", "VF05", "VF06", "VF07", + "VF08", "VF09", "VF10", "VF11", "VF12", "VF13", "VF14", "VF15", + "VF16", "VF17", "VF18", "VF19", "VF20", "VF21", "VF22", "VF23", + "VF24", "VF25", "VF26", "VF27", "VF28", "VF29", "VF30", "VF31"}; + +char *disRNameCP2i[] = { + "VI00", "VI01", "VI02", "VI03", "VI04", "VI05", "VI06", "VI07", + "VI08", "VI09", "VI10", "VI11", "VI12", "VI13", "VI14", "VI15", + "Status", "MAC", "Clip", "*RES*", "R", "I", "Q", "*RES*", + "*RES*", "*RES*", "TPC", "CMSAR0", "FBRST", "VPU-STAT", "*RES*", "CMSAR1"}; + +char *CP2VFnames[] = { "x", "y", "z", "w" }; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +#undef _Target_ +#undef _Branch_ +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + + +#define _rRs_ cpuRegs.GPR.r[_Rs_].UL[1], cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt_ cpuRegs.GPR.r[_Rt_].UL[1], cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd_ cpuRegs.GPR.r[_Rd_].UL[1], cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa_ cpuRegs.GPR.r[_Sa_].UL[1], cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + +#define _rFs_ cpuRegs.CP0.r[_Rd_] // Fs register + +#define _rRs32_ cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt32_ cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd32_ cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa32_ cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + + +#define _nRs_ _rRs_, disRNameGPR[_Rs_] +#define _nRt_ _rRt_, disRNameGPR[_Rt_] +#define _nRd_ _rRd_, disRNameGPR[_Rd_] +#define _nSa_ _rSa_, disRNameGPR[_Sa_] +#define _nRd0_ _rFs_, disRNameCP0[_Rd_] + +#define _nRs32_ _rRs32_, disRNameGPR[_Rs_] +#define _nRt32_ _rRt32_, disRNameGPR[_Rt_] +#define _nRd32_ _rRd32_, disRNameGPR[_Rd_] +#define _nSa32_ _rSa32_, disRNameGPR[_Sa_] + +#define _I_ _Im_, _Im_ +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR128(i) sprintf(ostr, "%s %8.8x_%8.8x_%8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64U(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], disRNameGPR[i]) +#define dGPR32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) + +#define dCP032(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.CP0.r[i], disRNameCP0[i]) + +#define dCP132(i) sprintf(ostr, "%s %f (%s),", ostr, fpuRegs.fpr[i].f, disRNameCP1[i]) +#define dCP1c32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, fpuRegs.fprc[i], disRNameCP1c[i]) +#define dCP1acc() sprintf(ostr, "%s %f (ACC),", ostr, fpuRegs.ACC.f) + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) + +#define dHI64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.HI.UL[1], cpuRegs.HI.UL[0], "hi") +#define dLO64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], "lo") +#define dImm() sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8x,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_) +#define dSa32() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_+32, _Sa_+32) +#define dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, cpuRegs.GPR.r[_Rs_].UL[0], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff) +#define dSaR() sprintf(ostr, "%s %8.8x,", ostr, cpuRegs.sa) + +typedef struct { + u32 addr; + char name[32]; +} sSymbol; + +static sSymbol *dSyms = NULL; +static int nSyms = 0; + +void disR5900AddSym(u32 addr, char *name) { + dSyms = (sSymbol*)realloc(dSyms, sizeof(sSymbol) * (nSyms+1)); + if (dSyms == NULL) return; + dSyms[nSyms].addr = addr; + strncpy(dSyms[nSyms].name, name, 32); + nSyms++; +} + +void disR5900FreeSyms() { + if (dSyms != NULL) { free(dSyms); dSyms = NULL; } + nSyms = 0; +} + +char *disR5900GetSym(u32 addr) { + int i; + + if (dSyms == NULL) return NULL; + for (i=0; i laddr) { + laddr = dSyms[i].addr; + j = i; + } + } + if (j == -1) return NULL; + return dSyms[j].name; +} + +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(ostr, "%s %s", ostr, str); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDI, dName("DADDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDIU, dName("DADDIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDADD, dName("DADD"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDADDU, dName("DADDU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDSUB, dName("DSUB"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDSUBU, dName("DSDBU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget(); dFindSym(_Target_);) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR32(31); dFindSym(_Target_);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR32(_Rs_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) +MakeDisF(disJALR, dName("JALR"); dGPR32(_Rs_); dGPR32(_Rd_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR64(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR64(_Rd_); dHI64();) +MakeDisF(disMFLO, dName("MFLO"); dGPR64(_Rd_); dLO64();) + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI64(); dGPR64(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO64(); dGPR64(_Rs_);) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disDSLL, dName("DSLL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSLL32, dName("DSLL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRA, dName("SRA"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRA, dName("DSRA"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRA32, dName("DSRA32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRL, dName("SRL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRL, dName("DSRL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRL32, dName("DSRL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSLLV, dName("DSLLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRAV, dName("DSRAV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRLV, dName("DSRLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWU, dName("LWU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLD, dName("LD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDL, dName("LDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDR, dName("LDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLQ, dName("LQ"); dGPR128(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSD, dName("SD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDL, dName("SDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDR, dName("SDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSQ, dName("SQ"); dGPR128(_Rt_); dOfB();) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, rd * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR32(_Rt_); dCP032(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP032(_Rd_); dGPR32(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +MakeDisF(disBGEZ, dName("BGEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + + +MakeDisF(disBEQL, dName("BEQL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNEL, dName("BNEL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBLEZL, dName("BLEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZL, dName("BGTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZL, dName("BLTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZL, dName("BGEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZALL, dName("BLTZALL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZALL, dName("BGEZALL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +MakeDisF(disBC0F, dName("BC0F"); dOffset();) +MakeDisF(disBC0T, dName("BC0T"); dOffset();) +MakeDisF(disBC0FL, dName("BC0FL"); dOffset();) +MakeDisF(disBC0TL, dName("BC0TL"); dOffset();) + +MakeDisF(disTLBR, dName("TLBR");) +MakeDisF(disTLBWI, dName("TLBWI");) +MakeDisF(disTLBWR, dName("TLBWR");) +MakeDisF(disTLBP, dName("TLBP");) +MakeDisF(disERET, dName("ERET");) +MakeDisF(disEI, dName("EI");) +MakeDisF(disDI, dName("DI");) + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +MakeDisF(disMFC1, dName("MFC1"); dGPR64(_Rt_); dCP132(_Fs_);) +MakeDisF(disCFC1, dName("CFC1"); dGPR64(_Rt_); dCP1c32(_Fs_);) +MakeDisF(disMTC1, dName("MTC1"); dCP132(_Fs_); dGPR64(_Rt_);) +MakeDisF(disCTC1, dName("CTC1"); dCP1c32(_Fs_); dGPR64(_Rt_);) + +MakeDisF(disBC1F, dName("BC1F");) +MakeDisF(disBC1T, dName("BC1T");) +MakeDisF(disBC1FL, dName("BC1FL");) +MakeDisF(disBC1TL, dName("BC1TL");) + +MakeDisF(disADDs, dName("ADDs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBs, dName("SUBs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULs, dName("MULs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disDIVs, dName("DIVs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSQRTs, dName("SQRTs"); dCP132(_Fd_); dCP132(_Ft_);) +MakeDisF(disABSs, dName("ABSs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMOVs, dName("MOVs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disNEGs, dName("NEGs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disRSQRTs, dName("RSQRTs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disADDAs, dName("ADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBAs, dName("SUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULAs, dName("MULAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDs, dName("MADDs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBs, dName("MSUBs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDAs, dName("MADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBAs, dName("MSUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCVTWs, dName("CVTWs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMAXs, dName("MAXs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMINs, dName("MINs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCFs, dName("CFs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCEQs, dName("CEQs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLTs, dName("CLTs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLEs, dName("CLEs"); dCP132(_Fs_); dCP132(_Ft_);) + +MakeDisF(disCVTSw, dName("CVTSw"); dCP132(_Fd_); dCP132(_Fs_);) + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +MakeDisF(disLWC1, dName("LWC1"); dCP132(_Rt_); dOffset();) +MakeDisF(disSWC1, dName("SWC1"); dCP132(_Rt_); dOffset();) + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +MakeDisF(disMOVZ, dName("MOVZ"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disMOVN, dName("MOVN"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ + +MakeDisF(disMULT1, dName("MULT1");) +MakeDisF(disMULTU1, dName("MULTU1");) + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADDW, dName("PADDW");) +MakeDisF(disPADDH, dName("PADDH");) +MakeDisF(disPADDB, dName("PADDB");) + +MakeDisF(disPADDSW, dName("PADDSW");) +MakeDisF(disPADDSH, dName("PADDSH");) +MakeDisF(disPADDSB, dName("PADDSB");) + +MakeDisF(disPSUBW, dName("PSUBW");) +MakeDisF(disPSUBH, dName("PSUBH");) +MakeDisF(disPSUBB, dName("PSUBB");) + +MakeDisF(disPSUBSW, dName("PSUBSW");) +MakeDisF(disPSUBSH, dName("PSUBSH");) +MakeDisF(disPSUBSB, dName("PSUBSB");) + +MakeDisF(disPCGTW, dName("PCGTW");) +MakeDisF(disPCGTH, dName("PCGTH");) +MakeDisF(disPCGTB, dName("PCGTB");) + +MakeDisF(disPMAXW, dName("PMAXW");) +MakeDisF(disPMAXH, dName("PMAXH");) + +MakeDisF(disPEXTLW, dName("PEXTLW"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLH, dName("PEXTLH"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLB, dName("PEXTLB");) +MakeDisF(disPEXTS, dName("PEXTS");) + +MakeDisF(disPPACW, dName("PPACW");) +MakeDisF(disPPACH, dName("PPACH");) +MakeDisF(disPPACB, dName("PPACB");) +MakeDisF(disPPACS, dName("PPACS");) + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADSBH, dName("PADSBH");) + +MakeDisF(disPABSW, dName("PABSW");) +MakeDisF(disPABSH, dName("PABSH");) + +MakeDisF(disPCEQW, dName("PCEQW");) +MakeDisF(disPCEQH, dName("PCEQH");) +MakeDisF(disPCEQB, dName("PCEQB");) + +MakeDisF(disPMINW, dName("PMINW");) +MakeDisF(disPMINH, dName("PMINH");) + +MakeDisF(disPADDUW, dName("PADDUW");) +MakeDisF(disPADDUH, dName("PADDUH");) +MakeDisF(disPADDUB, dName("PADDUB");) + +MakeDisF(disPSUBUW, dName("PSUBUW");) +MakeDisF(disPSUBUH, dName("PSUBUH");) +MakeDisF(disPSUBUB, dName("PSUBUB");) + +MakeDisF(disPEXTUW, dName("PEXTUW"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUH, dName("PEXTUH"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUB, dName("PEXTUB");) + +MakeDisF(disQFSRV, dName("QFSRV");) + +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDW, dName("PMADDW");) +MakeDisF(disPMADDH, dName("PMADDH");) + +MakeDisF(disPSLLVW, dName("PSLLVW");) +MakeDisF(disPSRLVW, dName("PSRLVW");) + +MakeDisF(disPMFHI, dName("PMFHI");) +MakeDisF(disPMFLO, dName("PMFLO");) + +MakeDisF(disPINTH, dName("PINTH");) + +MakeDisF(disPMULTW, dName("PMULTW");) +MakeDisF(disPMULTH, dName("PMULTH");) + +MakeDisF(disPDIVW, dName("PDIVW");) +MakeDisF(disPDIVH, dName("PDIVH");) + +MakeDisF(disPCPYLD, dName("PCPYLD"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPAND, dName("PAND"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPXOR, dName("PXOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPMSUBW, dName("PMSUBW");) +MakeDisF(disPMSUBH, dName("PMSUBH");) + +MakeDisF(disPHMADH, dName("PHMADH");) +MakeDisF(disPHMSBH, dName("PHMSBH");) + +MakeDisF(disPEXEW, dName("PEXEW");) +MakeDisF(disPEXEH, dName("PEXEH");) + +MakeDisF(disPREVH, dName("PREVH");) + +MakeDisF(disPDIVBW, dName("PDIVBW");) + +MakeDisF(disPROT3W, dName("PROT3W");) + +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDUW, dName("PMADDUW");) + +MakeDisF(disPSRAVW, dName("PSRAVW");) + +MakeDisF(disPMTHI, dName("PMTHI");) +MakeDisF(disPMTLO, dName("PMTLO");) + +MakeDisF(disPINTEH, dName("PINTEH");) + +MakeDisF(disPMULTUW, dName("PMULTUW");) +MakeDisF(disPDIVUW, dName("PDIVUW");) + +MakeDisF(disPCPYUD, dName("PCPYUD"); dGPR128(_Rd_); dGPR128(_Rt_); dGPR128(_Rs_);) + +MakeDisF(disPOR, dName("POR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPNOR, dName("PNOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPEXCH, dName("PEXCH");) +MakeDisF(disPEXCW, dName("PEXCW");) + +MakeDisF(disPCPYH, dName("PCPYH"); dGPR128(_Rd_); dGPR128(_Rt_);) + +/********************************************************* +* COP2 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X code>>24 +#define _Y code>>23 +#define _Z code>>22 +#define _W code>>21 + +MakeDisF(disLQC2, dName("LQC2"); dCP2128f(_Rt_); dOfB();) +MakeDisF(disSQC2, dName("SQC2"); dCP2128f(_Rt_); dOfB();) + +MakeDisF(disQMFC2, dName("QMFC2");) +MakeDisF(disQMTC2, dName("QMTC2");) +MakeDisF(disCFC2, dName("CFC2"); dGPR32(_Rt_); dCP232i(_Fs_);) +MakeDisF(disCTC2, dName("CTC2"); dCP232i(_Fs_); dGPR32(_Rt_);) + +MakeDisF(disBC2F, dName("BC2F");) +MakeDisF(disBC2T, dName("BC2T");) +MakeDisF(disBC2FL, dName("BC2FL");) +MakeDisF(disBC2TL, dName("BC2TL");) + +// SPEC1 +MakeDisF(disVADD, dName("VADD");) +MakeDisF(disVADDx, dName("VADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDy, dName("VADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDz, dName("VADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDw, dName("VADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDq, dName("VADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) +MakeDisF(disVADDi, dName("VADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) +MakeDisF(disVSUB, dName("VSUB");) +MakeDisF(disVSUBx, dName("VSUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBy, dName("VSUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBz, dName("VSUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBw, dName("VSUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBq, dName("VSUBq");) +MakeDisF(disVSUBi, dName("VSUBi");) +MakeDisF(disVMADD, dName("VMADD");) +MakeDisF(disVMADDx, dName("VMADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDy, dName("VMADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDz, dName("VMADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDw, dName("VMADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDq, dName("VMADDq");) +MakeDisF(disVMADDi, dName("VMADDi");) +MakeDisF(disVMSUB, dName("VMSUB");) +MakeDisF(disVMSUBx, dName("VMSUBx");) +MakeDisF(disVMSUBy, dName("VMSUBy");) +MakeDisF(disVMSUBz, dName("VMSUBz");) +MakeDisF(disVMSUBw, dName("VMSUBw");) +MakeDisF(disVMSUBq, dName("VMSUBq");) +MakeDisF(disVMSUBi, dName("VMSUBi");) +MakeDisF(disVMAX, dName("VMAX");) +MakeDisF(disVMAXx, dName("VMAXx");) +MakeDisF(disVMAXy, dName("VMAXy");) +MakeDisF(disVMAXz, dName("VMAXz");) +MakeDisF(disVMAXw, dName("VMAXw");) +MakeDisF(disVMAXi, dName("VMAXi");) +MakeDisF(disVMINI, dName("VMINI");) +MakeDisF(disVMINIx, dName("VMINIx");) +MakeDisF(disVMINIy, dName("VMINIy");) +MakeDisF(disVMINIz, dName("VMINIz");) +MakeDisF(disVMINIw, dName("VMINIw");) +MakeDisF(disVMINIi, dName("VMINIi");) +MakeDisF(disVMUL, dName("VMUL");) +MakeDisF(disVMULx, dName("VMULx");) +MakeDisF(disVMULy, dName("VMULy");) +MakeDisF(disVMULz, dName("VMULz");) +MakeDisF(disVMULw, dName("VMULw");) +MakeDisF(disVMULq, dName("VMULq");) +MakeDisF(disVMULi, dName("VMULi");) +MakeDisF(disVIADD, dName("VIADD");) +MakeDisF(disVIADDI, dName("VIADDI");) +MakeDisF(disVISUB, dName("VISUB");) +MakeDisF(disVIAND, dName("VIAND");) +MakeDisF(disVIOR, dName("VIOR");) +MakeDisF(disVOPMSUB, dName("VOPMSUB");) +MakeDisF(disVCALLMS, dName("VCALLMS");) +MakeDisF(disVCALLMSR, dName("VCALLMSR");) + +// SPEC2 +MakeDisF(disVADDA, dName("VADDA");) +MakeDisF(disVADDAx, dName("VADDAx");) +MakeDisF(disVADDAy, dName("VADDAy");) +MakeDisF(disVADDAz, dName("VADDAz");) +MakeDisF(disVADDAw, dName("VADDAw");) +MakeDisF(disVADDAq, dName("VADDAq");) +MakeDisF(disVADDAi, dName("VADDAi");) +MakeDisF(disVMADDA, dName("VMADDA");) +MakeDisF(disVMADDAx, dName("VMADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDAy, dName("VMADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDAz, dName("VMADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDAw, dName("VMADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDAq, dName("VMADDAq");) +MakeDisF(disVMADDAi, dName("VMADDAi");) +MakeDisF(disVSUBAx, dName("VSUBAx");) +MakeDisF(disVSUBAy, dName("VSUBAy");) +MakeDisF(disVSUBAz, dName("VSUBAz");) +MakeDisF(disVSUBAw, dName("VSUBAw");) +MakeDisF(disVMSUBAx, dName("VMSUBAx");) +MakeDisF(disVMSUBAy, dName("VMSUBAy");) +MakeDisF(disVMSUBAz, dName("VMSUBAz");) +MakeDisF(disVMSUBAw, dName("VMSUBAw");) +MakeDisF(disVITOF0, dName("VITOF0");) +MakeDisF(disVITOF4, dName("VITOF4");) +MakeDisF(disVITOF12, dName("VITOF12");) +MakeDisF(disVITOF15, dName("VITOF15");) +MakeDisF(disVFTOI0, dName("VFTOI0");) +MakeDisF(disVFTOI4, dName("VFTOI4");) +MakeDisF(disVFTOI12, dName("VFTOI12");) +MakeDisF(disVFTOI15, dName("VFTOI15");) +MakeDisF(disVMULA, dName("VMULA");) +MakeDisF(disVMULAx, dName("VMULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMULAy, dName("VMULAy");) +MakeDisF(disVMULAz, dName("VMULAz");) +MakeDisF(disVMULAw, dName("VMULAw");) +MakeDisF(disVMOVE, dName("VMOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_);) +MakeDisF(disVMR32, dName("VMR32");) +MakeDisF(disVDIV, dName("VDIV");) +MakeDisF(disVSQRT, dName("VSQRT"); dCP232f(_Ft_, _Ftf_);) +MakeDisF(disVRSQRT, dName("VRSQRT");) +MakeDisF(disVRNEXT, dName("VRNEXT");) +MakeDisF(disVRGET, dName("VRGET");) +MakeDisF(disVRINIT, dName("VRINIT");) +MakeDisF(disVRXOR, dName("VRXOR");) +MakeDisF(disVWAITQ, dName("VWAITQ");) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +MakeDisF(disSYNC, dName("SYNC");) +MakeDisF(disBREAK, dName("BREAK");) +MakeDisF(disSYSCALL, dName("SYSCALL"); dCode();) +MakeDisF(disCACHE, sprintf(ostr, "%s %-7s, %x,", ostr, "CACHE", _Rt_); dOfB();) +MakeDisF(disPREF, dName("PREF");) + +MakeDisF(disMFSA, dName("MFSA"); dGPR64(_Rd_); dSaR();) +MakeDisF(disMTSA, dName("MTSA"); dGPR64(_Rs_); dSaR();) + +MakeDisF(disMTSAB, dName("MTSAB");dGPR64(_Rs_); dImm();) +MakeDisF(disMTSAH, dName("MTSAH");dGPR64(_Rs_); dImm();) + +MakeDisF(disTGE, dName("TGE"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTGEU, dName("TGEU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLT, dName("TLT"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLTU, dName("TLTU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTEQ, dName("TEQ"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTNE, dName("TNE"); dGPR64(_Rs_); dGPR64(_Rt_);) + +MakeDisF(disTGEI, dName("TGEI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTGEIU, dName("TGEIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTI, dName("TLTI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTIU, dName("TLTIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTEQI, dName("TEQI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTNEI, dName("TNEI"); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + +TdisR5900F disR5900_MMI0[] = { // Subset of disMMI0 + disPADDW, disPSUBW, disPCGTW, disPMAXW, + disPADDH, disPSUBH, disPCGTH, disPMAXH, + disPADDB, disPSUBB, disPCGTB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDSW, disPSUBSW, disPEXTLW, disPPACW, + disPADDSH, disPSUBSH, disPEXTLH, disPPACH, + disPADDSB, disPSUBSB, disPEXTLB, disPPACB, + disNULL, disNULL, disPEXTS, disPPACS}; + +MakeDisF(disMMI0, disR5900_MMI0[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI1[] = { // Subset of disMMI1 + disNULL, disPABSW, disPCEQW, disPMINW, + disPADSBH, disPABSH, disPCEQH, disPMINH, + disNULL, disNULL, disPCEQB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDUW, disPSUBUW, disPEXTUW, disNULL, + disPADDUH, disPSUBUH, disPEXTUH, disNULL, + disPADDUB, disPSUBUB, disPEXTUB, disQFSRV, + disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI1, disR5900_MMI1[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI2[] = { // Subset of disMMI2 + disPMADDW, disNULL, disPSLLVW, disPSRLVW, + disPMSUBW, disNULL, disNULL, disNULL, + disPMFHI, disPMFLO, disPINTH, disNULL, + disPMULTW, disPDIVW, disPCPYLD, disNULL, + disPMADDH, disPHMADH, disPAND, disPXOR, + disPMSUBH, disPHMSBH, disNULL, disNULL, + disNULL, disNULL, disPEXEH, disPREVH, + disPMULTH, disPDIVBW, disPEXEW, disPROT3W}; + +MakeDisF(disMMI2, disR5900_MMI2[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI3[] = { // Subset of disMMI3 + disPMADDUW, disNULL, disNULL, disPSRAVW, + disNULL, disNULL, disNULL, disNULL, + disPMTHI, disPMTLO, disPINTEH, disNULL, + disPMULTUW, disPDIVUW, disPCPYUD, disNULL, + disNULL, disNULL, disPOR, disPNOR, + disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disPEXCH, disPCPYH, + disNULL, disNULL, disPEXCW, disNULL}; + +MakeDisF(disMMI3, disR5900_MMI3[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI[] = { // Subset of disMMI + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI0, disMMI2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMULT1, disMULTU1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI1, disMMI3, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI, disR5900_MMI[_Funct_] DisFInterfaceN) + + +TdisR5900F disR5900_COP0_BC0[] = { //subset of disCOP0 BC + disBC0F, disBC0T, disBC0FL, disBC0TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP0_BC0, disR5900_COP0_BC0[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP0_Func[] = { //subset of disCOP0 Function + disNULL, disTLBR, disTLBWI, disNULL, disNULL, disNULL, disTLBWR, disNULL, + disTLBP, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disERET, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disEI , disDI , disNULL , disNULL, disNULL, disNULL, disNULL , disNULL +}; +MakeDisF(disCOP0_Func, disR5900_COP0_Func[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disNULL, disNULL, disMTC0, disNULL, disNULL, disNULL, + disCOP0_BC0, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP0_Func, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR5900_COP0[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_S[] = { //subset of disCOP1 S + disADDs, disSUBs, disMULs, disDIVs, disSQRTs, disABSs, disMOVs, disNEGs, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disRSQRTs, disNULL, + disADDAs, disSUBAs, disMULAs, disNULL, disMADDs, disMSUBs, disMADDAs, disMSUBAs, + disNULL, disNULL, disNULL, disNULL, disCVTWs, disNULL, disNULL, disNULL, + disMINs, disMAXs, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCFs, disNULL, disCEQs, disNULL, disCLTs, disNULL, disCLEs, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_S, disR5900_COP1_S[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_W[] = { //subset of disCOP1 W + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCVTSw, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_W, disR5900_COP1_W[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_BC1[] = { //subset of disCOP1 BC + disBC1F, disBC1T, disBC1FL, disBC1TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_BC1, disR5900_COP1_BC1[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP1[] = { // Subset of disCOP1 + disMFC1, disNULL, disCFC1, disNULL, disMTC1, disNULL, disCTC1, disNULL, + disCOP1_BC1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP1_S, disNULL, disNULL, disNULL, disCOP1_W, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP1, disR5900_COP1[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC2[] = { //subset of disCOP2 SPEC2 + disVADDAx, disVADDAy, disVADDAz, disVADDAw, disVSUBAx, disVSUBAy, disVSUBAz, disVSUBAw, + disVMADDAx, disVMADDAy, disVMADDAz, disVMADDAw, disVMSUBAx, disVMSUBAy, disVMSUBAz, disVMSUBAw, + disVITOF0, disVITOF4, disVITOF12, disVITOF15, disVFTOI0, disVFTOI4, disVFTOI12, disVFTOI15, + disVMULAx, disVMULAy, disVMULAz, disVMULAw, disNULL, disNULL, disNULL, disNULL, + disVADDAq, disVMADDAq, disVADDAi, disVMADDAi, disNULL, disNULL, disNULL, disNULL, + disVADDA, disVMADDA, disVMULA, disNULL, disNULL, disNULL, disNULL, disNULL, + disVMOVE, disVMR32, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disVDIV, disVSQRT, disVRSQRT, disVWAITQ, disNULL, disNULL, disNULL, disNULL, + disVRNEXT, disVRGET, disVRINIT, disVRXOR, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_SPEC2, disR5900_COP2_SPEC2[(code & 0x3) | ((code >> 4) & 0x7c)] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC1[] = { //subset of disCOP2 SPEC1 + disVADDx, disVADDy, disVADDz, disVADDw, disVSUBx, disVSUBy, disVSUBz, disVSUBw, + disVMADDx, disVMADDy, disVMADDz, disVMADDw, disVMSUBx, disVMSUBy, disVMSUBz, disVMSUBw, + disVMAXx, disVMAXy, disVMAXz, disVMAXw, disVMINIx, disVMINIy, disVMINIz, disVMINIw, + disVMULx, disVMULy, disVMULz, disVMULw, disVMULq, disVMAXi, disVMULi, disVMINIi, + disVADDq, disVMADDq, disVADDi, disVMADDi, disVSUBq, disVMSUBq, disVSUBi, disVMSUBi, + disVADD, disVMADD, disVMUL, disVMAX, disVSUB, disVMSUB, disVOPMSUB, disVMINI, + disVIADD, disVISUB, disVIADDI, disNULL, disVIAND, disVIOR, disNULL, disNULL, + disVCALLMS, disVCALLMSR, disNULL, disNULL, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, +}; + +MakeDisF(disCOP2_SPEC1, disR5900_COP2_SPEC1[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_BC2[] = { //subset of disCOP2 BC + disBC2F, disBC2T, disBC2FL, disBC2TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_BC2, disR5900_COP2_BC2[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP2[] = { // Subset of disCOP2 + disNULL, disQMFC2, disCFC2, disNULL, disNULL, disQMTC2, disCTC2, disNULL, + disCOP2_BC2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1}; + +MakeDisF(disCOP2, disR5900_COP2[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_REGIMM[] = { // Subset of disREGIMM + disBLTZ, disBGEZ, disBLTZL, disBGEZL, disNULL, disNULL, disNULL, disNULL, + disTGEI, disTGEIU, disTLTI, disTLTIU, disTEQI, disNULL, disTNEI, disNULL, + disBLTZAL, disBGEZAL, disBLTZALL, disBGEZALL, disNULL, disNULL, disNULL, disNULL, + disMTSAB, disMTSAH , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disREGIMM, disR5900_REGIMM[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_SPECIAL[] = { + disSLL, disNULL, disSRL, disSRA, disSLLV, disNULL, disSRLV, disSRAV, + disJR, disJALR, disMOVZ, disMOVN, disSYSCALL, disBREAK,disNULL, disSYNC, + disMFHI, disMTHI, disMFLO, disMTLO, disDSLLV, disNULL, disDSRLV, disDSRAV, + disMULT, disMULTU,disDIV, disDIVU, disNULL, disNULL, disNULL, disNULL, + disADD, disADDU, disSUB, disSUBU, disAND, disOR, disXOR, disNOR, + disMFSA , disMTSA, disSLT, disSLTU, disDADD, disDADDU,disDSUB, disDSUBU, + disTGE, disTGEU, disTLT, disTLTU, disTEQ, disNULL, disTNE, disNULL, + disDSLL, disNULL, disDSRL, disDSRA, disDSLL32, disNULL, disDSRL32,disDSRA32 }; + +MakeDisF(disSPECIAL, disR5900_SPECIAL[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900[] = { + disSPECIAL, disREGIMM, disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI, disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disCOP1 , disCOP2, disNULL , disBEQL, disBNEL, disBLEZL, disBGTZL, + disDADDI , disDADDIU, disLDL , disLDR , disMMI , disNULL, disLQ , disSQ , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disLWU , + disSB , disSH , disSWL , disSW , disSDL , disSDR , disSWR , disCACHE, + disNULL , disLWC1 , disNULL, disPREF , disNULL, disNULL, disLQC2 , disLD , + disNULL , disSWC1 , disNULL, disNULL , disNULL, disNULL, disSQC2 , disSD }; + +MakeDisF(disR5900F, disR5900[code >> 26] DisFInterfaceN) + diff --git a/branches/pcsx2_0.9.2/DebugTools/DisR5900asm.c b/branches/pcsx2_0.9.2/DebugTools/DisR5900asm.c new file mode 100644 index 0000000..e3261d4 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisR5900asm.c @@ -0,0 +1,1679 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PS2Etypes.h" +#include "Debug.h" +#include "R5900.h" +#include "DisASM.h" + +unsigned long opcode_addr; + +/* +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +/// ******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) +*/ +/*************************CPUS REGISTERS**************************/ +char *GPR_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +//floating point cop1 Floating point reg +char *COP1_REG_FP[32] ={ + "f00","f01","f02","f03","f04","f05","f06","f07", + "f08","f09","f10","f11","f12","f13","f14","f15", + "f16","f17","f18","f19","f20","f21","f21","f23", + "f24","f25","f26","f27","f28","f29","f30","f31" +}; +//floating point cop1 control registers +char *COP1_REG_FCR[32] ={ + "fcr00","fcr01","fcr02","fcr03","fcr04","fcr05","fcr06","fcr07", + "fcr08","fcr09","fcr10","fcr11","fcr12","fcr13","fcr14","fcr15", + "fcr16","fcr17","fcr18","fcr19","fcr20","fcr21","fcr21","fcr23", + "fcr24","fcr25","fcr26","fcr27","fcr28","fcr29","fcr30","fcr31" +}; + +//floating point cop2 reg +char *COP2_REG_FP[32] ={ + "vf00","vf01","vf02","vf03","vf04","vf05","vf06","vf07", + "vf08","vf09","vf10","vf11","vf12","vf13","vf14","vf15", + "vf16","vf17","vf18","vf19","vf20","vf21","vf21","vf23", + "vf24","vf25","vf26","vf27","vf28","vf29","vf30","vf31" +}; +//cop2 control registers + +char *COP2_REG_CTL[32] ={ + "vi00","vi01","vi02","vi03","vi04","vi05","vi06","vi07", + "vi08","vi09","vi10","vi11","vi12","vi13","vi14","vi15", + "Status","MACflag","ClipFlag","c2c19","R","I","Q","c2c23", + "c2c24","c2c25","TPC","CMSAR0","FBRST","VPU-STAT","c2c30","CMSAR1" +}; + + + + + +//**************************************************************** +void P_SpecialOpcode(char *buf); +void P_REGIMMOpcode(char *buf); +void P_UnknownOpcode(char *buf); +void P_COP0(char *buf); +void P_COP1(char *buf); +void P_COP2(char *buf); +void P_MMI_Unknown(char *buf); +void P_MMI(char *buf); +void P_MMI0(char *buf); +void P_MMI1(char *buf); +void P_MMI2(char *buf); +void P_MMI3(char *buf); +void P_COP0_Unknown(char *buf); +void P_COP0_BC0(char *buf); +void P_COP0_Func(char *buf); +void P_COP1_BC1(char *buf); +void P_COP1_S(char *buf); +void P_COP1_W(char *buf); +void P_COP1_Unknown(char *buf); +void P_COP2_BC2(char *buf); +void P_COP2_SPECIAL(char *buf); +void P_COP2_Unknown(char *buf); +void P_COP2_SPECIAL2(char *buf); + +// **********************Standard Opcodes************************** +void P_J(char *buf); +void P_JAL(char *buf); +void P_BEQ(char *buf); +void P_BNE(char *buf); +void P_BLEZ(char *buf); +void P_BGTZ(char *buf); +void P_ADDI(char *buf); +void P_ADDIU(char *buf); +void P_SLTI(char *buf); +void P_SLTIU(char *buf); +void P_ANDI(char *buf); +void P_ORI(char *buf); +void P_XORI(char *buf); +void P_LUI(char *buf); +void P_BEQL(char *buf); +void P_BNEL(char *buf); +void P_BLEZL(char *buf); +void P_BGTZL(char *buf); +void P_DADDI(char *buf); +void P_DADDIU(char *buf); +void P_LDL(char *buf); +void P_LDR(char *buf); +void P_LB(char *buf); +void P_LH(char *buf); +void P_LWL(char *buf); +void P_LW(char *buf); +void P_LBU(char *buf); +void P_LHU(char *buf); +void P_LWR(char *buf); +void P_LWU(char *buf); +void P_SB(char *buf); +void P_SH(char *buf); +void P_SWL(char *buf); +void P_SW(char *buf); +void P_SDL(char *buf); +void P_SDR(char *buf); +void P_SWR(char *buf); +void P_CACHE(char *buf); +void P_LWC1(char *buf); +void P_PREF(char *buf); +void P_LQC2(char *buf); +void P_LD(char *buf); +void P_SQC2(char *buf); +void P_SD(char *buf); +void P_LQ(char *buf); +void P_SQ(char *buf); +void P_SWC1(char *buf); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void P_SLL(char *buf); +void P_SRL(char *buf); +void P_SRA(char *buf); +void P_SLLV(char *buf); +void P_SRLV(char *buf); +void P_SRAV(char *buf); +void P_JR(char *buf); +void P_JALR(char *buf); +void P_SYSCALL(char *buf); +void P_BREAK(char *buf); +void P_SYNC(char *buf); +void P_MFHI(char *buf); +void P_MTHI(char *buf); +void P_MFLO(char *buf); +void P_MTLO(char *buf); +void P_DSLLV(char *buf); +void P_DSRLV(char *buf); +void P_DSRAV(char *buf); +void P_MULT(char *buf); +void P_MULTU(char *buf); +void P_DIV(char *buf); +void P_DIVU(char *buf); +void P_ADD(char *buf); +void P_ADDU(char *buf); +void P_SUB(char *buf); +void P_SUBU(char *buf); +void P_AND(char *buf); +void P_OR(char *buf); +void P_XOR(char *buf); +void P_NOR(char *buf); +void P_SLT(char *buf); +void P_SLTU(char *buf); +void P_DADD(char *buf); +void P_DADDU(char *buf); +void P_DSUB(char *buf); +void P_DSUBU(char *buf); +void P_TGE(char *buf); +void P_TGEU(char *buf); +void P_TLT(char *buf); +void P_TLTU(char *buf); +void P_TEQ(char *buf); +void P_TNE(char *buf); +void P_DSLL(char *buf); +void P_DSRL(char *buf); +void P_DSRA(char *buf); +void P_DSLL32(char *buf); +void P_DSRL32(char *buf); +void P_DSRA32(char *buf); +void P_MOVZ(char *buf); +void P_MOVN(char *buf); +void P_MFSA(char *buf); +void P_MTSA(char *buf); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void P_BLTZ(char *buf); +void P_BGEZ(char *buf); +void P_BLTZL(char *buf); +void P_BGEZL(char *buf); +void P_TGEI(char *buf); +void P_TGEIU(char *buf); +void P_TLTI(char *buf); +void P_TLTIU(char *buf); +void P_TEQI(char *buf); +void P_TNEI(char *buf); +void P_BLTZAL(char *buf); +void P_BGEZAL(char *buf); +void P_BLTZALL(char *buf); +void P_BGEZALL(char *buf); +void P_MTSAB(char *buf); +void P_MTSAH(char *buf); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void P_MADD(char *buf); +void P_MADDU(char *buf); +void P_PLZCW(char *buf); +void P_MADD1(char *buf); +void P_MADDU1(char *buf); +void P_MFHI1(char *buf); +void P_MTHI1(char *buf); +void P_MFLO1(char *buf); +void P_MTLO1(char *buf); +void P_MULT1(char *buf); +void P_MULTU1(char *buf); +void P_DIV1(char *buf); +void P_DIVU1(char *buf); +void P_PMFHL(char *buf); +void P_PMTHL(char *buf); +void P_PSLLH(char *buf); +void P_PSRLH(char *buf); +void P_PSRAH(char *buf); +void P_PSLLW(char *buf); +void P_PSRLW(char *buf); +void P_PSRAW(char *buf); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf); +void P_PSUBW(char *buf); +void P_PCGTW(char *buf); +void P_PMAXW(char *buf); +void P_PADDH(char *buf); +void P_PSUBH(char *buf); +void P_PCGTH(char *buf); +void P_PMAXH(char *buf); +void P_PADDB(char *buf); +void P_PSUBB(char *buf); +void P_PCGTB(char *buf); +void P_PADDSW(char *buf); +void P_PSUBSW(char *buf); +void P_PEXTLW(char *buf); +void P_PPACW(char *buf); +void P_PADDSH(char *buf); +void P_PSUBSH(char *buf); +void P_PEXTLH(char *buf); +void P_PPACH(char *buf); +void P_PADDSB(char *buf); +void P_PSUBSB(char *buf); +void P_PEXTLB(char *buf); +void P_PPACB(char *buf); +void P_PEXT5(char *buf); +void P_PPAC5(char *buf); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf); +void P_PCEQW(char *buf); +void P_PMINW(char *buf); +void P_PADSBH(char *buf); +void P_PABSH(char *buf); +void P_PCEQH(char *buf); +void P_PMINH(char *buf); +void P_PCEQB(char *buf); +void P_PADDUW(char *buf); +void P_PSUBUW(char *buf); +void P_PEXTUW(char *buf); +void P_PADDUH(char *buf); +void P_PSUBUH(char *buf); +void P_PEXTUH(char *buf); +void P_PADDUB(char *buf); +void P_PSUBUB(char *buf); +void P_PEXTUB(char *buf); +void P_QFSRV(char *buf); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf); +void P_PSLLVW(char *buf); +void P_PSRLVW(char *buf); +void P_PMSUBW(char *buf); +void P_PMFHI(char *buf); +void P_PMFLO(char *buf); +void P_PINTH(char *buf); +void P_PMULTW(char *buf); +void P_PDIVW(char *buf); +void P_PCPYLD(char *buf); +void P_PMADDH(char *buf); +void P_PHMADH(char *buf); +void P_PAND(char *buf); +void P_PXOR(char *buf); +void P_PMSUBH(char *buf); +void P_PHMSBH(char *buf); +void P_PEXEH(char *buf); +void P_PREVH(char *buf); +void P_PMULTH(char *buf); +void P_PDIVBW(char *buf); +void P_PEXEW(char *buf); +void P_PROT3W(char *buf); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf); +void P_PSRAVW(char *buf); +void P_PMTHI(char *buf); +void P_PMTLO(char *buf); +void P_PINTEH(char *buf); +void P_PMULTUW(char *buf); +void P_PDIVUW(char *buf); +void P_PCPYUD(char *buf); +void P_POR(char *buf); +void P_PNOR(char *buf); +void P_PEXCH(char *buf); +void P_PCPYH(char *buf); +void P_PEXCW(char *buf); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf); +void P_MTC0(char *buf); +void P_BC0F(char *buf); +void P_BC0T(char *buf); +void P_BC0FL(char *buf); +void P_BC0TL(char *buf); +void P_TLBR(char *buf); +void P_TLBWI(char *buf); +void P_TLBWR(char *buf); +void P_TLBP(char *buf); +void P_ERET(char *buf); +void P_DI(char *buf); +void P_EI(char *buf); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf); +void P_CFC1(char *buf); +void P_MTC1(char *buf); +void P_CTC1(char *buf); +void P_BC1F(char *buf); +void P_BC1T(char *buf); +void P_BC1FL(char *buf); +void P_BC1TL(char *buf); +void P_ADD_S(char *buf); +void P_SUB_S(char *buf); +void P_MUL_S(char *buf); +void P_DIV_S(char *buf); +void P_SQRT_S(char *buf); +void P_ABS_S(char *buf); +void P_MOV_S(char *buf); +void P_NEG_S(char *buf); +void P_RSQRT_S(char *buf); +void P_ADDA_S(char *buf); +void P_SUBA_S(char *buf); +void P_MULA_S(char *buf); +void P_MADD_S(char *buf); +void P_MSUB_S(char *buf); +void P_MADDA_S(char *buf); +void P_MSUBA_S(char *buf); +void P_CVT_W(char *buf); +void P_MAX_S(char *buf); +void P_MIN_S(char *buf); +void P_C_F(char *buf); +void P_C_EQ(char *buf); +void P_C_LT(char *buf); +void P_C_LE(char *buf); + void P_CVT_S(char *buf); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf); +void P_CFC2(char *buf); +void P_QMTC2(char *buf); +void P_CTC2(char *buf); +void P_BC2F(char *buf); +void P_BC2T(char *buf); +void P_BC2FL(char *buf); +void P_BC2TL(char *buf); +//*****************SPECIAL 1 VUO TABLE******************************* +void P_VADDx(char *buf); +void P_VADDy(char *buf); +void P_VADDz(char *buf); +void P_VADDw(char *buf); +void P_VSUBx(char *buf); +void P_VSUBy(char *buf); +void P_VSUBz(char *buf); +void P_VSUBw(char *buf); +void P_VMADDx(char *buf); +void P_VMADDy(char *buf); +void P_VMADDz(char *buf); +void P_VMADDw(char *buf); +void P_VMSUBx(char *buf); +void P_VMSUBy(char *buf); +void P_VMSUBz(char *buf); +void P_VMSUBw(char *buf); +void P_VMAXx(char *buf); +void P_VMAXy(char *buf); +void P_VMAXz(char *buf); +void P_VMAXw(char *buf); +void P_VMINIx(char *buf); +void P_VMINIy(char *buf); +void P_VMINIz(char *buf); +void P_VMINIw(char *buf); +void P_VMULx(char *buf); +void P_VMULy(char *buf); +void P_VMULz(char *buf); +void P_VMULw(char *buf); +void P_VMULq(char *buf); +void P_VMAXi(char *buf); +void P_VMULi(char *buf); +void P_VMINIi(char *buf); +void P_VADDq(char *buf); +void P_VMADDq(char *buf); +void P_VADDi(char *buf); +void P_VMADDi(char *buf); +void P_VSUBq(char *buf); +void P_VMSUBq(char *buf); +void P_VSUbi(char *buf); +void P_VMSUBi(char *buf); +void P_VADD(char *buf); +void P_VMADD(char *buf); +void P_VMUL(char *buf); +void P_VMAX(char *buf); +void P_VSUB(char *buf); +void P_VMSUB(char *buf); +void P_VOPMSUB(char *buf); +void P_VMINI(char *buf); +void P_VIADD(char *buf); +void P_VISUB(char *buf); +void P_VIADDI(char *buf); +void P_VIAND(char *buf); +void P_VIOR(char *buf); +void P_VCALLMS(char *buf); +void P_CALLMSR(char *buf); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf); +void P_VADDAy(char *buf); +void P_VADDAz(char *buf); +void P_VADDAw(char *buf); +void P_VSUBAx(char *buf); +void P_VSUBAy(char *buf); +void P_VSUBAz(char *buf); +void P_VSUBAw(char *buf); +void P_VMADDAx(char *buf); +void P_VMADDAy(char *buf); +void P_VMADDAz(char *buf); +void P_VMADDAw(char *buf); +void P_VMSUBAx(char *buf); +void P_VMSUBAy(char *buf); +void P_VMSUBAz(char *buf); +void P_VMSUBAw(char *buf); +void P_VITOF0(char *buf); +void P_VITOF4(char *buf); +void P_VITOF12(char *buf); +void P_VITOF15(char *buf); +void P_VFTOI0(char *buf); +void P_VFTOI4(char *buf); +void P_VFTOI12(char *buf); +void P_VFTOI15(char *buf); +void P_VMULAx(char *buf); +void P_VMULAy(char *buf); +void P_VMULAz(char *buf); +void P_VMULAw(char *buf); +void P_VMULAq(char *buf); +void P_VABS(char *buf); +void P_VMULAi(char *buf); +void P_VCLIPw(char *buf); +void P_VADDAq(char *buf); +void P_VMADDAq(char *buf); +void P_VADDAi(char *buf); +void P_VMADDAi(char *buf); +void P_VSUBAq(char *buf); +void P_VMSUBAq(char *buf); +void P_VSUBAi(char *buf); +void P_VMSUBAi(char *buf); +void P_VADDA(char *buf); +void P_VMADDA(char *buf); +void P_VMULA(char *buf); +void P_VSUBA(char *buf); +void P_VMSUBA(char *buf); +void P_VOPMULA(char *buf); +void P_VNOP(char *buf); +void P_VMONE(char *buf); +void P_VMR32(char *buf); +void P_VLQI(char *buf); +void P_VSQI(char *buf); +void P_VLQD(char *buf); +void P_VSQD(char *buf); +void P_VDIV(char *buf); +void P_VSQRT(char *buf); +void P_VRSQRT(char *buf); +void P_VWAITQ(char *buf); +void P_VMTIR(char *buf); +void P_VMFIR(char *buf); +void P_VILWR(char *buf); +void P_VISWR(char *buf); +void P_VRNEXT(char *buf); +void P_VRGET(char *buf); +void P_VRINIT(char *buf); +void P_VRXOR(char *buf); +//************************************END OF SPECIAL2 VUO TABLE**************************** + + +/* + CPU: Instructions encoded by opcode field. + 31---------26---------------------------------------------------0 + | opcode | | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | +001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | +010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | +011 | DADDI |DADDIU | LDL | LDR | *6 | --- | LQ | SQ | +100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | +101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | +110 | --- | LWC1 | --- | PREF | --- | --- | LQC2 | LD | +111 | --- | SWC1 | --- | --- | --- | --- | SQC2 | SD | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = SPECIAL, see SPECIAL list *2 = REGIMM, see REGIMM list + *3 = COP0 *4 = COP1 + *5 = COP2 *6 = MMI table +*/ +void (*OpcodePrintTable[64])(char *buf) = { + P_SpecialOpcode, P_REGIMMOpcode, P_J, P_JAL, P_BEQ, P_BNE, P_BLEZ, P_BGTZ, + P_ADDI, P_ADDIU, P_SLTI, P_SLTIU, P_ANDI, P_ORI, P_XORI, P_LUI, + P_COP0, P_COP1, P_COP2, P_UnknownOpcode, P_BEQL, P_BNEL, P_BLEZL, P_BGTZL, + P_DADDI, P_DADDIU, P_LDL, P_LDR, P_MMI, P_UnknownOpcode, P_LQ, P_SQ, + P_LB, P_LH, P_LWL, P_LW, P_LBU, P_LHU, P_LWR, P_LWU, + P_SB, P_SH, P_SWL, P_SW, P_SDL, P_SDR, P_SWR, P_CACHE, + P_UnknownOpcode, P_LWC1, P_UnknownOpcode, P_PREF, P_UnknownOpcode,P_UnknownOpcode, P_LQC2, P_LD, + P_UnknownOpcode, P_SWC1, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode,P_UnknownOpcode, P_SQC2, P_SD +}; + + + /* + SPECIAL: Instr. encoded by function field when opcode field = SPECIAL + 31---------26------------------------------------------5--------0 + | = SPECIAL | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | +001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | +010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | +011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | +100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | +101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | +110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | +111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ + +void (*SpecialPrintTable[64])(char *buf) = { + P_SLL, P_UnknownOpcode, P_SRL, P_SRA, P_SLLV, P_UnknownOpcode, P_SRLV, P_SRAV, + P_JR, P_JALR, P_MOVZ, P_MOVN, P_SYSCALL, P_BREAK, P_UnknownOpcode, P_SYNC, + P_MFHI, P_MTHI, P_MFLO, P_MTLO, P_DSLLV, P_UnknownOpcode, P_DSRLV, P_DSRAV, + P_MULT, P_MULTU, P_DIV, P_DIVU, P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode, + P_ADD, P_ADDU, P_SUB, P_SUBU, P_AND, P_OR, P_XOR, P_NOR, + P_MFSA , P_MTSA , P_SLT, P_SLTU, P_DADD, P_DADDU, P_DSUB, P_DSUBU, + P_TGE, P_TGEU, P_TLT, P_TLTU, P_TEQ, P_UnknownOpcode, P_TNE, P_UnknownOpcode, + P_DSLL, P_UnknownOpcode, P_DSRL, P_DSRA, P_DSLL32, P_UnknownOpcode, P_DSRL32, P_DSRA32 +}; + +/* + REGIMM: Instructions encoded by the rt field when opcode field = REGIMM. + 31---------26----------20-------16------------------------------0 + | = REGIMM | | rt | | + ------6---------------------5------------------------------------ + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | + 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | + 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | + 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*REGIMMPrintTable[32])(char *buf) = { + P_BLTZ, P_BGEZ, P_BLTZL, P_BGEZL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_TGEI, P_TGEIU, P_TLTI, P_TLTIU, P_TEQI, P_UnknownOpcode, P_TNEI, P_UnknownOpcode, + P_BLTZAL, P_BGEZAL, P_BLTZALL, P_BGEZALL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_MTSAB, P_MTSAH , P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, +}; +/* + MMI: Instr. encoded by function field when opcode field = MMI + 31---------26------------------------------------------5--------0 + | = MMI | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | MADD | MADDU | --- | --- | PLZCW | --- | --- | --- | +001 | *1 | *2 | --- | --- | --- | --- | --- | --- | +010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | --- | --- | --- | --- | +011 | MULT1 | MULTU1| DIV1 | DIVU1 | --- | --- | --- | --- | +100 | MADD1 | MADDU1| --- | --- | --- | --- | --- | --- | +101 | *3 | *4 | --- | --- | --- | --- | --- | --- | +110 | PMFHL | PMTHL | --- | --- | PSLLH | --- | PSRLH | PSRAH | +111 | --- | --- | --- | --- | PSLLW | --- | PSRLW | PSRAW | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + + *1 = see MMI0 table *2 = see MMI2 Table + *3 = see MMI1 table *4 = see MMI3 Table +*/ +void (*MMIPrintTable[64])(char *buf) = { + P_MADD, P_MADDU, P_MMI_Unknown, P_MMI_Unknown, P_PLZCW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI0, P_MMI2, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MFHI1, P_MTHI1, P_MFLO1, P_MTLO1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MULT1, P_MULTU1, P_DIV1, P_DIVU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MADD1, P_MADDU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI1 , P_MMI3, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHL, P_PMTHL, P_MMI_Unknown, P_MMI_Unknown, P_PSLLH, P_MMI_Unknown, P_PSRLH, P_PSRAH, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_PSLLW, P_MMI_Unknown, P_PSRLW, P_PSRAW, +}; +/* + MMI0: Instr. encoded by function field when opcode field = MMI & MMI0 + + 31---------26------------------------------10--------6-5--------0 + | | |function | MMI0 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PADDW | PSUBW | PCGTW | PMAXW | +001 |PADDH | PSUBH | PCGTH | PMAXH | +010 |PADDB | PSUBB | PCGTB | --- | +011 | --- | --- | --- | --- | +100 |PADDSW |PSUBSW |PEXTLW | PPACW | +101 |PADDSH |PSUBSH |PEXTLH | PPACH | +110 |PADDSB |PSUBSB |PEXTLB | PPACB | +111 | --- | --- | PEXT5 | PPAC5 | + hi |-------|-------|-------|-------| +*/ +void (*MMI0PrintTable[32])(char *buf) = { + P_PADDW, P_PSUBW, P_PCGTW, P_PMAXW, + P_PADDH, P_PSUBH, P_PCGTH, P_PMAXH, + P_PADDB, P_PSUBB, P_PCGTB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDSW, P_PSUBSW, P_PEXTLW, P_PPACW, + P_PADDSH, P_PSUBSH, P_PEXTLH, P_PPACH, + P_PADDSB, P_PSUBSB, P_PEXTLB, P_PPACB, + P_MMI_Unknown, P_MMI_Unknown, P_PEXT5, P_PPAC5, +}; +/* + MMI1: Instr. encoded by function field when opcode field = MMI & MMI1 + + 31---------26------------------------------------------5--------0 + | | |function | MMI1 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 | --- | PABSW | PCEQW | PMINW | +001 |PADSBH | PABSH | PCEQH | PMINH | +010 | --- | --- | PCEQB | --- | +011 | --- | --- | --- | --- | +100 |PADDUW |PSUBUW |PEXTUW | --- | +101 |PADDUH |PSUBUH |PEXTUH | --- | +110 |PADDUB |PSUBUB |PEXTUB | QFSRV | +111 | --- | --- | --- | --- | + hi |-------|-------|-------|-------| +*/ +void (*MMI1PrintTable[32])(char *buf) = { + P_MMI_Unknown, P_PABSW, P_PCEQW, P_PMINW, + P_PADSBH, P_PABSH, P_PCEQH, P_PMINH, + P_MMI_Unknown, P_MMI_Unknown, P_PCEQB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDUW, P_PSUBUW, P_PEXTUW, P_MMI_Unknown, + P_PADDUH, P_PSUBUH, P_PEXTUH, P_MMI_Unknown, + P_PADDUB, P_PSUBUB, P_PEXTUB, P_QFSRV, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, +}; + +/* + MMI2: Instr. encoded by function field when opcode field = MMI & MMI2 + + 31---------26------------------------------------------5--------0 + | | |function | MMI2 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDW | --- |PSLLVW |PSRLVW | +001 |PMSUBW | --- | --- | --- | +010 |PMFHI |PMFLO |PINTH | --- | +011 |PMULTW |PDIVW |PCPYLD | --- | +100 |PMADDH |PHMADH | PAND | PXOR | +101 |PMSUBH |PHMSBH | --- | --- | +110 | --- | --- | PEXEH | PREVH | +111 |PMULTH |PDIVBW | PEXEW |PROT3W | + hi |-------|-------|-------|-------| +*/ +void (*MMI2PrintTable[32])(char *buf) = { + P_PMADDW, P_MMI_Unknown, P_PSLLVW, P_PSRLVW, + P_PMSUBW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHI, P_PMFLO, P_PINTH, P_MMI_Unknown, + P_PMULTW, P_PDIVW, P_PCPYLD, P_MMI_Unknown, + P_PMADDH, P_PHMADH, P_PAND, P_PXOR, + P_PMSUBH, P_PHMSBH, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXEH, P_PREVH, + P_PMULTH, P_PDIVBW, P_PEXEW, P_PROT3W, +}; +/* + MMI3: Instr. encoded by function field when opcode field = MMI & MMI3 + 31---------26------------------------------------------5--------0 + | | |function | MMI3 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDUW| --- | --- |PSRAVW | +001 | --- | --- | --- | --- | +010 |PMTHI | PMTLO |PINTEH | --- | +011 |PMULTUW| PDIVUW|PCPYUD | --- | +100 | --- | --- | POR | PNOR | +101 | --- | --- | --- | --- | +110 | --- | --- | PEXCH | PCPYH | +111 | --- | --- | PEXCW | --- | + hi |-------|-------|-------|-------| + */ +void (*MMI3PrintTable[32])(char *buf) = { + P_PMADDUW, P_MMI_Unknown, P_MMI_Unknown, P_PSRAVW, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMTHI, P_PMTLO, P_PINTEH, P_MMI_Unknown, + P_PMULTUW, P_PDIVUW, P_PCPYUD, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_POR, P_PNOR, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCH, P_PCPYH, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCW, P_MMI_Unknown, +}; +/* + COP0: Instructions encoded by the rs field when opcode = COP0. + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=BC See BC0 list *2 = TLB instr, see TLB list +*/ +void (*COP0PrintTable[32])(char *buf) = { + P_MFC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_MTC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_BC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Func, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + BC0: Instructions encoded by the rt field when opcode = COP0 & rs field=BC0 + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0BC0PrintTable[32])(char *buf) = { + P_BC0F, P_BC0T, P_BC0FL, P_BC0TL, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + C0=Instructions encode by function field when Opcode field=COP0 & rs field=C0 + 31---------26------------------------------------------5--------0 + | | | | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | +001 | TLBP | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | ERET | --- | --- | --- | --- | --- | --- | --- | +100 | --- | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | EI | DI | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0C0PrintTable[64])(char *buf) = { + P_COP0_Unknown, P_TLBR, P_TLBWI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_TLBWR, P_COP0_Unknown, + P_TLBP, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_ERET, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_EI, P_DI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown +}; +/* + COP1: Instructions encoded by the fmt field when opcode = COP1. + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC1 | --- | CFC1 | --- | MTC1 | --- | CTC1 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC1 list *2 = S instr, see FPU list + *3 = W instr, see FPU list +*/ +void (*COP1PrintTable[32])(char *buf) = { + P_MFC1, P_COP1_Unknown, P_CFC1, P_COP1_Unknown, P_MTC1, P_COP1_Unknown, P_CTC1, P_COP1_Unknown, + P_COP1_BC1, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_S, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_W, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + BC1: Instructions encoded by the rt field when opcode = COP1 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1BC1PrintTable[32])(char *buf) = { + P_BC1F, P_BC1T, P_BC1FL, P_BC1TL, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = S + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = S | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S| ABS.S | MOV.S | NEG.S | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- |RSQRT.S| --- | +011 | ADDA.S| SUBA.S| MULA.S| --- | MADD.S| MSUB.S|MADDA.S|MSUBA.S| +100 | --- | --- | --- | --- | CVT.W | --- | --- | --- | +101 | MAX.S | MIN.S | --- | --- | --- | --- | --- | --- | +110 | C.F | --- | C.EQ | --- | C.LT | --- | C.LE | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1SPrintTable[64])(char *buf) = { +P_ADD_S, P_SUB_S, P_MUL_S, P_DIV_S, P_SQRT_S, P_ABS_S, P_MOV_S, P_NEG_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_RSQRT_S, P_COP1_Unknown, +P_ADDA_S, P_SUBA_S, P_MULA_S, P_COP1_Unknown,P_MADD_S, P_MSUB_S, P_MADDA_S, P_MSUBA_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_CVT_W, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_MAX_S, P_MIN_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_C_F, P_COP1_Unknown,P_C_EQ, P_COP1_Unknown,P_C_LT, P_COP1_Unknown,P_C_LE, P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = W + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = W | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | --- | --- | --- | --- | --- | --- | --- | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | --- | --- | --- | --- | --- | --- | --- | --- | +100 | CVT.S | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1WPrintTable[64])(char *buf) = { +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_CVT_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; + +//************************************************************* +//COP2 TABLES :) +//************************************************************* +/* + COP2: Instructions encoded by the fmt field when opcode = COP2. + 31--------26-25------21 ----------------------------------------0 + | = COP2 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | --- | QMFC2 | CFC2 | --- | --- | QMTC2 | CTC2 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC2 list *2 =see special1 table +*/ +void (*COP2PrintTable[32])(char *buf) = { + P_COP2_Unknown, P_QMFC2, P_CFC2, P_COP2_Unknown, P_COP2_Unknown, P_QMTC2, P_CTC2, P_COP2_Unknown, + P_COP2_BC2, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + + +}; +/* + BC2: Instructions encoded by the rt field when opcode = COP2 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP2 | rs=BC2| | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + */ +void (*COP2BC2PrintTable[32])(char *buf) = { + P_BC2F, P_BC2T, P_BC2FL, P_BC2TL, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, +}; +/* + Special1 table : instructions encode by function field when opcode=COP2 & rs field=Special1 + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 |VADDx |VADDy |VADDz |VADDw |VSUBx |VSUBy |VSUBz |VSUBw | +001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw | +010 |VMAXx |VMAXy |VMAXz |VMAXw |VMINIx |VMINIy |VMINIz |VMINIw | +011 |VMULx |VMULy |VMULz |VMULw |VMULq |VMAXi |VMULi |VMINIi | +100 |VADDq |VMADDq |VADDi |VMADDi |VSUBq |VMSUBq |VSUbi |VMSUBi | +101 |VADD |VMADD |VMUL |VMAX |VSUB |VMSUB |VOPMSUB|VMINI | +110 |VIADD |VISUB |VIADDI | --- |VIAND |VIOR | --- | --- | +111 |VCALLMS|CALLMSR| --- | --- | *1 | *1 | *1 | *1 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=see special2 table +*/ +void (*COP2SPECIAL1PrintTable[64])(char *buf) = +{ + P_VADDx, P_VADDy, P_VADDz, P_VADDw, P_VSUBx, P_VSUBy, P_VSUBz, P_VSUBw, + P_VMADDx, P_VMADDy, P_VMADDz, P_VMADDw, P_VMSUBx, P_VMSUBy, P_VMSUBz, P_VMSUBw, + P_VMAXx, P_VMAXy, P_VMAXz, P_VMAXw, P_VMINIx, P_VMINIy, P_VMINIz, P_VMINIw, + P_VMULx, P_VMULy, P_VMULz, P_VMULw, P_VMULq, P_VMAXi, P_VMULi, P_VMINIi, + P_VADDq, P_VMADDq, P_VADDi, P_VMADDi, P_VSUBq, P_VMSUBq, P_VSUbi, P_VMSUBi, + P_VADD, P_VMADD, P_VMUL, P_VMAX, P_VSUB, P_VMSUB, P_VOPMSUB, P_VMINI, + P_VIADD, P_VISUB, P_VIADDI, P_COP2_Unknown,P_VIAND, P_VIOR, P_COP2_Unknown, P_COP2_Unknown, + P_VCALLMS, P_CALLMSR, P_COP2_Unknown,P_COP2_Unknown,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2, + +}; +/* + Special2 table : instructions encode by function field when opcode=COp2 & rs field=Special2 + + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special2 | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +0000 |VADDAx |VADDAy |VADDAz |VADDAw |VSUBAx |VSUBAy |VSUBAz |VSUBAw | +0001 |VMADDAx|VMADDAy|VMADDAz|VMADDAw|VMSUBAx|VMSUBAy|VMSUBAz|VMSUBAw| +0010 |VITOF0 |VITOF4 |VITOF12|VITOF15|VFTOI0 |VFTOI4 |VFTOI12|VFTOI15| +0011 |VMULAx |VMULAy |VMULAz |VMULAw |VMULAq |VABS |VMULAi |VCLIPw | +0100 |VADDAq |VMADDAq|VADDAi |VMADDAi|VSUBAq |VMSUBAq|VSUBAi |VMSUBAi| +0101 |VADDA |VMADDA |VMULA | --- |VSUBA |VMSUBA |VOPMULA|VNOP | +0110 |VMONE |VMR32 | --- | --- |VLQI |VSQI |VLQD |VSQD | +0111 |VDIV |VSQRT |VRSQRT |VWAITQ |VMTIR |VMFIR |VILWR |VISWR | +1000 |VRNEXT |VRGET |VRINIT |VRXOR | --- | --- | --- | --- | +1001 | --- | --- | --- | --- | --- | --- | --- | --- | +1010 | --- | --- | --- | --- | --- | --- | --- | --- | +1011 | --- | --- | --- | --- | --- | --- | --- | --- | +1100 | --- | --- | --- | --- | --- | --- | --- | --- | +1101 | --- | --- | --- | --- | --- | --- | --- | --- | +1110 | --- | --- | --- | --- | --- | --- | --- | --- | +1111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP2SPECIAL2PrintTable[128])(char *buf) = +{ + P_VADDAx ,P_VADDAy ,P_VADDAz ,P_VADDAw ,P_VSUBAx ,P_VSUBAy ,P_VSUBAz ,P_VSUBAw, + P_VMADDAx ,P_VMADDAy ,P_VMADDAz ,P_VMADDAw ,P_VMSUBAx ,P_VMSUBAy ,P_VMSUBAz ,P_VMSUBAw, + P_VITOF0 ,P_VITOF4 ,P_VITOF12 ,P_VITOF15 ,P_VFTOI0 ,P_VFTOI4 ,P_VFTOI12 ,P_VFTOI15, + P_VMULAx ,P_VMULAy ,P_VMULAz ,P_VMULAw ,P_VMULAq ,P_VABS ,P_VMULAi ,P_VCLIPw, + P_VADDAq ,P_VMADDAq ,P_VADDAi ,P_VMADDAi ,P_VSUBAq ,P_VMSUBAq ,P_VSUBAi ,P_VMSUBAi, + P_VADDA ,P_VMADDA ,P_VMULA ,P_COP2_Unknown,P_VSUBA ,P_VMSUBA ,P_VOPMULA ,P_VNOP, + P_VMONE ,P_VMR32 ,P_COP2_Unknown,P_COP2_Unknown,P_VLQI ,P_VSQI ,P_VLQD ,P_VSQD, + P_VDIV ,P_VSQRT ,P_VRSQRT ,P_VWAITQ ,P_VMTIR ,P_VMFIR ,P_VILWR ,P_VISWR, + P_VRNEXT ,P_VRGET ,P_VRINIT ,P_VRXOR ,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, +}; + +//**************************TABLES CALLS*********************** + +static char dbuf[1024]; +static char obuf[1024]; + +char *disR5900Fasm(u32 code, u32 pc) { + u32 scode = cpuRegs.code; + opcode_addr = pc; + cpuRegs.code = code; + OpcodePrintTable[(code) >> 26](dbuf); + + sprintf(obuf, "%08X:\t%s", pc, dbuf); + + cpuRegs.code = scode; + return obuf; +} + +void P_SpecialOpcode(char *buf) +{ + SpecialPrintTable[DECODE_FUNCTION](buf); +} +void P_REGIMMOpcode(char *buf) +{ + REGIMMPrintTable[DECODE_RT](buf); +} + +//***********COP0 TABLE CALLS******************************** + +void P_COP0(char *buf) +{ + COP0PrintTable[DECODE_RS](buf); +} +void P_COP0_BC0(char *buf) +{ + + COP0BC0PrintTable[DECODE_C0BC](buf); +} +void P_COP0_Func(char *buf) +{ + + COP0C0PrintTable[DECODE_FUNCTION](buf); +} + +//*****************MMI TABLES CALLS************************** +void P_MMI(char *buf) +{ + + MMIPrintTable[DECODE_FUNCTION](buf); +} +void P_MMI0(char *buf) +{ + MMI0PrintTable[DECODE_SA](buf); +} +void P_MMI1(char *buf) +{ + MMI1PrintTable[DECODE_SA](buf); +} +void P_MMI2(char *buf) +{ + MMI2PrintTable[DECODE_SA](buf); +} +void P_MMI3(char *buf) +{ + MMI3PrintTable[DECODE_SA](buf); +} +//****************END OF MMI TABLES CALLS********************** +//COP1 TABLECALLS******************************************* +void P_COP1(char *buf) +{ + + COP1PrintTable[DECODE_RS](buf); +} +void P_COP1_BC1(char *buf) +{ + COP1BC1PrintTable[DECODE_C1BC](buf); +} +void P_COP1_S(char *buf) +{ + COP1SPrintTable[DECODE_FUNCTION](buf); +} +void P_COP1_W(char *buf) +{ + COP1WPrintTable[DECODE_FUNCTION](buf); +} +//**********************END OF COP1 TABLE CALLS + +//************************************************************* +//************************COP2********************************** +void P_COP2(char *buf) +{ + + COP2PrintTable[DECODE_RS](buf); +} +void P_COP2_BC2(char *buf) +{ + COP2BC2PrintTable[DECODE_C2BC](buf); +} +void P_COP2_SPECIAL(char *buf) +{ + COP2SPECIAL1PrintTable[DECODE_FUNCTION ](buf); + +} +void P_COP2_SPECIAL2(char *buf) +{ + + COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](buf); + +} + +//**************************UNKNOWN**************************** +void P_UnknownOpcode(char *buf) +{ + strcpy(buf, "?????"); +} +void P_COP0_Unknown(char *buf) +{ + strcpy(buf, "COP0 ??"); +} +void P_COP1_Unknown(char *buf) +{ + strcpy(buf, "COP1 ??"); +} +void P_COP2_Unknown(char *buf) +{ + strcpy(buf,"COP2 ??"); +} + +void P_MMI_Unknown(char *buf) +{ + strcpy(buf,"MMI ??"); +} + + + +//************************************************************* + +//*****************SOME DECODE STUFF*************************** +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(buf, "%s %s", buf, str); \ +} + +char *jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_JUMP; + sprintf(buf, "0x%08X", addr); + + dFindSym(addr); + return buf; +} + +char *offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_OFFSET; + sprintf(buf, "0x%08X", addr); + dFindSym(addr); + return buf; +} + +//*********************END OF DECODE ROUTINES****************** + +//********************* Standard Opcodes*********************** +void P_J(char *buf) { sprintf(buf, "j\t%s", jump_decode());} +void P_JAL(char *buf) { sprintf(buf, "jal\t%s", jump_decode());} +void P_BEQ(char *buf) { sprintf(buf, "beq\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNE(char *buf) { sprintf(buf, "bne\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZ(char *buf) { sprintf(buf, "blez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZ(char *buf) { sprintf(buf, "bgtz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_ADDI(char *buf) { sprintf(buf, "addi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ADDIU(char *buf) { sprintf(buf, "addiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_SLTI(char *buf) { sprintf(buf, "slti\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_SLTIU(char *buf) { sprintf(buf, "sltiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_ANDI(char *buf) { sprintf(buf, "andi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ORI(char *buf) { sprintf(buf, "ori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_XORI(char *buf) { sprintf(buf, "xori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LUI(char *buf) { sprintf(buf, "lui\t%s, 0x%04X", GPR_REG[DECODE_RT], DECODE_IMMED); } +void P_BEQL(char *buf) { sprintf(buf, "beql\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNEL(char *buf) { sprintf(buf, "bnel\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZL(char *buf) { sprintf(buf, "blezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZL(char *buf) { sprintf(buf, "bgtzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_DADDI(char *buf) { sprintf(buf, "daddi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_DADDIU(char *buf) { sprintf(buf, "daddiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LDL(char *buf) { sprintf(buf, "ldl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LDR(char *buf) { sprintf(buf, "ldr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LB(char *buf) { sprintf(buf, "lb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LH(char *buf) { sprintf(buf, "lh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWL(char *buf) { sprintf(buf, "lwl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LW(char *buf) { sprintf(buf, "lw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LBU(char *buf) { sprintf(buf, "lbu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LHU(char *buf) { sprintf(buf, "lhu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWR(char *buf) { sprintf(buf, "lwr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWU(char *buf) { sprintf(buf, "lwu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SB(char *buf) { sprintf(buf, "sb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SH(char *buf) { sprintf(buf, "sh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWL(char *buf) { sprintf(buf, "swl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SW(char *buf) { sprintf(buf, "sw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDL(char *buf) { sprintf(buf, "sdl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDR(char *buf) { sprintf(buf, "sdr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWR(char *buf) { sprintf(buf, "swr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LD(char *buf) { sprintf(buf, "ld\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SD(char *buf) { sprintf(buf, "sd\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQ(char *buf) { sprintf(buf, "lq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQ(char *buf) { sprintf(buf, "sq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWC1(char *buf) { sprintf(buf, "swc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQC2(char *buf) { sprintf(buf, "sqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_PREF(char *buf) { strcpy(buf, "pref ---");/*sprintf(buf, "PREF\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[RS]); */} +void P_LWC1(char *buf) { sprintf(buf, "lwc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQC2(char *buf) { sprintf(buf, "lqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +//********************END OF STANDARD OPCODES************************* + +void P_SLL(char *buf) +{ + if (cpuRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); +} + +void P_SRL(char *buf) { sprintf(buf, "srl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SRA(char *buf) { sprintf(buf, "sra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SLLV(char *buf) { sprintf(buf, "sllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_SRLV(char *buf) { sprintf(buf, "srlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]);} +void P_SRAV(char *buf) { sprintf(buf, "srav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_JR(char *buf) { sprintf(buf, "jr\t%s", GPR_REG[DECODE_RS]); } + +void P_JALR(char *buf) +{ + int rd = DECODE_RD; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_REG[DECODE_RS]); + else + sprintf(buf, "jalr\t%s, %s", GPR_REG[rd], GPR_REG[DECODE_RS]); +} + + +void P_SYNC(char *buf) { sprintf(buf, "SYNC");} +void P_MFHI(char *buf) { sprintf(buf, "mfhi\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI(char *buf) { sprintf(buf, "mthi\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO(char *buf) { sprintf(buf, "mflo\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO(char *buf) { sprintf(buf, "mtlo\t%s", GPR_REG[DECODE_RS]); } +void P_DSLLV(char *buf) { sprintf(buf, "dsllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRLV(char *buf) { sprintf(buf, "dsrlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRAV(char *buf) { sprintf(buf, "dsrav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_MULT(char *buf) { sprintf(buf, "mult\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_MULTU(char *buf) { sprintf(buf, "multu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV(char *buf) { sprintf(buf, "div\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU(char *buf) { sprintf(buf, "divu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADD(char *buf) { sprintf(buf, "dadd\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADDU(char *buf) { sprintf(buf, "daddu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUB(char *buf) { sprintf(buf, "dsub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUBU(char *buf) { sprintf(buf, "dsubu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGE(char *buf) { sprintf(buf, "tge\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGEU(char *buf) { sprintf(buf, "tgeu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLT(char *buf) { sprintf(buf, "tlt\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLTU(char *buf) { sprintf(buf, "tltu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TEQ(char *buf) { sprintf(buf, "teq\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TNE(char *buf) { sprintf(buf, "tne\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSLL(char *buf) { sprintf(buf, "dsll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL(char *buf) { sprintf(buf, "dsrl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA(char *buf) { sprintf(buf, "dsra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSLL32(char *buf) { sprintf(buf, "dsll32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL32(char *buf) { sprintf(buf, "dsrl32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA32(char *buf) { sprintf(buf, "dsra32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_MOVZ(char *buf) { sprintf(buf, "movz\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MOVN(char *buf) { sprintf(buf, "movn\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFSA(char *buf) { sprintf(buf, "mfsa\t%s", GPR_REG[DECODE_RD]);} +void P_MTSA(char *buf) { sprintf(buf, "mtsa\t%s", GPR_REG[DECODE_RS]);} +//*** unsupport (yet) cpu opcodes +void P_SYSCALL(char *buf) { strcpy(buf, "syscall ---");/*sprintf(buf, "syscall\t0x%05X", DECODE_SYSCALL);*/} +void P_BREAK(char *buf) { strcpy(buf, "break ---");/*sprintf(buf, "break\t0x%05X", DECODE_BREAK); */} +void P_CACHE(char *buf) { strcpy(buf, "cache ---");/*sprintf(buf, "cache\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); */} +//************************REGIMM OPCODES*************************** +void P_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZL(char *buf) { sprintf(buf, "bltzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZL(char *buf) { sprintf(buf, "bgezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_TGEI(char *buf) { sprintf(buf, "tgei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TGEIU(char *buf) { sprintf(buf, "tgeiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTI(char *buf) { sprintf(buf, "tlti\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTIU(char *buf) { sprintf(buf, "tltiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TEQI(char *buf) { sprintf(buf, "teqi\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TNEI(char *buf) { sprintf(buf, "tnei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZALL(char *buf) { sprintf(buf, "bltzall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZALL(char *buf) { sprintf(buf, "bgezall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_MTSAB(char *buf) { sprintf(buf, "mtsab\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_MTSAH(char *buf) { sprintf(buf, "mtsah\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} + + +//***************************SPECIAL 2 CPU OPCODES******************* +const char* pmfhl_sub[] = { "lw", "uw", "slw", "lh", "sh" }; + +void P_MADD(char *buf) { sprintf(buf, "madd\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU(char *buf) { sprintf(buf, "maddu\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_PLZCW(char *buf) { sprintf(buf, "plzcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS]); } +void P_MADD1(char *buf) { sprintf(buf, "madd1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU1(char *buf) { sprintf(buf, "maddu1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFHI1(char *buf) { sprintf(buf, "mfhi1\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI1(char *buf) { sprintf(buf, "mthi1\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO1(char *buf) { sprintf(buf, "mflo1\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO1(char *buf) { sprintf(buf, "mtlo1\t%s", GPR_REG[DECODE_RS]); } +void P_MULT1(char *buf) { sprintf(buf, "mult1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MULTU1(char *buf) { sprintf(buf, "multu1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV1(char *buf) { sprintf(buf, "div1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU1(char *buf) { sprintf(buf, "divu1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//that have parametres that i haven't figure out how to display... +void P_PMFHL(char *buf) { sprintf(buf, "pmfhl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RD]); } +void P_PMTHL(char *buf) { sprintf(buf, "pmthl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RS]); } +void P_PSLLH(char *buf) { sprintf(buf, "psllh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_PSRLH(char *buf) { sprintf(buf, "psrlh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAH(char *buf) { sprintf(buf, "psrah \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSLLW(char *buf) { sprintf(buf, "psllw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRLW(char *buf) { sprintf(buf, "psrlw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAW(char *buf) { sprintf(buf, "psraw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +//***************************END OF SPECIAL OPCODES****************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf){ sprintf(buf, "paddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBW(char *buf){ sprintf(buf, "psubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTW(char *buf){ sprintf(buf, "pcgtw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXW(char *buf){ sprintf(buf, "pmaxw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDH(char *buf){ sprintf(buf, "paddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBH(char *buf){ sprintf(buf, "psubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTH(char *buf){ sprintf(buf, "pcgth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXH(char *buf){ sprintf(buf, "pmaxh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDB(char *buf){ sprintf(buf, "paddb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBB(char *buf){ sprintf(buf, "psubb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTB(char *buf){ sprintf(buf, "pcgtb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSW(char *buf){ sprintf(buf, "paddsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSW(char *buf){ sprintf(buf, "psubsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLW(char *buf){ sprintf(buf, "pextlw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACW(char *buf) { sprintf(buf, "ppacw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSH(char *buf){ sprintf(buf, "paddsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSH(char *buf){ sprintf(buf, "psubsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLH(char *buf){ sprintf(buf, "pextlh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACH(char *buf) { sprintf(buf, "ppach\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSB(char *buf){ sprintf(buf, "paddsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSB(char *buf){ sprintf(buf, "psubsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLB(char *buf){ sprintf(buf, "pextlb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACB(char *buf) { sprintf(buf, "ppacb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXT5(char *buf) { sprintf(buf, "pext5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PPAC5(char *buf) { sprintf(buf, "ppac5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//**********END OF MMI0 OPCODES********************************* +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf){ sprintf(buf, "pabsw%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQW(char *buf){ sprintf(buf, "pceqw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINW(char *buf){ sprintf(buf, "pminw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADSBH(char *buf){ sprintf(buf, "padsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PABSH(char *buf){ sprintf(buf, "pabsh%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQH(char *buf){ sprintf(buf, "pceqh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINH(char *buf){ sprintf(buf, "pminh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCEQB(char *buf){ sprintf(buf, "pceqb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUW(char *buf){ sprintf(buf, "padduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUW(char *buf){ sprintf(buf, "psubuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUW(char *buf){ sprintf(buf, "pextuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUH(char *buf){ sprintf(buf, "padduh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUH(char *buf){ sprintf(buf, "psubuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUH(char *buf){ sprintf(buf, "pextuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUB(char *buf){ sprintf(buf, "paddub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUB(char *buf){ sprintf(buf, "psubub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUB(char *buf){ sprintf(buf, "pextub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_QFSRV(char *buf) { sprintf(buf, "qfsrv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf){ sprintf(buf, "pmaddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSLLVW(char *buf){ sprintf(buf, "psllvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSRLVW(char *buf){ sprintf(buf, "psrlvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBW(char *buf){ sprintf(buf, "msubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMFHI(char *buf){ sprintf(buf, "pmfhi\t%s", GPR_REG[DECODE_RD]); } +void P_PMFLO(char *buf){ sprintf(buf, "pmflo\t%s", GPR_REG[DECODE_RD]); } +void P_PINTH(char *buf){ sprintf(buf, "pinth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTW(char *buf){ sprintf(buf, "pmultw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVW(char *buf){ sprintf(buf, "pdivw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYLD(char *buf){ sprintf(buf, "pcpyld\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMADDH(char *buf){ sprintf(buf, "pmaddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMADH(char *buf){ sprintf(buf, "phmadh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PAND(char *buf){ sprintf(buf, "pand\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PXOR(char *buf){ sprintf(buf, "pxor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBH(char *buf){ sprintf(buf, "pmsubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMSBH(char *buf){ sprintf(buf, "phmsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEH(char *buf){ sprintf(buf, "pexeh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PREVH(char *buf){ sprintf(buf, "prevh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PMULTH(char *buf){ sprintf(buf, "pmulth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVBW(char *buf){ sprintf(buf, "pdivbw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEW(char *buf){ sprintf(buf, "pexew\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PROT3W(char *buf){ sprintf(buf, "prot3w\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf){ sprintf(buf, "pmadduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PSRAVW(char *buf){ sprintf(buf, "psravw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PMTHI(char *buf){ sprintf(buf, "pmthi\t%s", GPR_REG[DECODE_RS]); } +void P_PMTLO(char *buf){ sprintf(buf, "pmtlo\t%s", GPR_REG[DECODE_RS]); } +void P_PINTEH(char *buf){ sprintf(buf, "pinteh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTUW(char *buf){ sprintf(buf, "pmultuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVUW(char *buf){ sprintf(buf, "pdivuw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYUD(char *buf){ sprintf(buf, "pcpyud\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_POR(char *buf){ sprintf(buf, "por\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PNOR(char *buf){ sprintf(buf, "pnor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXCH(char *buf){ sprintf(buf, "pexch\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PCPYH(char *buf){ sprintf(buf, "pcpyh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PEXCW(char *buf){ sprintf(buf, "pexcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_BC0F(char *buf){ sprintf(buf, "bc0f\t%s", offset_decode()); } +void P_BC0T(char *buf){ sprintf(buf, "bc0t\t%s", offset_decode()); } +void P_BC0FL(char *buf){ sprintf(buf, "bc0fl\t%s", offset_decode()); } +void P_BC0TL(char *buf){ sprintf(buf, "bc0tl\t%s", offset_decode()); } +void P_TLBR(char *buf){ strcpy(buf,"tlbr");} +void P_TLBWI(char *buf){ strcpy(buf,"tlbwi");} +void P_TLBWR(char *buf){ strcpy(buf,"tlbwr");} +void P_TLBP(char *buf){ strcpy(buf,"tlbp");} +void P_ERET(char *buf){ strcpy(buf,"eret");} +void P_DI(char *buf){ strcpy(buf,"di");} +void P_EI(char *buf){ strcpy(buf,"ei");} +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf){ sprintf(buf, "mfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CFC1(char *buf){ sprintf(buf, "cfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_MTC1(char *buf){ sprintf(buf, "mtc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CTC1(char *buf){ sprintf(buf, "ctc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_BC1F(char *buf){ sprintf(buf, "bc1f\t%s", offset_decode()); } +void P_BC1T(char *buf){ sprintf(buf, "bc1t\t%s", offset_decode()); } +void P_BC1FL(char *buf){ sprintf(buf, "bc1fl\t%s", offset_decode()); } +void P_BC1TL(char *buf){ sprintf(buf, "bc1tl\t%s", offset_decode()); } +void P_ADD_S(char *buf){ sprintf(buf, "add.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_SUB_S(char *buf){ sprintf(buf, "sub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MUL_S(char *buf){ sprintf(buf, "mul.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_DIV_S(char *buf){ sprintf(buf, "div.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SQRT_S(char *buf){ sprintf(buf, "sqrt.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FT]); } +void P_ABS_S(char *buf){ sprintf(buf, "abs.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MOV_S(char *buf){ sprintf(buf, "mov.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_NEG_S(char *buf){ sprintf(buf, "neg.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]);} +void P_RSQRT_S(char *buf){sprintf(buf, "rsqrt.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_ADDA_S(char *buf){ sprintf(buf, "adda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SUBA_S(char *buf){ sprintf(buf, "suba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MULA_S(char *buf){ sprintf(buf, "mula.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADD_S(char *buf){ sprintf(buf, "madd.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUB_S(char *buf){ sprintf(buf, "msub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADDA_S(char *buf){sprintf(buf, "madda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUBA_S(char *buf){sprintf(buf, "msuba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_W(char *buf){ sprintf(buf, "cvt.w.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MAX_S(char *buf){ sprintf(buf, "max.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MIN_S(char *buf){ sprintf(buf, "min.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_C_F(char *buf){ sprintf(buf, "c.f.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_EQ(char *buf){ sprintf(buf, "c.eq.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LT(char *buf){ sprintf(buf, "c.lt.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LE(char *buf){ sprintf(buf, "c.le.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_S(char *buf){ sprintf(buf, "cvt.s.w\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf){ sprintf(buf, "qmfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CFC2(char *buf){ sprintf(buf, "cfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_QMTC2(char *buf){ sprintf(buf, "qmtc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CTC2(char *buf){ sprintf(buf, "ctc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_BC2F(char *buf){ sprintf(buf, "bc2f\t%s", offset_decode()); } +void P_BC2T(char *buf){ sprintf(buf, "bc2t\t%s", offset_decode()); } +void P_BC2FL(char *buf){ sprintf(buf, "bc2fl\t%s", offset_decode()); } +void P_BC2TL(char *buf){ sprintf(buf, "bc2tl\t%s", offset_decode()); } +//******************************SPECIAL 1 VUO TABLE**************************************** +#define _X ((cpuRegs.code>>24) & 1) +#define _Y ((cpuRegs.code>>23) & 1) +#define _Z ((cpuRegs.code>>22) & 1) +#define _W ((cpuRegs.code>>21) & 1) + +const char *dest_string(void) +{ + static char str[5]; + int i; + i = 0; + if(_X) str[i++] = 'x'; + if(_Y) str[i++] = 'y'; + if(_Z) str[i++] = 'z'; + if(_W) str[i++] = 'w'; + str[i++] = 0; + return (const char *)str; +} + +char dest_fsf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>21)&3]; +} + +char dest_ftf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>23)&3]; +} + +void P_VADDx(char *buf){sprintf(buf, "vaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDy(char *buf){sprintf(buf, "vaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDz(char *buf){sprintf(buf, "vaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDw(char *buf){sprintf(buf, "vaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBx(char *buf){sprintf(buf, "vsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBy(char *buf){sprintf(buf, "vsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBz(char *buf){sprintf(buf, "vsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBw(char *buf){sprintf(buf, "vsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDx(char *buf){sprintf(buf, "vmaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDy(char *buf){sprintf(buf, "vmaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDz(char *buf){sprintf(buf, "vmaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDw(char *buf){sprintf(buf, "vmaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBx(char *buf){sprintf(buf, "vmsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBy(char *buf){sprintf(buf, "vmsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBz(char *buf){sprintf(buf, "vmsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBw(char *buf){sprintf(buf, "vmsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXx(char *buf){sprintf(buf, "vmaxx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXy(char *buf){sprintf(buf, "vmaxy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXz(char *buf){sprintf(buf, "vmaxz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXw(char *buf){sprintf(buf, "vmaxw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIx(char *buf){sprintf(buf, "vminix.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIy(char *buf){sprintf(buf, "vminiy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); ;} +void P_VMINIz(char *buf){sprintf(buf, "vminiz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIw(char *buf){sprintf(buf, "vminiw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULx(char *buf){sprintf(buf,"vmulx.%s %s,%s,%sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULy(char *buf){sprintf(buf,"vmuly.%s %s,%s,%sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULz(char *buf){sprintf(buf,"vmulz.%s %s,%s,%sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULw(char *buf){sprintf(buf,"vmulw.%s %s,%s,%sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULq(char *buf){sprintf(buf,"vmulq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMAXi(char *buf){sprintf(buf,"vmaxi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMULi(char *buf){sprintf(buf,"vmuli.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMINIi(char *buf){sprintf(buf,"vminii.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDq(char *buf){sprintf(buf,"vaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDq(char *buf){sprintf(buf,"vmaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDi(char *buf){sprintf(buf,"vaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDi(char *buf){sprintf(buf,"vmaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUBq(char *buf){sprintf(buf,"vsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBq(char *buf){sprintf(buf,"vmsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUbi(char *buf){sprintf(buf,"vsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBi(char *buf){sprintf(buf,"vmsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADD(char *buf){sprintf(buf, "vadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADD(char *buf){sprintf(buf, "vmadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMUL(char *buf){sprintf(buf, "vmul.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAX(char *buf){sprintf(buf, "vmax.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUB(char *buf){sprintf(buf, "vsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUB(char *buf){sprintf(buf, "vmsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMSUB(char *buf){sprintf(buf, "vopmsub.xyz %s, %s, %s", COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINI(char *buf){sprintf(buf, "vmini.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VIADD(char *buf){sprintf(buf,"viadd %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VISUB(char *buf){sprintf(buf,"visub %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VIADDI(char *buf){sprintf(buf,"viaddi %s, %s, 0x%x", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], DECODE_SA);} +void P_VIAND(char *buf){sprintf(buf,"viand %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VIOR(char *buf){sprintf(buf,"vior %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VCALLMS(char *buf){strcpy(buf,"vcallms");} +void P_CALLMSR(char *buf){strcpy(buf,"callmsr");} +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf){sprintf(buf,"vaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAy(char *buf){sprintf(buf,"vadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAz(char *buf){sprintf(buf,"vaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAw(char *buf){sprintf(buf,"vaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAx(char *buf){sprintf(buf,"vsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAy(char *buf){sprintf(buf,"vsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAz(char *buf){sprintf(buf,"vsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAw(char *buf){sprintf(buf,"vsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAx(char *buf){sprintf(buf,"vmaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAy(char *buf){sprintf(buf,"vmadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAz(char *buf){sprintf(buf,"vmaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAw(char *buf){sprintf(buf,"vmaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAx(char *buf){sprintf(buf,"vmsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAy(char *buf){sprintf(buf,"vmsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAz(char *buf){sprintf(buf,"vmsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAw(char *buf){sprintf(buf,"vmsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VITOF0(char *buf){sprintf(buf, "vitof0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF4(char *buf){sprintf(buf, "vitof4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF12(char *buf){sprintf(buf, "vitof12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF15(char *buf){sprintf(buf, "vitof15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI0(char *buf) {sprintf(buf, "vftoi0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI4(char *buf) {sprintf(buf, "vftoi4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI12(char *buf){sprintf(buf, "vftoi12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI15(char *buf){sprintf(buf, "vftoi15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VMULAx(char *buf){sprintf(buf,"vmulax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAy(char *buf){sprintf(buf,"vmulay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAz(char *buf){sprintf(buf,"vmulaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAw(char *buf){sprintf(buf,"vmulaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAq(char *buf){sprintf(buf,"vmulaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VABS(char *buf){sprintf(buf, "vabs.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]);} +void P_VMULAi(char *buf){sprintf(buf,"vmulaq.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VCLIPw(char *buf){sprintf(buf,"vclip %sxyz, %sw", COP2_REG_FP[DECODE_FS], COP2_REG_FP[DECODE_FT]);} +void P_VADDAq(char *buf){sprintf(buf,"vaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAq(char *buf){sprintf(buf,"vmaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDAi(char *buf){sprintf(buf,"vaddai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAi(char *buf){sprintf(buf,"vmaddai.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAq(char *buf){sprintf(buf,"vsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAq(char *buf){sprintf(buf,"vmsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAi(char *buf){sprintf(buf,"vsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAi(char *buf){sprintf(buf,"vmsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDA(char *buf){sprintf(buf,"vadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDA(char *buf){sprintf(buf,"vmadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULA(char *buf){sprintf(buf,"vmula.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBA(char *buf){sprintf(buf,"vsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBA(char *buf){sprintf(buf,"vmsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMULA(char *buf){sprintf(buf,"vopmula.xyz %sxyz, %sxyz" ,COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VNOP(char *buf){strcpy(buf,"vnop");} +void P_VMONE(char *buf){sprintf(buf,"vmove.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VMR32(char *buf){sprintf(buf,"vmr32.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VLQI(char *buf){sprintf(buf,"vlqi %s%s, (%s++)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQI(char *buf){sprintf(buf,"vsqi %s%s, (%s++)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VLQD(char *buf){sprintf(buf,"vlqd %s%s, (--%s)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQD(char *buf){sprintf(buf,"vsqd %s%s, (--%s)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VDIV(char *buf){sprintf(buf,"vdiv Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VSQRT(char *buf){sprintf(buf,"vsqrt Q, %s%c", COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VRSQRT(char *buf){sprintf(buf,"vrsqrt Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VWAITQ(char *buf){sprintf(buf,"vwaitq");} +void P_VMTIR(char *buf){sprintf(buf,"vmtir %s, %s%c", COP2_REG_CTL[DECODE_FT], COP2_REG_FP[DECODE_FS], dest_fsf());} +void P_VMFIR(char *buf){sprintf(buf,"vmfir %s%c, %s", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VILWR(char *buf){sprintf(buf,"vilwr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VISWR(char *buf){sprintf(buf,"viswr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRNEXT(char *buf){sprintf(buf,"vrnext %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRGET(char *buf){sprintf(buf,"vrget %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRINIT(char *buf){sprintf(buf,"vrinit R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRXOR(char *buf){sprintf(buf,"vrxor R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +//************************************END OF SPECIAL2 VUO TABLE**************************** diff --git a/branches/pcsx2_0.9.2/DebugTools/DisVU0Micro.c b/branches/pcsx2_0.9.2/DebugTools/DisVU0Micro.c new file mode 100644 index 0000000..f5d36dc --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisVU0Micro.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dNameU(i) { char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); sprintf(ostr, "%s %-7s,", ostr, op); } + + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) +#define dImm5() sprintf(ostr, "%s %d,", ostr, (code >> 6) & 0x1f) +#define dImm11() sprintf(ostr, "%s %d,", ostr, code & 0x7ff) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" +#include "VU.h" + +_disVUOpcodes(VU0); +_disVUTables(VU0); + diff --git a/branches/pcsx2_0.9.2/DebugTools/DisVU1Micro.c b/branches/pcsx2_0.9.2/DebugTools/DisVU1Micro.c new file mode 100644 index 0000000..fec3f27 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisVU1Micro.c @@ -0,0 +1,123 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VUmicro.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + if( !CHECK_VU1REC ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + else ostr[0] = 0; \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-12s", ostr, i); \ + +#define dNameU(i) { \ + char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); \ + sprintf(ostr, "%s %-12s", ostr, op); \ +} + +#define dCP2128f(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%8.8x) z=%f (%8.8x) y=%f (%8.8xl) x=%f (%8.8x) (%s),", ostr, VU1.VF[i].f.w, VU1.VF[i].UL[3], VU1.VF[i].f.z, VU1.VF[i].UL[2], VU1.VF[i].f.y, VU1.VF[i].UL[1], VU1.VF[i].f.x, VU1.VF[i].UL[0], disRNameCP2f[i]); \ +} \ + +#define dCP232x(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s x=%f (%s),", ostr, VU1.VF[i].f.x, disRNameCP2f[i]); \ +} \ + +#define dCP232y(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s y=%f (%s),", ostr, VU1.VF[i].f.y, disRNameCP2f[i]); \ +} \ + +#define dCP232z(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s z=%f (%s),", ostr, VU1.VF[i].f.z, disRNameCP2f[i]); \ +} + +#define dCP232w(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%s),", ostr, VU1.VF[i].f.w, disRNameCP2f[i]); \ +} + +#define dCP2ACCf() { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s ACC,", ostr); \ + else sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU1.ACC.f.w, VU1.ACC.f.z, VU1.ACC.f.y, VU1.ACC.f.x); \ +} \ + +#define dCP232i(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %8.8x (%s),", ostr, VU1.VI[i].UL, disRNameCP2i[i]); \ +} + +#define dCP232iF(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %f (%s),", ostr, VU1.VI[i].F, disRNameCP2i[i]); \ +} + +#define dCP232f(i, j) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \ + else sprintf(ostr, "%s %s=%f (%s),", ostr, CP2VFnames[j], VU1.VF[i].F[j], disRNameCP2f[i]); \ +} + +#define dImm5() sprintf(ostr, "%s %d,", ostr, (s16)((code >> 6) & 0x10 ? 0xfff0 | ((code >> 6) & 0xf) : (code >> 6) & 0xf)) +#define dImm11() sprintf(ostr, "%s %d,", ostr, (s16)(code & 0x400 ? 0xfc00 | (code & 0x3ff) : code & 0x3ff)) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" + +_disVUOpcodes(VU1); +_disVUTables(VU1); + diff --git a/branches/pcsx2_0.9.2/DebugTools/DisVUmicro.h b/branches/pcsx2_0.9.2/DebugTools/DisVUmicro.h new file mode 100644 index 0000000..7915cde --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisVUmicro.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUTables(VU) \ + \ +/****************/ \ +/* LOWER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##LowerOP_T3_00_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MOVE , dis##VU##MI_LQI , dis##VU##MI_DIV , dis##VU##MI_MTIR, \ + dis##VU##MI_RNEXT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_MFP , dis##VU##MI_XTOP , dis##VU##MI_XGKICK, \ + dis##VU##MI_ESADD , dis##VU##MI_EATANxy, dis##VU##MI_ESQRT, dis##VU##MI_ESIN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_01_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MR32 , dis##VU##MI_SQI , dis##VU##MI_SQRT , dis##VU##MI_MFIR, \ + dis##VU##MI_RGET , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , dis##VU##MI_XITOP, disNULL , \ + dis##VU##MI_ERSADD, dis##VU##MI_EATANxz, dis##VU##MI_ERSQRT, dis##VU##MI_EATAN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_10_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_LQD , dis##VU##MI_RSQRT, dis##VU##MI_ILWR, \ + dis##VU##MI_RINIT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ELENG , dis##VU##MI_ESUM , dis##VU##MI_ERCPR, dis##VU##MI_EEXP, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_11_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_SQD , dis##VU##MI_WAITQ, dis##VU##MI_ISWR, \ + dis##VU##MI_RXOR , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ERLENG, disNULL , dis##VU##MI_WAITP, disNULL , \ +}; \ + \ +MakeDisF(dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_00_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_01_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_10_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_11, dis##VU##LowerOP_T3_11_OPCODE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##LowerOP_OPCODE[64] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x20 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_IADD , dis##VU##MI_ISUB , dis##VU##MI_IADDI, disNULL , /* 0x30 */ \ + dis##VU##MI_IAND , dis##VU##MI_IOR , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_11, \ +}; \ + \ +MakeDisF(dis##VU##LowerOP, dis##VU##LowerOP_OPCODE[code & 0x3f] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroL[] = { \ + dis##VU##MI_LQ , dis##VU##MI_SQ , disNULL , disNULL, \ + dis##VU##MI_ILW , dis##VU##MI_ISW , disNULL , disNULL, \ + dis##VU##MI_IADDIU, dis##VU##MI_ISUBIU, disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##MI_FCEQ , dis##VU##MI_FCSET , dis##VU##MI_FCAND, dis##VU##MI_FCOR, /* 0x10 */ \ + dis##VU##MI_FSEQ , dis##VU##MI_FSSET , dis##VU##MI_FSAND, dis##VU##MI_FSOR, \ + dis##VU##MI_FMEQ , disNULL , dis##VU##MI_FMAND, dis##VU##MI_FMOR, \ + dis##VU##MI_FCGET , disNULL , disNULL , disNULL, \ + dis##VU##MI_B , dis##VU##MI_BAL , disNULL , disNULL, /* 0x20 */ \ + dis##VU##MI_JR , dis##VU##MI_JALR , disNULL , disNULL, \ + dis##VU##MI_IBEQ , dis##VU##MI_IBNE , disNULL , disNULL, \ + dis##VU##MI_IBLTZ , dis##VU##MI_IBGTZ , dis##VU##MI_IBLEZ, dis##VU##MI_IBGEZ, \ + disNULL , disNULL , disNULL , disNULL, /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##LowerOP , disNULL , disNULL , disNULL, /* 0x40*/ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x50 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x60 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x70 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroLF, dis##VU##MicroL[code >> 25] DisFInterfaceN) \ + \ + \ +/****************/ \ +/* UPPER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##_UPPER_FD_00_TABLE[32] = { \ + dis##VU##MI_ADDAx, dis##VU##MI_SUBx , dis##VU##MI_MADDAx, dis##VU##MI_MSUBAx, \ + dis##VU##MI_ITOF0, dis##VU##MI_FTOI0, dis##VU##MI_MULAx , dis##VU##MI_MULAq , \ + dis##VU##MI_ADDAq, dis##VU##MI_SUBAq, dis##VU##MI_ADDA , dis##VU##MI_SUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_01_TABLE[32] = { \ + dis##VU##MI_ADDAy , dis##VU##MI_SUBy , dis##VU##MI_MADDAy, dis##VU##MI_MSUBAy, \ + dis##VU##MI_ITOF4 , dis##VU##MI_FTOI4 , dis##VU##MI_MULAy , dis##VU##MI_ABS , \ + dis##VU##MI_MADDAq, dis##VU##MI_MSUBAq, dis##VU##MI_MADDA , dis##VU##MI_MSUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_10_TABLE[32] = { \ + dis##VU##MI_ADDAz , dis##VU##MI_SUBz , dis##VU##MI_MADDAz, dis##VU##MI_MSUBAz, \ + dis##VU##MI_ITOF12, dis##VU##MI_FTOI12, dis##VU##MI_MULAz , dis##VU##MI_MULAi , \ + dis##VU##MI_MADDAi, dis##VU##MI_SUBAi , dis##VU##MI_MULA , dis##VU##MI_OPMULA, \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_11_TABLE[32] = { \ + dis##VU##MI_ADDAw , dis##VU##MI_SUBw , dis##VU##MI_MADDAw, dis##VU##MI_MSUBAw, \ + dis##VU##MI_ITOF15, dis##VU##MI_FTOI15, dis##VU##MI_MULAw , dis##VU##MI_CLIP , \ + dis##VU##MI_MADDAi, dis##VU##MI_MSUBAi, disNULL , dis##VU##MI_NOP , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +MakeDisF(dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_00_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_01_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_10_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_11, dis##VU##_UPPER_FD_11_TABLE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroU[] = { \ + dis##VU##MI_ADDx , dis##VU##MI_ADDy , dis##VU##MI_ADDz , dis##VU##MI_ADDw, \ + dis##VU##MI_SUBx , dis##VU##MI_SUBy , dis##VU##MI_SUBz , dis##VU##MI_SUBw, \ + dis##VU##MI_MADDx , dis##VU##MI_MADDy , dis##VU##MI_MADDz , dis##VU##MI_MADDw, \ + dis##VU##MI_MSUBx , dis##VU##MI_MSUBy , dis##VU##MI_MSUBz , dis##VU##MI_MSUBw, \ + dis##VU##MI_MAXx , dis##VU##MI_MAXy , dis##VU##MI_MAXz , dis##VU##MI_MAXw, /* 0x10 */ \ + dis##VU##MI_MINIx , dis##VU##MI_MINIy , dis##VU##MI_MINIz , dis##VU##MI_MINIw, \ + dis##VU##MI_MULx , dis##VU##MI_MULy , dis##VU##MI_MULz , dis##VU##MI_MULw, \ + dis##VU##MI_MULq , dis##VU##MI_MAXi , dis##VU##MI_MULi , dis##VU##MI_MINIi, \ + dis##VU##MI_ADDq , dis##VU##MI_MADDq , dis##VU##MI_ADDi , dis##VU##MI_MADDi, /* 0x20 */ \ + dis##VU##MI_SUBq , dis##VU##MI_MSUBq , dis##VU##MI_SUBi , dis##VU##MI_MSUBi, \ + dis##VU##MI_ADD , dis##VU##MI_MADD , dis##VU##MI_MUL , dis##VU##MI_MAX, \ + dis##VU##MI_SUB , dis##VU##MI_MSUB , dis##VU##MI_OPMSUB, dis##VU##MI_MINI, \ + disNULL , disNULL , disNULL , disNULL , /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_11, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroUF, dis##VU##MicroU[code & 0x3f] DisFInterfaceN) \ + diff --git a/branches/pcsx2_0.9.2/DebugTools/DisVUops.h b/branches/pcsx2_0.9.2/DebugTools/DisVUops.h new file mode 100644 index 0000000..40cf978 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/DisVUops.h @@ -0,0 +1,197 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUOpcodes(VU) \ + \ +/*****************/ \ +/* LOWER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_DIV, dName("DIV"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_SQRT, dName("SQRT"); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_RSQRT, dName("RSQRT"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_IADDI, dName("IADDI"); dCP232i(_Ft_); dCP232i(_Fs_); dImm5();) \ +MakeDisF(dis##VU##MI_IADDIU, dName("IADDIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_IADD, dName("IADD"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IAND, dName("IAND"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IOR, dName("IOR"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUB, dName("ISUB"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUBIU, dName("ISUBIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_MOVE, if (_Fs_ == 0 && _Ft_ == 0) { dNameU("NOP"); } else { dNameU("MOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_); }) \ +MakeDisF(dis##VU##MI_MFIR, dNameU("MFIR"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_MTIR, dNameU("MTIR"); dCP232i(_Ft_); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_MR32, dNameU("MR32"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_LQ, dNameU("LQ"); dCP2128f(_Ft_); dCP232i(_Fs_); dImm11();) \ +MakeDisF(dis##VU##MI_LQD, dNameU("LQD"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LQI, dNameU("LQI"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_SQ, dNameU("SQ"); dCP2128f(_Fs_); dCP232i(_Ft_); dImm11(); ) \ +MakeDisF(dis##VU##MI_SQD, dNameU("SQD"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_SQI, dNameU("SQI"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ILW, dNameU("ILW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISW, dNameU("ISW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ILWR, dNameU("ILWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISWR, dNameU("ISWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LOI, dName("LOI"); ) \ +MakeDisF(dis##VU##MI_RINIT, dNameU("RINIT"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_RGET, dNameU("RGET"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RNEXT, dNameU("RNEXT"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RXOR, dNameU("RXOR"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_WAITQ, dName("WAITQ"); ) \ +MakeDisF(dis##VU##MI_FSAND, dName("FSAND"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff); ) \ +MakeDisF(dis##VU##MI_FSEQ, dName("FSEQ"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSOR, dName("FSOR"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSSET, dName("FSSET"); dCP232i(REG_STATUS_FLAG);) \ +MakeDisF(dis##VU##MI_FMAND, dName("FMAND"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMEQ, dName("FMEQ"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMOR, dName("FMOR"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FCAND, dName("FCAND"); dCP232i(1); sprintf(ostr, "%s %8.8x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCEQ, dName("FCEQ"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCOR, dName("FCOR"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCSET, dName("FCSET"); dCP232i(REG_CLIP_FLAG); sprintf(ostr, "%s %.6x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCGET, dName("FCGET"); dCP232i(_Ft_); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_IBEQ, dName("IBEQ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGEZ, dName("IBEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGTZ, dName("IBGTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLEZ, dName("IBLEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLTZ, dName("IBLTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBNE, dName("IBNE"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_B, dName("B"); dImm11();) \ +MakeDisF(dis##VU##MI_BAL, dName("BAL"); dImm11(); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_JR, dName("JR"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_JALR, dName("JALR"); dCP232i(_Ft_); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_MFP, dNameU("MFP"); dCP2128f(_Ft_); dCP232i(REG_P);) \ +MakeDisF(dis##VU##MI_WAITP, dName("WAITP"); ) \ +MakeDisF(dis##VU##MI_ESADD, dName("ESADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ERSADD, dName("ERSADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ELENG, dName("ELENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERLENG, dName("ERLENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_EATANxy, dName("EATANxy"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_EATANxz, dName("EATANxz"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ESUM, dName("ESUM"); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERCPR, dName("ERCPR"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESQRT, dName("ESQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ERSQRT, dName("ERSQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESIN, dName("ESIN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EATAN, dName("EATAN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EEXP, dName("EEXP"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_XITOP, dName("XITOP"); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_XGKICK, dName("XGKICK"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_XTOP, dName("XTOP"); dCP232i(_Ft_);) \ + \ + \ +/*****************/ \ +/* UPPER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_ABS, dNameU("ABS"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ADD, dNameU("ADD"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDi, dNameU("ADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDq, dNameU("ADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDx, dNameU("ADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDy, dNameU("ADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDz, dNameU("ADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDw, dNameU("ADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDA, dNameU("ADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAi, dNameU("ADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDAq, dNameU("ADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDAx, dNameU("ADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAy, dNameU("ADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAz, dNameU("ADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAw, dNameU("ADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUB, dNameU("SUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBi, dNameU("SUBi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBq, dNameU("SUBq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBx, dNameU("SUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBy, dNameU("SUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBz, dNameU("SUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBw, dNameU("SUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBA, dNameU("SUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAi, dNameU("SUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBAq, dNameU("SUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBAx, dNameU("SUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAy, dNameU("SUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAz, dNameU("SUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAw, dNameU("SUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MUL, dNameU("MUL"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULi, dNameU("MULi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULq, dNameU("MULq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULx, dNameU("MULx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULy, dNameU("MULy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULz, dNameU("MULz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULw, dNameU("MULw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MULA, dNameU("MULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAi, dNameU("MULAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULAq, dNameU("MULAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULAx, dNameU("MULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAy, dNameU("MULAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAz, dNameU("MULAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAw, dNameU("MULAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADD, dNameU("MADD"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDi, dNameU("MADDi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDq, dNameU("MADDq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDx, dNameU("MADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDy, dNameU("MADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDz, dNameU("MADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDw, dNameU("MADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDA, dNameU("MADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAi, dNameU("MADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDAq, dNameU("MADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDAx, dNameU("MADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAy, dNameU("MADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAz, dNameU("MADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAw, dNameU("MADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUB, dNameU("MSUB"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBi, dNameU("MSUBi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBq, dNameU("MSUBq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBx, dNameU("MSUBx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBy, dNameU("MSUBy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBz, dNameU("MSUBz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBw, dNameU("MSUBw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBA, dNameU("MSUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAi, dNameU("MSUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBAq, dNameU("MSUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBAx, dNameU("MSUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAy, dNameU("MSUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAz, dNameU("MSUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAw, dNameU("MSUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MAX, dNameU("MAX"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXi, dNameU("MAXi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MAXx, dNameU("MAXx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXy, dNameU("MAXy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXz, dNameU("MAXz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXw, dNameU("MAXw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MINI, dNameU("MINI"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIi, dNameU("MINIi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MINIx, dNameU("MINIx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIy, dNameU("MINIy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIz, dNameU("MINIz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIw, dNameU("MINIw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMULA, dNameU("OPMULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMSUB, dNameU("OPMSUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_NOP, dName("NOP");) \ +MakeDisF(dis##VU##MI_FTOI0, dNameU("FTOI0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI4, dNameU("FTOI4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI12, dNameU("FTOI12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI15, dNameU("FTOI15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF0, dNameU("ITOF0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF4, dNameU("ITOF4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF12, dNameU("ITOF12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF15, dNameU("ITOF15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_CLIP, dNameU("CLIP"); dCP2128f(_Fs_); dCP232w(_Ft_);) \ + diff --git a/branches/pcsx2_0.9.2/DebugTools/Makefile.am b/branches/pcsx2_0.9.2/DebugTools/Makefile.am new file mode 100644 index 0000000..ef228f6 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I../ +noinst_LIBRARIES = libDebugTools.a + +libDebugTools_a_SOURCES = \ +cpuopsDebug.c Debug.h.bak DisR3000asm.c DisVU0Micro.c DisVUops.h \ +cpuopsDebug.h DisASM.h DisR5900asm.c DisVU1Micro.c \ +Debug.h DisR3000A.c DisR5900.c DisVUmicro.h diff --git a/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.c b/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.c new file mode 100644 index 0000000..99d6baf --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.c @@ -0,0 +1,1063 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "cpuopsDebug.h" + +void UpdateR5900op() +{ + FILE *fp; + fp=fopen("cpuops.txt", "wt"); + fprintf(fp, "------------\n"); + fprintf(fp, "--R5900ops--\n"); + fprintf(fp, "------------\n"); + if(L_ADD>0) fprintf(fp, "Add %d\n", L_ADD); + if(L_ADDI>0) fprintf(fp, "Addi %d\n", L_ADDI); + if(L_ADDIU>0) fprintf(fp, "Addiu %d\n", L_ADDIU); + if(L_ADDU>0) fprintf(fp, "Addu %d\n", L_ADDU); + if(L_AND>0) fprintf(fp, "And %d\n", L_AND); + if(L_ANDI>0) fprintf(fp, "Andi %d\n", L_ANDI); + if(L_BEQ>0) fprintf(fp, "Beq %d\n", L_BEQ); + if(L_BEQL>0) fprintf(fp, "Beql %d\n", L_BEQL); + if(L_BGEZ>0) fprintf(fp, "Bgez %d\n", L_BGEZ); + if(L_BGEZAL>0) fprintf(fp, "Bgezal %d\n", L_BGEZAL); + if(L_BGEZALL>0) fprintf(fp, "Bgezall %d\n", L_BGEZALL); + if(L_BGEZL>0) fprintf(fp, "Bgezl %d\n", L_BGEZL); + if( L_BGTZ>0) fprintf(fp, "Bgtz %d\n", L_BGTZ); + if( L_BGTZL>0) fprintf(fp, "Bgtzl %d\n", L_BGTZL); + if(L_BLEZ>0) fprintf(fp, "Blez %d\n", L_BLEZ); + if(L_BLEZL>0) fprintf(fp, "blezl %d\n", L_BLEZL); + if(L_BLTZ>0) fprintf(fp, "bltz %d\n", L_BLTZ); + if(L_BLTZAL>0) fprintf(fp, "bltzal %d\n", L_BLTZAL); + if(L_BLTZALL>0) fprintf(fp, "bltzall %d\n", L_BLTZALL); + if(L_BLTZL>0) fprintf(fp, "bltzl %d\n", L_BLTZL); + if(L_BNE>0) fprintf(fp, "bne %d\n", L_BNE); + if(L_BNEL>0) fprintf(fp, "bnel %d\n", L_BNEL); + if(L_BREAK>0) fprintf(fp, "break %d\n", L_BREAK); + if(L_CACHE>0) fprintf(fp, "cache %d\n", L_CACHE); + if(L_DADD>0) fprintf(fp, "dadd %d\n", L_DADD); + if(L_DADDI>0) fprintf(fp, "daddi %d\n", L_DADDI); + if(L_DADDIU>0) fprintf(fp, "daddiu %d\n", L_DADDIU); + if(L_DADDU>0) fprintf(fp, "daddu %d\n", L_DADDU); + if(L_DIV>0) fprintf(fp, "div %d\n", L_DIV); + if(L_DIVU>0) fprintf(fp, "divu %d\n", L_DIVU); + if(L_DSLL>0) fprintf(fp, "dsll %d\n", L_DSLL); + if(L_DSLL32>0) fprintf(fp, "dsll32 %d\n", L_DSLL32); + if(L_DSLLV>0) fprintf(fp, "dsllv %d\n", L_DSLLV); + if(L_DSRA>0) fprintf(fp, "dsra %d\n", L_DSRA); + if(L_DSRA32>0) fprintf(fp, "dsra32 %d\n", L_DSRA32); + if(L_DSRAV>0) fprintf(fp, "dsrav %d\n", L_DSRAV); + if(L_DSRL>0) fprintf(fp, "dsrl %d\n", L_DSRL); + if(L_DSRL32>0) fprintf(fp, "dsr32 %d\n", L_DSRL32); + if(L_DSRLV>0) fprintf(fp, "dsrlv %d\n", L_DSRLV); + if(L_DSUB>0) fprintf(fp, "dsub %d\n", L_DSUB); + if(L_DSUBU>0) fprintf(fp, "dsubu %d\n", L_DSUBU); + if(L_J>0) fprintf(fp, "j %d\n", L_J); + if(L_JAL>0) fprintf(fp, "jal %d\n", L_JAL); + if(L_JALR>0) fprintf(fp, "jalr %d\n", L_JALR); + if(L_JR>0) fprintf(fp, "jr %d\n", L_JR); + if(L_LB>0) fprintf(fp, "lb %d\n", L_LB); + if(L_LBU>0) fprintf(fp, "lbu %d\n", L_LBU); + if(L_LD>0) fprintf(fp, "ld %d\n", L_LD); + if(L_LDL>0) fprintf(fp, "ldl %d\n", L_LDL); + if(L_LDR>0) fprintf(fp, "ldr %d\n", L_LDR); + if(L_LH>0) fprintf(fp, "lh %d\n", L_LH); + if(L_LHU>0) fprintf(fp, "lhu %d\n", L_LHU); + if(L_LQ>0) fprintf(fp, "lq %d\n", L_LQ); + if(L_LUI>0) fprintf(fp, "lui %d\n", L_LUI); + if(L_LW>0) fprintf(fp, "lw %d\n", L_LW); + if(L_LWL>0) fprintf(fp, "lwl %d\n", L_LWL); + if(L_LWR>0) fprintf(fp, "lwr %d\n", L_LWR); + if(L_LWU>0) fprintf(fp, "lwu %d\n", L_LWU); + if(L_MFHI>0) fprintf(fp, "mfhi %d\n", L_MFHI); + if(L_MFLO>0) fprintf(fp, "mflo %d\n", L_MFLO); + if(L_MFSA>0) fprintf(fp, "mfsa %d\n", L_MFSA); + if(L_MOVN>0) fprintf(fp, "movn %d\n", L_MOVN); + if(L_MOVZ>0) fprintf(fp, "movz %d\n", L_MOVZ); + if(L_MTHI>0) fprintf(fp, "mthi %d\n", L_MTHI); + if(L_MTLO>0) fprintf(fp, "mtlo %d\n", L_MTLO); + if(L_MTSA>0) fprintf(fp, "mtsa %d\n", L_MTSA); + if(L_MTSAB>0) fprintf(fp, "mtsab %d\n", L_MTSAB); + if(L_MTSAH>0) fprintf(fp, "mtsah %d\n", L_MTSAH); + if(L_MULT>0) fprintf(fp, "mult %d\n", L_MULT); + if(L_MULTU>0) fprintf(fp, "multu %d\n", L_MULTU); + if(L_NOR>0) fprintf(fp, "nor %d\n", L_NOR); + if(L_OR>0) fprintf(fp, "or %d\n", L_OR); + if(L_ORI>0) fprintf(fp, "ori %d\n", L_ORI); + if(L_PREF>0) fprintf(fp, "pref %d\n", L_PREF); + if(L_SB>0) fprintf(fp, "sb %d\n", L_SB); + if(L_SD>0) fprintf(fp, "sd %d\n", L_SD); + if(L_SDL>0) fprintf(fp, "sdl %d\n", L_SDL); + if(L_SDR>0) fprintf(fp, "sdr %d\n", L_SDR); + if(L_SH>0) fprintf(fp, "sh %d\n", L_SH); + if(L_SLL>0) fprintf(fp, "sll %d\n", L_SLL); + if(L_SLLV>0) fprintf(fp, "sllv %d\n", L_SLLV); + if(L_SLT>0) fprintf(fp, "slt %d\n", L_SLT); + if(L_SLTI>0) fprintf(fp, "slti %d\n", L_SLTI); + if(L_SLTIU>0) fprintf(fp, "sltiu %d\n", L_SLTIU); + if(L_SLTU>0) fprintf(fp, "sltu %d\n", L_SLTU); + if(L_SQ>0) fprintf(fp, "sq %d\n", L_SQ); + if(L_SRA>0) fprintf(fp, "sra %d\n", L_SRA); + if(L_SRAV>0) fprintf(fp, "srav %d\n", L_SRAV); + if(L_SRL>0) fprintf(fp, "srl %d\n", L_SRL); + if(L_SRLV>0) fprintf(fp, "srlv %d\n", L_SRLV); + if(L_SUB>0) fprintf(fp, "sub %d\n", L_SUB); + if(L_SUBU>0) fprintf(fp, "subu %d\n", L_SUBU); + if(L_SW>0) fprintf(fp, "sw %d\n", L_SW); + if(L_SWL>0) fprintf(fp, "swl %d\n", L_SWL); + if(L_SWR>0) fprintf(fp, "swr %d\n", L_SWR); + if(L_SYNC>0) fprintf(fp, "sync %d\n", L_SYNC); + if(L_SYSCALL>0) fprintf(fp, "syscall %d\n", L_SYSCALL); + if(L_TEQ>0) fprintf(fp, "teq %d\n", L_TEQ); + if(L_TEQI>0) fprintf(fp, "teqi %d\n", L_TEQI); + if(L_TGE>0) fprintf(fp, "tge %d\n", L_TGE); + if(L_TGEI>0) fprintf(fp, "tgei %d\n", L_TGEI); + if(L_TGEIU>0) fprintf(fp, "tgeiu %d\n", L_TGEIU); + if(L_TGEU>0) fprintf(fp, "tgeu %d\n", L_TGEU); + if(L_TLT>0) fprintf(fp, "tlt %d\n", L_TLT); + if(L_TLTI>0) fprintf(fp, "tlti %d\n", L_TLTI); + if(L_TLTIU>0) fprintf(fp, "tltiu %d\n", L_TLTIU); + if(L_TLTU>0) fprintf(fp, "tltu %d\n", L_TLTU); + if(L_TNE>0) fprintf(fp, "tne %d\n", L_TNE); + if(L_TNEI>0) fprintf(fp, "tnei %d\n", L_TNEI); + if(L_XOR>0) fprintf(fp, "xor %d\n", L_XOR); + if(L_XORI>0) fprintf(fp, "xori %d\n", L_XORI); + fprintf(fp, "------------\n"); + fprintf(fp, "--MMI ops--\n"); + fprintf(fp, "------------\n"); + if(L_DIV1>0) fprintf(fp, "div1 %d\n", L_DIV1); + if(L_DIVU1>0) fprintf(fp, "divu1 %d\n", L_DIVU1); + if(L_MADD>0) fprintf(fp, "madd %d\n", L_MADD); + if(L_MADD1>0) fprintf(fp, "madd1 %d\n", L_MADD1); + if(L_MADDU>0) fprintf(fp, "maddu %d\n", L_MADDU); + if(L_MADDU1>0) fprintf(fp, "maddu1 %d\n", L_MADDU1); + if(L_MFHI1>0) fprintf(fp, "mfhi1 %d\n", L_MFHI1); + if(L_MFLO1>0) fprintf(fp, "mflo1 %d\n", L_MFLO1); + if(L_MTHI1>0) fprintf(fp, "mthi1 %d\n", L_MTHI1); + if(L_MTLO1>0) fprintf(fp, "mtlo1 %d\n", L_MTLO1); + if(L_MULT1>0) fprintf(fp, "mult1 %d\n", L_MULT1); + if(L_MULTU1>0) fprintf(fp, "multu1 %d\n", L_MULTU1); + if(L_PABSH>0) fprintf(fp, "pabsh %d\n", L_PABSH); + if(L_PABSW>0) fprintf(fp, "pabsw %d\n", L_PABSW); + if(L_PADDB>0) fprintf(fp, "paddb %d\n", L_PADDB); + if(L_PADDH>0) fprintf(fp, "paddh %d\n", L_PADDH); + if(L_PADDSB>0) fprintf(fp, "paddsb %d\n", L_PADDSB); + if(L_PADDSH>0) fprintf(fp, "paddsh %d\n", L_PADDSH); + if(L_PADDSW>0) fprintf(fp, "paddsw %d\n", L_PADDSW); + if(L_PADDUB>0) fprintf(fp, "paddub %d\n", L_PADDUB); + if(L_PADDUH>0) fprintf(fp, "padduh %d\n", L_PADDUH); + if(L_PADDUW>0) fprintf(fp, "padduw %d\n", L_PADDUW); + if(L_PADDW>0) fprintf(fp, "paddw %d\n", L_PADDW); + if(L_PADSBH>0) fprintf(fp, "padsbh %d\n", L_PADSBH); + if(L_PAND>0) fprintf(fp, "pand %d\n", L_PAND); + if(L_PCEQB>0) fprintf(fp, "pceqb %d\n", L_PCEQB); + if(L_PCEQH>0) fprintf(fp, "pceqh %d\n", L_PCEQH); + if(L_PCEQW>0) fprintf(fp, "pceqw %d\n", L_PCEQW); + if(L_PCGTB>0) fprintf(fp, "pcgtb %d\n", L_PCGTB); + if(L_PCGTH>0) fprintf(fp, "pcgth %d\n", L_PCGTH); + if(L_PCGTW>0) fprintf(fp, "pcgtw %d\n", L_PCGTW); + if(L_PCPYH>0) fprintf(fp, "pcpyh %d\n", L_PCPYH); + if(L_PCPYLD>0) fprintf(fp, "pcpyld %d\n", L_PCPYLD); + if(L_PCPYUD>0) fprintf(fp, "pcpyud %d\n", L_PCPYUD); + if(L_PDIVBW>0) fprintf(fp, "pdivbw %d\n", L_PDIVBW); + if(L_PDIVUW>0) fprintf(fp, "pdivuw %d\n", L_PDIVUW); + if(L_PDIVW>0) fprintf(fp, "pdivw %d\n", L_PDIVW); + if(L_PEXCH>0) fprintf(fp, "pexch %d\n", L_PEXCH); + if(L_PEXCW>0) fprintf(fp, "pexcw %d\n", L_PEXCW); + if(L_PEXEH>0) fprintf(fp, "pexeh %d\n", L_PEXEH); + if(L_PEXEW>0) fprintf(fp, "pexew %d\n", L_PEXEW); + if(L_PEXT5>0) fprintf(fp, "pext5 %d\n", L_PEXT5); + if(L_PEXTLB>0) fprintf(fp, "pextlb %d\n", L_PEXTLB); + if(L_PEXTLH>0) fprintf(fp, "pextlh %d\n", L_PEXTLH); + if(L_PEXTLW>0) fprintf(fp, "pextlw %d\n", L_PEXTLW); + if(L_PEXTUB>0) fprintf(fp, "pextub %d\n", L_PEXTUB); + if(L_PEXTUH>0) fprintf(fp, "pextuh %d\n", L_PEXTUH); + if(L_PEXTUW>0) fprintf(fp, "pextuw %d\n", L_PEXTUW); + if(L_PHMADH>0) fprintf(fp, "phmadh %d\n", L_PHMADH); + if(L_PHMSBH>0) fprintf(fp, "phmsbh %d\n", L_PHMSBH); + if(L_PINTEH>0) fprintf(fp, "pinteh %d\n", L_PINTEH); + if(L_PINTH>0) fprintf(fp, "pinth %d\n", L_PINTH); + if(L_PLZCW>0) fprintf(fp, "plzcw %d\n", L_PLZCW); + if(L_PMADDH>0) fprintf(fp, "pmaddh %d\n", L_PMADDH); + if(L_PMADDUW>0) fprintf(fp, "pmadduw %d\n", L_PMADDUW); + if(L_PMADDW>0) fprintf(fp, "pmaddw %d\n", L_PMADDW); + if(L_PMAXH>0) fprintf(fp, "pmaxh %d\n", L_PMAXH); + if(L_PMAXW>0) fprintf(fp, "pmaxw %d\n", L_PMAXW); + if(L_PMFHI>0) fprintf(fp, "pmfhi %d\n", L_PMFHI); + if(L_PMFHL>0) fprintf(fp, "pmfhl %d\n", L_PMFHL); + if(L_PMFLO>0) fprintf(fp, "pmflo %d\n", L_PMFLO); + if(L_PMINH>0) fprintf(fp, "pminh %d\n", L_PMINH); + if(L_PMINW>0) fprintf(fp, "pminw %d\n", L_PMINW); + if(L_PMSUBH>0) fprintf(fp, "pmsubh %d\n", L_PMSUBH); + if(L_PMSUBW>0) fprintf(fp, "pmsubw %d\n", L_PMSUBW); + if(L_PMTHI>0) fprintf(fp, "pmthi %d\n", L_PMTHI); + if(L_PMTHL>0) fprintf(fp, "pmthl %d\n", L_PMTHL); + if(L_PMTLO>0) fprintf(fp, "pmtlo %d\n", L_PMTLO); + if(L_PMULTH>0) fprintf(fp, "pmulth %d\n", L_PMULTH); + if(L_PMULTUW>0) fprintf(fp, "pmultuw %d\n", L_PMULTUW); + if(L_PMULTW>0) fprintf(fp, "pmultw %d\n", L_PMULTW); + if(L_PNOR>0) fprintf(fp, "pnor %d\n", L_PNOR); + if(L_POR>0) fprintf(fp, "por %d\n", L_POR); + if(L_PPAC5>0) fprintf(fp, "ppac5 %d\n", L_PPAC5); + if(L_PPACB>0) fprintf(fp, "ppacb %d\n", L_PPACB); + if(L_PPACH>0) fprintf(fp, "ppach %d\n", L_PPACH); + if(L_PPACW>0) fprintf(fp, "ppacw %d\n", L_PPACW); + if(L_PREVH>0) fprintf(fp, "prevh %d\n", L_PREVH); + if(L_PROT3W>0) fprintf(fp, "prot3w %d\n", L_PROT3W); + if(L_PSLLH>0) fprintf(fp, "psllh %d\n", L_PSLLH); + if(L_PSLLVW>0) fprintf(fp, "psllvw %d\n", L_PSLLVW); + if(L_PSLLW>0) fprintf(fp, "psllw %d\n", L_PSLLW); + if(L_PSRAH>0) fprintf(fp, "psrah %d\n", L_PSRAH); + if(L_PSRAVW>0) fprintf(fp, "psravw %d\n", L_PSRAVW); + if(L_PSRAW>0) fprintf(fp, "psraw %d\n", L_PSRAW); + if(L_PSRLH>0) fprintf(fp, "psrlh %d\n", L_PSRLH); + if(L_PSRLVW>0) fprintf(fp, "psrlvw %d\n", L_PSRLVW); + if(L_PSRLW>0) fprintf(fp, "psrlw %d\n", L_PSRLW); + if(L_PSUBB>0) fprintf(fp, "psubb %d\n", L_PSUBB); + if(L_PSUBH>0) fprintf(fp, "psubh %d\n", L_PSUBH); + if(L_PSUBSB>0) fprintf(fp, "psubsb %d\n", L_PSUBSB); + if(L_PSUBSH>0) fprintf(fp, "psubsh %d\n", L_PSUBSH); + if(L_PSUBSW>0) fprintf(fp, "psubsw %d\n", L_PSUBSW); + if(L_PSUBUB>0) fprintf(fp, "psubub %d\n", L_PSUBUB); + if(L_PSUBUH>0) fprintf(fp, "psubuh %d\n", L_PSUBUH); + if(L_PSUBUW>0) fprintf(fp, "psubuw %d\n", L_PSUBUW); + if(L_PSUBW>0) fprintf(fp, "psubw %d\n", L_PSUBW); + if(L_PXOR>0) fprintf(fp, "pxor %d\n", L_PXOR); + if(L_QFSRV>0) fprintf(fp, "qfsrv %d\n", L_QFSRV); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP0 ops--\n"); + fprintf(fp, "------------\n"); + if(L_BC0F>0) fprintf(fp, "bc0f %d\n", L_BC0F); + if(L_BC0FL>0) fprintf(fp, "bc0fl %d\n", L_BC0FL); + if(L_BC0T>0) fprintf(fp, "bc0t %d\n", L_BC0T); + if(L_BC0TL>0) fprintf(fp, "bc0tl %d\n", L_BC0TL); + if(L_DI>0) fprintf(fp, "di %d\n", L_DI); + if(L_EI>0) fprintf(fp, "ei %d\n", L_EI); + if(L_ERET>0) fprintf(fp, "eret %d\n", L_ERET); + if(L_MTC0>0) fprintf(fp, "mtc0 %d\n", L_MTC0); + if(L_TLBP>0) fprintf(fp, "tlbp %d\n", L_TLBP); + if(L_TLBR>0) fprintf(fp, "tlbr %d\n", L_TLBR); + if(L_TLBWI>0) fprintf(fp, "tlbwi %d\n", L_TLBWI); + if(L_TLBWR>0) fprintf(fp, "tlbwr %d\n", L_TLBWR); + if(L_MFC0>0) fprintf(fp, "mfc0 %d\n", L_MFC0); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP1 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LWC1>0) fprintf(fp, "lwc1 %d\n", L_LWC1); + if(L_SWC1>0) fprintf(fp, "swc1 %d\n", L_SWC1); + if(L_ABS_S>0) fprintf(fp, "abs_s %d\n", L_ABS_S); + if(L_ADD_S>0) fprintf(fp, "add_s %d\n", L_ADD_S); + if(L_ADDA_S>0) fprintf(fp, "adda_s %d\n", L_ADDA_S); + if(L_BC1F>0) fprintf(fp, "bc1f %d\n", L_BC1F); + if(L_BC1FL>0) fprintf(fp, "bc1fl %d\n", L_BC1FL); + if(L_BC1T>0) fprintf(fp, "bc1t %d\n", L_BC1T); + if(L_BC1TL>0) fprintf(fp, "bc1tl %d\n", L_BC1TL); + if(L_C_EQ>0) fprintf(fp, "c_eq %d\n", L_C_EQ); + if(L_C_F>0) fprintf(fp, "c_f %d\n", L_C_F); + if(L_C_LE>0) fprintf(fp, "c_le %d\n", L_C_LE); + if(L_C_LT>0) fprintf(fp, "c_lt %d\n", L_C_LT); + if(L_CFC1>0) fprintf(fp, "cfc1 %d\n", L_CFC1); + if(L_CTC1>0) fprintf(fp, "ctc1 %d\n", L_CTC1); + if(L_CVT_S>0) fprintf(fp, "cvt_s %d\n", L_CVT_S); + if(L_CVT_W>0) fprintf(fp, "cvt_w %d\n", L_CVT_W); + if(L_DIV_S>0) fprintf(fp, "div_s %d\n", L_DIV_S); + if(L_MADD_S>0) fprintf(fp, "madd_s %d\n", L_MADD_S); + if(L_MADDA_S>0) fprintf(fp, "madda_s %d\n", L_MADDA_S); + if(L_MAX_S>0) fprintf(fp, "max_s %d\n", L_MAX_S); + if(L_MFC1>0) fprintf(fp, "mfc1 %d\n", L_MFC1); + if(L_MIN_S>0) fprintf(fp, "min_s %d\n", L_MIN_S); + if(L_MOV_S>0) fprintf(fp, "mov_s %d\n", L_MOV_S); + if(L_MSUB_S>0) fprintf(fp, "msub_s %d\n", L_MSUB_S); + if(L_MSUBA_S>0) fprintf(fp, "msuba_s %d\n", L_MSUBA_S); + if(L_MTC1>0) fprintf(fp, "mtc1 %d\n", L_MTC1); + if(L_MUL_S>0) fprintf(fp, "mul_s %d\n", L_MUL_S); + if(L_MULA_S>0) fprintf(fp, "mula_s %d\n", L_MULA_S); + if(L_NEG_S>0) fprintf(fp, "neg_s %d\n", L_NEG_S); + if(L_RSQRT_S>0) fprintf(fp, "rsqrt_s %d\n", L_RSQRT_S); + if(L_SQRT_S>0) fprintf(fp, "sqrt_s %d\n", L_SQRT_S); + if(L_SUB_S>0) fprintf(fp, "sub_s %d\n", L_SUB_S); + if(L_SUBA_S>0) fprintf(fp, "suba_s %d\n", L_SUBA_S); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP2 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LQC2>0) fprintf(fp, "lqc2 %d\n", L_LQC2); + if(L_SQC2>0) fprintf(fp, "sqc2 %d\n", L_SQC2); + if(L_BC2F>0) fprintf(fp, "bc2f %d\n", L_BC2F); + if(L_BC2FL>0) fprintf(fp, "bc2fl %d\n", L_BC2FL); + if(L_BC2T>0) fprintf(fp, "bc2t %d\n", L_BC2T); + if(L_BC2TL>0) fprintf(fp, "bc2tl %d\n", L_BC2TL); + if(L_CFC2>0) fprintf(fp, "cfc2 %d\n", L_CFC2); + if(L_CTC2>0) fprintf(fp, "ctc2 %d\n", L_CTC2); + if(L_QMFC2>0) fprintf(fp, "qmfc2 %d\n", L_QMFC2); + if(L_QMTC2>0) fprintf(fp, "qmtc2 %d\n", L_QMTC2); + if(L_VABS>0) fprintf(fp, "vabs %d\n", L_VABS); + if(L_VADD>0) fprintf(fp, "vadd %d\n", L_VADD); + if(L_VADDA>0) fprintf(fp, "vadda %d\n", L_VADDA); + if(L_VADDAi>0) fprintf(fp, "vaddai %d\n", L_VADDAi); + if(L_VADDAq>0) fprintf(fp, "vaddaq %d\n", L_VADDAq); + if(L_VADDAw>0) fprintf(fp, "vaddaw %d\n", L_VADDAw); + if(L_VADDAx>0) fprintf(fp, "vaddax %d\n", L_VADDAx); + if(L_VADDAy>0) fprintf(fp, "vadday %d\n", L_VADDAy); + if(L_VADDAz>0) fprintf(fp, "vaddaz %d\n", L_VADDAz); + if(L_VADDi>0) fprintf(fp, "vaddi %d\n", L_VADDi); + if(L_VADDq>0) fprintf(fp, "vaddq %d\n", L_VADDq); + if(L_VADDw>0) fprintf(fp, "vaddw %d\n", L_VADDw); + if(L_VADDx>0) fprintf(fp, "vaddx %d\n", L_VADDx); + if(L_VADDy>0) fprintf(fp, "vaddy %d\n", L_VADDy); + if(L_VADDz>0) fprintf(fp, "vaddz %d\n", L_VADDz); + if(L_VCALLMS>0) fprintf(fp, "vcallms %d\n", L_VCALLMS); + if(L_VCALLMSR>0) fprintf(fp, "vcallmsr %d\n", L_VCALLMSR); + if(L_VCLIPw>0) fprintf(fp, "vclip %d\n", L_VCLIPw); + if(L_VDIV>0) fprintf(fp, "vdiv %d\n", L_VDIV); + if(L_VFTOI0>0) fprintf(fp, "vftoi0 %d\n", L_VFTOI0); + if(L_VFTOI12>0) fprintf(fp, "vftoi12 %d\n", L_VFTOI12); + if(L_VFTOI15>0) fprintf(fp, "vftoi15 %d\n", L_VFTOI15); + if(L_VFTOI4>0) fprintf(fp, "vftoi14 %d\n", L_VFTOI4); + if(L_VIADD>0) fprintf(fp, "viadd %d\n", L_VIADD); + if(L_VIADDI>0) fprintf(fp, "viaddi %d\n", L_VIADDI); + if(L_VIAND>0) fprintf(fp, "viand %d\n", L_VIAND); + if(L_VILWR>0) fprintf(fp, "vilwr %d\n", L_VILWR); + if(L_VIOR>0) fprintf(fp, "vior %d\n", L_VIOR); + if(L_VISUB>0) fprintf(fp, "visub %d\n", L_VISUB); + if(L_VISWR>0) fprintf(fp, "viswr %d\n", L_VISWR); + if(L_VITOF0>0) fprintf(fp, "vitof0 %d\n", L_VITOF0); + if(L_VITOF12>0) fprintf(fp, "vitof12 %d\n", L_VITOF12); + if(L_VITOF15>0) fprintf(fp, "vitof15 %d\n", L_VITOF15); + if(L_VITOF4>0) fprintf(fp, "vitof4 %d\n", L_VITOF4); + if(L_VLQD>0) fprintf(fp, "vlqd %d\n", L_VLQD); + if(L_VLQI>0) fprintf(fp, "vlqi %d\n", L_VLQI); + if(L_VMADD>0) fprintf(fp, "vmadd %d\n", L_VMADD); + if(L_VMADDA>0) fprintf(fp, "vmadda %d\n", L_VMADDA); + if(L_VMADDAi>0) fprintf(fp, "vmaddai %d\n", L_VMADDAi); + if(L_VMADDAq>0) fprintf(fp, "vmaddaq %d\n", L_VMADDAq); + if(L_VMADDAw>0) fprintf(fp, "vmaddaw %d\n", L_VMADDAw); + if(L_VMADDAx>0) fprintf(fp, "vmaddax %d\n", L_VMADDAx); + if(L_VMADDAy>0) fprintf(fp, "vmadday %d\n", L_VMADDAy); + if(L_VMADDAz>0) fprintf(fp, "vmaddaz %d\n", L_VMADDAz); + if(L_VMADDi>0) fprintf(fp, "vmaddi %d\n", L_VMADDi); + if(L_VMADDq>0) fprintf(fp, "vmaddq %d\n", L_VMADDq); + if(L_VMADDw>0) fprintf(fp, "vmaddw %d\n", L_VMADDw); + if(L_VMADDx>0) fprintf(fp, "vmaddx %d\n", L_VMADDx); + if(L_VMADDy>0) fprintf(fp, "vmaddy %d\n", L_VMADDy); + if(L_VMADDz>0) fprintf(fp, "vmaddz %d\n", L_VMADDz); + if(L_VMAX>0) fprintf(fp, "vmax %d\n", L_VMAX); + if(L_VMAXi>0) fprintf(fp, "vmaxi %d\n", L_VMAXi); + if(L_VMAXw>0) fprintf(fp, "vmaxw %d\n", L_VMAXw); + if(L_VMAXx>0) fprintf(fp, "vmaxx %d\n", L_VMAXx); + if(L_VMAXy>0) fprintf(fp, "vmaxy %d\n", L_VMAXy); + if(L_VMAXz>0) fprintf(fp, "vmaxz %d\n", L_VMAXz); + if(L_VMFIR>0) fprintf(fp, "vmfir %d\n", L_VMFIR); + if(L_VMINI>0) fprintf(fp, "vmini %d\n", L_VMINI); + if(L_VMINIi>0) fprintf(fp, "vminii %d\n", L_VMINIi); + if(L_VMINIw>0) fprintf(fp, "vminiw %d\n", L_VMINIw); + if(L_VMINIx>0) fprintf(fp, "vminix %d\n", L_VMINIx); + if(L_VMINIy>0) fprintf(fp, "vminiy %d\n", L_VMINIy); + if(L_VMINIz>0) fprintf(fp, "vminiz %d\n", L_VMINIz); + if(L_VMOVE>0) fprintf(fp, "vmove %d\n", L_VMOVE); + if(L_VMR32>0) fprintf(fp, "vmr32 %d\n", L_VMR32); + if(L_VMSUB>0) fprintf(fp, "vmsub %d\n", L_VMSUB); + if(L_VMSUBA>0) fprintf(fp, "vmsuba %d\n", L_VMSUBA); + if(L_VMSUBAi>0) fprintf(fp, "vmsubai %d\n", L_VMSUBAi); + if(L_VMSUBAq>0) fprintf(fp, "vmsubaq %d\n", L_VMSUBAq); + if(L_VMSUBAw>0) fprintf(fp, "vmsubaw %d\n", L_VMSUBAw); + if(L_VMSUBAx>0) fprintf(fp, "vmsubax %d\n", L_VMSUBAx); + if(L_VMSUBAy>0) fprintf(fp, "vmsubay %d\n", L_VMSUBAy); + if(L_VMSUBAz>0) fprintf(fp, "vmsubaz %d\n", L_VMSUBAz); + if(L_VMSUBi>0) fprintf(fp, "vmsubi %d\n", L_VMSUBi); + if(L_VMSUBq>0) fprintf(fp, "vmsubq %d\n", L_VMSUBq); + if(L_VMSUBw>0) fprintf(fp, "vmsubw %d\n", L_VMSUBw); + if(L_VMSUBx>0) fprintf(fp, "vmsubx %d\n", L_VMSUBx); + if(L_VMSUBy>0) fprintf(fp, "vmsuby %d\n", L_VMSUBy); + if(L_VMSUBz>0) fprintf(fp, "vmsubz %d\n", L_VMSUBz); + if(L_VMTIR>0) fprintf(fp, "vmtir %d\n", L_VMTIR); + if(L_VMUL>0) fprintf(fp, "vmul %d\n", L_VMUL); + if(L_VMULA>0) fprintf(fp, "vmula %d\n", L_VMULA); + if(L_VMULAi>0) fprintf(fp, "vmulai %d\n", L_VMULAi); + if(L_VMULAq>0) fprintf(fp, "vmulaq %d\n", L_VMULAq); + if(L_VMULAw>0) fprintf(fp, "vmulaw %d\n", L_VMULAw); + if(L_VMULAx>0) fprintf(fp, "vmulax %d\n", L_VMULAx); + if(L_VMULAy>0) fprintf(fp, "vmulay %d\n", L_VMULAy); + if(L_VMULAz>0) fprintf(fp, "vmulaz %d\n", L_VMULAz); + if(L_VMULi>0) fprintf(fp, "vmuli %d\n", L_VMULi); + if(L_VMULq>0) fprintf(fp, "vmulq %d\n", L_VMULq); + if(L_VMULw>0) fprintf(fp, "vmulw %d\n", L_VMULw); + if(L_VMULx>0) fprintf(fp, "vmulx %d\n", L_VMULx); + if(L_VMULy>0) fprintf(fp, "vmuly %d\n", L_VMULy); + if(L_VMULz>0) fprintf(fp, "vmulz %d\n", L_VMULz); + if(L_VNOP>0) fprintf(fp, "vnop %d\n", L_VNOP); + if(L_VOPMSUB>0) fprintf(fp, "vopmsub %d\n", L_VOPMSUB); + if(L_VOPMULA>0) fprintf(fp, "vopmula %d\n", L_VOPMULA); + if(L_VRGET>0) fprintf(fp, "vrget %d\n", L_VRGET); + if(L_VRINIT>0) fprintf(fp, "vrinit %d\n", L_VRINIT); + if(L_VRNEXT>0) fprintf(fp, "vrnext %d\n", L_VRNEXT); + if(L_VRSQRT>0) fprintf(fp, "vrsqrt %d\n", L_VRSQRT); + if(L_VRXOR>0) fprintf(fp, "vrxor %d\n", L_VRXOR); + if(L_VSQD>0) fprintf(fp, "vsqd %d\n", L_VSQD); + if(L_VSQI>0) fprintf(fp, "vsqi %d\n", L_VSQI); + if(L_VSQRT>0) fprintf(fp, "vsqrt %d\n", L_VSQRT ); + if(L_VSUB>0) fprintf(fp, "vsub %d\n", L_VSUB); + if(L_VSUBA>0) fprintf(fp, "vsuba %d\n", L_VSUBA); + if(L_VSUBAi>0) fprintf(fp, "vsubai %d\n", L_VSUBAi); + if(L_VSUBAq>0) fprintf(fp, "vsubaq %d\n", L_VSUBAq); + if(L_VSUBAw>0) fprintf(fp, "vsubaw %d\n", L_VSUBAw); + if(L_VSUBAx>0) fprintf(fp, "vsubax %d\n", L_VSUBAx); + if(L_VSUBAy>0) fprintf(fp, "vsubay %d\n", L_VSUBAy); + if(L_VSUBAz>0) fprintf(fp, "vsubaz %d\n", L_VSUBAz); + if(L_VSUBi>0) fprintf(fp, "vsubi %d\n", L_VSUBi); + if(L_VSUBq>0) fprintf(fp, "vsubq %d\n", L_VSUBq); + if(L_VSUBw>0) fprintf(fp, "vsubw %d\n", L_VSUBw); + if(L_VSUBx>0) fprintf(fp, "vsubx %d\n", L_VSUBx); + if(L_VSUBy>0) fprintf(fp, "vsuby %d\n", L_VSUBy); + if(L_VSUBz>0) fprintf(fp, "vsubz %d\n", L_VSUBz); + if(L_VWAITQ>0) fprintf(fp, "vwaitq %d\n", L_VWAITQ); + + fclose(fp); + +} + + + + + + + + + + + +/***************/ +//R5900 +void LT_SPECIAL() {LT_SpecialPrintTable[_Funct_]();} +void LT_REGIMM() {LT_REGIMMPrintTable[_Rt_](); } +void LT_UnknownOpcode() {} +void LT_ADDI() { L_ADDI++;} +void LT_ADDIU() { L_ADDIU++;} +void LT_DADDI() { L_DADDI++;} +void LT_DADDIU(){ L_DADDIU++;} +void LT_ANDI() { L_ANDI++;} +void LT_ORI() { L_ORI++;} +void LT_XORI() {L_XORI++;} +void LT_SLTI() {L_SLTI++;} +void LT_SLTIU() {L_SLTIU++;} +void LT_ADD() { L_ADD++;} +void LT_ADDU() { L_ADDU++;} +void LT_DADD() { L_DADD++;} +void LT_DADDU() { L_DADDU++;} +void LT_SUB() { L_SUB++;} +void LT_SUBU() { L_SUBU++;} +void LT_DSUB() { L_DSUB++;} +void LT_DSUBU() { L_DSUBU++;} +void LT_AND() { L_AND++;} +void LT_OR() { L_OR++;} +void LT_XOR() { L_XOR++;} +void LT_NOR() { L_NOR++;} +void LT_SLT() { L_SLT++;} +void LT_SLTU() { L_SLTU++;} +void LT_J() { L_J++;} +void LT_JAL() { L_JAL++;} +void LT_JR() { L_JR++;} +void LT_JALR() { L_JALR++;} +void LT_DIV() { L_DIV++;} +void LT_DIVU() { L_DIVU++;} +void LT_MULT() { L_MULT++;} +void LT_MULTU() { L_MULTU++;} +void LT_LUI() { L_LUI++;} +void LT_MFHI() { L_MFHI++;} +void LT_MFLO() { L_MFLO++;} +void LT_MTHI() { L_MTHI++;} +void LT_MTLO() { L_MTLO++;} +void LT_SLL() { L_SLL++;} +void LT_DSLL() { L_DSLL++;} +void LT_DSLL32(){ L_DSLL32++;} +void LT_SRA() { L_SRA++;} +void LT_DSRA() { L_DSRA++;} +void LT_DSRA32(){ L_DSRA32++;} +void LT_SRL() { L_SRL++;} +void LT_DSRL() { L_DSRL++;} +void LT_DSRL32(){ L_DSRL32++;} +void LT_SLLV() { L_SLLV++;} +void LT_SRAV() { L_SRAV++;} +void LT_SRLV() { L_SRLV++;} +void LT_DSLLV() { L_DSLLV++;} +void LT_DSRAV() { L_DSRAV++;} +void LT_DSRLV() { L_DSRLV++;} +void LT_BEQ() { L_BEQ++;} +void LT_BNE() { L_BNE++;} +void LT_BGEZ() { L_BGEZ++;} +void LT_BGEZAL(){ L_BGEZAL++;} +void LT_BGTZ() { L_BGTZ++;} +void LT_BLEZ() { L_BLEZ++;} +void LT_BLTZ() { L_BLTZ++;} +void LT_BLTZAL(){ L_BLTZAL++;} +void LT_BEQL() { L_BEQL++;} +void LT_BNEL() { L_BNEL++;} +void LT_BLEZL() { L_BLEZL++;} +void LT_BGTZL() { L_BGTZL++;} +void LT_BLTZL() { L_BLTZL++;} +void LT_BGEZL() { L_BGEZL++;} +void LT_BLTZALL(){ L_BLTZALL++;} +void LT_BGEZALL(){ L_BGEZALL++;} +void LT_LB() {L_LB++;} +void LT_LBU() {L_LBU++;} +void LT_LH() {L_LH++;} +void LT_LHU() {L_LHU++;} +void LT_LW() {L_LW++;} +void LT_LWU() {L_LWU++;} +void LT_LWL() {L_LWL++;} +void LT_LWR() {L_LWR++;} +void LT_LD() {L_LD++;} +void LT_LDL() {L_LDL++;} +void LT_LDR() {L_LDR++;} +void LT_LQ() {L_LQ++;} +void LT_SB() {L_SB++;} +void LT_SH() {L_SH++;} +void LT_SW() {L_SW++;} +void LT_SWL() {L_SWL++;} +void LT_SWR() {L_SWR++;} +void LT_SD() {L_SD++;} +void LT_SDL() {L_SDL++;} +void LT_SDR() {L_SDR++;} +void LT_SQ() {L_SQ++;} +void LT_MOVZ() {L_MOVZ++;} +void LT_MOVN() {L_MOVN++;} +void LT_SYSCALL() {L_SYSCALL++;} +void LT_BREAK() {L_BREAK++;} +void LT_CACHE() {L_CACHE++;} +void LT_MFSA() {L_MFSA++;} +void LT_MTSA() {L_MTSA++;} +void LT_SYNC() {L_SYNC++;} +void LT_PREF() {L_PREF++;} +void LT_TGE() {L_TGE++;} +void LT_TGEU() {L_TGEU++;} +void LT_TLT() {L_TLT++;} +void LT_TLTU() {L_TLTU++;} +void LT_TEQ() {L_TEQ++;} +void LT_TNE() {L_TNE++;} +void LT_TGEI() {L_TGEI++;} +void LT_TGEIU() {L_TGEIU++;} +void LT_TLTI() {L_TLTI++;} +void LT_TLTIU() {L_TLTIU++;} +void LT_TEQI() {L_TEQI++;} +void LT_TNEI() {L_TNEI++;} +void LT_MTSAB() {L_MTSAB++;} +void LT_MTSAH() {L_MTSAH++;} +//cop0 +void LT_COP0(){ LT_COP0PrintTable[_Rs_]();} +void LT_COP0_BC0() {LT_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03]();} +void LT_COP0_Func() { LT_COP0C0PrintTable[_Funct_](); } +void LT_COP0_Unknown() { } +void LT_MFC0() {L_MFC0++;} +void LT_MTC0() {L_MTC0++;} +void LT_BC0F() {L_BC0F++;} +void LT_BC0T() {L_BC0T++;} +void LT_BC0FL(){L_BC0FL++;} +void LT_BC0TL(){L_BC0TL++;} +void LT_TLBR() {L_TLBR++;} +void LT_TLBWI(){L_TLBWI++;} +void LT_TLBWR(){L_TLBWR++;} +void LT_TLBP() {L_TLBP++;} +void LT_ERET() {L_ERET++;} +void LT_DI() {L_DI++;} +void LT_EI() {L_EI++;} +//mmi +void LT_MMI() {LT_MMIPrintTable[_Funct_]();} +void LT_MMI0() {LT_MMI0PrintTable[_Sa_]();} +void LT_MMI1() {LT_MMI1PrintTable[_Sa_]();} +void LT_MMI2() {LT_MMI2PrintTable[_Sa_]();} +void LT_MMI3() {LT_MMI3PrintTable[_Sa_]();} +void LT_MMI_Unknown() {} +void LT_MADD() {L_MADD++;} +void LT_MADDU(){L_MADDU++;} +void LT_PLZCW(){L_PLZCW++;} +void LT_MADD1(){L_MADD1++;} +void LT_MADDU1(){L_MADDU1++;} +void LT_MFHI1(){L_MFHI1++;} +void LT_MTHI1(){L_MTHI1++;} +void LT_MFLO1(){L_MFLO1++;} +void LT_MTLO1(){L_MTLO1++;} +void LT_MULT1(){L_MULT1++;} +void LT_MULTU1(){L_MULTU1++;} +void LT_DIV1(){L_DIV1++;} +void LT_DIVU1(){L_DIVU1++;} +void LT_PMFHL(){L_PMFHL++;} +void LT_PMTHL(){L_PMTHL++;} +void LT_PSLLH(){L_PSLLH++;} +void LT_PSRLH(){L_PSRLH++;} +void LT_PSRAH(){L_PSRAH++;} +void LT_PSLLW(){L_PSLLW++;} +void LT_PSRLW(){L_PSRLW++;} +void LT_PSRAW(){L_PSRAW++;} +void LT_PADDW(){L_PADDW++;} +void LT_PSUBW(){L_PSUBW++;} +void LT_PCGTW(){L_PCGTW++;} +void LT_PMAXW(){L_PMAXW++;} +void LT_PADDH(){L_PADDH++;} +void LT_PSUBH(){L_PSUBH++;} +void LT_PCGTH(){L_PCGTH++;} +void LT_PMAXH(){L_PMAXH++;} +void LT_PADDB(){L_PADDB++;} +void LT_PSUBB(){L_PSUBB++;} +void LT_PCGTB(){L_PCGTB++;} +void LT_PADDSW(){L_PADDSW++;} +void LT_PSUBSW(){L_PSUBSW++;} +void LT_PEXTLW(){L_PEXTLW++;} +void LT_PPACW(){L_PPACW++;} +void LT_PADDSH(){L_PADDSH++;} +void LT_PSUBSH(){L_PSUBSH++;} +void LT_PEXTLH(){L_PEXTLH++;} +void LT_PPACH(){L_PPACH++;} +void LT_PADDSB(){L_PADDSB++;} +void LT_PSUBSB(){L_PSUBSB++;} +void LT_PEXTLB(){L_PEXTLB++;} +void LT_PPACB(){L_PPACB++;} +void LT_PEXT5(){L_PEXT5++;} +void LT_PPAC5(){L_PPAC5++;} +void LT_PABSW(){L_PABSW++;} +void LT_PCEQW(){L_PCEQW++;} +void LT_PMINW(){L_PMINW++;} +void LT_PADSBH(){L_PADSBH++;} +void LT_PABSH(){L_PABSH++;} +void LT_PCEQH(){L_PCEQH++;} +void LT_PMINH(){L_PMINH++;} +void LT_PCEQB(){L_PCEQB++;} +void LT_PADDUW(){L_PADDUW++;} +void LT_PSUBUW(){L_PSUBUW++;} +void LT_PEXTUW(){L_PEXTUW++;} +void LT_PADDUH(){L_PADDUH++;} +void LT_PSUBUH(){L_PSUBUH++;} +void LT_PEXTUH(){L_PEXTUH++;} +void LT_PADDUB(){L_PADDUB++;} +void LT_PSUBUB(){L_PSUBUB++;} +void LT_PEXTUB(){L_PEXTUB++;} +void LT_QFSRV(){L_QFSRV++;} +void LT_PMADDW(){L_PMADDW++;} +void LT_PSLLVW(){L_PSLLVW++;} +void LT_PSRLVW(){L_PSRLVW++;} +void LT_PMSUBW(){L_PMSUBW++;} +void LT_PMFHI(){L_PMFHI++;} +void LT_PMFLO(){L_PMFLO++;} +void LT_PINTH(){L_PINTH++;} +void LT_PMULTW(){L_PMULTW++;} +void LT_PDIVW(){L_PDIVW++;} +void LT_PCPYLD(){L_PCPYLD++;} +void LT_PMADDH(){L_PMADDH++;} +void LT_PHMADH(){L_PHMADH++;} +void LT_PAND(){L_PAND++;} +void LT_PXOR(){L_PXOR++;} +void LT_PMSUBH(){L_PMSUBH++;} +void LT_PHMSBH(){L_PHMSBH++;} +void LT_PEXEH(){L_PEXEH++;} +void LT_PREVH(){L_PREVH++;} +void LT_PMULTH(){L_PMULTH++;} +void LT_PDIVBW(){L_PDIVBW++;} +void LT_PEXEW(){L_PEXEW++;} +void LT_PROT3W(){L_PROT3W++;} +void LT_PMADDUW(){L_PMADDUW++;} +void LT_PSRAVW(){L_PSRAVW++;} +void LT_PMTHI(){L_MTHI++;} +void LT_PMTLO(){L_PMTLO++;} +void LT_PINTEH(){L_PINTEH++;} +void LT_PMULTUW(){L_PMULTUW++;} +void LT_PDIVUW(){L_PDIVUW++;} +void LT_PCPYUD(){L_PCPYUD++;} +void LT_POR(){L_POR++;} +void LT_PNOR(){L_PNOR++;} +void LT_PEXCH(){L_PEXCH++;} +void LT_PCPYH(){L_PCPYH++;} +void LT_PEXCW(){L_PEXCW++;} +//COP1 +void LT_COP1() {LT_COP1PrintTable[_Rs_]();} +void LT_LWC1() {L_LWC1++;} +void LT_SWC1() {L_SWC1++;} +void LT_COP1_BC1() {LT_COP1BC1PrintTable[_Rt_]();} +void LT_COP1_S() {LT_COP1SPrintTable[_Funct_]();} +void LT_COP1_W() {LT_COP1WPrintTable[_Funct_]();} +void LT_COP1_Unknown() {} +void LT_MFC1(){L_MFC1++;} +void LT_CFC1(){L_CFC1++;} +void LT_MTC1(){L_MTC1++;} +void LT_CTC1(){L_CTC1++;} +void LT_BC1F(){L_BC1F++;} +void LT_BC1T(){L_BC1T++;} +void LT_BC1FL(){L_BC1FL++;} +void LT_BC1TL(){L_BC1TL++;} +void LT_ADD_S(){L_ADD_S++;} +void LT_SUB_S(){L_SUB_S++;} +void LT_MUL_S(){L_MUL_S++;} +void LT_DIV_S(){L_DIV_S++;} +void LT_SQRT_S(){L_SQRT_S++;} +void LT_ABS_S(){L_ABS_S++;} +void LT_MOV_S(){L_MOV_S++;} +void LT_NEG_S(){L_NEG_S++;} +void LT_RSQRT_S(){L_RSQRT_S++;} +void LT_ADDA_S(){L_ADDA_S++;} +void LT_SUBA_S(){L_SUBA_S++;} +void LT_MULA_S(){L_MULA_S++;} +void LT_MADD_S(){L_MADD_S++;} +void LT_MSUB_S(){L_MSUB_S++;} +void LT_MADDA_S(){L_MADDA_S++;} +void LT_MSUBA_S(){L_MSUBA_S++;} +void LT_CVT_W(){L_CVT_W++;} +void LT_MAX_S(){L_MAX_S++;} +void LT_MIN_S(){L_MIN_S++;} +void LT_C_F(){L_C_F++;} +void LT_C_EQ(){L_C_EQ++;} +void LT_C_LT(){L_C_LT++;} +void LT_C_LE(){L_C_LE++;} +void LT_CVT_S(){L_CVT_S++;} +//cop2 + +void LT_LQC2() {L_LQC2++;} +void LT_SQC2() {L_SQC2++;} +void LT_COP2() {LT_COP2PrintTable[_Rs_]();} +void LT_COP2_BC2() {LT_COP2BC2PrintTable[_Rt_]();} +void LT_COP2_SPECIAL() { LT_COP2SPECIAL1PrintTable[_Funct_]();} +void LT_COP2_SPECIAL2() {LT_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)]();} +void LT_COP2_Unknown(){} +void LT_QMFC2(){L_QMFC2++;} +void LT_CFC2(){L_CFC2++;} +void LT_QMTC2(){L_QMTC2++;} +void LT_CTC2(){L_CTC2++;} +void LT_BC2F(){L_BC2F++;} +void LT_BC2T(){L_BC2T++;} +void LT_BC2FL(){L_BC2FL++;} +void LT_BC2TL(){L_BC2TL++;} +void LT_VADDx(){L_VADDx++;} +void LT_VADDy(){L_VADDy++;} +void LT_VADDz(){L_VADDz++;} +void LT_VADDw(){L_VADDw++;} +void LT_VSUBx(){L_VSUBx++;} +void LT_VSUBy(){L_VSUBy++;} +void LT_VSUBz(){L_VSUBz++;} +void LT_VSUBw(){L_VSUBw++;} +void LT_VMADDx(){L_VMADDx++;} +void LT_VMADDy(){L_VMADDy++;} +void LT_VMADDz(){L_VMADDz++;} +void LT_VMADDw(){L_VMADDw++;} +void LT_VMSUBx(){L_VMSUBx++;} +void LT_VMSUBy(){L_VMSUBy++;} +void LT_VMSUBz(){L_VMSUBz++;} +void LT_VMSUBw(){L_VMSUBw++;} +void LT_VMAXx(){L_VMAXx++;} +void LT_VMAXy(){L_VMAXy++;} +void LT_VMAXz(){L_VMAXz++;} +void LT_VMAXw(){L_VMAXw++;} +void LT_VMINIx(){L_VMINIx++;} +void LT_VMINIy(){L_VMINIy++;} +void LT_VMINIz(){L_VMINIz++;} +void LT_VMINIw(){L_VMINIw++;} +void LT_VMULx(){L_VMULx++;} +void LT_VMULy(){L_VMULy++;} +void LT_VMULz(){L_VMULz++;} +void LT_VMULw(){L_VMULw++;} +void LT_VMULq(){L_VMULq++;} +void LT_VMAXi(){L_VMAXi++;} +void LT_VMULi(){L_VMULi++;} +void LT_VMINIi(){L_VMINIi++;} +void LT_VADDq(){L_VADDq++;} +void LT_VMADDq(){L_VMADDq++;} +void LT_VADDi(){L_VADDi++;} +void LT_VMADDi(){L_VMADDi++;} +void LT_VSUBq(){L_VSUBq++;} +void LT_VMSUBq(){L_VMSUBq++;} +void LT_VSUBi(){L_VSUBi++;} +void LT_VMSUBi(){L_VMSUBi++;} +void LT_VADD(){L_VADD++;} +void LT_VMADD(){L_VMADD++;} +void LT_VMUL(){L_VMUL++;} +void LT_VMAX(){L_VMAX++;} +void LT_VSUB(){L_VSUB++;} +void LT_VMSUB(){L_VMSUB++;} +void LT_VOPMSUB(){L_VOPMSUB++;} +void LT_VMINI(){L_VMINI++;} +void LT_VIADD(){L_VIADD++;} +void LT_VISUB(){L_VISUB++;} +void LT_VIADDI(){L_VIADDI++;} +void LT_VIAND(){L_VIAND++;} +void LT_VIOR(){L_VIOR++;} +void LT_VCALLMS(){L_VCALLMS++;} +void LT_VCALLMSR(){L_VCALLMSR++;} +void LT_VADDAx(){L_VADDAx++;} +void LT_VADDAy(){L_VADDAy++;} +void LT_VADDAz(){L_VADDAz++;} +void LT_VADDAw(){L_VADDAw++;} +void LT_VSUBAx(){L_VSUBAx++;} +void LT_VSUBAy(){L_VSUBAy++;} +void LT_VSUBAz(){L_VSUBAz++;} +void LT_VSUBAw(){L_VSUBAw++;} +void LT_VMADDAx(){L_VMADDAx++;} +void LT_VMADDAy(){L_VMADDAy++;} +void LT_VMADDAz(){L_VMADDAz++;} +void LT_VMADDAw(){L_VMADDAw++;} +void LT_VMSUBAx(){L_VMSUBAx++;} +void LT_VMSUBAy(){L_VMSUBAy++;} +void LT_VMSUBAz(){L_VMSUBAz++;} +void LT_VMSUBAw(){L_VMSUBAw++;} +void LT_VITOF0(){L_VITOF0++;} +void LT_VITOF4(){L_VITOF4++;} +void LT_VITOF12(){L_VITOF12++;} +void LT_VITOF15(){L_VITOF15++;} +void LT_VFTOI0(){L_VFTOI0++;} +void LT_VFTOI4(){L_VFTOI4++;} +void LT_VFTOI12(){L_VFTOI12++;} +void LT_VFTOI15(){L_VFTOI15++;} +void LT_VMULAx(){L_VMULAx++;} +void LT_VMULAy(){L_VMULAy++;} +void LT_VMULAz(){L_VMULAz++;} +void LT_VMULAw(){L_VMULAw++;} +void LT_VMULAq(){L_VMULAq++;} +void LT_VABS(){L_VABS++;} +void LT_VMULAi(){L_VMULAi++;} +void LT_VCLIPw(){L_VCLIPw++;} +void LT_VADDAq(){L_VADDAq++;} +void LT_VMADDAq(){L_VMADDAq++;} +void LT_VADDAi(){L_VADDAi++;} +void LT_VMADDAi(){L_VMADDAi++;} +void LT_VSUBAq(){L_VSUBAq++;} +void LT_VMSUBAq(){L_VMSUBAq++;} +void LT_VSUBAi(){L_VSUBAi++;} +void LT_VMSUBAi(){L_VMSUBAi++;} +void LT_VADDA(){L_VADDA++;} +void LT_VMADDA(){L_VMADDA++;} +void LT_VMULA(){L_VMULA++;} +void LT_VSUBA(){L_VSUBA++;} +void LT_VMSUBA(){L_VMSUBA++;} +void LT_VOPMULA(){L_VOPMULA++;} +void LT_VNOP(){L_VNOP++;} +void LT_VMOVE(){L_VMOVE++;} +void LT_VMR32(){L_VMR32++;} +void LT_VLQI(){L_VLQI++;} +void LT_VSQI(){L_VSQI++;} +void LT_VLQD(){L_VLQD++;} +void LT_VSQD(){L_VSQD++;} +void LT_VDIV(){L_VDIV++;} +void LT_VSQRT(){L_VSQRT++;} +void LT_VRSQRT(){L_VRSQRT++;} +void LT_VWAITQ(){L_VWAITQ++;} +void LT_VMTIR(){L_VMTIR++;} +void LT_VMFIR(){L_VMFIR++;} +void LT_VILWR(){L_VILWR++;} +void LT_VISWR(){L_VISWR++;} +void LT_VRNEXT(){L_VRNEXT++;} +void LT_VRGET(){L_VRGET++;} +void LT_VRINIT(){L_VRINIT++;} +void LT_VRXOR(){L_VRXOR++;} + +void (*LT_OpcodePrintTable[64])() = +{ + LT_SPECIAL, LT_REGIMM, LT_J, LT_JAL, LT_BEQ, LT_BNE, LT_BLEZ, LT_BGTZ, + LT_ADDI, LT_ADDIU, LT_SLTI, LT_SLTIU, LT_ANDI, LT_ORI, LT_XORI, LT_LUI, + LT_COP0, LT_COP1, LT_COP2, LT_UnknownOpcode, LT_BEQL, LT_BNEL, LT_BLEZL, LT_BGTZL, + LT_DADDI, LT_DADDIU, LT_LDL, LT_LDR, LT_MMI, LT_UnknownOpcode, LT_LQ, LT_SQ, + LT_LB, LT_LH, LT_LWL, LT_LW, LT_LBU, LT_LHU, LT_LWR, LT_LWU, + LT_SB, LT_SH, LT_SWL, LT_SW, LT_SDL, LT_SDR, LT_SWR, LT_CACHE, + LT_UnknownOpcode, LT_LWC1, LT_UnknownOpcode, LT_PREF, LT_UnknownOpcode,LT_UnknownOpcode, LT_LQC2, LT_LD, + LT_UnknownOpcode, LT_SWC1, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode,LT_UnknownOpcode, LT_SQC2, LT_SD +}; + + +void (*LT_SpecialPrintTable[64])() = +{ + LT_SLL, LT_UnknownOpcode, LT_SRL, LT_SRA, LT_SLLV, LT_UnknownOpcode, LT_SRLV, LT_SRAV, + LT_JR, LT_JALR, LT_MOVZ, LT_MOVN, LT_SYSCALL, LT_BREAK, LT_UnknownOpcode, LT_SYNC, + LT_MFHI, LT_MTHI, LT_MFLO, LT_MTLO, LT_DSLLV, LT_UnknownOpcode, LT_DSRLV, LT_DSRAV, + LT_MULT, LT_MULTU, LT_DIV, LT_DIVU, LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode, + LT_ADD, LT_ADDU, LT_SUB, LT_SUBU, LT_AND, LT_OR, LT_XOR, LT_NOR, + LT_MFSA , LT_MTSA , LT_SLT, LT_SLTU, LT_DADD, LT_DADDU, LT_DSUB, LT_DSUBU, + LT_TGE, LT_TGEU, LT_TLT, LT_TLTU, LT_TEQ, LT_UnknownOpcode, LT_TNE, LT_UnknownOpcode, + LT_DSLL, LT_UnknownOpcode, LT_DSRL, LT_DSRA, LT_DSLL32, LT_UnknownOpcode, LT_DSRL32, LT_DSRA32 +}; + +void (*LT_REGIMMPrintTable[32])() = { + LT_BLTZ, LT_BGEZ, LT_BLTZL, LT_BGEZL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_TGEI, LT_TGEIU, LT_TLTI, LT_TLTIU, LT_TEQI, LT_UnknownOpcode, LT_TNEI, LT_UnknownOpcode, + LT_BLTZAL, LT_BGEZAL, LT_BLTZALL, LT_BGEZALL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_MTSAB, LT_MTSAH , LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, +}; +void (*LT_MMIPrintTable[64])() = +{ + LT_MADD, LT_MADDU, LT_MMI_Unknown, LT_MMI_Unknown, LT_PLZCW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI0, LT_MMI2, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MFHI1, LT_MTHI1, LT_MFLO1, LT_MTLO1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MULT1, LT_MULTU1, LT_DIV1, LT_DIVU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MADD1, LT_MADDU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI1 , LT_MMI3, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHL, LT_PMTHL, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLH, LT_MMI_Unknown, LT_PSRLH, LT_PSRAH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLW, LT_MMI_Unknown, LT_PSRLW, LT_PSRAW, +}; + +void (*LT_MMI0PrintTable[32])() = +{ + LT_PADDW, LT_PSUBW, LT_PCGTW, LT_PMAXW, + LT_PADDH, LT_PSUBH, LT_PCGTH, LT_PMAXH, + LT_PADDB, LT_PSUBB, LT_PCGTB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDSW, LT_PSUBSW, LT_PEXTLW, LT_PPACW, + LT_PADDSH, LT_PSUBSH, LT_PEXTLH, LT_PPACH, + LT_PADDSB, LT_PSUBSB, LT_PEXTLB, LT_PPACB, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXT5, LT_PPAC5, +}; + +void (*LT_MMI1PrintTable[32])() = +{ + LT_MMI_Unknown, LT_PABSW, LT_PCEQW, LT_PMINW, + LT_PADSBH, LT_PABSH, LT_PCEQH, LT_PMINH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PCEQB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDUW, LT_PSUBUW, LT_PEXTUW, LT_MMI_Unknown, + LT_PADDUH, LT_PSUBUH, LT_PEXTUH, LT_MMI_Unknown, + LT_PADDUB, LT_PSUBUB, LT_PEXTUB, LT_QFSRV, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, +}; + + +void (*LT_MMI2PrintTable[32])() = +{ + LT_PMADDW, LT_MMI_Unknown, LT_PSLLVW, LT_PSRLVW, + LT_PMSUBW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHI, LT_PMFLO, LT_PINTH, LT_MMI_Unknown, + LT_PMULTW, LT_PDIVW, LT_PCPYLD, LT_MMI_Unknown, + LT_PMADDH, LT_PHMADH, LT_PAND, LT_PXOR, + LT_PMSUBH, LT_PHMSBH, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXEH, LT_PREVH, + LT_PMULTH, LT_PDIVBW, LT_PEXEW, LT_PROT3W, +}; + +void (*LT_MMI3PrintTable[32])() = +{ + LT_PMADDUW, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSRAVW, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMTHI, LT_PMTLO, LT_PINTEH, LT_MMI_Unknown, + LT_PMULTUW, LT_PDIVUW, LT_PCPYUD, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_POR, LT_PNOR, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCH, LT_PCPYH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCW, LT_MMI_Unknown, +}; + +void (*LT_COP0PrintTable[32])() = +{ + LT_MFC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_MTC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_BC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Func, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0BC0PrintTable[32])() = +{ + LT_BC0F, LT_BC0T, LT_BC0FL, LT_BC0TL, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0C0PrintTable[64])() = { + LT_COP0_Unknown, LT_TLBR, LT_TLBWI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_TLBWR, LT_COP0_Unknown, + LT_TLBP, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_ERET, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_EI, LT_DI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown +}; + + +void (*LT_COP1PrintTable[32])() = { + LT_MFC1, LT_COP1_Unknown, LT_CFC1, LT_COP1_Unknown, LT_MTC1, LT_COP1_Unknown, LT_CTC1, LT_COP1_Unknown, + LT_COP1_BC1, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_S, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_W, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1BC1PrintTable[32])() = { + LT_BC1F, LT_BC1T, LT_BC1FL, LT_BC1TL, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1SPrintTable[64])() = { +LT_ADD_S, LT_SUB_S, LT_MUL_S, LT_DIV_S, LT_SQRT_S, LT_ABS_S, LT_MOV_S, LT_NEG_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_RSQRT_S, LT_COP1_Unknown, +LT_ADDA_S, LT_SUBA_S, LT_MULA_S, LT_COP1_Unknown,LT_MADD_S, LT_MSUB_S, LT_MADDA_S, LT_MSUBA_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_CVT_W, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_MAX_S, LT_MIN_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_C_F, LT_COP1_Unknown,LT_C_EQ, LT_COP1_Unknown,LT_C_LT, LT_COP1_Unknown,LT_C_LE, LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP1WPrintTable[64])() = { +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_CVT_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP2PrintTable[32])() = { + LT_COP2_Unknown, LT_QMFC2, LT_CFC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_QMTC2, LT_CTC2, LT_COP2_Unknown, + LT_COP2_BC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, +}; + +void (*LT_COP2BC2PrintTable[32])() = { + LT_BC2F, LT_BC2T, LT_BC2FL, LT_BC2TL, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, +}; + +void (*LT_COP2SPECIAL1PrintTable[64])() = +{ + LT_VADDx, LT_VADDy, LT_VADDz, LT_VADDw, LT_VSUBx, LT_VSUBy, LT_VSUBz, LT_VSUBw, + LT_VMADDx, LT_VMADDy, LT_VMADDz, LT_VMADDw, LT_VMSUBx, LT_VMSUBy, LT_VMSUBz, LT_VMSUBw, + LT_VMAXx, LT_VMAXy, LT_VMAXz, LT_VMAXw, LT_VMINIx, LT_VMINIy, LT_VMINIz, LT_VMINIw, + LT_VMULx, LT_VMULy, LT_VMULz, LT_VMULw, LT_VMULq, LT_VMAXi, LT_VMULi, LT_VMINIi, + LT_VADDq, LT_VMADDq, LT_VADDi, LT_VMADDi, LT_VSUBq, LT_VMSUBq, LT_VSUBi, LT_VMSUBi, + LT_VADD, LT_VMADD, LT_VMUL, LT_VMAX, LT_VSUB, LT_VMSUB, LT_VOPMSUB, LT_VMINI, + LT_VIADD, LT_VISUB, LT_VIADDI, LT_COP2_Unknown,LT_VIAND, LT_VIOR, LT_COP2_Unknown, LT_COP2_Unknown, + LT_VCALLMS, LT_VCALLMSR, LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2, +}; + +void (*LT_COP2SPECIAL2PrintTable[128])() = +{ + LT_VADDAx ,LT_VADDAy ,LT_VADDAz ,LT_VADDAw ,LT_VSUBAx ,LT_VSUBAy ,LT_VSUBAz ,LT_VSUBAw, + LT_VMADDAx ,LT_VMADDAy ,LT_VMADDAz ,LT_VMADDAw ,LT_VMSUBAx ,LT_VMSUBAy ,LT_VMSUBAz ,LT_VMSUBAw, + LT_VITOF0 ,LT_VITOF4 ,LT_VITOF12 ,LT_VITOF15 ,LT_VFTOI0 ,LT_VFTOI4 ,LT_VFTOI12 ,LT_VFTOI15, + LT_VMULAx ,LT_VMULAy ,LT_VMULAz ,LT_VMULAw ,LT_VMULAq ,LT_VABS ,LT_VMULAi ,LT_VCLIPw, + LT_VADDAq ,LT_VMADDAq ,LT_VADDAi ,LT_VMADDAi ,LT_VSUBAq ,LT_VMSUBAq ,LT_VSUBAi ,LT_VMSUBAi, + LT_VADDA ,LT_VMADDA ,LT_VMULA ,LT_COP2_Unknown,LT_VSUBA ,LT_VMSUBA ,LT_VOPMULA ,LT_VNOP, + LT_VMOVE ,LT_VMR32 ,LT_COP2_Unknown,LT_COP2_Unknown,LT_VLQI ,LT_VSQI ,LT_VLQD ,LT_VSQD, + LT_VDIV ,LT_VSQRT ,LT_VRSQRT ,LT_VWAITQ ,LT_VMTIR ,LT_VMFIR ,LT_VILWR ,LT_VISWR, + LT_VRNEXT ,LT_VRGET ,LT_VRINIT ,LT_VRXOR ,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, +}; diff --git a/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.h b/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.h new file mode 100644 index 0000000..3422693 --- /dev/null +++ b/branches/pcsx2_0.9.2/DebugTools/cpuopsDebug.h @@ -0,0 +1,456 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void UpdateR5900op(); +extern void (*LT_OpcodePrintTable[64])(); +extern void (*LT_SpecialPrintTable[64])(); +extern void (*LT_REGIMMPrintTable[32])(); +extern void (*LT_MMIPrintTable[64])(); +extern void (*LT_MMI0PrintTable[32])(); +extern void (*LT_MMI1PrintTable[32])(); +extern void (*LT_MMI2PrintTable[32])(); +extern void (*LT_MMI3PrintTable[32])(); +extern void (*LT_COP0PrintTable[32])(); +extern void (*LT_COP0BC0PrintTable[32])(); +extern void (*LT_COP0C0PrintTable[64])(); +extern void (*LT_COP1PrintTable[32])(); +extern void (*LT_COP1BC1PrintTable[32])(); +extern void (*LT_COP1SPrintTable[64])(); +extern void (*LT_COP1WPrintTable[64])(); +extern void (*LT_COP2PrintTable[32])(); +extern void (*LT_COP2BC2PrintTable[32])(); +extern void (*LT_COP2SPECIAL1PrintTable[64])(); +extern void (*LT_COP2SPECIAL2PrintTable[128])(); +// **********************Standard Opcodes************************** +int L_ADD=0; +int L_ADDI=0; +int L_ADDIU=0; +int L_ADDU=0; +int L_AND=0; +int L_ANDI=0; +int L_BEQ=0; +int L_BEQL=0; +int L_BGEZ=0; +int L_BGEZAL=0; +int L_BGEZALL=0; +int L_BGEZL=0; +int L_BGTZ=0; +int L_BGTZL=0; +int L_BLEZ=0; +int L_BLEZL=0; +int L_BLTZ=0; +int L_BLTZAL=0; +int L_BLTZALL=0; +int L_BLTZL=0; +int L_BNE=0; +int L_BNEL=0; +int L_BREAK=0; +int L_CACHE=0; +int L_DADD=0; +int L_DADDI=0; +int L_DADDIU=0; +int L_DADDU=0; +int L_DIV=0; +int L_DIVU=0; +int L_DSLL=0; +int L_DSLL32=0; +int L_DSLLV=0; +int L_DSRA=0; +int L_DSRA32=0; +int L_DSRAV=0; +int L_DSRL=0; +int L_DSRL32=0; +int L_DSRLV=0; +int L_DSUB=0; +int L_DSUBU=0; +int L_J=0; +int L_JAL=0; +int L_JALR=0; +int L_JR=0; +int L_LB=0; +int L_LBU=0; +int L_LD=0; +int L_LDL=0; +int L_LDR=0; +int L_LH=0; +int L_LHU=0; +int L_LQ=0; +int L_LQC2=0; +int L_LUI=0; +int L_LW=0; +int L_LWC1=0; +int L_LWL=0; +int L_LWR=0; +int L_LWU=0; +int L_MFHI=0; +int L_MFLO=0; +int L_MFSA=0; +int L_MOVN=0; +int L_MOVZ=0; +int L_MTHI=0; +int L_MTLO=0; +int L_MTSA=0; +int L_MTSAB=0; +int L_MTSAH=0; +int L_MULT=0; +int L_MULTU=0; +int L_NOR=0; +int L_OR=0; +int L_ORI=0; +int L_PREF=0; +int L_SB=0; +int L_SD=0; +int L_SDL=0; +int L_SDR=0; +int L_SH=0; +int L_SLL=0; +int L_SLLV=0; +int L_SLT=0; +int L_SLTI=0; +int L_SLTIU=0; +int L_SLTU=0; +int L_SQ=0; +int L_SQC2=0; +int L_SRA=0; +int L_SRAV=0; +int L_SRL=0; +int L_SRLV=0; +int L_SUB=0; +int L_SUBU=0; +int L_SW=0; +int L_SWC1=0; +int L_SWL=0; +int L_SWR=0; +int L_SYNC=0; +int L_SYSCALL=0; +int L_TEQ=0; +int L_TEQI=0; +int L_TGE=0; +int L_TGEI=0; +int L_TGEIU=0; +int L_TGEU=0; +int L_TLT=0; +int L_TLTI=0; +int L_TLTIU=0; +int L_TLTU=0; +int L_TNE=0; +int L_TNEI=0; +int L_XOR=0; +int L_XORI=0; + + + + +//*****************MMI OPCODES********************************* +int L_MADD=0; +int L_MADDU=0; +int L_PLZCW=0; +int L_MADD1=0; +int L_MADDU1=0; +int L_MFHI1=0; +int L_MTHI1=0; +int L_MFLO1=0; +int L_MTLO1=0; +int L_MULT1=0; +int L_MULTU1=0; +int L_DIV1=0; +int L_DIVU1=0; +int L_PMFHL=0; +int L_PMTHL=0; +int L_PSLLH=0; +int L_PSRLH=0; +int L_PSRAH=0; +int L_PSLLW=0; +int L_PSRLW=0; +int L_PSRAW=0; +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +int L_PADDW=0; +int L_PSUBW=0; +int L_PCGTW=0; +int L_PMAXW=0; +int L_PADDH=0; +int L_PSUBH=0; +int L_PCGTH=0; +int L_PMAXH=0; +int L_PADDB=0; +int L_PSUBB=0; +int L_PCGTB=0; +int L_PADDSW=0; +int L_PSUBSW=0; +int L_PEXTLW=0; +int L_PPACW=0; +int L_PADDSH=0; +int L_PSUBSH=0; +int L_PEXTLH=0; +int L_PPACH=0; +int L_PADDSB=0; +int L_PSUBSB=0; +int L_PEXTLB=0; +int L_PPACB=0; +int L_PEXT5=0; +int L_PPAC5=0; +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +int L_PABSW=0; +int L_PCEQW=0; +int L_PMINW=0; +int L_PADSBH=0; +int L_PABSH=0; +int L_PCEQH=0; +int L_PMINH=0; +int L_PCEQB=0; +int L_PADDUW=0; +int L_PSUBUW=0; +int L_PEXTUW=0; +int L_PADDUH=0; +int L_PSUBUH=0; +int L_PEXTUH=0; +int L_PADDUB=0; +int L_PSUBUB=0; +int L_PEXTUB=0; +int L_QFSRV=0; +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +int L_PMADDW=0; +int L_PSLLVW=0; +int L_PSRLVW=0; +int L_PMSUBW=0; +int L_PMFHI=0; +int L_PMFLO=0; +int L_PINTH=0; +int L_PMULTW=0; +int L_PDIVW=0; +int L_PCPYLD=0; +int L_PMADDH=0; +int L_PHMADH=0; +int L_PAND=0; +int L_PXOR=0; +int L_PMSUBH=0; +int L_PHMSBH=0; +int L_PEXEH=0; +int L_PREVH=0; +int L_PMULTH=0; +int L_PDIVBW=0; +int L_PEXEW=0; +int L_PROT3W=0; +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +int L_PMADDUW=0; +int L_PSRAVW=0; +int L_PMTHI=0; +int L_PMTLO=0; +int L_PINTEH=0; +int L_PMULTUW=0; +int L_PDIVUW=0; +int L_PCPYUD=0; +int L_POR=0; +int L_PNOR=0; +int L_PEXCH=0; +int L_PCPYH=0; +int L_PEXCW=0; +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +int L_MFC0=0; +int L_MTC0=0; +int L_BC0F=0; +int L_BC0T=0; +int L_BC0FL=0; +int L_BC0TL=0; +int L_TLBR=0; +int L_TLBWI=0; +int L_TLBWR=0; +int L_TLBP=0; +int L_ERET=0; +int L_DI=0; +int L_EI=0; +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +int L_MFC1=0; +int L_CFC1=0; +int L_MTC1=0; +int L_CTC1=0; +int L_BC1F=0; +int L_BC1T=0; +int L_BC1FL=0; +int L_BC1TL=0; +int L_ADD_S=0; +int L_SUB_S=0; +int L_MUL_S=0; +int L_DIV_S=0; +int L_SQRT_S=0; +int L_ABS_S=0; +int L_MOV_S=0; +int L_NEG_S=0; +int L_RSQRT_S=0; +int L_ADDA_S=0; +int L_SUBA_S=0; +int L_MULA_S=0; +int L_MADD_S=0; +int L_MSUB_S=0; +int L_MADDA_S=0; +int L_MSUBA_S=0; +int L_CVT_W=0; +int L_MAX_S=0; +int L_MIN_S=0; +int L_C_F=0; +int L_C_EQ=0; +int L_C_LT=0; +int L_C_LE=0; + int L_CVT_S=0; +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +int L_QMFC2=0; +int L_CFC2=0; +int L_QMTC2=0; +int L_CTC2=0; +int L_BC2F=0; +int L_BC2T=0; +int L_BC2FL=0; +int L_BC2TL=0; +int L_VADDx=0; +int L_VADDy=0; +int L_VADDz=0; +int L_VADDw=0; +int L_VSUBx=0; +int L_VSUBy=0; +int L_VSUBz=0; +int L_VSUBw=0; +int L_VMADDx=0; +int L_VMADDy=0; +int L_VMADDz=0; +int L_VMADDw=0; +int L_VMSUBx=0; +int L_VMSUBy=0; +int L_VMSUBz=0; +int L_VMSUBw=0; +int L_VMAXx=0; +int L_VMAXy=0; +int L_VMAXz=0; +int L_VMAXw=0; +int L_VMINIx=0; +int L_VMINIy=0; +int L_VMINIz=0; +int L_VMINIw=0; +int L_VMULx=0; +int L_VMULy=0; +int L_VMULz=0; +int L_VMULw=0; +int L_VMULq=0; +int L_VMAXi=0; +int L_VMULi=0; +int L_VMINIi=0; +int L_VADDq=0; +int L_VMADDq=0; +int L_VADDi=0; +int L_VMADDi=0; +int L_VSUBq=0; +int L_VMSUBq=0; +int L_VSUBi=0; +int L_VMSUBi=0; +int L_VADD=0; +int L_VMADD=0; +int L_VMUL=0; +int L_VMAX=0; +int L_VSUB=0; +int L_VMSUB=0; +int L_VOPMSUB=0; +int L_VMINI=0; +int L_VIADD=0; +int L_VISUB=0; +int L_VIADDI=0; +int L_VIAND=0; +int L_VIOR=0; +int L_VCALLMS=0; +int L_VCALLMSR=0; +int L_VADDAx=0; +int L_VADDAy=0; +int L_VADDAz=0; +int L_VADDAw=0; +int L_VSUBAx=0; +int L_VSUBAy=0; +int L_VSUBAz=0; +int L_VSUBAw=0; +int L_VMADDAx=0; +int L_VMADDAy=0; +int L_VMADDAz=0; +int L_VMADDAw=0; +int L_VMSUBAx=0; +int L_VMSUBAy=0; +int L_VMSUBAz=0; +int L_VMSUBAw=0; +int L_VITOF0=0; +int L_VITOF4=0; +int L_VITOF12=0; +int L_VITOF15=0; +int L_VFTOI0=0; +int L_VFTOI4=0; +int L_VFTOI12=0; +int L_VFTOI15=0; +int L_VMULAx=0; +int L_VMULAy=0; +int L_VMULAz=0; +int L_VMULAw=0; +int L_VMULAq=0; +int L_VABS=0; +int L_VMULAi=0; +int L_VCLIPw=0; +int L_VADDAq=0; +int L_VMADDAq=0; +int L_VADDAi=0; +int L_VMADDAi=0; +int L_VSUBAq=0; +int L_VMSUBAq=0; +int L_VSUBAi=0; +int L_VMSUBAi=0; +int L_VADDA=0; +int L_VMADDA=0; +int L_VMULA=0; +int L_VSUBA=0; +int L_VMSUBA=0; +int L_VOPMULA=0; +int L_VNOP=0; +int L_VMOVE=0; +int L_VMR32=0; +int L_VLQI=0; +int L_VSQI=0; +int L_VLQD=0; +int L_VSQD=0; +int L_VDIV=0; +int L_VSQRT=0; +int L_VRSQRT=0; +int L_VWAITQ=0; +int L_VMTIR=0; +int L_VMFIR=0; +int L_VILWR=0; +int L_VISWR=0; +int L_VRNEXT=0; +int L_VRGET=0; +int L_VRINIT=0; +int L_VRXOR=0; diff --git a/branches/pcsx2_0.9.2/Decode_XA.c b/branches/pcsx2_0.9.2/Decode_XA.c new file mode 100644 index 0000000..3bd53f4 --- /dev/null +++ b/branches/pcsx2_0.9.2/Decode_XA.c @@ -0,0 +1,305 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ +//=== Modified by linuzappz +//============================================ + +#include + +#include "Decode_XA.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#endif + +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned long U32; + +#define NOT(_X_) (!(_X_)) +#define CLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} + +//============================================ +//=== ADPCM DECODING ROUTINES +//============================================ + +static double K0[4] = { + 0.0, + 0.9375, + 1.796875, + 1.53125 +}; + +static double K1[4] = { + 0.0, + 0.0, + -0.8125, + -0.859375 +}; + +#define BLKSIZ 28 /* block size (32 - 4 nibbles) */ + +//=========================================== +void ADPCM_InitDecode( ADPCM_Decode_t *decp ) +{ + decp->y0 = 0; + decp->y1 = 0; +} + +//=========================================== +#define SH 4 +#define SHC 10 + +#define IK0(fid) ((int)((-K0[fid]) * (1<> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + long y; + long x0, x1, x2, x3; + + y = *blockp++; + x3 = (short)( y & 0xf000) >> range; x3 <<= SH; + x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; + x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; + x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; + + x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; + x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; + x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; + x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; + + CLAMP( x0, -32768<> SH; destp += inc; + CLAMP( x1, -32768<> SH; destp += inc; + CLAMP( x2, -32768<> SH; destp += inc; + CLAMP( x3, -32768<> SH; destp += inc; + } + decp->y0 = fy0; + decp->y1 = fy1; +} + +static int headtable[4] = {0,2,8,10}; + +//=========================================== +static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { + const U8 *sound_groupsp; + const U8 *sound_datap, *sound_datap2; + int i, j, k, nbits; + U16 data[4096], *datap; + short *destp; + + destp = xdp->pcm; + nbits = xdp->nbits == 4 ? 4 : 2; + + if (xdp->stereo) { // stereo + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } + else { // mono + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } +} + +//============================================ +//=== XA SPECIFIC ROUTINES +//============================================ +typedef struct { +U8 filenum; +U8 channum; +U8 submode; +U8 coding; + +U8 filenum2; +U8 channum2; +U8 submode2; +U8 coding2; +} xa_subheader_t; + +#define SUB_SUB_EOF (1<<7) // end of file +#define SUB_SUB_RT (1<<6) // real-time sector +#define SUB_SUB_FORM (1<<5) // 0 form1 1 form2 +#define SUB_SUB_TRIGGER (1<<4) // used for interrupt +#define SUB_SUB_DATA (1<<3) // contains data +#define SUB_SUB_AUDIO (1<<2) // contains audio +#define SUB_SUB_VIDEO (1<<1) // contains video +#define SUB_SUB_EOR (1<<0) // end of record + +#define AUDIO_CODING_GET_STEREO(_X_) ( (_X_) & 3) +#define AUDIO_CODING_GET_FREQ(_X_) (((_X_) >> 2) & 3) +#define AUDIO_CODING_GET_BPS(_X_) (((_X_) >> 4) & 3) +#define AUDIO_CODING_GET_EMPHASIS(_X_) (((_X_) >> 6) & 1) + +#define SUB_UNKNOWN 0 +#define SUB_VIDEO 1 +#define SUB_AUDIO 2 + +//============================================ +static int parse_xa_audio_sector( xa_decode_t *xdp, + xa_subheader_t *subheadp, + unsigned char *sectorp, + int is_first_sector ) { + if ( is_first_sector ) { + switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { + case 0: xdp->freq = 37800; break; + case 1: xdp->freq = 18900; break; + default: xdp->freq = 0; break; + } + switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { + case 0: xdp->nbits = 4; break; + case 1: xdp->nbits = 8; break; + default: xdp->nbits = 0; break; + } + switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { + case 0: xdp->stereo = 0; break; + case 1: xdp->stereo = 1; break; + default: xdp->stereo = 0; break; + } + + if ( xdp->freq == 0 ) + return -1; + + ADPCM_InitDecode( &xdp->left ); + ADPCM_InitDecode( &xdp->right ); + + xdp->nsamples = 18 * 28 * 8; + if (xdp->stereo == 1) xdp->nsamples /= 2; + } + xa_decode_data( xdp, sectorp ); + + return 0; +} + +//================================================================ +//=== THIS IS WHAT YOU HAVE TO CALL +//=== xdp - structure were all important data are returned +//=== sectorp - data in input +//=== pcmp - data in output +//=== is_first_sector - 1 if it's the 1st sector of the stream +//=== - 0 for any other successive sector +//=== return -1 if error +//================================================================ +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, int is_first_sector ) { + if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) + return -1; + + return 0; +} + +/* EXAMPLE: +"nsamples" is the number of 16 bit samples +every sample is 2 bytes in mono and 4 bytes in stereo + +xa_decode_t xa; + + sectorp = read_first_sector(); + xa_decode_sector( &xa, sectorp, 1 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + + while ( --n_sectors ) + { + sectorp = read_next_sector(); + xa_decode_sector( &xa, sectorp, 0 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + } +*/ diff --git a/branches/pcsx2_0.9.2/Decode_XA.h b/branches/pcsx2_0.9.2/Decode_XA.h new file mode 100644 index 0000000..d363fb4 --- /dev/null +++ b/branches/pcsx2_0.9.2/Decode_XA.h @@ -0,0 +1,26 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct { + long y0, y1; +} ADPCM_Decode_t; + +typedef struct { + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/branches/pcsx2_0.9.2/Docs/BetaTesters.txt b/branches/pcsx2_0.9.2/Docs/BetaTesters.txt new file mode 100644 index 0000000..3d15fb1 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/BetaTesters.txt @@ -0,0 +1,13 @@ +Current PCSX2 Beta-Testers-Slaves :P : + +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever +Seta-San +Nave diff --git a/branches/pcsx2_0.9.2/Docs/ChangeLog.txt b/branches/pcsx2_0.9.2/Docs/ChangeLog.txt new file mode 100644 index 0000000..30480d3 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/ChangeLog.txt @@ -0,0 +1,2848 @@ +[ Legend: ] +[ + Added feature ] +[ * Improved/changed feature ] +[ - Bug fixed (we hope) ] +[ ! Attention (Notes) ] +[ M Maintenance ] +[ dates are dd/mm/yyyy !!! ] + +ChangeLog: + v0.9.2: + * 30/10/06:[*] Improved the way Unpacks are handled slightly, just so its a little quicker (not much) + [-] MMI bug causing corrupt characters on Max Payne fixed + [-] Performance counters corrected in INT and REC + [-] Branches in a branch delay slot no longer results in a crash + [*] Changed Run CD to Run CD/DVD, ps2 doesnt use CD's much :P + [*] Removed "Advanced" from the menu, not required anymore (at the moment) + [-] Small alteration to IPU transfers, ending the transfer too quickly + [-] Made a seperate branchtest for INT, fixed the VU not running on the bios in INT + (Refraction - Zerofrog) + + * 16/10/06:[-] Counter bugz again, seemed to effect the text in xmen + [-] Fixed an ipu bug which stopped the GTA San Andreas videos working + [-] couple more smaller unpack changes to remove a hack + (Refraction) + + * 15/10/06:[*] Moved some declarations from patch.c to patch.h + [-] Fixed problem with XML patch loading (see above). + [+] Merged my WIP cheat finder dialog (note WIP). + (Gigaherz) + + * 11/10/06:[+] Added XML Patch support + [-] More unpack fixes for GT3/GT4, Xmen, Midnight Club 2, FFX sky, Whiplash and more :) + (Refraction - Gigaherz) + + * 05/10/06:[-] Fixed VIF Unpack skipping write cycle counting (Fixes XMen 2 amongst other SPS) + [-] Small counter change, am i ever going to get peace from these :( + (Refraction) + + * 03/10/06:[-] Fixed MFIFO issue where VIF/GIF might not be ready + [*] Improved Guitar Hero fix, seems MFIFO isnt too keen on sliced transfers (especially on GIF) + [*] Modified VS2005 Project file so it compiles - Thanks to CKemu for doing that :P + (Refraction - CKemu) + + * 02/10/06:[*] Various changes in cdvd.c. Most notable is the implementation of cdvd.PwOff. + It is actualy INTR_STAT and has "completition" bits that are Ack'ed by cdvdman interrupt handler. + ...to be continued. + (Florin) + + * 30/09/06:[*] Corrected performance counter register reads on COP0 (3 regs are accessed by 1) - Lego Racers 2 + [-] Altered the order DIV on IOP rec handles signs - Lego Racers 2 + (Refraction) + + * 29/09/06:[-] Fixed condition where MFIFO could get ahead of itself/not have enough data available + (fixes Guitar Hero) + [-] Fixed up DMA Stalls between VIF/IPU/GIF, games such as Theme Park World should work properly now. + [+] Added cpu detection for Dual core Opterons, Athlon X2's and Intel Core 2 Duo's (no perf effect) + [+] Added saqibs sound changes so ADMA and ADPCM streams work. + [-] Yes, more counter fixes, fed up of these :P + [-] DMA transfers fixed when a QWC is already given, it transfers the QWC then ends (Fixes Ridge Racer 5 a bit) + [-] Small GSCSR changes, not sure what will be fixed. + [-] Event where the DMA could be terminated during a stall on VIF + [-] Various Rec + MTGS + IPU Fixes + (Refraction - Saqib - ZeroFrog) + + * 25/07/06:[-] Changed Vif0 COL/ROW mem write addresses, they were going to the same QW + [*] Made Vif stalls use cycles to delay, due to the spiderman fix we dont want these interrupting instantly! + (fixes Flatout BIFCO) + [-] Call/Ret now update the ASR status in the CHCR register + [-] Couple of small fixes to Tag BUSERR, altho i hope we never need them :P + [+] Added seperate EE counter logging + (Refraction) + +v0.9.1: + * 28/06/06:[+] MAJOR CHANGE: All recompilers and memory code rewritten. + eeRec now does block analysis, constant propagation, liveness + analysis, mmx/xmm reg caching, etc. + vuRec is about 10x faster than older vurec. Both VU0 and + VU1 recs work and share the same code. + iopRec - does same as eeRec, except is simpler + Altogether, 3D scenes are 2-4x faster than 0.9 release. + (zerofrog) + * 09/05/06:[*] Moved repository to SVN. Play nice. Any questions... you know where to find me + [+] new developer blogs from me and auMatt + (Florin-auMatt) + + * 05/05/06:[*] Changed names of the SSBUS registers in PsxHw.c + [!] dev1 is rom bus, dev5 is cdvd bus, dev9 is ata|smap|dvr|uart|flash bus + (Florin) + + * 04/05/06:[+] Added atad and dev9 functions names to psxinterpreter.c + (Florin) + + * 01/05/06:[+] Added *pass-through* MagicGate support. It will work with pre-decrypted files + (Florin) + + * 30/04/06:[-] Fixed (almost:P) the debug bios for remote debugging in WinMain.c + [*] Added PSX detection in Misc.c + [+] Added DevBlog.txt file to Docs. Please read and contribute. + (Florin) + + * 15/04/06:[M] Removed some *shit*; please don't commit *.suo/aps/opt/plg/ncb/exp files + [*] added/fixed some scmd commands in cdvd.c + (Florin) + + * 13/04/06:[*] Implemented CDVD Scmd 0x3E(set OSDVER for PSTwo), Thanks to loser for info. + (auMatt) + + * 12/04/06:[!] Uploaded to CVS the latest version, (fixed vc2005 project, + converted all files to CR/LF ending) + [!] When commiting to CVS, please write same text to comment as in here + [*] Changed the _MSC_VER version displaying; hoping ms will keep it linear :) + [*] Implemented properly CDVD Scmd 0x36 (get OSDVER for PStwo) + (Florin) + + * 10/04/06:[!] Changed to version 0.9.1 + [-] Fixed some Vif FIFO bugs and moved VIF interrupt to check the channel has ended + [-] Fixed some counter bugs (better now i can test on my ps2!) + [!] This code is not perfectly stable and contains debug printouts! It is purely for the other + devs who dont have the latest code ;) + (Refraction) + + v0.9: + * 02/04/06:[+] VU0 Rec added, still buggy + [*] VU1 Speedups and fixes, needs more testing but seems better + [*] CDVD Timing Improved wait times for commands reduced. + [-] Misc eeRec bug fixes made + [*] Vif stalls greatly improved loads more games now work! + [*] Counters modified with gates and improved accuracy + [*] Cycle counting in EE/IOP done on branches to cut download + 2D speed up by over double! + [-] Misc VIF unpack fixes + [-] GIF Stalls should now work correctly + [+] Virtual Memory for Windows XP users, quicker than TLB + [*] Difference CPU options can be mixed and matched by users choice + [-] SIF communication fixed, games can now be booted via the bios (in most cases) + [!] Lots of other fixes have been made by due to lazyness we didnt document! :D + [+] MTGS and Dual Core modes added which are VERY experimental! + [!] This is the FINAL code for 0.9 enjoy! + (Refraction, ZeroFrog, Saqib) + * 15/02/06:[+] Multithreaded GS/Dual Core Support + (zerofrog) + * 17/01/06:[-] Some changes in CDVD tray status + (efp) + + * 16/01/06:[-] Fixed sticky flags. + [*] Implemented/Fixed a lot of vu functions in vurec. VuRec now properly checks for underflow/overflow + (zerofrog) + * 15/01/06:[-] Bug fixes in VU rec/interp (Ebit, xgkick). Added 24bit precision for VUs. + [*] Changed all math functions to use the C++ floating point versions. + (zerofrog) + * 14/01/06:[-] VU Flag fixes + double removal (it needed doing) from zerofrog + [-] Disabled an old PSX Counter hack that i left in some how! + [*] Changed SIF reg code to something simpler and less time consuming + (Refraction) + * 13/01/06:[*] Fixed mac update flags for vu interpreter. + (zerofrog) + + * 12/01/06:[-] Changed IPU.c, thread syncing issue fixed by zerofrog + [*] Altered SBUS so it is triggered on PSX dma + [*] Removed a load of IOP hacks, should improve compatability in some cases + [!] A lot of changes have been made since 05/09/05 but weve lost track, whoops + (Refraction Saqib zerofrog) + + * 05/01/06:[*] Added GSreadFIFO2 for faster reads from GS. + [-] Fixed the multi-threaded IPU and added sync primitives for interrupts and DMA. + The green squares should be gone too. + (zerofrog) + + * 05/09/05:[-] Fixed VU-Rec crash if the pc overflowed the vumem, thanks to fumofumo! + [*] New Icon for 0.9 made by CKemu + [+] Vsync rate now selectable, current Vsync speed is default but less compatable in + some cases, option selects real vsync speed, syncs sound correctly. + (Refraction) + + * 03/09/05:[-] IOP rec & VU0rec fix, x86ptr being set in the wrong place, also a couple of vu-rec op fixes + thanks to fumofumo on irc. + [-] Slowed VSync down to actual speed, so sound isnt half the speed of the graphics, + a few more changes to counters as well, BOR works again, just slower ;p + (Refraction) + + * 30/08/05:[-] Few more changes to the counters, seems much better again, last fix killed stuff + [-] VSync rate now actually changes between PAL and NTSC, before it was stuck in NTSC + [-] Couple of changes in VIF + * 24/08/05:[-] Readded setting of Done on VIF1 TTE, added the same on VIF0 + [-] Applied VIF1 FBRST fix to VIF0 too + [-] Fixed problem causing Beats Of Rage to skip and altered slow sound prob again. + (Refraction) + + * 23/08/05:[-] Did some more timing fixes, they should be a LOT more compatable now + [-] Small change to FBRST, was causing crashes if VIF was finished. + [+] Added counter copy to hold on SBUS interrupt + (Refraction) + + * 21/08/05:[-] Few fixes in the eeRec, shouldnt crash on Kingdom Hearts now, Thanks to fumofumo! + [-] Fixed a bug in FBRST and Vif1, altho theres still an interrupting problem somewhere :/ + [-] Int VU now uses Single Precision (its faster) with no loss of graphics. + [-] Made sure MAC, CLIP and STATUS flags are all located on VU0. + [*] Enabled linuz's SSE unpack code, gives a nice little speed boost, works ok :) + [-] VU execute blocks limited to 128, seems a little faster, no loss of graphics, seems + to fix a few looping infinately issues (VU not breaking) (GiGaHeRz) + [-] Hack removed on TLBP, should hopefully work ok, doesnt seem to break anything (GiGaHeRz) + [+] Added SPU2 hack, should fix some games, not compatable with videos tho. removed fast dvd + [-] More counter stuff, also added gating to IOP counters, not totally sure on it. + [-] Added a couple of checks in VU & eeRec to make sure the constant registers werent overwritten + [-] Temp fix for the dma alignment error on GIF + [-] modified dma timings, qwc / BIAS could mess up if qwc = 1 + [-] Singled out some problematic VU-Rec ops that cause FFX to hang and borkey graphics. + (Refraction) + + * 12/08/05:[*] Few more timing things, music shouldnt be slow anymore on games and cleaned up + counters a bit. + [+] Added SBUS register logging on IOP side + [-] Temp fixed a MAC flag problem in vu-rec till linuz sorts it properly + [*] Committed new logo, nice job CKEmu ;) + [*] Vu-Rec now supports non SSE2 processors thanks to kekko for the changes! + (refraction) + + * 05/08/05:[+] Added faster Cd/DVD reads to the Advanced options (Refraction) + [-] The previous DVD/CD change by ref was just a hack, so i commited the old + version again + [-] I've commented out RECOMPILE_VUMI_LOADSTORE on iVUmicro.h, instead + of commenting it out in iVU1micro.c as ref did on last update, + that way is better until i fix the real problem + [*] Improved vuDIV for .x to .x cases + [+] Added PEXTRW/PINSRW + (linuzappz) + + * 05/08/05:[-] Fixed a couple of VU-Rec ops, swapped some over to the interpreter to fix 2d + (thanks to fumofumo for the tipoff) + [-] Yes more timing stuff :P think its as compatable as its going to get now. + [*] DVD/CD reads now considerably faster, some loading times down by 1600%!!! + Compatability still good :) + [-] Fixed a bug in 128bit hardware reads + [-] Fixed a bug i made in VU which messed graphics up eg Frequency and Sega Tennis + (refraction) + + * 04/08/05:[-] More IOP/EE timing fixes, Thanks for the info linuz + [-] Vsync speeds shouldnt be as insane as they were, the target was set as 1/4 the rate + instead of 1/2! + [!] 32bit timer interrupt checks arent working properly eg. overflow only works + when checking if they are equal, on target only works on overflow :/ but the checking + method which was used in SafeIOP is more accurate. + (refraction) + + * 03/08/05:[-] Fixed FTOX in VUrec + (linuzappz) + + * 31/07/05:[-] Reverted to old Branchtarget's, seems to stop the RecUNKs + [-] Fixed the timing a bit between IOP & EE, shouldn't need SafeIOP anymore :D + [-] Removed Pointless While loops on GIF & SPR, also fixed condition where SPR0 + couldn't use destination chain mode + [!] Gating on the IOP needs checking/completing, i have no docs on it so + i can't check the values for it, they seem different to EE :/ + [-] Removed GS Stall checking on GIF, could have caused it not to send data. + [*] Added code for faster V4-32 unpacks when CL == WL + [*] x86 code kept in int format for rec instead of U8 to INT conversion (GiGaHeRz) + (refraction) + + * 21/07/05:[-] Fixed setting of the Double Buffer + [-] Fixed the Branchtarget's for R3000A and R5900 + [*] Altered some stuff in vuflags, seems to give a speed boost :P + (refraction) + + * 18/07/05:[-] Removed some useless & 0xffff on Hw.c + [-] Reverted Sif changes to the old code, + gotta speak about this with refraction + [+] Added VIF1_STAT at vif1Write32, to handled the FDR bit + [-] VIF1 now clears qwc with "from memory" transfer + (linuzappz) + + * 17/07/05:[-] Fixed a bug in VIF where done could be unset + [-] Fixed a couple of bugs in VU + [*] Rewrote SIF0, seems to be a bit more compatable as well + as more readable + [-] Altered the loops for vu(1/0)exec, seems to fix some graphics + without comprimising compatability + (refraction) + + * 12/07/05:[-] Fixed VIF stop on stall occurance (refraction) + [-] Added two common funcs for source chain dmas + [-] Fixed REFE and END (even once again) in dmas + [-] Fixed interrupt i bit issue in Vif1 (on multiple i bits) + (linuzappz) + + * 08/07/05:[-] MFIFO now wraps around the ring buffer when it's full, + in both GIF/VIF1 + (linuzappz) + + * 06/07/05:[-] Bug in DIRECT/HL caused vif errors + [-] Recomitted old VIF0 IRQ stuff, seemed to cause problems + (Refraction) + + * 05/07/05:[-] Fixed IRQ setting for VIF0 transfers (Refraction) + [*] Removed Call/Ret from SPR1, not used (Refraction) + [+] Added some more comments to DMA stuff (Refraction) + [-] Reimplemented the old vifunpack code, since saqib's one + had problems 'in pieces' transfers + [-] ElfHeader now loads the data though the program headers only + [-] Removed tadr+= 16 on refe/end on dmas + [!] I'll start commenting more the code from now on, so it'll + be easier for us to understand every part of pcsx2, others + pls do the same kthx + (Refraction-linuzappz) + + * 02/07/05:[-] Added saqib vif fixes + [-] Fixed Stall canceling stat bits (VIF_STAT_INT) + [-] Fixed Stall bits clearing + (Refraction-saqib-linuzappz) + + * 29/06/05:[*] iR3000A now has defines same as iR5900.c + [+] Added PSXCNT_LOG + (linuzappz) + + * 28/06/05:[+] Added InterlaceHack (usefull for Dinasty Warriors 3) + [+] Added SafeCnts flag, which makes very accurate iop counters, + but they make pcsx2 slower + [+] Added FastIopClk which sets the PsxClk to 86864000 + [!] There are sorta hacks and will go away in time when i figure + out how to really fix them + (linuzappz) + + * 28/06/05:[+] Added SIO plugin specs. Should be followed by compatible plugins :P + (Florin) + + * 22/06/05:[-] Console supports colors ;) + (linuzappz) + + * 19/06/05:[-] Fixed D/T flags (added interrupts) at VU0/1 + (linuzappz) + + * 18/06/05:[-] Rather small fixes to last update in vif, replaced cyclenum + with _vif->cl, also fixed a timing issue in vif0 + (linuzappz) + + * 14/06/05:[-] Alot of bugs fixed in VIF. Masking was not correct so was + filling write. VIF0 was incorrect. The VIF0 Fifo was always being set to 0. + [-] dmaSPR1 now handles Transfer Tag option. + (saqib and Refraction) + + * 31/05/05:[-] Fixed UNPACK's with masking + (linuzappz) + + * 29/05/05:[-] Fixed a few small timing issues with VIF1 + [-] Refixed end source chain tag to add 16 to tadr + (linuzappz) + + * 28/05/05:[*] Uncommented GS dma irq code + [-] Fixed some switch cases at iVUmicro.c + [-] Tested/Fixed DIS_S/MAX_S/MIN_S at iFPU.c + (linuzappz) + + * 28/05/05:[*] removed CVT_S regcaching from iFPU.c. That doesn't seem to work properly :~ + [*] Added MAX_S , MIN_S to reg caching iFPU.c . Not tested but should work + (shadow) + + * 28/05/05:[+] Added PNOR and impoved a few more MMI opcodes + [+] Few more opcodes to ix86_sse.c as well + (shadow) + + * 26/05/05:[+] added emulated hardware cd/dvd sector decryption routines + (should make the playstation2 logo display correctly now amoung other things) + [-] fixed cdvdReadKey to get correct args sent to it, also behaves a little differently depending on args + (loser) + + * 26/05/05:[*] fixed a silly bug in iMMI.c pmaxh,pminh opcodes + [*] optimized PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + [*] few more addes to ix86_sse.c . Linuz seemed to discovered new opcodes :P + (shadow) + + * 25/05/05:[+] Few opcodes added in ix86_sse.c .Few of them still needs recheck (shadow- Gabest) + [*] Added the following SSE,SSE2 opcodes to iMMI.c . + paddub,padduh,paddh,pcpyld,pmaxh,pminh,paddsb,paddsh,psubsb,psubsw,paddb,paddw,psubsb,psubsh + psubb,psubb,psubh,psubw + [*] More opcodes in SSE2 . PCPYUD,PSRLW,PSRLH,PSRAH,PSRAW,PSLLH ,PSLLW ,PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + (shadow) + + * 24/05/05:[*] PSXCLK now can be changed at the ini, defaults + to the right value (36864000) if it's 0 anyways + [-] Fixed bug at Interpreter.c for sstates + (linuzappz) + + * 23/05/05:[-] fixed a bug in iMMi.c PADDSD,PSUBSD doesn't exist in ix86 (who added them?) + [*] Added a new prefix in ix86_SSE opcodes, it is now more clear to understand what each opcode do + that also helped to find that linuz had added an SSE2 instruction in iFPU.c bad linuz ;P + [-] PSMAXSW,PSMINSW was writing to a XMM register (the SSE version writes to MMX register) fixed.. + [+] a few more SSE2 instructions needed for iMMI.c added in ix86_sse.c . + Linuz code them properly pls ;) + (shadow) + + * 23/05/05:[+] Added Devc++ 4.9.9.2 project files for compiling mingw32 with IDE :) + [-] Added a few missing defines + [!] still my project file can't make as fast exe as linuz's sse build. can't figure why yet + the problem should me around Makefile.win :~ + (shadow) + + * 21/05/05:[-] More PS1 compat fixes + [!] Seems the GPU->GS is done by the PS1DRV, gotta find out more + (linuzappz) + + * 19/05/05:[+] PS1 games kinda boot now as well ;) + (linuzappz) + + * 16/05/05:[-] Misc GUI fixes + (linuzappz) + + * 15/05/05:[-] More FPU regcaching stuff + [!] Finally changed version to 0.9 :D + (linuzappz) + + v0.8: + * 10/05/05:[-] Added some more code for FPU regcaching, still unused + [!] Code is closed today until release, only bugfixes now + (linuzappz) + + * 08/05/05:[-] More fixes/improvemets to VUrec/iFPU + (linuzappz) + + * 07/05/05:[-] COP2 now is recompiled when VUrec is enabled + (linuzappz) + + * 05/05/05:[-] Fixed a rather small bug in VIF1 unpack + [-] VU random functions are more correct now, thx goes to _Riff_ and saqib + [-] Sio arranged better for sstates + [*] Modified "FireWire" syms to "FW" + (linuzappz) + + * 04/05/05:[-] Timings in VIF1 should be more accurate now + [-] Fixed bug in the elf loading filter + (linuzappz) + + * 02/05/05:[*] recommited the old reccop2.c (shadow) + + * 02/05/05:[-] Fixed bug in REF/REFS dma at VIF1/GS MFIFO + (saqib) + + * 02/05/05:[*] Cpudialog will disable the checkboxes if the requested features not found + (shadow) + + * 01/05/05:[*] Created a new <> folder to clean up some stuff in the existing interface + Folders became better now and included project files only for vcnet2003 so far... + [*] Moved all patchbrowser source to patchbrowser.c and added language support for it + [*] CpuDialog is now At CpuDlg.c . Redone the Dialog a lotta better ;) + [*] The remaining console,thread,patches configure are now part of the main menu + [*] Organize cpudetection code a bit better. Cpudetection is now done in winmain.c + (shadow) + * 01/05/05:[*] Even more VUrec stuff + [+] Added some more Stats.c info per frame + [-] Fixed some MFIFO bugs remaining + (linuzappz) + + * 30/04/05:[*] More work on VUrec, flags are somehow implemented, PSHUFD is now + used to unpack XYZW/IQ stuff and bug fixes as well :) + (linuzappz) + + * 29/04/05:[-] Updated VIF0 code as VIF1 + [-] VIF1 doens't clears str on MFIFO (saqib) + [-] Fixed some MFIFO bugs in both GS/VIF1(saqib) + [*] Cleaned up dma## functions + (linuzappz) + + * 28/04/05:[-] end source chain tag seems not to touch tadr + [-] Vif1 dmaIrq seems ok, need to test it more tough + (linuzappz) + + * 26/04/05:[+] Added BC1 ops at rec + [+] Started some optimizations for UNPACK + [-] Skipping vif mode was still a bit buggy, seems ok now + (linuzappz) + + * 25/04/05:[*] VIF1 dma is kinda more asynchonous now + (linuzappz) + + * 22/04/05:[+] Added some cache code, not used by default, + it's just for testing atm + (linuzappz) + + * 21/04/05:[-] Readded SysPrintf for Cd/DvdReads + [-] Fixed NReady busy stuff, thx to loser + (linuzappz) + + * 19/04/05:[-] More VUrec refixing/work + (linuzappz) + + * 18/04/05:[+] added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose + to the cdvd plugin definitions + [*] changed CDVDgetType to CDVDgetDiskType + [-] fixed NVM (eeprom) access from cdvd stuff + [+] added reading of mecha version from an external file + [-] fixed raw dvd sector readng for dvd9 discs (otp and ptp) + [+] added hw-reg read/write for DecSet register 0x1f40203A + [+] made cdSeek change the current cdvd sector + [*] incremented cdvd plugin version and brought cdvd plugins in cvs up to date + (loser) + [-] __WIN32__ should not be used over PS2Etypes.h, + __MSCW32__ or __MINGW32__ must be used there + (linuzappz) + + * 16/04/05:[-] xyzw stalls was kinda wrong ;P seems ok now + [-] Fixed a bit vurecs + (linuzappz) + + * 16/04/05:[+] Added GSsetCSR + (saqib-linuzappz) + + * 14/04/05:[-] Fixed some small bugs over VUops.c for the regsNum stuff, + thx goes to saqib + [-] Really fixed skipping vif this time :P + [-] Fixed DIV/RSQRT exceptions (saqib-linuzappz) + (linuzappz) + + * 13/04/05:[-] Fixed skipping write mode at Vif + [-] Fixed unpack overflowing + (linuzappz) + [-] updated all visual studio project files to have the correct source/lib/includes + also removed unused dirs and files. now even 'debug config' will build ok :) + (loser) + + * 10/04/05:[-] Fixed stalls for VF regs, xyzw must be handled separatedly + (linuzappz) + + * 04/04/05:[-] Kinda reworked VU MAC flags, also fixed RSQRT neg prob, thx to Riff/saqib + [-] Fixes to VifDma cl/wl stuff + (linuzappz) + + * 03/04/05:[*] Modified a bit how branch works on VUs + (linuzappz) + + * 02/04/05:[-] Some fixes to VU flags/pipelines + (linuzappz) + + * 30/03/05:[*] Cleaned up a bit writes to VIFX regs + [-] Fixed a small bug in vif1 stalls + [-] Commented readclock win32 code at CDVD.c + [-] Fixed two small issues with branches in interp + (linuzappz) + + * 29/03/05:[*] Added some fixes from LDChen to hConsole/WM_PAINT stuff + [*] Modified GetToc stuff in cdvd to support dvds + [*] cdvdTD uses lsn now + (linuzappz) + + * 28/03/05:[+] Added placetopatch == 1, which means patches will be applied every vsync ;) + (linuzappz) + + * 27/03/05:[*] Improved cpu detection for Amd's 64 using BrandID. Most of the models should be + detected correct now (at least my cpu does ;P) (shadow) + + * 24/03/05:[-] Fixed ISUBIU :D + [-] Some fixes to flags, status was fecked, now seems better + [-] Commented the GS dma IRQ again, seems to cause more probs, will + fix it later + (linuzappz) + + * 21/03/05:[-] Fixed VIFX_CODE reg + [+] Added previous normal vu fixes to vurec + [*] Added EFU pipeline to VUmicro, kinda untested + [-] Hopefully fixed GS dma IRQ + (linuzappz) + + * 21/03/05:[-] Fixed cdReadKey function to emulate correctly. Now games should boot using + Execute with non Modded Bios. + (auMatt & Loser) + + * 20/03/05:[-] Started reg caching for VUrec ;D + [*] Rearrenged a bit rec32/64, added a common 'x86' dir + (linuzappz) + + * 18/03/05:[-] VU1micro was being executed instead of VU0, bad linuz bad :P + [-] Fixed VU's JR/JALR/BAL :D + (linuzappz) + + * 17/03/05:[-] Cleanup/speedup/fixup from last fixes :P + [-] VIF0 has no from mode ;) + (linuzappz) + + * 16/03/05:[*] Added some more debug info to CDVD + (auMatt) + + * 15/03/05:[*] Added an evil vuDouble function to convert from vu float format + to ieee 754 format ;) + [-] Reworked MAX/MINI + [+] Added experimental work for VU pipelines + (linuzappz) + + * 14/03/05:[-] Added the pipelines VU1 bug to VU0 + (linuzappz) + + * 12/03/05:[-] Fixed some pipelines bug within VU1 + (linuzappz) + + * 10/03/05:[-] Fixed small bug over VIF1 dma FIFO + (linuzappz) + + * 08/03/05:[-] Fixed vu flushing over vuExecMicro + (linuzappz) + + * 06/03/05:[-] Fixed UNPACK V4_5 with mask + (linuzappz) + + * 04/03/05:[-] Small fixes to VUrec + (linuzappz) + + * 01/03/05:[+] Added new VS2005 sln and .vcproj to build the 32bit version of + pcsx2 in VS2005 Beta1 (You have to use different projects to build) + [*] Changed some of the files to make them compile in VS2005. + (GoldFinger) + + * 23/02/05:[-] Commented hack at VSync + [+] Added interleave mode for SPR + (linuzappz) + + * 20/02/05:[*] Changed IRQ defines to functions + [-] VIF irq by vifcode seems ok now + [+] Added offset/difference with mask UNPACK modes in vif + [-] SPR1 was transfer /4 the size it should have :/ + (linuzappz) + + * 16/02/05:[-] Fixed some VPU-STAT related issues + [+] 'sstates' dir is now created at init + (linuzappz) + + * 15/02/05:[+] Another DNAS by nachbrenner + (linuzappz) + + * 14/02/05:[+] Added offset/difference UNPACK modes in vif + (linuzappz) + + * 14/02/05:[*] 64bit rec back to x86-64 better this way + [*] Updated vsnet2005beta1 project files to compile with x86-64 dir + [*] Added a few pragma warnings disable to a few files to correct some silly vsnet2005beta1 + warnings (blah MS deprecated stdio pffff) (shadow) + + * 10/02/05:[-] Fixed bug in CDVD_findfile + (linuzappz) + + * 09/02/05:[*] GSvsync is now called on the vsync start + (linuzappz) + + * 08/02/05:[*] QWC is set to 0 after a normal transfer in GS/SPR1/VIF1 + and MADR is increased qwc*16 as well + (linuzappz) + + * 07/02/05:[*] Changed a bit the CPU dialog. Now it is better i guess :) . Linuz update the pcsx2.po again pls :D + [*] Added a __VCNET2005__ definition cause vcnet2005beta1 doesn't support inline asm.. + That only effects Cpudetection.c and Gte.c (not much since it has c code instead to use). + Cpudetection must be written on ml64 to be useable on vcnet2005. + [*] Added prelimary vcnet2005beta1 project files. gettext disabled cause we still doesn't have a + 64bit version for it + [*] Small fixes around and wholaaa i produced the first buggy pcsx2_64bit.exe :) (shadow) + + + * 07/02/05:[+] Added another DNAS version thx to Nachbrenner + [-] Fixed SPR0 chain mode + [-] Fixed intc/dmac interrupts that gets cleared right away + [-] Cleaned up langs a bit, only spanish works so far now + [+] Added 1f402007 reg, "BREAK", still not really handled ;P, + thx to matt + (linuzappz) + + * 31/01/05:[-] Disabled recompile functions recBGEZ() and recBLEZ() from iR3000.c . That will make + recompiler not to crash after the players selection screen in Virtua Fighter 4. Thanks + to JayteeMaster for bug tracing it ;) (shadow) + + * 30/01/05:[-] Fixed some more bugs in IPU, some streams had a few problems, now they are ok. + Quality of ipu playback also improved(thanks JayteeMaster for pointing it out) + (asadr aka saqib) + + * 26/01/05;[*] Merged a big part of linuz's amd64 rec to the normal rec (shadow) + + * 25/01/05:[-] Finally fixed IPU. Mpegs and IPU streams run + so do PSS files.Some fixes to MMI and Interpreter (asadr) + + * 23/01/05:[-] Fixed vurec crash on pcs that doesn't support SSE2 + [*] General cleanup on ix86-32 rec. Goldrec removed since no progress has been made + lately (shadow) + + * 20/01/05:[+] Added x86-64 rec, still unclean, but i'll leave for holidays this + saturday, so ^^ + (linuzappz) + + * 19/01/05:[-] Fix for end chain mode at vif, still gotta check it + (linuzappz) + + * 16/01/05:[-] Lots of fixes to VUmicro, thx to Refraction for pointig out + some bugs ^^ + [*] Commited ix86 changes for x64 + (linuzappz) + + * 13/01/05:[-] WriteNVM now takes address in param[1], thx to auMatt + (linuzappz) + + * 06/01/05:[-] Fixed long types at VU.h + [-] Removed memLUT decl + [!] Notice long is 8bytes long in amd64, so we should + stick to the u32/s32 types instead of using long pls :) + (linuzappz) + + * 06/01/05:[-] Fixed SBUS IRQ at iop + [-] dmaGetAddr now uses memLUTR + (linuzappz) + + * 05/01/05:[*] Changed some stuff for amd64, still more to come + [+] Added more memRead/Write funcs for speed + [-] Fixed some iVUmicro bugs + [-] Fixed QFSRV/MTSAH/MTSAB + (linuzappz) + + * 03/01/05:[+] Implemented MFLAG for VU0 + [-] Vsync is now genereted on boths cpus at the same time + (linuzappz) + + * 03/01/05:[-] Commented dma irq stuff, fecks some games, gotta recheck that + (linuzappz) + + * 22/12/04:[-] Fixed bug in branch address in vus + (linuzappz) + + v0.7: + * 18/12/04:[*] Added GSread8/16/GSwrite8/16, GSgifTransfer1 now has two args, + added the addr and pMem points to the VU1 mem + (linuzappz) + + * 16/12/04:[*] Pofis improved his Patchbrowser (shadow) + + * 06/12/04:[-] Fixed Langs support for win32 + (linuzappz) + + * 06/12/04:[*] Added support for 1.90 Bios NVM. + (auMatt) + + * 06/12/04:[+] Added Patch Browser for win32 . Made by Pofis (shadow) + + * 05/12/04:[*] NVM always loads rom %Bios%.NVM + [*] Cd/Dvd Reads are now again displayed on console, + that is very helpfull for testing :) + (linuzappz) + + * 28/11/04:[-] BC2T/F/TL/FL also check for VU1 to be stopped + [-] VU1 memory is masked on micro load/store instructions, + dunno yet about VU0, gotta test ;) + (linuzappz) + + * 26/11/04:[-] VU D/T flags are handled now (kindaof :P). + (linuzappz) + + * 20/11/04:[-] RTC timezone fixed (gigaherz) + + * 19/11/04:[-] Fixed vu branch negative overflows + (linuzappz) + + * 17/11/04:[*] Fixed some stuff in logging so now + -Memcards sysprintf messages Are now MEMCARDS_LOG define and enable with PAD_LOG + -Cdreads Dvdreads are now in CDR_LOG + -Vus Overflow enable from CPU_LOG + That means less logs at runtime and no more complains from nasty betatesters :D (shadow) + + + * 17/11/04:[*] fixed linuz bug in naming the memcards different in 2 different places + Memcards now are Mcd001.ps2 and Mcd002.ps2 in emu and McdDialog (shadow) + + * 16/11/04:[-] Fixed NVM File Load and Creation. Defaults to BIOS name als now. + (auMatt) + + * 15/11/04:[+] Added another DNAS at Misc.c. + (nachbrenner) + + * 14/11/04:[-] VU0/1 reset shouldn't reset the micro memory. + [*] Commented the LT_OpcodePrintTable call on Interpreter.c, + for speed :) + (linuzappz) + + * 12/11/04:[-] Second MCD works fine now. + (linuzappz) + + * 11/11/04:[-] Finally fixed SIF1 bug :D:D + (linuzappz) + + * 10/11/04:[+] Added MingW32 support ;). + (linuzappz) + + * 10/11/04:[-] Fixed NVM loading/reading/writing and also fixed v12 NVM issues. + (auMatt) + + * 09/11/04:[+] Added BiosVersion var. + [*] Sif stuff now gets saved over sstates. + (linuzappz) + + * 09/11/04:[-] Fixed bug in ModelID code in CDVD + (florin-auMatt) + + * 07/11/04:[-] Fixed bug that caused to interrupt twice before + handling the first interrupt. + (linuzappz) + + * 05/11/04:[-] Small fix for broken elfs. + (linuzappz) + + * 04/11/04:[-] CDVD was interrupting dma too much :P. + (linuzappz) + + * 03/11/04:[*] Added FREEZE_SIZE. + (gabest-linuzappz) + + * 03/11/04:[+] Added a couple of DNAS at Misc.c. + (nachbrenner) + + * 02/11/04:[+] Added hack for QFC in GS ;). + (linuzappz) + + * 01/11/04:[+] Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2. + (linuzappz) + + * 31/10/04:[-] Fixed v12 bios running. + (auMatt) + + * 30/10/04:[-] Fixed v9-v10 bios running. + (auMatt) + + * 28/10/04:[-] Really fixed SIF SMFLAG/MSFLAG :P:D + (linuzappz) + + * 28/10/04:[-] Fixed MCDS :D + (asadr) + + * 26/10/04:[*] Added rom2/erom support + (auMatt/linuzappz) + + * 23/10/04:[*] Added/Fixed Model Number Reading + (auMatt/Florin) + + * 18/10/04:[-] Fixed SIF SMFLAG/MSFLAG, needs testing tho + (linuzappz) + + * 06/10/04:[*] More BIOS detection added.(auMatt) + + * 04/10/04:[-] Fixed EXL bug + [-] Fixed SIF0/1 when fifo got filled up + (linuzappz) + + * 01/10/04:[-] CdReadConfig/CdWriteConfig now uses NVM ^^ + [!] Bios configurations now gets saved/loaded from NVM (nvm.raw) + (linuzappz) + + * 1/10/04:[+] Started coding the memcard manager. Far from finish but will be better soon :D + [*] Change settings . Default memcard is now a ps2 memcard. (shadow) + + * 30/09/04:[-] Newer bios will now work with pcsx2. Pads fixed, more + compatibility. (asadr) + + * 27/09/04:[-] VU0/1 Reset hopefull fixed + (linuzappz) + + * 16/09/04:[*] NVM now is readed/written from nvm.raw. + [-] ReadILink/GetMecaconVersion are really implemented ^^ + (auMatt-linuzappz) + + * 15/09/04:[*] Rewritten LoadConfig-SaveConfig to use ini instead of registry. + [*] Removed DeleteRegistry button. For obvious reasons :D (shadow) + + * 15/09/04:[-] Pads finally fixed - Fixed PADwin Plugin Required! + Updated stuff at PsxSio2.c and Sio.c (Pad Hack still + there but won't be used) asadr + + * 13/09/04:[+] Added an option for setting the main thread priority, usefull at work :P + (linuzappz) + + * 13/09/04:[*] Fixes to SCMD's (auMatt) + * 02/09/04:[*] Finally commited asadr's IPU changes + [-] Fixed small bug in memory dump for win32 + (linuzappz) + + * 30/08/04:[*] Added Deci2 Call back into the Interpreter.c for printf.(auMatt) + + * 18/08/04:[*] fixed finaly the IOP disasm. Should be correct now... + [+] for stuff for amd64 porting.notice that pcsx2_2003_amd64 project just check for 64bit + portability.Can't produce 64bit exe yet.. (shadow) + + * 15/08/04:[-] fixed the IOP-EE disasm problem.(for ppl with vc != 2003 you must include + DisR3000asm.c and DismAsm.h in your project files) + [!] Still have to finish the correct IOP disasm :D + [+] Added small framework for x86-64. Still nothing that useable :D (shadow) + + * 04/08/04:[-] PadHack now works again :) + [-] Sio2 now supports states again + (linuzappz) + + * 02/08/04:[*] F2 will print the selected state on the console + [*] Added overflow messages for ISW/ILW/ILWR/ISWR + [*] FBRST should reset the vus when VU0 Reset/VU1 Reset + bits are set, but i don't really know have much it's + resetted :P + (linuzappz) + + * 30/07/04:[-] Vif1 MPG lacked a flush + (linuzappz) + + * 28/06/04:[+] Added GSprintf, GSgetDriverInfo and PADgsDriverInfo + [+] Deci2Call 0x10 gets printed ;) + [-] Some fixes to CDVD reading + (linuzappz) + + * 24/06/04:[-] Fixed some bugs over interrupts and + exceptions + (linuzappz) + + * 22/06/04:[-] Couple of bugs fixed over IPU1 dma + [-] psHu32(INTC_STAT) changed to INTC_IRQ + (asadr-linuzappz) + + * 16/06/04:[-] Counters regs are returned in 16 bits + [+] Also added them for hwRead16 + [-] Counter only resets when writing to the mode reg + when the value & 0x3ff differs from the actual mode + [-] Fixed BCR interrupting for CDVD ;) + (linuzappz) + + * 14/06/04:[*] Enabled SSE Vif at i386.asm + [*] Added florin's work over mcds, still needs + a cleanup :) + (linuzappz) + + * 10/06/04:[*] CSRr is OR'd with 0x8 always over VSyncEnd + (linuzappz) + + * 08/06/04:[*] VU pointer gets aligned now + (linuzappz) + + * 07/06/04:[*] vuJALR now uses _Fs_*8 + [*] VSync now interrupt for INTC_STAT & 0x1 + [!] Based of debugging Aura for Laura :) + (linuzappz) + + * 07/06/04:[*] Detection for Chinese Bios. + (auMatt) + + * 04/06/04:[-] Cleaned a bit VIF1transfer, and now when + DIRECT/DIRECTHL cmd is misaligned it skips it + [*] Added USBirqHandler, USB specs v2 now + (linuzappz) + + * 04/06/04:[-] VU1 regs now are mapped to VU0 mem + (linuzappz) + + * 02/06/06:[*] finished most of the iops disasm works :P + [*] increase the firewire reg size . seems there are more regs ;p (shadow) + + * 25/05/04:[-] Fixed big stupid bug in counters ;P + Now they're accurate + (linuzappz) + + * 25/05/04:[*] Included new BIOS detection 'P'. For Free and Public BIOS Images. + (auMatt) + + * 20/05/04:[*] BCR now decrements for each cdvdReadSector, thx to Roor + (linuzappz) + + * 18/05/04:[*] Removed PsxBios2.c/h, and cleaned Irx funcs from ElfHeader.c/h + [+] Added cpuTestHwInts/cpuTestINTCInts/cpuTestDMACInts + [+] More work over mcds + [!] Now cpuBranchTest doesn't checks for irqs + (linuzappz) + + * 17/05/04:[-] Fixed bug psx counters, thx gold + (linuzappz) + + * 15/05/04:[+] Added IOP disasm in the debugger... + [!] Not yet finished and i disasm using R5900disasm atm. I will code it correctly soon (shadow) + + * 12/05/04:[*] More optimizations to the FPU rec + [*] BIAS was commented over Counters.c :/ lol + [-] Disabled EMMS_TRACE, it's buggy, dunno why tho + (linuzappz) + + * 11/05/04:[*] Now Saving/Loading FPU CW only for the ops that really need it + [*] Added some optimizations to jumps over rec + [*] Added LQC2/SQC2 + (linuzappz) + + * 08/05/04:[-] Fixed states loading/saving from the menu + (linuzappz) + + * 03/05/04:[*] Uncommented the sio2 1d100 hack + (linuzappz) + + * 3/05/04:[+] started reorganize the src. Lotta unneccesary stuff removed(like HLE) and lotta + organized. still needs a lot of work to clean but it's a start (shadow) + + * 02/05/04:[+] Added D3/D4 defines at Hw.h + (linuzappz) + + * 1/05/04:[+] Added a Delete Registry Button. It deletes pcsx2,gssoft settings + (shadow) + + * 30/04/04:[-] Small bugfix for cpu speed detection, thx to Rainer Aglas + (linuzappz) + + * 27/04/04:[+] Implemented ReadNVM/WriteNVM, untested though + (linuzappz) + + * 15/04/04:[-] SPUdma timings changed to 80, thx _Riff_ + (linuzappz) + + * 13/04/04:[*] Several changes for IPU + [+] IsBIOS now belongs to Misc.c + (asadr-linuzappz) + + [*] Dev9Null/USBLinuz/FireWire Plugins Configure now shows + Message. + [*] Configure Menu Shows USB and FireWire Options. + (auMatt) + + * 12/04/04:[-] Fixed SPU2async cycle, was getting reseted wrongly, + thx _Riff_ + [+] Added SPU2irqCallback + (linuzappz) + + * 08/04/04:[-] Unhacked sio2 for 1d100 recv1 mode + (linuzappz) + + * 07/04/04:[+] FireWire IRQ is implemented ok now + [-] Forgot dev9Interrupt over R3000A.c + (linuzappz) + + * 05/04/04:[+] Added Firewire plugin protocol. (shadow) + + * 02/04/04:[-] VIF-FIFO transfers seems to work better ;) need testing + [+] Added GSreadFIFO + (linuzappz) + + * 30/03/04:[*] sstates now use CRC as well :) + [*] emuLog.txt now goes at 'logs' dir + (linuzappz) + + * 29/03/04:[*] GSdma now waits qwords transferred cycles + before clearing CHCR and triggering, + OPH and APATH are handled as well now. + (linuzappz) + + * 25/03/04:[*] Some rewritte over Sio.c + (linuzappz) + + * 24/03/04:[-] ostr size is now 1024 in Dis*.c + [!] Finally v0.7 :D + (linuzappz) + + v0.6: + * 21/03/04:[-] About dialog was cropping the testers, thx CK :) + (linuzappz) + + * 19/03/04:[+] Added a PadHack option at the cpu dialog + [-] Couple of fixes for release + (linuzappz) + + * 16/03/04:[-] CRC had a bug, now it's ok, sorry :) + [-] Fixed bug in memInit, thx gold :) + [-] LoadState now loads the tlbs + (linuzappz) + + * 16/03/04:[-] Fixed another silly bug in loadElfFile ;) + (linuzappz) + + * 15/03/04:[+] Added texts on the console Title to make patch makers life easier :P (shadow) + + * 15/03/04:[-] Fixed a free in loadElfFile + (linuzappz) + + * 14/03/04:[*] loadElfFile now reads the whole file first + [-] DMA4/7 interrupt timings are more accurate now + (linuzappz) + + * 12/03/04:[+] Added i386.asm, only used on linux so far, + compiles using nasm, it replaces the inline + assembling for Vif + [-] Fixed bug in UNPACK for skipping write + (linuzappz) + + * 11/03/04:[*] Patches names are now using crc, + instead of ie.: + Ridge Racer V PAL was SCES_500.00.pnach, + now it is 5BBC2F40.pnach + this way games with the same code + will not get confused + [-] Fixed bug in disR5900GetUpperSym + (linuzappz) + + * 10/03/04:[+] Added SQ/LQ over iVUmicro + (linuzappz) + + * 09/03/04:[-] sio2Reset was missing from psxHwReset + [-] Fixed sio pad swaps for 0x1100 mode + (linuzappz) + + * 08/03/04:[*] Modified the DEV9irq stuff + (linuzappz) + + * 05/03/04:[-] DEV9irq now issues a SBUS_IRQ + [*] malloc memory is now aligned to 16bytes + (linuzappz) + + * 02/03/04:[-] Added presaving for MMI ops that needed that + [-] vuJR/vuJALR now masks Fs with ~0x7 + (linuzappz) + + * 02/03/04:[+] stats.txt now dumps the Cpu mode + (linuzappz) + + * 01/03/04:[-] dmaGetAddr now uses memLUT + [+] Finally added USB plugins ;) + (linuzappz) + + * 26/02/04:[-] Fixed VUops that didn't have presaving + (linuzappz) + + * 22/02/04:[+] More ops at DisVUops.h + [-] VifDma.c is cleaner now, also fixed some + stuff for savestates + [-] Added some remaining vars at cpuBranchTest + to cpuRegs for savestates + (linuzappz) + + * 21/02/04:[-] Fixed ITOF0 + (linuzappz) + + * 20/02/04:[-] Fixed savestates ;) + (linuzappz) + + * 19/02/04:[*] VUflags now should handle overflow/userflow ok + (linuzappz) + + * 17/02/04:[*] Improved and fixed sio2 stuff + [-] Fixed _vuMFIR + (linuzappz) + + * 16/02/04:[-] DIV could crash when divisor == 0.0, + as well as ERSADD + (linuzappz) + + * 13/02/04:[-] Fixed FCAND over VU1ops.c + [*] Merged VU1ops/VU0ops/Vops to VUops + [*] Cleaned up VUflags.c + [-] hackedRecv now defaults to 0x1100 + (linuzappz) + + * 09/02/04:[-] VifDma.c MPG now clears the VU0/1 Mem though Cpu->ClearVU0/1 + (linuzappz) + + * 09/02/04:[-] More SCMD functions added. Still require working code for them. :) + (auMatt) + + * 06/02/04:[-] More iVUmicro.c opcodes, fixes, and stuff :) + (linuzappz) + + * 06/02/04:[-] Fixed Bios Detection for HK Bios. + (auMatt) + + * 06/02/04:[-] Fixed CdRom/CDVD Interrupt for 0x41000200 chcr, + now it interrupts after the read ends + (linuzappz) + + * 05/02/04:[+] Added FALSE/TRUE in GRecCommon.h + [+] Added more 16bit ops to x86.c/h + [+] Fixed SQD/SQI and implemented IOR/IAND over iVUmicro + [-] BIAS is now 2 again + [+] Now only MARK is writable at Hw.c, for vif0/1Regs + (linuzappz) + + * 03/02/04:[-] Fixed FALSE to GREC_FALSE in GRecMain.c + [-] Added break to F5 ;) + [-] Commented 'ERL Set' SysPrintf + (linuzappz) + + * 02/02/04:[-] Included stdarg.h in GRecCommon.h + [+] Added some scmds to CDVD.c (auMatt) + [+] cdvd.Status now changes to CDVD_STATUS_SEEK_COMPLETE, + after a CdRead CMD + (linuzappz) + + * 16/01/04:[+] Added LQI/LQD/SQI/SQD over Recompiler + [-] Updated EE BIAS to 8, need to test this + [!] SQI/SQD are diabled still, because they are still buggy + and i don't have more time... vacations :D:D + (linuzappz) + + * 15/01/04:[+] Added code for dma interrupts, for IPU FDEC, still commented + (linuzappz) + + * 14/01/04:[+] Temporary fix for PADS. F5 now change the pad mode on the fly. if your game doesn't work + switch it from there. (shadow) + + * 12/01/04:[*] FIFO is now really 128bit as it should be :) + (linuzappz) + + * 09/01/04:[-] Fixed VU->VI[0] != 0 bug in VU1, VU0, Macromode, JALR, BAL, LQI, LQD, SQI, SQD were setting VU->VI[0]. + Address in VCALLMS was incorrect, was causing crash in VF4. + (asadr) + + * 09/01/04:[*] Start to convert VIF stuff to functions instead of macros, right now I just converted + them duplicating the code for VIF0/1 and it is working but it is not the best yet, + commiting just so others can debug VIF while I finish the work, did some minor fixes + on VIF too. + [*] The only major function needed to be reduced to one is VIF0transfer/VIF1transfer, all + others are ok (I think). + (GoldFinger) + + * 09/01/04:[-] Fixed LQC2 for _Fs_ == 0 + [*] Fixed several SIF bugs (NoComp) + (linuzappz) + + * 06/01/04:[-] Fixed UNPACK modes in VIF.c, the Indeterminate fields are now set to 1 by default. (asadr) + + * 04/01/04:[-] Fixed a bug in LQD and LQI when _Ft_ was 0. + (GoldFinger) + + * 04/01/04:[*] Modified the VIFregister structure, both VIFs(0,1) have the exactly same + structure, just VIF0 does not use some of the registers, so I unified the + structures for easy reading and less bugs. + (GoldFinger) + + * 31/12/03:[-] Added USB API at PS2Edefs.h ;) + [+] More ops at DisVUops.h + [*] UNPACK now flushes the VU micro + (linuzappz) + + * 30/12/03:[-] Fixed savestates in Misc.c and added fixed VIFdma.h + (asadr) + + * 29/12/03:[-] Fixed bug for new vu code in savestates + (linuzappz) + + * 27/12/03:[-] Fixed bug in my last update for R5900.c + (linuzappz) + + * 26/12/03:[*] VUflags are now updated when Rd == 0 as well, changed only + at VU1ops.c + [*] VU1Regs/VU0Regs is now VURegs + [!] I think we should merge VU1ops/VU0ops/Vops + (linuzappz) + + * 24/12/03:[-] Fixed DMA8 for PsxDma.c + [*] LUI is now as it was before asadr's update + [*] readded 'if Log' over debugI at Interpreter.c + (linuzappz) + + * 18/12/03:[*] Restructured VU code and VIF. Fixed stuff in Interpreter + and added CTC2 VU1 Microinstruction caller. + (asadr) + + * 18/12/03:[*] Improvements to TLB code. + (linuzappz) + + * 17/12/03:[-] Fixed iCP0.h define to __ICP0__ + [+] Added disR5900GetUpperSym + (linuzappz) + + * 08/12/03:[+] SSE recompile of vus started. Some opcodes works some yet not. + Missing flags that i gonna add soon. Gives some speed boost :) + (shadow) + + * 05/12/03:[-] Fixed bug in GS for CSR stuff + (linuzappz) + + * 03/12/03:[+] Added Interlock for CFC2/CTC2 + [-] Fixed CFC2/CTC2/LQC2/SQC2, they now + check for zero registers + [!] This should fix the 'R0 is not zero' + and the 'VU memory overflow' hopefully ;) + (linuzappz) + + * 03/12/03:[+] You now disable vu0 macromode too when you disable vu recs by the + checkbox iR5900.c + [-] corrected some more bugg0rs of linuzappz sse instructions ix86_sse.c + [!] careful linuzappz's code. Don't ever trust him cause he is a lazy bugg0r + His mind is only for pampita!:) (shadow) + + * 02/12/03:[+] Added UNPCKLPSRtoR and MOVLHPSRtoR, there you go expert :) + (linuzappz) + + * 01/12/03:[-] Fixed savestates + (linuzappz) + + * 30/11/03:[+] a few sse instructions in sse.c + a much cleaner code in reccop2.c (shadow) + + * 28/11/03:[-] Recommited old VUops.h with asadr's EATANxy/EATANxz bugfixes + [!] asadr, the VUops.h you commited was in html format, + and some opcodes you change were only to slow down things, + commit other ones that need fixes. + (linuzappz) + + * 28/11/03:[-] Fixed alot of bugs in VUops.h, hopefully some stuff will now + work as it should (asadr) + + * 27/11/03:[*] fixed some stuff in recCOP2.c (shadow) + + * 25/11/03:[-] Fixed bug in Vif.c, masks hopefully are ok now ;) + (linuzappz) + + * 25/11/03:[-] Fixed Interpreter.c ix86.h include + [-] Added to GRecBasic.h a newline at end of file, linux + complains else ;P + (linuzappz) + + * 24/11/03:[+] Added cpu detection in interpeter.c too so now you can use SSE,MMX code in + interpreter too without the fear that your pc doesn't support it ;P (shadow) + + * 22/11/03:[+] By Nachbrenner request i added a memory patcher in Debugger.Now you can make patches + while pcsx2 is running. It is not yet finished as it can only patch 32bit data but + all the patches so far are 32bit so no problem ;P (shadow) + [!] Update Common.h . We are up to pcsx2 0.6 now! :) + + v0.5: + * 21/11/03:[-] Fixed Vif.c bugs :) + [!] Source code closed for release 0.5, + only bugfixes con be submitted + (linuzappz) + + * 21/11/03:[*] Started optimizing vif.c but I find so many strange stuff (problably bugs), please + linuz, check the comments I added on the vif.c file, and tell me what to do. + (GoldFinger) + + * 20/11/03:[*] Reorganize the cpu dialog a bit and added a new option. Disable vu recompiler + with disable the recompile of vu and will save some games from freeze when + vu memory overflows (quite often) :P . This will be removed when vu problems will + solve :P (shadow) + + * 19/11/03:[-] Fixed bug in savestates + (linuzappz) + + * 18/11/03:[*] Removed the old reg caching code including the sources, so now the only rec + that works is the normal one. + [*] GoldRec is progressing, I did lots of changes to make the progress better, + right now nothing works. + (GoldFinger) + + * 14/11/03:[*] Modified GSfreezeData, now it's plugin dependant + [+] Added SPU2freeze/DEV9freeze + [-] Fixed bug in inifile_read, hi shadow bugg0r :P + [-] Fixed bug in Sio2 + (linuzappz) + + * 14/11/03:[*] change pcsx2 patch system to use *.pnach files.Now you need a patches dir in your + pcsx2. (shadow) + [!] Am i the only one that write a changelog here?? (shadow) + + * 13/11/03:[-] fixed savestate naming in win32 and linux (shadow) + + * 06/11/03:[+] cleaned up a bit rec vu and enabled vu0 micro (shadow) + + * 06/11/03:[-] Workaround in VifDma.h for FiFo transfer ;) + (linuzappz) + + * 04/11/03:[*] Changed the way we handle SPR TTE transfers, also + MFIFO_VIFtransfer transfer always the ptag+2 + [-] Unhacked Sio.c for PADs ;) + [!] Now you gotta use the PADwinKeyb from PADwin at cvs + (linuzappz) + + * 03/11/03:[-] Fixed ba8R16 bug in Memory.c + [*] Enabled VU1 micro recompilation + [*] dmaGetAddr goes though memLUTR now + (linuzappz) + + * 02/11/03:[-] Fixed MSUBA had the same problem as MSUB, iFPU.c + A = A - B * C != A = B * C - A :) + (GoldFinger) + + * 01/11/03:[+] Addded cpu speed detection in cpu detection code + [!] Linuz fix the cpu_detection.c to work with linux pls ;p + [!] Goldfinger was right.Police 24/7 is okay with MSUB now :) (shadow) + + + * 01/11/03:[-] Fixed MSUB (MADD was ok), iFPU.c + Expert, please try in Police 24/7... :) + (GoldFinger) + + * 31/10/03:[-] Fixed PCPYLD, MMI.c + (linuzappz) + + * 30/10/03:[-] disable MADD,MSUB from iFPU. that ops was causing bugs in police 24/7. + Can't figure why, can someone? (shadow) + + * 29/10/03:[-] Commented D/T flags for VUmicro + (linuzappz) + + * 28/10/03:[-] Fixed memory rec issue, blah, shadow was right again :P + (linuzappz) + + * 27/10/03:[-] More fixes to memory stuff, hwregs for 128bit + [-] Fixed vifNum == 0 for UNPACKs + [-] DEV9_R_DEV now goes though DEV9read16 :) + [+] FiFo VIF1 can read data now ;) + [-] Fixed rec mem limit, shadow was right ;P + [!] Try Make Your Dream Home now ;) + (linuzappz) + + * 26/10/03:[-] Fixed Memory stuff, now it works ok :) + (linuzappz) + + * 25/10/03:[*] Some changes to memory cards. It's not what you all expect:P + (Florin) + + * 25/10/03:[*] Improved more the cpudetection routine at the Supporting Instruction sets features + [-] Improved a bit the MMI and fixed some bugs that prevent PII cpus to work (shadow) + + * 23/10/03:[-] Fixed a bug in Memory, untested actually ;), should fix + the loader rec bug + (linuzappz) + + * 24/10/03:[*] Improved the cpudetection routine in goldrec.Now more info appears :) + (shadow) + + * 23/10/03:[*] Improved VIF for transfers in parts + [-] Fixed some bugs in DisVUops.h ;) + [-] Fixed a bug in Memory, VU1.Mem was twice, thx shadow :D + (linuzappz) + + * 21/10/03:[-] Scratchpad memory was set bigger that it really is + [-] Uncommented a few tlb related printfs just in case ;) + (linuzappz) + + * 20/10/03:[*] Rewritten several Memory.c code, it's very untested, so far + i only tested bios, so tell me what's broken now :) + (linuzappz) + + * 18/10/03:[*] Fixed the rec for use with the tlb code, but this is a no go, slow as hell we must + change the whole tlb stuff, please linuz, lets think better before implementing this. + (GoldFinger) + + * 14/10/03:[*] Modified the memRead functions, now they're better for tlbs + misses, but note that they have one more arg, so gold, you'll + have to update the rec + (linuzappz) + + * 12/10/03:[*] Removed the new module in cvs called GoldRec. Now GoldRec is a directory under ix86-32. + (GoldFinger) + + * 10/10/03:[*] Removed the new recompiler from the main project and removed its dependencies, now there + is a new module in cvs called GoldRec, you must check it out. + (GoldFinger) + + * 10/10/03:[*] Improved TLB stuff a lot ;) + (linuzappz) + + * 07/10/03:[-] Fixed bug for recompiler in psx writes from Memory.c + (linuzappz) + + * 06/10/03:[*] VU0/1 now uses the VURegs struct + [+] Added the possibility to load the System.map from ps2linux + [+] Added TLB exceptions + [-] Fixed psxM accesses from Memory.c + (linuzappz) + + * 04/10/03:[*] rewrote the recompiled vu micro startup code and separate it + [-] remove the 3dnow code for reccop2 as it created more problems that it actually solved + [+] qmf2,qmtc2 is now done in SSE too . (shadow) + + * 01/10/03:[+] Handle for the EDI flag at ERET, a guess actually ;) + (linuzappz) + + * 30/09/03:[*] Reg caching works with bios and almost everything as normal rec does, need to + check better what does not work. + [*] Splitted iR5900.c into several .c files for easy navigation and for sanity + purposes as iR5900.c was HUGE. + [-] Fix LOTS of reg caching bugs, the main one was the comparission of 64bits registers. + (GoldFinger) + + * 30/09/03:[*] Added a base interrupt delay for the dma7 (spu2) + [*] More improvements to VifDma.h + (linuzappz) + + * 29/09/03:[-] Reimplemented Interrupt latency over R5900.c + [-] Fixed load/store unsigned addr to signed one over VUops.h + (linuzappz) + + * 28/09/03:[-] Fixed dmaIrq's for Source Chain mode + (linuzappz) + + * 26/09/03:[-] Fix the speed optimization problem that was in softCall function in Bios.c, + added a #pragma to disable optimization just to that function and everything + is working again as it should (linuz, please check if this pragma will interfere + with linux) + [*] The win32 project is back like before, the new Recompiler project was removed and + everything is working. + (GoldFinger) + + * 26/09/03:[+] Added two keys (F11, F12) for Opening/Closing the CDVD tray, + only for linux so far. + (linuzappz) + + * 25/09/03:[*] Sio2 fixes. Now the mcs are 'seen' as PS2 cards but unformated(able:P) + (Florin) + + * 25/09/03:[*] Modified the project structure under win32, I separated the recompiler from + the main project into a static lib, so now I can work with two projects instead + of one and enable optimizations. Now register caching works much better as I + enable speed optimizations in the Recompiler project but had to disable it in + the main project, the real problem is the global optimizations, this way I am + proving that the problem is not on my code... :) + [-] Fix lots of reg caching bugs and commented some of the reg caching instructions + that are buggy. Lots of demos work now, P51, colors, colors15 and maybe some others. + (GoldFinger) + + * 23/09/03:[-] Changed the MessageBox in recFunctions.c to SysMessage + [+] FIFO for VIF0/1 now works :) + (linuzappz) + + * 23/09/03:[*] Splitted the bios files so the code is the .c files and not on the .h files + [-] Fixed several bugs in reg caching and improved the routines + [!] Visual Studio .NET (dont know the others) speed optimizations are + messing with the code so it is recommended to build release mode + without Speed optimizations + (GoldFinger) + + * 23/09/03:[-] Commented the Syms in BiosInit.h, since they are only + for scph10000 + [-] Fixed ret DMA op + [+] Added iVUmicro, for recompiler + (linuzappz) + + * 22/09/03:[*] Added ExecuteVU0/VU1Block in R5900cpu, R5900.c + [+] Destination Chain for SPR0 dma and added Vif masking + [!] Gold, please merge the beta changes i sent you for + the iVUmicro.c/h + (linuzappz) + + * 20/09/03:[*] Now pad2 works in lle mode [tested with bios browser] + [+] New SCMDs and MC commands + [-] Fixes in sio, sio2, cdvd, etc. + [!] Now mcs appear as not inserted, but they are wip:P + SecrCardAuth() works fine;) + (Florin) + + * 19/09/03:[-] Small bugfix in Hw.h, u32 qwc -> u16 qwc; u16 pad; + [+] Small hack in Memory.c for ba000006 + (linuzappz) + + * 17/09/03:[-] Corrected a unpack bug i forgot ;) + [+] Implemented mskpath3 / m3r flags + [-] Fixed rom1.bin lookup for linux + (linuzappz) + + * 16/09/03:[-] Linuz fixed the macro bug hanging Visual Studio + (Gold-linuz) + + * 16/09/03:[-] More bugfixes/additions to Vif/VUs + (linuzappz) + + * 15/09/03:[-] Fixes lots of bugs in Reg Caching, now other demos work. + (GoldFinger) + + * 13/09/03:[-] Some fixes to the subq in cdvd.c (Florin) + + * 13/09/03:[-] Fixed the reg caching bug in tut1. + [*] Changed the DEFINE for reg caching for the config expert put on the CPU + screen, now we have both way to test. Thanks Expert. + (GoldFinger) + + * 13/09/03:[+] Added an option for enable regcaching or not.Now goldfinger should make + support for that!! (shadow) + + * 12/09/03:[-] Fixed the normal rec bug + [+] Added lots of new instructions for reg caching now all tutorials work + (demo 1 is strange), 3stars work also. + (GoldFinger) + + * 12/09/03:[-] Small bugfixes to Vif/VUs + (linuzappz) + + * 10/09/03:[*] More work on ipu (Florin) + + * 10/09/03:[-] New recompiler code wasn't compiling over linux, now it's ok + [-] Fixed VU memory64 writes masks + [+] Added Stats.c/h, it will create a stats.txt with some stats info, + if you define a NOSTATS in Common.h that will not be used + (linuzappz) + + * 09/09/03:[*] Improved the filter of ELF loading in GUI + [*] Register caching started to work, tutorial demo2a is working, others are coming. + [*] Commied ix86.c again with previous fix as linuz removed it. + (GoldFinger) + + * 09/09/03:[-] Fixed __int64 to u64 in Misc.c + [-] Fixed small bug in Vif.h + [-] Fixed bug in GS.c, bios is ok now + [+] Implemented INTC_STAT/MASK and DMAC_STAT for 64bits + [!] I commited the last ix86.c/h, afaik you only + reformatted it gold, please don't reformat my + code + (linuzappz) + + * 09/09/03:[-] Disabled host support for bios as it is buggy. + [*] Added/fixed SCMDs (2,3,1A) in cdvd.c (Florin) + + * 08/09/03:[+] Vif0/1 regs are now mapped to hardware + (linuzappz) + + * 08/09/03:[-] fixed bug in cpu ops debugger. Now all opcodes should appear .(For you goldfinger!) + (shadow) + + * 07/09/03:[+] Completed phase 1/2 of adding host support for bios. (Florin) + + * 06/09/03:[-] Fixed bug in rec when using ezmpeg + * 06/09/03:[*] Re-structuring the whole recompiler to make it easier for + debug and for the sake of understanding + (GoldFinger) + + * 06/09/03:[*] Many things fixed/changed in ipu files (Florin) + + * 05/09/03:[+] Hot keys for savestates in win32 + F1 -> savestate + F2 -> change the slot + F3 -> loadstate + [+] checkbox for enable the patches in cpu dialog + (shadow) + + * 05/09/03:[+] Some more VUmicro debugging + (linuzappz) + + * 05/09/03:[+] Added VDEC & BDEC; now m2v files work but ipu files do not + (Florin) + + * 05/09/03:[-] bug fixed in ifpu.h (shadow) + + * 04/09/03:[+] Added Init of Plugins before Loading of + savestates. + [-] LoadOthers in WinMain.c had a plugin init + missing fixed that. + [!] Fixed GSsoft aswell. And increased vRam size from 4*1024*1024 + to 2*4*1024*1024 as OpenGL doesn't handle wrapping around in + memory. + (asadr) + + * 04/09/03:[+] HSync stuff, and better CSR/IMR handling + [+] Few more FPU insts in ix86.c/h + [!] Please tell me if something is now screwed :) + (linuzappz) + + * 04/09/03:[-] ipu fixes to dmas and vdec (Florin) + + * 02/09/03:[-] fixed the patch system + (goldfinger) + + * 02/09/03:[*] working savestates in win32 :) + (shadow) + + * 01/09/03:[*] Working savestates for linux :) + (linuzappz) + + * 02/09/03:[-] Bug fixes in IPU.c (still hacky when returning BP) + Now ezmpeg gets to VDEC;) (Florin) + + * 01/09/03:[-] Fixed old bug in Sio.c/CdRom.c + (linuzappz) + + * 30/08/03:[+] sceCdReadSubQ <- that is a bad name; it look more like + a gettoc entry (SCMD2) (Florin) + + * 29/08/03:[+] Started the register caching implementation, not ready to test yet + some new x86 opcodes to x86.c and .h iR5900.c is completely changed + a new define for iR5900.c is used to enable reg caching. + (GoldFinger) + + * 29/08/03:[-] Removed 3DNOW code is the FPU since 3DNOW is 64bits, + and FPU is 32bits + [+] Workaround in ElfHeader.c for pukklink, so it will + load ok with Run Cd + [+] Savestates :D + [-] Maybe fixed patches, blah :P + (linuzappz) + + * 27/08/03:[+] CdGetToc + CdReadSubQ + [*] Changed PS2Edefs specs 0.4.3 / CDVD v3 + [*] Changed back the CDVDgetTD function to have a 2nd param: cdvdTD + (Florin) + + * 26/08/03:[-] Fixed patching bug in BiosInit.h that was used only for scph10000 + (Florin) + + * 26/08/03:[*] SPR address in DMAs are now masked with 0x0fffffff + (linuzappz) + + * 25/08/03:[-] Fixed patch stuff + (shadow-linuzappz) + + * 25/08/03:[-] Fixed IDEC bitstream decoding. Now, all *.ipu files + should work fine (Florin) + + * 25/08/03:[-] Fixed VIF Transfers to include MARK reg in VIF0 aswell. + (asadr) + + * 22/08/03:[*] Changed the SSE opcodes to Macro mode (thanks Linuz) and linuz added some more + (GoldFinger) + + * 22/08/03:[-] Changed DEV9 stuff to use DEV9 plugins + (linuzappz) + + * 21/08/03:[+] Added SSE instructions ADDPSRtoR, ADDPSMtoR, SUBPSRtoR, SUBPSMtoR, MULPSRtoR, + MULPSMtoR, MINPSRtoR, MINPSMtoR, MAXPSRtoR, MAXPSMtoR, SQRTPSRtoR, SQRTPSMtoR, + RSQRTPSRtoR, RSQRTPSMtoR, RCPPSRtoR, RCPPSMtoR, CVTPS2PIRtoR, CVTPS2PIMtoR, + CVTPIPS2RtoR, CVTPIPS2MtoR, CMPEQPSRtoR, CMPEQPSMtoR, CMPLTPSRtoR, + CMPLTPSMtoR, CMPLEPSRtoR, CMPLEPSMtoR to ix86.c ( need to compile and check ) :P + (GoldFinger) + + * 21/08/03:[+] Added Patch.c + (shadow-linuzappz) + + * 19/08/03:[+] Fixed bug in PsxHw.h, thanks to psycho_tr + (linuzappz) + + * 15/08/03:[+] More to SMAP + (linuzappz) + + * 14/08/03:[-] Fixed Debugger/RDebugger + [!] There is still one bug left i saw in the RDebugger, + that's the threads are not ended ok, but i'll leave + that to you florin :) + (linuzappz) + + * 12/08/03:[*] Changed the time in CDVD.c and some WIN32 defines to __WIN32__ + (Florin) + + * 08/08/03:[+] Started SMAP/DEV9 stuff + (linuzappz) + + * 06/08/03:[-] Fixed MFIFO for GS dma + (linuzappz) + + v0.41: + * 05/08/03:[-] Uncommented some sif WIP stuff :) + [*] Addeded 0x00100008 PC for cpuExecuteBios as well + [-] Fixed silly bug in CDVD.c for DvdReads + (linuzappz) + + v0.4: + * 29/07/03:[-] Fixed bug in Sif code ;) + (linuzappz) + + * 26/07/03:[-] Fixed the dma memory checking for the scratchpad, + and implemented it over the remaining dmas + (linuzappz) + + * 25/07/03:[-] GSdma now ends when a transfer is outside the memory + [-] Bugfix to Sif1 dma + [-] Some changes in the ICFG write code, and + when D5_CHCR == 0, psxSu32(0x30) = 0x40000; + (linuzappz) + + * 22/07/03:[-] Counters fixes/improvements + [*] Improvements on CdRead/DvdRead + [*] Better Sif1/0 handling + (linuzappz) + + * 22/07/03:[+] New PS2Edefs 0.4.0 :) + (linuzappz) + + * 20/07/03:[-] DvdRead was really 2064 :P + (linuzappz) + + * 19/07/03:[-] Fixed BIG stupid bug in FiFo.c that i left there:P + [!] I'm ashamed:( + [*] Fixed getBits function with back buffer;) + [!] I'm proud of that B-) (Florin) + + * 18/07/03:[-] Fixed includes for Mpeg.c/yuv2rgb.c + [-] Modified DvdRead, uses 2048 blocksize, experimental ;) + [-] CDVDgetTD had to return s32, not u32 + [*] Some reorganization for the rec + (linuzappz) + + * 18/07/03:[-] Fixed some memory allocation bug in IPU.c + [i think there are more, searching...:P] (Florin) + + * 17/07/03:[-] Fixed another Sio bug ;) + [-] Fixed MULT1/MULTU1, s64 was really s32 + [-] Commented out the interrupt delay thingy ;), was causing + troubles with Kengo 2 + [+] Implemented DvdRead + (linuzappz) + + * 17/07/03:[-] Fixed bug in FiFo.c that caused flickering between movies + [*] Fixed color conversion (Florin) + + * 16/07/03:[-] Now we can boot games though bios :) + [-] Fixed 32bits shifts in Interpreter.c + (linuzappz) + + * 16/07/03:[*] Fixed (somehow:P) IDEC so that .ipu files works a bit (Florin) + + * 15/07/03:[*] Changed cdvdLoc stuff to lsn + [-] PsxDma10 now will just return if bcr < 4 + [-] Corrections to IPU1/0 dma transfers, untested but should be fine ;) + [!] Breaks compat with current cdvd plugs + (linuzappz) + + * 15/07/03:[+] CSC + PACK ipu commands Fixes to bitstream decoding (Florin) + + * 14/07/03:[-] Really implemented MFIFO now ;P + [!] mfifo.elf works just fine now, also tekkentag reaches a bit further + (linuzappz) + + * 14/07/03:[+] Some more work on IntraDECoding for IPU (florin) + + * 14/07/03:[-] Some cleaning over Sif.c + [+] MFIFO implemented in both GS/VIF + [-] Fixes to xpadman + (linuzappz) + + * 13/07/03:[*] VUmicro code now can run in "async mode" + [-] Fixed TTE in SPR1 dma + (linuzappz) + + * 10/07/03:[-] Fixed bug in R5900.c when HLE mode was on + [-] fileio ain't crashing anymore when the file is not there + [-] Fixed interrupts on VifDma.h + (linuzappz) + + * 09/07/03:[-] Fixed bug in GS dma transfers when TTE is enabled. + Was passing wrong size of qword now it is GSgifTransfer3(ptag+2, 4) + + * 08/07/03:[*] In Win32 cdvdReadRTC gets correct time. (Florin) + + * 08/07/03:[-] Fixed stupid bug in SPR1 dma, thanks florin :) + (linuzappz) + + * 07/07/03:[-] Fixed bug in Vif UNPACK cmd, tops was *16 ;) + [*] GSgifTransfer/2 => GSgifTransfer1/2/3 (PATH1/2/3) + [*] Updated GS.c with VifDma.h asadr changes, commented the TTE + transfer by now + [*] Updated as well the SPR1 dma + [!] Note that now all vu1 demos work :D + (linuzappz) + + * 06/07/03:[+] Implemented cdvdReadKey + (linuzappz) + + * 05/07/03:[+] VCALLMS/VCALLMSR now are implemented + [*] SPU dma4 now has a delay base of 0x10000 + [-] VifDma.h is now mostly as before asadr rewrote it + last time, since that way had problems with the TTE chcr + flag, now go check the bios Browser ;) + (linuzappz) + + * 04/07/03:[-] IOP won't die now after cpuRegs.cycle overflows :), R5900.c + (linuzappz) + + * 03/07/03:[-] Fixed WriteRTC and bug in Sio.c + (linuzappz) + + * 03/07/03:[+] Some IPU commands (BCLR,FDEC,SETIQ,SETVQ,SETTH) & IPU fifo + (Florin) + + * 02/07/03:[-] Cleaned a bit VifDma.h + [*] Modified the DmaExec macros, now the Dmas take care + to interrupt and to clear the STR bit + (linuzappz) + + * 30/06/03:[*] Usb hack ;), PsxHw.c + (linuzappz) + + * 29/06/03:[*] Modified Iop DMAs for async processing, only for spu/spu2 by now + [-] Vif dma refe/end now sets the tadr to 0, tek4 loops else, but + now is crashing after ;) + [!] sven shows one screen now, and others want to ;) + (linuzappz) + + * 29/06/03:[-] Removed the experimental code i added yesterday from CDVD.c/h + [*] Improved EE/IOP Rcnts + (linuzappz) + + * 28/06/03:[*] More on iop rcnts rewrite + [+] Experimental code in CdRead, now if the lsn sector is + the same than the last one readed it will add nSectors + to it, ie. it readed 2 sectors from 0:2:16; and then + it issues another cdread with the same lsn, it will read + from 0:2:18. + (linuzappz) + + * 27/06/03:[*] Started iop rcnts rewrite, untested and more to come ;) (linuzappz) + + * 27/06/03:[-] Some fixes on iop rcnts + [+] Implemented the SPU2async func + (linuzappz) + + * 26/06/03:[-] Really fixed HLE mode ;). (linuzappz) + + * 26/06/03:[-] Small CDVD.c corrections. (linuzappz) + + * 24/06/03:[*] Fixed elf loader at least not to crash at bad elfs. (Florin) + + * 23/06/03:[*] Added "rom1.bin" as a valid file for rom1 filesystem. (Florin) + + * 23/06/03:[-] Small fix to CDVD.c, maybe fixed a time out problem + with some cdvdman versions. + (linuzappz) + + * 20/06/03:[+] Some mcds work, PsxSio2.c, Sio.c + (linuzappz) + + * 17/06/03:[+] SPU dmas now call the correct funcs, PsxDma.c + (linuzappz) + + * 17/06/03:[-] Fixed Sio2, PADs are working :D, Sio.c, PsxSio2.c + [-] Fixed language in CDVD.c, now's english again :) + (linuzappz) + + * 16/06/03:[-] Better error handling over CDVD.c + [+] ROM1 stuff, Memory.c/h, PsxMem.c, iR3000A.c, iR5900.c + [!] PCSX2 now detects the rom1 in this way: ie. + you use scph10000.bin, then you must have + in the same dir scph10000.bin.rom1 or scph10000.rom1 + (linuzappz) + + * 16/06/03:[-] Rewrote the VIFtransfer and VIFdma again. Better speed and + compatibility this time (asadr). + + * 16/06/03:[*] Reoverwritten CDVD.c/h with my CDVD.c/h, + this is simpler, more direct and faster, + CdRom.c, PsxHw.c, R3000A.c, PsxCounters.c, + Memory.c + [-] Kinda workaround i think in the ICFG reg + (1450), PsxHw.c + [-] Removed VSyncHack at least ;), WinMain.c, + Common.h, ini.c + [!] Games start showing something :D:D + (linuzappz) + + * 15/06/03:[+] More dummy cdvd scmd (Florin) + + * 14/06/03:[-] Fixed SIF0 transfers, PsxDma.c, PsxHw.c/h. + [*] Cleaned up SIF1, R3000A.c, Sif.c + [+] Added a Run CD menuitem, WinMain.c, resource.h + [!] Bios shows something :D:D + (linuzappz) + + * 12/06/03:[-] Fixed bug in release version (unsafe compiler optimizations:P) + (Florin) + + * 11/06/03:[+] More functions on lle cdrom (cdread) (Florin) + + * 10/06/03:[+] Rudely overwritten linuzappz work in CDVD.c/.h + [!] Sorry man, i think i did the best...i created a framework + with names and so on. Also we have to talk about;) (Florin) + + * 10/06/03:[+] Started CDVD.c/h, moved old CDVD.h to CDVDlib.h, + PsxMem.c, PsxCommon.h (linuzappz) + + * 10/06/03:[*] Added new SPU2 dma functions plugin.c + [*] New PS2 plugins specifications 0.3.2 (shadow) + + * 09/06/03:[+] Add SPU2read/SPU2write to PsxMem.c + [-] Few fixes to PsxCounters.c + [+] Added PsxDma7, PsxHw.c, PsxDma.c (linuzappz) + + * 09/06/03:[-] Sif0 chaining fix (Florin) + + * 08/06/03:[+] Started with SIO2... (Florin) + + * 07/06/03:[-] Fixes to SIF0/SIF1 :D + [!] Now OSDSYS loads ok, and so does several modules in iop, + bios now gets stuck in a Deci2Call (reqsend) + (linuzappz) + + * 07/06/03:[-] Fixes0, Fixes1 (Florin;) + + * 06/06/03:[*] Fixed and improved the VIF Dma transfers and rewrote the VIF_Transfer. It's far + more compatible and fast ( all vu1 demos work:D ). (asadr) + + * 06/06/03:[*] Fixed sif1 (...waiting for a better solution;) (Florin) + + * 05/06/03:[-] Sif1 flags fixes (still buggy?) (Florin) + + * 04/06/03:[*] Some adjustments to PsxInterpreter.c (Florin) + + * 03/06/03:[-] Set the PSXCLK to 36.864 Mhz, by now, later PSXCLK should be + a variable, Common.h + [*] Improved iop hw maps, added DMA9/10, PsxDma.c/h, R3000A.c, PsxMem.c + [+] Added RCNT3/4/5 in PsxCounters.c/h, PsxBios.c, PsxHw.c/h + [+] Added a bit more of loggin in PsxInterpreter.c + [-] 0xba000006 now returns 1, for some bioses, Memory.c + [*] Improved dmaSIF1, SIF.c, and cleaned dmaSPR1, SPR.c + [!] Finally my name is on the v0.4 :P + (linuzappz) + + * 03/06/03:[-] Fixed GetPS2ElfName in Misc.c (Florin) + + * 22/05/03:[+] new flags code based in nsx2 flag code. vuflags.c vuflags.h + [*] vuops.h rewrote almost all the vu opcodes with new flags code Upper Instructions + should be okay but might still are some issues with the Lower instructions. + [-] added proper reset in vu1micro.c + [*] added the new vcnet files for compile properly with vuflags + (shadow) + + * 21/05/03:[-] Fully fixed of recSQ in iR5900.c. + [-] Fixed EMMS_TRACING on none 3DNOW machines, EMMS_TRACING now turned on again. + [*] Added CPU autodetection to iR5900.c + [!] #define CPU_3DNOW is not used now. + (Alexey Silinov) + + * 20/05/03:[-] Dummy fix of recSQ in iR5900.c. Recompiler back to work again. + (Alexey Silinov) + + * 10/05/03:[*] Improved fpu.c, just code optimizing in cvt_s, cvt_w, all branches opcodes and + some code organizing. + (GoldFinger) + + * 02/05/03:[+] Added some ioprps to Misc.c (Florin) + + * 02/05/03:[+] Some more work on Padman module 800100Xpadman.c , 800100Xpadman.h (shadow) + + * 30/04/03:[+] Added 2 more syscalls in BiosSysc.h (Florin) + + * 29/04/03:[+] More threads functions. (see threads.txt) + [!] To see threads switching, comment the 3 instructions + at the top of _ThreadHandler function (Bios.c) + (Florin) + + v0.3: + * 01/05/03:[-] Fixed dvd iso issue (roundup of numsectors ...+2047/2048) + in CDVDiso.c (Florin) + + * 30/04/03:[-] Fixed bug in CFC1, Fpu.c + [-] Fixed branches isns on VUops.h, US was instead of SS + [-] Added newline at oef for MMI.c, *mtapman.c + [-] Included in *loadfile.c + [*] Few changes over languages, Misc.c/h, WinMain.c + (linuzappz) + + * 29/04/03:[-] Added a workaround for the interrupt latency in the rec, + R5900.c + (linuzappz) + + * 28/04/03:[-] Fixed a bug in BiosInit.h, instead of 16 dmas there was 15 + [-] Counters 0,1,2 had interruption disabled, Counters.c + (linuzappz) + + * 27/04/03 [-] WinMain.c now only calls GetPS2Elf if on HLE mode + [-] parseCommandLine had a bug when not using HLE, ElfHeader.c + [*] Implemented memRead/Write128, Memory.c/h, iR5900.c + [*] Implemented a better way to count opcodes in iR5900.c + [*] Rewrote AddIntc/DmacHandler, RemoveIntc/DmacHandler, Bios* + (linuzappz) + + * 24/04/03:[*] More threads functions. (see threads.txt) (Florin) + + + * 23/04/03 [-] Undo the "VU0/1 control/integer regs are now the same" update, + VU*, DebugReg.c, (goldfinger-linuzappz) + [+] Implemented latency interrupt thingy ;), R5900.c/h + (linuzappz) + + * 21/04/03 [-] DMAC interrupt wasn't setting the cause in a0, Bios.c + [+] DMACTable is now being used with DefaultDmacHandler, Bios.c/h, + BiosInit.h, HLE.c + [+] Added dummy handles for mtapman901/3, Rpc_services.h, *mtapman* + [*] VIF0 code is now shared with VIF1 code, Vif.c, VifDma.h + (linuzappz) + + * 23/04/03:[*] Fixed RFU061_InitHeap, EndOfHeap, CreateThread, InitThreads + (Florin) + + * 21/04/03:[+] Started threads update (Bios.c/BiosInit.h/BiosSync.h/ + deci2_dbgp.c/ElfHeader.c/.h) (Florin) + [-] Fixed fifos a bit:) (FiFo.c/Hw.h) (Florin) + [*] Fixed VIF1 regs display in Hw.c. I know that those were handeled + but now is more clear (Asad-Florin) + + * 20/04/03:[-] Fixed a bug in WinMain.c. In case of the debuggers with HLE bios, + cpuExecuteBios() was not called, so the tlbs and all stuff + were not inited properly. (Florin) + + * 20/04/03:[-] Fixed a bug in VUmicro.h + [+] VIF1dma now handles 'from Memory' transfers, Vif.c + [-] F11 now un/sets Log, F12 un/sets symbol logging, WinMain.c + (linuzappz) + + * 19/04/03:[-] Fixed a bug in Interpreter.c + [-] VU0/1 control/integer regs are now the same, VU*, DebugReg.c + [*] Cleaned a bit GS.c + (linuzappz) + + * 17/04/03:[-] gsRead32 wasn't calling GSread32, lol :), GS.c + [+] Implemented more syscalls, as dummy for now, Bios.c/h, BiosSysc.h, + HLE.c + [*] Removed the CSR revision/intelace bits over GS.c + [+] Added GSirqCallback to PS2Edefs.h, GS.c, Plugins.c + [+] VIF1 cmd now handles the i bit, still not 100% correct, Vif.c + [-] Fixed several VIF1 bugs, Vif.c + (linuzappz) + + * 16/04/03:[*] biosInit is now called at hle_bootstrap, Bios.c, HLE.c, WinMain.c + [+] Added _TlbInit at biosInit, Bios.c + [*] Deci2Call is now better coded, Bios.c, BiosSysc.h + [-] Fixed some bugs over AddIntcHandler/AddDmacHandler, BiosSysc.h + [+] bios_SetSYSCALL is now implemented, BiosSysc.h + (linuzappz) + + * 17/04/03:[+] Breakpoint support for debugging bios. (Florin) + + * 16/04/03:[-] Readded an update that linuzappz missed in his src, + that was then used by many pcsx2 team members. [it is about my 16/03/2003's] + [+] sceCdReadIOPm in 80000595.c + (Florin) + + * 14/04/03:[*] Memory access bug in deci2 that made pcsx2 to crash. hi linuzappz + [+] MC functions fixes/dummies over 80000400mcserv.c + (Florin) + + * 12/04/03:[*] CP0Count now adds 2 every opcode, instead of 4 + (linuzappz) + + * 12/04/03:[-] Bios VSyncSetFlag is now fixed ok, Bios.c + [*] Started to implement new Bios code, Bios.c/h, BiosInit.h + BiosSysc.h, EEregs.h, HLE.c, R5900.c/h + [!] Please tell me if this update creates some incompatibility, + or something else works now, since the INTC/Exceptions code is + much better now :). + (linuzappz) + + * 08/04/03:[-] DMAC_STAT CIS? bits are now set after a DmaExec, Hw.c + [-] Fixed bug when a plugin returned -1, WinMain.c + [*] Cleaned a bit GSdma, GS.c + [-] Fixed bug in INTC interrupts, Bios.c + (linuzappz) + + * 07/04/03:[+] Added cpu opcodes debugger. Use the CPU ops button in the debugger + and it will create a cpuops.txt with the opcodes that used. + Debugger.c pcsx2.rc, cpuopdebug.c cpuopdebug.h . Now works only in + interpreter. (shadow) + + * 04/04/03:[+] Added LabelGreets/LabelAuthors to Misc.c/h, AboutDlg.c + [*] Languages code over pcsx2 is a bit better, WinMain.c + [+] Added Log to STDOUT over Logging dialog, pcsx2.rc, + Misc.c, resource.h + [+] Now we're emulating the VSync Start and the VSync End, Counters.c + (linuzappz) + + * 26/03/03:[*] Optimized PLZCW in mmi.c (GoldFinger) + [-] fixed MADD1 and MADDU1 in mmi.c (GoldFinger) + [-] PSLLH, PSRLH and PSRAH (sa needed to be the first 4 bits only), + mmi.c (GoldFinger) + [-] PADDSW, the manual seems to be wrong (well it is) so I tryed + to fix it, mmi.c (GoldFinger) + [-] PADDSB, PSUBSB, the comparision was wrong, mmi.c (GoldFinger) + [-] PADDSW, PSUBSW, PADDSH, PSUBSH, PADDSB, PSUBSB, PADDUW, PSUBUW, PADDUH, + PSUBUH, PADDUB, PSUBUB, the sum and sub need a conversion to the higher + value(s16,s32 and s64), mmi.c (GoldFinger) + [-] PMINH, the comparision needs to be signed, mmi.c (GoldFinger) + [-] PHMSBH, was wrong, fixed, mmi.c (GoldFinger) + [-] PEXEH, PREVH, was using _Rs_ when only _Rt_ should be, mmi.c (GoldFinger) + + * 26/03/03:[*] fixed fpu bugs. Hi linuzappz :) . Tmip is correct in interpreter mode finally + fpu.c (shadow) + + * 24/03/03:[+] Fixed Trap instructions, hi shadow :), also cleaned + up a bit the Interpreter.c (linuzappz) + + * 22/03/03:[+] Fixed the 'Load ELF File' issue, added the Memory Dump menu, + WinMain.c (Florin-linuzappz) + [!] I forgot the changelog entry in the last update, + please read it (linuzappz) + [!] I've updated again the pcsx2.po, florin sent one without the + linux port messages since i've never updated u the linux port ;) + + * 20/03/03:[+] Added GSsetWindowInfo, WinMain.c, PS2Edefs.h, Plugins.c + [+] Added MiltuLingual support, using gettext, WinMain.c, Plugins.c, + AboutDlg.c, ConfigDlg.c, pcsx2.rc, Memory.c, iR5900.c, iR3000A.c, + pcsx2.dsp, Sio.c, R5900.c, PsxMem.c, Hw.c, Common.h, ini.c, + resource.h, Win32.h + [-] Fixed IPU.c when IPU_LOG is not defined + [-] Fixed padman/loadfile.c when RPC_LOG is not defined + [*] Removed dummy memory area, Memory.c/h, PsxMem.c/h + (linuzappz) + + * 17/03/03:[*] add some more stuff to DisR5900asm.c . win debugger is better now (shadow) + [-] fix a bug in rec table (visubiu not exist) in macromode .. recCop2.c (shadow) + [!] recheck vu micromode tables. Hmm they seem correct (shadow) + + * 16/03/03:[+] Added "next" (aka "step over") support for deci2 debugging + [+] Added TTYP support (log redirection) (buggy;have to test more) + (Florin) + + * 15/03/03:[*] move loadfile to rpc using florins protocol hi florin;p (shadow) + + * 15/03/03:[*] Fixes to breakpoints in deci2 stuff (Florin) + + * 13/03/03:[+] More deci2 dbgp stuff (BREAK/CONTINUE/RUN) + [!] It is not fully tested. This is EXPERIMENTAL code. + [!] It may contain many bugs and there are also "known issues". + [*] changed names of shadow's padman files and made the according + changes to rpc_services.h & bios.c (Florin) + + * 12/03/03:[*] rewrote padman+xpadman according to florins protocol on RPC folder + [*] removed code from bios.c according to pad handling.. + [+] Add fix that make analog mode to work partially ;) (try turnip) (shadow) + + * 10/03/03:[+] Added more mem mappings to PsxMem.c & Memory.c in order + not to crash the emu when read from a not-covered area (Florin) + + * 10/03/03:[-] fix small bug in winmain that didn't let console to close winmain.c (shadow) + + * 04/03/03:[+] Added remaining UNPAKs and cleaned a bit, Vif.c/h (linuzappz) + + * 03/03/03:[*] replace console writes of IPU with IPU_LOG Ipu.c (Shadow) + + * 01/03/03:[-] Fixed partially FIFO bug; (unlogged change:P) + [!] I haven't fixed it all because is very messed up. + [+] Added a small fix to PsxMem.c in order to allow sifman to stay resident. + (Florin) + + * 28/02/03:[+] Added support for remote debugging with tcp/ip deci2 protocol. + [!] Not finished nor fully tested + [!] There's an issue on Win98 with winsock2 closing [have 2 check that] + [!] New src dir (rdebug\*.*), Win32\RDebugger.c/.h; + [!] also added ws2_32.lib to link libraries + (Florin) + + * 25/02/03:[+] Added 8bit DMAs to Hw.c + [+] More UNPACK cases to Vif.c (linuzappz) + + * 23/02/03:[+] Added BC0s in COP0.c + [!] the BC0s are still fake, but they should be ok ;) (linuzappz) + + * 22/02/03:[*] Now if the Recompiler fails to initialize it'll switch to interpreter (linuzappz) + + v0.2: + * 18/02/03:[-] Small fix in winmain.c in SysInit() causing a crash (shadow) + + * 12/02/03:[+] Added new DMA transfer codes to VIF.c, GS.c + [+] Added the new clipping code to the VU + [*] Fixed most of the VU ops. Better compatibility + [!] The new dma transfer code is 4-5% faster than the last one. :) + + * 12/02/03:[*] Fixed iR5900.c to include iR5900.h, moved some stuff from + ix86.h to iR5900.h + [-] Fixed CPU_LOG flags over iR5900.c/recCOP2.c + [+] Added some SysPrintfs over iR5900.c after x86Init + (linuzappz) + + * 26/01/03:[+] Added some defines in Hw.h (linuzappz) + + * 26/01/03:[-] Fixed include in IPU.c, 'common.h' for 'Common.h', + SJdata.c, 'rpc/...' '...' (linuzappz) + + * 04/02/03:[+] ix86.c: Added CPUID for linux. + SSE is autodetected now (linuzappz) + + * 28/01/03:[+] ix86.c: CPUID added. It will work if u don't change CPU on the FLY. :) + [*] ir5900.c: recompiler changed for CPUID. + [*] recCOP2.c: recompiler changed for CPUID. + (Alexey Silinov) + + * 27/01/03:[+] ir5900.c: recompile of DSRAV,PMINW,PMAXW added. + [!] I'am not sure in this code.Need find demos that use it. + [+] ix86.c: PANDNRtoR,PANDMRtoR added. + (Alexey Silinov) + + * 25/01/03:[-] ir5900.c: Some fpu opcodes for non 3DNOW version fixed with EMMS_TRACE on. + After Linuzappz request:memory opcodes + [-] (LB,LBU,LH,LHU,LW,LWU,.....,SB,SH,SW,...) fixed for version with EMMS_TRACE on. + [-] recCOP2.c: Bugfixed for non 3DNOW version(added another recCOP2SPECIAL1t,recCOP2SPECIAL2t tables). + + [!] Now EMMS_TRACE will work much better. + (Alexey Silinov) + + * 24/01/03:[+] ir5900.c: DSRA,DSRA32 recompilation added. + [*] shifts by _Imm_=0,_Rs_=0 optimized. + [+] PMFHI,PMFLO,PAND,PXOR,PMTHI,PMTLO,POR,PAND now can recompiled to SSE instructions. + [-] JUMPS bugfixed by putting SET_FPUSTATE before it, + because cpuBranchTest use FPU. Pillgen now ok with EMMS_TRACE. + [!] #define CPU_SSE in ix86.h if you have Pentium3/4 or Duron7/AthlonXP. + (Alexey Silinov) + + * 24/01/03: Fixed iR5900.c to compile without 3DNOW (linuzappz) + + * 24/01/03: Moved the emms's in Hw.c, GS.c, Memory.c to iR5900.c (linuzappz) + + * 24/01/03: Rewrote ini.c, same code as Pcsx now :) (linuzappz) + + * 24/01/03: Removed the browse info option over pcsx2.dsp (linuzappz) + + * 24/01/03: Some fixes in Hw.c, missings #ifdef HW_LOG/#endif, + reordered the ipu address and the IPU1 dma was wrong. (linuzappz) + + * 21/01/03: remove the fpu flags reorganize fpu.c a bit. Send code for using it + as reference to all the pcsx2 members. + + * 21/01/03:recCOP2.c + 75% of COP2 ops recompiled used 3DNOW. + only sign MAC flags updated. + Zero,Sticky will be done later. + (Alexey Silinov) + * 19/01/03: + ir5900.c: + Fixed recompiling of RSQRT_S for3DNOW,recPCPYUD(tskin.elf now ok), + recC_LE for x87 FPU(untitled.elf last part now ok). + Optimizing recompile of recADDI,recADDIU,recDADDI,recDADDIU, + recANDI,recORI,recXORI,... (check _Rs_,_Rt_= =0,!=0). + Optimiing recMOVZ,recMOVN only one JMP CC,.. needed. + Added #define EMMS_TRACE to. + Added #define ARITHMETICIMM_RECOMPILE,ARITHMETIC_RECOMPILE,etc. + (Alexey Silinov) + * 18/01/03: ir5900.c:Many recompiler opcodes fixed. + IPU DMA logging update. + (Alexey Silinov) + + * 18/01/03: Fixed fileio_lseek function in 80000001fileio.c. (Florin) + + * 16/01/03: Rewrite fpu and added two version of it. One with flags and + one without. The no flags version is much faster. + fpu.c ,r5900.h,common.h,r5900.c,ini, resources , winmain.c (shadow) + + * 15/01/03: Added memory mapping of IPU_CMD,IPU_CTRL,IPU_TOP,IPU_BP. + Added parsing of IPU commands. + (Alexey Silinov) + * 14/01/03: recMAX_S,recMIN_S,recC_F,recC_EQ,recC_LE,recC_LT-added. + recABS_S,recNEG_S-now don't use FPU. + ix86.c - 3DNOW opcodes added. + #ifdef CPU_3DNOW then FPU recompiled using 3DNOW instruction set. + Now we are ready TODO FPU register cache on CPU_3DNOW. + gs.c add emms before GS read,write. + (Alexey Silinov) + + * 14/01/03: Fixed stupid bug in 80000001fileio.c (Florin) + + * 13/01/03: Fixed some issues in CDVDiso.c & 80000597cdvdfsv.c (Florin) + + * 11/01/03: Fixed fileio [important] functions up to ioprp255 (Florin) + + * 11/01/03 some more MMI opcodes in rec (alexey silinov) + + * 10/01/03 recPADDUB-changed,recPADDUH-added (Alexey Silinov) + + + * 09/01/03 + My copy&paste bugs in recPCPYUD,recPAND,recPXOR fixed. + Now EMMS() instruction writing only before FPU commands if FPU state is MMX.With it size of recompiled code is reduced. + !!Added macros SET_FPUSTATE,SET_MMXSTATE it's must before MMX or FPU instruction. + Fixed many ops.ExtSign32to64() don't used anymore. it's faster and smaller to do CDQ(). + recLUI,recPCPYLD optimized. + Added recompilation of PMAXH,PMINH,PCGTB,PCGTH,PCGTW,PCEQB,PCEQH,PCEQW,PEXTLW,PEXTUW. + ir5900.c,ix86.c, ix86.h + (Alexey Silinov) + + + * 07/01/03: Fixed MADD, MADDA, MSUB, MSUBA opcodes in FPU.c ( asadr ) + + * 07/01/03: added MTSAB,MTSAH in interpreter.c (asadr) + + * 07/01/03: Added Flags in FPU.c, fixed SQRT, DIV, RSQRT opcodes in FPU.c ( asadr ) + + * 07/01/03: add some opcodes in interpreter.c (shadow) + + * 07/01/03: small fix in mult1,multu1 in MMI.c (shadow) + + * 07/01/03: more addes in recompiler iR5900.c (Alexey Silinov) + + * 07/01/03: fixed MULT,MULTU,MULT1,MULTU1 in rec and added DIV1,DIVU1 iR5900.c + (Alexey Silinov) + + * 07/01/03: add several MMI opcodes to recompiler iR5900.c ix86.c ix86.h + (Alexey Silinov) + + * 07/01/03: Fixed libpad version issues; added scePadInit2 support in Bios.c (Florin) + + * 06/01/03: Added sceDvdRead function to 80000595cdvdfsv.c, CDVDiso.h/.c + Moved sifcall_cdvdfsvA from Bios.c to 80000592cdvdfsv.c (Florin) + + * 05/01/03: Fixed libmc version 80000400mcserv.c + Added support for cdrom device in LoadHeap function 80000003sysmem.c (Florin) + + * 05/01/03: Added D and I Flag checking in vuDiv and SQRT opcodes and some more fixes ( asadr ) + + * 05/01/03: Merge all the vu code fixes to the better possible one vuops.h (shadow) + + * 05/01/03: Several vu fixes vuops.h (Alexey Silinov) + + * 04/01/03: Added temporary fix to vuDIV, vuRSQRT, vuERSADD, vuERCPR, ERSQRT ( asadr ) + + * 04/01/03: Added vuERCPRL, vuESUM , vuEATANxz, vuESIN, vuEATAN, vuEEXP, vuRXOR ( asadr ) + + * 04/01/03: Fixed GetPS2ElfName Misc.c + Romanian version pcsx2ro.rc & spell fixes in pcsx2.rc (Florin) + + * 03/01/03: Added callback support in Bios.c + Added function name display support (if you know other places, plz add...) + (Florin) + + * 02/01/03: Fixed sceCdRead (cdvdfsv1.4 and more?) 80000595cdvdfsv.c (Florin) + sceCdSeek, sceCdPause, sceCdStop, sceCdStatus + + * 02/01/03: Added SLTI,SLTIU,SLT,SLTU iR5900.c ( Alexey Silinov) + + * 02/01/03: Added SETS8R ix86.c ix86.h ( Alexey Silinov) + + * 01/01/03: YAH HAPPY NEW YEAR :) + + * 30/12/02: Added Dump memory button in Debug dialog over Debugger.c (Florin) + + * 29/12/02: Start work on Savestates Common.h, Misc.c. Need to include zlib.lib in project (shadow) + + * 29/12/02: Fix small bug In ERET. COP0.c (shadow) + + * 29/12/02: Some more Vu opcodes in the vuops.h (shadow) + + * 29/12/02: Added BC2F,BC2T,BC2TL,BC2FL not sure if i check the right bit althought Vu0.c (shadow) + + * 29/12/02: Added HLE opcode over DisR5900.c (linuzappz) + + * 29/12/02: Fixed some bugs on rec mode, Memory.c, PsxMem.c, + ix86.c/h, iR3000A.c, iR5900.c (linuzappz) + + * 29/12/02: Fixed JALR in Interpreter.c (linuzappz) + + * 28/12/02: Fixed stupid old bug in iR5900.c (linuzappz) + + * 26/12/02: Added compiler detection code (Win32/WinMain.c) (Florin) + + * 20/12/02: Refixed new Threads code, a bit hacky still ;), Bios.c/h, HLE.c (linuzappz) + + * 20/12/02: Refixed Counters.c, GS.c (linuzappz) + + * 20/12/02: Changed some cop0 names over DisR5900.c (linuzappz) + + * 20/12/02: Fixed EXL bit on cpuException, R5900.c (linuzappz) + + * 20/12/02: Fixed ERET, COP0.c, Interpreter.c, R5900.h (linuzappz) + + * 19/12/02: fix bugs in fileio system 80000001fileio.c (florin) + + * 19/12/02: rewrite MMI mmi.c (linuzappz) + + v0.1: + * 17/12/02: Small cleaning for release (linuzappz) + + * 17/12/02: Fixed a comment in CDVD.h (linuzappz) + + v0.046: + * 17/12/02: FIXED THAT BASTARD BUG with interpreter + R5900.c (shadow) + + * 16/12/02: Fixed CDVDFS_read function (CDVDisodrv.c). (Florin) + + * 07/12/02: Added support for SjDATA filesystem (SJdata.c/.h). + Small fixes in 80000003sysmem code. + Moved OpenPlugins call from debugger.c to WinMain.c + Added support for 0B001337cdvd rpc driver. (Florin) + + * 06/12/02: Fixed RPCVER for games that load ioprp.img. + Moved related code Bios.c to Misc.c. (Florin) + + * 05/12/02: Placed a guard in CDVDFS_init/CDVDisodrv.c + Added support for reading from cdvd in Elfheader.c/.h + Implemented RunCD option WinMain.c, GtkGui.c, Misc.c/.h (Florin) + + * 01/12/02: Made fileio_open more compatible with games (up to 2.0F/ioprp255) (Florin) + + * 30/11/02: Add test opcodes TGE,TGEU,TLT,TLTU,TEQ,TNE Intepreter.c (shadow) + + * 30/11/02: Add exceptions defines in R5900.h (shadow) + + * 01/12/02: Removed old VU0 code over VU0.c (linuzappz) + + * 31/11/02: Implemented CheckCdrom/LoadCdrom, still unfinished, Misc.c (linuzappz) + + v0.045: + * 31/11/02: Changed memRead32 for PSMu32 over Interpreter.c (linuzappz) + + * 31/11/02: Fixed CdRead, CDVDiso.c (linuzappz) + +// * 30/11/02: Added irqs for rcnt2/3, started thread HLE code rewrite, +// Bios.c, Counters.c (linuzappz) + + * 28/11/02: Fixed win32 fileio path, and some more small issues (linuzappz) + + * 27/11/02: Added BD0000X0 connection to 1000F0X0 and BC000000 ee memmap, + implemented direct rec clears, and added some more counters stuff, PsxMem.c/h, + Memory.c/h, iR3000A.c, iR5900.c, Counters.c/h, Hw.c, PsxHw.c (linuzappz) + + v0.044: + * 26/11/02: Added RPC handler for 80000595cdvdfsv + Fixes in iso handling system (read function can read more than 16KB) + Fixed issue with deci2call no.3 (junk re-printing) (Florin) + * 20/11/02: Automatic setting of RPCVER + (problems: 1. SDK samples do not load an ioprp; default is "2000";) + 2. starwars game load a ioprp.img; so RPCVER="0000") + Fixed bug in CDVDiso.c/CdRead(); check for null pointer + Fixed issue with the Joliet filesystem (Florin) + * 09/11/02: Added iso parsing & filesystem driver from libcdvd library by Hiryu & Sjeep + Added credits (Hiryu&Sjeep) to Aboutbox & Readme.txt + Changed the order of opening of plugins in Plugins.c/OpenPlugins() + Added (or moved code from bios.c) to handle RPC user & standard code + -works (or should work; needs intensive testing): + 014D704Enaplink, 80000001fileio, + 80000003sysmem, 80000592cdvdfsv, + 80000597cdvdfsv + -dummy (to be implemented; only params display): + 0B0110C5sjpcm, 0badca11amigamod(shadow), + 80000400mcserv,80000596cdvdfsv, + 80000601osdsnd + Added RPC_LOG logging stuff to debug.h, pcsx2.rc & resource.h + Added kputs handling for scePrintf in Deci2Call syscall in bios.c + (Florin) + + v0.043: + * 06/11/02: add some work for amigamod.irx HLE based on Florin + RPC code (shadow) + + * 21/10/02: implement some more opcodes for VU + flags in many opcodes + (shadow) + + * 19/10/02: Added more opcodes to VUops.h (from VU0.c), and started the implementation of flags, + VUflags.h, VU* (shadow-linuzappz) + * 12/10/02: Added fix for several bioses, Hw.c, removed hack for 30002R.bin R5900.c (linuzappz) + + * 06/10/02: Added 0xb2000000 map area as a 0x12000000 mirror, Memory.c (linuzappz) + + * 06/10/02: Added/Fixed some VIF1 unpack cases, Vif.c (linuzappz) + + * 06/10/02: Started Rewrite of SetGsCrt, Bios.c (linuzappz) + + * 05/10/02: Improved gsReads/Writes GS.c (linuzappz) + + * 28/09/02: Added iop HLE code for exceptions in PsxBios.c (linuzappz) + + * 24/09/02: Added ps2 bios check for config dialog in ConfigDlg.c/GtkGui.c (Florin) + + * 23/09/02: Added command line parsing for main's argc, argv in ElfHeader.c (Florin) + + * 14/09/02: Fixed small issue in PsxBios2.c/h, Bios.c (linuzappz) + + * 13/09/02: Fixed bug in Bios.c for sif_call (linuzappz) + + v0.042: + * 25/08/02: Fixed VU SQRT/RSQRT, also added ERSQRT, VUops.h (linuzappz) + + * 24/08/02: Added several stuff for IOP hle (linuzappz) + + * 09/08/02: Added: PADDSW, PSUBSW, PPACW, PADDSH, PSUBSH, PEXTLH, PPACH, PADDSB, PSUBSB, + PPACB, PEXT5, PPAC5, PABSW, PCEQW, PMINW, PADSBH, PABSH, PCEQH, PMINH, + PCEQB, PSUBUW, PADDUH, PSUBUH, PSUBUB, PEXTUB, QFSRV, PSLLVW, PSRLVW, + PINTH, PROT3W, PSRAVW, PEXCW, PEXCH, PINTEH, PMTHI, PMTLO, PEXEW, + PREVH, PEXEH, in MMI.c (GoldFinger) + + * 09/08/02: Changed: PADDUB to conform to defines (GoldFinger) + + v0.041: + * 11/08/02: More to VUops.h (shadow) + + * 10/08/02: Rewrote L/R Stores/Loads (linuzappz) + + * 05/08/02: Add some more opcodes to VUops.h some demos works again(shadow) + + * 04/08/02: Added VUops.h, VU0.c/h, still uncomplete (linuzappz) + + * 04/08/02: Added GSgifTransfer2 for PATH1, VU1micro.c, PS2Edefs.h, Plugins.c (linuzappz) + + * 03/08/02: Added unpack v4-32, Vif.c (linuzappz) + + * 02/08/02: Rewrote partially VUmicrocode, structures and stuff, VU1/0micro.c, VUmicro.h (linuzappz) + + * 02/08/02: Small change on Misc.c (linuzappz) + + * 01/08/02: cpuExecuteBios is now called before the LoadElf, WinMain.c (linuzappz) + + * 01/08/02: Added a couple of HW_LOGS in Hw.c (linuzappz) + + * 01/08/02: Fixed MFC2/CFC2 in DisR3000A.c (linuzappz) + + * 01/08/02: Added small hack on R3000A.c (linuzappz) + + * 01/08/02: Fixed bug in StartThread Bios.c (linuzappz) + + v0.040: + * 31/07/02: Small change in PsxInterpreter.c and PsxHw.c (linuzappz) + + * 31/07/02: Added CDVDgetTN and CDVDgetTD, PS2Edefs.h, Plugins.c, CdRom.c/h (linuzappz) + + * 30/07/02: Fixed Gte.c, now includes PsxCommon.h (linuzappz) + + * 30/07/02: Added GPU_LOG to Debug.h (linuzappz) + + * 30/07/02: IOP now has vsyncs, PsxCounters.c/h (linuzappz) + + * 30/07/02: Added PsxGPU.c/h, moved the GPU_xx stuff from PsxBios.c, PsxDma.c (linuzappz) + + * 24/07/02: Added psxSIF1transfer to R3000A.c,, Sif.c, still not working (linuzappz) + + * 24/07/02: Added a couple of address more to PsxHw.c (linuzappz) + + * 24/07/02: Added zeroEx func to trace writes to stdout, PsxInterpreter.c (linuzappz) + + * 24/07/02: Improved bios_write, PsxBios.c (linuzappz) + + * 24/07/02: PsxMem.c now handles the full 4mb of the bios mem (linuzappz) + + * 24/07/02: Hack for 30002R bios, R5900.c (linuzappz) + + * 24/07/02: Fixed BNEL, BEQL in disR5900.c (linuzappz) + + * 22/07/02: Remove biosCall, now use only biosException, Bios.c/h, Interpreter.c, + R5900.c (linuzappz) + + * 21/07/02: Intialaze of VU1 vu1microc,vumicro.h,R5900.c (shadow) + + * 21/07/02: implement VIF0transfer same way as VIF1transfer vif.c (shadow) + + * 20/07/02: Add debug logs in vu0,vu1 micromode + vu0 execute vu0micro.c, + vu1micro.c,vumicro.h (shadow) + + * 18/07/02: Clean up vu0 macromode vu0.c (shadow) + + * 19/07/02: PsxMem.c now handles 0xbf80xxxx hw addresses (linuzappz) + + * 17/07/02: IOP PRid is 0x1f (not 0x2), R3000A.c (linuzappz) + + * 17/07/02: More to VU1micro.c (shadow) + + * 14/07/02: Added psxMemRLUT/psxMemWLUT instead of only psxMemLUT, PsxMem.c/h (linuzappz) + + * 11/07/02: Added MADD1, MADDU1, PMFHL, PCGTW, PMAXW, PADDH, PSUBH, PCGTH, + PMAXH, PADDB, PCGTB, MMI.c (goldfinger) + + v0.039: + * 08/07/02: Commented the 0xe000 hw dma test, for jasper, Hw.c (linuzappz) + + * 08/07/02: Changed PADreadStatus for PADstartPoll/PADpoll, Plugins.c, PS2Edefs.h, Bios.c, + PsxBios.c, Sio.c (linuzappz) + + * 07/07/02: More to Vif1 dma and added vu1ExecMicro, Vif.c, VU1micro.c/h (linuzappz) + + * 06/07/02: Rewritten/updated iop code, CdRom.c/h, Common.h, Iop*, Psx*, Debug.h, + Decode_XA.c/h, DisR3000A.c, ElfHeader.c, Gte.c/h, Mdec.c/h, R3000A.c, + R5900.c/h, Sio.c/h, iR3000A.c, Bios.c, pcsx2.dsp (linuzappz) + + * 05/07/02: Added CDVDreadTrack/getBuffer and now we're using CDVD plugin, PS2Edefs.h, + Plugins.c, ConfigDlg.c, ini.c pcsx2.rc (linuzappz) + + * 05/07/02: Optimized recANDI and completed the mmi rec tables, iR5900.c,ix86.c/h (linuzappz) + + * 06/07/02: Add VU opcodes tables vu1micro.c,vu0micro.c,vumicro.h (shadow) + + * 03/07/02: Added MADDU, PMTHL, PLZCW, PSLLH, PSRLH, PSRAH, PSLLW, PSRLW, PSRAW in MMI.c(goldfinger) + + * 03/07/02: Small change in MULT1, MULTU1 for speed, MMI.c(goldfinger) + + * 03/07/02: Fixed MADD, PLZCW in MMI.c(goldfinger) + + * 03/07/02: Fixed signed extend in DIVU, SLL, SLLV, Interpreter.c(goldfinger) + + * 03/07/02: Fixed C_F, FPU.c(goldfinger) + + * 04/07/02: Fixed silly bug on Bios.c, also added a workaround on Counters.c (linuzappz) + + * 04/07/02: Refixed CVT_W/S, FPU.c (linuzappz) + + * 03/07/02: Fixed DIV/DIVU and implemented MOVZ/MOVN in iR5900.c (linuzappz) + + v0.038: + * 02/07/02: Small change on CVT_W, FPU.c (linuzappz) + + * 01/07/02: Changed a bit IPU.c/h, added the dmaIPUs on Hw.c and added IPU_LOG, Debug.h, + resource.h, pcsx2.rc, Common.h (linuzappz) + + * 30/06/02: Add the remaining vif regs in the structure vif.h (shadow) + + * 30/06/02: Framework for IPU ipu.c,ipu.h (shadow) + + v0.037: + * 30/06/02: Added a couple of MMI opcodes to iR5900.c, ix86.c/h, also added one more cdvd server, + Bios.c (linuzappz) + + * 29/06/02: Added most of the FPU opcodes on the recompiler, fixed DSRLV/DSLLV, and also added + LQ, SQ, MFHI, MFLO, MTLO, MTHI, iR5900.c, ix86.c/h (linuzappz) + + * 28/06/02: Refixed LDL,LDR,SDL,SDR, Interpreter.c (linuzappz) + + * 27/06/02: Fixed bug in ABS, FPU.c and completed more fpu opcodes on DisR5900.c + fix to vu0 (vu0.c) + (shadow-linuzappz) + + * 27/06/02: Fixed fileio for dummy files, Bios.c (linuzappz) + + * 26/06/02: Changes/(fixes?) to some opcodes in interpreter.c SRA,DSRA,MULT,MULTU + ,SDL,SDR,LDR,LDL.At least cubemastah is correct now!(GoldFinger) + + * 20/06/02: Fixed the new Logging, modified the files on the last entry + WinMain.c (linuzappz) + + * 18/06/02: Realtime Logging Debugger.c,resource.h,pcsx2.rc,ini.c, + Common.h,debug.h (you must enable it!)(need to fixed) (shadow) + + * 18/06/02: Add some work for sjpcm module on Bios.c (shadow) + + v0.36: + * 13/06/02: Fix basic3d on Bios.c (linuzappz) + + * 09/06/02: Fix for call/ret dma in GS.c (shadow) + + * 06/06/02: Started CDVD plugin API on PS2Edefs.h (linuzappz) + + * 06/06/02: Started HLE.c/h, Interpreter.c, Common.h, iR5900.c, InterTables.c/h (linuzappz) + + * 04/06/02: Added some more syscalls on Bios.c (linuzappz) + + * 02/06/02: Fixed some bugs on SPR.c, Sif.c, Vif.c (linuzappz) + + * 02/06/02: More work on DisR5900asm.c (shadow) + + * 02/06/02: More stuff on Vif.c/h and SPR.c (linuzappz) + + * 01/06/02: Started SIFdmas Hw.c, Sif.c/h, Common.h, added SIF_LOG to Debug.h, + also removed the BREAK code since the bios doesn't handles that, Interpreter.c (linuzappz) + + * 01/06/02: Added PLZCW to MMI.c (linuzappz) + + * 01/06/02: RFU060 is now as before, added INTC and DMAC stuff, added INTC regs 0x1000f000 and + 0x1000f010, and DMAC 0x1000e010, Hw.c/h, Bios.c, Counters.c, R5900.c/h (linuzappz) + + * 31/05/02: Thread stuff is better now, added RFU061 and fixed RFU060, Bios.c (linuzappz) + + * 30/05/02: VU0 stuff is almost complete on DisR5900asm.c (shadow) + + * 30/05/02: Set gp on ElfHeader.c (linuzappz) + + * 30/05/02: Renamed _LOG to EMU_LOG, Debug.h, WinMain.c (linuzappz) + + * 28/05/02: Implemented GetCop0/iGetCop0 bios calls, Bios.c (linuzappz) + + * 28/05/02: Added names to GPR/COP0 regs, R5900.h, COP0.c, Bios.c, Interpreter.c, + FPU.c, DisR5900.c, R5900.c, VU0.c, MMI.c, iR5900.c, ElfHeader.c (linuzappz) + + * 28/05/02: Fixed PSUBW, PSUBB, added PADDW, PEXTLB, PEXTUH, MMI.c, PERF + on Interpreter.c, and TLBWR, TLBR to COP0.c (linuzappz) + + * 28/05/02: disasm.c/h is now DisR5900asm.c, Debugger.c, Debug.h, also added symbols + support for it (linuzappz) + + v0.35: + * 27/05/02: INCREASE VERSION ON 0.036! WinMain.c (shadow) + + * 27/05/02: add partialy support for VU0 in Win32 disasm.fix a bug in tables for MMI + disasm.c disasm.h (shadow) + + * 27/05/02: add VU1 register debugger. resource.h, pcsx2.rc,debugger.h, debugreg.c (shadow) + + * 27/05/02: Started real threads stuff on Bios.c (linuzappz) + + * 27/05/02: Rewrote dmaGIF/dmaVIF1, GS.c/h, Vif.c/h, Hw.c/h (linuzappz) + + * 27/05/02: add Macros for VU0Mem + Some new VU0 opcodes VISWR,VILWR, (shadow - [TyRaNiD] ) + + * 27/05/02: add some new Defines (_Id_ _Is_ _It_ _Imm5_) and some new opcodes + VIADD,VISUB,VIOR,VIAND,VIADDDI,VFOI12,VFOI15,VABS (shadow) + + * 26/05/02: Added support for Symbols on DisR5900.c, ElfHeader.c, Debug.h, + also refixed the qwc on SPR.c (linuzappz) + + * 26/05/02: Added some cdvdfsv stuff on Bios.c, also set the gs revision to 3 in + CSR, GS.c (linuzappz) + + * 25/05/02: CTC2/CFC2 to DisR5900.c (linuzappz) + + * 25/05/02: Added BREAK opcode on Interpreter.c (linuzappz) + + * 25/05/02: Now the b0000000 to b2000000 address are handled as a 10000000 mirror, + Hw.c, Memory.c (linuzappz) + + * 25/05/02: Removed some old code on R5900.c, rewrote a bit the ElfHeader.c (linuzappz) + + * 24/05/02: Add gsWrite... on bios_SetGsCrt (tyranid) + + * 24/05/02: MULT1/MULTU1 are now ok MMI.c (linuzappz) + + * 24/05/02: Added 1000f000 addr on hwRead32, Hw.c (linuzappz) + + * 23/05/02: add VU0 opcodes VSUBi,VSUBq,VMULA,VMULAi,VMULAq,VMSUB,VMSUBi, + VMSUBq,VMADDA,VMAX,VMINI,VADDA,VADDAi,VADDAq,VADDAx,VADDAy, + VADDAz,VADDAw,VSUBA,VSUBAi,VSUBAq,VSUBAx,VSUBAy,VSUBAz,VSUBAw, + VMSUBA,VMSUBAx,VMSUBAy,VMSUVAz,VMSUBAw,VMSUBAi,VMSUBAq (shadow) + + * 23/05/02: add VU0-1 status. (vu0.h , vumicro.h) (shadow) + + * 23/05/02: Added VU0/1micro.c/VUmicro.h (shadow) + + * 23/05/02: Fixed bios_isceSifDmaStat (return -1), also started some work on the + zero-exception stuff, Bios.c, IopBios.c, R5900.c (linuzappz) + + * 23/05/02: VRNEXT should be fine now, VU0.c (linuzappz) + + * 23/05/02: Small addition on Bios.c, 0x80000003 cmd on bios_isceSifSetDma (linuzappz) + + * 22/05/02: Added define __VU0_H__ on VU0.h (linuzappz) + + * 22/05/02: Rewritten GSdma/dmaGIF stuff, now only GSgifTransfer exists, added dmaGIF to GS.c, also added + GIF_LOG to Debug.h, Plugins.c/h (linuzappz) + + * 21/05/02: Fixed one bug in WinMain.c, now can rerun a elf ok (linuzappz) + + * 21/05/02: More stuff to Vif.c (linuzappz) + + * 20/05/02: Fixed one bug in biosException (linuzappz) + + * Started SPRdmas, SPR.c/h, Hw.c, Common.h, also added SPR_LOG, Debug.h (linuzappz) + + * 'call' dmaChain mode in dmaVIF1 should be right now (linuzappz) + + * More changes to the GS plugin API, GSdmaGIF/GSdma, PS2Edefs.h, Plugins.c, Hw.c, Vif.c, + also fixed little bug in SPU2init (linuzappz) + + * Small change in GSmakeSnapshot, now pass char *path (linuzappz) + + v0.34: + + * add more opcodes to Disasm DisR5900.c (shadow) + + * correct MTSA in interpreter interpreter.c (_Rs_ and not _Rd_) (shadow) + + * fixed FPU register debugger debugreg.c .Now registers appears float (shadow) + + * Some more stuff on Bios.c/Counters.c, timer1 intc, fixed bug in CreateSema (semaid stuff), + and added iSignalSema (linuzappz) + + * Added some VU0 opcodes to DisR5900.c (linuzappz) + + * Fixed bug in FPU.c, BC1XX branch delay (linuzappz) + + * Started Vif0/1 dmas, Hw.c, Vif.c/h, Common.h, added VIF_LOG to Debug.h (linuzappz) + + * Fixed VSUBx, VMULz, renamed VMONE to VMOVE, VU0.c (linuzappz) + + * Moved COP2 from Interpreter.c to VU0.c, and MMI to MMI.c (linuzappz) + + * fixed VU0 register debugger debugreg.c (Linuzappz-shadow) + + * Added ExecuteBlock and removed ExecuteBios on R5900cpu, R59000.h, Interpreter.c + and iR5900.c, also added psxExecuteBios, R5900.c, WndMain.c (linuzappz) + + * Some fixes to VU0.c, _Rd_ == 0, not _Rd_ != 0 (linuzappz) + + * Added MTHI1/MTLO1, MMI.c (linuzappz) + + * Rewrote Memory.c (linuzappz) + + * Improved iR5900.c branchs, and updated ix86.c/h (linuzappz) + + * Fixed bug in MULTU, (u64) stuff (linuzappz) + + * Interrupt Exception code was wrong, 0 -> 0x400 (linuzappz) + + * Started ChangeLog + diff --git a/branches/pcsx2_0.9.2/Docs/License.txt b/branches/pcsx2_0.9.2/Docs/License.txt new file mode 100644 index 0000000..7d1f860 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/branches/pcsx2_0.9.2/Docs/PS2Edefs.txt b/branches/pcsx2_0.9.2/Docs/PS2Edefs.txt new file mode 100644 index 0000000..5442da8 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/PS2Edefs.txt @@ -0,0 +1,443 @@ + PS2E Definitions v0.3.0 (beta) + ------------------------------ + + Author: linuzappz@pcsx.net + +Note: Refer to PS2Edefs.h for more info. + +1) API Funcs +2) FAQs +3) Notes + +1) API Funcs: + --------- + + Common stuff: + ------------ + +// u32 CALLBACK PS2EgetLibType(void); + +Gets the plugin type, from the following defines: + +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +Note that the types can be ORed so you can make an +ie. GS/PAD plugin in one dll. + +// u32 CALLBACK PS2EgetLibVersion(void); + +Will get the plugin version: + +const unsigned char version = 1; // GS library v1 +const unsigned char revision = VERSION; +const unsigned char build = BUILD; // increase that with each version + +return version<<16|revision<<8|build; + +'version' is the GS plugin API version, as this is beta, +it should be 1. +'revision' and 'build' are plugin defined values. + +// char* CALLBACK PS2EgetLibName(void); + +Get the LibName, ie. "GSsoftdx Driver"; + + + + GS plugin API: + ------------- + +Basic funcs +----------- + +// s32 CALLBACK GSinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK GSopen(void *pDsp, char *Title); + +Opens the plugin, return 0 on success, else -1. +The plugin must fill the 'pDsp' arg (32bit) that'll be +passed to other plugins (*1), this is OS dependant (*2). + +On Win32: pass a HWND value, ie: + *(long*)pDsp = (long)GShwnd; +On Linux: pass a Display value, ie: + *(long*)pDsp = (long)display; + +*1 Even if this value is passed to every plugin, this +may not be used by the plugins. + +*2 This could change anyways, ie. maybe you can code a +GS/PAD plugin for a speacial library, so the pDsp +will be a value that you need to communicate between +them (if you need to do this). + +// void CALLBACK GSclose(); + +Close the plugin. + +// void CALLBACK GSshutdown(); + +Shutdown the plugin. + +// void CALLBACK GSvsync(); + +Called on every VSync. + +// void CALLBACK GSgifTransfer(u32 *pMem, u32 size); + +Transfer 'size' qwords (128bit) from 'pMem' to the Gif. + +// void CALLBACK GSgifTransfer2(u32 *pMem); + +Transfer a qwords (128bit) block from 'pMem' to the Gif. + +// void CALLBACK GSwrite32(u32 mem, u32 value); + +Writes to address 'mem' data 'value', 32bit. +Addresses can range from 0x12000000 to 0x14000000. + +// void CALLBACK GSwrite64(u32 mem, u64 value); + +Writes to address 'mem' data 'value', 64bit. +Addresses can range from 0x12000000 to 0x14000000. + +// u32 CALLBACK GSread32(u32 mem); + +Returns 32bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +// u64 CALLBACK GSread64(u32 mem); + +Returns 64bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +Extended funcs +-------------- + +// void CALLBACK GSkeyEvent(keyEvent *ev); + +Gets called when there is a keyEvent from the PAD plugin + +// void CALLBACK GSmakeSnapshot(char *path); + +Makes an snapshot of the vRam, can be a with the full +vRam or just the view area (as you prefer), to the dir +'path'. + + +// #ifdef __WIN32__ +// s32 CALLBACK GSsetWindowInfo(winInfo *info); +// #endif + +Windows only function, will pass the info struct to the +GS plugin, if the plugin will use this info it should +return 1 (TRUE), else the emu will destroy the window +handle and let the plugin take care of that. +This function must be called before the GSopen. +Note that the emu should hide the hMenu and the hStatusWnd +if it they are set. +The position and size of the window is not specified and +should be reset by the plugin, but the window passed should +be in a normal state, not maximized nor minimized. +After a GSclose the emu must destroy the window and +recreate it. + +// void CALLBACK GSconfigure(); + +Configure the plugin. + +// void CALLBACK GSabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK GStest(); + +Returns 0 if the plugin should work ok, else -1. + + + + PAD plugin API: -=[ OBSOLETE ]=- + -------------- + +Basic funcs +----------- + +// s32 CALLBACK PADinit(u32 flags); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK PADopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK PADclose(); + +Close the plugin. + +// void CALLBACK PADshutdown(); + +Shutdown the plugin. + +// keyEvent* CALLBACK PADkeyEvent(); + +Called every vsync, return NULL if no event happened. + +// u8 CALLBACK PADstartPoll(int pad); + +Starts polling data from the PAD, 'pad' can be 1 (pad1) +or 2 (pad2). +Returns first byte from buffer; + +// u8 CALLBACK PADpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt" or "padmem.txt", +for info about value/buffer data. + +// u32 CALLBACK PADquery(); + +returns: 1 if supported pad1 + 2 if supported pad2 + 3 if both are supported + +Extended funcs +-------------- + +// void CALLBACK PADconfigure(); + +Configure the plugin. + +// void CALLBACK PADabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK PADtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SIO plugin API: + -------------- + +Basic funcs +----------- + +// s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); + +Inits the plugin, return 0 on success, else -1. +port/slot combination will be used to load the corresponding + configuration data from ini. It's like an id for the instance. +'f' is a callback function that is used by SIO_TYPE_MTAP capable + plugins to change active slot in emulator (since sio is emu-controled). + +// s32 CALLBACK SIOopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK SIOclose(); + +Close the plugin. + +// void CALLBACK SIOshutdown(); + +Shutdown the plugin. + +// u8 CALLBACK SIOstartPoll(u8 value); + +Starts polling data from the SIO, 'value' is + 0x01, 0x21, 0x61 and 0x81 corresponding to pad, mtap, rm and mc. +Returns first byte from buffer; + +// u8 CALLBACK SIOpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt", "padmem.txt" or + "padspecs.txt" (http://ps2dev.ps2-scene.org/padspecs.txt), +for info about value/buffer data. + +// u32 CALLBACK SIOquery(); + +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +returns: ORed value of SIO_TYPE_xxxx - the capabilities of the plugin +eg. a remote control plugin will return SIO_TYPE_PAD | SIO_TYPE_RM + +Extended funcs +-------------- + +// void CALLBACK SIOconfigure(); + +Configure the plugin. + +// void CALLBACK SIOabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK SIOtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SPU2 plugin API: + --------------- + +TODO :) + +Basic funcs +----------- + +// s32 CALLBACK SPU2init(); +// s32 CALLBACK SPU2open(void *pDsp); +// void CALLBACK SPU2close(); +// void CALLBACK SPU2shutdown(); +// void CALLBACK SPU2update(); +// void CALLBACK SPU2dma(u32 *dmaAddr, char *pRam); +// void CALLBACK SPU2write(u32 mem, u16 value); +// u16 CALLBACK SPU2read(u32 mem); + +Extended funcs +-------------- + +// void CALLBACK SPU2configure(); +// void CALLBACK SPU2about(); +// s32 CALLBACK SPU2test(); + + + + CDVD plugin API: + --------------- + +Basic funcs +----------- + +// s32 CALLBACK CDVDinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK CDVDopen(); + +Opens the plugin, return 0 on success, else -1. + +// void CALLBACK CDVDclose(); + +Close the plugin. + +// void CALLBACK CDVDshutdown(); + +Shutdown the plugin. + +// s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +Starts reading from the specified 'lsn' sector location, +return 0 on success, else -1. + +// u8* CALLBACK CDVDgetBuffer(); + +Gets a pointer to the buffer with the sector data +readed by a previously CDVDreadTrack call. +The buffer size depends on the mode used for readTrack. + +note: return can be NULL (for async modes) + +// s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq); + +Read subq data from disc at 'lsn' location (only cds have subq data), +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); + +Get the the cdvdTN data for the currect CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTD(u8 Track, cdvdLoc *Buffer); + +Get the the cdvdTD data for the 'Track' track in the current CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTOC(void* toc); + +Get ps2 style toc from disc, return 0 on success, else -1. +(ps2 toc isnt quite the same as a normal disc toc, +especially for dvds) + +// s32 CALLBACK CDVDgetDiskType(); + +Returns disktype in the format CDVD_TYPE_xxxx + +// s32 CALLBACK CDVDgetTrayStatus(); + +Returns tray status in the format CDVD_TRAY_xxxx + +// s32 CALLBACK CDVDctrlTrayOpen(); + +Opens disc tray, return 0 on success, else -1. + +// s32 CALLBACK CDVDctrlTrayClose(); + +Closes disc tray, return 0 on success, else -1. + + +Extended funcs +-------------- + +// void CALLBACK CDVDconfigure(); + +Configure the plugin. + +// void CALLBACK CDVDabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK CDVDtest(); + +Returns 0 if the plugin should work ok, else -1. + + +2) FAQs + + * What's the right open/close sequence? + 1. CDVD + 2. GS + 3. PAD1/2 + 4. SPU2 + + * Where to start coding a plugin? + Get an open source plugin, mine are all open source, + so you can freely base on them. + + * Why GSgifTransfer2 exists? + GSgifTransfer2 is used by the XGKICK VU1 opcode, and + it doesn't has a size, the GSgifTransfer is used by he GIF + and the VIF dmas, and it has a size, so that's why :). + +3) Notes + + * CDVDgetBuffer should be used after CDVDreadTrack, + like this: + CDVDreadTrack(time); + ptr = CDVDgetBuffer(); + + but not like this; + ptr = CDVDgetBuffer(); + CDVDreadTrack(time); + + * Errors should be checked for both CDVDreadTrack and CDVDgetBuffer, + and not only CDVDreadTrack. + diff --git a/branches/pcsx2_0.9.2/Docs/Readme.txt b/branches/pcsx2_0.9.2/Docs/Readme.txt new file mode 100644 index 0000000..20d2c18 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/Readme.txt @@ -0,0 +1,196 @@ + + + + +PCSX2 - A PS2 EMU +------------------ +Here it is. A first try for an ps2 emulator... +Of course it isn't very advance now but there are some stuff here... + + + +Overview +-------- +Well i will try to catch up some questions. +First of all pcsx2 don't run Ps2 games yet! +And of course it is far from doing this. +So pcsx2 don't run GT3, get it? :) +So what pcsx2 is? pcsx2 is a try to emulate sony's beast. +Of course it isn't so easy as it might seems. +So far you can consider pcsx2 as a develop tool althought +i suggest don't use pcsx2 as a tool for writing your ps2dev +stuff :). Consider the opinion that pcsx2 have bugs and we +wrote this emu by reverse enginnering ps2 demos that might +have bugs too :) +Hope you enjoy pcsx2.. + +The Pcsx2 team.. + + +Configuration +------------- + +Cpu Options: + + +Misc Options: + + * Enable Console Output: + Displays the psx text output. + + + * Enable patches + Enable the patches for games.(if they exist). + Might fix some stuff might screw some stuff. + Enable it at your own risk. + + * Enable pad hack. + if your pads doesn't seem to work if you enable that much fix the pads for the specific game. + Warning!! not leave that option checked might broke some other games as well + +Recompiler options: + +* Disable Recompiler (default). It will run with interpreter if it is ON. + Slower but more compatible. + +* Disable Vu recompiler (default). Will disable the vu recompile + (of course if recompile mode is used). More compatible recompiler but slower. + + * Enable reg caching (disabled in 0.6) + Enable the reg caching recompiler (you must have enable interpeter cpu off!) + It is more faster than the default recompiler + + + +Quick Keys: + F1: Save state + F2: Change slot (0-5) + F3: Load State + F8: Makes a Snapshot + + (debugger keys) +---------------- + F11 un/sets Log + F12 un/sets symbol logging + +Status +------ + +Most part of ps2 have been emulate. + +Things that are still missing or uncomplete + +IPU : decoding almost done. Pcsx2 can play *.ipu or *.m2v files but no pss yet +VU : there are several issues with graphics ingames. Still we are not sure if it is GS, VIF or VU problems + but we are looking for it +recompiler: planning for fast reg cache core and recompile of vus . Soon :P + + +and of course a million other bugs that exists and we hope they will be fixed ;0 + + + + + +How you can help +---------------- +If you have any info you think we can use email us, but always ask before +sending files. If you want to help in some other way also email us. + + + +The Team +-------- +Nickname | Real Name | Place | Occupation | e-mail | Comments +--------------------------------------------------------------------------------------------------------------- +Linuzappz | | Argentina | Main coder | linuzappz@pcsx.net | Master of The GS emulation and so many others.. +Shadow | George Moralis | Greece | co-coder-webmaster| shadowpcsx2@yahoo.gr | Master of cpu, master of bugs, general coding... +florin | Florin Sasu | Romania | co-coder | florin@pcsx2.net | Master of HLE. Master of cd code and bios HLE.. +asadr | | Pakistan | co-coder | | Fixing bugs around (FPU, Interpreter, VUs...) +Goldfinger | | Brazil | co-coder | | MMI,FPU and general stuff +Nachnbrenner| | Germany | co-coder | | patch freak :P +aumatt | | co-coder | | a bit of all mostly handles CDVD cmds +loser | | Australia | co-coder | loser@internalreality.com | obscure cdvd related stuff +refraction | Alex Brown | England | co-coder | refraction@gmail.com | General Coding DMA/VIF etc + +ex-coders: +basara -co-coder . Recompiler programmer. general coding +[TyRaNiD] -co-coder . GS programmer.General coding +Roor -co-coder . General coding + + +Additional coding: + +F|RES +Pofis +Gigaherz +nocomp + + +BETA testers +------------ +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever + + +Team like to thanks the Follow people +------------------------------------- +Duke of NAPALM - for the 3d stars demo. The first demo that worked in pcsx2 :) +Tony Saveski (dreamtime) - for his great ps2tutorials!! +F|res - You will learn more about him soon. but a big thanks from shadow.. +Now3d - The guy that helped me at my first steps.. +Keith - Who believed in us.. +Bobbi - Thorgal: for hosting us, for design or page and some many other +Sjeep - Help and info +BGnome - Help testing stuff +Dixon - Design the new pcsx2 page, and the pcsx2.net domain +bositman - pcsx2 beta tester :) (gia sou bositman pare ta credits sou ) +No-Reccess- nice guy and great demo coder :) +nsx2 team - for help to vu ;) +razorblade - for the new pcsx2 logo,icon. +snake - he knows what for :P +ector - awesome emu :) +zezu - a good guy. good luck with your emu :P + + + + +Credits +-------------- +Hiryu & Sjeep - for their libcdvd (iso parsing and filesystem driver code) +Sjeep - for SjDATA filesystem driver +F|res - for the original DECI2 implementation +libmpeg2 - for mpeg2 decoding routines +aumatt - for applying fixes to pcsx2 +Microsoft - for vc.net 2003 :p (really faster than vc6) :P +NASM team - for nasm +CKemu - logos/design + + +and probably to a few more.. + +Special Shadow's thanks go to... +-------------------------------- +My friends : Dimitris, james, thodoris, thanasis and probably to a few more.. +and of course to a lady somewhere out there.... + + + + + +Log off/ +Linuzappz/ shadow / florin / asad/ goldfinger / nachbrenner (others???) + + + + + + + diff --git a/branches/pcsx2_0.9.2/Docs/RemoteDebugging.txt b/branches/pcsx2_0.9.2/Docs/RemoteDebugging.txt new file mode 100644 index 0000000..339b400 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/RemoteDebugging.txt @@ -0,0 +1,105 @@ +ͻ +NOTE: 1. this is an internal pcsx2 team document, for developers ONLY + 2. lamers/gamers are excluded + 3. DECI2 will not run your games:P +ͼ + +RemoteDebugging +=============== + +This is a new feature available for debugging applications within pcsx2 emu. + Using a remote debugger is not wellcomed unless it is more featured. + Fortunately, there are such debuggers. Currently added support is for win32 + target only; also, only TCP/IP remote connection and only for Sony's DECI2 + app-level protocol. Future addition could be GNU debugger remote support. + +Anyway, pcsx2 has a new menu item that allows one to start a debugging session + by specifying the listen port [default for DECI2 is 8510]. Pcsx2 will act like + a server for the remote debugger. It is set to accept connections on any IP. + For local debugging sessions, use IP=127.0.0.1 aka IP=localhost. On the + other hand, if a pcsx2 would be listening on an active IP in the Internet, + anyone could connect to it;) Only one connection is supported. After the + connection is closed by the client/remote tool, the only thing to do is to + "admire" the log window and then close it/restart the emu. + +So, to start a debug session: + - first start the emu [quite reasonable; because it will be the server]. There + are some issues if you start the client first or if you didn't close ALL the + client subprograms in the last debugging session. + - choose from the menu, Debug->Remote Debugging. A dialog will pop asking for + the port to use. Also, if you have a non-HLE bios selected in the Config box, + ie. a true bios, there will be also an option weather to debug the bios. You + have 2 choices: + -not checked=Run Bios + before any debug is performed a bios run. ie. the emu + will run the bios up to the shell loading or a bit + further, to the moment when all the iop modules are + loaded. You will have then a full environment loaded. + -checked=Debug Bios + nothing is done further and the PC=0xBFC00000. + - after that a connection log window will be shown and you can follow the + connection data exchange. First, the emu is placed in a wait state. + - this is the moment you have to run the client. It will open the connection. + The emu accepts the connection and the DECI2 protocol is on;) + You'll see how the client queries for registers values & memory areas. + - the situation gets complicated since you can do many things from now on: + +Debug bios: + - start with a bios selected and the check box checked (see above). + - PC=0xBFC00000 and you can trace the bios now. Anyway, there is no breakpoints + support for the bios as the client "thinks" you are debugging the real PS2, + so you cannot write to bios area. BTW: the breakpoints are implemented by + patching the code with a BREAK instruction. Since you cannot write such instr + you cannot put a breakpoint on the bios, cannot run to address and so on... +Run bios: + - start with a bios selected and the check box not checked (see above). + - wait till the emu runs the bios...it will take some time. After THAT the + connection log window will be displayed. + - PC=0x82000 or smth like that...you can check the environment set up while + running the bios. The modules window for instance. And various memory + structures. Also, this is the entrypoint of the shell loading. Try to trace + it;) +Debug an application: + - start with HLEbios selected (see above) + - since the debugger (the client) does debug whatever you want to. You can + load the elf to debug with pcsx2 loader (ie. with File->Load ELF file or + from the CDVD). But you will need to know the entrypoint to force it in + remote debugger (set PC to cursor or to address). This way is not recomended. + I like to use the loader of the debugger since it knows to load the source + also if available and does not cause troubles with setting the PC. Also, if + the ELF has symbols, it can run it to main;) + - now, you're on your own. Use step by step, step over, breakpoints, run to + cursor, run to address etc. HAPPY DEBUGGING! + +KNOWN ISSUES and NOTES +====================== + - use CDVDnull or another plugin as you like to have or not a src for cdvd + loading;) + - pcsx2 does not have support to debug the IOP. You can do this now but it is + a hard job. That is due to the fact that PS2 can run every processor + independently (ie. one can be stopped) and pcsx2 cannot. The emu runs either + all the procs or nothing. So, in the debugger, the debugged processor is on + stop and others are "running". When there will be added support for debugging + the IOP, also only one processor will run. + - do not step through the program very fast. Because of the communication speed + and a reentrancy issue, this will get the debugger in a FALSE run state. That + means that the debugger "thinks" that the PS2 (ie. pcsx2;)) is running, + although it is not. The simple solution to this is to press STOP/BREAK button + in the debugger. Notice also that some run states might be also true! When + you are stepping over a big loop...that might take some time, so if you stop + the emu you will get in the middle of the loop:P + - you can also notice the low speed that can also be met in the pcsx2 debugger. + That's because Cpu->Step() is used. + - also, notice that you cannot debug in recompiler mode! ONLY interpreter mode + works! + - IOP modules loading is not supported and the files loaded from host directory + are also loaded in pcsx2 way, ie. from host\ directory; not through remote + debugger. + - if you try to debug the bios and the code is not displayed...scroll down + in order to have only valid addresses on the screen; ie. the top address + to be 0xBFC00000 and in emu communication log there will be no ADDRESS ERROR. + + +=============================== +Florin (florinsasu@yahoo.com) +2003/04/17 diff --git a/branches/pcsx2_0.9.2/Docs/RunCDVD.txt b/branches/pcsx2_0.9.2/Docs/RunCDVD.txt new file mode 100644 index 0000000..abcede5 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/RunCDVD.txt @@ -0,0 +1,86 @@ + +RunCDVD - New feature explained +=============================== + +Q: What CDVD stands for? + +A: It is a short form for CD/DVD i.e. CD or DVD. + +---------------------------------------------------- + +Q: Can I run games? + +A: What do you mean by games? + There are two types of games: commercial ones and homebrew ones. + There are also two types of demos: from magazines and homebrew. + Homebrew SW will run first as they are simpler and are open-source sometimes. + +---------------------------------------------------- + +Q: Can I run commercial games? + +A: Yes, but this answer is not good for you:P + You cannot play them... + Technicaly, the game starts but it does not go very far, + because this is only the beginning... + +---------------------------------------------------- + +Q: So, what's the deal then? Is there any game that run? more? + +A: Yes, but as far as we know, not any comercial game. + Homebrew iso version of PSMS runs ok. + Also we cannot test with all the games as we don't have them all:P + +---------------------------------------------------- + +Q: When can I play game X ? + +A: Dunno, only time can say that... + We only added the CDVD loading option for now. + You will have to wait for another version of the emu to see any screenshot. + +---------------------------------------------------- + +Q: How do I run a CD/DVD game or iso/bin? + +A: You need a CDVD plugin. + Get the CDVDbin for Windows & CDVDlinuz for Linux + from http://pcsx2.ngemu.com (Download section) or from http://www.ngemu.com + Place it in Plugins directory. Run the emu and in configure dialog choose + that plugin. Then Run->Execute. When using the CDVDbin plugin + you will be promted to choose a file to use. + Select the iso or the bin of the game you own. + (To test that use psms.iso) + +---------------------------------------------------- + +Q: I have the game X on CD/DVD. What's the iso/bin stuff anyway? + +A: Well, if you have a game on CD/DVD and a bad CD/DVD drive, + you can backup it on the harddisk with a CD/DVD recording program or a simple + iso/bin ripper. That program will make an image of the CD/DVD disc + on the harddisk and you can use that image with the CDVDbin plugin. + +---------------------------------------------------- + +Q: What's the difference between .iso and .bin formats? + +A: Bin is an image with raw sectors of 2352 bytes. + Iso contains only the data part from a CD sector; ie. 2048 bytes + +---------------------------------------------------- + +Q: I have more questions. Where are the answers? + +A: First of all, think twice before asking a question. + It might be already answered or the answer is toooooo simple. + Also, there can be more questions that i missed. Use the PCSX2 forum + on http://www.ngemu.com for that. Thank you! + + +=============================== +Florin (florin@ngemu.com) + + + diff --git a/branches/pcsx2_0.9.2/Docs/ToDo.txt b/branches/pcsx2_0.9.2/Docs/ToDo.txt new file mode 100644 index 0000000..a8a595c --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/ToDo.txt @@ -0,0 +1,22 @@ +To do for Pcsx2: + * Fix threads, semas & events (linuzappz, Florin) + * Deci2: iop debug (since pcsx2 cannot run only one processor) (Florin) + tty notifications + * Continue RunCDVD option for PS1 exes loading. + * Continue Bios emulation. (linuzappz) + * Continue Recompiler. (linuzappz, basara) + * Fix bios execution. (linuzappz) + * Recheck TLBS. + * Continue HW stuff. (linuzappz) + * Fix VU code. (shadow) + * Check MMI.c. + * Check FPU code. + * Implement remaining COP0 opcodes. + * Deci2: + -speed up execution with Cpu->ExecuteBlock(); + -fix reentrancy problem with threads (if pressed step button to soon, + you get a false run state: the emu is on pause, but the debugger + thinks that it is running) (solution: critical zones) + -add drfp support [i guess this will not be done as it is not really needed] + -add iop files load&run support (iloadp; not a priority also) + (Florin) diff --git a/branches/pcsx2_0.9.2/Docs/Translating.txt b/branches/pcsx2_0.9.2/Docs/Translating.txt new file mode 100644 index 0000000..b936bb0 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/Translating.txt @@ -0,0 +1,24 @@ + Translating PCSX2 + ----------------- + +Just some small notes for translators. + +PCSX2 translations are based on the gettext library: +http://www.gnu.org/software/gettext. + +The main file to translate is pcsx2.po located at the +'Intl' dir, note that you must place the translated +strings over the msgstr and leave untouched the msgid. + +To test the translation use the msgfmt.exe utility to +convert the translated pcsx2.po file to a pcsx2.mo file +with this command: 'msgfmt pcsx2.po -o pcsx2.mo', after translating +the file please send it to us and please ask before +translating it, maybe someone has already started it +for your language. + +If you have any problems contact us and we'll try to +help you. + + linuzappz + diff --git a/branches/pcsx2_0.9.2/Docs/What_Is_Host.txt b/branches/pcsx2_0.9.2/Docs/What_Is_Host.txt new file mode 100644 index 0000000..5671a49 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/What_Is_Host.txt @@ -0,0 +1,45 @@ + +I will try to explain in sorta how HOST is working.. +----------------------------------------------------- + +Ps2 have the ability to use loader also other than cd-rom. +That is done through special syscall. Of course the file that +you load must support that.. + +Basically we wrote that for PSMS1.2 + +As you can see in the psms1.2 zip there is a file called psms-naplink.elf. +Well that is basically created from sjeep (hi sjeep) for be able to +use psms through your USB naplink to your ps2. (so no need to burn a cd) +Well pcsx2 does exactly that. Emulate Host +client (host is your pc, +client is your ps2). + +So how is work? +--------------- +Imagine that HOst is your cd-rom . +For psms e.g +place FILES.TXT + roms in folders that specificate in files.txt and you are +ready.. + +e.g + +Host +FILES.TXT +-ROMS1 +--Alienstorm.sms +--IamLamer.sms + +I think you get the Idea... +For more questions mail me..(shadow@pcsx.net) + +About +----- +This doc has been written from shadow... +Host support was added kindly to pcsx2 by Linuzappz +Thanks to sjeep for his psms1.2 emu and his support.. +Also thanks to Keith,bobbi,thorgal,akumax,now3d and probably to some more... + +Log off +shadow/linuzappz + + diff --git a/branches/pcsx2_0.9.2/Docs/WhatsNew.txt b/branches/pcsx2_0.9.2/Docs/WhatsNew.txt new file mode 100644 index 0000000..fb4178a --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/WhatsNew.txt @@ -0,0 +1,598 @@ + ********************************* + *What's new in pcsx2 v0.8 * 13th release + ********************************* + +General +------- +Compatibility has been increased since last release. More games go ingame now and 3d is okay in most of +them. Vurecs improved and speeded up a lot (buggy in many causes so use the simple rec for compatibility) +and IPU should work in some cases.(e.g VF4) + +CPUs +---- +Fixed QFSRV/MTSAH/MTSAB +Fixed SBUS IRQ at iop +Fix for end chain mode at vif +Fixed SPR0 chain mode +Fixed intc/dmac interrupts that gets cleared right away +Added offset/difference UNPACK modes in vif +VIF irq by vifcode seems ok now +Added interleave mode for SPR +Fixed UNPACK V4_5 with mask +Fixed small bug over VIF1 dma FIFO +VIF1 doens't clears str on MFIFO +Fixed some MFIFO bugs in both GS/VIF1 +Fixed bug in REF/REFS dma at VIF1/GS MFIFO + +IPU +--- +Finally fixed IPU. Mpegs and IPU streams run so do PSS files +Quality of ipu playback improved + +PLUGINS +------- +Added GSsetCSR +added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose to cdvd + +CDVD +---- +Added some more debug info to CDVD +Fixed cdReadKey function to emulate correctly. +Modified GetToc stuff in cdvd to support dvds +cdvdTD uses lsn now +Fixed NVM (eeprom) access from cdvd stuff +Added reading of mecha version from an external file +Fixed raw dvd sector readng for dvd9 discs (otp and ptp) +Added hw-reg read/write for DecSet register 0x1f40203A +Made cdSeek change the current cdvd sector +Fixed NReady busy stuff + +Memory +------ +Added more memRead/Write funcs for speed + +VUS +--- +Fixed bug in branch address in vus +Implemented MFLAG for VU0 +Fixed some iVUmicro bugs +Fixed some VPU-STAT related issues +Fixed vu flushing over vuExecMicro +Fixed some pipelines bug within VU1,VU0 +Reworked MAX/MINI +Fixed VU's JR/JALR/BAL,ISUBIU +Added EFU pipeline to VUmicro +Fixed DIV/RSQRT exceptions + +GUI +--- +Some improvements on interface. +Added placetopatch == 1, which means patches will be applied every vsync + + + ********************************* + *What's new in pcsx2 v0.7 * 12th release + ********************************* + +GENERAL +------- +Memcards and pads should work okay now. More compatibility earned since so many things +have been fixed from previous release :) + +VIF-VUS +------- +VIF-FIFO transfers seems to work better +VU1 regs now are mapped to VU0 mem +Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2 +Fixed vu branch negative overflows +VU D/T flags are handled now +VU pointer gets aligned now + +PLUGINS +------- + +Added Firewire plugin protocol + +SPU2 +---- +Fixed SPU2async cycle +SPUdma timings changed to 80 + +CDVD +---- +Implemented ReadNVM/WriteNVM +BCR now decrements for each cdvdReadSector +Fixes to SCMD's +ReadILink/GetMecaconVersion are really implemented +CdReadConfig/CdWriteConfig now uses NVM + +Interface +--------- +sstates now use CRC +Added IOP disasm in the debugger +Added rom2/erom support +Added Patch Browser for win32 + +IPU +--- +Several changes for IPU + + +HARDWARE +-------- +Fixed bug IOP counters +Fixed some bugs over interrupts and exceptions +Newer bios will now work with pcsx2. Pads fixed, more compatibility +Fixed SIF0/1 when fifo got filled up +Fixed EXL bug +Fixed SIF SMFLAG/MSFLAG +Fixed MCDS + + + + ********************************* + *What's new in pcsx2 v0.6 * 11th release + ********************************* + +General +------- +pcsx2 is 3 years old. Happy birthday pcsx2 :) +Now you can run even more games. some 3d games should work too . so enjoy :) + + +CPUS +---- +Recompiled VUs. Needs work but some stuff might work okay now +Fixed bug in Vif.c, masks hopefully are ok +Fixed alot of bugs in VUs, hopefully some stuff will now work as it should +Added Interlock for CFC2/CTC2 +Improvements to TLB code +Restructured VU code and VIF. Fixed stuff in Interpreter and added CTC2 VU1 Microinstruction caller +Fixed UNPACK modes in VIF, the Indeterminate fields are now set to 1 by default +VUflags now should handle overflow/userflow ok + +Hardware +-------- +Fixed DMA8 +Fixed bug in GS for CSR stuff +Fixed savestates +Fixed several SIF bugs +FIFO is now really 128bit as it should be +Added code for dma interrupts +Added some scmds to CDVD +Improved and fixed sio2 stuff +Modified the DEV9irq stuff +loadElfFile now reads the whole file first +DMA4/7 interrupt timings are more accurate now +Patches names are now using crc + +GUI +--- +Memory patcher (supports only 32bit patches so far) +Fixed Bios Detection for HK Bios + +PLUGINS +------- +ADDED usb plugins + + + ********************************* + *What's new in pcsx2 v0.5 * 10th release + ********************************* + +General +------- +A release that make you look things more promising. Several games can boot now and plenty of them can reach even ingame. +There are still big issues with graphics but many improvements have done from 0.41. Some games that now can reach ingame +are: +wild wild racing PAL (with patches) +Street fighter ex3 PAL (with patches) +Le Mans 24 Hours (24 Heures Du Mans) PAL (with patches) +V-rally 3 pal (with patches) + +and probably a lot more :) + + + +CPUs +--- +Fixes to VUs +Handle for the EDI flag at ERET(cop0) +New improved cpu detection routine +Commented D/T flags for VUmicro +fixed some FPU bugs in recompiler +fixed PCPYLD in interpreter +Add compiler blocks for vu0, vu1 and few instructions +Several other fixes in cpu cores +Reg caching recompiler (not enable in 0.5 ) + +Debugger +-------- +Fixed Debugger/rdebugger (there are still some issues) + +Memory +------ +Added TLB exceptions +Fixed IOP mem accesses from EE Memory +New memory routines + +VIF +--- +Fixed VIF Transfers to include MARK reg in VIF0 aswell. +FIFO for VIF0/1 now works +More improvements to VifDma +Improved VIF for transfers in parts +FiFo VIF1 can read data now + +IPU +--- +Fixed IDEC bitstream decoding. Now, all *.ipu files should work fine +bug fixes to IPU + + +Hardware +-------- +Fixed clock in bios +Fixed MFIFO for GS dma +CDVDgetTD function need a 2nd parametre (new cdvd plugins needed!!) +cdgetTOC + cdReadSubq +HSync stuff, and better CSR/IMR handling +Implemented mskpath3 / m3r flags +Fixed VU memory64 writes masks +Implemented INTC_STAT/MASK and DMAC_STAT for 64bits +Added/fixed SCMDs (2,3,1A) in cdvd +Vif0/1 regs are now mapped to hardware +Fixes in sio, sio2 +Destination Chain for SPR0 dma and added Vif masking +Now pad2 works in lle mode [tested with bios browser] +New SCMDs and MC commands +Fixed dmaIrq's for Source Chain mode +Fixed ret DMA op +Added a base interrupt delay for the dma7 (spu2) +Fixed pads. Now it should work okay most of the times +Changed the way we handle SPR TTE transfers + +MISC +---- +Added the possibility to load the System.map from ps2linux +Added patching system. *pnach files are used now +Added dev9 plugins +Savestates + + + ********************************* + *What's new in pcsx2 v0.41 * 9th release ( Update ) + ********************************* + +General +------- +This release fixes a minor issue with the DVD iso's not booting, as of now DVD iso booting +is fixed so please try all your games again !:) + +Hardware (lle) +-------- +Fixed bug in CDVD code for DvdReads, now DVD iso's should boot just fine. + + + ********************************* + *What's new in pcsx2 v0.4 * 9th release + ********************************* + +General +------- +This release is how we wanted the first pcsx2 release to be. Finally bios is working so +many things can happend from now on. Also "Bust a Move" seems to work and other games +like Kengo 2 goes much further. All of course is done in LLE now :) . + +CPUS +---- +fix the recompiler bug that made recompiler not to work in pcsx2 0.3 +new vu code. VU0 macromode should be perfect now. +new optimaze code for fpu +Rewrote VIF once again +bug fixes to MMI +reorganize recompiler + + +DMAS +---- +Improved SIF0,SIF1,SRP1 +Added IPU0,IP1 dmas + +IPU +--- +Added decoding and commands. Some samples are working. NO pss support yet! + +IOP +--- +improved the IOP stuff.IOP is functional under bios execution :) + +HLE +--- +more WIP in Threads .Much better now +more WIP in padman. + + +Hardware (lle) +-------- +ADDED SPU2 functions. SPU2 is now possible if someone implement a SPU2 plugin. +Changed a bit the GS protocol. Gs plugins need to modificate in order to work with 0.4 +SIO2 added .Pads seems to work . Memcard partial functional +CDVD emulation added. +IOP rootcounters fixed +IOP dmas implemented +MFIFO implemented + + + +General +------ +Fixed elf loader + + + ********************************* + *What's new in pcsx2 v0.3 * 8th release + ********************************* + + + +General +------- +This version of pcsx is the first that shows ingame progress from 1 game "Sven Goran's World Manager 2002".IT is the first +ps2 emu that reaches ingame :) . Also this version have Deci2 support (usefull only for developers althought) and several +bugs have been fixed. Enjoy ;) + + + +GUI +--- +-Added MiltuLingual support( English,Catalan,German,greek,italiano,romanian,spanish) + +CPUS +---- +-Fake BC0 opcodes in cop0 +-Trap instructions fixed in interpreter +-Fixed some fpu bugs in interpreter +-Fixed MMI bugs in interpreter +-VIF1 cmd now handles the i bit, still not 100% correct +-VIF1dma now handles 'from Memory' transfers +-More Unpack case in vif +-fixed several VIF1 bugs +-VIF0 fixed also + +Hardware +-------- +-8 bit DMAS +-mem128 read/write routines +-Implemented latency interrupt thingy +-Fixes to rootcounters +-FIFO fix +-IOPmem fix +-optimaze gs dma + +Debugging +--------- +-DECI 2 Protocol !! +-fix some stuff in pcsx2 debugger +-add cpu ops debug in debugger +-Logging to STDOUT added +-add more memory mapping for EE and IOP + +HLE +--- +-rewrote of HLE code for pads (padman-xpadman). This will solve some pad problems +-rewrote the HLE code for Loadmodule +-New INTC handling in HLE bios +-Implement VSyncSetFlag in HLE bios +-Added memory dummies in mcserv. Now memcards wil be appear as functional. +-sceCDReadIOPm in CDVD HLE +-Added dummy handles for mtapman901/3 +-new Threads at BIOS HLE. Still not finished + + + + ********************************* + *What's new in pcsx2 v0.2 * 7th release + ********************************* +General +------- +pcsx2 have now a more speedy recompiler using 3dnow-3dnow2-sse instructions. Vu macromode +have been recompiled with 3d now instructions so you can see more speed there if you have a +cpu that supports 3d now. The most speed is possible with an Athlon XP cpu or a Althon 4 mobile +More support for sse or probably for sse2 soon :) + + + +rewrite of MMI +fix bugs in fileio +fix counters +new thread HLE code +fixes to CDVD HLE code +fixes-adds to VU code More vu opcodes +add some more cpu opcodes +more ipu code +add 3dnow-3dnow2-sse instructions to recompiler + + + ********************************* + *What's new in pcsx2 v0.1 * 6th release + ********************************* + +General +------- +PSMS cd version seems to work. Pgen starts to work also.. (no roms seems to working althought) +and some games might boot now... This is the first ps2 emu that boots cds :) + +GUI +--- +Added command line parsing for main's argc +Added ps2 bios check for config dialog + + +Memory +------ +Some more adds to memory maps + +CPUS +---- +Implement VU flags + some more vu0-vu1 opcodes +Fix some VIF unpack cases +Some more opcodes to R5900 + +HLE +--- +better HLE + + +RPC services for +014D704Enaplink +0B001337cdvd +80000001fileio +80000003sysmem +80000592cdvdfsv +80000597cdvdfsv +80000595cdvdfsv ++for some more but mostly dummies + +CDVD iso parser (thanks Sjeep - hiryu) +support for SJDATA file system + + + ********************************* + *What's new in pcsx2 v0.042 * 5th release + ********************************* + +GENERAL COMMENTS +---------------- +Micromode works at the release. Also some more macromode demo should +work on this release.Enjoy ;) +NOTE: Logging has been disable from the release. If you need it +Mail me ( shadow@ngemu.com) + + +GUI +--- +-ADD CDVD plugin (partially) +-change a bit the controller plugin protocol +-change a bit the GS plugin protocol (for the VUmicromode transfers) + + +CPUS +---- +-FIXES to R5900 +-FIXES to FPU +-More work in recompiler +-ADDS+fixes opcodes for MMI +-Rewritten/updated iop code +-More work to micromode (vu0-vu1) + + + +DMA +--- +-More to VIFS DMA +-More to SIFS DMA + + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.038 * 4th release + ********************************* + + +GENERAL COMMENTS +---------------- +Vu0 appears functional now. (Most of the causes ) + + +CPUS +---- +Fixes to main R5900.Many opcodes fixed ( thanks Goldfinger) +Fixes to FPU +Add some Framework for the IPU +Add some more opcodes to the recompiler including FPU opcodes + + +Debugger +-------- +Logging system + + +BIOS HLE +-------- +some support for sjpcm.irx +Fixed fileio for dummy files + + +----------------------------------------------------------------------- + + ********************************* + *What's new in pcsx2 v0.036 * 3rd release + ********************************* + + +Debugger +------- +-Add VU0 - VU1 register window +-Add VU0 macromode in disasm (still not finished) +-Added support for Symbols + +GUI +--- +-Add SPU2 interface (very partial) +-change GS specifications a bit + +CPUS +---- +-Fixed some bugs in R5900.c +-Improve recompiler +-Add VIF0 - VIF1 (very partial) +-Add more VU0 macromode instructions +-Add IOP proccesor (partial) +-Add More opcodes in MMI +-better COP0 emulation (more tlbs) + +DMA +--- +-add Stratchpad DMAS +-add VIF dmas +-add SIF dmas (very partial) + +Memory +------ +-Total rewrite to support more HW + +BIOS HLE +-------- +Many more syscall is hle now. Compatibility increase a lot + + + +General +------ +Many stuff that we are not able to explain them in details :) + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.031 * 2nd release + ********************************* +-New icon +-New logo +-Some startup work on VU0.Many VUO macromode opcodes +-Some more opcodes in the main cpu. MFSA,MTSA,SQC2,LQC2 +-More opcodes to the MMI. +-Finished R5900 FPU. +-pad emulation using HLE.. both pad1 + pad2 +-more fixes to Recompiler (still far from finish) +-add the 4 Couters(partial) +-add FIFO registers +-Add support for HOST + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.026 * 1st release + ********************************* + +FIRST RELEASE ALL ARE NEW :) + diff --git a/branches/pcsx2_0.9.2/Docs/devblog.txt b/branches/pcsx2_0.9.2/Docs/devblog.txt new file mode 100644 index 0000000..130345c --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/devblog.txt @@ -0,0 +1,273 @@ +Developers Blog +=============== + +This file is mainly an R&D document containing developers findings. The aim is + to have it as much accurate as possible. Each item has to contain a number(ID), + the name of developer, revisions history and a short description. +Also, this document will serve as a pinboard - will contain coding rules, + explanations on implementation of different parts of the emulator, suggestions, + questions and ideas. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 4 +[name] Florin +[desc] PS2 info dumping project +[hist] 2006-05-08 initial version + +The emulator needs some information from a Playstation2 console. +We used to require the 'bios' software. In order to get better results + more and more information was needed. So here are some guidelines + on what we need and what we don't need from the console. +Also, a new dumper and handling of these infos in the emu are in work. + +a. The so-called 'bios', is actualy rom0 found in consoles, devkits, + test-kits and PSX at address 0xBFC00000 on both EE and IOP. + [!] Note that on 75xxx the EE side bios mismatch zone fields, + so it is recomended to make a IOP side dump. +b. Rom1 and Erom contain DvdPlayer related software and are located + starting with 0xBE000000 on PS2s from 18000 and up. Over various + versions, the size of rom1 and size and position of erom changed. + They used to be dumped separately, the new dumper will simplify this, + there'll only one file containing both rom1 and erom (2M or 4M). + [!] Note that on 70xxx and 75xxx (PStwo's) the dumping of erom from EE + is not possible, the correct dump is done only from IOP! + [!] rom1 and erom are identical for same generation for all zones. + In order to be able to run the dvdplayer code in the emulator, it needs + to be pre-decrypted. EROMDRV and DVDELF will have some 'decrypt' patches. +c. NVM (Non Volatile Memory) is 1K of code and provide valuable info about + console model and region. 10000 and 15000 don't contain the model name. + PStwo's contain the zone codes making possible to have a single version + of the rom for all zones. +d. Rom2 is found only in Chinese PS2s (50009, 70009...) and contains + a font file: GB18030. It is located at 0xBE400000. It was (w/o + justification) assumed that it is as big as rom1. There is no need to + dump it on any other console than chinese. The size is to be calculated + from the filesystem (as rom0 and rom1, it has romfs). +e. BBA (BroadBand Adapter) info is not needed to be dumped. At least not + for the emulator itself, maybe for the DEV9 plugin. Anyway, it's just + a MAC address that can be made up. +f. The current dumper is reading CDVD Mecha version. This will be replaced + by a more complete information file that will contain the following info: + from [EE] + CPU revision - revision code from COP0->PRId register + easier read from (u16)GetCop0(15) + high byte is 0x2E for EE + low byte is: high nibble major, low nibble minor of revision + FPU revision - revision code from COP1->control register 0 + same description as for cpu PRId + VUs revision - hum, i'm not aware of any revision for them :( + VUs memory - local and micro memory sizes are not detected + GS revision - upper halfword in CSR register + high byte is ID = 0x55 + low bytes is major.minor (per nibbles) + GS mem - is 4M + IPU revision - hum, i'm not aware of any revision for IPU :( + Caches - instruction and data cache sizes are read from + COP0->Config register + easier read from GetCop0(16). + MEM - total RAM available + easier read with Syscall +127 - GetMemorySize() + the values are: 32M for console and test-kits, + 128M for devkits and 64M for PSX + the size is not roughly detected. As devkits have multiple + boot modes (128M or 64M). + from [IOP] + CPU revision - revision code from COP0->PRId register + high byte seems to be 0 + low byte is major.minor (per nibbles) + initial japs have major=1, + most of the consoles have major=2, + 75xxx have a new IOP processor with major=3 + Caches - are known to be 4K-I$; 1K-D$ + 0xFFFE0130 is CACHE_CONFIG register... + MEM - total RAM available + easier to read with QueryMemSize() + the values are: 2M for consoles and test-kits, + 8M for devkits and PSX + again, the size is incorrectly read :) + SPU mem - 2M (any method of detection?) + CDVD mecha - version of CDVD controller + Scmd 0x03 with subcode 0x00 (outsize=4) + the first byte is the MG-encryption code + second is major, third is minor, fourth is [2b completed] + meka - i don't know; not supported on early consoles + Scmd 0x03 with subcode 0x90 (outsize=1+1) + DEV9 revision- type of DEV9 device: 0x2x for PCMCIA, 0x3x for EXPBAY + *(vu16*)BF80146E + USB OHCI rev - Hc_revision of the OHCI controller + *(vu32*)0xBF801600 + ILINK rev/id - I'm not sure of this one, on ps2's that don't have + firewire anymore, the value is 0xFF; on 10000 is random + *(vu32*)0xBF808480 and *(vu32*)0xBF808500 (looks like mirror) + +g. The dumper will sign the dumped content, so John Doe cannot play easily + with the bios data ;) The emu works correctly with good data/food. + +h. I'm thinking of a method to check for modified content (dumps made with a + chipped console). Probably, it will be done in the emu and presented as a + warrning. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 3 +[name] auMatt +[desc] PS2 NVM Data not 100% +[hist] 2006-05-07 initial version + + v0-v8 v9- Bits Bytes +͹ +͹ +PS1 Disc Spd 0x300 0x2c0 +PS1 Texture 0x300 0x2c0 +Video Output 0x300 0x2c0 +SPDIF 0x310 0x2c0 0 +A/R 0x310 0x2c0 1 & 2 +Language 0x311 0x2c1 All +TimeZone 0x312 0x2c2 +Summer Time 0x312 0x2c2 3 +Time Format 0x312 0x2c2 5 +DateNotation 0x312 0x2c2 6 & 7 +TimeZone 0x313 0x2c3 All +TimeZone 0x315 0x2c5 All +Model Number 0x1a0 0x1b0 16 +Console ID 0x1c8 0x1f0 8 +ILink ID 0x1c0 0x1e0 8 +Date Stamp 0x180 16 +Date Stamp 0x1e0 16 +Date Stamp 0x1f0 16 +Rem. Control 0x2c4 5 +Checksum 0x31f 0x2cf All + +Checksum is calculated by the previous 15 bytes added together, then ANDed with 0xFF +Serial Number of Console can be obtained from bytes 7,6 & 5 of the Console ID in dec. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 2 +[name] Florin +[desc] PS2 bios versioning +[hist] 2006-04-30 initial version + +MG zone - the MagicGate decryption zone. You can find the code as one of the bits + in the byte at offset +1C in MagicGate encrypted files +PS1 drv - the letter for PS1VERx files in PStwo rom0 +ROMVER - has the following format VVvvZTYYYYMMDD in 14 bytes + VV, vv are the version of the bios in BCD + Z is zone code, see below + T is type of the console: C - consumer console, D - devkit/test console + YYYYMMDD is date of the bios + - BxDATA-SYSTEM, BxEXEC-SYSTEM, BxEXEC-DVDPLAYER uses Z code in place of 'x' + I: default, Japan; A: Usa, Asia; E: Europe, Oceania, Russia; C: China +VERSTR - the code from that file in rom0 +OSDVER - VVvvZlng is the format of the file for scph5xxxx. in PStwo the last 4 letters + are read from NVM, offset +180 7 chars (ROMVER:1|OSDVER:4|VERSTR:1|DVDID:1) +mecha - version read from CDVD SCmd 0x03:0x00 + +The following table is far from complete... + + Japan USA AusNz UK EuropeKorea HK TaiwanRussiaChina Mexic +͹ +͹ +MG zone 0/J 1/U 3/O 2/E 2/E 4/A 4/A 4/A 5/R 6/C 7/M +PS1 drv J A E E E H H H E C A +ROMVER 0 J 1 A 2 E 2 E 2 E 1 H 1 H 1 H 2 E 3 C 1 A +VERSTR J A E E E J J J E J A +OSDVER 0 Jjpn1 Aeng2 Eeng2 Eeng2 Eeng5 Kkor6 Htch6 Htch4 Rrus3 Csch Aspa? +Ķ +v0 scph10000 Ķ + mecha0.12.0Ķ + ver0100JCĶ + date000117Ķ + scph15000 Ķ + mecha0.18.0Ķ + ver0101JCĶ + date000217Ķ + scph18000 Ķ + mecha0.22.0Ķ + ver0120JCĶ + date001027Ķ +͹ +v1 scph30000 30001 Ķ +v2 30000 30001 Ķ +v3 30000 30001 30002 30003 30004 Ķ +͹ +v4 scph30000 30001 30002 30003 30004 Ķ + mecha Ķ + ver 0120EC Ķ + date 000902 Ķ + 35000 35001 35002 35003 35004 35005 Ķ +͹ +v5 30000 30001 30002 30003 30004 30005 Ķ + scph30000R30001R30002R30003R30004R30005R30006R30007RĶ + mecha0.32.0 2.32.0 Ķ + ver0160JC 0160EC0160EC Ķ + date011004 011004011004 Ķ +v6 Ķ +͹ +v7 scph37000 Ķ + 39000 39001 39002 39003 39004 39005 39006 39007 39008 Ķ + mecha 1.36.0 Ķ + ver 0160AC Ķ + date 020207 Ķ + Ĵ39001NĴ39010N +Ķ +v8 scph39000 Ĵ39006 Ķ + mecha0.38.0 + ver0160JC + date020426 +͹ +v9 scph50000 50001 50002 50003 50004 50005N50006 50007 50008 50009 Ķ + Ĵ50001NĴ50010N + 55000 Ĵ55005N55006 55007 Ķ +Ķ +v10 scph 50001 50002 50003 50004 50006 50007 50009 50010 + mecha 4.54.04.??.0 6.??.0 + ver 0190EC 0190HC0190HC 0190CC + date 030623 030623030623 030623 +v11 50004 Mexic USA +ͻ +v12 scph70000 Ĵ70002 70003 70004 70005 70006 70007 70008 70009 Ĵ70011 70012 + mecha Ĵ3.62.02.62.02.??.0 4.64.0 5.??.0 Ĵ 1.60.0 + ver0200JCĴ0200EC0200EC0200EC 0200HC 0200EC Ĵ 0200AC + date040614Ĵ040614040614040614 040614 040614 Ĵ 040614 +v13 scph 70001 70002 70003 70004 ͼ +͹ +v14 scph75000 75001 75002 75003 75004 75005 75006 75007 75008 Ĵ75010 + mecha 1.66.03.66.0 Ĵ + ver 0220AC0220EC Ĵ + date 050620050620 Ĵ +Ľ + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 1 +[name] Florin +[desc] CVS management rules +[hist] 2006-04-30 initial version + +Please do not commit on CVS temporary files or those made by development tools + (IDEs). Eg: *.suo/aps/opt/plg/ncb/exp +Keep it clean and before commiting a new module see the previous structure and + naming rules. If unsure about how to do any opperation please ASK. please ASK! +There's no rush ;) +Also, I'm considering switching to SVN, as CVS seems to be *abandoned* by + sourceforge.net +Any change to sources has to be commited to the public CVS. The risk of + stealing is faced by any open-source developer - the difference is the + quality! The original will always stand up ;) +Try not to break the source by your patches. Although linux and 64-bit versions + are not maintained atm, your changes should be done with all versions in mind. +Happy coding :) diff --git a/branches/pcsx2_0.9.2/Docs/efpchangesv0.9linux.txt b/branches/pcsx2_0.9.2/Docs/efpchangesv0.9linux.txt new file mode 100644 index 0000000..f32471b --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/efpchangesv0.9linux.txt @@ -0,0 +1,112 @@ +Changes made to make v0.9 work in Linux: + +Common.h - PCSX2_MULTICORE undefined. + In my version of linux, spinlocks are bleeding edge calls, and not +implemented as standard. There may be a #define that can be used, but +as it would likely include either a kernel rebuild or thread library, +I hadn't bothered. + +Misc.c - SYNC_LOGGING undefined + I suspect because of PCSX2_MULTICORE being undefined, "g_mtxLog" +didn't get defined either. + +Interpreter.c - all "_controlfp" calls commented out. + I suspect a .h file is missing for the above call. + +Vif.c - Control of MMX, SSE, SSE2 (and SSE3) instructions. + Presence of the above CPU intrinsic calls can be detected using +__MMX__, __SSE__, __SSE2__, and __SSE3__. Header dependancies are +as follows: + __MMX__ can stand alone. + __SSE__ needs __MMX__. + __SSE2__ needs __SSE__ (which needs __MMX__) + __SSE3__ needs __SSE2__ and __SSE__ (which needs __MMX__) + Each of these flags can be used to load their own set of functions +as well as loading all functions in the dependant headers... + __MMX__ - #include + __SSE__ - #include + __SSE2__ - #include + __SSE3__ - #include + Since no tests for the above flags were conducted before loading +emmintrin.h, I blocked out that section of code with an "#if 0" line. + +IPU/IPU.c - After finding out that a dozen mutexes were set here without + PCSX2_MULTICORE blocking, I went back to Common.h and turned back on +PCSX2_MULTICORE. I knew now I would have to hunt down all instances of +spinlocks and replace them with straight mutexes. + R5900.h lines 150-167 - Spinlock defines commented out. + R5900.c lines 32-38 - Spinlock define commented out. + +IPU/IPU.c - invalid initializer - NULL on pthread_mutex_t / pthread_cond_t + Separated the variables initialized. Hunted up valid initializers in +pthread documentation in Linux. + __declspec() - In Common.h, I told Linux to ignore all references to this +function. #pragma pack(16) and/or __attribute__ ((?)) might be a better +choice for this. A couple of compiler flags also control byte alignment. +For dynamically allocatable blocks, memalign() might work. + Note: for 64 bit compiles (like athlon64), 16 byte alignment is assumed. + EBUSY undeclared - This relates to the define DESTROY_MUTEX in Common.h. +Included in Common.h so EBUSY is defined. + __forceinline - placed "#define __forceinline inline" in Common.h as Linux +has no equivlent (that I know of) to this. + +IPU/Idct.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +IPU/Mpeg.o - no target + Moved to IPU/mpeg2lib. Adjusted Makefile to find it. + +VifDma.c - See Vif.c for complaints about __SSE__ detection. + +Linux/Config.c - no member "PadHack" + Seems it was removed from the "Config" structure. Commented out the +set/get commands for it. + +x86/iVU0micro.c line 494 - too many arguments in 'vurecAnalyzeBlock' + This might be leftover code from a testrun. I removed the extra 'old' +variables. + +x86/iVU1micro.c - all "_controlfp" commands commented out. + See Interpreter.c above for details. + +Then I finally got to the Link portion of the compiler... + +Hw.o: + _aligned_malloc() is not defined in Linux. memalign() was obsoleted. +POSIX now recommends posix_memalign(boundary, size) from +for accurate boundary allocation... and working free() calls. + _aligned_free(), companion to the call above, is also not defined in +Linux. Fortunately, posix_memalign() only needs a free() call. + Both of the above was defined in Common.h + +IPU/IPU.o: + couldn't find pthread_... calls. Added -lpthread to $(LIBS) in Makefile + +FPU.o: + Certain math calls were added from . FPU2.cpp compiles those +calls... and adds a C interface to get to them. Included FPU2.o in the +object list in the Makefile. + +R5900.o: + pthread_mutex__unlock()? I thought it was just 1 underline there. Didn't +take any chances, though. Put in a define in Common.h to change it to +pthread_mutex_unlock(). + +Left to fix: + +x86/iVUmicro.o: + __assume(0): I don't know what this is used for. + +R5900.o: + InterlockedAnd(), InterlockedExchange(): Are these grouped mutex calls? + +VifDma.o: + SetNewMask(), g_vif1Masks(), g_vif0Masks(): + These were sliced off when I cut SSE off. Some work could bring them +back in, if they're needed for non-MMX/SSE/SSE2/SSE3 refrencing... + + +This doesn't even guarentee that once just these problems are fixed, the +compiled program will run. I only looked at compiling/linking. + +efp - Feb 16, 2006 diff --git a/branches/pcsx2_0.9.2/Docs/pcsx2_faq.txt b/branches/pcsx2_0.9.2/Docs/pcsx2_faq.txt new file mode 100644 index 0000000..4b8cdb8 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/pcsx2_faq.txt @@ -0,0 +1,229 @@ + + PPPP CCCC SSS X X 2222 + P P C C S S X X 2 2 + P P C S X X 2 + P P C S X X 2 + P P C S X X 2 + P P C SSS X 2 + PPPP C S X X 2 + P C S X X 2 + P C S X X 2 + P C C S S X X 2 + P CCCC SSS X X 2222222 + +**************** +*PCSX2 FAQ v0.1* +**************** + +This FAQ has been written for PCSX2 v0.6 + +FAQ Written by: CKemu & shadow +_________________________________________________________ + +Q: What is PCSX2? + +A: PCSX2 is a WIP PS2 (PlayStation 2) emulator, written by +linuzappz, shadow, florin. basara, asadr, goldfinger. PCSX2 is +constantly WIP (work in progress), and is in the early +stages of development (so don't expect much yet ;) ). + +Q: Why doesn't XYZ game work? + +A: PCSX2 is able to get many games to show 'screens'. Some of the games can reach ingame +and less more can be consider playable. Speed is too slow on many of them so 'viewable' is +a beter way to describe it :) + + +Q: Why don't these games work? + +A: PCSX2 is in the early stages of development. It can run some games (many of them without glitches) +but the speed issue prevent us of making the emu more compatible. + +Q: Where abouts do I find these demos? + +A:You can find some demos at http://pcsx2.ngemu.com or +http://ps2dev.livemedia.com.au. There are proberbly more +sites with PS2 homebrew demos. + +Q: Does PCSX2 require a 'real' PS2 BIOS. + +A: PCSX2 can use a 'real' BIOS, and is preferable to HLE +BIOS as it is more compatible. But HLE does work well +with many homebrew demos. + +Q: Why not use HLE? + +A: HLE is a difficult thing to do for a PS2. Game +developers use their own modules for each game. That +would mean we would have to HLE each module. This would +be a massive task, and not a good idea, as emulating +the real BIOS will mean compatibility with all released +games. + +Q: Where do I get a BIOS? + +A: You can dump the BIOS from your own PS2, DO NOT ask us +or anyone else for a BIOS, the BIOS is copyright of SONY +and is illegal to download, so we won't help you with +that. + +Q: I try to run a game, or the BIOS, but nothing happens! + +A: If no BIOS screen shows from attempting to run a +CD/DVD, your BIOS maybe incorrect. Go to +'config>configure', and under the BIOS menu, check that +firstly you haven't got the HLE BIOS selected, if you do +change to a 'real' BIOS. If you have a 'real' BIOS +selected and it still doesn't work, check that NO +percentage is written next to the BIOS, if it is for +instance "40%", your BIOS is to small (by 60%), or +corrupt (by 60%), you may need to redump it. Also if no +'real' BIOS is listed, check its not compressed 'eg +*.zip / *.rar' and extract it to the BIOS dir (note +sub-folders NOT supported, it must be in /BIOS/). + +If that is not the case, your BIOS isn't an actual PS2 +BIOS. To ensure that doesn't happen, dump your own ;) + +Q: I see lots of glitches with games/demos, why? + +A: Incomplete emulation of the GS, Vector Units etc, this +is a WIP emulator, and will have many bugs for some time, +until more is known about the PS2 hardware. Things +generally improve with each release, so you never know, +it may be fixed in the next release. + +Q: How can I help fix these bugs? + +A: Report these bugs to us, post at the offical PCSX2 +forums at http://www.ngemu.com. Make a post describing +the bug/glitch, perhaps with a screenshot showing it, +and details on your system setup, what plugins your +using etc. + +If you find any other bugs, with regards to the debugger, +plugins, or differences between what you see in the +emulator and a real PS2, feel free to email us. + +Q: How can I help develop for PCSX2? + +A: You can find the open-source plugins at +http://pcsx2.ngemu.com , coding a GS plugin or and SPU2 +plugin would help us greatly. Also if you have any +technical information on the PS2, please email us, +anyhelp is greatly appreciated. + +Q: Your emulator sucks!! I don't want to use it! + +A: Then don't, buy a real PS2. If you don't like it, +just don't and there is no need to tell us you don't +like it, the PCSX2 team put alot of hardwork into this +emulator, and don't care to know. + +Q: Can you give me some more 'technical' answers? + +A: A technical FAQ would be massive, and take months to +write. Instead email shadow / linuz with your questions. + +Q: When is the next release? + +A: The next release will happen when there is something +to show, internal changes, and technical changes don't +mean anything to the user, if they don't see something. +Pestering us will make no difference :P + +Q: GSsoft is s..l..o..w!! + +A: Then use one of the OpenGL plugins found at our site +http://pcsx2.ngemu.com or the GStaris plugin +( http://gstaris.ngemu.com ). + +Q: The emulator even with GStaris / GSmax is slow! Why? + +A: First of all, the PS2 is a powerfull piece of +hardware, and will require a powerfull machine to achive +NEAR correct speeds, + +Given that PCSX2 does not run any 'complex' commercial +games, it is hard to judge the system requirements that +will be eventually needed. Plugins and Emulator will get +faster as new releases are made, but you can improve +preformance by turning OFF "Enable Console Output" and +"Enable Interpreter CPU" under 'config>CPU>' in the menu. + +Q: Do I need a DVD drive? + +A: Yes, if you want to read a DVDrom you will need a DVD + drive, many PS2 games are written to CDrom, so its not +essential, unless you have a DVD based game you wish to +try. + +You can also use 'Linuz's CDVD ISO' plugin to run PS2 +games in ISO / BIN format from your HDD. Note only +NTFS Format drives (eg not FAT32) can store greater than +4GB in a single file. + +Q: I hear no sound! + +A: SPU2 Plugins are being worked on by a few coders, but +as of now the only SPU2 plugin is nullSPU, which outputs +no sound, If you are a coder, and feel you can help with +SPU2, please email us. + +Q: Where can I get help!!! + +A: You can get help from the people over at +http://www.ngemu.com or on IRC. Using an IRC client, log +onto #PCSX2 or #NGEMU (EFnet). You can politly ask for +help there (No BIOS / ROM / ISO requests, or you shall be +banned). If you cannot get help there, email the PCSX2 +team. + +_________________________________________________________ + +This FAQ was based on shadow's original FAQ, so thanks to +him. This was written to clear up some of the basic +questions you may have, and I hope it was of help. + +Written with very little sleep and too much coffee, so +please excuse the mistakes, they will be fixed shortly :D + +************ +*Thanks to:* +************ + +The PCSX2 team for making me a betatester, and providing us +with a fantastic PS2 emulator, and the opportinity for me to +work on SPU2 (highly WIP :P ) + +shadow, Linuzappz, Absolute0, [Tyranid], F|res, Roor, +Goldfinger, Florin, basara, asadr, CpUmaster, snake785, +mike9010, bositman, DWatcher, Keith, Martin64.....and many +more I am sure :D + +My lady, Lucy. Without her I would be lost. + +Coffee, where would we be without coffee :D + +********** +*Contact:* +********** + +If you think I should add something to this FAQ, or you +spotted a bug, you can contact me (CKemu) via IRC in +the #PCSX2 (EFnet) channel. + +You can contact the authors via: +http://pcsx2.ngemu.com (homepage) +http://www.pcsx2.net (homepage) +http://www.ngemu.com (offical forums) + +or on IRC: + +#PCSX2 (EFnet) + +Enjoy PCSX2!! + +Best Regards CKemu ( http://www.ckemu.com ). + +/EOF/ \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/Docs/specs.tex b/branches/pcsx2_0.9.2/Docs/specs.tex new file mode 100644 index 0000000..aca2581 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/specs.tex @@ -0,0 +1,159 @@ +\documentclass[10pt]{article} + +\begin{document} +\section{...stuff...} +-order the plugins are started\\ +-platform dependent stuff, calling convention\\ + +\section{Generic functions} +The following three functions will be present in all the plugin libraries, + in order to be recognized as valid PS2E plugins. They will help + the emulator to find a plugin capabilities. + +\subsection{PS2EgetLibType} +\begin{quote}\texttt{unsigned int} PS2EgetLibType(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibType] returns the type of the plugin. + In fact it indicates the APIs supported by the dynamic library. + The returned value can be one of: +\begin{itemize} +\item PS2E\_LT\_GS 0x01 +\item PS2E\_LT\_PAD 0x02 +\item PS2E\_LT\_SPU2 0x04 +\item PS2E\_LT\_CDVD 0x08 +\item PS2E\_LT\_DEV9 0x10 +\end{itemize} +Currently, these are the only plugin types supported. Note that the values + can be ORed. +\end{description} + + + +\subsection{PS2EgetLibVersion2} +\begin{quote}\texttt{unsigned int} PS2EgetLibVersion2(\texttt{unsigned int} + type);\end{quote} + +\begin{description} +\item[PS2EgetLibVersion2] returns a combination of version numbers. +Parameter \emph{type} is used to select the functions set for which + the emulator requests version information. See \texttt{PS2EgetLibType} + for the values of this parameter. + +The 5 APIs and their corresponding specs have changed over time. + In order to prevent crashes and incompatibilities, a spec version have + been introduced as the highest 16 bits of the returned value. +\begin{itemize} +\item PS2E\_GS\_VERSION 0x0002 +\item PS2E\_PAD\_VERSION 0x0002 +\item PS2E\_SPU2\_VERSION 0x0002 +\item PS2E\_CDVD\_VERSION 0x0003 +\item PS2E\_DEV9\_VERSION 0x0001 +\end{itemize} +Notice that when the specs do change \texttt{and} the compatibility is broken, + this version number is increased. The emulator loading code will support + only one version for a certain library type at a time. If the internal + version and plugin API version does not match, the plugin + will not be loaded nor used. + +The low half of the returned value reflects the version of the plugin itself. + A major.minor versioning scheme is used on the two bytes like this: +\begin{verbatim} +...//code +return (PS2E_CDVD_VERSION<<16) | (0<<8) | (67); //version 0.67 +\end{verbatim} +\end{description} + + + +\subsection{PS2EgetLibName} +\begin{quote}\texttt{char*} PS2EgetLibName(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibName] returns a string that contains a short\footnote{ +less then 30 chars in one line} name. The string is stored + in the plugin and will be used to represent the plugin in a config dialog. +\end{description} + + + + + +\section{CDVD functions} +This section describes the functions that corresponds to CDVD\footnote{short for CD/DVD} +API - type PS2E\_LT\_CDVD(0x08). + These specs are for PS2E\_CDVD\_VERSION(0x0003). + +\subsection{CDVDinit} +\begin{quote}\texttt{int} CDVDinit(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDinit] does the initialization of the CDVD interface. + It is the first function called; so, it can be used to do all the + init stuff such as reading saved configuration, one-time hardware init and + preparing the internal structures, tables, etc\ldots + If an error is found the function will return -1, otherwise 0. +\end{description} + + + +\subsection{CDVDshutdown} +\begin{quote}\texttt{void} CDVDshutdown(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDshutdown] is called when the emulator is closed. Do now the freeing + operations. DO NOT FORGET TO FREE the resources used. The OS will probably + free the garbage left, but some pieces of hardware might need a + ``deinitialization'' procedure in order to work next time the emulator + is run. Imagine that the user will choose another plugin to run with + next time instead of yours, do not cause troubles. +\end{description} + + + +\subsection{CDVDopen} +\begin{quote}\texttt{int} CDVDopen(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDopen] is called when the emulation starts. + It is recommended that functions called from now on (until + \texttt{CDVDclose} is met) to spend few processing time. Avoid calling + blocking functions and if you do, the user should be notified visualy. + Report errors by return value and warrings using a log. + If an error is found the function will return -1 and the emulation stops, + otherwise 0. + +Do not report errors using message boxes while the emu runs, the GS plugin + might use a display mode that can cause troubles to windowing system + in showing your message. +\end{description} + + + +\subsection{CDVDclose} +\begin{quote}\texttt{void} CDVDclose(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDclose] is called when the emulation is stopped. Some of the + resources that you aquired with \texttt{CDVDstart} have to be released now + in order that other programs to use them. If you locked the CD/DVD tray, + unlock it so the user can change the disc. +\end{description} + + + +\subsection{CDVDreadTrack} +\begin{quote}\texttt{int} CDVDreadTrack(\texttt{unsigned int} + lsn, \texttt{int} mode);\end{quote} + +\begin{description} +\item[CDVDreadTrack] is the function that performs the read of \texttt{a} + sector from the CD/DVD. Parameter \emph{lsn} specifies the absolute value + of the sector number in linear addressing mode without \emph{lead-in}\footnote{i.e.\ +without leading 150 sectors == 2 seconds}. Usualy, the plugin will read + a full sector of 2352 bytes in its internal buffer. + The second parameter tells what port of ... +\end{description} + +\end{document} + diff --git a/branches/pcsx2_0.9.2/Docs/threads.txt b/branches/pcsx2_0.9.2/Docs/threads.txt new file mode 100644 index 0000000..1da8358 --- /dev/null +++ b/branches/pcsx2_0.9.2/Docs/threads.txt @@ -0,0 +1,34 @@ + OK -> done & tested +---- -> not applicable +xxxx -> dummy +32CreateThread OK ---- +33DeleteThread ---- +34StartThread ---- OK +35ExitThread ---- +36ExitDeleteThread ---- +37TerminateThread ---- +38iTerminateThread +39DisableDispatchThread xxxxxxxx +40EnableDispatchThread xxxxxxxx +41ChangeThreadPriority ---- OK +42iChangeThreadPriority OK ---- +43RotateThreadReadyQueue ---- +44iRotateThreadReadyQueue +45ReleaseWaitThread ---- +46iReleaseWaitThread +47GetThreadId OK ---- +48ReferThreadStatus ͻ OK ---- +49iReferThreadStatus ͼ OK ---- +50SleepThread ---- +51WakeupThread ---- +52iWakeupThread +53CancelWakeupThread ͻ done---- +54iCancelWakeupThread ͼ done---- +55SuspendThread ͻ +56iSuspendThread ͼ +57ResumeThread ---- +58iResumeThread +59JoinThread xxxxxxxx +60RFU060_InitializeMainThread OK ---- +61RFU061_InitializeHeapArea OK ---- +62EndOfHeap OK ---- \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/EEregs.h b/branches/pcsx2_0.9.2/EEregs.h new file mode 100644 index 0000000..a25b709 --- /dev/null +++ b/branches/pcsx2_0.9.2/EEregs.h @@ -0,0 +1,40 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EEREGS_H__ +#define __EEREGS_H__ + +#define at cpuRegs.GPR.n.at +#define k0 cpuRegs.GPR.n.k0 +#define k1 cpuRegs.GPR.n.k1 +#define v0 cpuRegs.GPR.n.v0 +#define v1 cpuRegs.GPR.n.v1 +#define a0 cpuRegs.GPR.n.a0 +#define a1 cpuRegs.GPR.n.a1 +#define a2 cpuRegs.GPR.n.a2 +#define a3 cpuRegs.GPR.n.a3 +#define t0 cpuRegs.GPR.n.t0 +#define s0 cpuRegs.GPR.n.s0 +#define gp cpuRegs.GPR.n.gp +#define fp cpuRegs.GPR.n.s8 +#define sp cpuRegs.GPR.n.sp +#define ra cpuRegs.GPR.n.ra + +#define pc0 cpuRegs.pc + +#endif /* __EEREGS_H__ */ diff --git a/branches/pcsx2_0.9.2/Elfheader.c b/branches/pcsx2_0.9.2/Elfheader.c new file mode 100644 index 0000000..5d68b4c --- /dev/null +++ b/branches/pcsx2_0.9.2/Elfheader.c @@ -0,0 +1,660 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include //2002-09-28 (Florin) +#include + +#include "Common.h" +#include "CDVDisodrv.h" + +u32 ElfCRC; + +typedef struct { + u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) + u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE + u16 e_machine; //Processor: 8=MIPS R3000 + u32 e_version; //Version: 1=current + u32 e_entry; //Entry point address + u32 e_phoff; //Start of program headers (offset from file start) + u32 e_shoff; //Start of section headers (offset from file start) + u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips + u16 e_ehsize; //ELF header size (0x34 = 52 bytes) + u16 e_phentsize; //Program headers entry size + u16 e_phnum; //Number of program headers + u16 e_shentsize; //Section headers entry size + u16 e_shnum; //Number of section headers + u16 e_shstrndx; //Section header stringtable index +} ELF_HEADER; + +typedef struct { + u32 p_type; //see notes1 + u32 p_offset; //Offset from file start to program segment. + u32 p_vaddr; //Virtual address of the segment + u32 p_paddr; //Physical address of the segment + u32 p_filesz; //Number of bytes in the file image of the segment + u32 p_memsz; //Number of bytes in the memory image of the segment + u32 p_flags; //Flags for segment + u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment +} ELF_PHR; + +/* +notes1 +------ +0=Inactive +1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 +2=Dynamic linking +3=Interpreter. The array element must specify a path name +4=Note. The array element must specify the location and size of aux. info +5=reserved +6=The array element must specify location and size of the program header table. +*/ + +typedef struct { + u32 sh_name; //No. to the index of the Section header stringtable index + u32 sh_type; //See notes2 + u32 sh_flags; //see notes3 + u32 sh_addr; //Section start address + u32 sh_offset; //Offset from start of file to section + u32 sh_size; //Size of section + u32 sh_link; //Section header table index link + u32 sh_info; //Info + u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. + u32 sh_entsize; //Fixed size entries. +} ELF_SHR; +/* +notes 2 +------- +Type: +0=Inactive +1=PROGBITS +2=SYMTAB symbol table +3=STRTAB string table +4=RELA relocation entries +5=HASH hash table +6=DYNAMIC dynamic linking information +7=NOTE +8=NOBITS +9=REL relocation entries +10=SHLIB +0x70000000=LOPROC processor specifc +0x7fffffff=HIPROC +0x80000000=LOUSER lower bound +0xffffffff=HIUSER upper bound + +notes 3 +------- +Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) +1=Write section contains data the is be writeable during execution. +2=Alloc section occupies memory during execution +4=Exec section contains executable instructions +0xf0000000=Mask bits processor-specific +*/ + +typedef struct { + u32 st_name; + u32 st_value; + u32 st_size; + u8 st_info; + u8 st_other; + u16 st_shndx; +} Elf32_Sym; + +#define ELF32_ST_TYPE(i) ((i)&0xf) + +typedef struct { + u32 r_offset; + u32 r_info; +} Elf32_Rel; + +//unfinished!!!! + +char *sections_names; + +ELF_HEADER *elfHeader; +ELF_PHR *elfProgH; +ELF_SHR *elfSectH; +char *name; +u8 *elfdata; +u32 elfsize; + +struct stat sbuf; +struct TocEntry toc; + +//2002-09-19 (Florin) +char args[256]="ez.m2v"; //to be accessed by other files +unsigned int args_ptr; //a big value; in fact, it is an address + +//in a0 is passed the address of the command line args, +//i.e. a pointer to an area like this: +//+00 unknown/unused +//+04 argc; number of arguments +//+08 argv[0]; address of the first parameter - program name (char*) - +//+08 argv[1]; address of the second parameter (char*) | +//+0C argv[2]; and so on | +//........ | +//+08+4*argc the program name(first param) <-- +//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args' +// see above 'char args[256];' +unsigned int parseCommandLine( char *filename ) +{ + if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) ) + { // 4 + 4 + 256 + char * p; + int argc, + i; + + args_ptr -= 256; + if ( args_ptr < 0 ) + { + return 0; + } + args[ 255 ] = 0; + memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 ); //params 1, 2, etc copied + memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) ); +#ifdef __WIN32__ + p = strrchr( filename, '\\' ); +#else //linux + p = strrchr( filename, '/' ); +#endif + if ( p ) + { + p++; + } + else + { + p = filename; + } + args_ptr -= strlen( p ) + 1; + if ( args_ptr < 0 ) + { + return 0; + } + strcpy( (char*)&PS2MEM_BASE[ args_ptr ], p ); //fill param 0; i.e. name of the program + + for ( i = strlen( p ) + 1 + 256, argc = 0; i > 0; i-- ) + { + while ( i && ( ( PS2MEM_BASE[ args_ptr + i ] == 0 ) || ( PS2MEM_BASE[ args_ptr + i ] == 32 ) ) ) + { + i--; + } + if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ' ) + { + PS2MEM_BASE[ args_ptr + i + 1 ] = 0; + } + while ( i && ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i] != 32 ) ) + { + i--; + } + if ( ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i ] != 32 ) ) + { //i==0 + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i; + } + else + { + if ( ( PS2MEM_BASE[ args_ptr + i + 1 ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i + 1 ] != 32 ) ) + { + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1; + } + } + } + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all + + return ( args_ptr - argc * 4 - 8 ); + } + + return 0; +} +//--------------- + +int readFile( char *Exepath, char *ptr, u32 offset, int size ) { + FILE *f; + int fi; + + if ((strnicmp( Exepath, "cdrom0:", strlen("cdrom0:")) == 0) || + (strnicmp( Exepath, "cdrom1:", strlen("cdrom0:")) == 0)) { + if ((u32)offset >= toc.fileSize) return -1; + fi = CDVDFS_open(Exepath + strlen("cdromN:"), 1);//RDONLY + if (fi < 0) return -1; + CDVDFS_lseek(fi, offset, SEEK_SET); + size = CDVDFS_read(fi, ptr, size); + CDVDFS_close(fi ); + } else { + f = fopen(Exepath, "rb"); + if (f == NULL) return -1; + if ( offset >= (u64)sbuf.st_size) return -1; + fseek(f, offset, SEEK_SET); + size = fread(ptr, 1, size, f); + fclose(f); + } + + return size; +} + +int loadHeaders( char *Exepath ) { + elfHeader = (ELF_HEADER*)elfdata; + + if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) { + SysMessage( "size of section header not standard\n" ); + } + + if((elfHeader->e_shnum * elfHeader->e_shentsize) != 0) { + elfSectH = (ELF_SHR *) malloc( elfHeader->e_shnum * elfHeader->e_shentsize ); + } else { + elfSectH = NULL; + } + + if ( ( elfHeader->e_phnum * elfHeader->e_phentsize ) != 0 ) { + elfProgH = (ELF_PHR *) malloc( elfHeader->e_phnum * elfHeader->e_phentsize ); + } else { + elfProgH = NULL; + } + +#ifdef ELF_LOG + ELF_LOG( "type: " ); +#endif + switch( elfHeader->e_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", elfHeader->e_type ); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG( "no file type" ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG( "relocatable" ); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG( "executable" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG( "\n" ); + ELF_LOG( "machine: " ); +#endif + switch ( elfHeader->e_machine ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown" ); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG( "mips_rs3000" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("version: %d\n",elfHeader->e_version); + ELF_LOG("entry: %08x\n",elfHeader->e_entry); + ELF_LOG("flags: %08x\n",elfHeader->e_flags); + ELF_LOG("eh size: %08x\n",elfHeader->e_ehsize); + ELF_LOG("ph off: %08x\n",elfHeader->e_phoff); + ELF_LOG("ph entsiz: %08x\n",elfHeader->e_phentsize); + ELF_LOG("ph num: %08x\n",elfHeader->e_phnum); + ELF_LOG("sh off: %08x\n",elfHeader->e_shoff); + ELF_LOG("sh entsiz: %08x\n",elfHeader->e_shentsize); + ELF_LOG("sh num: %08x\n",elfHeader->e_shnum); + ELF_LOG("sh strndx: %08x\n",elfHeader->e_shstrndx); + + ELF_LOG("\n"); +#endif + + return TRUE; +} + + +BOOL loadProgramHeaders( char *Exepath ) +{ + int i; + + if ( elfHeader->e_phnum == 0 ) + { + return TRUE; + } + + // is this critical, or warning? + if ( elfHeader->e_phentsize != sizeof( ELF_PHR ) ) + { + SysMessage( "size of program header not standard\n" ); + } + + elfProgH = (ELF_PHR*)&elfdata[elfHeader->e_phoff]; + + for ( i = 0 ; i < elfHeader->e_phnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Program Header\n" ); + ELF_LOG( "type: " ); +#endif + switch ( elfProgH[ i ].p_type ) { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", (int)elfProgH[ i ].p_type ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("load"); +#endif + if (elfProgH[ i ].p_offset < elfsize) { + int size; + + if ((elfProgH[ i ].p_filesz + elfProgH[ i ].p_offset) > elfsize) { + size = elfsize - elfProgH[ i ].p_offset; + } else { + size = elfProgH[ i ].p_filesz; + } + memcpy(&PS2MEM_BASE[elfProgH[ i ].p_paddr & 0x1ffffff], + &elfdata[elfProgH[ i ].p_offset], + size); +#ifdef ELF_LOG + ELF_LOG("\t*LOADED*"); +#endif + } + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset); + ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr); + ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr); + ELF_LOG("file size: %08x\n",elfProgH[i].p_filesz); + ELF_LOG("mem size: %08x\n",elfProgH[i].p_memsz); + ELF_LOG("flags: %08x\n",elfProgH[i].p_flags); + ELF_LOG("palign: %08x\n",elfProgH[i].p_align); + ELF_LOG("\n"); +#endif + } + + return TRUE; +} + + +BOOL loadSectionHeaders( char * Exepath ) +{ + int i; + int i_st = -1; + int i_dt = -1; + + if (elfHeader->e_shnum == 0 || + elfHeader->e_shoff > elfsize) { + return TRUE; + } + + elfSectH = (ELF_SHR*)&elfdata[elfHeader->e_shoff]; + + if ( elfHeader->e_shstrndx < elfHeader->e_shnum ) { + sections_names = (char *)&elfdata[elfSectH[ elfHeader->e_shstrndx ].sh_offset]; + } + + for ( i = 0 ; i < elfHeader->e_shnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ elfSectH[ i ].sh_name ] ); +#endif + if ( elfSectH[i].sh_flags & 0x2 ) { + //2002-09-19 (Florin) + args_ptr = min( args_ptr, elfSectH[ i ].sh_addr & 0x1ffffff ); + //--------------- +/* if (elfSectH[i].sh_offset < elfsize) { + int size; + + if ((elfSectH[i].sh_size + elfSectH[i].sh_offset) > elfsize) { + size = elfsize - elfSectH[i].sh_offset; + } else { + size = elfSectH[i].sh_size; + } + memcpy(&PS2MEM_BASE[ elfSectH[ i ].sh_addr &0x1ffffff ], + &elfdata[elfSectH[i].sh_offset], + size); + } +#ifdef ELF_LOG + ELF_LOG( "\t*LOADED*" ); +#endif*/ + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("type: "); +#endif + switch ( elfSectH[ i ].sh_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG("unknown %08x",elfSectH[i].sh_type); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG("null"); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("progbits"); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG("symtab"); +#endif + break; + + case 0x3: +#ifdef ELF_LOG + ELF_LOG("strtab"); +#endif + break; + + case 0x4: +#ifdef ELF_LOG + ELF_LOG("rela"); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG("no bits"); +#endif + break; + + case 0x9: +#ifdef ELF_LOG + ELF_LOG("rel"); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("flags: %08x\n", elfSectH[i].sh_flags); + ELF_LOG("addr: %08x\n", elfSectH[i].sh_addr); + ELF_LOG("offset: %08x\n", elfSectH[i].sh_offset); + ELF_LOG("size: %08x\n", elfSectH[i].sh_size); + ELF_LOG("link: %08x\n", elfSectH[i].sh_link); + ELF_LOG("info: %08x\n", elfSectH[i].sh_info); + ELF_LOG("addralign: %08x\n", elfSectH[i].sh_addralign); + ELF_LOG("entsize: %08x\n", elfSectH[i].sh_entsize); +#endif + // dump symbol table + + if ( elfSectH[ i ].sh_type == 0x02 ) + { + i_st = i; + i_dt = elfSectH[i].sh_link; + } + } + + if ( ( i_st >= 0 ) && ( i_dt >= 0 ) ) + { + char * SymNames; + Elf32_Sym * eS; + + SymNames = (char*)&elfdata[elfSectH[ i_dt ].sh_offset]; + eS = (Elf32_Sym*)&elfdata[elfSectH[ i_st ].sh_offset]; + SysPrintf("found %d symbols\n", elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym )); + + for ( i = 1; i < (int)( elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym ) ); i++ ) { + if ( ( eS[ i ].st_value != 0 ) && ( ELF32_ST_TYPE( eS[ i ].st_info ) == 2 ) ) { +// SysPrintf("%x:%s\n", eS[i].st_value, &SymNames[eS[i].st_name]); + disR5900AddSym( eS[i].st_value, &SymNames[ eS[ i ].st_name ] ); +/* if (!strcmp(&SymNames[eS[i].st_name], "sceSifCheckStatRpc")) { + psMu32(eS[i].st_value & 0x1ffffff) = (0x3b << 26) | 1; + SysPrintf("found sceSifCheckStatRpc!!\n"); + }*/ + } + } + } + + return TRUE; +} + +extern int LoadPatch(char *patchfile); +extern void LoadGameSpecificSettings(); + +int loadElfFile(char *filename) { + char str[256]; + char str2[256]; + u32 crc; + u32 i; + + SysPrintf("loadElfFile: %s\n", filename); + if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) && + strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) { + if ( stat( filename, &sbuf ) != 0 ) + return -1; + elfsize = sbuf.st_size; + } else { + CDVDFS_init( ); + if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 ) + return -1; + elfsize = toc.fileSize; + } + + SysPrintf("loadElfFile: %d\n", elfsize); + elfdata = (u8*)malloc(elfsize); + if (elfdata == NULL) return -1; + readFile(filename, (char*)elfdata, 0, elfsize); + +/* { + FILE *f = fopen("game.elf", "wb"); + fwrite(elfdata, 1, elfsize, f); + fclose(f); + }*/ + + //2002-09-19 (Florin) + args_ptr = 0xFFFFFFFF; //big value, searching for minimum + //------------------- + loadHeaders( filename ); + cpuRegs.pc = elfHeader->e_entry; //set pc to proper place + loadProgramHeaders( filename ); + loadSectionHeaders( filename ); + +#ifdef ELF_LOG + ELF_LOG( "PC set to: %8.8lx\n", cpuRegs.pc ); +#endif + cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; + cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok + + //2002-09-19 (Florin) + cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); + //--------------- + + for ( i = 0; i < 0x100000; i++ ) { + if ( strcmp( "rom0:OSDSYS", (char*)PSM( i ) ) == 0 ) { + strcpy( (char*)PSM( i ), filename ); + SysPrintf( "addr %x \"%s\" -> \"%s\"\n", i, "rom0:OSDSYS", filename ); + } + } + + //CRC + for (i=0, crc=0; i +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +// Helper Macros +//**************************************************************** +#define _Ft_ ( ( cpuRegs.code >> 16 ) & 0x1F ) +#define _Fs_ ( ( cpuRegs.code >> 11 ) & 0x1F ) +#define _Fd_ ( ( cpuRegs.code >> 6 ) & 0x1F ) + +#define _FtValf_ fpuRegs.fpr[ _Ft_ ].f +#define _FsValf_ fpuRegs.fpr[ _Fs_ ].f +#define _FdValf_ fpuRegs.fpr[ _Fd_ ].f +#define _FAValf_ fpuRegs.ACC.f + +#define _ContVal_ fpuRegs.fprc[ 31 ] + +// Testing +#define _FtValUl_ fpuRegs.fpr[ _Ft_ ].UL +#define _FsValUl_ fpuRegs.fpr[ _Fs_ ].UL +#define _FdValUl_ fpuRegs.fpr[ _Fd_ ].UL +#define _FAValUl_ fpuRegs.ACC.UL + +//**************************************************************** + +void COP1() { +#ifdef FPU_LOG + FPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP1PrintTable[_Rs_](); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + + + +void LWC1() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);// ((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memRead32(addr, &fpuRegs.fpr[_Rt_].UL); +} + +void SWC1() { + s32 addr; + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);//((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memWrite32(addr, fpuRegs.fpr[_Rt_].UL); +} + +void COP1_BC1() { + Int_COP1BC1PrintTable[_Rt_](); +} + +void COP1_S() { + Int_COP1SPrintTable[_Funct_](); +} + +void COP1_W() { + Int_COP1WPrintTable[_Funct_](); +} + +void COP1_Unknown() { +#ifdef FPU_LOG + FPU_LOG("Unknown FPU opcode called\n"); +#endif +} + + + +void MFC1() { + if ( !_Rt_ ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)_FsValUl_; +} + +void CFC1() { + if ( !_Rt_ || ( _Fs_ != 0 && _Fs_ != 31 ) ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)fpuRegs.fprc[_Fs_]; +} + +void MTC1() { + _FsValUl_ = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +void CTC1() { + if(_Fs_!=31) return; + fpuRegs.fprc[_Fs_] = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +#define C_cond_S(cond) \ + _ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \ + ( _ContVal_ | 0x00800000 ) : \ + ( _ContVal_ & ~0x00800000 ); + +void C_F() { _ContVal_ &= ~0x00800000;} //clears C regardless +void C_EQ() { C_cond_S(==); } +void C_LT() { C_cond_S(<); } +void C_LE() { C_cond_S(<=); } + +#define BC1(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } +void BC1F() { BC1(==); } +void BC1T() { BC1(!=); } + +#define BC1L(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } else cpuRegs.pc += 4; +void BC1FL() { BC1L(==); } // Equal to 0 +void BC1TL() { BC1L(!=); } // different from 0 + + +void ADD_S() { _FdValf_ = _FsValf_ + _FtValf_; } +void SUB_S() { _FdValf_ = _FsValf_ - _FtValf_; } +void MUL_S() { _FdValf_ = _FsValf_ * _FtValf_; } +void MOV_S() { _FdValf_ = _FsValf_; } +void NEG_S() { _FdValf_ = -_FsValf_; } +void ADDA_S() { _FAValf_ = _FsValf_ + _FtValf_; } +void SUBA_S() { _FAValf_ = _FsValf_ - _FtValf_; } +void MULA_S() { _FAValf_ = _FsValf_ * _FtValf_; } +void MADD_S() { _FdValf_ = _FAValf_ + ( _FsValf_ * _FtValf_ ); } +void MSUB_S() { _FdValf_ = _FAValf_ - ( _FsValf_ * _FtValf_ ); } +void MADDA_S() { _FAValf_ += _FsValf_ * _FtValf_; } +void MSUBA_S() { _FAValf_ -= _FsValf_ * _FtValf_; } +void ABS_S() { _FdValf_ = fpufabsf(_FsValf_); } +void MAX_S() { _FdValf_ = max( _FsValf_, _FtValf_ ); } +void MIN_S() { _FdValf_ = min( _FsValf_, _FtValf_ ); } +void DIV_S() { if ( _FtValf_ ) { _FdValf_ = _FsValf_ / _FtValf_; } } +void SQRT_S() { + //if ( _FtValf_ >= 0.0f ) { _FdValf_ = fpusqrtf( _FtValf_ ); } + //else { + _FdValf_ = fpusqrtf(fpufabsf(_FtValf_)); + //} +} +void CVT_S() { _FdValf_ = (float)(s32)_FsValUl_; } +void CVT_W() { + if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValUl_ = (s32)(float)_FsValf_; } + else if ( _FsValUl_ & 0x80000000 ) { _FdValUl_ = 0x80000000; } + else { _FdValUl_ = 0x7fffffff; } +} + +void RSQRT_S() { + if ( _FtValf_ >= 0.0f ) { + float tmp = fpusqrtf( _FtValf_ ); + if ( tmp != 0 ) { _FdValf_ = _FsValf_ / tmp; } + } +} + +//3322 2222 2222 1111 1111 1100 0000 0000 +//1098 7654 3210 9876 5432 1098 7654 3210 +//0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/branches/pcsx2_0.9.2/FPU2.cpp b/branches/pcsx2_0.9.2/FPU2.cpp new file mode 100644 index 0000000..fbda9e9 --- /dev/null +++ b/branches/pcsx2_0.9.2/FPU2.cpp @@ -0,0 +1,25 @@ +#include + +// sqrtf only defined in C++ +extern "C" { + +float (*fpusqrtf)(float fval) = 0; +float (*fpufabsf)(float fval) = 0; +float (*fpusinf)(float fval) = 0; +float (*fpucosf)(float fval) = 0; +float (*fpuexpf)(float fval) = 0; +float (*fpuatanf)(float fval) = 0; +float (*fpuatan2f)(float fvalx, float fvaly) = 0; + +void InitFPUOps() +{ + fpusqrtf = sqrtf; + fpufabsf = fabsf; + fpusinf = sinf; + fpucosf = cosf; + fpuexpf = expf; + fpuatanf = atanf; + fpuatan2f = atan2f; +} + +} diff --git a/branches/pcsx2_0.9.2/FiFo.c b/branches/pcsx2_0.9.2/FiFo.c new file mode 100644 index 0000000..139911d --- /dev/null +++ b/branches/pcsx2_0.9.2/FiFo.c @@ -0,0 +1,177 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//well that might need a recheck :P +//(shadow bug0r work :P) + +//plz, change this file according to FIFO defs in hw.h +/* u64 VIF0[0x1000]; + u64 VIF1[0x1000]; + u64 GIF[0x1000]; + u64 IPU_out_FIFO[0x160]; // 128bit + u64 IPU_in_FIFO[0x160]; // 128bit +*/ + +#include +#include +#include + +#include "Common.h" +#include "Hw.h" +#include "GS.h" + +#include + +////////////////////////////////////////////////////////////////////////// +/////////////////////////// Quick & dirty FIFO :D //////////////////////// +////////////////////////////////////////////////////////////////////////// +extern int FIFOto_write(u32* pMem, int size); +extern void FIFOfrom_readsingle(void *value); + +extern int g_nIPU0Data; +extern u8* g_pIPU0Pointer; +extern int FOreadpos; +// NOTE: cannot use XMM/MMX regs +void ReadFIFO(u32 mem, u64 *out) { + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("ReadFIFO VIF0 0x%08X\n", mem); +#endif + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else + if ((mem >= 0x10005000) && (mem < 0x10006000)) { + +#ifdef PCSX2_DEVBUILD + VIF_LOG("ReadFIFO VIF1 0x%08X\n", mem); + + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("reading from vif1 fifo when stalled\n"); + } +#endif + + if (vif1Regs->stat & 0x800000) { + if (--psHu32(D1_QWC) == 0) { + vif1Regs->stat&= ~0x1f000000; + } else { + } + } + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else if( (mem&0xfffff010) == 0x10007000) { + + if( g_nIPU0Data > 0 ) { + out[0] = *(u64*)(g_pIPU0Pointer); + out[1] = *(u64*)(g_pIPU0Pointer+8); + FOreadpos = (FOreadpos + 4) & 31; + g_nIPU0Data--; + g_pIPU0Pointer += 16; + } + return; + }else if ( (mem&0xfffff010) == 0x10007010) { + FIFOfrom_readsingle((void*)out); + return; + } + SysPrintf("ReadFIFO Unknown %x\n", mem); +} + +void ConstReadFIFO(u32 mem) +{ + // not done +} + +extern HANDLE g_hGsEvent; + +void WriteFIFO(u32 mem, u64 *value) { + int ret; + + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF0 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + vif0ch->qwc += 1; + ret = VIF0transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10005000) && (mem < 0x10006000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF1 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + if(vif1Regs->stat & VIF1_STAT_FDR) + SysPrintf("writing to fifo when fdr is set!\n"); + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("writing to vif1 fifo when stalled\n"); + } +#endif + vif1ch->qwc += 1; + ret = VIF1transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10006000) && (mem < 0x10007000)) { + u64* data; +#ifdef GIF_LOG + GIF_LOG("WriteFIFO GIF 0x%08X\n", mem); +#endif + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + + if( CHECK_MULTIGS ) { + data = (u64*)GSRingBufCopy(NULL, 16, GS_RINGTYPE_P3); + + data[0] = value[0]; + data[1] = value[1]; + GSgifTransferDummy(2, (u32*)data, 1); + GSRINGBUF_DONECOPY(data, 16); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); + } + else { + FreezeXMMRegs(1); + GSGIFTRANSFER3((u32*)value, 1); + FreezeXMMRegs(0); + } + + } else + if ((mem&0xfffff010) == 0x10007010) { +#ifdef IPU_LOG + IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n", (mem - 0x10007010)/8, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + //commiting every 16 bytes + while( FIFOto_write((void*)value, 1) == 0 ) { + SysPrintf("IPU sleeping\n"); + Sleep(1); + } + } else { + SysPrintf("WriteFIFO Unknown %x\n", mem); + } +} + +void ConstWriteFIFO(u32 mem) { +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/GS.cpp b/branches/pcsx2_0.9.2/GS.cpp new file mode 100644 index 0000000..e56c14a --- /dev/null +++ b/branches/pcsx2_0.9.2/GS.cpp @@ -0,0 +1,1989 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// rewritten by zerofrog to add multithreading/gs caching to GS and VU1 + + +#if defined(__WIN32__) +#include +#endif + +#include + +#include +#include + +using namespace std; + +extern "C" { + +#define PLUGINtypedefs // for GSgifTransfer1 + +#include "PS2Etypes.h" +#include "PS2EDefs.h" +#include "zlib.h" +#include "ElfHeader.h" +#include "Misc.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "vifdma.h" +#include "memory.h" +#include "Hw.h" + +#include "ix86/ix86.h" +#include "iR5900.h" + +#include "counters.h" +#include "GS.h" + +extern _GSinit GSinit; +extern _GSopen GSopen; +extern _GSclose GSclose; +extern _GSshutdown GSshutdown; +extern _GSvsync GSvsync; +extern _GSgifTransfer1 GSgifTransfer1; +extern _GSgifTransfer2 GSgifTransfer2; +extern _GSgifTransfer3 GSgifTransfer3; +extern _GSgifSoftReset GSgifSoftReset; +extern _GSreadFIFO GSreadFIFO; +extern _GSreadFIFO2 GSreadFIFO2; + +extern _GSkeyEvent GSkeyEvent; +extern _GSchangeSaveState GSchangeSaveState; +extern _GSmakeSnapshot GSmakeSnapshot; +extern _GSmakeSnapshot2 GSmakeSnapshot2; +extern _GSirqCallback GSirqCallback; +extern _GSprintf GSprintf; +extern _GSsetBaseMem GSsetBaseMem; +extern _GSsetGameCRC GSsetGameCRC; +extern _GSsetFrameSkip GSsetFrameSkip; +extern _GSreset GSreset; +extern _GSwriteCSR GSwriteCSR; + +// could convert to pthreads easily, just don't have the time +HANDLE g_hGsEvent = NULL, // set when path3 is ready to be processed + g_hVuGSExit = NULL; // set when thread needs to exit +HANDLE g_hGSOpen = NULL, g_hGSDone = NULL; +HANDLE g_hVuGSThread = NULL; + +int g_FFXHack=0; + +#ifdef PCSX2_DEVBUILD + +// GS Playback +int g_SaveGSStream = 0; // save GS stream; 1 - prepare, 2 - save +int g_nLeftGSFrames = 0; // when saving, number of frames left +gzFile g_fGSSave; + +// MTGS recording +FILE* g_fMTGSWrite = NULL, *g_fMTGSRead = NULL; +u32 g_MTGSDebug = 0, g_MTGSId = 0; +#endif + +u32 CSRw; +void gsWaitGS(); + +extern long pDsp; + +PCSX2_ALIGNED16(u8 g_MTGSMem[0x2000]); // mtgs has to have its own memory + +} // extern "C" + +#ifdef WIN32_VIRTUAL_MEM +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +#else +#define gif ((DMACh*)&psH[0xA000]) +#endif + +#ifdef WIN32_VIRTUAL_MEM +#define PS2GS_BASE(mem) ((PS2MEM_BASE+0x12000000)+(mem&0x13ff)) +#else +u8 g_RealGSMem[0x2000]; +#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) +#endif + +// dummy GS for processing SIGNAL, FINISH, and LABEL commands +typedef struct +{ + u32 nloop : 15; + u32 eop : 1; + u32 dummy0 : 16; + u32 dummy1 : 14; + u32 pre : 1; + u32 prim : 11; + u32 flg : 2; + u32 nreg : 4; + u32 regs[2]; + u32 curreg; +} GIFTAG; + +static GIFTAG g_path[3]; +static PCSX2_ALIGNED16(BYTE s_byRegs[3][16]); + +HANDLE g_hAllGsReady[3] = {NULL}; + +DWORD WINAPI GSThreadProc(LPVOID lpParam); + +// g_pGSRingPos == g_pGSWritePos => fifo is empty +u8* g_pGSRingPos = NULL, // cur pos ring is at + *g_pGSWritePos = NULL; // cur pos ee thread is at + +extern int g_nCounters[]; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +void gsInit() +{ + if( CHECK_MULTIGS ) { + g_hGsEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + g_hVuGSExit = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSOpen = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSDone = CreateEvent(NULL, FALSE, FALSE, NULL); + + SysPrintf("gsInit\n"); + +#ifdef _DEBUG + assert( g_fMTGSWrite == NULL && g_fMTGSRead == NULL ); + g_fMTGSWrite = fopen("mtgswrite.txt", "w"); + g_fMTGSRead = fopen("mtgsread.txt", "w"); +#endif + + g_pGSRingPos = (u8*)VirtualAlloc(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + if( g_pGSRingPos != GS_RINGBUFFERBASE ) { + MessageBox(NULL, "Cannot alloc GS ring buffer\n", "Error", MB_OK); + exit(0); + } + + memcpy(g_MTGSMem, PS2MEM_GS, sizeof(g_MTGSMem)); + + if( GSsetBaseMem != NULL ) + GSsetBaseMem(g_MTGSMem); + + InterlockedExchangePointer(&g_pGSWritePos, GS_RINGBUFFERBASE); + g_hVuGSThread = CreateThread(NULL, 0, GSThreadProc, NULL, 0, NULL); + } +} + +void gsWaitGS() +{ + while( g_pGSRingPos != g_pGSWritePos ) + Sleep(1); +} + +void gsShutdown() +{ + if( CHECK_MULTIGS ) { + + SetEvent(g_hVuGSExit); + SysPrintf("Closing gs thread\n"); + WaitForSingleObject(g_hVuGSThread, INFINITE); + CloseHandle(g_hVuGSThread); + CloseHandle(g_hGsEvent); + CloseHandle(g_hVuGSExit); + CloseHandle(g_hGSOpen); + CloseHandle(g_hGSDone); + + VirtualFree(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_DECOMMIT|MEM_RELEASE); + +#ifdef _DEBUG + if( g_fMTGSWrite != NULL ) { + fclose(g_fMTGSWrite); + g_fMTGSWrite = NULL; + } + if( g_fMTGSRead != NULL ) { + fclose(g_fMTGSRead); + g_fMTGSRead = NULL; + } +#endif + } + else GSclose(); +} + +typedef u8* PU8; + +u8* GSRingBufCopy(void* mem, u32 size, u32 type) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + assert( size < GS_RINGBUFFERSIZE ); + assert( writepos < GS_RINGBUFFEREND ); + assert( ((u32)writepos & 15) == 0 ); + assert( (size&15) == 0); + + size += 16; + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos + size > GS_RINGBUFFEREND ) { + + // skip to beginning + while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) { + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + Sleep(1); + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } + + // notify GS + if( writepos != GS_RINGBUFFEREND ) { + InterlockedExchangePointer(writepos, GS_RINGTYPE_RESTART); + } + + InterlockedExchangePointer(&g_pGSWritePos, GS_RINGBUFFERBASE); + writepos = GS_RINGBUFFERBASE; + } + + while( writepos < tempbuf && (writepos+size >= tempbuf || (writepos+size == GS_RINGBUFFEREND && tempbuf == GS_RINGBUFFERBASE)) ) { + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + Sleep(1); + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } + + // just copy + *(u32*)writepos = type|(((size-16)>>4)<<16); + return writepos+16; +} + +void GSRingBufSimplePacket(int type, int data0, int data1, int data2) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + + assert( writepos + 16 <= GS_RINGBUFFEREND ); + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos < tempbuf && writepos+16 >= tempbuf ) { + + do { + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + Sleep(1); + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } while(writepos < tempbuf && writepos+16 >= tempbuf ); + } + + *(u32*)writepos = type; + *(int*)(writepos+4) = data0; + *(int*)(writepos+8) = data1; + *(int*)(writepos+12) = data2; + + writepos += 16; + if( writepos == GS_RINGBUFFEREND ) writepos = GS_RINGBUFFERBASE; + InterlockedExchangePointer(&g_pGSWritePos, writepos); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent); +} + +void gsReset() +{ + SysPrintf("GIF reset\n"); + + // GSDX crashes + //if( GSreset ) GSreset(); + + if( CHECK_MULTIGS ) { + ResetEvent(g_hGsEvent); + ResetEvent(g_hVuGSExit); + + g_pGSRingPos = g_pGSWritePos; + } + + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void gsGIFReset() +{ + memset(g_path, 0, sizeof(g_path)); + +#ifndef WIN32_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); + if( CHECK_MULTIGS ) + memset(g_path, 0, sizeof(g_path)); + +// else +// GSreset(); + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void CSRwrite(u32 value) +{ + CSRw |= value & ~0x60; + GSwriteCSR(CSRw); + + GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f); + + if( value & 0x100 ) { // FLUSH + //SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr); + } + + if (value & 0x200) { // resetGS + //GSCSRr = 0x400E; // The host FIFO neeeds to be empty too or GSsync will fail (saqib) + //GSIMR = 0xff00; + if( GSgifSoftReset != NULL ) { + GSgifSoftReset(7); + if( CHECK_MULTIGS ) { + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + } + } + else GSreset(); + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) + //Since when!! Refraction, since 4/21/06 (zerofrog) ok ill let you off, looks like theyre all set (ref) + GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 + + // and this too (fixed megaman ac) + //CSRw = (u32)GSCSRr; + GSwriteCSR(CSRw); + } +} + +static void IMRwrite(u32 value) { + GSIMR = (value & 0x1f00)|0x6000; + + // don't update mtgs mem +} + +void gsWrite8(u32 mem, u8 value) { + switch (mem) { + case 0x12001000: // GS_CSR + CSRwrite((CSRw & ~0x000000ff) | value); break; + case 0x12001001: // GS_CSR + CSRwrite((CSRw & ~0x0000ff00) | (value << 8)); break; + case 0x12001002: // GS_CSR + CSRwrite((CSRw & ~0x00ff0000) | (value << 16)); break; + case 0x12001003: // GS_CSR + CSRwrite((CSRw & ~0xff000000) | (value << 24)); break; + default: + *PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE8, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 8 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void gsConstWrite8(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12001000: // GS_CSR + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xff<<(mem&3)*8); + AND32ItoR(ECX, ~(0xff<<(mem&3)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + default: + _eeWriteConstMem8( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + _recPushReg(mmreg); + + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE8); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + break; + } +} + +extern void UpdateVSyncRate(); + +void gsWrite16(u32 mem, u16 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + + UpdateVSyncRate(); + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + + break; + + case 0x12001000: // GS_CSR + CSRwrite( (CSRw&0xffff0000) | value); + break; + case 0x12001002: // GS_CSR + CSRwrite( (CSRw&0xffff) | ((u32)value<<16)); + break; + case 0x12001010: // GS_IMR + SysPrintf("writing to IMR 16\n"); + IMRwrite(value); + break; + + default: + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 16 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void recSetSMODE1() +{ + iFlushCall(0); + AND32ItoR(EAX, 0x6000); + CMP32ItoR(EAX, 0x6000); + j8Ptr[5] = JNE8(0); + + // PAL + OR32ItoM( (u32)&Config.PsxType, 1); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // NTSC + AND32ItoM( (u32)&Config.PsxType, ~1 ); + + x86SetJ8( j8Ptr[6] ); + CALLFunc((u32)UpdateVSyncRate); +} + +void recSetSMODE2() +{ + TEST32ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // Interlaced + OR32ItoM( (u32)&Config.PsxType, 2); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // Non-Interlaced + AND32ItoM( (u32)&Config.PsxType, ~2 ); + + x86SetJ8( j8Ptr[6] ); +} + +void gsConstWrite16(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12000010: // GS_SMODE1 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE16); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12000020: // GS_SMODE2 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE16); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12001000: // GS_CSR + + assert( !(mem&2) ); + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + + MOV32MtoR(ECX, (u32)&CSRw); + AND32ItoR(EAX, 0xffff<<(mem&2)*8); + AND32ItoR(ECX, ~(0xffff<<(mem&2)*8)); + OR32ItoR(EAX, ECX); + PUSH32R(EAX); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem16( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + _recPushReg(mmreg); + + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE16); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + } +} + +void gsWrite32(u32 mem, u32 value) +{ + assert( !(mem&3)); + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u32*)PS2GS_BASE(mem) = value; + + UpdateVSyncRate(); + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + + break; + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u32*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + break; + + case 0x12001000: // GS_CSR + CSRwrite(value); + break; + + case 0x12001010: // GS_IMR + IMRwrite(value); + break; + default: + *(u32*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 32 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +// (value&0x1f00)|0x6000 +void gsConstWriteIMR(int mmreg) +{ + const u32 mem = 0x12001010; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_M32((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_MMXTAG ) { + SetMMXstate(); + MOVDMMXtoM((u32)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((u32)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((u32)PS2GS_BASE(mem), 0x6000); + } + else if( mmreg & MEM_EECONSTTAG ) { + MOV32ItoM( (u32)PS2GS_BASE(mem), (g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x1f00)|0x6000); + } + else { + AND32ItoR(mmreg, 0x1f00); + OR32ItoR(mmreg, 0x6000); + MOV32RtoM( (u32)PS2GS_BASE(mem), mmreg ); + } + + // IMR doesn't need to be updated in MTGS mode +} + +void gsConstWrite32(u32 mem, int mmreg) { + + switch (mem) { + + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + default: + _eeWriteConstMem32( (u32)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + _recPushReg(mmreg); + + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + } +} + +void gsWrite64(u32 mem, u64 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + UpdateVSyncRate(); + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, (u32)(value>>32)); + } + + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, 0); + } + + break; + case 0x12001000: // GS_CSR + CSRwrite((u32)value); + break; + + case 0x12001010: // GS_IMR + IMRwrite((u32)value); + break; + + default: + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, (u32)(value>>32)); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 64 at %8.8lx with data %8.8lx_%8.8lx\n", mem, ((u32*)&value)[1], (u32)value); +#endif +} + +void gsConstWrite64(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem64((u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32M((u32)PS2GS_BASE(mem)+4); + PUSH32M((u32)PS2GS_BASE(mem)); + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE64); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 16); + } + + break; + } +} + +void gsConstWrite128(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) PUSH32R(EAX); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE32); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 12); + } + + break; + + case 0x12001000: // GS_CSR + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)CSRwrite); + ADD32ItoR(ESP, 4); + break; + + case 0x12001010: // GS_IMR + // (value&0x1f00)|0x6000 + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem128( (u32)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + PUSH32M((u32)PS2GS_BASE(mem)+4); + PUSH32M((u32)PS2GS_BASE(mem)); + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE64); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 16); + + PUSH32M((u32)PS2GS_BASE(mem)+12); + PUSH32M((u32)PS2GS_BASE(mem)+8); + PUSH32I(mem&0x13ff); + PUSH32I(GS_RINGTYPE_MEMWRITE64); + CALLFunc((u32)GSRingBufSimplePacket); + ADD32ItoR(ESP, 16); + } + + break; + } +} + +u8 gsRead8(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 8 %8.8lx, at %8.8lx\n", *(u8*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u8*)PS2GS_BASE(mem); +} + +int gsConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 8 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem8(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u16 gsRead16(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 16 %8.8lx, at %8.8lx\n", *(u16*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u16*)PS2GS_BASE(mem); +} + +int gsConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 16 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem16(x86reg, (u32)PS2GS_BASE(mem), sign); + return 0; +} + +u32 gsRead32(u32 mem) { + +#ifdef GIF_LOG + GIF_LOG("GS read 32 %8.8lx, at %8.8lx\n", *(u32*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + return *(u32*)PS2GS_BASE(mem); +} + +int gsConstRead32(u32 x86reg, u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 32 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem32(x86reg, (u32)PS2GS_BASE(mem)); + return 0; +} + +u64 gsRead64(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + return *(u64*)PS2GS_BASE(mem); +} + +void gsConstRead64(u32 mem, int mmreg) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PS2GS_BASE(mem)); + else { + MOVQMtoR(mmreg, (u32)PS2GS_BASE(mem)); + SetMMXstate(); + } +} + +void gsConstRead128(u32 mem, int xmmreg) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 128 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem128( xmmreg, (u32)PS2GS_BASE(mem)); +} + + +void gsIrq() { + hwIntcIrq(0); +} + +static void GSRegHandlerSIGNAL(u32* data) +{ + GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + + if (!(GSCSRr & 0x1)) { + GSCSRr |= 1; // signal + //CSRw &= ~1; + + } + if (!(GSIMR&0x100) ) + gsIrq(); + +} + +static void GSRegHandlerFINISH(u32* data) +{ + + if (!(GSCSRr & 0x2)) { + //CSRw &= ~2; + GSCSRr |= 2; // finish + + } + if (!(GSIMR&0x200) ) + gsIrq(); +} + +static void GSRegHandlerLABEL(u32* data) +{ + GSSIGLBLID->LBLID = (GSSIGLBLID->LBLID&~data[1])|(data[0]&data[1]); +} + +typedef void (*GIFRegHandler)(u32* data); +static GIFRegHandler s_GSHandlers[3] = { GSRegHandlerSIGNAL, GSRegHandlerFINISH, GSRegHandlerLABEL }; + +// simulates a GIF tag +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size) +{ + int nreg, i, nloop; + u32 curreg; + u32 tempreg; + GIFTAG* ptag = &g_path[path]; + + if( path == 0 ) { + nloop = 0; + } + else { + nloop = ptag->nloop; + curreg = ptag->curreg; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + } + + while(size > 0) + { + if(nloop == 0) { + + ptag = (GIFTAG*)pMem; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + + pMem+= 4; + size--; + + if(ptag->nloop == 0 ) { + if( path == 0 ) { + + if( ptag->eop ) + return size; + + // ffx hack + if( g_FFXHack ) + continue; + + return size; + } + + g_path[path].nloop = 0; + + // motogp graphics show + if( !ptag->eop ) + continue; + + return size; + } + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + s_byRegs[path][i] = tempreg&0xf; + } + + nloop = ptag->nloop; + curreg = 0; + } + + switch(ptag->flg) + { + case 0: // PACKED + { + for(; size > 0; size--, pMem += 4) + { + if( s_byRegs[path][curreg] == 0xe && (pMem[2]&0xff) >= 0x60 ) { + if( (pMem[2]&0xff) < 0x64 ) + s_GSHandlers[pMem[2]&0x3](pMem); + } + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 4; + break; + } + } + } + + if( nloop > 0 ) { + assert(size == 0); + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 1: // REGLIST + { + size *= 2; + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + assert( (tempreg&0xf) < 0x64 ); + s_byRegs[path][i] = tempreg&0xf; + } + + for(; size > 0; pMem+= 2, size--) + { + if( s_byRegs[path][curreg] >= 0x60 ) + s_GSHandlers[s_byRegs[path][curreg]&3](pMem); + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + + if( nloop > 0 ) { + assert(size == 0); + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 2: // GIF_IMAGE (FROM_VFRAM) + case 3: + { + // simulate + if( (int)size < nloop ) { + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop-size; + return 0; + } + else { + pMem += nloop*4; + size -= nloop; + nloop = 0; + } + break; + } + } + + if( path == 0 && ptag->eop ) { + g_path[0].nloop = 0; + return size; + } + } + + g_path[path] = *ptag; + g_path[path].curreg = curreg; + g_path[path].nloop = nloop; + return size; +} + +int gsInterrupt() { +#ifdef GIF_LOG + GIF_LOG("gsInterrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(gif->qwc > 0) { + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("gs dma masked\n"); + return 0; + } + + dmaGIF(); + return 0; + } + + gif->chcr &= ~0x100; + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 + hwDmacIrq(DMAC_GIF); + + return 1; +} + +#define WRITERING_DMA(pMem, qwc) { \ + if( CHECK_MULTIGS) { \ + u8* pgsmem = GSRingBufCopy(pMem, (qwc)<<4, GS_RINGTYPE_P3); \ + if( pgsmem != NULL ) { \ + int sizetoread = (qwc)<<4; \ + u32 pendmem = (u32)gif->madr + sizetoread; \ + /* check if page of endmem is valid (dark cloud2) */ \ + if( dmaGetAddr(pendmem-16) == NULL ) { \ + pendmem = ((pendmem-16)&~0xfff)-16; \ + while(dmaGetAddr(pendmem) == NULL) { \ + pendmem = (pendmem&~0xfff)-16; \ + } \ + memcpy_amd(pgsmem, pMem, pendmem-(u32)gif->madr+16); \ + } \ + else memcpy_amd(pgsmem, pMem, sizetoread); \ + \ + GSRINGBUF_DONECOPY(pgsmem, sizetoread); \ + GSgifTransferDummy(2, pMem, qwc); \ + } \ + \ + if( !CHECK_DUALCORE ) SetEvent(g_hGsEvent); \ + } \ + else { \ + FreezeMMXRegs(1); \ + FreezeXMMRegs(1); \ + GSGIFTRANSFER3(pMem, qwc); \ + } \ +} \ + +int _GIFchain() { + u32 qwc = gif->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) { + // reset path3, fixes dark cloud 2 + if( GSgifSoftReset != NULL ) + GSgifSoftReset(4); + if( CHECK_MULTIGS ) { + memset(&g_path[2], 0, sizeof(g_path[2])); + } + + SysPrintf("NULL GIFchain\n"); + return -1; + } + + WRITERING_DMA(pMem, qwc); + + gif->madr+= qwc*16; + gif->qwc = 0; + return (qwc)*2; +} + +#define GIFchain() \ + if (gif->qwc) { \ + cycles+= _GIFchain(); /* guessing */ \ + } + +int gscount = 0; +static int prevcycles = 0; +static u32* prevtag = NULL; + +void dmaGIF() { + u32 *ptag; + int done=0; + int cycles=prevcycles; + u32 id; + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC ) { // GIF MFIFO + gifMFIFOInterrupt(); + return; + } + if( (psHu32(GIF_CTRL) & 8) ) { + // temporarily stop + SysPrintf("Gif dma temp paused?\n"); + return; + } + +#ifdef GIF_LOG + GIF_LOG("dmaGIF chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + gif->chcr, gif->madr, gif->qwc, + gif->tadr, gif->asr0, gif->asr1); +#endif + + if (psHu32(GIF_MODE) & 0x4) { + } else + if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) { + gif->chcr &= ~0x100; + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + hwDmacIrq(2); + return; + } + + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && prevcycles != 0) { // STD == GIF + SysPrintf("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); + + if( gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) ) { + INT(2, cycles); + return; + } + prevcycles = 0; + gif->qwc = 0; + } + + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x8000; //FIFO full + psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3 + psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) + + /*if( prevcycles != 0 ) { + assert( prevtag != NULL ); + + ptag = prevtag; + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + // transfer interrupted, so continue + prevcycles = 0; + GIFchain(); + + if (gif->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + done = 1; + + } + }*/ + + // Transfer Dn_QWC from Dn_MADR to GIF + if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode + //gscount++; + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && (gif->chcr & 0xc) == 0) { + SysPrintf("DMA Stall Control on GIF normal\n"); + } + GIFchain(); + } + else { + // Chain Mode + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + break; + } + cycles+=2; // Add 1 cycles from the QW read for the tag + // Transfer dma tag if tte is set + if (gif->chcr & 0x40) { + //u32 temptag[4] = {0}; +#ifdef PCSX2_DEVBUILD + //SysPrintf("GIF TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + + //temptag[0] = ptag[2]; + //temptag[1] = ptag[3]; + //GSGIFTRANSFER3(ptag, 1); + } + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + + + + done = hwDmacSrcChainWithStack(gif, id); +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr); +#endif + if (!done && (psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) && id == 4) { + // stalled + SysPrintf("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); + prevcycles = cycles; + gif->tadr -= 16; + hwDmacIrq(13); + INT(2, cycles); + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return; + } + } + + GIFchain(); //Transfers the data set by the switch + + if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("GIF TIE\n"); + + // SysPrintf("GSdmaIrq Set\n"); + done = 1; + //gif->qwc = 0; + break; + } + } + } + + prevtag = NULL; + prevcycles = 0; + INT(2, cycles); + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +static int mfifocycles; + +int mfifoGIFrbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((gif->madr+gif->qwc*16) >= (maddr+msize)) { + int s1 = (maddr+msize) - gif->madr; + int s2 = gif->qwc*16 - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + WRITERING_DMA(src, s1&~15); + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + WRITERING_DMA(src, s2&~15); + + } else { + /* it doesn't, so just transfer 'qwc*16' words + from 'gif->madr' to GS */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + + WRITERING_DMA(src, gif->qwc); + } + + gif->madr+= gif->qwc*16; + + + return 0; +} + +int mfifoGIFchain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (gif->qwc == 0) return 0; + + if (gif->madr >= maddr && + gif->madr <= (maddr+msize)) { + if (mfifoGIFrbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) return -1; + + WRITERING_DMA(pMem, gif->qwc); + gif->madr+= gif->qwc*16; + } + + mfifocycles+= (gif->qwc) * 2; /* guessing */ + gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + gif->qwc = 0; + + return 0; +} + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) + +static int giftempqwc = 0; +static int g_gifCycles = 0; +static int gifqwc = 0; +static int gifdone = 0; + +void mfifoGIFtransfer(int qwc) { + u32 *ptag; + int id; + u32 temp = 0; + mfifocycles = 0; + gifqwc += qwc; + g_gifCycles = 0; + if(gifqwc == 0) { + //#ifdef PCSX2_DEVBUILD + /*if( gifqwc > 1 ) + SysPrintf("gif mfifo tadr==madr but qwc = %d\n", gifqwc);*/ + //#endif + //INT(11,50); + return; + } +/*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ +#ifdef GIF_LOG + GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); +#endif + + if((gif->chcr & 0x100) == 0)SysPrintf("MFIFO GIF not ready!\n"); + //while (qwc > 0 && done == 0) { + if(gif->qwc == 0){ + if(gif->tadr == spr0->madr) { + #ifdef PCSX2_DEVBUILD + /*if( gifqwc > 1 ) + SysPrintf("gif mfifo tadr==madr but qwc = %d\n", gifqwc);*/ + #endif + //hwDmacIrq(14); + return; + } + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(gif->tadr); + + id = (ptag[0] >> 28) & 0x7; + gif->qwc = (ptag[0] & 0xffff); + gif->madr = ptag[1]; + mfifocycles += 2; + + + /*if(gif->chcr & 0x40) { //Not used-doesnt work :P + ret = GIFtransfer(ptag+2, 2, 1); + assert(ret == 0 ); // gif stall code not implemented + }*/ + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + + #ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr, gifqwc, spr0->madr); + #endif + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + if(gifqwc < gif->qwc && (gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->tadr += 16; + gifdone = 1; //End Transfer + break; + + case 1: // CNT - Transfer QWC following the tag. + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->madr = gif->tadr + 16; //Set MADR to QW after Tag + gif->tadr = gif->madr + (gif->qwc << 4); //Set TADR to QW following the data + gifdone = 0; + break; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + temp = gif->madr; //Temporarily Store ADDR + gif->madr = gif->tadr + 16; //Set MADR to QW following the tag + gif->tadr = temp; //Copy temporarily stored ADDR to Tag + gifdone = 0; + break; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + if(gifqwc < gif->qwc && (gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->tadr += 16; //Set TADR to next tag + gifdone = 0; + break; + + case 7: // End - Transfer QWC following the tag + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->madr = gif->tadr + 16; //Set MADR to data following the tag + gif->tadr = gif->madr + (gif->qwc << 4); //Set TADR to QW following the data + gifdone = 1; //End Transfer + break; + } + gifqwc--; + + //SysPrintf("GIF MFIFO qwc %d gif qwc %d, madr = %x, tadr = %x\n", qwc, gif->qwc, gif->madr, gif->tadr); + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + if((gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)){ + gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + gifqwc -= gif->qwc; + } + } + + if (mfifoGIFchain() == -1) { + SysPrintf("dmaChain error %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr); + gifdone = 1; + INT(11,mfifocycles+g_gifCycles); + } + + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoGIFtransfer: dmaIrq Set\n"); + //gifqwc = 0; + gifdone = 1; + } + +// if( (cpuRegs.interrupt & (1<<1)) && qwc > 0) { +// SysPrintf("gif mfifo interrupt %d\n", qwc); +// } + //} + + /*if(gifdone == 1) { + gifqwc = 0; + }*/ + INT(11,mfifocycles+g_gifCycles); + if(gifqwc == 0 && giftempqwc > 0) hwDmacIrq(14); + + //hwDmacIrq(1); +#ifdef SPR_LOG + SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); +#endif +} + +int gifMFIFOInterrupt() +{ + mfifocycles = 0; + + if(!(gif->chcr & 0x100)) return 1; + else if(gifqwc == 0 && gifdone == 0) return 1; + + if(gifdone == 0 && gifqwc != 0) { + mfifoGIFtransfer(0); + if(gif->qwc > 0) return 1; + else return 0; + } + if(gifdone == 0 || gif->qwc > 0) { + SysPrintf("Shouldnt go here\n"); + return 1; + } + gifdone = 0; + gif->chcr &= ~0x100; + hwDmacIrq(DMAC_GIF); + + return 1; +} + +DWORD WINAPI GSThreadProc(LPVOID lpParam) +{ + HANDLE handles[2] = { g_hGsEvent, g_hVuGSExit }; + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + u8* writepos; + u32 tag; + u32 counter = 0; + + { + int ret; + HANDLE openhandles[2] = { g_hGSOpen, g_hVuGSExit }; + if( WaitForMultipleObjects(2, openhandles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + return 0; + } + ret = GSopen((void *)&pDsp, "PCSX2", 1); + GSCSRr = 0x551B400F; // 0x55190000 + SysPrintf("gsOpen done\n"); + if (ret != 0) { SysMessage ("Error Opening GS Plugin"); return (DWORD)-1; } + SetEvent(g_hGSDone); + } + + SysPrintf("Starting GS thread\n"); + + while(1) { + + if( !CHECK_DUALCORE ) { + if( WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + GSclose(); + return 0; + } + } + else if( !(counter++ & 0xffff) ) { + if( WaitForSingleObject(g_hVuGSExit, 0) == WAIT_OBJECT_0 ) { + GSclose(); + return 0; + } + } + + if( g_pGSRingPos != g_pGSWritePos ) { + + do { + writepos = *(volatile PU8*)&g_pGSWritePos; + + while( g_pGSRingPos != writepos ) { + + assert( g_pGSRingPos < GS_RINGBUFFEREND ); + // process until writepos + tag = *(u32*)g_pGSRingPos; + + switch( tag&0xffff ) { + case GS_RINGTYPE_RESTART: + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( GS_RINGBUFFERBASE == writepos ) + goto ExitGS; + + continue; + + case GS_RINGTYPE_P1: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer1((u32*)(g_pGSRingPos+16), 0); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + + case GS_RINGTYPE_P2: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer2((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_P3: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer3((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_VSYNC: + GSvsync(*(int*)(g_pGSRingPos+4)); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + + case GS_RINGTYPE_FRAMESKIP: + GSsetFrameSkip(*(int*)(g_pGSRingPos+4)); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE8: + g_MTGSMem[*(int*)(g_pGSRingPos+4)] = *(u8*)(g_pGSRingPos+8); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE16: + *(u16*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u16*)(g_pGSRingPos+8); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE32: + *(u32*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u32*)(g_pGSRingPos+8); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE64: + *(u64*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u64*)(g_pGSRingPos+8); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + + case GS_RINGTYPE_VIFFIFO: + { + u64* pMem; + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + pMem = (u64*)dmaGetAddr(vif1ch->madr); + + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + break; + } + + if( GSreadFIFO2 == NULL ) { + int size; + for (size=(tag>>16); size>0; size--) { + GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, tag>>16); + + // set incase read + psHu64(0x5000) = pMem[2*(tag>>16)-2]; + psHu64(0x5008) = pMem[2*(tag>>16)-1]; + } + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + tag = (tag>>16) - (cpuRegs.cycle- *(u32*)(g_pGSRingPos+8)); + if( tag & 0x80000000 ) tag = 0; + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + + INT(1, tag); + InterlockedExchangeAdd((PLONG)&g_pGSRingPos, 16); + break; + } + + default: + + SysPrintf("GSThreadProc, bad packet writepos: %x g_pGSRingPos: %x, g_pGSWritePos: %x\n", writepos, g_pGSRingPos, g_pGSWritePos); + assert(0); + g_pGSRingPos = g_pGSWritePos; + //flushall(); + } + + assert( g_pGSRingPos <= GS_RINGBUFFEREND ); + if( g_pGSRingPos == GS_RINGBUFFEREND ) + InterlockedExchangePointer(&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( g_pGSRingPos == g_pGSWritePos ) { + break; + } + } +ExitGS: + ; + } while(g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos); + } + + // process vu1 + } + + return 0; +} + +int gsFreeze(gzFile f, int Mode) { + + gzfreeze(PS2MEM_GS, 0x2000); + gzfreeze(&CSRw, sizeof(CSRw)); + gzfreeze(g_path, sizeof(g_path)); + gzfreeze(s_byRegs, sizeof(s_byRegs)); + + return 0; +} + +#ifdef PCSX2_DEVBUILD + +struct GSStatePacket +{ + u32 type; + vector mem; +}; + +// runs the GS +void RunGSState(gzFile f) +{ + u32 newfield; + list< GSStatePacket > packets; + + while(!gzeof(f)) { + int type, size; + gzread(f, &type, sizeof(type)); + + if( type != GSRUN_VSYNC ) gzread(f, &size, 4); + + packets.push_back(GSStatePacket()); + GSStatePacket& p = packets.back(); + + p.type = type; + + if( type != GSRUN_VSYNC ) { + p.mem.resize(size*16); + gzread(f, &p.mem[0], size*16); + } + } + + list::iterator it = packets.begin(); + g_SaveGSStream = 3; + + int skipfirst = 0; + + // first extract the data + while(1) { + + switch(it->type) { + case GSRUN_TRANS1: + GSgifTransfer1((u32*)&it->mem[0], 0); + break; + case GSRUN_TRANS2: + GSgifTransfer2((u32*)&it->mem[0], it->mem.size()/16); + break; + case GSRUN_TRANS3: + GSgifTransfer3((u32*)&it->mem[0], it->mem.size()/16); + break; + case GSRUN_VSYNC: + // flip + newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000; + *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; + + GSvsync(newfield); + SysUpdate(); + +// if( g_SaveGSStream != 3 ) +// return; +// +// if( skipfirst ) { +// ++it; +// it = packets.erase(packets.begin(), it); +// skipfirst = 0; +// } +// + it = packets.begin(); + continue; + break; + default: + assert(0); + } + + ++it; + if( it == packets.end() ) + it = packets.begin(); + } +} + +#endif + +#undef GIFchain diff --git a/branches/pcsx2_0.9.2/GS.h b/branches/pcsx2_0.9.2/GS.h new file mode 100644 index 0000000..bc4959f --- /dev/null +++ b/branches/pcsx2_0.9.2/GS.h @@ -0,0 +1,218 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +typedef struct +{ + u32 SIGID; + u32 LBLID; +} GSRegSIGBLID; + +#ifdef WIN32_VIRTUAL_MEM +#define GSCSRr *((u64*)(PS2MEM_GS+0x1000)) +#define GSIMR *((u32*)(PS2MEM_GS+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(PS2MEM_GS+0x1080)) +#else +extern u8 g_RealGSMem[0x2000]; +#define GSCSRr *((u64*)(g_RealGSMem+0x1000)) +#define GSIMR *((u32*)(g_RealGSMem+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(g_RealGSMem+0x1080)) +#endif + +#define GS_RINGBUFFERBASE (u8*)(0x10200000) +#define GS_RINGBUFFERSIZE 0x00300000 // 2Mb +#define GS_RINGBUFFEREND (u8*)(GS_RINGBUFFERBASE+GS_RINGBUFFERSIZE) + +#define GS_RINGTYPE_RESTART 0 +#define GS_RINGTYPE_P1 1 +#define GS_RINGTYPE_P2 2 +#define GS_RINGTYPE_P3 3 +#define GS_RINGTYPE_VSYNC 4 +#define GS_RINGTYPE_VIFFIFO 5 // GSreadFIFO2 +#define GS_RINGTYPE_FRAMESKIP 6 +#define GS_RINGTYPE_MEMWRITE8 7 +#define GS_RINGTYPE_MEMWRITE16 8 +#define GS_RINGTYPE_MEMWRITE32 9 +#define GS_RINGTYPE_MEMWRITE64 10 + +// if returns NULL, don't copy (memory is preserved) +u8* GSRingBufCopy(void* mem, u32 size, u32 type); +void GSRingBufSimplePacket(int type, int data0, int data1, int data2); + +extern u8* g_pGSWritePos; +#ifdef PCSX2_DEVBUILD + +// use for debugging MTGS +extern FILE* g_fMTGSWrite, *g_fMTGSRead; +extern u32 g_MTGSDebug, g_MTGSId; + +#define MTGS_RECWRITE(start, size) { \ + if( g_MTGSDebug & 1 ) { \ + u32* pstart = (u32*)(start); \ + u32 cursize = (u32)(size); \ + fprintf(g_fMTGSWrite, "*%x-%x (%d)\n", (u32)(start), (u32)(size), ++g_MTGSId); \ + /*while(cursize > 0) { \ + fprintf(g_fMTGSWrite, "%x %x %x %x\n", pstart[0], pstart[1], pstart[2], pstart[3]); \ + pstart += 4; \ + cursize -= 16; \ + }*/ \ + if( g_MTGSDebug & 2 ) fflush(g_fMTGSWrite); \ + } \ +} \ + +#define MTGS_RECREAD(start, size) { \ + if( g_MTGSDebug & 1 ) { \ + u32* pstart = (u32*)(start); \ + u32 cursize = (u32)(size); \ + fprintf(g_fMTGSRead, "*%x-%x (%d)\n", (u32)(start), (u32)(size), ++g_MTGSId); \ + /*while(cursize > 0) { \ + fprintf(g_fMTGSRead, "%x %x %x %x\n", pstart[0], pstart[1], pstart[2], pstart[3]); \ + pstart += 4; \ + cursize -= 16; \ + }*/ \ + if( g_MTGSDebug & 4 ) fflush(g_fMTGSRead); \ + } \ +} \ + +#else + +#define MTGS_RECWRITE 0&& +#define MTGS_RECREAD 0&& + +#endif + +// mem and size are the ones from GSRingBufCopy +#define GSRINGBUF_DONECOPY(mem, size) { \ + u8* temp = (u8*)(mem) + (size); \ + assert( temp <= GS_RINGBUFFEREND); \ + MTGS_RECWRITE(mem, size); \ + if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer(&g_pGSWritePos, temp); \ +} + +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size); + +void gsInit(); +void gsShutdown(); +void gsReset(); + +// used for resetting GIF fifo +void gsGIFReset(); + +void gsWrite8(u32 mem, u8 value); +void gsConstWrite8(u32 mem, int mmreg); + +void gsWrite16(u32 mem, u16 value); +void gsConstWrite16(u32 mem, int mmreg); + +void gsWrite32(u32 mem, u32 value); +void gsConstWrite32(u32 mem, int mmreg); + +void gsWrite64(u32 mem, u64 value); +void gsConstWrite64(u32 mem, int mmreg); + +void gsConstWrite128(u32 mem, int mmreg); + +u8 gsRead8(u32 mem); +int gsConstRead8(u32 x86reg, u32 mem, u32 sign); + +u16 gsRead16(u32 mem); +int gsConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 gsRead32(u32 mem); +int gsConstRead32(u32 x86reg, u32 mem); + +u64 gsRead64(u32 mem); +void gsConstRead64(u32 mem, int mmreg); + +void gsConstRead128(u32 mem, int xmmreg); + +void gsIrq(); +int gsInterrupt(); +void dmaGIF(); +void mfifoGIFtransfer(int qwc); +int gsFreeze(gzFile f, int Mode); +int _GIFchain(); +int gifMFIFOInterrupt(); + +// GS Playback +#define GSRUN_TRANS1 1 +#define GSRUN_TRANS2 2 +#define GSRUN_TRANS3 3 +#define GSRUN_VSYNC 4 + +#ifdef PCSX2_DEVBUILD + +extern int g_SaveGSStream; +extern int g_nLeftGSFrames; +extern gzFile g_fGSSave; + +#define GSGIFTRANSFER1(pMem, addr) { \ + if( g_SaveGSStream == 2) { \ + int type = GSRUN_TRANS1; \ + int size = (0x4000-(addr))/16; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &size, 4); \ + gzwrite(g_fGSSave, ((u8*)pMem)+(addr), size*16); \ + } \ + GSgifTransfer1(pMem, addr); \ +} + +#define GSGIFTRANSFER2(pMem, size) { \ + if( g_SaveGSStream == 2) { \ + int type = GSRUN_TRANS2; \ + int _size = size; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &_size, 4); \ + gzwrite(g_fGSSave, pMem, _size*16); \ + } \ + GSgifTransfer2(pMem, size); \ +} + +#define GSGIFTRANSFER3(pMem, size) { \ + if( g_SaveGSStream == 2 ) { \ + int type = GSRUN_TRANS3; \ + int _size = size; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &_size, 4); \ + gzwrite(g_fGSSave, pMem, _size*16); \ + } \ + GSgifTransfer3(pMem, size); \ +} + +#define GSVSYNC() { \ + if( g_SaveGSStream == 2 ) { \ + int type = GSRUN_VSYNC; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + } \ +} \ + +#else + +#define GSGIFTRANSFER1(pMem, size) GSgifTransfer1(pMem, size) +#define GSGIFTRANSFER2(pMem, size) GSgifTransfer2(pMem, size) +#define GSGIFTRANSFER3(pMem, size) GSgifTransfer3(pMem, size) +#define GSVSYNC() + +#endif + +void RunGSState(gzFile f); + +#endif diff --git a/branches/pcsx2_0.9.2/Gte.h b/branches/pcsx2_0.9.2/Gte.h new file mode 100644 index 0000000..eaffa88 --- /dev/null +++ b/branches/pcsx2_0.9.2/Gte.h @@ -0,0 +1,52 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GTE_H__ +#define __GTE_H__ + +void gteMFC2(); +void gteCFC2(); +void gteMTC2(); +void gteCTC2(); +void gteLWC2(); +void gteSWC2(); + +void gteRTPS(); +void gteOP(); +void gteNCLIP(); +void gteDPCS(); +void gteINTPL(); +void gteMVMVA(); +void gteNCDS(); +void gteNCDT(); +void gteCDP(); +void gteNCCS(); +void gteCC(); +void gteNCS(); +void gteNCT(); +void gteSQR(); +void gteDCPL(); +void gteDPCT(); +void gteAVSZ3(); +void gteAVSZ4(); +void gteRTPT(); +void gteGPF(); +void gteGPL(); +void gteNCCT(); + +#endif /* __GTE_H__ */ diff --git a/branches/pcsx2_0.9.2/Hw.c b/branches/pcsx2_0.9.2/Hw.c new file mode 100644 index 0000000..2179c23 --- /dev/null +++ b/branches/pcsx2_0.9.2/Hw.c @@ -0,0 +1,2643 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include + +#include "Common.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "PsxMem.h" +#include "IPU/IPU.h" +#include "GS.h" + +#include + +#ifndef WIN32_VIRTUAL_MEM +u8 *psH; // hw mem +u16 *psHW; +u32 *psHL; +u64 *psHD; +#endif + +int hwInit() { + +#ifndef WIN32_VIRTUAL_MEM + psH = (u8*)_aligned_malloc(0x00010000, 16); + if (psH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } +#endif + + gsInit(); + vif0Init(); + vif1Init(); + vifDmaInit(); + sifInit(); + sprInit(); + ipuInit(); + + return 0; +} + +void hwShutdown() { +#ifndef WIN32_VIRTUAL_MEM + if (psH == NULL) return; + _aligned_free(psH); psH = NULL; +#endif + ipuShutdown(); +} + +void hwReset() +{ + memset(PS2MEM_HW+0x2000, 0, 0x0000e000); + + psHu32(0xf520) = 0x1201; + psHu32(0xf260) = 0x1D000060; + // i guess this is kinda a version, it's used by some bioses + psHu32(0xf590) = 0x1201; + + gsReset(); + ipuReset(); +} + +u8 hwRead8(u32 mem) +{ + u8 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(mem)); +#endif + + switch (mem) { + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem); + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u8)ret; + } + + if (mem < 0x10010000) + { + ret = psHu8(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 8 at %x\n",mem); +#endif + break; + } + + return ret; +} + +int hwConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + //psHu32(mem) &= ~0x4000; + return 0; + } + } + + if (mem < 0x10010000) + { + _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; +} + +u16 hwRead16(u32 mem) +{ + u16 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 16bit at %lx, ret %lx\n", mem, psHu16(mem)); +#endif + switch (mem) { + case 0x10000000: ret = (u16)rcntRcount(0); break; + case 0x10000010: ret = (u16)counters[0].mode; break; + case 0x10000020: ret = (u16)counters[0].target; break; + case 0x10000030: ret = (u16)counters[0].hold; break; + + case 0x10000800: ret = (u16)rcntRcount(1); break; + case 0x10000810: ret = (u16)counters[1].mode; break; + case 0x10000820: ret = (u16)counters[1].target; break; + case 0x10000830: ret = (u16)counters[1].hold; break; + + case 0x10001000: ret = (u16)rcntRcount(2); break; + case 0x10001010: ret = (u16)counters[2].mode; break; + case 0x10001020: ret = (u16)counters[2].target; break; + + case 0x10001800: ret = (u16)rcntRcount(3); break; + case 0x10001810: ret = (u16)counters[3].mode; break; + case 0x10001820: ret = (u16)counters[3].target; break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu16(mem) | 0x0102; + psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u16)ret; + } + if (mem < 0x10010000) { + ret = psHu16(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 16 at %x\n",mem); +#endif + break; + } + + return ret; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +static u32 s_regreads[3] = {0x010200000, 0xbfff0000, 0xF0000102}; +int hwConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10002000 ){ +#ifdef EECNT_LOG + EECNT_LOG("cnt read to %x\n", mem); +#endif + } +#endif + + switch (mem) { + case 0x10000000: + PUSH32I(0); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000020: + _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); + return 0; + case 0x10000030: + _eeReadConstMem16(x86reg, (u32)&counters[0].hold, sign); + return 0; + + case 0x10000800: + PUSH32I(1); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10000810: + _eeReadConstMem16(x86reg, (u32)&counters[1].mode, sign); + return 0; + + case 0x10000820: + _eeReadConstMem16(x86reg, (u32)&counters[1].target, sign); + return 0; + + case 0x10000830: + _eeReadConstMem16(x86reg, (u32)&counters[1].hold, sign); + return 0; + + case 0x10001000: + PUSH32I(2); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001010: + _eeReadConstMem16(x86reg, (u32)&counters[2].mode, sign); + return 0; + + case 0x10001020: + _eeReadConstMem16(x86reg, (u32)&counters[2].target, sign); + return 0; + + case 0x10001800: + PUSH32I(3); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001810: + _eeReadConstMem16(x86reg, (u32)&counters[3].mode, sign); + return 0; + + case 0x10001820: + _eeReadConstMem16(x86reg, (u32)&counters[3].target, sign); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff] - 2); + PORMtoR(x86reg&0xf, (u32)&s_regreads[0]); + PANDMtoR(x86reg&0xf, (u32)&s_regreads[1]); + } + else { + if( sign ) MOVSX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + else MOVZX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + + OR32ItoR(x86reg, 0x0102); + AND32ItoR(x86reg, ~0x4000); + } + return 0; + } + } + if (mem < 0x10010000) { + _eeReadConstMem16(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +static int b440; + +extern BOOL bExecBIOS; +static int b440table[] = { + 0, 31, 31, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0 }; + +#ifdef WIN32_VIRTUAL_MEM +__declspec(naked) void recCheckF440() +{ + __asm { + add b440, 1 + mov eax, b440 + sub eax, 3 + mov edx, 31 + + cmp eax, 27 + ja WriteVal + shl eax, 2 + mov edx, dword ptr [eax+b440table] + +WriteVal: + mov eax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [eax], edx + ret + } +} + +void iMemRead32Check() +{ + // test if 0xf440 + if( bExecBIOS ) { + u8* ptempptr[2]; + CMP32ItoR(ECX, 0x1000f440); + ptempptr[0] = JNE8(0); + +// // increment and test +// INC32M((int)&b440); +// MOV32MtoR(EAX, (int)&b440); +// SUB32ItoR(EAX, 3); +// MOV32ItoR(EDX, 31); +// +// CMP32ItoR(EAX, 27); +// +// // look up table +// ptempptr[1] = JA8(0); +// SHL32ItoR(EAX, 2); +// ADD32ItoR(EAX, (int)b440table); +// MOV32RmtoR(EDX, EAX); +// +// x86SetJ8( ptempptr[1] ); +// +// MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + CALLFunc((u32)recCheckF440); + + x86SetJ8( ptempptr[0] ); + } +} + +#endif + +u32 hwRead32(u32 mem) { + u32 ret; + +#ifdef SPR_LOG + SPR_LOG("Hardware read 32bit at %lx, ret %lx\n", mem, psHu32(mem)); +#endif + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead32(mem); + } + + // gauntlen uses 0x1001xxxx + switch (mem) { + case 0x10000000: return (u16)rcntRcount(0); + case 0x10000010: return (u16)counters[0].mode; + case 0x10000020: return (u16)counters[0].target; + case 0x10000030: return (u16)counters[0].hold; + + case 0x10000800: return (u16)rcntRcount(1); + case 0x10000810: return (u16)counters[1].mode; + case 0x10000820: return (u16)counters[1].target; + case 0x10000830: return (u16)counters[1].hold; + + case 0x10001000: return (u16)rcntRcount(2); + case 0x10001010: return (u16)counters[2].mode; + case 0x10001020: return (u16)counters[2].target; + + case 0x10001800: return (u16)rcntRcount(3); + case 0x10001810: return (u16)counters[3].mode; + case 0x10001820: return (u16)counters[3].target; + +#ifdef PCSX2_DEVBUILD + case 0x1000A000: + ret = psHu32(mem);//dma2 chcr + HW_LOG("Hardware read DMA2_CHCR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A010: + ret = psHu32(mem);//dma2 madr + HW_LOG("Hardware read DMA2_MADR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A020: + ret = psHu32(mem);//dma2 qwc + HW_LOG("Hardware readDMA2_QWC 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A030: + ret = psHu32(mem);//dma2 taddr + HW_LOG("Hardware read DMA2_TADDR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A040: + ret = psHu32(mem);//dma2 asr0 + HW_LOG("Hardware read DMA2_ASR0 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A050: + ret = psHu32(mem);//dma2 asr1 + HW_LOG("Hardware read DMA2_ASR1 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A080: + ret = psHu32(mem);//dma2 saddr + HW_LOG("Hardware read DMA2_SADDR 32 at %lx, ret %lx\n", mem, ret); + break; + case 0x1000B400: // dma4 chcr + ret = ((DMACh *)&PS2MEM_HW[0xb400])->chcr; + SPR_LOG("Hardware read IPU1_CHCR 32 at %lx, ret %x\n", mem, ret); + break; + + case 0x1000e010: // DMAC_STAT + HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); + return psHu32(0xe010); + case 0x1000f000: // INTC_STAT +// HW_LOG("INTC_STAT Read 32bit %x\n", psHu32(0xf000)); + return psHu32(0xf000); + case 0x1000f010: // INTC_MASK + HW_LOG("INTC_MASK Read 32bit %x\n", psHu32(0xf010)); + return psHu32(0xf010); +#endif + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + ret = 0; + break; + + case 0x1000f440: + + b440++; + switch (b440) { + case 3: case 6: case 9: case 10: + case 13: case 14: + case 17: case 18: + case 21: case 22: + case 25: case 26: + case 29: case 30: + ret = 0; break; + default: + ret = 0x1f; break; + } + break; + + case 0x1000f520: // DMAC_ENABLER +#ifdef HW_LOG + HW_LOG("DMAC_ENABLER Read 32bit %lx\n", psHu32(0xf590)); +#endif + return psHu32(0xf590); + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + // SIF Control Registers + /*1D000020 (word) - EE -> IOP status flag ( set to 0x10000 always ready ) + 1D000030 (word) - IOP -> EE status flag + 1D000040 (word) - See psxMem.c ( Initially set to 0xF00042 and reset to + to this value if 0x20 is written ) + 1D000060 (word) - used to detect whether the SIF interface exists + read must be 0x1D000060, or the top 20 bits must be zero + */ + // note, any changes you make in here, also make on recMemRead32 + if(mem ==0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem) | 0xF0000102; + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); +//#ifdef HW_LOG +// SysPrintf("sif %x(%x) Read 32bit %x\n", mem, 0xbd000000 | (mem & 0xf0),ret); +//#endif } + break; + + } + else if (mem < 0x10010000) { + ret = psHu32(mem); + } + else { + SysPrintf("32bit HW read of address 0x%x\n", mem); + ret = 0; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 32 at %lx, ret %lx\n", mem, ret); +#endif + break; + } + + return ret; +} + +int hwConstRead32(u32 x86reg, u32 mem) +{ + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuConstRead32(x86reg, mem); + } + + switch (mem) { + case 0x10000000: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 count read = %x\n", rcntRcount(0)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem32(x86reg, (u32)&counters[0].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 mode read = %x\n", counters[0].mode); +#endif + return 0; + case 0x10000020: + _eeReadConstMem32(x86reg, (u32)&counters[0].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 target read = %x\n", counters[0].target); +#endif + return 0; + case 0x10000030: + _eeReadConstMem32(x86reg, (u32)&counters[0].hold); + return 0; + + case 0x10000800: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 count read = %x\n", rcntRcount(1)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10000810: + _eeReadConstMem32(x86reg, (u32)&counters[1].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 mode read = %x\n", counters[1].mode); +#endif + return 0; + case 0x10000820: + _eeReadConstMem32(x86reg, (u32)&counters[1].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 target read = %x\n", counters[1].target); +#endif + return 0; + case 0x10000830: + _eeReadConstMem32(x86reg, (u32)&counters[1].hold); + return 0; + + case 0x10001000: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 count read = %x\n", rcntRcount(2)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10001010: + _eeReadConstMem32(x86reg, (u32)&counters[2].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 mode read = %x\n", counters[2].mode); +#endif + return 0; + case 0x10001020: + _eeReadConstMem32(x86reg, (u32)&counters[2].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 target read = %x\n", counters[2].target); +#endif + return 0; + case 0x10001030: + _eeReadConstMem32(x86reg, (u32)&counters[2].hold); + return 0; + + case 0x10001800: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 count read = %x\n", rcntRcount(3)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10001810: + _eeReadConstMem32(x86reg, (u32)&counters[3].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 mode read = %x\n", counters[3].mode); +#endif + return 0; + case 0x10001820: + _eeReadConstMem32(x86reg, (u32)&counters[3].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 target read = %x\n", counters[3].target); +#endif + return 0; + case 0x10001830: + _eeReadConstMem32(x86reg, (u32)&counters[3].hold); + return 0; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + + case 0x1000f440: + //iMemRead32Check(); + // increment and test + INC32M((int)&b440); + MOV32MtoR(EAX, (int)&b440); + SUB32ItoR(EAX, 3); + MOV32ItoR(EDX, 31); + + CMP32ItoR(EAX, 27); + + // look up table + j8Ptr[8] = JA8(0); + SHL32ItoR(EAX, 2); + ADD32ItoR(EAX, (int)b440table); + MOV32RmtoR(EDX, EAX); + + x86SetJ8( j8Ptr[8] ); + + MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + + if( IS_XMMREG(x86reg) ) SSE2_MOVD_R_to_XMM(x86reg&0xf, EDX); + else if( IS_MMXREG(x86reg) ) MOVD32RtoMMX(x86reg&0xf, EDX); + else MOV32RtoR(x86reg, EDX); + + return 0; + + case 0x1000f520: // DMAC_ENABLER + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[0xf590]); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_XMMREG(x86reg) ) { + SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + SSEX_POR_M128_to_XMM(x86reg&0xf, (u32)&s_regreads[2]); + } + else if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); + PORMtoR(x86reg&0xf, (u32)&s_regreads[2]); + } + else { + MOV32MtoR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + OR32ItoR(x86reg, 0xF0000102); + } + return 0; + } + } + + if (mem < 0x10010000) { + _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); + } + else { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +u64 hwRead64(u32 mem) { + u64 ret; + + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead64(mem); + } + + switch (mem) { + default: + if (mem < 0x10010000) { + ret = psHu64(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 64 at %x\n",mem); +#endif + break; + } + + return ret; +} + +void hwConstRead64(u32 mem, int mmreg) { + if ((mem>=0x10002000) && (mem<0x10003000)) { + ipuConstRead64(mem, mmreg); + return; + } + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)PSM(mem)); + else { + MOVQMtoR(mmreg, (u32)PSM(mem)); + SetMMXstate(); + } +} + +void hwRead128(u32 mem, u64 *out) { + if (mem >= 0x10004000 && mem < 0x10008000) { + ReadFIFO(mem, out); return; + } + + if (mem < 0x10010000) { + out[0] = psHu64(mem); + out[1] = psHu64(mem+8); + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 128 at %x\n",mem); +#endif +} + +PCSX2_ALIGNED16(u32 s_TempFIFO[4]); +void hwConstRead128(u32 mem, int xmmreg) { + if (mem >= 0x10004000 && mem < 0x10008000) { + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)ReadFIFO); + ADD32ItoR(ESP, 8); + _eeReadConstMem128( xmmreg, (u32)&s_TempFIFO[0]); + return; + } + + _eeReadConstMem128( xmmreg, (u32)PSM(mem)); +} + +// dark cloud2 uses it +#define DmaExec8(name, num) { \ + psHu8(mem) = (u8)value; \ + if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { \ + /*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/ \ + dma##name(); \ + } \ +} + +// when writing imm +#define recDmaExecI8(name, num) { \ + MOV8ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec8(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI8(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem8((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 1); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +char sio_buffer[1024]; +static int sio_count; + +void hwWrite8(u32 mem, u8 value) { + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite8 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, (counters[0].mode & 0xff00) | value); break; + case 0x10000011: rcntWmode(0, (counters[0].mode & 0xff) | value << 8); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, (counters[1].mode & 0xff00) | value); break; + case 0x10000811: rcntWmode(1, (counters[1].mode & 0xff) | value << 8); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, (counters[2].mode & 0xff00) | value); break; + case 0x10001011: rcntWmode(2, (counters[2].mode & 0xff) | value << 8); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, (counters[3].mode & 0xff00) | value); break; + case 0x10001811: rcntWmode(3, (counters[3].mode & 0xff) | value << 8); break; + case 0x10001820: rcntWtarget(3, value); break; + + case 0x1000f180: + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +// SysPrintf("%c", value); + break; + + case 0x10008001: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 +#ifdef DMA_LOG + DMA_LOG("VIF1dma %lx\n", value); +#endif + DmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value); +#endif + DmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + psHu8(0xf592) = value; + psHu8(0xf522) = value; + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu8(mem) = value; + break; + case 0x40: + if(!(value & 0x100)) psHu32(mem) &= ~0x100; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + psHu8(mem) = value; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value); +#endif + break; + } +} + +static void PrintDebug(u8 value) +{ + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +} + +#define CONSTWRITE_CALLTIMER(name, index, bit) { \ + if( !IS_CONSTREG(mmreg) ) { \ + if( bit == 8 ) MOVZX32R8toR(mmreg&0xf, mmreg&0xf); \ + else if( bit == 16 ) MOVZX32R16toR(mmreg&0xf, mmreg&0xf); \ + } \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + PUSH32I(index); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 8); \ +} \ + +#define CONSTWRITE_TIMERS(bit) \ + case 0x10000000: CONSTWRITE_CALLTIMER(rcntWcount, 0, bit); break; \ + case 0x10000010: CONSTWRITE_CALLTIMER(rcntWmode, 0, bit); break; \ + case 0x10000020: CONSTWRITE_CALLTIMER(rcntWtarget, 0, bit); break; \ + case 0x10000030: CONSTWRITE_CALLTIMER(rcntWhold, 0, bit); break; \ + \ + case 0x10000800: CONSTWRITE_CALLTIMER(rcntWcount, 1, bit); break; \ + case 0x10000810: CONSTWRITE_CALLTIMER(rcntWmode, 1, bit); break; \ + case 0x10000820: CONSTWRITE_CALLTIMER(rcntWtarget, 1, bit); break; \ + case 0x10000830: CONSTWRITE_CALLTIMER(rcntWhold, 1, bit); break; \ + \ + case 0x10001000: CONSTWRITE_CALLTIMER(rcntWcount, 2, bit); break; \ + case 0x10001010: CONSTWRITE_CALLTIMER(rcntWmode, 2, bit); break; \ + case 0x10001020: CONSTWRITE_CALLTIMER(rcntWtarget, 2, bit); break; \ + \ + case 0x10001800: CONSTWRITE_CALLTIMER(rcntWcount, 3, bit); break; \ + case 0x10001810: CONSTWRITE_CALLTIMER(rcntWmode, 3, bit); break; \ + case 0x10001820: CONSTWRITE_CALLTIMER(rcntWtarget, 3, bit); break; \ + +void hwConstWrite8(u32 mem, int mmreg) +{ + switch (mem) { + CONSTWRITE_TIMERS(8) + + case 0x1000f180: + _recPushReg(mmreg); \ + iFlushCall(0); + CALLFunc((u32)PrintDebug); + ADD32ItoR(ESP, 4); + break; + + case 0x10008001: // dma0 - vif0 + recDmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 + recDmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif + recDmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU + recDmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU + recDmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 + recDmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 + recDmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR + recDmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR + recDmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf522], mmreg ); + _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf592], mmreg ); + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem8( (u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JNZ8(0); + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + x86SetJ8(j8Ptr[5]); + } + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem8((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } + + break; + } +} + +#define DmaExec16(name, num) { \ + psHu16(mem) = (u16)value; \ + if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + SysPrintf("16bit DMA Start\n"); \ + dma##name(); \ + } \ +} + +#define recDmaExecI16(name, num) { \ + MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec16(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI16(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite16(u32 mem, u16 value) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite16 to %x\n", mem); +#endif + switch(mem) { + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec16(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec16(VIF1, 1); + break; + +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec16(GIF, 2); + break; +#ifdef HW_LOG + + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec16(IPU0, 3); + break; + +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec16(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec16(SIF0, 5); + break; + + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec16(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec16(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + psHu16(0xf592) = value; + psHu16(0xf522) = value; + break; + case 0x1000f130: + case 0x1000f132: + case 0x1000f410: + case 0x1000f412: + case 0x1000f430: + case 0x1000f432: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu16(mem) = value; + break; + case 0x20: + psHu16(mem) |= value; + break; + case 0x30: + psHu16(mem) &= ~value; + break; + case 0x40: + assert( (mem&2)==0); + if(!(value & 0x100)) psHu16(mem) &= ~0x100; + else psHu16(mem) |= 0x100; + break; + case 0x60: + psHu16(mem) = 0; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + +#ifndef WIN32_VIRTUAL_MEM + if (mem < 0x10010000) +#endif + { + psHu16(mem) = value; + } + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value); +#endif +} + +void hwConstWrite16(u32 mem, int mmreg) +{ + switch(mem&~3) { + CONSTWRITE_TIMERS(16) + case 0x10008000: // dma0 - vif0 + recDmaExec16(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec16(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec16(GIF, 2); + break; + case 0x1000b000: // dma3 - fromIPU + recDmaExec16(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec16(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec16(SIF0, 5); + break; + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 + recDmaExec16(SIF1, 6); + break; + case 0x1000c800: // dma7 - sif2 + recDmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR + recDmaExec16(SPR0, 8); + break; + case 0x1000d400: // dma9 - toSPR + recDmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf522], mmreg); + _eeWriteConstMem16((u32)&PS2MEM_HW[0xf592], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem16OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + if( IS_CONSTREG(mmreg) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else { + NOT32R(mmreg&0xf); + AND16RtoM((u32)&PS2MEM_HW[mem&0xffff], mmreg&0xf); + } + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + } + else { + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } +} + +#define DmaExec(name, num) { \ + /* why not allowing tags on sif0/sif2? */ \ + if(mem!= 0x1000c000 && mem != 0x1000c400 && mem != 0x1000c800) \ + psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; \ + else \ + psHu32(mem) = (u32)value; \ + if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + dma##name(); \ + } \ +} + +// when writing an Imm +#define recDmaExecI(name, num) { \ + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \ + if(mem!= 0x1000c000 && mem != 0x1000c800) MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + else MOV32ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ + if( c & 0x100 ) { \ + TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((u32)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec(name, num) { \ + iFlushCall(0); \ + if( IS_CONSTREG(mmreg) ) { \ + recDmaExecI(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + if(mem!= 0x1000c000 && mem != 0x1000c800) { \ + if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \ + MOV16RtoM((u32)&PS2MEM_HW[(mem) & 0xffff], EAX); \ + } \ + else { \ + _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + } \ + } \ + else _eeWriteConstMem32((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST16ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST32ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((u32)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwWrite32(u32 mem, u32 value) { + int i; + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuWrite32(mem,value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case GIF_CTRL: + //SysPrintf("GIF_CTRL write %x\n", value); + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + return; + + case GIF_MODE: + // need to set GIF_MODE (hamster ball) + psHu32(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + SysPrintf("Gifstat write value = %x\n", value); + return; + + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec(VIF1, 1); + break; +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; +#ifdef HW_LOG + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec(IPU0, 3); + break; +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec(SPR1, 9); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 32bit %x\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 32bit %x\n", value); +#endif + psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 + value = value >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (value & (1<=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuConstWrite32(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x10000000: CONSTWRITE_CALLTIMER32(rcntWcount, 0, bit); break; + case 0x10000010: CONSTWRITE_CALLTIMER32(rcntWmode, 0, bit); break; + case 0x10000020: CONSTWRITE_CALLTIMER32(rcntWtarget, 0, bit); break; + case 0x10000030: CONSTWRITE_CALLTIMER32(rcntWhold, 0, bit); break; + + case 0x10000800: CONSTWRITE_CALLTIMER32(rcntWcount, 1, bit); break; + case 0x10000810: CONSTWRITE_CALLTIMER32(rcntWmode, 1, bit); break; + case 0x10000820: CONSTWRITE_CALLTIMER32(rcntWtarget, 1, bit); break; + case 0x10000830: CONSTWRITE_CALLTIMER32(rcntWhold, 1, bit); break; + + case 0x10001000: CONSTWRITE_CALLTIMER32(rcntWcount, 2, bit); break; + case 0x10001010: CONSTWRITE_CALLTIMER32(rcntWmode, 2, bit); break; + case 0x10001020: CONSTWRITE_CALLTIMER32(rcntWtarget, 2, bit); break; + + case 0x10001800: CONSTWRITE_CALLTIMER32(rcntWcount, 3, bit); break; + case 0x10001810: CONSTWRITE_CALLTIMER32(rcntWmode, 3, bit); break; + case 0x10001820: CONSTWRITE_CALLTIMER32(rcntWtarget, 3, bit); break; + + case GIF_CTRL: + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + return; + + case GIF_STAT: // stat is readonly + return; + + case 0x10008000: // dma0 - vif0 + recDmaExec(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000b000: // dma3 - fromIPU + recDmaExec(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 + recDmaExec(SIF1, 6); + break; + + case 0x1000c800: // dma7 - sif2 + recDmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR + recDmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR + recDmaExec(SPR1, 9); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[0xf000], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + return; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + case 0x40: + if( IS_CONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + else { + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST32ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + MOV32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef WIN32_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + break; + } +} + +void hwWrite64(u32 mem, u64 value) { + u32 val32; + int i; + + if ((mem>=0x10002000) && (mem<=0x10002030)) { + ipuWrite64(mem, value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case GIF_CTRL: +#ifdef PCSX2_DEVBUILD + SysPrintf("GIF_CTRL write 64\n", value); +#endif + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + + return; + + case GIF_MODE: + psHu64(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 64bit %x\n", value); + psHu64(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 64bit %x\n", value); +#endif + val32 = (u32)value; + psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 + val32 = val32 >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (val32 & (1<=0x10002000) && (mem<=0x10002030)) { + ipuConstWrite64(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case GIF_CTRL: + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((u32)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); + + AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((u32)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((u32)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + + break; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + + _eeWriteConstMem64((u32)PSM(mem), mmreg); + break; + } +} + +void hwWrite128(u32 mem, u64 *value) { + if (mem >= 0x10004000 && mem < 0x10008000) { + WriteFIFO(mem, value); return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + psHu32(0xf590) = *(u32*)value; + psHu32(0xf520) = *(u32*)value; + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status); +#endif + break; + } +} + +void hwConstWrite128(u32 mem, int mmreg) +{ + if (mem >= 0x10004000 && mem < 0x10008000) { + _eeWriteConstMem128((u32)&s_TempFIFO[0], mmreg); + iFlushCall(0); + PUSH32I((u32)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((u32)WriteFIFO); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + +#ifdef WIN32_VIRTUAL_MEM + _eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg); +#else + if (mem < 0x10010000) + _eeWriteConstMem128((u32)&PS2MEM_HW[mem&0xffff], mmreg); +#endif + break; + } +} + +int intcInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu32(INTC_STAT)) == 0) { + SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); + return 1; + } + if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("intcInterrupt %x\n", psHu32(INTC_STAT) & psHu32(INTC_MASK)); +#endif + if(psHu32(INTC_STAT) & 0x2){ + counters[0].hold = rcntRcount(0); + counters[1].hold = rcntRcount(1); + } + + cpuException(0x400, cpuRegs.branch); + + return 1; +} + +int dmacTestInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + return 1; +} + +int dmacInterrupt() +{ +if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("dmacInterrupt %x\n", (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)); +#endif + + cpuException(0x800, cpuRegs.branch); + return 1; +} + +void hwIntcIrq(int n) { + //if( psHu32(INTC_MASK) & (1<= (maddr+msize)) { + int s1 = (maddr+msize) - addr; + int s2 = size - s1; + + /* it does, so first copy 's1' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, s1/4); + memcpy(dst, data, s1); + + /* and second copy 's2' bytes from '&data[s1]' to 'maddr' */ + dst = PSM(maddr); + if (dst == NULL) return -1; + Cpu->Clear(maddr, s2/4); + memcpy(dst, &data[s1], s2); + } else { + //u32 * tempptr, * tempptr2; + + /* it doesn't, so just copy 'size' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, size/4); + memcpy_amd(dst, data, size); + } + + return 0; +} + + +int hwDmacSrcChainWithStack(DMACh *dma, int id) { + u32 temp,finalAddress; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 5: // Call - Transfer QWC following the tag, save succeeding tag + temp = dma->madr; //Temporarily Store ADDR + finalAddress = dma->tadr + 16 + (dma->qwc << 4); //Store Address of Succeeding tag + + if ((dma->chcr & 0x30) == 0x0) { //Check if ASR0 is empty + dma->asr0 = finalAddress; //If yes store Succeeding tag + dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address in call stack + }else if((dma->chcr & 0x30) == 0x10){ + dma->chcr = (dma->chcr & 0xffffffcf) | 0x20; //2 Addresses in call stack + dma->asr1 = finalAddress; //If no store Succeeding tag in ASR1 + }else { + SysPrintf("Call Stack Overflow (report if it fixes/breaks anything)\n"); + return 1; //Return done + } + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + dma->tadr = temp; //Set TADR to temporarily stored ADDR + return 0; + + case 6: // Ret - Transfer QWC following the tag, load next tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + if ((dma->chcr & 0x30) == 0x20) { //If ASR1 is NOT equal to 0 (Contains address) + dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack + dma->tadr = dma->asr1; //Read ASR1 as next tag + dma->asr1 = 0; //Clear ASR1 + } else { //If ASR1 is empty (No address held) + if((dma->chcr & 0x30) == 0x10) { //Check if ASR0 is NOT equal to 0 (Contains address) + dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack + dma->tadr = dma->asr0; //Read ASR0 as next tag + dma->asr0 = 0; //Clear ASR0 + } else { //Else if ASR1 and ASR0 are empty + //dma->tadr += 16; //Clear tag address - Kills Klonoa 2 + return 1; //End Transfer + } + } + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //comment out tadr fixes lemans + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} + +int hwDmacSrcChain(DMACh *dma, int id) { + u32 temp; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} diff --git a/branches/pcsx2_0.9.2/Hw.h b/branches/pcsx2_0.9.2/Hw.h new file mode 100644 index 0000000..d288644 --- /dev/null +++ b/branches/pcsx2_0.9.2/Hw.h @@ -0,0 +1,408 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __HW_H__ +#define __HW_H__ + +#include "PS2Etypes.h" +#include + +#ifndef WIN32_VIRTUAL_MEM +extern u8 *psH; // hw mem +extern u16 *psHW; +extern u32 *psHL; +extern u64 *psHD; +#endif + +#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff]) + +extern u32 g_nextBranchCycle; + +#define INT(n, ecycle) { \ + g_nextBranchCycle = min(g_nextBranchCycle, cpuRegs.cycle+ecycle); \ + cpuRegs.interrupt|= 1 << n; \ + cpuRegs.sCycle[n] = cpuRegs.cycle; \ + cpuRegs.eCycle[n] = ecycle; \ +} + +// VIF0 -- 0x10004000 -- psH[0x4000] +// VIF1 -- 0x10005000 -- psH[0x5000] +// GIF -- 0x10006000 -- psH[0x6000] +// IPUout -- 0x10007000 -- psH[0x7000] +// IPUin -- 0x10007010 -- psH[0x7010] + +void ReadFIFO(u32 mem, u64 *out); +void ConstReadFIFO(u32 mem); + +void WriteFIFO(u32 mem, u64 *value); +void ConstWriteFIFO(u32 mem); + + +// +// --- DMA --- +// + +typedef struct { + u32 chcr; + u32 null0[3]; + u32 madr; + u32 null1[3]; + u16 qwc; u16 pad; + u32 null2[3]; + u32 tadr; + u32 null3[3]; + u32 asr0; + u32 null4[3]; + u32 asr1; + u32 null5[11]; + u32 sadr; +} DMACh; + +// HW defines + +#define RCNT0_COUNT 0x10000000 +#define RCNT0_MODE 0x10000010 +#define RCNT0_TARGET 0x10000020 +#define RCNT0_HOLD 0x10000030 + +#define RCNT1_COUNT 0x10000800 +#define RCNT1_MODE 0x10000810 +#define RCNT1_TARGET 0x10000820 +#define RCNT1_HOLD 0x10000830 + +#define RCNT2_COUNT 0x10001000 +#define RCNT2_MODE 0x10001010 +#define RCNT2_TARGET 0x10001020 + +#define RCNT3_COUNT 0x10001800 +#define RCNT3_MODE 0x10001810 +#define RCNT3_TARGET 0x10001820 + +#define IPU_CMD 0x10002000 +#define IPU_CTRL 0x10002010 +#define IPU_BP 0x10002020 +#define IPU_TOP 0x10002030 + +#define GIF_CTRL 0x10003000 +#define GIF_MODE 0x10003010 +#define GIF_STAT 0x10003020 +#define GIF_TAG0 0x10003040 +#define GIF_TAG1 0x10003050 +#define GIF_TAG2 0x10003060 +#define GIF_TAG3 0x10003070 +#define GIF_CNT 0x10003080 +#define GIF_P3CNT 0x10003090 +#define GIF_P3TAG 0x100030A0 + +#define GIF_FIFO 0x10006000 + +#define IPUout_FIFO 0x10007000 +#define IPUin_FIFO 0x10007010 + +//VIF0 +#define D0_CHCR 0x10008000 +#define D0_MADR 0x10008010 +#define D0_QWC 0x10008020 + +//VIF1 +#define D1_CHCR 0x10009000 +#define D1_MADR 0x10009010 +#define D1_QWC 0x10009020 +#define D1_TADR 0x10009030 + +//GS +#define D2_CHCR 0x1000A000 +#define D2_MADR 0x1000A010 +#define D2_QWC 0x1000A020 +#define D2_TADR 0x1000A030 + +//fromIPU +#define D3_CHCR 0x1000B000 +#define D3_MADR 0x1000B010 +#define D3_QWC 0x1000B020 + +//toIPU +#define D4_CHCR 0x1000B400 +#define D4_MADR 0x1000B410 +#define D4_QWC 0x1000B420 +#define D4_TADR 0x1000B430 + +//SIF0 +#define D5_CHCR 0x1000C000 +#define D5_MADR 0x1000C010 +#define D5_QWC 0x1000C020 + +//SIF1 +#define D6_CHCR 0x1000C400 +#define D6_MADR 0x1000C410 +#define D6_QWC 0x1000C420 + +//SIF2 +#define D7_CHCR 0x1000C800 +#define D7_MADR 0x1000C810 +#define D7_QWC 0x1000C820 + +//fromSPR +#define D8_CHCR 0x1000D000 +#define D8_MADR 0x1000D010 +#define D8_QWC 0x1000D020 +#define D8_SADR 0x1000D080 + + +#define DMAC_CTRL 0x1000E000 +#define DMAC_STAT 0x1000E010 +#define DMAC_PCR 0x1000E020 +#define DMAC_SQWC 0x1000E030 +#define DMAC_RBSR 0x1000E040 +#define DMAC_RBOR 0x1000E050 +#define DMAC_STADR 0x1000E060 + +#define INTC_STAT 0x1000F000 +#define INTC_MASK 0x1000F010 + +#define SBUS_F220 0x1000F220 +#define SBUS_SMFLG 0x1000F230 +#define SBUS_F240 0x1000F240 + +#define DMAC_ENABLER 0x1000F520 +#define DMAC_ENABLEW 0x1000F590 + +#define SBFLG_IOPALIVE 0x10000 +#define SBFLG_IOPSYNC 0x40000 + +#define GS_PMODE 0x12000000 +#define GS_SMODE1 0x12000010 +#define GS_SMODE2 0x12000020 +#define GS_SRFSH 0x12000030 +#define GS_SYNCH1 0x12000040 +#define GS_SYNCH2 0x12000050 +#define GS_SYNCV 0x12000060 +#define GS_DISPFB1 0x12000070 +#define GS_DISPLAY1 0x12000080 +#define GS_DISPFB2 0x12000090 +#define GS_DISPLAY2 0x120000A0 +#define GS_EXTBUF 0x120000B0 +#define GS_EXTDATA 0x120000C0 +#define GS_EXTWRITE 0x120000D0 +#define GS_BGCOLOR 0x120000E0 +#define GS_CSR 0x12001000 +#define GS_IMR 0x12001010 +#define GS_BUSDIR 0x12001040 +#define GS_SIGLBLID 0x12001080 + +#define INTC_GS 0 +#define INTC_SBUS 1 +#define INTC_VBLANK_S 2 +#define INTC_VBLANK_E 3 +#define INTC_VIF0 4 +#define INTC_VIF1 5 +#define INTC_VU0 6 +#define INTC_VU1 7 +#define INTC_IPU 8 +#define INTC_TIM0 9 +#define INTC_TIM1 10 +#define INTC_TIM2 11 +#define INTC_TIM3 12 + +#define DMAC_STAT_SIS (1<<13) // stall condition +#define DMAC_STAT_MEIS (1<<14) // mfifo empty +#define DMAC_STAT_BEIS (1<<15) // bus error +#define DMAC_STAT_SIM (1<<29) // stall mask +#define DMAC_STAT_MEIM (1<<30) // mfifo mask + +#define DMAC_VIF0 0 +#define DMAC_VIF1 1 +#define DMAC_GIF 2 +#define DMAC_FROM_IPU 3 +#define DMAC_TO_IPU 4 +#define DMAC_SIF0 5 +#define DMAC_SIF1 6 +#define DMAC_SIF2 7 +#define DMAC_FROM_SPR 8 +#define DMAC_TO_SPR 9 +#define DMAC_ERROR 15 + +#define VIF0_STAT_VPS_W (1) +#define VIF0_STAT_VPS_D (2) +#define VIF0_STAT_VPS_T (3) +#define VIF0_STAT_VPS (3) +#define VIF0_STAT_VEW (1<<2) +#define VIF0_STAT_MRK (1<<6) +#define VIF0_STAT_DBF (1<<7) +#define VIF0_STAT_VSS (1<<8) +#define VIF0_STAT_VFS (1<<9) +#define VIF0_STAT_VIS (1<<10) +#define VIF0_STAT_INT (1<<11) +#define VIF0_STAT_ER0 (1<<12) +#define VIF0_STAT_ER1 (1<<13) + +#define VIF1_STAT_VPS_W (1) +#define VIF1_STAT_VPS_D (2) +#define VIF1_STAT_VPS_T (3) +#define VIF1_STAT_VPS (3) +#define VIF1_STAT_VEW (1<<2) +#define VIF1_STAT_VGW (1<<3) +#define VIF1_STAT_MRK (1<<6) +#define VIF1_STAT_DBF (1<<7) +#define VIF1_STAT_VSS (1<<8) +#define VIF1_STAT_VFS (1<<9) +#define VIF1_STAT_VIS (1<<10) +#define VIF1_STAT_INT (1<<11) +#define VIF1_STAT_ER0 (1<<12) +#define VIF1_STAT_ER1 (1<<13) +#define VIF1_STAT_FDR (1<<23) + +//DMA interrupts & masks +#define BEISintr (0x8000) +#define VIF0intr (0x10001) +#define VIF1intr (0x20002) +#define GIFintr (0x40004) +#define IPU0intr (0x80008) +#define IPU1intr (0x100010) +#define SIF0intr (0x200020) +#define SIF1intr (0x400040) +#define SIF2intr (0x800080) +#define SPR0intr (0x1000100) +#define SPR1intr (0x2000200) +#define SISintr (0x20002000) +#define MEISintr (0x40004000) + +#define DMAend(dma, num) { \ + dma->chcr &= ~0x100; \ + psHu32(DMAC_STAT)|= 1<>12 ].aPFNs == NULL ) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", mem); + return NULL; + } +#endif + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + return p; +} + +#else + +__forceinline void *dmaGetAddr(u32 addr) { + u8 *ptr; + +/*#ifdef DMA_LOG + if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x\n", addr); } +#endif*/ + if (addr & 0x80000000) { // teh sux why the f00k 0xE0000000 + return (void*)&psS[addr & 0x3ff0]; + } + + ptr = (u8*)memLUTR[addr >> 12]; + if (ptr == NULL) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", addr); + return NULL; + } + return (void*)(ptr + (addr & 0xff0)); +} + +#endif + +int hwInit(); +void hwReset(); +void hwShutdown(); + +// hw read functions +u8 hwRead8 (u32 mem); +int hwConstRead8 (u32 x86reg, u32 mem, u32 sign); + +u16 hwRead16(u32 mem); +int hwConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 hwRead32(u32 mem); +int hwConstRead32(u32 x86reg, u32 mem); + +u64 hwRead64(u32 mem); +void hwConstRead64(u32 mem, int mmreg); + +void hwRead128(u32 mem, u64 *out); +void hwConstRead128(u32 mem, int xmmreg); + +// hw write functions +void hwWrite8 (u32 mem, u8 value); +void hwConstWrite8 (u32 mem, int mmreg); + +void hwWrite16(u32 mem, u16 value); +void hwConstWrite16(u32 mem, int mmreg); + +void hwWrite32(u32 mem, u32 value); +void hwConstWrite32(u32 mem, int mmreg); + +void hwWrite64(u32 mem, u64 value); +void hwConstWrite64(u32 mem, int mmreg); + +void hwWrite128(u32 mem, u64 *value); +void hwConstWrite128(u32 mem, int xmmreg); + +void hwIntcIrq(int n); +void hwDmacIrq(int n); + +int hwMFIFORead(u32 addr, u8 *data, int size); +int hwMFIFOWrite(u32 addr, u8 *data, int size); + +int hwDmacSrcChainWithStack(DMACh *dma, int id); +int hwDmacSrcChain(DMACh *dma, int id); + +int intcInterrupt(); +int dmacInterrupt(); + +#endif /* __HW_H__ */ diff --git a/branches/pcsx2_0.9.2/INSTALL.txt b/branches/pcsx2_0.9.2/INSTALL.txt new file mode 100644 index 0000000..d41d77d --- /dev/null +++ b/branches/pcsx2_0.9.2/INSTALL.txt @@ -0,0 +1,24 @@ +Pcsx2 Emulator + +Windows Compilation +------------------- + +Goto windows/VCprojects, open up the appropriate sln and compile + +Linux Compilation +----------------- + +[Currently in beta stages] + +in the main directory type: +aclocal +autoconf +automake +./configure [options] +make + + +[options] include + +--enable-debug {Build with symbols and no optimizations} +--enable-devbuild {Build with extra tests} diff --git a/branches/pcsx2_0.9.2/IPU/IPU.c b/branches/pcsx2_0.9.2/IPU/IPU.c new file mode 100644 index 0000000..ed1a3e3 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/IPU.c @@ -0,0 +1,1965 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "IPU.h" +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +#include +#include + +#include "iR5900.h" +#include "pcl/pcl.h" + +#ifdef __WIN32__ +#define FASTCALL __fastcall +#else +#define FASTCALL +#endif + +#ifndef WIN32_VIRTUAL_MEM +IPUregisters g_ipuRegsReal; +#endif + +#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000]) +#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400]) + +#define IPU_DMA_GIFSTALL 1 +#define IPU_DMA_TIE0 2 +#define IPU_DMA_TIE1 4 +#define IPU_DMA_ACTV1 8 +#define IPU_DMA_DOTIE1 16 +#define IPU_DMA_FIREINT0 32 +#define IPU_DMA_FIREINT1 64 +#define IPU_DMA_VIFSTALL 128 + +static int g_nDMATransfer = 0; +int g_nIPU0Data = 0; // data left to transfer +u8* g_pIPU0Pointer = NULL; +int g_nCmdPos[2] = {0}, g_nCmdIndex = 0; +int ipuCurCmd = 0xffffffff; + +// returns number of qw read +int FIFOfrom_write(u32 * value, int size); +void FIFOfrom_read(void *value,int size); +int FIFOto_read(void *value); +int FIFOto_write(u32* pMem, int size); +void FIFOto_clear(); + +int FOreadpos = 0, FOwritepos = 0; +static int FIreadpos = 0, FIwritepos = 0; +PCSX2_ALIGNED16(u32 fifo_input[32]); +PCSX2_ALIGNED16(u32 fifo_output[32]); + +void ReorderBitstream(); +u16 FillInternalBuffer(u32 * pointer, u32 advance); + +// the BP doesn't advance and returns -1 if there is no data to be read +tIPU_BP g_BP; +static coroutine_t s_routine; // used for executing BDEC/IDEC +static int s_RoutineDone = 0; +static u32 s_tempstack[0x1000]; // 16k + +void IPUCMD_WRITE(u32 val); +void IPUWorker(); +int IPU0dma(); +int IPU1dma(); + +#define BigEndian _byteswap_ulong +//__forceinline u32 FASTCALL BigEndian(u32 a){ +// return ((((a >> 24) & 0xFF) << 0) + (((a >> 16) & 0xFF) << 8) + +// (((a >> 8) & 0xFF) << 16) + (((a >> 0) & 0xFF) << 24)); +//} + +// Color conversion stuff +char convert_data_buffer[0x1C]; +convert_init_t convert_init={convert_data_buffer, 0x1C}; +convert_t *convert; + +// Quantization matrix +static u8 niq[64], //non-intraquant matrix + iq[64]; //intraquant matrix +u16 vqclut[16]; //clut conversion table +static u8 s_thresh[2]; //thresholds for color conversions +int coded_block_pattern=0; +PCSX2_ALIGNED16(struct macroblock_8 mb8); +PCSX2_ALIGNED16(struct macroblock_16 mb16); +PCSX2_ALIGNED16(struct macroblock_rgb32 rgb32); +PCSX2_ALIGNED16(struct macroblock_rgb16 rgb16); + +u8 indx4[16*16/2]; +u32 mpeg2_inited; //mpeg2_idct_init() must be called only once +u8 PCT[]={'r', 'I', 'P', 'B', 'D', '-', '-', '-'}; +decoder_t g_decoder; //static, only to place it in bss +decoder_t tempdec; + +extern u8 mpeg2_scan_norm[64]; +extern u8 mpeg2_scan_alt[64]; + +PCSX2_ALIGNED16(u8 _readbits[80]); //local buffer (ring buffer) +u8* readbits = _readbits; // always can decrement by one 1qw + +#define SATURATE_4BITS(val) ((val)>15 ? 15 : (val)) + +void IPUProcessInterrupt() +{ + if( ipuRegs->ctrl.BUSY ) { + IPUWorker(); + } +} + +///////////////////////////////////////////////////////// +// Register accesses (run on EE thread) +int ipuInit() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + memset(&g_BP, 0, sizeof(g_BP)); + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + return 0; +} + +void ipuReset() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + g_nDMATransfer = 0; +} + +void ipuShutdown() +{ +} + +int ipuFreeze(gzFile f, int Mode) { + IPUProcessInterrupt(); + + gzfreeze(ipuRegs, sizeof(IPUregisters)); + gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer)); + gzfreeze(&FIreadpos, sizeof(FIreadpos)); + gzfreeze(&FIwritepos, sizeof(FIwritepos)); + gzfreeze(fifo_input, sizeof(fifo_input)); + gzfreeze(&FOreadpos, sizeof(FOreadpos)); + gzfreeze(&FOwritepos, sizeof(FOwritepos)); + gzfreeze(fifo_output, sizeof(fifo_output)); + gzfreeze(&g_BP, sizeof(g_BP)); + gzfreeze(niq, sizeof(niq)); + gzfreeze(iq, sizeof(niq)); + gzfreeze(vqclut, sizeof(vqclut)); + gzfreeze(s_thresh, sizeof(s_thresh)); + gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern)); + gzfreeze(&g_decoder, sizeof(g_decoder)); + gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm)); + gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt)); + gzfreeze(g_nCmdPos, sizeof(g_nCmdPos)); + gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex)); + gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd)); + + gzfreeze(_readbits, sizeof(_readbits)); + + if( Mode == 0 ) { + int temp = readbits-_readbits; + gzfreeze(&temp, sizeof(temp)); + } + else { + int temp; + gzfreeze(&temp, sizeof(temp)); + readbits = _readbits; + } + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + + return 0; +} + +BOOL ipuCanFreeze() +{ + return ipuCurCmd == 0xffffffff; +} + +u32 ipuRead32(u32 mem) +{ + IPUProcessInterrupt(); + + switch (mem){ + + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl.IFC = g_BP.IFC; + //ipuRegs->ctrl.OFC = min(g_nIPU0Data, 8); // check if transfering to ipu0 + ipuRegs->ctrl.CBP = coded_block_pattern; + +#ifdef IPU_LOG + if( !ipuRegs->ctrl.BUSY ) { + IPU_LOG("Ipu read32: IPU_CTRL=0x%08X %x\n", ipuRegs->ctrl._u32, cpuRegs.pc); + } +#endif + return ipuRegs->ctrl._u32; + + case 0x10002020: // IPU_BP + + ipuRegs->ipubp = g_BP.BP & 0x7f; + ipuRegs->ipubp |= g_BP.IFC<<8; + ipuRegs->ipubp |= (g_BP.FP+g_BP.bufferhasnew) << 16; + +#ifdef IPU_LOG + IPU_LOG("Ipu read32: IPU_BP=0x%08X\n", *(u32*)&g_BP); +#endif + return ipuRegs->ipubp; + } + + return *(u32*)(((u8*)ipuRegs)+(mem&0xff)); // ipu repeats every 0x100 +} + +int ipuConstRead32(u32 x86reg, u32 mem) +{ + int workingreg, tempreg, tempreg2; + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + +// if( !(x86reg&(MEM_XMMTAG|MEM_MMXTAG)) ) { +// if( x86reg == EAX ) { +// tempreg = ECX; +// tempreg2 = EDX; +// } +// else if( x86reg == ECX ) { +// tempreg = EAX; +// tempreg2 = EDX; +// } +// else if( x86reg == EDX ) { +// tempreg = EAX; +// tempreg2 = ECX; +// } +// +// workingreg = x86reg; +// } +// else { + workingreg = EAX; + tempreg = ECX; + tempreg2 = EDX; +// } + + switch (mem){ + + case 0x10002010: // IPU_CTRL + + MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(workingreg, ~0x3f0f); // save OFC + OR8MtoR(workingreg, (u32)&g_BP.IFC); + OR8MtoR(workingreg+4, (u32)&coded_block_pattern); // or ah, mem + +// MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); +// AND32ItoR(workingreg, ~0x3fff); +// MOV32MtoR(tempreg, (u32)&g_nIPU0Data); +// MOV8MtoR(workingreg, (u32)&g_BP.IFC); +// +// CMP32ItoR(tempreg, 8); +// j8Ptr[5] = JLE8(0); +// MOV32ItoR(tempreg, 8); +// x86SetJ8( j8Ptr[5] ); +// SHL32ItoR(tempreg, 4); +// +// OR8MtoR(workingreg+4, (u32)&coded_block_pattern); // or ah, mem +// OR8RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ctrl._u32, workingreg); +#endif + // NOTE: not updating ipuRegs->ctrl +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + return 1; + + case 0x10002020: // IPU_BP + + assert( (u32)&g_BP.FP + 1 == (u32)&g_BP.bufferhasnew ); + + MOVZX32M8toR(workingreg, (u32)&g_BP.BP); + MOVZX32M8toR(tempreg, (u32)&g_BP.FP); + AND8ItoR(workingreg, 0x7f); + ADD8MtoR(tempreg, (u32)&g_BP.bufferhasnew); + MOV8MtoR(workingreg+4, (u32)&g_BP.IFC); + + SHL32ItoR(tempreg, 16); + OR32RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ipubp, workingreg); +#endif + // NOTE: not updating ipuRegs->ipubp +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + + return 1; + + default: + // ipu repeats every 0x100 + _eeReadConstMem32(x86reg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + return 0; + } + + return 0; +} + +u64 ipuRead64(u32 mem) +{ + IPUProcessInterrupt(); + +#ifdef PCSX2_DEVBUILD + if( mem == 0x10002010 ) { + SysPrintf("reading 64bit IPU ctrl\n"); + } + if( mem == 0x10002020 ) { + SysPrintf("reading 64bit IPU top\n"); + } +#endif + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + //if(!ipuRegs->cmd.BUSY){ + if( ipuRegs->cmd.DATA&0xffffff ) { + IPU_LOG("Ipu read64: IPU_CMD=BUSY=%x, DATA=%08X\n", ipuRegs->cmd.BUSY?1:0,ipuRegs->cmd.DATA); + } +#endif + //return *(u64*)&ipuRegs->cmd; + break; + + case 0x10002030: // IPU_TOP +#ifdef IPU_LOG + IPU_LOG("Ipu read64: IPU_TOP=%x, bp = %d\n",ipuRegs->top,g_BP.BP); +#endif + + //return *(u64*)&ipuRegs->top; + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu read64: Unknown=%x\n", mem); +#endif + break; + + } + return *(u64*)(((u8*)ipuRegs)+(mem&0xff)); +} + +void ipuConstRead64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)(((u8*)ipuRegs)+(mem&0xff))); + else { + MOVQMtoR(mmreg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + SetMMXstate(); + } +} + +void ipuSoftReset() +{ + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + FIFOto_clear(); + memset(fifo_output,0,sizeof(u32)*32); + FOwritepos = 0; + FOreadpos = 0; + coded_block_pattern = 0; + + ipuRegs->ctrl._u32 = 0; + g_BP.BP = 0; + g_BP.IFC = 0; + g_BP.FP = 0; + g_BP.bufferhasnew = 0; + ipuRegs->top = 0; + g_nCmdIndex = 0; + ipuCurCmd = 0xffffffff; + g_nCmdPos[0] = 0; g_nCmdPos[1] = 0; +} + +void ipuWrite32(u32 mem,u32 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE(value); + break; + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl._u32 = (value&0x47f30000)|(ipuRegs->ctrl._u32&0x8000ffff); + if (ipuRegs->ctrl.RST & 0x1) { // RESET + ipuSoftReset(); + } + +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CTRL=0x%08X\n",value); +#endif + + break; + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write32: Unknown=%x\n", mem); +#endif + *(u32*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite32(u32 mem, int mmreg) +{ + iFlushCall(0); + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) PUSH32R(mmreg); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: // IPU_CMD + if( (mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + case 0x10002010: // IPU_CTRL + if( mmreg & MEM_EECONSTTAG ) { + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x47f30000; + + if( c & 0x40000000 ) { + CALLFunc((u32)ipuSoftReset); + } + else { + AND32ItoM((u32)&ipuRegs->ctrl._u32, 0x8000ffff); + OR32ItoM((u32)&ipuRegs->ctrl._u32, c); + } + } + else { + if( mmreg & MEM_XMMTAG ) SSE2_MOVD_XMM_to_R(EAX, mmreg&0xf); + else if( mmreg & MEM_MMXTAG ) MOVD32MMXtoR(EAX, mmreg&0xf); + else POP32R(EAX); + + MOV32MtoR(ECX, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(EAX, 0x47f30000); + AND32ItoR(ECX, 0x8000ffff); + OR32RtoR(EAX, ECX); + MOV32RtoM((u32)&ipuRegs->ctrl._u32, EAX); + + TEST32ItoR(EAX, 0x40000000); + j8Ptr[5] = JZ8(0); + + // reset + CALLFunc((u32)ipuSoftReset); + + x86SetJ8( j8Ptr[5] ); + } + + break; + default: + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) POP32R(mmreg); + _eeWriteConstMem32((u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +void ipuWrite64(u32 mem, u64 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE((u32)value); + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: Unknown=%x\n", mem); +#endif + *(u64*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuConstWrite64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: + _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem64( (u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +/////////////////////////////////////////// +// IPU Commands (exec on worker thread only) + +static void ipuBCLR(u32 val) { + FIFOto_clear(); + g_BP.BP = val & 0x7F; + g_BP.FP = 0; + g_BP.IFC = 0; + ipuRegs->ctrl.BUSY = 0; + ipuRegs->cmd.BUSY = 0; +#ifdef IPU_LOG + IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X\n", g_BP.BP); +#endif +} + +static BOOL ipuIDEC(u32 val) +{ + tIPU_CMD_IDEC idec={0, 0, 0, 0, 0, 0, 0, 0, 0}; + + *(u32*)&idec=val; +#ifdef IPU_LOG + IPU_LOG("IPU IDEC command.\n"); + if (idec.FB){ IPU_LOG(" Skip %d bits.",idec.FB);} + IPU_LOG(" Quantizer step code=0x%X.",idec.QSC); + if (idec.DTD==0){ IPU_LOG(" Does not decode DT."); + }else{ IPU_LOG(" Decodes DT.");} + if (idec.SGN==0){ IPU_LOG(" No bias."); + }else{ IPU_LOG(" Bias=128.");} + if (idec.DTE==1){ IPU_LOG(" Dither Enabled.");} + if (idec.OFM==0){ IPU_LOG(" Output format is RGB32."); + }else{ IPU_LOG(" Output format is RGB16.");} + IPU_LOG("\n"); +#endif + g_BP.BP+= idec.FB;//skip FB bits + //from IPU_CTRL + ipuRegs->ctrl.PCT = I_TYPE; //Intra DECoding;) + g_decoder.coding_type =ipuRegs->ctrl.PCT; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from IDEC value + g_decoder.quantizer_scale =idec.QSC; + g_decoder.frame_pred_frame_dct=!idec.DTD; + g_decoder.sgn =idec.SGN; + g_decoder.dte =idec.DTE; + g_decoder.ofm =idec.OFM; + //other stuff + g_decoder.dcr =1;//resets DC prediction value + + s_routine = co_create(mpeg2sliceIDEC, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +#ifdef _DEBUG +static int s_bdec=0; +#else +#define s_bdec 0 +#endif + +static BOOL ipuBDEC(u32 val) +{ + tIPU_CMD_BDEC bdec={0, 0, 0, 0, 0, 0, 0, 0}; + *(u32*)&bdec=val; + +#ifdef IPU_LOG + IPU_LOG("IPU BDEC(macroblock decode) command %x, num: 0x%x\n",cpuRegs.pc, s_bdec); + if (bdec.FB){ IPU_LOG(" Skip 0x%X bits.", bdec.FB);} + if (bdec.MBI){ IPU_LOG(" Intra MB.");} + else{ IPU_LOG(" Non-intra MB.");} + if (bdec.DCR){ IPU_LOG(" Resets DC prediction value.");} + else{ IPU_LOG(" Doesn't reset DC prediction value.");} + if (bdec.DT){ IPU_LOG(" Use field DCT.");} + else{ IPU_LOG(" Use frame DCT.");} + IPU_LOG(" Quantiser step=0x%X\n",bdec.QSC); +#endif + +#ifdef _DEBUG + s_bdec++; +#endif + + g_BP.BP+= bdec.FB;//skip FB bits + g_decoder.coding_type = I_TYPE; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from BDEC value + /* JayteeMaster: the quantizer (linear/non linear) depends on the q_scale_type */ + g_decoder.quantizer_scale =g_decoder.q_scale_type?non_linear_quantizer_scale [bdec.QSC]:bdec.QSC<<1; + g_decoder.macroblock_modes =bdec.DT ? DCT_TYPE_INTERLACED : 0; + g_decoder.dcr =bdec.DCR; + g_decoder.macroblock_modes|=bdec.MBI ? MACROBLOCK_INTRA : MACROBLOCK_PATTERN; + + memset(&mb8, 0, sizeof(struct macroblock_8)); + memset(&mb16, 0, sizeof(struct macroblock_16)); + + s_routine = co_create(mpeg2_slice, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + co_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuVDEC(u32 val) { + + switch( g_nCmdPos[0] ) { + case 0: + ipuRegs->cmd.DATA = 0; + if( !getBits32((u8*)&g_decoder.bitstream_buf, 0) ) + return FALSE; + + g_decoder.bitstream_bits = -16; + g_decoder.bitstream_buf=BigEndian(g_decoder.bitstream_buf); + + //value = BigEndian(value); + switch((val >> 26) & 3){ + case 0://Macroblock Address Increment + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + ipuRegs->cmd.DATA = get_macroblock_address_increment(&g_decoder); + break; + case 1://Macroblock Type //known issues: no error detected + g_decoder.frame_pred_frame_dct=1;//prevent DCT_TYPE_INTERLACED + g_decoder.coding_type =ipuRegs->ctrl.PCT; + ipuRegs->cmd.DATA=get_macroblock_modes(&g_decoder); + break; + case 2://Motion Code //known issues: no error detected + ipuRegs->cmd.DATA=get_motion_delta(&g_decoder,0); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + case 3://DMVector + ipuRegs->cmd.DATA=get_dmv(&g_decoder); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + } + + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + g_BP.BP+=(g_decoder.bitstream_bits+16); + if((int)g_BP.BP < 0) { + g_BP.BP += 128; + ReorderBitstream(); + } + + ipuRegs->cmd.DATA = (ipuRegs->cmd.DATA & 0xFFFF) | ((g_decoder.bitstream_bits+16) << 16); + ipuRegs->ctrl.ECD = (ipuRegs->cmd.DATA==0); + + case 1: + if( !getBits32((u8*)&ipuRegs->top, 0) ) { + g_nCmdPos[0] = 1; + return FALSE; + } + + ipuRegs->top = BigEndian(ipuRegs->top); + +#ifdef IPU_LOG + IPU_LOG("IPU VDEC command data 0x%x(0x%x). Skip 0x%X bits/Table=%d (%s), pct %d\n", + ipuRegs->cmd.DATA,ipuRegs->cmd.DATA >> 16,val & 0x3f, (val >> 26) & 3, (val >> 26) & 1 ? + ((val >> 26) & 2 ? "DMV" : "MBT") : (((val >> 26) & 2 ? "MC" : "MBAI")),ipuRegs->ctrl.PCT); +#endif + + return TRUE; + } + + assert(0); + return FALSE; +} + +static BOOL ipuFDEC(u32 val) +{ + if( !getBits32((u8*)&ipuRegs->cmd.DATA, 0) ) + return FALSE; + + ipuRegs->cmd.DATA = BigEndian(ipuRegs->cmd.DATA); + ipuRegs->top = ipuRegs->cmd.DATA; + return TRUE; +} + +static BOOL ipuSETIQ(u32 val) +{ + int i; + + if ((val >> 27) & 1){ + g_nCmdPos[0] += getBits((u8*)niq + g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); // 8*8*8 + +#ifdef IPU_LOG + IPU_LOG("Read non-intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + niq[i*8+0], niq[i*8+1], niq[i*8+2], niq[i*8+3], + niq[i*8+4], niq[i*8+5], niq[i*8+6], niq[i*8+7]); + } +#endif + }else{ + g_nCmdPos[0] += getBits((u8*)iq+8*g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); +#ifdef IPU_LOG + IPU_LOG("Read intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + iq[i*8+0], iq[i*8+1], iq[i*8+2], iq[i*8+3], + iq[i*8+4], iq[i*8+5], iq[i*8+6], iq[i*8+7]); + } +#endif + } + + return g_nCmdPos[0] == 64; +} + +static BOOL ipuSETVQ(u32 val) +{ + g_nCmdPos[0] += getBits((u8*)vqclut+g_nCmdPos[0], 256-8*g_nCmdPos[0], 1); // 16*2*8 + + if( g_nCmdPos[0] == 32 ) { +#ifdef IPU_LOG + IPU_LOG("IPU SETVQ command.\nRead VQCLUT table from IPU FIFO.\n"); + IPU_LOG( + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n" + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n", + vqclut[0] >> 10, (vqclut[0] >> 5) & 0x1F, vqclut[0] & 0x1F, + vqclut[1] >> 10, (vqclut[1] >> 5) & 0x1F, vqclut[1] & 0x1F, + vqclut[2] >> 10, (vqclut[2] >> 5) & 0x1F, vqclut[2] & 0x1F, + vqclut[3] >> 10, (vqclut[3] >> 5) & 0x1F, vqclut[3] & 0x1F, + vqclut[4] >> 10, (vqclut[4] >> 5) & 0x1F, vqclut[4] & 0x1F, + vqclut[5] >> 10, (vqclut[5] >> 5) & 0x1F, vqclut[5] & 0x1F, + vqclut[6] >> 10, (vqclut[6] >> 5) & 0x1F, vqclut[6] & 0x1F, + vqclut[7] >> 10, (vqclut[7] >> 5) & 0x1F, vqclut[7] & 0x1F, + vqclut[8] >> 10, (vqclut[8] >> 5) & 0x1F, vqclut[8] & 0x1F, + vqclut[9] >> 10, (vqclut[9] >> 5) & 0x1F, vqclut[9] & 0x1F, + vqclut[10] >> 10, (vqclut[10] >> 5) & 0x1F, vqclut[10] & 0x1F, + vqclut[11] >> 10, (vqclut[11] >> 5) & 0x1F, vqclut[11] & 0x1F, + vqclut[12] >> 10, (vqclut[12] >> 5) & 0x1F, vqclut[12] & 0x1F, + vqclut[13] >> 10, (vqclut[13] >> 5) & 0x1F, vqclut[13] & 0x1F, + vqclut[14] >> 10, (vqclut[14] >> 5) & 0x1F, vqclut[14] & 0x1F, + vqclut[15] >> 10, (vqclut[15] >> 5) & 0x1F, vqclut[15] & 0x1F); +#endif + } + + return g_nCmdPos[0] == 32; +} + +// IPU Transfers are split into 8Qwords so we need to send ALL the data +static BOOL ipuCSC(u32 val) +{ + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + *(u32*)&csc=val; + +#ifdef IPU_LOG + IPU_LOG("IPU CSC(Colorspace conversion from YCbCr) command (%d).\n",csc.MBC); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is RGB32. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } +#endif + //SysPrintf("CSC\n"); + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 3072/8 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 3072-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 3072/8 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + if (csc.OFM){ + ipu_dither2(&rgb32, &rgb16, csc.DTE); + } + } + + if (csc.OFM){ + while(g_nCmdPos[1] < 32) + { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] <= 0 ) + return FALSE; + } + } + else { + while(g_nCmdPos[1] < 64) + { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb32)+4*g_nCmdPos[1], 64-g_nCmdPos[1]); + + if( g_nCmdPos[1] <= 0 ) + return FALSE; + } + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +// Todo - Need to add the same stop and start code as CSC +static BOOL ipuPACK(u32 val) { + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + + *(u32*)&csc=val; +#ifdef IPU_LOG + IPU_LOG("IPU PACK (Colorspace conversion from RGB32) command.\n"); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is INDX4. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } + IPU_LOG("Number of macroblocks to be converted: %d\n", csc.MBC); +#endif + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 512 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 64 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + ipu_dither2(&rgb32, &rgb16, csc.DTE); + if (csc.OFM){ + ipu_vq(&rgb16, indx4); + } + } + + if (csc.OFM) { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += FIFOfrom_write(((u32*)indx4)+4*g_nCmdPos[1], 8-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 8 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +static void ipuSETTH(u32 val) { + s_thresh[0] = (val & 0xff); + s_thresh[1] = ((val>>16) & 0xff); +#ifdef IPU_LOG + IPU_LOG("IPU SETTH (Set threshold value)command %x.\n", val&0xff00ff); +#endif +} + +/////////////////////// +// IPU Worker Thread // +/////////////////////// +#define IPU_INTERRUPT(dma) { \ + hwIntcIrq(INTC_IPU); \ +} + +void IPUCMD_WRITE(u32 val) { + + // don't process anything if currently busy + if( ipuRegs->ctrl.BUSY ) { + // wait for thread + SysPrintf("IPU BUSY!\n"); + } + + ipuRegs->ctrl.ECD = 0; + ipuRegs->ctrl.SCD = 0; //clear ECD/SCD + ipuRegs->cmd.DATA = val; + g_nCmdPos[0] = 0; + + switch (ipuRegs->cmd.CMD) { + case SCE_IPU_BCLR: + ipuBCLR(val); + IPU_INTERRUPT(DMAC_TO_IPU); + return; + + case SCE_IPU_VDEC: + + g_BP.BP+= val & 0x3F; + + // check if enough data in queue + if( ipuVDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_FDEC: + +#ifdef IPU_LOG + IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X bytes, BP 0x%X, FP %d, CHCR 0x%x, %x\n", + val & 0x3f,g_BP.IFC,(int)g_BP.BP,g_BP.FP,((DMACh*)&PS2MEM_HW[0xb400])->chcr,cpuRegs.pc); +#endif + + g_BP.BP+= val & 0x3F; + + if( ipuFDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_SETTH: + ipuSETTH(val); + hwIntcIrq(INTC_IPU); + return; + + case SCE_IPU_SETIQ: +#ifdef IPU_LOG + IPU_LOG("IPU SETIQ command.\n"); +#endif +#ifdef IPU_LOG + if (val & 0x3f){ + IPU_LOG("Skip %d bits.\n", val & 0x3f); + } +#endif + g_BP.BP+= val & 0x3F; + + if( ipuSETIQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( ipuSETVQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_CSC: + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuCSC(ipuRegs->cmd.DATA) ) { + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + case SCE_IPU_PACK: + + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuPACK(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + if( ipuIDEC(val) ) { + // idec done, ipu0 done too + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + FreezeMMXRegs(0); + + return; + + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + if( ipuBDEC(val)) { + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + FreezeMMXRegs(0); + + return; + } + + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + hwIntcIrq(INTC_IPU); +} + +void IPUWorker() +{ + assert( ipuRegs->ctrl.BUSY ); + + switch (ipuCurCmd) { + case SCE_IPU_VDEC: + if( !ipuVDEC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_FDEC: + if( !ipuFDEC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_SETIQ: + if( !ipuSETIQ(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( !ipuSETVQ(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + case SCE_IPU_CSC: + if( !ipuCSC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + break; + case SCE_IPU_PACK: + if( !ipuPACK(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + co_call(s_routine); + if( !s_RoutineDone ) { + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.OFC = 0; + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + // CHECK!: IPU0dma remains when IDEC is done, so we need to clear it + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + co_call(s_routine); + if(!s_RoutineDone) + { + //hwIntcIrq(INTC_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + + FreezeMMXRegs(0); + return; + + default: + SysPrintf("Unknown IPU command: %x\n", ipuRegs->cmd.CMD); + break; + } + + // success + ipuRegs->ctrl.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_TO_IPU); +} + +///////////////// +// Buffer reader + +// move the readbits queue +__forceinline void inc_readbits() +{ + readbits += 16; + if( readbits >= _readbits+64 ) { + + // move back + *(u64*)(_readbits) = *(u64*)(_readbits+64); + *(u64*)(_readbits+8) = *(u64*)(_readbits+72); + readbits = _readbits; + } +} + +// returns the pointer of readbits moved by 1 qword +__forceinline u8* next_readbits() +{ + return readbits + 16; +} + +// returns the pointer of readbits moved by 1 qword +u8* prev_readbits() +{ + if( readbits < _readbits+16 ) { + return _readbits+48-(readbits-_readbits); + } + + return readbits-16; +} + +void ReorderBitstream() +{ + readbits = prev_readbits(); + g_BP.bufferhasnew = 1; + //g_BP.FP++; +} + +// IPU has a 2qword internal buffer whose status is pointed by FP. +// If FP is 1, there's 1 qword in buffer. Second qword is only loaded +// incase there are less than 32bits available in the first qword. +// \return Number of bits available (clamps at 16 bits) +u16 FillInternalBuffer(u32 * pointer, u32 advance) +{ + if(g_BP.FP == 0) + { + if( FIFOto_read(next_readbits()) == 0 ) + return 0; + + g_BP.bufferhasnew = 0; + inc_readbits(); + g_BP.FP = 1; + } + else if(g_BP.FP < 2 && g_BP.bufferhasnew == 0) + { + // in reality, need only > 96, but IPU reads ahead + if( *(int*)pointer >= 96) { + if( FIFOto_read(next_readbits()) ) + { + g_BP.FP += 1; + }else if(*(int*)pointer >= 128) + return 0; + + } + } + + if(*(int*)pointer >= 128) + { + assert( g_BP.FP >= 1 || g_BP.bufferhasnew); + inc_readbits(); + + if(advance) + { + // Incase BDEC reorders bits, we need to make sure we have the old + // data backed up. So we store the last read qword into the 2nd slot + // of the internal buffer. After that we copy the new qword read in + // the 2nd slot to the 1st slot to be read. + if( !g_BP.bufferhasnew ) + g_BP.FP--; + g_BP.bufferhasnew = 0; + } + + *pointer &= 127; + } + + // fixed : added (g_BP.FP+g_BP.bufferhasnew)*128 as fp could have been 0 + return (g_BP.FP+g_BP.bufferhasnew) == 1 ? g_BP.FP*128-(*(int*)pointer) : 128; +} + +// whenever reading fractions of bytes. The low bits always come from the next byte +// while the high bits come from the current byte +u8 getBits32(u8 *address, u32 advance) +{ + register u32 mask, shift=0; + u8* readpos; + + // Check if the current BP has exceeded or reached the limit of 128 + if( FillInternalBuffer(&g_BP.BP,1) < 32 ) + return 0; + + readpos = readbits+(int)g_BP.BP/8; + + if (g_BP.BP & 7) { + + shift = g_BP.BP&7; + mask = (0xff>>shift); + mask = mask|(mask<<8)|(mask<<16)|(mask<<24); + + *(u32*)address = ((~mask&*(u32*)(readpos+1))>>(8-shift)) | (((mask)&*(u32*)readpos)<>shift); + mask = mask|(mask<<8); + + *(u16*)address = ((~mask&*(u16*)(readpos+1))>>(8-shift)) | (((mask)&*(u16*)readpos)<>shift); + + *(u8*)address = (((~mask)&readpos[1])>>(8-shift)) | (((mask)&*readpos)<> (pointer&7)) << + (8-howmuch-(pointer&7))) & 0xFF; + mask &= readbits[((pointer)>>3)]; + mask >>= 8-howmuch-(pointer&7); + pointer += howmuch; + size -= howmuch; + shift -= howmuch; + *address |= mask << shift; + } + + ++address; + } + else + { + u8* readmem; + while (size) + { + if( FillInternalBuffer(&pointer,advance) < 8 ) + return address-oldaddr; + + howmuch = min(128-pointer, size); + size -= howmuch; + + readmem = readbits + (pointer>>3); + pointer += howmuch; + howmuch >>= 3; + + while(howmuch >= 4) { + *(u32*)address = *(u32*)readmem; + howmuch -= 4; + address += 4; + readmem += 4; + } + + switch(howmuch) { + case 3: address[2] = readmem[2]; + case 2: address[1] = readmem[1]; + case 1: address[0] = readmem[0]; + case 0: + break; + default: __assume(0); + } + + address += howmuch; + } + } + + // If not advance then reset the Reading buffer value + if(advance) g_BP.BP = pointer; + else readbits = oldbits; // restore the last pointer + + return address-oldaddr; +} + +///////////////////// CORE FUNCTIONS ///////////////// +void Skl_YUV_To_RGB32_MMX(u8 *RGB, const int Dst_BpS, const u8 *Y, const u8 *U, const u8 *V, + const int Src_BpS, const int Width, const int Height); + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn){ + int i; + u8* p = (u8*)rgb32; + + convert_init.start(convert_init.id, (u8*)rgb32, CONVERT_FRAME); + convert_init.copy(convert_init.id, (u8*)mb8->Y, (u8*)mb8->Cr, (u8*)mb8->Cb, 0); + + // do alpha processing +// if( cpucaps.hasStreamingSIMD2Extensions ) { +// int i; +// u8* p = (u8*)rgb32; +// +// __asm { +// movaps xmm6, s_thresh +// pshufd xmm7, xmm6, 0xee +// pshufd xmm6, xmm6, 0x44 +// pxor xmm5, xmm5 +// } +// +// for(i = 0; i < 64; i += 4, p += 64) { +// // process 2 qws at a time +// __asm { +// // extract 8 dwords +// mov edi, p +// movaps xmm0, qword ptr [edi] +// movaps xmm1, qword ptr [edi+16] +// movaps xmm2, qword ptr [edi+32] +// movaps xmm3, qword ptr [edi+48] +// +// +// } + // fixes suikoden5 + if( s_thresh[0] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + if( p[0] < s_thresh[0] && p[1] < s_thresh[0] && p[2] < s_thresh[0] ) + *(u32*)p = 0; + else + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else if( s_thresh[1] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else { + for(i = 0; i < 64; i++, p += 16) { + p[3] = p[7] = p[11] = p[15] = 0x80; + } + } +} + +void ipu_dither2(struct macroblock_rgb32* rgb32, struct macroblock_rgb16 *rgb16, int dte) +{ + int i, j; + for(i = 0; i < 16; ++i) { + for(j = 0; j < 16; ++j) { + rgb16->c[i][j].r = rgb32->c[i][j].r>>3; + rgb16->c[i][j].g = rgb32->c[i][j].g>>3; + rgb16->c[i][j].b = rgb32->c[i][j].b>>3; + rgb16->c[i][j].a = rgb32->c[i][j].a==0x40; + } + } +} + +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte) +{ + //SysPrintf("IPU: Dither not implemented"); +} + +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4){ + SysPrintf("IPU: VQ not implemented"); +} + +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16){ + unsigned char *s=(unsigned char*)mb8; + signed short *d=(signed short*)mb16; + int i; + for (i=0; i< 256; i++) *d++ = *s++; //Y bias - 16 + for (i=0; i< 64; i++) *d++ = *s++; //Cr bias - 128 + for (i=0; i< 64; i++) *d++ = *s++; //Cb bias - 128 + /*for(i = 0; i < 384/(16*6); ++i, s += 16*4, d += 16*4) { + __m128i r0, r1, r2, r3, r4, r5, r6, r7; + + r0 = _mm_load_si128((__m128i*)s); + r2 = _mm_load_si128((__m128i*)s+1); + r4 = _mm_load_si128((__m128i*)s+2); + r6 = _mm_load_si128((__m128i*)s+3); + + // signed shift + r1 = _mm_srai_epi16(_mm_unpackhi_epi8(r0, r0), 8); + r0 = _mm_srai_epi16(_mm_unpacklo_epi8(r0, r0), 8); + r3 = _mm_srai_epi16(_mm_unpackhi_epi8(r2, r2), 8); + r2 = _mm_srai_epi16(_mm_unpacklo_epi8(r2, r2), 8); + r5 = _mm_srai_epi16(_mm_unpackhi_epi8(r4, r4), 8); + r4 = _mm_srai_epi16(_mm_unpacklo_epi8(r4, r4), 8); + r7 = _mm_srai_epi16(_mm_unpackhi_epi8(r6, r6), 8); + r6 = _mm_srai_epi16(_mm_unpacklo_epi8(r6, r6), 8); + + _mm_store_si128((__m128i*)d, r0); + _mm_store_si128((__m128i*)d+1, r1); + _mm_store_si128((__m128i*)d+2, r2); + _mm_store_si128((__m128i*)d+3, r3); + _mm_store_si128((__m128i*)d+4, r4); + _mm_store_si128((__m128i*)d+5, r5); + _mm_store_si128((__m128i*)d+6, r6); + _mm_store_si128((__m128i*)d+7, r7); + }*/ +} + +///////////////////// IPU DMA //////////////////////// +void FIFOto_clear() +{ + //assert( g_BP.IFC == 0 ); + //memset(fifo_input,0,sizeof(fifo_input)); + g_BP.IFC = 0; + FIreadpos = 0; + FIwritepos = 0; +} + +int FIFOto_read(void *value) +{ + // wait until enough data + if( g_BP.IFC == 0 ) { + if( IPU1dma() == 0 ) + return 0; + + assert( g_BP.IFC > 0 ); + } + + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_input[FIreadpos]; fifo_input[FIreadpos] = 0; + ((u32*)value)[1] = fifo_input[FIreadpos+1]; fifo_input[FIreadpos+1] = 0; + ((u32*)value)[2] = fifo_input[FIreadpos+2]; fifo_input[FIreadpos+2] = 0; + ((u32*)value)[3] = fifo_input[FIreadpos+3]; fifo_input[FIreadpos+3] = 0; + FIreadpos = (FIreadpos + 4) & 31; + g_BP.IFC--; + return 1; +} + +int FIFOto_write(u32* pMem, int size) +{ + int transsize; + int firsttrans = min(size, 8-(int)g_BP.IFC); + + g_BP.IFC+=firsttrans; + transsize = firsttrans; + + while(transsize-- > 0) { + fifo_input[FIwritepos] = pMem[0]; + fifo_input[FIwritepos+1] = pMem[1]; + fifo_input[FIwritepos+2] = pMem[2]; + fifo_input[FIwritepos+3] = pMem[3]; + FIwritepos = (FIwritepos+4)&31; + pMem +=4; + } + + return firsttrans; +} + +#define IPU1chain() { \ + if(ipu1dma->qwc > 0) \ + { \ + int qwc = ipu1dma->qwc; \ + pMem = (u32*)dmaGetAddr(ipu1dma->madr); \ + if (pMem == NULL) { SysPrintf("ipu1dma NULL!\n"); return totalqwc; } \ + qwc = FIFOto_write(pMem, qwc); \ + ipu1dma->madr += qwc<< 4; \ + ipu1dma->qwc -= qwc; \ + totalqwc += qwc; \ + if( ipu1dma->qwc > 0 ) { \ + g_nDMATransfer |= IPU_DMA_ACTV1; \ + return totalqwc; \ + } \ + } \ +} + +int IPU1dma() +{ + u32 *ptag, *pMem; + int done=0; + int ipu1cycles = 0; + int totalqwc = 0; + + assert( !(ipu1dma->chcr&0x40) ); + + if( !(ipu1dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc > 0 ) { + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer&IPU_DMA_DOTIE1)) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + + if( (ipu1dma->chcr&0xc) == 0 ) { + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + else { + u32 tag = ipu1dma->chcr; // upper bits describe current tag + + if ((ipu1dma->chcr & 0x80) && (tag&0x80000000)) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(tag&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); +#ifdef IPU_LOG + IPU_LOG("dmaIrq Set\n"); +#endif + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + switch( tag&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, (1+totalqwc)*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, (1+totalqwc)*BIAS); + return totalqwc; + } + } + } + + if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) { // Normal Mode + //SysPrintf("ipu1 normal empty qwc?\n"); + return totalqwc; + } + + // Transfer Dn_QWC from Dn_MADR to GIF + + if ((ipu1dma->chcr & 0xc) == 0 || ipu1dma->qwc > 0) { // Normal Mode + IPU1chain(); + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + } + else { + // Chain Mode + //while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("IPU1 BUSERR\n"); + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return totalqwc; + } + ipu1cycles+=1; // Add 1 cycles from the QW read for the tag + + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + ipu1dma->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + //ipu1dma->madr = ptag[1]; //MADR = ADDR field + +#ifdef IPU_LOG + IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x\n", + ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); +#endif + + //done = hwDmacSrcChainWithStack(ipu1dma, id); + switch(ptag[0] & 0x70000000) { + case 0x00000000: // refe + // do not change tadr + ipu1dma->madr = ptag[1]; + done = 1; + break; + + case 0x10000000: // cnt + ipu1dma->madr = ipu1dma->tadr + 16; + // Set the taddr to the next tag + ipu1dma->tadr += 16 + (ipu1dma->qwc << 4); + break; + + case 0x20000000: // next + ipu1dma->madr = ipu1dma->tadr + 16; + ipu1dma->tadr = ptag[1]; + break; + + case 0x30000000: // ref + ipu1dma->madr = ptag[1]; + ipu1dma->tadr += 16; + break; + + case 0x70000000: // end + // do not change tadr + ipu1dma->madr = ipu1dma->tadr + 16; + done = 1; + break; + + default: + #ifdef IPU_LOG + IPU_LOG("ERROR: different transfer mode!, Please report to PCSX2 Team\n"); + #endif + break; + } + + if( ptag[0] & 0x80000000 ) + g_nDMATransfer |= IPU_DMA_DOTIE1; + else + g_nDMATransfer &= ~IPU_DMA_DOTIE1; + + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (ptag[0]&0x80000000) && ipu1dma->qwc == 0) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + if( done ) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(ptag[0]&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + //} + + if(ipu1dma->qwc == 0){ + switch( ptag[0]&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + } + } + } + + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; +} + + + + +int FIFOfrom_write(u32 *value,int size) +{ + int transsize; + int firsttrans; + + if((int)ipuRegs->ctrl.OFC >= 8) IPU0dma(); + + transsize = min(size,8-(int)ipuRegs->ctrl.OFC); + firsttrans = transsize; + + while(transsize-- > 0) { + fifo_output[FOwritepos] = ((u32*)value)[0]; + fifo_output[FOwritepos+1] = ((u32*)value)[1]; + fifo_output[FOwritepos+2] = ((u32*)value)[2]; + fifo_output[FOwritepos+3] = ((u32*)value)[3]; + FOwritepos = (FOwritepos+4)&31; + value += 4; + } + + ipuRegs->ctrl.OFC+=firsttrans; + IPU0dma(); + //SysPrintf("Written %d qwords, %d\n",firsttrans,ipuRegs->ctrl.OFC); + + return firsttrans; +} + +void FIFOfrom_read(void *value,int size) +{ + ipuRegs->ctrl.OFC -= size; + while(size > 0) + { + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_output[FOreadpos]; fifo_output[FOreadpos] = 0; + ((u32*)value)[1] = fifo_output[FOreadpos+1]; fifo_output[FOreadpos+1] = 0; + ((u32*)value)[2] = fifo_output[FOreadpos+2]; fifo_output[FOreadpos+2] = 0; + ((u32*)value)[3] = fifo_output[FOreadpos+3]; fifo_output[FOreadpos+3] = 0; + (u32*)value += 4; + FOreadpos = (FOreadpos + 4) & 31; + size--; + } +} + + +void FIFOfrom_readsingle(void *value) +{ + if(ipuRegs->ctrl.OFC > 0) + { + ipuRegs->ctrl.OFC --; + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_output[FOreadpos]; fifo_output[FOreadpos] = 0; + ((u32*)value)[1] = fifo_output[FOreadpos+1]; fifo_output[FOreadpos+1] = 0; + ((u32*)value)[2] = fifo_output[FOreadpos+2]; fifo_output[FOreadpos+2] = 0; + ((u32*)value)[3] = fifo_output[FOreadpos+3]; fifo_output[FOreadpos+3] = 0; + FOreadpos = (FOreadpos + 4) & 31; + } +} + +int IPU0dma() +{ + int readsize; + void* pMem; + + int qwc = ipu0dma->qwc; + u32 chcr = ipu0dma->chcr; + + if( !(ipu0dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc == 0) + return 0; + + assert( !(ipu0dma->chcr&0x40) ); + +#ifdef IPU_LOG + IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx\n", + ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc); +#endif + + assert((ipu0dma->chcr & 0xC) == 0 ); + pMem = (u32*)dmaGetAddr(ipu0dma->madr); + readsize = min(ipu0dma->qwc, (int)ipuRegs->ctrl.OFC); + FIFOfrom_read(pMem,readsize); + ipu0dma->madr += readsize<< 4; + ipu0dma->qwc -= readsize; // note: qwc is u16 + if(ipu0dma->qwc == 0) { + if ((psHu32(DMAC_CTRL) & 0x30) == 0x30) { // STS == fromIPU + psHu32(DMAC_STADR) = ipu0dma->madr; + switch (psHu32(DMAC_CTRL) & 0xC0) { + case 0x80: // GIF + g_nDMATransfer |= IPU_DMA_GIFSTALL; + break; + case 0x40: // VIF + g_nDMATransfer |= IPU_DMA_VIFSTALL; + break; + } + } + INT(DMAC_FROM_IPU,readsize*BIAS); + + } + + return readsize; +} + +void dmaIPU0() // fromIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +void dmaIPU1() // toIPU +{ + IPU1dma(); + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +extern void dmaGIF(); + +int ipu0Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu0Interrupt: %x\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT0 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT0; + } + + if( g_nDMATransfer & IPU_DMA_GIFSTALL ) { + // gif + g_nDMATransfer &= ~IPU_DMA_GIFSTALL; + if(((DMACh*)&PS2MEM_HW[0xA000])->chcr & 0x100) dmaGIF(); + } + + if( g_nDMATransfer & IPU_DMA_VIFSTALL ) { + // vif + g_nDMATransfer &= ~IPU_DMA_VIFSTALL; + if(((DMACh*)&PS2MEM_HW[0x9000])->chcr & 0x100)dmaVIF1(); + } + + if( g_nDMATransfer & IPU_DMA_TIE0 ) { + g_nDMATransfer &= ~IPU_DMA_TIE0; + } + + ipu0dma->chcr &= ~0x100; + + hwDmacIrq(DMAC_FROM_IPU); + + return 1; +} + +int ipu1Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu1Interrupt %x:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT1 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT1; + } + + if( g_nDMATransfer & IPU_DMA_TIE1 ) { + g_nDMATransfer &= ~IPU_DMA_TIE1; + }else + ipu1dma->chcr &= ~0x100; + + hwDmacIrq(DMAC_TO_IPU); + + return 1; +} diff --git a/branches/pcsx2_0.9.2/IPU/IPU.h b/branches/pcsx2_0.9.2/IPU/IPU.h new file mode 100644 index 0000000..9f5e538 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/IPU.h @@ -0,0 +1,204 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IPU_H__ +#define __IPU_H__ + +#include "Common.h" + +#ifdef __WIN32__ +#pragma pack(1) +#endif + +// +// Bitfield Structure +// +typedef union { + struct { + u32 OPTION : 28; // VDEC decoded value + u32 CMD : 4; // last command + u32 _BUSY; + }; + struct { + u32 DATA; + u32 BUSY; + }; +} tIPU_CMD; + +#define IPU_CTRL_IFC_M (0x0f<< 0) +#define IPU_CTRL_OFC_M (0x0f<< 4) +#define IPU_CTRL_CBP_M (0x3f<< 8) +#define IPU_CTRL_ECD_M (0x01<<14) +#define IPU_CTRL_SCD_M (0x01<<15) +#define IPU_CTRL_IDP_M (0x03<<16) +#define IPU_CTRL_AS_M (0x01<<20) +#define IPU_CTRL_IVF_M (0x01<<21) +#define IPU_CTRL_QST_M (0x01<<22) +#define IPU_CTRL_MP1_M (0x01<<23) +#define IPU_CTRL_PCT_M (0x07<<24) +#define IPU_CTRL_RST_M (0x01<<30) +#define IPU_CTRL_BUSY_M (0x01<<31) + +#define IPU_CTRL_IFC_O ( 0) +#define IPU_CTRL_OFC_O ( 4) +#define IPU_CTRL_CBP_O ( 8) +#define IPU_CTRL_ECD_O (14) +#define IPU_CTRL_SCD_O (15) +#define IPU_CTRL_IDP_O (16) +#define IPU_CTRL_AS_O (20) +#define IPU_CTRL_IVF_O (21) +#define IPU_CTRL_QST_O (22) +#define IPU_CTRL_MP1_O (23) +#define IPU_CTRL_PCT_O (24) +#define IPU_CTRL_RST_O (30) +#define IPU_CTRL_BUSY_O (31) + + +// +// Bitfield Structure +// +typedef union { + struct { + u32 IFC : 4; // Input FIFO counter + u32 OFC : 4; // Output FIFO counter + u32 CBP : 6; // Coded block pattern + u32 ECD : 1; // Error code pattern + u32 SCD : 1; // Start code detected + u32 IDP : 2; // Intra DC precision + u32 resv0 : 2; + u32 AS : 1; // Alternate scan + u32 IVF : 1; // Intra VLC format + u32 QST : 1; // Q scale step + u32 MP1 : 1; // MPEG1 bit strea + u32 PCT : 3; // Picture Type + u32 resv1 : 3; + u32 RST : 1; // Reset + u32 BUSY : 1; // Busy + }; + u32 _u32; +} tIPU_CTRL; + +#define IPU_BP_BP_M (0x7f<< 0) +#define IPU_BP_IFC_M (0x0f<< 8) +#define IPU_BP_FP_M (0x03<<16) + +#define IPU_BP_BP_O ( 0) +#define IPU_BP_IFC_O ( 8) +#define IPU_BP_FP_O (16) + + +// +// Bitfield Structure +// +typedef struct { + u32 BP; // Bit stream point + u16 IFC; // Input FIFO counter + u8 FP; // FIFO point + u8 bufferhasnew; +} tIPU_BP; + +#ifdef __WIN32__ +#pragma pack() +#endif + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 3; + u32 DTD : 1; + u32 SGN : 1; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_IDEC; + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 4; + u32 DT : 1; + u32 DCR : 1; + u32 MBI : 1; + u32 cmd : 4; +} tIPU_CMD_BDEC; + +typedef struct { + u32 MBC :11; + u32 UN2 :15; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_CSC; + +#define SCE_IPU_BCLR 0x0 +#define SCE_IPU_IDEC 0x1 +#define SCE_IPU_BDEC 0x2 +#define SCE_IPU_VDEC 0x3 +#define SCE_IPU_FDEC 0x4 +#define SCE_IPU_SETIQ 0x5 +#define SCE_IPU_SETVQ 0x6 +#define SCE_IPU_CSC 0x7 +#define SCE_IPU_PACK 0x8 +#define SCE_IPU_SETTH 0x9 + +typedef struct { + tIPU_CMD cmd; + u32 dummy0[2]; + tIPU_CTRL ctrl; + u32 dummy1[3]; + u32 ipubp; + u32 dummy2[3]; + u32 top; + u32 topbusy; + u32 dummy3[2]; +} IPUregisters, *PIPUregisters; + +#define ipuRegs ((IPUregisters*)(PS2MEM_HW+0x2000)) + +void dmaIPU0(); +void dmaIPU1(); + +int ipuInit(); +void ipuReset(); +void ipuShutdown(); +int ipuFreeze(gzFile f, int Mode); +BOOL ipuCanFreeze(); + +u32 ipuRead32(u32 mem); +int ipuConstRead32(u32 x86reg, u32 mem); + +u64 ipuRead64(u32 mem); +void ipuConstRead64(u32 mem, int mmreg); + +void ipuWrite32(u32 mem,u32 value); +void ipuConstWrite32(u32 mem, int mmreg); + +void ipuWrite64(u32 mem,u64 value); +void ipuConstWrite64(u32 mem, int mmreg); + +int ipu0Interrupt(); +int ipu1Interrupt(); + +u8 getBits32(u8 *address, u32 advance); +u8 getBits16(u8 *address, u32 advance); +u8 getBits8(u8 *address, u32 advance); +int getBits(u8 *address, u32 size, u32 advance); + +#endif diff --git a/branches/pcsx2_0.9.2/IPU/Makefile.am b/branches/pcsx2_0.9.2/IPU/Makefile.am new file mode 100644 index 0000000..628f4ce --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I../ -I../x86 +noinst_LIBRARIES = libIPU.a + +libIPU_a_SOURCES = IPU.c IPU.h yuv2rgb.c yuv2rgb.h + +SUBDIRS = mpeg2lib + +LDADD = libmpeg2IPU.a \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/IPU/idct_mmx.obj b/branches/pcsx2_0.9.2/IPU/idct_mmx.obj new file mode 100644 index 0000000000000000000000000000000000000000..9f7d3136085bf4a54addc94ef8f77313e62d4963 GIT binary patch literal 11510 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 HNu%)(hlkEg literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.2/IPU/mpeg2lib/Idct.c b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Idct.c new file mode 100644 index 0000000..6529956 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Idct.c @@ -0,0 +1,302 @@ +/* + * idct.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//#include +#include "Common.h" +#include "ix86/ix86.h" + +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ +#define clp(val,res) res = (val < 0) ? 0 : ((val > 255) ? 255 : val); +#define clp2(val,res) res = (val < -255) ? -255 : ((val > 255) ? 255 : val); +/* idct main entry point */ +void (* mpeg2_idct_copy) (s16 * block, u8 * dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16 * dest, int stride); + +/* + * In legal streams, the IDCT output should be between -384 and +384. + * In corrupted streams, it is possible to force the IDCT output to go + * to +-3826 - this is the worst case for a column IDCT where the + * column inputs are 16-bit values. + */ +static u8 clip_lut[1024]; +#define CLIP(i) ((clip_lut+384)[(i)]) + +#if 0 +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + t0 = W0*d0 + W1*d1; \ + t1 = W0*d1 - W1*d0; \ +} while (0) +#else +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + int tmp = W0 * (d0 + d1); \ + t0 = tmp + (W1 - W0) * d1; \ + t1 = tmp - (W1 + W0) * d0; \ +} while (0) +#endif + +static void idct_row (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + /* shortcut */ + if (!(block[1] | ((s32 *)block)[1] | ((s32 *)block)[2] | + ((s32 *)block)[3])) { + u32 tmp = (u16) (block[0] << 3); + tmp |= tmp << 16; + ((s32 *)block)[0] = tmp; + ((s32 *)block)[1] = tmp; + ((s32 *)block)[2] = tmp; + ((s32 *)block)[3] = tmp; + return; + } + + d0 = (block[0] << 11) + 128; + d1 = block[1]; + d2 = block[2] << 11; + d3 = block[3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[4]; + d1 = block[5]; + d2 = block[6]; + d3 = block[7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) * 181) >> 8; + b2 = ((t0 - t1) * 181) >> 8; + + block[0] = (a0 + b0) >> 8; + block[1] = (a1 + b1) >> 8; + block[2] = (a2 + b2) >> 8; + block[3] = (a3 + b3) >> 8; + block[4] = (a3 - b3) >> 8; + block[5] = (a2 - b2) >> 8; + block[6] = (a1 - b1) >> 8; + block[7] = (a0 - b0) >> 8; +} + +static void idct_col (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + d0 = (block[8*0] << 11) + 65536; + d1 = block[8*1]; + d2 = block[8*2] << 11; + d3 = block[8*3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[8*4]; + d1 = block[8*5]; + d2 = block[8*6]; + d3 = block[8*7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 = (t0 - t2) >> 8; + t1 = (t1 - t3) >> 8; + b1 = (t0 + t1) * 181; + b2 = (t0 - t1) * 181; + + block[8*0] = (a0 + b0) >> 17; + block[8*1] = (a1 + b1) >> 17; + block[8*2] = (a2 + b2) >> 17; + block[8*3] = (a3 + b3) >> 17; + block[8*4] = (a3 - b3) >> 17; + block[8*5] = (a2 - b2) >> 17; + block[8*6] = (a1 - b1) >> 17; + block[8*7] = (a0 - b0) >> 17; +} + +static void mpeg2_idct_copy_c (s16 * block, u8 * dest, + const int stride) +{ + int i; + + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = CLIP (block[0]); + dest[1] = CLIP (block[1]); + dest[2] = CLIP (block[2]); + dest[3] = CLIP (block[3]); + dest[4] = CLIP (block[4]); + dest[5] = CLIP (block[5]); + dest[6] = CLIP (block[6]); + dest[7] = CLIP (block[7]); + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void mpeg2_idct_add_c (const int last, s16 * block, + /*u8*/s16 * dest, const int stride) +{ + int i; + + if (last != 129 || (block[0] & 7) == 4) { + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = block[0]; + dest[1] = block[1]; + dest[2] = block[2]; + dest[3] = block[3]; + dest[4] = block[4]; + dest[5] = block[5]; + dest[6] = block[6]; + dest[7] = block[7]; + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); + } else { + int DC; + + DC = (block[0] + 4) >> 3; + block[0] = block[63] = 0; + i = 8; + do { + dest[0] = DC; + dest[1] = DC; + dest[2] = DC; + dest[3] = DC; + dest[4] = DC; + dest[5] = DC; + dest[6] = DC; + dest[7] = DC; + dest += stride; + } while (--i); + } +} + +u8 mpeg2_scan_norm[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +u8 mpeg2_scan_alt[64] = { + /* Alternate scan pattern */ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* idct_mmx.c */ +void mpeg2_idct_copy_mmxext (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmxext (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_copy_mmx (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmx (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_mmx_init (void); + +void mpeg2_idct_init() +{ +#ifndef __VCNET2005__ + int i, j; + +/* if(hasMultimediaExtensions == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmx; + mpeg2_idct_add = mpeg2_idct_add_mmx; + mpeg2_idct_mmx_init (); + }else if(hasMultimediaExtensionsExt == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmxext; + mpeg2_idct_add = mpeg2_idct_add_mmxext; + mpeg2_idct_mmx_init (); + }else*/ + { + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } + } + +#else //blah vcnet2005 idiocity :D + int i,j; + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } +#endif +} diff --git a/branches/pcsx2_0.9.2/IPU/mpeg2lib/Makefile.am b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Makefile.am new file mode 100644 index 0000000..b5a6f10 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Makefile.am @@ -0,0 +1,4 @@ +INCLUDES = -I../ -I../../ -I../../x86 +noinst_LIBRARIES = libmpeg2IPU.a + +libmpeg2IPU_a_SOURCES = Idct.c Mpeg.c Mpeg.h Vlc.h \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.c b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.c new file mode 100644 index 0000000..fc8ba6d --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.c @@ -0,0 +1,1281 @@ +/* + * Mpeg.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Mpeg.h" +#include "Vlc.h" + +#define BigEndian _byteswap_ulong + +extern void (* mpeg2_idct_copy) (s16 * block, u8* dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +extern void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16* dest, int stride); + +extern int FIFOfrom_write(u32* value, int size); + +/* JayteeMaster: remove static attribute */ +/*static */int non_linear_quantizer_scale [] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +extern tIPU_BP g_BP; + +/* Bitstream and buffer needs to be realocated inorder for sucessful + reading of the old data. Here the old data stored in the 2nd slot + of the internal buffer is copied to 1st slot, and the new data read + into 1st slot is copied to the 2nd slot. Which will later be copied + back to the 1st slot when 128bits have been read. +*/ +extern void ReorderBitstream(); + +int get_macroblock_modes (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int macroblock_modes; + const MBtab * tab; + + switch (decoder->coding_type) { + case I_TYPE: + + macroblock_modes = UBITS (bit_buf, 2); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_I + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if ((! (decoder->frame_pred_frame_dct)) && + (decoder->picture_structure == FRAME_PICTURE)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes; + + case P_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_P + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case B_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + tab = MB_B + macroblock_modes; + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (! (macroblock_modes & MACROBLOCK_INTRA)) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_INTRA) + goto intra; + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + intra: + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case D_TYPE: + + macroblock_modes = UBITS (bit_buf, 1); + if( macroblock_modes == 0 ) + return 0; // error + DUMPBITS (bit_buf, bits, 1); + return MACROBLOCK_INTRA; + + default: + return 0; + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_quantizer_scale (decoder_t * const decoder) +{ + int quantizer_scale_code; + + quantizer_scale_code = UBITS (decoder->bitstream_buf, 5); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 5); + + if (decoder->q_scale_type) return non_linear_quantizer_scale [quantizer_scale_code]; + else return quantizer_scale_code << 1; +} + +static int get_coded_block_pattern (decoder_t * const decoder) +{ + const CBPtab * tab; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + if (decoder->bitstream_buf >= 0x20000000) { + tab = CBP_7 + (UBITS (decoder->bitstream_buf, 7) - 16); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; + } + + tab = CBP_9 + UBITS (decoder->bitstream_buf, 9); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; +} + +static int get_luma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_lum_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 3); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_chroma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 2); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define SATURATE(val) \ +do { \ + if (((u32)(val + 2048) > 4095)) \ + val = SBITS (val, 1) ^ 2047; \ +} while (0) + +static void get_intra_block_B14 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static void get_intra_block_B15 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x04000000) { + + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) { + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + /* if (i >= 128) break; */ /* end of block */ + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check against buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + } else if (bit_buf >= 0x02000000) { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>28) != 0x6 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_non_intra_block (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + s16 * dest; + + i = -1; + mismatch = 1; + dest = decoder->DCTblock; + + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void get_mpeg1_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = 0; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_mpeg1_non_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = -1; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + val = 2 * (val + SBITS (val, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +} + +static void slice_intra_DCT (decoder_t * const decoder, const int cc, + u8 * const dest, const int stride) +{ + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + /* Get the intra DC coefficient and inverse quantize it */ + if (cc == 0) decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); + else decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[cc] << (3 - decoder->intra_dc_precision); + + if (decoder->mpeg1) get_mpeg1_intra_block (decoder); + else if (decoder->intra_vlc_format){ + get_intra_block_B15 (decoder); + }else{ + get_intra_block_B14 (decoder); + } + + mpeg2_idct_copy (decoder->DCTblock, dest, stride); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void slice_non_intra_DCT (decoder_t * const decoder, + /*u8*/s16 * const dest, const int stride){ + int last; + memset(decoder->DCTblock,0,sizeof(decoder->DCTblock)); + if (decoder->mpeg1) last = get_mpeg1_non_intra_block (decoder); + else last = get_non_intra_block (decoder); + + mpeg2_idct_add (last, decoder->DCTblock, dest, stride); +} + +extern int coded_block_pattern; +extern u8 FillInternalBuffer(u32 * pointer, u32 advance); +extern decoder_t g_decoder; +extern int g_nIPU0Data; // or 0x80000000 whenever transferring +extern u8* g_pIPU0Pointer; + +void mpeg2sliceIDEC(void* pdone) +{ + u32 read; + decoder_t * decoder = &g_decoder; + + *(int*)pdone = 0; + bitstream_init(decoder); + + decoder->dc_dct_pred[0] = + decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + decoder->mbc=0; + + if (UBITS (decoder->bitstream_buf, 2) == 0) + { + ipuRegs->ctrl.SCD = 0; + }else{ + while (1) { + int DCT_offset, DCT_stride; + int mba_inc; + const MBAtab * mba; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + decoder->macroblock_modes = get_macroblock_modes (decoder); + + /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ + if (decoder->macroblock_modes & MACROBLOCK_QUANT)//only IDEC + decoder->quantizer_scale = get_quantizer_scale (decoder); + + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + + memset(decoder->mb8,0,sizeof(struct macroblock_8)); + memset(decoder->rgb32,0,sizeof(struct rgb32)); + + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + + // Send The MacroBlock via DmaIpuFrom + if (decoder->ofm==0){ + ipu_csc(decoder->mb8, decoder->rgb32, decoder->sgn); + + g_nIPU0Data = 64; + g_pIPU0Pointer = (u8*)decoder->rgb32; + while(g_nIPU0Data > 0) { + read = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + co_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + else{ + //ipu_dither(decoder->mb8, decoder->rgb16, decoder->dte); + ipu_csc(decoder->mb8, decoder->rgb32, decoder->dte); + ipu_dither2(decoder->rgb32, decoder->rgb16, decoder->dte); + + g_nIPU0Data = 32; + g_pIPU0Pointer = (u8*)decoder->rgb16; + while(g_nIPU0Data > 0) { + read = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ){ + co_resume(); + } + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + decoder->mbc++; + } + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + mba_inc = 0; + while (1) { + if (decoder->bitstream_buf >= 0x10000000) { + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + break; + } else if (decoder->bitstream_buf >= 0x03000000) { + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + break; + } else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + mba_inc += 33; + /* pass through */ + case 15: /* macroblock_stuffing (MPEG1 only) */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + continue; + default: /* end of slice/frame, or error? */ + { + int i; + ipuRegs->ctrl.SCD = 1; + ipuRegs->ctrl.ECD=0; + coded_block_pattern=decoder->coded_block_pattern; + + for (i=0; i<2; i++) { + u8 byte; + while(!getBits8(&byte, 0)) + co_resume(); + if (byte == 0) break; + g_BP.BP+= 8; + } + g_BP.BP-=32;//bitstream_init takes 32 bits + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + co_resume(); + } + ipuRegs->top = BigEndian(ipuRegs->top); + + *(int*)pdone = 1; + co_exit(); + } + } + } + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + mba_inc += mba->mba; + + if (mba_inc) { + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + do { + decoder->mbc++; + } while (--mba_inc); + } + } + } + + ipuRegs->ctrl.ECD=!ipuRegs->ctrl.SCD; + + coded_block_pattern=decoder->coded_block_pattern; + + g_BP.BP-=32;//bitstream_init takes 32 bits + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + co_resume(); + } + ipuRegs->top = BigEndian(ipuRegs->top); + + *(int*)pdone = 1; + co_exit(); +} + +void mpeg2_slice(void* pdone) +{ + int DCT_offset, DCT_stride; + u8 bit8=0; + u32 fp = g_BP.FP; + u32 bp; + decoder_t * decoder = &g_decoder; + u32 size = 0; + + *(int*)pdone = 0; + ipuRegs->ctrl.ECD = 0; + + memset(decoder->mb8,0,sizeof(struct macroblock_8)); + memset(decoder->mb16,0,sizeof(struct macroblock_16)); + + bitstream_init (decoder); + + if (decoder->dcr) + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + ipu_copy(decoder->mb8,decoder->mb16); + } else { + if (decoder->macroblock_modes & MACROBLOCK_PATTERN) { + decoder->coded_block_pattern = get_coded_block_pattern (decoder); + /* JayteeMaster: changed from mb8 to mb16 and from u8 to s16 */ + if (decoder->coded_block_pattern & 0x20) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y, DCT_stride); + if (decoder->coded_block_pattern & 0x10) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x08) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset, DCT_stride); + if (decoder->coded_block_pattern & 0x04) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x2) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cb, decoder->stride>>1); + if (decoder->coded_block_pattern & 0x1) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cr, decoder->stride>>1); + + } + } + + //Send The MacroBlock via DmaIpuFrom + size = 0; // Reset + + ipuRegs->ctrl.SCD=0; + coded_block_pattern=decoder->coded_block_pattern; + + //FillInternalBuffer(&g_BP.BP, 1); + + bp = g_BP.BP; + g_BP.BP+=decoder->bitstream_bits-16; + + // BP goes from 0 to 128, so negative values mean to read old buffer + // so we minus from 128 to get the correct BP + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + decoder->mbc = 1; + g_nIPU0Data = 48; + g_pIPU0Pointer = (u8*)decoder->mb16; + while(g_nIPU0Data > 0) { + size = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( size == 0 ) + co_resume(); + else { + g_pIPU0Pointer += size*16; + g_nIPU0Data -= size; + } + } + + IPU_LOG("BDEC %x, %d\n",g_BP.BP,g_BP.FP); + + while( !getBits8((u8*)&bit8, 0) ) + co_resume(); + if (bit8==0) ipuRegs->ctrl.SCD = 1; + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + co_resume(); + } + ipuRegs->top = BigEndian(ipuRegs->top); + + *(int*)pdone = 1; + co_exit(); +} + +int get_motion_delta (decoder_t * const decoder, + const int f_code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int delta; + int sign; + const MVtab * tab; + + if ( (bit_buf & 0x80000000) ) { + DUMPBITS (bit_buf, bits, 1); + return 0x00010000; + } else if ( (bit_buf & 0xf0000000) || ((bit_buf & 0xfc000000)==0x0c000000) ) { + + tab = MV_4 + UBITS (bit_buf, 4); + delta = (tab->delta << f_code) + 1; + bits += tab->len + f_code + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + delta += UBITS (bit_buf, f_code); + bit_buf <<= f_code; + + return (delta ^ sign) - sign; + + } else { + + tab = MV_10 + UBITS (bit_buf, 10); + delta = (tab->delta << f_code) + 1; + bits += tab->len + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) { + NEEDBITS (bit_buf, bits, bit_ptr); + delta += UBITS (bit_buf, f_code); + DUMPBITS (bit_buf, bits, f_code); + } + + return (delta ^ sign) - sign; + + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_dmv (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DMVtab * tab; + + tab = DMV_2 + UBITS (bit_buf, 2); + DUMPBITS (bit_buf, bits, tab->len); + return tab->dmv; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_macroblock_address_increment(decoder_t * const decoder){ + const MBAtab *mba; + + if (decoder->bitstream_buf >= 0x10000000) + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + else if (decoder->bitstream_buf >= 0x03000000) + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x23; + case 15: /* macroblock_stuffing (MPEG1 only) */ + if (decoder->mpeg1){ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x22; + } + default: + return 0;//error + } + + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + return mba->mba + 1; +} diff --git a/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.h b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.h new file mode 100644 index 0000000..297e50a --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Mpeg.h @@ -0,0 +1,186 @@ +/* + * Mpeg.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MPEG_H__ +#define __MPEG_H__ + +#include "Common.h" + +/* macroblock modes */ +#define MACROBLOCK_INTRA 1 +#define MACROBLOCK_PATTERN 2 +#define MACROBLOCK_MOTION_BACKWARD 4 +#define MACROBLOCK_MOTION_FORWARD 8 +#define MACROBLOCK_QUANT 16 +#define DCT_TYPE_INTERLACED 32 +/* motion_type */ +#define MOTION_TYPE_SHIFT 6 +#define MOTION_TYPE_MASK (3*64) +#define MOTION_TYPE_BASE 64 +#define MC_FIELD (1*64) +#define MC_FRAME (2*64) +#define MC_16X8 (2*64) +#define MC_DMV (3*64) + +/* picture structure */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +/* picture coding type */ +#define I_TYPE 1 +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +struct macroblock_8{ + unsigned char Y[16][16]; //0 + unsigned char Cb[8][8]; //1 + unsigned char Cr[8][8]; //2 +}; + +struct macroblock_16{ + short Y[16][16]; //0 + short Cb[8][8]; //1 + short Cr[8][8]; //2 +}; + +struct rgb32{ + unsigned char r, g, b, a; +}; + +struct macroblock_rgb32{ + struct rgb32 c[16][16]; +}; + +struct rgb16{ + unsigned short r:5, g:5, b:5, a:1; +}; + +struct macroblock_rgb16{ + struct rgb16 c[16][16]; +}; + +struct decoder_s { + /* first, state that carries information from one macroblock to the */ + /* next inside a slice, and is never used outside of mpeg2_slice() */ + + /* DCT coefficients - should be kept aligned ! */ + s16 DCTblock[64]; + + /* bit parsing stuff */ + u32 bitstream_buf; /* current 32 bit working set */ + int bitstream_bits; /* used bits in working set */ + u8 * bitstream_ptr; /* buffer with stream data; 128 bits buffer */ + + struct macroblock_8 *mb8; + struct macroblock_16 *mb16; + struct macroblock_rgb32 *rgb32; + struct macroblock_rgb16 *rgb16; + + int stride; + + /* predictor for DC coefficients in intra blocks */ + s16 dc_dct_pred[3]; + + int quantizer_scale; /* remove */ + int dmv_offset; /* remove */ + + /* now non-slice-specific information */ + + /* sequence header stuff */ + u8 *intra_quantizer_matrix; + u8 *non_intra_quantizer_matrix; + + /* picture header stuff */ + + /* what type of picture this is (I, P, B, D) */ + int coding_type; + + /* picture coding extension stuff */ + + /* quantization factor for intra dc coefficients */ + int intra_dc_precision; + /* top/bottom/both fields */ + int picture_structure; + /* bool to indicate all predictions are frame based */ + int frame_pred_frame_dct; + /* bool to indicate whether intra blocks have motion vectors */ + /* (for concealment) */ + int concealment_motion_vectors; + /* bit to indicate which quantization table to use */ + int q_scale_type; + /* bool to use different vlc tables */ + int intra_vlc_format; + /* used for DMV MC */ + int top_field_first; + // Pseudo Sign Offset + int sgn; + // Dither Enable + int dte; + // Output Format + int ofm; + // Macroblock count + int mbc; + // Macroblock type + int macroblock_modes; + // DC Reset + int dcr; + // Coded block pattern + int coded_block_pattern; + + /* stuff derived from bitstream */ + + /* pointer to the zigzag scan we're supposed to be using */ + const u8 * scan; + + int second_field; + + int mpeg1; +}; + +typedef struct decoder_s decoder_t; + +#define IDEC 0 +#define BDEC 1 +void mpeg2sliceIDEC(void* pdone); +void mpeg2_slice(void* pdone); +int get_macroblock_address_increment(decoder_t * const decoder); +int get_macroblock_modes (decoder_t * const decoder); +int get_motion_delta (decoder_t * const decoder, + const int f_code); +int get_dmv (decoder_t * const decoder); +int non_linear_quantizer_scale[]; // JayteeMaster: it is needed in Ipu.c + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn); +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte); +void ipu_dither2(struct macroblock_rgb32* rgb32, struct macroblock_rgb16 *rgb16, int dte); +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4); +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16); + +int slice (decoder_t * const decoder, u8 * buffer); +/* idct.c */ +void mpeg2_idct_init (); + +#endif//__MPEG_H__ diff --git a/branches/pcsx2_0.9.2/IPU/mpeg2lib/Vlc.h b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Vlc.h new file mode 100644 index 0000000..02f0881 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/mpeg2lib/Vlc.h @@ -0,0 +1,441 @@ +/* + * vlc.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VLC_H__ +#define __VLC_H__ + +#include "IPU.h" +#include "pcl/pcl.h" + +static u8 data[2]; +static u8 dword[4]; +static void GETWORD(u32 * bit_buf,int bits) +{ + while(!getBits16(data,1)) + co_resume(); + *bit_buf |= ((data[0] << 8) | data[1]) << (bits); +} + +static void bitstream_init (decoder_t * decoder){ + decoder->bitstream_bits = -16; + + while( !getBits32(dword, 1) ) + co_resume(); + + decoder->bitstream_buf = (dword[0] << 24) | (dword[1] << 16) | + (dword[2] << 8) |dword[3]; +} + +/* make sure that there are at least 16 valid bits in bit_buf */ +#define NEEDBITS(bit_buf,bits,bit_ptr) \ +do { \ + if (bits > 0) { \ + GETWORD(&bit_buf,bits); \ + bits -= 16; \ + } \ +} while (0) + +/* remove num valid bits from bit_buf */ +#define DUMPBITS(bit_buf,bits,num) \ +do { \ + /*IPU_LOG("DUMPBITS %d\n",num);*/ \ + bit_buf <<= (num); \ + bits += (num); \ +} while (0) + +/* take num bits from the high part of bit_buf and zero extend them */ +#define UBITS(bit_buf,num) (((u32)(bit_buf)) >> (32 - (num))) + +/* take num bits from the high part of bit_buf and sign extend them */ +#define SBITS(bit_buf,num) (((s32)(bit_buf)) >> (32 - (num))) + +typedef struct { + u8 modes; + u8 len; +} MBtab; + +typedef struct { + u8 delta; + u8 len; +} MVtab; + +typedef struct { + s8 dmv; + u8 len; +} DMVtab; + +typedef struct { + u8 cbp; + u8 len; +} CBPtab; + +typedef struct { + u8 size; + u8 len; +} DCtab; + +typedef struct { + u8 run; + u8 level; + u8 len; +} DCTtab; + +typedef struct { + u8 mba; + u8 len; +} MBAtab; + + +#define INTRA MACROBLOCK_INTRA +#define QUANT MACROBLOCK_QUANT + +static const MBtab MB_I [] = { + {INTRA|QUANT, 2}, {INTRA, 1} +}; + +#define MC MACROBLOCK_MOTION_FORWARD +#define CODED MACROBLOCK_PATTERN + +static const MBtab MB_P [] = { + {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, + {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} +}; + +#define FWD MACROBLOCK_MOTION_FORWARD +#define BWD MACROBLOCK_MOTION_BACKWARD +#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD + +static const MBtab MB_B [] = { + {0, 0}, {INTRA|QUANT, 6}, + {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, + {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, + {INTRA, 5}, {INTRA, 5}, + {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, + {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} +}; + +#undef INTRA +#undef QUANT +#undef MC +#undef CODED +#undef FWD +#undef BWD +#undef INTER + + +static const MVtab MV_4 [] = { + { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} +}; + +static const MVtab MV_10 [] = { + { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, + { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, + {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, + { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, + { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, + { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} +}; + + +static const DMVtab DMV_2 [] = { + { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} +}; + + +static const CBPtab CBP_7 [] = { + {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7}, + {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7}, + {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6}, + {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6}, + {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, + {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, + {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, + {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, + {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, + {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, + {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, + {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, + {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, + {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, + {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, + {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3} +}; + +static const CBPtab CBP_9 [] = { + {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9}, + {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9}, + {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8}, + {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8}, + {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8}, + {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8}, + {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8}, + {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8}, + {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8}, + {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8}, + {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8}, + {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8}, + {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8}, + {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8}, + {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8}, + {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8} +}; + +static const DCtab DC_lum_5 [] = { + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} +}; + +static const DCtab DC_chrom_5 [] = { + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} +}; + +static const DCtab DC_long [] = { + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} +}; + + +static const DCTtab DCT_16 [] = { + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, + { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, + { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, + { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} +}; + +static const DCTtab DCT_15 [] = { + { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, + { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, + { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, + { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, + { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, + { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, + { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, + { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, + { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, + { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, + { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, + { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} +}; + +static const DCTtab DCT_13 [] = { + { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, + { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, + { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, + { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, + { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, + { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, + { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, + { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, + { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, + { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, + { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, + { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} +}; + +static const DCTtab DCT_B14_10 [] = { + { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, + { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} +}; + +static const DCTtab DCT_B14_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, + { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, + { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, + { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, + { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} +}; + +static const DCTtab DCT_B14AC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} +}; + +static const DCTtab DCT_B14DC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} +}; + +static const DCTtab DCT_B15_10 [] = { + { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, + { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} +}; + +static const DCTtab DCT_B15_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, + { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, + { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, + { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, + { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, + { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, + { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, + { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} +}; + + +static const MBAtab MBA_5 [] = { + {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} +}; + +static const MBAtab MBA_11 [] = { + {32, 11}, {31, 11}, {30, 11}, {29, 11}, + {28, 11}, {27, 11}, {26, 11}, {25, 11}, + {24, 11}, {23, 11}, {22, 11}, {21, 11}, + {20, 10}, {20, 10}, {19, 10}, {19, 10}, + {18, 10}, {18, 10}, {17, 10}, {17, 10}, + {16, 10}, {16, 10}, {15, 10}, {15, 10}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} +}; +#endif//__VLC_H__ diff --git a/branches/pcsx2_0.9.2/IPU/yuv2rgb.asm b/branches/pcsx2_0.9.2/IPU/yuv2rgb.asm new file mode 100644 index 0000000..c571420 --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/yuv2rgb.asm @@ -0,0 +1,242 @@ +;/******************************************************** +; * Some code. Copyright (C) 2003 by Pascal Massimino. * +; * All Rights Reserved. (http://skal.planet-d.net) * +; * For Educational/Academic use ONLY. See 'LICENSE.TXT'.* +; ********************************************************/ +;////////////////////////////////////////////////////////// +;// NASM macros +;////////////////////////////////////////////////////////// + +%ifdef LINUX + +;////////////////////////////////////////////////////////// +; LINUX / egcs / macros +;////////////////////////////////////////////////////////// + +%macro extrn 1 + extern %1 + %define %1 %1 +%endmacro +%macro globl 1 + global %1 + %define %1 %1 +%endmacro + +%macro DATA 0 +[section data align=16 write alloc USE32] +%endmacro +%macro TEXT 0 +[section text align=16 nowrite alloc exec USE32] +%endmacro + +%endif ; LINUX + +;////////////////////////////////////////////////////////// + +%ifdef WIN32 + +%macro extrn 1 + extern _%1 + %define %1 _%1 +%endmacro + +%macro globl 1 + global _%1 + %define %1 _%1 +%endmacro + +%macro DATA 0 +[section .data align=16 write alloc USE32] +%endmacro +%macro TEXT 0 +[section .text align=16 nowrite alloc exec USE32] +%endmacro + +%endif ; WIN32 + +;////////////////////////////////////////////////////////// +; +; MACRO for timing. NASM. +; Total additional code size is 0xb0. +; this keep code alignment right. + +extrn Skl_Cur_Count_ +extrn Skl_Print_Tics + +%macro SKL_USE_RDSTC 0 +extrn SKL_RDTSC_0_ASM +extrn SKL_RDTSC_1_ASM +extrn SKL_RDTSC_2_ASM +%endmacro +%define SKL_RDTSC_OFFSET 15 ; check value with skl_rdtsc.h... + +%macro SKL_RDTSC_IN 0 + SKL_USE_RDSTC + call SKL_RDTSC_0_ASM +.Skl_RDTSC_Loop_: + call SKL_RDTSC_1_ASM +%endmacro + +%macro SKL_RDTSC_OUT 0 + call SKL_RDTSC_2_ASM + dec dword [Skl_Cur_Count_] + jge near .Skl_RDTSC_Loop_ + push dword 53 + call Skl_Print_Tics +%endmacro + +;////////////////////////////////////////////////////////// + +globl Skl_YUV_To_RGB32_MMX + +;////////////////////////////////////////////////////////////////////// + + ; eax: *U + ; ebx: *V + ; esi: *Y + ; edx: Src_BpS + ; edi: *Dst + ; ebx: Dst_BpS + ; ecx: Counter + +%define RGBp esp+20 +%define Yp esp+16 +%define Up esp+12 +%define Vp esp+8 +%define xCnt esp+4 +%define yCnt esp+0 + +Skl_YUV_To_RGB32_MMX: + + push ebx + push esi + push edi + push ebp + + mov edi, [esp+4 +16] ; RGB + mov ebp, [esp+12 +16] ; Y + mov eax, [esp+16 +16] ; U + mov ebx, [esp+20 +16] ; V + mov edx, [esp+24 +16] ; Src_BpS + mov ecx, [esp+28 +16] ; Width + + lea edi, [edi+4*ecx] ; RGB += Width*sizeof(32b) + lea ebp, [ebp+ecx] ; ebp: Y1 = Y + Width + add edx, ebp ; edx: Y2 = Y1+ BpS + push edi ; [RGBp] + push ebp ; [Yp] + shr ecx, 1 ; Width/=2 + lea eax, [eax+ecx] ; U += W/2 + lea ebx, [ebx+ecx] ; V += W/2 + push eax ; [Up] + push ebx ; [Vp] + + neg ecx ; ecx = -Width/2 + push ecx ; save [xCnt] + push eax ; fake ([yCnt]) + + mov ecx, [esp+32 +40] ; Height + shr ecx, 1 ; /2 + + mov esi, [Up] + mov edi, [Vp] + + jmp .Go + +align 16 +.Loop_y + dec ecx + jg .Add + + add esp, 24 ; rid of all tmp + pop ebp + pop edi + pop esi + pop ebx + + ret + +align 16 +.Add + mov edi, [esp+8 +40] ; Dst_BpS + mov esi, [esp+24 +40] ; Src_BpS + mov edx, [RGBp] + mov ebp, [Yp] + lea edx, [edx+2*edi] ; RGB += 2*Dst_BpS + lea ebp, [ebp+2*esi] ; Y += 2*Src_BpS + mov [RGBp], edx + mov edi, [Vp] + mov [Yp], ebp ; Y1 + lea edx, [ebp+esi] ; Y2 + + lea edi, [edi+esi] ; V += Src_BpS + add esi, [Up] ; U += Src_BpS + mov [Vp], edi + mov [Up], esi + +.Go + mov [yCnt], ecx + mov ecx, [xCnt] + + ; 5210c@640x480 + +.Loop_x ; edi,esi: U,V; ebp,edx: Y1, Y2; ecx: xCnt + + ; R = Y + a.U + ; G = Y + c.V + b.U + ; B = Y + d.V + + movzx eax, byte [edi+ecx+0] + movzx ebx, byte [esi+ecx+0] + movq mm0, [Skl_YUV_Tab32_MMX+0*2048 + eax*8] + movzx eax, byte [edi+ecx+1] + paddw mm0, [Skl_YUV_Tab32_MMX+1*2048 + ebx*8] + movzx ebx, byte [esi+ecx+1] + movq mm4, [Skl_YUV_Tab32_MMX+0*2048 + eax*8] + movzx eax, byte [ebp + 2*ecx+0] + paddw mm4, [Skl_YUV_Tab32_MMX+1*2048 + ebx*8] + movzx ebx, byte [ebp + 2*ecx+1] + + movq mm1, mm0 + movq mm2, mm0 + movq mm3, mm0 + movq mm5, mm4 + movq mm6, mm4 + movq mm7, mm4 + + paddw mm0, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [ebp + 2*ecx+2] + paddw mm1, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + movzx ebx, byte [ebp + 2*ecx+3] + packuswb mm0, mm1 + paddw mm4, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [edx + 2*ecx+0] + paddw mm5, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + + packuswb mm4, mm5 + mov esi, [RGBp] + movzx ebx, byte [edx + 2*ecx+1] + movq [esi+8*ecx+0], mm0 ; 2x32b + movq [esi+8*ecx+8], mm4 ; 2x32b + + paddw mm2, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [edx + 2*ecx+2] + paddw mm3, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + movzx ebx, byte [edx + 2*ecx+3] + packuswb mm2, mm3 + paddw mm6, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + add esi, [esp+8 +40] + paddw mm7, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + + mov edi, [Vp] + packuswb mm6, mm7 + movq [esi+8*ecx+0], mm2 ; 2x32b + movq [esi+8*ecx+8], mm6 ; 2x32b + + add ecx, 2 + mov esi, [Up] + + jl near .Loop_x + + mov ecx, [yCnt] + jmp .Loop_y diff --git a/branches/pcsx2_0.9.2/IPU/yuv2rgb.c b/branches/pcsx2_0.9.2/IPU/yuv2rgb.c new file mode 100644 index 0000000..17d6c0c --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/yuv2rgb.c @@ -0,0 +1,510 @@ +/* + * yuv2rgb.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +//#include "convert_internal.h" //START +typedef struct { + u8 * rgb_ptr; + int width; + int uv_stride, uv_stride_frame; + int rgb_stride, rgb_stride_frame; + void (* yuv2rgb) (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); +} convert_rgb_t; + +typedef void yuv2rgb_copy (void * id, u8 * const * src, + unsigned int v_offset); + +yuv2rgb_copy * yuv2rgb_init_mmxext (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mmx (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mlib (int bpp, int mode); +//#include "convert_internal.h" //END + +static u32 matrix_coefficients = 6; + +const s32 Inverse_Table_6_9[8][4] = { + {117504, 138453, 13954, 34903}, /*0 no sequence_display_extension */ + {117504, 138453, 13954, 34903}, /*1 ITU-R Rec. 709 (1990) */ + {104597, 132201, 25675, 53279}, /*2 unspecified */ + {104597, 132201, 25675, 53279}, /*3 reserved */ + {104448, 132798, 24759, 53109}, /*4 FCC */ + {104597, 132201, 25675, 53279}, /*5 ITU-R Rec. 624-4 System B, G */ + {104597, 132201, 25675, 53279}, /*6 SMPTE 170M */ + {117579, 136230, 16907, 35559} /*7 SMPTE 240M (1987) */ +}; + +typedef void yuv2rgb_c_internal (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); + +void * table_rV[256]; +void * table_gU[256]; +int table_gV[256]; +void * table_bU[256]; + +#define _RGB(type,i) \ + U = pu[i]; \ + V = pv[i]; \ + r = (type *) table_rV[V]; \ + g = (type *) (((u8 *)table_gU[U]) + table_gV[V]); \ + b = (type *) table_bU[U]; + +#define DST(py,dst,i) \ + Y = py[2*i]; \ + dst[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py[2*i+1]; \ + dst[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DSTRGB(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y]; + +#define DSTBGR(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y]; + +static void yuv2rgb_c_32 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u32 * r, * g, * b; + u32 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u32 *) _dst_1; + dst_2 = (u32 *) _dst_2; + + do { + _RGB (u32, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u32, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u32, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u32, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +/* This is very near from the yuv2rgb_c_32 code */ +static void yuv2rgb_c_24_rgb (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTRGB (py_1, dst_1, 0); + DSTRGB (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTRGB (py_2, dst_2, 1); + DSTRGB (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTRGB (py_1, dst_1, 2); + DSTRGB (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTRGB (py_2, dst_2, 3); + DSTRGB (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* only trivial mods from yuv2rgb_c_24_rgb */ +static void yuv2rgb_c_24_bgr (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTBGR (py_1, dst_1, 0); + DSTBGR (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTBGR (py_2, dst_2, 1); + DSTBGR (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTBGR (py_1, dst_1, 2); + DSTBGR (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTBGR (py_2, dst_2, 3); + DSTBGR (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void yuv2rgb_c_16 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u16 * r, * g, * b; + u16 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u16 *) _dst_1; + dst_2 = (u16 *) _dst_2; + + do { + _RGB (u16, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u16, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u16, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u16, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +static int div_round (int dividend, int divisor) +{ + if (dividend > 0) + return (dividend + (divisor>>1)) / divisor; + else + return -((-dividend + (divisor>>1)) / divisor); +} + +static yuv2rgb_c_internal * yuv2rgb_c_init (int order, int bpp) +{ + int i; + u8 table_Y[1024]; + u32 * table_32 = 0; + u16 * table_16 = 0; + u8 * table_8 = 0; + int entry_size = 0; + void * table_r = 0; + void * table_g = 0; + void * table_b = 0; + yuv2rgb_c_internal * yuv2rgb; + + int crv = Inverse_Table_6_9[matrix_coefficients][0]; + int cbu = Inverse_Table_6_9[matrix_coefficients][1]; + int cgu = -Inverse_Table_6_9[matrix_coefficients][2]; + int cgv = -Inverse_Table_6_9[matrix_coefficients][3]; + + for (i = 0; i < 1024; i++) { + int j; + + j = (76309 * (i - 384 - 16) + 32768) >> 16; + j = (j < 0) ? 0 : ((j > 255) ? 255 : j); + table_Y[i] = j; + } + + switch (bpp) { + case 32: + yuv2rgb = yuv2rgb_c_32; + + table_32 = (u32 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u32)); + + entry_size = sizeof (u32); + table_r = table_32 + 197; + table_b = table_32 + 197 + 685; + table_g = table_32 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) + ((u32 *) table_r)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 16 : 0); + for (i = -132; i < 256+132; i++) + ((u32 *) table_g)[i] = table_Y[i+384] << 8; + for (i = -232; i < 256+232; i++) + ((u32 *) table_b)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 0 : 16); + break; + + case 24: + yuv2rgb = (order == CONVERT_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; + + table_8 = (u8 *) malloc ((256 + 2*232) * sizeof (u8)); + + entry_size = sizeof (u8); + table_r = table_g = table_b = table_8 + 232; + + for (i = -232; i < 256+232; i++) + ((u8 * )table_b)[i] = table_Y[i+384]; + break; + + case 15: + case 16: + yuv2rgb = yuv2rgb_c_16; + + table_16 = (u16 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u16)); + + entry_size = sizeof (u16); + table_r = table_16 + 197; + table_b = table_16 + 197 + 685; + table_g = table_16 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_r)[i] = j; + } + for (i = -132; i < 256+132; i++) { + int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3); + + ((u16 *)table_g)[i] = j << 5; + } + for (i = -232; i < 256+232; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_b)[i] = j; + } + break; + + default: + fprintf (stderr, "%ibpp not supported by yuv2rgb\n", bpp); + exit (1); + } + + for (i = 0; i < 256; i++) { + table_rV[i] = (((u8 *)table_r) + + entry_size * div_round (crv * (i-128), 76309)); + table_gU[i] = (((u8 *)table_g) + + entry_size * div_round (cgu * (i-128), 76309)); + table_gV[i] = entry_size * div_round (cgv * (i-128), 76309); + table_bU[i] = (((u8 *)table_b) + + entry_size * div_round (cbu * (i-128), 76309)); + } + + return yuv2rgb; +} + +static void convert_yuv2rgb_c (void * _id, u8 * Y, u8 * Cr, u8 * Cb, + unsigned int v_offset) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + u8 * dst; + u8 * py; + u8 * pu; + u8 * pv; + int loop; + + dst = id->rgb_ptr + id->rgb_stride * v_offset; + py = Y; pu = Cr; pv = Cb; + + loop = 8; + do { + id->yuv2rgb (py, py + (id->uv_stride << 1), pu, pv, + dst, dst + id->rgb_stride, id->width); + py += id->uv_stride << 2; + pu += id->uv_stride; + pv += id->uv_stride; + dst += 2 * id->rgb_stride; + } while (--loop); +} + +static void convert_start (void * _id, u8 * dest, int flags) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + id->rgb_ptr = dest; + switch (flags) { + case CONVERT_BOTTOM_FIELD: + id->rgb_ptr += id->rgb_stride_frame; + /* break thru */ + case CONVERT_TOP_FIELD: + id->uv_stride = id->uv_stride_frame << 1; + id->rgb_stride = id->rgb_stride_frame << 1; + break; + default: + id->uv_stride = id->uv_stride_frame; + id->rgb_stride = id->rgb_stride_frame; + } +} + +static void convert_internal (int order, int bpp, int width, int height, + u32 accel, void * arg, + convert_init_t * result) +{ + convert_rgb_t * id = (convert_rgb_t *) result->id; + + if (!id) { + result->id_size = sizeof (convert_rgb_t); + } else { + id->width = width; + id->uv_stride_frame = width >> 1; + id->rgb_stride_frame = ((bpp + 7) >> 3) * width; + + result->buf_size[0] = id->rgb_stride_frame * height; + result->buf_size[1] = result->buf_size[2] = 0; + result->start = convert_start; + + result->copy = NULL; +#ifdef ARCH_X86 + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMXEXT)) { + result->copy = yuv2rgb_init_mmxext (order, bpp); + } + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMX)) { + result->copy = yuv2rgb_init_mmx (order, bpp); + } +#endif +#ifdef LIBVO_MLIB + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_MLIB)) { + result->copy = yuv2rgb_init_mlib (order, bpp); + } +#endif + if (result->copy == NULL) { + result->copy = convert_yuv2rgb_c; + id->yuv2rgb = yuv2rgb_c_init (order, bpp); + } + } +} + +void convert_rgb32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 32, width, height, accel, arg, result); +} + +void convert_rgb24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 24, width, height, accel, arg, result); +} + +void convert_rgb16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 16, width, height, accel, arg, result); +} + +void convert_rgb15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 15, width, height, accel, arg, result); +} + +void convert_bgr32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 32, width, height, accel, arg, result); +} + +void convert_bgr24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 24, width, height, accel, arg, result); +} + +void convert_bgr16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 16, width, height, accel, arg, result); +} + +void convert_bgr15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 15, width, height, accel, arg, result); +} + +convert_t* convert_rgb (int order, int bpp) +{ + if (order == CONVERT_RGB || order == CONVERT_BGR) + switch (bpp) { + case 32: return (order == CONVERT_RGB) ? convert_rgb32 : convert_bgr32; + case 24: return (order == CONVERT_RGB) ? convert_rgb24 : convert_bgr24; + case 16: return (order == CONVERT_RGB) ? convert_rgb16 : convert_bgr16; + case 15: return (order == CONVERT_RGB) ? convert_rgb15 : convert_bgr15; + } + return NULL; +} diff --git a/branches/pcsx2_0.9.2/IPU/yuv2rgb.h b/branches/pcsx2_0.9.2/IPU/yuv2rgb.h new file mode 100644 index 0000000..d9d4d9c --- /dev/null +++ b/branches/pcsx2_0.9.2/IPU/yuv2rgb.h @@ -0,0 +1,57 @@ +/* + * yuv2rgb.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef YUV2RGB_H +#define YUV2RGB_H + +#define CONVERT_FRAME 0 +#define CONVERT_TOP_FIELD 1 +#define CONVERT_BOTTOM_FIELD 2 +#define CONVERT_BOTH_FIELDS 3 + +typedef struct convert_init_s { + void * id; + int id_size; + int buf_size[3]; + void (* start) (void * id, u8 * dest, int flags); + void (* copy) (void * id, u8 * Y, u8 * Cr, u8 * Cb, unsigned int v_offset); +} convert_init_t; + +typedef void convert_t (int width, int height, u32 accel, void * arg, + convert_init_t * result); + +convert_t convert_rgb32; +convert_t convert_rgb24; +convert_t convert_rgb16; +convert_t convert_rgb15; +convert_t convert_bgr32; +convert_t convert_bgr24; +convert_t convert_bgr16; +convert_t convert_bgr15; + +#define CONVERT_RGB 0 +#define CONVERT_BGR 1 +convert_t * convert_rgb (int order, int bpp); + +#endif /* YUV2RGB_H */ diff --git a/branches/pcsx2_0.9.2/InterTables.c b/branches/pcsx2_0.9.2/InterTables.c new file mode 100644 index 0000000..5f79905 --- /dev/null +++ b/branches/pcsx2_0.9.2/InterTables.c @@ -0,0 +1,224 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//all tables for R5900 are define here.. + +#include "InterTables.h" + +void (*Int_OpcodePrintTable[64])() = +{ + SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, + ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, + COP0, COP1, COP2, UnknownOpcode, BEQL, BNEL, BLEZL, BGTZL, + DADDI, DADDIU, LDL, LDR, MMI, UnknownOpcode, LQ, SQ, + LB, LH, LWL, LW, LBU, LHU, LWR, LWU, + SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, + UnknownOpcode, LWC1, UnknownOpcode, PREF, UnknownOpcode,UnknownOpcode, LQC2, LD, + UnknownOpcode, SWC1, UnknownOpcode, UnknownOpcode, UnknownOpcode,UnknownOpcode, SQC2, SD +}; + + +void (*Int_SpecialPrintTable[64])() = +{ + SLL, UnknownOpcode, SRL, SRA, SLLV, UnknownOpcode, SRLV, SRAV, + JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, UnknownOpcode, SYNC, + MFHI, MTHI, MFLO, MTLO, DSLLV, UnknownOpcode, DSRLV, DSRAV, + MULT, MULTU, DIV, DIVU, UnknownOpcode,UnknownOpcode,UnknownOpcode,UnknownOpcode, + ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, + MFSA , MTSA , SLT, SLTU, DADD, DADDU, DSUB, DSUBU, + TGE, TGEU, TLT, TLTU, TEQ, UnknownOpcode, TNE, UnknownOpcode, + DSLL, UnknownOpcode, DSRL, DSRA, DSLL32, UnknownOpcode, DSRL32, DSRA32 +}; + +void (*Int_REGIMMPrintTable[32])() = { + BLTZ, BGEZ, BLTZL, BGEZL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + TGEI, TGEIU, TLTI, TLTIU, TEQI, UnknownOpcode, TNEI, UnknownOpcode, + BLTZAL, BGEZAL, BLTZALL, BGEZALL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + MTSAB, MTSAH , UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, +}; + +void (*Int_MMIPrintTable[64])() = +{ + MADD, MADDU, MMI_Unknown, MMI_Unknown, PLZCW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI0, MMI2, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MFHI1, MTHI1, MFLO1, MTLO1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MULT1, MULTU1, DIV1, DIVU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MADD1, MADDU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI1 , MMI3, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHL, PMTHL, MMI_Unknown, MMI_Unknown, PSLLH, MMI_Unknown, PSRLH, PSRAH, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, PSLLW, MMI_Unknown, PSRLW, PSRAW, +}; + +void (*Int_MMI0PrintTable[32])() = +{ + PADDW, PSUBW, PCGTW, PMAXW, + PADDH, PSUBH, PCGTH, PMAXH, + PADDB, PSUBB, PCGTB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDSW, PSUBSW, PEXTLW, PPACW, + PADDSH, PSUBSH, PEXTLH, PPACH, + PADDSB, PSUBSB, PEXTLB, PPACB, + MMI_Unknown, MMI_Unknown, PEXT5, PPAC5, +}; + +void (*Int_MMI1PrintTable[32])() = +{ + MMI_Unknown, PABSW, PCEQW, PMINW, + PADSBH, PABSH, PCEQH, PMINH, + MMI_Unknown, MMI_Unknown, PCEQB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDUW, PSUBUW, PEXTUW, MMI_Unknown, + PADDUH, PSUBUH, PEXTUH, MMI_Unknown, + PADDUB, PSUBUB, PEXTUB, QFSRV, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, +}; + + +void (*Int_MMI2PrintTable[32])() = +{ + PMADDW, MMI_Unknown, PSLLVW, PSRLVW, + PMSUBW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHI, PMFLO, PINTH, MMI_Unknown, + PMULTW, PDIVW, PCPYLD, MMI_Unknown, + PMADDH, PHMADH, PAND, PXOR, + PMSUBH, PHMSBH, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXEH, PREVH, + PMULTH, PDIVBW, PEXEW, PROT3W, +}; + +void (*Int_MMI3PrintTable[32])() = +{ + PMADDUW, MMI_Unknown, MMI_Unknown, PSRAVW, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMTHI, PMTLO, PINTEH, MMI_Unknown, + PMULTUW, PDIVUW, PCPYUD, MMI_Unknown, + MMI_Unknown, MMI_Unknown, POR, PNOR, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXCH, PCPYH, + MMI_Unknown, MMI_Unknown, PEXCW, MMI_Unknown, +}; + +void (*Int_COP0PrintTable[32])() = +{ + MFC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, MTC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_BC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Func, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0BC0PrintTable[32])() = +{ + BC0F, BC0T, BC0FL, BC0TL, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0C0PrintTable[64])() = { + COP0_Unknown, TLBR, TLBWI, COP0_Unknown, COP0_Unknown, COP0_Unknown, TLBWR, COP0_Unknown, + TLBP, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + ERET, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + EI, DI, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown +}; + +void (*Int_COP1PrintTable[32])() = { + MFC1, COP1_Unknown, CFC1, COP1_Unknown, MTC1, COP1_Unknown, CTC1, COP1_Unknown, + COP1_BC1, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_S, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_W, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1BC1PrintTable[32])() = { + BC1F, BC1T, BC1FL, BC1TL, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1SPrintTable[64])() = { +ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,RSQRT_S, COP1_Unknown, +ADDA_S, SUBA_S, MULA_S, COP1_Unknown,MADD_S, MSUB_S, MADDA_S, MSUBA_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,CVT_W, COP1_Unknown,COP1_Unknown,COP1_Unknown, +MAX_S, MIN_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +C_F, COP1_Unknown,C_EQ, COP1_Unknown,C_LT, COP1_Unknown,C_LE, COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + +void (*Int_COP1WPrintTable[64])() = { +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +CVT_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + + +void (*Int_COP2PrintTable[32])() = { + COP2_Unknown, QMFC2, CFC2, COP2_Unknown, COP2_Unknown, QMTC2, CTC2, COP2_Unknown, + COP2_BC2, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, +}; + +void (*Int_COP2BC2PrintTable[32])() = { + BC2F, BC2T, BC2FL, BC2TL, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, +}; + +void (*Int_COP2SPECIAL1PrintTable[64])() = +{ + VADDx, VADDy, VADDz, VADDw, VSUBx, VSUBy, VSUBz, VSUBw, + VMADDx, VMADDy, VMADDz, VMADDw, VMSUBx, VMSUBy, VMSUBz, VMSUBw, + VMAXx, VMAXy, VMAXz, VMAXw, VMINIx, VMINIy, VMINIz, VMINIw, + VMULx, VMULy, VMULz, VMULw, VMULq, VMAXi, VMULi, VMINIi, + VADDq, VMADDq, VADDi, VMADDi, VSUBq, VMSUBq, VSUBi, VMSUBi, + VADD, VMADD, VMUL, VMAX, VSUB, VMSUB, VOPMSUB, VMINI, + VIADD, VISUB, VIADDI, COP2_Unknown,VIAND, VIOR, COP2_Unknown, COP2_Unknown, + VCALLMS, VCALLMSR, COP2_Unknown,COP2_Unknown,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2, +}; + +void (*Int_COP2SPECIAL2PrintTable[128])() = +{ + VADDAx ,VADDAy ,VADDAz ,VADDAw ,VSUBAx ,VSUBAy ,VSUBAz ,VSUBAw, + VMADDAx ,VMADDAy ,VMADDAz ,VMADDAw ,VMSUBAx ,VMSUBAy ,VMSUBAz ,VMSUBAw, + VITOF0 ,VITOF4 ,VITOF12 ,VITOF15 ,VFTOI0 ,VFTOI4 ,VFTOI12 ,VFTOI15, + VMULAx ,VMULAy ,VMULAz ,VMULAw ,VMULAq ,VABS ,VMULAi ,VCLIPw, + VADDAq ,VMADDAq ,VADDAi ,VMADDAi ,VSUBAq ,VMSUBAq ,VSUBAi ,VMSUBAi, + VADDA ,VMADDA ,VMULA ,COP2_Unknown,VSUBA ,VMSUBA ,VOPMULA ,VNOP, + VMOVE ,VMR32 ,COP2_Unknown,COP2_Unknown,VLQI ,VSQI ,VLQD ,VSQD, + VDIV ,VSQRT ,VRSQRT ,VWAITQ ,VMTIR ,VMFIR ,VILWR ,VISWR, + VRNEXT ,VRGET ,VRINIT ,VRXOR ,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, +}; diff --git a/branches/pcsx2_0.9.2/InterTables.h b/branches/pcsx2_0.9.2/InterTables.h new file mode 100644 index 0000000..5788826 --- /dev/null +++ b/branches/pcsx2_0.9.2/InterTables.h @@ -0,0 +1,491 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef INTERTABLES_H +#define INTERTABLES_H + +extern void (*Int_OpcodePrintTable[64])(); +extern void (*Int_SpecialPrintTable[64])(); +extern void (*Int_REGIMMPrintTable[32])(); +extern void (*Int_MMIPrintTable[64])(); +extern void (*Int_MMI0PrintTable[32])(); +extern void (*Int_MMI1PrintTable[32])(); +extern void (*Int_MMI2PrintTable[32])(); +extern void (*Int_MMI3PrintTable[32])(); +extern void (*Int_COP0PrintTable[32])(); +extern void (*Int_COP0BC0PrintTable[32])(); +extern void (*Int_COP0C0PrintTable[64])(); +extern void (*Int_COP1PrintTable[32])(); +extern void (*Int_COP1BC1PrintTable[32])(); +extern void (*Int_COP1SPrintTable[64])(); +extern void (*Int_COP1WPrintTable[64])(); +extern void (*Int_COP2PrintTable[32])(); +extern void (*Int_COP2BC2PrintTable[32])(); +extern void (*Int_COP2SPECIAL1PrintTable[64])(); +extern void (*Int_COP2SPECIAL2PrintTable[128])(); + +void SPECIAL(); +void REGIMM(); +void UnknownOpcode(); +void COP0(); +void COP1(); +void COP2(); +void MMI_Unknown(); +void MMI(); +void MMI0(); +void MMI1(); +void MMI2(); +void MMI3(); +void COP0_Unknown(); +void COP0_BC0(); +void COP0_Func(); +void COP1_BC1(); +void COP1_S(); +void COP1_W(); +void COP1_Unknown(); +void COP2_BC2(); +void COP2_SPECIAL(); +void COP2_Unknown(); +void COP2_SPECIAL2(); + +// **********************Standard Opcodes************************** +void J(); +void JAL(); +void BEQ(); +void BNE(); +void BLEZ(); +void BGTZ(); +void ADDI(); +void ADDIU(); +void SLTI(); +void SLTIU(); +void ANDI(); +void ORI(); +void XORI(); +void LUI(); +void BEQL(); +void BNEL(); +void BLEZL(); +void BGTZL(); +void DADDI(); +void DADDIU(); +void LDL(); +void LDR(); +void LB(); +void LH(); +void LWL(); +void LW(); +void LBU(); +void LHU(); +void LWR(); +void LWU(); +void SB(); +void SH(); +void SWL(); +void SW(); +void SDL(); +void SDR(); +void SWR(); +void CACHE(); +void LWC1(); +void PREF(); +void LQC2(); +void LD(); +void SQC2(); +void SD(); +void LQ(); +void SQ(); +void SWC1(); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void SLL(); +void SRL(); +void SRA(); +void SLLV(); +void SRLV(); +void SRAV(); +void JR(); +void JALR(); +void SYSCALL(); +void BREAK(); +void SYNC(); +void MFHI(); +void MTHI(); +void MFLO(); +void MTLO(); +void DSLLV(); +void DSRLV(); +void DSRAV(); +void MULT(); +void MULTU(); +void DIV(); +void DIVU(); +void ADD(); +void ADDU(); +void SUB(); +void SUBU(); +void AND(); +void OR(); +void XOR(); +void NOR(); +void SLT(); +void SLTU(); +void DADD(); +void DADDU(); +void DSUB(); +void DSUBU(); +void TGE(); +void TGEU(); +void TLT(); +void TLTU(); +void TEQ(); +void TNE(); +void DSLL(); +void DSRL(); +void DSRA(); +void DSLL32(); +void DSRL32(); +void DSRA32(); +void MOVZ(); +void MOVN(); +void MFSA(); +void MTSA(); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void BLTZ(); +void BGEZ(); +void BLTZL(); +void BGEZL(); +void TGEI(); +void TGEIU(); +void TLTI(); +void TLTIU(); +void TEQI(); +void TNEI(); +void BLTZAL(); +void BGEZAL(); +void BLTZALL(); +void BGEZALL(); +void MTSAB(); +void MTSAH(); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void MADD(); +void MADDU(); +void PLZCW(); +void MADD1(); +void MADDU1(); +void MFHI1(); +void MTHI1(); +void MFLO1(); +void MTLO1(); +void MULT1(); +void MULTU1(); +void DIV1(); +void DIVU1(); +void PMFHL(); +void PMTHL(); +void PSLLH(); +void PSRLH(); +void PSRAH(); +void PSLLW(); +void PSRLW(); +void PSRAW(); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void PADDW(); +void PSUBW(); +void PCGTW(); +void PMAXW(); +void PADDH(); +void PSUBH(); +void PCGTH(); +void PMAXH(); +void PADDB(); +void PSUBB(); +void PCGTB(); +void PADDSW(); +void PSUBSW(); +void PEXTLW(); +void PPACW(); +void PADDSH(); +void PSUBSH(); +void PEXTLH(); +void PPACH(); +void PADDSB(); +void PSUBSB(); +void PEXTLB(); +void PPACB(); +void PEXT5(); +void PPAC5(); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void PABSW(); +void PCEQW(); +void PMINW(); +void PADSBH(); +void PABSH(); +void PCEQH(); +void PMINH(); +void PCEQB(); +void PADDUW(); +void PSUBUW(); +void PEXTUW(); +void PADDUH(); +void PSUBUH(); +void PEXTUH(); +void PADDUB(); +void PSUBUB(); +void PEXTUB(); +void QFSRV(); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void PMADDW(); +void PSLLVW(); +void PSRLVW(); +void PMSUBW(); +void PMFHI(); +void PMFLO(); +void PINTH(); +void PMULTW(); +void PDIVW(); +void PCPYLD(); +void PMADDH(); +void PHMADH(); +void PAND(); +void PXOR(); +void PMSUBH(); +void PHMSBH(); +void PEXEH(); +void PREVH(); +void PMULTH(); +void PDIVBW(); +void PEXEW(); +void PROT3W(); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void PMADDUW(); +void PSRAVW(); +void PMTHI(); +void PMTLO(); +void PINTEH(); +void PMULTUW(); +void PDIVUW(); +void PCPYUD(); +void POR(); +void PNOR(); +void PEXCH(); +void PCPYH(); +void PEXCW(); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void MFC0(); +void MTC0(); +void BC0F(); +void BC0T(); +void BC0FL(); +void BC0TL(); +void TLBR(); +void TLBWI(); +void TLBWR(); +void TLBP(); +void ERET(); +void DI(); +void EI(); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void MFC1(); +void CFC1(); +void MTC1(); +void CTC1(); +void BC1F(); +void BC1T(); +void BC1FL(); +void BC1TL(); +void ADD_S(); +void SUB_S(); +void MUL_S(); +void DIV_S(); +void SQRT_S(); +void ABS_S(); +void MOV_S(); +void NEG_S(); +void RSQRT_S(); +void ADDA_S(); +void SUBA_S(); +void MULA_S(); +void MADD_S(); +void MSUB_S(); +void MADDA_S(); +void MSUBA_S(); +void CVT_W(); +void MAX_S(); +void MIN_S(); +void C_F(); +void C_EQ(); +void C_LT(); +void C_LE(); + void CVT_S(); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void QMFC2(); +void CFC2(); +void QMTC2(); +void CTC2(); +void BC2F(); +void BC2T(); +void BC2FL(); +void BC2TL(); +//*****************SPECIAL 1 VUO TABLE******************************* +void VADDx(); +void VADDy(); +void VADDz(); +void VADDw(); +void VSUBx(); +void VSUBy(); +void VSUBz(); +void VSUBw(); +void VMADDx(); +void VMADDy(); +void VMADDz(); +void VMADDw(); +void VMSUBx(); +void VMSUBy(); +void VMSUBz(); +void VMSUBw(); +void VMAXx(); +void VMAXy(); +void VMAXz(); +void VMAXw(); +void VMINIx(); +void VMINIy(); +void VMINIz(); +void VMINIw(); +void VMULx(); +void VMULy(); +void VMULz(); +void VMULw(); +void VMULq(); +void VMAXi(); +void VMULi(); +void VMINIi(); +void VADDq(); +void VMADDq(); +void VADDi(); +void VMADDi(); +void VSUBq(); +void VMSUBq(); +void VSUBi(); +void VMSUBi(); +void VADD(); +void VMADD(); +void VMUL(); +void VMAX(); +void VSUB(); +void VMSUB(); +void VOPMSUB(); +void VMINI(); +void VIADD(); +void VISUB(); +void VIADDI(); +void VIAND(); +void VIOR(); +void VCALLMS(); +void VCALLMSR(); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void VADDAx(); +void VADDAy(); +void VADDAz(); +void VADDAw(); +void VSUBAx(); +void VSUBAy(); +void VSUBAz(); +void VSUBAw(); +void VMADDAx(); +void VMADDAy(); +void VMADDAz(); +void VMADDAw(); +void VMSUBAx(); +void VMSUBAy(); +void VMSUBAz(); +void VMSUBAw(); +void VITOF0(); +void VITOF4(); +void VITOF12(); +void VITOF15(); +void VFTOI0(); +void VFTOI4(); +void VFTOI12(); +void VFTOI15(); +void VMULAx(); +void VMULAy(); +void VMULAz(); +void VMULAw(); +void VMULAq(); +void VABS(); +void VMULAi(); +void VCLIPw(); +void VADDAq(); +void VMADDAq(); +void VADDAi(); +void VMADDAi(); +void VSUBAq(); +void VMSUBAq(); +void VSUBAi(); +void VMSUBAi(); +void VADDA(); +void VMADDA(); +void VMULA(); +void VSUBA(); +void VMSUBA(); +void VOPMULA(); +void VNOP(); +void VMOVE(); +void VMR32(); +void VLQI(); +void VSQI(); +void VLQD(); +void VSQD(); +void VDIV(); +void VSQRT(); +void VRSQRT(); +void VWAITQ(); +void VMTIR(); +void VMFIR(); +void VILWR(); +void VISWR(); +void VRNEXT(); +void VRGET(); +void VRINIT(); +void VRXOR(); +//************************************END OF SPECIAL2 ************ +#endif diff --git a/branches/pcsx2_0.9.2/Interpreter.c b/branches/pcsx2_0.9.2/Interpreter.c new file mode 100644 index 0000000..c991176 --- /dev/null +++ b/branches/pcsx2_0.9.2/Interpreter.c @@ -0,0 +1,1058 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "ix86/ix86.h" + +#include + +extern u32 maxrecmem; + +char *bios[256]={ +//0x00 + "RFU000_FullReset", "ResetEE", "SetGsCrt", "RFU003", + "Exit", "RFU005", "LoadExecPS2", "ExecPS2", + "RFU008", "RFU009", "AddSbusIntcHandler", "RemoveSbusIntcHandler", + "Interrupt2Iop", "SetVTLBRefillHandler", "SetVCommonHandler", "SetVInterruptHandler", +//0x10 + "AddIntcHandler", "RemoveIntcHandler", "AddDmacHandler", "RemoveDmacHandler", + "_EnableIntc", "_DisableIntc", "_EnableDmac", "_DisableDmac", + "_SetAlarm", "_ReleaseAlarm", "_iEnableIntc", "_iDisableIntc", + "_iEnableDmac", "_iDisableDmac", "_iSetAlarm", "_iReleaseAlarm", +//0x20 + "CreateThread", "DeleteThread", "StartThread", "ExitThread", + "ExitDeleteThread", "TerminateThread", "iTerminateThread", "DisableDispatchThread", + "EnableDispatchThread", "ChangeThreadPriority", "iChangeThreadPriority", "RotateThreadReadyQueue", + "iRotateThreadReadyQueue", "ReleaseWaitThread", "iReleaseWaitThread", "GetThreadId", +//0x30 + "ReferThreadStatus","iReferThreadStatus", "SleepThread", "WakeupThread", + "_iWakeupThread", "CancelWakeupThread", "iCancelWakeupThread", "SuspendThread", + "iSuspendThread", "ResumeThread", "iResumeThread", "JoinThread", + "RFU060", "RFU061", "EndOfHeap", "RFU063", +//0x40 + "CreateSema", "DeleteSema", "SignalSema", "iSignalSema", + "WaitSema", "PollSema", "iPollSema", "ReferSemaStatus", + "iReferSemaStatus", "RFU073", "SetOsdConfigParam", "GetOsdConfigParam", + "GetGsHParam", "GetGsVParam", "SetGsHParam", "SetGsVParam", +//0x50 + "RFU080_CreateEventFlag", "RFU081_DeleteEventFlag", + "RFU082_SetEventFlag", "RFU083_iSetEventFlag", + "RFU084_ClearEventFlag", "RFU085_iClearEventFlag", + "RFU086_WaitEventFlag", "RFU087_PollEventFlag", + "RFU088_iPollEventFlag", "RFU089_ReferEventFlagStatus", + "RFU090_iReferEventFlagStatus", "RFU091_GetEntryAddress", + "EnableIntcHandler_iEnableIntcHandler", + "DisableIntcHandler_iDisableIntcHandler", + "EnableDmacHandler_iEnableDmacHandler", + "DisableDmacHandler_iDisableDmacHandler", +//0x60 + "KSeg0", "EnableCache", "DisableCache", "GetCop0", + "FlushCache", "RFU101", "CpuConfig", "iGetCop0", + "iFlushCache", "RFU105", "iCpuConfig", "sceSifStopDma", + "SetCPUTimerHandler", "SetCPUTimer", "SetOsdConfigParam2", "SetOsdConfigParam2", +//0x70 + "GsGetIMR_iGsGetIMR", "GsGetIMR_iGsPutIMR", "SetPgifHandler", "SetVSyncFlag", + "RFU116", "print", "sceSifDmaStat_isceSifDmaStat", "sceSifSetDma_isceSifSetDma", + "sceSifSetDChain_isceSifSetDChain", "sceSifSetReg", "sceSifGetReg", "ExecOSD", + "Deci2Call", "PSMode", "MachineType", "GetMemorySize", +}; + +extern void (*LT_OpcodePrintTable[64])(); +int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef CPU_LOG +#define debugI() \ + if (Log) { CPU_LOG("%s\n", disR5900F(cpuRegs.code, pc)); } \ + if (cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1]) SysPrintf("R0 is not zero!!!!\n"); +#else +#define debugI() +#endif + +void execI() { + u32 pc = cpuRegs.pc; + + cpuRegs.cycle++; + //cpuRegs.CP0.n.Count++; /*count every cycles.*/ + + if (memRead32(cpuRegs.pc, &cpuRegs.code) == -1) return; + + debugI(); + cpuRegs.pc+= 4; +// if((cpuRegs.PERF.n.pccr & 0x80000020) == 0x80000020) cpuRegs.PERF.n.pcr0++; +// if((cpuRegs.PERF.n.pccr & 0x80008000) == 0x80008000) cpuRegs.PERF.n.pcr1++; + + Int_OpcodePrintTable[cpuRegs.code >> 26](); +} + +__inline void doBranch(u32 tar) { + branch2 = cpuRegs.branch = 1; + branchPC = tar; + execI(); + cpuRegs.branch = 0; + cpuRegs.pc = branchPC; + + IntcpuBranchTest(); +} + +void intDoBranch(u32 target) { + doBranch(target); +} + +void intSetBranch() { + branch2 = 1; +} + +void SPECIAL() {Int_SpecialPrintTable[_Funct_]();} +void REGIMM() {Int_REGIMMPrintTable[_Rt_](); } + + +void UnknownOpcode() { +#ifdef CPU_LOG + CPU_LOG("%8.8lx: Unknown opcode called\n", cpuRegs.pc); +#endif +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void ADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed!!!! +void ADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed !!! +void DADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void DADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void ANDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & (s64)_ImmU_; } // Rt = Rs And Im +void ORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | (s64)_ImmU_; } // Rt = Rs Or Im +void XORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ (s64)_ImmU_; } // Rt = Rs Xor Im +void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_); } // Rt = Rs < Im (signed) +void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_); } // Rt = Rs < Im (unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void ADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt (Exception on Integer Overflow) +void ADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt +void DADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void DADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void SUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs - Rt (Exception on Integer Overflow) +void SUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0]; } // Rd = Rs - Rt +void DSUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0];} +void DSUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0]; } +void AND() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs And Rt +void OR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Or Rt +void XOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Xor Rt +void NOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] =~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); }// Rd = Rs Nor Rt +void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]; } // Rd = Rs < Rt (signed) +void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs < Rt (unsigned) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void J() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +void JAL() { +#ifdef EMU_LOG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + _SetLink(31); doBranch(_JumpTarget_); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void JR() { +#ifdef EMU_LOG + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; + u32 pc = cpuRegs.pc; + int rs = _Rs_; +#endif + doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); + if (rs == 31) JumpCheckSymRet(pc); +#endif +} + +void JALR() { + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; +#ifdef EMU_LOG + u32 pc = cpuRegs.pc; +#endif + + if (_Rd_) { _SetLink(_Rd_); } + doBranch(temp); +#ifdef EMU_LOG + JumpCheckSym(temp, pc); +#endif +} + + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void DIV() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +void MULT() { //different in ps2... + s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +void MULTU() { //different in ps2.. + u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void LUI() { + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void MFHI() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; } // Rd = Hi +void MFLO() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void MTHI() { cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Hi = Rs +void MTLO() { cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Lo = Rs + + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void SLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << _Sa_); } // Rd = Rt << sa +void DSLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << _Sa_); } +void DSLL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (_Sa_+32));} +void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) +void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_); } +void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32));} +void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) +void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_); } +void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32));} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void SLLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt << rs +void SRAV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (arithmetic) +void SRLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (logical) +void DSLLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRAV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) \ + if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \ + else IntcpuBranchTest(); + + +void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else IntcpuBranchTest(); + +#define RepZBranchLinki32(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else IntcpuBranchTest(); + +void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + +#define RepZBranchLinki32Likely(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + +#define RepBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + + +void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt +void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt +void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0 +void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0 +void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0 +void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0 +void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link +void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void LB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead8RS(addr, &dummy); + } +} + +void LBU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead8RU(addr, &dummy); + } +} + +void LH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead16RS(addr, &dummy); + } +} + +void LHU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead16RU(addr, &dummy); + } +} + +void LW() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead32RS(addr, &dummy); + } +} + +void LWU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead32RU(addr, &dummy); + } +} + +u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void LWL() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWL_MASK[shift]) | + (mem << LWL_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + */ +} + +u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 }; +u32 LWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void LWR() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWR_MASK[shift]) | + (mem >> LWR_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + */ +} + +void LD() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead64(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead64(addr, &dummy); + } +} + +u64 LDL_MASK[8] = { 0x00ffffffffffffffLL, 0x0000ffffffffffffLL, 0x000000ffffffffffLL, 0x00000000ffffffffLL, + 0x0000000000ffffffLL, 0x000000000000ffffLL, 0x00000000000000ffLL, 0x0000000000000000LL }; +u32 LDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void LDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDL_MASK[shift]) | + (mem << LDL_SHIFT[shift]); +} + +u64 LDR_MASK[8] = { 0x0000000000000000LL, 0xff00000000000000LL, 0xffff000000000000LL, 0xffffff0000000000LL, + 0xffffffff00000000LL, 0xffffffffff000000LL, 0xffffffffffff0000LL, 0xffffffffffffff00LL }; +u32 LDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void LDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDR_MASK[shift]) | + (mem >> LDR_SHIFT[shift]); +} + +void LQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + + if (_Rt_) { + memRead128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +void SB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); +} + +void SH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); +} + +void SW(){ + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); +} + +u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000 }; +u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void SWL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] >> SWL_SHIFT[shift]) | + ( mem & SWL_MASK[shift]) ); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + */ +} + +u32 SWR_MASK[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; +u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void SWR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] << SWR_SHIFT[shift]) | + ( mem & SWR_MASK[shift]) ); + + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + */ +} + +void SD() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite64(addr,cpuRegs.GPR.r[_Rt_].UD[0]); +} + +u64 SDL_MASK[8] = { 0xffffffffffffff00LL, 0xffffffffffff0000LL, 0xffffffffff000000LL, 0xffffffff00000000LL, + 0xffffff0000000000LL, 0xffff000000000000LL, 0xff00000000000000LL, 0x0000000000000000LL }; +u32 SDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void SDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] >> SDL_SHIFT[shift]) | + ( mem & SDL_MASK[shift]) ); +} + +u64 SDR_MASK[8] = { 0x0000000000000000LL, 0x00000000000000ffLL, 0x000000000000ffffLL, 0x0000000000ffffffLL, + 0x00000000ffffffffLL, 0x000000ffffffffffLL, 0x0000ffffffffffffLL, 0x00ffffffffffffffLL }; +u32 SDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void SDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] << SDR_SHIFT[shift]) | + ( mem & SDR_MASK[shift]) ); +} + +void SQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + memWrite128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); +} + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +void MOVZ() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} +void MOVN() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] != 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +#include "Sifcmd.h" +/* +int __Deci2Call(int call, u32 *addr); +*/ +u32 *deci2addr = NULL; +u32 deci2handler; +char deci2buffer[256]; + +/* + * int Deci2Call(int, u_int *); + */ + +int __Deci2Call(int call, u32 *addr) { + if (call > 0x10) { + return -1; + } + + switch (call) { + case 1: // open + + deci2addr = (u32*)PSM(addr[1]); +#ifdef BIOS_LOG + BIOS_LOG("deci2open: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + deci2handler = addr[2]; + + return 1; + + case 2: // close + return 1; + + case 3: // reqsend + +#ifdef BIOS_LOG + BIOS_LOG("deci2reqsend: %x,%x,%x,%x: deci2addr: %x,%x,%x,buf=%x %x,%x,len=%x,%x\n", + addr[3], addr[2], addr[1], addr[0], + deci2addr[7], deci2addr[6], deci2addr[5], deci2addr[4], + deci2addr[3], deci2addr[2], deci2addr[1], deci2addr[0]); +#endif +// cpuRegs.pc = deci2handler; +// SysPrintf("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc)); + if (deci2addr == NULL) return 1; + if (deci2addr[1]>0xc){ + u8* pdeciaddr = (u8*)dmaGetAddr(deci2addr[4]+0xc); + if( pdeciaddr == NULL ) pdeciaddr = (u8*)PSM(deci2addr[4]+0xc); + else pdeciaddr += (deci2addr[4]+0xc)%16; + memcpy(deci2buffer, pdeciaddr, deci2addr[1]-0xc); + deci2buffer[deci2addr[1]-0xc>=255?255:deci2addr[1]-0xc]='\0'; + SysPrintf(deci2buffer); + } + deci2addr[3] = 0; + return 1; + + case 4: // poll +#ifdef BIOS_LOG + BIOS_LOG("deci2poll: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + return 1; + + case 5: // exrecv + return 1; + + case 6: // exsend + return 1; + + case 0x10://kputs + SysPrintf("%s", PSM(*addr)); + return 1; + } + + return 0; +} + + +void SYSCALL() { +#ifdef BIOS_LOG + u8 call; + + if (cpuRegs.GPR.n.v1.SL[0] < 0) + call = (u8)(-cpuRegs.GPR.n.v1.SL[0]); + else call = cpuRegs.GPR.n.v1.UC[0]; + BIOS_LOG("Bios call: %s (%x)\n", bios[call], call); + if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) { + SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0]))); + } else + //if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0])); + if (call == 0x77) { + struct t_sif_dma_transfer *dmat; +// struct t_sif_cmd_header *hdr; +// struct t_sif_rpc_bind *bind; +// struct t_rpc_server_data *server; + int n_transfer; + u32 addr; +// int sid; + + n_transfer = cpuRegs.GPR.n.a1.UL[0] - 1; + if (n_transfer >= 0) { + addr = cpuRegs.GPR.n.a0.UL[0] + n_transfer * sizeof(struct t_sif_dma_transfer); + dmat = (struct t_sif_dma_transfer*)PSM(addr); + +#ifdef BIOS_LOG + BIOS_LOG("bios_%s: n_transfer=%d, size=%x, attr=%x, dest=%x, src=%x\n", + bios[cpuRegs.GPR.n.v1.UC[0]], n_transfer, + dmat->size, dmat->attr, + dmat->dest, dmat->src); +#endif + } +//Log=1; + } +#endif +// if (cpuRegs.GPR.n.v1.UD[0] == 0x77) Log=1; + cpuRegs.pc -= 4; + cpuException(0x20, cpuRegs.branch); +} + +void BREAK(void) { + cpuRegs.pc -= 4; + cpuException(0x24, cpuRegs.branch); +} + +void MFSA( void ) { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = (s64)cpuRegs.sa; +} + +void MTSA( void ) { + cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; +} + +void SYNC( void ) +{ +} + +void PREF( void ) +{ +} + + + +/********************************************************* +* Register trap * +* Format: OP rs, rt * +*********************************************************/ + +void TGE() { + if (cpuRegs.GPR.r[_Rs_].SD[0]>= cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEU() { + if (cpuRegs.GPR.r[_Rs_].UD[0]>= cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLT() { + if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQ() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNE() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Trap with immediate operand * +* Format: OP rs, rt * +*********************************************************/ + +void TGEI() { + + if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] >= _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTI() { + if(cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNEI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Sa intructions * +* Format: OP rs, rt * +*********************************************************/ + +void MTSAB() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3; +} + +void MTSAH() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4; +} + + + +/////////////////////////////////////////// + +int intInit() { + //detect cpu for use the optimaze asm code + return 0; +} + +void intReset() { + cpuRegs.branch = 0; + branch2 = 0; +} + +void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + + +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); +extern u32 vudump; +extern int vu0branch, vu1branch; + +void intExecuteVU0Block() { +int i; + +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) + break; + +#ifdef _DEBUG + prevbranch = vu0branch; +#endif + vu0Exec(&VU0); +#ifdef _DEBUG + if( (vudump&0x80) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + } + + if( i < 0 && (VU0.branch || VU0.ebit) ) { + // execute one more + vu0Exec(&VU0); + } +} + +void intExecuteVU1Block() { + + int i; +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) + break; + +#ifdef _DEBUG + prevbranch = vu1branch; +#endif + vu1Exec(&VU1); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + } + + if( i < 0 && (VU1.branch || VU1.ebit) ) { + // execute one more + vu1Exec(&VU1); + } +} + + +void intEnableVU0micro(int enable) { +} + +void intEnableVU1micro(int enable) { +} + +void intStep() { + execI(); +} + +void intClear(u32 Addr, u32 Size) { +} + +void intVU0Clear(u32 Addr, u32 Size) { +} + +void intVU1Clear(u32 Addr, u32 Size) { +} + +void intShutdown() { +} + +R5900cpu intCpu = { + intInit, + intReset, + intStep, + intExecute, + intExecuteBlock, + intExecuteVU0Block, + intExecuteVU1Block, + intEnableVU0micro, + intEnableVU1micro, + intClear, + intVU0Clear, + intVU1Clear, + intShutdown +}; + diff --git a/branches/pcsx2_0.9.2/Linux/.pixmaps/pcsxAbout.xpm b/branches/pcsx2_0.9.2/Linux/.pixmaps/pcsxAbout.xpm new file mode 100644 index 0000000..2ebc445 --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/.pixmaps/pcsxAbout.xpm @@ -0,0 +1,334 @@ +/* XPM */ +static char *pcsxAbout[] = { +/* columns rows colors chars-per-pixel */ +"314 176 152 2", +" c #252d42", +". c #282e45", +"X c #282f48", +"o c #273046", +"O c #283046", +"+ c #2a334b", +"@ c #2d3650", +"# c #2e3853", +"$ c #303651", +"% c #303955", +"& c #333d5b", +"* c #383f57", +"= c #383e5d", +"- c #35405e", +"; c #39415d", +": c #364161", +"> c #384465", +", c #3a4668", +"< c #3e4866", +"1 c #3c496c", +"2 c #3e4b70", +"3 c #40475b", +"4 c #41485d", +"5 c #404767", +"6 c #424a63", +"7 c #434c6c", +"8 c #484f61", +"9 c #464e70", +"0 c #44506f", +"q c #4c5263", +"w c #465071", +"e c #495273", +"r c #4d5679", +"t c #4e5974", +"y c #4e587b", +"u c #515665", +"i c #535866", +"p c #545968", +"a c #595d69", +"s c #50577b", +"d c #505a75", +"f c #51597d", +"g c #5c606a", +"h c #55617f", +"j c #5a637b", +"k c #64666d", +"l c #65686e", +"z c #666870", +"x c #6b6d71", +"c c #6e7073", +"v c #767676", +"b c #545d81", +"n c #566085", +"m c #586185", +"M c #5b648a", +"N c #5e6883", +"B c #5e688d", +"V c #666d84", +"C c #606a8b", +"Z c #686f86", +"A c #626b93", +"S c #656f98", +"D c #687085", +"F c #6a738c", +"G c #667097", +"H c #667098", +"J c #6d7691", +"K c #6b749d", +"L c #6e7893", +"P c #72788c", +"I c #757d93", +"U c #6d76a0", +"Y c #6e78a1", +"T c #717ba4", +"R c #747ea8", +"E c #7c8397", +"W c #79829a", +"Q c #7680ab", +"! c #7a84ae", +"~ c #7c85b1", +"^ c #7e88b3", +"/ c #808080", +"( c #80838f", +") c #888888", +"_ c #808799", +"` c #82899d", +"' c gray57", +"] c gray60", +"[ c #858da3", +"{ c #858eba", +"} c #8d93a5", +"| c #8f95a8", +" . c #8690bc", +".. c #8891bd", +"X. c #9096a9", +"o. c #999ead", +"O. c #9aa0af", +"+. c #9ca2b4", +"@. c #a2a2a2", +"#. c #aaaaaa", +"$. c #a5a9b6", +"%. c #a7acba", +"&. c #a8adbc", +"*. c #aab0bf", +"=. c #bababa", +"-. c #8e96c3", +";. c #8e98c4", +":. c #9099c6", +">. c #959dca", +",. c #96a0cc", +"<. c #98a0cd", +"1. c #9ca5d1", +"2. c #a4add9", +"3. c #aab0c0", +"4. c #b3b6c2", +"5. c #b4b8c4", +"6. c #b6bbc8", +"7. c #adb5e1", +"8. c #b0b7e3", +"9. c #b0b8e3", +"0. c #bec2cb", +"q. c #bfc7ef", +"w. c #bfc7f0", +"e. c #c2c2c2", +"r. c #c0c3cd", +"t. c gray80", +"y. c #c2c6d1", +"u. c #ccced6", +"i. c #cdd0d7", +"p. c #ced1d9", +"a. c #d0d2d7", +"s. c #d4d5d9", +"d. c #dddddd", +"f. c #c0c7f0", +"g. c #c3cbf2", +"h. c #c8cef4", +"j. c #cad0f5", +"k. c #d9dbe1", +"l. c #d2d8f6", +"z. c #dbdff8", +"x. c #dce0f8", +"c. c gray90", +"v. c #e5e7eb", +"b. c #e6e8ec", +"n. c #eeeeee", +"m. c #e1e5f9", +"M. c #ebeefb", +"N. c #eff1fc", +"B. c #f2f3f5", +"V. c #f0f1fc", +"C. c #f7f8fd", +"Z. c #fefefe", +/* pixels */ +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 2 , , , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , > , > > , > , , : , , : , : , : , : > > > > : > > , : : : : > : : > : : : : : : : - : : - : - - : - - - - - - & - - & - - & & & & & & : & & & & & & & & & & & & & # # # # # & & # & # & # # & # # # # # # & # # & # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ X @ @ + @ @ + @ + @ + @ + + @ + + @ + + @ + + + + + + + + + + + + + + o + + o + + + o + X o X X + o o O O O O O X X O . . . . . . . . . o o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , , , 2 1 , 1 , , , , , 1 , , , , , , , , , , , , > , , , > , > : , , : : , , : , : , : > > , : : > > : : : , : : : : > : : : : : : : : : - : - - - : - - - - - - & - - & - - & : & : & : & & & & & & & & & # & & # & & & & & : & # # & # & # & & # # & & # & # # # # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + + @ + + + + + + + + + + + + + + + o X + + o o + o + o + X X + + + o X o X X O O O O o o O X O . . . o o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 , 2 , 1 1 1 , 1 1 1 1 , , 1 , 1 1 , 1 1 , 1 , 1 , , , , , , , , , , , > , , > , , > , , , : , : : , : , > : , > > : : > > : > : : > : : : : : > - : : - : - - : : : - : - - - - - & - & & - & - & & & & & & & & & & & & & & & & & # & # : # # # & & & & & # & # # & & # & # # # # # # # # & # # % # @ # # @ # # @ % @ @ @ @ @ @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + @ + + + + + + + + + + + + + + + + o + + + + X + o + + o + o o @ + X + X o o o X + X O O O O X X . . . o o . . o . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 2 , 2 2 1 1 1 1 , , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , , > , , > , > , > , > : , , > , , , : , : > > : > > > : > : > : : > : : : : : : : : - : : - : : - - - - - - - - - - - - - - - - & : & & : & & & & & & & & & # & & & & & & & # & : # & # # & # # & # # & # # # & & & # # & # # # # # # # # # # @ # @ @ # @ % @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ + + @ + + @ + + + @ + + + + + + + X + + + + + X + o + + o + o o X X X o o + o X O O O O X O O O O . . . o . o . . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 2 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , > , : , : : : , : , > : , , : , : > > , : > : : , : , : : : : > : : : : : : : : - - - - - - - - - : & & - - - & & & : & & & & & & & & & & & & & & & & : # # & & # # & # & # & # & & # # & # # # # & # # & # # # # @ # % % # # # # @ # @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ @ + @ @ + @ + + @ + + @ + + + + + + + + + + + + + + + + + + o o @ X o + o + o + o + + X X O O + O O O . . O . . . o o o o o . o o . . . . ", +"9 2 2 2 w 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 , 1 , 1 , 1 , , , 1 1 1 , 1 , , , , , , , , , , , , > , > > , , , > , , , : , : , , : : , : > > : : : , : : : : : : > : : : : : : - : : : - : : - - - - - - - & - : - & - & - & & & & & & & & & & & & & & & # & : # # # : # & & # & # & # & # # & # & # & # & # # # # # # # # % # @ # # # @ # # @ # @ @ @ @ @ # @ @ @ @ X @ @ @ + + @ @ @ + + + + + @ + @ + + + @ + + + + + + + X + X + o + o X + + o o + o o o + o o o o o o O O O O O O O . . O . o . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , , 1 1 , 1 , 1 , 1 , , 1 , , , , , , , , , : , > , , , , > , > > , , , : , , : , : : > , : , : > > : , : : : > : : : : : : : : : : : : - : - : : : - - : - - - : & & - & - - - & : & & : & & & & & & & & & & & # & : & & : # : & & # & # & # & # & # # # # # # # # # # # # # # # # # # # @ @ # @ @ # @ # @ @ @ # @ @ @ @ @ X @ @ @ + + + @ + @ @ + @ + + + + + + @ + + + + + + + + + o + o + X + o + + + X o + + o o + o o + o O O O O O O . . O . o . . o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , , , , > , > , > , , > : , , > > , , : , > > > : > : > : : > : > : : > : : : : : : : : - : : - : - - - - - - - - - & : - - & - & & & : & & & & & : & & & & & & & & & & # # & # # & # & & # & # # & & # & # & # & # # & & # # # # & # # # # # # # # @ # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + X + o + o @ + o o + o o + o X + O O O O O O O O o o . . o o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 2 , , , , , 1 , , 1 , , , , , , , , , , , , , , > , , > , , , , , , : , , : , , : > > , > > > > , : : , : : , : > : : : : : : > : : : - : - - : - - - - - - - - - : & & & & : & & : & & & & & & & & & & & & & # & # & # & # & & & # & # & # & # & # # & & # % # # & # # % @ & & @ & @ @ @ # @ @ # # @ @ @ @ @ @ @ @ # @ @ @ @ @ + @ + + @ @ + @ + @ @ + + @ + @ + + + + + + + + + + + o + + o + o + + + O + + O + + + X X o o o O O O O O X X O O O O O O . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 2 2 , 2 , , , , , , 1 , , , , , , , , , , , , , , , > , : , : , : , : , , : , > > : > : : > : : , : , : : : : > : : : : : : : : : : - : - : - - : - - - - - : & & : : & & : & & : & & & & & & & & & & & & & & & & & & & & # & # # & # & # & # & # # # % % # # # # # % @ @ @ @ @ % @ # # @ # @ # @ # # @ # @ X @ # X X # @ @ @ @ @ @ @ + + + @ + + + + + + + + + + + + + + + o + + + + o + + X + O O + + o O o X X X + o O X X X O O O O X . o O O O X o O . . o o o o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 1 1 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 , , 2 , 2 , 1 1 1 , 2 , , 1 , , , , , , , , , , , , , > , : : , , , : , , : : , > > : , : : : , , : : : , : > : , : , : : : : : - : : - : - : - - - - - - - & & : & : & & & & & & & : & & & & & & & & & & & & # & # & & & # & & # # & # # & & # # & # & # & # # # & & @ @ @ % @ @ % # @ @ @ # @ # @ @ @ # @ # X # # @ @ X @ @ @ @ @ + @ + @ + + @ + @ + + + + + + + + + + + + + + + X + X + + + o + o X o + X X X + o + + o O + O O O O O O X o o O O o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 2 , 1 , , , , , , , , , , , 1 , , , , , , , , , > , , > , , , , : , , , : , , > , : , : , , : : : : , : : : : : : : : : : : : : : - : : - : - : - - - - - - : : : & & : & : & : & & & & & & # & & & & & & & & & & & & # & & # & & & # & & # # & & # # # # # & # # # @ @ & @ @ % # @ # # # @ @ # @ @ @ @ @ @ # # # @ @ @ @ @ + @ + + @ + + @ + @ + @ + + + @ + + + @ + + + + + + + + + + + + O + + + O + + X + o X X O O o o O O O O O O X X O X O O O o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 , , 1 , 2 1 , , , , , 1 , , , , , > , , , , , , > , : , , , , : , , : : , > > , : , : : > , : , : : : : : : : , : : : : : : : : : : : : - - - - - - - - & : & : & - & & & : & : & & & & & & & & & & & & & & & & # # & # & # & # & & & & # # # & # % & # & # # # # & # # & & @ % @ @ % @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + X + + + o + + X + + O + X + X + + O + O O O O O O O O O O O O . X O O o . o O . . o . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 2 1 , 1 , 1 1 , , , 1 1 , , , , , , , , , , , , , > , , , , , : , : , : , , , : > > : , : , > > : > > : , : , : : : : : : : : : : : : : : : - : : - : - - - - - & : & & & : : & & & & & & & & : & & & & & & # & # & & & & & # & & & & # # # # & & # & # # # # # # # # # # # @ @ % @ @ @ @ @ & @ @ # # @ @ @ @ @ @ @ @ @ X @ X @ @ + + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + + + + + O + + o X + + o O O O O O + O O O O O O O o O . O O . . O . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , : , : , , : , , : , , : , , > > , : > , : : : > > : , : , : : : : : : : : : : : : : : : - - : : - - - - - - : : & : : : & & : & & & : & & & # & & & & & & # & & & & & # & # & # # & & # & # & # # & # & # # & # # # # # # & @ @ @ % # # # # # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ + + @ + + @ + + @ @ + + + + + + + + + + + o + + + o + + o o + + o O + + O + X O + O O O O O O O O O X O o O O O X o . . . . . o . . . o ", +"e 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , , , , 1 , , 1 , , , , , , , , > , , , , , , , : , , , : , : , > > : > , : : , , : > > : : : : : , > : : : : : : : : : : : : : - - - - - - - - : & & - & & : & & & : & & & & & & & & & & & & & & & & # & & & & & # & & # & # & # & # # # & % & # # & # # # # # @ & % @ # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ + + @ + + + @ + + @ + + + + + + + + + + o + + X + + + + X X + X X + O O O + + O O O O O O O . X O . . . . . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , 1 , 1 1 1 1 , , 1 > , 1 > , , 1 , , , , , , , , , , , , , , , , : : , , : > > > > > , > > > : : , : > : : > : > : > : : : : : : : - : - - - - - - - - - & - - : & & & & : - & & : & & & & : & & & & & & # & & & # & & & # & # & # & # & # & & # # # & # % % % % % % % % @ # # # # # @ @ @ # # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X X @ + + @ + + @ + + + + + + + + + + + O + + + o + o + + O + O O O + O + X O O + O + X O X o O . . . . o o . . . . o . O O O O ", +"2 2 2 2 2 2 2 e 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 1 1 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 1 1 1 , , 1 1 , , 1 , , , , , , , , , : , , , , : , , : , , , , : , > > > > : : > : , : > : : : , : : > : : : : : : : : - : : : - : : : - : - - - - - - & : : : & & - - & & : & & & & & & & & & & & & & & & & # & & & # % & # & # & # # # & # & # # % % % @ % @ % % @ % @ # # @ % # @ @ # @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X @ X @ X @ @ + @ + + + + + + + + + + + + + + + + + O X + + o + X o O O O + O O O O O O X X O O O O O O . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 1 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , , , 1 , , , 1 , , , , , , , , , , : , : : , : , : , , : , : > > > > > > > > > > : > : : : : : : : : : > : : : : : : - : : - - - : - - - - - & : & & & : : & & - - & & & & - & & # : & & & & & & & & & # # & & & & # & # & # # & & # % # # # @ % % % @ % % @ % # # # @ % # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ + @ + + + + + + + + + + + + O + + + + O + O O + + O + o + O + O + O o O + O O O O O O O X . . . o . . O O . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , , 2 , , 1 , , 1 , 1 , , > 1 , , , , , , , , , , , , , , , , , , > , : , , , : > > > > > > > : : : , : > , : > > : > : : : : : : : : : : : - : : - - - - : - - - - : & : & & & - & & & & & & & & & & & # : # & # & & & & & & # # & % & & # # & % # & # # & % & % % % @ % % % # # # # # @ # @ # # @ @ # @ # @ @ @ @ @ @ @ @ X @ @ @ X @ @ @ X @ + @ + + + + + @ @ + + + X + + + + + + + O + + + + + o + + o + X + O O O O O X O O O O O X X . . . . o . X O o . . o O . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , , 2 , 1 , 1 , , 1 , 1 , 1 , , , , , , , , , > , , , : , : , , : , > , : , > , , , > > > > > > > > : > > : : > : > : > : : : : : : > - : > - : : - - : - - - - - - - & - & & & : & & & & - & & & & & & & & & # & & & & & # & & & # # & & & & # # # % % & % # % # # % # @ % % # # % % @ % @ # # # $ # @ # @ @ @ @ @ @ @ @ @ @ # @ @ + @ @ @ X @ X @ @ + @ @ + + + + + + + + + + + + + + X + + + O O + O O + O O + o O + O + O O O O + X O O O O O . o . . . . o . O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , 1 , , , , , , , , , , , , , , > , , , , > , > > > , : > > > > : > > > > > : > > : : : : > : > : : > : - - : - : - - : : - - - - - - - - - - : : & & : & - - & - & - & & & & & & : & & & # & & # & & & & # # # # & & & & % % % % % % # % % @ % % # % @ # # @ % # # @ # @ # @ @ # @ @ @ @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + + @ @ + + + + + + + + + + + + + + + + + + + + + + O + o + + O O O O + O O O O X O o O O . o O . o . . o O O O O O . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , , , , : , , , , : , > > > > > > > > > > : > > > > : > : , : : : : > : : : : - > > - - - : - - : : - - - - - & : & : : & & : : & & & & & & & & & & & # & & # & & & & & & # & & & & # & # & # % % % % # # % & # % % % # # # # @ % # # # # # @ @ # # @ # @ @ @ @ @ # X @ @ @ @ @ @ @ X + @ X @ + @ @ + + + + + + + + + + + + + o + O + + O + O O + O O + + o o O + O O O + + O O O O O O X O . o . o o . . . . O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , : , , , : , : , : , , > > > > > > > > > > : : > > > : > : : > : : : : > : : > - - - - : - : : - - : - - - - : & : & & & : & & & - & & & : & & & & & & & & & & # & & # & # & & # & # & & # & % % % % & # % # % # % % % % # # % @ % @ $ # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ X @ + @ @ X @ + @ + + @ + @ + + + @ + + + + + + + + + + O + + + O + O + o X + O X + O O O O O O O O O O O . O o o . o o . . O O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , , 1 1 , 1 > 1 1 > 1 , , , , > , , , , , : , , : , , , , , > , > > > : , > > > > > > > > : > : , : , > : : : > : : : - : : : - : - : - : : - - - - - & : & : & & : & & & & & & : & & & & & : & & & : & & : & & & & # # & & # & # & # # & % % % % % % % # # # % % # # # % # @ % @ @ % @ # @ # @ # @ # @ @ @ @ # @ @ @ @ @ @ + + @ + + + @ + + + + + + @ + + @ + + + + X + + X + + O + + X X X + O + O O + + o o O O O O O O O O O X . . . o . . o . o . . . o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 1 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 1 > 1 > , , 1 , , , , , , , , , , , , , , > : , > > > > > , : , > : : > : > : > : : : : : > : : : : : : > : : : : : : - : - : - - - - - : & : & & : & & & : : & & & & & & & & # & & & & # & # # # & # & & # # & # & # & & % % % % % # % % % % # # # % # # @ @ % # # # # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + + @ @ + + @ @ + @ + + @ @ + + + + + + + + + + + + + X + + + + + + + X + O X O X X + O O O + O X O O O O O O . . o . o . O o O . o O O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 > 1 1 > , 1 , , , , , > , , , , , , > , : , > , > , > , , : , : > > : > > : > : , : , : : : > : : : : : : - : : : - - - - - - - - - - - : : & : : & : & & & & - & : & & & & & & & & : # & & & & # & & & & & & & & # & # # % % % % % % % # # # % % # # # # % @ # @ # # @ # # # @ @ # @ @ @ @ @ @ # # @ @ @ @ @ + + @ @ X + @ + + @ X + + + + + + + + + + + + + O + + + X X + X X O + O + O O X X O O O O X O O O O X o O . . o . . o . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , 1 1 , 1 1 > 1 , , , , , , , , : , , , : , : , , , > > > > > > > > > > > > > > > > : , : : : : , : : : > : : : : : : : - : : : : - - : - - - - & & : & & & : & : & & & & & & & & & & : # # # # & & # & & & # & # & # # # & # & # & % % % % % % % % # % % % % # # # % # # # @ # @ # @ @ @ @ @ @ @ # X @ # X @ @ X + @ @ @ + @ @ @ + @ + + + @ + + + + + + + + + + + + + + + X + O O + + O X X + + O + X O O + O X + O O O O o O . O . . . . o . o . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , 1 , , , 1 > , , , , , , > , , , , , , , , , , , > : > > > > : , > , : : > , : > > : : : , : : : : : : : : : : : : : - - : - : - - - - - - - : : & : : & - & & & - & : & & & & & & & & & & & & : & & & & # & & # & & & # % % % % % % % % % % % % % % # # # % % # % # % # # # # # @ # @ @ @ @ @ @ @ @ @ @ X # @ @ @ + @ + @ + + + @ + + + + @ + + + + + + + + + + O + + + O + + + + O + O + O O O O O + O + X O X O O O O O O O o o o o o . . . . . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , , , , , , , , , 1 , , , , , , , , , , , : , : : , , , , , > , > > , > : : , , : : , : > : : , : : : : , : : : : : : : : : : : - - - : - - - - - - & & : & & - : & : & & & & & & & & & & & & # & & & # # # & # & & % % & # % & % % % & % % % % % % # % # # # # # # # # # @ @ @ % @ # @ @ @ @ # @ @ @ @ @ X @ @ @ @ @ @ @ @ + @ @ X + @ + @ @ + + + + + + + + + + + + + + + O O + + + O O + O + O + + + O X O O O X O O O O O O O . O o o o . . . o . . . o o o o O ", +"2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , , , 1 , 1 , , , , , , , , , , , , , , , > , , , > , : , , , > > , > : , , > > > , : : : > > : : : : : : : : : : : : : : : : - : : : - - - - - - - - : & : & : & & & & & & & & & & & & & & & & & & & & # & & & & # & % & % & % & % & % % % % % % % % % # % # # % # # % @ # # @ # @ @ @ # # # @ @ @ @ @ @ @ @ @ @ @ # + + @ + @ @ + @ @ @ + + + @ + + + + + + + + + + + + + + + + + O + O + O O X + O O O O + O O O O O O O O O O O o O . . . o . . o o o . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , > , , > , , , > : , , > > , > > > > : > > > : > : , > : , : , : , : : : : : : , : : : - : - - : : - - : - - - - & : & : & - & : : & & : & & & & & & & & & & & & : # & & # : # # & % & # & # % % % & % % % % % % % # # % # # # # $ # # # @ % % # @ @ @ @ @ @ @ @ @ @ @ @ X # @ X @ @ @ + @ + @ + + + @ + + + + @ + @ + + + + + + + + O O + + + O + + O + + + O O + O + O O + O O O O O O O O O O . . O . . . o . . . . o o O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , > , , , > > > > > , > , > > , : , : , : > : : > > > > > : : > : : > : : : : : : : : : : : : : & : & & : - - : - & : & : # : : : # : : & & & : & @ - - - # - - - @ - - @ # - # # - - # # - # # # # % % - # # % % # # # # # # # # # # % # # @ % # # @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + + @ + + + + @ + @ + + + + + + + + + + + + + X X + + + + X + o + O + O O O + X O X o O + O O O O O O . . . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , , 1 1 1 1 , , , , 1 , , 1 , , , , , , , , , , , , > 1 > 1 > 1 > > , > > , , : , > > : , , : : > : > : > : > > : : : : : : : : & : : : : : : : : : : - : & : : & : & : : : # # : : # # : : # - - # - @ - @ - - @ @ - - # - # # % # - # # % - - % % % # % # % % # & # # # # # # # # # # # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ + @ @ # + @ @ + @ # @ @ + @ + + @ + @ + + + + + + + + + + + + X + + + o X + + O O + O O o o + o o o O O O O + O X X . . . o . . o . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 2 2 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , > , , , 1 > > 1 > > > > , : : , > > , : , : , , > > > > > : : : : > > : > : : : : : : - & : : : : : - & : & : & : & & : : # : : : # : : & : & & # - - - - - # - - - - - # - - # # - - # # - # - # % % % % % % % & # # # % # & # % @ % % # # # # @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ + + + + + + + @ + + + + + + + + + + + o + + + + o X + o + O + X o + o + + + O O O O O O O X o X O . o o . O X O . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , 1 1 , , 1 1 , , 1 , , , , , , , , , > > > > > > > , > , , , : > , : > : , : : : > > > : > > : : : : : : : > : : : : : : : : : : & : : & : & : : & : & : : # & : : & & # : # & - - # # - # - # @ # - @ # - # - - # - # # - # % # % % % % % % % # # # & # # # # @ % @ % # @ @ # # @ @ @ # @ @ @ @ @ @ @ @ + @ + + # @ @ + @ + @ + @ + @ + @ + + + + + + + + + + + + + + o + + X + + X + + X + + O + o o O O + O O O O O X o O . . o . X . X . o o . o O O O O ", +"2 2 2 2 2 2 0 2 2 2 2 2 1 2 2 1 2 1 2 2 2 1 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 1 , , , , 1 , , 1 1 , , , , 1 , , , , , , > > 1 > > > > , , > , : > > , , : , > , : > , > > > : : > : > : : > : : : : : : : : : : & : & : : : & & : - - & : & & : & : & & : : # : # : # @ - - - - # - - - @ - # - # - # # % # - # # # % & % % % % % % % # % # # # % # % % # # # # # # @ # @ # @ # @ @ @ @ @ @ @ @ @ @ @ # + # + + @ + + # @ + + + + + + + + + + + + + + + + + + + + + o + X + + + o o X O O O X O O O O O + X O O . X X . . O o . . . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , 1 , , , , , , , , , > , , , , , , , > , 1 : > > > , > , : : , : , > > : : > : : > > : > : : > : : : : : : : : : = : : : : & : & : : : & : : & : & & : & & : : # : & : : : - - @ - - - # @ - - # - - # # # - % - # # - - % % % % % % % % % % % % # # # % # # # # # @ # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ + @ + # # + @ + @ + + + + @ + # @ + + + + + + + + + o + + o X + + + + X X + o + + X + + O + O O O O O O O X . O o O O . o o . O . o o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 1 , 1 1 1 , , , 1 , , 1 , , , , , , , , > > , > > > 1 > , , : , , , > > , : : , : > , > > > > : : > : > : : > : > : : : : : : : : : : & & : : : - & - : & : & : : : & : # : & & & & # : - - @ - # - - - # - # @ # - # - # - # # # # - % % % % % % % % % # # # % % # # # # @ % @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ @ + @ + @ + + @ + + + + + + + + + + + + + + + + + X + + + + + X X X X + o X + O + + O + O O O O O O O O . O O o o . O . X o o . . o . . O O O O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , , , , 1 , , 1 , 1 , , , , , , , , , , , > , , , , , 1 > > > , : , > > : , > , : > > > > : : : : > > > : > : > > : : : : : : : : : : : : : : : : : & : & : & : & & : & & & & # : : # : & & & # - - - - # # - - # - - - # - # - # # - - # # # % & % % % % # % % % % % % # # # # # @ % # # % @ # @ # @ @ @ @ + @ @ @ @ @ @ + @ + @ @ @ @ + @ # + + + # + @ + @ + + + + + + + + + + + + + X o + + + X + X + + o + X O O O O + O O O O O O O O O . . . . O O . . . . . O O ", +"2 2 2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 1 1 2 1 2 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 1 , , , 1 1 , , , 1 , , , , , , > , > , , > > , , , : , : , : : , : , : > : > , > > > : > : : : : : : : : : : : : : : - : - : - : - - - - - & : : & : & : : : : : : & : # & # : # - - - # - - # - - # - - # - # # & & # # & # & % % & # # & # # # # # - # # % # + - - + - + + - # @ @ @ # @ # @ @ + # # @ + @ + @ + + @ @ + @ + + + # + @ + + + + + + + + + + + o + + o + o + + + O O + O + O X X O X O O O + X O O O O O O X . . . . . o . . . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 1 2 1 2 1 1 1 2 1 2 1 1 1 2 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , , 1 , , , , , 1 , , , , , , , , , , , , , > > 1 > : , , , , , , , : , , , > , > : > : : > > : > : : > : > : > : : : : : - - : - : - : - : - - : : & : & & & : # # : # : # : : : # - - # - - # - # @ # - # # - # # & # & & & # & # % & # & # % # % # # # # # # # # @ + + - O - + $ # # @ # @ @ @ @ # + @ + @ # @ @ + + # + @ + @ @ @ + + + @ + + + @ + + + + + + + + + + + + + + o + + + O + O + + + O + O X O X X O + O O O X O O . . . o o o . . . . . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 2 , 1 1 1 , , 1 1 1 1 , , 1 , 1 , , , 1 , , , , , , , , , , , > , , , > , > > , , : : , , : , : , : : > , : > : > : > > > : > > > : : > : : : : : : : : : : : - : - - : - & : & : & & : : # : : : : & : & : & & # - - # # # - - - # # - - # # - & # & # # & # & & & # # # & % % # # + - # # # # - + + + - O o + @ @ @ @ @ @ @ @ # # @ @ @ @ + @ # + @ @ @ + @ + + + @ + + @ + @ + + + + + + + + + + + + + + + o X + + X O + O O X + O + o o X X O O O O O X O O . . . o . . . . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , 1 , , , , , , , > , > , , , , > , , > , , : , , , : , , : , : , : > > : : : > : : > : : : : > : - : : : - : - : - : - - - - & : & : : & : : : # # : & & # : # : - - # - - - - # - - - - # - - # # & & # & # & # # % & # # % % # - # # # # # % # - @ - @ O - - + # @ # @ @ @ @ @ + @ @ # + # # @ + @ @ + + @ + @ # + + @ + + + + @ + + + + + + + + + o + + o + + + O X + O O + + O O O O X + X X O O O O + X O X O O o . . . o o o . o . o . o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 1 1 , 1 1 , 1 1 , , , 1 1 1 , 1 , , 1 1 , 1 , , , , , , , , , , > , > , , , > > > , : > , : , , : : , : , : : > : : , , : > > : : : : > : : : : : : : : : : - : - - - : - - - - - : & : & # : : : : # & : : : & # - # - - - @ @ - @ + - - # - # - & & & # # & # & # & # # % % % & - + # # - @ + - + - + @ + + - - # # # @ @ # @ @ # @ + + + @ @ @ @ @ + o @ @ @ @ + # + + + + + @ + + + + + + + + + + + + + + + o + + X O + O + O O O O O + + O + + + + O O + O O O O X X . . O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 2 2 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , , , 1 1 , , , , , , , , , , , , > , , , , , , , : , : , : , : : , : , > : : > > : : > > : : : : : : : : : : = : : - : : - - - - - - & & : : & : : # : : : & : & & : : - # - # - - - - - - - @ - # - # & # # & & # & # # # & & % # # # # + - + + + - @ @ @ + - - + + + @ # + # @ @ @ @ # + # @ # # + + + + # @ @ o + o + @ + + @ + + + + + + + + + + + + + o + o + + + O + X + O O O O + O + + + + + + + $ $ $ + $ + + + O O O O . . . . . . . o ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , , > , > , , > , > , , : : , , : , : , : , , : > : > : : : : > > : : : : : : : : : - : : : : : : - - : - - - - - - : & & : # : : # & # : # & & & & - - # - # - - # @ - - @ # - # - # & & # # & % & & # % % & % # % + - - + @ # + @ + - @ @ - + + - # @ # @ # @ @ @ + # + # @ + + @ @ + @ @ + @ @ + + + + + + + + + + @ + + + + + + + + o + + + o o + O O + O + O O + O + + @ + % % $ * # * * @ $ + + + O O O O o o o o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 2 1 1 1 1 1 1 1 1 1 2 1 , 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , 1 , , , , , , , , , > , , , , , , > , > > , : , , , > > , : , : , : : , : , : , , : : : : : : : > : : : : : : : : - : - : - - : : - - - : & & : : & : & : : : : # : & : # & # - - - @ - - # - - @ - - # - - & # & & & # & # # & % # # # # & - @ + - + - - O - @ + - + - + + @ # # # + @ @ @ @ @ # # + # # @ + # @ @ + + @ @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + O + + O + O + + + + + + % # * ; ; > : ; ; = * $ $ + + + O . . . . . o . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 2 2 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , 1 1 , 1 , , 1 1 , , , , , , , , , > , , , > , : , , , : , , : : , : , : , > : > : : , : > > : : : : : > : : : : : : : - : - : - - - - - - & - & : & : & & & : # : & & # : : & & & & & # & & & - 8 4 4 4 8 < 4 , , , < 4 4 4 8 4 4 4 4 4 4 4 4 4 4 4 4 8 4 4 - $ @ $ - + + - o # @ @ @ @ @ + @ + # @ + @ + # + @ @ + @ @ + @ + + + @ + + + @ + @ + + + + + + + + + + O + + + O + + X + + o + + + + + # = ; 5 7 2 e e e 1 7 < = # @ + + + O X . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 , 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , , , , , , , , , , , , , , > , > > , , : : , , : , , : , : , : > , : , > : : > : > : : : : : : : : : : - : : : : - : - - : - - : - : & : & & : & & & : & : & & & & & & & & & & & & 4 v v v v v v v v c v v v v v v v v v v v v v v v v v v v v v v k ; - + + - - $ # # @ # # @ # # @ @ @ @ @ @ + @ + @ @ + + @ @ + @ + @ + + @ + + + + + + O + + + + + + + O O + + O + X + o + O + + @ * * > 7 e s n M M m n f e 7 > * # + + O . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 > 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , , > , , , , , , : : , , : > , : > , : : , : > , : > : , : : : : : : : - : : : : : - : - : - - : - : & : : & : : & : & & & & : : & & & & & & & & & & # 4 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k $ @ O - $ @ # @ @ @ @ @ @ @ # @ # @ # # @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + + O + + X + o + o + + $ # * > w f M S U T R T K S m f 9 : * % + + O X . . . X . . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 , 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 , 1 , 1 , 1 1 , 1 , , 1 , , , , , , > > , , , : , , , : : , , , , : > > , : , : : , > : > : : : : : : : , : : : : : > - : - - - : - : - : - - : & : & & : & & & : & : & & & & & & & & & & & & & & & 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x ; - + O # @ @ # @ @ @ # @ + @ + + + # + @ + @ @ + @ + @ + + @ + + @ + + + + + + + + O + + X + O + + + + + + + X + + + @ $ ; > 0 f C K ! ..;.;.;. .~ Y B f 7 : * $ + O . . . . . X X X X X X X X X . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 > 1 1 , , 1 > 1 > 1 , , , , , , , , , , , , , > > , , , : , , , : , > , > : , > > : > : : > : : > > : : : : , : : : - - : : : - : - - : - : & : & - : & : & & & : & & & & : & & & : & & & & & & # & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v l - # @ @ @ @ @ # @ @ @ @ @ + @ # + @ + @ @ + @ + @ + @ @ + + + + @ + @ + + + + + + + + + + O + + + O O X + + o X + + $ # ; 7 y A R { <.2.7.9.7.2.>.{ R A r 7 = $ $ + X O . O X + X X $ + + + X X X X ", +"2 2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , 1 1 1 1 > 1 1 , , , , 1 , 1 > , , , , , , , > > , , : , , , > : , : , : , , > , : , , : > : > : > , : : > : : : > : > : : : : > : : : - : - > - - : - : & : - : : & & : & : & & : : # & : # & & & & & & & & & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k # $ # @ # @ @ @ @ @ @ @ @ @ @ @ @ # + @ @ + @ + @ + @ + @ + + + + @ + + + @ + + + + + + + + O + + + O + + O + + + % = , e M K ..1.9.w.j.j.j.w.7.1.{ Y M w 5 * $ + + O O . + + + $ $ $ $ $ * $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 > 1 1 , , 1 , , , 1 , , 1 , , , , , , , , , , > , , , , > : , , , , : > : > > : , , : : , , , : : , : : > , : : : : : : : - : : - : : : - : : - - : - - - & : & : : - & & & & & : : & & & # & & & & & & # 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 $ # @ @ @ # # # @ @ @ @ @ @ + @ + + # @ @ + @ @ + + + + + @ + @ + + + + + + + + + + + + + + + O + + + O + + + + # ; 7 f S ~ <.9.g.l.x.x.x.l.h.9.>.! G r 6 & $ + + O O + + + % * * = = 3 * * = $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , , 1 , 1 , 1 > , 1 > , , , , , , , , , , , , > > > , , , : , > > , , > > > : : , : > : : : , : : > : > : : : > : : : : : : : : : - - - - : - & : : & : & : & & & : & & : & & : # : # : & & & & & & & 0 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v c # # @ # # @ + @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + @ + @ @ + + + + + + @ + + + + + + + + O + O + + O + o + o + + @ % : 7 n U ..2.w.l.m.M.N.M.m.l.w.2.{ Y b 9 = $ + + + + + $ % = > 6 7 9 9 9 7 5 5 = ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , 1 , , , , , 1 , , , , , > , > > , , , , , > , > , : , , : , : , : , : : > > : , : : > : : : : : : : : : : : - : - - - : : : & : & & & & : & & : - & : & # : : # : & : & & & & & & & & , D c v c v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 # @ @ # # @ # @ @ @ @ + @ @ @ + @ + @ @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + O + + + + + * > e m T :.8.h.z.M.C.C.C.M.z.j.7.;.T M w ; $ $ X + $ $ * ; 7 w r b m M m b s 9 5 = % $ X $ . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > > > , , > > > , : : , : , : , : : , : > , : : : : > : > : > : : : : : - : - : > - & & : : : : : : & : & : : # - & & - & & : : # : & & & & & & & # : h l l l l l l l l l l l l l l l l l l l l l l v v v v v v v v v v v v v v v c @ # @ @ @ @ # + @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + @ + + + + @ + + + + + + # + @ @ + $ + + + + O + X + X + + $ & ; e C R :.9.h.m.V.Z.Z.Z.V.x.j.7.:.T M e 5 $ $ + + $ * : 7 r b S K T T T K A m s 7 3 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 2 1 2 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 , , , , 1 , , , , 1 , 1 , , , , 1 , , , , , , , > , > > , > , , > , , > , > , , : , : , : > , : > : : > : > : > : > : : : : > : : > - : - > - : : & : & : : & : & : & - - : & : & & & & # & : & & & & & & & & & & - & & # & # - # - - # & - % # - # # # & % % # g v v v v v v v v v v v v v v - - # @ @ @ @ @ @ @ @ @ @ @ + @ @ + + @ + @ + + @ X + @ + + + + @ + + + @ % # # # @ % $ % + + + + X + X + + + & > e M R ;.7.h.m.M.C.C.C.M.x.h.7.;.T M w ; * $ + $ * ; 7 s A T R ..-.-.-.{ ! K B s 7 3 $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , , , , , , , , , , , , , > > , > , > , > > , > > , > , : > , : , : , > : , : > : > > : : : : : : : : : : : - - : - : - - & : : : & : : & & - - - - & & - & & & : : : # # & & & & & # & & & & & & & & # & # - # # - # # # # # # & % % # # # @ g v v v v v v v v v v v v v i o @ @ # @ # @ @ + @ @ @ @ + @ + @ @ + @ + @ + @ @ + @ + @ + @ + @ @ # % # % % = # * * * @ # % $ + + + + + @ * ; w b K { 2.q.l.m.M.V.M.m.l.w.2.{ K b 7 ; $ $ $ $ = 6 r C R { >.2.2.8.7.2.>.{ Y C s 4 * * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , > , , > , , , : , : > , : : , : : > : : , : : > : : : > > : : > : : : : : - : : : > - - > : : & : : : & : : - : & : # - & & : # : & : : & & & & & & & & & # & # & & # & # - # # - # # % % & # # # & # & # # # - v v v v v v v v v v v v v c @ @ @ + # # @ # + + # @ @ @ @ @ + @ @ @ + @ + + X @ + + @ X + + @ $ % & = = : < < > : ; = # @ $ + + + + + $ # = 7 b S ~ <.9.h.l.z.x.x.l.h.9.>.~ G s 7 * % $ $ % 3 e m K { 1.8.f.h.j.h.f.8.1.{ U b r ; * . . . ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , , 1 1 1 , , , , , , , , , , , > , , , : , , > : > , > , > , > , : , > > > , : : , > > > > : : : > : : > : : : : : - : - - - - - : & : & : : & : & & : : : & & & & : & # & : # & & & & & & # & & & & & & & & # # - - # # - # - & % & % & # % # # # # p v v v v v v v v v v v v v - @ @ @ # + # + # # # @ + @ + @ + + @ @ @ + + + @ + @ + + @ @ @ # * = : 5 7 e e e e e 7 5 > = $ $ $ + + + + $ & , e b Y { 1.9.w.g.j.j.w.9.1.{ K M e : % % $ % = 7 s G R <.8.h.l.z.m.z.l.h.8.>.R A s 5 * + . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 1 2 1 1 2 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , , 1 , 1 1 , , , , 1 1 , , , , , , , > , , > , > > , > , , , , > > > > > , , > , > : > > > : : > > : : : > : : : > : : : : : - > - > - - : - : - & : : & & : & : & # : : : & : & : # : & & & & & & & & & # & & & & & & & # - # # # # - % # & # % # # & % - # # ; v v v v v v v v v v v v v < @ @ @ @ @ # # # # + + @ @ + @ @ + @ + @ + @ + + + @ + @ + $ % % : 5 7 r b b M M M m f r 7 < = # $ + + + + $ % = 7 y A T { >.2.7.7.7.2.>.{ T A r 7 = * + % % = 7 b K .2.f.l.m.M.M.M.m.l.g.2...K b 7 . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 1 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , , , , , > , > , > > , > > : : , : > , : , : , : : > > : : > : > : : : : : : : : - - - : - - & : : : : & : : & : # - : - & & & # : : & # : & & & & & & & & & & & # # & # & - # # - - # # # % # & # # % # # # # # # l v v v v v v v v v v v v q - @ @ @ @ @ @ @ + @ # @ @ @ + @ @ @ + + @ + @ @ + + @ + $ % & : 5 w f M K K R Q R K S M b 9 5 = & $ + + + $ $ = > 7 b A Y ~ -.;.:.-.-.~ Y C f 9 > * $ + $ % : w b Y ;.8.h.z.M.C.C.C.M.z.j.2.-.T b 9 ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 2 , 2 , , 1 , 1 , , , 1 , 1 , , , , , , , , , , , , , , > > > , , > > > > > > : , > : , : > > > > : > > : > > : : : > > : : : : : : : : : : : & : : & : : - & - - & & & : & E u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.v.u.} 6 % & & # & & # # # & % % % % % # # % # % # * i v v v v v v v v v v v v a - o - O + + + - + + + + + @ @ + @ @ + @ # + + + @ + $ @ @ # = < e f G Y ^ ..:.>.;...^ K S b 9 < = @ + + + + $ % = : 9 s M S K T R T K A m s 7 : * $ $ + $ $ ; e C T :.8.h.m.N.C.Z.C.N.x.h.8.:.T N w ; $ + O . . ", +"2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 2 , , 1 , 1 , , 1 , , , , , , , 1 , , , , , > , > , > , > , > > , > , > , > , : > : : , , : > : > : > : : : : : : : : : : : : : : : : & : : : : & : : & : & = - - : & & : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.E % & & # # & & & # & % % % % % % % % # # # q v v v v v v v v v v v v k o - @ @ - + + O - + - O - + @ + @ + + + + + @ + + @ @ @ $ ; ; 0 f A R .<.2.7.9.7.2.<...R C f 7 : # $ $ + + + $ % * 3 7 e s m M M m m f w 7 > * % $ + + + * ; w b T ;.8.g.z.M.C.Z.C.M.z.h.7...T b 9 * $ + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , > , > , > > > > > > > > : > : > , : : , > > > > > > : > : : : > : : : : : : : : : - & : & : & : : & : : : & : & : & & +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.E # & # & & # & # % % % % % % % % % % $ # 3 v v v v v v v v v v v v k - o O @ + O - - O @ + + + + + # @ @ # + # @ + + + @ + # % ; < r M Y .1.9.w.j.j.j.q.9.1...K M e 7 = $ + + + + + $ % = : < 5 w w e w 7 5 5 ; * % + + + + + $ ; 7 b K { 2.f.l.m.M.N.N.m.l.f.2.{ K b 9 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , 1 , 1 1 , , , , , 1 , , , , , , , , , > , , , , , , > > 1 > > > , > , , > , > : : , : : > : : : : > : : > : : : : : : : : : : : : : - : : : & & : : & & : & : & : & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.m & & & # & # & & % % % % % % % % # # # 4 v v v v v v v v v v v v k o - - @ @ - O + + @ - o - + + # + + + @ + + @ # + + @ @ ; ; 0 f S ^ <.9.j.l.x.x.x.l.j.9.<.^ S s 7 = $ $ + + + + + $ @ # = = ; > ; ; ; = * % + + + + O + + $ * 7 r A { >.8.g.l.z.x.z.l.g.8.>.R S s 6 * $ O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 2 , 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 1 , , , 1 , 1 1 , , 1 , , , , , , , , > , , , , > , > 1 > , > > > > > , : , : , , : , > : > > > : > : > : : > : : : : : : : : : : - : : : & : : & & : : & : & : & & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.k.# & & % % % # % % % % % % % % % # # # 4 v v v v v v v v v v v v k + O $ - + + + + # + + - + + @ @ + + + + + + + @ + + @ # ; ; w n Y ..2.g.l.m.M.N.M.m.l.f.2. .K m w ; * + + + + O + + O $ $ % % $ * % * $ $ $ + + O O O O + $ % 5 r b K { 1.8.f.g.h.h.f.8.1.{ Y b w : $ $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 2 2 2 , 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , 1 1 1 1 1 , , 1 , , , , , , , , , , , , , > , , , > > , > , > > > , , > > > : , : , : : , : > > : > : > : > > : > : : : : : : : - : - : : - : & : : & : : & & : & : & = : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.L & # & % & & % % % % % % % % % % # % 4 v v v v v v v v v v v v k - O - + - + + - + # + + @ + + @ @ @ @ @ @ @ # + @ @ # # - > e M Q :.7.j.x.N.C.Z.C.M.x.h.8.:.Y B e > * % + + + X + + + + + + $ $ + $ + + + + + O X O O + + % = 5 s C U { >.2.8.8.8.2.>.{ T C s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , > > > > , > > > > > > , : , : , : : , > : > > : > : : : : : : : : : : : : : : : : : & : : : & : : : : & : & : : & & t D V V V N D V N V V V x V V V o.Z.Z.Z.Z.Z.Z.Z.Z.Z.0.# & & % % % % % % % % % % & % # % # 4 v v v v v v v v v v v v k - - o + + + @ @ + # # + + # + @ @ @ @ + @ + + @ + + # # - < r B Q :.9.j.x.N.C.Z.Z.B.m.j.9.>.Q B e > # @ + + X O + X X + + + + + + + O + O O O X X X O X O + $ % ; 7 f C K ! { ;.:.-.{ R Y C s 7 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 , 2 1 1 1 1 1 1 1 2 , 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 , , 1 , , , 1 1 , , , , , , > , , > , , , , , > , , > > , , > , > : , : , : , : : > > : : > : > : : > > : > : : : : : : : - : : : & : : : : & & : : & : & & : & & & - & & & - - - & & - & & & % # } Z.Z.Z.Z.Z.Z.Z.Z.Z.< # % & % & % % % % % % % # % % % % 8 v v v v v v v v v v v v k o O + - - o @ @ @ # + o - + @ @ + + + @ + @ + + @ @ # # - < e M Q ;.7.h.x.N.C.C.C.N.x.h.9.:.R M e > * + + + + O O O O X O + O O + O O O X O X O O O O O O + $ % 5 7 f b S K T T Y K S b s 7 > = $ + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 1 2 , 2 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , > , , > , > , , > > , > > > > > > , , > > > > > > > > : > : > : > > - > : : : : : - : : : - - - : : - - - : & : : & : & : & : & : & - & & & & & & & & & # & & & & = v.Z.Z.Z.Z.Z.Z.Z.Z.P # % % & # # # # # & # # # # % # # i v v v v v v v v v v v v k @ @ - + @ @ @ @ @ @ + @ @ + @ @ + @ @ + @ + + + + $ + % = < w n Y ..2.f.l.m.N.B.N.x.l.f.2...U b 9 : # @ + + O O O O O O O O O O O O O O o . O O X O O O O O X + $ * ; 6 e r b m M b b r e 7 3 * $ + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 , , 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , , , 1 , , , , , , , , , , , , > , > , > , > , > , > , : : > : > , : : : > > > : > : : > : : > : : : : : : : > - > : & - : - : & & & & : : & & & & & & - & - & & & & & & & & & & & & # } Z.Z.Z.Z.Z.Z.Z.Z.o.& & # & # & & & # # & & # % # # # l v v v v v v v v v v v v u # @ + o - @ @ @ @ @ @ @ o - + @ @ + @ + + + @ @ + @ + % % ; 9 b H ^ <.9.h.l.x.x.x.l.g.8.<.! S b 7 = % @ + X O + + O + O O O + O O O X X o o O O X O O X + + $ * ; : 6 9 w e e 7 6 : * $ $ + X . ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 : , & 1 : 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , , , > , , > , , , , > > > > , > > > > , > > > , : : > > > > > > : > : > : > : : : : : : : : - : - - - : : - : : : : : & & & : & : & : - & & - - & & - & & & & & & & % & j Z.Z.Z.Z.Z.Z.Z.Z.u.% & % % & # # & # # # # # % % # - v v v v v v v v v v v v v q - o + @ @ @ @ @ @ @ @ + + @ + @ @ + + @ + @ + @ + + % # % ; 1 r M Y .1.9.f.j.j.j.q.9.2...K M r < = # @ + + O O O O O X + O O O O O O O X X O O o O . . X X + $ $ $ ; ; ; = = * * * $ + + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 L J J L J W W W W W W B Q L L L C 7 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , , , C J F J J F F L F F J J F J , , , , , > , , , > 9 F F F F F F F F F C F F F 2 , : > > > : : F D F D D D F 7 : : : - - : : : Z F Z Z Z Z Z - & : & & : : : & : & - & & & - & & - & & & & & & & & & & # & Z.Z.Z.Z.Z.Z.Z.Z.u.# # & % # # & # & # & # & % # % u v v v v v v v v v v v v v ; @ @ o - @ @ @ @ @ + @ @ @ @ @ @ + @ @ + @ + + + + + + $ % = > 1 b A R ..<.2.9.9.9.2.<. .R A f 1 ; * % + O + + O + O O + O O O O O O O X o o O O O O X . . X . X + + + + $ $ $ $ * $ $ + + + X . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.m.C.C.Z.Z.Z.Z.Z.b.J 1 1 1 1 1 1 1 1 , , 1 , 1 1 I b.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.> , , , , > , > w &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F : , : > : > > 6.Z.Z.Z.Z.Z.Z.` : : : > : : : I Z.Z.Z.Z.Z.Z.u.& : & & : : & : & & & & & - & & & & & & & & & & & & & & % & & B.Z.Z.Z.Z.Z.Z.Z.B.# & & # % & # & # # % % # # # - c v v v v v v v v v v v v v + + - # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ + @ + + @ + @ % # ; < w b A K ^ ..;.>.;...^ Y A f e < = @ + + + + O + O + O O O O O + O O O . O O O . o . . . . . . + + + + + + $ + + + O . . + . . O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.N.V.Z.Z.Z.Z.Z.Z.Z.Z.I 1 1 1 1 1 1 1 1 1 1 1 , [ Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , > , , , , k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F > : > > > : > D Z.Z.Z.Z.Z.Z.r.: > : : : : > 6.Z.Z.Z.Z.Z.Z.I : : - : : & - & : & : & : & - - & & & - & & & & & & & & & % & u.Z.Z.Z.Z.Z.Z.Z.Z.& % % # & # & # % & % # # # @ a v v v v v v v v v v v v v k - - O @ @ - o @ @ @ @ + @ @ + + @ @ + + @ + @ + @ + + @ + @ % # ; 5 w b B S Y Y Q R Y S M s w < * % @ @ O O O + O O O + X + O O O O O O O o . O X O O o o . o . . . . . . O O O . + O O O O + + + + + + + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 , 1 , 1 1 1 H Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , , &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.F > , : > : : > > v.Z.Z.Z.Z.Z.Z.7 : : : : : 7 Z.Z.Z.Z.Z.Z.v.: : & & : & : - - & & : - & & & & & - & & & & & & & & & & & & & B.Z.Z.Z.Z.Z.Z.Z.B.# & % & # # # % # # # # # % i v v v v v v v v v v v v v v 4 - O + @ @ @ @ @ @ @ @ @ @ @ + + @ + @ @ + @ + @ + @ + + @ + # % = - > 7 r f m B B M n b e 7 > = % @ + + + O O O + O O O X O O O O O O O O O o . o o . . . . X . . . . . . X . . X . O + O X $ $ $ $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.3.1 1 1 1 1 1 1 1 , , p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , > y Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.C.F > : , : , : > : | Z.Z.Z.Z.Z.Z.` : : : : : ` Z.Z.Z.Z.Z.Z.o.: & : : & : : & - & : & : & - & - - & & & & & & & & # & & & # & Z.Z.Z.Z.Z.Z.Z.Z.s.i i i p p p i p i p p a k v v v v v v v v v v v v v v v c $ + + - # @ @ + @ @ @ @ + @ @ @ @ @ @ @ + @ + @ + @ + + @ + @ + % # = = > < 7 e e e e e 7 , > ; # $ @ + + O + + O X X + O + O O O O O O O O O O o X O . . O . . . o X . . O + + $ $ % * * 3 * 3 * * $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.k.L L L L L L +.Z.Z.Z.Z.Z.Z.B.1 1 1 1 , 2 , 1 1 C Z.Z.Z.Z.Z.Z.Z.+.J J J J P F F J J F , , , > , , &.Z.Z.Z.Z.Z.Z.k.W F F F F F F F F F 2 > > > : > : : : 0 B.Z.Z.Z.Z.Z.r.: : : : : k.Z.Z.Z.Z.Z.Z.7 : - : - - - : & : & - - - & - - - & = & & : & & & & # - # - & V Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v v v a - + @ @ - @ @ @ + @ @ o + # # @ @ @ @ + @ + @ + + @ + + @ + + @ $ $ % & = * : : < < > : ; * # % $ $ + + + O O O + X X O O X O X O + X O O X O O O O O . . o . X O o X X X X X $ % & 3 5 9 9 9 e 7 5 ; = % $ X X ", +"2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 1 2 +.Z.Z.Z.Z.Z.Z.W 1 1 1 1 1 1 1 1 &.Z.Z.Z.Z.Z.Z.+., , , , , , 1 , , , , , , , , , , b.Z.Z.Z.Z.Z.B.9 > > , > > > > > > > > > > : > > > > : > 5.Z.Z.Z.Z.Z.Z.7 : : : d Z.Z.Z.Z.Z.Z.4.- : - - - - - & : & : & - & & & & & & & & & & - & & & & & - # 8 0.Z.Z.Z.Z.Z.Z.Z.Z.e.v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ + O - O @ @ @ + - + - # + + @ @ + + + @ + @ @ + @ @ + @ @ @ + $ $ $ % % % = & & * * * # % % $ + + + O + O + X O + + O O + X X O O X X O X O O O O . O . o o O o X + + $ * = 5 9 s b b b b b s 9 7 = * $ O X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 2 e Z.Z.Z.Z.Z.Z.+.1 1 1 , 1 1 1 , p.Z.Z.Z.Z.Z.Z.w , 1 , , 1 , , , , , , , , , , , d Z.Z.Z.Z.Z.Z.&.> > > , > > > > > > > > > > > > : > > > : N Z.Z.Z.Z.Z.Z.` > - : %.Z.Z.Z.Z.Z.Z.C = - - - - - - & : & : - & - - & & : & : & & & & & & = & - & q / B.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v v u # - - O + - + @ @ @ + @ @ @ @ + # @ @ @ @ @ + o + @ + @ $ @ # # % # # $ # % # # * $ % # % $ $ $ + + + + X + X + O O O O O + X X + O O O O O O X O o X X o . . X X o O X O + $ * = 7 r b C S T T T K A b s 7 : * + X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 1 1 1 2 1 2 0.Z.Z.Z.Z.Z.p., 1 1 1 1 , , 1 Z.Z.Z.Z.Z.Z.0., 1 1 , , , , 1 , , , , , > , , , F Z.Z.Z.Z.Z.Z.F , > > > > , > > > > > > > : > > > - > > : : k.Z.Z.Z.Z.Z.u.- - - v.Z.Z.Z.Z.Z.k.- - - : - - - - : & : & - & & & & - & & & & & & & & & % & # 8 v t.Z.Z.Z.Z.Z.Z.Z.Z.Z.) v v v v v v v v v v v v v v v v v v v v v v v v v v l * @ + + - O + O - @ @ @ @ @ + # # + @ o @ @ + @ + @ @ + $ # # % = = = ; * = & & & # $ @ + $ + + + + X + O + + O O O + O + O o X o o O O O O X X O O O O . o . . O O X X + + * = 7 s C Y { { -.-.-.{ ! K C s 7 * % $ O ", +"2 2 2 2 9 2 2 2 2 2 2 1 2 2 1 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 2 1 1 2 1 2 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , > , +.Z.Z.Z.Z.Z.Z.9 , > , > > , > > > > : > > > > > : > : - > > W Z.Z.Z.Z.Z.Z.t > I Z.Z.Z.Z.Z.Z._ - : - - - - - - & : & : & & - - - 5 V V V V V V V V V V V V =.d.Z.Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v c ; # # + - - @ + + - + + + + + + + + + # + # + @ + @ @ @ # # # ; - > , < , 5 > : = = # % $ @ + + + + O O + X O O + + + + O O O O o O o O O O X O O X O O O O X o o . O . o O O + $ * 7 s C T { >.2.2.8.8.2.>.{ Y M s 7 * $ + ", +"2 2 2 2 2 2 2 2 2 2 9 2 2 1 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 7 1 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 , 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , > , , , , +.Z.Z.Z.Z.Z.Z., > > , > > > > > > > > > > : > > > > : > > > : B.Z.Z.Z.Z.Z.} - 6.Z.Z.Z.Z.Z.B.7 - - : - - - - - : & : & & : - e 4.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ # % + + O O - O - + - + - o + - + + + @ + + + @ # @ $ # = = > 7 1 9 e e e w 7 < : = # % @ + + + + O + + + + O O O O O + O + + O O O O O + X O o X X . X o o o . . O o o o O O O $ * : e m K { 1.8.f.h.j.h.f.8.1.{ K m 9 ; $ + ", +"2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 2 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , 1 , , 1 , , , , , , , , , +.Z.Z.Z.Z.Z.Z., , > > , , > > > > > > > > > > > : - > > - - > %.Z.Z.Z.Z.Z.k.1 Z.Z.Z.Z.Z.Z.5.- : - - - - - - - & : & : : - j B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.c.v v v v v v v v v v v v v v v v v v v v v v v v v k * % % $ # - + + - O - O + # @ - + - o - + @ @ + # # + + - # = : , 7 t b n M A M M b r 7 5 = % $ @ + + + + X + O O + O + O O + O O O O O O O O O O o O O O . o . . . . o . . X X X + $ * 5 r C ! >.8.h.l.z.z.z.l.g.9.>.~ C r 5 * + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 , 1 1 , Z.Z.Z.Z.Z.Z.+., , , , , , , , , , , , , , , , , +.Z.Z.Z.Z.Z.Z.F > > , > > > > > > > > > > > > > > > > > > > : t Z.Z.Z.Z.Z.Z.+.Z.Z.Z.Z.Z.Z.r : - : - - - - - - : & - & & e B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.' v v v v v v v v v v v v v v v v v v v v v v v k 8 $ % $ $ @ + @ @ + - + + + - @ + o o - + + + # + # + + + @ @ & ; 7 e b M H Y R R R K S M b w , = * $ + + + O + X O + + O O + O O + O O + O O O O O O . o o O o o . o o . o . . o O + + = 7 f K .2.f.l.m.M.V.M.m.l.q.2.{ K f 7 = $ ", +"2 e 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 W Z.Z.Z.Z.Z.Z.1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , 1 , , , , 1 , , , , , , , I Z.Z.Z.Z.Z.Z.%., > , > > > > > > > : > : > > > : > : : > > > : u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- : - - : - - - - - - = - - = u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v c a p p q t p i p p u i i i u u u p u 6 4 & # # # # # # # # @ O @ @ - + + + - - O + + + + + + # + + @ @ @ - ; < 0 n A Y ^ -.:.>.:...^ T C f e < = @ + + + + + O + X + O + O O + + X O O O O O O O O O O O O . . o . . . o o . . . . . O + $ ; 9 m T ;.7.h.z.N.C.Z.C.M.z.h.7...T m 9 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+.1 1 1 , , , , , , , , , , , , , , N Z.Z.Z.Z.Z.Z.B.w > , , , > > > > , : > > > > > > : , > : - > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z._ : - - & - - - - - - - - & - V Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.n.' v v c - & % & # & % # % % # % % # % % # # $ % @ % # # # # # @ # @ @ - - @ + O - O o + + @ + - - + # + # @ $ # # ; ; 0 f A Q ..<.2.7.9.9.2.<. .Q A f 1 : * % @ + + X + X + O + O O O O O X O O O + O O O O O O o . o . . o . . . . . o . O O % ; e m T -.8.h.z.N.Z.Z.C.N.x.h.8.:.T m 9 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 1 1 2 2 1 1 1 p.Z.Z.Z.Z.Z.p.1 1 , 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., , 1 , 1 , , 1 , 1 , , , > , , > , B.Z.Z.Z.Z.Z.Z.k.I F D F F F F N > : > : > : > : , : : > > : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: - : : : : : : - - - - & - - 0.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.u.u.u.u.s.d.d.d.d.d.d.t.=.O.v v v v ; % # % # % % % % % & % % % % # & # # % @ % % # # # # @ # @ # @ @ O @ + - O - + @ - + + + + @ @ @ + @ $ # - ; 1 t B Y .1.9.w.j.j.j.f.9.1. .T M r < = % + + + + O + O + O O + + O + X + X X X O O O O O O O X . . . . . o . . . X o . . . O $ $ = 9 m T ;.7.h.l.M.C.C.C.M.x.h.7.;.K m 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 2 1 n Z.Z.Z.Z.Z.Z.&.1 1 1 1 1 1 , , Z.Z.Z.Z.Z.Z.+.1 , , , , , , , , , , , , , , , , , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.v.W > > > > : , : : > : : > > : O.Z.Z.Z.Z.Z.Z.Z.Z.Z.O.- : - : & : & - - - - - - - 5 Z.Z.Z.Z.Z.Z.Z.Z.Z.4.= & & & ; c v v v v v v v v v v v v k - & & # & % & % % % % % % # % # # & % % % % @ # # # # @ # # @ - O - @ + - + + @ @ @ + + - + + + @ @ @ @ # - ; 1 n H ^ 1.9.j.l.x.x.x.l.j.9.,.^ S b 7 ; % $ + + O + + O O + + O O + X O o X X + O O O O O O X X . . . . . . o . O O O + $ = 7 b K .2.f.l.m.M.N.M.m.l.f.2. .K h 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 1 2 2 2 1 0.Z.Z.Z.Z.Z.Z.W 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , 1 1 1 , , 1 , , , , , , , , , > d Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.! ; > > : : : > , : : : : : d Z.Z.Z.Z.Z.Z.Z.Z.Z.d : - : : & : : & : : : - - - I Z.Z.Z.Z.Z.Z.Z.Z.B.< & & & & - v v v v v v v v v v v v v q % % % % & % % % % & % % % % # & # # # # # # # # # # # # @ # # + + - O @ @ - + @ @ @ + - O + + @ @ @ @ @ # - ; e m Y -.2.q.l.x.M.N.M.m.l.q.2...Y m w : % % + O + + X + O O + + O O O O O + o o X X O O O O . O . . o o . . o o . . o . . O + $ * 6 s S R >.8.h.l.z.x.z.l.g.8.>.! S r 5 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.[ +.+.+.+.+.p.Z.Z.Z.Z.Z.Z.B.1 1 1 1 1 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , > , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.t > > , > , : : > : , > : : 6.Z.Z.Z.Z.Z.Z.Z.6.: - : - : : : & : : & & - & & o.Z.Z.Z.Z.Z.Z.Z.Z.4.& & & & & 4 v v v v v v v v v v v v v ; % % & % & % % & % # % % % % % # # # # # & # # # # # # # # @ @ @ @ @ @ - @ + O @ @ @ @ @ + - + @ + + @ # # - < e B Q ;.7.h.x.N.C.Z.C.M.x.j.7.;.R M e < ; # + + + X + O + X O O + + O + O X O O + O O o O O . O . . o o . . . . . . . . . O X $ * ; e b Y { <.8.f.g.j.h.f.7.<.{ Y b w ; $ + . ", +"2 2 2 r 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.+., 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , , , , , , , , 0 k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.0.> > , : : : : > : : : , : 4.Z.Z.Z.Z.Z.Z.Z.4.: - - : & - : : & - & : - - & 0.Z.Z.Z.Z.Z.Z.Z.Z.E & & & & & q v v v v v v v v v v v v v - # & % % % % % % % % % & % % % # & & # # # # # # # # # # @ # @ - @ @ @ O O @ - + + @ @ + + + + @ + @ @ # @ ; < r B Q >.9.j.x.N.C.Z.Z.N.x.j.9.>.Q B e < = + @ + O + O + O + O + O O O O O O O + O O O O O O . . o . . o . . . . O . . O X + $ = 7 s C U .>.2.7.9.7.2.>.{ Y M r 5 * $ O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 7 2 2 1 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 1 , 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , 1 1 , 1 , , , , , , , , , > , , , , w 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.B.> - : : , : , : > : : : 7 B.Z.Z.Z.Z.Z.Z.Z.B.7 : : - : : & & : : : & & : & p.Z.Z.Z.Z.Z.Z.Z.Z.D - & & & * i v v v v v v v v v v v v z # & % % % & % % % % % % # # % % # # # # # # # # # # # # # # # @ + @ - O + - @ @ - + + # - + - o + @ @ @ $ - ; ; t B R ;.9.h.x.N.C.Z.C.N.x.j.7.:.Y M e < * # # + + + O X + O + O O + O + O O O O O O O o O O . . . . . o . . . . o . o X X X $ % = 7 f C K ! .;.:.;.{ ! K C s 7 ; % + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.V 1 1 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , 1 , , , , , > , , , > , > , , 0 F F F F F F W 5.Z.Z.Z.Z.Z.Z.Z.I : > > : > > : > > : > | Z.Z.Z.Z.Z.Z.Z.Z.Z.} : : = : : - - : : & : : & : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & # a v v v v v v v v v v v v z - # & # & # - # # # & # % % % % # % # # % % # # # # # # # # # # @ # # @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ + @ * & < 9 M U -.2.w.l.m.M.N.N.x.l.g.2...K M w : = $ + + + + + O O + O O + O X O O X X X O O O O X O o o o o o . o . . . . . o o . O + $ * 3 7 r b S K T R K K A b r 7 * ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.B.6.n 1 1 1 1 1 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , , , , , , ; , , , > > > > > > , I Z.Z.Z.Z.Z.Z.+.> : > : > : > : : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: : : : & - - : & : & : - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & - & - & p v v v v v v v v v v v v z # # # & # & # # & # & # % % % % # % % % # # # # # @ # # @ % # # # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ # # > 2 b H ^ 1.9.j.l.x.x.x.l.h.9.,.^ S f 7 ; = + + + O O O + + X + X + O + O O + o + O O O O X O X X o o X o . . . o o o . . . X O + + $ % = 5 w r b m M m f r e 6 ; * ", +"2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 , 1 1 , , , , , , , , , , > , , > > ; , , , , > > , > > > > b.Z.Z.Z.Z.Z.0.> : > > : > : : > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.I : : : & : - & : : & & = : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & g v v v v v v v v v v v v g # - # & & # - - # # # & % % % % % % % # % # % # # % # # # % @ # @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ # * ; 1 r B T ..1.9.q.h.j.j.q.9.1. .Y M r < = $ + + + O + + O O + O + O + O O O O X o O O O O O O O O O . o o . . . X . X . O O O X $ % * ; 7 7 7 9 9 8 5 ; * + + ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , , , , 1 , , , 1 , , , , , > , , , > , > > , > , > > , > 5.Z.Z.Z.Z.Z.p.> > > : > : > > : : p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- - : : = : : : & : - - & p.Z.Z.Z.Z.Z.Z.Z.Z.V & - & & - p v v v v v v v v v v v v p - # - # # & # # & & # # % % % % % # # % % % # # # # # $ # @ @ $ @ # # @ @ # @ @ @ @ @ + @ @ @ @ # + @ + @ % # = , w f A Q ..1.2.7.9.9.2.<. .Q A b 7 ; = # + + + + O + + + O + O O O O + + O O O O X O O X O O X X O . O . . . o . . . . . O O X $ + % % % = ; ; * * * $ % ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , 1 1 , 1 , , , , , , , , > , > , , > , > , , > , : > > +.Z.Z.Z.Z.Z.u.: > > > > : > : : d Z.Z.Z.Z.Z.Z.u.Z.Z.Z.Z.Z.Z.t - : : & : : & : & & - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p - # - - & # - # # & & # & % % % % % % # # # # % % @ # @ % @ % @ # @ @ # @ # @ @ @ @ @ @ @ @ @ + + + @ + + # % # - < w n A R ^ ..>.>.>...^ Y A f 9 < = # % + + + O + O + O + + O + + O O O + X o X O O O O O O X . . o o . . . . O . . . + + $ $ $ $ $ $ $ $ $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 7 1 1 1 2 2 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , , , , , > , > > > > > > , > > +.Z.Z.Z.Z.Z.p.> > : : > > : > , %.Z.Z.Z.Z.Z.Z.j v.Z.Z.Z.Z.Z.4.- : & : : - - : - - - - u.Z.Z.Z.Z.Z.Z.Z.Z.Z & & - & & p v v v v v v v v v v v v p # # # # # & # % & # # # % % % % # # # % # % # % # # # % @ # @ # @ # # @ # @ @ @ @ @ @ @ @ + @ + @ @ + # @ # # % = - 1 e f B H Y Y Q Y Y S M y e 5 ; # % + + + O O + + O O X O O O O O + O O o + X X O O O O O X O O o . . o . o . o o X o X . . . O X X O + + + + O X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , , 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , , 1 , , , , , , , , , , , , , , > , > , , > > > , : , +.Z.Z.Z.Z.Z.u.: > > : > > > : 1 B.Z.Z.Z.Z.Z.b.: %.Z.Z.Z.Z.Z.B.7 : : : & - - - - : & : p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p # - & % - # % % # # & & % % % % % % % # # # # # # # @ % % @ @ $ @ @ @ @ @ @ @ @ @ # @ @ @ @ + @ # + # + @ + @ % # = ; < 0 t f m B B B m f r w < = % % % + + + + + O + + + + O X O O + O + O o o O + O O O O O O X o o . . o . . . o X X . . X X . . X . O . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.&., 1 , 1 1 , , , , 1 , , , , , , , , > , , , > , > > , , > > , , u.Z.Z.Z.Z.Z.%.> : > > : : : : ` Z.Z.Z.Z.Z.Z.| : d Z.Z.Z.Z.Z.Z.} : & & : - - : & - - & u.Z.Z.Z.Z.Z.Z.Z.Z.F & & & & & p v v v v v v v v v v v v p # - # # - # & % # & # # % % % % % # # # % # % # $ # % @ @ % @ % @ @ + - @ @ @ @ @ @ @ + @ @ @ # + # + @ + @ + + # % & ; > 7 0 w e r e e 1 < - ; * % + + + + O + + + O + + O + + O + O O O O O O O O O O O X X O X o . . o . X O . . . O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 b.Z.Z.Z.Z.Z.k., 1 1 , , , , , , , , , , , > , , , , , : , , : , > , > > > > 0 Z.Z.Z.Z.Z.Z.| , > : : > : > : v.Z.Z.Z.Z.Z.Z.t : : k.Z.Z.Z.Z.Z.v.: : & : : & : : - : & p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v i = % % & # % & # - - @ - + - + - % % % % # % # # % # # # # # # % @ @ # @ # @ @ @ @ @ @ + @ @ @ + # + @ @ + + @ @ @ # # # - - ; > , > < > - ; % # # @ + + + + + + + + + + $ + + X + O + O O X O O X O O O O O O O . X O O X X X X X O + + X X X X X . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.f.1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.Z.Z.Z.Z.Z.Z.J , , , , 1 , , 1 , , , , , , , , , , , , , , , > , > , > > , X.Z.Z.Z.Z.Z.Z.h > > > > > > , D Z.Z.Z.Z.Z.Z.k.: : : } Z.Z.Z.Z.Z.Z.I : : & & : & & - & - u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p % # & # # & # & + + - + - + - + % # % # # % # # # # # # # @ + # - # @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + # @ + + @ @ @ # # # # # - ; & ; % * # $ @ $ + + $ + + + $ + $ % $ + @ $ + @ + + O X + O + X + O O O X X . O O O X X O X O + + + $ + + + O O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 [ Z.Z.Z.Z.Z.Z.k.e , 1 1 , , , , , , , , , , , , , , , , , , , , > , > > > m B.Z.Z.Z.Z.Z.v.> > > > > : : > r.Z.Z.Z.Z.Z.Z.X.: : : d Z.Z.Z.Z.Z.Z.u.& : : : : & : & - & p.Z.Z.Z.Z.Z.Z.Z.Z.k.u.u.u.u.u.s.d.d.d.d.d.d.d.d.d.d.d.d.s.u.$.% & & # & # - + + - + - + - % # # # % % # # # # # # # # % # + @ @ @ @ @ @ @ # @ @ @ + # + # # + @ + @ @ @ + + + + # # @ @ # # # @ $ # $ @ @ + + + + + # @ $ * # * = & * * @ @ + + + + O O O O O O O O O O O . . O O O O + + $ $ $ * $ * $ $ $ + + . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 1 1 1 , 1 e B.Z.Z.Z.Z.Z.Z.B.p.p.p.p.p.p.i.i.i.i., , , , , : N i.i.i.i.i.u.p.u.p.p.p.Z.Z.Z.Z.Z.Z.Z.O.: > > : : > > t Z.Z.Z.Z.Z.Z.Z.7 : : : - k.Z.Z.Z.Z.Z.Z.e : & : & : : - : & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.& % # & # & + - - + - @ - + % % # % # # % # % # # # # @ @ @ @ @ @ @ # @ # @ @ @ + @ # + # + + # + @ + + + @ @ @ + @ @ @ @ @ @ @ @ + @ + + + + + + @ @ @ * = ; > : 5 : ; = & # # % + + + O O O O O O X O O o . O O O + + $ % * * * ; = = = * * $ $ + O X . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , F Z.C.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.M.1 : > > > > : > %.Z.Z.Z.Z.Z.Z.r.: : : : : ` Z.Z.Z.Z.Z.Z.4.- - : : & & - : & p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.% % - - - - - @ - + O $ - - % % # # & % # # # # # # @ # @ # @ @ - # @ @ @ @ @ @ @ @ @ @ + @ + @ + + @ + @ + + + @ + + @ @ + $ + + $ + + + + + + + # * ; > 5 7 e w e e 9 7 5 : * * + + + + X O O O O O O O O O O + + $ $ % = : 5 9 9 e 9 9 5 ; * * @ X X X ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 e k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , > , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : : > > : > > 7 B.Z.Z.Z.Z.Z.Z.` : : : : : 7 Z.Z.Z.Z.Z.Z.B.7 - & : & : - & & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.% % + $ + O @ - + - - + - + # # # # # # # # # # # % # # # @ @ @ + @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ @ + @ + @ @ + + + + + + + + + + + + + + + @ # $ % = > 0 e f m M M C b f e 9 : & $ $ + + X O O O O O X X O O O + + $ = = 6 e r b b C b b f e 6 ; & $ $ X ", +"2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 2 1 1 1 , 1 , 2 1 1 1 , 1 1 1 , , C k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , > , , , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : , : , : > : > ` Z.Z.Z.Z.Z.Z.B.7 : : : : : : r.Z.Z.Z.Z.Z.Z.} - & : : & - & - p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.- ; - - ; - - - - @ ; - - $ % # # # # # # # % % # # @ # # # - + @ @ # # @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ + @ + + @ + @ + + + + + + + + + @ $ * = < e s B G U R R T K G M s 9 5 = $ $ + O X X O X O O O X O + + $ * > 9 s m S K T T T K G m r 7 ; * $ X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 p.p.p.p.p.p.3.1 2 2 1 2 1 1 1 1 1 1 1 2 2 1 , 1 1 1 1 1 1 1 , 1 1 , [ 0.p.p.p.p.p.p.p.p.p.p.p.p.p., , , , , > N p.p.p.u.u.u.p.u.p.u.p.p.p.p.&.d , , : , : > > > : %.u.p.u.p.u.p.+.: : : : : : - I u.u.u.p.u.u.4.- : : & : - - & I B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.; 4 3 ; 3 3 ; 4 8 ; 4 4 ; 4 , > 4 4 4 4 4 < 3 3 3 3 3 3 3 3 - + @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ @ + + + # + # + + + + $ + + + + + + + @ # ; > 0 f A K ! { ;.>.:...! Y A f w : * $ + + + O O O O O O O O + $ * : 7 s M Y ! .;.:.-.{ R Y C s 7 = % $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 2 1 , 2 , 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , 1 , , > , , , , , , , , , , , , > , > , > > > > > , > : , , : , > , : : > > : : : , : : : > : : : : : : : : : : : - : : - : : & : & : - - - - - & V D V V V V V V V N V V E ] ] ] ] ] ] ] ] ] ] ] ] ] ] ' v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; O - o O - O O + $ O + - + - O @ @ + @ + @ + @ + + + @ + + @ + + @ + + + + + % + = : 7 f S T ..<.2.8.9.7.2.<.{ R B y 7 : * + + O O O O O X O + + + # : 7 s A Y { >.2.8.8.8.2.>.{ T A s 5 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 , 1 2 , , 1 1 , 2 , 1 , 1 , , , , 1 , 1 , , 1 , , , , , , , , , > , , > , , , > > , > , > > > > , : : > , : : , : > > : : > : : > : : : > : : : : : : : - - - : : & & : & : : & - - & - & - & - - & & - & - - & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - o - - + + - O - - $ O + - + + @ @ + @ + + @ @ + @ + + + + + + + + + + + + + * = 5 e M K .1.9.g.h.h.j.q.9.1.{ Y M e > & @ + + O O O O O O O + @ * : e b U { <.7.f.h.h.h.f.8.1.{ K b e ; % X X . . ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 , , , , , , , , , , , , , , , , , , > , > > , > , > , > > > > > , , , : : > > : > : > : > : : , : > : : : : : : > : : : : - : - : : : : : & : : - - - - - - - & - & & - - & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ - o - O O - + + - + + @ O + + @ + @ @ + @ + + @ + + @ + + + + + + + + + + % # : 7 b S ! <.9.h.l.x.m.x.l.g.9.>.~ A b 7 = % + + X O O O O O O + % = 5 s S ! >.8.h.l.z.m.z.l.h.8.>.R S s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 2 1 2 1 1 1 1 1 1 2 2 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 1 1 , , , 1 , , , , , , > , , , , , , , > > , : , > , > > : , : : , : : , > > > : : > : : : : > : : : > : : : : : : : - : : & : & : & : & & - & - - & & & & & & - & & & & & ; i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 O o - O - + O - o o + @ @ @ + @ @ + + + @ + @ + + @ + + + # + + + + + + + + # * > e m Y ..2.g.l.m.M.V.M.m.l.w.2.-.U b 7 ; % $ + O O O O O O + $ $ : 7 b U { 2.f.l.m.M.N.M.m.l.f.2.{ K b 7 * $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , > , > , , > , , > > > > > , > , > , > : , , : > : > > > : > > : > : : : > > : : : : - : : : : & : : & : : & : : : - - - & - & - - : & & & - & & & & & p v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ O - o - O - @ @ @ @ @ - O + + @ @ @ @ + @ + # + + @ + + + + + @ + + + + # $ & 5 e M T :.8.h.x.M.C.C.C.N.x.h.8.:.T m w : * $ + + O O O O X + + $ : w b R -.8.h.z.N.C.Z.C.M.z.h.7...T b e ; * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , > , > , , , , , , > > > > : , , > : , : , > > : > : : > : > : : : : : : : : : : : : - : : : : : & - : & & - - - - & - - & & - & - & & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - - O + o O - @ @ @ @ @ + @ @ @ + + @ + @ @ + @ + + # + + @ + + + + + + + @ % & > r M R >.9.h.x.V.C.Z.C.N.m.h.9.:.R M e > $ + + O O O O X O + + * 3 w M R ;.9.h.m.B.C.Z.C.N.z.j.8.:.R b e ; % + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 1 1 2 , 1 1 1 , 1 1 , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , > > , , , , > > , > > , > > > , : : , : , : : : > : > > : : : : : : : : : : : : : - : : : : - : & : : : : : & & - - - - & & - & & & - & & & & - & u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 o - - - - O O + - @ @ O - + @ @ @ @ + + @ + @ + + + + + + + + + @ + + + $ + @ = 5 e M R :.8.h.x.N.C.Z.C.M.x.j.7.;.T C e > * + + O O O O O O + + % ; w b R -.8.h.z.M.C.C.C.M.x.h.7.-.T b e = $ + . . ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , , > > , , > > , > > > , : , , : , : , : > : : , : : : , > > : > : : : : : : : : : - : - : & : & : & : & - - - & - - & & - - - & - & - & % - ; v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 - o O O + + - + O @ @ + + @ @ + + @ @ @ + @ + + @ @ + @ + @ + + + + + + + + @ * : e b K ..2.w.l.m.M.V.N.m.l.q.2. .K m 9 : # $ O O O X O O X O $ $ ; 7 b Y { 2.f.l.m.M.B.M.m.l.f.2.{ K f 9 * $ + . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , , , , , 1 , > , , , , > , , , , > , > > , > > > > : , , > : > > : > > > : > > > : : > > : : : : : : : : : - : : & : : - : - : : & : - & : & : - & : & - & & & & - & & & & - u p g z l l l l l l l l g l l k g l k k k k k k k k k k l l k l k k k k k k k k k k k k ; @ # @ # @ @ @ - + + - O O + @ @ @ + + @ + + @ @ + + + + + + + + + + + + + + % % : 7 f S ~ <.9.h.l.z.m.z.l.g.8.>.! G f 7 = $ + O O O O X O X + + $ * 7 s S ! >.8.h.l.z.z.z.l.h.8.>.! A s 5 % $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , , > , > > > , > > > , > > , > : : , , : > > : > > : : : > : : : > : : > : : : : : : : : : : & - : : & : : & - - & : & & : & - & & - & - & & & & & & & & & & & - & & & % % & - # - - - - @ - - @ - @ - @ - # @ - + - # - @ + + - + - # + # @ @ # @ @ @ @ @ @ + + + O + - - + @ + @ @ + @ + @ + @ + @ @ @ + + + + + + + + + @ $ = 5 r M T ..1.9.q.h.h.h.f.9.1. .T m e 5 * @ + + O O O O X + O + $ & : e M Y { 1.8.f.h.h.h.f.8.1.{ U b 9 5 * $ ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 2 1 1 2 2 1 1 1 1 1 , 1 1 1 1 , , 1 1 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , , , > , > > , , , > , , > > > > > , > , : : , , : > : > > > > > > : : : : : : : : : : : : & : : : : : & : : & : : : & : - : & & & - & & & & - & & & - & & & & - # % & % % & & & # - @ - @ + + - @ @ - + - + - - @ - + - # + - - + - + + + - - + + - O @ # # @ @ @ - - o - @ @ O + @ @ + @ @ @ + + + @ + + + + + @ + + + @ + + + # $ * : 9 f A T ..<.2.8.8.8.2.>.{ T A s 7 = * $ + O O O O O O O O + $ $ = 7 r A Y { >.2.8.8.7.2.>.{ T C s 5 = $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 2 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 , 1 1 , , 1 1 1 , , 1 , , , , , , , , , , , , , > > , > > , , > > , : , : , > > : > > > > : : : : : > > : : : : : > : : : - : : : : & : : & : - & & & : & & & & : & & - - & & & & & - # & - # & - # & & & & & # & & # - @ - - - + - - + - @ - + # + + - + # - @ + - @ + - - + + + - $ @ @ # @ @ @ @ + + + @ @ + @ @ + @ @ + @ + + @ + + @ + + @ + + @ + + + + + + + $ % = 5 e f A K ! ..;.>.;.{ { Y A f 9 5 = # + O O O O X O O X O O X $ & ; 7 s C U ! { ;.:.;. .! U C s 7 ; % $ X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , > > , > , , > > > > > , : : , : , > > > : > > : : : : : : : : : > : : : : : : : & : : : : : & : & & : - - - : - & & - - & & - - & & & & - - & & & & - & # % & # & # & - @ - @ - @ - # @ - + - @ # # - # - + - + @ + - - + + @ - + + + @ # @ # @ @ @ @ @ @ @ + + @ @ @ @ + @ @ + @ + @ + @ + + @ + + + + + + + + + + + @ $ # = 5 9 s M S K T R T U S M f w 5 * @ + + + O O O X O O o O O + + % * : 7 s m A K T T T K A m s 7 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , > > , , , > , , > > > > , > > : , , : > : : , > > : > > > > : : : : : : : : : - : : : : : : & : & : : : : : : - & - & & : - & & - & & & & & & - # - # # & & # & & & & & & & # @ - @ - @ - @ @ - + @ @ - # - + # # # # @ - # + @ + - + + + - - @ $ - @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + @ + + @ + + + @ + @ + + + + + + + $ % % = 5 9 e b m M C C b f e 7 : = $ @ + O O O O O + O X O X X + + $ = ; 7 e s b b m m b r e 6 = * $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 1 1 1 1 , 1 , , , , , 1 , , , , , , , , , , , > , , , , > > > > , , > > > , , , : > , , : : > > : > : : > > > : > > : > : : : : : : : : & : : & : - : & : & - & & - - & & - & - & - - & & & & & - & & & & & & & # & & # & % - @ - @ - + @ - # @ - @ - @ - # # # + # - # - + + - - @ - + + + - @ + + @ @ @ @ @ - @ @ + O @ + @ + @ + @ + + @ @ + @ + + @ + + + @ + + + + + + + + @ $ % = : 5 7 e e e e w 7 5 ; * # % + + + O O O O O O O O X X O O + $ $ * = 5 6 9 e w w 9 6 3 * * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , , , 1 , , 1 , , , , 1 , , , , , , , , , > , > , , > > , > > , > > > , : : , : : , : : > : > > : : > : > : : : : : : : : : : : : : : : : : & & : & : & : - - & - - & - & & & & & & - & & - # & & & & # & & & & & % & @ - @ - # - - @ - - + - # # @ @ - # - # + # # # - + + + - + - + + # @ # # @ @ @ + O @ @ @ - + @ @ + @ @ + @ + @ + @ + + + + @ + + + + + + + + + + + + @ @ % * & : 3 : > : : * = & $ $ + + O + O O O X O O O O O . X O O X + + % & * = = = ; = = * $ . $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 1 , , 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , : > > > > , , : : , : , : > > , : : > : > : : : : : : : : : : : : : : : : - : : - & : - : : & : & & : & & & : & - & & & - & - & & & & & & & & & & # & & & & # & # & # & & & # & # # & & @ # & @ # @ & @ @ & @ & @ @ @ @ @ @ @ & @ @ @ @ @ # @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + + @ + @ + + + + @ + + + + + + + + + + @ + @ @ # % % & % & & # @ @ @ + + + X X + O O O O X O O O O O O O O + + $ $ $ * $ * $ + $ + O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 1 1 2 2 2 1 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , : , , , : , , : > > , : , > : , > , , : : : : : > > > > > > : > > : : > : : > : - : : - - : - & : : & & - - : & : : & & : & & - & & & & & & & & & & & & & & # & & & & # & & & & # # & # # # & # & # # # # & @ & # % # # % & @ # # @ & # @ # # @ @ @ @ @ # @ @ @ @ # X @ @ @ @ @ + @ + @ + + @ @ + + + @ + + + + + + + + + + + + + + + o @ @ @ @ # # # @ @ + @ + + + X o o o o O O O O O O X X O O X X O O + + + + + + + + + + O O . . ", +"2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , , 1 1 , , 1 , , , , 1 , , , , , , , , , , , , , : , > , , , > > , : : , : , , : , : , , > > : : > : > : : : : : : : : : : : : : : : - : : : - : : & - & : & : : & : : & - & - & & & & & & & & & & & & # & & & & & & # & # & & & & & # # # & & # @ & @ & @ @ # @ % # @ @ @ @ # # # @ @ @ & # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ + + + @ + + + @ @ + @ + @ + + + + + + + + + o + + X + + + @ + + + @ + + + + + + X o O O o X X O O O O O O O O O O . X O O . O O + + . O + . O o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , , 1 1 , 1 , , 1 , , , , , , , , , , , , : , , , > , , , > , , , , : , : : : , , : : > : > > : > : > : > : > : : : : : : : : : - : - - : : - : : : : & : & & : & : & & & - & & - & - & & & & & & & & # & # & # & # & & & # # & # & # & # & # & @ & # # & # & # # # # & # # @ & @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ + @ @ @ @ @ + @ + + @ + + + + + + @ + + + + + + + @ o @ + + X o o + + o + + X + X X + o + O + X X + X O O O O X O O X X O . o O O . . . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , > , : : , , , : , , , : : , , : : > > : : > > > : > > : : : : : : : : : : : : : - : : - - - - & : & & & : & & & & : & & - & & & & & & & & & & & & & & & & & & & & # # # & & & # & # # # & # # & & @ & # # # % # # % @ # # # # @ @ & @ @ @ @ @ @ @ @ @ @ X @ @ # @ @ @ @ + @ @ + @ + @ + + @ + + + + + + + + + + + + + + + o + o + o + + o + X + + o O O O O O o o o O O O O O O O o o O O X O X o . . . . . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 2 2 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 1 , 1 , 1 , , 1 1 , 1 , , , , , , , : , , : , , > , , > , , , : , , , : : , , : , : , , : , , : : : > : : > > : : : : : - : - : : : - - - : - : : : : & : : & : : & : & : & - & & - & & & & & & & & & & & & # & & # & & & & & # # & # & # & # & & @ # @ @ @ & % # % # # & # # # # @ @ # @ @ @ @ @ @ @ @ @ # # @ @ X # X @ + @ + + @ + @ @ + @ + + + @ + + @ + + + + o + X @ + + + + + + + o + + + o o X + + O + o + O X O X O O O O O X o o X O O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , , 1 , 1 1 , , 1 , , , , , , , , , , , , , , > , : , , : , : , : : > , : : , : : : , : : > : > : : > : : > : : : : : : : : - : : - - - - : & : & : & : & : & & & - & & : & - & & & & & & & & & & & # & # # & # & & # & # & # & # & # % # @ # # & % # % @ # % # # # # # # @ # # @ @ & @ @ @ # @ @ @ @ # @ # X @ @ + @ + @ @ + @ + + @ + + @ @ + + + + + + + + + + + o o @ + + + X + + o o X o + + O O O O o + + o O O O O O O O X O O O O o X o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 , 1 , 1 , 1 1 , , , 1 , , , , , , , , , , , , , , : , > , , > , , , , : > , > , , , : , : , , : : > > : > : > : : : > : : : : : : : - - : - - : - : - & : & : & : & : & & : & & - & & & & - & & & & & & & & # & & & & & & & # & # & & # & # # # & & # & @ & # % % % % # # # % @ # # # # # @ # @ @ @ @ @ @ @ @ @ @ # X # & X @ @ @ @ + @ @ + @ @ + @ + + + + + + @ + + + + + + + X @ o + X + X + o + + + X o + O + + O O X o o O O O O X O X o o O X . . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , , , , 1 , , , , , , , , , , , , , , , : , : , > > > > > > > > > , : , : : > : : > : > : : : > : : : : : : : - : - : : : : & : & : & : & : & - - & - & - & - - & & & & & & & & & & & & & # & & & # & & # & & # # # & # & @ & # # @ & # # % # @ # # # # # @ # # # @ @ # # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ + + + + + + + + + + + X + + + + + X + + X + + + + + X + O O O O O + + X X O O O O O O X O . o . . X O O O O . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 1 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , 1 , , 1 1 , , , , , , , , , , , , : , , : , , , , , , , , , : > > > > : > : , : > > > > > > : : > : : : : : : : : : : : - : - & - - : & : : & & : : & & & - & - & & & & & & & & & & & # & & # & # & & & # & & & # # & & & & # & # & @ & & # # % % & # & # # % @ % # # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ # X # # X + @ + + + @ + @ + + + + + @ + @ + + + + + + + + + + + + + + X + + X o O O + X o + O O O O O + o O O O O O O X X . o o . o . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 1 1 2 1 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , > , , , , , > > : > > : , > > > > : , : : > > : : > : : : : : : > : : : : : : : - - : - : : : : & : : & : & : & : & : & : & & - & & & & & & & & & & & & & % & & & & & # & # & & # # # # & # # # & @ & & @ & # @ # # # % % @ & & X @ @ @ @ @ @ @ # @ # @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + @ + @ @ + + + @ + + + + + + + o + X + X + o + o X + + + O + o O O + + o + o O O O X + X O O o O O o o . . . O O . . o o O . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 , 1 , 1 , , , , , 1 , , 1 , , , , , , : , , , : , : , , : , > , > , > > > > : : , : > : > > > : > > > : : : : : : : : - : : : : - : & : : : : & : & : & : & & : & & : - & & - & - & & & & & & & & & & & # & # & # & & & # & & & & # # & & @ & @ @ & # @ & # # % @ @ @ @ @ & & @ @ @ # # @ # @ @ @ @ @ @ @ @ X @ @ @ @ @ + + @ + + @ @ + + @ + + + @ + + + + + + + + + + + + + + + + + + o + o + + + O + O O X O X O O O X O X X O O . O . o o . . . O . . o o ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , : , > , > > , : , , > > > > > > > > > > : : > > > : : > : : : : : : : : : : : - : : - : & : & - - : & & : : & : & & & & & & & : & & & & & & & & & & & & & & # & & & # & & # & & # & & # # & # & @ # # # # # # # # # # @ & & @ @ @ @ & @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + + + @ + + @ + + + + + + + + + + + + + + o + + o + + o O O + O X O O O O + O O O O O O O O O O O O O X X . . O o . o . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , > > , , > , > , > , , , : , : > > > > : > > : > > > : : : : > : : > : > : : : : : : : : - - : : & : : - - - - : & & : & : : & : & & & & & & - & & & & & & # & & & & & & # # & # & & # # & # # & # & # @ & & @ @ & & # & # % # @ @ @ @ @ @ @ @ # @ # # @ @ @ @ X @ @ @ @ @ @ @ + @ + @ @ + @ @ + @ @ + + + + + + + @ + + + + + + + + + + + + + O + + O + O + X + + O O o O O + O O O O O O O O O O O O O X o O o . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , 1 , 1 , , 1 , 1 , , , , , , , , , : , , , , , , > , > , > : , : , > > > > > > > > > > > > > : > > : > : : > : : : : : : : - : - : - - : - - - - & - & : & & & : & & & : & - & - & & & & & & & & & # # & # & & # & & # & # & & # & # # & # & # @ & # # # # # @ # % # @ @ @ @ & @ & @ @ @ # @ @ @ @ @ # @ @ @ @ @ X @ @ + @ + @ + @ + @ + + + @ + + + @ + + + + + + + + + o + + o + o + + O + O + O + O O O + O O O O O O O O O O O X o O O . O . X O o o o o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , , , , > , , > , , > , > , > , , , : > > > > > > > > : : : > > : > : : : > : : : : : : : : : - : - : : - - : - - : - : & : & : & & : & & & & & & & & & & & & & & & & & & & & & & & # & # & & # & # & # # & # & # @ # & @ & @ # # # # & @ & @ @ @ @ @ # @ # @ # @ @ @ @ @ @ # X @ @ @ @ @ + @ + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + + + O O + O + O + O O + O + O + O O O O O X O X O O O . . O o O o . . . . . ", +"2 2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , , 1 , 1 , 1 1 , 1 1 , 1 , , , , , , , , , , , , , , : , , : , , : , , : , , , > , > > > : , : > > > : > : > : : > : : : > : : : : : > : : : : : - - - : : - - : - - - & : & & & : : - & - - & - & & & & & & & & & # & & & & # & # & # & & # & # & # & # # & # & # & & & # # & # # # # # # # # # # @ # # @ @ @ @ @ # @ @ @ @ X @ @ @ @ @ @ @ @ X @ X @ + @ + @ + + @ + + + @ + + + + + + O + + + + + + + + X O + O O O + O + O O o X O O O O O O O o o o X X o O X . O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 1 , 2 1 1 1 , 1 , 1 1 , , 1 , 1 , 1 1 , , 1 , , , , , , , , , , , , , , , , , > , : , : > , : , > , > > > > > > : > > : > : > : : > : : : : : : : : : : - - - - - - & : : & : & : : & & & & & & & - & & & & & & & & & & & & & # & & & & & & # & & # & # & # & # & # # # @ # # # # # # & # # # # # # # # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ X @ @ X @ + @ + + + @ + + @ + + + X + + + + + + + + + X o + O + + O + + O + O O O X + O o O O O O O O o O O O O o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 , , 1 1 1 1 , 1 , , 1 , 1 , , 1 , 1 , , , , , , , , : , , , , , : > , : , , : , : : , > > > : > > > : > : > : > : : > : > > : : : : : : : - - : : : - - : & : - - & : - & : & : & - & & & & & & & & & & & & & & & & & # # & & # & & # # & # & # & & # # & & # # & # # # # # # # # # # # @ @ # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ X @ @ @ + + + + + + + + + + + + + + + + + + + O o + + + + O + O O O O o O O O + + O O O O O O O O X O O X O o o O . O O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 , 1 , 1 1 1 , 1 , , 1 , 1 , , , , 1 , , , , , , , , , , , , , , , , : , , , , , , : , > , , : , : > > > : : > > > : > : > : : : : : : : : : : : : : : : - - - - : - - - - : & : & & : & & & - - & & - & & & & & & & & & # & & & & & # & & & # & # & # & # # # & @ # & # # & # # # & # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ @ X @ + @ @ + @ + @ + + + + + + + + O + + + O + + X + o + + o + + + O + O O o O + O O X O O O O O X O O X O O O O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , > , , > , , > : , : , > : , , : , : > > > : : > : > > : : > : : : : : : : - : : : - : - : - : - - - - - & : & & - & : : & - & & & & & & & & & & # & & & & & & & # # & & & # & & # & # & & # # & # # # # # & # # # & # # # # # & # # @ @ @ @ # @ # @ @ # @ @ @ X @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ @ + + + + + + + + + + + + X + + O + O + o + + X + O O O O O O O O + X O O O O O O O . . o . O O O O o O O o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , > , , > , , : , > , , , : , : , : > > > > > > > > > > : > : > : : : : : : : : : : - : : - - - : - - - - - - : & & : & : & & - & & & - & - & & & & & & & & & & & # & & & & # # & # & & # & # & # & # # & # # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ X + X @ @ X @ + + + + + + + + + + + + + + + + + + + + o + o + X + O + o O + X X + + O O O O O O X X O O O . X O . o . o o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , , , > , > > > , , : , : , , : > , > > > > > > : > > : : > : > : : : > : > : : : : : : - : : - - : - - - - - - : & : & & & : & & & & & - & & - & & & & & & & & & & & # & & # & # & & # & # # & & & # # # # # & # % & # # # # # # # # # # @ # # @ # # @ @ @ @ @ @ @ @ X @ @ @ @ @ X + @ X @ @ X @ + + @ + @ + + + + + + + + X + + + + O + + + + + + O + + O + X O O O O O + + O O O O O O O O . . o . o o . O o O o O O o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 , 1 , 1 1 , , , , , , , , , , , , , , > > , , , > , : , , , : , : , , : > > > > > : > > : > > : : : : > : > : : : : : : : : - : : - : - - : - - - - & : & : : & & & : - & - & & & & & & & & & & # & & # & & # & # & & & # & # & & # # # # & & # & # % % # # # # # # # # # # # # @ @ # # @ @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + + + + + @ + + + + + + + + + + + + + X + o + X + O o O + o + O + O O O O O O O O O O O . . O X . . . . o o o O O o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , : , , , , > , , > , , , : > , : : , : > > , > > : > > > > : : > : > : > : : : : : : : : : : : - : : : & : : & : : & : & : & : : & & & & - & - & & & & & & & & & & & & & & # & & & # & & # & & @ & # & # # # # & # & % # # % # # # & # # # # # # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + @ + @ X + @ + + + @ + + @ + + + + + + O @ O + O + + + O + + X + O O + O O O O O X + X O O O O O X X o O O . . o . . . O o . . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , , 1 , 1 , 1 , , 1 , 1 , , , , , , , > , , > , > , > : , , , , , , : , > > > > > > > : : > > > > : : : : > : : : > : : : : : : : - : : : & : : : & : & : & : & & : & : & & & & & & & & & & & & & & # # & & & & # & & # & & # # & # & & # & & & & # # & # % # # # # @ # # # # @ # @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X X @ @ @ @ + @ + @ + + + + + + + + @ + + + + + + + + O + o + + + O + X + O O O + O X + X O X O O O O O O O o . . . o . . . . o o o . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , > , , , , > : , : , > : , , > > , : > > > > > : > : > : : > > : : > : : : : : : - : - - : - : : : & : & & : : & : : & : & & - & - & & & & & & & & & & # & & & # & & & & # & & # & # & # & # # # # # # # # # # % # # # % # # # # # # # @ # @ # @ @ @ # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ + + @ + @ + + + @ + + + + + + + + + X + + + + + O + + O + O O + X O + + O + X o + + o O O O X O X X o . O o . o o o o . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , : , , > , , , , > , > > , : : > > > > > > > > : > : > > : > : : > : : : : - : : : : - - : & & - : : - : & : & & & & & : & & - & & : & & & & & & & & & & & & & # & # & & & # & & # & # & & # & # # & & # # # # & & # # # # # # # # # # @ @ @ # @ @ @ @ @ @ X @ @ @ @ X @ @ X @ @ @ X @ + @ + + @ + + @ + + + + + + + + + + + O + + + + O O + + X + O + O O O + X O O O O O O O X O O X o o . . . . o . o . o . o . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , , , 1 , , , , 1 , , , , , , , , , , , , , : , , : : , > , > , : , : > : > > : : > > > : > : : > : : : : : : : : : - : : : : : : : : : & : & : : & : : & : & & & & & & - & & & & & & & & & & & & & & # # & & # & & # & # & # & & # & & # # # # # # % # % # # # # # # @ # # # # @ @ @ # @ @ # @ @ @ @ @ X X @ + @ + @ @ + + @ + + + + + @ + + + + + + + + + + + X + + + + + X + + X O O + O O O O O O O + o O O O + O O . . O . o o . . . . . . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 , , , , 1 , , , , , , , , , , , , , , , , , : , , : , : > : , : , > > > : > > : : > : > : : : > : : : : : : : : : : : - : : & : & : & & : & & : & : & & & & - : & & & & & & & & & & & # & & & # # & & & # & # # & & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ # @ # # @ @ @ @ @ @ @ @ # @ @ + @ @ @ + @ @ + + @ @ + + + @ + + + + + + + + + + + + O + X + + + X O + + O + X + + O + O O + X O O O O O . O . O . . o o . . . o o . . . O O ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 , 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 1 , , , , , , 1 , , , , , , , : , : , : , , , : , > > > : > , : > > > > > > > : : : > : > : : > : : : : : : : : & : : & : & : - : & : & & : : & : & : & - & & - - & & & & & & & & & & & & # & & & & & # & & & & # & & # & # & # & # # & & # % # # # % % # # # # # @ @ @ # # @ @ @ @ @ @ @ X # @ @ @ X @ @ @ @ + @ + @ @ @ @ + + + + @ + @ + + + + + + + + + + + + O + + O + + O O + + O O O + O O O o O O O O O O O . . o o . . . . . o o o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , 1 , , , 1 , , , , , , , , , , : , , , , , , > > , , > , , > , , : , > > > : > : > > > > : : > : > : : > : : : : : : : : : : : : - - : & : - : & & : & : & & - & & & - & & & & & & & # & & & & & & & # # & & # & # # & # # # & # & # # # & # # # # % % % % @ # # # # # # # # @ # @ # @ @ @ @ @ @ @ # @ @ # @ @ + + @ + @ + + + + @ + @ + + + + + + + + + + + + + + X + + O + + + O + + O O + O + O O O O O o O O O O O O . o . O . O o . . . o . o o O O ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 1 2 1 2 , 1 1 1 1 1 , 2 2 , 1 1 1 , 1 1 , , 1 1 , , 1 1 , , , , , 1 , , , , , , , , > , , > , > , > , : > , : , > : : , : > > > > > > : > > : : > : : : > : : : > : : : : : : - : - : - : & & : - & : : : & : & & : : & & & & & & : & & & & & & & & # & & & # & # & & & & # & # & # # & # # # & # & # # & # # # # # # # # # # # # @ @ - @ @ @ @ o - + o - @ @ @ @ @ @ @ + @ + + @ @ + @ + @ + @ + @ + + + + + + + + + + + + + + + + o + + X X + O + + X + + O O o O O O O O X X O X O X O o o O o O X X O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 1 2 1 1 2 1 2 1 1 2 , , 1 1 1 , 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , > , > , , , , , , : , , , > , > , : , > : > > : > > : > : : > : > : : : : : : : : : - : - - : : : : - : : & & & : : : & & : & : & & & & & & & & & & & & & & & & & & & & # # & & # & # & # # & & # # # & # # # # # & # # # # # # # # @ @ # + # @ o @ - o @ @ + @ @ @ + @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + X + + + o + o + + O + O O X X O O O + O O O O O + O O o X O O O O X O O X O o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 1 1 2 , 2 1 2 1 1 1 2 , 1 , , 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , , , , , , , , 1 , , , , > , , , > , > > , : , : : , , : > : , : : > > > > : > : > > : : : > : : : : : : : : : : : - : - : - : : & & : & & : & : & & & & & & : & & & & & & & & & & & & & & & # & & # # & & & # & # & # & & & # & & # # # # & # & # # # & # # # # # # # # + @ @ - @ - o @ @ @ @ @ @ @ + @ + @ @ + @ @ + + @ + @ + + + + + @ + + + + + + + + X X + + + + + + o o + O O O o + o X O O O + O O O O O O O X X o o O X o O X o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 2 1 1 1 1 2 1 1 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , 1 , 1 , , , , , , , , , , , > , , , > , , , > , , > > , > > : , > > > > > > : > : : > > : : > : : > : : : : : - : : - : : : & : : - : & : & : & : & : : & & & & & & & & & & & & & & # & # & & & # & & & # & # & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ + - @ @ @ o - + @ @ @ @ @ + o - + @ + @ @ + @ + + @ + + + @ @ + + + + + + + + + + + + + X + o + o + + O + + O + X + + o O O O O O O O O O O X X . . . . o O o O X . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 1 1 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , , , > > , , : , , , : > > , > , : > > : > > : > > : > > : > : : : : : : > : : - : : : - : & : : & : & : & : & : & & : & & & & & & : & & & & & & & & & # & & & & & & # # & & & # & # & # & # & # # # # # & & # # # & # # # # # # # # # # @ + + - o + + @ o + @ @ + @ @ + + @ @ + @ @ + + @ @ @ + + + @ + + + + + + + + + + + X + + + + + X + X + O + O o O X + O O O O O O O O O O X O o . o O . . o o o . o . X O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 , , 1 1 1 1 1 , , 1 , 1 , , , , 1 1 , 1 1 1 , , , , , , , , , , : , , , > , , : , > , > , : : , : > > : > > > > : > > : : > : > > > : : : & : : : - : - - : - & : - - - : : & & : : & : & & : & & & & & & & & & # & & & & & & # & & & & & & # & & & # & # # # & & # & # # # # # # # # # # # # # # # # @ # - + o - - @ @ - - o @ @ @ + @ @ @ + + @ @ + @ + + + + @ + + + + + + + + + + + + + + + + X + X + X + O + O + + o O O + + + O + O O O O O o X O . X o o O o O X O o . . O . O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 1 1 1 1 2 1 2 , 1 1 1 2 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , 1 , , , , , , , , , , , , , , , : , > , , > > > > , > , > : , : : , : , , : : > > : : : : > : > : : : : : : : : : : : - : : - : : & : & : & & & : & & : & & : & & : & : & & & & & & & & & & # & # & # & # # # # & # # & & & & # # # & # & # & # & # # # # # # # # # # @ # # @ + @ @ @ @ @ @ o - @ @ @ @ + @ + @ @ + @ + @ + @ + @ + + @ + + + @ + + + + + + + X + + + + + X + O + O + o + + + X O O O + O O O O O O X O X . . . . o X O X . o . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 2 1 2 1 1 1 1 1 2 , 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , 1 , , , , , , > , , , , > , , , , , , , , , : , : > , > , , : , > : > > > : > > > > : : : : : : : > : : : : : : : : - : : - : - : - - & : : & & & : & : & & & & & & & & & & & & & & & & & & & & & & & & & # & & # # # # & & # # & # # # # # # # # # & # # # # # # @ # @ - @ @ @ @ @ @ @ @ + @ @ @ @ @ # + @ @ @ + + @ + @ + + + + @ + + + + + + + + + + + + + o + + + X + O + O + o X O O + O O O O O O O O O O O O o . o . O o X . . . . O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 1 1 1 1 2 1 2 , 1 2 1 2 , 1 1 2 , 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , 1 1 , , , , , , , , , , > , > , , , > > > , : , , , > , > : , , : > : , > > : > : > > > : : : : > > : : : : : : : : & : & : : & : - - - - & : & : & : - & & & : & & & & & & & & & & & # & & # & & & # & # # & & # # & # & & # # & # # # # # # # # # # # # # # # # # # # # - o # @ @ @ @ @ + @ @ @ @ + @ + + @ @ @ + + + + @ + + + + + @ + + @ + + + + + + + + o + o + + + O + X + O O + + O + O + O + O O O O O O O O O O X . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 , 2 , 1 , , 1 1 , 1 1 , 1 , , 1 , , , , , , , 1 , 1 , , , , , , , , , > , , , > , , , : > , : > , : : , > > : > > : > : : : : > > > : : : : : : : : : : : : : : : : - : - - - - - & : & & & - - : & & & & & & & & & & & & & & & & & & # & & & & & # & & & # & # & # & # # & & # & # & # # # # # # # # # # @ # # - @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ + + @ + @ + + + + + + + + + + + + + + + + + o + X + + + + O O + O O O O O O O O O O X O O O X O X . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 2 2 , 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 1 , 1 , , 1 1 , 1 , , , , , , , , > , , , > > > > > : , : , > , , > , > > : : , > > > > : > > > : : : : > : : : : : : : : : : : & : : & - : & : - - - : : & - & & - & & & & - & & - & & & & & # & & & & & & # & # & & # & # # & # & # & # # & # # # # # & # & # # # # # # # # @ # @ o @ @ # # @ @ @ @ @ @ @ @ + @ @ + @ @ + @ + + + + + + + + + + + + + + + + + + o + + + o o + o + + O + O + O O O X + X + + O O + O O X O O O X O O X o o o o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 1 2 1 2 1 2 1 2 1 1 1 1 2 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , , > , , : , , > , : : , : , : , > : , : > : > : > : : > : > : > : : : : : : : : : : : : : : : & : : & - : & & : & : & - & : & : & & & & & & & & & & & & # & & # & & & & & & & # & # # & & # # & # # & # & # # # # # # # # # # # # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ @ @ + @ @ + @ @ @ + @ + + + + + + + + + + + + + + + + + X + O + O + + + O O O O O O O X O O O O O O O X X O . . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , , 1 , 1 , 1 , , , , 1 , , , , , , , , > , > > > , , , : , , : , > : , > , : > > > : > : > > : > : : > : > : : > : : : : : : : & : & & : : & : & & - & : & : - & - & - & - & & - & & & & & & & & # & & & & # & & # & # & & # & # & # # & & # # # # & # # & # # # & # # # # # # # # # # @ # @ # @ @ @ @ @ @ + @ @ @ @ @ # @ + + + @ + + + + + + + + @ + @ @ + + + + + + + + o + + + X + + O + + O + O + O + O O X O X O O O X o o O O o O O X o . o . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , , , , , , , , , , , , > , > , , : , , , > , : , : , > > : , > : : > : : > > : : : : : : : : : : : : : : : : : : : : - : : : : & : & - & & - & - & & & & & & & & & & & & & & & & & & & # & # & # # & # & # & & & # # & # # # # & # # & # # # # # # # # # @ @ @ # @ @ @ @ @ @ @ + @ @ @ @ + + @ + @ @ + @ + @ @ @ @ + + @ + + + + + + + + + + + o + + + o + + X O + O O + O O O O O O O + O O O O O O O o O O O o o o . o . . . . . ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 2 1 2 2 2 1 1 1 2 , 2 1 1 1 1 1 1 2 , 1 1 , 1 1 1 1 1 1 , 1 1 , , , , , 1 , , , , , , , , , , , , , , , , > , , : , > , : : , , : , : : , , : : > > > > : > : : > : > > : : : : : : : : : & & : : & & : - - & : & & & - - & - & - & & & - & & & & & & & & & & # & & # & & & # # & & # & # & # # # & # # # & # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + @ @ + @ + + + @ + @ + + + + + + + + + + + + + + + + + + + X + + + X O O + + O X O O O + X O X O O O O O O O O O O . . o o . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 2 1 1 1 1 , 1 , , , 1 , , , 1 , 1 , , , , , , , , , , > , , > , > > , , > , , > , > > , , : , : > > : , : > > : : > > : > : : : : : : : : : : : - : : : : & : : : & : - - : : & : & - - - & & - - & & & & & & & & & & & & & & & & & # & # & # & & # & # & # # & # # # & # # # & # # # # # # # # # # # # # # @ @ # @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + o + + o + o + + X X + O + O + O + O + O X O O O O O O O O O O O . o . . . . . o o " +}; diff --git a/branches/pcsx2_0.9.2/Linux/Config.c b/branches/pcsx2_0.9.2/Linux/Config.c new file mode 100644 index 0000000..3f65524 --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/Config.c @@ -0,0 +1,137 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "Linux.h" + +#define GetValue(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%s", var); \ + } + +#define GetValuel(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%x", &var); \ + } + +#define SetValue(name, var) \ + fprintf (f,"%s = %s\n", name, var); + +#define SetValuel(name, var) \ + fprintf (f,"%s = %x\n", name, var); + +int LoadConfig(PcsxConfig *Conf) { + struct stat buf; + FILE *f; + int size; + char *data,*tmp; + + if (stat(cfgfile, &buf) == -1) return -1; + size = buf.st_size; + + f = fopen(cfgfile,"r"); + if (f == NULL) return -1; + + data = (char*)malloc(size); + if (data == NULL) return -1; + + fread(data, 1, size, f); + fclose(f); + + GetValue("Bios", Config.Bios); + GetValue("GS", Config.GS); + GetValue("PAD1", Config.PAD1); + GetValue("PAD2", Config.PAD2); + GetValue("SPU2", Config.SPU2); + GetValue("CDVD", Config.CDVD); + GetValue("DEV9", Config.DEV9); + GetValue("USB", Config.USB); + GetValue("FW", Config.FW); + GetValue("Mcd1", Config.Mcd1); + GetValue("Mcd2", Config.Mcd2); + GetValue("PluginsDir", Config.PluginsDir); + GetValue("BiosDir", Config.BiosDir); + GetValuel("Cpu", Config.Cpu); + GetValuel("PsxOut", Config.PsxOut); + GetValuel("RegCaching", Config.Regcaching); + GetValuel("Patch", Config.Patch); + GetValuel("VUrec", Config.VUrec); +// GetValuel("PadHack", Config.PadHack); + GetValuel("varLog", varLog); + Config.Lang[0] = 0; + GetValue("Lang", Config.Lang); + + free(data); + +#ifdef ENABLE_NLS + if (Config.Lang[0]) { + extern int _nl_msg_cat_cntr; + + setenv("LANGUAGE", Config.Lang, 1); + ++_nl_msg_cat_cntr; + } +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + FILE *f; + + f = fopen(cfgfile,"w"); + if (f == NULL) return; + + SetValue("Bios", Config.Bios); + SetValue("GS", Config.GS); + SetValue("PAD1", Config.PAD1); + SetValue("PAD2", Config.PAD2); + SetValue("SPU2", Config.SPU2); + SetValue("CDVD", Config.CDVD); + SetValue("DEV9", Config.DEV9); + SetValue("USB", Config.USB); + SetValue("FW", Config.FW); + SetValue("Mcd1", Config.Mcd1); + SetValue("Mcd2", Config.Mcd2); + SetValue("PluginsDir", Config.PluginsDir); + SetValue("BiosDir", Config.BiosDir); + SetValuel("Cpu", Config.Cpu); + SetValuel("PsxOut", Config.PsxOut); + SetValuel("RegCaching", Config.Regcaching); + SetValuel("Patch", Config.Patch); + SetValuel("VUrec", Config.VUrec); +// SetValuel("PadHack", Config.PadHack); + SetValuel("varLog", varLog); + SetValue("Lang", Config.Lang); + + fclose(f); + + return; +} diff --git a/branches/pcsx2_0.9.2/Linux/GladeCalls.c b/branches/pcsx2_0.9.2/Linux/GladeCalls.c new file mode 100644 index 0000000..d8fa54e --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeCalls.c @@ -0,0 +1,828 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + + +void +OnDestroy (GtkObject *object, + gpointer user_data) +{ + +} + + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_Close (GtkButton *button, + gpointer user_data) +{ + +} + + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + + return FALSE; +} + + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Step (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Go (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Log (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/branches/pcsx2_0.9.2/Linux/GladeCalls.h b/branches/pcsx2_0.9.2/Linux/GladeCalls.h new file mode 100644 index 0000000..8c1a3db --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeCalls.h @@ -0,0 +1,411 @@ +#include + + +void +OnDestroy (GtkObject *object, + gpointer user_data); + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Gpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GpuAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data); + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data); + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_Close (GtkButton *button, + gpointer user_data); + +gboolean +OnDebug_ScrollBtn (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data); + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_Step (GtkButton *button, + gpointer user_data); + +void +OnDebug_Go (GtkButton *button, + gpointer user_data); + +void +OnDebug_Log (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data); + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data); + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data); + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data); + +void +OnLoggin_Cancel (GtkButton *button, + gpointer user_data); + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data); + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data); + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data); + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_GtkMenuItem_Language_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_item1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data); + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data); + +void +OnMemWrite_Ok (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data); + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FwAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data); diff --git a/branches/pcsx2_0.9.2/Linux/GladeFuncs.c b/branches/pcsx2_0.9.2/Linux/GladeFuncs.c new file mode 100644 index 0000000..c6ccdbe --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeFuncs.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "GladeFuncs.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists (".pixmaps", filename); + } + + if (!found_filename) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning (_("Error loading pixmap file: %s"), found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/branches/pcsx2_0.9.2/Linux/GladeFuncs.h b/branches/pcsx2_0.9.2/Linux/GladeFuncs.h new file mode 100644 index 0000000..86a3134 --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeFuncs.h @@ -0,0 +1,61 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/branches/pcsx2_0.9.2/Linux/GladeGui.c b/branches/pcsx2_0.9.2/Linux/GladeGui.c new file mode 100644 index 0000000..e01cf7f --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeGui.c @@ -0,0 +1,3008 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "GladeCalls.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +GtkWidget* +create_MainWindow (void) +{ + GtkWidget *MainWindow; + GtkWidget *vbox1; + GtkWidget *GtkMenuBar_Menu; + GtkWidget *GtkMenuItem_File; + GtkWidget *GtkMenuItem_File_menu; + GtkAccelGroup *GtkMenuItem_File_menu_accels; + GtkWidget *run_cd1; + GtkWidget *GtkMenuItem_LoadElf; + GtkWidget *separator2; + GtkWidget *states1; + GtkWidget *states1_menu; + GtkAccelGroup *states1_menu_accels; + GtkWidget *load1; + GtkWidget *load1_menu; + GtkAccelGroup *load1_menu_accels; + GtkWidget *slot_1; + GtkWidget *slot_3; + GtkWidget *slot_4; + GtkWidget *slot_5; + GtkWidget *slot_2; + GtkWidget *other1; + GtkWidget *save1; + GtkWidget *save1_menu; + GtkAccelGroup *save1_menu_accels; + GtkWidget *slot_6; + GtkWidget *slot_7; + GtkWidget *slot_8; + GtkWidget *slot_9; + GtkWidget *slot_10; + GtkWidget *other2; + GtkWidget *GtkMenuItem_Exit; + GtkWidget *GtkMenuItem_Emulator; + GtkWidget *GtkMenuItem_Emulator_menu; + GtkAccelGroup *GtkMenuItem_Emulator_menu_accels; + GtkWidget *GtkMenuItem_Run; + GtkWidget *GtkMenuItem_Reset; + GtkWidget *GtkMenuItem_Arguments; + GtkWidget *GtkMenuItem_Configuration; + GtkWidget *GtkMenuItem_Configuration_menu; + GtkAccelGroup *GtkMenuItem_Configuration_menu_accels; + GtkWidget *GtkMenuItem_PluginsBios; + GtkWidget *separator3; + GtkWidget *GtkMenuItem_Graphics; + GtkWidget *GtkMenuItem_Controllers; + GtkWidget *GtkMenuItem_Sound; + GtkWidget *GtkMenuItem_Cdvdrom; + GtkWidget *GtkMenuItem_Dev9; + GtkWidget *separator4; + GtkWidget *GtkMenuItem_Cpu; + GtkWidget *GtkMenuItem_Language; + GtkWidget *GtkMenuItem_Debug; + GtkWidget *GtkMenuItem_Debug_menu; + GtkAccelGroup *GtkMenuItem_Debug_menu_accels; + GtkWidget *GtkMenuItem_EnterDebugger; + GtkWidget *GtkMenuItem_Logging; + GtkWidget *GtkMenuItem_Help; + GtkWidget *GtkMenuItem_Help_menu; + GtkAccelGroup *GtkMenuItem_Help_menu_accels; + GtkWidget *GtkMenuItem_About; + + MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (MainWindow), "MainWindow", MainWindow); + gtk_widget_set_usize (MainWindow, -2, 200); + gtk_window_set_title (GTK_WINDOW (MainWindow), _("PCSX")); + gtk_window_set_position (GTK_WINDOW (MainWindow), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MainWindow), FALSE, FALSE, FALSE); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (MainWindow), vbox1); + + GtkMenuBar_Menu = gtk_menu_bar_new (); + gtk_widget_ref (GtkMenuBar_Menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuBar_Menu", GtkMenuBar_Menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuBar_Menu); + gtk_box_pack_start (GTK_BOX (vbox1), GtkMenuBar_Menu, FALSE, FALSE, 0); + + GtkMenuItem_File = gtk_menu_item_new_with_label (_("File")); + gtk_widget_ref (GtkMenuItem_File); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File", GtkMenuItem_File, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_File); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_File); + + GtkMenuItem_File_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_File_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_File_menu", GtkMenuItem_File_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_File), GtkMenuItem_File_menu); + GtkMenuItem_File_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_File_menu)); + + run_cd1 = gtk_menu_item_new_with_label (_("Run CD")); + gtk_widget_ref (run_cd1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "run_cd1", run_cd1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (run_cd1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), run_cd1); + + GtkMenuItem_LoadElf = gtk_menu_item_new_with_label (_("Load Elf")); + gtk_widget_ref (GtkMenuItem_LoadElf); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_LoadElf", GtkMenuItem_LoadElf, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_LoadElf); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_LoadElf); + + separator2 = gtk_menu_item_new (); + gtk_widget_ref (separator2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator2", separator2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator2); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), separator2); + gtk_widget_set_sensitive (separator2, FALSE); + + states1 = gtk_menu_item_new_with_label (_("States")); + gtk_widget_ref (states1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1", states1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (states1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), states1); + + states1_menu = gtk_menu_new (); + gtk_widget_ref (states1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "states1_menu", states1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (states1), states1_menu); + states1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (states1_menu)); + + load1 = gtk_menu_item_new_with_label (_("Load")); + gtk_widget_ref (load1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1", load1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (load1); + gtk_container_add (GTK_CONTAINER (states1_menu), load1); + + load1_menu = gtk_menu_new (); + gtk_widget_ref (load1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "load1_menu", load1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (load1), load1_menu); + load1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (load1_menu)); + + slot_1 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_1", slot_1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_1); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_1); + + slot_3 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_3", slot_3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_3); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_3); + + slot_4 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_4", slot_4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_4); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_4); + + slot_5 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_5); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_5", slot_5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_5); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_5); + + slot_2 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_2", slot_2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_2); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_2); + + other1 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other1", other1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other1); + gtk_container_add (GTK_CONTAINER (load1_menu), other1); + + save1 = gtk_menu_item_new_with_label (_("Save")); + gtk_widget_ref (save1); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1", save1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (save1); + gtk_container_add (GTK_CONTAINER (states1_menu), save1); + + save1_menu = gtk_menu_new (); + gtk_widget_ref (save1_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "save1_menu", save1_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (save1), save1_menu); + save1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (save1_menu)); + + slot_6 = gtk_menu_item_new_with_label (_("Slot 1")); + gtk_widget_ref (slot_6); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_6", slot_6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_6); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_6); + + slot_7 = gtk_menu_item_new_with_label (_("Slot 2")); + gtk_widget_ref (slot_7); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_7", slot_7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_7); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_7); + + slot_8 = gtk_menu_item_new_with_label (_("Slot 3")); + gtk_widget_ref (slot_8); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_8", slot_8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_8); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_8); + + slot_9 = gtk_menu_item_new_with_label (_("Slot 4")); + gtk_widget_ref (slot_9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_9", slot_9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_9); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_9); + + slot_10 = gtk_menu_item_new_with_label (_("Slot 5")); + gtk_widget_ref (slot_10); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "slot_10", slot_10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (slot_10); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_10); + + other2 = gtk_menu_item_new_with_label (_("Other...")); + gtk_widget_ref (other2); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "other2", other2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (other2); + gtk_container_add (GTK_CONTAINER (save1_menu), other2); + + GtkMenuItem_Exit = gtk_menu_item_new_with_label (_("Exit")); + gtk_widget_ref (GtkMenuItem_Exit); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Exit", GtkMenuItem_Exit, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Exit); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_Exit); + + GtkMenuItem_Emulator = gtk_menu_item_new_with_label (_("Emulator")); + gtk_widget_ref (GtkMenuItem_Emulator); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator", GtkMenuItem_Emulator, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Emulator); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Emulator); + + GtkMenuItem_Emulator_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Emulator_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Emulator_menu", GtkMenuItem_Emulator_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Emulator), GtkMenuItem_Emulator_menu); + GtkMenuItem_Emulator_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Emulator_menu)); + + GtkMenuItem_Run = gtk_menu_item_new_with_label (_("Run")); + gtk_widget_ref (GtkMenuItem_Run); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Run", GtkMenuItem_Run, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Run); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Run); + + GtkMenuItem_Reset = gtk_menu_item_new_with_label (_("Reset")); + gtk_widget_ref (GtkMenuItem_Reset); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Reset", GtkMenuItem_Reset, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Reset); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Reset); + + GtkMenuItem_Arguments = gtk_menu_item_new_with_label (_("Arguments")); + gtk_widget_ref (GtkMenuItem_Arguments); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Arguments", GtkMenuItem_Arguments, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Arguments); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Arguments); + + GtkMenuItem_Configuration = gtk_menu_item_new_with_label (_("Configuration")); + gtk_widget_ref (GtkMenuItem_Configuration); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration", GtkMenuItem_Configuration, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Configuration); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Configuration); + + GtkMenuItem_Configuration_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Configuration_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Configuration_menu", GtkMenuItem_Configuration_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Configuration), GtkMenuItem_Configuration_menu); + GtkMenuItem_Configuration_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Configuration_menu)); + + GtkMenuItem_PluginsBios = gtk_menu_item_new_with_label (_("Plugins & Bios")); + gtk_widget_ref (GtkMenuItem_PluginsBios); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_PluginsBios", GtkMenuItem_PluginsBios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_PluginsBios); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_PluginsBios); + + separator3 = gtk_menu_item_new (); + gtk_widget_ref (separator3); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator3", separator3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator3); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator3); + gtk_widget_set_sensitive (separator3, FALSE); + + GtkMenuItem_Graphics = gtk_menu_item_new_with_label (_("Graphics")); + gtk_widget_ref (GtkMenuItem_Graphics); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Graphics", GtkMenuItem_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Graphics); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Graphics); + + GtkMenuItem_Controllers = gtk_menu_item_new_with_label (_("Controllers")); + gtk_widget_ref (GtkMenuItem_Controllers); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Controllers", GtkMenuItem_Controllers, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Controllers); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Controllers); + + GtkMenuItem_Sound = gtk_menu_item_new_with_label (_("Sound")); + gtk_widget_ref (GtkMenuItem_Sound); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Sound", GtkMenuItem_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Sound); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Sound); + + GtkMenuItem_Cdvdrom = gtk_menu_item_new_with_label (_("Cdvdrom")); + gtk_widget_ref (GtkMenuItem_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cdvdrom", GtkMenuItem_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cdvdrom); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cdvdrom); + + GtkMenuItem_Dev9 = gtk_menu_item_new_with_label (_("Dev9")); + gtk_widget_ref (GtkMenuItem_Dev9); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Dev9", GtkMenuItem_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Dev9); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Dev9); + + separator4 = gtk_menu_item_new (); + gtk_widget_ref (separator4); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "separator4", separator4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (separator4); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator4); + gtk_widget_set_sensitive (separator4, FALSE); + + GtkMenuItem_Cpu = gtk_menu_item_new_with_label (_("Cpu")); + gtk_widget_ref (GtkMenuItem_Cpu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Cpu", GtkMenuItem_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Cpu); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cpu); + + GtkMenuItem_Language = gtk_menu_item_new_with_label (_("Language")); + gtk_widget_ref (GtkMenuItem_Language); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Language", GtkMenuItem_Language, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Language); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Language); + + GtkMenuItem_Debug = gtk_menu_item_new_with_label (_("Debug")); + gtk_widget_ref (GtkMenuItem_Debug); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug", GtkMenuItem_Debug, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Debug); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Debug); + + GtkMenuItem_Debug_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Debug_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Debug_menu", GtkMenuItem_Debug_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Debug), GtkMenuItem_Debug_menu); + GtkMenuItem_Debug_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Debug_menu)); + + GtkMenuItem_EnterDebugger = gtk_menu_item_new_with_label (_("Enter Debugger ...")); + gtk_widget_ref (GtkMenuItem_EnterDebugger); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_EnterDebugger", GtkMenuItem_EnterDebugger, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_EnterDebugger); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_EnterDebugger); + + GtkMenuItem_Logging = gtk_menu_item_new_with_label (_("Logging")); + gtk_widget_ref (GtkMenuItem_Logging); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Logging", GtkMenuItem_Logging, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Logging); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_Logging); + + GtkMenuItem_Help = gtk_menu_item_new_with_label (_("Help")); + gtk_widget_ref (GtkMenuItem_Help); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help", GtkMenuItem_Help, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_Help); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Help); + + GtkMenuItem_Help_menu = gtk_menu_new (); + gtk_widget_ref (GtkMenuItem_Help_menu); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_Help_menu", GtkMenuItem_Help_menu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Help), GtkMenuItem_Help_menu); + GtkMenuItem_Help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (GtkMenuItem_Help_menu)); + + GtkMenuItem_About = gtk_menu_item_new_with_label (_("About PCSX2")); + gtk_widget_ref (GtkMenuItem_About); + gtk_object_set_data_full (GTK_OBJECT (MainWindow), "GtkMenuItem_About", GtkMenuItem_About, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkMenuItem_About); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Help_menu), GtkMenuItem_About); + + gtk_signal_connect (GTK_OBJECT (MainWindow), "destroy", + GTK_SIGNAL_FUNC (OnDestroy), + NULL); + gtk_signal_connect (GTK_OBJECT (run_cd1), "activate", + GTK_SIGNAL_FUNC (OnFile_RunCD), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_LoadElf), "activate", + GTK_SIGNAL_FUNC (OnFile_LoadElf), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_1), "activate", + GTK_SIGNAL_FUNC (OnStates_Load1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_3), "activate", + GTK_SIGNAL_FUNC (OnStates_Load2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_4), "activate", + GTK_SIGNAL_FUNC (OnStates_Load3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_5), "activate", + GTK_SIGNAL_FUNC (OnStates_Load4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_2), "activate", + GTK_SIGNAL_FUNC (OnStates_Load5), + NULL); + gtk_signal_connect (GTK_OBJECT (other1), "activate", + GTK_SIGNAL_FUNC (OnStates_LoadOther), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_6), "activate", + GTK_SIGNAL_FUNC (OnStates_Save1), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_7), "activate", + GTK_SIGNAL_FUNC (OnStates_Save2), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_8), "activate", + GTK_SIGNAL_FUNC (OnStates_Save3), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_9), "activate", + GTK_SIGNAL_FUNC (OnStates_Save4), + NULL); + gtk_signal_connect (GTK_OBJECT (slot_10), "activate", + GTK_SIGNAL_FUNC (OnStates_Save5), + NULL); + gtk_signal_connect (GTK_OBJECT (other2), "activate", + GTK_SIGNAL_FUNC (OnStates_SaveOther), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Exit), "activate", + GTK_SIGNAL_FUNC (OnFile_Exit), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Run), "activate", + GTK_SIGNAL_FUNC (OnEmu_Run), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Reset), "activate", + GTK_SIGNAL_FUNC (OnEmu_Reset), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Arguments), "activate", + GTK_SIGNAL_FUNC (OnEmu_Arguments), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_PluginsBios), "activate", + GTK_SIGNAL_FUNC (OnConf_Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Graphics), "activate", + GTK_SIGNAL_FUNC (OnConf_Gs), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Controllers), "activate", + GTK_SIGNAL_FUNC (OnConf_Pads), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Sound), "activate", + GTK_SIGNAL_FUNC (OnConf_Spu2), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cdvdrom), "activate", + GTK_SIGNAL_FUNC (OnConf_Cdvd), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Dev9), "activate", + GTK_SIGNAL_FUNC (OnConf_Dev9), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Cpu), "activate", + GTK_SIGNAL_FUNC (OnConf_Cpu), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_EnterDebugger), "activate", + GTK_SIGNAL_FUNC (OnDebug_Debugger), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_Logging), "activate", + GTK_SIGNAL_FUNC (OnDebug_Logging), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkMenuItem_About), "activate", + GTK_SIGNAL_FUNC (OnHelp_About), + NULL); + + return MainWindow; +} + +GtkWidget* +create_AboutDlg (void) +{ + GtkWidget *AboutDlg; + GtkWidget *vbox2; + GtkWidget *packer1; + GtkWidget *hbox1; + GtkWidget *vbox4; + GtkWidget *GtkAbout_LabelVersion; + GtkWidget *frame1; + GtkWidget *vbox6; + GtkWidget *GtkAbout_LabelAuthors; + GtkWidget *pixmap1; + GtkWidget *frame2; + GtkWidget *vbox5; + GtkWidget *GtkAbout_LabelGreets; + GtkWidget *hbuttonbox1; + GtkWidget *GtkButton_Ok; + + AboutDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (AboutDlg), "AboutDlg", AboutDlg); + gtk_container_set_border_width (GTK_CONTAINER (AboutDlg), 10); + gtk_window_set_title (GTK_WINDOW (AboutDlg), _("Pcsx About")); + gtk_window_set_position (GTK_WINDOW (AboutDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (AboutDlg), FALSE, FALSE, FALSE); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (AboutDlg), vbox2); + + packer1 = gtk_packer_new (); + gtk_widget_ref (packer1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "packer1", packer1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (packer1); + gtk_box_pack_start (GTK_BOX (vbox2), packer1, FALSE, FALSE, 0); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox4); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox4", vbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox4); + gtk_box_pack_start (GTK_BOX (hbox1), vbox4, TRUE, TRUE, 0); + + GtkAbout_LabelVersion = gtk_label_new (_("PCSX2\r\r\r\nVersion x.x")); + gtk_widget_ref (GtkAbout_LabelVersion); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelVersion", GtkAbout_LabelVersion, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelVersion); + gtk_box_pack_start (GTK_BOX (vbox4), GtkAbout_LabelVersion, FALSE, FALSE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_ref (frame1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame1", frame1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox4), frame1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame1), 5); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox6); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox6", vbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (frame1), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + GtkAbout_LabelAuthors = gtk_label_new (_("written by...")); + gtk_widget_ref (GtkAbout_LabelAuthors); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelAuthors", GtkAbout_LabelAuthors, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelAuthors); + gtk_box_pack_start (GTK_BOX (vbox6), GtkAbout_LabelAuthors, FALSE, FALSE, 0); + + pixmap1 = create_pixmap (AboutDlg, "pcsxAbout.xpm"); + gtk_widget_ref (pixmap1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "pixmap1", pixmap1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (pixmap1); + gtk_box_pack_start (GTK_BOX (hbox1), pixmap1, TRUE, TRUE, 0); + + frame2 = gtk_frame_new (NULL); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox2), frame2, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame2), 5); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox5); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "vbox5", vbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (frame2), vbox5); + gtk_container_set_border_width (GTK_CONTAINER (vbox5), 5); + + GtkAbout_LabelGreets = gtk_label_new (_("greets to...")); + gtk_widget_ref (GtkAbout_LabelGreets); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkAbout_LabelGreets", GtkAbout_LabelGreets, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkAbout_LabelGreets); + gtk_box_pack_start (GTK_BOX (vbox5), GtkAbout_LabelGreets, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox1, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (AboutDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnHelpAbout_Ok), + NULL); + + return AboutDlg; +} + +GtkWidget* +create_ConfDlg (void) +{ + GtkWidget *ConfDlg; + GtkWidget *vbox12; + GtkWidget *table2; + GtkWidget *GtkCombo_Pad1; + GtkWidget *combo_entry4; + GtkWidget *GtkCombo_Pad2; + GtkWidget *combo_entry5; + GtkWidget *hbuttonbox6; + GtkWidget *GtkButton_PAD2configure; + GtkWidget *GtkButton_PAD2test; + GtkWidget *GtkButton_PAD2about; + GtkWidget *hbuttonbox7; + GtkWidget *GtkButton_PAD1configure; + GtkWidget *GtkButton_PAD1test; + GtkWidget *GtkButton_PAD1about; + GtkWidget *hbuttonbox8; + GtkWidget *GtkButton_GSconfigure; + GtkWidget *GtkButton_GStest; + GtkWidget *GtkButton_GSabout; + GtkWidget *GtkLabel_Graphics; + GtkWidget *GtkLabel_FirstController; + GtkWidget *GtkLabel_SecondController; + GtkWidget *GtkCombo_Gs; + GtkWidget *combo_entry2; + GtkWidget *GtkLabel_Sound; + GtkWidget *GtkCombo_Spu2; + GtkWidget *entry1; + GtkWidget *hbuttonbox12; + GtkWidget *GtkButton_SPU2configure; + GtkWidget *GtkButton_SPU2test; + GtkWidget *GtkButton_SPU2about; + GtkWidget *GtkCombo_Dev9; + GtkWidget *entry3; + GtkWidget *hbuttonbox21; + GtkWidget *GtkButton_DEV9configure; + GtkWidget *GtkButton_DEV9test; + GtkWidget *GtkButton_DEV9about; + GtkWidget *label23; + GtkWidget *GtkLabel_Cdvdrom; + GtkWidget *GtkCombo_Cdvd; + GtkWidget *entry2; + GtkWidget *hbuttonbox13; + GtkWidget *GtkButton_CDVDconfigure; + GtkWidget *GtkButton_CDVDtest; + GtkWidget *GtkButton_CDVDabout; + GtkWidget *label29; + GtkWidget *GtkCombo_Usb; + GtkWidget *entry4; + GtkWidget *hbuttonbox23; + GtkWidget *GtkButton_USBconfigure; + GtkWidget *GtkButton_USBtest; + GtkWidget *GtkButton_USBabout; + GtkWidget *GtkCombo_Bios; + GtkWidget *combo_entry7; + GtkWidget *GtkCombo_FW; + GtkWidget *entry5; + GtkWidget *hbuttonbox24; + GtkWidget *GtkButton_FWconfigure; + GtkWidget *GtkButton_FWtest; + GtkWidget *GtkButton_FWabout; + GtkWidget *label30; + GtkWidget *GtkLabel_Bios; + GtkWidget *hbox5; + GtkWidget *hbuttonbox11; + GtkWidget *GtkButton_SelectPluginsDir; + GtkWidget *GtkButton_SelectBiosDir; + GtkWidget *hbuttonbox10; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + ConfDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (ConfDlg), "ConfDlg", ConfDlg); + gtk_container_set_border_width (GTK_CONTAINER (ConfDlg), 10); + gtk_window_set_title (GTK_WINDOW (ConfDlg), _("Conf")); + gtk_window_set_position (GTK_WINDOW (ConfDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (ConfDlg), FALSE, FALSE, FALSE); + + vbox12 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "vbox12", vbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox12); + gtk_container_add (GTK_CONTAINER (ConfDlg), vbox12); + + table2 = gtk_table_new (14, 2, FALSE); + gtk_widget_ref (table2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "table2", table2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (vbox12), table2, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table2), 15); + + GtkCombo_Pad1 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad1", GtkCombo_Pad1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad1); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad1, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry4 = GTK_COMBO (GtkCombo_Pad1)->entry; + gtk_widget_ref (combo_entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry4", combo_entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry4); + + GtkCombo_Pad2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Pad2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Pad2", GtkCombo_Pad2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Pad2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad2, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry5 = GTK_COMBO (GtkCombo_Pad2)->entry; + gtk_widget_ref (combo_entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry5", combo_entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry5); + + hbuttonbox6 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox6); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox6", hbuttonbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox6); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox6, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox6), 0); + + GtkButton_PAD2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2configure", GtkButton_PAD2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2configure, GTK_CAN_DEFAULT); + + GtkButton_PAD2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2test", GtkButton_PAD2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2test, GTK_CAN_DEFAULT); + + GtkButton_PAD2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD2about", GtkButton_PAD2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2about, GTK_CAN_DEFAULT); + + hbuttonbox7 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox7", hbuttonbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox7); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox7, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox7), 0); + + GtkButton_PAD1configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_PAD1configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1configure", GtkButton_PAD1configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1configure, GTK_CAN_DEFAULT); + + GtkButton_PAD1test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_PAD1test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1test", GtkButton_PAD1test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1test); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1test, GTK_CAN_DEFAULT); + + GtkButton_PAD1about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_PAD1about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_PAD1about", GtkButton_PAD1about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_PAD1about); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1about, GTK_CAN_DEFAULT); + + hbuttonbox8 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox8); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox8", hbuttonbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox8); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox8, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox8), 0); + + GtkButton_GSconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_GSconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSconfigure", GtkButton_GSconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_GSconfigure, GTK_CAN_DEFAULT); + + GtkButton_GStest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_GStest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GStest", GtkButton_GStest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GStest); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GStest); + GTK_WIDGET_SET_FLAGS (GtkButton_GStest, GTK_CAN_DEFAULT); + + GtkButton_GSabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_GSabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_GSabout", GtkButton_GSabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_GSabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSabout); + GTK_WIDGET_SET_FLAGS (GtkButton_GSabout, GTK_CAN_DEFAULT); + + GtkLabel_Graphics = gtk_label_new (_("Graphics")); + gtk_widget_ref (GtkLabel_Graphics); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Graphics", GtkLabel_Graphics, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Graphics); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Graphics, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Graphics), 0, 0.5); + + GtkLabel_FirstController = gtk_label_new (_("First Controller")); + gtk_widget_ref (GtkLabel_FirstController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_FirstController", GtkLabel_FirstController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_FirstController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_FirstController, 0, 1, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_FirstController), 0, 0.5); + + GtkLabel_SecondController = gtk_label_new (_("Second Controller")); + gtk_widget_ref (GtkLabel_SecondController); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_SecondController", GtkLabel_SecondController, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_SecondController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_SecondController, 1, 2, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_SecondController), 0, 0.5); + + GtkCombo_Gs = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Gs); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Gs", GtkCombo_Gs, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Gs); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Gs, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry2 = GTK_COMBO (GtkCombo_Gs)->entry; + gtk_widget_ref (combo_entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry2", combo_entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry2); + + GtkLabel_Sound = gtk_label_new (_("Sound")); + gtk_widget_ref (GtkLabel_Sound); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Sound", GtkLabel_Sound, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Sound); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Sound, 1, 2, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Sound), 0, 0.5); + + GtkCombo_Spu2 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Spu2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Spu2", GtkCombo_Spu2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Spu2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Spu2, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry1 = GTK_COMBO (GtkCombo_Spu2)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox12 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox12); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox12", hbuttonbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox12); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox12, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox12), 0); + + GtkButton_SPU2configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_SPU2configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2configure", GtkButton_SPU2configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2configure, GTK_CAN_DEFAULT); + + GtkButton_SPU2test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_SPU2test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2test", GtkButton_SPU2test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2test); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2test, GTK_CAN_DEFAULT); + + GtkButton_SPU2about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_SPU2about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SPU2about", GtkButton_SPU2about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SPU2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2about); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2about, GTK_CAN_DEFAULT); + + GtkCombo_Dev9 = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Dev9); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Dev9", GtkCombo_Dev9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Dev9); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Dev9, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry3 = GTK_COMBO (GtkCombo_Dev9)->entry; + gtk_widget_ref (entry3); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry3", entry3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry3); + + hbuttonbox21 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox21); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox21", hbuttonbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox21); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox21, 0, 1, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox21), 0); + + GtkButton_DEV9configure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_DEV9configure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9configure", GtkButton_DEV9configure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9configure); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9configure, GTK_CAN_DEFAULT); + + GtkButton_DEV9test = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_DEV9test); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9test", GtkButton_DEV9test, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9test); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9test); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9test, GTK_CAN_DEFAULT); + + GtkButton_DEV9about = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_DEV9about); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_DEV9about", GtkButton_DEV9about, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_DEV9about); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9about); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9about, GTK_CAN_DEFAULT); + + label23 = gtk_label_new (_("Dev9")); + gtk_widget_ref (label23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label23", label23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label23); + gtk_table_attach (GTK_TABLE (table2), label23, 0, 1, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label23), 0, 0.5); + + GtkLabel_Cdvdrom = gtk_label_new (_("Cdvdrom")); + gtk_widget_ref (GtkLabel_Cdvdrom); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Cdvdrom", GtkLabel_Cdvdrom, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Cdvdrom); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Cdvdrom, 1, 2, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Cdvdrom), 0, 0.5); + + GtkCombo_Cdvd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Cdvd); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Cdvd", GtkCombo_Cdvd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Cdvd); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Cdvd, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry2 = GTK_COMBO (GtkCombo_Cdvd)->entry; + gtk_widget_ref (entry2); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry2", entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry2); + + hbuttonbox13 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox13); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox13", hbuttonbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox13); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox13, 1, 2, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox13), 0); + + GtkButton_CDVDconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_CDVDconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDconfigure", GtkButton_CDVDconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDconfigure, GTK_CAN_DEFAULT); + + GtkButton_CDVDtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_CDVDtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDtest", GtkButton_CDVDtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDtest); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDtest, GTK_CAN_DEFAULT); + + GtkButton_CDVDabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_CDVDabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_CDVDabout", GtkButton_CDVDabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CDVDabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDabout); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDabout, GTK_CAN_DEFAULT); + + label29 = gtk_label_new (_("Usb")); + gtk_widget_ref (label29); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label29", label29, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label29); + gtk_table_attach (GTK_TABLE (table2), label29, 0, 1, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label29), 0, 0.5); + + GtkCombo_Usb = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Usb); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Usb", GtkCombo_Usb, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Usb); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Usb, 0, 1, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry4 = GTK_COMBO (GtkCombo_Usb)->entry; + gtk_widget_ref (entry4); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry4", entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry4); + + hbuttonbox23 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox23); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox23", hbuttonbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox23); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox23, 0, 1, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox23), 0); + + GtkButton_USBconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_USBconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBconfigure", GtkButton_USBconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_USBconfigure, GTK_CAN_DEFAULT); + + GtkButton_USBtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_USBtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBtest", GtkButton_USBtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBtest); + GTK_WIDGET_SET_FLAGS (GtkButton_USBtest, GTK_CAN_DEFAULT); + + GtkButton_USBabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_USBabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_USBabout", GtkButton_USBabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_USBabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBabout); + GTK_WIDGET_SET_FLAGS (GtkButton_USBabout, GTK_CAN_DEFAULT); + + GtkCombo_Bios = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_Bios", GtkCombo_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Bios, 1, 2, 13, 14, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + combo_entry7 = GTK_COMBO (GtkCombo_Bios)->entry; + gtk_widget_ref (combo_entry7); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "combo_entry7", combo_entry7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry7); + + GtkCombo_FW = gtk_combo_new (); + gtk_widget_ref (GtkCombo_FW); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkCombo_FW", GtkCombo_FW, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_FW); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_FW, 1, 2, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + entry5 = GTK_COMBO (GtkCombo_FW)->entry; + gtk_widget_ref (entry5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "entry5", entry5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry5); + + hbuttonbox24 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox24); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox24", hbuttonbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox24); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox24, 1, 2, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox24), 0); + + GtkButton_FWconfigure = gtk_button_new_with_label (_("Configure")); + gtk_widget_ref (GtkButton_FWconfigure); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWconfigure", GtkButton_FWconfigure, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_FWconfigure, GTK_CAN_DEFAULT); + + GtkButton_FWtest = gtk_button_new_with_label (_("Test")); + gtk_widget_ref (GtkButton_FWtest); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWtest", GtkButton_FWtest, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWtest); + GTK_WIDGET_SET_FLAGS (GtkButton_FWtest, GTK_CAN_DEFAULT); + + GtkButton_FWabout = gtk_button_new_with_label (_("About")); + gtk_widget_ref (GtkButton_FWabout); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_FWabout", GtkButton_FWabout, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_FWabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWabout); + GTK_WIDGET_SET_FLAGS (GtkButton_FWabout, GTK_CAN_DEFAULT); + + label30 = gtk_label_new (_("FW")); + gtk_widget_ref (label30); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "label30", label30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label30); + gtk_table_attach (GTK_TABLE (table2), label30, 1, 2, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label30), 0, 0.5); + + GtkLabel_Bios = gtk_label_new (_("Bios")); + gtk_widget_ref (GtkLabel_Bios); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkLabel_Bios", GtkLabel_Bios, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Bios, 1, 2, 12, 13, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Bios), 0, 0.5); + + hbox5 = gtk_hbox_new (FALSE, 14); + gtk_widget_ref (hbox5); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbox5", hbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox5); + gtk_box_pack_start (GTK_BOX (vbox12), hbox5, TRUE, TRUE, 0); + + hbuttonbox11 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox11); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox11", hbuttonbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox11); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox11, FALSE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox11), GTK_BUTTONBOX_START); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox11), 0); + + GtkButton_SelectPluginsDir = gtk_button_new_with_label (_("Select Plugins Dir")); + gtk_widget_ref (GtkButton_SelectPluginsDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectPluginsDir", GtkButton_SelectPluginsDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectPluginsDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectPluginsDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectPluginsDir, GTK_CAN_DEFAULT); + + GtkButton_SelectBiosDir = gtk_button_new_with_label (_("Select Bios Dir")); + gtk_widget_ref (GtkButton_SelectBiosDir); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_SelectBiosDir", GtkButton_SelectBiosDir, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_SelectBiosDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectBiosDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectBiosDir, GTK_CAN_DEFAULT); + + hbuttonbox10 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox10); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "hbuttonbox10", hbuttonbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox10); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox10, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox10), 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (ConfDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_PAD1about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Pad1About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GStest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_GSabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_GsAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SPU2about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Spu2About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9configure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Conf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9test), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9Test), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_DEV9about), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Dev9About), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CDVDabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_CdvdAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_USBabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_UsbAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWconfigure), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWConf), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWtest), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWTest), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_FWabout), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_FWAbout), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectPluginsDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_PluginsPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_SelectBiosDir), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_BiosPath), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnConfConf_Cancel), + NULL); + + return ConfDlg; +} + +GtkWidget* +create_CpuDlg (void) +{ + GtkWidget *CpuDlg; + GtkWidget *vbox8; + GtkWidget *hbox20; + GtkWidget *GtkFrame_Options; + GtkWidget *vbox15; + GtkWidget *GtkCheckButton_PsxOut; + GtkWidget *GtkCheckButton_Patches; + GtkWidget *frame6; + GtkWidget *vbox26; + GtkWidget *GtkCheckButton_Cpu; + GtkWidget *GtkCheckButton_RegCaching; + GtkWidget *GtkCheckButton_VUrec; + GtkWidget *hbuttonbox3; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + CpuDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CpuDlg), "CpuDlg", CpuDlg); + gtk_container_set_border_width (GTK_CONTAINER (CpuDlg), 5); + gtk_window_set_title (GTK_WINDOW (CpuDlg), _("Cpu")); + gtk_window_set_position (GTK_WINDOW (CpuDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (CpuDlg), FALSE, FALSE, FALSE); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox8); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox8", vbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (CpuDlg), vbox8); + + hbox20 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox20); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbox20", hbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox20); + gtk_box_pack_start (GTK_BOX (vbox8), hbox20, TRUE, TRUE, 0); + + GtkFrame_Options = gtk_frame_new (_("Options")); + gtk_widget_ref (GtkFrame_Options); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkFrame_Options", GtkFrame_Options, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkFrame_Options); + gtk_box_pack_start (GTK_BOX (hbox20), GtkFrame_Options, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (GtkFrame_Options), 5); + + vbox15 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox15); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox15", vbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox15); + gtk_container_add (GTK_CONTAINER (GtkFrame_Options), vbox15); + gtk_container_set_border_width (GTK_CONTAINER (vbox15), 5); + + GtkCheckButton_PsxOut = gtk_check_button_new_with_label (_("Enable Console Output")); + gtk_widget_ref (GtkCheckButton_PsxOut); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_PsxOut", GtkCheckButton_PsxOut, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_PsxOut); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_PsxOut, FALSE, FALSE, 0); + + GtkCheckButton_Patches = gtk_check_button_new_with_label (_("Enable Patches")); + gtk_widget_ref (GtkCheckButton_Patches); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Patches", GtkCheckButton_Patches, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Patches); + gtk_box_pack_start (GTK_BOX (vbox15), GtkCheckButton_Patches, FALSE, FALSE, 0); + + frame6 = gtk_frame_new (_("Recompiler Options")); + gtk_widget_ref (frame6); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "frame6", frame6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox8), frame6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame6), 5); + + vbox26 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox26); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "vbox26", vbox26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox26); + gtk_container_add (GTK_CONTAINER (frame6), vbox26); + gtk_container_set_border_width (GTK_CONTAINER (vbox26), 5); + + GtkCheckButton_Cpu = gtk_check_button_new_with_label (_("Disable Recompiler")); + gtk_widget_ref (GtkCheckButton_Cpu); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_Cpu", GtkCheckButton_Cpu, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Cpu); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_Cpu, FALSE, FALSE, 0); + + GtkCheckButton_RegCaching = gtk_check_button_new_with_label (_("Enable Reg Caching")); + gtk_widget_ref (GtkCheckButton_RegCaching); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_RegCaching", GtkCheckButton_RegCaching, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_RegCaching); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_RegCaching, FALSE, FALSE, 0); + + GtkCheckButton_VUrec = gtk_check_button_new_with_label (_("Disable VUs recompilation")); + gtk_widget_ref (GtkCheckButton_VUrec); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkCheckButton_VUrec", GtkCheckButton_VUrec, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_VUrec); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_VUrec, FALSE, FALSE, 0); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "hbuttonbox3", hbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox8), hbuttonbox3, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CpuDlg), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnCpu_Cancel), + NULL); + + return CpuDlg; +} + +GtkWidget* +create_DebugWnd (void) +{ + GtkWidget *DebugWnd; + GtkWidget *vbox16; + GtkWidget *hbox16; + GSList *Debug_group = NULL; + GtkWidget *GtkRadioButton_EE; + GtkWidget *GtkRadioButton_IOP; + GtkWidget *hbox6; + GtkWidget *hbox7; + GtkWidget *scrolledwindow1; + GtkWidget *viewport1; + GtkWidget *GtkList_DisView; + GtkWidget *GtkVScrollbar_VList; + GtkWidget *vbox22; + GtkWidget *vbuttonbox2; + GtkWidget *button52; + GtkWidget *button53; + GtkWidget *button65; + GtkWidget *button64; + GtkWidget *vbuttonbox3; + GtkWidget *button58; + GtkWidget *button59; + GtkWidget *button60; + GtkWidget *button61; + GtkWidget *vbuttonbox1; + GtkWidget *button39; + GtkWidget *button40; + GtkWidget *button41; + GtkWidget *vbuttonbox4; + GtkWidget *button68; + GtkWidget *button69; + GtkWidget *button70; + + DebugWnd = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (DebugWnd), "DebugWnd", DebugWnd); + gtk_container_set_border_width (GTK_CONTAINER (DebugWnd), 5); + gtk_window_set_title (GTK_WINDOW (DebugWnd), _("PCSX2 Debugger")); + gtk_window_set_position (GTK_WINDOW (DebugWnd), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DebugWnd), FALSE, FALSE, FALSE); + + vbox16 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox16", vbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox16); + gtk_container_add (GTK_CONTAINER (DebugWnd), vbox16); + gtk_container_set_border_width (GTK_CONTAINER (vbox16), 5); + + hbox16 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox16); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox16", hbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox16); + gtk_box_pack_start (GTK_BOX (vbox16), hbox16, TRUE, TRUE, 0); + + GtkRadioButton_EE = gtk_radio_button_new_with_label (Debug_group, _("EE Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_EE)); + gtk_widget_ref (GtkRadioButton_EE); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_EE", GtkRadioButton_EE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_EE); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_EE, FALSE, FALSE, 0); + + GtkRadioButton_IOP = gtk_radio_button_new_with_label (Debug_group, _("IOP Debug Mode")); + Debug_group = gtk_radio_button_group (GTK_RADIO_BUTTON (GtkRadioButton_IOP)); + gtk_widget_ref (GtkRadioButton_IOP); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkRadioButton_IOP", GtkRadioButton_IOP, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkRadioButton_IOP); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_IOP, FALSE, FALSE, 0); + + hbox6 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox6); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox6", hbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox16), hbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox6), 5); + + hbox7 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox7); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "hbox7", hbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox7); + gtk_box_pack_start (GTK_BOX (hbox6), hbox7, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_ref (scrolledwindow1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "scrolledwindow1", scrolledwindow1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (scrolledwindow1); + gtk_box_pack_start (GTK_BOX (hbox7), scrolledwindow1, TRUE, TRUE, 0); + gtk_widget_set_usize (scrolledwindow1, 320, -2); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER); + + viewport1 = gtk_viewport_new (NULL, NULL); + gtk_widget_ref (viewport1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "viewport1", viewport1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (viewport1); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); + + GtkList_DisView = gtk_list_new (); + gtk_widget_ref (GtkList_DisView); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkList_DisView", GtkList_DisView, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkList_DisView); + gtk_container_add (GTK_CONTAINER (viewport1), GtkList_DisView); + + GtkVScrollbar_VList = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 412, 1, 20, 2))); + gtk_widget_ref (GtkVScrollbar_VList); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "GtkVScrollbar_VList", GtkVScrollbar_VList, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkVScrollbar_VList); + gtk_box_pack_start (GTK_BOX (hbox7), GtkVScrollbar_VList, TRUE, TRUE, 0); + + vbox22 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox22); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbox22", vbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox22); + gtk_box_pack_start (GTK_BOX (hbox6), vbox22, TRUE, TRUE, 0); + + vbuttonbox2 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox2", vbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox2, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox2), 0); + + button52 = gtk_button_new_with_label (_("Step")); + gtk_widget_ref (button52); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button52", button52, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button52); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button52); + GTK_WIDGET_SET_FLAGS (button52, GTK_CAN_DEFAULT); + + button53 = gtk_button_new_with_label (_("Skip")); + gtk_widget_ref (button53); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button53", button53, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button53); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button53); + GTK_WIDGET_SET_FLAGS (button53, GTK_CAN_DEFAULT); + + button65 = gtk_button_new_with_label (_("Go")); + gtk_widget_ref (button65); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button65", button65, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button65); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button65); + GTK_WIDGET_SET_FLAGS (button65, GTK_CAN_DEFAULT); + + button64 = gtk_button_new_with_label (_("Log On/Off")); + gtk_widget_ref (button64); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button64", button64, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button64); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button64); + GTK_WIDGET_SET_FLAGS (button64, GTK_CAN_DEFAULT); + + vbuttonbox3 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox3", vbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox3, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox3), 0); + + button58 = gtk_button_new_with_label (_("Set PC")); + gtk_widget_ref (button58); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button58", button58, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button58); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button58); + GTK_WIDGET_SET_FLAGS (button58, GTK_CAN_DEFAULT); + + button59 = gtk_button_new_with_label (_("Set BP Addr")); + gtk_widget_ref (button59); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button59", button59, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button59); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button59); + GTK_WIDGET_SET_FLAGS (button59, GTK_CAN_DEFAULT); + + button60 = gtk_button_new_with_label (_("Set BP Count")); + gtk_widget_ref (button60); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button60", button60, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button60); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button60); + GTK_WIDGET_SET_FLAGS (button60, GTK_CAN_DEFAULT); + + button61 = gtk_button_new_with_label (_("Clear BPs")); + gtk_widget_ref (button61); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button61", button61, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button61); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button61); + GTK_WIDGET_SET_FLAGS (button61, GTK_CAN_DEFAULT); + + vbuttonbox1 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox1", vbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (vbuttonbox1), 0); + + button39 = gtk_button_new_with_label (_("Dump code")); + gtk_widget_ref (button39); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button39", button39, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button39); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button39); + GTK_WIDGET_SET_FLAGS (button39, GTK_CAN_DEFAULT); + + button40 = gtk_button_new_with_label (_("Raw Dump")); + gtk_widget_ref (button40); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button40", button40, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button40); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button40); + GTK_WIDGET_SET_FLAGS (button40, GTK_CAN_DEFAULT); + + button41 = gtk_button_new_with_label (_("Close")); + gtk_widget_ref (button41); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button41", button41, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button41); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button41); + GTK_WIDGET_SET_FLAGS (button41, GTK_CAN_DEFAULT); + + vbuttonbox4 = gtk_vbutton_box_new (); + gtk_widget_ref (vbuttonbox4); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "vbuttonbox4", vbuttonbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbuttonbox4); + gtk_box_pack_start (GTK_BOX (hbox6), vbuttonbox4, TRUE, TRUE, 0); + + button68 = gtk_button_new_with_label (_("memWrite32")); + gtk_widget_ref (button68); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button68", button68, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button68); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button68); + GTK_WIDGET_SET_FLAGS (button68, GTK_CAN_DEFAULT); + + button69 = gtk_button_new_with_label (_("button69")); + gtk_widget_ref (button69); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button69", button69, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button69); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button69); + GTK_WIDGET_SET_FLAGS (button69, GTK_CAN_DEFAULT); + + button70 = gtk_button_new_with_label (_("button70")); + gtk_widget_ref (button70); + gtk_object_set_data_full (GTK_OBJECT (DebugWnd), "button70", button70, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button70); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button70); + GTK_WIDGET_SET_FLAGS (button70, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_EE), "toggled", + GTK_SIGNAL_FUNC (OnDebug_EEMode), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkRadioButton_IOP), "toggled", + GTK_SIGNAL_FUNC (OnDebug_IOPMode), + NULL); + gtk_signal_connect (GTK_OBJECT (button52), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Step), + NULL); + gtk_signal_connect (GTK_OBJECT (button53), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Skip), + NULL); + gtk_signal_connect (GTK_OBJECT (button65), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Go), + NULL); + gtk_signal_connect (GTK_OBJECT (button64), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Log), + NULL); + gtk_signal_connect (GTK_OBJECT (button58), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button59), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPA), + NULL); + gtk_signal_connect (GTK_OBJECT (button60), "clicked", + GTK_SIGNAL_FUNC (OnDebug_SetBPC), + NULL); + gtk_signal_connect (GTK_OBJECT (button61), "clicked", + GTK_SIGNAL_FUNC (OnDebug_ClearBPs), + NULL); + gtk_signal_connect (GTK_OBJECT (button39), "clicked", + GTK_SIGNAL_FUNC (OnDebug_DumpCode), + NULL); + gtk_signal_connect (GTK_OBJECT (button40), "clicked", + GTK_SIGNAL_FUNC (OnDebug_RawDump), + NULL); + gtk_signal_connect (GTK_OBJECT (button41), "clicked", + GTK_SIGNAL_FUNC (OnDebug_Close), + NULL); + gtk_signal_connect (GTK_OBJECT (button68), "clicked", + GTK_SIGNAL_FUNC (OnDebug_memWrite32), + NULL); + + return DebugWnd; +} + +GtkWidget* +create_SetPCDlg (void) +{ + GtkWidget *SetPCDlg; + GtkWidget *vbox17; + GtkWidget *label9; + GtkWidget *hbox8; + GtkWidget *label10; + GtkWidget *GtkEntry_dPC; + GtkWidget *hbuttonbox14; + GtkWidget *button42; + GtkWidget *button43; + + SetPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetPCDlg), "SetPCDlg", SetPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetPCDlg), _("SetPCDlg")); + gtk_window_set_position (GTK_WINDOW (SetPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetPCDlg), FALSE, FALSE, FALSE); + + vbox17 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox17); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "vbox17", vbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox17); + gtk_container_add (GTK_CONTAINER (SetPCDlg), vbox17); + gtk_container_set_border_width (GTK_CONTAINER (vbox17), 5); + + label9 = gtk_label_new (_("Set New PC Address (in Hex):")); + gtk_widget_ref (label9); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label9", label9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label9); + gtk_box_pack_start (GTK_BOX (vbox17), label9, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label9), 0.1, 0.5); + + hbox8 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox8); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbox8", hbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox8); + gtk_box_pack_start (GTK_BOX (vbox17), hbox8, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox8), 5); + + label10 = gtk_label_new (_("0x")); + gtk_widget_ref (label10); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "label10", label10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label10); + gtk_box_pack_start (GTK_BOX (hbox8), label10, FALSE, FALSE, 0); + + GtkEntry_dPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_dPC); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "GtkEntry_dPC", GtkEntry_dPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dPC); + gtk_box_pack_start (GTK_BOX (hbox8), GtkEntry_dPC, TRUE, TRUE, 0); + + hbuttonbox14 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox14); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "hbuttonbox14", hbuttonbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox14); + gtk_box_pack_start (GTK_BOX (vbox17), hbuttonbox14, TRUE, TRUE, 0); + + button42 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button42); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button42", button42, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button42); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button42); + GTK_WIDGET_SET_FLAGS (button42, GTK_CAN_DEFAULT); + + button43 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button43); + gtk_object_set_data_full (GTK_OBJECT (SetPCDlg), "button43", button43, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button43); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button43); + GTK_WIDGET_SET_FLAGS (button43, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button42), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button43), "clicked", + GTK_SIGNAL_FUNC (OnSetPC_Cancel), + NULL); + + return SetPCDlg; +} + +GtkWidget* +create_SetBPADlg (void) +{ + GtkWidget *SetBPADlg; + GtkWidget *vbox18; + GtkWidget *label11; + GtkWidget *hbox9; + GtkWidget *label12; + GtkWidget *GtkEntry_BPA; + GtkWidget *hbuttonbox15; + GtkWidget *button44; + GtkWidget *button45; + + SetBPADlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPADlg), "SetBPADlg", SetBPADlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPADlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPADlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPADlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPADlg), FALSE, FALSE, FALSE); + + vbox18 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox18); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "vbox18", vbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox18); + gtk_container_add (GTK_CONTAINER (SetBPADlg), vbox18); + gtk_container_set_border_width (GTK_CONTAINER (vbox18), 5); + + label11 = gtk_label_new (_("Set New BP Address (in Hex):")); + gtk_widget_ref (label11); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label11", label11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox18), label11, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label11), 0.1, 0.5); + + hbox9 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox9); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbox9", hbox9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox9); + gtk_box_pack_start (GTK_BOX (vbox18), hbox9, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox9), 5); + + label12 = gtk_label_new (_("0x")); + gtk_widget_ref (label12); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "label12", label12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label12); + gtk_box_pack_start (GTK_BOX (hbox9), label12, FALSE, FALSE, 0); + + GtkEntry_BPA = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPA); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "GtkEntry_BPA", GtkEntry_BPA, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPA); + gtk_box_pack_start (GTK_BOX (hbox9), GtkEntry_BPA, TRUE, TRUE, 0); + + hbuttonbox15 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox15); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "hbuttonbox15", hbuttonbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox15); + gtk_box_pack_start (GTK_BOX (vbox18), hbuttonbox15, TRUE, TRUE, 0); + + button44 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button44); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button44", button44, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button44); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button44); + GTK_WIDGET_SET_FLAGS (button44, GTK_CAN_DEFAULT); + + button45 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button45); + gtk_object_set_data_full (GTK_OBJECT (SetBPADlg), "button45", button45, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button45); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button45); + GTK_WIDGET_SET_FLAGS (button45, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button44), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button45), "clicked", + GTK_SIGNAL_FUNC (OnSetBPA_Cancel), + NULL); + + return SetBPADlg; +} + +GtkWidget* +create_SetBPCDlg (void) +{ + GtkWidget *SetBPCDlg; + GtkWidget *vbox19; + GtkWidget *label13; + GtkWidget *hbox10; + GtkWidget *label14; + GtkWidget *GtkEntry_BPC; + GtkWidget *hbuttonbox16; + GtkWidget *button46; + GtkWidget *button47; + + SetBPCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (SetBPCDlg), "SetBPCDlg", SetBPCDlg); + gtk_container_set_border_width (GTK_CONTAINER (SetBPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPCDlg), _("SetBreakPoint Addr")); + gtk_window_set_position (GTK_WINDOW (SetBPCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (SetBPCDlg), FALSE, FALSE, FALSE); + + vbox19 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox19); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "vbox19", vbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox19); + gtk_container_add (GTK_CONTAINER (SetBPCDlg), vbox19); + gtk_container_set_border_width (GTK_CONTAINER (vbox19), 5); + + label13 = gtk_label_new (_("Set New BP Count (in Hex):")); + gtk_widget_ref (label13); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label13", label13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label13); + gtk_box_pack_start (GTK_BOX (vbox19), label13, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label13), 0.1, 0.5); + + hbox10 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox10); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbox10", hbox10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox10); + gtk_box_pack_start (GTK_BOX (vbox19), hbox10, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox10), 5); + + label14 = gtk_label_new (_("0x")); + gtk_widget_ref (label14); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "label14", label14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label14); + gtk_box_pack_start (GTK_BOX (hbox10), label14, FALSE, FALSE, 0); + + GtkEntry_BPC = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_BPC); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "GtkEntry_BPC", GtkEntry_BPC, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_BPC); + gtk_box_pack_start (GTK_BOX (hbox10), GtkEntry_BPC, TRUE, TRUE, 0); + + hbuttonbox16 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox16); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "hbuttonbox16", hbuttonbox16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox16); + gtk_box_pack_start (GTK_BOX (vbox19), hbuttonbox16, TRUE, TRUE, 0); + + button46 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button46); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button46", button46, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button46); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button46); + GTK_WIDGET_SET_FLAGS (button46, GTK_CAN_DEFAULT); + + button47 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button47); + gtk_object_set_data_full (GTK_OBJECT (SetBPCDlg), "button47", button47, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button47); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button47); + GTK_WIDGET_SET_FLAGS (button47, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button46), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button47), "clicked", + GTK_SIGNAL_FUNC (OnSetBPC_Cancel), + NULL); + + return SetBPCDlg; +} + +GtkWidget* +create_DumpCDlg (void) +{ + GtkWidget *DumpCDlg; + GtkWidget *vbox20; + GtkWidget *label15; + GtkWidget *hbox11; + GtkWidget *label16; + GtkWidget *GtkEntry_DumpCF; + GtkWidget *hbox12; + GtkWidget *label17; + GtkWidget *GtkEntry_DumpCT; + GtkWidget *label21; + GtkWidget *hbuttonbox17; + GtkWidget *button48; + GtkWidget *button49; + + DumpCDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpCDlg), "DumpCDlg", DumpCDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpCDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpCDlg), _("Dump code")); + gtk_window_set_position (GTK_WINDOW (DumpCDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpCDlg), FALSE, FALSE, FALSE); + + vbox20 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox20); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "vbox20", vbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox20); + gtk_container_add (GTK_CONTAINER (DumpCDlg), vbox20); + gtk_container_set_border_width (GTK_CONTAINER (vbox20), 5); + + label15 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label15); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label15", label15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label15); + gtk_box_pack_start (GTK_BOX (vbox20), label15, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label15), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label15), 0.1, 0.5); + + hbox11 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox11); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox11", hbox11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox11); + gtk_box_pack_start (GTK_BOX (vbox20), hbox11, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox11), 5); + + label16 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label16); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label16", label16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label16); + gtk_box_pack_start (GTK_BOX (hbox11), label16, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label16), TRUE); + + GtkEntry_DumpCF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCF); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCF", GtkEntry_DumpCF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCF); + gtk_box_pack_start (GTK_BOX (hbox11), GtkEntry_DumpCF, TRUE, TRUE, 0); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox12); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbox12", hbox12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox12); + gtk_box_pack_start (GTK_BOX (vbox20), hbox12, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox12), 5); + + label17 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label17", label17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label17); + gtk_box_pack_start (GTK_BOX (hbox12), label17, FALSE, FALSE, 0); + gtk_widget_set_usize (label17, 45, -2); + + GtkEntry_DumpCT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpCT); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "GtkEntry_DumpCT", GtkEntry_DumpCT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpCT); + gtk_box_pack_start (GTK_BOX (hbox12), GtkEntry_DumpCT, TRUE, TRUE, 0); + + label21 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label21); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "label21", label21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label21); + gtk_box_pack_start (GTK_BOX (vbox20), label21, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label21), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label21), 0.1, 0.5); + + hbuttonbox17 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox17); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "hbuttonbox17", hbuttonbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox17); + gtk_box_pack_start (GTK_BOX (vbox20), hbuttonbox17, TRUE, TRUE, 0); + + button48 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button48); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button48", button48, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button48); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button48); + GTK_WIDGET_SET_FLAGS (button48, GTK_CAN_DEFAULT); + + button49 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button49); + gtk_object_set_data_full (GTK_OBJECT (DumpCDlg), "button49", button49, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button49); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button49); + GTK_WIDGET_SET_FLAGS (button49, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button48), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button49), "clicked", + GTK_SIGNAL_FUNC (OnDumpC_Cancel), + NULL); + + return DumpCDlg; +} + +GtkWidget* +create_DumpRDlg (void) +{ + GtkWidget *DumpRDlg; + GtkWidget *vbox21; + GtkWidget *label18; + GtkWidget *hbox13; + GtkWidget *label19; + GtkWidget *GtkEntry_DumpRF; + GtkWidget *hbox14; + GtkWidget *label20; + GtkWidget *GtkEntry_DumpRT; + GtkWidget *label22; + GtkWidget *hbuttonbox18; + GtkWidget *button50; + GtkWidget *button51; + + DumpRDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (DumpRDlg), "DumpRDlg", DumpRDlg); + gtk_container_set_border_width (GTK_CONTAINER (DumpRDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpRDlg), _("Raw Dump")); + gtk_window_set_position (GTK_WINDOW (DumpRDlg), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (DumpRDlg), FALSE, FALSE, FALSE); + + vbox21 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox21); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "vbox21", vbox21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox21); + gtk_container_add (GTK_CONTAINER (DumpRDlg), vbox21); + gtk_container_set_border_width (GTK_CONTAINER (vbox21), 5); + + label18 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_ref (label18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label18", label18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label18); + gtk_box_pack_start (GTK_BOX (vbox21), label18, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label18), 0.1, 0.5); + + hbox13 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox13); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox13", hbox13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox13); + gtk_box_pack_start (GTK_BOX (vbox21), hbox13, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox13), 5); + + label19 = gtk_label_new (_("From 0x")); + gtk_widget_ref (label19); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label19", label19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label19); + gtk_box_pack_start (GTK_BOX (hbox13), label19, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label19), TRUE); + + GtkEntry_DumpRF = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRF); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRF", GtkEntry_DumpRF, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRF); + gtk_box_pack_start (GTK_BOX (hbox13), GtkEntry_DumpRF, TRUE, TRUE, 0); + + hbox14 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox14); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbox14", hbox14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox14); + gtk_box_pack_start (GTK_BOX (vbox21), hbox14, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox14), 5); + + label20 = gtk_label_new (_("To 0x")); + gtk_widget_ref (label20); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label20", label20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label20); + gtk_box_pack_start (GTK_BOX (hbox14), label20, FALSE, FALSE, 0); + gtk_widget_set_usize (label20, 45, -2); + gtk_label_set_justify (GTK_LABEL (label20), GTK_JUSTIFY_LEFT); + + GtkEntry_DumpRT = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_DumpRT); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "GtkEntry_DumpRT", GtkEntry_DumpRT, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_DumpRT); + gtk_box_pack_start (GTK_BOX (hbox14), GtkEntry_DumpRT, TRUE, TRUE, 0); + + label22 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_ref (label22); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "label22", label22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (vbox21), label22, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label22), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label22), 0.1, 0.5); + + hbuttonbox18 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox18); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "hbuttonbox18", hbuttonbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox18); + gtk_box_pack_start (GTK_BOX (vbox21), hbuttonbox18, TRUE, TRUE, 0); + + button50 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button50); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button50", button50, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button50); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button50); + GTK_WIDGET_SET_FLAGS (button50, GTK_CAN_DEFAULT); + + button51 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button51); + gtk_object_set_data_full (GTK_OBJECT (DumpRDlg), "button51", button51, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button51); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button51); + GTK_WIDGET_SET_FLAGS (button51, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button50), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button51), "clicked", + GTK_SIGNAL_FUNC (OnDumpR_Cancel), + NULL); + + return DumpRDlg; +} + +GtkWidget* +create_Logging (void) +{ + GtkWidget *Logging; + GtkWidget *vbox23; + GtkWidget *hbox15; + GtkWidget *frame4; + GtkWidget *table3; + GtkWidget *Log0; + GtkWidget *Log1; + GtkWidget *Log2; + GtkWidget *Log3; + GtkWidget *Log4; + GtkWidget *Log5; + GtkWidget *Log6; + GtkWidget *Log7; + GtkWidget *Log8; + GtkWidget *Log9; + GtkWidget *Log10; + GtkWidget *Log11; + GtkWidget *Log12; + GtkWidget *Log13; + GtkWidget *Log15; + GtkWidget *Log14; + GtkWidget *Log16; + GtkWidget *Log31; + GtkWidget *Log; + GtkWidget *Log30; + GtkWidget *frame5; + GtkWidget *table4; + GtkWidget *Log27; + GtkWidget *Log26; + GtkWidget *Log25; + GtkWidget *Log24; + GtkWidget *Log23; + GtkWidget *Log22; + GtkWidget *Log21; + GtkWidget *Log20; + GtkWidget *Log28; + GtkWidget *hbuttonbox19; + GtkWidget *button66; + GtkWidget *button67; + + Logging = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (Logging), "Logging", Logging); + gtk_container_set_border_width (GTK_CONTAINER (Logging), 5); + gtk_window_set_title (GTK_WINDOW (Logging), _("Logging")); + gtk_window_set_position (GTK_WINDOW (Logging), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (Logging), FALSE, FALSE, FALSE); + + vbox23 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "vbox23", vbox23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox23); + gtk_container_add (GTK_CONTAINER (Logging), vbox23); + gtk_container_set_border_width (GTK_CONTAINER (vbox23), 5); + + hbox15 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbox15", hbox15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox15); + gtk_box_pack_start (GTK_BOX (vbox23), hbox15, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox15), 5); + + frame4 = gtk_frame_new (_("EE Logs")); + gtk_widget_ref (frame4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame4", frame4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (hbox15), frame4, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame4), 5); + + table3 = gtk_table_new (8, 3, FALSE); + gtk_widget_ref (table3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table3", table3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (frame4), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 5); + gtk_table_set_row_spacings (GTK_TABLE (table3), 5); + gtk_table_set_col_spacings (GTK_TABLE (table3), 5); + + Log0 = gtk_check_button_new_with_label (_("Cpu Log")); + gtk_widget_ref (Log0); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log0", Log0, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log0); + gtk_table_attach (GTK_TABLE (table3), Log0, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log1 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log1); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log1", Log1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log1); + gtk_table_attach (GTK_TABLE (table3), Log1, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log2 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log2); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log2", Log2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log2); + gtk_table_attach (GTK_TABLE (table3), Log2, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log3 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log3", Log3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log3); + gtk_table_attach (GTK_TABLE (table3), Log3, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log4 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log4", Log4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log4); + gtk_table_attach (GTK_TABLE (table3), Log4, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log5 = gtk_check_button_new_with_label (_("Elf Log")); + gtk_widget_ref (Log5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log5", Log5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log5); + gtk_table_attach (GTK_TABLE (table3), Log5, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log6 = gtk_check_button_new_with_label (_("Fpu Log")); + gtk_widget_ref (Log6); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log6", Log6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log6); + gtk_table_attach (GTK_TABLE (table3), Log6, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log7 = gtk_check_button_new_with_label (_("MMI Log")); + gtk_widget_ref (Log7); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log7", Log7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log7); + gtk_table_attach (GTK_TABLE (table3), Log7, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log8 = gtk_check_button_new_with_label (_("VU0 Log")); + gtk_widget_ref (Log8); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log8", Log8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log8); + gtk_table_attach (GTK_TABLE (table3), Log8, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log9 = gtk_check_button_new_with_label (_("Cop0 Log")); + gtk_widget_ref (Log9); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log9", Log9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log9); + gtk_table_attach (GTK_TABLE (table3), Log9, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log10 = gtk_check_button_new_with_label (_("Vif Log")); + gtk_widget_ref (Log10); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log10", Log10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log10); + gtk_table_attach (GTK_TABLE (table3), Log10, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log11 = gtk_check_button_new_with_label (_("SPR Log")); + gtk_widget_ref (Log11); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log11", Log11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log11); + gtk_table_attach (GTK_TABLE (table3), Log11, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log12 = gtk_check_button_new_with_label (_("GIF Log")); + gtk_widget_ref (Log12); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log12", Log12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log12); + gtk_table_attach (GTK_TABLE (table3), Log12, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log13 = gtk_check_button_new_with_label (_("Sif Log")); + gtk_widget_ref (Log13); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log13", Log13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log13); + gtk_table_attach (GTK_TABLE (table3), Log13, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log15 = gtk_check_button_new_with_label (_("VU Micro Log")); + gtk_widget_ref (Log15); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log15", Log15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log15); + gtk_table_attach (GTK_TABLE (table3), Log15, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log14 = gtk_check_button_new_with_label (_("IPU Log")); + gtk_widget_ref (Log14); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log14", Log14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log14); + gtk_table_attach (GTK_TABLE (table3), Log14, 1, 2, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log16 = gtk_check_button_new_with_label (_("RPC Log")); + gtk_widget_ref (Log16); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log16", Log16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log16); + gtk_table_attach (GTK_TABLE (table3), Log16, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log31 = gtk_check_button_new_with_label (_("Log to STDOUT")); + gtk_widget_ref (Log31); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log31", Log31, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log31); + gtk_table_attach (GTK_TABLE (table3), Log31, 2, 3, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log = gtk_check_button_new_with_label (_("Log")); + gtk_widget_ref (Log); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log", Log, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log); + gtk_table_attach (GTK_TABLE (table3), Log, 2, 3, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log30 = gtk_check_button_new_with_label (_("SYMs Log")); + gtk_widget_ref (Log30); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log30", Log30, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log30); + gtk_table_attach (GTK_TABLE (table3), Log30, 2, 3, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + frame5 = gtk_frame_new (_("IOP Logs")); + gtk_widget_ref (frame5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "frame5", frame5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (hbox15), frame5, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame5), 5); + + table4 = gtk_table_new (8, 2, FALSE); + gtk_widget_ref (table4); + gtk_object_set_data_full (GTK_OBJECT (Logging), "table4", table4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (frame5), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 5); + gtk_table_set_row_spacings (GTK_TABLE (table4), 5); + gtk_table_set_col_spacings (GTK_TABLE (table4), 5); + + Log27 = gtk_check_button_new_with_label (_("Cdr Log")); + gtk_widget_ref (Log27); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log27", Log27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log27); + gtk_table_attach (GTK_TABLE (table4), Log27, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log26 = gtk_check_button_new_with_label (_("Gte Log")); + gtk_widget_ref (Log26); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log26", Log26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log26); + gtk_table_attach (GTK_TABLE (table4), Log26, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log25 = gtk_check_button_new_with_label (_("Pad Log")); + gtk_widget_ref (Log25); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log25", Log25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log25); + gtk_table_attach (GTK_TABLE (table4), Log25, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log24 = gtk_check_button_new_with_label (_("Dma Log")); + gtk_widget_ref (Log24); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log24", Log24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log24); + gtk_table_attach (GTK_TABLE (table4), Log24, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log23 = gtk_check_button_new_with_label (_("Bios Log")); + gtk_widget_ref (Log23); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log23", Log23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log23); + gtk_table_attach (GTK_TABLE (table4), Log23, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log22 = gtk_check_button_new_with_label (_("Hw Log")); + gtk_widget_ref (Log22); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log22", Log22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log22); + gtk_table_attach (GTK_TABLE (table4), Log22, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log21 = gtk_check_button_new_with_label (_("Mem Log")); + gtk_widget_ref (Log21); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log21", Log21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log21); + gtk_table_attach (GTK_TABLE (table4), Log21, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log20 = gtk_check_button_new_with_label (_("IOP Log")); + gtk_widget_ref (Log20); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log20", Log20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log20); + gtk_table_attach (GTK_TABLE (table4), Log20, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log28 = gtk_check_button_new_with_label (_("GPU Log")); + gtk_widget_ref (Log28); + gtk_object_set_data_full (GTK_OBJECT (Logging), "Log28", Log28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Log28); + gtk_table_attach (GTK_TABLE (table4), Log28, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + hbuttonbox19 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox19); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbuttonbox19", hbuttonbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox19); + gtk_box_pack_start (GTK_BOX (vbox23), hbuttonbox19, TRUE, TRUE, 0); + + button66 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button66); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button66", button66, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button66); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button66); + GTK_WIDGET_SET_FLAGS (button66, GTK_CAN_DEFAULT); + + button67 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button67); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button67", button67, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button67); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button67); + GTK_WIDGET_SET_FLAGS (button67, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button66), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button67), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Cancel), + NULL); + + return Logging; +} + +GtkWidget* +create_CmdLine (void) +{ + GtkWidget *CmdLine; + GtkWidget *vbox24; + GtkWidget *GtkLabel_Text; + GtkWidget *hbox17; + GtkWidget *GtkEntry_dCMDLINE; + GtkWidget *GtkLabel_Note; + GtkWidget *hbuttonbox20; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + CmdLine = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (CmdLine), "CmdLine", CmdLine); + gtk_container_set_border_width (GTK_CONTAINER (CmdLine), 5); + gtk_window_set_title (GTK_WINDOW (CmdLine), _("Program arguments")); + gtk_window_set_position (GTK_WINDOW (CmdLine), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (CmdLine), TRUE); + gtk_window_set_policy (GTK_WINDOW (CmdLine), FALSE, FALSE, FALSE); + + vbox24 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox24); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "vbox24", vbox24, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox24); + gtk_container_add (GTK_CONTAINER (CmdLine), vbox24); + gtk_container_set_border_width (GTK_CONTAINER (vbox24), 5); + + GtkLabel_Text = gtk_label_new (_("Fill in the command line arguments for opened program:")); + gtk_widget_ref (GtkLabel_Text); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Text", GtkLabel_Text, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Text); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Text, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Text), 0.1, 0.5); + + hbox17 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox17); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbox17", hbox17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox17); + gtk_box_pack_start (GTK_BOX (vbox24), hbox17, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox17), 5); + + GtkEntry_dCMDLINE = gtk_entry_new_with_max_length (255); + gtk_widget_ref (GtkEntry_dCMDLINE); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkEntry_dCMDLINE", GtkEntry_dCMDLINE, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_dCMDLINE); + gtk_box_pack_start (GTK_BOX (hbox17), GtkEntry_dCMDLINE, TRUE, TRUE, 0); + gtk_tooltips_set_tip (tooltips, GtkEntry_dCMDLINE, _("If you don't know what to write leave it blank"), NULL); + + GtkLabel_Note = gtk_label_new (_("Note: this is intented for developers only.")); + gtk_widget_ref (GtkLabel_Note); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkLabel_Note", GtkLabel_Note, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkLabel_Note); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Note, FALSE, FALSE, 0); + + hbuttonbox20 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox20); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "hbuttonbox20", hbuttonbox20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox20); + gtk_box_pack_start (GTK_BOX (vbox24), hbuttonbox20, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (GtkButton_Ok); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Ok", GtkButton_Ok, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (GtkButton_Cancel); + gtk_object_set_data_full (GTK_OBJECT (CmdLine), "GtkButton_Cancel", GtkButton_Cancel, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (GtkButton_Ok), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Cancel), "clicked", + GTK_SIGNAL_FUNC (OnArguments_Cancel), + NULL); + + gtk_object_set_data (GTK_OBJECT (CmdLine), "tooltips", tooltips); + + return CmdLine; +} + +GtkWidget* +create_MemWrite32 (void) +{ + GtkWidget *MemWrite32; + GtkWidget *vbox25; + GtkWidget *hbox18; + GtkWidget *label27; + GtkWidget *label25; + GtkWidget *GtkEntry_Mem; + GtkWidget *hbox19; + GtkWidget *label28; + GtkWidget *label26; + GtkWidget *GtkEntry_Data; + GtkWidget *hbuttonbox22; + GtkWidget *button71; + GtkWidget *button72; + + MemWrite32 = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_object_set_data (GTK_OBJECT (MemWrite32), "MemWrite32", MemWrite32); + gtk_container_set_border_width (GTK_CONTAINER (MemWrite32), 5); + gtk_window_set_title (GTK_WINDOW (MemWrite32), _("memWrite32")); + gtk_window_set_position (GTK_WINDOW (MemWrite32), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (MemWrite32), FALSE, FALSE, FALSE); + + vbox25 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "vbox25", vbox25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox25); + gtk_container_add (GTK_CONTAINER (MemWrite32), vbox25); + gtk_container_set_border_width (GTK_CONTAINER (vbox25), 5); + + hbox18 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox18); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox18", hbox18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox18); + gtk_box_pack_start (GTK_BOX (vbox25), hbox18, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + label27 = gtk_label_new (_("Address ")); + gtk_widget_ref (label27); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label27", label27, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label27); + gtk_box_pack_start (GTK_BOX (hbox18), label27, FALSE, FALSE, 0); + + label25 = gtk_label_new (_("0x")); + gtk_widget_ref (label25); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label25", label25, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label25); + gtk_box_pack_start (GTK_BOX (hbox18), label25, FALSE, FALSE, 0); + + GtkEntry_Mem = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Mem); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Mem", GtkEntry_Mem, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Mem); + gtk_box_pack_start (GTK_BOX (hbox18), GtkEntry_Mem, TRUE, TRUE, 0); + + hbox19 = gtk_hbox_new (FALSE, 2); + gtk_widget_ref (hbox19); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbox19", hbox19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox19); + gtk_box_pack_start (GTK_BOX (vbox25), hbox19, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox19), 5); + + label28 = gtk_label_new (_("Data ")); + gtk_widget_ref (label28); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label28", label28, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label28); + gtk_box_pack_start (GTK_BOX (hbox19), label28, FALSE, FALSE, 0); + + label26 = gtk_label_new (_("0x")); + gtk_widget_ref (label26); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "label26", label26, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label26); + gtk_box_pack_start (GTK_BOX (hbox19), label26, FALSE, FALSE, 0); + + GtkEntry_Data = gtk_entry_new_with_max_length (8); + gtk_widget_ref (GtkEntry_Data); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "GtkEntry_Data", GtkEntry_Data, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Data); + gtk_box_pack_start (GTK_BOX (hbox19), GtkEntry_Data, TRUE, TRUE, 0); + + hbuttonbox22 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox22); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "hbuttonbox22", hbuttonbox22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox22); + gtk_box_pack_start (GTK_BOX (vbox25), hbuttonbox22, TRUE, TRUE, 0); + + button71 = gtk_button_new_with_label (_("Ok")); + gtk_widget_ref (button71); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button71", button71, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button71); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button71); + GTK_WIDGET_SET_FLAGS (button71, GTK_CAN_DEFAULT); + + button72 = gtk_button_new_with_label (_("Cancel")); + gtk_widget_ref (button72); + gtk_object_set_data_full (GTK_OBJECT (MemWrite32), "button72", button72, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button72); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button72); + GTK_WIDGET_SET_FLAGS (button72, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button71), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button72), "clicked", + GTK_SIGNAL_FUNC (OnMemWrite32_Cancel), + NULL); + + return MemWrite32; +} + diff --git a/branches/pcsx2_0.9.2/Linux/GladeGui.h b/branches/pcsx2_0.9.2/Linux/GladeGui.h new file mode 100644 index 0000000..111115a --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GladeGui.h @@ -0,0 +1,17 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_MainWindow (void); +GtkWidget* create_AboutDlg (void); +GtkWidget* create_ConfDlg (void); +GtkWidget* create_CpuDlg (void); +GtkWidget* create_DebugWnd (void); +GtkWidget* create_SetPCDlg (void); +GtkWidget* create_SetBPADlg (void); +GtkWidget* create_SetBPCDlg (void); +GtkWidget* create_DumpCDlg (void); +GtkWidget* create_DumpRDlg (void); +GtkWidget* create_Logging (void); +GtkWidget* create_CmdLine (void); +GtkWidget* create_MemWrite32 (void); diff --git a/branches/pcsx2_0.9.2/Linux/GtkGui.c b/branches/pcsx2_0.9.2/Linux/GtkGui.c new file mode 100644 index 0000000..134cc45 --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/GtkGui.c @@ -0,0 +1,1481 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Linux.h" +#include "GladeGui.h" +#include "GladeFuncs.h" + +static int needreset = 1; +int confret; +int confplug=0; + +_PS2EgetLibType PS2EgetLibType = NULL; +_PS2EgetLibVersion2 PS2EgetLibVersion2 = NULL; +_PS2EgetLibName PS2EgetLibName = NULL; + +// Helper Functions +void FindPlugins(); + +// Functions Callbacks +void OnFile_LoadElf(); +void OnFile_Exit(); +void OnEmu_Run(); +void OnEmu_Reset(); +void OnEmu_Arguments(); +void OnConf_Gs(); +void OnConf_Pads(); +void OnConf_Cpu(); +void OnConf_Conf(); +void OnLanguage(GtkMenuItem *menuitem, gpointer user_data); +void OnHelp_Help(); +void OnHelp_About(); + +GtkWidget *Window; +GtkWidget *CmdLine; //2002-09-28 (Florin) +GtkWidget *ConfDlg; +GtkWidget *AboutDlg; +GtkWidget *DebugWnd; +GtkWidget *LogDlg; +GtkWidget *FileSel; + +GtkAccelGroup *AccelGroup; + +typedef struct { + GtkWidget *Combo; + GList *glist; + char plist[255][255]; + int plugins; +} PluginConf; + +PluginConf GSConfS; +PluginConf PAD1ConfS; +PluginConf PAD2ConfS; +PluginConf SPU2ConfS; +PluginConf CDVDConfS; +PluginConf DEV9ConfS; +PluginConf USBConfS; +PluginConf FWConfS; +PluginConf BiosConfS; + +void StartGui() { + GtkWidget *Menu; + GtkWidget *Item; + int i; + + Window = create_MainWindow(); + gtk_window_set_title(GTK_WINDOW(Window), "PCSX2 v" PCSX2_VERSION); + +#ifndef NEW_LOGGING + Item = lookup_widget(Window, "GtkMenuItem_Logging"); + gtk_widget_set_sensitive(Item, FALSE); +#endif + + Item = lookup_widget(Window, "GtkMenuItem_Language"); + Menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(Item), Menu); + + for (i=0; iExecute(); +} + +void OnFile_RunCD() { + efile = 2; + RunExecute(1); +} + +void OnRunElf_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(elfname, File); + gtk_widget_destroy(FileSel); + needreset = 1; + efile = 1; + RunExecute(1); +} + +void OnRunElf_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnFile_LoadElf() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Psx Elf File")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnFile_Exit() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256]; + + // with this the problem with plugins that are linked with the pthread + // library is solved + + dir = opendir(Config.PluginsDir); + if (dir != NULL) { + while ((ent = readdir(dir)) != NULL) { + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) continue; + } + } + + printf(_("PCSX2 Quitting\n")); + if (UseGui) gtk_main_quit(); + SysClose(); + if (UseGui) gtk_exit(0); + else exit(0); +} + +void OnEmu_Run() { + RunExecute(1); +} + +void OnEmu_Reset() { + needreset = 1; +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + GtkWidget *Item; + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "GtkMenuItem_LoadSlot%d", i+1); + Item = lookup_widget(Window, str); + if (Slots[i] == -1) + gtk_widget_set_sensitive(Item, FALSE); + else + gtk_widget_set_sensitive(Item, TRUE); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "sstates/%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %d"), num+1); + else sprintf (Text, _("*PCSX*: Error Saving State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnStates_Load1() { States_Load(0); } +void OnStates_Load2() { States_Load(1); } +void OnStates_Load3() { States_Load(2); } +void OnStates_Load4() { States_Load(3); } +void OnStates_Load5() { States_Load(4); } + +void OnLoadOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + + efile = 2; + RunExecute(0); + + ret = LoadState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Loaded State %s"), str); + else sprintf (Text, _("*PCSX*: Error Loading State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnLoadOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_LoadOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +void OnSaveOther_Ok() { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + RunExecute(0); + + ret = SaveState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %s"), str); + else sprintf (Text, _("*PCSX*: Error Saving State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnSaveOther_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnStates_SaveOther() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +//2002-09-28 (Florin) +void OnArguments_Ok() { + GtkWidget *widgetCmdLine; + char *str; + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + str = gtk_entry_get_text(GTK_ENTRY(widgetCmdLine)); + memcpy(args, str, 256); + + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnArguments_Cancel() { + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnEmu_Arguments() { + GtkWidget *widgetCmdLine; + + CmdLine = create_CmdLine(); + gtk_window_set_title(GTK_WINDOW(CmdLine), _("Program arguments")); + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + gtk_entry_set_text(GTK_ENTRY(widgetCmdLine), args); + //args exported by ElfHeader.h + gtk_widget_show_all(CmdLine); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} +//------------------- + +void OnConf_Gs() { + gtk_widget_set_sensitive(Window, FALSE); + GSconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Pads() { + gtk_widget_set_sensitive(Window, FALSE); + PAD1configure(); + if (strcmp(Config.PAD1, Config.PAD2)) PAD2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Spu2() { + gtk_widget_set_sensitive(Window, FALSE); + SPU2configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Cdvd() { + gtk_widget_set_sensitive(Window, FALSE); + CDVDconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Dev9() { + gtk_widget_set_sensitive(Window, FALSE); + DEV9configure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Usb() { + gtk_widget_set_sensitive(Window, FALSE); + USBconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Fw() { + gtk_widget_set_sensitive(Window, FALSE); + FWconfigure(); + gtk_widget_set_sensitive(Window, TRUE); +} + +GtkWidget *CpuDlg; + +void OnCpu_Ok() { + GtkWidget *Btn; + long t; + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + Config.Regcaching = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + Config.Patch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + t = Config.Cpu; + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (t != Config.Cpu) { + cpuRestartCPU(); + } + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + Config.VUrec = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + Config.PsxOut = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + gtk_widget_destroy(CpuDlg); + + SaveConfig(); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnCpu_Cancel() { + gtk_widget_destroy(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + + +void OnConf_Cpu() { + GtkWidget *Btn; + + CpuDlg = create_CpuDlg(); + gtk_window_set_title(GTK_WINDOW(CpuDlg), _("Configuration")); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Cpu"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Cpu); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_PsxOut"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.PsxOut); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Regcaching); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.VUrec); + + Btn = lookup_widget(CpuDlg, "GtkCheckButton_Patches"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), Config.Patch); + +#ifndef CPU_LOG + Btn = lookup_widget(CpuDlg, "GtkCheckButton_RegCaching"); + gtk_widget_set_sensitive(Btn, FALSE); + Btn = lookup_widget(CpuDlg, "GtkCheckButton_VUrec"); + gtk_widget_set_sensitive(Btn, FALSE); +#endif + + gtk_widget_show_all(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +#define FindComboText(combo,list,conf) \ + if (strlen(conf) > 0) { \ + int i; \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(conf, list[i-2])) { \ + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), list[i-1]); \ + break; \ + } \ + } \ + } + +#define GetComboText(combo,list,conf) \ + { \ + int i; \ + char *tmp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(tmp, list[i-1])) { \ + strcpy(conf, list[i-2]); \ + break; \ + } \ + } \ + } + +void OnConfConf_Ok() { + GetComboText(GSConfS.Combo, GSConfS.plist, Config.GS) + GetComboText(PAD1ConfS.Combo, PAD1ConfS.plist, Config.PAD1); + GetComboText(PAD2ConfS.Combo, PAD2ConfS.plist, Config.PAD2); + GetComboText(SPU2ConfS.Combo, SPU2ConfS.plist, Config.SPU2); + GetComboText(CDVDConfS.Combo, CDVDConfS.plist, Config.CDVD); + GetComboText(DEV9ConfS.Combo, DEV9ConfS.plist, Config.DEV9); + GetComboText(USBConfS.Combo, USBConfS.plist, Config.USB); + GetComboText(FWConfS.Combo, FWConfS.plist, Config.FW); + GetComboText(BiosConfS.Combo, BiosConfS.plist, Config.Bios); + + SaveConfig(); + + if (confplug == 0) { + ReleasePlugins(); + LoadPlugins(); + } + + needreset = 1; + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 1; +} + +void OnConfConf_Cancel() { + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 0; +} + +#define ConfPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) conf(); \ + SysCloseLibrary(drv); + +#define TestPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + int ret = 0; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) { \ + ret = conf(); \ + if (ret == 0) \ + SysMessage(_("This plugin reports that should work correctly")); \ + else SysMessage(_("This plugin reports that should not work correctly")); \ + } \ + SysCloseLibrary(drv); + +void OnConfConf_GsConf() { + ConfPlugin(_GSconfigure, GSConfS, Config.GS, "GSconfigure"); +} + +void OnConfConf_GsTest() { + TestPlugin(_GStest, GSConfS, Config.GS, "GStest"); +} + +void OnConfConf_GsAbout() { + ConfPlugin(_GSabout, GSConfS, Config.GS, "GSabout"); +} + +void OnConfConf_Pad1Conf() { + ConfPlugin(_PADconfigure, PAD1ConfS, Config.PAD1, "PADconfigure"); +} + +void OnConfConf_Pad1Test() { + TestPlugin(_PADtest, PAD1ConfS, Config.PAD1, "PADtest"); +} + +void OnConfConf_Pad1About() { + ConfPlugin(_PADabout, PAD1ConfS, Config.PAD1, "PADabout"); +} + +void OnConfConf_Pad2Conf() { + ConfPlugin(_PADconfigure, PAD2ConfS, Config.PAD2, "PADconfigure"); +} + +void OnConfConf_Pad2Test() { + TestPlugin(_PADtest, PAD2ConfS, Config.PAD2, "PADtest"); +} + +void OnConfConf_Pad2About() { + ConfPlugin(_PADabout, PAD2ConfS, Config.PAD2, "PADabout"); +} + +void OnConfConf_Spu2Conf() { + ConfPlugin(_SPU2configure, SPU2ConfS, Config.SPU2, "SPU2configure"); +} + +void OnConfConf_Spu2Test() { + TestPlugin(_SPU2test, SPU2ConfS, Config.SPU2, "SPU2test"); +} + +void OnConfConf_Spu2About() { + ConfPlugin(_SPU2about, SPU2ConfS, Config.SPU2, "SPU2about"); +} + +void OnConfConf_CdvdConf() { + ConfPlugin(_CDVDconfigure, CDVDConfS, Config.CDVD, "CDVDconfigure"); +} + +void OnConfConf_CdvdTest() { + TestPlugin(_CDVDtest, CDVDConfS, Config.CDVD, "CDVDtest"); +} + +void OnConfConf_CdvdAbout() { + ConfPlugin(_CDVDabout, CDVDConfS, Config.CDVD, "CDVDabout"); +} + +void OnConfConf_Dev9Conf() { + ConfPlugin(_DEV9configure, DEV9ConfS, Config.DEV9, "DEV9configure"); +} + +void OnConfConf_Dev9Test() { + TestPlugin(_DEV9test, DEV9ConfS, Config.DEV9, "DEV9test"); +} + +void OnConfConf_Dev9About() { + ConfPlugin(_DEV9about, DEV9ConfS, Config.DEV9, "DEV9about"); +} + +void OnConfConf_UsbConf() { + ConfPlugin(_USBconfigure, USBConfS, Config.USB, "USBconfigure"); +} + +void OnConfConf_UsbTest() { + TestPlugin(_USBtest, USBConfS, Config.USB, "USBtest"); +} + +void OnConfConf_UsbAbout() { + ConfPlugin(_USBabout, USBConfS, Config.USB, "USBabout"); +} + +void OnConfConf_FWConf() { + ConfPlugin(_FWconfigure, FWConfS, Config.FW, "FWconfigure"); +} + +void OnConfConf_FWTest() { + TestPlugin(_FWtest, FWConfS, Config.FW, "FWtest"); +} + +void OnConfConf_FWAbout() { + ConfPlugin(_FWabout, FWConfS, Config.FW, "FWabout"); +} + +#define ConfCreatePConf(name, type) \ + type##ConfS.Combo = lookup_widget(ConfDlg, "GtkCombo_" name); \ + gtk_combo_set_popdown_strings(GTK_COMBO(type##ConfS.Combo), type##ConfS.glist); \ + FindComboText(type##ConfS.Combo, type##ConfS.plist, Config.type); \ + +void UpdateConfDlg() { + FindPlugins(); + + ConfCreatePConf("Gs", GS); + ConfCreatePConf("Pad1", PAD1); + ConfCreatePConf("Pad2", PAD2); + ConfCreatePConf("Spu2", SPU2); + ConfCreatePConf("Cdvd", CDVD); + ConfCreatePConf("Dev9", DEV9); + ConfCreatePConf("Usb", USB); + ConfCreatePConf("FW", FW); + ConfCreatePConf("Bios", Bios); +} + +void OnPluginsPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.PluginsDir, File); + if (Config.PluginsDir[strlen(Config.PluginsDir)-1] != '/') + strcat(Config.PluginsDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnPluginsPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_PluginsPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Plugins Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnBiosPath_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.BiosDir, File); + if (Config.BiosDir[strlen(Config.BiosDir)-1] != '/') + strcat(Config.BiosDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnBiosPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_BiosPath() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Bios Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnConf_Conf() { + FindPlugins(); + + ConfDlg = create_ConfDlg(); + gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configuration")); + + UpdateConfDlg(); + + gtk_widget_show_all(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +GtkWidget *CmdLine; +GtkWidget *ListDV; +GtkWidget *SetPCDlg, *SetPCEntry; +GtkWidget *SetBPADlg, *SetBPAEntry; +GtkWidget *SetBPCDlg, *SetBPCEntry; +GtkWidget *DumpCDlg, *DumpCTEntry, *DumpCFEntry; +GtkWidget *DumpRDlg, *DumpRTEntry, *DumpRFEntry; +GtkWidget *MemWriteDlg, *MemEntry, *DataEntry; +GtkAdjustment *DebugAdj; +static u32 dPC; +static u32 dBPA = -1; +static u32 dBPC = -1; +static char nullAddr[256]; +int DebugMode; // 0 - EE | 1 - IOP + +#include "R3000A.h" +#include "PsxMem.h" + +void UpdateDebugger() { + GtkWidget *item; + char *str; + int i; + GList *list = NULL; + u32 pc; + + DebugAdj->value = (gfloat)dPC/4; + + gtk_list_clear_items(GTK_LIST(ListDV), 0, 23); + + for (i=0; i<23; i++) { + u32 *mem; + pc = dPC + i*4; + if (DebugMode) { + mem = (u32*)PSXM(pc); + } else + mem = PSM(pc); + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", pc); str = nullAddr; } + else str = disR5900Fasm(*mem, pc); + item = gtk_list_item_new_with_label(str); + gtk_widget_show(item); + list = g_list_append(list, item); + } + gtk_list_append_items(GTK_LIST(ListDV), list); +} + +void OnDebug_Close() { + ClosePlugins(); + gtk_widget_destroy(DebugWnd); + gtk_main_quit(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnDebug_ScrollChange(GtkAdjustment *adj) { + dPC = (u32)adj->value*4; + dPC&= ~0x3; + + UpdateDebugger(); +} + +void OnSetPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetPCEntry)); + + sscanf(str, "%lx", &dPC); + dPC&= ~0x3; + + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetPC_Cancel() { + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetPC() { + SetPCDlg = create_SetPCDlg(); + + SetPCEntry = lookup_widget(SetPCDlg, "GtkEntry_dPC"); + + gtk_widget_show_all(SetPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPA_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPAEntry)); + + sscanf(str, "%lx", &dBPA); + dBPA&= ~0x3; + + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPA_Cancel() { + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPA() { + SetBPADlg = create_SetBPADlg(); + + SetBPAEntry = lookup_widget(SetBPADlg, "GtkEntry_BPA"); + + gtk_widget_show_all(SetBPADlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPC_Ok() { + char *str = gtk_entry_get_text(GTK_ENTRY(SetBPCEntry)); + + sscanf(str, "%lx", &dBPC); + + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPC_Cancel() { + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPC() { + SetBPCDlg = create_SetBPCDlg(); + + SetBPCEntry = lookup_widget(SetBPCDlg, "GtkEntry_BPC"); + + gtk_widget_show_all(SetBPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_ClearBPs() { + dBPA = -1; + dBPC = -1; +} + +void OnDumpC_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpCFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpCTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", addrf); str = nullAddr; } + else str = disR5900Fasm(*mem, addrf); + + fprintf(f, "%s\n", str); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpC_Cancel() { + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_DumpCode() { + DumpCDlg = create_DumpCDlg(); + + DumpCFEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCF"); + DumpCTEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCT"); + + gtk_widget_show_all(DumpCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDumpR_Ok() { + FILE *f; + char *str = gtk_entry_get_text(GTK_ENTRY(DumpRFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = gtk_entry_get_text(GTK_ENTRY(DumpRTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + u32 out; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) out = 0; + else out = *mem; + + fwrite(&out, 4, 1, f); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpR_Cancel() { + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_RawDump() { + DumpRDlg = create_DumpRDlg(); + + DumpRFEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRF"); + DumpRTEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRT"); + + gtk_widget_show_all(DumpRDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_Step() { + Cpu->Step(); + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Skip() { + cpuRegs.pc+= 4; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +int HasBreakPoint(u32 pc) { + if (pc == dBPA) return 1; + if (DebugMode == 0) { + if ((cpuRegs.cycle - 10) <= dBPC && + (cpuRegs.cycle + 10) >= dBPC) return 1; + } else { + if ((psxRegs.cycle - 100) <= dBPC && + (psxRegs.cycle + 100) >= dBPC) return 1; + } + return 0; +} + +void OnDebug_Go() { + for (;;) { + if (HasBreakPoint(cpuRegs.pc)) break; + Cpu->Step(); + } + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Log() { + Log = 1 - Log; +} + +void OnDebug_EEMode() { + DebugMode = 0; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_IOPMode() { + DebugMode = 1; + dPC = psxRegs.pc; + UpdateDebugger(); +} + +void OnMemWrite32_Ok() { + char *mem = gtk_entry_get_text(GTK_ENTRY(MemEntry)); + char *data = gtk_entry_get_text(GTK_ENTRY(DataEntry)); + + printf("memWrite32: %s, %s\n", mem, data); + memWrite32(strtol(mem, (char**)NULL, 0), strtol(data, (char**)NULL, 0)); + + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnMemWrite32_Cancel() { + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_memWrite32() { + MemWriteDlg = create_MemWrite32(); + + MemEntry = lookup_widget(MemWriteDlg, "GtkEntry_Mem"); + DataEntry = lookup_widget(MemWriteDlg, "GtkEntry_Data"); + + gtk_widget_show_all(MemWriteDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); + + UpdateDebugger(); +} + +void OnDebug_Debugger() { + GtkWidget *scroll; + + if (OpenPlugins() == -1) return; + if (needreset) { SysReset(); needreset = 0; } + + if (!efile) + efile=GetPS2ElfName(elfname); + if (efile) + loadElfFile(elfname); + efile=0; + + dPC = cpuRegs.pc; + + DebugWnd = create_DebugWnd(); + + ListDV = lookup_widget(DebugWnd, "GtkList_DisView"); + scroll = lookup_widget(DebugWnd, "GtkVScrollbar_VList"); + + DebugAdj = GTK_RANGE(scroll)->adjustment; + DebugAdj->lower = (gfloat)0x00000000/4; + DebugAdj->upper = (gfloat)0xffffffff/4; + DebugAdj->step_increment = (gfloat)1; + DebugAdj->page_increment = (gfloat)20; + DebugAdj->page_size = (gfloat)23; + + gtk_signal_connect(GTK_OBJECT(DebugAdj), + "value_changed", GTK_SIGNAL_FUNC(OnDebug_ScrollChange), + NULL); + + UpdateDebugger(); + + gtk_widget_show_all(DebugWnd); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +void OnLogging_Ok() { + GtkWidget *Btn; + char str[32]; + int i, ret; + + for (i=0; i<17; i++) { + sprintf(str, "Log%d", i); + Btn = lookup_widget(LogDlg, str); + ret = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (ret) varLog|= 1<d_name); \ + type##ConfS.glist = g_list_append(type##ConfS.glist, type##ConfS.plist[type##ConfS.plugins-1]); \ +} + +void FindPlugins() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256],name[256]; + + GSConfS.plugins = 0; CDVDConfS.plugins = 0; DEV9ConfS.plugins = 0; + PAD1ConfS.plugins = 0; PAD2ConfS.plugins = 0; SPU2ConfS.plugins = 0; + USBConfS.plugins = 0; FWConfS.plugins = 0; BiosConfS.plugins = 0; + GSConfS.glist = NULL; CDVDConfS.glist = NULL; DEV9ConfS.glist = NULL; + PAD1ConfS.glist = NULL; PAD2ConfS.glist = NULL; SPU2ConfS.glist = NULL; + USBConfS.glist = NULL; FWConfS.glist = NULL; BiosConfS.glist = NULL; + + dir = opendir(Config.PluginsDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.PluginsDir); + return; + } + while ((ent = readdir(dir)) != NULL) { + u32 version; + u32 type; + + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) { + printf("%s\n", dlerror()); continue; + } + + PS2EgetLibType = (_PS2EgetLibType) dlsym(Handle, "PS2EgetLibType"); + PS2EgetLibName = (_PS2EgetLibName) dlsym(Handle, "PS2EgetLibName"); + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) dlsym(Handle, "PS2EgetLibVersion2"); + if (PS2EgetLibType == NULL || PS2EgetLibName == NULL || PS2EgetLibVersion2 == NULL) + continue; + type = PS2EgetLibType(); + + if (type & PS2E_LT_GS) { + version = PS2EgetLibVersion2(PS2E_LT_GS); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_GS_VERSION) { + ComboAddPlugin(GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)dlsym(Handle, "PADquery"); + version = PS2EgetLibVersion2(PS2E_LT_PAD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(PAD1); + if (query() & 0x2) + ComboAddPlugin(PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2EgetLibVersion2(PS2E_LT_SPU2); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_SPU2_VERSION) { + ComboAddPlugin(SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2EgetLibVersion2(PS2E_LT_CDVD); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_CDVD_VERSION) { + ComboAddPlugin(CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2EgetLibVersion2(PS2E_LT_DEV9); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_DEV9_VERSION) { + ComboAddPlugin(DEV9); + } else SysPrintf("DEV9Plugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2EgetLibVersion2(PS2E_LT_USB); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_USB_VERSION) { + ComboAddPlugin(USB); + } else SysPrintf("USBPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2EgetLibVersion2(PS2E_LT_FW); + sprintf (name, "%s v%ld.%ld", PS2EgetLibName(), (version>>8)&0xff ,version&0xff); + if ((version >> 16) == PS2E_FW_VERSION) { + ComboAddPlugin(FW); + } else SysPrintf("FWPlugin %s: Version %x != %x\n", plugin, version >> 16, PS2E_FW_VERSION); + } + } + closedir(dir); + + dir = opendir(Config.BiosDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.BiosDir); + return; + } + + while ((ent = readdir(dir)) != NULL) { + struct stat buf; + char description[50]; //2002-09-28 (Florin) + + sprintf (plugin, "%s%s", Config.BiosDir, ent->d_name); + if (stat(plugin, &buf) == -1) continue; +// if (buf.st_size < (1024*512)) continue; + if (buf.st_size > (1024*4096)) continue; //2002-09-28 (Florin) + if (!IsBIOS(ent->d_name, description)) continue;//2002-09-28 (Florin) + + BiosConfS.plugins+=2; + sprintf(description, "%s (%s)", description, ent->d_name); + strcpy(BiosConfS.plist[BiosConfS.plugins-1], description);//2002-09-28 (Florin) modified + strcpy(BiosConfS.plist[BiosConfS.plugins-2], ent->d_name); + BiosConfS.glist = g_list_append(BiosConfS.glist, BiosConfS.plist[BiosConfS.plugins-1]); + } + closedir(dir); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + if (!UseGui) { printf("%s\n",msg); return; } + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), _("PCSX2 Msg")); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label(_("Ok")); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} diff --git a/branches/pcsx2_0.9.2/Linux/Linux.h b/branches/pcsx2_0.9.2/Linux/Linux.h new file mode 100644 index 0000000..cc966bb --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/Linux.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + +#include "Common.h" + +typedef struct { + char lang[256]; +} _langs; + +_langs *langs; +unsigned int langsMax; + +extern int UseGui; +char cfgfile[256]; + +int LoadConfig(); +void SaveConfig(); + +void StartGui(); +void RunGui(); + +int Pcsx2Configure(); + +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); + +#endif /* __LINUX_H__ */ diff --git a/branches/pcsx2_0.9.2/Linux/LnxMain.c b/branches/pcsx2_0.9.2/Linux/LnxMain.c new file mode 100644 index 0000000..ac8e48c --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/LnxMain.c @@ -0,0 +1,327 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "Linux.h" + + +static char Pcsx2Help[] = { + "Pcsx2 " PCSX2_VERSION "\n" + " pcsx2 [options] [file]\n" + "\toptions:\n" + "\t-nogui\t\tDon't open GtkGui\n" + "\t-cfg FILE\tLoads desired configuration file (def:Pcsx2.cfg)\n" + "\t-psxout\t\tEnable psx output\n" + "\t-h -help\tThis help\n" + "\tfile\t\tLoads file\n" +}; + +int UseGui = 1; +int needReset = 1; + + +int main(int argc, char *argv[]) { + char *file = NULL; + char elfname[256]; + char *lang; + int runcd=0; + int efile; + int i; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, "Langs"); + textdomain(PACKAGE); +#endif + + strcpy(cfgfile, "Pcsx2.cfg"); + + for (i=1; iExecute(); + + return 0; +} + +DIR *dir; + +void InitLanguages() { + dir = opendir("Langs"); +} + +char *GetLanguageNext() { + struct dirent *ent; + + if (dir == NULL) return NULL; + for (;;) { + ent = readdir(dir); + if (ent == NULL) return NULL; + + if (!strcmp(ent->d_name, ".")) continue; + if (!strcmp(ent->d_name, "..")) continue; + break; + } + + return ent->d_name; +} + +void CloseLanguages() { + if (dir) closedir(dir); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +int StatesC = 0; + +void KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case XK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Saved State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Saving State %d"), StatesC+1); + GPU_displayText(Text); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F2: + if (StatesC < 4) StatesC++; + else StatesC = 0; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); +/* GPU_freeze(2, (GPUFreeze_t *)&StatesC); + if (ShowPic) { ShowPic = 0; gpuShowPic(); }*/ + break; + case XK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); +/* if (ret == 0) + sprintf(Text, _("*PCSX*: Loaded State %d"), StatesC+1); + else sprintf(Text, _("*PCSX*: Error Loading State %d"), StatesC+1); + GPU_displayText(Text);*/ + break; + case XK_F5: +// if (sio2.hackedRecv==0x1D100) sio2.hackedRecv=0x1100; +// else sio2.hackedRecv=0x1D100; +// SysPrintf("hackedRecv : %x\n", sio2.hackedRecv); + break; + + case XK_F8: + GSmakeSnapshot("snap/"); + break; +#ifdef CPU_LOG + case XK_F9: + Log = 1 - Log; + SysPrintf("Log : %d\n", Log); + break; + case XK_F10: +/* if (varLog & 0x40000000) varLog&=~0x40000000; + else varLog|= 0x40000000; + SysPrintf("varLog %x\n", varLog);*/ + SysPrintf("hack\n"); + psxSu32(0x30) = 0x20000; +// psMu32(0x8010c904) = 0; + break; +#endif + case XK_F11: + SysPrintf("Open\n"); + cdCaseopen = 1; + break; + case XK_F12: + SysPrintf("Close\n"); + cdCaseopen = 0; + break; + case XK_Escape: + signal(SIGINT, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + ClosePlugins(); + if (!UseGui) exit(0); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +int SysInit() { + mkdir("sstates", 0755); + mkdir("memcards", 0755); + + cpuInit(); + while (LoadPlugins() == -1) { + if (Pcsx2Configure() == 0) exit(1); + } + + return 0; +} + +void SysReset() { + cpuReset(); +} + +void SysClose() { + cpuShutdown(); + ReleasePlugins(); + + if (emuLog != NULL) fclose(emuLog); +} + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (Config.PsxOut) { printf("%s", msg); fflush(stdout); } +#ifdef EMU_LOG + fprintf(emuLog, "%s", msg); +#endif +} + +void *SysLoadLibrary(char *lib) { + return dlopen(lib, RTLD_NOW); +} + +void *SysLoadSym(void *lib, char *sym) { + return dlsym(lib, sym); +} + +char *SysLibError() { + return dlerror(); +} + +void SysCloseLibrary(void *lib) { + dlclose(lib); +} + +void SysUpdate() { + KeyEvent(PAD1keyEvent()); + KeyEvent(PAD1keyEvent()); +} + +void SysRunGui() { + RunGui(); +} + +void *SysMmap(uptr base, u32 size) { + return mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +} + +void SysMunmap(uptr base, u32 size) { + munmap((uptr*)base, size); +} + diff --git a/branches/pcsx2_0.9.2/Linux/Makefile.am b/branches/pcsx2_0.9.2/Linux/Makefile.am new file mode 100644 index 0000000..544c741 --- /dev/null +++ b/branches/pcsx2_0.9.2/Linux/Makefile.am @@ -0,0 +1,16 @@ +LIBS = "-L/usr/lib/ $(QTDIR)/lib/ -L/usr/X11R6/lib/ -lqt-mt -lXext -lX11 -lpthread" +INCLUDES = "-I$(QTDIR)/include" + +noinst_PROGRAMS = pcsx2 + +# the application source, library search path, and link libraries +pcsx2_SOURCES = LnxMain.c +pcsx2_LDFLAGS = + +LDADD = ../libpcsx2.a ../DebugTools/libDebugTools.a ../IPU/libIPU.a ../x86/ix86/libix86.a ../pcl/libpcl.a ../RDebug/libRDebug.a ../zlib/libpcsx2zlib.a + +if X86_64 +LDADD += ../x86/ix86-64/libx86-64recomp.a +else +LDADD += ../x86/ix86-32/libx86-32recomp.a +endif diff --git a/branches/pcsx2_0.9.2/MMI.c b/branches/pcsx2_0.9.2/MMI.c new file mode 100644 index 0000000..abf4b46 --- /dev/null +++ b/branches/pcsx2_0.9.2/MMI.c @@ -0,0 +1,1475 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" + + +void MMI() { +#ifdef MMI_LOG + MMI_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_MMIPrintTable[_Funct_](); +} + +void MMI0() { + Int_MMI0PrintTable[_Sa_](); +} + +void MMI1() { + Int_MMI1PrintTable[_Sa_](); +} + +void MMI2() { + Int_MMI2PrintTable[_Sa_](); +} + +void MMI3() { + Int_MMI3PrintTable[_Sa_](); +} + +void MMI_Unknown() { + SysPrintf ("Unknown MMI opcode called\n"); +} + +//*****************MMI OPCODES********************************* + +void MADD() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[0] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +void MADDU() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[0] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +#define _PLZCW(n) { \ + sign = cpuRegs.GPR.r[_Rs_].UL[n] >> 31; \ + for (i=30; i>=0; i--) { \ + if (((cpuRegs.GPR.r[_Rs_].UL[n] >> i) & 0x1) != sign) { \ + break; \ + } \ + } \ + cpuRegs.GPR.r[_Rd_].UL[n] = 30 - i; \ +} + +void PLZCW() { + int i; + u32 sign; + + if (!_Rd_) return; + + _PLZCW (0); + _PLZCW (1); +} + +void MADD1() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[1] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MADDU1() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MFHI1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[1]; +} + +void MFLO1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MTHI1() { + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MTLO1() { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MULT1() { + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[1] = (s64)(s32)(temp & 0xffffffff); + cpuRegs.HI.UD[1] = (s64)(s32)(temp >> 32); + + /* Modified a bit . asadr */ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MULTU1() { + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.UD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void DIV1() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU1() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +#define PMFHL_CLAMP(dst, src) \ + if ((int)src > (int)0x00007fff) dst = 0x7fff; \ + else \ + if ((int)src < (int)0xffff8000) dst = 0x8000; \ + else dst = (u16)src; + +void PMFHL() { + if (!_Rd_) return; + + switch (_Sa_) { + case 0x00: // LW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + break; + + case 0x01: // UW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[3]; + break; + + case 0x02: // SLW + { + u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; + if (TempU64 >= 0x000000007fffffffLL) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffffLL; + } else if (TempU64 <= 0xffffffff80000000LL) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000LL; + } else { + cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0]; + } + + TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; + if (TempU64 >= 0x000000007fffffffLL) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffffLL; + } else if (TempU64 <= 0xffffffff80000000LL) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000LL; + } else { + cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2]; + } + } + break; + + case 0x03: // LH + cpuRegs.GPR.r[_Rd_].US[0] = cpuRegs.LO.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = cpuRegs.LO.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = cpuRegs.HI.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = cpuRegs.HI.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = cpuRegs.LO.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = cpuRegs.LO.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = cpuRegs.HI.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = cpuRegs.HI.US[6]; + break; + + case 0x04: // SH + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[0], cpuRegs.LO.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[1], cpuRegs.LO.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[2], cpuRegs.HI.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[3], cpuRegs.HI.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[4], cpuRegs.LO.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[5], cpuRegs.LO.UL[3]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[6], cpuRegs.HI.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[7], cpuRegs.HI.UL[3]); + break; + } +} + +void PMTHL() { + if (_Sa_ != 0) return; + + cpuRegs.LO.UL[0] = cpuRegs.GPR.r[_Rs_].UL[0]; + cpuRegs.HI.UL[0] = cpuRegs.GPR.r[_Rs_].UL[1]; + cpuRegs.LO.UL[2] = cpuRegs.GPR.r[_Rs_].UL[2]; + cpuRegs.HI.UL[2] = cpuRegs.GPR.r[_Rs_].UL[3]; +} + +#define _PSLLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] << ( _Sa_ & 0xf ); + +void PSLLH() { + if (!_Rd_) return; + + _PSLLH(0); _PSLLH(1); _PSLLH(2); _PSLLH(3); + _PSLLH(4); _PSLLH(5); _PSLLH(6); _PSLLH(7); +} + +#define _PSRLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] >> ( _Sa_ & 0xf ); + +void PSRLH () { + if (!_Rd_) return; + + _PSRLH(0); _PSRLH(1); _PSRLH(2); _PSRLH(3); + _PSRLH(4); _PSRLH(5); _PSRLH(6); _PSRLH(7); +} + +#define _PSRAH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n] >> ( _Sa_ & 0xf ); + +void PSRAH() { + if (!_Rd_) return; + + _PSRAH(0); _PSRAH(1); _PSRAH(2); _PSRAH(3); + _PSRAH(4); _PSRAH(5); _PSRAH(6); _PSRAH(7); +} + +#define _PSLLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] << _Sa_; + +void PSLLW() { + if (!_Rd_) return; + + _PSLLW(0); _PSLLW(1); _PSLLW(2); _PSLLW(3); +} + +#define _PSRLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] >> _Sa_; + +void PSRLW() { + if (!_Rd_) return; + + _PSRLW(0); _PSRLW(1); _PSRLW(2); _PSRLW(3); +} + +#define _PSRAW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n] >> _Sa_; + +void PSRAW() { + if (!_Rd_) return; + + _PSRAW(0); _PSRAW(1); _PSRAW(2); _PSRAW(3); +} + +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +#define _PADDW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] + cpuRegs.GPR.r[_Rt_].UL[n]; + +void PADDW() { + if (!_Rd_) return; + + _PADDW(0); _PADDW(1); _PADDW(2); _PADDW(3); +} + +#define _PSUBW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] - cpuRegs.GPR.r[_Rt_].UL[n]; + +void PSUBW() { + if (!_Rd_) return; + + _PSUBW(0); _PSUBW(1); _PSUBW(2); _PSUBW(3); +} + +#define _PCGTW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCGTW() { + if (!_Rd_) return; + + _PCGTW(0); _PCGTW(1); _PCGTW(2); _PCGTW(3); +} + +#define _PMAXW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].UL[n] : cpuRegs.GPR.r[_Rt_].UL[n]; + +void PMAXW() { + if (!_Rd_) return; + + _PMAXW(0); _PMAXW(1); _PMAXW(2); _PMAXW(3); +} + +#define _PADDH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] + cpuRegs.GPR.r[_Rt_].US[n]; + +void PADDH() { + if (!_Rd_) return; + + _PADDH(0); _PADDH(1); _PADDH(2); _PADDH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PSUBH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] - cpuRegs.GPR.r[_Rt_].US[n]; + +void PSUBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PSUBH(4); _PSUBH(5); _PSUBH(6); _PSUBH(7); +} + +#define _PCGTH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + 0xFFFF : 0x0000; + +void PCGTH() { + if (!_Rd_) return; + + _PCGTH(0); _PCGTH(1); _PCGTH(2); _PCGTH(3); + _PCGTH(4); _PCGTH(5); _PCGTH(6); _PCGTH(7); +} + +#define _PMAXH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMAXH() { + if (!_Rd_) return; + + _PMAXH(0); _PMAXH(1); _PMAXH(2); _PMAXH(3); + _PMAXH(4); _PMAXH(5); _PMAXH(6); _PMAXH(7); +} + +#define _PADDB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] + cpuRegs.GPR.r[_Rt_].SC[n]; + +void PADDB() { + if (!_Rd_) return; + + _PADDB(0); _PADDB(1); _PADDB(2); _PADDB(3); + _PADDB(4); _PADDB(5); _PADDB(6); _PADDB(7); + _PADDB(8); _PADDB(9); _PADDB(10); _PADDB(11); + _PADDB(12); _PADDB(13); _PADDB(14); _PADDB(15); +} + +#define _PSUBB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] - cpuRegs.GPR.r[_Rt_].SC[n]; + +void PSUBB() { + if (!_Rd_) return; + + _PSUBB(0); _PSUBB(1); _PSUBB(2); _PSUBB(3); + _PSUBB(4); _PSUBB(5); _PSUBB(6); _PSUBB(7); + _PSUBB(8); _PSUBB(9); _PSUBB(10); _PSUBB(11); + _PSUBB(12); _PSUBB(13); _PSUBB(14); _PSUBB(15); +} + +#define _PCGTB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].SC[n] > cpuRegs.GPR.r[_Rt_].SC[n]) ? \ + 0xFF : 0x00; + +void PCGTB() { + if (!_Rd_) return; + + _PCGTB(0); _PCGTB(1); _PCGTB(2); _PCGTB(3); + _PCGTB(4); _PCGTB(5); _PCGTB(6); _PCGTB(7); + _PCGTB(8); _PCGTB(9); _PCGTB(10); _PCGTB(11); + _PCGTB(12); _PCGTB(13); _PCGTB(14); _PCGTB(15); +} + +#define _PADDSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].SL[n] + (s64)cpuRegs.GPR.r[_Rt_].SL[n]; \ + if (sTemp64 > 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000LL) && (sTemp64 >= 0x100000000LL)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000LL; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PADDSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PADDSW(0); _PADDSW(1); _PADDSW(2); _PADDSW(3); +} + +#define _PSUBSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 >= 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000LL) && (sTemp64 >= 0x100000000LL)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000LL; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PSUBSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBSW(0); _PSUBSW(1); _PSUBSW(2); _PSUBSW(3); +} + +void PEXTLW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[1]; +} + +void PPACW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[2]; +} + +#define _PADDSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] + (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 > 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = (s16)sTemp32; \ + } + +void PADDSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDSH(0); _PADDSH(1); _PADDSH(2); _PADDSH(3); + _PADDSH(4); _PADDSH(5); _PADDSH(6); _PADDSH(7); +} + +#define _PSUBSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] - (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 >= 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (s16)sTemp32; \ + } + +void PSUBSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBSH(0); _PSUBSH(1); _PSUBSH(2); _PSUBSH(3); + _PSUBSH(4); _PSUBSH(5); _PSUBSH(6); _PSUBSH(7); +} + +void PEXTLH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[1]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[3]; +} + +void PPACH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[4] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PADDSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] + (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 > 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PADDSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PADDSB(0); _PADDSB(1); _PADDSB(2); _PADDSB(3); + _PADDSB(4); _PADDSB(5); _PADDSB(6); _PADDSB(7); + _PADDSB(8); _PADDSB(9); _PADDSB(10); _PADDSB(11); + _PADDSB(12); _PADDSB(13); _PADDSB(14); _PADDSB(15); +} + +#define _PSUBSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] - (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 >= 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PSUBSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBSB(0); _PSUBSB(1); _PSUBSB(2); _PSUBSB(3); + _PSUBSB(4); _PSUBSB(5); _PSUBSB(6); _PSUBSB(7); + _PSUBSB(8); _PSUBSB(9); _PSUBSB(10); _PSUBSB(11); + _PSUBSB(12); _PSUBSB(13); _PSUBSB(14); _PSUBSB(15); +} + +void PEXTLB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[1]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[1]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[3]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[3]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[5]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[5]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[7]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[7]; +} + +void PPACB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rt.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rt.UC[14]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[14]; +} + +#define _PEXT5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16); + +void PEXT5() { + if (!_Rd_) return; + + _PEXT5(0); _PEXT5(1); _PEXT5(2); _PEXT5(3); +} + +#define _PPAC5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000); + +void PPAC5() { + if (!_Rd_) return; + + _PPAC5(0); _PPAC5(1); _PPAC5(2); _PPAC5(3); +} + +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** + +#define _PABSW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]); + +void PABSW() { + if (!_Rd_) return; + + _PABSW(0); _PABSW(1); _PABSW(2); _PABSW(3); +} + +#define _PCEQW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].UL[n] == cpuRegs.GPR.r[_Rt_].UL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCEQW() { + if (!_Rd_) return; + + _PCEQW(0); _PCEQW(1); _PCEQW(2); _PCEQW(3); +} + +#define _PMINW(n) \ + cpuRegs.GPR.r[_Rd_].SL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] < cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].SL[n] : cpuRegs.GPR.r[_Rt_].SL[n]; + +void PMINW() { + if (!_Rd_) return; + + _PMINW(0); _PMINW(1); _PMINW(2); _PMINW(3); +} + +void PADSBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PABSH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]); + +void PABSH() { + if (!_Rd_) return; + + _PABSH(0); _PABSH(1); _PABSH(2); _PABSH(3); + _PABSH(4); _PABSH(5); _PABSH(6); _PABSH(7); +} + +#define _PCEQH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].US[n] == cpuRegs.GPR.r[_Rt_].US[n]) ? 0xFFFF : 0x0000; + +void PCEQH() { + if (!_Rd_) return; + + _PCEQH(0); _PCEQH(1); _PCEQH(2); _PCEQH(3); + _PCEQH(4); _PCEQH(5); _PCEQH(6); _PCEQH(7); +} + +#define _PMINH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] < cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMINH() { + if (!_Rd_) return; + + _PMINH(0); _PMINH(1); _PMINH(2); _PMINH(3); + _PMINH(4); _PMINH(5); _PMINH(6); _PMINH(7); +} + +#define _PCEQB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].UC[n] == \ + cpuRegs.GPR.r[_Rt_].UC[n]) ? 0xFF : 0x00; + +void PCEQB() { + if (!_Rd_) return; + + _PCEQB(0); _PCEQB(1); _PCEQB(2); _PCEQB(3); + _PCEQB(4); _PCEQB(5); _PCEQB(6); _PCEQB(7); + _PCEQB(8); _PCEQB(9); _PCEQB(10); _PCEQB(11); + _PCEQB(12); _PCEQB(13); _PCEQB(14); _PCEQB(15); +} + +#define _PADDUW(n) \ + tmp = (s64)cpuRegs.GPR.r[_Rs_].UL[n] + (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (tmp > 0xffffffff) \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0xffffffff; \ + else cpuRegs.GPR.r[_Rd_].UL[n] = (u32)tmp; + +void PADDUW () { + s64 tmp; + + if (!_Rd_) return; + + _PADDUW(0); _PADDUW(1); _PADDUW(2); _PADDUW(3); +} + +#define _PSUBUW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (u32)sTemp64; \ + } + +void PSUBUW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBUW(0); _PSUBUW(1); _PSUBUW(2); _PSUBUW(3); +} + +void PEXTUW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[3]; +} + +#define _PADDUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] + (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 > 0xFFFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0xFFFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PADDUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDUH(0); _PADDUH(1); _PADDUH(2); _PADDUH(3); + _PADDUH(4); _PADDUH(5); _PADDUH(6); _PADDUH(7); +} + +#define _PSUBUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] - (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PSUBUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBUH(0); _PSUBUH(1); _PSUBUH(2); _PSUBUH(3); + _PSUBUH(4); _PSUBUH(5); _PSUBUH(6); _PSUBUH(7); +} + +void PEXTUH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PADDUB(n) \ + Temp16 = (u16)cpuRegs.GPR.r[_Rs_].UC[n] + (u16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (Temp16 > 0xFF) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0xFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)Temp16; \ + } + +void PADDUB() { + u16 Temp16; + + if (!_Rd_) return; + + _PADDUB(0); _PADDUB(1); _PADDUB(2); _PADDUB(3); + _PADDUB(4); _PADDUB(5); _PADDUB(6); _PADDUB(7); + _PADDUB(8); _PADDUB(9); _PADDUB(10); _PADDUB(11); + _PADDUB(12); _PADDUB(13); _PADDUB(14); _PADDUB(15); +} + +#define _PSUBUB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].UC[n] - (s16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (sTemp16 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)sTemp16; \ + } + +void PSUBUB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBUB(0); _PSUBUB(1); _PSUBUB(2); _PSUBUB(3); + _PSUBUB(4); _PSUBUB(5); _PSUBUB(6); _PSUBUB(7); + _PSUBUB(8); _PSUBUB(9); _PSUBUB(10); _PSUBUB(11); + _PSUBUB(12); _PSUBUB(13); _PSUBUB(14); _PSUBUB(15); +} + +void PEXTUB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[15]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[15]; +} + +void QFSRV() { // JayteeMaster: changed a bit to avoid screw up + GPR_reg Rd; + if (!_Rd_) return; + + if (cpuRegs.sa == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; + } else { + if (cpuRegs.sa < 64) { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } else { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } + } +} + +//********END OF MMI1 OPCODES*********************************** + +//*********MMI2 OPCODES*************************************** + +#define _PMADDW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) + \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMADDW() { + _PMADDW(0, 0); + _PMADDW(1, 2); +} + +void PSLLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (s32)(cpuRegs.GPR.r[_Rt_].UL[2] << + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PSRLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].UL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +#define _PMSUBW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) - \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMSUBW() { + _PMSUBW(0, 0); + _PMSUBW(1, 2); +} + +void PMFHI() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.HI.UD[1]; +} + +void PMFLO() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.LO.UD[1]; +} + +void PINTH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PMULTW(dd, ss) { \ + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ + } \ +} + +void PMULTW() { + _PMULTW(0, 0); + _PMULTW(1, 2); +} + +#define _PDIVW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss]; \ + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss]; \ + } + +void PDIVW() { + _PDIVW(0, 0); + _PDIVW(1, 2); +} + +void PCPYLD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; +} + +void PMADDH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp; */ + + temp = cpuRegs.LO.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp; */ + + temp = cpuRegs.HI.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp; */ + + temp = cpuRegs.LO.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp; */ + + temp = cpuRegs.HI.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } + +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMADH(hlr, dd, n) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[n] = temp; */\ +} + +void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3 + _PHMADH(LO, 0, 0); + _PHMADH(HI, 0, 2); + _PHMADH(LO, 2, 4); + _PHMADH(HI, 2, 6); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PAND() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] & cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PXOR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] ^ cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = cpuRegs.LO.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = cpuRegs.HI.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = cpuRegs.LO.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = cpuRegs.HI.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMSBH(hlr, dd, n, rdd) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[rdd] = temp;*/ \ +} + +void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up + _PHMSBH(LO, 0, 0, 0); + _PHMSBH(HI, 0, 2, 1); + _PHMSBH(LO, 2, 4, 2); + _PHMSBH(HI, 2, 6, 3); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PEXEH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PREVH () { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PMULTH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +#define _PDIVBW(n) \ + cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]); \ + cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]); \ + +void PDIVBW() { + if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return; + + _PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3); +} + +void PEXEW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +void PROT3W() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//*****END OF MMI2 OPCODES*********************************** + +//*************************MMI3 OPCODES************************ + +#define _PMADDUW(dd, ss) { \ + u64 tempu = (u64)((u64)cpuRegs.LO.UL[ss] | ((u64)cpuRegs.HI.UL[ss] << 32)) + \ + ((u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ +} + +void PMADDUW() { + _PMADDUW(0, 0); + _PMADDUW(1, 2); +} + +void PSRAVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].SL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].SL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PMTHI() { + cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PMTLO() { + cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PINTEH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PMULTUW(dd, ss) { \ + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ + } \ +} + +void PMULTUW() { + _PMULTUW(0, 0); + _PMULTUW(1, 2); +} + +#define _PDIVUW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] / (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + cpuRegs.HI.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] % (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + } + +void PDIVUW() { + _PDIVUW(0, 0); + _PDIVUW(1, 2); +} + +void PCPYUD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[1]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void POR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PNOR () { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = ~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); + cpuRegs.GPR.r[_Rd_].UD[1] = ~(cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]); +} + +void PEXCH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PCPYH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PEXCW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//**********************END OF MMI3 OPCODES******************** + +// obs: +// QFSRV not verified + diff --git a/branches/pcsx2_0.9.2/Makefile.am b/branches/pcsx2_0.9.2/Makefile.am new file mode 100644 index 0000000..444825b --- /dev/null +++ b/branches/pcsx2_0.9.2/Makefile.am @@ -0,0 +1,23 @@ +AUTOMAKE_OPTIONS = foreign +INCLUDES = -IDebugTools/ -Ix86/ +noinst_LIBRARIES = libpcsx2.a + +libpcsx2_a_SOURCES = \ +CdRom.c Decode_XA.h Mdec.h PsxBios.h R3000A.c Vif.h \ +CdRom.h EEregs.h memcpy_amd.cpp PsxCommon.h R3000A.h VU0.c \ +CDVD.c Elfheader.c Memory.c PsxCounters.c R5900.c VU0.h \ +CDVD.h Elfheader.h Memory.h PsxCounters.h R5900.h VU0micro.c \ +CDVDiso.c FiFo.c Misc.c PsxDma.c Sif.c VU1micro.c \ +CDVDisodrv.c FPU2.cpp Misc.h PsxDma.h Sifcmd.h VUflags.c \ +CDVDisodrv.h FPU.c MMI.c PsxGPU.c Sif.h VUflags.h \ +CDVDiso.h GS.cpp Patch.c PsxGPU.h Sio.c VU.h \ +CDVDlib.h GS.h Patch.h PsxHw.c Sio.h VUmicro.h \ +Common.h Hw.c Plugins.c PsxHw.h SPR.c VUops.c \ +COP0.c Hw.h Plugins.h PsxInterpreter.c SPR.h VUops.h \ +COP0.h Interpreter.c PS2Edefs.h PsxMem.c System.h \ +Counters.c InterTables.c PS2Etypes.h PsxMem.h Vif.c \ +Counters.h InterTables.h PsxBios2.h PsxSio2.c VifDma.c \ +Decode_XA.c Mdec.c PsxBios.c PsxSio2.h VifDma.h + + +SUBDIRS = . DebugTools IPU pcl RDebug zlib tinyxml x86 Linux \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/Mdec.c b/branches/pcsx2_0.9.2/Mdec.c new file mode 100644 index 0000000..babc7a9 --- /dev/null +++ b/branches/pcsx2_0.9.2/Mdec.c @@ -0,0 +1,521 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This code was based on the FPSE v0.08 Mdec decoder*/ + +#include +#include + +#include "PsxCommon.h" +#include "Mdec.h" + +#define FIXED + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define FIX_1_082392200 (277) +#define FIX_1_414213562 (362) +#define FIX_1_847759065 (473) +#define FIX_2_613125930 (669) + +#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS)) + +#define DEQUANTIZE(coef,quantval) (coef) + +#define DESCALE(x,n) ((x)>>(n)) +#define RANGE(n) (n) + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +static void idct1(int *block) +{ + int val = RANGE(DESCALE(block[0], PASS1_BITS+3)); + int i; + for(i=0;i>16)*(bcr&0xffff); + + if (cmd==0x60000000) { + } else + if (cmd==0x40000001) { + u8 *p = (u8*)PSXM(adr); + iqtab_init(iq_y,p); + iqtab_init(iq_uv,p+64); + } else + if ((cmd&0xf5ff0000)==0x30000000) { + mdec.rl = (u16*)PSXM(adr); + } + else { + } + + HW_DMA0_CHCR &= ~0x01000000; + psxDmaInterrupt(0); +} + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DCTSIZE2*6]; + unsigned short *image; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command); +#endif + + if (chcr!=0x01000200) return; + + size = (bcr>>16)*(bcr&0xffff); + image = (u16*)PSXM(adr); + if (mdec.command&0x08000000) { + for (;size>0;size-=(16*16)/2,image+=(16*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb15(blk,image); + } + } else { + for (;size>0;size-=(24*16)/2,image+=(24*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb24(blk,(u8 *)image); + } + } + + HW_DMA1_CHCR &= ~0x01000000; + psxDmaInterrupt(1); +} + + +#define RUNOF(a) ((a)>>10) +#define VALOF(a) (((int)(a)<<(32-10))>>(32-10)) + +static int zscan[DCTSIZE2] = { + 0 ,1 ,8 ,16,9 ,2 ,3 ,10, + 17,24,32,25,18,11,4 ,5 , + 12,19,26,33,40,48,41,34, + 27,20,13,6 ,7 ,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static int aanscales[DCTSIZE2] = { + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +void iqtab_init(int *iqtab,unsigned char *iq_y) +{ +#define CONST_BITS14 14 +#define IFAST_SCALE_BITS 2 + int i; + + for(i=0;i>(CONST_BITS14-IFAST_SCALE_BITS); + } +} + +#define NOP 0xfe00 +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) { + int i,k,q_scale,rl; + int *iqtab; + + memset (blk, 0, 6*DCTSIZE2*4); + iqtab = iq_uv; + for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i>1) iqtab = iq_y; + + // zigzag transformation + rl = *mdec_rl++; + q_scale = RUNOF(rl); + blk[0] = iqtab[0]*VALOF(rl); + for(k = 0;;) { + rl = *mdec_rl++; + if (rl==NOP) break; + k += RUNOF(rl)+1; // skip level zero-coefficients + if (k > 63) break; + blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16; + } +// blk[0] = (blk[0] * iq_t[0] * 8) / 16; +// for(int j=1;j<64;j++) +// blk[j] = blk[j] * iq_t[j] * q_scale; + + // idct + idct(blk,k+1); + + blk+=DCTSIZE2; + } + return mdec_rl; +} + +#ifdef FIXED +#define MULR(a) ((((int)0x0000059B) * (a)) >> 10) +#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10) +#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10) +#define MULB(a) ((((int)0x00000716) * (a)) >> 10) +#else +#define MULR(a) ((int)((float)1.40200 * (a))) +#define MULG(a) ((int)((float)-0.3437 * (a))) +#define MULG2(a) ((int)((float)-0.7143 * (a))) +#define MULB(a) ((int)((float)1.77200 * (a))) +#endif + +#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) ) +#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff] +/*#define ROUND(c) round(c+128) +int round(int r) { + if (r<0) return 0; + if (r>255) return 255; + return r; +}*/ + +#define RGB15(n, Y) \ + image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B)); + +#define RGB15BW(n, Y) \ + image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y)); + +#define RGB24(n, Y) \ + image[n+2] = ROUND(Y + R); \ + image[n+1] = ROUND(Y + G); \ + image[n+0] = ROUND(Y + B); + +#define RGB24BW(n, Y) \ + image[n+2] = ROUND(Y); \ + image[n+1] = ROUND(Y); \ + image[n+0] = ROUND(Y); + +unsigned char roundtbl[256*3]; + +void round_init(void) { + int i; + for(i=0;i<256;i++) { + roundtbl[i]=0; + roundtbl[i+256]=i; + roundtbl[i+512]=255; + } +} + +void yuv2rgb15(int *blk,unsigned short *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(0, Yblk[0]); + RGB15(1, Yblk[1]); + RGB15(16, Yblk[8]); + RGB15(17, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(8, Yblk[DCTSIZE2+0]); + RGB15(9, Yblk[DCTSIZE2+1]); + RGB15(24, Yblk[DCTSIZE2+8]); + RGB15(25, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Yblk+=2) { + RGB15BW(0, Yblk[0]); + RGB15BW(1, Yblk[1]); + RGB15BW(16, Yblk[8]); + RGB15BW(17, Yblk[9]); + + RGB15BW(8, Yblk[DCTSIZE2+0]); + RGB15BW(9, Yblk[DCTSIZE2+1]); + RGB15BW(24, Yblk[DCTSIZE2+8]); + RGB15BW(25, Yblk[DCTSIZE2+9]); + } + } +} + +void yuv2rgb24(int *blk,unsigned char *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(0, Yblk[0]); + RGB24(1*3, Yblk[1]); + RGB24(16*3, Yblk[8]); + RGB24(17*3, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(8*3, Yblk[DCTSIZE2+0]); + RGB24(9*3, Yblk[DCTSIZE2+1]); + RGB24(24*3, Yblk[DCTSIZE2+8]); + RGB24(25*3, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Yblk+=2) { + RGB24BW(0, Yblk[0]); + RGB24BW(1*3, Yblk[1]); + RGB24BW(16*3, Yblk[8]); + RGB24BW(17*3, Yblk[9]); + + RGB24BW(8*3, Yblk[DCTSIZE2+0]); + RGB24BW(9*3, Yblk[DCTSIZE2+1]); + RGB24BW(24*3, Yblk[DCTSIZE2+8]); + RGB24BW(25*3, Yblk[DCTSIZE2+9]); + } + } +} + +int mdecFreeze(gzFile f, int Mode) { + + gzfreeze(&mdec, sizeof(mdec)); + + gzfreezel(iq_y); + + gzfreezel(iq_uv); + + + + return 0; + +} + + + + diff --git a/branches/pcsx2_0.9.2/Mdec.h b/branches/pcsx2_0.9.2/Mdec.h new file mode 100644 index 0000000..33690c9 --- /dev/null +++ b/branches/pcsx2_0.9.2/Mdec.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MDEC_H__ +#define __MDEC_H__ + +void mdecInit(); +void mdecWrite0(u32 data); +void mdecWrite1(u32 data); +u32 mdecRead0(); +u32 mdecRead1(); +void psxDma0(u32 madr, u32 bcr, u32 chcr); +void psxDma1(u32 madr, u32 bcr, u32 chcr); +int mdecFreeze(gzFile f, int Mode); + +#endif /* __MDEC_H__ */ diff --git a/branches/pcsx2_0.9.2/Memory.c b/branches/pcsx2_0.9.2/Memory.c new file mode 100644 index 0000000..63d2b42 --- /dev/null +++ b/branches/pcsx2_0.9.2/Memory.c @@ -0,0 +1,3056 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + +RAM +--- +0x00100000-0x01ffffff this is the physical address for the ram.its cached there +0x20100000-0x21ffffff uncached +0x30100000-0x31ffffff uncached & acceleretade +0xa0000000-0xa1ffffff MIRROR might...??? +0x80000000-0x81ffffff MIRROR might... ???? + +scratch pad +---------- +0x70000000-0x70003fff scratch pad + +BIOS +---- +0x1FC00000 - 0x1FFFFFFF un-cached +0x9FC00000 - 0x9FFFFFFF cached +0xBFC00000 - 0xBFFFFFFF un-cached +*/ + +////////// +// Rewritten by zerofrog(@gmail.com) to add os virtual memory +////////// + + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#pragma warning(disable:4799) // No EMMS at end of function + +#include +#include +#include +#include + +#include "Common.h" +#include "iR5900.h" +#include "PsxMem.h" +#include "R3000A.h" +#include "PsxHw.h" +#include "VUmicro.h" +#include "GS.h" + +#include + +extern u32 maxrecmem; + +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +//#define FULLTLB +int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode + +u16 ba0R16(u32 mem) { +#ifdef MEM_LOG + //MEM_LOG("ba00000 Memory read16 address %x\n", mem); +#endif + +#ifdef WIN32_VIRTUAL_MEM + if (mem == 0x1a000006) { +#else + if (mem == 0xba000006) { +#endif + static int ba6; + ba6++; + if (ba6 == 3) ba6 = 0; + return ba6; + } + return 0; +} + +///////////////////////////// +// VIRTUAL MEM START +///////////////////////////// +#ifdef WIN32_VIRTUAL_MEM + +//#define VM_RETRANSLATE(mem) (PS2MEM_BASE_+mem) + +// Some games read/write between different addrs but same physical memory +// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog) +u32 VM_RETRANSLATE(u32 mem) +{ + u8* p, *pbase; + if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem + return PS2MEM_BASE_+mem; + + p = (u8*)dmaGetAddrBase(mem), *pbase; + + // do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often + if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) { + return PS2MEM_BASE_+mem; + } + + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); + + return (u32)p; +} + +PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs) +{ + PSMEMORYMAP m; + m.aPFNs = aPFNs; + m.aVFNs = aVFNs; + return m; +} + +// only do vm hack for release +#ifndef PCSX2_DEVBUILD +#define VM_HACK +#endif + +static int XmmExtendedRegOffset = 160; + +// virtual memory blocks + +//#ifdef WIN32_FILE_MAPPING +//HANDLE s_psM, s_psHw, s_psS, s_psxM, s_psVuMem; +//#define PHYSICAL_ALLOC(ptr, size, block) { \ +// block = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, bufSize, #block); +////MapViewOfFileEx +//} +// +//#else + +PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0}; +PSMEMORYMAP *memLUT = NULL; + +#define PHYSICAL_ALLOC(ptr, size, block) { \ + if(SysPhysicalAlloc(size, &block) == -1 ) \ + goto eCleanupAndExit; \ + if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \ + goto eCleanupAndExit; \ +} \ + +//#endif + +#define VIRTUAL_ALLOC(base, size, Protection) { \ + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \ + if( lpMemReserved == NULL || base != lpMemReserved ) \ + { \ + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \ + goto eCleanupAndExit; \ + } \ +} \ + +#define PHYSICAL_FREE(ptr, size, block) { \ + SysVirtualFree(ptr, size); \ + SysPhysicalFree(&block); \ +} \ + +#define VIRTUAL_FREE(ptr, size) { \ + VirtualFree(ptr, size, MEM_DECOMMIT); \ + VirtualFree(ptr, 0, MEM_RELEASE); \ +} \ + +static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 }; + +INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata) +{ + int i; + u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters; + + assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + XmmExtendedRegOffset = 160; + + for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) { + if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) { + XmmExtendedRegOffset = i*4; + break; + } + } + + pexdata->ContextRecord->Eip += 7; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +#if _MSC_VER < 1400 +#define VC_HANDLER _except_handler3 +#else +#define VC_HANDLER _except_handler4 +#endif + +//C's default exception handler +EXCEPTION_DISPOSITION VC_HANDLER( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +char cpp_handler_instructions[5]; +BOOL saved_handler_instructions = FALSE; + +//Exception handler that replaces C's default handler. +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +#pragma pack(1) +typedef struct _jmp_instr +{ + unsigned char jmp; + DWORD offset; +} jmp_instr; +#pragma pack() + +BOOL WriteMemory(void * loc, void * buffer, int size) +{ + DWORD o2; + HANDLE hProcess = GetCurrentProcess(); + + //change the protection of pages containing range of memory + //[loc, loc+size] to READ WRITE + DWORD old_protection; + + BOOL ret; + ret = VirtualProtectEx(hProcess, loc, size, + PAGE_READWRITE, &old_protection); + if(ret == FALSE) + return FALSE; + + ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL); + + //restore old protection + VirtualProtectEx(hProcess, loc, size, old_protection, &o2); + + return (ret == TRUE); +} + +BOOL ReadMemory(void *loc, void *buffer, DWORD size) +{ + HANDLE hProcess = GetCurrentProcess(); + DWORD bytes_read = 0; + BOOL ret; + ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read); + return (ret == TRUE && bytes_read == size); +} + +BOOL install_my_handler() +{ + void * my_hdlr = SysPageFaultExceptionFilter; + void * cpp_hdlr = VC_HANDLER; + + jmp_instr jmp_my_hdlr; + jmp_my_hdlr.jmp = 0xE9; + + //We actually calculate the offset from __CxxFrameHandler+5 + //as the jmp instruction is 5 byte length. + jmp_my_hdlr.offset = (char*)(my_hdlr) - + ((char*)(cpp_hdlr) + 5); + + if(!saved_handler_instructions) + { + if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, + sizeof(cpp_handler_instructions))) + return FALSE; + saved_handler_instructions = TRUE; + } + + return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr)); +} + +BOOL restore_cpp_handler() +{ + if(!saved_handler_instructions) + return FALSE; + else + { + void *loc = VC_HANDLER; + return WriteMemory(loc, cpp_handler_instructions, + sizeof(cpp_handler_instructions)); + } +} + +int memInit() { + + int i; + LPVOID pExtraMem = NULL; + + // release the previous reserved mem + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); + + // allocate all virtual memory + PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY); + PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM); + PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS); + + VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE); + + // reserve the left over 224Mb, don't map + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x02000000 ) + goto eCleanupAndExit; + + // reserve left over psx mem + pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_PSX+0x00200000 ) + goto eCleanupAndExit; + + // reserve gs mem + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x20000000 ) + goto eCleanupAndExit; + + // special addrs mmap + VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE); + + // alloc virtual mappings + memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16); + memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000); + for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]); + for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]); + for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]); + for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]); + + for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]); + + // map to other modes + memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + + if (psxInit() == -1) + goto eCleanupAndExit; + + // figure out xmm reg offset +// __asm movups xmm0, s_testmem +// __try { +// u8* p = 0; +// __asm { +// mov eax, dword ptr [p] +// } +// } +// __except( FindXmmOffsetException( GetExceptionInformation() ) ) { +// } + +//#ifdef WIN32_FILE_MAPPING + if( !install_my_handler() ) { + SysPrintf("Failed to install custom exception handler!\n"); + return -1; + } +//#endif + + return 0; + +eCleanupAndExit: + if( pExtraMem != NULL ) + VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE); + memShutdown(); + return -1; +} + +void memShutdown() +{ + VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE); + + PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_FREE(PS2MEM_ROM, 0x00400000); + VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000); + VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000); + VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000); + PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM); + PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs + + VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000); + VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000); + VIRTUAL_FREE(PS2MEM_GS, 0x00010000); + VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000); + + VIRTUAL_FREE(PS2MEM_B80, 0x00010000); + VIRTUAL_FREE(PS2MEM_BA0, 0x00010000); + + VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE); + + _aligned_free(memLUT); memLUT = NULL; + + // reserve mem + VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { + + PSMEMORYMAP* pmap; + + if( vaddr == paddr ) + return; + + if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) { + pmap = &memLUT[vaddr >> 12]; + + if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs || + pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) { + + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + pmap->aVFNs[0] = 0; + } + + *pmap = memLUT[paddr >> 12]; + } +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + +// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) { +// Cpu->Clear(vaddr&~0xfff, 0x1000/4); +// if( memLUT[vaddr>>12].aVFNs != NULL ) { +// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL ); +// memLUT[vaddr>>12].aVFNs = NULL; +// memLUT[vaddr>>12].aPFNs = NULL; +// } +// } +} + +#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7)) +#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4))) + +//NOTE: A lot of the code reading depends on the registers being less than 8 +// MOV8 88/8A +// MOV16 6689 +// MOV32 89/8B +// SSEMtoR64 120f +// SSERtoM64 130f +// SSEMtoR128 280f +// SSERtoM128 290f + +#define SKIP_WRITE(pexdata) { \ + switch(code&0xff) { \ + case 0x88: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + break; \ + case 0x66: \ + assert( code&0x800000 ); \ + assert( (code&0xffff) == 0x8966 ); \ + ContextRecord->Eip += 7; \ + break; \ + case 0x89: \ + assert( code&0x8000 ); \ + ContextRecord->Eip += 6; \ + break; \ + case 0x0f: /* 130f, 230f*/ \ + assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \ + assert( code&0x800000 ); \ + ContextRecord->Eip += 7; \ + break; \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +#define SKIP_READ(pexdata) { \ + switch(code&0xff) { \ + case 0x8A: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x66: \ + if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \ + else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \ + rd = (code>>(24+3))&7; \ + break; \ + case 0x8B: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x0f: { \ + assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \ + if( !(code&0x800000) ) goto DefaultHandler; \ + ContextRecord->Eip += 7; \ + rd = (code>>(16+3))&7; \ + break; } \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ) +{ + u32 addr; + + C_ASSERT(sizeof(ContextRecord->Eax) == 4); + + // If the exception is not a page fault, exit. + if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + { + // call old handler + EXCEPTION_DISPOSITION d; + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // get bad virtual address + addr = (u32)ExceptionRecord->ExceptionInformation[1]; + + if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) { + PSMEMORYMAP* pmap; + + pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12]; + + if( pmap->aPFNs == NULL ) { + // NOTE: this is a hack because the address is truncated and there's no way + // to tell what it's upper bits are (due to OS limitations). + pmap += 0x80000; + if( pmap->aPFNs == NULL ) { + pmap += 0x20000; + } + //else addr += 0x20000000; + } + + if( pmap->aPFNs != NULL ) { + LPVOID pnewaddr; + DWORD oldaddr = pmap->aVFNs[0]; + + if( pmap->aVFNs[0] != 0 ) { + // delete the current mapping + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL); + } + + assert( pmap->aPFNs[0] != 0 ); + + pmap->aVFNs[0] = addr&~0xfff; + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + // try allocing the virtual mem + pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs) ) + return ExceptionContinueExecution; + + SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n", + addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]); + } + } + else { + // check if vumem + + if( (addr&0xffff4000) == 0x11000000 ) { + // vu0mem + SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL); + + s_psVuMem.aVFNs[1] = addr&~0xfff; + SysMapUserPhysicalPages((void*)addr, 1, &s_psVuMem.aPFNs[1]); + + return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION; + } + } + + { + // call old handler + EXCEPTION_DISPOSITION d; + +#ifdef VM_HACK + u32 code = *(u32*)ExceptionRecord->ExceptionAddress; + u32 rd = 0; + + if( ExceptionRecord->ExceptionInformation[0] ) { + //SKIP_WRITE(ptrs); + // shouldn't be writing + } + else { + SysPrintf("vmhack "); + SKIP_READ(ptrs); + //((u32*)&ContextRecord->Eax)[rd] = 0; + return ExceptionContinueExecution; + } + +DefaultHandler: +#endif + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // continue execution + return EXCEPTION_CONTINUE_EXECUTION; +} + +u8 recMemRead8() +{ + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&~0xffff) ) { + case 0x1f400000: return psxHw4Read8(mem); + case 0x10000000: return hwRead8(mem); + case 0x1f800000: return psxHwRead8(mem); + case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00)); + case 0x14000000: + { + u32 ret = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u8*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +void _eeReadConstMem8(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-3); + assert(0); + } + else { + if( sign ) MOVSX32M8toR(mmreg, mem); + else MOVZX32M8toR(mmreg, mem); + } +} + +void _eeReadConstMem16(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-2); + assert(0); + } + else { + if( sign ) MOVSX32M16toR(mmreg, mem); + else MOVZX32M16toR(mmreg, mem); + } +} + +void _eeReadConstMem32(int mmreg, u32 mem) +{ + if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem); + } + else MOV32MtoR(mmreg, mem); +} + +void _eeReadConstMem128(int mmreg, u32 mem) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQMtoR((mmreg>>4)&0xf, mem+8); + MOVQMtoR(mmreg&0xf, mem); + } + else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem); +} + +void _eeWriteConstMem8(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV8RtoM(mem, mmreg); +} + +void _eeWriteConstMem16(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_CONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV16RtoM(mem, mmreg); +} + +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + switch(op) { + case 0: // and + if( IS_CONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else AND16RtoM(mem, mmreg); + break; + case 1: // and + if( IS_CONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else OR16RtoM(mem, mmreg); + break; + default: assert(0); + } +} + +void _eeWriteConstMem32(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV32RtoM(mem, mmreg); +} + +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op) +{ + switch(op) { + case 0: // and + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_PAND_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PANDMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + AND32RtoM(mem, mmreg&0xf); + } + break; + + case 1: // or + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_POR_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PORMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + OR32RtoM(mem, mmreg&0xf); + } + break; + + case 2: // not and + if( mmreg & MEM_XMMTAG ) { + _deleteEEreg(mmreg>>16, 1); + SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem); + SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + _deleteEEreg(mmreg>>16, 1); + PANDNMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + NOT32R(mmreg&0xf); + AND32RtoM(mem, mmreg&0xf); + } + break; + + default: assert(0); + } +} + +void _eeWriteConstMem64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + } + else assert(0); +} + +void _eeWriteConstMem128(u32 mem, int mmreg) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + MOVQRtoM(mem+8, (mmreg>>4)&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + SetMMXstate(); + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + MOVQRtoM(mem+8, mmreg&0xf); + } + else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf); +} + +void _eeMoveMMREGtoR(x86IntRegType to, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVD32MMXtoR(to, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else if( mmreg != to ) MOV32RtoR(to, mmreg); +} + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign); + case 0x1000: return hwConstRead8(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead8(x86reg, mem, sign); + case 0x1200: return gsConstRead8(x86reg, mem, sign); + case 0x1400: + { + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + return 1; + } + + default: + _eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +u16 recMemRead16() { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( mem>>16 ) { + case 0x1000: return hwRead16(mem); + case 0x1f80: return psxHwRead16(mem); + case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00)); + case 0x1800: return 0; + case 0x1a00: return ba0R16(mem); + case 0x1f90: + case 0x1f00: + return SPU2read(mem); + case 0x1400: + { + u32 ret = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u16*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: return hwConstRead16(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead16(x86reg, mem, sign); + case 0x1200: return gsConstRead16(x86reg, mem, sign); + case 0x1800: + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + case 0x1a00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)ba0R16); + ADD32ItoR(ESP, 4); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f90: + case 0x1f00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1400: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + default: + _eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +__declspec(naked) +u32 recMemRead32() { + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwread + cmp dx, 0x1f80 + je psxhwread + cmp dx, 0x1200 + je gsread + cmp dx, 0x1400 + je devread + + // default read + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +hwread: + { + __asm { + cmp ecx, 0x10002000 + jb counterread + + cmp ecx, 0x1000f260 + je hwsifpresetread + cmp ecx, 0x1000f240 + je hwsifsyncread + + cmp ecx, 0x10003000 + jb hwdefread2 + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + + // ipu +hwdefread2: + push ecx + call ipuRead32 + add esp, 4 + ret + + // sif +hwsifpresetread: + mov eax, 0 + ret +hwsifsyncread: + mov eax, dword ptr [0x1000F240+PS2MEM_BASE_] + or eax, 0xF0000102 + ret + } + +counterread: + { + static u32 mem, index; + + // counters + __asm mov mem, ecx + index = (mem>>11)&3; + + if( (mem&0x7ff) == 0 ) { + __asm { + push index + call rcntRcount + add esp, 4 + and eax, 0xffff + ret + } + } + + index = (u32)&counters[index] + ((mem>>2)&0xc); + + __asm { + mov eax, index + mov eax, dword ptr [eax] + movzx eax, ax + ret + } + } + } + +psxhwread: + __asm { + push ecx + call psxHwRead32 + add esp, 4 + ret + } + +gsread: + __asm { + and ecx, 0xfffff3ff + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +devread: + __asm { + and ecx, 0xfbffffff + push ecx + call DEV9read32 + add esp, 4 + ret + } +} + +int recMemConstRead32(u32 x86reg, u32 mem) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&~0xffff) ) { + case 0x10000000: return hwConstRead32(x86reg, mem); + case 0x1f800000: return psxHwConstRead32(x86reg, mem); + case 0x12000000: return gsConstRead32(x86reg, mem); + case 0x14000000: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read32); + return 1; + + default: + _eeReadConstMem32(x86reg, VM_RETRANSLATE(mem)); + return 0; + } +} + +void recMemRead64(u64 *out) +{ + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: *out = hwRead64(mem); return; + case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return; + case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return; + + default: + //assert(0); + *out = *(u64*)(PS2MEM_BASE+mem); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead64(mem, mmreg); return; + case 0x12000000: gsConstRead64(mem, mmreg); return; + default: + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem)); + else { + MOVQMtoR(mmreg, VM_RETRANSLATE(mem)); + SetMMXstate(); + } + return; + } +} + +void recMemRead128(u64 *out) { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: + hwRead128(mem, out); + return; + case 0x12000000: + out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); + out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8); + return; + case 0x11000000: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + default: + //assert(0); + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead128(u32 mem, int xmmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead128(mem, xmmreg); return; + case 0x12000000: gsConstRead128(mem, xmmreg); return; + default: + _eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem)); + return; + } +} + +void errwrite() +{ + int i, bit, tempeax; + __asm mov i, ecx + __asm mov tempeax, eax + __asm mov bit, edx + SysPrintf("Error write%d at %x\n", bit, i); + assert(0); + __asm mov eax, tempeax + __asm mov ecx, i +} + +void recMemWrite8() +{ + register u32 mem; + register u8 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, al + + switch( mem>>16 ) { + case 0x1f40: psxHw4Write8(mem, value); return; + case 0x1000: hwWrite8(mem, value); return; + case 0x1f80: psxHwWrite8(mem, value); return; + case 0x1200: gsWrite8(mem, value); return; + case 0x1400: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + *(u8*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite8(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0; + case 0x1000: hwConstWrite8(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0; + case 0x1200: gsConstWrite8(mem, mmreg); return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write8); + return 0; + + case 0x1100: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +void recMemWrite16() { + + register u32 mem; + register u16 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, ax + + switch( mem>>16 ) { + case 0x1000: hwWrite16(mem, value); return; + case 0x1f80: psxHwWrite16(mem, value); return; + case 0x1200: gsWrite16(mem, value); return; + case 0x1f90: + case 0x1f00: SPU2write(mem, value); return; + case 0x1400: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + *(u16*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite16(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: hwConstWrite16(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0; + case 0x1200: gsConstWrite16(mem, mmreg); return 0; + case 0x1f90: + case 0x1f00: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write16); + return 0; + + case 0x1100: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +__declspec(naked) +void recMemWrite32() +{ + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1f80 + je psxwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1400 + je devwrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + ret + +hwwrite: + push eax + push ecx + call hwWrite32 + add esp, 8 + ret +psxwrite: + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret +gswrite: + push eax + push ecx + call gsWrite32 + add esp, 8 + ret +devwrite: + and ecx, 0xfbffffff + push eax + push ecx + call DEV9write32 + add esp, 8 + ret +vuwrite: + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite32(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem&0xffff0000 ) { + case 0x10000000: hwConstWrite32(mem, mmreg); return 0; + case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0; + case 0x12000000: gsConstWrite32(mem, mmreg); return 0; + case 0x1f900000: + case 0x1f000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x14000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1100: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) void recMemWrite64() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov edx, 64 + call errwrite + +hwwrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call hwWrite64 + add esp, 12 + ret + +gswrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call gsWrite64 + add esp, 12 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem>>16) ) { + case 0x1000: hwConstWrite64(mem, mmreg); return 0; + case 0x1200: gsConstWrite64(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) +void recMemWrite128() +{ + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + mov edx, 128 + call errwrite + +hwwrite: + + push eax + push ecx + call hwWrite128 + add esp, 8 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov edi, dword ptr [eax+8] + mov eax, dword ptr [eax+12] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + mov dword ptr [ecx+PS2MEM_BASE_+8], edi + mov dword ptr [ecx+PS2MEM_BASE_+12], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + + // default write + //movaps xmm7, qword ptr [eax] + + // removes possible exceptions and saves on remapping memory + // *might* be faster for certain games, no way to tell +// cmp ecx, 0x20000000 +// jb Write128 +// +// // look for better mapping +// mov edx, ecx +// shr edx, 12 +// shl edx, 3 +// add edx, memLUT +// mov edx, dword ptr [edx + 4] +// cmp edx, 0 +// je Write128 +// mov edx, dword ptr [edx] +// cmp edx, 0 +// je Write128 +// and ecx, 0xfff +// movaps qword ptr [ecx+edx], xmm7 +// jmp CheckOverwrite +//Write128: + //movaps qword ptr [ecx+PS2MEM_BASE_], xmm7 + ret + +gswrite: + sub esp, 8 + movlps xmm7, qword ptr [eax] + movlps qword ptr [esp], xmm7 + push ecx + call gsWrite64 + + // call again for upper 8 bytes + movlps xmm7, qword ptr [eax+8] + movlps qword ptr [esp+4], xmm7 + add [esp], 8 + call gsWrite64 + add esp, 12 + ret + } +} + +int recMemConstWrite128(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstWrite128(mem, mmreg); return 0; + case 0x12000000: gsConstWrite128(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +int memRead8 (u32 mem, u8 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = psxHw4Read8(mem); return 0; + case 0x10000000: *out = hwRead8(mem); return 0; + case 0x1f800000: *out = psxHwRead8(mem); return 0; + case 0x12000000: *out = gsRead8(mem); return 0; + case 0x14000000: + *out = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (s8)hwRead8(mem); return 0; + case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (s8)gsRead8(mem); return 0; + case 0x14000000: + *out = (s8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (u8)hwRead8(mem); return 0; + case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (u8)gsRead8(mem); return 0; + case 0x14000000: + *out = (u8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead16(mem); return 0; + case 0x1f800000: *out = psxHwRead16(mem); return 0; + case 0x12000000: *out = gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = SPU2read(mem); return 0; + break; + case 0x14000000: + *out = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s16)hwRead16(mem); return 0; + case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0; + case 0x12000000: *out = (s16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (s16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (s16)SPU2read(mem); return 0; + break; + case 0x14000000: + *out = (s16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u16)hwRead16(mem ); return 0; + case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0; + case 0x12000000: *out = (u16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (u16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (u16)SPU2read(mem ); return 0; + break; + case 0x14000000: + *out = (u16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead32(mem); return 0; + case 0x1f800000: *out = psxHwRead32(mem); return 0; + case 0x12000000: *out = gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s32)hwRead32(mem); return 0; + case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (s32)gsRead32(mem); return 0; + case 0x14000000: + *out = (s32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u32)hwRead32(mem); return 0; + case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (u32)gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead64(mem); return 0; + case 0x12000000: *out = gsRead64(mem); return 0; + + default: + *out = *(u64*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: + hwRead128(mem, out); + return 0; + case 0x12000000: + out[0] = gsRead64(mem); + out[1] = gsRead64(mem + 8); + return 0; + + default: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: psxHw4Write8(mem, value); return; + case 0x10000000: hwWrite8(mem, value); return; + case 0x1f800000: psxHwWrite8(mem, value); return; + case 0x12000000: gsWrite8(mem, value); return; + case 0x14000000: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + + default: + *(u8*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite16(mem, value); return; + case 0x1f800000: psxHwWrite16(mem, value); return; + case 0x12000000: gsWrite16(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + + default: + *(u16*)(PS2MEM_BASE+mem) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite32(mem, value); return; + case 0x1f800000: psxHwWrite32(mem, value); return; + case 0x12000000: gsWrite32(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write32(mem & ~0x4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value); + return; + + default: + *(u32*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite64(mem, value); return; + case 0x12000000: gsWrite64(mem, value); return; + + default: + *(u64*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite128(mem, value); return; + case 0x12000000: + gsWrite64(mem, value[0]); + gsWrite64(mem + 8, value[1]); + return; + + default: + *(u64*)(PS2MEM_BASE+mem) = value[0]; + *(u64*)(PS2MEM_BASE+mem+8) = value[1]; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +#else + +u8 *psM; //32mb Main Ram +u8 *psR; //4mb rom area +u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +u8 *psR2; // 0x00080000 +u8 *psER; // 0x001C0000 +u8 *psS; //0.015 mb, scratch pad + +uptr *memLUTR; +uptr *memLUTW; +uptr *memLUTRK; +uptr *memLUTWK; +uptr *memLUTRU; +uptr *memLUTWU; + +///////////////////////////// +// REGULAR MEM START +///////////////////////////// + +void memMapMem(u32 base) { + int i; + + for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure) + + for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure) +} + +void memMapKernelMem() { + memMapMem(0xa0000); + memMapMem(0x80000); + memMapMem(0x00000); +} + +void memMapSupervisorMem() { +} + +void memMapUserMem() { +} + +int memInit() { + int i; + + memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + + psM = (u8*)_aligned_malloc(0x02000010, 16); + psR = (u8*)_aligned_malloc(0x00400010, 16); + psR1 = (u8*)_aligned_malloc(0x00080010, 16); + psR2 = (u8*)_aligned_malloc(0x00080010, 16); + psER = (u8*)_aligned_malloc(0x001C0010, 16); + psS = (u8*)_aligned_malloc(0x00004010, 16); + if (memLUTRK == NULL || memLUTWK == NULL || + memLUTRU == NULL || memLUTWU == NULL || + psM == NULL || psR == NULL || psR1 == NULL || + psR2 == NULL || psER == NULL || psS == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(memLUTRK, 0, 0x100000 * 4); + memset(memLUTWK, 0, 0x100000 * 4); + memset(memLUTRU, 0, 0x100000 * 4); + memset(memLUTWU, 0, 0x100000 * 4); + + memset(psM, 0, 0x02000010); + memset(psR, 0, 0x00400010); + memset(psR1, 0, 0x00080010); + memset(psR2, 0, 0x00080010); + memset(psER, 0, 0x001C0010); + memset(psS, 0, 0x00004010); + + if (psxInit() == -1) return -1; + + for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12]; + + for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12]; + + + memMapKernelMem(); + memMapSupervisorMem(); + memMapUserMem(); + + memSetKernelMode(); + + return 0; +} + +void memShutdown() { + FREE(psM); + FREE(psR); + FREE(psR1); + FREE(psR2); + FREE(psER); + FREE(psS); + FREE(memLUTRK); + FREE(memLUTWK); + FREE(memLUTRU); + FREE(memLUTWU); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { +// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr); + + memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12]; + + memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12]; +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + memLUTRU[vaddr >> 12] = 0; + memLUTWU[vaddr >> 12] = 0; + +#ifdef FULLTLB + memLUTRK[vaddr >> 12] = 0; + memLUTWK[vaddr >> 12] = 0; +#endif +} + +int memRead8 (u32 mem, u8 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = ba0R16(mem); return 0; + case 6: // gsm + *out = gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (s16)ba0R16(mem); return 0; + case 6: // gsm + *out = (s16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (s16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (u16)ba0R16(mem); return 0; + case 6: // gsm + *out = (u16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (u16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + assert( (int)p < 8 ); + + switch ((int)p) { + case 1: // hwm + *out = hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(s32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (s32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = (u32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u8 *tmp = readCache(mem); + *out = *(u64*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u64*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)p) { + case 1: // hwm + *out = hwRead64(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead64(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + u64 *tmp = (u64*)readCache(mem); + out[0] = tmp[0]; + out[1] = tmp[1]; + return 0; + } +#endif + p+= mem & 0xfff; + out[0] = ((u64*)p)[0]; + out[1] = ((u64*)p)[1]; + return 0; + } + + switch ((int)p) { + case 1: // hwm + hwRead128(mem & ~0xa0000000, out); return 0; + case 6: // gsm + out[0] = gsRead64((mem ) & ~0xa0000000); + out[1] = gsRead64((mem+8) & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache8(mem, value); + return; + } +#endif + *(u8 *)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&(~3)); +// PSXREC_CLEARM(mem & 0x1ffffc); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite8(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite8(mem & ~0xa0000000, value); return; + case 3: // psh4 + psxHw4Write8(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite8(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write8(mem & ~0xa4000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value); + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache16(mem, value); + return; + } +#endif + *(u16*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~1); + //PSXREC_CLEARM(mem & 0x1ffffe); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite16(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite16(mem & ~0xa0000000, value); return; + case 5: // ba0 +#ifdef MEM_LOG + MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value); +#endif + return; + case 6: // gsm + gsWrite16(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write16(mem & ~0xa4000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value); + return; + case 8: // spu2 + SPU2write(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + char *p; + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache32(mem, value); + return; + } +#endif + *(u32*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); +// PSXREC_CLEARM(mem & 0x1fffff); + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite32(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite32(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite32(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write32(mem & ~0xa4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value); + return; + } +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { + #ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache64(mem, value); + return; + } + #endif + /* __asm __volatile ( + "movq %1, %%mm0\n" + "movq %%mm0, %0\n" + "emms\n" + : "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value) + );*/ + *(u64*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + + + switch ((int)p) { + case 1: // hwm + hwWrite64(mem & ~0xa0000000, value); + return; + case 6: // gsm + gsWrite64(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((int)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0) { + writeCache128(mem, value); + return; + } +#endif + p+= mem & 0xfff; + ((u64*)p)[0] = value[0]; + ((u64*)p)[1] = value[1]; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + +/* PSXREC_CLEARM((mem) & 0x1fffff); + PSXREC_CLEARM((mem+4) & 0x1fffff); + PSXREC_CLEARM((mem+8) & 0x1fffff); + PSXREC_CLEARM((mem+12) & 0x1fffff);*/ + } + return; + } + + switch ((int)p) { + case 1: // hwm + hwWrite128(mem & ~0xa0000000, value); + return; + case 6: // gsm + mem &= ~0xa0000000; + gsWrite64(mem, value[0]); + gsWrite64(mem+8, value[1]); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + + +#endif // WIN32_VIRTUAL_MEM + +void loadBiosRom(char *ext, u8 *dest) { + struct stat buf; + char Bios1[256]; + char Bios[256]; + FILE *fp; + char *ptr; + int i; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + sprintf(Bios1, "%s.%s", Bios, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s", Bios); + ptr = Bios1; i = strlen(Bios1); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = 0; + strcat(Bios1, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + SysPrintf("\n\n\n"); + SysPrintf("**************\n"); + SysPrintf("%s NOT FOUND\n", ext); + SysPrintf("**************\n\n\n"); +} + +void memReset() { + struct stat buf; + char Bios[256]; + FILE *fp; + +#ifdef WIN32_VIRTUAL_MEM + DWORD OldProtect; + memset(PS2MEM_BASE, 0, 0x02000000); + memset(PS2MEM_SCRATCH, 0, 0x00004000); +#else + memset(psM, 0, 0x02000000); + memset(psS, 0, 0x00004000); +#endif + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + if (stat(Bios, &buf) == -1) { + SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios); + return; + } + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + fp = fopen(Bios, "rb"); + fread(PS2MEM_ROM, 1, buf.st_size, fp); + fclose(fp); + + BiosVersion = GetBiosVersion(); + SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff); + + //injectIRX("host.irx"); //not fully tested; still buggy + + // reset memLUT + + loadBiosRom("rom1", PS2MEM_ROM1); + loadBiosRom("rom2", PS2MEM_ROM2); + loadBiosRom("erom", PS2MEM_EROM); + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif +} + +void memSetKernelMode() { +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRK; + memLUTW = memLUTWK; +#endif + MemMode = 0; +} + +void memSetSupervisorMode() { +} + +void memSetUserMode() { +#ifdef FULLTLB +#ifndef WIN32_VIRTUAL_MEM + memLUTR = memLUTRU; + memLUTW = memLUTWU; +#endif + MemMode = 2; +#endif +} diff --git a/branches/pcsx2_0.9.2/Memory.h b/branches/pcsx2_0.9.2/Memory.h new file mode 100644 index 0000000..36ed71f --- /dev/null +++ b/branches/pcsx2_0.9.2/Memory.h @@ -0,0 +1,263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +////////// +// Rewritten by zerofrog to add os virtual memory +////////// + +#ifndef __MEMORY_H__ +#define __MEMORY_H__ + +//#define ENABLECACHE + +#ifdef WIN32_VIRTUAL_MEM + +typedef struct _PSMEMORYMAP +{ + ULONG_PTR* aPFNs, *aVFNs; +} PSMEMORYMAP; + +#define TRANSFORM_ADDR(memaddr) ( ((u32)(memaddr)>=0x40000000) ? ((memaddr)&~0xa0000000) : (memaddr) ) + +//new memory model +#define PS2MEM_BASE_ 0x18000000 +#define PS2MEM_PSX_ (PS2MEM_BASE_+0x1c000000) + +#define PS2MEM_BASE ((u8*)PS2MEM_BASE_) +#define PS2MEM_HW ((u8*)((u32)PS2MEM_BASE+0x10000000)) +#define PS2MEM_ROM ((u8*)((u32)PS2MEM_BASE+0x1fc00000)) +#define PS2MEM_ROM1 ((u8*)((u32)PS2MEM_BASE+0x1e000000)) +#define PS2MEM_ROM2 ((u8*)((u32)PS2MEM_BASE+0x1e400000)) +#define PS2MEM_EROM ((u8*)((u32)PS2MEM_BASE+0x1e040000)) +#define PS2MEM_PSX ((u8*)PS2MEM_PSX_) +#define PS2MEM_SCRATCH ((u8*)((u32)PS2MEM_BASE+0x50000000)) +#define PS2MEM_VU0MICRO ((u8*)((u32)PS2MEM_BASE+0x11000000)) +#define PS2MEM_VU0MEM ((u8*)((u32)PS2MEM_BASE+0x11004000)) +#define PS2MEM_VU1MICRO ((u8*)((u32)PS2MEM_BASE+0x11008000)) +#define PS2MEM_VU1MEM ((u8*)((u32)PS2MEM_BASE+0x1100c000)) + +// function for mapping memory +#define PS2MEM_PSXHW ((u8*)((u32)PS2MEM_BASE+0x1f800000)) +#define PS2MEM_PSXHW4 ((u8*)((u32)PS2MEM_BASE+0x1f400000)) +#define PS2MEM_GS ((u8*)((u32)PS2MEM_BASE+0x12000000)) +#define PS2MEM_DEV9 ((u8*)((u32)PS2MEM_BASE+0x14000000)) +#define PS2MEM_SPU2 ((u8*)((u32)PS2MEM_BASE+0x1f900000)) +#define PS2MEM_SPU2_ ((u8*)((u32)PS2MEM_BASE+0x1f000000)) // ? +#define PS2MEM_B80 ((u8*)((u32)PS2MEM_BASE+0x18000000)) +#define PS2MEM_BA0 ((u8*)((u32)PS2MEM_BASE+0x1a000000)) + +#define PSM(mem) (PS2MEM_BASE + TRANSFORM_ADDR(mem)) + +#else + +extern u8 *psM; //32mb Main Ram +extern u8 *psR; //4mb rom area +extern u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +extern u8 *psR2; // 0x00080000 +extern u8 *psER; // 0x001C0000 +extern u8 *psS; //0.015 mb, scratch pad + +#define PS2MEM_BASE psM +#define PS2MEM_HW psH +#define PS2MEM_ROM psR +#define PS2MEM_ROM1 psR1 +#define PS2MEM_ROM2 psR2 +#define PS2MEM_EROM psER +#define PS2MEM_SCRATCH psS + +extern u8 g_RealGSMem[0x2000]; +#define PS2MEM_GS g_RealGSMem + +//#define _PSM(mem) (memLUTR[(mem) >> 12] == 0 ? NULL : (void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define PSM(mem) ((void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define FREE(ptr) _aligned_free(ptr) + +extern uptr *memLUTR; +extern uptr *memLUTW; +extern uptr *memLUTRK; +extern uptr *memLUTWK; +extern uptr *memLUTRU; +extern uptr *memLUTWU; + +#endif + +#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs64(mem) (*(s64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu8(mem) (*(u8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu16(mem) (*(u16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu32(mem) (*(u32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu64(mem) (*(u64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) + +#define psRs8(mem) (*(s8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs16(mem) (*(s16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs32(mem) (*(s32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs64(mem) (*(s64*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu8(mem) (*(u8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu16(mem) (*(u16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu32(mem) (*(u32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu64(mem) (*(u64*)&PS2MEM_ROM[(mem) & 0x3fffff]) + +#define psR1s8(mem) (*(s8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s16(mem) (*(s16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s32(mem) (*(s32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s64(mem) (*(s64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u8(mem) (*(u8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u16(mem) (*(u16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u32(mem) (*(u32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u64(mem) (*(u64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) + +#define psR2s8(mem) (*(s8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s16(mem) (*(s16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s32(mem) (*(s32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s64(mem) (*(s64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u8(mem) (*(u8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u16(mem) (*(u16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u32(mem) (*(u32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u64(mem) (*(u64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) + +#define psERs8(mem) (*(s8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs16(mem) (*(s16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs32(mem) (*(s32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs64(mem) (*(s64*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu8(mem) (*(u8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu16(mem) (*(u16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff]) + +#define psSs8(mem) (*(s8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs16(mem) (*(s16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs32(mem) (*(s32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs64(mem) (*(s64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu8(mem) (*(u8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu16(mem) (*(u16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) + +#define PSMs8(mem) (*(s8 *)PSM(mem)) +#define PSMs16(mem) (*(s16*)PSM(mem)) +#define PSMs32(mem) (*(s32*)PSM(mem)) +#define PSMs64(mem) (*(s64*)PSM(mem)) +#define PSMu8(mem) (*(u8 *)PSM(mem)) +#define PSMu16(mem) (*(u16*)PSM(mem)) +#define PSMu32(mem) (*(u32*)PSM(mem)) +#define PSMu64(mem) (*(u64*)PSM(mem)) + +int memInit(); +void memReset(); +void memSetKernelMode(); +void memSetSupervisorMode(); +void memSetUserMode(); +void memSetPageAddr(u32 vaddr, u32 paddr); +void memClearPageAddr(u32 vaddr); +void memShutdown(); + +int memRead8(u32 mem, u8 *out); +int memRead8RS(u32 mem, u64 *out); +int memRead8RU(u32 mem, u64 *out); +int memRead16(u32 mem, u16 *out); +int memRead16RS(u32 mem, u64 *out); +int memRead16RU(u32 mem, u64 *out); +int memRead32(u32 mem, u32 *out); +int memRead32RS(u32 mem, u64 *out); +int memRead32RU(u32 mem, u64 *out); +int memRead64(u32 mem, u64 *out); +int memRead128(u32 mem, u64 *out); +void memWrite8 (u32 mem, u8 value); +void memWrite16(u32 mem, u16 value); +void memWrite32(u32 mem, u32 value); +void memWrite64(u32 mem, u64 value); +void memWrite128(u32 mem, u64 *value); + +// recMemConstRead8, recMemConstRead16, recMemConstRead32 return 1 if a call was made, 0 otherwise +u8 recMemRead8(); +u16 recMemRead16(); +u32 recMemRead32(); +void recMemRead64(u64 *out); +void recMemRead128(u64 *out); + +// returns 1 if mem should be cleared +void recMemWrite8(); +void recMemWrite16(); +void recMemWrite32(); +void recMemWrite64(); +void recMemWrite128(); + +// VM only functions +#ifdef WIN32_VIRTUAL_MEM + +void _eeReadConstMem8(int mmreg, u32 mem, int sign); +void _eeReadConstMem16(int mmreg, u32 mem, int sign); +void _eeReadConstMem32(int mmreg, u32 mem); +void _eeReadConstMem128(int mmreg, u32 mem); +void _eeWriteConstMem8(u32 mem, int mmreg); +void _eeWriteConstMem16(u32 mem, int mmreg); +void _eeWriteConstMem32(u32 mem, int mmreg); +void _eeWriteConstMem64(u32 mem, int mmreg); +void _eeWriteConstMem128(u32 mem, int mmreg); +void _eeMoveMMREGtoR(int to, int mmreg); + +// extra ops +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op); +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op); + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead32(u32 x86reg, u32 mem); +void recMemConstRead64(u32 mem, int mmreg); +void recMemConstRead128(u32 mem, int xmmreg); + +int recMemConstWrite8(u32 mem, int mmreg); +int recMemConstWrite16(u32 mem, int mmreg); +int recMemConstWrite32(u32 mem, int mmreg); +int recMemConstWrite64(u32 mem, int mmreg); +int recMemConstWrite128(u32 mem, int xmmreg); + +#else + +#define _eeReadConstMem8 0&& +#define _eeReadConstMem16 0&& +#define _eeReadConstMem32 0&& +#define _eeReadConstMem128 0&& +#define _eeWriteConstMem8 0&& +#define _eeWriteConstMem16 0&& +#define _eeWriteConstMem32 0&& +#define _eeWriteConstMem64 0&& +#define _eeWriteConstMem128 0&& +#define _eeMoveMMREGtoR 0&& + +// extra ops +#define _eeWriteConstMem16OP 0&& +#define _eeWriteConstMem32OP 0&& + +#define recMemConstRead8 0&& +#define recMemConstRead16 0&& +#define recMemConstRead32 0&& +#define recMemConstRead64 0&& +#define recMemConstRead128 0&& + +#define recMemConstWrite8 0&& +#define recMemConstWrite16 0&& +#define recMemConstWrite32 0&& +#define recMemConstWrite64 0&& +#define recMemConstWrite128 0&& + +#endif + +#endif diff --git a/branches/pcsx2_0.9.2/Misc.c b/branches/pcsx2_0.9.2/Misc.c new file mode 100644 index 0000000..728247e --- /dev/null +++ b/branches/pcsx2_0.9.2/Misc.c @@ -0,0 +1,895 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "CDVDisodrv.h" +#include "VUmicro.h" +#ifdef __WIN32__ +#include "RDebug/deci2.h" +#endif + +#include "GS.h" + +u32 dwSaveVersion = 0x7a30000e; +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; +extern int g_psxWriteOk; + +PcsxConfig Config; +u32 BiosVersion; +char CdromId[12]; + +char *LabelAuthors = { N_( + "PCSX2 a PS2 emulator\n\n" + "written by:\n" + "saqib, refraction, zerofrog,\n" + "shadow, linuzappz, florin,\n" + "nachbrenner, auMatt, loser, \n" + "alexey silinov, goldfinger,\n" + "\n" + "Webmasters: CKemu, Falcon4ever") +}; + +char *LabelGreets = { N_( + "Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" + "Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" + "Seta-San, Skarmeth, blackd_wd, _Demo_\n" + "\n" + "Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n" + "\n" + "Some betatester/support dudes: Belmont, bositman, ChaosCode, CKemu, crushtest," + "falcon4ever, GeneralPlot, jegHegy, parotaku, Prafull, Razorblade, Rudy_X, Seta-san") +}; + +static struct { + char *name; + u32 size; +} ioprps[]={ + {"IOPRP14", 43845}, + {"IOPRP142", 48109}, + {"IOPRP143", 58317}, + {"IOPRP144", 58525}, + {"IOPRP15", 82741}, + {"IOPRP151", 82917}, + {"IOPRP153", 82949}, + {"IOPRP16", 91909}, + {"IOPRP165", 98901}, + {"IOPRP20", 109809}, + {"IOPRP202", 110993}, + {"IOPRP205", 119797}, + {"IOPRP21", 126857}, + {"IOPRP211", 129577}, + {"IOPRP213", 129577}, + {"IOPRP214", 140945}, + {"IOPRP22", 199257}, + {"IOPRP221", 196937}, + {"IOPRP222", 198233}, + {"IOPRP224", 201065}, + {"IOPRP23", 230329}, + {"IOPRP234", 247641}, + {"IOPRP24", 251065}, + {"IOPRP241", 251049}, + {"IOPRP242", 252409}, + {"IOPRP243", 253201}, + {"IOPRP250", 264897}, + {"IOPRP252", 265233}, + {"IOPRP253", 267217}, + {"IOPRP254", 264449}, + {"IOPRP255", 264449}, + {"IOPRP260", 248945}, + {"IOPRP270", 249121}, + {"IOPRP271", 266817}, + {"IOPRP280", 269889}, + {"IOPRP300", 275345}, + {"DNAS280", 272753}, + {"DNAS270", 251729}, + {"DNAS271", 268977}, + {"DNAS300", 278641}, + {"DNAS280", 272705}, + {"DNAS255", 264945}, + {NULL, 0} +}; + +void GetRPCVersion(char *ioprp, char *rpcver){ + char *p=ioprp; int i; + struct TocEntry te; + + if (p && (CDVD_findfile(p+strlen("cdromN:"), &te) != -1)){ + for (i=0; ioprps[i].size>0; i++) + if (te.fileSize==ioprps[i].size) + break; + if (ioprps[i].size>0) + p=ioprps[i].name; + } + if (p && (p=strstr(p, "IOPRP")+strlen("IOPRP"))){ + for (i=0;(i<4) && p && (*p>='0') && (*p<='9');i++, p++) rpcver[i]=*p; + for ( ; i<4 ;i++ ) rpcver[i]='0'; + } +} + +u32 GetBiosVersion() { + unsigned int fileOffset=0; + char *ROMVER; + char vermaj[8]; + char vermin[8]; + struct romdir *rd; + u32 version; + int i; + + for (i=0; i<512*1024; i++) { + rd = (struct romdir*)&psRu8(i); + if (strncmp(rd->fileName, "RESET", 5) == 0) + break; /* found romdir */ + } + if (i == 512*1024) return -1; + + while(strlen(rd->fileName) > 0){ + if (strcmp(rd->fileName, "ROMVER") == 0){ // found romver + ROMVER = &psRs8(fileOffset); + + strncpy(vermaj, ROMVER+ 0, 2); vermaj[2] = 0; + strncpy(vermin, ROMVER+ 2, 2); vermin[2] = 0; + version = strtol(vermaj, (char**)NULL, 0) << 8; + version|= strtol(vermin, (char**)NULL, 0); + + return version; + } + + if ((rd->fileSize % 0x10)==0) + fileOffset += rd->fileSize; + else + fileOffset += (rd->fileSize + 0x10) & 0xfffffff0; + + rd++; + } + + return -1; +} + +//2002-09-22 (Florin) +int IsBIOS(char *filename, char *description){ + struct stat buf; + char Bios[260], ROMVER[14+1], zone[12+1]; + FILE *fp; + unsigned int fileOffset=0, found=FALSE; + struct romdir rd; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, filename); + + if (stat(Bios, &buf) == -1) return FALSE; + + fp = fopen(Bios, "rb"); + if (fp == NULL) return FALSE; + + while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1)) + if (strcmp(rd.fileName, "RESET") == 0) + break; /* found romdir */ + + if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) { + fclose(fp); + return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img + } + + while(strlen(rd.fileName) > 0){ + if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver + unsigned int filepos=ftell(fp); + fseek(fp, fileOffset, SEEK_SET); + if (fread(&ROMVER, 14, 1, fp) == 0) break; + fseek(fp, filepos, SEEK_SET);//go back + + switch(ROMVER[4]){ + case 'T':sprintf(zone, "T10K "); break; + case 'X':sprintf(zone, "Test ");break; + case 'J':sprintf(zone, "Japan "); break; + case 'A':sprintf(zone, "USA "); break; + case 'E':sprintf(zone, "Europe"); break; + case 'H':sprintf(zone, "HK "); break; + case 'P':sprintf(zone, "Free "); break; + case 'C':sprintf(zone, "China "); break; + default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show + } + sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone, + ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); + strncpy(description+ 8, ROMVER+ 0, 2);//ver major + strncpy(description+11, ROMVER+ 2, 2);//ver minor + strncpy(description+14, ROMVER+12, 2);//day + strncpy(description+17, ROMVER+10, 2);//month + strncpy(description+20, ROMVER+ 6, 4);//year + found = TRUE; + } + + if ((rd.fileSize % 0x10)==0) + fileOffset += rd.fileSize; + else + fileOffset += (rd.fileSize + 0x10) & 0xfffffff0; + + if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break; + } + fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize; + + fclose(fp); + + if (found) { + char percent[6]; + + if (buf.st_size<(int)fileOffset){ + sprintf(percent, " %d%%", buf.st_size*100/(int)fileOffset); + strcat(description, percent);//we force users to have correct bioses, + //not that lame scph10000 of 513KB ;-) + } + return TRUE; + } + + return FALSE; //fail quietly +} + +// LOAD STUFF + +#define ISODCL(from, to) (to - from + 1) + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +#define READTRACK(lsn) \ + if (CDVDreadTrack(lsn, CDVD_MODE_2352) == -1) return -1; \ + buf = CDVDgetBuffer(); if (buf == NULL) return -1; + +int LoadCdrom() { + return 0; +} + +int CheckCdrom() { + u8 *buf; + + READTRACK(16); + strncpy(CdromId, (char*)buf+52, 10); + + return 0; +} + +int GetPS2ElfName(char *name){ + FILE *fp; + int f; + char buffer[256];//if a file is longer...it should be shorter :D + char *pos; + static struct TocEntry tocEntry; + int i; + + CDVDFS_init(); + + // check if the file exists + if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){ + SysPrintf("SYSTEM.CNF not found\n"); + return 0;//could not find; not a PS/PS2 cdvd + } + + f=CDVDFS_open("SYSTEM.CNF;1", 1); + CDVDFS_read(f, buffer, 256); + CDVDFS_close(f); + + buffer[tocEntry.fileSize]='\0'; + +// SysPrintf( +// "---------------------SYSTEM.CNF---------------------\n" +// "%s" +// "----------------------------------------------------\n", buffer); + pos=strstr(buffer, "BOOT2"); + if (pos==NULL){ + pos=strstr(buffer, "BOOT"); + if (pos==NULL) { + SysPrintf("This is not a PS2 game!\n"); + return 0; + } + return 1; + } + pos+=strlen("BOOT2"); + while (pos && *pos && pos<=&buffer[255] + && (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z')) + pos++; + if (!pos || *pos==0) + return 0; + + sscanf(pos, "%s", name); + //SysPrintf("ELF name: '%s'\n", name); + + if (strncmp("cdrom0:\\", name, 8) == 0) { + strncpy(CdromId, name+8, 11); CdromId[11] = 0; + } + +// inifile_read(CdromId); + + fp = fopen("System.map", "r"); + if (fp) { + u32 addr; + + SysPrintf("Loading System.map\n", fp); + while (!feof(fp)) { + fseek(fp, 8, SEEK_CUR); + buffer[0] = '0'; buffer[1] = 'x'; + for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0; + addr = strtoul(buffer, (char**)NULL, 0); + fseek(fp, 3, SEEK_CUR); + for (i=0; i<256; i++) { + buffer[i] = fgetc(fp); + if (buffer[i] == '\n' || buffer[i] == 0) break; + } + if (buffer[i] == 0) break; + buffer[i] = 0; + + disR5900AddSym(addr, buffer); + } + fclose(fp); + } + + return 2; +} + +/*#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +static int PSXGetFileType(FILE *f) { + unsigned long current; + unsigned long mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + + strcpy(CdromId, "SLUS_999.99"); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { SysMessage("Error opening file: %s", ExePath); return 0; } + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile); + fclose(tmpFile); + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.s_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + break; + case CPE_EXE: + SysMessage("Pcsx found that you wanna use a CPE file. CPE files not support yet"); + break; + case COFF_EXE: + SysMessage("Pcsx found that you wanna use a COFF file.COFF files not support yet"); + break; + case INVALID_EXE: + SysMessage("This file is not a psx file"); + break; + } + return 1; +} +*/ + +u16 logProtocol; +u8 logSource; +int connected=0; + +#define SYNC_LOGGING + +void __Log(char *fmt, ...) { +#ifdef EMU_LOG + va_list list; + static char tmp[2024]; //hm, should be enough + + va_start(list, fmt); +#ifdef __WIN32__ + if (connected && logProtocol>=0 && logProtocol<0x10){ + vsprintf(tmp, fmt, list); + sendTTYP(logProtocol, logSource, tmp); + }//else //!!!!! is disabled, so the text goes to ttyp AND log +#endif + { +#ifndef LOG_STDOUT + if (varLog & 0x80000000) { + vsprintf(tmp, fmt, list); + SysPrintf(tmp); + } else if( emuLog != NULL ) { + vfprintf(emuLog, fmt, list); + } +#else //i assume that this will not be used (Florin) + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + } + va_end(list); +#endif +} + +// STATES + +#define STATE_VERSION "STv6" +const char Pcsx2Header[32] = STATE_VERSION " PCSX2 v" PCSX2_VERSION; + +#define _PS2Esave(type) \ + if (type##freeze(FREEZE_SIZE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + \ + if (type##freeze(FREEZE_SAVE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + \ + gzwrite(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + gzwrite(f, fP.data, fP.size); \ + free(fP.data); \ + } + +#define _PS2Eload(type) \ + gzread(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + gzread(f, fP.data, fP.size); \ + } \ + if (type##freeze(FREEZE_LOAD, &fP) == -1) { \ + /* skip */ \ + /*if (fP.size) free(fP.data); \ + gzclose(f); \ + return -1;*/ \ + } \ + if (fP.size) free(fP.data); + + +extern void gsWaitGS(); + +extern u32 g_nextBranchCycle, g_psxNextBranchCycle; + +int SaveState(char *file) { + + gzFile f; + freezeData fP; + + gsWaitGS(); + + SysPrintf("SaveState: %s\n", file); + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, &dwSaveVersion, 4); + + gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + + gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory + + gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs] + gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzwrite(f, &EEsCycle, sizeof(EEsCycle)); + gzwrite(f, &EEoCycle, sizeof(EEoCycle)); + gzwrite(f, &IOPoCycle, sizeof(IOPoCycle)); + gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzwrite(f, s_iLastPERFCycle, sizeof(u32)*2); + gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + //gzwrite(f, (void*)&ipuRegs, sizeof(IPUregisters)); // ipu regs + //hope didn't forgot any cpu.... + + rcntFreeze(f, 1); + gsFreeze(f, 1); + vu0Freeze(f, 1); + vu1Freeze(f, 1); + vif0Freeze(f, 1); + vif1Freeze(f, 1); + sifFreeze(f, 1); + ipuFreeze(f, 1); + + // iop now + gzwrite(f, psxM, 0x00200000); // 2 MB main memory + //gzwrite(f, psxP, 0x00010000); // pralell memory + gzwrite(f, psxH, 0x00010000); // hardware memory + //gzwrite(f, psxS, 0x00010000); // sif memory + + sioFreeze(f, 1); + cdrFreeze(f, 1); + cdvdFreeze(f, 1); + psxRcntFreeze(f, 1); + //mdecFreeze(f, 1); + sio2Freeze(f, 1); + + SysPrintf("Saving GS\n"); + _PS2Esave(GS); + SysPrintf("Saving SPU2\n"); + _PS2Esave(SPU2); + SysPrintf("Saving DEV9\n"); + _PS2Esave(DEV9); + SysPrintf("Saving USB\n"); + _PS2Esave(USB); + SysPrintf("Saving ok\n"); + + gzclose(f); + + return 0; +} + +extern u32 dumplog; +extern u32 s_vucount; + +int LoadState(char *file) { + + gzFile f; + freezeData fP; + int i; + u32 OldProtect; + u32 dwVer; + +#ifdef _DEBUG + s_vucount = 0; + //dumplog |= 2; +#endif + + SysPrintf("LoadState: %s\n", file); + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, &dwVer, 4); + + if( dwVer != dwSaveVersion ) { + + if( dwVer != 0x7a30000d ) { + gzclose(f); + SysPrintf("Save state wrong version\n"); + return 0; + } + } + + // stop and reset the system first + gsWaitGS(); + + for (i=0; i<48; i++) ClearTLB(i); + + Cpu->Reset(); + recResetVU0(); + recResetVU1(); + psxCpu->Reset(); + + SysPrintf("Loading memory\n"); + +#ifdef WIN32_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + +#ifdef WIN32_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif + + gzread(f, PS2MEM_HW, 0x00010000); // hardware memory + + SysPrintf("Loading structs\n"); + gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs + gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzread(f, &EEsCycle, sizeof(EEsCycle)); + gzread(f, &EEoCycle, sizeof(EEoCycle)); + gzread(f, &IOPoCycle, sizeof(IOPoCycle)); + gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + if( dwVer >= 0x7a30000e ) { + gzread(f, s_iLastPERFCycle, sizeof(u32)*2); + } + gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + rcntFreeze(f, 0); + gsFreeze(f, 0); + vu0Freeze(f, 0); + vu1Freeze(f, 0); + vif0Freeze(f, 0); + vif1Freeze(f, 0); + sifFreeze(f, 0); + ipuFreeze(f, 0); + + // iop now + SysPrintf("Loading iop mem\n"); + gzread(f, psxM, 0x00200000); // 2 MB main memory + //gzread(f, psxP, 0x00010000); // pralell memory + gzread(f, psxH, 0x00010000); // hardware memory + //gzread(f, psxS, 0x00010000); // sif memory + + SysPrintf("Loading iop stuff\n"); + sioFreeze(f, 0); + cdrFreeze(f, 0); + cdvdFreeze(f, 0); + psxRcntFreeze(f, 0); + //mdecFreeze(f, 0); + sio2Freeze(f, 0); + + SysPrintf("Loading GS\n"); + _PS2Eload(GS); + SysPrintf("Loading SPU2\n"); + _PS2Eload(SPU2); + SysPrintf("Loading DEV9\n"); + _PS2Eload(DEV9); + SysPrintf("Loading USB\n"); + _PS2Eload(USB); + + SysPrintf("Loading ok\n"); + + gzclose(f); + + //dumplog |= 4; + WriteCP0Status(cpuRegs.CP0.n.Status.val); + for (i=0; i<48; i++) WriteTLB(i); + + return 0; +} + +#ifdef PCSX2_DEVBUILD + +int SaveGSState(char *file) +{ + if( g_SaveGSStream ) return -1; + + SysPrintf("SaveGSState: %s\n", file); + g_fGSSave = gzopen(file, "wb"); + if (g_fGSSave == NULL) return -1; + + g_SaveGSStream = 1; + g_nLeftGSFrames = 2; + + gzwrite(g_fGSSave, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames)); + + return 0; +} + +extern long pDsp; +int LoadGSState(char *file) +{ + int ret; + char strfile[255]; + gzFile f; + freezeData fP; + + f = gzopen(file, "rb"); + if (f == NULL) { + + _snprintf(strfile, 255, "sstates\\%s", file); + // try prefixing with sstates + f = gzopen(strfile, "rb"); + if( f == NULL ) { + SysPrintf("Failed to find gs state\n"); + return -1; + } + + file = strfile; + } + + SysPrintf("LoadGSState: %s\n", file); + + GSirqCallback(gsIrq); + ret = GSopen(&pDsp, "PCSX2", 0); + if (ret != 0) { + SysMessage (_("Error Opening GS Plugin")); + return -1; + } + + ret = PAD1open((void *)&pDsp); + + gzread(f, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames)); + + gsFreeze(f, 0); + _PS2Eload(GS); + + RunGSState(f); + gzclose(f); + + GSclose(); + PAD1close(); + + return 0; +} + +#endif + +int CheckState(char *file) { + gzFile f; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, 32); + + gzclose(f); + + if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1; + + return 0; +} + + +typedef struct { + char id[8]; + char name[64]; +} LangDef; + +LangDef sLangs[] = { + { "ar_AR", N_("Arabic") }, + { "bg_BG", N_("Bulgarian") }, + { "ca_CA", N_("Catalan") }, + { "du_DU", N_("Dutch") }, + { "de_DE", N_("German") }, + { "el_EL", N_("Greek") }, + { "en_US", N_("English") }, + { "fr_FR", N_("French") }, + { "hb_HB" , N_("Hebrew") }, + { "hu_HU", N_("Hungarian") }, + { "it_IT", N_("Italian") }, + { "ja_JA", N_("Japanese") }, + { "po_PO", N_("Portuguese") }, + { "pl_PL" , N_("Polish") }, + { "ro_RO", N_("Romanian") }, + { "ru_RU", N_("Russian") }, + { "es_ES", N_("Spanish") }, + { "sh_SH" , N_("S-Chinese") }, + { "sw_SW", N_("Swedish") }, + { "tc_TC", N_("T-Chinese") }, + { "tr_TR", N_("Turkish") }, + { "", "" }, +}; + + +char *ParseLang(char *id) { + int i=0; + + while (sLangs[i].id[0] != 0) { + if (!strcmp(id, sLangs[i].id)) + return _(sLangs[i].name); + i++; + } + + return id; +} + +void injectIRX(char *filename){ + struct stat buf; + char path[260], name[260], *p, *q; + struct romdir *rd; + int iROMDIR=-1, iIOPBTCONF=-1, iBLANK=-1, i, filesize; + FILE *fp; + + strcpy(name, filename); + for (i=0; name[i] && name[i]!='.' && i<10; i++) name[i]=toupper(name[i]);name[i]=0; + + //phase 1: find ROMDIR in bios + for (p=(char*)PS2MEM_ROM; p<(char*)PS2MEM_ROM+0x80000; p++) + if (strncmp(p, "RESET", 5)==0) + break; + rd=(struct romdir*)p; + + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, name, strlen(name))==0)break; + if (rd[i].fileName[0])return;//already in;) + + //phase 2: make room in IOPBTCONF & ROMDIR + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, "ROMDIR", 6)==0)iROMDIR=i; + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, "IOPBTCONF", 9)==0)iIOPBTCONF=i; + + for (i=0; rd[i].fileName[0]; i++)if (rd[i].fileName[0]=='-')break; iBLANK=i; + rd[iBLANK].fileSize-=DIRENTRY_SIZE+DIRENTRY_SIZE; + p=(char*)PS2MEM_ROM;for (i=0; iq){*((u64*)p)=*((u64*)p-4);*((u64*)p+1)=*((u64*)p-3);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iIOPBTCONF].fileSize+=DIRENTRY_SIZE; + + q=(char*)PS2MEM_ROM;for (i=0; i<=iROMDIR; i++) q+=(rd[i].fileSize+0xF)&(~0xF); + while (p >q){*((u64*)p)=*((u64*)p-2);*((u64*)p+1)=*((u64*)p-1);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iROMDIR].fileSize+=DIRENTRY_SIZE; + + //phase 3: add the name to the end of IOPBTCONF + p=(char*)PS2MEM_ROM;for (i=0; i +#include + +#undef s_addr + +// compile-time assert +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#define PCSX2_GSMULTITHREAD 1 // uses multithreaded gs +#define PCSX2_DUALCORE 2 // speed up for dual cores +#define PCSX2_FRAMELIMIT 4 // limits frames to normal speeds +#define PCSX2_EEREC 0x10 +#define PCSX2_VU0REC 0x20 +#define PCSX2_VU1REC 0x40 +#define PCSX2_COP2REC 0x80 +#define PCSX2_FORCEABS 0x100 +#define PCSX2_FRAMELIMIT_MASK 0xc00 +#define PCSX2_FRAMELIMIT_NORMAL 0x000 +#define PCSX2_FRAMELIMIT_LIMIT 0x400 +#define PCSX2_FRAMELIMIT_SKIP 0x800 +#define PCSX2_FRAMELIMIT_VUSKIP 0xc00 + +#define CHECK_MULTIGS (Config.Options&PCSX2_GSMULTITHREAD) +#define CHECK_DUALCORE (Config.Options&PCSX2_DUALCORE) +#define CHECK_EEREC (Config.Options&PCSX2_EEREC) +#define CHECK_COP2REC (Config.Options&PCSX2_COP2REC) // goes with ee option +#define CHECK_FORCEABS 1// always on, (Config.Options&PCSX2_FORCEABS) + +#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK) + +//#ifdef PCSX2_DEVBUILD +#define CHECK_VU0REC (Config.Options&PCSX2_VU0REC) +#define CHECK_VU1REC (Config.Options&PCSX2_VU1REC) +//#else +//// force to VU recs all the time +//#define CHECK_VU0REC 1 +//#define CHECK_VU1REC 1 +// +//#endif + +typedef struct { + char Bios[256]; + char GS[256]; + char PAD1[256]; + char PAD2[256]; + char SPU2[256]; + char CDVD[256]; + char DEV9[256]; + char USB[256]; + char FW[256]; + char Mcd1[256]; + char Mcd2[256]; + char PluginsDir[256]; + char BiosDir[256]; + char Lang[256]; + u32 Options; // PCSX2_X options + int PsxOut; + int PsxType; + int Cdda; + int Mdec; + int Patch; + int ThPriority; + int SafeCnts; +} PcsxConfig; + +extern PcsxConfig Config; +extern u32 BiosVersion; +extern char CdromId[12]; + +#define gzfreeze(ptr, size) \ + if (Mode == 1) gzwrite(f, ptr, size); \ + else if (Mode == 0) gzread(f, ptr, size); + +#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr)) + +int LoadCdrom(); +int CheckCdrom(); +int GetPS2ElfName(char*); + +extern char *LabelAuthors; +extern char *LabelGreets; +int SaveState(char *file); +int LoadState(char *file); +int CheckState(char *file); + +int SaveGSState(char *file); +int LoadGSState(char *file); + +char *ParseLang(char *id); + +#ifdef __WIN32__ +void ListPatches (HWND hW); +int ReadPatch (HWND hW, char fileName[1024]); +char * lTrim (char *s); +BOOL Save_Patch_Proc( char * filename ); +#endif + +#define DIRENTRY_SIZE 16 + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct romdir{ + char fileName[10]; + u16 extInfoSize; + u32 fileSize; +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +u32 GetBiosVersion(); +int IsBIOS(char *filename, char *description); + +void * memcpy_amd(void *dest, const void *src, size_t n); +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize); +void memxor_mmx(void* dst, const void* src1, int cmpsize); + +#ifdef __WIN32__ +#pragma pack() +#endif + +void __Log(char *fmt, ...); +void injectIRX(char *filename); + +#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) + +// declare linux equivalents +inline void* pcsx2_aligned_malloc(size_t size, size_t align) +{ + char* p = (char*)malloc(size+align+1); + int off = 1+align - ((int)(p+1) % align); + + p += off; + p[-1] = off; + + return p; +} + +inline void pcsx2_aligned_free(void* pmem) +{ + char* p = (char*)pmem; + free(p - (int)p[-1]); +} + +#define _aligned_malloc pcsx2_aligned_malloc +#define _aligned_free pcsx2_aligned_free + +#endif + +// cross-platform atomic operations +#if defined (__MSCW32__) + +LONG __cdecl _InterlockedIncrement(LONG volatile *Addend); +LONG __cdecl _InterlockedDecrement(LONG volatile *Addend); +LONG __cdecl _InterlockedCompareExchange(LPLONG volatile Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LPLONG volatile Target, LONG Value); +PVOID __cdecl _InterlockedExchangePointer(PVOID volatile* Target, PVOID Value); + +LONG __cdecl _InterlockedExchangeAdd(LPLONG volatile Addend, LONG Value); +LONG __cdecl _InterlockedAnd(LPLONG volatile Addend, LONG Value); + +#pragma intrinsic (_InterlockedCompareExchange) +#define InterlockedCompareExchange _InterlockedCompareExchange + +#pragma intrinsic (_InterlockedExchange) +#define InterlockedExchange _InterlockedExchange + +#pragma intrinsic (_InterlockedExchangeAdd) +#define InterlockedExchangeAdd _InterlockedExchangeAdd + +#pragma intrinsic (_InterlockedIncrement) +#define InterlockedIncrement _InterlockedIncrement + +#pragma intrinsic (_InterlockedDecrement) +#define InterlockedDecrement _InterlockedDecrement + +#pragma intrinsic (_InterlockedAnd) +#define InterlockedAnd _InterlockedAnd + +#elif defined(__LINUX__) + +#endif + +#endif /* __MISC_H__ */ diff --git a/branches/pcsx2_0.9.2/PS2Edefs.h b/branches/pcsx2_0.9.2/PS2Edefs.h new file mode 100644 index 0000000..ab262bc --- /dev/null +++ b/branches/pcsx2_0.9.2/PS2Edefs.h @@ -0,0 +1,805 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/branches/pcsx2_0.9.2/PS2Etypes.h b/branches/pcsx2_0.9.2/PS2Etypes.h new file mode 100644 index 0000000..055c40c --- /dev/null +++ b/branches/pcsx2_0.9.2/PS2Etypes.h @@ -0,0 +1,75 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_WIN32) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +#endif /* __PS2ETYPES_H__ */ diff --git a/branches/pcsx2_0.9.2/Patch.c b/branches/pcsx2_0.9.2/Patch.c new file mode 100644 index 0000000..5b1cfb2 --- /dev/null +++ b/branches/pcsx2_0.9.2/Patch.c @@ -0,0 +1,381 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Includes +// +#include +#include + +#include "PsxCommon.h" + +#include "windows/cheats/cheats.h" + +#include "patch.h" + +// +// Variables +// +PatchTextTable commands[] = +{ + { "comment", 1, patchFunc_comment }, + { "gametitle", 2, patchFunc_gametitle }, + { "patch", 3, patchFunc_patch }, + { "fastmemory", 4, patchFunc_fastmemory }, // enable for faster but bugger mem (mvc2 is faster) + { "roundmode", 5, patchFunc_roundmode }, // changes rounding mode for floating point + // syntax: roundmode=X,Y + // possible values for X,Y: NEAR, DOWN, UP, CHOP + // X - EE rounding mode (default is NEAR) + // Y - VU rounding mode (default is CHOP) + { "", 0, NULL } +}; + +PatchTextTable dataType[] = +{ + { "byte", 1, NULL }, + { "short", 2, NULL }, + { "word", 3, NULL }, + { "double", 4, NULL }, + { "", 0, NULL } +}; + +PatchTextTable cpuCore[] = +{ + { "EE", 1, NULL }, + { "IOP", 2, NULL }, + { "", 0, NULL } +}; + +IniPatch patch[ MAX_PATCH ]; +int patchnumber; + + +// +// Function Implementations +// + +int PatchTableExecute( char * text1, char * text2, PatchTextTable * Table ) +{ + int i = 0; + + while ( Table[ i ].text[ 0 ] ) + { + if ( !strcmp( Table[ i ].text, text1 ) ) + { + if ( Table[ i ].func ) + { + Table[ i ].func( text1, text2 ); + } + break; + } + i++; + } + + return Table[ i ].code; +} + +void _applypatch(int place, IniPatch *p) { + if (p->placetopatch != place) return; + + if (p->enabled == 0) return; + + if (p->cpu == 1) { //EE + if (p->type == 1) { //byte + memWrite8(p->addr, (u8)p->data); + } else + if (p->type == 2) { //short + memWrite16(p->addr, (u16)p->data); + } else + if (p->type == 3) { //word + memWrite32(p->addr, (u32)p->data); + } else + if (p->type == 4) { //double + memWrite64(p->addr, p->data); + } + } else + if (p->cpu == 2) { //IOP + if (p->type == 1) { //byte + psxMemWrite8(p->addr, (u8)p->data); + } else + if (p->type == 2) { //short + psxMemWrite16(p->addr, (u16)p->data); + } else + if (p->type == 3) { //word + psxMemWrite32(p->addr, (u32)p->data); + } + } +} + +//this is for apply patches directly to memory +void applypatch(int place) { + int i; + + if (place == 0) { + SysPrintf(" patchnumber: %d\n", patchnumber); + } + + for ( i = 0; i < patchnumber; i++ ) { + _applypatch(place, &patch[i]); + } +} + +void patchFunc_comment( char * text1, char * text2 ) +{ + SysPrintf( "comment: %s \n", text2 ); +} + +char strgametitle[256] = {0}; + +void patchFunc_gametitle( char * text1, char * text2 ) +{ + SysPrintf( "gametitle: %s \n", text2 ); +#ifdef __WIN32__ + sprintf(strgametitle,"%s",text2); + if (gApp.hConsole) SetConsoleTitle(strgametitle); +#endif +} + +void patchFunc_patch( char * cmd, char * param ) +{ + //patch=placetopatch,cpucore,address,type,data + char * pText; + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached: %s=%s\n", cmd, param ); + return; + } + + pText = strtok( param, "," ); + pText = param; +// inifile_trim( pText ); + + patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].cpu = PatchTableExecute( pText, NULL, cpuCore ); + if ( patch[ patchnumber ].cpu == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].addr ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].type = PatchTableExecute( pText, NULL, dataType ); + if ( patch[ patchnumber ].type == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%I64X", &patch[ patchnumber ].data ); + + patch[ patchnumber ].enabled = 1; + + patchnumber++; +} + +//this routine is for execute the commands of the ini file +void inifile_command( char * cmd ) +{ + int code; + char command[ 256 ]; + char parameter[ 256 ]; + + // extract param part (after '=') + char * pEqual = strchr( cmd, '=' ); + + if ( ! pEqual ) + { + // fastmemory doesn't have = + pEqual = cmd+strlen(cmd); +// SysPrintf( "Ini file ERROR: unknow line: %s \n", cmd ); +// return; + } + + memset( command, 0, sizeof( command ) ); + memset( parameter, 0, sizeof( parameter ) ); + + strncpy( command, cmd, pEqual - cmd ); + strncpy( parameter, pEqual + 1, sizeof( parameter ) ); + + inifile_trim( command ); + inifile_trim( parameter ); + + code = PatchTableExecute( command, parameter, commands ); +} + +void inifile_trim( char * buffer ) +{ + char * pInit = buffer; + char * pEnd = NULL; + + while ( ( *pInit == ' ' ) || ( *pInit == '\t' ) ) //skip space + { + pInit++; + } + if ( ( pInit[ 0 ] == '/' ) && ( pInit[ 1 ] == '/' ) ) //remove comment + { + buffer[ 0 ] = '\0'; + return; + } + pEnd = pInit + strlen( pInit ) - 1; + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + while ( ( *pEnd == '\r' ) || ( *pEnd == '\n' ) || + ( *pEnd == ' ' ) || ( *pEnd == '\t' ) ) + { + pEnd--; + } + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + memmove( buffer, pInit, pEnd - pInit + 1 ); + buffer[ pEnd - pInit + 1 ] = '\0'; +} + +void inisection_process( FILE * f1 ) +{ + char buffer[ 1024 ]; + while( fgets( buffer, sizeof( buffer ), f1 ) ) + { + inifile_trim( buffer ); + if ( buffer[ 0 ] ) + { + inifile_command( buffer ); + } + } +} + +//this routine is for reading the ini file + +void inifile_read( char * name ) +{ + FILE * f1; + char buffer[ 1024 ]; + + patchnumber = 0; +#ifdef __WIN32__ + sprintf( buffer, "patches\\%s.pnach", name ); +#else + sprintf( buffer, "patches/%s.pnach", name ); +#endif + + f1 = fopen( buffer, "rt" ); + if( !f1 ) + { + SysPrintf( _( "patch file for this game not found. Can't apply any patches\n" ) ); + return; + } + + inisection_process( f1 ); + + fclose( f1 ); +} + +void resetpatch( void ) +{ + patchnumber = 0; +} + +int AddPatch(int Mode, int Place, int Address, int Size, u64 data) +{ + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached.\n"); + return -1; + } + + patch[patchnumber].placetopatch = Mode; + patch[patchnumber].cpu = Place; + patch[patchnumber].addr=Address; + patch[patchnumber].type=Size; + patch[patchnumber].data = data; + return patchnumber++; +} + +void patchFunc_fastmemory( char * cmd, char * param ) +{ + SetFastMemory(1); +} + +void patchFunc_roundmode( char * cmd, char * param ) +{ + //roundmode = X,Y + int index; + char * pText; + + u32 eetype=0x0000; + u32 vutype=0x6000; + + index = 0; + pText = strtok( param, ", " ); + while(pText != NULL) { + u32 type = 0xffff; + if( stricmp(pText, "near") == 0 ) { + type = 0x0000; + } + else if( stricmp(pText, "down") == 0 ) { + type = 0x2000; + } + else if( stricmp(pText, "up") == 0 ) { + type = 0x4000; + } + else if( stricmp(pText, "chop") == 0 ) { + type = 0x6000; + } + + if( type == 0xffff ) { + printf("bad argument (%s) to round mode! skipping...\n", pText); + break; + } + + if( index == 0 ) eetype=type; + else vutype=type; + + if( index == 1 ) + break; + + index++; + pText = strtok(NULL, ", "); + } + + SetRoundMode(eetype,vutype); +} + +void SetRoundMode(u32 ee, u32 vu) +{ + g_sseMXCSR = 0x9f80|ee; + g_sseVUMXCSR = 0x9f80|vu; + + SetCPUState(); +} diff --git a/branches/pcsx2_0.9.2/Patch.h b/branches/pcsx2_0.9.2/Patch.h new file mode 100644 index 0000000..12a5d8c --- /dev/null +++ b/branches/pcsx2_0.9.2/Patch.h @@ -0,0 +1,78 @@ +#ifndef __PATCH_H__ +#define __PATCH_H__ + +// +// Defines +// +#define MAX_PATCH 1024 + +#define IFIS(x,str) if(!strnicmp(x,str,sizeof(str)-1)) + +#define GETNEXT_PARAM() \ + while ( *param && ( *param != ',' ) ) param++; \ + if ( *param ) param++; \ + while ( *param && ( *param == ' ' ) ) param++; \ + if ( *param == 0 ) { SysPrintf( _( "Not enough params for inicommand\n" ) ); return; } + +// +// Typedefs +// +typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 ); + +typedef struct +{ + char * text; + int code; + PATCHTABLEFUNC func; +} PatchTextTable; + +typedef struct +{ + int enabled; + int group; + int type; + int cpu; + int placetopatch; + u32 addr; + u64 data; +} IniPatch; + +// +// Function prototypes +// +void patchFunc_comment( char * text1, char * text2 ); +void patchFunc_gametitle( char * text1, char * text2 ); +void patchFunc_patch( char * text1, char * text2 ); +void patchFunc_fastmemory( char * text1, char * text2 ); +void patchFunc_roundmode( char * text1, char * text2 ); + +void inifile_trim( char * buffer ); + +// +// Variables +// +extern PatchTextTable commands[]; + +extern PatchTextTable dataType[]; + +extern PatchTextTable cpuCore[]; + +extern IniPatch patch[ MAX_PATCH ]; +extern int patchnumber; + + +void applypatch( int place ); +void inifile_read( char * name ); +void inifile_command( char * cmd ); +void resetpatch( void ); + +int AddPatch(int Mode, int Place, int Address, int Size, u64 data); + +void SetFastMemory(int); // iR5900LoadStore.c + +extern u32 g_sseMXCSR, g_sseVUMXCSR; // iR5900.c +void SetCPUState(); +void SetRoundMode(u32 ee, u32 vu); + +#endif /* __PATCH_H__ */ + diff --git a/branches/pcsx2_0.9.2/Plugins.c b/branches/pcsx2_0.9.2/Plugins.c new file mode 100644 index 0000000..ce3aeca --- /dev/null +++ b/branches/pcsx2_0.9.2/Plugins.c @@ -0,0 +1,607 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "GS.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define CheckErr(func) \ + err = SysLibError(); \ + if (err != NULL) { SysMessage (_("%s: Error loading %s: %s"), filename, func, err); return -1; } + +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, name); if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } + +#define TestPS2Esyms(type) { \ + _PS2EgetLibVersion2 PS2EgetLibVersion2; \ + SysLoadSym(drv, "PS2EgetLibType"); CheckErr("PS2EgetLibType"); \ + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) SysLoadSym(drv, "PS2EgetLibVersion2"); CheckErr("PS2EgetLibVersion2"); \ + SysLoadSym(drv, "PS2EgetLibName"); CheckErr("PS2EgetLibName"); \ + if( ((PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff) != PS2E_##type##_VERSION) { \ + SysMessage (_("Can't load '%s', wrong PS2E version (%x != %x)"), filename, (PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff, PS2E_##type##_VERSION); return -1; \ + } \ +} + +static char *err; +static int errval; + +void *GSplugin; + +void CALLBACK GS_printf(int timeout, char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + SysPrintf(msg); +} + +s32 CALLBACK GS_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK GS_keyEvent(keyEvent *ev) {} +void CALLBACK GS_makeSnapshot(char *path) {} +void CALLBACK GS_irqCallback(void (*callback)()) {} +void CALLBACK GS_configure() {} +void CALLBACK GS_about() {} +long CALLBACK GS_test() { return 0; } + +#define LoadGSsym1(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 1); + +#define LoadGSsym0(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); \ + if (GS##dest == NULL) GS##dest = (_GS##dest) GS_##dest; + +#define LoadGSsymN(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); + +int LoadGSplugin(char *filename) { + void *drv; + + GSplugin = SysLoadLibrary(filename); + if (GSplugin == NULL) { SysMessage (_("Could Not Load GS Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = GSplugin; + TestPS2Esyms(GS); + LoadGSsym1(init, "GSinit"); + LoadGSsym1(shutdown, "GSshutdown"); + LoadGSsym1(open, "GSopen"); + LoadGSsym1(close, "GSclose"); + LoadGSsym1(gifTransfer1, "GSgifTransfer1"); + LoadGSsym1(gifTransfer2, "GSgifTransfer2"); + LoadGSsym1(gifTransfer3, "GSgifTransfer3"); + LoadGSsym1(readFIFO, "GSreadFIFO"); + LoadGSsymN(readFIFO2, "GSreadFIFO2"); // optional + LoadGSsym1(vsync, "GSvsync"); + + LoadGSsym0(keyEvent, "GSkeyEvent"); + LoadGSsymN(changeSaveState, "GSchangeSaveState"); + LoadGSsymN(gifSoftReset, "GSgifSoftReset"); + LoadGSsym0(makeSnapshot, "GSmakeSnapshot"); + LoadGSsym0(irqCallback, "GSirqCallback"); + LoadGSsym0(printf, "GSprintf"); + LoadGSsym1(setBaseMem, "GSsetBaseMem"); + LoadGSsymN(setGameCRC, "GSsetGameCRC"); + LoadGSsym1(reset, "GSreset"); + LoadGSsym1(writeCSR, "GSwriteCSR"); + LoadGSsymN(makeSnapshot2,"GSmakeSnapshot2"); + LoadGSsymN(getDriverInfo,"GSgetDriverInfo"); + + LoadGSsymN(setFrameSkip, "GSsetFrameSkip"); + +#ifdef __WIN32__ + LoadGSsymN(setWindowInfo,"GSsetWindowInfo"); +#endif + LoadGSsym0(freeze, "GSfreeze"); + LoadGSsym0(configure, "GSconfigure"); + LoadGSsym0(about, "GSabout"); + LoadGSsym0(test, "GStest"); + + return 0; +} + +void *PAD1plugin; + +void CALLBACK PAD1_configure() {} +void CALLBACK PAD1_about() {} +long CALLBACK PAD1_test() { return 0; } + +#define LoadPAD1sym1(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 1); + +#define LoadPAD1sym0(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); \ + if (PAD1##dest == NULL) PAD1##dest = (_PAD##dest) PAD1_##dest; + +#define LoadPAD1symN(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); + +int LoadPAD1plugin(char *filename) { + void *drv; + + PAD1plugin = SysLoadLibrary(filename); + if (PAD1plugin == NULL) { SysMessage (_("Could Not Load PAD1 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD1plugin; + TestPS2Esyms(PAD); + LoadPAD1sym1(init, "PADinit"); + LoadPAD1sym1(shutdown, "PADshutdown"); + LoadPAD1sym1(open, "PADopen"); + LoadPAD1sym1(close, "PADclose"); + LoadPAD1sym1(keyEvent, "PADkeyEvent"); + LoadPAD1sym1(startPoll, "PADstartPoll"); + LoadPAD1sym1(poll, "PADpoll"); + LoadPAD1sym1(query, "PADquery"); + + LoadPAD1symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD1sym0(configure, "PADconfigure"); + LoadPAD1sym0(about, "PADabout"); + LoadPAD1sym0(test, "PADtest"); + + return 0; +} + +void *PAD2plugin; + +void CALLBACK PAD2_configure() {} +void CALLBACK PAD2_about() {} +long CALLBACK PAD2_test() { return 0; } + +#define LoadPAD2sym1(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 1); + +#define LoadPAD2sym0(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); \ + if (PAD2##dest == NULL) PAD2##dest = (_PAD##dest) PAD2_##dest; + +#define LoadPAD2symN(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); + +int LoadPAD2plugin(char *filename) { + void *drv; + + PAD2plugin = SysLoadLibrary(filename); + if (PAD2plugin == NULL) { SysMessage (_("Could Not Load PAD2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD2plugin; + TestPS2Esyms(PAD); + LoadPAD2sym1(init, "PADinit"); + LoadPAD2sym1(shutdown, "PADshutdown"); + LoadPAD2sym1(open, "PADopen"); + LoadPAD2sym1(close, "PADclose"); + LoadPAD2sym1(keyEvent, "PADkeyEvent"); + LoadPAD2sym1(startPoll, "PADstartPoll"); + LoadPAD2sym1(poll, "PADpoll"); + LoadPAD2sym1(query, "PADquery"); + + LoadPAD2symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD2sym0(configure, "PADconfigure"); + LoadPAD2sym0(about, "PADabout"); + LoadPAD2sym0(test, "PADtest"); + + return 0; +} + +void *SPU2plugin; + +s32 CALLBACK SPU2_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK SPU2_configure() {} +void CALLBACK SPU2_about() {} +s32 CALLBACK SPU2_test() { return 0; } + +#define LoadSPU2sym1(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 1); + +#define LoadSPU2sym0(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); \ + if (SPU2##dest == NULL) SPU2##dest = (_SPU2##dest) SPU2_##dest; + +#define LoadSPU2symN(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); + +int LoadSPU2plugin(char *filename) { + void *drv; + + SPU2plugin = SysLoadLibrary(filename); + if (SPU2plugin == NULL) { SysMessage (_("Could Not Load SPU2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = SPU2plugin; + TestPS2Esyms(SPU2); + LoadSPU2sym1(init, "SPU2init"); + LoadSPU2sym1(shutdown, "SPU2shutdown"); + LoadSPU2sym1(open, "SPU2open"); + LoadSPU2sym1(close, "SPU2close"); + LoadSPU2sym1(write, "SPU2write"); + LoadSPU2sym1(read, "SPU2read"); + LoadSPU2sym1(readDMA4Mem, "SPU2readDMA4Mem"); + LoadSPU2sym1(writeDMA4Mem, "SPU2writeDMA4Mem"); + LoadSPU2sym1(interruptDMA4,"SPU2interruptDMA4"); + LoadSPU2sym1(readDMA7Mem, "SPU2readDMA7Mem"); + LoadSPU2sym1(writeDMA7Mem, "SPU2writeDMA7Mem"); + LoadSPU2sym1(interruptDMA7,"SPU2interruptDMA7"); + LoadSPU2sym1(ReadMemAddr, "SPU2ReadMemAddr"); + LoadSPU2sym1(WriteMemAddr, "SPU2WriteMemAddr"); + LoadSPU2sym1(irqCallback, "SPU2irqCallback"); + + LoadSPU2sym0(freeze, "SPU2freeze"); + LoadSPU2sym0(configure, "SPU2configure"); + LoadSPU2sym0(about, "SPU2about"); + LoadSPU2sym0(test, "SPU2test"); + LoadSPU2symN(async, "SPU2async"); + + return 0; +} + +void *CDVDplugin; + +void CALLBACK CDVD_configure() {} +void CALLBACK CDVD_about() {} +long CALLBACK CDVD_test() { return 0; } + +#define LoadCDVDsym1(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 1); + +#define LoadCDVDsym0(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + if (CDVD##dest == NULL) CDVD##dest = (_CDVD##dest) CDVD_##dest; + +#define LoadCDVDsymN(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + +int LoadCDVDplugin(char *filename) { + void *drv; + + CDVDplugin = SysLoadLibrary(filename); + if (CDVDplugin == NULL) { SysMessage (_("Could Not Load CDVD Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = CDVDplugin; + TestPS2Esyms(CDVD); + LoadCDVDsym1(init, "CDVDinit"); + LoadCDVDsym1(shutdown, "CDVDshutdown"); + LoadCDVDsym1(open, "CDVDopen"); + LoadCDVDsym1(close, "CDVDclose"); + LoadCDVDsym1(readTrack, "CDVDreadTrack"); + LoadCDVDsym1(getBuffer, "CDVDgetBuffer"); + LoadCDVDsym1(readSubQ, "CDVDreadSubQ"); + LoadCDVDsym1(getTN, "CDVDgetTN"); + LoadCDVDsym1(getTD, "CDVDgetTD"); + LoadCDVDsym1(getTOC, "CDVDgetTOC"); + LoadCDVDsym1(getDiskType, "CDVDgetDiskType"); + LoadCDVDsym1(getTrayStatus, "CDVDgetTrayStatus"); + LoadCDVDsym1(ctrlTrayOpen, "CDVDctrlTrayOpen"); + LoadCDVDsym1(ctrlTrayClose, "CDVDctrlTrayClose"); + + LoadCDVDsym0(configure, "CDVDconfigure"); + LoadCDVDsym0(about, "CDVDabout"); + LoadCDVDsym0(test, "CDVDtest"); + LoadCDVDsymN(newDiskCB, "CDVDnewDiskCB"); + + return 0; +} + +void *DEV9plugin; + +s32 CALLBACK DEV9_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK DEV9_configure() {} +void CALLBACK DEV9_about() {} +long CALLBACK DEV9_test() { return 0; } + +#define LoadDEV9sym1(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 1); + +#define LoadDEV9sym0(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 0); \ + if (DEV9##dest == NULL) DEV9##dest = (_DEV9##dest) DEV9_##dest; + +int LoadDEV9plugin(char *filename) { + void *drv; + + DEV9plugin = SysLoadLibrary(filename); + if (DEV9plugin == NULL) { SysMessage (_("Could Not Load DEV9 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = DEV9plugin; + TestPS2Esyms(DEV9); + LoadDEV9sym1(init, "DEV9init"); + LoadDEV9sym1(shutdown, "DEV9shutdown"); + LoadDEV9sym1(open, "DEV9open"); + LoadDEV9sym1(close, "DEV9close"); + LoadDEV9sym1(read8, "DEV9read8"); + LoadDEV9sym1(read16, "DEV9read16"); + LoadDEV9sym1(read32, "DEV9read32"); + LoadDEV9sym1(write8, "DEV9write8"); + LoadDEV9sym1(write16, "DEV9write16"); + LoadDEV9sym1(write32, "DEV9write32"); + LoadDEV9sym1(readDMA8Mem, "DEV9readDMA8Mem"); + LoadDEV9sym1(writeDMA8Mem, "DEV9writeDMA8Mem"); + LoadDEV9sym1(irqCallback, "DEV9irqCallback"); + LoadDEV9sym1(irqHandler, "DEV9irqHandler"); + + LoadDEV9sym0(freeze, "DEV9freeze"); + LoadDEV9sym0(configure, "DEV9configure"); + LoadDEV9sym0(about, "DEV9about"); + LoadDEV9sym0(test, "DEV9test"); + + return 0; +} + +void *USBplugin; + +s32 CALLBACK USB_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK USB_configure() {} +void CALLBACK USB_about() {} +long CALLBACK USB_test() { return 0; } + +#define LoadUSBsym1(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 1); + +#define LoadUSBsym0(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 0); \ + if (USB##dest == NULL) USB##dest = (_USB##dest) USB_##dest; + +int LoadUSBplugin(char *filename) { + void *drv; + + USBplugin = SysLoadLibrary(filename); + if (USBplugin == NULL) { SysMessage (_("Could Not Load USB Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = USBplugin; + TestPS2Esyms(USB); + LoadUSBsym1(init, "USBinit"); + LoadUSBsym1(shutdown, "USBshutdown"); + LoadUSBsym1(open, "USBopen"); + LoadUSBsym1(close, "USBclose"); + LoadUSBsym1(read8, "USBread8"); + LoadUSBsym1(read16, "USBread16"); + LoadUSBsym1(read32, "USBread32"); + LoadUSBsym1(write8, "USBwrite8"); + LoadUSBsym1(write16, "USBwrite16"); + LoadUSBsym1(write32, "USBwrite32"); + LoadUSBsym1(irqCallback, "USBirqCallback"); + LoadUSBsym1(irqHandler, "USBirqHandler"); + LoadUSBsym1(setRAM, "USBsetRAM"); + + LoadUSBsym0(freeze, "USBfreeze"); + LoadUSBsym0(configure, "USBconfigure"); + LoadUSBsym0(about, "USBabout"); + LoadUSBsym0(test, "USBtest"); + + return 0; +} +void *FWplugin; + +s32 CALLBACK FW_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK FW_configure() {} +void CALLBACK FW_about() {} +long CALLBACK FW_test() { return 0; } + +#define LoadFWsym1(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 1); + +#define LoadFWsym0(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 0); \ + if (FW##dest == NULL) FW##dest = (_FW##dest) FW_##dest; + +int LoadFWplugin(char *filename) { + void *drv; + + FWplugin = SysLoadLibrary(filename); + if (FWplugin == NULL) { SysMessage (_("Could Not Load FW Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = FWplugin; + TestPS2Esyms(FW); + LoadFWsym1(init, "FWinit"); + LoadFWsym1(shutdown, "FWshutdown"); + LoadFWsym1(open, "FWopen"); + LoadFWsym1(close, "FWclose"); + LoadFWsym1(read32, "FWread32"); + LoadFWsym1(write32, "FWwrite32"); + LoadFWsym1(irqCallback, "FWirqCallback"); + + LoadFWsym0(freeze, "FWfreeze"); + LoadFWsym0(configure, "FWconfigure"); + LoadFWsym0(about, "FWabout"); + LoadFWsym0(test, "FWtest"); + + return 0; +} +static int loadp=0; + +int InitPlugins() { + int ret; + + if( GSsetBaseMem ) { + + if( CHECK_MULTIGS ) { + extern u8 g_MTGSMem[]; + GSsetBaseMem(g_MTGSMem); + } + else { + GSsetBaseMem(PS2MEM_GS); + } + } + + ret = GSinit(); + if (ret != 0) { SysMessage (_("GSinit error: %d"), ret); return -1; } + ret = PAD1init(1); + if (ret != 0) { SysMessage (_("PAD1init error: %d"), ret); return -1; } + ret = PAD2init(2); + if (ret != 0) { SysMessage (_("PAD2init error: %d"), ret); return -1; } + ret = SPU2init(); + if (ret != 0) { SysMessage (_("SPU2init error: %d"), ret); return -1; } + ret = CDVDinit(); + if (ret != 0) { SysMessage (_("CDVDinit error: %d"), ret); return -1; } + ret = DEV9init(); + if (ret != 0) { SysMessage (_("DEV9init error: %d"), ret); return -1; } + ret = USBinit(); + if (ret != 0) { SysMessage (_("USBinit error: %d"), ret); return -1; } + ret = FWinit(); + if (ret != 0) { SysMessage (_("FWinit error: %d"), ret); return -1; } + return 0; +} + +void ShutdownPlugins() { + GSshutdown(); + PAD1shutdown(); + PAD2shutdown(); + SPU2shutdown(); + CDVDshutdown(); + DEV9shutdown(); + USBshutdown(); + FWshutdown(); +} + +int LoadPlugins() { + char Plugin[256]; + + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.GS); + if (LoadGSplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD1); + if (LoadPAD1plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD2); + if (LoadPAD2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.SPU2); + if (LoadSPU2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.CDVD); + if (LoadCDVDplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.DEV9); + if (LoadDEV9plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.USB); + if (LoadUSBplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.FW); + if (LoadFWplugin(Plugin) == -1) return -1; + if (InitPlugins() == -1) return -1; + + loadp=1; + + return 0; +} + +long pDsp; +static pluginsopened = 0; +extern void spu2DMA4Irq(); +extern void spu2DMA7Irq(); +extern void spu2Irq(); +extern HANDLE g_hGSOpen, g_hGSDone; +int OpenPlugins() { + GSdriverInfo info; + int ret; + + if (loadp == 0) return -1; + + //first we need the data + if (CDVDnewDiskCB) CDVDnewDiskCB(cdvdNewDiskCB); + ret = CDVDopen(); + if (ret != 0) { SysMessage (_("Error Opening CDVD Plugin")); return -1; } + cdvdNewDiskCB(); + + //video + GSirqCallback(gsIrq); + + // make sure only call open once per instance + if( !pluginsopened ) { + if( CHECK_MULTIGS ) { + SetEvent(g_hGSOpen); + WaitForSingleObject(g_hGSDone, INFINITE); + } + else { + ret = GSopen((void *)&pDsp, "PCSX2", 0); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); return -1; } + } + } + + //then the user input + if (GSgetDriverInfo) { + GSgetDriverInfo(&info); + if (PAD1gsDriverInfo) PAD1gsDriverInfo(&info); + if (PAD2gsDriverInfo) PAD2gsDriverInfo(&info); + } + ret = PAD1open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD1 Plugin")); return -1; } + ret = PAD2open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD2 Plugin")); return -1; } + + //the sound + + SPU2irqCallback(spu2Irq,spu2DMA4Irq,spu2DMA7Irq); + ret = SPU2open((void*)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening SPU2 Plugin")); return -1; } + + //and last the dev9 + DEV9irqCallback(dev9Irq); + dev9Handler = DEV9irqHandler(); + ret = DEV9open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening DEV9 Plugin")); return -1; } + + USBirqCallback(usbIrq); + usbHandler = USBirqHandler(); + USBsetRAM(psxM); + ret = USBopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening USB Plugin")); return -1; } + + FWirqCallback(fwIrq); + ret = FWopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening FW Plugin")); return -1; } + + pluginsopened = 1; + return 0; +} + +extern void gsWaitGS(); + +void ClosePlugins() +{ + gsWaitGS(); + + CDVDclose(); + DEV9close(); + USBclose(); + FWclose(); + SPU2close(); + PAD1close(); + PAD2close(); +} + +void ResetPlugins() { + gsWaitGS(); + + ShutdownPlugins(); + InitPlugins(); +} + +void ReleasePlugins() { + if (loadp == 0) return; + + if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL || + SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL || + USBplugin == NULL || FWplugin == NULL) return; + + ShutdownPlugins(); + + SysCloseLibrary(GSplugin); GSplugin = NULL; + SysCloseLibrary(PAD1plugin); PAD1plugin = NULL; + SysCloseLibrary(PAD2plugin); PAD2plugin = NULL; + SysCloseLibrary(SPU2plugin); SPU2plugin = NULL; + SysCloseLibrary(CDVDplugin); CDVDplugin = NULL; + SysCloseLibrary(DEV9plugin); DEV9plugin = NULL; + SysCloseLibrary(USBplugin); USBplugin = NULL; + SysCloseLibrary(FWplugin); FWplugin = NULL; + loadp=0; +} diff --git a/branches/pcsx2_0.9.2/Plugins.h b/branches/pcsx2_0.9.2/Plugins.h new file mode 100644 index 0000000..0f282f2 --- /dev/null +++ b/branches/pcsx2_0.9.2/Plugins.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PLUGINS_H__ +#define __PLUGINS_H__ + +#define PLUGINtypedefs +#define PLUGINfuncs +#include "PS2Edefs.h" + +int LoadPlugins(); +void ReleasePlugins(); +int OpenPlugins(); +void ClosePlugins(); +void ResetPlugins(); + +#endif /* __PLUGINS_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxBios.c b/branches/pcsx2_0.9.2/PsxBios.c new file mode 100644 index 0000000..2e1495e --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxBios.c @@ -0,0 +1,300 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "PsxCommon.h" + +char *biosA0n[256] = { +// 0x00 + "open", "lseek", "read", "write", + "close", "ioctl", "exit", "sys_a0_07", + "getc", "putc", "todigit", "atof", + "strtoul", "strtol", "abs", "labs", +// 0x10 + "atoi", "atol", "atob", "setjmp", + "longjmp", "strcat", "strncat", "strcmp", + "strncmp", "strcpy", "strncpy", "strlen", + "index", "rindex", "strchr", "strrchr", +// 0x20 + "strpbrk", "strspn", "strcspn", "strtok", + "strstr", "toupper", "tolower", "bcopy", + "bzero", "bcmp", "memcpy", "memset", + "memmove", "memcmp", "memchr", "rand", +// 0x30 + "srand", "qsort", "strtod", "malloc", + "free", "lsearch", "bsearch", "calloc", + "realloc", "InitHeap", "_exit", "getchar", + "putchar", "gets", "puts", "printf", +// 0x40 + "sys_a0_40", "LoadTest", "Load", "Exec", + "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram", + "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets", + "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f", +// 0x50 + "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53", + "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57", + "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init", + "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open", +// 0x60 + "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile", + "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write", + "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase", + "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f", +// 0x70 + "_bu_init", "_96_init", "_96_remove", "sys_a0_73", + "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77", + "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b", + "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f", +// 0x80 + "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83", + "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87", + "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b", + "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f", +// 0x90 + "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93", + "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide", + "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b", + "SetConf", "GetConf", "sys_a0_9e", "SetMem", +// 0xa0 + "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr", + "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0", + "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info", + "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af", +// 0xb0 + "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3", + "?? sub_function", +}; + +char *biosB0n[256] = { +// 0x00 + "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03", + "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent", + "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent", + "EnableEvent", "DisableEvent", "OpenTh", "CloseTh", +// 0x10 + "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD", + "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption", + "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b", + "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f", +// 0x20 + "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23", + "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27", + "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b", + "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f", +// 0x30 + "sys_b0_30", "sys_b0_31", "open", "lseek", + "read", "write", "close", "ioctl", + "exit", "sys_b0_39", "getc", "putc", + "getchar", "putchar", "gets", "puts", +// 0x40 + "cd", "format", "firstfile", "nextfile", + "rename", "delete", "undelete", "AddDevice", + "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD", + "StopCARD", "sys_b0_4d", "_card_write", "_card_read", +// 0x50 + "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53", + "_get_errno", "_get_error", "GetC0Table", "GetB0Table", + "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD", + "_card_status", "_card_wait", +}; + +char *biosC0n[256] = { +// 0x00 + "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP", + "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler", + "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError", + "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f", +// 0x10 + "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut", + "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc", + "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect", + "PatchAOTable", +}; + +//#define r0 (psxRegs.GPR.n.r0) +#define at (psxRegs.GPR.n.at) +#define v0 (psxRegs.GPR.n.v0) +#define v1 (psxRegs.GPR.n.v1) +#define a0 (psxRegs.GPR.n.a0) +#define a1 (psxRegs.GPR.n.a1) +#define a2 (psxRegs.GPR.n.a2) +#define a3 (psxRegs.GPR.n.a3) +#define t0 (psxRegs.GPR.n.t0) +#define t1 (psxRegs.GPR.n.t1) +#define t2 (psxRegs.GPR.n.t2) +#define t3 (psxRegs.GPR.n.t3) +#define t4 (psxRegs.GPR.n.t4) +#define t5 (psxRegs.GPR.n.t5) +#define t6 (psxRegs.GPR.n.t6) +#define t7 (psxRegs.GPR.n.t7) +#define s0 (psxRegs.GPR.n.s0) +#define s1 (psxRegs.GPR.n.s1) +#define s2 (psxRegs.GPR.n.s2) +#define s3 (psxRegs.GPR.n.s3) +#define s4 (psxRegs.GPR.n.s4) +#define s5 (psxRegs.GPR.n.s5) +#define s6 (psxRegs.GPR.n.s6) +#define s7 (psxRegs.GPR.n.s7) +#define t8 (psxRegs.GPR.n.t6) +#define t9 (psxRegs.GPR.n.t7) +#define k0 (psxRegs.GPR.n.k0) +#define k1 (psxRegs.GPR.n.k1) +#define gp (psxRegs.GPR.n.gp) +#define sp (psxRegs.GPR.n.sp) +#define fp (psxRegs.GPR.n.s8) +#define ra (psxRegs.GPR.n.ra) +#define pc0 (psxRegs.pc) + +#define Ra0 ((char*)PSXM(a0)) +#define Ra1 ((char*)PSXM(a1)) +#define Ra2 ((char*)PSXM(a2)) +#define Ra3 ((char*)PSXM(a3)) +#define Rv0 ((char*)PSXM(v0)) +#define Rsp ((char*)PSXM(sp)) + +void bios_write() { // 0x35/0x03 + + + if (a0 == 1) { // stdout + char *ptr = Ra1; + + while (a2 > 0) { + SysPrintf(COLOR_RED "%c" COLOR_RESET, *ptr++); a2--; + } + pc0 = ra; return; + } +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("bios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2); +#endif + + v0 = -1; + + pc0 = ra; +} + +void bios_printf() { // 3f + char tmp[1024]; + char tmp2[1024]; + unsigned long save[4]; + char *ptmp = tmp; + int n=1, i=0, j; + + memcpy(save, (char*)PSXM(sp), 4*4); + psxMu32(sp) = a0; + psxMu32(sp + 4) = a1; + psxMu32(sp + 8) = a2; + psxMu32(sp + 12) = a3; + + while (Ra0[i]) { + switch (Ra0[i]) { + case '%': + j = 0; + tmp2[j++] = '%'; +_start: + switch (Ra0[++i]) { + case '.': + case 'l': + tmp2[j++] = Ra0[i]; goto _start; + default: + if (Ra0[i] >= '0' && Ra0[i] <= '9') { + tmp2[j++] = Ra0[i]; + goto _start; + } + break; + } + tmp2[j++] = Ra0[i]; + tmp2[j] = 0; + + switch (Ra0[i]) { + case 'f': case 'F': + ptmp+= sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break; + case 'a': case 'A': + case 'e': case 'E': + case 'g': case 'G': + ptmp+= sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break; + case 'p': + case 'i': + case 'd': case 'D': + case 'o': case 'O': + case 'x': case 'X': + ptmp+= sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break; + case 'c': + ptmp+= sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break; + case 's': + ptmp+= sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break; + case '%': + *ptmp++ = Ra0[i]; break; + } + i++; + break; + default: + *ptmp++ = Ra0[i++]; + } + } + *ptmp = 0; + + memcpy((char*)PSXM(sp), save, 4*4); + + SysPrintf(COLOR_RED "%s" COLOR_RESET, tmp); + + pc0 = ra; +} + +void bios_putchar () { // 3d + char tmp[12]; + + sprintf (tmp,"%c",(char)a0); + SysPrintf(tmp); + + pc0 = ra; +} + +void bios_puts () { // 3e/3f + SysPrintf(Ra0); + + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +void psxBiosInit() { + int i; + + for(i = 0; i < 256; i++) { + biosA0[i] = NULL; + biosB0[i] = NULL; + biosC0[i] = NULL; + } + biosA0[0x3e] = bios_puts; + biosA0[0x3f] = bios_printf; + + biosB0[0x3d] = bios_putchar; + biosB0[0x3f] = bios_puts; + +} + +void psxBiosShutdown() { +} + diff --git a/branches/pcsx2_0.9.2/PsxBios.h b/branches/pcsx2_0.9.2/PsxBios.h new file mode 100644 index 0000000..1ac0fe7 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxBios.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +extern char *biosA0n[256]; +extern char *biosB0n[256]; +extern char *biosC0n[256]; + +void psxBiosInit(); +void psxBiosShutdown(); +void psxBiosException(); +void psxBiosFreeze(int Mode); + +extern void (*biosA0[256])(); +extern void (*biosB0[256])(); +extern void (*biosC0[256])(); + +#endif /* __PSXBIOS_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxBios2.h b/branches/pcsx2_0.9.2/PsxBios2.h new file mode 100644 index 0000000..a0c6640 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxBios2.h @@ -0,0 +1,94 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/***** sysmem imageInfo +00000800: 00 16 00 00 70 14 00 00 01 01 00 00 01 00 00 00 +0000 next: .word ? //00001600 +0004 name: .word ? //00001470 +0008 version: .half ? //0101 +000A flags: .half ? //---- +000C index: .half ? //0001 +000E field_E: .half ? //---- +00000810: 90 08 00 00 A0 94 00 00 30 08 00 00 40 0C 00 00 +0010 entry: .word ? //00000890 +0014 gp_value: .word ? //000094A0 +0018 p1_vaddr: .word ? //00000830 +001C text_size: .word ? //00000C40 +00000820: 40 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 +0020 data_size: .word ? //00000040 +0024 bss_size: .word ? //00000010 +0028 field_28: .word ? //-------- +002C field_2C: .word ? //-------- +*****/ + +#ifndef __PSX_BIOS_H__ +#define __PSX_BIOS_H__ + +typedef struct { + u32 next, //+00 + name; //+04 + u16 version, //+08 + flags, //+0A + index, //+0C + _unkE; //+0E + u32 entry, //+10 + _gp, //+14 + vaddr, //+18 + text_size, //+1C + data_size, //+20 + bss_size, //+24 + _pad28, //+28 + _pad2C; //+2C +} irxImageInfo; //=30 + +typedef struct { + int active; + u32 server; + u32 fhandler; +} _sifServer; + +#define SIF_SERVERS 32 + +_sifServer sifServer[SIF_SERVERS]; + +// max modules/funcs + +#define IRX_MODULES 64 +#define IRX_FUNCS 256 + +typedef struct { + u32 num; + u32 entry; +} irxFunc; + +typedef struct { + int active; + u32 name[2]; + irxFunc funcs[IRX_FUNCS]; +} irxModule; + +irxModule irxMod[IRX_MODULES]; + + +void iopModulesInit(); +int iopSetImportFunc(u32 *ptr); +int iopSetExportFunc(u32 *ptr); +void sifServerCall(u32 server, u32 num, char *bin, int insize, char *bout, int outsize); +void sifAddServer(u32 server, u32 fhandler); + +#endif diff --git a/branches/pcsx2_0.9.2/PsxCommon.h b/branches/pcsx2_0.9.2/PsxCommon.h new file mode 100644 index 0000000..d556d63 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxCommon.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#ifdef __WIN32__ +#include +#endif + +#include "PS2Etypes.h" + +#include "System.h" +#include + +long LoadCdBios; +int cdOpenCase; + +#include "Plugins.h" +#include "R3000A.h" +#include "PsxMem.h" +#include "PsxHw.h" +#include "PsxBios.h" +#include "PsxDma.h" +#include "PsxCounters.h" +#include "CdRom.h" +#include "Sio.h" +#include "DebugTools/Debug.h" +#include "PsxSio2.h" +#include "CDVD.h" + +#endif /* __PSXCOMMON_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxCounters.c b/branches/pcsx2_0.9.2/PsxCounters.c new file mode 100644 index 0000000..4aa0efa --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxCounters.c @@ -0,0 +1,631 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "PsxCommon.h" + +psxCounter psxCounters[8]; +u32 psxNextCounter, psxNextsCounter; +static int cnts = 6; +u8 psxhblankgate = 0; +u8 psxvblankgate = 0; +u8 psxcntmask = 0; + +static void psxRcntUpd16(u32 index) { + //psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[index].rate); + + //psxCounters[index].Cycle = (0xffff - psxCounters[index].count) * psxCounters[index].rate; + //psxCounters[index].CycleT = (psxCounters[index].target - psxCounters[index].count) * psxCounters[index].rate; +} + +static void psxRcntUpd32(u32 index) { + //psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[index].rate); + + //psxCounters[index].Cycle = (0xfffee000 - psxCounters[index].count) * psxCounters[index].rate; + //psxCounters[index].CycleT = (psxCounters[index].target - psxCounters[index].count) * psxCounters[index].rate; +} + +static void psxRcntReset16(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd16(index); +} + +static void psxRcntReset32(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd32(index); +} + +static void psxRcntSet() { + u32 c; + int i; + + psxNextCounter = 0xffffffff; + psxNextsCounter = psxRegs.cycle; + + for (i=0; i<3; i++) { + c = (u32)(0xffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + //if(psxCounters[i].mode & 0x0800) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + for (i=3; i<6; i++) { + c = (u32)(0xfffee000 - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + //if(psxCounters[i].mode & 0x0800) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + + c = (u32)(psxCounters[6].CycleT - (psxRegs.cycle - psxCounters[6].sCycleT)) ; + if (c < psxNextCounter) { + psxNextCounter = c; + } +} + + +void psxRcntInit() { + int i; + + memset(psxCounters, 0, sizeof(psxCounters)); + + for (i=0; i<3; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0x0; + } + for (i=3; i<6; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0x0; + } + + psxCounters[0].interrupt = 0x10; + psxCounters[1].interrupt = 0x20; + psxCounters[2].interrupt = 0x40; + + psxCounters[3].interrupt = 0x04000; + psxCounters[4].interrupt = 0x08000; + psxCounters[5].interrupt = 0x10000; + + if (SPU2async != NULL) { + cnts = 7; + + psxCounters[6].rate = 1; + psxCounters[6].CycleT = 48000; + psxCounters[6].mode = 0x8; + } else cnts = 6; + + for (i=0; i<3; i++) + psxCounters[i].sCycleT = psxRegs.cycle; + for (i=3; i<6; i++) + psxCounters[i].sCycleT = psxRegs.cycle; + for (i=6; i> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxCounters[i].mode &= ~0x10000000; + psxRcntUpd16(i); + break; + case 0x3: //GATE_ON_Start + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxCounters[i].mode &= ~0x10000000; + psxRcntUpd32(i); + break; + case 0x3: //GATE_ON_Start + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} +void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts + int i = counter; + + if(counter < 3){ //Gates for 16bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + SysPrintf("PSX Gate %x\n", i); + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x3: //GATE_ON_Start + psxCounters[i].mode &= ~0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + SysPrintf("PSX Gate %x\n", i); + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x3: //GATE_ON_Start + psxCounters[i].mode &= ~0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} + +void _testRcnt16target(int i) { + +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount16(i), psxCounters[i].target); +#endif + + psxCounters[i].mode|= 0x0800; // Target flag + if(psxCounters[i].mode & 0x80) + if (psxCounters[i].mode & 0x10)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + if (psxCounters[i].mode & 0x10) // Target interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd16(i); + return; + } + if(!(psxCounters[i].mode & 0x40))psxcntmask |= (1<= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle) / psxCounters[i].rate, psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count); +#endif + + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80) + psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxcntmask &= ~(1<= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount32(i), psxCounters[i].target); +#endif + + psxCounters[i].mode|= 0x0800; // Target flag + if(psxCounters[i].mode & 0x80) + if (psxCounters[i].mode & 0x10)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + + if (psxCounters[i].mode & 0x10) // Target interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + + + if (psxCounters[i].mode & 0x8) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd32(i); + return; + } + if(!(psxCounters[i].mode & 0x40))psxcntmask |= (1<= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount32(i), psxCounters[i].count); +#endif + + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80) + psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxcntmask &= ~(1<= psxCounters[i].target){ + _testRcnt16target(i); + } + + if ((u32)psxRcntCycles(i) >= 0xffff) + _testRcnt16overflow(i); +} + +void _testRcnt32(int i) { + + if(!(psxHu32(0x1070) & psxCounters[i].interrupt)) { + psxCounters[i].mode &= ~0x1800; + psxCounters[i].mode |= 0x400; + } + if (!(psxcntmask & (1<= psxCounters[i].target){ + _testRcnt32target(i); + } + + if (psxRcntCycles(i) >= 0xfffee000) + _testRcnt32overflow(i); +} + +void psxRcntUpdate() { + int i; + for (i=0; i<=5; i++) { + psxCounters[i].count += (psxRegs.cycle - psxCounters[i].sCycleT) / psxCounters[i].rate; + psxCounters[i].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[i].rate); + } + _testRcnt16(0); + _testRcnt16(1); + _testRcnt16(2); + _testRcnt32(3); + _testRcnt32(4); + _testRcnt32(5); + + if (cnts >= 7 && (psxRegs.cycle - psxCounters[6].sCycleT) >= psxCounters[6].CycleT) { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);//(u32)(psxRegs.cycle - psxNextsCounter)); + psxCounters[6].sCycleT = psxRegs.cycle; + } + + psxRcntSet(); +} + +void psxRcntWcount16(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif + SysPrintf("Write to 16bit count reg counter %x\n",index); + psxCounters[index].count = value & 0xffff; + SysPrintf("Counter %x count write %x\n", index, value); + psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWcount32(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif + SysPrintf("Write to 32bit count reg counter %x\n", index); + psxCounters[index].count = value; + SysPrintf("Counter %x count write %x\n", index, value); + psxRcntUpd32(index); + psxRcntSet(); +} + +void psxRcnt0Wmode(u32 value) { +#ifdef PSXCNT_LOG + //PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 0 Value write %x\n", value & 0x1c00); + } + + psxCounters[0].mode = value; + psxCounters[0].mode|= 0x0400; + psxCounters[0].rate = 1; + psxcntmask &= ~(1); + if(value & 0x100) psxCounters[0].rate = PSXPIXEL; + + if(psxCounters[0].mode & 0x1){ + SysPrintf("Gate Check set on Counter 0\n"); + psxCounters[0].mode|= 0x1000000; + psxhblankgate |= 1; + }else + psxhblankgate &= ~1; + + psxCounters[0].count = 0; + psxRcntUpd16(0); + psxRcntSet(); + //} +} + +void psxRcnt1Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[1] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 1 Value write %x\n", value & 0x1c00); + } + + psxCounters[1].mode = value; + psxCounters[1].mode|= 0x0400; + psxCounters[1].rate = 1; + psxcntmask &= ~(1<<1); + if(value & 0x100)psxCounters[1].rate = PSXHBLANK; + + if(psxCounters[1].mode & 0x1){ + SysPrintf("Gate Check set on Counter 1\n"); + psxCounters[1].mode|= 0x1000000; + psxvblankgate |= 1<<1; + }else + psxvblankgate &= ~(1<<1); + + psxCounters[1].count = 0; + psxRcntUpd16(1); + psxRcntSet(); + //} +} + +void psxRcnt2Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[2] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 2 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<2); + psxCounters[2].mode = value; + psxCounters[2].mode|= 0x0400; + + switch(value & 0x200){ + case 0x200: + psxCounters[2].rate = 8; + break; + case 0x000: + psxCounters[2].rate = 1; + break; + } + + if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C2, disabling\n"); + psxCounters[2].mode|= 0x1000000; + } + // Need to set a rate and target + psxCounters[2].count = 0; + psxRcntUpd16(2); + psxRcntSet(); +} + +void psxRcnt3Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[3] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 3 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<3); + psxCounters[3].mode = value; + psxCounters[3].rate = 1; + psxCounters[3].mode|= 0x0400; + + if(value & 0x100)psxCounters[3].rate = PSXHBLANK; + + if(psxCounters[3].mode & 0x1){ + SysPrintf("Gate Check set on Counter 3\n"); + psxCounters[3].mode|= 0x1000000; + psxvblankgate |= 1<<3; + }else + psxvblankgate &= ~(1<<3); + + psxCounters[3].count = 0; + psxRcntUpd32(3); + psxRcntSet(); + //} +} + +void psxRcnt4Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[4] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 4 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<4); + psxCounters[4].mode = value; + psxCounters[4].mode|= 0x0400; + + switch(value & 0x6000){ + case 0x0000: + psxCounters[4].rate = 1; + break; + case 0x2000: + psxCounters[4].rate = 8; + break; + case 0x4000: + psxCounters[4].rate = 16; + break; + case 0x6000: + psxCounters[4].rate = 256; + break; + } + // Need to set a rate and target + if((psxCounters[4].mode & 0x7) == 0x7 || (psxCounters[4].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C4, disabling\n"); + psxCounters[4].mode|= 0x1000000; + } + psxCounters[4].count = 0; + psxRcntUpd32(4); + psxRcntSet(); +} + +void psxRcnt5Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[5] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 5 Value write %x\n", value & 0x1c00); + } + psxcntmask &= ~(1<<5); + psxCounters[5].mode = value; + psxCounters[5].mode|= 0x0400; + + switch(value & 0x6000){ + case 0x0000: + psxCounters[5].rate = 1; + break; + case 0x2000: + psxCounters[5].rate = 8; + break; + case 0x4000: + psxCounters[5].rate = 16; + break; + case 0x6000: + psxCounters[5].rate = 256; + break; + } + // Need to set a rate and target + if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C5, disabling\n"); + psxCounters[5].mode|= 0x1000000; + } + psxCounters[5].count = 0; + psxRcntUpd32(5); + psxRcntSet(); +} + +void psxRcntWtarget16(int index, u32 value) { + //if(psxCounters[index].sCycleT > psxRegs.cycle) ReSyncTarget(index); +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget16[%ld] = %lx\n", index, value); +#endif + psxCounters[index].target = value & 0xffff; + psxRcntSet(); +} + +void psxRcntWtarget32(int index, u32 value) { + //if(psxCounters[index].sCycleT > psxRegs.cycle) ReSyncTarget(index); + psxCounters[index].target = value; + +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x\n", + index, value, psxRcntRcount32(index), psxCounters[index].sCycleT, psxCounters[index].CycleT); +#endif + //if(index == 5) SysPrintf("Counter 5 tar set CT %x, Tar %x, mode %x, psx.cycle %x\n", psxCounters[index].CycleT + psxCounters[index].sCycleT, psxCounters[index].target, psxCounters[index].mode, psxRegs.cycle); + psxRcntSet(); +} + +u16 psxRcntRcount16(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u16)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +u32 psxRcntRcount32(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u32)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +u64 psxRcntCycles(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u64)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +int psxRcntFreeze(gzFile f, int Mode) { + gzfreezel(psxCounters); + + return 0; +} diff --git a/branches/pcsx2_0.9.2/PsxCounters.h b/branches/pcsx2_0.9.2/PsxCounters.h new file mode 100644 index 0000000..2a616fb --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxCounters.h @@ -0,0 +1,55 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOUNTERS_H__ +#define __PSXCOUNTERS_H__ + +typedef struct { + u32 count, mode, target; + u32 rate, interrupt, otarget; + u32 sCycle, Cycle; + u32 sCycleT, CycleT; +} psxCounter; + +extern psxCounter psxCounters[8]; +extern u32 psxNextCounter, psxNextsCounter; + +void psxRcntInit(); +void psxRcntUpdate(); +void cntspu2async(); +void psxRcntWcount16(int index, u32 value); +void psxRcntWcount32(int index, u32 value); +void psxRcnt0Wmode(u32 value); +void psxRcnt1Wmode(u32 value); +void psxRcnt2Wmode(u32 value); +void psxRcnt3Wmode(u32 value); +void psxRcnt4Wmode(u32 value); +void psxRcnt5Wmode(u32 value); +void psxRcntWtarget16(int index, u32 value); +void psxRcntWtarget32(int index, u32 value); +u16 psxRcntRcount16(int index); +u32 psxRcntRcount32(int index); +u64 psxRcntCycles(int index); +int psxRcntFreeze(gzFile f, int Mode); + +void psxVSyncStart(); +void psxVSyncEnd(); +void psxCheckStartGate(int counter); +void psxCheckEndGate(int counter); + +#endif /* __PSXCOUNTERS_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxDma.c b/branches/pcsx2_0.9.2/PsxDma.c new file mode 100644 index 0000000..a603d95 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxDma.c @@ -0,0 +1,255 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "PsxCommon.h" +// Dma0/1 in Mdec.c +// Dma3 in CdRom.c +// Dma8 in PsxSpd.c +// Dma11/12 in PsxSio2.c +//static int spudmaenable[2]; +void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + + switch (chcr) { + case 0x01000201: //cpu to spu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2writeDMA4Mem((u16 *)PSXM(madr), size*2); + break; + case 0x01000200: //spu to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2readDMA4Mem((u16 *)PSXM(madr), size*2); + psxCpu->Clear(HW_DMA4_MADR, size); + break; + + default: + SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + + //spudmaenable[0] = size; +} + +int psxDma4Interrupt() { + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + psxHu32(0x1070)|= 1<<9; + return 1; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU + HW_DMA2_CHCR &= ~0x01000000; + psxDmaInterrupt(2); +} + +void psxDma6(u32 madr, u32 bcr, u32 chcr) { + u32 *mem = (u32 *)PSXM(madr); + +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr == 0x11000002) { + while (bcr--) { + *mem-- = (madr - 4) & 0xffffff; + madr -= 4; + } + mem++; *mem = 0xffffff; + } else { + // Unknown option +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + } + HW_DMA6_CHCR &= ~0x01000000; + psxDmaInterrupt(6); +} + +void psxDma7(u32 madr, u32 bcr, u32 chcr) { + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 7 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 7 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 7 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + + switch (chcr) { + case 0x01000201: //cpu to spu2 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2writeDMA7Mem((u16 *)PSXM(madr), size*2); + break; + case 0x01000200: //spu2 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2readDMA7Mem((u16 *)PSXM(madr), size*2); + psxCpu->Clear(HW_DMA7_MADR, size); + break; + default: + SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + HW_DMA7_CHCR &= ~0x01000000; + +} + +int psxDma7Interrupt() { + + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + return 1; + +} + +void psxDma9(u32 madr, u32 bcr, u32 chcr) { + + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc000]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR); +#endif + + psHu32(0x1000F240) |= 0x2000; + if (dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void psxDma10(u32 madr, u32 bcr, u32 chcr) { + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc400]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx\n", chcr, madr, bcr); +#endif + + psHu32(0x1000F240) |= 0x4000; + if (dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void psxDma8(u32 madr, u32 bcr, u32 chcr) { + int size; + + switch (chcr & 0x01000201) { + case 0x01000201: //cpu to dev9 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9writeDMA8Mem((u32*)PSXM(madr), size*8); + break; + case 0x01000200: //dev9 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9readDMA8Mem((u32*)PSXM(madr), size*8); + break; +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + HW_DMA8_CHCR &= ~0x01000000; + psxDmaInterrupt2(1); +} + +int dev9Interrupt() { + if (dev9Handler == NULL) goto irq; + if (dev9Handler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<13; + //SBUS + hwIntcIrq(INTC_SBUS); + return 1; +} + +void dev9Irq(int cycles) { + PSX_INT(20, (PSXCLK/cycles)); +} + +int usbInterrupt() { + if (usbHandler == NULL) goto irq; + if (usbHandler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<22; + //SBUS + hwIntcIrq(INTC_SBUS); + return 1; +} + +void usbIrq(int cycles) { + PSX_INT(21, (PSXCLK/cycles)); +} + +void fwIrq() { + psxHu32(0x1070)|= 1<<24; + //SBUS + hwIntcIrq(INTC_SBUS); +} + +void spu2DMA4Irq() { + SPU2interruptDMA4(); + //HW_DMA4_BCR = 0; + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); +} + +void spu2DMA7Irq() { + SPU2interruptDMA7(); + //HW_DMA7_BCR = 0; + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); +} + +void spu2Irq() { + psxHu32(0x1070)|= 1<<9; + //SBUS + hwIntcIrq(INTC_SBUS); +} diff --git a/branches/pcsx2_0.9.2/PsxDma.h b/branches/pcsx2_0.9.2/PsxDma.h new file mode 100644 index 0000000..9db6f17 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxDma.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXDMA_H__ +#define __PSXDMA_H__ + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void psxDma3(u32 madr, u32 bcr, u32 chcr); +void psxDma4(u32 madr, u32 bcr, u32 chcr); +void psxDma6(u32 madr, u32 bcr, u32 chcr); +void psxDma7(u32 madr, u32 bcr, u32 chcr); +void psxDma8(u32 madr, u32 bcr, u32 chcr); +void psxDma9(u32 madr, u32 bcr, u32 chcr); +void psxDma10(u32 madr, u32 bcr, u32 chcr); + +int psxDma4Interrupt(); +int psxDma7Interrupt(); +int dev9Interrupt(); +DEV9handler dev9Handler; +void dev9Irq(int cycles); +int usbInterrupt(); +USBhandler usbHandler; +void usbIrq(int cycles); +void fwIrq(); +void spu2Irq(); + +#endif /* __PSXDMA_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxGPU.c b/branches/pcsx2_0.9.2/PsxGPU.c new file mode 100644 index 0000000..7bbf1d0 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxGPU.c @@ -0,0 +1,1067 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + + +u32 gpuStatus = 0x14802000; +int gpuMode = 0; +u8 gpuCmd; +int gpuDataC = 0; +int gpuDataP; +u32 gpuDataRet; +u32 gpuData[256]; +u32 gpuInfo[8] = {0, 0, 0, 0, 0, 0, 0, 2}; +int imageTransfer; +s16 imTX, imTXc, imTY, imTYc; +s16 imageX0, imageX1; +s16 imageY0, imageY1; + +// Draw Primitives + +void primPolyF3(unsigned char * baseAddr) { +/* PolyF3 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, prim.x2, prim.y2, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyFT3(unsigned char * baseAddr) { +/* PolyFT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c = MAKERGB24(prim.r, prim.g, prim.b); + c = ((prim.r*2 + prim.g*2 + prim.b*2) / 3); if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MIN(prim.u1, prim.u2)), + MAX(prim.v0, MIN(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog ("PolyFT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyF4(unsigned char *baseAddr) { +/* PolyF4 prim; + unsigned int c; + int point[8]; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyF4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + point[0] = prim.x0; point[1] = prim.y0; + point[2] = prim.x1; point[3] = prim.y1; + point[4] = prim.x3; point[5] = prim.y3; + point[6] = prim.x2; point[7] = prim.y2; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + polygon(drawvram, 4, point, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("PolyF4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyFT4(unsigned char * baseAddr) { +/* PolyFT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c, id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyFT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c = MAKERGB24(prim.r,prim.g,prim.b); + c = (prim.r*2 + prim.g*2 + prim.b*2) / 3; if (c > 0xff) c = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyFT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d) c=%x", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0,c);*/ +} + +void primPolyG3(unsigned char *baseAddr) { +/* PolyG3 prim; + V3D_f v[3]; + unsigned int c0,c1,c2; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[2]); + + pslog("polyG3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyGT3(unsigned char *baseAddr) { +/* PolyGT3 prim; + V3D_f v[3]; + Cache *tex; + unsigned int c0,c1,c2,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT3)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + +// c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); +// c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); +// c2 = MAKERGB24(prim.r2, prim.g2, prim.b2); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, prim.u2)), + MIN(prim.v0, MIN(prim.v1, prim.v2)), + MAX(prim.u0, MAX(prim.u1, prim.u2)), + MAX(prim.v0, MAX(prim.v1, prim.v2))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[2]); + } + else triangle3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[2]); + + pslog("polyGT3 %d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,(prim.code&2)!=0);*/ +} + +void primPolyG4(unsigned char * baseAddr) { +/* PolyG4 prim; + V3D_f v[4]; + unsigned int c0,c1,c2,c3; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyG4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + + c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); + c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); + c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); + c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; v[3].c = c3; + + if (prim.code & 2) return; + quad3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyG4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primPolyGT4(unsigned char *baseAddr) { +/* PolyGT4 prim; + V3D_f v[4]; + Cache *tex; + unsigned int c0,c1,c2,c3,id; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(PolyGT4)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + prim.x2 += offsX; prim.y2 += offsY; + prim.x3 += offsX; prim.y3 += offsY; + +// c0 = MAKERGB24(prim.r0,prim.g0,prim.b0); +// c1 = MAKERGB24(prim.r1,prim.g1,prim.b1); +// c2 = MAKERGB24(prim.r2,prim.g2,prim.b2); +// c3 = MAKERGB24(prim.r3,prim.g3,prim.b3); + c0 = (prim.r0*2 + prim.g0*2 + prim.b0*2) / 3; if (c0 > 0xff) c0 = 0xff; + c1 = (prim.r1*2 + prim.g1*2 + prim.b1*2) / 3; if (c1 > 0xff) c1 = 0xff; + c2 = (prim.r2*2 + prim.g2*2 + prim.b2*2) / 3; if (c2 > 0xff) c2 = 0xff; + c3 = (prim.r3*2 + prim.g3*2 + prim.b3*2) / 3; if (c3 > 0xff) c3 = 0xff; + + id = (prim.clut << 16) | prim.tpage; + tex = CacheGet(id, MIN(prim.u0, MIN(prim.u1, MIN(prim.u2, prim.u3))), + MIN(prim.v0, MIN(prim.v1, MIN(prim.v2, prim.v3))), + MAX(prim.u0, MAX(prim.u1, MAX(prim.u2, prim.u3))), + MAX(prim.v0, MAX(prim.v1, MAX(prim.v2, prim.v3)))); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; + v[0].u = prim.u0; v[0].v = prim.v0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; + v[1].u = prim.u1; v[1].v = prim.v1; v[1].c = c1; + v[2].x = prim.x2; v[2].y = prim.y2; v[2].z = 0; + v[2].u = prim.u2; v[2].v = prim.v2; v[2].c = c2; + v[3].x = prim.x3; v[3].y = prim.y3; v[3].z = 0; + v[3].u = prim.u3; v[3].v = prim.v3; v[3].c = c3; + + if (prim.code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, tex->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, tex->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("PolyGT4 %d,%d;%d,%d;%d,%d;%d,%d (st=%d)", + prim.x0,prim.y0,prim.x1,prim.y1,prim.x2,prim.y2,prim.x3,prim.y3,(prim.code&2)!=0);*/ +} + +void primLineF2(unsigned char *baseAddr) { +/* LineF2 prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineF2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c = MAKERGB15(prim.r, prim.g, prim.b); + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + line(drawvram, prim.x0, prim.y0, prim.x1, prim.y1, c); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF2 : %d,%d - %d,%d : color = %x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c);*/ +} + +void primLineF(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + + c = MAKERGB15(baseAddr[0], baseAddr[1], baseAddr[2]); + + if (baseAddr[3] & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + } + + if (baseAddr[3] & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineF vert = %d : color = %x\n", + i,c);*/ +} + +void primLineG2(unsigned char *baseAddr) { +/* LineG2 prim; + V3D_f v[2]; + unsigned int c0,c1; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(LineG2)); + + prim.x0 += offsX; prim.y0 += offsY; + prim.x1 += offsX; prim.y1 += offsY; + + c0 = MAKERGB24(prim.r0, prim.g0, prim.b0); + c1 = MAKERGB24(prim.r1, prim.g1, prim.b1); + + v[0].x = prim.x0; v[0].y = prim.y0; v[0].z = 0; v[0].c = c0; + v[1].x = prim.x1; v[1].y = prim.y1; v[1].z = 0; v[1].c = c1; + + if (prim.code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + triangle3d_f(drawvram, POLYTYPE_GRGB, NULL, &v[0], &v[1], &v[1]); + if (prim.code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("LineG2 : %d,%d - %d,%d : color = %x,%x\n", + prim.x0,prim.y0,prim.x1,prim.y1,c0,c1);*/ +} + +void primLineG(unsigned char *baseAddr) { +/* unsigned int c,x,y,lx=0,ly=0,lc=0; + unsigned int *baseAddri = (unsigned int *)baseAddr; + int i,j; + + if (norender) return; + + for (i=0;i<99;i++) + if (baseAddri[i]==0x55555555) + break; + + i--; + i/=2; + + + for (j=0;j>16)&0xffff; + + x += offsX; + y += offsY; + + if (j>0) + line(drawvram, x, y, lx, ly, c); + + lx = x; + ly = y; + lc = c; + } + + pslog ("LineG vert = %d\n", + i);*/ +} + +void primTileS(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, ((short*)baseAddr)[4], ((short*)baseAddr)[5]);*/ +} + +void primSprtS(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, ((short*)baseAddr)[6], ((short*)baseAddr)[7]);*/ +} + +void primTile1(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 1, 1);*/ +} + +void primTile8(unsigned char * baseAddr) { +/* RectWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 8, 8);*/ +} + +void primSprt8(unsigned char * baseAddr) { +/* SprtWH prim; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite((SprtWH *)baseAddr, 8, 8);*/ +} + +void primTile16(unsigned char * baseAddr) { +/* RectWH prim; + + memcpy(&prim, baseAddr, sizeof(RectWH)); + drawRect(&prim, 16, 16);*/ +} + +void primSprt16(unsigned char * baseAddr) { +/* SprtWH prim; + + memcpy(&prim, baseAddr, sizeof(SprtWH)); + drawSprite(&prim, 16, 16);*/ +} + +// Command Primitives + +void primVoid(unsigned char * baseAddr) { +} + +void primClrCache(unsigned char * baseAddr) { +} + +void primBlkFill(unsigned char * baseAddr) { +/* Rect prim; + unsigned int c; + + if (norender) return; + + memcpy(&prim, baseAddr, sizeof(Rect)); + + if ((prim.x > 1023) | (prim.y > 511)) return; + if (((prim.w + prim.x) > 1024) | ((prim.y + prim.h) > 512)) return; + if (prim.x < 0) prim.x = 0; + if (prim.y < 0) prim.y = 0; + if (prim.w > 1023) prim.w = 1023; + if (prim.h > 511) prim.h = 511; + + c = MAKERGB15(baseAddr[0],baseAddr[1],baseAddr[2]); + + pslog ("BlkFill %d,%d;%d,%d ,c=%x", + prim.x,prim.y,prim.w,prim.h,c); + + set_clip(drawvram, 0, 0, 1023, 511); + rectfill(drawvram, prim.x, prim.y, prim.w + prim.x - 1, prim.h + prim.y - 1, c); + SetClip();*/ +} + +void primMoveImage(unsigned char * baseAddr) { +/* short *gpuData = ((unsigned short *) baseAddr); + short imageSX,imageSY,imageDX,imageDY,imageW,imageH; + + imageSX = gpuData[2] & 0x3ff; + imageSY = gpuData[3] & 0x1ff; + + imageDX = gpuData[4] & 0x3ff; + imageDY = gpuData[5] & 0x1ff; + + imageW = gpuData[6] & 0xffff; + imageH = gpuData[7] & 0xffff; + + if((imageSY+imageH)>512) imageH=512-imageSY; + if((imageDY+imageH)>512) imageH=512-imageDY; + if((imageSX+imageW)>1024) imageW=1024-imageSX; + if((imageDX+imageW)>1024) imageW=1024-imageDX; + + pslog("MoveImage %d,%d %d,%d %d,%d\n", + imageSX, imageSY, imageDX, imageDY, imageW, imageH); + + UnsetClip(); + blit(vram, vram, imageSX, imageSY, imageDX, imageDY, imageW, imageH); + SetClip();*/ +} + +void primLoadImage(unsigned char * baseAddr) { + u32 gifTag[16]; + unsigned short *gpuData = ((unsigned short *) baseAddr); + + imageX0 = gpuData[2] & 0x3ff; + imageY0 = gpuData[3] & 0x1ff; + imageX1 = gpuData[4]; + imageY1 = gpuData[5]; + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imageTransfer = 2; + +#ifdef GPU_LOG + GPU_LOG ("LoadImage %d,%d %d,%d\n", imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1); +#endif + + gifTag[0] = 3; // nloop = 3 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 0; + gifTag[9] = (imageY0 << 16) | imageX0; + gifTag[10] = 0x51; // trxpos + + gifTag[12] = imageX1; + gifTag[13] = imageY1; + gifTag[14] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 4); +} + +void primStoreImage(unsigned char * baseAddr) { +/* unsigned long *gpuData = ((unsigned long *) baseAddr); + + imageX0 = (short)(gpuData[1] & 0x3ff); + imageY0 = (short)(gpuData[1]>>16) & 0x1ff; + imageX1 = (short)(gpuData[2] & 0xffff); + imageY1 = (short)((gpuData[2]>>16) & 0xffff); + + imTX=imageX0; imTY=imageY0; + imTXc=imageX1; imTYc=imageY1; + imSize=imageY1*imageX1/2; + + imageTransfer = 3; + GpuStatus|=0x08000000; + + pslog ("StoreImage %d,%d %d,%d\n" + ,imageX0, imageY0, imageX0 + imageX1, imageY0 + imageY1);*/ +} + +// Enviroment Primitives + +void primTPage(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + TPage = (short)(gdata & 0x7ff); + textAddrX = (gdata&0xf)<<6; + textAddrY = (((gdata)<<4)&0x100)+(((gdata)>>2)&0x200); + textTP = (gdata & 0x180) >> 7; + textABR = (gdata >> 5) & 0x3; + textREST = (gdata&0x00ffffff)>>9; + + GpuStatus = (GpuStatus & ~0x7ff) | (TPage);*/ +} + +void primTWindow(unsigned char *baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + tWinW = gdata&0xf; + tWinH = (gdata>>4)&0xf; + tWinX = (gdata>>8)&0xf; + tWinY = (gdata>>12)&0xf; + + pslog("primTWindow %d,%d %d,%d\n", tWinX, tWinY, tWinW, tWinH);*/ +} + +void primAreaStart(unsigned char * baseAddr) { +/* unsigned int gdata = ((unsigned int *)baseAddr)[0]; + + clipX = gdata & 0x3ff; + clipY = (gdata>>10) & 0x1ff; + SetClip(); + pslog("primAreaStart %dx%d\n", clipX, clipY); + GpuInfo[3] = gdata & 0xffffff;*/ +} + +void primAreaEnd(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + clipW = (short)(gdata & 0x3ff); + clipH = (short)((gdata>>10) & 0x1ff); + SetClip(); + pslog("primAreaEnd %dx%d\n", clipW, clipH); + GpuInfo[4] = gdata & 0xffffff;*/ +} + +void primDrawOffset(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + offsX = (short)(gdata & 0x3ff); + offsY = (short)((gdata >> 11) & 0x1ff); + pslog("primDrawOffset %dx%d\n", offsX, offsY); + GpuInfo[5] = gdata & 0xffffff;*/ +} + +void primMask(unsigned char * baseAddr) { +/* unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + md = gdata & 1; + me = gdata & 2; + GpuStatus = (GpuStatus & ~(3<<11)) | ((gdata&3)<<11);*/ +} + +// Drawing Helper Functions +/* +void drawSprite(SprtWH *prim, short w, short h) { + Cache *sprt; + unsigned int id; + + prim->x+=offsX; + prim->y+=offsY; + + id = (prim->clut << 16) | TPage; +// sprt = CacheGet(id, prim->u, prim->v, w + prim->u, h + prim->v); + sprt = CacheGet(id, 0, 0, 256, 256); + + if ((prim->r >= 0x80) & (prim->g >= 0x80) & (prim->b >= 0x80) & (!(prim->code & 2))) { + masked_blit(sprt->tex, drawvram, prim->u, prim->v, prim->x, prim->y, w, h); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,0x808080,prim->u,prim->v,(prim->code&2)!=0,id); + } + else { + V3D_f v[4]; + unsigned int c; + +// c = MAKERGB24(prim->r*2,prim->g*2,prim->b*2); + c = (prim->r*2 + prim->g*2 + prim->b*2) / 3; if (c > 0xff) c = 0xff; + + v[0].x = prim->x; v[0].y = prim->y; v[0].z = 0; + v[0].u = prim->u; v[0].v = prim->v; v[0].c = c; + v[1].x = prim->x; v[1].y = prim->y + h; v[1].z = 0; + v[1].u = prim->u; v[1].v = prim->v + h; v[1].c = c; + v[2].x = prim->x + w; v[2].y = prim->y; v[2].z = 0; + v[2].u = prim->u + w; v[2].v = prim->v; v[2].c = c; + v[3].x = prim->x + w; v[3].y = prim->y + h; v[3].z = 0; + v[3].u = prim->u + w; v[3].v = prim->v + h; v[3].c = c; + + if (prim->code & 2) { + SetST((id&0x6)>>5); + quad3d_f(drawvram, POLYTYPE_ATEX_MASK_TRANS, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + } + else quad3d_f(drawvram, POLYTYPE_ATEX_MASK_LIT, sprt->tex, &v[0], &v[1], &v[3], &v[2]); + + pslog ("Sprite : %d,%d - %dx%d (c=%x)- u,v: %d,%d (semi-transparency=%d) tex id=%x", + prim->x,prim->y,w,h,c,prim->u,prim->v,(prim->code&2)!=0,id); + } + +} + +void drawRect(RectWH *prim, short w, short h) { + unsigned int c; + + prim->x+=offsX; + prim->y+=offsY; + + c = MAKERGB15(prim->r,prim->g,prim->b); + + if (prim->code & 2) { + SetST(textABR); + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + rectfill(drawvram, prim->x, prim->y, w + prim->x - 1, h + prim->y - 1, c); + if (prim->code & 2) drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + + pslog ("Rectangle %d,%d %dx%d (semi-transparency=%d) c=%x", + prim->x,prim->y,w,h,(prim->code & 2)!=0,c); +}*/ + +// + +void primNI(unsigned char *bA) { +// if (bA[3]) pslog("PRIM: *NI* %02x",bA[3]); +} + + +unsigned char primTableC[256] = { + 1,1,3,0,0,0,0,0, // 00 + 0,0,0,0,0,0,0,0, // 08 + 0,0,0,0,0,0,0,0, // 10 + 0,0,0,0,0,0,0,0, // 18 + 4,4,4,4,7,7,7,7, // 20 + 5,5,5,5,9,9,9,9, // 28 + 6,6,6,6,9,9,9,9, // 30 + 8,8,8,8,12,12,12,12, // 38 + 3,3,3,3,0,0,0,0, // 40 + 5,5,5,5,6,6,6,6, // 48 + 4,4,4,4,0,0,0,0, // 50 + 7,7,7,7,9,9,9,9, // 58 + 3,3,3,3,4,4,4,4, // 60 + 2,2,2,2,0,0,0,0, // 68 + 2,2,2,2,3,3,3,3, // 70 + 2,2,2,2,3,3,3,3, // 78 + 4,0,0,0,0,0,0,0, // 80 + 0,0,0,0,0,0,0,0, // 88 + 0,0,0,0,0,0,0,0, // 90 + 0,0,0,0,0,0,0,0, // 98 + 3,0,0,0,0,0,0,0, // a0 + 0,0,0,0,0,0,0,0, // a8 + 0,0,0,0,0,0,0,0, // b0 + 0,0,0,0,0,0,0,0, // b8 + 3,0,0,0,0,0,0,0, // c0 + 0,0,0,0,0,0,0,0, // c8 + 0,0,0,0,0,0,0,0, // d0 + 0,0,0,0,0,0,0,0, // d8 + 0,1,1,1,1,1,1,0, // e0 + 0,0,0,0,0,0,0,0, // e8 + 0,0,0,0,0,0,0,0, // f0 + 0,0,0,0,0,0,0,0 // f8 +}; + +void (*primTableJ[256])(unsigned char *) = { + // 00 + primVoid,primClrCache,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineF,primLineF,primLineF,primLineF,primNI,primNI,primNI,primNI, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineG,primLineG,primLineG,primLineG,primNI,primNI,primNI,primNI, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,primTPage,primTWindow,primAreaStart,primAreaEnd,primDrawOffset,primMask,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +u32 cd[4]; +int cdC = 0; + +__inline void writePixel(short x, short y, u16 p) { + u32 gifTag[16]; + + cd[cdC] = ((p & 0x7c00) << 9) | + ((p & 0x03e0) << 6) | + ((p & 0x001f) << 3); + cdC++; + if (cdC < 4) return; + cdC = 0; + + gifTag[0] = 1; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); + GSgifTransfer3(cd, 1); +} + +void GPU_writeData(u32 data) { + gpuDataRet = data; + + if (imageTransfer == 2) { + // image transfer to VRAM + if (imTYc>0 && imTXc>0) { + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)data); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + if ((imTY>=0) && (imTY<512) && (imTX>=0) && (imTX<1024)) { + writePixel(imTX, imTY, (u16)(data>>16)); + } + + imTX++; imTXc--; + if (imTXc<=0) { + imTX = imageX0; imTXc = imageX1; + imTYc--; imTY++; + } + if (imTYc <= 0) { imageTransfer = 0; return; } + + return; + } + else imageTransfer = 0; + } + +#ifdef GPU_LOG + GPU_LOG("!GPU! DATA = %08x\n", data); +#endif + + if (gpuDataC == 0) { + gpuCmd = (u8)(data >> 24); + gpuDataC = primTableC[gpuCmd]; + if (gpuDataC) { + gpuData[0] = data; + gpuDataP = 1; + } else { +#ifdef GPU_LOG + GPU_LOG("GPU ERROR CMD: %x, data=%x\n", gpuCmd, data); +#endif + return; + } + } else { + if (gpuDataP >= 256) return; + gpuData[gpuDataP++] = data; + } + + if (gpuDataP == gpuDataC) { + gpuDataP = gpuDataC = 0; +#ifdef GPU_LOG + GPU_LOG("Gpu(writeData) Command %x\n", gpuCmd); +#endif + primTableJ[gpuCmd]((u8*)gpuData); + } +} + +void GPU_writeStatus(u32 data) { +// u32 gifTag[16]; + + switch (data >> 24) { + case 0x00: +/* gifTag[0] = 2; // nloop = 2 + gifTag[1] = (1 << 28); // regs = 1 + gifTag[2] = 0xe; // ad reg + + gifTag[4] = 0; + gifTag[5] = ((1024/64) << 16) | 0; + gifTag[6] = 0x50; // bitbltbuf + + gifTag[8] = 320; + gifTag[9] = 240; + gifTag[10] = 0x52; // trxreg + + GSgifTransfer3(gifTag, 3);*/ + GSwrite64(0x12000070, (1024/64) << 9); + break; + + case 0x10: + switch (data&7) { + case 3: + case 4: + case 5: + case 7: + gpuDataRet = gpuInfo[data&7]; + break; + default: +#ifdef GPU_LOG + GPU_LOG("GPU INFO UNK: %x\n", data); +#endif + break; + } + break; + } +} + +u32 GPU_readData() { + return gpuDataRet; +} + +u32 GPU_readStatus() { + gpuStatus^= 0x80000000; + return gpuStatus; +} + +void GPU_writeDataMem(u32 *pMem, int iSize) { +/* u32 gifTag[16]; + int i; + u16 *ptr = (u16*)pMem;*/ + +#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + while (iSize) { + GPU_writeData(*pMem); + pMem++; iSize--; + } + +/*#ifdef GPU_LOG + GPU_LOG("GPUwriteDataMem: %d\n", iSize); +#endif + + if (iSize > 0x7fff) { + } else { + gifTag[0] = iSize & 0x7fff; + gifTag[1] = 2 << 26; + + GSgifTransfer3(gifTag, 1); +// GSgifTransfer3(pMem, iSize); + GSgifTransfer3(ptr1, iSize); + } + imageTransfer = 0;*/ +} + +void GPU_readDataMem(u32 *pMem, int iSize) { +} + +void GPU_dmaChain(u32 *baseAddrL, u32 addr) { + unsigned long dmaMem; + unsigned char * baseAddrB; + unsigned char count; + unsigned char cmd; + + baseAddrB = (unsigned char*) baseAddrL; + + for (;;) { + count = baseAddrB[addr+3]; + dmaMem = addr+4; + while (count) { + if (imageTransfer == 2) { + GPU_writeData(baseAddrL[dmaMem/4]); + dmaMem+=4; + count--; + continue; + } + cmd = baseAddrB[dmaMem+3]; + if (primTableC[cmd] == 0) { + dmaMem+=4; + count--; + } else { +#ifdef GPU_LOG + GPU_LOG("Gpu(DmaChain) Command %x : %x\n", cmd, baseAddrL[dmaMem/4]); +#endif + primTableJ[cmd]((u8*)baseAddrL + dmaMem); + dmaMem+=(primTableC[cmd]*4); + count-=primTableC[cmd]; + } + } + addr = baseAddrL[addr/4]&0xffffff; + if (addr <= 0 || addr == 0xffffff) break; + addr&=0x7fffff; + } +} diff --git a/branches/pcsx2_0.9.2/PsxGPU.h b/branches/pcsx2_0.9.2/PsxGPU.h new file mode 100644 index 0000000..0126298 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxGPU.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXGPU_H__ +#define __PSXGPU_H__ + +#include "PS2Etypes.h" + +void GPU_writeData(u32 data); +void GPU_writeStatus(u32 data); +u32 GPU_readData(); +u32 GPU_readStatus(); +void GPU_writeDataMem(u32 *pMem, int iSize); +void GPU_readDataMem(u32 *pMem, int iSize); +void GPU_dmaChain(u32 *baseAddrL, u32 addr); + +#endif /* __PSXGPU_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxHw.c b/branches/pcsx2_0.9.2/PsxHw.c new file mode 100644 index 0000000..1ecaaa4 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxHw.c @@ -0,0 +1,2941 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +#include "iR5900.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// NOTE: Any modifications to read/write fns should also go into their const counterparts + +void psxHwReset() { +/* if (Config.Sio) psxHu32(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu32(0x1070) |= 0x200;*/ + + memset(psxH, 0, 0x10000); + +// mdecInit(); //intialize mdec decoder + cdrReset(); + cdvdReset(); + psxRcntInit(); + sioInit(); +// sio2Reset(); +} + +u8 psxHwRead8(u32 add) { + u8 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread8(add); + } + + switch (add) { + case 0x1f801040: hard = sioRead8();break; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + return DEV9read8(add); + +#ifdef PCSX2_DEVBUILD + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter read %x\n", add); + hard = psxHu8(add); + return hard; +#endif + + case 0x1f801800: hard = cdrRead0(); break; + case 0x1f801801: hard = cdrRead1(); break; + case 0x1f801802: hard = cdrRead2(); break; + case 0x1f801803: hard = cdrRead3(); break; + + case 0x1f803100: // PS/EE/IOP conf related + hard = 0x10; // Dram 2M + break; + + case 0x1F808264: + hard = sio2_fifoOut();//sio2 serial data feed/fifo_out +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read8 DATAOUT %08X\n", hard); +#endif + return hard; + + default: + hard = psxHu8(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD8_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R8toR(EAX, EAX); \ + else MOVZX32R8toR(EAX, EAX); \ +} \ + +static u32 s_16 = 0x10; + +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign) { + + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD8_CALL(USBread8); + // since calling from different dll, esp already changed + return 1; + } + + switch (add) { + case 0x1f801040: + CONSTREAD8_CALL(sioRead8); + return 1; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + +#ifdef PCSX2_DEVBUILD + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter read %x\n", add); + _eeReadConstMem8(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; +#endif + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD8_CALL(DEV9read8); + return 1; + + case 0x1f801800: CONSTREAD8_CALL(cdrRead0); return 1; + case 0x1f801801: CONSTREAD8_CALL(cdrRead1); return 1; + case 0x1f801802: CONSTREAD8_CALL(cdrRead2); return 1; + case 0x1f801803: CONSTREAD8_CALL(cdrRead3); return 1; + + case 0x1f803100: // PS/EE/IOP conf related + if( IS_XMMREG(x86reg) ) SSEX_MOVD_M32_to_XMM(x86reg&0xf, (u32)&s_16); + else if( IS_MMXREG(x86reg) ) MOVDMtoMMX(x86reg&0xf, (u32)&s_16); + else MOV32ItoR(x86reg, 0x10); + return 0; + + case 0x1F808264: //sio2 serial data feed/fifo_out + CONSTREAD8_CALL(sio2_fifoOut); + return 1; + + default: + _eeReadConstMem8(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } +} + +u16 psxHwRead16(u32 add) { + u16 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread16(add); + } + + switch (add) { +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070)); + return psxHu16(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074)); + return psxHu16(0x1074); +#endif + + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801044: + hard = sio.StatReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801048: + hard = sio.ModeReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104a: + hard = sio.CtrlReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104e: + hard = sio.BaudReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + + //Serial port stuff not support now ;P + // case 0x1f801050: hard = serial_read16(); break; + // case 0x1f801054: hard = serial_status_read(); break; + // case 0x1f80105a: hard = serial_control_read(); break; + // case 0x1f80105e: hard = serial_baud_read(); break; + + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read16: %x\n", hard); +#endif + return hard; + + case 0x1f80146e: // DEV9_R_REV + return DEV9read16(add); + + case 0x1f801480: + hard = (u16)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = psxCounters[3].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u16)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = psxCounters[4].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u16)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = psxCounters[5].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read16: %lx\n", hard); +#endif + return hard; + + case 0x1f801504: + hard = psxHu16(0x1504); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit read %lx\n", hard); +#endif + return hard; + case 0x1f801506: + hard = psxHu16(0x1506); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit read %lx\n", hard); +#endif + return hard; + //case 0x1f802030: hard = //int_2000???? + //case 0x1f802040: hard =//dip switches...?? + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + hard = SPU2read(add); + } else { + hard = psxHu16(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 16bit read at address %lx\n", add); +#endif + } + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +void psxConstReadCounterMode16(int x86reg, int index, int sign) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode - 2); + } + else { + if( sign ) MOVSX32M16toR(ECX, (u32)&psxCounters[index].mode); + else MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + + MOV32RtoR(x86reg, ECX); + } + + //AND16ItoR(ECX, ~0x1800); + //OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign) { + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD16_CALL(USBread16); + return 1; + } + + switch (add) { + + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + PUSH32R(EAX); + CALLFunc((u32)sioRead8); + POP32R(ECX); + AND32ItoR(ECX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoR(EAX, ECX); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f801044: + _eeReadConstMem16(x86reg, (u32)&sio.StatReg, sign); + return 0; + + case 0x1f801048: + _eeReadConstMem16(x86reg, (u32)&sio.ModeReg, sign); + return 0; + + case 0x1f80104a: + _eeReadConstMem16(x86reg, (u32)&sio.CtrlReg, sign); + return 0; + + case 0x1f80104e: + _eeReadConstMem16(x86reg, (u32)&sio.BaudReg, sign); + return 0; + + // counters[0] + case 0x1f801100: + PUSH32I(0); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode16(x86reg, 0, sign); + return 0; + + case 0x1f801108: + _eeReadConstMem16(x86reg, (u32)&psxCounters[0].target, sign); + return 0; + + // counters[1] + case 0x1f801110: + PUSH32I(1); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode16(x86reg, 1, sign); + return 0; + + case 0x1f801118: + _eeReadConstMem16(x86reg, (u32)&psxCounters[1].target, sign); + return 0; + + // counters[2] + case 0x1f801120: + PUSH32I(2); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode16(x86reg, 2, sign); + return 0; + + case 0x1f801128: + _eeReadConstMem16(x86reg, (u32)&psxCounters[2].target, sign); + return 0; + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD16_CALL(DEV9read16); + return 1; + + // counters[3] + case 0x1f801480: + PUSH32I(3); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode16(x86reg, 3, sign); + return 0; + + case 0x1f801488: + _eeReadConstMem16(x86reg, (u32)&psxCounters[3].target, sign); + return 0; + + // counters[4] + case 0x1f801490: + PUSH32I(4); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode16(x86reg, 4, sign); + return 0; + + case 0x1f801498: + _eeReadConstMem16(x86reg, (u32)&psxCounters[4].target, sign); + return 0; + + // counters[5] + case 0x1f8014a0: + PUSH32I(5); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode16(x86reg, 5, sign); + return 0; + + case 0x1f8014a8: + _eeReadConstMem16(x86reg, (u32)&psxCounters[5].target, sign); + return 0; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + + PUSH32I(add); + CONSTREAD16_CALL(SPU2read); + return 1; + } else { + _eeReadConstMem16(x86reg, (u32)&psxH[(add) & 0xffff], sign); + return 0; + } + } +} + +u32 psxHwRead32(u32 add) { + u32 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread32(add); + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + return FWread32(add); + } + + switch (add) { + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; + hard|= sioRead8() << 16; + hard|= sioRead8() << 24; +#ifdef PAD_LOG + PAD_LOG("sio read32 ;ret = %lx\n", hard); +#endif + return hard; + + // case 0x1f801050: hard = serial_read32(); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size read %lx\n", psxHu32(0x1060)); + return psxHu32(0x1060); +#endif +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070)); + return psxHu32(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074)); + return psxHu32(0x1074); +#endif + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + hard = psxHu32(0x1078); + psxHu32(0x1078) = 0; + return hard; + +/* case 0x1f801810: +// hard = GPU_readData(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit read %lx\n", hard); +#endif + return hard;*/ +/* case 0x1f801814: + hard = GPU_readStatus(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit read %lx\n", hard); +#endif + return hard; +*/ +/* case 0x1f801820: hard = mdecRead0(); break; + case 0x1f801824: hard = mdecRead1(); break; +*/ +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit read %lx\n", psxHu32(0x10a0)); + return HW_DMA2_MADR; + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit read %lx\n", psxHu32(0x10a4)); + return HW_DMA2_BCR; + case 0x1f8010a8: + PSXHW_LOG("DMA2 CHCR 32bit read %lx\n", psxHu32(0x10a8)); + return HW_DMA2_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit read %lx\n", psxHu32(0x10b0)); + return HW_DMA3_MADR; + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit read %lx\n", psxHu32(0x10b4)); + return HW_DMA3_BCR; + case 0x1f8010b8: + PSXHW_LOG("DMA3 CHCR 32bit read %lx\n", psxHu32(0x10b8)); + return HW_DMA3_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit read %lx\n", HW_DMA9_MADR); + return HW_DMA9_MADR; + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit read %lx\n", HW_DMA9_BCR); + return HW_DMA9_BCR; + case 0x1f801528: + PSXHW_LOG("DMA9 CHCR 32bit read %lx\n", HW_DMA9_CHCR); + return HW_DMA9_CHCR; + case 0x1f80152C: + PSXHW_LOG("DMA9 TADR 32bit read %lx\n", HW_DMA9_TADR); + return HW_DMA9_TADR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit read %lx\n", HW_DMA10_MADR); + return HW_DMA10_MADR; + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit read %lx\n", HW_DMA10_BCR); + return HW_DMA10_BCR; + case 0x1f801538: + PSXHW_LOG("DMA10 CHCR 32bit read %lx\n", HW_DMA10_CHCR); + return HW_DMA10_CHCR; +#endif + +// case 0x1f8010f0: PSXHW_LOG("DMA PCR 32bit read " << psxHu32(0x10f0)); +// return HW_DMA_PCR; // dma rest channel +#ifdef PSXHW_LOG + case 0x1f8010f4: + PSXHW_LOG("DMA ICR 32bit read %lx\n", HW_DMA_ICR); + return HW_DMA_ICR; +#endif +//SSBus registers + case 0x1f801000: + hard = psxHu32(0x1000); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801004: + hard = psxHu32(0x1004); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801008: + hard = psxHu32(0x1008); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80100C: + hard = psxHu32(0x100C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801010: + hard = psxHu32(0x1010); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS rom_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801014: + hard = psxHu32(0x1014); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801018: + hard = psxHu32(0x1018); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80101C: + hard = psxHu32(0x101C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801020: + hard = psxHu32(0x1020); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS com_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801400: + hard = psxHu32(0x1400); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801404: + hard = psxHu32(0x1404); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801408: + hard = psxHu32(0x1408); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80140C: + hard = psxHu32(0x140C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801410: + hard = psxHu32(0x1410); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801414: + hard = psxHu32(0x1414); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801418: + hard = psxHu32(0x1418); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80141C: + hard = psxHu32(0x141C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801420: + hard = psxHu32(0x1420); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + + case 0x1f8010f0: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR 32bit read %lx\n", HW_DMA_PCR); +#endif + return HW_DMA_PCR; + + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit read %lx\n", HW_DMA4_CHCR); +#endif + return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) + + // time for rootcounters :) + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801104: + hard = (u16)psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801114: + hard = (u16)psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801124: + hard = (u16)psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801480: + hard = (u32)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = (u16)psxCounters[3].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u32)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = (u16)psxCounters[4].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u32)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = (u16)psxCounters[5].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801450: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("%08X ICFG 32bit read %x\n", psxRegs.pc, hard); +#endif + return hard; + + + case 0x1F8010C0: + HW_DMA4_MADR = SPU2ReadMemAddr(0); + return HW_DMA4_MADR; + + case 0x1f801500: + HW_DMA7_MADR = SPU2ReadMemAddr(1); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 MADR 32bit read %lx\n", HW_DMA7_MADR); +#endif + return HW_DMA7_MADR; // DMA7 madr + case 0x1f801504: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR 32bit read %lx\n", HW_DMA7_BCR); +#endif + return HW_DMA7_BCR; // DMA7 bcr + + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit read %lx\n", HW_DMA7_CHCR); +#endif + return HW_DMA7_CHCR; // DMA7 chcr (SPU2) + + case 0x1f801570: + hard = psxHu32(0x1570); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit read %lx\n", hard); +#endif + return hard; +#ifdef PSXHW_LOG + case 0x1f801574: + PSXHW_LOG("DMA ICR2 32bit read %lx\n", HW_DMA_ICR2); + return HW_DMA_ICR2; +#endif + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + hard=sio2_getSend3((add-0x1F808200)/4); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read param[%d] (%lx)\n", (add-0x1F808200)/4, hard); +#endif + return hard; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + hard=sio2_getSend1((add-0x1F808240)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send1[%d] (%lx)\n", (add-0x1F808240)/8, hard); +#endif + return hard; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + hard=sio2_getSend2((add-0x1F808244)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send2[%d] (%lx)\n", (add-0x1F808244)/8, hard); +#endif + return hard; + + case 0x1F808268: + hard=sio2_getCtrl(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read CTRL (%lx)\n", hard); +#endif + return hard; + + case 0x1F80826C: + hard=sio2_getRecv1(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv1 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808270: + hard=sio2_getRecv2(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv2 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808274: + hard=sio2_getRecv3(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv3 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808278: + hard=sio2_get8278(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [8278] (%lx)\n", hard); +#endif + return hard; + + case 0x1F80827C: + hard=sio2_get827C(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [827C] (%lx)\n", hard); +#endif + return hard; + + case 0x1F808280: + hard=sio2_getIntr(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read INTR (%lx)\n", hard); +#endif + return hard; + + default: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; +} + +void psxConstReadCounterMode32(int x86reg, int index) +{ + if( IS_MMXREG(x86reg) ) { + MOV16MtoR(ECX, (u32)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (u32)&psxCounters[index].mode); + } + else { + MOVZX32M16toR(ECX, (u32)&psxCounters[index].mode); + MOV32RtoR(x86reg, ECX); + } + + //AND16ItoR(ECX, ~0x1800); + //OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +static u32 s_tempsio; +int psxHwConstRead32(u32 x86reg, u32 add) { + if (add >= 0x1f801600 && add < 0x1f801700) { + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBread32); + return 1; + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWread32); + return 1; + } + + switch (add) { + case 0x1f801040: + iFlushCall(0); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + MOV32RtoM((u32)&s_tempsio, EAX); + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoM((u32)&s_tempsio, EAX); + + // 3rd + CALLFunc((u32)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 16); + OR32RtoM((u32)&s_tempsio, EAX); + + // 4th + CALLFunc((u32)sioRead8); + SHL32ItoR(EAX, 24); + OR32MtoR(EAX, (u32)&s_tempsio); + return 1; + + //case 0x1f801050: hard = serial_read32(); break;//serial port + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + _eeReadConstMem32(x86reg, (u32)&psxH[add&0xffff]); + MOV32ItoM((u32)&psxH[add&0xffff], 0); + return 0; + + // counters[0] + case 0x1f801100: + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode32(x86reg, 0); + return 0; + + case 0x1f801108: + _eeReadConstMem32(x86reg, (u32)&psxCounters[0].target); + return 0; + + // counters[1] + case 0x1f801110: + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode32(x86reg, 1); + return 0; + + case 0x1f801118: + _eeReadConstMem32(x86reg, (u32)&psxCounters[1].target); + return 0; + + // counters[2] + case 0x1f801120: + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode32(x86reg, 2); + return 0; + + case 0x1f801128: + _eeReadConstMem32(x86reg, (u32)&psxCounters[2].target); + return 0; + + // counters[3] + case 0x1f801480: + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode32(x86reg, 3); + return 0; + + case 0x1f801488: + _eeReadConstMem32(x86reg, (u32)&psxCounters[3].target); + return 0; + + // counters[4] + case 0x1f801490: + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode32(x86reg, 4); + return 0; + + case 0x1f801498: + _eeReadConstMem32(x86reg, (u32)&psxCounters[4].target); + return 0; + + // counters[5] + case 0x1f8014a0: + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode32(x86reg, 5); + return 0; + + case 0x1f8014a8: + _eeReadConstMem32(x86reg, (u32)&psxCounters[5].target); + return 0; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_getSend3); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_getSend1); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_getSend2); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808268: + iFlushCall(0); + CALLFunc((u32)sio2_getCtrl); + return 1; + + case 0x1F80826C: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv1); + return 1; + + case 0x1F808270: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv2); + return 1; + + case 0x1F808274: + iFlushCall(0); + CALLFunc((u32)sio2_getRecv3); + return 1; + + case 0x1F808278: + iFlushCall(0); + CALLFunc((u32)sio2_get8278); + return 1; + + case 0x1F80827C: + iFlushCall(0); + CALLFunc((u32)sio2_get827C); + return 1; + + case 0x1F808280: + iFlushCall(0); + CALLFunc((u32)sio2_getIntr); + return 1; + + case 0x1F801C00: + iFlushCall(0); + CALLFunc((u32)SPU2ReadMemAddr(0)); + return 1; + + case 0x1F801500: + iFlushCall(0); + CALLFunc((u32)SPU2ReadMemAddr(1)); + return 1; + + default: + _eeReadConstMem32(x86reg, (u32)&psxH[(add) & 0xffff]); + return 0; + } +} + +static int pbufi; +static s8 pbuf[1024]; + +#define DmaExec(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite8(u32 add, u8 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite8(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0xa) SysPrintf("8bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: sioWrite8(value); break; + // case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter write %x\n", add); + psxHu8(add) = value; + return; + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 8bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu8(0x1450) = value; + return; + + case 0x1f801800: cdrWrite0(value); break; + case 0x1f801801: cdrWrite1(value); break; + case 0x1f801802: cdrWrite2(value); break; + case 0x1f801803: cdrWrite3(value); break; + + case 0x1f80380c: + if (value == '\r') break; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); break; + } + pbuf[pbufi++] = value; + break; + + case 0x1F808260: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write8 DATAIN <- %08X\n", value); +#endif + sio2_fifoIn(value);return;//serial data feed/fifo + + default: + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +#define CONSTWRITE_CALL(name) { \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void Write8PrintBuffer(u8 value) +{ + if (value == '\r') return; + if (value == '\n' || pbufi >= 1023) { + pbuf[pbufi++] = 0; pbufi = 0; + SysPrintf("%s\n", pbuf); return; + } + pbuf[pbufi++] = value; +} + +void psxHwConstWrite8(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite8); + return; + } + + switch (add) { + case 0x1f801040: + CONSTWRITE_CALL(sioWrite8); break; + //case 0x1f801050: serial_write8(value); break;//serial port + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter write %x\n", add); + _eeWriteConstMem8((u32)&psxH[(add) & 0xffff], mmreg); + return; + case 0x1f801800: CONSTWRITE_CALL(cdrWrite0); break; + case 0x1f801801: CONSTWRITE_CALL(cdrWrite1); break; + case 0x1f801802: CONSTWRITE_CALL(cdrWrite2); break; + case 0x1f801803: CONSTWRITE_CALL(cdrWrite3); break; + case 0x1f80380c: CONSTWRITE_CALL(Write8PrintBuffer); break; + case 0x1F808260: CONSTWRITE_CALL(sio2_fifoIn); break; + + default: + _eeWriteConstMem8((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +void psxHwWrite16(u32 add, u16 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite16(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)(value>>8)); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801044: +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801048: + sio.ModeReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104a: // control register + sioWriteCtrl16(value); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104e: // baudrate register + sio.BaudReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + + //serial port ;P + // case 0x1f801050: serial_write16(value); break; + // case 0x1f80105a: serial_control_write(value);break; + // case 0x1f80105e: serial_baud_write(value); break; + // case 0x1f801054: serial_status_write(value); break; + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 16bit write %x\n", value); +#endif +// if (Config.Sio) psxHu16(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; + psxHu16(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value); + psxHu16(0x1074) = value; + return; +#endif + + case 0x1f8010c4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); +#endif + psxHu16(0x10c4) = value; return; // DMA4 bcr_size + + case 0x1f8010c6: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); +#endif + psxHu16(0x10c6) = value; return; // DMA4 bcr_count + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(0, value); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(0, value); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(1, value); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(1, value); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(2, value); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 16bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu16(0x1450) = value/* & (~0x8)*/; + return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 16bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 16bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 16bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f801504: + psxHu16(0x1504) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit write %lx\n", value); +#endif + return; + case 0x1f801506: + psxHu16(0x1506) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit write %lx\n", value); +#endif + return; + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + SPU2write(add, value); + return; + } + + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 16bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHwConstWrite16(u32 add, int mmreg) { + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite16); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 3); + return; + case 0x1f801044: + return; + case 0x1f801048: + _eeWriteConstMem16((u32)&sio.ModeReg, mmreg); + return; + case 0x1f80104a: // control register + CONSTWRITE_CALL(sioWriteCtrl16); + return; + case 0x1f80104e: // baudrate register + _eeWriteConstMem16((u32)&sio.BaudReg, mmreg); + return; + + case 0x1f801070: + _eeWriteConstMem16OP((u32)&psxH[(add) & 0xffff], mmreg, 0); + return; + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)SPU2write); + // leave esp alone + return; + } + + _eeWriteConstMem16((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +#define DmaExec2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite32(u32 add, u32 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite32(add, value); return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + FWwrite32(add, value); return; + } + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)((value&0xff) >> 8)); + sioWrite8((u8)((value&0xff) >> 16)); + sioWrite8((u8)((value&0xff) >> 24)); +#ifdef PAD_LOG + PAD_LOG("sio write32 %lx\n", value); +#endif + return; + // case 0x1f801050: serial_write32(value); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size write %lx\n", value); + psxHu32(add) = value; + return; // Ram size +#endif + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 32bit write %lx\n", value); +#endif +// if (Config.Sio) psxHu32(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu32(0x1070) |= 0x200; + psxHu32(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: + PSXHW_LOG("IMASK 32bit write %lx\n", value); + psxHu32(0x1074) = value; + return; + + case 0x1f801078: + PSXHW_LOG("ICTRL 32bit write %lx\n", value); +// SysPrintf("ICTRL 32bit write %lx\n", value); + psxHu32(0x1078) = value; + return; +#endif + + //SSBus registers + case 0x1f801000: + psxHu32(0x1000) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801004: + psxHu32(0x1004) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801008: + psxHu32(0x1008) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f80100C: + psxHu32(0x100C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801010: + psxHu32(0x1010) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS rom_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801014: + psxHu32(0x1014) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801018: + psxHu32(0x1018) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f80101C: + psxHu32(0x101C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801020: + psxHu32(0x1020) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS com_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801400: + psxHu32(0x1400) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801404: + psxHu32(0x1404) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801408: + psxHu32(0x1408) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f80140C: + psxHu32(0x140C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801410: + psxHu32(0x1410) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801414: + psxHu32(0x1414) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801418: + psxHu32(0x1418) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f80141C: + psxHu32(0x141C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801420: + psxHu32(0x1420) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f801080: + PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); + HW_DMA0_MADR = value; return; // DMA0 madr + case 0x1f801084: + PSXHW_LOG("DMA0 BCR 32bit write %lx\n", value); + HW_DMA0_BCR = value; return; // DMA0 bcr +#endif + case 0x1f801088: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA0 CHCR 32bit write %lx\n", value); +#endif + HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +// DmaExec(0); + return; + +#ifdef PSXHW_LOG + case 0x1f801090: + PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); + HW_DMA1_MADR = value; return; // DMA1 madr + case 0x1f801094: + PSXHW_LOG("DMA1 BCR 32bit write %lx\n", value); + HW_DMA1_BCR = value; return; // DMA1 bcr +#endif + case 0x1f801098: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA1 CHCR 32bit write %lx\n", value); +#endif + HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +// DmaExec(1); + return; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); + HW_DMA2_MADR = value; return; // DMA2 madr + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit write %lx\n", value); + HW_DMA2_BCR = value; return; // DMA2 bcr +#endif + case 0x1f8010a8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA2 CHCR 32bit write %lx\n", value); +#endif + HW_DMA2_CHCR = value; // DMA2 chcr (GPU DMA) + DmaExec(2); + return; + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); + HW_DMA3_MADR = value; return; // DMA3 madr + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit write %lx\n", value); + HW_DMA3_BCR = value; return; // DMA3 bcr +#endif + case 0x1f8010b8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA3 CHCR 32bit write %lx\n", value); +#endif + HW_DMA3_CHCR = value; // DMA3 chcr (CDROM DMA) + DmaExec(3); + + return; + + case 0x1f8010c0: + PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); + SPU2WriteMemAddr(0,value); + HW_DMA4_MADR = value; return; // DMA4 madr + case 0x1f8010c4: + PSXHW_LOG("DMA4 BCR 32bit write %lx\n", value); + HW_DMA4_BCR = value; return; // DMA4 bcr + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit write %lx\n", value); +#endif + HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) + DmaExec(4); + return; + +#if 0 + case 0x1f8010d0: break; //DMA5write_madr(); + case 0x1f8010d4: break; //DMA5write_bcr(); + case 0x1f8010d8: break; //DMA5write_chcr(); // Not yet needed?? +#endif + +#ifdef PSXHW_LOG + case 0x1f8010e0: + PSXHW_LOG("DMA6 MADR 32bit write %lx\n", value); + HW_DMA6_MADR = value; return; // DMA6 madr + case 0x1f8010e4: + PSXHW_LOG("DMA6 BCR 32bit write %lx\n", value); + HW_DMA6_BCR = value; return; // DMA6 bcr +#endif + case 0x1f8010e8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA6 CHCR 32bit write %lx\n", value); +#endif + HW_DMA6_CHCR = value; // DMA6 chcr (OT clear) + DmaExec(6); + return; + + case 0x1f801500: + PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); + SPU2WriteMemAddr(1,value); + HW_DMA7_MADR = value; return; // DMA7 madr + case 0x1f801504: + PSXHW_LOG("DMA7 BCR 32bit write %lx\n", value); + HW_DMA7_BCR = value; return; // DMA7 bcr + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit write %lx\n", value); +#endif + HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) + DmaExec2(7); + return; + +#ifdef PSXHW_LOG + case 0x1f801510: + PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); + HW_DMA8_MADR = value; return; // DMA8 madr + case 0x1f801514: + PSXHW_LOG("DMA8 BCR 32bit write %lx\n", value); + HW_DMA8_BCR = value; return; // DMA8 bcr +#endif + case 0x1f801518: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA8 CHCR 32bit write %lx\n", value); +#endif + HW_DMA8_CHCR = value; // DMA8 chcr (DEV9) + DmaExec2(8); + return; + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); + HW_DMA9_MADR = value; return; // DMA9 madr + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit write %lx\n", value); + HW_DMA9_BCR = value; return; // DMA9 bcr +#endif + case 0x1f801528: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA9 CHCR 32bit write %lx\n", value); +#endif + HW_DMA9_CHCR = value; // DMA9 chcr (SIF0) + DmaExec2(9); + return; +#ifdef PSXHW_LOG + case 0x1f80152c: + PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value); + HW_DMA9_TADR = value; return; // DMA9 tadr +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); + HW_DMA10_MADR = value; return; // DMA10 madr + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit write %lx\n", value); + HW_DMA10_BCR = value; return; // DMA10 bcr +#endif + case 0x1f801538: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA10 CHCR 32bit write %lx\n", value); +#endif + HW_DMA10_CHCR = value; // DMA10 chcr (SIF1) + DmaExec2(10); + return; + +#ifdef PSXHW_LOG + case 0x1f801540: + PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); + HW_DMA11_MADR = value; return; + + case 0x1f801544: + PSXHW_LOG("DMA11 SIO2in BCR 32bit write %lx\n", value); + HW_DMA11_BCR = value; return; +#endif + case 0x1f801548: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA11 SIO2in CHCR 32bit write %lx\n", value); +#endif + HW_DMA11_CHCR = value; // DMA11 chcr (SIO2 in) + DmaExec2(11); + return; + +#ifdef PSXHW_LOG + case 0x1f801550: + PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); + HW_DMA12_MADR = value; return; + + case 0x1f801554: + PSXHW_LOG("DMA12 SIO2out BCR 32bit write %lx\n", value); + HW_DMA12_BCR = value; return; +#endif + case 0x1f801558: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA12 SIO2out CHCR 32bit write %lx\n", value); +#endif + HW_DMA12_CHCR = value; // DMA12 chcr (SIO2 out) + DmaExec2(12); + return; + + case 0x1f801570: + psxHu32(0x1570) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit write %lx\n", value); + HW_DMA_PCR = value; + return; +#endif + + case 0x1f8010f4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR; + HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + + case 0x1f801574: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR2; + HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + +/* case 0x1f801810: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit write %lx\n", value); +#endif + GPU_writeData(value); return; + case 0x1f801814: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit write %lx\n", value); +#endif + GPU_writeStatus(value); return; +*/ +/* case 0x1f801820: + mdecWrite0(value); break; + case 0x1f801824: + mdecWrite1(value); break; +*/ + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(0, value ); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 32bit write %lx\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(0, value ); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(1, value ); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 32bit write %lx\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(1, value ); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(2, value ); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 32bit write %lx\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 32bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 32bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 32bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f8014c0: +#ifdef PSXHW_LOG + PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); +#endif + SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value); + break; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 32bit write %lx\n", psxRegs.pc, value); } +#endif +/* if (value && + psxSu32(0x20) == 0x20000 && + (psxSu32(0x30) == 0x20000 || + psxSu32(0x30) == 0x40000)) { // don't ask me why :P + psxSu32(0x20) = 0x10000; + psxSu32(0x30) = 0x10000; + }*/ + psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; + return; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write param[%d] <- %lx\n", (add-0x1F808200)/4, value); +#endif + sio2_setSend3((add-0x1F808200)/4, value); return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send1[%d] <- %lx\n", (add-0x1F808240)/8, value); +#endif + sio2_setSend1((add-0x1F808240)/8, value); return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send2[%d] <- %lx\n", (add-0x1F808244)/8, value); +#endif + sio2_setSend2((add-0x1F808244)/8, value); return; + + case 0x1F808268: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write CTRL <- %lx\n", value); +#endif + sio2_setCtrl(value); return; + + case 0x1F808278: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [8278] <- %lx\n", value); +#endif + sio2_set8278(value); return; + + case 0x1F80827C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [827C] <- %lx\n", value); +#endif + sio2_set827C(value); return; + + case 0x1F808280: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write INTR <- %lx\n", value); +#endif + sio2_setIntr(value); return; + + default: + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); +#endif + return; + } + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit write at address %lx value %lx\n", add, value); +#endif +} + +#define recDmaExec(n) { \ + iFlushCall(0); \ + if( n > 6 ) \ + TEST32ItoM((u32)&HW_DMA_PCR2, 8 << ((n-7) * 4)); \ + else \ + TEST32ItoM((u32)&HW_DMA_PCR, 8 << (n * 4)); \ + j8Ptr[5] = JZ8(0); \ + MOV32MtoR(EAX, (u32)&HW_DMA##n##_CHCR); \ + TEST32ItoR(EAX, 0x01000000); \ + j8Ptr[6] = JZ8(0); \ + \ + PUSH32R(EAX); \ + PUSH32M((u32)&HW_DMA##n##_BCR); \ + PUSH32M((u32)&HW_DMA##n##_MADR); \ + CALLFunc((u32)psxDma##n); \ + ADD32ItoR(ESP, 12); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ +} \ + +#define CONSTWRITE_CALL32(name) { \ + iFlushCall(0); \ + _recPushReg(mmreg); \ + CALLFunc((u32)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void psxHwConstWrite32(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)USBwrite32); + return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((u32)FWwrite32); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((u32)sioWrite8); + ADD32ItoR(ESP, 1); + return; + + case 0x1f801070: + _eeWriteConstMem32OP((u32)&psxH[(add) & 0xffff], mmreg, 0); // and + return; + +// case 0x1f801088: +// HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +//// DmaExec(0); +// return; + +// case 0x1f801098: +// HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +//// DmaExec(1); +// return; + + case 0x1f8010a8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(2); + return; + + case 0x1f8010b8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(3); + return; + + case 0x1f8010c8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(4); + return; + + case 0x1f8010e8: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(6); + return; + + case 0x1f801508: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(7); + return; + + case 0x1f801518: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(8); + return; + + case 0x1f801528: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(9); + return; + + case 0x1f801538: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(10); + return; + + case 0x1f801548: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(11); + return; + + case 0x1f801558: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + recDmaExec(12); + return; + + case 0x1f8010f4: + case 0x1f801574: + { + // u32 tmp = (~value) & HW_DMA_ICR; + _eeMoveMMREGtoR(EAX, mmreg); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND32MtoR(ECX, (u32)&psxH[(add) & 0xffff]); + + // HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + XOR32RtoR(EAX, ECX); + AND32ItoR(EAX, 0xffffff); + XOR32RtoR(EAX, ECX); + MOV32RtoM((u32)&psxH[(add) & 0xffff], EAX); + return; + } + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL32(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL32(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL32(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((u32)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL32(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL32(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL32(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((u32)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014c0: + SysPrintf("RTC_HOLDMODE 32bit write\n"); + break; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((u32)sio2_setSend3); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((u32)sio2_setSend1); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((u32)sio2_setSend2); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808268: CONSTWRITE_CALL32(sio2_setCtrl); return; + case 0x1F808278: CONSTWRITE_CALL32(sio2_set8278); return; + case 0x1F80827C: CONSTWRITE_CALL32(sio2_set827C); return; + case 0x1F808280: CONSTWRITE_CALL32(sio2_setIntr); return; + + case 0x1F8010C0: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((u32)SPU2WriteMemAddr); + return; + + case 0x1F801500: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((u32)SPU2WriteMemAddr); + return; + default: + _eeWriteConstMem32((u32)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +u8 psxHw4Read8(u32 add) { + u8 hard; + + switch (add) { + case 0x1f402004: return cdvdRead04(); + case 0x1f402005: return cdvdRead05(); + case 0x1f402006: return cdvdRead06(); + case 0x1f402007: return cdvdRead07(); + case 0x1f402008: return cdvdRead08(); + case 0x1f40200A: return cdvdRead0A(); + case 0x1f40200B: return cdvdRead0B(); + case 0x1f40200C: return cdvdRead0C(); + case 0x1f40200D: return cdvdRead0D(); + case 0x1f40200E: return cdvdRead0E(); + case 0x1f40200F: return cdvdRead0F(); + case 0x1f402013: return cdvdRead13(); + case 0x1f402015: return cdvdRead15(); + case 0x1f402016: return cdvdRead16(); + case 0x1f402017: return cdvdRead17(); + case 0x1f402018: return cdvdRead18(); + case 0x1f402020: return cdvdRead20(); + case 0x1f402021: return cdvdRead21(); + case 0x1f402022: return cdvdRead22(); + case 0x1f402023: return cdvdRead23(); + case 0x1f402024: return cdvdRead24(); + case 0x1f402028: return cdvdRead28(); + case 0x1f402029: return cdvdRead29(); + case 0x1f40202A: return cdvdRead2A(); + case 0x1f40202B: return cdvdRead2B(); + case 0x1f40202C: return cdvdRead2C(); + case 0x1f402030: return cdvdRead30(); + case 0x1f402031: return cdvdRead31(); + case 0x1f402032: return cdvdRead32(); + case 0x1f402033: return cdvdRead33(); + case 0x1f402034: return cdvdRead34(); + case 0x1f402038: return cdvdRead38(); + case 0x1f402039: return cdvdRead39(); + case 0x1f40203A: return cdvdRead3A(); + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + return 0; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + + return hard; +} + +int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) { + switch (add) { + case 0x1f402004: CONSTREAD8_CALL((u32)cdvdRead04); return 1; + case 0x1f402005: CONSTREAD8_CALL((u32)cdvdRead05); return 1; + case 0x1f402006: CONSTREAD8_CALL((u32)cdvdRead06); return 1; + case 0x1f402007: CONSTREAD8_CALL((u32)cdvdRead07); return 1; + case 0x1f402008: CONSTREAD8_CALL((u32)cdvdRead08); return 1; + case 0x1f40200A: CONSTREAD8_CALL((u32)cdvdRead0A); return 1; + case 0x1f40200B: CONSTREAD8_CALL((u32)cdvdRead0B); return 1; + case 0x1f40200C: CONSTREAD8_CALL((u32)cdvdRead0C); return 1; + case 0x1f40200D: CONSTREAD8_CALL((u32)cdvdRead0D); return 1; + case 0x1f40200E: CONSTREAD8_CALL((u32)cdvdRead0E); return 1; + case 0x1f40200F: CONSTREAD8_CALL((u32)cdvdRead0F); return 1; + case 0x1f402013: CONSTREAD8_CALL((u32)cdvdRead13); return 1; + case 0x1f402015: CONSTREAD8_CALL((u32)cdvdRead15); return 1; + case 0x1f402016: CONSTREAD8_CALL((u32)cdvdRead16); return 1; + case 0x1f402017: CONSTREAD8_CALL((u32)cdvdRead17); return 1; + case 0x1f402018: CONSTREAD8_CALL((u32)cdvdRead18); return 1; + case 0x1f402020: CONSTREAD8_CALL((u32)cdvdRead20); return 1; + case 0x1f402021: CONSTREAD8_CALL((u32)cdvdRead21); return 1; + case 0x1f402022: CONSTREAD8_CALL((u32)cdvdRead22); return 1; + case 0x1f402023: CONSTREAD8_CALL((u32)cdvdRead23); return 1; + case 0x1f402024: CONSTREAD8_CALL((u32)cdvdRead24); return 1; + case 0x1f402028: CONSTREAD8_CALL((u32)cdvdRead28); return 1; + case 0x1f402029: CONSTREAD8_CALL((u32)cdvdRead29); return 1; + case 0x1f40202A: CONSTREAD8_CALL((u32)cdvdRead2A); return 1; + case 0x1f40202B: CONSTREAD8_CALL((u32)cdvdRead2B); return 1; + case 0x1f40202C: CONSTREAD8_CALL((u32)cdvdRead2C); return 1; + case 0x1f402030: CONSTREAD8_CALL((u32)cdvdRead30); return 1; + case 0x1f402031: CONSTREAD8_CALL((u32)cdvdRead31); return 1; + case 0x1f402032: CONSTREAD8_CALL((u32)cdvdRead32); return 1; + case 0x1f402033: CONSTREAD8_CALL((u32)cdvdRead33); return 1; + case 0x1f402034: CONSTREAD8_CALL((u32)cdvdRead34); return 1; + case 0x1f402038: CONSTREAD8_CALL((u32)cdvdRead38); return 1; + case 0x1f402039: CONSTREAD8_CALL((u32)cdvdRead39); return 1; + case 0x1f40203A: CONSTREAD8_CALL((u32)cdvdRead3A); return 1; + default: + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + XOR32RtoR(x86reg, x86reg); + return 0; + } +} + +void psxHw4Write8(u32 add, u8 value) { + switch (add) { + case 0x1f402004: cdvdWrite04(value); return; + case 0x1f402005: cdvdWrite05(value); return; + case 0x1f402006: cdvdWrite06(value); return; + case 0x1f402007: cdvdWrite07(value); return; + case 0x1f402008: cdvdWrite08(value); return; + case 0x1f40200A: cdvdWrite0A(value); return; + case 0x1f40200F: cdvdWrite0F(value); return; + case 0x1f402014: cdvdWrite14(value); return; + case 0x1f402016: + cdvdWrite16(value); + FreezeMMXRegs(0); + return; + case 0x1f402017: cdvdWrite17(value); return; + case 0x1f402018: cdvdWrite18(value); return; + case 0x1f40203A: cdvdWrite3A(value); return; + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value); + return; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHw4ConstWrite8(u32 add, int mmreg) { + switch (add) { + case 0x1f402004: CONSTWRITE_CALL(cdvdWrite04); return; + case 0x1f402005: CONSTWRITE_CALL(cdvdWrite05); return; + case 0x1f402006: CONSTWRITE_CALL(cdvdWrite06); return; + case 0x1f402007: CONSTWRITE_CALL(cdvdWrite07); return; + case 0x1f402008: CONSTWRITE_CALL(cdvdWrite08); return; + case 0x1f40200A: CONSTWRITE_CALL(cdvdWrite0A); return; + case 0x1f40200F: CONSTWRITE_CALL(cdvdWrite0F); return; + case 0x1f402014: CONSTWRITE_CALL(cdvdWrite14); return; + case 0x1f402016: + _freeMMXregs(); + CONSTWRITE_CALL(cdvdWrite16); + return; + case 0x1f402017: CONSTWRITE_CALL(cdvdWrite17); return; + case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; + case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; + default: + SysPrintf("*Unknown 8bit write at address %lx\n", add); + return; + } +} + +void psxDmaInterrupt(int n) { + if (HW_DMA_ICR & (1 << (16 + n))) { + HW_DMA_ICR|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (9 + n); + psxHu32(0x1070) |= 8; + + } +} + +void psxDmaInterrupt2(int n) { + if (HW_DMA_ICR2 & (1 << (16 + n))) { +/* if (HW_DMA_ICR2 & (1 << (24 + n))) { + SysPrintf("*PCSX2*: HW_DMA_ICR2 n=%d already set\n", n); + } + if (psxHu32(0x1070) & 8) { + SysPrintf("*PCSX2*: psxHu32(0x1070) 8 already set (n=%d)\n", n); + }*/ + HW_DMA_ICR2|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (16 + n); + psxHu32(0x1070) |= 8; + } +} diff --git a/branches/pcsx2_0.9.2/PsxHw.h b/branches/pcsx2_0.9.2/PsxHw.h new file mode 100644 index 0000000..c0f4b64 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxHw.h @@ -0,0 +1,117 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXHW_H__ +#define __PSXHW_H__ + +#define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA +#define HW_DMA0_BCR (psxHu32(0x1084)) +#define HW_DMA0_CHCR (psxHu32(0x1088)) + +#define HW_DMA1_MADR (psxHu32(0x1090)) // MDEC out DMA +#define HW_DMA1_BCR (psxHu32(0x1094)) +#define HW_DMA1_CHCR (psxHu32(0x1098)) + +#define HW_DMA2_MADR (psxHu32(0x10a0)) // GPU DMA +#define HW_DMA2_BCR (psxHu32(0x10a4)) +#define HW_DMA2_CHCR (psxHu32(0x10a8)) +#define HW_DMA2_TADR (psxHu32(0x10ac)) + +#define HW_DMA3_MADR (psxHu32(0x10b0)) // CDROM DMA +#define HW_DMA3_BCR (psxHu32(0x10b4)) +#define HW_DMA3_BCR_L16 (psxHu16(0x10b4)) +#define HW_DMA3_BCR_H16 (psxHu16(0x10b6)) +#define HW_DMA3_CHCR (psxHu32(0x10b8)) + +#define HW_DMA4_MADR (psxHu32(0x10c0)) // SPU DMA +#define HW_DMA4_BCR (psxHu32(0x10c4)) +#define HW_DMA4_CHCR (psxHu32(0x10c8)) +#define HW_DMA4_TADR (psxHu32(0x10cc)) + +#define HW_DMA6_MADR (psxHu32(0x10e0)) // GPU DMA (OT) +#define HW_DMA6_BCR (psxHu32(0x10e4)) +#define HW_DMA6_CHCR (psxHu32(0x10e8)) + +#define HW_DMA7_MADR (psxHu32(0x1500)) // SPU2 DMA +#define HW_DMA7_BCR (psxHu32(0x1504)) +#define HW_DMA7_CHCR (psxHu32(0x1508)) + +#define HW_DMA8_MADR (psxHu32(0x1510)) // DEV9 DMA +#define HW_DMA8_BCR (psxHu32(0x1514)) +#define HW_DMA8_CHCR (psxHu32(0x1518)) + +#define HW_DMA9_MADR (psxHu32(0x1520)) // SIF0 DMA +#define HW_DMA9_BCR (psxHu32(0x1524)) +#define HW_DMA9_CHCR (psxHu32(0x1528)) +#define HW_DMA9_TADR (psxHu32(0x152c)) + +#define HW_DMA10_MADR (psxHu32(0x1530)) // SIF1 DMA +#define HW_DMA10_BCR (psxHu32(0x1534)) +#define HW_DMA10_CHCR (psxHu32(0x1538)) + +#define HW_DMA11_MADR (psxHu32(0x1540)) // SIO2 in +#define HW_DMA11_BCR (psxHu32(0x1544)) +#define HW_DMA11_CHCR (psxHu32(0x1548)) + +#define HW_DMA12_MADR (psxHu32(0x1550)) // SIO2 out +#define HW_DMA12_BCR (psxHu32(0x1554)) +#define HW_DMA12_CHCR (psxHu32(0x1558)) + +#define HW_DMA_PCR (psxHu32(0x10f0)) +#define HW_DMA_ICR (psxHu32(0x10f4)) + +#define HW_DMA_PCR2 (psxHu32(0x1570)) +#define HW_DMA_ICR2 (psxHu32(0x1574)) + +#define PSX_INT(n, ecycle) \ + psxRegs.interrupt|= 1 << n; \ + g_psxNextBranchCycle = min(g_psxNextBranchCycle, psxRegs.cycle+ecycle); \ + psxRegs.sCycle[n] = psxRegs.cycle; \ + psxRegs.eCycle[n] = ecycle; + + +void psxHwReset(); +u8 psxHwRead8 (u32 add); +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign); + +u16 psxHwRead16(u32 add); +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign); + +u32 psxHwRead32(u32 add); +int psxHwConstRead32(u32 x86reg, u32 add); + +void psxHwWrite8 (u32 add, u8 value); +void psxHwConstWrite8(u32 add, int mmreg); + +void psxHwWrite16(u32 add, u16 value); +void psxHwConstWrite16(u32 add, int mmreg); + +void psxHwWrite32(u32 add, u32 value); +void psxHwConstWrite32(u32 add, int mmreg); + +u8 psxHw4Read8 (u32 add); +int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign); + +void psxHw4Write8(u32 add, u8 value); +void psxHw4ConstWrite8(u32 add, int mmreg); + +int psxHwFreeze(gzFile f, int Mode); +void psxDmaInterrupt(int n); +void psxDmaInterrupt2(int n); + +#endif /* __PSXHW_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxInterpreter.c b/branches/pcsx2_0.9.2/PsxInterpreter.c new file mode 100644 index 0000000..ebd9739 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxInterpreter.c @@ -0,0 +1,782 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +//#include "PsxBios2.h" + +static int branch = 0; +static int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef PSXCPU_LOG +#define debugI() \ + if (Log) { \ + PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); \ + } +#else +#define debugI() +#endif + +#define execI() { \ + psxRegs.code = PSXMu32(psxRegs.pc); \ + \ + debugI(); \ + psxRegs.pc+= 4; \ + psxRegs.cycle++; \ + \ + psxBSC[psxRegs.code >> 26](); \ + EEsCycle-= (psxRegs.cycle - IOPoCycle) << 3; \ + IOPoCycle = psxRegs.cycle; \ +} + +#define doBranch(tar) { \ + branch2 = branch = 1; \ + branchPC = tar; \ + execI(); \ + branch = 0; \ + psxRegs.pc = branchPC; \ + \ + psxBranchTest(); \ +} + +// Subsets +void (*psxBSC[64])(); +void (*psxSPC[64])(); +void (*psxREG[32])(); +void (*psxCP0[32])(); +void (*psxCP2[64])(); +void (*psxCP2BSC[32])(); + +extern void bios_write(); +extern void bios_printf(); + +typedef struct { + char name[8]; + char names[64][32]; + int maxn; +} irxlib; + +#define IRXLIBS 14 +irxlib irxlibs[32] = { +/*00*/ { { "sysmem" } , + { "start", "init_memory", "retonly", "return_addr_of_memsize", + "AllocSysMemory", "FreeSysMemory", "QueryMemSize", "QueryMaxFreeMemSize", + "QueryTotalFreeMemSize", "QueryBlockTopAddress", "QueryBlockSize", "retonly", + "retonly", "retonly", "Kprintf", "set_Kprintf" } , + 16 }, +/*01*/ { { "loadcore" } , + { "start", "retonly", "retonly_", "return_LibraryEntryTable", + "FlushIcache", "FlushDcache", "RegisterLibraryEntries", "ReleaseLibraryEntries", + "findFixImports", "restoreImports", "RegisterNonAutoLinkEntries", "QueryLibraryEntryTable", + "QueryBootMode", "RegisterBootMode", "setFlag", "resetFlag", + "linkModule", "unlinkModule", "retonly_", "retonly_", + "registerFunc", "jumpA0001B34", "read_header", "load_module", + "findImageInfo" }, + 25 }, +/*02*/ { { "excepman" } , + { "start", "reinit", "deinit", "getcommon", + "RegisterExceptionHandler", "RegisterPriorityExceptionHandler", + "RegisterDefaultExceptionHandler", "ReleaseExceptionHandler", + "ReleaseDefaultExceptionHandler" } , + 9 }, +/*03_4*/{ { "intrman" } , + { "start", "return_0", "deinit", "call3", + "RegisterIntrHandler", "ReleaseIntrHandler", "EnableIntr", "DisableIntr", + "CpuDisableIntr", "CpuEnableIntr", "syscall04", "syscall08", + "resetICTRL", "setICTRL", "syscall0C", "call15", + "call16", "CpuSuspendIntr", "CpuResumeIntr", "CpuSuspendIntr", + "CpuResumeIntr", "syscall10", "syscall14", "QueryIntrContext", + "QueryIntrStack", "iCatchMultiIntr", "retonly", "call27", + "set_h1", "reset_h1", "set_h2", "reset_h2" } , + 0x20 }, +/*05*/ { { "ssbusc" } , + { "start", "retonly", "return_0", "retonly", + "setTable1", "getTable1", "setTable2", "getTable2", + "setCOM_DELAY_1st", "getCOM_DELAY_1st", "setCOM_DELAY_2nd", "getCOM_DELAY_2nd", + "setCOM_DELAY_3rd", "getCOM_DELAY_3rd", "setCOM_DELAY_4th", "getCOM_DELAY_4th", + "setCOM_DELAY", "getCOM_DELAY" } , + 18 }, +/*06*/ { { "dmacman" } , + { "start", "retonly", "deinit", "retonly", + "SetD_MADR", "GetD_MADR", "SetD_BCR", "GetD_BCR", + "SetD_CHCR", "GetD_CHCR", "SetD_TADR", "GetD_TADR", + "Set_4_9_A", "Get_4_9_A", "SetDPCR", "GetDPCR", + "SetDPCR2", "GetDPCR2", "SetDPCR3", "GetDPCR3", + "SetDICR", "GetDICR", "SetDICR2", "GetDICR2", + "SetBF80157C", "GetBF80157C", "SetBF801578", "GetBF801578", + "SetDMA", "SetDMA_chainedSPU_SIF0", "SetDMA_SIF0", "SetDMA_SIF1", + "StartTransfer", "SetVal", "EnableDMAch", "DisableDMAch" } , + 36 }, +/*07_8*/{ { "timrman" } , + { "start", "retonly", "retonly", "call3", + "AllocHardTimer", "ReferHardTimer", "FreeHardTimer", "SetTimerMode", + "GetTimerStatus", "SetTimerCounter", "GetTimerCounter", "SetTimerCompare", + "GetTimerCompare", "SetHoldMode", "GetHoldMode", "GetHoldReg", + "GetHardTimerIntrCode" } , + 17 }, +/*09*/ { { "sysclib" } , + { "start", "reinit", "retonly", "retonly", + "setjmp", "longjmp", "toupper", "tolower", + "look_ctype_table", "get_ctype_table", "memchr", "memcmp", + "memcpy", "memmove", "memset", "bcmp", + "bcopy", "bzero", "prnt", "sprintf", + "strcat", "strchr", "strcmp", "strcpy", + "strcspn", "index", "rindex", "strlen", + "strncat", "strncmp", "strncpy", "strpbrk", + "strrchr", "strspn", "strstr", "strtok", + "strtol", "atob", "strtoul", "wmemcopy", + "wmemset", "vsprintf" } , + 0x2b }, +/*0A*/ { { "heaplib" } , + { "start", "retonly", "retonly", "retonly", + "CreateHeap", "DestroyHeap", "HeapMalloc", "HeapFree", + "HeapSize", "retonly", "retonly", "call11", + "call12", "call13", "call14", "call15", + "retonly", "retonly" } , + 18 }, +/*13*/ { { "stdio" } , + { "start", "unknown", "unknown", "unknown", + "printf" } , + 5 }, +/*14*/ { { "sifman" } , + { "start", "retonly", "deinit", "retonly", + "sceSif2Init", "sceSifInit", "sceSifSetDChain", "sceSifSetDma", + "sceSifDmaStat", "sceSifSend", "sceSifSendSync", "sceSifIsSending", + "sceSifSetSIF0DMA", "sceSifSendSync0", "sceSifIsSending0", "sceSifSetSIF1DMA", + "sceSifSendSync1", "sceSifIsSending1", "sceSifSetSIF2DMA", "sceSifSendSync2", + "sceSifIsSending2", "getEEIOPflags", "setEEIOPflags", "getIOPEEflags", + "setIOPEEflags", "getEErcvaddr", "getIOPrcvaddr", "setIOPrcvaddr", + "call28", "sceSifCheckInit", "setSif0CB", "resetSif0CB", + "retonly", "retonly", "retonly", "retonly" } , + 36 }, +/*16*/ { { "sifcmd" } , + { "start", "retonly", "deinit", "retonly", + "sceSifInitCmd", "sceSifExitCmd", "sceSifGetSreg", "sceSifSetSreg", + "sceSifSetCmdBuffer", "sceSifSetSysCmdBuffer", + "sceSifAddCmdHandler", "sceSifRemoveCmdHandler", + "sceSifSendCmd", "isceSifSendCmd", "sceSifInitRpc", "sceSifBindRpc", + "sceSifCallRpc", "sceSifRegisterRpc", + "sceSifCheckStatRpc", "sceSifSetRpcQueue", + "sceSifGetNextRequest", "sceSifExecRequest", + "sceSifRpcLoop", "sceSifGetOtherData", + "sceSifRemoveRpc", "sceSifRemoveRpcQueue", + "setSif1CB", "resetSif1CB", + "retonly", "retonly", "retonly", "retonly" } , + 32 }, +/*19*/ { { "cdvdman" } , + { "start", "retonly", "retonly", "retonly", + "sceCdInit", "sceCdStandby", "sceCdRead", "sceCdSeek", + "sceCdGetError", "sceCdGetToc", "sceCdSearchFile", "sceCdSync", + "sceCdGetDiskType", "sceCdDiskReady", "sceCdTrayReq", "sceCdStop", + "sceCdPosToInt", "sceCdIntToPos", "retonly", "call19", + "sceDvdRead", "sceCdCheckCmd", "_sceCdRI", "sceCdWriteILinkID", + "sceCdReadClock", "sceCdWriteRTC", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdStatus", "sceCdApplySCmd", "setHDmode", "sceCdOpenConfig", + "sceCdCloseConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdReadKey", + "sceCdDecSet", "sceCdCallback", "sceCdPause", "sceCdBreak", + "call40", "sceCdReadConsoleID", "sceCdWriteConsoleID", "sceCdGetMecaconVersion", + "sceCdGetReadPos", "AudioDigitalOut", "sceCdNop", "_sceGetFsvRbuf", + "_sceCdstm0Cb", "_sceCdstm1Cb", "_sceCdSC", "_sceCdRC", + "sceCdForbidDVDP", "sceCdReadSubQ", "sceCdApplyNCmd", "AutoAdjustCtrl", + "sceCdStInit", "sceCdStRead", "sceCdStSeek", "sceCdStStart", + "sceCdStStat", "sceCdStStop" } , + 62 }, +/*??*/ { { "sio2man" } , + { "start", "retonly", "deinit", "retonly", + "set8268_ctrl", "get8268_ctrl", "get826C_recv1", "call7_send1", + "call8_send1", "call9_send2", "call10_send2", "get8270_recv2", + "call12_set_params", "call13_get_params", "get8274_recv3", "set8278", + "get8278", "set827C", "get827C", "set8260_datain", + "get8264_dataout", "set8280_intr", "get8280_intr", "signalExchange1", + "signalExchange2", "packetExchange" } , + 26 } +}; + +#define Ra0 ((char*)PSXM(psxRegs.GPR.n.a0)) +#define Ra1 ((char*)PSXM(psxRegs.GPR.n.a1)) +#define Ra2 ((char*)PSXM(psxRegs.GPR.n.a2)) +#define Ra3 ((char*)PSXM(psxRegs.GPR.n.a3)) + +char* intrname[]={ +"INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00 +"INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04 +"INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08 +"INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C +"INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10 +"INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14 +"INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18 +"INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C +"INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20 +"INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24 +"INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28 +"INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C +"INT_30", "INT_31", "INT_32", "INT_33", //30 +"INT_34", "INT_35", "INT_36", "INT_37", //34 +"INT_38", "INT_39", "INT_3A", "INT_3B", //38 +"INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C +"INT_MAX" //40 +}; + +void zeroEx() { + u32 pc; + u32 code; + char *lib; + char *fname = NULL; + int i; + + if (!Config.PsxOut) return; + + pc = psxRegs.pc; + while (PSXMu32(pc) != 0x41e00000) pc-=4; + + lib = (char*)PSXM(pc+12); + code = PSXMu32(psxRegs.pc - 4) & 0xffff; + + for (i=0; i= (u32)irxlibs[i].maxn) break; + + fname = irxlibs[i].names[code]; break; + } + } + +#ifdef PSXBIOS_LOG + {char libz[9]; memcpy(libz, lib, 8); libz[8]=0; + PSXBIOS_LOG("%s: %s (%x)" + " (%x, %x, %x, %x)" //comment this line to disable param showing + , libz, fname == NULL ? "unknown" : fname, code, + psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + } +#endif + +// Log=0; +// if (!strcmp(lib, "intrman") && code == 0x11) Log=1; +// if (!strcmp(lib, "sifman") && code == 0x5) Log=1; +// if (!strcmp(lib, "sifcmd") && code == 0x4) Log=1; +// if (!strcmp(lib, "thbase") && code == 0x6) Log=1; +/* + if (!strcmp(lib, "sifcmd") && code == 0xe) { + branchPC = psxRegs.GPR.n.ra; + psxRegs.GPR.n.v0 = 0; + return; + } +*/ + if (!strncmp(lib, "ioman", 5) && code == 7) { + if (psxRegs.GPR.n.a0 == 1) { + pc = psxRegs.pc; + bios_write(); + psxRegs.pc = pc; + } + } + + if (!strncmp(lib, "sysmem", 6) && code == 0xe) { + bios_printf(); + psxRegs.pc = psxRegs.GPR.n.ra; + } + + if (!strncmp(lib, "loadcore", 8) && code == 6) { + SysPrintf("loadcore RegisterLibraryEntries (%x): %8.8s\n", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12)); + } + + if (!strncmp(lib, "intrman", 7) && code == 4) { + SysPrintf("intrman RegisterIntrHandler (%x): intr %s, handler %x\n", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2); + } + + if (!strncmp(lib, "sifcmd", 6) && code == 17) { + SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1); + } + +#ifdef PSXBIOS_LOG + if (!strncmp(lib, "sysclib", 8)) { + switch (code) { + case 0x16: // strcmp + if (varLog & 0x00800000) EMU_LOG(" \"%s\": \"%s\"", Ra0, Ra1); + break; + + case 0x1e: // strncpy + if (varLog & 0x00800000) EMU_LOG(" \"%s\"", Ra1); + break; + } + } +#endif + +#ifdef PSXBIOS_LOG + if (varLog & 0x00800000) EMU_LOG("\n"); +#endif + +/* psxRegs.pc = branchPC; + pc = psxRegs.GPR.n.ra; + while (psxRegs.pc != pc) psxCpu->ExecuteBlock(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("%s: %s (%x) END\n", lib, fname == NULL ? "unknown" : fname, code); +#endif*/ +} +/*/==========================================CALL LOG +char* getName(char *file, u32 addr){ + FILE *f; u32 a; + static char name[100]; + + f=fopen(file, "r"); + if (!f) + name[0]=0; + else{ + while (!feof(f)){ + fscanf(f, "%08X %s\r\n", &a, name); + if (a==addr)break; + } + fclose(f); + } + return name; +} + +void spyFunctions(){ + register irxImageInfo *iii; + if (psxRegs.pc >= 0x200000) return; + for (iii=(irxImageInfo*)PSXM(0x800); iii && iii->text_size; + iii=iii->next ? (irxImageInfo*)PSXM(iii->next) : NULL) + if (iii->vaddr<=psxRegs.pc && psxRegs.pcvaddr+iii->text_size+iii->data_size+iii->bss_size){ + if (strcmp("secrman_for_cex", PSXM(iii->name))==0){ + char *name=getName("secrman.fun", psxRegs.pc-iii->vaddr); + if (strncmp("__push_params", name, 13)==0){ + PAD_LOG(PSXM(psxRegs.GPR.n.a0), psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + }else{ + PAD_LOG("secrman: %s (ra=%06X cycle=%d)\n", name, psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}}else + if (strcmp("mcman", PSXM(iii->name))==0){ + PAD_LOG("mcman: %s (ra=%06X cycle=%d)\n", getName("mcman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("padman", PSXM(iii->name))==0){ + PAD_LOG("padman: %s (ra=%06X cycle=%d)\n", getName("padman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("sio2man", PSXM(iii->name))==0){ + PAD_LOG("sio2man: %s (ra=%06X cycle=%d)\n", getName("sio2man.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);} + break; + } +} +*/ +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow) +void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im +void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im +void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im +void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im +void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed) +void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow) +void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt +void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow) +void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt +void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt +void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt +void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt +void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt +void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed) +void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void psxDIV() { + if (_rRt_ != 0) { + _rLo_ = _i32(_rRs_) / _i32(_rRt_); + _rHi_ = _i32(_rRs_) % _i32(_rRt_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi +void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs +void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +void psxBREAK() { + // Break exception - psx rom doens't handles this + psxRegs.pc -= 4; + psxException(0x24, branch); +} + +void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); + +} + +void psxRFE() { +// SysPrintf("RFE\n"); + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +// Log=0; +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_); + +void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +void psxJ() { doBranch(_JumpTarget_); } +void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); /*spyFunctions();*/ } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void psxJR() { doBranch(_u32(_rRs_)); } +void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); } + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +void psxLB() { + if (_Rt_) { + _rRt_ = (s8 )psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + if (_Rt_) { + _rRt_ = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + if (_Rt_) { + _rRt_ = (s16)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + if (_Rt_) { + _rRt_ = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + if (_Rt_) { + _rRt_ = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +void psxLWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) | + ( mem << (24 - shift) ); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + + */ +} + +void psxLWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) | + ( mem >> shift ); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + + */ +} + +void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +void psxSWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) | + ( mem & (0xffffff00 << shift) )); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + + */ +} + +void psxSWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) | + (mem & (0x00ffffff >> (24 - shift)) ) ) ); + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } +void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } + +void psxMTC0() { _rFs_ = _u32(_rRt_); } +void psxCTC0() { _rFs_ = _u32(_rRt_); } + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +void psxNULL() { +SysPrintf("psx: Unimplemented op %x\n", psxRegs.code); +} + +void psxSPECIAL() { + psxSPC[_Funct_](); +} + +void psxREGIMM() { + psxREG[_Rt_](); +} + +void psxCOP0() { + psxCP0[_Rs_](); +} + +void psxCOP2() { + psxCP2[_Funct_](); +} + +void psxBASIC() { + psxCP2BSC[_Rs_](); +} + + +void (*psxBSC[64])() = { + psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, + psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , + psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL +}; + + +void (*psxSPC[64])() = { + psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV, + psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL, + psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL, + psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL, + psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR , + psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL +}; + +void (*psxREG[32])() = { + psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP0[32])() = { + psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP2[64])() = { + psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08 + psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38 +}; + +void (*psxCP2BSC[32])() = { + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + + +/////////////////////////////////////////// + +static int intInit() { + return 0; +} + +static void intReset() { +} + +static void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + while (EEsCycle > 0){ + branch2 = 0; + while (!branch2) + execI(); + } +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; diff --git a/branches/pcsx2_0.9.2/PsxMem.c b/branches/pcsx2_0.9.2/PsxMem.c new file mode 100644 index 0000000..31b5d14 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxMem.c @@ -0,0 +1,1605 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" +#include "VU.h" +#include "iCore.h" +#include "ir3000A.h" + +extern u32 g_psxMaxRecMem; +int g_psxWriteOk=1; +static u32 writectrl; + +#ifdef WIN32_VIRTUAL_MEM + +int psxMemInit() +{ + // all mem taken care by memInit + return 0; +} + +void psxMemReset() +{ + memset(psxM, 0, 0x00200000); +} + +void psxMemShutdown() +{ +} + +#ifdef _DEBUG + +#define ASSERT_WRITEOK \ +{ \ + __asm cmp g_psxWriteOk, 1 \ + __asm je WriteOk \ + __asm int 10 \ +} \ +WriteOk: \ + +#else +#define ASSERT_WRITEOK +#endif + +u8 psxMemRead8(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + break; + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + mem &= 0x1fffffff; + return psxHw4Read8(mem); + + case 0x1000: return DEV9read8(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u8*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f40 + je hw4read + cmp dx, 0x1000 + je devread + cmp dx, 0x1f00 + je spuread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead8 + add esp, 4 + ret + +hw4read: + push ecx + call psxHw4Read8 + add esp, 4 + ret + +devread: + push ecx + call DEV9read8 + // stack already incremented + ret + +spuread: + push ecx + call SPU2read + // stack already incremented + ret + } +} + +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + return psxHwConstRead8(x86reg, mem&0x1fffffff, sign); + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + return psxHw4ConstRead8(x86reg, mem&0x1fffffff, sign); + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(x86reg, EAX); + else MOVZX32R8toR(x86reg, EAX); + return 0; + + default: + _eeReadConstMem8(x86reg, (u32)PSXM(mem), sign); + return 0; + } +} + +u16 psxMemRead16(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu16(0x1000F240) | 0x0002; + case 0x60: return 0; + default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1f90: + return SPU2read(mem & 0x1FFFFFFF); + case 0x1000: + return DEV9read16(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u16*)PSXM(mem); + } +} + +__declspec(naked) void psxRecMemRead16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f90 + je spuread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead16 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 2 + jmp End +Sif60: + xor eax, eax + jmp End + +spuread: + push ecx + call SPU2read + // stack already incremented + +End: + ret + +devread: + push ecx + call DEV9read16 + // stack already incremented + ret + } +} + +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead16(x86reg, mem&0x1fffffff, sign); + + case 0x1d00: + + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xF240, sign); + OR32ItoR(x86reg, 0x0002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0), sign); + break; + } + return 0; + + case 0x1f90: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + default: + assert( g_psxWriteOk ); + _eeReadConstMem16(x86reg, (u32)PSXM(mem), sign); + return 0; + } + + return 0; +} + +u32 psxMemRead32(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu32(0x1000F240) | 0xF0000002; + case 0x60: return 0; + default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1fff: return g_psxWriteOk; + case 0x1000: + return DEV9read32(mem & 0x1FFFFFFF); + + default: + //assert(g_psxWriteOk); + if( mem == 0xfffe0130 ) + return writectrl; + else if( mem == 0xffffffff ) + return writectrl; + else if( g_psxWriteOk ) + return *(u32*)PSXM(mem); + else return 0; + } +} + +__declspec(naked) void psxRecMemRead32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + cmp ecx, 0x1ffe0130 + je WriteCtrlRead + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead32 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + // do the read from ps2 mem + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 0xf0000002 + jmp End +Sif60: + xor eax, eax +End: + ret + +devread: + push ecx + call DEV9read32 + // stack already incremented + ret + +WriteCtrlRead: + mov eax, writectrl + ret + } +} + +int psxRecMemConstRead32(u32 x86reg, u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead32(x86reg, mem&0x1fffffff); + + case 0x1d00: + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xF240); + OR32ItoR(x86reg, 0xf0000002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0)); + break; + } + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9read32); + return 1; + + default: + if( mem == 0xfffe0130 ) + MOV32MtoR(x86reg, (u32)&writectrl); + else { + XOR32RtoR(x86reg, x86reg); + CMP32ItoM((u32)&g_psxWriteOk, 0); + CMOVNE32MtoR(x86reg, (u32)PSXM(mem)); + } + + return 0; + } +} + +void psxMemWrite8(u32 mem, u8 value) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + break; + + case 0x1f40: + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + break; + + case 0x1d00: + SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + *(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value; + break; + + case 0x1000: + DEV9write8(mem & 0x1fffffff, value); + return; + + default: + assert(g_psxWriteOk); + *(u8 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f40 + je hw4write + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov byte ptr [ecx+PS2MEM_BASE_], al + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite8 + add esp, 8 + ret + +hw4write: + push eax + push ecx + call psxHw4Write8 + add esp, 8 + ret + +devwrite: + push eax + push ecx + call DEV9write8 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite8(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + psxHwConstWrite8(mem&0x1fffffff, mmreg); + return 0; + case 0x1f40: + psxHw4ConstWrite8(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + assert(0); + _eeWriteConstMem8((u32)(PS2MEM_HW+0xf200+(mem&0xff)), mmreg); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write8); + return 0; + + default: + _eeWriteConstMem8((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite16(u32 mem, u16 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + default: + assert(0); + } + return; + + case 0x1f90: + SPU2write(mem & 0x1FFFFFFF, value); return; + + case 0x1000: + DEV9write16(mem & 0x1fffffff, value); return; + default: + assert( g_psxWriteOk ); + *(u16 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +__declspec(naked) void psxRecMemWrite16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f90 + je spuwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov word ptr [ecx+PS2MEM_BASE_], ax + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite16 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif60: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +spuwrite: + push eax + push ecx + call SPU2write + // stack alwritey incremented + ret + +devwrite: + push eax + push ecx + call DEV9write16 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite16(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite16(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem16((u32)(PS2MEM_HW+0xf210), mmreg); + return 0; + case 0x40: + { + // delete x86reg + _eeMoveMMREGtoR(EAX, mmreg); + + assert( mmreg != EBX ); + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1f90: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)SPU2write); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write16); + return 0; + + default: + _eeWriteConstMem16((u32)PSXM(mem), mmreg); + return 1; + } +} + +void psxMemWrite32(u32 mem, u32 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + default: + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + } + + return; + + case 0x1000: + DEV9write32(mem & 0x1fffffff, value); + return; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + g_psxWriteOk = 0; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + g_psxWriteOk = 1; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + break; + + default: + + if( g_psxWriteOk ) { + *(u32 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + } + + break; + } +} + +__declspec(naked) void psxRecMemWrite32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + cmp dx, 0x1ffe + je WriteCtrl + } + + __asm { + // rom writes, has to be PS2MEM_BASE_ + test g_psxWriteOk, 1 + jz endwrite + +memwrite: + mov dword ptr [ecx+PS2MEM_BASE_], eax +endwrite: + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + cmp dl, 0x30 + je Sif30 + cmp dl, 0x20 + je Sif20 + + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif30: + or dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif20: + not eax + and dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif60: + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +devwrite: + push eax + push ecx + call DEV9write32 + // stack alwritey incremented + ret + +WriteCtrl: + cmp ecx, 0x1ffe0130 + jne End + + mov writectrl, eax + + cmp eax, 0x800 + je SetWriteNotOk + cmp eax, 0x804 + je SetWriteNotOk + cmp eax, 0xc00 + je SetWriteNotOk + cmp eax, 0xc04 + je SetWriteNotOk + cmp eax, 0xcc0 + je SetWriteNotOk + cmp eax, 0xcc4 + je SetWriteNotOk + cmp eax, 0x0c4 + je SetWriteNotOk + + // test ok + cmp eax, 0x1e988 + je SetWriteOk + cmp eax, 0x1edd8 + je SetWriteOk + +End: + ret + +SetWriteNotOk: + mov g_psxWriteOk, 0 + ret +SetWriteOk: + mov g_psxWriteOk, 1 + ret + } +} + +int psxRecMemConstWrite32(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite32(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem32((u32)PS2MEM_HW+0xf210, mmreg); + return 0; + case 0x20: + // write to ps2 mem + // delete x86reg + if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM((u32)PS2MEM_HW+0xf220, ~g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else { + NOT32R(mmreg); + AND32RtoM((u32)PS2MEM_HW+0xf220, mmreg); + } + return 0; + case 0x30: + // write to ps2 mem + _eeWriteConstMem32OP((u32)PS2MEM_HW+0xf230, mmreg, 1); + return 0; + case 0x40: + { + // delete x86reg + assert( mmreg != EBX ); + + _eeMoveMMREGtoR(EAX, mmreg); + + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + u8* ptrs[9]; + + _eeWriteConstMem32((u32)&writectrl, mmreg); + + if( IS_PSXCONSTREG(mmreg) ) { + switch (g_psxConstRegs[(mmreg>>16)&0x1f]) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + MOV32ItoM((u32)&g_psxWriteOk, 0); + break; + case 0x1e988: + case 0x1edd8: + MOV32ItoM((u32)&g_psxWriteOk, 1); + break; + default: + assert(0); + } + } + else { + // not ok + CMP32ItoR(mmreg, 0x800); + ptrs[0] = JE8(0); + CMP32ItoR(mmreg, 0x804); + ptrs[1] = JE8(0); + CMP32ItoR(mmreg, 0xc00); + ptrs[2] = JE8(0); + CMP32ItoR(mmreg, 0xc04); + ptrs[3] = JE8(0); + CMP32ItoR(mmreg, 0xcc0); + ptrs[4] = JE8(0); + CMP32ItoR(mmreg, 0xcc4); + ptrs[5] = JE8(0); + CMP32ItoR(mmreg, 0x0c4); + ptrs[6] = JE8(0); + + // ok + CMP32ItoR(mmreg, 0x1e988); + ptrs[7] = JE8(0); + CMP32ItoR(mmreg, 0x1edd8); + ptrs[8] = JE8(0); + + x86SetJ8(ptrs[0]); + x86SetJ8(ptrs[1]); + x86SetJ8(ptrs[2]); + x86SetJ8(ptrs[3]); + x86SetJ8(ptrs[4]); + x86SetJ8(ptrs[5]); + x86SetJ8(ptrs[6]); + MOV32ItoM((u32)&g_psxWriteOk, 0); + ptrs[0] = JMP8(0); + + x86SetJ8(ptrs[7]); + x86SetJ8(ptrs[8]); + MOV32ItoM((u32)&g_psxWriteOk, 1); + + x86SetJ8(ptrs[0]); + } + } + return 0; + + default: + TEST8ItoM((u32)&g_psxWriteOk, 1); + j8Ptr[0] = JZ8(0); + _eeWriteConstMem32((u32)PSXM(mem), mmreg); + x86SetJ8(j8Ptr[0]); + return 1; + } +} + +#else + +// TLB functions + +s8 *psxM; +s8 *psxP; +s8 *psxH; +s8 *psxS; +uptr *psxMemWLUT; +uptr *psxMemRLUT; + +int psxMemInit() +{ + int i; + + psxMemRLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + memset(psxMemRLUT, 0, 0x10000 * sizeof(uptr)); + memset(psxMemWLUT, 0, 0x10000 * sizeof(uptr)); + + psxM = (char*)_aligned_malloc(0x00200000,16); + psxP = (char*)_aligned_malloc(0x00010000,16); + psxH = (char*)_aligned_malloc(0x00010000,16); + psxS = (char*)_aligned_malloc(0x00010000,16); + if (psxMemRLUT == NULL || psxMemWLUT == NULL || + psxM == NULL || psxP == NULL || psxH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + memset(psxH, 0, 0x00010000); + memset(psxS, 0, 0x00010000); + + +// MemR + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x9fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0xbfc0] = (uptr)&PS2MEM_ROM[i << 16]; + + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x9e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0xbe00] = (uptr)&PS2MEM_ROM1[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + +// MemW + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + +// for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16]; + +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + + return 0; +} + +void psxMemReset() { + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + //memset(psxS, 0, 0x00010000); +} + +void psxMemShutdown() +{ + _aligned_free(psxM); + _aligned_free(psxP); + _aligned_free(psxH); + _aligned_free(psxMemRLUT); + _aligned_free(psxMemWLUT); +} + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + return psxHw4Read8(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + return *(u8 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lb %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u16 psxMemRead16(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u16 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu16(0x1000F200); + break; + case 0x10: + ret= psHu16(0x1000F210); + break; + case 0x40: + ret= psHu16(0x1000F240) | 0x0002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu16(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u16 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1F90) + return SPU2read(mem & 0x1FFFFFFF); + if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lh %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u32 psxMemRead32(u32 mem) { + char *p; + u32 t; + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + //see also Hw.c + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u32 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu32(0x1000F200); + break; + case 0x10: + ret= psHu32(0x1000F210); + break; + case 0x20: + ret= psHu32(0x1000F220); + break; + case 0x30: // EE Side + ret= psHu32(0x1000F230); + break; + case 0x40: + ret= psHu32(0x1000F240) | 0xF0000002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu32(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u32 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); + + if (mem != 0xfffe0130) { +#ifdef PSXMEM_LOG + if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); +#endif + } else { + return writectrl; + } + return 0; + } + } +} + +void psxMemWrite8(u32 mem, u8 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u8 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + if (t == 0x1d00) { + psxSu8(mem) = value; return; + } + if (t == 0x1000) { + DEV9write8(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite16(u32 mem, u16 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); + *(u16 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (t == 0x1d00) { + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu16(mem) = value; return; + } + if (t == 0x1F90) { + SPU2write(mem & 0x1FFFFFFF, value); return; + } + if (t == 0x1000) { + DEV9write16(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite32(u32 mem, u32 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + } else { + //see also Hw.c + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u32 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (mem != 0xfffe0130) { + if (t == 0x1d00) { +#ifdef MEM_LOG + MEM_LOG("iop Sif reg write %x value %x\n", mem, value); +#endif + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu32(mem) = value; + + // write to ps2 mem + if( (mem & 0xf0) != 0x60 ) + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + return; + } + if (t == 0x1000) { + DEV9write32(mem & 0x1fffffff, value); return; + } + + //if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); +#ifdef PSXMEM_LOG + if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } +#endif + } else { + int i; + + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + if (g_psxWriteOk == 0) break; + g_psxWriteOk = 0; + memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(uptr)); +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + if (g_psxWriteOk == 1) break; + g_psxWriteOk = 1; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + } + } +} + +#endif diff --git a/branches/pcsx2_0.9.2/PsxMem.h b/branches/pcsx2_0.9.2/PsxMem.h new file mode 100644 index 0000000..b9d861b --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxMem.h @@ -0,0 +1,113 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#ifdef WIN32_VIRTUAL_MEM + +// VM +#define psxM PS2MEM_PSX +#define psxH PS2MEM_PSXHW + +#define PSXM(mem) ((mem&0x10000000)?PSM(mem):(PS2MEM_PSX+(mem&0x1fffff))) +#define _PSXM(mem) PSXM(mem) + +#else + +// TLB +extern s8 *psxM; +extern s8 *psxP; +extern s8 *psxH; +extern s8 *psxS; +extern uptr *psxMemWLUT; +extern uptr *psxMemRLUT; + +#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) +#define _PSXM(mem) ((void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) + +#define psxSs8(mem) psxS[(mem) & 0xffff] +#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) +#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) +#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) +#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) +#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) + +#endif + +#define psxMs8(mem) psxM[(mem) & 0x1fffff] +#define psxMs16(mem) (*(s16*)&psxM[(mem) & 0x1fffff]) +#define psxMs32(mem) (*(s32*)&psxM[(mem) & 0x1fffff]) +#define psxMu8(mem) (*(u8*) &psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (*(u16*)&psxM[(mem) & 0x1fffff]) +#define psxMu32(mem) (*(u32*)&psxM[(mem) & 0x1fffff]) +#define psxMu64(mem) (*(u64*)&psxM[(mem) & 0x1fffff]) + +#define psxPs8(mem) psxP[(mem) & 0xffff] +#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) +#define psxPs32(mem) (*(s32*)&psxP[(mem) & 0xffff]) +#define psxPu8(mem) (*(u8*) &psxP[(mem) & 0xffff]) +#define psxPu16(mem) (*(u16*)&psxP[(mem) & 0xffff]) +#define psxPu32(mem) (*(u32*)&psxP[(mem) & 0xffff]) + +#define psxHs8(mem) psxH[(mem) & 0xffff] +#define psxHs16(mem) (*(s16*)&psxH[(mem) & 0xffff]) +#define psxHs32(mem) (*(s32*)&psxH[(mem) & 0xffff]) +#define psxHu8(mem) (*(u8*) &psxH[(mem) & 0xffff]) +#define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff]) +#define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff]) + +#define PSXMs8(mem) (*(s8 *)_PSXM(mem)) +#define PSXMs16(mem) (*(s16*)_PSXM(mem)) +#define PSXMs32(mem) (*(s32*)_PSXM(mem)) +#define PSXMu8(mem) (*(u8 *)_PSXM(mem)) +#define PSXMu16(mem) (*(u16*)_PSXM(mem)) +#define PSXMu32(mem) (*(u32*)_PSXM(mem)) + +int psxMemInit(); +void psxMemReset(); +void psxMemShutdown(); + +u8 psxMemRead8 (u32 mem); +u16 psxMemRead16(u32 mem); +u32 psxMemRead32(u32 mem); +void psxMemWrite8 (u32 mem, u8 value); +void psxMemWrite16(u32 mem, u16 value); +void psxMemWrite32(u32 mem, u32 value); + +// x86reg and mmreg are always x86 regs +void psxRecMemRead8(); +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead16(); +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead32(); +int psxRecMemConstRead32(u32 x86reg, u32 mem); + +void psxRecMemWrite8(); +int psxRecMemConstWrite8(u32 mem, int mmreg); + +void psxRecMemWrite16(); +int psxRecMemConstWrite16(u32 mem, int mmreg); + +void psxRecMemWrite32(); +int psxRecMemConstWrite32(u32 mem, int mmreg); + + +#endif /* __PSXMEMORY_H__ */ diff --git a/branches/pcsx2_0.9.2/PsxSio2.c b/branches/pcsx2_0.9.2/PsxSio2.c new file mode 100644 index 0000000..4ca632d --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxSio2.c @@ -0,0 +1,251 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + +/* +w [8268]=0x3bc sio2_start/sio2man +r [8270] padman_start/padman + padman->7480[00]=bit4; + padman->7480[13]=bit5; + packetExchange(&703F8); +w [8268]|=0x0C; +........ +w [8268]|=0x01; + +only recv2 & dataout influences padman +*/ + +// 0xBF808200,0xBF808204,0xBF808208,0xBF80820C, +// 0xBF808210,0xBF808214,0xBF808218,0xBF80821C, packet->sendArray3 +// 0xBF808220,0xBF808224,0xBF808228,0xBF80822C, call12/13_s/getparams +// 0xBF808230,0xBF808234,0xBF808238,0xBF80823C, + +// 0xBF808240,0xBF808248,0xBF808250,0xBF808258, packet->sendArray1/call_7/8 +// 0xBF808244,0xBF80824C,0xBF808254,0xBF80825C, packet->sendArray2/call_9/10 + +// 0xBF808260, serial data/fifo in/out s/get8260_datain/out packet->sendbuf(nomem!) +// 0xBF808268, ctrl s/get8268_ctrl + +// 0xBF80826C, packet->recv1/2/3 get826C_recv1, get8270_recv2, get8274_recv3 +// 0xBF808270,0xBF808274, + +// 0xBF808278,0xBF80827C, s/get8278, s/get827C +// 0xBF808280 interrupt related s/get8280_intr + + +void sio2Reset() { + SysPrintf("Sio2 init\n"); + memset(&sio2, 0, sizeof(sio2)); + sio2.packet.recvVal1 = 0x1D100; // Nothing is connected at start +} + +u32 sio2_getRecv1() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv1 = %x\n",sio2.packet.recvVal1); +#endif + return sio2.packet.recvVal1; +} + +u32 sio2_getRecv2() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv2 = %x\n",0xF); +#endif + return 0xF; +}//0, 0x10, 0x20, 0x10 | 0x20; bits 4 & 5 + +u32 sio2_getRecv3() { + if(sio2.packet.recvVal3 == 0x8C || sio2.packet.recvVal3 == 0x8b || + sio2.packet.recvVal3 == 0x83) + { +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio2.packet.recvVal3); +#endif + sio.packetsize = sio2.packet.recvVal3; + sio2.packet.recvVal3 = 0; // Reset + return sio.packetsize; + }else{ +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio.packetsize << 16); +#endif + return sio.packetsize << 16; + } +} + +void sio2_setSend1(u32 index, u32 value){sio2.packet.sendArray1[index]=value;} //0->3 +u32 sio2_getSend1(u32 index){return sio2.packet.sendArray1[index];} //0->3 +void sio2_setSend2(u32 index, u32 value){sio2.packet.sendArray2[index]=value;} //0->3 +u32 sio2_getSend2(u32 index){return sio2.packet.sendArray2[index];} //0->3 +void sio2_setSend3(u32 index, u32 value) {int i; +/* if (index == 0) { + printf("value: %x\n", value); + }*/ + sio2.packet.sendArray3[index]=value; +#ifdef PAD_LOG + if (index==15){ + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray1[i]);}PAD_LOG("\n"); + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray2[i]);}PAD_LOG("\n"); + for (i=0; i<8; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + for ( ; i<16; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + } +#endif +} //0->15 + +u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //0->15 + +void sio2_setCtrl(u32 value){ + sio2.ctrl=value; + if (sio2.ctrl & 1){ //recv packet + //handle data that had been sent + + //trigger interupt for SIO2 + psxHu32(0x1070)|=0x20000; + //SBUS + hwIntcIrq(INTC_SBUS); + sio2.recvIndex=0; + sio2.ctrl &= ~1; + } else { // send packet + //clean up + sio2.packet.sendSize=0; //reset size + sio2.cmdport=0; + sio2.cmdlength=0; + sioWriteCtrl16(SIO_RESET); + } +} +u32 sio2_getCtrl(){return sio2.ctrl;} + +void sio2_setIntr(u32 value){sio2.intr=value;} +u32 sio2_getIntr(){ + return sio2.intr; +} + +void sio2_set8278(u32 value){sio2._8278=value;} +u32 sio2_get8278(){return sio2._8278;} +void sio2_set827C(u32 value){sio2._827C=value;} +u32 sio2_get827C(){return sio2._827C;} + +void sio2_fifoIn(u8 value){ + u16 ctrl=0x0002; + if (sio2.packet.sendArray3[sio2.cmdport] && (sio2.cmdlength==0)){//else do nothing! + + sio2.cmdlength=(sio2.packet.sendArray3[sio2.cmdport] >> 8) & 0x1FF; + ctrl &= ~0x2000; + ctrl |= (sio2.packet.sendArray3[sio2.cmdport] & 1) << 13;//it is correct this way:P; what did you want to do? + //sioWriteCtrl16(SIO_RESET); + sioWriteCtrl16(ctrl); +#ifdef PSXDMA_LOG + PSXDMA_LOG("sio2_fifoIn: ctrl = %x, cmdlength = %x, cmdport = %d (%x)\n", ctrl, sio2.cmdlength, sio2.cmdport, sio2.packet.sendArray3[sio2.cmdport]); +#endif + sio2.cmdport++;//position in sendArray3 + } + if (sio2.cmdlength) sio2.cmdlength--; + +// sioWriteCtrl16(ctrl); + + sioWrite8(value); + if (sio2.packet.sendSize > BUFSIZE) {//asadr + SysPrintf("*PCSX2*: sendSize >= %d\n", BUFSIZE); + } else { + sio2.buf[sio2.packet.sendSize] = sioRead8(); + sio2.packet.sendSize++; + } +} + +u8 sio2_fifoOut(){ + u8 value=0; + + if (sio2.recvIndex <= sio2.packet.sendSize){ + value = sio2.buf[sio2.recvIndex++]; + } else { + SysPrintf("*PCSX2*: buffer overrun\n"); + } + return value; //no data +} + +///////////////////////////////////////////////// +//////////////////////////////////////////// DMA +///////////////////////////////////////////////// + +void psxDma11(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 11 - SIO2 in *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x01000201) return; + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + PSX_INT(11,(bcr>>2)); + while (bcr > 0) { + sio2_fifoIn(PSXMu8(madr)); + bcr--; madr++; + if(sio2.packet.sendSize == BUFSIZE) break; + } + HW_DMA11_MADR = madr; + HW_DMA11_BCR = bcr; + +} + +int psxDMA11Interrupt() +{ + HW_DMA11_CHCR &= ~0x01000000; + psxDmaInterrupt2(4); + return 1; +} + +void psxDma12(u32 madr, u32 bcr, u32 chcr) { + int wordsize, totalblocks; +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 12 - SIO2 out *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x41000200) return; + + wordsize = (bcr & 0xffff); + totalblocks = (bcr >> 16); + bcr = (totalblocks * wordsize) * 4; // 8 bits + sio2.recvIndex = 0; // Set To start asadr + PSX_INT(12,(bcr>>2)); + while (bcr > 0) { + PSXMu8(madr) = sio2_fifoOut(); + bcr--; madr++; + if(sio2.recvIndex == sio2.packet.sendSize) break; + } + HW_DMA12_MADR = madr; + HW_DMA12_BCR = bcr; + PSX_INT(12,(bcr>>2)); + +} + +int psxDMA12Interrupt() +{ + HW_DMA12_CHCR &= ~0x01000000; + psxDmaInterrupt2(5); + return 1; +} + +int sio2Freeze(gzFile f, int Mode) { + gzfreeze(&sio2, sizeof(sio2)); + + return 0; +} + diff --git a/branches/pcsx2_0.9.2/PsxSio2.h b/branches/pcsx2_0.9.2/PsxSio2.h new file mode 100644 index 0000000..6f5aea8 --- /dev/null +++ b/branches/pcsx2_0.9.2/PsxSio2.h @@ -0,0 +1,98 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXSIO2_H__ +#define __PSXSIO2_H__ + + +#define BUFSIZE 1024 + +//from sio2man.c + +struct SIO2_packet { + unsigned int recvVal1; // 0x00 + unsigned int sendArray1[4]; // 0x04-0x10 + unsigned int sendArray2[4]; // 0x14-0x20 + + unsigned int recvVal2; // 0x24 + + unsigned int sendArray3[16]; // 0x28-0x64 + + unsigned int recvVal3; // 0x68 + + int sendSize; // 0x6C + int recvSize; // 0x70 + + unsigned char *sendBuf; // 0x74 + unsigned char *recvBuf; // 0x78 + + unsigned int dmacAddress1; + unsigned int dmacSize1; + unsigned int dmacCount1; + unsigned int dmacAddress2; + unsigned int dmacSize2; + unsigned int dmacCount2; +}; + +typedef struct { + struct SIO2_packet packet; + u32 ctrl; + u32 intr; + u32 _8278, _827C; + int recvIndex; + u32 hackedRecv; + int cmdport; + int cmdlength; //length of a command sent to a port + //is less_equal than the dma send size + u8 buf[BUFSIZE]; +} sio2Struct; + +sio2Struct sio2; + +void sio2Reset(); +u32 sio2_getRecv1(); +u32 sio2_getRecv2(); +u32 sio2_getRecv3(); +void sio2_setSend1(u32 index, u32 value); //0->3 +u32 sio2_getSend1(u32 index); //0->3 +void sio2_setSend2(u32 index, u32 value); //0->3 +u32 sio2_getSend2(u32 index); //0->3 +void sio2_setSend3(u32 index, u32 value); //0->15 +u32 sio2_getSend3(u32 index); //0->15 + +void sio2_setCtrl(u32 value); +u32 sio2_getCtrl(); +void sio2_setIntr(u32 value); +u32 sio2_getIntr(); +void sio2_set8278(u32 value); +u32 sio2_get8278(); +void sio2_set827C(u32 value); +u32 sio2_get827C(); + +void sio2_fifoIn(u8 value); +u8 sio2_fifoOut(); + +void psxDma11(u32 madr, u32 bcr, u32 chcr); +void psxDma12(u32 madr, u32 bcr, u32 chcr); + +int psxDMA11Interrupt(); +int psxDMA12Interrupt(); +int sio2Freeze(gzFile f, int Mode); + +#endif /* __PSXSIO2_H__ */ + diff --git a/branches/pcsx2_0.9.2/R3000A.c b/branches/pcsx2_0.9.2/R3000A.c new file mode 100644 index 0000000..1c69aaf --- /dev/null +++ b/branches/pcsx2_0.9.2/R3000A.c @@ -0,0 +1,213 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" + +// used for constant propagation +R3000Acpu *psxCpu; +u32 g_psxConstRegs[32]; +u32 g_psxHasConstReg, g_psxFlushedConstReg; + +PCSX2_ALIGNED16(psxRegisters psxRegs); + +int psxInit() +{ + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + +#ifdef PCSX2_DEVBUILD + Log=0; +#endif + + if (psxMemInit() == -1) return -1; + + return psxCpu->Init(); +} + +void psxReset() { + + psxCpu->Reset(); + + psxMemReset(); + + memset(&psxRegs, 0, sizeof(psxRegs)); + + psxRegs.pc = 0xbfc00000; // Start in bootstrap + + psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1 + psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A + + psxHwReset(); + psxBiosInit(); + psxExecuteBios(); +} + +void psxShutdown() { + psxMemShutdown(); + psxBiosShutdown(); + psxCpu->Shutdown(); +} + +void psxException(u32 code, u32 bd) { +// PSXCPU_LOG("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); +// SysPrintf("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); + // Set the Cause + psxRegs.CP0.n.Cause &= ~0x7f; + psxRegs.CP0.n.Cause |= code; + +#ifdef PSXCPU_LOG + if (bd) { PSXCPU_LOG("bd set\n"); } +#endif + // Set the EPC & PC + if (bd) { + psxRegs.CP0.n.Cause|= 0x80000000; + psxRegs.CP0.n.EPC = (psxRegs.pc - 4); + } else + psxRegs.CP0.n.EPC = (psxRegs.pc); + + if (psxRegs.CP0.n.Status & 0x400000) + psxRegs.pc = 0xbfc00180; + else + psxRegs.pc = 0x80000080; + + // Set the Status + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) | + ((psxRegs.CP0.n.Status & 0xf) << 2); + + /*if ((((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) { + // "hokuto no ken" / "Crash Bandicot 2" ... fix + PSXMu32(psxRegs.CP0.n.EPC)&= ~0x02000000; + }*/ + + if (Config.PsxOut && !CHECK_EEREC) { + u32 call = psxRegs.GPR.n.t1 & 0xff; + switch (psxRegs.pc & 0x1fffff) { + case 0xa0: +#ifdef PSXBIOS_LOG + if (call != 0x28 && call != 0xe) { + PSXBIOS_LOG("Bios call a0: %s (%x) %x,%x,%x,%x\n", biosA0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosA0[call]) + biosA0[call](); + break; + case 0xb0: +#ifdef PSXBIOS_LOG + if (call != 0x17 && call != 0xb) { + PSXBIOS_LOG("Bios call b0: %s (%x) %x,%x,%x,%x\n", biosB0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosB0[call]) + biosB0[call](); + break; + case 0xc0: +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("Bios call c0: %s (%x) %x,%x,%x,%x\n", biosC0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); +#endif + if (biosC0[call]) + biosC0[call](); + break; + } + } + + /*if (psxRegs.CP0.n.Cause == 0x400 && (!(psxHu32(0x1450) & 0x8))) { + hwIntcIrq(1); + }*/ +} + +#define PSX_TESTINT(n, callback) \ + if (psxRegs.interrupt & (1 << n)) { \ + if ((int)(psxRegs.cycle - psxRegs.sCycle[n]) >= psxRegs.eCycle[n]) { \ + if (callback() == 1) { \ + psxRegs.interrupt&= ~(1 << n); \ + } \ + } \ + else if( (int)(g_psxNextBranchCycle - psxRegs.sCycle[n]) > psxRegs.eCycle[n] ) \ + g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n]; \ + } + +static void _psxTestInterrupts() { + PSX_TESTINT(4, psxDma4Interrupt); + PSX_TESTINT(7, psxDma7Interrupt); + + PSX_TESTINT(11, psxDMA11Interrupt); // SIO2 + PSX_TESTINT(12, psxDMA12Interrupt); // SIO2 + PSX_TESTINT(16, sioInterrupt); + PSX_TESTINT(17, cdrInterrupt); + PSX_TESTINT(18, cdrReadInterrupt); + PSX_TESTINT(19, cdvdReadInterrupt); + PSX_TESTINT(20, dev9Interrupt); + PSX_TESTINT(21, usbInterrupt); +} + +#define IOP_WAIT_CYCLE 64 + +void psxBranchTest() +{ + EEsCycle -= (psxRegs.cycle - IOPoCycle) << 3; + IOPoCycle = psxRegs.cycle; + if( EEsCycle > 0 ) + g_psxNextBranchCycle = psxRegs.cycle + min(IOP_WAIT_CYCLE, (EEsCycle>>3)); + else + g_psxNextBranchCycle = psxRegs.cycle; + + if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + _psxTestInterrupts(); + } + +// if( (int)psxRegs.cycle-(int)g_psxNextBranchCycle > 0 ) +// g_psxNextBranchCycle = psxRegs.cycle+1; +// else + if( (int)(g_psxNextBranchCycle-psxNextsCounter) >= (u32)psxNextCounter ) + g_psxNextBranchCycle = (u32)psxNextsCounter+(u32)psxNextCounter; + + if (psxHu32(0x1078)) { + if(psxHu32(0x1070) & psxHu32(0x1074)){ + if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) { +//#ifdef PSXCPU_LOG +// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); +//#endif + psxException(0, 0); + } + } + } +} + +void psxExecuteBios() { +/* while (psxRegs.pc != 0x80030000) + psxCpu->ExecuteBlock(); +#ifdef PSX_LOG + PSX_LOG("*BIOS END*\n"); +#endif*/ +} + +void psxRestartCPU() +{ + psxCpu->Shutdown(); + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + + if (psxCpu->Init() == -1) { + SysClose(); + exit(1); + } + psxCpu->Reset(); +} diff --git a/branches/pcsx2_0.9.2/R3000A.h b/branches/pcsx2_0.9.2/R3000A.h new file mode 100644 index 0000000..be1f7f4 --- /dev/null +++ b/branches/pcsx2_0.9.2/R3000A.h @@ -0,0 +1,213 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#include + +extern u32 g_psxNextBranchCycle; + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*Clear)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R3000Acpu; + +extern R3000Acpu *psxCpu; +extern R3000Acpu psxInt; +extern R3000Acpu psxRec; + +typedef union { + struct { + u32 r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra, hi, lo; // hi needs to be at index 32! don't change + } n; + u32 r[34]; /* Lo, Hi in r[33] and r[32] */ +} GPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} CP0Regs; + +typedef struct { + short x, y; +} SVector2D; + +typedef struct { + short z, pad; +} SVector2Dz; + +typedef struct { + short x, y, z, pad; +} SVector3D; + +typedef struct { + short x, y, z, pad; +} LVector3D; + +typedef struct { + unsigned char r, g, b, c; +} CBGR; + +typedef struct { + short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad; +} SMatrix3D; + +typedef union { + struct { + SVector3D v0, v1, v2; + CBGR rgb; + s32 otz; + s32 ir0, ir1, ir2, ir3; + SVector2D sxy0, sxy1, sxy2, sxyp; + SVector2Dz sz0, sz1, sz2, sz3; + CBGR rgb0, rgb1, rgb2; + s32 reserved; + s32 mac0, mac1, mac2, mac3; + u32 irgb, orgb; + s32 lzcs, lzcr; + } n; + u32 r[32]; +} CP2Data; + +typedef union { + struct { + SMatrix3D rMatrix; + s32 trX, trY, trZ; + SMatrix3D lMatrix; + s32 rbk, gbk, bbk; + SMatrix3D cMatrix; + s32 rfc, gfc, bfc; + s32 ofx, ofy; + s32 h; + s32 dqa, dqb; + s32 zsf3, zsf4; + s32 flag; + } n; + u32 r[32]; +} CP2Ctrl; + +typedef struct { + GPRRegs GPR; /* General Purpose Registers */ + CP0Regs CP0; /* Coprocessor0 Registers */ + CP2Data CP2D; /* Cop2 data registers */ + CP2Ctrl CP2C; /* Cop2 control registers */ + u32 pc; /* Program counter */ + u32 code; /* The instruction */ + u32 cycle; + u32 interrupt; + u32 sCycle[64]; + u32 eCycle[64]; + u32 _msflag[32]; + u32 _smflag[32]; +} psxRegisters; + +extern psxRegisters psxRegs; + +#define PSX_IS_CONST1(reg) ((reg)<32 && (g_psxHasConstReg&(1<<(reg)))) +#define PSX_IS_CONST2(reg1, reg2) ((g_psxHasConstReg&(1<<(reg1)))&&(g_psxHasConstReg&(1<<(reg2)))) +#define PSX_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_psxHasConstReg |= (1<<(reg)); \ + g_psxFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define PSX_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_psxHasConstReg &= ~(1<<(reg)); \ +} + +extern u32 g_psxConstRegs[32]; +extern u32 g_psxHasConstReg, g_psxFlushedConstReg; + +#ifndef _PC_ + +#define _i32(x) (s32)x +#define _u32(x) x + +#define _i16(x) (short)x +#define _u16(x) (unsigned short)x + +#define _i8(x) (char)x +#define _u8(x) (unsigned char)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ psxRegs.pc // The next PC to be executed + +#define _Funct_ ((psxRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((psxRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((psxRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((psxRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((psxRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((unsigned short)psxRegs.code) // The immediate part of the instruction register +#define _Target_ (psxRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((short)psxRegs.code) // sign-extended immediate +#define _ImmU_ (psxRegs.code&0xffff) // zero-extended immediate + +#define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register +#define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register +#define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register +#define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register +#define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register + +#define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register +#define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register +#define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register +#define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register + +#define _rHi_ psxRegs.GPR.n.hi // The HI register +#define _rLo_ psxRegs.GPR.n.lo // The LO register + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Imm_ * 4) + _PC_) // Calculates the target during a branch instruction +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((short)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; + +#endif + +int psxInit(); +void psxReset(); +void psxShutdown(); +void psxException(u32 code, u32 step); +void psxBranchTest(); +void psxExecuteBios(); +void psxRestartCPU(); + +#endif /* __R3000A_H__ */ diff --git a/branches/pcsx2_0.9.2/R5900.c b/branches/pcsx2_0.9.2/R5900.c new file mode 100644 index 0000000..faff2de --- /dev/null +++ b/branches/pcsx2_0.9.2/R5900.c @@ -0,0 +1,578 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "Hw.h" +#include "Debug.h" +#include "R3000A.h" +#include "VUmicro.h" +#include "GS.h" + +static int inter; + +PCSX2_ALIGNED16(cpuRegisters cpuRegs); +PCSX2_ALIGNED16(fpuRegisters fpuRegs); +PCSX2_ALIGNED16(tlbs tlb[48]); +PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0}; + +u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0; +R5900cpu *Cpu; + +int EEsCycle; +u32 EEoCycle, IOPoCycle; + +extern u32 dwSaveVersion; + +int cpuInit() +{ + int ret; + + SysPrintf("PCSX2 v" PCSX2_VERSION " save ver: %x\n", dwSaveVersion); + SysPrintf("Color Legend: White - PCSX2 message\n"); + SysPrintf(COLOR_GREEN " Green - EE sio2 printf\n" COLOR_RESET); + SysPrintf(COLOR_RED " Red - IOP printf\n" COLOR_RESET); + + printf("%d", (u32)&cpuRegs.pc - (u32)&cpuRegs); + + InitFPUOps(); + cpudetectInit(); + + cpuRegs.constzero = 0; + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + ret = Cpu->Init(); + if (ret == -1 && CHECK_EEREC) { + SysMessage(_("Error initializing Recompiler, switching to Interpreter")); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC); + Cpu = &intCpu; + ret = Cpu->Init(); + } + +#ifdef WIN32_VIRTUAL_MEM + if (memInit() == -1) { + PROCESS_INFORMATION pi; + STARTUPINFO si; + char strdir[255], strexe[255]; + if( MessageBox(NULL, "Failed to allocate enough physical memory to run pcsx2. Try closing\n" + "down background programs, restarting windows, or buying more memory.\n\n" + "Launch TLB version of pcsx2 (pcsx2t.exe)?", "Memory Allocation Error", MB_YESNO) == IDYES ) { + + GetCurrentDirectory(ARRAYSIZE(strdir), strdir); + _snprintf(strexe, ARRAYSIZE(strexe), "%s\\pcsx2t.exe", strdir); + + memset(&si, 0, sizeof(si)); + + if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) { + _snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe); + MessageBox(NULL, strdir, "Failure", MB_OK); + } + else { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + } + + return -1; + } +#endif + if (hwInit() == -1) return -1; + if (vu0Init() == -1) return -1; + if (vu1Init() == -1) return -1; +#ifndef WIN32_VIRTUAL_MEM + if (memInit() == -1) return -1; +#endif + +#ifdef PCSX2_DEVBUILD + Log = 0; +#endif + + return ret; +} + +void cpuReset() +{ + Cpu->Reset(); + + memReset(); + + memset(&cpuRegs, 0, sizeof(cpuRegs)); + memset(&fpuRegs, 0, sizeof(fpuRegs)); + memset(&tlb, 0, sizeof(tlb)); + + cpuRegs.pc = 0xbfc00000; ///set pc reg to stack + cpuRegs.CP0.n.Config = 0x440; + cpuRegs.CP0.n.Status.val = 0x70400004; //0x10900000 <-- wrong; // COP0 enabled | BEV = 1 | TS = 1 + cpuRegs.CP0.n.PRid = 0x00002e20; // PRevID = Revision ID, same as R5900 + fpuRegs.fprc[0] = 0x00002e00; // fpu Revision.. + fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control + + vu0Reset(); + vu1Reset(); + hwReset(); + vif0Reset(); + vif1Reset(); + rcntInit(); + psxReset(); +} + +void cpuShutdown() +{ + hwShutdown(); +// biosShutdown(); + psxShutdown(); + vu0Shutdown(); + vu1Shutdown(); + memShutdown(); + gsShutdown(); + disR5900FreeSyms(); + + Cpu->Shutdown(); +} + +void cpuException(u32 code, u32 bd) { + u32 offset; + cpuRegs.CP0.n.Cause = code & 0xffff; + + if(cpuRegs.CP0.n.Status.b.ERL == 0){ //Error Level 0-1 + if(((code & 0x7C) >= 0x8) && ((code & 0x7C) <= 0xC)) offset = 0x0; //TLB Refill + else if ((code & 0x7C) == 0x0) offset = 0x200; //Interrupt + else offset = 0x180; // Everything else + + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.BEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } else { //Error Level 2 + SysPrintf("FIX ME: Level 2 cpuException\n"); + if((code & 0x38000) <= 0x8000 ) { //Reset / NMI + cpuRegs.pc = 0xBFC00000; + SysPrintf("Reset request\n"); + UpdateCP0Status(); + return; + } else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter + else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug + else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code); + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.DEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } + UpdateCP0Status(); +} + +void cpuTlbMiss(u32 addr, u32 bd, u32 excode) { + SysPrintf("cpuTlbMiss %x, %x, status=%x, code=%x\n", cpuRegs.pc, cpuRegs.cycle, cpuRegs.CP0.n.Status.val, excode); + if (bd) { + SysPrintf("branch delay!!\n"); + } + cpuRegs.CP0.n.BadVAddr = addr; + cpuRegs.CP0.n.Context &= 0xFF80000F; + cpuRegs.CP0.n.Context |= (addr >> 9) & 0x007FFFF0; + cpuRegs.CP0.n.EntryHi = (addr & 0xFFFFE000) | (cpuRegs.CP0.n.EntryHi & 0x1FFF); + + cpuRegs.CP0.n.Cause = excode; + if (!(cpuRegs.CP0.n.Status.val & 0x2)) { // EXL bit + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + } + + if ((cpuRegs.CP0.n.Status.val & 0x1) == 0) { + cpuRegs.pc = 0x80000000; + } else { + cpuRegs.pc = 0x80000180; + } + + cpuRegs.CP0.n.Status.b.EXL = 1; + UpdateCP0Status(); +// Log=1; varLog|= 0x40000000; +} + +void cpuTlbMissR(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBL); +} + +void cpuTlbMissW(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBS); +} + +void JumpCheckSym(u32 addr, u32 pc) { +#if 0 +// if (addr == 0x80051770) { SysPrintf("Log!: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); Log=1; varLog|= 0x40000000; } + if (addr == 0x8002f150) { SysPrintf("printk: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (addr == 0x8002aba0) return; + if (addr == 0x8002f450) return; + if (addr == 0x800dd520) return; +// if (addr == 0x80049300) SysPrintf("register_blkdev: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (addr == 0x8013cb70) { SysPrintf("change_root: %x\n", cpuRegs.GPR.n.a0.UL[0]); } +// if (addr == 0x8013d1e8) { SysPrintf("Log!\n"); Log++; if (Log==2) exit(0); varLog|= 0x40000000; } +// if (addr == 0x00234e88) { SysPrintf("StoreImage\n"); Log=1; /*psMu32(0x234e88) = 0x03e00008; psMu32(0x234e8c) = 0;*/ } +#endif +/* if ((pc >= 0x00131D50 && + pc < 0x00132454) || + (pc >= 0x00786a90 && + pc < 0x00786ac8))*/ + /*if (varLog & 0x40000000) { + char *str; + char *strf; + + str = disR5900GetSym(addr); + if (str != NULL) { + strf = disR5900GetUpperSym(pc); + if (strf) { + SysPrintf("Func %8.8x: %s (called by %8.8x: %s)\n", addr, str, pc, strf); + } else { + SysPrintf("Func %8.8x: %s (called by %x)\n", addr, str, pc); + } + if (!strcmp(str, "printf")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (!strcmp(str, "printk")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + } + }*/ +} + +void JumpCheckSymRet(u32 addr) { + /*if (varLog & 0x40000000) { + char *str; + str = disR5900GetUpperSym(addr); + if (str != NULL) { + SysPrintf("Return : %s, v0=%8.8x\n", str, cpuRegs.GPR.n.v0.UL[0]); + } + }*/ +} + +__inline void _cpuTestMissingINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 && + psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + SysPrintf("*PCSX2*: Error, missing INTC Interrupt\n"); + } + } +} + +__inline void _cpuTestMissingDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 && + (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)) { + if ((cpuRegs.interrupt & (1 << 31)) == 0) { + SysPrintf("*PCSX2*: Error, missing DMAC Interrupt\n"); + } + } +} + +void cpuTestMissingHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestMissingINTC(); + _cpuTestMissingDMAC(); +// _cpuTestTIMR(); + } +} + +#define TESTINT(n, callback) { \ + if ( (cpuRegs.interrupt & (1 << n)) ) { \ + if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \ + if (callback() == 1) { \ + cpuRegs.interrupt &= ~(1 << n); \ + } \ + } \ + else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \ + g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \ + } \ + } \ +} \ + +void _cpuTestInterrupts() { + + inter = cpuRegs.interrupt; + /* These are 'pcsx2 interrupts', they handle asynchronous stuff + that depends on the cycle timings */ + + TESTINT(0, vif0Interrupt); + TESTINT(10, vifMFIFOInterrupt); + TESTINT(1, vif1Interrupt); + TESTINT(11, gifMFIFOInterrupt); + TESTINT(2, gsInterrupt); + TESTINT(3, ipu0Interrupt); + TESTINT(4, ipu1Interrupt); + TESTINT(5, EEsif0Interrupt); + TESTINT(6, EEsif1Interrupt); + TESTINT(8, SPRFROMinterrupt); + TESTINT(9, SPRTOinterrupt); + + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + TESTINT(30, intcInterrupt); + TESTINT(31, dmacInterrupt); +} + +u32 s_iLastCOP0Cycle = 0; +u32 s_iLastPERFCycle[2] = {0,0}; + +static void _cpuTestTIMR() { + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) { + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + } + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) { + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + s_iLastPERFCycle[1] = cpuRegs.cycle; + } + + if ( (cpuRegs.CP0.n.Status.val & 0x8000) && + cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { + SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); + cpuException(0x808000, cpuRegs.branch); + } +} + +#define EE_WAIT_CYCLE 512 + +// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates +u32 g_nextBranchCycle = 0; +u32 s_lastvsync[2]; +extern u8 g_globalXMMSaved, g_globalMMXSaved; +u32 loaded = 0; + +void IntcpuBranchTest() +{ + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 0; + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + if (VU0.VI[REG_VPU_STAT].UL & 0x100) { + Cpu->ExecuteVU1Block(); + } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 1; +} + +void cpuBranchTest() +{ + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 0; + +// if( !loaded && cpuRegs.cycle > 0x08000000 ) { +// char strstate[255]; +// sprintf(strstate, "sstates/%8.8x.000", ElfCRC); +// LoadState(strstate); +// loaded = 1; +// } + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + + assert( !g_globalXMMSaved && !g_globalMMXSaved ); + g_EEFreezeRegs = 1; +} + +static void _cpuTestINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 ){ + if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + INT(30,4); + } + } + } +} + +static void _cpuTestDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 ){ + if (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) { + if ( (cpuRegs.interrupt & (1 << 31)) == 0) { + INT(31, 4); + } + } + } +} + +void cpuTestHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + _cpuTestINTC(); + _cpuTestDMAC(); + _cpuTestTIMR(); +} + +void cpuTestINTCInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestINTC(); + } +} + +void cpuTestDMACInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestDMAC(); + } +} + +void cpuTestTIMRInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestTIMR(); + } +} + +extern BOOL bExecBIOS; +void cpuExecuteBios() +{ + // filter CPU options + if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC; + else Config.Options &= ~PCSX2_COP2REC; + + if( !cpucaps.hasStreamingSIMDExtensions ) { + Config.Options &= ~(PCSX2_VU1REC|PCSX2_VU0REC); + } + + // remove frame skipping if GS doesn't support it + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_SKIP: + case PCSX2_FRAMELIMIT_VUSKIP: + if( GSsetFrameSkip == NULL ) + Config.Options &= ~PCSX2_FRAMELIMIT_MASK; + break; + } + + SysPrintf("Using Frame Skipping: "); + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_NORMAL: SysPrintf("Normal\n"); break; + case PCSX2_FRAMELIMIT_LIMIT: SysPrintf("Limit\n"); break; + case PCSX2_FRAMELIMIT_SKIP: SysPrintf("Skip\n"); break; + case PCSX2_FRAMELIMIT_VUSKIP: SysPrintf("VU Skip\n"); break; + } + + + SysPrintf("* PCSX2 *: ExecuteBios\n"); + + bExecBIOS = TRUE; + while (cpuRegs.pc != 0x00200008 && + cpuRegs.pc != 0x00100008) { + Cpu->ExecuteBlock(); + } + + bExecBIOS = FALSE; +// REC_CLEARM(0x00200008); +// REC_CLEARM(0x00100008); +// REC_CLEARM(cpuRegs.pc); + if( CHECK_EEREC ) Cpu->Reset(); + + SysPrintf("* PCSX2 *: ExecuteBios Complete\n"); + GSprintf(5, "PCSX2 v" PCSX2_VERSION "\nExecuteBios Complete\n"); +} + +void cpuRestartCPU() +{ + Cpu = CHECK_EEREC ? &recCpu : &intCpu; + + // restart vus + if (Cpu->Init() == -1) { + SysClose(); + exit(1); + } + + vu0Init(); + vu1Init(); + Cpu->Reset(); + psxRestartCPU(); +} + diff --git a/branches/pcsx2_0.9.2/R5900.h b/branches/pcsx2_0.9.2/R5900.h new file mode 100644 index 0000000..c3f33e5 --- /dev/null +++ b/branches/pcsx2_0.9.2/R5900.h @@ -0,0 +1,285 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R5900_H__ +#define __R5900_H__ + +#include + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Step)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*ExecuteVU0Block)(); /* executes up to a jump */ + void (*ExecuteVU1Block)(); /* executes up to a jump */ + void (*EnableVU0micro)(int enable); + void (*EnableVU1micro)(int enable); + void (*Clear)(u32 Addr, u32 Size); + void (*ClearVU0)(u32 Addr, u32 Size); + void (*ClearVU1)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R5900cpu; + +extern R5900cpu *Cpu; +extern R5900cpu intCpu; +extern R5900cpu recCpu; + +typedef union { // Declare union type GPR register + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} GPR_reg; + +typedef union { + struct { + GPR_reg r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra; + } n; + GPR_reg r[32]; +} GPRregs; + +typedef union { + struct { + u32 pccr, pcr0, pcr1, pad; + } n; + u32 r[4]; +} PERFregs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare; + union { + struct { + int IE:1; + int EXL:1; + int ERL:1; + int KSU:2; + int unused0:3; + int IM:8; + int EIE:1; + int _EDI:1; + int CH:1; + int unused1:3; + int BEV:1; + int DEV:1; + int unused2:2; + int FR:1; + int unused3:1; + int CU:4; + } b; + u32 val; + } Status; + u32 Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Debug, + DEPC, PerfCnt, ErrCtl, CacheErr, + TagLo, TagHi, ErrorEPC, DESAVE; + } n; + u32 r[32]; +} CP0regs; + +typedef struct { + GPRregs GPR; // GPR regs + // NOTE: don't change order since recompiler uses it + GPR_reg HI; + GPR_reg LO; // hi & log 128bit wide + CP0regs CP0; // is COP0 32bit? + u32 sa; // shift amount (32bit), needs to be 16 byte aligned + u32 constzero; // always 0, for MFSA + u32 pc; // Program counter + u32 code; // The instruction + PERFregs PERF; + u32 eCycle[32]; + u32 sCycle[32]; // for internal counters + u32 cycle; // calculate cpucycles.. + u32 interrupt; + int branch; + int opmode; // operating mode + u32 tempcycles; +} cpuRegisters; + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; +extern cpuRegisters cpuRegs; + +// used for optimization +typedef union { + u64 UD[1]; //64 bits + s64 SD[1]; + u32 UL[2]; + s32 SL[3]; + u16 US[4]; + s16 SS[4]; + u8 UC[8]; + s8 SC[8]; +} GPR_reg64; + +#define GPR_IS_CONST1(reg) ((reg)<32 && (g_cpuHasConstReg&(1<<(reg)))) +#define GPR_IS_CONST2(reg1, reg2) ((g_cpuHasConstReg&(1<<(reg1)))&&(g_cpuHasConstReg&(1<<(reg2)))) +#define GPR_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_cpuHasConstReg |= (1<<(reg)); \ + g_cpuFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define GPR_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_cpuHasConstReg &= ~(1<<(reg)); \ +} + +extern GPR_reg64 g_cpuConstRegs[32]; +extern u32 g_cpuHasConstReg, g_cpuFlushedConstReg; + +typedef union { + float f; + u32 UL; +} FPRreg; + +typedef struct { + FPRreg fpr[32]; // 32bit floating point registers + u32 fprc[32]; // 32bit floating point control registers + FPRreg ACC; // 32 bit accumulator +} fpuRegisters; + +extern fpuRegisters fpuRegs; + + +typedef struct { + u32 PageMask,EntryHi; + u32 EntryLo0,EntryLo1; + u32 Mask, nMask; + u32 G; + u32 ASID; + u32 VPN2; + u32 PFN0; + u32 PFN1; +} tlbs; + +extern tlbs tlb[48]; + +#ifndef _PC_ + +#define _i64(x) (s64)x +#define _u64(x) (u64)x + +#define _i32(x) (s32)x +#define _u32(x) (u32)x + +#define _i16(x) (s16)x +#define _u16(x) (u16)x + +#define _i8(x) (s8)x +#define _u8(x) (u8)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ cpuRegs.pc // The next PC to be executed + +#define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((u16)cpuRegs.code) // The immediate part of the instruction register +#define _Target_ (cpuRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((s16)cpuRegs.code) // sign-extended immediate +#define _ImmU_ (cpuRegs.code&0xffff) // zero-extended immediate + + +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) cpuRegs.GPR.r[x].UD[0] = _PC_ + 4; // Sets the return address in the link register + +#endif + +int cpuInit(); +void cpuReset(); +void cpuShutdown(); +void cpuException(u32 code, u32 bd); +void cpuTlbMissR(u32 addr, u32 bd); +void cpuTlbMissW(u32 addr, u32 bd); +void IntcpuBranchTest(); +void cpuBranchTest(); +void cpuTestHwInts(); +void cpuTestINTCInts(); +void cpuTestDMACInts(); +void cpuTestTIMRInts(); +void _cpuTestInterrupts(); +void cpuExecuteBios(); +void cpuRestartCPU(); + +u32 VirtualToPhysicalR(u32 addr); +u32 VirtualToPhysicalW(u32 addr); + +void intDoBranch(u32 target); +void intSetBranch(); +void intExecuteVU0Block(); +void intExecuteVU1Block(); + +void JumpCheckSym(u32 addr, u32 pc); +void JumpCheckSymRet(u32 addr); + +// check to see if needs freezing +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs ) { FreezeXMMRegs_(save); } + +//exception code +#define EXC_CODE(x) ((x)<<2) + +#define EXC_CODE_Int EXC_CODE(0) +#define EXC_CODE_Mod EXC_CODE(1) /* TLB Modification exception */ +#define EXC_CODE_TLBL EXC_CODE(2) /* TLB Miss exception (load or instruction fetch) */ +#define EXC_CODE_TLBS EXC_CODE(3) /* TLB Miss exception (store) */ +#define EXC_CODE_AdEL EXC_CODE(4) +#define EXC_CODE_AdES EXC_CODE(5) +#define EXC_CODE_IBE EXC_CODE(6) +#define EXC_CODE_DBE EXC_CODE(7) +#define EXC_CODE_Sys EXC_CODE(8) +#define EXC_CODE_Bp EXC_CODE(9) +#define EXC_CODE_Ri EXC_CODE(10) +#define EXC_CODE_CpU EXC_CODE(11) +#define EXC_CODE_Ov EXC_CODE(12) +#define EXC_CODE_Tr EXC_CODE(13) +#define EXC_CODE_FPE EXC_CODE(15) +#define EXC_CODE_WATCH EXC_CODE(23) +#define EXC_CODE__MASK 0x0000007c +#define EXC_CODE__SHIFT 2 + +#define EXC_TLB_STORE 1 +#define EXC_TLB_LOAD 0 + + +#endif /* __R5900_H__ */ diff --git a/branches/pcsx2_0.9.2/RDebug/Makefile.am b/branches/pcsx2_0.9.2/RDebug/Makefile.am new file mode 100644 index 0000000..c7c1c6c --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I../ +noinst_LIBRARIES = libRDebug.a + +libRDebug_a_SOURCES = \ +deci2.c deci2_dcmp.c deci2_drfp.h deci2_iloadp.h deci2_ttyp.c \ +deci2_dbgp.c deci2_dcmp.h deci2.h deci2_netmp.c deci2_ttyp.h \ +deci2_dbgp.h deci2_iloadp.c deci2_netmp.h \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/RDebug/deci2.c b/branches/pcsx2_0.9.2/RDebug/deci2.c new file mode 100644 index 0000000..49add6e --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2.c @@ -0,0 +1,26 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +void exchangeSD(DECI2_HEADER *h){ + u8 tmp =h->source; + h->source =h->destination; + h->destination =tmp; +} diff --git a/branches/pcsx2_0.9.2/RDebug/deci2.h b/branches/pcsx2_0.9.2/RDebug/deci2.h new file mode 100644 index 0000000..80cbe13 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2.h @@ -0,0 +1,66 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2_H__ +#define __DECI2_H__ + +#include "Common.h" +#include "deci2_dcmp.h" +#include "deci2_iloadp.h" +#include "deci2_dbgp.h" +#include "deci2_netmp.h" +#include "deci2_ttyp.h" + +#define PROTO_DCMP 0x0001 +#define PROTO_ITTYP 0x0110 +#define PROTO_IDBGP 0x0130 +#define PROTO_ILOADP 0x0150 +#define PROTO_ETTYP 0x0220 +#define PROTO_EDBGP 0x0230 +#define PROTO_NETMP 0x0400 + + +#pragma pack(1) +typedef struct tag_DECI2_HEADER{ + u16 length, //+00 + _pad, //+02 + protocol; //+04 + char source, //+06 + destination;//+07 +} DECI2_HEADER; //=08 + +typedef struct tag_DECI2_DBGP_BRK{ + u32 address, //+00 + count; //+04 +} DECI2_DBGP_BRK; //=08 +#pragma pack() + +#define STOP 0 +#define RUN 1 + +extern DECI2_DBGP_BRK ebrk[32], ibrk[32]; +extern int ebrk_count, ibrk_count; +extern int runStatus, runCode, runCount; +extern HANDLE runEvent; //i don't like this; +extern int connected; + //when add linux code this might change + +int writeData(char *result); +void exchangeSD(DECI2_HEADER *h); + +#endif//__DECI2_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/deci2.txt b/branches/pcsx2_0.9.2/RDebug/deci2.txt new file mode 100644 index 0000000..8cf7221 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2.txt @@ -0,0 +1,27 @@ +pcsx2 log->debugger tty mapping +Ŀ +Bios EE 0 IOP Bios +CPU & MMI & COP0 & FPU EE 1 IOP IOP cpu +VU0 & VUMicro EE 2 IOP HW +VIF EE 3 IOP GTE +GIF EE 4 IOP GPU +DMA EE 5 IOP DMA +HW & Unknown Memory EE 6 IOP Unknown Memory +ELF & Scratch pad EE 7 IOP PAD +IPU EE 8 IOP CDR +SIF & RPC services EE 9 IOP + +SysMessage EEKernelIOP SysMessage + +PRODG: 230,130, 120,121,122,110-119,11F,210-219,21F,410 +CW: 230,130,150,120,121, 210-219,21F,110-119,11F + +0400 PROTO_NETMP +0001 PROTO_DCMP + PROTO_MTWKS +012? PROTO_DRFP (%s) +0230 PROTO_ESDBG +0130 PROTO_ISDBG +011? PROTO_I%dTTY +021? PROTO_E%dTTY + diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.c b/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.c new file mode 100644 index 0000000..5ff8dc5 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.c @@ -0,0 +1,410 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "VUmicro.h" +#include "deci2.h" + +typedef struct tag_DECI2_DBGP_HEADER{ + DECI2_HEADER h; //+00 + u16 id; //+08 + u8 type, //+0A + code, //+0B + result, //+0C + count; //+0D + u16 _pad; //+0E +} DECI2_DBGP_HEADER; //=10 + +typedef struct tag_DECI2_DBGP_CONF{ + u32 major_ver, //+00 + minor_ver, //+04 + target_id, //+08 + _pad, //+0C + mem_align, //+10 + _pad2, //+14 + reg_size, //+18 + nreg, //+1C + nbrkpt, //+20 + ncont, //+24 + nstep, //+28 + nnext, //+2C + mem_limit_align, //+30 + mem_limit_size, //+34 + run_stop_state, //+38 + hdbg_area_addr, //+3C + hdbg_area_size; //+40 +} DECI2_DBGP_CONF; //=44 + +DECI2_DBGP_CONF +cpu={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu0={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu1={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 32, 1, 0x00, 0x00, 0x07, 0x200, 1, 0x0001E670, 0x100}; +//iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 0, 1, 0x00, 0x00, 0x07, 0x200, 0, 0x00006940, 0x100}; + +#pragma pack(2) +typedef struct tag_DECI2_DBGP_EREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u64 value[2]; //+04 +} DECI2_DBGP_EREG; //=14 + +typedef struct tag_DECI2_DBGP_IREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u32 value; //+04 +} DECI2_DBGP_IREG; //=08 + +typedef struct tag_DECI2_DBGP_MEM{ + u8 space, //+00 + align; //+01 + u16 _pad; //+02 + u32 address; //+04 + u32 length; //+08 +} DECI2_DBGP_MEM; //=0C + +typedef struct tag_DECI2_DBGP_RUN{ + u32 entry, //+00 + gp, //+04 + _pad, //+08 + _pad1, //+0C + argc; //+10 + u32 argv[0]; //+14 +} DECI2_DBGP_RUN; //=14 +#pragma pack() + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy){ + DECI2_DBGP_HEADER *in=(DECI2_DBGP_HEADER*)inbuffer, + *out=(DECI2_DBGP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DBGP_HEADER); + DECI2_DBGP_EREG *eregs=(DECI2_DBGP_EREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_IREG *iregs=(DECI2_DBGP_IREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_MEM *mem =(DECI2_DBGP_MEM*) ((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_RUN *run =(DECI2_DBGP_RUN*) ((u8*)in+sizeof(DECI2_DBGP_HEADER)); + static char line[1024]; + int i, s; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + //out->h.length=sizeof(DECI2_DBGP_HEADER); + out->type++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->type){ + case 0x00://ok + sprintf(line, "%s/GETCONF", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I'){ + memcpy(data, &iop, sizeof(DECI2_DBGP_CONF)); + }else + switch(in->id){ + case 0:memcpy(data, &cpu, sizeof(DECI2_DBGP_CONF));break; + case 1:memcpy(data, &vu0, sizeof(DECI2_DBGP_CONF));break; + case 2:memcpy(data, &vu1, sizeof(DECI2_DBGP_CONF));break; + } + break; + case 0x02://ok + sprintf(line, "%s/2", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + break; + case 0x04://ok + sprintf(line, "%s/GETREG count=%d kind[0]=%d number[0]=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:iregs[i].value=psxRegs.GPR.n.lo;break; + case 1:iregs[i].value=psxRegs.GPR.n.hi;break; + } + break; + case 2:iregs[i].value=psxRegs.GPR.r[iregs[i].number]; break; + case 3: + if (iregs[i].number==14) psxRegs.CP0.n.EPC=psxRegs.pc; + iregs[i].value=psxRegs.CP0.r[iregs[i].number]; + break; + case 6:iregs[i].value=psxRegs.CP2D.r[iregs[i].number]; break; + case 7:iregs[i].value=psxRegs.CP2C.r[iregs[i].number]; break; + default: + iregs[0].value++;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(eregs[i].value, &cpuRegs.GPR.r[eregs[i].number], 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(eregs[i].value, &cpuRegs.HI.UD[0], 8);break; + case 1:memcpy(eregs[i].value, &cpuRegs.LO.UD[0], 8);break; + case 2:memcpy(eregs[i].value, &cpuRegs.HI.UD[1], 8);break; + case 3:memcpy(eregs[i].value, &cpuRegs.LO.UD[1], 8);break; + case 4:memcpy(eregs[i].value, &cpuRegs.sa, 4); break; + } + case 2: + if (eregs[i].number==14) cpuRegs.CP0.n.EPC=cpuRegs.pc; + memcpy(eregs[i].value, &cpuRegs.CP0.r[eregs[i].number], 4); + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(eregs[i].value, &fpuRegs.fpr[eregs[i].number], 4);break; + case 6:memcpy(eregs[i].value, &fpuRegs.fprc[eregs[i].number], 4);break; + case 7:memcpy(eregs[i].value, &VU0.VF[eregs[i].number], 16);break; + case 8:memcpy(eregs[i].value, &VU0.VI[eregs[i].number], 4);break; + case 9:memcpy(eregs[i].value, &VU1.VF[eregs[i].number], 16);break; + case 10:memcpy(eregs[i].value, &VU1.VI[eregs[i].number], 4);break; + default: + eregs[0].value[0]++;//dummy; might be assert(0) + } + break; + case 0x06://ok + sprintf(line, "%s/PUTREG count=%d kind[0]=%d number[0]=%d value=%016I64X_%016I64X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number, eregs[0].value[1], eregs[0].value[0]); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:psxRegs.GPR.n.lo=iregs[i].value;break; + case 1:psxRegs.GPR.n.hi=iregs[i].value;break; + } + break; + case 2:psxRegs.GPR.r[iregs[i].number]=iregs[i].value; break; + case 3: + psxRegs.CP0.r[iregs[i].number]=iregs[i].value; + if (iregs[i].number==14) psxRegs.pc=psxRegs.CP0.n.EPC; + break; + case 6:psxRegs.CP2D.r[iregs[i].number]=iregs[i].value; break; + case 7:psxRegs.CP2C.r[iregs[i].number]=iregs[i].value; break; + default: + ;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(&cpuRegs.GPR.r[eregs[i].number], eregs[i].value, 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(&cpuRegs.HI.UD[0], eregs[i].value, 8);break; + case 1:memcpy(&cpuRegs.LO.UD[0], eregs[i].value, 8);break; + case 2:memcpy(&cpuRegs.HI.UD[1], eregs[i].value, 8);break; + case 3:memcpy(&cpuRegs.LO.UD[1], eregs[i].value, 8);break; + case 4:memcpy(&cpuRegs.sa, eregs[i].value, 4); break; + } + break; + case 2: + memcpy(&cpuRegs.CP0.r[eregs[i].number], eregs[i].value, 4); + if (eregs[i].number==14) cpuRegs.pc=cpuRegs.CP0.n.EPC; + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(&fpuRegs.fpr[eregs[i].number], eregs[i].value, 4);break; + case 6:memcpy(&fpuRegs.fprc[eregs[i].number], eregs[i].value, 4);break; + case 7:memcpy(&VU0.VF[eregs[i].number], eregs[i].value, 16);break; + case 8:memcpy(&VU0.VI[eregs[i].number], eregs[i].value, 4);break; + case 9:memcpy(&VU1.VF[eregs[i].number], eregs[i].value, 16);break; + case 10:memcpy(&VU1.VI[eregs[i].number], eregs[i].value, 4);break; + default: + ;//dummy; might be assert(0) + } + break; + case 0x08://ok + sprintf(line, "%s/RDMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)out+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSXM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(data, PSM(mem->address), mem->length); + else + if ((((mem->address & 0x1FFFFFFF)>128*1024*1024) || ((mem->address & 0x1FFFFFFF)<32*1024*1024)) && PSM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(data, &VU0.Mem[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Mem[mem->address & 0x3FFF], mem->length); + break; + case 2: + if (in->id==1) + memcpy(data, &VU0.Micro[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Micro[mem->address & 0x3FFF], mem->length); + break; + } + out->h.length=mem->length+data-(u8*)out; + break; + case 0x0a://ok + sprintf(line, "%s/WRMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)in+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if (mem->length==4 && *(int*)data==0x0000000D) + strcat(line, " BREAKPOINT"); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(PSXM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(PSM(mem->address), data, mem->length); + else + if (PSM(mem->address & 0x1FFFFFFF)) + memcpy(PSM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(&VU0.Mem[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Mem[mem->address & 0x3FFF], data, mem->length); + break; + case 2: + if (in->id==1) + memcpy(&VU0.Micro[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Micro[mem->address & 0x3FFF], data, mem->length); + break; + } + out->h.length=sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM); + break; + case 0x10://ok + sprintf(line, "%s/GETBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I') memcpy(data, ibrk, out->count=ibrk_count); + else memcpy(data, ebrk, out->count=ebrk_count); + out->h.length=sizeof(DECI2_DBGP_HEADER)+out->count*sizeof(DECI2_DBGP_BRK); + break; + case 0x12://ok [does not break on iop brkpts] + sprintf(line, "%s/PUTBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + out->h.length=sizeof(DECI2_DBGP_HEADER); + if (in->count>32){ + out->result=1; + strcat(line, "TOO MANY"); + break; + } + if (in->h.destination=='I') memcpy(ibrk, data, ibrk_count=in->count); + else memcpy(ebrk, data, ebrk_count=in->count); + out->count=0; + break; + case 0x14://ok, [w/o iop] + sprintf(line, "%s/BREAK count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + if (in->h.destination=='I') + ; + else{ + out->result = ( InterlockedExchange(&runStatus, STOP)==STOP ? + 0x20 : 0x21 ); + out->code=0xFF; + Sleep(50); + } + break; + case 0x16://ok, [w/o iop] + sprintf(line, "%s/CONTINUE code=%s count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", + in->code==0?"CONT":in->code==1?"STEP":"NEXT", in->count); + if (in->h.destination=='I') + ; + else{ + InterlockedExchange(&runStatus, STOP); + Sleep(100);//first get the run thread to Wait state + runCount=in->count; + runCode=in->code; + SetEvent(runEvent);//kick it + } + break; + case 0x18://ok [without argc/argv stuff] + sprintf(line, "%s/RUN code=%d count=%d entry=0x%08X gp=0x%08X argc=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->code, in->count, + run->entry, run->gp, run->argc); + cpuRegs.CP0.n.EPC=cpuRegs.pc=run->entry; + cpuRegs.GPR.n.gp.UL[0]=run->gp; +// threads_array[0].argc = run->argc; + for (i=0, s=0; i<(int)run->argc; i++) s+=run->argv[i]; + memcpy(PSM(0), &run->argv[run->argc], s); +// threads_array[0].argstring = 0; + InterlockedExchange(&runStatus, STOP); + Sleep(1000);//first get the run thread to Wait state + runCount=0; + runCode=0xFF; + SetEvent(runEvent);//awake it + out->h.length=sizeof(DECI2_DBGP_HEADER); + break; + default: + sprintf(line, "type=0x%02X code=%d count=%d [unknown]", in->type, in->code, in->count); + } + sprintf(message, "[DBGP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + sprintf(eepc, "%08X", cpuRegs.pc); + sprintf(ioppc, "%08X", psxRegs.pc); + sprintf(eecy, "%d", cpuRegs.cycle); + sprintf(iopcy, "%d", psxRegs.cycle); + writeData(outbuffer); +} + +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count){ + static DECI2_DBGP_HEADER tmp; + tmp.h.length =sizeof(DECI2_DBGP_HEADER); + tmp.h._pad =0; + tmp.h.protocol =( source=='E' ? PROTO_EDBGP : PROTO_IDBGP ); + tmp.h.source =source; + tmp.h.destination='H'; + tmp.id =id; + tmp.type =0x15; + tmp.code =code; + tmp.result =result; + tmp.count =count; + tmp._pad =0; + writeData((char*)&tmp); +} diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.h b/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.h new file mode 100644 index 0000000..ab28c21 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_dbgp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DBGP_H__ +#define __DECI2DBGP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy); +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count); + +#endif//__DECI2DBGP_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.c b/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.c new file mode 100644 index 0000000..9348040 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.c @@ -0,0 +1,83 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +typedef struct tag_DECI2_DCMP_CONNECT{ + u8 result, //+00 + _pad[3];//+01 + u64 EEboot, //+04 + IOPboot;//+0C +} DECI2_DCMP_CONNECT; //=14 + +typedef struct tag_DECI2_DCMP_ECHO{ + u16 identifier, //+00 + sequence; //+02 + u8 data[32]; //+04 +} DECI2_DCMP_ECHO; //=24 + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + DECI2_DCMP_CONNECT *connect=(DECI2_DCMP_CONNECT*)data; + DECI2_DCMP_ECHO *echo =(DECI2_DCMP_ECHO*)data; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ +/* case 0: + sprintf(message, " [DCMP] type=CONNECT code=%s EEboot=0x%I64X IOP=0x%I64X", + in->code==0?"CONNECT":"DISCONNECT", connect->EEboot, connect->IOPboot); + data=(u8*)out+sizeof(DECI2_DCMP_HEADER); + connect=(DECI2_DCMP_CONNECT*)data; + connect->result=0; + break; + case 1: + sprintf(message, " [DCMP] type=ECHO id=%X seq=%X", echo->identifier, echo->sequence); + exchangeSD(&out->h); + break; +// not implemented, not needed? + default: + sprintf(message, " [DCMP] type=%d[unknown]", in->type); +*/ } + out->code++; +} + +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size){ + static char tmp[100]; + ((DECI2_DCMP_HEADER*)tmp)->h.length =sizeof(DECI2_DCMP_HEADER)+size; + ((DECI2_DCMP_HEADER*)tmp)->h._pad =0; + ((DECI2_DCMP_HEADER*)tmp)->h.protocol =protocol; + ((DECI2_DCMP_HEADER*)tmp)->h.source =source; + ((DECI2_DCMP_HEADER*)tmp)->h.destination=destination; + ((DECI2_DCMP_HEADER*)tmp)->type =type; + ((DECI2_DCMP_HEADER*)tmp)->code =code; + ((DECI2_DCMP_HEADER*)tmp)->_pad =0; + memcpy(&tmp[sizeof(DECI2_DCMP_HEADER)], data, size); + writeData(tmp); +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.h b/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.h new file mode 100644 index 0000000..18e2c80 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_dcmp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DCMP_H__ +#define __DECI2DCMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message); +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size); + +#endif//__DECI2DCMP_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_drfp.c b/branches/pcsx2_0.9.2/RDebug/deci2_drfp.c new file mode 100644 index 0000000..64b2670 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_drfp.c @@ -0,0 +1,48 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +extern char d2_message[100]; + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ + case 4://[OK] + sprintf(message, " [DCMP] code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + break; + default: + sprintf(message, " [DCMP] code=%d[unknown] result=%d", netmp->code, netmp->result); + } + result->code++; + result->result=0; //ok +} diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_drfp.h b/branches/pcsx2_0.9.2/RDebug/deci2_drfp.h new file mode 100644 index 0000000..eb90970 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_drfp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DRFP_H__ +#define __DECI2DRFP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2DRFP_H__ \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.c b/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.c new file mode 100644 index 0000000..d761e8b --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.c @@ -0,0 +1,106 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "PsxBios2.h" +#include "deci2.h" + +typedef struct tag_DECI2_ILOADP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 cmd + action, //+09 + result, //+0A + stamp; //+0B + u32 moduleId; //+0C +} DECI2_ILOADP_HEADER; //=10 + +typedef struct tag_DECI2_ILOADP_INFO{ + u16 version, //+00 + flags; //+02 + u32 module_address, //+04 + text_size, //+08 + data_size, //+0C + bss_size, //+10 + _pad[3]; //+14 +} DECI2_ILOADP_INFO; + +void writeInfo(DECI2_ILOADP_INFO *info, + u16 version, u16 flags, u32 module_address, + u32 text_size, u32 data_size, u32 bss_size){ + info->version =version; + info->flags =flags; + info->module_address=module_address; + info->text_size =text_size; + info->data_size =data_size; + info->bss_size =bss_size; + info->_pad[0]=info->_pad[1]=info->_pad[2]=0; +} + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message){ + DECI2_ILOADP_HEADER *in=(DECI2_ILOADP_HEADER*)inbuffer, + *out=(DECI2_ILOADP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_ILOADP_HEADER); + irxImageInfo *iii; + static char line[1024]; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_ILOADP_HEADER); + out->code++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->code){ + case 0: + sprintf(line, "code=START action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 2: + sprintf(line, "code=REMOVE action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 4: + sprintf(line, "code=LIST action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for (iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0, data+=4) + *(u32*)data=iii->index; + + out->h.length=data-(u8*)out; + break; + case 6: + sprintf(line, "code=INFO action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for(iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0) + if (iii->index==in->moduleId){ + writeInfo((DECI2_ILOADP_INFO*)data, + iii->version, iii->flags, iii->vaddr, iii->text_size, iii->data_size, iii->bss_size); + data+=sizeof(DECI2_ILOADP_INFO); + strcpy(data, PSXM(iii->name)); + data+=strlen(PSXM(iii->name))+4; + data=(char*)((int)data & 0xFFFFFFFC); + break; + + } + out->h.length=data-(u8*)out; + break; + case 8: + sprintf(line, "code=WATCH action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + default: + sprintf(line, "code=%d[unknown]", in->code); + } + sprintf(message, "[ILOADP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + writeData(outbuffer); +} diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.h b/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.h new file mode 100644 index 0000000..a55b046 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_iloadp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2ILOADP_H__ +#define __DECI2ILOADP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2ILOADP_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_netmp.c b/branches/pcsx2_0.9.2/RDebug/deci2_netmp.c new file mode 100644 index 0000000..472dfc5 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_netmp.c @@ -0,0 +1,134 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_NETMP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 + result; //+09 +} DECI2_NETMP_HEADER; //=0A + +typedef struct tag_DECI2_NETMP_CONNECT{ + u8 priority, //+00 + _pad; //+01 + u16 protocol; //+02 +} DECI2_NETMP_CONNECT; //=04 + +char d2_message[100]; +int d2_count=1; +DECI2_NETMP_CONNECT d2_connect[50]={0xFF, 0, 0x400}; + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_NETMP_HEADER *in=(DECI2_NETMP_HEADER*)inbuffer, + *out=(DECI2_NETMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_NETMP_HEADER); + DECI2_NETMP_CONNECT *connect=(DECI2_NETMP_CONNECT*)data; //connect + int i, n; + static char p[100], line[1024]; + u64 EEboot, IOPboot; //reset + u16 node; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_NETMP_HEADER); + out->code++; + out->result=0; //ok + switch(in->code){ + case 0: + n=(in->h.length-sizeof(DECI2_NETMP_HEADER)) / sizeof(DECI2_NETMP_CONNECT); + sprintf(line, "code=CONNECT"); + for (i=0; ih.length=data-(u8*)out; + writeData(outbuffer); + + node=(u16)'I'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=(u16)'E'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=PROTO_ILOADP; + sendDCMP(PROTO_DCMP, 'I', 'H', 2, 1, (char*)&node, sizeof(node)); + + for (i=0; i<10; i++){ + node=PROTO_ETTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + } + node=PROTO_ETTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + break; + case 4://[OK] + sprintf(line, "code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + writeData(outbuffer); + break; + case 6://[ok] + sprintf(line, "code=STATUS"); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER)+2; + /* + memcpy(data, d2_connect, 1*sizeof(DECI2_NETMP_CONNECT)); + data+=1*sizeof(DECI2_NETMP_CONNECT); + *(u32*)data=1;//quite fast;) + data+=4; + memcpy(data, d2_message, strlen(d2_message)); + data+=strlen(d2_message); + *(u32*)data=0;//null end the string on a word boundary + data+=3;data=(u8*)((int)data & 0xFFFFFFFC);*/ + + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + case 8: + sprintf(line, "code=KILL protocol=0x%04X", *(u16*)data); + writeData(outbuffer); + break; + case 10: + sprintf(line, "code=VERSION %s", data); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER); + strcpy(data, "0.2.0");data+=strlen("0.2.0");//emu version;) + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + default: + sprintf(line, "code=%d[unknown] result=%d", in->code, in->result); + writeData(outbuffer); + } + sprintf(message, "[NETMP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); +} diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_netmp.h b/branches/pcsx2_0.9.2/RDebug/deci2_netmp.h new file mode 100644 index 0000000..760224d --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_netmp.h @@ -0,0 +1,27 @@ + /* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2NETMP_H__ +#define __DECI2NETMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2NETMP_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.c b/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.c new file mode 100644 index 0000000..ce66e2f --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.c @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_TTYP_HEADER{ + DECI2_HEADER h; //+00 + u32 flushreq; //+08 + u8 data[0]; //+0C +} DECI2_TTYP_HEADER; //=0C + +void sendTTYP(u16 protocol, u8 source, char *data){ + static char tmp[2048]; + ((DECI2_TTYP_HEADER*)tmp)->h.length =sizeof(DECI2_TTYP_HEADER)+strlen(data); + ((DECI2_TTYP_HEADER*)tmp)->h._pad =0; + ((DECI2_TTYP_HEADER*)tmp)->h.protocol =protocol +(source=='E' ? PROTO_ETTYP : PROTO_ITTYP); + ((DECI2_TTYP_HEADER*)tmp)->h.source =source; + ((DECI2_TTYP_HEADER*)tmp)->h.destination='H'; + ((DECI2_TTYP_HEADER*)tmp)->flushreq =0; + if (((DECI2_TTYP_HEADER*)tmp)->h.length>2048) + SysMessage("TTYP: Buffer overflow"); + else + memcpy(&tmp[sizeof(DECI2_TTYP_HEADER)], data, strlen(data)); + //writeData(tmp); +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.h b/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.h new file mode 100644 index 0000000..8d27146 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/deci2_ttyp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2TTYP_H__ +#define __DECI2TTYP_H__ + +#include "Common.h" +#include "deci2.h" + +//void D2_(char *inbuffer, char *outbuffer, char *message); +void sendTTYP(u16 protocol, u8 source, char *data); + +#endif//__DECI2TTYP_H__ diff --git a/branches/pcsx2_0.9.2/RDebug/iloadp.txt b/branches/pcsx2_0.9.2/RDebug/iloadp.txt new file mode 100644 index 0000000..c8b6c68 --- /dev/null +++ b/branches/pcsx2_0.9.2/RDebug/iloadp.txt @@ -0,0 +1,32 @@ +ILOADP_MODULE_INFO{ + u16 flags Ŀ <Ŀ + u16 version < + u32 addr + u32 sz_text + u32 sz_data + u32 sz_bss + u32 reserved1 + u32 reserved2 + u32 reserved3 + u8* name +}; + +ILOADP_HDR{ + u8 cmd + u8 action + u8 result + u8 stamp + u32 module_id +}; + +ILOADP_START(cmd==00) +------------------------------------------ +ILOADP_HDR_START{ + ILOADP_HDR hdr //+00 + u8* modulename //+10 //asciiz +}; //=10+strlen(modulename)+1 +action 0D(IOP_LOAD_IRX) +modulename host:E:\TEMP2\GCC\share\SIO2D.IRX + +action 02(IOP_RUN) +modulename E:\TEMP2\GCC\share\SIO2D.IRX param diff --git a/branches/pcsx2_0.9.2/SPR.c b/branches/pcsx2_0.9.2/SPR.c new file mode 100644 index 0000000..0ea5d9e --- /dev/null +++ b/branches/pcsx2_0.9.2/SPR.c @@ -0,0 +1,399 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "SPR.h" + +#include "iR5900.h" + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) + +void sprInit() { +} + +//__inline static void SPR0transfer(u32 *data, int size) { +///* while (size > 0) { +//#ifdef SPR_LOG +// SPR_LOG("SPR1transfer: %x\n", *data); +//#endif +// data++; size--; +// }*/ +// size <<= 2; +// if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO +// (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO +// hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } else { +// u32 * p = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; +// //WriteCodeSSE2(p,data,size >> 4); +// memcpy_amd((u8*)data, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } +// spr0->sadr+= size; +//} + +static void TestClearVUs(u32 madr, u32 size) +{ + if( madr >= 0x11000000 ) { + if( madr < 0x11004000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu0\n"); +#endif + Cpu->ClearVU0(madr&0xfff, size); + } + else if( madr >= 0x11008000 && madr < 0x1100c000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu1\n"); +#endif + Cpu->ClearVU1(madr&0x3fff, size); + } + } +} + +int _SPR0chain() { + u32 qwc = spr0->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr0->madr); + if (pMem == NULL) return -1; + + //SPR0transfer(pMem, qwc << 2); + qwc <<= 4; + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr += (spr0->qwc * 16); + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + } else { + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + + Cpu->Clear(spr0->madr, qwc>>2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + spr0->madr += qwc; + } + spr0->sadr += qwc; + + spr0->qwc = 0; + return (qwc>>4) * BIAS; // bus is 1/2 the ee speed +} + +#define SPR0chain() \ + if (spr0->qwc) { \ + cycles += _SPR0chain(); \ +/* cycles+= spr0->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR0interleave() { + int qwc = spr0->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + //SysPrintf("dmaSPR0 interleave\n"); +#ifdef SPR_LOG + SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx\n", + spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr); +#endif + while (qwc > 0) { + spr0->qwc = min(tqwc, qwc); qwc-= spr0->qwc; + pMem = (u32*)dmaGetAddr(spr0->madr); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } else { + Cpu->Clear(spr0->madr, spr0->qwc<<2); + // clear VU mem also! + TestClearVUs(spr0->madr, spr0->qwc<<2); + + memcpy_amd((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } + cycles += tqwc * BIAS; + spr0->sadr+= spr0->qwc * 16; + spr0->madr+= (sqwc+spr0->qwc)*16; //qwc-= sqwc; + } + + spr0->qwc = 0; + INT(8, cycles); +} + +void _dmaSPR0() { + u32 *ptag; + int id; + int cycles = 0; + int done = 0; + + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR0 stall %d\n", (psHu32(DMAC_CTRL)>>6)&3); + } + + if ((spr0->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR0interleave(); + return; + } + + // Transfer Dn_QWC from SPR to Dn_MADR + + + + if ((spr0->chcr & 0xc) == 0 || spr0->qwc > 0) { // Normal Mode + SPR0chain(); + INT(8, cycles); + + return; + } + + // Destination Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; + spr0->sadr+= 16; + + // Transfer dma tag if tte is set +// if (spr0->chcr & 0x40) SPR0transfer(ptag, 4); + + spr0->chcr = ( spr0->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr0->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR stall control\n"); + } + + switch (id) { + case 0: // CNTS - Transfer QWC following the tag (Stall Control) + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20 ) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register + break; + + case 1: // CNT - Transfer QWC following the tag. + break; + + case 7: // End - Transfer QWC following the tag + done = 1; //End Transfer + break; + } + SPR0chain(); + if (spr0->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag + //SysPrintf("SPR0 TIE\n"); + done = 1; + spr0->qwc = 0; + break; + } + + +/* if (spr0->chcr & 0x80 && ptag[0] >> 31) { +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return; + }*/ + } + + INT(8, cycles); + +} + +int SPRFROMinterrupt() +{ + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return 1; +} + +extern void mfifoGIFtransfer(int); +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +void dmaSPR0() { // fromSPR + int qwc = spr0->qwc; +#ifdef SPR_LOG + SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx\n", + spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); +#endif + + _dmaSPR0(); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) { // GIF MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + //SysPrintf("mfifoGIFtransfer %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); + if(gif->chcr & 0x100)mfifoGIFtransfer(qwc); + } else + if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + //SysPrintf("mfifoVIF1transfer %x madr %x, tadr %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr); + if(vif1ch->chcr & 0x100)mfifoVIF1transfer(qwc); + } + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +__inline static void SPR1transfer(u32 *data, int size) { +/* { + int i; + for (i=0; isadr+i*4) & 0x3fff, data[i] ); +#endif + } + }*/ + //Cpu->Clear(spr1->sadr, size); // why? + memcpy_amd(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2); + + spr1->sadr+= size << 2; +} + +int _SPR1chain() { + u32 qwc = spr1->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr1->madr); + if (pMem == NULL) return -1; + + SPR1transfer(pMem, qwc << 2); + spr1->madr+= spr1->qwc << 4; + spr1->qwc = 0; + return (qwc) * BIAS; +} + +#define SPR1chain() \ + if (spr1->qwc) { \ + cycles += _SPR1chain(); \ +/* cycles+= spr1->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR1interleave() { + int qwc = spr1->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + +#ifdef SPR_LOG + SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx\n", + spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr); +#endif + while (qwc > 0) { + spr1->qwc = min(tqwc, qwc); qwc-= spr1->qwc; + pMem = (u32*)dmaGetAddr(spr1->madr); + memcpy_amd(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc <<4); + spr1->sadr += spr1->qwc * 16; + cycles += spr1->qwc * BIAS; + spr1->madr+= (sqwc + spr1->qwc) * 16; //qwc-= sqwc; + } + + spr1->qwc = 0; + INT(9, cycles); + +} + +void dmaSPR1() { // toSPR + u32 *ptag; + int id, done=0; + int cycles = 0; + +#ifdef SPR_LOG + SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" + " tadr = 0x%x, sadr = 0x%x\n", + spr1->chcr, spr1->madr, spr1->qwc, + spr1->tadr, spr1->sadr); +#endif + + if ((spr1->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR1interleave(); + FreezeMMXRegs(0); + return; + } + + + if ((spr1->chcr & 0xc) == 0 || spr1->qwc > 0) { // Normal Mode + // Transfer Dn_QWC from Dn_MADR to SPR1 + SPR1chain(); + INT(9, cycles); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("SPR1 Tag BUSERR\n"); + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + done = 1; + break; + } + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr1->madr = ptag[1]; //MADR = ADDR field + + // Transfer dma tag if tte is set + if (spr1->chcr & 0x40) { +#ifdef SPR_LOG + SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + SPR1transfer(ptag, 4); //Transfer Tag + + } + + + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr1->qwc, id, spr1->madr); +#endif + + done = hwDmacSrcChain(spr1, id); + SPR1chain(); //Transfers the data set by the switch + + if (spr1->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("SPR1 TIE\n"); + spr1->qwc = 0; + break; + } + } + + + INT(9, cycles); + FreezeMMXRegs(0); +} + +int SPRTOinterrupt() +{ + spr1->chcr &= ~0x100; + hwDmacIrq(9); + return 1; +} + diff --git a/branches/pcsx2_0.9.2/SPR.h b/branches/pcsx2_0.9.2/SPR.h new file mode 100644 index 0000000..7ae0a57 --- /dev/null +++ b/branches/pcsx2_0.9.2/SPR.h @@ -0,0 +1,29 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPR_H__ +#define __SPR_H__ + +#include "Common.h" + +void sprInit(); +void dmaSPR0(); +void dmaSPR1(); +int SPRFROMinterrupt(); +int SPRTOinterrupt(); +#endif /* __SPR_H__ */ diff --git a/branches/pcsx2_0.9.2/Sif.c b/branches/pcsx2_0.9.2/Sif.c new file mode 100644 index 0000000..912d753 --- /dev/null +++ b/branches/pcsx2_0.9.2/Sif.c @@ -0,0 +1,616 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "Sif.h" +#include "Sifcmd.h" + +#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000]) +#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) +#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) + +#define FIFO_SIF0_W 128 +#define FIFO_SIF1_W 128 + +typedef struct { + u32 fifoData[FIFO_SIF0_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; + struct sifData sifData; +} _sif0; + +typedef struct { + u32 fifoData[FIFO_SIF1_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; +} _sif1; + +_sif0 sif0; +_sif1 sif1; + +int sifInit() { + memset(&sif0, 0, sizeof(sif0)); + memset(&sif1, 0, sizeof(sif1)); + + return 0; +} + +void SIF0write(u32 *from, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoWritePos)) { + int wP0 = (FIFO_SIF0_W-sif0.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif0.fifoData[0], &from[wP0], wP1 << 2); + sif0.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif0.fifoData[sif0.fifoWritePos], from, words << 2); + sif0.fifoWritePos += words; + } + + sif0.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 + %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoWritePos); +#endif + +/* if (sif0.fifoSize == FIFO_SIF0_W) { + Cpu->ExecuteBlock(); + }*/ +} + +void SIF0read(u32 *to, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoReadPos)) + { + int wP0 = (FIFO_SIF0_W-sif0.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif0.fifoData[0], wP1 << 2); + sif0.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif0.fifoData[sif0.fifoReadPos], words << 2); + sif0.fifoReadPos += words; + } + + sif0.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 - %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoReadPos); +#endif +} + +void SIF1write(u32 *from, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoWritePos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoWritePos); + int wP1 = words - wP0; + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2); + memcpy_amd(&sif1.fifoData[0], &from[wP0], wP1 << 2); + sif1.fifoWritePos = wP1; + } + else + { + memcpy_amd(&sif1.fifoData[sif1.fifoWritePos], from, words << 2); + sif1.fifoWritePos += words; + } + + sif1.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 + %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoWritePos); +#endif + +/* if (sif1.fifoSize == FIFO_SIF1_W) { + psxCpu->ExecuteBlock(); + }*/ +} + +void SIF1read(u32 *to, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoReadPos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoReadPos); + int wP1 = words - wP0; + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2); + memcpy_amd(&to[wP0], &sif1.fifoData[0], wP1 << 2); + sif1.fifoReadPos = wP1; + } + else + { + memcpy_amd(to, &sif1.fifoData[sif1.fifoReadPos], words << 2); + sif1.fifoReadPos += words; + } + + sif1.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 - %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoReadPos); +#endif +} + +void SIF0Dma() +{ + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + +#ifdef SIF_LOG + SIF_LOG("SIF0 DMA start...\n"); +#endif + + do + { + notDone = 0; + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + if(HW_DMA9_CHCR & 0x01000000) // If EE SIF0 is enabled + { + int size = sif0.counter; //HW_DMA9_BCR >> 16; + + if(size == 0) // If there's no more to transfer + { + // Note.. add normal mode here + if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA + { +#ifdef SIF_LOG + SIF_LOG(" IOP SIF Stopped\n"); +#endif + + // Stop & signal interrupts on IOP + HW_DMA9_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + sif0.sifData.data = 0; + } + else if(FIFO_SIF1_W-sif0.fifoSize >= 2) // Chain mode + { + // Process DMA tag at HW_DMA9_TADR + sif0.sifData = *(struct sifData *)PSXM(HW_DMA9_TADR); + + sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4. + + SIF0write((u32*)PSXM(HW_DMA9_TADR+8), 4); + + //psxCycles += 2; + + HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF; + HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2; + //HW_DMA9_BCR = (sif0.sifData.words << 16) | 1; + sif0.counter = sif0.sifData.words & 0xFFFFFF; + notDone = 1; + +#ifdef SIF_LOG + SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)\n", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.sifData.words, sif0.sifData.data); +#endif + if(sif0.sifData.data & 0x40000000) + { +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + } + else + { +#ifdef SIF_LOG + SIF_LOG(" CNT %08X, %08X\n", sif0.sifData.data, sif0.sifData.words); +#endif + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int wTransfer = sif0.counter; // HW_DMA9_BCR >> 16; + + if (wTransfer > (FIFO_SIF0_W-sif0.fifoSize)) + wTransfer = (FIFO_SIF0_W-sif0.fifoSize); + +#ifdef SIF_LOG + SIF_LOG("+++++++++++ %lX of %lX\n", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/ ); +#endif + + SIF0write((u32*)PSXM(HW_DMA9_MADR), wTransfer); + HW_DMA9_MADR += wTransfer << 2; + //HW_DMA9_BCR = (HW_DMA9_BCR & 0xFFFF) | (((HW_DMA9_BCR >> 16) - wTransfer)<<16); + //psxCycles += (wTransfer / 4) * BIAS; + sif0.counter -= wTransfer; + + notDone = 1; + } + } + + if(sif0dma->chcr & 0x100) // If EE SIF enabled and there's something to transfer + { + int size = sif0dma->qwc; + if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) { // STS == fromSIF0 + SysPrintf("SIF0 stall control\n"); + } + if(size > 0) // If we're reading something continue to do so + { + if(sif0.fifoSize > 0) + { + int readSize = size; + + if(readSize > (sif0.fifoSize/4)) + readSize = (sif0.fifoSize/4); + + //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X\n", readSize, sif0dma->madr); +#ifdef SIF_LOG + SIF_LOG("----------- %lX of %lX\n", readSize << 2, size << 2 ); +#endif + + _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); + + SIF0read((u32*)ptag, readSize*4); + Cpu->Clear(sif0dma->madr, readSize*4); + + //cycles += readSize * BIAS; + sif0dma->qwc -= readSize; + sif0dma->madr += readSize << 4; + + notDone = 1; + } + } + else + { + if(sif0.chain && sif0dma->chcr & 0x80000000) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" EE SIF interrupt\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.end) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" EE SIF end\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.fifoSize >= 4) // Read a tag + { + static PCSX2_ALIGNED16(u32 tag[4]); + SIF0read((u32*)&tag[0], 4); // Tag + + sif0dma->qwc = (u16)tag[0]; + sif0dma->madr = tag[1]; + sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000); + +#ifdef SIF_LOG + SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)\n", sif0dma->madr, sif0dma->qwc, (tag[0]>>28)&3, (tag[0]>>31)&1, tag[1], tag[0]); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) != 0 && ((tag[0]>>28)&3) == 0)psHu32(DMAC_STADR) = sif0dma->madr + (sif0dma->qwc * 16); + notDone = 1; + sif0.chain = 1; + if(tag[0] & 0x40000000) + sif0.end = 1; + + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +void SIF1Dma() +{ + int id; + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + + do + { + notDone = 0; + + if(sif1dma->chcr & 0x100) // If EE SIF1 is enabled + { + if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0) { // STS == fromSIF1 + SysPrintf("SIF1 stall control\n"); + } + + if(sif1dma->qwc == 0) // If there's no more to transfer + { + if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA + { + // Stop & signal interrupts on EE + sif1dma->chcr &= ~0x100; + hwDmacIrq(6); + sif1.chain = 0; + sif1.end = 0; + } + else // Chain mode + { + // Process DMA tag at sif1dma->tadr + notDone = 1; + _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); + sif1dma->chcr = ( sif1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); // Copy the tag + sif1dma->qwc = (u16)ptag[0]; + + if (sif1dma->chcr & 0x40) { + SysPrintf("SIF1 TTE\n"); + SIF1write(ptag+2, 2); + } + + sif1.chain = 1; + id = (ptag[0] >> 28) & 0x7; + + switch(id) + { + case 0: // refe +#ifdef SIF_LOG + SIF_LOG(" REFE %08X\n", ptag[1]); +#endif + sif1.end = 1; + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 1: // cnt +#ifdef SIF_LOG + SIF_LOG(" CNT\n"); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + case 2: // next +#ifdef SIF_LOG + SIF_LOG(" NEXT %08X\n", ptag[1]); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = ptag[1]; + break; + + case 3: // ref + case 4: // refs +#ifdef SIF_LOG + SIF_LOG(" REF %08X\n", ptag[1]); +#endif + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 7: // end +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + sif1.end = 1; + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + default: + SysPrintf("Bad addr1 source chain\n"); + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int qwTransfer = sif1dma->qwc; + u32 *data; + + notDone = 1; + + _dmaGetAddr(sif1dma, data, sif1dma->madr, 6); + + if(qwTransfer > (FIFO_SIF1_W-sif1.fifoSize)/4) // Copy part of sif1dma into FIFO + qwTransfer = (FIFO_SIF1_W-sif1.fifoSize)/4; + + SIF1write(data, qwTransfer << 2); + + sif1dma->madr += qwTransfer << 4; + //cycles += qwTransfer * BIAS; + sif1dma->qwc -= qwTransfer; + } + } + + if(HW_DMA10_CHCR & 0x01000000 ) // If IOP SIF enabled and there's something to transfer + { + int size = sif1.counter; + + if(size > 0) // If we're reading something continue to do so + { + if(sif1.fifoSize > 0) + { + int readSize = size; + + if(readSize > sif1.fifoSize) + readSize = sif1.fifoSize; + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF doing transfer %04X to %08X\n", readSize, HW_DMA10_MADR); +#endif + + SIF1read((u32*)PSXM(HW_DMA10_MADR), readSize); + psxCpu->Clear(HW_DMA10_MADR, readSize); + //psxCycles += readSize / 4; + sif1.counter = size-readSize; + HW_DMA10_MADR += readSize << 2; + notDone = 1; + } + } + + if(size <= 0 || sif1.fifoSize == 0) + { + if(sif1.tagMode & 0x80) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" IOP SIF interrupt\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.tagMode & 0x40) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" IOP SIF end\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.fifoSize >= 4) // Read a tag + { + struct sifData d; + + SIF1read((u32*)&d, 4); + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d\n", d.data & 0xffffff, d.words, (d.data>>28)&7, (d.data>>31)&1); +#endif + HW_DMA10_MADR = d.data & 0xffffff; + sif1.counter = d.words; + sif1.tagMode = (d.data >> 24) & 0xFF; + notDone = 1; + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +int sif0Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(9, 0x800); + return 0; + }*/ + + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int sif1Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(10, 0x800); + return 0; + }*/ + + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int EEsif0Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<5)) { + INT(5, 0x800); + return 0; + }*/ + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + + return 1; +} + +int EEsif1Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<6)) { + INT(6, 0x800); + return 0; + }*/ + hwDmacIrq(6); + + return 1; +} + +void dmaSIF0() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr); +#endif + + if (sif0.fifoReadPos != sif0.fifoWritePos) { + SysPrintf("warning, sif0.fifoReadPos != sif0.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x2000; + if(sif0dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + hwIntcIrq(INTC_SBUS); + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void dmaSIF1() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr); +#endif + + if (sif1.fifoReadPos != sif1.fifoWritePos) { + SysPrintf("warning, sif1.fifoReadPos != sif1.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x4000; + if(sif1dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void dmaSIF2() { + +#ifdef SIF_LOG + SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx\n", + sif2dma->chcr, sif2dma->madr, sif2dma->qwc); +#endif + + sif2dma->chcr&= ~0x100; + hwDmacIrq(7); + SysPrintf("*PCSX2*: dmaSIF2\n"); +} + + +int sifFreeze(gzFile f, int Mode) { + gzfreeze(&sif0, sizeof(sif0)); + gzfreeze(&sif1, sizeof(sif1)); + return 0; +} diff --git a/branches/pcsx2_0.9.2/Sif.h b/branches/pcsx2_0.9.2/Sif.h new file mode 100644 index 0000000..e381605 --- /dev/null +++ b/branches/pcsx2_0.9.2/Sif.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIF_H__ +#define __SIF_H__ + +#include "Common.h" + +struct sifData{ + int data, + words, + count, + addr; +}; + +int eeSifTransfer; + +DMACh *sif0ch; +DMACh *sif1ch; +DMACh *sif2ch; + +int sifInit(); +void SIF0Dma(); +void SIF1Dma(); +void dmaSIF0(); +void dmaSIF1(); +void dmaSIF2(); +int EEsif1Interrupt(); +int EEsif0Interrupt(); +int EEsif2Interrupt(); +int sifFreeze(gzFile f, int Mode); + + +#endif /* __SIF_H__ */ diff --git a/branches/pcsx2_0.9.2/Sifcmd.h b/branches/pcsx2_0.9.2/Sifcmd.h new file mode 100644 index 0000000..b953fed --- /dev/null +++ b/branches/pcsx2_0.9.2/Sifcmd.h @@ -0,0 +1,193 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIFCMD_H__ +#define __SIFCMD_H__ + +/* from sifcmd.h */ + +#define SYSTEM_CMD 0x80000000 + +struct t_sif_cmd_header +{ + u32 size; + void *dest; + int command; + u32 unknown; +}; + +struct t_sif_dma_transfer +{ + void *src, + *dest; + int size; + int attr; +}; + +struct t_sif_handler +{ + void (*handler) ( void *a, void *b); + void *buff; +}; + +#define SYSTEM_CMD_CHANGE_SADDR 0x80000000 +#define SYSTEM_CMD_INIT_CMD 0x80000002 +struct t_sif_saddr{ + struct t_sif_cmd_header hdr; //+00 + void *newaddr; //+10 +}; //=14 + +#define SYSTEM_CMD_SET_SREG 0x80000001 +struct t_sif_sreg{ + struct t_sif_cmd_header hdr; //+00 + int index; //+10 + unsigned int value; //+14 +}; //=18 + +#define SYSTEM_CMD_RESET 0x80000003 +struct t_sif_reset{ + struct t_sif_cmd_header hdr; //+00 + int size, //+10 + flag; //+14 + char data[80]; //+18 +}; //=68 + +/* end of sifcmd.h */ + +/* from sifsrpc.h */ + +struct t_sif_rpc_rend +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_client_data *client; /* 7 */ + u32 command; /* 8 */ + struct t_rpc_server_data *server; /* 9 */ + void *buff, /* 10 */ + *buff2; /* 11 */ +}; + +struct t_sif_rpc_other_data +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_receive_data *receive; /* 07 */ + void *src; /* 08 */ + void *dest; /* 09 */ + int size; /* 10 */ +}; + +struct t_sif_rpc_bind +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ +}; + +struct t_sif_rpc_call +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ + int send_size; /* 09 */ + void *receive; /* 10 */ + int rec_size; /* 11 */ + int has_async_ef; /* 12 */ + struct t_rpc_server_data *server; /* 13 */ +}; + +struct t_rpc_server_data +{ + int command; /* 04 00 */ + + void * (*func)(u32, void *, int); /* 05 01 */ + void *buff; /* 06 02 */ + int size; /* 07 03 */ + + void * (*func2)(u32, void *, int); /* 08 04 */ + void *buff2; /* 09 05 */ + int size2; /* 10 06 */ + + struct t_rpc_client_data *client; /* 11 07 */ + void *pkt_addr; /* 12 08 */ + int rpc_number; /* 13 09 */ + + void *receive; /* 14 10 */ + int rec_size; /* 15 11 */ + int has_async_ef; /* 16 12 */ + int rec_id; /* 17 13 */ + + struct t_rpc_server_data *link; /* 18 14 */ + struct r_rpc_server_data *next; /* 19 15 */ + struct t_rpc_data_queue *queued_object; /* 20 16 */ +}; + + +struct t_rpc_header +{ + void *pkt_addr; /* 04 00 */ + u32 rpc_id; /* 05 01 */ + int sema_id; /* 06 02 */ + u32 mode; /* 07 03 */ +}; + + +struct t_rpc_client_data +{ + struct t_rpc_header hdr; + u32 command; /* 04 08 */ + void *buff, /* 05 09 */ + *buff2; /* 06 10 */ + void (*end_function) ( void *); /* 07 11 */ + void *end_param; /* 08 12*/ + struct t_rpc_server_data *server; /* 09 13 */ +}; + +struct t_rpc_receive_data +{ + struct t_rpc_header hdr; + void *src, /* 04 */ + *dest; /* 05 */ + int size; /* 06 */ +}; + +struct t_rpc_data_queue +{ + int thread_id, /* 00 */ + active; /* 01 */ + struct t_rpc_server_data *svdata_ref, /* 02 */ + *start, /* 03 */ + *end; /* 04 */ + struct t_rpc_data_queue *next; /* 05 */ +}; + +/* end of sifrpc.h */ + +#endif//__SIFCMD_H__ diff --git a/branches/pcsx2_0.9.2/Sio.c b/branches/pcsx2_0.9.2/Sio.c new file mode 100644 index 0000000..f352692 --- /dev/null +++ b/branches/pcsx2_0.9.2/Sio.c @@ -0,0 +1,566 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "PsxCommon.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + +const unsigned char buf1[] = {0x25, 0x46, 0x01, 0x31, 0x00, 0xA2, 0x11, 0x01, 0xE1};//{0x64, 0x23, 0x2, 0x43, 0x0, 0xa2, 0x11, 0x1, 0xb4}; +const unsigned char buf2[] = {0xC5, 0xBD, 0x66, 0x00, 0x59, 0x44, 0x01, 0x02, 0x00};//{0x6d, 0x21, 0x30, 0x0, 0x55, 0x19, 0x2, 0x2, 0x30}; +const unsigned char buf4[] = {0x02, 0x9A, 0x9E, 0x06, 0x6D, 0x3C, 0xF0, 0x7E, 0xDF};//{0xa3, 0x5d, 0x2f, 0xa2, 0xd8, 0x7c, 0x5b, 0x35, 0xb9}; +const unsigned char buff[] = {0xC2, 0x39, 0x6F, 0x27, 0xC8, 0xDF, 0x2A, 0x23, 0xAD};//{0xf3, 0x9b, 0x32, 0x87, 0x31, 0xda, 0x9d, 0x10, 0xbb}; +const unsigned char buf11[] = {0xA8, 0x42, 0x5D, 0x87, 0x65, 0x32, 0x6F, 0xE8, 0xE0};//{0x39, 0xd2, 0xb9, 0x5c, 0xcf, 0x31, 0x2d, 0x23, 0xfe}; +const unsigned char buf13[] = {0x46, 0x31, 0xFC, 0x97, 0xA8, 0x6D, 0xE2, 0x12, 0x29};//{0x20, 0x2e, 0xd7, 0x99, 0x92, 0x29, 0x4a, 0x12, 0xa3}; + +const unsigned char cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; +struct mc_command_0x26_tag mc_command_0x26= + {'+', 512, 16, 0x4000, 0x52, 'Z'};//sizeof()==11 + +// clk cycle byte +// 4us * 8bits = ((PSXCLK / 1000000) * 32) / BIAS; (linuzappz) +#define SIO_INT() PSX_INT(16, PSXCLK/250000); /*270;*/ + +void _ReadMcd(char *data, u32 adr, int size) { + ReadMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +void _SaveMcd(char *data, u32 adr, int size) { + SaveMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +unsigned char _xor(unsigned char *buf, unsigned int length){ + register unsigned char i, x; + + for (x=0, i=0; i>13)+1, value); +#endif + } + sio.mc_command=value; + if (sio.mc_command!=0x21 && sio.mc_command!=0x22 && sio.mc_command!=0x23 && + (sio.mc_command!=0xF0) && (sio.mc_command!=0xF1) && (sio.mc_command!=0xF2)) { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + } + return; + case 99://as is... + sio.packetsize++; + sio.parp++; + switch(sio.mc_command) + { + case 0x21: + case 0x22: + case 0x23: + if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0; + if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8; + if (sio.parp==4)sio.sector|=(value & 0xFF)<<16; + if (sio.parp==5)sio.sector|=(value & 0xFF)<<24; + if (sio.parp==6) + { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X sio.sector 0x%04X\n", + ((sio.CtrlReg&0x2000)>>13)+1, sio.mc_command, sio.sector); +#endif + } + break; + case 0x27: + if(sio.parp==2) { + sio.terminator = value; + sio.buf[4] = value; + } + break; + case 0x28: + if(sio.parp == 2) { + sio.buf[2] = '+'; + if(value == 0) { + sio.buf[4] = 0xFF; + sio.buf[3] = sio.terminator; + }else{ + sio.buf[4] = 0x5A; + sio.buf[3] = sio.terminator; + } + } + break; + case 0x42: + if (sio.parp==2) { + sio.bufcount=5+value; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + sio.buf[sio.bufcount]=sio.terminator; + } else + if ((sio.parp>2) && (sio.parp>13)+1, value, _xor(&sio.buf[3], sio.bufcount-5)); +#endif + } + } + break; + case 0x43: + if (sio.parp==2){ + sio.bufcount=value+5; + sio.buf[3]='+'; + _ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value); + if(sio.mode==2) { + int j; + for(j=0; j < value; j++) + sio.buf[4+j] = ~sio.buf[4+j]; + } + sio.k+=value; + sio.buf[sio.bufcount-1]=_xor(&sio.buf[4], value); + sio.buf[sio.bufcount]=sio.terminator; + } + break; + case 0x82: + if(sio.parp==2) { + sio.buf[2]='+'; + sio.buf[3]=sio.terminator; + } + break; + case 0xF0: + if (sio.parp==2) + { + u32 flag=0; +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0xF0:0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + switch(value){ + case 1: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf1,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 2: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf2,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 4: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf4,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 6: + case 7: + case 11: + flag=0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + break;//IN + case 15: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buff,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 17: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf11,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 19: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf13,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + default: + sio.bufcount=4; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + } + + if ((sio.bufcount==13) && flag){ + sio.buf[sio.bufcount-1] = 0;//xor value for OUT data + sio.buf[3]='+'; + } + sio.buf[sio.bufcount]=sio.terminator; + } + break; + } + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + return; + } + + switch (sio.mtapst) { + case 0x1: + sio.packetsize++; + sio.parp = 1; + SIO_INT(); + switch(value) { + case 0x12: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x13: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x21: sio.mtapst = 2; sio.bufcount = 6; break; + } + sio.buf[sio.bufcount]='Z'; + sio.buf[sio.bufcount-1]='+'; + return; + case 0x2: + sio.packetsize++; + sio.parp++; + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + SIO_INT(); + return; + } + + switch (value) { + case 0x01: // start pad + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + + switch (sio.CtrlReg&0x2002) { + case 0x0002: sio.buf[0] = PAD1startPoll(1); break; + case 0x2002: sio.buf[0] = PAD2startPoll(2); break; + } + + sio.bufcount = 2; + sio.parp = 0; + sio.padst = 1; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x21: // start mtap + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio.mtapst = 1; + sio2.packet.recvVal1 = 0x1D100; // Mtap is not connected :) + SIO_INT(); + return; + + case 0x61: // start remote control sensor + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x81: // start memcard + sio.StatReg &= ~TX_EMPTY; + sio.StatReg |= RX_RDY; + memcpy(sio.buf, cardh, 4); + sio.parp = 0; + sio.bufcount = 3; + sio.mcdst = 1; + sio.packetsize = 1; + sio.rdwr = 0; + sio2.packet.recvVal1 = 0x1100; // Memcard1 is present + SIO_INT(); + return; + } +} + +void sioWriteCtrl16(unsigned short value) { + sio.CtrlReg = value & ~RESET_ERR; + if (value & RESET_ERR) sio.StatReg &= ~IRQ; + if ((sio.CtrlReg & SIO_RESET) || (!sio.CtrlReg)) { + sio.mtapst = 0; sio.padst = 0; sio.mcdst = 0; sio.parp = 0; + sio.StatReg = TX_RDY | TX_EMPTY; + psxRegs.interrupt&= ~(1<<16); + } +} + +int sioInterrupt() { +#ifdef PAD_LOG + PAD_LOG("Sio Interrupt\n"); +#endif + sio.StatReg|= IRQ; + psxHu32(0x1070)|=0x80; + return 1; +} + +FILE *LoadMcd(int mcd) { + char str[256]; + FILE *f; + + if (mcd == 1) { + strcpy(str, Config.Mcd1); + } else { + strcpy(str, Config.Mcd2); + } + if (*str == 0) sprintf(str, "memcards/Mcd00%d.ps2", mcd); + f = fopen(str, "r+b"); + if (f == NULL) { + CreateMcd(str); + f = fopen(str, "r+b"); + } + if (f == NULL) { + SysMessage (_("Failed loading MemCard %s"), str); return NULL; + } + + return f; +} + +void SeekMcd(FILE *f, u32 adr) { + u32 size; + + fseek(f, 0, SEEK_END); size = ftell(f); + if (size == MCD_SIZE + 64) + fseek(f, adr + 64, SEEK_SET); + else if (size == MCD_SIZE + 3904) + fseek(f, adr + 3904, SEEK_SET); + else + fseek(f, adr, SEEK_SET); +} + +void ReadMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + memset(data, 0, size); + return; + } + SeekMcd(f, adr); + fread(data, 1, size, f); + fclose(f); +} + +void SaveMcd(int mcd, char *data, u32 adr, int size) { + FILE *f = LoadMcd(mcd); + if (f == NULL) { + return; + } + SeekMcd(f, adr); + fwrite(data, 1, size, f); + fclose(f); +} + +void CreateMcd(char *mcd) { + FILE *fp; + int i=0, j=0; + int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + + fp = fopen(mcd, "wb"); + if (fp == NULL) return; + for(i=0; i < 16384; i++) + { + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 16; j++) fputc(enc[j],fp); + } + fclose(fp); +} + +int sioFreeze(gzFile f, int Mode) { + gzfreeze(&sio, sizeof(sio)); + + return 0; +} + + diff --git a/branches/pcsx2_0.9.2/Sio.h b/branches/pcsx2_0.9.2/Sio.h new file mode 100644 index 0000000..2d55a01 --- /dev/null +++ b/branches/pcsx2_0.9.2/Sio.h @@ -0,0 +1,114 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _SIO_H_ +#define _SIO_H_ + +typedef struct { + u16 StatReg; + u16 ModeReg; + u16 CtrlReg; + u16 BaudReg; + + u8 buf[256]; + u32 bufcount; + u32 parp; + u32 mcdst,rdwr; + u8 adrH,adrL; + u32 padst; + u32 mtapst; + u32 packetsize; + + u8 terminator; + u8 mode; + u8 mc_command; + u32 lastsector; + u32 sector; + u32 k; +} _sio; +_sio sio; + +#define MCD_SIZE (1024 * 8 * 16) +#define MC2_SIZE (1024 * 528 * 16) + +// Status Flags +#define TX_RDY 0x0001 +#define RX_RDY 0x0002 +#define TX_EMPTY 0x0004 +#define PARITY_ERR 0x0008 +#define RX_OVERRUN 0x0010 +#define FRAMING_ERR 0x0020 +#define SYNC_DETECT 0x0040 +#define DSR 0x0080 +#define CTS 0x0100 +#define IRQ 0x0200 + +// Control Flags +#define TX_PERM 0x0001 +#define DTR 0x0002 +#define RX_PERM 0x0004 +#define BREAK 0x0008 +#define RESET_ERR 0x0010 +#define RTS 0x0020 +#define SIO_RESET 0x0040 + +int Mcd1Size, Mcd2Size; + +int sioInit(); +void sioShutdown(); +unsigned char sioRead8(); +void sioWrite8(unsigned char value); +void sioWriteCtrl16(unsigned short value); +int sioInterrupt(); +int sioFreeze(gzFile f, int Mode); + +FILE *LoadMcd(int mcd); +void ReadMcd(int mcd, char *data, u32 adr, int size); +void SaveMcd(int mcd, char *data, u32 adr, int size); +void CreateMcd(char *mcd); + +typedef struct { + char Title[48]; + char ID[14]; + char Name[16]; + int IconCount; + short Icon[16*16*3]; + unsigned char Flags; +} McdBlock; + +#ifdef __WIN32__ +#pragma pack(1) +#endif +struct mc_command_0x26_tag{ + u8 field_151; //+02 flags + u16 sectorSize; //+03 divide to it + u16 field_2C; //+05 divide to it + u32 mc_size; //+07 + u8 _xor; //+0b don't forget to recalculate it!!! + u8 Z; //+0c +#ifdef __WIN32__ +}; +#pragma pack() +#else +} __attribute__((packed)); +#endif + +void GetMcdBlockInfo(int mcd, int block, McdBlock *info); + +#endif diff --git a/branches/pcsx2_0.9.2/Stats.c b/branches/pcsx2_0.9.2/Stats.c new file mode 100644 index 0000000..c5d5f26 --- /dev/null +++ b/branches/pcsx2_0.9.2/Stats.c @@ -0,0 +1,71 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "Stats.h" + +void statsOpen() { + stats.vsyncCount = 0; + stats.vsyncTime = time(NULL); + stats.eeCycles = 0; + stats.eeSCycle = 0; + stats.iopCycles = 0; + stats.iopSCycle = 0; +} + +void statsClose() { + time_t t; + FILE *f; + + t = time(NULL) - stats.vsyncTime; +#ifdef __WIN32__ + f = fopen("logs\\stats.txt", "w"); +#else + f = fopen("logs/stats.txt", "w"); +#endif + if (!f) { SysPrintf("Can't open stats.txt\n"); return; } + fprintf(f, "-- PCSX2 v%s statics--\n\n", PCSX2_VERSION); + fprintf(f, "Ran for %d seconds\n", t); + fprintf(f, "Total VSyncs: %d (%s)\n", stats.vsyncCount, Config.PsxType ? "PAL" : "NTSC"); +#ifndef __x86_64__ + fprintf(f, "VSyncs per Seconds: %g\n", (double)stats.vsyncCount / t); +#endif + fprintf(f, "Total EE Instructions Executed: %lld\n", stats.eeCycles); + fprintf(f, "Total IOP Instructions Executed: %lld\n", stats.iopCycles); + if (!CHECK_EEREC) fprintf(f, "Interpreter Mode\n"); + else fprintf(f, "Recompiler Mode: VUrec1 %s, VUrec0 %s\n", + CHECK_VU1REC ? "Enabled" : "Disabled", CHECK_VU0REC ? "Enabled" : "Disabled"); + fclose(f); +} + +void statsVSync() { + static u64 accum = 0, accumvu1 = 0; + static u32 frame = 0; + + stats.eeCycles+= cpuRegs.cycle - stats.eeSCycle; + stats.eeSCycle = cpuRegs.cycle; + stats.iopCycles+= psxRegs.cycle - stats.iopSCycle; + stats.iopSCycle = psxRegs.cycle; + stats.vsyncCount++; + stats.vif1count = 0; + stats.vu1count = 0; +} diff --git a/branches/pcsx2_0.9.2/Stats.h b/branches/pcsx2_0.9.2/Stats.h new file mode 100644 index 0000000..a914e6b --- /dev/null +++ b/branches/pcsx2_0.9.2/Stats.h @@ -0,0 +1,43 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __STATS_H__ +#define __STATS_H__ + +#include + +typedef struct { + time_t vsyncTime; + u32 vsyncCount; + u32 eeCycles; + u32 eeSCycle; + u32 iopCycles; + u32 iopSCycle; + + u32 ticko; + u32 framecount; + u32 vu1count; + u32 vif1count; +} Stats; +Stats stats; + +void statsOpen(); +void statsClose(); +void statsVSync(); + +#endif /* __STATS_H__ */ diff --git a/branches/pcsx2_0.9.2/System.h b/branches/pcsx2_0.9.2/System.h new file mode 100644 index 0000000..a425b93 --- /dev/null +++ b/branches/pcsx2_0.9.2/System.h @@ -0,0 +1,59 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +int SysInit(); // Init mem and plugins +void SysReset(); // Resets mem +void SysPrintf(char *fmt, ...); // Printf used by bios syscalls +void SysMessage(char *fmt, ...); // Message used to print msg to users +void SysUpdate(); // Called on VBlank (to update i.e. pads) +void SysRunGui(); // Returns to the Gui +void SysClose(); // Close mem and plugins +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void *SysMmap(uptr base, u32 size); +void SysMunmap(uptr base, u32 size); + +#ifdef WIN32_VIRTUAL_MEM +typedef struct _PSMEMORYBLOCK +{ + ULONG_PTR NumberPages; + ULONG_PTR* aPFNs; + ULONG_PTR* aVFNs; // virtual pages that own the physical pages +} PSMEMORYBLOCK; + +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock); +void SysPhysicalFree(PSMEMORYBLOCK* pblock); +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualFree(void* lpMemReserved, u32 size); + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualProtectFree(void* lpMemReserved, u32 size); + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray); + +// call to enable physical page allocation +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); + +#endif + +#endif /* __SYSTEM_H__ */ diff --git a/branches/pcsx2_0.9.2/VU.h b/branches/pcsx2_0.9.2/VU.h new file mode 100644 index 0000000..758bd80 --- /dev/null +++ b/branches/pcsx2_0.9.2/VU.h @@ -0,0 +1,174 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU_H__ +#define __VU_H__ + +#define REG_STATUS_FLAG 16 +#define REG_MAC_FLAG 17 +#define REG_CLIP_FLAG 18 +#define REG_ACC_FLAG 19 // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) +#define REG_R 20 +#define REG_I 21 +#define REG_Q 22 +#define REG_P 23 //only exists in micromode +#define REG_VF0_FLAG 24 // dummy flag that indicates VF0 is read (nothing to do with VI[24]) +#define REG_TPC 26 +#define REG_CMSAR0 27 +#define REG_FBRST 28 +#define REG_VPU_STAT 29 +#define REG_CMSAR1 31 + +enum VUStatus { + VU_Ready = 0, + VU_Run = 1, + VU_Stop = 2, +}; + +typedef union { + struct { + float x,y,z,w; + } f; + struct { + u32 x,y,z,w; + } i; + + float F[4]; + + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} VECTOR; + +typedef union { + float F; + s32 SL; + u32 UL; + s16 SS[2]; + u16 US[2]; + s8 SC[4]; + u8 UC[4]; +} REG_VI; + +#define VUFLAG_BREAKONMFLAG 0x00000001 +#define VUFLAG_MFLAGSET 0x00000002 + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; + u32 statusflag; +} fdivPipe; + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; +} efuPipe; + +typedef struct { + int enable; + int reg; + int xyzw; + u32 sCycle; + u32 Cycle; + u32 macflag; + u32 statusflag; + u32 clipflag; +} fmacPipe; + +typedef struct _VURegs { + VECTOR VF[32]; + REG_VI VI[32]; + VECTOR ACC; + REG_VI q; + REG_VI p; + + u32 macflag; + u32 statusflag; + u32 clipflag; + + u32 cycle; + u32 flags; + + void (*vuExec)(struct _VURegs*); + VIFregisters *vifRegs; + + u8 *Mem; + u8 *Micro; + + u32 code; + u32 maxmem; + u32 maxmicro; + + u16 branch; + u16 ebit; + u32 branchpc; + + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + +} VURegs; + +#define VUPIPE_NONE 0 +#define VUPIPE_FMAC 1 +#define VUPIPE_FDIV 2 +#define VUPIPE_EFU 3 +#define VUPIPE_IALU 4 +#define VUPIPE_BRANCH 5 +#define VUPIPE_XGKICK 6 + +#define VUREG_READ 0x1 +#define VUREG_WRITE 0x2 + +typedef struct { + u8 pipe; // if 0xff, COP2 + u8 VFwrite; + u8 VFwxyzw; + u8 VFr0xyzw; + u8 VFr1xyzw; + u8 VFread0; + u8 VFread1; + u32 VIwrite; + u32 VIread; + int cycles; +} _VURegsNum; + +extern VURegs* g_pVU1; +extern VURegs VU0; + +#define VU1 (*g_pVU1) + +__forceinline u32* GET_VU_MEM(VURegs* VU, u32 addr) +{ + if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); + + if( addr >= 0x4200 ) return &VU1.VI[(addr>>2)&0x1f].UL; + + return (u32*)(VU0.Mem+(addr&0x0fff)); +} + +#endif /* __VU_H__ */ diff --git a/branches/pcsx2_0.9.2/VU0.c b/branches/pcsx2_0.9.2/VU0.c new file mode 100644 index 0000000..92dc4b9 --- /dev/null +++ b/branches/pcsx2_0.9.2/VU0.c @@ -0,0 +1,383 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO + -Fix the flags Proper as they aren't handle now.. + -Add BC Table opcodes + -Add Interlock in QMFC2,QMTC2,CFC2,CTC2 + -Finish instruction set + -Bug Fixes!!! +*/ + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUops.h" +#include "VUmicro.h" + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X (cpuRegs.code>>24) & 0x1 +#define _Y (cpuRegs.code>>23) & 0x1 +#define _Z (cpuRegs.code>>22) & 0x1 +#define _W (cpuRegs.code>>21) & 0x1 + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) + +#include "VUflags.h" + +PCSX2_ALIGNED16(VURegs VU0); + +void COP2() { +#ifdef VU0_LOG + VU0_LOG("%s\n", disR5900Fasm(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP2PrintTable[_Rs_](); +} + +void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} +void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} + +void COP2_SPECIAL2() { + Int_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](); +} + +void COP2_Unknown() +{ +#ifdef CPU_LOG + CPU_LOG("Unknown COP2 opcode called\n"); +#endif +} + +void LQC2() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code; + if (_Ft_) { + memRead128(addr, &VU0.VF[_Ft_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +// Asadr.Changed +void SQC2() { + u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; + memWrite64(addr, VU0.VF[_Ft_].UD[0]); + memWrite64(addr+8,VU0.VF[_Ft_].UD[1]); +} + + +//**************************************************************************** +void _vu0WaitMicro() { + int startcycle; + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) { + return; + } + + startcycle = VU0.cycle; + + VU0.flags|= VUFLAG_BREAKONMFLAG; + VU0.flags&= ~VUFLAG_MFLAGSET; + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU0Block(); + } while ((VU0.VI[REG_VPU_STAT].UL & 0x1) && (VU0.flags & VUFLAG_MFLAGSET) == 0); + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + + //NEW + cpuRegs.cycle += (VU0.cycle-startcycle)*2; + VU0.flags&= ~VUFLAG_BREAKONMFLAG; +} + + +void QMFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UD[0] = VU0.VF[_Fs_].UD[0]; + cpuRegs.GPR.r[_Rt_].UD[1] = VU0.VF[_Fs_].UD[1]; +} + +void QMTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + VU0.VF[_Fs_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + VU0.VF[_Fs_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void CFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UL[0] = VU0.VI[_Fs_].UL; + if(VU0.VI[_Fs_].UL & 0x80000000) + cpuRegs.GPR.r[_Rt_].UL[1] = 0xffffffff; + else + cpuRegs.GPR.r[_Rt_].UL[1] = 0; +} + +void CTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + VU0.VI[REG_FBRST].UL = cpuRegs.GPR.r[_Rt_].UL[0] & 0x0C0C; + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x1) { // VU0 Force Break + SysPrintf("fixme: VU0 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x2) { // VU0 Reset + //SysPrintf("fixme: VU0 Reset\n"); + vu0ResetRegs(); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x100) { // VU1 Force Break + SysPrintf("fixme: VU1 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x200) { // VU1 Reset +// SysPrintf("fixme: VU1 Reset\n"); + vu1ResetRegs(); + } + break; + case REG_CMSAR1: // REG_CMSAR1 + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { + VU1.VI[REG_TPC].UL = cpuRegs.GPR.r[_Rt_].US[0]; + vu1ExecMicro(VU1.VI[REG_TPC].UL); // Execute VU1 Micro SubRoutine + } + break; + default: + VU0.VI[_Fs_].UL = cpuRegs.GPR.r[_Rt_].UL[0]; + break; + } +} + +//--------------------------------------------------------------------------------------- + + +#define SYNCMSFLAGS() VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; VU0.VI[REG_MAC_FLAG].UL = VU0.macflag; +#define SYNCFDIV() VU0.VI[REG_Q].UL = VU0.q.UL; VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; + +void VABS() { VU0.code = cpuRegs.code; _vuABS(&VU0); } +void VADD() { VU0.code = cpuRegs.code; _vuADD(&VU0); SYNCMSFLAGS(); } +void VADDi() { VU0.code = cpuRegs.code; _vuADDi(&VU0); SYNCMSFLAGS(); } +void VADDq() { VU0.code = cpuRegs.code; _vuADDq(&VU0); SYNCMSFLAGS(); } +void VADDx() { VU0.code = cpuRegs.code; _vuADDx(&VU0); SYNCMSFLAGS(); } +void VADDy() { VU0.code = cpuRegs.code; _vuADDy(&VU0); SYNCMSFLAGS(); } +void VADDz() { VU0.code = cpuRegs.code; _vuADDz(&VU0); SYNCMSFLAGS(); } +void VADDw() { VU0.code = cpuRegs.code; _vuADDw(&VU0); SYNCMSFLAGS(); } +void VADDA() { VU0.code = cpuRegs.code; _vuADDA(&VU0); SYNCMSFLAGS(); } +void VADDAi() { VU0.code = cpuRegs.code; _vuADDAi(&VU0); SYNCMSFLAGS(); } +void VADDAq() { VU0.code = cpuRegs.code; _vuADDAq(&VU0); SYNCMSFLAGS(); } +void VADDAx() { VU0.code = cpuRegs.code; _vuADDAx(&VU0); SYNCMSFLAGS(); } +void VADDAy() { VU0.code = cpuRegs.code; _vuADDAy(&VU0); SYNCMSFLAGS(); } +void VADDAz() { VU0.code = cpuRegs.code; _vuADDAz(&VU0); SYNCMSFLAGS(); } +void VADDAw() { VU0.code = cpuRegs.code; _vuADDAw(&VU0); SYNCMSFLAGS(); } +void VSUB() { VU0.code = cpuRegs.code; _vuSUB(&VU0); SYNCMSFLAGS(); } +void VSUBi() { VU0.code = cpuRegs.code; _vuSUBi(&VU0); SYNCMSFLAGS(); } +void VSUBq() { VU0.code = cpuRegs.code; _vuSUBq(&VU0); SYNCMSFLAGS(); } +void VSUBx() { VU0.code = cpuRegs.code; _vuSUBx(&VU0); SYNCMSFLAGS(); } +void VSUBy() { VU0.code = cpuRegs.code; _vuSUBy(&VU0); SYNCMSFLAGS(); } +void VSUBz() { VU0.code = cpuRegs.code; _vuSUBz(&VU0); SYNCMSFLAGS(); } +void VSUBw() { VU0.code = cpuRegs.code; _vuSUBw(&VU0); SYNCMSFLAGS(); } +void VSUBA() { VU0.code = cpuRegs.code; _vuSUBA(&VU0); SYNCMSFLAGS(); } +void VSUBAi() { VU0.code = cpuRegs.code; _vuSUBAi(&VU0); SYNCMSFLAGS(); } +void VSUBAq() { VU0.code = cpuRegs.code; _vuSUBAq(&VU0); SYNCMSFLAGS(); } +void VSUBAx() { VU0.code = cpuRegs.code; _vuSUBAx(&VU0); SYNCMSFLAGS(); } +void VSUBAy() { VU0.code = cpuRegs.code; _vuSUBAy(&VU0); SYNCMSFLAGS(); } +void VSUBAz() { VU0.code = cpuRegs.code; _vuSUBAz(&VU0); SYNCMSFLAGS(); } +void VSUBAw() { VU0.code = cpuRegs.code; _vuSUBAw(&VU0); SYNCMSFLAGS(); } +void VMUL() { VU0.code = cpuRegs.code; _vuMUL(&VU0); SYNCMSFLAGS(); } +void VMULi() { VU0.code = cpuRegs.code; _vuMULi(&VU0); SYNCMSFLAGS(); } +void VMULq() { VU0.code = cpuRegs.code; _vuMULq(&VU0); SYNCMSFLAGS(); } +void VMULx() { VU0.code = cpuRegs.code; _vuMULx(&VU0); SYNCMSFLAGS(); } +void VMULy() { VU0.code = cpuRegs.code; _vuMULy(&VU0); SYNCMSFLAGS(); } +void VMULz() { VU0.code = cpuRegs.code; _vuMULz(&VU0); SYNCMSFLAGS(); } +void VMULw() { VU0.code = cpuRegs.code; _vuMULw(&VU0); SYNCMSFLAGS(); } +void VMULA() { VU0.code = cpuRegs.code; _vuMULA(&VU0); SYNCMSFLAGS(); } +void VMULAi() { VU0.code = cpuRegs.code; _vuMULAi(&VU0); SYNCMSFLAGS(); } +void VMULAq() { VU0.code = cpuRegs.code; _vuMULAq(&VU0); SYNCMSFLAGS(); } +void VMULAx() { VU0.code = cpuRegs.code; _vuMULAx(&VU0); SYNCMSFLAGS(); } +void VMULAy() { VU0.code = cpuRegs.code; _vuMULAy(&VU0); SYNCMSFLAGS(); } +void VMULAz() { VU0.code = cpuRegs.code; _vuMULAz(&VU0); SYNCMSFLAGS(); } +void VMULAw() { VU0.code = cpuRegs.code; _vuMULAw(&VU0); SYNCMSFLAGS(); } +void VMADD() { VU0.code = cpuRegs.code; _vuMADD(&VU0); SYNCMSFLAGS(); } +void VMADDi() { VU0.code = cpuRegs.code; _vuMADDi(&VU0); SYNCMSFLAGS(); } +void VMADDq() { VU0.code = cpuRegs.code; _vuMADDq(&VU0); SYNCMSFLAGS(); } +void VMADDx() { VU0.code = cpuRegs.code; _vuMADDx(&VU0); SYNCMSFLAGS(); } +void VMADDy() { VU0.code = cpuRegs.code; _vuMADDy(&VU0); SYNCMSFLAGS(); } +void VMADDz() { VU0.code = cpuRegs.code; _vuMADDz(&VU0); SYNCMSFLAGS(); } +void VMADDw() { VU0.code = cpuRegs.code; _vuMADDw(&VU0); SYNCMSFLAGS(); } +void VMADDA() { VU0.code = cpuRegs.code; _vuMADDA(&VU0); SYNCMSFLAGS(); } +void VMADDAi() { VU0.code = cpuRegs.code; _vuMADDAi(&VU0); SYNCMSFLAGS(); } +void VMADDAq() { VU0.code = cpuRegs.code; _vuMADDAq(&VU0); SYNCMSFLAGS(); } +void VMADDAx() { VU0.code = cpuRegs.code; _vuMADDAx(&VU0); SYNCMSFLAGS(); } +void VMADDAy() { VU0.code = cpuRegs.code; _vuMADDAy(&VU0); SYNCMSFLAGS(); } +void VMADDAz() { VU0.code = cpuRegs.code; _vuMADDAz(&VU0); SYNCMSFLAGS(); } +void VMADDAw() { VU0.code = cpuRegs.code; _vuMADDAw(&VU0); SYNCMSFLAGS(); } +void VMSUB() { VU0.code = cpuRegs.code; _vuMSUB(&VU0); SYNCMSFLAGS(); } +void VMSUBi() { VU0.code = cpuRegs.code; _vuMSUBi(&VU0); SYNCMSFLAGS(); } +void VMSUBq() { VU0.code = cpuRegs.code; _vuMSUBq(&VU0); SYNCMSFLAGS(); } +void VMSUBx() { VU0.code = cpuRegs.code; _vuMSUBx(&VU0); SYNCMSFLAGS(); } +void VMSUBy() { VU0.code = cpuRegs.code; _vuMSUBy(&VU0); SYNCMSFLAGS(); } +void VMSUBz() { VU0.code = cpuRegs.code; _vuMSUBz(&VU0); SYNCMSFLAGS(); } +void VMSUBw() { VU0.code = cpuRegs.code; _vuMSUBw(&VU0); SYNCMSFLAGS(); } +void VMSUBA() { VU0.code = cpuRegs.code; _vuMSUBA(&VU0); SYNCMSFLAGS(); } +void VMSUBAi() { VU0.code = cpuRegs.code; _vuMSUBAi(&VU0); SYNCMSFLAGS(); } +void VMSUBAq() { VU0.code = cpuRegs.code; _vuMSUBAq(&VU0); SYNCMSFLAGS(); } +void VMSUBAx() { VU0.code = cpuRegs.code; _vuMSUBAx(&VU0); SYNCMSFLAGS(); } +void VMSUBAy() { VU0.code = cpuRegs.code; _vuMSUBAy(&VU0); SYNCMSFLAGS(); } +void VMSUBAz() { VU0.code = cpuRegs.code; _vuMSUBAz(&VU0); SYNCMSFLAGS(); } +void VMSUBAw() { VU0.code = cpuRegs.code; _vuMSUBAw(&VU0); SYNCMSFLAGS(); } +void VMAX() { VU0.code = cpuRegs.code; _vuMAX(&VU0); } +void VMAXi() { VU0.code = cpuRegs.code; _vuMAXi(&VU0); } +void VMAXx() { VU0.code = cpuRegs.code; _vuMAXx(&VU0); } +void VMAXy() { VU0.code = cpuRegs.code; _vuMAXy(&VU0); } +void VMAXz() { VU0.code = cpuRegs.code; _vuMAXz(&VU0); } +void VMAXw() { VU0.code = cpuRegs.code; _vuMAXw(&VU0); } +void VMINI() { VU0.code = cpuRegs.code; _vuMINI(&VU0); } +void VMINIi() { VU0.code = cpuRegs.code; _vuMINIi(&VU0); } +void VMINIx() { VU0.code = cpuRegs.code; _vuMINIx(&VU0); } +void VMINIy() { VU0.code = cpuRegs.code; _vuMINIy(&VU0); } +void VMINIz() { VU0.code = cpuRegs.code; _vuMINIz(&VU0); } +void VMINIw() { VU0.code = cpuRegs.code; _vuMINIw(&VU0); } +void VOPMULA() { VU0.code = cpuRegs.code; _vuOPMULA(&VU0); SYNCMSFLAGS(); } +void VOPMSUB() { VU0.code = cpuRegs.code; _vuOPMSUB(&VU0); SYNCMSFLAGS(); } +void VNOP() { VU0.code = cpuRegs.code; _vuNOP(&VU0); } +void VFTOI0() { VU0.code = cpuRegs.code; _vuFTOI0(&VU0); } +void VFTOI4() { VU0.code = cpuRegs.code; _vuFTOI4(&VU0); } +void VFTOI12() { VU0.code = cpuRegs.code; _vuFTOI12(&VU0); } +void VFTOI15() { VU0.code = cpuRegs.code; _vuFTOI15(&VU0); } +void VITOF0() { VU0.code = cpuRegs.code; _vuITOF0(&VU0); } +void VITOF4() { VU0.code = cpuRegs.code; _vuITOF4(&VU0); } +void VITOF12() { VU0.code = cpuRegs.code; _vuITOF12(&VU0); } +void VITOF15() { VU0.code = cpuRegs.code; _vuITOF15(&VU0); } +void VCLIPw() { VU0.code = cpuRegs.code; _vuCLIP(&VU0); VU0.VI[REG_CLIP_FLAG].UL = VU0.clipflag; } + +void VDIV() { VU0.code = cpuRegs.code; _vuDIV(&VU0); SYNCFDIV(); } +void VSQRT() { VU0.code = cpuRegs.code; _vuSQRT(&VU0); SYNCFDIV(); } +void VRSQRT() { VU0.code = cpuRegs.code; _vuRSQRT(&VU0); SYNCFDIV(); } +void VIADD() { VU0.code = cpuRegs.code; _vuIADD(&VU0); } +void VIADDI() { VU0.code = cpuRegs.code; _vuIADDI(&VU0); } +void VIADDIU() { VU0.code = cpuRegs.code; _vuIADDIU(&VU0); } +void VIAND() { VU0.code = cpuRegs.code; _vuIAND(&VU0); } +void VIOR() { VU0.code = cpuRegs.code; _vuIOR(&VU0); } +void VISUB() { VU0.code = cpuRegs.code; _vuISUB(&VU0); } +void VISUBIU() { VU0.code = cpuRegs.code; _vuISUBIU(&VU0); } +void VMOVE() { VU0.code = cpuRegs.code; _vuMOVE(&VU0); } +void VMFIR() { VU0.code = cpuRegs.code; _vuMFIR(&VU0); } +void VMTIR() { VU0.code = cpuRegs.code; _vuMTIR(&VU0); } +void VMR32() { VU0.code = cpuRegs.code; _vuMR32(&VU0); } +void VLQ() { VU0.code = cpuRegs.code; _vuLQ(&VU0); } +void VLQD() { VU0.code = cpuRegs.code; _vuLQD(&VU0); } +void VLQI() { VU0.code = cpuRegs.code; _vuLQI(&VU0); } +void VSQ() { VU0.code = cpuRegs.code; _vuSQ(&VU0); } +void VSQD() { VU0.code = cpuRegs.code; _vuSQD(&VU0); } +void VSQI() { VU0.code = cpuRegs.code; _vuSQI(&VU0); } +void VILW() { VU0.code = cpuRegs.code; _vuILW(&VU0); } +void VISW() { VU0.code = cpuRegs.code; _vuISW(&VU0); } +void VILWR() { VU0.code = cpuRegs.code; _vuILWR(&VU0); } +void VISWR() { VU0.code = cpuRegs.code; _vuISWR(&VU0); } +void VRINIT() { VU0.code = cpuRegs.code; _vuRINIT(&VU0); } +void VRGET() { VU0.code = cpuRegs.code; _vuRGET(&VU0); } +void VRNEXT() { VU0.code = cpuRegs.code; _vuRNEXT(&VU0); } +void VRXOR() { VU0.code = cpuRegs.code; _vuRXOR(&VU0); } +void VWAITQ() { VU0.code = cpuRegs.code; _vuWAITQ(&VU0); } +void VFSAND() { VU0.code = cpuRegs.code; _vuFSAND(&VU0); } +void VFSEQ() { VU0.code = cpuRegs.code; _vuFSEQ(&VU0); } +void VFSOR() { VU0.code = cpuRegs.code; _vuFSOR(&VU0); } +void VFSSET() { VU0.code = cpuRegs.code; _vuFSSET(&VU0); } +void VFMAND() { VU0.code = cpuRegs.code; _vuFMAND(&VU0); } +void VFMEQ() { VU0.code = cpuRegs.code; _vuFMEQ(&VU0); } +void VFMOR() { VU0.code = cpuRegs.code; _vuFMOR(&VU0); } +void VFCAND() { VU0.code = cpuRegs.code; _vuFCAND(&VU0); } +void VFCEQ() { VU0.code = cpuRegs.code; _vuFCEQ(&VU0); } +void VFCOR() { VU0.code = cpuRegs.code; _vuFCOR(&VU0); } +void VFCSET() { VU0.code = cpuRegs.code; _vuFCSET(&VU0); } +void VFCGET() { VU0.code = cpuRegs.code; _vuFCGET(&VU0); } +void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); } + +#define CP2COND (/*(VU0.VI[REG_VPU_STAT].US[0] & 1) | */((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) + +#define BC2(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC2F() { BC2(== 0);} +void BC2T() { BC2(== 1);} + +#define BC2L(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC2FL() { BC2L(== 0);} +void BC2TL() { BC2L(== 1);} + +void vu0Finish() +{ + if( (VU0.VI[REG_VPU_STAT].UL & 0x1) ) { + int i = 0; + while(i++ < 32) { + Cpu->ExecuteVU0Block(); + if(!(VU0.VI[REG_VPU_STAT].UL & 0x1)) + break; + } + + if(VU0.VI[REG_VPU_STAT].UL & 0x1) { + VU0.VI[REG_VPU_STAT].UL &= ~1; +#ifdef PCSX2_DEVBUILD + SysPrintf("VU0 stall\n"); +#endif + } + } +} + +void VCALLMS() { + + vu0Finish(); + vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void VCALLMSR() { + vu0Finish(); + vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} diff --git a/branches/pcsx2_0.9.2/VU0.h b/branches/pcsx2_0.9.2/VU0.h new file mode 100644 index 0000000..5a8bc6d --- /dev/null +++ b/branches/pcsx2_0.9.2/VU0.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU0_H__ +#define __VU0_H__ + +#include "VU.h" +#define Lcode cpuRegs.code + +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); + +void recResetVU0( void ); + +void vu0Finish(); + +extern VURegs VU0; + +extern char *recMemVU0; /* VU0 blocks */ +extern char *recVU0; /* VU1 mem */ +extern char *recVU0mac; +extern char *recVU0status; +extern char *recVU0clip; +extern char *recVU0Q; +extern char *recVU0cycles; +extern char* recVU0XMMRegs; +extern char *recPtrVU0; + +extern u32 vu0recpcold; + +#endif /* __VU0_H__ */ diff --git a/branches/pcsx2_0.9.2/VU0micro.c b/branches/pcsx2_0.9.2/VU0micro.c new file mode 100644 index 0000000..c130e58 --- /dev/null +++ b/branches/pcsx2_0.9.2/VU0micro.c @@ -0,0 +1,714 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +extern PSMEMORYMAP *memLUT; +#endif + +int vu0Init() +{ +#ifdef WIN32_VIRTUAL_MEM + // unmap all vu0 pages + SysMapUserPhysicalPages(PS2MEM_VU0MICRO, 16, NULL); + + // mirror 4 times + VU0.Micro = PS2MEM_VU0MICRO; + memLUT[0x11000].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11000].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11001].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11001].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11002].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11002].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11003].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11003].aVFNs = &s_psVuMem.aVFNs[0]; + + // since vuregisters are mapped in vumem0, go to diff addr, but mapping to same physical addr + VU0.Mem = VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( VU0.Mem != (void*)0x11000000 ) { + SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError()); + return -1; + } + + memLUT[0x11004].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11004].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11005].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11005].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11006].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11006].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11007].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11007].aVFNs = &s_psVuMem.aVFNs[1]; + + // map only registers + SysMapUserPhysicalPages(VU0.Mem+0x4000, 1, &s_psVuMem.aPFNs[2]); +#else + VU0.Mem = (u8*)_aligned_malloc(0x4000+sizeof(VURegs), 16); // for VU1 + VU0.Micro = (u8*)_aligned_malloc(4*1024, 16); + memset(VU0.Mem, 0, 0x4000+sizeof(VURegs)); + memset(VU0.Micro, 0, 4*1024); +#endif + + +// VU0.VF = (VECTOR*)_aligned_malloc(32*sizeof(VECTOR), 16); +// VU0.VI = (REG_VI*)_aligned_malloc(32*sizeof(REG_VI), 16); +// if (VU0.VF == NULL || VU0.VI == NULL) { +// SysMessage(_("Error allocating memory")); return -1; +// } + + /* this is kinda tricky, maxmem is set to 0x4400 here, + tho it's not 100% accurate, since the mem goes from + 0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs), + i guess it shouldn't be a problem, + at least hope so :) (linuz) + */ + VU0.maxmem = 0x4400-4; + VU0.maxmicro = 4*1024-4; + VU0.vuExec = vu0Exec; + VU0.vifRegs = vif0Regs; + + if( CHECK_VU0REC ) { + SuperVUInit(0); + } + + vu0Reset(); + + return 0; +} + +void vu0Shutdown() +{ + if( CHECK_VU0REC ) { + SuperVUDestroy(0); + } + +#ifdef WIN32_VIRTUAL_MEM + if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL) ) + SysPrintf("err releasing vu0 mem %d\n", GetLastError()); + if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 ) + SysPrintf("err freeing vu0 %d\n", GetLastError()); +#else + _aligned_free(VU0.Mem); + _aligned_free(VU0.Micro); +#endif + + VU0.Mem = NULL; + VU0.Micro = NULL; +// _aligned_free(VU0.VF); VU0.VF = NULL; +// _aligned_free(VU0.VI); VU0.VI = NULL; +} + +void vu0ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0 + VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0 + vif0Regs->stat &= ~4; +} + +void vu0Reset() +{ + memset(&VU0.ACC, 0, sizeof(VECTOR)); + memset(VU0.VF, 0, sizeof(VECTOR)*32); + memset(VU0.VI, 0, sizeof(REG_VI)*32); + VU0.VF[0].f.x = 0.0f; + VU0.VF[0].f.y = 0.0f; + VU0.VF[0].f.z = 0.0f; + VU0.VF[0].f.w = 1.0f; + VU0.VI[0].UL = 0; + memset(VU0.Mem, 0, 4*1024); + memset(VU0.Micro, 0, 4*1024); + + recResetVU0(); +} + +void recResetVU0( void ) +{ + if( CHECK_VU0REC ) { + SuperVUReset(0); + } +} + +void vu0Freeze(gzFile f, int Mode) { + gzfreeze(&VU0.ACC, sizeof(VECTOR)); + gzfreeze(&VU0.code, sizeof(u32)); + gzfreeze(VU0.Mem, 4*1024); + gzfreeze(VU0.Micro, 4*1024); + gzfreeze(VU0.VF, 32*sizeof(VECTOR)); + gzfreeze(VU0.VI, 32*sizeof(REG_VI)); +} + + +void VU0MI_XGKICK() { +} + +void VU0MI_XTOP() { +} + +void vu0ExecMicro(u32 addr) { +#ifdef VUM_LOG + VUM_LOG("vu0ExecMicro %x\n", addr); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x1; + VU0.VI[REG_VPU_STAT].UL&= ~0xAE; + if (addr != -1) VU0.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU0); + Cpu->ExecuteVU0Block(); +} + +void _vu0ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU0); + VU0_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu0ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU0); + VU0_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); +int vu0branch = 0; +void _vu0Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){ + #ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + VU->cycle++; + return; + } + + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { + VU->ebit = 2; + } + if (ptr[1] & 0x20000000) { /* M flag */ + VU->flags|= VUFLAG_MFLAGSET; +// SysPrintf("fixme: M flag set\n"); + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x4) { + VU0.VI[REG_VPU_STAT].UL|= 0x2; + hwIntcIrq(INTC_VU0); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x8) { + VU0.VI[REG_VPU_STAT].UL|= 0x4; + hwIntcIrq(INTC_VU0); + } + } + + VU->code = ptr[1]; + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu0ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + memset(&lregs, 0, sizeof(lregs)); + } else { + VU->code = ptr[0]; + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vu0branch = lregs.pipe == VUPIPE_BRANCH; + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU0.VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu0ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu0ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + + if (!(ptr[1] & 0x80000000)) + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + VU->branch--; + if (VU->branch == 0) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ + vif0Regs->stat&= ~0x4; + } + } +} + +void vu0Exec(VURegs* VU) { +// u32 *ptr; + + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + } else { + _vu0Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU0, VU0); +_vuRegsTables(VU0, VU0regs); + +void VU0unknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU0regsunknown(_VURegsNum *VUregsn) { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0MI_ABS() { _vuABS(&VU0); } +void VU0MI_ADD() { _vuADD(&VU0); } +void VU0MI_ADDi() { _vuADDi(&VU0); } +void VU0MI_ADDq() { _vuADDq(&VU0); } +void VU0MI_ADDx() { _vuADDx(&VU0); } +void VU0MI_ADDy() { _vuADDy(&VU0); } +void VU0MI_ADDz() { _vuADDz(&VU0); } +void VU0MI_ADDw() { _vuADDw(&VU0); } +void VU0MI_ADDA() { _vuADDA(&VU0); } +void VU0MI_ADDAi() { _vuADDAi(&VU0); } +void VU0MI_ADDAq() { _vuADDAq(&VU0); } +void VU0MI_ADDAx() { _vuADDAx(&VU0); } +void VU0MI_ADDAy() { _vuADDAy(&VU0); } +void VU0MI_ADDAz() { _vuADDAz(&VU0); } +void VU0MI_ADDAw() { _vuADDAw(&VU0); } +void VU0MI_SUB() { _vuSUB(&VU0); } +void VU0MI_SUBi() { _vuSUBi(&VU0); } +void VU0MI_SUBq() { _vuSUBq(&VU0); } +void VU0MI_SUBx() { _vuSUBx(&VU0); } +void VU0MI_SUBy() { _vuSUBy(&VU0); } +void VU0MI_SUBz() { _vuSUBz(&VU0); } +void VU0MI_SUBw() { _vuSUBw(&VU0); } +void VU0MI_SUBA() { _vuSUBA(&VU0); } +void VU0MI_SUBAi() { _vuSUBAi(&VU0); } +void VU0MI_SUBAq() { _vuSUBAq(&VU0); } +void VU0MI_SUBAx() { _vuSUBAx(&VU0); } +void VU0MI_SUBAy() { _vuSUBAy(&VU0); } +void VU0MI_SUBAz() { _vuSUBAz(&VU0); } +void VU0MI_SUBAw() { _vuSUBAw(&VU0); } +void VU0MI_MUL() { _vuMUL(&VU0); } +void VU0MI_MULi() { _vuMULi(&VU0); } +void VU0MI_MULq() { _vuMULq(&VU0); } +void VU0MI_MULx() { _vuMULx(&VU0); } +void VU0MI_MULy() { _vuMULy(&VU0); } +void VU0MI_MULz() { _vuMULz(&VU0); } +void VU0MI_MULw() { _vuMULw(&VU0); } +void VU0MI_MULA() { _vuMULA(&VU0); } +void VU0MI_MULAi() { _vuMULAi(&VU0); } +void VU0MI_MULAq() { _vuMULAq(&VU0); } +void VU0MI_MULAx() { _vuMULAx(&VU0); } +void VU0MI_MULAy() { _vuMULAy(&VU0); } +void VU0MI_MULAz() { _vuMULAz(&VU0); } +void VU0MI_MULAw() { _vuMULAw(&VU0); } +void VU0MI_MADD() { _vuMADD(&VU0); } +void VU0MI_MADDi() { _vuMADDi(&VU0); } +void VU0MI_MADDq() { _vuMADDq(&VU0); } +void VU0MI_MADDx() { _vuMADDx(&VU0); } +void VU0MI_MADDy() { _vuMADDy(&VU0); } +void VU0MI_MADDz() { _vuMADDz(&VU0); } +void VU0MI_MADDw() { _vuMADDw(&VU0); } +void VU0MI_MADDA() { _vuMADDA(&VU0); } +void VU0MI_MADDAi() { _vuMADDAi(&VU0); } +void VU0MI_MADDAq() { _vuMADDAq(&VU0); } +void VU0MI_MADDAx() { _vuMADDAx(&VU0); } +void VU0MI_MADDAy() { _vuMADDAy(&VU0); } +void VU0MI_MADDAz() { _vuMADDAz(&VU0); } +void VU0MI_MADDAw() { _vuMADDAw(&VU0); } +void VU0MI_MSUB() { _vuMSUB(&VU0); } +void VU0MI_MSUBi() { _vuMSUBi(&VU0); } +void VU0MI_MSUBq() { _vuMSUBq(&VU0); } +void VU0MI_MSUBx() { _vuMSUBx(&VU0); } +void VU0MI_MSUBy() { _vuMSUBy(&VU0); } +void VU0MI_MSUBz() { _vuMSUBz(&VU0); } +void VU0MI_MSUBw() { _vuMSUBw(&VU0); } +void VU0MI_MSUBA() { _vuMSUBA(&VU0); } +void VU0MI_MSUBAi() { _vuMSUBAi(&VU0); } +void VU0MI_MSUBAq() { _vuMSUBAq(&VU0); } +void VU0MI_MSUBAx() { _vuMSUBAx(&VU0); } +void VU0MI_MSUBAy() { _vuMSUBAy(&VU0); } +void VU0MI_MSUBAz() { _vuMSUBAz(&VU0); } +void VU0MI_MSUBAw() { _vuMSUBAw(&VU0); } +void VU0MI_MAX() { _vuMAX(&VU0); } +void VU0MI_MAXi() { _vuMAXi(&VU0); } +void VU0MI_MAXx() { _vuMAXx(&VU0); } +void VU0MI_MAXy() { _vuMAXy(&VU0); } +void VU0MI_MAXz() { _vuMAXz(&VU0); } +void VU0MI_MAXw() { _vuMAXw(&VU0); } +void VU0MI_MINI() { _vuMINI(&VU0); } +void VU0MI_MINIi() { _vuMINIi(&VU0); } +void VU0MI_MINIx() { _vuMINIx(&VU0); } +void VU0MI_MINIy() { _vuMINIy(&VU0); } +void VU0MI_MINIz() { _vuMINIz(&VU0); } +void VU0MI_MINIw() { _vuMINIw(&VU0); } +void VU0MI_OPMULA() { _vuOPMULA(&VU0); } +void VU0MI_OPMSUB() { _vuOPMSUB(&VU0); } +void VU0MI_NOP() { _vuNOP(&VU0); } +void VU0MI_FTOI0() { _vuFTOI0(&VU0); } +void VU0MI_FTOI4() { _vuFTOI4(&VU0); } +void VU0MI_FTOI12() { _vuFTOI12(&VU0); } +void VU0MI_FTOI15() { _vuFTOI15(&VU0); } +void VU0MI_ITOF0() { _vuITOF0(&VU0); } +void VU0MI_ITOF4() { _vuITOF4(&VU0); } +void VU0MI_ITOF12() { _vuITOF12(&VU0); } +void VU0MI_ITOF15() { _vuITOF15(&VU0); } +void VU0MI_CLIP() { _vuCLIP(&VU0); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0MI_DIV() { _vuDIV(&VU0); } +void VU0MI_SQRT() { _vuSQRT(&VU0); } +void VU0MI_RSQRT() { _vuRSQRT(&VU0); } +void VU0MI_IADD() { _vuIADD(&VU0); } +void VU0MI_IADDI() { _vuIADDI(&VU0); } +void VU0MI_IADDIU() { _vuIADDIU(&VU0); } +void VU0MI_IAND() { _vuIAND(&VU0); } +void VU0MI_IOR() { _vuIOR(&VU0); } +void VU0MI_ISUB() { _vuISUB(&VU0); } +void VU0MI_ISUBIU() { _vuISUBIU(&VU0); } +void VU0MI_MOVE() { _vuMOVE(&VU0); } +void VU0MI_MFIR() { _vuMFIR(&VU0); } +void VU0MI_MTIR() { _vuMTIR(&VU0); } +void VU0MI_MR32() { _vuMR32(&VU0); } +void VU0MI_LQ() { _vuLQ(&VU0); } +void VU0MI_LQD() { _vuLQD(&VU0); } +void VU0MI_LQI() { _vuLQI(&VU0); } +void VU0MI_SQ() { _vuSQ(&VU0); } +void VU0MI_SQD() { _vuSQD(&VU0); } +void VU0MI_SQI() { _vuSQI(&VU0); } +void VU0MI_ILW() { _vuILW(&VU0); } +void VU0MI_ISW() { _vuISW(&VU0); } +void VU0MI_ILWR() { _vuILWR(&VU0); } +void VU0MI_ISWR() { _vuISWR(&VU0); } +void VU0MI_RINIT() { _vuRINIT(&VU0); } +void VU0MI_RGET() { _vuRGET(&VU0); } +void VU0MI_RNEXT() { _vuRNEXT(&VU0); } +void VU0MI_RXOR() { _vuRXOR(&VU0); } +void VU0MI_WAITQ() { _vuWAITQ(&VU0); } +void VU0MI_FSAND() { _vuFSAND(&VU0); } +void VU0MI_FSEQ() { _vuFSEQ(&VU0); } +void VU0MI_FSOR() { _vuFSOR(&VU0); } +void VU0MI_FSSET() { _vuFSSET(&VU0); } +void VU0MI_FMAND() { _vuFMAND(&VU0); } +void VU0MI_FMEQ() { _vuFMEQ(&VU0); } +void VU0MI_FMOR() { _vuFMOR(&VU0); } +void VU0MI_FCAND() { _vuFCAND(&VU0); } +void VU0MI_FCEQ() { _vuFCEQ(&VU0); } +void VU0MI_FCOR() { _vuFCOR(&VU0); } +void VU0MI_FCSET() { _vuFCSET(&VU0); } +void VU0MI_FCGET() { _vuFCGET(&VU0); } +void VU0MI_IBEQ() { _vuIBEQ(&VU0); } +void VU0MI_IBGEZ() { _vuIBGEZ(&VU0); } +void VU0MI_IBGTZ() { _vuIBGTZ(&VU0); } +void VU0MI_IBLTZ() { _vuIBLTZ(&VU0); } +void VU0MI_IBLEZ() { _vuIBLEZ(&VU0); } +void VU0MI_IBNE() { _vuIBNE(&VU0); } +void VU0MI_B() { _vuB(&VU0); } +void VU0MI_BAL() { _vuBAL(&VU0); } +void VU0MI_JR() { _vuJR(&VU0); } +void VU0MI_JALR() { _vuJALR(&VU0); } +void VU0MI_MFP() { _vuMFP(&VU0); } +void VU0MI_WAITP() { _vuWAITP(&VU0); } +void VU0MI_ESADD() { _vuESADD(&VU0); } +void VU0MI_ERSADD() { _vuERSADD(&VU0); } +void VU0MI_ELENG() { _vuELENG(&VU0); } +void VU0MI_ERLENG() { _vuERLENG(&VU0); } +void VU0MI_EATANxy() { _vuEATANxy(&VU0); } +void VU0MI_EATANxz() { _vuEATANxz(&VU0); } +void VU0MI_ESUM() { _vuESUM(&VU0); } +void VU0MI_ERCPR() { _vuERCPR(&VU0); } +void VU0MI_ESQRT() { _vuESQRT(&VU0); } +void VU0MI_ERSQRT() { _vuERSQRT(&VU0); } +void VU0MI_ESIN() { _vuESIN(&VU0); } +void VU0MI_EATAN() { _vuEATAN(&VU0); } +void VU0MI_EEXP() { _vuEEXP(&VU0); } +void VU0MI_XITOP() { _vuXITOP(&VU0); } + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU0, VUregsn); } +void VU0regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU0, VUregsn); } +void VU0regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU0, VUregsn); } +void VU0regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU0, VUregsn); } +void VU0regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU0, VUregsn); } +void VU0regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU0, VUregsn); } +void VU0regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU0, VUregsn); } +void VU0regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU0, VUregsn); } +void VU0regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU0, VUregsn); } +void VU0regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU0, VUregsn); } +void VU0regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU0, VUregsn); } +void VU0regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU0, VUregsn); } +void VU0regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU0, VUregsn); } +void VU0regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU0, VUregsn); } +void VU0regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU0, VUregsn); } +void VU0regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU0, VUregsn); } +void VU0regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU0, VUregsn); } +void VU0regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU0, VUregsn); } +void VU0regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU0, VUregsn); } +void VU0regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU0, VUregsn); } +void VU0regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU0, VUregsn); } +void VU0regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU0, VUregsn); } +void VU0regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU0, VUregsn); } +void VU0regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU0, VUregsn); } +void VU0regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU0, VUregsn); } +void VU0regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU0, VUregsn); } +void VU0regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU0, VUregsn); } +void VU0regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU0, VUregsn); } +void VU0regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU0, VUregsn); } +void VU0regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU0, VUregsn); } +void VU0regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU0, VUregsn); } +void VU0regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU0, VUregsn); } +void VU0regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU0, VUregsn); } +void VU0regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU0, VUregsn); } +void VU0regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU0, VUregsn); } +void VU0regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU0, VUregsn); } +void VU0regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU0, VUregsn); } +void VU0regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU0, VUregsn); } +void VU0regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU0, VUregsn); } +void VU0regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU0, VUregsn); } +void VU0regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU0, VUregsn); } +void VU0regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU0, VUregsn); } +void VU0regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU0, VUregsn); } +void VU0regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU0, VUregsn); } +void VU0regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU0, VUregsn); } +void VU0regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU0, VUregsn); } +void VU0regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU0, VUregsn); } +void VU0regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU0, VUregsn); } +void VU0regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU0, VUregsn); } +void VU0regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU0, VUregsn); } +void VU0regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU0, VUregsn); } +void VU0regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU0, VUregsn); } +void VU0regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU0, VUregsn); } +void VU0regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU0, VUregsn); } +void VU0regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU0, VUregsn); } +void VU0regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU0, VUregsn); } +void VU0regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU0, VUregsn); } +void VU0regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU0, VUregsn); } +void VU0regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU0, VUregsn); } +void VU0regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU0, VUregsn); } +void VU0regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU0, VUregsn); } +void VU0regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU0, VUregsn); } +void VU0regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU0, VUregsn); } +void VU0regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU0, VUregsn); } +void VU0regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU0, VUregsn); } +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU0, VUregsn); } +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU0, VUregsn); } +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU0, VUregsn); } +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU0, VUregsn); } +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU0, VUregsn); } +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU0, VUregsn); } +void VU0regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU0, VUregsn); } +void VU0regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU0, VUregsn); } +void VU0regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU0, VUregsn); } +void VU0regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU0, VUregsn); } +void VU0regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU0, VUregsn); } +void VU0regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU0, VUregsn); } +void VU0regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU0, VUregsn); } +void VU0regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU0, VUregsn); } +void VU0regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU0, VUregsn); } +void VU0regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU0, VUregsn); } +void VU0regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU0, VUregsn); } +void VU0regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU0, VUregsn); } +void VU0regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU0, VUregsn); } +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU0, VUregsn); } +void VU0regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU0, VUregsn); } +void VU0regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU0, VUregsn); } +void VU0regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU0, VUregsn); } +void VU0regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU0, VUregsn); } +void VU0regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU0, VUregsn); } +void VU0regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU0, VUregsn); } +void VU0regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU0, VUregsn); } +void VU0regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU0, VUregsn); } +void VU0regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU0, VUregsn); } +void VU0regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU0, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU0, VUregsn); } +void VU0regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU0, VUregsn); } +void VU0regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU0, VUregsn); } +void VU0regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU0, VUregsn); } +void VU0regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU0, VUregsn); } +void VU0regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU0, VUregsn); } +void VU0regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU0, VUregsn); } +void VU0regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU0, VUregsn); } +void VU0regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU0, VUregsn); } +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU0, VUregsn); } +void VU0regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU0, VUregsn); } +void VU0regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU0, VUregsn); } +void VU0regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU0, VUregsn); } +void VU0regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU0, VUregsn); } +void VU0regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU0, VUregsn); } +void VU0regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU0, VUregsn); } +void VU0regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU0, VUregsn); } +void VU0regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU0, VUregsn); } +void VU0regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU0, VUregsn); } +void VU0regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU0, VUregsn); } +void VU0regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU0, VUregsn); } +void VU0regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU0, VUregsn); } +void VU0regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU0, VUregsn); } +void VU0regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU0, VUregsn); } +void VU0regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU0, VUregsn); } +void VU0regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU0, VUregsn); } +void VU0regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU0, VUregsn); } +void VU0regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU0, VUregsn); } +void VU0regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU0, VUregsn); } +void VU0regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU0, VUregsn); } +void VU0regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU0, VUregsn); } +void VU0regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU0, VUregsn); } +void VU0regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU0, VUregsn); } +void VU0regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU0, VUregsn); } +void VU0regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU0, VUregsn); } +void VU0regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU0, VUregsn); } +void VU0regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU0, VUregsn); } +void VU0regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU0, VUregsn); } +void VU0regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU0, VUregsn); } +void VU0regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU0, VUregsn); } +void VU0regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU0, VUregsn); } +void VU0regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU0, VUregsn); } +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU0, VUregsn); } +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU0, VUregsn); } +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU0, VUregsn); } +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU0, VUregsn); } +void VU0regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU0, VUregsn); } +void VU0regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU0, VUregsn); } +void VU0regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU0, VUregsn); } +void VU0regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU0, VUregsn); } +void VU0regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU0, VUregsn); } +void VU0regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU0, VUregsn); } +void VU0regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU0, VUregsn); } +void VU0regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU0, VUregsn); } +void VU0regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU0, VUregsn); } +void VU0regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU0, VUregsn); } +void VU0regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU0, VUregsn); } +void VU0regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU0, VUregsn); } +void VU0regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU0, VUregsn); } +void VU0regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU0, VUregsn); } +void VU0regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU0, VUregsn); } +void VU0regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU0, VUregsn); } +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU0, VUregsn); } +void VU0regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU0, VUregsn); } +void VU0regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU0, VUregsn); } +void VU0regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU0, VUregsn); } +void VU0regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU0, VUregsn); } +void VU0regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU0, VUregsn); } +void VU0regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU0, VUregsn); } diff --git a/branches/pcsx2_0.9.2/VU1micro.c b/branches/pcsx2_0.9.2/VU1micro.c new file mode 100644 index 0000000..e80bf88 --- /dev/null +++ b/branches/pcsx2_0.9.2/VU1micro.c @@ -0,0 +1,669 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUops.h" +#include "VUflags.h" +#include "ivu1micro.h" + +#include "iVUzerorec.h" + +VURegs* g_pVU1; + +#ifdef WIN32_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +#endif + +#ifdef __MSCW32__ +#pragma warning(disable:4113) +#endif + +int vu1Init() +{ + assert( VU0.Mem != NULL ); + g_pVU1 = (VURegs*)(VU0.Mem + 0x4000); + +#ifdef WIN32_VIRTUAL_MEM + VU1.Mem = PS2MEM_VU1MEM; + VU1.Micro = PS2MEM_VU1MICRO; +#else + VU1.Mem = (u8*)_aligned_malloc(16*1024, 16); + VU1.Micro = (u8*)_aligned_malloc(16*1024, 16); + if (VU1.Mem == NULL || VU1.Micro == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + memset(VU1.Mem, 0,16*1024); + memset(VU1.Micro, 0,16*1024); +#endif + + VU1.maxmem = -1;//16*1024-4; + VU1.maxmicro = 16*1024-4; +// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000); +// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200); + VU1.vuExec = vu1Exec; + VU1.vifRegs = vif1Regs; + + if( CHECK_VU1REC ) { + recVU1Init(); + } + + vu1Reset(); + + return 0; +} + +void vu1Shutdown() { + if( CHECK_VU1REC ) { + recVU1Shutdown(); + } +} + +void vu1ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1 + VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1 + vif1Regs->stat &= ~4; +} + +void vu1Reset() { + memset(&VU1.ACC, 0, sizeof(VECTOR)); + memset(VU1.VF, 0, sizeof(VECTOR)*32); + memset(VU1.VI, 0, sizeof(REG_VI)*32); + VU1.VF[0].f.x = 0.0f; + VU1.VF[0].f.y = 0.0f; + VU1.VF[0].f.z = 0.0f; + VU1.VF[0].f.w = 1.0f; + VU1.VI[0].UL = 0; + memset(VU1.Mem, 0, 16*1024); + memset(VU1.Micro, 0, 16*1024); + + recResetVU1(); +} + +void vu1Freeze(gzFile f, int Mode) { + gzfreeze(&VU1.ACC, sizeof(VECTOR)); + gzfreeze(&VU1.code, sizeof(u32)); + gzfreeze(VU1.Mem, 16*1024); + gzfreeze(VU1.Micro, 16*1024); + gzfreeze(VU1.VF, 32*sizeof(VECTOR)); + gzfreeze(VU1.VI, 32*sizeof(REG_VI)); +} + +static int count; + +void vu1ExecMicro(u32 addr) +{ +#ifdef VUM_LOG + VUM_LOG("vu1ExecMicro %x\n", addr); + VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x100; + VU0.VI[REG_VPU_STAT].UL&= ~0x7E000; + vif1Regs->stat|= 0x4; + if (addr != -1) VU1.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU1); + + FreezeXMMRegs(1); + //do { + Cpu->ExecuteVU1Block(); + //} while(VU0.VI[REG_VPU_STAT].UL & 0x100); + // rec can call vu1ExecMicro + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void _vu1ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU1); + VU1_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu1ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU1); + VU1_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +int vu1branch = 0; + +void _vu1Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU1.VI[REG_TPC].UL >= VU1.maxmicro){ +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { /* E flag */ + VU->ebit = 2; + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x400) { + VU0.VI[REG_VPU_STAT].UL|= 0x200; + hwIntcIrq(INTC_VU1); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x800) { + VU0.VI[REG_VPU_STAT].UL|= 0x400; + hwIntcIrq(INTC_VU1); + } + } + +#ifdef VUM_LOG + if (Log) { + VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)\n", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); + } +#endif + + VU->code = ptr[1]; + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu1ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + } else { + VU->code = ptr[0]; + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vu1branch = lregs.pipe == VUPIPE_BRANCH; + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU->VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu1ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu1ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + if (VU->branch-- == 1) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + vif1Regs->stat&= ~0x4; + } + } +} + +void vu1Exec(VURegs* VU) { + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + } else { + _vu1Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU1, VU1); +_vuRegsTables(VU1, VU1regs); + +void VU1unknown(_VURegsNum *VUregsn) { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU1regsunknown(_VURegsNum *VUregsn) { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1MI_ABS() { _vuABS(&VU1); } +void VU1MI_ADD() { _vuADD(&VU1); } +void VU1MI_ADDi() { _vuADDi(&VU1); } +void VU1MI_ADDq() { _vuADDq(&VU1); } +void VU1MI_ADDx() { _vuADDx(&VU1); } +void VU1MI_ADDy() { _vuADDy(&VU1); } +void VU1MI_ADDz() { _vuADDz(&VU1); } +void VU1MI_ADDw() { _vuADDw(&VU1); } +void VU1MI_ADDA() { _vuADDA(&VU1); } +void VU1MI_ADDAi() { _vuADDAi(&VU1); } +void VU1MI_ADDAq() { _vuADDAq(&VU1); } +void VU1MI_ADDAx() { _vuADDAx(&VU1); } +void VU1MI_ADDAy() { _vuADDAy(&VU1); } +void VU1MI_ADDAz() { _vuADDAz(&VU1); } +void VU1MI_ADDAw() { _vuADDAw(&VU1); } +void VU1MI_SUB() { _vuSUB(&VU1); } +void VU1MI_SUBi() { _vuSUBi(&VU1); } +void VU1MI_SUBq() { _vuSUBq(&VU1); } +void VU1MI_SUBx() { _vuSUBx(&VU1); } +void VU1MI_SUBy() { _vuSUBy(&VU1); } +void VU1MI_SUBz() { _vuSUBz(&VU1); } +void VU1MI_SUBw() { _vuSUBw(&VU1); } +void VU1MI_SUBA() { _vuSUBA(&VU1); } +void VU1MI_SUBAi() { _vuSUBAi(&VU1); } +void VU1MI_SUBAq() { _vuSUBAq(&VU1); } +void VU1MI_SUBAx() { _vuSUBAx(&VU1); } +void VU1MI_SUBAy() { _vuSUBAy(&VU1); } +void VU1MI_SUBAz() { _vuSUBAz(&VU1); } +void VU1MI_SUBAw() { _vuSUBAw(&VU1); } +void VU1MI_MUL() { _vuMUL(&VU1); } +void VU1MI_MULi() { _vuMULi(&VU1); } +void VU1MI_MULq() { _vuMULq(&VU1); } +void VU1MI_MULx() { _vuMULx(&VU1); } +void VU1MI_MULy() { _vuMULy(&VU1); } +void VU1MI_MULz() { _vuMULz(&VU1); } +void VU1MI_MULw() { _vuMULw(&VU1); } +void VU1MI_MULA() { _vuMULA(&VU1); } +void VU1MI_MULAi() { _vuMULAi(&VU1); } +void VU1MI_MULAq() { _vuMULAq(&VU1); } +void VU1MI_MULAx() { _vuMULAx(&VU1); } +void VU1MI_MULAy() { _vuMULAy(&VU1); } +void VU1MI_MULAz() { _vuMULAz(&VU1); } +void VU1MI_MULAw() { _vuMULAw(&VU1); } +void VU1MI_MADD() { _vuMADD(&VU1); } +void VU1MI_MADDi() { _vuMADDi(&VU1); } +void VU1MI_MADDq() { _vuMADDq(&VU1); } +void VU1MI_MADDx() { _vuMADDx(&VU1); } +void VU1MI_MADDy() { _vuMADDy(&VU1); } +void VU1MI_MADDz() { _vuMADDz(&VU1); } +void VU1MI_MADDw() { _vuMADDw(&VU1); } +void VU1MI_MADDA() { _vuMADDA(&VU1); } +void VU1MI_MADDAi() { _vuMADDAi(&VU1); } +void VU1MI_MADDAq() { _vuMADDAq(&VU1); } +void VU1MI_MADDAx() { _vuMADDAx(&VU1); } +void VU1MI_MADDAy() { _vuMADDAy(&VU1); } +void VU1MI_MADDAz() { _vuMADDAz(&VU1); } +void VU1MI_MADDAw() { _vuMADDAw(&VU1); } +void VU1MI_MSUB() { _vuMSUB(&VU1); } +void VU1MI_MSUBi() { _vuMSUBi(&VU1); } +void VU1MI_MSUBq() { _vuMSUBq(&VU1); } +void VU1MI_MSUBx() { _vuMSUBx(&VU1); } +void VU1MI_MSUBy() { _vuMSUBy(&VU1); } +void VU1MI_MSUBz() { _vuMSUBz(&VU1); } +void VU1MI_MSUBw() { _vuMSUBw(&VU1); } +void VU1MI_MSUBA() { _vuMSUBA(&VU1); } +void VU1MI_MSUBAi() { _vuMSUBAi(&VU1); } +void VU1MI_MSUBAq() { _vuMSUBAq(&VU1); } +void VU1MI_MSUBAx() { _vuMSUBAx(&VU1); } +void VU1MI_MSUBAy() { _vuMSUBAy(&VU1); } +void VU1MI_MSUBAz() { _vuMSUBAz(&VU1); } +void VU1MI_MSUBAw() { _vuMSUBAw(&VU1); } +void VU1MI_MAX() { _vuMAX(&VU1); } +void VU1MI_MAXi() { _vuMAXi(&VU1); } +void VU1MI_MAXx() { _vuMAXx(&VU1); } +void VU1MI_MAXy() { _vuMAXy(&VU1); } +void VU1MI_MAXz() { _vuMAXz(&VU1); } +void VU1MI_MAXw() { _vuMAXw(&VU1); } +void VU1MI_MINI() { _vuMINI(&VU1); } +void VU1MI_MINIi() { _vuMINIi(&VU1); } +void VU1MI_MINIx() { _vuMINIx(&VU1); } +void VU1MI_MINIy() { _vuMINIy(&VU1); } +void VU1MI_MINIz() { _vuMINIz(&VU1); } +void VU1MI_MINIw() { _vuMINIw(&VU1); } +void VU1MI_OPMULA() { _vuOPMULA(&VU1); } +void VU1MI_OPMSUB() { _vuOPMSUB(&VU1); } +void VU1MI_NOP() { _vuNOP(&VU1); } +void VU1MI_FTOI0() { _vuFTOI0(&VU1); } +void VU1MI_FTOI4() { _vuFTOI4(&VU1); } +void VU1MI_FTOI12() { _vuFTOI12(&VU1); } +void VU1MI_FTOI15() { _vuFTOI15(&VU1); } +void VU1MI_ITOF0() { _vuITOF0(&VU1); } +void VU1MI_ITOF4() { _vuITOF4(&VU1); } +void VU1MI_ITOF12() { _vuITOF12(&VU1); } +void VU1MI_ITOF15() { _vuITOF15(&VU1); } +void VU1MI_CLIP() { _vuCLIP(&VU1); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1MI_DIV() { _vuDIV(&VU1); } +void VU1MI_SQRT() { _vuSQRT(&VU1); } +void VU1MI_RSQRT() { _vuRSQRT(&VU1); } +void VU1MI_IADD() { _vuIADD(&VU1); } +void VU1MI_IADDI() { _vuIADDI(&VU1); } +void VU1MI_IADDIU() { _vuIADDIU(&VU1); } +void VU1MI_IAND() { _vuIAND(&VU1); } +void VU1MI_IOR() { _vuIOR(&VU1); } +void VU1MI_ISUB() { _vuISUB(&VU1); } +void VU1MI_ISUBIU() { _vuISUBIU(&VU1); } +void VU1MI_MOVE() { _vuMOVE(&VU1); } +void VU1MI_MFIR() { _vuMFIR(&VU1); } +void VU1MI_MTIR() { _vuMTIR(&VU1); } +void VU1MI_MR32() { _vuMR32(&VU1); } +void VU1MI_LQ() { _vuLQ(&VU1); } +void VU1MI_LQD() { _vuLQD(&VU1); } +void VU1MI_LQI() { _vuLQI(&VU1); } +void VU1MI_SQ() { _vuSQ(&VU1); } +void VU1MI_SQD() { _vuSQD(&VU1); } +void VU1MI_SQI() { _vuSQI(&VU1); } +void VU1MI_ILW() { _vuILW(&VU1); } +void VU1MI_ISW() { _vuISW(&VU1); } +void VU1MI_ILWR() { _vuILWR(&VU1); } +void VU1MI_ISWR() { _vuISWR(&VU1); } +void VU1MI_RINIT() { _vuRINIT(&VU1); } +void VU1MI_RGET() { _vuRGET(&VU1); } +void VU1MI_RNEXT() { _vuRNEXT(&VU1); } +void VU1MI_RXOR() { _vuRXOR(&VU1); } +void VU1MI_WAITQ() { _vuWAITQ(&VU1); } +void VU1MI_FSAND() { _vuFSAND(&VU1); } +void VU1MI_FSEQ() { _vuFSEQ(&VU1); } +void VU1MI_FSOR() { _vuFSOR(&VU1); } +void VU1MI_FSSET() { _vuFSSET(&VU1); } +void VU1MI_FMAND() { _vuFMAND(&VU1); } +void VU1MI_FMEQ() { _vuFMEQ(&VU1); } +void VU1MI_FMOR() { _vuFMOR(&VU1); } +void VU1MI_FCAND() { _vuFCAND(&VU1); } +void VU1MI_FCEQ() { _vuFCEQ(&VU1); } +void VU1MI_FCOR() { _vuFCOR(&VU1); } +void VU1MI_FCSET() { _vuFCSET(&VU1); } +void VU1MI_FCGET() { _vuFCGET(&VU1); } +void VU1MI_IBEQ() { _vuIBEQ(&VU1); } +void VU1MI_IBGEZ() { _vuIBGEZ(&VU1); } +void VU1MI_IBGTZ() { _vuIBGTZ(&VU1); } +void VU1MI_IBLTZ() { _vuIBLTZ(&VU1); } +void VU1MI_IBLEZ() { _vuIBLEZ(&VU1); } +void VU1MI_IBNE() { _vuIBNE(&VU1); } +void VU1MI_B() { _vuB(&VU1); } +void VU1MI_BAL() { _vuBAL(&VU1); } +void VU1MI_JR() { _vuJR(&VU1); } +void VU1MI_JALR() { _vuJALR(&VU1); } +void VU1MI_MFP() { _vuMFP(&VU1); } +void VU1MI_WAITP() { _vuWAITP(&VU1); } +void VU1MI_ESADD() { _vuESADD(&VU1); } +void VU1MI_ERSADD() { _vuERSADD(&VU1); } +void VU1MI_ELENG() { _vuELENG(&VU1); } +void VU1MI_ERLENG() { _vuERLENG(&VU1); } +void VU1MI_EATANxy() { _vuEATANxy(&VU1); } +void VU1MI_EATANxz() { _vuEATANxz(&VU1); } +void VU1MI_ESUM() { _vuESUM(&VU1); } +void VU1MI_ERCPR() { _vuERCPR(&VU1); } +void VU1MI_ESQRT() { _vuESQRT(&VU1); } +void VU1MI_ERSQRT() { _vuERSQRT(&VU1); } +void VU1MI_ESIN() { _vuESIN(&VU1); } +void VU1MI_EATAN() { _vuEATAN(&VU1); } +void VU1MI_EEXP() { _vuEEXP(&VU1); } +void VU1MI_XITOP() { _vuXITOP(&VU1); } +void VU1MI_XGKICK() { _vuXGKICK(&VU1); } +void VU1MI_XTOP() { _vuXTOP(&VU1); } + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU1, VUregsn); } +void VU1regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU1, VUregsn); } +void VU1regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU1, VUregsn); } +void VU1regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU1, VUregsn); } +void VU1regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU1, VUregsn); } +void VU1regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU1, VUregsn); } +void VU1regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU1, VUregsn); } +void VU1regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU1, VUregsn); } +void VU1regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU1, VUregsn); } +void VU1regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU1, VUregsn); } +void VU1regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU1, VUregsn); } +void VU1regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU1, VUregsn); } +void VU1regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU1, VUregsn); } +void VU1regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU1, VUregsn); } +void VU1regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU1, VUregsn); } +void VU1regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU1, VUregsn); } +void VU1regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU1, VUregsn); } +void VU1regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU1, VUregsn); } +void VU1regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU1, VUregsn); } +void VU1regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU1, VUregsn); } +void VU1regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU1, VUregsn); } +void VU1regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU1, VUregsn); } +void VU1regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU1, VUregsn); } +void VU1regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU1, VUregsn); } +void VU1regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU1, VUregsn); } +void VU1regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU1, VUregsn); } +void VU1regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU1, VUregsn); } +void VU1regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU1, VUregsn); } +void VU1regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU1, VUregsn); } +void VU1regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU1, VUregsn); } +void VU1regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU1, VUregsn); } +void VU1regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU1, VUregsn); } +void VU1regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU1, VUregsn); } +void VU1regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU1, VUregsn); } +void VU1regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU1, VUregsn); } +void VU1regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU1, VUregsn); } +void VU1regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU1, VUregsn); } +void VU1regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU1, VUregsn); } +void VU1regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU1, VUregsn); } +void VU1regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU1, VUregsn); } +void VU1regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU1, VUregsn); } +void VU1regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU1, VUregsn); } +void VU1regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU1, VUregsn); } +void VU1regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU1, VUregsn); } +void VU1regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU1, VUregsn); } +void VU1regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU1, VUregsn); } +void VU1regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU1, VUregsn); } +void VU1regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU1, VUregsn); } +void VU1regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU1, VUregsn); } +void VU1regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU1, VUregsn); } +void VU1regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU1, VUregsn); } +void VU1regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU1, VUregsn); } +void VU1regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU1, VUregsn); } +void VU1regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU1, VUregsn); } +void VU1regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU1, VUregsn); } +void VU1regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU1, VUregsn); } +void VU1regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU1, VUregsn); } +void VU1regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU1, VUregsn); } +void VU1regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU1, VUregsn); } +void VU1regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU1, VUregsn); } +void VU1regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU1, VUregsn); } +void VU1regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU1, VUregsn); } +void VU1regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU1, VUregsn); } +void VU1regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU1, VUregsn); } +void VU1regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU1, VUregsn); } +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU1, VUregsn); } +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU1, VUregsn); } +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU1, VUregsn); } +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU1, VUregsn); } +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU1, VUregsn); } +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU1, VUregsn); } +void VU1regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU1, VUregsn); } +void VU1regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU1, VUregsn); } +void VU1regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU1, VUregsn); } +void VU1regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU1, VUregsn); } +void VU1regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU1, VUregsn); } +void VU1regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU1, VUregsn); } +void VU1regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU1, VUregsn); } +void VU1regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU1, VUregsn); } +void VU1regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU1, VUregsn); } +void VU1regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU1, VUregsn); } +void VU1regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU1, VUregsn); } +void VU1regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU1, VUregsn); } +void VU1regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU1, VUregsn); } +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU1, VUregsn); } +void VU1regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU1, VUregsn); } +void VU1regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU1, VUregsn); } +void VU1regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU1, VUregsn); } +void VU1regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU1, VUregsn); } +void VU1regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU1, VUregsn); } +void VU1regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU1, VUregsn); } +void VU1regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU1, VUregsn); } +void VU1regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU1, VUregsn); } +void VU1regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU1, VUregsn); } +void VU1regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU1, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU1, VUregsn); } +void VU1regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU1, VUregsn); } +void VU1regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU1, VUregsn); } +void VU1regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU1, VUregsn); } +void VU1regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU1, VUregsn); } +void VU1regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU1, VUregsn); } +void VU1regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU1, VUregsn); } +void VU1regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU1, VUregsn); } +void VU1regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU1, VUregsn); } +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU1, VUregsn); } +void VU1regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU1, VUregsn); } +void VU1regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU1, VUregsn); } +void VU1regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU1, VUregsn); } +void VU1regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU1, VUregsn); } +void VU1regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU1, VUregsn); } +void VU1regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU1, VUregsn); } +void VU1regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU1, VUregsn); } +void VU1regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU1, VUregsn); } +void VU1regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU1, VUregsn); } +void VU1regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU1, VUregsn); } +void VU1regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU1, VUregsn); } +void VU1regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU1, VUregsn); } +void VU1regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU1, VUregsn); } +void VU1regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU1, VUregsn); } +void VU1regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU1, VUregsn); } +void VU1regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU1, VUregsn); } +void VU1regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU1, VUregsn); } +void VU1regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU1, VUregsn); } +void VU1regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU1, VUregsn); } +void VU1regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU1, VUregsn); } +void VU1regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU1, VUregsn); } +void VU1regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU1, VUregsn); } +void VU1regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU1, VUregsn); } +void VU1regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU1, VUregsn); } +void VU1regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU1, VUregsn); } +void VU1regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU1, VUregsn); } +void VU1regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU1, VUregsn); } +void VU1regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU1, VUregsn); } +void VU1regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU1, VUregsn); } +void VU1regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU1, VUregsn); } +void VU1regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU1, VUregsn); } +void VU1regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU1, VUregsn); } +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU1, VUregsn); } +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU1, VUregsn); } +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU1, VUregsn); } +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU1, VUregsn); } +void VU1regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU1, VUregsn); } +void VU1regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU1, VUregsn); } +void VU1regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU1, VUregsn); } +void VU1regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU1, VUregsn); } +void VU1regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU1, VUregsn); } +void VU1regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU1, VUregsn); } +void VU1regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU1, VUregsn); } +void VU1regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU1, VUregsn); } +void VU1regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU1, VUregsn); } +void VU1regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU1, VUregsn); } +void VU1regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU1, VUregsn); } +void VU1regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU1, VUregsn); } +void VU1regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU1, VUregsn); } +void VU1regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU1, VUregsn); } +void VU1regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU1, VUregsn); } +void VU1regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU1, VUregsn); } +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU1, VUregsn); } +void VU1regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU1, VUregsn); } +void VU1regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU1, VUregsn); } +void VU1regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU1, VUregsn); } +void VU1regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU1, VUregsn); } +void VU1regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU1, VUregsn); } +void VU1regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU1, VUregsn); } diff --git a/branches/pcsx2_0.9.2/VUflags.c b/branches/pcsx2_0.9.2/VUflags.c new file mode 100644 index 0000000..5050f46 --- /dev/null +++ b/branches/pcsx2_0.9.2/VUflags.c @@ -0,0 +1,95 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +/*****************************************/ +/* NEW FLAGS */ //By asadr. Thnkx F|RES :p +/*****************************************/ + + +__inline void vuUpdateDI(VURegs * VU) { +// u32 Flag_S = 0; +// u32 Flag_I = 0; +// u32 Flag_D = 0; +// +// /* +// FLAG D - I +// */ +// Flag_I = (VU->statusflag >> 4) & 0x1; +// Flag_D = (VU->statusflag >> 5) & 0x1; +// +// VU->statusflag|= (Flag_I | (VU0.VI[REG_STATUS_FLAG].US[0] >> 4)) << 10; +// VU->statusflag|= (Flag_D | (VU0.VI[REG_STATUS_FLAG].US[0] >> 5)) << 11; +} + +#define VU_MAC_UPDATE(name, shift) \ +u32 name(VURegs * VU, float f) { \ + u32 v = *(u32*)&f; \ + int exp = (v >> 23) & 0xff; \ + u32 s = v & 0x80000000; \ + \ + if (s) VU->macflag |= 0x0010<macflag &= ~(0x0010<macflag = (VU->macflag & ~(0x1100<macflag = (VU->macflag&~(0x1000<macflag = (VU->macflag&~(0x0100<macflag = (VU->macflag & ~(0x1101<macflag&= ~(0x1111<macflag & 0x000F) newflag = 0x1; + if (VU->macflag & 0x00F0) newflag |= 0x2; + if (VU->macflag & 0x0F00) newflag |= 0x4; + if (VU->macflag & 0xF000) newflag |= 0x8; + VU->statusflag = (VU->statusflag&0xc30)|newflag|((VU->statusflag&0xf)<<6); +} diff --git a/branches/pcsx2_0.9.2/VUflags.h b/branches/pcsx2_0.9.2/VUflags.h new file mode 100644 index 0000000..37338a5 --- /dev/null +++ b/branches/pcsx2_0.9.2/VUflags.h @@ -0,0 +1,38 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUFLAGS_H__ +#define __VUFLAGS_H__ + +#include "VU.h" + +void vuUpdateDI(VURegs * VU); +u32 VU_MACx_UPDATE(VURegs * VU, float x); +u32 VU_MACy_UPDATE(VURegs * VU, float y); +u32 VU_MACz_UPDATE(VURegs * VU, float z); +u32 VU_MACw_UPDATE(VURegs * VU, float w); +void VU_MACx_CLEAR(VURegs * VU); +void VU_MACy_CLEAR(VURegs * VU); +void VU_MACz_CLEAR(VURegs * VU); +void VU_MACw_CLEAR(VURegs * VU); +void VU_STAT_UPDATE(VURegs * VU); + + +#endif + + diff --git a/branches/pcsx2_0.9.2/VUmicro.h b/branches/pcsx2_0.9.2/VUmicro.h new file mode 100644 index 0000000..eabb10f --- /dev/null +++ b/branches/pcsx2_0.9.2/VUmicro.h @@ -0,0 +1,1263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUMICRO_H__ +#define __VUMICRO_H__ + +#include "VU.h" + +//both for VU0 VU1 micromode + +extern void (*VU0_LOWER_OPCODE[128])(); +extern void (*VU0_UPPER_OPCODE[64])(); + +extern void (*VU0_UPPER_FD_00_TABLE[32])(); +extern void (*VU0_UPPER_FD_01_TABLE[32])(); +extern void (*VU0_UPPER_FD_10_TABLE[32])(); +extern void (*VU0_UPPER_FD_11_TABLE[32])(); + +extern void (*VU0regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU0regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +extern void (*VU1_LOWER_OPCODE[128])(); +extern void (*VU1_UPPER_OPCODE[64])(); + +extern void (*VU1_UPPER_FD_00_TABLE[32])(); +extern void (*VU1_UPPER_FD_01_TABLE[32])(); +extern void (*VU1_UPPER_FD_10_TABLE[32])(); +extern void (*VU1_UPPER_FD_11_TABLE[32])(); + +extern void (*VU1regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU1regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +// VU0 +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); +void vu0ExecMicro(u32 addr); +void vu0Exec(VURegs* VU); +void vu0Finish(); +void recResetVU0( void ); + +// VU1 +int vu1Init(); +void vu1Reset(); +void vu1ResetRegs(); +void recResetVU1( void ); +void vu1Freeze(gzFile f, int Mode); +void vu1Shutdown(); +void vu1ExecMicro(u32 addr); +void vu1Exec(VURegs* VU); + +void VU0_UPPER_FD_00(); +void VU0_UPPER_FD_01(); +void VU0_UPPER_FD_10(); +void VU0_UPPER_FD_11(); + +void VU0LowerOP(); +void VU0LowerOP_T3_00(); +void VU0LowerOP_T3_01(); +void VU0LowerOP_T3_10(); +void VU0LowerOP_T3_11(); + +void VU0unknown(); + +void VU1_UPPER_FD_00(); +void VU1_UPPER_FD_01(); +void VU1_UPPER_FD_10(); +void VU1_UPPER_FD_11(); + +void VU1LowerOP(); +void VU1LowerOP_T3_00(); +void VU1LowerOP_T3_01(); +void VU1LowerOP_T3_10(); +void VU1LowerOP_T3_11(); + +void VU1unknown(); + +void VU0regs_UPPER_FD_00(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_01(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_10(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_11(_VURegsNum *VUregsn); + +void VU0regsLowerOP(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_00(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_01(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_10(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_11(_VURegsNum *VUregsn); + +void VU0regsunknown(_VURegsNum *VUregsn); + +void VU1regs_UPPER_FD_00(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_01(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_10(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_11(_VURegsNum *VUregsn); + +void VU1regsLowerOP(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_00(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_01(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_10(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_11(_VURegsNum *VUregsn); + +void VU1regsunknown(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void VU0MI_ABS(); +void VU0MI_ADD(); +void VU0MI_ADDi(); +void VU0MI_ADDq(); +void VU0MI_ADDx(); +void VU0MI_ADDy(); +void VU0MI_ADDz(); +void VU0MI_ADDw(); +void VU0MI_ADDA(); +void VU0MI_ADDAi(); +void VU0MI_ADDAq(); +void VU0MI_ADDAx(); +void VU0MI_ADDAy(); +void VU0MI_ADDAz(); +void VU0MI_ADDAw(); +void VU0MI_SUB(); +void VU0MI_SUBi(); +void VU0MI_SUBq(); +void VU0MI_SUBx(); +void VU0MI_SUBy(); +void VU0MI_SUBz(); +void VU0MI_SUBw(); +void VU0MI_SUBA(); +void VU0MI_SUBAi(); +void VU0MI_SUBAq(); +void VU0MI_SUBAx(); +void VU0MI_SUBAy(); +void VU0MI_SUBAz(); +void VU0MI_SUBAw(); +void VU0MI_MUL(); +void VU0MI_MULi(); +void VU0MI_MULq(); +void VU0MI_MULx(); +void VU0MI_MULy(); +void VU0MI_MULz(); +void VU0MI_MULw(); +void VU0MI_MULA(); +void VU0MI_MULAi(); +void VU0MI_MULAq(); +void VU0MI_MULAx(); +void VU0MI_MULAy(); +void VU0MI_MULAz(); +void VU0MI_MULAw(); +void VU0MI_MADD(); +void VU0MI_MADDi(); +void VU0MI_MADDq(); +void VU0MI_MADDx(); +void VU0MI_MADDy(); +void VU0MI_MADDz(); +void VU0MI_MADDw(); +void VU0MI_MADDA(); +void VU0MI_MADDAi(); +void VU0MI_MADDAq(); +void VU0MI_MADDAx(); +void VU0MI_MADDAy(); +void VU0MI_MADDAz(); +void VU0MI_MADDAw(); +void VU0MI_MSUB(); +void VU0MI_MSUBi(); +void VU0MI_MSUBq(); +void VU0MI_MSUBx(); +void VU0MI_MSUBy(); +void VU0MI_MSUBz(); +void VU0MI_MSUBw(); +void VU0MI_MSUBA(); +void VU0MI_MSUBAi(); +void VU0MI_MSUBAq(); +void VU0MI_MSUBAx(); +void VU0MI_MSUBAy(); +void VU0MI_MSUBAz(); +void VU0MI_MSUBAw(); +void VU0MI_MAX(); +void VU0MI_MAXi(); +void VU0MI_MAXx(); +void VU0MI_MAXy(); +void VU0MI_MAXz(); +void VU0MI_MAXw(); +void VU0MI_MINI(); +void VU0MI_MINIi(); +void VU0MI_MINIx(); +void VU0MI_MINIy(); +void VU0MI_MINIz(); +void VU0MI_MINIw(); +void VU0MI_OPMULA(); +void VU0MI_OPMSUB(); +void VU0MI_NOP(); +void VU0MI_FTOI0(); +void VU0MI_FTOI4(); +void VU0MI_FTOI12(); +void VU0MI_FTOI15(); +void VU0MI_ITOF0(); +void VU0MI_ITOF4(); +void VU0MI_ITOF12(); +void VU0MI_ITOF15(); +void VU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0MI_DIV(); +void VU0MI_SQRT(); +void VU0MI_RSQRT(); +void VU0MI_IADD(); +void VU0MI_IADDI(); +void VU0MI_IADDIU(); +void VU0MI_IAND(); +void VU0MI_IOR(); +void VU0MI_ISUB(); +void VU0MI_ISUBIU(); +void VU0MI_MOVE(); +void VU0MI_MFIR(); +void VU0MI_MTIR(); +void VU0MI_MR32(); +void VU0MI_LQ(); +void VU0MI_LQD(); +void VU0MI_LQI(); +void VU0MI_SQ(); +void VU0MI_SQD(); +void VU0MI_SQI(); +void VU0MI_ILW(); +void VU0MI_ISW(); +void VU0MI_ILWR(); +void VU0MI_ISWR(); +void VU0MI_LOI(); +void VU0MI_RINIT(); +void VU0MI_RGET(); +void VU0MI_RNEXT(); +void VU0MI_RXOR(); +void VU0MI_WAITQ(); +void VU0MI_FSAND(); +void VU0MI_FSEQ(); +void VU0MI_FSOR(); +void VU0MI_FSSET(); +void VU0MI_FMAND(); +void VU0MI_FMEQ(); +void VU0MI_FMOR(); +void VU0MI_FCAND(); +void VU0MI_FCEQ(); +void VU0MI_FCOR(); +void VU0MI_FCSET(); +void VU0MI_FCGET(); +void VU0MI_IBEQ(); +void VU0MI_IBGEZ(); +void VU0MI_IBGTZ(); +void VU0MI_IBLEZ(); +void VU0MI_IBLTZ(); +void VU0MI_IBNE(); +void VU0MI_B(); +void VU0MI_BAL(); +void VU0MI_JR(); +void VU0MI_JALR(); +void VU0MI_MFP(); +void VU0MI_WAITP(); +void VU0MI_ESADD(); +void VU0MI_ERSADD(); +void VU0MI_ELENG(); +void VU0MI_ERLENG(); +void VU0MI_EATANxy(); +void VU0MI_EATANxz(); +void VU0MI_ESUM(); +void VU0MI_ERCPR(); +void VU0MI_ESQRT(); +void VU0MI_ERSQRT(); +void VU0MI_ESIN(); +void VU0MI_EATAN(); +void VU0MI_EEXP(); +void VU0MI_XGKICK(); +void VU0MI_XTOP(); +void VU0MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn); +void VU0regsMI_ADD(_VURegsNum *VUregsn); +void VU0regsMI_ADDi(_VURegsNum *VUregsn); +void VU0regsMI_ADDq(_VURegsNum *VUregsn); +void VU0regsMI_ADDx(_VURegsNum *VUregsn); +void VU0regsMI_ADDy(_VURegsNum *VUregsn); +void VU0regsMI_ADDz(_VURegsNum *VUregsn); +void VU0regsMI_ADDw(_VURegsNum *VUregsn); +void VU0regsMI_ADDA(_VURegsNum *VUregsn); +void VU0regsMI_ADDAi(_VURegsNum *VUregsn); +void VU0regsMI_ADDAq(_VURegsNum *VUregsn); +void VU0regsMI_ADDAx(_VURegsNum *VUregsn); +void VU0regsMI_ADDAy(_VURegsNum *VUregsn); +void VU0regsMI_ADDAz(_VURegsNum *VUregsn); +void VU0regsMI_ADDAw(_VURegsNum *VUregsn); +void VU0regsMI_SUB(_VURegsNum *VUregsn); +void VU0regsMI_SUBi(_VURegsNum *VUregsn); +void VU0regsMI_SUBq(_VURegsNum *VUregsn); +void VU0regsMI_SUBx(_VURegsNum *VUregsn); +void VU0regsMI_SUBy(_VURegsNum *VUregsn); +void VU0regsMI_SUBz(_VURegsNum *VUregsn); +void VU0regsMI_SUBw(_VURegsNum *VUregsn); +void VU0regsMI_SUBA(_VURegsNum *VUregsn); +void VU0regsMI_SUBAi(_VURegsNum *VUregsn); +void VU0regsMI_SUBAq(_VURegsNum *VUregsn); +void VU0regsMI_SUBAx(_VURegsNum *VUregsn); +void VU0regsMI_SUBAy(_VURegsNum *VUregsn); +void VU0regsMI_SUBAz(_VURegsNum *VUregsn); +void VU0regsMI_SUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MUL(_VURegsNum *VUregsn); +void VU0regsMI_MULi(_VURegsNum *VUregsn); +void VU0regsMI_MULq(_VURegsNum *VUregsn); +void VU0regsMI_MULx(_VURegsNum *VUregsn); +void VU0regsMI_MULy(_VURegsNum *VUregsn); +void VU0regsMI_MULz(_VURegsNum *VUregsn); +void VU0regsMI_MULw(_VURegsNum *VUregsn); +void VU0regsMI_MULA(_VURegsNum *VUregsn); +void VU0regsMI_MULAi(_VURegsNum *VUregsn); +void VU0regsMI_MULAq(_VURegsNum *VUregsn); +void VU0regsMI_MULAx(_VURegsNum *VUregsn); +void VU0regsMI_MULAy(_VURegsNum *VUregsn); +void VU0regsMI_MULAz(_VURegsNum *VUregsn); +void VU0regsMI_MULAw(_VURegsNum *VUregsn); +void VU0regsMI_MADD(_VURegsNum *VUregsn); +void VU0regsMI_MADDi(_VURegsNum *VUregsn); +void VU0regsMI_MADDq(_VURegsNum *VUregsn); +void VU0regsMI_MADDx(_VURegsNum *VUregsn); +void VU0regsMI_MADDy(_VURegsNum *VUregsn); +void VU0regsMI_MADDz(_VURegsNum *VUregsn); +void VU0regsMI_MADDw(_VURegsNum *VUregsn); +void VU0regsMI_MADDA(_VURegsNum *VUregsn); +void VU0regsMI_MADDAi(_VURegsNum *VUregsn); +void VU0regsMI_MADDAq(_VURegsNum *VUregsn); +void VU0regsMI_MADDAx(_VURegsNum *VUregsn); +void VU0regsMI_MADDAy(_VURegsNum *VUregsn); +void VU0regsMI_MADDAz(_VURegsNum *VUregsn); +void VU0regsMI_MADDAw(_VURegsNum *VUregsn); +void VU0regsMI_MSUB(_VURegsNum *VUregsn); +void VU0regsMI_MSUBi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBw(_VURegsNum *VUregsn); +void VU0regsMI_MSUBA(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MAX(_VURegsNum *VUregsn); +void VU0regsMI_MAXi(_VURegsNum *VUregsn); +void VU0regsMI_MAXx(_VURegsNum *VUregsn); +void VU0regsMI_MAXy(_VURegsNum *VUregsn); +void VU0regsMI_MAXz(_VURegsNum *VUregsn); +void VU0regsMI_MAXw(_VURegsNum *VUregsn); +void VU0regsMI_MINI(_VURegsNum *VUregsn); +void VU0regsMI_MINIi(_VURegsNum *VUregsn); +void VU0regsMI_MINIx(_VURegsNum *VUregsn); +void VU0regsMI_MINIy(_VURegsNum *VUregsn); +void VU0regsMI_MINIz(_VURegsNum *VUregsn); +void VU0regsMI_MINIw(_VURegsNum *VUregsn); +void VU0regsMI_OPMULA(_VURegsNum *VUregsn); +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU0regsMI_NOP(_VURegsNum *VUregsn); +void VU0regsMI_FTOI0(_VURegsNum *VUregsn); +void VU0regsMI_FTOI4(_VURegsNum *VUregsn); +void VU0regsMI_FTOI12(_VURegsNum *VUregsn); +void VU0regsMI_FTOI15(_VURegsNum *VUregsn); +void VU0regsMI_ITOF0(_VURegsNum *VUregsn); +void VU0regsMI_ITOF4(_VURegsNum *VUregsn); +void VU0regsMI_ITOF12(_VURegsNum *VUregsn); +void VU0regsMI_ITOF15(_VURegsNum *VUregsn); +void VU0regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn); +void VU0regsMI_SQRT(_VURegsNum *VUregsn); +void VU0regsMI_RSQRT(_VURegsNum *VUregsn); +void VU0regsMI_IADD(_VURegsNum *VUregsn); +void VU0regsMI_IADDI(_VURegsNum *VUregsn); +void VU0regsMI_IADDIU(_VURegsNum *VUregsn); +void VU0regsMI_IAND(_VURegsNum *VUregsn); +void VU0regsMI_IOR(_VURegsNum *VUregsn); +void VU0regsMI_ISUB(_VURegsNum *VUregsn); +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU0regsMI_MOVE(_VURegsNum *VUregsn); +void VU0regsMI_MFIR(_VURegsNum *VUregsn); +void VU0regsMI_MTIR(_VURegsNum *VUregsn); +void VU0regsMI_MR32(_VURegsNum *VUregsn); +void VU0regsMI_LQ(_VURegsNum *VUregsn); +void VU0regsMI_LQD(_VURegsNum *VUregsn); +void VU0regsMI_LQI(_VURegsNum *VUregsn); +void VU0regsMI_SQ(_VURegsNum *VUregsn); +void VU0regsMI_SQD(_VURegsNum *VUregsn); +void VU0regsMI_SQI(_VURegsNum *VUregsn); +void VU0regsMI_ILW(_VURegsNum *VUregsn); +void VU0regsMI_ISW(_VURegsNum *VUregsn); +void VU0regsMI_ILWR(_VURegsNum *VUregsn); +void VU0regsMI_ISWR(_VURegsNum *VUregsn); +void VU0regsMI_LOI(_VURegsNum *VUregsn); +void VU0regsMI_RINIT(_VURegsNum *VUregsn); +void VU0regsMI_RGET(_VURegsNum *VUregsn); +void VU0regsMI_RNEXT(_VURegsNum *VUregsn); +void VU0regsMI_RXOR(_VURegsNum *VUregsn); +void VU0regsMI_WAITQ(_VURegsNum *VUregsn); +void VU0regsMI_FSAND(_VURegsNum *VUregsn); +void VU0regsMI_FSEQ(_VURegsNum *VUregsn); +void VU0regsMI_FSOR(_VURegsNum *VUregsn); +void VU0regsMI_FSSET(_VURegsNum *VUregsn); +void VU0regsMI_FMAND(_VURegsNum *VUregsn); +void VU0regsMI_FMEQ(_VURegsNum *VUregsn); +void VU0regsMI_FMOR(_VURegsNum *VUregsn); +void VU0regsMI_FCAND(_VURegsNum *VUregsn); +void VU0regsMI_FCEQ(_VURegsNum *VUregsn); +void VU0regsMI_FCOR(_VURegsNum *VUregsn); +void VU0regsMI_FCSET(_VURegsNum *VUregsn); +void VU0regsMI_FCGET(_VURegsNum *VUregsn); +void VU0regsMI_IBEQ(_VURegsNum *VUregsn); +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBNE(_VURegsNum *VUregsn); +void VU0regsMI_B(_VURegsNum *VUregsn); +void VU0regsMI_BAL(_VURegsNum *VUregsn); +void VU0regsMI_JR(_VURegsNum *VUregsn); +void VU0regsMI_JALR(_VURegsNum *VUregsn); +void VU0regsMI_MFP(_VURegsNum *VUregsn); +void VU0regsMI_WAITP(_VURegsNum *VUregsn); +void VU0regsMI_ESADD(_VURegsNum *VUregsn); +void VU0regsMI_ERSADD(_VURegsNum *VUregsn); +void VU0regsMI_ELENG(_VURegsNum *VUregsn); +void VU0regsMI_ERLENG(_VURegsNum *VUregsn); +void VU0regsMI_EATANxy(_VURegsNum *VUregsn); +void VU0regsMI_EATANxz(_VURegsNum *VUregsn); +void VU0regsMI_ESUM(_VURegsNum *VUregsn); +void VU0regsMI_ERCPR(_VURegsNum *VUregsn); +void VU0regsMI_ESQRT(_VURegsNum *VUregsn); +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU0regsMI_ESIN(_VURegsNum *VUregsn); +void VU0regsMI_EATAN(_VURegsNum *VUregsn); +void VU0regsMI_EEXP(_VURegsNum *VUregsn); +void VU0regsMI_XGKICK(_VURegsNum *VUregsn); +void VU0regsMI_XTOP(_VURegsNum *VUregsn); +void VU0regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1MI_ABS(); +void VU1MI_ADD(); +void VU1MI_ADDi(); +void VU1MI_ADDq(); +void VU1MI_ADDx(); +void VU1MI_ADDy(); +void VU1MI_ADDz(); +void VU1MI_ADDw(); +void VU1MI_ADDA(); +void VU1MI_ADDAi(); +void VU1MI_ADDAq(); +void VU1MI_ADDAx(); +void VU1MI_ADDAy(); +void VU1MI_ADDAz(); +void VU1MI_ADDAw(); +void VU1MI_SUB(); +void VU1MI_SUBi(); +void VU1MI_SUBq(); +void VU1MI_SUBx(); +void VU1MI_SUBy(); +void VU1MI_SUBz(); +void VU1MI_SUBw(); +void VU1MI_SUBA(); +void VU1MI_SUBAi(); +void VU1MI_SUBAq(); +void VU1MI_SUBAx(); +void VU1MI_SUBAy(); +void VU1MI_SUBAz(); +void VU1MI_SUBAw(); +void VU1MI_MUL(); +void VU1MI_MULi(); +void VU1MI_MULq(); +void VU1MI_MULx(); +void VU1MI_MULy(); +void VU1MI_MULz(); +void VU1MI_MULw(); +void VU1MI_MULA(); +void VU1MI_MULAi(); +void VU1MI_MULAq(); +void VU1MI_MULAx(); +void VU1MI_MULAy(); +void VU1MI_MULAz(); +void VU1MI_MULAw(); +void VU1MI_MADD(); +void VU1MI_MADDi(); +void VU1MI_MADDq(); +void VU1MI_MADDx(); +void VU1MI_MADDy(); +void VU1MI_MADDz(); +void VU1MI_MADDw(); +void VU1MI_MADDA(); +void VU1MI_MADDAi(); +void VU1MI_MADDAq(); +void VU1MI_MADDAx(); +void VU1MI_MADDAy(); +void VU1MI_MADDAz(); +void VU1MI_MADDAw(); +void VU1MI_MSUB(); +void VU1MI_MSUBi(); +void VU1MI_MSUBq(); +void VU1MI_MSUBx(); +void VU1MI_MSUBy(); +void VU1MI_MSUBz(); +void VU1MI_MSUBw(); +void VU1MI_MSUBA(); +void VU1MI_MSUBAi(); +void VU1MI_MSUBAq(); +void VU1MI_MSUBAx(); +void VU1MI_MSUBAy(); +void VU1MI_MSUBAz(); +void VU1MI_MSUBAw(); +void VU1MI_MAX(); +void VU1MI_MAXi(); +void VU1MI_MAXx(); +void VU1MI_MAXy(); +void VU1MI_MAXz(); +void VU1MI_MAXw(); +void VU1MI_MINI(); +void VU1MI_MINIi(); +void VU1MI_MINIx(); +void VU1MI_MINIy(); +void VU1MI_MINIz(); +void VU1MI_MINIw(); +void VU1MI_OPMULA(); +void VU1MI_OPMSUB(); +void VU1MI_NOP(); +void VU1MI_FTOI0(); +void VU1MI_FTOI4(); +void VU1MI_FTOI12(); +void VU1MI_FTOI15(); +void VU1MI_ITOF0(); +void VU1MI_ITOF4(); +void VU1MI_ITOF12(); +void VU1MI_ITOF15(); +void VU1MI_CLIP(); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1MI_DIV(); +void VU1MI_SQRT(); +void VU1MI_RSQRT(); +void VU1MI_IADD(); +void VU1MI_IADDI(); +void VU1MI_IADDIU(); +void VU1MI_IAND(); +void VU1MI_IOR(); +void VU1MI_ISUB(); +void VU1MI_ISUBIU(); +void VU1MI_MOVE(); +void VU1MI_MFIR(); +void VU1MI_MTIR(); +void VU1MI_MR32(); +void VU1MI_LQ(); +void VU1MI_LQD(); +void VU1MI_LQI(); +void VU1MI_SQ(); +void VU1MI_SQD(); +void VU1MI_SQI(); +void VU1MI_ILW(); +void VU1MI_ISW(); +void VU1MI_ILWR(); +void VU1MI_ISWR(); +void VU1MI_LOI(); +void VU1MI_RINIT(); +void VU1MI_RGET(); +void VU1MI_RNEXT(); +void VU1MI_RXOR(); +void VU1MI_WAITQ(); +void VU1MI_FSAND(); +void VU1MI_FSEQ(); +void VU1MI_FSOR(); +void VU1MI_FSSET(); +void VU1MI_FMAND(); +void VU1MI_FMEQ(); +void VU1MI_FMOR(); +void VU1MI_FCAND(); +void VU1MI_FCEQ(); +void VU1MI_FCOR(); +void VU1MI_FCSET(); +void VU1MI_FCGET(); +void VU1MI_IBEQ(); +void VU1MI_IBGEZ(); +void VU1MI_IBGTZ(); +void VU1MI_IBLTZ(); +void VU1MI_IBLEZ(); +void VU1MI_IBNE(); +void VU1MI_B(); +void VU1MI_BAL(); +void VU1MI_JR(); +void VU1MI_JALR(); +void VU1MI_MFP(); +void VU1MI_WAITP(); +void VU1MI_ESADD(); +void VU1MI_ERSADD(); +void VU1MI_ELENG(); +void VU1MI_ERLENG(); +void VU1MI_EATANxy(); +void VU1MI_EATANxz(); +void VU1MI_ESUM(); +void VU1MI_ERCPR(); +void VU1MI_ESQRT(); +void VU1MI_ERSQRT(); +void VU1MI_ESIN(); +void VU1MI_EATAN(); +void VU1MI_EEXP(); +void VU1MI_XGKICK(); +void VU1MI_XTOP(); +void VU1MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn); +void VU1regsMI_ADD(_VURegsNum *VUregsn); +void VU1regsMI_ADDi(_VURegsNum *VUregsn); +void VU1regsMI_ADDq(_VURegsNum *VUregsn); +void VU1regsMI_ADDx(_VURegsNum *VUregsn); +void VU1regsMI_ADDy(_VURegsNum *VUregsn); +void VU1regsMI_ADDz(_VURegsNum *VUregsn); +void VU1regsMI_ADDw(_VURegsNum *VUregsn); +void VU1regsMI_ADDA(_VURegsNum *VUregsn); +void VU1regsMI_ADDAi(_VURegsNum *VUregsn); +void VU1regsMI_ADDAq(_VURegsNum *VUregsn); +void VU1regsMI_ADDAx(_VURegsNum *VUregsn); +void VU1regsMI_ADDAy(_VURegsNum *VUregsn); +void VU1regsMI_ADDAz(_VURegsNum *VUregsn); +void VU1regsMI_ADDAw(_VURegsNum *VUregsn); +void VU1regsMI_SUB(_VURegsNum *VUregsn); +void VU1regsMI_SUBi(_VURegsNum *VUregsn); +void VU1regsMI_SUBq(_VURegsNum *VUregsn); +void VU1regsMI_SUBx(_VURegsNum *VUregsn); +void VU1regsMI_SUBy(_VURegsNum *VUregsn); +void VU1regsMI_SUBz(_VURegsNum *VUregsn); +void VU1regsMI_SUBw(_VURegsNum *VUregsn); +void VU1regsMI_SUBA(_VURegsNum *VUregsn); +void VU1regsMI_SUBAi(_VURegsNum *VUregsn); +void VU1regsMI_SUBAq(_VURegsNum *VUregsn); +void VU1regsMI_SUBAx(_VURegsNum *VUregsn); +void VU1regsMI_SUBAy(_VURegsNum *VUregsn); +void VU1regsMI_SUBAz(_VURegsNum *VUregsn); +void VU1regsMI_SUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MUL(_VURegsNum *VUregsn); +void VU1regsMI_MULi(_VURegsNum *VUregsn); +void VU1regsMI_MULq(_VURegsNum *VUregsn); +void VU1regsMI_MULx(_VURegsNum *VUregsn); +void VU1regsMI_MULy(_VURegsNum *VUregsn); +void VU1regsMI_MULz(_VURegsNum *VUregsn); +void VU1regsMI_MULw(_VURegsNum *VUregsn); +void VU1regsMI_MULA(_VURegsNum *VUregsn); +void VU1regsMI_MULAi(_VURegsNum *VUregsn); +void VU1regsMI_MULAq(_VURegsNum *VUregsn); +void VU1regsMI_MULAx(_VURegsNum *VUregsn); +void VU1regsMI_MULAy(_VURegsNum *VUregsn); +void VU1regsMI_MULAz(_VURegsNum *VUregsn); +void VU1regsMI_MULAw(_VURegsNum *VUregsn); +void VU1regsMI_MADD(_VURegsNum *VUregsn); +void VU1regsMI_MADDi(_VURegsNum *VUregsn); +void VU1regsMI_MADDq(_VURegsNum *VUregsn); +void VU1regsMI_MADDx(_VURegsNum *VUregsn); +void VU1regsMI_MADDy(_VURegsNum *VUregsn); +void VU1regsMI_MADDz(_VURegsNum *VUregsn); +void VU1regsMI_MADDw(_VURegsNum *VUregsn); +void VU1regsMI_MADDA(_VURegsNum *VUregsn); +void VU1regsMI_MADDAi(_VURegsNum *VUregsn); +void VU1regsMI_MADDAq(_VURegsNum *VUregsn); +void VU1regsMI_MADDAx(_VURegsNum *VUregsn); +void VU1regsMI_MADDAy(_VURegsNum *VUregsn); +void VU1regsMI_MADDAz(_VURegsNum *VUregsn); +void VU1regsMI_MADDAw(_VURegsNum *VUregsn); +void VU1regsMI_MSUB(_VURegsNum *VUregsn); +void VU1regsMI_MSUBi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBw(_VURegsNum *VUregsn); +void VU1regsMI_MSUBA(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MAX(_VURegsNum *VUregsn); +void VU1regsMI_MAXi(_VURegsNum *VUregsn); +void VU1regsMI_MAXx(_VURegsNum *VUregsn); +void VU1regsMI_MAXy(_VURegsNum *VUregsn); +void VU1regsMI_MAXz(_VURegsNum *VUregsn); +void VU1regsMI_MAXw(_VURegsNum *VUregsn); +void VU1regsMI_MINI(_VURegsNum *VUregsn); +void VU1regsMI_MINIi(_VURegsNum *VUregsn); +void VU1regsMI_MINIx(_VURegsNum *VUregsn); +void VU1regsMI_MINIy(_VURegsNum *VUregsn); +void VU1regsMI_MINIz(_VURegsNum *VUregsn); +void VU1regsMI_MINIw(_VURegsNum *VUregsn); +void VU1regsMI_OPMULA(_VURegsNum *VUregsn); +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU1regsMI_NOP(_VURegsNum *VUregsn); +void VU1regsMI_FTOI0(_VURegsNum *VUregsn); +void VU1regsMI_FTOI4(_VURegsNum *VUregsn); +void VU1regsMI_FTOI12(_VURegsNum *VUregsn); +void VU1regsMI_FTOI15(_VURegsNum *VUregsn); +void VU1regsMI_ITOF0(_VURegsNum *VUregsn); +void VU1regsMI_ITOF4(_VURegsNum *VUregsn); +void VU1regsMI_ITOF12(_VURegsNum *VUregsn); +void VU1regsMI_ITOF15(_VURegsNum *VUregsn); +void VU1regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn); +void VU1regsMI_SQRT(_VURegsNum *VUregsn); +void VU1regsMI_RSQRT(_VURegsNum *VUregsn); +void VU1regsMI_IADD(_VURegsNum *VUregsn); +void VU1regsMI_IADDI(_VURegsNum *VUregsn); +void VU1regsMI_IADDIU(_VURegsNum *VUregsn); +void VU1regsMI_IAND(_VURegsNum *VUregsn); +void VU1regsMI_IOR(_VURegsNum *VUregsn); +void VU1regsMI_ISUB(_VURegsNum *VUregsn); +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU1regsMI_MOVE(_VURegsNum *VUregsn); +void VU1regsMI_MFIR(_VURegsNum *VUregsn); +void VU1regsMI_MTIR(_VURegsNum *VUregsn); +void VU1regsMI_MR32(_VURegsNum *VUregsn); +void VU1regsMI_LQ(_VURegsNum *VUregsn); +void VU1regsMI_LQD(_VURegsNum *VUregsn); +void VU1regsMI_LQI(_VURegsNum *VUregsn); +void VU1regsMI_SQ(_VURegsNum *VUregsn); +void VU1regsMI_SQD(_VURegsNum *VUregsn); +void VU1regsMI_SQI(_VURegsNum *VUregsn); +void VU1regsMI_ILW(_VURegsNum *VUregsn); +void VU1regsMI_ISW(_VURegsNum *VUregsn); +void VU1regsMI_ILWR(_VURegsNum *VUregsn); +void VU1regsMI_ISWR(_VURegsNum *VUregsn); +void VU1regsMI_LOI(_VURegsNum *VUregsn); +void VU1regsMI_RINIT(_VURegsNum *VUregsn); +void VU1regsMI_RGET(_VURegsNum *VUregsn); +void VU1regsMI_RNEXT(_VURegsNum *VUregsn); +void VU1regsMI_RXOR(_VURegsNum *VUregsn); +void VU1regsMI_WAITQ(_VURegsNum *VUregsn); +void VU1regsMI_FSAND(_VURegsNum *VUregsn); +void VU1regsMI_FSEQ(_VURegsNum *VUregsn); +void VU1regsMI_FSOR(_VURegsNum *VUregsn); +void VU1regsMI_FSSET(_VURegsNum *VUregsn); +void VU1regsMI_FMAND(_VURegsNum *VUregsn); +void VU1regsMI_FMEQ(_VURegsNum *VUregsn); +void VU1regsMI_FMOR(_VURegsNum *VUregsn); +void VU1regsMI_FCAND(_VURegsNum *VUregsn); +void VU1regsMI_FCEQ(_VURegsNum *VUregsn); +void VU1regsMI_FCOR(_VURegsNum *VUregsn); +void VU1regsMI_FCSET(_VURegsNum *VUregsn); +void VU1regsMI_FCGET(_VURegsNum *VUregsn); +void VU1regsMI_IBEQ(_VURegsNum *VUregsn); +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBNE(_VURegsNum *VUregsn); +void VU1regsMI_B(_VURegsNum *VUregsn); +void VU1regsMI_BAL(_VURegsNum *VUregsn); +void VU1regsMI_JR(_VURegsNum *VUregsn); +void VU1regsMI_JALR(_VURegsNum *VUregsn); +void VU1regsMI_MFP(_VURegsNum *VUregsn); +void VU1regsMI_WAITP(_VURegsNum *VUregsn); +void VU1regsMI_ESADD(_VURegsNum *VUregsn); +void VU1regsMI_ERSADD(_VURegsNum *VUregsn); +void VU1regsMI_ELENG(_VURegsNum *VUregsn); +void VU1regsMI_ERLENG(_VURegsNum *VUregsn); +void VU1regsMI_EATANxy(_VURegsNum *VUregsn); +void VU1regsMI_EATANxz(_VURegsNum *VUregsn); +void VU1regsMI_ESUM(_VURegsNum *VUregsn); +void VU1regsMI_ERCPR(_VURegsNum *VUregsn); +void VU1regsMI_ESQRT(_VURegsNum *VUregsn); +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU1regsMI_ESIN(_VURegsNum *VUregsn); +void VU1regsMI_EATAN(_VURegsNum *VUregsn); +void VU1regsMI_EEXP(_VURegsNum *VUregsn); +void VU1regsMI_XGKICK(_VURegsNum *VUregsn); +void VU1regsMI_XTOP(_VURegsNum *VUregsn); +void VU1regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU Micromode Tables/Opcodes defs macros +*****************************************/ + + +#define _vuTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])() = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])() = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])() = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])() = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])() = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])() = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00() { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](); \ +} \ + \ + void PREFIX##_UPPER_FD_01() { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_10() { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_11() { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP() { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](); \ +} \ + \ + void PREFIX##LowerOP_T3_00() { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_01() { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_10() { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_11() { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](); \ +} + +#define _vuRegsTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_MADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_01(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_10(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_11(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_00(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_01(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_10(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_11(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} + + +#ifdef VUM_LOG + +#define IdebugUPPER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroUF(VU.code, VU.VI[REG_TPC].UL)); } +#define IdebugLOWER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroLF(VU.code, VU.VI[REG_TPC].UL)); } + +#else + +#define IdebugUPPER(VU) +#define IdebugLOWER(VU) + +#endif + +#ifdef VUM_LOG +#define _vuExecMicroDebug(VU) \ + VUM_LOG("_vuExecMicro: %8.8x\n", VU.VI[REG_TPC].UL); +#else +#define _vuExecMicroDebug(VU) +#endif + +#include "VUops.h" + +#endif + diff --git a/branches/pcsx2_0.9.2/VUops.c b/branches/pcsx2_0.9.2/VUops.c new file mode 100644 index 0000000..5017eeb --- /dev/null +++ b/branches/pcsx2_0.9.2/VUops.c @@ -0,0 +1,2959 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" +#include "GS.h" + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU->code>>24) & 0x1) +#define _Y ((VU->code>>23) & 0x1) +#define _Z ((VU->code>>22) & 0x1) +#define _W ((VU->code>>21) & 0x1) + +#define _XYZW ((VU->code>>21) & 0xF) + +#define _Fsf_ ((VU->code >> 21) & 0x03) +#define _Ftf_ ((VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + + +VECTOR RDzero; + +void _vuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } +} + +void _vuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } +#endif + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } +} + +void _vuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing EFU pipe\n"); } +#endif + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } +} + +// called at end of program +void _vuFlushAll(VURegs* VU) +{ + int nRepeat = 1, i; + + do { + nRepeat = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + nRepeat = 1; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } + + if (VU->fdiv.enable ) { + + nRepeat = 1; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { + #ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } + #endif + nRepeat = 1; + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } + } + + if (VU->efu.enable) { + + nRepeat = 1; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { + #ifdef VUM_LOG + // if (Log) { VUM_LOG("flushing EFU pipe\n"); } + #endif + nRepeat = 1; + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } + } + + VU->cycle++; + + } while(nRepeat); +} + +void _vuTestPipes(VURegs * VU) { + _vuFMACflush(VU); + _vuFDIVflush(VU); + _vuEFUflush(VU); +} + +void _vuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + VU->fmac[i].xyzw & xyzw) break; + } + + if (i == 8) return; + + cycle = VU->fmac[i].Cycle - (VU->cycle - VU->fmac[i].sCycle) + 1; // add 1 delay! (fixes segaclassics bad geom) + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; +#ifdef VUM_LOG + if (Log) { VUM_LOG("FMAC[%d] stall %d\n", i, cycle); } +#endif + VU->cycle+= cycle; + _vuTestPipes(VU); +} + +void _vuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { +// SysPrintf("*PCSX2*: error , out of fmacs %d\n", VU->cycle); + } + +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FMAC pipe[%d]; xyzw=%x\n", i, xyzw); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = VU->cycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].reg = reg; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].macflag = VU->macflag; + VU->fmac[i].statusflag = VU->statusflag; + VU->fmac[i].clipflag = VU->clipflag; +} + +void _vuFDIVAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FDIV pipe\n"); } +#endif + VU->fdiv.enable = 1; + VU->fdiv.sCycle = VU->cycle; + VU->fdiv.Cycle = cycles; + VU->fdiv.reg.F = VU->q.F; + VU->fdiv.statusflag = VU->statusflag; +} + +void _vuEFUAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding EFU pipe\n"); } +#endif + VU->efu.enable = 1; + VU->efu.sCycle = VU->cycle; + VU->efu.Cycle = cycles; + VU->efu.reg.F = VU->p.F; +} + +void _vuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (VU->cycle - VU->fdiv.sCycle); +#ifdef VUM_LOG + if (Log) { VUM_LOG("waiting FDIV pipe %d\n", cycle); } +#endif + VU->fdiv.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; +} + +void _vuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (VU->cycle - VU->efu.sCycle); +#ifdef VUM_LOG +// if (Log) { VUM_LOG("waiting EFU pipe %d\n", cycle); } +#endif + VU->efu.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_P].UL = VU->efu.reg.UL; +} + +void _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFread0) { + _vuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _vuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } +} + +void _vuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _vuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { + _vuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _vuFMACAdd(VU, 0, 0); + } +} + +void _vuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushFDIV(VU); +} + +void _vuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_Q)) { + _vuFDIVAdd(VU, VUregsn->cycles); + } +} + + +void _vuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushEFU(VU); +} + +void _vuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_P)) { + _vuEFUAdd(VU, VUregsn->cycles); + } +} + +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + } +} + +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuTestEFUStalls(VU, VUregsn); break; + } +} + +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + } +} + +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuAddEFUStalls(VU, VUregsn); break; + } +} + + +/******************************/ +/* VU Upper instructions */ +/******************************/ +static u32 d; + +static float vuDouble(u32 f) +{ + switch(f & 0x7f800000){ + case 0x0: + f &= 0x80000000; + return *(float*)&f; + break; + case 0x7f800000: + d = (f & 0x80000000)|0x7f7fffff; + return *(float*)&d; + break; + default: + return *(float*)&f; + break; + } +} + +void _vuABS(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X){ VU->VF[_Ft_].f.x = fpufabsf(vuDouble(VU->VF[_Fs_].i.x)); } + if (_Y){ VU->VF[_Ft_].f.y = fpufabsf(vuDouble(VU->VF[_Fs_].i.y)); } + if (_Z){ VU->VF[_Ft_].f.z = fpufabsf(vuDouble(VU->VF[_Fs_].i.z)); } + if (_W){ VU->VF[_Ft_].f.w = fpufabsf(vuDouble(VU->VF[_Fs_].i.w)); } +}/*Reworked from define to function. asadr*/ + + +void _vuADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_I].UL));} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_I].UL));} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_I].UL));} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_I].UL));} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + fty);} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + fty);} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + fty);} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + fty);} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ti); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ti); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ti); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ti); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAq(VURegs * VU) { + float tf = vuDouble(VU->VI[REG_Q].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tf); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tf); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tf); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tf); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + + +void _vuSUBA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuMUL(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave Q reg in ti. asadr */ +void _vuMULAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave X reg in ti. asadr */ +void _vuMULAx(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAy(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAz(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAw(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + + +void _vuMADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +/* No need to presave . asadr */ +void _vuMADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftx)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftx)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftx)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * fty)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * fty)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * fty)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * fty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftz)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftz)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftz)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftw)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftw)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftw)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * ti)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * ti)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * ti)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * ti)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * tq)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * tq)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * tq)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * tq)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 10/05/03 shadow*/ + +void _vuMADDAx(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAy(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAz(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAw(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ti ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ti ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ti ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ti ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tq ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tq ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tq ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tq ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftx ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftx ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftx ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftx ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * fty ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * fty ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * fty ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * fty ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftz ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftz ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftz ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftz ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftw ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftw ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftw ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftw ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAi(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAq(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tx)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tx)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tx)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ty)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ty)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ty)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tz)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tz)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tz)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tw)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tw)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tw)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +u32 _MAX(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? b : a; + } else { // +b + return b; + } + } else { // +a + if (b & 0x80000000) { // -b + return a; + } else { // +b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMAX(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMAXi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMAXx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMAXy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMAXz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMAXw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftw); +} + +u32 _MINI(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? b : a; + } else { // +b + return a; + } + } else { // +a + if (b & 0x80000000) { // -b + return b; + } else { // +b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMINI(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMINIi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMINIx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMINIy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMINIz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMINIw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftw); +} + +void _vuOPMULA(VURegs * VU) { + VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); + VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); + VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuOPMSUB(VURegs * VU) { + VECTOR * dst; + float ftx, fty, ftz; + float fsx, fsy, fsz; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx = vuDouble(VU->VF[_Ft_].i.x); fty = vuDouble(VU->VF[_Ft_].i.y); ftz = vuDouble(VU->VF[_Ft_].i.z); + fsx = vuDouble(VU->VF[_Fs_].i.x); fsy = vuDouble(VU->VF[_Fs_].i.y); fsz = vuDouble(VU->VF[_Fs_].i.z); + dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - fsy * ftz); + dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - fsz * ftx); + dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - fsx * fty); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuNOP(VURegs * VU) { +} + +void _vuFTOI0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)vuDouble(VU->VF[_Fs_].i.x); + if (_Y) VU->VF[_Ft_].SL[1] = (s32)vuDouble(VU->VF[_Fs_].i.y); + if (_Z) VU->VF[_Ft_].SL[2] = (s32)vuDouble(VU->VF[_Fs_].i.z); + if (_W) VU->VF[_Ft_].SL[3] = (s32)vuDouble(VU->VF[_Fs_].i.w); +} + +void _vuFTOI4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int4(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int4(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int4(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int4(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int12(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int12(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int12(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int12(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int15(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int15(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int15(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int15(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuITOF0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = (float)VU->VF[_Fs_].SL[0]; + if (_Y) VU->VF[_Ft_].f.y = (float)VU->VF[_Fs_].SL[1]; + if (_Z) VU->VF[_Ft_].f.z = (float)VU->VF[_Fs_].SL[2]; + if (_W) VU->VF[_Ft_].f.w = (float)VU->VF[_Fs_].SL[3]; +} + +void _vuITOF4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int4_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int4_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int4_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int4_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int12_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int12_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int12_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int12_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int15_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int15_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int15_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int15_to_float(VU->VF[_Fs_].SL[3]); +} + +/* Different type of clipping by presaving w. asadr */ +void _vuCLIP(VURegs * VU) { + float value = fpufabsf(vuDouble(VU->VF[_Ft_].i.w)); + + VU->clipflag <<= 6; + if ( vuDouble(VU->VF[_Fs_].i.x) > +value ) VU->clipflag|= 0x01; + if ( vuDouble(VU->VF[_Fs_].i.x) < -value ) VU->clipflag|= 0x02; + if ( vuDouble(VU->VF[_Fs_].i.y) > +value ) VU->clipflag|= 0x04; + if ( vuDouble(VU->VF[_Fs_].i.y) < -value ) VU->clipflag|= 0x08; + if ( vuDouble(VU->VF[_Fs_].i.z) > +value ) VU->clipflag|= 0x10; + if ( vuDouble(VU->VF[_Fs_].i.z) < -value ) VU->clipflag|= 0x20; + VU->clipflag = VU->clipflag & 0xFFFFFF; + VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; + + +}/*last update 16/07/05 refraction - Needs checking */ + + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuDIV(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft == 0.0) { + if (fs == 0.0) { + VU->statusflag |= 0x10; + } else { + VU->statusflag |= 0x20; + } + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } else { + VU->q.F = fs / ft; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + +void _vuSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + +// _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft < 0.0 ) + VU->statusflag |= 0x10; + VU->q.F = fpusqrtf(fpufabsf(ft)); + VU->q.F = vuDouble(VU->q.UL); +} //last update 15/01/06 zerofrog + + +/* Eminent Bug - Dvisior == 0 Check Missing ( D Flag Not Set ) */ +/* REFIXED....ASADR; rerefixed....zerofrog */ +void _vuRSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + float temp; + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if ( ft == 0.0 ) { + VU->statusflag |= 0x20; + + if( fs != 0 ) { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } + else { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0x80000000; + } else { + VU->q.UL = 0; + } + + VU->statusflag |= 0x10; + } + + } else { + if (ft < 0.0) { + VU->statusflag |= 0x10; + } + + temp = fpusqrtf(fpufabsf(ft)); + VU->q.F = fs / temp; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + + +void _vuIADDI(VURegs * VU) { + s16 imm = ((VU->code >> 6) & 0x1f); + imm = ((imm & 0x10 ? 0xfff0 : 0) | (imm & 0xf)); + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + imm; +}//last checked 17/05/03 shadow NOTE: not quite sure about that + +void _vuIADDIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +}//last checked 17/05/03 shadow + +void _vuIADD(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] + VU->VI[_Ft_].SS[0]; +}//last checked 17/05/03 shadow + +void _vuIAND(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] & VU->VI[_Ft_].US[0]; +}//last checked 17/05/03 shadow + +void _vuIOR(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] | VU->VI[_Ft_].US[0]; +} + +void _vuISUB(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] - VU->VI[_Ft_].SS[0]; +} + +void _vuISUBIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] - (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +} + +void _vuMOVE(VURegs * VU) { + if(_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VF[_Fs_].UL[0]; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VF[_Fs_].UL[1]; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VF[_Fs_].UL[2]; + if (_W) VU->VF[_Ft_].UL[3] = VU->VF[_Fs_].UL[3]; +}//last checked 17/05/03 shadow + +void _vuMFIR(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)VU->VI[_Fs_].SS[0]; + if (_Y) VU->VF[_Ft_].SL[1] = (s32)VU->VI[_Fs_].SS[0]; + if (_Z) VU->VF[_Ft_].SL[2] = (s32)VU->VI[_Fs_].SS[0]; + if (_W) VU->VF[_Ft_].SL[3] = (s32)VU->VI[_Fs_].SS[0]; +} + +// Big bug!!! mov from fs to ft not ft to fs. asadr +void _vuMTIR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = *(u16*)&VU->VF[_Fs_].F[_Fsf_]; +} + +void _vuMR32(VURegs * VU) { + u32 tx; + if (_Ft_ == 0) return; + + tx = VU->VF[_Fs_].i.x; + if (_X) VU->VF[_Ft_].i.x = VU->VF[_Fs_].i.y; + if (_Y) VU->VF[_Ft_].i.y = VU->VF[_Fs_].i.z; + if (_Z) VU->VF[_Ft_].i.z = VU->VF[_Fs_].i.w; + if (_W) VU->VF[_Ft_].i.w = tx; +}//last updated 23/10/03 linuzappz + +void _vuLQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQD( VURegs * VU ) { + u32 addr; + u32 *ptr; + + if (_Fs_ != 0) VU->VI[_Fs_].US[0]--; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQI(VURegs * VU) { + if (_Ft_) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; + } + if (_Fs_ != 0) VU->VI[_Fs_].US[0]++; +} + +/* addr is now signed. Asadr */ +void _vuSQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Ft_].SS[0]) * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQD(VURegs * VU) { + u32 addr; + u32 *ptr; + + if(_Ft_ != 0) VU->VI[_Ft_].US[0]--; + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQI(VURegs * VU) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; + if(_Ft_ != 0) VU->VI[_Ft_].US[0]++; +} + +/* addr now signed. asadr */ +void _vuILW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +void _vuILWR(VURegs * VU) { + u32 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISWR(VURegs * VU) { + u32 addr; + u16 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +/* code contributed by _Riff_ + +The following code implements a Galois form M-series LFSR that can be configured to have a width from 0 to 32. +A Galois field can be represented as G(X) = g_m * X^m + g_(m-1) * X^(m-1) + ... + g_1 * X^1 + g0. +A Galois form M-Series LFSR represents a Galois field where g0 = g_m = 1 and the generated set contains 2^M - 1 values. +In modulo-2 arithmetic, addition is replaced by XOR and multiplication is replaced by AND. +The code is written in such a way that the polynomial lsb (g0) should be set to 0 and g_m is not represented. +As an example for setting the polynomial variable correctly, the 23-bit M-series generating polynomial X^23+X^14 + would be specified as (1 << 14). +*/ + + +//The two-tap 23 stage M-series polynomials are x23+x18 and x23+x14 ((1 << 18) and (1 << 14), respectively). +//The reverse sequences can be generated by x23+x(23-18) and x23+x(23-14) ((1 << 9) and (1 << 5), respectively) +u32 poly = 1 << 5; + +void SetPoly(u32 newPoly) { + poly = poly & ~1; +} + +void AdvanceLFSR(VURegs * VU) { + // code from www.project-fao.org + int x = (VU->VI[REG_R].UL >> 4) & 1; + int y = (VU->VI[REG_R].UL >> 22) & 1; + VU->VI[REG_R].UL <<= 1; + VU->VI[REG_R].UL ^= x ^ y; + VU->VI[REG_R].UL = (VU->VI[REG_R].UL&0x7fffff)|0x3f800000; +} +// old +// u32 lfsr = VU->VI[REG_R].UL & 0x007FFFFF; +// u32 oldlfsr = lfsr; +// lfsr <<= 1; +// if (oldlfsr & 0x00400000) { +// lfsr ^= poly; +// lfsr |= 1; +// } +// +// VU->VI[REG_R].UL = 0x3F800000 | (lfsr & 0x007FFFFF); + +void _vuRINIT(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | (VU->VF[_Fs_].UL[_Fsf_] & 0x007FFFFF); +} + +void _vuRGET(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRNEXT(VURegs * VU) { + if (_Ft_ == 0) return; + AdvanceLFSR(VU); + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRXOR(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | ((VU->VI[REG_R].UL ^ VU->VF[_Fs_].UL[_Fsf_]) & 0x007FFFFF); +} + +void _vuWAITQ(VURegs * VU) { +} + +void _vuFSAND(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) & imm; +} + +void _vuFSEQ(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + if((VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) == imm) VU->VI[_Ft_].US[0] = 1; + else VU->VI[_Ft_].US[0] = 0; +} + +void _vuFSOR(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) | imm; +} + +void _vuFSSET(VURegs * VU) { + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + VU->statusflag = (imm & 0xFC0) | (VU->VI[REG_STATUS_FLAG].US[0] & 0x3F); +} + +void _vuFMAND(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[_Fs_].US[0] & (VU->VI[REG_MAC_FLAG].UL & 0xFFFF); +} + +void _vuFMEQ(VURegs * VU) { + if(_Ft_ == 0) return; + if((VU->VI[REG_MAC_FLAG].UL & 0xFFFF) == VU->VI[_Fs_].US[0]){ + VU->VI[_Ft_].US[0] =1;} else { VU->VI[_Ft_].US[0] =0; } +} + +void _vuFMOR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_MAC_FLAG].UL & 0xFFFF) | VU->VI[_Fs_].US[0]; +} + +void _vuFCAND(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) & (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCEQ(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) == (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCOR(VURegs * VU) { + u32 hold = (VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) | ( VU->code & 0xFFFFFF); + if(hold == 0xFFFFFF) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCSET(VURegs * VU) { + VU->clipflag = (u32) (VU->code & 0xFFFFFF); + VU->VI[REG_CLIP_FLAG].UL = (u32) (VU->code & 0xFFFFFF); +} + +void _vuFCGET(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[REG_CLIP_FLAG].UL & 0x0FFF; +} + +s32 _branchAddr(VURegs * VU) { + s32 bpc = VU->VI[REG_TPC].SL + _Imm11_ * 8; + if (bpc < 0) { + bpc = VU->VI[REG_TPC].SL + _UImm11_ * 8; + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void _setBranch(VURegs * VU, u32 bpc) { + VU->branch = 2; + VU->branchpc = bpc; +// VU->vuExec(VU); +// VU->VI[REG_TPC].UL = bpc; +} + +void _vuIBEQ(VURegs * VU) { + if (VU->VI[_Ft_].US[0] == VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] >= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] > 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] <= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] < 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBNE(VURegs * VU) { + if (VU->VI[_Ft_].US[0] != VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuB(VURegs * VU) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); +} + +void _vuBAL(VURegs * VU) { + s32 bpc = _branchAddr(VU); + + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuJR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + _setBranch(VU, bpc); +} + +void _vuJALR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuMFP(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].i.x = VU->VI[REG_P].UL; + if (_Y) VU->VF[_Ft_].i.y = VU->VI[REG_P].UL; + if (_Z) VU->VF[_Ft_].i.z = VU->VI[REG_P].UL; + if (_W) VU->VF[_Ft_].i.w = VU->VI[REG_P].UL; +} + +void _vuWAITP(VURegs * VU) { +} + +void _vuESADD(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + VU->p.F = p; +} + +void _vuERSADD(VURegs * VU) { + float p = (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x)) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y)) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z)); + if (p != 0.0) + p = 1.0f / p; + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to value being -ve for sqrt *asadr */ +void _vuELENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if(p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERLENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if (p >= 0) { + p = fpusqrtf(p); + if (p != 0) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxy(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.y), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxz(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.z), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +void _vuESUM(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Fs_].i.w); + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERCPR(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p != 0){ + p = 1.0 / p; + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to Value being -ve for sqrt *asadr */ +void _vuESQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERSQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0) { + p = fpusqrtf(p); + if (p) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +void _vuESIN(VURegs * VU) { + float p = fpusinf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEATAN(VURegs * VU) { + float p = fpuatanf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEEXP(VURegs * VU) { + float p = fpuexpf(-(vuDouble(VU->VF[_Fs_].UL[_Fsf_]))); + VU->p.F = p; +} + +void _vuXITOP(VURegs * VU) { + if (_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->vifRegs->itop; +} + +//extern u32 vudump; +//static void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 56 ) { +// __Log("xgkick %d\n", scount); +// vudump |= 8; +// } +//} + +void _vuXGKICK(VURegs * VU) +{ + // flush all pipelines first (in the right order) + _vuFlushAll(VU); + //countfn(); + GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); +} + +void _vuXTOP(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (u16)VU->vifRegs->top; +} + +#define GET_VF0_FLAG(reg) (((reg)==0)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_I)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_Q)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_I)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_Q)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Ft_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw = 0xff; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0); \ +} + +#define VUREGS_IDISIT(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Fd_; \ + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); \ +} + +#define VUREGS_ITIS(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Ft_; \ + VUregsn->VIread = 1 << _Fs_; \ +} + +#define VUREGS_PFS(OP, _cycles) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_EFU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << REG_P; \ + VUregsn->VIread = GET_VF0_FLAG(_Fs_); \ + VUregsn->cycles = _cycles; \ +} + + + +VUREGS_FTFS(ABS); + +VUREGS_FDFSFT(ADD, 0); +VUREGS_FDFSI(ADDi, 0); +VUREGS_FDFSQ(ADDq, 0); +VUREGS_FDFSFTx(ADDx, 0); +VUREGS_FDFSFTy(ADDy, 0); +VUREGS_FDFSFTz(ADDz, 0); +VUREGS_FDFSFTw(ADDw, 0); + +VUREGS_ACCFSFT(ADDA, 0); +VUREGS_ACCFSI(ADDAi, 0); +VUREGS_ACCFSQ(ADDAq, 0); +VUREGS_ACCFSFTx(ADDAx, 0); +VUREGS_ACCFSFTy(ADDAy, 0); +VUREGS_ACCFSFTz(ADDAz, 0); +VUREGS_ACCFSFTw(ADDAw, 0); + +VUREGS_FDFSFT(SUB, 0); +VUREGS_FDFSI(SUBi, 0); +VUREGS_FDFSQ(SUBq, 0); +VUREGS_FDFSFTx(SUBx, 0); +VUREGS_FDFSFTy(SUBy, 0); +VUREGS_FDFSFTz(SUBz, 0); +VUREGS_FDFSFTw(SUBw, 0); + +VUREGS_ACCFSFT(SUBA, 0); +VUREGS_ACCFSI(SUBAi, 0); +VUREGS_ACCFSQ(SUBAq, 0); +VUREGS_ACCFSFTx(SUBAx, 0); +VUREGS_ACCFSFTy(SUBAy, 0); +VUREGS_ACCFSFTz(SUBAz, 0); +VUREGS_ACCFSFTw(SUBAw, 0); + +#define VUREGS_FDFSFTxyzw_MUL(OP, ACC, xyzw) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + if( _Ft_ == 0 && xyzw > 1 && _XYZW == 0xf ) { /* resetting to 0 */ \ + VUregsn->pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = (ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = GET_VF0_FLAG(_Fs_)|((ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 0; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_NONE; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_FTFS(FTOI0); +VUREGS_FTFS(FTOI4); +VUREGS_FTFS(FTOI12); +VUREGS_FTFS(FTOI15); +VUREGS_FTFS(ITOF0); +VUREGS_FTFS(ITOF4); +VUREGS_FTFS(ITOF12); +VUREGS_FTFS(ITOF15); + +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0x1; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1 << REG_CLIP_FLAG); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFr0xyzw = 0; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw = 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 12; +} + +VUREGS_ITIS(IADDI); +VUREGS_ITIS(IADDIU); +VUREGS_IDISIT(IADD); +VUREGS_IDISIT(IAND); +VUREGS_IDISIT(IOR); +VUREGS_IDISIT(ISUB); +VUREGS_ITIS(ISUBIU); + +VUREGS_FTFS(MOVE); + +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +VUREGS_FTFS(MR32); + +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = (1 << _Ft_); + VUregsn->VIread = (1 << _Fs_); +} + +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = (1 << REG_R)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_STATUS_FLAG; + VUregsn->VIread = 0;//1 << REG_STATUS_FLAG; this kills speed +} + +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = 0; +} + +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_P; +} + +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_EFU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_PFS(ESADD, 10); +VUREGS_PFS(ERSADD, 17); +VUREGS_PFS(ELENG, 17); +VUREGS_PFS(ERLENG, 23); +VUREGS_PFS(EATANxy, 53); +VUREGS_PFS(EATANxz, 53); +VUREGS_PFS(ESUM, 11); +VUREGS_PFS(ERCPR, 11); +VUREGS_PFS(ESQRT, 11); +VUREGS_PFS(ERSQRT, 17); +VUREGS_PFS(ESIN, 28); +VUREGS_PFS(EATAN, 53); +VUREGS_PFS(EEXP, 43); + +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_XGKICK; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} diff --git a/branches/pcsx2_0.9.2/VUops.h b/branches/pcsx2_0.9.2/VUops.h new file mode 100644 index 0000000..0b4a0f9 --- /dev/null +++ b/branches/pcsx2_0.9.2/VUops.h @@ -0,0 +1,393 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU1OPS_H__ +#define __VU1OPS_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include "VU.h" + +#define float_to_int4(x) (s32)((float)x * (1.0f / 0.0625f)) +#define float_to_int12(x) (s32)((float)x * (1.0f / 0.000244140625f)) +#define float_to_int15(x) (s32)((float)x * (1.0f / 0.000030517578125)) + +#define int4_to_float(x) (float)((float)x * 0.0625f) +#define int12_to_float(x) (float)((float)x * 0.000244140625f) +#define int15_to_float(x) (float)((float)x * 0.000030517578125) + +#define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) + +void _vuSetCycleFlags(VURegs * VU); +void _vuFlushFDIV(VURegs * VU); +void _vuFlushEFU(VURegs * VU); +void _vuTestPipes(VURegs * VU); +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuABS(VURegs * VU); +void _vuADD(VURegs * VU); +void _vuADDi(VURegs * VU); +void _vuADDq(VURegs * VU); +void _vuADDx(VURegs * VU); +void _vuADDy(VURegs * VU); +void _vuADDz(VURegs * VU); +void _vuADDw(VURegs * VU); +void _vuADDA(VURegs * VU); +void _vuADDAi(VURegs * VU); +void _vuADDAq(VURegs * VU); +void _vuADDAx(VURegs * VU); +void _vuADDAy(VURegs * VU); +void _vuADDAz(VURegs * VU); +void _vuADDAw(VURegs * VU); +void _vuSUB(VURegs * VU); +void _vuSUBi(VURegs * VU); +void _vuSUBq(VURegs * VU); +void _vuSUBx(VURegs * VU); +void _vuSUBy(VURegs * VU); +void _vuSUBz(VURegs * VU); +void _vuSUBw(VURegs * VU); +void _vuSUBA(VURegs * VU); +void _vuSUBAi(VURegs * VU); +void _vuSUBAq(VURegs * VU); +void _vuSUBAx(VURegs * VU); +void _vuSUBAy(VURegs * VU); +void _vuSUBAz(VURegs * VU); +void _vuSUBAw(VURegs * VU); +void _vuMUL(VURegs * VU); +void _vuMULi(VURegs * VU); +void _vuMULq(VURegs * VU); +void _vuMULx(VURegs * VU); +void _vuMULy(VURegs * VU); +void _vuMULz(VURegs * VU); +void _vuMULw(VURegs * VU); +void _vuMULA(VURegs * VU); +void _vuMULAi(VURegs * VU); +void _vuMULAq(VURegs * VU); +void _vuMULAx(VURegs * VU); +void _vuMULAy(VURegs * VU); +void _vuMULAz(VURegs * VU); +void _vuMULAw(VURegs * VU); +void _vuMADD(VURegs * VU) ; +void _vuMADDi(VURegs * VU); +void _vuMADDq(VURegs * VU); +void _vuMADDx(VURegs * VU); +void _vuMADDy(VURegs * VU); +void _vuMADDz(VURegs * VU); +void _vuMADDw(VURegs * VU); +void _vuMADDA(VURegs * VU); +void _vuMADDAi(VURegs * VU); +void _vuMADDAq(VURegs * VU); +void _vuMADDAx(VURegs * VU); +void _vuMADDAy(VURegs * VU); +void _vuMADDAz(VURegs * VU); +void _vuMADDAw(VURegs * VU); +void _vuMSUB(VURegs * VU); +void _vuMSUBi(VURegs * VU); +void _vuMSUBq(VURegs * VU); +void _vuMSUBx(VURegs * VU); +void _vuMSUBy(VURegs * VU); +void _vuMSUBz(VURegs * VU) ; +void _vuMSUBw(VURegs * VU) ; +void _vuMSUBA(VURegs * VU); +void _vuMSUBAi(VURegs * VU); +void _vuMSUBAq(VURegs * VU); +void _vuMSUBAx(VURegs * VU); +void _vuMSUBAy(VURegs * VU); +void _vuMSUBAz(VURegs * VU); +void _vuMSUBAw(VURegs * VU); +void _vuMAX(VURegs * VU); +void _vuMAXi(VURegs * VU); +void _vuMAXx(VURegs * VU); +void _vuMAXy(VURegs * VU); +void _vuMAXz(VURegs * VU); +void _vuMAXw(VURegs * VU); +void _vuMINI(VURegs * VU); +void _vuMINIi(VURegs * VU); +void _vuMINIx(VURegs * VU); +void _vuMINIy(VURegs * VU); +void _vuMINIz(VURegs * VU); +void _vuMINIw(VURegs * VU); +void _vuOPMULA(VURegs * VU); +void _vuOPMSUB(VURegs * VU); +void _vuNOP(VURegs * VU); +void _vuFTOI0(VURegs * VU); +void _vuFTOI4(VURegs * VU); +void _vuFTOI12(VURegs * VU); +void _vuFTOI15(VURegs * VU); +void _vuITOF0(VURegs * VU) ; +void _vuITOF4(VURegs * VU) ; +void _vuITOF12(VURegs * VU); +void _vuITOF15(VURegs * VU); +void _vuCLIP(VURegs * VU); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuDIV(VURegs * VU); +void _vuSQRT(VURegs * VU); +void _vuRSQRT(VURegs * VU); +void _vuIADDI(VURegs * VU); +void _vuIADDIU(VURegs * VU); +void _vuIADD(VURegs * VU); +void _vuIAND(VURegs * VU); +void _vuIOR(VURegs * VU); +void _vuISUB(VURegs * VU); +void _vuISUBIU(VURegs * VU); +void _vuMOVE(VURegs * VU); +void _vuMFIR(VURegs * VU); +void _vuMTIR(VURegs * VU); +void _vuMR32(VURegs * VU); +void _vuLQ(VURegs * VU) ; +void _vuLQD(VURegs * VU); +void _vuLQI(VURegs * VU); +void _vuSQ(VURegs * VU); +void _vuSQD(VURegs * VU); +void _vuSQI(VURegs * VU); +void _vuILW(VURegs * VU); +void _vuISW(VURegs * VU); +void _vuILWR(VURegs * VU); +void _vuISWR(VURegs * VU); +void _vuLOI(VURegs * VU); +void _vuRINIT(VURegs * VU); +void _vuRGET(VURegs * VU); +void _vuRNEXT(VURegs * VU); +void _vuRXOR(VURegs * VU); +void _vuWAITQ(VURegs * VU); +void _vuFSAND(VURegs * VU); +void _vuFSEQ(VURegs * VU); +void _vuFSOR(VURegs * VU); +void _vuFSSET(VURegs * VU); +void _vuFMAND(VURegs * VU); +void _vuFMEQ(VURegs * VU); +void _vuFMOR(VURegs * VU); +void _vuFCAND(VURegs * VU); +void _vuFCEQ(VURegs * VU); +void _vuFCOR(VURegs * VU); +void _vuFCSET(VURegs * VU); +void _vuFCGET(VURegs * VU); +void _vuIBEQ(VURegs * VU); +void _vuIBGEZ(VURegs * VU); +void _vuIBGTZ(VURegs * VU); +void _vuIBLEZ(VURegs * VU); +void _vuIBLTZ(VURegs * VU); +void _vuIBNE(VURegs * VU); +void _vuB(VURegs * VU); +void _vuBAL(VURegs * VU); +void _vuJR(VURegs * VU); +void _vuJALR(VURegs * VU); +void _vuMFP(VURegs * VU); +void _vuWAITP(VURegs * VU); +void _vuESADD(VURegs * VU); +void _vuERSADD(VURegs * VU); +void _vuELENG(VURegs * VU); +void _vuERLENG(VURegs * VU); +void _vuEATANxy(VURegs * VU); +void _vuEATANxz(VURegs * VU); +void _vuESUM(VURegs * VU); +void _vuERCPR(VURegs * VU); +void _vuESQRT(VURegs * VU); +void _vuERSQRT(VURegs * VU); +void _vuESIN(VURegs * VU); +void _vuEATAN(VURegs * VU); +void _vuEEXP(VURegs * VU); +void _vuXITOP(VURegs * VU); +void _vuXGKICK(VURegs * VU); +void _vuXTOP(VURegs * VU); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuRegsABS(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMUL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAX(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsNOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUBIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMOVE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLOI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsELENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERLENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESUM(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERCPR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESIN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATAN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEEXP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn); + +#endif diff --git a/branches/pcsx2_0.9.2/Vif.c b/branches/pcsx2_0.9.2/Vif.c new file mode 100644 index 0000000..8281075 --- /dev/null +++ b/branches/pcsx2_0.9.2/Vif.c @@ -0,0 +1,989 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +VIFregisters *_vifRegs; +u32* _vifMaskRegs = NULL; +PCSX2_ALIGNED16(u32 g_vifRow0[4]); +PCSX2_ALIGNED16(u32 g_vifCol0[4]); +PCSX2_ALIGNED16(u32 g_vifRow1[4]); +PCSX2_ALIGNED16(u32 g_vifCol1[4]); +u32* _vifRow = NULL; + +vifStruct *_vif; + +static int n; +static int i; + +__inline static int _limit( int a, int max ) +{ + return ( a > max ? max : a ); +} + +#define _UNPACKpart( offnum, func ) \ + if ( ( size > 0 ) && ( _vifRegs->offset == offnum ) ) { \ + func; \ + size--; \ + _vifRegs->offset++; \ + } + +#define _UNPACKpart_nosize( offnum, func ) \ + if ( ( _vifRegs->offset == offnum ) ) { \ + func; \ + _vifRegs->offset++; \ + } + +static void _writeX( u32 *dest, u32 data ) +{ + //int n; + + switch ( _vif->cl ) { + case 0: n = 0; break; + case 1: n = 8; break; + case 2: n = 16; break; + default: n = 24; break; + } +/*#ifdef VIF_LOG + VIF_LOG("_writeX %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r0; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +/*#ifdef VIF_LOG + VIF_LOG("_writeX-done : Data %x : Row %x\n", *dest, _vifRegs->r0); +#endif*/ +} + +static void _writeY( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 2; break; + case 1: n = 10; break; + case 2: n = 18; break; + default: n = 26; break; + } +/*#ifdef VIF_LOG + VIF_LOG("_writeY %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Y!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r1; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +/*#ifdef VIF_LOG + VIF_LOG("_writeY-done : Data %x : Row %x\n", *dest, _vifRegs->r1); +#endif*/ +} + +static void _writeZ( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 4; break; + case 1: n = 12; break; + case 2: n = 20; break; + default: n = 28; break; + } +/*#ifdef VIF_LOG + VIF_LOG("_writeZ %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Z!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r2; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void _writeW( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 6; break; + case 1: n = 14; break; + case 2: n = 22; break; + default: n = 30; break; + } +/*#ifdef VIF_LOG + VIF_LOG("_writeW %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew W!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r3; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void writeX( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeX(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } +/*#ifdef VIF_LOG + VIF_LOG("writeX %8.8x : Mode %d, r0 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r0,data); +#endif*/ +} + +static void writeY( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeY(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Y!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } +/*#ifdef VIF_LOG + VIF_LOG("writeY %8.8x : Mode %d, r1 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r1,data); +#endif*/ +} + +static void writeZ( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeZ(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Z!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } +/*#ifdef VIF_LOG + VIF_LOG("writeZ %8.8x : Mode %d, r2 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r2,data); +#endif*/ +} + +static void writeW( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeW(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } +/*#ifdef VIF_LOG + VIF_LOG("writeW %8.8x : Mode %d, r3 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r3,data); +#endif*/ +} + +void UNPACK_S_32(u32 *dest, u32 *data) { + writeX(dest++, *data); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_S_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data) ); + _UNPACKpart(1, writeY(dest++, *data) ); + _UNPACKpart(2, writeZ(dest++, *data) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)data - (u32)_data; +} + +#define _UNPACK_S_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_S_16s( u32 *dest, u32 *data ) { + _UNPACK_S_16( s16 ); +} + +void UNPACK_S_16u( u32 *dest, u32 *data ) { + _UNPACK_S_16( u16 ); +} + +#define _UNPACK_S_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata) ); \ + _UNPACKpart(1, writeY(dest++, *sdata) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_S_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(s16); +} + +int UNPACK_S_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(u16); +} + +#define _UNPACK_S_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_S_8s(u32 *dest, u32 *data) { + _UNPACK_S_8(s8); +} + +void UNPACK_S_8u(u32 *dest, u32 *data) { + _UNPACK_S_8(u8); +} + +#define _UNPACK_S_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata) ); \ + _UNPACKpart(1, writeY(dest++, *cdata) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_S_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(s8); +} + +int UNPACK_S_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(u8); +} + +void UNPACK_V2_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); + +} + +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++)); + _UNPACKpart(1, writeY(dest++, *data++)); + _UNPACKpart_nosize(2, writeZ(dest++, 0)); + _UNPACKpart_nosize(3, writeW(dest++, 0)); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V2_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); \ + + +void UNPACK_V2_16s(u32 *dest, u32 *data) { + _UNPACK_V2_16(s16); +} + +void UNPACK_V2_16u(u32 *dest, u32 *data) { + _UNPACK_V2_16(u16); +} + +#define _UNPACK_V2_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V2_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(s16); +} + +int UNPACK_V2_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(u16); +} + +#define _UNPACK_V2_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_V2_8s(u32 *dest, u32 *data) { + _UNPACK_V2_8(s8); +} + +void UNPACK_V2_8u(u32 *dest, u32 *data) { + _UNPACK_V2_8(u8); +} + +#define _UNPACK_V2_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V2_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(s8); +} + +int UNPACK_V2_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(u8); +} + +void UNPACK_V3_32(u32 *dest, u32 *data) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_V3_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++); ); + _UNPACKpart(1, writeY(dest++, *data++); ); + _UNPACKpart(2, writeZ(dest++, *data++); ); + _UNPACKpart_nosize(3, writeW(dest++, 0); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V3_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_V3_16s(u32 *dest, u32 *data) { + _UNPACK_V3_16(s16); +} + +void UNPACK_V3_16u(u32 *dest, u32 *data) { + _UNPACK_V3_16(u16); +} + +#define _UNPACK_V3_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart(2, writeZ(dest++, *sdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V3_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(s16); +} + +int UNPACK_V3_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(u16); +} + +#define _UNPACK_V3_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_V3_8s(u32 *dest, u32 *data) { + _UNPACK_V3_8(s8); +} + +void UNPACK_V3_8u(u32 *dest, u32 *data) { + _UNPACK_V3_8(u8); +} + +#define _UNPACK_V3_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart(2, writeZ(dest++, *cdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V3_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(s8); +} + +int UNPACK_V3_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(u8); +} + +void UNPACK_V4_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, *data++); +} + +int UNPACK_V4_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++) ); + _UNPACKpart(1, writeY(dest++, *data++) ); + _UNPACKpart(2, writeZ(dest++, *data++) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (u32)data - (u32)_data; +} + +#define _UNPACK_V4_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, *sdata++); + +void UNPACK_V4_16s(u32 *dest, u32 *data) { + _UNPACK_V4_16(s16); +} + +void UNPACK_V4_16u(u32 *dest, u32 *data) { + _UNPACK_V4_16(u16); +} + +#define _UNPACK_V4_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++) ); \ + _UNPACKpart(1, writeY(dest++, *sdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata++) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)sdata - (u32)data; + +int UNPACK_V4_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(s16); +} + +int UNPACK_V4_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(u16); +} + +#define _UNPACK_V4_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, *cdata++); + +void UNPACK_V4_8s(u32 *dest, u32 *data) { + _UNPACK_V4_8(s8); +} + +void UNPACK_V4_8u(u32 *dest, u32 *data) { + _UNPACK_V4_8(u8); +} + +#define _UNPACK_V4_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++) ); \ + _UNPACKpart(1, writeY(dest++, *cdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata++) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (u32)cdata - (u32)data; + +int UNPACK_V4_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(s8); +} + +int UNPACK_V4_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(u8); +} + +void UNPACK_V4_5(u32 *dest, u32 *data) { + u16 *sdata = (u16*)data; + u32 rgba; + + rgba = *sdata++; + writeX(dest++, (rgba & 0x001f) << 3); + writeY(dest++, (rgba & 0x03e0) >> 2); + writeZ(dest++, (rgba & 0x7c00) >> 7); + writeW(dest++, (rgba & 0x8000) >> 8); +} + +int UNPACK_V4_5part(u32 *dest, u32 *data, int size) { + u16 *sdata = (u16*)data; + u32 rgba; + + while (size > 0) { + rgba = *sdata++; + _UNPACKpart(0, writeX(dest++, (rgba & 0x001f) << 3); ); + _UNPACKpart(1, writeY(dest++, (rgba & 0x03e0) >> 2); ); + _UNPACKpart(2, writeZ(dest++, (rgba & 0x7c00) >> 7); ); + _UNPACKpart(3, writeW(dest++, (rgba & 0x8000) >> 8); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (u32)sdata - (u32)data; +} + +static int cycles; +extern int g_vifCycles; +static int vifqwc = 0; +static int mfifoVIF1rbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((vif1ch->madr+(vif1ch->qwc << 4)) >= (maddr+msize)) { + int s1 = (maddr+msize) - vif1ch->madr; + int s2 = (vif1ch->qwc << 4) - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + if(vif1.vifstalled == 1) + ret = VIF1transfer(src+vif1.irqoffset, s1/4-vif1.irqoffset, 0); + else + ret = VIF1transfer(src, s1>>2, 0); + assert(ret == 0 ); // vif stall code not implemented + if(ret == -2) return ret; + if(vif1ch->madr > (maddr+msize)) SysPrintf("Copied too much VIF! %x\n", vif1ch->madr); + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + vif1ch->madr = maddr; + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s2>>2, 0); + assert(ret == 0 ); // vif stall code not implemented + } else { + /* it doesn't, so just transfer 'qwc*4' words + from 'vif1ch->madr' to VIF1 */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + if(vif1.vifstalled == 1) + ret = VIF1transfer(src+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + else + ret = VIF1transfer(src, vif1ch->qwc << 2, 0); + if(ret == -2) return ret; + vif1ch->madr = psHu32(DMAC_RBOR) + (vif1ch->madr & psHu32(DMAC_RBSR)); + assert(ret == 0 ); // vif stall code not implemented + } + + //vif1ch->madr+= (vif1ch->qwc << 4); + + + return ret; +} + +static int mfifoVIF1chain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *pMem; + int mfifoqwc = vif1ch->qwc; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (vif1ch->qwc == 0) return 0; + + if (vif1ch->madr >= maddr && + vif1ch->madr <= (maddr+msize)) { + ret = mfifoVIF1rbTransfer(); + } else { + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) return -1; + if(vif1.vifstalled == 1) + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + else + ret = VIF1transfer(pMem, vif1ch->qwc << 2, 0); + + assert(ret == 0 ); // vif stall code not implemented + + //vif1ch->madr+= (vif1ch->qwc << 4); + } + + cycles+= (mfifoqwc) * BIAS; /* guessing */ + mfifoqwc = 0; + //vif1ch->qwc = 0; + //if(vif1.vifstalled == 1) SysPrintf("Vif1 MFIFO stalls not implemented\n"); + // + vif1.vifstalled = 0; + return ret; +} + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +static int tempqwc = 0; + +void mfifoVIF1transfer(int qwc) { + u32 *ptag; + int id; + int done = 0, ret; + u32 temp = 0; + cycles = 0; + vifqwc += qwc; + g_vifCycles = 0; + /*if(vifqwc == 0) { + //#ifdef PCSX2_DEVBUILD + /*if( vifqwc > 1 ) + SysPrintf("vif mfifo tadr==madr but qwc = %d\n", vifqwc);*/ + //#endif + + //INT(10,50); + /* return; + }*/ + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ +/*#ifdef VIF_LOG + VIF_LOG("mfifoVIF1transfer %x madr %x, tadr %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr); +#endif*/ + + //if((vif1ch->chcr & 0x100) == 0)SysPrintf("MFIFO VIF1 not ready!\n"); + //while (qwc > 0 && done == 0) { + if(vif1ch->qwc == 0){ + if(vif1ch->tadr == spr0->madr) { + #ifdef PCSX2_DEVBUILD + /*if( vifqwc > 1 ) + SysPrintf("vif mfifo tadr==madr but qwc = %d\n", vifqwc);*/ + #endif + //hwDmacIrq(14); + return; + } + + ptag = (u32*)dmaGetAddr(vif1ch->tadr); + + id = (ptag[0] >> 28) & 0x7; + vif1ch->qwc = (ptag[0] & 0xffff); + vif1ch->madr = ptag[1]; + cycles += 2; + + + + if (vif1ch->chcr & 0x40) { + ret = VIF1transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -2) { + vif1.vifstalled = 1; + return; //IRQ set by VIFTransfer + } + } + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + + #ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr); + #endif + vifqwc--; + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); + vif1.done = 2; //End Transfer + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 1: // CNT - Transfer QWC following the tag. + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = vif1ch->madr; //Temporarily Store ADDR + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag + vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 7: // End - Transfer QWC following the tag + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data + vif1.done = 2; //End Transfer + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + } + + + //SysPrintf("VIF1 MFIFO qwc %d vif1 qwc %d, madr = %x, tadr = %x\n", qwc, vif1ch->qwc, vif1ch->madr, vif1ch->tadr); + + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)){ + vifqwc -= vif1ch->qwc; + } + } + + ret = mfifoVIF1chain(); + if (ret == -1) { + SysPrintf("dmaChain error %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); + vif1.done = 1; + INT(10,cycles+g_vifCycles); + } + if(ret == -2){ + //SysPrintf("VIF MFIFO Stall\n"); + vif1.vifstalled = 1; + INT(10,cycles+g_vifCycles); + return; + } + + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef VIF_LOG + VIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoVIF1transfer: dmaIrq Set\n"); + //vifqwc = 0; + vif1.done = 1; + } + +// if( (cpuRegs.interrupt & (1<<1)) && qwc > 0) { +// SysPrintf("vif1 mfifo interrupt %d\n", qwc); +// } + //} + + /*if(vif1.done == 1) { + vifqwc = 0; + }*/ + INT(10,cycles+g_vifCycles); + if(vif1.done == 2) vif1.done = 1; + if(vifqwc == 0 && vif1.done == 0) hwDmacIrq(14); + + //hwDmacIrq(1); +#ifdef SPR_LOG + SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr); +#endif +} + +int vifMFIFOInterrupt() +{ + + if(!(vif1ch->chcr & 0x100)) return 1; + if(vif1.vifstalled == 1 && vif1Regs->stat & VIF1_STAT_VIS) { + if(vif1.irq) { + vif1Regs->stat|= VIF1_STAT_INT; + hwIntcIrq(5); + --vif1.irq; + } + + return 1; + } + + if(vif1.done != 1 && vifqwc != 0) { + mfifoVIF1transfer(0); + if(vif1ch->qwc > 0 && vif1.vifstalled == 0) return 1; + else return 0; + } else if(vif1.done != 1) return 1; + + vif1.done = 0; + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); +// vif1ch->chcr &= ~0x100; +// vif1Regs->stat&= ~0x1F000000; // FQC=0 +// hwDmacIrq(DMAC_VIF1); +// +// if (vif1.irq > 0) { +// vif1.irq--; +// hwIntcIrq(5); // VIF1 Intc +// } + return 1; +} diff --git a/branches/pcsx2_0.9.2/Vif.h b/branches/pcsx2_0.9.2/Vif.h new file mode 100644 index 0000000..749171d --- /dev/null +++ b/branches/pcsx2_0.9.2/Vif.h @@ -0,0 +1,108 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VIF_H__ +#define __VIF_H__ + +typedef struct { + u8 cl, wl; + u8 pad[2]; +} vifCycle; + +typedef struct { + u32 stat; + u32 pad0[3]; + u32 fbrst; + u32 pad1[3]; + u32 err; + u32 pad2[3]; + u32 mark; + u32 pad3[3]; + vifCycle cycle; //data write cycle + u32 pad4[3]; + u32 mode; + u32 pad5[3]; + u32 num; + u32 pad6[3]; + u32 mask; + u32 pad7[3]; + u32 code; + u32 pad8[3]; + u32 itops; + u32 pad9[3]; + u32 base; // Not used in VIF0 + u32 pad10[3]; + u32 ofst; // Not used in VIF0 + u32 pad11[3]; + u32 tops; // Not used in VIF0 + u32 pad12[3]; + u32 itop; + u32 pad13[3]; + u32 top; // Not used in VIF0 + u32 pad14[3]; + u32 mskpath3; + u32 pad15[3]; + u32 r0; // row0 register + u32 pad16[3]; + u32 r1; // row1 register + u32 pad17[3]; + u32 r2; // row2 register + u32 pad18[3]; + u32 r3; // row3 register + u32 pad19[3]; + u32 c0; // col0 register + u32 pad20[3]; + u32 c1; // col1 register + u32 pad21[3]; + u32 c2; // col2 register + u32 pad22[3]; + u32 c3; // col3 register + u32 pad23[3]; + u32 offset; // internal UNPACK offset + u32 addr; +} VIFregisters; + +#define vif0Regs ((VIFregisters*)&PS2MEM_HW[0x3800]) +#define vif1Regs ((VIFregisters*)&PS2MEM_HW[0x3c00]) + +void dmaVIF0(); +void dmaVIF1(); +void mfifoVIF1transfer(int qwc); +int VIF0transfer(u32 *data, int size, int istag); +int VIF1transfer(u32 *data, int size, int istag); +int vifMFIFOInterrupt(); + +#if (defined(__i386__) || defined(__x86_64__)) +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask); +#else +#define SetNewMask 0&& +#endif + +#define XMM_R0 xmm0 +#define XMM_R1 xmm1 +#define XMM_R2 xmm2 +#define XMM_WRITEMASK xmm3 +#define XMM_ROWMASK xmm4 +#define XMM_ROWCOLMASK xmm5 +#define XMM_ROW xmm6 +#define XMM_COL xmm7 + +#define XMM_R3 XMM_COL + + +#endif /* __VIF_H__ */ diff --git a/branches/pcsx2_0.9.2/VifDma.c b/branches/pcsx2_0.9.2/VifDma.c new file mode 100644 index 0000000..d9da69a --- /dev/null +++ b/branches/pcsx2_0.9.2/VifDma.c @@ -0,0 +1,2347 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Vif.h" +#include "VUmicro.h" +#include "GS.h" + +#include "VifDma.h" + +#include + +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) + +// Extern variables +extern VIFregisters *_vifRegs; +extern vifStruct *_vif; +extern u32* _vifMaskRegs; +extern u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +extern u32* _vifRow; + +vifStruct vif0, vif1; + +PCSX2_ALIGNED16(u32 g_vif1Masks[64]); +PCSX2_ALIGNED16(u32 g_vif0Masks[64]); +u32 g_vif1HasMask3[4] = {0}, g_vif0HasMask3[4] = {0}; + +// Generic constants +static const unsigned int VIF0intc = 4; +static const unsigned int VIF1intc = 5; +static const unsigned int VIF0dmanum = 0; +static const unsigned int VIF1dmanum = 1; + +#ifdef _WIN32 +extern HANDLE g_hGsEvent; +#else +extern pthread_cond_t g_condGsEvent; +#endif + +int g_vifCycles = 0; +extern void * memcpy_amd(void *dest, const void *src, size_t n); + +typedef void (*UNPACKFUNCTYPE)( u32 *dest, u32 *data ); +typedef int (*UNPACKPARTFUNCTYPE)( u32 *dest, u32 *data, int size ); +void (*Vif1CMDTLB[82])(); +void (*Vif0CMDTLB[75])(); +int (*Vif1TransTLB[128])(u32 *data, int size); +int (*Vif0TransTLB[128])(u32 *data, int size); + +typedef struct { + UNPACKFUNCTYPE funcU; + UNPACKFUNCTYPE funcS; + UNPACKPARTFUNCTYPE funcUpart; + UNPACKPARTFUNCTYPE funcSpart; + + int bsize; // currently unused + int dsize; // byte size of one channel + int gsize; // size of data in bytes used for each write cycle + int qsize; // used for unpack parts, num of vectors that + // will be decompressed from data for 1 cycle +} VIFUnpackFuncTable; + +/* block size; data size; group size; qword size; */ +#define _UNPACK_TABLE32(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name, UNPACK_##name, \ + UNPACK_##name##part, UNPACK_##name##part, \ + bsize, dsize, gsize, qsize }, + +#define _UNPACK_TABLE(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name##u, UNPACK_##name##s, \ + UNPACK_##name##upart, UNPACK_##name##spart, \ + bsize, dsize, gsize, qsize }, + +// Main table for function unpacking +static const VIFUnpackFuncTable VIFfuncTable[16] = { + _UNPACK_TABLE32(S_32, 1, 4, 4, 4) // 0x0 - S-32 + _UNPACK_TABLE(S_16, 2, 2, 2, 4) // 0x1 - S-16 + _UNPACK_TABLE(S_8, 4, 1, 1, 4) // 0x2 - S-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x3 + + _UNPACK_TABLE32(V2_32, 24, 4, 8, 2) // 0x4 - V2-32 + _UNPACK_TABLE(V2_16, 12, 2, 4, 2) // 0x5 - V2-16 + _UNPACK_TABLE(V2_8, 6, 1, 2, 2) // 0x6 - V2-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x7 + + _UNPACK_TABLE32(V3_32, 36, 4, 12, 3) // 0x8 - V3-32 + _UNPACK_TABLE(V3_16, 18, 2, 6, 3) // 0x9 - V3-16 + _UNPACK_TABLE(V3_8, 9, 1, 3, 3) // 0xA - V3-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0xB + + _UNPACK_TABLE32(V4_32, 48, 4, 16, 4) // 0xC - V4-32 + _UNPACK_TABLE(V4_16, 24, 2, 8, 4) // 0xD - V4-16 + _UNPACK_TABLE(V4_8, 12, 1, 4, 4) // 0xE - V4-8 + _UNPACK_TABLE32(V4_5, 6, 2, 2, 4) // 0xF - V4-5 +}; + + + +#if (defined(__i386__) || defined(__x86_64__)) + +typedef struct { + // regular 0, 1, 2; mask 0, 1, 2 + UNPACKPARTFUNCTYPE funcU[9], funcS[9]; +} VIFSSEUnpackTable; + +#define DECL_UNPACK_TABLE_SSE(name, sign) \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2(u32* dest, u32* data, int dmasize); \ + +#define _UNPACK_TABLE_SSE(name, sign) \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_2, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_2, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2 \ + +#define _UNPACK_TABLE_SSE_NULL \ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + +// Main table for function unpacking +DECL_UNPACK_TABLE_SSE(S_32, u); +DECL_UNPACK_TABLE_SSE(S_16, u); +DECL_UNPACK_TABLE_SSE(S_8, u); +DECL_UNPACK_TABLE_SSE(S_16, s); +DECL_UNPACK_TABLE_SSE(S_8, s); + +DECL_UNPACK_TABLE_SSE(V2_32, u); +DECL_UNPACK_TABLE_SSE(V2_16, u); +DECL_UNPACK_TABLE_SSE(V2_8, u); +DECL_UNPACK_TABLE_SSE(V2_16, s); +DECL_UNPACK_TABLE_SSE(V2_8, s); + +DECL_UNPACK_TABLE_SSE(V3_32, u); +DECL_UNPACK_TABLE_SSE(V3_16, u); +DECL_UNPACK_TABLE_SSE(V3_8, u); +DECL_UNPACK_TABLE_SSE(V3_16, s); +DECL_UNPACK_TABLE_SSE(V3_8, s); + +DECL_UNPACK_TABLE_SSE(V4_32, u); +DECL_UNPACK_TABLE_SSE(V4_16, u); +DECL_UNPACK_TABLE_SSE(V4_8, u); +DECL_UNPACK_TABLE_SSE(V4_16, s); +DECL_UNPACK_TABLE_SSE(V4_8, s); +DECL_UNPACK_TABLE_SSE(V4_5, u); + +static const VIFSSEUnpackTable VIFfuncTableSSE[16] = { + { _UNPACK_TABLE_SSE(S_32, u), _UNPACK_TABLE_SSE(S_32, u) }, + { _UNPACK_TABLE_SSE(S_16, u), _UNPACK_TABLE_SSE(S_16, s) }, + { _UNPACK_TABLE_SSE(S_8, u), _UNPACK_TABLE_SSE(S_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V2_32, u), _UNPACK_TABLE_SSE(V2_32, u) }, + { _UNPACK_TABLE_SSE(V2_16, u), _UNPACK_TABLE_SSE(V2_16, s) }, + { _UNPACK_TABLE_SSE(V2_8, u), _UNPACK_TABLE_SSE(V2_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V3_32, u), _UNPACK_TABLE_SSE(V3_32, u) }, + { _UNPACK_TABLE_SSE(V3_16, u), _UNPACK_TABLE_SSE(V3_16, s) }, + { _UNPACK_TABLE_SSE(V3_8, u), _UNPACK_TABLE_SSE(V3_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V4_32, u), _UNPACK_TABLE_SSE(V4_32, u) }, + { _UNPACK_TABLE_SSE(V4_16, u), _UNPACK_TABLE_SSE(V4_16, s) }, + { _UNPACK_TABLE_SSE(V4_8, u), _UNPACK_TABLE_SSE(V4_8, s) }, + { _UNPACK_TABLE_SSE(V4_5, u), _UNPACK_TABLE_SSE(V4_5, u) }, +}; + +#endif + + +void vif0FLUSH(); +void vif1FLUSH(); + +void vifDmaInit() { +} + +__inline static int _limit( int a, int max ) { + return ( a > max ? max : a ); +} + +extern void DummyExecuteVU1Block(void); + +//#define VIFUNPACKDEBUG //enable unpack debugging output + +static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int VIFdmanum){ + const VIFUnpackFuncTable *unpack; + vifStruct *vif; + unpack = &VIFfuncTable[ unpackType ]; +// varLog |= 0x00000400; + if (VIFdmanum == 0) vif = &vif0; + else vif = &vif1; + + switch(unpackType){ + case 0x0: + vif->tag.addr += size*4; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-32 skip, size = %d\n", size); +#endif + break; + case 0x1: + vif->tag.addr += size*8; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-16 skip, size = %d\n", size); +#endif + break; + case 0x2: + vif->tag.addr += size*16; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-8 skip, size = %d\n", size); +#endif + break; + case 0x4: + vif->tag.addr += size + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-32 skip, size = %d\n", size); +#endif + break; + case 0x5: + vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-16 skip, size = %d\n", size); +#endif + break; + case 0x6: + vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-8 skip, size = %d\n", size); +#endif + break; + case 0x8: + vif->tag.addr += size + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-32 skip, size = %d\n", size); +#endif + break; + case 0x9: + vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-16 skip, size = %d\n", size); +#endif + break; + case 0xA: + vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-8 skip, size = %d\n", size); +#endif + break; + case 0xC: + vif->tag.addr += size; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-32 skip, size = %d, CL = %d, WL = %d\n", size, vif1Regs->cycle.cl, vif1Regs->cycle.wl); +#endif + break; + case 0xD: + vif->tag.addr += size * 2; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-16 skip, size = %d\n", size); +#endif + break; + case 0xE: + vif->tag.addr += size * 4; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-8 skip, size = %d\n", size); +#endif + break; + case 0xF: + vif->tag.addr += size * 8; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-5 skip, size = %d\n", size); +#endif + break; + default: + SysPrintf("Invalid unpack type %x\n", unpackType); + break; + } +} + +#ifdef _MSC_VER +//#define __MMX__ +//#define __SSE__ +#include +#include +#endif + +static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdmanum) { + u32 *dest; + unsigned int unpackType; + UNPACKFUNCTYPE func; + UNPACKPARTFUNCTYPE funcP; + const VIFUnpackFuncTable *ft; + vifStruct *vif; + VIFregisters *vifRegs; + VURegs * VU; + u8 *cdata = (u8*)data; + int memsize; + +#ifdef _MSC_VER + _mm_prefetch((char*)data, _MM_HINT_NTA); +#endif + + if (VIFdmanum == 0) { + VU = &VU0; + vif = &vif0; + vifRegs = vif0Regs; + memsize = 0x1000; + assert( v->addr < 0x1000 ); + v->addr &= 0xfff; + } else { + + VU = &VU1; + vif = &vif1; + vifRegs = vif1Regs; + memsize = 0x4000; + assert( v->addr < 0x4000 ); + v->addr &= 0x3fff; + + if( Cpu->ExecuteVU1Block == DummyExecuteVU1Block ) { + // don't process since the frame is dummy + vif->tag.addr += (size / (VIFfuncTable[ vif->cmd & 0xf ].gsize* vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + return; + } + } + + dest = (u32*)(VU->Mem + v->addr); + +#ifdef VIF_LOG + VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); +#endif + +/* if (vifRegs->cycle.cl > vifRegs->cycle.wl) { + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + }*/ +#ifdef _DEBUG + if (v->size != size) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning v->size != size\n"); +#endif + } + if ((v->addr+size*4) > memsize) { + SysPrintf("*PCSX2*: fixme unpack overflow\n"); + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + } +#endif + // The unpack type + unpackType = v->cmd & 0xf; + /*if (v->size != size) { + SysPrintf("*PCSX2*: v->size = %d, size = %d mode = %x\n", v->size, size, unpackType); + }*/ +#ifdef VIFUNPACKDEBUG + if (size == 0) { + SysPrintf("*PCSX2*: Unpack %x with size 0!! v->size = %d cl = %d, wl = %d, mode %d mask %x\n", v->cmd, v->size, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->mode, vifRegs->mask); + //return; + } +#endif + + + + if(unpackType == 0xC && vifRegs->cycle.cl == vifRegs->cycle.wl) { + // v4-32 + if(vifRegs->mode == 0 && !(vifRegs->code & 0x10000000)){ + if (v->size != size)ProcessMemSkip(size << 2, unpackType, VIFdmanum); + + memcpy_amd((u8*)dest, cdata, size << 2); + size = 0; + return; + } + } + +#ifdef _MSC_VER + _mm_prefetch((char*)data+128, _MM_HINT_NTA); +#endif + _vifRegs = (VIFregisters*)vifRegs; + _vifMaskRegs = VIFdmanum ? g_vif1Masks : g_vif0Masks; + _vif = vif; + _vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; + + // Unpacking + //vif->wl = 0; vif->cl = 0; + + + + if (v->size != size)ProcessMemSkip(size<<2, unpackType, VIFdmanum); +size<<= 2; +#ifdef _DEBUG + memsize = size; +#endif + if( _vifRegs->offset > 0) { + int destinc, unpacksize; +#ifdef VIFUNPACKDEBUG + SysPrintf("aligning packet size = %d offset %d\n", size, vifRegs->offset); +#endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + if(vifRegs->offset < (u32)ft->qsize){ + unpacksize = (ft->qsize - vifRegs->offset); + } else { + unpacksize = 0; + SysPrintf("Unpack align offset = 0\n"); + } + destinc = 4 - vifRegs->offset; + funcP(dest, (u32*)cdata, unpacksize); + size -= unpacksize*ft->dsize; + cdata += unpacksize*ft->dsize; + + vifRegs->num--; + ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { + if(vifRegs->cycle.cl != vifRegs->cycle.wl){ + dest += ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + destinc; + vif->tag.addr += ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + } else { + dest += destinc; + } + vif->cl = 0; + } + else { + dest += destinc; + + } +#ifdef VIFUNPACKDEBUG + SysPrintf("aligning packet done size = %d offset %d\n", size, vifRegs->offset); +#endif + //} + //skipmeminc += (((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2)*4) * skipped; + } + + if (vifRegs->cycle.cl >= vifRegs->cycle.wl && size > 0 && vifRegs->num > 0) { // skipping write + +#ifdef _DEBUG + static s_count=0; +#endif + u32* olddest = dest; + ft = &VIFfuncTable[ unpackType ]; + + if( !(v->addr&0xf) && cpucaps.hasStreamingSIMD2Extensions ) { + const UNPACKPARTFUNCTYPE* pfn; + int writemask; + //static LARGE_INTEGER lbase, lfinal; + //QueryPerformanceCounter(&lbase); + u32 oldcycle = -1; + FreezeXMMRegs(1); + +// u16 tempdata[4] = { 0x8000, 0x7fff, 0x1010, 0xd0d0 }; +// vifRegs->cycle.cl = 4; +// vifRegs->cycle.wl = 1; +// SetNewMask(g_vif1Masks, g_vif1HasMask3, 0x3f, ~0x3f); +// memset(dest, 0xcd, 64*4); +// VIFfuncTableSSE[1].funcS[6](dest, (u32*)tempdata, 8); + +#ifdef _MSC_VER + if( VIFdmanum ) { + __asm movaps XMM_ROW, qword ptr [g_vifRow1] + __asm movaps XMM_COL, qword ptr [g_vifCol1] + } + else { + __asm movaps XMM_ROW, qword ptr [g_vifRow0] + __asm movaps XMM_COL, qword ptr [g_vifCol0] + } +#else + if( VIFdmanum ) { + __asm__(".intel_syntax\n" + "movaps %%xmm6, qword ptr [%0]\n" + "movaps %%xmm7, qword ptr [%1]\n" + ".att_syntax\n" : :"i"(g_vifRow1), "i"(g_vifCol1) ); + } + else { + __asm__(".intel_syntax\n" + "movaps %%xmm6, qword ptr [%0]\n" + "movaps %%xmm7, qword ptr [%1]\n" + ".att_syntax\n" : : "i"(g_vifRow0), "i"(g_vifCol0) ); + } +#endif + + if( vifRegs->cycle.cl == 0 || vifRegs->cycle.wl == 0 || (vifRegs->cycle.cl == vifRegs->cycle.wl && !(vifRegs->code&0x10000000)) ) { + oldcycle = *(u32*)&vifRegs->cycle; + vifRegs->cycle.cl = vifRegs->cycle.wl = 1; + } + + size = min(size, (int)vifRegs->num*ft->gsize); + pfn = vif->usn ? VIFfuncTableSSE[unpackType].funcU: VIFfuncTableSSE[unpackType].funcS; + writemask = VIFdmanum ? g_vif1HasMask3[min(vifRegs->cycle.wl,3)] : g_vif0HasMask3[min(vifRegs->cycle.wl,3)]; + writemask = pfn[(((vifRegs->code & 0x10000000)>>28)<mode](dest, (u32*)cdata, size); + + if( oldcycle != -1 ) *(u32*)&vifRegs->cycle = oldcycle; + + // if size is left over, update the src,dst pointers + if( writemask > 0 ) { + int left; + left = (size-writemask)/ft->gsize; + cdata += size-writemask; + dest = (u32*)((u8*)dest + ((left/vifRegs->cycle.wl)*vifRegs->cycle.cl + left%vifRegs->cycle.wl)*16); + vifRegs->num -= left; + } + else vifRegs->num -= size/ft->gsize; + + vif->tag.addr += (size / (ft->gsize* vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + size = writemask; + + _vifRegs->r0 = _vifRow[0]; + _vifRegs->r1 = _vifRow[1]; + _vifRegs->r2 = _vifRow[2]; + _vifRegs->r3 = _vifRow[3]; + //QueryPerformanceCounter(&lfinal); + //((LARGE_INTEGER*)g_nCounters)->QuadPart += lfinal.QuadPart - lbase.QuadPart; + } + else + { + int incdest; + + // Assigning the normal upack function, the part type is assigned later + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + 4; + + //SysPrintf("slow vif\n"); + //if(skipped > 0) skipped = 0; + vif->tag.addr += (size / (ft->gsize*vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + + while (size >= ft->gsize && vifRegs->num > 0) { + funcP( dest, (u32*)cdata, ft->qsize); + cdata += ft->gsize; + size -= ft->gsize; + + vifRegs->num--; + //SysPrintf("%d transferred, remaining %d, vifnum %d\n", ft->gsize, size, vifRegs->num); + ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { + dest += incdest; + vif->cl = 0; + } + else + { + dest += 4; + } + } + + // have to update + _vifRow[0] = _vifRegs->r0; + _vifRow[1] = _vifRegs->r1; + _vifRow[2] = _vifRegs->r2; + _vifRow[3] = _vifRegs->r3; + } + + // used for debugging vif +// { +// int i, j; +// u32* curdest = olddest; +// FILE* ftemp = fopen("temp.txt", "a+"); +// fprintf(ftemp, "%x %x %x\n", s_count, size, vif->tag.addr); +// fprintf(ftemp, "%x %x %x\n", vifRegs->code>>24, vifRegs->mode, *(u32*)&vifRegs->cycle); +// fprintf(ftemp, "row: %x %x %x %x\n", _vifRow[0], _vifRow[1], _vifRow[2], _vifRow[3]); +// //fprintf(ftemp, "row2: %x %x %x %x\n", _vifRegs->r0, _vifRegs->r1, _vifRegs->r2, _vifRegs->r3); +// +// for(i = 0; i < memsize; ) { +// for(j = 0; j <= ((vifRegs->code>>26)&3); ++j) { +// fprintf(ftemp, "%x ", curdest[j]); +// } +// fprintf(ftemp, "\n"); +// curdest += 4*vifRegs->cycle.cl; +// i += j*ft->dsize; +// } +// fclose(ftemp); +// } +// s_count++; + + if( size >= ft->dsize && vifRegs->num > 0) { + #ifdef VIF_LOG + VIF_LOG("warning, end with size = %d\n", size); + #endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + #ifdef VIFUNPACKDEBUG + SysPrintf("end with size %x dsize = %x\n", size, ft->dsize); + #endif + while (size >= ft->dsize) { + /* unpack one qword */ + funcP(dest, (u32*)cdata, 1); + dest += 1; + size -= ft->dsize; + } + #ifdef VIFUNPACKDEBUG + SysPrintf("leftover done, size %d, vifnum %d, addr %x\n", size, vifRegs->num, vif->tag.addr); + #endif + } + + } + else if (vifRegs->cycle.cl < vifRegs->cycle.wl) { /* filling write */ + u32 dummy[8]; +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: filling write\n"); +#endif + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; +#ifdef VIFUNPACKDEBUG + SysPrintf("filling write %d cl %d, wl %d\n", vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl); +#endif + while (size >= ft->gsize || vifRegs->num > 0) { + if (vif->cl == vifRegs->cycle.wl) { + vif->cl = 0; + } + // + if (vif->cl < vifRegs->cycle.cl) { /* unpack one qword */ + funcP( dest, (u32*)cdata, ft->qsize); + cdata += ft->gsize; + size -= ft->gsize; + vif->cl++; + vifRegs->num--; + if (vif->cl == vifRegs->cycle.wl) { + vif->cl = 0; + } + } + else + { + funcP( dest, (u32*)dummy, ft->qsize); + //cdata += ft->gsize; + //size -= ft->gsize; + vif->tag.addr += 16; + vifRegs->num--; + ++vif->cl; + + } + dest += 4; + //++vif->wl; + } + } + + if(vifRegs->num == 0 && size > 3) SysPrintf("Size = %x, Vifnum = 0!\n", size); +} + +static void vuExecMicro( u32 addr, const unsigned int VIFdmanum ) +{ + int _cycles; + VURegs * VU; + //void (*_vuExecMicro)(); + +// MessageBox(NULL, "3d doesn't work\n", "Query", MB_OK); +// return; + + if (VIFdmanum == 0) { + //_vuExecMicro = Cpu->ExecuteVU0Block; + VU = &VU0; + vif0FLUSH(); + } else { + //_vuExecMicro = Cpu->ExecuteVU1Block; + VU = &VU1; + vif1FLUSH(); + } + + VU->vifRegs->itop = VU->vifRegs->itops; + + if (VIFdmanum == 1) { + /* in case we're handling a VIF1 execMicro + set the top with the tops value */ + VU->vifRegs->top = VU->vifRegs->tops; + + /* is DBF flag set in VIF_STAT? */ + if (VU->vifRegs->stat & 0x80) { + /* it is, so set tops with base + ofst + and clear stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base; + VU->vifRegs->stat &= ~0x80; + } else { + /* it is not, so set tops with base + and set the stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; + VU->vifRegs->stat |= 0x80; + } + } + + if (VIFdmanum == 0) { + _cycles = VU0.cycle; + vu0ExecMicro(addr); + // too much delay + //g_vifCycles+= (VU0.cycle - _cycles)*BIAS; + } else { + _cycles = VU1.cycle; + vu1ExecMicro(addr); + // too much delay + //g_vifCycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +void vif0Init() { + u32 i; + extern u8 s_maskwrite[256]; + + for(i = 0; i < 256; ++i ) { + s_maskwrite[i] = ((i&3)==3)||((i&0xc)==0xc)||((i&0x30)==0x30)||((i&0xc0)==0xc0); + } + + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); +} + +__inline void vif0FLUSH() { + int _cycles; + _cycles = VU0.cycle; + + vu0Finish(); + g_vifCycles+= (VU0.cycle - _cycles)*BIAS; +} + +__inline void vif0UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + if(vif0Regs->cycle.wl == 0 && vif0Regs->cycle.wl < vif0Regs->cycle.cl){ + SysPrintf("Vif0 CL %d, WL %d\n", vif0Regs->cycle.cl, vif0Regs->cycle.wl); + vif0.cmd &= ~0x7f; + return; + } + + vif0FLUSH(); + + vl = (vif0.cmd ) & 0x3; + vn = (vif0.cmd >> 2) & 0x3; + vif0.tag.addr = (data[0] & 0x3ff) << 4; + vif0.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + vif0Regs->num = vifNum; + + if ( vif0Regs->cycle.wl <= vif0Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) + + _limit( vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl ); + + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + + vif0.wl = 0; vif0.cl = 0; + vif0.tag.cmd = vif0.cmd; + vif0.tag.size = len; + vif0Regs->offset = 0; +} + +__inline void _vif0mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif0mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU0.Micro + addr, data, size << 2)) { + memcpy_amd(VU0.Micro + addr, data, size << 2); + Cpu->ClearVU0(addr, size); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Table +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int (*Vif0TransTLB[128])(u32 *data, int size) = +{ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x7*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0xF*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x17*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x1F*/ + Vif0TransSTMask , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x27*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x2F*/ + Vif0TransSTRow , Vif0TransSTCol , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x37*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x3F*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x47*/ + Vif0TransNull , Vif0TransNull , Vif0TransMPG , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x4F*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x57*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x5F*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x67*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , /*0x6F*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x77*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack /*0x7F*/ +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 CMD Table +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void (*Vif0CMDTLB[75])() = +{ + Vif0CMDNop , Vif0CMDSTCycl , Vif0CMDNull , Vif0CMDNull , Vif0CMDITop , Vif0CMDSTMod , Vif0CMDNull, Vif0CMDMark , /*0x7*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0xF*/ + Vif0CMDFlushE , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull, Vif0CMDMSCALF, Vif0CMDMSCALF, Vif0CMDNull , Vif0CMDMSCNT, /*0x17*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x1F*/ + Vif0CMDSTMask , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x27*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x2F*/ + Vif0CMDSTRowCol, Vif0CMDSTRowCol, Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x37*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x3F*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x47*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDMPGTransfer +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int Vif0TransNull(u32 *data, int size){ // Shouldnt go here + SysPrintf("VIF0 Shouldnt go here CMD = %x\n", vif0Regs->code); + vif0.cmd = 0; + return 0; +} +static int Vif0TransSTMask(u32 *data, int size){ // STMASK + SetNewMask(g_vif0Masks, g_vif0HasMask3, data[0], vif0Regs->mask); + vif0Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif0Regs->mask); +#endif + vif0.tag.size = 0; + vif0.cmd = 0; + return 1; +} + +static int Vif0TransSTRow(u32 *data, int size){ // STROW + int ret; + + u32* pmem = &vif0Regs->r0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifRow0+vif0.tag.addr; + assert( vif0.tag.addr < 4 ); + ret = min(4-vif0.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + if(vif0.tag.size == 0) vif0.cmd = 0; + + return ret; +} + +static int Vif0TransSTCol(u32 *data, int size){ // STCOL + int ret; + + u32* pmem = &vif0Regs->c0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifCol0+vif0.tag.addr; + ret = min(4-vif0.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + if(vif0.tag.size == 0) vif0.cmd = 0; + return ret; +} + +static int Vif0TransMPG(u32 *data, int size){ // MPG + if (size < vif0.tag.size) { + _vif0mpgTransfer(vif0.tag.addr, data, size); + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + return size; + } else { + int ret; + _vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); + ret = vif0.tag.size; + vif0.tag.size = 0; + vif0.cmd = 0; + return ret; + } +} + +static int Vif0TransUnpack(u32 *data, int size){ // UNPACK + if (size < vif0.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif0.tag, size, VIF0dmanum); + // g_vifCycles+= size >> 1; + //vif0.tag.addr += size << 2; + vif0.tag.size -= size; + return size; + } else { + int ret; + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + //g_vifCycles+= vif0.tag.size >> 1; + ret = vif0.tag.size; + vif0.tag.size = 0; + vif0.cmd = 0; + return ret; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif0 CMD Base Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void Vif0CMDNop(){ // NOP + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTCycl(){ // STCYCL + vif0Regs->cycle.cl = (u8)vif0Regs->code; + vif0Regs->cycle.wl = (u8)(vif0Regs->code >> 8); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDITop(){ // ITOP + vif0Regs->itops = vif0Regs->code & 0x3ff; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTMod(){ // STMOD + vif0Regs->mode = vif0Regs->code & 0x3; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMark(){ // MARK + vif0Regs->mark = (u16)vif0Regs->code; + vif0Regs->stat |= VIF0_STAT_MRK; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDFlushE(){ // FLUSHE + vif0FLUSH(); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMSCALF(){ //MSCAL/F + vuExecMicro( (u16)(vif0Regs->code) << 3, VIF0dmanum ); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMSCNT(){ // MSCNT + vuExecMicro( -1, VIF0dmanum ); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTMask(){ // STMASK + vif0.tag.size = 1; +} + +static void Vif0CMDSTRowCol(){// STROW / STCOL + vif0.tag.addr = 0; + vif0.tag.size = 4; +} + +static void Vif0CMDMPGTransfer(){ // MPG + int vifNum; + vif0FLUSH(); + vifNum = (u8)(vif0Regs->code >> 16); + if (vifNum == 0) vifNum = 256; + vif0.tag.addr = (u16)(vif0Regs->code) << 3; + vif0.tag.size = vifNum * 2; +} + +static void Vif0CMDNull(){ // invalid opcode + // if ME1, then force the vif to interrupt + vif0.cmd = (vif0Regs->err&0x40)?0x80:0; + if ((vif0Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif0.cmd ); + vif0Regs->stat |= 1 << 13; + } +} + +int VIF0transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + //vif0.irqoffset = 0; +#ifdef VIF_LOG + VIF_LOG( "VIF0transfer: size %x (vif0.cmd %x)\n", size, vif0.cmd ); +#endif + + //return 0; + if(vif0.savedtag){ + vif0.cmd = vif0.savedtag; + vif0.savedtag = 0; + } + //vif0.irq = 0; + while (size > 0) { + + if((vif0.cmd & 0x70) == 0x50 && istag) { + vif0.savedtag = vif0.cmd; + vif0.cmd = 0; + continue; + } + if((vif0.cmd & 0x70) == 0x40 && istag && size < 2) { + vif0.savedtag = vif0.cmd; + vif0.cmd = 0; + continue; + } + if (vif0.cmd & 0x7f) { + //vif0Regs->stat |= VIF0_STAT_VPS_T; + ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif0Regs->stat &= ~VIF0_STAT_VPS_T; + continue; + } + + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + + // if interrupt and new cmd is NOT MARK + if(vif0.irq && ((vif0Regs->code >> 24) & 0x7f) != 0x7 && vif0.tag.size == 0) { + if(vif0.tag.size > 0) SysPrintf("Stall when vif0 tagsize %x code %x\n", vif0.tag.size, vif0.cmd); + break; + } + vif0.cmd = (data[0] >> 24); + vif0Regs->code = data[0]; + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + //vif0Regs->stat |= VIF0_STAT_VPS_D; + if ((vif0.cmd & 0x60) == 0x60) { + vif0UNPACK(data); + } else { + //vif0CMD(data, size); + Vif0CMDTLB[(vif0.cmd & 0x7f)](); + } + //vif0Regs->stat &= ~VIF0_STAT_VPS_D; + if(vif0.tag.size > 0) vif0Regs->stat |= VIF0_STAT_VPS_W; + ++data; + --size; + ++transferred; + + if ((vif0.cmd & 0x80) && !(vif0Regs->err & 0x1) && ((vif0Regs->code >> 24) & 0x7f) != 0x7 ) { //i bit on vifcode and not masked by VIF0_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif0.cmd, psHu32(INTC_MASK) ); +#endif + + //vif0Regs->stat|= VIF0_STAT_VIS; + ++vif0.irq; + vif0.cmd &= 0x7f; + } + if(vif0.irq && ((vif0Regs->code >> 24) & 0x7f) != 0x7 && vif0.tag.size == 0) { + break; + } + } + + // use tag.size because some game doesn't like .cmd + //if( !vif0.cmd ) + if( !vif0.tag.size ) + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + if (vif0.irq > 0) { + + if( istag ) { + return -2; + } + + // spiderman doesn't break on qw boundaries + vif0.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + //SysPrintf("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + } + + return 0; +} + +int _VIF0chain() { + u32 *pMem; + u32 qwc = vif0ch->qwc; + u32 ret; + + if (vif0ch->qwc == 0 && vif0.irqoffset != 0) SysPrintf("Narf0 QWC %x, offset %x\n", vif0ch->qwc, vif0.irqoffset); + if (vif0ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif0ch->madr); + if (pMem == NULL) + return -1; + + if( vif0.vifstalled ) { + ret = VIF0transfer(pMem+vif0.irqoffset, vif0ch->qwc*4-vif0.irqoffset, 0); + } + else { + ret = VIF0transfer(pMem, vif0ch->qwc*4, 0); + } + /*vif0ch->madr+= (vif0ch->qwc << 4); + vif0ch->qwc-= qwc;*/ + g_vifCycles+= (qwc-vif0ch->qwc)*BIAS; /* guessing */ + return ret; +} + + +int _chainVIF0() { + int id; + u32 *ptag; + //int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("Vif0 Tag BUSERR\n"); + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif0ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif0ch->madr = ptag[1]; //MADR = ADDR field + g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + vif0.done |= hwDmacSrcChainWithStack(vif0ch, id); + if (vif0ch->chcr & 0x40) { + ret = VIF0transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + vif0.vifstalled = 1; + return vif0.done; //IRQ set by VIFTransfer + } + } + + + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif0ch, id); + ret = _VIF0chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif0.vifstalled = 1; + return vif0.done; + } + + //if(id == 7)vif0ch->tadr = vif0ch->madr; + + vif0.vifstalled = 0; + + if ((vif0ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF0 TIE\n"); + //SysPrintf( "VIF0dmaIrq Set\n" ); + //vif0ch->qwc = 0; + //vif0Regs->stat|= VIF0_STAT_VIS; //Set the Tag Interrupt flag of VIF0_STAT + vif0.done = 1; + return vif0.done; //End Transfer + } + return vif0.done; //Return Done +} + +static int _vif0Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif0Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(vif0.vifstalled == 1) { + if(vif0.irq) { + vif0Regs->stat|= VIF0_STAT_INT; + hwIntcIrq(VIF0intc); + --vif0.irq; + } + vif0Regs->stat&= ~0xF000000; // FQC=0 + if(vif0.done == 1 && vif0ch->qwc == 0 && vif0.irqoffset == 0) { + //SysPrintf("Vif0 Stall, done = 1 qwc = 0 irqoffset = %x, tell ref\n", vif0.irqoffset); + vif0.vifstalled = 0; + } else + return 1; + } + if (vif0ch->chcr & 0x4 && vif0.done == 0 && vif0.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif0 dma masked\n"); + return 0; + } + + g_vifCycles = 0; + if(vif0ch->qwc > 0) _VIF0chain(); + ret = _chainVIF0(); + INT(0, g_vifCycles); + return 0; + //if(ret!=2) + /*else*/ //return 1; + } + + + + + vif0ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF0); + vif0Regs->stat&= ~0xF000000; // FQC=0 + + return 1; +} + +int vif0Interrupt() { + + int ret; + + ret = _vif0Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF0() { + +#ifdef VIF_LOG + VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif0ch->chcr, vif0ch->madr, vif0ch->qwc, + vif0ch->tadr, vif0ch->asr0, vif0ch->asr1 ); +#endif + + /* Check if there is a pending irq */ + /*if (vif0.irq > 0) { + vif0.irq--; + hwIntcIrq(VIF0intc); + return; + }*/ +// if(vif0ch->qwc > 0) { +// _VIF0chain(); +// INT(0, g_vifCycles); +// } + g_vifCycles = 0; + + + vif0Regs->stat|= 0x8000000; // FQC=8 + + if (!(vif0ch->chcr & 0x4) || vif0ch->qwc > 0) { // Normal Mode + if(_VIF0chain() == -2) { + SysPrintf("Stall on normal\n"); + vif0.vifstalled = 1; + return; + } + vif0.done = 1; + INT(0, g_vifCycles); + return; + } + +/* if (_VIF0chain() != 0) { + INT(0, g_vifCycles); + return; + }*/ + // Chain Mode + vif0.done = 0; + _vif0Interrupt(); + INT(0, g_vifCycles); +} + +void dmaVIF0() +{ + _dmaVIF0(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif0Write32(u32 mem, u32 value) { + if (mem == 0x10003830) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF0_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF0_STAT and set mark with 'value' */ + vif0Regs->stat&= ~VIF0_STAT_MRK; + vif0Regs->mark = value; + } else + if (mem == 0x10003810) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF0_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif0 Reset\n"); + memset(&vif0, 0, sizeof(vif0)); + vif0ch->qwc = 0; //? + psHu64(0x10004000) = 0; + psHu64(0x10004008) = 0; + vif0.done = 1; + vif0Regs->err = 0; + vif0Regs->stat&= ~0xF000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif0Regs->stat |= VIF0_STAT_VFS; + SysPrintf("vif0 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif0Regs->stat |= VIF0_STAT_VSS; + //SysPrintf("Vif0 Stop\n"); + //dmaVIF0(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif0Regs->stat & (VIF0_STAT_INT|VIF0_STAT_VSS|VIF0_STAT_VIS|VIF0_STAT_VFS)) { + cancel = 1; + } + + vif0Regs->stat &= ~(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | + VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); + if (cancel) { + //SysPrintf("VIF0 Stall Resume\n"); + if( vif0.vifstalled ) { + // loop necessary for spiderman + if ( _VIF0chain() != -2 ) + vif0.vifstalled = 0; + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + INT(0, g_vifCycles); // Gets the timing right - Flatout + } + } + } + } else + if (mem == 0x10003820) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF0_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF0_ERR with 'value' */ + vif0Regs->err = value; + } else{ + SysPrintf("Unknown Vif0 write to %x\n", mem); + if( mem >= 0x10003900 && mem < 0x10003980 ) { + + assert( (mem&0xf) == 0 ); + if( mem < 0x10003940 ) g_vifRow0[(mem>>4)&3] = value; + else g_vifCol0[(mem>>4)&3] = value; + } else psHu32(mem) = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif0Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif0, 0, sizeof(vif0)); + memset(vif0Regs, 0, sizeof(vif0Regs)); + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); + psHu64(0x10004000) = 0; + psHu64(0x10004008) = 0; + vif0.done = 1; + vif0Regs->stat&= ~0xF000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif0Freeze(gzFile f, int Mode) { + gzfreeze(&vif0, sizeof(vif0)); + if (Mode == 0) + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +void vif1Init() { + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); +} + +__inline void vif1FLUSH() { + int _cycles; + _cycles = VU1.cycle; + + if( VU0.VI[REG_VPU_STAT].UL & 0x100 ) { + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + +// FreezeXMMRegs(0); +// FreezeMMXRegs(0); + + g_vifCycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +__inline void vif1UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + if(vif1Regs->cycle.wl == 0 && vif1Regs->cycle.wl < vif1Regs->cycle.cl){ + SysPrintf("Vif1 CL %d, WL %d\n", vif1Regs->cycle.cl, vif1Regs->cycle.wl); + vif1.cmd &= ~0x7f; + return; + } + vif1FLUSH(); + + vl = (vif1.cmd ) & 0x3; + vn = (vif1.cmd >> 2) & 0x3; + vif1.tag.addr = (data[0] & 0x3ff); + vif1.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + vif1Regs->num = vifNum; + + if ( vif1Regs->cycle.wl <= vif1Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) + + _limit( vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl ); + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + if ( ( data[0] >> 15) & 0x1 ) { + vif1.tag.addr += vif1Regs->tops; + } + vif1.wl = 0; vif1.cl = 0; + vif1.tag.addr <<= 4; + + vif1.tag.addr &= 0x3fff; + vif1.tag.cmd = vif1.cmd; + vif1.tag.size = len; + vif1Regs->offset = 0; +} + +__inline void _vif1mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif1mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU1.Micro + addr, data, size << 2)) { + memcpy_amd(VU1.Micro + addr, data, size << 2); + Cpu->ClearVU1(addr, size); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Table +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int (*Vif1TransTLB[128])(u32 *data, int size) = +{ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x7*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0xF*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x17*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x1F*/ + Vif1TransSTMask , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x27*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x2F*/ + Vif1TransSTRow , Vif1TransSTCol , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x37*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x3F*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x47*/ + Vif1TransNull , Vif1TransNull , Vif1TransMPG , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x4F*/ + Vif1TransDirectHL, Vif1TransDirectHL, Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x57*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x5F*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x67*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , /*0x6F*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x77*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack /*0x7F*/ +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 CMD Table +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void (*Vif1CMDTLB[82])() = +{ + Vif1CMDNop , Vif1CMDSTCycl , Vif1CMDOffset , Vif1CMDBase , Vif1CMDITop , Vif1CMDSTMod , Vif1CMDMskPath3, Vif1CMDMark , /*0x7*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0xF*/ + Vif1CMDFlush , Vif1CMDFlush , Vif1CMDNull , Vif1CMDFlush, Vif1CMDMSCALF, Vif1CMDMSCALF, Vif1CMDNull , Vif1CMDMSCNT, /*0x17*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x1F*/ + Vif1CMDSTMask , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x27*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x2F*/ + Vif1CMDSTRowCol, Vif1CMDSTRowCol, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x37*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x3F*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x47*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDMPGTransfer, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x4F*/ + Vif1CMDDirectHL, Vif1CMDDirectHL +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int Vif1TransNull(u32 *data, int size){ // Shouldnt go here + SysPrintf("Shouldnt go here CMD = %x\n", vif1Regs->code); + vif1.cmd = 0; + return 0; +} +static int Vif1TransSTMask(u32 *data, int size){ // STMASK + SetNewMask(g_vif1Masks, g_vif1HasMask3, data[0], vif1Regs->mask); + vif1Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif1Regs->mask); +#endif + vif1.tag.size = 0; + vif1.cmd = 0; + return 1; +} + +static int Vif1TransSTRow(u32 *data, int size){ + int ret; + + u32* pmem = &vif1Regs->r0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifRow1+vif1.tag.addr; + assert( vif1.tag.addr < 4 ); + ret = min(4-vif1.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + if(vif1.tag.size == 0) vif1.cmd = 0; + + return ret; +} + +static int Vif1TransSTCol(u32 *data, int size){ + int ret; + + u32* pmem = &vif1Regs->c0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifCol1+vif1.tag.addr; + ret = min(4-vif1.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; + default: __assume(0); + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + if(vif1.tag.size == 0) vif1.cmd = 0; + return ret; +} + +static int Vif1TransMPG(u32 *data, int size){ + if (size < vif1.tag.size) { + _vif1mpgTransfer(vif1.tag.addr, data, size); + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + return size; + } else { + int ret; + _vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + return ret; + } +} + +static int Vif1TransDirectHL(u32 *data, int size){ + int ret; + + if (size < vif1.tag.size) { + vif1.tag.size-= size; + ret = size; + } else { + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + } + + if( CHECK_MULTIGS ) { + u8* gsmem = GSRingBufCopy(data, ret<<2, GS_RINGTYPE_P2); + if( gsmem != NULL ) { + memcpy_amd(gsmem, data, ret<<2); + GSRINGBUF_DONECOPY(gsmem, ret<<2); + GSgifTransferDummy(1, data, ret>>2); + } + + if( !CHECK_DUALCORE ) SetEvent(g_hGsEvent);//GS_SETEVENT(); + } + else { + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSGIFTRANSFER2(data, (ret >> 2)); + } + return ret; +} + +static int Vif1TransUnpack(u32 *data, int size){ + if (size < vif1.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif1.tag, size, VIF1dmanum); + // g_vifCycles+= size >> 1; + //vif1.tag.addr += size << 2; + vif1.tag.size -= size; + return size; + } else { + int ret; + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + //g_vifCycles+= vif1.tag.size >> 1; + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + return ret; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 CMD Base Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void Vif1CMDNop(){ // NOP + vif1.cmd &= ~0x7f; +} +static void Vif1CMDSTCycl(){ // STCYCL + vif1Regs->cycle.cl = (u8)vif1Regs->code; + vif1Regs->cycle.wl = (u8)(vif1Regs->code >> 8); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDOffset(){ // OFFSET + vif1Regs->ofst = vif1Regs->code & 0x3ff; + vif1Regs->stat &= ~0x80; + vif1Regs->tops = vif1Regs->base; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDBase(){ // BASE + vif1Regs->base = vif1Regs->code & 0x3ff; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDITop(){ // ITOP + vif1Regs->itops = vif1Regs->code & 0x3ff; + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDSTMod(){ // STMOD + vif1Regs->mode = vif1Regs->code & 0x3; + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDMskPath3(){ // MSKPATH3 + vif1Regs->mskpath3 = (vif1Regs->code >> 15) & 0x1; + if ( vif1Regs->mskpath3 ) { + if(gif->qwc) _GIFchain(); // Finish the transfer first + psHu32(GIF_STAT) |= 0x2; + } else { + psHu32(GIF_STAT) &= ~0x2; + if(gif->qwc) _GIFchain(); // Finish the transfer first + } + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDMark(){ // MARK + vif1Regs->mark = (u16)vif1Regs->code; + vif1Regs->stat |= VIF1_STAT_MRK; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDFlush(){ // FLUSH/E/A + vif1FLUSH(); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDMSCALF(){ //MSCAL/F + vuExecMicro( (u16)(vif1Regs->code) << 3, VIF1dmanum ); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDMSCNT(){ // MSCNT + vuExecMicro( -1, VIF1dmanum ); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDSTMask(){ // STMASK + vif1.tag.size = 1; +} +static void Vif1CMDSTRowCol(){// STROW / STCOL + vif1.tag.addr = 0; + vif1.tag.size = 4; +} + +static void Vif1CMDMPGTransfer(){ // MPG + int vifNum; + vif1FLUSH(); + vifNum = (u8)(vif1Regs->code >> 16); + if (vifNum == 0) vifNum = 256; + vif1.tag.addr = (u16)(vif1Regs->code) << 3; + vif1.tag.size = vifNum * 2; +} +static void Vif1CMDDirectHL(){ // DIRECT/HL + int vifImm; + vifImm = (u16)vif1Regs->code; + if (vifImm == 0) { + vif1.tag.size = 65536 << 2; + } else { + vif1.tag.size = vifImm << 2; + } +} +static void Vif1CMDNull(){ // invalid opcode + // if ME1, then force the vif to interrupt + vif1.cmd = (vif1Regs->err&0x40)?0x80:0; + if ((vif1Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif1.cmd ); + vif1Regs->stat |= 1 << 13; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int VIF1transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + //vif1.irqoffset = 0; +#ifdef VIF_LOG + VIF_LOG( "VIF1transfer: size %x (vif1.cmd %x)\n", size, vif1.cmd ); +#endif + + //return 0; + if(vif1.savedtag){ + vif1.cmd = vif1.savedtag; + vif1.savedtag = 0; + } + //vif1.irq = 0; + while (size > 0) { + + if((vif1.cmd & 0x70) == 0x50 && istag) { + vif1.savedtag = vif1.cmd; + vif1.cmd = 0; + continue; + } + if((vif1.cmd & 0x70) == 0x40 && istag && size < 2) { + vif1.savedtag = vif1.cmd; + vif1.cmd = 0; + continue; + } + if (vif1.cmd & 0x7f) { + //vif1Regs->stat |= VIF1_STAT_VPS_T; + ret = Vif1TransTLB[(vif1.cmd & 0x7f)](data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif1Regs->stat &= ~VIF1_STAT_VPS_T; + continue; + } + + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + + // if interrupt and new cmd is NOT MARK + if(vif1.irq && ((vif1Regs->code >> 24) & 0x7f) != 0x7 && vif1.tag.size == 0) { + if(vif1.tag.size > 0) SysPrintf("Stall when vif1 tagsize %x code %x\n", vif1.tag.size, vif1.cmd); + break; + } + vif1.cmd = (data[0] >> 24); + vif1Regs->code = data[0]; + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + //vif1Regs->stat |= VIF1_STAT_VPS_D; + if ((vif1.cmd & 0x60) == 0x60) { + vif1UNPACK(data); + } else { + //vif1CMD(data, size); + Vif1CMDTLB[(vif1.cmd & 0x7f)](); + } + //vif1Regs->stat &= ~VIF1_STAT_VPS_D; + if(vif1.tag.size > 0) vif1Regs->stat |= VIF1_STAT_VPS_W; + ++data; + --size; + ++transferred; + + if ((vif1.cmd & 0x80) && !(vif1Regs->err & 0x1) && ((vif1Regs->code >> 24) & 0x7f) != 0x7 ) { //i bit on vifcode and not masked by VIF1_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif1.cmd, psHu32(INTC_MASK) ); +#endif + /*if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ + SysPrintf("VIF1 Stall on MFIFO, not implemented!\n"); + }*/ + vif1Regs->stat|= VIF1_STAT_VIS; + ++vif1.irq; + vif1.cmd &= 0x7f; + } + if(vif1.irq && ((vif1Regs->code >> 24) & 0x7f) != 0x7 && vif1.tag.size == 0) { + break; + } + } + + // use tag.size because some game doesn't like .cmd + //if( !vif1.cmd ) + if( !vif1.tag.size ) + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + if (vif1.irq > 0) { + + if( istag ) { + return -2; + } + + // spiderman doesn't break on qw boundaries + vif1.irqoffset = transferred%4; // cannot lose the offset + + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + } + + return 0; +} + +int _VIF1chain() { + u32 *pMem; + u32 qwc = vif1ch->qwc; + u32 ret; + + if (vif1ch->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) + return -1; + + if( vif1.vifstalled ) { + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + } + else { + ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); + } + /*vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->qwc-= qwc;*/ + g_vifCycles+= (qwc-vif1ch->qwc)*BIAS; /* guessing */ + return ret; +} + +static int prevvifcycles = 0; +static u32* prevviftag = NULL; +u32 *vifptag; +int _chainVIF1() { + int id; + //int done=0; + int ret; + //g_vifCycles = prevvifcycles; + + vifptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR + if (vifptag == NULL) { //Is ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vifptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (vifptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif1ch->qwc = (u16)vifptag[0]; //QWC set to lower 16bits of the tag + vif1ch->madr = vifptag[1]; //MADR = ADDR field + g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vifptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); + + + + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + vifptag[1], vifptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + + //} else + + + if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1 + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) { + // stalled + + //SysPrintf("Vif1 Stalling %x, %x, DMA_CTRL = %x\n",vif1ch->madr, psHu32(DMAC_STADR), psHu32(DMAC_CTRL)); + /*prevvifcycles = g_vifCycles; + prevviftag = vifptag;*/ + hwDmacIrq(13); + vif1ch->tadr -= 16; + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return 2; + } + } + prevvifcycles = 0; + + if (vif1ch->chcr & 0x40) { + ret = VIF1transfer(vifptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + vif1.vifstalled = 1; + return vif1.done; //IRQ set by VIFTransfer + } + } +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + vifptag[1], vifptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif1ch, id); + ret = _VIF1chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + vif1.vifstalled = 1; + return vif1.done; + } + + + + vif1.vifstalled = 0; + + + + if ((vif1ch->chcr & 0x80) && (vifptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF1 TIE\n"); + //SysPrintf( "VIF1dmaIrq Set\n" ); + //vif1ch->qwc = 0; + //vif1Regs->stat|= VIF1_STAT_VIS; //Set the Tag Interrupt flag of VIF1_STAT + vif1.done = 1; + return vif1.done; //End Transfer + } + return vif1.done; //Return Done +} + +static int _vif1Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(vif1.vifstalled == 1) { + if(vif1.irq) { + vif1Regs->stat|= VIF1_STAT_INT; + hwIntcIrq(VIF1intc); + --vif1.irq; + } + + vif1Regs->stat&= ~0x1F000000; // FQC=0 + // One game doesnt like vif stalling at end, cant remember what. + if(vif1.done == 1 && vif1ch->qwc == 0 && vif1.irqoffset == 0) { + //SysPrintf("Vif1 Stall, done = 1 qwc = 0 irqoffset = %x, tell ref\n", vif1.irqoffset); + vif1.vifstalled = 0; + } else + return 1; + } + if (vif1ch->chcr & 0x4 && vif1.done == 0 && vif1.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif1 dma masked\n"); + return 0; + } + + g_vifCycles = 0; + + ret = _chainVIF1(); + INT(1, g_vifCycles); + return 0; + } + + + + + prevviftag = NULL; + prevvifcycles = 0; + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); + vif1Regs->stat&= ~0x1F000000; // FQC=0 + + return 1; +} + +int vif1Interrupt() { + + int ret; + + ret = _vif1Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF1() { + +#ifdef VIF_LOG + VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif1ch->chcr, vif1ch->madr, vif1ch->qwc, + vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); +#endif + + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + /* Check if there is a pending irq */ + /*if (vif1.irq > 0) { + vif1.irq--; + hwIntcIrq(VIF1intc); + return; + }*/ +// if(vif1ch->qwc > 0) { +// _VIF1chain(); +// INT(1, g_vifCycles); +// } + vif1.done = 0; + g_vifCycles = 0; + + /*if( prevvifcycles != 0 ) { + int stallret = 0; + assert( prevviftag != NULL ); + + vifptag = prevviftag; + // transfer interrupted, so continue + //_VIF1chain(); + _chainVIF1(); + + if (vif1ch->chcr & 0x80 && vifptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG("dmaIrq Set\n"); +#endif + vif1.done = 1; + INT(1, g_vifCycles); + return; + } + //vif1.done = 1; + INT(1, g_vifCycles); + return; + }*/ + + if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO + vifMFIFOInterrupt(); + return; + } + +#ifdef PCSX2_DEVBUILD + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 + //SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); + //return; + } +#endif + + + vif1Regs->stat|= 0x10000000; // FQC=16 + + if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { + SysPrintf("DMA Stall Control on VIF1 normal\n"); + } + if ((vif1ch->chcr & 0x1)) { // to Memory + if(_VIF1chain() == -2) { + SysPrintf("Stall on normal\n"); + vif1.vifstalled = 1; + return; + } + INT(1, g_vifCycles); + } else { // from Memory + + if( CHECK_MULTIGS ) { + u8* pTempMem, *pEndMem; + + u8* pMem = GSRingBufCopy(NULL, 0, GS_RINGTYPE_VIFFIFO); + assert( vif1ch->qwc < 0x10000 ); + *(u32*)(pMem-16) = GS_RINGTYPE_VIFFIFO|(vif1ch->qwc<<16); // hack + *(u32*)(pMem-12) = vif1ch->madr; + *(u32*)(pMem-8) = cpuRegs.cycle; + + // touch all the pages to make sure they are in memory + pTempMem = dmaGetAddr(vif1ch->madr); + pEndMem = (u8*)((u32)(pTempMem + vif1ch->qwc*16 + 0xfff)&~0xfff); + pTempMem = (u8*)((u32)pTempMem&~0xfff); + while(pTempMem < pEndMem ) { + pTempMem[0] = 0; + pTempMem += 0x1000; + } + + GSRINGBUF_DONECOPY(pMem, 0); + + if( !CHECK_DUALCORE ) + SetEvent(g_hGsEvent);//GS_SETEVENT(); + + // wait is, the safest option + } + else { + + int size; + u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) { //Is ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + vif1.done = 1; + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, g_vifCycles); + return; //Return -1 as an error has occurred + } + + if( GSreadFIFO2 == NULL ) { + for (size=vif1ch->qwc; size>0; --size) { + if (size > 1) GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, vif1ch->qwc); + + // set incase read + psHu64(0x5000) = pMem[2*vif1ch->qwc-2]; + psHu64(0x5008) = pMem[2*vif1ch->qwc-1]; + } + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, g_vifCycles); + } + } + vif1.done = 1; + return; + } + +/* if (_VIF1chain() != 0) { + INT(1, g_vifCycles); + return; + }*/ + + // Chain Mode + vif1.done = 0; + INT(1, g_vifCycles); +} + +void dmaVIF1() +{ + _dmaVIF1(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif1Write32(u32 mem, u32 value) { + if (mem == 0x10003c30) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF1_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF1_STAT and set mark with 'value' */ + vif1Regs->stat&= ~VIF1_STAT_MRK; + vif1Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF1_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif1 Reset\n"); + memset(&vif1, 0, sizeof(vif1)); + vif1ch->qwc = 0; //? + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->err = 0; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif1Regs->stat |= VIF1_STAT_VFS; + SysPrintf("vif1 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif1Regs->stat |= VIF1_STAT_VSS; + //SysPrintf("Vif1 Stop\n"); + //dmaVIF1(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + cancel = 1; + } + + vif1Regs->stat &= ~(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | + VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1); + if (cancel) { + //SysPrintf("VIF1 Stall Resume\n"); + if( vif1.vifstalled ) { + // loop necessary for spiderman + if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ + //vif1.vifstalled = 0; + //SysPrintf("MFIFO Stall\n"); + INT(10, g_vifCycles); + }else { + if ( _VIF1chain() != -2 ) + vif1.vifstalled = 0; + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + INT(1, g_vifCycles); // Gets the timing right - Flatout + } + } + } + } + } else + if (mem == 0x10003c20) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF1_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF1_ERR with 'value' */ + vif1Regs->err = value; + } else + if (mem == 0x10003c00) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF1_STAT write32 0x%8.8x\n", value); +#endif + +#ifdef PCSX2_DEVBUILD + /* Only FDR bit is writable, so mask the rest */ + if( (vif1Regs->stat & VIF1_STAT_FDR) ^ (value & VIF1_STAT_FDR) ) { + // different so can't be stalled + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + SysPrintf("changing dir when vif1 fifo stalled\n"); + } + } +#endif + + vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR); + if (vif1Regs->stat & VIF1_STAT_FDR) { + vif1Regs->stat|= 0x01000000; + } else { + vif1ch->qwc = 0; + vif1.vifstalled = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + } + else + if (mem == 0x10003c50) { // MODE + vif1Regs->mode = value; + } + else { + SysPrintf("Unknown Vif1 write to %x\n", mem); + if( mem >= 0x10003d00 && mem < 0x10003d80 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003d40) g_vifRow1[(mem>>4)&3] = value; + else g_vifCol1[(mem>>4)&3] = value; + } else psHu32(mem) = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif1Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif1, 0, sizeof(vif1)); + memset(vif1Regs, 0, sizeof(vif1Regs)); + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif1Freeze(gzFile f, int Mode) { + gzfreeze(&vif1, sizeof(vif1)); + if (Mode == 0) + SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); + + return 0; +} diff --git a/branches/pcsx2_0.9.2/VifDma.h b/branches/pcsx2_0.9.2/VifDma.h new file mode 100644 index 0000000..65570a0 --- /dev/null +++ b/branches/pcsx2_0.9.2/VifDma.h @@ -0,0 +1,164 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIFDMA_H__ +#define __VIFDMA_H__ + +typedef struct { + int addr; + int size; + int cmd; + u16 wl; + u16 cl; +} vifCode; + +// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito +typedef struct { + vifCode tag; + int cmd; + int irq; + int cl; + int wl; + u8 usn; + u8 done; + u8 vifstalled; + u8 irqoffset; // 32bit offset where next vif code is + u32 savedtag; +} vifStruct; + +extern vifStruct vif0, vif1; + +#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000]) +#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000]) + +void UNPACK_S_32( u32 *dest, u32 *data ); +int UNPACK_S_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_S_16u( u32 *dest, u32 *data ); +int UNPACK_S_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_16s( u32 *dest, u32 *data ); +int UNPACK_S_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_S_8u( u32 *dest, u32 *data ); +int UNPACK_S_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_8s( u32 *dest, u32 *data ); +int UNPACK_S_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_32( u32 *dest, u32 *data ); +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_16u( u32 *dest, u32 *data ); +int UNPACK_V2_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_16s( u32 *dest, u32 *data ); +int UNPACK_V2_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_8u( u32 *dest, u32 *data ); +int UNPACK_V2_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_8s( u32 *dest, u32 *data ); +int UNPACK_V2_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_32( u32 *dest, u32 *data ); +int UNPACK_V3_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_16u( u32 *dest, u32 *data ); +int UNPACK_V3_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_16s( u32 *dest, u32 *data ); +int UNPACK_V3_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_8u( u32 *dest, u32 *data ); +int UNPACK_V3_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_8s( u32 *dest, u32 *data ); +int UNPACK_V3_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_32( u32 *dest, u32 *data ); +int UNPACK_V4_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_16u( u32 *dest, u32 *data ); +int UNPACK_V4_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_16s( u32 *dest, u32 *data ); +int UNPACK_V4_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_8u( u32 *dest, u32 *data ); +int UNPACK_V4_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_8s( u32 *dest, u32 *data ); +int UNPACK_V4_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_5( u32 *dest, u32 *data ); +int UNPACK_V4_5part( u32 *dest, u32 *data, int size ); +extern void (*Vif0CMDTLB[75])(); // VIF0 CMD Table +extern int (*Vif0TransTLB[128])(); // VIF0 Transfer Data Table +int Vif0TransNull(u32 *data, int size); //Shouldnt Go Here +int Vif0TransSTMask(u32 *data, int size); //STCOL +int Vif0TransSTRow(u32 *data, int size); //STCOL +int Vif0TransSTCol(u32 *data, int size); //STCOL +int Vif0TransMPG(u32 *data, int size); // MPG +int Vif0TransUnpack(u32 *data, int size); // UNPACK +void Vif0CMDNop(); // NOP +void Vif0CMDSTCycl(); // STCYCL +void Vif0CMDITop(); // ITOP +void Vif0CMDSTMod(); // STMOD +void Vif0CMDMark(); // MARK +void Vif0CMDFlushE(); // FLUSHE +void Vif0CMDMSCALF(); //MSCAL/F +void Vif0CMDMSCNT(); // MSCNT +void Vif0CMDSTMask(); // STMASK +void Vif0CMDSTRowCol();// STROW / STCOL +void Vif0CMDMPGTransfer(); // MPG +void Vif0CMDNull(); // invalid opcode + + +extern void (*Vif1CMDTLB[82])(); // VIF1 CMD Table +extern int (*Vif1TransTLB[128])(); // VIF1 Transfer Data Table +int Vif1TransNull(u32 *data, int size); //Shouldnt Go Here +int Vif1TransSTMask(u32 *data, int size); //STCOL +int Vif1TransSTRow(u32 *data, int size); //STCOL +int Vif1TransSTCol(u32 *data, int size); //STCOL +int Vif1TransMPG(u32 *data, int size); // MPG +int Vif1TransDirectHL(u32 *data, int size); // DIRECT/HL +int Vif1TransUnpack(u32 *data, int size); // UNPACK +void Vif1CMDNop(); // NOP +void Vif1CMDSTCycl(); // STCYCL +void Vif1CMDOffset(); // OFFSET +void Vif1CMDBase(); // BASE +void Vif1CMDITop(); // ITOP +void Vif1CMDSTMod(); // STMOD +void Vif1CMDMskPath3(); // MSKPATH3 +void Vif1CMDMark(); // MARK +void Vif1CMDFlush(); // FLUSH/E/A +void Vif1CMDMSCALF(); //MSCAL/F +void Vif1CMDMSCNT(); // MSCNT +void Vif1CMDSTMask(); // STMASK +void Vif1CMDSTRowCol();// STROW / STCOL +void Vif1CMDMPGTransfer(); // MPG +void Vif1CMDDirectHL(); // DIRECT/HL +void Vif1CMDNull(); // invalid opcode + +void vifDmaInit(); +void vif0Init(); +void vif1Init(); +int vif0Interrupt(); +int vif1Interrupt(); + +void vif0Write32(u32 mem, u32 value); +void vif1Write32(u32 mem, u32 value); + +void vif0Reset(); +void vif1Reset(); +int vif0Freeze(gzFile f, int Mode); +int vif1Freeze(gzFile f, int Mode); + +#endif diff --git a/branches/pcsx2_0.9.2/cheatscpp.h b/branches/pcsx2_0.9.2/cheatscpp.h new file mode 100644 index 0000000..0918189 --- /dev/null +++ b/branches/pcsx2_0.9.2/cheatscpp.h @@ -0,0 +1,31 @@ +#ifndef CHEATSCPP_H_INCLUDED +#define CHEATSCPP_H_INCLUDED + +class Group +{ +public: + string title; + bool enabled; + int parentIndex; + + Group(int nParent,bool nEnabled, string &nTitle); + +}; + +class Patch +{ +public: + string title; + int group; + bool enabled; + int patchIndex; + + Patch(int patch, int grp, bool en, string &ttl); + + Patch operator =(const Patch&p); +}; + +extern vector groups; +extern vector patches; + +#endif//CHEATSCPP_H_INCLUDED diff --git a/branches/pcsx2_0.9.2/configure.ac b/branches/pcsx2_0.9.2/configure.ac new file mode 100644 index 0000000..f202376 --- /dev/null +++ b/branches/pcsx2_0.9.2/configure.ac @@ -0,0 +1,91 @@ +AC_INIT(pcsx2,0.9.2,zerofrog@gmail.com) + +AM_INIT_AUTOMAKE(pcsx2,0.9.2) + +AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) + +AC_PROG_RANLIB + +dnl Check for debug build +AC_MSG_CHECKING(debug build) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), + debug=$enableval,debug=no) +if test "x$debug" == xyes +then + AC_DEFINE(_DEBUG,1,[_DEBUG]) + CFLAGS="-g " + CPPFLAGS="-g " + CXXFLAGS="-g " +else + CFLAGS="-O2 -fomit-frame-pointer " + CPPFLAGS="-O2 -fomit-frame-pointer " + CXXFLAGS="-O2 -fomit-frame-pointer " +fi +AC_MSG_RESULT($debug) + +dnl CFLAGS+="-masm=intel " +dnl CPPFLAGS="-masm=intel " +dnl CXXFLAGS="-masm=intel " + +AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) + +dnl Check for dev build +AC_MSG_CHECKING(for development build) +AC_ARG_ENABLE(devbuild, AC_HELP_STRING([--enable-devbuild], [Special Build for developers that simplifies testing and adds extra checks]), + devbuild=$enableval,devbuild=no) +if test "x$devbuild" == xyes +then + AC_DEFINE(PCSX2_DEVBUILD,1,[PCSX2_DEVBUILD]) +fi +AC_MSG_RESULT($devbuild) + +dnl Check for 64bit CPU +AC_MSG_CHECKING(for a x86-64 CPU) +dnl if test "$build_os" == "target_os" +dnl then +AC_TRY_RUN([ +int main() +{ +int a = 0; +int*pa = &a; +asm("mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + : : "r"(pa) : "%rax"); +return 0; +} +],cpu64=yes,cpu64=no,) +dnl else +dnl cpu64=no +dnl fi +if test "x$cpu64" == xyes +then +AC_DEFINE(__x86_64__,1,[__x86_64__]) +fi +AC_MSG_RESULT($cpu64) +AM_CONDITIONAL(X86_64, test x$cpu64 = xyes) + +AC_OUTPUT([ + Makefile + DebugTools/Makefile + Linux/Makefile + IPU/Makefile + IPU/mpeg2lib/Makefile + pcl/Makefile + RDebug/Makefile + tinyxml/Makefile + x86/Makefile + x86/ix86/Makefile + x86/ix86-32/Makefile + x86/ix86-64/Makefile + zlib/Makefile + ]) + +bindir = pcsx2exe + +echo "Configuration:" +echo " Target system type: $target" +echo " x86-64 build? $cpu64" +echo " Debug build? $debug" +echo " Dev build? $devbuild" \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/depcomp b/branches/pcsx2_0.9.2/depcomp new file mode 100644 index 0000000..88b3a13 --- /dev/null +++ b/branches/pcsx2_0.9.2/depcomp @@ -0,0 +1,529 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/branches/pcsx2_0.9.2/install-sh b/branches/pcsx2_0.9.2/install-sh new file mode 100644 index 0000000..4d4a951 --- /dev/null +++ b/branches/pcsx2_0.9.2/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/branches/pcsx2_0.9.2/memcpy_amd.cpp b/branches/pcsx2_0.9.2/memcpy_amd.cpp new file mode 100644 index 0000000..60b1bde --- /dev/null +++ b/branches/pcsx2_0.9.2/memcpy_amd.cpp @@ -0,0 +1,612 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +//#include + +// Inline assembly syntax for use with Visual C++ +extern "C" { + +#ifdef __WIN32__ +#include +#endif + +#include "PS2Etypes.h" +#include "Misc.h" + +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeMMXRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeMMXRegs_(save); } +#define FreezeXMMRegs(save) if( g_EEFreezeRegs && CHECK_EEREC ) { FreezeXMMRegs_(save); } + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalMMXSaved; + +void checkregs() +{ + assert( !g_globalMMXLocked || g_globalMMXSaved ); +} +#endif + +#ifdef _MSC_VER + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + FreezeMMXRegs(1); + +#ifdef _DEBUG + __asm call checkregs +#endif + + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + push esi + mov ecx, cmpsize + mov edx, src1 + mov esi, src2 + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je ContinueTest + mov eax, 1 + jmp End + + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pcmpeqd mm4, [edx+32] + pand mm0, mm2 + pcmpeqd mm5, [edx+40] + pand mm0, mm3 + pcmpeqd mm6, [edx+48] + pand mm0, mm4 + pcmpeqd mm7, [edx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edx, 64 +ContinueTest: + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je Done4 + mov eax, 1 + jmp End + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov esi, [esi+4] + cmp eax, [edx] + je Next + mov eax, 1 + jmp End + +Next: + cmp esi, [edx+4] + setne al + jmp End + +Done: + xor eax, eax + +End: + pop esi + emms + } +} + + +// returns the xor of all elements, cmpsize has to be mult of 8 +void memxor_mmx(void* dst, const void* src1, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov eax, src1 + mov ebx, ecx + mov edx, dst + + cmp ecx, 64 + jl Setup4 + + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + movq mm4, [eax+32] + movq mm5, [eax+40] + movq mm6, [eax+48] + movq mm7, [eax+56] + sub ecx, 64 + add eax, 64 + cmp ecx, 64 + jl End8 + +Cmp8: + pxor mm0, [eax] + pxor mm1, [eax+8] + pxor mm2, [eax+16] + pxor mm3, [eax+24] + pxor mm4, [eax+32] + pxor mm5, [eax+40] + pxor mm6, [eax+48] + pxor mm7, [eax+56] + + sub ecx, 64 + add eax, 64 + cmp ecx, 64 + jge Cmp8 + +End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp ecx, 32 + jl End4 + pxor mm0, [eax] + pxor mm1, [eax+8] + pxor mm2, [eax+16] + pxor mm3, [eax+24] + sub ecx, 32 + add eax, 32 + jmp End4 + +Setup4: + cmp ecx, 32 + jl Setup2 + + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + sub ecx, 32 + add eax, 32 + +End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp ecx, 16 + jl End2 + pxor mm0, [eax] + pxor mm1, [eax+8] + sub ecx, 16 + add eax, 16 + jmp End2 + +Setup2: + cmp ecx, 16 + jl Setup1 + + movq mm0, [eax] + movq mm1, [eax+8] + sub ecx, 16 + add eax, 16 + +End2: + pxor mm0, mm1 + + cmp ecx, 8 + jl End1 + pxor mm0, [eax] +End1: + movq [edx], mm0 + jmp End + +Setup1: + movq mm0, [eax] + movq [edx], mm0 +End: + emms + } +} + +#else +// assume gcc or mingw + +#include +#include + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ +memcpy(dest, src, n); +return dest; +} + + +#endif + +} diff --git a/branches/pcsx2_0.9.2/missing b/branches/pcsx2_0.9.2/missing new file mode 100644 index 0000000..894e786 --- /dev/null +++ b/branches/pcsx2_0.9.2/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/branches/pcsx2_0.9.2/mkinstalldirs b/branches/pcsx2_0.9.2/mkinstalldirs new file mode 100644 index 0000000..259dbfc --- /dev/null +++ b/branches/pcsx2_0.9.2/mkinstalldirs @@ -0,0 +1,158 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2005-06-29.22 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/branches/pcsx2_0.9.2/pcl/Makefile.am b/branches/pcsx2_0.9.2/pcl/Makefile.am new file mode 100644 index 0000000..030c434 --- /dev/null +++ b/branches/pcsx2_0.9.2/pcl/Makefile.am @@ -0,0 +1,3 @@ +noinst_LIBRARIES = libpcl.a + +libpcl_a_SOURCES = pcl.c pcl_config.h pcl.h diff --git a/branches/pcsx2_0.9.2/pcl/pcl.c b/branches/pcsx2_0.9.2/pcl/pcl.c new file mode 100644 index 0000000..b878266 --- /dev/null +++ b/branches/pcsx2_0.9.2/pcl/pcl.c @@ -0,0 +1,507 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#include +#include +#include "pcl_config.h" +#include "pcl.h" + +#if defined(CO_USE_UCONEXT) +#include + +typedef ucontext_t co_core_ctx_t; +#else +#include + +typedef jmp_buf co_core_ctx_t; +#endif + +#if defined(CO_USE_SIGCONTEXT) +#include +#endif + + +/* + * The following value must be power of two ( N^2 ). + */ +#define CO_STK_ALIGN 256 +#define CO_STK_COROSIZE ((sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1)) +#define CO_MIN_SIZE (4 * 1024) + + +typedef struct s_co_ctx { + co_core_ctx_t cc; +} co_ctx_t; + +typedef struct s_coroutine { + co_ctx_t ctx; + int alloc; + struct s_coroutine *caller; + struct s_coroutine *restarget; + void (*func)(void *); + void *data; +} coroutine; + + +static coroutine co_main; +static coroutine *co_curr = &co_main; +static coroutine *co_dhelper; + +#if defined(CO_USE_SIGCONTEXT) + +static volatile int ctx_called; +static co_ctx_t *ctx_creating; +static void *ctx_creating_func; +static sigset_t ctx_creating_sigs; +static co_ctx_t ctx_trampoline; +static co_ctx_t ctx_caller; + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + + +static int co_ctx_sdir(unsigned long psp) { + int nav = 0; + unsigned long csp = (unsigned long) &nav; + + return psp > csp ? -1: +1; +} + + +static int co_ctx_stackdir(void) { + int cav = 0; + + return co_ctx_sdir((unsigned long) &cav); +} + + +#if defined(CO_USE_UCONEXT) + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + + if (getcontext(&ctx->cc)) + return -1; + + ctx->cc.uc_link = NULL; + + ctx->cc.uc_stack.ss_sp = stkbase; + ctx->cc.uc_stack.ss_size = stksiz - sizeof(long); + ctx->cc.uc_stack.ss_flags = 0; + + makecontext(&ctx->cc, func, 1); + + return 0; +} + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (swapcontext(&octx->cc, &nctx->cc) < 0) { + fprintf(stderr, "[PCL] Context switch failed: curr=%p\n", + co_curr); + exit(1); + } +} + +#else /* #if defined(CO_USE_UCONEXT) */ + +#if defined(CO_USE_SIGCONTEXT) + +/* + * This code comes from the GNU Pth implementation and uses the + * sigstack/sigaltstack() trick. + * + * The ingenious fact is that this variant runs really on _all_ POSIX + * compliant systems without special platform kludges. But be _VERY_ + * carefully when you change something in the following code. The slightest + * change or reordering can lead to horribly broken code. Really every + * function call in the following case is intended to be how it is, doubt + * me... + * + * For more details we strongly recommend you to read the companion + * paper ``Portable Multithreading -- The Signal Stack Trick for + * User-Space Thread Creation'' from Ralf S. Engelschall. + */ + +static void co_ctx_bootstrap(void) { + co_ctx_t * volatile ctx_starting; + void (* volatile ctx_starting_func)(void); + + /* + * Switch to the final signal mask (inherited from parent) + */ + sigprocmask(SIG_SETMASK, &ctx_creating_sigs, NULL); + + /* + * Move startup details from static storage to local auto + * variables which is necessary because it has to survive in + * a local context until the thread is scheduled for real. + */ + ctx_starting = ctx_creating; + ctx_starting_func = (void (*)(void)) ctx_creating_func; + + /* + * Save current machine state (on new stack) and + * go back to caller until we're scheduled for real... + */ + if (!setjmp(ctx_starting->cc)) + longjmp(ctx_caller.cc, 1); + + /* + * The new thread is now running: GREAT! + * Now we just invoke its init function.... + */ + ctx_starting_func(); + + fprintf(stderr, "[PCL] Hmm, you really shouldn't reach this point: curr=%p\n", + co_curr); + exit(1); +} + + +static void co_ctx_trampoline(int sig) { + /* + * Save current machine state and _immediately_ go back with + * a standard "return" (to stop the signal handler situation) + * to let him remove the stack again. Notice that we really + * have do a normal "return" here, or the OS would consider + * the thread to be running on a signal stack which isn't + * good (for instance it wouldn't allow us to spawn a thread + * from within a thread, etc.) + */ + if (!setjmp(ctx_trampoline.cc)) { + ctx_called = 1; + return; + } + + /* + * Ok, the caller has longjmp'ed back to us, so now prepare + * us for the real machine state switching. We have to jump + * into another function here to get a new stack context for + * the auto variables (which have to be auto-variables + * because the start of the thread happens later). + */ + co_ctx_bootstrap(); +} + + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + struct sigaction sa; + struct sigaction osa; + sigset_t osigs; + sigset_t sigs; +#if defined(CO_HAS_SIGSTACK) + struct sigstack ss; + struct sigstack oss; +#elif defined(CO_HAS_SIGALTSTACK) + struct sigaltstack ss; + struct sigaltstack oss; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Preserve the SIGUSR1 signal state, block SIGUSR1, + * and establish our signal handler. The signal will + * later transfer control onto the signal stack. + */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGUSR1); + sigprocmask(SIG_BLOCK, &sigs, &osigs); + sa.sa_handler = co_ctx_trampoline; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_ONSTACK; + if (sigaction(SIGUSR1, &sa, &osa) != 0) + return -1; + + /* + * Set the new stack. + * + * For sigaltstack we're lucky [from sigaltstack(2) on + * FreeBSD 3.1]: ``Signal stacks are automatically adjusted + * for the direction of stack growth and alignment + * requirements'' + * + * For sigstack we have to decide ourself [from sigstack(2) + * on Solaris 2.6]: ``The direction of stack growth is not + * indicated in the historical definition of struct sigstack. + * The only way to portably establish a stack pointer is for + * the application to determine stack growth direction.'' + */ +#if defined(CO_HAS_SIGALTSTACK) + ss.ss_sp = stkbase; + ss.ss_size = stksiz - sizeof(long); + ss.ss_flags = 0; + if (sigaltstack(&ss, &oss) < 0) + return -1; +#elif defined(CO_HAS_SIGSTACK) + if (co_ctx_stackdir() < 0) + ss.ss_sp = (stkbase + stksiz - sizeof(long)); + else + ss.ss_sp = stkbase; + ss.ss_onstack = 0; + if (sigstack(&ss, &oss) < 0) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Now transfer control onto the signal stack and set it up. + * It will return immediately via "return" after the setjmp() + * was performed. Be careful here with race conditions. The + * signal can be delivered the first time sigsuspend() is + * called. + */ + ctx_called = 0; + kill(getpid(), SIGUSR1); + sigfillset(&sigs); + sigdelset(&sigs, SIGUSR1); + while (!ctx_called) + sigsuspend(&sigs); + + /* + * Inform the system that we are back off the signal stack by + * removing the alternative signal stack. Be careful here: It + * first has to be disabled, before it can be removed. + */ +#if defined(CO_HAS_SIGALTSTACK) + sigaltstack(NULL, &ss); + ss.ss_flags = SS_DISABLE; + if (sigaltstack(&ss, NULL) < 0) + return -1; + sigaltstack(NULL, &ss); + if (!(ss.ss_flags & SS_DISABLE)) + return -1; + if (!(oss.ss_flags & SS_DISABLE)) + sigaltstack(&oss, NULL); +#elif defined(CO_HAS_SIGSTACK) + if (sigstack(&oss, NULL)) + return -1; +#else +#error "PCL: Unknown context stack type" +#endif + + /* + * Restore the old SIGUSR1 signal handler and mask + */ + sigaction(SIGUSR1, &osa, NULL); + sigprocmask(SIG_SETMASK, &osigs, NULL); + + /* + * Set creation information. + */ + ctx_creating = ctx; + ctx_creating_func = func; + memcpy(&ctx_creating_sigs, &osigs, sizeof(sigset_t)); + + /* + * Now enter the trampoline again, but this time not as a signal + * handler. Instead we jump into it directly. + */ + if (!setjmp(ctx_caller.cc)) + longjmp(ctx_trampoline.cc, 1); + + return 0; +} + +#else /* #if defined(CO_USE_SIGCONTEXT) */ + +static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { + char *stack; + + stack = stkbase + stksiz - sizeof(long); + + setjmp(ctx->cc); + +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(JB_PC) && defined(JB_SP) + ctx->cc[0].__jmpbuf[JB_PC] = (int) func; + ctx->cc[0].__jmpbuf[JB_SP] = (int) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && defined(__mc68000__) + ctx->cc[0].__jmpbuf[0].__aregs[0] = (long) func; + ctx->cc[0].__jmpbuf[0].__sp = (int *) stack; +#elif defined(__GNU_LIBRARY__) && defined(__i386__) + ctx->cc[0].__jmpbuf[0].__pc = func; + ctx->cc[0].__jmpbuf[0].__sp = stack; +#elif defined(_WIN32) && defined(_MSC_VER) + ((_JUMP_BUFFER *) &ctx->cc)->Eip = (long) func; + ((_JUMP_BUFFER *) &ctx->cc)->Esp = (long) stack; +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 0 && (defined(__powerpc64__) || defined(__powerpc__)) + ctx->cc[0].__jmpbuf[JB_LR] = (int) func; + ctx->cc[0].__jmpbuf[JB_GPR1] = (int) stack; +#else + + // automatically assume windows/x86 (cygwin) +typedef struct __JUMP_BUFFER { + unsigned long Ebp; + unsigned long Ebx; + unsigned long Edi; + unsigned long Esi; + unsigned long Esp; + unsigned long Eip; + unsigned long Registration; + unsigned long TryLevel; + unsigned long Cookie; + unsigned long UnwindFunc; + unsigned long UnwindData[6]; +} _JUMP_BUFFER; + + ((_JUMP_BUFFER *) &ctx->cc)->Eip = (long) func; + ((_JUMP_BUFFER *) &ctx->cc)->Esp = (long) stack; +#warning "PCL: Unsupported setjmp/longjmp platform. Please report to " +#endif + + return 0; +} + +#endif /* #if defined(CO_USE_SIGCONTEXT) */ + + +static void co_switch_context(co_ctx_t *octx, co_ctx_t *nctx) { + + if (!setjmp(octx->cc)) + longjmp(nctx->cc, 1); +} + +#endif /* #if defined(CO_USE_UCONEXT) */ + + +static void co_runner(void) { + coroutine *co = co_curr; + + co->restarget = co->caller; + co->func(co->data); + co_exit(); +} + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size) { + int alloc = 0, r = CO_STK_COROSIZE; + coroutine *co; + + if ((size &= ~(sizeof(long) - 1)) < CO_MIN_SIZE) + return NULL; + if (!stack) { + size = (size + sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1); + stack = malloc(size); + if (!stack) + return NULL; + alloc = size; + } + co = stack; + stack = (char *) stack + CO_STK_COROSIZE; + co->alloc = alloc; + co->func = func; + co->data = data; + if (co_set_context(&co->ctx, co_runner, stack, size - CO_STK_COROSIZE) < 0) { + if (alloc) + free(co); + return NULL; + } + + return (coroutine_t) co; +} + + +void co_delete(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + + if (co == co_curr) { + fprintf(stderr, "[PCL] Cannot delete itself: curr=%p\n", + co_curr); + exit(1); + } + if (co->alloc) + free(co); +} + + +void co_call(coroutine_t coro) { + coroutine *co = (coroutine *) coro, *oldco = co_curr; + + co->caller = co_curr; + co_curr = co; + + co_switch_context(&oldco->ctx, &co->ctx); +} + + +void co_resume(void) { + + co_call(co_curr->restarget); + co_curr->restarget = co_curr->caller; +} + + +static void co_del_helper(void *data) { + coroutine *cdh; + + for (;;) { + cdh = co_dhelper; + co_dhelper = NULL; + co_delete(co_curr->caller); + co_call((coroutine_t) cdh); + if (!co_dhelper) { + fprintf(stderr, "[PCL] Resume to delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + } +} + + +void co_exit_to(coroutine_t coro) { + coroutine *co = (coroutine *) coro; + static coroutine *dchelper = NULL; + static char stk[CO_MIN_SIZE]; + + if (!dchelper && + !(dchelper = co_create(co_del_helper, NULL, stk, sizeof(stk)))) { + fprintf(stderr, "[PCL] Unable to create delete helper coroutine: curr=%p\n", + co_curr); + exit(1); + } + + co_dhelper = co; + + co_call((coroutine_t) dchelper); + + fprintf(stderr, "[PCL] Stale coroutine called: curr=%p\n", + co_curr); + exit(1); +} + + +void co_exit(void) { + + co_exit_to((coroutine_t) co_curr->restarget); +} + + +coroutine_t co_current(void) { + + return (coroutine_t) co_curr; +} + diff --git a/branches/pcsx2_0.9.2/pcl/pcl.h b/branches/pcsx2_0.9.2/pcl/pcl.h new file mode 100644 index 0000000..122112e --- /dev/null +++ b/branches/pcsx2_0.9.2/pcl/pcl.h @@ -0,0 +1,49 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_H) +#define PCL_H + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef void *coroutine_t; + + +coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size); +void co_delete(coroutine_t coro); +void co_call(coroutine_t coro); +void co_resume(void); +void co_exit_to(coroutine_t coro); +void co_exit(void); +coroutine_t co_current(void); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/branches/pcsx2_0.9.2/pcl/pcl_config.h b/branches/pcsx2_0.9.2/pcl/pcl_config.h new file mode 100644 index 0000000..9c37c64 --- /dev/null +++ b/branches/pcsx2_0.9.2/pcl/pcl_config.h @@ -0,0 +1,60 @@ +/* + * PCL by Davide Libenzi ( Portable Coroutine Library ) + * Copyright (C) 2003 Davide Libenzi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Davide Libenzi + * + */ + +#if !defined(PCL_CONFIG_H) +#define PCL_CONFIG_H + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif /* #if defined(HAVE_CONFIG_H) */ + + +#if defined(HAVE_GETCONTEXT) && defined(HAVE_MAKECONTEXT) && defined(HAVE_SWAPCONTEXT) + +/* + * Use this if the system has a working getcontext/makecontext/swapcontext + * implementation. + */ +#define CO_USE_UCONEXT + +#elif defined(HAVE_SIGACTION) + +/* + * Use this to have the generic signal implementation ( not working on + * Windows ). Suggested on generic Unix implementations or on Linux with + * CPU different from x86 family. + */ +#define CO_USE_SIGCONTEXT + +/* + * Use this in conjuction with CO_USE_SIGCONTEXT to use the sigaltstack + * environment ( suggested when CO_USE_SIGCONTEXT is defined ). + */ +#if defined(HAVE_SIGALTSTACK) +#define CO_HAS_SIGALTSTACK +#endif + +#endif + + +#endif + diff --git a/branches/pcsx2_0.9.2/pcsxAbout.bmp b/branches/pcsx2_0.9.2/pcsxAbout.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da33bb08f4a3c365d835b0972a7dfbc43f8b01a2 GIT binary patch literal 251192 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
#6CXrR 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%0A&bFGJ^?ZxKwaSay%~z|BlTbA{G+_QCqA8wMysG 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 yT^R{P!VvN=U0F-&j(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, '\0' }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/branches/pcsx2_0.9.2/tinyxml/tinystr.h b/branches/pcsx2_0.9.2/tinyxml/tinystr.h new file mode 100644 index 0000000..3c2aa9d --- /dev/null +++ b/branches/pcsx2_0.9.2/tinyxml/tinystr.h @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/branches/pcsx2_0.9.2/tinyxml/tinyxml.cpp b/branches/pcsx2_0.9.2/tinyxml/tinyxml.cpp new file mode 100644 index 0000000..1bd61cd --- /dev/null +++ b/branches/pcsx2_0.9.2/tinyxml/tinyxml.cpp @@ -0,0 +1,1866 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + + +bool TiXmlBase::condenseWhiteSpace = true; + +void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + return 0; + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return &node->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const char* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s ); + } + else { + *i = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const std::string* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s->c_str() ); + } + else { + *i = 0; + } + } + return s; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const char* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s ); + } + else { + *d = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const std::string* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s->c_str() ); + } + else { + *d = 0; + } + } + return s; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); + #else + sprintf( buf, "%d", val ); + #endif + SetAttribute( name, buf ); +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + std::ostringstream oss; + oss << val; + SetAttribute( name, oss.str() ); +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); + #else + sprintf( buf, "%f", val ); + #endif + SetAttribute( name, buf ); +} + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING _name( cname ); + TIXML_STRING _value( cvalue ); + #else + const char* _name = cname; + const char* _value = cvalue; + #endif + + TiXmlAttribute* node = attributeSet.Find( _name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + // See STL_STRING_BUG below. + //StringToBuffer buf( value ); + + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + // See STL_STRING_BUG below. +// StringToBuffer buf( value ); +// +// if ( buf.buffer && SaveFile( buf.buffer ) ) +// return true; +// +// return false; + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // Add an extra string to avoid the crash. + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = fopen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length == 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + const char* lastPos = buf; + const char* p = buf; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + if ( *p == 0xa ) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append( lastPos, (p-lastPos+1) ); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert( p <= (buf+length) ); + } + else if ( *p == 0xd ) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ( (p-lastPos) > 0 ) { + data.append( lastPos, p-lastPos ); // do not add the CR + } + data += (char)0xa; // a proper newline + + if ( *(p+1) == 0xa ) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert( p <= (buf+length) ); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert( p <= (buf+length) ); + } + } + else { + ++p; + } + } + // Handle any left over characters. + if ( p-lastPos ) { + data.append( lastPos, p-lastPos ); + } + delete [] buf; + buf = 0; + + Parse( data.c_str(), 0, encoding ); + + if ( Error() ) + return false; + else + return true; +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = fopen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorDesc = errorDesc.c_str (); + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + PutString( name, &n ); + PutString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( sscanf( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); + #else + sprintf (buf, "%lf", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + PutString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} +*/ +#endif + + +const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} +*/ + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + buffer += text.Value(); + } + else + { + DoIndent(); + buffer += text.Value(); + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/branches/pcsx2_0.9.2/tinyxml/tinyxml.h b/branches/pcsx2_0.9.2/tinyxml/tinyxml.h new file mode 100644 index 0000000..5391236 --- /dev/null +++ b/branches/pcsx2_0.9.2/tinyxml/tinyxml.h @@ -0,0 +1,1776 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 2; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simple called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& doc ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& doc ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& element ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& declaration ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& text ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& comment ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& unknown ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Puts a string to a stream, expanding entities as it goes. + // Note this should not contian the '<', '>', etc, or they will be transformed into entities! + static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + + #endif + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + #ifdef TIXML_USE_STL + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + TiXmlDocument* doc = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + p = ReadText( p, &value, false, endTag, false, encoding ); + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + +// int tabsize = 4; +// if ( document ) +// tabsize = document->TabSize(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i +#include +#include +#include +#include +using namespace std; + +#include "tinyxml.h" + +extern "C" { +# include "../ps2etypes.h" +# include "../patch.h" + +# ifdef __WIN32__ + struct AppData { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; + } extern gApp; +# endif + + void SysPrintf(char *fmt, ...); + int LoadPatch(char *patchfile); +} + +#include "../cheatscpp.h" + +int LoadGroup(TiXmlNode *group, int parent); + +Group::Group(int nParent,bool nEnabled, string &nTitle): + parentIndex(nParent),enabled(nEnabled),title(nTitle) +{ +} + +Patch::Patch(int patch, int grp, bool en, string &ttl): + title(ttl), + group(grp), + enabled(en), + patchIndex(patch) +{ +} + +Patch Patch::operator =(const Patch&p) +{ + title.assign(p.title); + group=p.group; + enabled=p.enabled; + patchIndex=p.patchIndex; + return *this; +} + + +vector groups; +vector patches; + +int LoadPatch(char *crc) +{ + char pfile[256]; + sprintf(pfile,"patches\\%s.xml",crc); + + patchnumber=0; + + TiXmlDocument doc( pfile ); + bool loadOkay = doc.LoadFile(); + if ( !loadOkay ) + { + SysPrintf("XML Patch Loader: Could not load file '%s'. Error='%s'.\n", pfile, doc.ErrorDesc() ); + return -1; + } + + TiXmlNode *root = doc.FirstChild("GAME"); + if(!root) + { + SysPrintf("XML Patch Loader: Root node is not GAME, invalid patch file.\n"); + return -1; + } + + TiXmlElement *rootelement = root->ToElement(); + + const char *title=rootelement->Attribute("title"); + if(title) + SysPrintf("XML Patch Loader: Game Title: %s\n",title); + + int result=LoadGroup(root,-1); + if(result) { + patchnumber=0; + return result; + } + +#ifdef __WIN32__ + if (gApp.hConsole) + { + if(title) + SetConsoleTitle(title); + else + SetConsoleTitle(""); + } + +#endif + + return 0; +} + + +int LoadGroup(TiXmlNode *group,int gParent) +{ + + TiXmlElement *groupelement = group->ToElement(); + + const char *gtitle=groupelement->Attribute("title"); + if(gtitle) + SysPrintf("XML Patch Loader: Group Title: %s\n",gtitle); + + const char *enable=groupelement->Attribute("enabled"); + bool gEnabled=true; + if(enable) + { + if(strcmp(enable,"false")==0) + { + SysPrintf("XML Patch Loader: Group is disabled.\n"); + gEnabled=false; + } + } + + TiXmlNode *comment = group->FirstChild("COMMENT"); + if(comment) + { + TiXmlElement *cmelement = comment->ToElement(); + const char *comment = cmelement->GetText(); + if(comment) + SysPrintf("XML Patch Loader: Group Comment:\n%s\n---\n",comment); + } + + string t; + + if(gtitle) + t.assign(gtitle); + else + t.clear(); + + Group gp=Group(gParent,gEnabled,t); + groups.push_back(gp); + + int gIndex=groups.size()-1; + + + TiXmlNode *fastmemory=group->FirstChild("FASTMEMORY"); + if(fastmemory!=NULL) + SetFastMemory(1); + + TiXmlNode *roundmode=group->FirstChild("ROUNDMODE"); + if(roundmode!=NULL) + { + int eetype=0x0000; + int vutype=0x6000; + + TiXmlElement *rm=roundmode->ToElement(); + if(rm!=NULL) + { + const char *eetext=rm->Attribute("ee"); + const char *vutext=rm->Attribute("vu"); + + if(eetext != NULL) { + eetype = 0xffff; + if( stricmp(eetext, "near") == 0 ) { + eetype = 0x0000; + } + else if( stricmp(eetext, "down") == 0 ) { + eetype = 0x2000; + } + else if( stricmp(eetext, "up") == 0 ) { + eetype = 0x4000; + } + else if( stricmp(eetext, "chop") == 0 ) { + eetype = 0x6000; + } + } + + if(vutext != NULL) { + vutype = 0xffff; + if( stricmp(vutext, "near") == 0 ) { + vutype = 0x0000; + } + else if( stricmp(vutext, "down") == 0 ) { + vutype = 0x2000; + } + else if( stricmp(vutext, "up") == 0 ) { + vutype = 0x4000; + } + else if( stricmp(vutext, "chop") == 0 ) { + vutype = 0x6000; + } + } + } + if(( eetype == 0xffff )||( vutype == 0xffff )) { + printf("XML Patch Loader: WARNING: Invalid value in ROUNDMODE.\n"); + } + else { + SetRoundMode(eetype,vutype); + } + } + + TiXmlNode *cpatch = group->FirstChild("PATCH"); + while(cpatch) + { + TiXmlElement *celement = cpatch->ToElement(); + if(!celement) + { + SysPrintf("XML Patch Loader: ERROR: Couldn't convert node to element.\n" ); + return -1; + } + + + const char *ptitle=celement->Attribute("title"); + const char *penable=celement->Attribute("enabled"); + const char *applymode=celement->Attribute("applymode"); + const char *place=celement->Attribute("place"); + const char *address=celement->Attribute("address"); + const char *size=celement->Attribute("size"); + const char *value=celement->Attribute("value"); + + if(ptitle) { + SysPrintf("XML Patch Loader: Patch title: %s\n", ptitle); + } + + bool penabled=gEnabled; + if(penable) + { + if(strcmp(penable,"false")==0) + { + SysPrintf("XML Patch Loader: Patch is disabled.\n"); + penabled=false; + } + } + + if(!applymode) applymode="frame"; + if(!place) place="EE"; + if(!address) { + SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain an address.\n"); + return -1; + } + if(!value) { + SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain a value.\n"); + return -1; + } + if(!size) { + SysPrintf("XML Patch Loader: WARNING: Patch doesn't contain the size. Trying to deduce from the value size.\n"); + switch(strlen(value)) + { + case 8: + case 7: + case 6: + case 5: + size="32"; + break; + case 4: + case 3: + size="16"; + break; + case 2: + case 1: + size="8"; + break; + case 0: + size="0"; + break; + default: + size="64"; + break; + } + } + + if(strcmp(applymode,"startup")==0) + { + patch[patchnumber].placetopatch=0; + } else + if(strcmp(applymode,"vsync")==0) + { + patch[patchnumber].placetopatch=1; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid applymode attribute.\n"); + patchnumber=0; + return -1; + } + + if(strcmp(place,"EE")==0) + { + patch[patchnumber].cpu=1; + } else + if(strcmp(place,"IOP")==0) + { + patch[patchnumber].cpu=2; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid place attribute.\n"); + patchnumber=0; + return -1; + } + + if(strcmp(size,"64")==0) + { + patch[patchnumber].type=4; + } else + if(strcmp(size,"32")==0) + { + patch[patchnumber].type=3; + } else + if(strcmp(size,"16")==0) + { + patch[patchnumber].type=2; + } else + if(strcmp(size,"8")==0) + { + patch[patchnumber].type=1; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid size attribute.\n"); + patchnumber=0; + return -1; + } + + sscanf( address, "%X", &patch[ patchnumber ].addr ); + sscanf( value, "%I64X", &patch[ patchnumber ].data ); + + patch[patchnumber].enabled=penabled?1:0; + + string pt; + + if(ptitle) + pt.assign(ptitle); + else + pt.clear(); + + Patch p=Patch(patchnumber,gIndex,penabled,pt); + patches.push_back(p); + + patchnumber++; + + cpatch = cpatch->NextSibling("PATCH"); + } + + cpatch = group->FirstChild("GROUP"); + while(cpatch) { + int result=LoadGroup(cpatch,gIndex); + if(result) return result; + cpatch = cpatch->NextSibling("GROUP"); + } + + return 0; +} diff --git a/branches/pcsx2_0.9.2/windows/AboutDlg.c b/branches/pcsx2_0.9.2/windows/AboutDlg.c new file mode 100644 index 0000000..fa214a7 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/AboutDlg.c @@ -0,0 +1,65 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "resource.h" +#include "AboutDlg.h" +#include "Common.h" + +#ifdef __MINGW32__ +#define IDC_STATIC (-1) +#endif + +#ifdef __MSCW32__ +#define IDC_STATIC (-1) +#endif + +HWND hW; +HBITMAP hBMP, hSilverBMP; + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); + + hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, + 230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL); + SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP); + + SetWindowText(hDlg, _("About")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_TEXT), _("PCSX2 EMU\n")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_AUTHORS), _(LabelAuthors)); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_GREETS), _(LabelGreets)); + return TRUE; + + case WM_COMMAND: + switch(wParam) { + case IDOK: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/branches/pcsx2_0.9.2/windows/AboutDlg.h b/branches/pcsx2_0.9.2/windows/AboutDlg.h new file mode 100644 index 0000000..1a209be --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/AboutDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_ABOUTDLG_H_ +#define _PCSX2_ABOUTDLG_H_ + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif diff --git a/branches/pcsx2_0.9.2/windows/Cdrom02.ico b/branches/pcsx2_0.9.2/windows/Cdrom02.ico new file mode 100644 index 0000000000000000000000000000000000000000..07588baeaa79ee6acf726e73fb70937a1dadb53e GIT binary patch literal 12862 zcmeHO>(f_d75()kE6fWRf~lFNF^(DOq=`*Kw`shE;~15usFWItiKUlh5G4rAsI13nq&$ zn@r|UCX+?@0X6v}e#pl+Z_Z@GpZM&fNB+m_Vf!fR*u$m*15oqCk91@z8&FR0H|bl| zGOhS`>uYo?WsSjTl)mm*9sL9ASabl@Ael04Q_M%>@V@}*mLN@zp2+#=?`^t{4Us7; z+lSgi@Y9E4*rBgaD%@O2+>rI_S{1<>I|3{31P^gM5+kw5H4z{*$^&HymP&VnVe$ol z30pEQDCf#hy~}MlD35M&SjK$rK~MXj%>+0i0MD9f$Tc=2!L$a93If+qDY1H*pfTXMX2}`~d1=YTogYDW=>WM?bI)WwDBp?>0|YOe@Y9e)8c1*41j8dBA2? zlS#m>^PSAMASpxd>+3_{_A318nYIGy<5#?OMh;4qFY*-^d~mS7AHiYsj!<={!JNuMNXg%|ax_u3h-1fyX5lJ`S$}?Am^yg?B52ct&9imH+&&l&{ zJM-1295POulfRL(t)eH+B$fbsmdxeHpX{wCBrC5305)S z58P=7Rd?6{uY>4d?qHRz<1ylUj4B=@MMx&R(+=Ej`%x zJQ09k;p5yXS;#Ya9Bn;{CnDAzM z`)2kmjY$&xjG9qCrt;SjAR}c|fVXa9z3n{##%X3Se|@f#Jj_+{04l9g0MM+OlSWye zzj>p*xy;_Wkwpx!tN@K;XdfV@hdT!9(~WHw zAd63!)6=WdD?ln8C|D7@ZR)k!dyTz*jqSbG0En;UNJgWtG!EuZB^>gQCT^Hpt=J`V zL8p&bq}Q#&$d))t!L$YW+D}-odl#PW+79NQ{WfiDka+gn=@^6hSAT4%SG>RaBSRG| z9!#tT^MBGLUsnbMi);XeMDicl9@Gz6uS8FP6|oCG>8OMLy=(~MNfb%_uirP;Qq~?- zjP(lJQ9fkY6A2NoLugvWxJQy?yKx2^d)5kiIIh^YRM?^{dG^GkV>dj>MwrBUcAzFU&%gujq(e0k&x4) zmL6$e__nE@50K2q%Qv>oh}Q?d7p`DDWy^#KxVqeSUC#deWvmW6zsnhQZ41U$VqD1q zW8yF*6MQ~|Cu$Qu?GA(axm5M^fs z^J&AfT|5|{k#xd%`IbnJ{oFV0xl6qgXso+d=qjv2yfXkyc21v&$*bzHJgO@<8T z7pv!#;n_=U$0hdcH@pJuzzD2SpfBUetOY?pKkQuOF(hJi%6Ok?pEB{OKOPv&pKix9-@eFD+q|}aJwPzx(V-dT+oniE!4&(Mi|m;TjlC{0 z6~FDGQR0_WcpdT7ducDUr!TOlzZP9U3~;|j`30H`z0q?%b-q3IRo0W|v&tw?b*x7D zn5V9Y%FNDh{fa$_I?uMAR{$^=junG(lrOW@d4S6ZaIS4RxAZON*jAOubGYKx!6^9| zDFS3pG7;>FvyJuTD2->^7BJ$0eHgf$7clr(6>YoME7Jv4Z8fUgXNRkIl2XHqEn5bIAZ?7vL(y1Lml1ldWZ%SEk1~wr-9e;ubjidgn0`fb;@R zzKFGQ4PTcGUFWWEPh=Q^V&05$2*WN|-YVD}Tl)ppI&@(OG&&Em9*Oe=pxMTXo?3aA zzYa^!=lm_k%aaIGzpIcXVJP*)+Rs~4k4`ZVh|E=j!P{nA-vT#VITRAvre3elbDJiQ ze$G&9y$cUADOh_F^{fC~1)jdm!*X?^hf+3p*pL|ibP@{znoj<+Wh)Iv$;ybUis7$N n`PAcpb11c{#lWfW9typ-^%X;YTBH31;@<&$`v3pWzreo$+!n*^ literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.2/windows/ConfigDlg.c b/branches/pcsx2_0.9.2/windows/ConfigDlg.c new file mode 100644 index 0000000..777b109 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/ConfigDlg.c @@ -0,0 +1,499 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include //2002-09-22 (Florin) +#include "common.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +#define ComboAddPlugin(hw, str) { \ + sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \ + lp = (char *)malloc(strlen(FindData.cFileName)+8); \ + sprintf(lp, "%s", FindData.cFileName); \ + i = ComboBox_AddString(hw, tmpStr); \ + ComboBox_SetItemData(hw, i, lp); \ + if (stricmp(str, lp)==0) \ + ComboBox_SetCurSel(hw, i); \ +} + +BOOL OnConfigureDialog(HWND hW) { + WIN32_FIND_DATA FindData; + HANDLE Find; + HANDLE Lib; + _PS2EgetLibType PS2E_GetLibType; + _PS2EgetLibName PS2E_GetLibName; + _PS2EgetLibVersion2 PS2E_GetLibVersion2; + HWND hWC_GS=GetDlgItem(hW,IDC_LISTGS); + HWND hWC_PAD1=GetDlgItem(hW,IDC_LISTPAD1); + HWND hWC_PAD2=GetDlgItem(hW,IDC_LISTPAD2); + HWND hWC_SPU2=GetDlgItem(hW,IDC_LISTSPU2); + HWND hWC_CDVD=GetDlgItem(hW,IDC_LISTCDVD); + HWND hWC_DEV9=GetDlgItem(hW,IDC_LISTDEV9); + HWND hWC_USB=GetDlgItem(hW,IDC_LISTUSB); + HWND hWC_FW=GetDlgItem(hW,IDC_LISTFW); + HWND hWC_BIOS=GetDlgItem(hW,IDC_LISTBIOS); + char tmpStr[256]; + char *lp; + int i; + + strcpy(tmpStr, Config.PluginsDir); + strcat(tmpStr, "*.dll"); + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + sprintf(tmpStr,"%s%s", Config.PluginsDir, FindData.cFileName); + Lib = LoadLibrary(tmpStr); + if (Lib == NULL) { SysPrintf("%s: %d\n", tmpStr, GetLastError()); continue; } + + PS2E_GetLibType = (_PS2EgetLibType) GetProcAddress((HMODULE)Lib,"PS2EgetLibType"); + PS2E_GetLibName = (_PS2EgetLibName) GetProcAddress((HMODULE)Lib,"PS2EgetLibName"); + PS2E_GetLibVersion2 = (_PS2EgetLibVersion2) GetProcAddress((HMODULE)Lib,"PS2EgetLibVersion2"); + + if (PS2E_GetLibType != NULL && PS2E_GetLibName != NULL && PS2E_GetLibVersion2 != NULL) { + u32 version; + long type; + + type = PS2E_GetLibType(); + if (type & PS2E_LT_GS) { + version = PS2E_GetLibVersion2(PS2E_LT_GS); + if ( ((version >> 16)&0xff) == PS2E_GS_VERSION) { + ComboAddPlugin(hWC_GS, Config.GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, 0xff&(version >> 16), PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)GetProcAddress((HMODULE)Lib, "PADquery"); + version = PS2E_GetLibVersion2(PS2E_LT_PAD); + if (((version >> 16)&0xff) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(hWC_PAD1, Config.PAD1); + if (query() & 0x2) + ComboAddPlugin(hWC_PAD2, Config.PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2E_GetLibVersion2(PS2E_LT_SPU2); + if ( ((version >> 16)&0xff) == PS2E_SPU2_VERSION) { + ComboAddPlugin(hWC_SPU2, Config.SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2E_GetLibVersion2(PS2E_LT_CDVD); + if (((version >> 16)&0xff) == PS2E_CDVD_VERSION) { + ComboAddPlugin(hWC_CDVD, Config.CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2E_GetLibVersion2(PS2E_LT_DEV9); + if (((version >> 16)&0xff) == PS2E_DEV9_VERSION) { + ComboAddPlugin(hWC_DEV9, Config.DEV9); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2E_GetLibVersion2(PS2E_LT_USB); + if (((version >> 16)&0xff) == PS2E_USB_VERSION) { + ComboAddPlugin(hWC_USB, Config.USB); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2E_GetLibVersion2(PS2E_LT_FW); + if (((version >> 16)&0xff) == PS2E_FW_VERSION) { + ComboAddPlugin(hWC_FW, Config.FW); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_FW_VERSION); + } + } + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + +// BIOS + + /*lp=(char *)malloc(strlen("HLE") + 1); + sprintf(lp, "HLE"); + i=ComboBox_AddString(hWC_BIOS, _("Internal HLE Bios")); + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, lp)==0) + ComboBox_SetCurSel(hWC_BIOS, i);*/ + + strcpy(tmpStr, Config.BiosDir); + strcat(tmpStr, "*"); + Find=FindFirstFile(tmpStr, &FindData); + + do { + char description[50]; //2002-09-22 (Florin) + if (Find==INVALID_HANDLE_VALUE) break; + if (!strcmp(FindData.cFileName, ".")) continue; + if (!strcmp(FindData.cFileName, "..")) continue; +// if (FindData.nFileSizeLow < 1024 * 512) continue; + if (FindData.nFileSizeLow > 1024 * 4096) continue; //2002-09-22 (Florin) + if (!IsBIOS(FindData.cFileName, description)) continue;//2002-09-22 (Florin) + lp = (char *)malloc(strlen(FindData.cFileName)+8); + sprintf(lp, "%s", (char *)FindData.cFileName); + i = ComboBox_AddString(hWC_BIOS, description); //2002-09-22 (Florin) modified + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, FindData.cFileName)==0) + ComboBox_SetCurSel(hWC_BIOS, i); + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + + if (ComboBox_GetCurSel(hWC_GS) == -1) + ComboBox_SetCurSel(hWC_GS, 0); + if (ComboBox_GetCurSel(hWC_PAD1) == -1) + ComboBox_SetCurSel(hWC_PAD1, 0); + if (ComboBox_GetCurSel(hWC_PAD2) == -1) + ComboBox_SetCurSel(hWC_PAD2, 0); + if (ComboBox_GetCurSel(hWC_SPU2) == -1) + ComboBox_SetCurSel(hWC_SPU2, 0); + if (ComboBox_GetCurSel(hWC_CDVD) == -1) + ComboBox_SetCurSel(hWC_CDVD, 0); + if (ComboBox_GetCurSel(hWC_DEV9) == -1) + ComboBox_SetCurSel(hWC_DEV9, 0); + if (ComboBox_GetCurSel(hWC_USB) == -1) + ComboBox_SetCurSel(hWC_USB, 0); + if (ComboBox_GetCurSel(hWC_FW) == -1) + ComboBox_SetCurSel(hWC_FW, 0); + if (ComboBox_GetCurSel(hWC_BIOS) == -1) + ComboBox_SetCurSel(hWC_BIOS, 0); + + return TRUE; +} + +#define CleanCombo(item) \ + hWC = GetDlgItem(hW, item); \ + iCnt = ComboBox_GetCount(hWC); \ + for (i=0; i +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char cpuspeedc[20]; + char features[256]; + u32 newopts; + + switch(uMsg) { + case WM_INITDIALOG: + SetWindowText(hW, _("Cpu Config")); + SetDlgItemText(hW, IDC_VENDORINPUT,cpuinfo.x86ID ); + SetDlgItemText(hW, IDC_FAMILYINPUT, cpuinfo.x86Fam); + sprintf(cpuspeedc,"%d MHZ",cpuinfo.cpuspeed); + SetDlgItemText(hW, IDC_CPUSPEEDINPUT, cpuspeedc); + //features[0]=':'; + //strcat(features,""); + strcpy(features,""); + if(cpucaps.hasMultimediaExtensions) strcat(features,"MMX"); + if(cpucaps.hasStreamingSIMDExtensions) strcat(features,",SSE"); + if(cpucaps.hasStreamingSIMD2Extensions) strcat(features,",SSE2"); + if(cpucaps.hasStreamingSIMD3Extensions) strcat(features,",SSE3"); +// if(cpucaps.has3DNOWInstructionExtensions) strcat(features,",3DNOW"); +// if(cpucaps.has3DNOWInstructionExtensionsExt)strcat(features,",3DNOW+"); + if(cpucaps.hasAMD64BitArchitecture) strcat(features,",x86-64"); + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + if(!cpucaps.hasStreamingSIMDExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILERVU),FALSE);//disable checkbox if no SSE2 found + Config.Options &= (PCSX2_VU0REC|PCSX2_VU1REC);//disable the config just in case + } + if(!cpucaps.hasMultimediaExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILER),FALSE); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC);//return to interpreter mode + + } + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + + CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC); + +//#ifdef PCSX2_DEVBUILD + CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC); + CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC); +//#else +// // don't show +// ShowWindow(GetDlgItem(hW, IDC_CPU_VUGROUP), SW_HIDE); +// ShowWindow(GetDlgItem(hW, IDC_CPU_VU0REC), SW_HIDE); +// ShowWindow(GetDlgItem(hW, IDC_CPU_VU1REC), SW_HIDE); +//#endif + + CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS); + CheckDlgButton(hW, IDC_CPU_MULTI, !!CHECK_DUALCORE); + + CheckRadioButton(hW,IDC_CPU_FL_NORMAL, IDC_CPU_FL_NORMAL+3, IDC_CPU_FL_NORMAL+(CHECK_FRAMELIMIT>>10)); + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + + case IDOK: + Cpu->Shutdown(); + vu0Shutdown(); + vu1Shutdown(); + + newopts = 0; + + if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC; + +//#ifdef PCSX2_DEVBUILD + if( SendDlgItemMessage(hW,IDC_CPU_VU0REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU0REC; + if( SendDlgItemMessage(hW,IDC_CPU_VU1REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU1REC; +//#else +// newopts |= PCSX2_VU0REC|PCSX2_VU1REC; +//#endif + + if( SendDlgItemMessage(hW,IDC_CPU_GSMULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_GSMULTITHREAD; + if( SendDlgItemMessage(hW,IDC_CPU_MULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_DUALCORE; + if( SendDlgItemMessage(hW,IDC_CPU_FRAMELIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT; + + if( SendDlgItemMessage(hW,IDC_CPU_FL_NORMAL,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_NORMAL; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_LIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_LIMIT; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIP,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_SKIP; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIPVU,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_VUSKIP; + + if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) { + Config.Options = newopts; + SaveConfig(); + MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK); + exit(0); + } + + if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC; + + Config.Options = newopts; + + UpdateVSyncRate(); + SaveConfig(); + + cpuRestartCPU(); + EndDialog(hW, TRUE); + return TRUE; + } + } + return FALSE; +} diff --git a/branches/pcsx2_0.9.2/windows/DebugMemory.c b/branches/pcsx2_0.9.2/windows/DebugMemory.c new file mode 100644 index 0000000..cf79747 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/DebugMemory.c @@ -0,0 +1,239 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "resource.h" + + +unsigned long memory_addr; +BOOL mem_inupdate = FALSE; +HWND memoryhWnd,hWnd_memscroll,hWnd_memorydump; +unsigned long memory_patch; +unsigned long data_patch; + +///MEMORY DUMP +unsigned char Debug_Read8(unsigned long addr)//just for anycase.. +{ +#ifdef __MSCW32__ + __try + { +#endif + u8 val8; + memRead8(addr, &val8); + return val8; +#ifdef __MSCW32__ + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return 0; + } +#endif +} + + +void RefreshMemory(void) +{ + int x, y; + unsigned long addr; + unsigned char b; + + char buf[128], text[32], temp[8]; + + + + addr = memory_addr; + + if (!mem_inupdate) + { + sprintf(buf, "%08X", addr); + SetDlgItemText(memoryhWnd, IDC_MEMORY_ADDR, buf); + } + + SendMessage(hWnd_memorydump, LB_RESETCONTENT, 0, 0); + + for (y = 0; y < 21; y++) + { + memset(text, 0, 32); + sprintf(buf, "%08X: ", addr); + + for (x = 0; x < 16; x++) + { + b = Debug_Read8(addr++); + + sprintf(temp, "%02X ", b); + strcat(buf, temp); + + if (b < 32 || b > 127) b = 32; + sprintf(temp, "%c", b); + strcat(text, temp); + + + if (x == 7) strcat(buf, " "); + } + + strcat(buf, " "); + strcat(buf, text); + + SendMessage(hWnd_memorydump, LB_ADDSTRING, 0, (LPARAM)buf); + } +} + + +BOOL APIENTRY DumpMemProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], buf[128]; + u32 start_pc, end_pc, addr; + u8 data; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMPMEM_START, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_END, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, "dump.raw"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMPMEM_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, fname, 128); + fp = fopen(fname, "wb"); + if (fp == NULL) + { + SysMessage("Can't open file '%s' for writing!\n", fname); + } + else + { + for (addr = start_pc; addr < end_pc; addr ++) { + memRead8( addr, &data ); + fwrite(&data, 1, 1, fp); + } + + fclose(fp); + } + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + + + +BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + char buf[16]; + switch (message) + { + case WM_INITDIALOG: + memory_addr = cpuRegs.pc; + sprintf(buf, "%08X", memory_addr); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + memory_patch= 0; + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf); + data_patch=0; + sprintf(buf, "%08X", data_patch); + SetDlgItemText(hDlg, IDC_DATA_PATCH, buf); + hWnd_memorydump = GetDlgItem(hDlg, IDC_MEMORY_DUMP); + hWnd_memscroll = GetDlgItem(hDlg, IDC_MEM_SCROLL); + + + + SendMessage(hWnd_memorydump, LB_INITSTORAGE, 11, 1280); + SendMessage(hWnd_memscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_memscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + RefreshMemory(); + return TRUE; + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + case SB_LINEDOWN: memory_addr += 0x00000010; RefreshMemory(); break; + case SB_LINEUP: memory_addr -= 0x00000010; RefreshMemory(); break; + case SB_PAGEDOWN: memory_addr += 0x00000150; RefreshMemory(); break; + case SB_PAGEUP: memory_addr -= 0x00000150; RefreshMemory(); break; + } + + return TRUE; + + case WM_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + + + case WM_COMMAND: + if (HIWORD(wParam) == EN_UPDATE) + { + mem_inupdate = TRUE; + GetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf, 9); + buf[8] = 0; + + sscanf(buf, "%x", &memory_addr); + RefreshMemory(); + mem_inupdate = FALSE; + return TRUE; + } + + switch (LOWORD(wParam)) { + case IDC_PATCH: + GetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf, 9);//32bit address + buf[8] = 0; + sscanf(buf, "%x", &memory_patch); + GetDlgItemText(hDlg, IDC_DATA_PATCH, buf, 9);//32 bit data only for far + buf[8] = 0; + sscanf(buf, "%x", &data_patch); + memWrite32( memory_patch, data_patch ); + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + RefreshMemory(); + return TRUE; + + case IDC_DUMPRAW: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMPMEM), hDlg, (DLGPROC)DumpMemProc); + + return TRUE; + + case IDC_MEMORY_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + + return FALSE; +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/windows/Debugger.c b/branches/pcsx2_0.9.2/windows/Debugger.c new file mode 100644 index 0000000..3164c9d --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/Debugger.c @@ -0,0 +1,562 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "Common.h" +#include "win32.h" +#include "PsxMem.h" +#include "R3000A.h" + +extern void (*IOP_DEBUG_BSC[64])(char *buf); +extern void UpdateR5900op(); +void RefreshIOPDebugger(void); +extern int ISR3000A;//for disasm +HWND hWnd_debugdisasm, hWnd_debugscroll,hWnd_IOP_debugdisasm, hWnd_IOP_debugscroll; +unsigned long DebuggerPC = 0; +HWND hRegDlg;//for debug registers.. +HWND debughWnd; +unsigned long DebuggerIOPPC=0; +HWND hIOPDlg;//IOP debugger + + +void RefreshDebugAll()//refresh disasm and register window +{ + RefreshDebugger(); + RefreshIOPDebugger(); + UpdateRegs(); + + +} + +void MakeDebugOpcode(void) +{ + memRead32( opcode_addr, &cpuRegs.code ); +} + +void MakeIOPDebugOpcode(void) +{ + psxRegs.code = PSXMu32( opcode_addr); +} + +BOOL HasBreakpoint() +{ + int t; + + for (t = 0; t < NUM_BREAKPOINTS; t++) + { + switch (bkpt_regv[t].type) { + case 1: // exec + if (cpuRegs.pc == bkpt_regv[t].value) return TRUE; + break; + + case 2: // count + if ((cpuRegs.cycle - 10) <= bkpt_regv[t].value && + (cpuRegs.cycle + 10) >= bkpt_regv[t].value) return TRUE; + break; + } + } + return FALSE; + +} +BOOL APIENTRY JumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + unsigned long temp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_JUMP_PC, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_JUMP_PC, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &temp); + + temp &= 0xFFFFFFFC; + DebuggerPC = temp - 0x00000038; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +extern void EEDumpRegs(FILE * fp); +extern void IOPDumpRegs(FILE * fp); +BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], tmp[128], buf[128]; + unsigned long start_pc, end_pc, temp; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_START, buf); + SetDlgItemText(hDlg, IDC_DUMP_END, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt"); + + sprintf(buf, "%08X", psxRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMP_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAME, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"EE DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + + + opcode_addr=temp; + MakeDebugOpcode(); + OpcodePrintTable[(cpuRegs.code) >> 26](tmp); + if (HasBreakpoint(temp)) + { + sprintf(buf, "*%08X %08X: %s", temp, cpuRegs.code, tmp); + } + else + { + sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp); + } + + fprintf(fp, "%s\n", buf); + } + + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"EE REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + EEDumpRegs(fp); + fclose(fp); + } + + + + GetDlgItemText(hDlg, IDC_DUMP_STARTIOP, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_ENDIOP, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"IOP DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + opcode_addr=temp; + MakeIOPDebugOpcode(); + IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp); + sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp); + fprintf(fp, "%s\n", buf); + } + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"IOP REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + IOPDumpRegs(fp); + fclose(fp); + } + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpexecProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[0].value); + SetDlgItemText(hDlg, IDC_EXECBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_EXECBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[0].value); + bkpt_regv[0].type = 1; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpcntProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[1].value); + SetDlgItemText(hDlg, IDC_CNTBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_CNTBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[1].value); + bkpt_regv[1].type = 2; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} +HINSTANCE m2_hInst; +HWND m2_hWnd; +HWND hIopDlg; + +LRESULT CALLBACK IOP_DISASM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + hWnd_IOP_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM_IOP); + hWnd_IOP_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL_IOP); + + SendMessage(hWnd_IOP_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_IOP_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_IOP_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + RefreshIOPDebugger(); + return (TRUE); + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerIOPPC += 0x00000004; RefreshIOPDebugger(); break; + case SB_LINEUP: DebuggerIOPPC -= 0x00000004; RefreshIOPDebugger(); break; + case SB_PAGEDOWN: DebuggerIOPPC += 0x00000029; RefreshIOPDebugger(); break; + case SB_PAGEUP: DebuggerIOPPC -= 0x00000029; RefreshIOPDebugger(); break; + } + return TRUE; + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +int CreatePropertySheet2(HWND hwndOwner) +{ + PROPSHEETPAGE psp[1]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m2_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_IOP_DEBUG); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)IOP_DISASM; + psp[0].pszTitle = "Iop Disasm"; + psp[0].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m2_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "IOP Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); +} + +BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + FARPROC jmpproc, dumpproc; + FARPROC bpexecproc, bpcntproc; + u32 oldpc = 0; + + switch (message) + { + case WM_INITDIALOG: + // if (OpenPlugins() == -1) return TRUE;//moved to WinMain.c + + ShowCursor(TRUE); + + SetWindowText(hDlg, "R5900 Debugger"); + debughWnd=hDlg; + DebuggerPC = 0; + // Clear all breakpoints. + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + + hWnd_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM); + hWnd_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL); + + SendMessage(hWnd_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + hRegDlg = (HWND)CreatePropertySheet(hDlg); + hIopDlg = (HWND)CreatePropertySheet2(hDlg); + UpdateRegs(); + SetWindowPos(hRegDlg, NULL, 425, 0, 600, 515,0 ); + SetWindowPos(hIopDlg, NULL, 0 ,515,600,230,0); + RefreshDebugger(); + + + + RefreshIOPDebugger(); + return TRUE; + + case WM_VSCROLL: + + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerPC += 0x00000004; RefreshDebugAll(); break; + case SB_LINEUP: DebuggerPC -= 0x00000004; RefreshDebugAll(); break; + case SB_PAGEDOWN: DebuggerPC += 0x00000074; RefreshDebugAll(); break; + case SB_PAGEUP: DebuggerPC -= 0x00000074; RefreshDebugAll(); break; + } + + + + + return TRUE; + + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_DEBUG_STEP: + oldpc = psxRegs.pc; + Cpu->Step(); + while(oldpc == psxRegs.pc) Cpu->Step(); + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_SKIP: + cpuRegs.pc+= 4; + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_GO: + for (;;) { + if (HasBreakpoint()) { + Cpu->Step(); + break; + } + Cpu->Step(); + } + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_LOG: +#ifdef PCSX2_DEVBUILD + Log = 1 - Log; +#endif + return TRUE; + + case IDC_DEBUG_RESETTOPC: + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_JUMP: + jmpproc = MakeProcInstance((FARPROC)JumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_JUMP), debughWnd, (DLGPROC)jmpproc); + FreeProcInstance(jmpproc); + + RefreshDebugAll(); + return TRUE; + case IDC_CPUOP: + + UpdateR5900op(); + return TRUE; + + case IDC_DEBUG_BP_EXEC: + bpexecproc = MakeProcInstance((FARPROC)BpexecProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPEXEC), debughWnd, (DLGPROC)bpexecproc); + FreeProcInstance(bpexecproc); + + return TRUE; + + case IDC_DEBUG_BP_COUNT: + bpcntproc = MakeProcInstance((FARPROC)BpcntProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPCNT), debughWnd, (DLGPROC)bpcntproc); + FreeProcInstance(bpcntproc); + return TRUE; + + case IDC_DEBUG_BP_CLEAR: + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + return TRUE; + + case IDC_DEBUG_DUMP: + dumpproc = MakeProcInstance((FARPROC)DumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMP), debughWnd, (DLGPROC)dumpproc); + FreeProcInstance(dumpproc); + return TRUE; + + case IDC_DEBUG_MEMORY: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), debughWnd, (DLGPROC)MemoryProc); + return TRUE; + + case IDC_DEBUG_CLOSE: + + EndDialog(hRegDlg ,TRUE); + EndDialog(hDlg,TRUE); + EndDialog(hIopDlg,TRUE); + + ClosePlugins(); + + return TRUE; + } + break; + } + + return FALSE; +} + +void RefreshDebugger(void) +{ + unsigned long t; + int cnt; + + + + if (DebuggerPC == 0) + DebuggerPC = cpuRegs.pc; //- 0x00000038; + + SendMessage(hWnd_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerPC, cnt = 0; t < (DebuggerPC + 0x00000074); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 *mem = (u32*)PSM(t); + char *str; + if (mem == NULL) { + char nullAddr[256]; + sprintf(nullAddr, "%8.8lx 00000000: NULL MEMORY", t); str = nullAddr; + } else { + str = disR5900Fasm(*mem, t); + } + SendMessage(hWnd_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} + +void RefreshIOPDebugger(void) +{ + unsigned long t; + int cnt; + + DebuggerIOPPC = psxRegs.pc; //- 0x00000038; + + SendMessage(hWnd_IOP_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerIOPPC, cnt = 0; t < (DebuggerIOPPC + 0x00000029); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 mem = PSXMu32(t); + char *str = disR3000Fasm(mem, t); + SendMessage(hWnd_IOP_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} diff --git a/branches/pcsx2_0.9.2/windows/Debugger.h b/branches/pcsx2_0.9.2/windows/Debugger.h new file mode 100644 index 0000000..d4e3d20 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/Debugger.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define NUM_BREAKPOINTS 8 + +extern void (*OpcodePrintTable[64])(char *buf); + +extern BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + + +extern BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern void RefreshDebugger(void); + +unsigned long opcode_addr; + +typedef struct +{ + int type; + unsigned long value; +} breakpoints; + +breakpoints bkpt_regv[NUM_BREAKPOINTS]; + + + +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +void UpdateRegs(void); +int CreatePropertySheet(HWND hwndOwner); diff --git a/branches/pcsx2_0.9.2/windows/Debugreg.c b/branches/pcsx2_0.9.2/windows/Debugreg.c new file mode 100644 index 0000000..3edc325 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/Debugreg.c @@ -0,0 +1,1483 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 +#include +#include + +#include "resource.h" +#include "Debugger.h" +#include "Debug.h" +#include "R5900.h" +#include "R3000a.h" +#include "VUmicro.h" + +HINSTANCE m_hInst; +HWND m_hWnd; +char text1[256]; + + +/*R3000a registers handle */ +static HWND IOPGPR0Handle=NULL; +static HWND IOPGPR1Handle=NULL; +static HWND IOPGPR2Handle=NULL; +static HWND IOPGPR3Handle=NULL; +static HWND IOPGPR4Handle=NULL; +static HWND IOPGPR5Handle=NULL; +static HWND IOPGPR6Handle=NULL; +static HWND IOPGPR7Handle=NULL; +static HWND IOPGPR8Handle=NULL; +static HWND IOPGPR9Handle=NULL; +static HWND IOPGPR10Handle=NULL; +static HWND IOPGPR11Handle=NULL; +static HWND IOPGPR12Handle=NULL; +static HWND IOPGPR13Handle=NULL; +static HWND IOPGPR14Handle=NULL; +static HWND IOPGPR15Handle=NULL; +static HWND IOPGPR16Handle=NULL; +static HWND IOPGPR17Handle=NULL; +static HWND IOPGPR18Handle=NULL; +static HWND IOPGPR19Handle=NULL; +static HWND IOPGPR20Handle=NULL; +static HWND IOPGPR21Handle=NULL; +static HWND IOPGPR22Handle=NULL; +static HWND IOPGPR23Handle=NULL; +static HWND IOPGPR24Handle=NULL; +static HWND IOPGPR25Handle=NULL; +static HWND IOPGPR26Handle=NULL; +static HWND IOPGPR27Handle=NULL; +static HWND IOPGPR28Handle=NULL; +static HWND IOPGPR29Handle=NULL; +static HWND IOPGPR30Handle=NULL; +static HWND IOPGPR31Handle=NULL; +static HWND IOPGPRPCHandle=NULL; +static HWND IOPGPRHIHandle=NULL; +static HWND IOPGPRLOHandle=NULL; + +/*R5900 registers handle */ +static HWND GPR0Handle=NULL; +static HWND GPR1Handle=NULL; +static HWND GPR2Handle=NULL; +static HWND GPR3Handle=NULL; +static HWND GPR4Handle=NULL; +static HWND GPR5Handle=NULL; +static HWND GPR6Handle=NULL; +static HWND GPR7Handle=NULL; +static HWND GPR8Handle=NULL; +static HWND GPR9Handle=NULL; +static HWND GPR10Handle=NULL; +static HWND GPR11Handle=NULL; +static HWND GPR12Handle=NULL; +static HWND GPR13Handle=NULL; +static HWND GPR14Handle=NULL; +static HWND GPR15Handle=NULL; +static HWND GPR16Handle=NULL; +static HWND GPR17Handle=NULL; +static HWND GPR18Handle=NULL; +static HWND GPR19Handle=NULL; +static HWND GPR20Handle=NULL; +static HWND GPR21Handle=NULL; +static HWND GPR22Handle=NULL; +static HWND GPR23Handle=NULL; +static HWND GPR24Handle=NULL; +static HWND GPR25Handle=NULL; +static HWND GPR26Handle=NULL; +static HWND GPR27Handle=NULL; +static HWND GPR28Handle=NULL; +static HWND GPR29Handle=NULL; +static HWND GPR30Handle=NULL; +static HWND GPR31Handle=NULL; +static HWND GPRPCHandle=NULL; +static HWND GPRHIHandle=NULL; +static HWND GPRLOHandle=NULL; +/*end of r3000a registers handle */ +/*cop0 registers here */ +static HWND COP00Handle=NULL; +static HWND COP01Handle=NULL; +static HWND COP02Handle=NULL; +static HWND COP03Handle=NULL; +static HWND COP04Handle=NULL; +static HWND COP05Handle=NULL; +static HWND COP06Handle=NULL; +static HWND COP07Handle=NULL; +static HWND COP08Handle=NULL; +static HWND COP09Handle=NULL; +static HWND COP010Handle=NULL; +static HWND COP011Handle=NULL; +static HWND COP012Handle=NULL; +static HWND COP013Handle=NULL; +static HWND COP014Handle=NULL; +static HWND COP015Handle=NULL; +static HWND COP016Handle=NULL; +static HWND COP017Handle=NULL; +static HWND COP018Handle=NULL; +static HWND COP019Handle=NULL; +static HWND COP020Handle=NULL; +static HWND COP021Handle=NULL; +static HWND COP022Handle=NULL; +static HWND COP023Handle=NULL; +static HWND COP024Handle=NULL; +static HWND COP025Handle=NULL; +static HWND COP026Handle=NULL; +static HWND COP027Handle=NULL; +static HWND COP028Handle=NULL; +static HWND COP029Handle=NULL; +static HWND COP030Handle=NULL; +static HWND COP031Handle=NULL; +static HWND COP0PCHandle=NULL; +static HWND COP0HIHandle=NULL; +static HWND COP0LOHandle=NULL; +/*end of cop0 registers */ +/*cop1 registers here */ +static HWND COP10Handle=NULL; +static HWND COP11Handle=NULL; +static HWND COP12Handle=NULL; +static HWND COP13Handle=NULL; +static HWND COP14Handle=NULL; +static HWND COP15Handle=NULL; +static HWND COP16Handle=NULL; +static HWND COP17Handle=NULL; +static HWND COP18Handle=NULL; +static HWND COP19Handle=NULL; +static HWND COP110Handle=NULL; +static HWND COP111Handle=NULL; +static HWND COP112Handle=NULL; +static HWND COP113Handle=NULL; +static HWND COP114Handle=NULL; +static HWND COP115Handle=NULL; +static HWND COP116Handle=NULL; +static HWND COP117Handle=NULL; +static HWND COP118Handle=NULL; +static HWND COP119Handle=NULL; +static HWND COP120Handle=NULL; +static HWND COP121Handle=NULL; +static HWND COP122Handle=NULL; +static HWND COP123Handle=NULL; +static HWND COP124Handle=NULL; +static HWND COP125Handle=NULL; +static HWND COP126Handle=NULL; +static HWND COP127Handle=NULL; +static HWND COP128Handle=NULL; +static HWND COP129Handle=NULL; +static HWND COP130Handle=NULL; +static HWND COP131Handle=NULL; +static HWND COP1C0Handle=NULL; +static HWND COP1C1Handle=NULL; +static HWND COP1ACCHandle=NULL; +/*end of cop1 registers */ +/*cop2 floating registers*/ +static HWND VU0F00Handle=NULL; +static HWND VU0F01Handle=NULL; +static HWND VU0F02Handle=NULL; +static HWND VU0F03Handle=NULL; +static HWND VU0F04Handle=NULL; +static HWND VU0F05Handle=NULL; +static HWND VU0F06Handle=NULL; +static HWND VU0F07Handle=NULL; +static HWND VU0F08Handle=NULL; +static HWND VU0F09Handle=NULL; +static HWND VU0F10Handle=NULL; +static HWND VU0F11Handle=NULL; +static HWND VU0F12Handle=NULL; +static HWND VU0F13Handle=NULL; +static HWND VU0F14Handle=NULL; +static HWND VU0F15Handle=NULL; +static HWND VU0F16Handle=NULL; +static HWND VU0F17Handle=NULL; +static HWND VU0F18Handle=NULL; +static HWND VU0F19Handle=NULL; +static HWND VU0F20Handle=NULL; +static HWND VU0F21Handle=NULL; +static HWND VU0F22Handle=NULL; +static HWND VU0F23Handle=NULL; +static HWND VU0F24Handle=NULL; +static HWND VU0F25Handle=NULL; +static HWND VU0F26Handle=NULL; +static HWND VU0F27Handle=NULL; +static HWND VU0F28Handle=NULL; +static HWND VU0F29Handle=NULL; +static HWND VU0F30Handle=NULL; +static HWND VU0F31Handle=NULL; +/*end of cop2 floating registers*/ +/*cop2 control registers */ +static HWND VU0C00Handle=NULL; +static HWND VU0C01Handle=NULL; +static HWND VU0C02Handle=NULL; +static HWND VU0C03Handle=NULL; +static HWND VU0C04Handle=NULL; +static HWND VU0C05Handle=NULL; +static HWND VU0C06Handle=NULL; +static HWND VU0C07Handle=NULL; +static HWND VU0C08Handle=NULL; +static HWND VU0C09Handle=NULL; +static HWND VU0C10Handle=NULL; +static HWND VU0C11Handle=NULL; +static HWND VU0C12Handle=NULL; +static HWND VU0C13Handle=NULL; +static HWND VU0C14Handle=NULL; +static HWND VU0C15Handle=NULL; +static HWND VU0C16Handle=NULL; +static HWND VU0C17Handle=NULL; +static HWND VU0C18Handle=NULL; +static HWND VU0C19Handle=NULL; +static HWND VU0C20Handle=NULL; +static HWND VU0C21Handle=NULL; +static HWND VU0C22Handle=NULL; +static HWND VU0C23Handle=NULL; +static HWND VU0C24Handle=NULL; +static HWND VU0C25Handle=NULL; +static HWND VU0C26Handle=NULL; +static HWND VU0C27Handle=NULL; +static HWND VU0C28Handle=NULL; +static HWND VU0C29Handle=NULL; +static HWND VU0C30Handle=NULL; +static HWND VU0C31Handle=NULL; +static HWND VU0ACCHandle=NULL; +/*end of cop2 control registers */ +/*vu1 floating registers*/ +static HWND VU1F00Handle=NULL; +static HWND VU1F01Handle=NULL; +static HWND VU1F02Handle=NULL; +static HWND VU1F03Handle=NULL; +static HWND VU1F04Handle=NULL; +static HWND VU1F05Handle=NULL; +static HWND VU1F06Handle=NULL; +static HWND VU1F07Handle=NULL; +static HWND VU1F08Handle=NULL; +static HWND VU1F09Handle=NULL; +static HWND VU1F10Handle=NULL; +static HWND VU1F11Handle=NULL; +static HWND VU1F12Handle=NULL; +static HWND VU1F13Handle=NULL; +static HWND VU1F14Handle=NULL; +static HWND VU1F15Handle=NULL; +static HWND VU1F16Handle=NULL; +static HWND VU1F17Handle=NULL; +static HWND VU1F18Handle=NULL; +static HWND VU1F19Handle=NULL; +static HWND VU1F20Handle=NULL; +static HWND VU1F21Handle=NULL; +static HWND VU1F22Handle=NULL; +static HWND VU1F23Handle=NULL; +static HWND VU1F24Handle=NULL; +static HWND VU1F25Handle=NULL; +static HWND VU1F26Handle=NULL; +static HWND VU1F27Handle=NULL; +static HWND VU1F28Handle=NULL; +static HWND VU1F29Handle=NULL; +static HWND VU1F30Handle=NULL; +static HWND VU1F31Handle=NULL; +/*end of vu1 floating registers*/ +/*vu1 control registers */ +static HWND VU1C00Handle=NULL; +static HWND VU1C01Handle=NULL; +static HWND VU1C02Handle=NULL; +static HWND VU1C03Handle=NULL; +static HWND VU1C04Handle=NULL; +static HWND VU1C05Handle=NULL; +static HWND VU1C06Handle=NULL; +static HWND VU1C07Handle=NULL; +static HWND VU1C08Handle=NULL; +static HWND VU1C09Handle=NULL; +static HWND VU1C10Handle=NULL; +static HWND VU1C11Handle=NULL; +static HWND VU1C12Handle=NULL; +static HWND VU1C13Handle=NULL; +static HWND VU1C14Handle=NULL; +static HWND VU1C15Handle=NULL; +static HWND VU1C16Handle=NULL; +static HWND VU1C17Handle=NULL; +static HWND VU1C18Handle=NULL; +static HWND VU1C19Handle=NULL; +static HWND VU1C20Handle=NULL; +static HWND VU1C21Handle=NULL; +static HWND VU1C22Handle=NULL; +static HWND VU1C23Handle=NULL; +static HWND VU1C24Handle=NULL; +static HWND VU1C25Handle=NULL; +static HWND VU1C26Handle=NULL; +static HWND VU1C27Handle=NULL; +static HWND VU1C28Handle=NULL; +static HWND VU1C29Handle=NULL; +static HWND VU1C30Handle=NULL; +static HWND VU1C31Handle=NULL; +static HWND VU1ACCHandle=NULL; +/*end of vu1 control registers */ + +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +//comctl32 lib must add to project.. +int CreatePropertySheet(HWND hwndOwner) +{ + + PROPSHEETPAGE psp[7]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_GPREGS); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)R5900reg; + psp[0].pszTitle = "R5900"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = m_hInst; + psp[1].pszTemplate = MAKEINTRESOURCE( IDD_CP0REGS ); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc =(DLGPROC)COP0reg; + psp[1].pszTitle = "COP0"; + psp[1].lParam = 0; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = PSP_USETITLE; + psp[2].hInstance = m_hInst; + psp[2].pszTemplate = MAKEINTRESOURCE( IDD_CP1REGS ); + psp[2].pszIcon = NULL; + psp[2].pfnDlgProc =(DLGPROC)COP1reg; + psp[2].pszTitle = "COP1"; + psp[2].lParam = 0; + + psp[3].dwSize = sizeof(PROPSHEETPAGE); + psp[3].dwFlags = PSP_USETITLE; + psp[3].hInstance = m_hInst; + psp[3].pszTemplate = MAKEINTRESOURCE( IDD_VU0REGS ); + psp[3].pszIcon = NULL; + psp[3].pfnDlgProc =(DLGPROC)COP2Freg; + psp[3].pszTitle = "COP2F"; + psp[3].lParam = 0; + + psp[4].dwSize = sizeof(PROPSHEETPAGE); + psp[4].dwFlags = PSP_USETITLE; + psp[4].hInstance = m_hInst; + psp[4].pszTemplate = MAKEINTRESOURCE( IDD_VU0INTEGER ); + psp[4].pszIcon = NULL; + psp[4].pfnDlgProc =(DLGPROC)COP2Creg; + psp[4].pszTitle = "COP2C"; + psp[4].lParam = 0; + + psp[5].dwSize = sizeof(PROPSHEETPAGE); + psp[5].dwFlags = PSP_USETITLE; + psp[5].hInstance = m_hInst; + psp[5].pszTemplate = MAKEINTRESOURCE( IDD_VU1REGS ); + psp[5].pszIcon = NULL; + psp[5].pfnDlgProc =(DLGPROC)VU1Freg; + psp[5].pszTitle = "VU1F"; + psp[5].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_VU1INTEGER ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)VU1Creg; + psp[6].pszTitle = "VU1C"; + psp[6].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_IOPREGS ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)R3000reg; + psp[6].pszTitle = "R3000"; + psp[6].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); + +} +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + IOPGPR0Handle=GetDlgItem(hDlg,IDC_IOPGPR0); + IOPGPR1Handle=GetDlgItem(hDlg,IDC_IOPGPR1); + IOPGPR2Handle=GetDlgItem(hDlg,IDC_IOPGPR2); + IOPGPR3Handle=GetDlgItem(hDlg,IDC_IOPGPR3); + IOPGPR4Handle=GetDlgItem(hDlg,IDC_IOPGPR4); + IOPGPR5Handle=GetDlgItem(hDlg,IDC_IOPGPR5); + IOPGPR6Handle=GetDlgItem(hDlg,IDC_IOPGPR6); + IOPGPR7Handle=GetDlgItem(hDlg,IDC_IOPGPR7); + IOPGPR8Handle=GetDlgItem(hDlg,IDC_IOPGPR8); + IOPGPR9Handle=GetDlgItem(hDlg,IDC_IOPGPR9); + IOPGPR10Handle=GetDlgItem(hDlg,IDC_IOPGPR10); + IOPGPR11Handle=GetDlgItem(hDlg,IDC_IOPGPR11); + IOPGPR12Handle=GetDlgItem(hDlg,IDC_IOPGPR12); + IOPGPR13Handle=GetDlgItem(hDlg,IDC_IOPGPR13); + IOPGPR14Handle=GetDlgItem(hDlg,IDC_IOPGPR14); + IOPGPR15Handle=GetDlgItem(hDlg,IDC_IOPGPR15); + IOPGPR16Handle=GetDlgItem(hDlg,IDC_IOPGPR16); + IOPGPR17Handle=GetDlgItem(hDlg,IDC_IOPGPR17); + IOPGPR18Handle=GetDlgItem(hDlg,IDC_IOPGPR18); + IOPGPR19Handle=GetDlgItem(hDlg,IDC_IOPGPR19); + IOPGPR20Handle=GetDlgItem(hDlg,IDC_IOPGPR20); + IOPGPR21Handle=GetDlgItem(hDlg,IDC_IOPGPR21); + IOPGPR22Handle=GetDlgItem(hDlg,IDC_IOPGPR22); + IOPGPR23Handle=GetDlgItem(hDlg,IDC_IOPGPR23); + IOPGPR24Handle=GetDlgItem(hDlg,IDC_IOPGPR24); + IOPGPR25Handle=GetDlgItem(hDlg,IDC_IOPGPR25); + IOPGPR26Handle=GetDlgItem(hDlg,IDC_IOPGPR26); + IOPGPR27Handle=GetDlgItem(hDlg,IDC_IOPGPR27); + IOPGPR28Handle=GetDlgItem(hDlg,IDC_IOPGPR28); + IOPGPR29Handle=GetDlgItem(hDlg,IDC_IOPGPR29); + IOPGPR30Handle=GetDlgItem(hDlg,IDC_IOPGPR30); + IOPGPR31Handle=GetDlgItem(hDlg,IDC_IOPGPR31); + IOPGPRPCHandle=GetDlgItem(hDlg,IDC_IOPGPR_PC); + IOPGPRHIHandle=GetDlgItem(hDlg,IDC_IOPGPR_HI); + IOPGPRLOHandle=GetDlgItem(hDlg,IDC_IOPGPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + GPR0Handle=GetDlgItem(hDlg,IDC_GPR0); + GPR1Handle=GetDlgItem(hDlg,IDC_GPR1); + GPR2Handle=GetDlgItem(hDlg,IDC_GPR2); + GPR3Handle=GetDlgItem(hDlg,IDC_GPR3); + GPR4Handle=GetDlgItem(hDlg,IDC_GPR4); + GPR5Handle=GetDlgItem(hDlg,IDC_GPR5); + GPR6Handle=GetDlgItem(hDlg,IDC_GPR6); + GPR7Handle=GetDlgItem(hDlg,IDC_GPR7); + GPR8Handle=GetDlgItem(hDlg,IDC_GPR8); + GPR9Handle=GetDlgItem(hDlg,IDC_GPR9); + GPR10Handle=GetDlgItem(hDlg,IDC_GPR10); + GPR11Handle=GetDlgItem(hDlg,IDC_GPR11); + GPR12Handle=GetDlgItem(hDlg,IDC_GPR12); + GPR13Handle=GetDlgItem(hDlg,IDC_GPR13); + GPR14Handle=GetDlgItem(hDlg,IDC_GPR14); + GPR15Handle=GetDlgItem(hDlg,IDC_GPR15); + GPR16Handle=GetDlgItem(hDlg,IDC_GPR16); + GPR17Handle=GetDlgItem(hDlg,IDC_GPR17); + GPR18Handle=GetDlgItem(hDlg,IDC_GPR18); + GPR19Handle=GetDlgItem(hDlg,IDC_GPR19); + GPR20Handle=GetDlgItem(hDlg,IDC_GPR20); + GPR21Handle=GetDlgItem(hDlg,IDC_GPR21); + GPR22Handle=GetDlgItem(hDlg,IDC_GPR22); + GPR23Handle=GetDlgItem(hDlg,IDC_GPR23); + GPR24Handle=GetDlgItem(hDlg,IDC_GPR24); + GPR25Handle=GetDlgItem(hDlg,IDC_GPR25); + GPR26Handle=GetDlgItem(hDlg,IDC_GPR26); + GPR27Handle=GetDlgItem(hDlg,IDC_GPR27); + GPR28Handle=GetDlgItem(hDlg,IDC_GPR28); + GPR29Handle=GetDlgItem(hDlg,IDC_GPR29); + GPR30Handle=GetDlgItem(hDlg,IDC_GPR30); + GPR31Handle=GetDlgItem(hDlg,IDC_GPR31); + GPRPCHandle=GetDlgItem(hDlg,IDC_GPR_PC); + GPRHIHandle=GetDlgItem(hDlg,IDC_GPR_HI); + GPRLOHandle=GetDlgItem(hDlg,IDC_GPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP00Handle=GetDlgItem(hDlg,IDC_CP00); + COP01Handle=GetDlgItem(hDlg,IDC_CP01); + COP02Handle=GetDlgItem(hDlg,IDC_CP02); + COP03Handle=GetDlgItem(hDlg,IDC_CP03); + COP04Handle=GetDlgItem(hDlg,IDC_CP04); + COP05Handle=GetDlgItem(hDlg,IDC_CP05); + COP06Handle=GetDlgItem(hDlg,IDC_CP06); + COP07Handle=GetDlgItem(hDlg,IDC_CP07); + COP08Handle=GetDlgItem(hDlg,IDC_CP08); + COP09Handle=GetDlgItem(hDlg,IDC_CP09); + COP010Handle=GetDlgItem(hDlg,IDC_CP010); + COP011Handle=GetDlgItem(hDlg,IDC_CP011); + COP012Handle=GetDlgItem(hDlg,IDC_CP012); + COP013Handle=GetDlgItem(hDlg,IDC_CP013); + COP014Handle=GetDlgItem(hDlg,IDC_CP014); + COP015Handle=GetDlgItem(hDlg,IDC_CP015); + COP016Handle=GetDlgItem(hDlg,IDC_CP016); + COP017Handle=GetDlgItem(hDlg,IDC_CP017); + COP018Handle=GetDlgItem(hDlg,IDC_CP018); + COP019Handle=GetDlgItem(hDlg,IDC_CP019); + COP020Handle=GetDlgItem(hDlg,IDC_CP020); + COP021Handle=GetDlgItem(hDlg,IDC_CP021); + COP022Handle=GetDlgItem(hDlg,IDC_CP022); + COP023Handle=GetDlgItem(hDlg,IDC_CP023); + COP024Handle=GetDlgItem(hDlg,IDC_CP024); + COP025Handle=GetDlgItem(hDlg,IDC_CP025); + COP026Handle=GetDlgItem(hDlg,IDC_CP026); + COP027Handle=GetDlgItem(hDlg,IDC_CP027); + COP028Handle=GetDlgItem(hDlg,IDC_CP028); + COP029Handle=GetDlgItem(hDlg,IDC_CP029); + COP030Handle=GetDlgItem(hDlg,IDC_CP030); + COP031Handle=GetDlgItem(hDlg,IDC_CP031); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP10Handle=GetDlgItem(hDlg,IDC_FP0); + COP11Handle=GetDlgItem(hDlg,IDC_FP1); + COP12Handle=GetDlgItem(hDlg,IDC_FP2); + COP13Handle=GetDlgItem(hDlg,IDC_FP3); + COP14Handle=GetDlgItem(hDlg,IDC_FP4); + COP15Handle=GetDlgItem(hDlg,IDC_FP5); + COP16Handle=GetDlgItem(hDlg,IDC_FP6); + COP17Handle=GetDlgItem(hDlg,IDC_FP7); + COP18Handle=GetDlgItem(hDlg,IDC_FP8); + COP19Handle=GetDlgItem(hDlg,IDC_FP9); + COP110Handle=GetDlgItem(hDlg,IDC_FP10); + COP111Handle=GetDlgItem(hDlg,IDC_FP11); + COP112Handle=GetDlgItem(hDlg,IDC_FP12); + COP113Handle=GetDlgItem(hDlg,IDC_FP13); + COP114Handle=GetDlgItem(hDlg,IDC_FP14); + COP115Handle=GetDlgItem(hDlg,IDC_FP15); + COP116Handle=GetDlgItem(hDlg,IDC_FP16); + COP117Handle=GetDlgItem(hDlg,IDC_FP17); + COP118Handle=GetDlgItem(hDlg,IDC_FP18); + COP119Handle=GetDlgItem(hDlg,IDC_FP19); + COP120Handle=GetDlgItem(hDlg,IDC_FP20); + COP121Handle=GetDlgItem(hDlg,IDC_FP21); + COP122Handle=GetDlgItem(hDlg,IDC_FP22); + COP123Handle=GetDlgItem(hDlg,IDC_FP23); + COP124Handle=GetDlgItem(hDlg,IDC_FP24); + COP125Handle=GetDlgItem(hDlg,IDC_FP25); + COP126Handle=GetDlgItem(hDlg,IDC_FP26); + COP127Handle=GetDlgItem(hDlg,IDC_FP27); + COP128Handle=GetDlgItem(hDlg,IDC_FP28); + COP129Handle=GetDlgItem(hDlg,IDC_FP29); + COP130Handle=GetDlgItem(hDlg,IDC_FP30); + COP131Handle=GetDlgItem(hDlg,IDC_FP31); + COP1C0Handle=GetDlgItem(hDlg,IDC_FCR0); + COP1C1Handle=GetDlgItem(hDlg,IDC_FCR31); + COP1ACCHandle=GetDlgItem(hDlg,IDC_FPU_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0F00Handle=GetDlgItem(hDlg,IDC_VU0_VF00); + VU0F01Handle=GetDlgItem(hDlg,IDC_VU0_VF01); + VU0F02Handle=GetDlgItem(hDlg,IDC_VU0_VF02); + VU0F03Handle=GetDlgItem(hDlg,IDC_VU0_VF03); + VU0F04Handle=GetDlgItem(hDlg,IDC_VU0_VF04); + VU0F05Handle=GetDlgItem(hDlg,IDC_VU0_VF05); + VU0F06Handle=GetDlgItem(hDlg,IDC_VU0_VF06); + VU0F07Handle=GetDlgItem(hDlg,IDC_VU0_VF07); + VU0F08Handle=GetDlgItem(hDlg,IDC_VU0_VF08); + VU0F09Handle=GetDlgItem(hDlg,IDC_VU0_VF09); + VU0F10Handle=GetDlgItem(hDlg,IDC_VU0_VF10); + VU0F11Handle=GetDlgItem(hDlg,IDC_VU0_VF11); + VU0F12Handle=GetDlgItem(hDlg,IDC_VU0_VF12); + VU0F13Handle=GetDlgItem(hDlg,IDC_VU0_VF13); + VU0F14Handle=GetDlgItem(hDlg,IDC_VU0_VF14); + VU0F15Handle=GetDlgItem(hDlg,IDC_VU0_VF15); + VU0F16Handle=GetDlgItem(hDlg,IDC_VU0_VF16); + VU0F17Handle=GetDlgItem(hDlg,IDC_VU0_VF17); + VU0F18Handle=GetDlgItem(hDlg,IDC_VU0_VF18); + VU0F19Handle=GetDlgItem(hDlg,IDC_VU0_VF19); + VU0F20Handle=GetDlgItem(hDlg,IDC_VU0_VF20); + VU0F21Handle=GetDlgItem(hDlg,IDC_VU0_VF21); + VU0F22Handle=GetDlgItem(hDlg,IDC_VU0_VF22); + VU0F23Handle=GetDlgItem(hDlg,IDC_VU0_VF23); + VU0F24Handle=GetDlgItem(hDlg,IDC_VU0_VF24); + VU0F25Handle=GetDlgItem(hDlg,IDC_VU0_VF25); + VU0F26Handle=GetDlgItem(hDlg,IDC_VU0_VF26); + VU0F27Handle=GetDlgItem(hDlg,IDC_VU0_VF27); + VU0F28Handle=GetDlgItem(hDlg,IDC_VU0_VF28); + VU0F29Handle=GetDlgItem(hDlg,IDC_VU0_VF29); + VU0F30Handle=GetDlgItem(hDlg,IDC_VU0_VF30); + VU0F31Handle=GetDlgItem(hDlg,IDC_VU0_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0C00Handle=GetDlgItem(hDlg,IDC_VU0_VI00); + VU0C01Handle=GetDlgItem(hDlg,IDC_VU0_VI01); + VU0C02Handle=GetDlgItem(hDlg,IDC_VU0_VI02); + VU0C03Handle=GetDlgItem(hDlg,IDC_VU0_VI03); + VU0C04Handle=GetDlgItem(hDlg,IDC_VU0_VI04); + VU0C05Handle=GetDlgItem(hDlg,IDC_VU0_VI05); + VU0C06Handle=GetDlgItem(hDlg,IDC_VU0_VI06); + VU0C07Handle=GetDlgItem(hDlg,IDC_VU0_VI07); + VU0C08Handle=GetDlgItem(hDlg,IDC_VU0_VI08); + VU0C09Handle=GetDlgItem(hDlg,IDC_VU0_VI09); + VU0C10Handle=GetDlgItem(hDlg,IDC_VU0_VI10); + VU0C11Handle=GetDlgItem(hDlg,IDC_VU0_VI11); + VU0C12Handle=GetDlgItem(hDlg,IDC_VU0_VI12); + VU0C13Handle=GetDlgItem(hDlg,IDC_VU0_VI13); + VU0C14Handle=GetDlgItem(hDlg,IDC_VU0_VI14); + VU0C15Handle=GetDlgItem(hDlg,IDC_VU0_VI15); + VU0C16Handle=GetDlgItem(hDlg,IDC_VU0_VI16); + VU0C17Handle=GetDlgItem(hDlg,IDC_VU0_VI17); + VU0C18Handle=GetDlgItem(hDlg,IDC_VU0_VI18); + VU0C19Handle=GetDlgItem(hDlg,IDC_VU0_VI19); + VU0C20Handle=GetDlgItem(hDlg,IDC_VU0_VI20); + VU0C21Handle=GetDlgItem(hDlg,IDC_VU0_VI21); + VU0C22Handle=GetDlgItem(hDlg,IDC_VU0_VI22); + VU0C23Handle=GetDlgItem(hDlg,IDC_VU0_VI23); + VU0C24Handle=GetDlgItem(hDlg,IDC_VU0_VI24); + VU0C25Handle=GetDlgItem(hDlg,IDC_VU0_VI25); + VU0C26Handle=GetDlgItem(hDlg,IDC_VU0_VI26); + VU0C27Handle=GetDlgItem(hDlg,IDC_VU0_VI27); + VU0C28Handle=GetDlgItem(hDlg,IDC_VU0_VI28); + VU0C29Handle=GetDlgItem(hDlg,IDC_VU0_VI29); + VU0C30Handle=GetDlgItem(hDlg,IDC_VU0_VI30); + VU0C31Handle=GetDlgItem(hDlg,IDC_VU0_VI31); + VU0ACCHandle=GetDlgItem(hDlg,IDC_VU0_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + + +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1F00Handle=GetDlgItem(hDlg,IDC_VU1_VF00); + VU1F01Handle=GetDlgItem(hDlg,IDC_VU1_VF01); + VU1F02Handle=GetDlgItem(hDlg,IDC_VU1_VF02); + VU1F03Handle=GetDlgItem(hDlg,IDC_VU1_VF03); + VU1F04Handle=GetDlgItem(hDlg,IDC_VU1_VF04); + VU1F05Handle=GetDlgItem(hDlg,IDC_VU1_VF05); + VU1F06Handle=GetDlgItem(hDlg,IDC_VU1_VF06); + VU1F07Handle=GetDlgItem(hDlg,IDC_VU1_VF07); + VU1F08Handle=GetDlgItem(hDlg,IDC_VU1_VF08); + VU1F09Handle=GetDlgItem(hDlg,IDC_VU1_VF09); + VU1F10Handle=GetDlgItem(hDlg,IDC_VU1_VF10); + VU1F11Handle=GetDlgItem(hDlg,IDC_VU1_VF11); + VU1F12Handle=GetDlgItem(hDlg,IDC_VU1_VF12); + VU1F13Handle=GetDlgItem(hDlg,IDC_VU1_VF13); + VU1F14Handle=GetDlgItem(hDlg,IDC_VU1_VF14); + VU1F15Handle=GetDlgItem(hDlg,IDC_VU1_VF15); + VU1F16Handle=GetDlgItem(hDlg,IDC_VU1_VF16); + VU1F17Handle=GetDlgItem(hDlg,IDC_VU1_VF17); + VU1F18Handle=GetDlgItem(hDlg,IDC_VU1_VF18); + VU1F19Handle=GetDlgItem(hDlg,IDC_VU1_VF19); + VU1F20Handle=GetDlgItem(hDlg,IDC_VU1_VF20); + VU1F21Handle=GetDlgItem(hDlg,IDC_VU1_VF21); + VU1F22Handle=GetDlgItem(hDlg,IDC_VU1_VF22); + VU1F23Handle=GetDlgItem(hDlg,IDC_VU1_VF23); + VU1F24Handle=GetDlgItem(hDlg,IDC_VU1_VF24); + VU1F25Handle=GetDlgItem(hDlg,IDC_VU1_VF25); + VU1F26Handle=GetDlgItem(hDlg,IDC_VU1_VF26); + VU1F27Handle=GetDlgItem(hDlg,IDC_VU1_VF27); + VU1F28Handle=GetDlgItem(hDlg,IDC_VU1_VF28); + VU1F29Handle=GetDlgItem(hDlg,IDC_VU1_VF29); + VU1F30Handle=GetDlgItem(hDlg,IDC_VU1_VF30); + VU1F31Handle=GetDlgItem(hDlg,IDC_VU1_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1C00Handle=GetDlgItem(hDlg,IDC_VU1_VI00); + VU1C01Handle=GetDlgItem(hDlg,IDC_VU1_VI01); + VU1C02Handle=GetDlgItem(hDlg,IDC_VU1_VI02); + VU1C03Handle=GetDlgItem(hDlg,IDC_VU1_VI03); + VU1C04Handle=GetDlgItem(hDlg,IDC_VU1_VI04); + VU1C05Handle=GetDlgItem(hDlg,IDC_VU1_VI05); + VU1C06Handle=GetDlgItem(hDlg,IDC_VU1_VI06); + VU1C07Handle=GetDlgItem(hDlg,IDC_VU1_VI07); + VU1C08Handle=GetDlgItem(hDlg,IDC_VU1_VI08); + VU1C09Handle=GetDlgItem(hDlg,IDC_VU1_VI09); + VU1C10Handle=GetDlgItem(hDlg,IDC_VU1_VI10); + VU1C11Handle=GetDlgItem(hDlg,IDC_VU1_VI11); + VU1C12Handle=GetDlgItem(hDlg,IDC_VU1_VI12); + VU1C13Handle=GetDlgItem(hDlg,IDC_VU1_VI13); + VU1C14Handle=GetDlgItem(hDlg,IDC_VU1_VI14); + VU1C15Handle=GetDlgItem(hDlg,IDC_VU1_VI15); + VU1C16Handle=GetDlgItem(hDlg,IDC_VU1_VI16); + VU1C17Handle=GetDlgItem(hDlg,IDC_VU1_VI17); + VU1C18Handle=GetDlgItem(hDlg,IDC_VU1_VI18); + VU1C19Handle=GetDlgItem(hDlg,IDC_VU1_VI19); + VU1C20Handle=GetDlgItem(hDlg,IDC_VU1_VI20); + VU1C21Handle=GetDlgItem(hDlg,IDC_VU1_VI21); + VU1C22Handle=GetDlgItem(hDlg,IDC_VU1_VI22); + VU1C23Handle=GetDlgItem(hDlg,IDC_VU1_VI23); + VU1C24Handle=GetDlgItem(hDlg,IDC_VU1_VI24); + VU1C25Handle=GetDlgItem(hDlg,IDC_VU1_VI25); + VU1C26Handle=GetDlgItem(hDlg,IDC_VU1_VI26); + VU1C27Handle=GetDlgItem(hDlg,IDC_VU1_VI27); + VU1C28Handle=GetDlgItem(hDlg,IDC_VU1_VI28); + VU1C29Handle=GetDlgItem(hDlg,IDC_VU1_VI29); + VU1C30Handle=GetDlgItem(hDlg,IDC_VU1_VI30); + VU1C31Handle=GetDlgItem(hDlg,IDC_VU1_VI31); + VU1ACCHandle=GetDlgItem(hDlg,IDC_VU1_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +void UpdateRegs(void) +{ + + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[0]); + SendMessage(IOPGPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[1]); + SendMessage(IOPGPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[2]); + SendMessage(IOPGPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[3]); + SendMessage(IOPGPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[4]); + SendMessage(IOPGPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[5]); + SendMessage(IOPGPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[6]); + SendMessage(IOPGPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[7]); + SendMessage(IOPGPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[8]); + SendMessage(IOPGPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[9]); + SendMessage(IOPGPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[10]); + SendMessage(IOPGPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[11]); + SendMessage(IOPGPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[12]); + SendMessage(IOPGPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[13]); + SendMessage(IOPGPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[14]); + SendMessage(IOPGPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[15]); + SendMessage(IOPGPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[16]); + SendMessage(IOPGPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[17]); + SendMessage(IOPGPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[18]); + SendMessage(IOPGPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[19]); + SendMessage(IOPGPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[20]); + SendMessage(IOPGPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[21]); + SendMessage(IOPGPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[22]); + SendMessage(IOPGPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[23]); + SendMessage(IOPGPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[24]); + SendMessage(IOPGPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[25]); + SendMessage(IOPGPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[26]); + SendMessage(IOPGPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[27]); + SendMessage(IOPGPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[28]); + SendMessage(IOPGPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[29]); + SendMessage(IOPGPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[30]); + SendMessage(IOPGPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[31]); + SendMessage(IOPGPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",psxRegs.pc ); + SendMessage(IOPGPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[32]); + SendMessage(IOPGPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[33]); + SendMessage(IOPGPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[0].UL[3],cpuRegs.GPR.r[0].UL[2],cpuRegs.GPR.r[0].UL[1],cpuRegs.GPR.r[0].UL[0] ); + SendMessage(GPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[1].UL[3], cpuRegs.GPR.r[1].UL[2],cpuRegs.GPR.r[1].UL[1],cpuRegs.GPR.r[1].UL[0] ); + SendMessage(GPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[2].UL[3],cpuRegs.GPR.r[2].UL[2], cpuRegs.GPR.r[2].UL[1],cpuRegs.GPR.r[2].UL[0]); + SendMessage(GPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[3].UL[3],cpuRegs.GPR.r[3].UL[2], cpuRegs.GPR.r[3].UL[1],cpuRegs.GPR.r[3].UL[0] ); + SendMessage(GPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[4].UL[3],cpuRegs.GPR.r[4].UL[2], cpuRegs.GPR.r[4].UL[1],cpuRegs.GPR.r[4].UL[0] ); + SendMessage(GPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[5].UL[3],cpuRegs.GPR.r[5].UL[2],cpuRegs.GPR.r[5].UL[1], cpuRegs.GPR.r[5].UL[0] ); + SendMessage(GPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[6].UL[3],cpuRegs.GPR.r[6].UL[2], cpuRegs.GPR.r[6].UL[1], cpuRegs.GPR.r[6].UL[0]); + SendMessage(GPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[7].UL[3], cpuRegs.GPR.r[7].UL[2],cpuRegs.GPR.r[7].UL[1],cpuRegs.GPR.r[7].UL[0] ); + SendMessage(GPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[8].UL[3],cpuRegs.GPR.r[8].UL[2],cpuRegs.GPR.r[8].UL[1],cpuRegs.GPR.r[8].UL[0] ); + SendMessage(GPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[9].UL[3],cpuRegs.GPR.r[9].UL[2],cpuRegs.GPR.r[9].UL[1], cpuRegs.GPR.r[9].UL[0] ); + SendMessage(GPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[10].UL[3],cpuRegs.GPR.r[10].UL[2],cpuRegs.GPR.r[10].UL[1],cpuRegs.GPR.r[10].UL[0] ); + SendMessage(GPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[11].UL[3],cpuRegs.GPR.r[11].UL[2],cpuRegs.GPR.r[11].UL[1],cpuRegs.GPR.r[11].UL[0] ); + SendMessage(GPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[12].UL[3],cpuRegs.GPR.r[12].UL[2],cpuRegs.GPR.r[12].UL[1],cpuRegs.GPR.r[12].UL[0] ); + SendMessage(GPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[13].UL[3],cpuRegs.GPR.r[13].UL[2],cpuRegs.GPR.r[13].UL[1],cpuRegs.GPR.r[13].UL[0] ); + SendMessage(GPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[14].UL[3],cpuRegs.GPR.r[14].UL[2],cpuRegs.GPR.r[14].UL[1],cpuRegs.GPR.r[14].UL[0] ); + SendMessage(GPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[15].UL[3],cpuRegs.GPR.r[15].UL[2],cpuRegs.GPR.r[15].UL[1],cpuRegs.GPR.r[15].UL[0] ); + SendMessage(GPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[16].UL[3],cpuRegs.GPR.r[16].UL[2],cpuRegs.GPR.r[16].UL[1],cpuRegs.GPR.r[16].UL[0] ); + SendMessage(GPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[17].UL[3],cpuRegs.GPR.r[17].UL[2],cpuRegs.GPR.r[17].UL[1],cpuRegs.GPR.r[17].UL[0] ); + SendMessage(GPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[18].UL[3],cpuRegs.GPR.r[18].UL[2],cpuRegs.GPR.r[18].UL[1],cpuRegs.GPR.r[18].UL[0] ); + SendMessage(GPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[19].UL[3],cpuRegs.GPR.r[19].UL[2],cpuRegs.GPR.r[19].UL[1],cpuRegs.GPR.r[19].UL[0] ); + SendMessage(GPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[20].UL[3],cpuRegs.GPR.r[20].UL[2],cpuRegs.GPR.r[20].UL[1],cpuRegs.GPR.r[20].UL[0] ); + SendMessage(GPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[21].UL[3],cpuRegs.GPR.r[21].UL[2],cpuRegs.GPR.r[21].UL[1],cpuRegs.GPR.r[21].UL[0] ); + SendMessage(GPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[22].UL[3],cpuRegs.GPR.r[22].UL[2],cpuRegs.GPR.r[22].UL[1],cpuRegs.GPR.r[22].UL[0] ); + SendMessage(GPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[23].UL[3],cpuRegs.GPR.r[23].UL[2],cpuRegs.GPR.r[23].UL[1],cpuRegs.GPR.r[23].UL[0] ); + SendMessage(GPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[24].UL[3],cpuRegs.GPR.r[24].UL[2],cpuRegs.GPR.r[24].UL[1],cpuRegs.GPR.r[24].UL[0] ); + SendMessage(GPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[25].UL[3],cpuRegs.GPR.r[25].UL[2],cpuRegs.GPR.r[25].UL[1],cpuRegs.GPR.r[25].UL[0] ); + SendMessage(GPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[26].UL[3],cpuRegs.GPR.r[26].UL[2],cpuRegs.GPR.r[26].UL[1],cpuRegs.GPR.r[26].UL[0] ); + SendMessage(GPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[27].UL[3],cpuRegs.GPR.r[27].UL[2],cpuRegs.GPR.r[27].UL[1],cpuRegs.GPR.r[27].UL[0] ); + SendMessage(GPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[28].UL[3],cpuRegs.GPR.r[28].UL[2],cpuRegs.GPR.r[28].UL[1],cpuRegs.GPR.r[28].UL[0] ); + SendMessage(GPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[29].UL[3],cpuRegs.GPR.r[29].UL[2],cpuRegs.GPR.r[29].UL[1],cpuRegs.GPR.r[29].UL[0] ); + SendMessage(GPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[30].UL[3],cpuRegs.GPR.r[30].UL[2],cpuRegs.GPR.r[30].UL[1],cpuRegs.GPR.r[30].UL[0] ); + SendMessage(GPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[31].UL[3],cpuRegs.GPR.r[31].UL[2],cpuRegs.GPR.r[31].UL[1],cpuRegs.GPR.r[31].UL[0] ); + SendMessage(GPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.pc ); + SendMessage(GPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2] ,cpuRegs.HI.UL[1] ,cpuRegs.HI.UL[0] ); + SendMessage(GPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0\0",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0] ); + SendMessage(GPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[0] ); + SendMessage(COP00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[1]); + SendMessage(COP01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[2]); + SendMessage(COP02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[3]); + SendMessage(COP03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[4]); + SendMessage(COP04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[5]); + SendMessage(COP05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[6]); + SendMessage(COP06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[7]); + SendMessage(COP07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[8]); + SendMessage(COP08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[9]); + SendMessage(COP09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[10]); + SendMessage(COP010Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[11]); + SendMessage(COP011Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[12]); + SendMessage(COP012Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[13]); + SendMessage(COP013Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[14]); + SendMessage(COP014Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[15]); + SendMessage(COP015Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[16]); + SendMessage(COP016Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[17]); + SendMessage(COP017Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[18]); + SendMessage(COP018Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[19]); + SendMessage(COP019Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[20]); + SendMessage(COP020Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[21]); + SendMessage(COP021Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[22]); + SendMessage(COP022Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[23]); + SendMessage(COP023Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[24]); + SendMessage(COP024Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[25]); + SendMessage(COP025Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[26]); + SendMessage(COP026Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[27]); + SendMessage(COP027Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[28]); + SendMessage(COP028Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[29]); + SendMessage(COP029Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[30]); + SendMessage(COP030Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[31]); + SendMessage(COP031Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f",fpuRegs.fpr[0].f ); + SendMessage(COP10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[1].f); + SendMessage(COP11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[2].f); + SendMessage(COP12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[3].f); + SendMessage(COP13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[4].f); + SendMessage(COP14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[5].f); + SendMessage(COP15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[6].f); + SendMessage(COP16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[7].f); + SendMessage(COP17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[8].f); + SendMessage(COP18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[9].f); + SendMessage(COP19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[10].f); + SendMessage(COP110Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[11].f); + SendMessage(COP111Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[12].f); + SendMessage(COP112Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[13].f); + SendMessage(COP113Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[14].f); + SendMessage(COP114Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[15].f); + SendMessage(COP115Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[16].f); + SendMessage(COP116Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[17].f); + SendMessage(COP117Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[18].f); + SendMessage(COP118Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[19].f); + SendMessage(COP119Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[20].f); + SendMessage(COP120Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[21].f); + SendMessage(COP121Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[22].f); + SendMessage(COP122Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[23].f); + SendMessage(COP123Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[24].f); + SendMessage(COP124Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[25].f); + SendMessage(COP125Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[26].f); + SendMessage(COP126Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[27].f); + SendMessage(COP127Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[28].f); + SendMessage(COP128Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[29].f); + SendMessage(COP129Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[30].f); + SendMessage(COP130Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[31].f); + SendMessage(COP131Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[0]); + SendMessage(COP1C0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[31]); + SendMessage(COP1C1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.ACC.f); + SendMessage(COP1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[0].f.w,VU0.VF[0].f.z,VU0.VF[0].f.y,VU0.VF[0].f.x ); + SendMessage(VU0F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[1].f.w,VU0.VF[1].f.z,VU0.VF[1].f.y,VU0.VF[1].f.x ); + SendMessage(VU0F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[2].f.w,VU0.VF[2].f.z,VU0.VF[2].f.y,VU0.VF[2].f.x ); + SendMessage(VU0F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[3].f.w,VU0.VF[3].f.z,VU0.VF[3].f.y,VU0.VF[3].f.x ); + SendMessage(VU0F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[4].f.w,VU0.VF[4].f.z,VU0.VF[4].f.y,VU0.VF[4].f.x ); + SendMessage(VU0F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[5].f.w,VU0.VF[5].f.z,VU0.VF[5].f.y,VU0.VF[5].f.x); + SendMessage(VU0F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[6].f.w,VU0.VF[6].f.z,VU0.VF[6].f.y,VU0.VF[6].f.x ); + SendMessage(VU0F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[7].f.w,VU0.VF[7].f.z,VU0.VF[7].f.y,VU0.VF[7].f.x ); + SendMessage(VU0F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[8].f.w,VU0.VF[8].f.z,VU0.VF[8].f.y,VU0.VF[8].f.x ); + SendMessage(VU0F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[9].f.w,VU0.VF[9].f.z,VU0.VF[9].f.y,VU0.VF[9].f.x ); + SendMessage(VU0F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[10].f.w,VU0.VF[10].f.z,VU0.VF[10].f.y,VU0.VF[10].f.x ); + SendMessage(VU0F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[11].f.w,VU0.VF[11].f.z,VU0.VF[11].f.y,VU0.VF[11].f.x ); + SendMessage(VU0F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[12].f.w,VU0.VF[12].f.z,VU0.VF[12].f.y,VU0.VF[12].f.x ); + SendMessage(VU0F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[13].f.w,VU0.VF[13].f.z,VU0.VF[13].f.y,VU0.VF[13].f.x ); + SendMessage(VU0F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[14].f.w,VU0.VF[14].f.z,VU0.VF[14].f.y,VU0.VF[14].f.x ); + SendMessage(VU0F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[15].f.w,VU0.VF[15].f.z,VU0.VF[15].f.y,VU0.VF[15].f.x ); + SendMessage(VU0F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[16].f.w,VU0.VF[16].f.z,VU0.VF[16].f.y,VU0.VF[16].f.x ); + SendMessage(VU0F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[17].f.w,VU0.VF[17].f.z,VU0.VF[17].f.y,VU0.VF[17].f.x ); + SendMessage(VU0F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[18].f.w,VU0.VF[18].f.z,VU0.VF[18].f.y,VU0.VF[18].f.x ); + SendMessage(VU0F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[19].f.w,VU0.VF[19].f.z,VU0.VF[19].f.y,VU0.VF[19].f.x ); + SendMessage(VU0F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[20].f.w,VU0.VF[20].f.z,VU0.VF[20].f.y,VU0.VF[20].f.x ); + SendMessage(VU0F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[21].f.w,VU0.VF[21].f.z,VU0.VF[21].f.y,VU0.VF[21].f.x ); + SendMessage(VU0F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[22].f.w,VU0.VF[22].f.z,VU0.VF[22].f.y,VU0.VF[22].f.x ); + SendMessage(VU0F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[23].f.w,VU0.VF[23].f.z,VU0.VF[23].f.y,VU0.VF[23].f.x ); + SendMessage(VU0F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[24].f.w,VU0.VF[24].f.z,VU0.VF[24].f.y,VU0.VF[24].f.x ); + SendMessage(VU0F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[25].f.w,VU0.VF[25].f.z,VU0.VF[25].f.y,VU0.VF[25].f.x ); + SendMessage(VU0F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[26].f.w,VU0.VF[26].f.z,VU0.VF[26].f.y,VU0.VF[26].f.x ); + SendMessage(VU0F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[27].f.w,VU0.VF[27].f.z,VU0.VF[27].f.y,VU0.VF[27].f.x ); + SendMessage(VU0F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[28].f.w,VU0.VF[28].f.z,VU0.VF[28].f.y,VU0.VF[28].f.x ); + SendMessage(VU0F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[29].f.w,VU0.VF[29].f.z,VU0.VF[29].f.y,VU0.VF[29].f.x ); + SendMessage(VU0F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[30].f.w,VU0.VF[30].f.z,VU0.VF[30].f.y,VU0.VF[30].f.x ); + SendMessage(VU0F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[31].f.w,VU0.VF[31].f.z,VU0.VF[31].f.y,VU0.VF[31].f.x ); + SendMessage(VU0F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU0.VI[0] ); + SendMessage(VU0C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[1]); + SendMessage(VU0C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[2]); + SendMessage(VU0C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[3]); + SendMessage(VU0C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[4]); + SendMessage(VU0C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[5]); + SendMessage(VU0C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[6]); + SendMessage(VU0C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[7]); + SendMessage(VU0C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[8]); + SendMessage(VU0C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[9]); + SendMessage(VU0C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[10]); + SendMessage(VU0C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[11]); + SendMessage(VU0C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[12]); + SendMessage(VU0C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[13]); + SendMessage(VU0C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[14]); + SendMessage(VU0C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[15]); + SendMessage(VU0C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[16]); + SendMessage(VU0C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[17]); + SendMessage(VU0C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[18]); + SendMessage(VU0C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[19]); + SendMessage(VU0C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[20]); + SendMessage(VU0C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[21]); + SendMessage(VU0C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[22]); + SendMessage(VU0C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[23]); + SendMessage(VU0C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[24]); + SendMessage(VU0C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[25]); + SendMessage(VU0C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[26]); + SendMessage(VU0C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[27]); + SendMessage(VU0C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[28]); + SendMessage(VU0C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[29]); + SendMessage(VU0C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[30]); + SendMessage(VU0C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[31]); + SendMessage(VU0C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU0.ACC.f.w,VU0.ACC.f.z,VU0.ACC.f.y,VU0.ACC.f.x ); + SendMessage(VU0ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[0].f.w,VU1.VF[0].f.z,VU1.VF[0].f.y,VU1.VF[0].f.x ); + SendMessage(VU1F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[1].f.w,VU1.VF[1].f.z,VU1.VF[1].f.y,VU1.VF[1].f.x ); + SendMessage(VU1F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[2].f.w,VU1.VF[2].f.z,VU1.VF[2].f.y,VU1.VF[2].f.x ); + SendMessage(VU1F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[3].f.w,VU1.VF[3].f.z,VU1.VF[3].f.y,VU1.VF[3].f.x ); + SendMessage(VU1F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[4].f.w,VU1.VF[4].f.z,VU1.VF[4].f.y,VU1.VF[4].f.x ); + SendMessage(VU1F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[5].f.w,VU1.VF[5].f.z,VU1.VF[5].f.y,VU1.VF[5].f.x); + SendMessage(VU1F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[6].f.w,VU1.VF[6].f.z,VU1.VF[6].f.y,VU1.VF[6].f.x ); + SendMessage(VU1F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[7].f.w,VU1.VF[7].f.z,VU1.VF[7].f.y,VU1.VF[7].f.x ); + SendMessage(VU1F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[8].f.w,VU1.VF[8].f.z,VU1.VF[8].f.y,VU1.VF[8].f.x ); + SendMessage(VU1F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[9].f.w,VU1.VF[9].f.z,VU1.VF[9].f.y,VU1.VF[9].f.x ); + SendMessage(VU1F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[10].f.w,VU1.VF[10].f.z,VU1.VF[10].f.y,VU1.VF[10].f.x ); + SendMessage(VU1F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[11].f.w,VU1.VF[11].f.z,VU1.VF[11].f.y,VU1.VF[11].f.x ); + SendMessage(VU1F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[12].f.w,VU1.VF[12].f.z,VU1.VF[12].f.y,VU1.VF[12].f.x ); + SendMessage(VU1F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[13].f.w,VU1.VF[13].f.z,VU1.VF[13].f.y,VU1.VF[13].f.x ); + SendMessage(VU1F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[14].f.w,VU1.VF[14].f.z,VU1.VF[14].f.y,VU1.VF[14].f.x ); + SendMessage(VU1F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[15].f.w,VU1.VF[15].f.z,VU1.VF[15].f.y,VU1.VF[15].f.x ); + SendMessage(VU1F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[16].f.w,VU1.VF[16].f.z,VU1.VF[16].f.y,VU1.VF[16].f.x ); + SendMessage(VU1F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[17].f.w,VU1.VF[17].f.z,VU1.VF[17].f.y,VU1.VF[17].f.x ); + SendMessage(VU1F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[18].f.w,VU1.VF[18].f.z,VU1.VF[18].f.y,VU1.VF[18].f.x ); + SendMessage(VU1F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[19].f.w,VU1.VF[19].f.z,VU1.VF[19].f.y,VU1.VF[19].f.x ); + SendMessage(VU1F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[20].f.w,VU1.VF[20].f.z,VU1.VF[20].f.y,VU1.VF[20].f.x ); + SendMessage(VU1F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[21].f.w,VU1.VF[21].f.z,VU1.VF[21].f.y,VU1.VF[21].f.x ); + SendMessage(VU1F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[22].f.w,VU1.VF[22].f.z,VU1.VF[22].f.y,VU1.VF[22].f.x ); + SendMessage(VU1F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[23].f.w,VU1.VF[23].f.z,VU1.VF[23].f.y,VU1.VF[23].f.x ); + SendMessage(VU1F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[24].f.w,VU1.VF[24].f.z,VU1.VF[24].f.y,VU1.VF[24].f.x ); + SendMessage(VU1F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[25].f.w,VU1.VF[25].f.z,VU1.VF[25].f.y,VU1.VF[25].f.x ); + SendMessage(VU1F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[26].f.w,VU1.VF[26].f.z,VU1.VF[26].f.y,VU1.VF[26].f.x ); + SendMessage(VU1F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[27].f.w,VU1.VF[27].f.z,VU1.VF[27].f.y,VU1.VF[27].f.x ); + SendMessage(VU1F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[28].f.w,VU1.VF[28].f.z,VU1.VF[28].f.y,VU1.VF[28].f.x ); + SendMessage(VU1F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[29].f.w,VU1.VF[29].f.z,VU1.VF[29].f.y,VU1.VF[29].f.x ); + SendMessage(VU1F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[30].f.w,VU1.VF[30].f.z,VU1.VF[30].f.y,VU1.VF[30].f.x ); + SendMessage(VU1F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[31].f.w,VU1.VF[31].f.z,VU1.VF[31].f.y,VU1.VF[31].f.x ); + SendMessage(VU1F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU1.VI[0] ); + SendMessage(VU1C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[1]); + SendMessage(VU1C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[2]); + SendMessage(VU1C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[3]); + SendMessage(VU1C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[4]); + SendMessage(VU1C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[5]); + SendMessage(VU1C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[6]); + SendMessage(VU1C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[7]); + SendMessage(VU1C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[8]); + SendMessage(VU1C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[9]); + SendMessage(VU1C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[10]); + SendMessage(VU1C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[11]); + SendMessage(VU1C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[12]); + SendMessage(VU1C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[13]); + SendMessage(VU1C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[14]); + SendMessage(VU1C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[15]); + SendMessage(VU1C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[16]); + SendMessage(VU1C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[17]); + SendMessage(VU1C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[18]); + SendMessage(VU1C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[19]); + SendMessage(VU1C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[20]); + SendMessage(VU1C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[21]); + SendMessage(VU1C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[22]); + SendMessage(VU1C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[23]); + SendMessage(VU1C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[24]); + SendMessage(VU1C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[25]); + SendMessage(VU1C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[26]); + SendMessage(VU1C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[27]); + SendMessage(VU1C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[28]); + SendMessage(VU1C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[29]); + SendMessage(VU1C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[30]); + SendMessage(VU1C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[31]); + SendMessage(VU1C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU1.ACC.f.w,VU1.ACC.f.z,VU1.ACC.f.y,VU1.ACC.f.x ); + SendMessage(VU1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + +} + + +void EEDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x_%x_%x_%x",cpuRegs.GPR.r[i].UL[3],cpuRegs.GPR.r[i].UL[2],cpuRegs.GPR.r[i].UL[1],cpuRegs.GPR.r[i].UL[0]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",cpuRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2],cpuRegs.HI.UL[1],cpuRegs.HI.UL[0]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + + + for(i = 0; i < 32; i++) + { + sprintf(text1,"0x%x",cpuRegs.CP0.r[i]); + sprintf(text2,"COP0 Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } +} + +void IOPDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x",psxRegs.GPR.r[i]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",psxRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[32]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[33]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); +} diff --git a/branches/pcsx2_0.9.2/windows/McdsDlg.c b/branches/pcsx2_0.9.2/windows/McdsDlg.c new file mode 100644 index 0000000..f425919 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/McdsDlg.c @@ -0,0 +1,124 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + + +HWND mcdDlg; + + +void Open_Mcd_Proc(HWND hW, int mcd) { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[1024]; + char *str; + + memset(szFileName, 0, sizeof(szFileName)); + memset(szFileTitle, 0, sizeof(szFileTitle)); + memset(szFilter, 0, sizeof(szFilter)); + + + strcpy(szFilter, _("Ps2 Memory Card (*.ps2)")); + str = szFilter + strlen(szFilter) + 1; + strcpy(str, "*.ps2"); + + str+= strlen(str) + 1; + strcpy(str, _("All Files")); + str+= strlen(str) + 1; + strcpy(str, "*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hW; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = "memcards"; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "MC2"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD1 : IDC_MCD2), szFileName); + } +} + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + mcdDlg = hW; + + SetWindowText(hW, _("Memcard Manager")); + + Button_SetText(GetDlgItem(hW, IDOK), _("OK")); + Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL1), _("Select Mcd")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL2), _("Select Mcd")); + + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1")); + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2")); + + if (!strlen(Config.Mcd1)) strcpy(Config.Mcd1, "memcards\\Mcd001.ps2"); + if (!strlen(Config.Mcd2)) strcpy(Config.Mcd2, "memcards\\Mcd002.ps2"); + Edit_SetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1); + Edit_SetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_MCDSEL1: + Open_Mcd_Proc(hW, 1); + return TRUE; + case IDC_MCDSEL2: + Open_Mcd_Proc(hW, 2); + return TRUE; + case IDCANCEL: + EndDialog(hW,FALSE); + + return TRUE; + case IDOK: + Edit_GetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1, 256); + Edit_GetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2, 256); + + SaveConfig(); + + EndDialog(hW,TRUE); + + return TRUE; + } + case WM_DESTROY: + return TRUE; + } + return FALSE; +} + diff --git a/branches/pcsx2_0.9.2/windows/McdsDlg.h b/branches/pcsx2_0.9.2/windows/McdsDlg.h new file mode 100644 index 0000000..c911430 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/McdsDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MCDSDLG_H__ +#define __MCDSDLG_H__ + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __MCDSDLG_H__ */ diff --git a/branches/pcsx2_0.9.2/windows/PatchBrowser.c b/branches/pcsx2_0.9.2/windows/PatchBrowser.c new file mode 100644 index 0000000..ec664c7 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/PatchBrowser.c @@ -0,0 +1,352 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************** +* +* patchbrowser.c contains all the src of patchbrowser window +* no interaction with emulation code +***************************/ + +#include +#include +#include "Common.h" +#include "win32.h" +#include "resource.h" + +/* + * TODO: + * - not topmost + * - resize stuff + * - ask to save in exit (check if changed) + */ +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + int tmpi,i; + char fileName[MAX_PATH], *tmpStr; + FILE *fp; + + switch(uMsg) { + + case WM_INITDIALOG: + SetWindowText(hW, _("Patches Browser")); + Button_SetText(GetDlgItem(hW,IDC_REFRESHPATCHLIST), _("Refresh List")); + Button_SetText(GetDlgItem(hW,IDC_NEWPATCH), _("New Patch")); + Button_SetText(GetDlgItem(hW,IDC_SAVEPATCH), _("Save Patch")); + Button_SetText(GetDlgItem(hW,IDC_EXITPB), _("Exit")); + Static_SetText(GetDlgItem(hW,IDC_GAMENAMESEARCH), _("Search game name patch:")); + //List Patches + ListPatches ((HWND) hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + + case IDC_NEWPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"a")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't create the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + fclose(fp); + i = MessageBox(hW,(LPCTSTR)"File created sucessfully.\nClear textbox?",NULL,(UINT)(MB_YESNO|MB_ICONQUESTION)); + if (i==IDYES) SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)""); + + return TRUE; + + case IDC_SAVEPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"w")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't save the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + tmpi = SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_GETLINECOUNT, (WPARAM)NULL, (LPARAM)NULL); + i=0; + for (;tmpi>=0;tmpi--) + i += SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_LINELENGTH, (WPARAM)tmpi, (LPARAM)NULL); + + tmpStr = (char *) malloc(i); + sprintf(tmpStr,""); + SendDlgItemMessage(hW, IDC_PATCHTEXT, WM_GETTEXT, (WPARAM)i, (LPARAM)tmpStr); + + //remove \r + for (i=0,tmpi=0; tmpStr[i]!='\0'; i++) + if (tmpStr[i] != '\r') + tmpStr[tmpi++] = tmpStr[i]; + tmpStr[tmpi] = '\0'; + + fputs(tmpStr,fp); + + fclose(fp); + free(tmpStr); + + MessageBox(hW,(LPCTSTR)"File saved sucessfully.",NULL,(UINT)MB_ICONINFORMATION); + + return TRUE; + + case IDC_REFRESHPATCHLIST: + + //List Patches + ListPatches ((HWND) hW); + + return TRUE; + + case IDC_EXITPB: + + //Close Dialog + EndDialog(hW, FALSE); + + return TRUE; + + case IDC_PATCHCRCLIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + return ReadPatch ((HWND) hW, fileName); + + case IDC_PATCHNAMELIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + //another small hack :p + //eg. SOCOM Demo PAL (7dd01dd9.pnach) + for (i=0;i<(int)strlen(fileName);i++) + if (fileName[i] == '(') tmpi = i; + + sprintf(fileName,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + fileName[tmpi+1],fileName[tmpi+2],fileName[tmpi+3], + fileName[tmpi+4],fileName[tmpi+5],fileName[tmpi+6], + fileName[tmpi+7],fileName[tmpi+8],fileName[tmpi+9], + fileName[tmpi+10],fileName[tmpi+11],fileName[tmpi+12], + fileName[tmpi+13],fileName[tmpi+14]); + + //sanity check + if (fileName[tmpi+15] != ')') return FALSE; + + return ReadPatch ((HWND) hW, fileName); + + case IDC_SEARCHPATCHTEXT: + + //get text + SendDlgItemMessage(hW, IDC_SEARCHPATCHTEXT, EM_GETLINE, 0, (LPARAM)fileName); + //search + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)fileName); + //select match item + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_SETCURSEL, (WPARAM)tmpi, (LPARAM)NULL); + + return TRUE; + } + return TRUE; + + case WM_CLOSE: + EndDialog(hW, FALSE); + break; + + } + return FALSE; +} +void ListPatches (HWND hW) { + + int i, tmpi, filesize, totalPatch=0, totalSize=0; + char tmpStr[MAX_PATH], *fileData; + WIN32_FIND_DATA FindData; + HANDLE Find; + FILE *fp; + + //clear listbox's + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + + //sprintf(tmpStr,"%s*.pnach", Config.PatchDir) + sprintf(tmpStr, "patches\\*.pnach"); + + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + + sprintf(tmpStr,"%s", FindData.cFileName); + + //add file name to crc list + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT) LB_ADDSTRING, (WPARAM)NULL, (LPARAM)tmpStr); + + //sprintf(tmpStr,"%s%s", Config.PatchDir, FindData.cFileName) + sprintf(tmpStr,"patches\\%s", FindData.cFileName); + + fp = fopen(tmpStr, "r"); + if (fp == NULL) break; + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + totalSize += filesize; + fseek(fp, 0, SEEK_SET); + + fileData = (char *) malloc(filesize+1024); + sprintf(fileData,""); + + //read file + while((tmpi=fgetc(fp)) != EOF) + sprintf(fileData,"%s%c",fileData,tmpi); + + //small hack :p + for(i=0;ii;tmpi--) + fileData[tmpi] = fileData[tmpi-1]; + fileData[i] = '\r'; + fileData[i+1] = '\n'; + i++; + } + } + + SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)fileData); + + sprintf(fileData,""); + fclose(fp); + + return TRUE; +} + + +//Left Trim (remove the spaces at the left of a string) +char * lTrim (char *s) { + int count=0,i,tmpi; + + for (i=0;i<(int)strlen(s); i++) { + if (s[i] == ' ') count++; + else { + for (tmpi=0;tmpi<(int)strlen(s);tmpi++) + s[tmpi] = s[tmpi+count]; + break; + } + } + return s; +} + + +BOOL Save_Patch_Proc( char * filename ) { + + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "Patch Files (*.pnach)\0*.pnach\0ALL Files (*.*)\0*.*"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "TXT"; + ofn.Flags = OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + if ( GetSaveFileName( &ofn ) ) { + + strcpy( filename, szFileName ); + + return TRUE; + } + else { + return FALSE; + } +} diff --git a/branches/pcsx2_0.9.2/windows/RDebugger.c b/branches/pcsx2_0.9.2/windows/RDebugger.c new file mode 100644 index 0000000..576cc57 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/RDebugger.c @@ -0,0 +1,375 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "RDebugger.h" +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "../rdebug/deci2.h" + +u32 port=8510; +SOCKET serversocket, remote; +char message[1024]; //message to add to listbox + +int runStatus=STOP, runCode=0, runCount=1; +HANDLE runEvent=NULL; + +DECI2_DBGP_BRK ebrk[32], + ibrk[32]; +int ebrk_count=0, + ibrk_count=0; + +int debuggedCpu=0; //default is to debug EE cpu; IOP=1 +u32 breakAddress=0; //disabled; ie. you cannot use address 0 for a breakpoint +u32 breakCycle=0; //disabled; ie. you cannot stop after 0 cycles + +int CreateSocket(HWND hDlg, int port){ + WSADATA wsadata; + SOCKADDR_IN saServer; + + if (WSAStartup( MAKEWORD(1, 1), &wsadata) || + ((serversocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET)){ + MessageBox(hDlg, "Could not create socket\n[Is TCP/IP installed? WinSock 1.1 or above?]", 0, MB_OK); + return FALSE; + } + sprintf(message, "[PCSX2] %s status=%s", wsadata.szDescription, wsadata.szSystemStatus); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + saServer.sin_family = AF_INET; + saServer.sin_addr.S_un.S_addr = INADDR_ANY; // accept any address + saServer.sin_port = htons(port); // port to listen to + + if (bind(serversocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr))==SOCKET_ERROR){ + sprintf(message, "Could not bind to port %d\n" + "[Is there another server running on that port?]", port); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Port %d is opened", port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + // SOMAXCONN connections in queque? maybe 1 is enough... + if (listen(serversocket, SOMAXCONN) == SOCKET_ERROR){ + sprintf(message, "Listening for a connection failed\n" + "[dunno?]"); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Listening for a connection to establish..."); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + cpuRegs.CP0.n.EPC=cpuRegs.pc; + psxRegs.CP0.n.EPC=psxRegs.pc; + sprintf(message, "%08X", cpuRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), message); + sprintf(message, "%08X", psxRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), message); + sprintf(message, "%d", cpuRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), message); + sprintf(message, "%d", psxRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), message); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGEE), (debuggedCpu==0)); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGIOP), (debuggedCpu==1)); + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAT), 8); //8 hex digits + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAFTER), 10);//10 decimal digits + sprintf(message, "%08X", breakAddress); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAT), message); + sprintf(message, "%d", breakCycle); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), message); + + Button_Enable(GetDlgItem(hDlg, IDC_DEBUGIOP), FALSE);//////////////////////// + + return TRUE; +} + +int readData(char *buffer){ + int r, count=0; + u8 *p=buffer; + + memset(buffer, 0, BUFFERSIZE); + while (((count+= r = recv(remote, p, BUFFERSIZE, 0))!=INVALID_SOCKET) && + (count<*(u16*)buffer)) + p+=r; + + if (r==INVALID_SOCKET) + return 0; + + return count; +} + +int writeData(char *result){ + int r;/*, i; + static char l[300], p[10]; + DECI2_HEADER *header=(DECI2_HEADER*)result; +*/ + r = send(remote, result, *(u16*)result, 0); + if (r==SOCKET_ERROR) + return 0; +/* + sprintf(l, "size=%d, src=%c dst=%c proto=0x%04X ", + header->length-8, header->source, header->destination, header->protocol); + for (i=8; i<*(u16*)result; i++){ + sprintf(p, "%02X ", result[i]); + strcat(l, p); + } + SysMessage(l); +*/ + return r; +} + +DWORD WINAPI ServingFunction(LPVOID lpParam){ + static u8 buffer[BUFFERSIZE], //a big buffer + result[BUFFERSIZE], //a big buffer + eepc[9], ioppc[9], eecy[15], iopcy[15]; + SOCKADDR_IN saClient; + HWND hDlg=(HWND)lpParam; + DWORD size=sizeof(struct sockaddr); + int exit=FALSE; + + if ((remote = accept(serversocket, (struct sockaddr*)&saClient, &size))==INVALID_SOCKET){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Commmunication lost. THE END"); + return FALSE; + } + sprintf(message, "[PCSX2] Connected to %d.%d.%d.%d on remote port %d", + saClient.sin_addr.S_un.S_un_b.s_b1, + saClient.sin_addr.S_un.S_un_b.s_b2, + saClient.sin_addr.S_un.S_un_b.s_b3, + saClient.sin_addr.S_un.S_un_b.s_b4, + saClient.sin_port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Start serving..."); + connected=1;//from this point on, all log stuff goes to ttyp + + //sendBREAK('E', 0, 0xff, 0x21, 1); //do not enable this unless you know what you are doing! + while (!exit && readData(buffer)){ + DECI2_HEADER *header=(DECI2_HEADER*)buffer; + + switch(header->protocol){ + case 0x0000:exit=TRUE; break; + case PROTO_DCMP:D2_DCMP(buffer, result, message); break; +// case 0x0120:D2_DRFP_EE(buffer, result, message); break; +// case 0x0121:D2_DRFP_IOP(buffer, result, message); break; +// case 0x0122:break; + case PROTO_IDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy); break; +// case 0x0140:break; + case PROTO_ILOADP:D2_ILOADP(buffer, result, message); break; + case PROTO_EDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy);break; +// case 0x0240:break; + case PROTO_NETMP:D2_NETMP(buffer, result, message); break; + default: + sprintf(message, "[DECI2 %c->%c/%04X] Protocol=0x%04X", + header->source, header->destination, + header->length, header->protocol); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + continue; + } + if (exit==FALSE){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), eepc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), ioppc); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), eecy); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), iopcy); + } + } + connected=0; + + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Connection closed. THE END"); + return TRUE; +} + +DWORD WINAPI Run2(LPVOID lpParam){ + HWND hDlg=(HWND)lpParam; + static char pc[9]; + int i; + + while (1){ + if (runStatus==RUN){ + if (PSMu32(cpuRegs.pc)==0x0000000D){ + sendBREAK('E', 0, runCode, 0x22, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((runCode==2) && (//next + ((PSMu32(cpuRegs.pc) & 0xFC000000)==0x0C000000) ||//JAL + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x00000009) ||//JALR + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C) //SYSCALL + )){u32 tmppc=cpuRegs.pc, skip=(PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C ? 4 : 8; + while (cpuRegs.pc!=tmppc+skip) + Cpu->Step(); + }else + Cpu->Step(); //use this with breakpoints & step-by-step +// Cpu->ExecuteBlock(); //use this to run faster, but not for stepping +// sprintf(pc, "%08X", cpuRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), pc); +// sprintf(pc, "%08X", psxRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), pc); +// sprintf(pc, "%d", cpuRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), pc); +// sprintf(pc, "%d", psxRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), pc); + if (runCount!=0 && --runCount==0){ + sendBREAK('E', 0, runCode, 0x23, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakAddress) && (breakAddress==cpuRegs.pc)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakCycle) && (breakCycle==cpuRegs.cycle)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + breakCycle=0; + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), "0"); + continue; + } + for (i=0; i +#include +#include + +#define BUFFERSIZE (128*1024) + +extern LRESULT WINAPI RemoteDebuggerParamsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern LRESULT WINAPI RemoteDebuggerProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.sln b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.sln new file mode 100644 index 0000000..78bd7db --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2003.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug TLB = Debug TLB + Release = Release + Release (to Public) = Release (to Public) + Release TLB = Release TLB + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.ActiveCfg = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.Build.0 = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.Build.0 = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).ActiveCfg = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).Build.0 = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.Build.0 = Release TLB|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.vcproj b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.vcproj new file mode 100644 index 0000000..bfc8db7 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2003.vcproj @@ -0,0 +1,1260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.sln b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.sln new file mode 100644 index 0000000..2bd4145 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug TLB|Win32 = Debug TLB|Win32 + Debug|Win32 = Debug|Win32 + Release TLB|Win32 = Release TLB|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.ActiveCfg = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.Build.0 = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.vcproj b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.vcproj new file mode 100644 index 0000000..204c242 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005.vcproj @@ -0,0 +1,1535 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.sln b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.sln new file mode 100644 index 0000000..98a5f30 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005beta1_64bits.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj new file mode 100644 index 0000000..1c3da07 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/VCprojects/pcsx2_2005beta1_64bits.vcproj @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/pcsx2_0.9.2/windows/Win32.h b/branches/pcsx2_0.9.2/windows/Win32.h new file mode 100644 index 0000000..607396d --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/Win32.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIN32_H__ +#define __WIN32_H__ + +extern int needReset; + +AppData gApp; +HWND hStatusWnd; + +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); +void CreateMainWindow(int nCmdShow); +void RunGui(); +int LoadConfig(); +void SaveConfig(); + +BOOL Open_File_Proc(char *filename); +BOOL Pcsx2Configure(HWND hWnd); +void RunExecute(int run); +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); +void OpenConsole(); +void CloseConsole(); +#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text); + +//patch browser window +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +//cpu dialog window +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + diff --git a/branches/pcsx2_0.9.2/windows/WinMain.c b/branches/pcsx2_0.9.2/windows/WinMain.c new file mode 100644 index 0000000..edb913f --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/WinMain.c @@ -0,0 +1,1977 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "resource.h" +#include "debugger.h" +#include "rdebugger.h" +#include "AboutDlg.h" +#include "McdsDlg.h" + +#include "VU.h" +#include "iCore.h" +#include "iVUzerorec.h" + +#include "cheats/cheats.h" + +#define COMPILEDATE __DATE__ + +static int efile; +char filename[256]; +extern char strgametitle[256]; +extern int g_SaveGSStream; + +static int AccBreak = 0; +int needReset = 1; +unsigned int langsMax; +typedef struct { + char lang[256]; +} _langs; +_langs *langs = NULL; + +int nDisableSC = 0; // screensaver +int firstRun=1; + +void OpenConsole() { + COORD csize; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + SMALL_RECT srect; + + if (gApp.hConsole) return; + AllocConsole(); + SetConsoleTitle(_("Ps2 Output")); + csize.X = 100; + csize.Y = 1024; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + srect = csbiInfo.srWindow; + srect.Right = srect.Left + 99; + srect.Bottom = srect.Top + 64; + SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); + gApp.hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} + +void CloseConsole() { + if (gApp.hConsole == NULL) return; + FreeConsole(); gApp.hConsole = NULL; +} +void strcatz(char *dst, char *src) { + int len = strlen(dst) + 1; + strcpy(dst + len, src); +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def +//------------------- + +void RunExecute(int run) { + SetThreadPriority(GetCurrentThread(), Config.ThPriority); + SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); + nDisableSC = 1; + + if (needReset == 1) { + SysReset(); + } + + AccBreak = 1; + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + + if (OpenPlugins() == -1) { + CreateMainWindow(SW_SHOWNORMAL); + return; + } + + if (needReset == 1) { + cpuExecuteBios(); + if (efile == 2) + efile=GetPS2ElfName(filename); + if (efile) + loadElfFile(filename); + efile=0; + needReset = 0; + } + + // this needs to be called for every new game! (note: sometimes launching games through bios will give a crc of 0) + if( GSsetGameCRC != NULL ) + GSsetGameCRC(ElfCRC); + + if (run) Cpu->Execute(); +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + int i; + + for (i=0; i<5; i++) { + if (Slots[i] == -1) + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED); + else + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf (str, "sstates\\%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); + if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + StatusSet(Text); + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %d"), num+1); + else sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1); + StatusSet(Text); + + RunExecute(1); +} + +void OnStates_LoadOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + ret = LoadState(szFileName); + + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Saving State %s"), szFileName); + StatusSet(Text); + + Cpu->Execute(); + } +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +char* g_pRunGSState = NULL; + +void OnStates_SaveOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + ret = SaveState(szFileName); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Loaded State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Loading State %s"), szFileName); + StatusSet(Text); + + RunExecute(1); + } +} + +#ifdef PCSX2_DEVBUILD + +TESTRUNARGS g_TestRun; + +static int ParseCommandLine(char* pcmd) +{ + const char* pdelim = " \t\r\n"; + char* token = strtok(pcmd, pdelim); + + g_TestRun.efile = 1; + + while(token != NULL) { + + if( stricmp(token, "-help") == 0) { + MessageBox(NULL, "pcsx2 [-option value]\n" + "\tPcsx2 Team 2003-2006\n\n" + "-help {display this help file}\n" + "-title [name] {run this image/iso/elf}\n" + "-image [name] {path and base name of image (do not include the .ext)}\n" + "-log [name] {log path to save log file in}\n" + "-logopt [hex] {log options in hex (see debug.h) }\n" + "-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n" + "-frame [frame] {game will run up to this frame before exiting}\n" + "-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n" + "-jpg {save images to jpg format}\n" + "-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n" + "-gs [dllpath] {specify the dll load path of the GS plugin}\n" + "-cdvd [dllpath] {specify the dll load path of the CDVD plugin}\n" + "-spu [dllpath] {specify the dll load path of the SPU2 plugin}\n", + "Help", MB_OK); + return -1; + } + else if( stricmp(token, "-title") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.ptitle = token; + } + else if( stricmp(token, "-image") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pimagename = token; + } + else if( stricmp(token, "-log") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.plogname = token; + } + else if( stricmp(token, "-logopt") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + if( token[0] == '0' && token[1] == 'x' ) token += 2; + sscanf(token, "%x", &varLog); + } + } + else if( stricmp(token, "-pad") == 0 ) { + token = strtok(NULL, pdelim); + printf("-pad ignored\n"); + } + else if( stricmp(token, "-frame") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.frame = atoi(token); + } + } + else if( stricmp(token, "-numimages") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.numimages = atoi(token); + } + } + else if( stricmp(token, "-efile") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.efile = atoi(token); + } + } + else if( stricmp(token, "-jpg") == 0 ) { + g_TestRun.jpgcapture = 1; + } + else if( stricmp(token, "-gs") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pgsdll = token; + } + else if( stricmp(token, "-cdvd") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pcdvddll = token; + } + else if( stricmp(token, "-spu") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pspudll = token; + } + else if( stricmp(token, "-loadgs") == 0 ) { + token = strtok(NULL, pdelim); + g_pRunGSState = token; + } + else { + printf("invalid args\n"); + return -1; + } + + if( token == NULL ) { + printf("invalid args\n"); + return -1; + } + + token = strtok(NULL, pdelim); + } + + if( g_TestRun.ptitle != NULL ) + g_TestRun.enabled = 1; + + return 0; +} + +#endif +extern void LoadPatch(char *crc); + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char *lang; + int i; + +#ifdef WIN32_VIRTUAL_MEM + LPVOID lpMemReserved; +#endif + + InitCommonControls(); + pInstance=hInstance; + FirstShow=true; + +#ifdef WIN32_VIRTUAL_MEM + + if( !SysLoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) ) + return 0; + + lpMemReserved = VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); + + if( lpMemReserved == NULL || lpMemReserved!= PS2MEM_BASE ) { + char str[255]; + sprintf(str, "Cannot allocate mem addresses 0x20000000-0x40000000, err: %d", GetLastError()); + MessageBox(NULL, str, "SysError", MB_OK); + return 0; + } +#endif + + gApp.hInstance = hInstance; + gApp.hMenu = NULL; + gApp.hWnd = NULL; + gApp.hConsole = NULL; + +#ifdef ENABLE_NLS + bindtextdomain(PACKAGE, "Langs\\"); + textdomain(PACKAGE); +#endif + + if (LoadConfig() == -1) { + memset(&Config, 0, sizeof(Config)); + //strcpy(Config.Bios, "HLE"); + strcpy(Config.BiosDir, "Bios\\"); + strcpy(Config.PluginsDir, "Plugins\\"); + Config.Patch = 1; + + SysMessage(_("Pcsx2 needs to be configured")); + Pcsx2Configure(NULL); + + return 0; + } + if (Config.Lang[0] == 0) { + strcpy(Config.Lang, "en_US"); + } + + langs = (_langs*)malloc(sizeof(_langs)); + strcpy(langs[0].lang, "en_US"); + InitLanguages(); i=1; + while ((lang = GetLanguageNext()) != NULL) { + langs = (_langs*)realloc(langs, sizeof(_langs)*(i+1)); + strcpy(langs[i].lang, lang); + i++; + } + CloseLanguages(); + langsMax = i; + + if (Config.PsxOut) OpenConsole(); + +#ifdef PCSX2_DEVBUILD + memset(&g_TestRun, 0, sizeof(g_TestRun)); + + if( lpCmdLine == NULL || *lpCmdLine == 0 ) + SysPrintf("-help to see arguments\n"); + else if( ParseCommandLine(lpCmdLine) == -1 ) { + return 2; + } + + if( g_TestRun.pgsdll ) + _snprintf(Config.GS, sizeof(Config.GS), "%s", g_TestRun.pgsdll); + if( g_TestRun.pcdvddll ) + _snprintf(Config.CDVD, sizeof(Config.CDVD), "%s", g_TestRun.pcdvddll); + if( g_TestRun.pspudll ) + _snprintf(Config.SPU2, sizeof(Config.SPU2), "%s", g_TestRun.pspudll); +#endif + + if (SysInit() == -1) return 1; + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled ) { + // run without ui + _snprintf(filename, sizeof(filename), "%s", g_TestRun.ptitle); + needReset = 1; + efile = g_TestRun.efile; + RunExecute(1); + SysClose(); + return 0; // success! + } +#endif + +#ifdef PCSX2_DEVBUILD + if( g_pRunGSState ) { + LoadGSState(g_pRunGSState); + SysClose(); + return 0; + } +#endif + + CreateMainWindow(nCmdShow); + + // output the help commands + SysPrintf("\tF1 - save state\n"); + SysPrintf("\t(Shift +) F2 - cycle states\n"); + SysPrintf("\tF3 - load state\n"); + +#ifdef PCSX2_DEVBUILD + SysPrintf("\tF10 - dump performance counters\n"); + SysPrintf("\tF11 - save GS state\n"); + SysPrintf("\tF12 - dump hardware registers\n"); +#endif + + LoadPatch("default"); + + RunGui(); + +#ifdef WIN32_VIRTUAL_MEM + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); +#endif + + return 0; +} + +void RunGui() { + MSG msg; + + for (;;) { + if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + Sleep(10); + } +} + +#define NUM_STATES 10 +int StatesC = 0; +extern void iDumpRegisters(u32 startpc, u32 temp); +extern void recExecuteVU1Block(void); +extern void DummyExecuteVU1Block(void); + +void CALLBACK KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + switch (ev->key) { + case VK_F1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); + break; + case VK_F2: + if( (GetKeyState(VK_SHIFT)&0x8000) ) + StatesC = (StatesC+NUM_STATES-1)%NUM_STATES; + else + StatesC = (StatesC+1)%NUM_STATES; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); + if( GSchangeSaveState != NULL ) { + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + GSchangeSaveState(StatesC, Text); + } + break; + case VK_F3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); + break; + + case VK_F4: + // cycle + Config.Options = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_LIMIT)&PCSX2_FRAMELIMIT_MASK); + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_NORMAL: + if( GSsetFrameSkip != NULL ) GSsetFrameSkip(0); + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Normal - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_LIMIT: + if( GSsetFrameSkip != NULL ) GSsetFrameSkip(0); + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Limit - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_SKIP: + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Frame Skip - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_VUSKIP: + SysPrintf("VU Skip - Frame Limit Mode Changed\n"); + break; + } + SaveConfig(); + break; + // note: VK_F5-VK_F7 are reserved for GS + case VK_F8: + GSmakeSnapshot("snap\\"); + break; + +#ifdef PCSX2_DEVBUILD + case VK_F10: + { + int num; + FILE* f; + BASEBLOCKEX** ppblocks = GetAllBaseBlocks(&num, 0); + + f = fopen("perflog.txt", "w"); + while(num-- > 0 ) { + if( ppblocks[0]->visited > 0 ) { + fprintf(f, "%u %u %u %u\n", ppblocks[0]->startpc, (u32)(ppblocks[0]->ltime.QuadPart / ppblocks[0]->visited), ppblocks[0]->visited, ppblocks[0]->size); + } + ppblocks[0]->visited = 0; + ppblocks[0]->ltime.QuadPart = 0; + ppblocks++; + } + fclose(f); + SysPrintf("perflog.txt written\n"); + break; + } + + case VK_F11: + if( CHECK_MULTIGS ) { + SysPrintf("Cannot make gsstates in MTGS mode\n"); + } + else { + if( strgametitle[0] != 0 ) { + // only take the first two words + char name[255], temptitle[255], *tok; + _snprintf(temptitle, 255, "%s", strgametitle); + tok = strtok(strgametitle, " "); + sprintf(name, "%s_", strlwr(tok)); + tok = strtok(NULL, " "); + if( tok != NULL ) strcat(name, tok); + + sprintf(Text, "sstates/gs_%s.%3.3d", name, StatesC); + } + else + sprintf(Text, "sstates/gs%8.8X.%3.3d", ElfCRC, StatesC); + + SaveGSState(Text); + } + break; + + case VK_F12: + iDumpRegisters(cpuRegs.pc, 0); + SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc); + break; +#endif + + case VK_ESCAPE: +#ifdef PCSX2_DEVBUILD + if( g_SaveGSStream >= 3 ) { + // gs state + g_SaveGSStream = 4; + break; + } +#endif + + ClosePlugins(); + CreateMainWindow(SW_SHOWNORMAL); + RunGui(); + nDisableSC = 0; + break; + default: + GSkeyEvent(ev); + break; + } +} + +#ifdef PCSX2_DEVBUILD + +BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { + int i; + switch (message) { + case WM_INITDIALOG: + for (i=0; i<32; i++) + if (varLog & (1<= ID_LANGS && LOWORD(wParam) <= (ID_LANGS + langsMax)) { + AccBreak = 1; + DestroyWindow(gApp.hWnd); + ChangeLanguage(langs[LOWORD(wParam) - ID_LANGS].lang); + CreateMainWindow(SW_NORMAL); + return TRUE; + } + } + break; + case WM_DESTROY: + if (!AccBreak) { + SysClose(); + DeleteObject(hbitmap_background); + PostQuitMessage(0); + exit(0); + } else AccBreak = 0; + return TRUE; + + case WM_SYSCOMMAND: + if( nDisableSC && (wParam== SC_SCREENSAVE || wParam == SC_MONITORPOWER) ) { + return FALSE; + } + else + return DefWindowProc(hWnd, msg, wParam, lParam); + break; + + case WM_QUIT: + if (Config.PsxOut) CloseConsole(); + exit(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + return FALSE; +} + +#define _ADDSUBMENU(menu, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDSUBMENU(menun, string) \ + _ADDSUBMENU(gApp.hMenu, menun, string); + +#define ADDSUBMENUS(submn, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDMENUITEM(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDMENUITEMC(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED | MFS_CHECKED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDSEPARATOR(menun) \ + item.fMask = MIIM_TYPE; \ + item.fType = MFT_SEPARATOR; \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +void CreateMainMenu() { + MENUITEMINFO item; + HMENU submenu[5]; + char buf[256]; + int i; + + item.cbSize = sizeof(MENUITEMINFO); + item.dwTypeData = buf; + item.cch = 256; + + gApp.hMenu = CreateMenu(); + + //submenu = CreatePopupMenu(); + //AppendMenu(gApp.hMenu, MF_STRING | MF_POPUP, (UINT)submenu, _("&File")); + ADDSUBMENU(0, _("&File")); + ADDMENUITEM(0, _("E&xit"), ID_FILE_EXIT); + ADDSEPARATOR(0); + ADDSUBMENUS(0, 1, _("&States")); + ADDSEPARATOR(0); + ADDMENUITEM(0, _("&Open ELF File"), ID_FILEOPEN); + ADDMENUITEM(0, _("&Run CD/DVD"), ID_FILE_RUNCD); + ADDSUBMENUS(1, 3, _("&Save")); + ADDSUBMENUS(1, 2, _("&Load")); + ADDMENUITEM(2, _("&Other..."), ID_FILE_STATES_LOAD_OTHER); + ADDMENUITEM(2, _("Slot &5"), ID_FILE_STATES_LOAD_SLOT5); + ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT4); + ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT3); + ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT2); + ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT1); + ADDMENUITEM(3, _("&Other..."), ID_FILE_STATES_SAVE_OTHER); + ADDMENUITEM(3, _("Slot &5"), ID_FILE_STATES_SAVE_SLOT5); + ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT4); + ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT3); + ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT2); + ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT1); + + ADDSUBMENU(0, _("&Run")); + + ADDSUBMENUS(0, 1, _("&Process Priority")); + ADDMENUITEM(1, _("&Low"), ID_PROCESSLOW ); + ADDMENUITEM(1, _("High"), ID_PROCESSHIGH); + ADDMENUITEM(1, _("Normal"), ID_PROCESSNORMAL); + ADDMENUITEM(0,_("&Arguments"), ID_RUN_CMDLINE); + ADDMENUITEM(0,_("Re&set"), ID_RUN_RESET); + ADDMENUITEM(0,_("E&xecute"), ID_RUN_EXECUTE); + + ADDSUBMENU(0,_("&Config")); +#ifdef PCSX2_DEVBUILD +// ADDMENUITEM(0,_("&Advanced"), ID_CONFIG_ADVANCED); +#endif + ADDMENUITEM(0,_("&Patches"), ID_PATCHBROWSER); + ADDMENUITEM(0,_("C&pu"), ID_CONFIG_CPU); + ADDMENUITEM(0,_("&Memcards"), ID_CONFIG_MEMCARDS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("Fire&Wire"), ID_CONFIG_FW); + ADDMENUITEM(0,_("U&SB"), ID_CONFIG_USB); + ADDMENUITEM(0,_("D&ev9"), ID_CONFIG_DEV9); + ADDMENUITEM(0,_("C&dvdrom"), ID_CONFIG_CDVDROM); + ADDMENUITEM(0,_("&Sound"), ID_CONFIG_SOUND); + ADDMENUITEM(0,_("C&ontrollers"), ID_CONFIG_CONTROLLERS); + ADDMENUITEM(0,_("&Graphics"), ID_CONFIG_GRAPHICS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("&Configure"), ID_CONFIG_CONFIGURE); + + ADDSUBMENU(0,_("&Language")); + + for (i=langsMax-1; i>=0; i--) { + if (!strcmp(Config.Lang, langs[i].lang)) { + ADDMENUITEMC(0,ParseLang(langs[i].lang), ID_LANGS + i); + } else { + ADDMENUITEM(0,ParseLang(langs[i].lang), ID_LANGS + i); + } + } + +#ifdef PCSX2_DEVBUILD + ADDSUBMENU(0, _("&Debug")); + ADDMENUITEM(0,_("&Logging"), ID_DEBUG_LOGGING); + ADDMENUITEM(0,_("Memory Dump"), ID_DEBUG_MEMORY_DUMP); + ADDMENUITEM(0,_("&Remote Debugging"), ID_DEBUG_REMOTEDEBUGGING); + ADDMENUITEM(0,_("Enter &Debugger..."), ID_DEBUG_ENTERDEBUGGER); +#endif + + ADDSUBMENU(0, _("&Misc")); + ADDMENUITEM(0,("Enable &Patches"), ID_PATCHES); + ADDMENUITEM(0,("Enable &Console"), ID_CONSOLE); + ADDSEPARATOR(0); + ADDMENUITEM(0,("Patch &Finder..."), ID_CHEAT_FINDER_SHOW); + ADDMENUITEM(0,("Patch &Browser..."), ID_CHEAT_BROWSER_SHOW); + + + ADDSUBMENU(0, _("&Help")); + ADDMENUITEM(0,_("&Compatibility List..."), ID_HELP_HELP); + ADDMENUITEM(0,_("&About..."), ID_HELP_ABOUT); + +#ifndef PCSX2_DEVBUILD + EnableMenuItem(GetSubMenu(gApp.hMenu, 4), ID_DEBUG_LOGGING, MF_GRAYED); +#endif +} + +void CreateMainWindow(int nCmdShow) { + WNDCLASS wc; + HWND hWnd; + char buf[256]; + char COMPILER[20]=""; + BITMAP bm; + RECT rect; + int w, h; + +#ifdef _MSC_VER + sprintf(COMPILER, "(VC%d)", (_MSC_VER+100)/200);//hacky:) works for VC6 & VC.NET +#elif __BORLANDC__ + sprintf(COMPILER, "(BC)"); +#endif + /* Load Background Bitmap from the ressource */ + hbitmap_background = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + + wc.lpszClassName = "PCSX2 Main"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = gApp.hInstance; + wc.hIcon = LoadIcon(gApp.hInstance, MAKEINTRESOURCE(IDI_ICON)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_MENUTEXT); + wc.lpszMenuName = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + + RegisterClass(&wc); + GetObject(hbitmap_background, sizeof(bm), &bm); + + { +#ifdef WIN32_VIRTUAL_MEM + const char* pvm = "VM"; +#else + const char* pvm = "non VM"; +#endif + +#ifdef PCSX2_DEVBUILD + sprintf(buf, _("PCSX2 %s Watermoose - %s Compile Date - %s %s"), PCSX2_VERSION, pvm, COMPILEDATE, COMPILER); +#else + sprintf(buf, _("PCSX2 %s Watermoose - %s"), PCSX2_VERSION, pvm); +#endif + } + + hWnd = CreateWindow("PCSX2 Main", + buf, WS_OVERLAPPED | WS_SYSMENU, + 20, 20, 320, 240, NULL, NULL, + gApp.hInstance, NULL); + + gApp.hWnd = hWnd; + ResetMenuSlots(); + CreateMainMenu(); + + SetMenu(gApp.hWnd, gApp.hMenu); + if(Config.ThPriority==THREAD_PRIORITY_NORMAL) CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_HIGHEST) CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_LOWEST) CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); + if(Config.PsxOut) CheckMenuItem(gApp.hMenu,ID_CONSOLE,MF_CHECKED); + if(Config.Patch) CheckMenuItem(gApp.hMenu,ID_PATCHES,MF_CHECKED); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "PCSX2 %s", PCSX2_VERSION); + StatusSet(buf); + + w = bm.bmWidth; h = bm.bmHeight; + GetWindowRect(hStatusWnd, &rect); + h+= rect.bottom - rect.top; + GetMenuItemRect(hWnd, gApp.hMenu, 0, &rect); + h+= rect.bottom - rect.top; + MoveWindow(hWnd, 20, 20, w, h, TRUE); + + DestroyWindow(hStatusWnd); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot", PCSX2_VERSION); + StatusSet(buf); + ShowWindow(hWnd, nCmdShow); + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} + +BOOL Open_File_Proc(char * filename) { + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "ELF"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) { + struct stat buf; + + if (stat(szFileName, &buf) != 0) { + return FALSE; + } + + strcpy(filename, szFileName); + return TRUE; + } + + return FALSE; +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetWindowText(hDlg, _("Program arguments")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); + Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); + Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); + + SetDlgItemText(hDlg, IDC_CMDLINE, args); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + char tmp[256]; + + GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); + + ZeroMemory(args, 256); + strcpy(args, tmp); + args[255]=0; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +WIN32_FIND_DATA lFindData; +HANDLE lFind; +int lFirst; + +void InitLanguages() { + lFind = FindFirstFile("Langs\\*", &lFindData); + lFirst = 1; +} + +char *GetLanguageNext() { + for (;;) { + if (!strcmp(lFindData.cFileName, ".")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + if (!strcmp(lFindData.cFileName, "..")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + break; + } + if (lFirst == 0) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + } else lFirst = 0; + if (lFind==INVALID_HANDLE_VALUE) return NULL; + + return lFindData.cFileName; +} + +void CloseLanguages() { + if (lFind!=INVALID_HANDLE_VALUE) FindClose(lFind); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +//------------------- + +static int sinit=0; + +int SysInit() { + CreateDirectory("memcards", NULL); + CreateDirectory("sstates", NULL); +#ifdef EMU_LOG + CreateDirectory("logs", NULL); + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.plogname != NULL ) + emuLog = fopen(g_TestRun.plogname, "w"); + if( emuLog == NULL ) + emuLog = fopen("logs\\emuLog.txt","w"); +#endif + + if( emuLog != NULL ) + setvbuf(emuLog, NULL, _IONBF, 0); + +#endif + if (cpuInit() == -1) return -1; + + while (LoadPlugins() == -1) { + if (Pcsx2Configure(NULL) == FALSE) { + exit(1); + } + } + + sinit=1; + + return 0; +} + +void SysReset() { + if (sinit == 0) return; + StatusSet(_("Resetting...")); + cpuReset(); + StatusSet(_("Ready")); +} + + +void SysClose() { + if (sinit == 0) return; + cpuShutdown(); + ReleasePlugins(); + sinit=0; +} + +int concolors[] = { + 0, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_GREEN | FOREGROUND_RED, + FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +}; + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + char *ptr; + DWORD tmp; + int len, s; + int i, j; + + if (Config.PsxOut == 0) return; + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + msg[511] = '\0'; + va_end(list); + + ptr = msg; len = strlen(msg); + for (i=0, j=0; i 0x7ffe) // String is too large + return FALSE; + } + + // Store the string. + pLsaString->Buffer = (WCHAR *)pwszString; + pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR); + pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR); + + return TRUE; +} + +PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucName; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList; + //LSA_TRUST_INFORMATION myDomain; + NTSTATUS ntsResult; + PWCHAR DomainString = NULL; + + // Initialize an LSA_UNICODE_STRING with the name. + if (!InitLsaString(&lucName, AccountName)) + { + wprintf(L"Failed InitLsaString\n"); + return NULL; + } + + ntsResult = LsaLookupNames2( + PolicyHandle, // handle to a Policy object + 0, + 1, // number of names to look up + &lucName, // pointer to an array of names + &lrdlDomainList, // receives domain information + <sTranslatedSID // receives relative SIDs + ); + if (0 != ntsResult) + { + wprintf(L"Failed LsaLookupNames - %lu \n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + + // Get the domain the account resides in. +// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex]; +// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1); +// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length); + + // Display the relative Id. +// wprintf(L"Relative Id is %lu in domain %ws.\n", +// ltsTranslatedSID->RelativeId, +// DomainString); + + LsaFreeMemory(lrdlDomainList); + + return ltsTranslatedSID; +} + +BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle, BOOL bAdd) +{ + LSA_UNICODE_STRING lucPrivilege; + NTSTATUS ntsResult; + + // Create an LSA_UNICODE_STRING for the privilege name(s). + if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege")) + { + wprintf(L"Failed InitLsaString\n"); + return FALSE; + } + + if( bAdd ) { + ntsResult = LsaAddAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID. + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + } + else { + ntsResult = LsaRemoveAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID + FALSE, + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + } + + if (ntsResult == 0) + { + wprintf(L"Privilege added.\n"); + } + else + { + int err = LsaNtStatusToWinError(ntsResult); + char str[255]; + _snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult)); + MessageBox(NULL, str, "Privilege error", MB_OK); + return FALSE; + } + + return TRUE; +} + +#define TARGET_SYSTEM_NAME L"mysystem" +LSA_HANDLE GetPolicyHandle() +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR SystemName[] = TARGET_SYSTEM_NAME; + USHORT SystemNameLength; + LSA_UNICODE_STRING lusSystemName; + NTSTATUS ntsResult; + LSA_HANDLE lsahPolicyHandle; + + // Object attributes are reserved, so initialize to zeroes. + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + //Initialize an LSA_UNICODE_STRING to the server name. + SystemNameLength = wcslen(SystemName); + lusSystemName.Buffer = SystemName; + lusSystemName.Length = SystemNameLength * sizeof(WCHAR); + lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR); + + // Get a handle to the Policy object. + ntsResult = LsaOpenPolicy( + NULL, //Name of the target system. + &ObjectAttributes, //Object attributes. + POLICY_ALL_ACCESS, //Desired access permissions. + &lsahPolicyHandle //Receives the policy handle. + ); + + if (ntsResult != 0) + { + // An error occurred. Display it as a win32 error code. + wprintf(L"OpenPolicy returned %lu\n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + return lsahPolicyHandle; +} + + +/***************************************************************** + LoggedSetLockPagesPrivilege: a function to obtain, if possible, or + release the privilege of locking physical pages. + + Inputs: + + HANDLE hProcess: Handle for the process for which the + privilege is needed + + BOOL bEnable: Enable (TRUE) or disable? + + Return value: TRUE indicates success, FALSE failure. + +*****************************************************************/ +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable) +{ + struct { + u32 Count; + LUID_AND_ATTRIBUTES Privilege [1]; + } Info; + + HANDLE Token; + BOOL Result; + + // Open the token. + + Result = OpenProcessToken ( hProcess, + TOKEN_ADJUST_PRIVILEGES, + & Token); + + if( Result != TRUE ) { + SysPrintf( "Cannot open process token.\n" ); + return FALSE; + } + + // Enable or disable? + + Info.Count = 1; + if( bEnable ) + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + } + else + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_REMOVED; + } + + // Get the LUID. + Result = LookupPrivilegeValue ( NULL, + SE_LOCK_MEMORY_NAME, + &(Info.Privilege[0].Luid)); + + if( Result != TRUE ) + { + SysPrintf( "Cannot get privilege value for %s.\n", SE_LOCK_MEMORY_NAME ); + return FALSE; + } + + // Adjust the privilege. + + Result = AdjustTokenPrivileges ( Token, FALSE, + (PTOKEN_PRIVILEGES) &Info, + 0, NULL, NULL); + + // Check the result. + if( Result != TRUE ) + { + SysPrintf ("Cannot adjust token privileges, error %u.\n", GetLastError() ); + return FALSE; + } + else + { + if( GetLastError() != ERROR_SUCCESS ) + { + + BOOL bSuc = FALSE; + LSA_HANDLE policy; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + +// if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) ) +// return FALSE; + DWORD len = sizeof(s_szUserName); + GetUserNameW(s_szUserName, &len); + + policy = GetPolicyHandle(); + + if( policy != NULL ) { + + ltsTranslatedSID = GetSIDInformation(s_szUserName, policy); + + if( ltsTranslatedSID != NULL ) { + bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy, bEnable); + LsaFreeMemory(ltsTranslatedSID); + } + + LsaClose(policy); + } + + if( bSuc ) { + // Get the LUID. + LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)); + + bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL); + } + + if( bSuc ) { + if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n" + "Log off/on and run pcsx2 again. Do you want to log off?\n", + "Privilege changed query", MB_YESNO) == IDYES ) { + ExitWindows(EWX_LOGOFF, 0); + } + } + else { + MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n" + "Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n" + "Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n" + "Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n" + "(zerofrog)\n", "Virtual Memory Access Denied", MB_OK); + return FALSE; + } + } + } + + CloseHandle( Token ); + + return TRUE; +} + +static u32 s_dwPageSize = 0; +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock) +{ +//#ifdef WIN32_FILE_MAPPING +// assert(0); +//#endif + ULONG_PTR NumberOfPagesInitial; // initial number of pages requested + int PFNArraySize; // memory to request for PFN array + BOOL bResult; + + assert( pblock != NULL ); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); + + if( s_dwPageSize == 0 ) { + SYSTEM_INFO sSysInfo; // useful system information + GetSystemInfo(&sSysInfo); // fill the system information structure + s_dwPageSize = sSysInfo.dwPageSize; + + if( s_dwPageSize != 0x1000 ) { + SysMessage("Error! OS page size must be 4Kb!\n" + "If for some reason the OS cannot have 4Kb pages, then will need\n" + "to add a special translation LUT in pcsx2 (which will slow things down a LOT!)"); + return -1; + } + } + + // Calculate the number of pages of memory to request. + pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize; + PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR); + + pblock->aPFNs = (ULONG_PTR *) HeapAlloc (GetProcessHeap (), 0, PFNArraySize); + + if (pblock->aPFNs == NULL) { + SysPrintf("Failed to allocate on heap.\n"); + goto eCleanupAndExit; + } + + // Allocate the physical memory. + NumberOfPagesInitial = pblock->NumberPages; + bResult = AllocateUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( bResult != TRUE ) + { + SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + if( NumberOfPagesInitial != pblock->NumberPages ) + { + SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial ); + goto eCleanupAndExit; + } + + pblock->aVFNs = (ULONG_PTR*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); + + return 0; + +eCleanupAndExit: + SysPhysicalFree(pblock); + return -1; +} + +void SysPhysicalFree(PSMEMORYBLOCK* pblock) +{ + assert( pblock != NULL ); + + // Free the physical pages. + FreeUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs); + if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); +} + +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + BOOL bResult; + ULONG_PTR i; + + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE ); + if( lpMemReserved == NULL || base != lpMemReserved ) + { + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); + goto eCleanupAndExit; + } + + // Map the physical memory into the window. + bResult = MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); + + for(i = 0; i < pblock->NumberPages; ++i) + pblock->aVFNs[i] = (ULONG_PTR)base + 0x1000*i; + + if( bResult != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to map, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + return 0; + +eCleanupAndExit: + SysVirtualFree(base, size); + return -1; +} + +void SysVirtualFree(void* lpMemReserved, u32 size) +{ + // unmap + if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to unmap, error %u.\n", GetLastError() ); + return; + } + + // Free virtual memory. + VirtualFree( lpMemReserved, 0, MEM_RELEASE ); +} + +void SysVirtualProtectAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + // Reserve the virtual memory. + VirtualProtect( base, size, PAGE_READWRITE, NULL ); + MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); +} + +void SysVirtualProtectFree(void* lpMemReserved, u32 size) +{ + VirtualProtect(lpMemReserved, 0x1000, PAGE_NOACCESS, NULL); + MapUserPhysicalPages( lpMemReserved, size/s_dwPageSize, NULL ); +} + +BOOL SysMapUserPhysicalPages(PVOID Addr, ULONG_PTR NumPages, PULONG_PTR PageArray) +{ + BOOL bResult = MapUserPhysicalPages(Addr, NumPages, PageArray); + +#ifdef _DEBUG + //if( !bResult ) + //__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError()); +#endif + + return bResult; +} + +#else + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/windows/afxresmw.h b/branches/pcsx2_0.9.2/windows/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/branches/pcsx2_0.9.2/windows/cheats/browser.cpp b/branches/pcsx2_0.9.2/windows/cheats/browser.cpp new file mode 100644 index 0000000..c031f8e --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/cheats/browser.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include +#include + +using namespace std; + +#include "../cheatscpp.h" + +extern "C" { +#include "windows/resource.h" +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "Memory.h" + +#include "cheats.h" +#include "../../patch.h" +} + +HWND hWndBrowser; + +HTREEITEM AddTreeItem(HWND treeview, HTREEITEM parent, const char *name, LPARAM lp) +{ + TVINSERTSTRUCT node={ + parent, + 0, + { + TVIF_TEXT, + NULL, + TVIS_EXPANDED, + TVIS_EXPANDED, + const_cast(name), + 0, + 0, + 0, + 0, + lp, + 1 + } + }; + + return TreeView_InsertItem(treeview,&node); +} + +HTREEITEM AddGroups(HWND treeview, HTREEITEM parent, int parentIndex) +{ + HTREEITEM p=NULL; + for(unsigned int i=0;i0) + { + AddTreeItem(treeview,p,patches[j].title.c_str(),0x01000000|j); + } + } + } + } + } + return p; +} + +BOOL CALLBACK BrowserProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + int wmId,wmEvent; + + switch(uMsg) + { + + case WM_PAINT: + return FALSE; + case WM_INITDIALOG: + hWndBrowser=hWnd; + { + //Add groups to the Treeview + HTREEITEM root=AddGroups(GetDlgItem(hWnd,IDC_GROUPS),0, -1); + TreeView_SetItemState(GetDlgItem(hWnd,IDC_GROUPS),root,TVIS_EXPANDED|TVIS_EXPANDEDONCE|TVIS_EXPANDPARTIAL|TVIS_BOLD,0x00F0); + } + break; + + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDOK: + EndDialog(hWnd,1); + break; + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void ShowCheats(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_CHEATS),hParent,(DLGPROC)BrowserProc,1); +} diff --git a/branches/pcsx2_0.9.2/windows/cheats/cheats.cpp b/branches/pcsx2_0.9.2/windows/cheats/cheats.cpp new file mode 100644 index 0000000..a612068 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/cheats/cheats.cpp @@ -0,0 +1,600 @@ +#include +#include +#include +#include + +#include + +extern "C" { +#include "windows/resource.h" +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "Memory.h" + +#include "cheats.h" +#include "../../patch.h" +} + +class result +{ +public: + u32 address; + result(u32 addr): + address(addr) + { + } +}; + +char *sizenames[4]={"char","short","word","double"}; + +char mtext[100]; + +HINSTANCE pInstance; + +int TSelect; + +bool Unsigned; +int Source; +int Compare; +int Size; +int CompareTo; + +u64 CompareValue; + +std::vector results; + +//int mresults; + +bool FirstSearch; + +bool FirstShow; + +char olds[0x02000000]; + +char tn[100]; +char to[100]; +char tv[100]; + +#ifdef WIN32_VIRTUAL_MEM +u8 *mptr[2]={PS2MEM_BASE,PS2MEM_PSX}; +#else +char *mptr[2]; +extern "C" extern s8 *psxM; +#endif + +int msize[2]={0x02000000,0x00200000}; + +int lticks; + +HWND hWndFinder; + +LVCOLUMN cols[3]={ + {LVCF_TEXT|LVCF_WIDTH,0,60,"Address",0,0,0}, + {LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM,0,60,"Old V",1,0,0}, + {LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM,0,60,"New V",2,0,0} +}; + +LVITEM item[3]={ + {LVIF_TEXT|LVIF_STATE,0,0,0,0,tn,0,0,0,0}, + {LVIF_TEXT|LVIF_STATE,0,1,0,0,to,0,0,0,0}, + {LVIF_TEXT|LVIF_STATE,0,2,0,0,tv,0,0,0,0} +}; + +void DoEvents() +{ + MSG msg; + while(PeekMessage(&msg,0,0,0,PM_REMOVE)!=0) + DispatchMessage(&msg); +} + +void UpdateStatus() +{ + int nticks=GetTickCount(); + if((nticks-lticks)>250) + { + int nshown=ListView_GetItemCount(GetDlgItem(hWndFinder,IDC_RESULTS)); + sprintf(mtext,"%d matches found (%d shown).",results.size(),nshown); + SetWindowText(GetDlgItem(hWndFinder,IDC_MATCHES),mtext); + lticks=nticks; + DoEvents(); + } +} + +void SearchReset() +{ + memcpy(olds,mptr[Source],msize[Source]); + FirstSearch=true; + + results.clear(); + +} + +int AddResult(u32 addr) +{ + result nr=result(addr); + results.push_back(nr); + return 1; +} + +bool CompareAny(u64 val,u64 cto) +{ + + if(Unsigned) + { + switch(Size) + { + case 0: + val=(u8)val; + cto=(u8)cto; + break; + case 1: + val=(u16)val; + cto=(u16)cto; + break; + case 2: + val=(u32)val; + cto=(u32)cto; + break; + case 3: + break; + default:return false; + } + switch(Compare) + { + case 0: /* EQ */ + return val==cto; + case 1: /* GT */ + return val> cto; + case 2: /* LT */ + return val< cto; + case 3: /* GE */ + return val>=cto; + case 4: /* LE */ + return val<=cto; + default:/* NE */ + return val!=cto; + } + } + else + { + switch(Size) + { + case 0: + val=(s8)val; + cto=(s8)cto; + break; + case 1: + val=(s16)val; + cto=(s16)cto; + break; + case 2: + val=(s32)val; + cto=(s32)cto; + break; + case 3: + break; + default:return false; + } + switch(Compare) + { + case 0: /* EQ */ + return (s64)val==(s64)cto; + case 1: /* GT */ + return (s64)val> (s64)cto; + case 2: /* LT */ + return (s64)val< (s64)cto; + case 3: /* GE */ + return (s64)val>=(s64)cto; + case 4: /* LE */ + return (s64)val<=(s64)cto; + default:/* NE */ + return (s64)val!=(s64)cto; + } + } +} + +void SearchFirst() +{ + int MSize=1< oldr=std::vector(results); + + results.clear(); + + for(i=0;i", + Source?"IOP":"EE", + tn, + sizenames[Size]); + + SetWindowText(GetDlgItem(hWnd,IDC_ADDR),tn); + SetWindowText(GetDlgItem(hWnd,IDC_VALUE),tv); + SetWindowText(GetDlgItem(hWnd,IDC_NAME),to); + + break; + } + } + + + break; + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDOK: + GetWindowText(GetDlgItem(hWnd,IDC_VALUE),tv,100); + value=_atoi64(tv); + AddPatch(1,Source+1,results[Selected].address,Size+1,value); + + EndDialog(hWnd,1); + break; + + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void AddCheat(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR retret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ADD),hParent,(DLGPROC)AddCheatProc,(LPARAM)hParent); +} + +void AddResults(HWND hWnd) +{ + int i,mresults; + u64 sizemask=(1<<(1<32768) { + mresults=32768; + } + + ListView_DeleteAllItems(GetDlgItem(hWnd,IDC_RESULTS)); + + for(i=0;i32768) { + sprintf(mtext,"%d matches found (32768 shown).",results.size()); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),mtext); + } + else { + sprintf(mtext,"%d matches found.",results.size()); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),mtext); + } + +} + +BOOL CALLBACK FinderProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + int wmId,wmEvent; + LRESULT lStyle; + + switch(uMsg) + { + + case WM_PAINT: + INIT_CHECK(IDC_UNSIGNED,Unsigned); + return FALSE; + case WM_INITDIALOG: + +#ifndef WIN32_VIRTUAL_MEM + mptr[0]=(char*)psM; + mptr[1]=psxM; +#endif + + + hWndFinder=hWnd; + + ENABLE_CONTROL(IDC_VALUE,false); + + GROUP_INIT(IDC_EE,Source); + GROUP_SELECT(IDC_EE); + GROUP_SELECT(IDC_IOP); + + GROUP_INIT(IDC_OLD,CompareTo); + GROUP_SELECT(IDC_OLD); + GROUP_SELECT(IDC_SET); + ENABLE_CONTROL(IDC_VALUE,(CompareTo!=0)); + + GROUP_INIT(IDC_EQ,Compare); + GROUP_SELECT(IDC_EQ); + GROUP_SELECT(IDC_GT); + GROUP_SELECT(IDC_LT); + GROUP_SELECT(IDC_GE); + GROUP_SELECT(IDC_LE); + GROUP_SELECT(IDC_NE); + + GROUP_INIT(IDC_8B,Size); + GROUP_SELECT(IDC_8B); + GROUP_SELECT(IDC_16B); + GROUP_SELECT(IDC_32B); + GROUP_SELECT(IDC_64B); + + INIT_CHECK(IDC_UNSIGNED,Unsigned); + + //Listview Init + lStyle = SendMessage(GetDlgItem(hWnd,IDC_RESULTS), LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); + SendMessage(GetDlgItem(hWnd,IDC_RESULTS), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lStyle | LVS_EX_FULLROWSELECT); + + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),0,&cols[0]); + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),1,&cols[1]); + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),2,&cols[2]); + + if(FirstShow) + { + SearchReset(); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),"ready to search."); + FirstShow=false; + } + else { + AddResults(hWnd); + } + + break; + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDC_ADD: + AddCheat(pInstance,hWnd); + break; + + case IDC_RESET: + ENABLE_CONTROL(IDC_EE, true); + ENABLE_CONTROL(IDC_IOP, true); + ENABLE_CONTROL(IDC_LRESULTS,true); + ENABLE_CONTROL(IDC_STATUS, true); + ENABLE_CONTROL(IDC_UNSIGNED,true); + ENABLE_CONTROL(IDC_8B, true); + ENABLE_CONTROL(IDC_16B, true); + ENABLE_CONTROL(IDC_32B, true); + ENABLE_CONTROL(IDC_64B, true); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),"ready to search."); + SearchReset(); + ListView_DeleteAllItems(GetDlgItem(hWnd,IDC_RESULTS)); + break; + + case IDC_SEARCH: + GetWindowText(GetDlgItem(hWnd,IDC_VALUE),mtext,100); + CompareValue=atoi(mtext); + ENABLE_CONTROL(IDC_SEARCH, false); + ENABLE_CONTROL(IDC_RESET, false); + ENABLE_CONTROL(IDC_ADD, false); + ENABLE_CONTROL(IDCANCEL, false); + if(FirstSearch) { + ENABLE_CONTROL(IDC_EE, false); + ENABLE_CONTROL(IDC_IOP, false); + ENABLE_CONTROL(IDC_LRESULTS,false); + ENABLE_CONTROL(IDC_STATUS, false); + ENABLE_CONTROL(IDC_UNSIGNED,false); + ENABLE_CONTROL(IDC_8B, false); + ENABLE_CONTROL(IDC_16B, false); + ENABLE_CONTROL(IDC_32B, false); + ENABLE_CONTROL(IDC_64B, false); + SearchFirst(); + } + else SearchMore(); + + AddResults(hWnd); + + memcpy(olds,mptr[Source],msize[Source]); + + ENABLE_CONTROL(IDC_SEARCH, true); + ENABLE_CONTROL(IDC_RESET, true); + ENABLE_CONTROL(IDC_ADD, true); + ENABLE_CONTROL(IDCANCEL, true); + + break; + + HANDLE_CHECK(IDC_UNSIGNED,Unsigned); + + HANDLE_GROUP_ITEM(IDC_EE); + HANDLE_GROUP_ITEM(IDC_IOP); + BEGIN_GROUP_HANDLER(IDC_EE,Source); + GROUP_SELECT(IDC_EE); + GROUP_SELECT(IDC_IOP); + break; + + HANDLE_GROUP_ITEM(IDC_OLD); + HANDLE_GROUP_ITEM(IDC_SET); + BEGIN_GROUP_HANDLER(IDC_OLD,CompareTo); + GROUP_SELECT(IDC_OLD); + GROUP_SELECT(IDC_SET); + ENABLE_CONTROL(IDC_VALUE,(CompareTo!=0)); + break; + + HANDLE_GROUP_ITEM(IDC_EQ); + HANDLE_GROUP_ITEM(IDC_GT); + HANDLE_GROUP_ITEM(IDC_LT); + HANDLE_GROUP_ITEM(IDC_GE); + HANDLE_GROUP_ITEM(IDC_LE); + HANDLE_GROUP_ITEM(IDC_NE); + BEGIN_GROUP_HANDLER(IDC_EQ,Compare); + GROUP_SELECT(IDC_EQ); + GROUP_SELECT(IDC_GT); + GROUP_SELECT(IDC_LT); + GROUP_SELECT(IDC_GE); + GROUP_SELECT(IDC_LE); + GROUP_SELECT(IDC_NE); + break; + + HANDLE_GROUP_ITEM(IDC_8B); + HANDLE_GROUP_ITEM(IDC_16B); + HANDLE_GROUP_ITEM(IDC_32B); + HANDLE_GROUP_ITEM(IDC_64B); + BEGIN_GROUP_HANDLER(IDC_8B,Size); + GROUP_SELECT(IDC_8B); + GROUP_SELECT(IDC_16B); + GROUP_SELECT(IDC_32B); + GROUP_SELECT(IDC_64B); + break; + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void ShowFinder(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_FINDER),hParent,(DLGPROC)FinderProc,1); +} diff --git a/branches/pcsx2_0.9.2/windows/cheats/cheats.h b/branches/pcsx2_0.9.2/windows/cheats/cheats.h new file mode 100644 index 0000000..e4242da --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/cheats/cheats.h @@ -0,0 +1,19 @@ +#ifndef CHEATS_H_INCLUDED +#define CHEATS_H_INCLUDED + +#ifndef __cplusplus +typedef enum ebool +{ + false, + true +} bool; +#endif + +extern HINSTANCE pInstance; +extern bool FirstShow; + +void AddCheat(HINSTANCE hInstance, HWND hParent); +void ShowFinder(HINSTANCE hInstance, HWND hParent); +void ShowCheats(HINSTANCE hInstance, HWND hParent); + +#endif//CHEATS_H_INCLUDED diff --git a/branches/pcsx2_0.9.2/windows/ini.c b/branches/pcsx2_0.9.2/windows/ini.c new file mode 100644 index 0000000..9bc404a --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/ini.c @@ -0,0 +1,173 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* +15-09-2004 : file rewriten for work with inis (shadow) +*/ + +#include +#include +#include +#include "Common.h" +#include "win32.h" +#include + +int LoadConfig() { + FILE *fp; + +#ifdef ENABLE_NLS + char text[256]; + extern int _nl_msg_cat_cntr; +#endif + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return -1; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + fp=fopen("inis\\pcsx2.ini","rt");//check if pcsx2.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + return -1; + } + fclose(fp); + //interface + GetPrivateProfileString("Interface", "Bios", NULL, szValue, 256, szIniFile); + strcpy(Conf->Bios, szValue); + GetPrivateProfileString("Interface", "Lang", NULL, szValue, 256, szIniFile); + strcpy(Conf->Lang, szValue); + GetPrivateProfileString("Interface", "Ps2Out", NULL, szValue, 20, szIniFile); + Conf->PsxOut = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "ThPriority", NULL, szValue, 20, szIniFile); + Conf->ThPriority = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "PluginsDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->PluginsDir, szValue); + GetPrivateProfileString("Interface", "BiosDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->BiosDir, szValue); + GetPrivateProfileString("Interface", "Mcd1", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd1, szValue); + GetPrivateProfileString("Interface", "Mcd2", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd2, szValue); + //plugins + GetPrivateProfileString("Plugins", "GS", NULL, szValue, 256, szIniFile); + strcpy(Conf->GS, szValue); + GetPrivateProfileString("Plugins", "SPU2", NULL, szValue, 256, szIniFile); + strcpy(Conf->SPU2, szValue); + GetPrivateProfileString("Plugins", "CDVD", NULL, szValue, 256, szIniFile); + strcpy(Conf->CDVD, szValue); + GetPrivateProfileString("Plugins", "PAD1", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD1, szValue); + GetPrivateProfileString("Plugins", "PAD2", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD2, szValue); + GetPrivateProfileString("Plugins", "DEV9", NULL, szValue, 256, szIniFile); + strcpy(Conf->DEV9, szValue); + GetPrivateProfileString("Plugins", "USB", NULL, szValue, 256, szIniFile); + strcpy(Conf->USB, szValue); + GetPrivateProfileString("Plugins", "FW", NULL, szValue, 256, szIniFile); + strcpy(Conf->FW, szValue); + //cpu + GetPrivateProfileString("Cpu Options", "Options", NULL, szValue, 20, szIniFile); + Conf->Options= (u32)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Cpu Options", "SafeCnts", NULL, szValue, 20, szIniFile); + Conf->SafeCnts = strtoul(szValue, NULL, 0); + + //Misc + GetPrivateProfileString("Misc", "Patch", NULL, szValue, 20, szIniFile); + Conf->Patch = strtoul(szValue, NULL, 10); + +#ifdef PCSX2_DEVBUILD + GetPrivateProfileString("Misc", "varLog", NULL, szValue, 20, szIniFile); + varLog = strtoul(szValue, NULL, 16); +#endif + +#ifdef ENABLE_NLS + sprintf(text, "LANGUAGE=%s", Conf->Lang); +#ifdef __MSCW32__ + gettext_putenv(text); +#else + putenv(text); +#endif +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + //interface + sprintf(szValue,"%s",Conf->Bios); + WritePrivateProfileString("Interface","Bios",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Lang); + WritePrivateProfileString("Interface","Lang",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PluginsDir); + WritePrivateProfileString("Interface","PluginsDir",szValue,szIniFile); + sprintf(szValue,"%s",Conf->BiosDir); + WritePrivateProfileString("Interface","BiosDir",szValue,szIniFile); + sprintf(szValue,"%u",Conf->PsxOut); + WritePrivateProfileString("Interface","Ps2Out",szValue,szIniFile); + sprintf(szValue,"%u",Conf->ThPriority); + WritePrivateProfileString("Interface","ThPriority",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd1); + WritePrivateProfileString("Interface","Mcd1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd2); + WritePrivateProfileString("Interface","Mcd2",szValue,szIniFile); + //plugins + sprintf(szValue,"%s",Conf->GS); + WritePrivateProfileString("Plugins","GS",szValue,szIniFile); + sprintf(szValue,"%s",Conf->SPU2); + WritePrivateProfileString("Plugins","SPU2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->CDVD); + WritePrivateProfileString("Plugins","CDVD",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD1); + WritePrivateProfileString("Plugins","PAD1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD2); + WritePrivateProfileString("Plugins","PAD2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->DEV9); + WritePrivateProfileString("Plugins","DEV9",szValue,szIniFile); + sprintf(szValue,"%s",Conf->USB); + WritePrivateProfileString("Plugins","USB",szValue,szIniFile); + sprintf(szValue,"%s",Conf->FW); + WritePrivateProfileString("Plugins","FW",szValue,szIniFile); + //cpu + sprintf(szValue,"%u", Conf->Options); + WritePrivateProfileString("Cpu Options","Options",szValue,szIniFile); + sprintf(szValue,"%u",Conf->SafeCnts); + WritePrivateProfileString("Cpu Options","SafeCnts",szValue,szIniFile); + //Misc + sprintf(szValue,"%u",Conf->Patch); + WritePrivateProfileString("Misc","Patch",szValue,szIniFile); + sprintf(szValue,"%x",varLog); + WritePrivateProfileString("Misc","varLog",szValue,szIniFile); + + +} + diff --git a/branches/pcsx2_0.9.2/windows/libs/gnu_gettext.lib b/branches/pcsx2_0.9.2/windows/libs/gnu_gettext.lib new file mode 100644 index 0000000000000000000000000000000000000000..8b3885a56b2f9d31a261c89fbd0e31d15fc51c14 GIT binary patch literal 2916 zcmcIm%}*0S6#s1t6sieCjfr2dB!s{PNNJ%MHH)HwP(D)1#miW_1)4xhuow>{UOD)e zcr=_1C;tEshIsPefwS?z4d2_H*-nSjr35CKop~QSZ{GX8H#7au^1Fr27x7WMzD=dm zQxlV^#6&&Y9+UL=cv8;Z#Q}5!(LtcY0b=_==ds_rW&y7s(nvktEBgVB+)ud+F}JY1 zl+B5m*DJ5GbIZA9XHiX1+<#N( zZ&?ITv(`hx2nds~MvAP4(uZe8SYaqbL%!h8^YZlDhcqK+!%qAzB>!0 z!fxe#WxZ+-Wryv|+~T|^H9xnB!GH1!J}xmY;O!pIFa@Vj+1{Z|pY*li>`d8IX!0&2 zP`*2Wx9?5G@w{YPQN>BJ4lxkuq-q@I5Aa7eULANYDIOwtOW!M3^tDz-B9#j6jf@rX zD&w2CN8Tx{Mw#P!qS{BxoN>kF%=w}SIdbOQTt-|5<0rI}3vaKuku{;GN+La}#m+xf zevt(q@y4y7bc;@VHvo2F&Uu}vjpXl;Ja zaLr~cKDBMK#D|gjZZNQeL5E_QR8SiB9+54Mr>I?I#?olnw`A~$tM~08+2M0W1UIE= z%Amu&QpIg}^?J3lK4TO7^Zk!*F$rj%vLVHS>w*CX+ CYG_^n literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.2/windows/libs/libintlmsc.h b/branches/pcsx2_0.9.2/windows/libs/libintlmsc.h new file mode 100644 index 0000000..fd5f482 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/libs/libintlmsc.h @@ -0,0 +1,116 @@ +/* This file is part of a Windows32 DLL Interface to: + GNU gettext - internationalization aids + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + + This file was written by Franco Bez + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* REPLACEMENT FOR ORIGINAL LIBINTL.H for use with Windows32 */ + +#if !defined(__LIBINTL_H_INCLUDED) +#define __LIBINTL_H_INCLUDED + +#if defined(__cplusplus) +extern "C" { +#endif + +/* See if we allready know what we want static or dll linkage or none at all*/ +#if defined DONT_USE_GETTEXT || ( defined USE_SAFE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) || ( defined USE_GETTEXT_DLL && defined USE_SAFE_GETTEXT_DLL ) || ( defined USE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) +/* TWO IS HARDLY POSSIBLE */ +#undef USE_GETTEXT_DLL +#undef USE_GETTEXT_STATIC +#undefd USE_SAFE_GETTEXT_DLL +#endif /* MORE THAN ONE - OR NONE AT ALL */ + +#if !defined USE_GETTEXT_DLL && !defined USE_SAFE_GETTEXT_DLL && !defined USE_GETTEXT_STATIC && !defined DONT_USE_GETTEXT +/* not explicitly defined so try to guess it - + if GNUC is used - we use static linkage by default + because at the moment this is the only plattform + for which a static lib is available + else we use the DLL built with GNUC */ +# if defined __GNUC__ +# define USE_GETTEXT_STATIC +# else +# define USE_GETTEXT_DLL +# endif /* __GNUC__ */ +#endif /* NONE */ + +/* NOW ONLY ONE OF + DONT_USE_GETTEXT , USE_GETTEXT_DLL , USE_SAFE_GETTEXT_DLL , USE_GETTEXT_STATIC + IS DEFINED */ + +#if defined USE_GETTEXT_DLL +/* exported functions in DLL gnu_gettext.dll + you should link with import library + -lgnu_gettext (for mingw32) OR gnu_gettext.lib (MSVC) */ +__declspec(dllimport) char *gettext(const char *__msgid); +__declspec(dllimport) char *dgettext(const char *__domainname,const char *__msgid); +__declspec(dllimport) char *dcgettext(const char *__domainname,const char *__msgid, int __category); +__declspec(dllimport) char *textdomain(const char *__domainname); +__declspec(dllimport) char *bindtextdomain(const char *__domainname,const char *__dirname); +/* calling _putenv from within the DLL */ +__declspec(dllexport) int gettext_putenv(const char *envstring); +#endif /* DLL */ + +#if defined USE_SAFE_GETTEXT_DLL +/* Uses DLL gnu_gettext.dll ONLY if present, otherwise NO translation will take place + you should link with "safe_gettext_dll.o -lstdc++" see README for safe_gettext_dll for Details */ +/* The safe gettext functions */ +extern char *gettext(const char *szMsgId); +extern char *dgettext(const char *szDomain,const char *szMsgId); +extern char *dcgettext(const char *szDomain,const char *szMsgId,int iCategory); +extern char *textdomain(const char *szDomain); +extern char *bindtextdomain(const char *szDomain,const char *szDirectory); +/* calling _putenv from within the DLL */ +extern int gettext_putenv(const char *envstring); +#endif /* SAFE DLL */ + +#if defined USE_GETTEXT_STATIC +/* exported functions in static library libintl.a + and supporting macros + you should link with -lintl (mingw32) */ +extern char *gettext__(const char *__msgid); +extern char *dgettext__(const char *__domainname,const char *__msgid); +extern char *dcgettext__(const char *__domainname,const char *__msgid, int __category); +extern char *textdomain__(const char *__domainname); +extern char *bindtextdomain__(const char *__domainname,const char *__dirname); +#define gettext(szMsgId) gettext__(szMsgId) +#define dgettext(szDomain,szMsgId) dgettext__(szDomain,szMsgId) +#define dcgettext(szDomain,szMsgId,iCategory) dcgettext__(szDomain,szMsgId,iCategory) +#define textdomain(szDomain) textdomain__(szDomain) +#define bindtextdomain(szDomain,szDirectory) bindtextdomain__(szDomain,szDirectory) +// dummy - for static linkage - calling _putenv from within the DLL +#define gettext_putenv(a) _putenv(a) +#endif /* STATIC */ + +#if defined DONT_USE_GETTEXT +/* DON'T USE GETTEXT AT ALL + MAKROS TO MAKE CODE COMPILE WELL, BUT GETTEXT WILL NOT BE USESD +*/ +# define gettext(Msgid) (Msgid) +# define dgettext(Domainname, Msgid) (Msgid) +# define dcgettext(Domainname, Msgid, Category) (Msgid) +# define textdomain(Domainname) ((char *) Domainname) +# define bindtextdomain(Domainname, Dirname) ((char *) Dirname) +// dummy - for static linkage - calling _putenv from within the DLL +# define gettext_putenv(a) _putenv(a) +#endif /* DON'T USE AT ALL */ + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /*!defined(__LIBINTL_H_INCLUDED)*/ diff --git a/branches/pcsx2_0.9.2/windows/libs/pthread.h b/branches/pcsx2_0.9.2/windows/libs/pthread.h new file mode 100644 index 0000000..a0add29 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/libs/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,7,0,0 +#define PTW32_VERSION_STRING "2, 7, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/branches/pcsx2_0.9.2/windows/libs/pthreadVC2.lib b/branches/pcsx2_0.9.2/windows/libs/pthreadVC2.lib new file mode 100644 index 0000000000000000000000000000000000000000..b447a8b71ec31903598669991dac05f24ace9f25 GIT binary patch literal 29280 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 literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.2/windows/libs/sched.h b/branches/pcsx2_0.9.2/windows/libs/sched.h new file mode 100644 index 0000000..10ecb5d --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/libs/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/branches/pcsx2_0.9.2/windows/libs/semaphore.h b/branches/pcsx2_0.9.2/windows/libs/semaphore.h new file mode 100644 index 0000000..ea42ce3 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/libs/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/branches/pcsx2_0.9.2/windows/mingw/Makefile.win b/branches/pcsx2_0.9.2/windows/mingw/Makefile.win new file mode 100644 index 0000000..7449952 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/Makefile.win @@ -0,0 +1,348 @@ +# Project: pcsx2 +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//pcsx2_private.res +OBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LINKOBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LIBS = -mwindows -Wall -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -s +INCS = -I"../../" -I"C:/Documents and Settings/shadow/Desktop/Npcsx2" -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +CXXINCS = -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +BIN = pcsx2.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -D__WIN32__ -D__MINGW32__ -O3 -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before pcsx2.exe all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o "pcsx2.exe" $(LIBS) + +Obj//AboutDlg.o: ../AboutDlg.c + $(CC) -c ../AboutDlg.c -o Obj//AboutDlg.o $(CFLAGS) + +Obj//ConfigDlg.o: ../ConfigDlg.c + $(CC) -c ../ConfigDlg.c -o Obj//ConfigDlg.o $(CFLAGS) + +Obj//CpuDlg.o: ../CpuDlg.c + $(CC) -c ../CpuDlg.c -o Obj//CpuDlg.o $(CFLAGS) + +Obj//Debugger.o: ../Debugger.c + $(CC) -c ../Debugger.c -o Obj//Debugger.o $(CFLAGS) + +Obj//DebugMemory.o: ../DebugMemory.c + $(CC) -c ../DebugMemory.c -o Obj//DebugMemory.o $(CFLAGS) + +Obj//Debugreg.o: ../Debugreg.c + $(CC) -c ../Debugreg.c -o Obj//Debugreg.o $(CFLAGS) + +Obj//ini.o: ../ini.c + $(CC) -c ../ini.c -o Obj//ini.o $(CFLAGS) + +Obj//McdsDlg.o: ../McdsDlg.c + $(CC) -c ../McdsDlg.c -o Obj//McdsDlg.o $(CFLAGS) + +Obj//PatchBrowser.o: ../PatchBrowser.c + $(CC) -c ../PatchBrowser.c -o Obj//PatchBrowser.o $(CFLAGS) + +Obj//RDebugger.o: ../RDebugger.c + $(CC) -c ../RDebugger.c -o Obj//RDebugger.o $(CFLAGS) + +Obj//WinMain.o: ../WinMain.c + $(CC) -c ../WinMain.c -o Obj//WinMain.o $(CFLAGS) + +Obj//Idct.o: ../../IPU/Idct.c + $(CC) -c ../../IPU/Idct.c -o Obj//Idct.o $(CFLAGS) + +Obj//IPU.o: ../../IPU/IPU.c + $(CC) -c ../../IPU/IPU.c -o Obj//IPU.o $(CFLAGS) + +Obj//Mpeg.o: ../../IPU/Mpeg.c + $(CC) -c ../../IPU/Mpeg.c -o Obj//Mpeg.o $(CFLAGS) + +Obj//yuv2rgb.o: ../../IPU/yuv2rgb.c + $(CC) -c ../../IPU/yuv2rgb.c -o Obj//yuv2rgb.o $(CFLAGS) + +Obj//cpuopsDebug.o: ../../DebugTools/cpuopsDebug.c + $(CC) -c ../../DebugTools/cpuopsDebug.c -o Obj//cpuopsDebug.o $(CFLAGS) + +Obj//DisR3000A.o: ../../DebugTools/DisR3000A.c + $(CC) -c ../../DebugTools/DisR3000A.c -o Obj//DisR3000A.o $(CFLAGS) + +Obj//DisR3000asm.o: ../../DebugTools/DisR3000asm.c + $(CC) -c ../../DebugTools/DisR3000asm.c -o Obj//DisR3000asm.o $(CFLAGS) + +Obj//DisR5900.o: ../../DebugTools/DisR5900.c + $(CC) -c ../../DebugTools/DisR5900.c -o Obj//DisR5900.o $(CFLAGS) + +Obj//DisR5900asm.o: ../../DebugTools/DisR5900asm.c + $(CC) -c ../../DebugTools/DisR5900asm.c -o Obj//DisR5900asm.o $(CFLAGS) + +Obj//DisVU0Micro.o: ../../DebugTools/DisVU0Micro.c + $(CC) -c ../../DebugTools/DisVU0Micro.c -o Obj//DisVU0Micro.o $(CFLAGS) + +Obj//DisVU1Micro.o: ../../DebugTools/DisVU1Micro.c + $(CC) -c ../../DebugTools/DisVU1Micro.c -o Obj//DisVU1Micro.o $(CFLAGS) + +Obj//adler32.o: ../../zlib/adler32.c + $(CC) -c ../../zlib/adler32.c -o Obj//adler32.o $(CFLAGS) + +Obj//compress.o: ../../zlib/compress.c + $(CC) -c ../../zlib/compress.c -o Obj//compress.o $(CFLAGS) + +Obj//crc32.o: ../../zlib/crc32.c + $(CC) -c ../../zlib/crc32.c -o Obj//crc32.o $(CFLAGS) + +Obj//deflate.o: ../../zlib/deflate.c + $(CC) -c ../../zlib/deflate.c -o Obj//deflate.o $(CFLAGS) + +Obj//gzio.o: ../../zlib/gzio.c + $(CC) -c ../../zlib/gzio.c -o Obj//gzio.o $(CFLAGS) + +Obj//infback.o: ../../zlib/infback.c + $(CC) -c ../../zlib/infback.c -o Obj//infback.o $(CFLAGS) + +Obj//inffast.o: ../../zlib/inffast.c + $(CC) -c ../../zlib/inffast.c -o Obj//inffast.o $(CFLAGS) + +Obj//inflate.o: ../../zlib/inflate.c + $(CC) -c ../../zlib/inflate.c -o Obj//inflate.o $(CFLAGS) + +Obj//inftrees.o: ../../zlib/inftrees.c + $(CC) -c ../../zlib/inftrees.c -o Obj//inftrees.o $(CFLAGS) + +Obj//trees.o: ../../zlib/trees.c + $(CC) -c ../../zlib/trees.c -o Obj//trees.o $(CFLAGS) + +Obj//uncompr.o: ../../zlib/uncompr.c + $(CC) -c ../../zlib/uncompr.c -o Obj//uncompr.o $(CFLAGS) + +Obj//zutil.o: ../../zlib/zutil.c + $(CC) -c ../../zlib/zutil.c -o Obj//zutil.o $(CFLAGS) + +Obj//iR5900Arit.o: ../../ix86-32/iR5900Arit.c + $(CC) -c ../../ix86-32/iR5900Arit.c -o Obj//iR5900Arit.o $(CFLAGS) + +Obj//iR5900AritImm.o: ../../ix86-32/iR5900AritImm.c + $(CC) -c ../../ix86-32/iR5900AritImm.c -o Obj//iR5900AritImm.o $(CFLAGS) + +Obj//iR5900Branch.o: ../../ix86-32/iR5900Branch.c + $(CC) -c ../../ix86-32/iR5900Branch.c -o Obj//iR5900Branch.o $(CFLAGS) + +Obj//iR5900Jump.o: ../../ix86-32/iR5900Jump.c + $(CC) -c ../../ix86-32/iR5900Jump.c -o Obj//iR5900Jump.o $(CFLAGS) + +Obj//iR5900LoadStore.o: ../../ix86-32/iR5900LoadStore.c + $(CC) -c ../../ix86-32/iR5900LoadStore.c -o Obj//iR5900LoadStore.o $(CFLAGS) + +Obj//iR5900Move.o: ../../ix86-32/iR5900Move.c + $(CC) -c ../../ix86-32/iR5900Move.c -o Obj//iR5900Move.o $(CFLAGS) + +Obj//iR5900MultDiv.o: ../../ix86-32/iR5900MultDiv.c + $(CC) -c ../../ix86-32/iR5900MultDiv.c -o Obj//iR5900MultDiv.o $(CFLAGS) + +Obj//iR5900Shift.o: ../../ix86-32/iR5900Shift.c + $(CC) -c ../../ix86-32/iR5900Shift.c -o Obj//iR5900Shift.o $(CFLAGS) + +Obj//iCP0.o: ../../x86/iCP0.c + $(CC) -c ../../x86/iCP0.c -o Obj//iCP0.o $(CFLAGS) + +Obj//iFPU.o: ../../x86/iFPU.c + $(CC) -c ../../x86/iFPU.c -o Obj//iFPU.o $(CFLAGS) + +Obj//iMMI.o: ../../x86/iMMI.c + $(CC) -c ../../x86/iMMI.c -o Obj//iMMI.o $(CFLAGS) + +Obj//iR3000A.o: ../../x86/iR3000A.c + $(CC) -c ../../x86/iR3000A.c -o Obj//iR3000A.o $(CFLAGS) + +Obj//iR5900.o: ../../x86/iR5900.c + $(CC) -c ../../x86/iR5900.c -o Obj//iR5900.o $(CFLAGS) + +Obj//iVU0micro.o: ../../x86/iVU0micro.c + $(CC) -c ../../x86/iVU0micro.c -o Obj//iVU0micro.o $(CFLAGS) + +Obj//iVU1micro.o: ../../x86/iVU1micro.c + $(CC) -c ../../x86/iVU1micro.c -o Obj//iVU1micro.o $(CFLAGS) + +Obj//iVUmicro.o: ../../x86/iVUmicro.c + $(CC) -c ../../x86/iVUmicro.c -o Obj//iVUmicro.o $(CFLAGS) + +Obj//recCOP2.o: ../../x86/recCOP2.c + $(CC) -c ../../x86/recCOP2.c -o Obj//recCOP2.o $(CFLAGS) + +Obj//ix86.o: ../../x86/ix86/ix86.c + $(CC) -c ../../x86/ix86/ix86.c -o Obj//ix86.o $(CFLAGS) + +Obj//ix86_3dnow.o: ../../x86/ix86/ix86_3dnow.c + $(CC) -c ../../x86/ix86/ix86_3dnow.c -o Obj//ix86_3dnow.o $(CFLAGS) + +Obj//ix86_cpudetect.o: ../../x86/ix86/ix86_cpudetect.c + $(CC) -c ../../x86/ix86/ix86_cpudetect.c -o Obj//ix86_cpudetect.o $(CFLAGS) + +Obj//ix86_fpu.o: ../../x86/ix86/ix86_fpu.c + $(CC) -c ../../x86/ix86/ix86_fpu.c -o Obj//ix86_fpu.o $(CFLAGS) + +Obj//ix86_mmx.o: ../../x86/ix86/ix86_mmx.c + $(CC) -c ../../x86/ix86/ix86_mmx.c -o Obj//ix86_mmx.o $(CFLAGS) + +Obj//ix86_sse.o: ../../x86/ix86/ix86_sse.c + $(CC) -c ../../x86/ix86/ix86_sse.c -o Obj//ix86_sse.o $(CFLAGS) + +Obj//CDVD.o: ../../CDVD.c + $(CC) -c ../../CDVD.c -o Obj//CDVD.o $(CFLAGS) + +Obj//CDVDiso.o: ../../CDVDiso.c + $(CC) -c ../../CDVDiso.c -o Obj//CDVDiso.o $(CFLAGS) + +Obj//CDVDisodrv.o: ../../CDVDisodrv.c + $(CC) -c ../../CDVDisodrv.c -o Obj//CDVDisodrv.o $(CFLAGS) + +Obj//COP0.o: ../../COP0.c + $(CC) -c ../../COP0.c -o Obj//COP0.o $(CFLAGS) + +Obj//Counters.o: ../../Counters.c + $(CC) -c ../../Counters.c -o Obj//Counters.o $(CFLAGS) + +Obj//Decode_XA.o: ../../Decode_XA.c + $(CC) -c ../../Decode_XA.c -o Obj//Decode_XA.o $(CFLAGS) + +Obj//Elfheader.o: ../../Elfheader.c + $(CC) -c ../../Elfheader.c -o Obj//Elfheader.o $(CFLAGS) + +Obj//FiFo.o: ../../FiFo.c + $(CC) -c ../../FiFo.c -o Obj//FiFo.o $(CFLAGS) + +Obj//FPU.o: ../../FPU.c + $(CC) -c ../../FPU.c -o Obj//FPU.o $(CFLAGS) + +Obj//GS.o: ../../GS.c + $(CC) -c ../../GS.c -o Obj//GS.o $(CFLAGS) + +Obj//Gte.o: ../../Gte.c + $(CC) -c ../../Gte.c -o Obj//Gte.o $(CFLAGS) + +Obj//Hw.o: ../../Hw.c + $(CC) -c ../../Hw.c -o Obj//Hw.o $(CFLAGS) + +Obj//Interpreter.o: ../../Interpreter.c + $(CC) -c ../../Interpreter.c -o Obj//Interpreter.o $(CFLAGS) + +Obj//InterTables.o: ../../InterTables.c + $(CC) -c ../../InterTables.c -o Obj//InterTables.o $(CFLAGS) + +Obj//Mdec.o: ../../Mdec.c + $(CC) -c ../../Mdec.c -o Obj//Mdec.o $(CFLAGS) + +Obj//Memory.o: ../../Memory.c + $(CC) -c ../../Memory.c -o Obj//Memory.o $(CFLAGS) + +Obj//Misc.o: ../../Misc.c + $(CC) -c ../../Misc.c -o Obj//Misc.o $(CFLAGS) + +Obj//MMI.o: ../../MMI.c + $(CC) -c ../../MMI.c -o Obj//MMI.o $(CFLAGS) + +Obj//Patch.o: ../../Patch.c + $(CC) -c ../../Patch.c -o Obj//Patch.o $(CFLAGS) + +Obj//Plugins.o: ../../Plugins.c + $(CC) -c ../../Plugins.c -o Obj//Plugins.o $(CFLAGS) + +Obj//PsxBios.o: ../../PsxBios.c + $(CC) -c ../../PsxBios.c -o Obj//PsxBios.o $(CFLAGS) + +Obj//PsxCounters.o: ../../PsxCounters.c + $(CC) -c ../../PsxCounters.c -o Obj//PsxCounters.o $(CFLAGS) + +Obj//PsxDma.o: ../../PsxDma.c + $(CC) -c ../../PsxDma.c -o Obj//PsxDma.o $(CFLAGS) + +Obj//PsxGPU.o: ../../PsxGPU.c + $(CC) -c ../../PsxGPU.c -o Obj//PsxGPU.o $(CFLAGS) + +Obj//PsxHw.o: ../../PsxHw.c + $(CC) -c ../../PsxHw.c -o Obj//PsxHw.o $(CFLAGS) + +Obj//PsxInterpreter.o: ../../PsxInterpreter.c + $(CC) -c ../../PsxInterpreter.c -o Obj//PsxInterpreter.o $(CFLAGS) + +Obj//PsxMem.o: ../../PsxMem.c + $(CC) -c ../../PsxMem.c -o Obj//PsxMem.o $(CFLAGS) + +Obj//PsxSio2.o: ../../PsxSio2.c + $(CC) -c ../../PsxSio2.c -o Obj//PsxSio2.o $(CFLAGS) + +Obj//R3000A.o: ../../R3000A.c + $(CC) -c ../../R3000A.c -o Obj//R3000A.o $(CFLAGS) + +Obj//R5900.o: ../../R5900.c + $(CC) -c ../../R5900.c -o Obj//R5900.o $(CFLAGS) + +Obj//Sif.o: ../../Sif.c + $(CC) -c ../../Sif.c -o Obj//Sif.o $(CFLAGS) + +Obj//Sio.o: ../../Sio.c + $(CC) -c ../../Sio.c -o Obj//Sio.o $(CFLAGS) + +Obj//SPR.o: ../../SPR.c + $(CC) -c ../../SPR.c -o Obj//SPR.o $(CFLAGS) + +Obj//Stats.o: ../../Stats.c + $(CC) -c ../../Stats.c -o Obj//Stats.o $(CFLAGS) + +Obj//Vif.o: ../../Vif.c + $(CC) -c ../../Vif.c -o Obj//Vif.o $(CFLAGS) + +Obj//VifDma.o: ../../VifDma.c + $(CC) -c ../../VifDma.c -o Obj//VifDma.o $(CFLAGS) + +Obj//VU0.o: ../../VU0.c + $(CC) -c ../../VU0.c -o Obj//VU0.o $(CFLAGS) + +Obj//VU0micro.o: ../../VU0micro.c + $(CC) -c ../../VU0micro.c -o Obj//VU0micro.o $(CFLAGS) + +Obj//VU1micro.o: ../../VU1micro.c + $(CC) -c ../../VU1micro.c -o Obj//VU1micro.o $(CFLAGS) + +Obj//VUflags.o: ../../VUflags.c + $(CC) -c ../../VUflags.c -o Obj//VUflags.o $(CFLAGS) + +Obj//VUops.o: ../../VUops.c + $(CC) -c ../../VUops.c -o Obj//VUops.o $(CFLAGS) + +Obj//Cache.o: ../../Cache.c + $(CC) -c ../../Cache.c -o Obj//Cache.o $(CFLAGS) + +Obj//CdRom.o: ../../CdRom.c + $(CC) -c ../../CdRom.c -o Obj//CdRom.o $(CFLAGS) + +Obj//deci2.o: ../../RDebug/deci2.c + $(CC) -c ../../RDebug/deci2.c -o Obj//deci2.o $(CFLAGS) + +Obj//deci2_dbgp.o: ../../RDebug/deci2_dbgp.c + $(CC) -c ../../RDebug/deci2_dbgp.c -o Obj//deci2_dbgp.o $(CFLAGS) + +Obj//deci2_dcmp.o: ../../RDebug/deci2_dcmp.c + $(CC) -c ../../RDebug/deci2_dcmp.c -o Obj//deci2_dcmp.o $(CFLAGS) + +Obj//deci2_iloadp.o: ../../RDebug/deci2_iloadp.c + $(CC) -c ../../RDebug/deci2_iloadp.c -o Obj//deci2_iloadp.o $(CFLAGS) + +Obj//deci2_netmp.o: ../../RDebug/deci2_netmp.c + $(CC) -c ../../RDebug/deci2_netmp.c -o Obj//deci2_netmp.o $(CFLAGS) + +Obj//deci2_ttyp.o: ../../RDebug/deci2_ttyp.c + $(CC) -c ../../RDebug/deci2_ttyp.c -o Obj//deci2_ttyp.o $(CFLAGS) + +Obj//pcsx2_private.res: pcsx2_private.rc ../pcsx2.rc + $(WINDRES) -i pcsx2_private.rc --input-format=rc -o Obj//pcsx2_private.res -O coff --include-dir ../../ --include-dir ../ --include-dir ../mingw diff --git a/branches/pcsx2_0.9.2/windows/mingw/afxres.h b/branches/pcsx2_0.9.2/windows/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/branches/pcsx2_0.9.2/windows/mingw/pcsx2.dev b/branches/pcsx2_0.9.2/windows/mingw/pcsx2.dev new file mode 100644 index 0000000..db8fafb --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/pcsx2.dev @@ -0,0 +1,2116 @@ +[Project] +FileName=pcsx2.dev +Name=pcsx2 +UnitCount=205 +Type=0 +Ver=1 +ObjFiles= +Includes=../..;../../zlib;../../DebugTools;../../IPU;../../x86;../../ix86-32;..;../RDebug +Libs= +PrivateResource=pcsx2_private.rc +ResourceIncludes=../../;../;..\mingw +MakeIncludes= +Compiler=-v_@@_-D__WIN32___@@_-D__MINGW32__ _@@_-Wall _@@_-O3 ${-fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing} -mfpmath=sse -march=athlon64_@@_ _@@_ +CppCompiler= +Linker=-lcomctl32 _@@_-lwsock32 _@@_-lwinmm _@@_-lgdi32 _@@_-lcomdlg32 _@@__@@_-m128bit-long-double_@@_ +IsCpp=0 +Icon= +ExeOutput=../ +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=pcsx2.exe +HostApplication= +Folders=cpu,DebugTools,DECI2,GUI,Hardware,IOP_CPU,IPU,ix86,ix86/x86,ix86-32,misc,plugins,Sif,zlib +CommandLine= +UseCustomMakefile=0 +CustomMakefile=..\Makefile +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=..\AboutDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\AboutDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\ConfigDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\CpuDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\Debugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\Debugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\DebugMemory.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\Debugreg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\ini.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\McdsDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\McdsDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\PatchBrowser.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\pcsx2.rc +Folder=GUI +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\RDebugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\RDebugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\resource.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\Win32.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\WinMain.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=afxres.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\..\IPU\Idct.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\..\IPU\IPU.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\..\IPU\IPU.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\..\IPU\Mpeg.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\..\IPU\Mpeg.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\..\IPU\Vlc.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\..\IPU\yuv2rgb.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\..\IPU\yuv2rgb.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\..\DebugTools\cpuopsDebug.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\..\DebugTools\cpuopsDebug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\..\DebugTools\Debug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\..\DebugTools\DisASM.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\..\DebugTools\DisR3000A.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\..\DebugTools\DisR3000asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\..\DebugTools\DisR5900.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\..\DebugTools\DisR5900asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\..\DebugTools\DisVU0Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\..\DebugTools\DisVU1Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\..\DebugTools\DisVUmicro.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\..\DebugTools\DisVUops.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\..\zlib\adler32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\..\zlib\compress.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\..\zlib\crc32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=..\..\zlib\crc32.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=..\..\zlib\deflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=..\..\zlib\deflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=..\..\zlib\gzio.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=..\..\zlib\infback.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=..\..\zlib\inffast.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=..\..\zlib\inffast.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=..\..\zlib\inffixed.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=..\..\zlib\inflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=..\..\zlib\inflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit53] +FileName=..\..\zlib\inftrees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=..\..\zlib\inftrees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=..\..\zlib\trees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=..\..\zlib\trees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=..\..\zlib\uncompr.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=..\..\zlib\zconf.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=..\..\zlib\zlib.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=..\..\zlib\zutil.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=..\..\zlib\zutil.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit62] +FileName=..\..\ix86-32\iR5900Arit.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit63] +FileName=..\..\ix86-32\iR5900Arit.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit64] +FileName=..\..\ix86-32\iR5900AritImm.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit65] +FileName=..\..\ix86-32\iR5900AritImm.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit66] +FileName=..\..\ix86-32\iR5900Branch.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit67] +FileName=..\..\ix86-32\iR5900Branch.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit68] +FileName=..\..\ix86-32\iR5900Jump.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit69] +FileName=..\..\ix86-32\iR5900Jump.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit70] +FileName=..\..\ix86-32\iR5900LoadStore.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit71] +FileName=..\..\ix86-32\iR5900LoadStore.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit72] +FileName=..\..\ix86-32\iR5900Move.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit73] +FileName=..\..\ix86-32\iR5900Move.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit74] +FileName=..\..\ix86-32\iR5900MultDiv.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit75] +FileName=..\..\ix86-32\iR5900MultDiv.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit76] +FileName=..\..\ix86-32\iR5900Shift.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=..\..\ix86-32\iR5900Shift.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit78] +FileName=..\..\x86\iCP0.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=..\..\x86\iCP0.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit80] +FileName=..\..\x86\iFPU.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit81] +FileName=..\..\x86\iFPU.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit82] +FileName=..\..\x86\iMMI.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit83] +FileName=..\..\x86\iMMI.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit84] +FileName=..\..\x86\iR3000A.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit85] +FileName=..\..\x86\iR5900.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit86] +FileName=..\..\x86\iR5900.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit87] +FileName=..\..\x86\iVU0micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit88] +FileName=..\..\x86\iVU0micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit89] +FileName=..\..\x86\iVU1micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit90] +FileName=..\..\x86\iVU1micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit91] +FileName=..\..\x86\iVUmicro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit92] +FileName=..\..\x86\iVUmicro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit93] +FileName=..\..\x86\iVUops.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit94] +FileName=..\..\x86\recCOP2.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit95] +FileName=..\..\x86\ix86\ix86.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit96] +FileName=..\..\x86\ix86\ix86.h +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit97] +FileName=..\..\x86\ix86\ix86_3dnow.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit98] +FileName=..\..\x86\ix86\ix86_cpudetect.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit99] +FileName=..\..\x86\ix86\ix86_fpu.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit100] +FileName=..\..\x86\ix86\ix86_mmx.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit101] +FileName=..\..\x86\ix86\ix86_sse.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit102] +FileName=..\..\CDVD.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit103] +FileName=..\..\CDVD.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit104] +FileName=..\..\CDVDiso.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit105] +FileName=..\..\CDVDiso.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit106] +FileName=..\..\CDVDisodrv.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit107] +FileName=..\..\CDVDisodrv.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit108] +FileName=..\..\CDVDlib.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit109] +FileName=..\..\Common.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit110] +FileName=..\..\COP0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit111] +FileName=..\..\COP0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit112] +FileName=..\..\Counters.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit113] +FileName=..\..\Counters.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit114] +FileName=..\..\Decode_XA.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit115] +FileName=..\..\Decode_XA.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit116] +FileName=..\..\EEregs.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit117] +FileName=..\..\Elfheader.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit118] +FileName=..\..\Elfheader.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit119] +FileName=..\..\FiFo.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit120] +FileName=..\..\FPU.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit121] +FileName=..\..\GS.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit122] +FileName=..\..\GS.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit123] +FileName=..\..\Gte.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit124] +FileName=..\..\Gte.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit125] +FileName=..\..\Hw.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit126] +FileName=..\..\Hw.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit127] +FileName=..\..\Interpreter.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit128] +FileName=..\..\InterTables.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit129] +FileName=..\..\InterTables.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit130] +FileName=..\..\Mdec.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit131] +FileName=..\..\Mdec.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit132] +FileName=..\..\Memory.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit133] +FileName=..\..\Memory.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit134] +FileName=..\..\Misc.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit135] +FileName=..\..\Misc.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit136] +FileName=..\..\MMI.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit137] +FileName=..\..\Patch.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit138] +FileName=..\..\Patch.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit139] +FileName=..\..\Plugins.c +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit140] +FileName=..\..\Plugins.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit141] +FileName=..\..\PS2Edefs.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit142] +FileName=..\..\PS2Etypes.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit143] +FileName=..\..\PsxBios2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit144] +FileName=..\..\PsxBios.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit145] +FileName=..\..\PsxBios.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit146] +FileName=..\..\PsxCommon.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit147] +FileName=..\..\PsxCounters.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit148] +FileName=..\..\PsxCounters.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit149] +FileName=..\..\PsxDma.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit150] +FileName=..\..\PsxDma.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit151] +FileName=..\..\PsxGPU.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit152] +FileName=..\..\PsxGPU.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit153] +FileName=..\..\PsxHw.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit154] +FileName=..\..\PsxHw.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit155] +FileName=..\..\PsxInterpreter.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit156] +FileName=..\..\PsxMem.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit157] +FileName=..\..\PsxMem.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit158] +FileName=..\..\PsxSio2.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit159] +FileName=..\..\PsxSio2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit160] +FileName=..\..\R3000A.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit161] +FileName=..\..\R3000A.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit162] +FileName=..\..\R5900.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit163] +FileName=..\..\R5900.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit164] +FileName=..\..\Sif.c +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit165] +FileName=..\..\Sif.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit166] +FileName=..\..\Sifcmd.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit167] +FileName=..\..\Sio.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit168] +FileName=..\..\Sio.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit169] +FileName=..\..\SPR.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit170] +FileName=..\..\SPR.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit171] +FileName=..\..\Stats.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit172] +FileName=..\..\Stats.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit173] +FileName=..\..\System.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit174] +FileName=..\..\Vif.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit175] +FileName=..\..\Vif.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=..\..\VifDma.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit177] +FileName=..\..\VifDma.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit178] +FileName=..\..\VU0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit179] +FileName=..\..\VU0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit180] +FileName=..\..\VU0micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit181] +FileName=..\..\VU1micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit182] +FileName=..\..\VU.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit183] +FileName=..\..\VUflags.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit184] +FileName=..\..\VUflags.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit185] +FileName=..\..\VUmicro.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit186] +FileName=..\..\VUops.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit187] +FileName=..\..\VUops.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit188] +FileName=..\..\Cache.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit189] +FileName=..\..\Cache.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit190] +FileName=..\..\CdRom.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit191] +FileName=..\..\CdRom.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit192] +FileName=..\Cdrom02.ico +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit193] +FileName=..\..\pcsxAbout.bmp +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit194] +FileName=..\..\RDebug\deci2.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit195] +FileName=..\..\RDebug\deci2.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit196] +FileName=..\..\RDebug\deci2_dbgp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit197] +FileName=..\..\RDebug\deci2_dbgp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit198] +FileName=..\..\RDebug\deci2_dcmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit199] +FileName=..\..\RDebug\deci2_dcmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit202] +FileName=..\..\RDebug\deci2_netmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit203] +FileName=..\..\RDebug\deci2_netmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit204] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit205] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit206] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit207] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit200] +FileName=..\..\RDebug\deci2_iloadp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit201] +FileName=..\..\RDebug\deci2_iloadp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/branches/pcsx2_0.9.2/windows/mingw/pcsx2.layout b/branches/pcsx2_0.9.2/windows/mingw/pcsx2.layout new file mode 100644 index 0000000..eb0d940 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/pcsx2.layout @@ -0,0 +1,1424 @@ +[Editor_0] +CursorCol=1 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_1] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_4] +CursorCol=1 +CursorRow=95 +TopLine=54 +LeftChar=1 +Open=1 +Top=1 +[Editor_3] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_6] +CursorCol=2 +CursorRow=239 +TopLine=193 +LeftChar=1 +Open=0 +Top=0 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_9] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_10] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_11] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_12] +CursorCol=1 +CursorRow=19 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_13] +CursorCol=20 +CursorRow=172 +TopLine=132 +LeftChar=1 +Open=0 +Top=0 +[Editor_14] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_15] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_16] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_17] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_2] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_19] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_20] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_22] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_23] +CursorCol=1 +CursorRow=175 +TopLine=146 +LeftChar=1 +Open=0 +Top=0 +[Editor_24] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_25] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_26] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_21] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_27] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_28] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_29] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_31] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_30] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_32] +CursorCol=48 +CursorRow=360 +TopLine=315 +LeftChar=1 +Open=0 +Top=0 +[Editor_33] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_34] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_35] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_36] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_37] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_38] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_39] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_40] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_41] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_42] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_43] +CursorCol=8 +CursorRow=841 +TopLine=812 +LeftChar=1 +Open=0 +Top=0 +[Editor_44] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_45] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_46] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_47] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_48] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_49] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_50] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_51] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_52] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_53] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_54] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_55] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_56] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_57] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_58] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_59] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_60] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_61] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_62] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_63] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_64] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_65] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_66] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_67] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_68] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_69] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_70] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_71] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_72] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_73] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_74] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_75] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_76] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_77] +CursorCol=18 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_78] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_79] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_80] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_81] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_82] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_83] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_84] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_85] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_86] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_87] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_88] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_89] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_90] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_91] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_92] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_93] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_113] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_114] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_189] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_190] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_187] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_188] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_135] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_143] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_126] +CursorCol=1 +CursorRow=515 +TopLine=496 +LeftChar=1 +Open=0 +Top=0 +[Editor_127] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_128] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_133] +CursorCol=1 +CursorRow=684 +TopLine=643 +LeftChar=1 +Open=0 +Top=0 +[Editor_134] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_136] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_137] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_138] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_139] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_140] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_141] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_145] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_144] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_142] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_146] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_147] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_150] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_152] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_154] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_132] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_148] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_149] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_151] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_153] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_155] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_156] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_157] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_158] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_159] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_160] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_161] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_162] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_173] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_174] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_175] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_176] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_181] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_177] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_178] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_179] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_180] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_182] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_183] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_184] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_185] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_186] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_119] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_131] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_124] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_125] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_122] +CursorCol=17 +CursorRow=207 +TopLine=197 +LeftChar=1 +Open=0 +Top=0 +[Editor_123] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_129] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_130] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_163] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_164] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_166] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_167] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_109] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_110] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_192] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_170] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_168] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_169] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_165] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_111] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_112] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_101] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_102] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_103] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_104] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_105] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_106] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_107] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_115] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_116] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_117] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_118] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_120] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_121] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_171] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Focused=-1 +Order=-1 +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_94] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_95] +Open=0 +Top=0 +[Editor_96] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_97] +Open=1 +Top=0 +CursorCol=28 +CursorRow=477 +TopLine=439 +LeftChar=1 +[Editor_98] +Open=0 +Top=0 +[Editor_99] +Open=0 +Top=0 +CursorCol=1 +CursorRow=337 +TopLine=296 +LeftChar=1 +[Editor_100] +Open=0 +Top=0 +[Editor_108] +Open=0 +Top=0 +CursorCol=3 +CursorRow=3 +TopLine=1 +LeftChar=1 +[Editor_172] +Open=0 +Top=0 +[Editor_191] +Open=0 +Top=0 +[Editor_193] +Open=0 +Top=0 +CursorCol=20 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_194] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_195] +Open=0 +Top=0 +CursorCol=1 +CursorRow=349 +TopLine=1 +LeftChar=1 +[Editor_196] +Open=0 +Top=0 +[Editor_197] +Open=0 +Top=0 +CursorCol=6 +CursorRow=42 +TopLine=37 +LeftChar=1 +[Editor_198] +Open=0 +Top=0 +CursorCol=6 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_199] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_200] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_201] +Open=0 +Top=0 +CursorCol=21 +CursorRow=133 +TopLine=89 +LeftChar=1 +[Editor_202] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_203] +Open=0 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_204] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_205] +Open=1 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_206] +Open=0 +Top=0 diff --git a/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.h b/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.h new file mode 100644 index 0000000..38d3841 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef PCSX2_PRIVATE_H +#define PCSX2_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*PCSX2_PRIVATE_H*/ diff --git a/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.rc b/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.rc new file mode 100644 index 0000000..aea0afe --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/mingw/pcsx2_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "../pcsx2.rc" + diff --git a/branches/pcsx2_0.9.2/windows/pcsx2.rc b/branches/pcsx2_0.9.2/windows/pcsx2.rc new file mode 100644 index 0000000..e393cfd --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/pcsx2.rc @@ -0,0 +1,1535 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Rumano resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CMDLINE DIALOG 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Program arguments" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,36,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,99,37,50,14 + CTEXT "Tip: If you don't know what to write\nleave it blank", + IDC_TIP,7,56,172,19,WS_BORDER + EDITTEXT IDC_CMDLINE,7,17,172,14,ES_AUTOHSCROLL + LTEXT "Fill in the command line arguments for opened program:", + IDC_TEXT,7,7,174,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CMDLINE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Rumano resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Ingls (Estados Unidos) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CP0REGS DIALOG 0, 0, 267, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP0 " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CP00,48,7,51,12,ES_READONLY + LTEXT "Index",-1,7,9,18,8 + EDITTEXT IDC_CP01,48,21,51,12,ES_READONLY + LTEXT "Random",-1,7,23,28,8 + EDITTEXT IDC_CP02,48,35,51,12,ES_READONLY + LTEXT "EntryLo0",-1,7,37,29,8 + EDITTEXT IDC_CP03,48,49,51,12,ES_READONLY + LTEXT "EntryLo1",-1,7,51,29,8 + EDITTEXT IDC_CP04,48,63,51,12,ES_READONLY + LTEXT "Context",-1,7,65,25,8 + EDITTEXT IDC_CP05,48,77,51,12,ES_READONLY + LTEXT "PageMask",-1,7,79,35,8 + EDITTEXT IDC_CP06,48,91,51,12,ES_READONLY + LTEXT "Wired",-1,7,93,20,8 + EDITTEXT IDC_CP07,48,105,51,12,ES_READONLY + EDITTEXT IDC_CP08,48,119,51,12,ES_READONLY + LTEXT "BadVAddr",-1,7,121,33,8 + EDITTEXT IDC_CP09,48,133,52,12,ES_READONLY + LTEXT "Count",-1,7,135,20,8 + EDITTEXT IDC_CP010,48,147,51,12,ES_READONLY + LTEXT "EntryHi",-1,7,149,24,8 + EDITTEXT IDC_CP011,48,161,52,12,ES_READONLY + LTEXT "Compare",-1,7,163,29,8 + EDITTEXT IDC_CP012,48,175,51,12,ES_READONLY + LTEXT "Status",-1,7,177,21,8 + EDITTEXT IDC_CP013,48,189,51,12,ES_READONLY + LTEXT "Cause",-1,7,191,21,8 + EDITTEXT IDC_CP014,48,203,51,12,ES_READONLY + LTEXT "EPC",-1,7,205,15,8 + EDITTEXT IDC_CP015,48,218,51,12,ES_READONLY + LTEXT "PRId",-1,7,219,17,8 + EDITTEXT IDC_CP016,191,7,51,12,ES_READONLY + LTEXT "Config",-1,145,9,21,8 + EDITTEXT IDC_CP017,191,21,51,12,ES_READONLY + EDITTEXT IDC_CP018,191,35,51,12,ES_READONLY + EDITTEXT IDC_CP019,191,49,51,12,ES_READONLY + EDITTEXT IDC_CP020,191,63,51,12,ES_READONLY + EDITTEXT IDC_CP021,191,77,51,12,ES_READONLY + EDITTEXT IDC_CP022,191,91,51,12,ES_READONLY + EDITTEXT IDC_CP023,191,105,51,12,ES_READONLY + EDITTEXT IDC_CP024,191,119,51,12,ES_READONLY + EDITTEXT IDC_CP025,191,133,51,12,ES_READONLY + EDITTEXT IDC_CP026,191,147,51,12,ES_READONLY + LTEXT "Debug",-1,147,122,22,8 + EDITTEXT IDC_CP027,191,161,51,12,ES_READONLY + LTEXT "Perf",-1,149,136,14,8 + EDITTEXT IDC_CP028,191,175,51,12,ES_READONLY + LTEXT "TagLo",-1,145,177,22,8 + EDITTEXT IDC_CP029,191,189,51,12,ES_READONLY + LTEXT "TagHi",-1,145,191,20,8 + EDITTEXT IDC_CP030,191,203,51,12,ES_READONLY + LTEXT "ErrorEPC",-1,145,205,30,8 + EDITTEXT IDC_CP031,191,218,51,12,ES_READONLY +END + +IDD_DEBUG DIALOGEX 0, 0, 281, 297 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Debugger" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM,7,28,198,235,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Close",IDC_DEBUG_CLOSE,223,249,50,14 + PUSHBUTTON "Step",IDC_DEBUG_STEP,223,36,50,14 + PUSHBUTTON "Skip",IDC_DEBUG_SKIP,223,54,50,14 + PUSHBUTTON "Go",IDC_DEBUG_GO,223,19,50,14 + PUSHBUTTON "Bkpt on Exec",IDC_DEBUG_BP_EXEC,223,129,50,14 + SCROLLBAR IDC_DEBUG_SCROLL,205,28,11,235,SBS_VERT + PUSHBUTTON "Jump to ADDR",IDC_DEBUG_JUMP,223,112,50,14 + PUSHBUTTON "Un/Set Log",IDC_DEBUG_LOG,223,71,50,14 + PUSHBUTTON "Bkpt on Count",IDC_DEBUG_BP_COUNT,223,145,50,14 + PUSHBUTTON "Dump code",IDC_DEBUG_DUMP,223,194,50,14 + PUSHBUTTON "Clear Bkpts",IDC_DEBUG_BP_CLEAR,223,162,50,14 + PUSHBUTTON "Dump memory",IDC_DEBUG_MEMORY,223,211,50,14 + PUSHBUTTON "Cpu ops",IDC_CPUOP,223,227,50,14 + PUSHBUTTON "Reset to PC",IDC_DEBUG_RESETTOPC,223,96,50,14 +END + +IDD_DUMP DIALOGEX 0, 0, 386, 96 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump code" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_DUMP_START,73,14,82,13 + EDITTEXT IDC_DUMP_END,73,29,82,13 + EDITTEXT IDC_DUMP_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,87,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,227,73,50,14 + LTEXT "Start PC Address:",IDC_STATIC,19,17,52,8 + LTEXT "End PC Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 + GROUPBOX "EE",IDC_STATIC,14,6,167,64 + EDITTEXT IDC_DUMP_STARTIOP,255,15,82,13 + EDITTEXT IDC_DUMP_ENDIOP,255,30,82,13 + EDITTEXT IDC_DUMP_FNAMEIOP,255,50,82,13,ES_AUTOHSCROLL + LTEXT "Start PC Address:",IDC_STATIC,201,18,52,8 + LTEXT "End PC Address:",IDC_STATIC,201,33,50,8 + LTEXT "Filename:",IDC_STATIC,201,54,31,8 + GROUPBOX "IOP",IDC_STATIC,195,7,167,63 +END + +IDD_GPREGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "R5900 Main registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_GPR0,22,7,166,12,ES_READONLY + LTEXT "R0",-1,7,9,10,8 + EDITTEXT IDC_GPR1,22,21,166,12,ES_READONLY + LTEXT "AT",-1,7,23,10,8 + EDITTEXT IDC_GPR2,22,35,166,12,ES_READONLY + LTEXT "V0",-1,7,37,10,8 + EDITTEXT IDC_GPR3,22,49,166,12,ES_READONLY + LTEXT "V1",-1,7,51,10,8 + EDITTEXT IDC_GPR4,22,63,166,12,ES_READONLY + LTEXT "A0",-1,7,65,10,8 + EDITTEXT IDC_GPR5,22,77,166,12,ES_READONLY + LTEXT "A1",-1,7,79,10,8 + EDITTEXT IDC_GPR6,22,91,166,12,ES_READONLY + LTEXT "A2",-1,7,93,10,8 + EDITTEXT IDC_GPR7,22,105,166,12,ES_READONLY + LTEXT "A3",-1,7,107,10,8 + EDITTEXT IDC_GPR8,22,119,166,12,ES_READONLY + LTEXT "T0",-1,7,121,10,8 + EDITTEXT IDC_GPR9,22,133,166,12,ES_READONLY + LTEXT "T1",-1,7,135,10,8 + EDITTEXT IDC_GPR10,22,147,166,12,ES_READONLY + LTEXT "T2",-1,7,149,10,8 + EDITTEXT IDC_GPR11,22,161,166,12,ES_READONLY + LTEXT "T3",-1,7,163,10,8 + EDITTEXT IDC_GPR12,22,175,166,12,ES_READONLY + LTEXT "T4",-1,7,177,10,8 + EDITTEXT IDC_GPR13,22,189,166,12,ES_READONLY + LTEXT "T5",-1,7,191,10,8 + EDITTEXT IDC_GPR14,22,203,166,12,ES_READONLY + LTEXT "T6",-1,7,205,10,8 + EDITTEXT IDC_GPR15,22,218,166,12,ES_READONLY + LTEXT "T7",-1,7,219,10,8 + EDITTEXT IDC_GPR16,214,7,165,12,ES_READONLY + LTEXT "S0",-1,196,10,10,8 + EDITTEXT IDC_GPR17,214,20,166,12,ES_READONLY + LTEXT "S1",-1,196,22,10,8 + EDITTEXT IDC_GPR18,214,35,166,12,ES_READONLY + LTEXT "S2",-1,196,36,10,8 + EDITTEXT IDC_GPR19,214,49,165,12,ES_READONLY + LTEXT "S3",-1,196,52,10,8 + EDITTEXT IDC_GPR20,214,63,165,12,ES_READONLY + LTEXT "S4",-1,196,66,10,8 + EDITTEXT IDC_GPR21,214,76,165,12,ES_READONLY + LTEXT "S5",-1,196,80,10,8 + EDITTEXT IDC_GPR22,214,91,165,12,ES_READONLY + LTEXT "S6",-1,196,94,10,8 + EDITTEXT IDC_GPR23,214,105,165,12,ES_READONLY + LTEXT "S7",-1,196,108,10,8 + EDITTEXT IDC_GPR24,214,119,165,12,ES_READONLY + LTEXT "T8",-1,196,121,10,8 + EDITTEXT IDC_GPR25,214,132,165,12,ES_READONLY + LTEXT "T9",-1,196,135,10,8 + EDITTEXT IDC_GPR26,214,147,165,12,ES_READONLY + LTEXT "K0",-1,196,149,10,8 + EDITTEXT IDC_GPR27,214,161,165,12,ES_READONLY + LTEXT "K1",-1,196,163,10,8 + EDITTEXT IDC_GPR28,214,175,165,12,ES_READONLY + LTEXT "GP",-1,196,178,11,8 + EDITTEXT IDC_GPR29,214,188,165,12,ES_READONLY + LTEXT "SP",-1,196,190,10,8 + EDITTEXT IDC_GPR30,214,203,165,12,ES_READONLY + LTEXT "S8",-1,196,205,10,8 + EDITTEXT IDC_GPR31,214,217,165,12,ES_READONLY + LTEXT "RA",-1,196,220,11,8 + EDITTEXT IDC_GPR_PC,20,260,57,12,ES_READONLY + LTEXT "PC",-1,7,263,10,8 + EDITTEXT IDC_GPR_HI,21,238,167,12,ES_READONLY + LTEXT "HI",-1,7,241,8,8 + LTEXT "LO",-1,196,241,10,8 + EDITTEXT IDC_GPR_LO,214,238,165,12,ES_READONLY +END + +IDD_JUMP DIALOG 0, 0, 175, 64 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Jump to specific address" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_JUMP_PC,73,14,82,13 + DEFPUSHBUTTON "OK",IDOK,25,43,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14 + LTEXT "Enter new PC Address:",IDC_STATIC,3,18,70,8 +END + +IDD_MEMORY DIALOG 0, 0, 317, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Memory" +FONT 8, "Courier" +BEGIN + EDITTEXT IDC_MEMORY_ADDR,54,7,97,12 + PUSHBUTTON "Close",IDC_MEMORY_CLOSE,266,7,42,14 + LTEXT "Address:",IDC_STATIC,14,8,34,8 + LISTBOX IDC_MEMORY_DUMP,3,29,300,169,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_TABSTOP + SCROLLBAR IDC_MEM_SCROLL,303,29,9,172,SBS_VERT + GROUPBOX "Memory Patch",IDC_STATIC,3,204,307,57 + EDITTEXT IDC_ADDRESS_PATCH,124,220,97,12 + EDITTEXT IDC_DATA_PATCH,124,242,97,12 + LTEXT "Address",IDC_STATIC,84,222,40,8 + LTEXT "Data",IDC_STATIC,85,244,39,8 + PUSHBUTTON "Patch It",IDC_PATCH,238,230,64,16 + PUSHBUTTON "Raw dump",IDC_DUMPRAW,204,7,50,14 +END + +IDD_VU1INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1 Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU1_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU1_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU1_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU1_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU1_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU1_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU1_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU1_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU1_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU1_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU1_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU1_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU1_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU1_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU1_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU1_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU1_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU1_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU1_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU1_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU1_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU1_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU1_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU1_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU1_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU1_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU1_VI27,172,161,89,12,WS_DISABLED + LTEXT "P register",IDC_STATIC,124,108,30,8 + EDITTEXT IDC_VU1_VI28,172,175,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI29,172,189,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU1_VI31,172,218,89,12,WS_DISABLED + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU1_ACC,78,239,166,12,ES_READONLY +END + +IDD_VU0REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU0_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU0_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU0_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU0_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU0_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU0_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU0_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU0_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU0_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU0_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU0_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU0_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU0_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU0_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU0_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU0_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU0_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU0_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU0_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU0_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU0_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU0_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU0_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU0_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU0_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU0_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU0_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU0_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU0_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU0_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU0_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_CP1REGS DIALOG 0, 0, 357, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP1 Registers " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_FP0,29,7,89,12,WS_DISABLED + LTEXT "FP0",IDC_STATIC,7,9,14,8 + EDITTEXT IDC_FP1,29,21,89,12,WS_DISABLED + LTEXT "FP1",IDC_STATIC,7,23,14,8 + EDITTEXT IDC_FP2,29,35,89,12,WS_DISABLED + LTEXT "FP2",IDC_STATIC,7,37,14,8 + EDITTEXT IDC_FP3,29,49,89,12,WS_DISABLED + LTEXT "FP3",IDC_STATIC,7,51,14,8 + EDITTEXT IDC_FP4,29,63,89,12,WS_DISABLED + LTEXT "FP4",IDC_STATIC,7,65,14,8 + EDITTEXT IDC_FP5,29,77,89,12,WS_DISABLED + LTEXT "FP5",IDC_STATIC,7,79,14,8 + EDITTEXT IDC_FP6,29,91,89,12,WS_DISABLED + LTEXT "FP6",IDC_STATIC,7,93,14,8 + EDITTEXT IDC_FP7,29,105,89,12,WS_DISABLED + LTEXT "FP7",IDC_STATIC,7,107,14,8 + EDITTEXT IDC_FP8,29,119,89,12,WS_DISABLED + LTEXT "FP8",IDC_STATIC,7,121,14,8 + EDITTEXT IDC_FP9,29,133,89,12,WS_DISABLED + LTEXT "FP9",IDC_STATIC,7,135,14,8 + EDITTEXT IDC_FP10,29,147,89,12,WS_DISABLED + LTEXT "FP10",IDC_STATIC,7,149,18,8 + EDITTEXT IDC_FP11,29,161,89,12,WS_DISABLED + LTEXT "FP11",IDC_STATIC,7,163,18,8 + EDITTEXT IDC_FP12,29,175,89,12,WS_DISABLED + LTEXT "FP12",IDC_STATIC,7,177,18,8 + EDITTEXT IDC_FP13,29,189,89,12,WS_DISABLED + LTEXT "FP13",IDC_STATIC,7,191,18,8 + EDITTEXT IDC_FP14,29,203,89,12,WS_DISABLED + LTEXT "FP14",IDC_STATIC,7,205,18,8 + EDITTEXT IDC_FP15,29,218,89,12,WS_DISABLED + LTEXT "FP15",IDC_STATIC,7,219,18,8 + EDITTEXT IDC_FP16,145,7,89,12,WS_DISABLED + LTEXT "FP16",IDC_STATIC,123,9,18,8 + EDITTEXT IDC_FP17,145,21,89,12,WS_DISABLED + LTEXT "FP17",IDC_STATIC,123,23,18,8 + EDITTEXT IDC_FP18,145,35,89,12,WS_DISABLED + LTEXT "FP18",IDC_STATIC,123,37,18,8 + EDITTEXT IDC_FP19,145,49,89,12,WS_DISABLED + LTEXT "FP19",IDC_STATIC,123,51,18,8 + EDITTEXT IDC_FP20,145,63,89,12,WS_DISABLED + LTEXT "FP20",IDC_STATIC,123,65,18,8 + EDITTEXT IDC_FP21,145,77,89,12,WS_DISABLED + LTEXT "FP21",IDC_STATIC,123,79,18,8 + EDITTEXT IDC_FP22,145,91,89,12,WS_DISABLED + LTEXT "FP22",IDC_STATIC,123,93,18,8 + EDITTEXT IDC_FP23,145,105,89,12,WS_DISABLED + LTEXT "FP23",IDC_STATIC,123,107,18,8 + EDITTEXT IDC_FP24,145,119,89,12,WS_DISABLED + LTEXT "FP24",IDC_STATIC,123,121,18,8 + EDITTEXT IDC_FP25,145,133,89,12,WS_DISABLED + LTEXT "FP25",IDC_STATIC,123,135,18,8 + EDITTEXT IDC_FP26,145,147,89,12,WS_DISABLED + LTEXT "FP26",IDC_STATIC,123,149,18,8 + EDITTEXT IDC_FP27,145,161,89,12,WS_DISABLED + LTEXT "FP27",IDC_STATIC,123,163,18,8 + EDITTEXT IDC_FP28,145,175,89,12,WS_DISABLED + LTEXT "FP28",IDC_STATIC,123,177,18,8 + EDITTEXT IDC_FP29,145,189,89,12,WS_DISABLED + LTEXT "FP29",IDC_STATIC,123,191,18,8 + EDITTEXT IDC_FP30,145,203,89,12,WS_DISABLED + LTEXT "FP30",IDC_STATIC,123,205,18,8 + EDITTEXT IDC_FP31,145,218,89,12,WS_DISABLED + LTEXT "FP31",IDC_STATIC,123,219,18,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,244,8,1, + 223 + LTEXT "Implementation/Revision Reg",IDC_STATIC,253,9,94,8 + EDITTEXT IDC_FCR0,298,21,50,12,WS_DISABLED + LTEXT "FCR0",IDC_STATIC,253,23,19,8 + LTEXT "Control/Status Register",IDC_STATIC,253,37,74,8 + EDITTEXT IDC_FCR31,298,49,50,12,WS_DISABLED + LTEXT "FCR31",IDC_STATIC,253,51,23,8 + LTEXT "Accumulator",IDC_STATIC,256,68,43,14 + EDITTEXT IDC_FPU_ACC,299,68,49,12,ES_AUTOHSCROLL | WS_DISABLED +END + +IDD_VU0INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU0_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU0_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU0_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU0_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU0_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU0_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU0_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU0_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU0_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU0_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU0_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU0_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU0_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU0_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU0_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU0_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU0_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU0_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU0_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU0_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU0_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU0_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU0_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU0_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU0_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU0_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU0_VI27,172,161,89,12,WS_DISABLED + LTEXT "CMSAR0 reg",IDC_STATIC,123,163,42,8 + EDITTEXT IDC_VU0_VI28,172,175,89,12,WS_DISABLED + LTEXT "FBRST register",IDC_STATIC,123,177,49,8 + EDITTEXT IDC_VU0_VI29,172,189,89,12,WS_DISABLED + LTEXT "VPU-STAT reg",IDC_STATIC,123,191,48,8 + EDITTEXT IDC_VU0_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU0_VI31,172,218,89,12,WS_DISABLED + LTEXT "CMSAR1 reg",IDC_STATIC,123,219,42,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU0_ACC,78,239,166,12,ES_READONLY + LTEXT "P register",IDC_STATIC,124,108,30,8 +END + +IDD_VU1REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU1_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU1_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU1_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU1_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU1_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU1_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU1_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU1_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU1_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU1_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU1_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU1_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU1_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU1_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU1_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU1_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU1_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU1_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU1_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU1_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU1_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU1_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU1_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU1_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU1_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU1_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU1_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU1_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU1_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU1_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU1_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_RDEBUGPARAMS DIALOGEX 0, 0, 174, 58 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,37,50,14 + EDITTEXT IDC_PORT,127,7,40,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Accept connections on TCP/IP port:",IDC_STATIC,7,7,120, + 10 + CONTROL "Debug Bios",IDC_DEBUGBIOS,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | WS_TABSTOP,7,22,50,10 +END + +IDD_RDEBUG DIALOGEX 0, 0, 254, 271 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "E&xit",IDOK,199,251,48,14 + LISTBOX IDC_COMMUNICATION,7,7,240,211,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + PUSHBUTTON "&Clear",IDC_CLEAR,199,229,48,14 + EDITTEXT IDC_EEPC,74,229,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPPC,132,229,52,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "EE pc address:\t IOP pc address:",IDC_STATIC,77,219,113, + 9 + CONTROL "Debug EE",IDC_DEBUGEE,"Button",BS_AUTORADIOBUTTON,77, + 255,48,10 + CONTROL "Debug IOP",IDC_DEBUGIOP,"Button",BS_AUTORADIOBUTTON | + BS_LEFTTEXT,132,254,50,11 + EDITTEXT IDC_STOPAT,7,229,56,13,ES_AUTOHSCROLL + EDITTEXT IDC_STOPAFTER,7,252,56,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Break at (hex addr):",IDC_STATIC,7,219,67,8 + LTEXT "Break after (cycles):",IDC_STATIC,7,243,66,8 + EDITTEXT IDC_EECYCLE,74,241,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPCYCLE,132,241,52,12,ES_AUTOHSCROLL | ES_READONLY +END + +IDD_MCDCONF DIALOG 0, 0, 407, 197 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Memcard Manager" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,285,175,50,14 + PUSHBUTTON "Cancel",IDCANCEL,345,175,50,14 + EDITTEXT IDC_MCD1,10,155,160,14,ES_AUTOHSCROLL + EDITTEXT IDC_MCD2,235,155,160,14,ES_AUTOHSCROLL + PUSHBUTTON "Select Mcd",IDC_MCDSEL1,10,135,50,14 + PUSHBUTTON "Select Mcd",IDC_MCDSEL2,235,135,50,14 + GROUPBOX "Memory Card 2",IDC_FRAMEMCD2,230,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT1,65,135,50,14 + GROUPBOX "Memory Card 1",IDC_FRAMEMCD1,5,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT2,290,135,50,14 + CONTROL "List3",IDC_LIST1,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,15,160,110 + CONTROL "List3",IDC_LIST2,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,235,15,160,110 + PUSHBUTTON "Reload Mcd",IDC_RELOAD1,120,135,50,14 + PUSHBUTTON "Reload Mcd",IDC_RELOAD2,345,135,50,14 + PUSHBUTTON "-> Copy ->",IDC_COPYTO2,180,30,45,14 + PUSHBUTTON "<- Copy <-",IDC_COPYTO1,180,50,45,14 + PUSHBUTTON "Paste",IDC_PASTE,180,70,45,14 + PUSHBUTTON "<- Un/Delete",IDC_DELETE1,180,90,45,14 + PUSHBUTTON "Un/Delete ->",IDC_DELETE2,180,110,45,14 +END + +IDD_DUMPMEM DIALOG 0, 0, 175, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump memory" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DUMPMEM_START,73,14,82,13 + EDITTEXT IDC_DUMPMEM_END,73,29,82,13 + EDITTEXT IDC_DUMPMEM_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,25,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,74,50,14 + LTEXT "Start Address:",IDC_STATIC,19,17,52,8 + LTEXT "End Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 +END + +IDD_DIALOGBAR DIALOGEX 0, 0, 330, 16 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "TODO: layout dialog bar",IDC_STATIC,126,4,77,8 +END + +IDD_IOPREGS DIALOGEX 0, 0, 417, 295 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "IOP Main Registers" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_IOPGPR0,22,20,166,12,ES_READONLY + LTEXT "R0",-1,7,23,10,8 + EDITTEXT IDC_IOPGPR1,22,34,166,12,ES_READONLY + LTEXT "AT",-1,7,36,10,8 + EDITTEXT IDC_IOPGPR2,22,49,166,12,ES_READONLY + LTEXT "V0",-1,7,50,10,8 + EDITTEXT IDC_IOPGPR3,22,63,166,12,ES_READONLY + LTEXT "V1",-1,7,65,10,8 + EDITTEXT IDC_IOPGPR4,22,76,166,12,ES_READONLY + LTEXT "A0",-1,7,79,10,8 + EDITTEXT IDC_IOPGPR5,22,90,166,12,ES_READONLY + LTEXT "A1",-1,7,92,10,8 + EDITTEXT IDC_IOPGPR6,22,105,166,12,ES_READONLY + LTEXT "A2",-1,7,106,10,8 + EDITTEXT IDC_IOPGPR7,22,119,166,12,ES_READONLY + LTEXT "A3",-1,7,121,10,8 + EDITTEXT IDC_IOPGPR8,22,132,166,12,ES_READONLY + LTEXT "T0",-1,7,135,10,8 + EDITTEXT IDC_IOPGPR9,22,146,166,12,ES_READONLY + LTEXT "T1",-1,7,148,10,8 + EDITTEXT IDC_IOPGPR10,22,161,166,12,ES_READONLY + LTEXT "T2",-1,7,162,10,8 + EDITTEXT IDC_IOPGPR11,22,175,166,12,ES_READONLY + LTEXT "T3",-1,7,177,10,8 + EDITTEXT IDC_IOPGPR12,22,188,166,12,ES_READONLY + LTEXT "T4",-1,7,191,10,8 + EDITTEXT IDC_IOPGPR13,22,202,166,12,ES_READONLY + LTEXT "T5",-1,7,204,10,8 + EDITTEXT IDC_IOPGPR14,22,217,166,12,ES_READONLY + LTEXT "T6",-1,7,218,10,8 + EDITTEXT IDC_IOPGPR15,22,231,166,12,ES_READONLY + LTEXT "T7",-1,7,233,10,8 + EDITTEXT IDC_IOPGPR16,214,20,165,12,ES_READONLY + LTEXT "S0",-1,196,23,10,8 + EDITTEXT IDC_IOPGPR17,214,34,166,12,ES_READONLY + LTEXT "S1",-1,196,36,10,8 + EDITTEXT IDC_IOPGPR18,214,49,166,12,ES_READONLY + LTEXT "S2",-1,196,50,10,8 + EDITTEXT IDC_IOPGPR19,214,63,165,12,ES_READONLY + LTEXT "S3",-1,196,66,10,8 + EDITTEXT IDC_IOPGPR20,214,76,165,12,ES_READONLY + LTEXT "S4",-1,196,79,10,8 + EDITTEXT IDC_IOPGPR21,214,90,165,12,ES_READONLY + LTEXT "S5",-1,196,94,10,8 + EDITTEXT IDC_IOPGPR22,214,105,165,12,ES_READONLY + LTEXT "S6",-1,196,108,10,8 + EDITTEXT IDC_IOPGPR23,214,119,165,12,ES_READONLY + LTEXT "S7",-1,196,122,10,8 + EDITTEXT IDC_IOPGPR24,214,132,165,12,ES_READONLY + LTEXT "T8",-1,196,135,10,8 + EDITTEXT IDC_IOPGPR25,214,146,165,12,ES_READONLY + LTEXT "T9",-1,196,148,10,8 + EDITTEXT IDC_IOPGPR26,214,161,165,12,ES_READONLY + LTEXT "K0",-1,196,162,10,8 + EDITTEXT IDC_IOPGPR27,214,175,165,12,ES_READONLY + LTEXT "K1",-1,196,177,10,8 + EDITTEXT IDC_IOPGPR28,214,188,165,12,ES_READONLY + LTEXT "GP",-1,196,191,11,8 + EDITTEXT IDC_IOPGPR29,214,202,165,12,ES_READONLY + LTEXT "SP",-1,196,204,10,8 + EDITTEXT IDC_IOPGPR30,214,217,165,12,ES_READONLY + LTEXT "S8",-1,196,218,10,8 + EDITTEXT IDC_IOPGPR31,214,231,165,12,ES_READONLY + LTEXT "RA",-1,196,234,11,8 + EDITTEXT IDC_IOPGPR_PC,20,272,57,12,ES_READONLY + LTEXT "PC",-1,7,276,10,8 + EDITTEXT IDC_IOPGPR_HI,21,252,167,12,ES_READONLY + LTEXT "HI",-1,7,255,8,8 + LTEXT "LO",-1,196,255,10,8 + EDITTEXT IDC_IOPGPR_LO,214,252,165,12,ES_READONLY +END + +IDD_USERNAME DIALOGEX 0, 0, 186, 79 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Enter User Name" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,58,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,58,50,14 + LTEXT "Pcsx2 needs to allocate physical memory in order to execute faster. Enter the windows username you wish this privilege to be enabled for.", + IDC_STATIC,7,7,172,25 + EDITTEXT IDC_USER_NAME,73,37,106,13,ES_AUTOHSCROLL + LTEXT "User Name:",IDC_STATIC,7,41,38,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DEBUG, DIALOG + BEGIN + BOTTOMMARGIN, 282 + END + + IDD_RDEBUGPARAMS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + END + + IDD_RDEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 247 + TOPMARGIN, 7 + BOTTOMMARGIN, 265 + END + + IDD_MCDCONF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 240 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_DIALOGBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 323 + TOPMARGIN, 7 + BOTTOMMARGIN, 9 + END + + IDD_IOPREGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 410 + TOPMARGIN, 7 + BOTTOMMARGIN, 284 + END + + IDD_USERNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 72 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_PS2SILVER BITMAP "ps2_silver.bmp" +#endif // Ingls (Estados Unidos) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Ingls (Reino Unido) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUT_DIALOG DIALOGEX 0, 0, 431, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_ACCEPTFILES +CAPTION "About" +FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,250,50,14 + CTEXT "PCSX2 \nVersion x.x",IDC_PCSX_ABOUT_TEXT,55,10,45,15,0, + WS_EX_TRANSPARENT + CTEXT "PCSX2 a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,36, + 135,92,0,WS_EX_TRANSPARENT + CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,88,158,311,77 + GROUPBOX "",IDC_STATIC,5,29,145,113 + GROUPBOX "",IDC_STATIC,77,148,333,91 + CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,0,167,70,74 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + ABOUT_DIALOG, DIALOG + BEGIN + RIGHTMARGIN, 429 + BOTTOMMARGIN, 264 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +SPLASH_LOGO BITMAP "..\\pcsxAbout.bmp" +#endif // Ingls (Reino Unido) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Espaol resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_FINDER DIALOGEX 3, 1, 262, 212 +STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU +CAPTION "Cheat Finder" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "Results",IDC_RESULTS,"SysListView32",LVS_REPORT | + WS_TABSTOP,96,15,161,153,WS_EX_CLIENTEDGE + GROUPBOX "Values of size",IDC_STATIC,5,44,86,45 + CHECKBOX "Unsigned",IDC_UNSIGNED,11,74,70,10,NOT WS_TABSTOP + CONTROL "64bits",IDC_64B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 48,64,33,10 + CONTROL "32bits",IDC_32B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 48,54,33,10 + CONTROL "16bits",IDC_16B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,64,33,10 + CONTROL "8bits",IDC_8B,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11, + 54,33,10 + PUSHBUTTON "Close",IDCANCEL,208,192,49,15,NOT WS_TABSTOP + PUSHBUTTON "Search",IDC_SEARCH,96,192,49,15,NOT WS_TABSTOP + GROUPBOX "Comapred to",IDC_STATIC,5,162,86,45 + EDITTEXT IDC_VALUE,21,192,65,12,ES_AUTOHSCROLL | NOT WS_TABSTOP + CONTROL "Specific Value",IDC_SET,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,182,75,10 + CONTROL "Old Value",IDC_OLD,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,172,75,10 + GROUPBOX "Search in",IDC_STATIC,5,5,86,35 + CONTROL "Smaller or equal",IDC_LE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,139,75,10 + CONTROL "Greater or equal",IDC_GE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,129,75,10 + CONTROL "Smaller",IDC_LT,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,120,75,10 + CONTROL "Greater",IDC_GT,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,110,75,10 + CONTROL "Equal",IDC_EQ,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11, + 101,75,10 + PUSHBUTTON "Reset",IDC_RESET,96,172,49,15,NOT WS_TABSTOP + PUSHBUTTON "Add",IDC_ADD,208,172,49,15,NOT WS_TABSTOP + RTEXT "1 match found.",IDC_MATCHES,125,5,132,10,NOT WS_GROUP + LTEXT "Results:",IDC_STATIC,96,5,29,10,NOT WS_GROUP + CONTROL "EE RAM",IDC_EE,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,15,43,10 + CONTROL "IOP RAM",IDC_IOP,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,25,43,10 + CONTROL "Not equal",IDC_NE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,148,75,10 + GROUPBOX "being",IDC_STATIC,5,92,86,67 +END + +IDD_ADD DIALOGEX 3, 1, 145, 74 +STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU +CAPTION "Add Cheat" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + PUSHBUTTON "OK",IDOK,37,54,49,15,NOT WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,91,54,49,15,NOT WS_TABSTOP + LTEXT "Cheat Name",IDC_STATIC,5,30,75,10,NOT WS_GROUP + LTEXT "New Value",IDC_STATIC,69,5,70,10,NOT WS_GROUP + LTEXT "Address",IDC_STATIC,5,5,59,10,NOT WS_GROUP + EDITTEXT IDC_NAME,5,39,134,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + EDITTEXT IDC_VALUE,69,15,70,12,ES_AUTOHSCROLL | NOT WS_TABSTOP + EDITTEXT IDC_ADDR,5,15,59,12,ES_AUTOHSCROLL | NOT WS_TABSTOP +END + +IDD_CHEATS DIALOGEX 0, 0, 232, 222 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,119,201,50,14 + PUSHBUTTON "Cancel",IDCANCEL,175,201,50,14 + CONTROL "",IDC_GROUPS,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_EDITLABELS | TVS_CHECKBOXES | + WS_TABSTOP,7,7,218,126,WS_EX_CLIENTEDGE + CONTROL "",IDC_PATCHES,"SysListView32",LVS_REPORT | WS_TABSTOP,7, + 139,218,57,WS_EX_CLIENTEDGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CHEATS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 225 + TOPMARGIN, 7 + BOTTOMMARGIN, 215 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Espaol resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Espaol (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 317, 244 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_LISTGS,10,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGGS,10,35,45,12 + PUSHBUTTON "Test...",IDC_TESTGS,60,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTGS,110,35,45,12 + COMBOBOX IDC_LISTSPU2,166,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGSPU2,165,35,45,12 + PUSHBUTTON "Test...",IDC_TESTSPU2,215,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTSPU2,265,35,43,12 + COMBOBOX IDC_LISTCDVD,10,105,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGCDVD,10,125,43,12 + PUSHBUTTON "Test...",IDC_TESTCDVD,60,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTCDVD,110,125,45,12 + COMBOBOX IDC_LISTBIOS,165,196,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,207,223,50,14 + PUSHBUTTON "Cancel",IDCANCEL,260,223,50,14 + RTEXT "Graphics",IDC_GRAPHICS,50,5,41,10,SS_CENTERIMAGE + RTEXT "Sound",IDC_SOUND,200,5,43,10,SS_CENTERIMAGE + RTEXT "Cdvdrom",IDC_CDVDROM,65,95,30,10,SS_CENTERIMAGE + RTEXT "Bios",IDC_BIOS,228,185,15,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD1,10,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD1,10,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD1,60,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD1,110,80,45,12 + RTEXT "Second Controller",IDC_SECONDCONTROLLER,205,50,58,10, + SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD2,166,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD2,165,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD2,215,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD2,265,80,45,12 + CTEXT "First Controller",IDC_FIRSTCONTROLLER,55,50,48,10, + SS_CENTERIMAGE + PUSHBUTTON "Set Bios Directory",IDC_BIOSDIR,90,223,65,14 + PUSHBUTTON "Set Plugins Directory",IDC_PLUGINSDIR,7,223,75,14 + COMBOBOX IDC_LISTDEV9,165,105,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGDEV9,165,125,43,12 + PUSHBUTTON "Test...",IDC_TESTDEV9,215,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTDEV9,265,125,45,12 + CTEXT "Dev9",IDC_DEV9,221,95,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTUSB,10,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGUSB,10,170,43,12 + PUSHBUTTON "Test...",IDC_TESTUSB,60,170,45,12 + PUSHBUTTON "About...",IDC_ABOUTUSB,110,170,45,12 + CTEXT "Usb",IDC_USB,66,140,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTFW,165,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGFW,165,169,43,12 + PUSHBUTTON "Test...",IDC_TESTFW,214,169,45,12 + PUSHBUTTON "About...",IDC_ABOUTFW,265,169,45,12 + LTEXT "FireWire",IDC_STATIC,227,141,39,8 +END + +IDD_BPEXEC DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Exec" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EXECBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Address:",IDC_STATIC,5,13,84,8 +END + +IDD_BPCNT DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Count" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CNTBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Count:",IDC_STATIC,5,13,77,8 +END + +IDD_ADVANCED DIALOGEX 0, 0, 177, 69 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Advanced" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,47,50,14 + PUSHBUTTON "Cancel",IDCANCEL,121,47,50,14 + CONTROL "Enable Reg Caching",IDC_REGCACHING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,15,81,10 + GROUPBOX "",IDC_STATIC,2,7,168,38 + PUSHBUTTON "Reset",IDC_ADVRESET,5,47,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 237 + HORZGUIDE, 169 + END + + IDD_BPEXEC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 6 + BOTTOMMARGIN, 54 + END + + IDD_BPCNT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + IDD_ADVANCED, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "Cdrom02.ico" +#endif // Espaol (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Griego resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ELL) +#ifdef _WIN32 +LANGUAGE LANG_GREEK, SUBLANG_DEFAULT +#pragma code_page(1253) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PATCHBROWSER DIALOGEX 0, 0, 487, 282 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patches Browser" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "New Patch",IDC_NEWPATCH,112,257,60,14 + EDITTEXT IDC_PATCHTEXT,113,95,354,153,ES_MULTILINE | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "Save Patch",IDC_SAVEPATCH,186,257,60,14,WS_DISABLED + PUSHBUTTON "Refresh List",IDC_REFRESHPATCHLIST,21,257,60,14 + LISTBOX IDC_PATCHCRCLIST,19,95,69,153,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_PATCHNAMELIST,17,34,452,50,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Search game name patch:",IDC_GAMENAMESEARCH,17,16,101,9 + EDITTEXT IDC_SEARCHPATCHTEXT,109,14,295,12,ES_AUTOHSCROLL + PUSHBUTTON "Exit",IDC_EXITPB,411,257,59,14 +END + +IDD_LOGGING DIALOGEX 0, 0, 263, 177 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Logging" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,206,156,50,14 + CONTROL "Cpu log",IDC_CPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,5,53,10 + CONTROL "COP0 log",IDC_COP0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,20,59,10 + CONTROL "FPU log",IDC_FPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,35,55,10 + CONTROL "MMI log",IDC_MMILOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,50,55,10 + CONTROL "VUO log",IDC_VU0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,65,56,10 + CONTROL "Bios log",IDC_BIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,80,54,10 + CONTROL "DMA log",IDC_DMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,95,57,10 + CONTROL "HW log",IDC_HWLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 5,110,53,10 + CONTROL "Unknown Memory log",IDC_MEMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,5,84,10 + CONTROL "Elf log",IDC_ELFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,20,35,10 + CONTROL "VIF log",IDC_VIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,35,38,10 + CONTROL "Scratch pad log",IDC_SPRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,50,66,10 + CONTROL "Gif log",IDC_GIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,65,49,10 + CONTROL "SIF log",IDC_SIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,80,51,10 + GROUPBOX "IOP",IDC_STATIC,161,7,95,127 + CONTROL "IOP cpu log",IDC_IOPLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,15,67,10 + CONTROL "HW log",IDC_IOPHWLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,30,53,10 + CONTROL "Bios log",IDC_IOPBIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,45,41,10 + CONTROL "Unknown Memory log",IDC_IOPMEMLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,60,85,10 + CONTROL "IPU log",IDC_IPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,95,39,10 + CONTROL "DMA log",IDC_IOPDMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,75,67,10 + CONTROL "PAD log",IDC_IOPPADLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,90,53,10 + CONTROL "CDR log",IDC_IOPCDRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,104,43,10 + CONTROL "VUMicro log",IDC_VUMICROLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,110,55,10 + CONTROL "RPC services log",IDC_RPCSERVICES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,5,125,67,10 + CONTROL "Log to STDOUT",IDC_STDOUTPUTLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,75,125,68,10 + CONTROL "Log",IDC_LOGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5, + 140,28,10 + CONTROL "Symbols log",IDC_SYMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,140,53,10 + CONTROL "Counters log",IDC_IOPCNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,118,55,10 + CONTROL "EE Counters log",IDC_EECNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,139,73,11 +END + +IDD_IOP_DEBUG DIALOGEX 0, 0, 358, 107 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Debug" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM_IOP,7,7,330,92,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + SCROLLBAR IDC_DEBUG_SCROLL_IOP,340,7,11,93,SBS_VERT +END + +IDD_CPUDLG DIALOGEX 0, 0, 222, 356 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "EERec - EE/IOP recompiler (need MMX/SSE)", + IDC_CPU_EEREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 110,161,18 + CONTROL "VU0rec - enable recompiler for VU0 unit",IDC_CPU_VU0REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,141,154,18 + CONTROL "VU1rec - enable recompiler for VU1 unit",IDC_CPU_VU1REC, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,155,142,18 + CONTROL "Multi threaded GS mode (MTGS)\n (faster on dual core/HT procs, requires pcsx2 restart)", + IDC_CPU_GSMULTI,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,185,208,18 + CONTROL "Dual Core Mode (DC) - Much faster but only valid with MTGS", + IDC_CPU_MULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 207,208,13 + CONTROL "Normal - All frames are rendered as fast as possible.", + IDC_CPU_FL_NORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 15,241,193,10 + CONTROL "Limit - Force frames to normal speeds if too fast.", + IDC_CPU_FL_LIMIT,"Button",BS_AUTORADIOBUTTON,15,254,180, + 10 + CONTROL "Frame Skip - In order to achieve normal speeds,\n some frames are skipped (fast).\n Fps displayed counts skipped frames too.", + IDC_CPU_FL_SKIP,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE,15,268,187,28 + CONTROL "VU Skip - Same as 'Frame Skip', but tries to skip more.\n Artifcats might be present, but will be faster.", + IDC_CPU_FL_SKIPVU,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE,15,300,187,16 + DEFPUSHBUTTON "OK",IDOK,7,335,61,14 + PUSHBUTTON "Cancel",IDCANCEL,79,335,50,14,NOT WS_TABSTOP + LTEXT "CPU vendor ",IDC_VENDORNAME,12,24,42,12 + GROUPBOX "",IDC_STATIC,7,12,207,90 + LTEXT "Family",IDC_FAMILYNAME,12,42,36,12 + LTEXT "Cpu Speed",IDC_CPUSPEEDNAME,12,60,38,12 + LTEXT "",IDC_VENDORINPUT,54,24,154,12 + LTEXT "",IDC_FAMILYINPUT,54,42,154,12 + LTEXT "",IDC_FEATURESINPUT,54,82,154,12 + LTEXT "",IDC_CPUSPEEDINPUT,54,60,157,12 + GROUPBOX "VU Recompilers - All options are set by default", + IDC_CPU_VUGROUP,7,131,207,46 + GROUPBOX "Frame Limiting",IDC_STATIC,7,228,207,94 + LTEXT "Features",IDC_FEATURESNAME,12,78,34,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_LOGGING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 256 + TOPMARGIN, 7 + BOTTOMMARGIN, 170 + END + + IDD_IOP_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 351 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_CPUDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 215 + TOPMARGIN, 7 + BOTTOMMARGIN, 349 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Griego resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/branches/pcsx2_0.9.2/windows/ps2_silver.bmp b/branches/pcsx2_0.9.2/windows/ps2_silver.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cb58820cdf1d734c0f8889bde4b6023e9feb4e12 GIT binary patch literal 37974 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 literal 0 HcmV?d00001 diff --git a/branches/pcsx2_0.9.2/windows/resource.h b/branches/pcsx2_0.9.2/windows/resource.h new file mode 100644 index 0000000..c0cf367 --- /dev/null +++ b/branches/pcsx2_0.9.2/windows/resource.h @@ -0,0 +1,675 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pcsx2.rc +// +#define IDR_MENU 101 +#define IDD_CONFIG 101 +#define IDD_MCDCONF 102 +#define IDD_BPEXEC 103 +#define ABOUT_DIALOG 104 +#define IDD_BPCNT 105 +#define IDD_DEBUG 108 +#define IDI_ICON 108 +#define IDD_MEMORY 110 +#define IDD_VU0REGS 111 +#define IDD_JUMP 112 +#define SPLASH_LOGO 113 +#define IDD_VU0INTEGER 113 +#define IDD_GPREGS 114 +#define IDD_CP0REGS 115 +#define IDD_CP1REGS 116 +#define IDD_VU1INTEGER 117 +#define IDD_VU1REGS 118 +#define IDD_LOGGING 119 +#define IDD_CMDLINE 120 +#define IDD_RDEBUGPARAMS 121 +#define ID_DEBUG_REMOTEDEBUGGING 122 +#define IDD_RDEBUG 123 +#define IDD_DIALOGBAR 124 +#define IDD_IOP_DEBUG 125 +#define IDD_CPUDLG 126 +#define IDD_ADVANCED 127 +#define IDD_IOPREGS 128 +#define IDD_USERNAME 129 +#define IDB_PS2SILVER 132 +#define IDD_CHEATS 133 +#define IDD_DUMP 136 +#define IDD_DUMPMEM 137 +#define IDD_PATCHBROWSER 138 +#define IDD_FINDER 174 +#define IDD_ADD 175 +#define IDC_MEM_SCROLL 1001 +#define IDC_EXECBP 1001 +#define IDC_CNTBP 1002 +#define IDC_MCD2 1004 +#define IDC_VU0_VF00 1005 +#define IDC_MCD1 1005 +#define IDC_VU0_VF01 1006 +#define IDC_MCDSEL1 1006 +#define IDC_VU0_VF02 1007 +#define IDC_MCDSEL2 1007 +#define IDC_VU0_VF03 1008 +#define IDC_VU0_VF04 1009 +#define IDC_DEBUG_DISASM 1010 +#define IDC_VU0_VF05 1010 +#define IDC_VU0_VF06 1011 +#define IDC_VU0_VF07 1012 +#define IDC_VU0_VF08 1013 +#define IDC_PCSX_ABOUT_TEXT 1014 +#define IDC_PSXOUT 1014 +#define IDC_VU0_VF09 1014 +#define IDC_CPU 1015 +#define IDC_VU0_VF10 1015 +#define IDC_VSYNCHACK 1016 +#define IDC_VU0_VF11 1016 +#define IDC_VU0_VF12 1017 +#define IDC_VU0_VF13 1018 +#define IDC_VU0_VF14 1019 +#define IDC_CP07 1020 +#define IDC_VU0_VF15 1020 +#define IDC_VU0_VF16 1021 +#define IDC_VU0_VF17 1022 +#define IDC_VU0_VF18 1023 +#define IDC_VU0_VF19 1024 +#define IDC_VU0_VF20 1025 +#define IDC_VU0_VF21 1026 +#define IDC_VU0_VF22 1027 +#define IDC_VU0_VF23 1028 +#define IDC_DEBUG_CLOSE 1029 +#define IDC_VU0_VF24 1029 +#define IDC_DEBUG_STEP 1030 +#define IDC_VU0_VF25 1030 +#define IDC_DEBUG_SKIP 1031 +#define IDC_VU0_VF26 1031 +#define IDC_DEBUG_GO 1032 +#define IDC_VU0_VF27 1032 +#define IDC_DEBUG_BP_EXEC 1033 +#define IDC_VU0_VF28 1033 +#define IDC_CP021 1034 +#define IDC_DEBUG_SCROLL 1034 +#define IDC_VU0_VF29 1034 +#define IDC_CP022 1035 +#define IDC_DEBUG_RESETTOPC 1035 +#define IDC_VU0_VF30 1035 +#define IDC_CP023 1036 +#define IDC_FPU_ACC 1036 +#define IDC_DEBUG_JUMP 1036 +#define IDC_MEMORY_CLOSE 1036 +#define IDC_VU0_VF31 1036 +#define IDC_CP024 1037 +#define IDC_DEBUG_BREAK 1037 +#define IDC_MEMORY_ADDR 1037 +#define IDC_DEBUG_LOG 1037 +#define IDC_CP025 1038 +#define IDC_MEMORY_DUMP 1038 +#define IDC_DEBUG_BP_COUNT 1038 +#define IDC_VU0_VI00 1038 +#define IDC_DEBUG_L1 1039 +#define IDC_VU0_VI01 1039 +#define IDC_ADDRESS_PATCH 1039 +#define IDC_DEBUG_L2 1040 +#define IDC_VU0_VI02 1040 +#define IDC_DATA_PATCH 1040 +#define IDC_DEBUG_L3 1041 +#define IDC_VU0_VI03 1041 +#define IDC_FRAMEMCD1 1041 +#define IDC_DEBUG_L4 1042 +#define IDC_VU0_VI04 1042 +#define IDC_FRAMEMCD2 1042 +#define IDC_DEBUG_L5 1043 +#define IDC_VU0_VI05 1043 +#define IDC_CP031 1044 +#define IDC_DEBUG_L6 1044 +#define IDC_VU0_VI06 1044 +#define IDC_DEBUG_L7 1045 +#define IDC_VU0_VI07 1045 +#define IDC_DEBUG_L8 1046 +#define IDC_VU0_VI08 1046 +#define IDC_DEBUG_L9 1047 +#define IDC_GPR0 1047 +#define IDC_VU0_VI09 1047 +#define IDC_DEBUG_L10 1048 +#define IDC_GPR1 1048 +#define IDC_VU0_VI10 1048 +#define IDC_DEBUG_L11 1049 +#define IDC_GPR2 1049 +#define IDC_VU0_VI11 1049 +#define IDC_DEBUG_L12 1050 +#define IDC_GPR3 1050 +#define IDC_VU0_VI12 1050 +#define IDC_DEBUG_L13 1051 +#define IDC_GPR4 1051 +#define IDC_VU0_VI13 1051 +#define IDC_DEBUG_L14 1052 +#define IDC_GPR5 1052 +#define IDC_LISTGS 1052 +#define IDC_VU0_VI14 1052 +#define IDC_DEBUG_L15 1053 +#define IDC_GPR6 1053 +#define IDC_LISTSPU 1053 +#define IDC_VU0_VI15 1053 +#define IDC_LISTSPU2 1053 +#define IDC_DEBUG_L16 1054 +#define IDC_GPR7 1054 +#define IDC_LISTCDR 1054 +#define IDC_VU0_VI16 1054 +#define IDC_LISTCDVD 1054 +#define IDC_DEBUG_L17 1055 +#define IDC_GPR8 1055 +#define IDC_LISTBIOS 1055 +#define IDC_VU0_VI17 1055 +#define IDC_DEBUG_L18 1056 +#define IDC_GPR9 1056 +#define IDC_CONFIGGS 1056 +#define IDC_VU0_VI18 1056 +#define IDC_DEBUG_L19 1057 +#define IDC_GPR10 1057 +#define IDC_TESTGS 1057 +#define IDC_VU0_VI19 1057 +#define IDC_DEBUG_L20 1058 +#define IDC_ABOUTGS 1058 +#define IDC_VU0_VI20 1058 +#define IDC_DEBUG_L21 1059 +#define IDC_CONFIGSPU 1059 +#define IDC_VU0_VI21 1059 +#define IDC_CONFIGSPU2 1059 +#define IDC_DEBUG_L22 1060 +#define IDC_TESTSPU 1060 +#define IDC_VU0_VI22 1060 +#define IDC_TESTSPU2 1060 +#define IDC_DEBUG_L23 1061 +#define IDC_ABOUTSPU 1061 +#define IDC_VU0_VI23 1061 +#define IDC_ABOUTSPU2 1061 +#define IDC_DEBUG_L24 1062 +#define IDC_CONFIGCDR 1062 +#define IDC_VU0_VI24 1062 +#define IDC_CONFIGCDVD 1062 +#define IDC_DEBUG_L25 1063 +#define IDC_GPR11 1063 +#define IDC_TESTCDR 1063 +#define IDC_VU0_VI25 1063 +#define IDC_TESTCDVD 1063 +#define IDC_DEBUG_L26 1064 +#define IDC_ABOUTCDR 1064 +#define IDC_VU0_VI26 1064 +#define IDC_ABOUTCDVD 1064 +#define IDC_DEBUG_L27 1065 +#define IDC_VU0_VI27 1065 +#define IDC_LISTDEV9 1065 +#define IDC_DEBUG_L28 1066 +#define IDC_LISTPAD 1066 +#define IDC_LISTPAD1 1066 +#define IDC_VU0_VI28 1066 +#define IDC_DEBUG_L29 1067 +#define IDC_CONFIGPAD 1067 +#define IDC_CONFIGPAD1 1067 +#define IDC_VU0_VI29 1067 +#define IDC_DEBUG_R1 1068 +#define IDC_GPR12 1068 +#define IDC_TESTPAD 1068 +#define IDC_TESTPAD1 1068 +#define IDC_VU0_VI30 1068 +#define IDC_DEBUG_R2 1069 +#define IDC_GPR13 1069 +#define IDC_ABOUTPAD 1069 +#define IDC_ABOUTPAD1 1069 +#define IDC_VU0_VI31 1069 +#define IDC_DEBUG_R3 1070 +#define IDC_GPR14 1070 +#define IDC_LISTPAD2 1070 +#define IDC_VU0_ACC 1070 +#define IDC_DEBUG_R4 1071 +#define IDC_GPR15 1071 +#define IDC_CONFIGPAD2 1071 +#define IDC_VU1_VF00 1071 +#define IDC_DEBUG_R5 1072 +#define IDC_GPR16 1072 +#define IDC_TESTPAD2 1072 +#define IDC_VU1_VF01 1072 +#define IDC_DEBUG_R6 1073 +#define IDC_GPR17 1073 +#define IDC_ABOUTPAD2 1073 +#define IDC_VU1_VF02 1073 +#define IDC_DEBUG_R7 1074 +#define IDC_GPR18 1074 +#define IDC_VU1_VF03 1074 +#define IDC_CONFIGDEV9 1074 +#define IDC_DEBUG_R8 1075 +#define IDC_GPR19 1075 +#define IDC_VU1_VF04 1075 +#define IDC_TESTDEV9 1075 +#define IDC_DEBUG_R9 1076 +#define IDC_GPR20 1076 +#define IDC_VU1_VF05 1076 +#define IDC_ABOUTDEV9 1076 +#define IDC_DEBUG_R10 1077 +#define IDC_GPR21 1077 +#define IDC_VU1_VF06 1077 +#define IDC_LISTUSB 1077 +#define IDC_DEBUG_R11 1078 +#define IDC_GPR22 1078 +#define IDC_VU1_VF07 1078 +#define IDC_CONFIGUSB 1078 +#define IDC_DEBUG_R12 1079 +#define IDC_GPR23 1079 +#define IDC_VU1_VF08 1079 +#define IDC_TESTUSB 1079 +#define IDC_DEBUG_R13 1080 +#define IDC_GPR24 1080 +#define IDC_VU1_VF09 1080 +#define IDC_ABOUTUSB 1080 +#define IDC_DEBUG_R14 1081 +#define IDC_GPR25 1081 +#define IDC_VU1_VF10 1081 +#define IDC_LISTFW 1081 +#define IDC_DEBUG_R15 1082 +#define IDC_GPR26 1082 +#define IDC_VU1_VF11 1082 +#define IDC_CONFIGFW 1082 +#define IDC_DEBUG_R16 1083 +#define IDC_GPR27 1083 +#define IDC_VU1_VF12 1083 +#define IDC_TESTFW 1083 +#define IDC_DEBUG_R17 1084 +#define IDC_GPR28 1084 +#define IDC_VU1_VF13 1084 +#define IDC_ABOUTFW 1084 +#define IDC_DEBUG_R18 1085 +#define IDC_GPR29 1085 +#define IDC_VU1_VF14 1085 +#define IDC_DEBUG_R19 1086 +#define IDC_GPR30 1086 +#define IDC_VU1_VF15 1086 +#define IDC_DEBUG_R20 1087 +#define IDC_GPR31 1087 +#define IDC_VU1_VF16 1087 +#define IDC_DEBUG_R21 1088 +#define IDC_VU1_VF17 1088 +#define IDC_DEBUG_R22 1089 +#define IDC_GPR_PC 1089 +#define IDC_VU1_VF18 1089 +#define IDC_DEBUG_R23 1090 +#define IDC_VU1_VF19 1090 +#define IDC_DEBUG_R24 1091 +#define IDC_GPR_HI 1091 +#define IDC_VU1_VF20 1091 +#define IDC_DEBUG_R25 1092 +#define IDC_GPR_LO 1092 +#define IDC_VU1_VF21 1092 +#define IDC_CP00 1093 +#define IDC_DEBUG_R26 1093 +#define IDC_VU1_VF22 1093 +#define IDC_CP01 1094 +#define IDC_DEBUG_R27 1094 +#define IDC_VU1_VF23 1094 +#define IDC_CP02 1095 +#define IDC_DEBUG_R28 1095 +#define IDC_VU1_VF24 1095 +#define IDC_CP03 1096 +#define IDC_DEBUG_R29 1096 +#define IDC_VU1_VF25 1096 +#define IDC_CP04 1097 +#define IDC_DEBUG_DUMP 1097 +#define IDC_JUMP_PC 1097 +#define IDC_VU1_VF26 1097 +#define IDC_CP05 1098 +#define IDC_DEBUG_DUMPRAW 1098 +#define IDC_DUMP_END 1098 +#define IDC_VU1_VF27 1098 +#define IDC_DEBUG_LOGGING 1098 +#define IDC_DEBUG_MEMORY 1098 +#define IDC_CP06 1099 +#define IDC_DUMP_FNAME 1099 +#define IDC_DEBUG_BP_CLEAR 1099 +#define IDC_VU1_VF28 1099 +#define IDC_CP08 1100 +#define IDC_VU1_VF29 1100 +#define IDC_DUMP_ENDIOP 1100 +#define IDC_CP09 1101 +#define IDC_VU1_VF30 1101 +#define IDC_DUMP_FNAMEIOP 1101 +#define IDC_CP010 1102 +#define IDC_VU1_VF31 1102 +#define IDC_CP011 1103 +#define IDC_VU1_VI00 1103 +#define IDC_CP012 1104 +#define IDC_VU1_VI01 1104 +#define IDC_CP013 1105 +#define IDC_VU1_VI02 1105 +#define IDC_CP014 1106 +#define IDC_VU1_VI03 1106 +#define IDC_CP015 1107 +#define IDC_VU1_VI04 1107 +#define IDC_CP016 1108 +#define IDC_VU1_VI05 1108 +#define IDC_CP017 1109 +#define IDC_VU1_VI06 1109 +#define IDC_CP018 1110 +#define IDC_VU1_VI07 1110 +#define IDC_CP019 1111 +#define IDC_VU1_VI08 1111 +#define IDC_CP020 1112 +#define IDC_VU1_VI09 1112 +#define IDC_CP026 1113 +#define IDC_VU1_VI10 1113 +#define IDC_CP027 1114 +#define IDC_VU1_VI11 1114 +#define IDC_CP028 1115 +#define IDC_VU1_VI12 1115 +#define IDC_CP029 1116 +#define IDC_VU1_VI13 1116 +#define IDC_CP030 1117 +#define IDC_VU1_VI14 1117 +#define IDC_FP0 1118 +#define IDC_VU1_VI15 1118 +#define IDC_FP1 1119 +#define IDC_VU1_VI16 1119 +#define IDC_FP2 1120 +#define IDC_VU1_VI17 1120 +#define IDC_FP3 1121 +#define IDC_VU1_VI18 1121 +#define IDC_FP4 1122 +#define IDC_VU1_VI19 1122 +#define IDC_FP5 1123 +#define IDC_VU1_VI20 1123 +#define IDC_FP6 1124 +#define IDC_VU1_VI21 1124 +#define IDC_FP7 1125 +#define IDC_VU1_VI22 1125 +#define IDC_FP8 1126 +#define IDC_VU1_VI23 1126 +#define IDC_FP9 1127 +#define IDC_VU1_VI24 1127 +#define IDC_FP10 1128 +#define IDC_VU1_VI25 1128 +#define IDC_FP11 1129 +#define IDC_VU1_VI26 1129 +#define IDC_FP12 1130 +#define IDC_VU1_VI27 1130 +#define IDC_FP13 1131 +#define IDC_VU1_VI28 1131 +#define IDC_FP14 1132 +#define IDC_VU1_VI29 1132 +#define IDC_FP15 1133 +#define IDC_VU1_VI30 1133 +#define IDC_FP16 1134 +#define IDC_VU1_VI31 1134 +#define IDC_FP17 1135 +#define IDC_VU1_ACC 1135 +#define IDC_FP18 1136 +#define IDC_FP19 1137 +#define IDC_FP20 1138 +#define IDC_FP21 1139 +#define IDC_FP22 1140 +#define IDC_FP23 1141 +#define IDC_FP24 1142 +#define IDC_FP25 1143 +#define IDC_FP26 1144 +#define IDC_FP27 1145 +#define IDC_FP28 1146 +#define IDC_FP29 1147 +#define IDC_FP30 1148 +#define IDC_FP31 1149 +#define IDC_FCR0 1150 +#define IDC_FCR31 1151 +#define IDC_CMDLINE 1155 +#define IDC_PORT 1157 +#define IDC_COMMUNICATION 1158 +#define IDC_CLEAR 1160 +#define IDC_DEBUGBIOS 1161 +#define IDC_EEPC 1162 +#define IDC_IOPPC 1163 +#define IDC_PCSX_ABOUT_GREETS 1163 +#define IDC_PCSX_ABOUT_AUTHORS 1164 +#define IDC_EECYCLE 1164 +#define IDC_GRAPHICS 1165 +#define IDC_IOPCYCLE 1165 +#define IDC_SOUND 1166 +#define IDC_FIRSTCONTROLLER 1167 +#define IDC_SECONDCONTROLLER 1168 +#define IDC_CDVDROM 1169 +#define IDC_BIOS 1170 +#define IDC_MISCOPTIONS 1171 +#define IDC_DEV9 1171 +#define IDC_DUMP_START 1172 +#define IDC_TIP 1172 +#define IDC_USB 1172 +#define IDC_TEXT 1173 +#define IDC_DUMP_STARTIOP 1173 +#define IDC_CPUOP 1175 +#define IDC_DEBUGEE 1176 +#define IDC_DEBUGIOP 1177 +#define IDC_STOPAT 1178 +#define IDC_STOPAFTER 1179 +#define IDC_PATCH 1180 +#define IDC_REGCACHE 1181 +#define IDC_RECOPTIONS 1182 +#define IDC_PADHACK 1183 +#define IDC_VUREC 1184 +#define IDC_LOGS 1186 +#define IDDELREG 1187 +#define IDC_TAB_DEBUG 1188 +#define IDC_DUMPMEM_FNAME 1188 +#define IDC_DUMPMEM_END 1189 +#define IDC_DUMPMEM_START 1190 +#define IDC_DUMPRAW 1191 +#define IDC_DEBUG_DISASM_IOP 1193 +#define IDC_DEBUG_SCROLL_IOP 1194 +#define IDC_THPRIORITY 1195 +#define IDC_EXITPB 1196 +#define IDC_CPUOPTION 1196 +#define IDC_VENDORNAME 1197 +#define IDC_FAMILYNAME 1198 +#define IDC_CPUSPEEDNAME 1199 +#define IDC_FEATURESNAME 1200 +#define IDC_VENDORINPUT 1201 +#define IDC_FAMILYINPUT 1202 +#define IDC_CPUSPEEDINPUT 1203 +#define IDC_FEATURESINPUT 1204 +#define IDC_RADIOINTEPRETER 1205 +#define IDC_RADIORECOMPILER 1206 +#define IDC_RADIORECOMPILERVU 1207 +#define IDC_REGCACHING 1208 +#define IDC_INTERLACEHACK 1210 +#define IDC_SAFECOUNTERS 1211 +#define IDC_IOPCLK 1213 +#define IDC_ADVRESET 1214 +#define IDC_FASTIOPCLK 1215 +#define IDC_CHECK2 1217 +#define IDC_SPU2HACK 1218 +#define IDC_VSYNCRATE 1219 +#define IDC_IOPGPR0 1220 +#define IDC_IOPGPR1 1221 +#define IDC_IOPGPR2 1222 +#define IDC_IOPGPR16 1223 +#define IDC_IOPGPR17 1224 +#define IDC_IOPGPR18 1225 +#define IDC_IOPGPR19 1226 +#define IDC_IOPGPR20 1227 +#define IDC_IOPGPR21 1228 +#define IDC_IOPGPR22 1229 +#define IDC_IOPGPR23 1230 +#define IDC_IOPGPR24 1231 +#define IDC_IOPGPR25 1232 +#define IDC_IOPGPR26 1233 +#define IDC_IOPGPR27 1234 +#define IDC_IOPGPR28 1235 +#define IDC_IOPGPR29 1236 +#define IDC_IOPGPR30 1237 +#define IDC_IOPGPR31 1238 +#define IDC_IOPGPR_LO 1239 +#define IDC_IOPGPR_HI 1240 +#define IDC_IOPGPR_PC 1241 +#define IDC_IOPGPR15 1242 +#define IDC_IOPGPR14 1243 +#define IDC_IOPGPR13 1244 +#define IDC_IOPGPR12 1245 +#define IDC_IOPGPR11 1246 +#define IDC_IOPGPR10 1247 +#define IDC_IOPGPR9 1248 +#define IDC_IOPGPR8 1249 +#define IDC_IOPGPR7 1250 +#define IDC_IOPGPR6 1251 +#define IDC_IOPGPR5 1252 +#define IDC_IOPGPR4 1253 +#define IDC_BIOSDIR 1254 +#define IDC_IOPGPR3 1254 +#define IDC_PLUGINSDIR 1255 +#define IDC_EDIT2 1256 +#define IDC_BIAS 1256 +#define IDC_USER_NAME 1257 +#define IDC_CPU_MULTI 1258 +#define IDC_CPU_MULTI2 1259 +#define IDC_CPU_GSMULTI 1259 +#define IDC_PS2SILVER_RECT 1259 +#define IDC_CPU_MULTI3 1260 +#define IDC_CPU_FRAMELIMIT 1260 +#define IDC_CPU_FRAMELIMIT2 1261 +#define IDC_CPU_EEREC 1262 +#define IDC_CPU_VU1REC 1263 +#define IDC_CHECK4 1264 +#define IDC_CPU_VU0REC 1264 +#define IDC_CPU_FL_NORMAL 1265 +#define IDC_IDC_CPU_FL_LIMIT 1266 +#define IDC_CPU_FL_LIMIT 1266 +#define IDC_CPU_FL_SKIP 1267 +#define IDC_CPU_FL_SKIPVU 1268 +#define IDC_CPU_VUGROUP 1269 +#define IDC_MONTHCALENDAR1 1270 +#define IDC_GROUPS 1272 +#define IDC_PATCHES 1273 +#define IDC_LOG 1500 +#define IDC_CPULOG 1500 +#define IDC_MEMLOG 1501 +#define IDC_HWLOG 1502 +#define IDC_DMALOG 1503 +#define IDC_BIOSLOG 1504 +#define IDC_ELFLOG 1505 +#define IDC_FPULOG 1506 +#define IDC_MMILOG 1507 +#define IDC_VU0LOG 1508 +#define IDC_COP0LOG 1509 +#define IDC_VIFLOG 1510 +#define IDC_SPRLOG 1511 +#define IDC_GIFLOG 1512 +#define IDC_SIFLOG 1513 +#define IDC_IPULOG 1514 +#define IDC_VUMICROLOG 1515 +#define IDC_RPCSERVICES 1516 +#define IDC_IOPLOG 1520 +#define IDC_IOPMEMLOG 1521 +#define IDC_IOPHWLOG 1522 +#define IDC_IOPBIOSLOG 1523 +#define IDC_IOPDMALOG 1524 +#define IDC_IOPPADLOG 1525 +#define IDC_IOPGTELOG 1526 +#define IDC_IOPCDRLOG 1527 +#define IDC_IOPGPULOG 1527 +#define IDC_IOPCNTLOG 1529 +#define IDC_EECNTLOG 1530 +#define IDC_SYMLOG 1531 +#define IDC_STDOUTPUTLOG 1532 +#define IDC_SEARCH 1701 +#define IDC_VALUE 1702 +#define IDC_OLD 1703 +#define IDC_SET 1704 +#define IDC_EQ 1705 +#define IDC_GT 1706 +#define IDC_LT 1707 +#define IDC_GE 1708 +#define IDC_LE 1709 +#define IDC_NE 1710 +#define IDC_EE 1711 +#define IDC_IOP 1712 +#define IDC_RESET 1713 +#define IDC_ADD 1714 +#define IDC_LRESULTS 1715 +#define IDC_STATUS 1716 +#define IDC_UNSIGNED 1717 +#define IDC_8B 1718 +#define IDC_16B 1719 +#define IDC_32B 1720 +#define IDC_64B 1721 +#define IDC_RESULTS 1722 +#define IDC_NAME 1723 +#define IDC_ADDR 1725 +#define IDC_MATCHES 1726 +#define ID_FILEOPEN 40001 +#define ID_DEBUG_MEMORY_DUMP 40002 +#define ID_FILE_EXIT 40003 +#define ID_RUN_EXECUTE 40004 +#define ID_RUN_RESET 40005 +#define ID_HELP_ABOUT 40006 +#define ID_CONFIG_CONFIGURE 40007 +#define ID_CONFIG_CPU 40008 +#define ID_CONFIG_GRAPHICS 40009 +#define ID_CONFIG_CONTROLLERS 40010 +#define ID_DEBUG_LOGGING 40011 +#define ID_CONFIG_SOUND 40012 +#define ID_CONFIG_CDVDROM 40013 +#define ID_RUN_CMDLINE 40014 +#define ID_FILE_RUNCD 40015 +#define ID_DEBUG_ENTERDEBUGGER 40016 +#define ID_CONFIG_DEV9 40017 +#define ID_FILE_STATES_LOAD_SLOT1 40018 +#define ID_FILE_STATES_LOAD_SLOT2 40019 +#define ID_FILE_STATES_LOAD_SLOT3 40020 +#define ID_FILE_STATES_LOAD_SLOT4 40021 +#define ID_FILE_STATES_LOAD_SLOT5 40022 +#define ID_FILE_STATES_LOAD_OTHER 40023 +#define ID_FILE_STATES_SAVE_SLOT1 40024 +#define ID_FILE_STATES_SAVE_SLOT2 40025 +#define ID_FILE_STATES_SAVE_SLOT3 40026 +#define ID_FILE_STATES_SAVE_SLOT4 40027 +#define ID_FILE_STATES_SAVE_SLOT5 40028 +#define ID_FILE_STATES_SAVE_OTHER 40029 +#define ID_CONFIG_FW 40030 +#define ID_CONFIG_USB 40031 +#define ID_CONFIG_MEMCARDS 40032 +#define IDC_FORMAT1 40033 +#define IDC_FORMAT2 40034 +#define IDC_LIST1 40035 +#define IDC_LIST2 40036 +#define IDC_RELOAD1 40037 +#define IDC_RELOAD2 40038 +#define IDC_COPYTO2 40039 +#define IDC_COPYTO1 40040 +#define IDC_PASTE 40041 +#define IDC_DELETE1 40042 +#define IDC_DELETE2 40043 +#define ID_PATCHBROWSER 40044 +#define ID_NEWPATCH 40045 +#define IDC_NEWPATCH 40045 +#define IDC_PATCHTEXT 40046 +#define IDC_SAVEPATCH 40047 +#define IDC_REFRESHPATCHLIST 40048 +#define IDC_PATCHCRCLIST 40049 +#define IDC_PATCHNAMELIST 40050 +#define IDC_GAMENAMESEARCH 40051 +#define IDC_SEARCHPATCHTEXT 40052 +#define ID_PROCESSLOW 40053 +#define ID_PROCESSNORMAL 40054 +#define ID_PROCESSHIGH 40055 +#define ID_CONSOLE 40056 +#define ID_PATCHES 40057 +#define ID_CONFIG_ADVANCED 40058 +#define ID_INTERLACEHACK 40059 +#define ID_SAFECNTS 40060 +#define ID_SPU2HACK 40061 +#define ID_VSYNCRATE 40062 +#define ID_HELP_HELP 40063 +#define ID_CHEAT_FINDER_SHOW 40100 +#define ID_CHEAT_BROWSER_SHOW 40101 +#define ID_LANGS 50000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 134 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1274 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/branches/pcsx2_0.9.2/x86/Makefile.am b/branches/pcsx2_0.9.2/x86/Makefile.am new file mode 100644 index 0000000..98288fe --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = -I../ +noinst_LIBRARIES = libx86recomp.a + +libx86recomp_a_SOURCES = \ +iCore.cpp iFPU.c iR3000A.cpp iR5900.h iVU1micro.c iVUops.h \ +iCore.h iFPU.h iR3000A.h ir5900tables.c iVU1micro.h iVUzerorec.cpp \ +iCP0.c iMMI.c iR3000Atables.cpp iVU0micro.c iVUmicro.c iVUzerorec.h \ +iCP0.h iMMI.h iR5900.c iVU0micro.h iVUmicro.h recCOP2.c + + + +if X86_64 +tempdir = ix86-64 +else +tempdir = ix86-32 +endif + +SUBDIRS = ix86 $(tempdir) \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iCP0.c b/branches/pcsx2_0.9.2/x86/iCP0.c new file mode 100644 index 0000000..771e31d --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iCP0.c @@ -0,0 +1,370 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iCP0.h" + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +#ifndef CP0_RECOMPILE + +REC_SYS(MFC0); +REC_SYS(MTC0); +REC_SYS(BC0F); +REC_SYS(BC0T); +REC_SYS(BC0FL); +REC_SYS(BC0TL); +REC_SYS(TLBR); +REC_SYS(TLBWI); +REC_SYS(TLBWR); +REC_SYS(TLBP); +REC_SYS(ERET); +REC_SYS(DI); +REC_SYS(EI); + +#else + +//////////////////////////////////////////////////// +//REC_SYS(MTC0); +//////////////////////////////////////////////////// +REC_SYS(BC0F); +//////////////////////////////////////////////////// +REC_SYS(BC0T); +//////////////////////////////////////////////////// +REC_SYS(BC0FL); +//////////////////////////////////////////////////// +REC_SYS(BC0TL); +//////////////////////////////////////////////////// +REC_SYS(TLBR); +//////////////////////////////////////////////////// +REC_SYS(TLBWI); +//////////////////////////////////////////////////// +REC_SYS(TLBWR); +//////////////////////////////////////////////////// +REC_SYS(TLBP); +//////////////////////////////////////////////////// +REC_SYS(ERET); +//////////////////////////////////////////////////// +REC_SYS(DI); +//////////////////////////////////////////////////// +REC_SYS(EI); + +//////////////////////////////////////////////////// +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; + +void recMFC0( void ) +{ + int mmreg; + + if ( ! _Rt_ ) return; + + if( _Rd_ == 9 ) { + MOV32MtoR( EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ] ); + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + ADD32RtoR(EAX, ECX); + SUB32MtoR(EAX, (u32)&s_iLastCOP0Cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32RtoM((u32)&cpuRegs.CP0.r[ _Rd_ ], EAX); + + _deleteEEreg(_Rt_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else EEINST_RESETHASLIVE1(_Rt_); + return; + } + if( _Rd_ == 25 ) { + + _deleteEEreg(_Rt_, 0); + switch(_Imm_ & 0x3F){ + case 0: + MOV32MtoR(EAX, (u32)&cpuRegs.PERF.n.pccr); break; + case 1: + // check if needs to be incremented + MOV32MtoR(ECX, (u32)&cpuRegs.PERF.n.pccr); + MOV32MtoR(EAX, (u32)&cpuRegs.PERF.n.pcr0); + AND32ItoR(ECX, 0x800003E0); + + CMP32ItoR(ECX, 0x80000020); + j8Ptr[0] = JNE8(0); + + MOV32MtoR(EDX, (u32)&cpuRegs.cycle); + SUB32MtoR(EAX, (u32)&s_iLastPERFCycle[0]); + ADD32RtoR(EAX, EDX); + MOV32RtoM((u32)&s_iLastPERFCycle[0], EDX); + MOV32RtoM((u32)&cpuRegs.PERF.n.pcr0, EAX); + + x86SetJ8(j8Ptr[0]); + break; + case 3: + // check if needs to be incremented + MOV32MtoR(ECX, (u32)&cpuRegs.PERF.n.pccr); + MOV32MtoR(EAX, (u32)&cpuRegs.PERF.n.pcr1); + AND32ItoR(ECX, 0x800F8000); + + CMP32ItoR(ECX, 0x80008000); + j8Ptr[0] = JNE8(0); + + MOV32MtoR(EDX, (u32)&cpuRegs.cycle); + SUB32MtoR(EAX, (u32)&s_iLastPERFCycle[1]); + ADD32RtoR(EAX, EDX); + MOV32RtoM((u32)&s_iLastPERFCycle[1], EDX); + MOV32RtoM((u32)&cpuRegs.PERF.n.pcr1, EAX); + + x86SetJ8(j8Ptr[0]); + + break; + } + + MOV32RtoM( (u32)&cpuRegs.CP0.r[ _Rt_ ], EAX ); + +#ifdef PCSX2_DEVBUILD + SysPrintf("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); +#endif + return; + } + + _eeOnWriteReg(_Rt_, 1); + + if( EEINST_ISLIVE1(_Rt_) ) { + _deleteEEreg(_Rt_, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + + if( (mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + SetMMXstate(); + } + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + + if( EEINST_ISLIVE2(_Rt_) ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + } + else { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + } + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.r[ _Rd_ ]); + if(_Rd_ == 12) AND32ItoR(EAX, 0xf0c79c1f); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + } +} + +void updatePCCR() +{ + // read the old pccr and update pcr0/1 + MOV32MtoR(EAX, (u32)&cpuRegs.PERF.n.pccr); + MOV32RtoR(EDX, EAX); + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + + AND32ItoR(EAX, 0x800003E0); + CMP32ItoR(EAX, 0x80000020); + j8Ptr[0] = JNE8(0); + MOV32MtoR(EAX, (u32)&s_iLastPERFCycle[0]); + ADD32RtoM((u32)&cpuRegs.PERF.n.pcr0, ECX); + SUB32RtoM((u32)&cpuRegs.PERF.n.pcr0, EAX); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EDX, 0x800F8000); + CMP32ItoR(EDX, 0x80008000); + j8Ptr[0] = JNE8(0); + MOV32MtoR(EAX, (u32)&s_iLastPERFCycle[1]); + ADD32RtoM((u32)&cpuRegs.PERF.n.pcr1, ECX); + SUB32RtoM((u32)&cpuRegs.PERF.n.pcr1, EAX); + x86SetJ8(j8Ptr[0]); +} + +void recMTC0() +{ + if( GPR_IS_CONST1(_Rt_) ) { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + MOV32ItoM((u32)&cpuRegs.CP0.r[9], g_cpuConstRegs[_Rt_].UL[0]); + break; + case 25: + SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); + switch(_Imm_ & 0x3F){ + case 0: + + updatePCCR(); + MOV32ItoM((u32)&cpuRegs.PERF.n.pccr, g_cpuConstRegs[_Rt_].UL[0]); + + // update the cycles + MOV32RtoM((u32)&s_iLastPERFCycle[0], ECX); + MOV32RtoM((u32)&s_iLastPERFCycle[1], ECX); + break; + case 1: + MOV32MtoR(EAX, (u32)&cpuRegs.cycle); + MOV32ItoM((u32)&cpuRegs.PERF.n.pcr0, g_cpuConstRegs[_Rt_].UL[0]); + MOV32RtoM((u32)&s_iLastPERFCycle[0], EAX); + break; + case 3: + MOV32MtoR(EAX, (u32)&cpuRegs.cycle); + MOV32ItoM((u32)&cpuRegs.PERF.n.pcr1, g_cpuConstRegs[_Rt_].UL[0]); + MOV32RtoM((u32)&s_iLastPERFCycle[1], EAX); + break; + } + break; + default: + MOV32ItoM((u32)&cpuRegs.CP0.r[_Rd_], g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + SUB32ItoR(ESP, 4); + _eeMoveGPRtoRm(ESP, _Rt_); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + break; + case 9: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[9], _Rt_); + MOV32RtoM((u32)&s_iLastCOP0Cycle, ECX); + break; + case 25: + SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); + switch(_Imm_ & 0x3F){ + case 0: + updatePCCR(); + _eeMoveGPRtoM((u32)&cpuRegs.PERF.n.pccr, _Rt_); + + // update the cycles + MOV32RtoM((u32)&s_iLastPERFCycle[0], ECX); + MOV32RtoM((u32)&s_iLastPERFCycle[1], ECX); + break; + case 1: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + _eeMoveGPRtoM((u32)&cpuRegs.PERF.n.pcr0, _Rt_); + MOV32RtoM((u32)&s_iLastPERFCycle[0], ECX); + break; + case 3: + MOV32MtoR(ECX, (u32)&cpuRegs.cycle); + _eeMoveGPRtoM((u32)&cpuRegs.PERF.n.pcr1, _Rt_); + MOV32RtoM((u32)&s_iLastPERFCycle[1], ECX); + break; + } + break; + default: + _eeMoveGPRtoM((u32)&cpuRegs.CP0.r[_Rd_], _Rt_); + break; + } + } +} + +/*void rec(COP0) { +} + +void rec(BC0F) { +} + +void rec(BC0T) { +} + +void rec(BC0FL) { +} + +void rec(BC0TL) { +} + +void rec(TLBR) { +} + +void rec(TLBWI) { +} + +void rec(TLBWR) { +} + +void rec(TLBP) { +} + +void rec(ERET) { +} +*/ +/* +//////////////////////////////////////////////////// +void recDI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + AND32ItoR(EAX, ~0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} + +//////////////////////////////////////////////////// +void recEI( void ) +{ + MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status); + OR32ItoR(EAX, 0x10000); + PUSH32R(EAX); + CALLFunc((u32)WriteCP0Status); + ADD32ItoR(ESP, 4); + +} +*/ + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iCP0.h b/branches/pcsx2_0.9.2/x86/iCP0.h new file mode 100644 index 0000000..52e99b7 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iCP0.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ICP0_H__ +#define __ICP0_H__ + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +void recMFC0( void ); +void recMTC0( void ); +void recCOP0( void ); +void recBC0F( void ); +void recBC0T( void ); +void recBC0FL( void ); +void recBC0TL( void ); +void recTLBR( void ); +void recTLBWI( void ); +void recTLBWR( void ); +void recTLBP( void ); +void recERET( void ); +void recDI( void ); +void recEI( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iCore.cpp b/branches/pcsx2_0.9.2/x86/iCore.cpp new file mode 100644 index 0000000..dc17e43 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iCore.cpp @@ -0,0 +1,2413 @@ +#include +#include +#include +#include + +extern "C" { + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 g_x86AllocCounter = 0; +u16 g_xmmAllocCounter = 0; +u16 g_mmxAllocCounter = 0; + +u16 x86FpuState, iCWstate; +EEINST* g_pCurInstInfo = NULL; + +u32 g_cpuRegHasLive1 = 0, g_cpuPrevRegHasLive1 = 0; // set if upper 32 bits are live +u32 g_cpuRegHasSignExt = 0, g_cpuPrevRegHasSignExt = 0; // set if upper 32 bits are the sign extension of the lower integer + +// used to make sure regs don't get changed while in recompiler +// use FreezeMMXRegs, FreezeXMMRegs +u8 g_globalMMXSaved = 0, g_globalXMMSaved = 0; +u32 g_recWriteback = 0; + +#ifdef _DEBUG +char g_globalMMXLocked = 0, g_globalXMMLocked = 0; +#endif + +_xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +PCSX2_ALIGNED16(u64 g_globalMMXData[8]); +PCSX2_ALIGNED16(u64 g_globalXMMData[2*XMMREGS]); + +// X86 caching +_x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; +static int s_x86checknext = 0; + +} // end extern "C" + +#include + +void _initX86regs() { + memset(x86regs, 0, sizeof(x86regs)); + g_x86AllocCounter = 0; + s_x86checknext = 0; +} + +__forceinline u32 _x86GetAddr(int type, int reg) +{ + switch(type&~X86TYPE_VU1) { + case X86TYPE_GPR: return (u32)&cpuRegs.GPR.r[reg]; + case X86TYPE_VI: { + //assert( reg < 16 || reg == REG_R ); + return (type&X86TYPE_VU1)?(u32)&VU1.VI[reg]:(u32)&VU0.VI[reg]; + } + case X86TYPE_MEMOFFSET: return 0; + case X86TYPE_VIMEMOFFSET: return 0; + case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.q:(u32)&VU0.q; + case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.p:(u32)&VU0.p; + case X86TYPE_PSX: return (u32)&psxRegs.GPR.r[reg]; + case X86TYPE_PCWRITEBACK: + return (u32)&g_recWriteback; + case X86TYPE_VUJUMP: + return (u32)&g_recWriteback; + default: assert(0); + } + + return 0; +} + +int _getFreeX86reg(int mode) +{ + int i, tempi; + u32 bestcount = 0x10000; + + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + + for (i=0; i= maxreg ) continue; + if( (mode&MODE_NOFRAME) && reg==EBP ) continue; + + if (x86regs[reg].inuse == 0) { + s_x86checknext = (reg+1)%X86REGS; + return reg; + } + } + + tempi = -1; + for (i=1; i= 0 && reg < 32 ); + +// if( X86_ISVI(type) ) +// assert( reg < 16 || reg == REG_R ); + + // don't alloc EAX and ESP,EBP if MODE_NOFRAME + int oldmode = mode; + int noframe = mode&MODE_NOFRAME; + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + mode &= ~(MODE_NOFRAME|MODE_8BITREG); + int readfromreg = -1; + + if( type != X86TYPE_TEMP ) { + + if( maxreg < X86REGS ) { + // make sure reg isn't in the higher regs + + for(i = maxreg; i < X86REGS; ++i) { + if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) continue; + + if( mode & MODE_READ ) { + readfromreg = i; + x86regs[i].inuse = 0; + break; + } + else if( mode & MODE_WRITE ) { + x86regs[i].inuse = 0; + break; + } + } + } + + for (i=1; i= maxreg) ) { + if( x86regs[i].mode & MODE_READ ) + readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + + if( x86reg >= 0 ) { + // requested specific reg, so return that instead + if( i != x86reg ) { + if( x86regs[i].mode & MODE_READ ) readfromreg = i; + //if( x86regs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + } + + if( type != X86TYPE_TEMP && !(x86regs[i].mode & MODE_READ) && (mode&MODE_READ)) { + + if( type == X86TYPE_GPR ) _flushConstReg(reg); + + if( X86_ISVI(type) && reg < 16 ) MOVZX32M16toR(i, _x86GetAddr(type, reg)); + else MOV32MtoR(i, _x86GetAddr(type, reg)); + + x86regs[i].mode |= MODE_READ; + } + + x86regs[i].needed = 1; + x86regs[i].mode|= mode; + return i; + } + } + + if (x86reg == -1) { + x86reg = _getFreeX86reg(oldmode); + } + else { + _freeX86reg(x86reg); + } + + x86regs[x86reg].type = type; + x86regs[x86reg].reg = reg; + x86regs[x86reg].mode = mode; + x86regs[x86reg].needed = 1; + x86regs[x86reg].inuse = 1; + + if( mode & MODE_READ ) { + if( readfromreg >= 0 ) MOV32RtoR(x86reg, readfromreg); + else { + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) { + XOR32RtoR(x86reg, x86reg); + } + else { + _flushConstReg(reg); + _deleteMMXreg(MMX_GPR+reg, 1); + _deleteGPRtoXMMreg(reg, 1); + + _eeMoveGPRtoR(x86reg, reg); + + _deleteMMXreg(MMX_GPR+reg, 0); + _deleteGPRtoXMMreg(reg, 0); + } + } + else { + if( X86_ISVI(type) && reg < 16 ) { + if( reg == 0 ) XOR32RtoR(x86reg, x86reg); + else MOVZX32M16toR(x86reg, _x86GetAddr(type, reg)); + } + else MOV32MtoR(x86reg, _x86GetAddr(type, reg)); + } + } +} + + return x86reg; +} + +int _checkX86reg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 && x86reg < X86REGS ); + + if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { + x86regs[x86reg].mode &= ~MODE_WRITE; + + if( X86_ISVI(x86regs[x86reg].type) && x86regs[x86reg].reg < 16 ) { + MOV16RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + else + MOV32RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + + x86regs[x86reg].inuse = 0; +} + +void _freeX86regs() { + int i; + + for (i=0; i= 0 ) return -1; + + if( poffset ) *poffset = x86regs[i].extra; + return i; +} + +// MMX Caching +_mmxregs mmxregs[8], s_saveMMXregs[8]; +static int s_mmxchecknext = 0; + +void _initMMXregs() +{ + memset(mmxregs, 0, sizeof(mmxregs)); + g_mmxAllocCounter = 0; + s_mmxchecknext = 0; +} + +__forceinline void* _MMXGetAddr(int reg) +{ + assert( reg != MMX_TEMP ); + + if( reg == MMX_LO ) return &cpuRegs.LO; + if( reg == MMX_HI ) return &cpuRegs.HI; + if( reg == MMX_FPUACC ) return &fpuRegs.ACC; + + if( reg >= MMX_GPR && reg < MMX_GPR+32 ) return &cpuRegs.GPR.r[reg&31]; + if( reg >= MMX_FPU && reg < MMX_FPU+32 ) return &fpuRegs.fpr[reg&31]; + if( reg >= MMX_COP0 && reg < MMX_COP0+32 ) return &cpuRegs.CP0.r[reg&31]; + + assert( 0 ); + return NULL; +} + +int _getFreeMMXreg() +{ + int i, tempi; + u32 bestcount = 0x10000; + + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) { + _freeMMXreg(i); + return i; + } + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + _freeMMXreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) { + _freeMMXreg(i); + return i; + } + } + } + + tempi = -1; + for (i=0; i= 0 ) { + if (cpucaps.hasStreamingSIMD2Extensions) { + SSE_MOVHPS_XMM_to_M64((u32)_MMXGetAddr(reg)+8, xmmreg); + if( mode & MODE_READ ) + SSE2_MOVDQ2Q_XMM_to_MM(mmxreg, xmmreg); + + if( xmmregs[xmmreg].mode & MODE_WRITE ) + mmxregs[mmxreg].mode |= MODE_WRITE; + + // don't flush + xmmregs[xmmreg].inuse = 0; + } + else { + _freeXMMreg(xmmreg); + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + + } + } + else { + if( MMX_ISGPR(reg) ) { + if(mode&(MODE_READHALF|MODE_READ)) _flushConstReg(reg-MMX_GPR); + } + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + } + } + + return mmxreg; +} + +int _checkMMXreg(int reg, int mode) +{ + int i; + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !EEINST_ISLIVEMMX(mmxregs[i].reg-MMX_GPR) ) { + return 1; + } + } + } + + // check for dead regs + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + return 1; + } + } + } + + return 0; +} + +void _freeMMXreg(int mmxreg) +{ + assert( mmxreg < MMXREGS ); + if (!mmxregs[mmxreg].inuse) return; + + if (mmxregs[mmxreg].mode & MODE_WRITE ) { + + if( mmxregs[mmxreg].reg >= MMX_GPR && mmxregs[mmxreg].reg < MMX_GPR+32 ) + assert( !(g_cpuHasConstReg & (1<<(mmxregs[mmxreg].reg-MMX_GPR))) ); + + assert( mmxregs[mmxreg].reg != MMX_GPR ); + + if( MMX_IS32BITS(mmxregs[mmxreg].reg) ) + MOVDMMXtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + else + MOVQRtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + + SetMMXstate(); + } + + mmxregs[mmxreg].mode &= ~MODE_WRITE; + mmxregs[mmxreg].inuse = 0; +} + +void _moveMMXreg(int mmxreg) +{ + int i; + if( !mmxregs[mmxreg].inuse ) return; + + for (i=0; iVF[x].UL[0] +#define VU_ACCx_ADDR (u32)&VU->ACC.UL[0] + +static int s_xmmchecknext = 0; + +void _initXMMregs() { + memset(xmmregs, 0, sizeof(xmmregs)); + g_xmmAllocCounter = 0; + s_xmmchecknext = 0; +} + +__forceinline void* _XMMGetAddr(int type, int reg, VURegs *VU) +{ + if (type == XMMTYPE_VFREG ) return (void*)VU_VFx_ADDR(reg); + else if (type == XMMTYPE_ACC ) return (void*)VU_ACCx_ADDR; + else if (type == XMMTYPE_GPRREG) { + if( reg < 32 ) + assert( !(g_cpuHasConstReg & (1<regs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + _freeXMMreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; iregs[xmmregs[i].reg] & EEINST_XMM) ) { + _freeXMMreg(i); + return i; + } + } + } + + tempi = -1; + bestcount = 0xffff; + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + xmmregs[i].needed = 1; + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ) ) { + SSE_MOVAPS_M128_to_XMM(i, VU_VFx_ADDR(vfreg)); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_VFREG; + xmmregs[xmmreg].reg = vfreg; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_VFx_ADDR(xmmregs[xmmreg].reg)); + } + + return xmmreg; +} + +int _checkXMMreg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ)) { + SSE_MOVAPS_M128_to_XMM(i, VU_ACCx_ADDR); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].needed = 1; + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_ACC; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + xmmregs[xmmreg].reg = 0; + + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_ACCx_ADDR); + } + + return xmmreg; +} + +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode) { + int i; + + for (i=0; i= 0 ) { + // transfer + if (cpucaps.hasStreamingSIMD2Extensions ) { + + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(xmmreg, mmxreg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(xmmreg, xmmreg); + SSE2_PUNPCKHQDQ_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + + if( mmxregs[mmxreg].mode & MODE_WRITE ) { + + // instead of setting to write, just flush to mem + if( !(mode & MODE_WRITE) ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], mmxreg); + } + //xmmregs[xmmreg].mode |= MODE_WRITE; + } + + // don't flush + mmxregs[mmxreg].inuse = 0; + } + else { + _freeMMXreg(mmxreg); + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + else { + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + } + else { + _deleteMMXreg(MMX_GPR+gprreg, 0); + } + + return xmmreg; +} + +int _allocFPACCtoXMMreg(int xmmreg, int mode) +{ + int i; + if( !cpucaps.hasStreamingSIMDExtensions ) return -1; + + for (i=0; iregs[xmmregs[i].reg]&EEINST_USED) ) { + return 1; + } + } + } + return 0; +} + +void _moveXMMreg(int xmmreg) +{ + int i; + if( !xmmregs[xmmreg].inuse ) return; + + for (i=0; i= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) { + SSE2_MOVD_XMM_to_R(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) { + MOVD32MMXtoR(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + } + } +} + +void _eeMoveGPRtoM(u32 to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_M32(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVDMMXtoM(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoM(to, EAX ); + } + } +} + +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_Rm(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVD32MMXtoRm(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoRm(to, EAX ); + } + } +} + +// PSX +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoR( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(to, (int)&psxRegs.GPR.r[ fromgpr ] ); + } +} + +void _psxMoveGPRtoM(u32 to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_psxConstRegs[fromgpr] ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoM(to, EAX ); + } +} + +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( PSX_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 ); + else { + // check x86 + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ fromgpr ] ); + MOV32RtoRm(to, EAX ); + } +} + +void _recPushReg(int mmreg) +{ + if( IS_XMMREG(mmreg) ) { + SUB32ItoR(ESP, 4); + SSEX_MOVD_XMM_to_Rm(ESP, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + SUB32ItoR(ESP, 4); + MOVD32MMXtoRm(ESP, mmreg&0xf); + } + else if( IS_CONSTREG(mmreg) ) { + PUSH32I(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + PUSH32I(g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else PUSH32R(mmreg); +} + +void _signExtendSFtoM(u32 mem) +{ + LAHF(); + SAR16ItoR(EAX, 15); + CWDE(); + MOV32RtoM(mem, EAX ); +} + +int _signExtendMtoMMX(x86MMXRegType to, u32 mem) +{ + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, mem); + MOVQRtoR(to, t0reg); + PSRADItoR(t0reg, 31); + PUNPCKLDQRtoR(to, t0reg); + _freeMMXreg(t0reg); + return to; +} + +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg) +{ + assert( to >= 0 && from >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + EEINST_RESETHASLIVE1(gprreg); + if( to != from ) MOVQRtoR(to, from); + return to; + } + + if( to == from ) return _signExtendGPRtoMMX(to, gprreg, 0); + if( !(g_pCurInstInfo->regs[gprfromreg]&EEINST_LASTUSE) ) { + if( EEINST_ISLIVEMMX(gprfromreg) ) { + MOVQRtoR(to, from); + return _signExtendGPRtoMMX(to, gprreg, 0); + } + } + + // from is free for use + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + + if( EEINST_ISLIVEMMX(gprfromreg) ) { + _freeMMXreg(from); + } + + MOVQRtoR(to, from); + PSRADItoR(from, 31); + PUNPCKLDQRtoR(to, from); + return to; + } + else { + MOVQRtoR(to, from); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], from); + PSRADItoR(from, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], from); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift) +{ + assert( to >= 0 && shift >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + if( shift > 0 ) PSRADItoR(to, shift); + EEINST_RESETHASLIVE1(gprreg); + return to; + } + + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, to); + PSRADItoR(to, 31); + if( shift > 0 ) PSRADItoR(t0reg, shift); + PUNPCKLDQRtoR(t0reg, to); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[to]; + mmxregs[to].inuse = 0; + return t0reg; + } + else { + // will be used in the future as mmx + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + + // read again + MOVQMtoR(to, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + mmxregs[to].mode &= ~MODE_WRITE; + return to; + } + } + else { + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +PCSX2_ALIGNED16(u32 s_zeros[4]) = {0}; +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy) +{ + int t0reg; +// if( g_xmmtypes[from] == XMMT_FPS && (!candestroy || _hasFreeXMMreg()) ) { +// // special floating point implementation +// // NOTE: doesn't sign extend 0x80000000 +// xmmregs[from].needed = 1; +// t0reg = _allocTempXMMreg(XMMT_FPS, -1); +// SSE_XORPS_XMM_to_XMM(t0reg, t0reg); +// SSE_MOVSS_XMM_to_M32(to, from); +// SSE_CMPNLESS_XMM_to_XMM(t0reg, from); +// SSE_MOVSS_XMM_to_M32(to+4, t0reg); +// _freeXMMreg(t0reg); +// return 0; +// } +// else { + g_xmmtypes[from] = XMMT_INT; + if( candestroy ) { + if( g_xmmtypes[from] == XMMT_FPS || !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVSS_XMM_to_M32(to, from); + else SSE2_MOVD_XMM_to_M32(to, from); + +// if( g_xmmtypes[from] == XMMT_FPS ) { +// SSE_CMPLTSS_M32_to_XMM(from, (u32)&s_zeros[0]); +// SSE_MOVSS_XMM_to_M32(to+4, from); +// return 1; +// } +// else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to+4, from); + return 1; + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SAR32ItoM(to+4, 31); + return 0; + } +// } + } + else { + // can't destroy and type is int + assert( g_xmmtypes[from] == XMMT_INT ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _hasFreeXMMreg() ) { + xmmregs[from].needed = 1; + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, from); + SSE2_PSRAD_I8_to_XMM(from, 31); + SSE2_MOVD_XMM_to_M32(to, t0reg); + SSE2_MOVD_XMM_to_M32(to+4, from); + + // swap xmm regs.. don't ask + xmmregs[t0reg] = xmmregs[from]; + xmmregs[from].inuse = 0; + } + else { + SSE2_MOVD_XMM_to_M32(to+4, from); + SSE2_MOVD_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + } + else { + SSE_MOVSS_XMM_to_M32(to+4, from); + SSE_MOVSS_XMM_to_M32(to, from); + SAR32ItoM(to+4, 31); + } + + return 0; + } + //} + + assert(0); +} + +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode) +{ + if( pinst->regs[gprreg] & EEINST_XMM ) return _allocGPRtoXMMreg(-1, gprreg, mode); + + return _checkXMMreg(XMMTYPE_GPRREG, gprreg, mode); +} + +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode) +{ + if( pinst->fpuregs[fpureg] & EEINST_XMM ) return _allocFPtoXMMreg(-1, fpureg, mode); + + return _checkXMMreg(XMMTYPE_FPREG, fpureg, mode); +} + +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode) +{ + if( pinst->regs[reg] & EEINST_MMX ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + + return _checkMMXreg(MMX_GPR+reg, mode); +} + +void _recClearInst(EEINST* pinst) +{ + memset(&pinst->regs[0], EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2, sizeof(pinst->regs)); + memset(&pinst->fpuregs[0], EEINST_LIVE0, sizeof(pinst->fpuregs)); + memset(&pinst->info, 0, sizeof(EEINST)-sizeof(pinst->regs)-sizeof(pinst->fpuregs)); +} + +// returns nonzero value if reg has been written between [startpc, endpc-4] +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == xmmtype && pinst->readReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +void _recFillRegister(EEINST* pinst, int type, int reg, int write) +{ + int i = 0; + if( write ) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == XMMTYPE_TEMP ) { + pinst->writeType[i] = type; + pinst->writeReg[i] = reg; + return; + } + } + assert(0); + } + else { + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == XMMTYPE_TEMP ) { + pinst->readType[i] = type; + pinst->readReg[i] = reg; + return; + } + } + assert(0); + } +} + +// Writebacks // +void _recClearWritebacks() +{ +} + +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent) +{ +} + +EEINSTWRITEBACK* _recCheckWriteBack(int cycle) +{ + return NULL; +} + +void _recMove128MtoM(u32 to, u32 from) +{ + MOV32MtoR(EAX, from); + MOV32MtoR(EDX, from+4); + MOV32RtoM(to, EAX); + MOV32RtoM(to+4, EDX); + MOV32MtoR(EAX, from+8); + MOV32MtoR(EDX, from+12); + MOV32RtoM(to+8, EAX); + MOV32RtoM(to+12, EDX); +} + +void _recMove128RmOffsettoM(u32 to, u32 offset) +{ + MOV32RmtoROffset(EAX, ECX, offset); + MOV32RmtoROffset(EDX, ECX, offset+4); + MOV32RtoM(to, EAX); + MOV32RtoM(to+4, EDX); + MOV32RmtoROffset(EAX, ECX, offset+8); + MOV32RmtoROffset(EDX, ECX, offset+12); + MOV32RtoM(to+8, EAX); + MOV32RtoM(to+12, EDX); +} + +void _recMove128MtoRmOffset(u32 offset, u32 from) +{ + MOV32MtoR(EAX, from); + MOV32MtoR(EDX, from+4); + MOV32RtoRmOffset(ECX, EAX, offset); + MOV32RtoRmOffset(ECX, EDX, offset+4); + MOV32MtoR(EAX, from+8); + MOV32MtoR(EDX, from+12); + MOV32RtoRmOffset(ECX, EAX, offset+8); + MOV32RtoRmOffset(ECX, EDX, offset+12); +} + +static PCSX2_ALIGNED16(u32 s_ones[2]) = {0xffffffff, 0xffffffff}; + +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op) +{ + switch(op) { + case 0: PANDRtoR(to, from); break; + case 1: PORRtoR(to, from); break; + case 2: PXORRtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op) +{ + switch(op) { + case 0: PANDMtoR(to, from); break; + case 1: PORMtoR(to, from); break; + case 2: PXORMtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND32RtoM(to, from); break; + case 1: OR32RtoM(to, from); break; + case 2: XOR32RtoM(to, from); break; + case 3: OR32RtoM(to, from); break; + } +} + +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32MtoR(to, from); break; + case 1: OR32MtoR(to, from); break; + case 2: XOR32MtoR(to, from); break; + case 3: OR32MtoR(to, from); break; + } +} + +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoR(to, from); break; + case 1: OR32ItoR(to, from); break; + case 2: XOR32ItoR(to, from); break; + case 3: OR32ItoR(to, from); break; + } +} + +void LogicalOp32ItoM(u32 to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoM(to, from); break; + case 1: OR32ItoM(to, from); break; + case 2: XOR32ItoM(to, from); break; + case 3: OR32ItoM(to, from); break; + } +} + +using namespace std; + +struct BASEBLOCKS +{ + // 0 - ee, 1 - iop + inline void Add(BASEBLOCKEX*); + inline void Remove(BASEBLOCKEX*); + inline int Get(u32 startpc); + inline void Reset(); + + inline BASEBLOCKEX** GetAll(int* pnum); + + vector blocks; +}; + +void BASEBLOCKS::Add(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + + switch(blocks.size()) { + case 0: + blocks.push_back(pex); + return; + case 1: + assert( blocks.front()->startpc != pex->startpc ); + + if( blocks.front()->startpc < pex->startpc ) { + blocks.push_back(pex); + } + else blocks.insert(blocks.begin(), pex); + + return; + + default: + { + int imin = 0, imax = blocks.size(), imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > pex->startpc ) imax = imid; + else imin = imid+1; + } + + assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc ); + if( imin > 0 ) assert( blocks[imin-1]->startpc < pex->startpc ); + blocks.insert(blocks.begin()+imin, pex); + + return; + } + } +} + +int BASEBLOCKS::Get(u32 startpc) +{ + switch(blocks.size()) { + case 1: + return 0; + case 2: + return blocks.front()->startpc < startpc; + + default: + { + int imin = 0, imax = blocks.size()-1, imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > startpc ) imax = imid; + else if( blocks[imid]->startpc == startpc ) return imid; + else imin = imid+1; + } + + assert( blocks[imin]->startpc == startpc ); + return imin; + } + } +} + +void BASEBLOCKS::Remove(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + int i = Get(pex->startpc); + assert( blocks[i] == pex ); + blocks.erase(blocks.begin()+i); +} + +void BASEBLOCKS::Reset() +{ + blocks.resize(0); + blocks.reserve(512); +} + +BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum) +{ + assert( pnum != NULL ); + *pnum = blocks.size(); + return &blocks[0]; +} + +static BASEBLOCKS s_vecBaseBlocksEx[2]; + +void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Add(pex); +} + +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu) +{ + return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)]; +} + +void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Remove(pex); +} + +void ResetBaseBlockEx(int cpu) +{ + s_vecBaseBlocksEx[cpu].Reset(); +} + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu) +{ + return s_vecBaseBlocksEx[cpu].GetAll(pnum); +} diff --git a/branches/pcsx2_0.9.2/x86/iCore.h b/branches/pcsx2_0.9.2/x86/iCore.h new file mode 100644 index 0000000..198ef94 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iCore.h @@ -0,0 +1,421 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_CORE_RECOMPILER_ +#define _PCSX2_CORE_RECOMPILER_ + +#include "iVUmicro.h" + +// used to keep block information +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +typedef struct _BASEBLOCK +{ + u32 pFnptr : 28; + u32 uType : 4; + u32 startpc; +} BASEBLOCK; + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +// extra block info (only valid for start of fn) +typedef struct _BASEBLOCKEX +{ + u16 size; // size in dwords + u16 dummy; + u32 startpc; // for debugging? + +#ifdef PCSX2_DEVBUILD + u32 visited; // number of times called + LARGE_INTEGER ltime; // regs it assumes to have set already +#endif + +} BASEBLOCKEX; + +#define GET_BLOCKTYPE(b) ((b)->Type) +#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + +#define FPU_STATE 0 +#define MMX_STATE 1 + +#define X86TYPE_TEMP 0 +#define X86TYPE_GPR 1 +#define X86TYPE_VI 2 +#define X86TYPE_MEMOFFSET 3 +#define X86TYPE_VIMEMOFFSET 4 +#define X86TYPE_VUQREAD 5 +#define X86TYPE_VUPREAD 6 +#define X86TYPE_VUQWRITE 7 +#define X86TYPE_VUPWRITE 8 +#define X86TYPE_PSX 9 +#define X86TYPE_PCWRITEBACK 10 +#define X86TYPE_VUJUMP 12 // jump from random mem (g_recWriteback) +#define X86TYPE_VITEMP 13 + +#define X86TYPE_VU1 0x80 + +#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u8 type; // X86TYPE_ + u16 counter; + u32 extra; // extra info assoc with the reg +} _x86regs; + +extern _x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; + +void _initX86regs(); +int _getFreeX86reg(int mode); +int _allocX86reg(int x86reg, int type, int reg, int mode); +void _deleteX86reg(int type, int reg, int flush); +int _checkX86reg(int type, int reg, int mode); +void _addNeededX86reg(int type, int reg); +void _clearNeededX86regs(); +void _freeX86reg(int x86reg); +void _freeX86regs(); + +void _eeSetLoadStoreReg(int gprreg, u32 offset, int x86reg); +int _eeGeLoadStoreReg(int gprreg, int* poffset); + +void recReset(); + +// when using mmx/xmm regs, use; 0 is load +// freezes no matter the state +void FreezeMMXRegs_(int save); +void FreezeXMMRegs_(int save); +void SetFPUstate(); +void SetMMXstate(); + +#define MODE_READ 1 +#define MODE_WRITE 2 +#define MODE_READHALF 4 // read only low 64 bits +#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF +#define MODE_VUZ 0x10 // z only doesn't work for now +#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory) +#define MODE_NOFLUSH 0x20 // can't flush reg to mem +#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg +#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx + +// max is 0x7f, when 0x80 is set, need to flush reg +#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index] +#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0; +#define MMX_GPR 0 +#define MMX_HI 32 +#define MMX_LO 33 +#define MMX_FPUACC 34 +#define MMX_FPU 64 +#define MMX_COP0 96 +#define MMX_TEMP 0x7f + +#define MMX_IS32BITS(x) (((x)>=MMX_FPU&&(x)= MMX_GPR && (x) < MMX_GPR+34) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u16 counter; +} _mmxregs; + +void _initMMXregs(); +int _getFreeMMXreg(); +int _allocMMXreg(int MMXreg, int reg, int mode); +void _addNeededMMXreg(int reg); +int _checkMMXreg(int reg, int mode); +void _clearNeededMMXregs(); +void _deleteMMXreg(int reg, int flush); +void _freeMMXreg(int mmxreg); +void _moveMMXreg(int mmxreg); // instead of freeing, moves it to a diff location +void _flushMMXregs(); +u8 _hasFreeMMXreg(); +void _freeMMXregs(); +int _getNumMMXwrite(); + +void _flushCachedRegs(); +void _flushConstRegs(); +void _flushConstReg(int reg); + +// return type: 0 - const, 1 - mmx, 2 - xmm +#define PROCESS_EE_MMX 0x01 +#define PROCESS_EE_XMM 0x02 + +// currently only used in FPU +#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem +#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem + +// not used in VU recs +#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs +#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs +#define PROCESS_EE_LO 0x40 // lo reg is valid +#define PROCESS_EE_HI 0x80 // hi reg is valid +#define PROCESS_EE_ACC 0x40 // acc reg is valid + +// used in VU recs +#define PROCESS_VU_UPDATEFLAGS 0x10 +#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation +#define PROCESS_VU_COP2 0x80 // simple cop2 + +#define EEREC_S (((info)>>8)&0xf) +#define EEREC_T (((info)>>12)&0xf) +#define EEREC_D (((info)>>16)&0xf) +#define EEREC_LO (((info)>>20)&0xf) +#define EEREC_HI (((info)>>24)&0xf) +#define EEREC_ACC (((info)>>20)&0xf) +#define EEREC_TEMP (((info)>>24)&0xf) + +#define PROCESS_EE_SET_S(reg) ((reg)<<8) +#define PROCESS_EE_SET_T(reg) ((reg)<<12) +#define PROCESS_EE_SET_D(reg) ((reg)<<16) +#define PROCESS_EE_SET_LO(reg) ((reg)<<20) +#define PROCESS_EE_SET_HI(reg) ((reg)<<24) +#define PROCESS_EE_SET_ACC(reg) ((reg)<<20) + +#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg) +#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24) + +// special info not related to above flags +#define PROCESS_CONSTS 1 +#define PROCESS_CONSTT 2 + +#define XMM_CONV_VU(VU) (VU==&VU1) + +#define XMMTYPE_TEMP 0 // has to be 0 +#define XMMTYPE_VFREG 1 +#define XMMTYPE_ACC 2 +#define XMMTYPE_FPREG 3 +#define XMMTYPE_FPACC 4 +#define XMMTYPE_GPRREG 5 + +// lo and hi regs +#define XMMGPR_LO MMX_LO +#define XMMGPR_HI MMX_HI +#define XMMFPU_ACC 32 + +typedef struct { + u8 inuse; + u8 reg; + u8 type; + u8 mode; + u8 needed; + u8 VU; // 0 = VU0, 1 = VU1 + u16 counter; +} _xmmregs; + +void _initXMMregs(); +int _getFreeXMMreg(); +int _allocTempXMMreg(XMMSSEType type, int xmmreg); +int _allocVFtoXMMreg(VURegs *VU, int xmmreg, int vfreg, int mode); +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode); +int _allocGPRtoXMMreg(int xmmreg, int gprreg, int mode); +int _allocACCtoXMMreg(VURegs *VU, int xmmreg, int mode); +int _allocFPACCtoXMMreg(int xmmreg, int mode); +int _checkXMMreg(int type, int reg, int mode); +void _addNeededVFtoXMMreg(int vfreg); +void _addNeededACCtoXMMreg(); +void _addNeededFPtoXMMreg(int fpreg); +void _addNeededFPACCtoXMMreg(); +void _addNeededGPRtoXMMreg(int gprreg); +void _clearNeededXMMregs(); +void _deleteVFtoXMMreg(int reg, int vu, int flush); +void _deleteACCtoXMMreg(int vu, int flush); +void _deleteGPRtoXMMreg(int reg, int flush); +void _deleteFPtoXMMreg(int reg, int flush); +void _freeXMMreg(int xmmreg); +void _moveXMMreg(int xmmreg); // instead of freeing, moves it to a diff location +void _flushXMMregs(); +u8 _hasFreeXMMreg(); +void _freeXMMregs(); +int _getNumXMMwrite(); + +// Constants used for controlling iFlushCall, _psxFlushCall +#define FLUSH_CACHED_REGS 1 +#define FLUSH_FLUSH_XMM 2 +#define FLUSH_FREE_XMM 4 // both flushes and frees +#define FLUSH_FLUSH_MMX 8 +#define FLUSH_FREE_MMX 16 // both flushes and frees + +#define FLUSH_EVERYTHING 0xff +// no freeing, used when callee won't destroy mmx/xmm regs +#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX) +// used when regs aren't going to be changed be callee +#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX) + +// Note: All functions with _ee prefix are for EE only + +// finds where the GPR is stored and moves lower 32 bits to EAX +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr); +void _eeMoveGPRtoM(u32 to, int fromgpr); +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr); + +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr); +void _psxMoveGPRtoM(u32 to, int fromgpr); +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); + +// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs +void _recPushReg(int mmreg); + +void _signExtendSFtoM(u32 mem); +int _signExtendMtoMMX(x86MMXRegType to, u32 mem); +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg); + +// returns new index of reg, lower 32 bits already in mmx +// shift is used when the data is in the top bits of the mmx reg to begin with +// a negative shift is for sign extension +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift); +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns true if reg destroyed + +// Defines for passing register info + +// only valid during writes. If write128, then upper 64bits are in an mmxreg +// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f) +#define MEM_EECONSTTAG 0x0100 +#define MEM_PSXCONSTTAG 0x0200 +// mmreg is mmxreg +#define MEM_MMXTAG 0x0800 +// mmreg is xmmreg +#define MEM_XMMTAG 0x8000 + +#define IS_CONSTREG(reg) (reg>=0&&((reg)&MEM_EECONSTTAG)) +#define IS_PSXCONSTREG(reg) (reg>=0&&((reg)&MEM_PSXCONSTTAG)) +#define IS_MMXREG(reg) (reg>=0&&((reg)&MEM_MMXTAG)) +#define IS_XMMREG(reg) (reg>=0&&((reg)&MEM_XMMTAG)) + +////////////////////// +// Instruction Info // +////////////////////// +#define EEINST_LIVE0 1 // if var is ever used (read or write) +#define EEINST_LIVE1 2 // if cur var's next 32 bits are needed +#define EEINST_LIVE2 4 // if cur var's next 64 bits are needed +#define EEINST_LASTUSE 8 // if var isn't written/read anymore +#define EEINST_MMX 0x10 // var will be used in mmx ops +#define EEINST_XMM 0x20 // var will be used in xmm ops (takes precedence +#define EEINST_USED 0x40 + +#define EEINSTINFO_COP1 1 +#define EEINSTINFO_COP2 2 +#define EEINSTINFO_NOREC 4 // if set, inst is recompiled alone +#define EEINSTINFO_COREC 8 // if set, inst is recompiled with another similar inst +#define EEINSTINFO_MMX EEINST_MMX +#define EEINSTINFO_XMM EEINST_XMM + +typedef struct _EEINST +{ + u8 regs[34]; // includes HI/LO (HI=32, LO=33) + u8 fpuregs[33]; // ACC=32 + u8 info; // extra info, if 1 inst is COP1, 2 inst is COP2. Also uses EEINST_MMX|EEINST_XMM + + // uses XMMTYPE_ flags; if type == XMMTYPE_TEMP, not used + u8 writeType[3], writeReg[3]; // reg written in this inst, 0 if no reg + u8 readType[4], readReg[4]; + + // valid if info & EEINSTINFO_COP2 + int cycle; // cycle of inst (at offset from block) + _VURegsNum vuregs; + + u8 numpeeps; // number of peephole optimizations +} EEINST; + +extern EEINST* g_pCurInstInfo; // info for the cur instruction +void _recClearInst(EEINST* pinst); + +// returns the number of insts + 1 until written (0 if not written) +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg); +// returns the number of insts + 1 until used (0 if not used) +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg); +void _recFillRegister(EEINST* pinst, int type, int reg, int write); + +#define EEINST_ISLIVEMMX(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)) +#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) +#define EEINST_ISLIVE1(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE1) +#define EEINST_ISLIVE2(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE2) + +#define FPUINST_ISLIVE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0) +#define FPUINST_LASTUSE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE) + +// if set, then the variable at this inst really has its upper 32 bits valid +// The difference between EEINST_LIVE1 is that the latter is used in back propagation +// The former is set at recompile time. +#define EEINST_RESETHASLIVE1(reg) { if( (reg) < 32 ) g_cpuRegHasLive1 &= ~(1<<(reg)); } +#define EEINST_HASLIVE1(reg) (g_cpuPrevRegHasLive1&(1<<(reg))) + +#define EEINST_SETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt |= (1<<(reg)); } +#define EEINST_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); } +#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg))) + +// writeback inst (used for cop2) +typedef struct _EEINSTWRITEBACK +{ + int cycle; + u32 viwrite; // mask of written viregs (REG_STATUS_FLAG and REG_MAC_FLAG are treated the same) + EEINST* parent; +} EEINSTWRITEBACK; + +void _recClearWritebacks(); +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent); + +// if cycle == -1, returns the next writeback (used for flushing) +EEINSTWRITEBACK* _recCheckWriteBack(int cycle); + +extern u32 g_recWriteback; // used for jumps +extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1; +extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt; + +extern u16 x86FpuState, iCWstate; +extern u8 g_globalMMXSaved, g_globalXMMSaved; +extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS]; +extern _xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalXMMLocked; +#endif + +// allocates only if later insts use XMM, otherwise checks +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode); +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode); +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode); + +void _recMove128MtoM(u32 to, u32 from); +void _recMove128RmOffsettoM(u32 to, u32 offset); +void _recMove128MtoRmOffset(u32 offset, u32 from); + +// op = 0, and +// op = 1, or +// op = 2, xor +// op = 3, nor (the 32bit versoins only do OR) +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoM(u32 to, u32 from, int op); + +// 0 - ee, 1 - iop +void AddBaseBlockEx(BASEBLOCKEX*, int cpu); +void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu); +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu); +void ResetBaseBlockEx(int cpu); + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iFPU.c b/branches/pcsx2_0.9.2/x86/iFPU.c new file mode 100644 index 0000000..579263a --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iFPU.c @@ -0,0 +1,1357 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iFPU.h" + +#define REC_FPUBRANCH(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ + branch = 2; \ +} + +#define REC_FPUFUNC(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)f); \ +} + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +extern u32 g_minvals[4], g_maxvals[4]; + +void SetQFromStack(u32 mem) +{ + write16(0xe5d9); + FNSTSWtoAX(); + write8(0x9e); + j8Ptr[0] = JAE8(0); // jnc + + // sign bit is in bit 9 of EAX + FSTP(0); // pop + AND32ItoR(EAX, 0x200); + SHL32ItoR(EAX, 22); + OR32MtoR(EAX, (u32)&g_maxvals[0]); + MOV32RtoM(mem, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + // just pop + FSTP32(mem); + x86SetJ8(j8Ptr[1]); +} + +//////////////////////////////////////////////////// +void recMFC1(void) { + int regt, regs; + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + if( regs >= 0 ) { + _deleteGPRtoXMMreg(_Rt_, 2); + regt = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + + if( regt >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regt, regs); + + if(EEINST_ISLIVE1(_Rt_)) _signExtendGPRtoMMX(regt, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + if(EEINST_ISLIVE1(_Rt_)) { + _signExtendXMMtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs); + } + } + } + else if( (regs = _checkMMXreg(MMX_FPU+_Fs_, MODE_READ)) >= 0 ) { + // convert to mmx reg + mmxregs[regs].reg = MMX_GPR+_Rt_; + mmxregs[regs].mode |= MODE_READ|MODE_WRITE; + _signExtendGPRtoMMX(regs, _Rt_, 0); + } + else { + regt = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } + + _deleteEEreg(MMX_GPR+_Rt_, 0); + + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCFC1(void) +{ + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + MOV32MtoR( EAX, (u32)&fpuRegs.fprc[ _Fs_ ] ); + _deleteEEreg(_Rt_, 0); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } +} + +//////////////////////////////////////////////////// +void recMTC1(void) +{ + if( GPR_IS_CONST1(_Rt_) ) { + _deleteFPtoXMMreg(_Fs_, 0); + MOV32ItoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + if( g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE ) { + // transfer the reg directly + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteFPtoXMMreg(_Fs_, 2); + _allocFPtoXMMreg(mmreg, _Fs_, MODE_WRITE); + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) SSE_MOVSS_XMM_to_XMM(mmreg2, mmreg); + else SSE_MOVSS_XMM_to_M32((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + + if( cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(mmreg2, mmreg); + } + else { + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + _deleteFPtoXMMreg(_Fs_, 0); + SetMMXstate(); + MOVDMMXtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + + if( mmreg2 >= 0 ) SSE_MOVSS_M32_to_XMM(mmreg2, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + MOV32RtoM((u32)&fpuRegs.fpr[ _Fs_ ].UL, EAX); + } + } + } +} + +//////////////////////////////////////////////////// +void recCTC1( void ) +{ + if( GPR_IS_CONST1(_Rt_)) { + MOV32ItoM((u32)&fpuRegs.fprc[ _Fs_ ], g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + SSEX_MOVD_XMM_to_M32((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&fpuRegs.fprc[ _Fs_ ], mmreg); + SetMMXstate(); + } + else { + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&fpuRegs.fprc[ _Fs_ ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCOP1_BC1() +{ + recCP1BC1[_Rt_](); +} + +static u32 _mxcsr = 0x7F80; +static u32 _mxcsrs; +static u32 fpucw = 0x007f; +static u32 fpucws = 0; + +//////////////////////////////////////////////////// +void SaveCW(int type) { + if (iCWstate & type) return; + + if (type == 2) { +// SSE_STMXCSR((u32)&_mxcsrs); +// SSE_LDMXCSR((u32)&_mxcsr); + } else { + FNSTCW( (u32)&fpucws ); + FLDCW( (u32)&fpucw ); + } + iCWstate|= type; +} + +//////////////////////////////////////////////////// +void LoadCW( void ) { + if (iCWstate == 0) return; + + if (iCWstate & 2) { + //SSE_LDMXCSR((u32)&_mxcsrs); + } + if (iCWstate & 1) { + FLDCW( (u32)&fpucws ); + } + iCWstate = 0; +} + +//////////////////////////////////////////////////// +void recCOP1_S( void ) +{ + if( !EE_FPU_REGCACHING || !cpucaps.hasStreamingSIMD2Extensions) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1S[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +void recCOP1_W( void ) +{ + if( !EE_FPU_REGCACHING ) { + _freeMMXreg(6); + _freeMMXreg(7); + } + recCP1W[ _Funct_ ]( ); +} + +#ifndef FPU_RECOMPILE + + +REC_FPUFUNC(ADD_S); +REC_FPUFUNC(SUB_S); +REC_FPUFUNC(MUL_S); +REC_FPUFUNC(DIV_S); +REC_FPUFUNC(SQRT_S); +REC_FPUFUNC(RSQRT_S); +REC_FPUFUNC(ABS_S); +REC_FPUFUNC(MOV_S); +REC_FPUFUNC(NEG_S); +REC_FPUFUNC(ADDA_S); +REC_FPUFUNC(SUBA_S); +REC_FPUFUNC(MULA_S); +REC_FPUFUNC(MADD_S); +REC_FPUFUNC(MSUB_S); +REC_FPUFUNC(MADDA_S); +REC_FPUFUNC(MSUBA_S); +REC_FPUFUNC(CVT_S); +REC_FPUFUNC(CVT_W); +REC_FPUFUNC(MIN_S); +REC_FPUFUNC(MAX_S); +REC_FPUBRANCH(BC1F); +REC_FPUBRANCH(BC1T); +REC_FPUBRANCH(BC1FL); +REC_FPUBRANCH(BC1TL); +REC_FPUFUNC(C_F); +REC_FPUFUNC(C_EQ); +REC_FPUFUNC(C_LE); +REC_FPUFUNC(C_LT); + +#else + +#ifdef EE_FPU_REGCACHING + +// define all FPU ops with XMM +#endif + +//////////////////////////////////////////////////// +void recC_EQ_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + j8Ptr[0] = JZ8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); +} + +void recC_EQ_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[_Fs_].f); + FCOMP32( (u32)&fpuRegs.fpr[_Ft_].f); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004000 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_EQ, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_F() +{ + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); +} + +//////////////////////////////////////////////////// +void recC_LT_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JB8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JBE8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LT_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00000100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[1] ); +} + +FPURECOMPILE_CONSTCODE(C_LT, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_LE_xmm(int info ) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (u32)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (u32)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JBE8(0); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JB8(0); + OR32ItoM((u32)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (u32)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +void recC_LE_(int info) +{ + SetFPUstate(); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (u32)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (u32)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +FPURECOMPILE_CONSTCODE(C_LE, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +static void (*recComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_ADDSS_XMM_to_XMM, SSE_MULSS_XMM_to_XMM, SSE_MAXSS_XMM_to_XMM, SSE_MINSS_XMM_to_XMM }; + +static void (*recComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_ADDSS_M32_to_XMM, SSE_MULSS_M32_to_XMM, SSE_MAXSS_M32_to_XMM, SSE_MINSS_M32_to_XMM }; + +void recCommutativeOp(int info, int regd, int op) { + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd == EEREC_S) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + } + break; + case PROCESS_EE_T: + if (regd == EEREC_T) recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_T); + recComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Fs_]); + } + break; + default: + if (regd == EEREC_S) { + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + else if (regd == EEREC_T) { + recComOpXMM_to_XMM[op](regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } +} + +static void (*recNonComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_SUBSS_XMM_to_XMM, SSE_DIVSS_XMM_to_XMM }; + +static void (*recNonComOpM32_to_XMM[] )(x86SSERegType, u32) = { + SSE_SUBSS_M32_to_XMM, SSE_DIVSS_M32_to_XMM }; + +int recNonCommutativeOp(int info, int regd, int op) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd != EEREC_S) SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpM32_to_XMM[op](regd, (u32)&fpuRegs.fpr[_Ft_]); + break; + case PROCESS_EE_T: + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](t0reg, EEREC_T); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_M32_to_XMM(regd, (u32)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + default: + if (regd == EEREC_S) { + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } else + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + recNonComOpXMM_to_XMM[op](t0reg, regd); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } + + return regd; +} + +void recADD_S_xmm(int info) { + recCommutativeOp(info, EEREC_D, 0); +} + +void recADD_S_(int info) { + SetFPUstate(); + + SaveCW(1); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(ADD_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recSUB_S_xmm(int info) +{ + recNonCommutativeOp(info, EEREC_D, 0); +} + +void recSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SUB_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recMUL_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 1); +} + +void recMUL_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MUL_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recDIV_S_xmm(int info) +{ + int regd = recNonCommutativeOp(info, EEREC_D, 1); + SSE_MAXSS_M32_to_XMM(regd, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(regd, (u32)&g_maxvals[0]); + +// _freeXMMreg(EEREC_D); +// MOV32MtoR(EAX, (int)&fpuRegs.fpr[_Fd_]); +// AND32ItoR(EAX, 0x7f800000); +// CMP32ItoR(EAX, 0x7f800000); +// j8Ptr[0] = JNE8(0); +// MOV32ItoM((int)&fpuRegs.fpr[_Fd_], 0); +// x86SetJ8(j8Ptr[0]); +} + +void recDIV_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(DIV_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +static u32 PCSX2_ALIGNED16(s_neg[4]) = { 0x80000000, 0, 0, 0 }; +static u32 PCSX2_ALIGNED16(s_pos[4]) = { 0x7fffffff, 0, 0, 0 }; + +void recSQRT_S_xmm(int info) +{ + if( info & PROCESS_EE_T ) { + if( CHECK_FORCEABS ) { + if( EEREC_D == EEREC_T ) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&s_pos[0]); + SSE_ANDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( CHECK_FORCEABS ) { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + } + } +} + +void recSQRT_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(SQRT_S, XMMINFO_WRITED|XMMINFO_READT); + +void recABS_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + else { + if( _Fs_ == _Fd_ ) { + AND32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x7fffffff); + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode &= ~MODE_WRITE; + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&s_pos[0]); + } + } +} + +void recABS_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].f ); + AND32ItoR( EAX, 0x7fffffff ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(ABS_S, XMMINFO_WRITED|XMMINFO_READS); + +void recMOV_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } +} + +void recMOV_S_(int info) +{ + MOV32MtoR( EAX, (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +} + +FPURECOMPILE_CONSTCODE(MOV_S, XMMINFO_WRITED|XMMINFO_READS); + +void recNEG_S_xmm(int info) { + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&s_neg[0]); +} + +void recNEG_S_(int info) +{ + MOV32MtoR( EAX,(u32)&fpuRegs.fpr[ _Fs_ ].f ); + XOR32ItoR( EAX, 0x80000000 ); + MOV32RtoM( (u32)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +FPURECOMPILE_CONSTCODE(NEG_S, XMMINFO_WRITED|XMMINFO_READS); + +void recRSQRT_S_xmm(int info) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_RSQRTSS_M32_to_XMM(t0reg, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + + break; + case PROCESS_EE_T: + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + break; + default: + if( EEREC_D == EEREC_S ) { + int t0reg; + if( g_pCurInstInfo->regs[_Ft_]&EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + } + + SSE_RSQRTSS_XMM_to_XMM(t0reg, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + break; + } + + SSE_MAXSS_M32_to_XMM(EEREC_D, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_D, (u32)&g_maxvals[0]); +} + +void recRSQRT_S_(int info) +{ + static u32 tmp; + + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (u32)&tmp ); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (u32)&tmp ); + SetQFromStack( (u32)&fpuRegs.fpr[ _Fd_ ].f ); + +// FLD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); +// FSQRT( ); +// FSTP32( (u32)&tmp ); +// +// MOV32MtoR( EAX, (u32)&tmp ); +// OR32RtoR( EAX, EAX ); +// j8Ptr[ 0 ] = JE8( 0 ); +// FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); +// FDIV32( (u32)&tmp ); +// FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +// x86SetJ8( j8Ptr[ 0 ] ); +} + +FPURECOMPILE_CONSTCODE(RSQRT_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recADDA_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_ACC, 0); +} + +void recADDA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(ADDA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recSUBA_S_xmm(int info) { + recNonCommutativeOp(info, EEREC_ACC, 0); +} + +void recSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(SUBA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMULA_S_xmm(int info) { + recCommutativeOp(info, EEREC_ACC, 1); +} + +void recMULA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MULA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + SSE_MULSS_M32_to_XMM(regd, mreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + default: + if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (u32)&fpuRegs.ACC); + } + break; + } +} + +void recMADD_S_xmm(int info) +{ + recMADDtemp(info, EEREC_D); +} + +void recMADD_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MADD_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDA_S_xmm(int info) +{ + recMADDtemp(info, EEREC_ACC); +} + +void recMADDA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (u32)&fpuRegs.ACC.f ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MADDA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + if( !(info&PROCESS_EE_ACC)) { + int regacc = _allocFPACCtoXMMreg(-1, MODE_WRITE|MODE_READ); + info |= PROCESS_EE_SET_ACC(regacc)|PROCESS_EE_ACC; + } + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(u32)&fpuRegs.fpr[_Ft_]:(u32)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_M32_to_XMM(regd, mreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + + break; + default: + if (regd == EEREC_S) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if (regd == EEREC_T) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + break; + } +} + +void recMSUB_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_D); +} + +void recMSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(MSUB_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBA_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_ACC); +} + +void recMSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (u32)&fpuRegs.ACC.f ); + FLD32( (u32)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (u32)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (u32)&fpuRegs.ACC.f ); +} + +FPURECOMPILE_CONSTCODE(MSUBA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recCVT_S_xmm(int info) +{ + if( !(info&PROCESS_EE_S) || (EEREC_D != EEREC_S && !(info&PROCESS_EE_MODEWRITES)) ) { + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( info&PROCESS_EE_MODEWRITES ) { + if( xmmregs[EEREC_S].reg == _Fs_ ) + _deleteFPtoXMMreg(_Fs_, 1); + else { + // force sync + SSE_MOVSS_XMM_to_M32((u32)&fpuRegs.fpr[_Fs_], EEREC_S); + } + } + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (u32)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode |= MODE_WRITE; // in the case that _Fs_ == _Fd_ + } + } +} + +void recCVT_S_(int info) +{ + SetFPUstate(); + FILD32( (u32)&fpuRegs.fpr[ _Fs_ ].UL ); + FSTP32( (u32)&fpuRegs.fpr[ _Fd_ ].f ); +} + +FPURECOMPILE_CONSTCODE(CVT_S, XMMINFO_WRITED|XMMINFO_READS); + +//////////////////////////////////////////////////// +void recCVT_W() +{ + if( cpucaps.hasStreamingSIMDExtensions ) { + int t0reg; + int regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + + if( regs >= 0 ) { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CVTTSS2SI_XMM_to_R32(EAX, regs); + } + else SSE_CVTTSS2SI_M32_to_R32(EAX, (u32)&fpuRegs.fpr[ _Fs_ ]); + + _deleteFPtoXMMreg(_Fd_, 2); + + CMP32ItoR(EAX, 0x80000000); + j8Ptr[0] = JNE8(0); + + // need to detect if reg is positive + if( regs >= 0 ) { + SSE_UCOMISS_XMM_to_XMM(regs, t0reg); + j8Ptr[2] = JB8(0); + } + else { + TEST32ItoM((u32)&fpuRegs.fpr[_Fs_], 0x80000000); + j8Ptr[2] = JNZ8(0); + } + + MOV32ItoM((u32)&fpuRegs.fpr[_Fd_], 0x7fffffff); + j8Ptr[1] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[2] ); + MOV32RtoM((u32)&fpuRegs.fpr[_Fd_], EAX); + + x86SetJ8( j8Ptr[1] ); + } + else { + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); + iFlushCall(FLUSH_EVERYTHING); + _flushConstRegs(); + CALLFunc((u32)CVT_W); + } +} + +void recMAX_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 2); +} + +void recMAX_S_(int info) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MAX_S ); +} + +FPURECOMPILE_CONSTCODE(MAX_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recMIN_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 3); +} + +void recMIN_S_(int info) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MIN_S ); +} + +FPURECOMPILE_CONSTCODE(MIN_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recBC1F( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBC1T( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + //j32Ptr[1] = JMP32(0); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + //x86SetJ32(j32Ptr[1]); +} + +//////////////////////////////////////////////////// +void recBC1FL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBC1TL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (u32)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iFPU.h b/branches/pcsx2_0.9.2/x86/iFPU.h new file mode 100644 index 0000000..0d94bff --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iFPU.h @@ -0,0 +1,60 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IFPU_H__ +#define __IFPU_H__ + +void recMFC1( void ); +void recCFC1( void ); +void recMTC1( void ); +void recCTC1( void ); +void recCOP1_BC1( void ); +void recCOP1_S( void ); +void recCOP1_W( void ); +void recC_EQ( void ); +void recC_F( void ); +void recC_LT( void ); +void recC_LE( void ); +void recADD_S( void ); +void recSUB_S( void ); +void recMUL_S( void ); +void recDIV_S( void ); +void recSQRT_S( void ); +void recABS_S( void ); +void recMOV_S( void ); +void recNEG_S( void ); +void recRSQRT_S( void ); +void recADDA_S( void ); +void recSUBA_S( void ); +void recMULA_S( void ); +void recMADD_S( void ); +void recMSUB_S( void ); +void recMADDA_S( void ); +void recMSUBA_S( void ); +void recCVT_S( void ); +void recCVT_W( void ); +void recMAX_S( void ); +void recMIN_S( void ); +void recBC1F( void ); +void recBC1T( void ); +void recBC1FL( void ); +void recBC1TL( void ); + +#endif + + diff --git a/branches/pcsx2_0.9.2/x86/iMMI.c b/branches/pcsx2_0.9.2/x86/iMMI.c new file mode 100644 index 0000000..fd1e8f1 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iMMI.c @@ -0,0 +1,3370 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* cached MMI opcodes * +* * +*********************************************************/ + +// NOTE: This code is disabled when xmm reg caching is ENABLED (instead use iMMI.c) +// This also means that every change that goes into here has to be repeated in iMMI.c and MMI.c (zerofrog) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" + +#ifndef MMI_RECOMPILE + +REC_FUNC( PLZCW, _Rd_ ); + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +REC_FUNC( PMFHL, _Rd_ ); +REC_FUNC( PMTHL, _Rd_ ); + +REC_FUNC( PSRLW, _Rd_ ); +REC_FUNC( PSRLH, _Rd_ ); + +REC_FUNC( PSRAH, _Rd_ ); +REC_FUNC( PSRAW, _Rd_ ); + +REC_FUNC( PSLLH, _Rd_ ); +REC_FUNC( PSLLW, _Rd_ ); + +#else + +void recPLZCW() +{ + int regd = -1; + int regs = 0; + + if ( ! _Rd_ ) return; + + if( GPR_IS_CONST1(_Rs_) ) { + _eeOnWriteReg(_Rd_, 0); + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + + for(regs = 0; regs < 2; ++regs) { + u32 val = g_cpuConstRegs[_Rs_].UL[regs]; + + if( val != 0 ) { + u32 setbit = val&0x80000000; + g_cpuConstRegs[_Rd_].UL[regs] = 0; + val <<= 1; + + while((val & 0x80000000) == setbit) { + g_cpuConstRegs[_Rd_].UL[regs]++; + val <<= 1; + } + } + else { + g_cpuConstRegs[_Rd_].UL[regs] = 31; + } + } + return; + } + + _eeOnWriteReg(_Rd_, 0); + + if( (regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE2_MOVD_XMM_to_R(EAX, regs); + regs |= MEM_XMMTAG; + } + else if( (regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVD32MMXtoR(EAX, regs); + SetMMXstate(); + regs |= MEM_MMXTAG; + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + regs = 0; + } + + if( EEINST_ISLIVE1(_Rd_) ) + _deleteEEreg(_Rd_, 0); + else { + if( (regd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) < 0 ) { + _deleteEEreg(_Rd_, 0); + } + } + + // first word + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 31); + } + else { + SetMMXstate(); + PCMPEQDRtoR(regd, regd); + PSRLQItoR(regd, 59); + } + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + else { + SetMMXstate(); + MOVD32RtoMMX(regd, ECX); + } + + x86SetJ8(j8Ptr[1]); + + // second word + if( EEINST_ISLIVE1(_Rd_) ) { + if( regs >= 0 && (regs & MEM_XMMTAG) ) { + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + SSE2_MOVD_XMM_to_R(EAX, regs&0xf); + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + } + else if( regs >= 0 && (regs & MEM_MMXTAG) ) { + PSHUFWRtoR(regs, regs, 0x4e); + MOVD32MMXtoR(EAX, regs&0xf); + PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e); + SetMMXstate(); + } + else MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + MOV32ItoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 31); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX); + x86SetJ8(j8Ptr[1]); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + + GPR_DEL_CONST(_Rd_); +} + +static u32 PCSX2_ALIGNED16(s_CmpMasks[]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPMFHL() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) + + int t0reg; + + switch (_Sa_) { + case 0x00: // LW + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + break; + + case 0x01: // UW + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0xdd); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0xdd); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x02: // SLW + // fall to interp + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + iFlushCall(FLUSH_CACHED_REGS); // since calling CALLFunc + CALLFunc( (u32)PMFHL ); + break; + + case 0x03: // LH + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x04: // SH + if( EEREC_D == EEREC_HI ) { + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x72); + } + else { + if( EEREC_D != EEREC_LO ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_HI); + + // shuffle so a1a0b1b0->a1b1a0b0 + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); + } + break; + default: + SysPrintf("PMFHL??\n"); + assert(0); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMFHL, _Rd_ ); +} + +void recPMTHL() +{ + SysPrintf("PMTHL email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PMTHL, 0 ); +} + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +#define MMX_ALLOC_TEMP1(code) { \ + int t0reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ +} \ + +#define MMX_ALLOC_TEMP2(code) { \ + int t0reg, t1reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ +} \ + +#define MMX_ALLOC_TEMP3(code) { \ + int t0reg, t1reg, t2reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ +} \ + +#define MMX_ALLOC_TEMP4(code) { \ + int t0reg, t1reg, t2reg, t3reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t3reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ + _freeMMXreg(t3reg); \ +} \ + +//////////////////////////////////////////////////// +void recPSRLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLWItoR( t0reg, _Sa_&0xf ); + PSRLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRLW( void ) +{ + if( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLDItoR( t0reg, _Sa_ ); + PSRLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRAWItoR( t0reg, _Sa_&0xf ); + PSRAWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRADItoR( t0reg, _Sa_ ); + PSRADItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLWItoR( t0reg, _Sa_&0xf ); + PSLLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLDItoR( t0reg, _Sa_ ); + PSLLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +/* +void recMADD( void ) +{ +} + +void recMADDU( void ) +{ +} + +void recPLZCW( void ) +{ +} +*/ + +#ifdef MMI0_RECOMPILE + +void recMMI0( void ) +{ + recMMI0t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI1_RECOMPILE + +void recMMI1( void ) +{ + recMMI1t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI2_RECOMPILE + +void recMMI2( void ) +{ + recMMI2t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI3_RECOMPILE + +void recMMI3( void ) +{ + recMMI3t[ _Sa_ ]( ); +} + +#endif + +#endif + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ +#ifndef MMI0_RECOMPILE + +REC_FUNC( PADDB, _Rd_); +REC_FUNC( PADDH, _Rd_); +REC_FUNC( PADDW, _Rd_); +REC_FUNC( PADDSB, _Rd_); +REC_FUNC( PADDSH, _Rd_); +REC_FUNC( PADDSW, _Rd_); +REC_FUNC( PSUBB, _Rd_); +REC_FUNC( PSUBH, _Rd_); +REC_FUNC( PSUBW, _Rd_); +REC_FUNC( PSUBSB, _Rd_); +REC_FUNC( PSUBSH, _Rd_); +REC_FUNC( PSUBSW, _Rd_); + +REC_FUNC( PMAXW, _Rd_); +REC_FUNC( PMAXH, _Rd_); + +REC_FUNC( PCGTW, _Rd_); +REC_FUNC( PCGTH, _Rd_); +REC_FUNC( PCGTB, _Rd_); + +REC_FUNC( PEXTLW, _Rd_); + +REC_FUNC( PPACW, _Rd_); +REC_FUNC( PEXTLH, _Rd_); +REC_FUNC( PPACH, _Rd_); +REC_FUNC( PEXTLB, _Rd_); +REC_FUNC( PPACB, _Rd_); +REC_FUNC( PEXT5, _Rd_); +REC_FUNC( PPAC5, _Rd_); + +#else + +//////////////////////////////////////////////////// +void recPMAXW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMAXW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPACW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(((_Rs_!=0||!cpucaps.hasStreamingSIMD2Extensions)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + + // swap mmx regs.. don't ask + xmmregs[t0reg] = xmmregs[EEREC_D]; + xmmregs[EEREC_D].inuse = 0; + } + } + } + else { + if( EEREC_D != EEREC_S ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x88 ); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x88 ); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); //Copy this one cos it could get overwritten + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], ECX); //This is where we bring it back + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +void recPPACH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, t0reg, 0x88); + } + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[6]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[4]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +//////////////////////////////////////////////////// +void recPPACB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, EEREC_D); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(t0reg, 8); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(t0reg, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PPACB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXT5() +{ + SysPrintf("PEXT5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PEXT5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPAC5() +{ + SysPrintf("PPAC5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PPAC5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMAXH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + if( cpucaps.hasStreamingSIMDExtensions ) { + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + SSE_PMAXSW_MM_to_MM( t0reg, t1reg ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMAXSW_MM_to_MM( t2reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) + } + else { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PMAXH ); + } +} + +//////////////////////////////////////////////////// +void recPCGTB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PCMPGTBRtoR( t0reg, t1reg ); + + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPGTBRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTWRtoR( t0reg, t1reg ); + PCMPGTWRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTW( void ) +{ + //TODO:optimize RS | RT== 0 + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTDRtoR( t0reg, t1reg ); + PCMPGTDRtoR( t2reg, t3reg); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSBRtoR( t0reg, t2reg); + PADDSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSWRtoR( t0reg, t2reg); + PADDSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + + //SysPrintf("PADDSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PADDSW ); +} + +//////////////////////////////////////////////////// +void recPSUBSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSBRtoR( t0reg, t2reg); + PSUBSBRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSWRtoR( t0reg, t2reg); + PSUBSWRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + //SysPrintf("PSUBSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PSUBSW ); +} + +//////////////////////////////////////////////////// +void recPADDB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDBRtoR( t0reg, t2reg ); + PADDBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDWRtoR( t0reg, t2reg ); + PADDWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDDRtoR( t0reg, t2reg ); + PADDDRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBBRtoR( t0reg, t2reg ); + PSUBBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBWRtoR( t0reg, t2reg ); + PSUBWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBDRtoR( t0reg, t2reg); + PSUBDRtoR( t1reg, t3reg); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPEXTLW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); +} + +void recPEXTLB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + //SysPrintf("PEXTLB\n"); + //Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[7]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[6]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[5]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[4]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[3]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[2]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[1]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[0]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); +} + +void recPEXTLH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((u32)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +#endif + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ +#ifndef MMI1_RECOMPILE + +REC_FUNC( PABSW, _Rd_); +REC_FUNC( PABSH, _Rd_); + +REC_FUNC( PMINW, _Rd_); +REC_FUNC( PADSBH, _Rd_); +REC_FUNC( PMINH, _Rd_); +REC_FUNC( PCEQB, _Rd_); +REC_FUNC( PCEQH, _Rd_); +REC_FUNC( PCEQW, _Rd_); + +REC_FUNC( PADDUB, _Rd_); +REC_FUNC( PADDUH, _Rd_); +REC_FUNC( PADDUW, _Rd_); + +REC_FUNC( PSUBUB, _Rd_); +REC_FUNC( PSUBUH, _Rd_); +REC_FUNC( PSUBUW, _Rd_); + +REC_FUNC( PEXTUW, _Rd_); +REC_FUNC( PEXTUH, _Rd_); +REC_FUNC( PEXTUB, _Rd_); +REC_FUNC( QFSRV, _Rd_); + +#else + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(int s_MaskHighBitD[4]) = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; +PCSX2_ALIGNED16(int s_MaskHighBitW[4]) = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; + +void recPABSW() +{ + if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPABSH() +{ +if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(t0reg, 15); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPMINW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_S); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMINW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPADSBH() +{ + SysPrintf("PADSBH email zero if abnormal behavior\n"); + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_D); + // reset lower bits to 0s + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 8); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + } + + // t0reg - adds, EEREC_D - subs + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE(PADSBH, _Rd_); +} + +//////////////////////////////////////////////////// +void recPADDUW() +{ +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rt_ == 0 ) { + if( _Rs_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( _Rs_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + int t2reg = _allocTempXMMreg(XMMT_INT, -1); + + if( _hasFreeXMMreg() ) { + int t3reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t3reg, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(t1reg, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t2reg, t0reg); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t3reg, t0reg); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t3reg); + _freeXMMreg(t3reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSE2_PSRLDQ_I8_to_XMM(t2reg, 8); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xE8); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t0reg); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + } + + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, t2reg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t2reg); + SSE2_PCMPGTD_XMM_to_XMM(t1reg, t0reg); + SSEX_POR_XMM_to_XMM(EEREC_D, t1reg); + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + } + +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUW() +{ + SysPrintf("PSUBUW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSUBUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXTUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXTUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recQFSRV() +{ + u8* pshift1, *pshift2, *poldptr, *pnewptr; + + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + + poldptr = x86Ptr; + x86Ptr += 6; + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 0); + pshift1 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + x86Ptr = pnewptr; + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + MOV32ItoR(ECX, 16); + SUB32RtoR(ECX, EAX); + + poldptr = x86Ptr; + x86Ptr += 12; + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 0); + pshift1 = x86Ptr-1; + + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 0); + pshift2 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((u32)pshift1, EAX); + MOV8RtoM((u32)pshift2, ECX); + + x86Ptr = pnewptr; + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( QFSRV, _Rd_ ); +} + + +void recPEXTUB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but faster than int + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[8]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[9]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[10]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[11]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[12]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[13]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[14]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UC[15]); + MOV8RtoM((u32)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); +} + +//////////////////////////////////////////////////// +void recPEXTUW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 2 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 2 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 3 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 3 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); +} + +//////////////////////////////////////////////////// +void recPMINH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + if( cpucaps.hasStreamingSIMDExtensions ) { + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMINSW_MM_to_MM( t0reg, t2reg ); + SSE_PMINSW_MM_to_MM( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) + } + else { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)PMINH ); + } +} + +//////////////////////////////////////////////////// +void recPCEQB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQBRtoR( t0reg, t2reg ); + PCMPEQBRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQWRtoR( t0reg, t2reg ); + PCMPEQWRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t0reg, t2reg ); + PCMPEQDRtoR( t1reg, t3reg ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rt_ ) { + if( EEREC_D == EEREC_S ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( EEREC_D != EEREC_S ) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSBRtoR( t0reg, t2reg ); + PADDUSBRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSWRtoR( t0reg, t2reg ); + PADDUSWRtoR( t1reg, t3reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +#endif +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ +#ifndef MMI2_RECOMPILE + +REC_FUNC( PMFHI, _Rd_); +REC_FUNC( PMFLO, _Rd_); +REC_FUNC( PCPYLD, _Rd_); +REC_FUNC( PAND, _Rd_); +REC_FUNC( PXOR, _Rd_); + +REC_FUNC( PMADDW, _Rd_); +REC_FUNC( PSLLVW, _Rd_); +REC_FUNC( PSRLVW, _Rd_); +REC_FUNC( PMSUBW, _Rd_); +REC_FUNC( PINTH, _Rd_); +REC_FUNC( PMULTW, _Rd_); +REC_FUNC( PDIVW, _Rd_); +REC_FUNC( PMADDH, _Rd_); +REC_FUNC( PHMADH, _Rd_); +REC_FUNC( PMSUBH, _Rd_); +REC_FUNC( PHMSBH, _Rd_); +REC_FUNC( PEXEH, _Rd_); +REC_FUNC( PREVH, _Rd_); +REC_FUNC( PMULTH, _Rd_); +REC_FUNC( PDIVBW, _Rd_); +REC_FUNC( PEXEW, _Rd_); +REC_FUNC( PROT3W, _Rd_ ); + +#else + +//////////////////////////////////////////////////// +void recPMADDW() +{ + SysPrintf("PMADDW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMADDW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSLLVW() +{ + SysPrintf("PSLLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSLLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSRLVW() +{ + SysPrintf("PSRLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSRLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBW() +{ + SysPrintf("PMSUBW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) +// int t0reg = _allocTempXMMreg(XMMT_INT, -1); +// +// if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); +// else { +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); +// SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// } +// +// // add from LO/HI +// SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSUBQ_XMM_to_XMM(EEREC_LO, EEREC_D); +// +// // get the signs +// SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +// SSE2_PSRAD_I8_to_XMM(t0reg, 31); +// +// // interleave +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); +// +// SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); +// SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); +// +// _freeXMMreg(t0reg); +//CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTW() +{ + SysPrintf("PMULTW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMULTW, _Rd_ ); +} +//////////////////////////////////////////////////// +void recPDIVW() +{ + SysPrintf("PDIVW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + REC_FUNC_INLINE( PDIVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPDIVBW() +{ + SysPrintf("PDIVBW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PDIVBW, _Rd_ ); //-- +} + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(int s_mask[4]) = {~0, 0, ~0, 0}; + +void recPHMADH() +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _Rd_ ? EEREC_D : _allocTempXMMreg(XMMT_INT, -1); + + if( t0reg == EEREC_S ) { + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + if( t0reg == EEREC_T ) { + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + } + else { + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + } + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + } + else { + if( t0reg != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_T); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + } + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + SSE2_PAND_M128_to_XMM(EEREC_LO, (u32)s_mask); + SSE2_PAND_M128_to_XMM(EEREC_HI, (u32)s_mask); + + if( !_Rd_ ) _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMADH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBH() +{ + SysPrintf("PMSUBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPHMSBH() +{ + SysPrintf("PHMSBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMSBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXEH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xc6); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPREVH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x17); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x17); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PREVH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPINTH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_MOVHLPS_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[0]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[2], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[4], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[0], EDX); + + MOV16MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].US[5]); + MOV16MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rs_].US[7]); + MOV16MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].US[3]); + + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[5], EBX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[7], ECX); + MOV16RtoM( (u32)&cpuRegs.GPR.r[_Rd_].US[6], EDX); +} + +void recPEXEW( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPROT3W( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc9); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( EBX, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPMULTH( void ) +{ +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_HI, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_LO, EEREC_HI); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(t0reg, EEREC_HI); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, t0reg, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_HI); + } + + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_LO, t0reg); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(!_Rt_ || !_Rs_) { + MOV32ItoM( (u32)&cpuRegs.LO.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.LO.UL[3], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.HI.UL[3], 0); + + if( _Rd_ ) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], 0); + MOV32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], 0); + } + return; + } + + //Done - Refraction + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +void recPMFHI( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_HI); +CPU_SSE_XMMCACHE_END + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.HI.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMFLO( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.LO.UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPAND( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PANDMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PANDMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPXOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PXORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PXORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYLD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READS)|XMMINFO_READT) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + else if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + else { + if( EEREC_D == EEREC_T ) SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x44); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t1reg ); + SetMMXstate(); + ) +} + + +void recPMADDH( void ) +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PADDD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(_Rt_ && _Rs_){ + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (u32)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (u32)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (u32)&cpuRegs.HI.UL[3], EAX); + + } + + if (_Rd_) { + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[0]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.LO.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (u32)&cpuRegs.HI.UL[2]); + MOV32RtoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +#endif +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ +#ifndef MMI3_RECOMPILE + +REC_FUNC( PMADDUW, _Rd_); +REC_FUNC( PSRAVW, _Rd_); +REC_FUNC( PMTHI, _Rd_); +REC_FUNC( PMTLO, _Rd_); +REC_FUNC( PINTEH, _Rd_); +REC_FUNC( PMULTUW, _Rd_); +REC_FUNC( PDIVUW, _Rd_); +REC_FUNC( PCPYUD, _Rd_); +REC_FUNC( POR, _Rd_); +REC_FUNC( PNOR, _Rd_); +REC_FUNC( PCPYH, _Rd_); +REC_FUNC( PEXCW, _Rd_); +REC_FUNC( PEXCH, _Rd_); + +#else + +//////////////////////////////////////////////////// +REC_FUNC( PSRAVW, _Rd_ ); + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(u32 s_tempPINTEH[4]) = {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPINTEH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + int t0reg = -1; + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PAND_M128_to_XMM(EEREC_D, (u32)s_tempPINTEH); + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_S, 0xa0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xa0); + } + else if( EEREC_D == EEREC_T ) { + assert( EEREC_D != EEREC_S ); + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_S) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSRLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + } + + if( t0reg >= 0 ) _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PINTEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTUW() +{ + SysPrintf("PMULTUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PMULTUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMADDUW() +{ + SysPrintf("PMADDUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // add from LO/HI + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + SSE2_PADDQ_XMM_to_XMM(EEREC_D, EEREC_LO); + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +//do EEINST_SETSIGNEXT +REC_FUNC( PDIVUW, _Rd_ ); + +//////////////////////////////////////////////////// +void recPEXCW() +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXCH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPNOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + } + else { + if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + if( _Rt_ != 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + if( EEREC_D == EEREC_S ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + if( EEREC_S != EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg ); + SSEX_PXOR_XMM_to_XMM( EEREC_D, t0reg ); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP3( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PORMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t2reg, t2reg ); + PXORRtoR( t0reg, t2reg ); + PXORRtoR( t1reg, t2reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTHI( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITEHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_HI, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTLO( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITELO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_LO, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYUD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READT)|XMMINFO_WRITED) + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + } + else { + if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + //TODO + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + } + else { + if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0xee); + } + else if( EEREC_D == EEREC_T ) { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( _Rs_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + else if( _Rt_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + if( EEREC_S != EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + if ( _Rt_ != 0 ) + { + PORMtoR ( t0reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR ( t1reg, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + } + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //PUSH32R( EBX ); + MOVZX32M16toR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOV32RtoR( ECX, EAX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EAX, ECX ); + MOVZX32M16toR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOV32RtoR( ECX, EDX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EDX, ECX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], EDX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EDX ); + //POP32R( EBX ); +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iMMI.h b/branches/pcsx2_0.9.2/x86/iMMI.h new file mode 100644 index 0000000..c69b6bc --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iMMI.h @@ -0,0 +1,133 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ +#ifndef __IMMI_H__ +#define __IMMI_H__ + +void recMADD(); +void recMADDU(); +void recPLZCW(); +void recMMI0(); +void recMMI1(); +void recMMI2(); +void recMMI3(); +void recMADD1(); +void recMADDU1(); +void recPMFHL(); +void recPMTHL(); +void recPMAXW(); +void recPMINW(); +void recPPACW(); +void recPEXTLH(); +void recPPACH(); +void recPEXTLB(); +void recPPACB(); +void recPEXT5(); +void recPPAC5(); +void recPABSW(); +void recPADSBH(); +void recPABSH(); +void recPADDUW(); +void recPSUBUW(); +void recPSUBUH(); +void recPEXTUH(); +void recPSUBUB(); +void recPEXTUB(); +void recQFSRV(); +void recPMADDW(); +void recPSLLVW(); +void recPSRLVW(); +void recPMSUBW(); +void recPINTH(); +void recPMULTW(); +void recPDIVW(); +void recPMADDH(); +void recPHMADH(); +void recPMSUBH(); +void recPHMSBH(); +void recPEXEH(); +void recPREVH(); +void recPMULTH(); +void recPDIVBW(); +void recPEXEW(); +void recPROT3W(); +void recPMADDUW(); +void recPSRAVW(); +void recPINTEH(); +void recPMULTUW(); +void recPDIVUW(); +void recPEXCH(); +void recPEXCW(); + +void recPSRLH(); +void recPSRLW(); +void recPSRAH(); +void recPSRAW(); +void recPSLLH(); +void recPSLLW(); +void recMTHI1(); +void recMTLO1(); +void recMFHI1(); +void recMFLO1(); +void recMULT1(); +void recMULTU1(); +void recDIV1(); +void recDIVU1(); +void recPMAXH(); +void recPCGTB(); +void recPCGTH(); +void recPCGTW(); +void recPADDSB(); +void recPADDSH(); +void recPADDSW(); +void recPSUBSB(); +void recPSUBSH(); +void recPSUBSW(); +void recPADDB(); +void recPADDH(); +void recPADDW(); +void recPSUBB(); +void recPSUBH(); +void recPSUBW(); +void recPEXTLW(); +void recPEXTUW(); +void recPMINH(); +void recPCEQB(); +void recPCEQH(); +void recPCEQW(); +void recPADDUB(); +void recPADDUH(); +void recPMFHI(); +void recPMFLO(); +void recPAND(); +void recPXOR(); +void recPCPYLD(); +void recPNOR(); +void recPMTHI(); +void recPMTLO(); +void recPCPYUD(); +void recPOR(); +void recPCPYH(); + +#endif + + diff --git a/branches/pcsx2_0.9.2/x86/iR3000A.cpp b/branches/pcsx2_0.9.2/x86/iR3000A.cpp new file mode 100644 index 0000000..8311384 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR3000A.cpp @@ -0,0 +1,1376 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking Jan06 +// and added reg caching, const propagation, block analysis Jun06 +// zerofrog(@gmail.com) + +#if 1 + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "zlib.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" +#include "PsxCounters.h" + +extern u32 psxNextCounter, psxNextsCounter; +u32 g_psxMaxRecMem = 0; +extern char *disRNameGPR[]; +extern char* disR3000Fasm(u32 code, u32 pc); +} + +#define PSX_NUMBLOCKS (1<<12) +#define MAPBASE 0x48000000 +#define RECMEM_SIZE (8*1024*1024) + +// R3000A statics +uptr *psxRecLUT; +int psxreclog = 0; + +static u32 s_BranchCount = 0; +static char *recMem; // the recompiled blocks will be here +static BASEBLOCK *recRAM; // and the ptr to the blocks here +static BASEBLOCK *recROM; // and here +static BASEBLOCK *recROM1; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr; +u32 psxpc; // recompiler psxpc +int psxbranch; // set for branch +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_psxNextBranchCycle = 0; + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what psxpc the current block ends + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +static u32 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_psxBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch); +void psxRecompileNextInstruction(int delayslot); +static void recRecompile(u32 startpc); + +extern void (*rpsxBSC[64])(); +extern void (*rpsxBSC_co[64])(); +void rpsxpropBSC(EEINST* prev, EEINST* pinst); + +#ifdef _DEBUG +extern "C" u32 psxdump = 0; +#else +#define psxdump 0 +#endif + +#define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) + +#define PSXREC_CLEARM(mem) { \ + if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PSX_GETBLOCK(mem); \ + if( *(u32*)p ) psxRecClearMem(p); \ + } \ +} \ + +BASEBLOCKEX* PSX_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+PSX_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 1); +} + +//////////////////////////////////////////////////// +static void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + u8 used[34]; + int numused, count; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, psxpc, psxRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); +sprintf( filename, "dumps\\psxdump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/psxdump%.8X.txt", startpc); +#endif + + fflush( stdout ); + + f = fopen( filename, "w" ); + assert( f != NULL ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR3000Fasm( *(u32*)PSXM( i ), i ) ); + } + + // write the instruction info + fprintf(f, "\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _psxIsLoadStore(u32 tempcode) +{ + switch(tempcode>>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + return 1; + } + return 0; +} + +void _psxFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( psxpc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && PSX_IS_CONST1(i) ) _psxFlushConstReg(i); + else { + _deleteX86reg(X86TYPE_PSX, i, 1); + } + } +} + +int _psxFlushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_psxHasConstReg & (1< 0 ); + + // make sure right GPR was saved + assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1< 0) { + pblock = PSX_GETBLOCK(psxRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != psxRegs.pc ) { + recRecompile(psxRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + +#ifdef _DEBUG + + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R3000AFNPTR)pblock->pFnptr); + // use call instead of pfn() + __asm call pfn +#endif + } +} + +extern u32 g_psxNextBranchCycle; +u32 g_psxlastpc = 0; +static u32 g_temp; + +// jumped to when invalid psxpc address +__declspec(naked,noreturn) void psxDispatcher() +{ + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == psxRegs.pc + mov ecx, psxRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push psxRegs.pc // psxpc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new psxpc +// and eax, 0x0fffffff +// mov ecx, psxRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void psxDispatcherClear() +{ + // EDX contains the current psxpc + __asm mov psxRegs.pc, edx + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + if( s_pDispatchBlock->startpc == psxRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable psxpc address +__declspec(naked,noreturn) void psxDispatcherReg() +{ + __asm { + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov edx, psxRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, psxRecLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == psxRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +static void recClear(u32 Addr, u32 Size) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + PSXREC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void rpsxMemConstClear(u32 mem) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !psxRecLUT[mem>>16] ) + return; + + CMP32ItoM((u32)PSX_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PSX_GETBLOCK(mem)); + CALLFunc((u32)psxRecClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); +} + +void psxRecClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + psxRecClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)psxDispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PSX_GETBLOCK(p->startpc); + pexblock = PSX_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 1); + pexblock->size = 0; + pexblock->startpc = 0; +} + +void psxSetBranchReg(u32 reg) +{ + psxbranch = 1; + + if( reg != 0xffffffff ) { + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, reg); + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + } + + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void psxSetBranchImm( u32 imm ) +{ + u32* ptr; + psxbranch = 1; + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&psxRegs.pc, imm ); + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(imm, imm <= psxpc); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)psxDispatcher - ( (u32)x86Ptr + 5 )); +} + +#define USE_FAST_BRANCHES 0 + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch) +{ + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&psxRegs.cycle); + ADD32ItoR(ECX, s_psxBlockCycles*17/16); // greater mult factor causes nfsmw to crash + MOV32RtoM((int)&psxRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + return; + } + + SUB32MtoR(ECX, (int)&g_psxNextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + CALLFunc((int)psxBranchTest); + + CMP32ItoM((int)&EEsCycle, 0); + j8Ptr[2] = JG8(0); + RET2(); + x86SetJ8( j8Ptr[2] ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&psxRegs.pc, newpc); + JNE32((u32)psxDispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + +static int *s_pCode; + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("iop code changed! %x\n", pctemp); +} + +void rpsxSYSCALL() +{ + MOV32ItoM( (u32)&psxRegs.code, psxRegs.code ); + MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4); + _psxFlushCall(FLUSH_NODESTROY); + + PUSH32I(psxbranch == 1 ? 1 : 0); + PUSH32I(0x20); + CALLFunc ((int)psxException); + ADD32ItoR(ESP, 8); + + CMP32ItoM((int)&psxRegs.pc, psxpc-4); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&psxRegs.cycle, s_psxBlockCycles); + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + + //if (!psxbranch) psxbranch = 2; +} + +u32 psxRecompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PSX_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( psxpc == pblock->startpc ) + return 0; + } + + return 1; +} + +void psxRecompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + + BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && psxpc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == psxpc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + psxRecClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", psxpc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + +#ifdef _DEBUG + MOV32ItoR(EAX, psxpc); +#endif + + s_pCode = (int *)PSXM( psxpc ); + assert(s_pCode); + + psxRegs.code = *(int *)s_pCode; + s_psxBlockCycles++; + psxpc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, psxRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, psxpc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +//#endif + + + g_pCurInstInfo++; + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + assert(0); +// recBSC_co[cpuRegs.code>>26](); +// psxpc += 4; +// s_psxBlockCycles++; +// g_pCurInstInfo++; + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + rpsxBSC[ psxRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //_psxFlushUnusedConstReg(); + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + _clearNeededX86regs(); +} + +static void recExecute() { + for (;;) execute(); +} + +static void recExecuteBlock() { + + execute(); +} + +extern "C" +void iDumpPsxRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + + __Log("%spsxreg: %x\n", pstr, startpc); + for(i = 0; i < 34; i+=2) __Log("%spsx%d: %x %x\n", pstr, i, psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); + __Log("%scycle: %x %x %x %x; counters %x %x\n", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, IOPoCycle, + (u32)psxNextsCounter, (u32)psxNextCounter); + + for(i = 0; i < 6; ++i) __Log("%scounter%d: %x %x %x\n", pstr, i, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT); +// for(i = 0; i < 32; ++i) { +// __Log("int%d: %x %x\n", i, psxRegs.sCycle[i], psxRegs.eCycle[i]); +// } +} + +void iDumpPsxRegisters(u32 startpc); + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0; + const int skip = 0; + + if( (psxdump&2) ) {//&& lastrec != g_psxlastpc ) { + curcount++; + + if( curcount > skip ) { + iDumpPsxRegisters(g_psxlastpc, 1); + curcount = 0; + } + + lastrec = g_psxlastpc; + } +} + +u32 s_recblocks[] = {0}; + +static void recRecompile(u32 startpc) +{ + u32 i; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + +#ifdef _DEBUG + //psxdump |= 4; + if( psxdump & 4 ) + iDumpPsxRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + s_pCurBlock = PSX_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + psxRecClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < PSX_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%PSX_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%PSX_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%PSX_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + + psxbranch = 0; + + s_pCurBlock->startpc = startpc; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_psxBlockCycles = 0; + + // reset recomp state variables + psxpc = startpc; + s_saveConstGPRreg = 0; + g_psxHasConstReg = g_psxFlushedConstReg = 1; + + _initX86regs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_psxlastpc, psxpc); + CALLFunc((u32)printfn); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + + while(1) { + BASEBLOCK* pblock = PSX_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + psxRegs.code = *(int *)PSXM(i); + + switch(psxRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ == 0 || _Rt_ == 1 || _Rt_ == 16 || _Rt_ == 17 ) { + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + psxRegs.code = *(int *)PSXM(i-4); + pcur[-1] = pcur[0]; + rpsxpropBSC(pcur-1, pcur); + pcur--; + } + } + + // peephole optimizations // +// { +// g_pCurInstInfo = s_pInstCache; +// +// for(i = startpc; i < s_nEndBlock-4; i += 4) { +// g_pCurInstInfo++; +// if( psxRecompileCodeSafe(i) ) { +// u32 curcode = *(u32*)PSXM(i); +// u32 nextcode = *(u32*)PSXM(i+4); +// if( _psxIsLoadStore(curcode) && _psxIsLoadStore(nextcode) && (curcode>>26) == (nextcode>>26) && rpsxBSC_co[curcode>>26] != NULL ) { +// +// // rs has to be the same, and cannot be just written +// if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_psxLoadWritesRs(curcode) ) { +// +// // good enough +// g_pCurInstInfo[0].info |= EEINSTINFO_COREC; +// g_pCurInstInfo[0].numpeeps = 1; +// g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; +// g_pCurInstInfo++; +// i += 4; +// continue; +// } +// } +// } +// } +// } + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (psxdump & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + g_pCurInstInfo = s_pInstCache; + while (!psxbranch && psxpc < s_nEndBlock) { + psxRecompileNextInstruction(0); + } + + assert( (psxpc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (psxpc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 1); + + if( !(psxpc&0x10000000) ) + g_psxMaxRecMem = max( (psxpc&~0xa0000000), g_psxMaxRecMem ); + + if( psxbranch == 2 ) { + _psxFlushCall(FLUSH_EVERYTHING); + + iPsxBranchTest(0xffffffff, 1); + + JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( psxbranch != 3 ); + if( psxbranch ) assert( !willbranch3 ); + else ADD32ItoM((int)&psxRegs.cycle, s_psxBlockCycles*17/16); + + if( willbranch3 ) { + BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock); + assert( psxpc == s_nEndBlock ); + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&psxRegs.pc, psxpc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + psxbranch = 3; + } + else if( !psxbranch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&psxRegs.pc, psxpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + //JMP32((u32)psxDispatcherReg - ( (u32)x86Ptr + 5 )); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+RECMEM_SIZE ); + + recPtr = x86Ptr; + + assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); + + if( !psxbranch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PSX_GETBLOCK(psxpc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != psxpc ) + recRecompile(psxpc); + + // could have reset + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iR3000A.h b/branches/pcsx2_0.9.2/x86/iR3000A.h new file mode 100644 index 0000000..d435909 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR3000A.h @@ -0,0 +1,99 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _R3000A_SUPERREC_ +#define _R3000A_SUPERREC_ + +extern void __Log(char *fmt, ...); + +// to be consistent with EE +#define PSX_HI MMX_HI +#define PSX_LO MMX_LO + +extern uptr *psxRecLUT; + +u8 _psxLoadWritesRs(u32 tempcode); +u8 _psxIsLoadStore(u32 tempcode); + +void _psxFlushAllUnused(); +int _psxFlushUnusedConstReg(); +void _psxFlushCachedRegs(); +void _psxFlushConstReg(int reg); +void _psxFlushConstRegs(); + +void _psxDeleteReg(int reg, int flush); +void _psxFlushCall(int flushtype); + +void _psxOnWriteReg(int reg); +void PSX_CHECK_SAVE_REG(int reg); + +extern u32 psxpc; // recompiler pc +extern int psxbranch; // set for branch + +void psxSaveBranchState(); +void psxLoadBranchState(); + +void psxSetBranchReg(u32 reg); +void psxSetBranchImm( u32 imm ); +void psxRecompileNextInstruction(int delayslot); + +typedef void (*R3000AFNPTR)(); +typedef void (*R3000AFNPTR_INFO)(int info); + +void psxRecClearMem(BASEBLOCK* p); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define PSXRECOMPILE_CONSTCODE0(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst0(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_); \ +} \ + +// rt = rs op imm16 +#define PSXRECOMPILE_CONSTCODE1(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst1(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// rd = rt op sa +#define PSXRECOMPILE_CONSTCODE2(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst2(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// [lo,hi] = rt op rs +#define PSXRECOMPILE_CONSTCODE3(fn, LOHI) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst3(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_, LOHI); \ +} \ + +// rd = rs op rt +void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode); +// rt = rs op imm16 +void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// rd = rt op sa +void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// [lo,hi] = rt op rs +void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode, int LOHI); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iR3000Atables.cpp b/branches/pcsx2_0.9.2/x86/iR3000Atables.cpp new file mode 100644 index 0000000..85c1076 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR3000Atables.cpp @@ -0,0 +1,2069 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if 1 + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "ir3000A.h" + +extern void psxLWL(); +extern void psxLWR(); +extern void psxSWL(); +extern void psxSWR(); + +extern int g_psxWriteOk; +extern u32 g_psxMaxRecMem; +} + +// R3000A instruction implementation +#define REC_FUNC(f) \ +void psx##f(); \ +static void rpsx##f() { \ + MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \ + _psxFlushCall(FLUSH_EVERYTHING); \ + /*MOV32ItoM((u32)&psxRegs.pc, (u32)pc);*/ \ + CALLFunc((u32)psx##f); \ + PSX_DEL_CONST(_Rt_); \ +/* branch = 2; */\ +} + +//// +void rpsxADDIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] + _Imm_; +} + +// adds a constant to sreg and puts into dreg +void rpsxADDconst(int dreg, int sreg, u32 off, int info) +{ + if (sreg) { + if (sreg == dreg) { + ADD32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + if (off) ADD32ItoR(EAX, off); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } +} + +void rpsxADDIU_(int info) +{ + // Rt = Rs + Im + if (!_Rt_) return; + rpsxADDconst(_Rt_, _Rs_, _Imm_, info); +} + +PSXRECOMPILE_CONSTCODE1(ADDIU); + +void rpsxADDI() { rpsxADDIU(); } + +//// SLTI +void rpsxSLTI_const() +{ + g_psxConstRegs[_Rt_] = *(int*)&g_psxConstRegs[_Rs_] < _Imm_; +} + +void rpsxSLTconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETL8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTI_(int info) { rpsxSLTconst(info, _Rt_, _Rs_, _Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTI); + +//// SLTIU +void rpsxSLTIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] < _ImmU_; +} + +void rpsxSLTUconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETB8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTIU_(int info) { rpsxSLTUconst(info, _Rt_, _Rs_, (s32)_Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTIU); + +//// ANDI +void rpsxANDI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] & _ImmU_; +} + +void rpsxANDconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + AND32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + AND32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], 0); + } +} + +void rpsxANDI_(int info) { rpsxANDconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ANDI); + +//// ORI +void rpsxORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] | _ImmU_; +} + +void rpsxORconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + OR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + OR32ItoR (EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxORI_(int info) { rpsxORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ORI); + +void rpsxXORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] ^ _ImmU_; +} + +void rpsxXORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm == 0xffffffff ) { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } + else if (imm) { + + if (sreg == dreg) { + XOR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + XOR32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxXORI_(int info) { rpsxXORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(XORI); + +void rpsxLUI() +{ + if(!_Rt_) return; + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + PSX_SET_CONST(_Rt_); + g_psxConstRegs[_Rt_] = psxRegs.code << 16; +} + +void rpsxADDU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] + g_psxConstRegs[_Rt_]; +} + +void rpsxADDU_consts(int info) { rpsxADDconst(_Rd_, _Rt_, g_psxConstRegs[_Rs_], info); } +void rpsxADDU_constt(int info) +{ + info |= PROCESS_EE_SET_S(EEREC_T); + rpsxADDconst(_Rd_, _Rs_, g_psxConstRegs[_Rt_], info); +} + +void rpsxADDU_(int info) +{ + if (_Rs_ && _Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Rs_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } else if (_Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else { + XOR32RtoR(EAX, EAX); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(ADDU); + +void rpsxADD() { rpsxADDU(); } + + +void rpsxSUBU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] - g_psxConstRegs[_Rt_]; +} + +void rpsxSUBU_consts(int info) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rs_]); + SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSUBU_constt(int info) { rpsxADDconst(_Rd_, _Rs_, -(int)g_psxConstRegs[_Rt_], info); } + +void rpsxSUBU_(int info) +{ + // Rd = Rs - Rt + if (!_Rd_) return; + + if( _Rd_ == _Rs_ ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SUB32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +PSXRECOMPILE_CONSTCODE0(SUBU); + +void rpsxSUB() { rpsxSUBU(); } + +void rpsxLogicalOp(int info, int op) +{ + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[vreg]); + LogicalOp32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX, op); + if( op == 3 ) + NOT32M((u32)&psxRegs.GPR.r[_Rd_]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]); + LogicalOp32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_], op); + if( op == 3 ) + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], ECX); + } +} + +void rpsxAND_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] & g_psxConstRegs[_Rt_]; +} + +void rpsxAND_consts(int info) { rpsxANDconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxAND_constt(int info) { rpsxANDconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxAND_(int info) { rpsxLogicalOp(info, 0); } + +PSXRECOMPILE_CONSTCODE0(AND); + +void rpsxOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]; +} + +void rpsxOR_consts(int info) { rpsxORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxOR_constt(int info) { rpsxORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxOR_(int info) { rpsxLogicalOp(info, 1); } + +PSXRECOMPILE_CONSTCODE0(OR); + +//// XOR +void rpsxXOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] ^ g_psxConstRegs[_Rt_]; +} + +void rpsxXOR_consts(int info) { rpsxXORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxXOR_constt(int info) { rpsxXORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxXOR_(int info) { rpsxLogicalOp(info, 2); } + +PSXRECOMPILE_CONSTCODE0(XOR); + +//// NOR +void rpsxNOR_const() +{ + g_psxConstRegs[_Rd_] = ~(g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]); +} + +void rpsxNORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm ) { + if( dreg == sreg ) { + OR32ItoM((u32)&psxRegs.GPR.r[dreg], imm); + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + OR32ItoR(ECX, imm); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } + else { + if( dreg == sreg ) { + NOT32M((u32)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((u32)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxNOR_consts(int info) { rpsxNORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxNOR_constt(int info) { rpsxNORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxNOR_(int info) { rpsxLogicalOp(info, 3); } + +PSXRECOMPILE_CONSTCODE0(NOR); + +//// SLT +void rpsxSLT_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rs_] < *(int*)&g_psxConstRegs[_Rt_]; +} + +void rpsxSLT_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETG8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLT_constt(int info) { rpsxSLTconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLT_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLT); + +//// SLTU +void rpsxSLTU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] < g_psxConstRegs[_Rt_]; +} + +void rpsxSLTU_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETA8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLTU_constt(int info) { rpsxSLTUconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLTU_(int info) +{ + // Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLTU); + +//// MULT +void rpsxMULT_const() +{ + u64 res = (s64)((s64)*(int*)&g_psxConstRegs[_Rs_] * (s64)*(int*)&g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTsuperconst(int info, int sreg, int imm, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32ItoR(EAX, imm); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[sreg]); + else MUL32M ((uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULTsuper(int info, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + else MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULT_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 1); } +void rpsxMULT_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 1); } +void rpsxMULT_(int info) { rpsxMULTsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(MULT, 1); + +//// MULTU +void rpsxMULTU_const() +{ + u64 res = (u64)((u64)g_psxConstRegs[_Rs_] * (u64)g_psxConstRegs[_Rt_]); + + MOV32ItoM((u32)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTU_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 0); } +void rpsxMULTU_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 0); } +void rpsxMULTU_(int info) { rpsxMULTsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(MULTU, 1); + +//// DIV +void rpsxDIV_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = *(int*)&g_psxConstRegs[_Rs_] / *(int*)&g_psxConstRegs[_Rt_]; + hi = *(int*)&g_psxConstRegs[_Rs_] % *(int*)&g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVsuperconsts(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rs_]; + + if( imm ) { + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32ItoR(EAX, imm); + + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); + } + else { + XOR32RtoR(EAX, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxDIVsuperconstt(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rt_]; + + if( imm ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + MOV32ItoR(ECX, imm); + //CDQ(); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + } +} + +void rpsxDIVsuper(int info, int sign) +{ + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); +} + +void rpsxDIV_consts(int info) { rpsxDIVsuperconsts(info, 1); } +void rpsxDIV_constt(int info) { rpsxDIVsuperconstt(info, 1); } +void rpsxDIV_(int info) { rpsxDIVsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(DIV, 1); + +//// DIVU +void rpsxDIVU_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = g_psxConstRegs[_Rs_] / g_psxConstRegs[_Rt_]; + hi = g_psxConstRegs[_Rs_] % g_psxConstRegs[_Rt_]; + MOV32ItoM((u32)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((u32)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVU_consts(int info) { rpsxDIVsuperconsts(info, 0); } +void rpsxDIVU_constt(int info) { rpsxDIVsuperconstt(info, 0); } +void rpsxDIVU_(int info) { rpsxDIVsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(DIVU, 1); + +//// LoadStores +#ifdef WIN32_VIRTUAL_MEM + +// VM load store functions (fastest) + +//#define REC_SLOWREAD +//#define REC_SLOWWRITE + +int _psxPrepareReg(int gprreg) +{ + return 0; +} + +static u32 s_nAddMemOffset = 0; + +#define SET_HWLOC() { \ + x86SetJ8(j8Ptr[0]); \ + SHR32ItoR(ECX, 3); \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ +} \ + +int rpsxSetMemLocation(int regs, int mmreg) +{ + s_nAddMemOffset = 0; + MOV32MtoR( ECX, (int)&psxRegs.GPR.r[ regs ] ); + + if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); + + SHL32ItoR(ECX, 3); + j8Ptr[0] = JS8(0); + SHR32ItoR(ECX, 3); + AND32ItoR(ECX, 0x1fffff); // 2Mb + return 1; +} + +void recLoad32(u32 bit, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _psxOnWriteReg(_Rt_); + mmreg = EAX; + + switch(bit) { + case 8: ineax = psxRecMemConstRead8(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); break; + case 16: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 2 == 0 ); + ineax = psxRecMemConstRead16(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); + break; + case 32: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 4 == 0 ); + ineax = psxRecMemConstRead32(mmreg, g_psxConstRegs[_Rs_]+_Imm_); + break; + } + + if( _Rt_ ) MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)psxRecMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)psxRecMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + CALLFunc( (int)psxRecMemRead32 ); + break; + } + + x86SetJ8(j8Ptr[1]); + } + + if( _Rt_ ) + MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } +} + +void rpsxLB() { recLoad32(8, 1); } +void rpsxLBU() { recLoad32(8, 0); } +void rpsxLH() { recLoad32(16, 1); } +void rpsxLHU() { recLoad32(16, 0); } +void rpsxLW() { recLoad32(32, 0); } + +extern void rpsxMemConstClear(u32 mem); + +// check if mem is executable, and clear it +__declspec(naked) void rpsxWriteMemClear() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, psxRecLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call psxRecClearMem + add esp, 4 +ClearRet: + ret + } +} + +extern u32 s_psxBlockCycles; +void recStore(int bit) +{ +#ifdef REC_SLOWWRITE + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + u8* pjmpok; + u32 addr = g_psxConstRegs[_Rs_]+_Imm_; + int doclear = 0; + + if( !(addr & 0x10000000) ) { + // check g_psxWriteOk + CMP32ItoM((u32)&g_psxWriteOk, 0); + pjmpok = JE8(0); + } + + switch(bit) { + case 8: + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite8(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite8(addr, EAX); + } + + break; + + case 16: + assert( (addr)%2 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite16(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite16(addr, EAX); + } + + break; + + case 32: + assert( (addr)%4 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite32(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite32(addr, EAX); + } + + break; + } + + if( !(addr & 0x10000000) ) { + if( doclear ) rpsxMemConstClear((addr)&~3); + x86SetJ8(pjmpok); + } + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + CMP32ItoM((u32)&g_psxWriteOk, 0); + u8* pjmpok = JE8(0); + + if( PSX_IS_CONST1( _Rt_ ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 16: MOV16ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 32: MOV32ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + } + } + else { + switch(bit) { + case 8: + MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV8RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 16: + MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV16RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 32: + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + } + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&g_psxMaxRecMem); + + j8Ptr[1] = JAE8(0); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + CALLFunc((u32)rpsxWriteMemClear); + + if( dohw ) { + j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( PSX_IS_CONST1(_Rt_) ) { + switch(bit) { + case 8: MOV8ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 16: MOV16ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 32: MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); break; + } + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 16: MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 32: MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + } + } + + if( s_nAddMemOffset != 0 ) ADD32ItoR(ECX, s_nAddMemOffset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)psxRecMemWrite8 ); break; + case 16: CALLFunc( (int)psxRecMemWrite16 ); break; + case 32: CALLFunc( (int)psxRecMemWrite32 ); break; + } + + x86SetJ8(j8Ptr[2]); + } + + x86SetJ8(j8Ptr[1]); + x86SetJ8(pjmpok); + } +} + +void rpsxSB() { recStore(8); } +void rpsxSH() { recStore(16); } +void rpsxSW() { recStore(32); } + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +#else + +// TLB loadstore functions (slower +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +static void rpsxLB() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLBU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead8); + if (_Rt_) { + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLH() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLHU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemRead16); + if (_Rt_) { + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLW() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + + TEST32ItoR(EAX, 0x10000000); + j8Ptr[0] = JZ8(0); + + PUSH32R (EAX); + CALLFunc((int)psxMemRead32); + if (_Rt_) { + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + ADD32ItoR(ESP, 4); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + // read from psM directly + AND32ItoR(EAX, 0x0fffffff); + ADD32ItoR(EAX, (u32)psxM); + + MOV32RmtoR( EAX, EAX ); + MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], EAX); + + x86SetJ8(j8Ptr[1]); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxSB() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite8); + ADD32ItoR(ESP, 8); +} + +static void rpsxSH() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite16); + ADD32ItoR(ESP, 8); +} + +static void rpsxSW() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + PUSH32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(EAX, _Imm_); + PUSH32R (EAX); + CALLFunc((int)psxMemWrite32); + ADD32ItoR(ESP, 8); +} + +#endif // end load store + +//// SLL +void rpsxSLL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << _Sa_; +} + +// shifttype: 0 - sll, 1 - srl, 2 - sra +void rpsxShiftConst(int info, int rdreg, int rtreg, int imm, int shifttype) +{ + imm &= 0x1f; + if (imm) { + if( rdreg == rtreg ) { + switch(shifttype) { + case 0: SHL32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 1: SHR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + case 2: SAR32ItoM((u32)&psxRegs.GPR.r[rdreg], imm); break; + } + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[rtreg]); + switch(shifttype) { + case 0: SHL32ItoR(EAX, imm); break; + case 1: SHR32ItoR(EAX, imm); break; + case 2: SAR32ItoR(EAX, imm); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[rdreg], EAX); + } + } + else { + if( rdreg != rtreg ) { + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[rtreg]); + MOV32RtoM((u32)&psxRegs.GPR.r[rdreg], EAX); + } + } +} + +void rpsxSLL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 0); } +PSXRECOMPILE_CONSTCODE2(SLL); + +//// SRL +void rpsxSRL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 1); } +PSXRECOMPILE_CONSTCODE2(SRL); + +//// SRA +void rpsxSRA_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRA_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 2); } +PSXRECOMPILE_CONSTCODE2(SRA); + +//// SLLV +void rpsxSLLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxShiftVconsts(int info, int shifttype) +{ + rpsxShiftConst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_], shifttype); +} + +void rpsxShiftVconstt(int info, int shifttype) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + switch(shifttype) { + case 0: SHL32CLtoR(EAX); break; + case 1: SHR32CLtoR(EAX); break; + case 2: SAR32CLtoR(EAX); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLLV_consts(int info) { rpsxShiftVconsts(info, 0); } +void rpsxSLLV_constt(int info) { rpsxShiftVconstt(info, 0); } +void rpsxSLLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLLV); + +//// SRLV +void rpsxSRLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRLV_consts(int info) { rpsxShiftVconsts(info, 1); } +void rpsxSRLV_constt(int info) { rpsxShiftVconstt(info, 1); } +void rpsxSRLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRLV); + +//// SRAV +void rpsxSRAV_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRAV_consts(int info) { rpsxShiftVconsts(info, 2); } +void rpsxSRAV_constt(int info) { rpsxShiftVconstt(info, 2); } +void rpsxSRAV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRAV); + +extern void rpsxSYSCALL(); + +void rpsxBREAK() { +} + +void rpsxMFHI() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTHI() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } +} + +void rpsxMFLO() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTLO() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxJ() +{ + // j target + u32 newpc = _Target_ * 4 + (psxpc & 0xf0000000); + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJAL() +{ + u32 newpc = (_Target_ << 2) + ( psxpc & 0xf0000000 ); + _psxDeleteReg(31, 0); + PSX_SET_CONST(31); + g_psxConstRegs[31] = psxpc + 4; + + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJR() +{ + psxSetBranchReg(_Rs_); +} + +void rpsxJALR() +{ + // jalr Rs + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, _Rs_); + + if ( _Rd_ ) + { + _psxDeleteReg(_Rd_, 0); + PSX_SET_CONST(_Rd_); + g_psxConstRegs[_Rd_] = psxpc + 4; + } + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&psxRegs.pc, EAX); + } + + psxSetBranchReg(0xffffffff); +} + +//// BEQ +static void* s_pbranchjmp; +static u32 s_do32 = 0; + +#define JUMPVALID(pjmp) (( x86Ptr - (s8*)pjmp ) <= 0x80) + +void rpsxSetBranchEQ(int info, int process) +{ + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rt_ ], g_psxConstRegs[_Rs_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&psxRegs.GPR.r[ _Rs_ ], g_psxConstRegs[_Rt_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else { + MOV32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rs_ ] ); + CMP32MtoR( EAX, (int)&psxRegs.GPR.r[ _Rt_ ] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } +} + +void rpsxBEQ_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] == g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + } + else + { + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + psxSaveBranchState(); + + rpsxSetBranchEQ(info, process); + + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + } +} + +void rpsxBEQ_(int info) { rpsxBEQ_process(info, 0); } +void rpsxBEQ_consts(int info) { rpsxBEQ_process(info, PROCESS_CONSTS); } +void rpsxBEQ_constt(int info) { rpsxBEQ_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BEQ, 0); + +//// BNE +void rpsxBNE_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] != g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + return; + } + + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + rpsxSetBranchEQ(info, process); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +void rpsxBNE_(int info) { rpsxBNE_process(info, 0); } +void rpsxBNE_consts(int info) { rpsxBNE_process(info, PROCESS_CONSTS); } +void rpsxBNE_constt(int info) { rpsxBNE_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BNE, 0); + +//// BLTZ +void rpsxBLTZ() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZ +void rpsxBGEZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLTZAL +void rpsxBLTZAL() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + else { + PSX_SET_CONST(_Rt_); + g_psxConstRegs[31] = psxpc+4; + } + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZAL +void rpsxBGEZAL() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + else MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLEZ +void rpsxBLEZ() +{ + // Branch if Rs <= 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] > 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JLE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JLE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +//// BGTZ +void rpsxBGTZ() +{ + // Branch if Rs > 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] <= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JG8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JG32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +void rpsxMFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxCFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxMTC0() +{ + // Cop0->Rd = Rt + if( PSX_IS_CONST1(_Rt_) ) { + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], g_psxConstRegs[_Rt_]); + } + else { + _psxDeleteReg(_Rt_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); + } +} + +void rpsxCTC0() +{ + // Cop0->Rd = Rt + rpsxMTC0(); +} + +void rpsxRFE() +{ + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); +} + +// R3000A tables +extern void (*rpsxBSC[64])(); +extern void (*rpsxSPC[64])(); +extern void (*rpsxREG[32])(); +extern void (*rpsxCP0[32])(); +extern void (*rpsxCP2[64])(); +extern void (*rpsxCP2BSC[32])(); + +static void rpsxSPECIAL() { rpsxSPC[_Funct_](); } +static void rpsxREGIMM() { rpsxREG[_Rt_](); } +static void rpsxCOP0() { rpsxCP0[_Rs_](); } +static void rpsxBASIC() { rpsxCP2BSC[_Rs_](); } + +static void rpsxNULL() { + SysPrintf("psxUNK: %8.8x\n", psxRegs.code); +} + +void (*rpsxBSC[64])() = { + rpsxSPECIAL, rpsxREGIMM, rpsxJ , rpsxJAL , rpsxBEQ , rpsxBNE , rpsxBLEZ, rpsxBGTZ, + rpsxADDI , rpsxADDIU , rpsxSLTI, rpsxSLTIU, rpsxANDI, rpsxORI , rpsxXORI, rpsxLUI , + rpsxCOP0 , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxLB , rpsxLH , rpsxLWL , rpsxLW , rpsxLBU , rpsxLHU , rpsxLWR , rpsxNULL, + rpsxSB , rpsxSH , rpsxSWL , rpsxSW , rpsxNULL, rpsxNULL, rpsxSWR , rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxSPC[64])() = { + rpsxSLL , rpsxNULL, rpsxSRL , rpsxSRA , rpsxSLLV , rpsxNULL , rpsxSRLV, rpsxSRAV, + rpsxJR , rpsxJALR, rpsxNULL, rpsxNULL, rpsxSYSCALL, rpsxBREAK, rpsxNULL, rpsxNULL, + rpsxMFHI, rpsxMTHI, rpsxMFLO, rpsxMTLO, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxMULT, rpsxMULTU, rpsxDIV, rpsxDIVU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxADD , rpsxADDU, rpsxSUB , rpsxSUBU, rpsxAND , rpsxOR , rpsxXOR , rpsxNOR , + rpsxNULL, rpsxNULL, rpsxSLT , rpsxSLTU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL +}; + +void (*rpsxREG[32])() = { + rpsxBLTZ , rpsxBGEZ , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxBLTZAL, rpsxBGEZAL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxCP0[32])() = { + rpsxMFC0, rpsxNULL, rpsxCFC0, rpsxNULL, rpsxMTC0, rpsxNULL, rpsxCTC0, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxRFE , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +// coissued insts +void (*rpsxBSC_co[64] )() = { + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpsxpropSetRead(reg) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpsxpropSetWrite(reg) { \ + prev->regs[reg] &= ~EEINST_LIVE0; \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +void rpsxpropBSC(EEINST* prev, EEINST* pinst); +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst); +void rpsxpropCP0(EEINST* prev, EEINST* pinst); +void rpsxpropCP2(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J , JAL , BEQ , BNE , BLEZ, BGTZ, +//ADDI , ADDIU , SLTI, SLTIU, ANDI, ORI , XORI, LUI , +//COP0 , NULL , COP2, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//LB , LH , LWL , LW , LBU , LHU , LWR , NULL, +//SB , SH , SWL , SW , NULL, NULL, SWR , NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL +void rpsxpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(psxRegs.code >> 26) { + case 0: rpsxpropSPECIAL(prev, pinst); break; + case 1: rpsxpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpsxpropSetWrite(31); + break; + case 4: // beq + case 5: // bne + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 6: // blez + case 7: // bgtz + rpsxpropSetRead(_Rs_); + break; + + case 15: // lui + rpsxpropSetWrite(_Rt_); + break; + + case 16: rpsxpropCP0(prev, pinst); break; + case 18: assert(0); break; + + // stores + case 40: case 41: case 42: case 43: case 46: + rpsxpropSetRead(_Rt_); + rpsxpropSetRead(_Rs_); + break; + + default: + rpsxpropSetWrite(_Rt_); + rpsxpropSetRead(_Rs_); + break; + } +} + +//SLL , NULL, SRL , SRA , SLLV , NULL , SRLV, SRAV, +//JR , JALR, NULL, NULL, SYSCALL, BREAK, NULL, NULL, +//MFHI, MTHI, MFLO, MTLO, NULL , NULL , NULL, NULL, +//MULT, MULTU, DIV, DIVU, NULL , NULL , NULL, NULL, +//ADD , ADDU, SUB , SUBU, AND , OR , XOR , NOR , +//NULL, NULL, SLT , SLTU, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rt_); + break; + + case 8: // JR + rpsxpropSetRead(_Rs_); + break; + case 9: // JALR + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_HI); + break; + case 17: // mthi + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + break; + case 18: // mflo + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_LO); + break; + case 19: // mtlo + rpsxpropSetWrite(PSX_LO); + rpsxpropSetRead(_Rs_); + break; + + case 24: // mult + case 25: // multu + case 26: // div + case 27: // divu + rpsxpropSetWrite(PSX_LO); + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpsxpropSetWrite(_Rd_); + if( _Rs_ ) rpsxpropSetRead(_Rs_); + if( _Rt_ ) rpsxpropSetRead(_Rt_); + break; + + default: + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + } +} + +//BLTZ , BGEZ , NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL, +//BLTZAL, BGEZAL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpsxpropSetRead(_Rs_); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpsxpropSetRead(_Rs_); + break; + + default: + assert(0); + break; + } +} + +//MFC0, NULL, CFC0, NULL, MTC0, NULL, CTC0, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//RFE , NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + case 2: // cfc0 + rpsxpropSetWrite(_Rt_); + break; + + case 4: // mtc0 + case 6: // ctc0 + rpsxpropSetRead(_Rt_); + break; + case 16: // rfe + break; + default: + assert(0); + } +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iR5900-32.S b/branches/pcsx2_0.9.2/x86/iR5900-32.S new file mode 100644 index 0000000..5172914 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR5900-32.S @@ -0,0 +1,181 @@ +# iR5900.c assembly routines +# zerofrog(@gmail.com) +.intel_syntax + +.globl Dispatcher + .type Dispatcher, @function +Dispatcher: + # EDX contains the current pc to jump to, stack contains the jump addr to modify + push %edx + + # calc PC_GETBLOCK + # ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + mov %eax, s_pDispatchBlock + + ## check if startpc == cpuRegs.pc + mov %ecx, cpuRegs.pc + ##and %ecx, 0x5fffffff ## remove higher bits + cmp %ecx, dword ptr [%eax+BLOCKTYPE_STARTPC] + je CheckPtr + + ## recompile + push cpuRegs.pc ## pc + call recRecompile + add esp, 4 ## pop old param + mov %eax, s_pDispatchBlock +CheckPtr: + mov %eax, dword ptr [%eax] + +#ifdef _DEBUG + test %eax, %eax + jnz CallFn + # throw an exception + int 10 + +CallFn: +#endif + + and %eax, 0x0fffffff + mov %edx, %eax + pop %ecx ## x86Ptr to mod + sub %edx, %ecx + sub %edx, 4 + mov dword ptr [%ecx], %edx + + jmp %eax +} + +.globl DispatcherClear + .type DispatcherClear, @function +DisptacherClear: + ## EDX contains the current pc + mov cpuRegs.pc, %edx + push %edx + + ## calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + if( s_pDispatchBlock->startpc == cpuRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + ## already modded the code, jump to the new place + __asm { + pop %edx + add esp, 4 ## ignore stack + mov %eax, s_pDispatchBlock + mov %eax, dword ptr [%eax] + and %eax, 0x0fffffff + jmp %eax + } + } + + call recRecompile + add esp, 4 ## pop old param + mov %eax, s_pDispatchBlock + mov %eax, dword ptr [%eax] + + pop %ecx ## old fnptr + + and %eax, 0x0fffffff + mov byte ptr [%ecx], 0xe9 ## jmp32 + mov %edx, %eax + sub %edx, %ecx + sub %edx, 5 + mov dword ptr [%ecx+1], %edx + + jmp %eax + +## called when jumping to variable pc address +.globl DispatcherReg + .type DispatcherReg, @function +DispatcherReg: + + ##s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov %edx, cpuRegs.pc + mov %ecx, %edx + + shr %edx, 14 + and %edx, 0xfffffffc + add %edx, recLUT + mov %edx, dword ptr [%edx] + + mov %eax, %ecx + and %eax, 0xfffc + ## %edx += 2*%eax + shl %eax, 1 + add %edx, %eax + + ## check if startpc == cpuRegs.pc + mov %eax, %ecx + ##and %eax, 0x5fffffff ## remove higher bits + cmp %eax, dword ptr [%edx+BLOCKTYPE_STARTPC] + jne recomp + + mov %eax, dword ptr [%edx] + +#ifdef _DEBUG + test %eax, %eax + jnz CallFn2 + # throw an exception + int 10 + +CallFn2: + +#endif + + and %eax, 0x0fffffff + jmp %eax ## fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], %edx + mov dword ptr [esp], %ecx + call recRecompile + mov %edx, dword ptr [esp+4] + add esp, 8 + + mov %eax, dword ptr [%edx] + and %eax, 0x0fffffff + jmp %eax ## fnptr + +.globl _StartPerfCounter + .type _StartPerfCounter, @function +_StartPerfCounter: + + push %eax + push %ebx + push %ecx + + rdtsc + mov dword ptr [lbase], %eax + mov dword ptr [lbase + 4], %edx + + pop %ecx + pop %ebx + pop %eax + ret + +.globl _StopPerfCounter + .type _StopPerfCounter, @function +_StopPerfCounter: + + push %eax + push %ebx + push %ecx + + rdtsc + + sub %eax, dword ptr [lbase] + sbb %edx, dword ptr [lbase + 4] + mov %ecx, s_pCurBlock_ltime + add %eax, dword ptr [%ecx] + adc %edx, dword ptr [%ecx + 4] + mov dword ptr [%ecx], %eax + mov dword ptr [%ecx + 4], %edx + pop %ecx + pop %ebx + pop %eax + ret + \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iR5900.c b/branches/pcsx2_0.9.2/x86/iR5900.c new file mode 100644 index 0000000..de72d2c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR5900.c @@ -0,0 +1,3187 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 +// Recompiled completely rewritten to add block level recompilation/reg-caching/ +// liveness analysis/constant propagation Apr06 (zerofrog@gmail.com) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "VU.h" +#include "VUmicro.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +u32 maxrecmem = 0; +uptr *recLUT; + +#define X86 +#define RECSTACK_SIZE 0x00010000 + +#define EE_NUMBLOCKS (1<<15) + +static char *recMem = NULL; // the recompiled blocks will be here +static char* recStack = NULL; // stack mem +static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here +static BASEBLOCK *recROM = NULL; // and here +static BASEBLOCK *recROM1 = NULL; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr = NULL, *recStackPtr = NULL; +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_EEFreezeRegs = 0; // if set, should freeze the regs + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what pc the current block ends +static u32 s_nHasDelay = 0; + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +extern void (*recBSC[64])(); +extern void (*recBSC_co[64])(); +void rpropBSC(EEINST* prev, EEINST* pinst); + +// save states for branches +static u16 s_savex86FpuState, s_saveiCWstate; +static GPR_reg64 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_nBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +void recCOP2RecompileInst(); +int recCOP2AnalyzeBlock(u32 startpc, u32 endpc); +void recCOP2EndBlock(void); + +#ifdef _DEBUG +u32 dumplog = 0; +#else +#define dumplog 0 +#endif + +u32 pc; // recompiler pc +int branch; // set for branch +BOOL bExecBIOS = FALSE; + +#ifdef PCSX2_DEVBUILD +static LARGE_INTEGER lbase = {0}, lfinal = {0}; +static u32 s_startcount = 0; +#endif + +#ifdef __x86_64__ +char *txt0 = "RAX = %x : RDX = %x : RCX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#else +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; +#endif + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls); // reccop2.c +static void iBranchTest(u32 newpc, u32 cpuBranch); +static void recRecompile( u32 startpc ); +void recCOP22( void ); + +BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 0); +} + +//////////////////////////////////////////////////// +void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + extern char *disRNameGPR[]; + u8 used[34]; + u8 fpuused[33]; + int numused, count, fpunumused; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, pc, cpuRegs.cycle ); +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\dump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/dump%.8X.txt", startpc); +#endif + + fflush( stdout ); +// f = fopen( "dump1", "wb" ); +// fwrite( ptr, 1, (u32)x86Ptr - (u32)ptr, f ); +// fclose( f ); +// +//#ifdef __x86_64__ +// sprintf( command, "objdump -D --target=binary --architecture=i386:x86-64 dump1 > %s", filename ); +//#else +// sprintf( command, "objdump -D --target=binary --architecture=i386 dump1 > %s", filename ); +//#endif +// system( command ); + + f = fopen( filename, "w" ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR5900Fasm( PSMu32( i ), i ) ); + } + + // write the instruction info + + fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memset(fpuused, 0, sizeof(fpuused)); + fpunumused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count>26) { + case 26: // ldl + case 27: // ldr + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 55: // LD + case 30: // lq + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _eeIsLoadStoreCoIssue(u32 firstcode, u32 secondcode) +{ + switch(firstcode>>26) { + case 34: // lwl + return (secondcode>>26)==38; + case 38: // lwr + return (secondcode>>26)==34; + case 42: // swl + return (secondcode>>26)==46; + case 46: // swr + return (secondcode>>26)==42; + case 26: // ldl + return (secondcode>>26)==27; + case 27: // ldr + return (secondcode>>26)==26; + case 44: // sdl + return (secondcode>>26)==45; + case 45: // sdr + return (secondcode>>26)==44; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + + // stores + case 40: case 41: case 43: + case 63: // sd + return (secondcode>>26)==(firstcode>>26); + + case 30: // lq + case 31: // sq + case 49: // lwc1 + case 57: // swc1 + case 54: // lqc2 + case 62: // sqc2 + return (secondcode>>26)==(firstcode>>26)&&cpucaps.hasStreamingSIMDExtensions; + } + return 0; +} + +u8 _eeIsLoadStoreCoX(u32 tempcode) +{ + switch( tempcode>>26 ) { + case 30: case 31: case 49: case 57: case 55: case 63: + return 1; + } + return 0; +} + +void _eeFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( pc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && GPR_IS_CONST1(i) ) _flushConstReg(i); + else { + _deleteMMXreg(MMX_GPR+i, 1); + _deleteGPRtoXMMreg(i, 1); + } + } + + //TODO when used info is done for FPU and VU0 + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse && xmmregs[i].type != XMMTYPE_GPRREG ) + _freeXMMreg(i); + } +} + +u32* _eeGetConstReg(int reg) +{ + assert( GPR_IS_CONST1( reg ) ); + + if( g_cpuFlushedConstReg & (1<regs[xmmregs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, xmmregs[i].reg) ) { + _freeXMMreg(i); + xmmregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushMMXunused() +{ + int i; + for (i=0; iregs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR) ) { + _freeMMXreg(i); + mmxregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_cpuHasConstReg & (1<regs[reg]&EEINST_LASTUSE) ) { + if( mmx ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + return _allocGPRtoXMMreg(-1, reg, mode); + } + + return -1; +} + +#define PROCESS_EE_SETMODES(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo +// core of reg caching +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) +{ + int mmreg1, mmreg2, mmreg3, mmtemp, moded; + + if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; + + if( xmminfo&XMMINFO_WRITED) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( xmminfo & XMMINFO_WRITED ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + } + if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededMMXreg(MMX_GPR+MMX_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededMMXreg(MMX_GPR+MMX_HI); + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_MMX) { +// mmreg1 = _allocMMXreg(-1, MMX_GPR+vreg, MODE_READ); +// _addNeededMMXreg(MMX_GPR+vreg); +// } + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(vreg)) ) { + if( EEINST_ISLIVEMMX(vreg) ) { + _freeMMXreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_MMX; + + // do it all in mmx + if( mmreg1 < 0 ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + // check for last used, if so don't alloc a new MMX reg + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_)) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg2].inuse = 1; + mmxregs[mmreg2].reg = _Rd_; + mmxregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_)) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); + _addNeededGPRtoXMMreg(_Rs_); + _addNeededGPRtoXMMreg(_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { +// mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); +// _addNeededGPRtoXMMreg(vreg); +// } + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { + _freeXMMreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_XMM; + + // do it all in xmm + if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg2].inuse = 1; + xmmregs[mmreg2].reg = _Rd_; + xmmregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2); + + // don't delete, fn will take care of them +// if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { +// _deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0); +// } +// if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { +// _deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0); +// } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rt_ ) return; + + CHECK_SAVE_REG(_Rt_); + _eeProcessHasLive(_Rt_, 0); + EEINST_RESETSIGNEXT(_Rt_); + + if( GPR_IS_CONST1(_Rs_) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _deleteGPRtoXMMreg(_Rt_, 2); + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rt_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + if( EEINST_ISLIVEMMX(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rt_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rt_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rt_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rt_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rt_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rd_ ) return; + + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + + if( GPR_IS_CONST1(_Rt_) ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + if( EEINST_ISLIVEMMX(_Rt_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 2); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt op rs +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode) +{ + assert(0); + // for now, don't support xmm + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + multicode(0); +} + +// Simple Code Templates // + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 0); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rt_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rt_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 0); + + if( GPR_IS_CONST1(_Rs_) ) { + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST1(_Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT) +{ + assert(0); + // for now, don't support xmm + if( MULT ) { + CHECK_SAVE_REG(_Rd_); + _deleteGPRtoXMMreg(_Rd_, 0); + } + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTS); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + multicode(0); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); +} + +// EE XMM allocation code +int eeRecompileCodeXMM(int xmminfo) +{ + int info = PROCESS_EE_XMM; + + // save state + if( xmminfo & XMMINFO_WRITED ) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + // flush consts + if( xmminfo & XMMINFO_READT ) { + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + } + if( xmminfo & XMMINFO_READS) { + if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rs_); + } + } + + if( xmminfo & XMMINFO_WRITED ) { + GPR_DEL_CONST(_Rd_); + } + + // add needed + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + _addNeededGPRtoXMMreg(XMMGPR_LO); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + _addNeededGPRtoXMMreg(XMMGPR_HI); + } + if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); + if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); + if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); + + // allocate + if( xmminfo & XMMINFO_READS) { + int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); + } + if( xmminfo & XMMINFO_READT) { + int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); + } + + if( xmminfo & XMMINFO_WRITED ) { + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); + + int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); + + if( regd < 0 ) { + if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(EEREC_T); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_T].inuse = 1; + xmmregs[EEREC_T].reg = _Rd_; + xmmregs[EEREC_T].mode = readd; + regd = EEREC_T; + } + else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(EEREC_S); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_S].inuse = 1; + xmmregs[EEREC_S].reg = _Rd_; + xmmregs[EEREC_S].mode = readd; + regd = EEREC_S; + } + else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); + } + + info |= PROCESS_EE_SET_D(regd); + } + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); + info |= PROCESS_EE_LO; + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); + info |= PROCESS_EE_HI; + } + return info; +} + +// EE COP1(FPU) XMM allocation code +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define PROCESS_EE_SETMODES_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// rd = rs op rt +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo) +{ + int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; + + if( EE_FPU_REGCACHING && cpucaps.hasStreamingSIMDExtensions ) { + int info = PROCESS_EE_XMM; + + if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); + if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); + if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); + + if( xmminfo & XMMINFO_READT ) { + if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); + else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); + } + + if( xmminfo & XMMINFO_READS ) { + if( (!(xmminfo&XMMINFO_READT)||mmregt>=0) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) + mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); + } + + if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES_XMM(mmregs); + if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET_XMM(mmregt); + + if( xmminfo & XMMINFO_READD ) { + assert( xmminfo & XMMINFO_WRITED ); + mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); + } + + if( xmminfo & XMMINFO_READACC ) { + if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); + else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); + } + + if( xmminfo & XMMINFO_WRITEACC ) { + + // check for last used, if so don't alloc a new XMM reg + int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); + + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); + + if( mmregacc < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = 0; + xmmregs[mmregt].mode = readacc; + xmmregs[mmregt].type = XMMTYPE_FPACC; + mmregacc = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = 0; + xmmregs[mmregs].mode = readacc; + xmmregs[mmregs].type = XMMTYPE_FPACC; + mmregacc = mmregs; + } + else mmregacc = _allocFPACCtoXMMreg(-1, readacc); + } + + xmmregs[mmregacc].mode |= MODE_WRITE; + } + else if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); + + if( mmregd < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = _Fd_; + xmmregs[mmregt].mode = readd; + mmregd = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = _Fd_; + xmmregs[mmregs].mode = readd; + mmregd = mmregs; + } + else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { + if( FPUINST_ISLIVE(XMMFPU_ACC) ) + _freeXMMreg(mmregacc); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregacc].inuse = 1; + xmmregs[mmregacc].reg = _Fd_; + xmmregs[mmregacc].mode = readd; + xmmregs[mmregacc].type = XMMTYPE_FPREG; + mmregd = mmregacc; + } + else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + } + } + + assert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); + + if( xmminfo & XMMINFO_WRITED ) { + assert( mmregd >= 0 ); + info |= PROCESS_EE_SET_D(mmregd); + } + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { + if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; + else assert( !(xmminfo&XMMINFO_WRITEACC)); + } + + if( xmminfo & XMMINFO_READS ) { + if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; + } + if( xmminfo & XMMINFO_READT ) { + if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; + } + + // at least one must be in xmm + if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { + assert( mmregs >= 0 || mmregt >= 0 ); + } + + xmmcode(info); + _clearNeededXMMregs(); + return; + } + + if( xmminfo & XMMINFO_READS ) _deleteFPtoXMMreg(_Fs_, 0); + if( xmminfo & XMMINFO_READT ) _deleteFPtoXMMreg(_Ft_, 0); + if( xmminfo & (XMMINFO_READD|XMMINFO_WRITED) ) _deleteFPtoXMMreg(_Fd_, 0); + if( xmminfo & (XMMINFO_READACC|XMMINFO_WRITEACC) ) _deleteFPtoXMMreg(XMMFPU_ACC, 0); + fpucode(0); +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +//////////////////////////////////////////////////// +extern u8 g_MACFlagTransform[256]; // for vus + +u32 g_sseMXCSR = 0x9f80; // disable all exception, round to 0, flush to 0 +u32 g_sseVUMXCSR = 0xff80; +void SetCPUState() +{ + // SSE STATE // + // WARNING: do not touch unless you know what you are doing + + if( cpucaps.hasStreamingSIMDExtensions ) { + // do NOT set Denormals-Are-Zero flag (charlie and chocfac messes up) + //g_sseMXCSR = 0x9f80; // changing the rounding mode to 0x2000 (near) kills grandia III! + // changing the rounding mode to 0x0000 or 0x4000 totally kills gitaroo + // so... grandia III wins (you can change individual games with the 'roundmode' patch command) + + __asm ldmxcsr g_sseMXCSR // set the new sse control + //g_sseVUMXCSR = g_sseMXCSR|0x6000; + } +} + +extern BOOL install_my_handler(); + +#define REC_CACHEMEM 0x01000000 + +int recInit( void ) +{ + int i; + const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + + recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 ); + memset( recLUT, 0, 0x010000 * sizeof(uptr) ); + recMem = (char*)SysMmap(0, REC_CACHEMEM); + + // 32 alignment necessary + recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK)); + recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK)); + recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK)); + recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16); + recStack = (char*)malloc( RECSTACK_SIZE ); + + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize ); + + if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) { + SysMessage( _( "Error allocating memory" ) ); + return -1; + } + + for ( i = 0x0000; i < 0x0200; i++ ) + { + recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0040; i++ ) + { + recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0004; i++ ) + { + recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + } + + memcpy( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); + memcpy( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); + + memset(recMem, 0xcd, REC_CACHEMEM); + memset(recStack, 0, RECSTACK_SIZE); + + // SSE3 detection, manually create the code + x86SetPtr(recMem); + SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0); + RET(); + + cpucaps.hasStreamingSIMD3Extensions = 1; + __try { + __asm call recMem + } + __except(EXCEPTION_EXECUTE_HANDLER) { + cpucaps.hasStreamingSIMD3Extensions = 0; + +#ifdef WIN32_VIRTUAL_MEM + // necessary since can potentially kill the custom handler + install_my_handler(); +#endif + } + + SysPrintf( "x86Init: \n" ); + SysPrintf( "\tCPU vender name = %s\n", cpuinfo.x86ID ); + SysPrintf( "\tFamilyID = %x\n", cpuinfo.x86StepID ); + SysPrintf( "\tx86Family = %s\n", cpuinfo.x86Fam ); + SysPrintf( "\tCPU speed = %d.%03d Ghz\n", cpuinfo.cpuspeed / 1000, cpuinfo.cpuspeed%1000); + SysPrintf( "\tx86PType = %s\n", cpuinfo.x86Type ); + SysPrintf( "\tx86Flags = %8.8x\n", cpuinfo.x86Flags ); + SysPrintf( "\tx86EFlags = %8.8x\n", cpuinfo.x86EFlags ); + SysPrintf( "Features: \n" ); + SysPrintf( "\t%sDetected MMX\n", cpucaps.hasMultimediaExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE\n", cpucaps.hasStreamingSIMDExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE2\n", cpucaps.hasStreamingSIMD2Extensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE3\n", cpucaps.hasStreamingSIMD3Extensions ? "" : "Not " ); + + if ( cpuinfo.x86ID[0] == 'A' ) //AMD cpu + { + SysPrintf( " Extented AMD Features: \n" ); + SysPrintf( "\t%sDetected MMX2\n", cpucaps.hasMultimediaExtensionsExt ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW\n", cpucaps.has3DNOWInstructionExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW2\n", cpucaps.has3DNOWInstructionExtensionsExt ? "" : "Not " ); + } + if ( !( cpucaps.hasMultimediaExtensions ) ) + { + SysMessage( _( "Processor doesn't supports MMX, can't run recompiler without that" ) ); + return -1; + } + + x86FpuState = FPU_STATE; + + SuperVUInit(-1); + + for(i = 0; i < 256; ++i) { + g_MACFlagTransform[i] = macarr[i>>4]|(macarr[i&15]<<4); + } + + SetCPUState(); + + return 0; +} + +//////////////////////////////////////////////////// +void recReset( void ) { +#ifdef PCSX2_DEVBUILD + SysPrintf("EE Recompiler data reset\n"); +#endif + + s_nNextBlock = 0; + maxrecmem = 0; + memset( recRAM, 0, sizeof(BASEBLOCK)/4*0x02000000 ); + memset( recROM, 0, sizeof(BASEBLOCK)/4*0x00400000 ); + memset( recROM1, 0, sizeof(BASEBLOCK)/4*0x00040000 ); + memset( recBlocks, 0, sizeof(BASEBLOCKEX)*EE_NUMBLOCKS ); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); + ResetBaseBlockEx(0); + + __asm emms + +#ifdef _DEBUG + // don't clear since save states won't work + //memset(recMem, 0xcd, REC_CACHEMEM); +#endif + + recPtr = recMem; + recStackPtr = recStack; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +void recShutdown( void ) +{ + if ( recMem == NULL ) { + return; + } + + _aligned_free( recLUT ); + SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL; + _aligned_free( recRAM ); recRAM = NULL; + _aligned_free( recROM ); recROM = NULL; + _aligned_free( recROM1 ); recROM1 = NULL; + _aligned_free( recBlocks ); recBlocks = NULL; + free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0; + + SuperVUDestroy(-1); + + x86Shutdown( ); +} + +void recEnableVU0micro(int enable) { +} + +void recEnableVU1micro(int enable) { +} + +#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code +static u32 s_uSaveESP = 0, s_uSaveEBP; + +static void execute( void ) +{ +#ifdef _DEBUG + u8* fnptr; + u32 oldesi; +#else + R5900FNPTR pfn; +#endif + BASEBLOCK* pblock = PC_GETBLOCK(cpuRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != cpuRegs.pc ) { + recRecompile(cpuRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + g_EEFreezeRegs = 1; + + // skip the POPs +#ifdef _DEBUG + fnptr = (u8*)pblock->pFnptr; + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + mov s_uSaveEBP, ebp + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + pfn = ((R5900FNPTR)pblock->pFnptr); + // use call instead of pfn() + //__asm mov s_uSaveEBP, ebp + __asm call pfn + +#endif + + g_EEFreezeRegs = 0; +} + +void recStep( void ) { +} + +void recExecute( void ) { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);//ABOVE_NORMAL_PRIORITY_CLASS); + //SetThreadAffinityMask(GetCurrentThread(), 0); + if( Config.Options & PCSX2_EEREC ) Config.Options |= PCSX2_COP2REC; + + for (;;) + execute(); +} + +void recExecuteBlock( void ) { + execute(); +} + +//////////////////////////////////////////////////// +extern u32 g_nextBranchCycle; + +u32 g_lastpc = 0; +u32 g_EEDispatchTemp; +u32 s_pCurBlock_ltime; + +#ifdef _MSC_VER + +// jumped to when invalid pc address +__declspec(naked,noreturn) void Dispatcher() +{ + // EDX contains the current pc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == cpuRegs.pc + mov ecx, cpuRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push cpuRegs.pc // pc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_EEDispatchTemp, eax + assert( g_EEDispatchTemp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new pc +// and eax, 0x0fffffff +// mov ecx, cpuRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void DispatcherClear() +{ + // EDX contains the current pc + __asm mov cpuRegs.pc, edx + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + if( s_pDispatchBlock->startpc == cpuRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable pc address +__declspec(naked,noreturn) void DispatcherReg() +{ + __asm { + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov edx, cpuRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == cpuRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_EEDispatchTemp, eax + assert( g_EEDispatchTemp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +#ifdef PCSX2_DEVBUILD +__declspec(naked) void _StartPerfCounter() +{ + __asm { + push eax + push ebx + push ecx + + rdtsc + mov dword ptr [offset lbase], eax + mov dword ptr [offset lbase + 4], edx + + pop ecx + pop ebx + pop eax + ret + } +} + +__declspec(naked) void _StopPerfCounter() +{ + __asm { + push eax + push ebx + push ecx + + rdtsc + + sub eax, dword ptr [offset lbase] + sbb edx, dword ptr [offset lbase + 4] + mov ecx, s_pCurBlock_ltime + add eax, dword ptr [ecx] + adc edx, dword ptr [ecx + 4] + mov dword ptr [ecx], eax + mov dword ptr [ecx + 4], edx + pop ecx + pop ebx + pop eax + ret + } +} + +#endif // PCSX2_DEVBUILD + +#ifdef __cplusplus +extern "C" { +#endif + +void Dispatcher(); +void DispatcherClear(); +void DispatcherReg(); +void _StartPerfCounter(); +void _StopPerfCounter(); + +#ifdef __cplusplus +} +#endif + +#else // _MSC_VER + +#endif + +//////////////////////////////////////////////////// +void recClear64(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 16)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); +} + +void recClear128(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 32)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); + if( left > 2 && *(u32*)(p+2) ) recClearMem(p+2); + if( left > 3 && *(u32*)(p+3) ) recClearMem(p+3); +} + +void recClear( u32 Addr, u32 Size ) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + REC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void recClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms + if (cpucaps.has3DNOWInstructionExtensions) __asm femms + else __asm emms + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + recClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PC_GETBLOCK(p->startpc); + pexblock = PC_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 0); + pexblock->size = 0; + pexblock->startpc = 0; +} + +// check for end of bios +void CheckForBIOSEnd() +{ + MOV32MtoR(EAX, (int)&cpuRegs.pc); + + CMP32ItoR(EAX, 0x00200008); + j8Ptr[0] = JE8(0); + + CMP32ItoR(EAX, 0x00100008); + j8Ptr[1] = JE8(0); + + // return + j8Ptr[2] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[1] ); + + // bios end + RET2(); + + x86SetJ8( j8Ptr[2] ); +} + +static int *s_pCode; + +void SetBranchReg( u32 reg ) +{ + branch = 1; + + if( reg != 0xffffffff ) { +// if( GPR_IS_CONST1(reg) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[reg].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+reg, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ reg ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, reg); + + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + } + +// CMP32ItoM((u32)&cpuRegs.pc, 0); +// j8Ptr[5] = JNE8(0); +// CALLFunc((u32)tempfn); +// x86SetJ8( j8Ptr[5] ); + + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void SetBranchImm( u32 imm ) +{ + u32* ptr; + branch = 1; + + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&cpuRegs.pc, imm ); + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(imm, imm <= pc); + if( bExecBIOS ) CheckForBIOSEnd(); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)Dispatcher - ( (u32)x86Ptr + 5 )); +} + +void SaveBranchState() +{ + s_savex86FpuState = x86FpuState; + s_saveiCWstate = iCWstate; + s_savenBlockCycles = s_nBlockCycles; + s_saveConstGPRreg = 0xffffffff; // indicate searching + s_saveHasConstReg = g_cpuHasConstReg; + s_saveFlushedConstReg = g_cpuFlushedConstReg; + s_psaveInstInfo = g_pCurInstInfo; + s_saveRegHasLive1 = g_cpuRegHasLive1; + s_saveRegHasSignExt = g_cpuRegHasSignExt; + + // save all mmx regs + memcpy(s_saveMMXregs, mmxregs, sizeof(mmxregs)); + memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); +} + +void LoadBranchState() +{ + x86FpuState = s_savex86FpuState; + iCWstate = s_saveiCWstate; + s_nBlockCycles = s_savenBlockCycles; + + if( s_saveConstGPRreg != 0xffffffff ) { + assert( s_saveConstGPRreg > 0 ); + + // make sure right GPR was saved + assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<ltime); + CALLFunc((u32)_StopPerfCounter); + } +#endif +} + +#define USE_FAST_BRANCHES 0 + +//void testfpu() +//{ +// int i; +// for(i = 0; i < 32; ++i ) { +// if( fpuRegs.fpr[i].UL== 0x7f800000 || fpuRegs.fpr[i].UL == 0xffc00000) { +// SysPrintf("bad fpu: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// +// if( VU0.VF[i].UL[0] == 0xffc00000 || //(VU0.VF[i].UL[1]&0xffc00000) == 0xffc00000 || +// VU0.VF[i].UL[0] == 0x7f800000) { +// SysPrintf("bad vu0: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// } +//} + +//static void cleanup() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +static void iBranchTest(u32 newpc, u32 cpuBranch) +{ +#ifdef PCSX2_DEVBUILD + if( s_startcount ) { + StopPerfCounter(); + ADD32ItoM( (u32)&s_pCurBlockEx->visited, 1 ); + } +#endif + +#ifdef _DEBUG + //CALLFunc((u32)testfpu); +#endif + + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&cpuRegs.cycle); + ADD32ItoR(ECX, s_nBlockCycles*9/8); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI + MOV32RtoM((int)&cpuRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + return; + } + + SUB32MtoR(ECX, (int)&g_nextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + // has to be in the middle of Save/LoadBranchState + CALLFunc( (int)cpuBranchTest ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&cpuRegs.pc, newpc); + JNE32((u32)DispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + + +//////////////////////////////////////////////////// +#ifndef CP2_RECOMPILE + +REC_SYS(COP2); + +#else + +void recCOP2( void ) +{ +#ifdef CPU_LOG + CPU_LOG( "Recompiling COP2:%s\n", disR5900Fasm( cpuRegs.code, cpuRegs.pc ) ); +#endif + + if ( !cpucaps.hasStreamingSIMDExtensions ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + g_cpuHasConstReg = 1; // reset all since COP2 can change regs + CALLFunc( (u32)COP2 ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + } + else + { + recCOP22( ); + } +} + +#endif + +//////////////////////////////////////////////////// +void recSYSCALL( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)SYSCALL ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +void recBREAK( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BREAK ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + RET(); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +static void checkcodefn() +{ + int pctemp; + + __asm mov pctemp, eax + SysPrintf("code changed! %x\n", pctemp); + assert(0); +} + +void checkpchanged(u32 startpc) +{ + assert(0); +} + +//#ifdef _DEBUG +//#define CHECK_XMMCHANGED() CALLFunc((u32)checkxmmchanged); +//#else +//#define CHECK_XMMCHANGED() +//#endif +// +//static void checkxmmchanged() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +u32 recompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PC_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pc == pblock->startpc ) + return 0; + } + + return 1; +} + +void recompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + int i, count; + + BASEBLOCK* pblock = PC_GETBLOCK(pc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && pc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == pc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + recClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", pc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSM( pc ); + assert(s_pCode); + +#ifdef _DEBUG + MOV32ItoR(EAX, pc); +#endif + + cpuRegs.code = *(int *)s_pCode; + s_nBlockCycles++; + pc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, cpuRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, pc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +// +// if( !delayslot ) { +// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); +// j8Ptr[0] = JB8(0); +// CMP32ItoM((u32)&cpuRegs.pc, pc); +// j8Ptr[1] = JA8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[ 0 ] ); +// x86SetJ8( j8Ptr[ 1 ] ); +// PUSH32I(s_pCurBlockEx->startpc); +// CALLFunc((u32)checkpchanged); +// ADD32ItoR(ESP, 4); +// x86SetJ8( j8Ptr[ 2 ] ); +// } +//#endif + + g_pCurInstInfo++; + + // reorder register priorities +// for(i = 0; i < X86REGS; ++i) { +// if( x86regs[i].inuse ) { +// if( count > 0 ) mmxregs[i].counter = 1000-count; +// else mmxregs[i].counter = 0; +// } +// } + + for(i = 0; i < MMXREGS; ++i) { + if( mmxregs[i].inuse ) { + assert( MMX_ISGPR(mmxregs[i].reg) ); + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR); + if( count > 0 ) mmxregs[i].counter = 1000-count; + else mmxregs[i].counter = 0; + } + } + + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); + if( count > 0 ) xmmregs[i].counter = 1000-count; + else xmmregs[i].counter = 0; + } + } + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + +#ifdef WIN32_VIRTUAL_MEM + if( g_pCurInstInfo->numpeeps > 1 ) { + switch(cpuRegs.code>>26) { + case 30: recLQ_coX(g_pCurInstInfo->numpeeps); break; + case 31: recSQ_coX(g_pCurInstInfo->numpeeps); break; + case 49: recLWC1_coX(g_pCurInstInfo->numpeeps); break; + case 57: recSWC1_coX(g_pCurInstInfo->numpeeps); break; + case 55: recLD_coX(g_pCurInstInfo->numpeeps); break; + case 63: recSD_coX(g_pCurInstInfo->numpeeps); break; + default: + assert(0); + } + + pc += g_pCurInstInfo->numpeeps*4; + s_nBlockCycles += g_pCurInstInfo->numpeeps; + g_pCurInstInfo += g_pCurInstInfo->numpeeps; + } + else { + recBSC_co[cpuRegs.code>>26](); + pc += 4; + s_nBlockCycles++; + g_pCurInstInfo++; + } +#else + assert(0); +#endif + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + + // if this instruction is a jump or a branch, exit right away + if( delayslot ) { + switch(cpuRegs.code>>26) { + case 1: + switch(_Rt_) { + case 0: case 1: case 2: case 3: case 0x10: case 0x11: case 0x12: case 0x13: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + return; + } + break; + + case 2: case 3: case 4: case 5: case 6: case 7: case 0x14: case 0x15: case 0x16: case 0x17: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + return; + } + } + recBSC[ cpuRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //if( !_flushUnusedConstReg() ) { + int flushed = 0; + if( _getNumMMXwrite() > 3 ) flushed = _flushMMXunused(); + if( !flushed && _getNumXMMwrite() > 2 ) _flushXMMunused(); + s_bFlushReg = !flushed; +// } +// else s_bFlushReg = 0; + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + //CHECK_XMMCHANGED(); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + +// _freeXMMregs(); +// _freeMMXregs(); +// _flushCachedRegs(); +// g_cpuHasConstReg = 0; +} + +//__declspec(naked) void iDummyBlock() +//{ +//// g_lastpc = cpuRegs.pc; +//// +//// do { +//// cpuRegs.cycle = g_nextBranchCycle; +//// cpuBranchTest(); +//// } while(g_lastpc == cpuRegs.pc); +//// +//// __asm jmp DispatcherReg +// __asm { +//RepDummy: +// add cpuRegs.cycle, 9 +// call cpuBranchTest +// cmp cpuRegs.pc, 0x81fc0 +// je RepDummy +// jmp DispatcherReg +// } +//} + +//////////////////////////////////////////////////// +#include "R3000A.h" +#include "PsxCounters.h" +#include "psxmem.h" +extern tIPU_BP g_BP; + +extern u32 psxdump; +extern u32 psxNextCounter, psxNextsCounter; +extern void iDumpPsxRegisters(u32 startpc, u32 temp); +extern Counter counters[6]; +void iDumpRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + extern char *disRNameGPR[]; + + __Log("%sreg: %x %x %x %x %x\n", pstr, startpc, cpuRegs.interrupt, *(int*)(psxM+0x6e832), *(int*)(PS2MEM_BASE+0x18ef00), *(int*)(PS2MEM_BASE+0x131ed82)); + for(i = 1; i < 32; ++i) __Log("%s: %x_%x_%x_%x\n", disRNameGPR[i], cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x\n", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x\n", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x\n", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x\n", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + __Log("%svfACC: %x %x %x %x\n", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x\n", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x\n", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("cyc11: %x %x; vu0: %x, vu1: %x\n", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x\n", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x\n", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + } + __Log("VIF0_STAT = %x, VIF1_STAT = %x\n", psHu32(0x3800), psHu32(0x3C00)); + __Log("ipu %x %x %x %x; bp: %x %x %x %x\n", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x\n", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + for(i = 0; i < ARRAYSIZE(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x\n", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x\n", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x\n", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x\n", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +} + +extern u32 psxdump; + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0, count2 = 0; + const int skip = 0; + static int i; + + assert( !g_globalMMXSaved ); + assert( !g_globalXMMSaved ); + +#ifdef _DEBUG + //__asm stmxcsr i + //assert( i = g_sseMXCSR ); +#endif + + if( (dumplog&2) ) {//&& lastrec != g_lastpc ) { + + curcount++; + + if( curcount > skip ) { + iDumpRegisters(g_lastpc, 1); + curcount = 0; + } + + lastrec = g_lastpc; + } +} + +u32 s_recblocks[] = {0}; + +void badespfn() { + assert(0); + SysPrintf("Bad esp!\n"); +} + +#define OPTIMIZE_COP2 0//CHECK_VU0REC + +static void recRecompile( u32 startpc ) +{ + u32 i = 0; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + u32 usecop2; + +#ifdef _DEBUG + if( dumplog & 4 ) + iDumpRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) { + recReset(); + } + if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) { +#ifdef _DEBUG + SysPrintf("stack reset\n"); +#endif + recReset(); + } + + s_pCurBlock = PC_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + recClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < EE_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_pCurBlock->startpc = startpc; + + // slower +// if( startpc == 0x81fc0 ) { +// +// MOV32MtoR(ECX, (u32)&g_nextBranchCycle); +// MOV32RtoM((u32)&cpuRegs.cycle, ECX); +// //ADD32ItoR(ECX, 9); +// //ADD32ItoM((u32)&cpuRegs.cycle, 512); +// CALLFunc((u32)cpuBranchTest); +// CMP32ItoM((u32)&cpuRegs.pc, 0x81fc0); +// JE8(s_pCurBlock->pFnptr - (u32)(x86Ptr+2) ); +// JMP32((u32)DispatcherReg - (u32)(x86Ptr+5)); +// +// pc = startpc + 9*4; +// assert( (pc-startpc)>>2 <= 0xffff ); +// s_pCurBlockEx->size = (pc-startpc)>>2; +// +// for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // don't overwrite if delay slot +// if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // set the block ptr +// AddBaseBlockEx(s_pCurBlockEx, 0); +// +// if( !(pc&0x10000000) ) +// maxrecmem = max( (pc&~0xa0000000), maxrecmem ); +// +// recPtr = x86Ptr; +// return; +// } + + branch = 0; + + // reset recomp state variables + s_nBlockCycles = 0; + pc = startpc; + x86FpuState = FPU_STATE; + iCWstate = 0; + s_saveConstGPRreg = 0; + g_cpuHasConstReg = g_cpuFlushedConstReg = 1; + g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; + g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; + _recClearWritebacks(); + assert( g_cpuConstRegs[0].UD[0] == 0 ); + + _initX86regs(); + _initXMMregs(); + _initMMXregs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_lastpc, pc); + CALLFunc((u32)printfn); + +// CMP32MtoR(EBP, (u32)&s_uSaveEBP); +// j8Ptr[0] = JE8(0); +// CALLFunc((u32)badespfn); +// x86SetJ8(j8Ptr[0]); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + s_nHasDelay = 0; + + while(1) { + BASEBLOCK* pblock = PC_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + cpuRegs.code = *(int *)PSM(i); + + switch(cpuRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + s_nHasDelay = 1; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) { + // branches + if( _Rt_ == 2 && _Rt_ == 3 && _Rt_ == 18 && _Rt_ == 19 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nHasDelay = 1; + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + case 20: case 21: case 22: case 23: + + if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + + case 16: // cp0 + if( _Rs_ == 16 ) { + if( _Funct_ == 24 ) { // eret + s_nEndBlock = i+4; + goto StartRecomp; + } + } + + break; + case 17: // cp1 + case 18: // cp2 + if( _Rs_ == 8 ) { + // BC1F, BC1T, BC1FL, BC1TL + // BC2F, BC2T, BC2FL, BC2TL + if( _Rt_ >= 2 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + break; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + cpuRegs.code = *(int *)PSM(i-4); + pcur[-1] = pcur[0]; + rpropBSC(pcur-1, pcur); + pcur--; + } + } + + // analyze instructions // + { + usecop2 = 0; + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock; i += 4) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(i); + + // cop2 // + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + + if( !usecop2 ) { + // init + if( OPTIMIZE_COP2 ) { + memset(VU0.fmac,0,sizeof(VU0.fmac)); + memset(&VU0.fdiv,0,sizeof(VU0.fdiv)); + memset(&VU0.efu,0,sizeof(VU0.efu)); + } + vucycle = 0; + usecop2 = 1; + } + + VU0.code = cpuRegs.code; + _cop2AnalyzeOp(g_pCurInstInfo, OPTIMIZE_COP2); + continue; + } + + if( usecop2 ) vucycle++; + + // peephole optimizations // +#ifdef WIN32_VIRTUAL_MEM + if( i < s_nEndBlock-4 && recompileCodeSafe(i) ) { + u32 curcode = cpuRegs.code; + u32 nextcode = *(u32*)PSM(i+4); + if( _eeIsLoadStoreCoIssue(curcode, nextcode) && recBSC_co[curcode>>26] != NULL ) { + + // rs has to be the same, and cannot be just written + if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_eeLoadWritesRs(curcode) ) { + + if( _eeIsLoadStoreCoX(curcode) && ((nextcode>>16)&0x1f) != ((curcode>>21)&0x1f) ) { + // see how many stores there are + u32 j; + // use xmmregs since only supporting lwc1,lq,swc1,sq + for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + u32 nncode = *(u32*)PSM(j); + if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || + _eeLoadWritesRs(nncode)) + break; + } + + if( j > i+8 ) { + u32 num = (j-i)>>2; // number of stores that can coissue + assert( num <= XMMREGS ); + + g_pCurInstInfo[0].numpeeps = num-1; + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + + while(i < j-4) { + g_pCurInstInfo++; + g_pCurInstInfo[0].info |= EEINSTINFO_NOREC; + i += 4; + } + + continue; + } + + // fall through + } + + // unaligned loadstores + + // if LWL, check if LWR and that offsets are +3 away + switch(curcode >> 26) { + case 0x22: // LWL + if( (nextcode>>26) != 0x26 || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x26: // LWR + if( (nextcode>>26) != 0x22 || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x2a: // SWL + if( (nextcode>>26) != 0x2e || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x2e: // SWR + if( (nextcode>>26) != 0x2a || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x1a: // LDL + if( (nextcode>>26) != 0x1b || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x1b: // LWR + if( (nextcode>>26) != 0x1aa || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + + case 0x2c: // SWL + if( (nextcode>>26) != 0x2d || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x2d: // SWR + if( (nextcode>>26) != 0x2c || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + } + + // good enough + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + g_pCurInstInfo[0].numpeeps = 1; + g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; + g_pCurInstInfo++; + i += 4; + continue; + } + } + } +#endif // end peephole + } + + if( usecop2 ) { + // add necessary mac writebacks + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock-4; i += 4) { + g_pCurInstInfo++; + + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + } + } + } + } + + // perf counters // +#ifdef PCSX2_DEVBUILD + s_startcount = 0; +// if( pc+32 < s_nEndBlock ) { +// // only blocks with more than 8 insts +// //PUSH32I((u32)&lbase); +// //CALLFunc((u32)QueryPerformanceCounter); +// lbase.QuadPart = GetCPUTick(); +// s_startcount = 1; +// } +#endif + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (dumplog & 1) ) //|| usecop2 ) + iDumpBlock(startpc, recPtr); +#endif + + // finally recompile // + g_pCurInstInfo = s_pInstCache; + while (!branch && pc < s_nEndBlock) { + recompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (pc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (pc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 0); +// if( p[1].startpc == p[0].startpc + 4 ) { +// assert( p[1].pFnptr != 0 ); +// // already fn in place, so add to list +// AddBaseBlockEx(s_pCurBlockEx, 0); +// } +// else +// *(BASEBLOCKEX**)(p+1) = pex; +// } + + //PC_SETBLOCKEX(s_pCurBlock, s_pCurBlockEx); + + if( !(pc&0x10000000) ) + maxrecmem = max( (pc&~0xa0000000), maxrecmem ); + + if( branch == 2 ) { + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( branch != 3 ); + if( branch ) assert( !willbranch3 ); + else ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + + if( willbranch3 ) { + BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); + assert( pc == s_nEndBlock ); + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + } + else if( !branch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + + iFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+REC_CACHEMEM ); + assert( recStackPtr < recStack+RECSTACK_SIZE ); + assert( x86FpuState == 0 ); + + recPtr = x86Ptr; + + assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); + + if( !branch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PC_GETBLOCK(pc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != pc ) + recRecompile(pc); + + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R5900cpu recCpu = { + recInit, + recReset, + recStep, + recExecute, + recExecuteBlock, + recExecuteVU0Block, + recExecuteVU1Block, + recEnableVU0micro, + recEnableVU1micro, + recClear, + recClearVU0, + recClearVU1, + recShutdown +}; diff --git a/branches/pcsx2_0.9.2/x86/iR5900.h b/branches/pcsx2_0.9.2/x86/iR5900.h new file mode 100644 index 0000000..c3b46a4 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iR5900.h @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900_H__ +#define __IR5900_H__ + +#include "VU.h" +#include "iCore.h" + +// these might not work anymore +#define ARITHMETICIMM_RECOMPILE +#define ARITHMETIC_RECOMPILE +#define MULTDIV_RECOMPILE +#define SHIFT_RECOMPILE +#define BRANCH_RECOMPILE +#define JUMP_RECOMPILE +#define LOADSTORE_RECOMPILE +#define MOVE_RECOMPILE +#define MMI_RECOMPILE +#define MMI0_RECOMPILE +#define MMI1_RECOMPILE +#define MMI2_RECOMPILE +#define MMI3_RECOMPILE +#define FPU_RECOMPILE +#define CP0_RECOMPILE +#define CP2_RECOMPILE + +#define EE_CONST_PROP // rec2 - enables constant propagation (faster) +#define EE_FPU_REGCACHING 1 + +#define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT) + +void recClearMem(BASEBLOCK* p); +#define REC_CLEARM(mem) { \ + if ((mem) < maxrecmem && recLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PC_GETBLOCK(mem); \ + if( *(u32*)p ) recClearMem(p); \ + } \ +} \ + +extern u32 pc; +extern int branch; +extern uptr* recLUT; + +extern u32 pc; // recompiler pc +extern int branch; // set for branch +extern u32 target; // branch target +extern u16 x86FpuState; +extern u16 iCWstate; +extern u32 s_nBlockCycles; // cycles of current block recompiling + +#define REC_FUNC_INLINE( f, delreg ) \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); + +#define REC_FUNC( f, delreg ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); \ + } + +#define REC_SYS( f ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc( (u32)f ); \ + branch = 2; \ + } + +// used when processing branches +void SaveBranchState(); +void LoadBranchState(); + +void recompileNextInstruction(int delayslot); +void SetBranchReg( u32 reg ); +void SetBranchImm( u32 imm ); + +void iFlushCall(int flushtype); +void SaveCW(); +void LoadCW(); + +extern void (*recBSC[64])(); +extern void (*recSPC[64])(); +extern void (*recREG[32])(); +extern void (*recCP0[32])(); +extern void (*recCP0BC0[32])(); +extern void (*recCP0C0[64])(); +extern void (*recCP1[32])(); +extern void (*recCP1BC1[32])(); +extern void (*recCP1S[64])(); +extern void (*recCP1W[64])(); +extern void (*recMMIt[64])(); +extern void (*recMMI0t[32])(); +extern void (*recMMI1t[32])(); +extern void (*recMMI2t[32])(); +extern void (*recMMI3t[32])(); + +u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg + +void _eeFlushAllUnused(); +void _eeOnWriteReg(int reg, int signext); + +// totally deletes from const, xmm, and mmx entries +// if flush is 1, also flushes to memory +// if 0, only flushes if not an xmm reg (used when overwriting lower 64bits of reg) +void _deleteEEreg(int reg, int flush); + +// allocates memory on the instruction size and returns the pointer +void* recAllocStackMem(int size, int align); + +////////////////////////////////////// +// Templates for code recompilation // +////////////////////////////////////// +typedef void (*R5900FNPTR)(); +typedef void (*R5900FNPTR_INFO)(int info); + +#define EERECOMPILE_CODE0(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeRecompileCode0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_, xmminfo); \ +} \ + +#define EERECOMPILE_CODEX(codename, fn) \ +void rec##fn(void) \ +{ \ + codename(rec##fn##_const, rec##fn##_); \ +} \ + +// +// MMX/XMM caching helpers +// + +// rd = rs op rt +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo); +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rt op rs (SPECIAL) +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define EERECOMPILE_CONSTCODE0(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_); \ +} \ + +// rt = rs op imm16 +#define EERECOMPILE_CONSTCODE1(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst1(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op sa +#define EERECOMPILE_CONSTCODE2(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst2(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op rs +#define EERECOMPILE_CONSTCODESPECIAL(fn, mult) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConstSPECIAL(rec##fn##_const, rec##fn##_, mult); \ +} \ + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode); +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT); + +// XMM caching helpers +#define XMMINFO_READLO 0x01 +#define XMMINFO_READHI 0x02 +#define XMMINFO_WRITELO 0x04 +#define XMMINFO_WRITEHI 0x08 +#define XMMINFO_WRITED 0x10 +#define XMMINFO_READD 0x20 +#define XMMINFO_READS 0x40 +#define XMMINFO_READT 0x80 +#define XMMINFO_READD_LO 0x100 // if set and XMMINFO_READD is set, reads only low 64 bits of D +#define XMMINFO_READACC 0x200 +#define XMMINFO_WRITEACC 0x400 + +#define CPU_SSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_SSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_FPUSSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeFPURecompileCodeXMM(xmminfo); \ + +#define CPU_SSE_XMMCACHE_END \ + _clearNeededXMMregs(); \ + return; \ + } \ + +#define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeFPURecompileCode(rec##fn##_xmm, rec##fn##_, xmminfo); \ +} \ + +// rd = rs op rt (all regs need to be in xmm) +int eeRecompileCodeXMM(int xmminfo); +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo); + +#endif // __IR5900_H__ diff --git a/branches/pcsx2_0.9.2/x86/iVU0micro.c b/branches/pcsx2_0.9.2/x86/iVU0micro.c new file mode 100644 index 0000000..12b09c8 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVU0micro.c @@ -0,0 +1,790 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +static VURegs * const VU = (VURegs*)&VU0; + +//u32 vu0time = 0; +//static LARGE_INTEGER vu0base, vu0final; + +#ifdef PCSX2_DEVBUILD +extern u32 vudump; +#endif + +#define VF_VAL(x) ((x==0x80000000)?0:(x)) +static u32 vuprogcount = 0; +void iDumpVU0Registers() +{ + int i; + + for(i = 1; i < 32; ++i) { + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), + VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F); + else if( i == REG_MAC_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0xff); + else if( i == REG_STATUS_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0x03); + else if( i == REG_CLIP_FLAG ) __Log("0\n"); + else __Log("%x\n", VU0.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); +} + +void recExecuteVU0Block( void ) +{ + //SysPrintf("executeVU0 %x\n", VU0.VI[ REG_TPC ].UL); + //QueryPerformanceCounter(&vu0base); + + assert( VU0.VI[REG_VPU_STAT].UL & 1 ); + +#ifdef _DEBUG + vuprogcount++; + +// __Log("VU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); + +// vudump |= 0x10; +// vudump |= 0x80; + + if( (vudump&0x80) && !CHECK_VU0REC ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + + //while( (VU0.VI[ REG_VPU_STAT ].UL&1) ) { + if( CHECK_VU0REC) { + FreezeXMMRegs(1); + SuperVUExecuteProgram(VU0.VI[ REG_TPC ].UL, 0); + } + else { + intExecuteVU0Block(); + } + //} + +// __Log("eVU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); +// QueryPerformanceCounter(&vu0final); +// vu0time += (u32)(vu0final.QuadPart-vu0final.QuadPart); +} + +void recClearVU0( u32 Addr, u32 Size ) +{ + if( CHECK_VU0REC ) { + SuperVUClear(Addr, Size*4, 0); + } +} + +void (*recVU0_LOWER_OPCODE[128])() = { + recVU0MI_LQ , recVU0MI_SQ , recVU0unknown , recVU0unknown, + recVU0MI_ILW , recVU0MI_ISW , recVU0unknown , recVU0unknown, + recVU0MI_IADDIU, recVU0MI_ISUBIU, recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_FCEQ , recVU0MI_FCSET , recVU0MI_FCAND, recVU0MI_FCOR, /* 0x10 */ + recVU0MI_FSEQ , recVU0MI_FSSET , recVU0MI_FSAND, recVU0MI_FSOR, + recVU0MI_FMEQ , recVU0unknown , recVU0MI_FMAND, recVU0MI_FMOR, + recVU0MI_FCGET , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_B , recVU0MI_BAL , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0MI_JR , recVU0MI_JALR , recVU0unknown , recVU0unknown, + recVU0MI_IBEQ , recVU0MI_IBNE , recVU0unknown , recVU0unknown, + recVU0MI_IBLTZ , recVU0MI_IBGTZ , recVU0MI_IBLEZ, recVU0MI_IBGEZ, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x40*/ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x50 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x60 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x70 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, +}; + +void (*recVU0LowerOP_T3_00_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MOVE , recVU0MI_LQI , recVU0MI_DIV , recVU0MI_MTIR, + recVU0MI_RNEXT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_MFP , recVU0unknown , recVU0unknown, + recVU0MI_ESADD , recVU0MI_EATANxy, recVU0MI_ESQRT, recVU0MI_ESIN, +}; + +void (*recVU0LowerOP_T3_01_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MR32 , recVU0MI_SQI , recVU0MI_SQRT , recVU0MI_MFIR, + recVU0MI_RGET , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0MI_XITOP, recVU0unknown, + recVU0MI_ERSADD, recVU0MI_EATANxz, recVU0MI_ERSQRT, recVU0MI_EATAN, +}; + +void (*recVU0LowerOP_T3_10_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_LQD , recVU0MI_RSQRT, recVU0MI_ILWR, + recVU0MI_RINIT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ELENG , recVU0MI_ESUM , recVU0MI_ERCPR, recVU0MI_EEXP, +}; + +void (*recVU0LowerOP_T3_11_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_SQD , recVU0MI_WAITQ, recVU0MI_ISWR, + recVU0MI_RXOR , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ERLENG, recVU0unknown , recVU0MI_WAITP, recVU0unknown, +}; + +void (*recVU0LowerOP_OPCODE[64])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_IADD , recVU0MI_ISUB , recVU0MI_IADDI, recVU0unknown, /* 0x30 */ + recVU0MI_IAND , recVU0MI_IOR , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP_T3_00, recVU0LowerOP_T3_01, recVU0LowerOP_T3_10, recVU0LowerOP_T3_11, +}; + +void (*recVU0_UPPER_OPCODE[64])() = { + recVU0MI_ADDx , recVU0MI_ADDy , recVU0MI_ADDz , recVU0MI_ADDw, + recVU0MI_SUBx , recVU0MI_SUBy , recVU0MI_SUBz , recVU0MI_SUBw, + recVU0MI_MADDx , recVU0MI_MADDy , recVU0MI_MADDz , recVU0MI_MADDw, + recVU0MI_MSUBx , recVU0MI_MSUBy , recVU0MI_MSUBz , recVU0MI_MSUBw, + recVU0MI_MAXx , recVU0MI_MAXy , recVU0MI_MAXz , recVU0MI_MAXw, /* 0x10 */ + recVU0MI_MINIx , recVU0MI_MINIy , recVU0MI_MINIz , recVU0MI_MINIw, + recVU0MI_MULx , recVU0MI_MULy , recVU0MI_MULz , recVU0MI_MULw, + recVU0MI_MULq , recVU0MI_MAXi , recVU0MI_MULi , recVU0MI_MINIi, + recVU0MI_ADDq , recVU0MI_MADDq , recVU0MI_ADDi , recVU0MI_MADDi, /* 0x20 */ + recVU0MI_SUBq , recVU0MI_MSUBq , recVU0MI_SUBi , recVU0MI_MSUBi, + recVU0MI_ADD , recVU0MI_MADD , recVU0MI_MUL , recVU0MI_MAX, + recVU0MI_SUB , recVU0MI_MSUB , recVU0MI_OPMSUB, recVU0MI_MINI, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0_UPPER_FD_00, recVU0_UPPER_FD_01, recVU0_UPPER_FD_10, recVU0_UPPER_FD_11, +}; + +void (*recVU0_UPPER_FD_00_TABLE[32])() = { + recVU0MI_ADDAx, recVU0MI_SUBAx , recVU0MI_MADDAx, recVU0MI_MSUBAx, + recVU0MI_ITOF0, recVU0MI_FTOI0, recVU0MI_MULAx , recVU0MI_MULAq , + recVU0MI_ADDAq, recVU0MI_SUBAq, recVU0MI_ADDA , recVU0MI_SUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_01_TABLE[32])() = { + recVU0MI_ADDAy , recVU0MI_SUBAy , recVU0MI_MADDAy, recVU0MI_MSUBAy, + recVU0MI_ITOF4 , recVU0MI_FTOI4 , recVU0MI_MULAy , recVU0MI_ABS , + recVU0MI_MADDAq, recVU0MI_MSUBAq, recVU0MI_MADDA , recVU0MI_MSUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_10_TABLE[32])() = { + recVU0MI_ADDAz , recVU0MI_SUBAz , recVU0MI_MADDAz, recVU0MI_MSUBAz, + recVU0MI_ITOF12, recVU0MI_FTOI12, recVU0MI_MULAz , recVU0MI_MULAi , + recVU0MI_MADDAi, recVU0MI_SUBAi , recVU0MI_MULA , recVU0MI_OPMULA, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_11_TABLE[32])() = { + recVU0MI_ADDAw , recVU0MI_SUBAw , recVU0MI_MADDAw, recVU0MI_MSUBAw, + recVU0MI_ITOF15, recVU0MI_FTOI15, recVU0MI_MULAw , recVU0MI_CLIP , + recVU0MI_MADDAi, recVU0MI_MSUBAi, recVU0unknown , recVU0MI_NOP , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void recVU0_UPPER_FD_00( void ) +{ + recVU0_UPPER_FD_00_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_01( void ) +{ + recVU0_UPPER_FD_01_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_10( void ) +{ + recVU0_UPPER_FD_10_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_11( void ) +{ + recVU0_UPPER_FD_11_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP( void ) +{ + recVU0LowerOP_OPCODE[ VU0.code & 0x3f ]( ); +} + +void recVU0LowerOP_T3_00( void ) +{ + recVU0LowerOP_T3_00_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_01( void ) +{ + recVU0LowerOP_T3_01_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_10( void ) +{ + recVU0LowerOP_T3_10_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_11( void ) +{ + recVU0LowerOP_T3_11_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + + +void recVU0unknown( void ) +{ +#ifdef CPU_LOG + CPU_LOG("Unknown VU0 micromode opcode calledn"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +#ifdef RECOMPILE_VUMI_ABS +void recVU0MI_ABS() { recVUMI_ABS(VU, VUREC_INFO); } +#else +void recVU0MI_ABS() { REC_VUOP(VU0, ABS); } +#endif + +#ifdef RECOMPILE_VUMI_ADD +void recVU0MI_ADD() { recVUMI_ADD(VU, VUREC_INFO); } +void recVU0MI_ADDi() { recVUMI_ADDi(VU, VUREC_INFO); } +void recVU0MI_ADDq() { recVUMI_ADDq(VU, VUREC_INFO); } +void recVU0MI_ADDx() { recVUMI_ADDx(VU, VUREC_INFO); } +void recVU0MI_ADDy() { recVUMI_ADDy(VU, VUREC_INFO); } +void recVU0MI_ADDz() { recVUMI_ADDz(VU, VUREC_INFO); } +void recVU0MI_ADDw() { recVUMI_ADDw(VU, VUREC_INFO); } +#else +void recVU0MI_ADD() { REC_VUOP(VU0, ADD); } +void recVU0MI_ADDi() { REC_VUOP(VU0, ADDi); } +void recVU0MI_ADDq() { REC_VUOP(VU0, ADDq); } +void recVU0MI_ADDx() { REC_VUOP(VU0, ADDx); } +void recVU0MI_ADDy() { REC_VUOP(VU0, ADDy); } +void recVU0MI_ADDz() { REC_VUOP(VU0, ADDz); } +void recVU0MI_ADDw() { REC_VUOP(VU0, ADDw); } +#endif + +#ifdef RECOMPILE_VUMI_ADDA +void recVU0MI_ADDA() { recVUMI_ADDA(VU, VUREC_INFO); } +void recVU0MI_ADDAi() { recVUMI_ADDAi(VU, VUREC_INFO); } +void recVU0MI_ADDAq() { recVUMI_ADDAq(VU, VUREC_INFO); } +void recVU0MI_ADDAx() { recVUMI_ADDAx(VU, VUREC_INFO); } +void recVU0MI_ADDAy() { recVUMI_ADDAy(VU, VUREC_INFO); } +void recVU0MI_ADDAz() { recVUMI_ADDAz(VU, VUREC_INFO); } +void recVU0MI_ADDAw() { recVUMI_ADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_ADDA() { REC_VUOP(VU0, ADDA); } +void recVU0MI_ADDAi() { REC_VUOP(VU0, ADDAi); } +void recVU0MI_ADDAq() { REC_VUOP(VU0, ADDAq); } +void recVU0MI_ADDAx() { REC_VUOP(VU0, ADDAx); } +void recVU0MI_ADDAy() { REC_VUOP(VU0, ADDAy); } +void recVU0MI_ADDAz() { REC_VUOP(VU0, ADDAz); } +void recVU0MI_ADDAw() { REC_VUOP(VU0, ADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_SUB +void recVU0MI_SUB() { recVUMI_SUB(VU, VUREC_INFO); } +void recVU0MI_SUBi() { recVUMI_SUBi(VU, VUREC_INFO); } +void recVU0MI_SUBq() { recVUMI_SUBq(VU, VUREC_INFO); } +void recVU0MI_SUBx() { recVUMI_SUBx(VU, VUREC_INFO); } +void recVU0MI_SUBy() { recVUMI_SUBy(VU, VUREC_INFO); } +void recVU0MI_SUBz() { recVUMI_SUBz(VU, VUREC_INFO); } +void recVU0MI_SUBw() { recVUMI_SUBw(VU, VUREC_INFO); } +#else +void recVU0MI_SUB() { REC_VUOP(VU0, SUB); } +void recVU0MI_SUBi() { REC_VUOP(VU0, SUBi); } +void recVU0MI_SUBq() { REC_VUOP(VU0, SUBq); } +void recVU0MI_SUBx() { REC_VUOP(VU0, SUBx); } +void recVU0MI_SUBy() { REC_VUOP(VU0, SUBy); } +void recVU0MI_SUBz() { REC_VUOP(VU0, SUBz); } +void recVU0MI_SUBw() { REC_VUOP(VU0, SUBw); } +#endif + +#ifdef RECOMPILE_VUMI_SUBA +void recVU0MI_SUBA() { recVUMI_SUBA(VU, VUREC_INFO); } +void recVU0MI_SUBAi() { recVUMI_SUBAi(VU, VUREC_INFO); } +void recVU0MI_SUBAq() { recVUMI_SUBAq(VU, VUREC_INFO); } +void recVU0MI_SUBAx() { recVUMI_SUBAx(VU, VUREC_INFO); } +void recVU0MI_SUBAy() { recVUMI_SUBAy(VU, VUREC_INFO); } +void recVU0MI_SUBAz() { recVUMI_SUBAz(VU, VUREC_INFO); } +void recVU0MI_SUBAw() { recVUMI_SUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_SUBA() { REC_VUOP(VU0, SUBA); } +void recVU0MI_SUBAi() { REC_VUOP(VU0, SUBAi); } +void recVU0MI_SUBAq() { REC_VUOP(VU0, SUBAq); } +void recVU0MI_SUBAx() { REC_VUOP(VU0, SUBAx); } +void recVU0MI_SUBAy() { REC_VUOP(VU0, SUBAy); } +void recVU0MI_SUBAz() { REC_VUOP(VU0, SUBAz); } +void recVU0MI_SUBAw() { REC_VUOP(VU0, SUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MUL +void recVU0MI_MUL() { recVUMI_MUL(VU, VUREC_INFO); } +void recVU0MI_MULi() { recVUMI_MULi(VU, VUREC_INFO); } +void recVU0MI_MULq() { recVUMI_MULq(VU, VUREC_INFO); } +void recVU0MI_MULx() { recVUMI_MULx(VU, VUREC_INFO); } +void recVU0MI_MULy() { recVUMI_MULy(VU, VUREC_INFO); } +void recVU0MI_MULz() { recVUMI_MULz(VU, VUREC_INFO); } +void recVU0MI_MULw() { recVUMI_MULw(VU, VUREC_INFO); } +#else +void recVU0MI_MUL() { REC_VUOP(VU0, MUL); } +void recVU0MI_MULi() { REC_VUOP(VU0, MULi); } +void recVU0MI_MULq() { REC_VUOP(VU0, MULq); } +void recVU0MI_MULx() { REC_VUOP(VU0, MULx); } +void recVU0MI_MULy() { REC_VUOP(VU0, MULy); } +void recVU0MI_MULz() { REC_VUOP(VU0, MULz); } +void recVU0MI_MULw() { REC_VUOP(VU0, MULw); } +#endif + +#ifdef RECOMPILE_VUMI_MULA +void recVU0MI_MULA() { recVUMI_MULA(VU, VUREC_INFO); } +void recVU0MI_MULAi() { recVUMI_MULAi(VU, VUREC_INFO); } +void recVU0MI_MULAq() { recVUMI_MULAq(VU, VUREC_INFO); } +void recVU0MI_MULAx() { recVUMI_MULAx(VU, VUREC_INFO); } +void recVU0MI_MULAy() { recVUMI_MULAy(VU, VUREC_INFO); } +void recVU0MI_MULAz() { recVUMI_MULAz(VU, VUREC_INFO); } +void recVU0MI_MULAw() { recVUMI_MULAw(VU, VUREC_INFO); } +#else +void recVU0MI_MULA() { REC_VUOP(VU0, MULA); } +void recVU0MI_MULAi() { REC_VUOP(VU0, MULAi); } +void recVU0MI_MULAq() { REC_VUOP(VU0, MULAq); } +void recVU0MI_MULAx() { REC_VUOP(VU0, MULAx); } +void recVU0MI_MULAy() { REC_VUOP(VU0, MULAy); } +void recVU0MI_MULAz() { REC_VUOP(VU0, MULAz); } +void recVU0MI_MULAw() { REC_VUOP(VU0, MULAw); } +#endif + +#ifdef RECOMPILE_VUMI_MADD +void recVU0MI_MADD() { recVUMI_MADD(VU, VUREC_INFO); } +void recVU0MI_MADDi() { recVUMI_MADDi(VU, VUREC_INFO); } +void recVU0MI_MADDq() { recVUMI_MADDq(VU, VUREC_INFO); } +void recVU0MI_MADDx() { recVUMI_MADDx(VU, VUREC_INFO); } +void recVU0MI_MADDy() { recVUMI_MADDy(VU, VUREC_INFO); } +void recVU0MI_MADDz() { recVUMI_MADDz(VU, VUREC_INFO); } +void recVU0MI_MADDw() { recVUMI_MADDw(VU, VUREC_INFO); } +#else +void recVU0MI_MADD() { REC_VUOP(VU0, MADD); } +void recVU0MI_MADDi() { REC_VUOP(VU0, MADDi); } +void recVU0MI_MADDq() { REC_VUOP(VU0, MADDq); } +void recVU0MI_MADDx() { REC_VUOP(VU0, MADDx); } +void recVU0MI_MADDy() { REC_VUOP(VU0, MADDy); } +void recVU0MI_MADDz() { REC_VUOP(VU0, MADDz); } +void recVU0MI_MADDw() { REC_VUOP(VU0, MADDw); } +#endif + +#ifdef RECOMPILE_VUMI_MADDA +void recVU0MI_MADDA() { recVUMI_MADDA(VU, VUREC_INFO); } +void recVU0MI_MADDAi() { recVUMI_MADDAi(VU, VUREC_INFO); } +void recVU0MI_MADDAq() { recVUMI_MADDAq(VU, VUREC_INFO); } +void recVU0MI_MADDAx() { recVUMI_MADDAx(VU, VUREC_INFO); } +void recVU0MI_MADDAy() { recVUMI_MADDAy(VU, VUREC_INFO); } +void recVU0MI_MADDAz() { recVUMI_MADDAz(VU, VUREC_INFO); } +void recVU0MI_MADDAw() { recVUMI_MADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_MADDA() { REC_VUOP(VU0, MADDA); } +void recVU0MI_MADDAi() { REC_VUOP(VU0, MADDAi); } +void recVU0MI_MADDAq() { REC_VUOP(VU0, MADDAq); } +void recVU0MI_MADDAx() { REC_VUOP(VU0, MADDAx); } +void recVU0MI_MADDAy() { REC_VUOP(VU0, MADDAy); } +void recVU0MI_MADDAz() { REC_VUOP(VU0, MADDAz); } +void recVU0MI_MADDAw() { REC_VUOP(VU0, MADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUB +void recVU0MI_MSUB() { recVUMI_MSUB(VU, VUREC_INFO); } +void recVU0MI_MSUBi() { recVUMI_MSUBi(VU, VUREC_INFO); } +void recVU0MI_MSUBq() { recVUMI_MSUBq(VU, VUREC_INFO); } +void recVU0MI_MSUBx() { recVUMI_MSUBx(VU, VUREC_INFO); } +void recVU0MI_MSUBy() { recVUMI_MSUBy(VU, VUREC_INFO); } +void recVU0MI_MSUBz() { recVUMI_MSUBz(VU, VUREC_INFO); } +void recVU0MI_MSUBw() { recVUMI_MSUBw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUB() { REC_VUOP(VU0, MSUB); } +void recVU0MI_MSUBi() { REC_VUOP(VU0, MSUBi); } +void recVU0MI_MSUBq() { REC_VUOP(VU0, MSUBq); } +void recVU0MI_MSUBx() { REC_VUOP(VU0, MSUBx); } +void recVU0MI_MSUBy() { REC_VUOP(VU0, MSUBy); } +void recVU0MI_MSUBz() { REC_VUOP(VU0, MSUBz); } +void recVU0MI_MSUBw() { REC_VUOP(VU0, MSUBw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUBA +void recVU0MI_MSUBA() { recVUMI_MSUBA(VU, VUREC_INFO); } +void recVU0MI_MSUBAi() { recVUMI_MSUBAi(VU, VUREC_INFO); } +void recVU0MI_MSUBAq() { recVUMI_MSUBAq(VU, VUREC_INFO); } +void recVU0MI_MSUBAx() { recVUMI_MSUBAx(VU, VUREC_INFO); } +void recVU0MI_MSUBAy() { recVUMI_MSUBAy(VU, VUREC_INFO); } +void recVU0MI_MSUBAz() { recVUMI_MSUBAz(VU, VUREC_INFO); } +void recVU0MI_MSUBAw() { recVUMI_MSUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUBA() { REC_VUOP(VU0, MSUBA); } +void recVU0MI_MSUBAi() { REC_VUOP(VU0, MSUBAi); } +void recVU0MI_MSUBAq() { REC_VUOP(VU0, MSUBAq); } +void recVU0MI_MSUBAx() { REC_VUOP(VU0, MSUBAx); } +void recVU0MI_MSUBAy() { REC_VUOP(VU0, MSUBAy); } +void recVU0MI_MSUBAz() { REC_VUOP(VU0, MSUBAz); } +void recVU0MI_MSUBAw() { REC_VUOP(VU0, MSUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MAX +void recVU0MI_MAX() { recVUMI_MAX(VU, VUREC_INFO); } +void recVU0MI_MAXi() { recVUMI_MAXi(VU, VUREC_INFO); } +void recVU0MI_MAXx() { recVUMI_MAXx(VU, VUREC_INFO); } +void recVU0MI_MAXy() { recVUMI_MAXy(VU, VUREC_INFO); } +void recVU0MI_MAXz() { recVUMI_MAXz(VU, VUREC_INFO); } +void recVU0MI_MAXw() { recVUMI_MAXw(VU, VUREC_INFO); } +#else +void recVU0MI_MAX() { REC_VUOP(VU0, MAX); } +void recVU0MI_MAXi() { REC_VUOP(VU0, MAXi); } +void recVU0MI_MAXx() { REC_VUOP(VU0, MAXx); } +void recVU0MI_MAXy() { REC_VUOP(VU0, MAXy); } +void recVU0MI_MAXz() { REC_VUOP(VU0, MAXz); } +void recVU0MI_MAXw() { REC_VUOP(VU0, MAXw); } +#endif + +#ifdef RECOMPILE_VUMI_MINI +void recVU0MI_MINI() { recVUMI_MINI(VU, VUREC_INFO); } +void recVU0MI_MINIi() { recVUMI_MINIi(VU, VUREC_INFO); } +void recVU0MI_MINIx() { recVUMI_MINIx(VU, VUREC_INFO); } +void recVU0MI_MINIy() { recVUMI_MINIy(VU, VUREC_INFO); } +void recVU0MI_MINIz() { recVUMI_MINIz(VU, VUREC_INFO); } +void recVU0MI_MINIw() { recVUMI_MINIw(VU, VUREC_INFO); } +#else +void recVU0MI_MINI() { REC_VUOP(VU0, MINI); } +void recVU0MI_MINIi() { REC_VUOP(VU0, MINIi); } +void recVU0MI_MINIx() { REC_VUOP(VU0, MINIx); } +void recVU0MI_MINIy() { REC_VUOP(VU0, MINIy); } +void recVU0MI_MINIz() { REC_VUOP(VU0, MINIz); } +void recVU0MI_MINIw() { REC_VUOP(VU0, MINIw); } +#endif + +#ifdef RECOMPILE_VUMI_FTOI +void recVU0MI_FTOI0() { recVUMI_FTOI0(VU, VUREC_INFO); } +void recVU0MI_FTOI4() { recVUMI_FTOI4(VU, VUREC_INFO); } +void recVU0MI_FTOI12() { recVUMI_FTOI12(VU, VUREC_INFO); } +void recVU0MI_FTOI15() { recVUMI_FTOI15(VU, VUREC_INFO); } +void recVU0MI_ITOF0() { recVUMI_ITOF0(VU, VUREC_INFO); } +void recVU0MI_ITOF4() { recVUMI_ITOF4(VU, VUREC_INFO); } +void recVU0MI_ITOF12() { recVUMI_ITOF12(VU, VUREC_INFO); } +void recVU0MI_ITOF15() { recVUMI_ITOF15(VU, VUREC_INFO); } +#else +void recVU0MI_FTOI0() { REC_VUOP(VU0, FTOI0); } +void recVU0MI_FTOI4() { REC_VUOP(VU0, FTOI4); } +void recVU0MI_FTOI12() { REC_VUOP(VU0, FTOI12); } +void recVU0MI_FTOI15() { REC_VUOP(VU0, FTOI15); } +void recVU0MI_ITOF0() { REC_VUOP(VU0, ITOF0); } +void recVU0MI_ITOF4() { REC_VUOP(VU0, ITOF4); } +void recVU0MI_ITOF12() { REC_VUOP(VU0, ITOF12); } +void recVU0MI_ITOF15() { REC_VUOP(VU0, ITOF15); } +#endif + +void recVU0MI_OPMULA() { recVUMI_OPMULA(VU, VUREC_INFO); } +void recVU0MI_OPMSUB() { recVUMI_OPMSUB(VU, VUREC_INFO); } +void recVU0MI_NOP() { } +void recVU0MI_CLIP() { recVUMI_CLIP(VU, VUREC_INFO); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +#ifdef RECOMPILE_VUMI_MISC + +void recVU0MI_MTIR() { recVUMI_MTIR(VU, VUREC_INFO); } +void recVU0MI_MR32() { recVUMI_MR32(VU, VUREC_INFO); } +void recVU0MI_MFIR() { recVUMI_MFIR(VU, VUREC_INFO); } +void recVU0MI_MOVE() { recVUMI_MOVE(VU, VUREC_INFO); } +void recVU0MI_WAITQ() { recVUMI_WAITQ(VU, VUREC_INFO); } +void recVU0MI_MFP() { recVUMI_MFP(VU, VUREC_INFO); } +void recVU0MI_WAITP() { SysPrintf("vu0 wait p?\n"); } + +#else + +void recVU0MI_MOVE() { REC_VUOP(VU0, MOVE); } +void recVU0MI_MFIR() { REC_VUOP(VU0, MFIR); } +void recVU0MI_MTIR() { REC_VUOP(VU0, MTIR); } +void recVU0MI_MR32() { REC_VUOP(VU0, MR32); } +void recVU0MI_WAITQ() { } +void recVU0MI_MFP() { REC_VUOP(VU0, MFP); } +void recVU0MI_WAITP() { REC_VUOP(VU0, WAITP); } + +#endif + +#ifdef RECOMPILE_VUMI_MATH + +void recVU0MI_SQRT() { recVUMI_SQRT(VU, VUREC_INFO); } +void recVU0MI_RSQRT() { recVUMI_RSQRT(VU, VUREC_INFO); } +void recVU0MI_DIV() { recVUMI_DIV(VU, VUREC_INFO); } + +#else + +void recVU0MI_DIV() { REC_VUOP(VU0, DIV);} +void recVU0MI_SQRT() { REC_VUOP(VU0, SQRT); } +void recVU0MI_RSQRT() { REC_VUOP(VU0, RSQRT); } + +#endif + +#ifdef RECOMPILE_VUMI_E + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { recVUMI_ELENG(VU, VUREC_INFO); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#else + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { REC_VUOP(VU0, ELENG); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#endif + +#ifdef RECOMPILE_VUMI_X + +void recVU0MI_XITOP() { recVUMI_XITOP(VU, VUREC_INFO); } +void recVU0MI_XGKICK() { recVUMI_XGKICK(VU, VUREC_INFO); } +void recVU0MI_XTOP() { recVUMI_XTOP(VU, VUREC_INFO); } + +#else + +void recVU0MI_XITOP() { REC_VUOP(VU0, XITOP); } +void recVU0MI_XGKICK() { REC_VUOP(VU0, XGKICK);} +void recVU0MI_XTOP() { REC_VUOP(VU0, XTOP);} + +#endif + +#ifdef RECOMPILE_VUMI_RANDOM + +void recVU0MI_RINIT() { recVUMI_RINIT(VU, VUREC_INFO); } +void recVU0MI_RGET() { recVUMI_RGET(VU, VUREC_INFO); } +void recVU0MI_RNEXT() { recVUMI_RNEXT(VU, VUREC_INFO); } +void recVU0MI_RXOR() { recVUMI_RXOR(VU, VUREC_INFO); } + +#else + +void recVU0MI_RINIT() { REC_VUOP(VU0, RINIT); } +void recVU0MI_RGET() { REC_VUOP(VU0, RGET); } +void recVU0MI_RNEXT() { REC_VUOP(VU0, RNEXT); } +void recVU0MI_RXOR() { REC_VUOP(VU0, RXOR); } + +#endif + +#ifdef RECOMPILE_VUMI_FLAG + +void recVU0MI_FSAND() { recVUMI_FSAND(VU, VUREC_INFO); } +void recVU0MI_FSEQ() { recVUMI_FSEQ(VU, VUREC_INFO); } +void recVU0MI_FSOR() { recVUMI_FSOR(VU, VUREC_INFO); } +void recVU0MI_FSSET() { recVUMI_FSSET(VU, VUREC_INFO); } +void recVU0MI_FMEQ() { recVUMI_FMEQ(VU, VUREC_INFO); } +void recVU0MI_FMOR() { recVUMI_FMOR(VU, VUREC_INFO); } +void recVU0MI_FCEQ() { recVUMI_FCEQ(VU, VUREC_INFO); } +void recVU0MI_FCOR() { recVUMI_FCOR(VU, VUREC_INFO); } +void recVU0MI_FCSET() { recVUMI_FCSET(VU, VUREC_INFO); } +void recVU0MI_FCGET() { recVUMI_FCGET(VU, VUREC_INFO); } +void recVU0MI_FCAND() { recVUMI_FCAND(VU, VUREC_INFO); } +void recVU0MI_FMAND() { recVUMI_FMAND(VU, VUREC_INFO); } + +#else + +void recVU0MI_FSAND() { REC_VUOP(VU0, FSAND); } +void recVU0MI_FSEQ() { REC_VUOP(VU0, FSEQ); } +void recVU0MI_FSOR() { REC_VUOP(VU0, FSOR); } +void recVU0MI_FSSET() { REC_VUOP(VU0, FSSET); } +void recVU0MI_FMAND() { REC_VUOP(VU0, FMAND); } +void recVU0MI_FMEQ() { REC_VUOP(VU0, FMEQ); } +void recVU0MI_FMOR() { REC_VUOP(VU0, FMOR); } +void recVU0MI_FCAND() { REC_VUOP(VU0, FCAND); } +void recVU0MI_FCEQ() { REC_VUOP(VU0, FCEQ); } +void recVU0MI_FCOR() { REC_VUOP(VU0, FCOR); } +void recVU0MI_FCSET() { REC_VUOP(VU0, FCSET); } +void recVU0MI_FCGET() { REC_VUOP(VU0, FCGET); } + +#endif + +#ifdef RECOMPILE_VUMI_LOADSTORE + +void recVU0MI_LQ() { recVUMI_LQ(VU, VUREC_INFO); } +void recVU0MI_LQD() { recVUMI_LQD(VU, VUREC_INFO); } +void recVU0MI_LQI() { recVUMI_LQI(VU, VUREC_INFO); } +void recVU0MI_SQ() { recVUMI_SQ(VU, VUREC_INFO); } +void recVU0MI_SQD() { recVUMI_SQD(VU, VUREC_INFO); } +void recVU0MI_SQI() { recVUMI_SQI(VU, VUREC_INFO); } +void recVU0MI_ILW() { recVUMI_ILW(VU, VUREC_INFO); } +void recVU0MI_ISW() { recVUMI_ISW(VU, VUREC_INFO); } +void recVU0MI_ILWR() { recVUMI_ILWR(VU, VUREC_INFO); } +void recVU0MI_ISWR() { recVUMI_ISWR(VU, VUREC_INFO); } + +#else + +void recVU0MI_LQ() { REC_VUOP(VU0, LQ); } +void recVU0MI_LQD() { REC_VUOP(VU0, LQD); } +void recVU0MI_LQI() { REC_VUOP(VU0, LQI); } +void recVU0MI_SQ() { REC_VUOP(VU0, SQ); } +void recVU0MI_SQD() { REC_VUOP(VU0, SQD); } +void recVU0MI_SQI() { REC_VUOP(VU0, SQI); } +void recVU0MI_ILW() { REC_VUOP(VU0, ILW); } +void recVU0MI_ISW() { REC_VUOP(VU0, ISW); } +void recVU0MI_ILWR() { REC_VUOP(VU0, ILWR); } +void recVU0MI_ISWR() { REC_VUOP(VU0, ISWR); } + +#endif + +#ifdef RECOMPILE_VUMI_ARITHMETIC + +void recVU0MI_IADD() { recVUMI_IADD(VU, VUREC_INFO); } +void recVU0MI_IADDI() { recVUMI_IADDI(VU, VUREC_INFO); } +void recVU0MI_IADDIU() { recVUMI_IADDIU(VU, VUREC_INFO); } +void recVU0MI_IOR() { recVUMI_IOR(VU, VUREC_INFO); } +void recVU0MI_ISUB() { recVUMI_ISUB(VU, VUREC_INFO); } +void recVU0MI_IAND() { recVUMI_IAND(VU, VUREC_INFO); } +void recVU0MI_ISUBIU() { recVUMI_ISUBIU(VU, VUREC_INFO); } + +#else + +void recVU0MI_IADD() { REC_VUOP(VU0, IADD); } +void recVU0MI_IADDI() { REC_VUOP(VU0, IADDI); } +void recVU0MI_IADDIU() { REC_VUOP(VU0, IADDIU); } +void recVU0MI_IOR() { REC_VUOP(VU0, IOR); } +void recVU0MI_ISUB() { REC_VUOP(VU0, ISUB); } +void recVU0MI_IAND() { REC_VUOP(VU0, IAND); } +void recVU0MI_ISUBIU() { REC_VUOP(VU0, ISUBIU); } + +#endif + +#ifdef RECOMPILE_VUMI_BRANCH + +void recVU0MI_IBEQ() { recVUMI_IBEQ(VU, VUREC_INFO); } +void recVU0MI_IBGEZ() { recVUMI_IBGEZ(VU, VUREC_INFO); } +void recVU0MI_IBLTZ() { recVUMI_IBLTZ(VU, VUREC_INFO); } +void recVU0MI_IBLEZ() { recVUMI_IBLEZ(VU, VUREC_INFO); } +void recVU0MI_IBGTZ() { recVUMI_IBGTZ(VU, VUREC_INFO); } +void recVU0MI_IBNE() { recVUMI_IBNE(VU, VUREC_INFO); } +void recVU0MI_B() { recVUMI_B(VU, VUREC_INFO); } +void recVU0MI_BAL() { recVUMI_BAL(VU, VUREC_INFO); } +void recVU0MI_JR() { recVUMI_JR(VU, VUREC_INFO); } +void recVU0MI_JALR() { recVUMI_JALR(VU, VUREC_INFO); } + +#else + +void recVU0MI_IBEQ() { REC_VUOP(VU0, IBEQ); } +void recVU0MI_IBGEZ() { REC_VUOP(VU0, IBGEZ); } +void recVU0MI_IBGTZ() { REC_VUOP(VU0, IBGTZ); } +void recVU0MI_IBLTZ() { REC_VUOP(VU0, IBLTZ); } +void recVU0MI_IBLEZ() { REC_VUOP(VU0, IBLEZ); } +void recVU0MI_IBNE() { REC_VUOP(VU0, IBNE); } +void recVU0MI_B() { REC_VUOP(VU0, B); } +void recVU0MI_BAL() { REC_VUOP(VU0, BAL); } +void recVU0MI_JR() { REC_VUOP(VU0, JR); } +void recVU0MI_JALR() { REC_VUOP(VU0, JALR); } + +#endif + diff --git a/branches/pcsx2_0.9.2/x86/iVU0micro.h b/branches/pcsx2_0.9.2/x86/iVU0micro.h new file mode 100644 index 0000000..1b3c1c5 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVU0micro.h @@ -0,0 +1,229 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU0MICRO_H__ +#define __IVU0MICRO_H__ + +void recResetVU0(); +void recExecuteVU0Block( void ); +void recClearVU0( u32 Addr, u32 Size ); + +extern void (*recVU0_LOWER_OPCODE[128])(); +extern void (*recVU0_UPPER_OPCODE[64])(); + +extern void (*recVU0_UPPER_FD_00_TABLE[32])(); +extern void (*recVU0_UPPER_FD_01_TABLE[32])(); +extern void (*recVU0_UPPER_FD_10_TABLE[32])(); +extern void (*recVU0_UPPER_FD_11_TABLE[32])(); + +extern void (*recVU1_LOWER_OPCODE[128])(); +extern void (*recVU1_UPPER_OPCODE[64])(); + +extern void (*recVU1_UPPER_FD_00_TABLE[32])(); +extern void (*recVU1_UPPER_FD_01_TABLE[32])(); +extern void (*recVU1_UPPER_FD_10_TABLE[32])(); +extern void (*recVU1_UPPER_FD_11_TABLE[32])(); + +void recVU0_UPPER_FD_00(); +void recVU0_UPPER_FD_01(); +void recVU0_UPPER_FD_10(); +void recVU0_UPPER_FD_11(); + +void recVU0LowerOP(); +void recVU0LowerOP_T3_00(); +void recVU0LowerOP_T3_01(); +void recVU0LowerOP_T3_10(); +void recVU0LowerOP_T3_11(); + +void recVU0unknown(); + + + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void recVU0MI_ABS(); +void recVU0MI_ADD(); +void recVU0MI_ADDi(); +void recVU0MI_ADDq(); +void recVU0MI_ADDx(); +void recVU0MI_ADDy(); +void recVU0MI_ADDz(); +void recVU0MI_ADDw(); +void recVU0MI_ADDA(); +void recVU0MI_ADDAi(); +void recVU0MI_ADDAq(); +void recVU0MI_ADDAx(); +void recVU0MI_ADDAy(); +void recVU0MI_ADDAz(); +void recVU0MI_ADDAw(); +void recVU0MI_SUB(); +void recVU0MI_SUBi(); +void recVU0MI_SUBq(); +void recVU0MI_SUBx(); +void recVU0MI_SUBy(); +void recVU0MI_SUBz(); +void recVU0MI_SUBw(); +void recVU0MI_SUBA(); +void recVU0MI_SUBAi(); +void recVU0MI_SUBAq(); +void recVU0MI_SUBAx(); +void recVU0MI_SUBAy(); +void recVU0MI_SUBAz(); +void recVU0MI_SUBAw(); +void recVU0MI_MUL(); +void recVU0MI_MULi(); +void recVU0MI_MULq(); +void recVU0MI_MULx(); +void recVU0MI_MULy(); +void recVU0MI_MULz(); +void recVU0MI_MULw(); +void recVU0MI_MULA(); +void recVU0MI_MULAi(); +void recVU0MI_MULAq(); +void recVU0MI_MULAx(); +void recVU0MI_MULAy(); +void recVU0MI_MULAz(); +void recVU0MI_MULAw(); +void recVU0MI_MADD(); +void recVU0MI_MADDi(); +void recVU0MI_MADDq(); +void recVU0MI_MADDx(); +void recVU0MI_MADDy(); +void recVU0MI_MADDz(); +void recVU0MI_MADDw(); +void recVU0MI_MADDA(); +void recVU0MI_MADDAi(); +void recVU0MI_MADDAq(); +void recVU0MI_MADDAx(); +void recVU0MI_MADDAy(); +void recVU0MI_MADDAz(); +void recVU0MI_MADDAw(); +void recVU0MI_MSUB(); +void recVU0MI_MSUBi(); +void recVU0MI_MSUBq(); +void recVU0MI_MSUBx(); +void recVU0MI_MSUBy(); +void recVU0MI_MSUBz(); +void recVU0MI_MSUBw(); +void recVU0MI_MSUBA(); +void recVU0MI_MSUBAi(); +void recVU0MI_MSUBAq(); +void recVU0MI_MSUBAx(); +void recVU0MI_MSUBAy(); +void recVU0MI_MSUBAz(); +void recVU0MI_MSUBAw(); +void recVU0MI_MAX(); +void recVU0MI_MAXi(); +void recVU0MI_MAXx(); +void recVU0MI_MAXy(); +void recVU0MI_MAXz(); +void recVU0MI_MAXw(); +void recVU0MI_MINI(); +void recVU0MI_MINIi(); +void recVU0MI_MINIx(); +void recVU0MI_MINIy(); +void recVU0MI_MINIz(); +void recVU0MI_MINIw(); +void recVU0MI_OPMULA(); +void recVU0MI_OPMSUB(); +void recVU0MI_NOP(); +void recVU0MI_FTOI0(); +void recVU0MI_FTOI4(); +void recVU0MI_FTOI12(); +void recVU0MI_FTOI15(); +void recVU0MI_ITOF0(); +void recVU0MI_ITOF4(); +void recVU0MI_ITOF12(); +void recVU0MI_ITOF15(); +void recVU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void recVU0MI_DIV(); +void recVU0MI_SQRT(); +void recVU0MI_RSQRT(); +void recVU0MI_IADD(); +void recVU0MI_IADDI(); +void recVU0MI_IADDIU(); +void recVU0MI_IAND(); +void recVU0MI_IOR(); +void recVU0MI_ISUB(); +void recVU0MI_ISUBIU(); +void recVU0MI_MOVE(); +void recVU0MI_MFIR(); +void recVU0MI_MTIR(); +void recVU0MI_MR32(); +void recVU0MI_LQ(); +void recVU0MI_LQD(); +void recVU0MI_LQI(); +void recVU0MI_SQ(); +void recVU0MI_SQD(); +void recVU0MI_SQI(); +void recVU0MI_ILW(); +void recVU0MI_ISW(); +void recVU0MI_ILWR(); +void recVU0MI_ISWR(); +void recVU0MI_RINIT(); +void recVU0MI_RGET(); +void recVU0MI_RNEXT(); +void recVU0MI_RXOR(); +void recVU0MI_WAITQ(); +void recVU0MI_FSAND(); +void recVU0MI_FSEQ(); +void recVU0MI_FSOR(); +void recVU0MI_FSSET(); +void recVU0MI_FMAND(); +void recVU0MI_FMEQ(); +void recVU0MI_FMOR(); +void recVU0MI_FCAND(); +void recVU0MI_FCEQ(); +void recVU0MI_FCOR(); +void recVU0MI_FCSET(); +void recVU0MI_FCGET(); +void recVU0MI_IBEQ(); +void recVU0MI_IBGEZ(); +void recVU0MI_IBGTZ(); +void recVU0MI_IBLEZ(); +void recVU0MI_IBLTZ(); +void recVU0MI_IBNE(); +void recVU0MI_B(); +void recVU0MI_BAL(); +void recVU0MI_JR(); +void recVU0MI_JALR(); +void recVU0MI_MFP(); +void recVU0MI_WAITP(); +void recVU0MI_ESADD(); +void recVU0MI_ERSADD(); +void recVU0MI_ELENG(); +void recVU0MI_ERLENG(); +void recVU0MI_EATANxy(); +void recVU0MI_EATANxz(); +void recVU0MI_ESUM(); +void recVU0MI_ERCPR(); +void recVU0MI_ESQRT(); +void recVU0MI_ERSQRT(); +void recVU0MI_ESIN(); +void recVU0MI_EATAN(); +void recVU0MI_EEXP(); +void recVU0MI_XITOP(); + +#endif /* __IVU0MICRO_H__ */ diff --git a/branches/pcsx2_0.9.2/x86/iVU1micro.c b/branches/pcsx2_0.9.2/x86/iVU1micro.c new file mode 100644 index 0000000..38f1745 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVU1micro.c @@ -0,0 +1,229 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VU.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// TODO: there's a bug in spyro start menu where release vurec works but debug vurec breaks + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +#define VU ((VURegs*)&VU1) + +u32 vu1recpcold = -1; +u32 vu1reccountold = -1; + +static _vuopinfo _opinfo[256]; + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU1.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU1.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU1.code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU1.code>>24) & 0x1) +#define _Y ((VU1.code>>23) & 0x1) +#define _Z ((VU1.code>>22) & 0x1) +#define _W ((VU1.code>>21) & 0x1) + +#define _Fsf_ ((VU1.code >> 21) & 0x03) +#define _Ftf_ ((VU1.code >> 23) & 0x03) + + +#define VU1_VFx_ADDR(x) (u32)&VU1.VF[x].UL[0] +#define VU1_VFy_ADDR(x) (u32)&VU1.VF[x].UL[1] +#define VU1_VFz_ADDR(x) (u32)&VU1.VF[x].UL[2] +#define VU1_VFw_ADDR(x) (u32)&VU1.VF[x].UL[3] + +#define VU1_REGR_ADDR (u32)&VU1.VI[REG_R] +#define VU1_REGI_ADDR (u32)&VU1.VI[REG_I] +#define VU1_REGQ_ADDR (u32)&VU1.VI[REG_Q] +#define VU1_REGMAC_ADDR (u32)&VU1.VI[REG_MAC_FLAG] + +#define VU1_VI_ADDR(x) (u32)&VU1.VI[x].UL + +#define VU1_ACCx_ADDR (u32)&VU1.ACC.UL[0] +#define VU1_ACCy_ADDR (u32)&VU1.ACC.UL[1] +#define VU1_ACCz_ADDR (u32)&VU1.ACC.UL[2] +#define VU1_ACCw_ADDR (u32)&VU1.ACC.UL[3] + +static void VU1RecompileBlock(void); + +void recVU1Init() +{ + SuperVUInit(1); +} + +void recVU1Shutdown() +{ + SuperVUDestroy(1); +} + +void recResetVU1( void ) { + + if( CHECK_VU1REC ) { + SuperVUReset(1); + } + + vu1recpcold = 0; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +static void iDumpBlock() +{ + FILE *f; + char filename[ 256 ]; + u32 *mem; + u32 i; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#endif + SysPrintf( "dump1 %x => %x (%s)\n", VU1.VI[ REG_TPC ].UL, pc, filename ); + + f = fopen( filename, "wb" ); + for ( i = VU1.VI[REG_TPC].UL; i < pc; i += 8 ) { + char* pstr; + mem = (u32*)&VU1.Micro[i]; + + pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%x: %-40s ", i, pstr); + + pstr = disVU1MicroLF( mem[0], i ); + fprintf(f, "%s\n", pstr); + } + fclose( f ); +} + +#define VF_VAL(x) ((x==0x80000000)?0:(x)) + +u32 g_VUProgramId = 0; +void iDumpVU1Registers() +{ + int i; +// static int icount = 0; +// __Log("%x\n", icount); + for(i = 1; i < 32; ++i) { +// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2], +// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]); + //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); + //else __Log("%x\n", VU1.VI[i].UL); + else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); +} + +#ifdef PCSX2_DEVBUILD +u32 vuprogcount = 0; +u32 vudump = 0; +#endif + +void DummyExecuteVU1Block(void) +{ + VU0.VI[ REG_VPU_STAT ].UL &= ~0x100; +} + +void recExecuteVU1Block(void) +{ +#ifdef _DEBUG + vuprogcount++; + + if( vudump & 8 ) { + __Log("start vu1: %x %x\n", VU1.VI[ REG_TPC ].UL, vuprogcount); + } +#endif + + if (CHECK_VU1REC) + { + if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + + assert( (VU1.VI[ REG_TPC ].UL&7) == 0 ); + + //__Log("prog: %x %x %x\n", vuprogcount, *(int*)0x1883a740, *(int*)0x18fe5fe0); + //for(i = 1; i < 32; ++i) __Log("vf%d: %x %x %x %x, vi: %x\n", i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + + //if( VU1.VI[ REG_TPC ].UL == 0x670 ) { +// __Log("VU: %x %x\n", VU1.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU1Registers(); +// vudump |= 8; + + // while loop needed since not always will return finished + do { + SuperVUExecuteProgram(VU1.VI[ REG_TPC ].UL, 1); + } + while( VU0.VI[ REG_VPU_STAT ].UL&0x100 ); + +// __Log("eVU: %x\n", VU1.VI[ REG_TPC ].UL); +// iDumpVU1Registers(); + } + else { +#ifdef _DEBUG + if( (vudump&8) ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + + while(VU0.VI[ REG_VPU_STAT ].UL&0x100) + intExecuteVU1Block(); + } +} + +void recClearVU1( u32 Addr, u32 Size ) { + assert( (Addr&7) == 0 ); + + if( CHECK_VU1REC ) { + SuperVUClear(Addr, Size*4, 1); + } +} diff --git a/branches/pcsx2_0.9.2/x86/iVU1micro.h b/branches/pcsx2_0.9.2/x86/iVU1micro.h new file mode 100644 index 0000000..cd83b5c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVU1micro.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU1MICRO_H__ +#define __IVU1MICRO_H__ + +void recVU1Init(); +void recVU1Shutdown(); +void recResetVU1(); +void recExecuteVU1Block( void ); +void recClearVU1( u32 Addr, u32 Size ); + +extern u32 vudump; +void iDumpVU1Registers(); + +#endif /* __IVU1MICRO_H__ */ diff --git a/branches/pcsx2_0.9.2/x86/iVUmicro.c b/branches/pcsx2_0.9.2/x86/iVUmicro.c new file mode 100644 index 0000000..75b9602 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVUmicro.c @@ -0,0 +1,4807 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "GS.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "iVUzerorec.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +int vucycle; +int vucycleold; +_vuopinfo *cinfo = NULL; + +//Lower/Upper instructions can use that.. +#define _Ft_ (( VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ (( VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ (( VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X (( VU->code>>24) & 0x1) +#define _Y (( VU->code>>23) & 0x1) +#define _Z (( VU->code>>22) & 0x1) +#define _W (( VU->code>>21) & 0x1) + +#define _XYZW_SS (_X+_Y+_Z+_W==1) + +#define _Fsf_ (( VU->code >> 21) & 0x03) +#define _Ftf_ (( VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + +#define VU_VFx_ADDR(x) (int)&VU->VF[x].UL[0] +#define VU_VFy_ADDR(x) (int)&VU->VF[x].UL[1] +#define VU_VFz_ADDR(x) (int)&VU->VF[x].UL[2] +#define VU_VFw_ADDR(x) (int)&VU->VF[x].UL[3] + +#define VU_REGR_ADDR (int)&VU->VI[REG_R] +#define VU_REGQ_ADDR (int)&VU->VI[REG_Q] +#define VU_REGMAC_ADDR (int)&VU->VI[REG_MAC_FLAG] + +#define VU_VI_ADDR(x, read) GetVIAddr(VU, x, read, info) + +#define VU_ACCx_ADDR (int)&VU->ACC.UL[0] +#define VU_ACCy_ADDR (int)&VU->ACC.UL[1] +#define VU_ACCz_ADDR (int)&VU->ACC.UL[2] +#define VU_ACCw_ADDR (int)&VU->ACC.UL[3] + +#define _X_Y_Z_W ((( VU->code >> 21 ) & 0xF ) ) + +PCSX2_ALIGNED16(float recMult_float_to_int4[4]) = { 16.0, 16.0, 16.0, 16.0 }; +PCSX2_ALIGNED16(float recMult_float_to_int12[4]) = { 4096.0, 4096.0, 4096.0, 4096.0 }; +PCSX2_ALIGNED16(float recMult_float_to_int15[4]) = { 32768.0, 32768.0, 32768.0, 32768.0 }; + +PCSX2_ALIGNED16(float recMult_int_to_float4[4]) = { 0.0625f, 0.0625f, 0.0625f, 0.0625f }; +PCSX2_ALIGNED16(float recMult_int_to_float12[4]) = { 0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625 }; +PCSX2_ALIGNED16(float recMult_int_to_float15[4]) = { 0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125 }; +static s32 bpc; +_VURegsNum* g_VUregs = NULL; +u8 g_MACFlagTransform[256] = {0}; // used to flip xyzw bits + +static int SSEmovMask[ 16 ][ 4 ] = +{ +{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +{ 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } +}; + +#define VU_SWAPSRC 0xf090 // don't touch + +#define _vuIsRegSwappedWithTemp() (VU_SWAPSRC & (1<<_X_Y_Z_W)) + +// use for allocating vi regs +#define ALLOCTEMPX86(mode) _allocX86reg(-1, X86TYPE_TEMP, 0, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ALLOCVI(vi, mode) _allocX86reg(-1, X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), vi, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ADD_VI_NEEDED(vi) _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), vi); + +// 1 - src, 0 - dest wzyx +void VU_MERGE0(int dest, int src) { // 0000 +} +void VU_MERGE1(int dest, int src) { // 1000 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4); +} +void VU_MERGE2(int dest, int src) { // 0100 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x64); +} +void VU_MERGE3(int dest, int src) { // 1100 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE4(int dest, int src) { // 0010s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE5(int dest, int src) { // 1010 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xd8); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd8); +} +void VU_MERGE6(int dest, int src) { // 0110 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x9c); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x78); +} +void VU_MERGE7(int dest, int src) { // 1110s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE8(int dest, int src) { // 0001 + SSE_MOVSS_XMM_to_XMM(dest, src); +} +void VU_MERGE9(int dest, int src) { // 1001 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc9); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd2); +} +void VU_MERGE10(int dest, int src) { // 0101 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x8d); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x72); +} +void VU_MERGE11(int dest, int src) { // 1101 + SSE_MOVSS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE12(int dest, int src) { // 0011s + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE13(int dest, int src) { // 1011s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0x64); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE14(int dest, int src) { // 0111s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xc4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE15(int dest, int src) { // 1111s + SSE_MOVAPS_XMM_to_XMM(dest, src); +} + +typedef void (*VUMERGEFN)(int dest, int src); +static VUMERGEFN s_VuMerge[16] = { + VU_MERGE0, VU_MERGE1, VU_MERGE2, VU_MERGE3, + VU_MERGE4, VU_MERGE5, VU_MERGE6, VU_MERGE7, + VU_MERGE8, VU_MERGE9, VU_MERGE10, VU_MERGE11, + VU_MERGE12, VU_MERGE13, VU_MERGE14, VU_MERGE15 }; + +#define VU_MERGE_REGS(dest, src) { \ + if( dest != src ) s_VuMerge[_X_Y_Z_W](dest, src); \ +} \ + +#define VU_MERGE_REGS_CUSTOM(dest, src, xyzw) { \ + if( dest != src ) s_VuMerge[xyzw](dest, src); \ +} \ + +void _unpackVF_xyzw(int dstreg, int srcreg, int xyzw) +{ + // don't use pshufd + if( dstreg == srcreg || !cpucaps.hasStreamingSIMD3Extensions) { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + switch (xyzw) { + case 0: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x00); break; + case 1: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); break; + case 2: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xaa); break; + case 3: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); break; + } + } + else { + switch (xyzw) { + case 0: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 1: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 2: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + case 3: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + } + } +} + +void _unpackVFSS_xyzw(int dstreg, int srcreg, int xyzw) +{ + switch (xyzw) { + case 0: + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + break; + case 1: + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); + } + break; + case 2: + SSE_MOVHLPS_XMM_to_XMM(dstreg, srcreg); + break; + case 3: + if( cpucaps.hasStreamingSIMD3Extensions && dstreg != srcreg ) { + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + } + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); + } + break; + } +} + +void _vuFlipRegSS(VURegs * VU, int reg) +{ + assert( _XYZW_SS ); + if( _Y ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xe1); + else if( _Z ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xc6); + else if( _W ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0x27); +} + +void _vuMoveSS(VURegs * VU, int dstreg, int srcreg) +{ + assert( _XYZW_SS ); + if( _Y ) _unpackVFSS_xyzw(dstreg, srcreg, 1); + else if( _Z ) _unpackVFSS_xyzw(dstreg, srcreg, 2); + else if( _W ) _unpackVFSS_xyzw(dstreg, srcreg, 3); + else _unpackVFSS_xyzw(dstreg, srcreg, 0); +} + +void _recvuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((vucycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing FMAC pipe[%d]\n", i); } +#endif + VU->fmac[i].enable = 0; + } + } +} + +void _recvuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((vucycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->fdiv.enable = 0; + } +} + +void _recvuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((vucycle - VU->efu.sCycle) >= VU->efu.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->efu.enable = 0; + } +} + +void _recvuTestPipes(VURegs * VU) { + _recvuFMACflush(VU); + _recvuFDIVflush(VU); + _recvuEFUflush(VU); +} + +void _recvuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + u32 mask = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + (VU->fmac[i].xyzw & xyzw)) break; + } + + if (i == 8) return; + + // do a perchannel delay + // old code +// cycle = VU->fmac[i].Cycle - (vucycle - VU->fmac[i].sCycle); + + // new code + mask = 4; // w +// if( VU->fmac[i].xyzw & 1 ) mask = 4; // w +// else if( VU->fmac[i].xyzw & 2 ) mask = 3; // z +// else if( VU->fmac[i].xyzw & 4 ) mask = 2; // y +// else { +// assert(VU->fmac[i].xyzw & 8 ); +// mask = 1; // x +// } + +// mask = 0; +// if( VU->fmac[i].xyzw & 1 ) mask++; // w +// else if( VU->fmac[i].xyzw & 2 ) mask++; // z +// else if( VU->fmac[i].xyzw & 4 ) mask++; // y +// else if( VU->fmac[i].xyzw & 8 ) mask++; // x + + assert( (int)VU->fmac[i].sCycle < (int)vucycle ); + cycle = 0; + if( vucycle - VU->fmac[i].sCycle < mask ) + cycle = mask - (vucycle - VU->fmac[i].sCycle); + + VU->fmac[i].enable = 0; + vucycle+= cycle; + _recvuTestPipes(VU); +} + +void _recvuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { + SysPrintf("*PCSX2*: error , out of fmacs\n"); + } + +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding FMAC pipe[%d]; reg %d\n", i, reg); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = vucycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].reg = reg; +} + +void _recvuFDIVAdd(VURegs * VU, int cycles) { +// SysPrintf("adding FDIV pipe\n"); + VU->fdiv.enable = 1; + VU->fdiv.sCycle = vucycle; + VU->fdiv.Cycle = cycles; +} + +void _recvuEFUAdd(VURegs * VU, int cycles) { +// SysPrintf("adding EFU pipe\n"); + VU->efu.enable = 1; + VU->efu.sCycle = vucycle; + VU->efu.Cycle = cycles; +} + +void _recvuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + + if( VUregsn->VFread0 && (VUregsn->VFread0 == VUregsn->VFread1) ) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw|VUregsn->VFr1xyzw); + } + else { + if (VUregsn->VFread0) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _recvuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } + } +} + +void _recvuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _recvuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { +// SysPrintf("REG_CLIP_FLAG pipe\n"); + _recvuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _recvuFMACAdd(VU, 0, 0); + } +} + +void _recvuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (vucycle - VU->fdiv.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->fdiv.enable = 0; + vucycle+= cycle; +} + +void _recvuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (vucycle - VU->efu.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->efu.enable = 0; + vucycle+= cycle; +} + +void _recvuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushFDIV(VU); +} + +void _recvuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushEFU(VU); +} + +void _recvuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_Q)) { + _recvuFDIVAdd(VU, VUregsn->cycles); + } +} + +void _recvuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_P)) { + _recvuEFUAdd(VU, VUregsn->cycles); + } +} + +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + } +} + +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuTestEFUStalls(VU, VUregsn); break; + } +} + +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + } +} + +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuAddEFUStalls(VU, VUregsn); break; + } +} + + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs) +{ + _VURegsNum* lregs; + _VURegsNum* uregs; + int *ptr; + + lregs = pCodeRegs; + uregs = pCodeRegs+1; + + ptr = (int*)&VU->Micro[pc]; + pc += 8; + + if (ptr[1] & 0x40000000) { // EOP + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } + + _recvuTestUpperStalls(VU, uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + + if (uregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (uregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + info->cycle = vucycle; + memset(lregs, 0, sizeof(lregs)); + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](lregs); + } + + _recvuTestLowerStalls(VU, lregs); + info->cycle = vucycle; + + if (lregs->pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs->VIwrite & (1 << REG_Q)) { + info->q |= 4; + info->cycles = lregs->cycles; + info->pqinst = (VU->code&2)>>1; // rsqrt is 2 + } + else if (lregs->pipe == VUPIPE_FDIV) { + info->q |= 8|1; + info->pqinst = 0; + } + + if (lregs->VIwrite & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 4; + info->cycles = lregs->cycles; + + switch( VU->code & 0xff ) { + case 0xfd: info->pqinst = 0; break; //eatan + case 0x7c: info->pqinst = 0; break; //eatanxy + case 0x7d: info->pqinst = 0; break; //eatanzy + case 0xfe: info->pqinst = 1; break; //eexp + case 0xfc: info->pqinst = 2; break; //esin + case 0x3f: info->pqinst = 3; break; //erleng + case 0x3e: info->pqinst = 4; break; //eleng + case 0x3d: info->pqinst = 4; break; //ersadd + case 0xbd: info->pqinst = 4; break; //ersqrt + case 0xbe: info->pqinst = 5; break; //ercpr + case 0xbc: info->pqinst = 5; break; //esqrt + case 0x7e: info->pqinst = 5; break; //esum + case 0x3c: info->pqinst = 6; break; //esadd + default: assert(0); + } + } + else if (lregs->pipe == VUPIPE_EFU) { + info->p |= 8|1; + } + + if (lregs->VIread & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_READ; + if (lregs->VIread & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_READ; + + if (lregs->VIwrite & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_WRITE; + if (lregs->VIwrite & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_WRITE; + + if (lregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (lregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + _recvuAddLowerStalls(VU, lregs); + } + _recvuAddUpperStalls(VU, uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +// Analyze an op - first pass +void _vurecAnalyzeOp(VURegs *VU, _vuopinfo *info) { + _VURegsNum lregs; + _VURegsNum uregs; + int *ptr; + +// SysPrintf("_vurecAnalyzeOp %x; %p\n", pc, info); + ptr = (int*)&VU->Micro[pc]; + pc += 8; + +/* SysPrintf("_vurecAnalyzeOp Upper: %s\n", disVU1MicroUF( ptr[1], pc ) ); + if ((ptr[1] & 0x80000000) == 0) { + SysPrintf("_vurecAnalyzeOp Lower: %s\n", disVU1MicroLF( ptr[0], pc ) ); + }*/ + if (ptr[1] & 0x40000000) { + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + } + + _recvuTestUpperStalls(VU, &uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + + if (uregs.VIwrite & (1 << REG_CLIP_FLAG)) { + info->clipflag |= VUOP_WRITE; + } + + if (uregs.VIread & (1 << REG_Q)) { + info->q |= VUOP_READ; + } + + if (uregs.VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= VUOP_READ; + } + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + info->cycle = vucycle; + + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + } + + _recvuTestLowerStalls(VU, &lregs); + info->cycle = vucycle; + + if (lregs.pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs.VIwrite & (1 << REG_Q)) { +// SysPrintf("write to Q\n"); + info->q |= VUOP_WRITE; + info->cycles = lregs.cycles; + } + else if (lregs.pipe == VUPIPE_FDIV) { + info->q |= 8|1; + } + + if (lregs.VIwrite & (1 << REG_P)) { +// SysPrintf("write to P\n"); + info->p |= VUOP_WRITE; + info->cycles = lregs.cycles; + } + else if (lregs.pipe == VUPIPE_EFU) { + assert( VU == &VU1 ); + info->p |= 8|1; + } + + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + info->clipflag|= VUOP_READ; + } + + if (lregs.VIread & (1 << REG_STATUS_FLAG)) { + info->statusflag|= VUOP_READ; + } + + if (lregs.VIread & (1 << REG_MAC_FLAG)) { + info->macflag|= VUOP_READ; + } + + _recvuAddLowerStalls(VU, &lregs); + } + _recvuAddUpperStalls(VU, &uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs) +{ + int info = 0; + int vfread0=-1, vfread1 = -1, vfwrite = -1, vfacc = -1, vftemp=-1; + + assert( regs != NULL ); + + if( regs->VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<VFread0 ) vfread0 = _allocVFtoXMMreg(VU, -1, regs->VFread0, MODE_READ); + else if( regs->VIread & (1<VFread1 ) vfread1 = _allocVFtoXMMreg(VU, -1, regs->VFread1, MODE_READ); + else if( (regs->VIread & (1<VFr1xyzw != 0xff) vfread1 = _allocVFtoXMMreg(VU, -1, 0, MODE_READ); + + if( regs->VIread & (1<VIwrite&(1<VIwrite & (1<VFwxyzw != 0xf?MODE_READ:0)); + } + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwrite, MODE_WRITE|(regs->VFwxyzw != 0xf?MODE_READ:0)); + } + + if( vfacc>= 0 ) info |= PROCESS_EE_SET_ACC(vfacc); + if( vfwrite >= 0 ) { + if( regs->VFwrite == _Ft_ && vfread1 < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite); + } + else { + assert( regs->VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite); + } + } + + if( vfread0 >= 0 ) info |= PROCESS_EE_SET_S(vfread0); + if( vfread1 >= 0 ) info |= PROCESS_EE_SET_T(vfread1); + + vftemp = _allocTempXMMreg(XMMT_FPS, -1); + info |= PROCESS_VU_SET_TEMP(vftemp); + + if( regs->VIwrite & (1 << REG_CLIP_FLAG) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + int t1reg = _allocTempXMMreg(XMMT_FPS, -1); + int t2reg = _allocTempXMMreg(XMMT_FPS, -1); + + info |= PROCESS_EE_SET_D(t1reg); + info |= PROCESS_EE_SET_ACC(t2reg); + + _freeXMMreg(t1reg); // don't need + _freeXMMreg(t2reg); // don't need + } + else if( regs->VIwrite & (1<statusflag & 1 ) info |= PROCESS_VU_UPDATEFLAGS; + if( cinfo->macflag & 1) info |= PROCESS_VU_UPDATEFLAGS; + + if( regs->pipe == 0xff ) info |= PROCESS_VU_COP2; + + return info; +} + +// returns the correct VI addr +u32 GetVIAddr(VURegs * VU, int reg, int read, int info) +{ + if( info & PROCESS_VU_SUPER ) return SuperVUGetVIAddr(reg, read); + if( info & PROCESS_VU_COP2 ) return (u32)&VU->VI[reg].UL; + + if( read != 1 ) { + if( reg == REG_MAC_FLAG ) return (u32)&VU->macflag; + if( reg == REG_CLIP_FLAG ) return (u32)&VU->clipflag; + if( reg == REG_STATUS_FLAG ) return (u32)&VU->statusflag; + if( reg == REG_Q ) return (u32)&VU->q; + if( reg == REG_P ) return (u32)&VU->p; + } + + return (u32)&VU->VI[reg].UL; +} + +// gets a temp reg that is not EEREC_TEMP +int _vuGetTempXMMreg(int info) +{ + int t1reg = -1; + + if( _hasFreeXMMreg() ) { + t1reg = _allocTempXMMreg(XMMT_FPS, -1); + if( t1reg == EEREC_TEMP && _hasFreeXMMreg() ) { + int t = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t1reg); + t1reg = t; + _freeXMMreg(t1reg); + } + else { + _freeXMMreg(t1reg); + t1reg = -1; + } + } + + return t1reg; +} + +PCSX2_ALIGNED16(u32 g_minvals[4]) = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}; +PCSX2_ALIGNED16(u32 g_maxvals[4]) = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}; + +static PCSX2_ALIGNED16(int const_clip[]) = { + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + +static PCSX2_ALIGNED16(u32 s_FloatMinMax[]) = { + 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, + 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, + 0, 0, 0, 0 }; + +static PCSX2_ALIGNED16(float s_fones[]) = { 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f }; +static PCSX2_ALIGNED16(u32 s_mask[]) = {0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff }; +static PCSX2_ALIGNED16(u32 s_expmask[]) = {0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000}; + +void CheckForOverflowSS_(int fdreg, int t0reg) +{ + assert( t0reg != fdreg ); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDSS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVSS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNESS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow_(int fdreg, int t0reg, int keepxyzw) +{ +// SSE_MAXPS_M128_to_XMM(fdreg, (u32)g_minvals); +// SSE_MINPS_M128_to_XMM(fdreg, (u32)g_maxvals); + + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, fdreg); + // for partial masks, sometimes regs can be integers + if( keepxyzw != 15 ) + SSE_ORPS_M128_to_XMM(t0reg, (u32)&SSEmovMask[15-keepxyzw][0]); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVAPS_M128_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNEPS_M128_to_XMM(t0reg, (u32)s_expmask); +// //SSE_ORPS_M128_to_XMM(t0reg, (u32)g_minvals); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow(VURegs *VU, int info, int regd) +{ + if( CHECK_FORCEABS && EEREC_TEMP != regd) { + // changing the order produces different results (tektag) + CheckForOverflow_(regd, EEREC_TEMP, _X_Y_Z_W); + } +} + +// if unordered replaces with 0x7f7fffff (note, loses sign) +void ClampUnordered(int regd, int t0reg, int dosign) +{ + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, regd); + SSE_ANDPS_XMM_to_XMM(regd, t0reg); + SSE_ANDNPS_M128_to_XMM(t0reg, (u32)g_maxvals); + SSE_ORPS_XMM_to_XMM(regd, t0reg); +} + +// VU Flags +// NOTE: flags don't compute under/over flows since it is highly unlikely +// that games used them. Including them will lower performance. +int g_VUSignedZero=0; // most games like =0, one game likes !=0 +int g_VUExtraFlags=0; +void recUpdateFlags(VURegs * VU, int reg, int info) +{ + u32 flagmask; + u8* pjmp; + u32 macaddr, stataddr, prevstataddr; + int x86macflag, x86newflag, x86oldflag; + const static u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + if( !(info & PROCESS_VU_UPDATEFLAGS) ) + return; + + flagmask = macarr[_X_Y_Z_W]; + macaddr = VU_VI_ADDR(REG_MAC_FLAG, 0); + stataddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + prevstataddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + if( stataddr == 0 ) { + stataddr = prevstataddr; + } + //assert( stataddr != 0); + + + // 20 insts + x86newflag = ALLOCTEMPX86(MODE_8BITREG); + x86macflag = ALLOCTEMPX86(0); + x86oldflag = ALLOCTEMPX86(0); + + // can do with 8 bits since only computing zero/sign flags + if( EEREC_TEMP != reg ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_CMPEQPS_XMM_to_XMM(EEREC_TEMP, reg); + + MOV32MtoR(x86oldflag, prevstataddr); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + XOR32RtoR(EAX, EAX); + + if( !g_VUSignedZero ) { + SSE_ANDNPS_XMM_to_XMM(EEREC_TEMP, reg); // necessary! + } + + AND32ItoR(x86newflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + if( !g_VUSignedZero ) SSE_MOVMSKPS_XMM_to_R32(x86macflag, EEREC_TEMP); // sign + else SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // sign + + SHL32ItoR(x86newflag, 4); + AND32ItoR(x86macflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + OR32RtoR(x86macflag, x86newflag); + } + else { + SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // mask is < 0 (including 80000000) + + MOV32MtoR(x86oldflag, prevstataddr); + XOR32RtoR(EAX, EAX); + + SSE_CMPEQPS_M128_to_XMM(EEREC_TEMP, (u32)&s_FloatMinMax[8]); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + if( !g_VUSignedZero ) { + NOT32R(x86newflag); + AND32RtoR(x86macflag, x86newflag); + } + + AND32ItoR(x86macflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + if( !g_VUSignedZero ) { + NOT32R(x86newflag); + } + + AND32ItoR(x86newflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SHL32ItoR(x86newflag, 4); + OR32RtoR(x86macflag, x86newflag); + } + + // x86macflag - new untransformed mac flag, EAX - new status bits, x86oldflag - old status flag + // x86macflag = zero_wzyx | sign_wzyx + MOV8RmtoROffset(x86newflag, x86macflag, (u32)g_MACFlagTransform); // transform + //MOV16RmSOffsettoR(x86newflag, x86macflag, (u32)g_MACFlagTransform, 1); + MOV32RtoR(x86macflag, x86oldflag); + SHL32ItoR(x86macflag, 6); + OR32RtoR(x86oldflag, x86macflag); + + if( macaddr != 0 ) { + + MOV8RtoM(macaddr, x86newflag); + + if( g_VUExtraFlags && flagmask != 0xf ) { + MOV8MtoR(x86newflag, VU_VI_ADDR(REG_MAC_FLAG, 2)); // get previous written + AND8ItoR(x86newflag, ~g_MACFlagTransform[(flagmask|(flagmask<<4))]); + OR8RtoM(macaddr, x86newflag); + } + } + + AND32ItoR(x86oldflag, 0x0c0); + OR32RtoR(x86oldflag, EAX); + MOV32RtoM(stataddr, x86oldflag); + + _freeX86reg(x86macflag); + _freeX86reg(x86newflag); + _freeX86reg(x86oldflag); +} + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +static PCSX2_ALIGNED16(int const_abs_table[16][4]) = +{ + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, +}; + +void recVUMI_ABS(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_T, (int)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + } +} + +PCSX2_ALIGNED16(float s_two[4]) = {0,0,0,2}; + +void recVUMI_ADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_two); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_two); + } + } + else { + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + +// if( _Fd_ == 0 && (_Fs_ == 0 || _Ft_ == 0) ) +// info |= PROCESS_VU_UPDATEFLAGS; + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_ADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Ft_ == 0 && xyzw < 3 ) { + // just move + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if( _Fs_ == 0 && !_W ) { + // just move + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADDi(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDq(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDx(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 0, info); } +void recVUMI_ADDy(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 1, info); } +void recVUMI_ADDz(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 2, info); } +void recVUMI_ADDw(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 3, info); } + +void recVUMI_ADDA(VURegs *VU, int info) +{ + if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + assert( EEREC_ACC != EEREC_TEMP ); + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_ACC, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( _Fs_ == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_ACC, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDAi(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDAq(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDAx(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 0, info); } +void recVUMI_ADDAy(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 1, info); } +void recVUMI_ADDAz(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 2, info); } +void recVUMI_ADDAw(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 3, info); } + +void recVUMI_SUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_D, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Ft_ > 0 || _W ) SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + // neopets works better with this? + //CheckForOverflow(info, EEREC_D); +} + +void recVUMI_SUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if (EEREC_D != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +static PCSX2_ALIGNED16(s_unaryminus[4]) = {0x80000000, 0, 0, 0}; + +void recVUMI_SUB_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, xyzw); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + if( _Fs_ > 0 ) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)s_unaryminus); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } +// else if( _XYZW_SS && xyzw == 0 ) { +// if( EEREC_D == EEREC_S ) { +// if( EEREC_D == EEREC_T ) { +// SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } +// else if( EEREC_D == EEREC_T ) { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_SUBi(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBq(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBx(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 0, info); } +void recVUMI_SUBy(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 1, info); } +void recVUMI_SUBz(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 2, info); } +void recVUMI_SUBw(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 3, info); } + +void recVUMI_SUBA(VURegs *VU, int info) +{ + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_ACC, (u32)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_ACC); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBAi(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBAq(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBAx(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 0, info); } +void recVUMI_SUBAy(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 1, info); } +void recVUMI_SUBAz(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 2, info); } +void recVUMI_SUBAw(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 3, info); } + +void recVUMI_MUL_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W == 1 && (_Ft_ == 0 || _Fs_==0) ) { // W + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, _Ft_ ? EEREC_T : EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( _Fd_ == _Fs_ && _Fs_ == _Ft_ && _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_D); + _vuFlipRegSS(VU, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (regd == EEREC_S) SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + } + } +} + +void recVUMI_MUL_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _XYZW_SS ) { + if( regd == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( regd == EEREC_S ) { + _vuFlipRegSS(VU, regd); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, regd); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + if( xyzw < 3 ) { + if (_X_Y_Z_W != 0xf) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + SSE_XORPS_XMM_to_XMM(regd, regd); + } + } + else { + assert(xyzw==3); + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( regd != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( regd == EEREC_T ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MUL_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + // spacefisherman needs overflow checking on MULi.z + if( addr == VU_REGQ_ADDR || _Z ) + CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MUL_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MULi(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULq(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULx(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 0, info); } +void recVUMI_MULy(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 1, info); } +void recVUMI_MULz(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 2, info); } +void recVUMI_MULw(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 3, info); } + +void recVUMI_MULA( VURegs *VU, int info ) +{ + recVUMI_MUL_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_iq(VURegs *VU, int addr, int info) +{ + recVUMI_MUL_iq_toD(VU, addr, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_xyzw(VURegs *VU, int xyzw, int info) +{ + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULAi(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULAq(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULAx(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 0, info); } +void recVUMI_MULAy(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 1, info); } +void recVUMI_MULAz(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 2, info); } +void recVUMI_MULAw(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 3, info); } + +void recVUMI_MADD_toD(VURegs *VU, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } +} + +void recVUMI_MADD_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + if( _Fs_ == 0 ) { + // add addr to w + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + else { + assert( EEREC_TEMP < XMMREGS ); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else if( regd == EEREC_S ) { + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else { + if( _Fs_ == 0 ) { + // add addr to w + if( _W ) { + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + + return; + } + + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + + if( xyzw == 3 ) { + // just add + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_S ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_S); + } + } + else { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_S ) SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_S); + } + } + } + } + else { + // just move acc to regd + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + + return; + } + + if( _X_Y_Z_W == 8 ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if( regd == EEREC_ACC ) { + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + // super bust-a-move arrows + CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MADDi(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MADDq(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MADDx(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 0, info); } +void recVUMI_MADDy(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 1, info); } +void recVUMI_MADDz(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 2, info); } +void recVUMI_MADDw(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 3, info); } + +void recVUMI_MADDA( VURegs *VU, int info ) +{ + recVUMI_MADD_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAi( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_VI_ADDR(REG_I, 1), EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAq( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_REGQ_ADDR, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAx( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 0, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAy( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 1, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAz( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 2, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAw( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 3, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUB_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_S ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_T ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_temp_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + if( regd != EEREC_TEMP ) { + VU_MERGE_REGS(regd, t1reg); + } + else + SSE_MOVAPS_XMM_to_XMM(regd, t1reg); + + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (u32)&const_clip[4]); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_iq_toD(VURegs *VU, int regd, int addr, int info) +{ + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB_xyzw_toD(VURegs *VU, int regd, int xyzw, int info) +{ + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_iq_toD(VU, EEREC_D, addr, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MSUBi(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MSUBq(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MSUBx(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 0, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBy(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 1, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBz(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 2, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBw(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 3, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBA( VURegs *VU, int info ) +{ + recVUMI_MSUB_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAi( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_VI_ADDR(REG_I, 1), info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAq( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_REGQ_ADDR, info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAx( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 0, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAy( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 1, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAz( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 2, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAw( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 3, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MAX(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MAX_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MAX_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + else if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + if( _X_Y_Z_W & 1 ) { + // w included, so insert the whole reg + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[0]); + } + else { + // w not included, can zero out + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + } + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + } + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + else SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_fones); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } +} + +void recVUMI_MAXi(VURegs *VU, int info) { recVUMI_MAX_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MAXx(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 0, info); } +void recVUMI_MAXy(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 1, info); } +void recVUMI_MAXz(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 2, info); } +void recVUMI_MAXw(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 3, info); } + +void recVUMI_MINI(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_T, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_S, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MINI_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINI_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINIi(VURegs *VU, int info) { recVUMI_MINI_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MINIx(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 0, info); } +void recVUMI_MINIy(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 1, info); } +void recVUMI_MINIz(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 2, info); } +void recVUMI_MINIw(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 3, info); } + +void recVUMI_OPMULA( VURegs *VU, int info ) +{ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xD2); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T ); + + VU_MERGE_REGS_CUSTOM(EEREC_ACC, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_ACC ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_OPMSUB( VURegs *VU, int info ) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM( EEREC_T, EEREC_T, 0xD2 ); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T); + + // negate and add + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (u32)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS_CUSTOM(EEREC_D, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_D ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_NOP( VURegs *VU, int info ) +{ +} + +void recVUMI_FTOI0(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_FTOIX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if (EEREC_T != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + } +} + +void recVUMI_FTOI4( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int4[0], info); } +void recVUMI_FTOI12( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int12[0], info); } +void recVUMI_FTOI15( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (int)&recMult_float_to_int15[0], info); } + +void recVUMI_ITOF0( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + } +} + +void recVUMI_ITOFX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + } +} + +void recVUMI_ITOF4( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float4[0], info); } +void recVUMI_ITOF12( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float12[0], info); } +void recVUMI_ITOF15( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (int)&recMult_int_to_float15[0], info); } + +void recVUMI_CLIP(VURegs *VU, int info) +{ + int t1reg = EEREC_D; + int t2reg = EEREC_ACC; + int x86temp0, x86temp1; + + u32 clipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + u32 prevclipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 2); + + if( clipaddr == 0 ) { + // battle star has a clip right before fcset + SysPrintf("skipping vu clip\n"); + return; + } + assert( clipaddr != 0 ); + assert( t1reg != t2reg && t1reg != EEREC_TEMP && t2reg != EEREC_TEMP ); + + x86temp1 = ALLOCTEMPX86(MODE_8BITREG); + x86temp0 = ALLOCTEMPX86(0); + + if( _Ft_ == 0 ) { + // all 1s + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)&s_fones[0]); + SSE_MOVAPS_M128_to_XMM(t1reg, (u32)&s_fones[4]); + + MOV32MtoR(EAX, prevclipaddr); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, 3); + SSE_XORPS_XMM_to_XMM(t1reg, t1reg); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)const_clip); + + MOV32MtoR(EAX, prevclipaddr); + + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + } + + SSE_CMPLTPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_CMPNLEPS_XMM_to_XMM(t1reg, EEREC_S); + + SHL32ItoR(EAX, 6); + + SSE_MOVAPS_XMM_to_XMM(t2reg, EEREC_TEMP); + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, t1reg); + SSE_UNPCKHPS_XMM_to_XMM(t2reg, t1reg); + SSE_MOVMSKPS_XMM_to_R32(x86temp0, EEREC_TEMP); // -y,+y,-x,+x + SSE_MOVMSKPS_XMM_to_R32(x86temp1, t2reg); // -w,+w,-z,+z + + AND32ItoR(EAX, 0xffffff); + + AND8ItoR(x86temp1, 0x3); + SHL32ItoR(x86temp1, 4); + OR32RtoR(EAX, x86temp0); + OR32RtoR(EAX, x86temp1); + + MOV32RtoM(clipaddr, EAX); + if( !(info&(PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void recVUMI_DIV(VURegs *VU, int info) +{ + if( _Fs_ == 0 ) { + + if( _Ft_ == 0 ) { + if( _Fsf_ < 3 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0); + else if( _Ftf_ < 0 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x7f7fffff); + else MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x3f800000); + return; + } + + if( _Fsf_ == 3 ) { // = 1 + // don't use RCPSS (very bad precision) + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + if( _Ftf_ == 0 || (xmmregs[EEREC_T].mode & MODE_WRITE) ) { + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + } + } + else { // = 0 + MOV32ItoR(VU_VI_ADDR(REG_Q, 0), 0); + return; + } + } + else { + if( _Fsf_ == 0 ) SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + // revert + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_SQRT( VURegs *VU, int info ) +{ + if( _Ftf_ ) { + if( xmmregs[EEREC_T].mode & MODE_WRITE ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Ft_].UL[_Ftf_]); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_RSQRT(VURegs *VU, int info) +{ + if( _Ftf_ ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + if( _Fs_ == 0 ) { + if( _Fsf_ == 3 ) SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void _addISIMMtoIT(VURegs *VU, s16 imm, int info) +{ + int fsreg = -1, ftreg; + if (_Ft_ == 0) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32ItoR(ftreg, imm&0xffff); + return; + } + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if (ftreg == fsreg) { + if (imm != 0 ) { + ADD16ItoR(ftreg, imm); + } + } else { + if( imm ) { + LEA32RtoR(ftreg, fsreg, imm); + MOVZX32R16toR(ftreg, ftreg); + } + else MOV32RtoR(ftreg, fsreg); + } +} + +void recVUMI_IADDI(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code >> 6 ) & 0x1f; + imm = ( imm & 0x10 ? 0xfff0 : 0) | ( imm & 0xf ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADDIU(VURegs *VU, int info) +{ + int imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADD( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else { + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) ADD32RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) ADD32RtoR(fdreg, fsreg); + else LEA16RRtoR(fdreg, fsreg, ftreg); + MOVZX32R16toR(fdreg, fdreg); // neeed since don't know if fdreg's upper bits are 0 + } +} + +void recVUMI_IAND( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Fs_ == 0 ) || ( _Ft_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) AND16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) AND16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, ftreg); + AND32RtoR(fdreg, fsreg); + } +} + +void recVUMI_IOR( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) OR16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) OR16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, fsreg); + OR32RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUB( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + NEG16R(fdreg); + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) SUB16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) { + SUB16RtoR(fdreg, fsreg); + NEG16R(fdreg); + } + else { + MOV32RtoR(fdreg, fsreg); + SUB16RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUBIU( VURegs *VU, int info ) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + imm = -imm; + _addISIMMtoIT(VU, (u32)imm & 0xffff, info); +} + +void recVUMI_MOVE( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_MFIR( VURegs *VU, int info ) +{ + static u32 s_temp; + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, 1); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _XYZW_SS ) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + _vuFlipRegSS(VU, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + SSE2_MOVD_M32_to_XMM(EEREC_T, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_T, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } + else { + MOVSX32M16toR(EAX, VU_VI_ADDR(_Fs_, 1)); + MOV32RtoM((u32)&s_temp, EAX); + + if( _X_Y_Z_W != 0xf ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, (u32)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } +} + +void recVUMI_MTIR( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, 2); + + if( _Fsf_ == 0 ) { + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_S); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_TEMP); + } + + AND32ItoM(VU_VI_ADDR(_Ft_, 0), 0xffff); +} + +void recVUMI_MR32( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x39); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x39); + } +} + +// if x86reg < 0, reads directly from offset +void _loadEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + if( x86reg >= 0 ) { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + + case 8: // X + SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } + else { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_M64_to_XMM(EEREC_T, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + case 8: // X + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_M64_to_XMM(EEREC_T, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_T, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_T, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } +} + +int recVUTransformAddr(int x86reg, VURegs* VU, int vireg, int imm) +{ + u8* pjmp[2]; + if( x86reg == EAX ) { + if (imm) ADD32ItoR(x86reg, imm); + } + else { + if( imm ) LEA32RtoR(EAX, x86reg, imm); + else MOV32RtoR(EAX, x86reg); + } + + if( VU == &VU1 ) { + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0x3fff); + } + else { + // if addr >= 4200, reads integers + CMP32ItoR(EAX, 0x420); + pjmp[0] = JL8(0); + AND32ItoR(EAX, 0x1f); + SHL32ItoR(EAX, 2); + OR32ItoR(EAX, 0x4200); + + pjmp[1] = JMP8(0); + x86SetJ8(pjmp[0]); + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0xfff); // can be removed + + x86SetJ8(pjmp[1]); + } + + return EAX; +} + +void recVUMI_LQ(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)GET_VU_MEM(VU, (u32)imm*16), info); + } else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_LQD( VURegs *VU, int info ) +{ + int fsreg; + + if ( _Fs_ != 0 ) { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + SUB16ItoR( fsreg, 1 ); + } + + if ( _Ft_ == 0 ) return; + + if ( _Fs_ == 0 ) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_LQI(VURegs *VU, int info) +{ + int fsreg; + + if ( _Ft_ == 0 ) { + if( _Fs_ != 0 ) { + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_WRITE|MODE_READ)) >= 0 ) { + ADD16ItoR(fsreg, 1); + } + else { + ADD16ItoM( VU_VI_ADDR( _Fs_, 0 ), 1 ); + } + } + return; + } + + if (_Fs_ == 0) { + _loadEAX(VU, -1, (u32)VU->Mem, info); + } else { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (u32)VU->Mem, info); + ADD16ItoR( fsreg, 1 ); + } +} + +void _saveEAX(VURegs *VU, int x86reg, u32 offset, int info) +{ + int t1reg; + + if( _Fs_ == 0 ) { + if( _XYZW_SS ) { + u32 c = _W ? 0x3f800000 : 0; + if( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); + else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c); + } + else { + int zeroreg = (x86reg == EAX) ? ALLOCTEMPX86(0) : EAX; + + XOR32RtoR(zeroreg, zeroreg); + if( x86reg >= 0 ) { + if( _X ) MOV32RtoRmOffset(x86reg, zeroreg, offset); + if( _Y ) MOV32RtoRmOffset(x86reg, zeroreg, offset+4); + if( _Z ) MOV32RtoRmOffset(x86reg, zeroreg, offset+8); + if( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12); + } + else { + if( _X ) MOV32RtoM(offset, zeroreg); + if( _Y ) MOV32RtoM(offset+4, zeroreg); + if( _Z ) MOV32RtoM(offset+8, zeroreg); + if( _W ) MOV32ItoM(offset+12, 0x3f800000); + } + + if( zeroreg != EAX ) _freeX86reg(zeroreg); + } + return; + } + + switch(_X_Y_Z_W) { + case 1: // W + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + break; + case 2: // Z + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + break; + case 3: // ZW + if( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S); + break; + case 4: // Y + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + break; + case 6: // YZ + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xc9); + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xd2); + break; + case 8: // X + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + break; + case 9: // XW + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); + + break; + case 12: // XY + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + break; + + case 14: // XYZ + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) { + SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + } + else { + SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + } + break; + case 15: // XYZW + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + } + break; + default: + + // EEREC_D is a temp reg + // find the first nonwrite reg + t1reg = _vuGetTempXMMreg(info); + + if( t1reg < 0 ) { + for(t1reg = 0; t1reg < XMMREGS; ++t1reg) { + if( xmmregs[t1reg].inuse && !(xmmregs[t1reg].mode&MODE_WRITE) ) break; + } + + if( t1reg == XMMREGS ) t1reg = -1; + else { + if( t1reg != EEREC_S ) _allocTempXMMreg(XMMT_FPS, t1reg); + } + } + + if( t1reg >= 0 ) { + // found a temp reg + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + if( t1reg != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + + VU_MERGE_REGS(EEREC_TEMP, t1reg); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + } + + if( t1reg != EEREC_S ) _freeXMMreg(t1reg); + else { + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + } + else { + // do it with one reg + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + VU_MERGE_REGS(EEREC_TEMP, EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + } + + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (u32)&VU->VF[_Fs_]); + } + + break; + } +} + +void recVUMI_SQ(VURegs *VU, int info) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if ( _Ft_ == 0 ) { + _saveEAX(VU, -1, (u32)GET_VU_MEM(VU, (int)imm * 16), info); + } + else { + int ftreg = ALLOCVI(_Ft_, MODE_READ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, imm), (u32)VU->Mem, info); + } +} + +void recVUMI_SQD(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + SUB16ItoR( ftreg, 1 ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + } +} + +void recVUMI_SQI(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (u32)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (u32)VU->Mem, info); + + ADD16ItoR( ftreg, 1 ); + } +} + +void recVUMI_ILW(VURegs *VU, int info) +{ + int ftreg; + s16 imm, off; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (u32)GET_VU_MEM(VU, (int)imm * 16 + off) ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (u32)VU->Mem + off); + } +} + +void recVUMI_ISW( VURegs *VU, int info ) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + + if (_Fs_ == 0) { + u32 off = (u32)GET_VU_MEM(VU, (int)imm * 16); + int ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_X) MOV32RtoM(off, ftreg); + if (_Y) MOV32RtoM(off+4, ftreg); + if (_Z) MOV32RtoM(off+8, ftreg); + if (_W) MOV32RtoM(off+12, ftreg); + } + else { + int x86reg, fsreg, ftreg; + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_ILWR( VURegs *VU, int info ) +{ + int off, ftreg; + + if ( _Ft_ == 0 ) return; + + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (int)VU->Mem + off ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (int)VU->Mem + off); + } +} + +void recVUMI_ISWR( VURegs *VU, int info ) +{ + int ftreg; + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_Fs_ == 0) { + if (_X) MOV32RtoM((int)VU->Mem, ftreg); + if (_Y) MOV32RtoM((int)VU->Mem+4, ftreg); + if (_Z) MOV32RtoM((int)VU->Mem+8, ftreg); + if (_W) MOV32RtoM((int)VU->Mem+12, ftreg); + } + else { + int x86reg; + int fsreg = ALLOCVI(_Fs_, MODE_READ); + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (u32)VU->Mem+12); + } +} + +void recVUMI_RINIT(VURegs *VU, int info) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 2); + + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + MOV32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR( rreg, 0x7f << 23 ); + } +} + +void recVUMI_RGET(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + + if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +void recVUMI_RNEXT( VURegs *VU, int info ) +{ + int rreg, x86temp0, x86temp1; + if ( _Ft_ == 0) return; + + rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + x86temp0 = ALLOCTEMPX86(0); + x86temp1 = ALLOCTEMPX86(0); + + // code from www.project-fao.org + MOV32MtoR(rreg, VU_REGR_ADDR); + MOV32RtoR(x86temp0, rreg); + SHR32ItoR(x86temp0, 4); + AND32ItoR(x86temp0, 1); + + MOV32RtoR(x86temp1, rreg); + SHR32ItoR(x86temp1, 22); + AND32ItoR(x86temp1, 1); + + SHL32ItoR(rreg, 1); + XOR32RtoR(x86temp0, x86temp1); + XOR32RtoR(rreg, x86temp0); + AND32ItoR(rreg, 0x7fffff); + OR32ItoR(rreg, 0x3f800000); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); + + recVUMI_RGET(VU, info); +} + +void recVUMI_RXOR( VURegs *VU, int info ) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode & MODE_NOFLUSH) ) { + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_XORPS_M128_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + XOR32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR ( rreg, 0x3f800000 ); + } +} + +void recVUMI_WAITQ( VURegs *VU, int info ) +{ +// if( info & PROCESS_VU_SUPER ) { +// //CALLFunc(waitqfn); +// SuperVUFlush(0, 1); +// } +} + +void recVUMI_FSAND( VURegs *VU, int info ) +{ + int ftreg; + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32MtoR(ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1)); + AND32ItoR( ftreg, 0xFF&imm ); // yes 0xff not 0xfff since only first 8 bits are valid! +} + +void recVUMI_FSEQ( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if ( _Ft_ == 0 ) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( EAX, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + XOR32RtoR(ftreg, ftreg); + + CMP16ItoR(EAX, imm); + SETE8R(ftreg); +} + +void recVUMI_FSOR( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if(_Ft_ == 0) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + OR32ItoR( ftreg, imm ); +} + +void recVUMI_FSSET(VURegs *VU, int info) +{ + u32 writeaddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + u32 prevaddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + + MOV32MtoR(EAX, prevaddr); + AND32ItoR(EAX, 0x3f); + if ((imm&0xfc0) != 0) OR32ItoR(EAX, imm & 0xFC0); + + MOV32RtoM(writeaddr ? writeaddr : prevaddr, EAX); +} + +void recVUMI_FMAND( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + assert(ftreg < 4 ); + + if( fsreg >= 0 ) { + if( ftreg != fsreg ) MOV32RtoR(ftreg, fsreg); + } + else MOV8MtoR(ftreg, VU_VI_ADDR(_Fs_, 1)); + + //AND16MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + AND8MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + MOVZX32R8toR(ftreg, ftreg); +} + +void recVUMI_FMEQ( VURegs *VU, int info ) +{ + int ftreg, fsreg; + if ( _Ft_ == 0 ) return; + + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + // really 8 since not doing under/over flows + CMP8MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(EAX); + MOVZX32R8toR(ftreg, EAX); + } + else { + ADD_VI_NEEDED(_Fs_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + + XOR32RtoR(ftreg, ftreg); + + CMP8MtoR(fsreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(ftreg); + } +} + +void recVUMI_FMOR( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + MOVZX32M8toR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + OR8MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + else { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + + if( fsreg >= 0 ) { + OR16RtoR( ftreg, fsreg); + } + else { + OR16MtoR( ftreg, VU_VI_ADDR(_Fs_, 1)); + } + } +} + +void recVUMI_FCAND( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + XOR32RtoR(ftreg, ftreg); + AND32ItoR( EAX, VU->code & 0xFFFFFF ); + SETNZ8R(ftreg); +} + +void recVUMI_FCEQ( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + CMP32ItoR( EAX, VU->code&0xffffff ); + SETE8R(ftreg); +} + +void recVUMI_FCOR( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + OR32ItoR( EAX, (VU->code & 0xFFFFFF)|0xff000000 ); + ADD32ItoR(EAX, 1); + + // set to 1 if EAX is 0 + SETZ8R(ftreg); +} + +void recVUMI_FCSET( VURegs *VU, int info ) +{ + u32 addr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + + MOV32ItoM(addr ? addr : VU_VI_ADDR(REG_CLIP_FLAG, 2), VU->code&0xffffff ); + + if( !(info & (PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) + MOV32ItoM( VU_VI_ADDR(REG_CLIP_FLAG, 1), VU->code&0xffffff ); +} + +void recVUMI_FCGET( VURegs *VU, int info ) +{ + int ftreg; + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOV32MtoR(ftreg, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + AND32ItoR(ftreg, 0x0fff); +} + +// SuperVU branch fns are in ivuzerorec.cpp +static s32 _recbranchAddr(VURegs * VU) +{ + bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void recVUMI_IBEQ(VURegs *VU, int info) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBNE( VURegs *VU, int info ) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_B(VURegs *VU, int info) +{ + // supervu will take care of the rest + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + branch |= 3; +} + +void recVUMI_BAL( VURegs *VU, int info ) +{ + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_JR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + branch |= 3; +} + +void recVUMI_JALR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_MFP(VURegs *VU, int info) +{ + if (_Ft_ == 0) return; + + if( _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_T); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +static PCSX2_ALIGNED16(float s_tempmem[4]); + +void recVUMI_WAITP(VURegs *VU, int info) +{ +// if( info & PROCESS_VU_SUPER ) +// SuperVUFlush(1, 1); +} + +// in all EFU insts, EEREC_D is a temp reg +void vuSqSumXYZ(int regd, int regs, int regtemp) +{ + SSE_MOVAPS_XMM_to_XMM(regtemp, regs); + SSE_MULPS_XMM_to_XMM(regtemp, regtemp); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(regd, regtemp); + SSE_ADDPS_XMM_to_XMM(regd, regtemp); // regd.z = x+y+z + SSE_MOVHLPS_XMM_to_XMM(regd, regd); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(regd, regtemp); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + SSE_SHUFPS_XMM_to_XMM(regtemp, regtemp, 0x55); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + } +} + +void recVUMI_ESADD( VURegs *VU, int info) +{ + assert( VU == &VU1 ); + if( EEREC_TEMP != EEREC_D ) { + vuSqSumXYZ(EEREC_TEMP, EEREC_S, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); + } + else { + // special code to reset P + MOV32ItoM(VU_VI_ADDR(REG_P, 0), 0); + } +} + +void recVUMI_ERSADD( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + // almost same as vuSqSumXYZ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); // EEREC_D.z = x+y+z + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_D); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + } + + // don't use RCPSS (very bad precision) + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ELENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERLENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_EATANxy( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[1]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[1]); + } + + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATANxz( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((u32)&s_tempmem[0]); + FLD32((u32)&s_tempmem[2]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[0]); + FLD32((u32)&VU->VF[_Fs_].UL[2]); + } + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_ESUM( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); // y+w, x+z + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); // y+w, y+w, x+z, x+z + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERCPR( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[0].UL[3]); + + // don't use RCPSS (very bad precision) + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + // revert + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (u32)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (u32)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERSQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_TEMP, (u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESIN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + FSIN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATAN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FLD32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + } + + FLD1(); + FLD32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EEXP( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + FLDL2E(); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((u32)&s_tempmem[2], EEREC_S); + } + FMUL32((u32)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FMUL32((u32)&VU->VF[_Fs_].UL[_Fsf_]); + } + + // basically do 2^(log_2(e) * val) + FLD(0); + FRNDINT(); + FXCH(1); + FSUB32Rto0(1); + F2XM1(); + FLD1(); + FADD320toR(1); + FSCALE(); + FSTP(1); + + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_XITOP( VURegs *VU, int info ) +{ + int ftreg; + if (_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->itop ); +} + +void recVUMI_XTOP( VURegs *VU, int info ) +{ + int ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (int)&VU->vifRegs->top ); +} + +extern HANDLE g_hGsEvent; + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) +{ + u32 size; + u8* pmem; + u32* data = (u32*)((u8*)pMem + (addr&0x3fff)); + + static int scount = 0; + ++scount; + + size = GSgifTransferDummy(0, data, 0x4000>>4); + + size = 0x4000-(size<<4); + assert( size > 0 && addr+size <= 0x4000 ); + + pmem = GSRingBufCopy(NULL, size, GS_RINGTYPE_P1); + assert( pmem != NULL ); + + memcpy_amd(pmem, (u8*)pMem+addr, size); + GSRINGBUF_DONECOPY(pmem, size); + + if( !CHECK_DUALCORE ) { + SetEvent(g_hGsEvent); + } +} + +void recVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + PUSH32R(fsreg); + PUSH32I((int)VU->Mem); + iFlushCall(FLUSH_NOCONST); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { + CALLFunc((int)GSgifTransfer1); + } +} diff --git a/branches/pcsx2_0.9.2/x86/iVUmicro.h b/branches/pcsx2_0.9.2/x86/iVUmicro.h new file mode 100644 index 0000000..2e38d50 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVUmicro.h @@ -0,0 +1,274 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVUMICRO_H__ +#define __IVUMICRO_H__ + +#define VU0_MEMSIZE 0x1000 +#define VU1_MEMSIZE 0x4000 + +#define RECOMPILE_VUMI_ABS +#define RECOMPILE_VUMI_SUB +#define RECOMPILE_VUMI_SUBA +#define RECOMPILE_VUMI_MADD +#define RECOMPILE_VUMI_MADDA +#define RECOMPILE_VUMI_MSUB +#define RECOMPILE_VUMI_MSUBA + +#define RECOMPILE_VUMI_ADD +#define RECOMPILE_VUMI_ADDA +#define RECOMPILE_VUMI_MUL +#define RECOMPILE_VUMI_MULA +#define RECOMPILE_VUMI_MAX +#define RECOMPILE_VUMI_MINI +#define RECOMPILE_VUMI_FTOI + +#define RECOMPILE_VUMI_MATH +#define RECOMPILE_VUMI_MISC +#define RECOMPILE_VUMI_E +#define RECOMPILE_VUMI_X +#define RECOMPILE_VUMI_RANDOM +#define RECOMPILE_VUMI_FLAG +#define RECOMPILE_VUMI_BRANCH +#define RECOMPILE_VUMI_ARITHMETIC +#define RECOMPILE_VUMI_LOADSTORE + +#ifdef __x86_64__ +#undef RECOMPILE_VUMI_X +#endif + +u32 GetVIAddr(VURegs * VU, int reg, int read, int info); // returns the correct VI addr +void recUpdateFlags(VURegs * VU, int reg, int info); + +void _recvuTestPipes(VURegs * VU); +void _recvuFlushFDIV(VURegs * VU); +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +#define VUOP_READ 2 +#define VUOP_WRITE 4 + +// save on mem +typedef struct { + int cycle; + int cycles; + u8 statusflag; + u8 macflag; + u8 clipflag; + u8 dummy; + u8 q; + u8 p; + u16 pqinst; // bit of instruction specifying index (srec only) +} _vuopinfo; +extern _vuopinfo *cinfo; + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs); + +// allocates all the necessary regs and returns the indices +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs); + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr); // used for MTGS in XGKICK + +extern _VURegsNum* g_VUregs; + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; +#define VUREC_INFO eeVURecompileCode(VU, g_VUregs) + +extern int vucycle; +extern int vucycleold; + + +/***************************************** + VU Micromode Upper instructions +*****************************************/ + +void recVUMI_ABS(VURegs *vuRegs, int info); +void recVUMI_ADD(VURegs *vuRegs, int info); +void recVUMI_ADDi(VURegs *vuRegs, int info); +void recVUMI_ADDq(VURegs *vuRegs, int info); +void recVUMI_ADDx(VURegs *vuRegs, int info); +void recVUMI_ADDy(VURegs *vuRegs, int info); +void recVUMI_ADDz(VURegs *vuRegs, int info); +void recVUMI_ADDw(VURegs *vuRegs, int info); +void recVUMI_ADDA(VURegs *vuRegs, int info); +void recVUMI_ADDAi(VURegs *vuRegs, int info); +void recVUMI_ADDAq(VURegs *vuRegs, int info); +void recVUMI_ADDAx(VURegs *vuRegs, int info); +void recVUMI_ADDAy(VURegs *vuRegs, int info); +void recVUMI_ADDAz(VURegs *vuRegs, int info); +void recVUMI_ADDAw(VURegs *vuRegs, int info); +void recVUMI_SUB(VURegs *vuRegs, int info); +void recVUMI_SUBi(VURegs *vuRegs, int info); +void recVUMI_SUBq(VURegs *vuRegs, int info); +void recVUMI_SUBx(VURegs *vuRegs, int info); +void recVUMI_SUBy(VURegs *vuRegs, int info); +void recVUMI_SUBz(VURegs *vuRegs, int info); +void recVUMI_SUBw(VURegs *vuRegs, int info); +void recVUMI_SUBA(VURegs *vuRegs, int info); +void recVUMI_SUBAi(VURegs *vuRegs, int info); +void recVUMI_SUBAq(VURegs *vuRegs, int info); +void recVUMI_SUBAx(VURegs *vuRegs, int info); +void recVUMI_SUBAy(VURegs *vuRegs, int info); +void recVUMI_SUBAz(VURegs *vuRegs, int info); +void recVUMI_SUBAw(VURegs *vuRegs, int info); +void recVUMI_MUL(VURegs *vuRegs, int info); +void recVUMI_MULi(VURegs *vuRegs, int info); +void recVUMI_MULq(VURegs *vuRegs, int info); +void recVUMI_MULx(VURegs *vuRegs, int info); +void recVUMI_MULy(VURegs *vuRegs, int info); +void recVUMI_MULz(VURegs *vuRegs, int info); +void recVUMI_MULw(VURegs *vuRegs, int info); +void recVUMI_MULA(VURegs *vuRegs, int info); +void recVUMI_MULAi(VURegs *vuRegs, int info); +void recVUMI_MULAq(VURegs *vuRegs, int info); +void recVUMI_MULAx(VURegs *vuRegs, int info); +void recVUMI_MULAy(VURegs *vuRegs, int info); +void recVUMI_MULAz(VURegs *vuRegs, int info); +void recVUMI_MULAw(VURegs *vuRegs, int info); +void recVUMI_MADD(VURegs *vuRegs, int info); +void recVUMI_MADDi(VURegs *vuRegs, int info); +void recVUMI_MADDq(VURegs *vuRegs, int info); +void recVUMI_MADDx(VURegs *vuRegs, int info); +void recVUMI_MADDy(VURegs *vuRegs, int info); +void recVUMI_MADDz(VURegs *vuRegs, int info); +void recVUMI_MADDw(VURegs *vuRegs, int info); +void recVUMI_MADDA(VURegs *vuRegs, int info); +void recVUMI_MADDAi(VURegs *vuRegs, int info); +void recVUMI_MADDAq(VURegs *vuRegs, int info); +void recVUMI_MADDAx(VURegs *vuRegs, int info); +void recVUMI_MADDAy(VURegs *vuRegs, int info); +void recVUMI_MADDAz(VURegs *vuRegs, int info); +void recVUMI_MADDAw(VURegs *vuRegs, int info); +void recVUMI_MSUB(VURegs *vuRegs, int info); +void recVUMI_MSUBi(VURegs *vuRegs, int info); +void recVUMI_MSUBq(VURegs *vuRegs, int info); +void recVUMI_MSUBx(VURegs *vuRegs, int info); +void recVUMI_MSUBy(VURegs *vuRegs, int info); +void recVUMI_MSUBz(VURegs *vuRegs, int info); +void recVUMI_MSUBw(VURegs *vuRegs, int info); +void recVUMI_MSUBA(VURegs *vuRegs, int info); +void recVUMI_MSUBAi(VURegs *vuRegs, int info); +void recVUMI_MSUBAq(VURegs *vuRegs, int info); +void recVUMI_MSUBAx(VURegs *vuRegs, int info); +void recVUMI_MSUBAy(VURegs *vuRegs, int info); +void recVUMI_MSUBAz(VURegs *vuRegs, int info); +void recVUMI_MSUBAw(VURegs *vuRegs, int info); +void recVUMI_MAX(VURegs *vuRegs, int info); +void recVUMI_MAXi(VURegs *vuRegs, int info); +void recVUMI_MAXx(VURegs *vuRegs, int info); +void recVUMI_MAXy(VURegs *vuRegs, int info); +void recVUMI_MAXz(VURegs *vuRegs, int info); +void recVUMI_MAXw(VURegs *vuRegs, int info); +void recVUMI_MINI(VURegs *vuRegs, int info); +void recVUMI_MINIi(VURegs *vuRegs, int info); +void recVUMI_MINIx(VURegs *vuRegs, int info); +void recVUMI_MINIy(VURegs *vuRegs, int info); +void recVUMI_MINIz(VURegs *vuRegs, int info); +void recVUMI_MINIw(VURegs *vuRegs, int info); +void recVUMI_OPMULA(VURegs *vuRegs, int info); +void recVUMI_OPMSUB(VURegs *vuRegs, int info); +void recVUMI_NOP(VURegs *vuRegs, int info); +void recVUMI_FTOI0(VURegs *vuRegs, int info); +void recVUMI_FTOI4(VURegs *vuRegs, int info); +void recVUMI_FTOI12(VURegs *vuRegs, int info); +void recVUMI_FTOI15(VURegs *vuRegs, int info); +void recVUMI_ITOF0(VURegs *vuRegs, int info); +void recVUMI_ITOF4(VURegs *vuRegs, int info); +void recVUMI_ITOF12(VURegs *vuRegs, int info); +void recVUMI_ITOF15(VURegs *vuRegs, int info); +void recVUMI_CLIP(VURegs *vuRegs, int info); + +/***************************************** + VU Micromode Lower instructions +*****************************************/ + +void recVUMI_DIV(VURegs *vuRegs, int info); +void recVUMI_SQRT(VURegs *vuRegs, int info); +void recVUMI_RSQRT(VURegs *vuRegs, int info); +void recVUMI_IADD(VURegs *vuRegs, int info); +void recVUMI_IADDI(VURegs *vuRegs, int info); +void recVUMI_IADDIU(VURegs *vuRegs, int info); +void recVUMI_IAND(VURegs *vuRegs, int info); +void recVUMI_IOR(VURegs *vuRegs, int info); +void recVUMI_ISUB(VURegs *vuRegs, int info); +void recVUMI_ISUBIU(VURegs *vuRegs, int info); +void recVUMI_MOVE(VURegs *vuRegs, int info); +void recVUMI_MFIR(VURegs *vuRegs, int info); +void recVUMI_MTIR(VURegs *vuRegs, int info); +void recVUMI_MR32(VURegs *vuRegs, int info); +void recVUMI_LQ(VURegs *vuRegs, int info); +void recVUMI_LQD(VURegs *vuRegs, int info); +void recVUMI_LQI(VURegs *vuRegs, int info); +void recVUMI_SQ(VURegs *vuRegs, int info); +void recVUMI_SQD(VURegs *vuRegs, int info); +void recVUMI_SQI(VURegs *vuRegs, int info); +void recVUMI_ILW(VURegs *vuRegs, int info); +void recVUMI_ISW(VURegs *vuRegs, int info); +void recVUMI_ILWR(VURegs *vuRegs, int info); +void recVUMI_ISWR(VURegs *vuRegs, int info); +void recVUMI_LOI(VURegs *vuRegs, int info); +void recVUMI_RINIT(VURegs *vuRegs, int info); +void recVUMI_RGET(VURegs *vuRegs, int info); +void recVUMI_RNEXT(VURegs *vuRegs, int info); +void recVUMI_RXOR(VURegs *vuRegs, int info); +void recVUMI_WAITQ(VURegs *vuRegs, int info); +void recVUMI_FSAND(VURegs *vuRegs, int info); +void recVUMI_FSEQ(VURegs *vuRegs, int info); +void recVUMI_FSOR(VURegs *vuRegs, int info); +void recVUMI_FSSET(VURegs *vuRegs, int info); +void recVUMI_FMAND(VURegs *vuRegs, int info); +void recVUMI_FMEQ(VURegs *vuRegs, int info); +void recVUMI_FMOR(VURegs *vuRegs, int info); +void recVUMI_FCAND(VURegs *vuRegs, int info); +void recVUMI_FCEQ(VURegs *vuRegs, int info); +void recVUMI_FCOR(VURegs *vuRegs, int info); +void recVUMI_FCSET(VURegs *vuRegs, int info); +void recVUMI_FCGET(VURegs *vuRegs, int info); +void recVUMI_IBEQ(VURegs *vuRegs, int info); +void recVUMI_IBGEZ(VURegs *vuRegs, int info); +void recVUMI_IBGTZ(VURegs *vuRegs, int info); +void recVUMI_IBLTZ(VURegs *vuRegs, int info); +void recVUMI_IBLEZ(VURegs *vuRegs, int info); +void recVUMI_IBNE(VURegs *vuRegs, int info); +void recVUMI_B(VURegs *vuRegs, int info); +void recVUMI_BAL(VURegs *vuRegs, int info); +void recVUMI_JR(VURegs *vuRegs, int info); +void recVUMI_JALR(VURegs *vuRegs, int info); +void recVUMI_MFP(VURegs *vuRegs, int info); +void recVUMI_WAITP(VURegs *vuRegs, int info); +void recVUMI_ESADD(VURegs *vuRegs, int info); +void recVUMI_ERSADD(VURegs *vuRegs, int info); +void recVUMI_ELENG(VURegs *vuRegs, int info); +void recVUMI_ERLENG(VURegs *vuRegs, int info); +void recVUMI_EATANxy(VURegs *vuRegs, int info); +void recVUMI_EATANxz(VURegs *vuRegs, int info); +void recVUMI_ESUM(VURegs *vuRegs, int info); +void recVUMI_ERCPR(VURegs *vuRegs, int info); +void recVUMI_ESQRT(VURegs *vuRegs, int info); +void recVUMI_ERSQRT(VURegs *vuRegs, int info); +void recVUMI_ESIN(VURegs *vuRegs, int info); +void recVUMI_EATAN(VURegs *vuRegs, int info); +void recVUMI_EEXP(VURegs *vuRegs, int info); +void recVUMI_XGKICK(VURegs *vuRegs, int info); +void recVUMI_XTOP(VURegs *vuRegs, int info); +void recVUMI_XITOP(VURegs *vuRegs, int info); +void recVUMI_XTOP( VURegs *VU , int info); + +#endif /* __IVUMICRO_H__ */ diff --git a/branches/pcsx2_0.9.2/x86/iVUops.h b/branches/pcsx2_0.9.2/x86/iVUops.h new file mode 100644 index 0000000..79d4a78 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVUops.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#define REC_VUOP(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUOPFLAGS(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUBRANCH(VU, f) { \ + _freeXMMregs(&VU); \ + _freeMMXregs(&VU0); \ + SetFPUstate(); \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + MOV32ItoM((u32)&VU.VI[REG_TPC].UL, (u32)pc); \ + CALLFunc((u32)VU##MI_##f); \ + branch = 1; \ +} \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/iVUzerorec.cpp b/branches/pcsx2_0.9.2/x86/iVUzerorec.cpp new file mode 100644 index 0000000..b9e09e8 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVUzerorec.cpp @@ -0,0 +1,4039 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define PLUGINtypedefs // for GSgifTransfer1 + +#if defined(__WIN32__) +#include +#endif + +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "zlib.h" +#include "Misc.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" + +#include "Memory.h" +#include "Hw.h" +#include "GS.h" + +#include "ix86/ix86.h" +#include "iR5900.h" + +#include "iVUzerorec.h" + +// temporary externs +extern u32 vudump; +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); + +extern char* disVU1MicroUF(u32 code, u32 pc); +extern char* disVU1MicroLF(u32 code, u32 pc); + +extern _GSgifTransfer1 GSgifTransfer1; + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include +using namespace std; + +#ifdef __MSCW32__ + +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// SuperVURec optimization options, uncomment only for debugging purposes +#define SUPERVU_CACHING // vu programs are saved and queried via CRC (might query the wrong program) + // disable when in doubt +#define SUPERVU_X86CACHING // use x86reg caching (faster) +#define SUPERVU_WRITEBACKS // don't flush the writebacks after every block +#define SUPERVU_XGKICKDELAY // yes this is needed + +#ifndef _DEBUG +#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) +#endif + +#define VU_EXESIZE 0x00800000 + +#define _Imm11_ ((s32)(vucode & 0x400 ? 0xfffffc00 | (vucode & 0x3ff) : vucode & 0x3ff)&0x3fff) +#define _UImm11_ ((s32)(vucode & 0x7ff)&0x3fff) + +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +static const u32 QWaitTimes[] = { 6, 12 }; +static const u32 PWaitTimes[] = { 53, 43, 28, 23, 17, 11, 10 }; + +static u32 s_vuInfo; // info passed into rec insts + +static const u32 s_MemSize[2] = {VU0_MEMSIZE, VU1_MEMSIZE}; +static char* s_recVUMem = NULL, *s_recVUPtr = NULL; + +// tables +extern void (*recSVU_UPPER_OPCODE[64])(); +extern void (*recSVU_LOWER_OPCODE[128])(); + +#define INST_Q_READ 0x0001 // flush Q +#define INST_P_READ 0x0002 // flush P +#define INST_BRANCH_DELAY 0x0004 +#define INST_CLIP_WRITE 0x0040 // inst writes CLIP in the future +#define INST_STATUS_WRITE 0x0080 +#define INST_MAC_WRITE 0x0100 +#define INST_Q_WRITE 0x0200 +#define INST_DUMMY_ 0x8000 +#define INST_DUMMY 0x83c0 + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +union VURecRegs +{ + struct { + u16 reg; + u16 type; + }; + u32 id; +}; + +class VuBaseBlock; + +struct VuFunctionHeader +{ + struct RANGE + { + RANGE() : pmem(NULL) {} + + u16 start, size; + void* pmem; // all the mem + }; + + VuFunctionHeader() : pprogfunc(NULL), startpc(0xffffffff) {} + ~VuFunctionHeader() { + for(vector::iterator it = ranges.begin(); it != ranges.end(); ++it) { + free(it->pmem); + } + } + + // returns true if the checksum for the current mem is the same as this fn + bool IsSame(void* pmem); + + u32 startpc; + void* pprogfunc; + + vector ranges; +}; + +struct VuBlockHeader +{ + VuBaseBlock* pblock; + u32 delay; +}; + +// one vu inst (lower and upper) +class VuInstruction +{ +public: + VuInstruction() { memset(this, 0, sizeof(VuInstruction)); nParentPc = -1; } + + int nParentPc; // used for syncing with flag writes, -1 for no parent + + _vuopinfo info; + + _VURegsNum regs[2]; // [0] - lower, [1] - upper + u32 livevars[2]; // live variables right before this inst, [0] - inst, [1] - float + u32 addvars[2]; // live variables to add + u32 usedvars[2]; // set if var is used in the future including vars used in this inst + u32 keepvars[2]; + u16 pqcycles; // the number of cycles to stall if function writes to the regs + u16 type; // INST_ + + u32 pClipWrite, pMACWrite, pStatusWrite; // addrs to write the flags + u32 vffree[2]; + s8 vfwrite[2], vfread0[2], vfread1[2], vfacc[2]; + s8 vfflush[2]; // extra flush regs + + int SetCachedRegs(int upper, u32 vuxyz); + void Recompile(list::const_iterator& itinst, u32 vuxyz); +}; + +#define BLOCKTYPE_EOP 0x01 // at least one of the children of the block contains eop (or the block itself) +#define BLOCKTYPE_FUNCTION 0x02 +#define BLOCKTYPE_HASEOP 0x04 // last inst of block is an eop +#define BLOCKTYPE_MACFLAGS 0x08 +#define BLOCKTYPE_ANALYZED 0x40 +#define BLOCKTYPE_IGNORE 0x80 // special for recursive fns +#define BLOCKTYPE_ANALYZEDPARENT 0x100 + +// base block used when recompiling +class VuBaseBlock +{ +public: + typedef list LISTBLOCKS; + + VuBaseBlock(); + + // returns true if the leads to a EOP (ALL VU blocks must ret true) + void AssignVFRegs(); + void AssignVIRegs(int parent); + + // returns true if only xyz of the reg has been used so far + u32 GetModeXYZW(u32 curpc, int vfreg); + + list::iterator GetInstIterAtPc(int instpc); + void GetInstsAtPc(int instpc, list& listinsts); + + void Recompile(); + + u16 type; // BLOCKTYPE_ + u16 id; + u16 startpc; + u16 endpc; // first inst not in block + void* pcode; // x86 code pointer + int cycles; + list insts; + list parents; + LISTBLOCKS blocks; // blocks branches to + u32* pChildJumps[4]; // addrs that need to be filled with the children's start addrs + // if highest bit is set, addr needs to be relational + u32 vuxyz; // corresponding bit is set if reg's xyz channels are used only + u32 vuxy; // corresponding bit is set if reg's xyz channels are used only + + _xmmregs startregs[XMMREGS], endregs[XMMREGS]; + int nStartx86, nEndx86; // indices into s_vecRegArray + + int allocX86Regs; +}; + +struct WRITEBACK +{ + void InitInst(VuInstruction* pinst, int cycle) const + { + u32 write = viwrite[0]|viwrite[1]; + pinst->type = ((write&(1<nParentPc = nParentPc; + pinst->info.cycle = cycle; + for(int i = 0; i < 2; ++i) { + pinst->regs[i].VIwrite = viwrite[i]; + pinst->regs[i].VIread = viread[i]; + } + } + + static int SortWritebacks(const WRITEBACK& w1, const WRITEBACK& w2) { + return w1.cycle < w2.cycle; + } + + int nParentPc; + int cycle; + u32 viwrite[2]; + u32 viread[2]; +}; + +struct VUPIPELINES +{ + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + list< WRITEBACK > listWritebacks; +}; + +VuBaseBlock::VuBaseBlock() +{ + type = 0; endpc = 0; cycles = 0; pcode = NULL; id = 0; + memset(pChildJumps, 0, sizeof(pChildJumps)); + memset(startregs, 0, sizeof(startregs)); + memset(endregs, 0, sizeof(endregs)); + allocX86Regs = nStartx86 = nEndx86 = -1; +} + +#define SUPERVU_STACKSIZE 0x1000 + +static list s_listVUHeaders[2]; +static list* s_plistCachedHeaders[2]; +static VuFunctionHeader** recVUHeaders[2] = {NULL}; +static VuBlockHeader* recVUBlocks[2] = {NULL}; +static u8* recVUStack = NULL, *recVUStackPtr = NULL; +static vector<_x86regs> s_vecRegArray(128); + +static VURegs* VU = NULL; +static list s_listBlocks; +static u32 s_vu = 0; +static u32 s_UnconditionalDelay = 0; // 1 if there are two sequential branches and the last is unconditional + +// Global functions +static void* SuperVUGetProgram(u32 startpc, int vuindex); +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex); +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc, const VUPIPELINES& pipes); +static void SuperVUInitLiveness(VuBaseBlock* pblock); +static void SuperVULivenessAnalysis(); +static void SuperVUEliminateDeadCode(); +static void SuperVUAssignRegs(); + +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg); +#define SuperVUFreeXMMreg 0&& +void SuperVUFreeXMMregs(u32* livevars); + +static u32* SuperVUStaticAlloc(u32 size); +static void SuperVURecompile(); +void SuperVUEndProgram(); + +// allocate VU resources +void SuperVUInit(int vuindex) +{ + if( vuindex < 0 ) { + s_recVUMem = (char*)SysMmap(0, VU_EXESIZE); + memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + recVUStack = new u8[SUPERVU_STACKSIZE * 4]; + } + else { + recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex]/8]; + recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex]/8]; + s_plistCachedHeaders[vuindex] = new list[s_MemSize[vuindex]/8]; + } +} + +// destroy VU resources +void SuperVUDestroy(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUDestroy(0); + SuperVUDestroy(1); + SysMunmap((uptr)s_recVUMem, VU_EXESIZE); + s_recVUPtr = NULL; + delete[] recVUStack; recVUStack = NULL; + } + else { + delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL; + delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL; + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL; + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// reset VU +void SuperVUReset(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUReset(0); + SuperVUReset(1); + + //memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + + memset(recVUStack, 0, SUPERVU_STACKSIZE); + } + else { + if( recVUHeaders[vuindex] ) memset( recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex]/8) ); + if( recVUBlocks[vuindex] ) memset( recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex]/8) ); + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// clear the block and any joining blocks +void SuperVUClear(u32 startpc, u32 size, int vuindex) +{ + vector::iterator itrange; + list::iterator it = s_listVUHeaders[vuindex].begin(); + u32 endpc = startpc+size; + while( it != s_listVUHeaders[vuindex].end() ) { + + // for every fn, check if it has code in the range + FORIT(itrange, (*it)->ranges) { + if( startpc < (u32)itrange->start+itrange->size && itrange->start < endpc ) + break; + } + + if( itrange != (*it)->ranges.end() ) { + recVUHeaders[vuindex][(*it)->startpc/8] = NULL; +#ifdef SUPERVU_CACHING + list* plist = &s_plistCachedHeaders[vuindex][(*it)->startpc/8]; + plist->push_back(*it); + if( plist->size() > 10 ) { + // list is too big, delete + delete plist->front(); + plist->pop_front(); + } + it = s_listVUHeaders[vuindex].erase(it); +#else + delete *it; + it = s_listVUHeaders[vuindex].erase(it); +#endif + } + else ++it; + } +} + +static VuFunctionHeader* s_pFnHeader = NULL; +static VuBaseBlock* s_pCurBlock = NULL; +static VuInstruction* s_pCurInst = NULL; +static u32 s_StatusRead = 0, s_MACRead = 0, s_ClipRead = 0; // read addrs +static u32 s_PrevStatusWrite = 0, s_PrevMACWrite = 0, s_PrevClipWrite = 0, s_PrevIWrite = 0; +static u32 s_WriteToReadQ = 0; +static u32 s_TotalVUCycles; // total cycles since start of program execution + +int SuperVUGetLiveness(int vfreg) +{ + assert( s_pCurInst != NULL ); + if( vfreg == 32 ) return ((s_pCurInst->livevars[0]&(1<usedvars[0]&(1<livevars[0]&(1<usedvars[0]&(1<livevars[1]&(1<usedvars[1]&(1<pStatusWrite); + assert(!read || addr != 0); + return addr; + } + case REG_MAC_FLAG: + { + return (read==2) ? s_PrevMACWrite : (read ? s_MACRead : s_pCurInst->pMACWrite); + } + case REG_CLIP_FLAG: + { + u32 addr = (read==2) ? s_PrevClipWrite : (read ? s_ClipRead : s_pCurInst->pClipWrite); + assert( !read || addr != 0 ); + return addr; + } + case REG_Q: return (read || s_WriteToReadQ) ? (int)&VU->VI[REG_Q] : (u32)(u32)&VU->q; + case REG_P: return read ? (int)&VU->VI[REG_P] : (u32)(u32)&VU->p; + case REG_I: return s_PrevIWrite; + } + + return (u32)&VU->VI[reg]; +} + +void SuperVUDumpBlock(list& blocks, int vuindex) +{ + FILE *f; + char filename[ 256 ], str[256]; + u32 *mem; + u32 i; + static int gid = 0; + +#ifdef __WIN32__ + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#endif + //SysPrintf( "dump1 %x => %s\n", s_pFnHeader->startpc, filename ); + + f = fopen( filename, "w" ); + + fprintf(f, "Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); + fprintf(f, "Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" + "%.2x - mac_write, %.2x -qflush\n", + INST_Q_READ, INST_P_READ, INST_CLIP_WRITE, INST_STATUS_WRITE, INST_MAC_WRITE, INST_Q_WRITE); + fprintf(f, "XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); + + list::iterator itblock; + list::iterator itinst; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + FORIT(itblock, blocks) { + fprintf(f, "block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', + (*itblock)->startpc, (*itblock)->endpc-8); + FORIT(itchild, (*itblock)->blocks) { + fprintf(f, "%x ", (*itchild)->startpc); + } + fprintf(f, "; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], + (*itblock)->vuxy&(*itblock)->insts.front().usedvars[1]); + + itinst = (*itblock)->insts.begin(); + i = (*itblock)->startpc; + while(itinst != (*itblock)->insts.end() ) { + assert( i <= (*itblock)->endpc ); + if( itinst->type & INST_DUMMY ) { + if( itinst->nParentPc >= 0 && !(itinst->type&INST_DUMMY_)) { + // search for the parent + fprintf(f, "writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); + } + } + else { + mem = (u32*)&VU->Micro[i]; + char* pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%.4x: %-40s", i, pstr); + if( mem[1] & 0x80000000 ) fprintf(f, " I=%f(%.8x)\n", *(float*)mem, mem[0]); + else fprintf(f, "%s\n", disVU1MicroLF( mem[0], i )); + i += 8; + } + + ++itinst; + } + + fprintf(f, "\n"); + + _x86regs* pregs; + if( (*itblock)->nStartx86 >= 0 || (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "X86: AX CX DX BX SP BP SI DI\n"); + } + + if( (*itblock)->nStartx86 >= 0 ) { + pregs = &s_vecRegArray[(*itblock)->nStartx86]; + fprintf(f, "STR: "); + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + if( (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "END: "); + pregs = &s_vecRegArray[(*itblock)->nEndx86]; + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + itinst = (*itblock)->insts.begin(); + for ( i = (*itblock)->startpc; i < (*itblock)->endpc; ++itinst ) { + + if( itinst->type & INST_DUMMY ) { + } + else { + sprintf(str, "%.4x:%x f:%.8x_%.8x", i, itinst->type, itinst->livevars[1], itinst->usedvars[1]); + fprintf(f, "%-46s i:%.8x_%.8x c:%d pq:%d\n", str, + itinst->livevars[0], itinst->usedvars[0], (int)itinst->info.cycle, (int)itinst->pqcycles ); + + sprintf(str, "XMM r0:%d r1:%d w:%d a:%d t:%x;", + itinst->vfread0[1], itinst->vfread1[1], itinst->vfwrite[1], itinst->vfacc[1], itinst->vffree[1]); + fprintf(f, "%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, + itinst->vfread0[0], itinst->vfread1[0], itinst->vfwrite[0], itinst->vfacc[0], itinst->vffree[0]); + i += 8; + } + } + + fprintf(f, "\n---------------\n"); + } + + fclose( f ); +} + +static LARGE_INTEGER svubase, svufinal; +static u32 svutime; + +// uncomment to count svu exec time +//#define SUPERVU_COUNT +u32 SuperVUGetRecTimes(int clear) +{ + u32 temp = svutime; + if( clear ) svutime = 0; + return temp; +} + +// Private methods +static void* SuperVUGetProgram(u32 startpc, int vuindex) +{ + assert( startpc < s_MemSize[vuindex] ); + assert( (startpc%8) == 0 ); + assert( recVUHeaders[vuindex] != NULL ); + VuFunctionHeader** pheader = &recVUHeaders[vuindex][startpc/8]; + + if( *pheader == NULL ) { +#ifdef _DEBUG +// if( vuindex ) VU1.VI[REG_TPC].UL = startpc; +// else VU0.VI[REG_TPC].UL = startpc; +// __Log("VU: %x\n", startpc); +// iDumpVU1Registers(); +// vudump |= 2; +#endif + + // measure run time + //QueryPerformanceCounter(&svubase); + +#ifdef SUPERVU_CACHING + void* pmem = (vuindex&1) ? VU1.Micro : VU0.Micro; + // check if program exists in cache + list::iterator it; + FORIT(it, s_plistCachedHeaders[vuindex][startpc/8]) { + if( (*it)->IsSame(pmem) ) { + // found, transfer to regular lists + void* pfn = (*it)->pprogfunc; + recVUHeaders[vuindex][startpc/8] = *it; + s_listVUHeaders[vuindex].push_back(*it); + s_plistCachedHeaders[vuindex][startpc/8].erase(it); + return pfn; + } + } +#endif + + *pheader = SuperVURecompileProgram(startpc, vuindex); + + if( *pheader == NULL ) { + assert( s_TotalVUCycles > 0 ); + if( vuindex ) VU1.VI[REG_TPC].UL = startpc; + else VU0.VI[REG_TPC].UL = startpc; + return SuperVUEndProgram; + } + + //QueryPerformanceCounter(&svufinal); + //svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); + + assert( (*pheader)->pprogfunc != NULL ); + } + + assert( (*pheader)->startpc == startpc ); + + return (*pheader)->pprogfunc; +} + +bool VuFunctionHeader::IsSame(void* pmem) +{ +#ifdef SUPERVU_CACHING + //u32 checksum[2]; + vector::iterator it; + FORIT(it, ranges) { + //memxor_mmx(checksum, (u8*)pmem+it->start, it->size); + //if( checksum[0] != it->checksum[0] || checksum[1] != it->checksum[1] ) + // return false; + if( memcmp_mmx((u8*)pmem+it->start, it->pmem, it->size) ) + return false; + } +#endif + return true; +} + +list::iterator VuBaseBlock::GetInstIterAtPc(int instpc) +{ + assert( instpc >= 0 ); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + if( it != insts.end() ) + return it; + + assert( 0 ); + return insts.begin(); +} + +void VuBaseBlock::GetInstsAtPc(int instpc, list& listinsts) +{ + assert( instpc >= 0 ); + + listinsts.clear(); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + if( it != insts.end() ) { + listinsts.push_back(&(*it)); + return; + } + + // look for the pc in other blocks + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + if( *itblock == this ) + continue; + + if( instpc >= (*itblock)->startpc && instpc < (*itblock)->endpc ) { + listinsts.push_back(&(*(*itblock)->GetInstIterAtPc(instpc))); + } + } + + assert(listinsts.size()>0); +} + +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex) +{ + assert( vuindex < 2 ); + assert( s_recVUPtr != NULL ); + //SysPrintf("svu%c rec: %x\n", '0'+vuindex, startpc); + + // if recPtr reached the mem limit reset whole mem + if ( ( (u32)s_recVUPtr - (u32)s_recVUMem ) >= VU_EXESIZE-0x40000 ) { + //SysPrintf("SuperVU reset mem\n"); + SuperVUReset(-1); + if( s_TotalVUCycles > 0 ) { + // already executing, so return NULL + return NULL; + } + } + + list::iterator itblock; + + s_vu = vuindex; + VU = s_vu ? &VU1 : &VU0; + s_pFnHeader = new VuFunctionHeader(); + s_listVUHeaders[vuindex].push_back(s_pFnHeader); + s_pFnHeader->startpc = startpc; + + memset( recVUBlocks[s_vu], 0, sizeof(VuBlockHeader) * (s_MemSize[s_vu]/8) ); + + // analyze the global graph + s_listBlocks.clear(); + VUPIPELINES pipes; + memset(pipes.fmac, 0, sizeof(pipes.fmac)); + memset(&pipes.fdiv, 0, sizeof(pipes.fdiv)); + memset(&pipes.efu, 0, sizeof(pipes.efu)); + SuperVUBuildBlocks(NULL, startpc, pipes); + + // fill parents + VuBaseBlock::LISTBLOCKS::iterator itchild; + FORIT(itblock, s_listBlocks) { + FORIT(itchild, (*itblock)->blocks) + (*itchild)->parents.push_back(*itblock); + + //(*itblock)->type &= ~(BLOCKTYPE_IGNORE|BLOCKTYPE_ANALYZED); + } + + assert( s_listBlocks.front()->startpc == startpc ); + s_listBlocks.front()->type |= BLOCKTYPE_FUNCTION; + + FORIT(itblock, s_listBlocks) { + SuperVUInitLiveness(*itblock); + } + + SuperVULivenessAnalysis(); + SuperVUEliminateDeadCode(); + SuperVUAssignRegs(); + +#ifdef _DEBUG + if( (s_vu && (vudump&1)) || (!s_vu && (vudump&16)) ) + SuperVUDumpBlock(s_listBlocks, s_vu); +#endif + + // code generation + x86SetPtr(s_recVUPtr); + _initXMMregs(); + branch = 0; + + SuperVURecompile(); + + s_recVUPtr = x86Ptr; + + // set the function's range + VuFunctionHeader::RANGE r; + s_pFnHeader->ranges.reserve(s_listBlocks.size()); + + FORIT(itblock, s_listBlocks) { + r.start = (*itblock)->startpc; + r.size = (*itblock)->endpc-(*itblock)->startpc; +#ifdef SUPERVU_CACHING + //memxor_mmx(r.checksum, &VU->Micro[r.start], r.size); + r.pmem = malloc(r.size); + memcpy(r.pmem, &VU->Micro[r.start], r.size); +#endif + s_pFnHeader->ranges.push_back(r); + } + + // destroy + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + delete *itblock; + } + s_listBlocks.clear(); + + assert( s_recVUPtr < s_recVUMem+VU_EXESIZE ); + + return s_pFnHeader; +} + +static int _recbranchAddr(u32 vucode) { + u32 bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + bpc &= (s_MemSize[s_vu]-1); + + return bpc; +} + +// return inst that flushes everything +static VuInstruction SuperVUFlushInst() +{ + VuInstruction inst; + // don't need to raed q/p + inst.type = INST_DUMMY_;//|INST_Q_READ|INST_P_READ; + return inst; +} + +void SuperVUAddWritebacks(VuBaseBlock* pblock, const list& listWritebacks) +{ +#ifdef SUPERVU_WRITEBACKS + // regardless of repetition, add the pipes (for selfloops) + list::const_iterator itwriteback = listWritebacks.begin(); + list::iterator itinst = pblock->insts.begin(), itinst2; + + while(itwriteback != listWritebacks.end()) { + if( itinst != pblock->insts.end() && itinst->info.cycle < itwriteback->cycle ) { + ++itinst; + continue; + } + + itinst2 = pblock->insts.insert(itinst, VuInstruction()); + itwriteback->InitInst(&(*itinst2), vucycle); + ++itwriteback; + } +#endif +} + +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc, const VUPIPELINES& pipes) +{ + // check if block already exists + VuBlockHeader* pbh = &recVUBlocks[s_vu][startpc/8]; + if( pbh->pblock != NULL ) { + + VuBaseBlock* pblock = pbh->pblock; + list::iterator itinst; + + if( pblock->startpc == startpc ) { + SuperVUAddWritebacks(pblock, pipes.listWritebacks); + return pblock; + } + + // have to divide the blocks, pnewblock is first block + assert( startpc > pblock->startpc ); + assert( startpc < pblock->endpc ); + + u32 dummyinst = (startpc-pblock->startpc)>>3; + + // count inst non-dummy insts + itinst = pblock->insts.begin(); + u32 inst = 0; + while(dummyinst > 0) { + if( itinst->type & INST_DUMMY ) + ++itinst; + else { + ++itinst; + --dummyinst; + } + } + + // NOTE: still leaves insts with their writebacks in different blocks + while( itinst->type & INST_DUMMY ) + ++itinst; + + int cycleoff = itinst->info.cycle; + + // new block + VuBaseBlock* pnewblock = new VuBaseBlock(); + s_listBlocks.push_back(pnewblock); + + pnewblock->startpc = startpc; + pnewblock->endpc = pblock->endpc; + pnewblock->cycles = pblock->cycles-cycleoff; + + pnewblock->blocks.splice(pnewblock->blocks.end(), pblock->blocks); + pnewblock->insts.splice(pnewblock->insts.end(), pblock->insts, itinst, pblock->insts.end()); + pnewblock->type = pblock->type; + + // any writebacks in the next 3 cycles also belong to original block + for(itinst = pnewblock->insts.begin(); itinst != pnewblock->insts.end(); ) { + if( (itinst->type & INST_DUMMY) && itinst->nParentPc >= 0 && itinst->nParentPc < (int)startpc ) { + + if( !(itinst->type & INST_Q_WRITE) ) + pblock->insts.push_back(*itinst); + itinst = pnewblock->insts.erase(itinst); + continue; + } + + ++itinst; + } + + pbh = &recVUBlocks[s_vu][startpc/8]; + for(u32 inst = startpc; inst < pblock->endpc; inst += 8) { + if( pbh->pblock == pblock ) + pbh->pblock = pnewblock; + ++pbh; + } + + FORIT(itinst, pnewblock->insts) + itinst->info.cycle -= cycleoff; + + SuperVUAddWritebacks(pnewblock, pipes.listWritebacks); + + // old block + pblock->blocks.push_back(pnewblock); + pblock->endpc = startpc; + pblock->cycles = cycleoff; + pblock->type &= BLOCKTYPE_MACFLAGS; + //pblock->insts.push_back(SuperVUFlushInst()); //don't need + + return pnewblock; + } + + VuBaseBlock* pblock = new VuBaseBlock(); + s_listBlocks.push_back(pblock); + + int i = 0; + branch = 0; + pc = startpc; + pblock->startpc = startpc; + + // clear stalls (might be a prob) + memcpy(VU->fmac, pipes.fmac, sizeof(pipes.fmac)); + memcpy(&VU->fdiv, &pipes.fdiv, sizeof(pipes.fdiv)); + memcpy(&VU->efu, &pipes.efu, sizeof(pipes.efu)); +// memset(VU->fmac, 0, sizeof(VU->fmac)); +// memset(&VU->fdiv, 0, sizeof(VU->fdiv)); +// memset(&VU->efu, 0, sizeof(VU->efu)); + + vucycle = 0; + + u8 macflags = 0; + + list< WRITEBACK > listWritebacks; + list< WRITEBACK >::iterator itwriteback; + list::iterator itinst; + u32 hasSecondBranch = 0; + u32 needFullStatusFlag = 0; + +#ifdef SUPERVU_WRITEBACKS + listWritebacks = pipes.listWritebacks; +#endif + + // first analysis pass for status flags + while(1) { + u32* ptr = (u32*)&VU->Micro[pc]; + pc += 8; + int prevbranch = branch; + + if( ptr[1] & 0x40000000 ) + branch = 1; + + if( !(ptr[1] & 0x80000000) ) { // not I + switch( ptr[0]>>25 ) { + case 0x24: // jr + case 0x25: // jalr + case 0x20: // B + case 0x21: // BAL + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + branch = 1; + break; + + case 0x14: // fseq + case 0x17: // fsor + //needFullStatusFlag = 2; + break; + + case 0x16: // fsand + if( (ptr[0]&0xc0) ) { + // sometimes full sticky bits are needed (simple series 2000 - oane chapara) + //SysPrintf("needSticky: %x-%x\n", s_pFnHeader->startpc, startpc); + needFullStatusFlag = 2; + } + break; + } + } + + if( prevbranch ) + break; + + assert( pc < s_MemSize[s_vu] ); + } + + // second full pass + pc = startpc; + branch = 0; + + while(1) { + + if( !branch && pbh->pblock != NULL ) { + pblock->blocks.push_back(pbh->pblock); + break; + } + + int prevbranch = branch; + + if( !prevbranch ) { + pbh->pblock = pblock; + } + else assert( prevbranch || pbh->pblock == NULL); + + pblock->insts.push_back(VuInstruction()); + + VuInstruction* pinst = &pblock->insts.back(); + SuperVUAnalyzeOp(VU, &pinst->info, pinst->regs); + + if( prevbranch ) { + if( pinst->regs[0].pipe == VUPIPE_BRANCH ) + hasSecondBranch = 1; + pinst->type |= INST_BRANCH_DELAY; + } + + // check write back + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ) { + if( pinst->info.cycle >= itwriteback->cycle ) { + itinst = pblock->insts.insert(--pblock->insts.end(), VuInstruction()); + itwriteback->InitInst(&(*itinst), pinst->info.cycle); + itwriteback = listWritebacks.erase(itwriteback); + } + else ++itwriteback; + } + + // add new writebacks + WRITEBACK w = {0}; + const u32 allflags = (1<regs[j].VIwrite & allflags; + + if( pinst->info.macflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.statusflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.macflag|pinst->info.statusflag) & VUOP_READ ) + macflags = 1; + if( pinst->regs[0].VIread & ((1<VIwrite |= lregs->VIwrite & (1<info.statusflag&VUOP_WRITE)&&!(pinst->regs[0].VIwrite&(1<regs[j].VIread & allflags; + + if( (pinst->regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIwrite &= ~allflags; + } + + if( pinst->info.macflag & VUOP_READ) w.viread[1] |= 1<info.statusflag & VUOP_READ) w.viread[1] |= 1<info.cycle+4; + listWritebacks.push_back(w); + } + + if( pinst->info.q&VUOP_READ ) pinst->type |= INST_Q_READ; + if( pinst->info.p&VUOP_READ ) pinst->type |= INST_P_READ; + + if( pinst->info.q&VUOP_WRITE ) { + pinst->pqcycles = QWaitTimes[pinst->info.pqinst]+1; + + memset(&w, 0, sizeof(w)); + w.nParentPc = pc-8; + w.cycle = pinst->info.cycle+pinst->pqcycles; + w.viwrite[0] = 1<info.p&VUOP_WRITE ) + pinst->pqcycles = PWaitTimes[pinst->info.pqinst]+1; + + if( prevbranch ) { + break; + } + + // make sure there is always a branch + // sensible soccer overflows on vu0, so increase the limit... + if( (s_vu==1 && i >= 0x799) || (s_vu==0 && i >= 0x201) ) { + SysPrintf("VuRec base block doesn't terminate!\n"); + assert(0); + break; + } + + i++; + pbh++; + } + + if( macflags ) + pblock->type |= BLOCKTYPE_MACFLAGS; + + pblock->endpc = pc; + u32 lastpc = pc; + + pblock->cycles = vucycle; + +#ifdef SUPERVU_WRITEBACKS + if( !branch || (branch&8) ) +#endif + { + // flush writebacks + if( listWritebacks.size() > 0 ) { + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + + listWritebacks.clear(); + } + } + + if( !branch ) + return pblock; + + if( branch & 8 ) { + // what if also a jump? + pblock->type |= BLOCKTYPE_EOP|BLOCKTYPE_HASEOP; + + // add an instruction to flush p and q (if written) + pblock->insts.push_back(SuperVUFlushInst()); + return pblock; + } + + // it is a (cond) branch or a jump + u32 vucode = *(u32*)(VU->Micro+lastpc-16); + int bpc = _recbranchAddr(vucode)-8; + + VUPIPELINES newpipes; + memcpy(newpipes.fmac, VU->fmac, sizeof(newpipes.fmac)); + memcpy(&newpipes.fdiv, &VU->fdiv, sizeof(newpipes.fdiv)); + memcpy(&newpipes.efu, &VU->efu, sizeof(newpipes.efu)); + + for(i = 0; i < 8; ++i) newpipes.fmac[i].sCycle -= vucycle; + newpipes.fdiv.sCycle -= vucycle; + newpipes.efu.sCycle -= vucycle; + + if( listWritebacks.size() > 0 ) { + bool bFlushWritebacks = (vucode>>25)==0x24||(vucode>>25)==0x25||(vucode>>25)==0x20||(vucode>>25)==0x21; + + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<cycle <= vucycle || bFlushWritebacks ) { + pblock->insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + else { + newpipes.listWritebacks.push_back(*itwriteback); + newpipes.listWritebacks.back().cycle -= vucycle; + } + } + } + + u32 firstbranch = vucode>>25; + switch(firstbranch) { + case 0x24: // jr + pblock->type |= BLOCKTYPE_EOP; // jump out of procedure, since not returning, set EOP + pblock->insts.push_back(SuperVUFlushInst()); + break; + + case 0x25: // jalr + { + // linking, so will return to procedure + pblock->insts.push_back(SuperVUFlushInst()); + + VuBaseBlock* pjumpblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + + pblock->blocks.push_back(pjumpblock); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + pblock->blocks.push_back(pbranchblock); + + // if has a second branch that is B or BAL, skip this + u32 secondbranch = (*(u32*)(VU->Micro+lastpc-8))>>25; + if( !hasSecondBranch || (secondbranch != 0x21 && secondbranch != 0x20) ) { + pbranchblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + } + + break; + } + default: + assert(pblock->blocks.size() == 1); + break; + } + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + if( hasSecondBranch ) { + u32 vucode = *(u32*)(VU->Micro+lastpc-8); + pc = lastpc; + int bpc = _recbranchAddr(vucode); + + switch(vucode>>25) { + case 0x24: // jr + SysPrintf("svurec bad jr jump!\n"); + assert(0); + break; + + case 0x25: // jalr + { + SysPrintf("svurec bad jalr jump!\n"); + assert(0); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // replace instead of pushing a new block + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + // only add the block if the previous branch doesn't include the next instruction (ie, if a direct jump) + if( firstbranch == 0x24 || firstbranch == 0x25 || firstbranch == 0x20 || firstbranch == 0x21 ) { + pbranchblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + } + + break; + } + default: + assert(0); + } + } + + return recVUBlocks[s_vu][startpc/8].pblock; +} + +static void SuperVUInitLiveness(VuBaseBlock* pblock) +{ + list::iterator itinst, itnext; + + assert( pblock->insts.size() > 0 ); + + for(itinst = pblock->insts.begin(); itinst != pblock->insts.end(); ++itinst) { + + if( itinst->type & INST_DUMMY_ ) { + itinst->addvars[0] = itinst->addvars[1] = 0xffffffff; + itinst->livevars[0] = itinst->livevars[1] = 0xffffffff; + itinst->keepvars[0] = itinst->keepvars[1] = 0xffffffff; + itinst->usedvars[0] = itinst->usedvars[1] = 0; + } + else { + itinst->addvars[0] = itinst->regs[0].VIread | itinst->regs[1].VIread; + itinst->addvars[1] = (itinst->regs[0].VFread0 ? (1 << itinst->regs[0].VFread0) : 0) | + (itinst->regs[0].VFread1 ? (1 << itinst->regs[0].VFread1) : 0) | + (itinst->regs[1].VFread0 ? (1 << itinst->regs[1].VFread0) : 0) | + (itinst->regs[1].VFread1 ? (1 << itinst->regs[1].VFread1) : 0); + + // vf0 is not handled by VFread + if( !itinst->regs[0].VFread0 && (itinst->regs[0].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[1].VFread0 && (itinst->regs[1].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[0].VFread1 && (itinst->regs[0].VIread & (1<regs[0].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + if( !itinst->regs[1].VFread1 && (itinst->regs[1].VIread & (1<regs[1].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + + + u32 vfwrite = 0; + if( itinst->regs[0].VFwrite != 0 ) { + if( itinst->regs[0].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[0].VFwrite; + else vfwrite |= 1<regs[0].VFwrite; + } + if( itinst->regs[1].VFwrite != 0 ) { + if( itinst->regs[1].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[1].VFwrite; + else vfwrite |= 1<regs[1].VFwrite; + } + if( (itinst->regs[1].VIwrite & (1<regs[1].VFwxyzw != 0xf ) + itinst->addvars[1] |= 1<regs[0].VIwrite|itinst->regs[1].VIwrite); + + itinst->usedvars[0] = itinst->addvars[0]|viwrite; + itinst->usedvars[1] = itinst->addvars[1]|vfwrite; + +// itinst->addvars[0] &= ~viwrite; +// itinst->addvars[1] &= ~vfwrite; + itinst->keepvars[0] = ~viwrite; + itinst->keepvars[1] = ~vfwrite; + } + } + + itinst = --pblock->insts.end(); + while( itinst != pblock->insts.begin() ) { + itnext = itinst; --itnext; + + itnext->usedvars[0] |= itinst->usedvars[0]; + itnext->usedvars[1] |= itinst->usedvars[1]; + + itinst = itnext; + } +} + +u32 COMPUTE_LIVE(u32 R, u32 K, u32 L) +{ + u32 live = R | ((L)&(K)); + // speciall process mac and status flags + // only propagate liveness if doesn't write to the flag + if( !(L&(1<::reverse_iterator itblock; + list::iterator itinst, itnext; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + u32 livevars[2]; + + do { + changed = FALSE; + for(itblock = s_listBlocks.rbegin(); itblock != s_listBlocks.rend(); ++itblock) { + + u32 newlive; + VuBaseBlock* pb = *itblock; + + // the last inst relies on the neighbor's insts + itinst = --pb->insts.end(); + + if( pb->blocks.size() > 0 ) { + livevars[0] = 0; livevars[1] = 0; + for( itchild = pb->blocks.begin(); itchild != pb->blocks.end(); ++itchild) { + VuInstruction& front = (*itchild)->insts.front(); + livevars[0] |= front.livevars[0]; + livevars[1] |= front.livevars[1]; + } + + newlive = COMPUTE_LIVE(itinst->addvars[0], itinst->keepvars[0], livevars[0]); + if( itinst->livevars[0] != newlive ) { + changed = TRUE; + itinst->livevars[0] = newlive; + } + + newlive = COMPUTE_LIVE(itinst->addvars[1], itinst->keepvars[1], livevars[1]); + if( itinst->livevars[1] != newlive ) { + changed = TRUE; + itinst->livevars[1] = newlive; + } + } + + while( itinst != pb->insts.begin() ) { + + itnext = itinst; --itnext; + + newlive = COMPUTE_LIVE(itnext->addvars[0], itnext->keepvars[0], itinst->livevars[0]); + + if( itnext->livevars[0] != newlive ) { + changed = TRUE; + itnext->livevars[0] = newlive; + itnext->livevars[1] = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + } + else { + newlive = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + if( itnext->livevars[1] != newlive ) { + changed = TRUE; + itnext->livevars[1] = newlive; + } + } + + itinst = itnext; + } + +// if( (livevars[0] | itinst->livevars[0]) != itinst->livevars[0] ) { +// changed = TRUE; +// itinst->livevars[0] |= livevars[0]; +// } +// if( (livevars[1] | itinst->livevars[1]) != itinst->livevars[1] ) { +// changed = TRUE; +// itinst->livevars[1] |= livevars[1]; +// } +// +// while( itinst != pb->insts.begin() ) { +// +// itnext = itinst; --itnext; +// if( (itnext->livevars[0] | (itinst->livevars[0] & itnext->keepvars[0])) != itnext->livevars[0] ) { +// changed = TRUE; +// itnext->livevars[0] |= itinst->livevars[0] & itnext->keepvars[0]; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// else if( (itnext->livevars[1] | (itinst->livevars[1] & itnext->keepvars[1])) != itnext->livevars[1] ) { +// changed = TRUE; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// +// itinst = itnext; +// } + } + + } while(changed); +} + +static void SuperVUEliminateDeadCode() +{ + list::iterator itblock; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itinst, itnext; + list listParents; + list::iterator itparent; + + FORIT(itblock, s_listBlocks) { + +#ifdef _DEBUG + u32 startpc = (*itblock)->startpc; + u32 curpc = startpc; +#endif + + itnext = (*itblock)->insts.begin(); + itinst = itnext++; + while(itnext != (*itblock)->insts.end() ) { + if( itinst->type & (INST_CLIP_WRITE|INST_MAC_WRITE|INST_STATUS_WRITE) ) { + itinst->regs[0].VIwrite &= itnext->livevars[0]; + itinst->regs[1].VIwrite &= itnext->livevars[0]; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + (*itblock)->GetInstsAtPc(itinst->nParentPc, listParents); + int removetype = 0; + + FORIT(itparent, listParents) { + VuInstruction* parent = *itparent; + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; + // parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; + // parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~removetype; + if( itinst->type == 0 ) { + itnext = (*itblock)->insts.erase(itinst); + itinst = itnext++; + continue; + } + } +#ifdef _DEBUG + else curpc += 8; +#endif + itinst = itnext; + ++itnext; + } + + if( itinst->type & INST_DUMMY ) { + // last inst with the children + u32 mask = 0; + for(itchild = (*itblock)->blocks.begin(); itchild != (*itblock)->blocks.end(); ++itchild) { + mask |= (*itchild)->insts.front().livevars[0]; + } + itinst->regs[0].VIwrite &= mask; + itinst->regs[1].VIwrite &= mask; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + if( itinst->nParentPc >= 0 ) { + + (*itblock)->GetInstsAtPc(itinst->nParentPc, listParents); + int removetype = 0; + + FORIT(itparent, listParents) { + VuInstruction* parent = *itparent; + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; +#ifndef SUPERVU_WRITEBACKS + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; +#ifndef SUPERVU_WRITEBACKS + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~removetype; + if( itinst->type == 0 ) { + (*itblock)->insts.erase(itinst); + } + } + } + } +} + +// assigns xmm/x86 regs to all instructions, ignore mode field +// returns true if changed +bool AlignStartRegsToEndRegs(_xmmregs* startregs, const list& parents) +{ + list::const_iterator itblock, itblock2; + int bestscore; + _xmmregs bestregs; + bool bchanged = false; + + // find the best merge of regs that minimizes writes/reads + for(int i = 0; i < XMMREGS; ++i) { + + bestscore = 1000; + memset(&bestregs, 0, sizeof(bestregs)); + + FORIT(itblock, parents) { + int curscore = 0; + if( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->endregs[i].inuse ) { + int type = (*itblock)->endregs[i].type; + int reg = (*itblock)->endregs[i].reg; + + FORIT(itblock2, parents) { + if( (*itblock2)->type & BLOCKTYPE_ANALYZED ) { + if( (*itblock2)->endregs[i].inuse ) { + if( (*itblock2)->endregs[i].type != type || (*itblock2)->endregs[i].reg != reg ) { + curscore += 1; + } + } + else curscore++; + } + } + } + + if( curscore < 1 && curscore < bestscore ) { + memcpy(&bestregs, &(*itblock)->endregs[i], sizeof(bestregs)); + bestscore = curscore; + } + } + + if( bestscore < 1 ) { + if( startregs[i].inuse == bestregs.inuse ) { + if( bestregs.inuse && (startregs[i].type != bestregs.type || startregs[i].reg != bestregs.reg) ) + bchanged = true; + } + else bchanged = true; + + memcpy(&startregs[i], &bestregs, sizeof(bestregs)); + FORIT(itblock, parents) memcpy(&(*itblock)->endregs[i], &bestregs, sizeof(bestregs)); + } + else { + if( startregs[i].inuse ) bchanged = true; + startregs[i].inuse = 0; + FORIT(itblock, parents) (*itblock)->endregs[i].inuse = 0; + } + } + + return bchanged; +} + +void VuBaseBlock::AssignVFRegs() +{ + int i; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itblock; + list::iterator itinst, itnext, itinst2; + + // init the start regs + if( type & BLOCKTYPE_ANALYZED ) return; // nothing changed + memcpy(xmmregs, startregs, sizeof(xmmregs)); + + if( type & BLOCKTYPE_ANALYZED ) { + // check if changed + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse != startregs[i].inuse ) + break; + if( xmmregs[i].inuse && (xmmregs[i].reg != startregs[i].reg || xmmregs[i].type != startregs[i].type) ) + break; + } + + if( i == XMMREGS ) return; // nothing changed + } + + s8* oldX86 = x86Ptr; + + FORIT(itinst, insts) { + + if( itinst->type & INST_DUMMY ) + continue; + + // reserve, go from upper to lower + int lastwrite = -1; + + for(i = 1; i >= 0; --i) { + _VURegsNum* regs = itinst->regs+i; + + // redo the counters so that the proper regs are released + for(int j = 0; j < XMMREGS; ++j) { + if( xmmregs[j].inuse ) { + if( xmmregs[j].type == XMMTYPE_VFREG ) { + int count = 0; + itinst2 = itinst; + + if( i ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg ) { + itinst2 = insts.end(); + break; + } + else { + ++count; + ++itinst2; + } + } + + while(itinst2 != insts.end() ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg || + itinst2->regs[1].VFread0 == xmmregs[j].reg || itinst2->regs[1].VFread1 == xmmregs[j].reg || itinst2->regs[1].VFwrite == xmmregs[j].reg) + break; + + ++count; + ++itinst2; + } + xmmregs[j].counter = 1000-count; + } + else { + assert( xmmregs[j].type == XMMTYPE_ACC ); + + int count = 0; + itinst2 = itinst; + + if( i ) ++itinst2; // acc isn't used in lower insts + + while(itinst2 != insts.end() ) { + assert( !((itinst2->regs[0].VIread|itinst2->regs[0].VIwrite) & (1<regs[1].VIread|itinst2->regs[1].VIwrite) & (1<VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<vfread0[i] = itinst->vfread1[i] = itinst->vfwrite[i] = itinst->vfacc[i] = -1; + itinst->vfflush[i] = -1; + + if( regs->VFread0 ) itinst->vfread0[i] = _allocVFtoXMMreg(VU, -1, regs->VFread0, 0); + else if( regs->VIread & (1<vfread0[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VFread1 ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, regs->VFread1, 0); + else if( (regs->VIread & (1<VFr1xyzw != 0xff ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VIread & (1<vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + + int reusereg = -1; // 0 - VFwrite, 1 - VFAcc + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwxyzw == 0xf ) { + itinst->vfwrite[i] = _checkXMMreg(XMMTYPE_VFREG, regs->VFwrite, 0); + if( itinst->vfwrite[i] < 0 ) reusereg = 0; + } + else { + itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + else if( regs->VIwrite & (1<VFwxyzw == 0xf ) { + itinst->vfacc[i] = _checkXMMreg(XMMTYPE_ACC, 0, 0); + if( itinst->vfacc[i] < 0 ) reusereg = 1; + } + else { + itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + } + } + + if( reusereg >= 0 ) { + // reuse + itnext = itinst; itnext++; + + u8 type = reusereg ? XMMTYPE_ACC : XMMTYPE_VFREG; + u8 reg = reusereg ? 0 : regs->VFwrite; + + if( itinst->vfacc[i] >= 0 && lastwrite != itinst->vfacc[i] && + (itnext == insts.end() || ((regs->VIread&(1<usedvars[0]&(1<livevars[0]&(1<livevars[0]&(1<vfacc[i]); + xmmregs[itinst->vfacc[i]].inuse = 1; + xmmregs[itinst->vfacc[i]].reg = reg; + xmmregs[itinst->vfacc[i]].type = type; + xmmregs[itinst->vfacc[i]].mode = 0; + itinst->vfwrite[i] = itinst->vfacc[i]; + } + else if( itinst->vfread0[i] >= 0 && lastwrite != itinst->vfread0[i] && + (itnext == insts.end() || (regs->VFread0 > 0 && (!(itnext->usedvars[1]&(1<VFread0)) || !(itnext->livevars[1]&(1<VFread0))))) ) { + + if(itnext == insts.end() || (itnext->livevars[1]®s->VFread0)) _freeXMMreg(itinst->vfread0[i]); + xmmregs[itinst->vfread0[i]].inuse = 1; + xmmregs[itinst->vfread0[i]].reg = reg; + xmmregs[itinst->vfread0[i]].type = type; + xmmregs[itinst->vfread0[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread0[i]; + else itinst->vfwrite[i] = itinst->vfread0[i]; + } + else if( itinst->vfread1[i] >= 0 && lastwrite != itinst->vfread1[i] && + (itnext == insts.end() || (regs->VFread1 > 0 && (!(itnext->usedvars[1]&(1<VFread1)) || !(itnext->livevars[1]&(1<VFread1))))) ) { + + if(itnext == insts.end() || (itnext->livevars[1]®s->VFread1)) _freeXMMreg(itinst->vfread1[i]); + xmmregs[itinst->vfread1[i]].inuse = 1; + xmmregs[itinst->vfread1[i]].reg = reg; + xmmregs[itinst->vfread1[i]].type = type; + xmmregs[itinst->vfread1[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread1[i]; + else itinst->vfwrite[i] = itinst->vfread1[i]; + } + else { + if( reusereg ) itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + else itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + + if( itinst->vfwrite[i] >= 0 ) lastwrite = itinst->vfwrite[i]; + else if( itinst->vfacc[i] >= 0 ) lastwrite = itinst->vfacc[i]; + + // always alloc at least 1 temp reg + int free0 = (i||regs->VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<vfwrite[1] >= 0 && (itinst->vfread0[0]==itinst->vfwrite[1]||itinst->vfread1[0]==itinst->vfwrite[1]) ) { + itinst->vfflush[i] = _allocTempXMMreg(XMMT_FPS, -1); + } + + if( i == 1 && (regs->VIwrite & (1<VIwrite & (1<vfflush[i] >= 0 ) _freeXMMreg(itinst->vfflush[i]); + if( free0 >= 0 ) _freeXMMreg(free0); + + itinst->vffree[i] = (free0&0xf)|(free1<<8)|(free2<<16); + + _clearNeededXMMregs(); + } + } + + assert( x86Ptr == oldX86 ); + u32 analyzechildren = !(type&BLOCKTYPE_ANALYZED); + type |= BLOCKTYPE_ANALYZED; + + //memset(endregs, 0, sizeof(endregs)); + + if( analyzechildren ) { + FORIT(itchild, blocks) (*itchild)->AssignVFRegs(); + } +} + +struct MARKOVBLANKET +{ + list parents; + list children; +}; + +static MARKOVBLANKET s_markov; + +void VuBaseBlock::AssignVIRegs(int parent) +{ + const int maxregs = 6; + + if( parent ) { + if( (type&BLOCKTYPE_ANALYZEDPARENT) ) + return; + + type |= BLOCKTYPE_ANALYZEDPARENT; + s_markov.parents.push_back(this); + for(LISTBLOCKS::iterator it = blocks.begin(); it != blocks.end(); ++it) { + (*it)->AssignVIRegs(0); + } + return; + } + + if( (type&BLOCKTYPE_ANALYZED) ) + return; + + // child + assert( allocX86Regs == -1 ); + allocX86Regs = s_vecRegArray.size(); + s_vecRegArray.resize(allocX86Regs+X86REGS); + + _x86regs* pregs = &s_vecRegArray[allocX86Regs]; + memset(pregs, 0, sizeof(_x86regs)*X86REGS); + + assert( parents.size() > 0 ); + + list::iterator itparent; + u32 usedvars = insts.front().usedvars[0]; + u32 livevars = insts.front().livevars[0]; + + if( parents.size() > 0 ) { + u32 usedvars2 = 0xffffffff; + FORIT(itparent, parents) usedvars2 &= (*itparent)->insts.front().usedvars[0]; + usedvars |= usedvars2; + } + + usedvars &= livevars; + + // currently order doesn't matter + int num = 0; + + if( usedvars ) { + for(int i = 1; i < 16; ++i) { + if( usedvars & (1<= maxregs ) break; + } + } + } + + if( num < maxregs) { + livevars &= ~usedvars; + livevars &= insts.back().usedvars[0]; + + if( livevars ) { + for(int i = 1; i < 16; ++i) { + if( livevars & (1<= maxregs) break; + } + } + } + } + + s_markov.children.push_back(this); + type |= BLOCKTYPE_ANALYZED; + FORIT(itparent, parents) { + (*itparent)->AssignVIRegs(1); + } +} + +u32 VuBaseBlock::GetModeXYZW(u32 curpc, int vfreg) +{ + if( vfreg <= 0 ) return false; + + list::iterator itinst = insts.begin(); + advance(itinst, (curpc-startpc)/8); + + u8 mxy = 1; + u8 mxyz = 1; + + while(itinst != insts.end()) { + for(int i = 0; i < 2; ++i ) { + if( itinst->regs[i].VFwrite == vfreg ) { + if( itinst->regs[i].VFwxyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFwxyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread0 == vfreg ) { + if( itinst->regs[i].VFr0xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr0xyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread1 == vfreg ) { + if( itinst->regs[i].VFr1xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr1xyzw != 0xc ) mxy = 0; + } + + if( !mxy && !mxyz ) return 0; + } + ++itinst; + } + + return (mxy?MODE_VUXY:0)|(mxyz?MODE_VUXYZ:0); +} + +static void SuperVUAssignRegs() +{ + list::iterator itblock, itblock2; + + // assign xyz regs +// FORIT(itblock, s_listBlocks) { +// (*itblock)->vuxyz = 0; +// (*itblock)->vuxy = 0; +// +// for(int i = 0; i < 32; ++i) { +// u32 mode = (*itblock)->GetModeXYZW((*itblock)->startpc, i); +// if( mode & MODE_VUXYZ ) { +// if( mode & MODE_VUZ ) (*itblock)->vuxyz |= 1<vuxy |= 1<type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->AssignVFRegs(); + + // VI assignments, find markov blanket for each node in the graph + // then allocate regs based on the commonly used ones +#ifdef SUPERVU_X86CACHING + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~(BLOCKTYPE_ANALYZED|BLOCKTYPE_ANALYZEDPARENT); + s_vecRegArray.resize(0); + u8 usedregs[16]; + + // note: first block always has to start with no alloc regs + bool bfirst = true; + + FORIT(itblock, s_listBlocks) { + + if( !((*itblock)->type & BLOCKTYPE_ANALYZED) ) { + + if( (*itblock)->parents.size() == 0 ) { + (*itblock)->type |= BLOCKTYPE_ANALYZED; + bfirst = false; + continue; + } + + s_markov.children.clear(); + s_markov.parents.clear(); + (*itblock)->AssignVIRegs(0); + + // assign the regs + int regid = s_vecRegArray.size(); + s_vecRegArray.resize(regid+X86REGS); + + _x86regs* mergedx86 = &s_vecRegArray[regid]; + memset(mergedx86, 0, sizeof(_x86regs)*X86REGS); + + if( !bfirst ) { + *(u32*)usedregs = *((u32*)usedregs+1) = *((u32*)usedregs+2) = *((u32*)usedregs+3) = 0; + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->allocX86Regs >= 0 ); + _x86regs* pregs = &s_vecRegArray[(*itblock2)->allocX86Regs]; + for(int i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse && pregs[i].reg < 16) { + //assert( pregs[i].reg < 16); + usedregs[pregs[i].reg]++; + } + } + } + + int num = 1; + for(int i = 0; i < 16; ++i) { + if( usedregs[i] == s_markov.children.size() ) { + // use + mergedx86[num].inuse = 1; + mergedx86[num].reg = i; + mergedx86[num].type = (s_vu?X86TYPE_VU1:0)|X86TYPE_VI; + mergedx86[num].mode = MODE_READ; + if( ++num >= X86REGS ) + break; + if( num == ESP ) + ++num; + } + } + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->nStartx86 == -1 ); + (*itblock2)->nStartx86 = regid; + } + + FORIT(itblock2, s_markov.parents) { + assert( (*itblock2)->nEndx86 == -1 ); + (*itblock2)->nEndx86 = regid; + } + } + + bfirst = false; + } + } +#endif +} + +////////////////// +// Recompilation +////////////////// + +// cycles in which the last Q,P regs were finished (written to VU->VI[]) +// the write occurs before the instruction is executed at that cycle +// compare with s_TotalVUCycles +// if less than 0, already flushed +static int s_writeQ, s_writeP; +static int s_recWriteQ, s_recWriteP; // wait times during recompilation +static int s_needFlush; // first bit - Q, second bit - P, third bit - Q has been written, fourth bit - P has been written + +static u32 s_vu1ebp, s_vuedi, s_vuebx, s_vu1esp, s_vu1esi, s_callstack;//, s_vu1esp +static u32 s_ssecsr; +static int s_JumpX86; +static int s_ScheduleXGKICK = 0, s_XGKICKReg = -1; + +extern "C" u32 g_sseVUMXCSR, g_sseMXCSR; + +void recSVUMI_XGKICK_( VURegs *VU ); + +// entry point of all vu programs from emulator calls +__declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svubase); +#endif + __asm { + mov eax, dword ptr [esp] + mov s_TotalVUCycles, 0 // necessary to be here! + add esp, 4 + mov s_callstack, eax + call SuperVUGetProgram + + // save cpu state + mov s_vu1ebp, ebp + mov s_vu1esi, esi // have to save even in Release + mov s_vuedi, edi // have to save even in Release + mov s_vuebx, ebx + } +#ifdef _DEBUG + __asm { + mov s_vu1esp, esp + } +#endif + + __asm { + //stmxcsr s_ssecsr + ldmxcsr g_sseVUMXCSR + + // init vars + mov s_writeQ, 0xffffffff + mov s_writeP, 0xffffffff + + jmp eax + } +} + +static void SuperVUCleanupProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +#endif + +#ifdef _DEBUG + assert( s_vu1esp == 0 ); +#endif + + VU = vuindex ? &VU1 : &VU0; + VU->cycle += s_TotalVUCycles; + if( (int)s_writeQ > 0 ) VU->VI[REG_Q] = VU->q; + if( (int)s_writeP > 0 ) { + assert(VU == &VU1); + VU1.VI[REG_P] = VU1.p; // only VU1 + } +} + +// exit point of all vu programs +__declspec(naked) static void SuperVUEndProgram() +{ + __asm { + // restore cpu state + ldmxcsr g_sseMXCSR + + mov ebp, s_vu1ebp + mov esi, s_vu1esi + mov edi, s_vuedi + mov ebx, s_vuebx + } + +#ifdef _DEBUG + __asm { + sub s_vu1esp, esp + } +#endif + + __asm { + call SuperVUCleanupProgram + jmp s_callstack // so returns correctly + } +} + +// Flushes P/Q regs +void SuperVUFlush(int p, int wait) +{ + u8* pjmp[3]; + if( !(s_needFlush&(1<info.cycle < recwait ) return; + + if( recwait == 0 ) { + // write didn't happen this block + MOV32MtoR(EAX, p ? (u32)&s_writeP : (u32)&s_writeQ); + OR32RtoR(EAX, EAX); + pjmp[0] = JS8(0); + + if( s_pCurInst->info.cycle ) SUB32ItoR(EAX, s_pCurInst->info.cycle); + + // if writeQ <= total+offset + if( !wait ) { // only write back if time is up + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[1] = JG8(0); + } + else { + // add (writeQ-total-offset) to s_TotalVUCycles + // necessary? + CMP32MtoR(EAX, (u32)&s_TotalVUCycles); + pjmp[2] = JLE8(0); + MOV32RtoM((u32)&s_TotalVUCycles, EAX); + x86SetJ8(pjmp[2]); + } + } + else if( wait && s_pCurInst->info.cycle < recwait ) { + ADD32ItoM((u32)&s_TotalVUCycles, recwait); + } + + MOV32MtoR(EAX, SuperVUGetVIAddr(p?REG_P:REG_Q, 0)); + MOV32ItoM(p ? (u32)&s_writeP : (u32)&s_writeQ, 0x80000000); + MOV32RtoM(SuperVUGetVIAddr(p?REG_P:REG_Q, 1), EAX); + + if( recwait == 0 ) { + if( !wait ) x86SetJ8(pjmp[1]); + x86SetJ8(pjmp[0]); + } + + if( wait || (!p && recwait == 0 && s_pCurInst->info.cycle >= 12) || (!p && recwait > 0 && s_pCurInst->info.cycle >= recwait ) ) + s_needFlush &= ~(1<::iterator itblock; + + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->Recompile(); + // make sure everything compiled + FORIT(itblock, s_listBlocks) assert( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->pcode != NULL ); + + // link all blocks + FORIT(itblock, s_listBlocks) { + VuBaseBlock::LISTBLOCKS::iterator itchild; + + assert( (*itblock)->blocks.size() <= ARRAYSIZE((*itblock)->pChildJumps) ); + + int i = 0; + FORIT(itchild, (*itblock)->blocks) { + + if( (u32)(*itblock)->pChildJumps[i] == 0xffffffff ) + continue; + + if( (*itblock)->pChildJumps[i] == NULL ) { + VuBaseBlock* pchild = *itchild; + + if( pchild->type & BLOCKTYPE_HASEOP) { + assert( pchild->blocks.size() == 0); + + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + + MOV32ItoM((u32)&VU->VI[REG_TPC], pchild->endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + // only other case is when there are two branches + else assert( (*itblock)->insts.back().regs[0].pipe == VUPIPE_BRANCH ); + + continue; + } + + if( (u32)(*itblock)->pChildJumps[i] & 0x80000000 ) { + // relative + *(u32*)&(*itblock)->pChildJumps[i] &= 0x7fffffff; + *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode - ((u32)(*itblock)->pChildJumps[i] + 4); + } + else *(*itblock)->pChildJumps[i] = (u32)(*itchild)->pcode; + + ++i; + } + } + + s_pFnHeader->pprogfunc = s_listBlocks.front()->pcode; +} + +static u32 s_svulast = 0, s_vufnheader; +extern "C" u32 s_vucount = 0; +static u32 lastrec = 0, skipparent = -1; +static u32 s_saveecx, s_saveedx, s_saveebx, s_saveesi, s_saveedi, s_saveebp; +static u32 badaddrs[][2] = {0,0xffff}; + +__declspec(naked) static void svudispfn() +{ + static u32 i; + static u32 curvu; + + __asm { + mov curvu, eax + mov s_saveecx, ecx + mov s_saveedx, edx + mov s_saveebx, ebx + mov s_saveesi, esi + mov s_saveedi, edi + mov s_saveebp, ebp + } + +// for(i = 1; i < 32; ++i) { +// if( (VU1.VF[i].UL[3]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[3] &= 0xff7fffff; +// if( (VU1.VF[i].UL[2]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[2] &= 0xff7fffff; +// if( (VU1.VF[i].UL[1]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[1] &= 0xff7fffff; +// if( (VU1.VF[i].UL[0]&0x7f800000) == 0x7f800000 ) VU1.VF[i].UL[0] &= 0xff7fffff; +// } + + if( ((vudump&8) && curvu) || ((vudump&0x80) && !curvu) ) { //&& lastrec != g_vu1last ) { + + if( skipparent != lastrec ) { + for(i = 0; i < ARRAYSIZE(badaddrs); ++i) { + if( s_svulast == badaddrs[i][1] && lastrec == badaddrs[i][0] ) + break; + } + + if( i == ARRAYSIZE(badaddrs) ) + { + static int curesp; + __asm mov curesp, esp + __Log("tVU: %x\n", s_svulast, s_vucount); + if( curvu ) iDumpVU1Registers(); + else iDumpVU0Registers(); + s_vucount++; + } + } + + lastrec = s_svulast; + } + + __asm { + mov ecx, s_saveecx + mov edx, s_saveedx + mov ebx, s_saveebx + mov esi, s_saveesi + mov edi, s_saveedi + mov ebp, s_saveebp + ret + } +} + +// frees an xmmreg depending on the liveness info of hte current inst +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg) +//{ +// if( !xmmregs[xmmreg].inuse ) return; +// if( xmmregs[xmmreg].type == xmmtype && xmmregs[xmmreg].reg == reg ) return; +// +// if( s_pNextInst == NULL ) { +// // last inst, free +// _freeXMMreg(xmmreg); +// return; +// } +// +// if( xmmregs[xmmreg].type == XMMTYPE_VFREG ) { +// if( (s_pCurInst->livevars[1]|s_pNextInst->livevars[1]) & (1<livevars[0]|s_pNextInst->livevars[0]) & (1<VF[xmmregs[i].reg] : (u32)&VU->ACC; + + if( xmmregs[i].mode & MODE_VUZ ) { + SSE_MOVHPS_XMM_to_M64(addr, (x86SSERegType)i); + SSE_SHUFPS_M128_to_XMM((x86SSERegType)i, addr, 0xc4); + } + else SSE_MOVHPS_M64_to_XMM((x86SSERegType)i, addr+8); + + xmmregs[i].mode &= ~MODE_VUXYZ; + } + + _freeXMMreg(i); + } + } + } + + //_freeXMMregs(); +} + +//void timeout() { SysPrintf("VU0 timeout\n"); } +void SuperVUTestVU0Condition(u32 incstack) +{ + if( s_vu ) return; // vu0 only + + CMP32ItoM((u32)&s_TotalVUCycles, 512); // sometimes games spin on vu0, so be careful with this value + // woody hangs if too high + + if( incstack ) { + u8* ptr = JB8(0); + + if( incstack ) ADD32ItoR(ESP, incstack); + //CALLFunc((u32)timeout); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + + x86SetJ8(ptr); + } + else { + JAE32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 6 ) ); + } +} + +void VuBaseBlock::Recompile() +{ + if( type & BLOCKTYPE_ANALYZED ) return; + + x86Align(16); + pcode = x86Ptr; + +#ifdef _DEBUG + MOV32ItoM((u32)&s_vufnheader, s_pFnHeader->startpc); + MOV32ItoM((u32)&VU->VI[REG_TPC], startpc); + MOV32ItoM((u32)&s_svulast, startpc); + list::iterator itparent; + for(itparent = parents.begin(); itparent != parents.end(); ++itparent) { + if( (*itparent)->blocks.size()==1 && (*itparent)->blocks.front()->startpc == startpc && + ((*itparent)->insts.size() < 2 || (----(*itparent)->insts.end())->regs[0].pipe != VUPIPE_BRANCH) ) { + MOV32ItoM((u32)&skipparent, (*itparent)->startpc); + break; + } + } + + if( itparent == parents.end() ) MOV32ItoM((u32)&skipparent, -1); + + MOV32ItoR(EAX, s_vu); + CALLFunc((u32)svudispfn); +#endif + + s_pCurBlock = this; + s_needFlush = 3; + pc = startpc; + branch = 0; + s_recWriteQ = s_recWriteP = 0; + s_XGKICKReg = -1; + s_ScheduleXGKICK = 0; + + s_ClipRead = s_PrevClipWrite = (u32)&VU->VI[REG_CLIP_FLAG]; + s_StatusRead = s_PrevStatusWrite = (u32)&VU->VI[REG_STATUS_FLAG]; + s_MACRead = s_PrevMACWrite = (u32)&VU->VI[REG_MAC_FLAG]; + s_PrevIWrite = (u32)&VU->VI[REG_I]; + s_JumpX86 = 0; + s_UnconditionalDelay = 0; + + memcpy(xmmregs, startregs, sizeof(xmmregs)); +#ifdef SUPERVU_X86CACHING + if( nStartx86 >= 0 ) + memcpy(x86regs, &s_vecRegArray[nStartx86], sizeof(x86regs)); + else _initX86regs(); +#else + _initX86regs(); +#endif + + list::iterator itinst; + FORIT(itinst, insts) { + s_pCurInst = &(*itinst); + if( s_JumpX86 > 0 ) { + if( !x86regs[s_JumpX86].inuse ) { + // load + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_READ); + } + x86regs[s_JumpX86].needed = 1; + } + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) { + assert( x86regs[s_XGKICKReg].inuse ); + x86regs[s_XGKICKReg].needed = 1; + } + itinst->Recompile(itinst, vuxyz); + + if( s_ScheduleXGKICK > 0 ) { + if( s_ScheduleXGKICK-- == 1 ) { + recSVUMI_XGKICK_(VU); + } + } + } + assert( pc == endpc ); + assert( s_ScheduleXGKICK == 0 ); + + // flush flags + if( s_PrevClipWrite != (u32)&VU->VI[REG_CLIP_FLAG] ) { + MOV32MtoR(EAX, s_PrevClipWrite); + MOV32RtoM((u32)&VU->VI[REG_CLIP_FLAG], EAX); + } + if( s_PrevStatusWrite != (u32)&VU->VI[REG_STATUS_FLAG] ) { + MOV32MtoR(EAX, s_PrevStatusWrite); + MOV32RtoM((u32)&VU->VI[REG_STATUS_FLAG], EAX); + } + if( s_PrevMACWrite != (u32)&VU->VI[REG_MAC_FLAG] ) { + MOV32MtoR(EAX, s_PrevMACWrite); + MOV32RtoM((u32)&VU->VI[REG_MAC_FLAG], EAX); + } + if( s_PrevIWrite != (u32)&VU->VI[REG_I] ) { + MOV32ItoM((u32)&VU->VI[REG_I], *(u32*)s_PrevIWrite); // never changes + } + + ADD32ItoM((u32)&s_TotalVUCycles, cycles); + + // compute branches, jumps, eop + if( type & BLOCKTYPE_HASEOP ) { + // end + _freeXMMregs(); + _freeX86regs(); + AND32ItoM( (u32)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (u32)&VU->vifRegs->stat, ~0x4 ); + if( !branch ) MOV32ItoM((u32)&VU->VI[REG_TPC], endpc); + JMP32( (u32)SuperVUEndProgram - ( (u32)x86Ptr + 5 )); + } + else { + + u32 livevars[2] = {0}; + + list::iterator lastinst = GetInstIterAtPc(endpc-8); + lastinst++; + + if( lastinst != insts.end() ) { + livevars[0] = lastinst->livevars[0]; + livevars[1] = lastinst->livevars[1]; + } + else { + // take from children + if( blocks.size() > 0 ) { + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + livevars[0] |= (*itchild)->insts.front().livevars[0]; + livevars[1] |= (*itchild)->insts.front().livevars[1]; + } + } + else { + livevars[0] = ~0; + livevars[1] = ~0; + } + } + + SuperVUFreeXMMregs(livevars); + + // get rid of any writes, otherwise _freeX86regs will write + x86regs[s_JumpX86].mode &= ~MODE_WRITE; + + if( branch == 1 ) { + if( !x86regs[s_JumpX86].inuse ) { + assert( x86regs[s_JumpX86].type == X86TYPE_VUJUMP ); + s_JumpX86 = 0xffffffff; // notify to jump from g_recWriteback + } + } + + // align VI regs +#ifdef SUPERVU_X86CACHING + if( nEndx86 >= 0 ) { + _x86regs* endx86 = &s_vecRegArray[nEndx86]; + for(int i = 0; i < X86REGS; ++i) { + if( endx86[i].inuse ) { + + if( s_JumpX86 == i && x86regs[s_JumpX86].inuse ) { + x86regs[s_JumpX86].inuse = 0; + x86regs[EAX].inuse = 1; + MOV32RtoR(EAX, s_JumpX86); + s_JumpX86 = EAX; + } + + if( x86regs[i].inuse ) { + if( x86regs[i].type == endx86[i].type && x86regs[i].reg == endx86[i].reg ) { + _freeX86reg(i); + // will continue to use it + continue; + } + + if( x86regs[i].type == (X86TYPE_VI|(s_vu?X86TYPE_VU1:0)) ) { +#ifdef SUPERVU_INTERCACHING + if( livevars[0] & (1<code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) << 3; +// ADD32ItoRmOffset(ESP, delta, 0); + ADD32ItoR(ESP, 8); // restore + pChildJumps[0] = (u32*)((u32)JMP32(0)|0x80000000); + + break; + } + case 0: + case 3: // unconditional branch + pChildJumps[s_UnconditionalDelay] = (u32*)((u32)JMP32(0)|0x80000000); + break; + + default: +#ifdef PCSX2_DEVBUILD + SysPrintf("Bad branch %x\n", branch); +#endif + assert(0); + break; + } + } + + type |= BLOCKTYPE_ANALYZED; + + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + (*itchild)->Recompile(); + } +} + +#define GET_VUXYZMODE(reg) 0//((vuxyz&(1<<(reg)))?MODE_VUXYZ:0) + +int VuInstruction::SetCachedRegs(int upper, u32 vuxyz) +{ + if( vfread0[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread0[upper], XMMTYPE_VFREG, regs[upper].VFread0); + _allocVFtoXMMreg(VU, vfread0[upper], regs[upper].VFread0, MODE_READ|GET_VUXYZMODE(regs[upper].VFread0)); + } + if( vfread1[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread1[upper], XMMTYPE_VFREG, regs[upper].VFread1); + _allocVFtoXMMreg(VU, vfread1[upper], regs[upper].VFread1, MODE_READ|GET_VUXYZMODE(regs[upper].VFread1)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIread&(1<= 0 ) { + assert( regs[upper].VFwrite > 0); + SuperVUFreeXMMreg(vfwrite[upper], XMMTYPE_VFREG, regs[upper].VFwrite); + _allocVFtoXMMreg(VU, vfwrite[upper], regs[upper].VFwrite, + MODE_WRITE|(regs[upper].VFwxyzw != 0xf?MODE_READ:0)|GET_VUXYZMODE(regs[upper].VFwrite)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIwrite&(1<= 0 ) info |= PROCESS_EE_SET_S(vfread0[upper]); + if( vfread1[upper] >= 0 ) info |= PROCESS_EE_SET_T(vfread1[upper]); + if( vfacc[upper] >= 0 ) info |= PROCESS_VU_SET_ACC(vfacc[upper]); + if( vfwrite[upper] >= 0 ) { + if( regs[upper].VFwrite == _Ft_ && vfread1[upper] < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite[upper]); + } + else { + assert( regs[upper].VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite[upper]); + } + } + + if( (vffree[upper]&0xf) < XMMREGS ) { + SuperVUFreeXMMreg(vffree[upper]&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vffree[upper]&0xf); + } + info |= PROCESS_VU_SET_TEMP(vffree[upper]&0xf); + + if( vfflush[upper] >= 0 ) { + SuperVUFreeXMMreg(vfflush[upper], XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vfflush[upper]); + } + + if( upper && (regs[upper].VIwrite & (1 << REG_CLIP_FLAG)) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + assert( vfwrite[upper] == -1 ); + SuperVUFreeXMMreg((vffree[upper]>>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + + SuperVUFreeXMMreg((vffree[upper]>>16)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>16)&0xf); + info |= PROCESS_EE_SET_ACC((vffree[upper]>>16)&0xf); + + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + _freeXMMreg((vffree[upper]>>16)&0xf); // don't need anymore + } + else if( regs[upper].VIwrite & (1<>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + } + + if( vfflush[upper] >= 0 ) _freeXMMreg(vfflush[upper]); + if( (vffree[upper]&0xf) < XMMREGS ) _freeXMMreg(vffree[upper]&0xf); // don't need anymore + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<::const_iterator& itinst, u32 vuxyz) +{ + static PCSX2_ALIGNED16(VECTOR _VF); + static PCSX2_ALIGNED16(VECTOR _VFc); + u32 *ptr; + u8* pjmp; + int vfregstore=0, viregstore=0; + + assert( s_pCurInst == this); + s_WriteToReadQ = 0; + + ptr = (u32*)&VU->Micro[ pc ]; + + if( type & INST_Q_READ ) + SuperVUFlush(0, (ptr[0] == 0x800003bf)||!!(regs[0].VIwrite & (1<startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_ClipRead = (u32)&VU->VI[REG_CLIP_FLAG]; + else { + s_ClipRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pClipWrite; + } + } + + // before modifying, check if they will ever be read + if( s_pCurBlock->type & BLOCKTYPE_MACFLAGS ) { + if( type & INST_STATUS_WRITE ) { + + if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_StatusRead = (u32)&VU->VI[REG_STATUS_FLAG]; + else { + s_StatusRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pStatusWrite; + } + } + if( type & INST_MAC_WRITE ) { + + if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_MACRead = (u32)&VU->VI[REG_MAC_FLAG]; + else { + s_MACRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pMACWrite; + } + } + } + + assert( s_ClipRead != 0 ); + assert( s_MACRead != 0 ); + assert( s_StatusRead != 0 ); + return; + } + +#ifdef _DEBUG +// CMP32ItoM((u32)ptr, ptr[0]); +// j8Ptr[0] = JNE8(0); +// CMP32ItoM((u32)(ptr+1), ptr[1]); +// j8Ptr[1] = JNE8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[0] ); +// x86SetJ8( j8Ptr[1] ); +// PUSH32I(ptr[0]); +// PUSH32I(s_vu); +// PUSH32I(pc); +// CALLFunc((u32)checkvucodefn); +// ADD32ItoR(ESP, 12); +// x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoR(EAX, pc); +#endif + + assert( !(type & (INST_CLIP_WRITE|INST_STATUS_WRITE|INST_MAC_WRITE)) ); + pc += 8; + + list::const_iterator itinst2; + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<type & BLOCKTYPE_MACFLAGS ) { + if( pMACWrite == NULL ) { + pMACWrite = (u32)SuperVUStaticAlloc(4); + } + if( pStatusWrite == NULL ) + pStatusWrite = (u32)SuperVUStaticAlloc(4); + } + else { + assert( s_StatusRead == (u32)&VU->VI[REG_STATUS_FLAG] ); + assert( s_MACRead == (u32)&VU->VI[REG_MAC_FLAG] ); + pMACWrite = s_MACRead; + pStatusWrite = s_StatusRead; + } + } + + if( pClipWrite == NULL && ((regs[0].VIwrite|regs[1].VIwrite) & (1<insts.end() ) { + if( (itinst2->regs[0].VIread|itinst2->regs[0].VIwrite|itinst2->regs[1].VIread|itinst2->regs[1].VIwrite) && (1<flags, VUFLAG_MFLAGSET); + } + if (ptr[1] & 0x10000000) { // D flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x400:0x004); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x200:0x002); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + if (ptr[1] & 0x08000000) { // T flag + TEST32ItoM((u32)&VU0.VI[REG_FBRST].UL, s_vu?0x800:0x008); + u8* ptr = JZ8(0); + OR32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x400:0x004); + PUSH32I(s_vu?INTC_VU1:INTC_VU0); + CALLFunc((u32)hwIntcIrq); + ADD32ItoR(ESP, 4); + x86SetJ8(ptr); + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + + assert( !(regs[0].VIwrite & ((1<code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + + s_PrevIWrite = (u32)ptr; + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + else { + if( regs[0].VIwrite & (1<insts.end()); + u32* codeptr2 = ptr+2; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( !(itinst2->type & INST_DUMMY) && ((itinst2->regs[0].VIwrite&(1<type & INST_Q_WRITE) && itinst2->nParentPc == pc-8 ) { + break; + } + if( itinst2->type & INST_Q_READ ) { + cacheq = 1; + break; + } + if( itinst2->type & INST_DUMMY ) { + ++itinst2; + continue; + } + codeptr2 += 2; + ++itinst2; + } + + if( itinst2 == s_pCurBlock->insts.end() ) + cacheq = 1; + + int x86temp = -1; + if( cacheq ) + x86temp = _allocX86reg(-1, X86TYPE_TEMP, 0, 0); + + // new is written so flush old + // if type & INST_Q_READ, already flushed + if( !(type & INST_Q_READ) && s_recWriteQ == 0 ) MOV32MtoR(EAX, (u32)&s_writeQ); + + if( cacheq ) + MOV32MtoR(x86temp, (u32)&s_TotalVUCycles); + + if( !(type & INST_Q_READ) ) { + if( s_recWriteQ == 0 ) { + OR32RtoR(EAX, EAX); + pjmp = JS8(0); + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + x86SetJ8(pjmp); + } + else if( s_needFlush & 1 ) { + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + s_needFlush &= ~1; + } + } + + // write new Q + if( cacheq ) { + assert(s_pCurInst->pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeQ, x86temp); + s_needFlush |= 1; + } + else { + // won't be writing back + s_WriteToReadQ = 1; + s_needFlush &= ~1; + MOV32ItoM((u32)&s_writeQ, 0x80000001); + } + + s_recWriteQ = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + if( x86temp >= 0 ) + _freeX86reg(x86temp); + } + + if( regs[0].VIwrite & (1<pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((u32)&s_writeP, x86temp); + s_needFlush |= 2; + + s_recWriteP = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + _freeX86reg(x86temp); + } + + if( ptr[0] == 0x800003bf ) // waitq + SuperVUFlush(0, 1); + + if( ptr[0] == 0x800007bf ) // waitp + SuperVUFlush(1, 1); + +#ifdef PCSX2_DEVBUILD + if ( regs[1].VIread & regs[0].VIwrite & ~((1<startpc); + } +#endif + + u32 modewrite = 0; + if( vfwrite[1] >= 0 && xmmregs[vfwrite[1]].inuse && xmmregs[vfwrite[1]].type == XMMTYPE_VFREG && xmmregs[vfwrite[1]].reg == regs[1].VFwrite ) + modewrite = xmmregs[vfwrite[1]].mode & MODE_WRITE; + + VU->code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + + if (vfwrite[1] >= 0) { + assert( regs[1].VFwrite > 0 ); + + if (vfwrite[0] == vfwrite[1]) { + //SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle %x\n", s_pCurBlock->startpc); + } + + if (vfread0[0] == vfwrite[1] || vfread1[0] == vfwrite[1] ) { + assert( regs[0].VFread0 == regs[1].VFwrite || regs[0].VFread1 == regs[1].VFwrite ); + assert( vfflush[0] >= 0 ); + if( modewrite ) { + SSE_MOVAPS_XMM_to_M128((u32)&VU->VF[regs[1].VFwrite], (x86SSERegType)vfwrite[1]); + } + vfregstore = 1; + } + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + + // necessary because status can be set by both upper and lower + if( regs[1].VIwrite & (1<code = ptr[0]; + s_vuInfo = SetCachedRegs(0, vuxyz); + + if( vfregstore ) { + // load + SSE_MOVAPS_M128_to_XMM(vfflush[0], (u32)&VU->VF[regs[1].VFwrite]); + + assert( xmmregs[vfwrite[1]].mode & MODE_WRITE ); + + // replace with vfflush + if( _Fs_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_S(0xf); + s_vuInfo |= PROCESS_EE_SET_S(vfflush[0]); + } + if( _Ft_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_T(0xf); + s_vuInfo |= PROCESS_EE_SET_T(vfflush[0]); + } + + xmmregs[vfflush[0]].mode |= MODE_NOFLUSH|MODE_WRITE; // so that lower inst doesn't flush + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + // check if inst before branch and the write is the same as the read in the branch (wipeout) + int oldreg=0; +// if( pc == s_pCurBlock->endpc-16 ) { +// itinst2 = itinst; ++itinst2; +// if( itinst2->regs[0].pipe == VUPIPE_BRANCH && (itinst->regs[0].VIwrite&itinst2->regs[0].VIread) ) { +// +// CALLFunc((u32)branchfn); +// assert( itinst->regs[0].VIwrite & 0xffff ); +// SysPrintf("vi write before branch\n"); +// for(s_CacheVIReg = 0; s_CacheVIReg < 16; ++s_CacheVIReg) { +// if( itinst->regs[0].VIwrite & (1<endpc-8 && s_CacheVIReg >= 0 ) { +// assert( s_CacheVIX86 > 0 && x86regs[s_CacheVIX86].inuse && x86regs[s_CacheVIX86].reg == s_CacheVIReg && x86regs[s_CacheVIX86].type == X86TYPE_VITEMP ); +// +// oldreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), s_CacheVIReg, MODE_READ); +// x86regs[s_CacheVIX86].needed = 1; +// assert( x86regs[oldreg].mode & MODE_WRITE ); +// +// x86regs[s_CacheVIX86].type = X86TYPE_VI|(s_vu?X86TYPE_VU1:0); +// x86regs[oldreg].type = X86TYPE_VITEMP; +// } + + recSVU_LOWER_OPCODE[ VU->code >> 25 ](); + +// if( pc == s_pCurBlock->endpc-8 && s_CacheVIReg >= 0 ) { +// // revert +// x86regs[s_CacheVIX86].inuse = 0; +// x86regs[oldreg].type = X86TYPE_VI|(s_vu?X86TYPE_VU1:0); +// } + + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + + // clip is always written so ok + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<code); + int curjump = 0; + + if( s_pCurInst->type & INST_BRANCH_DELAY ) { + assert( (branch&0x17)!=0x10 && (branch&0x17)!=4 ); // no jump handlig for now + + if( (branch & 0x7) == 3 ) { + // previous was a direct jump + curjump = 1; + } + else if( branch & 1 ) curjump = 2; + } + + assert( s_JumpX86 > 0 ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr-1; + + if( !(s_pCurInst->type & INST_BRANCH_DELAY) ) { + j8Ptr[1] = JMP8(0); + x86SetJ8( j8Ptr[ 0 ] ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), pc+8); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr-1; + + x86SetJ8( j8Ptr[ 1 ] ); + } + else + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +// supervu specific insts +void recSVUMI_IBQ_prep() +{ + int fsreg, ftreg; + + if( _Fs_ == 0 ) { + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( ftreg >= 0 ) { + CMP16ItoR( ftreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Ft_, 1), 0); + } + else if( _Ft_ == 0 ) { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR( fsreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Fs_, 1), 0); + } + else { + _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_); + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + if( ftreg >= 0 ) { + CMP16RtoR( fsreg, ftreg ); + } + else CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + else if( ftreg >= 0 ) { + CMP16MtoR(ftreg, SuperVUGetVIAddr(_Fs_, 1)); + } + else { + fsreg = _allocX86reg(-1, X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + } +} + +void recSVUMI_IBEQ() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JNE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + } + + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JLE8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JG8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JNS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBNE() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_B() +{ + // supervu will take care of the rest + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; + s_UnconditionalDelay = 1; + } + + branch |= 3; +} + +void recSVUMI_BAL() +{ + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; + s_UnconditionalDelay = 1; + } + + branch |= 3; +} + +void recSVUMI_JR() +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + branch |= 0x10; // 0x08 is reserved +} + +void recSVUMI_JALR() +{ + _addNeededX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_); + + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); // necessary, charlie and chocolate factory gives bad addrs, but graphics are ok + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { + PUSH32I(s_vu); + PUSH32R(EAX); + } + + branch |= 4; +} + +#ifdef SUPERVU_COUNT +void StopSVUCounter() +{ + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +} + +void StartSVUCounter() +{ + QueryPerformanceCounter(&svubase); +} +#endif + +#ifdef PCSX2_DEVBUILD +void vu1xgkick(u32* pMem, u32 addr) +{ + assert( addr < 0x4000 ); +#ifdef _DEBUG + static int scount = 0; + static int curesp; + __asm mov curesp, esp + scount++; + if( vudump & 8 ) { + __Log("xgkick 0x%x (%d)\n", addr, scount); + } +#endif + + GSGIFTRANSFER1(pMem, addr); +} + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 16 ) { +// __Log("xgkick %d\n", scount); +// vudump |= 8; +// } +//} + +#endif + +void recSVUMI_XGKICK_( VURegs *VU ) +{ + assert( s_XGKICKReg > 0 && x86regs[s_XGKICKReg].inuse && x86regs[s_XGKICKReg].type == X86TYPE_VITEMP); + + x86regs[s_XGKICKReg].inuse = 0; // so free doesn't flush + _freeX86regs(); + _freeXMMregs(); + + PUSH32R(s_XGKICKReg); + PUSH32I((int)VU->Mem); + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StopSVUCounter); +#endif + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((int)VU1XGKICK_MTGSTransfer); + ADD32ItoR(ESP, 8); + } + else { +#ifdef PCSX2_DEVBUILD + CALLFunc((int)vu1xgkick); + ADD32ItoR(ESP, 8); +#else + CALLFunc((int)GSgifTransfer1); +#endif + } + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StartSVUCounter); +#endif + + s_ScheduleXGKICK = 0; +} + +void recSVUMI_XGKICK( VURegs *VU, int info ) +{ + if( s_ScheduleXGKICK ) { + // second xgkick, so launch the first + recSVUMI_XGKICK_(VU); + } + + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + _freeX86reg(fsreg); // flush + x86regs[fsreg].inuse = 1; + x86regs[fsreg].type = X86TYPE_VITEMP; + x86regs[fsreg].needed = 1; + x86regs[fsreg].mode = MODE_WRITE|MODE_READ; + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + s_XGKICKReg = fsreg; + +#ifdef SUPERVU_XGKICKDELAY + if( pc == s_pCurBlock->endpc ) { + recSVUMI_XGKICK_(VU); + } + else { + s_ScheduleXGKICK = 2; + } +#else + recSVUMI_XGKICK_(VU); +#endif +} + +// upper inst +void recSVUMI_ABS() { recVUMI_ABS(VU, s_vuInfo); } + +void recSVUMI_ADD() { recVUMI_ADD(VU, s_vuInfo); } +void recSVUMI_ADDi() { recVUMI_ADDi(VU, s_vuInfo); } +void recSVUMI_ADDq() { recVUMI_ADDq(VU, s_vuInfo); } +void recSVUMI_ADDx() { recVUMI_ADDx(VU, s_vuInfo); } +void recSVUMI_ADDy() { recVUMI_ADDy(VU, s_vuInfo); } +void recSVUMI_ADDz() { recVUMI_ADDz(VU, s_vuInfo); } +void recSVUMI_ADDw() { recVUMI_ADDw(VU, s_vuInfo); } + +void recSVUMI_ADDA() { recVUMI_ADDA(VU, s_vuInfo); } +void recSVUMI_ADDAi() { recVUMI_ADDAi(VU, s_vuInfo); } +void recSVUMI_ADDAq() { recVUMI_ADDAq(VU, s_vuInfo); } +void recSVUMI_ADDAx() { recVUMI_ADDAx(VU, s_vuInfo); } +void recSVUMI_ADDAy() { recVUMI_ADDAy(VU, s_vuInfo); } +void recSVUMI_ADDAz() { recVUMI_ADDAz(VU, s_vuInfo); } +void recSVUMI_ADDAw() { recVUMI_ADDAw(VU, s_vuInfo); } + +void recSVUMI_SUB() { recVUMI_SUB(VU, s_vuInfo); } +void recSVUMI_SUBi() { recVUMI_SUBi(VU, s_vuInfo); } +void recSVUMI_SUBq() { recVUMI_SUBq(VU, s_vuInfo); } +void recSVUMI_SUBx() { recVUMI_SUBx(VU, s_vuInfo); } +void recSVUMI_SUBy() { recVUMI_SUBy(VU, s_vuInfo); } +void recSVUMI_SUBz() { recVUMI_SUBz(VU, s_vuInfo); } +void recSVUMI_SUBw() { recVUMI_SUBw(VU, s_vuInfo); } + +void recSVUMI_SUBA() { recVUMI_SUBA(VU, s_vuInfo); } +void recSVUMI_SUBAi() { recVUMI_SUBAi(VU, s_vuInfo); } +void recSVUMI_SUBAq() { recVUMI_SUBAq(VU, s_vuInfo); } +void recSVUMI_SUBAx() { recVUMI_SUBAx(VU, s_vuInfo); } +void recSVUMI_SUBAy() { recVUMI_SUBAy(VU, s_vuInfo); } +void recSVUMI_SUBAz() { recVUMI_SUBAz(VU, s_vuInfo); } +void recSVUMI_SUBAw() { recVUMI_SUBAw(VU, s_vuInfo); } + +void recSVUMI_MUL() { recVUMI_MUL(VU, s_vuInfo); } +void recSVUMI_MULi() { recVUMI_MULi(VU, s_vuInfo); } +void recSVUMI_MULq() { recVUMI_MULq(VU, s_vuInfo); } +void recSVUMI_MULx() { recVUMI_MULx(VU, s_vuInfo); } +void recSVUMI_MULy() { recVUMI_MULy(VU, s_vuInfo); } +void recSVUMI_MULz() { recVUMI_MULz(VU, s_vuInfo); } +void recSVUMI_MULw() { recVUMI_MULw(VU, s_vuInfo); } + +void recSVUMI_MULA() { recVUMI_MULA(VU, s_vuInfo); } +void recSVUMI_MULAi() { recVUMI_MULAi(VU, s_vuInfo); } +void recSVUMI_MULAq() { recVUMI_MULAq(VU, s_vuInfo); } +void recSVUMI_MULAx() { recVUMI_MULAx(VU, s_vuInfo); } +void recSVUMI_MULAy() { recVUMI_MULAy(VU, s_vuInfo); } +void recSVUMI_MULAz() { recVUMI_MULAz(VU, s_vuInfo); } +void recSVUMI_MULAw() { recVUMI_MULAw(VU, s_vuInfo); } + +void recSVUMI_MADD() { recVUMI_MADD(VU, s_vuInfo); } +void recSVUMI_MADDi() { recVUMI_MADDi(VU, s_vuInfo); } +void recSVUMI_MADDq() { recVUMI_MADDq(VU, s_vuInfo); } +void recSVUMI_MADDx() { recVUMI_MADDx(VU, s_vuInfo); } +void recSVUMI_MADDy() { recVUMI_MADDy(VU, s_vuInfo); } +void recSVUMI_MADDz() { recVUMI_MADDz(VU, s_vuInfo); } +void recSVUMI_MADDw() { recVUMI_MADDw(VU, s_vuInfo); } + +void recSVUMI_MADDA() { recVUMI_MADDA(VU, s_vuInfo); } +void recSVUMI_MADDAi() { recVUMI_MADDAi(VU, s_vuInfo); } +void recSVUMI_MADDAq() { recVUMI_MADDAq(VU, s_vuInfo); } +void recSVUMI_MADDAx() { recVUMI_MADDAx(VU, s_vuInfo); } +void recSVUMI_MADDAy() { recVUMI_MADDAy(VU, s_vuInfo); } +void recSVUMI_MADDAz() { recVUMI_MADDAz(VU, s_vuInfo); } +void recSVUMI_MADDAw() { recVUMI_MADDAw(VU, s_vuInfo); } + +void recSVUMI_MSUB() { recVUMI_MSUB(VU, s_vuInfo); } +void recSVUMI_MSUBi() { recVUMI_MSUBi(VU, s_vuInfo); } +void recSVUMI_MSUBq() { recVUMI_MSUBq(VU, s_vuInfo); } +void recSVUMI_MSUBx() { recVUMI_MSUBx(VU, s_vuInfo); } +void recSVUMI_MSUBy() { recVUMI_MSUBy(VU, s_vuInfo); } +void recSVUMI_MSUBz() { recVUMI_MSUBz(VU, s_vuInfo); } +void recSVUMI_MSUBw() { recVUMI_MSUBw(VU, s_vuInfo); } + +void recSVUMI_MSUBA() { recVUMI_MSUBA(VU, s_vuInfo); } +void recSVUMI_MSUBAi() { recVUMI_MSUBAi(VU, s_vuInfo); } +void recSVUMI_MSUBAq() { recVUMI_MSUBAq(VU, s_vuInfo); } +void recSVUMI_MSUBAx() { recVUMI_MSUBAx(VU, s_vuInfo); } +void recSVUMI_MSUBAy() { recVUMI_MSUBAy(VU, s_vuInfo); } +void recSVUMI_MSUBAz() { recVUMI_MSUBAz(VU, s_vuInfo); } +void recSVUMI_MSUBAw() { recVUMI_MSUBAw(VU, s_vuInfo); } + +void recSVUMI_MAX() { recVUMI_MAX(VU, s_vuInfo); } +void recSVUMI_MAXi() { recVUMI_MAXi(VU, s_vuInfo); } +void recSVUMI_MAXx() { recVUMI_MAXx(VU, s_vuInfo); } +void recSVUMI_MAXy() { recVUMI_MAXy(VU, s_vuInfo); } +void recSVUMI_MAXz() { recVUMI_MAXz(VU, s_vuInfo); } +void recSVUMI_MAXw() { recVUMI_MAXw(VU, s_vuInfo); } + +void recSVUMI_MINI() { recVUMI_MINI(VU, s_vuInfo); } +void recSVUMI_MINIi() { recVUMI_MINIi(VU, s_vuInfo); } +void recSVUMI_MINIx() { recVUMI_MINIx(VU, s_vuInfo); } +void recSVUMI_MINIy() { recVUMI_MINIy(VU, s_vuInfo); } +void recSVUMI_MINIz() { recVUMI_MINIz(VU, s_vuInfo); } +void recSVUMI_MINIw() { recVUMI_MINIw(VU, s_vuInfo); } + +void recSVUMI_FTOI0() { recVUMI_FTOI0(VU, s_vuInfo); } +void recSVUMI_FTOI4() { recVUMI_FTOI4(VU, s_vuInfo); } +void recSVUMI_FTOI12() { recVUMI_FTOI12(VU, s_vuInfo); } +void recSVUMI_FTOI15() { recVUMI_FTOI15(VU, s_vuInfo); } +void recSVUMI_ITOF0() { recVUMI_ITOF0(VU, s_vuInfo); } +void recSVUMI_ITOF4() { recVUMI_ITOF4(VU, s_vuInfo); } +void recSVUMI_ITOF12() { recVUMI_ITOF12(VU, s_vuInfo); } +void recSVUMI_ITOF15() { recVUMI_ITOF15(VU, s_vuInfo); } + +void recSVUMI_OPMULA() { recVUMI_OPMULA(VU, s_vuInfo); } +void recSVUMI_OPMSUB() { recVUMI_OPMSUB(VU, s_vuInfo); } +void recSVUMI_NOP() { } +void recSVUMI_CLIP() { recVUMI_CLIP(VU, s_vuInfo); } + +// lower inst +void recSVUMI_MTIR() { recVUMI_MTIR(VU, s_vuInfo); } +void recSVUMI_MR32() { recVUMI_MR32(VU, s_vuInfo); } +void recSVUMI_MFIR() { recVUMI_MFIR(VU, s_vuInfo); } +void recSVUMI_MOVE() { recVUMI_MOVE(VU, s_vuInfo); } +void recSVUMI_WAITQ() { recVUMI_WAITQ(VU, s_vuInfo); } +void recSVUMI_MFP() { recVUMI_MFP(VU, s_vuInfo); } +void recSVUMI_WAITP() { recVUMI_WAITP(VU, s_vuInfo); } + +void recSVUMI_SQRT() { recVUMI_SQRT(VU, s_vuInfo); } +void recSVUMI_RSQRT() { recVUMI_RSQRT(VU, s_vuInfo); } +void recSVUMI_DIV() { recVUMI_DIV(VU, s_vuInfo); } + +void recSVUMI_ESADD() { recVUMI_ESADD(VU, s_vuInfo); } +void recSVUMI_ERSADD() { recVUMI_ERSADD(VU, s_vuInfo); } +void recSVUMI_ELENG() { recVUMI_ELENG(VU, s_vuInfo); } +void recSVUMI_ERLENG() { recVUMI_ERLENG(VU, s_vuInfo); } +void recSVUMI_EATANxy() { recVUMI_EATANxy(VU, s_vuInfo); } +void recSVUMI_EATANxz() { recVUMI_EATANxz(VU, s_vuInfo); } +void recSVUMI_ESUM() { recVUMI_ESUM(VU, s_vuInfo); } +void recSVUMI_ERCPR() { recVUMI_ERCPR(VU, s_vuInfo); } +void recSVUMI_ESQRT() { recVUMI_ESQRT(VU, s_vuInfo); } +void recSVUMI_ERSQRT() { recVUMI_ERSQRT(VU, s_vuInfo); } +void recSVUMI_ESIN() { recVUMI_ESIN(VU, s_vuInfo); } +void recSVUMI_EATAN() { recVUMI_EATAN(VU, s_vuInfo); } +void recSVUMI_EEXP() { recVUMI_EEXP(VU, s_vuInfo); } + +void recSVUMI_XITOP() { recVUMI_XITOP(VU, s_vuInfo); } +void recSVUMI_XGKICK() { recSVUMI_XGKICK(VU, s_vuInfo); } +void recSVUMI_XTOP() { recVUMI_XTOP(VU, s_vuInfo); } + +void recSVUMI_RINIT() { recVUMI_RINIT(VU, s_vuInfo); } +void recSVUMI_RGET() { recVUMI_RGET(VU, s_vuInfo); } +void recSVUMI_RNEXT() { recVUMI_RNEXT(VU, s_vuInfo); } +void recSVUMI_RXOR() { recVUMI_RXOR(VU, s_vuInfo); } + +void recSVUMI_FSAND() { recVUMI_FSAND(VU, s_vuInfo); } +void recSVUMI_FSEQ() { recVUMI_FSEQ(VU, s_vuInfo); } +void recSVUMI_FSOR() { recVUMI_FSOR(VU, s_vuInfo); } +void recSVUMI_FSSET() { recVUMI_FSSET(VU, s_vuInfo); } +void recSVUMI_FMEQ() { recVUMI_FMEQ(VU, s_vuInfo); } +void recSVUMI_FMOR() { recVUMI_FMOR(VU, s_vuInfo); } +void recSVUMI_FCEQ() { recVUMI_FCEQ(VU, s_vuInfo); } +void recSVUMI_FCOR() { recVUMI_FCOR(VU, s_vuInfo); } +void recSVUMI_FCSET() { recVUMI_FCSET(VU, s_vuInfo); } +void recSVUMI_FCGET() { recVUMI_FCGET(VU, s_vuInfo); } +void recSVUMI_FCAND() { recVUMI_FCAND(VU, s_vuInfo); } +void recSVUMI_FMAND() { recVUMI_FMAND(VU, s_vuInfo); } + +void recSVUMI_LQ() { recVUMI_LQ(VU, s_vuInfo); } +void recSVUMI_LQD() { recVUMI_LQD(VU, s_vuInfo); } +void recSVUMI_LQI() { recVUMI_LQI(VU, s_vuInfo); } +void recSVUMI_SQ() { recVUMI_SQ(VU, s_vuInfo); } +void recSVUMI_SQD() { recVUMI_SQD(VU, s_vuInfo); } +void recSVUMI_SQI() { recVUMI_SQI(VU, s_vuInfo); } +void recSVUMI_ILW() { recVUMI_ILW(VU, s_vuInfo); } +void recSVUMI_ISW() { recVUMI_ISW(VU, s_vuInfo); } +void recSVUMI_ILWR() { recVUMI_ILWR(VU, s_vuInfo); } +void recSVUMI_ISWR() { recVUMI_ISWR(VU, s_vuInfo); } + +void recSVUMI_IADD() { recVUMI_IADD(VU, s_vuInfo); } +void recSVUMI_IADDI() { recVUMI_IADDI(VU, s_vuInfo); } +void recSVUMI_IADDIU() { recVUMI_IADDIU(VU, s_vuInfo); } +void recSVUMI_IOR() { recVUMI_IOR(VU, s_vuInfo); } +void recSVUMI_ISUB() { recVUMI_ISUB(VU, s_vuInfo); } +void recSVUMI_IAND() { recVUMI_IAND(VU, s_vuInfo); } +void recSVUMI_ISUBIU() { recVUMI_ISUBIU(VU, s_vuInfo); } + +void recSVU_UPPER_FD_00( void ); +void recSVU_UPPER_FD_01( void ); +void recSVU_UPPER_FD_10( void ); +void recSVU_UPPER_FD_11( void ); +void recSVULowerOP( void ); +void recSVULowerOP_T3_00( void ); +void recSVULowerOP_T3_01( void ); +void recSVULowerOP_T3_10( void ); +void recSVULowerOP_T3_11( void ); +void recSVUunknown( void ); + +void (*recSVU_LOWER_OPCODE[128])() = { + recSVUMI_LQ , recSVUMI_SQ , recSVUunknown , recSVUunknown, + recSVUMI_ILW , recSVUMI_ISW , recSVUunknown , recSVUunknown, + recSVUMI_IADDIU, recSVUMI_ISUBIU, recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_FCEQ , recSVUMI_FCSET , recSVUMI_FCAND, recSVUMI_FCOR, /* 0x10 */ + recSVUMI_FSEQ , recSVUMI_FSSET , recSVUMI_FSAND, recSVUMI_FSOR, + recSVUMI_FMEQ , recSVUunknown , recSVUMI_FMAND, recSVUMI_FMOR, + recSVUMI_FCGET , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_B , recSVUMI_BAL , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUMI_JR , recSVUMI_JALR , recSVUunknown , recSVUunknown, + recSVUMI_IBEQ , recSVUMI_IBNE , recSVUunknown , recSVUunknown, + recSVUMI_IBLTZ , recSVUMI_IBGTZ , recSVUMI_IBLEZ, recSVUMI_IBGEZ, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x40*/ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x50 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x60 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x70 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, +}; + +void (*recSVULowerOP_T3_00_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MOVE , recSVUMI_LQI , recSVUMI_DIV , recSVUMI_MTIR, + recSVUMI_RNEXT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_MFP , recSVUMI_XTOP , recSVUMI_XGKICK, + recSVUMI_ESADD , recSVUMI_EATANxy, recSVUMI_ESQRT, recSVUMI_ESIN, +}; + +void (*recSVULowerOP_T3_01_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MR32 , recSVUMI_SQI , recSVUMI_SQRT , recSVUMI_MFIR, + recSVUMI_RGET , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUMI_XITOP, recSVUunknown, + recSVUMI_ERSADD, recSVUMI_EATANxz, recSVUMI_ERSQRT, recSVUMI_EATAN, +}; + +void (*recSVULowerOP_T3_10_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_LQD , recSVUMI_RSQRT, recSVUMI_ILWR, + recSVUMI_RINIT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ELENG , recSVUMI_ESUM , recSVUMI_ERCPR, recSVUMI_EEXP, +}; + +void (*recSVULowerOP_T3_11_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_SQD , recSVUMI_WAITQ, recSVUMI_ISWR, + recSVUMI_RXOR , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ERLENG, recSVUunknown , recSVUMI_WAITP, recSVUunknown, +}; + +void (*recSVULowerOP_OPCODE[64])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_IADD , recSVUMI_ISUB , recSVUMI_IADDI, recSVUunknown, /* 0x30 */ + recSVUMI_IAND , recSVUMI_IOR , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP_T3_00, recSVULowerOP_T3_01, recSVULowerOP_T3_10, recSVULowerOP_T3_11, +}; + +void (*recSVU_UPPER_OPCODE[64])() = { + recSVUMI_ADDx , recSVUMI_ADDy , recSVUMI_ADDz , recSVUMI_ADDw, + recSVUMI_SUBx , recSVUMI_SUBy , recSVUMI_SUBz , recSVUMI_SUBw, + recSVUMI_MADDx , recSVUMI_MADDy , recSVUMI_MADDz , recSVUMI_MADDw, + recSVUMI_MSUBx , recSVUMI_MSUBy , recSVUMI_MSUBz , recSVUMI_MSUBw, + recSVUMI_MAXx , recSVUMI_MAXy , recSVUMI_MAXz , recSVUMI_MAXw, /* 0x10 */ + recSVUMI_MINIx , recSVUMI_MINIy , recSVUMI_MINIz , recSVUMI_MINIw, + recSVUMI_MULx , recSVUMI_MULy , recSVUMI_MULz , recSVUMI_MULw, + recSVUMI_MULq , recSVUMI_MAXi , recSVUMI_MULi , recSVUMI_MINIi, + recSVUMI_ADDq , recSVUMI_MADDq , recSVUMI_ADDi , recSVUMI_MADDi, /* 0x20 */ + recSVUMI_SUBq , recSVUMI_MSUBq , recSVUMI_SUBi , recSVUMI_MSUBi, + recSVUMI_ADD , recSVUMI_MADD , recSVUMI_MUL , recSVUMI_MAX, + recSVUMI_SUB , recSVUMI_MSUB , recSVUMI_OPMSUB, recSVUMI_MINI, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVU_UPPER_FD_00, recSVU_UPPER_FD_01, recSVU_UPPER_FD_10, recSVU_UPPER_FD_11, +}; + +void (*recSVU_UPPER_FD_00_TABLE[32])() = { + recSVUMI_ADDAx, recSVUMI_SUBAx , recSVUMI_MADDAx, recSVUMI_MSUBAx, + recSVUMI_ITOF0, recSVUMI_FTOI0, recSVUMI_MULAx , recSVUMI_MULAq , + recSVUMI_ADDAq, recSVUMI_SUBAq, recSVUMI_ADDA , recSVUMI_SUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_01_TABLE[32])() = { + recSVUMI_ADDAy , recSVUMI_SUBAy , recSVUMI_MADDAy, recSVUMI_MSUBAy, + recSVUMI_ITOF4 , recSVUMI_FTOI4 , recSVUMI_MULAy , recSVUMI_ABS , + recSVUMI_MADDAq, recSVUMI_MSUBAq, recSVUMI_MADDA , recSVUMI_MSUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_10_TABLE[32])() = { + recSVUMI_ADDAz , recSVUMI_SUBAz , recSVUMI_MADDAz, recSVUMI_MSUBAz, + recSVUMI_ITOF12, recSVUMI_FTOI12, recSVUMI_MULAz , recSVUMI_MULAi , + recSVUMI_MADDAi, recSVUMI_SUBAi , recSVUMI_MULA , recSVUMI_OPMULA, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_11_TABLE[32])() = { + recSVUMI_ADDAw , recSVUMI_SUBAw , recSVUMI_MADDAw, recSVUMI_MSUBAw, + recSVUMI_ITOF15, recSVUMI_FTOI15, recSVUMI_MULAw , recSVUMI_CLIP , + recSVUMI_MADDAi, recSVUMI_MSUBAi, recSVUunknown , recSVUMI_NOP , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void recSVU_UPPER_FD_00( void ) +{ + recSVU_UPPER_FD_00_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_01( void ) +{ + recSVU_UPPER_FD_01_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_10( void ) +{ + recSVU_UPPER_FD_10_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_11( void ) +{ + recSVU_UPPER_FD_11_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP( void ) +{ + recSVULowerOP_OPCODE[ VU->code & 0x3f ]( ); +} + +void recSVULowerOP_T3_00( void ) +{ + recSVULowerOP_T3_00_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_01( void ) +{ + recSVULowerOP_T3_01_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_10( void ) +{ + recSVULowerOP_T3_10_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_11( void ) +{ + recSVULowerOP_T3_11_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVUunknown( void ) +{ + SysPrintf("Unknown SVU micromode opcode called\n"); +} + diff --git a/branches/pcsx2_0.9.2/x86/iVUzerorec.h b/branches/pcsx2_0.9.2/x86/iVUzerorec.h new file mode 100644 index 0000000..693aa96 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVUzerorec.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#ifndef VU1_SUPER_RECOMPILER +#define VU1_SUPER_RECOMPILER + +#ifdef __cplusplus +extern "C" { +#endif + +void SuperVUInit(int vuindex); // if vuindex is -1, inits the global VU resources +void SuperVUDestroy(int vuindex); // if vuindex is -1, destroys everything +void SuperVUReset(int vuindex); // if vuindex is -1, resets everything + +void SuperVUExecuteProgram(u32 startpc, int vuindex); +void SuperVUClear(u32 startpc, u32 size, int vuindex); + +u32 SuperVUGetRecTimes(int clear); + +// read = 0, will write to reg +// read = 1, will read from reg +// read = 2, addr of previously written reg (used for status and clip flags) +u32 SuperVUGetVIAddr(int reg, int read); + +// if p == 0, flush q else flush p; if wait is != 0, waits for p/q +void SuperVUFlush(int p, int wait); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/pcsx2_0.9.2/x86/iVif.S b/branches/pcsx2_0.9.2/x86/iVif.S new file mode 100644 index 0000000..e69de29 diff --git a/branches/pcsx2_0.9.2/x86/iVif.cpp b/branches/pcsx2_0.9.2/x86/iVif.cpp new file mode 100644 index 0000000..c065d6d --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/iVif.cpp @@ -0,0 +1,2142 @@ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +extern VIFregisters *_vifRegs; +extern u32* _vifMaskRegs; +extern u32* _vifRow; + +#if defined(_MSC_VER) // gcc functions can be found in iVif.S + +#include +#include + +// sse2 highly optimized vif (~200 separate functions are built) zerofrog(@gmail.com) +extern u32 g_vif1Masks[48], g_vif0Masks[48]; +extern u32 g_vif1HasMask3[4], g_vif0HasMask3[4]; + +//static const u32 writearr[4] = { 0xffffffff, 0, 0, 0 }; +//static const u32 rowarr[4] = { 0, 0xffffffff, 0, 0 }; +//static const u32 colarr[4] = { 0, 0, 0xffffffff, 0 }; +//static const u32 updatearr[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0 }; + +// arranged in writearr, rowarr, colarr, updatearr +static PCSX2_ALIGNED16(u32 s_maskarr[16][4]) = { + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff, + 0xffff0000, 0x00000000, 0x0000ffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, + 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff, + 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, + 0x00000000, 0xffff0000, 0x00000000, 0xffff0000, + 0x0000ffff, 0x00000000, 0xffff0000, 0xffffffff, + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x00000000, 0x00000000, 0x0000ffff, + 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, + 0x00000000, 0x00000000, 0x0000ffff, 0x0000ffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +u8 s_maskwrite[256]; +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask) +{ + u32 i; + u32 prev = 0; + if( !cpucaps.hasStreamingSIMD2Extensions ) return; + FreezeXMMRegs(1); + + for(i = 0; i < 4; ++i, mask >>= 8, oldmask >>= 8, vif1masks += 16) { + + prev |= s_maskwrite[mask&0xff];//((mask&3)==3)||((mask&0xc)==0xc)||((mask&0x30)==0x30)||((mask&0xc0)==0xc0); + hasmask[i] = prev; + + if( (mask&0xff) != (oldmask&0xff) ) { + __m128i r0, r1, r2, r3; + r0 = _mm_load_si128((__m128i*)&s_maskarr[mask&15][0]); + r2 = _mm_unpackhi_epi16(r0, r0); + r0 = _mm_unpacklo_epi16(r0, r0); + + r1 = _mm_load_si128((__m128i*)&s_maskarr[(mask>>4)&15][0]); + r3 = _mm_unpackhi_epi16(r1, r1); + r1 = _mm_unpacklo_epi16(r1, r1); + + _mm_storel_pi((__m64*)&vif1masks[0], *(__m128*)&r0); + _mm_storel_pi((__m64*)&vif1masks[2], *(__m128*)&r1); + _mm_storeh_pi((__m64*)&vif1masks[4], *(__m128*)&r0); + _mm_storeh_pi((__m64*)&vif1masks[6], *(__m128*)&r1); + + _mm_storel_pi((__m64*)&vif1masks[8], *(__m128*)&r2); + _mm_storel_pi((__m64*)&vif1masks[10], *(__m128*)&r3); + _mm_storeh_pi((__m64*)&vif1masks[12], *(__m128*)&r2); + _mm_storeh_pi((__m64*)&vif1masks[14], *(__m128*)&r3); + } + } +} + +// msvc++ +#define VIF_SRC ecx +#define VIF_INC edx +#define VIF_DST edi + +// writing masks +#define UNPACK_Write0_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST+(DEST_OFFSET)], r0 \ +} \ + +#define UNPACK_Write1_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Write0_Mask UNPACK_Write0_Regular +#define UNPACK_Write1_Mask UNPACK_Write1_Regular + +#define UNPACK_Write0_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + /* masked write (dest needs to be in edi) */ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL) + 48] \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, 16 \ +} \ + +#define UNPACK_Write1_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ +{ \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0) + 48] \ + /* masked write (dest needs to be in edi) */ \ + /*__asm maskmovdqu r0, XMM_WRITEMASK*/ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pandn XMM_WRITEMASK, qword ptr [VIF_DST] \ + __asm por r0, XMM_WRITEMASK \ + __asm MOVDQA qword ptr [VIF_DST], r0 \ + __asm add VIF_DST, VIF_INC \ +} \ + +#define UNPACK_Mask_SSE_0(r0) \ +{ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ +} \ + +// once a qword is uncomprssed, applies masks and saves +// note: modifying XMM_WRITEMASK +#define UNPACK_Mask_SSE_1(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm por r0, XMM_ROWCOLMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_Mask_SSE_2(r0) \ +{ \ + /* dest = row + write (only when mask=0), otherwise write \ + row = row + write (only when mask = 0), otherwise row */ \ + __asm pand r0, XMM_WRITEMASK \ + __asm pand XMM_WRITEMASK, XMM_ROW \ + __asm paddd XMM_ROW, r0 \ + __asm por r0, XMM_ROWCOLMASK \ + __asm paddd r0, XMM_WRITEMASK \ +} \ + +#define UNPACK_WriteMask_SSE_0 UNPACK_Mask_SSE_0 +#define UNPACK_WriteMask_SSE_1 UNPACK_Mask_SSE_1 +#define UNPACK_WriteMask_SSE_2 UNPACK_Mask_SSE_2 + +#define UNPACK_Regular_SSE_0(r0) + +#define UNPACK_Regular_SSE_1(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ +} \ + +#define UNPACK_Regular_SSE_2(r0) \ +{ \ + __asm paddd r0, XMM_ROW \ + __asm movdqa XMM_ROW, r0 \ +} \ + +// setting up masks +#define UNPACK_Setup_Mask_SSE(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(CL)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_0(CL) UNPACK_Setup_Mask_SSE(CL); +#define UNPACK_Start_Setup_Mask_SSE_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(CL) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(CL) + 32] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Setup_Mask_SSE_0_1(CL) +#define UNPACK_Setup_Mask_SSE_1_1(CL) \ +{ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ +} \ + +#define UNPACK_Setup_Mask_SSE_2_1(CL) { \ + /* ignore CL, since vif.cycle.wl == 1 */ \ + __asm mov eax, _vifMaskRegs \ + __asm movdqa XMM_ROWMASK, qword ptr [eax + 64*(0) + 16] \ + __asm movdqa XMM_ROWCOLMASK, qword ptr [eax + 64*(0) + 32] \ + __asm movdqa XMM_WRITEMASK, qword ptr [eax + 64*(0)] \ + __asm pand XMM_ROWMASK, XMM_ROW \ + __asm pand XMM_ROWCOLMASK, XMM_COL \ + __asm por XMM_ROWCOLMASK, XMM_ROWMASK \ +} \ + +#define UNPACK_Setup_Mask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) + +// write mask always destroys XMM_WRITEMASK, so 0_0 = 1_0 +#define UNPACK_Setup_WriteMask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_0_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_1_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_2_1(CL) UNPACK_Setup_Mask_SSE_2_1(CL) + +#define UNPACK_Start_Setup_WriteMask_SSE_0(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_1(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_2(CL) UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Start_Setup_Regular_SSE_0(CL) +#define UNPACK_Start_Setup_Regular_SSE_1(CL) +#define UNPACK_Start_Setup_Regular_SSE_2(CL) +#define UNPACK_Setup_Regular_SSE_0_0(CL) +#define UNPACK_Setup_Regular_SSE_1_0(CL) +#define UNPACK_Setup_Regular_SSE_2_0(CL) +#define UNPACK_Setup_Regular_SSE_0_1(CL) +#define UNPACK_Setup_Regular_SSE_1_1(CL) +#define UNPACK_Setup_Regular_SSE_2_1(CL) + +#define UNPACK_INC_DST_0_Regular(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Regular(qw) +#define UNPACK_INC_DST_0_Mask(qw) __asm add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Mask(qw) +#define UNPACK_INC_DST_0_WriteMask(qw) +#define UNPACK_INC_DST_1_WriteMask(qw) + +// unpacks for 1,2,3,4 elements (V3 uses this directly) +#define UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ +} \ + +// V3 uses this directly +#define UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ +} \ + +#define UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(2) \ +} \ + +#define UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType) { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(1) \ +} \ + +// S-32 +// only when cl==1 +#define UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R3, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_S_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_S_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_S_32SSE_2A UNPACK_S_32SSE_2 + +#define UNPACK_S_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_32SSE_1A UNPACK_S_32SSE_1 + +// S-16 +#define UNPACK_S_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R3, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_S_16SSE_4A UNPACK_S_16SSE_4 + +#define UNPACK_S_16SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R2, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_S_16SSE_3A UNPACK_S_16SSE_3 + +#define UNPACK_S_16SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_S_16SSE_2A UNPACK_S_16SSE_2 + +#define UNPACK_S_16SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_16SSE_1A UNPACK_S_16SSE_1 + +// S-8 +#define UNPACK_S_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R3, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + \ + __asm pshufd XMM_R0, XMM_R3, 0 \ + __asm pshufd XMM_R1, XMM_R3, 0x55 \ + __asm pshufd XMM_R2, XMM_R3, 0xaa \ + __asm pshufd XMM_R3, XMM_R3, 0xff \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} + +#define UNPACK_S_8SSE_4A UNPACK_S_8SSE_4 + +#define UNPACK_S_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R2, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm pshufd XMM_R0, XMM_R2, 0 \ + __asm pshufd XMM_R1, XMM_R2, 0x55 \ + __asm pshufd XMM_R2, XMM_R2, 0xaa \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_S_8SSE_3A UNPACK_S_8SSE_3 + +#define UNPACK_S_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R1, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + \ + __asm pshufd XMM_R0, XMM_R1, 0 \ + __asm pshufd XMM_R1, XMM_R1, 0x55 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_S_8SSE_2A UNPACK_S_8SSE_2 + +#define UNPACK_S_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm pshufd XMM_R0, XMM_R0, 0 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm inc VIF_SRC \ + } \ +} \ + +#define UNPACK_S_8SSE_1A UNPACK_S_8SSE_1 + +// V2-32 +#define UNPACK_V2_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm MOVDQA XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+24] \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V2_32SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V2_32SSE_2A UNPACK_V2_32SSE_2 + +#define UNPACK_V2_32SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_32SSE_1A UNPACK_V2_32SSE_1 + +// V2-16 +#define UNPACK_V2_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V2_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, dword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V2-8 +#define UNPACK_V2_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + __asm pshufd XMM_R3, XMM_R2, 0xee \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V2_8SSE_4A UNPACK_V2_8SSE_4 + +#define UNPACK_V2_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpckhwd XMM_R2, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V2_8SSE_3A UNPACK_V2_8SSE_3 + +#define UNPACK_V2_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + \ + /* move the lower 64 bits down*/ \ + __asm pshufd XMM_R1, XMM_R0, 0xee \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V2_8SSE_2A UNPACK_V2_8SSE_2 + +#define UNPACK_V2_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V2_8SSE_1A UNPACK_V2_8SSE_1 + +// V3-32 +#define UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) { \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + /* midnight club 2 crashes because reading a qw at +36 is out of bounds */ \ + __asm MOVDQA XMM_R3, qword ptr [VIF_SRC+32] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + __asm psrldq XMM_R3, 4 \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) \ + } \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V3_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + } \ + { \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+24] \ + } \ + { \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3) \ + } \ + { \ + __asm add VIF_SRC, 36 \ + } \ +} \ + +#define UNPACK_V3_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+12] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V3_32SSE_2A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_2(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ +{ \ + { \ + __asm MOVDQA XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_32SSE_1A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_1(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqu) + +// V3-16 +#define UNPACK_V3_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm movq XMM_R3, qword ptr [VIF_SRC+18] \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} + +#define UNPACK_V3_16SSE_4A UNPACK_V3_16SSE_4 + +#define UNPACK_V3_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm movq XMM_R2, qword ptr [VIF_SRC+12] \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 18 \ + } \ +} \ + +#define UNPACK_V3_16SSE_3A UNPACK_V3_16SSE_3 + +#define UNPACK_V3_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V3_16SSE_2A UNPACK_V3_16SSE_2 + +#define UNPACK_V3_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_16SSE_1A UNPACK_V3_16SSE_1 + +// V3-8 +#define UNPACK_V3_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R1, qword ptr [VIF_SRC] \ + __asm movq XMM_R3, qword ptr [VIF_SRC+6] \ + \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklbw XMM_R3, XMM_R3 \ + __asm punpcklwd XMM_R0, XMM_R1 \ + __asm psrldq XMM_R1, 6 \ + __asm punpcklwd XMM_R2, XMM_R3 \ + __asm psrldq XMM_R3, 6 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm punpcklwd XMM_R3, XMM_R3 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} + +#define UNPACK_V3_8SSE_4A UNPACK_V3_8SSE_4 + +#define UNPACK_V3_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, word ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm movd XMM_R2, dword ptr [VIF_SRC+6] \ + __asm punpcklbw XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpcklwd XMM_R1, XMM_R1 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 9 \ + } \ +} \ + +#define UNPACK_V3_8SSE_3A UNPACK_V3_8SSE_3 + +#define UNPACK_V3_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm movd XMM_R1, dword ptr [VIF_SRC+3] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R1, XMM_R1 \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V3_8SSE_2A UNPACK_V3_8SSE_2 + +#define UNPACK_V3_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 3 \ + } \ +} \ + +#define UNPACK_V3_8SSE_1A UNPACK_V3_8SSE_1 + +// V4-32 +#define UNPACK_V4_32SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqa XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + __asm movdqu XMM_R3, qword ptr [VIF_SRC+48] \ + } \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 64 \ + } \ +} + +#define UNPACK_V4_32SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqa XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+32] \ + } \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 48 \ + } \ +} + +#define UNPACK_V4_32SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqa XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R1, qword ptr [VIF_SRC+16] \ + } \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_32SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqa XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + } \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +// V4-16 +#define UNPACK_V4_16SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + __asm punpckhwd XMM_R3, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movdqu XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 32 \ + } \ +} + +#define UNPACK_V4_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R2, qword ptr [VIF_SRC+16] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 16 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 24 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhwd XMM_R1, qword ptr [VIF_SRC] \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movq XMM_R1, qword ptr [VIF_SRC+8] \ + \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R1, XMM_R1 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 16 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm punpcklwd XMM_R0, qword ptr [VIF_SRC] \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ +{ \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 16 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +// V4-8 +#define UNPACK_V4_8SSE_4A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movdqu XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R3, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 16 \ + } \ +} + +#define UNPACK_V4_8SSE_3A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpckhbw XMM_R2, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + __asm movd XMM_R2, dword ptr [VIF_SRC+8] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklbw XMM_R2, XMM_R2 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 12 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movq XMM_R0, qword ptr [VIF_SRC] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm UNPACK_RIGHTSHIFT XMM_R1, 24 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1A(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm punpcklbw XMM_R0, qword ptr [VIF_SRC] \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_8SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm movd XMM_R0, dword ptr [VIF_SRC] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm UNPACK_RIGHTSHIFT XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +// V4-5 +static PCSX2_ALIGNED16(u32 s_TempDecompress[4]) = {0}; + +#define DECOMPRESS_RGBA(OFFSET) { \ + /* R */ \ + __asm mov bl, al \ + __asm shl bl, 3 \ + __asm mov byte ptr [s_TempDecompress+OFFSET], bl \ + /* G */ \ + __asm mov bx, ax \ + __asm shr bx, 2 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+1], bl \ + /* B */ \ + __asm mov bx, ax \ + __asm shr bx, 7 \ + __asm and bx, 0xf8 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+2], bl \ + __asm mov bx, ax \ + __asm shr bx, 8 \ + __asm and bx, 0x80 \ + __asm mov byte ptr [s_TempDecompress+OFFSET+3], bl \ +} \ + +#define UNPACK_V4_5SSE_4(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm mov ax, word ptr [VIF_SRC+6] \ + } \ + DECOMPRESS_RGBA(12); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R3, XMM_R2 \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + __asm psrld XMM_R3, 24 \ + } \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 8 \ + } \ +} + +#define UNPACK_V4_5SSE_4A UNPACK_V4_5SSE_4 + +#define UNPACK_V4_5SSE_3(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm mov ax, word ptr [VIF_SRC+4] \ + } \ + DECOMPRESS_RGBA(8); \ + { \ + __asm movdqa XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpckhbw XMM_R2, XMM_R0 \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R2, XMM_R2 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + __asm psrld XMM_R2, 24 \ + } \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 6 \ + } \ +} \ + +#define UNPACK_V4_5SSE_3A UNPACK_V4_5SSE_3 + +#define UNPACK_V4_5SSE_2(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov eax, dword ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm shr eax, 16 \ + } \ + DECOMPRESS_RGBA(4); \ + { \ + __asm movq XMM_R0, qword ptr [s_TempDecompress] \ + \ + __asm punpcklbw XMM_R0, XMM_R0 \ + \ + __asm punpckhwd XMM_R1, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + __asm psrld XMM_R1, 24 \ + } \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 4 \ + } \ +} \ + +#define UNPACK_V4_5SSE_2A UNPACK_V4_5SSE_2 + +#define UNPACK_V4_5SSE_1(CL, TOTALCL, MaskType, ModeType) { \ + { \ + __asm mov ax, word ptr [VIF_SRC] \ + } \ + DECOMPRESS_RGBA(0); \ + { \ + __asm movd XMM_R0, dword ptr [s_TempDecompress] \ + __asm punpcklbw XMM_R0, XMM_R0 \ + __asm punpcklwd XMM_R0, XMM_R0 \ + \ + __asm psrld XMM_R0, 24 \ + } \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + { \ + __asm add VIF_SRC, 2 \ + } \ +} \ + +#define UNPACK_V4_5SSE_1A UNPACK_V4_5SSE_1 + +#pragma warning(disable:4731) + +//#ifdef _DEBUG +#define PUSHESI __asm mov s_saveesi, esi +#define POPESI __asm mov esi, s_saveesi +//#else +//#define PUSHESI +//#define POPESI +//#endif + +#define PUSHEDI +#define POPEDI +#define PUSHEBP //__asm mov dword ptr [esp-4], ebp +#define POPEBP //__asm mov ebp, dword ptr [esp-4] + +//__asm mov eax, pr0 \ +///* load row */ \ +//__asm movss XMM_ROW, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_ROW, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_ROW, XMM_R0 \ +//\ +//__asm mov eax, pc0 \ +//__asm movss XMM_R3, dword ptr [eax] \ +//__asm movss XMM_R1, dword ptr [eax+4] \ +//__asm punpckldq XMM_R3, XMM_R1 \ +//__asm movss XMM_R0, dword ptr [eax+8] \ +//__asm movss XMM_R1, dword ptr [eax+12] \ +//__asm punpckldq XMM_R0, XMM_R1 \ +//__asm punpcklqdq XMM_R3, XMM_R0 \ + +#define SAVE_ROW_REG_BASE { \ + { \ + /* save the row reg */ \ + __asm mov eax, _vifRow \ + __asm movdqa qword ptr [eax], XMM_ROW \ + __asm mov eax, _vifRegs \ + __asm movss dword ptr [eax+0x100], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x110], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x120], XMM_ROW \ + __asm psrldq XMM_ROW, 4 \ + __asm movss dword ptr [eax+0x130], XMM_ROW \ + } \ +} \ + +#define SAVE_NO_REG + +extern int g_nCounters[4]; + +static int tempcl = 0, incdest; +static int s_saveesi, s_saveinc; + +// qsize - bytes of compressed size of 1 decompressed qword +#define defUNPACK_SkippingWrite(name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG) \ +int UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType##(u32* dest, u32* data, int dmasize) \ +{ \ + incdest = ((_vifRegs->cycle.cl - _vifRegs->cycle.wl)<<4); \ + \ + switch( _vifRegs->cycle.wl ) { \ + case 1: \ + { \ + /*__asm inc dword ptr [g_nCounters] \ + __asm mov eax, dmasize \ + __asm add dword ptr [g_nCounters+4], eax*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov esi, dmasize \ + } \ + UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ + { \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm mov VIF_INC, incdest \ + __asm add VIF_INC, 16 \ + } \ + \ + /* first align VIF_SRC to 16 bytes */ \ +C1_Align16: \ + { \ + __asm test VIF_SRC, 15 \ + __asm jz C1_UnpackAligned \ + } \ + UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_DoneWithDec \ + __asm sub esi, qsize \ + __asm jmp C1_Align16 \ + } \ +C1_UnpackAligned: \ + { \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + __asm cmp esi, (4*qsize) \ + __asm jl C1_Unpack3 \ + __asm prefetchnta [eax + 192] \ + } \ +C1_Unpack4: \ + UNPACK_##name##SSE_4A(0, 1, MaskType, ModeType); \ + { \ + __asm cmp esi, (8*qsize) \ + __asm jl C1_DoneUnpack4 \ + __asm sub esi, (4*qsize) \ + __asm jmp C1_Unpack4 \ + } \ +C1_DoneUnpack4: \ + { \ + __asm sub esi, (4*qsize) \ + __asm cmp esi, qsize \ + __asm jl C1_Done3 \ + __asm cmp esi, (2*qsize) \ + __asm jl C1_Unpack1 \ + __asm cmp esi, (3*qsize) \ + __asm jl C1_Unpack2 \ + /* fall through */ \ + } \ +C1_Unpack3: \ + UNPACK_##name##SSE_3A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack2: \ + UNPACK_##name##SSE_2A(0, 1, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C1_Done3 \ + } \ +C1_Unpack1: \ + UNPACK_##name##SSE_1A(0, 1, MaskType, ModeType); \ +C1_DoneWithDec: \ + { \ + __asm sub esi, qsize \ + } \ +C1_Done3: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + case 2: \ + { \ + /*__asm inc dword ptr [g_nCounters+4]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (2*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C2_Done3 \ + } \ +C2_Unpack: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (4*qsize) \ + __asm jl C2_Done2 \ + __asm sub esi, (2*qsize) \ + __asm jmp C2_Unpack /* unpack next */ \ + } \ +C2_Done2: \ + { \ + __asm sub esi, (2*qsize) \ + } \ +C2_Done3: \ + { \ + __asm cmp esi, qsize \ + __asm jl C2_Done4 \ + } \ + /* execute left over qw */ \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + } \ +C2_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + case 3: \ + { \ + /*__asm inc dword ptr [g_nCounters+8]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, incdest \ + __asm mov esi, dmasize \ + __asm cmp esi, (3*qsize) \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + __asm jl C3_Done5 \ + } \ +C3_Unpack: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + \ + { \ + __asm add VIF_DST, VIF_INC /* take into account wl */ \ + __asm cmp esi, (6*qsize) \ + __asm jl C3_Done2 \ + __asm sub esi, (3*qsize) \ + __asm jmp C3_Unpack /* unpack next */ \ + } \ +C3_Done2: \ + { \ + __asm sub esi, (3*qsize) \ + } \ +C3_Done5: \ + { \ + __asm cmp esi, qsize \ + __asm jl C3_Done4 \ + /* execute left over qw */ \ + __asm cmp esi, (2*qsize) \ + __asm jl C3_Done3 \ + } \ + \ + /* process 2 qws */ \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C3_Done4 \ + } \ + \ +C3_Done3: \ + /* process 1 qw */ \ + { \ + __asm sub esi, qsize \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ +C3_Done4: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + \ + default: /* >= 4 */ \ + tempcl = _vifRegs->cycle.wl-3; \ + { \ + /*__asm inc dword ptr [g_nCounters+12]*/ \ + PUSHESI \ + PUSHEDI \ + __asm mov VIF_INC, tempcl \ + __asm mov s_saveinc, VIF_INC \ + __asm mov esi, dmasize \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + /* move source and dest */ \ + __asm mov VIF_DST, dest \ + __asm mov VIF_SRC, data \ + } \ +C4_Unpack: \ + { \ + __asm cmp esi, (3*qsize) \ + __asm jge C4_Unpack3 \ + __asm cmp esi, (2*qsize) \ + __asm jge C4_Unpack2 \ + } \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, qsize \ + __asm jmp C4_Done \ + } \ +C4_Unpack2: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + /* not enough data left */ \ + { \ + __asm sub esi, (2*qsize) \ + __asm jmp C4_Done \ + } \ +C4_Unpack3: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + { \ + __asm sub esi, (3*qsize) \ + /* more data left, process 1qw at a time */ \ + __asm mov VIF_INC, s_saveinc \ + } \ +C4_UnpackX: \ + { \ + /* check if any data left */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + \ + } \ + UNPACK_##name##SSE_1(3, 0, MaskType, ModeType); \ + { \ + __asm sub esi, qsize \ + __asm cmp VIF_INC, 1 \ + __asm je C4_DoneLoop \ + __asm sub VIF_INC, 1 \ + __asm jmp C4_UnpackX \ + } \ +C4_DoneLoop: \ + { \ + __asm add VIF_DST, incdest /* take into account wl */ \ + __asm cmp esi, qsize \ + __asm jl C4_Done \ + __asm jmp C4_Unpack /* unpack next */ \ + } \ +C4_Done: \ + { \ + POPEDI \ + __asm mov dmasize, esi \ + POPESI \ + } \ + SAVE_ROW_REG; \ + return dmasize; \ + } \ + \ + return dmasize; \ +} \ + +//{ \ +// /*__asm inc dword ptr [g_nCounters] \ +// __asm mov eax, dmasize \ +// __asm add dword ptr [g_nCounters+4], eax*/ \ +// PUSHESI \ +// PUSHEDI \ +// __asm mov esi, dmasize \ +// } \ +// UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ +// { \ +// __asm cmp esi, qsize \ +// __asm jl C1_Done3 \ +// \ +// /* move source and dest */ \ +// __asm mov VIF_DST, dest \ +// __asm mov VIF_SRC, data \ +// __asm mov VIF_INC, incdest \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// __asm cmp esi, (3*qsize) \ +// __asm jl C1_Unpack2 \ +// __asm imul VIF_INC, 3 \ +// __asm prefetchnta [eax + 192] \ +// } \ +//C1_Unpack3: \ +// UNPACK_##name##SSE_3(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm cmp esi, (6*qsize) \ +// __asm jl C1_DoneUnpack3 \ +// __asm sub esi, (3*qsize) \ +// __asm jmp C1_Unpack3 \ +// } \ +//C1_DoneUnpack3: \ +// { \ +// __asm sub esi, (3*qsize) \ +// __asm mov VIF_INC, dword ptr [esp] /* restore old ptr */ \ +// __asm cmp esi, (2*qsize) \ +// __asm jl C1_Unpack1 \ +// /* fall through */ \ +// } \ +//C1_Unpack2: \ +// UNPACK_##name##SSE_2(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC \ +// __asm add VIF_DST, VIF_INC \ +// __asm sub esi, (2*qsize) \ +// __asm jmp C1_Done3 \ +// } \ +//C1_Unpack1: \ +// UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ +// { \ +// __asm add VIF_DST, VIF_INC /* take into account wl */ \ +// __asm sub esi, qsize \ +// } \ +//C1_Done3: \ +// { \ +// POPEDI \ +// __asm mov dmasize, esi \ +// POPESI \ +// } \ +// SAVE_ROW_REG; \ + +//while(size >= qsize) { +// funcP( dest, (u32*)cdata, chans); +// cdata += ft->qsize; +// size -= ft->qsize; +// +// if (vif->cl >= wl) { +// dest += incdest; +// vif->cl = 0; +// } +// else { +// dest += 4; +// vif->cl++; +// } +//} + +#define UNPACK_RIGHTSHIFT psrld +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, u, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, u, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_32, 4); +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_32, 8); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_32, 12); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_32, 16); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); +defUNPACK_SkippingWrite2(V4_5, 2); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#define UNPACK_RIGHTSHIFT psrad +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, s, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, s, SAVE_NO_REG); \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE); \ + +defUNPACK_SkippingWrite2(S_16, 2); +defUNPACK_SkippingWrite2(S_8, 1); +defUNPACK_SkippingWrite2(V2_16, 4); +defUNPACK_SkippingWrite2(V2_8, 2); +defUNPACK_SkippingWrite2(V3_16, 6); +defUNPACK_SkippingWrite2(V3_8, 3); +defUNPACK_SkippingWrite2(V4_16, 8); +defUNPACK_SkippingWrite2(V4_8, 4); + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/branches/pcsx2_0.9.2/x86/ir5900tables.c b/branches/pcsx2_0.9.2/x86/ir5900tables.c new file mode 100644 index 0000000..14756f1 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ir5900tables.c @@ -0,0 +1,1369 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Holds instruction tables for the r5900 recompiler + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" + +//////////////////////////////////////////////////// +static void recNULL( void ) +{ + SysPrintf("EE: Unimplemented op %x\n", cpuRegs.code); +} + +//////////////////////////////////////////////////// +static void recREGIMM( void ) +{ + recREG[ _Rt_ ]( ); +} + +//////////////////////////////////////////////////// +static void recSPECIAL( void ) +{ + recSPC[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0( void ) +{ + recCP0[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0BC0( void ) +{ + recCP0BC0[ ( cpuRegs.code >> 16 ) & 0x03 ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0C0( void ) +{ + recCP0C0[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP1( void ) { + recCP1[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recMMI( void ) +{ + recMMIt[ _Funct_ ]( ); +} + + +/********************************************************** +* UNHANDLED YET OPCODES +* +**********************************************************/ + +//////////////////////////////////////////////////// +//REC_SYS(PREF); +//////////////////////////////////////////////////// +//REC_SYS(MFSA); +//////////////////////////////////////////////////// +//REC_SYS(MTSA); +//////////////////////////////////////////////////// +REC_SYS(TGE); +//////////////////////////////////////////////////// +REC_SYS(TGEU); +//////////////////////////////////////////////////// +REC_SYS(TLT); +//////////////////////////////////////////////////// +REC_SYS(TLTU); +//////////////////////////////////////////////////// +REC_SYS(TEQ); +//////////////////////////////////////////////////// +REC_SYS(TNE); +//////////////////////////////////////////////////// +REC_SYS(TGEI); +//////////////////////////////////////////////////// +REC_SYS(TGEIU); +//////////////////////////////////////////////////// +REC_SYS(TLTI); +//////////////////////////////////////////////////// +REC_SYS(TLTIU); +//////////////////////////////////////////////////// +REC_SYS(TEQI); +//////////////////////////////////////////////////// +REC_SYS(TNEI); +//////////////////////////////////////////////////// +//REC_SYS(MTSAB); +//////////////////////////////////////////////////// +//REC_SYS(MTSAH); +//////////////////////////////////////////////////// +REC_SYS(CACHE); + +//////////////////////////////////////////////////// +//static void recCACHE( void ) { +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (u32)CACHE ); +// //branch = 2; +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// RET(); +// x86SetJ8(j8Ptr[0]); +//} + + +static void recPREF( void ) +{ +} + + + +//////////////////////////////////////////////////// +static void recSYNC( void ) +{ +} + +static void recMFSA( void ) +{ + int mmreg; + if (!_Rd_) return; + + mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + if( mmreg >= 0 ) { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.sa); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.sa); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + _deleteEEreg(_Rd_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + } +} + +static void recMTSA( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + } + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.sa, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&cpuRegs.sa, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } + } +} + +/* +void recTGE( void ) +{ +} + +void recTGEU( void ) +{ +} + +void recTLT( void ) +{ +} + +void recTLTU( void ) +{ +} + +void recTEQ( void ) +{ +} + +void recTNE( void ) +{ +} + +void recTGEI( void ) +{ +} + +void recTGEIU( void ) +{ +} + +void recTLTI( void ) +{ +} + +void recTLTIU( void ) +{ +} + +void recTEQI( void ) +{ +} + +void recTNEI( void ) +{ +} + +*/ +static void recMTSAB( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0xF); + XOR32ItoR(EAX, _Imm_&0xf); + SHL32ItoR(EAX, 3); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +static void recMTSAH( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0x7); + XOR32RtoR(EAX, _Imm_&0x7); + SHL32ItoR(EAX, 4); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +///////////////////////////////// +// Foward-Prob Function Tables // +///////////////////////////////// +extern void recCOP2( void ); +extern void recSYSCALL( void ); +extern void recBREAK( void ); + +void (*recBSC[64] )() = { + recSPECIAL, recREGIMM, recJ, recJAL, recBEQ, recBNE, recBLEZ, recBGTZ, + recADDI, recADDIU, recSLTI, recSLTIU, recANDI, recORI, recXORI, recLUI, + recCOP0, recCOP1, recCOP2, recNULL, recBEQL, recBNEL, recBLEZL, recBGTZL, + recDADDI, recDADDIU, recLDL, recLDR, recMMI, recNULL, recLQ, recSQ, + recLB, recLH, recLWL, recLW, recLBU, recLHU, recLWR, recLWU, + recSB, recSH, recSWL, recSW, recSDL, recSDR, recSWR, recCACHE, + recNULL, recLWC1, recNULL, recPREF, recNULL, recNULL, recLQC2, recLD, + recNULL, recSWC1, recNULL, recNULL, recNULL, recNULL, recSQC2, recSD +}; + +#ifdef WIN32_VIRTUAL_MEM +// coissued insts +void (*recBSC_co[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recLDL_co, recLDR_co, recNULL, recNULL, recLQ_co, recSQ_co, + recLB_co, recLH_co, recLWL_co, recLW_co, recLBU_co, recLHU_co, recLWR_co, recLWU_co, + recSB_co, recSH_co, recSWL_co, recSW_co, recSDL_co, recSDR_co, recSWR_co, recNULL, + recNULL, recLWC1_co, recNULL, recNULL, recNULL, recNULL, recLQC2_co, recLD_co, + recNULL, recSWC1_co, recNULL, recNULL, recNULL, recNULL, recSQC2_co, recSD_co +}; +#endif + +void (*recSPC[64] )() = { + recSLL, recNULL, recSRL, recSRA, recSLLV, recNULL, recSRLV, recSRAV, + recJR, recJALR, recMOVZ, recMOVN, recSYSCALL, recBREAK, recNULL, recSYNC, + recMFHI, recMTHI, recMFLO, recMTLO, recDSLLV, recNULL, recDSRLV, recDSRAV, + recMULT, recMULTU, recDIV, recDIVU, recNULL, recNULL, recNULL, recNULL, + recADD, recADDU, recSUB, recSUBU, recAND, recOR, recXOR, recNOR, + recMFSA, recMTSA, recSLT, recSLTU, recDADD, recDADDU, recDSUB, recDSUBU, + recTGE, recTGEU, recTLT, recTLTU, recTEQ, recNULL, recTNE, recNULL, + recDSLL, recNULL, recDSRL, recDSRA, recDSLL32, recNULL, recDSRL32, recDSRA32 +}; + +void (*recREG[32] )() = { + recBLTZ, recBGEZ, recBLTZL, recBGEZL, recNULL, recNULL, recNULL, recNULL, + recTGEI, recTGEIU, recTLTI, recTLTIU, recTEQI, recNULL, recTNEI, recNULL, + recBLTZAL, recBGEZAL, recBLTZALL, recBGEZALL, recNULL, recNULL, recNULL, recNULL, + recMTSAB, recMTSAH, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0[32] )() = { + recMFC0, recNULL, recNULL, recNULL, recMTC0, recNULL, recNULL, recNULL, + recCOP0BC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP0C0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0BC0[32] )() = { + recBC0F, recBC0T, recBC0FL, recBC0TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0C0[64] )() = { + recNULL, recTLBR, recTLBWI, recNULL, recNULL, recNULL, recTLBWR, recNULL, + recTLBP, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recERET, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recEI, recDI, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1[32] )() = { + recMFC1, recNULL, recCFC1, recNULL, recMTC1, recNULL, recCTC1, recNULL, + recCOP1_BC1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP1_S, recNULL, recNULL, recNULL, recCOP1_W, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1BC1[32] )() = { + recBC1F, recBC1T, recBC1FL, recBC1TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1S[64] )() = { + recADD_S, recSUB_S, recMUL_S, recDIV_S, recSQRT_S, recABS_S, recMOV_S, recNEG_S, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recRSQRT_S, recNULL, + recADDA_S, recSUBA_S, recMULA_S, recNULL, recMADD_S, recMSUB_S, recMADDA_S, recMSUBA_S, + recNULL, recNULL, recNULL, recNULL, recCVT_W, recNULL, recNULL, recNULL, + recMAX_S, recMIN_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recC_F, recNULL, recC_EQ, recNULL, recC_LT, recNULL, recC_LE, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1W[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCVT_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMIt[64] )() = { + recMADD, recMADDU, recNULL, recNULL, recPLZCW, recNULL, recNULL, recNULL, + recMMI0, recMMI2, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMFHI1, recMTHI1, recMFLO1, recMTLO1, recNULL, recNULL, recNULL, recNULL, + recMULT1, recMULTU1, recDIV1, recDIVU1, recNULL, recNULL, recNULL, recNULL, + recMADD1, recMADDU1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMMI1 , recMMI3, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recPMFHL, recPMTHL, recNULL, recNULL, recPSLLH, recNULL, recPSRLH, recPSRAH, + recNULL, recNULL, recNULL, recNULL, recPSLLW, recNULL, recPSRLW, recPSRAW, +}; + +void (*recMMI0t[32] )() = { + recPADDW, recPSUBW, recPCGTW, recPMAXW, + recPADDH, recPSUBH, recPCGTH, recPMAXH, + recPADDB, recPSUBB, recPCGTB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDSW, recPSUBSW, recPEXTLW, recPPACW, + recPADDSH, recPSUBSH, recPEXTLH, recPPACH, + recPADDSB, recPSUBSB, recPEXTLB, recPPACB, + recNULL, recNULL, recPEXT5, recPPAC5, +}; + +void (*recMMI1t[32] )() = { + recNULL, recPABSW, recPCEQW, recPMINW, + recPADSBH, recPABSH, recPCEQH, recPMINH, + recNULL, recNULL, recPCEQB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDUW, recPSUBUW, recPEXTUW, recNULL, + recPADDUH, recPSUBUH, recPEXTUH, recNULL, + recPADDUB, recPSUBUB, recPEXTUB, recQFSRV, + recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMI2t[32] )() = { + recPMADDW, recNULL, recPSLLVW, recPSRLVW, + recPMSUBW, recNULL, recNULL, recNULL, + recPMFHI, recPMFLO, recPINTH, recNULL, + recPMULTW, recPDIVW, recPCPYLD, recNULL, + recPMADDH, recPHMADH, recPAND, recPXOR, + recPMSUBH, recPHMSBH, recNULL, recNULL, + recNULL, recNULL, recPEXEH, recPREVH, + recPMULTH, recPDIVBW, recPEXEW, recPROT3W, +}; + +void (*recMMI3t[32] )() = { + recPMADDUW, recNULL, recNULL, recPSRAVW, + recNULL, recNULL, recNULL, recNULL, + recPMTHI, recPMTLO, recPINTEH, recNULL, + recPMULTUW, recPDIVUW, recPCPYUD, recNULL, + recNULL, recNULL, recPOR, recPNOR, + recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recPEXCH, recPCPYH, + recNULL, recNULL, recPEXCW, recNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpropSetRead(reg, mask) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpropSetWrite0(reg, mask, live) { \ + prev->regs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +#define rpropSetWrite(reg, mask) { \ + rpropSetWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +#define rpropSetFast(write1, read1, read2, mask) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ +} \ + +#define rpropSetLOHI(write1, read1, read2, mask, lo, hi) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( (lo) & MODE_WRITE ) { rpropSetWrite(XMMGPR_LO, mask); } \ + if( (hi) & MODE_WRITE ) { rpropSetWrite(XMMGPR_HI, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ + if( (lo) & MODE_READ ) { rpropSetRead(XMMGPR_LO, mask); } \ + if( (hi) & MODE_READ ) { rpropSetRead(XMMGPR_HI, mask); } \ +} \ + +// FPU regs +#define rpropSetFPURead(reg, mask) { \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + prev->fpuregs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0); \ +} \ + +#define rpropSetFPUWrite0(reg, mask, live) { \ + prev->fpuregs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + prev->fpuregs[reg] |= EEINST_USED; \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 1); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 1); \ +} + +#define rpropSetFPUWrite(reg, mask) { \ + rpropSetFPUWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +void rpropBSC(EEINST* prev, EEINST* pinst); +void rpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpropREGIMM(EEINST* prev, EEINST* pinst); +void rpropCP0(EEINST* prev, EEINST* pinst); +void rpropCP1(EEINST* prev, EEINST* pinst); +void rpropCP2(EEINST* prev, EEINST* pinst); +void rpropMMI(EEINST* prev, EEINST* pinst); +void rpropMMI0(EEINST* prev, EEINST* pinst); +void rpropMMI1(EEINST* prev, EEINST* pinst); +void rpropMMI2(EEINST* prev, EEINST* pinst); +void rpropMMI3(EEINST* prev, EEINST* pinst); + +#define EEINST_REALXMM (cpucaps.hasStreamingSIMDExtensions?EEINST_XMM:0) + +//SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, +//ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, +//COP0, COP1, COP2, NULL, BEQL, BNEL, BLEZL, BGTZL, +//DADDI, DADDIU, LDL, LDR, MMI, NULL, LQ, SQ, +//LB, LH, LWL, LW, LBU, LHU, LWR, LWU, +//SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, +//NULL, LWC1, NULL, PREF, NULL, NULL, LQC2, LD, +//NULL, SWC1, NULL, NULL, NULL, NULL, SQC2, SD +void rpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(cpuRegs.code >> 26) { + case 0: rpropSPECIAL(prev, pinst); break; + case 1: rpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpropSetWrite(31, EEINST_LIVE1); + break; + case 4: // beq + case 5: // bne + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0); + break; + + case 20: // beql + case 21: // bnel + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0); + break; + + case 6: // blez + case 7: // bgtz + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 22: // blezl + case 23: // bgtzl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // daddi + case 25: // daddiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|((_Rs_!=0&&cpucaps.hasStreamingSIMD2Extensions)?EEINST_MMX:0)); + break; + + case 8: // addi + case 9: // addiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + break; + + case 10: // slti + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + case 11: // sltiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 12: // andi + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, (_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 13: // ori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 14: // xori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 15: // lui + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 16: rpropCP0(prev, pinst); break; + case 17: rpropCP1(prev, pinst); break; + case 18: rpropCP2(prev, pinst); break; + + // loads + case 34: // lwl + case 38: // lwr + case 26: // ldl + case 27: // ldr + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 28: rpropMMI(prev, pinst); break; + + case 30: // lq + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 31: // sq + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + rpropSetRead(_Rt_, 0); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 44: // sdl + case 45: // sdr + case 63: // sd + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX|EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 49: // lwc1 + rpropSetFPUWrite(_Rt_, EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 57: // swc1 + rpropSetFPURead(_Rt_, EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 54: // lqc2 + case 62: // sqc2 + rpropSetRead(_Rs_, 0); + break; + + default: + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=0?EEINST_MMX:0)); + break; + } +} + +//SLL, NULL, SRL, SRA, SLLV, NULL, SRLV, SRAV, +//JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, NULL, SYNC, +//MFHI, MTHI, MFLO, MTLO, DSLLV, NULL, DSRLV, DSRAV, +//MULT, MULTU, DIV, DIVU, NULL, NULL, NULL, NULL, +//ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, +//MFSA, MTSA, SLT, SLTU, DADD, DADDU, DSUB, DSUBU, +//TGE, TGEU, TLT, TLTU, TEQ, NULL, TNE, NULL, +//DSLL, NULL, DSRL, DSRA, DSLL32, NULL, DSRL32, DSRA32 +void rpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 4: // sllv + case 6: // srlv + case 7: // srav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 8: // JR + rpropSetRead(_Rs_, 0); + break; + case 9: // JALR + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 10: // movz + case 11: // movn + // do not write _Rd_! + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rd_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + _recFillRegister(pinst, XMMTYPE_GPRREG, _Rd_, 1); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_REALXMM)|EEINST_LIVE1); + break; + case 17: // mthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_REALXMM)|EEINST_LIVE1); + break; + case 19: // mtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 20: // dsllv + case 22: // dsrlv + case 23: // dsrav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + + case 24: // mult + // can do unsigned mult only if HI isn't used + //temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE0|EEINST_LIVE1))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + temp = 0; + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + case 26: // div + case 27: // divu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_REALXMM|EEINST_MMX; + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ ) rpropSetRead(_Rs_, 0); + if( _Rt_ ) rpropSetRead(_Rt_, 0); + pinst->info |= EEINST_MMX; + break; + + case 36: // and + case 37: // or + case 38: // xor + case 39: // nor + // if rd == rs or rt, keep live1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + break; + + case 40: // mfsa + rpropSetWrite(_Rd_, EEINST_LIVE1); + break; + case 41: // mtsa + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + break; + + case 42: // slt + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 43: // sltu + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 44: // dadd + case 45: // daddu + case 46: // dsub + case 47: // dsubu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ == 0 || _Rt_ == 0 ) { + // just a copy, so don't force mmx + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + } + else { + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + } + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + // traps + case 48: case 49: case 50: case 51: case 52: case 54: + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + break; + + case 56: // dsll + case 58: // dsrl + case 59: // dsra + case 62: // dsrl32 + case 63: // dsra32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 60: // dsll32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + default: + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + } +} + +//BLTZ, BGEZ, BLTZL, BGEZL, NULL, NULL, NULL, NULL, +//TGEI, TGEIU, TLTI, TLTIU, TEQI, NULL, TNEI, NULL, +//BLTZAL, BGEZAL, BLTZALL, BGEZALL, NULL, NULL, NULL, NULL, +//MTSAB, MTSAH, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 2: // bltzl + case 3: // bgezl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + // traps + case 8: + case 9: + case 10: + case 11: + case 12: + case 14: + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 18: // bltzall + case 19: // bgezall + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mtsab + case 25: // mtsah + rpropSetRead(_Rs_, 0); + break; + default: + assert(0); + break; + } +} + +//MFC0, NULL, NULL, NULL, MTC0, NULL, NULL, NULL, +//COP0BC0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//COP0C0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 4: + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 8: // cop0bc0 + _recClearInst(prev); + prev->info = 0; + break; + case 16: // cop0c0 + _recClearInst(prev); + prev->info = 0; + break; + } +} + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +//ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, RSQRT_S, NULL, +//ADDA_S, SUBA_S, MULA_S, NULL, MADD_S, MSUB_S, MADDA_S, MSUBA_S, +//NULL, NULL, NULL, NULL, CVT_W, NULL, NULL, NULL, +//MAX_S, MIN_S, NULL, NULL, NULL, NULL, NULL, NULL, +//C_F, NULL, C_EQ, NULL, C_LT, NULL, C_LE, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP1(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + case 2: // cfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM|EEINST_MMX); + break; + case 4: // mtc1 + rpropSetFPUWrite(_Fs_, EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 6: // ctc1 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM|EEINST_MMX); + break; + case 8: // bc1 + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + break; + case 16: + // floating point ops + pinst->info |= EEINST_REALXMM; + switch( _Funct_ ) { + case 0: // add.s + case 1: // sub.s + case 2: // mul.s + case 3: // div.s + case 22: // rsqrt.s + case 40: // max.s + case 41: // min.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 4: // sqrt.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 5: // abs.s + case 6: // mov.s + case 7: // neg.s + case 36: // cvt.w + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + case 24: // adda.s + case 25: // suba.s + case 26: // mula.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 28: // madd.s + case 29: // msub.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + + case 30: // madda.s + case 31: // msuba.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + + case 48: // c.f + case 50: // c.eq + case 52: // c.lt + case 54: // c.le + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + default: assert(0); + } + break; + case 20: + assert( _Funct_ == 32 ); // CVT.S.W + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + default: + assert(0); + } +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +void rpropCP2(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 1: // qmfc2 + rpropSetWrite(_Rt_, EEINST_LIVE2|EEINST_LIVE1); + break; + + case 2: // cfc2 + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 5: // qmtc2 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 6: // ctc2 + rpropSetRead(_Rt_, 0); + break; + + case 8: // bc2 + break; + + default: + // vu macro mode insts + pinst->info |= 2; + break; + } +} + +//MADD, MADDU, NULL, NULL, PLZCW, NULL, NULL, NULL, +//MMI0, MMI2, NULL, NULL, NULL, NULL, NULL, NULL, +//MFHI1, MTHI1, MFLO1, MTLO1, NULL, NULL, NULL, NULL, +//MULT1, MULTU1, DIV1, DIVU1, NULL, NULL, NULL, NULL, +//MADD1, MADDU1, NULL, NULL, NULL, NULL, NULL, NULL, +//MMI1 , MMI3, NULL, NULL, NULL, NULL, NULL, NULL, +//PMFHL, PMTHL, NULL, NULL, PSLLH, NULL, PSRLH, PSRAH, +//NULL, NULL, NULL, NULL, PSLLW, NULL, PSRLW, PSRAW, +void rpropMMI(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(cpuRegs.code&0x3f) { + case 0: // madd + case 1: // maddu + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 4: // plzcw + rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1); + break; + case 8: rpropMMI0(prev, pinst); break; + case 9: rpropMMI2(prev, pinst); break; + + case 16: // mfhi1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM); + rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2); + break; + case 17: // mthi1 + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM); + rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2); + break; + case 19: // mtlo1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mult1 + temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE2))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + case 26: // div1 + case 27: // divu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_REALXMM|EEINST_MMX; + break; + + case 32: // madd1 + case 33: // maddu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2); + break; + + case 40: rpropMMI1(prev, pinst); break; + case 41: rpropMMI3(prev, pinst); break; + + case 48: // pmfhl + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 49: // pmthl + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +//recPADDW, PSUBW, PCGTW, PMAXW, +//PADDH, PSUBH, PCGTH, PMAXH, +//PADDB, PSUBB, PCGTB, NULL, +//NULL, NULL, NULL, NULL, +//PADDSW, PSUBSW, PEXTLW, PPACW, +//PADDSH, PSUBSH, PEXTLH, PPACH, +//PADDSB, PSUBSB, PEXTLB, PPACB, +//NULL, NULL, PEXT5, PPAC5, +void rpropMMI0(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 16: // paddsw + case 17: // psubsw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextlw + case 22: // pextlh + case 26: // pextlb + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + + case 30: // pext5 + case 31: // ppac5 + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI1(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 1: // pabsw + case 5: // pabsh + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 17: // psubuw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextuw + case 22: // pextuh + case 26: // pextub + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI2(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmaddw + case 4: // pmsubw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 2: // psllvw + case 3: // psllvw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + case 8: // pmfhi + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 9: // pmflo + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 10: // pinth + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 12: // pmultw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyld + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 16: // pmaddh + case 17: // phmadh + case 20: // pmsubh + case 21: // phmsbh + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + + case 26: // pexeh + case 27: // prevh + case 30: // pexew + case 31: // prot3w + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 28: // pmulth + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE); + break; + case 29: // pdivbw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI3(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmadduw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 3: // psravw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + + case 8: // pmthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 9: // pmtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 12: // pmultuw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivuw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyud + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM); + break; + + case 26: // pexch + case 27: // pcpyh + case 30: // pexcw + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/Makefile.am b/branches/pcsx2_0.9.2/x86/ix86-32/Makefile.am new file mode 100644 index 0000000..c185861 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I../ +noinst_LIBRARIES = libix86-32.a + +libix86_32_a_SOURCES = \ +iR5900Arit.c iR5900Branch.c iR5900LoadStore.c iR5900MultDiv.c \ +iR5900Arit.h iR5900Branch.h iR5900LoadStore.h iR5900MultDiv.h \ +iR5900AritImm.c iR5900Jump.c iR5900Move.c iR5900Shift.c \ +iR5900AritImm.h iR5900Jump.h iR5900Move.h iR5900Shift.h diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.c new file mode 100644 index 0000000..d692ea8 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.c @@ -0,0 +1,1996 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +// NOTE: The reason ADD/SUB/etc are so large is because they are very commonly +// used and recompiler needs to cover ALL possible usages to minimize code size (zerofrog) + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#elif defined(EE_CONST_PROP) + +//// ADD +void recADD_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0]; +} + +void recADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] ) { + u32* ptempmem; + + ptempmem = _eeGetConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(vreg) ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, mmreg, vreg); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[ creg ].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(vreg) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[creg].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)_eeGetConstReg(creg)); + PADDDMtoR(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == vreg ) { + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( g_cpuConstRegs[ creg ].UL[0] ) + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[0] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +// s is constant +void recADD_consts(int info) +{ + recADD_constv(info, _Rs_, _Rt_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rt_); +} + +// t is constant +void recADD_constt(int info) +{ + recADD_constv(info, _Rt_, _Rs_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); +} + +// nothing is constant +void recADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PADDDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDDRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDDRtoR(EEREC_D, EEREC_S); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PADDDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( _Rd_ == _Rs_ ) { + if( _Rd_ == _Rt_ ) SHL32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 1); // mult by 2 + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + + return; + } + else if( _Rd_ == _Rt_ ) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( _Rs_ != _Rt_ ) ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else SHL32ItoR(EAX, 1); // mult by 2 + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// ADDU +void recADDU( void ) +{ + recADD( ); +} + +//// DADD +void recDADD_const( void ) +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ creg ].UD[0] ) { + + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDQMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + if( g_cpuConstRegs[ creg ].UD[0] ) PADDQMtoR(mmreg, (u32)_eeGetConstReg(creg)); + } + else { + + if( g_cpuConstRegs[ creg ].UL[0] == 0 && g_cpuConstRegs[ creg ].UL[1] == 0 && _hasFreeMMXreg() ) { + // copy + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + if( EEINST_ISLIVE1(_Rd_) ) MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + else { + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + if( _Rd_ == vreg ) { + + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ creg ].UL[ 0 ] || g_cpuConstRegs[ creg ].UL[ 1 ]) ) { + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + ADC32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ creg ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + } + + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32ItoR( EDX, g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDADD_consts(int info) +{ + recDADD_constv(info, _Rs_, _Rt_); +} + +void recDADD_constt(int info) +{ + recDADD_constv(info, _Rt_, _Rs_); +} + +void recDADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PADDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( _Rs_ != _Rt_ ) PADDQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else PSLLQItoR(mmreg, 1); // mult by 2 + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// DADDU +void recDADDU( void ) +{ + recDADD( ); +} + +//// SUB + +void recSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0]; +} + +void recSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rs_ ].UL[0] ) { + + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + } + else { + if( _Rd_ == _Rt_ ) { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) SUB32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rs_ ].UL[ 0 ]); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + NEG32R(EAX); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +void recSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rt_ ].UL[0] ) { + + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(_Rs_) ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, EEREC_S, _Rs_); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[_Rt_].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(_Rs_) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[_Rt_].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PSUBDMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == _Rs_ ) { + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +void recSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PSUBDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + info = (info&~PROCESS_EE_SET_D(0xf))|PROCESS_EE_SET_D(t0reg); + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBDRtoR(EEREC_D, EEREC_T); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_)) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PSUBDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( !EEINST_ISLIVE1(_Rd_) ) { + if( _Rd_ == _Rs_) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SUBU +void recSUBU( void ) +{ + recSUB( ); +} + +//// DSUB +void recDSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rs_ ].UD[0] ) { + + // flush + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (u32)_eeGetConstReg(_Rs_)); + PSUBQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] || g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoR( EDX, g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + else { + + if( _Rd_ == _Rt_ ) { + // negate _Rt_ all in memory + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + NEG32M((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADC32ItoR(EDX, 0); + NEG32R(EDX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + } + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + // take negative of 64bit number + NEG32R(EAX); + + if( EEINST_ISLIVE1(_Rd_) ) { + ADC32ItoR(EDX, 0); + NEG32R(EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rt_ ].UD[0] ) { + + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( g_cpuConstRegs[_Rt_].UD[0] ) PSUBQMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + + if( _Rd_ == _Rs_ ) { + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ]) ) { + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + SBB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ) { + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32ItoR( EDX, g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PSUBQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBQRtoR(EEREC_D, EEREC_T); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[ 0 ]); + PSUBQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( _Rd_ == _Rs_ ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSUBU +void recDSUBU( void ) +{ + recDSUB( ); +} + +//// AND +void recAND_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0]; +} + +void recAND_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PANDMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + PXORRtoR(EEREC_D, EEREC_D); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PANDMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + else { + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + + if( _Rd_ == vreg ) { + AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + AND32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) + AND32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recAND_consts(int info) +{ + recAND_constv(info, _Rs_, _Rt_); +} + +void recAND_constt(int info) +{ + recAND_constv(info, _Rt_, _Rs_); +} + +void recLogicalOp(int info, int op) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( EEREC_D == EEREC_S ) LogicalOpRtoR(EEREC_D, EEREC_T, op); + else if( EEREC_D == EEREC_T ) LogicalOpRtoR(EEREC_D, EEREC_S, op); + else { + MOVQRtoR(EEREC_D, EEREC_S); + LogicalOpRtoR(EEREC_D, EEREC_T, op); + } + } + else if( (g_pCurInstInfo->regs[_Rs_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + int rsreg, rtreg, rdreg; + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + rsreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + rtreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + SetMMXstate(); + + if( rdreg == rsreg ) { + if( rtreg >= 0 ) LogicalOpRtoR(rdreg, rtreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ], op); + } + else { + if( rdreg != rtreg ) { + if( rtreg >= 0 ) MOVQRtoR(rdreg, rtreg); + else MOVQMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ]); + } + + if( rsreg >= 0 ) LogicalOpRtoR(rdreg, rsreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rs_ ], op); + } + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX, op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ] + 4, EDX, op ); + if( op == 3 ) { + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]+4); + } + + if( !EEINST_ISLIVE1(_Rd_) ) EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ] + 4 ); + LogicalOp32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ], op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op ); + + if( op == 3 ) { + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + } + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } +} + +void recAND_(int info) +{ + recLogicalOp(info, 0); +} + +EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// OR +void recOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]; +} + +void recOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recOR_consts(int info) +{ + recOR_constv(info, _Rs_, _Rt_); +} + +void recOR_constt(int info) +{ + recOR_constv(info, _Rt_, _Rs_); +} + +void recOR_(int info) +{ + recLogicalOp(info, 1); +} + +EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// XOR +void recXOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0]; +} + +void recXOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PXORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PXORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) XOR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) XOR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recXOR_consts(int info) +{ + recXOR_constv(info, _Rs_, _Rt_); +} + +void recXOR_constt(int info) +{ + recXOR_constv(info, _Rt_, _Rs_); +} + +void recXOR_(int info) +{ + recLogicalOp(info, 2); +} + +EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// NOR +void recNOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]); +} + +void recNOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + + // take the NOT + PCMPEQDRtoR( t0reg,t0reg); + PXORRtoR( EEREC_D,t0reg); + _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PCMPEQDRtoR( t0reg,t0reg); + if( g_cpuConstRegs[ creg ].UD[0] ) PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + + // take the NOT + PXORRtoR( rdreg,t0reg); + + _freeMMXreg(t0reg); + } + else { + if( _Rd_ == vreg ) { + NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]); + + if( g_cpuConstRegs[creg].UL[0] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], ~g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recNOR_consts(int info) +{ + recNOR_constv(info, _Rs_, _Rt_); +} + +void recNOR_constt(int info) +{ + recNOR_constv(info, _Rt_, _Rs_); +} + +void recNOR_(int info) +{ + recLogicalOp(info, 3); +} + +EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SLT - test with silent hill, lemans +void recSLT_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0]; +} + +static u32 s_sltconst = 0x80000000; +static u32 s_sltconst64[2] = {0, 0x80000000}; +u32 s_sltone = 1; + +void recSLTs_consts(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( g_cpuConstRegs[_Rs_].UL[1] == (g_cpuConstRegs[_Rs_].SL[0]<0?0xffffffff:0) && EEINST_ISSIGNEXT(_Rt_) ) { + // just compare the lower values + if( sign ) { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000; + ptempmem[1] = 0; + + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORMtoR(EEREC_D, (u32)&s_sltconst); + } + + PCMPGTDMtoR(EEREC_D, (u32)ptempmem); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + + // fall through + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + } + } + + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + j8Ptr[1] = JBE8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +// SLT with one operand coming from mem (compares only low 32 bits) +void recSLTmemconstt(int regd, int regs, u32 mem, int sign) +{ + // just compare the lower values + int t0reg; + + if( sign ) { + if( regd == regs ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, mem); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQMtoR(regd, mem); + PCMPGTDRtoR(regd, regs); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + } + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( regd == regs ) { + MOVQMtoR(t0reg, mem); + PXORMtoR(regs, (u32)&s_sltconst); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQRtoR(t0reg, regs); + MOVQMtoR(regd, mem); + PXORMtoR(t0reg, (u32)&s_sltconst); + PCMPGTDRtoR(regd, t0reg); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + _freeMMXreg(t0reg); + } + } +} + +void recSLTs_constt(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( EEINST_ISSIGNEXT(_Rs_) && g_cpuConstRegs[_Rt_].UL[1] == (g_cpuConstRegs[_Rt_].SL[0]<0?0xffffffff:0) ) { + // just compare the lower values + if( sign ) { + recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000; + ptempmem[1] = 0; + + recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + + // fall through + } + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLTs_(int info, int sign) +{ + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLT_consts(int info) +{ + recSLTs_consts(info, 1); +} + +void recSLT_constt(int info) +{ + recSLTs_constt(info, 1); +} + +void recSLT_(int info) +{ + int t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 1); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 1); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + // just compare the lower values + if( EEREC_D == EEREC_S ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + PCMPGTDRtoR(t0reg, EEREC_S); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDRtoR(EEREC_D, EEREC_S); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } +} + +EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +// SLTU - test with silent hill, lemans +void recSLTU_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0]; +} + +void recSLTU_consts(int info) +{ + recSLTs_consts(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_constt(int info) +{ + recSLTs_constt(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_(int info) +{ + int t1reg; + + assert( !(info & PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 0); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 0); + return; + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOVDMtoMMX(t1reg, (u32)&s_sltconst); + + if( EEREC_D == EEREC_S ) { + PXORRtoR(EEREC_S, t1reg); + PXORRtoR(t1reg, EEREC_T); + PCMPGTDRtoR(t1reg, EEREC_S); + + PUNPCKLDQRtoR(t1reg, t1reg); + PSRLQItoR(t1reg, 63); + + // swap regs + mmxregs[t1reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(t1reg, EEREC_S); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORRtoR(EEREC_D, t1reg); + PXORRtoR(t1reg, EEREC_S); + } + + PCMPGTDRtoR(EEREC_D, t1reg); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + + _freeMMXreg(t1reg); + } +} + +EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) +{ + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) +{ + if ( ! _Rd_ ) + { + return; + } + if ( ( _Rt_ == 0 ) || ( _Rs_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PANDRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + +} + +//////////////////////////////////////////////////// +void recOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0x0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0x0 ); + } + else if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PORRtoR( MM0, MM1 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recXOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0x0); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0x0); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recNOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0xffffffff); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0xffffffff); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PORMtoR( MM0,(int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +// test with silent hill, lemans +void recSLT( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JG8( 0 ); + j8Ptr[2] = JL8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) +{ + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JA8( 0 ); + j8Ptr[2] = JB8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.h new file mode 100644 index 0000000..5fcd64d --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.c new file mode 100644 index 0000000..8a075ae --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.c @@ -0,0 +1,659 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#elif defined(EE_CONST_PROP) + +//// ADDI +void recADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + _Imm_; +} + +void recADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rs_); + + if( info & PROCESS_EE_MMX ) { + if( _Imm_ != 0 ) { + + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDDMtoR(EEREC_T, (u32)ptempmem); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + + if( EEINST_ISLIVE1(_Rt_) ) + _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); + else + EEINST_RESETHASLIVE1(_Rt_); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + if( _Imm_ != 0 ) { + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDDMtoR(rtreg, (u32)ptempmem); + + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + } + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, ADDI); + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + _Imm_; +} + +void recDADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( _Imm_ != 0 ) { + + // flush + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDQMtoR(EEREC_T, (u32)ptempmem); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int rtreg; + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDQMtoR(rtreg, (u32)ptempmem); + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + ADC32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], _Imm_<0?0xffffffff:0); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, DADDI); + +//// DADDIU +void recDADDIU( void ) +{ + recDADDI( ); +} + +//// SLTIU +void recSLTIU_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < (u64)(_Imm_); +} + +extern void recSLTmemconstt(int regd, int regs, u32 mem, int sign); +extern u32 s_sltone; + +void recSLTIU_(int info) +{ + if( info & PROCESS_EE_MMX ) { + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = ((s32)(_Imm_))^0x80000000; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 0); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTIU); + +//// SLTI +void recSLTI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < (s64)(_Imm_); +} + +void recSLTI_(int info) +{ + if( info & PROCESS_EE_MMX) { + + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = _Imm_; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 1); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + // test silent hill if modding + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTI); + +//// ANDI +void recANDI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & (s64)_ImmU_; +} + +extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +extern void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +extern void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoM(u32 to, u32 from, int op); + +void recLogicalOpI(int info, int op) +{ + if( info & PROCESS_EE_MMX ) { + SetMMXstate(); + + if( _ImmU_ != 0 ) { + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + LogicalOpMtoR(EEREC_T, (u32)ptempmem, op); + } + else { + if( op == 0 ) PXORRtoR(EEREC_T, EEREC_T); + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && ((_Rt_ != _Rs_) || (_ImmU_==0)) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + u32* ptempmem; + + SetMMXstate(); + + ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( op == 0 ) { + if ( _ImmU_ != 0 ) { + if( _ImmU_ == 0xffff ) { + // take a shortcut + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] - 2); + PSRLDItoR(rtreg, 16); + } + else { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PANDMtoR(rtreg, (u32)ptempmem); + } + } + else PXORRtoR(rtreg, rtreg); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if ( _ImmU_ != 0 ) LogicalOpMtoR(rtreg, (u32)ptempmem, op); + } + } + else { + if ( _ImmU_ != 0 ) + { + if( _Rt_ == _Rs_ ) { + LogicalOp32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_, op); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + LogicalOp32ItoR( EAX, _ImmU_, op); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + + if( op == 0 ) { + if( EEINST_ISLIVE1(_Rt_ ) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + } + else + { + if( op == 0 ) { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + } + else { + if( _Rt_ != _Rs_ ) { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + } + + if( !EEINST_ISLIVE1(_Rt_) ) EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +void recANDI_(int info) +{ + recLogicalOpI(info, 0); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ANDI); + +//////////////////////////////////////////////////// +void recORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | (s64)_ImmU_; +} + +void recORI_(int info) +{ + recLogicalOpI(info, 1); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ORI); + +//////////////////////////////////////////////////// +void recXORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ (s64)_ImmU_; +} + +void recXORI_(int info) +{ + recLogicalOpI(info, 2); +} + +EERECOMPILE_CODEX(eeRecompileCode1, XORI); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) +{ +#ifdef __x86_64_ + if ( ! _Rt_ ) + { + return; + } + + MOV64MtoR( RAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +#else + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + if ( _Imm_ < 0 ) + { + ADC32ItoR( EDX, 0xffffffff ); + } + else + { + ADC32ItoR( EDX, 0 ); + } + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + return; + + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + return; + + // test silent hill if modding + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recANDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + if ( _ImmU_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } + +} + +//////////////////////////////////////////////////// +static u64 _imm = 0; // temp immediate + +void recORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recXORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PXORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ], MM0 ); + SetMMXstate(); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.h new file mode 100644 index 0000000..4bd7a0c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.c new file mode 100644 index 0000000..75faf79 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.c @@ -0,0 +1,1087 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + +#if defined(EE_CONST_PROP) + +void recSetBranchEQ(int info, int bne, int process) +{ + if( info & PROCESS_EE_MMX ) { + int t0reg; + + SetMMXstate(); + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + if( t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + PCMPEQDRtoR(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEMMX(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + PCMPEQDRtoR(t0reg, EEREC_S); + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PCMPEQDRtoR(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + + PMOVMSKBMMXtoR(EAX, t0reg); + + _eeFlushAllUnused(); + + CMP8ItoR( EAX, 0xff ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( info & PROCESS_EE_XMM ) { + int t0reg; + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + + if( t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeXMMreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _eeFlushAllUnused(); + + AND8ItoR(EAX, 3); + CMP8ItoR( EAX, 0x3 ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + + _eeFlushAllUnused(); + + if( bne ) { + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + + x86SetJ8( j8Ptr[0] ); + } + else { + // beq + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +void recSetBranchL(int ltz) +{ + int regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + PXORRtoR(t0reg, t0reg); + PCMPGTDRtoR(t0reg, regs); + PMOVMSKBMMXtoR(EAX, t0reg); + + _freeMMXreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 0x80 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, regs); + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _freeXMMreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 2 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + if( ltz ) j32Ptr[ 0 ] = JGE32( 0 ); + else j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +//// BEQ +void recBEQ_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +void recBEQ_(int info) { recBEQ_process(info, 0); } +void recBEQ_consts(int info) { recBEQ_process(info, PROCESS_CONSTS); } +void recBEQ_constt(int info) { recBEQ_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQ, XMMINFO_READS|XMMINFO_READT); + +//// BNE +void recBNE_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + recSetBranchEQ(info, 1, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBNE_(int info) { recBNE_process(info, 0); } +void recBNE_consts(int info) { recBNE_process(info, PROCESS_CONSTS); } +void recBNE_constt(int info) { recBNE_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNE, XMMINFO_READS|XMMINFO_READT); + +//// BEQL +void recBEQL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBEQL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +void recBEQL_(int info) { recBEQL_process(info, 0); } +void recBEQL_consts(int info) { recBEQL_process(info, PROCESS_CONSTS); } +void recBEQL_constt(int info) { recBEQL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQL, XMMINFO_READS|XMMINFO_READT); + +//// BNEL +void recBNEL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm(branchTo); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBNEL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +void recBNEL_(int info) { recBNEL_process(info, 0); } +void recBNEL_consts(int info) { recBNEL_process(info, PROCESS_CONSTS); } +void recBNEL_constt(int info) { recBNEL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNEL, XMMINFO_READS|XMMINFO_READT); + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +//void recBLTZAL( void ) +//{ +// SysPrintf("BLTZAL\n"); +// _eeFlushAllUnused(); +// MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (int)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (int)BLTZAL ); +// branch = 2; +//} + +//////////////////////////////////////////////////// +void recBLTZAL(int info) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + SysPrintf("BLTZAL\n"); + _eeOnWriteReg(31, 0); + _eeFlushAllUnused(); + + _deleteEEreg(31, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[0], pc+4); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[1], 0); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#endif + +//// BLEZ +void recBLEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//// BGTZ +void recBGTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JL32( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JG32( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.h new file mode 100644 index 0000000..3370b8a --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.c new file mode 100644 index 0000000..af4cf2b --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.c @@ -0,0 +1,131 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + _deleteEEreg(31, 0); + GPR_SET_CONST(31); + g_cpuConstRegs[31].UL[0] = pc + 4; + g_cpuConstRegs[31].UL[1] = 0; + + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, _Rs_); + // uncomment when there are NO instructions that need to call interpreter +// int mmreg; +// if( GPR_IS_CONST1(_Rs_) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[_Rs_].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + + if ( _Rd_ ) + { + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + g_cpuConstRegs[_Rd_].UL[0] = pc + 4; + g_cpuConstRegs[_Rd_].UL[1] = 0; + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + + SetBranchReg(0xffffffff); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.h new file mode 100644 index 0000000..d35f87c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.c new file mode 100644 index 0000000..0d9a282 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.c @@ -0,0 +1,4286 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else + +PCSX2_ALIGNED16(u64 retValues[2]); +extern u32 maxrecmem; +static u32 s_bCachingMem = 0; +static u32 s_nAddMemOffset = 0; +static u32 s_tempaddr = 0; + +void _eeOnLoadWrite(int reg) +{ + int regt; + + if( !reg ) return; + + _eeOnWriteReg(reg, 1); + regt = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + if( cpucaps.hasStreamingSIMD2Extensions && (reg != _Rs_) ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(regt, regt); + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + else SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } +} + +#ifdef WIN32_VIRTUAL_MEM + +extern void iMemRead32Check(); + +#define _Imm_co_ (*(s16*)PSM(pc)) + +// perf counters +#ifdef PCSX2_DEVBUILD +extern void StartPerfCounter(); +extern void StopPerfCounter(); +#else +#define StartPerfCounter() +#define StopPerfCounter() +#endif + +//////////////////////////////////////////////////// +//#define REC_SLOWREAD +//#define REC_SLOWWRITE +#define REC_FORCEMMX 0 + +// if sp, always mem write +int _eeIsMemWrite() { return _Rs_==29||_Rs_== 31||_Rs_==26||_Rs_==27; } // sp, ra, k0, k1 +// gp can be 1000a020 (jak1) + +void recTransferX86ToReg(int x86reg, int gprreg, int sign) +{ + //if( !REC_FORCEMMX ) assert( _checkMMXreg(MMX_GPR+gprreg, MODE_WRITE) == -1 ); + if( sign ) { + if( x86reg == EAX && EEINST_ISLIVE1(gprreg) ) CDQ(); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + + if(EEINST_ISLIVE1(gprreg)) { + if( x86reg == EAX ) MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], EDX ); + else { + SAR32ItoR(x86reg, 31); + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], x86reg ); + } + } + else { + EEINST_RESETHASLIVE1(gprreg); + } + } + else { + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + if(EEINST_ISLIVE1(gprreg)) MOV32ItoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(gprreg); + } +} + +#ifdef _DEBUG +void testaddrs() +{ + register int tempaddr; + + __asm mov tempaddr, ecx + //__asm mov incaddr, edx + + assert( (tempaddr < 0x40000000) || (tempaddr&0xd0000000)==0x50000000 || (tempaddr >= 0x80000000 && tempaddr < 0xc0000000) ); + //assert( (tempaddr>>28) == ((tempaddr+incaddr)>>28) ); + + __asm mov ecx, tempaddr +} +#endif + +#define SET_HWLOC() { \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[2]); \ + else x86SetJ8(j8Ptr[0]); \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[3]); \ + else x86SetJ8(j8Ptr[3]); \ + if (x86FpuState==MMX_STATE) { \ + if (cpucaps.has3DNOWInstructionExtensions) FEMMS(); \ + else EMMS(); \ + } \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ + if( s_bCachingMem & 4 ) AND32ItoR(ECX, 0x5fffffff); \ +} \ + +static u16 g_MemMasks0[16] = {0x00f0, 0x80f1, 0x00f2, 0x00f3, + 0x00f1, 0x00f5, 0x00f1, 0x00f5, + 0x00f5, 0x80f5, 0x00f5, 0x80f5, + 0x00f1, 0x00f1, 0x00f1, 0x00f5 }; +static u16 g_MemMasks8[16] = {0x0080, 0x8081, 0x0082, 0x0083, + 0x0081, 0x0085, 0x0081, 0x0085, + 0x0085, 0x8085, 0x0085, 0x8085, + 0x0081, 0x0081, 0x0081, 0x0085 }; +static u16 g_MemMasks16[16] ={0x0000, 0x8001, 0x0002, 0x0003, + 0x0001, 0x0005, 0x0001, 0x0005, + 0x0005, 0x8005, 0x0005, 0x8005, + 0x0001, 0x0001, 0x0001, 0x0005 }; + +static int s_bFastMemory = 0; +void SetFastMemory(int bSetFast) +{ + s_bFastMemory = bSetFast; + if( bSetFast) { + g_MemMasks0[0] = 0x00f0; g_MemMasks0[1] = 0x80f1; g_MemMasks0[2] = 0x00f0; g_MemMasks0[3] = 0x00f1; + g_MemMasks8[0] = 0x0080; g_MemMasks8[1] = 0x8081; g_MemMasks8[2] = 0x0080; g_MemMasks8[3] = 0x0081; + g_MemMasks16[0] = 0x0000; g_MemMasks16[1] = 0x8001; g_MemMasks16[2] = 0x0000; g_MemMasks16[3] = 0x0001; + } + else { + g_MemMasks0[0] = 0x00f0; g_MemMasks0[1] = 0x80f1; g_MemMasks0[2] = 0x00f2; g_MemMasks0[3] = 0x00f3; + g_MemMasks8[0] = 0x0080; g_MemMasks8[1] = 0x8081; g_MemMasks8[2] = 0x0082; g_MemMasks8[3] = 0x0083; + g_MemMasks16[0] = 0x0000; g_MemMasks16[1] = 0x8001; g_MemMasks16[2] = 0x0002; g_MemMasks16[3] = 0x0003; + } +} + +void assertmem() +{ + __asm mov s_tempaddr, ecx + __asm mov s_bCachingMem, edx + SysPrintf("%x(%x) not mem write!\n", s_tempaddr, s_bCachingMem); + assert(0); +} + +int _eePrepareReg(int gprreg) +{ + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + + if( mmreg >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + mmreg |= MEM_XMMTAG; + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + if( mmxregs[mmreg].mode&MODE_WRITE ) mmreg |= MEM_MMXTAG; + else { + mmxregs[mmreg].needed = 0; // coX can possibly use all regs + mmreg = 0; + } + } + else { + mmreg = 0; + } + + return mmreg; +} + +int _eePrepareReg_coX(int gprreg, int num) +{ + int mmreg = _eePrepareReg(gprreg); + + if( (mmreg&MEM_MMXTAG) && num == 7 ) { + if( mmxregs[mmreg&0xf].mode & MODE_WRITE ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg], mmreg&0xf); + mmxregs[mmreg&0xf].mode &= ~MODE_WRITE; + mmxregs[mmreg&0xf].needed = 0; + } + } + + return mmreg; +} + +// returns true if should also include harware writes +int recSetMemLocation(int regs, int imm, int mmreg, int msize, int j32) +{ + s_bCachingMem = j32 ? 2 : 0; + s_nAddMemOffset = 0; + + //int num; + if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) { + SSE2_MOVD_XMM_to_R(ECX, mmreg&0xf); + } + else if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) { + MOVD32MMXtoR(ECX, mmreg&0xf); + SetMMXstate(); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ regs ].UL[ 0 ] ); + } + + if ( imm != 0 ) ADD32ItoR( ECX, imm ); + + LoadCW(); + +#ifdef _DEBUG + //CALLFunc((u32)testaddrs); +#endif + + + // 32bit version (faster?) +// MOV32RtoR(EAX, ECX); +// ROR32ItoR(ECX, 28); +// SHR32ItoR(EAX, 28); +// MOV32RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 2); +// AND8RtoR(ECX, EAX); +// ROR32ItoR(ECX, 4); +// // do extra alignment masks here +// OR32RtoR(EAX, EAX); + + if( _eeIsMemWrite() ) { + u8* ptr; + CMP32ItoR(ECX, 0x40000000); + ptr = JB8(0); + if( msize == 1 ) AND32ItoR(ECX, 0x5ffffff8); + else if( msize == 2 ) AND32ItoR(ECX, 0x5ffffff0); + else AND32ItoR(ECX, 0x5fffffff); + x86SetJ8(ptr); + if( msize == 1 ) AND8ItoR(ECX, 0xf8); + else if( msize == 2 ) AND8ItoR(ECX, 0xf0); +#ifdef _DEBUG + MOV32RtoR(EAX, ECX); + SHR32ItoR(EAX, 28); + CMP32ItoR(EAX, 1); + ptr = JNE8(0); + MOV32ItoR(EDX, _Rs_); + CALLFunc((u32)assertmem); + x86SetJ8(ptr); +#endif + return 0; + } + else { + // 16 bit version + MOV32RtoR(EAX, ECX); + ROR32ItoR(ECX, 28); + SHR32ItoR(EAX, 28); + MOV16RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 1); + AND8RtoR(ECX, EAX); + ROR32ItoR(ECX, 4); + + OR16RtoR(EAX, EAX); + + if( s_bCachingMem & 2 ) j32Ptr[2] = j32Ptr[3] = JS32(0); + else j8Ptr[0] = j8Ptr[3] = JS8(0); + } + + return 1; +} + + +void recLoad32(u32 bit, u32 imm, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _eeOnLoadWrite(_Rt_); + if( bit == 32 ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_MMXTAG; + else mmreg = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + mmreg = EAX; + } + + switch(bit) { + case 8: ineax = recMemConstRead8(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); break; + case 16: + assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 2 == 0 ); + ineax = recMemConstRead16(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); + break; + case 32: + // used by LWL/LWR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 4 == 0 ); + ineax = recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm); + break; + } + + if( ineax || !(mmreg&MEM_MMXTAG) ) { + if( mmreg&MEM_MMXTAG ) mmxregs[mmreg&0xf].inuse = 0; + recTransferX86ToReg(EAX, _Rt_, sign); + } + else { + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + + if( REC_FORCEMMX ) mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + else _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, imm, mmregs, 0, 0); + + if( mmreg >= 0 ) { + MOVD32RmOffsettoMMX(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset-(32-bit)/8); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + else { + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + if( mmreg >= 0 ) { + if( EEINST_ISLIVE1(_Rt_) ) MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_]); + else MOVD32RtoMMX(mmreg, EAX); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLoad32_co(u32 bit, u32 sign) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax = 0; + u32 written = 0; + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + + if( bit == 32 ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_MMXTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_MMXTAG; + else mmreg2 = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + mmreg1 = EBX; + mmreg2 = EAX; + } + + // do const processing + switch(bit) { + case 8: + if( recMemConstRead8(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead8(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 16: + if( recMemConstRead16(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead16(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 32: + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + break; + } + + if( !written && _Rt_ ) { + if( mmreg1&MEM_MMXTAG ) { + assert( mmxregs[mmreg1&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg1&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg1&0xf, 32-bit); + } + else recTransferX86ToReg(mmreg1, _Rt_, sign); + } + if( nextrt ) { + g_pCurInstInfo++; + if( !ineax && (mmreg2 & MEM_MMXTAG) ) { + assert( mmxregs[mmreg2&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg2&0xf, nextrt, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg2&0xf, 32-bit); + } + else { + if( mmreg2&MEM_MMXTAG ) mmxregs[mmreg2&0xf].inuse = 0; + recTransferX86ToReg(mmreg2, nextrt, sign); + } + g_pCurInstInfo--; + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + assert( !REC_FORCEMMX ); + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + switch(bit) { + case 8: + if( sign ) { + MOVSX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 16: + if( sign ) { + MOVSX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 32: + MOV32RmtoROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EBX, _Rt_, sign); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + break; + case 16: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + break; + case 32: + MOV32RtoM((u32)&s_tempaddr, ECX); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( nextrt ) { + g_pCurInstInfo++; + recTransferX86ToReg(EAX, nextrt, sign); + g_pCurInstInfo--; + } + } +} + +void recLB( void ) { recLoad32(8, _Imm_, 1); } +void recLB_co( void ) { recLoad32_co(8, 1); } +void recLBU( void ) { recLoad32(8, _Imm_, 0); } +void recLBU_co( void ) { recLoad32_co(8, 0); } +void recLH( void ) { recLoad32(16, _Imm_, 1); } +void recLH_co( void ) { recLoad32_co(16, 1); } +void recLHU( void ) { recLoad32(16, _Imm_, 0); } +void recLHU_co( void ) { recLoad32_co(16, 0); } +void recLW( void ) { recLoad32(32, _Imm_, 1); } +void recLW_co( void ) { recLoad32_co(32, 1); } +void recLWU( void ) { recLoad32(32, _Imm_, 0); } +void recLWU_co( void ) { recLoad32_co(32, 0); } + +//////////////////////////////////////////////////// + +// paired with LWR +void recLWL_co(void) { recLoad32(32, _Imm_-3, 1); } + +void recLWL( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, 24-shift*8); + AND32ItoR(ECX, (0xffffff>>(shift*8))); + OR32RtoR(EAX, ECX); + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) { + // mem << LWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHL32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff); + SAR32CLtoR(EDX); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(EDX, ECX); + + // combine + OR32RtoR(EAX, EDX); + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// + +// paired with LWL +void recLWR_co(void) { recLoad32(32, _Imm_, 1); } + +void recLWR( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, shift*8); + AND32ItoR(ECX, (0xffffff00<<(24-shift*8))); + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + PUSH32R(ECX); + AND32ItoR(ECX, ~3); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) + { + // mem << LWL_SHIFT[shift] + MOV32RtoR(ECX, EDX); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 3); // *8 + SHR32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(EDX, ECX); + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(ECX, EDX); + + // combine + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// +void recLoad64(u32 imm, int align) +{ + int mmreg; + int mask = align ? ~7 : ~0; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // also used by LDL/LDR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 8 == 0 ); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg); + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + if( !_hasFreeMMXreg() && _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ|MODE_WRITE); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, t0reg); + + if( _Rt_ ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UD[0], t0reg); + } + + _freeMMXreg(t0reg); + } + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + MOVQRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + + SetMMXstate(); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + SSE_MOVLPSRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + SSE_MOVLPS_M64_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + } + else { + int t0reg = _Rt_ ? _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE) : -1; + + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + if( t0reg >= 0 ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + SetMMXstate(); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( _Rt_ ) { + //_deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + ADD32ItoR(ESP, 4); + + if( t0reg >= 0 ) MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); +} + +void recLD(void) { recLoad64(_Imm_, 1); } + +void recLD_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLD(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int mmreg1 = -1, mmreg2 = -1, t0reg = -1, t1reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + if( nextrt ) _eeOnWriteReg(nextrt, 0); + + if( _Rt_ ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 < 0 ) { + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg1 >= 0 ) mmreg1 |= 0x8000; + } + + if( mmreg1 < 0 && _hasFreeMMXreg() ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + if( nextrt ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 < 0 ) { + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE|MODE_READ); + if( mmreg2 >= 0 ) mmreg2 |= 0x8000; + } + + if( mmreg2 < 0 && _hasFreeMMXreg() ) mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_WRITE); + } + + if( mmreg1 < 0 || mmreg2 < 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( mmreg1 < 0 && mmreg2 < 0 && _hasFreeMMXreg() ) { + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + else t1reg = t0reg; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 1, 0); + + if( mmreg1 >= 0 ) { + if( mmreg1 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _Rt_ ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], t0reg); + } + } + + if( mmreg2 >= 0 ) { + if( mmreg2 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + else MOVQRmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( nextrt ) { + MOVQRmtoROffset(t1reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ], t1reg); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg1 >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg1 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + if( _Rt_ ) { + _deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + + if( mmreg2 >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + + if( mmreg2 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + else MOVQMtoR(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + } + else { + if( nextrt ) { + _deleteEEreg(nextrt, 0); + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + } + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + if( mmreg1 < 0 || mmreg2 < 0 || !(mmreg1&0x8000) || !(mmreg2&0x8000) ) SetMMXstate(); + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + if( t0reg != t1reg && t1reg >= 0 ) _freeMMXreg(t1reg); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +void recLD_coX( int num ) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLD(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _eeOnWriteReg(nextrts[i], 0); + } + + if( _Rt_ ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg < 0 ) { + mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + } + else mmreg |= MEM_MMXTAG; + } + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckGPRtoMMX(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + if( mmregs[i] < 0 ) { + mmregs[i] = _allocCheckGPRtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE|MODE_READ); + if( mmregs[i] >= 0 ) mmregs[i] |= MEM_XMMTAG; + else mmregs[i] = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_WRITE)|MEM_MMXTAG; + } + else mmregs[i] |= MEM_MMXTAG; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 1, 0); + + if( mmreg >= 0 ) { + if( mmreg & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + u32 off = PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + + if( mmregs[i] >= 0 ) { + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmregs[i]&0xf, ECX, off); + else MOVQRmtoROffset(mmregs[i]&0xf, ECX, off); + } + } + + if( dohw ) { + if( (s_bCachingMem & 2) || num > 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead64 ); + } + + for(i = 0; i < num; ++i ) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( mmregs[i] >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + CALLFunc( (int)recMemRead64 ); + + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + else MOVQMtoR(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + } + else { + MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead64 ); + } + } + + ADD32ItoR(ESP, 4); + + if( (s_bCachingMem & 2) || num > 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +//////////////////////////////////////////////////// +void recLDL_co(void) { + recLoad64(_Imm_-7, 0); } + +void recLDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR_co(void) { recLoad64(_Imm_, 0); } + +void recLDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + int mmreg = -1; +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + // malice hits this + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Rt_ ) { + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_XMM) || !(g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + else { + int t0reg; + _deleteGPRtoXMMreg(_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + mmreg |= t0reg<<4; + } + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + } + + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + if( !_Rt_ ) _freeXMMreg(mmreg); + if( IS_MMXREG(mmreg) ) { + // flush temp + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], (mmreg>>4)&0xf); + _freeMMXreg((mmreg>>4)&0xf); + } + else assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else +#endif + { + int dohw; + int mmregs; + int t0reg = -1; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) + _flushConstReg(_Rs_); + + mmregs = _eePrepareReg(_Rs_); + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + // check if can process mmx + if( _hasFreeMMXreg() ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) { + mmreg |= MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg < 0 ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + } + } + + if( mmreg < 0 ) { + _deleteEEreg(_Rt_, 1); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + ADD32ItoR(ESP, 4); + } + } + else { + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQ_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLQ(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int t0reg = -1; + int mmregs = _eePrepareReg(_Rs_); + + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + if( _hasFreeMMXreg() ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) { + mmreg1 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg1 < 0 ) { + mmreg1 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + } + } + + if( nextrt ) { + _eeOnWriteReg(nextrt, 0); + + if( _hasFreeMMXreg() ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) { + mmreg2 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+nextrt, 2); + + if( mmreg2 < 0 ) { + mmreg2 = _allocGPRtoXMMreg(-1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + } + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg1 >= 0 && (mmreg1 & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else if( mmreg1 >= 0 && (mmreg1 & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( nextrt ) { + if( mmreg2 >= 0 && (mmreg2 & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOVQRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((u32)&cpuRegs.GPR.r[nextrt].UL[2], t0reg); + } + else if( mmreg2 >= 0 && (mmreg2 & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[nextrt].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrt].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead128 ); + + if( _Rt_) { + if( mmreg1 >= 0 && (mmreg1 & MEM_MMXTAG) ) MOVQMtoR(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else if( mmreg1 >= 0 && (mmreg1 & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + if( nextrt ) { + if( mmreg2 >= 0 && (mmreg2 & MEM_MMXTAG) ) MOVQMtoR(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ]); + else if( mmreg2 >= 0 && (mmreg2 & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ] ); + } + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } +} + +// coissues more than 2 LQs +void recLQ_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLQ(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + if( _Rt_ ) _deleteMMXreg(MMX_GPR+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + if( nextrts[i] ) _deleteMMXreg(MMX_GPR+nextrts[i], 2); + } + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) { + _eeOnWriteReg(nextrts[i], 0); + mmregs[i] = _allocGPRtoXMMreg(-1, nextrts[i], MODE_WRITE); + } + else mmregs[i] = -1; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 2, 1); + + if( _Rt_ ) SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + u32 off = s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + if( nextrts[i] ) SSEX_MOVDQARmtoROffset(mmregs[i], ECX, PS2MEM_BASE_+off&~0xf); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + if( _Rt_) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( nextrts[i] ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead128 ); + if( nextrts[i] ) SSEX_MOVDQA_M128_to_XMM(mmregs[i], (int)&cpuRegs.GPR.r[ nextrts[i] ].UL[ 0 ] ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +extern void recClear64(BASEBLOCK* p); +extern void recClear128(BASEBLOCK* p); + +// check if clearing executable code, size is in dwords +void recMemConstClear(u32 mem, u32 size) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !recLUT[mem>>16] ) + return; + + //iFlushCall(0); // just in case + + // check if mem is executable, and clear it + //CMP32ItoM((u32)&maxrecmem, mem); + //j8Ptr[5] = JBE8(0); + + // can clear now + if( size == 1 ) { + CMP32ItoM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); + } + else if( size == 2 ) { + // need to clear 8 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+8, 0); + j8Ptr[7] = JNE8(0); + + j8Ptr[8] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[6] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear64); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[8] ); + } + else { + assert( size == 4 ); + // need to clear 16 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK), 0); + j8Ptr[7] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*2, 0); + j8Ptr[8] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*3, 0); + j8Ptr[9] = JNE8(0); + + j8Ptr[10] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[8] ); + x86SetJ8( j8Ptr[9] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear128); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[10] ); + } + + //x86SetJ8(j8Ptr[5]); +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear32() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, recLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call recClearMem + add esp, 4 +ClearRet: + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear64() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear64 + ret +Clear64: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check both blocks + cmp dword ptr [edx], 0 + jne DoClear0 + cmp dword ptr [edx+8], 0 + jne DoClear1 + ret + +DoClear1: + add edx, 8 +DoClear0: + sub esp, 4 + mov dword ptr [esp], edx + call recClear64 + add esp, 4 + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear128() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear128 + ret +Clear128: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check all 4 blocks + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + ret + +DoClear: + sub esp, 4 + mov dword ptr [esp], edx + call recClear128 + add esp, 4 + ret + } +} + +void recStore_raw(EEINST* pinst, int bit, int x86reg, int gprreg, u32 offset) +{ + if( bit == 128 ) { + int mmreg; + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + + SetMMXstate(); + } + else { + + if( GPR_IS_CONST1( gprreg ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + SetMMXstate(); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( _hasFreeMMXreg() ) { + int t0reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); +// MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); +// MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset+8); + } + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + } + return; + } + + if( GPR_IS_CONST1( gprreg ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 16: MOV16ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 32: MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 64: + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + break; + } + } + else { + int mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ); + if( mmreg < 0 ) { + mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + if( mmreg >= 0 ) mmreg |= 0x8000; + } + + if( bit == 64 ) { + //sd + if( mmreg >= 0 ) { + if( mmreg & 0x8000 ) { + SSE_MOVLPSRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVQRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + if( (mmreg = _allocCheckGPRtoMMX(pinst, gprreg, MODE_READ)) >= 0 ) { + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_GPR+gprreg, MODE_READ); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + } + } + } + else if( bit == 32 ) { + // sw + if( mmreg >= 0 ) { + if( mmreg & 0x8000) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVD32MMXtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); + } + } + else { + // sb, sh + if( mmreg >= 0) { + if( mmreg & 0x8000) { + if( !(xmmregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + else { + if( !(mmxregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + } + + if( mmreg >= 0) { + if( mmreg & 0x8000 ) SSE2_MOVD_XMM_to_R(x86reg, mmreg&0xf); + else { + MOVD32MMXtoR(x86reg, mmreg&0xf); + SetMMXstate(); + } + } + else { + switch(bit) { + case 8: MOV8MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + + switch(bit) { + case 8: MOV8RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 16: MOV16RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 32: MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + } + } + } +} + +void recStore_call(int bit, int gprreg, u32 offset) +{ + // some type of hardware write + if( GPR_IS_CONST1( gprreg ) ) { + if( bit == 128 ) { + if( gprreg > 0 ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], g_cpuConstRegs[gprreg].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], g_cpuConstRegs[gprreg].UL[1]); + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + if( !(g_cpuFlushedConstReg&(1<= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + // sd + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVLPS_XMM_to_M64((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + SetMMXstate(); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else { + // sb, sh, sw + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + SSE2_MOVD_XMM_to_R(EAX, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE)) { + MOVD32MMXtoR(EAX, mmreg); + SetMMXstate(); + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + } + } + + if( offset != 0 ) ADD32ItoR(ECX, offset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)recMemWrite8 ); break; + case 16: CALLFunc( (int)recMemWrite16 ); break; + case 32: CALLFunc( (int)recMemWrite32 ); break; + case 64: CALLFunc( (int)recMemWrite64 ); break; + case 128: CALLFunc( (int)recMemWrite128 ); break; + } +} + +int _eePrepConstWrite128(int gprreg) +{ + int mmreg = 0; + + if( GPR_IS_CONST1(gprreg) ) { + if( gprreg ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + _freeMMXreg(mmreg); + mmreg |= (gprreg<<16)|MEM_EECONSTTAG; + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(mmreg, mmreg); + _freeXMMreg(mmreg); + mmreg |= MEM_XMMTAG; + } + } + else { + if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + int mmregtemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmregtemp, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + mmreg |= (mmregtemp<<4)|MEM_MMXTAG; + _freeMMXreg(mmregtemp); + } + else mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ)|MEM_XMMTAG; + } + + return mmreg; +} + +void recStore(int bit, u32 imm, int align) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+imm; + int doclear = 0; + StopPerfCounter(); + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite8(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 16: + assert( (addr)%2 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite16(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 32: + // used by SWL/SWR + //assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + break; + case 64: + { + //assert( (addr)%8 == 0 ); + int mask = align ? ~7 : ~0; + + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite64(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else { + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + + if( doclear ) { + recMemConstClear((addr)&~7, 2); + } + + break; + } + case 128: + //assert( (addr)%16 == 0 ); + + if( recMemConstWrite128((addr)&~15, _eePrepConstWrite128(_Rt_)) ) { + CMP32ItoM((u32)&maxrecmem, addr); + j8Ptr[0] = JB8(0); + recMemConstClear((addr)&~15, 4); + x86SetJ8(j8Ptr[0]); + } + + break; + } + + StartPerfCounter(); + } + else +#endif + { + int dohw; + int mmregs; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, imm, mmregs, align ? bit/64 : 0, 0); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[4] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + if( bit < 32 || !align ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[5] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + StopPerfCounter(); + recStore_call(bit, _Rt_, s_nAddMemOffset); + StartPerfCounter(); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recStore_co(int bit, int align) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_; + u32 coaddr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_; + int mmreg, t0reg = -1, mmreg2; + int doclear = 0; + + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite8(addr, EAX); + } + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite8(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite8(coaddr, EAX); + } + break; + case 16: + assert( (addr)%2 == 0 ); + assert( (coaddr)%2 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite16(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite16(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite16(coaddr, EAX); + } + break; + case 32: + assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite32(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_XMMTAG|(nextrt<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_MMXTAG|(nextrt<<16)); + } + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite32(coaddr, EAX); + } + + break; + case 64: + { + int mask = align ? ~7 : ~0; + //assert( (addr)%8 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + + if( GPR_IS_CONST1(nextrt) ) mmreg2 = MEM_EECONSTTAG|(nextrt<<16); + else if( (mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + mmreg2 |= MEM_XMMTAG|(nextrt<<16); + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_READ)|MEM_MMXTAG|(nextrt<<16); + + doclear = recMemConstWrite64((addr)&mask, mmreg); + doclear |= recMemConstWrite64((coaddr)&mask, mmreg2); + doclear <<= 1; + break; + } + case 128: + assert( (addr)%16 == 0 ); + + mmreg = _eePrepConstWrite128(_Rt_); + mmreg2 = _eePrepConstWrite128(nextrt); + doclear = recMemConstWrite128((addr)&~15, mmreg); + doclear |= recMemConstWrite128((coaddr)&~15, mmreg2); + doclear <<= 2; + break; + } + + if( doclear ) { + u8* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+(_Imm_ < _Imm_co_ ? _Imm_ : _Imm_co_)); + ptr = JB8(0); + recMemConstClear((addr)&~(doclear*4-1), doclear); + recMemConstClear((coaddr)&~(doclear*4-1), doclear); + x86SetJ8A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int off = _Imm_co_-_Imm_; + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align ? bit/64 : 0, bit==128); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + recStore_raw(g_pCurInstInfo+1, bit, EBX, nextrt, s_nAddMemOffset+off); + + // clear the writes, do only one camera (with the lowest addr) + if( off < 0 ) ADD32ItoR(ECX, s_nAddMemOffset+off); + else if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( off < 0 ) ADD32ItoR(ECX, -off); + else ADD32ItoR(ECX, off); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(bit, _Rt_, s_nAddMemOffset); + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(bit, nextrt, s_nAddMemOffset+_Imm_co_-_Imm_); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recSB( void ) { recStore(8, _Imm_, 1); } +void recSB_co( void ) { recStore_co(8, 1); } +void recSH( void ) { recStore(16, _Imm_, 1); } +void recSH_co( void ) { recStore_co(16, 1); } +void recSW( void ) { recStore(32, _Imm_, 1); } +void recSW_co( void ) { recStore_co(32, 1); } + +//////////////////////////////////////////////////// +void recSWL_co(void) { recStore(32, _Imm_-3, 0); } + +void recSWL( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0xffffff00<<(shift*8)); + SHR32ItoR(ECX, 24-shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem >> SWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHR32CLtoR(EBX); + + // mov temp and compute _rt_ & SWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +//////////////////////////////////////////////////// +void recSWR_co(void) { recStore(32, _Imm_, 0); } + +void recSWR( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0x00ffffff>>(24-shift*8)); + SHL32ItoR(ECX, shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem << SWR_SHIFT[shift] + MOV32RtoR(ECX, EDX); + SHL32CLtoR(EBX); + + // mov temp and compute _rt_ & SWR_MASK[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0x00ffffff); + SHR32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +void recSD( void ) { recStore(64, _Imm_, 1); } +void recSD_co( void ) { recStore_co(64, 1); } + +// coissues more than 2 SDs +void recSD_coX(int num, int align) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + u32 mask = align ? ~7 : ~0; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&mask, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + if( GPR_IS_CONST1(nextrts[i]) ) mmreg = MEM_EECONSTTAG|(nextrts[i]<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrts[i], MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_READ)|MEM_MMXTAG|(nextrts[i]<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&mask, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~7, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~7, 2); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align, 1); + + recStore_raw(g_pCurInstInfo, 64, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 64, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear64); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear64); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(64, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(64, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +//////////////////////////////////////////////////// +void recSDL_co(void) { recStore(64, _Imm_-7, 0); } + +void recSDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR_co(void) { recStore(64, _Imm_, 0); } + +void recSDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { recStore(128, _Imm_, 1); } +void recSQ_co( void ) { recStore_co(128, 1); } + +// coissues more than 2 SQs +void recSQ_coX(int num) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + mmreg = _eePrepConstWrite128(_Rt_); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + mmreg = _eePrepConstWrite128(nextrts[i]); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+imm)&~15, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~15, 4); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 1); + + recStore_raw(g_pCurInstInfo, 128, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 128, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear128); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear128); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(128, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(128, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + mmreg = EAX; + } + + if( !(mmreg&MEM_XMMTAG) ) + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + else +#endif + { + int dohw; + int regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + + if( regt >= 0 ) SSE2_MOVD_R_to_XMM(regt, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 written = 0; + int ineax, mmreg1, mmreg2; + + mmreg1 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + else mmreg2 = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_XMMTAG ) xmmregs[mmreg1&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + + if( !written ) { + if( !(mmreg1&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + } + + if( ineax || !(mmreg2 & MEM_XMMTAG) ) { + if( mmreg2&MEM_XMMTAG ) xmmregs[mmreg2&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int regt, regtnext; + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + regtnext = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( regtnext >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regtnext, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32R(ECX); + CALLFunc( (int)recMemRead32 ); + POP32R(ECX); + + if( regt >= 0 ) { + SSE2_MOVD_R_to_XMM(regt, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( regtnext >= 0 ) { + SSE2_MOVD_R_to_XMM(regtnext, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recLWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax; + u32 written = 0; + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + // recompile two at a time + for(i = 0; i < num-1; i += 2) { + nextrts[0] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + nextrts[1] = ((*(u32*)(PSM(pc+i*4+4)) >> 16) & 0x1F); + + written = 0; + mmregs[0] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[0], MODE_WRITE); + if( mmregs[0] >= 0 ) mmregs[0] |= MEM_XMMTAG; + else mmregs[0] = EBX; + + mmregs[1] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+2, nextrts[1], MODE_WRITE); + if( mmregs[1] >= 0 ) mmregs[1] |= MEM_XMMTAG; + else mmregs[1] = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmregs[0], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmregs[0]&MEM_XMMTAG ) xmmregs[mmregs[0]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmregs[1], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4+4))); + + if( !written ) { + if( !(mmregs[0]&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + } + + if( ineax || !(mmregs[1] & MEM_XMMTAG) ) { + if( mmregs[1]&MEM_XMMTAG ) xmmregs[mmregs[1]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[1] ].UL, EAX ); + } + } + + if( i < num ) { + // one left + int nextrt = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrt, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _deleteMMXreg(MMX_FPU+nextrts[i], 2); + } + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead32 ); + + if( mmreg >= 0 ) SSE2_MOVD_R_to_XMM(mmreg, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( mmregs[i] >= 0 ) SSE2_MOVD_R_to_XMM(mmregs[i], EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recSWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrt<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + int mmreg1, mmreg2; + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + assert( _checkMMXreg(MMX_FPU+nextrt, MODE_READ) == -1 ); + + mmreg1 = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if(mmreg1 >= 0 ) { + if( mmreg2 >= 0 ) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + else { + if( mmreg2 >= 0 ) { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32MtoR(EDX, (int)&fpuRegs.fpr[ nextrt ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg1 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg1); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + if( mmreg2 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg2); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recSWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + for(i = 0; i < num; ++i) { + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)), mmreg); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + for(i = 0; i < num; ++i) { + assert( _checkMMXreg(MMX_FPU+nextrts[i], MODE_READ) == -1 ); + mmregs[i] = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmregs[i], PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + if( mmregs[i] >= 0 && (xmmregs[mmregs[i]].mode&MODE_WRITE) ) SSE2_MOVD_XMM_to_R(EAX, mmregs[i]); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + CALLFunc( (int)recMemWrite32 ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else mmreg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + if( !_Ft_ ) _freeXMMreg(mmreg); + } + else +#endif + { + int dohw, mmregs; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Ft_ ) { + s8* rawreadptr = x86Ptr; + + if( mmreg >= 0 ) { + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&VU0.VF[_Ft_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + CALLFunc( (int)recMemRead128 ); + if( mmreg >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0] ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + else { + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQC2_co( void ) +{ + int mmreg1 = -1, mmreg2 = -1, t0reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg1 >= 0 ? mmreg1 : t0reg); + + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + else if( t0reg < 0 ) t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_)&~15, mmreg2 >= 0 ? mmreg2 : t0reg); + + if( t0reg >= 0 ) _freeXMMreg(t0reg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + if( mmreg1 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + if( mmreg2 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Ft_ ) PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg1 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0] ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&VU0.VF[nextrt].UD[0], 0 ); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg2 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0] ); + + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[1]); + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + } + else +#endif + { + s8* rawreadptr; + int dohw, mmregs; + + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg); + } + } + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +void recSQC2_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1, mmreg2; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg1); + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_)&~15, mmreg2); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg1 = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_VFREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( mmreg1 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg1 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg1); + } + else if( _hasFreeMMXreg() ) { + mmreg1 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg1); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( mmreg2 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( _hasFreeXMMreg() ) { + mmreg2 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + _freeXMMreg(mmreg2); + } + else if( _hasFreeMMXreg() ) { + mmreg2 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UL[2]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + SetMMXstate(); + _freeMMXreg(mmreg2); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+4); + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( mmreg1 >= 0) { + if( xmmregs[mmreg1].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg1); + } + } + + MOV32RtoM((u32)&s_tempaddr, ECX); + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + if( mmreg2 >= 0) { + if( xmmregs[mmreg2].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[nextrt].UD[0], mmreg2); + } + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + MOV32ItoR(EAX, (int)&VU0.VF[nextrt].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +#else + +PCSX2_ALIGNED16(u32 dummyValue[4]); + +void SetFastMemory(int bSetFast) +{ + // nothing +} + +//////////////////////////////////////////////////// +void recLB( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVSX32R8toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLBU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R8toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLH( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOVSX32R16toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLHU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R16toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLW( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWR ); +} + +//////////////////////////////////////////////////// +extern void MOV64RmtoR( x86IntRegType to, x86IntRegType from ); + +void recLD( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead64 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + AND32ItoR( EAX, ~0xf ); + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); + +} + +//////////////////////////////////////////////////// +void recSB( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite8 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite16 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite64 ); + ADD32ItoR( ESP, 12 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + AND32ItoR( EAX, ~0xf ); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +#endif + +#endif \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.h new file mode 100644 index 0000000..fd078b9 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900LoadStore.h @@ -0,0 +1,90 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSDL( void ); +void recSDR( void ); +void recSQ( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +// coissues +#ifdef WIN32_VIRTUAL_MEM +void recLB_co( void ); +void recLBU_co( void ); +void recLH_co( void ); +void recLHU_co( void ); +void recLW_co( void ); +void recLWU_co( void ); +void recLWL_co( void ); +void recLWR_co( void ); +void recLD_co( void ); +void recLDR_co( void ); +void recLDL_co( void ); +void recLQ_co( void ); +void recSB_co( void ); +void recSH_co( void ); +void recSW_co( void ); +void recSWL_co( void ); +void recSWR_co( void ); +void recSD_co( void ); +void recSDL_co( void ); +void recSDR_co( void ); +void recSQ_co( void ); +void recLWC1_co( void ); +void recSWC1_co( void ); +void recLQC2_co( void ); +void recSQC2_co( void ); + +// coissue-X +void recLD_coX(int num); +void recLQ_coX(int num); +void recLWC1_coX(int num); +void recSD_coX(int num); +void recSQ_coX(int num); +void recSWC1_coX(int num); + +#endif + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.c new file mode 100644 index 0000000..961711b --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.c @@ -0,0 +1,836 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#elif defined(EE_CONST_PROP) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//// LUI +void recLUI(int info) +{ + int mmreg; + if(!_Rt_) return; + + _eeOnWriteReg(_Rt_, 1); + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE)) >= 0 ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + } + + _deleteEEreg(_Rt_, 0); + GPR_SET_CONST(_Rt_); + g_cpuConstRegs[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +//////////////////////////////////////////////////// +void recMFHILO(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + assert( regd != reghi ); + + xmmregs[regd].inuse = 0; + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + else { + SSE_MOVLPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + SSE2_MOVQ_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + reghi = _checkMMXreg(MMX_GPR+xmmhilo, MODE_READ); + + if( reghi >= 0 ) { + + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], regd); + } + xmmregs[regd].inuse = 0; + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + SetMMXstate(); + + if( regd >= 0 ) { + MOVQRtoR(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + else SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 0 ] : (int)&cpuRegs.LO.UL[ 0 ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.UL[ 1 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } +} + +void recMTHILO(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + assert( reghi != regs ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + _deleteGPRtoXMMreg(_Rs_, 0); + SSE2_PUNPCKHQDQ_XMM_to_XMM(reghi, reghi); + SSE2_PUNPCKLQDQ_XMM_to_XMM(regs, reghi); + + // swap regs + xmmregs[regs] = xmmregs[reghi]; + xmmregs[reghi].inuse = 0; + xmmregs[regs].mode |= MODE_WRITE; + } + else { + SSE2EMU_MOVSD_XMM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + if( EEINST_ISLIVE2(xmmhilo) ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64(addrhilo+8, reghi); + } + xmmregs[reghi].inuse = 0; + MOVQRtoM(addrhilo, regs); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + _flushConstReg(_Rs_); + SSE_MOVLPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + } + else { + reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, xmmhilo, MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + //SetMMXstate(); + SSE2_MOVDQ2Q_XMM_to_MM(reghi, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoR(reghi, regs); + } + else { + _flushConstReg(_Rs_); + MOVQMtoR(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + } + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+4, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo, EAX ); + MOV32RtoM( addrhilo+4, EDX ); + } + } + } + } + } +} + +void recMFHI( void ) +{ + recMFHILO(1); +} + +void recMFLO( void ) +{ + recMFHILO(0); +} + +void recMTHI( void ) +{ + recMTHILO(1); +} + +void recMTLO( void ) +{ + recMTHILO(0); +} + +//////////////////////////////////////////////////// +void recMFHILO1(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + SSEX_MOVHLPS_XMM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + _deleteEEreg(_Rd_, 0); + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PUNPCKHQDQ_M128_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + SSE2_PSHUFD_XMM_to_XMM(regd, regd, 0x4e); + } + else { + SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + } + else { + SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + + xmmregs[regd].mode |= MODE_WRITE; + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 2 ] : (int)&cpuRegs.LO.UL[ 2 ]); + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 3 ] : (int)&cpuRegs.LO.UL[ 3 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + } + } +} + +void recMTHILO1(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, xmmhilo, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_XMM_to_XMM(reghi, regs); + else SSE_MOVLHPS_XMM_to_XMM(reghi, regs); + } + else { + _deleteEEreg(_Rs_, 1); + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_M128_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + else SSE_MOVHPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ]); + + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo+8, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo+8, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo+8, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+12, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo+8, EAX ); + MOV32RtoM( addrhilo+12, EDX ); + } + } + } + } +} + +void recMFHI1( void ) +{ + recMFHILO1(1); +} + +void recMFLO1( void ) +{ + recMFHILO1(0); +} + +void recMTHI1( void ) +{ + recMTHILO1(1); +} + +void recMTLO1( void ) +{ + recMTHILO1(0); +} + +//// MOVZ +void recMOVZtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +static PCSX2_ALIGNED16(s_zero[4]) = {0,0,0xffffffff, 0xffffffff}; + +void recMOVZtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVZtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + if( info & PROCESS_EE_MMX ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + return; + } + + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVZtemp_(int info) +{ + int t0reg = -1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVZtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVZ() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + else { + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; + g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + return; + } + } + + recMOVZtemp(); +} + +//// MOVN +void recMOVNtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +void recMOVNtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVNtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVNtemp_(int info) +{ + int t0reg=-1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVNtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVN() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + else { + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; + g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + return; + } + } + + recMOVNtemp(); +} + +#else + +//////////////////////////////////////////////////// +void recLUI( void ) +{ + if(!_Rt_) return; + if ( _Imm_ < 0 ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0xffffffff ); //V + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); //V + } +} + +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.h new file mode 100644 index 0000000..ae501e3 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.c new file mode 100644 index 0000000..3894766 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.c @@ -0,0 +1,953 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC( MULT1 ); +REC_FUNC( MULTU1 ); + +REC_FUNC(DIV); +REC_FUNC(DIVU); +REC_FUNC( DIV1 ); +REC_FUNC( DIVU1 ); + +REC_FUNC( MADD ); +REC_FUNC( MADDU ); +REC_FUNC( MADD1 ); +REC_FUNC( MADDU1 ); + +#elif defined(EE_CONST_PROP) + +// if upper is 1, write in upper 64 bits of LO/HI +void recWritebackHILO(int info, int writed, int upper) +{ + int regd, reglo = -1, reghi, savedlo = 0; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + MOV32RtoR( ECX, EDX ); + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + + _deleteMMXreg(XMMGPR_LO, 2); + + if( (reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ)) >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + + xmmregs[reglo].inuse = 0; + reglo = -1; + } + + CDQ(); + MOV32RtoM( loaddr, EAX ); + MOV32RtoM( loaddr+4, EDX ); + savedlo = 1; + } + + if ( writed && _Rd_ ) + { + _eeOnWriteReg(_Rd_, 1); + + regd = -1; + if( g_pCurInstInfo->regs[_Rd_] & EEINST_MMX ) { + + if( savedlo ) { + regd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + MOVQMtoR(regd, loaddr); + } + } + else if( g_pCurInstInfo->regs[_Rd_] & EEINST_XMM ) { + if( savedlo ) { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE|MODE_READ); + if( regd >= 0 ) { + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + regd |= 0x8000; + } + } + } + + if( regd < 0 ) { + _deleteEEreg(_Rd_, 0); + + if( EEINST_ISLIVE1(_Rd_) && !savedlo ) CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else EEINST_RESETHASLIVE1(_Rd_); + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + _deleteMMXreg(XMMGPR_HI, 2); + + if( (reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ)) >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + else SSE_MOVHPS_XMM_to_M64(hiaddr+8, reghi); + } + + xmmregs[reghi].inuse = 0; + reghi = -1; + } + + MOV32RtoM(hiaddr, ECX ); + SAR32ItoR(ECX, 31); + MOV32RtoM(hiaddr+4, ECX ); + } +} + +void recWritebackHILOMMX(int info, int regsource, int writed, int upper) +{ + int regd, t0reg, t1reg = -1; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + SetMMXstate(); + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, regsource); + PSRADItoR(t0reg, 31); // shift in 0s + + if( (g_pCurInstInfo->regs[XMMGPR_LO] & testlive) || (writed && _Rd_) ) { + if( (g_pCurInstInfo->regs[XMMGPR_HI] & testlive) ) + { + if( !_hasFreeMMXreg() ) { + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t1reg, regsource); + } + + PUNPCKLDQRtoR(regsource, t0reg); + } + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + int reglo; + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + MOVQRtoR(reglo, regsource); + } + else { + reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ); + + MOVQRtoM(loaddr, regsource); + + if( reglo >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + xmmregs[reglo].inuse = 0; + reglo = -1; + } + } + } + + if ( writed && _Rd_ ) + { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + if( regd != regsource ) MOVQRtoR(regd, regsource); + } + else { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ); + + if( regd >= 0 ) { + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + // lo written + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + + xmmregs[regd].inuse = 0; + } + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + int mmreg = -1, reghi; + + if( t1reg >= 0 ) { + PUNPCKHDQRtoR(t1reg, t0reg); + mmreg = t1reg; + } + else { + // can't modify regsource + PUNPCKHDQRtoR(t0reg, regsource); + mmreg = t0reg; + PSHUFWRtoR(t0reg, t0reg, 0x4e); + } + + if( upper ) { + reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ); + if( reghi >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + } + + xmmregs[reghi].inuse = 0; + MOVQRtoM(hiaddr, mmreg); + } + else { + _deleteGPRtoXMMreg(XMMGPR_HI, 2); + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + mmxregs[mmreg].mode = MODE_WRITE; + mmxregs[mmreg].reg = MMX_GPR+MMX_HI; + + if( t1reg >= 0 ) t1reg = -1; + else t0reg = -1; + } + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg&0xf); + if( t1reg >= 0 ) _freeMMXreg(t1reg&0xf); +} + +void recWritebackConstHILO(u64 res, int writed, int upper) +{ + int reglo, reghi; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + MOVQMtoR(reglo, (u32)ptr); + } + else { + reglo = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE|MODE_READ); + + if( reglo >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reglo, (u32)ptr); + } + else { + MOV32ItoM(loaddr, res & 0xffffffff); + MOV32ItoM(loaddr+4, (res&0x80000000)?0xffffffff:0); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + MOVQMtoR(reghi, (u32)ptr); + } + else { + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr); + } + else { + _deleteEEreg(XMMGPR_HI, 0); + MOV32ItoM(hiaddr, res >> 32); + MOV32ItoM(hiaddr+4, (res>>63)?0xffffffff:0); + } + } + } + + if (!writed || !_Rd_) return; + g_cpuConstRegs[_Rd_].UD[0] = (s32)(res & 0xffffffff); //that is the difference +} + +//// MULT +void recMULT_const() +{ + s64 res = (s64)g_cpuConstRegs[_Rs_].SL[0] * (s64)g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process); +void recMULTsuper(int info, int upper, int process) +{ + assert( !(info&PROCESS_EE_MMX) ); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + recWritebackHILO(info, 1, upper); +} + +//void recMULT_process(int info, int process) +//{ +// if( EEINST_ISLIVEMMX(XMMGPR_HI) || !(info&PROCESS_EE_MMX) ) { +// recMULTsuper(info, 0, process); +// } +// else { +// // EEREC_D isn't set +// int mmregd; +// +// if( _Rd_ ) { +// assert(EEREC_D == 0); +// mmregd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); +// +// if( mmregd < 0 ) { +// if( !(process&PROCESS_CONSTS) && ((g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rs_)) ) { +// _freeMMXreg(EEREC_S); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_S].inuse = 1; +// mmxregs[EEREC_S].reg = _Rd_; +// mmxregs[EEREC_S].mode = MODE_WRITE; +// mmregd = EEREC_S; +// } +// else if( !(process&PROCESS_CONSTT) && ((g_pCurInstInfo->regs[_Rt_]&EEINST_LASTUSE)||!EEINST_ISLIVEMMX(_Rt_)) ) { +// _freeMMXreg(EEREC_T); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_T].inuse = 1; +// mmxregs[EEREC_T].reg = _Rd_; +// mmxregs[EEREC_T].mode = MODE_WRITE; +// mmregd = EEREC_T; +// } +// else mmregd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); +// } +// +// info |= PROCESS_EE_SET_D(mmregd); +// } +// recMULTUsuper(info, 0, process); +// } +// +// // sometimes _Rd_ can be const +// if( _Rd_ ) _eeOnWriteReg(_Rd_, 1); +//} + +void recMULT_(int info) +{ + //recMULT_process(info, 0); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, 0); + } + else recMULTUsuper(info, 0, 0); +} + +void recMULT_consts(int info) +{ + //recMULT_process(info, PROCESS_CONSTS); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTS); + } + else recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULT_constt(int info) +{ + //recMULT_process(info, PROCESS_CONSTT); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTT); + } + else recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't set XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI +EERECOMPILE_CODE0(MULT, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// MULTU +void recMULTU_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process) +{ + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( (info & PROCESS_EE_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + + if( !_Rd_ ) { + // need some temp reg + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + assert( EEREC_D == 0 ); + info |= PROCESS_EE_SET_D(t0reg); + } + + if( process & PROCESS_CONSTS ) { + u32* ptempmem = _eeGetConstReg(_Rs_); + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else if( process & PROCESS_CONSTT ) { + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else { + if( EEREC_D == EEREC_S ) PMULUDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PMULUDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQRtoR(EEREC_D, EEREC_T); + } + } + + recWritebackHILOMMX(info, EEREC_D, 1, upper); + + if( !_Rd_ ) _freeMMXreg(EEREC_D); + return; + } + + if( info & PROCESS_EE_MMX ) { + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_].UL[0], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + _deleteMMXreg(MMX_GPR+_Rd_, 0); + } + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_S); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EAX, EEREC_S); + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + } + + recWritebackHILO(info, 1, upper); +} + +void recMULTU_(int info) +{ + recMULTUsuper(info, 0, 0); +} + +void recMULTU_consts(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULTU_constt(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't specify XMMINFO_WRITELO or XMMINFO_WRITEHI, that is taken care of +EERECOMPILE_CODE0(MULTU, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULT1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULT1_(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, 0); + } + else recMULTUsuper(info, 1, 0); +} + +void recMULT1_consts(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTS); + } + else recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULT1_constt(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTT); + } + else recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULT1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULTU1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULTU1_(int info) +{ + recMULTUsuper(info, 1, 0); +} + +void recMULTU1_consts(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULTU1_constt(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// DIV +void recDIV_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVsuper(int info, int sign, int upper, int process) +{ + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTT ) { + if( !g_cpuConstRegs[_Rt_].UL[0] ) + return; + MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] ); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + } + + if( process & PROCESS_CONSTS ) + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + + if( sign ) { + CDQ(); + IDIV32R( ECX ); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R( ECX ); + } + if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] ); + + // need to execute regardless of bad divide + recWritebackHILO(info, 0, upper); +} + +void recDIV_(int info) +{ + recDIVsuper(info, 1, 0, 0); +} + +void recDIV_consts(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTS); +} + +void recDIV_constt(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +//// DIVU +void recDIVU_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVU_(int info) +{ + recDIVsuper(info, 0, 0, 0); +} + +void recDIVU_consts(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTS); +} + +void recDIVU_constt(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +void recDIV1_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIV1_(int info) +{ + recDIVsuper(info, 1, 1, 0); +} + +void recDIV1_consts(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTS); +} + +void recDIV1_constt(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT); + +void recDIVU1_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIVU1_(int info) +{ + recDIVsuper(info, 0, 1, 0); +} + +void recDIVU1_consts(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTS); +} + +void recDIVU1_constt(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU1, XMMINFO_READS|XMMINFO_READT); + +//do EEINST_SETSIGNEXT +REC_FUNC( MADD, _Rd_ ); + +static PCSX2_ALIGNED16(u32 s_MaddMask[]) = { 0x80000000, 0, 0x80000000, 0 }; + +void recMADDU() +{ + _eeOnWriteReg(_Rd_, 1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + u64 result = ((u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + + // dadd + MOV32MtoR( EAX, (int)&cpuRegs.LO.UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.HI.UL[ 0 ] ); + ADD32ItoR( EAX, (u32)result&0xffffffff ); + ADC32ItoR( ECX, (u32)(result>>32) ); + CDQ(); + if( _Rd_) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); + return; + } + + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if ( GPR_IS_CONST1(_Rt_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + MOV32RtoR( ECX, EDX ); + ADD32MtoR( EAX, (u32)&cpuRegs.LO.UL[0] ); + ADC32MtoR( ECX, (u32)&cpuRegs.HI.UL[0] ); + CDQ(); + if( _Rd_ ) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); +} + +void recMADD1() +{ + SysPrintf("MADD1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + REC_FUNC_INLINE( MADD1, _Rd_ ); +} + +void recMADDU1() +{ + SysPrintf("MADDU1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + REC_FUNC_INLINE( MADDU1, _Rd_ ); +} + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MULT1, _Rd_ ); +REC_FUNC( MULTU1, _Rd_ ); +REC_FUNC( DIV1, _Rd_ ); +REC_FUNC( DIVU1, _Rd_ ); + +REC_FUNC( MADD, _Rd_ ); +REC_FUNC( MADDU, _Rd_ ); +REC_FUNC( MADD1, _Rd_ ); +REC_FUNC( MADDU1, _Rd_ ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.h new file mode 100644 index 0000000..243fd5c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.c b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.c new file mode 100644 index 0000000..3f3c6bd --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.c @@ -0,0 +1,1349 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#elif defined(EE_CONST_PROP) + +//// SLL +void recSLL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << _Sa_); +} + +void recSLLs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( g_pCurInstInfo->regs[_Rd_]&EEINST_MMX ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(rdreg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLL_(int info) +{ + recSLLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SLL); + +//// SRL +void recSRL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> _Sa_); +} + +void recSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + // rdreg already sign extended + PSLLQItoR(rdreg, 32); + PSRLQItoR(rdreg, 32+sa); +// t0reg = _allocMMXreg(-1, MMX_TEMP, 0); +// +// // it is a signed shift +// PSRLDItoR(rdreg, sa); +// MOVQRtoR(t0reg, rdreg); +// PSRADItoR(t0reg, 31); +// +// take lower dword of rdreg and lower dword of t0reg +// PUNPCKLDQRtoR(rdreg, t0reg); +// _freeMMXreg(t0reg); + } +} + +void recSRL_(int info) +{ + recSRLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRL); + +//// SRA +void recSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> _Sa_); +} + +void recSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SAR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(rdreg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(t0reg, rdreg); + + // swap regs + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recSRA_(int info) +{ + recSRAs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRA); + +//////////////////////////////////////////////////// +void recDSLL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << _Sa_); +} + +void recDSLLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa); +} + +void recDSLL_(int info) +{ + recDSLLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL); + +//////////////////////////////////////////////////// +void recDSRL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> _Sa_); +} + +void recDSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa); +} + +void recDSRL_(int info) +{ + recDSRLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL); + +//// DSRA +void recDSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> _Sa_); +} + +void recDSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLQItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + PSRADItoR(t0reg, sa); + PSRLQItoR(rdreg, sa); + + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + } +} + +void recDSRA_(int info) +{ + recDSRAs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA); + +///// DSLL32 +void recDSLL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (_Sa_+32)); +} + +void recDSLL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa+32); +} + +void recDSLL32_(int info) +{ + recDSLL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL32); + +//// DSRL32 +void recDSRL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (_Sa_+32)); +} + +void recDSRL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa+32); +} + +void recDSRL32_(int info) +{ + recDSRL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL32); + +//// DSRA32 +void recDSRA32_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> (_Sa_+32)); +} + +void recDSRA32s_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ( ); + if ( sa != 0 ) SAR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, 31); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + if( sa ) PSRADItoR(rdreg, sa); + PUNPCKHDQRtoR(rdreg, rdreg); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + if( sa ) { + PSRADItoR(rdreg, sa); + PSRADItoR(t0reg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + // better timing + PSRADItoR(rdreg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(t0reg, rdreg); + + // swap + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recDSRA32_(int info) +{ + recDSRA32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA32); + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +PCSX2_ALIGNED16(u32 s_sa[4]) = {0x1f, 0, 0x3f, 0}; + +int recSetShiftV(int info, int* rsreg, int* rtreg, int* rdreg, int* rstemp, int forcemmx, int shift64) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + *rtreg = EEREC_T; + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_)) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else if( forcemmx || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + *rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + else { + return 0; + } + + if( *rtreg != *rdreg ) MOVQRtoR(*rdreg, *rtreg); + return 1; +} + +void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift64) +{ + if( info & PROCESS_EE_MMX ) { + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVEMMX(_Rs_) ) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else { + _addNeededMMXreg(MMX_GPR+_Rd_); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + + _flushConstReg(_Rt_); +} + +void recMoveSignToRd(int info) +{ + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + + if( info & PROCESS_EE_MMX ) { + mmxregs[EEREC_D].inuse = 0; + } +} + +//// SLLV +void recSLLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSLLV_consts(int info) +{ + recSLLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info & PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRLV +void recSRLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRLV_consts(int info) +{ + recSRLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRAV +void recSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRAV_consts(int info) +{ + recSRAs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSLLV +void recDSLLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSLLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSLLs_(info, sa); + else recDSLL32s_(info, sa-32); +} + +void recDSLLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRLV +void recDSRLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRLs_(info, sa); + else recDSRL32s_(info, sa-32); +} + +void recDSRLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRAV +void recDSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s64)(g_cpuConstRegs[_Rt_].SD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRAV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRAs_(info, sa); + else recDSRA32s_(info, sa-32); +} + +void recDSRAV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recDSRA( void ) +{ + if( !_Rd_ ) return; //? + + if ( _Sa_ != 0 ) { + // it is a signed shift + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoR(MM1, MM0); + PSRADItoR(MM0, _Sa_); + PSRLQItoR(MM1, _Sa_); + + PUNPCKHDQRtoR(MM0, MM0); // shift to lower + // take lower dword of MM1 and lower dword of MM0 + + PUNPCKLDQRtoR(MM1, MM0); + + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM1); + } + else { + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSRA32(void) +{ + if( !_Rd_ ) return; //? + + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ(); + + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_ ); + } + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); +} + +//////////////////////////////////////////////////// +void recSLL( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHL32ItoR( EAX, _Sa_ ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHR32ItoR( EAX, _Sa_); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRA( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSLL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSLLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSRLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSLL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSLLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX,(int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSRLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +//////////////////////////////////////////////////// + + +//////////////////////////////////////////////////// +void recSLLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRAV( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +static u64 _sa = 0; +void recDSLLV( void ) +{ + if ( ! _Rd_ ) return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSLLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) +{ + if ( ! _Rd_ ) return; + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSRLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} +//////////////////////////////////////////////////////////////// +void recDSRAV( void ) +{ + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if ( _Rs_ != 0 ) { + PXORRtoR(MM1, MM1); + + // calc high bit + MOVQRtoR(MM2, MM0); + PUNPCKHDQRtoR(MM2, MM2); // shift to lower + PCMPGTDRtoR(MM1, MM2); + + // it is a signed shift + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOVD32RtoMMX(MM2, EAX); // amount to shift + NOT32R(EAX); + ADD32ItoR(EAX, 65); + + // right logical shift + PSRLQRtoR(MM0, MM2); + + // shift highest bit, 64 - eax + MOVD32RtoMMX(MM2, EAX); + PSLLQRtoR(MM1, MM2); // highest bits + + PORRtoR(MM0, MM1); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.h b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.h new file mode 100644 index 0000000..b7b3592 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-32/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/Makefile.am b/branches/pcsx2_0.9.2/x86/ix86-64/Makefile.am new file mode 100644 index 0000000..6bbf3da --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/Makefile.am @@ -0,0 +1,3 @@ +noinst_LIBRARIES = libx86-64recomp.a + +libx86_64recomp_a_SOURCES = ir5900Arit.c \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.c new file mode 100644 index 0000000..482ce5d --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.c @@ -0,0 +1,542 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD32RtoR(rdreg, rsreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + ADD32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Rt_ != 0) { + ADD32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + ADD64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + ADD64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + ADD64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + SUB32RtoR(t0reg, rdreg); + MOV32RtoR(rdreg, t0reg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rsreg); + SUB32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) + { + SUB32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) { + int rdreg; + int rsreg; + int rtreg; + int t0reg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SUB64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + t0reg = _allocTempX86reg(-1); + + MOV64RtoR(t0reg, rsreg); + SUB64RtoR(t0reg, rdreg); + MOV64RtoR(rdreg, t0reg); + + _freeX86reg(t0reg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + SUB64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + SUB64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + AND64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + AND64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); +#else + if (_Rt_ == _Rd_) { // Rd&= Rs + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else if (_Rs_ == _Rd_) { // Rd&= Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + AND64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else { // Rd = Rs & Rt + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) { + XOR64RtoR(RAX, RAX); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[0], RAX ); + } else if ( _Rs_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else if ( _Rt_ == 0 ) + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else + { + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +#endif +} + +//////////////////////////////////////////////////// +void recXOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rtreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + XOR64RtoR(rdreg, rsreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + XOR64RtoR(rdreg, rtreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + XOR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recNOR( void ) { + int rdreg; + int rsreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_READ | MODE_WRITE); + + OR64RtoR(rdreg, rsreg); + NOT64R(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rsreg); + OR64RtoR(rdreg, rtreg); + NOT64R(rdreg); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + NOT64R(RAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + +#endif +} + +//////////////////////////////////////////////////// +void recSLT( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) { + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + MOV64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + SBB64RtoR(EAX, EAX); + NEG64R (EAX); + MOV64RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.h new file mode 100644 index 0000000..5fcd64d --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.c new file mode 100644 index 0000000..a9d1223 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.c @@ -0,0 +1,314 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV32ItoR(rtreg, _Imm_); + ADD32RtoR(rtreg, rsreg); + SHL64ItoR(rtreg, 32); + SAR64ItoR(rtreg, 32); + } + } + + _clearNeededX86regs(); + +#else + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Imm_ != 0) { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +#endif +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + ADD64ItoR(rtreg, _Imm_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64ItoR(rtreg, _Imm_); + ADD64RtoR(rtreg, rsreg); + } + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); + +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETB8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + { + return; + } +#ifdef ENABLE_REGCACHING + _freeX86regs(); +#endif + + MOV64MtoR(RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64ItoR(RAX, _Imm_); + SETL8R (EAX); + AND64ItoR(EAX, 0xff); + MOV64RtoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recANDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + AND64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + AND64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if ( _ImmU_ != 0 ) { + if (_Rs_ == _Rt_) { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + AND32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_ ); + } else { + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + else + { + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } +#endif +} + +//////////////////////////////////////////////////// +void recORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + OR64ItoR(rtreg, _ImmU_); + } else + if (_Rs_ == 0) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + if (_Imm_ == 0) { + MOV64RtoR(rtreg, rsreg); + } else { + MOV64RtoR(rtreg, rsreg); + OR64ItoR(rtreg, _ImmU_); + } + } + + _clearNeededX86regs(); + +#else + + if (_Rs_ == _Rt_) { + OR32ItoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], _ImmU_ ); + } else { + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + OR64ItoR( RAX, _ImmU_ ); + } + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + } + +#endif +} + +//////////////////////////////////////////////////// +void recXORI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rt_ == _Rs_) { + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE | MODE_READ); + XOR64ItoR(rtreg, _ImmU_); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + + MOV64RtoR(rtreg, rsreg); + XOR64ItoR(rtreg, _ImmU_); + } + + _clearNeededX86regs(); + +#else + + MOV64MtoR( RAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + XOR64ItoR( RAX, _ImmU_ ); + MOV64RtoM( (u32)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + +#endif +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.h new file mode 100644 index 0000000..4bd7a0c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.c new file mode 100644 index 0000000..6de85ad --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.c @@ -0,0 +1,341 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + + if ( _Rs_ == _Rt_ ) + { + SetBranchImm( _Imm_ * 4 + pc/*, 1*/ ); + } + else + { + u32 branchTo = _Imm_ * 4 + pc; + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + if ( _Rs_ == _Rt_ ) + { + return; + } + + // SetFPUstate(); + MOV64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 2 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//#if 0 +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j8Ptr[ 1 ] = JG8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JNZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j8Ptr[ 1 ] = JL8( 0 ); + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j8Ptr[ 2 ] = JZ8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 3 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 1 ] ); + x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 3 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBLTZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = _Imm_ * 4 + pc; + + CMP32ItoM( (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + MOV32ItoM( (u32)&target, branchTo ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + MOV32ItoM( (u32)&target, pc + 4 ); + x86SetJ8( j8Ptr[ 1 ] ); + + SetBranch( ); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLEZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + j8Ptr[ 2 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 2 ] ); + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j8Ptr[ 1 ] = JNE8( 0 ); + + MOV32ItoM( (u32)&cpuRegs.pc, pc + 4 ); + iRet( TRUE ); + + x86SetJ8( j8Ptr[ 0 ] ); + x86SetJ8( j8Ptr[ 1 ] ); + + MOV32ItoM( (u32)&target, _Imm_ * 4 + pc ); + + SetBranch( ); +} + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(); + CALLFunc( (u32)BGEZL ); + branch = 2; +} +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.h new file mode 100644 index 0000000..3370b8a --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.c new file mode 100644 index 0000000..d879ec4 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 0 ], pc + 4 ); + MOV32ItoM( (u32)&cpuRegs.GPR.r[31].UL[ 1 ], 0 ); + + SetBranchImm(_Target_ * 4 + ( pc & 0xf0000000 )/*, 0*/); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_ ); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + if ( _Rd_ ) { + MOV64ItoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], pc + 4 ); + } + + SetBranchReg( _Rs_ ); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.h new file mode 100644 index 0000000..d35f87c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.c new file mode 100644 index 0000000..3642530 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.c @@ -0,0 +1,554 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "VU0.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +#else +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +u64 retValue; +u64 dummyValue[ 4 ]; + +//////////////////////////////////////////////////// +void recLB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead8RS ); +} + +//////////////////////////////////////////////////// +void recLBU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead8RU ); +} + +//////////////////////////////////////////////////// +void recLH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + iFlushCall(); + CALLFunc( (u32)memRead16RS ); +} + +//////////////////////////////////////////////////// +void recLHU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead16RU ); +} + +void tests() { + SysPrintf("Err\n"); +} + +//////////////////////////////////////////////////// +void recLW( void ) { + int rsreg; + int rtreg; + int t0reg; + int t1reg; + int t2reg; + +#if 0 +//def ENABLE_REGCACHING + + _freeX86regs(); + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + t0reg = _allocTempX86reg(-1); + t1reg = _allocTempX86reg(-1); + t2reg = _allocTempX86reg(-1); + + MOV32RtoR(t0reg, rsreg); + if (_Imm_ != 0) { + ADD32ItoR(t0reg, _Imm_); + } + MOV32RtoR(t2reg, t0reg); + SHR32ItoR(t0reg, 12); + + MOV64MtoR(t1reg, (u32)&memLUTR); + MOV64RmStoR(t1reg, t1reg, t0reg, 3); + + CMP64ItoR(t1reg, 0x10); + j8Ptr[0] = JL8(0); + + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + AND32ItoR(t2reg, 0xfff); + LogX86(); + MOV64RmStoR(rtreg, t1reg, t2reg, 0); + _clearNeededX86regs(); + _freeX86regs(); + +// j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +// x86SetJ8(j8Ptr[1]); + +#else + + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( EDI, _Imm_ ); + } + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RS ); + +#endif +} + +//////////////////////////////////////////////////// +void recLWU( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead32RU ); +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LWR ); +} + +//////////////////////////////////////////////////// +void recLD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + if ( _Rt_ ) + { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead64 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + AND32ItoR( EDI, ~0xf ); + + if ( _Rt_ ) { + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV32ItoR( ESI, &dummyValue ); + } + CALLFunc( (u32)memRead128 ); +} + +//////////////////////////////////////////////////// +void recSB( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite16 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV32MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite32 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + MOV64MtoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite64 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) { + iFlushCall(); + + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + CALLFunc( (u32)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { + iFlushCall(); + + MOV32MtoR( EDI, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EDI, _Imm_ ); + } + AND32ItoR( EDI, ~0xf ); + + MOV32ItoR( ESI, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (u32)memWrite128 ); +} +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, LWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + if ( Config.Regcaching ) + { + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.code, cpuRegs.code ); + GRec_Instruction( GREC_INST_MOVIMM32, &cpuRegs.pc, pc ); + + GRec_Instruction( GREC_INST_CALL, SWC1, NULL, 0, GREC_TRUE ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (u32)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite32 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "LQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (u32)&dummyValue ); + } + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memRead128 ); + ADD32ItoR( ESP, 8 ); + } +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + if ( Config.Regcaching ) + { + GRecAssert( GREC_FALSE, "SQC2 not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (u32)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + iFlushCall(); + CALLFunc( (u32)memWrite128 ); + ADD32ItoR( ESP, 8 ); + } +} +*/ +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.h new file mode 100644 index 0000000..1a5b99e --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900LoadStore.h @@ -0,0 +1,56 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSQ( void ); +void recSDL( void ); +void recSDR( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.c new file mode 100644 index 0000000..46302a6 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.c @@ -0,0 +1,256 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#else +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLUI( void ) { + int rtreg; + + if (!_Rt_) return; + +#ifdef ENABLE_REGCACHING + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_WRITE); + MOV64ItoR(rtreg, (s32)(_Imm_ << 16)); + _clearNeededX86regs(); +#else + MOV64ItoM((u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (s32)(_Imm_ << 16)); +#endif +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecLog( "MFHI: PC: 0x%.8X, RD: %d, x86Ptr: 0x%.8x\n", pc, _Rd_, x86Ptr ); + + GRec_Instruction( GREC_INST_MOV64, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.HI.UD[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MFLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + } +} +*/ +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTHI not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + if ( Config.Regcaching && ConfigNewRec ) + { + GRecAssert( GREC_FALSE, "MTLO not implemented" ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOVQMtoR( MM0, (u32)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (u32)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + } +} + +*/ +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ +/* +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVZ: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_Z, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( Config.Regcaching ) + { + GRecLog( "MOVN: PC: 0x%.8X, RD: %d, RT: %d, RS: %d, x86Ptr: 0x%.8x\n", + pc, _Rd_, _Rt_, _Rs_, x86Ptr ); + + GRec_Instruction( GREC_INST_CMPIMM64, &cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], (GRec_u64)0 ); + GRec_Instruction( GREC_INST_MOVCC64, GREC_CMP_NZ, &cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], &cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else + { + if ( Config.Regcaching ) + { + GRecReleaseAll( ); + } + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + } +} +*/ +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.h new file mode 100644 index 0000000..ae501e3 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.c new file mode 100644 index 0000000..0d84b8e --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.c @@ -0,0 +1,138 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC(DIV); +REC_FUNC(DIVU); + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (u32)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); +} + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.h new file mode 100644 index 0000000..243fd5c --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.c b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.c new file mode 100644 index 0000000..3950c07 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.c @@ -0,0 +1,761 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#else + + +//////////////////////////////////////////////////// +void recDSRA( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SAR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRA32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SAR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SAR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHL32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SHR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHR32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +#endif +} + +//////////////////////////////////////////////////// +void recSRA(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SAR32ItoR(rdreg, _Sa_); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(rdreg, rtreg); + if (_Sa_) { + SAR32ItoR(rdreg, _Sa_); + } + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHL64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHL64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + if (_Sa_) { + SHR64ItoR(rdreg, _Sa_); + } + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLL32(void) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHL64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHL64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHL64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) { + int rdreg; + int rtreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + if (_Rd_ == _Rt_) { + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + SHR64ItoR(rdreg, _Sa_ + 32); + } else { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV64RtoR(rdreg, rtreg); + SHR64ItoR(rdreg, _Sa_ + 32); + } + + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + + +//////////////////////////////////////////////////// +void recSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV32RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR32CLtoR(rdreg); + SHL64ItoR(rdreg, 32); + SAR64ItoR(rdreg, 32); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV32MtoR( EAX, (u32)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (u32)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSLLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHL64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHL64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SHR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +//////////////////////////////////////////////////// +void recDSRAV( void ) { + int rdreg; + int rsreg; + int rtreg; + int clreg; + + if (!_Rd_) return; + +#ifdef ENABLE_REGCACHING + + clreg = _allocTempX86reg(ECX); + if (_Rd_ == _Rs_) { + _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rdreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else + if (_Rd_ == _Rt_) { + _addNeededGPRtoX86reg(_Rs_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE | MODE_READ); + + MOV32RtoR(clreg, rsreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } else { + _addNeededGPRtoX86reg(_Rs_); _addNeededGPRtoX86reg(_Rt_); + _addNeededGPRtoX86reg(_Rd_); + rsreg = _allocGPRtoX86reg(-1, _Rs_, MODE_READ); + rtreg = _allocGPRtoX86reg(-1, _Rt_, MODE_READ); + rdreg = _allocGPRtoX86reg(-1, _Rd_, MODE_WRITE); + + MOV32RtoR(clreg, rsreg); + MOV64RtoR(rdreg, rtreg); + AND32ItoR(clreg, 0x1f); + SAR64CLtoR(rdreg); + } + + _freeX86reg(clreg); + _clearNeededX86regs(); +#else + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SAR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +#endif +} + +#endif + diff --git a/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.h b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.h new file mode 100644 index 0000000..b7b3592 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86-64/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/branches/pcsx2_0.9.2/x86/ix86/Makefile.am b/branches/pcsx2_0.9.2/x86/ix86/Makefile.am new file mode 100644 index 0000000..e4cf70f --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/Makefile.am @@ -0,0 +1,4 @@ +INCLUDES = -I../ -I../../ +noinst_LIBRARIES = libix86.a + +libix86_a_SOURCES = ix86_3dnow.c ix86.c ix86_cpudetect.c ix86_fpu.c ix86.h ix86_mmx.c ix86_sse.c \ No newline at end of file diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86.c b/branches/pcsx2_0.9.2/x86/ix86/ix86.c new file mode 100644 index 0000000..dfa9c2e --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86.c @@ -0,0 +1,3133 @@ +/* + * ix86 core v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +#include +#include +#include +#include "ix86.h" + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +extern void SysPrintf(char *fmt, ...); + +// This function is just for rec debugging purposes +void CheckX86Ptr( void ) +{ +} + +void write64( u64 val ) +{ +#ifdef _DEBUG + CheckX86Ptr( ); +#endif + + *(u64*)x86Ptr = val; + x86Ptr += 8; +} + +void Rex( int w, int r, int x, int b ) +{ + assert(0); + write8( 0x40 | (w << 3) | (r << 2) | (x << 1) | (b) ); +} + +void ModRM( int mod, int rm, int reg ) +{ + write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) ); +} + +void SibSB( int ss, int rm, int index ) +{ + write8( ( ss << 6 ) | ( rm << 3 ) | ( index ) ); +} + +void SET8R( int cc, int to ) +{ + write8( 0x0F ); + write8( cc ); + write8( 0xC0 | ( to ) ); +} + +u8* J8Rel( int cc, int to ) +{ + write8( cc ); + write8( to ); + return x86Ptr - 1; +} + +u16* J16Rel( int cc, u32 to ) +{ + write16( 0x0F66 ); + write8( cc ); + write16( to ); + return (u16*)( x86Ptr - 2 ); +} + +u32* J32Rel( int cc, u32 to ) +{ + write8( 0x0F ); + write8( cc ); + write32( to ); + return (u32*)( x86Ptr - 4 ); +} + +void CMOV32RtoR( int cc, int to, int from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 3, to, from ); +} + +void CMOV32MtoR( int cc, int to, u32 from ) +{ + write8( 0x0F ); + write8( cc ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////////////////////// +void x86SetPtr( char* ptr ) +{ + x86Ptr = ptr; +} + +//////////////////////////////////////////////////// +void x86Shutdown( void ) +{ +} + +//////////////////////////////////////////////////// +void x86SetJ8( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + + if( ((u32)x86Ptr&0xf) > 4 ) { + + u32 newjump = jump + 16-((u32)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +void x86SetJ16( u16 *j16 ) +{ + // doesn't work + u32 jump = ( x86Ptr - (s8*)j16 ) - 2; + + if ( jump > 0x7fff ) { + assert(0); + SysPrintf( "j16 greater than 0x7fff!!\n" ); + } + *j16 = (u16)jump; +} + +void x86SetJ16A( u16 *j16 ) +{ + if( ((u32)x86Ptr&0xf) > 4 ) { + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + x86SetJ16(j16); +} + +//////////////////////////////////////////////////// +void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (s8*)j32 ) - 4; +} + +void x86SetJ32A( u32* j32 ) +{ + while((u32)x86Ptr&0xf) *x86Ptr++ = 0x90; + x86SetJ32(j32); +} + +//////////////////////////////////////////////////// +void x86Align( int bytes ) +{ + // fordward align + x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) ); +} + +/********************/ +/* IX86 intructions */ +/********************/ + +void STC( void ) +{ + write8( 0xF9 ); +} + +void CLC( void ) +{ + write8( 0xF8 ); +} + +//////////////////////////////////// +// mov instructions / +//////////////////////////////////// + +/* mov r64 to r64 */ +void MOV64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r64 to m64 */ +void MOV64RtoM( u64 to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( (u32)MEMADDR(to, 4) ); +} + +/* mov m64 to r64 */ +void MOV64MtoR( x86IntRegType to, u64 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( (u32)MEMADDR(from, 4) ); +} + +/* mov imm32 to m64 */ +void MOV64ItoM(u32 to, u32 from ) +{ + Rex(1, 0, 0, 0); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* mov imm32 to r64 */ +void MOV32Ito64R( x86IntRegType to, s32 from ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xC7 ); + ModRM( 0, 0, to ); + write32( from ); +} + +/* mov imm64 to r64 */ +void MOV64ItoR( x86IntRegType to, u64 from ) { + Rex(1, 0, 0, to >> 3); + write8( 0xB8 | (to & 0x7) ); + write64( from ); +} + +/* mov [r64] to r64 */ +void MOV64RmtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +/* mov [r64][r64*scale] to r64 */ +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov r64 to [r64] */ +void MOV64RtoRm( x86IntRegType to, x86IntRegType from ) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov r64 to [r64][r64*scale] */ +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + Rex(1, from >> 3, 0, to >> 3); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + + +/* mov r32 to r32 */ +void MOV32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r32 to m32 */ +void MOV32RtoM( u32 to, x86IntRegType from ) +{ + if (from > 7) { + Rex(0, from >> 3, 0, 0); + } + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m32 to r32 */ +void MOV32MtoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r32 */ +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + if (from == ESP) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x8B ); + ModRM( 0, to, from ); + } +} + +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) { + if (from > 7 || to > 7) { + Rex(0, to >> 3, 0, from >> 3); + } + + write8( 0x8B ); + + if( offset == 0 ) { + if (from == ESP) { + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 0, to, from ); + } + } + else if( offset < 128 ) { + if (from == ESP) { + ModRM( 1, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 1, to, from ); + } + write8(offset); + } + else { + if (from == ESP) { + ModRM( 2, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + ModRM( 2, to, from ); + } + write32(offset); + } +} + +/* mov [r32][r32*scale] to r32 */ +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +/* mov r32 to [r32] */ +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ) { + if (from > 7 || to > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + if (to == ESP) { + write8( 0x89 ); + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } else { + write8( 0x89 ); + ModRM( 0, from, to ); + } +} + +/* mov r32 to [r32][r32*scale] */ +void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov imm32 to r32 */ +void MOV32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB8 | (to & 0x7) ); + write32( from ); +} + +/* mov imm32 to m32 */ +void MOV32ItoM(u32 to, u32 from ) +{ + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// mov imm32 to [r32+off] +void MOV32ItoRmOffset( x86IntRegType to, u32 from, u32 offset) +{ + write8( 0xC7 ); + + if( to == ESP ) { + + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 ) { + ModRM( 1, 0, 4 ); + ModRM( 0, ESP, 4 ); + write8(offset); + } + else { + ModRM( 2, 0, 4 ); + ModRM( 0, ESP, 4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, 0, to ); + } + else if( offset < 128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } + + write32(from); +} + +// mov r32 to [r32+off] +void MOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x89 ); + + if (to == ESP) { + if( offset == 0 ) { + ModRM( 0, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + else if( offset < 128 ) { + ModRM( 1, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write8(offset); + } + else { + ModRM( 2, from, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + } + else { + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +/* mov r16 to m16 */ +void MOV16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m16 to r16 */ +void MOV16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOV16RmtoR( x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 0, to, from ); +} + +void MOV16RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write8( 0x66 ); + write8( 0x8B ); + ModRM( 2, to, from ); + write32( offset ); +} + +void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) +{ + write16( 0x8B66 ); + ModRM( 0, to, 0x4 ); + ModRM( scale, from1, 5); + write32(from2); +} + +void MOV16RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, from, to ); +} + +/* mov imm16 to m16 */ +void MOV16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + write8( 0x66 ); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +void MOV16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write16( 0xB866 | ((to & 0x7)<<8) ); + write16( from ); +} + +// mov imm16 to [r16+off] +void MOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset) +{ + assert( to != ESP ); + write16( 0xC766 ); + ModRM( 2, 0, to ); + write32(offset); + write16(from); +} + +// mov r16 to [r16+off] +void MOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write16( 0x8966 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* mov r8 to m8 */ +void MOV8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x88 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m8 to r8 */ +void MOV8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x8A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r8 */ +void MOV8RmtoR(x86IntRegType to, x86IntRegType from) +{ + write8( 0x8A ); + ModRM( 0, to, from ); +} + +void MOV8RmtoROffset(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8( 0x8A ); + ModRM( 2, to, from ); + write32(offset); +} + +void MOV8RtoRm(x86IntRegType to, x86IntRegType from) +{ + write8( 0x88 ); + ModRM( 0, from, to ); +} + +/* mov imm8 to m8 */ +void MOV8ItoM( u32 to, u8 from ) +{ + write8( 0xC6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +// mov imm8 to r8 +void MOV8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xB0 | (to & 0x7) ); + write8( from ); +} + +// mov imm8 to [r8+off] +void MOV8ItoRmOffset( x86IntRegType to, u8 from, u32 offset) +{ + assert( to != ESP ); + write8( 0xC6 ); + ModRM( 2, 0, to ); + write32(offset); + write8(from); +} + +// mov r8 to [r8+off] +void MOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, u32 offset) +{ + assert( to != ESP ); + write8( 0x88 ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movsx r8 to r32 */ +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBE0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m8 to r32 */ +void MOVSX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xBE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movsx r16 to r32 */ +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 3, to, from ); +} + +void MOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, from ); +} + +void MOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xBF0F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movsx m16 to r32 */ +void MOVSX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xBF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r8 to r32 */ +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB60F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB60F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m8 to r32 */ +void MOVZX32M8toR( x86IntRegType to, u32 from ) +{ + write16( 0xB60F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movzx r16 to r32 */ +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 3, to, from ); +} + +void MOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xB70F ); + ModRM( 0, to, from ); +} + +void MOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0xB70F ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movzx m16 to r32 */ +void MOVZX32M16toR( x86IntRegType to, u32 from ) +{ + write16( 0xB70F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// mov r32+off to r32 +void MOV32RmOffsettoR( x86IntRegType to, x86IntRegType from, u32 offset) +{ + if( offset == 0 ) { + MOV32RtoR(to, from); + return; + } + + write8(0x8d); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8( offset ); + } + else { + ModRM( 2, to, from ); + write32( offset ); + } +} + +// mov r32+r32 to r32 +void MOV32Rm2toR( x86IntRegType to, x86IntRegType from1, x86IntRegType from2) +{ + write8(0x8d); + ModRM( 0, to, 4 ); + ModRM( 0, from1, from2 ); +} + +/* cmovbe r32 to r32 */ +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x46, to, from ); +} + +/* cmovbe m32 to r32*/ +void CMOVBE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x46, to, from ); +} + +/* cmovb r32 to r32 */ +void CMOVB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x42, to, from ); +} + +/* cmovb m32 to r32*/ +void CMOVB32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x42, to, from ); +} + +/* cmovae r32 to r32 */ +void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x43, to, from ); +} + +/* cmovae m32 to r32*/ +void CMOVAE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x43, to, from ); +} + +/* cmova r32 to r32 */ +void CMOVA32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x47, to, from ); +} + +/* cmova m32 to r32*/ +void CMOVA32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x47, to, from ); +} + +/* cmovo r32 to r32 */ +void CMOVO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x40, to, from ); +} + +/* cmovo m32 to r32 */ +void CMOVO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x40, to, from ); +} + +/* cmovp r32 to r32 */ +void CMOVP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4A, to, from ); +} + +/* cmovp m32 to r32 */ +void CMOVP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4A, to, from ); +} + +/* cmovs r32 to r32 */ +void CMOVS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x48, to, from ); +} + +/* cmovs m32 to r32 */ +void CMOVS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x48, to, from ); +} + +/* cmovno r32 to r32 */ +void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x41, to, from ); +} + +/* cmovno m32 to r32 */ +void CMOVNO32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x41, to, from ); +} + +/* cmovnp r32 to r32 */ +void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4B, to, from ); +} + +/* cmovnp m32 to r32 */ +void CMOVNP32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4B, to, from ); +} + +/* cmovns r32 to r32 */ +void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x49, to, from ); +} + +/* cmovns m32 to r32 */ +void CMOVNS32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x49, to, from ); +} + +/* cmovne r32 to r32 */ +void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x45, to, from ); +} + +/* cmovne m32 to r32*/ +void CMOVNE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x45, to, from ); +} + +/* cmove r32 to r32*/ +void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x44, to, from ); +} + +/* cmove m32 to r32*/ +void CMOVE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x44, to, from ); +} + +/* cmovg r32 to r32*/ +void CMOVG32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4F, to, from ); +} + +/* cmovg m32 to r32*/ +void CMOVG32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4F, to, from ); +} + +/* cmovge r32 to r32*/ +void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4D, to, from ); +} + +/* cmovge m32 to r32*/ +void CMOVGE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4D, to, from ); +} + +/* cmovl r32 to r32*/ +void CMOVL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4C, to, from ); +} + +/* cmovl m32 to r32*/ +void CMOVL32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4C, to, from ); +} + +/* cmovle r32 to r32*/ +void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + CMOV32RtoR( 0x4E, to, from ); +} + +/* cmovle m32 to r32*/ +void CMOVLE32MtoR( x86IntRegType to, u32 from ) +{ + CMOV32MtoR( 0x4E, to, from ); +} + +//////////////////////////////////// +// arithmetic instructions / +//////////////////////////////////// + +/* add imm32 to r64 */ +void ADD64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX) { + write8( 0x05 ); + } else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add m64 to r64 */ +void ADD64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* add r64 to r64 */ +void ADD64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add imm32 to r32 */ +void ADD32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, to >> 3, 0, 0); + } + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add imm32 to m32 */ +void ADD32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// add imm32 to [r32+off] +void ADD32ItoRmOffset( x86IntRegType to, u32 from, u32 offset) +{ + write8( 0x81 ); + + if( to == ESP ) { + + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 ) { + ModRM( 1, 0, 4 ); + ModRM( 0, ESP, 4 ); + write8(offset); + } + else { + ModRM( 2, 0, 4 ); + ModRM( 0, ESP, 4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, 0, to ); + } + else if( offset < 128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } + + write32(from); +} + +/* add r32 to r32 */ +void ADD32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add r32 to m32 */ +void ADD32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m32 to r32 */ +void ADD32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ) +{ + write16( 0x0366 ); + ModRM( 3, to, from ); +} + +/* add imm16 to r16 */ +void ADD16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +/* add imm16 to m16 */ +void ADD16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* add r16 to m16 */ +void ADD16RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m16 to r16 */ +void ADD16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x02 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* adc imm32 to r32 */ +void ADC32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x15 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 2, to ); + } + write32( from ); +} + +/* adc imm32 to m32 */ +void ADC32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* adc r32 to r32 */ +void ADC32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 3, from, to ); +} + +/* adc m32 to r32 */ +void ADC32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x13 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// adc r32 to m32 +void ADC32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x11 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r32 */ +void INC32R( x86IntRegType to ) +{ + write8( 0x40 + to ); +} + +/* inc m32 */ +void INC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r16 */ +void INC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x40 + to ); +} + +/* inc m16 */ +void INC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* sub imm32 to r64 */ +void SUB64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub r64 to r64 */ +void SUB64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m64 to r64 */ +void SUB64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sub imm32 to r32 */ +void SUB32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x2D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub imm32 to m32 */ +void SUB32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sub r32 to r32 */ +void SUB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + if (to > 7 || from > 7) { + Rex(0, from >> 3, 0, to >> 3); + } + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m32 to r32 */ +void SUB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// sub r32 to m32 +void SUB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x29 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ) +{ + write16( 0x2b66 ); + ModRM( 3, to, from ); +} + +/* sub imm16 to r16 */ +void SUB16ItoR( x86IntRegType to, u16 from ) { + write8( 0x66 ); + if ( to == EAX ) { + write8( 0x2D ); + } else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write16( from ); +} + +/* sub imm16 to m16 */ +void SUB16ItoM( u32 to, u16 from ) { + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* sub m16 to r16 */ +void SUB16MtoR( x86IntRegType to, u32 from ) { + write8( 0x66 ); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r64 to r64 */ +void SBB64RtoR( x86IntRegType to, x86IntRegType from ) { + Rex(1, to >> 3, 0, from >> 3); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR( x86IntRegType to, u32 from ) { + if ( to == EAX ) { + write8( 0x1D ); + } else { + write8( 0x81 ); + ModRM( 3, 3, to ); + } + write32( from ); +} + +/* sbb imm32 to m32 */ +void SBB32ItoM( u32 to, u32 from ) { + write8( 0x81 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sbb r32 to r32 */ +void SBB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb m32 to r32 */ +void SBB32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x1B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r32 to m32 */ +void SBB32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x19 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* dec r32 */ +void DEC32R( x86IntRegType to ) +{ + write8( 0x48 + to ); +} + +/* dec m32 */ +void DEC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* dec r16 */ +void DEC16R( x86IntRegType to ) +{ + write8( 0x66 ); + write8( 0x48 + to ); +} + +/* dec m16 */ +void DEC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 4, from ); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 5, from ); +} + +/* mul eax by m32 to edx:eax */ +void MUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xAF0F ); + ModRM( 3, to, from ); +} + +/* div eax by r32 to edx:eax */ +void DIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 6, from ); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 7, from ); +} + +/* div eax by m32 to edx:eax */ +void DIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r64 */ +void SHL64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 4, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl cl to r64 */ +void SHL64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +/* shr imm8 to r64 */ +void SHR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 5, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); +} + +/* shr cl to r64 */ +void SHR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +/* shl imm8 to r32 */ +void SHL32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl imm8 to m32 */ +void SHL32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shl cl to r32 */ +void SHL32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write16( 0xD166 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write16( 0xC166 ); + ModRM( 3, 4, to ); + write8( from ); +} + +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC0 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shr imm8 to r32 */ +void SHR32ItoR( x86IntRegType to, u8 from ) { + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* shr imm8 to m32 */ +void SHR32ItoM( u32 to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + write8( from ); + } +} + +/* shr cl to r32 */ +void SHR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC0 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* sar imm8 to r64 */ +void SAR64ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) + { + Rex(1, 0, 0, to >> 3); + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + Rex(1, 0, 0, to >> 3); + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar cl to r64 */ +void SAR64CLtoR( x86IntRegType to ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +/* sar imm8 to r32 */ +void SAR32ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar imm8 to m32 */ +void SAR32ItoM( u32 to, u8 from ) +{ + write8( 0xC1 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* sar cl to r32 */ +void SAR32CLtoR( x86IntRegType to ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( from == 1 ) + { + write16( 0xD166 ); + ModRM( 3, 7, to ); + return; + } + write16( 0xC166 ); + ModRM( 3, 7, to ); + write8( from ); +} + +void ROR32ItoR( x86IntRegType to,u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xc8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xc8 | to ); + write8( from ); + } +} + +void RCR32ItoR( x86IntRegType to, u8 from ) +{ + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xd8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xd8 | to ); + write8( from ); + } +} + +// shld imm8 to r32 +void SHLD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xA4 ); + ModRM( 3, from, to ); + write8( shift ); +} + +// shrd imm8 to r32 +void SHRD32ItoR( u32 to, u32 from, u8 shift ) +{ + write8( 0x0F ); + write8( 0xAC ); + ModRM( 3, from, to ); + write8( shift ); +} + +//////////////////////////////////// +// logical instructions / +//////////////////////////////////// + +/* or imm32 to r32 */ +void OR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x0D ); + } else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or m64 to r64 */ +void OR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* or r64 to r64 */ +void OR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x09 ); + ModRM( 3, from, to ); +} + + +/* or imm32 to r32 */ +void OR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or imm32 to m32 */ +void OR32ItoM(u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* or r32 to r32 */ +void OR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 3, from, to ); +} + +/* or r32 to m32 */ +void OR32RtoM(u32 to, x86IntRegType from ) +{ + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* or m32 to r32 */ +void OR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 3, from, to ); +} + +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x0D66 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 1, to ); + } + write16( from ); +} + +// or imm16 to m316 +void OR16ItoM( u32 to, u16 from ) +{ + write16( 0x8166 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* or m16 to r16 */ +void OR16MtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0B66 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to m16 +void OR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x0966 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 3, from, to ); +} + +// or r8 to m8 +void OR8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x08 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or imm8 to m8 +void OR8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// or m8 to r8 +void OR8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x0A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r64 */ +void XOR64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x35 ); + } else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor r64 to r64 */ +void XOR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor m64 to r64 */ +void XOR64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r32 */ +void XOR32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor imm32 to m32 */ +void XOR32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* xor r32 to r32 */ +void XOR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r16 to r16 */ +void XOR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r32 to m32 */ +void XOR32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* xor m32 to r32 */ +void XOR32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) { + write16( 0x3566 ); + } + else { + write16( 0x8166 ); + ModRM( 3, 6, to ); + } + write16( from ); +} + +// xor r16 to m16 +void XOR16RtoM( u32 to, x86IntRegType from ) +{ + write16( 0x3166 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and imm32 to r64 */ +void AND64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, 0, 0, to >> 3); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and m64 to r64 */ +void AND64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* and r64 to m64 */ +void AND64RtoM( u32 to, x86IntRegType from ) +{ + Rex(1, 0, 0, 0); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and r64 to r64 */ +void AND64RtoR( x86IntRegType to, x86IntRegType from ) +{ + Rex(1, from >> 3, 0, to >> 3); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and imm32 to r32 */ +void AND32ItoR( x86IntRegType to, u32 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and sign ext imm8 to r32 */ +void AND32I8toR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + write8( 0x83 ); + ModRM( 3, 0x4, to ); + write8( from ); +} + +/* and imm32 to m32 */ +void AND32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* and sign ext imm8 to m32 */ +void AND32I8toM( u32 to, u8 from ) +{ + write8( 0x83 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* and r32 to r32 */ +void AND32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and r32 to m32 */ +void AND32RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m32 to r32 */ +void AND32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x2366 ); + ModRM( 3, to, from ); +} + +/* and imm16 to r16 */ +void AND16ItoR( x86IntRegType to, u16 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write16( 0x2566 ); + } else { + write16( 0x8166 ); + ModRM( 3, 0x4, to ); + } + write16( from ); +} + +/* and imm16 to m16 */ +void AND16ItoM( u32 to, u16 from ) +{ + write8( 0x8166 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write16( from ); +} + +/* and r16 to m16 */ +void AND16RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m16 to r16 */ +void AND16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* and imm8 to r8 */ +void AND8ItoR( x86IntRegType to, u8 from ) +{ + if (to > 7) { + Rex(0, 0, 0, to >> 3); + } + if ( to == EAX ) { + write8( 0x24 ); + } else { + write8( 0x80 ); + ModRM( 3, 0x4, to ); + } + write8( from ); +} + +/* and imm8 to m8 */ +void AND8ItoM( u32 to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x22 ); + ModRM( 3, to, from ); +} + +/* and r8 to m8 */ +void AND8RtoM( u32 to, x86IntRegType from ) +{ + write8( 0x20 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m8 to r8 */ +void AND8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x22 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* not r64 */ +void NOT64R( x86IntRegType from ) +{ + Rex(1, 0, 0, from >> 3); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +/* not r32 */ +void NOT32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +// not m32 +void NOT32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r64 */ +void NEG64R( x86IntRegType from ) +{ + Rex(1, from >> 3, 0, 0); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +/* neg r32 */ +void NEG32R( x86IntRegType from ) +{ + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +void NEG32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r16 */ +void NEG16R( x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +u8* JMP( u32 to ) { + u32 jump = ( x86Ptr - (s8*)to ) - 1; + + if ( jump > 0x7f ) { + return (u8*)JMP32( to ); + } else { + return (u8*)JMP8( to ); + } +} + +/* jmp rel8 */ +u8* JMP8( u8 to ) +{ + write8( 0xEB ); + write8( to ); + return x86Ptr - 1; +} + +/* jmp rel32 */ +u32* JMP32( u32 to ) +{ + write8( 0xE9 ); + write32( to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32 */ +void JMP32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +// jmp m32 +void JMP32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4)); +} + +/* jmp r64 */ +void JMP64R( x86IntRegType to ) { + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +/* jp rel8 */ +u8* JP8( u8 to ) { + return J8Rel( 0x7A, to ); +} + +/* jnp rel8 */ +u8* JNP8( u8 to ) { + return J8Rel( 0x7B, to ); +} + +/* je rel8 */ +u8* JE8( u8 to ) { + return J8Rel( 0x74, to ); +} + +/* jz rel8 */ +u8* JZ8( u8 to ) +{ + return J8Rel( 0x74, to ); +} + +/* js rel8 */ +u8* JS8( u8 to ) +{ + return J8Rel( 0x78, to ); +} + +/* jns rel8 */ +u8* JNS8( u8 to ) +{ + return J8Rel( 0x79, to ); +} + +/* jg rel8 */ +u8* JG8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jge rel8 */ +u8* JGE8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jl rel8 */ +u8* JL8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* ja rel8 */ +u8* JA8( u8 to ) +{ + return J8Rel( 0x77, to ); +} + +u8* JAE8( u8 to ) +{ + return J8Rel( 0x73, to ); +} + +/* jb rel8 */ +u8* JB8( u8 to ) +{ + return J8Rel( 0x72, to ); +} + +/* jbe rel8 */ +u8* JBE8( u8 to ) +{ + return J8Rel( 0x76, to ); +} + +/* jle rel8 */ +u8* JLE8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jne rel8 */ +u8* JNE8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jnz rel8 */ +u8* JNZ8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jng rel8 */ +u8* JNG8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jnge rel8 */ +u8* JNGE8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* jnl rel8 */ +u8* JNL8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jnle rel8 */ +u8* JNLE8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jo rel8 */ +u8* JO8( u8 to ) +{ + return J8Rel( 0x70, to ); +} + +/* jno rel8 */ +u8* JNO8( u8 to ) +{ + return J8Rel( 0x71, to ); +} + +// jb rel8 +u16* JB16( u16 to ) +{ + return J16Rel( 0x82, to ); +} + +// jb rel32 +u32* JB32( u32 to ) +{ + return J32Rel( 0x82, to ); +} + +/* je rel32 */ +u32* JE32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jz rel32 */ +u32* JZ32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jg rel32 */ +u32* JG32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jge rel32 */ +u32* JGE32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jl rel32 */ +u32* JL32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jle rel32 */ +u32* JLE32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jae rel32 */ +u32* JAE32( u32 to ) +{ + return J32Rel( 0x83, to ); +} + +/* jne rel32 */ +u32* JNE32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jnz rel32 */ +u32* JNZ32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jng rel32 */ +u32* JNG32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jnge rel32 */ +u32* JNGE32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jnl rel32 */ +u32* JNL32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jnle rel32 */ +u32* JNLE32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jo rel32 */ +u32* JO32( u32 to ) +{ + return J32Rel( 0x80, to ); +} + +/* jno rel32 */ +u32* JNO32( u32 to ) +{ + return J32Rel( 0x81, to ); +} + +// js rel32 +u32* JS32( u32 to ) +{ + return J32Rel( 0x88, to ); +} + + +/* call func */ +void CALLFunc( u32 func ) +{ + CALL32( func - ( (u32)x86Ptr + 5 ) ); +} + +/* call rel32 */ +void CALL32( u32 to ) +{ + write8( 0xE8 ); + write32( to ); +} + +/* call r32 */ +void CALL32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call r64 */ +void CALL64R( x86IntRegType to ) +{ + Rex(1, 0, 0, to >> 3); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call m32 */ +void CALL32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r64 */ +void CMP64ItoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp m64 to r64 */ +void CMP64MtoR( x86IntRegType to, u32 from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* cmp imm32 to r32 */ +void CMP32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp imm32 to m32 */ +void CMP32ItoM( u32 to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* cmp r32 to r32 */ +void CMP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m32 to r32 */ +void CMP32MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, to ); + write8(from); +} + +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) +{ + assert( to != ESP ); + write8( 0x83 ); + ModRM( 1, 7, to ); + write8(off); + write8(from); +} + +// cmp imm8 to [r32] +void CMP32I8toM( u32 to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* cmp imm16 to r16 */ +void CMP16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write16( from ); +} + +/* cmp imm16 to m16 */ +void CMP16ItoM( u32 to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* cmp r16 to r16 */ +void CMP16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m16 to r16 */ +void CMP16MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x66 ); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0x3C ); + } + else + { + write8( 0x80 ); + ModRM( 3, 7, to ); + } + write8( from ); +} + +// cmp m8 to r8 +void CMP8MtoR( x86IntRegType to, u32 from ) +{ + write8( 0x3A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* test imm32 to r32 */ +void TEST32ItoR( x86IntRegType to, u32 from ) +{ + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +void TEST32ItoM( u32 to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* test r32 to r32 */ +void TEST32RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, to ); + write32(from); +} + +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ) +{ + if ( to == EAX ) + { + write16( 0xA966 ); + } + else + { + write16( 0xF766 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x8566 ); + ModRM( 3, from, to ); +} + +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ) +{ + if ( to == EAX ) + { + write8( 0xA8 ); + } + else + { + write8( 0xF6 ); + ModRM( 3, 0, to ); + } + write8( from ); +} + +// test imm8 to r8 +void TEST8ItoM( u32 to, u8 from ) +{ + write8( 0xF6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write8( from ); +} + +/* sets r8 */ +void SETS8R( x86IntRegType to ) +{ + SET8R( 0x98, to ); +} + +/* setl r8 */ +void SETL8R( x86IntRegType to ) +{ + SET8R( 0x9C, to ); +} + +// setge r8 +void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); } +// setg r8 +void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); } +// seta r8 +void SETA8R( x86IntRegType to ) { SET8R(0x97, to); } +// setae r8 +void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); } +/* setb r8 */ +void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); } +/* setb r8 */ +void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); } +// setz r8 +void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); } +// sete r8 +void SETE8R( x86IntRegType to ) { SET8R(0x94, to); } + +/* push r32 */ +void PUSH32R( x86IntRegType from ) +{ + write8( 0x50 | from ); +} + +/* push m32 */ +void PUSH32M( u32 from ) +{ + write8( 0xFF ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* push imm32 */ +void PUSH32I( u32 from ) +{ + write8( 0x68 ); + write32( from ); +} + +/* pop r32 */ +void POP32R( x86IntRegType from ) +{ + write8( 0x58 | from ); +} + +/* pushad */ +void PUSHA32( void ) +{ + write8( 0x60 ); +} + +/* popad */ +void POPA32( void ) +{ + write8( 0x61 ); +} + +/* pushfd */ +void PUSHFD( void ) +{ + write8( 0x9C ); +} + +/* popfd */ +void POPFD( void ) +{ + write8( 0x9D ); +} + +void RET( void ) { write8( 0xC3 ); } +void RET2( void ) { write16( 0xc3f3 ); } + +void CBW( void ) { write16( 0x9866 ); } +void CWD( void ) { write8( 0x98 ); } +void CDQ( void ) { write8( 0x99 ); } +void CWDE() { write8(0x98); } + +void LAHF() { write8(0x9f); } +void SAHF() { write8(0x9e); } + +void BT32ItoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBA0F ); + write8( 0xE0 | to ); + write8( from ); +} + +void BSRRtoR(x86IntRegType to, x86IntRegType from) +{ + write16( 0xBD0F ); + ModRM( 3, from, to ); +} + +void BSWAP32R( x86IntRegType to ) +{ + write8( 0x0F ); + write8( 0xC8 + to ); +} + +// to = from + offset +void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) +{ + write8(0x66); + LEA32RtoR(to, from, offset); +} + +void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) +{ + write8(0x8d); + + if( from == ESP ) { + if( offset == 0 ) { + ModRM(1, to, from); + write8(0x24); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(0x24); + write8(offset); + } + else { + ModRM(2, to, from); + write8(0x24); + write32(offset); + } + } + else { + if( offset == 0 && from != EBP && from!=ESP ) { + ModRM(0, to, from); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(offset); + } + else { + ModRM(2, to, from); + write32(offset); + } + } +} + +// to = from0 + from1 +void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x66); + LEA32RRtoR(to, from0, from1); +} + +void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x8d); + if( from0 == EBP || from1 == EBP ) { + + if( from0 == EBP ) SWAP(from0, from1); + ModRM(1, to, 4); + ModRM(0, from0, from1); + write8(0); + } + else { + ModRM(0, to, 4); + ModRM(0, from0, from1); + } +} + +// to = from << scale (max is 3) +void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + write8(0x66); + LEA32RStoR(to, from, scale); +} + +void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + if( to == from ) { + SHL32ItoR(to, scale); + return; + } + + if( from != ESP ) { + write8(0x8d); + ModRM(0, to, 4); + ModRM(scale, from, 5); + write32(0); + } + else { + MOV32RtoR(to, from); + LEA32RStoR(to, to, scale); + } +} diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86.h b/branches/pcsx2_0.9.2/x86/ix86/ix86.h new file mode 100644 index 0000000..4c3b780 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86.h @@ -0,0 +1,1642 @@ +/* + * ix86 definitions v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "PS2Etypes.h" // Basic types header + +#ifdef __x86_64__ +#define XMMREGS 16 +#define X86REGS 16 +#else +#define XMMREGS 8 +#define X86REGS 8 +#endif + +#define MMXREGS 8 + +#define SIB 4 +#define DISP32 5 + +// general types +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 +#define RAX 0 +#define RBX 3 +#define RCX 1 +#define RDX 2 +#define RSI 6 +#define RDI 7 +#define RBP 5 +#define RSP 4 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +typedef int x86IntRegType; + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; + +typedef enum +{ + XMMT_INT = 0, // integer (sse2 only) + XMMT_FPS = 1, // floating point + //XMMT_FPD = 3, // double +} XMMSSEType; + +extern XMMSSEType g_xmmtypes[XMMREGS]; + +void cpudetectInit( void );//this is all that needs to be called and will fill up the below structs + +//cpu capabilities structure +typedef struct { + u32 hasFloatingPointUnit; + u32 hasVirtual8086ModeEnhancements; + u32 hasDebuggingExtensions; + u32 hasPageSizeExtensions; + u32 hasTimeStampCounter; + u32 hasModelSpecificRegisters; + u32 hasPhysicalAddressExtension; + u32 hasCOMPXCHG8BInstruction; + u32 hasAdvancedProgrammableInterruptController; + u32 hasSEPFastSystemCall; + u32 hasMemoryTypeRangeRegisters; + u32 hasPTEGlobalFlag; + u32 hasMachineCheckArchitecture; + u32 hasConditionalMoveAndCompareInstructions; + u32 hasFGPageAttributeTable; + u32 has36bitPageSizeExtension; + u32 hasProcessorSerialNumber; + u32 hasCFLUSHInstruction; + u32 hasDebugStore; + u32 hasACPIThermalMonitorAndClockControl; + u32 hasMultimediaExtensions; + u32 hasFastStreamingSIMDExtensionsSaveRestore; + u32 hasStreamingSIMDExtensions; + u32 hasStreamingSIMD2Extensions; + u32 hasSelfSnoop; + u32 hasHyperThreading; + u32 hasThermalMonitor; + u32 hasIntel64BitArchitecture; + u32 hasStreamingSIMD3Extensions; + //that is only for AMDs + u32 hasMultimediaExtensionsExt; + u32 hasAMD64BitArchitecture; + u32 has3DNOWInstructionExtensionsExt; + u32 has3DNOWInstructionExtensions; +} CAPABILITIES; + +extern CAPABILITIES cpucaps; + +typedef struct { + + u32 x86Family; // Processor Family + u32 x86Model; // Processor Model + u32 x86PType; // Processor Type + u32 x86StepID; // Stepping ID + u32 x86Flags; // Feature Flags + u32 x86EFlags; // Extended Feature Flags + //all the above returns hex values + s8 x86ID[16]; // Vendor ID //the vendor creator (in %s) + s8 x86Type[20]; //cpu type in char format //the cpu type (in %s) + s8 x86Fam[50]; // family in char format //the original cpu name string (in %s) + u32 cpuspeed; // speed of cpu //this will give cpu speed (in %d) +} CPUINFO; + +extern CPUINFO cpuinfo; + +extern s8 *x86Ptr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + + +#ifdef __x86_64__ +#define MEMADDR(addr, oplen) ((addr) - ((u64)x86Ptr + ((u64)oplen))) +#else +#define MEMADDR(addr, oplen) (addr) +#endif + + + +void write8( int val ); +void write16( int val ); +void write32( u32 val ); +void write64( u64 val ); + + +void x86SetPtr( char *ptr ); +void x86Shutdown( void ); + +void x86SetJ8( u8 *j8 ); +void x86SetJ8A( u8 *j8 ); +void x86SetJ16( u16 *j16 ); +void x86SetJ16A( u16 *j16 ); +void x86SetJ32( u32 *j32 ); +void x86SetJ32A( u32 *j32 ); + +void x86Align( int bytes ); +u64 GetCPUTick( void ); + +// General Helper functions + +void Rex( int w, int r, int x, int b ); +void ModRM( int mod, int rm, int reg ); +void SibSB( int ss, int rm, int index ); +void SET8R( int cc, int to ); +u8* J8Rel( int cc, int to ); +u32* J32Rel( int cc, u32 to ); +void CMOV32RtoR( int cc, int to, int from ); +void CMOV32MtoR( int cc, int to, u32 from ); + +//****************** +// IX86 intructions +//****************** + +// +// * scale values: +// * 0 - *1 +// * 1 - *2 +// * 2 - *4 +// * 3 - *8 +// + +void STC( void ); +void CLC( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r64 to r64 +void MOV64RtoR( x86IntRegType to, x86IntRegType from ); +// mov r64 to m64 +void MOV64RtoM( u64 to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, u64 from ); +// mov imm32 to m64 +void MOV64ItoM( u32 to, u32 from ); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( u32 to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, u32 from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, u32 offset ); +// mov [r32][r32< subtract ST(0) from ST(1), store in ST(1) and POP stack +void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +void FDIV320toR( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src), pop stack, store in ST(src) +void FDIV320toRP( x86IntRegType src ); + +// fadd m32 to fpu reg stack +void FADD32( u32 from ); +// fsub m32 to fpu reg stack +void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +void FDIV32( u32 from ); +// fcomi st, st( i) +void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +void FCOM32( u32 from ); +// fabs fpu reg stack +void FABS( void ); +// fsqrt fpu reg stack +void FSQRT( void ); +// ftan fpu reg stack +void FPATAN( void ); +// fsin fpu reg stack +void FSIN( void ); +// fchs fpu reg stack +void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +void FCMOVNU32( x86IntRegType from ); +void FCOMP32( u32 from ); +void FNSTSWtoAX( void ); + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, u32 from ); +// movq r64 to m64 +void MOVQRtoM( u32 to, x86MMXRegType from ); + +// pand r64 to r64 +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +void PANDMtoR( x86MMXRegType to, u32 from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, u32 from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, u32 from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, u32 from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, u32 from ); +// psllq imm8 to r64 +void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +void PSRLQMtoR( x86MMXRegType to, u32 from ); +// psrlq imm8 to r64 +void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +void PADDUSBMtoR( x86MMXRegType to, u32 from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, u32 from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, u32 from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, u32 from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, u32 from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ); +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDMtoR( x86MMXRegType to, u32 from ); + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ); +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ); +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDMtoR( x86MMXRegType to, u32 from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDMtoR( x86MMXRegType to, u32 from ); +void PSRLWItoR( x86MMXRegType to, u8 from ); +void PSRLDItoR( x86MMXRegType to, u8 from ); +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSLLWItoR( x86MMXRegType to, u8 from ); +void PSLLDItoR( x86MMXRegType to, u8 from ); +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSRAWItoR( x86MMXRegType to, u8 from ); +void PSRADItoR( x86MMXRegType to, u8 from ); +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ); +void MOVQ64ItoR( x86MMXRegType reg, u64 i ); //Prototype.Todo add all consts to end of block.not after jr $+8 +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void MOVDMtoMMX( x86MMXRegType to, u32 from ); +void MOVDMMXtoM( u32 to, x86MMXRegType from ); +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ); +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8); +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8); +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from); + +// emms +void EMMS( void ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word 64bits +//********************************************************************************** +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from); +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from); + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from); + +//********************* +// SSE instructions * +//********************* +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ); +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ); + +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void SSE_MOVLPSRtoRm( x86MMXRegType to, x86IntRegType from ); +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ); + +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ); +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ); + +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); + +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ); + +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ); +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ); +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from); +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from); +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ); +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +// VectorPath +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ); + +void SSE_STMXCSR( u32 from ); +void SSE_LDMXCSR( u32 from ); + + +//********************* +// SSE 2 Instructions* +//********************* +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from); +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from); + +// mult by half words +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from); +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from); + + +//**********************************************************************************/ +//PMOVMSKB: Create 16bit mask from signs of 8bit integers +//********************************************************************************** +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ); +void SSE_PINSRW_R32_to_XMM(x86SSERegType from, x86IntRegType to, u8 imm8 ); + + +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ); +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ); +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ); + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from); + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from); +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from); +//********************* +// SSE-X - uses both SSE,SSE2 code and tries to keep consistensies between the data +// Uses g_xmmtypes to infer the correct type. +//********************* +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ); +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ); +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ); + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ); +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from); +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from); + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, u32 from ); +void PFCMPGTMtoR( x86IntRegType to, u32 from ); +void PFCMPGEMtoR( x86IntRegType to, u32 from ); +void PFADDMtoR( x86IntRegType to, u32 from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, u32 from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, u32 from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, u32 from ); +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PF2IDMtoR( x86IntRegType to, u32 from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, u32 from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, u32 from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, u32 from ); +void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from); +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ); +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ); +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +/* SSE2 emulated functions for SSE CPU's by kekko*/ + +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ); +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); + +//////////////////////////////////////////////////// +#ifdef _DEBUG +#define WRITECHECK() CheckX86Ptr() +#else +#define WRITECHECK() +#endif + +#define write8(val ) { \ + *(u8*)x86Ptr = (u8)val; \ + x86Ptr++; \ +} \ + +#define write16(val ) \ +{ \ + *(u16*)x86Ptr = (u16)val; \ + x86Ptr += 2; \ +} \ + +#define write32( val ) \ +{ \ + *(u32*)x86Ptr = val; \ + x86Ptr += 4; \ +} \ + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86_3dnow.c b/branches/pcsx2_0.9.2/x86/ix86/ix86_3dnow.c new file mode 100644 index 0000000..df56fd0 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86_3dnow.c @@ -0,0 +1,184 @@ + +#include "ix86.h" + +/**********************/ +/* 3DNOW instructions */ +/**********************/ + +/* femms */ +void FEMMS( void ) +{ + write16( 0x0E0F ); +} + +void PFCMPEQMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB0 ); +} + +void PFCMPGTMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA0 ); +} + +void PFCMPGEMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x90 ); +} + +void PFADDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9E ); +} + +void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9E ); +} + +void PFSUBMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9A ); +} + +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9A ); +} + +void PFMULMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB4 ); +} + +void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB4 ); +} + +void PFRCPMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x96 ); +} + +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x96 ); +} + +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA6 ); +} + +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB6 ); +} + +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x97 ); +} + +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA7 ); +} + +void PF2IDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x1D ); +} + +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x1D ); +} + +void PI2FDMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x0D ); +} + +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x0D ); +} + +void PFMAXMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA4 ); +} + +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA4 ); +} + +void PFMINMtoR( x86IntRegType to, u32 from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x94 ); +} + +void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x94 ); +} diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86_cpudetect.c b/branches/pcsx2_0.9.2/x86/ix86/ix86_cpudetect.c new file mode 100644 index 0000000..475f935 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86_cpudetect.c @@ -0,0 +1,500 @@ +/* Cpudetection lib + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if defined (__WIN32__) + +#include + +#endif + +#include +#include + +#include "ix86.h" + +#if defined (__VCNET2005__) + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +CAPABILITIES cpucaps; +CPUINFO cpuinfo; + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag; + +#if defined (__VCNET2005__) + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (__MSCW32__) && !defined(__x86_64__) + __asm + { + push ebx; + push edi; + + pushfd; + pop eax; + mov edx, eax; + xor eax, 1 << 21; + push eax; + popfd; + pushfd; + pop eax; + xor eax, edx; + mov flag, eax; + } + if ( ! flag ) + { + return -1; + } + + __asm + { + mov eax, cmd; + cpuid; + mov edi, [regs] + mov [edi], eax; + mov [edi+4], ebx; + mov [edi+8], ecx; + mov [edi+12], edx; + + pop edi; + pop ebx; + } + + return 0; + + +#else + + __asm__ __volatile__ ( +#ifdef __x86_64__ + "sub $0x18, %%rsp\n" +#endif + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%edx\n" + "xor $0x200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%eax\n" + "mov %%eax, %0\n" +#ifdef __x86_64__ + "add $0x18, %%rsp\n" +#endif + : "=r"(flag) : + ); + + if ( ! flag ) + { + return -1; + } + + __asm__ __volatile__ ( + "push %%ebx\n" + "push %%edx\n" + "mov %4, %%eax\n" + "cpuid\n" + "mov %%eax, %0\n" + "mov %%ebx, %1\n" + "mov %%ecx, %2\n" + "mov %%edx, %3\n" + "pop %%edx\n" + "pop %%ebx\n" + : "=m" (regs[0]), "=m" (regs[1]), "=m" (regs[2]), "=m" (regs[3]) + : "m"(cmd) + : "eax", "ecx"//, "edx", "ebx" + ); + + return 0; +#endif +} + +u64 GetCPUTick( void ) +{ +#if defined (__VCNET2005__) + + return __rdtsc(); + +#elif defined(__MSCW32__) && !defined(__x86_64__) + + __asm rdtsc; + +#else + + u32 _a, _d; + __asm__ __volatile__ ("rdtsc" : "=a"(_a), "=d"(_d)); + return (u64)_a | ((u64)_d << 32); + +#endif +} + +#if defined __LINUX__ + +#include +#include + +u32 timeGetTime( void ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#endif + +s64 CPUSpeedHz( unsigned int time ) +{ + s64 timeStart, + timeStop; + s64 startTick, + endTick; + s64 overhead; + + if( ! cpucaps.hasTimeStampCounter ) + { + return 0; //check if function is supported + } + + overhead = GetCPUTick() - GetCPUTick(); + + timeStart = timeGetTime( ); + while( timeGetTime( ) == timeStart ) + { + timeStart = timeGetTime( ); + } + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > time ) + { + endTick = GetCPUTick( ); + break; + } + } + + return (s64)( ( endTick - startTick ) + ( overhead ) ); +} + +//////////////////////////////////////////////////// +void cpudetectInit( void ) +{ + u32 regs[ 4 ]; + u32 cmds; + u32 AMDspeed; + s8 AMDspeedString[10]; + int cputype=0; // Cpu type + //AMD 64 STUFF + u32 x86_64_8BITBRANDID; + u32 x86_64_12BITBRANDID; + memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) ); + cpuinfo.x86Family = 0; + cpuinfo.x86Model = 0; + cpuinfo.x86PType = 0; + cpuinfo.x86StepID = 0; + cpuinfo.x86Flags = 0; + cpuinfo.x86EFlags = 0; + + if ( iCpuId( 0, regs ) == -1 ) return; + + cmds = regs[ 0 ]; + ((u32*)cpuinfo.x86ID)[ 0 ] = regs[ 1 ]; + ((u32*)cpuinfo.x86ID)[ 1 ] = regs[ 3 ]; + ((u32*)cpuinfo.x86ID)[ 2 ] = regs[ 2 ]; + if ( cmds >= 0x00000001 ) + { + if ( iCpuId( 0x00000001, regs ) != -1 ) + { + cpuinfo.x86StepID = regs[ 0 ] & 0xf; + cpuinfo.x86Model = (regs[ 0 ] >> 4) & 0xf; + cpuinfo.x86Family = (regs[ 0 ] >> 8) & 0xf; + cpuinfo.x86PType = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[1] & 0xff; + cpuinfo.x86Flags = regs[ 3 ]; + } + } + if ( iCpuId( 0x80000000, regs ) != -1 ) + { + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + if ( iCpuId( 0x80000001, regs ) != -1 ) + { + x86_64_12BITBRANDID = regs[1] & 0xfff; + cpuinfo.x86EFlags = regs[ 3 ]; + + } + } + } + switch(cpuinfo.x86PType) + { + case 0: + strcpy( cpuinfo.x86Type, "Standard OEM"); + break; + case 1: + strcpy( cpuinfo.x86Type, "Overdrive"); + break; + case 2: + strcpy( cpuinfo.x86Type, "Dual"); + break; + case 3: + strcpy( cpuinfo.x86Type, "Reserved"); + break; + default: + strcpy( cpuinfo.x86Type, "Unknown"); + break; + } + if ( cpuinfo.x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p + if ( cpuinfo.x86ID[ 0 ] == 'A' ){ cputype=1;} + + if ( cputype == 0 ) //intel cpu + { + if( ( cpuinfo.x86Family >= 7 ) && ( cpuinfo.x86Family < 15 ) ) + { + strcpy( cpuinfo.x86Fam, "Intel P6 family (Not PIV and Higher then PPro" ); + } + else + { + switch( cpuinfo.x86Family ) + { + // Start at 486 because if it's below 486 there is no cpuid instruction + case 4: + strcpy( cpuinfo.x86Fam, "Intel 486" ); + break; + case 5: + switch( cpuinfo.x86Model ) + { + case 4: + case 8: // 0.25 m + strcpy( cpuinfo.x86Fam, "Intel Pentium (MMX)"); + break; + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium" ); + } + break; + case 6: + switch( cpuinfo.x86Model ) + { + case 0: // Pentium pro (P6 A-Step) + case 1: // Pentium pro + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro" ); + break; + + case 2: // 66 MHz FSB + case 5: // Xeon/Celeron (0.25 m) + case 6: // Internal L2 cache + strcpy( cpuinfo.x86Fam, "Intel Pentium II" ); + break; + + case 7: // Xeon external L2 cache + case 8: // Xeon/Celeron with 256 KB on-die L2 cache + case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache + case 11: // Xeon/Celeron with Tualatin core, on-die cache + strcpy( cpuinfo.x86Fam, "Intel Pentium III" ); + break; + case 15: // Core 2 Duo Allendale/Conroe + strcpy( cpuinfo.x86Fam, "Intel Core 2 Duo" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro (Unknown)" ); + } + break; + case 15: + switch( cpuinfo.x86Model ) + { + case 0: // Willamette (A-Step) + case 1: // Willamette + strcpy( cpuinfo.x86Fam, "Willamette Intel Pentium IV" ); + break; + case 2: // Northwood + strcpy( cpuinfo.x86Fam, "Northwood Intel Pentium IV" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium IV (Unknown)" ); + break; + } + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown Intel CPU" ); + } + } + } + else if ( cputype == 1 ) //AMD cpu + { + if( cpuinfo.x86Family >= 7 ) + { + if((x86_64_12BITBRANDID !=0) || (x86_64_8BITBRANDID !=0)) + { + if(x86_64_8BITBRANDID == 0 ) + { + switch((x86_64_12BITBRANDID >>6)& 0x3f) + { + case 4: + strcpy(cpuinfo.x86Fam,"AMD Athlon(tm) 64 Processor"); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 12: + strcpy(cpuinfo.x86Fam,"AMD Opteron(tm) Processor"); + break; + case 5: + strcpy( cpuinfo.x86Fam, "AMD Athlon X2 Processor" ); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 44: + strcpy( cpuinfo.x86Fam, "AMD Opteron(tm) Dual Core Processor" ); + break; + default: + strcpy(cpuinfo.x86Fam,"Unknown AMD 64 proccesor"); + + } + } + else //8bit brand id is non zero + { + strcpy(cpuinfo.x86Fam,"Unsupported yet AMD64 cpu"); + } + } + else + { + strcpy( cpuinfo.x86Fam, "AMD K7+ Processor" ); + } + } + else + { + switch ( cpuinfo.x86Family ) + { + case 4: + switch( cpuinfo.x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( cpuinfo.x86Fam, "AMD 5x86 Processor" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( cpuinfo.x86Fam, "AMD 486 Processor" ); + break; + + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + + } + break; + + case 5: + switch( cpuinfo.x86Model) + { + case 0: // SSA 5 (75, 90 and 100 Mhz) + case 1: // 5k86 (PR 120 and 133 MHz) + case 2: // 5k86 (PR 166 MHz) + case 3: // K5 5k86 (PR 200 MHz) + strcpy( cpuinfo.x86Fam, "AMD K5 Processor" ); + break; + + case 6: + case 7: // (0.25 m) + case 8: // K6-2 + case 9: // K6-III + case 14: // K6-2+ / K6-III+ + strcpy( cpuinfo.x86Fam, "AMD K6 Series Processor" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + } + break; + case 6: + strcpy( cpuinfo.x86Fam, "AMD Athlon XP Processor" ); + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown AMD CPU" ); + } + } + } + //capabilities + cpucaps.hasFloatingPointUnit = ( cpuinfo.x86Flags >> 0 ) & 1; + cpucaps.hasVirtual8086ModeEnhancements = ( cpuinfo.x86Flags >> 1 ) & 1; + cpucaps.hasDebuggingExtensions = ( cpuinfo.x86Flags >> 2 ) & 1; + cpucaps.hasPageSizeExtensions = ( cpuinfo.x86Flags >> 3 ) & 1; + cpucaps.hasTimeStampCounter = ( cpuinfo.x86Flags >> 4 ) & 1; + cpucaps.hasModelSpecificRegisters = ( cpuinfo.x86Flags >> 5 ) & 1; + cpucaps.hasPhysicalAddressExtension = ( cpuinfo.x86Flags >> 6 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 7 ) & 1; + cpucaps.hasCOMPXCHG8BInstruction = ( cpuinfo.x86Flags >> 8 ) & 1; + cpucaps.hasAdvancedProgrammableInterruptController = ( cpuinfo.x86Flags >> 9 ) & 1; + cpucaps.hasSEPFastSystemCall = ( cpuinfo.x86Flags >> 11 ) & 1; + cpucaps.hasMemoryTypeRangeRegisters = ( cpuinfo.x86Flags >> 12 ) & 1; + cpucaps.hasPTEGlobalFlag = ( cpuinfo.x86Flags >> 13 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 14 ) & 1; + cpucaps.hasConditionalMoveAndCompareInstructions = ( cpuinfo.x86Flags >> 15 ) & 1; + cpucaps.hasFGPageAttributeTable = ( cpuinfo.x86Flags >> 16 ) & 1; + cpucaps.has36bitPageSizeExtension = ( cpuinfo.x86Flags >> 17 ) & 1; + cpucaps.hasProcessorSerialNumber = ( cpuinfo.x86Flags >> 18 ) & 1; + cpucaps.hasCFLUSHInstruction = ( cpuinfo.x86Flags >> 19 ) & 1; + cpucaps.hasDebugStore = ( cpuinfo.x86Flags >> 21 ) & 1; + cpucaps.hasACPIThermalMonitorAndClockControl = ( cpuinfo.x86Flags >> 22 ) & 1; + cpucaps.hasMultimediaExtensions = ( cpuinfo.x86Flags >> 23 ) & 1; //mmx + cpucaps.hasFastStreamingSIMDExtensionsSaveRestore = ( cpuinfo.x86Flags >> 24 ) & 1; + cpucaps.hasStreamingSIMDExtensions = ( cpuinfo.x86Flags >> 25 ) & 1; //sse + cpucaps.hasStreamingSIMD2Extensions = ( cpuinfo.x86Flags >> 26 ) & 1; //sse2 + cpucaps.hasSelfSnoop = ( cpuinfo.x86Flags >> 27 ) & 1; + cpucaps.hasHyperThreading = ( cpuinfo.x86Flags >> 28 ) & 1; + cpucaps.hasThermalMonitor = ( cpuinfo.x86Flags >> 29 ) & 1; + cpucaps.hasIntel64BitArchitecture = ( cpuinfo.x86Flags >> 30 ) & 1; + //that is only for AMDs + cpucaps.hasMultimediaExtensionsExt = ( cpuinfo.x86EFlags >> 22 ) & 1; //mmx2 + cpucaps.hasAMD64BitArchitecture = ( cpuinfo.x86EFlags >> 29 ) & 1; //64bit cpu + cpucaps.has3DNOWInstructionExtensionsExt = ( cpuinfo.x86EFlags >> 30 ) & 1; //3dnow+ + cpucaps.has3DNOWInstructionExtensions = ( cpuinfo.x86EFlags >> 31 ) & 1; //3dnow + cpuinfo.cpuspeed = (u32 )(CPUSpeedHz( 1000 ) / 1000000); +} diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86_fpu.c b/branches/pcsx2_0.9.2/x86/ix86/ix86_fpu.c new file mode 100644 index 0000000..98034a5 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86_fpu.c @@ -0,0 +1,269 @@ +#include +#include +#include "ix86.h" + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fld m32 to fpu reg stack */ +void FLD32( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// fld st(i) +void FLD(int st) { write16(0xc0d9+(st<<8)); } + +void FLD1() { write16(0xe8d9); } +void FLDL2E() { write16(0xead9); } + +/* fst m32 from fpu reg stack */ +void FST32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// fstp st(i) +void FSTP(int st) { write16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +void FLDCW( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x7, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void FNSTSWtoAX( void ) +{ + write16( 0xE0DF ); +} + +void FXAM() +{ + write16(0xe5d9); +} + +void FDECSTP() { write16(0xf6d9); } +void FRNDINT() { write16(0xfcd9); } +void FXCH(int st) { write16(0xc8d9+(st<<8)); } +void F2XM1() { write16(0xf0d9); } +void FSCALE() { write16(0xfdd9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +void FADD32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +void FADD320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +void FSUB32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +void FSUB320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +void FSUBP( void ) +{ + write8( 0xDE ); + write8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +void FMUL32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +void FMUL320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +void FDIV32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +void FDIV320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xF8 + src ); +} + +void FDIV320toRP( x86IntRegType src ) +{ + write8( 0xDE ); + write8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +void FADD32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x1, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fabs fpu reg stack */ +void FABS( void ) +{ + write16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +void FSQRT( void ) +{ + write16( 0xFAD9 ); +} + +void FPATAN(void) { write16(0xf3d9); } +void FSIN(void) { write16(0xfed9); } + +/* fchs fpu reg stack */ +void FCHS( void ) +{ + write16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +void FCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +void FCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +void FUCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +void FUCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +void FCOM32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fcomp m32 to fpu reg stack */ +void FCOMP32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +#define FCMOV32( low, high ) \ + { \ + write8( low ); \ + write8( high + from ); \ + } + +void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86_mmx.c b/branches/pcsx2_0.9.2/x86/ix86/ix86_mmx.c new file mode 100644 index 0000000..0f484ba --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86_mmx.c @@ -0,0 +1,632 @@ + +#include "ix86.h" + +#include + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6F0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movq r64 to m64 */ +void MOVQRtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7F0F ); + ModRM( 0, from, DISP32 ); + write32(MEMADDR(to, 4)); +} + +/* pand r64 to r64 */ +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDB0F ); + ModRM( 3, to, from ); +} + +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDF0F ); + ModRM( 3, to, from ); +} + +/* por r64 to r64 */ +void PORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEB0F ); + ModRM( 3, to, from ); +} + +/* pxor r64 to r64 */ +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEF0F ); + ModRM( 3, to, from ); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF30F ); + ModRM( 3, to, from ); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 6, to); + write8( from ); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD30F ); + ModRM( 3, to, from ); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 2, to); + write8( from ); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDC0F ); + ModRM( 3, to, from ); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDD0F ); + ModRM( 3, to, from ); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddb r64 to r64 */ +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFC0F ); + ModRM( 3, to, from ); +} + +/* paddb m64 to r64 */ +void PADDBMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddw r64 to r64 */ +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFD0F ); + ModRM( 3, to, from ); +} + +/* paddw m64 to r64 */ +void PADDWMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddd r64 to r64 */ +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFE0F ); + ModRM( 3, to, from ); +} + +/* paddd m64 to r64 */ +void PADDDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* emms */ +void EMMS( void ) +{ + write16( 0x770F ); +} + +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEC0F ); + ModRM( 3, to, from ); +} + +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xED0F ); + ModRM( 3, to, from ); +} + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xD40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD40F ); + ModRM( 3, to, from ); +} + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE80F ); + ModRM( 3, to, from ); +} + +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE90F ); + ModRM( 3, to, from ); +} + + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF80F ); + ModRM( 3, to, from ); +} + +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF90F ); + ModRM( 3, to, from ); +} + +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFA0F ); + ModRM( 3, to, from ); +} + +void PSUBDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFA0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD80F ); + ModRM( 3, to, from ); +} + +void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD90F ); + ModRM( 3, to, from ); +} + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xFB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFB0F ); + ModRM( 3, to, from ); +} + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xF40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF40F ); + ModRM( 3, to, from ); +} + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x740F ); + ModRM( 3, to, from ); +} + +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x750F ); + ModRM( 3, to, from ); +} + +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x760F ); + ModRM( 3, to, from ); +} + +void PCMPEQDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x760F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x640F ); + ModRM( 3, to, from ); +} + +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x650F ); + ModRM( 3, to, from ); +} + +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x660F ); + ModRM( 3, to, from ); +} + +void PCMPGTDMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x660F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSRLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD20F ); + ModRM( 3, to, from ); +} + +void PSLLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF20F ); + ModRM( 3, to, from ); +} + +void PSRAWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE20F ); + ModRM( 3, to, from ); +} + +/* por m64 to r64 */ +void PORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pxor m64 to r64 */ +void PXORMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xEF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pand m64 to r64 */ +void PANDMtoR( x86MMXRegType to, u32 from ) +{ + //u64 rip = (u64)x86Ptr + 7; + write16( 0xDB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PANDNMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0xDF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6A0F ); + ModRM( 3, to, from ); +} + +void PUNPCKHDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x6A0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x620F ); + ModRM( 3, to, from ); +} + +void PUNPCKLDQMtoR( x86MMXRegType to, u32 from ) +{ + write16( 0x620F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOVQ64ItoR( x86MMXRegType reg, u64 i ) +{ + MOVQMtoR( reg, ( u32 )(x86Ptr) + 2 + 7 ); + JMP8( 8 ); + write64( i ); +} + +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6F0F ); + ModRM( 3, to, from ); +} + +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6F0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7F0F ); + + if( offset < 128 ) { + ModRM( 1, from , to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movd m32 to r64 */ +void MOVDMtoMMX( x86MMXRegType to, u32 from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movd r64 to m32 */ +void MOVDMMXtoM( u32 to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 3, to, from ); +} + +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, from ); +} + +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6E0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 3, from, to ); +} + +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, to ); + if( to >= 4 ) { + // no idea why + assert( to == ESP ); + write8(0x24); + } + +} + +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7E0F ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///* movd r32 to r64 */ +//void MOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x6E0F ); +// ModRM( 3, to, from ); +//} +// +///* movq r64 to r32 */ +//void MOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x7E0F ); +// ModRM( 3, from, to ); +//} + +// untested +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x630F ); + ModRM( 3, to, from ); +} + +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x6B0F ); + ModRM( 3, to, from ); +} + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) +{ + write16( 0xD70F ); + ModRM( 3, to, from ); +} + +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) +{ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0xc40f ); + ModRM( 3, to, from ); + write8( imm8 ); +} + +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) +{ + write16(0x700f); + ModRM( 3, to, from ); + write8(imm8); +} + +void PSHUFWMtoR(x86MMXRegType to, u32 from, u8 imm8) +{ + write16( 0x700f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); + write8(imm8); +} + +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) +{ + write16(0xf70f); + ModRM( 3, to, from ); +} diff --git a/branches/pcsx2_0.9.2/x86/ix86/ix86_sse.c b/branches/pcsx2_0.9.2/x86/ix86/ix86_sse.c new file mode 100644 index 0000000..7442294 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/ix86/ix86_sse.c @@ -0,0 +1,1582 @@ +#include +#include "ix86.h" + +PCSX2_ALIGNED16(unsigned int p[4]); +PCSX2_ALIGNED16(unsigned int p2[4]); +PCSX2_ALIGNED16(float f[4]); + + +XMMSSEType g_xmmtypes[XMMREGS] = {0}; + +/********************/ +/* SSE instructions */ +/********************/ + +#define SSEMtoR( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS ) ; \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSERtoM( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( from < XMMREGS) ; \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSE_SS_MtoR( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS ) ; \ + write8( 0xf3 ); \ + if (to > 7) Rex(1, to >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSE_SS_RtoM( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( from < XMMREGS) ; \ + write8( 0xf3 ); \ + if (from > 7) Rex(1, from >> 3, 0, 0); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSERtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define SSEMtoR66( code ) \ + write8( 0x66 ); \ + SSEMtoR( code, 0 ); + +#define SSERtoM66( code ) \ + write8( 0x66 ); \ + SSERtoM( code, 0 ); + +#define SSERtoR66( code ) \ + write8( 0x66 ); \ + SSERtoR( code ); + +#define _SSERtoR66( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0x66 ); \ + if (to > 7 || from > 7) Rex(1, from >> 3, 0, to >> 3); \ + write16( code ); \ + ModRM( 3, from, to ); + +#define SSE_SS_RtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0xf3 ); \ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define CMPPSMtoR( op ) \ + SSEMtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPPSRtoR( op ) \ + SSERtoR( 0xc20f ); \ + write8( op ); + +#define CMPSSMtoR( op ) \ + SSE_SS_MtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPSSRtoR( op ) \ + SSE_SS_RtoR( 0xc20f ); \ + write8( op ); + + + + + +/* movups [r32][r32*scale] to xmm1 */ +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups xmm1 to [r32][r32*scale] */ +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups [r32] to r32 */ +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + ModRM( 0, to, from ); +} + +/* movups r32 to [r32] */ +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16( 0x110f ); + ModRM( 0, from, to ); +} + +/* movlps [r32] to r32 */ +void SSE_MOVLPSRmtoR( x86MMXRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 0, to, from ); +} + +void SSE_MOVLPSRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x120f ); + ModRM( 2, to, from ); + write32(offset); +} + +/* movaps r32 to [r32] */ +void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 0, from, to ); +} + +void SSE_MOVLPSRtoRmOffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x130f ); + ModRM( 2, from, to ); + write32(offset); +} + +/* movaps [r32][r32*scale] to xmm1 */ +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movaps xmm1 to [r32][r32*scale] */ +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +// movaps [r32+offset] to r32 +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x280f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movaps r32 to [r32+offset] +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x290f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movdqa [r32+offset] to r32 +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (to > 7) Rex(1, to >> 3, 0, 0); + write8(0x66); + write16( 0x6f0f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movdqa r32 to [r32+offset] +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (from > 7) Rex(1, from >> 3, 0, 0); + write8(0x66); + write16( 0x7f0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +// movups [r32+offset] to r32 +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if (to > 7) Rex(1, to >> 3, 0, 0); + write16( 0x100f ); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +// movups r32 to [r32+offset] +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if (from > 7) Rex(1, from >> 3, 0, 0); + write16( 0x110f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +//**********************************************************************************/ +//MOVAPS: Move aligned Packed Single Precision FP values * +//********************************************************************************** +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x280f, 0 ); } +void SSE_MOVAPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); } +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x280f ); } + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x100f, 0 ); } +void SSE_MOVUPS_XMM_to_M128( u32 to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVSD_XMM_to_XMM(to, from); + else { + write8(0xf2); + SSERtoR( 0x100f); + } +} + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from); + else { + write8(0xf3); SSEMtoR( 0x7e0f, 0); + } +} + +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from); + else { + write8(0xf3); SSERtoR( 0x7e0f); + } +} + +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from); + else { + SSERtoM66(0xd60f); + } +} + +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVDQ2Q_XMM_to_MM(to, from); + else { + write8(0xf2); + SSERtoR( 0xd60f); + } +} +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ2DQ_MM_to_XMM(to, from); + else { + write8(0xf3); + SSERtoR( 0xd60f); + } +} + +//**********************************************************************************/ +//MOVSS: Move Scalar Single-Precision FP value * +//********************************************************************************** +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x100f, 0 ); } +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); } +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0xf3); write16(0x110f); + ModRM(0, from, to); +} + +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x100f ); } + +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0xf3); write16( 0x100f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write8(0xf3); write16(0x110f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); } +//**********************************************************************************/ +//MOVLPS: Move low Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x120f, 0 ); } +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); } + +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16( 0x120f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + write16(0x130f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHPS: Move High Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x160f, 0 ); } +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); } + +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16( 0x160f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write16(0x170f); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVLHPS: Moved packed Single-Precision FP low to high * +//********************************************************************************** +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHLPS: Moved packed Single-Precision FP High to Low * +//********************************************************************************** +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDPS: Logical Bit-wise AND for Single FP * +//********************************************************************************** +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x540f, 0 ); } +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x540f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDNPS : Logical Bit-wise AND NOT of Single-precision FP values * +//********************************************************************************** +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x550f, 0 ); } +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x550f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RCPPS : Packed Single-Precision FP Reciprocal * +//********************************************************************************** +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x530f ); } +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x530f, 0 ); } + +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x530f); } +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR(0x530f, 0); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ORPS : Bit-wise Logical OR of Single-Precision FP Data * +//********************************************************************************** +void SSE_ORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x560f, 0 ); } +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x560f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//XORPS : Bitwise Logical XOR of Single-Precision FP Values * +//********************************************************************************** +void SSE_XORPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x570f, 0 ); } +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x570f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDPS : ADD Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x580f, 0 ); } +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x580f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDSS : ADD Scalar Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x580f, 0 ); } +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x580f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBPS: Packed Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5c0f, 0 ); } +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5c0f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBSS : Scalar Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5c0f, 0 ); } +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5c0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULPS : Packed Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x590f, 0 ); } +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULSS : Scalar Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x590f, 0 ); } +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Packed Single-Precission FP compare (CMPccPS) * +//********************************************************************************** +//missing SSE_CMPPS_I8_to_XMM +// SSE_CMPPS_M32_to_XMM +// SSE_CMPPS_XMM_to_XMM +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 0 ); } +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 1 ); } +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 2 ); } +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 3 ); } +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 4 ); } +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 5 ); } +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 6 ); } +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, u32 from ) { CMPPSMtoR( 7 ); } +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 7 ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Scalar Single-Precission FP compare (CMPccSS) * +//********************************************************************************** +//missing SSE_CMPSS_I8_to_XMM +// SSE_CMPSS_M32_to_XMM +// SSE_CMPSS_XMM_to_XMM +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 0 ); } +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 1 ); } +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 2 ); } +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 3 ); } +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 4 ); } +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 5 ); } +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 6 ); } +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, u32 from ) { CMPSSMtoR( 7 ); } +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, u32 from ) +{ + write16( 0x2e0f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + write16( 0x2e0f ); + ModRM( 3, to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x520f, 0 ); } +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x520f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTSS : Scalar Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x520f, 0 ); } +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x520f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTPS : Packed Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x510f, 0 ); } +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x510f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTSS : Scalar Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x510f, 0 ); } +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x510f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXPS: Return Packed Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5f0f, 0 ); } +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXSS: Return Scalar Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * +//********************************************************************************** +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x2a0f, 0 ); } +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPS2PI: Packed Single FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, u32 from ) { SSEMtoR( 0x2d0f, 0 ); } +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } + +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, u32 from) { write8(0xf3); SSEMtoR(0x2c0f, 0); } +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) +{ + write8(0xf3); + write16(0x2c0f); + ModRM(3, to, from); +} + +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x2a0f, 0); } +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) +{ + write8(0xf3); + write16(0x2a0f); + ModRM(3, to, from); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * +//********************************************************************************** +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5b0f, 0 ); } +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); } + +//**********************************************************************************/ +//CVTPS2DQ: Packed Single Precision FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0x5b0f ); } +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } + +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { write8(0xf3); SSERtoR(0x5b0f); } +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINPS: Return Packed Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5d0f, 0 ); } +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5d0f ); } + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINSS: Return Scalar Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMAXSW: Packed Signed Integer Word Maximum * +//********************************************************************************** +//missing + // SSE_PMAXSW_M64_to_MM +// SSE2_PMAXSW_M128_to_XMM +// SSE2_PMAXSW_XMM_to_XMM +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEE0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMINSW: Packed Signed Integer Word Minimum * +//********************************************************************************** +//missing + // SSE_PMINSW_M64_to_MM +// SSE2_PMINSW_M128_to_XMM +// SSE2_PMINSW_XMM_to_XMM +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEA0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SHUFPS: Shuffle Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8( imm8 ); } +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } + +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset, u8 imm8 ) +{ + write16(0xc60f); + + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } + write8(imm8); +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSHUFD: Shuffle Packed DoubleWords * +//********************************************************************************** +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_PSHUFD_XMM_to_XMM(to, from, imm8); + } + else { + SSERtoR66( 0x700F ); + write8( imm8 ); + } +} +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { SSEMtoR66( 0x700F ); write8( imm8 ); } + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF2); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF2); SSEMtoR(0x700F, 1); write8(imm8); } +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF3); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, u32 from, u8 imm8 ) { write8(0xF3); SSEMtoR(0x700F, 1); write8(imm8); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x140f, 0); } +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x140F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKHPS: Unpack and Interleave High Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR(0x150f, 0); } +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x150F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVPS : Packed Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR( 0x5e0F, 0 ); } +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5e0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVSS : Scalar Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, u32 from ) { SSE_SS_MtoR( 0x5e0F, 0 ); } +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5e0F ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//STMXCSR : Store Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_STMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//LDMXCSR : Load Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_LDMXCSR( u32 from ) { + write16( 0xAE0F ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PADDB,PADDW,PADDD : Add Packed Integers * +//********************************************************************************** +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); } +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFC0F ); } +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFD0F ); } +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFE0F ); } + +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, u32 from ) { SSEMtoR66( 0xD40F ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x640F ); } +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x640F ); } +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x650F ); } +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x660F ); } +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x740F ); } +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0x750F ); } +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_XMM_to_XMM(to, from); + } + else { + SSERtoR66( 0x760F ); + } +} + +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, u32 from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_M128_to_XMM(to, from); + } + else { + SSEMtoR66( 0x760F ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); } +void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); } +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF80F ); } +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xF90F ); } +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFA0F ); } +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, u32 from ){ SSEMtoR66( 0xFB0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66(0x6E0F); } +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_R_to_XMM(to, from); + } + else { + SSERtoR66(0x6E0F); + } +} + +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0x6e0f ); + ModRM( 0, to, from ); +} + +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + write8(0x66); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + + write16( 0x6e0f ); + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); } +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_R(to, from); + } + else { + _SSERtoR66(0x7E0F); + } +} + +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0x66); + write16( 0x7e0f ); + ModRM( 0, from, to ); +} + +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset); + } + else { + write8(0x66); + write16( 0x7e0f ); + + if( offset == 0 ) { + ModRM( 0, from, to ); + } + else if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } +void SSE2_POR_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xEB0F ); } + +// logical and to &= from +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDB0F ); } +void SSE2_PAND_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDB0F ); } + +// to = (~to) & from +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDF0F ); } +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDF0F ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PXOR : SSE Bitwise XOR * +//********************************************************************************** +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEF0F ); } +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEF0F ) }; +/////////////////////////////////////////////////////////////////////////////////////// + +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, u32 from) {SSEMtoR66(0x6F0F); } +void SSE2_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ){SSERtoM66(0x7F0F);} +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSERtoR66(0x6F0F); } + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xF3); SSEMtoR(0x6F0F, 0); } +void SSE2_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from) { write8(0xF3); SSERtoM(0x7F0F, 0); } +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { write8(0xF3); SSERtoR(0x6F0F); } + +// shift right logical + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD10F); } +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); } +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD20F); } +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); } +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xD30F); } +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 3 , to ); + write8( imm8 ); +} + +// shift right arithmetic + +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); } +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE10F); } +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE20F); } +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xE20F); } +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +// shift left logical + +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); } +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF10F); } +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); } +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF20F); } +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); } +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66(0xF30F); } +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + // FIXME + write8( 0x66 ); + write16( 0x730F ); + ModRM( 3, 7 , to ); + write8( imm8 ); +} + +// + +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEE0F ); } +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEE0F ); } + +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); } +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDE0F ); } + +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); } +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEA0F ); } + +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); } +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xDA0F ); } + +// + +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); } +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xEC0F ); } + +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); } +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xED0F ); } + +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); } +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE80F ); } + +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); } +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, u32 from ){ SSEMtoR66( 0xE90F ); } + +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD80F ); } +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xD90F ); } + +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDC0F ); } +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, u32 from ) { SSEMtoR66( 0xDD0F ); } + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x630F ); } +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x630F ); } +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6B0F ); } + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x670F ); } + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x600F ); } +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x600F ); } + +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x680F ); } + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x610F ); } +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x690F ); } + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x620F ); } +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6A0F ); } + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6C0F ); } + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0x6D0F ); } + +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xD50F ); } +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xE50F ); } + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, u32 from) { SSEMtoR66( 0xF40F ); } + +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); } + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); } +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); } + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf2); SSERtoR( 0x7c0f ); } +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, u32 from){ write8(0xf2); SSEMtoR( 0x7c0f, 0 ); } + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { + write8(0xf3); + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0x120f); + ModRM( 3, to, from ); +} + +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x120f, 0); } +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x160f); } +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, u32 from) { write8(0xf3); SSEMtoR(0x160f, 0); } + +// SSE-X +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQA_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset); + else SSE_MOVAPSRmtoROffset(to, from, offset); +} + +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset); + else SSE_MOVAPSRtoRmOffset(to, from, offset); +} + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQU_XMM_to_M128( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); + else SSE_MOVSS_M32_to_XMM(to, from); +} + +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); + else SSE_MOVSS_XMM_to_M32(to, from); +} + +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from); + else SSE_MOVSS_XMM_to_Rm(to, from); +} + +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset); + else SSE_MOVSS_RmOffset_to_XMM(to, from, offset); +} + +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, u32 offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset); + else SSE_MOVSS_XMM_to_RmOffset(to, from, offset); +} + +void SSEX_POR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); + else SSE_ORPS_M128_to_XMM(to, from); +} + +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); + else SSE_ORPS_XMM_to_XMM(to, from); +} + +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); + else SSE_XORPS_M128_to_XMM(to, from); +} + +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); + else SSE_XORPS_XMM_to_XMM(to, from); +} + +void SSEX_PAND_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); + else SSE_ANDPS_M128_to_XMM(to, from); +} + +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); + else SSE_ANDPS_XMM_to_XMM(to, from); +} + +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, u32 from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); + else SSE_ANDNPS_M128_to_XMM(to, from); +} + +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); + else SSE_ANDNPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); + else SSE_UNPCKLPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); + else SSE_UNPCKLPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, u32 from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); + else SSE_UNPCKHPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); + else SSE_UNPCKHPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); + if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); + } + else { + SSE_MOVHLPS_XMM_to_XMM(to, from); + } +} + +// SSE2 emulation +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_SHUFPS_XMM_to_XMM(to, from, 0x4e); + SSE_SHUFPS_XMM_to_XMM(to, to, 0x4e); +} + +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, u32 from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE_MOVLPS_M64_to_XMM(to, from); +} + +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE2EMU_MOVSD_XMM_to_XMM(to, from); +} + +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, u32 offset ) +{ + MOV32RmtoROffset(EAX, from, offset); + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, EAX); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} + +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, u32 offset ) +{ + SSE_MOVSS_XMM_to_M32((u32)p, from); + MOV32MtoR(EAX, (u32)p); + MOV32RtoRmOffset(to, EAX, offset); +} + +extern void SetMMXstate(); + +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + SSE_MOVLPS_XMM_to_M64((u32)p, from); + MOVQMtoR(to, (u32)p); + SetMMXstate(); +} + +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + MOVQRtoM((u32)p, from); + SSE_MOVLPS_M64_to_XMM(to, (u32)p); + SetMMXstate(); +} + +/****************************************************************************/ +/* SSE2 Emulated functions for SSE CPU's by kekko */ +/****************************************************************************/ +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { + MOV32ItoR(EAX, (u32)&p); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + MOV32ItoR(ECX, (u32)imm8); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 2); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 4); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 6); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + SUB32ItoR(EBX, 12); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + MOV32ItoR(to, (u32)&p); + SSE_MOVUPSRtoRm(to, from); + MOV32RmtoR(to, to); +} + + +extern void SetFPUstate(); +extern void _freeMMXreg(int mmxreg); + +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { + SetFPUstate(); + _freeMMXreg(7); + SSE_MOVAPS_XMM_to_M128((u32)f, from); + + FLD32((u32)&f[0]); + FISTP32((u32)&p2[0]); + FLD32((u32)&f[1]); + FISTP32((u32)&p2[1]); + FLD32((u32)&f[2]); + FISTP32((u32)&p2[2]); + FLD32((u32)&f[3]); + FISTP32((u32)&p2[3]); + + SSE_MOVAPS_M128_to_XMM(to, (u32)p2); +} + +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, u32 from ) { + SetFPUstate(); + _freeMMXreg(7); + FILD32((u32)from); + FSTP32((u32)&f[0]); + FILD32((u32)from+4); + FSTP32((u32)&f[1]); + FILD32((u32)from+8); + FSTP32((u32)&f[2]); + FILD32((u32)from+12); + FSTP32((u32)&f[3]); + + SSE_MOVAPS_M128_to_XMM(to, (u32)f); +} + +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&p); + SSE_MOVUPSRtoRm(EAX, from); + MOV32RmtoR(EAX, EAX); + MOV32RtoM(to, EAX); +} + +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, from); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} diff --git a/branches/pcsx2_0.9.2/x86/recCOP2.c b/branches/pcsx2_0.9.2/x86/recCOP2.c new file mode 100644 index 0000000..70d1541 --- /dev/null +++ b/branches/pcsx2_0.9.2/x86/recCOP2.c @@ -0,0 +1,744 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#include +#include +#include +#include "Common.h" +#include "Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "iVU0micro.h" +#include "iVUmicro.h" + + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// cycle cycles statusflag macflag clipflag +_vuopinfo g_cop2info = {0, 0, 1, 1, 1, 0, 0}; + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) +#define _Cc_ (cpuRegs.code & 0x03) + +#define REC_COP2_FUNC(f, delreg) \ + void f(); \ + void rec##f() { \ + SysPrintf("cop2 "#f" called\n"); \ + SetFPUstate(); \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_NOCONST); \ + CALLFunc((u32)f); \ + _freeX86regs(); \ + branch = 2; \ +} + +#define INTERPRETATE_COP2_FUNC(f) \ +void recV##f() { \ + MOV32ItoM((u32)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((u32)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((u32)V##f); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +extern u32 dumplog; +#define REC_COP2_VU0_Q(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +void rec_C2UNK() +{ + SysPrintf("Cop2 bad opcode:%x\n",cpuRegs.code); +} + +void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) +{ + SysPrintf("Cop2 bad _vuRegs code:%x\n",cpuRegs.code); +} + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn); + +void (*recCOP2t[32])(); +void (*recCOP2_BC2t[32])(); +void (*recCOP2SPECIAL1t[64])(); +void (*recCOP2SPECIAL2t[128])(); + +void recCOP2(); +void recCOP2_SPECIAL(); +void recCOP2_BC2(); +void recCOP2_SPECIAL2(); + +extern void _vu0WaitMicro(); + +static void recCFC2() +{ + int mmreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteGPRtoXMMreg(_Rt_, 2); + + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE)) >= 0 ) { + + if( _Fs_ >= 16 ) { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + + if( EEINST_ISLIVE1(_Rt_) ) { + _signExtendGPRtoMMX(mmreg, _Rt_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + else { + MOVDMtoMMX(mmreg, (u32)&VU0.VI[ _Fs_ ].UL); + } + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&VU0.VI[ _Fs_ ].UL); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // no sign extending + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1],0); + } + else { + CDQ(); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + + _eeOnWriteReg(_Rt_, 1); +} + +static void recCTC2() +{ + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( GPR_IS_CONST1(_Rt_) ) { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + if( g_cpuConstRegs[_Rt_].UL[0] & 2 ) { + CALLFunc((u32)vu0ResetRegs); + } + + if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 ) { + CALLFunc((u32)vu1ResetRegs); + } + + MOV16ItoM((u32)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c); + break; + + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + MOV32ItoM((u32)&VU1.VI[REG_TPC].UL, g_cpuConstRegs[_Rt_].UL[0]&0xffff); + PUSH32I(g_cpuConstRegs[_Rt_].UL[0]&0xffff); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + MOV32ItoM((u32)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + _eeMoveGPRtoR(EAX, _Rt_); + + TEST32ItoR(EAX,0x2); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu0ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX,0x200); + j8Ptr[0] = JZ8(0); + CALLFunc((u32)vu1ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EAX,0x0C0C); + MOV16RtoM((u32)&VU0.VI[REG_FBRST].UL,EAX); + break; + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((u32)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + _eeMoveGPRtoR(EAX, _Rt_); + MOV16RtoM((u32)&VU1.VI[REG_TPC].UL,EAX); + + PUSH32R(EAX); + CALLFunc((u32)vu1ExecMicro); // Execute VU1 Micro SubRoutine + ADD32ItoR(ESP,4); + + x86SetJ8( j8Ptr[0] ); + break; + default: + _eeMoveGPRtoM((u32)&VU0.VI[_Fs_].UL,_Rt_); + break; + } + } +} + +static void recQMFC2(void) +{ + int t0reg, fsreg; + _xmmregs temp; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + + // could 'borrow' the reg + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ); + + if( fsreg >= 0 ) { + if( xmmregs[fsreg].mode & MODE_WRITE ) { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg); + + // change regs + temp = xmmregs[t0reg]; + xmmregs[t0reg] = xmmregs[fsreg]; + xmmregs[fsreg] = temp; + } + else { + // swap regs + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + + xmmregs[fsreg] = xmmregs[t0reg]; + xmmregs[t0reg].inuse = 0; + } + } + else { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( t0reg >= 0 ) { + SSE_MOVAPS_M128_to_XMM( t0reg, (u32)&VU0.VF[_Fs_].UD[0]); + } + else { + _recMove128MtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], (u32)&VU0.VF[_Fs_].UL[0]); + } + } + + _clearNeededXMMregs(); +} + +static void recQMTC2() +{ + int mmreg, fsreg; + + if (cpuRegs.code & 1) { + iFlushCall(FLUSH_NOCONST); + CALLFunc((u32)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg); + } + else { + // swap regs + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + xmmregs[mmreg] = xmmregs[fsreg]; + xmmregs[mmreg].mode = MODE_WRITE; + xmmregs[fsreg].inuse = 0; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((u32)&cpuRegs.GPR.r[_Rt_], mmreg); + + // swap regs + xmmregs[mmreg].type = XMMTYPE_VFREG; + xmmregs[mmreg].VU = 0; + xmmregs[mmreg].reg = _Fs_; + xmmregs[mmreg].mode = MODE_WRITE; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg); + SSE_MOVHPS_M64_to_XMM(fsreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[2]); + } + else { + + if( GPR_IS_CONST1( _Rt_ ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 ); + _flushConstReg(_Rt_); + } + + SSE_MOVAPS_M128_to_XMM(fsreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + } + } + else { + _deleteEEreg(_Rt_, 0); + _recMove128MtoM((u32)&VU0.VF[_Fs_].UL[0], (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + } + + _clearNeededXMMregs(); +} + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls) +{ + _vuRegsCOP22(&VU0, &pinst->vuregs); + if( !dostalls ) return; + + _recvuTestLowerStalls(&VU0, &pinst->vuregs); + + switch(VU0.code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU0.code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + pinst->vuregs.VIwrite |= (1<vuregs.VIwrite |= (1<vuregs.VIwrite & (1 << REG_CLIP_FLAG)) { + _recAddWriteBack(vucycle+4, 1<vuregs.VIwrite & (1 << REG_Q)) { + _recAddWriteBack(vucycle+pinst->vuregs.cycles, 1<cycle = vucycle; + _recvuAddLowerStalls(&VU0, &pinst->vuregs); + _recvuTestPipes(&VU0); + + vucycle++; +} + +////////////////////////////////////////////////////////////////////////// +// BC2: Instructions +////////////////////////////////////////////////////////////////////////// +REC_COP2_FUNC(BC2F, 0); +REC_COP2_FUNC(BC2T, 0); +REC_COP2_FUNC(BC2FL, 0); +REC_COP2_FUNC(BC2TL, 0); + +////////////////////////////////////////////////////////////////////////// +// Special1 instructions +////////////////////////////////////////////////////////////////////////// +//TODO: redirect all the opcodes to the ivu0micro same functions +REC_COP2_VU0(IADD); +REC_COP2_VU0(IADDI); +REC_COP2_VU0(ISUB); +REC_COP2_VU0(IOR); +REC_COP2_VU0(IAND); +REC_COP2_VU0(OPMSUB); +REC_COP2_VU0(MADDq); +REC_COP2_VU0(MADDi); +REC_COP2_VU0(MSUBq); +REC_COP2_VU0(MSUBi); +REC_COP2_VU0(SUBi); +REC_COP2_VU0(SUBq); +REC_COP2_VU0(MULi); +REC_COP2_VU0(MULq); +REC_COP2_VU0(MAXi); +REC_COP2_VU0(MINIi); +REC_COP2_VU0(MUL); +REC_COP2_VU0(MAX); +REC_COP2_VU0(MADD); +REC_COP2_VU0(MSUB); + +REC_COP2_VU0(MINIx); +REC_COP2_VU0(MINIy); +REC_COP2_VU0(MINIz); +REC_COP2_VU0(MINIw); + +REC_COP2_VU0(MAXx); +REC_COP2_VU0(MAXy); +REC_COP2_VU0(MAXz); +REC_COP2_VU0(MAXw); + +REC_COP2_VU0(MULx); +REC_COP2_VU0(MULy); +REC_COP2_VU0(MULz); +REC_COP2_VU0(MULw); + +REC_COP2_VU0(ADD); +REC_COP2_VU0(ADDi); +REC_COP2_VU0(ADDq); +REC_COP2_VU0(ADDx); +REC_COP2_VU0(ADDy); +REC_COP2_VU0(ADDz); +REC_COP2_VU0(ADDw); + +REC_COP2_VU0(SUBx); +REC_COP2_VU0(SUBy); +REC_COP2_VU0(SUBz); +REC_COP2_VU0(SUBw); + +REC_COP2_VU0(MADDx); +REC_COP2_VU0(MADDy); +REC_COP2_VU0(MADDz); +REC_COP2_VU0(MADDw); + +REC_COP2_VU0(MSUBx); +REC_COP2_VU0(MSUBy); +REC_COP2_VU0(MSUBz); +REC_COP2_VU0(MSUBw); + +REC_COP2_VU0(SUB); +REC_COP2_VU0(MINI); + +////////////////////////////////////////////////////////////////////////// +// Special2 instructions +////////////////////////////////////////////////////////////////////////// + +REC_COP2_VU0(CLIP); +REC_COP2_VU0(LQI); +REC_COP2_VU0(SQI); +REC_COP2_VU0(LQD); +REC_COP2_VU0(SQD); +REC_COP2_VU0(MTIR); +REC_COP2_VU0(MFIR); +REC_COP2_VU0(ILWR); +REC_COP2_VU0(ISWR); +REC_COP2_VU0(RINIT); +REC_COP2_VU0(RXOR); +REC_COP2_VU0(RNEXT); +REC_COP2_VU0(RGET); + +REC_COP2_VU0(ITOF0); +REC_COP2_VU0(ITOF4); +REC_COP2_VU0(ITOF12); +REC_COP2_VU0(ITOF15); +REC_COP2_VU0(FTOI0); +REC_COP2_VU0(FTOI4); +REC_COP2_VU0(FTOI12); +REC_COP2_VU0(FTOI15); +REC_COP2_VU0(MADDA); +REC_COP2_VU0(MSUBA); +REC_COP2_VU0(MADDAi); +REC_COP2_VU0(MADDAq); +REC_COP2_VU0(MADDAx); +REC_COP2_VU0(MADDAy); +REC_COP2_VU0(MADDAz); +REC_COP2_VU0(MADDAw); +REC_COP2_VU0(MSUBAi); +REC_COP2_VU0(MSUBAq); +REC_COP2_VU0(MSUBAx); +REC_COP2_VU0(MSUBAy); +REC_COP2_VU0(MSUBAz); +REC_COP2_VU0(MSUBAw); +REC_COP2_VU0(ADDAi); +REC_COP2_VU0(ADDA); +REC_COP2_VU0(SUBA); +REC_COP2_VU0(MULA); +REC_COP2_VU0(ADDAq); +REC_COP2_VU0(ADDAx); +REC_COP2_VU0(ADDAy); +REC_COP2_VU0(ADDAz); +REC_COP2_VU0(ADDAw); +REC_COP2_VU0(SUBAi); +REC_COP2_VU0(SUBAq); +REC_COP2_VU0(SUBAx); +REC_COP2_VU0(SUBAy); +REC_COP2_VU0(SUBAz); +REC_COP2_VU0(SUBAw); +REC_COP2_VU0(MULAi); +REC_COP2_VU0(MULAq); +REC_COP2_VU0(MULAx); +REC_COP2_VU0(MULAy); +REC_COP2_VU0(MULAz); +REC_COP2_VU0(MULAw); +REC_COP2_VU0(OPMULA); +REC_COP2_VU0(MOVE); +REC_COP2_VU0_Q(DIV); +REC_COP2_VU0_Q(SQRT); +REC_COP2_VU0_Q(RSQRT); +REC_COP2_VU0(MR32); +REC_COP2_VU0(ABS); + +void recVNOP(){} +void recVWAITQ(){} +INTERPRETATE_COP2_FUNC(CALLMS); +INTERPRETATE_COP2_FUNC(CALLMSR); + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn); + +// information +void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xf; +} + +void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIread = 1<<_Fs_; +} + +void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFwrite = _Fs_; + VUregsn->VFwxyzw= 0xf; +} + +void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIwrite = 1<<_Fs_; +} + +void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, +}; + +void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw, + _vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw, + _vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw, + _vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi, + _vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi, + _vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI, + _vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2, +}; + +void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw, + _vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw, + _vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15, + _vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP, + _vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi, + _vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP, + _vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD, + _vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR, + _vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, +}; + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2t[_Rs_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn) +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + _vuRegsCOP2SPECIAL2t[opc](VU, VUregsn); +} + +// recompilation +void (*recCOP2t[32])() = { + rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, + recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, +}; + +void (*recCOP2_BC2t[32])() = { + recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, +}; + +void (*recCOP2SPECIAL1t[64])() = { + recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, + recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, + recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, + recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, + recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, + recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, + recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, + recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2, +}; + +void (*recCOP2SPECIAL2t[128])() = { + recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw, + recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw, + recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15, + recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP, + recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi, + recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP, + recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD, + recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR, + recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, +}; + +void recCOP22() +{ + cinfo = &g_cop2info; + g_VUregs = &g_pCurInstInfo->vuregs; + VU0.code = cpuRegs.code; + g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2 + recCOP2t[_Rs_](); + _freeX86regs(); +} + +void recCOP2_SPECIAL() +{ + recCOP2SPECIAL1t[_Funct_](); +} + +void recCOP2_BC2() +{ + recCOP2_BC2t[_Rt_](); +} + +void recCOP2_SPECIAL2() +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + recCOP2SPECIAL2t[opc](); +} diff --git a/branches/pcsx2_0.9.2/zlib/ChangeLog b/branches/pcsx2_0.9.2/zlib/ChangeLog new file mode 100644 index 0000000..85b8253 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Lvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/branches/pcsx2_0.9.2/zlib/Makefile.am b/branches/pcsx2_0.9.2/zlib/Makefile.am new file mode 100644 index 0000000..ff26496 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libpcsx2zlib.a + +libpcsx2zlib_a_SOURCES = \ +adler32.c crc32.c deflate.h inffast.c inflate.c inftrees.h trees.h zlib.h \ +crc32.h gzio.c inffast.h inflate.h uncompr.c zutil.c \ +compress.c deflate.c infback.c inffixed.h inftrees.c trees.c zconf.h zutil.h diff --git a/branches/pcsx2_0.9.2/zlib/README b/branches/pcsx2_0.9.2/zlib/README new file mode 100644 index 0000000..718aab2 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/branches/pcsx2_0.9.2/zlib/adler32.c b/branches/pcsx2_0.9.2/zlib/adler32.c new file mode 100644 index 0000000..bc0842f --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/branches/pcsx2_0.9.2/zlib/compress.c b/branches/pcsx2_0.9.2/zlib/compress.c new file mode 100644 index 0000000..e7ea2c5 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/branches/pcsx2_0.9.2/zlib/crc32.c b/branches/pcsx2_0.9.2/zlib/crc32.c new file mode 100644 index 0000000..aa8b984 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/branches/pcsx2_0.9.2/zlib/crc32.h b/branches/pcsx2_0.9.2/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/branches/pcsx2_0.9.2/zlib/deflate.c b/branches/pcsx2_0.9.2/zlib/deflate.c new file mode 100644 index 0000000..efe7b63 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/branches/pcsx2_0.9.2/zlib/deflate.h b/branches/pcsx2_0.9.2/zlib/deflate.h new file mode 100644 index 0000000..26775e9 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/branches/pcsx2_0.9.2/zlib/gzio.c b/branches/pcsx2_0.9.2/zlib/gzio.c new file mode 100644 index 0000000..4cfd64f --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/branches/pcsx2_0.9.2/zlib/infback.c b/branches/pcsx2_0.9.2/zlib/infback.c new file mode 100644 index 0000000..5cf5d22 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/branches/pcsx2_0.9.2/zlib/inffast.c b/branches/pcsx2_0.9.2/zlib/inffast.c new file mode 100644 index 0000000..63aa440 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/branches/pcsx2_0.9.2/zlib/inffast.h b/branches/pcsx2_0.9.2/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/branches/pcsx2_0.9.2/zlib/inffixed.h b/branches/pcsx2_0.9.2/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/branches/pcsx2_0.9.2/zlib/inflate.c b/branches/pcsx2_0.9.2/zlib/inflate.c new file mode 100644 index 0000000..71fe3cc --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/branches/pcsx2_0.9.2/zlib/inflate.h b/branches/pcsx2_0.9.2/zlib/inflate.h new file mode 100644 index 0000000..b696512 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/branches/pcsx2_0.9.2/zlib/inftrees.c b/branches/pcsx2_0.9.2/zlib/inftrees.c new file mode 100644 index 0000000..55fd27b --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/branches/pcsx2_0.9.2/zlib/inftrees.h b/branches/pcsx2_0.9.2/zlib/inftrees.h new file mode 100644 index 0000000..1dbfe53 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/branches/pcsx2_0.9.2/zlib/trees.c b/branches/pcsx2_0.9.2/zlib/trees.c new file mode 100644 index 0000000..d0bce9f --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/branches/pcsx2_0.9.2/zlib/trees.h b/branches/pcsx2_0.9.2/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/branches/pcsx2_0.9.2/zlib/uncompr.c b/branches/pcsx2_0.9.2/zlib/uncompr.c new file mode 100644 index 0000000..82ebef7 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/branches/pcsx2_0.9.2/zlib/zconf.h b/branches/pcsx2_0.9.2/zlib/zconf.h new file mode 100644 index 0000000..b073c9e --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/branches/pcsx2_0.9.2/zlib/zlib.h b/branches/pcsx2_0.9.2/zlib/zlib.h new file mode 100644 index 0000000..d54ac94 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/branches/pcsx2_0.9.2/zlib/zutil.c b/branches/pcsx2_0.9.2/zlib/zutil.c new file mode 100644 index 0000000..db137f8 --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/branches/pcsx2_0.9.2/zlib/zutil.h b/branches/pcsx2_0.9.2/zlib/zutil.h new file mode 100644 index 0000000..e300f7c --- /dev/null +++ b/branches/pcsx2_0.9.2/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..d39c8ab --- /dev/null +++ b/build.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# Usage: sh build.sh [option] +# option can be all (rebuilds everything), clean, or nothing (incremental build) +# Modify the individual build.sh for specific program options like debug symbols +export PCSX2OPTIONS="--enable-debug --enable-devbuild --enable-sse2 --prefix `pwd`" +export PCSX2PLUGINS="`pwd`/bin/plugins" +curdir=`pwd` + +cd ${curdir}/plugins +sh build.sh $@ + +if [ $? -ne 0 ] +then +echo Error with building plugins +exit 1 +fi + +cd ${curdir}/pcsx2 +#mkdir debugdev +#cd debugdev +#sh ../build.sh $@ +sh build.sh $@ + +if [ $? -ne 0 ] +then +echo Error with building pcsx2 +exit 1 +fi diff --git a/pcsx2/CDVD.c b/pcsx2/CDVD.c new file mode 100644 index 0000000..af6fd1d --- /dev/null +++ b/pcsx2/CDVD.c @@ -0,0 +1,1862 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2007 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PsxCommon.h" +#include "CDVDiso.h" + +cdvdStruct cdvd; + +char *mg_zones[8] = {"Japan", "USA", "Europe", "Oceania", "Asia", "Russia", "China", "Mexico"}; + +char *nCmdName[0x100]= { + "CdSync", "CdNop", "CdStandby", "CdStop", + "CdPause", "CdSeek", "CdRead", "CdReadCDDA", + "CdReadDVDV", "CdGetToc", "", "NCMD_B", + "CdReadKey", "", "sceCdReadXCDDA", "sceCdChgSpdlCtrl", +}; + +char *sCmdName[0x100]= { + "", "sceCdGetDiscType", "sceCdReadSubQ", "subcommands",//sceCdGetMecaconVersion, read/write console id, read renewal date + "", "sceCdTrayState", "sceCdTrayCtrl", "", + "sceCdReadClock", "sceCdWriteClock", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdSetHDMode", "", "", "sceCdPowerOff", + "", "", "sceCdReadILinkID", "sceCdWriteILinkID", /*10*/ + "sceAudioDigitalOut", "sceForbidDVDP", "sceAutoAdjustCtrl", "sceCdReadModelNumber", + "sceWriteModelNumber", "sceCdForbidCD", "sceCdBootCertify", "sceCdCancelPOffRdy", + "sceCdBlueLEDCtl", "", "sceRemote2Read", "sceRemote2_7", + "sceRemote2_6", "sceCdWriteWakeUpTime", "sceCdReadWakeUpTime", "", /*20*/ + "sceCdRcBypassCtl", "", "", "", + "", "sceCdNoticeGameStart", "", "", + "sceCdXBSPowerCtl", "sceCdXLEDCtl", "sceCdBuzzerCtl", "", + "", "sceCdSetMediumRemoval", "sceCdGetMediumRemoval", "sceCdXDVRPReset", /*30*/ + "", "", "__sceCdGetOSDVER", "", + "", "", "", "", + "", "", "", "", + "sceCdOpenConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdCloseConfig", /*40*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*50*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*60*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "", "", "", "", /*70*/ + "", "", "", "", + "", "", "", "", + "", "", "", "", + "mechacon_auth_0x80", "mechacon_auth_0x81", "mechacon_auth_0x82", "mechacon_auth_0x83", /*80*/ + "mechacon_auth_0x84", "mechacon_auth_0x85", "mechacon_auth_0x86", "mechacon_auth_0x87", + "mechacon_auth_0x88", "", "", "", + "", "sceMgWriteData", "sceMgReadData", "mechacon_auth_0x8F", + "sceMgWriteHeaderStart", "sceMgReadBITLength", "sceMgWriteDatainLength", "sceMgWriteDataoutLength", /*90*/ + "sceMgReadKbit", "sceMgReadKbit2", "sceMgReadKcon", "sceMgReadKcon2", + "sceMgReadIcvPs2", "", "", "", + "", "", "", "", + /*A0, no sCmds above?*/ +}; + +// NVM (eeprom) layout info +typedef struct { + u32 biosVer; // bios version that this eeprom layout is for + s32 config0; // offset of 1st config block + s32 config1; // offset of 2nd config block + s32 config2; // offset of 3rd config block + s32 consoleId; // offset of console id (?) + s32 ilinkId; // offset of ilink id (ilink mac address) + s32 modelNum; // offset of ps2 model number (eg "SCPH-70002") + s32 osdver; // offset of OSDVER for PStwo +} NVMLayout; + +#define NVM_FORMAT_MAX 2 +NVMLayout nvmlayouts[NVM_FORMAT_MAX] = +{ + {0x000, 0x280, 0x300, 0x200, 0x1C8, 0x1C0, 0x1A0, 0x180}, // eeproms from bios v0.00 and up + {0x146, 0x270, 0x2B0, 0x200, 0x1C8, 0x1E0, 0x1B0, 0x180}, // eeproms from bios v1.70 and up +}; + + +unsigned long cdvdReadTime=0; + +#define CDVDREAD_INT(eCycle) PSX_INT(19, eCycle) + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +#define SetResultSize(size) \ + cdvd.ResultC = size; cdvd.ResultP = 0; \ + cdvd.sDataIn&=~0x40; + + +/* is cdvd.Status only for NCMDS? (linuzappz) */ +enum cdvdStatus { + CDVD_STATUS_NONE = 0x00, // not sure ;) + CDVD_STATUS_SEEK_COMPLETE = 0x0A, +}; + +static int mg_BIToffset(u8 *buffer); + +FILE *_cdvdOpenMechaVer() { + char *ptr; + int i; + char file[256]; + char Bios[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the mecha ver file + sprintf(file, "%s", Bios); + ptr = file; i = (int)strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "MEC"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenMechaVer: Error creating %s", file); + exit(1); + } + fputc(0x03, fd); + fputc(0x06, fd); + fputc(0x02, fd); + fputc(0x00, fd); + } + return fd; +} +s32 cdvdGetMechaVer(u8* ver) +{ + FILE* fd = _cdvdOpenMechaVer(); + if (fd == NULL) return 1; + fseek(fd, 0, SEEK_SET); + fread(ver, 1, 4, fd); + fclose(fd); + return 0; +} + +FILE *_cdvdOpenNVM() { + char *ptr; + int i; + char Bios[256]; + char file[256]; + FILE* fd; + + // get the name of the bios file + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + // use the bios filename to get the name of the nvm file + sprintf(file, "%s", Bios); + ptr = file; i = (int)strlen(file); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = '\0'; + strcat(file, "NVM"); + + // if file doesnt exist, create empty one + fd = fopen(file, "r+b"); + if (fd == NULL) { + SysPrintf("NVM File Not Found , Creating Blank File\n"); + fd = fopen(file, "wb"); + if (fd == NULL) { + SysMessage("_cdvdOpenNVM: Error creating %s", file); + exit(1); + } + for (i=0; i<1024; i++) fputc(0, fd); + } + return fd; +} + +// +// the following 'cdvd' functions all return 0 if successful +// + +s32 cdvdReadNVM(u8 *dst, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fread(dst, 1, bytes, fd); + fclose(fd); + return 0; +} +s32 cdvdWriteNVM(const u8 *src, int offset, int bytes) { + FILE* fd = _cdvdOpenNVM(); + if (fd == NULL) return 1; + fseek(fd, offset, SEEK_SET); + fwrite(src, 1, bytes, fd); + fclose(fd); + return 0; +} + +#define GET_NVM_DATA(buff, offset, size, fmtOffset) getNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) +#define SET_NVM_DATA(buff, offset, size, fmtOffset) setNvmData(buff, offset, size, BiosVersion, offsetof(NVMLayout, fmtOffset)) + +s32 getNvmData(u8* buffer, s32 offset, s32 size, u32 biosVersion, s32 fmtOffset) +{ + // find the correct bios version + NVMLayout* nvmLayout = NULL; + s32 nvmIdx; + for(nvmIdx=0; nvmIdx= cdvd.CNumBlocks) + return 1; + else if( + ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))|| + ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))|| + ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7)) + ) + { + memset(config, 0, 16); + return 0; + } + + // get config data + if(cdvd.COffset == 0) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config0); else + if(cdvd.COffset == 2) + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); + else + return GET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); +} +s32 cdvdWriteConfig(const u8* config) +{ + // make sure its in write mode + if(cdvd.CReadWrite != 1) + return 1; + // check if block index is in bounds + else if(cdvd.CBlockIndex >= cdvd.CNumBlocks) + return 1; + else if( + ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))|| + ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))|| + ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7)) + ) + return 0; + + // get config data + if(cdvd.COffset == 0) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config0); else + if(cdvd.COffset == 2) + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config2); + else + return SET_NVM_DATA(config, (cdvd.CBlockIndex++)*16, 16, config1); +} + + +void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { + char str[256]; + int numbers; + int letters; + unsigned int key_0_3; + unsigned char key_4; + unsigned char key_14; + char exeName[12]; + + // get main elf name + GetPS2ElfName(str); + sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); + SysPrintf("exeName = %s\n",exeName); + + // convert the number characters to a real 32bit number + numbers = ((((exeName[5] - '0'))*10000) + + (((exeName[ 6] - '0'))*1000) + + (((exeName[ 7] - '0'))*100) + + (((exeName[ 9] - '0'))*10) + + (((exeName[10] - '0'))*1) ); + + // combine the lower 7 bits of each char + // to make the 4 letters fit into a single u32 + letters = (int)((exeName[3]&0x7F)<< 0) | + (int)((exeName[2]&0x7F)<< 7) | + (int)((exeName[1]&0x7F)<<14) | + (int)((exeName[0]&0x7F)<<21); + + // calculate magic numbers + key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80 + key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07 + key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03 + + // clear key values + memset(key, 0, 16); + + // store key values + key[ 0] = (key_0_3&0x000000FF)>> 0; + key[ 1] = (key_0_3&0x0000FF00)>> 8; + key[ 2] = (key_0_3&0x00FF0000)>>16; + key[ 3] = (key_0_3&0xFF000000)>>24; + key[ 4] = key_4; + + if(arg2 == 75) + { + key[14] = key_14; + key[15] = 0x05; + } + else if(arg2 == 3075) + { + key[15] = 0x01; + } + else if(arg2 == 4246) + { + // 0x0001F2F707 = sector 0x0001F2F7 dec 0x07 + key[ 0] = 0x07; + key[ 1] = 0xF7; + key[ 2] = 0xF2; + key[ 3] = 0x01; + key[ 4] = 0x00; + key[15] = 0x01; + } + else + { + key[15] = 0x01; + } + + SysPrintf("CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X\n",cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15]); +} + +s32 cdvdGetToc(void* toc) { + s32 ret = CDVDgetTOC(toc); + if(ret == -1) ret = 0x80; + return ret; +/* + cdvdTN diskInfo; + cdvdTD trackInfo; + u8 _time[3]; + u32 type; + int i, err; + + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + type = CDVDgetDiskType(); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + if (type == CDVD_TYPE_CDDA) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x01; + } else + if (type == CDVD_TYPE_PS2DVD) { + if (trackInfo.lsn >= (2048*1024)) { // dual sided + PSXMu8(HW_DMA3_MADR+ 0) = 0x24; + } else { + PSXMu8(HW_DMA3_MADR+ 0) = 0x04; + } + } else + if (type == CDVD_TYPE_PS2CD) { + PSXMu8(HW_DMA3_MADR+ 0) = 0x41; + } + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x04) { + PSXMu8(HW_DMA3_MADR+ 1) = 0x02; + PSXMu8(HW_DMA3_MADR+ 2) = 0xF2; + PSXMu8(HW_DMA3_MADR+ 3) = 0x00; + + if (PSXMu8(HW_DMA3_MADR+ 0) & 0x20) { + PSXMu8(HW_DMA3_MADR+ 4) = 0x41; + PSXMu8(HW_DMA3_MADR+ 5) = 0x95; + } else { + PSXMu8(HW_DMA3_MADR+ 4) = 0x86; + PSXMu8(HW_DMA3_MADR+ 5) = 0x72; + } + PSXMu8(HW_DMA3_MADR+ 6) = 0x00; + PSXMu8(HW_DMA3_MADR+ 7) = 0x00; + PSXMu8(HW_DMA3_MADR+ 8) = 0x00; + PSXMu8(HW_DMA3_MADR+ 9) = 0x00; + PSXMu8(HW_DMA3_MADR+10) = 0x00; + PSXMu8(HW_DMA3_MADR+11) = 0x00; + + PSXMu8(HW_DMA3_MADR+12) = 0x00; + PSXMu8(HW_DMA3_MADR+13) = 0x00; + PSXMu8(HW_DMA3_MADR+14) = 0x00; + PSXMu8(HW_DMA3_MADR+15) = 0x00; + + PSXMu8(HW_DMA3_MADR+16) = 0x00; + PSXMu8(HW_DMA3_MADR+17) = 0x03; + PSXMu8(HW_DMA3_MADR+18) = 0x00; + PSXMu8(HW_DMA3_MADR+19) = 0x00; + + } else { + PSXMu8(HW_DMA3_MADR+ 1) = 0x00; + PSXMu8(HW_DMA3_MADR+ 2) = 0xA0; + PSXMu8(HW_DMA3_MADR+ 7) = itob(diskInfo.strack);//Number of FirstTrack + + PSXMu8(HW_DMA3_MADR+12) = 0xA1; + PSXMu8(HW_DMA3_MADR+17) = itob(diskInfo.etrack);//Number of LastTrack + + PSXMu8(HW_DMA3_MADR+22) = 0xA2;//DiskLength + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+27) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+28) = itob(_time[1]); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) { + err=CDVDgetTD(i, &trackInfo); + LSNtoMSF(_time, trackInfo.lsn); + PSXMu8(HW_DMA3_MADR+i*10+30) = trackInfo.type; + PSXMu8(HW_DMA3_MADR+i*10+32) = err == -1 ? 0 : itob(i); //number + PSXMu8(HW_DMA3_MADR+i*10+37) = itob(_time[2]); + PSXMu8(HW_DMA3_MADR+i*10+38) = itob(_time[1]); + PSXMu8(HW_DMA3_MADR+i*10+39) = itob(_time[0]); + } + } +*/ +} + +s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq) +{ + s32 ret = CDVDreadSubQ(lsn, subq); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayOpen() +{ + s32 ret = CDVDctrlTrayOpen(); + if(ret == -1) ret = 0x80; + return ret; +} + +s32 cdvdCtrlTrayClose() +{ + s32 ret = CDVDctrlTrayClose(); + if(ret == -1) ret = 0x80; + return ret; +} + +// Modified by (efp) - 16/01/2006 +// checks if tray was opened since last call to this func +s32 cdvdGetTrayStatus() +{ + s32 ret = CDVDgetTrayStatus(); + // get current tray state + if (cdCaseopen) return(CDVD_TRAY_OPEN); + + + if (ret == -1) return(CDVD_TRAY_CLOSE); + return(ret); +} +// Note: Is tray status being kept as a var here somewhere? +// cdvdNewDiskCB() can update it's status as well... + +// Modified by (efp) - 16/01/2006 +s32 cdvdGetDiskType() { + // defs 0.9.0 + if(CDVDnewDiskCB) return(cdvd.Type); + + // defs.0.8.1 + if(cdvdGetTrayStatus() == CDVD_TRAY_OPEN) return(CDVD_TYPE_NODISC); + // Note: Hmmm. Need to modify cdvd.Type as well? + // or just throw it out. CDVDgetDiskType() sets type to "NODISC" anyway. + + cdvd.Type = CDVDgetDiskType(); + if (cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if (GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? + return(cdvd.Type); +} // END cdvdGetDiskType() + + +// check whether disc is single or dual layer +// if its dual layer, check what the disctype is and what sector number +// layer1 starts at +// +// args: gets value for dvd type (0=single layer, 1=ptp, 2=otp) +// gets value for start lsn of layer1 +// returns: 1 if on dual layer disc +// 0 if not on dual layer disc +s32 cdvdReadDvdDualInfo(s32* dualType, u32* layer1Start) +{ + u8 toc[2064]; + *dualType = 0; + *layer1Start = 0; + + // if error getting toc, settle for single layer disc ;) + if(cdvdGetToc(toc)) + return 0; + if(toc[14] & 0x60) + { + if(toc[14] & 0x10) + { + // otp dvd + *dualType = 2; + *layer1Start = (toc[25]<<16) + (toc[26]<<8) + (toc[27]) - 0x30000 + 1; + } + else + { + // ptp dvd + *dualType = 1; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + } + else + { + // single layer dvd + *dualType = 0; + *layer1Start = (toc[21]<<16) + (toc[22]<<8) + (toc[23]) - 0x30000 + 1; + } + + return 1; +} + + +void cdvdReset() { + memset(&cdvd, 0, sizeof(cdvd)); + cdvd.sDataIn = 0x40; + cdvd.Ready = 0x4e; + cdCaseopen = 0; + cdvd.Speed = 4; + cdvd.BlockSize = 2064; + cdvdReadTimeRcnt(0); +} +void cdvdReadTimeRcnt(int mode){ // Mode 0 is DVD, Mode 1 is CD + int readsize = 0; // 1 Sector size + int amount = 0; // Total bytes transfered at 1x speed + //if(mode) amount = 153600; + //else + amount = 1280000; + + readsize = amount / cdvd.BlockSize; // Time taken for 1 sector to be read + cdvdReadTime = ((PSXCLK / readsize) / BIAS) / cdvd.Speed; +} + +int cdvdFreeze(gzFile f, int Mode) { + gzfreeze(&cdvd, sizeof(cdvd)); + if (Mode == FREEZE_LOAD) { + if (cdvd.Reading) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + } + } + + return 0; +} + +int cdvdInterrupt() { + return 1; +} + +// Modified by (efp) - 16/01/2006 +void cdvdNewDiskCB() { + cdvd.Type = CDVDgetDiskType(); + if(cdvd.Type == CDVD_TYPE_PS2CD) { + char str[256]; + if(GetPS2ElfName(str) == 1) { + cdvd.Type = CDVD_TYPE_PSCD; + } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. + } // ENDIF- Is the type listed as a PS2 CD? +} // END cdvdNewDiskCB() + +void mechaDecryptBytes(unsigned char* buffer, int size) +{ + int i; + + int shiftAmount = (cdvd.decSet>>4) & 7; + int doXor = (cdvd.decSet) & 1; + int doShift = (cdvd.decSet) & 2; + unsigned char key = cdvd.Key[4]; + + for(i=0; i>shiftAmount) | (buffer[i]<<(8-shiftAmount)); + } +} + +int cdvdReadSector() { + s32 bcr; + +#ifdef CDR_LOG + CDR_LOG("SECTOR %d (BCR %x;%x)\n", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16); +#endif + bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4; + if (bcr < cdvd.BlockSize) { + //SysPrintf("*PCSX2*: cdvdReadSector: bcr < cdvd.BlockSize; %x < %x\n", bcr, cdvd.BlockSize); + if (HW_DMA3_CHCR & 0x01000000) { + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + } + return -1; + } + + // if raw dvd sector 'fill in the blanks' + if (cdvd.BlockSize == 2064) { + // get info on dvd type and layer1 start + u32 layer1Start; + s32 dualType; + s32 layerNum; + u32 lsn = cdvd.Sector; + cdvdReadDvdDualInfo(&dualType, &layer1Start); + + if((dualType == 1) && (lsn >= layer1Start)) { + // dual layer ptp disc + layerNum = 1; + lsn = lsn-layer1Start + 0x30000; + } else if((dualType == 2) && (lsn >= layer1Start)) { + // dual layer otp disc + layerNum = 1; + lsn = ~(layer1Start+0x30000 - 1); + } else { + // single layer disc + // or on first layer of dual layer disc + layerNum = 0; + lsn += 0x30000; + } // ENDLONGIF- Assumed the other dualType is 0. + + PSXMu8(HW_DMA3_MADR+0) = 0x20 | layerNum; + PSXMu8(HW_DMA3_MADR+1) = (u8)(lsn >> 16); + PSXMu8(HW_DMA3_MADR+2) = (u8)(lsn >> 8); + PSXMu8(HW_DMA3_MADR+3) = (u8)(lsn ); + + // sector IED (not calculated at present) + PSXMu8(HW_DMA3_MADR+4) = 0; + PSXMu8(HW_DMA3_MADR+5) = 0; + + // sector CPR_MAI (not calculated at present) + PSXMu8(HW_DMA3_MADR+ 6) = 0; + PSXMu8(HW_DMA3_MADR+ 7) = 0; + PSXMu8(HW_DMA3_MADR+ 8) = 0; + PSXMu8(HW_DMA3_MADR+ 9) = 0; + PSXMu8(HW_DMA3_MADR+10) = 0; + PSXMu8(HW_DMA3_MADR+11) = 0; + + // normal 2048 bytes of sector data + memcpy_fast(PSXM(HW_DMA3_MADR+12), cdr.pTransfer, 2048); + + // 4 bytes of edc (not calculated at present) + PSXMu8(HW_DMA3_MADR+2060) = 0; + PSXMu8(HW_DMA3_MADR+2061) = 0; + PSXMu8(HW_DMA3_MADR+2062) = 0; + PSXMu8(HW_DMA3_MADR+2063) = 0; + } else { + // normal read + memcpy_fast(PSXM(HW_DMA3_MADR), cdr.pTransfer, cdvd.BlockSize); + } + // decrypt sector's bytes + if(cdvd.decSet) + mechaDecryptBytes((unsigned char*)PSXM(HW_DMA3_MADR), cdvd.BlockSize); + +// SysPrintf("sector %x;%x;%x\n", PSXMu8(HW_DMA3_MADR+0), PSXMu8(HW_DMA3_MADR+1), PSXMu8(HW_DMA3_MADR+2)); + + HW_DMA3_BCR_H16-= (cdvd.BlockSize / (HW_DMA3_BCR_L16*4)); + HW_DMA3_MADR+= cdvd.BlockSize; + //FreezeMMXRegs(0); + + return 0; +} + +int cdvdReadInterrupt() { + + //SysPrintf("cdvdReadInterrupt %x %x %x %x %x\n", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4); + if (cdvd.Readed == 0) { + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + cdvd.Readed = 1; + cdvd.Status = CDVD_STATUS_SEEK_COMPLETE; + + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + if (cdvd.Reading == 1) { + if (cdvd.RErr == 0) { + cdr.pTransfer = CDVDgetBuffer(); + } else cdr.pTransfer = NULL; + if (cdr.pTransfer == NULL) { + cdvd.RetryCntP++; + SysPrintf("READ ERROR %d\n", cdvd.Sector); + if (cdvd.RetryCntP <= cdvd.RetryCnt) { + cdvd.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + } + cdvd.Reading = 0; + } + if (cdvdReadSector() == -1) { + assert( (int)cdvdReadTime > 0 ); + CDVDREAD_INT(cdvdReadTime); + return 0; + } + + cdvd.Sector++; + + if (--cdvd.nSectors <= 0) { + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + return 1; + } + + cdvd.RetryCntP = 0; + cdvd.Reading = 1; + cdr.RErr = CDVDreadTrack(cdvd.Sector, cdvd.ReadMode); + CDVDREAD_INT(cdvdReadTime); + return 0; +} + +void cdvdVsync() { + cdvd.RTCcount++; + if (cdvd.RTCcount < 60) return; + cdvd.RTCcount = 0; + + cdvd.RTC.second++; + if (cdvd.RTC.second < 60) return; + cdvd.RTC.second = 0; + + cdvd.RTC.minute++; + if (cdvd.RTC.minute < 60) return; + cdvd.RTC.minute = 0; + + cdvd.RTC.hour++; + if (cdvd.RTC.hour < 24) return; + cdvd.RTC.hour = 0; + + cdvd.RTC.day++; + if (cdvd.RTC.day < 30) return; + cdvd.RTC.day = 0; + + cdvd.RTC.month++; + if (cdvd.RTC.month < 12) return; + cdvd.RTC.month = 0; + + cdvd.RTC.year++; +} + + +u8 cdvdRead04(void) { // NCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead04(NCMD) %x\n", cdvd.nCommand); +#endif + return cdvd.nCommand; +} + +u8 cdvdRead05(void) { // N-READY +#ifdef CDR_LOG + CDR_LOG("cdvdRead05(NReady) %x\n", cdvd.Ready); +#endif + return cdvd.Ready; +} + +u8 cdvdRead06(void) { // ERROR +#ifdef CDR_LOG + CDR_LOG("cdvdRead06(Error) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead07(void) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdRead07(Break) %x\n", 0); +#endif + return 0; +} + +u8 cdvdRead08(void) { // INTR_STAT +#ifdef CDR_LOG + CDR_LOG("cdvdRead08(IntrReason) %x\n", cdvd.PwOff); +#endif + return cdvd.PwOff; +} + +u8 cdvdRead0A(void) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdRead0A(Status) %x\n", cdvd.Status); +#endif + return cdvd.Status; +} + +u8 cdvdRead0B(void) { // TRAY-STATE (if tray has been opened) + u8 tray = cdvdGetTrayStatus(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0B(Tray) %x\n", tray); +#endif + return tray; +} + +u8 cdvdRead0C(void) { // CRT MINUTE +#ifdef CDR_LOG + CDR_LOG("cdvdRead0C(Min) %x\n", itob((u8)(cdvd.Sector/(60*75)))); +#endif + return itob((u8)(cdvd.Sector/(60*75))); +} + +u8 cdvdRead0D(void) { // CRT SECOND +#ifdef CDR_LOG + CDR_LOG("cdvdRead0D(Sec) %x\n", itob((u8)((cdvd.Sector/75)%60)+2)); +#endif + return itob((u8)((cdvd.Sector/75)%60)+2); +} + +u8 cdvdRead0E(void) { // CRT FRAME +#ifdef CDR_LOG + CDR_LOG("cdvdRead0E(Frame) %x\n", itob((u8)(cdvd.Sector%75))); +#endif + return itob((u8)(cdvd.Sector%75)); +} + +u8 cdvdRead0F(void) { // TYPE + u8 type = cdvdGetDiskType(); +#ifdef CDR_LOG + CDR_LOG("cdvdRead0F(Disc Type) %x\n", type); +#endif + return type; +} + +u8 cdvdRead13(void) { // UNKNOWN +#ifdef CDR_LOG + CDR_LOG("cdvdRead13(Unknown) %x\n", 4); +#endif + return 4; +} + +u8 cdvdRead15(void) { // RSV +#ifdef CDR_LOG + CDR_LOG("cdvdRead15(RSV)\n"); +#endif + return 0x01; // | 0x80 for ATAPI mode +} + +u8 cdvdRead16(void) { // SCOMMAND +#ifdef CDR_LOG + CDR_LOG("cdvdRead16(SCMD) %x\n", cdvd.sCommand); +#endif + return cdvd.sCommand; +} + +u8 cdvdRead17(void) { // SREADY +#ifdef CDR_LOG + CDR_LOG("cdvdRead17(SReady) %x\n", cdvd.sDataIn); +#endif + return cdvd.sDataIn; +} + +u8 cdvdRead18(void) { // SDATAOUT + u8 ret=0; + + if ((cdvd.sDataIn & 0x40) == 0) { + if (cdvd.ResultP < cdvd.ResultC) { + cdvd.ResultP++; + if (cdvd.ResultP >= cdvd.ResultC) cdvd.sDataIn|= 0x40; + ret = cdvd.Result[cdvd.ResultP-1]; + } + } + +#ifdef CDR_LOG + CDR_LOG("cdvdRead18(SDataOut) %x (ResultC=%d, ResultP=%d)\n", ret, cdvd.ResultC, cdvd.ResultP); +#endif + + return ret; +} + +u8 cdvdRead20(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead20(Key0) %x\n", cdvd.Key[0]); +#endif + return cdvd.Key[0]; +} + +u8 cdvdRead21(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead21(Key1) %x\n", cdvd.Key[1]); +#endif + return cdvd.Key[1]; +} + +u8 cdvdRead22(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead22(Key2) %x\n", cdvd.Key[2]); +#endif + return cdvd.Key[2]; +} + +u8 cdvdRead23(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead23(Key3) %x\n", cdvd.Key[3]); +#endif + return cdvd.Key[3]; +} + +u8 cdvdRead24(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead24(Key4) %x\n", cdvd.Key[4]); +#endif + return cdvd.Key[4]; +} + +u8 cdvdRead28(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead28(Key5) %x\n", cdvd.Key[5]); +#endif + return cdvd.Key[5]; +} + +u8 cdvdRead29(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead29(Key6) %x\n", cdvd.Key[6]); +#endif + return cdvd.Key[6]; +} + +u8 cdvdRead2A(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2A(Key7) %x\n", cdvd.Key[7]); +#endif + return cdvd.Key[7]; +} + +u8 cdvdRead2B(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2B(Key8) %x\n", cdvd.Key[8]); +#endif + return cdvd.Key[8]; +} + +u8 cdvdRead2C(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead2C(Key9) %x\n", cdvd.Key[9]); +#endif + return cdvd.Key[9]; +} + +u8 cdvdRead30(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead30(Key10) %x\n", cdvd.Key[10]); +#endif + return cdvd.Key[10]; +} + +u8 cdvdRead31(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead31(Key11) %x\n", cdvd.Key[11]); +#endif + return cdvd.Key[11]; +} + +u8 cdvdRead32(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead32(Key12) %x\n", cdvd.Key[12]); +#endif + return cdvd.Key[12]; +} + +u8 cdvdRead33(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead33(Key13) %x\n", cdvd.Key[13]); +#endif + return cdvd.Key[13]; +} + +u8 cdvdRead34(void) { +#ifdef CDR_LOG + CDR_LOG("cdvdRead34(Key14) %x\n", cdvd.Key[14]); +#endif + return cdvd.Key[14]; +} + +u8 cdvdRead38(void) { // valid parts of key data (first and last are valid) +#ifdef CDR_LOG + CDR_LOG("cdvdRead38(KeysValid) %x\n", cdvd.Key[15]); +#endif + return cdvd.Key[15]; +} + +u8 cdvdRead39(void) { // KEY-XOR +#ifdef CDR_LOG + CDR_LOG("cdvdRead39(KeyXor) %x\n", cdvd.KeyXor); +#endif + return cdvd.KeyXor; +} + +u8 cdvdRead3A(void) { // DEC_SET +#ifdef CDR_LOG + CDR_LOG("cdvdRead3A(DecSet) %x\n", cdvd.decSet); +#endif + SysPrintf("DecSet Read: %02X\n", cdvd.decSet); + return cdvd.decSet; +} + + + +void cdvdWrite04(u8 rt) { // NCOMMAND + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)\n", nCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.nCommand = rt; + cdvd.Status = CDVD_STATUS_NONE; + switch (rt) { + case 0x00: // CdNop + case 0x01: // CdNop_ + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + // from an emulation point of view there is not much need to do anything for these + case 0x02: // CdStandby + case 0x03: // CdStop + case 0x04: // CdPause + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + // should we change the sector location here? + case 0x05: // CdSeek + cdvd.Sector = *(int*)(cdvd.Param+0); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + case 0x06: // CdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; // CD + case 0x02: cdvd.Speed = 2; break; // CD + case 0x03: cdvd.Speed = 4; break; // CD + case 0x04: cdvd.Speed = 12; break; // CD + default: cdvd.Speed = 24; break; // CD + } + switch (cdvd.Param[10]) { + case 2: cdvd.ReadMode = CDVD_MODE_2340; cdvd.BlockSize = 2340; break; + case 1: cdvd.ReadMode = CDVD_MODE_2328; cdvd.BlockSize = 2328; break; + case 0: default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break; + } + if(cdvd.Speed > 4) cdvdReadTimeRcnt(1); + else cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "CdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + + break; + + case 0x07: // CdReadCDDA + case 0x0E: // CdReadXCDDA + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + switch (cdvd.Param[9]) { + case 0x01: cdvd.Speed = 1; break; + case 0x02: cdvd.Speed = 2; break; + case 0x03: cdvd.Speed = 4; break; + case 0x04: cdvd.Speed = 12; break; + default: cdvd.Speed = 24; break; + } + switch (cdvd.Param[10]) { + case 1: cdvd.ReadMode = CDVD_MODE_2368; cdvd.BlockSize = 2368; break; + case 2: + case 0: cdvd.ReadMode = CDVD_MODE_2352; cdvd.BlockSize = 2352; break; + } + cdvdReadTimeRcnt(1); + SysPrintf("CdAudioRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + break; + + case 0x08: // DvdRead + cdvd.Sector = *(int*)(cdvd.Param+0); + cdvd.nSectors = *(int*)(cdvd.Param+4); + if (cdvd.Param[8] == 0) cdvd.RetryCnt = 0x100; + else cdvd.RetryCnt = cdvd.Param[8]; + cdvd.SpindlCtrl = cdvd.Param[9]; + cdvd.Speed = 4; + cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2064; // Why oh why was it 2064 + cdvdReadTimeRcnt(0); +#ifdef CDR_LOG + CDR_LOG( "DvdRead: %d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)\n", cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074)); +#endif + SysPrintf("DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx\n", cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed); + cdvd.Readed = 0; + cdvd.PwOff = 1;//cmdcmplt + CDVDREAD_INT(1); + break; + + case 0x09: // CdGetToc & cdvdman_call19 + //Param[0] is 0 for CdGetToc and any value for cdvdman_call19 + //the code below handles only CdGetToc! + //if(cdvd.Param[0]==0x01) + //{ + SysPrintf("CDGetToc Param[0]=%d, Param[1]=%d\n",cdvd.Param[0],cdvd.Param[1]); + //} + cdvdGetToc(PSXM(HW_DMA3_MADR)); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); + break; + + case 0x0C: // CdReadKey + { + unsigned char arg0 = cdvd.Param[0]; + unsigned short arg1 = cdvd.Param[1] | (cdvd.Param[2]<<8); + unsigned int arg2 = cdvd.Param[3] | (cdvd.Param[4]<<8) | (cdvd.Param[5]<<16) | (cdvd.Param[6]<<24); + SysPrintf("cdvdReadKey(%d, %d, %d)\n", arg0, arg1, arg2); + cdvdReadKey(arg0, arg1, arg2, cdvd.Key); + cdvd.KeyXor = 0x00; + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + } + + case 0x0F: // CdChgSpdlCtrl + SysPrintf("sceCdChgSpdlCtrl(%d)\n", cdvd.Param[0]); + cdvd.PwOff = 1;//cmdcmplt + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + + default: + SysPrintf("NCMD Unknown %x\n", rt); + psxHu32(0x1070)|= 0x4; + //SBUS + hwIntcIrq(INTC_SBUS); + break; + } + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite05(u8 rt) { // NDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite05(NDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite06(u8 rt) { // HOWTO +#ifdef CDR_LOG + CDR_LOG("cdvdWrite06(HowTo) %x\n", rt); +#endif + cdvd.HowTo = rt; +} + +void cdvdWrite07(u8 rt) { // BREAK +#ifdef CDR_LOG + CDR_LOG("cdvdWrite07(Break) %x\n", rt); +#endif + SysPrintf("*PCSX2*: CDVD BREAK %x\n" , rt); +} + +void cdvdWrite08(u8 rt) { // INTR_STAT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite08(IntrReason) = ACK(%x)\n", rt); +#endif + cdvd.PwOff &= ~rt; +} + +void cdvdWrite0A(u8 rt) { // STATUS +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0A(Status) %x\n", rt); +#endif +} + +void cdvdWrite0F(u8 rt) { // TYPE +#ifdef CDR_LOG + CDR_LOG("cdvdWrite0F(Type) %x\n", rt); +#endif +SysPrintf("*PCSX2*: CDVD TYPE %x\n", rt); +} + +void cdvdWrite14(u8 rt) { // PS1 MODE?? + u32 cycle = psxRegs.cycle; + psxReset(); + psxHu32(0x1f801450) = 0x8; + psxHu32(0x1f801078) = 1; + psxRegs.cycle = cycle; + +#ifdef PCSX2_DEVBUILD + varLog|= 0x10000000;// | 0x00400000;// | 0x1fe00000; +#endif +} + +void cdvdWrite16(u8 rt) { // SCOMMAND +// cdvdTN diskInfo; +// cdvdTD trackInfo; +// int i, lbn, type, min, sec, frm, address; + int address; + u8 tmp; + +#ifdef CDR_LOG + CDR_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)\n", sCmdName[rt], rt, cdvd.ParamP); +#endif + cdvd.sCommand = rt; + switch (rt) { + +// case 0x01: // GetDiscType - from cdvdman (0:1) +// SetResultSize(1); +// cdvd.Result[0] = 0; +// break; + + case 0x02: // CdReadSubQ (0:11) + SetResultSize(11); + cdvd.Result[0] = cdvdReadSubQ(cdvd.Sector, (cdvdSubQ*)&cdvd.Result[1]); + break; + + case 0x03: // Mecacon-command + if(cdvd.Param[0]==0x00) { + // get mecha version (1:4) + SetResultSize(4); + cdvdGetMechaVer(&cdvd.Result[0]); + } + else if(cdvd.Param[0]==0x44) { + // write console ID (9:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteConsoleID(&cdvd.Param[1]); + } + else if(cdvd.Param[0]==0x45) { + // read console ID (1:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadConsoleID(&cdvd.Result[1]); + } + else if(cdvd.Param[0]==0xFD) { + // _sceCdReadRenewalDate (1:6) BCD + SetResultSize(6); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0x04;//year + cdvd.Result[2] = 0x12;//month + cdvd.Result[3] = 0x10;//day + cdvd.Result[4] = 0x01;//hour + cdvd.Result[5] = 0x30;//min + } else { + SetResultSize(1); + cdvd.Result[0] = 0x80; + SysPrintf("*Unknown Mecacon Command param[0]=%02X\n", cdvd.Param[0]); + } + break; + + case 0x05: // CdTrayReqState (0:1) - resets the tray open detection + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x06: // CdTrayCtrl (1:1) + SetResultSize(1); + if(cdvd.Param[0] == 0) + cdvd.Result[0] = cdvdCtrlTrayOpen(); + else + cdvd.Result[0] = cdvdCtrlTrayClose(); + break; + + case 0x08: // CdReadRTC (0:8) + SetResultSize(8); + memcpy_fast(cdvd.Result, (u8*)&cdvd.RTC, 8); + /* do not uncomment this by now, it kinda makes + things a bit more random for debugging (linuz) */ +/* + { + time_t sysTime; + struct tm* utcTime; + time(&sysTime); + utcTime = gmtime(&sysTime); + cdvd.RTC.second =itob((u8)utcTime->tm_sec); + cdvd.RTC.minute =itob((u8)utcTime->tm_min); + cdvd.RTC.hour =itob((u8)utcTime->tm_hour); // add 8 to the hours (the ps2 wants it this way) + cdvd.RTC.day =itob((u8)utcTime->tm_mday); + cdvd.RTC.month =itob((u8)utcTime->tm_mon); + cdvd.RTC.year =itob((u8)(utcTime->tm_year+100)); + cdvd.RTC.pad =0; + } +*/ + break; + + case 0x09: // sceCdWriteRTC (7:1) + SetResultSize(1); + cdvd.Result[0] = 0; + memcpy_fast((u8*)&cdvd.RTC, cdvd.Param, 7); + cdvd.RTC.pad = 0; + break; + + case 0x0A: // sceCdReadNVM (2:3) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + if (address < 512) { + SetResultSize(3); + cdvd.Result[0] = cdvdReadNVM(&cdvd.Result[1], address*2, 2); + // swap bytes around + tmp = cdvd.Result[1]; + cdvd.Result[1] = cdvd.Result[2]; + cdvd.Result[2] = tmp; + } else { + SetResultSize(1); + cdvd.Result[0] = 0xff; + } + break; + + case 0x0B: // sceCdWriteNVM (4:1) + address = (cdvd.Param[0]<<8) | cdvd.Param[1]; + SetResultSize(1); + if (address < 512) { + // swap bytes around + tmp = cdvd.Param[2]; + cdvd.Param[2] = cdvd.Param[3]; + cdvd.Param[3] = tmp; + cdvd.Result[0] = cdvdWriteNVM(&cdvd.Param[2], address*2, 2); + } else { + cdvd.Result[0] = 0xff; + } + break; + +// case 0x0C: // sceCdSetHDMode (1:1) +// break; + + + case 0x0F: // sceCdPowerOff (0:1)- Call74 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x12: // sceCdReadILinkId (0:9) + SetResultSize(9); + cdvd.Result[0] = cdvdReadILinkID(&cdvd.Result[1]); + break; + + case 0x13: // sceCdWriteILinkID (8:1) + SetResultSize(1); + cdvd.Result[0] = cdvdWriteILinkID(&cdvd.Param[1]); + break; + + case 0x14: // CdCtrlAudioDigitalOut (1:1) + //parameter can be 2, 0, ... + SetResultSize(1); + cdvd.Result[0] = 0; //8 is a flag; not used + break; + + case 0x15: // sceCdForbidDVDP (0:1) + //SysPrintf("sceCdForbidDVDP\n"); + SetResultSize(1); + cdvd.Result[0] = 5; + break; + + case 0x16: // AutoAdjustCtrl - from cdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x17: // CdReadModelNumber (1:9) - from xcdvdman + SetResultSize(9); + cdvd.Result[0] = cdvdReadModelNumber(&cdvd.Result[1], cdvd.Param[0]); + break; + + case 0x18: // CdWriteModelNumber (9:1) - from xcdvdman + SetResultSize(1); + cdvd.Result[0] = cdvdWriteModelNumber(&cdvd.Param[1], cdvd.Param[0]); + break; + +// case 0x19: // sceCdForbidRead (0:1) - from xcdvdman +// break; + + case 0x1A: // sceCdBootCertify (4:1)//(4:16 in psx?) + SetResultSize(1);//on input there are 4 bytes: 1;?10;J;C for 18000; 1;60;E;C for 39002 from ROMVER + cdvd.Result[0]=1;//i guess that means okay + break; + + case 0x1B: // sceCdCancelPOffRdy (0:1) - Call73 from Xcdvdman (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x1C: // sceCdBlueLEDCtl (1:1) - Call72 from Xcdvdman + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x1D: // cdvdman_call116 (0:5) - In V10 Bios +// break; + + case 0x1E: // sceRemote2Read (0:5) - // 00 14 AA BB CC -> remote key code + SetResultSize(5); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x14; + cdvd.Result[2] = 0x00; + cdvd.Result[3] = 0x00; + cdvd.Result[4] = 0x00; + break; + +// case 0x1F: // sceRemote2_7 (2:1) - cdvdman_call117 +// break; + + case 0x20: // sceRemote2_6 (0:3) // 00 01 00 + SetResultSize(3); + cdvd.Result[0] = 0x00; + cdvd.Result[1] = 0x01; + cdvd.Result[2] = 0x00; + break; + +// case 0x21: // sceCdWriteWakeUpTime (8:1) +// break; + + case 0x22: // sceCdReadWakeUpTime (0:10) + SetResultSize(10); + cdvd.Result[0] = 0; + cdvd.Result[1] = 0; + cdvd.Result[2] = 0; + cdvd.Result[3] = 0; + cdvd.Result[4] = 0; + cdvd.Result[5] = 0; + cdvd.Result[6] = 0; + cdvd.Result[7] = 0; + cdvd.Result[8] = 0; + cdvd.Result[9] = 0; + break; + + case 0x24: // sceCdRCBypassCtrl (1:1) - In V10 Bios + // FIXME: because PRId<0x23, the bit 0 of sio2 don't get updated 0xBF808284 + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x25: // cdvdman_call120 (1:1) - In V10 Bios +// break; + +// case 0x26: // cdvdman_call128 (0,3) - In V10 Bios +// break; + +// case 0x27: // cdvdman_call148 (0:13) - In V10 Bios +// break; + +// case 0x28: // cdvdman_call150 (1:1) - In V10 Bios +// break; + + case 0x29: //sceCdNoticeGameStart (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + +// case 0x2C: //sceCdXBSPowerCtl (2:2) +// break; + +// case 0x2D: //sceCdXLEDCtl (2:2) +// break; + +// case 0x2E: //sceCdBuzzerCtl (0:1) +// break; + +// case 0x2F: //cdvdman_call167 (16:1) +// break; + +// case 0x30: //cdvdman_call169 (1:9) +// break; + + case 0x31: //sceCdSetMediumRemoval (1:1) + SetResultSize(1); + cdvd.Result[0] = 0; + break; + + case 0x32: //sceCdGetMediumRemoval (0:2) + SetResultSize(2); + cdvd.Result[0] = 0; + cdvd.Result[0] = 0; + break; + +// case 0x33: //sceCdXDVRPReset (1:1) +// break; + + case 0x36: //cdvdman_call189 [__sceCdGetOSDVER - made up name] (0:15) + SetResultSize(15); + cdvd.Result[0] = cdvdReadOSDVER(&cdvd.Result[3]); + cdvd.Result[1] = 0;//0x10 - encryption zone == (1< cdvd.mg_maxsize) + cdvd.Result[0] = 0x80; + else{ + memcpy_fast(cdvd.mg_buffer + cdvd.mg_size, cdvd.Param, cdvd.ParamC); + cdvd.mg_size += cdvd.ParamC; + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + } + break; + + case 0x8E: // sceMgReadData + SetResultSize(min(16, cdvd.mg_size)); + memcpy_fast(cdvd.Result, cdvd.mg_buffer, cdvd.ResultC); + cdvd.mg_size -= cdvd.ResultC; + memcpy_fast(cdvd.mg_buffer, cdvd.mg_buffer+cdvd.ResultC, cdvd.mg_size); + break; + + case 0x88: // secrman: __mechacon_auth_0x88 //for now it is the same; so, fall;) + case 0x8F: // secrman: __mechacon_auth_0x8F + SetResultSize(1);//in:0 + if (cdvd.mg_datatype == 1){// header data + u64* psrc, *pdst; + int bit_ofs, i; + + if (cdvd.mg_maxsize != cdvd.mg_size) goto fail_pol_cal; + if (cdvd.mg_size < 0x20) goto fail_pol_cal; + if (cdvd.mg_size != *(u16*)&cdvd.mg_buffer[0x14]) goto fail_pol_cal; + SysPrintf("[MG] ELF_size=0x%X Hdr_size=0x%X unk=0x%X flags=0x%X count=%d zones=", + *(u32*)&cdvd.mg_buffer[0x10], *(u16*)&cdvd.mg_buffer[0x14], *(u16*)&cdvd.mg_buffer[0x16], + *(u16*)&cdvd.mg_buffer[0x18], *(u16*)&cdvd.mg_buffer[0x1A]); + for (i=0; i<8; i++) + if (cdvd.mg_buffer[0x1C] & (1<> 0) & 0xFF; + cdvd.Result[2] = (cdvd.mg_size >> 8) & 0xFF; + break; + + case 0x92: // sceMgWriteDatainLength + cdvd.mg_size = 0; + cdvd.mg_datatype = 0;//data (encrypted) + cdvd.mg_maxsize = cdvd.Param[0] | (((int)cdvd.Param[1])<<8); + SetResultSize(1);//in:2 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + + case 0x93: // sceMgWriteDataoutLength + SetResultSize(1);//in:2 + if (((cdvd.Param[0] | (((int)cdvd.Param[1])<<8)) == cdvd.mg_size) && (cdvd.mg_datatype == 0)){ + cdvd.mg_maxsize = 0; // don't allow any write + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + }else + cdvd.Result[0] = 0x80; + break; + + case 0x94: // sceMgReadKbit - read first half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + + ((int*)(cdvd.Result+1))[0] = ((int*)cdvd.mg_kbit)[0]; + ((int*)(cdvd.Result+1))[1] = ((int*)cdvd.mg_kbit)[1]; + break; + + case 0x95: // sceMgReadKbit2 - read second half of BIT key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + ((int*)(cdvd.Result+1))[0] = ((int*)(cdvd.mg_kbit+8))[0]; + ((int*)(cdvd.Result+1))[1] = ((int*)(cdvd.mg_kbit+8))[1]; + break; + + case 0x96: // sceMgReadKcon - read first half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + ((int*)(cdvd.Result+1))[0] = ((int*)cdvd.mg_kcon)[0]; + ((int*)(cdvd.Result+1))[1] = ((int*)cdvd.mg_kcon)[1]; + break; + + case 0x97: // sceMgReadKcon2 - read second half of content key + SetResultSize(1+8);//in:0 + cdvd.Result[0] = 0; + ((int*)(cdvd.Result+1))[0] = ((int*)(cdvd.mg_kcon+8))[0]; + ((int*)(cdvd.Result+1))[1] = ((int*)(cdvd.mg_kcon+8))[1]; + break; + + default: + // fake a 'correct' command + SysPrintf("SCMD Unknown %x\n", rt); + SetResultSize(1); //in:0 + cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error + break; + } + //SysPrintf("SCMD - %x\n", rt); + cdvd.ParamP = 0; cdvd.ParamC = 0; +} + +void cdvdWrite17(u8 rt) { // SDATAIN +#ifdef CDR_LOG + CDR_LOG("cdvdWrite17(SDataIn) %x\n", rt); +#endif + if (cdvd.ParamP < 32) { + cdvd.Param[cdvd.ParamP++] = rt; + cdvd.ParamC++; + } +} + +void cdvdWrite18(u8 rt) { // SDATAOUT +#ifdef CDR_LOG + CDR_LOG("cdvdWrite18(SDataOut) %x\n", rt); +#endif + SysPrintf("*PCSX2* SDATAOUT\n"); +} + +void cdvdWrite3A(u8 rt) { // DEC-SET +#ifdef CDR_LOG + CDR_LOG("cdvdWrite3A(DecSet) %x\n", rt); +#endif + cdvd.decSet = rt; + SysPrintf("DecSet Write: %02X\n", cdvd.decSet); +} + +static int mg_BIToffset(u8 *buffer){ + int i, ofs = 0x20; for (i=0; i<*(u16*)&buffer[0x1A]; i++)ofs+=0x10; + if (*(u16*)&buffer[0x18] & 1)ofs+=buffer[ofs]; + if ((*(u16*)&buffer[0x18] & 0xF000)==0)ofs+=8; + return ofs + 0x20; +} diff --git a/pcsx2/CDVD.h b/pcsx2/CDVD.h new file mode 100644 index 0000000..c1dec54 --- /dev/null +++ b/pcsx2/CDVD.h @@ -0,0 +1,144 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#include "PsxCommon.h" + +typedef struct { + u8 status; + u8 second; + u8 minute; + u8 hour; + u8 pad; + u8 day; + u8 month; + u8 year; +} cdvdRTC; + +typedef struct { + u8 nCommand; + u8 Ready; + u8 Error; + u8 PwOff; + u8 Status; + u8 Type; + u8 sCommand; + u8 sDataIn; + u8 sDataOut; + u8 HowTo; + + u8 Param[32]; + u8 Result[32]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + + u8 CBlockIndex; + u8 COffset; + u8 CReadWrite; + u8 CNumBlocks; + + int RTCcount; + cdvdRTC RTC; + + u32 Sector; + int nSectors; + int Readed; + int Reading; + int ReadMode; + int BlockSize; + int Speed; + int RetryCnt; + int RetryCntP; + int RErr; + int SpindlCtrl; + + u8 Key[16]; + u8 KeyXor; + u8 decSet; + + u8 mg_buffer[65536]; + int mg_size; + int mg_maxsize; + int mg_datatype;//0-data(encrypted); 1-header + u8 mg_kbit[16];//last BIT key 'seen' + u8 mg_kcon[16];//last content key 'seen' +// char Unused[4096]; +} cdvdStruct; + +extern cdvdStruct cdvd; + +void cdvdReset(); +void cdvdReadTimeRcnt(int mode); +void cdvdVsync(); +int cdvdInterrupt(); +int cdvdFreeze(gzFile f, int Mode); +int cdvdReadInterrupt(); +void cdvdNewDiskCB(); +u8 cdvdRead04(void); +u8 cdvdRead05(void); +u8 cdvdRead06(void); +u8 cdvdRead07(void); +u8 cdvdRead08(void); +u8 cdvdRead0A(void); +u8 cdvdRead0B(void); +u8 cdvdRead0C(void); +u8 cdvdRead0D(void); +u8 cdvdRead0E(void); +u8 cdvdRead0F(void); +u8 cdvdRead13(void); +u8 cdvdRead15(void); +u8 cdvdRead16(void); +u8 cdvdRead17(void); +u8 cdvdRead18(void); +u8 cdvdRead20(void); +u8 cdvdRead21(void); +u8 cdvdRead22(void); +u8 cdvdRead23(void); +u8 cdvdRead24(void); +u8 cdvdRead28(void); +u8 cdvdRead29(void); +u8 cdvdRead2A(void); +u8 cdvdRead2B(void); +u8 cdvdRead2C(void); +u8 cdvdRead30(void); +u8 cdvdRead31(void); +u8 cdvdRead32(void); +u8 cdvdRead33(void); +u8 cdvdRead34(void); +u8 cdvdRead38(void); +u8 cdvdRead39(void); +u8 cdvdRead3A(void); +void cdvdWrite04(u8 rt); +void cdvdWrite05(u8 rt); +void cdvdWrite06(u8 rt); +void cdvdWrite07(u8 rt); +void cdvdWrite08(u8 rt); +void cdvdWrite0A(u8 rt); +void cdvdWrite0F(u8 rt); +void cdvdWrite14(u8 rt); +void cdvdWrite16(u8 rt); +void cdvdWrite17(u8 rt); +void cdvdWrite18(u8 rt); +void cdvdWrite3A(u8 rt); + +#endif /* __CDVD_H__ */ diff --git a/pcsx2/CDVDiso.c b/pcsx2/CDVDiso.c new file mode 100644 index 0000000..b9788e4 --- /dev/null +++ b/pcsx2/CDVDiso.c @@ -0,0 +1,835 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + * Fixed CdRead by linuzappz + */ + +#include + +//#ifndef strnicmp +//#define strnicmp strncasecmp +//#endif + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +struct dir_toc_data{ + unsigned int start_LBA; + unsigned int num_sectors; + unsigned int num_entries; + unsigned int current_entry; + unsigned int current_sector; + unsigned int current_sector_offset; + unsigned int inc_dirs; + unsigned char extension_list[128+1]; +}; + +//static u8 cdVolDescriptor[2048]; +static struct dir_toc_data getDirTocData; +static struct cdVolDesc CDVolDesc; + +void _splitpath2(const char *constpath, char *dir, char *fname){ + // 255 char max path-length is an ISO9660 restriction + // we must change this for Joliet or relaxed iso restriction support + static char pathcopy[1024+1]; + + char* slash; + + strncpy(pathcopy, constpath, 1024); + + slash = strrchr (pathcopy, '/'); + + // if the path doesn't contain a '/' then look for a '\' + if (!slash) + slash = strrchr (pathcopy, (int)'\\'); + + // if a slash was found + if (slash != NULL) + { + // null terminate the path + slash[0] = 0; + // and copy the path into 'dir' + strncpy(dir, pathcopy, 1024); + dir[255]=0; + + // copy the filename into 'fname' + strncpy(fname, slash+1, 128); + fname[128]=0; + } + else + { + dir[0] = 0; + + strncpy(fname, pathcopy, 128); + fname[128]=0; + } + +} + +// Used in findfile +int tolower(int c); +int strcasecmp(const char *s1, const char *s2){ + while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +// Copy a TOC Entry from the CD native format to our tidier format +void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){ + int i; + int filenamelen; + + tocEntry->fileSize = internalTocEntry->fileSize; + tocEntry->fileLBA = internalTocEntry->fileLBA; + tocEntry->fileProperties = internalTocEntry->fileProperties; + memcpy(tocEntry->date, internalTocEntry->dateStamp, 7); + + if (CDVolDesc.filesystemType == 2){ + // This is a Joliet Filesystem, so use Unicode to ISO string copy + + filenamelen = internalTocEntry->filenameLength/2; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + for (i=0; i < filenamelen; i++) + tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1]; + + tocEntry->filename[filenamelen] = 0; + } + else{ + filenamelen = internalTocEntry->filenameLength; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + // use normal string copy + strncpy(tocEntry->filename,internalTocEntry->filename,128); + tocEntry->filename[filenamelen] = 0; + } +} + +// Check if a TOC Entry matches our extension list +int TocEntryCompare(char* filename, char* extensions){ + static char ext_list[129]; + + char* token; + + char* ext_point; + + strncpy(ext_list,extensions,128); + ext_list[128]=0; + + token = strtok( ext_list, " ," ); + while( token != NULL ) + { + // if 'token' matches extension of 'filename' + // then return a match + ext_point = strrchr(filename,'.'); + + if (strnicmp(ext_point, token, strlen(token)) == 0) + return (TRUE); + + /* Get next token: */ + token = strtok( NULL, " ," ); + } + + // If not match found then return FALSE + return (FALSE); + +} + +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + int rmode; + + switch (mode->datapattern) { + case CdSecS2048: + rmode = CDVD_MODE_2048; break; + case CdSecS2328: + rmode = CDVD_MODE_2328; break; + case CdSecS2340: + rmode = CDVD_MODE_2340; break; + default: + return 0; + } + + for (i=0; idatapattern){ + case CdSecS2048: + memcpy_fast((void*)((uptr)buf+2048*i), buff, 2048);break;//only data + case CdSecS2328: + memcpy_fast((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub + case CdSecS2340: + memcpy_fast((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync + } + } + return 1; +} + +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + + for (i=lsn; i<(lsn+sectors); i++){ + if (CDVDreadTrack(i, CDVD_MODE_2048)==-1) + return 0; + buff = CDVDgetBuffer(); + if (buff==NULL) return 0; + +// switch (mode->datapattern){ +// case CdSecS2064: + ((u32*)buf)[0] = i + 0x30000; + memcpy_fast((u8*)buf+12, buff, 2048); + buf = (char*)buf + 2064; break; +// default: +// return 0; +// } + } + + return 1; +} + +/************************************************************** +* The functions below are not exported for normal file-system * +* operations, but are used by the file-system operations, and * +* may also be exported for use via RPC * +**************************************************************/ + +int CDVD_GetVolumeDescriptor(void){ + // Read until we find the last valid Volume Descriptor + int volDescSector; + + static struct cdVolDesc localVolDesc; + +#ifdef DEBUG + printf("CDVD_GetVolumeDescriptor called\n"); +#endif + + for (volDescSector = 16; volDescSector<20; volDescSector++) + { + CdRead(volDescSector,1,&localVolDesc,&cdReadMode); +// CdSync(0x00); + + // If this is still a volume Descriptor + if (strncmp(localVolDesc.volID, "CD001", 5) == 0) + { + if ((localVolDesc.filesystemType == 1) || + (localVolDesc.filesystemType == 2)) + { + memcpy_fast(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc)); + } + } + else + break; + } + +#ifdef DEBUG + if (CDVolDesc.filesystemType == 1) + printf("CD FileSystem is ISO9660\n"); + else if (CDVolDesc.filesystemType == 2) + printf("CD FileSystem is Joliet\n"); + else printf("Could not detect CD FileSystem type\n"); +#endif +// CdStop(); + + return TRUE; +} + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry){ + static char filename[128+1]; + static char pathname[1024+1]; + static char toc[2048]; + char* dirname; + + + static struct TocEntry localTocEntry; // used for internal checking only + + int found_dir; + + int num_dir_sectors; + int current_sector; + + int dir_lba; + + struct dirTocEntry* tocEntryPointer; + +#ifdef DEBUG + printf("CDVD_findfile called\n"); +#endif + + //make sure we have good cdReadMode + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; + + _splitpath2(fname, pathname, filename); + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + tocEntryPointer = (struct dirTocEntry*)toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + current_sector = tocEntryPointer->fileLBA; + + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + + while( dirname != NULL ) + { + found_dir = FALSE; +/* + while(tocEntryPointer->length > 0) + { + // while there are still more directory entries then search through + // for the one we want + + if (tocEntryPointer->fileProperties & 0x02) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcasecmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } +*/ + while(1) + { + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) + { + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + tocEntryPointer = (struct dirTocEntry*)toc; + } + else + { + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + + if (tocEntryPointer->fileProperties & 0x02) + { + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + { + printf("CDVD_findfile: could not find dir\n"); + return -1; + } + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE) + { + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + tocEntryPointer = (struct dirTocEntry*)toc; + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + +#ifdef DEBUG + printf("CDVD_findfile: found dir, now looking for file\n"); +#endif + + tocEntryPointer = (struct dirTocEntry*)toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + dir_lba = tocEntryPointer->fileLBA; + + tocEntryPointer = (struct dirTocEntry*)toc; + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + + while (num_dir_sectors > 0) + { + while(tocEntryPointer->length != 0) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) || + ((filename[strlen(filename)-2] == ';') && + (localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') && + (strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0))) + { + // if the filename matches then copy the toc Entry + tocEntry->fileLBA = localTocEntry.fileLBA; + tocEntry->fileProperties = localTocEntry.fileProperties; + tocEntry->fileSize = localTocEntry.fileSize; + + strcpy(tocEntry->filename, localTocEntry.filename); + memcpy(tocEntry->date, localTocEntry.date, 7); + +#ifdef DEBUG + printf("CDVD_findfile: found file\n"); +#endif + + return TRUE; + } + + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + dir_lba++; + + if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){ + printf("Couldn't Read from CD !\n"); + return -1; + } +// CdSync(0x00); + + tocEntryPointer = (struct dirTocEntry*)toc; + } + } + +#ifdef DEBUG + printf("CDVD_findfile: could not find file\n"); +#endif + + return FALSE; +} + +// This is the RPC-ready function which takes the request to start the tocEntry retrieval +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){ +// int dir_depth = 1; + static char toc[2048]; + char* dirname; + int found_dir; + int num_dir_sectors; + unsigned int toc_entry_num; + struct dirTocEntry* tocEntryPointer; + static struct TocEntry localTocEntry; + int current_sector; + + // store the extension list statically for the retrieve function + strncpy(getDirTocData.extension_list, extensions, 128); + getDirTocData.extension_list[128]=0; + + getDirTocData.inc_dirs = inc_dirs; + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname); +#endif + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + tocEntryPointer = (struct dirTocEntry*)toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; + current_sector = tocEntryPointer->fileLBA; + + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + + // use strtok to get the next dir name + + // if there isnt one, then assume we want the LBA + // for the current one, and exit the while loop + + // if there is another dir name then increment dir_depth + // and look through dir table entries until we find the right name + // if we dont find the right name + // before finding an entry at a higher level (lower num), then return nothing + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + while( dirname != NULL ){ + found_dir = FALSE; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) { + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + tocEntryPointer = (struct dirTocEntry*)toc; + } + else{ + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + if (tocEntryPointer->fileProperties & 0x02){ + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0){ + // if the name matches then we've found the directory + found_dir = TRUE; +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector); + RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA); +#endif + break; + } + } + + // point to the next entry + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + return -1; + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + tocEntryPointer = (struct dirTocEntry*)toc; + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + + // We know how much data we need to read in from the DirTocHeader + // but we need to read in at least 1 sector before we can get this value + + // Now we need to COUNT the number of entries (dont do anything with info at this point) + // so set the tocEntryPointer to point to the first actual file entry + + // This is a bit of a waste of reads since we're not actually copying the data out yet, + // but we dont know how big this TOC might be, so we cant allocate a specific size + + tocEntryPointer = (struct dirTocEntry*)toc; + + // Need to STORE the start LBA and number of Sectors, for use by the retrieve func. + getDirTocData.start_LBA = localTocEntry.fileLBA; + getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11; + getDirTocData.num_entries = 0; + getDirTocData.current_entry = 0; + getDirTocData.current_sector = getDirTocData.start_LBA; + getDirTocData.current_sector_offset = 0; + + num_dir_sectors = getDirTocData.num_sectors; + + tocEntryPointer = (struct dirTocEntry*)toc; + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + + toc_entry_num=0; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){ + // decrease the number of dirs remaining + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + tocEntryPointer = (struct dirTocEntry*)toc; + +// continue; + } + else{ + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + return (toc_entry_num); + } + } + + // We've found a file/dir in this directory + // now check if it matches our extension list (if there is one) + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if (localTocEntry.fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs){ + toc_entry_num++; + } + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + } + else{ + toc_entry_num++; + } + } + + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + } + + + // THIS SHOULD BE UNREACHABLE - + // since we are trying to count ALL matching entries, rather than upto a limit + + + // STORE total number of TOC entries + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + + + // we've reached the toc entry limit, so return how many we've done + return (toc_entry_num); + +} + +// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries +// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){ + static char toc[2048]; + int toc_entry_num; + + struct dirTocEntry* tocEntryPointer; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + if (getDirTocData.current_entry == 0){ + // if this is the first read then make sure we point to the first real entry + tocEntryPointer = (struct dirTocEntry*)toc; + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + tocEntryPointer = (struct dirTocEntry*)((char*)tocEntryPointer + tocEntryPointer->length); + + + getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc; + } + else{ + tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset); + } + + if (req_entries > 128) + req_entries = 128; + + for (toc_entry_num=0; toc_entry_num < req_entries;){ + if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){ + // decrease the number of dirs remaining + getDirTocData.num_sectors--; + + if (getDirTocData.num_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + getDirTocData.current_sector_offset = 0; + tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset); + +// continue; + } + else{ + return (toc_entry_num); + } + } + + // This must be incremented even if the filename doesnt match extension list + getDirTocData.current_entry++; + + // We've found a file in this directory + // now check if it matches our extension list (if there is one) + + // Copy the entry regardless, as it makes the comparison easier + // if it doesn't match then it will just be overwritten + TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer); + + if (tocEntry[toc_entry_num].fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs) { + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset); + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset); + + } + else{ + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + tocEntryPointer = (struct dirTocEntry*)(toc + getDirTocData.current_sector_offset); + } + } +/* + if (strlen(getDirTocData.extension_list) > 0) + { + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE) + { + + // increment this here, rather than in the main for loop + // since this should count the number of matching entries + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else + { + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } +*/ + } + return (toc_entry_num); +} diff --git a/pcsx2/CDVDiso.h b/pcsx2/CDVDiso.h new file mode 100644 index 0000000..7d8b265 --- /dev/null +++ b/pcsx2/CDVDiso.h @@ -0,0 +1,131 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISO_H__ +#define __CDVDISO_H__ + +#include "CDVDlib.h" + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs); +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries); + +#if defined(_MSC_VER) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(_MSC_VER) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(_MSC_VER) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(_MSC_VER) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTableEntry +{ + u8 dirNameLength; + u8 reserved; + u32 dirTOCLBA; + u16 dirDepth; + u8 dirName[32]; +#if defined(_MSC_VER) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTocEntry +{ + short length; + unsigned int fileLBA; + unsigned int fileLBA_bigend; + unsigned int fileSize; + unsigned int fileSize_bigend; + unsigned char dateStamp[6]; + unsigned char reserved1; + unsigned char fileProperties; + unsigned char reserved2[6]; + unsigned char filenameLength; + unsigned char filename[128]; +#if defined(_MSC_VER) +}; +#else +} __attribute__((packed)); +#endif // This is the internal format on the CD +// TocEntry structure contains only the important stuff needed for export + +#if defined(_MSC_VER) +#pragma pack() +#endif + +#endif//__CDVDISO_H__ diff --git a/pcsx2/CDVDisodrv.c b/pcsx2/CDVDisodrv.c new file mode 100644 index 0000000..c4dcb47 --- /dev/null +++ b/pcsx2/CDVDisodrv.c @@ -0,0 +1,263 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#include + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +CdRMode cdReadMode; + +struct fdtable{ +//int fd; + int fileSize; + int LBA; + int filePos; +}; + +static struct fdtable fd_table[16]; +static int fd_used[16]; +static int files_open=0; +static int inited=FALSE; + +/************************************************************* +* The functions below are the normal file-system operations, * +* used to provide a standard filesystem interface * +*************************************************************/ + +////////////////////////////////////////////////////////////////////// +// CDVDFS_init +// called by 80000592 sceCdInit() +////////////////////////////////////////////////////////////////////// +void CDVDFS_init(){ + + if (inited) return;//might change in the future as a param; forceInit/Reset + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00\n"); + RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n"); + RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.\n", "cdfs"); +#endif + + //CdInit(0); already called by plugin loading system ;) + + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; //isofs driver only needs + //2KB sectors + + memset(fd_table, 0, sizeof(fd_table)); + memset(fd_used, 0, 16*sizeof(int)); + + inited = TRUE; + + return; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_open +// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_open(char *name, int mode){ + register int j; + static struct TocEntry tocEntry; + + // check if the file exists + if (CDVD_findfile(name, &tocEntry) != TRUE) + return -1; + + if(mode != 1) return -2; //SCE_RDONLY + + // set up a new file descriptor + for(j=0; j < 16; j++) if(fd_used[j] == 0) break; + if(j >= 16) return -3; + + fd_used[j] = 1; + files_open++; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:open] internal fd=%d\n", j); +#endif + + fd_table[j].fileSize = tocEntry.fileSize; + fd_table[j].LBA = tocEntry.fileLBA; + fd_table[j].filePos = 0; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d\n",tocEntry.fileSize); +#endif + + return j; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_lseek +// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_lseek(int fd, int offset, int whence){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + switch(whence){ + case SEEK_SET: + fd_table[fd].filePos = offset; + break; + + case SEEK_CUR: + fd_table[fd].filePos += offset; + break; + + case SEEK_END: + fd_table[fd].filePos = fd_table[fd].fileSize + offset; + break; + + default: + return -1; + } + + if (fd_table[fd].filePos < 0) + fd_table[fd].filePos = 0; + + if (fd_table[fd].filePos > fd_table[fd].fileSize) + fd_table[fd].filePos = fd_table[fd].fileSize; + + return fd_table[fd].filePos; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_read +// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_read( int fd, char *buffer, int size ){ +// int start_sector; + int off_sector; +// int num_sectors; + + //static char local_buffer[2024*2048]; //4MB + static char lb[2048]; //2KB + //Start, Aligned, End + int ssector, asector, esector; + int ssize=0, asize, esize; + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + // A few sanity checks + if (fd_table[fd].filePos > fd_table[fd].fileSize){ + // We cant start reading from past the beginning of the file + return 0; // File exists but we couldnt read anything from it + } + + if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize) + size = fd_table[fd].fileSize - fd_table[fd].filePos; + + // Now work out where we want to start reading from + asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + if (off_sector){ + ssize = min(2048 - off_sector, size); + size -= ssize; + asector++; + } + asize = size & 0xFFFFF800; + esize = size & 0x000007FF; + esector=asector + (asize >> 11); + size += ssize; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n", ssector, esector-(esize==0)); +#endif + + if (ssize){ if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy_fast(buffer, lb + off_sector, ssize); + } + if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + if (esize){ if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy_fast(buffer+ssize+asize, lb, esize); + } +/*********************** + // Now work out where we want to start reading from + start_sector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + num_sectors = ((off_sector + size) >> 11) + 1; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n",start_sector,start_sector+num_sectors); +#endif + + // Read the data (we only ever get 16KB max request at once) + if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + //RPC_LOG("sector = %d, start sector = %d\n",sector,start_sector); + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + //CdSync(0); hm, a wait function maybe... + + memcpy_fast(buffer,local_buffer+off_sector,size); +**************************/ + fd_table[fd].filePos += size; + + return (size); +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_write +// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:" +// hehe, this ain't a CD writing option :D +////////////////////////////////////////////////////////////////////// +int CDVDFS_write( int fd, char * buffer, int size ){ + if(size == 0) return 0; + else return -1; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_close +// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_close( int fd){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] internal fd %d\n", fd); +#endif + + fd_used[fd] = 0; + files_open--; + + return 0; +} + diff --git a/pcsx2/CDVDisodrv.h b/pcsx2/CDVDisodrv.h new file mode 100644 index 0000000..dcf8545 --- /dev/null +++ b/pcsx2/CDVDisodrv.h @@ -0,0 +1,22 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISODRV_H__ +#define __CDVDISODRV_H__ + +//#include "Common.h" +#include "CDVDlib.h" + +extern CdRMode cdReadMode; + +/* Filing-system exported functions */ +void CDVDFS_init(); +int CDVDFS_open(char *name, int mode); +int CDVDFS_lseek(int fd, int offset, int whence); +int CDVDFS_read( int fd, char * buffer, int size ); +int CDVDFS_write( int fd, char * buffer, int size ); +int CDVDFS_close( int fd); + +#endif//__CDVDISODRV_H__ diff --git a/pcsx2/CDVDlib.h b/pcsx2/CDVDlib.h new file mode 100644 index 0000000..e027204 --- /dev/null +++ b/pcsx2/CDVDlib.h @@ -0,0 +1,185 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Linux kernel headers + * Modified by Florin for PCSX2 emu + */ + +#ifndef _CDVDLIB_H +#define _CDVDLIB_H + +#include "Common.h" + +// Macros for READ Data pattan +#define CdSecS2048 0 // sector size 2048 +#define CdSecS2328 1 // sector size 2328 +#define CdSecS2340 2 // sector size 2340 + +//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ + +/* + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + * 2340, or 2352 bytes long. + * Sector types of the standard CD-ROM data formats: + * + * format sector type user data size (bytes) + * ----------------------------------------------------------------------------- + * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW) + * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE) + * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0) + * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE) + * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + * + * + * The layout of the standard CD-ROM data formats: + * ----------------------------------------------------------------------------- + * - audio (red): | audio_sample_bytes | + * | 2352 | + * + * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + * | 12 - 4 - 2048 - 4 - 8 - 276 | + * + * - data (yellow, mode2): | sync - head - data | + * | 12 - 4 - 2336 | + * + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + * | 12 - 4 - 8 - 2048 - 4 - 276 | + * + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + * | 12 - 4 - 8 - 2324 - 4 | + * + */ + +// Macros for Spindle control +#define CdSpinMax 0 +#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. +#define CdSpinStm 0 // Recommended stream rotation speed. + +// Macros for TrayReq +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 + +/* + * Macros for sceCdGetDiskType() //comments translated from japanese;) + */ +#define SCECdIllgalMedia 0xff + /* ILIMEDIA (Illegal Media) + A non-PS / non-PS2 Disc. */ +#define SCECdDVDV 0xfe + /* DVDV (DVD Video) + A non-PS / non-PS2 Disc, but a DVD Video Disc */ +#define SCECdCDDA 0xfd + /* CDDA (CD DA) + A non-PS / non-PS2 Disc that include a DA track */ +#define SCECdPS2DVD 0x14 + /* PS2DVD PS2 consumer DVD. */ +#define SCECdPS2CDDA 0x13 + /* PS2CDDA PS2 consumer CD that includes a DA track */ +#define SCECdPS2CD 0x12 + /* PS2CD PS2 consumer CD that does not include a DA track */ +#define SCECdPSCDDA 0x11 + /* PSCDDA PS CD that includes a DA track */ +#define SCECdPSCD 0x10 + /* PSCD PS CD that does not include a DA track */ +#define SCECdDETCT 0x01 + /* DETCT (Detecting) Disc distinction action */ +#define SCECdNODISC 0x00 + /* NODISC (No disc) No disc entered */ + +/* + * Media mode + */ +#define SCECdCD 1 +#define SCECdDVD 2 + +typedef struct { + u8 stat; // 0: normal. Any other: error + u8 second; // second (BCD value) + u8 minute; // minute (BCD value) + u8 hour; // hour (BCD value) + u8 week; // week (BCD value) + u8 day; // day (BCD value) + u8 month; // month (BCD value) + u8 year; // year (BCD value) +} CdCLOCK; + +typedef struct { + u32 lsn; // Logical sector number of file + u32 size; // File size (in bytes) + char name[16]; // Filename + u8 date[8]; // 1th: Seconds + // 2th: Minutes + // 3th: Hours + // 4th: Date + // 5th: Month + // 6th 7th: Year (4 digits) +} CdlFILE; + +typedef struct { + u8 minute; // Minutes + u8 second; // Seconds + u8 sector; // Sector + u8 track; // Track number +} CdlLOCCD; + +typedef struct { + u8 trycount; // Read try count (No. of error retries + 1) (0 - 255) + u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed. + // SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. + u8 datapattern; // SCECdSecS2048: Data size 2048 bytes + // SCECdSecS2328: 2328 bytes + // SCECdSecS2340: 2340 bytes + u8 pad; // Padding data produced by alignment. +} CdRMode; + +#if defined(_WIN32) +#pragma pack(1) +#endif + +struct TocEntry +{ + u32 fileLBA; + u32 fileSize; + u8 fileProperties; + u8 padding1[3]; + u8 filename[128+1]; + u8 date[7]; +#if defined(_WIN32) +}; +#else +} __attribute__((packed)); +#endif + +#if defined(_WIN32) +#pragma pack() +#endif + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +/* +int CdBreak(void); +int CdCallback( void (*func)() ); +int CdDiskReady(int mode); +int CdGetDiskType(void); +int CdGetError(void); +u32 CdGetReadPos(void); +int CdGetToc(u8 *toc); +int CdInit(int init_mode); +CdlLOCCD *CdIntToPos(int i, CdlLOCCD *p); +int CdPause(void); +int CdPosToInt(CdlLOCCD *p);*/ +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +/*int CdReadClock(CdCLOCK *rtc); +int CdSearchFile (CdlFILE *fp, const char *name); +int CdSeek(u32 lsn); +int CdStandby(void); +int CdStatus(void); +int CdStop(void); +int CdSync(int mode); +int CdTrayReq(int mode, u32 *traycnt); +*/ +#endif // _CDVDLIB_H diff --git a/pcsx2/COP0.c b/pcsx2/COP0.c new file mode 100644 index 0000000..fe4aa56 --- /dev/null +++ b/pcsx2/COP0.c @@ -0,0 +1,363 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +//extern BOOL bExecBIOS; + +void COP0() { + Int_COP0PrintTable[_Rs_](); +} + +void COP0_BC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03](); +} + +void COP0_Func() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP0C0PrintTable[_Funct_](); +} + +void COP0_Unknown() { +#ifdef CPU_LOG + CPU_LOG("COP0 Unknown opcode called\n"); +#endif +} + +void UpdateCP0Status() { + u32 value = cpuRegs.CP0.n.Status.val; + + if (value & 0x06 || + (value & 0x18) == 0) { // Kernel Mode (KSU = 0 | EXL = 1 | ERL = 1)*/ + memSetKernelMode(); // Kernel memory always + } else { // User Mode + memSetUserMode(); + } + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)cpuTestHwInts(); +} + +void WriteCP0Status(u32 value) { + cpuRegs.CP0.n.Status.val = value; + UpdateCP0Status(); +} + +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; + +void MFC0() { + if (!_Rt_) return; +#ifdef COP0_LOG + if (_Rd_ != 9) { COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); } +#endif + + //if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MFC0 _Rd_ %x = %x\n", _Rd_, cpuRegs.CP0.r[_Rd_]); + switch (_Rd_) { + + case 12: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)(cpuRegs.CP0.r[_Rd_] & 0xf0c79c1f); break; + case 25: + switch(_Imm_ & 0x3F){ + case 0: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pccr; break; + case 1: + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) { + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + } + + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pcr0; + break; + case 3: + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) { + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + s_iLastPERFCycle[1] = cpuRegs.cycle; + } + cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.PERF.n.pcr1; + break; + } + /*SysPrintf("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/ + break; + case 9: + // update + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + default: cpuRegs.GPR.r[_Rt_].UD[0] = (s64)cpuRegs.CP0.r[_Rd_]; + } +} + +void MTC0() { +#ifdef COP0_LOG + COP0_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + //if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MTC0 _Rd_ %x = %x\n", _Rd_, cpuRegs.CP0.r[_Rd_]); + switch (_Rd_) { + case 25: + /*if(bExecBIOS == FALSE && _Rd_ == 25) SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/ + switch(_Imm_ & 0x3F){ + case 0: + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + cpuRegs.PERF.n.pccr = cpuRegs.GPR.r[_Rt_].UL[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + s_iLastPERFCycle[1] = cpuRegs.cycle; + break; + case 1: cpuRegs.PERF.n.pcr0 = cpuRegs.GPR.r[_Rt_].UL[0]; s_iLastPERFCycle[0] = cpuRegs.cycle; break; + case 3: cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0]; s_iLastPERFCycle[1] = cpuRegs.cycle; break; + } + break; + case 12: WriteCP0Status(cpuRegs.GPR.r[_Rt_].UL[0]); break; + case 9: s_iLastCOP0Cycle = cpuRegs.cycle; cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + default: cpuRegs.CP0.r[_Rd_] = cpuRegs.GPR.r[_Rt_].UL[0]; break; + } +} + +int CPCOND0() { + if(((psHu16(DMAC_STAT) & psHu16(DMAC_PCR)) & 0x3ff) == (psHu16(DMAC_PCR) & 0x3ff)) return 1; + else return 0; +} + +//#define CPCOND0 1 + +#define BC0(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC0F() { + BC0(== 0); +} + +void BC0T() { + BC0(== 1); +} + +#define BC0L(cond) \ + if (CPCOND0() cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC0FL() { + BC0L(== 0); +} + +void BC0TL() { + BC0L(== 1); +} + +void TLBR() { +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + int i = cpuRegs.CP0.n.Index&0x1f; + +// if( !bExecBIOS ) +// __Log("TLBR %d\n", cpuRegs.CP0.n.Index&0x1f); + + SysPrintf("COP0_TLBR\n"); + cpuRegs.CP0.n.PageMask = tlb[i].PageMask; + cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi&~(tlb[i].PageMask|0x1f00); + cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0&~1)|((tlb[i].EntryHi>>12)&1); + cpuRegs.CP0.n.EntryLo1 =(tlb[i].EntryLo1&~1)|((tlb[i].EntryHi>>12)&1); +} + +void ClearTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memClearPageAddr(addr << 12); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void WriteTLB(int i) { + u32 mask, addr; + u32 saddr, eaddr; + + tlb[i].PageMask = cpuRegs.CP0.n.PageMask; + tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi; + tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0; + tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1; + + tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff; + tlb[i].nMask = (~tlb[i].Mask) & 0xfff; + tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13; + tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff; + tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1; + tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN0|= (0x80000000); + tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12; + tlb[i].PFN1|= (0x80000000); + if (tlb[i].VPN2 == 0x70000000) return; + + if (tlb[i].EntryLo0 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = tlb[i].VPN2 >> 12; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN0 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } + + if (tlb[i].EntryLo1 & 0x2) { + mask = ((~tlb[i].Mask) << 1) & 0xfffff; + saddr = (tlb[i].VPN2 >> 12) + tlb[i].Mask + 1; + eaddr = saddr + tlb[i].Mask + 1; + + for (addr=saddr; addr> 12) & mask)) { //match + memSetPageAddr(addr << 12, tlb[i].PFN1 + ((addr - saddr) << 12)); + Cpu->Clear(addr << 12, 1); + } + } + } +} + +void TLBWI() { + int j = cpuRegs.CP0.n.Index & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWI %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWI %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBWR() { + int j = cpuRegs.CP0.n.Random & 0x3f; + + if (j > 48) return; + +#ifdef CPU_LOG +/* CPU_LOG("COP0_TLBWR %d:%x,%x,%x,%x\n", + cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi, + cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);*/ +#endif + +// if( !bExecBIOS ) +// __Log("TLBWR %d\n", j); + + ClearTLB(j); + WriteTLB(j); +} + +void TLBP() { + int i; + + + union { + struct { + u32 VPN2:19; + u32 VPN2X:2; + u32 G:3; + u32 ASID:8; + } s; + u32 u; + } EntryHi32; + +// if( !bExecBIOS ) +// __Log("TLBP %x\n", cpuRegs.CP0.n.EntryHi); + + EntryHi32.u=cpuRegs.CP0.n.EntryHi; + + cpuRegs.CP0.n.Index=0xFFFFFFFF; + for(i=0;i<48;i++){ + if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2)) + &&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { + cpuRegs.CP0.n.Index=i; + break; + } + } + if(cpuRegs.CP0.n.Index == 0xFFFFFFFF) cpuRegs.CP0.n.Index = 0x80000000; +} + +void ERET() { + if (cpuRegs.CP0.n.Status.b.ERL) { + cpuRegs.pc = cpuRegs.CP0.n.ErrorEPC; + cpuRegs.CP0.n.Status.b.ERL = 0; + } else { + cpuRegs.pc = cpuRegs.CP0.n.EPC; + cpuRegs.CP0.n.Status.b.EXL = 0; + } + UpdateCP0Status(); + intSetBranch(); +} + +void DI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 0; + UpdateCP0Status(); + } +} + +void EI() { + if (cpuRegs.CP0.n.Status.b._EDI || cpuRegs.CP0.n.Status.b.EXL || + cpuRegs.CP0.n.Status.b.ERL || (cpuRegs.CP0.n.Status.b.KSU == 0)) { + cpuRegs.CP0.n.Status.b.EIE = 1; + UpdateCP0Status(); + } +} + diff --git a/pcsx2/COP0.h b/pcsx2/COP0.h new file mode 100644 index 0000000..30ad063 --- /dev/null +++ b/pcsx2/COP0.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COP0_H__ +#define __COP0_H__ + +void WriteCP0Status(u32 value); +void UpdateCP0Status(); +void WriteTLB(int i); +void ClearTLB(int i); + +#endif /* __COP0_H__ */ diff --git a/pcsx2/Cache.c b/pcsx2/Cache.c new file mode 100644 index 0000000..5a3865e --- /dev/null +++ b/pcsx2/Cache.c @@ -0,0 +1,392 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "Cache.h" + +#ifndef PCSX2_VIRTUAL_MEM +_cacheS pCache[64]; +int getFreeCache(u32 mem, int mode, int * way) { + u8 * out; + u32 paddr; + u32 taddr[2]; + u8 * t; + int number; + int i = (mem >> 6) & 0x3F; + + paddr = memLUTR[mem >> 12]; + taddr[0] = memLUTW[pCache[i].tag[0]>>12]; + taddr[1] = memLUTW[pCache[i].tag[1]>>12]; + + if (taddr[0] == paddr && (pCache[i].tag[0] & 0x20)) + { + *way = 0; + return i; + }else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20)) + { + *way = 1; + return i; + } + + number = ((pCache[i].tag[0]>>4) & 1) ^ ((pCache[i].tag[1]>>4) & 1); + + if(pCache[i].tag[number] & 0x60) // Valid Dirty + { + t = (char *)(taddr[number]); + out = (u8*)(t + (mem & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[i].data[number][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[i].data[number][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[i].data[number][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[i].data[number][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[i].data[number][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[i].data[number][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[i].data[number][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[i].data[number][3].b8._8)[1]; + } + + + + if(mode == 1) + { + pCache[i].tag[number] |= 0x40; // Set Dirty Bit if mode == write + } + + pCache[i].tag[number] &= ~(0xFFFFF000); + pCache[i].tag[number] |= ((mem>>12) & 0xFFFFF) << 12; + + + t = (u8 *)paddr; + out= (u8*)(t + (mem & 0xFC0)); + ((u64*)pCache[i].data[number][0].b8._8)[0] = ((u64*)out)[0]; + ((u64*)pCache[i].data[number][0].b8._8)[1] = ((u64*)out)[1]; + ((u64*)pCache[i].data[number][1].b8._8)[0] = ((u64*)out)[2]; + ((u64*)pCache[i].data[number][1].b8._8)[1] = ((u64*)out)[3]; + ((u64*)pCache[i].data[number][2].b8._8)[0] = ((u64*)out)[4]; + ((u64*)pCache[i].data[number][2].b8._8)[1] = ((u64*)out)[5]; + ((u64*)pCache[i].data[number][3].b8._8)[0] = ((u64*)out)[6]; + ((u64*)pCache[i].data[number][3].b8._8)[1] = ((u64*)out)[7]; + + if(pCache[i].tag[number] & 0x10) pCache[i].tag[number] &= ~(0x10); + else pCache[i].tag[number] |= 0x10; + + pCache[i].tag[number] |= 0x20; + *way = number; + return i; +} + +void writeCache8(u32 mem, u8 value) { + int i, number; + + i = getFreeCache(mem,1,&number); +// CACHE_LOG("writeCache8 %8.8x adding to %d, way %d, value %x\n", mem, i,number,value); + + pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)] = value; +} + +void writeCache16(u32 mem, u16 value) { + int i, number; + + i = getFreeCache(mem,1,&number); +// CACHE_LOG("writeCache16 %8.8x adding to %d, way %d, value %x\n", mem, i,number,value); + + *(u16*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache32(u32 mem, u32 value) { + int i, number; + + i = getFreeCache(mem,1,&number); +// CACHE_LOG("writeCache32 %8.8x adding to %d, way %d, value %x\n", mem, i,number,value); + *(u32*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache64(u32 mem, u64 value) { + int i, number; + + i = getFreeCache(mem,1,&number); +// CACHE_LOG("writeCache64 %8.8x adding to %d, way %d, value %x\n", mem, i,number,value); + *(u64*)(&pCache[i].data[number][(mem>>4) & 0x3].b8._8[(mem&0xf)]) = value; +} + +void writeCache128(u32 mem, u64 *value) { + int i, number; + + i = getFreeCache(mem,1,&number); +// CACHE_LOG("writeCache128 %8.8x adding to %d\n", mem, i); + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[0] = value[0]; + ((u64*)pCache[i].data[number][(mem>>4) & 0x3].b8._8)[1] = value[1]; +} + +u8 *readCache(u32 mem) { + int i, number; + + i = getFreeCache(mem,0,&number); +// CACHE_LOG("readCache %8.8x from %d, way %d\n", mem, i,number); + + return pCache[i].data[number][(mem>>4) & 0x3].b8._8; +} + +extern int Dcache; +void CACHE() { + u32 addr; + //if(Dcache == 0) return; + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + switch (_Rt_) { + case 0x1a: + { + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTR[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef CACHE_LOG + CACHE_LOG("CACHE DHIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + case 0x18: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } + +#ifdef CACHE_LOG + CACHE_LOG("CACHE DHWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr);//paddr[way]); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + + break; + } + case 0x1c: + { + u8 * out; + int index = (addr >> 6) & 0x3F; + u32 paddr[2]; + int way; + u32 taddr = memLUTW[addr >> 12]; + paddr[0] = memLUTW[pCache[index].tag[0] >> 12]; + paddr[1] = memLUTW[pCache[index].tag[1] >> 12]; + + if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20)) + { + way = 0; + } + else if(paddr[1] == taddr && (pCache[index].tag[1] & 0x20)) + { + way = 1; + } + else + { + return; + } +#ifdef CACHE_LOG + CACHE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Valid Dirty + { + char * t = (char *)(taddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x40); + break; + } + case 0x16: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * t, * out; +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXIN addr %x, index %d, way %d, flag %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + pCache[index].tag[way] &= ~(0x6F); + + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + case 0x11: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + cpuRegs.CP0.r[28] = *(u32 *)(out+(addr&0xf)); +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXLDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x10: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + + cpuRegs.CP0.r[28] = 0; + cpuRegs.CP0.r[28] = pCache[index].tag[way]; +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXLTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x13: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + u8 * out = pCache[index].data[way][(addr>>4) & 0x3].b8._8; + *(u32*)(&pCache[index].data[way][(addr>>4) & 0x3].b8._8[(addr&0xf)]) = cpuRegs.CP0.r[28]; +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXSDT addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28]); +#endif + break; + } + case 0x12: + { + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + pCache[index].tag[way] = cpuRegs.CP0.r[28]; +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXSTG addr %x, index %d, way %d, DATA %x\n",addr,index,way,cpuRegs.CP0.r[28] & 0x6F); +#endif + break; + } + case 0x14: + { + + u8 * out; + int index = (addr >> 6) & 0x3F; + int way = addr & 0x1; + +#ifdef CACHE_LOG + CACHE_LOG("CACHE DXWBIN addr %x, index %d, way %d, Flags %x\n",addr,index,way,pCache[index].tag[way] & 0x78); +#endif + if(pCache[index].tag[way] & 0x60) // Dirty + { + u32 paddr = memLUTW[pCache[index].tag[way] >> 12]; + char * t = (char *)(paddr); + out = (u8*)(t + (addr & 0xFC0)); + ((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0]; + ((u64*)out)[1] = ((u64*)pCache[index].data[way][0].b8._8)[1]; + ((u64*)out)[2] = ((u64*)pCache[index].data[way][1].b8._8)[0]; + ((u64*)out)[3] = ((u64*)pCache[index].data[way][1].b8._8)[1]; + ((u64*)out)[4] = ((u64*)pCache[index].data[way][2].b8._8)[0]; + ((u64*)out)[5] = ((u64*)pCache[index].data[way][2].b8._8)[1]; + ((u64*)out)[6] = ((u64*)pCache[index].data[way][3].b8._8)[0]; + ((u64*)out)[7] = ((u64*)pCache[index].data[way][3].b8._8)[1]; + } + + pCache[index].tag[way] &= ~(0x6F); + ((u64*)pCache[index].data[way][0].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][0].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][1].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][2].b8._8)[1] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[0] = 0; + ((u64*)pCache[index].data[way][3].b8._8)[1] = 0; + break; + } + } +} +#else + +void CACHE() { +} + +#endif \ No newline at end of file diff --git a/pcsx2/Cache.h b/pcsx2/Cache.h new file mode 100644 index 0000000..017b10d --- /dev/null +++ b/pcsx2/Cache.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#include "Common.h" + +typedef struct __u8bit_128 { + u8 _8[16]; + +}_u8bit_128; + +typedef struct _u128v2 { + _u8bit_128 b8; + +}u128; + +typedef struct { + u32 tag[2]; + u128 data[2][4]; +} _cacheS; + +_cacheS pCache[64]; +void writeCache8(u32 mem, u8 value); +void writeCache16(u32 mem, u16 value); +void writeCache32(u32 mem, u32 value); +void writeCache64(u32 mem, u64 value); +void writeCache128(u32 mem, u64 *value); +u8 *readCache(u32 mem); + +#endif /* __CACHE_H__ */ diff --git a/pcsx2/CdRom.c b/pcsx2/CdRom.c new file mode 100644 index 0000000..a0f4908 --- /dev/null +++ b/pcsx2/CdRom.c @@ -0,0 +1,1080 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2007 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +//THIS ALL IS FOR THE CDROM REGISTERS HANDLING +#include "PsxCommon.h" + +#define CdlSync 0 +#define CdlNop 1 +#define CdlSetloc 2 +#define CdlPlay 3 +#define CdlForward 4 +#define CdlBackward 5 +#define CdlReadN 6 +#define CdlStandby 7 +#define CdlStop 8 +#define CdlPause 9 +#define CdlInit 10 +#define CdlMute 11 +#define CdlDemute 12 +#define CdlSetfilter 13 +#define CdlSetmode 14 +#define CdlGetmode 15 +#define CdlGetlocL 16 +#define CdlGetlocP 17 +#define Cdl18 18 +#define CdlGetTN 19 +#define CdlGetTD 20 +#define CdlSeekL 21 +#define CdlSeekP 22 +#define CdlTest 25 +#define CdlID 26 +#define CdlReadS 27 +#define CdlReset 28 +#define CdlReadToc 30 + +#define AUTOPAUSE 249 +#define READ_ACK 250 +#define READ 251 +#define REPPLAY_ACK 252 +#define REPPLAY 253 +#define ASYNC 254 +/* don't set 255, it's reserved */ + +char *CmdName[0x100]= { + "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", + "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", + "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", + "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, + NULL, "CdlTest", "CdlID", "CdlReadS", + "CdlReset", NULL, "CDlReadToc", NULL +}; + +u8 Test04[] = { 0 }; +u8 Test05[] = { 0 }; +u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; +u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; +u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; + +// 1x = 75 sectors per second +// PSXCLK = 1 sec in the ps +// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) +//#define cdReadTime ((PSXCLK / 75) / BIAS) +unsigned long cdReadTime;// = ((PSXCLK / 75) / BIAS); + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +/*static struct CdrStat stat; +static struct SubQ *subq;*/ + +#define CDR_INT(eCycle) PSX_INT(17, eCycle) +#define CDREAD_INT(eCycle) PSX_INT(18, eCycle) + +#define StartReading(type) { \ + cdr.Reading = type; \ + cdr.FirstSector = 1; \ + cdr.Readed = 0xff; \ + AddIrqQueue(READ_ACK, 0x800); \ +} + +#define StopReading() { \ + if (cdr.Reading) { \ + cdr.Reading = 0; \ + psxRegs.interrupt&=~0x40000; \ + } \ +} + +#define StopCdda() { \ + if (cdr.Play) { \ +/* if (!Config.Cdda) CDR_stop();*/ \ + cdr.StatP&=~0x80; \ + cdr.Play = 0; \ + } \ +} + +#define SetResultSize(size) { \ + cdr.ResultP = 0; \ + cdr.ResultC = size; \ + cdr.ResultReady = 1; \ +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + lsn += 150; + Time[2] = lsn / 4500; // minuten + lsn = lsn - Time[2] * 4500; // minuten rest + Time[1] = lsn / 75; // sekunden + Time[0] = lsn - Time[1] * 75; // sekunden rest +} + +void ReadTrack() { + cdr.Prev[0] = itob(cdr.SetSector[0]); + cdr.Prev[1] = itob(cdr.SetSector[1]); + cdr.Prev[2] = itob(cdr.SetSector[2]); + +#ifdef CDR_LOG + CDR_LOG("KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); +#endif + cdr.RErr = CDVDreadTrack(MSFtoLSN(cdr.SetSector), CDVD_MODE_2352); +} + +// cdr.Stat: +#define NoIntr 0 +#define DataReady 1 +#define Complete 2 +#define Acknowledge 3 +#define DataEnd 4 +#define DiskError 5 + +void AddIrqQueue(u8 irq, unsigned long ecycle) { + cdr.Irq = irq; + if (cdr.Stat) { + cdr.eCycle = ecycle; + } else { + CDR_INT(ecycle); + } +} + +int cdrInterrupt() { + cdvdTD trackInfo; + int i; + u8 Irq = cdr.Irq; + + if (cdr.Stat) { + CDR_INT(0x800); + return 0; + } + + cdr.Irq = 0xff; + cdr.Ctrl&=~0x80; + + switch (Irq) { + case CdlSync: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlNop: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +/* i = stat.Status; + if (CDR_getStatus(&stat) != -1) { + if (stat.Type == 0xff) cdr.Stat = DiskError; + if (stat.Status & 0x10) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x11; + cdr.Result[0]&=~0x02; + } + else if (i & 0x10) { + cdr.StatP |= 0x2; + cdr.Result[0]|= 0x2; + CheckCdrom(); + } + }*/ + break; + + case CdlSetloc: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlPlay: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + cdr.StatP|= 0x82; +// if ((cdr.Mode & 0x5) == 0x5) AddIrqQueue(REPPLAY, cdReadTime); + break; + + case CdlForward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlBackward: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStandby: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlStop: + cdr.CmdProcess = 0; + SetResultSize(1); + cdr.StatP&=~0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; +// cdr.Stat = Acknowledge; + break; + + case CdlPause: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlPause + 0x20, 0x800); + break; + + case CdlPause + 0x20: + SetResultSize(1); + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlInit: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; +// if (!cdr.Init) { + AddIrqQueue(CdlInit + 0x20, 0x800); +// } + break; + + case CdlInit + 0x20: + SetResultSize(1); + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + cdr.Init = 1; + break; + + case CdlMute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlDemute: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetfilter: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlSetmode: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlGetmode: + SetResultSize(6); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = cdr.Mode; + cdr.Result[2] = cdr.File; + cdr.Result[3] = cdr.Channel; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocL: + SetResultSize(8); +// for (i=0; i<8; i++) cdr.Result[i] = itob(cdr.Transfer[i]); + for (i=0; i<8; i++) cdr.Result[i] = cdr.Transfer[i]; + cdr.Stat = Acknowledge; + break; + + case CdlGetlocP: + SetResultSize(8); +/* subq = (struct SubQ*) CDR_getBufferSub(); + if (subq != NULL) { + cdr.Result[0] = subq->TrackNumber; + cdr.Result[1] = subq->IndexNumber; + memcpy(cdr.Result+2, subq->TrackRelativeAddress, 3); + memcpy(cdr.Result+5, subq->AbsoluteAddress, 3); + } else { +*/ cdr.Result[0] = 1; + cdr.Result[1] = 1; + cdr.Result[2] = cdr.Prev[0]; + cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); + cdr.Result[4] = cdr.Prev[2]; + cdr.Result[5] = cdr.Prev[0]; + cdr.Result[6] = cdr.Prev[1]; + cdr.Result[7] = cdr.Prev[2]; +// } + cdr.Stat = Acknowledge; + break; + + case CdlGetTN: + cdr.CmdProcess = 0; + SetResultSize(3); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + if (CDVDgetTN(&cdr.ResultTN) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + cdr.Stat = Acknowledge; + cdr.Result[1] = itob(cdr.ResultTN.strack); + cdr.Result[2] = itob(cdr.ResultTN.etrack); + } + break; + + case CdlGetTD: + cdr.CmdProcess = 0; + cdr.Track = btoi(cdr.Param[0]); + SetResultSize(4); + cdr.StatP|= 0x2; + if (CDVDgetTD(cdr.Track, &trackInfo) == -1) { + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + } else { + LSNtoMSF(cdr.ResultTD, trackInfo.lsn); + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = itob(cdr.ResultTD[0]); + cdr.Result[2] = itob(cdr.ResultTD[1]); + cdr.Result[3] = itob(cdr.ResultTD[2]); + } + break; + + case CdlSeekL: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekL + 0x20, 0x800); + break; + + case CdlSeekL + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlSeekP: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlSeekP + 0x20, 0x800); + break; + + case CdlSeekP + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case CdlTest: + cdr.Stat = Acknowledge; + switch (cdr.Param[0]) { + case 0x20: // System Controller ROM Version + SetResultSize(4); + *(int*)cdr.Result = *(int*)Test20; + break; + case 0x22: + SetResultSize(8); + *(int*)cdr.Result = *(int*)Test22; + break; + case 0x23: case 0x24: + SetResultSize(8); + *(int*)cdr.Result = *(int*)Test23; + break; + } + break; + + case CdlID: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlID + 0x20, 0x800); + break; + + case CdlID + 0x20: + SetResultSize(8); +// if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player + cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD +/* } + else { + if (stat.Type == 2) { + cdr.Result[0] = 0x08; + cdr.Result[1] = 0x10; + } + else { + cdr.Result[0] = 0x00; + cdr.Result[1] = 0x00; + } + }*/ + if (!LoadCdBios) cdr.Result[1] |= 0x80; + + cdr.Result[2] = 0x00; + cdr.Result[3] = 0x00; + strncpy((char *)&cdr.Result[4], "PCSX", 4); + cdr.Stat = Complete; + break; + + case CdlReset: + SetResultSize(1); + cdr.StatP = 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + break; + + case CdlReadToc: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + AddIrqQueue(CdlReadToc + 0x20, 0x800); + break; + + case CdlReadToc + 0x20: + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Complete; + break; + + case AUTOPAUSE: + cdr.OCUP = 0; +/* SetResultSize(1); + StopCdda(); + StopReading(); + cdr.OCUP = 0; + cdr.StatP&=~0x20; + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = DataEnd; +*/ AddIrqQueue(CdlPause, 0x400); + break; + + case READ_ACK: + if (!cdr.Reading) return 1; + + SetResultSize(1); + cdr.StatP|= 0x2; + cdr.Result[0] = cdr.StatP; + cdr.Stat = Acknowledge; + + ReadTrack(); + + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + + break; + + case REPPLAY_ACK: + cdr.Stat = Acknowledge; + cdr.Result[0] = cdr.StatP; + SetResultSize(1); + AddIrqQueue(REPPLAY, cdReadTime); + break; + + case REPPLAY: + if ((cdr.Mode & 5) != 5) break; +/* if (CDR_getStatus(&stat) == -1) { + cdr.Result[0] = 0; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + cdr.Result[4] = 0; + cdr.Result[5] = 0; + cdr.Result[6] = 0; + cdr.Result[7] = 0; + } else memcpy(cdr.Result, &stat.Track, 8); + cdr.Stat = 1; + SetResultSize(8); + AddIrqQueue(REPPLAY_ACK, cdReadTime); +*/ break; + + case 0xff: + return 1; + + default: + cdr.Stat = Complete; + break; + } + + if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4; + +#ifdef CDR_LOG + CDR_LOG("Cdr Interrupt %x\n", Irq); +#endif + return 1; +} + +int cdrReadInterrupt() { + u8 *buf; + + if (!cdr.Reading) return 1; + + if (cdr.Stat) { + CDREAD_INT(0x800); + return 0; + } + +#ifdef CDR_LOG + CDR_LOG("KEY END"); +#endif + + cdr.OCUP = 1; + SetResultSize(1); + cdr.StatP|= 0x22; + cdr.Result[0] = cdr.StatP; + + SysMessage("Reading From CDR"); + buf = CDVDgetBuffer(); + if (buf == NULL) cdr.RErr = -1; + + if (cdr.RErr == -1) { +#ifdef CDR_LOG + fprintf(emuLog, " err\n"); +#endif + memset(cdr.Transfer, 0, 2340); + cdr.Stat = DiskError; + cdr.Result[0]|= 0x01; + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + return 0; + } + + memcpy_fast(cdr.Transfer, buf+12, 2340); + cdr.Stat = DataReady; + +#ifdef CDR_LOG + fprintf(emuLog, " %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); +#endif + +/* if ((cdr.Muted == 1) && (cdr.Mode & 0x40) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA + if ((cdr.Transfer[4+2] & 0x4) && + ((cdr.Mode&0x8) ? (cdr.Transfer[4+1] == cdr.Channel) : 1) && + (cdr.Transfer[4+0] == cdr.File)) { + int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); + + if (!ret) { + SPU_playADPCMchannel(&cdr.Xa); + cdr.FirstSector = 0; + } + else cdr.FirstSector = -1; + } + }*/ + + cdr.SetSector[2]++; + if (cdr.SetSector[2] == 75) { + cdr.SetSector[2] = 0; + cdr.SetSector[1]++; + if (cdr.SetSector[1] == 60) { + cdr.SetSector[1] = 0; + cdr.SetSector[0]++; + } + } + + cdr.Readed = 0; + + if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF +#ifdef CDR_LOG + CDR_LOG("AutoPausing Read\n"); +#endif +// AddIrqQueue(AUTOPAUSE, 0x800); + AddIrqQueue(CdlPause, 0x800); + } + else { + ReadTrack(); + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + } + + psxHu32(0x1070)|=0x4; + return 0; +} + +/* +cdrRead0: + bit 0 - 0 REG1 command send / 1 REG1 data read + bit 1 - 0 data transfer finish / 1 data transfer ready/in progress + bit 2 - unknown + bit 3 - unknown + bit 4 - unknown + bit 5 - 1 result ready + bit 6 - 1 dma ready + bit 7 - 1 command being processed +*/ + +u8 cdrRead0(void) { + if (cdr.ResultReady) cdr.Ctrl|= 0x20; + else cdr.Ctrl&=~0x20; + + if (cdr.OCUP) cdr.Ctrl|= 0x40; + else cdr.Ctrl&=~0x40; + + // what means the 0x10 and the 0x08 bits? i only saw it used by the bios + cdr.Ctrl|=0x18; + +#ifdef CDR_LOG + CDR_LOG("CD0 Read: %x\n", cdr.Ctrl); +#endif + return psxHu8(0x1800) = cdr.Ctrl; +} + +/* +cdrWrite0: + 0 - to send a command / 1 - to get the result +*/ + +void cdrWrite0(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD0 write: %x\n", rt); +#endif + cdr.Ctrl = rt | (cdr.Ctrl & ~0x3); + + if (rt == 0) { + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + } +} + +u8 cdrRead1(void) { + if (cdr.ResultReady && cdr.Ctrl & 0x1) { + psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; + if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0; + } else psxHu8(0x1801) = 0; +#ifdef CDR_LOG + CDR_LOG("CD1 Read: %x\n", psxHu8(0x1801)); +#endif + return psxHu8(0x1801); +} + +void cdrWrite1(u8 rt) { + int i; + +#ifdef CDR_LOG + CDR_LOG("CD1 write: %x (%s)\n", rt, CmdName[rt]); +#endif +// psxHu8(0x1801) = rt; + cdr.Cmd = rt; + cdr.OCUP = 0; + +#ifdef CDRCMD_DEBUG + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); + if (cdr.ParamC) { + SysPrintf(" Param[%d] = {", cdr.ParamC); + for (i=0;i cdr.ResultTN[1]) cdr.CurTrack = cdr.ResultTN[1]; + if (CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD) != -1) { + int tmp = cdr.ResultTD[2]; + cdr.ResultTD[2] = cdr.ResultTD[0]; + cdr.ResultTD[0] = tmp; + if (!Config.Cdda) CDR_play(cdr.ResultTD); + } + } + } + else if (!Config.Cdda) CDR_play(cdr.SetSector); +*/ cdr.Play = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlForward: + if (cdr.CurTrack < 0xaa) cdr.CurTrack++; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlBackward: + if (cdr.CurTrack > 1) cdr.CurTrack--; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadN: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(1); + break; + + case CdlStandby: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlStop: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlPause: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x40000); + break; + + case CdlReset: + case CdlInit: + StopCdda(); + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlMute: + cdr.Muted = 0; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlDemute: + cdr.Muted = 1; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetfilter: + cdr.File = cdr.Param[0]; + cdr.Channel = cdr.Param[1]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSetmode: +#ifdef CDR_LOG + CDR_LOG("Setmode %x\n", cdr.Param[0]); +#endif + cdr.Mode = cdr.Param[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetmode: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocL: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetlocP: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTN: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlGetTD: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekL: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlSeekP: + ((unsigned long *)cdr.SetSectorSeek)[0] = ((unsigned long *)cdr.SetSector)[0]; + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlTest: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlID: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + case CdlReadS: + cdr.Irq = 0; + StopReading(); + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + StartReading(2); + break; + + case CdlReadToc: + cdr.Ctrl|= 0x80; + cdr.Stat = NoIntr; + AddIrqQueue(cdr.Cmd, 0x800); + break; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd); +#endif + return; + } + if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4; +} + +u8 cdrRead2(void) { + u8 ret; + + if (cdr.Readed == 0) { + ret = 0; + } else { + ret = *cdr.pTransfer++; + } + +#ifdef CDR_LOG + CDR_LOG("CD2 Read: %x\n", ret); +#endif + return ret; +} + +void cdrWrite2(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD2 write: %x\n", rt); +#endif + if (cdr.Ctrl & 0x1) { + switch (rt) { + case 0x07: + cdr.ParamP = 0; + cdr.ParamC = 0; + cdr.ResultReady = 0; + cdr.Ctrl = 0; + break; + + default: + cdr.Reg2 = rt; + break; + } + } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { + cdr.Param[cdr.ParamP++] = rt; + cdr.ParamC++; + } +} + +u8 cdrRead3(void) { + if (cdr.Stat) { + if (cdr.Ctrl & 0x1) psxHu8(0x1803) = cdr.Stat | 0xE0; + else psxHu8(0x1803) = 0xff; + } else psxHu8(0x1803) = 0; +#ifdef CDR_LOG + CDR_LOG("CD3 Read: %x\n", psxHu8(0x1803)); +#endif + return psxHu8(0x1803); +} + +void cdrWrite3(u8 rt) { +#ifdef CDR_LOG + CDR_LOG("CD3 write: %x\n", rt); +#endif + if (rt == 0x07 && cdr.Ctrl & 0x1) { + cdr.Stat = 0; + + if (cdr.Irq == 0xff) { cdr.Irq = 0; return; } + if (cdr.Irq) { + CDR_INT(cdr.eCycle); + }/* else if (cdr.Reading) { + CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); + }*/ + return; + } + if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { + cdr.Readed = 1; + cdr.pTransfer = cdr.Transfer; + + switch (cdr.Mode&0x30) { + case 0x10: + case 0x00: cdr.pTransfer+=12; break; + default: break; + } + } +} + +void psxDma3(u32 madr, u32 bcr, u32 chcr) { + u32 cdsize; + +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + switch (chcr) { + case 0x11000000: + case 0x11400100: + if (cdr.Readed == 0) { +#ifdef CDR_LOG + CDR_LOG("*** DMA 3 *** NOT READY\n"); +#endif + return; + } + + cdsize = (bcr & 0xffff) * 4; + + memcpy_fast((u8*)PSXM(madr), cdr.pTransfer, cdsize); + psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=cdsize; + + break; + case 0x41000200: + //SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr); + // size = 16 * 32 * 4 (one sector) +/* PSXMu8(madr+0) = 0x10; + PSXMu8(madr+1) = 0x00; + PSXMu8(madr+2) = 0x03; + PSXMu8(madr+3) = 0x00;*/ + return; + + default: +#ifdef CDR_LOG + CDR_LOG("Unknown cddma %lx\n", chcr); +#endif + break; + } + HW_DMA3_CHCR &= ~0x01000000; + psxDmaInterrupt(3); +} + +void cdrReset() { + memset(&cdr, 0, sizeof(cdr)); + cdr.CurTrack=1; + cdr.File=1; cdr.Channel=1; + cdReadTime = (PSXCLK / 1757) * BIAS; + //DVD is 4x (PSXCLK / 75) CD is 24x on the PS2, so that would mean CD = (PSXCLK / 450) + // 75/4 = 18.75 x 24 = 450 remember its faster than the PS1 ;) Refraction + + // with the timing set to 60 Gran Turismo works + // anybody knows why it doesn't with 75? + // 75 is the correct cdrom timing +// if (Config.CdTiming) +// cdReadTime = (PSXCLK / 60) / BIAS; + // this seems to be the most compatible + // let's leave like this until we know why + // 75 is buggy with some games +} + +int cdrFreeze(gzFile f, int Mode) { + int tmp; + + gzfreeze(&cdr, sizeof(cdr)); + + if (Mode == 1) tmp = (int)(cdr.pTransfer - cdr.Transfer); + gzfreeze(&tmp, 4); + if (Mode == 0) cdr.pTransfer = cdr.Transfer + tmp; + + return 0; +} + diff --git a/pcsx2/CdRom.h b/pcsx2/CdRom.h new file mode 100644 index 0000000..569909e --- /dev/null +++ b/pcsx2/CdRom.h @@ -0,0 +1,92 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDROM_H__ +#define __CDROM_H__ + +#include "PsxCommon.h" +#include "Decode_XA.h" +#include "PS2Edefs.h" + +typedef struct { + u8 OCUP; + u8 Reg1Mode; + u8 Reg2; + u8 CmdProcess; + u8 Ctrl; + u8 Stat; + + u8 StatP; + + u8 Transfer[2352]; + u8 *pTransfer; + + u8 Prev[4]; + u8 Param[8]; + u8 Result[8]; + + u8 ParamC; + u8 ParamP; + u8 ResultC; + u8 ResultP; + u8 ResultReady; + u8 Cmd; + u8 Readed; + unsigned long Reading; + + cdvdTN ResultTN; + u8 ResultTD[4]; + u8 SetSector[4]; + u8 SetSectorSeek[4]; + u8 Track; + int Play; + int CurTrack; + int Mode, File, Channel, Muted; + int Reset; + int RErr; + int FirstSector; + + xa_decode_t Xa; + + int Init; + + u8 Irq; + unsigned long eCycle; + + char Unused[4087]; +} cdrStruct; + +cdrStruct cdr; + +s32 MSFtoLSN(u8 *Time); +void LSNtoMSF(u8 *Time, s32 lsn); + +void cdrReset(); +int cdrInterrupt(); +int cdrReadInterrupt(); +u8 cdrRead0(void); +u8 cdrRead1(void); +u8 cdrRead2(void); +u8 cdrRead3(void); +void cdrWrite0(u8 rt); +void cdrWrite1(u8 rt); +void cdrWrite2(u8 rt); +void cdrWrite3(u8 rt); +int cdrFreeze(gzFile f, int Mode); + +#endif /* __CDROM_H__ */ diff --git a/pcsx2/Common.h b/pcsx2/Common.h new file mode 100644 index 0000000..e783fb1 --- /dev/null +++ b/pcsx2/Common.h @@ -0,0 +1,254 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +#include +#include + +#if defined(__x86_64__) +#define DONT_USE_GETTEXT +#endif + +#if defined(_WIN32) + +#include + +typedef struct { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; +} AppData; + +extern AppData gApp; +#define pthread_mutex__unlock pthread_mutex_unlock + +#elif defined(__MINGW32__) + +#include +#include +#define BOOL int +#include // posix_memalign() +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +//#define max(a,b) (((a) > (b)) ? (a) : (b)) +//#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define __declspec(x) +#define __assume(x) ; +#define strnicmp strncasecmp +#define stricmp strcasecmp +#include +//#pragma intrinsic (InterlockedAnd) +// Definitions added Feb 16, 2006 by efp +//#define __declspec(x) +#include +#define __forceinline inline +#define _aligned_malloc(x,y) __mingw_aligned_malloc(x,y) +#define _aligned_free(x) __mingw_aligned_free(x) +#define pthread_mutex__unlock pthread_mutex_unlock + +#define fpusqrtf sqrtf +#define fpufabsf fabsf +#define fpusinf sinf +#define fpucosf cosf +#define fpuexpf expf +#define fpuatanf atanf +#define fpuatan2f atan2f + +#else + +#include +#include // posix_memalign() + +// Definitions added Feb 16, 2006 by efp +//#ifndef __declspec +//#define __declspec(x) +//#endif + +#endif + +#ifdef ENABLE_NLS + +#ifdef __MSCW32__ +#include "libintlmsc.h" +#else +#include +#include +#endif + +#undef _ +#define _(String) dgettext (PACKAGE, String) +#ifdef gettext_noop +# define N_(String) gettext_noop (String) +#else +# define N_(String) (String) +#endif + +#else + +#define _(msgid) msgid +#define N_(msgid) msgid + +#endif + +#include "PS2Etypes.h" + +typedef struct _TESTRUNARGS +{ + u8 enabled; + u8 jpgcapture; + + int frame; // if < 0, frame is unlimited (run until crash). + int numimages; + int curimage; + u32 autopad; // mask for auto buttons + int efile; + int snapdone; + + char* ptitle; + char* pimagename; + char* plogname; + char* pgsdll, *pcdvddll, *pspudll; + +} TESTRUNARGS; + +extern TESTRUNARGS g_TestRun; + +#define BIAS 2 // Bus is half of the actual ps2 speed +//#define PS2CLK 36864000 /* 294.912 mhz */ +//#define PSXCLK 9216000 /* 36.864 Mhz */ +//#define PSXCLK 186864000 /* 36.864 Mhz */ +#define PS2CLK 294912000 /* 294.912 mhz */ +#define PSXCLK 36864000 /* 36.864 Mhz */ + + +/* Config.PsxType == 1: PAL: + VBlank interlaced 50.00 Hz + VBlank non-interlaced 49.76 Hz + HBlank 15.625 KHz + Config.PsxType == 0: NSTC + VBlank interlaced 59.94 Hz + VBlank non-interlaced 59.82 Hz + HBlank 15.73426573 KHz */ +#define PS2VBLANK_NTSC_INT ((int)(PS2CLK / 59.94)) +#define PS2VBLANK_NTSC ((int)(PS2CLK / 59.82)) +#define PS2VBLANK_PAL_INT ((int)(PS2CLK / 50.00)) +#define PS2VBLANK_PAL ((int)(PS2CLK / 49.76)) +#define VBLANK_NTSC ((Config.PsxType & 2) ? 59.94 : 59.82) +#define VBLANK_PAL ((Config.PsxType & 2) ? 50.00 : 49.76) +#define HBLANK_NTSC (15734.26573) +#define HBLANK_PAL (15625) +#define PS2HBLANKEND_PAL (386*8) +#define PS2HBLANKEND_NTSC (371*8) +#define PS2VBLANKPAL ((Config.PsxType & 2) ? 312.5 : 314) +#define PS2VBLANKNTSC ((Config.PsxType & 2) ? 262.5 : 263) +#define PS2VBLANKEND_PAL ((int)(PS2HBLANK_PAL*6)) +#define PS2VBLANKEND_NTSC ((int)(PS2HBLANK_NTSC*6)) + +#define PS2HBLANK_NTSC ((int)(PS2CLK / HBLANK_NTSC)) +#define PS2HBLANK_PAL ((int)(PS2CLK / HBLANK_PAL)) +#define PS2HBLANK ((int)((Config.PsxType & 1) ? PS2HBLANK_PAL : PS2HBLANK_NTSC)) +#define PS2HBLANKEND ((int)((Config.PsxType & 1) ? PS2HBLANKEND_PAL : PS2HBLANKEND_NTSC)) +#define PS2VBLANKEND ((int)((Config.PsxType & 1) ? PS2VBLANKEND_PAL : PS2VBLANKEND_NTSC)) +#define PSXVBLANK_NTSC ((int)(PSXCLK / VBLANK_NTSC)) +#define PSXVBLANK_PAL ((int)(PSXCLK / VBLANK_PAL)) +#define PSXVBLANK ((int)((Config.PsxType & 1) ? PSXVBLANK_PAL : PSXVBLANK_NTSC)) +#define PSXHBLANK_NTSC ((int)(PSXCLK / HBLANK_NTSC)) +#define PSXHBLANK_PAL ((int)(PSXCLK / HBLANK_PAL)) +#define PSXHBLANK ((int)((Config.PsxType & 1) ? PSXHBLANK_PAL : PSXHBLANK_NTSC)) +#define PSXPIXEL ((int)(PSXCLK / 13500000)) +#define PSXSOUNDCLK ((int)(48000)) + +#define COLOR_BLACK "\033[30m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[32m" +#define COLOR_YELLOW "\033[33m" +#define COLOR_BLUE "\033[34m" +#define COLOR_MAGENTA "\033[35m" +#define COLOR_CYAN "\033[36m" +#define COLOR_WHITE "\033[37m" +#define COLOR_RESET "\033[0m" + +#include // sync functions + +#include "R5900.h" +#include "DebugTools/Debug.h" +#include "System.h" +#include "Memory.h" +#include "Elfheader.h" +#include "Hw.h" +//#include "GS.h" +#include "Vif.h" +#include "SPR.h" +#include "Sif.h" +#include "Plugins.h" +#include "PS2Edefs.h" +#include "Misc.h" +#include "Counters.h" +#include "IPU/IPU.h" +#include "Patch.h" +#include "COP0.h" +#include "VifDma.h" +#if (defined(__i386__) || defined(__x86_64__)) +#include "x86/ix86/ix86.h" +#endif + +int cdCaseopen; + +extern void __Log(char *fmt, ...); +extern u16 logProtocol; +extern u8 logSource; +#define PCSX2_VERSION "0.9.3" + +// C++ code for sqrtf +void InitFPUOps(); +extern float (*fpusqrtf)(float fval); +extern float (*fpufabsf)(float fval); +extern float (*fpusinf)(float fval); +extern float (*fpucosf)(float fval); +extern float (*fpuexpf)(float fval); +extern float (*fpuatanf)(float fval); +extern float (*fpuatan2f)(float fvalx, float fvaly); + +// Added Feb 16, 2006 by efp +#ifdef __LINUX__ +#include // EBUSY +#endif /* __LINUX__ */ + +#define DESTROY_MUTEX(mutex) { \ + int err = pthread_mutex_destroy(&mutex); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#mutex"\n"); \ +} \ + +#define DESTROY_COND(cond) { \ + int err = pthread_cond_destroy(&cond); \ + if( err == EBUSY ) \ + SysPrintf("cannot destroy"#cond"\n"); \ +} \ + +#endif /* __COMMON_H__ */ diff --git a/pcsx2/Counters.c b/pcsx2/Counters.c new file mode 100644 index 0000000..75ec10b --- /dev/null +++ b/pcsx2/Counters.c @@ -0,0 +1,663 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "GS.h" + +int gates = 0; +extern u8 psxhblankgate; +int hblankend = 0; +Counter counters[6]; +u32 nextCounter, nextsCounter; +static void (*s_prevExecuteVU1Block)() = NULL; + +// its so it doesnt keep triggering an interrupt once its reached its target +// if it doesnt reset the counter it needs stopping +u32 eecntmask = 0; + +void rcntUpdTarget(int index) { + counters[index].sCycleT = cpuRegs.cycle - (cpuRegs.cycle % counters[index].rate); +} + +void rcntUpd(int index) { + counters[index].sCycle = cpuRegs.cycle - (cpuRegs.cycle % counters[index].rate); + rcntUpdTarget(index); +} + +void rcntReset(int index) { + counters[index].count = 0; + counters[index].mode&= ~0x00400C00; + rcntUpd(index); +} + +void rcntSet() { + u32 c; + int i; + + nextCounter = 0xffffffff; + nextsCounter = cpuRegs.cycle; + + for (i = 0; i < 4; i++) { + if (!(counters[i].mode & 0x80)) continue; // Stopped + + c = (0xffff - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + + // the + 10 is just in case of overflow + if(!(counters[i].mode & 0x100)) continue; + c = (counters[i].target - rcntCycle(i)) * counters[i].rate; + if (c < nextCounter) { + nextCounter = c; + } + + } + //Calculate HBlank + c = counters[4].CycleT - (cpuRegs.cycle - counters[4].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } + //Calculate VBlank + c = counters[5].CycleT - (cpuRegs.cycle - counters[5].sCycleT); + if (c < nextCounter) { + nextCounter = c; + } +} + +void rcntInit() { + int i; + + memset(counters, 0, sizeof(counters)); + + for (i=0; i<4; i++) { + counters[i].rate = 2; + counters[i].target = 0xffff; + } + counters[0].interrupt = 9; + counters[1].interrupt = 10; + counters[2].interrupt = 11; + counters[3].interrupt = 12; + + counters[4].mode = 0x3c0; // The VSync counter mode + counters[5].mode = 0x3c0; + + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + UpdateVSyncRate(); + + for (i=0; i<4; i++) rcntUpd(i); + rcntSet(); + + assert(Cpu != NULL && Cpu->ExecuteVU1Block != NULL ); + s_prevExecuteVU1Block = Cpu->ExecuteVU1Block; +} + +void UpdateVSyncRate() { + if (Config.PsxType & 1) { + SysPrintf("PAL\n"); + counters[4].rate = PS2HBLANK_PAL; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_PAL_INT; + else counters[5].rate = PS2VBLANK_PAL; + } else { + SysPrintf("NTSC\n"); + counters[4].rate = PS2HBLANK_NTSC; + if(Config.PsxType & 2)counters[5].rate = PS2VBLANK_NTSC_INT; + else counters[5].rate = PS2VBLANK_NTSC; + } + counters[4].CycleT = PS2HBLANKEND; + counters[4].Cycle = counters[4].rate-PS2HBLANKEND; + + counters[5].CycleT = PS2VBLANKEND; + counters[5].Cycle = counters[5].rate-PS2VBLANKEND; +} + +// debug code, used for stats +int g_nCounters[4]; +extern u32 s_lastvsync[2]; +LARGE_INTEGER lfreq; +static int iFrame = 0; + +void FrameLimiter() +{ + static u32 dwStartTime = 0, dwEndTime = 0; + + // do over 4 frames instead of 1 + if( (iFrame&3) == 0 ) { + u32 frames = (Config.PsxType&1) ? (4000 / 50 - 4) : (4000 / 60 - 4); + dwEndTime = timeGetTime(); + + if( dwEndTime < dwStartTime + frames ) { + if( dwEndTime < dwStartTime + frames - 3 ) + Sleep(frames-(dwEndTime-dwStartTime)-3); + + while(dwEndTime < dwStartTime + frames) dwEndTime = timeGetTime(); + } + + dwStartTime = timeGetTime(); + } +} + +extern u32 CSRw; +extern u32 SuperVUGetRecTimes(int clear); +extern u32 vu0time; + +extern void DummyExecuteVU1Block(void); + +#include "VU.h" +void VSync() { + + //QueryPerformanceFrequency(&lfreq); + + if (counters[5].mode & 0x10000) { // VSync End (22 hsyncs) + + // swap the vsync field + u32 newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000; + *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; + iFrame++; + + // wait until GS stops + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_VSYNC, newfield, 0, 0); + } + else { + GSvsync(newfield); + + // update here on single thread mode + if( PAD1update != NULL ) PAD1update(0); + if( PAD2update != NULL ) PAD2update(1); + } + + counters[5].mode&= ~0x10000; + hwIntcIrq(3); + psxVSyncEnd(); + + if(gates)rcntEndGate(0x8); + SysUpdate(); + } else { // VSync Start (240 hsyncs) + //UpdateVSyncRateEnd(); + + + //SysPrintf("c: %x, %x\n", cpuRegs.cycle, *(u32*)&VU1.Micro[16]); + //if( (iFrame%20) == 0 ) SysPrintf("svu time: %d\n", SuperVUGetRecTimes(1)); +// if( (iFrame%10) == 0 ) { +// SysPrintf("vu0 time: %d\n", vu0time); +// vu0time = 0; +// } + + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled && g_TestRun.frame > 0 ) { + if( iFrame > g_TestRun.frame ) { + // take a snapshot + if( g_TestRun.pimagename != NULL && GSmakeSnapshot2 != NULL ) { + if( g_TestRun.snapdone ) { + g_TestRun.curimage++; + g_TestRun.snapdone = 0; + g_TestRun.frame += 20; + if( g_TestRun.curimage >= g_TestRun.numimages ) { + // exit + SysClose(); + exit(0); + } + } + else { + // query for the image + GSmakeSnapshot2(g_TestRun.pimagename, &g_TestRun.snapdone, g_TestRun.jpgcapture); + } + } + else { + // exit + SysClose(); + exit(0); + } + } + } + + GSVSYNC(); + + if( g_SaveGSStream == 1 ) { + freezeData fP; + + g_SaveGSStream = 2; + gsFreeze(g_fGSSave, 1); + + if (GSfreeze(FREEZE_SIZE, &fP) == -1) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + fP.data = (s8*)malloc(fP.size); + if (fP.data == NULL) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + if (GSfreeze(FREEZE_SAVE, &fP) == -1) { + gzclose(g_fGSSave); + g_SaveGSStream = 0; + } + else { + gzwrite(g_fGSSave, &fP.size, sizeof(fP.size)); + if (fP.size) { + gzwrite(g_fGSSave, fP.data, fP.size); + free(fP.data); + } + } + } + } + } + else if( g_SaveGSStream == 2 ) { + + if( --g_nLeftGSFrames <= 0 ) { + gzclose(g_fGSSave); + g_fGSSave = NULL; + g_SaveGSStream = 0; + SysPrintf("Done saving GS stream\n"); + } + } +#endif + + // used to limit frames + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_LIMIT: + FrameLimiter(); + break; + + case PCSX2_FRAMELIMIT_SKIP: + case PCSX2_FRAMELIMIT_VUSKIP: + { + // the 6 was after trial and error + static u32 uPrevTimes[6] = {0}, uNextFrame = 0, uNumFrames = 0, uTotalTime = 0; + static u32 uLastTime = 0; + static int nConsecutiveSkip = 0, nConsecutiveRender = 0; + extern u32 g_bVUSkip; + static int changed = 0; + static int nNoSkipFrames = 0; + + u32 uExpectedTime; + u32 uCurTime = timeGetTime(); + u32 uDeltaTime = uCurTime - uLastTime; + + assert( GSsetFrameSkip != NULL ); + + if( uLastTime > 0 ) { + + if( uNumFrames == ARRAYSIZE(uPrevTimes) ) + uTotalTime -= uPrevTimes[uNextFrame]; + + uPrevTimes[uNextFrame] = uDeltaTime; + uNextFrame = (uNextFrame + 1) % ARRAYSIZE(uPrevTimes); + uTotalTime += uDeltaTime; + + if( uNumFrames < ARRAYSIZE(uPrevTimes) ) + ++uNumFrames; + } + + uExpectedTime = (Config.PsxType&1) ? (ARRAYSIZE(uPrevTimes) * 1000 / 50 -1) : (ARRAYSIZE(uPrevTimes) * 1000 / 60 - 1); + + if( nNoSkipFrames > 0 ) + --nNoSkipFrames; + + // hmm... this might be more complicated than it needs to be + if( changed != 0 ) { + if( changed > 0 ) { + ++nConsecutiveRender; + --changed; + + if( nConsecutiveRender > 20 && uTotalTime + 1 < uExpectedTime ) { + Sleep(uExpectedTime-uTotalTime); + nNoSkipFrames = ARRAYSIZE(uPrevTimes); + } + } + else { + ++nConsecutiveSkip; + ++changed; + } + } + else { + if( nNoSkipFrames == 0 && nConsecutiveRender > 3 && nConsecutiveSkip < 20 && + (CHECK_MULTIGS? (uTotalTime >= uExpectedTime + uDeltaTime/4 && (uTotalTime >= uExpectedTime + uDeltaTime*3/4 || nConsecutiveSkip==0)) : + (uTotalTime >= uExpectedTime + (uDeltaTime/4))) ) { + + if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP ) { + + Cpu->ExecuteVU1Block = DummyExecuteVU1Block; + } + + if( nConsecutiveSkip == 0 ) { + if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 1, 0, 0); + else GSsetFrameSkip(1); + } + + changed = -3; + nConsecutiveSkip++; + } + else { + + if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_VUSKIP ) { + Cpu->ExecuteVU1Block = s_prevExecuteVU1Block; + } + + if( nConsecutiveSkip ) { + if( CHECK_MULTIGS ) GSRingBufSimplePacket(GS_RINGTYPE_FRAMESKIP, 0, 0, 0); + else GSsetFrameSkip(0); + + nConsecutiveRender = 0; + } + + changed = 3; + nConsecutiveRender++; + nConsecutiveSkip = 0; + + if( nConsecutiveRender > 20 && uTotalTime + 1 < uExpectedTime ) { + Sleep(uExpectedTime-uTotalTime); + nNoSkipFrames = ARRAYSIZE(uPrevTimes); + } + } + } + + uLastTime = uCurTime; + + break; + } + } + + //counters[5].mode&= ~0x10000; + //UpdateVSyncRate(); + + //SysPrintf("ctrs: %d %d %d %d\n", g_nCounters[0], g_nCounters[1], g_nCounters[2], g_nCounters[3]); + //SysPrintf("vif: %d\n", (((LARGE_INTEGER*)g_nCounters)->QuadPart * 1000000) / lfreq.QuadPart); + //memset(g_nCounters, 0, 16); + counters[5].mode|= 0x10000; + + if (!(GSCSRr & 0x8)){ + GSCSRr|= 0x8; + + } + if (!(GSIMR&0x800) ) + gsIrq(); + hwIntcIrq(2); + psxVSyncStart(); + + if(Config.Patch) applypatch(1); + if(gates)rcntStartGate(0x8); + +// __Log("%u %u 0\n", cpuRegs.cycle-s_lastvsync[1], timeGetTime()-s_lastvsync[0]); +// s_lastvsync[0] = timeGetTime(); +// s_lastvsync[1] = cpuRegs.cycle; + } +} + + +void rcntUpdate() +{ + int i; + for (i=0; i<=3; i++) { + if ((counters[i].mode & 0x80)) counters[i].count += (int)((cpuRegs.cycle - counters[i].sCycleT) / counters[i].rate); + counters[i].sCycleT = cpuRegs.cycle - (cpuRegs.cycle % counters[i].rate); + } + for (i=0; i<=3; i++) { + if (!(counters[i].mode & 0x80)) continue; // Stopped + + + if ((counters[i].count & ~0x3) == (counters[i].target & ~0x3)) { // Target interrupt + /*if (rcntCycle(i) != counters[i].target){ + SysPrintf("rcntcycle = %d, target = %d, cyclet = %d\n", rcntCycle(i), counters[i].target, counters[i].sCycleT); + counters[i].sCycleT += (rcntCycle(i) - counters[i].target) * counters[i].rate; + SysPrintf("rcntcycle = %d, target = %d, cyclet = %d\n", rcntCycle(i), counters[i].target, counters[i].sCycleT); + }*/ + //if ((eecntmask & (1 << i)) == 0) { + + if(counters[i].mode & 0x100 && !(counters[i].mode & 0x400)) { + counters[i].mode|= 0x0400; // Target flag + hwIntcIrq(counters[i].interrupt); + + } + //eecntmask |= (1 << i); + //} + if (counters[i].mode & 0x40) { // Reset on target + counters[i].count = 0; + eecntmask &= ~(1 << i); + //rcntUpd(i); + } + + } + + + if (counters[i].count >= 0xffff) { + eecntmask &= ~(1 << i); + + if (counters[i].mode & 0x0200 && !(counters[i].mode & 0x800)) { // Overflow interrupt + counters[i].mode|= 0x0800; // Overflow flag + hwIntcIrq(counters[i].interrupt); +// SysPrintf("counter[%d] overflow interrupt (%x)\n", i, cpuRegs.cycle); + } + counters[i].count = 0; + //rcntUpd(i); + } + // rcntUpd(i); + } + + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT && hblankend == 1){ + + if (!(GSCSRr & 0x4)){ + GSCSRr |= 4; // signal + + } + if (!(GSIMR&0x400) ) + gsIrq(); + if(gates)rcntEndGate(0); + if(psxhblankgate)psxCheckEndGate(0); + hblankend = 0; + counters[4].CycleT = counters[4].rate; + } + if ((cpuRegs.cycle - counters[4].sCycleT) >= counters[4].CycleT) { + counters[4].sCycleT = cpuRegs.cycle; + counters[4].sCycle = cpuRegs.cycle; + counters[4].CycleT = counters[4].rate-PS2HBLANKEND; + counters[4].Cycle = counters[4].rate; + counters[4].count = 0; + + if(gates)rcntStartGate(0); + if(psxhblankgate)psxCheckStartGate(0); + hblankend = 1; + } + + if ((cpuRegs.cycle - counters[5].sCycleT) + >= counters[5].CycleT && (counters[5].mode & 0x10000)){ + counters[5].CycleT = counters[5].rate; + VSync(); + } + + if ((cpuRegs.cycle - counters[5].sCycleT) >= counters[5].CycleT) { + counters[5].sCycleT = cpuRegs.cycle; + counters[5].sCycle = cpuRegs.cycle; + counters[5].CycleT = counters[5].rate-PS2VBLANKEND; + counters[5].Cycle = counters[5].rate; + counters[5].count = 0; + VSync(); + } + rcntSet(); +} + +void rcntWcount(int index, u32 value) { + //SysPrintf ("writeCcount[%d] = %x\n", index, value); +#ifdef EECNT_LOG + EECNT_LOG("EE count write %d count %x with %x target %x eecycle %x\n", index, counters[index].count, value, counters[index].target, cpuRegs.eCycle); +#endif + //if((u16)value < counters[index].target) + //eecntmask &= ~(1 << index); + counters[index].count = value & 0xffff; + rcntUpd(index); + rcntSet(); +} + +void rcntWmode(int index, u32 value) +{ + + + if (value & 0xc00) { //Clear status flags, the ps2 only clears what is given in the value + //eecntmask &= ~(1 << index); + counters[index].mode &= ~(value & 0xc00); + } + + if((value & 0x80) && !(counters[index].mode & 0x80)) rcntUpd(index); //Counter wasnt started, so set the start cycle + +// if((value & 0x3ff) != (counters[index].mode & 0x3ff))eecntmask &= ~(1 << index); + counters[index].mode = (counters[index].mode & 0xc00) | (value & 0x3ff); + +#ifdef EECNT_LOG + EECNT_LOG("EE counter set %d mode %x\n", index, counters[index].mode); +#endif + + switch (value & 0x3) { //Clock rate divisers *2, they use BUSCLK speed not PS2CLK + case 0: counters[index].rate = 2; break; + case 1: counters[index].rate = 32; break; + case 2: counters[index].rate = 512; break; + case 3: counters[index].rate = PS2HBLANK; break; + } + + if((counters[index].mode & 0xF) == 0x7) { + gates &= ~(1<> 4); + switch((counters[i].mode & 0x30) >> 4){ + case 0x0: //Count When Signal is low (off) + counters[i].count = rcntRcount(i); + rcntUpd(i); + counters[i].mode &= ~0x80; + break; + case 0x1: //Reset and start counting on Vsync start + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x2: //Reset and start counting on Vsync end + //Do Nothing + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntEndGate(int mode){ + int i; + + for(i=0; i <=3; i++){ //Gates for counters + if(!(gates & (1<> 4); + switch((counters[i].mode & 0x30) >> 4){ + case 0x0: //Count When Signal is low (off) + rcntUpd(i); + counters[i].mode |= 0x80; + break; + case 0x1: //Reset and start counting on Vsync start + //Do Nothing + break; + case 0x2: //Reset and start counting on Vsync end + counters[i].mode |= 0x80; + rcntReset(i); + break; + case 0x3: //Reset and start counting on Vsync start and end + counters[i].mode |= 0x80; + rcntReset(i); + break; + default: + SysPrintf("EE Start Counter %x Gate error\n", i); + break; + } + } +} +void rcntWtarget(int index, u32 value) { + + //eecntmask &= ~(1 << index); + counters[index].target = value & 0xffff; + +#ifdef EECNT_LOG + EECNT_LOG("EE target write %d target %x value %x\n", index, counters[index].target, value); +#endif + rcntSet(); +} + +void rcntWhold(int index, u32 value) { +#ifdef EECNT_LOG + EECNT_LOG("EE hold write %d value %x\n", index, value); +#endif + counters[index].hold = value; +} + +u16 rcntRcount(int index) { + u16 ret; + + if ((counters[index].mode & 0x80)) { + ret = counters[index].count + (int)((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); + }else{ + ret = counters[index].count; + } + + return (u16)ret; +} + +u32 rcntCycle(int index) { + + if ((counters[index].mode & 0x80)) { + return (u32)counters[index].count + (int)((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); + }else{ + return (u32)counters[index].count; + } +} + +int rcntFreeze(gzFile f, int Mode) { + gzfreezel(counters); + gzfreeze(&nextCounter, sizeof(nextCounter)); + gzfreeze(&nextsCounter, sizeof(nextsCounter)); + + return 0; +} + diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h new file mode 100644 index 0000000..8db0188 --- /dev/null +++ b/pcsx2/Counters.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COUNTERS_H__ +#define __COUNTERS_H__ + +typedef struct { + u32 count, mode, target, hold; + u32 rate, interrupt; + u32 Cycle, sCycle; + u32 CycleT, sCycleT; +} Counter; + +extern Counter counters[6]; +extern u32 nextCounter, nextsCounter; + +void rcntInit(); +void rcntUpdate(); +void rcntStartGate(int mode); +void rcntEndGate(int mode); +void rcntWcount(int index, u32 value); +void rcntWmode(int index, u32 value); +void rcntWtarget(int index, u32 value); +void rcntWhold(int index, u32 value); +u16 rcntRcount(int index); +u32 rcntCycle(int index); +int rcntFreeze(gzFile f, int Mode); + +void UpdateVSyncRate(); + +#endif /* __COUNTERS_H__ */ diff --git a/pcsx2/DebugTools/Debug.h b/pcsx2/DebugTools/Debug.h new file mode 100644 index 0000000..6df5ba1 --- /dev/null +++ b/pcsx2/DebugTools/Debug.h @@ -0,0 +1,137 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "Common.h" + +FILE *emuLog; + +char* disR5900F(u32 code, u32 pc); +char* disR5900Fasm(u32 code, u32 pc); +char* disR3000Fasm(u32 code, u32 pc); + +void disR5900AddSym(u32 addr, char *name); +char* disR5900GetSym(u32 addr); +char* disR5900GetUpperSym(u32 addr); +void disR5900FreeSyms(); + +char* disVU0MicroUF(u32 code, u32 pc); +char* disVU0MicroLF(u32 code, u32 pc); +char* disVU1MicroUF(u32 code, u32 pc); +char* disVU1MicroLF(u32 code, u32 pc); + +char* disR3000AF(u32 code, u32 pc); + +extern char *CP2VFnames[]; +extern char *disRNameCP2f[]; +extern char *disRNameCP2i[]; + +//that way is slower but you now not need to compile every time ;P +#ifdef PCSX2_DEVBUILD + +int Log; +u32 varLog; + +//memcars has the same number as PAD_LOG +#define MEMCARDS_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log + +#define CPU_LOG if (varLog & 0x00000001) {logProtocol=1; logSource='E';} if (varLog & 0x00000001) __Log +#define MEM_LOG if (varLog & 0x00000002) {logProtocol=6; logSource='E';} if (varLog & 0x00000002) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000002) __Log +#define HW_LOG if (varLog & 0x00000004) {logProtocol=6; logSource='E';} if (varLog & 0x00000004) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000004) __Log +#define DMA_LOG if (varLog & 0x00000008) {logProtocol=5; logSource='E';} if (varLog & 0x00000008) __Log +#define BIOS_LOG if (varLog & 0x00000010) {logProtocol=0; logSource='E';} if (varLog & 0x00000010) __Log("%8.8lx: ", cpuRegs.pc); if (varLog & 0x00000010) __Log +#define ELF_LOG if (varLog & 0x00000020) {logProtocol=7; logSource='E';} if (varLog & 0x00000020) __Log +#define FPU_LOG if (varLog & 0x00000040) {logProtocol=1; logSource='E';} if (varLog & 0x00000040) __Log +#define MMI_LOG if (varLog & 0x00000080) {logProtocol=1; logSource='E';} if (varLog & 0x00000080) __Log +#define VU0_LOG if (varLog & 0x00000100) {logProtocol=2; logSource='E';} if (varLog & 0x00000100) __Log +#define COP0_LOG if (varLog & 0x00000200) {logProtocol=1; logSource='E';} if (varLog & 0x00000200) __Log +#define VIF_LOG if (varLog & 0x00000400) {logProtocol=3; logSource='E';} if (varLog & 0x00000400) __Log +#define SPR_LOG if (varLog & 0x00000800) {logProtocol=7; logSource='E';} if (varLog & 0x00000800) __Log +#define GIF_LOG if (varLog & 0x00001000) {logProtocol=4; logSource='E';} if (varLog & 0x00001000) __Log +#define SIF_LOG if (varLog & 0x00002000) {logProtocol=9; logSource='E';} if (varLog & 0x00002000) __Log +#define IPU_LOG if (varLog & 0x00004000) {logProtocol=8; logSource='E';} if (varLog & 0x00004000) __Log +#define VUM_LOG if (varLog & 0x00008000) {logProtocol=2; logSource='E';} if (varLog & 0x00008000) __Log +#define RPC_LOG if (varLog & 0x00010000) {logProtocol=9; logSource='E';} if (varLog & 0x00010000) __Log + +#define PSXCPU_LOG if (varLog & 0x00100000) {logProtocol=1; logSource='I';} if (varLog & 0x00100000) __Log +#define PSXMEM_LOG if (varLog & 0x00200000) {logProtocol=6; logSource='I';} if (varLog & 0x00200000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00200000) __Log +#define PSXHW_LOG if (varLog & 0x00400000) {logProtocol=2; logSource='I';} if (varLog & 0x00400000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00400000) __Log +#define PSXBIOS_LOG if (varLog & 0x00800000) {logProtocol=0; logSource='I';} if (varLog & 0x00800000) __Log("%8.8lx : ", psxRegs.pc); if (varLog & 0x00800000) __Log +#define PSXDMA_LOG if (varLog & 0x01000000) {logProtocol=5; logSource='I';} if (varLog & 0x01000000) __Log + +#define PAD_LOG if (varLog & 0x02000000) {logProtocol=7; logSource='I';} if (varLog & 0x02000000) __Log +#define GTE_LOG if (varLog & 0x04000000) {logProtocol=3; logSource='I';} if (varLog & 0x04000000) __Log +#define CDR_LOG if (varLog & 0x08000000) {logProtocol=8; logSource='I';} if (varLog & 0x08000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x08000000) __Log +#define GPU_LOG if (varLog & 0x10000000) {logProtocol=4; logSource='I';} if (varLog & 0x10000000) __Log +#define PSXCNT_LOG if (varLog & 0x20000000) {logProtocol=0; logSource='I';} if (varLog & 0x20000000) __Log("%8.8lx %8.8lx: ", psxRegs.pc, psxRegs.cycle); if (varLog & 0x20000000) __Log +#define EECNT_LOG if (varLog & 0x40000000) {logProtocol=0; logSource='I';} if (varLog & 0x40000000) __Log("%8.8lx %8.8lx: ", cpuRegs.pc, cpuRegs.cycle); if (varLog & 0x40000000) __Log + +#if defined (CPU_LOG) || defined(MEM_LOG) || defined(HW_LOG) || defined(DMA_LOG) || \ + defined(BIOS_LOG) || defined(ELF_LOG) || defined(FPU_LOG) || defined(MMI_LOG) || \ + defined(VU0_LOG) || defined(COP0_LOG) || defined(VIF_LOG) || defined(SPR_LOG) || \ + defined(GIF_LOG) || defined(SIF_LOG) || defined(IPU_LOG) || defined(VUM_log) || \ + defined(PSXCPU_LOG) || defined(PSXMEM_LOG)|| defined(IOPBIOS_LOG)|| defined(IOPHW_LOG)|| \ + defined(PAD_LOG) || defined(GTE_LOG) || defined(CDR_LOG) || defined(GPU_LOG) || \ + defined(MEMCARDS_LOG)|| defined(PSXCNT_LOG) || defined(EECNT_LOG) +#define EMU_LOG __Log +#endif + +#else // PCSX2_DEVBUILD + +#define varLog 0 +#define Log 0 + +#define CPU_LOG 0&& +#define MEM_LOG 0&& +#define HW_LOG 0&& +#define DMA_LOG 0&& +#define BIOS_LOG 0&& +#define ELF_LOG 0&& +#define FPU_LOG 0&& +#define MMI_LOG 0&& +#define VU0_LOG 0&& +#define COP0_LOG 0&& +#define VIF_LOG 0&& +#define SPR_LOG 0&& +#define GIF_LOG 0&& +#define SIF_LOG 0&& +#define IPU_LOG 0&& +#define VUM_LOG 0&& +#define RPC_LOG 0&& + +#define PSXCPU_LOG 0&& +#define PSXMEM_LOG 0&& +#define PSXHW_LOG 0&& +#define PSXBIOS_LOG 0&& +#define PSXDMA_LOG 0&& + +#define PAD_LOG 0&& +#define GTE_LOG 0&& +#define CDR_LOG 0&& +#define GPU_LOG 0&& +#define PSXCNT_LOG 0&& +#define EECNT_LOG 0&& + +#define EMU_LOG 0&& + +#endif + +#endif /* __DEBUG_H__ */ diff --git a/pcsx2/DebugTools/DisASM.h b/pcsx2/DebugTools/DisASM.h new file mode 100644 index 0000000..ceb5917 --- /dev/null +++ b/pcsx2/DebugTools/DisASM.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "R5900.h" + +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +///******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) + +//IOP + +#define DECODE_RD_IOP ((psxRegs.code >> 11) & 0x1F) +#define DECODE_RT_IOP ((psxRegs.code >> 16) & 0x1F) +#define DECODE_RS_IOP ((psxRegs.code >> 21) & 0x1F) +#define DECODE_IMMED_IOP ( psxRegs.code & 0xFFFF) +#define DECODE_SA_IOP ((psxRegs.code >> 6) & 0x1F) +#define DECODE_FS_IOP (DECODE_RD_IOP) + diff --git a/pcsx2/DebugTools/DisR3000A.c b/pcsx2/DebugTools/DisR3000A.c new file mode 100644 index 0000000..d0dad71 --- /dev/null +++ b/pcsx2/DebugTools/DisR3000A.c @@ -0,0 +1,318 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Debug.h" + +char ostr[256]; + +// Names of registers +static char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra"}; + +static char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + + +// Type deffinition of our functions + +typedef char* (*TdisR3000AF)(u32 code, u32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisFg(fn, b) char* fn(u32 code, u32 pc) { b; return ostr; } +#define MakeDisF(fn, b) \ + static char* fn(u32 code, u32 pc) { \ + sprintf (ostr, "%8.8lx %8.8lx:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + + +#include "R3000A.h" + +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ +#undef _Target_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.r[i], disRNameGPR[i]) +#define dCP0(i) sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.CP0.r[i], disRNameCP0[i]) +#define dHI() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.hi, "hi") +#define dLO() sprintf(ostr, "%s %8.8lx (%s),", ostr, psxRegs.GPR.n.lo, "lo") +#define dImm() sprintf(ostr, "%s %4.4lx (%ld),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8lx,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2lx (%ld),", ostr, _Sa_, _Sa_) +#define dOfB() sprintf(ostr, "%s %4.4lx (%8.8lx (%s)),", ostr, _Im_, psxRegs.GPR.r[_Rs_], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8lx,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8lx,", ostr, (code >> 6) & 0xffffff) + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR(_Rt_); dGPR(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR(_Rt_); dGPR(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR(_Rd_); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR(_Rs_); dGPR(_Rt_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR(_Rs_); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, dName("BGEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR(_Rs_); dOffset();) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR(_Rd_); dGPR(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disSRA, dName("SRA"); dGPR(_Rd_); dGPR(_Rt_); dSa();) +MakeDisF(disSRL, dName("SRL"); dGPR(_Rd_); dGPR(_Rt_); dSa();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR(_Rd_); dGPR(_Rt_); dGPR(_Rs_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR(_Rd_); dHI();) +MakeDisF(disMFLO, dName("MFLO"); dGPR(_Rd_); dLO();) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI(); dGPR(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO(); dGPR(_Rs_);) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, dName("BREAK")) +MakeDisF(disRFE, dName("RFE")) +MakeDisF(disSYSCALL, dName("SYSCALL")) + + + +MakeDisF(disRTPS, dName("RTPS")) +MakeDisF(disOP , dName("OP")) +MakeDisF(disNCLIP, dName("NCLIP")) +MakeDisF(disDPCS, dName("DPCS")) +MakeDisF(disINTPL, dName("INTPL")) +MakeDisF(disMVMVA, dName("MVMVA")) +MakeDisF(disNCDS , dName("NCDS")) +MakeDisF(disCDP , dName("CDP")) +MakeDisF(disNCDT , dName("NCDT")) +MakeDisF(disNCCS , dName("NCCS")) +MakeDisF(disCC , dName("CC")) +MakeDisF(disNCS , dName("NCS")) +MakeDisF(disNCT , dName("NCT")) +MakeDisF(disSQR , dName("SQR")) +MakeDisF(disDCPL , dName("DCPL")) +MakeDisF(disDPCT , dName("DPCT")) +MakeDisF(disAVSZ3, dName("AVSZ3")) +MakeDisF(disAVSZ4, dName("AVSZ4")) +MakeDisF(disRTPT , dName("RTPT")) +MakeDisF(disGPF , dName("GPF")) +MakeDisF(disGPL , dName("GPL")) +MakeDisF(disNCCT , dName("NCCT")) + +MakeDisF(disMFC2, dName("MFC2"); dGPR(_Rt_);) +MakeDisF(disCFC2, dName("CFC2"); dGPR(_Rt_);) +MakeDisF(disMTC2, dName("MTC2")) +MakeDisF(disCTC2, dName("CTC2")) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR(_Rs_); dGPR(_Rt_); dOffset();) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget();) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR(31);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR(_Rs_);) +MakeDisF(disJALR, dName("JALR"); dGPR(_Rs_); dGPR(_Rd_)) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disLWC2, dName("LWC2"); dGPR(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR(_Rt_); dOfB();) +MakeDisF(disSWC2, dName("SWC2"); dGPR(_Rt_); dOfB();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP0(_Rd_); dGPR(_Rt_);) +MakeDisF(disCFC0, dName("CFC0"); dGPR(_Rt_); dCP0(_Rd_);) +MakeDisF(disCTC0, dName("CTC0"); dCP0(_Rd_); dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT }; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disNULL , disNULL, disNULL, disNULL , disNULL }; + +MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) diff --git a/pcsx2/DebugTools/DisR3000asm.c b/pcsx2/DebugTools/DisR3000asm.c new file mode 100644 index 0000000..4afa2d1 --- /dev/null +++ b/pcsx2/DebugTools/DisR3000asm.c @@ -0,0 +1,361 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Debug.h" +#include "R5900.h" +#include "R3000A.h" +#include "DisASM.h" + +unsigned long IOP_opcode_addr; + +char *GPR_IOP_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_IOP_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +void IOPD_SPECIAL(char *buf); +void IOPD_REGIMM(char *buf); +void IOPD_J(char *buf); +void IOPD_JAL(char *buf); +void IOPD_BEQ(char *buf); +void IOPD_BNE(char *buf); +void IOPD_BLEZ(char *buf); +void IOPD_BGTZ(char *buf); +void IOPD_ADDI(char *buf); +void IOPD_ADDIU(char *buf); +void IOPD_SLTI(char *buf); +void IOPD_SLTIU(char *buf); +void IOPD_ANDI(char *buf); +void IOPD_ORI(char *buf); +void IOPD_XORI(char *buf); +void IOPD_LUI(char *buf); +void IOPD_COP0(char *buf); +void IOPD_COP2(char *buf); +void IOPD_LB(char *buf); +void IOPD_LH(char *buf); +void IOPD_LWL(char *buf); +void IOPD_LW(char *buf); +void IOPD_LBU(char *buf); +void IOPD_LHU(char *buf); +void IOPD_LWR(char *buf); +void IOPD_SB(char *buf); +void IOPD_SH(char *buf); +void IOPD_SWL(char *buf); +void IOPD_SW(char *buf); +void IOPD_SWR(char *buf); +void IOPD_LWC2(char *buf); +void IOPD_SWC2(char *buf); + +void IOPD_SLL(char *buf); +void IOPD_SRL(char *buf); +void IOPD_SRA(char *buf); +void IOPD_SLLV(char *buf); +void IOPD_SRLV(char *buf); +void IOPD_SRAV(char *buf); +void IOPD_JR(char *buf); +void IOPD_JALR(char *buf); +void IOPD_SYSCALL(char *buf); +void IOPD_BREAK(char *buf); +void IOPD_MFHI(char *buf); +void IOPD_MTHI(char *buf); +void IOPD_MFLO(char *buf); +void IOPD_MTLO(char *buf); +void IOPD_MULT(char *buf); +void IOPD_MULTU(char *buf); +void IOPD_DIV(char *buf); +void IOPD_DIVU(char *buf); +void IOPD_ADD(char *buf); +void IOPD_ADDU(char *buf); +void IOPD_SUB(char *buf); +void IOPD_SUBU(char *buf); +void IOPD_AND(char *buf); +void IOPD_OR(char *buf); +void IOPD_XOR(char *buf); +void IOPD_NOR(char *buf); +void IOPD_SLT(char *buf); +void IOPD_SLTU(char *buf); + + +void IOPD_BLTZ(char *buf); +void IOPD_BGEZ(char *buf); +void IOPD_BLTZAL(char *buf); +void IOPD_BGEZAL(char *buf); + + + +void IOPD_MFC0(char *buf); +void IOPD_CFC0(char *buf); +void IOPD_MTC0(char *buf); +void IOPD_CTC0(char *buf); +void IOPD_RFE(char *buf); + + + +void IOPD_BASIC(char *buf); +void IOPD_RTPS(char *buf); +void IOPD_NCLIP(char *buf); +void IOPD_OP(char *buf); +void IOPD_DPCS(char *buf); +void IOPD_INTPL(char *buf); +void IOPD_MVMVA(char *buf); +void IOPD_NCDS(char *buf); +void IOPD_CDP(char *buf); +void IOPD_NCDT(char *buf); +void IOPD_NCCS(char *buf); +void IOPD_CC(char *buf); +void IOPD_NCS(char *buf); +void IOPD_NCT(char *buf); +void IOPD_SQR(char *buf); +void IOPD_DCPL(char *buf); +void IOPD_DPCT(char *buf); +void IOPD_AVSZ3(char *buf); +void IOPD_AVSZ4(char *buf); +void IOPD_RTPT(char *buf); +void IOPD_GPF(char *buf); +void IOPD_GPL(char *buf); +void IOPD_NCCT(char *buf); + + + +void IOPD_MFC2(char *buf); +void IOPD_CFC2(char *buf); +void IOPD_MTC2(char *buf); +void IOPD_CTC2(char *buf); +void IOPD_NULL(char *buf); + + + + void (*IOP_DEBUG_BSC[64])(char *buf) = { + IOPD_SPECIAL, IOPD_REGIMM, IOPD_J , IOPD_JAL , IOPD_BEQ , IOPD_BNE , IOPD_BLEZ, IOPD_BGTZ, + IOPD_ADDI , IOPD_ADDIU , IOPD_SLTI, IOPD_SLTIU, IOPD_ANDI, IOPD_ORI , IOPD_XORI, IOPD_LUI , + IOPD_COP0 , IOPD_NULL , IOPD_COP2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_LB , IOPD_LH , IOPD_LWL , IOPD_LW , IOPD_LBU , IOPD_LHU , IOPD_LWR , IOPD_NULL, + IOPD_SB , IOPD_SH , IOPD_SWL , IOPD_SW , IOPD_NULL, IOPD_NULL, IOPD_SWR , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_LWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_SWC2, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + + +void (*IOP_DEBUG_SPC[64])(char *buf) = { + IOPD_SLL , IOPD_NULL , IOPD_SRL , IOPD_SRA , IOPD_SLLV , IOPD_NULL , IOPD_SRLV, IOPD_SRAV, + IOPD_JR , IOPD_JALR , IOPD_NULL, IOPD_NULL, IOPD_SYSCALL, IOPD_BREAK, IOPD_NULL, IOPD_NULL, + IOPD_MFHI, IOPD_MTHI , IOPD_MFLO, IOPD_MTLO, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_MULT, IOPD_MULTU, IOPD_DIV , IOPD_DIVU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_ADD , IOPD_ADDU , IOPD_SUB , IOPD_SUBU, IOPD_AND , IOPD_OR , IOPD_XOR , IOPD_NOR , + IOPD_NULL, IOPD_NULL , IOPD_SLT , IOPD_SLTU, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_REG[32])(char *buf) = { + IOPD_BLTZ , IOPD_BGEZ , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_BLTZAL, IOPD_BGEZAL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP0[32])(char *buf) = { + IOPD_MFC0, IOPD_NULL, IOPD_CFC0, IOPD_NULL, IOPD_MTC0, IOPD_NULL, IOPD_CTC0, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_RFE , IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +void (*IOP_DEBUG_CP2[64])(char *buf) = { + IOPD_BASIC, IOPD_RTPS , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NCLIP, IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_OP , IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_DPCS , IOPD_INTPL, IOPD_MVMVA, IOPD_NCDS, IOPD_CDP , IOPD_NULL , IOPD_NCDT , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NCCS, IOPD_CC , IOPD_NULL , IOPD_NCS , IOPD_NULL, + IOPD_NCT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_SQR , IOPD_DCPL , IOPD_DPCT , IOPD_NULL, IOPD_NULL, IOPD_AVSZ3, IOPD_AVSZ4, IOPD_NULL, + IOPD_RTPT , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_NULL , IOPD_NULL , IOPD_NULL, + IOPD_NULL , IOPD_NULL , IOPD_NULL , IOPD_NULL, IOPD_NULL, IOPD_GPF , IOPD_GPL , IOPD_NCCT +}; + +void (*IOP_DEBUG_CP2BSC[32])(char *buf) = { + IOPD_MFC2, IOPD_NULL, IOPD_CFC2, IOPD_NULL, IOPD_MTC2, IOPD_NULL, IOPD_CTC2, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, + IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL, IOPD_NULL +}; + +static char dbuf2[1024]; +static char obuf2[1024]; + +char *disR3000Fasm(u32 code, u32 pc) { + u32 scode = psxRegs.code; + IOP_opcode_addr = pc; + psxRegs.code = code; + IOP_DEBUG_BSC[(code) >> 26](dbuf2); + + sprintf(obuf2, "%08lX:\t%s", pc, dbuf2); + + psxRegs.code = scode; + return obuf2; +} +char *IOP_jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = (IOP_opcode_addr & 0xf0000000)|((psxRegs.code&0x3ffffff)<<2); + sprintf(buf, "0x%08lX", addr); + return buf; +} +char *IOP_offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = ((((short)( psxRegs.code & 0xFFFF) * 4) + IOP_opcode_addr + 4)); + sprintf(buf, "0x%08lX", addr); + return buf; +} +//basic table +void IOPD_SPECIAL(char *buf){IOP_DEBUG_SPC[((psxRegs.code) & 0x3F)](buf);} +void IOPD_REGIMM(char *buf){IOP_DEBUG_REG[DECODE_RT_IOP](buf);} +void IOPD_J(char *buf) { sprintf(buf, "j\t%s", IOP_jump_decode());} +void IOPD_JAL(char *buf){sprintf(buf, "jal\t%s", IOP_jump_decode());} +void IOPD_BEQ(char *buf){sprintf(buf, "beq\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BNE(char *buf){sprintf(buf, "bne\t%s, %s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP], IOP_offset_decode()); } +void IOPD_BLEZ(char *buf){sprintf(buf, "blez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGTZ(char *buf){sprintf(buf, "bgtz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_ADDI(char *buf){sprintf(buf, "addi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ADDIU(char *buf){sprintf(buf, "addiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTI(char *buf){sprintf(buf, "slti\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_SLTIU(char *buf){sprintf(buf, "sltiu\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ANDI(char *buf){sprintf(buf, "andi\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP);} +void IOPD_ORI(char *buf){sprintf(buf, "ori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_XORI(char *buf){sprintf(buf, "xori\t%s, %s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP], DECODE_IMMED_IOP); } +void IOPD_LUI(char *buf){sprintf(buf, "lui\t%s, 0x%04lX", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP); } +void IOPD_COP0(char *buf){IOP_DEBUG_CP0[DECODE_RS_IOP](buf);} +void IOPD_COP2(char *buf){IOP_DEBUG_CP2[((psxRegs.code) & 0x3F)](buf);} +void IOPD_LB(char *buf){sprintf(buf, "lb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LH(char *buf){sprintf(buf, "lh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWL(char *buf){sprintf(buf, "lwl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LW(char *buf){sprintf(buf, "lw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LBU(char *buf){sprintf(buf, "lbu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LHU(char *buf){sprintf(buf, "lhu\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_LWR(char *buf){sprintf(buf, "lwr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SB(char *buf){sprintf(buf, "sb\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SH(char *buf){sprintf(buf, "sh\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWL(char *buf){sprintf(buf, "swl\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SW(char *buf){sprintf(buf, "sw\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SWR(char *buf){sprintf(buf, "swr\t%s, 0x%04lX(%s)", GPR_IOP_REG[DECODE_RT_IOP], DECODE_IMMED_IOP, GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_LWC2(char *buf){strcpy(buf, "lwc2");} +void IOPD_SWC2(char *buf){strcpy(buf, "swc2");} +//special table +void IOPD_SLL(char *buf) +{ + if (psxRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); +} +void IOPD_SRL(char *buf){sprintf(buf, "srl\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP); } +void IOPD_SRA(char *buf){sprintf(buf, "sra\t%s, %s, 0x%02lX", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], DECODE_SA_IOP);} +void IOPD_SLLV(char *buf){sprintf(buf, "sllv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_SRLV(char *buf){sprintf(buf, "srlv\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_SRAV(char *buf){sprintf(buf, "srav\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RT_IOP], GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_JR(char *buf){sprintf(buf, "jr\t%s", GPR_IOP_REG[DECODE_RS_IOP]);} +void IOPD_JALR(char *buf) +{ + int rd = DECODE_RD_IOP; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_IOP_REG[DECODE_RS_IOP]); + else + sprintf(buf, "jalr\t%s, %s", GPR_IOP_REG[rd], GPR_IOP_REG[DECODE_RS_IOP]); +} + +void IOPD_SYSCALL(char *buf){strcpy(buf, "syscall");} +void IOPD_BREAK(char *buf){strcpy(buf, "break");} +void IOPD_MFHI(char *buf){sprintf(buf, "mfhi\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTHI(char *buf){sprintf(buf, "mthi\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MFLO(char *buf){sprintf(buf, "mflo\t%s", GPR_IOP_REG[DECODE_RD_IOP]); } +void IOPD_MTLO(char *buf){sprintf(buf, "mtlo\t%s", GPR_IOP_REG[DECODE_RS_IOP]); } +void IOPD_MULT(char *buf){sprintf(buf, "mult\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_MULTU(char *buf){sprintf(buf, "multu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIV(char *buf){sprintf(buf, "div\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]);} +void IOPD_DIVU(char *buf){sprintf(buf, "divu\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } + +void IOPD_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +void IOPD_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_IOP_REG[DECODE_RD_IOP], GPR_IOP_REG[DECODE_RS_IOP], GPR_IOP_REG[DECODE_RT_IOP]); } +//regimm + +void IOPD_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } +void IOPD_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_IOP_REG[DECODE_RS_IOP], IOP_offset_decode()); } + +//cop0 + +void IOPD_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CFC0(char *buf){ sprintf(buf, "cfc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_CTC0(char *buf){ sprintf(buf, "ctc0\t%s, %s", GPR_IOP_REG[DECODE_RT_IOP], COP0_IOP_REG[DECODE_FS_IOP]); } +void IOPD_RFE(char *buf){strcpy(buf, "rfe");} +//cop2 +void IOPD_BASIC(char *buf){IOP_DEBUG_CP2BSC[DECODE_RS_IOP](buf);} +void IOPD_RTPS(char *buf){strcpy(buf, "rtps");} +void IOPD_NCLIP(char *buf){strcpy(buf, "nclip");} +void IOPD_OP(char *buf){strcpy(buf, "op");} +void IOPD_DPCS(char *buf){strcpy(buf, "dpcs");} +void IOPD_INTPL(char *buf){strcpy(buf, "intpl");} +void IOPD_MVMVA(char *buf){strcpy(buf, "mvmva");} +void IOPD_NCDS(char *buf){strcpy(buf, "ncds");} +void IOPD_CDP(char *buf){strcpy(buf, "cdp");} +void IOPD_NCDT(char *buf){strcpy(buf, "ncdt");} +void IOPD_NCCS(char *buf){strcpy(buf, "nccs");} +void IOPD_CC(char *buf){strcpy(buf, "cc");} +void IOPD_NCS(char *buf){strcpy(buf, "ncs");} +void IOPD_NCT(char *buf){strcpy(buf, "nct");} +void IOPD_SQR(char *buf){strcpy(buf, "sqr");} +void IOPD_DCPL(char *buf){strcpy(buf, "dcpl");} +void IOPD_DPCT(char *buf){strcpy(buf, "dpct");} +void IOPD_AVSZ3(char *buf){strcpy(buf, "avsz3");} +void IOPD_AVSZ4(char *buf){strcpy(buf, "avsz4");} +void IOPD_RTPT(char *buf){strcpy(buf, "rtpt");} +void IOPD_GPF(char *buf){strcpy(buf, "gpf");} +void IOPD_GPL(char *buf){strcpy(buf, "gpl");} +void IOPD_NCCT(char *buf){strcpy(buf, "ncct");} +//cop2 basic +void IOPD_MFC2(char *buf){strcpy(buf, "mfc2");} +void IOPD_CFC2(char *buf){strcpy(buf, "cfc2");} +void IOPD_MTC2(char *buf){strcpy(buf, "mtc2");} +void IOPD_CTC2(char *buf){strcpy(buf, "ctc2");} +//null +void IOPD_NULL(char *buf){strcpy(buf, "????");} diff --git a/pcsx2/DebugTools/DisR5900.c b/pcsx2/DebugTools/DisR5900.c new file mode 100644 index 0000000..28ef02c --- /dev/null +++ b/pcsx2/DebugTools/DisR5900.c @@ -0,0 +1,993 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VU.h" + +long jumpMode; +char ostr[1024]; + +// Names of registers +char *disRNameGPR[] = { + "r0", "at", "v0", "v1", "a0", "a1","a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5","t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5","s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp","fp", "ra", "hi", "lo"}; // lo,hi used in rec + +char *disRNameCP0[] = { + "Index" , "Random" , "EntryLo0" , "EntryLo1", "Context" , "PageMask" , "Wired" , "*RES*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID", + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "*RES*" , "*RES*" , "*RES*" , "Debug", + "DEPC" , "PerfCnt" , "ErrCtl" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "DESAVE"}; + +char *disRNameCP1[] = { + "FPR0" , "FPR1" , "FPR2" , "FPR3" , "FPR4" , "FPR5" , "FPR6" , "FPR7", + "FPR8" , "FPR9" , "FPR10", "FPR11", "FPR12", "FPR13", "FPR14", "FPR15", + "FPR16", "FPR17", "FPR18", "FPR19", "FPR20", "FPR21", "FPR22", "FPR23", + "FPR24", "FPR25", "FPR26", "FPR27", "FPR28", "FPR29", "FPR30", "FPR31"}; + +char *disRNameCP1c[] = { + "FRevID", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", + "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "*RES*", "FStatus"}; + +char *disRNameCP2f[] = { + "VF00", "VF01", "VF02", "VF03", "VF04", "VF05", "VF06", "VF07", + "VF08", "VF09", "VF10", "VF11", "VF12", "VF13", "VF14", "VF15", + "VF16", "VF17", "VF18", "VF19", "VF20", "VF21", "VF22", "VF23", + "VF24", "VF25", "VF26", "VF27", "VF28", "VF29", "VF30", "VF31"}; + +char *disRNameCP2i[] = { + "VI00", "VI01", "VI02", "VI03", "VI04", "VI05", "VI06", "VI07", + "VI08", "VI09", "VI10", "VI11", "VI12", "VI13", "VI14", "VI15", + "Status", "MAC", "Clip", "*RES*", "R", "I", "Q", "*RES*", + "*RES*", "*RES*", "TPC", "CMSAR0", "FBRST", "VPU-STAT", "*RES*", "CMSAR1"}; + +char *CP2VFnames[] = { "x", "y", "z", "w" }; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +#undef _Target_ +#undef _Branch_ +#undef _Funct_ +#undef _Rd_ +#undef _Rt_ +#undef _Rs_ +#undef _Sa_ +#undef _Im_ + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + + +#define _rRs_ cpuRegs.GPR.r[_Rs_].UL[1], cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt_ cpuRegs.GPR.r[_Rt_].UL[1], cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd_ cpuRegs.GPR.r[_Rd_].UL[1], cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa_ cpuRegs.GPR.r[_Sa_].UL[1], cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + +#define _rFs_ cpuRegs.CP0.r[_Rd_] // Fs register + +#define _rRs32_ cpuRegs.GPR.r[_Rs_].UL[0] // Rs register +#define _rRt32_ cpuRegs.GPR.r[_Rt_].UL[0] // Rt register +#define _rRd32_ cpuRegs.GPR.r[_Rd_].UL[0] // Rd register +#define _rSa32_ cpuRegs.GPR.r[_Sa_].UL[0] // Sa register + + +#define _nRs_ _rRs_, disRNameGPR[_Rs_] +#define _nRt_ _rRt_, disRNameGPR[_Rt_] +#define _nRd_ _rRd_, disRNameGPR[_Rd_] +#define _nSa_ _rSa_, disRNameGPR[_Sa_] +#define _nRd0_ _rFs_, disRNameCP0[_Rd_] + +#define _nRs32_ _rRs32_, disRNameGPR[_Rs_] +#define _nRt32_ _rRt32_, disRNameGPR[_Rt_] +#define _nRd32_ _rRd32_, disRNameGPR[_Rd_] +#define _nSa32_ _rSa32_, disRNameGPR[_Sa_] + +#define _I_ _Im_, _Im_ +#define _Target_ ((pc & 0xf0000000) + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dGPR128(i) sprintf(ostr, "%s %8.8x_%8.8x_%8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) +#define dGPR64U(i) sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], disRNameGPR[i]) +#define dGPR32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.GPR.r[i].UL[0], disRNameGPR[i]) + +#define dCP032(i) sprintf(ostr, "%s %8.8x (%s),", ostr, cpuRegs.CP0.r[i], disRNameCP0[i]) + +#define dCP132(i) sprintf(ostr, "%s %f (%s),", ostr, fpuRegs.fpr[i].f, disRNameCP1[i]) +#define dCP1c32(i) sprintf(ostr, "%s %8.8x (%s),", ostr, fpuRegs.fprc[i], disRNameCP1c[i]) +#define dCP1acc() sprintf(ostr, "%s %f (ACC),", ostr, fpuRegs.ACC.f) + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) + +#define dHI64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.HI.UL[1], cpuRegs.HI.UL[0], "hi") +#define dLO64() sprintf(ostr, "%s %8.8x_%8.8x (%s),", ostr, cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], "lo") +#define dImm() sprintf(ostr, "%s %4.4x (%d),", ostr, _Im_, _Im_) +#define dTarget() sprintf(ostr, "%s %8.8x,", ostr, _Target_) +#define dSa() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_, _Sa_) +#define dSa32() sprintf(ostr, "%s %2.2x (%d),", ostr, _Sa_+32, _Sa_+32) +#define dOfB() sprintf(ostr, "%s %4.4x (%8.8x (%s)),", ostr, _Im_, cpuRegs.GPR.r[_Rs_].UL[0], disRNameGPR[_Rs_]) +#define dOffset() sprintf(ostr, "%s %8.8x,", ostr, _Branch_) +#define dCode() sprintf(ostr, "%s %8.8x,", ostr, (code >> 6) & 0xffffff) +#define dSaR() sprintf(ostr, "%s %8.8x,", ostr, cpuRegs.sa) + +typedef struct { + u32 addr; + char name[32]; +} sSymbol; + +static sSymbol *dSyms = NULL; +static int nSyms = 0; + +void disR5900AddSym(u32 addr, char *name) { + dSyms = (sSymbol*)realloc(dSyms, sizeof(sSymbol) * (nSyms+1)); + if (dSyms == NULL) return; + dSyms[nSyms].addr = addr; + strncpy(dSyms[nSyms].name, name, 32); + nSyms++; +} + +void disR5900FreeSyms() { + if (dSyms != NULL) { free(dSyms); dSyms = NULL; } + nSyms = 0; +} + +char *disR5900GetSym(u32 addr) { + int i; + + if (dSyms == NULL) return NULL; + for (i=0; i laddr) { + laddr = dSyms[i].addr; + j = i; + } + } + if (j == -1) return NULL; + return dSyms[j].name; +} + +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(ostr, "%s %s", ostr, str); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +MakeDisF(disADDI, dName("ADDI"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disADDIU, dName("ADDIU"); dGPR64(_Rt_); dGPR32(_Rs_); dImm();) +MakeDisF(disANDI, dName("ANDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disORI, dName("ORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTI, dName("SLTI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disSLTIU, dName("SLTIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disXORI, dName("XORI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDI, dName("DADDI"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) +MakeDisF(disDADDIU, dName("DADDIU"); dGPR64(_Rt_); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, dName("ADD"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disADDU, dName("ADDU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDADD, dName("DADD"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDADDU, dName("DADDU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSUB, dName("SUB"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disSUBU, dName("SUBU"); dGPR64(_Rd_); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDSUB, dName("DSUB"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disDSUBU, dName("DSDBU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disAND, dName("AND"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disOR, dName("OR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disXOR, dName("XOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disNOR, dName("NOR"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLT, dName("SLT"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disSLTU, dName("SLTU"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, dName("J"); dTarget(); dFindSym(_Target_);) +MakeDisF(disJAL, dName("JAL"); dTarget(); dGPR32(31); dFindSym(_Target_);) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, dName("JR"); dGPR32(_Rs_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) +MakeDisF(disJALR, dName("JALR"); dGPR32(_Rs_); dGPR32(_Rd_); dFindSym(cpuRegs.GPR.r[_Rs_].UL[0]);) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, dName("DIV"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disDIVU, dName("DIVU"); dGPR32(_Rs_); dGPR32(_Rt_);) +MakeDisF(disMULT, dName("MULT"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) +MakeDisF(disMULTU, dName("MULTU"); dGPR32(_Rs_); dGPR32(_Rt_); dGPR32(_Rd_);) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, dName("LUI"); dGPR64(_Rt_); dImm();) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, dName("MFHI"); dGPR64(_Rd_); dHI64();) +MakeDisF(disMFLO, dName("MFLO"); dGPR64(_Rd_); dLO64();) + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +MakeDisF(disMTHI, dName("MTHI"); dHI64(); dGPR64(_Rs_);) +MakeDisF(disMTLO, dName("MTLO"); dLO64(); dGPR64(_Rs_);) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, if (code) { dName("SLL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa(); } else { dName("NOP"); }) +MakeDisF(disDSLL, dName("DSLL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSLL32, dName("DSLL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRA, dName("SRA"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRA, dName("DSRA"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRA32, dName("DSRA32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) +MakeDisF(disSRL, dName("SRL"); dGPR64(_Rd_); dGPR32(_Rt_); dSa();) +MakeDisF(disDSRL, dName("DSRL"); dGPR64(_Rd_); dGPR64(_Rt_); dSa();) +MakeDisF(disDSRL32, dName("DSRL32"); dGPR64(_Rd_); dGPR64(_Rt_); dSa32();) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, dName("SLLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSLLV, dName("DSLLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRAV, dName("SRAV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRAV, dName("DSRAV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) +MakeDisF(disSRLV, dName("SRLV"); dGPR64(_Rd_); dGPR32(_Rt_); dGPR32(_Rs_);) +MakeDisF(disDSRLV, dName("DSRLV"); dGPR64(_Rd_); dGPR64(_Rt_); dGPR32(_Rs_);) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, dName("LB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLBU, dName("LBU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLH, dName("LH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLHU, dName("LHU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLW, dName("LW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWU, dName("LWU"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWL, dName("LWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLWR, dName("LWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLD, dName("LD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDL, dName("LDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLDR, dName("LDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disLQ, dName("LQ"); dGPR128(_Rt_); dOfB();) +MakeDisF(disSB, dName("SB"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSH, dName("SH"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSW, dName("SW"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWL, dName("SWL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSWR, dName("SWR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSD, dName("SD"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDL, dName("SDL"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSDR, dName("SDR"); dGPR64(_Rt_); dOfB();) +MakeDisF(disSQ, dName("SQ"); dGPR128(_Rt_); dOfB();) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, dName("BEQ"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNE, dName("BNE"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, rd * +*********************************************************/ +MakeDisF(disMFC0, dName("MFC0"); dGPR32(_Rt_); dCP032(_Rd_);) +MakeDisF(disMTC0, dName("MTC0"); dCP032(_Rd_); dGPR32(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +MakeDisF(disBGEZ, dName("BGEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZAL, dName("BGEZAL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZ, dName("BGTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLEZ, dName("BLEZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZ, dName("BLTZ"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZAL, dName("BLTZAL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + + +MakeDisF(disBEQL, dName("BEQL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBNEL, dName("BNEL"); dGPR64(_Rs_); dGPR64(_Rt_); dOffset();) +MakeDisF(disBLEZL, dName("BLEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGTZL, dName("BGTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZL, dName("BLTZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZL, dName("BGEZL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBLTZALL, dName("BLTZALL"); dGPR64(_Rs_); dOffset();) +MakeDisF(disBGEZALL, dName("BGEZALL"); dGPR64(_Rs_); dOffset();) + + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +MakeDisF(disBC0F, dName("BC0F"); dOffset();) +MakeDisF(disBC0T, dName("BC0T"); dOffset();) +MakeDisF(disBC0FL, dName("BC0FL"); dOffset();) +MakeDisF(disBC0TL, dName("BC0TL"); dOffset();) + +MakeDisF(disTLBR, dName("TLBR");) +MakeDisF(disTLBWI, dName("TLBWI");) +MakeDisF(disTLBWR, dName("TLBWR");) +MakeDisF(disTLBP, dName("TLBP");) +MakeDisF(disERET, dName("ERET");) +MakeDisF(disEI, dName("EI");) +MakeDisF(disDI, dName("DI");) + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +MakeDisF(disMFC1, dName("MFC1"); dGPR64(_Rt_); dCP132(_Fs_);) +MakeDisF(disCFC1, dName("CFC1"); dGPR64(_Rt_); dCP1c32(_Fs_);) +MakeDisF(disMTC1, dName("MTC1"); dCP132(_Fs_); dGPR64(_Rt_);) +MakeDisF(disCTC1, dName("CTC1"); dCP1c32(_Fs_); dGPR64(_Rt_);) + +MakeDisF(disBC1F, dName("BC1F");) +MakeDisF(disBC1T, dName("BC1T");) +MakeDisF(disBC1FL, dName("BC1FL");) +MakeDisF(disBC1TL, dName("BC1TL");) + +MakeDisF(disADDs, dName("ADDs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBs, dName("SUBs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULs, dName("MULs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disDIVs, dName("DIVs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSQRTs, dName("SQRTs"); dCP132(_Fd_); dCP132(_Ft_);) +MakeDisF(disABSs, dName("ABSs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMOVs, dName("MOVs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disNEGs, dName("NEGs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disRSQRTs, dName("RSQRTs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disADDAs, dName("ADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disSUBAs, dName("SUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMULAs, dName("MULAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDs, dName("MADDs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBs, dName("MSUBs"); dCP132(_Fd_); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMADDAs, dName("MADDAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMSUBAs, dName("MSUBAs"); dCP1acc(); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCVTWs, dName("CVTWs"); dCP132(_Fd_); dCP132(_Fs_);) +MakeDisF(disMAXs, dName("MAXs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disMINs, dName("MINs"); dCP132(_Fd_); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCFs, dName("CFs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCEQs, dName("CEQs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLTs, dName("CLTs"); dCP132(_Fs_); dCP132(_Ft_);) +MakeDisF(disCLEs, dName("CLEs"); dCP132(_Fs_); dCP132(_Ft_);) + +MakeDisF(disCVTSw, dName("CVTSw"); dCP132(_Fd_); dCP132(_Fs_);) + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +MakeDisF(disLWC1, dName("LWC1"); dCP132(_Rt_); dOffset();) +MakeDisF(disSWC1, dName("SWC1"); dCP132(_Rt_); dOffset();) + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +MakeDisF(disMOVZ, dName("MOVZ"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disMOVN, dName("MOVN"); dGPR64(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ + +MakeDisF(disMULT1, dName("MULT1");) +MakeDisF(disMULTU1, dName("MULTU1");) + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADDW, dName("PADDW");) +MakeDisF(disPADDH, dName("PADDH");) +MakeDisF(disPADDB, dName("PADDB");) + +MakeDisF(disPADDSW, dName("PADDSW");) +MakeDisF(disPADDSH, dName("PADDSH");) +MakeDisF(disPADDSB, dName("PADDSB");) + +MakeDisF(disPSUBW, dName("PSUBW");) +MakeDisF(disPSUBH, dName("PSUBH");) +MakeDisF(disPSUBB, dName("PSUBB");) + +MakeDisF(disPSUBSW, dName("PSUBSW");) +MakeDisF(disPSUBSH, dName("PSUBSH");) +MakeDisF(disPSUBSB, dName("PSUBSB");) + +MakeDisF(disPCGTW, dName("PCGTW");) +MakeDisF(disPCGTH, dName("PCGTH");) +MakeDisF(disPCGTB, dName("PCGTB");) + +MakeDisF(disPMAXW, dName("PMAXW");) +MakeDisF(disPMAXH, dName("PMAXH");) + +MakeDisF(disPEXTLW, dName("PEXTLW"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLH, dName("PEXTLH"); dGPR128(_Rd_); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disPEXTLB, dName("PEXTLB");) +MakeDisF(disPEXTS, dName("PEXTS");) + +MakeDisF(disPPACW, dName("PPACW");) +MakeDisF(disPPACH, dName("PPACH");) +MakeDisF(disPPACB, dName("PPACB");) +MakeDisF(disPPACS, dName("PPACS");) + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ + +MakeDisF(disPADSBH, dName("PADSBH");) + +MakeDisF(disPABSW, dName("PABSW");) +MakeDisF(disPABSH, dName("PABSH");) + +MakeDisF(disPCEQW, dName("PCEQW");) +MakeDisF(disPCEQH, dName("PCEQH");) +MakeDisF(disPCEQB, dName("PCEQB");) + +MakeDisF(disPMINW, dName("PMINW");) +MakeDisF(disPMINH, dName("PMINH");) + +MakeDisF(disPADDUW, dName("PADDUW");) +MakeDisF(disPADDUH, dName("PADDUH");) +MakeDisF(disPADDUB, dName("PADDUB");) + +MakeDisF(disPSUBUW, dName("PSUBUW");) +MakeDisF(disPSUBUH, dName("PSUBUH");) +MakeDisF(disPSUBUB, dName("PSUBUB");) + +MakeDisF(disPEXTUW, dName("PEXTUW"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUH, dName("PEXTUH"); dGPR128(_Rd_); dGPR64U(_Rs_); dGPR64U(_Rt_);) +MakeDisF(disPEXTUB, dName("PEXTUB");) + +MakeDisF(disQFSRV, dName("QFSRV");) + +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDW, dName("PMADDW");) +MakeDisF(disPMADDH, dName("PMADDH");) + +MakeDisF(disPSLLVW, dName("PSLLVW");) +MakeDisF(disPSRLVW, dName("PSRLVW");) + +MakeDisF(disPMFHI, dName("PMFHI");) +MakeDisF(disPMFLO, dName("PMFLO");) + +MakeDisF(disPINTH, dName("PINTH");) + +MakeDisF(disPMULTW, dName("PMULTW");) +MakeDisF(disPMULTH, dName("PMULTH");) + +MakeDisF(disPDIVW, dName("PDIVW");) +MakeDisF(disPDIVH, dName("PDIVH");) + +MakeDisF(disPCPYLD, dName("PCPYLD"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPAND, dName("PAND"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPXOR, dName("PXOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPMSUBW, dName("PMSUBW");) +MakeDisF(disPMSUBH, dName("PMSUBH");) + +MakeDisF(disPHMADH, dName("PHMADH");) +MakeDisF(disPHMSBH, dName("PHMSBH");) + +MakeDisF(disPEXEW, dName("PEXEW");) +MakeDisF(disPEXEH, dName("PEXEH");) + +MakeDisF(disPREVH, dName("PREVH");) + +MakeDisF(disPDIVBW, dName("PDIVBW");) + +MakeDisF(disPROT3W, dName("PROT3W");) + +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ + +MakeDisF(disPMADDUW, dName("PMADDUW");) + +MakeDisF(disPSRAVW, dName("PSRAVW");) + +MakeDisF(disPMTHI, dName("PMTHI");) +MakeDisF(disPMTLO, dName("PMTLO");) + +MakeDisF(disPINTEH, dName("PINTEH");) + +MakeDisF(disPMULTUW, dName("PMULTUW");) +MakeDisF(disPDIVUW, dName("PDIVUW");) + +MakeDisF(disPCPYUD, dName("PCPYUD"); dGPR128(_Rd_); dGPR128(_Rt_); dGPR128(_Rs_);) + +MakeDisF(disPOR, dName("POR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) +MakeDisF(disPNOR, dName("PNOR"); dGPR128(_Rd_); dGPR128(_Rs_); dGPR128(_Rt_);) + +MakeDisF(disPEXCH, dName("PEXCH");) +MakeDisF(disPEXCW, dName("PEXCW");) + +MakeDisF(disPCPYH, dName("PCPYH"); dGPR128(_Rd_); dGPR128(_Rt_);) + +/********************************************************* +* COP2 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X code>>24 +#define _Y code>>23 +#define _Z code>>22 +#define _W code>>21 + +MakeDisF(disLQC2, dName("LQC2"); dCP2128f(_Rt_); dOfB();) +MakeDisF(disSQC2, dName("SQC2"); dCP2128f(_Rt_); dOfB();) + +MakeDisF(disQMFC2, dName("QMFC2");) +MakeDisF(disQMTC2, dName("QMTC2");) +MakeDisF(disCFC2, dName("CFC2"); dGPR32(_Rt_); dCP232i(_Fs_);) +MakeDisF(disCTC2, dName("CTC2"); dCP232i(_Fs_); dGPR32(_Rt_);) + +MakeDisF(disBC2F, dName("BC2F");) +MakeDisF(disBC2T, dName("BC2T");) +MakeDisF(disBC2FL, dName("BC2FL");) +MakeDisF(disBC2TL, dName("BC2TL");) + +// SPEC1 +MakeDisF(disVADD, dName("VADD");) +MakeDisF(disVADDx, dName("VADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDy, dName("VADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDz, dName("VADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDw, dName("VADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVADDq, dName("VADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) +MakeDisF(disVADDi, dName("VADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) +MakeDisF(disVSUB, dName("VSUB");) +MakeDisF(disVSUBx, dName("VSUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBy, dName("VSUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBz, dName("VSUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBw, dName("VSUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) +MakeDisF(disVSUBq, dName("VSUBq");) +MakeDisF(disVSUBi, dName("VSUBi");) +MakeDisF(disVMADD, dName("VMADD");) +MakeDisF(disVMADDx, dName("VMADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDy, dName("VMADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDz, dName("VMADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDw, dName("VMADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDq, dName("VMADDq");) +MakeDisF(disVMADDi, dName("VMADDi");) +MakeDisF(disVMSUB, dName("VMSUB");) +MakeDisF(disVMSUBx, dName("VMSUBx");) +MakeDisF(disVMSUBy, dName("VMSUBy");) +MakeDisF(disVMSUBz, dName("VMSUBz");) +MakeDisF(disVMSUBw, dName("VMSUBw");) +MakeDisF(disVMSUBq, dName("VMSUBq");) +MakeDisF(disVMSUBi, dName("VMSUBi");) +MakeDisF(disVMAX, dName("VMAX");) +MakeDisF(disVMAXx, dName("VMAXx");) +MakeDisF(disVMAXy, dName("VMAXy");) +MakeDisF(disVMAXz, dName("VMAXz");) +MakeDisF(disVMAXw, dName("VMAXw");) +MakeDisF(disVMAXi, dName("VMAXi");) +MakeDisF(disVMINI, dName("VMINI");) +MakeDisF(disVMINIx, dName("VMINIx");) +MakeDisF(disVMINIy, dName("VMINIy");) +MakeDisF(disVMINIz, dName("VMINIz");) +MakeDisF(disVMINIw, dName("VMINIw");) +MakeDisF(disVMINIi, dName("VMINIi");) +MakeDisF(disVMUL, dName("VMUL");) +MakeDisF(disVMULx, dName("VMULx");) +MakeDisF(disVMULy, dName("VMULy");) +MakeDisF(disVMULz, dName("VMULz");) +MakeDisF(disVMULw, dName("VMULw");) +MakeDisF(disVMULq, dName("VMULq");) +MakeDisF(disVMULi, dName("VMULi");) +MakeDisF(disVIADD, dName("VIADD");) +MakeDisF(disVIADDI, dName("VIADDI");) +MakeDisF(disVISUB, dName("VISUB");) +MakeDisF(disVIAND, dName("VIAND");) +MakeDisF(disVIOR, dName("VIOR");) +MakeDisF(disVOPMSUB, dName("VOPMSUB");) +MakeDisF(disVCALLMS, dName("VCALLMS");) +MakeDisF(disVCALLMSR, dName("VCALLMSR");) + +// SPEC2 +MakeDisF(disVADDA, dName("VADDA");) +MakeDisF(disVADDAx, dName("VADDAx");) +MakeDisF(disVADDAy, dName("VADDAy");) +MakeDisF(disVADDAz, dName("VADDAz");) +MakeDisF(disVADDAw, dName("VADDAw");) +MakeDisF(disVADDAq, dName("VADDAq");) +MakeDisF(disVADDAi, dName("VADDAi");) +MakeDisF(disVMADDA, dName("VMADDA");) +MakeDisF(disVMADDAx, dName("VMADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMADDAy, dName("VMADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) +MakeDisF(disVMADDAz, dName("VMADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) +MakeDisF(disVMADDAw, dName("VMADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) +MakeDisF(disVMADDAq, dName("VMADDAq");) +MakeDisF(disVMADDAi, dName("VMADDAi");) +MakeDisF(disVSUBAx, dName("VSUBAx");) +MakeDisF(disVSUBAy, dName("VSUBAy");) +MakeDisF(disVSUBAz, dName("VSUBAz");) +MakeDisF(disVSUBAw, dName("VSUBAw");) +MakeDisF(disVMSUBAx, dName("VMSUBAx");) +MakeDisF(disVMSUBAy, dName("VMSUBAy");) +MakeDisF(disVMSUBAz, dName("VMSUBAz");) +MakeDisF(disVMSUBAw, dName("VMSUBAw");) +MakeDisF(disVITOF0, dName("VITOF0");) +MakeDisF(disVITOF4, dName("VITOF4");) +MakeDisF(disVITOF12, dName("VITOF12");) +MakeDisF(disVITOF15, dName("VITOF15");) +MakeDisF(disVFTOI0, dName("VFTOI0");) +MakeDisF(disVFTOI4, dName("VFTOI4");) +MakeDisF(disVFTOI12, dName("VFTOI12");) +MakeDisF(disVFTOI15, dName("VFTOI15");) +MakeDisF(disVMULA, dName("VMULA");) +MakeDisF(disVMULAx, dName("VMULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) +MakeDisF(disVMULAy, dName("VMULAy");) +MakeDisF(disVMULAz, dName("VMULAz");) +MakeDisF(disVMULAw, dName("VMULAw");) +MakeDisF(disVMOVE, dName("VMOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_);) +MakeDisF(disVMR32, dName("VMR32");) +MakeDisF(disVDIV, dName("VDIV");) +MakeDisF(disVSQRT, dName("VSQRT"); dCP232f(_Ft_, _Ftf_);) +MakeDisF(disVRSQRT, dName("VRSQRT");) +MakeDisF(disVRNEXT, dName("VRNEXT");) +MakeDisF(disVRGET, dName("VRGET");) +MakeDisF(disVRINIT, dName("VRINIT");) +MakeDisF(disVRXOR, dName("VRXOR");) +MakeDisF(disVWAITQ, dName("VWAITQ");) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +MakeDisF(disSYNC, dName("SYNC");) +MakeDisF(disBREAK, dName("BREAK");) +MakeDisF(disSYSCALL, dName("SYSCALL"); dCode();) +MakeDisF(disCACHE, sprintf(ostr, "%s %-7s, %x,", ostr, "CACHE", _Rt_); dOfB();) +MakeDisF(disPREF, dName("PREF");) + +MakeDisF(disMFSA, dName("MFSA"); dGPR64(_Rd_); dSaR();) +MakeDisF(disMTSA, dName("MTSA"); dGPR64(_Rs_); dSaR();) + +MakeDisF(disMTSAB, dName("MTSAB");dGPR64(_Rs_); dImm();) +MakeDisF(disMTSAH, dName("MTSAH");dGPR64(_Rs_); dImm();) + +MakeDisF(disTGE, dName("TGE"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTGEU, dName("TGEU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLT, dName("TLT"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTLTU, dName("TLTU"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTEQ, dName("TEQ"); dGPR64(_Rs_); dGPR64(_Rt_);) +MakeDisF(disTNE, dName("TNE"); dGPR64(_Rs_); dGPR64(_Rt_);) + +MakeDisF(disTGEI, dName("TGEI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTGEIU, dName("TGEIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTI, dName("TLTI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTLTIU, dName("TLTIU"); dGPR64(_Rs_); dImm();) +MakeDisF(disTEQI, dName("TEQI"); dGPR64(_Rs_); dImm();) +MakeDisF(disTNEI, dName("TNEI"); dGPR64(_Rs_); dImm();) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, dName("*** Bad OP ***");) + +TdisR5900F disR5900_MMI0[] = { // Subset of disMMI0 + disPADDW, disPSUBW, disPCGTW, disPMAXW, + disPADDH, disPSUBH, disPCGTH, disPMAXH, + disPADDB, disPSUBB, disPCGTB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDSW, disPSUBSW, disPEXTLW, disPPACW, + disPADDSH, disPSUBSH, disPEXTLH, disPPACH, + disPADDSB, disPSUBSB, disPEXTLB, disPPACB, + disNULL, disNULL, disPEXTS, disPPACS}; + +MakeDisF(disMMI0, disR5900_MMI0[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI1[] = { // Subset of disMMI1 + disNULL, disPABSW, disPCEQW, disPMINW, + disPADSBH, disPABSH, disPCEQH, disPMINH, + disNULL, disNULL, disPCEQB, disNULL, + disNULL, disNULL, disNULL, disNULL, + disPADDUW, disPSUBUW, disPEXTUW, disNULL, + disPADDUH, disPSUBUH, disPEXTUH, disNULL, + disPADDUB, disPSUBUB, disPEXTUB, disQFSRV, + disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI1, disR5900_MMI1[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI2[] = { // Subset of disMMI2 + disPMADDW, disNULL, disPSLLVW, disPSRLVW, + disPMSUBW, disNULL, disNULL, disNULL, + disPMFHI, disPMFLO, disPINTH, disNULL, + disPMULTW, disPDIVW, disPCPYLD, disNULL, + disPMADDH, disPHMADH, disPAND, disPXOR, + disPMSUBH, disPHMSBH, disNULL, disNULL, + disNULL, disNULL, disPEXEH, disPREVH, + disPMULTH, disPDIVBW, disPEXEW, disPROT3W}; + +MakeDisF(disMMI2, disR5900_MMI2[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI3[] = { // Subset of disMMI3 + disPMADDUW, disNULL, disNULL, disPSRAVW, + disNULL, disNULL, disNULL, disNULL, + disPMTHI, disPMTLO, disPINTEH, disNULL, + disPMULTUW, disPDIVUW, disPCPYUD, disNULL, + disNULL, disNULL, disPOR, disPNOR, + disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disPEXCH, disPCPYH, + disNULL, disNULL, disPEXCW, disNULL}; + +MakeDisF(disMMI3, disR5900_MMI3[_Sa_] DisFInterfaceN) + +TdisR5900F disR5900_MMI[] = { // Subset of disMMI + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI0, disMMI2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMULT1, disMULTU1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disMMI1, disMMI3, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disMMI, disR5900_MMI[_Funct_] DisFInterfaceN) + + +TdisR5900F disR5900_COP0_BC0[] = { //subset of disCOP0 BC + disBC0F, disBC0T, disBC0FL, disBC0TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP0_BC0, disR5900_COP0_BC0[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP0_Func[] = { //subset of disCOP0 Function + disNULL, disTLBR, disTLBWI, disNULL, disNULL, disNULL, disTLBWR, disNULL, + disTLBP, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disERET, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disNULL, disNULL, disNULL , disNULL, disNULL, disNULL, disNULL , disNULL, + disEI , disDI , disNULL , disNULL, disNULL, disNULL, disNULL , disNULL +}; +MakeDisF(disCOP0_Func, disR5900_COP0_Func[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disNULL, disNULL, disMTC0, disNULL, disNULL, disNULL, + disCOP0_BC0, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP0_Func, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP0, disR5900_COP0[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_S[] = { //subset of disCOP1 S + disADDs, disSUBs, disMULs, disDIVs, disSQRTs, disABSs, disMOVs, disNEGs, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disRSQRTs, disNULL, + disADDAs, disSUBAs, disMULAs, disNULL, disMADDs, disMSUBs, disMADDAs, disMSUBAs, + disNULL, disNULL, disNULL, disNULL, disCVTWs, disNULL, disNULL, disNULL, + disMINs, disMAXs, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCFs, disNULL, disCEQs, disNULL, disCLTs, disNULL, disCLEs, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_S, disR5900_COP1_S[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_W[] = { //subset of disCOP1 W + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCVTSw, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_W, disR5900_COP1_W[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP1_BC1[] = { //subset of disCOP1 BC + disBC1F, disBC1T, disBC1FL, disBC1TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP1_BC1, disR5900_COP1_BC1[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP1[] = { // Subset of disCOP1 + disMFC1, disNULL, disCFC1, disNULL, disMTC1, disNULL, disCTC1, disNULL, + disCOP1_BC1, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP1_S, disNULL, disNULL, disNULL, disCOP1_W, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disCOP1, disR5900_COP1[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC2[] = { //subset of disCOP2 SPEC2 + disVADDAx, disVADDAy, disVADDAz, disVADDAw, disVSUBAx, disVSUBAy, disVSUBAz, disVSUBAw, + disVMADDAx, disVMADDAy, disVMADDAz, disVMADDAw, disVMSUBAx, disVMSUBAy, disVMSUBAz, disVMSUBAw, + disVITOF0, disVITOF4, disVITOF12, disVITOF15, disVFTOI0, disVFTOI4, disVFTOI12, disVFTOI15, + disVMULAx, disVMULAy, disVMULAz, disVMULAw, disNULL, disNULL, disNULL, disNULL, + disVADDAq, disVMADDAq, disVADDAi, disVMADDAi, disNULL, disNULL, disNULL, disNULL, + disVADDA, disVMADDA, disVMULA, disNULL, disNULL, disNULL, disNULL, disNULL, + disVMOVE, disVMR32, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disVDIV, disVSQRT, disVRSQRT, disVWAITQ, disNULL, disNULL, disNULL, disNULL, + disVRNEXT, disVRGET, disVRINIT, disVRXOR, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_SPEC2, disR5900_COP2_SPEC2[(code & 0x3) | ((code >> 4) & 0x7c)] DisFInterfaceN) + +TdisR5900F disR5900_COP2_SPEC1[] = { //subset of disCOP2 SPEC1 + disVADDx, disVADDy, disVADDz, disVADDw, disVSUBx, disVSUBy, disVSUBz, disVSUBw, + disVMADDx, disVMADDy, disVMADDz, disVMADDw, disVMSUBx, disVMSUBy, disVMSUBz, disVMSUBw, + disVMAXx, disVMAXy, disVMAXz, disVMAXw, disVMINIx, disVMINIy, disVMINIz, disVMINIw, + disVMULx, disVMULy, disVMULz, disVMULw, disVMULq, disVMAXi, disVMULi, disVMINIi, + disVADDq, disVMADDq, disVADDi, disVMADDi, disVSUBq, disVMSUBq, disVSUBi, disVMSUBi, + disVADD, disVMADD, disVMUL, disVMAX, disVSUB, disVMSUB, disVOPMSUB, disVMINI, + disVIADD, disVISUB, disVIADDI, disNULL, disVIAND, disVIOR, disNULL, disNULL, + disVCALLMS, disVCALLMSR, disNULL, disNULL, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, disCOP2_SPEC2, +}; + +MakeDisF(disCOP2_SPEC1, disR5900_COP2_SPEC1[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900_COP2_BC2[] = { //subset of disCOP2 BC + disBC2F, disBC2T, disBC2FL, disBC2TL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, +}; + +MakeDisF(disCOP2_BC2, disR5900_COP2_BC2[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_COP2[] = { // Subset of disCOP2 + disNULL, disQMFC2, disCFC2, disNULL, disNULL, disQMTC2, disCTC2, disNULL, + disCOP2_BC2, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, + disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1, disCOP2_SPEC1}; + +MakeDisF(disCOP2, disR5900_COP2[_Rs_] DisFInterfaceN) + +TdisR5900F disR5900_REGIMM[] = { // Subset of disREGIMM + disBLTZ, disBGEZ, disBLTZL, disBGEZL, disNULL, disNULL, disNULL, disNULL, + disTGEI, disTGEIU, disTLTI, disTLTIU, disTEQI, disNULL, disTNEI, disNULL, + disBLTZAL, disBGEZAL, disBLTZALL, disBGEZALL, disNULL, disNULL, disNULL, disNULL, + disMTSAB, disMTSAH , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL}; + +MakeDisF(disREGIMM, disR5900_REGIMM[_Rt_] DisFInterfaceN) + +TdisR5900F disR5900_SPECIAL[] = { + disSLL, disNULL, disSRL, disSRA, disSLLV, disNULL, disSRLV, disSRAV, + disJR, disJALR, disMOVZ, disMOVN, disSYSCALL, disBREAK,disNULL, disSYNC, + disMFHI, disMTHI, disMFLO, disMTLO, disDSLLV, disNULL, disDSRLV, disDSRAV, + disMULT, disMULTU,disDIV, disDIVU, disNULL, disNULL, disNULL, disNULL, + disADD, disADDU, disSUB, disSUBU, disAND, disOR, disXOR, disNOR, + disMFSA , disMTSA, disSLT, disSLTU, disDADD, disDADDU,disDSUB, disDSUBU, + disTGE, disTGEU, disTLT, disTLTU, disTEQ, disNULL, disTNE, disNULL, + disDSLL, disNULL, disDSRL, disDSRA, disDSLL32, disNULL, disDSRL32,disDSRA32 }; + +MakeDisF(disSPECIAL, disR5900_SPECIAL[_Funct_] DisFInterfaceN) + +TdisR5900F disR5900[] = { + disSPECIAL, disREGIMM, disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI, disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disCOP1 , disCOP2, disNULL , disBEQL, disBNEL, disBLEZL, disBGTZL, + disDADDI , disDADDIU, disLDL , disLDR , disMMI , disNULL, disLQ , disSQ , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disLWU , + disSB , disSH , disSWL , disSW , disSDL , disSDR , disSWR , disCACHE, + disNULL , disLWC1 , disNULL, disPREF , disNULL, disNULL, disLQC2 , disLD , + disNULL , disSWC1 , disNULL, disNULL , disNULL, disNULL, disSQC2 , disSD }; + +MakeDisF(disR5900F, disR5900[code >> 26] DisFInterfaceN) + diff --git a/pcsx2/DebugTools/DisR5900asm.c b/pcsx2/DebugTools/DisR5900asm.c new file mode 100644 index 0000000..e3261d4 --- /dev/null +++ b/pcsx2/DebugTools/DisR5900asm.c @@ -0,0 +1,1679 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PS2Etypes.h" +#include "Debug.h" +#include "R5900.h" +#include "DisASM.h" + +unsigned long opcode_addr; + +/* +//DECODE PROCUDURES + +//cop0 +#define DECODE_FS (DECODE_RD) +#define DECODE_FT (DECODE_RT) +#define DECODE_FD (DECODE_SA) +/// ******** + +#define DECODE_FUNCTION ((cpuRegs.code) & 0x3F) +#define DECODE_RD ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define DECODE_RT ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define DECODE_RS ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define DECODE_SA ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define DECODE_IMMED ( cpuRegs.code & 0xFFFF) // The immediate part of the instruction register +#define DECODE_OFFSET ((((short)DECODE_IMMED * 4) + opcode_addr + 4)) +#define DECODE_JUMP (opcode_addr & 0xf0000000)|((cpuRegs.code&0x3ffffff)<<2) +#define DECODE_SYSCALL ((opcode_addr & 0x03FFFFFF) >> 6) +#define DECODE_BREAK (DECODE_SYSCALL) +#define DECODE_C0BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C1BC ((cpuRegs.code >> 16) & 0x03) +#define DECODE_C2BC ((cpuRegs.code >> 16) & 0x03) +*/ +/*************************CPUS REGISTERS**************************/ +char *GPR_REG[32] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" +}; +char *COP0_REG[32] ={ + "Index","Random","EntryLo0","EntryLo1","Context","PageMask", + "Wired","C0r7","BadVaddr","Count","EntryHi","Compare","Status", + "Cause","EPC","PRId","Config","C0r17","C0r18","C0r19","C0r20", + "C0r21","C0r22","C0r23","Debug","Perf","C0r26","C0r27","TagLo", + "TagHi","ErrorPC","C0r31" +}; +//floating point cop1 Floating point reg +char *COP1_REG_FP[32] ={ + "f00","f01","f02","f03","f04","f05","f06","f07", + "f08","f09","f10","f11","f12","f13","f14","f15", + "f16","f17","f18","f19","f20","f21","f21","f23", + "f24","f25","f26","f27","f28","f29","f30","f31" +}; +//floating point cop1 control registers +char *COP1_REG_FCR[32] ={ + "fcr00","fcr01","fcr02","fcr03","fcr04","fcr05","fcr06","fcr07", + "fcr08","fcr09","fcr10","fcr11","fcr12","fcr13","fcr14","fcr15", + "fcr16","fcr17","fcr18","fcr19","fcr20","fcr21","fcr21","fcr23", + "fcr24","fcr25","fcr26","fcr27","fcr28","fcr29","fcr30","fcr31" +}; + +//floating point cop2 reg +char *COP2_REG_FP[32] ={ + "vf00","vf01","vf02","vf03","vf04","vf05","vf06","vf07", + "vf08","vf09","vf10","vf11","vf12","vf13","vf14","vf15", + "vf16","vf17","vf18","vf19","vf20","vf21","vf21","vf23", + "vf24","vf25","vf26","vf27","vf28","vf29","vf30","vf31" +}; +//cop2 control registers + +char *COP2_REG_CTL[32] ={ + "vi00","vi01","vi02","vi03","vi04","vi05","vi06","vi07", + "vi08","vi09","vi10","vi11","vi12","vi13","vi14","vi15", + "Status","MACflag","ClipFlag","c2c19","R","I","Q","c2c23", + "c2c24","c2c25","TPC","CMSAR0","FBRST","VPU-STAT","c2c30","CMSAR1" +}; + + + + + +//**************************************************************** +void P_SpecialOpcode(char *buf); +void P_REGIMMOpcode(char *buf); +void P_UnknownOpcode(char *buf); +void P_COP0(char *buf); +void P_COP1(char *buf); +void P_COP2(char *buf); +void P_MMI_Unknown(char *buf); +void P_MMI(char *buf); +void P_MMI0(char *buf); +void P_MMI1(char *buf); +void P_MMI2(char *buf); +void P_MMI3(char *buf); +void P_COP0_Unknown(char *buf); +void P_COP0_BC0(char *buf); +void P_COP0_Func(char *buf); +void P_COP1_BC1(char *buf); +void P_COP1_S(char *buf); +void P_COP1_W(char *buf); +void P_COP1_Unknown(char *buf); +void P_COP2_BC2(char *buf); +void P_COP2_SPECIAL(char *buf); +void P_COP2_Unknown(char *buf); +void P_COP2_SPECIAL2(char *buf); + +// **********************Standard Opcodes************************** +void P_J(char *buf); +void P_JAL(char *buf); +void P_BEQ(char *buf); +void P_BNE(char *buf); +void P_BLEZ(char *buf); +void P_BGTZ(char *buf); +void P_ADDI(char *buf); +void P_ADDIU(char *buf); +void P_SLTI(char *buf); +void P_SLTIU(char *buf); +void P_ANDI(char *buf); +void P_ORI(char *buf); +void P_XORI(char *buf); +void P_LUI(char *buf); +void P_BEQL(char *buf); +void P_BNEL(char *buf); +void P_BLEZL(char *buf); +void P_BGTZL(char *buf); +void P_DADDI(char *buf); +void P_DADDIU(char *buf); +void P_LDL(char *buf); +void P_LDR(char *buf); +void P_LB(char *buf); +void P_LH(char *buf); +void P_LWL(char *buf); +void P_LW(char *buf); +void P_LBU(char *buf); +void P_LHU(char *buf); +void P_LWR(char *buf); +void P_LWU(char *buf); +void P_SB(char *buf); +void P_SH(char *buf); +void P_SWL(char *buf); +void P_SW(char *buf); +void P_SDL(char *buf); +void P_SDR(char *buf); +void P_SWR(char *buf); +void P_CACHE(char *buf); +void P_LWC1(char *buf); +void P_PREF(char *buf); +void P_LQC2(char *buf); +void P_LD(char *buf); +void P_SQC2(char *buf); +void P_SD(char *buf); +void P_LQ(char *buf); +void P_SQ(char *buf); +void P_SWC1(char *buf); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void P_SLL(char *buf); +void P_SRL(char *buf); +void P_SRA(char *buf); +void P_SLLV(char *buf); +void P_SRLV(char *buf); +void P_SRAV(char *buf); +void P_JR(char *buf); +void P_JALR(char *buf); +void P_SYSCALL(char *buf); +void P_BREAK(char *buf); +void P_SYNC(char *buf); +void P_MFHI(char *buf); +void P_MTHI(char *buf); +void P_MFLO(char *buf); +void P_MTLO(char *buf); +void P_DSLLV(char *buf); +void P_DSRLV(char *buf); +void P_DSRAV(char *buf); +void P_MULT(char *buf); +void P_MULTU(char *buf); +void P_DIV(char *buf); +void P_DIVU(char *buf); +void P_ADD(char *buf); +void P_ADDU(char *buf); +void P_SUB(char *buf); +void P_SUBU(char *buf); +void P_AND(char *buf); +void P_OR(char *buf); +void P_XOR(char *buf); +void P_NOR(char *buf); +void P_SLT(char *buf); +void P_SLTU(char *buf); +void P_DADD(char *buf); +void P_DADDU(char *buf); +void P_DSUB(char *buf); +void P_DSUBU(char *buf); +void P_TGE(char *buf); +void P_TGEU(char *buf); +void P_TLT(char *buf); +void P_TLTU(char *buf); +void P_TEQ(char *buf); +void P_TNE(char *buf); +void P_DSLL(char *buf); +void P_DSRL(char *buf); +void P_DSRA(char *buf); +void P_DSLL32(char *buf); +void P_DSRL32(char *buf); +void P_DSRA32(char *buf); +void P_MOVZ(char *buf); +void P_MOVN(char *buf); +void P_MFSA(char *buf); +void P_MTSA(char *buf); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void P_BLTZ(char *buf); +void P_BGEZ(char *buf); +void P_BLTZL(char *buf); +void P_BGEZL(char *buf); +void P_TGEI(char *buf); +void P_TGEIU(char *buf); +void P_TLTI(char *buf); +void P_TLTIU(char *buf); +void P_TEQI(char *buf); +void P_TNEI(char *buf); +void P_BLTZAL(char *buf); +void P_BGEZAL(char *buf); +void P_BLTZALL(char *buf); +void P_BGEZALL(char *buf); +void P_MTSAB(char *buf); +void P_MTSAH(char *buf); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void P_MADD(char *buf); +void P_MADDU(char *buf); +void P_PLZCW(char *buf); +void P_MADD1(char *buf); +void P_MADDU1(char *buf); +void P_MFHI1(char *buf); +void P_MTHI1(char *buf); +void P_MFLO1(char *buf); +void P_MTLO1(char *buf); +void P_MULT1(char *buf); +void P_MULTU1(char *buf); +void P_DIV1(char *buf); +void P_DIVU1(char *buf); +void P_PMFHL(char *buf); +void P_PMTHL(char *buf); +void P_PSLLH(char *buf); +void P_PSRLH(char *buf); +void P_PSRAH(char *buf); +void P_PSLLW(char *buf); +void P_PSRLW(char *buf); +void P_PSRAW(char *buf); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf); +void P_PSUBW(char *buf); +void P_PCGTW(char *buf); +void P_PMAXW(char *buf); +void P_PADDH(char *buf); +void P_PSUBH(char *buf); +void P_PCGTH(char *buf); +void P_PMAXH(char *buf); +void P_PADDB(char *buf); +void P_PSUBB(char *buf); +void P_PCGTB(char *buf); +void P_PADDSW(char *buf); +void P_PSUBSW(char *buf); +void P_PEXTLW(char *buf); +void P_PPACW(char *buf); +void P_PADDSH(char *buf); +void P_PSUBSH(char *buf); +void P_PEXTLH(char *buf); +void P_PPACH(char *buf); +void P_PADDSB(char *buf); +void P_PSUBSB(char *buf); +void P_PEXTLB(char *buf); +void P_PPACB(char *buf); +void P_PEXT5(char *buf); +void P_PPAC5(char *buf); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf); +void P_PCEQW(char *buf); +void P_PMINW(char *buf); +void P_PADSBH(char *buf); +void P_PABSH(char *buf); +void P_PCEQH(char *buf); +void P_PMINH(char *buf); +void P_PCEQB(char *buf); +void P_PADDUW(char *buf); +void P_PSUBUW(char *buf); +void P_PEXTUW(char *buf); +void P_PADDUH(char *buf); +void P_PSUBUH(char *buf); +void P_PEXTUH(char *buf); +void P_PADDUB(char *buf); +void P_PSUBUB(char *buf); +void P_PEXTUB(char *buf); +void P_QFSRV(char *buf); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf); +void P_PSLLVW(char *buf); +void P_PSRLVW(char *buf); +void P_PMSUBW(char *buf); +void P_PMFHI(char *buf); +void P_PMFLO(char *buf); +void P_PINTH(char *buf); +void P_PMULTW(char *buf); +void P_PDIVW(char *buf); +void P_PCPYLD(char *buf); +void P_PMADDH(char *buf); +void P_PHMADH(char *buf); +void P_PAND(char *buf); +void P_PXOR(char *buf); +void P_PMSUBH(char *buf); +void P_PHMSBH(char *buf); +void P_PEXEH(char *buf); +void P_PREVH(char *buf); +void P_PMULTH(char *buf); +void P_PDIVBW(char *buf); +void P_PEXEW(char *buf); +void P_PROT3W(char *buf); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf); +void P_PSRAVW(char *buf); +void P_PMTHI(char *buf); +void P_PMTLO(char *buf); +void P_PINTEH(char *buf); +void P_PMULTUW(char *buf); +void P_PDIVUW(char *buf); +void P_PCPYUD(char *buf); +void P_POR(char *buf); +void P_PNOR(char *buf); +void P_PEXCH(char *buf); +void P_PCPYH(char *buf); +void P_PEXCW(char *buf); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf); +void P_MTC0(char *buf); +void P_BC0F(char *buf); +void P_BC0T(char *buf); +void P_BC0FL(char *buf); +void P_BC0TL(char *buf); +void P_TLBR(char *buf); +void P_TLBWI(char *buf); +void P_TLBWR(char *buf); +void P_TLBP(char *buf); +void P_ERET(char *buf); +void P_DI(char *buf); +void P_EI(char *buf); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf); +void P_CFC1(char *buf); +void P_MTC1(char *buf); +void P_CTC1(char *buf); +void P_BC1F(char *buf); +void P_BC1T(char *buf); +void P_BC1FL(char *buf); +void P_BC1TL(char *buf); +void P_ADD_S(char *buf); +void P_SUB_S(char *buf); +void P_MUL_S(char *buf); +void P_DIV_S(char *buf); +void P_SQRT_S(char *buf); +void P_ABS_S(char *buf); +void P_MOV_S(char *buf); +void P_NEG_S(char *buf); +void P_RSQRT_S(char *buf); +void P_ADDA_S(char *buf); +void P_SUBA_S(char *buf); +void P_MULA_S(char *buf); +void P_MADD_S(char *buf); +void P_MSUB_S(char *buf); +void P_MADDA_S(char *buf); +void P_MSUBA_S(char *buf); +void P_CVT_W(char *buf); +void P_MAX_S(char *buf); +void P_MIN_S(char *buf); +void P_C_F(char *buf); +void P_C_EQ(char *buf); +void P_C_LT(char *buf); +void P_C_LE(char *buf); + void P_CVT_S(char *buf); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf); +void P_CFC2(char *buf); +void P_QMTC2(char *buf); +void P_CTC2(char *buf); +void P_BC2F(char *buf); +void P_BC2T(char *buf); +void P_BC2FL(char *buf); +void P_BC2TL(char *buf); +//*****************SPECIAL 1 VUO TABLE******************************* +void P_VADDx(char *buf); +void P_VADDy(char *buf); +void P_VADDz(char *buf); +void P_VADDw(char *buf); +void P_VSUBx(char *buf); +void P_VSUBy(char *buf); +void P_VSUBz(char *buf); +void P_VSUBw(char *buf); +void P_VMADDx(char *buf); +void P_VMADDy(char *buf); +void P_VMADDz(char *buf); +void P_VMADDw(char *buf); +void P_VMSUBx(char *buf); +void P_VMSUBy(char *buf); +void P_VMSUBz(char *buf); +void P_VMSUBw(char *buf); +void P_VMAXx(char *buf); +void P_VMAXy(char *buf); +void P_VMAXz(char *buf); +void P_VMAXw(char *buf); +void P_VMINIx(char *buf); +void P_VMINIy(char *buf); +void P_VMINIz(char *buf); +void P_VMINIw(char *buf); +void P_VMULx(char *buf); +void P_VMULy(char *buf); +void P_VMULz(char *buf); +void P_VMULw(char *buf); +void P_VMULq(char *buf); +void P_VMAXi(char *buf); +void P_VMULi(char *buf); +void P_VMINIi(char *buf); +void P_VADDq(char *buf); +void P_VMADDq(char *buf); +void P_VADDi(char *buf); +void P_VMADDi(char *buf); +void P_VSUBq(char *buf); +void P_VMSUBq(char *buf); +void P_VSUbi(char *buf); +void P_VMSUBi(char *buf); +void P_VADD(char *buf); +void P_VMADD(char *buf); +void P_VMUL(char *buf); +void P_VMAX(char *buf); +void P_VSUB(char *buf); +void P_VMSUB(char *buf); +void P_VOPMSUB(char *buf); +void P_VMINI(char *buf); +void P_VIADD(char *buf); +void P_VISUB(char *buf); +void P_VIADDI(char *buf); +void P_VIAND(char *buf); +void P_VIOR(char *buf); +void P_VCALLMS(char *buf); +void P_CALLMSR(char *buf); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf); +void P_VADDAy(char *buf); +void P_VADDAz(char *buf); +void P_VADDAw(char *buf); +void P_VSUBAx(char *buf); +void P_VSUBAy(char *buf); +void P_VSUBAz(char *buf); +void P_VSUBAw(char *buf); +void P_VMADDAx(char *buf); +void P_VMADDAy(char *buf); +void P_VMADDAz(char *buf); +void P_VMADDAw(char *buf); +void P_VMSUBAx(char *buf); +void P_VMSUBAy(char *buf); +void P_VMSUBAz(char *buf); +void P_VMSUBAw(char *buf); +void P_VITOF0(char *buf); +void P_VITOF4(char *buf); +void P_VITOF12(char *buf); +void P_VITOF15(char *buf); +void P_VFTOI0(char *buf); +void P_VFTOI4(char *buf); +void P_VFTOI12(char *buf); +void P_VFTOI15(char *buf); +void P_VMULAx(char *buf); +void P_VMULAy(char *buf); +void P_VMULAz(char *buf); +void P_VMULAw(char *buf); +void P_VMULAq(char *buf); +void P_VABS(char *buf); +void P_VMULAi(char *buf); +void P_VCLIPw(char *buf); +void P_VADDAq(char *buf); +void P_VMADDAq(char *buf); +void P_VADDAi(char *buf); +void P_VMADDAi(char *buf); +void P_VSUBAq(char *buf); +void P_VMSUBAq(char *buf); +void P_VSUBAi(char *buf); +void P_VMSUBAi(char *buf); +void P_VADDA(char *buf); +void P_VMADDA(char *buf); +void P_VMULA(char *buf); +void P_VSUBA(char *buf); +void P_VMSUBA(char *buf); +void P_VOPMULA(char *buf); +void P_VNOP(char *buf); +void P_VMONE(char *buf); +void P_VMR32(char *buf); +void P_VLQI(char *buf); +void P_VSQI(char *buf); +void P_VLQD(char *buf); +void P_VSQD(char *buf); +void P_VDIV(char *buf); +void P_VSQRT(char *buf); +void P_VRSQRT(char *buf); +void P_VWAITQ(char *buf); +void P_VMTIR(char *buf); +void P_VMFIR(char *buf); +void P_VILWR(char *buf); +void P_VISWR(char *buf); +void P_VRNEXT(char *buf); +void P_VRGET(char *buf); +void P_VRINIT(char *buf); +void P_VRXOR(char *buf); +//************************************END OF SPECIAL2 VUO TABLE**************************** + + +/* + CPU: Instructions encoded by opcode field. + 31---------26---------------------------------------------------0 + | opcode | | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | +001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | +010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | +011 | DADDI |DADDIU | LDL | LDR | *6 | --- | LQ | SQ | +100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | +101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | +110 | --- | LWC1 | --- | PREF | --- | --- | LQC2 | LD | +111 | --- | SWC1 | --- | --- | --- | --- | SQC2 | SD | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = SPECIAL, see SPECIAL list *2 = REGIMM, see REGIMM list + *3 = COP0 *4 = COP1 + *5 = COP2 *6 = MMI table +*/ +void (*OpcodePrintTable[64])(char *buf) = { + P_SpecialOpcode, P_REGIMMOpcode, P_J, P_JAL, P_BEQ, P_BNE, P_BLEZ, P_BGTZ, + P_ADDI, P_ADDIU, P_SLTI, P_SLTIU, P_ANDI, P_ORI, P_XORI, P_LUI, + P_COP0, P_COP1, P_COP2, P_UnknownOpcode, P_BEQL, P_BNEL, P_BLEZL, P_BGTZL, + P_DADDI, P_DADDIU, P_LDL, P_LDR, P_MMI, P_UnknownOpcode, P_LQ, P_SQ, + P_LB, P_LH, P_LWL, P_LW, P_LBU, P_LHU, P_LWR, P_LWU, + P_SB, P_SH, P_SWL, P_SW, P_SDL, P_SDR, P_SWR, P_CACHE, + P_UnknownOpcode, P_LWC1, P_UnknownOpcode, P_PREF, P_UnknownOpcode,P_UnknownOpcode, P_LQC2, P_LD, + P_UnknownOpcode, P_SWC1, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode,P_UnknownOpcode, P_SQC2, P_SD +}; + + + /* + SPECIAL: Instr. encoded by function field when opcode field = SPECIAL + 31---------26------------------------------------------5--------0 + | = SPECIAL | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | +001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | +010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | +011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | +100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | +101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | +110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | +111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ + +void (*SpecialPrintTable[64])(char *buf) = { + P_SLL, P_UnknownOpcode, P_SRL, P_SRA, P_SLLV, P_UnknownOpcode, P_SRLV, P_SRAV, + P_JR, P_JALR, P_MOVZ, P_MOVN, P_SYSCALL, P_BREAK, P_UnknownOpcode, P_SYNC, + P_MFHI, P_MTHI, P_MFLO, P_MTLO, P_DSLLV, P_UnknownOpcode, P_DSRLV, P_DSRAV, + P_MULT, P_MULTU, P_DIV, P_DIVU, P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode,P_UnknownOpcode, + P_ADD, P_ADDU, P_SUB, P_SUBU, P_AND, P_OR, P_XOR, P_NOR, + P_MFSA , P_MTSA , P_SLT, P_SLTU, P_DADD, P_DADDU, P_DSUB, P_DSUBU, + P_TGE, P_TGEU, P_TLT, P_TLTU, P_TEQ, P_UnknownOpcode, P_TNE, P_UnknownOpcode, + P_DSLL, P_UnknownOpcode, P_DSRL, P_DSRA, P_DSLL32, P_UnknownOpcode, P_DSRL32, P_DSRA32 +}; + +/* + REGIMM: Instructions encoded by the rt field when opcode field = REGIMM. + 31---------26----------20-------16------------------------------0 + | = REGIMM | | rt | | + ------6---------------------5------------------------------------ + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | + 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | + 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | + 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*REGIMMPrintTable[32])(char *buf) = { + P_BLTZ, P_BGEZ, P_BLTZL, P_BGEZL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_TGEI, P_TGEIU, P_TLTI, P_TLTIU, P_TEQI, P_UnknownOpcode, P_TNEI, P_UnknownOpcode, + P_BLTZAL, P_BGEZAL, P_BLTZALL, P_BGEZALL, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, + P_MTSAB, P_MTSAH , P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, P_UnknownOpcode, +}; +/* + MMI: Instr. encoded by function field when opcode field = MMI + 31---------26------------------------------------------5--------0 + | = MMI | | function| + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | MADD | MADDU | --- | --- | PLZCW | --- | --- | --- | +001 | *1 | *2 | --- | --- | --- | --- | --- | --- | +010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | --- | --- | --- | --- | +011 | MULT1 | MULTU1| DIV1 | DIVU1 | --- | --- | --- | --- | +100 | MADD1 | MADDU1| --- | --- | --- | --- | --- | --- | +101 | *3 | *4 | --- | --- | --- | --- | --- | --- | +110 | PMFHL | PMTHL | --- | --- | PSLLH | --- | PSRLH | PSRAH | +111 | --- | --- | --- | --- | PSLLW | --- | PSRLW | PSRAW | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + + *1 = see MMI0 table *2 = see MMI2 Table + *3 = see MMI1 table *4 = see MMI3 Table +*/ +void (*MMIPrintTable[64])(char *buf) = { + P_MADD, P_MADDU, P_MMI_Unknown, P_MMI_Unknown, P_PLZCW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI0, P_MMI2, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MFHI1, P_MTHI1, P_MFLO1, P_MTLO1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MULT1, P_MULTU1, P_DIV1, P_DIVU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MADD1, P_MADDU1, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI1 , P_MMI3, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHL, P_PMTHL, P_MMI_Unknown, P_MMI_Unknown, P_PSLLH, P_MMI_Unknown, P_PSRLH, P_PSRAH, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_PSLLW, P_MMI_Unknown, P_PSRLW, P_PSRAW, +}; +/* + MMI0: Instr. encoded by function field when opcode field = MMI & MMI0 + + 31---------26------------------------------10--------6-5--------0 + | | |function | MMI0 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PADDW | PSUBW | PCGTW | PMAXW | +001 |PADDH | PSUBH | PCGTH | PMAXH | +010 |PADDB | PSUBB | PCGTB | --- | +011 | --- | --- | --- | --- | +100 |PADDSW |PSUBSW |PEXTLW | PPACW | +101 |PADDSH |PSUBSH |PEXTLH | PPACH | +110 |PADDSB |PSUBSB |PEXTLB | PPACB | +111 | --- | --- | PEXT5 | PPAC5 | + hi |-------|-------|-------|-------| +*/ +void (*MMI0PrintTable[32])(char *buf) = { + P_PADDW, P_PSUBW, P_PCGTW, P_PMAXW, + P_PADDH, P_PSUBH, P_PCGTH, P_PMAXH, + P_PADDB, P_PSUBB, P_PCGTB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDSW, P_PSUBSW, P_PEXTLW, P_PPACW, + P_PADDSH, P_PSUBSH, P_PEXTLH, P_PPACH, + P_PADDSB, P_PSUBSB, P_PEXTLB, P_PPACB, + P_MMI_Unknown, P_MMI_Unknown, P_PEXT5, P_PPAC5, +}; +/* + MMI1: Instr. encoded by function field when opcode field = MMI & MMI1 + + 31---------26------------------------------------------5--------0 + | | |function | MMI1 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 | --- | PABSW | PCEQW | PMINW | +001 |PADSBH | PABSH | PCEQH | PMINH | +010 | --- | --- | PCEQB | --- | +011 | --- | --- | --- | --- | +100 |PADDUW |PSUBUW |PEXTUW | --- | +101 |PADDUH |PSUBUH |PEXTUH | --- | +110 |PADDUB |PSUBUB |PEXTUB | QFSRV | +111 | --- | --- | --- | --- | + hi |-------|-------|-------|-------| +*/ +void (*MMI1PrintTable[32])(char *buf) = { + P_MMI_Unknown, P_PABSW, P_PCEQW, P_PMINW, + P_PADSBH, P_PABSH, P_PCEQH, P_PMINH, + P_MMI_Unknown, P_MMI_Unknown, P_PCEQB, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PADDUW, P_PSUBUW, P_PEXTUW, P_MMI_Unknown, + P_PADDUH, P_PSUBUH, P_PEXTUH, P_MMI_Unknown, + P_PADDUB, P_PSUBUB, P_PEXTUB, P_QFSRV, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, +}; + +/* + MMI2: Instr. encoded by function field when opcode field = MMI & MMI2 + + 31---------26------------------------------------------5--------0 + | | |function | MMI2 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDW | --- |PSLLVW |PSRLVW | +001 |PMSUBW | --- | --- | --- | +010 |PMFHI |PMFLO |PINTH | --- | +011 |PMULTW |PDIVW |PCPYLD | --- | +100 |PMADDH |PHMADH | PAND | PXOR | +101 |PMSUBH |PHMSBH | --- | --- | +110 | --- | --- | PEXEH | PREVH | +111 |PMULTH |PDIVBW | PEXEW |PROT3W | + hi |-------|-------|-------|-------| +*/ +void (*MMI2PrintTable[32])(char *buf) = { + P_PMADDW, P_MMI_Unknown, P_PSLLVW, P_PSRLVW, + P_PMSUBW, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMFHI, P_PMFLO, P_PINTH, P_MMI_Unknown, + P_PMULTW, P_PDIVW, P_PCPYLD, P_MMI_Unknown, + P_PMADDH, P_PHMADH, P_PAND, P_PXOR, + P_PMSUBH, P_PHMSBH, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXEH, P_PREVH, + P_PMULTH, P_PDIVBW, P_PEXEW, P_PROT3W, +}; +/* + MMI3: Instr. encoded by function field when opcode field = MMI & MMI3 + 31---------26------------------------------------------5--------0 + | | |function | MMI3 | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--| lo +000 |PMADDUW| --- | --- |PSRAVW | +001 | --- | --- | --- | --- | +010 |PMTHI | PMTLO |PINTEH | --- | +011 |PMULTUW| PDIVUW|PCPYUD | --- | +100 | --- | --- | POR | PNOR | +101 | --- | --- | --- | --- | +110 | --- | --- | PEXCH | PCPYH | +111 | --- | --- | PEXCW | --- | + hi |-------|-------|-------|-------| + */ +void (*MMI3PrintTable[32])(char *buf) = { + P_PMADDUW, P_MMI_Unknown, P_MMI_Unknown, P_PSRAVW, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_PMTHI, P_PMTLO, P_PINTEH, P_MMI_Unknown, + P_PMULTUW, P_PDIVUW, P_PCPYUD, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_POR, P_PNOR, + P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, P_MMI_Unknown, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCH, P_PCPYH, + P_MMI_Unknown, P_MMI_Unknown, P_PEXCW, P_MMI_Unknown, +}; +/* + COP0: Instructions encoded by the rs field when opcode = COP0. + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=BC See BC0 list *2 = TLB instr, see TLB list +*/ +void (*COP0PrintTable[32])(char *buf) = { + P_MFC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_MTC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_BC0, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Func, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + BC0: Instructions encoded by the rt field when opcode = COP0 & rs field=BC0 + 31--------26-25------21 ----------------------------------------0 + | = COP0 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0BC0PrintTable[32])(char *buf) = { + P_BC0F, P_BC0T, P_BC0FL, P_BC0TL, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, +}; +/* + C0=Instructions encode by function field when Opcode field=COP0 & rs field=C0 + 31---------26------------------------------------------5--------0 + | | | | + ------6----------------------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | +001 | TLBP | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | ERET | --- | --- | --- | --- | --- | --- | --- | +100 | --- | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | EI | DI | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP0C0PrintTable[64])(char *buf) = { + P_COP0_Unknown, P_TLBR, P_TLBWI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_TLBWR, P_COP0_Unknown, + P_TLBP, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_ERET, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, + P_EI, P_DI, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown, P_COP0_Unknown +}; +/* + COP1: Instructions encoded by the fmt field when opcode = COP1. + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | MFC1 | --- | CFC1 | --- | MTC1 | --- | CTC1 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC1 list *2 = S instr, see FPU list + *3 = W instr, see FPU list +*/ +void (*COP1PrintTable[32])(char *buf) = { + P_MFC1, P_COP1_Unknown, P_CFC1, P_COP1_Unknown, P_MTC1, P_COP1_Unknown, P_CTC1, P_COP1_Unknown, + P_COP1_BC1, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_S, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_W, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + BC1: Instructions encoded by the rt field when opcode = COP1 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP1 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1BC1PrintTable[32])(char *buf) = { + P_BC1F, P_BC1T, P_BC1FL, P_BC1TL, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, + P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = S + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = S | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S| ABS.S | MOV.S | NEG.S | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- |RSQRT.S| --- | +011 | ADDA.S| SUBA.S| MULA.S| --- | MADD.S| MSUB.S|MADDA.S|MSUBA.S| +100 | --- | --- | --- | --- | CVT.W | --- | --- | --- | +101 | MAX.S | MIN.S | --- | --- | --- | --- | --- | --- | +110 | C.F | --- | C.EQ | --- | C.LT | --- | C.LE | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1SPrintTable[64])(char *buf) = { +P_ADD_S, P_SUB_S, P_MUL_S, P_DIV_S, P_SQRT_S, P_ABS_S, P_MOV_S, P_NEG_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_RSQRT_S, P_COP1_Unknown, +P_ADDA_S, P_SUBA_S, P_MULA_S, P_COP1_Unknown,P_MADD_S, P_MSUB_S, P_MADDA_S, P_MSUBA_S, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_CVT_W, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_MAX_S, P_MIN_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_C_F, P_COP1_Unknown,P_C_EQ, P_COP1_Unknown,P_C_LT, P_COP1_Unknown,P_C_LE, P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; +/* + FPU: Instructions encoded by the function field when opcode = COP1 + and rs = W + 31--------26-25------21 -------------------------------5--------0 + | = COP1 | = W | | function| + ------6----------5-----------------------------------------6----- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 | --- | --- | --- | --- | --- | --- | --- | --- | +001 | --- | --- | --- | --- | --- | --- | --- | --- | +010 | --- | --- | --- | --- | --- | --- | --- | --- | +011 | --- | --- | --- | --- | --- | --- | --- | --- | +100 | CVT.S | --- | --- | --- | --- | --- | --- | --- | +101 | --- | --- | --- | --- | --- | --- | --- | --- | +110 | --- | --- | --- | --- | --- | --- | --- | --- | +111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP1WPrintTable[64])(char *buf) = { +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_CVT_S, P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown,P_COP1_Unknown, +}; + +//************************************************************* +//COP2 TABLES :) +//************************************************************* +/* + COP2: Instructions encoded by the fmt field when opcode = COP2. + 31--------26-25------21 ----------------------------------------0 + | = COP2 | fmt | | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | --- | QMFC2 | CFC2 | --- | --- | QMTC2 | CTC2 | --- | + 01 | *1 | --- | --- | --- | --- | --- | --- | --- | + 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1 = BC instructions, see BC2 list *2 =see special1 table +*/ +void (*COP2PrintTable[32])(char *buf) = { + P_COP2_Unknown, P_QMFC2, P_CFC2, P_COP2_Unknown, P_COP2_Unknown, P_QMTC2, P_CTC2, P_COP2_Unknown, + P_COP2_BC2, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, P_COP2_SPECIAL, + + +}; +/* + BC2: Instructions encoded by the rt field when opcode = COP2 & rs field=BC1 + 31--------26-25------21 ----------------------------------------0 + | = COP2 | rs=BC2| | + ------6----------5----------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo + 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | + 01 | --- | --- | --- | --- | --- | --- | --- | --- | + 10 | --- | --- | --- | --- | --- | --- | --- | --- | + 11 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + */ +void (*COP2BC2PrintTable[32])(char *buf) = { + P_BC2F, P_BC2T, P_BC2FL, P_BC2TL, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, + P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, P_COP2_Unknown, +}; +/* + Special1 table : instructions encode by function field when opcode=COP2 & rs field=Special1 + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +000 |VADDx |VADDy |VADDz |VADDw |VSUBx |VSUBy |VSUBz |VSUBw | +001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw | +010 |VMAXx |VMAXy |VMAXz |VMAXw |VMINIx |VMINIy |VMINIz |VMINIw | +011 |VMULx |VMULy |VMULz |VMULw |VMULq |VMAXi |VMULi |VMINIi | +100 |VADDq |VMADDq |VADDi |VMADDi |VSUBq |VMSUBq |VSUbi |VMSUBi | +101 |VADD |VMADD |VMUL |VMAX |VSUB |VMSUB |VOPMSUB|VMINI | +110 |VIADD |VISUB |VIADDI | --- |VIAND |VIOR | --- | --- | +111 |VCALLMS|CALLMSR| --- | --- | *1 | *1 | *1 | *1 | + hi |-------|-------|-------|-------|-------|-------|-------|-------| + *1=see special2 table +*/ +void (*COP2SPECIAL1PrintTable[64])(char *buf) = +{ + P_VADDx, P_VADDy, P_VADDz, P_VADDw, P_VSUBx, P_VSUBy, P_VSUBz, P_VSUBw, + P_VMADDx, P_VMADDy, P_VMADDz, P_VMADDw, P_VMSUBx, P_VMSUBy, P_VMSUBz, P_VMSUBw, + P_VMAXx, P_VMAXy, P_VMAXz, P_VMAXw, P_VMINIx, P_VMINIy, P_VMINIz, P_VMINIw, + P_VMULx, P_VMULy, P_VMULz, P_VMULw, P_VMULq, P_VMAXi, P_VMULi, P_VMINIi, + P_VADDq, P_VMADDq, P_VADDi, P_VMADDi, P_VSUBq, P_VMSUBq, P_VSUbi, P_VMSUBi, + P_VADD, P_VMADD, P_VMUL, P_VMAX, P_VSUB, P_VMSUB, P_VOPMSUB, P_VMINI, + P_VIADD, P_VISUB, P_VIADDI, P_COP2_Unknown,P_VIAND, P_VIOR, P_COP2_Unknown, P_COP2_Unknown, + P_VCALLMS, P_CALLMSR, P_COP2_Unknown,P_COP2_Unknown,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2,P_COP2_SPECIAL2, + +}; +/* + Special2 table : instructions encode by function field when opcode=COp2 & rs field=Special2 + + 31---------26---------------------------------------------------0 + | =COP2 | rs=Special2 | + ------6---------------------------------------------------------- + |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo +0000 |VADDAx |VADDAy |VADDAz |VADDAw |VSUBAx |VSUBAy |VSUBAz |VSUBAw | +0001 |VMADDAx|VMADDAy|VMADDAz|VMADDAw|VMSUBAx|VMSUBAy|VMSUBAz|VMSUBAw| +0010 |VITOF0 |VITOF4 |VITOF12|VITOF15|VFTOI0 |VFTOI4 |VFTOI12|VFTOI15| +0011 |VMULAx |VMULAy |VMULAz |VMULAw |VMULAq |VABS |VMULAi |VCLIPw | +0100 |VADDAq |VMADDAq|VADDAi |VMADDAi|VSUBAq |VMSUBAq|VSUBAi |VMSUBAi| +0101 |VADDA |VMADDA |VMULA | --- |VSUBA |VMSUBA |VOPMULA|VNOP | +0110 |VMONE |VMR32 | --- | --- |VLQI |VSQI |VLQD |VSQD | +0111 |VDIV |VSQRT |VRSQRT |VWAITQ |VMTIR |VMFIR |VILWR |VISWR | +1000 |VRNEXT |VRGET |VRINIT |VRXOR | --- | --- | --- | --- | +1001 | --- | --- | --- | --- | --- | --- | --- | --- | +1010 | --- | --- | --- | --- | --- | --- | --- | --- | +1011 | --- | --- | --- | --- | --- | --- | --- | --- | +1100 | --- | --- | --- | --- | --- | --- | --- | --- | +1101 | --- | --- | --- | --- | --- | --- | --- | --- | +1110 | --- | --- | --- | --- | --- | --- | --- | --- | +1111 | --- | --- | --- | --- | --- | --- | --- | --- | + hi |-------|-------|-------|-------|-------|-------|-------|-------| +*/ +void (*COP2SPECIAL2PrintTable[128])(char *buf) = +{ + P_VADDAx ,P_VADDAy ,P_VADDAz ,P_VADDAw ,P_VSUBAx ,P_VSUBAy ,P_VSUBAz ,P_VSUBAw, + P_VMADDAx ,P_VMADDAy ,P_VMADDAz ,P_VMADDAw ,P_VMSUBAx ,P_VMSUBAy ,P_VMSUBAz ,P_VMSUBAw, + P_VITOF0 ,P_VITOF4 ,P_VITOF12 ,P_VITOF15 ,P_VFTOI0 ,P_VFTOI4 ,P_VFTOI12 ,P_VFTOI15, + P_VMULAx ,P_VMULAy ,P_VMULAz ,P_VMULAw ,P_VMULAq ,P_VABS ,P_VMULAi ,P_VCLIPw, + P_VADDAq ,P_VMADDAq ,P_VADDAi ,P_VMADDAi ,P_VSUBAq ,P_VMSUBAq ,P_VSUBAi ,P_VMSUBAi, + P_VADDA ,P_VMADDA ,P_VMULA ,P_COP2_Unknown,P_VSUBA ,P_VMSUBA ,P_VOPMULA ,P_VNOP, + P_VMONE ,P_VMR32 ,P_COP2_Unknown,P_COP2_Unknown,P_VLQI ,P_VSQI ,P_VLQD ,P_VSQD, + P_VDIV ,P_VSQRT ,P_VRSQRT ,P_VWAITQ ,P_VMTIR ,P_VMFIR ,P_VILWR ,P_VISWR, + P_VRNEXT ,P_VRGET ,P_VRINIT ,P_VRXOR ,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, + P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown,P_COP2_Unknown, +}; + +//**************************TABLES CALLS*********************** + +static char dbuf[1024]; +static char obuf[1024]; + +char *disR5900Fasm(u32 code, u32 pc) { + u32 scode = cpuRegs.code; + opcode_addr = pc; + cpuRegs.code = code; + OpcodePrintTable[(code) >> 26](dbuf); + + sprintf(obuf, "%08X:\t%s", pc, dbuf); + + cpuRegs.code = scode; + return obuf; +} + +void P_SpecialOpcode(char *buf) +{ + SpecialPrintTable[DECODE_FUNCTION](buf); +} +void P_REGIMMOpcode(char *buf) +{ + REGIMMPrintTable[DECODE_RT](buf); +} + +//***********COP0 TABLE CALLS******************************** + +void P_COP0(char *buf) +{ + COP0PrintTable[DECODE_RS](buf); +} +void P_COP0_BC0(char *buf) +{ + + COP0BC0PrintTable[DECODE_C0BC](buf); +} +void P_COP0_Func(char *buf) +{ + + COP0C0PrintTable[DECODE_FUNCTION](buf); +} + +//*****************MMI TABLES CALLS************************** +void P_MMI(char *buf) +{ + + MMIPrintTable[DECODE_FUNCTION](buf); +} +void P_MMI0(char *buf) +{ + MMI0PrintTable[DECODE_SA](buf); +} +void P_MMI1(char *buf) +{ + MMI1PrintTable[DECODE_SA](buf); +} +void P_MMI2(char *buf) +{ + MMI2PrintTable[DECODE_SA](buf); +} +void P_MMI3(char *buf) +{ + MMI3PrintTable[DECODE_SA](buf); +} +//****************END OF MMI TABLES CALLS********************** +//COP1 TABLECALLS******************************************* +void P_COP1(char *buf) +{ + + COP1PrintTable[DECODE_RS](buf); +} +void P_COP1_BC1(char *buf) +{ + COP1BC1PrintTable[DECODE_C1BC](buf); +} +void P_COP1_S(char *buf) +{ + COP1SPrintTable[DECODE_FUNCTION](buf); +} +void P_COP1_W(char *buf) +{ + COP1WPrintTable[DECODE_FUNCTION](buf); +} +//**********************END OF COP1 TABLE CALLS + +//************************************************************* +//************************COP2********************************** +void P_COP2(char *buf) +{ + + COP2PrintTable[DECODE_RS](buf); +} +void P_COP2_BC2(char *buf) +{ + COP2BC2PrintTable[DECODE_C2BC](buf); +} +void P_COP2_SPECIAL(char *buf) +{ + COP2SPECIAL1PrintTable[DECODE_FUNCTION ](buf); + +} +void P_COP2_SPECIAL2(char *buf) +{ + + COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](buf); + +} + +//**************************UNKNOWN**************************** +void P_UnknownOpcode(char *buf) +{ + strcpy(buf, "?????"); +} +void P_COP0_Unknown(char *buf) +{ + strcpy(buf, "COP0 ??"); +} +void P_COP1_Unknown(char *buf) +{ + strcpy(buf, "COP1 ??"); +} +void P_COP2_Unknown(char *buf) +{ + strcpy(buf,"COP2 ??"); +} + +void P_MMI_Unknown(char *buf) +{ + strcpy(buf,"MMI ??"); +} + + + +//************************************************************* + +//*****************SOME DECODE STUFF*************************** +#define dFindSym(i) { \ + char *str = disR5900GetSym(i); \ + if (str != NULL) sprintf(buf, "%s %s", buf, str); \ +} + +char *jump_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_JUMP; + sprintf(buf, "0x%08X", addr); + + dFindSym(addr); + return buf; +} + +char *offset_decode(void) +{ + static char buf[256]; + unsigned long addr; + addr = DECODE_OFFSET; + sprintf(buf, "0x%08X", addr); + dFindSym(addr); + return buf; +} + +//*********************END OF DECODE ROUTINES****************** + +//********************* Standard Opcodes*********************** +void P_J(char *buf) { sprintf(buf, "j\t%s", jump_decode());} +void P_JAL(char *buf) { sprintf(buf, "jal\t%s", jump_decode());} +void P_BEQ(char *buf) { sprintf(buf, "beq\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNE(char *buf) { sprintf(buf, "bne\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZ(char *buf) { sprintf(buf, "blez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZ(char *buf) { sprintf(buf, "bgtz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_ADDI(char *buf) { sprintf(buf, "addi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ADDIU(char *buf) { sprintf(buf, "addiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_SLTI(char *buf) { sprintf(buf, "slti\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_SLTIU(char *buf) { sprintf(buf, "sltiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_ANDI(char *buf) { sprintf(buf, "andi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_ORI(char *buf) { sprintf(buf, "ori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_XORI(char *buf) { sprintf(buf, "xori\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LUI(char *buf) { sprintf(buf, "lui\t%s, 0x%04X", GPR_REG[DECODE_RT], DECODE_IMMED); } +void P_BEQL(char *buf) { sprintf(buf, "beql\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BNEL(char *buf) { sprintf(buf, "bnel\t%s, %s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT], offset_decode()); } +void P_BLEZL(char *buf) { sprintf(buf, "blezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGTZL(char *buf) { sprintf(buf, "bgtzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_DADDI(char *buf) { sprintf(buf, "daddi\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_DADDIU(char *buf) { sprintf(buf, "daddiu\t%s, %s, 0x%04X", GPR_REG[DECODE_RT], GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_LDL(char *buf) { sprintf(buf, "ldl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LDR(char *buf) { sprintf(buf, "ldr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LB(char *buf) { sprintf(buf, "lb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LH(char *buf) { sprintf(buf, "lh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWL(char *buf) { sprintf(buf, "lwl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LW(char *buf) { sprintf(buf, "lw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LBU(char *buf) { sprintf(buf, "lbu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LHU(char *buf) { sprintf(buf, "lhu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWR(char *buf) { sprintf(buf, "lwr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LWU(char *buf) { sprintf(buf, "lwu\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SB(char *buf) { sprintf(buf, "sb\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SH(char *buf) { sprintf(buf, "sh\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWL(char *buf) { sprintf(buf, "swl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SW(char *buf) { sprintf(buf, "sw\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDL(char *buf) { sprintf(buf, "sdl\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SDR(char *buf) { sprintf(buf, "sdr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWR(char *buf) { sprintf(buf, "swr\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LD(char *buf) { sprintf(buf, "ld\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SD(char *buf) { sprintf(buf, "sd\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQ(char *buf) { sprintf(buf, "lq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQ(char *buf) { sprintf(buf, "sq\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SWC1(char *buf) { sprintf(buf, "swc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_SQC2(char *buf) { sprintf(buf, "sqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_PREF(char *buf) { strcpy(buf, "pref ---");/*sprintf(buf, "PREF\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[RS]); */} +void P_LWC1(char *buf) { sprintf(buf, "lwc1\t%s, 0x%04X(%s)", COP1_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +void P_LQC2(char *buf) { sprintf(buf, "lqc2\t%s, 0x%04X(%s)", COP2_REG_FP[DECODE_FT], DECODE_IMMED, GPR_REG[DECODE_RS]); } +//********************END OF STANDARD OPCODES************************* + +void P_SLL(char *buf) +{ + if (cpuRegs.code == 0x00000000) + strcpy(buf, "nop"); + else + sprintf(buf, "sll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); +} + +void P_SRL(char *buf) { sprintf(buf, "srl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SRA(char *buf) { sprintf(buf, "sra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_SLLV(char *buf) { sprintf(buf, "sllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_SRLV(char *buf) { sprintf(buf, "srlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]);} +void P_SRAV(char *buf) { sprintf(buf, "srav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_JR(char *buf) { sprintf(buf, "jr\t%s", GPR_REG[DECODE_RS]); } + +void P_JALR(char *buf) +{ + int rd = DECODE_RD; + + if (rd == 31) + sprintf(buf, "jalr\t%s", GPR_REG[DECODE_RS]); + else + sprintf(buf, "jalr\t%s, %s", GPR_REG[rd], GPR_REG[DECODE_RS]); +} + + +void P_SYNC(char *buf) { sprintf(buf, "SYNC");} +void P_MFHI(char *buf) { sprintf(buf, "mfhi\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI(char *buf) { sprintf(buf, "mthi\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO(char *buf) { sprintf(buf, "mflo\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO(char *buf) { sprintf(buf, "mtlo\t%s", GPR_REG[DECODE_RS]); } +void P_DSLLV(char *buf) { sprintf(buf, "dsllv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRLV(char *buf) { sprintf(buf, "dsrlv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_DSRAV(char *buf) { sprintf(buf, "dsrav\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_MULT(char *buf) { sprintf(buf, "mult\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_MULTU(char *buf) { sprintf(buf, "multu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV(char *buf) { sprintf(buf, "div\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU(char *buf) { sprintf(buf, "divu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADD(char *buf) { sprintf(buf, "add\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_ADDU(char *buf) { sprintf(buf, "addu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUB(char *buf) { sprintf(buf, "sub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SUBU(char *buf) { sprintf(buf, "subu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_AND(char *buf) { sprintf(buf, "and\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_OR(char *buf) { sprintf(buf, "or\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_XOR(char *buf) { sprintf(buf, "xor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_NOR(char *buf) { sprintf(buf, "nor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLT(char *buf) { sprintf(buf, "slt\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_SLTU(char *buf) { sprintf(buf, "sltu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADD(char *buf) { sprintf(buf, "dadd\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DADDU(char *buf) { sprintf(buf, "daddu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUB(char *buf) { sprintf(buf, "dsub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSUBU(char *buf) { sprintf(buf, "dsubu\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGE(char *buf) { sprintf(buf, "tge\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TGEU(char *buf) { sprintf(buf, "tgeu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLT(char *buf) { sprintf(buf, "tlt\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TLTU(char *buf) { sprintf(buf, "tltu\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TEQ(char *buf) { sprintf(buf, "teq\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_TNE(char *buf) { sprintf(buf, "tne\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DSLL(char *buf) { sprintf(buf, "dsll\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL(char *buf) { sprintf(buf, "dsrl\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA(char *buf) { sprintf(buf, "dsra\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSLL32(char *buf) { sprintf(buf, "dsll32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRL32(char *buf) { sprintf(buf, "dsrl32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_DSRA32(char *buf) { sprintf(buf, "dsra32\t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_MOVZ(char *buf) { sprintf(buf, "movz\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MOVN(char *buf) { sprintf(buf, "movn\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFSA(char *buf) { sprintf(buf, "mfsa\t%s", GPR_REG[DECODE_RD]);} +void P_MTSA(char *buf) { sprintf(buf, "mtsa\t%s", GPR_REG[DECODE_RS]);} +//*** unsupport (yet) cpu opcodes +void P_SYSCALL(char *buf) { strcpy(buf, "syscall ---");/*sprintf(buf, "syscall\t0x%05X", DECODE_SYSCALL);*/} +void P_BREAK(char *buf) { strcpy(buf, "break ---");/*sprintf(buf, "break\t0x%05X", DECODE_BREAK); */} +void P_CACHE(char *buf) { strcpy(buf, "cache ---");/*sprintf(buf, "cache\t%s, 0x%04X(%s)", GPR_REG[DECODE_RT], DECODE_IMMED, GPR_REG[DECODE_RS]); */} +//************************REGIMM OPCODES*************************** +void P_BLTZ(char *buf) { sprintf(buf, "bltz\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZ(char *buf) { sprintf(buf, "bgez\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZL(char *buf) { sprintf(buf, "bltzl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZL(char *buf) { sprintf(buf, "bgezl\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_TGEI(char *buf) { sprintf(buf, "tgei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TGEIU(char *buf) { sprintf(buf, "tgeiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTI(char *buf) { sprintf(buf, "tlti\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TLTIU(char *buf) { sprintf(buf, "tltiu\t%s,0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TEQI(char *buf) { sprintf(buf, "teqi\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_TNEI(char *buf) { sprintf(buf, "tnei\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED); } +void P_BLTZAL(char *buf) { sprintf(buf, "bltzal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZAL(char *buf) { sprintf(buf, "bgezal\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BLTZALL(char *buf) { sprintf(buf, "bltzall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_BGEZALL(char *buf) { sprintf(buf, "bgezall\t%s, %s", GPR_REG[DECODE_RS], offset_decode()); } +void P_MTSAB(char *buf) { sprintf(buf, "mtsab\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} +void P_MTSAH(char *buf) { sprintf(buf, "mtsah\t%s, 0x%04X", GPR_REG[DECODE_RS], DECODE_IMMED);} + + +//***************************SPECIAL 2 CPU OPCODES******************* +const char* pmfhl_sub[] = { "lw", "uw", "slw", "lh", "sh" }; + +void P_MADD(char *buf) { sprintf(buf, "madd\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU(char *buf) { sprintf(buf, "maddu\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_PLZCW(char *buf) { sprintf(buf, "plzcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS]); } +void P_MADD1(char *buf) { sprintf(buf, "madd1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MADDU1(char *buf) { sprintf(buf, "maddu1\t%s, %s %s", GPR_REG[DECODE_RD],GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MFHI1(char *buf) { sprintf(buf, "mfhi1\t%s", GPR_REG[DECODE_RD]); } +void P_MTHI1(char *buf) { sprintf(buf, "mthi1\t%s", GPR_REG[DECODE_RS]); } +void P_MFLO1(char *buf) { sprintf(buf, "mflo1\t%s", GPR_REG[DECODE_RD]); } +void P_MTLO1(char *buf) { sprintf(buf, "mtlo1\t%s", GPR_REG[DECODE_RS]); } +void P_MULT1(char *buf) { sprintf(buf, "mult1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_MULTU1(char *buf) { sprintf(buf, "multu1\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]);} +void P_DIV1(char *buf) { sprintf(buf, "div1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_DIVU1(char *buf) { sprintf(buf, "divu1\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//that have parametres that i haven't figure out how to display... +void P_PMFHL(char *buf) { sprintf(buf, "pmfhl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RD]); } +void P_PMTHL(char *buf) { sprintf(buf, "pmthl.%s \t%s", pmfhl_sub[DECODE_SA], GPR_REG[DECODE_RS]); } +void P_PSLLH(char *buf) { sprintf(buf, "psllh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA); } +void P_PSRLH(char *buf) { sprintf(buf, "psrlh \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAH(char *buf) { sprintf(buf, "psrah \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSLLW(char *buf) { sprintf(buf, "psllw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRLW(char *buf) { sprintf(buf, "psrlw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +void P_PSRAW(char *buf) { sprintf(buf, "psraw \t%s, %s, 0x%02X", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], DECODE_SA);} +//***************************END OF SPECIAL OPCODES****************** +//*************************MMI0 OPCODES************************ + +void P_PADDW(char *buf){ sprintf(buf, "paddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBW(char *buf){ sprintf(buf, "psubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTW(char *buf){ sprintf(buf, "pcgtw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXW(char *buf){ sprintf(buf, "pmaxw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDH(char *buf){ sprintf(buf, "paddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBH(char *buf){ sprintf(buf, "psubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTH(char *buf){ sprintf(buf, "pcgth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMAXH(char *buf){ sprintf(buf, "pmaxh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDB(char *buf){ sprintf(buf, "paddb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBB(char *buf){ sprintf(buf, "psubb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCGTB(char *buf){ sprintf(buf, "pcgtb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSW(char *buf){ sprintf(buf, "paddsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSW(char *buf){ sprintf(buf, "psubsw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLW(char *buf){ sprintf(buf, "pextlw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACW(char *buf) { sprintf(buf, "ppacw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSH(char *buf){ sprintf(buf, "paddsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSH(char *buf){ sprintf(buf, "psubsh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLH(char *buf){ sprintf(buf, "pextlh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACH(char *buf) { sprintf(buf, "ppach\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDSB(char *buf){ sprintf(buf, "paddsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBSB(char *buf){ sprintf(buf, "psubsb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTLB(char *buf){ sprintf(buf, "pextlb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PPACB(char *buf) { sprintf(buf, "ppacb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXT5(char *buf) { sprintf(buf, "pext5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PPAC5(char *buf) { sprintf(buf, "ppac5\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//**********END OF MMI0 OPCODES********************************* +//**********MMI1 OPCODES************************************** +void P_PABSW(char *buf){ sprintf(buf, "pabsw%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQW(char *buf){ sprintf(buf, "pceqw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINW(char *buf){ sprintf(buf, "pminw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADSBH(char *buf){ sprintf(buf, "padsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PABSH(char *buf){ sprintf(buf, "pabsh%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PCEQH(char *buf){ sprintf(buf, "pceqh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMINH(char *buf){ sprintf(buf, "pminh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCEQB(char *buf){ sprintf(buf, "pceqb\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUW(char *buf){ sprintf(buf, "padduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUW(char *buf){ sprintf(buf, "psubuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUW(char *buf){ sprintf(buf, "pextuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUH(char *buf){ sprintf(buf, "padduh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUH(char *buf){ sprintf(buf, "psubuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUH(char *buf){ sprintf(buf, "pextuh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PADDUB(char *buf){ sprintf(buf, "paddub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSUBUB(char *buf){ sprintf(buf, "psubub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXTUB(char *buf){ sprintf(buf, "pextub\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_QFSRV(char *buf) { sprintf(buf, "qfsrv\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void P_PMADDW(char *buf){ sprintf(buf, "pmaddw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSLLVW(char *buf){ sprintf(buf, "psllvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PSRLVW(char *buf){ sprintf(buf, "psrlvw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBW(char *buf){ sprintf(buf, "msubw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMFHI(char *buf){ sprintf(buf, "pmfhi\t%s", GPR_REG[DECODE_RD]); } +void P_PMFLO(char *buf){ sprintf(buf, "pmflo\t%s", GPR_REG[DECODE_RD]); } +void P_PINTH(char *buf){ sprintf(buf, "pinth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTW(char *buf){ sprintf(buf, "pmultw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVW(char *buf){ sprintf(buf, "pdivw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYLD(char *buf){ sprintf(buf, "pcpyld\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMADDH(char *buf){ sprintf(buf, "pmaddh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMADH(char *buf){ sprintf(buf, "phmadh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PAND(char *buf){ sprintf(buf, "pand\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PXOR(char *buf){ sprintf(buf, "pxor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMSUBH(char *buf){ sprintf(buf, "pmsubh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PHMSBH(char *buf){ sprintf(buf, "phmsbh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEH(char *buf){ sprintf(buf, "pexeh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PREVH(char *buf){ sprintf(buf, "prevh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PMULTH(char *buf){ sprintf(buf, "pmulth\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVBW(char *buf){ sprintf(buf, "pdivbw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXEW(char *buf){ sprintf(buf, "pexew\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +void P_PROT3W(char *buf){ sprintf(buf, "prot3w\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]); } +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void P_PMADDUW(char *buf){ sprintf(buf, "pmadduw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PSRAVW(char *buf){ sprintf(buf, "psravw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT], GPR_REG[DECODE_RS]); } +void P_PMTHI(char *buf){ sprintf(buf, "pmthi\t%s", GPR_REG[DECODE_RS]); } +void P_PMTLO(char *buf){ sprintf(buf, "pmtlo\t%s", GPR_REG[DECODE_RS]); } +void P_PINTEH(char *buf){ sprintf(buf, "pinteh\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PMULTUW(char *buf){ sprintf(buf, "pmultuw\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PDIVUW(char *buf){ sprintf(buf, "pdivuw\t%s, %s", GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PCPYUD(char *buf){ sprintf(buf, "pcpyud\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_POR(char *buf){ sprintf(buf, "por\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PNOR(char *buf){ sprintf(buf, "pnor\t%s, %s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RS], GPR_REG[DECODE_RT]); } +void P_PEXCH(char *buf){ sprintf(buf, "pexch\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PCPYH(char *buf){ sprintf(buf, "pcpyh\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +void P_PEXCW(char *buf){ sprintf(buf, "pexcw\t%s, %s", GPR_REG[DECODE_RD], GPR_REG[DECODE_RT]);} +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void P_MFC0(char *buf){ sprintf(buf, "mfc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_MTC0(char *buf){ sprintf(buf, "mtc0\t%s, %s", GPR_REG[DECODE_RT], COP0_REG[DECODE_FS]); } +void P_BC0F(char *buf){ sprintf(buf, "bc0f\t%s", offset_decode()); } +void P_BC0T(char *buf){ sprintf(buf, "bc0t\t%s", offset_decode()); } +void P_BC0FL(char *buf){ sprintf(buf, "bc0fl\t%s", offset_decode()); } +void P_BC0TL(char *buf){ sprintf(buf, "bc0tl\t%s", offset_decode()); } +void P_TLBR(char *buf){ strcpy(buf,"tlbr");} +void P_TLBWI(char *buf){ strcpy(buf,"tlbwi");} +void P_TLBWR(char *buf){ strcpy(buf,"tlbwr");} +void P_TLBP(char *buf){ strcpy(buf,"tlbp");} +void P_ERET(char *buf){ strcpy(buf,"eret");} +void P_DI(char *buf){ strcpy(buf,"di");} +void P_EI(char *buf){ strcpy(buf,"ei");} +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void P_MFC1(char *buf){ sprintf(buf, "mfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CFC1(char *buf){ sprintf(buf, "cfc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_MTC1(char *buf){ sprintf(buf, "mtc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FP[DECODE_FS]); } +void P_CTC1(char *buf){ sprintf(buf, "ctc1\t%s, %s", GPR_REG[DECODE_RT], COP1_REG_FCR[DECODE_FS]); } +void P_BC1F(char *buf){ sprintf(buf, "bc1f\t%s", offset_decode()); } +void P_BC1T(char *buf){ sprintf(buf, "bc1t\t%s", offset_decode()); } +void P_BC1FL(char *buf){ sprintf(buf, "bc1fl\t%s", offset_decode()); } +void P_BC1TL(char *buf){ sprintf(buf, "bc1tl\t%s", offset_decode()); } +void P_ADD_S(char *buf){ sprintf(buf, "add.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_SUB_S(char *buf){ sprintf(buf, "sub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MUL_S(char *buf){ sprintf(buf, "mul.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_DIV_S(char *buf){ sprintf(buf, "div.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SQRT_S(char *buf){ sprintf(buf, "sqrt.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FT]); } +void P_ABS_S(char *buf){ sprintf(buf, "abs.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MOV_S(char *buf){ sprintf(buf, "mov.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_NEG_S(char *buf){ sprintf(buf, "neg.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]);} +void P_RSQRT_S(char *buf){sprintf(buf, "rsqrt.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_ADDA_S(char *buf){ sprintf(buf, "adda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_SUBA_S(char *buf){ sprintf(buf, "suba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MULA_S(char *buf){ sprintf(buf, "mula.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADD_S(char *buf){ sprintf(buf, "madd.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUB_S(char *buf){ sprintf(buf, "msub.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MADDA_S(char *buf){sprintf(buf, "madda.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_MSUBA_S(char *buf){sprintf(buf, "msuba.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_W(char *buf){ sprintf(buf, "cvt.w.s\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +void P_MAX_S(char *buf){ sprintf(buf, "max.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_MIN_S(char *buf){ sprintf(buf, "min.s\t%s, %s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]);} +void P_C_F(char *buf){ sprintf(buf, "c.f.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_EQ(char *buf){ sprintf(buf, "c.eq.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LT(char *buf){ sprintf(buf, "c.lt.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_C_LE(char *buf){ sprintf(buf, "c.le.s\t%s, %s", COP1_REG_FP[DECODE_FS], COP1_REG_FP[DECODE_FT]); } +void P_CVT_S(char *buf){ sprintf(buf, "cvt.s.w\t%s, %s", COP1_REG_FP[DECODE_FD], COP1_REG_FP[DECODE_FS]); } +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void P_QMFC2(char *buf){ sprintf(buf, "qmfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CFC2(char *buf){ sprintf(buf, "cfc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_QMTC2(char *buf){ sprintf(buf, "qmtc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_FP[DECODE_FS]); } +void P_CTC2(char *buf){ sprintf(buf, "ctc2\t%s, %s", GPR_REG[DECODE_RT], COP2_REG_CTL[DECODE_FS]); } +void P_BC2F(char *buf){ sprintf(buf, "bc2f\t%s", offset_decode()); } +void P_BC2T(char *buf){ sprintf(buf, "bc2t\t%s", offset_decode()); } +void P_BC2FL(char *buf){ sprintf(buf, "bc2fl\t%s", offset_decode()); } +void P_BC2TL(char *buf){ sprintf(buf, "bc2tl\t%s", offset_decode()); } +//******************************SPECIAL 1 VUO TABLE**************************************** +#define _X ((cpuRegs.code>>24) & 1) +#define _Y ((cpuRegs.code>>23) & 1) +#define _Z ((cpuRegs.code>>22) & 1) +#define _W ((cpuRegs.code>>21) & 1) + +const char *dest_string(void) +{ + static char str[5]; + int i; + i = 0; + if(_X) str[i++] = 'x'; + if(_Y) str[i++] = 'y'; + if(_Z) str[i++] = 'z'; + if(_W) str[i++] = 'w'; + str[i++] = 0; + return (const char *)str; +} + +char dest_fsf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>21)&3]; +} + +char dest_ftf() +{ + const arr[4] = { 'x', 'y', 'z', 'w' }; + return arr[(cpuRegs.code>>23)&3]; +} + +void P_VADDx(char *buf){sprintf(buf, "vaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDy(char *buf){sprintf(buf, "vaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDz(char *buf){sprintf(buf, "vaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VADDw(char *buf){sprintf(buf, "vaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBx(char *buf){sprintf(buf, "vsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBy(char *buf){sprintf(buf, "vsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBz(char *buf){sprintf(buf, "vsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBw(char *buf){sprintf(buf, "vsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDx(char *buf){sprintf(buf, "vmaddx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDy(char *buf){sprintf(buf, "vmaddy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDz(char *buf){sprintf(buf, "vmaddz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDw(char *buf){sprintf(buf, "vmaddw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBx(char *buf){sprintf(buf, "vmsubx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBy(char *buf){sprintf(buf, "vmsuby.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBz(char *buf){sprintf(buf, "vmsubz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBw(char *buf){sprintf(buf, "vmsubw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXx(char *buf){sprintf(buf, "vmaxx.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXy(char *buf){sprintf(buf, "vmaxy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXz(char *buf){sprintf(buf, "vmaxz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAXw(char *buf){sprintf(buf, "vmaxw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIx(char *buf){sprintf(buf, "vminix.%s %s, %s, %sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIy(char *buf){sprintf(buf, "vminiy.%s %s, %s, %sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); ;} +void P_VMINIz(char *buf){sprintf(buf, "vminiz.%s %s, %s, %sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINIw(char *buf){sprintf(buf, "vminiw.%s %s, %s, %sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULx(char *buf){sprintf(buf,"vmulx.%s %s,%s,%sx", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULy(char *buf){sprintf(buf,"vmuly.%s %s,%s,%sy", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULz(char *buf){sprintf(buf,"vmulz.%s %s,%s,%sz", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULw(char *buf){sprintf(buf,"vmulw.%s %s,%s,%sw", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULq(char *buf){sprintf(buf,"vmulq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMAXi(char *buf){sprintf(buf,"vmaxi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMULi(char *buf){sprintf(buf,"vmuli.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMINIi(char *buf){sprintf(buf,"vminii.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDq(char *buf){sprintf(buf,"vaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDq(char *buf){sprintf(buf,"vmaddq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADDi(char *buf){sprintf(buf,"vaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMADDi(char *buf){sprintf(buf,"vmaddi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUBq(char *buf){sprintf(buf,"vsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBq(char *buf){sprintf(buf,"vmsubq.%s %s,%s,Q",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VSUbi(char *buf){sprintf(buf,"vsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VMSUBi(char *buf){sprintf(buf,"vmsubi.%s %s,%s,I",dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS]); } +void P_VADD(char *buf){sprintf(buf, "vadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADD(char *buf){sprintf(buf, "vmadd.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMUL(char *buf){sprintf(buf, "vmul.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMAX(char *buf){sprintf(buf, "vmax.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUB(char *buf){sprintf(buf, "vsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUB(char *buf){sprintf(buf, "vmsub.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMSUB(char *buf){sprintf(buf, "vopmsub.xyz %s, %s, %s", COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMINI(char *buf){sprintf(buf, "vmini.%s %s, %s, %s", dest_string(),COP2_REG_FP[DECODE_FD], COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VIADD(char *buf){sprintf(buf,"viadd %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VISUB(char *buf){sprintf(buf,"visub %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VIADDI(char *buf){sprintf(buf,"viaddi %s, %s, 0x%x", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], DECODE_SA);} +void P_VIAND(char *buf){sprintf(buf,"viand %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VIOR(char *buf){sprintf(buf,"vior %s, %s, %s", COP2_REG_CTL[DECODE_SA], COP2_REG_CTL[DECODE_FS], COP2_REG_CTL[DECODE_FT]);} +void P_VCALLMS(char *buf){strcpy(buf,"vcallms");} +void P_CALLMSR(char *buf){strcpy(buf,"callmsr");} +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void P_VADDAx(char *buf){sprintf(buf,"vaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAy(char *buf){sprintf(buf,"vadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAz(char *buf){sprintf(buf,"vaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VADDAw(char *buf){sprintf(buf,"vaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAx(char *buf){sprintf(buf,"vsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAy(char *buf){sprintf(buf,"vsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAz(char *buf){sprintf(buf,"vsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VSUBAw(char *buf){sprintf(buf,"vsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAx(char *buf){sprintf(buf,"vmaddax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAy(char *buf){sprintf(buf,"vmadday.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAz(char *buf){sprintf(buf,"vmaddaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMADDAw(char *buf){sprintf(buf,"vmaddaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAx(char *buf){sprintf(buf,"vmsubax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAy(char *buf){sprintf(buf,"vmsubay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAz(char *buf){sprintf(buf,"vmsubaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMSUBAw(char *buf){sprintf(buf,"vmsubaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VITOF0(char *buf){sprintf(buf, "vitof0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF4(char *buf){sprintf(buf, "vitof4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF12(char *buf){sprintf(buf, "vitof12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VITOF15(char *buf){sprintf(buf, "vitof15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI0(char *buf) {sprintf(buf, "vftoi0.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI4(char *buf) {sprintf(buf, "vftoi4.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI12(char *buf){sprintf(buf, "vftoi12.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VFTOI15(char *buf){sprintf(buf, "vftoi15.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]); } +void P_VMULAx(char *buf){sprintf(buf,"vmulax.%s ACC,%s,%sx",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAy(char *buf){sprintf(buf,"vmulay.%s ACC,%s,%sy",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAz(char *buf){sprintf(buf,"vmulaz.%s ACC,%s,%sz",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAw(char *buf){sprintf(buf,"vmulaw.%s ACC,%s,%sw",dest_string(),COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]);} +void P_VMULAq(char *buf){sprintf(buf,"vmulaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VABS(char *buf){sprintf(buf, "vabs.%s %s, %s", dest_string(),COP2_REG_FP[DECODE_FT], COP2_REG_FP[DECODE_FS]);} +void P_VMULAi(char *buf){sprintf(buf,"vmulaq.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VCLIPw(char *buf){sprintf(buf,"vclip %sxyz, %sw", COP2_REG_FP[DECODE_FS], COP2_REG_FP[DECODE_FT]);} +void P_VADDAq(char *buf){sprintf(buf,"vaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAq(char *buf){sprintf(buf,"vmaddaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDAi(char *buf){sprintf(buf,"vaddai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMADDAi(char *buf){sprintf(buf,"vmaddai.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAq(char *buf){sprintf(buf,"vsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAq(char *buf){sprintf(buf,"vmsubaq.%s ACC %s, Q" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VSUBAi(char *buf){sprintf(buf,"vsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VMSUBAi(char *buf){sprintf(buf,"vmsubai.%s ACC %s, I" ,dest_string(), COP2_REG_FP[DECODE_FS]); } +void P_VADDA(char *buf){sprintf(buf,"vadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMADDA(char *buf){sprintf(buf,"vmadda.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMULA(char *buf){sprintf(buf,"vmula.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VSUBA(char *buf){sprintf(buf,"vsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VMSUBA(char *buf){sprintf(buf,"vmsuba.%s ACC %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VOPMULA(char *buf){sprintf(buf,"vopmula.xyz %sxyz, %sxyz" ,COP2_REG_FP[DECODE_FS],COP2_REG_FP[DECODE_FT]); } +void P_VNOP(char *buf){strcpy(buf,"vnop");} +void P_VMONE(char *buf){sprintf(buf,"vmove.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VMR32(char *buf){sprintf(buf,"vmr32.%s, %s, %s" ,dest_string(), COP2_REG_FP[DECODE_FT],COP2_REG_FP[DECODE_FS]); } +void P_VLQI(char *buf){sprintf(buf,"vlqi %s%s, (%s++)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQI(char *buf){sprintf(buf,"vsqi %s%s, (%s++)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VLQD(char *buf){sprintf(buf,"vlqd %s%s, (--%s)", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VSQD(char *buf){sprintf(buf,"vsqd %s%s, (--%s)", COP2_REG_FP[DECODE_FS], dest_string(), COP2_REG_CTL[DECODE_FT]);} +void P_VDIV(char *buf){sprintf(buf,"vdiv Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VSQRT(char *buf){sprintf(buf,"vsqrt Q, %s%c", COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VRSQRT(char *buf){sprintf(buf,"vrsqrt Q, %s%c, %s%c", COP2_REG_FP[DECODE_FS], dest_fsf(), COP2_REG_FP[DECODE_FT], dest_ftf());} +void P_VWAITQ(char *buf){sprintf(buf,"vwaitq");} +void P_VMTIR(char *buf){sprintf(buf,"vmtir %s, %s%c", COP2_REG_CTL[DECODE_FT], COP2_REG_FP[DECODE_FS], dest_fsf());} +void P_VMFIR(char *buf){sprintf(buf,"vmfir %s%c, %s", COP2_REG_FP[DECODE_FT], dest_string(), COP2_REG_CTL[DECODE_FS]);} +void P_VILWR(char *buf){sprintf(buf,"vilwr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VISWR(char *buf){sprintf(buf,"viswr %s, (%s)%s", COP2_REG_CTL[DECODE_FT], COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRNEXT(char *buf){sprintf(buf,"vrnext %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRGET(char *buf){sprintf(buf,"vrget %s%s, R", COP2_REG_CTL[DECODE_FT], dest_string());} +void P_VRINIT(char *buf){sprintf(buf,"vrinit R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +void P_VRXOR(char *buf){sprintf(buf,"vrxor R, %s%s", COP2_REG_CTL[DECODE_FS], dest_string());} +//************************************END OF SPECIAL2 VUO TABLE**************************** diff --git a/pcsx2/DebugTools/DisVU0Micro.c b/pcsx2/DebugTools/DisVU0Micro.c new file mode 100644 index 0000000..f5d36dc --- /dev/null +++ b/pcsx2/DebugTools/DisVU0Micro.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-7s,", ostr, i) +#define dNameU(i) { char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); sprintf(ostr, "%s %-7s,", ostr, op); } + + +#define dCP2128f(i) sprintf(ostr, "%s w=%f z=%f y=%f x=%f (%s),", ostr, VU0.VF[i].f.w, VU0.VF[i].f.z, VU0.VF[i].f.y, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232x(i) sprintf(ostr, "%s x=%f (%s),", ostr, VU0.VF[i].f.x, disRNameCP2f[i]) +#define dCP232y(i) sprintf(ostr, "%s y=%f (%s),", ostr, VU0.VF[i].f.y, disRNameCP2f[i]) +#define dCP232z(i) sprintf(ostr, "%s z=%f (%s),", ostr, VU0.VF[i].f.z, disRNameCP2f[i]) +#define dCP232w(i) sprintf(ostr, "%s w=%f (%s),", ostr, VU0.VF[i].f.w, disRNameCP2f[i]) +#define dCP2ACCf() sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU0.ACC.f.w, VU0.ACC.f.z, VU0.ACC.f.y, VU0.ACC.f.x) +#define dCP232i(i) sprintf(ostr, "%s %8.8x (%s),", ostr, VU0.VI[i].UL, disRNameCP2i[i]) +#define dCP232iF(i) sprintf(ostr, "%s %f (%s),", ostr, VU0.VI[i].F, disRNameCP2i[i]) +#define dCP232f(i, j) sprintf(ostr, "%s Q %s=%f (%s),", ostr, CP2VFnames[j], VU0.VF[i].F[j], disRNameCP2f[i]) +#define dImm5() sprintf(ostr, "%s %d,", ostr, (code >> 6) & 0x1f) +#define dImm11() sprintf(ostr, "%s %d,", ostr, code & 0x7ff) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" +#include "VU.h" + +_disVUOpcodes(VU0); +_disVUTables(VU0); + diff --git a/pcsx2/DebugTools/DisVU1Micro.c b/pcsx2/DebugTools/DisVU1Micro.c new file mode 100644 index 0000000..fec3f27 --- /dev/null +++ b/pcsx2/DebugTools/DisVU1Micro.c @@ -0,0 +1,123 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Debug.h" +#include "VUmicro.h" + +char ostr[1024]; + +// Type deffinition of our functions +#define DisFInterface (u32 code, u32 pc) +#define DisFInterfaceT (u32, u32) +#define DisFInterfaceN (code, pc) + +typedef char* (*TdisR5900F)DisFInterface; + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + char* fn DisFInterface { \ + if( !CHECK_VU1REC ) sprintf (ostr, "%8.8x %8.8x:", pc, code); \ + else ostr[0] = 0; \ + b; /*ostr[(strlen(ostr) - 1)] = 0;*/ return ostr; \ + } + +//Lower/Upper instructions can use that.. +#define _Ft_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((code >> 6) & 0x1F) // The sa part of the instruction register + +#define dName(i) sprintf(ostr, "%s %-12s", ostr, i); \ + +#define dNameU(i) { \ + char op[256]; sprintf(op, "%s.%s%s%s%s", i, _X ? "x" : "", _Y ? "y" : "", _Z ? "z" : "", _W ? "w" : ""); \ + sprintf(ostr, "%s %-12s", ostr, op); \ +} + +#define dCP2128f(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%8.8x) z=%f (%8.8x) y=%f (%8.8xl) x=%f (%8.8x) (%s),", ostr, VU1.VF[i].f.w, VU1.VF[i].UL[3], VU1.VF[i].f.z, VU1.VF[i].UL[2], VU1.VF[i].f.y, VU1.VF[i].UL[1], VU1.VF[i].f.x, VU1.VF[i].UL[0], disRNameCP2f[i]); \ +} \ + +#define dCP232x(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s x=%f (%s),", ostr, VU1.VF[i].f.x, disRNameCP2f[i]); \ +} \ + +#define dCP232y(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s y=%f (%s),", ostr, VU1.VF[i].f.y, disRNameCP2f[i]); \ +} \ + +#define dCP232z(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s z=%f (%s),", ostr, VU1.VF[i].f.z, disRNameCP2f[i]); \ +} + +#define dCP232w(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2f[i]); \ + else sprintf(ostr, "%s w=%f (%s),", ostr, VU1.VF[i].f.w, disRNameCP2f[i]); \ +} + +#define dCP2ACCf() { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s ACC,", ostr); \ + else sprintf(ostr, "%s w=%f z=%f y=%f x=%f (ACC),", ostr, VU1.ACC.f.w, VU1.ACC.f.z, VU1.ACC.f.y, VU1.ACC.f.x); \ +} \ + +#define dCP232i(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %8.8x (%s),", ostr, VU1.VI[i].UL, disRNameCP2i[i]); \ +} + +#define dCP232iF(i) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s,", ostr, disRNameCP2i[i]); \ + else sprintf(ostr, "%s %f (%s),", ostr, VU1.VI[i].F, disRNameCP2i[i]); \ +} + +#define dCP232f(i, j) { \ + if( CHECK_VU1REC ) sprintf(ostr, "%s %s%s,", ostr, disRNameCP2f[i], CP2VFnames[j]); \ + else sprintf(ostr, "%s %s=%f (%s),", ostr, CP2VFnames[j], VU1.VF[i].F[j], disRNameCP2f[i]); \ +} + +#define dImm5() sprintf(ostr, "%s %d,", ostr, (s16)((code >> 6) & 0x10 ? 0xfff0 | ((code >> 6) & 0xf) : (code >> 6) & 0xf)) +#define dImm11() sprintf(ostr, "%s %d,", ostr, (s16)(code & 0x400 ? 0xfc00 | (code & 0x3ff) : code & 0x3ff)) +#define dImm15() sprintf(ostr, "%s %d,", ostr, ( ( code >> 10 ) & 0x7800 ) | ( code & 0x7ff )) + +#define _X ((code>>24) & 0x1) +#define _Y ((code>>23) & 0x1) +#define _Z ((code>>22) & 0x1) +#define _W ((code>>21) & 0x1) + +#define _Fsf_ ((code >> 21) & 0x03) +#define _Ftf_ ((code >> 23) & 0x03) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +extern char* disNULL DisFInterface; + +#include "DisVUmicro.h" +#include "DisVUops.h" + +_disVUOpcodes(VU1); +_disVUTables(VU1); + diff --git a/pcsx2/DebugTools/DisVUmicro.h b/pcsx2/DebugTools/DisVUmicro.h new file mode 100644 index 0000000..e2c5b9e --- /dev/null +++ b/pcsx2/DebugTools/DisVUmicro.h @@ -0,0 +1,209 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUTables(VU) \ + \ +/****************/ \ +/* LOWER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##LowerOP_T3_00_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MOVE , dis##VU##MI_LQI , dis##VU##MI_DIV , dis##VU##MI_MTIR, \ + dis##VU##MI_RNEXT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_MFP , dis##VU##MI_XTOP , dis##VU##MI_XGKICK, \ + dis##VU##MI_ESADD , dis##VU##MI_EATANxy, dis##VU##MI_ESQRT, dis##VU##MI_ESIN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_01_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_MR32 , dis##VU##MI_SQI , dis##VU##MI_SQRT , dis##VU##MI_MFIR, \ + dis##VU##MI_RGET , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , dis##VU##MI_XITOP, disNULL , \ + dis##VU##MI_ERSADD, dis##VU##MI_EATANxz, dis##VU##MI_ERSQRT, dis##VU##MI_EATAN, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_10_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_LQD , dis##VU##MI_RSQRT, dis##VU##MI_ILWR, \ + dis##VU##MI_RINIT , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ELENG , dis##VU##MI_ESUM , dis##VU##MI_ERCPR, dis##VU##MI_EEXP, \ +}; \ + \ +TdisR5900F dis##VU##LowerOP_T3_11_OPCODE[32] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , dis##VU##MI_SQD , dis##VU##MI_WAITQ, dis##VU##MI_ISWR, \ + dis##VU##MI_RXOR , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_ERLENG, disNULL , dis##VU##MI_WAITP, disNULL , \ +}; \ + \ +MakeDisF(dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_00_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_01_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_10_OPCODE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##LowerOP_T3_11, dis##VU##LowerOP_T3_11_OPCODE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##LowerOP_OPCODE[64] = { \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x10 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , /* 0x20 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##MI_IADD , dis##VU##MI_ISUB , dis##VU##MI_IADDI, disNULL , /* 0x30 */ \ + dis##VU##MI_IAND , dis##VU##MI_IOR , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##LowerOP_T3_00, dis##VU##LowerOP_T3_01, dis##VU##LowerOP_T3_10, dis##VU##LowerOP_T3_11, \ +}; \ + \ +MakeDisF(dis##VU##LowerOP, dis##VU##LowerOP_OPCODE[code & 0x3f] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroL[] = { \ + dis##VU##MI_LQ , dis##VU##MI_SQ , disNULL , disNULL, \ + dis##VU##MI_ILW , dis##VU##MI_ISW , disNULL , disNULL, \ + dis##VU##MI_IADDIU, dis##VU##MI_ISUBIU, disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##MI_FCEQ , dis##VU##MI_FCSET , dis##VU##MI_FCAND, dis##VU##MI_FCOR, /* 0x10 */ \ + dis##VU##MI_FSEQ , dis##VU##MI_FSSET , dis##VU##MI_FSAND, dis##VU##MI_FSOR, \ + dis##VU##MI_FMEQ , disNULL , dis##VU##MI_FMAND, dis##VU##MI_FMOR, \ + dis##VU##MI_FCGET , disNULL , disNULL , disNULL, \ + dis##VU##MI_B , dis##VU##MI_BAL , disNULL , disNULL, /* 0x20 */ \ + dis##VU##MI_JR , dis##VU##MI_JALR , disNULL , disNULL, \ + dis##VU##MI_IBEQ , dis##VU##MI_IBNE , disNULL , disNULL, \ + dis##VU##MI_IBLTZ , dis##VU##MI_IBGTZ , dis##VU##MI_IBLEZ, dis##VU##MI_IBGEZ, \ + disNULL , disNULL , disNULL , disNULL, /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + dis##VU##LowerOP , disNULL , disNULL , disNULL, /* 0x40*/ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x50 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x60 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, /* 0x70 */ \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ + disNULL , disNULL , disNULL , disNULL, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroLF, dis##VU##MicroL[code >> 25] DisFInterfaceN) \ + \ + \ +/****************/ \ +/* UPPER TABLES */ \ +/****************/ \ + \ +TdisR5900F dis##VU##_UPPER_FD_00_TABLE[32] = { \ + dis##VU##MI_ADDAx, dis##VU##MI_SUBx , dis##VU##MI_MADDAx, dis##VU##MI_MSUBAx, \ + dis##VU##MI_ITOF0, dis##VU##MI_FTOI0, dis##VU##MI_MULAx , dis##VU##MI_MULAq , \ + dis##VU##MI_ADDAq, dis##VU##MI_SUBAq, dis##VU##MI_ADDA , dis##VU##MI_SUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_01_TABLE[32] = { \ + dis##VU##MI_ADDAy , dis##VU##MI_SUBy , dis##VU##MI_MADDAy, dis##VU##MI_MSUBAy, \ + dis##VU##MI_ITOF4 , dis##VU##MI_FTOI4 , dis##VU##MI_MULAy , dis##VU##MI_ABS , \ + dis##VU##MI_MADDAq, dis##VU##MI_MSUBAq, dis##VU##MI_MADDA , dis##VU##MI_MSUBA , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_10_TABLE[32] = { \ + dis##VU##MI_ADDAz , dis##VU##MI_SUBz , dis##VU##MI_MADDAz, dis##VU##MI_MSUBAz, \ + dis##VU##MI_ITOF12, dis##VU##MI_FTOI12, dis##VU##MI_MULAz , dis##VU##MI_MULAi , \ + dis##VU##MI_ADDAi, dis##VU##MI_SUBAi , dis##VU##MI_MULA , dis##VU##MI_OPMULA, \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +TdisR5900F dis##VU##_UPPER_FD_11_TABLE[32] = { \ + dis##VU##MI_ADDAw , dis##VU##MI_SUBw , dis##VU##MI_MADDAw, dis##VU##MI_MSUBAw, \ + dis##VU##MI_ITOF15, dis##VU##MI_FTOI15, dis##VU##MI_MULAw , dis##VU##MI_CLIP , \ + dis##VU##MI_MADDAi, dis##VU##MI_MSUBAi, disNULL , dis##VU##MI_NOP , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ +}; \ + \ +MakeDisF(dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_00_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_01_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_10_TABLE[_Fd_] DisFInterfaceN) \ +MakeDisF(dis##VU##_UPPER_FD_11, dis##VU##_UPPER_FD_11_TABLE[_Fd_] DisFInterfaceN) \ + \ +TdisR5900F dis##VU##MicroU[] = { \ + dis##VU##MI_ADDx , dis##VU##MI_ADDy , dis##VU##MI_ADDz , dis##VU##MI_ADDw, \ + dis##VU##MI_SUBx , dis##VU##MI_SUBy , dis##VU##MI_SUBz , dis##VU##MI_SUBw, \ + dis##VU##MI_MADDx , dis##VU##MI_MADDy , dis##VU##MI_MADDz , dis##VU##MI_MADDw, \ + dis##VU##MI_MSUBx , dis##VU##MI_MSUBy , dis##VU##MI_MSUBz , dis##VU##MI_MSUBw, \ + dis##VU##MI_MAXx , dis##VU##MI_MAXy , dis##VU##MI_MAXz , dis##VU##MI_MAXw, /* 0x10 */ \ + dis##VU##MI_MINIx , dis##VU##MI_MINIy , dis##VU##MI_MINIz , dis##VU##MI_MINIw, \ + dis##VU##MI_MULx , dis##VU##MI_MULy , dis##VU##MI_MULz , dis##VU##MI_MULw, \ + dis##VU##MI_MULq , dis##VU##MI_MAXi , dis##VU##MI_MULi , dis##VU##MI_MINIi, \ + dis##VU##MI_ADDq , dis##VU##MI_MADDq , dis##VU##MI_ADDi , dis##VU##MI_MADDi, /* 0x20 */ \ + dis##VU##MI_SUBq , dis##VU##MI_MSUBq , dis##VU##MI_SUBi , dis##VU##MI_MSUBi, \ + dis##VU##MI_ADD , dis##VU##MI_MADD , dis##VU##MI_MUL , dis##VU##MI_MAX, \ + dis##VU##MI_SUB , dis##VU##MI_MSUB , dis##VU##MI_OPMSUB, dis##VU##MI_MINI, \ + disNULL , disNULL , disNULL , disNULL , /* 0x30 */ \ + disNULL , disNULL , disNULL , disNULL , \ + disNULL , disNULL , disNULL , disNULL , \ + dis##VU##_UPPER_FD_00, dis##VU##_UPPER_FD_01, dis##VU##_UPPER_FD_10, dis##VU##_UPPER_FD_11, \ +}; \ + \ + \ +MakeDisF(dis##VU##MicroUF, dis##VU##MicroU[code & 0x3f] DisFInterfaceN) \ + diff --git a/pcsx2/DebugTools/DisVUops.h b/pcsx2/DebugTools/DisVUops.h new file mode 100644 index 0000000..40cf978 --- /dev/null +++ b/pcsx2/DebugTools/DisVUops.h @@ -0,0 +1,197 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#define _disVUOpcodes(VU) \ + \ +/*****************/ \ +/* LOWER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_DIV, dName("DIV"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_SQRT, dName("SQRT"); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_RSQRT, dName("RSQRT"); dCP232f(_Fs_, _Fsf_); dCP232f(_Ft_, _Ftf_);) \ +MakeDisF(dis##VU##MI_IADDI, dName("IADDI"); dCP232i(_Ft_); dCP232i(_Fs_); dImm5();) \ +MakeDisF(dis##VU##MI_IADDIU, dName("IADDIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_IADD, dName("IADD"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IAND, dName("IAND"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_IOR, dName("IOR"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUB, dName("ISUB"); dCP232i(_Fd_); dCP232i(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ISUBIU, dName("ISUBIU"); dCP232i(_Ft_); dCP232i(_Fs_); dImm15();) \ +MakeDisF(dis##VU##MI_MOVE, if (_Fs_ == 0 && _Ft_ == 0) { dNameU("NOP"); } else { dNameU("MOVE"); dCP2128f(_Ft_); dCP2128f(_Fs_); }) \ +MakeDisF(dis##VU##MI_MFIR, dNameU("MFIR"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_MTIR, dNameU("MTIR"); dCP232i(_Ft_); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_MR32, dNameU("MR32"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_LQ, dNameU("LQ"); dCP2128f(_Ft_); dCP232i(_Fs_); dImm11();) \ +MakeDisF(dis##VU##MI_LQD, dNameU("LQD"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LQI, dNameU("LQI"); dCP2128f(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_SQ, dNameU("SQ"); dCP2128f(_Fs_); dCP232i(_Ft_); dImm11(); ) \ +MakeDisF(dis##VU##MI_SQD, dNameU("SQD"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_SQI, dNameU("SQI"); dCP2128f(_Fs_); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_ILW, dNameU("ILW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISW, dNameU("ISW"); dCP232i(_Ft_); dImm11(); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ILWR, dNameU("ILWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_ISWR, dNameU("ISWR"); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_LOI, dName("LOI"); ) \ +MakeDisF(dis##VU##MI_RINIT, dNameU("RINIT"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_RGET, dNameU("RGET"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RNEXT, dNameU("RNEXT"); dCP232i(REG_R); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_RXOR, dNameU("RXOR"); dCP232i(REG_R); dCP232f(_Fs_, _Fsf_);) \ +MakeDisF(dis##VU##MI_WAITQ, dName("WAITQ"); ) \ +MakeDisF(dis##VU##MI_FSAND, dName("FSAND"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff); ) \ +MakeDisF(dis##VU##MI_FSEQ, dName("FSEQ"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSOR, dName("FSOR"); dCP232i(_Ft_); dCP232i(REG_STATUS_FLAG); sprintf(ostr, "%s %.3x,", ostr, code&0xfff);) \ +MakeDisF(dis##VU##MI_FSSET, dName("FSSET"); dCP232i(REG_STATUS_FLAG);) \ +MakeDisF(dis##VU##MI_FMAND, dName("FMAND"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMEQ, dName("FMEQ"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FMOR, dName("FMOR"); dCP232i(_Ft_); dCP232i(REG_MAC_FLAG); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_FCAND, dName("FCAND"); dCP232i(1); sprintf(ostr, "%s %8.8x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCEQ, dName("FCEQ"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCOR, dName("FCOR"); dCP232i(1); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_FCSET, dName("FCSET"); dCP232i(REG_CLIP_FLAG); sprintf(ostr, "%s %.6x,", ostr, code&0xffffff); ) \ +MakeDisF(dis##VU##MI_FCGET, dName("FCGET"); dCP232i(_Ft_); dCP232i(REG_CLIP_FLAG);) \ +MakeDisF(dis##VU##MI_IBEQ, dName("IBEQ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGEZ, dName("IBEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBGTZ, dName("IBGTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLEZ, dName("IBLEZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBLTZ, dName("IBLTZ"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_IBNE, dName("IBNE"); dImm11(); dCP232i(_Ft_); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_B, dName("B"); dImm11();) \ +MakeDisF(dis##VU##MI_BAL, dName("BAL"); dImm11(); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_JR, dName("JR"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_JALR, dName("JALR"); dCP232i(_Ft_); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_MFP, dNameU("MFP"); dCP2128f(_Ft_); dCP232i(REG_P);) \ +MakeDisF(dis##VU##MI_WAITP, dName("WAITP"); ) \ +MakeDisF(dis##VU##MI_ESADD, dName("ESADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ERSADD, dName("ERSADD"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ELENG, dName("ELENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERLENG, dName("ERLENG"); dCP2128f(_Fs_); ) \ +MakeDisF(dis##VU##MI_EATANxy, dName("EATANxy"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_EATANxz, dName("EATANxz"); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ESUM, dName("ESUM"); dCP232i(_Fs_); ) \ +MakeDisF(dis##VU##MI_ERCPR, dName("ERCPR"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESQRT, dName("ESQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ERSQRT, dName("ERSQRT"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_ESIN, dName("ESIN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EATAN, dName("EATAN"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_EEXP, dName("EEXP"); dCP232f(_Fs_, _Fsf_); ) \ +MakeDisF(dis##VU##MI_XITOP, dName("XITOP"); dCP232i(_Ft_);) \ +MakeDisF(dis##VU##MI_XGKICK, dName("XGKICK"); dCP232i(_Fs_);) \ +MakeDisF(dis##VU##MI_XTOP, dName("XTOP"); dCP232i(_Ft_);) \ + \ + \ +/*****************/ \ +/* UPPER OPCODES */ \ +/*****************/ \ + \ +MakeDisF(dis##VU##MI_ABS, dNameU("ABS"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ADD, dNameU("ADD"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDi, dNameU("ADDi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDq, dNameU("ADDq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDx, dNameU("ADDx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDy, dNameU("ADDy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDz, dNameU("ADDz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDw, dNameU("ADDw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDA, dNameU("ADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAi, dNameU("ADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_ADDAq, dNameU("ADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_ADDAx, dNameU("ADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAy, dNameU("ADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAz, dNameU("ADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_ADDAw, dNameU("ADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUB, dNameU("SUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBi, dNameU("SUBi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBq, dNameU("SUBq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBx, dNameU("SUBx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBy, dNameU("SUBy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBz, dNameU("SUBz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBw, dNameU("SUBw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBA, dNameU("SUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAi, dNameU("SUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_SUBAq, dNameU("SUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_SUBAx, dNameU("SUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAy, dNameU("SUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAz, dNameU("SUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_SUBAw, dNameU("SUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MUL, dNameU("MUL"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULi, dNameU("MULi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULq, dNameU("MULq"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULx, dNameU("MULx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULy, dNameU("MULy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULz, dNameU("MULz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULw, dNameU("MULw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MULA, dNameU("MULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAi, dNameU("MULAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MULAq, dNameU("MULAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MULAx, dNameU("MULAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAy, dNameU("MULAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAz, dNameU("MULAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MULAw, dNameU("MULAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADD, dNameU("MADD"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDi, dNameU("MADDi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDq, dNameU("MADDq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDx, dNameU("MADDx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDy, dNameU("MADDy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDz, dNameU("MADDz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDw, dNameU("MADDw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDA, dNameU("MADDA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAi, dNameU("MADDAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MADDAq, dNameU("MADDAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MADDAx, dNameU("MADDAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAy, dNameU("MADDAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAz, dNameU("MADDAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MADDAw, dNameU("MADDAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUB, dNameU("MSUB"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBi, dNameU("MSUBi"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBq, dNameU("MSUBq"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBx, dNameU("MSUBx"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBy, dNameU("MSUBy"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBz, dNameU("MSUBz"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBw, dNameU("MSUBw"); dCP2128f(_Fd_); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBA, dNameU("MSUBA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAi, dNameU("MSUBAi"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MSUBAq, dNameU("MSUBAq"); dCP2ACCf(); dCP2128f(_Fs_); dCP232iF(REG_Q);) \ +MakeDisF(dis##VU##MI_MSUBAx, dNameU("MSUBAx"); dCP2ACCf(); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAy, dNameU("MSUBAy"); dCP2ACCf(); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAz, dNameU("MSUBAz"); dCP2ACCf(); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MSUBAw, dNameU("MSUBAw"); dCP2ACCf(); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MAX, dNameU("MAX"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXi, dNameU("MAXi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MAXx, dNameU("MAXx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXy, dNameU("MAXy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXz, dNameU("MAXz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MAXw, dNameU("MAXw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_MINI, dNameU("MINI"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIi, dNameU("MINIi"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232iF(REG_I);) \ +MakeDisF(dis##VU##MI_MINIx, dNameU("MINIx"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232x(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIy, dNameU("MINIy"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232y(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIz, dNameU("MINIz"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232z(_Ft_);) \ +MakeDisF(dis##VU##MI_MINIw, dNameU("MINIw"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP232w(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMULA, dNameU("OPMULA"); dCP2ACCf(); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_OPMSUB, dNameU("OPMSUB"); dCP2128f(_Fd_); dCP2128f(_Fs_); dCP2128f(_Ft_);) \ +MakeDisF(dis##VU##MI_NOP, dName("NOP");) \ +MakeDisF(dis##VU##MI_FTOI0, dNameU("FTOI0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI4, dNameU("FTOI4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI12, dNameU("FTOI12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_FTOI15, dNameU("FTOI15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF0, dNameU("ITOF0"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF4, dNameU("ITOF4"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF12, dNameU("ITOF12"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_ITOF15, dNameU("ITOF15"); dCP2128f(_Ft_); dCP2128f(_Fs_);) \ +MakeDisF(dis##VU##MI_CLIP, dNameU("CLIP"); dCP2128f(_Fs_); dCP232w(_Ft_);) \ + diff --git a/pcsx2/DebugTools/Makefile.am b/pcsx2/DebugTools/Makefile.am new file mode 100644 index 0000000..8d6763c --- /dev/null +++ b/pcsx2/DebugTools/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I@srcdir@/../ +noinst_LIBRARIES = libDebugTools.a + +libDebugTools_a_SOURCES = \ +cpuopsDebug.c Debug.h.bak DisR3000asm.c DisVU0Micro.c DisVUops.h \ +cpuopsDebug.h DisASM.h DisR5900asm.c DisVU1Micro.c \ +Debug.h DisR3000A.c DisR5900.c DisVUmicro.h diff --git a/pcsx2/DebugTools/cpuopsDebug.c b/pcsx2/DebugTools/cpuopsDebug.c new file mode 100644 index 0000000..99d6baf --- /dev/null +++ b/pcsx2/DebugTools/cpuopsDebug.c @@ -0,0 +1,1063 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "Debug.h" +#include "cpuopsDebug.h" + +void UpdateR5900op() +{ + FILE *fp; + fp=fopen("cpuops.txt", "wt"); + fprintf(fp, "------------\n"); + fprintf(fp, "--R5900ops--\n"); + fprintf(fp, "------------\n"); + if(L_ADD>0) fprintf(fp, "Add %d\n", L_ADD); + if(L_ADDI>0) fprintf(fp, "Addi %d\n", L_ADDI); + if(L_ADDIU>0) fprintf(fp, "Addiu %d\n", L_ADDIU); + if(L_ADDU>0) fprintf(fp, "Addu %d\n", L_ADDU); + if(L_AND>0) fprintf(fp, "And %d\n", L_AND); + if(L_ANDI>0) fprintf(fp, "Andi %d\n", L_ANDI); + if(L_BEQ>0) fprintf(fp, "Beq %d\n", L_BEQ); + if(L_BEQL>0) fprintf(fp, "Beql %d\n", L_BEQL); + if(L_BGEZ>0) fprintf(fp, "Bgez %d\n", L_BGEZ); + if(L_BGEZAL>0) fprintf(fp, "Bgezal %d\n", L_BGEZAL); + if(L_BGEZALL>0) fprintf(fp, "Bgezall %d\n", L_BGEZALL); + if(L_BGEZL>0) fprintf(fp, "Bgezl %d\n", L_BGEZL); + if( L_BGTZ>0) fprintf(fp, "Bgtz %d\n", L_BGTZ); + if( L_BGTZL>0) fprintf(fp, "Bgtzl %d\n", L_BGTZL); + if(L_BLEZ>0) fprintf(fp, "Blez %d\n", L_BLEZ); + if(L_BLEZL>0) fprintf(fp, "blezl %d\n", L_BLEZL); + if(L_BLTZ>0) fprintf(fp, "bltz %d\n", L_BLTZ); + if(L_BLTZAL>0) fprintf(fp, "bltzal %d\n", L_BLTZAL); + if(L_BLTZALL>0) fprintf(fp, "bltzall %d\n", L_BLTZALL); + if(L_BLTZL>0) fprintf(fp, "bltzl %d\n", L_BLTZL); + if(L_BNE>0) fprintf(fp, "bne %d\n", L_BNE); + if(L_BNEL>0) fprintf(fp, "bnel %d\n", L_BNEL); + if(L_BREAK>0) fprintf(fp, "break %d\n", L_BREAK); + if(L_CACHE>0) fprintf(fp, "cache %d\n", L_CACHE); + if(L_DADD>0) fprintf(fp, "dadd %d\n", L_DADD); + if(L_DADDI>0) fprintf(fp, "daddi %d\n", L_DADDI); + if(L_DADDIU>0) fprintf(fp, "daddiu %d\n", L_DADDIU); + if(L_DADDU>0) fprintf(fp, "daddu %d\n", L_DADDU); + if(L_DIV>0) fprintf(fp, "div %d\n", L_DIV); + if(L_DIVU>0) fprintf(fp, "divu %d\n", L_DIVU); + if(L_DSLL>0) fprintf(fp, "dsll %d\n", L_DSLL); + if(L_DSLL32>0) fprintf(fp, "dsll32 %d\n", L_DSLL32); + if(L_DSLLV>0) fprintf(fp, "dsllv %d\n", L_DSLLV); + if(L_DSRA>0) fprintf(fp, "dsra %d\n", L_DSRA); + if(L_DSRA32>0) fprintf(fp, "dsra32 %d\n", L_DSRA32); + if(L_DSRAV>0) fprintf(fp, "dsrav %d\n", L_DSRAV); + if(L_DSRL>0) fprintf(fp, "dsrl %d\n", L_DSRL); + if(L_DSRL32>0) fprintf(fp, "dsr32 %d\n", L_DSRL32); + if(L_DSRLV>0) fprintf(fp, "dsrlv %d\n", L_DSRLV); + if(L_DSUB>0) fprintf(fp, "dsub %d\n", L_DSUB); + if(L_DSUBU>0) fprintf(fp, "dsubu %d\n", L_DSUBU); + if(L_J>0) fprintf(fp, "j %d\n", L_J); + if(L_JAL>0) fprintf(fp, "jal %d\n", L_JAL); + if(L_JALR>0) fprintf(fp, "jalr %d\n", L_JALR); + if(L_JR>0) fprintf(fp, "jr %d\n", L_JR); + if(L_LB>0) fprintf(fp, "lb %d\n", L_LB); + if(L_LBU>0) fprintf(fp, "lbu %d\n", L_LBU); + if(L_LD>0) fprintf(fp, "ld %d\n", L_LD); + if(L_LDL>0) fprintf(fp, "ldl %d\n", L_LDL); + if(L_LDR>0) fprintf(fp, "ldr %d\n", L_LDR); + if(L_LH>0) fprintf(fp, "lh %d\n", L_LH); + if(L_LHU>0) fprintf(fp, "lhu %d\n", L_LHU); + if(L_LQ>0) fprintf(fp, "lq %d\n", L_LQ); + if(L_LUI>0) fprintf(fp, "lui %d\n", L_LUI); + if(L_LW>0) fprintf(fp, "lw %d\n", L_LW); + if(L_LWL>0) fprintf(fp, "lwl %d\n", L_LWL); + if(L_LWR>0) fprintf(fp, "lwr %d\n", L_LWR); + if(L_LWU>0) fprintf(fp, "lwu %d\n", L_LWU); + if(L_MFHI>0) fprintf(fp, "mfhi %d\n", L_MFHI); + if(L_MFLO>0) fprintf(fp, "mflo %d\n", L_MFLO); + if(L_MFSA>0) fprintf(fp, "mfsa %d\n", L_MFSA); + if(L_MOVN>0) fprintf(fp, "movn %d\n", L_MOVN); + if(L_MOVZ>0) fprintf(fp, "movz %d\n", L_MOVZ); + if(L_MTHI>0) fprintf(fp, "mthi %d\n", L_MTHI); + if(L_MTLO>0) fprintf(fp, "mtlo %d\n", L_MTLO); + if(L_MTSA>0) fprintf(fp, "mtsa %d\n", L_MTSA); + if(L_MTSAB>0) fprintf(fp, "mtsab %d\n", L_MTSAB); + if(L_MTSAH>0) fprintf(fp, "mtsah %d\n", L_MTSAH); + if(L_MULT>0) fprintf(fp, "mult %d\n", L_MULT); + if(L_MULTU>0) fprintf(fp, "multu %d\n", L_MULTU); + if(L_NOR>0) fprintf(fp, "nor %d\n", L_NOR); + if(L_OR>0) fprintf(fp, "or %d\n", L_OR); + if(L_ORI>0) fprintf(fp, "ori %d\n", L_ORI); + if(L_PREF>0) fprintf(fp, "pref %d\n", L_PREF); + if(L_SB>0) fprintf(fp, "sb %d\n", L_SB); + if(L_SD>0) fprintf(fp, "sd %d\n", L_SD); + if(L_SDL>0) fprintf(fp, "sdl %d\n", L_SDL); + if(L_SDR>0) fprintf(fp, "sdr %d\n", L_SDR); + if(L_SH>0) fprintf(fp, "sh %d\n", L_SH); + if(L_SLL>0) fprintf(fp, "sll %d\n", L_SLL); + if(L_SLLV>0) fprintf(fp, "sllv %d\n", L_SLLV); + if(L_SLT>0) fprintf(fp, "slt %d\n", L_SLT); + if(L_SLTI>0) fprintf(fp, "slti %d\n", L_SLTI); + if(L_SLTIU>0) fprintf(fp, "sltiu %d\n", L_SLTIU); + if(L_SLTU>0) fprintf(fp, "sltu %d\n", L_SLTU); + if(L_SQ>0) fprintf(fp, "sq %d\n", L_SQ); + if(L_SRA>0) fprintf(fp, "sra %d\n", L_SRA); + if(L_SRAV>0) fprintf(fp, "srav %d\n", L_SRAV); + if(L_SRL>0) fprintf(fp, "srl %d\n", L_SRL); + if(L_SRLV>0) fprintf(fp, "srlv %d\n", L_SRLV); + if(L_SUB>0) fprintf(fp, "sub %d\n", L_SUB); + if(L_SUBU>0) fprintf(fp, "subu %d\n", L_SUBU); + if(L_SW>0) fprintf(fp, "sw %d\n", L_SW); + if(L_SWL>0) fprintf(fp, "swl %d\n", L_SWL); + if(L_SWR>0) fprintf(fp, "swr %d\n", L_SWR); + if(L_SYNC>0) fprintf(fp, "sync %d\n", L_SYNC); + if(L_SYSCALL>0) fprintf(fp, "syscall %d\n", L_SYSCALL); + if(L_TEQ>0) fprintf(fp, "teq %d\n", L_TEQ); + if(L_TEQI>0) fprintf(fp, "teqi %d\n", L_TEQI); + if(L_TGE>0) fprintf(fp, "tge %d\n", L_TGE); + if(L_TGEI>0) fprintf(fp, "tgei %d\n", L_TGEI); + if(L_TGEIU>0) fprintf(fp, "tgeiu %d\n", L_TGEIU); + if(L_TGEU>0) fprintf(fp, "tgeu %d\n", L_TGEU); + if(L_TLT>0) fprintf(fp, "tlt %d\n", L_TLT); + if(L_TLTI>0) fprintf(fp, "tlti %d\n", L_TLTI); + if(L_TLTIU>0) fprintf(fp, "tltiu %d\n", L_TLTIU); + if(L_TLTU>0) fprintf(fp, "tltu %d\n", L_TLTU); + if(L_TNE>0) fprintf(fp, "tne %d\n", L_TNE); + if(L_TNEI>0) fprintf(fp, "tnei %d\n", L_TNEI); + if(L_XOR>0) fprintf(fp, "xor %d\n", L_XOR); + if(L_XORI>0) fprintf(fp, "xori %d\n", L_XORI); + fprintf(fp, "------------\n"); + fprintf(fp, "--MMI ops--\n"); + fprintf(fp, "------------\n"); + if(L_DIV1>0) fprintf(fp, "div1 %d\n", L_DIV1); + if(L_DIVU1>0) fprintf(fp, "divu1 %d\n", L_DIVU1); + if(L_MADD>0) fprintf(fp, "madd %d\n", L_MADD); + if(L_MADD1>0) fprintf(fp, "madd1 %d\n", L_MADD1); + if(L_MADDU>0) fprintf(fp, "maddu %d\n", L_MADDU); + if(L_MADDU1>0) fprintf(fp, "maddu1 %d\n", L_MADDU1); + if(L_MFHI1>0) fprintf(fp, "mfhi1 %d\n", L_MFHI1); + if(L_MFLO1>0) fprintf(fp, "mflo1 %d\n", L_MFLO1); + if(L_MTHI1>0) fprintf(fp, "mthi1 %d\n", L_MTHI1); + if(L_MTLO1>0) fprintf(fp, "mtlo1 %d\n", L_MTLO1); + if(L_MULT1>0) fprintf(fp, "mult1 %d\n", L_MULT1); + if(L_MULTU1>0) fprintf(fp, "multu1 %d\n", L_MULTU1); + if(L_PABSH>0) fprintf(fp, "pabsh %d\n", L_PABSH); + if(L_PABSW>0) fprintf(fp, "pabsw %d\n", L_PABSW); + if(L_PADDB>0) fprintf(fp, "paddb %d\n", L_PADDB); + if(L_PADDH>0) fprintf(fp, "paddh %d\n", L_PADDH); + if(L_PADDSB>0) fprintf(fp, "paddsb %d\n", L_PADDSB); + if(L_PADDSH>0) fprintf(fp, "paddsh %d\n", L_PADDSH); + if(L_PADDSW>0) fprintf(fp, "paddsw %d\n", L_PADDSW); + if(L_PADDUB>0) fprintf(fp, "paddub %d\n", L_PADDUB); + if(L_PADDUH>0) fprintf(fp, "padduh %d\n", L_PADDUH); + if(L_PADDUW>0) fprintf(fp, "padduw %d\n", L_PADDUW); + if(L_PADDW>0) fprintf(fp, "paddw %d\n", L_PADDW); + if(L_PADSBH>0) fprintf(fp, "padsbh %d\n", L_PADSBH); + if(L_PAND>0) fprintf(fp, "pand %d\n", L_PAND); + if(L_PCEQB>0) fprintf(fp, "pceqb %d\n", L_PCEQB); + if(L_PCEQH>0) fprintf(fp, "pceqh %d\n", L_PCEQH); + if(L_PCEQW>0) fprintf(fp, "pceqw %d\n", L_PCEQW); + if(L_PCGTB>0) fprintf(fp, "pcgtb %d\n", L_PCGTB); + if(L_PCGTH>0) fprintf(fp, "pcgth %d\n", L_PCGTH); + if(L_PCGTW>0) fprintf(fp, "pcgtw %d\n", L_PCGTW); + if(L_PCPYH>0) fprintf(fp, "pcpyh %d\n", L_PCPYH); + if(L_PCPYLD>0) fprintf(fp, "pcpyld %d\n", L_PCPYLD); + if(L_PCPYUD>0) fprintf(fp, "pcpyud %d\n", L_PCPYUD); + if(L_PDIVBW>0) fprintf(fp, "pdivbw %d\n", L_PDIVBW); + if(L_PDIVUW>0) fprintf(fp, "pdivuw %d\n", L_PDIVUW); + if(L_PDIVW>0) fprintf(fp, "pdivw %d\n", L_PDIVW); + if(L_PEXCH>0) fprintf(fp, "pexch %d\n", L_PEXCH); + if(L_PEXCW>0) fprintf(fp, "pexcw %d\n", L_PEXCW); + if(L_PEXEH>0) fprintf(fp, "pexeh %d\n", L_PEXEH); + if(L_PEXEW>0) fprintf(fp, "pexew %d\n", L_PEXEW); + if(L_PEXT5>0) fprintf(fp, "pext5 %d\n", L_PEXT5); + if(L_PEXTLB>0) fprintf(fp, "pextlb %d\n", L_PEXTLB); + if(L_PEXTLH>0) fprintf(fp, "pextlh %d\n", L_PEXTLH); + if(L_PEXTLW>0) fprintf(fp, "pextlw %d\n", L_PEXTLW); + if(L_PEXTUB>0) fprintf(fp, "pextub %d\n", L_PEXTUB); + if(L_PEXTUH>0) fprintf(fp, "pextuh %d\n", L_PEXTUH); + if(L_PEXTUW>0) fprintf(fp, "pextuw %d\n", L_PEXTUW); + if(L_PHMADH>0) fprintf(fp, "phmadh %d\n", L_PHMADH); + if(L_PHMSBH>0) fprintf(fp, "phmsbh %d\n", L_PHMSBH); + if(L_PINTEH>0) fprintf(fp, "pinteh %d\n", L_PINTEH); + if(L_PINTH>0) fprintf(fp, "pinth %d\n", L_PINTH); + if(L_PLZCW>0) fprintf(fp, "plzcw %d\n", L_PLZCW); + if(L_PMADDH>0) fprintf(fp, "pmaddh %d\n", L_PMADDH); + if(L_PMADDUW>0) fprintf(fp, "pmadduw %d\n", L_PMADDUW); + if(L_PMADDW>0) fprintf(fp, "pmaddw %d\n", L_PMADDW); + if(L_PMAXH>0) fprintf(fp, "pmaxh %d\n", L_PMAXH); + if(L_PMAXW>0) fprintf(fp, "pmaxw %d\n", L_PMAXW); + if(L_PMFHI>0) fprintf(fp, "pmfhi %d\n", L_PMFHI); + if(L_PMFHL>0) fprintf(fp, "pmfhl %d\n", L_PMFHL); + if(L_PMFLO>0) fprintf(fp, "pmflo %d\n", L_PMFLO); + if(L_PMINH>0) fprintf(fp, "pminh %d\n", L_PMINH); + if(L_PMINW>0) fprintf(fp, "pminw %d\n", L_PMINW); + if(L_PMSUBH>0) fprintf(fp, "pmsubh %d\n", L_PMSUBH); + if(L_PMSUBW>0) fprintf(fp, "pmsubw %d\n", L_PMSUBW); + if(L_PMTHI>0) fprintf(fp, "pmthi %d\n", L_PMTHI); + if(L_PMTHL>0) fprintf(fp, "pmthl %d\n", L_PMTHL); + if(L_PMTLO>0) fprintf(fp, "pmtlo %d\n", L_PMTLO); + if(L_PMULTH>0) fprintf(fp, "pmulth %d\n", L_PMULTH); + if(L_PMULTUW>0) fprintf(fp, "pmultuw %d\n", L_PMULTUW); + if(L_PMULTW>0) fprintf(fp, "pmultw %d\n", L_PMULTW); + if(L_PNOR>0) fprintf(fp, "pnor %d\n", L_PNOR); + if(L_POR>0) fprintf(fp, "por %d\n", L_POR); + if(L_PPAC5>0) fprintf(fp, "ppac5 %d\n", L_PPAC5); + if(L_PPACB>0) fprintf(fp, "ppacb %d\n", L_PPACB); + if(L_PPACH>0) fprintf(fp, "ppach %d\n", L_PPACH); + if(L_PPACW>0) fprintf(fp, "ppacw %d\n", L_PPACW); + if(L_PREVH>0) fprintf(fp, "prevh %d\n", L_PREVH); + if(L_PROT3W>0) fprintf(fp, "prot3w %d\n", L_PROT3W); + if(L_PSLLH>0) fprintf(fp, "psllh %d\n", L_PSLLH); + if(L_PSLLVW>0) fprintf(fp, "psllvw %d\n", L_PSLLVW); + if(L_PSLLW>0) fprintf(fp, "psllw %d\n", L_PSLLW); + if(L_PSRAH>0) fprintf(fp, "psrah %d\n", L_PSRAH); + if(L_PSRAVW>0) fprintf(fp, "psravw %d\n", L_PSRAVW); + if(L_PSRAW>0) fprintf(fp, "psraw %d\n", L_PSRAW); + if(L_PSRLH>0) fprintf(fp, "psrlh %d\n", L_PSRLH); + if(L_PSRLVW>0) fprintf(fp, "psrlvw %d\n", L_PSRLVW); + if(L_PSRLW>0) fprintf(fp, "psrlw %d\n", L_PSRLW); + if(L_PSUBB>0) fprintf(fp, "psubb %d\n", L_PSUBB); + if(L_PSUBH>0) fprintf(fp, "psubh %d\n", L_PSUBH); + if(L_PSUBSB>0) fprintf(fp, "psubsb %d\n", L_PSUBSB); + if(L_PSUBSH>0) fprintf(fp, "psubsh %d\n", L_PSUBSH); + if(L_PSUBSW>0) fprintf(fp, "psubsw %d\n", L_PSUBSW); + if(L_PSUBUB>0) fprintf(fp, "psubub %d\n", L_PSUBUB); + if(L_PSUBUH>0) fprintf(fp, "psubuh %d\n", L_PSUBUH); + if(L_PSUBUW>0) fprintf(fp, "psubuw %d\n", L_PSUBUW); + if(L_PSUBW>0) fprintf(fp, "psubw %d\n", L_PSUBW); + if(L_PXOR>0) fprintf(fp, "pxor %d\n", L_PXOR); + if(L_QFSRV>0) fprintf(fp, "qfsrv %d\n", L_QFSRV); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP0 ops--\n"); + fprintf(fp, "------------\n"); + if(L_BC0F>0) fprintf(fp, "bc0f %d\n", L_BC0F); + if(L_BC0FL>0) fprintf(fp, "bc0fl %d\n", L_BC0FL); + if(L_BC0T>0) fprintf(fp, "bc0t %d\n", L_BC0T); + if(L_BC0TL>0) fprintf(fp, "bc0tl %d\n", L_BC0TL); + if(L_DI>0) fprintf(fp, "di %d\n", L_DI); + if(L_EI>0) fprintf(fp, "ei %d\n", L_EI); + if(L_ERET>0) fprintf(fp, "eret %d\n", L_ERET); + if(L_MTC0>0) fprintf(fp, "mtc0 %d\n", L_MTC0); + if(L_TLBP>0) fprintf(fp, "tlbp %d\n", L_TLBP); + if(L_TLBR>0) fprintf(fp, "tlbr %d\n", L_TLBR); + if(L_TLBWI>0) fprintf(fp, "tlbwi %d\n", L_TLBWI); + if(L_TLBWR>0) fprintf(fp, "tlbwr %d\n", L_TLBWR); + if(L_MFC0>0) fprintf(fp, "mfc0 %d\n", L_MFC0); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP1 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LWC1>0) fprintf(fp, "lwc1 %d\n", L_LWC1); + if(L_SWC1>0) fprintf(fp, "swc1 %d\n", L_SWC1); + if(L_ABS_S>0) fprintf(fp, "abs_s %d\n", L_ABS_S); + if(L_ADD_S>0) fprintf(fp, "add_s %d\n", L_ADD_S); + if(L_ADDA_S>0) fprintf(fp, "adda_s %d\n", L_ADDA_S); + if(L_BC1F>0) fprintf(fp, "bc1f %d\n", L_BC1F); + if(L_BC1FL>0) fprintf(fp, "bc1fl %d\n", L_BC1FL); + if(L_BC1T>0) fprintf(fp, "bc1t %d\n", L_BC1T); + if(L_BC1TL>0) fprintf(fp, "bc1tl %d\n", L_BC1TL); + if(L_C_EQ>0) fprintf(fp, "c_eq %d\n", L_C_EQ); + if(L_C_F>0) fprintf(fp, "c_f %d\n", L_C_F); + if(L_C_LE>0) fprintf(fp, "c_le %d\n", L_C_LE); + if(L_C_LT>0) fprintf(fp, "c_lt %d\n", L_C_LT); + if(L_CFC1>0) fprintf(fp, "cfc1 %d\n", L_CFC1); + if(L_CTC1>0) fprintf(fp, "ctc1 %d\n", L_CTC1); + if(L_CVT_S>0) fprintf(fp, "cvt_s %d\n", L_CVT_S); + if(L_CVT_W>0) fprintf(fp, "cvt_w %d\n", L_CVT_W); + if(L_DIV_S>0) fprintf(fp, "div_s %d\n", L_DIV_S); + if(L_MADD_S>0) fprintf(fp, "madd_s %d\n", L_MADD_S); + if(L_MADDA_S>0) fprintf(fp, "madda_s %d\n", L_MADDA_S); + if(L_MAX_S>0) fprintf(fp, "max_s %d\n", L_MAX_S); + if(L_MFC1>0) fprintf(fp, "mfc1 %d\n", L_MFC1); + if(L_MIN_S>0) fprintf(fp, "min_s %d\n", L_MIN_S); + if(L_MOV_S>0) fprintf(fp, "mov_s %d\n", L_MOV_S); + if(L_MSUB_S>0) fprintf(fp, "msub_s %d\n", L_MSUB_S); + if(L_MSUBA_S>0) fprintf(fp, "msuba_s %d\n", L_MSUBA_S); + if(L_MTC1>0) fprintf(fp, "mtc1 %d\n", L_MTC1); + if(L_MUL_S>0) fprintf(fp, "mul_s %d\n", L_MUL_S); + if(L_MULA_S>0) fprintf(fp, "mula_s %d\n", L_MULA_S); + if(L_NEG_S>0) fprintf(fp, "neg_s %d\n", L_NEG_S); + if(L_RSQRT_S>0) fprintf(fp, "rsqrt_s %d\n", L_RSQRT_S); + if(L_SQRT_S>0) fprintf(fp, "sqrt_s %d\n", L_SQRT_S); + if(L_SUB_S>0) fprintf(fp, "sub_s %d\n", L_SUB_S); + if(L_SUBA_S>0) fprintf(fp, "suba_s %d\n", L_SUBA_S); + fprintf(fp, "------------\n"); + fprintf(fp, "--COP2 ops--\n"); + fprintf(fp, "------------\n"); + if(L_LQC2>0) fprintf(fp, "lqc2 %d\n", L_LQC2); + if(L_SQC2>0) fprintf(fp, "sqc2 %d\n", L_SQC2); + if(L_BC2F>0) fprintf(fp, "bc2f %d\n", L_BC2F); + if(L_BC2FL>0) fprintf(fp, "bc2fl %d\n", L_BC2FL); + if(L_BC2T>0) fprintf(fp, "bc2t %d\n", L_BC2T); + if(L_BC2TL>0) fprintf(fp, "bc2tl %d\n", L_BC2TL); + if(L_CFC2>0) fprintf(fp, "cfc2 %d\n", L_CFC2); + if(L_CTC2>0) fprintf(fp, "ctc2 %d\n", L_CTC2); + if(L_QMFC2>0) fprintf(fp, "qmfc2 %d\n", L_QMFC2); + if(L_QMTC2>0) fprintf(fp, "qmtc2 %d\n", L_QMTC2); + if(L_VABS>0) fprintf(fp, "vabs %d\n", L_VABS); + if(L_VADD>0) fprintf(fp, "vadd %d\n", L_VADD); + if(L_VADDA>0) fprintf(fp, "vadda %d\n", L_VADDA); + if(L_VADDAi>0) fprintf(fp, "vaddai %d\n", L_VADDAi); + if(L_VADDAq>0) fprintf(fp, "vaddaq %d\n", L_VADDAq); + if(L_VADDAw>0) fprintf(fp, "vaddaw %d\n", L_VADDAw); + if(L_VADDAx>0) fprintf(fp, "vaddax %d\n", L_VADDAx); + if(L_VADDAy>0) fprintf(fp, "vadday %d\n", L_VADDAy); + if(L_VADDAz>0) fprintf(fp, "vaddaz %d\n", L_VADDAz); + if(L_VADDi>0) fprintf(fp, "vaddi %d\n", L_VADDi); + if(L_VADDq>0) fprintf(fp, "vaddq %d\n", L_VADDq); + if(L_VADDw>0) fprintf(fp, "vaddw %d\n", L_VADDw); + if(L_VADDx>0) fprintf(fp, "vaddx %d\n", L_VADDx); + if(L_VADDy>0) fprintf(fp, "vaddy %d\n", L_VADDy); + if(L_VADDz>0) fprintf(fp, "vaddz %d\n", L_VADDz); + if(L_VCALLMS>0) fprintf(fp, "vcallms %d\n", L_VCALLMS); + if(L_VCALLMSR>0) fprintf(fp, "vcallmsr %d\n", L_VCALLMSR); + if(L_VCLIPw>0) fprintf(fp, "vclip %d\n", L_VCLIPw); + if(L_VDIV>0) fprintf(fp, "vdiv %d\n", L_VDIV); + if(L_VFTOI0>0) fprintf(fp, "vftoi0 %d\n", L_VFTOI0); + if(L_VFTOI12>0) fprintf(fp, "vftoi12 %d\n", L_VFTOI12); + if(L_VFTOI15>0) fprintf(fp, "vftoi15 %d\n", L_VFTOI15); + if(L_VFTOI4>0) fprintf(fp, "vftoi14 %d\n", L_VFTOI4); + if(L_VIADD>0) fprintf(fp, "viadd %d\n", L_VIADD); + if(L_VIADDI>0) fprintf(fp, "viaddi %d\n", L_VIADDI); + if(L_VIAND>0) fprintf(fp, "viand %d\n", L_VIAND); + if(L_VILWR>0) fprintf(fp, "vilwr %d\n", L_VILWR); + if(L_VIOR>0) fprintf(fp, "vior %d\n", L_VIOR); + if(L_VISUB>0) fprintf(fp, "visub %d\n", L_VISUB); + if(L_VISWR>0) fprintf(fp, "viswr %d\n", L_VISWR); + if(L_VITOF0>0) fprintf(fp, "vitof0 %d\n", L_VITOF0); + if(L_VITOF12>0) fprintf(fp, "vitof12 %d\n", L_VITOF12); + if(L_VITOF15>0) fprintf(fp, "vitof15 %d\n", L_VITOF15); + if(L_VITOF4>0) fprintf(fp, "vitof4 %d\n", L_VITOF4); + if(L_VLQD>0) fprintf(fp, "vlqd %d\n", L_VLQD); + if(L_VLQI>0) fprintf(fp, "vlqi %d\n", L_VLQI); + if(L_VMADD>0) fprintf(fp, "vmadd %d\n", L_VMADD); + if(L_VMADDA>0) fprintf(fp, "vmadda %d\n", L_VMADDA); + if(L_VMADDAi>0) fprintf(fp, "vmaddai %d\n", L_VMADDAi); + if(L_VMADDAq>0) fprintf(fp, "vmaddaq %d\n", L_VMADDAq); + if(L_VMADDAw>0) fprintf(fp, "vmaddaw %d\n", L_VMADDAw); + if(L_VMADDAx>0) fprintf(fp, "vmaddax %d\n", L_VMADDAx); + if(L_VMADDAy>0) fprintf(fp, "vmadday %d\n", L_VMADDAy); + if(L_VMADDAz>0) fprintf(fp, "vmaddaz %d\n", L_VMADDAz); + if(L_VMADDi>0) fprintf(fp, "vmaddi %d\n", L_VMADDi); + if(L_VMADDq>0) fprintf(fp, "vmaddq %d\n", L_VMADDq); + if(L_VMADDw>0) fprintf(fp, "vmaddw %d\n", L_VMADDw); + if(L_VMADDx>0) fprintf(fp, "vmaddx %d\n", L_VMADDx); + if(L_VMADDy>0) fprintf(fp, "vmaddy %d\n", L_VMADDy); + if(L_VMADDz>0) fprintf(fp, "vmaddz %d\n", L_VMADDz); + if(L_VMAX>0) fprintf(fp, "vmax %d\n", L_VMAX); + if(L_VMAXi>0) fprintf(fp, "vmaxi %d\n", L_VMAXi); + if(L_VMAXw>0) fprintf(fp, "vmaxw %d\n", L_VMAXw); + if(L_VMAXx>0) fprintf(fp, "vmaxx %d\n", L_VMAXx); + if(L_VMAXy>0) fprintf(fp, "vmaxy %d\n", L_VMAXy); + if(L_VMAXz>0) fprintf(fp, "vmaxz %d\n", L_VMAXz); + if(L_VMFIR>0) fprintf(fp, "vmfir %d\n", L_VMFIR); + if(L_VMINI>0) fprintf(fp, "vmini %d\n", L_VMINI); + if(L_VMINIi>0) fprintf(fp, "vminii %d\n", L_VMINIi); + if(L_VMINIw>0) fprintf(fp, "vminiw %d\n", L_VMINIw); + if(L_VMINIx>0) fprintf(fp, "vminix %d\n", L_VMINIx); + if(L_VMINIy>0) fprintf(fp, "vminiy %d\n", L_VMINIy); + if(L_VMINIz>0) fprintf(fp, "vminiz %d\n", L_VMINIz); + if(L_VMOVE>0) fprintf(fp, "vmove %d\n", L_VMOVE); + if(L_VMR32>0) fprintf(fp, "vmr32 %d\n", L_VMR32); + if(L_VMSUB>0) fprintf(fp, "vmsub %d\n", L_VMSUB); + if(L_VMSUBA>0) fprintf(fp, "vmsuba %d\n", L_VMSUBA); + if(L_VMSUBAi>0) fprintf(fp, "vmsubai %d\n", L_VMSUBAi); + if(L_VMSUBAq>0) fprintf(fp, "vmsubaq %d\n", L_VMSUBAq); + if(L_VMSUBAw>0) fprintf(fp, "vmsubaw %d\n", L_VMSUBAw); + if(L_VMSUBAx>0) fprintf(fp, "vmsubax %d\n", L_VMSUBAx); + if(L_VMSUBAy>0) fprintf(fp, "vmsubay %d\n", L_VMSUBAy); + if(L_VMSUBAz>0) fprintf(fp, "vmsubaz %d\n", L_VMSUBAz); + if(L_VMSUBi>0) fprintf(fp, "vmsubi %d\n", L_VMSUBi); + if(L_VMSUBq>0) fprintf(fp, "vmsubq %d\n", L_VMSUBq); + if(L_VMSUBw>0) fprintf(fp, "vmsubw %d\n", L_VMSUBw); + if(L_VMSUBx>0) fprintf(fp, "vmsubx %d\n", L_VMSUBx); + if(L_VMSUBy>0) fprintf(fp, "vmsuby %d\n", L_VMSUBy); + if(L_VMSUBz>0) fprintf(fp, "vmsubz %d\n", L_VMSUBz); + if(L_VMTIR>0) fprintf(fp, "vmtir %d\n", L_VMTIR); + if(L_VMUL>0) fprintf(fp, "vmul %d\n", L_VMUL); + if(L_VMULA>0) fprintf(fp, "vmula %d\n", L_VMULA); + if(L_VMULAi>0) fprintf(fp, "vmulai %d\n", L_VMULAi); + if(L_VMULAq>0) fprintf(fp, "vmulaq %d\n", L_VMULAq); + if(L_VMULAw>0) fprintf(fp, "vmulaw %d\n", L_VMULAw); + if(L_VMULAx>0) fprintf(fp, "vmulax %d\n", L_VMULAx); + if(L_VMULAy>0) fprintf(fp, "vmulay %d\n", L_VMULAy); + if(L_VMULAz>0) fprintf(fp, "vmulaz %d\n", L_VMULAz); + if(L_VMULi>0) fprintf(fp, "vmuli %d\n", L_VMULi); + if(L_VMULq>0) fprintf(fp, "vmulq %d\n", L_VMULq); + if(L_VMULw>0) fprintf(fp, "vmulw %d\n", L_VMULw); + if(L_VMULx>0) fprintf(fp, "vmulx %d\n", L_VMULx); + if(L_VMULy>0) fprintf(fp, "vmuly %d\n", L_VMULy); + if(L_VMULz>0) fprintf(fp, "vmulz %d\n", L_VMULz); + if(L_VNOP>0) fprintf(fp, "vnop %d\n", L_VNOP); + if(L_VOPMSUB>0) fprintf(fp, "vopmsub %d\n", L_VOPMSUB); + if(L_VOPMULA>0) fprintf(fp, "vopmula %d\n", L_VOPMULA); + if(L_VRGET>0) fprintf(fp, "vrget %d\n", L_VRGET); + if(L_VRINIT>0) fprintf(fp, "vrinit %d\n", L_VRINIT); + if(L_VRNEXT>0) fprintf(fp, "vrnext %d\n", L_VRNEXT); + if(L_VRSQRT>0) fprintf(fp, "vrsqrt %d\n", L_VRSQRT); + if(L_VRXOR>0) fprintf(fp, "vrxor %d\n", L_VRXOR); + if(L_VSQD>0) fprintf(fp, "vsqd %d\n", L_VSQD); + if(L_VSQI>0) fprintf(fp, "vsqi %d\n", L_VSQI); + if(L_VSQRT>0) fprintf(fp, "vsqrt %d\n", L_VSQRT ); + if(L_VSUB>0) fprintf(fp, "vsub %d\n", L_VSUB); + if(L_VSUBA>0) fprintf(fp, "vsuba %d\n", L_VSUBA); + if(L_VSUBAi>0) fprintf(fp, "vsubai %d\n", L_VSUBAi); + if(L_VSUBAq>0) fprintf(fp, "vsubaq %d\n", L_VSUBAq); + if(L_VSUBAw>0) fprintf(fp, "vsubaw %d\n", L_VSUBAw); + if(L_VSUBAx>0) fprintf(fp, "vsubax %d\n", L_VSUBAx); + if(L_VSUBAy>0) fprintf(fp, "vsubay %d\n", L_VSUBAy); + if(L_VSUBAz>0) fprintf(fp, "vsubaz %d\n", L_VSUBAz); + if(L_VSUBi>0) fprintf(fp, "vsubi %d\n", L_VSUBi); + if(L_VSUBq>0) fprintf(fp, "vsubq %d\n", L_VSUBq); + if(L_VSUBw>0) fprintf(fp, "vsubw %d\n", L_VSUBw); + if(L_VSUBx>0) fprintf(fp, "vsubx %d\n", L_VSUBx); + if(L_VSUBy>0) fprintf(fp, "vsuby %d\n", L_VSUBy); + if(L_VSUBz>0) fprintf(fp, "vsubz %d\n", L_VSUBz); + if(L_VWAITQ>0) fprintf(fp, "vwaitq %d\n", L_VWAITQ); + + fclose(fp); + +} + + + + + + + + + + + +/***************/ +//R5900 +void LT_SPECIAL() {LT_SpecialPrintTable[_Funct_]();} +void LT_REGIMM() {LT_REGIMMPrintTable[_Rt_](); } +void LT_UnknownOpcode() {} +void LT_ADDI() { L_ADDI++;} +void LT_ADDIU() { L_ADDIU++;} +void LT_DADDI() { L_DADDI++;} +void LT_DADDIU(){ L_DADDIU++;} +void LT_ANDI() { L_ANDI++;} +void LT_ORI() { L_ORI++;} +void LT_XORI() {L_XORI++;} +void LT_SLTI() {L_SLTI++;} +void LT_SLTIU() {L_SLTIU++;} +void LT_ADD() { L_ADD++;} +void LT_ADDU() { L_ADDU++;} +void LT_DADD() { L_DADD++;} +void LT_DADDU() { L_DADDU++;} +void LT_SUB() { L_SUB++;} +void LT_SUBU() { L_SUBU++;} +void LT_DSUB() { L_DSUB++;} +void LT_DSUBU() { L_DSUBU++;} +void LT_AND() { L_AND++;} +void LT_OR() { L_OR++;} +void LT_XOR() { L_XOR++;} +void LT_NOR() { L_NOR++;} +void LT_SLT() { L_SLT++;} +void LT_SLTU() { L_SLTU++;} +void LT_J() { L_J++;} +void LT_JAL() { L_JAL++;} +void LT_JR() { L_JR++;} +void LT_JALR() { L_JALR++;} +void LT_DIV() { L_DIV++;} +void LT_DIVU() { L_DIVU++;} +void LT_MULT() { L_MULT++;} +void LT_MULTU() { L_MULTU++;} +void LT_LUI() { L_LUI++;} +void LT_MFHI() { L_MFHI++;} +void LT_MFLO() { L_MFLO++;} +void LT_MTHI() { L_MTHI++;} +void LT_MTLO() { L_MTLO++;} +void LT_SLL() { L_SLL++;} +void LT_DSLL() { L_DSLL++;} +void LT_DSLL32(){ L_DSLL32++;} +void LT_SRA() { L_SRA++;} +void LT_DSRA() { L_DSRA++;} +void LT_DSRA32(){ L_DSRA32++;} +void LT_SRL() { L_SRL++;} +void LT_DSRL() { L_DSRL++;} +void LT_DSRL32(){ L_DSRL32++;} +void LT_SLLV() { L_SLLV++;} +void LT_SRAV() { L_SRAV++;} +void LT_SRLV() { L_SRLV++;} +void LT_DSLLV() { L_DSLLV++;} +void LT_DSRAV() { L_DSRAV++;} +void LT_DSRLV() { L_DSRLV++;} +void LT_BEQ() { L_BEQ++;} +void LT_BNE() { L_BNE++;} +void LT_BGEZ() { L_BGEZ++;} +void LT_BGEZAL(){ L_BGEZAL++;} +void LT_BGTZ() { L_BGTZ++;} +void LT_BLEZ() { L_BLEZ++;} +void LT_BLTZ() { L_BLTZ++;} +void LT_BLTZAL(){ L_BLTZAL++;} +void LT_BEQL() { L_BEQL++;} +void LT_BNEL() { L_BNEL++;} +void LT_BLEZL() { L_BLEZL++;} +void LT_BGTZL() { L_BGTZL++;} +void LT_BLTZL() { L_BLTZL++;} +void LT_BGEZL() { L_BGEZL++;} +void LT_BLTZALL(){ L_BLTZALL++;} +void LT_BGEZALL(){ L_BGEZALL++;} +void LT_LB() {L_LB++;} +void LT_LBU() {L_LBU++;} +void LT_LH() {L_LH++;} +void LT_LHU() {L_LHU++;} +void LT_LW() {L_LW++;} +void LT_LWU() {L_LWU++;} +void LT_LWL() {L_LWL++;} +void LT_LWR() {L_LWR++;} +void LT_LD() {L_LD++;} +void LT_LDL() {L_LDL++;} +void LT_LDR() {L_LDR++;} +void LT_LQ() {L_LQ++;} +void LT_SB() {L_SB++;} +void LT_SH() {L_SH++;} +void LT_SW() {L_SW++;} +void LT_SWL() {L_SWL++;} +void LT_SWR() {L_SWR++;} +void LT_SD() {L_SD++;} +void LT_SDL() {L_SDL++;} +void LT_SDR() {L_SDR++;} +void LT_SQ() {L_SQ++;} +void LT_MOVZ() {L_MOVZ++;} +void LT_MOVN() {L_MOVN++;} +void LT_SYSCALL() {L_SYSCALL++;} +void LT_BREAK() {L_BREAK++;} +void LT_CACHE() {L_CACHE++;} +void LT_MFSA() {L_MFSA++;} +void LT_MTSA() {L_MTSA++;} +void LT_SYNC() {L_SYNC++;} +void LT_PREF() {L_PREF++;} +void LT_TGE() {L_TGE++;} +void LT_TGEU() {L_TGEU++;} +void LT_TLT() {L_TLT++;} +void LT_TLTU() {L_TLTU++;} +void LT_TEQ() {L_TEQ++;} +void LT_TNE() {L_TNE++;} +void LT_TGEI() {L_TGEI++;} +void LT_TGEIU() {L_TGEIU++;} +void LT_TLTI() {L_TLTI++;} +void LT_TLTIU() {L_TLTIU++;} +void LT_TEQI() {L_TEQI++;} +void LT_TNEI() {L_TNEI++;} +void LT_MTSAB() {L_MTSAB++;} +void LT_MTSAH() {L_MTSAH++;} +//cop0 +void LT_COP0(){ LT_COP0PrintTable[_Rs_]();} +void LT_COP0_BC0() {LT_COP0BC0PrintTable[(cpuRegs.code >> 16) & 0x03]();} +void LT_COP0_Func() { LT_COP0C0PrintTable[_Funct_](); } +void LT_COP0_Unknown() { } +void LT_MFC0() {L_MFC0++;} +void LT_MTC0() {L_MTC0++;} +void LT_BC0F() {L_BC0F++;} +void LT_BC0T() {L_BC0T++;} +void LT_BC0FL(){L_BC0FL++;} +void LT_BC0TL(){L_BC0TL++;} +void LT_TLBR() {L_TLBR++;} +void LT_TLBWI(){L_TLBWI++;} +void LT_TLBWR(){L_TLBWR++;} +void LT_TLBP() {L_TLBP++;} +void LT_ERET() {L_ERET++;} +void LT_DI() {L_DI++;} +void LT_EI() {L_EI++;} +//mmi +void LT_MMI() {LT_MMIPrintTable[_Funct_]();} +void LT_MMI0() {LT_MMI0PrintTable[_Sa_]();} +void LT_MMI1() {LT_MMI1PrintTable[_Sa_]();} +void LT_MMI2() {LT_MMI2PrintTable[_Sa_]();} +void LT_MMI3() {LT_MMI3PrintTable[_Sa_]();} +void LT_MMI_Unknown() {} +void LT_MADD() {L_MADD++;} +void LT_MADDU(){L_MADDU++;} +void LT_PLZCW(){L_PLZCW++;} +void LT_MADD1(){L_MADD1++;} +void LT_MADDU1(){L_MADDU1++;} +void LT_MFHI1(){L_MFHI1++;} +void LT_MTHI1(){L_MTHI1++;} +void LT_MFLO1(){L_MFLO1++;} +void LT_MTLO1(){L_MTLO1++;} +void LT_MULT1(){L_MULT1++;} +void LT_MULTU1(){L_MULTU1++;} +void LT_DIV1(){L_DIV1++;} +void LT_DIVU1(){L_DIVU1++;} +void LT_PMFHL(){L_PMFHL++;} +void LT_PMTHL(){L_PMTHL++;} +void LT_PSLLH(){L_PSLLH++;} +void LT_PSRLH(){L_PSRLH++;} +void LT_PSRAH(){L_PSRAH++;} +void LT_PSLLW(){L_PSLLW++;} +void LT_PSRLW(){L_PSRLW++;} +void LT_PSRAW(){L_PSRAW++;} +void LT_PADDW(){L_PADDW++;} +void LT_PSUBW(){L_PSUBW++;} +void LT_PCGTW(){L_PCGTW++;} +void LT_PMAXW(){L_PMAXW++;} +void LT_PADDH(){L_PADDH++;} +void LT_PSUBH(){L_PSUBH++;} +void LT_PCGTH(){L_PCGTH++;} +void LT_PMAXH(){L_PMAXH++;} +void LT_PADDB(){L_PADDB++;} +void LT_PSUBB(){L_PSUBB++;} +void LT_PCGTB(){L_PCGTB++;} +void LT_PADDSW(){L_PADDSW++;} +void LT_PSUBSW(){L_PSUBSW++;} +void LT_PEXTLW(){L_PEXTLW++;} +void LT_PPACW(){L_PPACW++;} +void LT_PADDSH(){L_PADDSH++;} +void LT_PSUBSH(){L_PSUBSH++;} +void LT_PEXTLH(){L_PEXTLH++;} +void LT_PPACH(){L_PPACH++;} +void LT_PADDSB(){L_PADDSB++;} +void LT_PSUBSB(){L_PSUBSB++;} +void LT_PEXTLB(){L_PEXTLB++;} +void LT_PPACB(){L_PPACB++;} +void LT_PEXT5(){L_PEXT5++;} +void LT_PPAC5(){L_PPAC5++;} +void LT_PABSW(){L_PABSW++;} +void LT_PCEQW(){L_PCEQW++;} +void LT_PMINW(){L_PMINW++;} +void LT_PADSBH(){L_PADSBH++;} +void LT_PABSH(){L_PABSH++;} +void LT_PCEQH(){L_PCEQH++;} +void LT_PMINH(){L_PMINH++;} +void LT_PCEQB(){L_PCEQB++;} +void LT_PADDUW(){L_PADDUW++;} +void LT_PSUBUW(){L_PSUBUW++;} +void LT_PEXTUW(){L_PEXTUW++;} +void LT_PADDUH(){L_PADDUH++;} +void LT_PSUBUH(){L_PSUBUH++;} +void LT_PEXTUH(){L_PEXTUH++;} +void LT_PADDUB(){L_PADDUB++;} +void LT_PSUBUB(){L_PSUBUB++;} +void LT_PEXTUB(){L_PEXTUB++;} +void LT_QFSRV(){L_QFSRV++;} +void LT_PMADDW(){L_PMADDW++;} +void LT_PSLLVW(){L_PSLLVW++;} +void LT_PSRLVW(){L_PSRLVW++;} +void LT_PMSUBW(){L_PMSUBW++;} +void LT_PMFHI(){L_PMFHI++;} +void LT_PMFLO(){L_PMFLO++;} +void LT_PINTH(){L_PINTH++;} +void LT_PMULTW(){L_PMULTW++;} +void LT_PDIVW(){L_PDIVW++;} +void LT_PCPYLD(){L_PCPYLD++;} +void LT_PMADDH(){L_PMADDH++;} +void LT_PHMADH(){L_PHMADH++;} +void LT_PAND(){L_PAND++;} +void LT_PXOR(){L_PXOR++;} +void LT_PMSUBH(){L_PMSUBH++;} +void LT_PHMSBH(){L_PHMSBH++;} +void LT_PEXEH(){L_PEXEH++;} +void LT_PREVH(){L_PREVH++;} +void LT_PMULTH(){L_PMULTH++;} +void LT_PDIVBW(){L_PDIVBW++;} +void LT_PEXEW(){L_PEXEW++;} +void LT_PROT3W(){L_PROT3W++;} +void LT_PMADDUW(){L_PMADDUW++;} +void LT_PSRAVW(){L_PSRAVW++;} +void LT_PMTHI(){L_MTHI++;} +void LT_PMTLO(){L_PMTLO++;} +void LT_PINTEH(){L_PINTEH++;} +void LT_PMULTUW(){L_PMULTUW++;} +void LT_PDIVUW(){L_PDIVUW++;} +void LT_PCPYUD(){L_PCPYUD++;} +void LT_POR(){L_POR++;} +void LT_PNOR(){L_PNOR++;} +void LT_PEXCH(){L_PEXCH++;} +void LT_PCPYH(){L_PCPYH++;} +void LT_PEXCW(){L_PEXCW++;} +//COP1 +void LT_COP1() {LT_COP1PrintTable[_Rs_]();} +void LT_LWC1() {L_LWC1++;} +void LT_SWC1() {L_SWC1++;} +void LT_COP1_BC1() {LT_COP1BC1PrintTable[_Rt_]();} +void LT_COP1_S() {LT_COP1SPrintTable[_Funct_]();} +void LT_COP1_W() {LT_COP1WPrintTable[_Funct_]();} +void LT_COP1_Unknown() {} +void LT_MFC1(){L_MFC1++;} +void LT_CFC1(){L_CFC1++;} +void LT_MTC1(){L_MTC1++;} +void LT_CTC1(){L_CTC1++;} +void LT_BC1F(){L_BC1F++;} +void LT_BC1T(){L_BC1T++;} +void LT_BC1FL(){L_BC1FL++;} +void LT_BC1TL(){L_BC1TL++;} +void LT_ADD_S(){L_ADD_S++;} +void LT_SUB_S(){L_SUB_S++;} +void LT_MUL_S(){L_MUL_S++;} +void LT_DIV_S(){L_DIV_S++;} +void LT_SQRT_S(){L_SQRT_S++;} +void LT_ABS_S(){L_ABS_S++;} +void LT_MOV_S(){L_MOV_S++;} +void LT_NEG_S(){L_NEG_S++;} +void LT_RSQRT_S(){L_RSQRT_S++;} +void LT_ADDA_S(){L_ADDA_S++;} +void LT_SUBA_S(){L_SUBA_S++;} +void LT_MULA_S(){L_MULA_S++;} +void LT_MADD_S(){L_MADD_S++;} +void LT_MSUB_S(){L_MSUB_S++;} +void LT_MADDA_S(){L_MADDA_S++;} +void LT_MSUBA_S(){L_MSUBA_S++;} +void LT_CVT_W(){L_CVT_W++;} +void LT_MAX_S(){L_MAX_S++;} +void LT_MIN_S(){L_MIN_S++;} +void LT_C_F(){L_C_F++;} +void LT_C_EQ(){L_C_EQ++;} +void LT_C_LT(){L_C_LT++;} +void LT_C_LE(){L_C_LE++;} +void LT_CVT_S(){L_CVT_S++;} +//cop2 + +void LT_LQC2() {L_LQC2++;} +void LT_SQC2() {L_SQC2++;} +void LT_COP2() {LT_COP2PrintTable[_Rs_]();} +void LT_COP2_BC2() {LT_COP2BC2PrintTable[_Rt_]();} +void LT_COP2_SPECIAL() { LT_COP2SPECIAL1PrintTable[_Funct_]();} +void LT_COP2_SPECIAL2() {LT_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)]();} +void LT_COP2_Unknown(){} +void LT_QMFC2(){L_QMFC2++;} +void LT_CFC2(){L_CFC2++;} +void LT_QMTC2(){L_QMTC2++;} +void LT_CTC2(){L_CTC2++;} +void LT_BC2F(){L_BC2F++;} +void LT_BC2T(){L_BC2T++;} +void LT_BC2FL(){L_BC2FL++;} +void LT_BC2TL(){L_BC2TL++;} +void LT_VADDx(){L_VADDx++;} +void LT_VADDy(){L_VADDy++;} +void LT_VADDz(){L_VADDz++;} +void LT_VADDw(){L_VADDw++;} +void LT_VSUBx(){L_VSUBx++;} +void LT_VSUBy(){L_VSUBy++;} +void LT_VSUBz(){L_VSUBz++;} +void LT_VSUBw(){L_VSUBw++;} +void LT_VMADDx(){L_VMADDx++;} +void LT_VMADDy(){L_VMADDy++;} +void LT_VMADDz(){L_VMADDz++;} +void LT_VMADDw(){L_VMADDw++;} +void LT_VMSUBx(){L_VMSUBx++;} +void LT_VMSUBy(){L_VMSUBy++;} +void LT_VMSUBz(){L_VMSUBz++;} +void LT_VMSUBw(){L_VMSUBw++;} +void LT_VMAXx(){L_VMAXx++;} +void LT_VMAXy(){L_VMAXy++;} +void LT_VMAXz(){L_VMAXz++;} +void LT_VMAXw(){L_VMAXw++;} +void LT_VMINIx(){L_VMINIx++;} +void LT_VMINIy(){L_VMINIy++;} +void LT_VMINIz(){L_VMINIz++;} +void LT_VMINIw(){L_VMINIw++;} +void LT_VMULx(){L_VMULx++;} +void LT_VMULy(){L_VMULy++;} +void LT_VMULz(){L_VMULz++;} +void LT_VMULw(){L_VMULw++;} +void LT_VMULq(){L_VMULq++;} +void LT_VMAXi(){L_VMAXi++;} +void LT_VMULi(){L_VMULi++;} +void LT_VMINIi(){L_VMINIi++;} +void LT_VADDq(){L_VADDq++;} +void LT_VMADDq(){L_VMADDq++;} +void LT_VADDi(){L_VADDi++;} +void LT_VMADDi(){L_VMADDi++;} +void LT_VSUBq(){L_VSUBq++;} +void LT_VMSUBq(){L_VMSUBq++;} +void LT_VSUBi(){L_VSUBi++;} +void LT_VMSUBi(){L_VMSUBi++;} +void LT_VADD(){L_VADD++;} +void LT_VMADD(){L_VMADD++;} +void LT_VMUL(){L_VMUL++;} +void LT_VMAX(){L_VMAX++;} +void LT_VSUB(){L_VSUB++;} +void LT_VMSUB(){L_VMSUB++;} +void LT_VOPMSUB(){L_VOPMSUB++;} +void LT_VMINI(){L_VMINI++;} +void LT_VIADD(){L_VIADD++;} +void LT_VISUB(){L_VISUB++;} +void LT_VIADDI(){L_VIADDI++;} +void LT_VIAND(){L_VIAND++;} +void LT_VIOR(){L_VIOR++;} +void LT_VCALLMS(){L_VCALLMS++;} +void LT_VCALLMSR(){L_VCALLMSR++;} +void LT_VADDAx(){L_VADDAx++;} +void LT_VADDAy(){L_VADDAy++;} +void LT_VADDAz(){L_VADDAz++;} +void LT_VADDAw(){L_VADDAw++;} +void LT_VSUBAx(){L_VSUBAx++;} +void LT_VSUBAy(){L_VSUBAy++;} +void LT_VSUBAz(){L_VSUBAz++;} +void LT_VSUBAw(){L_VSUBAw++;} +void LT_VMADDAx(){L_VMADDAx++;} +void LT_VMADDAy(){L_VMADDAy++;} +void LT_VMADDAz(){L_VMADDAz++;} +void LT_VMADDAw(){L_VMADDAw++;} +void LT_VMSUBAx(){L_VMSUBAx++;} +void LT_VMSUBAy(){L_VMSUBAy++;} +void LT_VMSUBAz(){L_VMSUBAz++;} +void LT_VMSUBAw(){L_VMSUBAw++;} +void LT_VITOF0(){L_VITOF0++;} +void LT_VITOF4(){L_VITOF4++;} +void LT_VITOF12(){L_VITOF12++;} +void LT_VITOF15(){L_VITOF15++;} +void LT_VFTOI0(){L_VFTOI0++;} +void LT_VFTOI4(){L_VFTOI4++;} +void LT_VFTOI12(){L_VFTOI12++;} +void LT_VFTOI15(){L_VFTOI15++;} +void LT_VMULAx(){L_VMULAx++;} +void LT_VMULAy(){L_VMULAy++;} +void LT_VMULAz(){L_VMULAz++;} +void LT_VMULAw(){L_VMULAw++;} +void LT_VMULAq(){L_VMULAq++;} +void LT_VABS(){L_VABS++;} +void LT_VMULAi(){L_VMULAi++;} +void LT_VCLIPw(){L_VCLIPw++;} +void LT_VADDAq(){L_VADDAq++;} +void LT_VMADDAq(){L_VMADDAq++;} +void LT_VADDAi(){L_VADDAi++;} +void LT_VMADDAi(){L_VMADDAi++;} +void LT_VSUBAq(){L_VSUBAq++;} +void LT_VMSUBAq(){L_VMSUBAq++;} +void LT_VSUBAi(){L_VSUBAi++;} +void LT_VMSUBAi(){L_VMSUBAi++;} +void LT_VADDA(){L_VADDA++;} +void LT_VMADDA(){L_VMADDA++;} +void LT_VMULA(){L_VMULA++;} +void LT_VSUBA(){L_VSUBA++;} +void LT_VMSUBA(){L_VMSUBA++;} +void LT_VOPMULA(){L_VOPMULA++;} +void LT_VNOP(){L_VNOP++;} +void LT_VMOVE(){L_VMOVE++;} +void LT_VMR32(){L_VMR32++;} +void LT_VLQI(){L_VLQI++;} +void LT_VSQI(){L_VSQI++;} +void LT_VLQD(){L_VLQD++;} +void LT_VSQD(){L_VSQD++;} +void LT_VDIV(){L_VDIV++;} +void LT_VSQRT(){L_VSQRT++;} +void LT_VRSQRT(){L_VRSQRT++;} +void LT_VWAITQ(){L_VWAITQ++;} +void LT_VMTIR(){L_VMTIR++;} +void LT_VMFIR(){L_VMFIR++;} +void LT_VILWR(){L_VILWR++;} +void LT_VISWR(){L_VISWR++;} +void LT_VRNEXT(){L_VRNEXT++;} +void LT_VRGET(){L_VRGET++;} +void LT_VRINIT(){L_VRINIT++;} +void LT_VRXOR(){L_VRXOR++;} + +void (*LT_OpcodePrintTable[64])() = +{ + LT_SPECIAL, LT_REGIMM, LT_J, LT_JAL, LT_BEQ, LT_BNE, LT_BLEZ, LT_BGTZ, + LT_ADDI, LT_ADDIU, LT_SLTI, LT_SLTIU, LT_ANDI, LT_ORI, LT_XORI, LT_LUI, + LT_COP0, LT_COP1, LT_COP2, LT_UnknownOpcode, LT_BEQL, LT_BNEL, LT_BLEZL, LT_BGTZL, + LT_DADDI, LT_DADDIU, LT_LDL, LT_LDR, LT_MMI, LT_UnknownOpcode, LT_LQ, LT_SQ, + LT_LB, LT_LH, LT_LWL, LT_LW, LT_LBU, LT_LHU, LT_LWR, LT_LWU, + LT_SB, LT_SH, LT_SWL, LT_SW, LT_SDL, LT_SDR, LT_SWR, LT_CACHE, + LT_UnknownOpcode, LT_LWC1, LT_UnknownOpcode, LT_PREF, LT_UnknownOpcode,LT_UnknownOpcode, LT_LQC2, LT_LD, + LT_UnknownOpcode, LT_SWC1, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode,LT_UnknownOpcode, LT_SQC2, LT_SD +}; + + +void (*LT_SpecialPrintTable[64])() = +{ + LT_SLL, LT_UnknownOpcode, LT_SRL, LT_SRA, LT_SLLV, LT_UnknownOpcode, LT_SRLV, LT_SRAV, + LT_JR, LT_JALR, LT_MOVZ, LT_MOVN, LT_SYSCALL, LT_BREAK, LT_UnknownOpcode, LT_SYNC, + LT_MFHI, LT_MTHI, LT_MFLO, LT_MTLO, LT_DSLLV, LT_UnknownOpcode, LT_DSRLV, LT_DSRAV, + LT_MULT, LT_MULTU, LT_DIV, LT_DIVU, LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode,LT_UnknownOpcode, + LT_ADD, LT_ADDU, LT_SUB, LT_SUBU, LT_AND, LT_OR, LT_XOR, LT_NOR, + LT_MFSA , LT_MTSA , LT_SLT, LT_SLTU, LT_DADD, LT_DADDU, LT_DSUB, LT_DSUBU, + LT_TGE, LT_TGEU, LT_TLT, LT_TLTU, LT_TEQ, LT_UnknownOpcode, LT_TNE, LT_UnknownOpcode, + LT_DSLL, LT_UnknownOpcode, LT_DSRL, LT_DSRA, LT_DSLL32, LT_UnknownOpcode, LT_DSRL32, LT_DSRA32 +}; + +void (*LT_REGIMMPrintTable[32])() = { + LT_BLTZ, LT_BGEZ, LT_BLTZL, LT_BGEZL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_TGEI, LT_TGEIU, LT_TLTI, LT_TLTIU, LT_TEQI, LT_UnknownOpcode, LT_TNEI, LT_UnknownOpcode, + LT_BLTZAL, LT_BGEZAL, LT_BLTZALL, LT_BGEZALL, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, + LT_MTSAB, LT_MTSAH , LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, LT_UnknownOpcode, +}; +void (*LT_MMIPrintTable[64])() = +{ + LT_MADD, LT_MADDU, LT_MMI_Unknown, LT_MMI_Unknown, LT_PLZCW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI0, LT_MMI2, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MFHI1, LT_MTHI1, LT_MFLO1, LT_MTLO1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MULT1, LT_MULTU1, LT_DIV1, LT_DIVU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MADD1, LT_MADDU1, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI1 , LT_MMI3, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHL, LT_PMTHL, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLH, LT_MMI_Unknown, LT_PSRLH, LT_PSRAH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSLLW, LT_MMI_Unknown, LT_PSRLW, LT_PSRAW, +}; + +void (*LT_MMI0PrintTable[32])() = +{ + LT_PADDW, LT_PSUBW, LT_PCGTW, LT_PMAXW, + LT_PADDH, LT_PSUBH, LT_PCGTH, LT_PMAXH, + LT_PADDB, LT_PSUBB, LT_PCGTB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDSW, LT_PSUBSW, LT_PEXTLW, LT_PPACW, + LT_PADDSH, LT_PSUBSH, LT_PEXTLH, LT_PPACH, + LT_PADDSB, LT_PSUBSB, LT_PEXTLB, LT_PPACB, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXT5, LT_PPAC5, +}; + +void (*LT_MMI1PrintTable[32])() = +{ + LT_MMI_Unknown, LT_PABSW, LT_PCEQW, LT_PMINW, + LT_PADSBH, LT_PABSH, LT_PCEQH, LT_PMINH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PCEQB, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PADDUW, LT_PSUBUW, LT_PEXTUW, LT_MMI_Unknown, + LT_PADDUH, LT_PSUBUH, LT_PEXTUH, LT_MMI_Unknown, + LT_PADDUB, LT_PSUBUB, LT_PEXTUB, LT_QFSRV, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, +}; + + +void (*LT_MMI2PrintTable[32])() = +{ + LT_PMADDW, LT_MMI_Unknown, LT_PSLLVW, LT_PSRLVW, + LT_PMSUBW, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMFHI, LT_PMFLO, LT_PINTH, LT_MMI_Unknown, + LT_PMULTW, LT_PDIVW, LT_PCPYLD, LT_MMI_Unknown, + LT_PMADDH, LT_PHMADH, LT_PAND, LT_PXOR, + LT_PMSUBH, LT_PHMSBH, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXEH, LT_PREVH, + LT_PMULTH, LT_PDIVBW, LT_PEXEW, LT_PROT3W, +}; + +void (*LT_MMI3PrintTable[32])() = +{ + LT_PMADDUW, LT_MMI_Unknown, LT_MMI_Unknown, LT_PSRAVW, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_PMTHI, LT_PMTLO, LT_PINTEH, LT_MMI_Unknown, + LT_PMULTUW, LT_PDIVUW, LT_PCPYUD, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_POR, LT_PNOR, + LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, LT_MMI_Unknown, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCH, LT_PCPYH, + LT_MMI_Unknown, LT_MMI_Unknown, LT_PEXCW, LT_MMI_Unknown, +}; + +void (*LT_COP0PrintTable[32])() = +{ + LT_MFC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_MTC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_BC0, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Func, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0BC0PrintTable[32])() = +{ + LT_BC0F, LT_BC0T, LT_BC0FL, LT_BC0TL, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, +}; + +void (*LT_COP0C0PrintTable[64])() = { + LT_COP0_Unknown, LT_TLBR, LT_TLBWI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_TLBWR, LT_COP0_Unknown, + LT_TLBP, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_ERET, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, + LT_EI, LT_DI, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown, LT_COP0_Unknown +}; + + +void (*LT_COP1PrintTable[32])() = { + LT_MFC1, LT_COP1_Unknown, LT_CFC1, LT_COP1_Unknown, LT_MTC1, LT_COP1_Unknown, LT_CTC1, LT_COP1_Unknown, + LT_COP1_BC1, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_S, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_W, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1BC1PrintTable[32])() = { + LT_BC1F, LT_BC1T, LT_BC1FL, LT_BC1TL, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, + LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, LT_COP1_Unknown, +}; + +void (*LT_COP1SPrintTable[64])() = { +LT_ADD_S, LT_SUB_S, LT_MUL_S, LT_DIV_S, LT_SQRT_S, LT_ABS_S, LT_MOV_S, LT_NEG_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_RSQRT_S, LT_COP1_Unknown, +LT_ADDA_S, LT_SUBA_S, LT_MULA_S, LT_COP1_Unknown,LT_MADD_S, LT_MSUB_S, LT_MADDA_S, LT_MSUBA_S, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_CVT_W, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_MAX_S, LT_MIN_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_C_F, LT_COP1_Unknown,LT_C_EQ, LT_COP1_Unknown,LT_C_LT, LT_COP1_Unknown,LT_C_LE, LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP1WPrintTable[64])() = { +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_CVT_S, LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown,LT_COP1_Unknown, +}; + +void (*LT_COP2PrintTable[32])() = { + LT_COP2_Unknown, LT_QMFC2, LT_CFC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_QMTC2, LT_CTC2, LT_COP2_Unknown, + LT_COP2_BC2, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, + LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, LT_COP2_SPECIAL, +}; + +void (*LT_COP2BC2PrintTable[32])() = { + LT_BC2F, LT_BC2T, LT_BC2FL, LT_BC2TL, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, + LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, LT_COP2_Unknown, +}; + +void (*LT_COP2SPECIAL1PrintTable[64])() = +{ + LT_VADDx, LT_VADDy, LT_VADDz, LT_VADDw, LT_VSUBx, LT_VSUBy, LT_VSUBz, LT_VSUBw, + LT_VMADDx, LT_VMADDy, LT_VMADDz, LT_VMADDw, LT_VMSUBx, LT_VMSUBy, LT_VMSUBz, LT_VMSUBw, + LT_VMAXx, LT_VMAXy, LT_VMAXz, LT_VMAXw, LT_VMINIx, LT_VMINIy, LT_VMINIz, LT_VMINIw, + LT_VMULx, LT_VMULy, LT_VMULz, LT_VMULw, LT_VMULq, LT_VMAXi, LT_VMULi, LT_VMINIi, + LT_VADDq, LT_VMADDq, LT_VADDi, LT_VMADDi, LT_VSUBq, LT_VMSUBq, LT_VSUBi, LT_VMSUBi, + LT_VADD, LT_VMADD, LT_VMUL, LT_VMAX, LT_VSUB, LT_VMSUB, LT_VOPMSUB, LT_VMINI, + LT_VIADD, LT_VISUB, LT_VIADDI, LT_COP2_Unknown,LT_VIAND, LT_VIOR, LT_COP2_Unknown, LT_COP2_Unknown, + LT_VCALLMS, LT_VCALLMSR, LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2,LT_COP2_SPECIAL2, +}; + +void (*LT_COP2SPECIAL2PrintTable[128])() = +{ + LT_VADDAx ,LT_VADDAy ,LT_VADDAz ,LT_VADDAw ,LT_VSUBAx ,LT_VSUBAy ,LT_VSUBAz ,LT_VSUBAw, + LT_VMADDAx ,LT_VMADDAy ,LT_VMADDAz ,LT_VMADDAw ,LT_VMSUBAx ,LT_VMSUBAy ,LT_VMSUBAz ,LT_VMSUBAw, + LT_VITOF0 ,LT_VITOF4 ,LT_VITOF12 ,LT_VITOF15 ,LT_VFTOI0 ,LT_VFTOI4 ,LT_VFTOI12 ,LT_VFTOI15, + LT_VMULAx ,LT_VMULAy ,LT_VMULAz ,LT_VMULAw ,LT_VMULAq ,LT_VABS ,LT_VMULAi ,LT_VCLIPw, + LT_VADDAq ,LT_VMADDAq ,LT_VADDAi ,LT_VMADDAi ,LT_VSUBAq ,LT_VMSUBAq ,LT_VSUBAi ,LT_VMSUBAi, + LT_VADDA ,LT_VMADDA ,LT_VMULA ,LT_COP2_Unknown,LT_VSUBA ,LT_VMSUBA ,LT_VOPMULA ,LT_VNOP, + LT_VMOVE ,LT_VMR32 ,LT_COP2_Unknown,LT_COP2_Unknown,LT_VLQI ,LT_VSQI ,LT_VLQD ,LT_VSQD, + LT_VDIV ,LT_VSQRT ,LT_VRSQRT ,LT_VWAITQ ,LT_VMTIR ,LT_VMFIR ,LT_VILWR ,LT_VISWR, + LT_VRNEXT ,LT_VRGET ,LT_VRINIT ,LT_VRXOR ,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, + LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown,LT_COP2_Unknown, +}; diff --git a/pcsx2/DebugTools/cpuopsDebug.h b/pcsx2/DebugTools/cpuopsDebug.h new file mode 100644 index 0000000..3422693 --- /dev/null +++ b/pcsx2/DebugTools/cpuopsDebug.h @@ -0,0 +1,456 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void UpdateR5900op(); +extern void (*LT_OpcodePrintTable[64])(); +extern void (*LT_SpecialPrintTable[64])(); +extern void (*LT_REGIMMPrintTable[32])(); +extern void (*LT_MMIPrintTable[64])(); +extern void (*LT_MMI0PrintTable[32])(); +extern void (*LT_MMI1PrintTable[32])(); +extern void (*LT_MMI2PrintTable[32])(); +extern void (*LT_MMI3PrintTable[32])(); +extern void (*LT_COP0PrintTable[32])(); +extern void (*LT_COP0BC0PrintTable[32])(); +extern void (*LT_COP0C0PrintTable[64])(); +extern void (*LT_COP1PrintTable[32])(); +extern void (*LT_COP1BC1PrintTable[32])(); +extern void (*LT_COP1SPrintTable[64])(); +extern void (*LT_COP1WPrintTable[64])(); +extern void (*LT_COP2PrintTable[32])(); +extern void (*LT_COP2BC2PrintTable[32])(); +extern void (*LT_COP2SPECIAL1PrintTable[64])(); +extern void (*LT_COP2SPECIAL2PrintTable[128])(); +// **********************Standard Opcodes************************** +int L_ADD=0; +int L_ADDI=0; +int L_ADDIU=0; +int L_ADDU=0; +int L_AND=0; +int L_ANDI=0; +int L_BEQ=0; +int L_BEQL=0; +int L_BGEZ=0; +int L_BGEZAL=0; +int L_BGEZALL=0; +int L_BGEZL=0; +int L_BGTZ=0; +int L_BGTZL=0; +int L_BLEZ=0; +int L_BLEZL=0; +int L_BLTZ=0; +int L_BLTZAL=0; +int L_BLTZALL=0; +int L_BLTZL=0; +int L_BNE=0; +int L_BNEL=0; +int L_BREAK=0; +int L_CACHE=0; +int L_DADD=0; +int L_DADDI=0; +int L_DADDIU=0; +int L_DADDU=0; +int L_DIV=0; +int L_DIVU=0; +int L_DSLL=0; +int L_DSLL32=0; +int L_DSLLV=0; +int L_DSRA=0; +int L_DSRA32=0; +int L_DSRAV=0; +int L_DSRL=0; +int L_DSRL32=0; +int L_DSRLV=0; +int L_DSUB=0; +int L_DSUBU=0; +int L_J=0; +int L_JAL=0; +int L_JALR=0; +int L_JR=0; +int L_LB=0; +int L_LBU=0; +int L_LD=0; +int L_LDL=0; +int L_LDR=0; +int L_LH=0; +int L_LHU=0; +int L_LQ=0; +int L_LQC2=0; +int L_LUI=0; +int L_LW=0; +int L_LWC1=0; +int L_LWL=0; +int L_LWR=0; +int L_LWU=0; +int L_MFHI=0; +int L_MFLO=0; +int L_MFSA=0; +int L_MOVN=0; +int L_MOVZ=0; +int L_MTHI=0; +int L_MTLO=0; +int L_MTSA=0; +int L_MTSAB=0; +int L_MTSAH=0; +int L_MULT=0; +int L_MULTU=0; +int L_NOR=0; +int L_OR=0; +int L_ORI=0; +int L_PREF=0; +int L_SB=0; +int L_SD=0; +int L_SDL=0; +int L_SDR=0; +int L_SH=0; +int L_SLL=0; +int L_SLLV=0; +int L_SLT=0; +int L_SLTI=0; +int L_SLTIU=0; +int L_SLTU=0; +int L_SQ=0; +int L_SQC2=0; +int L_SRA=0; +int L_SRAV=0; +int L_SRL=0; +int L_SRLV=0; +int L_SUB=0; +int L_SUBU=0; +int L_SW=0; +int L_SWC1=0; +int L_SWL=0; +int L_SWR=0; +int L_SYNC=0; +int L_SYSCALL=0; +int L_TEQ=0; +int L_TEQI=0; +int L_TGE=0; +int L_TGEI=0; +int L_TGEIU=0; +int L_TGEU=0; +int L_TLT=0; +int L_TLTI=0; +int L_TLTIU=0; +int L_TLTU=0; +int L_TNE=0; +int L_TNEI=0; +int L_XOR=0; +int L_XORI=0; + + + + +//*****************MMI OPCODES********************************* +int L_MADD=0; +int L_MADDU=0; +int L_PLZCW=0; +int L_MADD1=0; +int L_MADDU1=0; +int L_MFHI1=0; +int L_MTHI1=0; +int L_MFLO1=0; +int L_MTLO1=0; +int L_MULT1=0; +int L_MULTU1=0; +int L_DIV1=0; +int L_DIVU1=0; +int L_PMFHL=0; +int L_PMTHL=0; +int L_PSLLH=0; +int L_PSRLH=0; +int L_PSRAH=0; +int L_PSLLW=0; +int L_PSRLW=0; +int L_PSRAW=0; +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +int L_PADDW=0; +int L_PSUBW=0; +int L_PCGTW=0; +int L_PMAXW=0; +int L_PADDH=0; +int L_PSUBH=0; +int L_PCGTH=0; +int L_PMAXH=0; +int L_PADDB=0; +int L_PSUBB=0; +int L_PCGTB=0; +int L_PADDSW=0; +int L_PSUBSW=0; +int L_PEXTLW=0; +int L_PPACW=0; +int L_PADDSH=0; +int L_PSUBSH=0; +int L_PEXTLH=0; +int L_PPACH=0; +int L_PADDSB=0; +int L_PSUBSB=0; +int L_PEXTLB=0; +int L_PPACB=0; +int L_PEXT5=0; +int L_PPAC5=0; +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +int L_PABSW=0; +int L_PCEQW=0; +int L_PMINW=0; +int L_PADSBH=0; +int L_PABSH=0; +int L_PCEQH=0; +int L_PMINH=0; +int L_PCEQB=0; +int L_PADDUW=0; +int L_PSUBUW=0; +int L_PEXTUW=0; +int L_PADDUH=0; +int L_PSUBUH=0; +int L_PEXTUH=0; +int L_PADDUB=0; +int L_PSUBUB=0; +int L_PEXTUB=0; +int L_QFSRV=0; +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +int L_PMADDW=0; +int L_PSLLVW=0; +int L_PSRLVW=0; +int L_PMSUBW=0; +int L_PMFHI=0; +int L_PMFLO=0; +int L_PINTH=0; +int L_PMULTW=0; +int L_PDIVW=0; +int L_PCPYLD=0; +int L_PMADDH=0; +int L_PHMADH=0; +int L_PAND=0; +int L_PXOR=0; +int L_PMSUBH=0; +int L_PHMSBH=0; +int L_PEXEH=0; +int L_PREVH=0; +int L_PMULTH=0; +int L_PDIVBW=0; +int L_PEXEW=0; +int L_PROT3W=0; +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +int L_PMADDUW=0; +int L_PSRAVW=0; +int L_PMTHI=0; +int L_PMTLO=0; +int L_PINTEH=0; +int L_PMULTUW=0; +int L_PDIVUW=0; +int L_PCPYUD=0; +int L_POR=0; +int L_PNOR=0; +int L_PEXCH=0; +int L_PCPYH=0; +int L_PEXCW=0; +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +int L_MFC0=0; +int L_MTC0=0; +int L_BC0F=0; +int L_BC0T=0; +int L_BC0FL=0; +int L_BC0TL=0; +int L_TLBR=0; +int L_TLBWI=0; +int L_TLBWR=0; +int L_TLBP=0; +int L_ERET=0; +int L_DI=0; +int L_EI=0; +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +int L_MFC1=0; +int L_CFC1=0; +int L_MTC1=0; +int L_CTC1=0; +int L_BC1F=0; +int L_BC1T=0; +int L_BC1FL=0; +int L_BC1TL=0; +int L_ADD_S=0; +int L_SUB_S=0; +int L_MUL_S=0; +int L_DIV_S=0; +int L_SQRT_S=0; +int L_ABS_S=0; +int L_MOV_S=0; +int L_NEG_S=0; +int L_RSQRT_S=0; +int L_ADDA_S=0; +int L_SUBA_S=0; +int L_MULA_S=0; +int L_MADD_S=0; +int L_MSUB_S=0; +int L_MADDA_S=0; +int L_MSUBA_S=0; +int L_CVT_W=0; +int L_MAX_S=0; +int L_MIN_S=0; +int L_C_F=0; +int L_C_EQ=0; +int L_C_LT=0; +int L_C_LE=0; + int L_CVT_S=0; +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +int L_QMFC2=0; +int L_CFC2=0; +int L_QMTC2=0; +int L_CTC2=0; +int L_BC2F=0; +int L_BC2T=0; +int L_BC2FL=0; +int L_BC2TL=0; +int L_VADDx=0; +int L_VADDy=0; +int L_VADDz=0; +int L_VADDw=0; +int L_VSUBx=0; +int L_VSUBy=0; +int L_VSUBz=0; +int L_VSUBw=0; +int L_VMADDx=0; +int L_VMADDy=0; +int L_VMADDz=0; +int L_VMADDw=0; +int L_VMSUBx=0; +int L_VMSUBy=0; +int L_VMSUBz=0; +int L_VMSUBw=0; +int L_VMAXx=0; +int L_VMAXy=0; +int L_VMAXz=0; +int L_VMAXw=0; +int L_VMINIx=0; +int L_VMINIy=0; +int L_VMINIz=0; +int L_VMINIw=0; +int L_VMULx=0; +int L_VMULy=0; +int L_VMULz=0; +int L_VMULw=0; +int L_VMULq=0; +int L_VMAXi=0; +int L_VMULi=0; +int L_VMINIi=0; +int L_VADDq=0; +int L_VMADDq=0; +int L_VADDi=0; +int L_VMADDi=0; +int L_VSUBq=0; +int L_VMSUBq=0; +int L_VSUBi=0; +int L_VMSUBi=0; +int L_VADD=0; +int L_VMADD=0; +int L_VMUL=0; +int L_VMAX=0; +int L_VSUB=0; +int L_VMSUB=0; +int L_VOPMSUB=0; +int L_VMINI=0; +int L_VIADD=0; +int L_VISUB=0; +int L_VIADDI=0; +int L_VIAND=0; +int L_VIOR=0; +int L_VCALLMS=0; +int L_VCALLMSR=0; +int L_VADDAx=0; +int L_VADDAy=0; +int L_VADDAz=0; +int L_VADDAw=0; +int L_VSUBAx=0; +int L_VSUBAy=0; +int L_VSUBAz=0; +int L_VSUBAw=0; +int L_VMADDAx=0; +int L_VMADDAy=0; +int L_VMADDAz=0; +int L_VMADDAw=0; +int L_VMSUBAx=0; +int L_VMSUBAy=0; +int L_VMSUBAz=0; +int L_VMSUBAw=0; +int L_VITOF0=0; +int L_VITOF4=0; +int L_VITOF12=0; +int L_VITOF15=0; +int L_VFTOI0=0; +int L_VFTOI4=0; +int L_VFTOI12=0; +int L_VFTOI15=0; +int L_VMULAx=0; +int L_VMULAy=0; +int L_VMULAz=0; +int L_VMULAw=0; +int L_VMULAq=0; +int L_VABS=0; +int L_VMULAi=0; +int L_VCLIPw=0; +int L_VADDAq=0; +int L_VMADDAq=0; +int L_VADDAi=0; +int L_VMADDAi=0; +int L_VSUBAq=0; +int L_VMSUBAq=0; +int L_VSUBAi=0; +int L_VMSUBAi=0; +int L_VADDA=0; +int L_VMADDA=0; +int L_VMULA=0; +int L_VSUBA=0; +int L_VMSUBA=0; +int L_VOPMULA=0; +int L_VNOP=0; +int L_VMOVE=0; +int L_VMR32=0; +int L_VLQI=0; +int L_VSQI=0; +int L_VLQD=0; +int L_VSQD=0; +int L_VDIV=0; +int L_VSQRT=0; +int L_VRSQRT=0; +int L_VWAITQ=0; +int L_VMTIR=0; +int L_VMFIR=0; +int L_VILWR=0; +int L_VISWR=0; +int L_VRNEXT=0; +int L_VRGET=0; +int L_VRINIT=0; +int L_VRXOR=0; diff --git a/pcsx2/Decode_XA.c b/pcsx2/Decode_XA.c new file mode 100644 index 0000000..3bd53f4 --- /dev/null +++ b/pcsx2/Decode_XA.c @@ -0,0 +1,305 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ +//=== Modified by linuzappz +//============================================ + +#include + +#include "Decode_XA.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) +#endif + +typedef unsigned char U8; +typedef unsigned short U16; +typedef unsigned long U32; + +#define NOT(_X_) (!(_X_)) +#define CLAMP(_X_,_MI_,_MA_) {if(_X_<_MI_)_X_=_MI_;if(_X_>_MA_)_X_=_MA_;} + +//============================================ +//=== ADPCM DECODING ROUTINES +//============================================ + +static double K0[4] = { + 0.0, + 0.9375, + 1.796875, + 1.53125 +}; + +static double K1[4] = { + 0.0, + 0.0, + -0.8125, + -0.859375 +}; + +#define BLKSIZ 28 /* block size (32 - 4 nibbles) */ + +//=========================================== +void ADPCM_InitDecode( ADPCM_Decode_t *decp ) +{ + decp->y0 = 0; + decp->y1 = 0; +} + +//=========================================== +#define SH 4 +#define SHC 10 + +#define IK0(fid) ((int)((-K0[fid]) * (1<> 4) & 0x0f; + range = (filter_range >> 0) & 0x0f; + + fy0 = decp->y0; + fy1 = decp->y1; + + for (i = BLKSIZ/4; i; --i) { + long y; + long x0, x1, x2, x3; + + y = *blockp++; + x3 = (short)( y & 0xf000) >> range; x3 <<= SH; + x2 = (short)((y << 4) & 0xf000) >> range; x2 <<= SH; + x1 = (short)((y << 8) & 0xf000) >> range; x1 <<= SH; + x0 = (short)((y << 12) & 0xf000) >> range; x0 <<= SH; + + x0 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x0; + x1 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x1; + x2 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x2; + x3 -= (IK0(filterid) * fy0 + (IK1(filterid) * fy1)) >> SHC; fy1 = fy0; fy0 = x3; + + CLAMP( x0, -32768<> SH; destp += inc; + CLAMP( x1, -32768<> SH; destp += inc; + CLAMP( x2, -32768<> SH; destp += inc; + CLAMP( x3, -32768<> SH; destp += inc; + } + decp->y0 = fy0; + decp->y1 = fy1; +} + +static int headtable[4] = {0,2,8,10}; + +//=========================================== +static void xa_decode_data( xa_decode_t *xdp, unsigned char *srcp ) { + const U8 *sound_groupsp; + const U8 *sound_datap, *sound_datap2; + int i, j, k, nbits; + U16 data[4096], *datap; + short *destp; + + destp = xdp->pcm; + nbits = xdp->nbits == 4 ? 4 : 2; + + if (xdp->stereo) { // stereo + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp+0, 2 ); + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->right, sound_groupsp[headtable[i]+1], data, + destp+1, 2 ); + + destp += 28*2; + } + } + } + else { // mono + for (j=0; j < 18; j++) { + sound_groupsp = srcp + j * 128; // sound groups header + sound_datap = sound_groupsp + 16; // sound data just after the header + + for (i=0; i < nbits; i++) { + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] & 0x0f) | + ((U16)(sound_datap2[ 4] & 0x0f) << 4) | + ((U16)(sound_datap2[ 8] & 0x0f) << 8) | + ((U16)(sound_datap2[12] & 0x0f) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+0], data, + destp, 1 ); + + destp += 28; + + datap = data; + sound_datap2 = sound_datap + i; + if ((xdp->nbits == 8) && (xdp->freq == 37800)) { // level A + for (k=0; k < 14; k++, sound_datap2 += 8) { + *(datap++) = (U16)sound_datap2[0] | + (U16)(sound_datap2[4] << 8); + } + } else { // level B/C + for (k=0; k < 7; k++, sound_datap2 += 16) { + *(datap++) = (U16)(sound_datap2[ 0] >> 4) | + ((U16)(sound_datap2[ 4] >> 4) << 4) | + ((U16)(sound_datap2[ 8] >> 4) << 8) | + ((U16)(sound_datap2[12] >> 4) << 12); + } + } + ADPCM_DecodeBlock16( &xdp->left, sound_groupsp[headtable[i]+1], data, + destp, 1 ); + + destp += 28; + } + } + } +} + +//============================================ +//=== XA SPECIFIC ROUTINES +//============================================ +typedef struct { +U8 filenum; +U8 channum; +U8 submode; +U8 coding; + +U8 filenum2; +U8 channum2; +U8 submode2; +U8 coding2; +} xa_subheader_t; + +#define SUB_SUB_EOF (1<<7) // end of file +#define SUB_SUB_RT (1<<6) // real-time sector +#define SUB_SUB_FORM (1<<5) // 0 form1 1 form2 +#define SUB_SUB_TRIGGER (1<<4) // used for interrupt +#define SUB_SUB_DATA (1<<3) // contains data +#define SUB_SUB_AUDIO (1<<2) // contains audio +#define SUB_SUB_VIDEO (1<<1) // contains video +#define SUB_SUB_EOR (1<<0) // end of record + +#define AUDIO_CODING_GET_STEREO(_X_) ( (_X_) & 3) +#define AUDIO_CODING_GET_FREQ(_X_) (((_X_) >> 2) & 3) +#define AUDIO_CODING_GET_BPS(_X_) (((_X_) >> 4) & 3) +#define AUDIO_CODING_GET_EMPHASIS(_X_) (((_X_) >> 6) & 1) + +#define SUB_UNKNOWN 0 +#define SUB_VIDEO 1 +#define SUB_AUDIO 2 + +//============================================ +static int parse_xa_audio_sector( xa_decode_t *xdp, + xa_subheader_t *subheadp, + unsigned char *sectorp, + int is_first_sector ) { + if ( is_first_sector ) { + switch ( AUDIO_CODING_GET_FREQ(subheadp->coding) ) { + case 0: xdp->freq = 37800; break; + case 1: xdp->freq = 18900; break; + default: xdp->freq = 0; break; + } + switch ( AUDIO_CODING_GET_BPS(subheadp->coding) ) { + case 0: xdp->nbits = 4; break; + case 1: xdp->nbits = 8; break; + default: xdp->nbits = 0; break; + } + switch ( AUDIO_CODING_GET_STEREO(subheadp->coding) ) { + case 0: xdp->stereo = 0; break; + case 1: xdp->stereo = 1; break; + default: xdp->stereo = 0; break; + } + + if ( xdp->freq == 0 ) + return -1; + + ADPCM_InitDecode( &xdp->left ); + ADPCM_InitDecode( &xdp->right ); + + xdp->nsamples = 18 * 28 * 8; + if (xdp->stereo == 1) xdp->nsamples /= 2; + } + xa_decode_data( xdp, sectorp ); + + return 0; +} + +//================================================================ +//=== THIS IS WHAT YOU HAVE TO CALL +//=== xdp - structure were all important data are returned +//=== sectorp - data in input +//=== pcmp - data in output +//=== is_first_sector - 1 if it's the 1st sector of the stream +//=== - 0 for any other successive sector +//=== return -1 if error +//================================================================ +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, int is_first_sector ) { + if (parse_xa_audio_sector(xdp, (xa_subheader_t *)sectorp, sectorp + sizeof(xa_subheader_t), is_first_sector)) + return -1; + + return 0; +} + +/* EXAMPLE: +"nsamples" is the number of 16 bit samples +every sample is 2 bytes in mono and 4 bytes in stereo + +xa_decode_t xa; + + sectorp = read_first_sector(); + xa_decode_sector( &xa, sectorp, 1 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + + while ( --n_sectors ) + { + sectorp = read_next_sector(); + xa_decode_sector( &xa, sectorp, 0 ); + play_wave( xa.pcm, xa.freq, xa.nsamples ); + } +*/ diff --git a/pcsx2/Decode_XA.h b/pcsx2/Decode_XA.h new file mode 100644 index 0000000..d363fb4 --- /dev/null +++ b/pcsx2/Decode_XA.h @@ -0,0 +1,26 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct { + long y0, y1; +} ADPCM_Decode_t; + +typedef struct { + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/pcsx2/Docs/BetaTesters.txt b/pcsx2/Docs/BetaTesters.txt new file mode 100644 index 0000000..3d15fb1 --- /dev/null +++ b/pcsx2/Docs/BetaTesters.txt @@ -0,0 +1,13 @@ +Current PCSX2 Beta-Testers-Slaves :P : + +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever +Seta-San +Nave diff --git a/pcsx2/Docs/ChangeLog.txt b/pcsx2/Docs/ChangeLog.txt new file mode 100644 index 0000000..b8c4bd1 --- /dev/null +++ b/pcsx2/Docs/ChangeLog.txt @@ -0,0 +1,2851 @@ +[ Legend: ] +[ + Added feature ] +[ * Improved/changed feature ] +[ - Bug fixed (we hope) ] +[ ! Attention (Notes) ] +[ M Maintenance ] +[ dates are dd/mm/yyyy !!! ] + +ChangeLog: + v0.9.3: + * 26/11/06 [*] Version 0.9.3 started :) + (Refraction) + v0.9.2: + * 30/10/06:[*] Improved the way Unpacks are handled slightly, just so its a little quicker (not much) + [-] MMI bug causing corrupt characters on Max Payne fixed + [-] Performance counters corrected in INT and REC + [-] Branches in a branch delay slot no longer results in a crash + [*] Changed Run CD to Run CD/DVD, ps2 doesnt use CD's much :P + [*] Removed "Advanced" from the menu, not required anymore (at the moment) + [-] Small alteration to IPU transfers, ending the transfer too quickly + [-] Made a seperate branchtest for INT, fixed the VU not running on the bios in INT + (Refraction - Zerofrog) + + * 16/10/06:[-] Counter bugz again, seemed to effect the text in xmen + [-] Fixed an ipu bug which stopped the GTA San Andreas videos working + [-] couple more smaller unpack changes to remove a hack + (Refraction) + + * 15/10/06:[*] Moved some declarations from patch.c to patch.h + [-] Fixed problem with XML patch loading (see above). + [+] Merged my WIP cheat finder dialog (note WIP). + (Gigaherz) + + * 11/10/06:[+] Added XML Patch support + [-] More unpack fixes for GT3/GT4, Xmen, Midnight Club 2, FFX sky, Whiplash and more :) + (Refraction - Gigaherz) + + * 05/10/06:[-] Fixed VIF Unpack skipping write cycle counting (Fixes XMen 2 amongst other SPS) + [-] Small counter change, am i ever going to get peace from these :( + (Refraction) + + * 03/10/06:[-] Fixed MFIFO issue where VIF/GIF might not be ready + [*] Improved Guitar Hero fix, seems MFIFO isnt too keen on sliced transfers (especially on GIF) + [*] Modified VS2005 Project file so it compiles - Thanks to CKemu for doing that :P + (Refraction - CKemu) + + * 02/10/06:[*] Various changes in cdvd.c. Most notable is the implementation of cdvd.PwOff. + It is actualy INTR_STAT and has "completition" bits that are Ack'ed by cdvdman interrupt handler. + ...to be continued. + (Florin) + + * 30/09/06:[*] Corrected performance counter register reads on COP0 (3 regs are accessed by 1) - Lego Racers 2 + [-] Altered the order DIV on IOP rec handles signs - Lego Racers 2 + (Refraction) + + * 29/09/06:[-] Fixed condition where MFIFO could get ahead of itself/not have enough data available + (fixes Guitar Hero) + [-] Fixed up DMA Stalls between VIF/IPU/GIF, games such as Theme Park World should work properly now. + [+] Added cpu detection for Dual core Opterons, Athlon X2's and Intel Core 2 Duo's (no perf effect) + [+] Added saqibs sound changes so ADMA and ADPCM streams work. + [-] Yes, more counter fixes, fed up of these :P + [-] DMA transfers fixed when a QWC is already given, it transfers the QWC then ends (Fixes Ridge Racer 5 a bit) + [-] Small GSCSR changes, not sure what will be fixed. + [-] Event where the DMA could be terminated during a stall on VIF + [-] Various Rec + MTGS + IPU Fixes + (Refraction - Saqib - ZeroFrog) + + * 25/07/06:[-] Changed Vif0 COL/ROW mem write addresses, they were going to the same QW + [*] Made Vif stalls use cycles to delay, due to the spiderman fix we dont want these interrupting instantly! + (fixes Flatout BIFCO) + [-] Call/Ret now update the ASR status in the CHCR register + [-] Couple of small fixes to Tag BUSERR, altho i hope we never need them :P + [+] Added seperate EE counter logging + (Refraction) + +v0.9.1: + * 28/06/06:[+] MAJOR CHANGE: All recompilers and memory code rewritten. + eeRec now does block analysis, constant propagation, liveness + analysis, mmx/xmm reg caching, etc. + vuRec is about 10x faster than older vurec. Both VU0 and + VU1 recs work and share the same code. + iopRec - does same as eeRec, except is simpler + Altogether, 3D scenes are 2-4x faster than 0.9 release. + (zerofrog) + * 09/05/06:[*] Moved repository to SVN. Play nice. Any questions... you know where to find me + [+] new developer blogs from me and auMatt + (Florin-auMatt) + + * 05/05/06:[*] Changed names of the SSBUS registers in PsxHw.c + [!] dev1 is rom bus, dev5 is cdvd bus, dev9 is ata|smap|dvr|uart|flash bus + (Florin) + + * 04/05/06:[+] Added atad and dev9 functions names to psxinterpreter.c + (Florin) + + * 01/05/06:[+] Added *pass-through* MagicGate support. It will work with pre-decrypted files + (Florin) + + * 30/04/06:[-] Fixed (almost:P) the debug bios for remote debugging in WinMain.c + [*] Added PSX detection in Misc.c + [+] Added DevBlog.txt file to Docs. Please read and contribute. + (Florin) + + * 15/04/06:[M] Removed some *shit*; please don't commit *.suo/aps/opt/plg/ncb/exp files + [*] added/fixed some scmd commands in cdvd.c + (Florin) + + * 13/04/06:[*] Implemented CDVD Scmd 0x3E(set OSDVER for PSTwo), Thanks to loser for info. + (auMatt) + + * 12/04/06:[!] Uploaded to CVS the latest version, (fixed vc2005 project, + converted all files to CR/LF ending) + [!] When commiting to CVS, please write same text to comment as in here + [*] Changed the _MSC_VER version displaying; hoping ms will keep it linear :) + [*] Implemented properly CDVD Scmd 0x36 (get OSDVER for PStwo) + (Florin) + + * 10/04/06:[!] Changed to version 0.9.1 + [-] Fixed some Vif FIFO bugs and moved VIF interrupt to check the channel has ended + [-] Fixed some counter bugs (better now i can test on my ps2!) + [!] This code is not perfectly stable and contains debug printouts! It is purely for the other + devs who dont have the latest code ;) + (Refraction) + + v0.9: + * 02/04/06:[+] VU0 Rec added, still buggy + [*] VU1 Speedups and fixes, needs more testing but seems better + [*] CDVD Timing Improved wait times for commands reduced. + [-] Misc eeRec bug fixes made + [*] Vif stalls greatly improved loads more games now work! + [*] Counters modified with gates and improved accuracy + [*] Cycle counting in EE/IOP done on branches to cut download + 2D speed up by over double! + [-] Misc VIF unpack fixes + [-] GIF Stalls should now work correctly + [+] Virtual Memory for Windows XP users, quicker than TLB + [*] Difference CPU options can be mixed and matched by users choice + [-] SIF communication fixed, games can now be booted via the bios (in most cases) + [!] Lots of other fixes have been made by due to lazyness we didnt document! :D + [+] MTGS and Dual Core modes added which are VERY experimental! + [!] This is the FINAL code for 0.9 enjoy! + (Refraction, ZeroFrog, Saqib) + * 15/02/06:[+] Multithreaded GS/Dual Core Support + (zerofrog) + * 17/01/06:[-] Some changes in CDVD tray status + (efp) + + * 16/01/06:[-] Fixed sticky flags. + [*] Implemented/Fixed a lot of vu functions in vurec. VuRec now properly checks for underflow/overflow + (zerofrog) + * 15/01/06:[-] Bug fixes in VU rec/interp (Ebit, xgkick). Added 24bit precision for VUs. + [*] Changed all math functions to use the C++ floating point versions. + (zerofrog) + * 14/01/06:[-] VU Flag fixes + double removal (it needed doing) from zerofrog + [-] Disabled an old PSX Counter hack that i left in some how! + [*] Changed SIF reg code to something simpler and less time consuming + (Refraction) + * 13/01/06:[*] Fixed mac update flags for vu interpreter. + (zerofrog) + + * 12/01/06:[-] Changed IPU.c, thread syncing issue fixed by zerofrog + [*] Altered SBUS so it is triggered on PSX dma + [*] Removed a load of IOP hacks, should improve compatability in some cases + [!] A lot of changes have been made since 05/09/05 but weve lost track, whoops + (Refraction Saqib zerofrog) + + * 05/01/06:[*] Added GSreadFIFO2 for faster reads from GS. + [-] Fixed the multi-threaded IPU and added sync primitives for interrupts and DMA. + The green squares should be gone too. + (zerofrog) + + * 05/09/05:[-] Fixed VU-Rec crash if the pc overflowed the vumem, thanks to fumofumo! + [*] New Icon for 0.9 made by CKemu + [+] Vsync rate now selectable, current Vsync speed is default but less compatable in + some cases, option selects real vsync speed, syncs sound correctly. + (Refraction) + + * 03/09/05:[-] IOP rec & VU0rec fix, x86ptr being set in the wrong place, also a couple of vu-rec op fixes + thanks to fumofumo on irc. + [-] Slowed VSync down to actual speed, so sound isnt half the speed of the graphics, + a few more changes to counters as well, BOR works again, just slower ;p + (Refraction) + + * 30/08/05:[-] Few more changes to the counters, seems much better again, last fix killed stuff + [-] VSync rate now actually changes between PAL and NTSC, before it was stuck in NTSC + [-] Couple of changes in VIF + * 24/08/05:[-] Readded setting of Done on VIF1 TTE, added the same on VIF0 + [-] Applied VIF1 FBRST fix to VIF0 too + [-] Fixed problem causing Beats Of Rage to skip and altered slow sound prob again. + (Refraction) + + * 23/08/05:[-] Did some more timing fixes, they should be a LOT more compatable now + [-] Small change to FBRST, was causing crashes if VIF was finished. + [+] Added counter copy to hold on SBUS interrupt + (Refraction) + + * 21/08/05:[-] Few fixes in the eeRec, shouldnt crash on Kingdom Hearts now, Thanks to fumofumo! + [-] Fixed a bug in FBRST and Vif1, altho theres still an interrupting problem somewhere :/ + [-] Int VU now uses Single Precision (its faster) with no loss of graphics. + [-] Made sure MAC, CLIP and STATUS flags are all located on VU0. + [*] Enabled linuz's SSE unpack code, gives a nice little speed boost, works ok :) + [-] VU execute blocks limited to 128, seems a little faster, no loss of graphics, seems + to fix a few looping infinately issues (VU not breaking) (GiGaHeRz) + [-] Hack removed on TLBP, should hopefully work ok, doesnt seem to break anything (GiGaHeRz) + [+] Added SPU2 hack, should fix some games, not compatable with videos tho. removed fast dvd + [-] More counter stuff, also added gating to IOP counters, not totally sure on it. + [-] Added a couple of checks in VU & eeRec to make sure the constant registers werent overwritten + [-] Temp fix for the dma alignment error on GIF + [-] modified dma timings, qwc / BIAS could mess up if qwc = 1 + [-] Singled out some problematic VU-Rec ops that cause FFX to hang and borkey graphics. + (Refraction) + + * 12/08/05:[*] Few more timing things, music shouldnt be slow anymore on games and cleaned up + counters a bit. + [+] Added SBUS register logging on IOP side + [-] Temp fixed a MAC flag problem in vu-rec till linuz sorts it properly + [*] Committed new logo, nice job CKEmu ;) + [*] Vu-Rec now supports non SSE2 processors thanks to kekko for the changes! + (refraction) + + * 05/08/05:[+] Added faster Cd/DVD reads to the Advanced options (Refraction) + [-] The previous DVD/CD change by ref was just a hack, so i commited the old + version again + [-] I've commented out RECOMPILE_VUMI_LOADSTORE on iVUmicro.h, instead + of commenting it out in iVU1micro.c as ref did on last update, + that way is better until i fix the real problem + [*] Improved vuDIV for .x to .x cases + [+] Added PEXTRW/PINSRW + (linuzappz) + + * 05/08/05:[-] Fixed a couple of VU-Rec ops, swapped some over to the interpreter to fix 2d + (thanks to fumofumo for the tipoff) + [-] Yes more timing stuff :P think its as compatable as its going to get now. + [*] DVD/CD reads now considerably faster, some loading times down by 1600%!!! + Compatability still good :) + [-] Fixed a bug in 128bit hardware reads + [-] Fixed a bug i made in VU which messed graphics up eg Frequency and Sega Tennis + (refraction) + + * 04/08/05:[-] More IOP/EE timing fixes, Thanks for the info linuz + [-] Vsync speeds shouldnt be as insane as they were, the target was set as 1/4 the rate + instead of 1/2! + [!] 32bit timer interrupt checks arent working properly eg. overflow only works + when checking if they are equal, on target only works on overflow :/ but the checking + method which was used in SafeIOP is more accurate. + (refraction) + + * 03/08/05:[-] Fixed FTOX in VUrec + (linuzappz) + + * 31/07/05:[-] Reverted to old Branchtarget's, seems to stop the RecUNKs + [-] Fixed the timing a bit between IOP & EE, shouldn't need SafeIOP anymore :D + [-] Removed Pointless While loops on GIF & SPR, also fixed condition where SPR0 + couldn't use destination chain mode + [!] Gating on the IOP needs checking/completing, i have no docs on it so + i can't check the values for it, they seem different to EE :/ + [-] Removed GS Stall checking on GIF, could have caused it not to send data. + [*] Added code for faster V4-32 unpacks when CL == WL + [*] x86 code kept in int format for rec instead of U8 to INT conversion (GiGaHeRz) + (refraction) + + * 21/07/05:[-] Fixed setting of the Double Buffer + [-] Fixed the Branchtarget's for R3000A and R5900 + [*] Altered some stuff in vuflags, seems to give a speed boost :P + (refraction) + + * 18/07/05:[-] Removed some useless & 0xffff on Hw.c + [-] Reverted Sif changes to the old code, + gotta speak about this with refraction + [+] Added VIF1_STAT at vif1Write32, to handled the FDR bit + [-] VIF1 now clears qwc with "from memory" transfer + (linuzappz) + + * 17/07/05:[-] Fixed a bug in VIF where done could be unset + [-] Fixed a couple of bugs in VU + [*] Rewrote SIF0, seems to be a bit more compatable as well + as more readable + [-] Altered the loops for vu(1/0)exec, seems to fix some graphics + without comprimising compatability + (refraction) + + * 12/07/05:[-] Fixed VIF stop on stall occurance (refraction) + [-] Added two common funcs for source chain dmas + [-] Fixed REFE and END (even once again) in dmas + [-] Fixed interrupt i bit issue in Vif1 (on multiple i bits) + (linuzappz) + + * 08/07/05:[-] MFIFO now wraps around the ring buffer when it's full, + in both GIF/VIF1 + (linuzappz) + + * 06/07/05:[-] Bug in DIRECT/HL caused vif errors + [-] Recomitted old VIF0 IRQ stuff, seemed to cause problems + (Refraction) + + * 05/07/05:[-] Fixed IRQ setting for VIF0 transfers (Refraction) + [*] Removed Call/Ret from SPR1, not used (Refraction) + [+] Added some more comments to DMA stuff (Refraction) + [-] Reimplemented the old vifunpack code, since saqib's one + had problems 'in pieces' transfers + [-] ElfHeader now loads the data though the program headers only + [-] Removed tadr+= 16 on refe/end on dmas + [!] I'll start commenting more the code from now on, so it'll + be easier for us to understand every part of pcsx2, others + pls do the same kthx + (Refraction-linuzappz) + + * 02/07/05:[-] Added saqib vif fixes + [-] Fixed Stall canceling stat bits (VIF_STAT_INT) + [-] Fixed Stall bits clearing + (Refraction-saqib-linuzappz) + + * 29/06/05:[*] iR3000A now has defines same as iR5900.c + [+] Added PSXCNT_LOG + (linuzappz) + + * 28/06/05:[+] Added InterlaceHack (usefull for Dinasty Warriors 3) + [+] Added SafeCnts flag, which makes very accurate iop counters, + but they make pcsx2 slower + [+] Added FastIopClk which sets the PsxClk to 86864000 + [!] There are sorta hacks and will go away in time when i figure + out how to really fix them + (linuzappz) + + * 28/06/05:[+] Added SIO plugin specs. Should be followed by compatible plugins :P + (Florin) + + * 22/06/05:[-] Console supports colors ;) + (linuzappz) + + * 19/06/05:[-] Fixed D/T flags (added interrupts) at VU0/1 + (linuzappz) + + * 18/06/05:[-] Rather small fixes to last update in vif, replaced cyclenum + with _vif->cl, also fixed a timing issue in vif0 + (linuzappz) + + * 14/06/05:[-] Alot of bugs fixed in VIF. Masking was not correct so was + filling write. VIF0 was incorrect. The VIF0 Fifo was always being set to 0. + [-] dmaSPR1 now handles Transfer Tag option. + (saqib and Refraction) + + * 31/05/05:[-] Fixed UNPACK's with masking + (linuzappz) + + * 29/05/05:[-] Fixed a few small timing issues with VIF1 + [-] Refixed end source chain tag to add 16 to tadr + (linuzappz) + + * 28/05/05:[*] Uncommented GS dma irq code + [-] Fixed some switch cases at iVUmicro.c + [-] Tested/Fixed DIS_S/MAX_S/MIN_S at iFPU.c + (linuzappz) + + * 28/05/05:[*] removed CVT_S regcaching from iFPU.c. That doesn't seem to work properly :~ + [*] Added MAX_S , MIN_S to reg caching iFPU.c . Not tested but should work + (shadow) + + * 28/05/05:[+] Added PNOR and impoved a few more MMI opcodes + [+] Few more opcodes to ix86_sse.c as well + (shadow) + + * 26/05/05:[+] added emulated hardware cd/dvd sector decryption routines + (should make the playstation2 logo display correctly now amoung other things) + [-] fixed cdvdReadKey to get correct args sent to it, also behaves a little differently depending on args + (loser) + + * 26/05/05:[*] fixed a silly bug in iMMI.c pmaxh,pminh opcodes + [*] optimized PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + [*] few more addes to ix86_sse.c . Linuz seemed to discovered new opcodes :P + (shadow) + + * 25/05/05:[+] Few opcodes added in ix86_sse.c .Few of them still needs recheck (shadow- Gabest) + [*] Added the following SSE,SSE2 opcodes to iMMI.c . + paddub,padduh,paddh,pcpyld,pmaxh,pminh,paddsb,paddsh,psubsb,psubsw,paddb,paddw,psubsb,psubsh + psubb,psubb,psubh,psubw + [*] More opcodes in SSE2 . PCPYUD,PSRLW,PSRLH,PSRAH,PSRAW,PSLLH ,PSLLW ,PCEQB,PCEQH,PCEQW,PCGTB,PCGTH,PCGTW + (shadow) + + * 24/05/05:[*] PSXCLK now can be changed at the ini, defaults + to the right value (36864000) if it's 0 anyways + [-] Fixed bug at Interpreter.c for sstates + (linuzappz) + + * 23/05/05:[-] fixed a bug in iMMi.c PADDSD,PSUBSD doesn't exist in ix86 (who added them?) + [*] Added a new prefix in ix86_SSE opcodes, it is now more clear to understand what each opcode do + that also helped to find that linuz had added an SSE2 instruction in iFPU.c bad linuz ;P + [-] PSMAXSW,PSMINSW was writing to a XMM register (the SSE version writes to MMX register) fixed.. + [+] a few more SSE2 instructions needed for iMMI.c added in ix86_sse.c . + Linuz code them properly pls ;) + (shadow) + + * 23/05/05:[+] Added Devc++ 4.9.9.2 project files for compiling mingw32 with IDE :) + [-] Added a few missing defines + [!] still my project file can't make as fast exe as linuz's sse build. can't figure why yet + the problem should me around Makefile.win :~ + (shadow) + + * 21/05/05:[-] More PS1 compat fixes + [!] Seems the GPU->GS is done by the PS1DRV, gotta find out more + (linuzappz) + + * 19/05/05:[+] PS1 games kinda boot now as well ;) + (linuzappz) + + * 16/05/05:[-] Misc GUI fixes + (linuzappz) + + * 15/05/05:[-] More FPU regcaching stuff + [!] Finally changed version to 0.9 :D + (linuzappz) + + v0.8: + * 10/05/05:[-] Added some more code for FPU regcaching, still unused + [!] Code is closed today until release, only bugfixes now + (linuzappz) + + * 08/05/05:[-] More fixes/improvemets to VUrec/iFPU + (linuzappz) + + * 07/05/05:[-] COP2 now is recompiled when VUrec is enabled + (linuzappz) + + * 05/05/05:[-] Fixed a rather small bug in VIF1 unpack + [-] VU random functions are more correct now, thx goes to _Riff_ and saqib + [-] Sio arranged better for sstates + [*] Modified "FireWire" syms to "FW" + (linuzappz) + + * 04/05/05:[-] Timings in VIF1 should be more accurate now + [-] Fixed bug in the elf loading filter + (linuzappz) + + * 02/05/05:[*] recommited the old reccop2.c (shadow) + + * 02/05/05:[-] Fixed bug in REF/REFS dma at VIF1/GS MFIFO + (saqib) + + * 02/05/05:[*] Cpudialog will disable the checkboxes if the requested features not found + (shadow) + + * 01/05/05:[*] Created a new <> folder to clean up some stuff in the existing interface + Folders became better now and included project files only for vcnet2003 so far... + [*] Moved all patchbrowser source to patchbrowser.c and added language support for it + [*] CpuDialog is now At CpuDlg.c . Redone the Dialog a lotta better ;) + [*] The remaining console,thread,patches configure are now part of the main menu + [*] Organize cpudetection code a bit better. Cpudetection is now done in winmain.c + (shadow) + * 01/05/05:[*] Even more VUrec stuff + [+] Added some more Stats.c info per frame + [-] Fixed some MFIFO bugs remaining + (linuzappz) + + * 30/04/05:[*] More work on VUrec, flags are somehow implemented, PSHUFD is now + used to unpack XYZW/IQ stuff and bug fixes as well :) + (linuzappz) + + * 29/04/05:[-] Updated VIF0 code as VIF1 + [-] VIF1 doens't clears str on MFIFO (saqib) + [-] Fixed some MFIFO bugs in both GS/VIF1(saqib) + [*] Cleaned up dma## functions + (linuzappz) + + * 28/04/05:[-] end source chain tag seems not to touch tadr + [-] Vif1 dmaIrq seems ok, need to test it more tough + (linuzappz) + + * 26/04/05:[+] Added BC1 ops at rec + [+] Started some optimizations for UNPACK + [-] Skipping vif mode was still a bit buggy, seems ok now + (linuzappz) + + * 25/04/05:[*] VIF1 dma is kinda more asynchonous now + (linuzappz) + + * 22/04/05:[+] Added some cache code, not used by default, + it's just for testing atm + (linuzappz) + + * 21/04/05:[-] Readded SysPrintf for Cd/DvdReads + [-] Fixed NReady busy stuff, thx to loser + (linuzappz) + + * 19/04/05:[-] More VUrec refixing/work + (linuzappz) + + * 18/04/05:[+] added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose + to the cdvd plugin definitions + [*] changed CDVDgetType to CDVDgetDiskType + [-] fixed NVM (eeprom) access from cdvd stuff + [+] added reading of mecha version from an external file + [-] fixed raw dvd sector readng for dvd9 discs (otp and ptp) + [+] added hw-reg read/write for DecSet register 0x1f40203A + [+] made cdSeek change the current cdvd sector + [*] incremented cdvd plugin version and brought cdvd plugins in cvs up to date + (loser) + [-] __WIN32__ should not be used over PS2Etypes.h, + __MSCW32__ or __MINGW32__ must be used there + (linuzappz) + + * 16/04/05:[-] xyzw stalls was kinda wrong ;P seems ok now + [-] Fixed a bit vurecs + (linuzappz) + + * 16/04/05:[+] Added GSsetCSR + (saqib-linuzappz) + + * 14/04/05:[-] Fixed some small bugs over VUops.c for the regsNum stuff, + thx goes to saqib + [-] Really fixed skipping vif this time :P + [-] Fixed DIV/RSQRT exceptions (saqib-linuzappz) + (linuzappz) + + * 13/04/05:[-] Fixed skipping write mode at Vif + [-] Fixed unpack overflowing + (linuzappz) + [-] updated all visual studio project files to have the correct source/lib/includes + also removed unused dirs and files. now even 'debug config' will build ok :) + (loser) + + * 10/04/05:[-] Fixed stalls for VF regs, xyzw must be handled separatedly + (linuzappz) + + * 04/04/05:[-] Kinda reworked VU MAC flags, also fixed RSQRT neg prob, thx to Riff/saqib + [-] Fixes to VifDma cl/wl stuff + (linuzappz) + + * 03/04/05:[*] Modified a bit how branch works on VUs + (linuzappz) + + * 02/04/05:[-] Some fixes to VU flags/pipelines + (linuzappz) + + * 30/03/05:[*] Cleaned up a bit writes to VIFX regs + [-] Fixed a small bug in vif1 stalls + [-] Commented readclock win32 code at CDVD.c + [-] Fixed two small issues with branches in interp + (linuzappz) + + * 29/03/05:[*] Added some fixes from LDChen to hConsole/WM_PAINT stuff + [*] Modified GetToc stuff in cdvd to support dvds + [*] cdvdTD uses lsn now + (linuzappz) + + * 28/03/05:[+] Added placetopatch == 1, which means patches will be applied every vsync ;) + (linuzappz) + + * 27/03/05:[*] Improved cpu detection for Amd's 64 using BrandID. Most of the models should be + detected correct now (at least my cpu does ;P) (shadow) + + * 24/03/05:[-] Fixed ISUBIU :D + [-] Some fixes to flags, status was fecked, now seems better + [-] Commented the GS dma IRQ again, seems to cause more probs, will + fix it later + (linuzappz) + + * 21/03/05:[-] Fixed VIFX_CODE reg + [+] Added previous normal vu fixes to vurec + [*] Added EFU pipeline to VUmicro, kinda untested + [-] Hopefully fixed GS dma IRQ + (linuzappz) + + * 21/03/05:[-] Fixed cdReadKey function to emulate correctly. Now games should boot using + Execute with non Modded Bios. + (auMatt & Loser) + + * 20/03/05:[-] Started reg caching for VUrec ;D + [*] Rearrenged a bit rec32/64, added a common 'x86' dir + (linuzappz) + + * 18/03/05:[-] VU1micro was being executed instead of VU0, bad linuz bad :P + [-] Fixed VU's JR/JALR/BAL :D + (linuzappz) + + * 17/03/05:[-] Cleanup/speedup/fixup from last fixes :P + [-] VIF0 has no from mode ;) + (linuzappz) + + * 16/03/05:[*] Added some more debug info to CDVD + (auMatt) + + * 15/03/05:[*] Added an evil vuDouble function to convert from vu float format + to ieee 754 format ;) + [-] Reworked MAX/MINI + [+] Added experimental work for VU pipelines + (linuzappz) + + * 14/03/05:[-] Added the pipelines VU1 bug to VU0 + (linuzappz) + + * 12/03/05:[-] Fixed some pipelines bug within VU1 + (linuzappz) + + * 10/03/05:[-] Fixed small bug over VIF1 dma FIFO + (linuzappz) + + * 08/03/05:[-] Fixed vu flushing over vuExecMicro + (linuzappz) + + * 06/03/05:[-] Fixed UNPACK V4_5 with mask + (linuzappz) + + * 04/03/05:[-] Small fixes to VUrec + (linuzappz) + + * 01/03/05:[+] Added new VS2005 sln and .vcproj to build the 32bit version of + pcsx2 in VS2005 Beta1 (You have to use different projects to build) + [*] Changed some of the files to make them compile in VS2005. + (GoldFinger) + + * 23/02/05:[-] Commented hack at VSync + [+] Added interleave mode for SPR + (linuzappz) + + * 20/02/05:[*] Changed IRQ defines to functions + [-] VIF irq by vifcode seems ok now + [+] Added offset/difference with mask UNPACK modes in vif + [-] SPR1 was transfer /4 the size it should have :/ + (linuzappz) + + * 16/02/05:[-] Fixed some VPU-STAT related issues + [+] 'sstates' dir is now created at init + (linuzappz) + + * 15/02/05:[+] Another DNAS by nachbrenner + (linuzappz) + + * 14/02/05:[+] Added offset/difference UNPACK modes in vif + (linuzappz) + + * 14/02/05:[*] 64bit rec back to x86-64 better this way + [*] Updated vsnet2005beta1 project files to compile with x86-64 dir + [*] Added a few pragma warnings disable to a few files to correct some silly vsnet2005beta1 + warnings (blah MS deprecated stdio pffff) (shadow) + + * 10/02/05:[-] Fixed bug in CDVD_findfile + (linuzappz) + + * 09/02/05:[*] GSvsync is now called on the vsync start + (linuzappz) + + * 08/02/05:[*] QWC is set to 0 after a normal transfer in GS/SPR1/VIF1 + and MADR is increased qwc*16 as well + (linuzappz) + + * 07/02/05:[*] Changed a bit the CPU dialog. Now it is better i guess :) . Linuz update the pcsx2.po again pls :D + [*] Added a __VCNET2005__ definition cause vcnet2005beta1 doesn't support inline asm.. + That only effects Cpudetection.c and Gte.c (not much since it has c code instead to use). + Cpudetection must be written on ml64 to be useable on vcnet2005. + [*] Added prelimary vcnet2005beta1 project files. gettext disabled cause we still doesn't have a + 64bit version for it + [*] Small fixes around and wholaaa i produced the first buggy pcsx2_64bit.exe :) (shadow) + + + * 07/02/05:[+] Added another DNAS version thx to Nachbrenner + [-] Fixed SPR0 chain mode + [-] Fixed intc/dmac interrupts that gets cleared right away + [-] Cleaned up langs a bit, only spanish works so far now + [+] Added 1f402007 reg, "BREAK", still not really handled ;P, + thx to matt + (linuzappz) + + * 31/01/05:[-] Disabled recompile functions recBGEZ() and recBLEZ() from iR3000.c . That will make + recompiler not to crash after the players selection screen in Virtua Fighter 4. Thanks + to JayteeMaster for bug tracing it ;) (shadow) + + * 30/01/05:[-] Fixed some more bugs in IPU, some streams had a few problems, now they are ok. + Quality of ipu playback also improved(thanks JayteeMaster for pointing it out) + (asadr aka saqib) + + * 26/01/05;[*] Merged a big part of linuz's amd64 rec to the normal rec (shadow) + + * 25/01/05:[-] Finally fixed IPU. Mpegs and IPU streams run + so do PSS files.Some fixes to MMI and Interpreter (asadr) + + * 23/01/05:[-] Fixed vurec crash on pcs that doesn't support SSE2 + [*] General cleanup on ix86-32 rec. Goldrec removed since no progress has been made + lately (shadow) + + * 20/01/05:[+] Added x86-64 rec, still unclean, but i'll leave for holidays this + saturday, so ^^ + (linuzappz) + + * 19/01/05:[-] Fix for end chain mode at vif, still gotta check it + (linuzappz) + + * 16/01/05:[-] Lots of fixes to VUmicro, thx to Refraction for pointig out + some bugs ^^ + [*] Commited ix86 changes for x64 + (linuzappz) + + * 13/01/05:[-] WriteNVM now takes address in param[1], thx to auMatt + (linuzappz) + + * 06/01/05:[-] Fixed long types at VU.h + [-] Removed memLUT decl + [!] Notice long is 8bytes long in amd64, so we should + stick to the u32/s32 types instead of using long pls :) + (linuzappz) + + * 06/01/05:[-] Fixed SBUS IRQ at iop + [-] dmaGetAddr now uses memLUTR + (linuzappz) + + * 05/01/05:[*] Changed some stuff for amd64, still more to come + [+] Added more memRead/Write funcs for speed + [-] Fixed some iVUmicro bugs + [-] Fixed QFSRV/MTSAH/MTSAB + (linuzappz) + + * 03/01/05:[+] Implemented MFLAG for VU0 + [-] Vsync is now genereted on boths cpus at the same time + (linuzappz) + + * 03/01/05:[-] Commented dma irq stuff, fecks some games, gotta recheck that + (linuzappz) + + * 22/12/04:[-] Fixed bug in branch address in vus + (linuzappz) + + v0.7: + * 18/12/04:[*] Added GSread8/16/GSwrite8/16, GSgifTransfer1 now has two args, + added the addr and pMem points to the VU1 mem + (linuzappz) + + * 16/12/04:[*] Pofis improved his Patchbrowser (shadow) + + * 06/12/04:[-] Fixed Langs support for win32 + (linuzappz) + + * 06/12/04:[*] Added support for 1.90 Bios NVM. + (auMatt) + + * 06/12/04:[+] Added Patch Browser for win32 . Made by Pofis (shadow) + + * 05/12/04:[*] NVM always loads rom %Bios%.NVM + [*] Cd/Dvd Reads are now again displayed on console, + that is very helpfull for testing :) + (linuzappz) + + * 28/11/04:[-] BC2T/F/TL/FL also check for VU1 to be stopped + [-] VU1 memory is masked on micro load/store instructions, + dunno yet about VU0, gotta test ;) + (linuzappz) + + * 26/11/04:[-] VU D/T flags are handled now (kindaof :P). + (linuzappz) + + * 20/11/04:[-] RTC timezone fixed (gigaherz) + + * 19/11/04:[-] Fixed vu branch negative overflows + (linuzappz) + + * 17/11/04:[*] Fixed some stuff in logging so now + -Memcards sysprintf messages Are now MEMCARDS_LOG define and enable with PAD_LOG + -Cdreads Dvdreads are now in CDR_LOG + -Vus Overflow enable from CPU_LOG + That means less logs at runtime and no more complains from nasty betatesters :D (shadow) + + + * 17/11/04:[*] fixed linuz bug in naming the memcards different in 2 different places + Memcards now are Mcd001.ps2 and Mcd002.ps2 in emu and McdDialog (shadow) + + * 16/11/04:[-] Fixed NVM File Load and Creation. Defaults to BIOS name als now. + (auMatt) + + * 15/11/04:[+] Added another DNAS at Misc.c. + (nachbrenner) + + * 14/11/04:[-] VU0/1 reset shouldn't reset the micro memory. + [*] Commented the LT_OpcodePrintTable call on Interpreter.c, + for speed :) + (linuzappz) + + * 12/11/04:[-] Second MCD works fine now. + (linuzappz) + + * 11/11/04:[-] Finally fixed SIF1 bug :D:D + (linuzappz) + + * 10/11/04:[+] Added MingW32 support ;). + (linuzappz) + + * 10/11/04:[-] Fixed NVM loading/reading/writing and also fixed v12 NVM issues. + (auMatt) + + * 09/11/04:[+] Added BiosVersion var. + [*] Sif stuff now gets saved over sstates. + (linuzappz) + + * 09/11/04:[-] Fixed bug in ModelID code in CDVD + (florin-auMatt) + + * 07/11/04:[-] Fixed bug that caused to interrupt twice before + handling the first interrupt. + (linuzappz) + + * 05/11/04:[-] Small fix for broken elfs. + (linuzappz) + + * 04/11/04:[-] CDVD was interrupting dma too much :P. + (linuzappz) + + * 03/11/04:[*] Added FREEZE_SIZE. + (gabest-linuzappz) + + * 03/11/04:[+] Added a couple of DNAS at Misc.c. + (nachbrenner) + + * 02/11/04:[+] Added hack for QFC in GS ;). + (linuzappz) + + * 01/11/04:[+] Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2. + (linuzappz) + + * 31/10/04:[-] Fixed v12 bios running. + (auMatt) + + * 30/10/04:[-] Fixed v9-v10 bios running. + (auMatt) + + * 28/10/04:[-] Really fixed SIF SMFLAG/MSFLAG :P:D + (linuzappz) + + * 28/10/04:[-] Fixed MCDS :D + (asadr) + + * 26/10/04:[*] Added rom2/erom support + (auMatt/linuzappz) + + * 23/10/04:[*] Added/Fixed Model Number Reading + (auMatt/Florin) + + * 18/10/04:[-] Fixed SIF SMFLAG/MSFLAG, needs testing tho + (linuzappz) + + * 06/10/04:[*] More BIOS detection added.(auMatt) + + * 04/10/04:[-] Fixed EXL bug + [-] Fixed SIF0/1 when fifo got filled up + (linuzappz) + + * 01/10/04:[-] CdReadConfig/CdWriteConfig now uses NVM ^^ + [!] Bios configurations now gets saved/loaded from NVM (nvm.raw) + (linuzappz) + + * 1/10/04:[+] Started coding the memcard manager. Far from finish but will be better soon :D + [*] Change settings . Default memcard is now a ps2 memcard. (shadow) + + * 30/09/04:[-] Newer bios will now work with pcsx2. Pads fixed, more + compatibility. (asadr) + + * 27/09/04:[-] VU0/1 Reset hopefull fixed + (linuzappz) + + * 16/09/04:[*] NVM now is readed/written from nvm.raw. + [-] ReadILink/GetMecaconVersion are really implemented ^^ + (auMatt-linuzappz) + + * 15/09/04:[*] Rewritten LoadConfig-SaveConfig to use ini instead of registry. + [*] Removed DeleteRegistry button. For obvious reasons :D (shadow) + + * 15/09/04:[-] Pads finally fixed - Fixed PADwin Plugin Required! + Updated stuff at PsxSio2.c and Sio.c (Pad Hack still + there but won't be used) asadr + + * 13/09/04:[+] Added an option for setting the main thread priority, usefull at work :P + (linuzappz) + + * 13/09/04:[*] Fixes to SCMD's (auMatt) + * 02/09/04:[*] Finally commited asadr's IPU changes + [-] Fixed small bug in memory dump for win32 + (linuzappz) + + * 30/08/04:[*] Added Deci2 Call back into the Interpreter.c for printf.(auMatt) + + * 18/08/04:[*] fixed finaly the IOP disasm. Should be correct now... + [+] for stuff for amd64 porting.notice that pcsx2_2003_amd64 project just check for 64bit + portability.Can't produce 64bit exe yet.. (shadow) + + * 15/08/04:[-] fixed the IOP-EE disasm problem.(for ppl with vc != 2003 you must include + DisR3000asm.c and DismAsm.h in your project files) + [!] Still have to finish the correct IOP disasm :D + [+] Added small framework for x86-64. Still nothing that useable :D (shadow) + + * 04/08/04:[-] PadHack now works again :) + [-] Sio2 now supports states again + (linuzappz) + + * 02/08/04:[*] F2 will print the selected state on the console + [*] Added overflow messages for ISW/ILW/ILWR/ISWR + [*] FBRST should reset the vus when VU0 Reset/VU1 Reset + bits are set, but i don't really know have much it's + resetted :P + (linuzappz) + + * 30/07/04:[-] Vif1 MPG lacked a flush + (linuzappz) + + * 28/06/04:[+] Added GSprintf, GSgetDriverInfo and PADgsDriverInfo + [+] Deci2Call 0x10 gets printed ;) + [-] Some fixes to CDVD reading + (linuzappz) + + * 24/06/04:[-] Fixed some bugs over interrupts and + exceptions + (linuzappz) + + * 22/06/04:[-] Couple of bugs fixed over IPU1 dma + [-] psHu32(INTC_STAT) changed to INTC_IRQ + (asadr-linuzappz) + + * 16/06/04:[-] Counters regs are returned in 16 bits + [+] Also added them for hwRead16 + [-] Counter only resets when writing to the mode reg + when the value & 0x3ff differs from the actual mode + [-] Fixed BCR interrupting for CDVD ;) + (linuzappz) + + * 14/06/04:[*] Enabled SSE Vif at i386.asm + [*] Added florin's work over mcds, still needs + a cleanup :) + (linuzappz) + + * 10/06/04:[*] CSRr is OR'd with 0x8 always over VSyncEnd + (linuzappz) + + * 08/06/04:[*] VU pointer gets aligned now + (linuzappz) + + * 07/06/04:[*] vuJALR now uses _Fs_*8 + [*] VSync now interrupt for INTC_STAT & 0x1 + [!] Based of debugging Aura for Laura :) + (linuzappz) + + * 07/06/04:[*] Detection for Chinese Bios. + (auMatt) + + * 04/06/04:[-] Cleaned a bit VIF1transfer, and now when + DIRECT/DIRECTHL cmd is misaligned it skips it + [*] Added USBirqHandler, USB specs v2 now + (linuzappz) + + * 04/06/04:[-] VU1 regs now are mapped to VU0 mem + (linuzappz) + + * 02/06/06:[*] finished most of the iops disasm works :P + [*] increase the firewire reg size . seems there are more regs ;p (shadow) + + * 25/05/04:[-] Fixed big stupid bug in counters ;P + Now they're accurate + (linuzappz) + + * 25/05/04:[*] Included new BIOS detection 'P'. For Free and Public BIOS Images. + (auMatt) + + * 20/05/04:[*] BCR now decrements for each cdvdReadSector, thx to Roor + (linuzappz) + + * 18/05/04:[*] Removed PsxBios2.c/h, and cleaned Irx funcs from ElfHeader.c/h + [+] Added cpuTestHwInts/cpuTestINTCInts/cpuTestDMACInts + [+] More work over mcds + [!] Now cpuBranchTest doesn't checks for irqs + (linuzappz) + + * 17/05/04:[-] Fixed bug psx counters, thx gold + (linuzappz) + + * 15/05/04:[+] Added IOP disasm in the debugger... + [!] Not yet finished and i disasm using R5900disasm atm. I will code it correctly soon (shadow) + + * 12/05/04:[*] More optimizations to the FPU rec + [*] BIAS was commented over Counters.c :/ lol + [-] Disabled EMMS_TRACE, it's buggy, dunno why tho + (linuzappz) + + * 11/05/04:[*] Now Saving/Loading FPU CW only for the ops that really need it + [*] Added some optimizations to jumps over rec + [*] Added LQC2/SQC2 + (linuzappz) + + * 08/05/04:[-] Fixed states loading/saving from the menu + (linuzappz) + + * 03/05/04:[*] Uncommented the sio2 1d100 hack + (linuzappz) + + * 3/05/04:[+] started reorganize the src. Lotta unneccesary stuff removed(like HLE) and lotta + organized. still needs a lot of work to clean but it's a start (shadow) + + * 02/05/04:[+] Added D3/D4 defines at Hw.h + (linuzappz) + + * 1/05/04:[+] Added a Delete Registry Button. It deletes pcsx2,gssoft settings + (shadow) + + * 30/04/04:[-] Small bugfix for cpu speed detection, thx to Rainer Aglas + (linuzappz) + + * 27/04/04:[+] Implemented ReadNVM/WriteNVM, untested though + (linuzappz) + + * 15/04/04:[-] SPUdma timings changed to 80, thx _Riff_ + (linuzappz) + + * 13/04/04:[*] Several changes for IPU + [+] IsBIOS now belongs to Misc.c + (asadr-linuzappz) + + [*] Dev9Null/USBLinuz/FireWire Plugins Configure now shows + Message. + [*] Configure Menu Shows USB and FireWire Options. + (auMatt) + + * 12/04/04:[-] Fixed SPU2async cycle, was getting reseted wrongly, + thx _Riff_ + [+] Added SPU2irqCallback + (linuzappz) + + * 08/04/04:[-] Unhacked sio2 for 1d100 recv1 mode + (linuzappz) + + * 07/04/04:[+] FireWire IRQ is implemented ok now + [-] Forgot dev9Interrupt over R3000A.c + (linuzappz) + + * 05/04/04:[+] Added Firewire plugin protocol. (shadow) + + * 02/04/04:[-] VIF-FIFO transfers seems to work better ;) need testing + [+] Added GSreadFIFO + (linuzappz) + + * 30/03/04:[*] sstates now use CRC as well :) + [*] emuLog.txt now goes at 'logs' dir + (linuzappz) + + * 29/03/04:[*] GSdma now waits qwords transferred cycles + before clearing CHCR and triggering, + OPH and APATH are handled as well now. + (linuzappz) + + * 25/03/04:[*] Some rewritte over Sio.c + (linuzappz) + + * 24/03/04:[-] ostr size is now 1024 in Dis*.c + [!] Finally v0.7 :D + (linuzappz) + + v0.6: + * 21/03/04:[-] About dialog was cropping the testers, thx CK :) + (linuzappz) + + * 19/03/04:[+] Added a PadHack option at the cpu dialog + [-] Couple of fixes for release + (linuzappz) + + * 16/03/04:[-] CRC had a bug, now it's ok, sorry :) + [-] Fixed bug in memInit, thx gold :) + [-] LoadState now loads the tlbs + (linuzappz) + + * 16/03/04:[-] Fixed another silly bug in loadElfFile ;) + (linuzappz) + + * 15/03/04:[+] Added texts on the console Title to make patch makers life easier :P (shadow) + + * 15/03/04:[-] Fixed a free in loadElfFile + (linuzappz) + + * 14/03/04:[*] loadElfFile now reads the whole file first + [-] DMA4/7 interrupt timings are more accurate now + (linuzappz) + + * 12/03/04:[+] Added i386.asm, only used on linux so far, + compiles using nasm, it replaces the inline + assembling for Vif + [-] Fixed bug in UNPACK for skipping write + (linuzappz) + + * 11/03/04:[*] Patches names are now using crc, + instead of ie.: + Ridge Racer V PAL was SCES_500.00.pnach, + now it is 5BBC2F40.pnach + this way games with the same code + will not get confused + [-] Fixed bug in disR5900GetUpperSym + (linuzappz) + + * 10/03/04:[+] Added SQ/LQ over iVUmicro + (linuzappz) + + * 09/03/04:[-] sio2Reset was missing from psxHwReset + [-] Fixed sio pad swaps for 0x1100 mode + (linuzappz) + + * 08/03/04:[*] Modified the DEV9irq stuff + (linuzappz) + + * 05/03/04:[-] DEV9irq now issues a SBUS_IRQ + [*] malloc memory is now aligned to 16bytes + (linuzappz) + + * 02/03/04:[-] Added presaving for MMI ops that needed that + [-] vuJR/vuJALR now masks Fs with ~0x7 + (linuzappz) + + * 02/03/04:[+] stats.txt now dumps the Cpu mode + (linuzappz) + + * 01/03/04:[-] dmaGetAddr now uses memLUT + [+] Finally added USB plugins ;) + (linuzappz) + + * 26/02/04:[-] Fixed VUops that didn't have presaving + (linuzappz) + + * 22/02/04:[+] More ops at DisVUops.h + [-] VifDma.c is cleaner now, also fixed some + stuff for savestates + [-] Added some remaining vars at cpuBranchTest + to cpuRegs for savestates + (linuzappz) + + * 21/02/04:[-] Fixed ITOF0 + (linuzappz) + + * 20/02/04:[-] Fixed savestates ;) + (linuzappz) + + * 19/02/04:[*] VUflags now should handle overflow/userflow ok + (linuzappz) + + * 17/02/04:[*] Improved and fixed sio2 stuff + [-] Fixed _vuMFIR + (linuzappz) + + * 16/02/04:[-] DIV could crash when divisor == 0.0, + as well as ERSADD + (linuzappz) + + * 13/02/04:[-] Fixed FCAND over VU1ops.c + [*] Merged VU1ops/VU0ops/Vops to VUops + [*] Cleaned up VUflags.c + [-] hackedRecv now defaults to 0x1100 + (linuzappz) + + * 09/02/04:[-] VifDma.c MPG now clears the VU0/1 Mem though Cpu->ClearVU0/1 + (linuzappz) + + * 09/02/04:[-] More SCMD functions added. Still require working code for them. :) + (auMatt) + + * 06/02/04:[-] More iVUmicro.c opcodes, fixes, and stuff :) + (linuzappz) + + * 06/02/04:[-] Fixed Bios Detection for HK Bios. + (auMatt) + + * 06/02/04:[-] Fixed CdRom/CDVD Interrupt for 0x41000200 chcr, + now it interrupts after the read ends + (linuzappz) + + * 05/02/04:[+] Added FALSE/TRUE in GRecCommon.h + [+] Added more 16bit ops to x86.c/h + [+] Fixed SQD/SQI and implemented IOR/IAND over iVUmicro + [-] BIAS is now 2 again + [+] Now only MARK is writable at Hw.c, for vif0/1Regs + (linuzappz) + + * 03/02/04:[-] Fixed FALSE to GREC_FALSE in GRecMain.c + [-] Added break to F5 ;) + [-] Commented 'ERL Set' SysPrintf + (linuzappz) + + * 02/02/04:[-] Included stdarg.h in GRecCommon.h + [+] Added some scmds to CDVD.c (auMatt) + [+] cdvd.Status now changes to CDVD_STATUS_SEEK_COMPLETE, + after a CdRead CMD + (linuzappz) + + * 16/01/04:[+] Added LQI/LQD/SQI/SQD over Recompiler + [-] Updated EE BIAS to 8, need to test this + [!] SQI/SQD are diabled still, because they are still buggy + and i don't have more time... vacations :D:D + (linuzappz) + + * 15/01/04:[+] Added code for dma interrupts, for IPU FDEC, still commented + (linuzappz) + + * 14/01/04:[+] Temporary fix for PADS. F5 now change the pad mode on the fly. if your game doesn't work + switch it from there. (shadow) + + * 12/01/04:[*] FIFO is now really 128bit as it should be :) + (linuzappz) + + * 09/01/04:[-] Fixed VU->VI[0] != 0 bug in VU1, VU0, Macromode, JALR, BAL, LQI, LQD, SQI, SQD were setting VU->VI[0]. + Address in VCALLMS was incorrect, was causing crash in VF4. + (asadr) + + * 09/01/04:[*] Start to convert VIF stuff to functions instead of macros, right now I just converted + them duplicating the code for VIF0/1 and it is working but it is not the best yet, + commiting just so others can debug VIF while I finish the work, did some minor fixes + on VIF too. + [*] The only major function needed to be reduced to one is VIF0transfer/VIF1transfer, all + others are ok (I think). + (GoldFinger) + + * 09/01/04:[-] Fixed LQC2 for _Fs_ == 0 + [*] Fixed several SIF bugs (NoComp) + (linuzappz) + + * 06/01/04:[-] Fixed UNPACK modes in VIF.c, the Indeterminate fields are now set to 1 by default. (asadr) + + * 04/01/04:[-] Fixed a bug in LQD and LQI when _Ft_ was 0. + (GoldFinger) + + * 04/01/04:[*] Modified the VIFregister structure, both VIFs(0,1) have the exactly same + structure, just VIF0 does not use some of the registers, so I unified the + structures for easy reading and less bugs. + (GoldFinger) + + * 31/12/03:[-] Added USB API at PS2Edefs.h ;) + [+] More ops at DisVUops.h + [*] UNPACK now flushes the VU micro + (linuzappz) + + * 30/12/03:[-] Fixed savestates in Misc.c and added fixed VIFdma.h + (asadr) + + * 29/12/03:[-] Fixed bug for new vu code in savestates + (linuzappz) + + * 27/12/03:[-] Fixed bug in my last update for R5900.c + (linuzappz) + + * 26/12/03:[*] VUflags are now updated when Rd == 0 as well, changed only + at VU1ops.c + [*] VU1Regs/VU0Regs is now VURegs + [!] I think we should merge VU1ops/VU0ops/Vops + (linuzappz) + + * 24/12/03:[-] Fixed DMA8 for PsxDma.c + [*] LUI is now as it was before asadr's update + [*] readded 'if Log' over debugI at Interpreter.c + (linuzappz) + + * 18/12/03:[*] Restructured VU code and VIF. Fixed stuff in Interpreter + and added CTC2 VU1 Microinstruction caller. + (asadr) + + * 18/12/03:[*] Improvements to TLB code. + (linuzappz) + + * 17/12/03:[-] Fixed iCP0.h define to __ICP0__ + [+] Added disR5900GetUpperSym + (linuzappz) + + * 08/12/03:[+] SSE recompile of vus started. Some opcodes works some yet not. + Missing flags that i gonna add soon. Gives some speed boost :) + (shadow) + + * 05/12/03:[-] Fixed bug in GS for CSR stuff + (linuzappz) + + * 03/12/03:[+] Added Interlock for CFC2/CTC2 + [-] Fixed CFC2/CTC2/LQC2/SQC2, they now + check for zero registers + [!] This should fix the 'R0 is not zero' + and the 'VU memory overflow' hopefully ;) + (linuzappz) + + * 03/12/03:[+] You now disable vu0 macromode too when you disable vu recs by the + checkbox iR5900.c + [-] corrected some more bugg0rs of linuzappz sse instructions ix86_sse.c + [!] careful linuzappz's code. Don't ever trust him cause he is a lazy bugg0r + His mind is only for pampita!:) (shadow) + + * 02/12/03:[+] Added UNPCKLPSRtoR and MOVLHPSRtoR, there you go expert :) + (linuzappz) + + * 01/12/03:[-] Fixed savestates + (linuzappz) + + * 30/11/03:[+] a few sse instructions in sse.c + a much cleaner code in reccop2.c (shadow) + + * 28/11/03:[-] Recommited old VUops.h with asadr's EATANxy/EATANxz bugfixes + [!] asadr, the VUops.h you commited was in html format, + and some opcodes you change were only to slow down things, + commit other ones that need fixes. + (linuzappz) + + * 28/11/03:[-] Fixed alot of bugs in VUops.h, hopefully some stuff will now + work as it should (asadr) + + * 27/11/03:[*] fixed some stuff in recCOP2.c (shadow) + + * 25/11/03:[-] Fixed bug in Vif.c, masks hopefully are ok now ;) + (linuzappz) + + * 25/11/03:[-] Fixed Interpreter.c ix86.h include + [-] Added to GRecBasic.h a newline at end of file, linux + complains else ;P + (linuzappz) + + * 24/11/03:[+] Added cpu detection in interpeter.c too so now you can use SSE,MMX code in + interpreter too without the fear that your pc doesn't support it ;P (shadow) + + * 22/11/03:[+] By Nachbrenner request i added a memory patcher in Debugger.Now you can make patches + while pcsx2 is running. It is not yet finished as it can only patch 32bit data but + all the patches so far are 32bit so no problem ;P (shadow) + [!] Update Common.h . We are up to pcsx2 0.6 now! :) + + v0.5: + * 21/11/03:[-] Fixed Vif.c bugs :) + [!] Source code closed for release 0.5, + only bugfixes con be submitted + (linuzappz) + + * 21/11/03:[*] Started optimizing vif.c but I find so many strange stuff (problably bugs), please + linuz, check the comments I added on the vif.c file, and tell me what to do. + (GoldFinger) + + * 20/11/03:[*] Reorganize the cpu dialog a bit and added a new option. Disable vu recompiler + with disable the recompile of vu and will save some games from freeze when + vu memory overflows (quite often) :P . This will be removed when vu problems will + solve :P (shadow) + + * 19/11/03:[-] Fixed bug in savestates + (linuzappz) + + * 18/11/03:[*] Removed the old reg caching code including the sources, so now the only rec + that works is the normal one. + [*] GoldRec is progressing, I did lots of changes to make the progress better, + right now nothing works. + (GoldFinger) + + * 14/11/03:[*] Modified GSfreezeData, now it's plugin dependant + [+] Added SPU2freeze/DEV9freeze + [-] Fixed bug in inifile_read, hi shadow bugg0r :P + [-] Fixed bug in Sio2 + (linuzappz) + + * 14/11/03:[*] change pcsx2 patch system to use *.pnach files.Now you need a patches dir in your + pcsx2. (shadow) + [!] Am i the only one that write a changelog here?? (shadow) + + * 13/11/03:[-] fixed savestate naming in win32 and linux (shadow) + + * 06/11/03:[+] cleaned up a bit rec vu and enabled vu0 micro (shadow) + + * 06/11/03:[-] Workaround in VifDma.h for FiFo transfer ;) + (linuzappz) + + * 04/11/03:[*] Changed the way we handle SPR TTE transfers, also + MFIFO_VIFtransfer transfer always the ptag+2 + [-] Unhacked Sio.c for PADs ;) + [!] Now you gotta use the PADwinKeyb from PADwin at cvs + (linuzappz) + + * 03/11/03:[-] Fixed ba8R16 bug in Memory.c + [*] Enabled VU1 micro recompilation + [*] dmaGetAddr goes though memLUTR now + (linuzappz) + + * 02/11/03:[-] Fixed MSUBA had the same problem as MSUB, iFPU.c + A = A - B * C != A = B * C - A :) + (GoldFinger) + + * 01/11/03:[+] Addded cpu speed detection in cpu detection code + [!] Linuz fix the cpu_detection.c to work with linux pls ;p + [!] Goldfinger was right.Police 24/7 is okay with MSUB now :) (shadow) + + + * 01/11/03:[-] Fixed MSUB (MADD was ok), iFPU.c + Expert, please try in Police 24/7... :) + (GoldFinger) + + * 31/10/03:[-] Fixed PCPYLD, MMI.c + (linuzappz) + + * 30/10/03:[-] disable MADD,MSUB from iFPU. that ops was causing bugs in police 24/7. + Can't figure why, can someone? (shadow) + + * 29/10/03:[-] Commented D/T flags for VUmicro + (linuzappz) + + * 28/10/03:[-] Fixed memory rec issue, blah, shadow was right again :P + (linuzappz) + + * 27/10/03:[-] More fixes to memory stuff, hwregs for 128bit + [-] Fixed vifNum == 0 for UNPACKs + [-] DEV9_R_DEV now goes though DEV9read16 :) + [+] FiFo VIF1 can read data now ;) + [-] Fixed rec mem limit, shadow was right ;P + [!] Try Make Your Dream Home now ;) + (linuzappz) + + * 26/10/03:[-] Fixed Memory stuff, now it works ok :) + (linuzappz) + + * 25/10/03:[*] Some changes to memory cards. It's not what you all expect:P + (Florin) + + * 25/10/03:[*] Improved more the cpudetection routine at the Supporting Instruction sets features + [-] Improved a bit the MMI and fixed some bugs that prevent PII cpus to work (shadow) + + * 23/10/03:[-] Fixed a bug in Memory, untested actually ;), should fix + the loader rec bug + (linuzappz) + + * 24/10/03:[*] Improved the cpudetection routine in goldrec.Now more info appears :) + (shadow) + + * 23/10/03:[*] Improved VIF for transfers in parts + [-] Fixed some bugs in DisVUops.h ;) + [-] Fixed a bug in Memory, VU1.Mem was twice, thx shadow :D + (linuzappz) + + * 21/10/03:[-] Scratchpad memory was set bigger that it really is + [-] Uncommented a few tlb related printfs just in case ;) + (linuzappz) + + * 20/10/03:[*] Rewritten several Memory.c code, it's very untested, so far + i only tested bios, so tell me what's broken now :) + (linuzappz) + + * 18/10/03:[*] Fixed the rec for use with the tlb code, but this is a no go, slow as hell we must + change the whole tlb stuff, please linuz, lets think better before implementing this. + (GoldFinger) + + * 14/10/03:[*] Modified the memRead functions, now they're better for tlbs + misses, but note that they have one more arg, so gold, you'll + have to update the rec + (linuzappz) + + * 12/10/03:[*] Removed the new module in cvs called GoldRec. Now GoldRec is a directory under ix86-32. + (GoldFinger) + + * 10/10/03:[*] Removed the new recompiler from the main project and removed its dependencies, now there + is a new module in cvs called GoldRec, you must check it out. + (GoldFinger) + + * 10/10/03:[*] Improved TLB stuff a lot ;) + (linuzappz) + + * 07/10/03:[-] Fixed bug for recompiler in psx writes from Memory.c + (linuzappz) + + * 06/10/03:[*] VU0/1 now uses the VURegs struct + [+] Added the possibility to load the System.map from ps2linux + [+] Added TLB exceptions + [-] Fixed psxM accesses from Memory.c + (linuzappz) + + * 04/10/03:[*] rewrote the recompiled vu micro startup code and separate it + [-] remove the 3dnow code for reccop2 as it created more problems that it actually solved + [+] qmf2,qmtc2 is now done in SSE too . (shadow) + + * 01/10/03:[+] Handle for the EDI flag at ERET, a guess actually ;) + (linuzappz) + + * 30/09/03:[*] Reg caching works with bios and almost everything as normal rec does, need to + check better what does not work. + [*] Splitted iR5900.c into several .c files for easy navigation and for sanity + purposes as iR5900.c was HUGE. + [-] Fix LOTS of reg caching bugs, the main one was the comparission of 64bits registers. + (GoldFinger) + + * 30/09/03:[*] Added a base interrupt delay for the dma7 (spu2) + [*] More improvements to VifDma.h + (linuzappz) + + * 29/09/03:[-] Reimplemented Interrupt latency over R5900.c + [-] Fixed load/store unsigned addr to signed one over VUops.h + (linuzappz) + + * 28/09/03:[-] Fixed dmaIrq's for Source Chain mode + (linuzappz) + + * 26/09/03:[-] Fix the speed optimization problem that was in softCall function in Bios.c, + added a #pragma to disable optimization just to that function and everything + is working again as it should (linuz, please check if this pragma will interfere + with linux) + [*] The win32 project is back like before, the new Recompiler project was removed and + everything is working. + (GoldFinger) + + * 26/09/03:[+] Added two keys (F11, F12) for Opening/Closing the CDVD tray, + only for linux so far. + (linuzappz) + + * 25/09/03:[*] Sio2 fixes. Now the mcs are 'seen' as PS2 cards but unformated(able:P) + (Florin) + + * 25/09/03:[*] Modified the project structure under win32, I separated the recompiler from + the main project into a static lib, so now I can work with two projects instead + of one and enable optimizations. Now register caching works much better as I + enable speed optimizations in the Recompiler project but had to disable it in + the main project, the real problem is the global optimizations, this way I am + proving that the problem is not on my code... :) + [-] Fix lots of reg caching bugs and commented some of the reg caching instructions + that are buggy. Lots of demos work now, P51, colors, colors15 and maybe some others. + (GoldFinger) + + * 23/09/03:[-] Changed the MessageBox in recFunctions.c to SysMessage + [+] FIFO for VIF0/1 now works :) + (linuzappz) + + * 23/09/03:[*] Splitted the bios files so the code is the .c files and not on the .h files + [-] Fixed several bugs in reg caching and improved the routines + [!] Visual Studio .NET (dont know the others) speed optimizations are + messing with the code so it is recommended to build release mode + without Speed optimizations + (GoldFinger) + + * 23/09/03:[-] Commented the Syms in BiosInit.h, since they are only + for scph10000 + [-] Fixed ret DMA op + [+] Added iVUmicro, for recompiler + (linuzappz) + + * 22/09/03:[*] Added ExecuteVU0/VU1Block in R5900cpu, R5900.c + [+] Destination Chain for SPR0 dma and added Vif masking + [!] Gold, please merge the beta changes i sent you for + the iVUmicro.c/h + (linuzappz) + + * 20/09/03:[*] Now pad2 works in lle mode [tested with bios browser] + [+] New SCMDs and MC commands + [-] Fixes in sio, sio2, cdvd, etc. + [!] Now mcs appear as not inserted, but they are wip:P + SecrCardAuth() works fine;) + (Florin) + + * 19/09/03:[-] Small bugfix in Hw.h, u32 qwc -> u16 qwc; u16 pad; + [+] Small hack in Memory.c for ba000006 + (linuzappz) + + * 17/09/03:[-] Corrected a unpack bug i forgot ;) + [+] Implemented mskpath3 / m3r flags + [-] Fixed rom1.bin lookup for linux + (linuzappz) + + * 16/09/03:[-] Linuz fixed the macro bug hanging Visual Studio + (Gold-linuz) + + * 16/09/03:[-] More bugfixes/additions to Vif/VUs + (linuzappz) + + * 15/09/03:[-] Fixes lots of bugs in Reg Caching, now other demos work. + (GoldFinger) + + * 13/09/03:[-] Some fixes to the subq in cdvd.c (Florin) + + * 13/09/03:[-] Fixed the reg caching bug in tut1. + [*] Changed the DEFINE for reg caching for the config expert put on the CPU + screen, now we have both way to test. Thanks Expert. + (GoldFinger) + + * 13/09/03:[+] Added an option for enable regcaching or not.Now goldfinger should make + support for that!! (shadow) + + * 12/09/03:[-] Fixed the normal rec bug + [+] Added lots of new instructions for reg caching now all tutorials work + (demo 1 is strange), 3stars work also. + (GoldFinger) + + * 12/09/03:[-] Small bugfixes to Vif/VUs + (linuzappz) + + * 10/09/03:[*] More work on ipu (Florin) + + * 10/09/03:[-] New recompiler code wasn't compiling over linux, now it's ok + [-] Fixed VU memory64 writes masks + [+] Added Stats.c/h, it will create a stats.txt with some stats info, + if you define a NOSTATS in Common.h that will not be used + (linuzappz) + + * 09/09/03:[*] Improved the filter of ELF loading in GUI + [*] Register caching started to work, tutorial demo2a is working, others are coming. + [*] Commied ix86.c again with previous fix as linuz removed it. + (GoldFinger) + + * 09/09/03:[-] Fixed __int64 to u64 in Misc.c + [-] Fixed small bug in Vif.h + [-] Fixed bug in GS.c, bios is ok now + [+] Implemented INTC_STAT/MASK and DMAC_STAT for 64bits + [!] I commited the last ix86.c/h, afaik you only + reformatted it gold, please don't reformat my + code + (linuzappz) + + * 09/09/03:[-] Disabled host support for bios as it is buggy. + [*] Added/fixed SCMDs (2,3,1A) in cdvd.c (Florin) + + * 08/09/03:[+] Vif0/1 regs are now mapped to hardware + (linuzappz) + + * 08/09/03:[-] fixed bug in cpu ops debugger. Now all opcodes should appear .(For you goldfinger!) + (shadow) + + * 07/09/03:[+] Completed phase 1/2 of adding host support for bios. (Florin) + + * 06/09/03:[-] Fixed bug in rec when using ezmpeg + * 06/09/03:[*] Re-structuring the whole recompiler to make it easier for + debug and for the sake of understanding + (GoldFinger) + + * 06/09/03:[*] Many things fixed/changed in ipu files (Florin) + + * 05/09/03:[+] Hot keys for savestates in win32 + F1 -> savestate + F2 -> change the slot + F3 -> loadstate + [+] checkbox for enable the patches in cpu dialog + (shadow) + + * 05/09/03:[+] Some more VUmicro debugging + (linuzappz) + + * 05/09/03:[+] Added VDEC & BDEC; now m2v files work but ipu files do not + (Florin) + + * 05/09/03:[-] bug fixed in ifpu.h (shadow) + + * 04/09/03:[+] Added Init of Plugins before Loading of + savestates. + [-] LoadOthers in WinMain.c had a plugin init + missing fixed that. + [!] Fixed GSsoft aswell. And increased vRam size from 4*1024*1024 + to 2*4*1024*1024 as OpenGL doesn't handle wrapping around in + memory. + (asadr) + + * 04/09/03:[+] HSync stuff, and better CSR/IMR handling + [+] Few more FPU insts in ix86.c/h + [!] Please tell me if something is now screwed :) + (linuzappz) + + * 04/09/03:[-] ipu fixes to dmas and vdec (Florin) + + * 02/09/03:[-] fixed the patch system + (goldfinger) + + * 02/09/03:[*] working savestates in win32 :) + (shadow) + + * 01/09/03:[*] Working savestates for linux :) + (linuzappz) + + * 02/09/03:[-] Bug fixes in IPU.c (still hacky when returning BP) + Now ezmpeg gets to VDEC;) (Florin) + + * 01/09/03:[-] Fixed old bug in Sio.c/CdRom.c + (linuzappz) + + * 30/08/03:[+] sceCdReadSubQ <- that is a bad name; it look more like + a gettoc entry (SCMD2) (Florin) + + * 29/08/03:[+] Started the register caching implementation, not ready to test yet + some new x86 opcodes to x86.c and .h iR5900.c is completely changed + a new define for iR5900.c is used to enable reg caching. + (GoldFinger) + + * 29/08/03:[-] Removed 3DNOW code is the FPU since 3DNOW is 64bits, + and FPU is 32bits + [+] Workaround in ElfHeader.c for pukklink, so it will + load ok with Run Cd + [+] Savestates :D + [-] Maybe fixed patches, blah :P + (linuzappz) + + * 27/08/03:[+] CdGetToc + CdReadSubQ + [*] Changed PS2Edefs specs 0.4.3 / CDVD v3 + [*] Changed back the CDVDgetTD function to have a 2nd param: cdvdTD + (Florin) + + * 26/08/03:[-] Fixed patching bug in BiosInit.h that was used only for scph10000 + (Florin) + + * 26/08/03:[*] SPR address in DMAs are now masked with 0x0fffffff + (linuzappz) + + * 25/08/03:[-] Fixed patch stuff + (shadow-linuzappz) + + * 25/08/03:[-] Fixed IDEC bitstream decoding. Now, all *.ipu files + should work fine (Florin) + + * 25/08/03:[-] Fixed VIF Transfers to include MARK reg in VIF0 aswell. + (asadr) + + * 22/08/03:[*] Changed the SSE opcodes to Macro mode (thanks Linuz) and linuz added some more + (GoldFinger) + + * 22/08/03:[-] Changed DEV9 stuff to use DEV9 plugins + (linuzappz) + + * 21/08/03:[+] Added SSE instructions ADDPSRtoR, ADDPSMtoR, SUBPSRtoR, SUBPSMtoR, MULPSRtoR, + MULPSMtoR, MINPSRtoR, MINPSMtoR, MAXPSRtoR, MAXPSMtoR, SQRTPSRtoR, SQRTPSMtoR, + RSQRTPSRtoR, RSQRTPSMtoR, RCPPSRtoR, RCPPSMtoR, CVTPS2PIRtoR, CVTPS2PIMtoR, + CVTPIPS2RtoR, CVTPIPS2MtoR, CMPEQPSRtoR, CMPEQPSMtoR, CMPLTPSRtoR, + CMPLTPSMtoR, CMPLEPSRtoR, CMPLEPSMtoR to ix86.c ( need to compile and check ) :P + (GoldFinger) + + * 21/08/03:[+] Added Patch.c + (shadow-linuzappz) + + * 19/08/03:[+] Fixed bug in PsxHw.h, thanks to psycho_tr + (linuzappz) + + * 15/08/03:[+] More to SMAP + (linuzappz) + + * 14/08/03:[-] Fixed Debugger/RDebugger + [!] There is still one bug left i saw in the RDebugger, + that's the threads are not ended ok, but i'll leave + that to you florin :) + (linuzappz) + + * 12/08/03:[*] Changed the time in CDVD.c and some WIN32 defines to __WIN32__ + (Florin) + + * 08/08/03:[+] Started SMAP/DEV9 stuff + (linuzappz) + + * 06/08/03:[-] Fixed MFIFO for GS dma + (linuzappz) + + v0.41: + * 05/08/03:[-] Uncommented some sif WIP stuff :) + [*] Addeded 0x00100008 PC for cpuExecuteBios as well + [-] Fixed silly bug in CDVD.c for DvdReads + (linuzappz) + + v0.4: + * 29/07/03:[-] Fixed bug in Sif code ;) + (linuzappz) + + * 26/07/03:[-] Fixed the dma memory checking for the scratchpad, + and implemented it over the remaining dmas + (linuzappz) + + * 25/07/03:[-] GSdma now ends when a transfer is outside the memory + [-] Bugfix to Sif1 dma + [-] Some changes in the ICFG write code, and + when D5_CHCR == 0, psxSu32(0x30) = 0x40000; + (linuzappz) + + * 22/07/03:[-] Counters fixes/improvements + [*] Improvements on CdRead/DvdRead + [*] Better Sif1/0 handling + (linuzappz) + + * 22/07/03:[+] New PS2Edefs 0.4.0 :) + (linuzappz) + + * 20/07/03:[-] DvdRead was really 2064 :P + (linuzappz) + + * 19/07/03:[-] Fixed BIG stupid bug in FiFo.c that i left there:P + [!] I'm ashamed:( + [*] Fixed getBits function with back buffer;) + [!] I'm proud of that B-) (Florin) + + * 18/07/03:[-] Fixed includes for Mpeg.c/yuv2rgb.c + [-] Modified DvdRead, uses 2048 blocksize, experimental ;) + [-] CDVDgetTD had to return s32, not u32 + [*] Some reorganization for the rec + (linuzappz) + + * 18/07/03:[-] Fixed some memory allocation bug in IPU.c + [i think there are more, searching...:P] (Florin) + + * 17/07/03:[-] Fixed another Sio bug ;) + [-] Fixed MULT1/MULTU1, s64 was really s32 + [-] Commented out the interrupt delay thingy ;), was causing + troubles with Kengo 2 + [+] Implemented DvdRead + (linuzappz) + + * 17/07/03:[-] Fixed bug in FiFo.c that caused flickering between movies + [*] Fixed color conversion (Florin) + + * 16/07/03:[-] Now we can boot games though bios :) + [-] Fixed 32bits shifts in Interpreter.c + (linuzappz) + + * 16/07/03:[*] Fixed (somehow:P) IDEC so that .ipu files works a bit (Florin) + + * 15/07/03:[*] Changed cdvdLoc stuff to lsn + [-] PsxDma10 now will just return if bcr < 4 + [-] Corrections to IPU1/0 dma transfers, untested but should be fine ;) + [!] Breaks compat with current cdvd plugs + (linuzappz) + + * 15/07/03:[+] CSC + PACK ipu commands Fixes to bitstream decoding (Florin) + + * 14/07/03:[-] Really implemented MFIFO now ;P + [!] mfifo.elf works just fine now, also tekkentag reaches a bit further + (linuzappz) + + * 14/07/03:[+] Some more work on IntraDECoding for IPU (florin) + + * 14/07/03:[-] Some cleaning over Sif.c + [+] MFIFO implemented in both GS/VIF + [-] Fixes to xpadman + (linuzappz) + + * 13/07/03:[*] VUmicro code now can run in "async mode" + [-] Fixed TTE in SPR1 dma + (linuzappz) + + * 10/07/03:[-] Fixed bug in R5900.c when HLE mode was on + [-] fileio ain't crashing anymore when the file is not there + [-] Fixed interrupts on VifDma.h + (linuzappz) + + * 09/07/03:[-] Fixed bug in GS dma transfers when TTE is enabled. + Was passing wrong size of qword now it is GSgifTransfer3(ptag+2, 4) + + * 08/07/03:[*] In Win32 cdvdReadRTC gets correct time. (Florin) + + * 08/07/03:[-] Fixed stupid bug in SPR1 dma, thanks florin :) + (linuzappz) + + * 07/07/03:[-] Fixed bug in Vif UNPACK cmd, tops was *16 ;) + [*] GSgifTransfer/2 => GSgifTransfer1/2/3 (PATH1/2/3) + [*] Updated GS.c with VifDma.h asadr changes, commented the TTE + transfer by now + [*] Updated as well the SPR1 dma + [!] Note that now all vu1 demos work :D + (linuzappz) + + * 06/07/03:[+] Implemented cdvdReadKey + (linuzappz) + + * 05/07/03:[+] VCALLMS/VCALLMSR now are implemented + [*] SPU dma4 now has a delay base of 0x10000 + [-] VifDma.h is now mostly as before asadr rewrote it + last time, since that way had problems with the TTE chcr + flag, now go check the bios Browser ;) + (linuzappz) + + * 04/07/03:[-] IOP won't die now after cpuRegs.cycle overflows :), R5900.c + (linuzappz) + + * 03/07/03:[-] Fixed WriteRTC and bug in Sio.c + (linuzappz) + + * 03/07/03:[+] Some IPU commands (BCLR,FDEC,SETIQ,SETVQ,SETTH) & IPU fifo + (Florin) + + * 02/07/03:[-] Cleaned a bit VifDma.h + [*] Modified the DmaExec macros, now the Dmas take care + to interrupt and to clear the STR bit + (linuzappz) + + * 30/06/03:[*] Usb hack ;), PsxHw.c + (linuzappz) + + * 29/06/03:[*] Modified Iop DMAs for async processing, only for spu/spu2 by now + [-] Vif dma refe/end now sets the tadr to 0, tek4 loops else, but + now is crashing after ;) + [!] sven shows one screen now, and others want to ;) + (linuzappz) + + * 29/06/03:[-] Removed the experimental code i added yesterday from CDVD.c/h + [*] Improved EE/IOP Rcnts + (linuzappz) + + * 28/06/03:[*] More on iop rcnts rewrite + [+] Experimental code in CdRead, now if the lsn sector is + the same than the last one readed it will add nSectors + to it, ie. it readed 2 sectors from 0:2:16; and then + it issues another cdread with the same lsn, it will read + from 0:2:18. + (linuzappz) + + * 27/06/03:[*] Started iop rcnts rewrite, untested and more to come ;) (linuzappz) + + * 27/06/03:[-] Some fixes on iop rcnts + [+] Implemented the SPU2async func + (linuzappz) + + * 26/06/03:[-] Really fixed HLE mode ;). (linuzappz) + + * 26/06/03:[-] Small CDVD.c corrections. (linuzappz) + + * 24/06/03:[*] Fixed elf loader at least not to crash at bad elfs. (Florin) + + * 23/06/03:[*] Added "rom1.bin" as a valid file for rom1 filesystem. (Florin) + + * 23/06/03:[-] Small fix to CDVD.c, maybe fixed a time out problem + with some cdvdman versions. + (linuzappz) + + * 20/06/03:[+] Some mcds work, PsxSio2.c, Sio.c + (linuzappz) + + * 17/06/03:[+] SPU dmas now call the correct funcs, PsxDma.c + (linuzappz) + + * 17/06/03:[-] Fixed Sio2, PADs are working :D, Sio.c, PsxSio2.c + [-] Fixed language in CDVD.c, now's english again :) + (linuzappz) + + * 16/06/03:[-] Better error handling over CDVD.c + [+] ROM1 stuff, Memory.c/h, PsxMem.c, iR3000A.c, iR5900.c + [!] PCSX2 now detects the rom1 in this way: ie. + you use scph10000.bin, then you must have + in the same dir scph10000.bin.rom1 or scph10000.rom1 + (linuzappz) + + * 16/06/03:[-] Rewrote the VIFtransfer and VIFdma again. Better speed and + compatibility this time (asadr). + + * 16/06/03:[*] Reoverwritten CDVD.c/h with my CDVD.c/h, + this is simpler, more direct and faster, + CdRom.c, PsxHw.c, R3000A.c, PsxCounters.c, + Memory.c + [-] Kinda workaround i think in the ICFG reg + (1450), PsxHw.c + [-] Removed VSyncHack at least ;), WinMain.c, + Common.h, ini.c + [!] Games start showing something :D:D + (linuzappz) + + * 15/06/03:[+] More dummy cdvd scmd (Florin) + + * 14/06/03:[-] Fixed SIF0 transfers, PsxDma.c, PsxHw.c/h. + [*] Cleaned up SIF1, R3000A.c, Sif.c + [+] Added a Run CD menuitem, WinMain.c, resource.h + [!] Bios shows something :D:D + (linuzappz) + + * 12/06/03:[-] Fixed bug in release version (unsafe compiler optimizations:P) + (Florin) + + * 11/06/03:[+] More functions on lle cdrom (cdread) (Florin) + + * 10/06/03:[+] Rudely overwritten linuzappz work in CDVD.c/.h + [!] Sorry man, i think i did the best...i created a framework + with names and so on. Also we have to talk about;) (Florin) + + * 10/06/03:[+] Started CDVD.c/h, moved old CDVD.h to CDVDlib.h, + PsxMem.c, PsxCommon.h (linuzappz) + + * 10/06/03:[*] Added new SPU2 dma functions plugin.c + [*] New PS2 plugins specifications 0.3.2 (shadow) + + * 09/06/03:[+] Add SPU2read/SPU2write to PsxMem.c + [-] Few fixes to PsxCounters.c + [+] Added PsxDma7, PsxHw.c, PsxDma.c (linuzappz) + + * 09/06/03:[-] Sif0 chaining fix (Florin) + + * 08/06/03:[+] Started with SIO2... (Florin) + + * 07/06/03:[-] Fixes to SIF0/SIF1 :D + [!] Now OSDSYS loads ok, and so does several modules in iop, + bios now gets stuck in a Deci2Call (reqsend) + (linuzappz) + + * 07/06/03:[-] Fixes0, Fixes1 (Florin;) + + * 06/06/03:[*] Fixed and improved the VIF Dma transfers and rewrote the VIF_Transfer. It's far + more compatible and fast ( all vu1 demos work:D ). (asadr) + + * 06/06/03:[*] Fixed sif1 (...waiting for a better solution;) (Florin) + + * 05/06/03:[-] Sif1 flags fixes (still buggy?) (Florin) + + * 04/06/03:[*] Some adjustments to PsxInterpreter.c (Florin) + + * 03/06/03:[-] Set the PSXCLK to 36.864 Mhz, by now, later PSXCLK should be + a variable, Common.h + [*] Improved iop hw maps, added DMA9/10, PsxDma.c/h, R3000A.c, PsxMem.c + [+] Added RCNT3/4/5 in PsxCounters.c/h, PsxBios.c, PsxHw.c/h + [+] Added a bit more of loggin in PsxInterpreter.c + [-] 0xba000006 now returns 1, for some bioses, Memory.c + [*] Improved dmaSIF1, SIF.c, and cleaned dmaSPR1, SPR.c + [!] Finally my name is on the v0.4 :P + (linuzappz) + + * 03/06/03:[-] Fixed GetPS2ElfName in Misc.c (Florin) + + * 22/05/03:[+] new flags code based in nsx2 flag code. vuflags.c vuflags.h + [*] vuops.h rewrote almost all the vu opcodes with new flags code Upper Instructions + should be okay but might still are some issues with the Lower instructions. + [-] added proper reset in vu1micro.c + [*] added the new vcnet files for compile properly with vuflags + (shadow) + + * 21/05/03:[-] Fully fixed of recSQ in iR5900.c. + [-] Fixed EMMS_TRACING on none 3DNOW machines, EMMS_TRACING now turned on again. + [*] Added CPU autodetection to iR5900.c + [!] #define CPU_3DNOW is not used now. + (Alexey Silinov) + + * 20/05/03:[-] Dummy fix of recSQ in iR5900.c. Recompiler back to work again. + (Alexey Silinov) + + * 10/05/03:[*] Improved fpu.c, just code optimizing in cvt_s, cvt_w, all branches opcodes and + some code organizing. + (GoldFinger) + + * 02/05/03:[+] Added some ioprps to Misc.c (Florin) + + * 02/05/03:[+] Some more work on Padman module 800100Xpadman.c , 800100Xpadman.h (shadow) + + * 30/04/03:[+] Added 2 more syscalls in BiosSysc.h (Florin) + + * 29/04/03:[+] More threads functions. (see threads.txt) + [!] To see threads switching, comment the 3 instructions + at the top of _ThreadHandler function (Bios.c) + (Florin) + + v0.3: + * 01/05/03:[-] Fixed dvd iso issue (roundup of numsectors ...+2047/2048) + in CDVDiso.c (Florin) + + * 30/04/03:[-] Fixed bug in CFC1, Fpu.c + [-] Fixed branches isns on VUops.h, US was instead of SS + [-] Added newline at oef for MMI.c, *mtapman.c + [-] Included in *loadfile.c + [*] Few changes over languages, Misc.c/h, WinMain.c + (linuzappz) + + * 29/04/03:[-] Added a workaround for the interrupt latency in the rec, + R5900.c + (linuzappz) + + * 28/04/03:[-] Fixed a bug in BiosInit.h, instead of 16 dmas there was 15 + [-] Counters 0,1,2 had interruption disabled, Counters.c + (linuzappz) + + * 27/04/03 [-] WinMain.c now only calls GetPS2Elf if on HLE mode + [-] parseCommandLine had a bug when not using HLE, ElfHeader.c + [*] Implemented memRead/Write128, Memory.c/h, iR5900.c + [*] Implemented a better way to count opcodes in iR5900.c + [*] Rewrote AddIntc/DmacHandler, RemoveIntc/DmacHandler, Bios* + (linuzappz) + + * 24/04/03:[*] More threads functions. (see threads.txt) (Florin) + + + * 23/04/03 [-] Undo the "VU0/1 control/integer regs are now the same" update, + VU*, DebugReg.c, (goldfinger-linuzappz) + [+] Implemented latency interrupt thingy ;), R5900.c/h + (linuzappz) + + * 21/04/03 [-] DMAC interrupt wasn't setting the cause in a0, Bios.c + [+] DMACTable is now being used with DefaultDmacHandler, Bios.c/h, + BiosInit.h, HLE.c + [+] Added dummy handles for mtapman901/3, Rpc_services.h, *mtapman* + [*] VIF0 code is now shared with VIF1 code, Vif.c, VifDma.h + (linuzappz) + + * 23/04/03:[*] Fixed RFU061_InitHeap, EndOfHeap, CreateThread, InitThreads + (Florin) + + * 21/04/03:[+] Started threads update (Bios.c/BiosInit.h/BiosSync.h/ + deci2_dbgp.c/ElfHeader.c/.h) (Florin) + [-] Fixed fifos a bit:) (FiFo.c/Hw.h) (Florin) + [*] Fixed VIF1 regs display in Hw.c. I know that those were handeled + but now is more clear (Asad-Florin) + + * 20/04/03:[-] Fixed a bug in WinMain.c. In case of the debuggers with HLE bios, + cpuExecuteBios() was not called, so the tlbs and all stuff + were not inited properly. (Florin) + + * 20/04/03:[-] Fixed a bug in VUmicro.h + [+] VIF1dma now handles 'from Memory' transfers, Vif.c + [-] F11 now un/sets Log, F12 un/sets symbol logging, WinMain.c + (linuzappz) + + * 19/04/03:[-] Fixed a bug in Interpreter.c + [-] VU0/1 control/integer regs are now the same, VU*, DebugReg.c + [*] Cleaned a bit GS.c + (linuzappz) + + * 17/04/03:[-] gsRead32 wasn't calling GSread32, lol :), GS.c + [+] Implemented more syscalls, as dummy for now, Bios.c/h, BiosSysc.h, + HLE.c + [*] Removed the CSR revision/intelace bits over GS.c + [+] Added GSirqCallback to PS2Edefs.h, GS.c, Plugins.c + [+] VIF1 cmd now handles the i bit, still not 100% correct, Vif.c + [-] Fixed several VIF1 bugs, Vif.c + (linuzappz) + + * 16/04/03:[*] biosInit is now called at hle_bootstrap, Bios.c, HLE.c, WinMain.c + [+] Added _TlbInit at biosInit, Bios.c + [*] Deci2Call is now better coded, Bios.c, BiosSysc.h + [-] Fixed some bugs over AddIntcHandler/AddDmacHandler, BiosSysc.h + [+] bios_SetSYSCALL is now implemented, BiosSysc.h + (linuzappz) + + * 17/04/03:[+] Breakpoint support for debugging bios. (Florin) + + * 16/04/03:[-] Readded an update that linuzappz missed in his src, + that was then used by many pcsx2 team members. [it is about my 16/03/2003's] + [+] sceCdReadIOPm in 80000595.c + (Florin) + + * 14/04/03:[*] Memory access bug in deci2 that made pcsx2 to crash. hi linuzappz + [+] MC functions fixes/dummies over 80000400mcserv.c + (Florin) + + * 12/04/03:[*] CP0Count now adds 2 every opcode, instead of 4 + (linuzappz) + + * 12/04/03:[-] Bios VSyncSetFlag is now fixed ok, Bios.c + [*] Started to implement new Bios code, Bios.c/h, BiosInit.h + BiosSysc.h, EEregs.h, HLE.c, R5900.c/h + [!] Please tell me if this update creates some incompatibility, + or something else works now, since the INTC/Exceptions code is + much better now :). + (linuzappz) + + * 08/04/03:[-] DMAC_STAT CIS? bits are now set after a DmaExec, Hw.c + [-] Fixed bug when a plugin returned -1, WinMain.c + [*] Cleaned a bit GSdma, GS.c + [-] Fixed bug in INTC interrupts, Bios.c + (linuzappz) + + * 07/04/03:[+] Added cpu opcodes debugger. Use the CPU ops button in the debugger + and it will create a cpuops.txt with the opcodes that used. + Debugger.c pcsx2.rc, cpuopdebug.c cpuopdebug.h . Now works only in + interpreter. (shadow) + + * 04/04/03:[+] Added LabelGreets/LabelAuthors to Misc.c/h, AboutDlg.c + [*] Languages code over pcsx2 is a bit better, WinMain.c + [+] Added Log to STDOUT over Logging dialog, pcsx2.rc, + Misc.c, resource.h + [+] Now we're emulating the VSync Start and the VSync End, Counters.c + (linuzappz) + + * 26/03/03:[*] Optimized PLZCW in mmi.c (GoldFinger) + [-] fixed MADD1 and MADDU1 in mmi.c (GoldFinger) + [-] PSLLH, PSRLH and PSRAH (sa needed to be the first 4 bits only), + mmi.c (GoldFinger) + [-] PADDSW, the manual seems to be wrong (well it is) so I tryed + to fix it, mmi.c (GoldFinger) + [-] PADDSB, PSUBSB, the comparision was wrong, mmi.c (GoldFinger) + [-] PADDSW, PSUBSW, PADDSH, PSUBSH, PADDSB, PSUBSB, PADDUW, PSUBUW, PADDUH, + PSUBUH, PADDUB, PSUBUB, the sum and sub need a conversion to the higher + value(s16,s32 and s64), mmi.c (GoldFinger) + [-] PMINH, the comparision needs to be signed, mmi.c (GoldFinger) + [-] PHMSBH, was wrong, fixed, mmi.c (GoldFinger) + [-] PEXEH, PREVH, was using _Rs_ when only _Rt_ should be, mmi.c (GoldFinger) + + * 26/03/03:[*] fixed fpu bugs. Hi linuzappz :) . Tmip is correct in interpreter mode finally + fpu.c (shadow) + + * 24/03/03:[+] Fixed Trap instructions, hi shadow :), also cleaned + up a bit the Interpreter.c (linuzappz) + + * 22/03/03:[+] Fixed the 'Load ELF File' issue, added the Memory Dump menu, + WinMain.c (Florin-linuzappz) + [!] I forgot the changelog entry in the last update, + please read it (linuzappz) + [!] I've updated again the pcsx2.po, florin sent one without the + linux port messages since i've never updated u the linux port ;) + + * 20/03/03:[+] Added GSsetWindowInfo, WinMain.c, PS2Edefs.h, Plugins.c + [+] Added MiltuLingual support, using gettext, WinMain.c, Plugins.c, + AboutDlg.c, ConfigDlg.c, pcsx2.rc, Memory.c, iR5900.c, iR3000A.c, + pcsx2.dsp, Sio.c, R5900.c, PsxMem.c, Hw.c, Common.h, ini.c, + resource.h, Win32.h + [-] Fixed IPU.c when IPU_LOG is not defined + [-] Fixed padman/loadfile.c when RPC_LOG is not defined + [*] Removed dummy memory area, Memory.c/h, PsxMem.c/h + (linuzappz) + + * 17/03/03:[*] add some more stuff to DisR5900asm.c . win debugger is better now (shadow) + [-] fix a bug in rec table (visubiu not exist) in macromode .. recCop2.c (shadow) + [!] recheck vu micromode tables. Hmm they seem correct (shadow) + + * 16/03/03:[+] Added "next" (aka "step over") support for deci2 debugging + [+] Added TTYP support (log redirection) (buggy;have to test more) + (Florin) + + * 15/03/03:[*] move loadfile to rpc using florins protocol hi florin;p (shadow) + + * 15/03/03:[*] Fixes to breakpoints in deci2 stuff (Florin) + + * 13/03/03:[+] More deci2 dbgp stuff (BREAK/CONTINUE/RUN) + [!] It is not fully tested. This is EXPERIMENTAL code. + [!] It may contain many bugs and there are also "known issues". + [*] changed names of shadow's padman files and made the according + changes to rpc_services.h & bios.c (Florin) + + * 12/03/03:[*] rewrote padman+xpadman according to florins protocol on RPC folder + [*] removed code from bios.c according to pad handling.. + [+] Add fix that make analog mode to work partially ;) (try turnip) (shadow) + + * 10/03/03:[+] Added more mem mappings to PsxMem.c & Memory.c in order + not to crash the emu when read from a not-covered area (Florin) + + * 10/03/03:[-] fix small bug in winmain that didn't let console to close winmain.c (shadow) + + * 04/03/03:[+] Added remaining UNPAKs and cleaned a bit, Vif.c/h (linuzappz) + + * 03/03/03:[*] replace console writes of IPU with IPU_LOG Ipu.c (Shadow) + + * 01/03/03:[-] Fixed partially FIFO bug; (unlogged change:P) + [!] I haven't fixed it all because is very messed up. + [+] Added a small fix to PsxMem.c in order to allow sifman to stay resident. + (Florin) + + * 28/02/03:[+] Added support for remote debugging with tcp/ip deci2 protocol. + [!] Not finished nor fully tested + [!] There's an issue on Win98 with winsock2 closing [have 2 check that] + [!] New src dir (rdebug\*.*), Win32\RDebugger.c/.h; + [!] also added ws2_32.lib to link libraries + (Florin) + + * 25/02/03:[+] Added 8bit DMAs to Hw.c + [+] More UNPACK cases to Vif.c (linuzappz) + + * 23/02/03:[+] Added BC0s in COP0.c + [!] the BC0s are still fake, but they should be ok ;) (linuzappz) + + * 22/02/03:[*] Now if the Recompiler fails to initialize it'll switch to interpreter (linuzappz) + + v0.2: + * 18/02/03:[-] Small fix in winmain.c in SysInit() causing a crash (shadow) + + * 12/02/03:[+] Added new DMA transfer codes to VIF.c, GS.c + [+] Added the new clipping code to the VU + [*] Fixed most of the VU ops. Better compatibility + [!] The new dma transfer code is 4-5% faster than the last one. :) + + * 12/02/03:[*] Fixed iR5900.c to include iR5900.h, moved some stuff from + ix86.h to iR5900.h + [-] Fixed CPU_LOG flags over iR5900.c/recCOP2.c + [+] Added some SysPrintfs over iR5900.c after x86Init + (linuzappz) + + * 26/01/03:[+] Added some defines in Hw.h (linuzappz) + + * 26/01/03:[-] Fixed include in IPU.c, 'common.h' for 'Common.h', + SJdata.c, 'rpc/...' '...' (linuzappz) + + * 04/02/03:[+] ix86.c: Added CPUID for linux. + SSE is autodetected now (linuzappz) + + * 28/01/03:[+] ix86.c: CPUID added. It will work if u don't change CPU on the FLY. :) + [*] ir5900.c: recompiler changed for CPUID. + [*] recCOP2.c: recompiler changed for CPUID. + (Alexey Silinov) + + * 27/01/03:[+] ir5900.c: recompile of DSRAV,PMINW,PMAXW added. + [!] I'am not sure in this code.Need find demos that use it. + [+] ix86.c: PANDNRtoR,PANDMRtoR added. + (Alexey Silinov) + + * 25/01/03:[-] ir5900.c: Some fpu opcodes for non 3DNOW version fixed with EMMS_TRACE on. + After Linuzappz request:memory opcodes + [-] (LB,LBU,LH,LHU,LW,LWU,.....,SB,SH,SW,...) fixed for version with EMMS_TRACE on. + [-] recCOP2.c: Bugfixed for non 3DNOW version(added another recCOP2SPECIAL1t,recCOP2SPECIAL2t tables). + + [!] Now EMMS_TRACE will work much better. + (Alexey Silinov) + + * 24/01/03:[+] ir5900.c: DSRA,DSRA32 recompilation added. + [*] shifts by _Imm_=0,_Rs_=0 optimized. + [+] PMFHI,PMFLO,PAND,PXOR,PMTHI,PMTLO,POR,PAND now can recompiled to SSE instructions. + [-] JUMPS bugfixed by putting SET_FPUSTATE before it, + because cpuBranchTest use FPU. Pillgen now ok with EMMS_TRACE. + [!] #define CPU_SSE in ix86.h if you have Pentium3/4 or Duron7/AthlonXP. + (Alexey Silinov) + + * 24/01/03: Fixed iR5900.c to compile without 3DNOW (linuzappz) + + * 24/01/03: Moved the emms's in Hw.c, GS.c, Memory.c to iR5900.c (linuzappz) + + * 24/01/03: Rewrote ini.c, same code as Pcsx now :) (linuzappz) + + * 24/01/03: Removed the browse info option over pcsx2.dsp (linuzappz) + + * 24/01/03: Some fixes in Hw.c, missings #ifdef HW_LOG/#endif, + reordered the ipu address and the IPU1 dma was wrong. (linuzappz) + + * 21/01/03: remove the fpu flags reorganize fpu.c a bit. Send code for using it + as reference to all the pcsx2 members. + + * 21/01/03:recCOP2.c + 75% of COP2 ops recompiled used 3DNOW. + only sign MAC flags updated. + Zero,Sticky will be done later. + (Alexey Silinov) + * 19/01/03: + ir5900.c: + Fixed recompiling of RSQRT_S for3DNOW,recPCPYUD(tskin.elf now ok), + recC_LE for x87 FPU(untitled.elf last part now ok). + Optimizing recompile of recADDI,recADDIU,recDADDI,recDADDIU, + recANDI,recORI,recXORI,... (check _Rs_,_Rt_= =0,!=0). + Optimiing recMOVZ,recMOVN only one JMP CC,.. needed. + Added #define EMMS_TRACE to. + Added #define ARITHMETICIMM_RECOMPILE,ARITHMETIC_RECOMPILE,etc. + (Alexey Silinov) + * 18/01/03: ir5900.c:Many recompiler opcodes fixed. + IPU DMA logging update. + (Alexey Silinov) + + * 18/01/03: Fixed fileio_lseek function in 80000001fileio.c. (Florin) + + * 16/01/03: Rewrite fpu and added two version of it. One with flags and + one without. The no flags version is much faster. + fpu.c ,r5900.h,common.h,r5900.c,ini, resources , winmain.c (shadow) + + * 15/01/03: Added memory mapping of IPU_CMD,IPU_CTRL,IPU_TOP,IPU_BP. + Added parsing of IPU commands. + (Alexey Silinov) + * 14/01/03: recMAX_S,recMIN_S,recC_F,recC_EQ,recC_LE,recC_LT-added. + recABS_S,recNEG_S-now don't use FPU. + ix86.c - 3DNOW opcodes added. + #ifdef CPU_3DNOW then FPU recompiled using 3DNOW instruction set. + Now we are ready TODO FPU register cache on CPU_3DNOW. + gs.c add emms before GS read,write. + (Alexey Silinov) + + * 14/01/03: Fixed stupid bug in 80000001fileio.c (Florin) + + * 13/01/03: Fixed some issues in CDVDiso.c & 80000597cdvdfsv.c (Florin) + + * 11/01/03: Fixed fileio [important] functions up to ioprp255 (Florin) + + * 11/01/03 some more MMI opcodes in rec (alexey silinov) + + * 10/01/03 recPADDUB-changed,recPADDUH-added (Alexey Silinov) + + + * 09/01/03 + My copy&paste bugs in recPCPYUD,recPAND,recPXOR fixed. + Now EMMS() instruction writing only before FPU commands if FPU state is MMX.With it size of recompiled code is reduced. + !!Added macros SET_FPUSTATE,SET_MMXSTATE it's must before MMX or FPU instruction. + Fixed many ops.ExtSign32to64() don't used anymore. it's faster and smaller to do CDQ(). + recLUI,recPCPYLD optimized. + Added recompilation of PMAXH,PMINH,PCGTB,PCGTH,PCGTW,PCEQB,PCEQH,PCEQW,PEXTLW,PEXTUW. + ir5900.c,ix86.c, ix86.h + (Alexey Silinov) + + + * 07/01/03: Fixed MADD, MADDA, MSUB, MSUBA opcodes in FPU.c ( asadr ) + + * 07/01/03: added MTSAB,MTSAH in interpreter.c (asadr) + + * 07/01/03: Added Flags in FPU.c, fixed SQRT, DIV, RSQRT opcodes in FPU.c ( asadr ) + + * 07/01/03: add some opcodes in interpreter.c (shadow) + + * 07/01/03: small fix in mult1,multu1 in MMI.c (shadow) + + * 07/01/03: more addes in recompiler iR5900.c (Alexey Silinov) + + * 07/01/03: fixed MULT,MULTU,MULT1,MULTU1 in rec and added DIV1,DIVU1 iR5900.c + (Alexey Silinov) + + * 07/01/03: add several MMI opcodes to recompiler iR5900.c ix86.c ix86.h + (Alexey Silinov) + + * 07/01/03: Fixed libpad version issues; added scePadInit2 support in Bios.c (Florin) + + * 06/01/03: Added sceDvdRead function to 80000595cdvdfsv.c, CDVDiso.h/.c + Moved sifcall_cdvdfsvA from Bios.c to 80000592cdvdfsv.c (Florin) + + * 05/01/03: Fixed libmc version 80000400mcserv.c + Added support for cdrom device in LoadHeap function 80000003sysmem.c (Florin) + + * 05/01/03: Added D and I Flag checking in vuDiv and SQRT opcodes and some more fixes ( asadr ) + + * 05/01/03: Merge all the vu code fixes to the better possible one vuops.h (shadow) + + * 05/01/03: Several vu fixes vuops.h (Alexey Silinov) + + * 04/01/03: Added temporary fix to vuDIV, vuRSQRT, vuERSADD, vuERCPR, ERSQRT ( asadr ) + + * 04/01/03: Added vuERCPRL, vuESUM , vuEATANxz, vuESIN, vuEATAN, vuEEXP, vuRXOR ( asadr ) + + * 04/01/03: Fixed GetPS2ElfName Misc.c + Romanian version pcsx2ro.rc & spell fixes in pcsx2.rc (Florin) + + * 03/01/03: Added callback support in Bios.c + Added function name display support (if you know other places, plz add...) + (Florin) + + * 02/01/03: Fixed sceCdRead (cdvdfsv1.4 and more?) 80000595cdvdfsv.c (Florin) + sceCdSeek, sceCdPause, sceCdStop, sceCdStatus + + * 02/01/03: Added SLTI,SLTIU,SLT,SLTU iR5900.c ( Alexey Silinov) + + * 02/01/03: Added SETS8R ix86.c ix86.h ( Alexey Silinov) + + * 01/01/03: YAH HAPPY NEW YEAR :) + + * 30/12/02: Added Dump memory button in Debug dialog over Debugger.c (Florin) + + * 29/12/02: Start work on Savestates Common.h, Misc.c. Need to include zlib.lib in project (shadow) + + * 29/12/02: Fix small bug In ERET. COP0.c (shadow) + + * 29/12/02: Some more Vu opcodes in the vuops.h (shadow) + + * 29/12/02: Added BC2F,BC2T,BC2TL,BC2FL not sure if i check the right bit althought Vu0.c (shadow) + + * 29/12/02: Added HLE opcode over DisR5900.c (linuzappz) + + * 29/12/02: Fixed some bugs on rec mode, Memory.c, PsxMem.c, + ix86.c/h, iR3000A.c, iR5900.c (linuzappz) + + * 29/12/02: Fixed JALR in Interpreter.c (linuzappz) + + * 28/12/02: Fixed stupid old bug in iR5900.c (linuzappz) + + * 26/12/02: Added compiler detection code (Win32/WinMain.c) (Florin) + + * 20/12/02: Refixed new Threads code, a bit hacky still ;), Bios.c/h, HLE.c (linuzappz) + + * 20/12/02: Refixed Counters.c, GS.c (linuzappz) + + * 20/12/02: Changed some cop0 names over DisR5900.c (linuzappz) + + * 20/12/02: Fixed EXL bit on cpuException, R5900.c (linuzappz) + + * 20/12/02: Fixed ERET, COP0.c, Interpreter.c, R5900.h (linuzappz) + + * 19/12/02: fix bugs in fileio system 80000001fileio.c (florin) + + * 19/12/02: rewrite MMI mmi.c (linuzappz) + + v0.1: + * 17/12/02: Small cleaning for release (linuzappz) + + * 17/12/02: Fixed a comment in CDVD.h (linuzappz) + + v0.046: + * 17/12/02: FIXED THAT BASTARD BUG with interpreter + R5900.c (shadow) + + * 16/12/02: Fixed CDVDFS_read function (CDVDisodrv.c). (Florin) + + * 07/12/02: Added support for SjDATA filesystem (SJdata.c/.h). + Small fixes in 80000003sysmem code. + Moved OpenPlugins call from debugger.c to WinMain.c + Added support for 0B001337cdvd rpc driver. (Florin) + + * 06/12/02: Fixed RPCVER for games that load ioprp.img. + Moved related code Bios.c to Misc.c. (Florin) + + * 05/12/02: Placed a guard in CDVDFS_init/CDVDisodrv.c + Added support for reading from cdvd in Elfheader.c/.h + Implemented RunCD option WinMain.c, GtkGui.c, Misc.c/.h (Florin) + + * 01/12/02: Made fileio_open more compatible with games (up to 2.0F/ioprp255) (Florin) + + * 30/11/02: Add test opcodes TGE,TGEU,TLT,TLTU,TEQ,TNE Intepreter.c (shadow) + + * 30/11/02: Add exceptions defines in R5900.h (shadow) + + * 01/12/02: Removed old VU0 code over VU0.c (linuzappz) + + * 31/11/02: Implemented CheckCdrom/LoadCdrom, still unfinished, Misc.c (linuzappz) + + v0.045: + * 31/11/02: Changed memRead32 for PSMu32 over Interpreter.c (linuzappz) + + * 31/11/02: Fixed CdRead, CDVDiso.c (linuzappz) + +// * 30/11/02: Added irqs for rcnt2/3, started thread HLE code rewrite, +// Bios.c, Counters.c (linuzappz) + + * 28/11/02: Fixed win32 fileio path, and some more small issues (linuzappz) + + * 27/11/02: Added BD0000X0 connection to 1000F0X0 and BC000000 ee memmap, + implemented direct rec clears, and added some more counters stuff, PsxMem.c/h, + Memory.c/h, iR3000A.c, iR5900.c, Counters.c/h, Hw.c, PsxHw.c (linuzappz) + + v0.044: + * 26/11/02: Added RPC handler for 80000595cdvdfsv + Fixes in iso handling system (read function can read more than 16KB) + Fixed issue with deci2call no.3 (junk re-printing) (Florin) + * 20/11/02: Automatic setting of RPCVER + (problems: 1. SDK samples do not load an ioprp; default is "2000";) + 2. starwars game load a ioprp.img; so RPCVER="0000") + Fixed bug in CDVDiso.c/CdRead(); check for null pointer + Fixed issue with the Joliet filesystem (Florin) + * 09/11/02: Added iso parsing & filesystem driver from libcdvd library by Hiryu & Sjeep + Added credits (Hiryu&Sjeep) to Aboutbox & Readme.txt + Changed the order of opening of plugins in Plugins.c/OpenPlugins() + Added (or moved code from bios.c) to handle RPC user & standard code + -works (or should work; needs intensive testing): + 014D704Enaplink, 80000001fileio, + 80000003sysmem, 80000592cdvdfsv, + 80000597cdvdfsv + -dummy (to be implemented; only params display): + 0B0110C5sjpcm, 0badca11amigamod(shadow), + 80000400mcserv,80000596cdvdfsv, + 80000601osdsnd + Added RPC_LOG logging stuff to debug.h, pcsx2.rc & resource.h + Added kputs handling for scePrintf in Deci2Call syscall in bios.c + (Florin) + + v0.043: + * 06/11/02: add some work for amigamod.irx HLE based on Florin + RPC code (shadow) + + * 21/10/02: implement some more opcodes for VU + flags in many opcodes + (shadow) + + * 19/10/02: Added more opcodes to VUops.h (from VU0.c), and started the implementation of flags, + VUflags.h, VU* (shadow-linuzappz) + * 12/10/02: Added fix for several bioses, Hw.c, removed hack for 30002R.bin R5900.c (linuzappz) + + * 06/10/02: Added 0xb2000000 map area as a 0x12000000 mirror, Memory.c (linuzappz) + + * 06/10/02: Added/Fixed some VIF1 unpack cases, Vif.c (linuzappz) + + * 06/10/02: Started Rewrite of SetGsCrt, Bios.c (linuzappz) + + * 05/10/02: Improved gsReads/Writes GS.c (linuzappz) + + * 28/09/02: Added iop HLE code for exceptions in PsxBios.c (linuzappz) + + * 24/09/02: Added ps2 bios check for config dialog in ConfigDlg.c/GtkGui.c (Florin) + + * 23/09/02: Added command line parsing for main's argc, argv in ElfHeader.c (Florin) + + * 14/09/02: Fixed small issue in PsxBios2.c/h, Bios.c (linuzappz) + + * 13/09/02: Fixed bug in Bios.c for sif_call (linuzappz) + + v0.042: + * 25/08/02: Fixed VU SQRT/RSQRT, also added ERSQRT, VUops.h (linuzappz) + + * 24/08/02: Added several stuff for IOP hle (linuzappz) + + * 09/08/02: Added: PADDSW, PSUBSW, PPACW, PADDSH, PSUBSH, PEXTLH, PPACH, PADDSB, PSUBSB, + PPACB, PEXT5, PPAC5, PABSW, PCEQW, PMINW, PADSBH, PABSH, PCEQH, PMINH, + PCEQB, PSUBUW, PADDUH, PSUBUH, PSUBUB, PEXTUB, QFSRV, PSLLVW, PSRLVW, + PINTH, PROT3W, PSRAVW, PEXCW, PEXCH, PINTEH, PMTHI, PMTLO, PEXEW, + PREVH, PEXEH, in MMI.c (GoldFinger) + + * 09/08/02: Changed: PADDUB to conform to defines (GoldFinger) + + v0.041: + * 11/08/02: More to VUops.h (shadow) + + * 10/08/02: Rewrote L/R Stores/Loads (linuzappz) + + * 05/08/02: Add some more opcodes to VUops.h some demos works again(shadow) + + * 04/08/02: Added VUops.h, VU0.c/h, still uncomplete (linuzappz) + + * 04/08/02: Added GSgifTransfer2 for PATH1, VU1micro.c, PS2Edefs.h, Plugins.c (linuzappz) + + * 03/08/02: Added unpack v4-32, Vif.c (linuzappz) + + * 02/08/02: Rewrote partially VUmicrocode, structures and stuff, VU1/0micro.c, VUmicro.h (linuzappz) + + * 02/08/02: Small change on Misc.c (linuzappz) + + * 01/08/02: cpuExecuteBios is now called before the LoadElf, WinMain.c (linuzappz) + + * 01/08/02: Added a couple of HW_LOGS in Hw.c (linuzappz) + + * 01/08/02: Fixed MFC2/CFC2 in DisR3000A.c (linuzappz) + + * 01/08/02: Added small hack on R3000A.c (linuzappz) + + * 01/08/02: Fixed bug in StartThread Bios.c (linuzappz) + + v0.040: + * 31/07/02: Small change in PsxInterpreter.c and PsxHw.c (linuzappz) + + * 31/07/02: Added CDVDgetTN and CDVDgetTD, PS2Edefs.h, Plugins.c, CdRom.c/h (linuzappz) + + * 30/07/02: Fixed Gte.c, now includes PsxCommon.h (linuzappz) + + * 30/07/02: Added GPU_LOG to Debug.h (linuzappz) + + * 30/07/02: IOP now has vsyncs, PsxCounters.c/h (linuzappz) + + * 30/07/02: Added PsxGPU.c/h, moved the GPU_xx stuff from PsxBios.c, PsxDma.c (linuzappz) + + * 24/07/02: Added psxSIF1transfer to R3000A.c,, Sif.c, still not working (linuzappz) + + * 24/07/02: Added a couple of address more to PsxHw.c (linuzappz) + + * 24/07/02: Added zeroEx func to trace writes to stdout, PsxInterpreter.c (linuzappz) + + * 24/07/02: Improved bios_write, PsxBios.c (linuzappz) + + * 24/07/02: PsxMem.c now handles the full 4mb of the bios mem (linuzappz) + + * 24/07/02: Hack for 30002R bios, R5900.c (linuzappz) + + * 24/07/02: Fixed BNEL, BEQL in disR5900.c (linuzappz) + + * 22/07/02: Remove biosCall, now use only biosException, Bios.c/h, Interpreter.c, + R5900.c (linuzappz) + + * 21/07/02: Intialaze of VU1 vu1microc,vumicro.h,R5900.c (shadow) + + * 21/07/02: implement VIF0transfer same way as VIF1transfer vif.c (shadow) + + * 20/07/02: Add debug logs in vu0,vu1 micromode + vu0 execute vu0micro.c, + vu1micro.c,vumicro.h (shadow) + + * 18/07/02: Clean up vu0 macromode vu0.c (shadow) + + * 19/07/02: PsxMem.c now handles 0xbf80xxxx hw addresses (linuzappz) + + * 17/07/02: IOP PRid is 0x1f (not 0x2), R3000A.c (linuzappz) + + * 17/07/02: More to VU1micro.c (shadow) + + * 14/07/02: Added psxMemRLUT/psxMemWLUT instead of only psxMemLUT, PsxMem.c/h (linuzappz) + + * 11/07/02: Added MADD1, MADDU1, PMFHL, PCGTW, PMAXW, PADDH, PSUBH, PCGTH, + PMAXH, PADDB, PCGTB, MMI.c (goldfinger) + + v0.039: + * 08/07/02: Commented the 0xe000 hw dma test, for jasper, Hw.c (linuzappz) + + * 08/07/02: Changed PADreadStatus for PADstartPoll/PADpoll, Plugins.c, PS2Edefs.h, Bios.c, + PsxBios.c, Sio.c (linuzappz) + + * 07/07/02: More to Vif1 dma and added vu1ExecMicro, Vif.c, VU1micro.c/h (linuzappz) + + * 06/07/02: Rewritten/updated iop code, CdRom.c/h, Common.h, Iop*, Psx*, Debug.h, + Decode_XA.c/h, DisR3000A.c, ElfHeader.c, Gte.c/h, Mdec.c/h, R3000A.c, + R5900.c/h, Sio.c/h, iR3000A.c, Bios.c, pcsx2.dsp (linuzappz) + + * 05/07/02: Added CDVDreadTrack/getBuffer and now we're using CDVD plugin, PS2Edefs.h, + Plugins.c, ConfigDlg.c, ini.c pcsx2.rc (linuzappz) + + * 05/07/02: Optimized recANDI and completed the mmi rec tables, iR5900.c,ix86.c/h (linuzappz) + + * 06/07/02: Add VU opcodes tables vu1micro.c,vu0micro.c,vumicro.h (shadow) + + * 03/07/02: Added MADDU, PMTHL, PLZCW, PSLLH, PSRLH, PSRAH, PSLLW, PSRLW, PSRAW in MMI.c(goldfinger) + + * 03/07/02: Small change in MULT1, MULTU1 for speed, MMI.c(goldfinger) + + * 03/07/02: Fixed MADD, PLZCW in MMI.c(goldfinger) + + * 03/07/02: Fixed signed extend in DIVU, SLL, SLLV, Interpreter.c(goldfinger) + + * 03/07/02: Fixed C_F, FPU.c(goldfinger) + + * 04/07/02: Fixed silly bug on Bios.c, also added a workaround on Counters.c (linuzappz) + + * 04/07/02: Refixed CVT_W/S, FPU.c (linuzappz) + + * 03/07/02: Fixed DIV/DIVU and implemented MOVZ/MOVN in iR5900.c (linuzappz) + + v0.038: + * 02/07/02: Small change on CVT_W, FPU.c (linuzappz) + + * 01/07/02: Changed a bit IPU.c/h, added the dmaIPUs on Hw.c and added IPU_LOG, Debug.h, + resource.h, pcsx2.rc, Common.h (linuzappz) + + * 30/06/02: Add the remaining vif regs in the structure vif.h (shadow) + + * 30/06/02: Framework for IPU ipu.c,ipu.h (shadow) + + v0.037: + * 30/06/02: Added a couple of MMI opcodes to iR5900.c, ix86.c/h, also added one more cdvd server, + Bios.c (linuzappz) + + * 29/06/02: Added most of the FPU opcodes on the recompiler, fixed DSRLV/DSLLV, and also added + LQ, SQ, MFHI, MFLO, MTLO, MTHI, iR5900.c, ix86.c/h (linuzappz) + + * 28/06/02: Refixed LDL,LDR,SDL,SDR, Interpreter.c (linuzappz) + + * 27/06/02: Fixed bug in ABS, FPU.c and completed more fpu opcodes on DisR5900.c + fix to vu0 (vu0.c) + (shadow-linuzappz) + + * 27/06/02: Fixed fileio for dummy files, Bios.c (linuzappz) + + * 26/06/02: Changes/(fixes?) to some opcodes in interpreter.c SRA,DSRA,MULT,MULTU + ,SDL,SDR,LDR,LDL.At least cubemastah is correct now!(GoldFinger) + + * 20/06/02: Fixed the new Logging, modified the files on the last entry + WinMain.c (linuzappz) + + * 18/06/02: Realtime Logging Debugger.c,resource.h,pcsx2.rc,ini.c, + Common.h,debug.h (you must enable it!)(need to fixed) (shadow) + + * 18/06/02: Add some work for sjpcm module on Bios.c (shadow) + + v0.36: + * 13/06/02: Fix basic3d on Bios.c (linuzappz) + + * 09/06/02: Fix for call/ret dma in GS.c (shadow) + + * 06/06/02: Started CDVD plugin API on PS2Edefs.h (linuzappz) + + * 06/06/02: Started HLE.c/h, Interpreter.c, Common.h, iR5900.c, InterTables.c/h (linuzappz) + + * 04/06/02: Added some more syscalls on Bios.c (linuzappz) + + * 02/06/02: Fixed some bugs on SPR.c, Sif.c, Vif.c (linuzappz) + + * 02/06/02: More work on DisR5900asm.c (shadow) + + * 02/06/02: More stuff on Vif.c/h and SPR.c (linuzappz) + + * 01/06/02: Started SIFdmas Hw.c, Sif.c/h, Common.h, added SIF_LOG to Debug.h, + also removed the BREAK code since the bios doesn't handles that, Interpreter.c (linuzappz) + + * 01/06/02: Added PLZCW to MMI.c (linuzappz) + + * 01/06/02: RFU060 is now as before, added INTC and DMAC stuff, added INTC regs 0x1000f000 and + 0x1000f010, and DMAC 0x1000e010, Hw.c/h, Bios.c, Counters.c, R5900.c/h (linuzappz) + + * 31/05/02: Thread stuff is better now, added RFU061 and fixed RFU060, Bios.c (linuzappz) + + * 30/05/02: VU0 stuff is almost complete on DisR5900asm.c (shadow) + + * 30/05/02: Set gp on ElfHeader.c (linuzappz) + + * 30/05/02: Renamed _LOG to EMU_LOG, Debug.h, WinMain.c (linuzappz) + + * 28/05/02: Implemented GetCop0/iGetCop0 bios calls, Bios.c (linuzappz) + + * 28/05/02: Added names to GPR/COP0 regs, R5900.h, COP0.c, Bios.c, Interpreter.c, + FPU.c, DisR5900.c, R5900.c, VU0.c, MMI.c, iR5900.c, ElfHeader.c (linuzappz) + + * 28/05/02: Fixed PSUBW, PSUBB, added PADDW, PEXTLB, PEXTUH, MMI.c, PERF + on Interpreter.c, and TLBWR, TLBR to COP0.c (linuzappz) + + * 28/05/02: disasm.c/h is now DisR5900asm.c, Debugger.c, Debug.h, also added symbols + support for it (linuzappz) + + v0.35: + * 27/05/02: INCREASE VERSION ON 0.036! WinMain.c (shadow) + + * 27/05/02: add partialy support for VU0 in Win32 disasm.fix a bug in tables for MMI + disasm.c disasm.h (shadow) + + * 27/05/02: add VU1 register debugger. resource.h, pcsx2.rc,debugger.h, debugreg.c (shadow) + + * 27/05/02: Started real threads stuff on Bios.c (linuzappz) + + * 27/05/02: Rewrote dmaGIF/dmaVIF1, GS.c/h, Vif.c/h, Hw.c/h (linuzappz) + + * 27/05/02: add Macros for VU0Mem + Some new VU0 opcodes VISWR,VILWR, (shadow - [TyRaNiD] ) + + * 27/05/02: add some new Defines (_Id_ _Is_ _It_ _Imm5_) and some new opcodes + VIADD,VISUB,VIOR,VIAND,VIADDDI,VFOI12,VFOI15,VABS (shadow) + + * 26/05/02: Added support for Symbols on DisR5900.c, ElfHeader.c, Debug.h, + also refixed the qwc on SPR.c (linuzappz) + + * 26/05/02: Added some cdvdfsv stuff on Bios.c, also set the gs revision to 3 in + CSR, GS.c (linuzappz) + + * 25/05/02: CTC2/CFC2 to DisR5900.c (linuzappz) + + * 25/05/02: Added BREAK opcode on Interpreter.c (linuzappz) + + * 25/05/02: Now the b0000000 to b2000000 address are handled as a 10000000 mirror, + Hw.c, Memory.c (linuzappz) + + * 25/05/02: Removed some old code on R5900.c, rewrote a bit the ElfHeader.c (linuzappz) + + * 24/05/02: Add gsWrite... on bios_SetGsCrt (tyranid) + + * 24/05/02: MULT1/MULTU1 are now ok MMI.c (linuzappz) + + * 24/05/02: Added 1000f000 addr on hwRead32, Hw.c (linuzappz) + + * 23/05/02: add VU0 opcodes VSUBi,VSUBq,VMULA,VMULAi,VMULAq,VMSUB,VMSUBi, + VMSUBq,VMADDA,VMAX,VMINI,VADDA,VADDAi,VADDAq,VADDAx,VADDAy, + VADDAz,VADDAw,VSUBA,VSUBAi,VSUBAq,VSUBAx,VSUBAy,VSUBAz,VSUBAw, + VMSUBA,VMSUBAx,VMSUBAy,VMSUVAz,VMSUBAw,VMSUBAi,VMSUBAq (shadow) + + * 23/05/02: add VU0-1 status. (vu0.h , vumicro.h) (shadow) + + * 23/05/02: Added VU0/1micro.c/VUmicro.h (shadow) + + * 23/05/02: Fixed bios_isceSifDmaStat (return -1), also started some work on the + zero-exception stuff, Bios.c, IopBios.c, R5900.c (linuzappz) + + * 23/05/02: VRNEXT should be fine now, VU0.c (linuzappz) + + * 23/05/02: Small addition on Bios.c, 0x80000003 cmd on bios_isceSifSetDma (linuzappz) + + * 22/05/02: Added define __VU0_H__ on VU0.h (linuzappz) + + * 22/05/02: Rewritten GSdma/dmaGIF stuff, now only GSgifTransfer exists, added dmaGIF to GS.c, also added + GIF_LOG to Debug.h, Plugins.c/h (linuzappz) + + * 21/05/02: Fixed one bug in WinMain.c, now can rerun a elf ok (linuzappz) + + * 21/05/02: More stuff to Vif.c (linuzappz) + + * 20/05/02: Fixed one bug in biosException (linuzappz) + + * Started SPRdmas, SPR.c/h, Hw.c, Common.h, also added SPR_LOG, Debug.h (linuzappz) + + * 'call' dmaChain mode in dmaVIF1 should be right now (linuzappz) + + * More changes to the GS plugin API, GSdmaGIF/GSdma, PS2Edefs.h, Plugins.c, Hw.c, Vif.c, + also fixed little bug in SPU2init (linuzappz) + + * Small change in GSmakeSnapshot, now pass char *path (linuzappz) + + v0.34: + + * add more opcodes to Disasm DisR5900.c (shadow) + + * correct MTSA in interpreter interpreter.c (_Rs_ and not _Rd_) (shadow) + + * fixed FPU register debugger debugreg.c .Now registers appears float (shadow) + + * Some more stuff on Bios.c/Counters.c, timer1 intc, fixed bug in CreateSema (semaid stuff), + and added iSignalSema (linuzappz) + + * Added some VU0 opcodes to DisR5900.c (linuzappz) + + * Fixed bug in FPU.c, BC1XX branch delay (linuzappz) + + * Started Vif0/1 dmas, Hw.c, Vif.c/h, Common.h, added VIF_LOG to Debug.h (linuzappz) + + * Fixed VSUBx, VMULz, renamed VMONE to VMOVE, VU0.c (linuzappz) + + * Moved COP2 from Interpreter.c to VU0.c, and MMI to MMI.c (linuzappz) + + * fixed VU0 register debugger debugreg.c (Linuzappz-shadow) + + * Added ExecuteBlock and removed ExecuteBios on R5900cpu, R59000.h, Interpreter.c + and iR5900.c, also added psxExecuteBios, R5900.c, WndMain.c (linuzappz) + + * Some fixes to VU0.c, _Rd_ == 0, not _Rd_ != 0 (linuzappz) + + * Added MTHI1/MTLO1, MMI.c (linuzappz) + + * Rewrote Memory.c (linuzappz) + + * Improved iR5900.c branchs, and updated ix86.c/h (linuzappz) + + * Fixed bug in MULTU, (u64) stuff (linuzappz) + + * Interrupt Exception code was wrong, 0 -> 0x400 (linuzappz) + + * Started ChangeLog + diff --git a/pcsx2/Docs/License.txt b/pcsx2/Docs/License.txt new file mode 100644 index 0000000..7d1f860 --- /dev/null +++ b/pcsx2/Docs/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/pcsx2/Docs/PS2Edefs.txt b/pcsx2/Docs/PS2Edefs.txt new file mode 100644 index 0000000..5442da8 --- /dev/null +++ b/pcsx2/Docs/PS2Edefs.txt @@ -0,0 +1,443 @@ + PS2E Definitions v0.3.0 (beta) + ------------------------------ + + Author: linuzappz@pcsx.net + +Note: Refer to PS2Edefs.h for more info. + +1) API Funcs +2) FAQs +3) Notes + +1) API Funcs: + --------- + + Common stuff: + ------------ + +// u32 CALLBACK PS2EgetLibType(void); + +Gets the plugin type, from the following defines: + +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +Note that the types can be ORed so you can make an +ie. GS/PAD plugin in one dll. + +// u32 CALLBACK PS2EgetLibVersion(void); + +Will get the plugin version: + +const unsigned char version = 1; // GS library v1 +const unsigned char revision = VERSION; +const unsigned char build = BUILD; // increase that with each version + +return version<<16|revision<<8|build; + +'version' is the GS plugin API version, as this is beta, +it should be 1. +'revision' and 'build' are plugin defined values. + +// char* CALLBACK PS2EgetLibName(void); + +Get the LibName, ie. "GSsoftdx Driver"; + + + + GS plugin API: + ------------- + +Basic funcs +----------- + +// s32 CALLBACK GSinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK GSopen(void *pDsp, char *Title); + +Opens the plugin, return 0 on success, else -1. +The plugin must fill the 'pDsp' arg (32bit) that'll be +passed to other plugins (*1), this is OS dependant (*2). + +On Win32: pass a HWND value, ie: + *(long*)pDsp = (long)GShwnd; +On Linux: pass a Display value, ie: + *(long*)pDsp = (long)display; + +*1 Even if this value is passed to every plugin, this +may not be used by the plugins. + +*2 This could change anyways, ie. maybe you can code a +GS/PAD plugin for a speacial library, so the pDsp +will be a value that you need to communicate between +them (if you need to do this). + +// void CALLBACK GSclose(); + +Close the plugin. + +// void CALLBACK GSshutdown(); + +Shutdown the plugin. + +// void CALLBACK GSvsync(); + +Called on every VSync. + +// void CALLBACK GSgifTransfer(u32 *pMem, u32 size); + +Transfer 'size' qwords (128bit) from 'pMem' to the Gif. + +// void CALLBACK GSgifTransfer2(u32 *pMem); + +Transfer a qwords (128bit) block from 'pMem' to the Gif. + +// void CALLBACK GSwrite32(u32 mem, u32 value); + +Writes to address 'mem' data 'value', 32bit. +Addresses can range from 0x12000000 to 0x14000000. + +// void CALLBACK GSwrite64(u32 mem, u64 value); + +Writes to address 'mem' data 'value', 64bit. +Addresses can range from 0x12000000 to 0x14000000. + +// u32 CALLBACK GSread32(u32 mem); + +Returns 32bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +// u64 CALLBACK GSread64(u32 mem); + +Returns 64bit from address 'mem'. +Addresses can range from 0x12000000 to 0x14000000. + +Extended funcs +-------------- + +// void CALLBACK GSkeyEvent(keyEvent *ev); + +Gets called when there is a keyEvent from the PAD plugin + +// void CALLBACK GSmakeSnapshot(char *path); + +Makes an snapshot of the vRam, can be a with the full +vRam or just the view area (as you prefer), to the dir +'path'. + + +// #ifdef __WIN32__ +// s32 CALLBACK GSsetWindowInfo(winInfo *info); +// #endif + +Windows only function, will pass the info struct to the +GS plugin, if the plugin will use this info it should +return 1 (TRUE), else the emu will destroy the window +handle and let the plugin take care of that. +This function must be called before the GSopen. +Note that the emu should hide the hMenu and the hStatusWnd +if it they are set. +The position and size of the window is not specified and +should be reset by the plugin, but the window passed should +be in a normal state, not maximized nor minimized. +After a GSclose the emu must destroy the window and +recreate it. + +// void CALLBACK GSconfigure(); + +Configure the plugin. + +// void CALLBACK GSabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK GStest(); + +Returns 0 if the plugin should work ok, else -1. + + + + PAD plugin API: -=[ OBSOLETE ]=- + -------------- + +Basic funcs +----------- + +// s32 CALLBACK PADinit(u32 flags); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK PADopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK PADclose(); + +Close the plugin. + +// void CALLBACK PADshutdown(); + +Shutdown the plugin. + +// keyEvent* CALLBACK PADkeyEvent(); + +Called every vsync, return NULL if no event happened. + +// u8 CALLBACK PADstartPoll(int pad); + +Starts polling data from the PAD, 'pad' can be 1 (pad1) +or 2 (pad2). +Returns first byte from buffer; + +// u8 CALLBACK PADpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt" or "padmem.txt", +for info about value/buffer data. + +// u32 CALLBACK PADquery(); + +returns: 1 if supported pad1 + 2 if supported pad2 + 3 if both are supported + +Extended funcs +-------------- + +// void CALLBACK PADconfigure(); + +Configure the plugin. + +// void CALLBACK PADabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK PADtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SIO plugin API: + -------------- + +Basic funcs +----------- + +// s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); + +Inits the plugin, return 0 on success, else -1. +port/slot combination will be used to load the corresponding + configuration data from ini. It's like an id for the instance. +'f' is a callback function that is used by SIO_TYPE_MTAP capable + plugins to change active slot in emulator (since sio is emu-controled). + +// s32 CALLBACK SIOopen(void *pDsp); + +Opens the plugin, return 0 on success, else -1. +The 'pDsp' is a value from the GS plugin (refer to +GSopen). + +// void CALLBACK SIOclose(); + +Close the plugin. + +// void CALLBACK SIOshutdown(); + +Shutdown the plugin. + +// u8 CALLBACK SIOstartPoll(u8 value); + +Starts polling data from the SIO, 'value' is + 0x01, 0x21, 0x61 and 0x81 corresponding to pad, mtap, rm and mc. +Returns first byte from buffer; + +// u8 CALLBACK SIOpoll(u8 value); + +Returns next byte from buffer; +Refer to "pad and mem card data.txt", "padmem.txt" or + "padspecs.txt" (http://ps2dev.ps2-scene.org/padspecs.txt), +for info about value/buffer data. + +// u32 CALLBACK SIOquery(); + +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +returns: ORed value of SIO_TYPE_xxxx - the capabilities of the plugin +eg. a remote control plugin will return SIO_TYPE_PAD | SIO_TYPE_RM + +Extended funcs +-------------- + +// void CALLBACK SIOconfigure(); + +Configure the plugin. + +// void CALLBACK SIOabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK SIOtest(); + +Returns 0 if the plugin should work ok, else -1. + + + + SPU2 plugin API: + --------------- + +TODO :) + +Basic funcs +----------- + +// s32 CALLBACK SPU2init(); +// s32 CALLBACK SPU2open(void *pDsp); +// void CALLBACK SPU2close(); +// void CALLBACK SPU2shutdown(); +// void CALLBACK SPU2update(); +// void CALLBACK SPU2dma(u32 *dmaAddr, char *pRam); +// void CALLBACK SPU2write(u32 mem, u16 value); +// u16 CALLBACK SPU2read(u32 mem); + +Extended funcs +-------------- + +// void CALLBACK SPU2configure(); +// void CALLBACK SPU2about(); +// s32 CALLBACK SPU2test(); + + + + CDVD plugin API: + --------------- + +Basic funcs +----------- + +// s32 CALLBACK CDVDinit(); + +Inits the plugin, return 0 on success, else -1. + +// s32 CALLBACK CDVDopen(); + +Opens the plugin, return 0 on success, else -1. + +// void CALLBACK CDVDclose(); + +Close the plugin. + +// void CALLBACK CDVDshutdown(); + +Shutdown the plugin. + +// s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +Starts reading from the specified 'lsn' sector location, +return 0 on success, else -1. + +// u8* CALLBACK CDVDgetBuffer(); + +Gets a pointer to the buffer with the sector data +readed by a previously CDVDreadTrack call. +The buffer size depends on the mode used for readTrack. + +note: return can be NULL (for async modes) + +// s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq); + +Read subq data from disc at 'lsn' location (only cds have subq data), +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); + +Get the the cdvdTN data for the currect CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTD(u8 Track, cdvdLoc *Buffer); + +Get the the cdvdTD data for the 'Track' track in the current CdRom, +return 0 on success, else -1. + +// s32 CALLBACK CDVDgetTOC(void* toc); + +Get ps2 style toc from disc, return 0 on success, else -1. +(ps2 toc isnt quite the same as a normal disc toc, +especially for dvds) + +// s32 CALLBACK CDVDgetDiskType(); + +Returns disktype in the format CDVD_TYPE_xxxx + +// s32 CALLBACK CDVDgetTrayStatus(); + +Returns tray status in the format CDVD_TRAY_xxxx + +// s32 CALLBACK CDVDctrlTrayOpen(); + +Opens disc tray, return 0 on success, else -1. + +// s32 CALLBACK CDVDctrlTrayClose(); + +Closes disc tray, return 0 on success, else -1. + + +Extended funcs +-------------- + +// void CALLBACK CDVDconfigure(); + +Configure the plugin. + +// void CALLBACK CDVDabout(); + +Shows an About Dialog of the plugin. + +// s32 CALLBACK CDVDtest(); + +Returns 0 if the plugin should work ok, else -1. + + +2) FAQs + + * What's the right open/close sequence? + 1. CDVD + 2. GS + 3. PAD1/2 + 4. SPU2 + + * Where to start coding a plugin? + Get an open source plugin, mine are all open source, + so you can freely base on them. + + * Why GSgifTransfer2 exists? + GSgifTransfer2 is used by the XGKICK VU1 opcode, and + it doesn't has a size, the GSgifTransfer is used by he GIF + and the VIF dmas, and it has a size, so that's why :). + +3) Notes + + * CDVDgetBuffer should be used after CDVDreadTrack, + like this: + CDVDreadTrack(time); + ptr = CDVDgetBuffer(); + + but not like this; + ptr = CDVDgetBuffer(); + CDVDreadTrack(time); + + * Errors should be checked for both CDVDreadTrack and CDVDgetBuffer, + and not only CDVDreadTrack. + diff --git a/pcsx2/Docs/Readme.txt b/pcsx2/Docs/Readme.txt new file mode 100644 index 0000000..20d2c18 --- /dev/null +++ b/pcsx2/Docs/Readme.txt @@ -0,0 +1,196 @@ + + + + +PCSX2 - A PS2 EMU +------------------ +Here it is. A first try for an ps2 emulator... +Of course it isn't very advance now but there are some stuff here... + + + +Overview +-------- +Well i will try to catch up some questions. +First of all pcsx2 don't run Ps2 games yet! +And of course it is far from doing this. +So pcsx2 don't run GT3, get it? :) +So what pcsx2 is? pcsx2 is a try to emulate sony's beast. +Of course it isn't so easy as it might seems. +So far you can consider pcsx2 as a develop tool althought +i suggest don't use pcsx2 as a tool for writing your ps2dev +stuff :). Consider the opinion that pcsx2 have bugs and we +wrote this emu by reverse enginnering ps2 demos that might +have bugs too :) +Hope you enjoy pcsx2.. + +The Pcsx2 team.. + + +Configuration +------------- + +Cpu Options: + + +Misc Options: + + * Enable Console Output: + Displays the psx text output. + + + * Enable patches + Enable the patches for games.(if they exist). + Might fix some stuff might screw some stuff. + Enable it at your own risk. + + * Enable pad hack. + if your pads doesn't seem to work if you enable that much fix the pads for the specific game. + Warning!! not leave that option checked might broke some other games as well + +Recompiler options: + +* Disable Recompiler (default). It will run with interpreter if it is ON. + Slower but more compatible. + +* Disable Vu recompiler (default). Will disable the vu recompile + (of course if recompile mode is used). More compatible recompiler but slower. + + * Enable reg caching (disabled in 0.6) + Enable the reg caching recompiler (you must have enable interpeter cpu off!) + It is more faster than the default recompiler + + + +Quick Keys: + F1: Save state + F2: Change slot (0-5) + F3: Load State + F8: Makes a Snapshot + + (debugger keys) +---------------- + F11 un/sets Log + F12 un/sets symbol logging + +Status +------ + +Most part of ps2 have been emulate. + +Things that are still missing or uncomplete + +IPU : decoding almost done. Pcsx2 can play *.ipu or *.m2v files but no pss yet +VU : there are several issues with graphics ingames. Still we are not sure if it is GS, VIF or VU problems + but we are looking for it +recompiler: planning for fast reg cache core and recompile of vus . Soon :P + + +and of course a million other bugs that exists and we hope they will be fixed ;0 + + + + + +How you can help +---------------- +If you have any info you think we can use email us, but always ask before +sending files. If you want to help in some other way also email us. + + + +The Team +-------- +Nickname | Real Name | Place | Occupation | e-mail | Comments +--------------------------------------------------------------------------------------------------------------- +Linuzappz | | Argentina | Main coder | linuzappz@pcsx.net | Master of The GS emulation and so many others.. +Shadow | George Moralis | Greece | co-coder-webmaster| shadowpcsx2@yahoo.gr | Master of cpu, master of bugs, general coding... +florin | Florin Sasu | Romania | co-coder | florin@pcsx2.net | Master of HLE. Master of cd code and bios HLE.. +asadr | | Pakistan | co-coder | | Fixing bugs around (FPU, Interpreter, VUs...) +Goldfinger | | Brazil | co-coder | | MMI,FPU and general stuff +Nachnbrenner| | Germany | co-coder | | patch freak :P +aumatt | | co-coder | | a bit of all mostly handles CDVD cmds +loser | | Australia | co-coder | loser@internalreality.com | obscure cdvd related stuff +refraction | Alex Brown | England | co-coder | refraction@gmail.com | General Coding DMA/VIF etc + +ex-coders: +basara -co-coder . Recompiler programmer. general coding +[TyRaNiD] -co-coder . GS programmer.General coding +Roor -co-coder . General coding + + +Additional coding: + +F|RES +Pofis +Gigaherz +nocomp + + +BETA testers +------------ +belmont +parotaku +bositman +CKemu +Raziel +Snake875 +Elly +CpUMasteR +Falcon4Ever + + +Team like to thanks the Follow people +------------------------------------- +Duke of NAPALM - for the 3d stars demo. The first demo that worked in pcsx2 :) +Tony Saveski (dreamtime) - for his great ps2tutorials!! +F|res - You will learn more about him soon. but a big thanks from shadow.. +Now3d - The guy that helped me at my first steps.. +Keith - Who believed in us.. +Bobbi - Thorgal: for hosting us, for design or page and some many other +Sjeep - Help and info +BGnome - Help testing stuff +Dixon - Design the new pcsx2 page, and the pcsx2.net domain +bositman - pcsx2 beta tester :) (gia sou bositman pare ta credits sou ) +No-Reccess- nice guy and great demo coder :) +nsx2 team - for help to vu ;) +razorblade - for the new pcsx2 logo,icon. +snake - he knows what for :P +ector - awesome emu :) +zezu - a good guy. good luck with your emu :P + + + + +Credits +-------------- +Hiryu & Sjeep - for their libcdvd (iso parsing and filesystem driver code) +Sjeep - for SjDATA filesystem driver +F|res - for the original DECI2 implementation +libmpeg2 - for mpeg2 decoding routines +aumatt - for applying fixes to pcsx2 +Microsoft - for vc.net 2003 :p (really faster than vc6) :P +NASM team - for nasm +CKemu - logos/design + + +and probably to a few more.. + +Special Shadow's thanks go to... +-------------------------------- +My friends : Dimitris, james, thodoris, thanasis and probably to a few more.. +and of course to a lady somewhere out there.... + + + + + +Log off/ +Linuzappz/ shadow / florin / asad/ goldfinger / nachbrenner (others???) + + + + + + + diff --git a/pcsx2/Docs/RemoteDebugging.txt b/pcsx2/Docs/RemoteDebugging.txt new file mode 100644 index 0000000..339b400 --- /dev/null +++ b/pcsx2/Docs/RemoteDebugging.txt @@ -0,0 +1,105 @@ +ͻ +NOTE: 1. this is an internal pcsx2 team document, for developers ONLY + 2. lamers/gamers are excluded + 3. DECI2 will not run your games:P +ͼ + +RemoteDebugging +=============== + +This is a new feature available for debugging applications within pcsx2 emu. + Using a remote debugger is not wellcomed unless it is more featured. + Fortunately, there are such debuggers. Currently added support is for win32 + target only; also, only TCP/IP remote connection and only for Sony's DECI2 + app-level protocol. Future addition could be GNU debugger remote support. + +Anyway, pcsx2 has a new menu item that allows one to start a debugging session + by specifying the listen port [default for DECI2 is 8510]. Pcsx2 will act like + a server for the remote debugger. It is set to accept connections on any IP. + For local debugging sessions, use IP=127.0.0.1 aka IP=localhost. On the + other hand, if a pcsx2 would be listening on an active IP in the Internet, + anyone could connect to it;) Only one connection is supported. After the + connection is closed by the client/remote tool, the only thing to do is to + "admire" the log window and then close it/restart the emu. + +So, to start a debug session: + - first start the emu [quite reasonable; because it will be the server]. There + are some issues if you start the client first or if you didn't close ALL the + client subprograms in the last debugging session. + - choose from the menu, Debug->Remote Debugging. A dialog will pop asking for + the port to use. Also, if you have a non-HLE bios selected in the Config box, + ie. a true bios, there will be also an option weather to debug the bios. You + have 2 choices: + -not checked=Run Bios + before any debug is performed a bios run. ie. the emu + will run the bios up to the shell loading or a bit + further, to the moment when all the iop modules are + loaded. You will have then a full environment loaded. + -checked=Debug Bios + nothing is done further and the PC=0xBFC00000. + - after that a connection log window will be shown and you can follow the + connection data exchange. First, the emu is placed in a wait state. + - this is the moment you have to run the client. It will open the connection. + The emu accepts the connection and the DECI2 protocol is on;) + You'll see how the client queries for registers values & memory areas. + - the situation gets complicated since you can do many things from now on: + +Debug bios: + - start with a bios selected and the check box checked (see above). + - PC=0xBFC00000 and you can trace the bios now. Anyway, there is no breakpoints + support for the bios as the client "thinks" you are debugging the real PS2, + so you cannot write to bios area. BTW: the breakpoints are implemented by + patching the code with a BREAK instruction. Since you cannot write such instr + you cannot put a breakpoint on the bios, cannot run to address and so on... +Run bios: + - start with a bios selected and the check box not checked (see above). + - wait till the emu runs the bios...it will take some time. After THAT the + connection log window will be displayed. + - PC=0x82000 or smth like that...you can check the environment set up while + running the bios. The modules window for instance. And various memory + structures. Also, this is the entrypoint of the shell loading. Try to trace + it;) +Debug an application: + - start with HLEbios selected (see above) + - since the debugger (the client) does debug whatever you want to. You can + load the elf to debug with pcsx2 loader (ie. with File->Load ELF file or + from the CDVD). But you will need to know the entrypoint to force it in + remote debugger (set PC to cursor or to address). This way is not recomended. + I like to use the loader of the debugger since it knows to load the source + also if available and does not cause troubles with setting the PC. Also, if + the ELF has symbols, it can run it to main;) + - now, you're on your own. Use step by step, step over, breakpoints, run to + cursor, run to address etc. HAPPY DEBUGGING! + +KNOWN ISSUES and NOTES +====================== + - use CDVDnull or another plugin as you like to have or not a src for cdvd + loading;) + - pcsx2 does not have support to debug the IOP. You can do this now but it is + a hard job. That is due to the fact that PS2 can run every processor + independently (ie. one can be stopped) and pcsx2 cannot. The emu runs either + all the procs or nothing. So, in the debugger, the debugged processor is on + stop and others are "running". When there will be added support for debugging + the IOP, also only one processor will run. + - do not step through the program very fast. Because of the communication speed + and a reentrancy issue, this will get the debugger in a FALSE run state. That + means that the debugger "thinks" that the PS2 (ie. pcsx2;)) is running, + although it is not. The simple solution to this is to press STOP/BREAK button + in the debugger. Notice also that some run states might be also true! When + you are stepping over a big loop...that might take some time, so if you stop + the emu you will get in the middle of the loop:P + - you can also notice the low speed that can also be met in the pcsx2 debugger. + That's because Cpu->Step() is used. + - also, notice that you cannot debug in recompiler mode! ONLY interpreter mode + works! + - IOP modules loading is not supported and the files loaded from host directory + are also loaded in pcsx2 way, ie. from host\ directory; not through remote + debugger. + - if you try to debug the bios and the code is not displayed...scroll down + in order to have only valid addresses on the screen; ie. the top address + to be 0xBFC00000 and in emu communication log there will be no ADDRESS ERROR. + + +=============================== +Florin (florinsasu@yahoo.com) +2003/04/17 diff --git a/pcsx2/Docs/RunCDVD.txt b/pcsx2/Docs/RunCDVD.txt new file mode 100644 index 0000000..abcede5 --- /dev/null +++ b/pcsx2/Docs/RunCDVD.txt @@ -0,0 +1,86 @@ + +RunCDVD - New feature explained +=============================== + +Q: What CDVD stands for? + +A: It is a short form for CD/DVD i.e. CD or DVD. + +---------------------------------------------------- + +Q: Can I run games? + +A: What do you mean by games? + There are two types of games: commercial ones and homebrew ones. + There are also two types of demos: from magazines and homebrew. + Homebrew SW will run first as they are simpler and are open-source sometimes. + +---------------------------------------------------- + +Q: Can I run commercial games? + +A: Yes, but this answer is not good for you:P + You cannot play them... + Technicaly, the game starts but it does not go very far, + because this is only the beginning... + +---------------------------------------------------- + +Q: So, what's the deal then? Is there any game that run? more? + +A: Yes, but as far as we know, not any comercial game. + Homebrew iso version of PSMS runs ok. + Also we cannot test with all the games as we don't have them all:P + +---------------------------------------------------- + +Q: When can I play game X ? + +A: Dunno, only time can say that... + We only added the CDVD loading option for now. + You will have to wait for another version of the emu to see any screenshot. + +---------------------------------------------------- + +Q: How do I run a CD/DVD game or iso/bin? + +A: You need a CDVD plugin. + Get the CDVDbin for Windows & CDVDlinuz for Linux + from http://pcsx2.ngemu.com (Download section) or from http://www.ngemu.com + Place it in Plugins directory. Run the emu and in configure dialog choose + that plugin. Then Run->Execute. When using the CDVDbin plugin + you will be promted to choose a file to use. + Select the iso or the bin of the game you own. + (To test that use psms.iso) + +---------------------------------------------------- + +Q: I have the game X on CD/DVD. What's the iso/bin stuff anyway? + +A: Well, if you have a game on CD/DVD and a bad CD/DVD drive, + you can backup it on the harddisk with a CD/DVD recording program or a simple + iso/bin ripper. That program will make an image of the CD/DVD disc + on the harddisk and you can use that image with the CDVDbin plugin. + +---------------------------------------------------- + +Q: What's the difference between .iso and .bin formats? + +A: Bin is an image with raw sectors of 2352 bytes. + Iso contains only the data part from a CD sector; ie. 2048 bytes + +---------------------------------------------------- + +Q: I have more questions. Where are the answers? + +A: First of all, think twice before asking a question. + It might be already answered or the answer is toooooo simple. + Also, there can be more questions that i missed. Use the PCSX2 forum + on http://www.ngemu.com for that. Thank you! + + +=============================== +Florin (florin@ngemu.com) + + + diff --git a/pcsx2/Docs/Translating.txt b/pcsx2/Docs/Translating.txt new file mode 100644 index 0000000..b936bb0 --- /dev/null +++ b/pcsx2/Docs/Translating.txt @@ -0,0 +1,24 @@ + Translating PCSX2 + ----------------- + +Just some small notes for translators. + +PCSX2 translations are based on the gettext library: +http://www.gnu.org/software/gettext. + +The main file to translate is pcsx2.po located at the +'Intl' dir, note that you must place the translated +strings over the msgstr and leave untouched the msgid. + +To test the translation use the msgfmt.exe utility to +convert the translated pcsx2.po file to a pcsx2.mo file +with this command: 'msgfmt pcsx2.po -o pcsx2.mo', after translating +the file please send it to us and please ask before +translating it, maybe someone has already started it +for your language. + +If you have any problems contact us and we'll try to +help you. + + linuzappz + diff --git a/pcsx2/Docs/What_Is_Host.txt b/pcsx2/Docs/What_Is_Host.txt new file mode 100644 index 0000000..5671a49 --- /dev/null +++ b/pcsx2/Docs/What_Is_Host.txt @@ -0,0 +1,45 @@ + +I will try to explain in sorta how HOST is working.. +----------------------------------------------------- + +Ps2 have the ability to use loader also other than cd-rom. +That is done through special syscall. Of course the file that +you load must support that.. + +Basically we wrote that for PSMS1.2 + +As you can see in the psms1.2 zip there is a file called psms-naplink.elf. +Well that is basically created from sjeep (hi sjeep) for be able to +use psms through your USB naplink to your ps2. (so no need to burn a cd) +Well pcsx2 does exactly that. Emulate Host +client (host is your pc, +client is your ps2). + +So how is work? +--------------- +Imagine that HOst is your cd-rom . +For psms e.g +place FILES.TXT + roms in folders that specificate in files.txt and you are +ready.. + +e.g + +Host +FILES.TXT +-ROMS1 +--Alienstorm.sms +--IamLamer.sms + +I think you get the Idea... +For more questions mail me..(shadow@pcsx.net) + +About +----- +This doc has been written from shadow... +Host support was added kindly to pcsx2 by Linuzappz +Thanks to sjeep for his psms1.2 emu and his support.. +Also thanks to Keith,bobbi,thorgal,akumax,now3d and probably to some more... + +Log off +shadow/linuzappz + + diff --git a/pcsx2/Docs/WhatsNew.txt b/pcsx2/Docs/WhatsNew.txt new file mode 100644 index 0000000..fb4178a --- /dev/null +++ b/pcsx2/Docs/WhatsNew.txt @@ -0,0 +1,598 @@ + ********************************* + *What's new in pcsx2 v0.8 * 13th release + ********************************* + +General +------- +Compatibility has been increased since last release. More games go ingame now and 3d is okay in most of +them. Vurecs improved and speeded up a lot (buggy in many causes so use the simple rec for compatibility) +and IPU should work in some cases.(e.g VF4) + +CPUs +---- +Fixed QFSRV/MTSAH/MTSAB +Fixed SBUS IRQ at iop +Fix for end chain mode at vif +Fixed SPR0 chain mode +Fixed intc/dmac interrupts that gets cleared right away +Added offset/difference UNPACK modes in vif +VIF irq by vifcode seems ok now +Added interleave mode for SPR +Fixed UNPACK V4_5 with mask +Fixed small bug over VIF1 dma FIFO +VIF1 doens't clears str on MFIFO +Fixed some MFIFO bugs in both GS/VIF1 +Fixed bug in REF/REFS dma at VIF1/GS MFIFO + +IPU +--- +Finally fixed IPU. Mpegs and IPU streams run so do PSS files +Quality of ipu playback improved + +PLUGINS +------- +Added GSsetCSR +added CDVDreadSubQ, CDVDgetTOC, CDVDctrlTrayOpen, CDVDctrlTrayClose to cdvd + +CDVD +---- +Added some more debug info to CDVD +Fixed cdReadKey function to emulate correctly. +Modified GetToc stuff in cdvd to support dvds +cdvdTD uses lsn now +Fixed NVM (eeprom) access from cdvd stuff +Added reading of mecha version from an external file +Fixed raw dvd sector readng for dvd9 discs (otp and ptp) +Added hw-reg read/write for DecSet register 0x1f40203A +Made cdSeek change the current cdvd sector +Fixed NReady busy stuff + +Memory +------ +Added more memRead/Write funcs for speed + +VUS +--- +Fixed bug in branch address in vus +Implemented MFLAG for VU0 +Fixed some iVUmicro bugs +Fixed some VPU-STAT related issues +Fixed vu flushing over vuExecMicro +Fixed some pipelines bug within VU1,VU0 +Reworked MAX/MINI +Fixed VU's JR/JALR/BAL,ISUBIU +Added EFU pipeline to VUmicro +Fixed DIV/RSQRT exceptions + +GUI +--- +Some improvements on interface. +Added placetopatch == 1, which means patches will be applied every vsync + + + ********************************* + *What's new in pcsx2 v0.7 * 12th release + ********************************* + +GENERAL +------- +Memcards and pads should work okay now. More compatibility earned since so many things +have been fixed from previous release :) + +VIF-VUS +------- +VIF-FIFO transfers seems to work better +VU1 regs now are mapped to VU0 mem +Implemented VU0 Interlocks over CFC2/CTC2/QMFC2/QMTC2 +Fixed vu branch negative overflows +VU D/T flags are handled now +VU pointer gets aligned now + +PLUGINS +------- + +Added Firewire plugin protocol + +SPU2 +---- +Fixed SPU2async cycle +SPUdma timings changed to 80 + +CDVD +---- +Implemented ReadNVM/WriteNVM +BCR now decrements for each cdvdReadSector +Fixes to SCMD's +ReadILink/GetMecaconVersion are really implemented +CdReadConfig/CdWriteConfig now uses NVM + +Interface +--------- +sstates now use CRC +Added IOP disasm in the debugger +Added rom2/erom support +Added Patch Browser for win32 + +IPU +--- +Several changes for IPU + + +HARDWARE +-------- +Fixed bug IOP counters +Fixed some bugs over interrupts and exceptions +Newer bios will now work with pcsx2. Pads fixed, more compatibility +Fixed SIF0/1 when fifo got filled up +Fixed EXL bug +Fixed SIF SMFLAG/MSFLAG +Fixed MCDS + + + + ********************************* + *What's new in pcsx2 v0.6 * 11th release + ********************************* + +General +------- +pcsx2 is 3 years old. Happy birthday pcsx2 :) +Now you can run even more games. some 3d games should work too . so enjoy :) + + +CPUS +---- +Recompiled VUs. Needs work but some stuff might work okay now +Fixed bug in Vif.c, masks hopefully are ok +Fixed alot of bugs in VUs, hopefully some stuff will now work as it should +Added Interlock for CFC2/CTC2 +Improvements to TLB code +Restructured VU code and VIF. Fixed stuff in Interpreter and added CTC2 VU1 Microinstruction caller +Fixed UNPACK modes in VIF, the Indeterminate fields are now set to 1 by default +VUflags now should handle overflow/userflow ok + +Hardware +-------- +Fixed DMA8 +Fixed bug in GS for CSR stuff +Fixed savestates +Fixed several SIF bugs +FIFO is now really 128bit as it should be +Added code for dma interrupts +Added some scmds to CDVD +Improved and fixed sio2 stuff +Modified the DEV9irq stuff +loadElfFile now reads the whole file first +DMA4/7 interrupt timings are more accurate now +Patches names are now using crc + +GUI +--- +Memory patcher (supports only 32bit patches so far) +Fixed Bios Detection for HK Bios + +PLUGINS +------- +ADDED usb plugins + + + ********************************* + *What's new in pcsx2 v0.5 * 10th release + ********************************* + +General +------- +A release that make you look things more promising. Several games can boot now and plenty of them can reach even ingame. +There are still big issues with graphics but many improvements have done from 0.41. Some games that now can reach ingame +are: +wild wild racing PAL (with patches) +Street fighter ex3 PAL (with patches) +Le Mans 24 Hours (24 Heures Du Mans) PAL (with patches) +V-rally 3 pal (with patches) + +and probably a lot more :) + + + +CPUs +--- +Fixes to VUs +Handle for the EDI flag at ERET(cop0) +New improved cpu detection routine +Commented D/T flags for VUmicro +fixed some FPU bugs in recompiler +fixed PCPYLD in interpreter +Add compiler blocks for vu0, vu1 and few instructions +Several other fixes in cpu cores +Reg caching recompiler (not enable in 0.5 ) + +Debugger +-------- +Fixed Debugger/rdebugger (there are still some issues) + +Memory +------ +Added TLB exceptions +Fixed IOP mem accesses from EE Memory +New memory routines + +VIF +--- +Fixed VIF Transfers to include MARK reg in VIF0 aswell. +FIFO for VIF0/1 now works +More improvements to VifDma +Improved VIF for transfers in parts +FiFo VIF1 can read data now + +IPU +--- +Fixed IDEC bitstream decoding. Now, all *.ipu files should work fine +bug fixes to IPU + + +Hardware +-------- +Fixed clock in bios +Fixed MFIFO for GS dma +CDVDgetTD function need a 2nd parametre (new cdvd plugins needed!!) +cdgetTOC + cdReadSubq +HSync stuff, and better CSR/IMR handling +Implemented mskpath3 / m3r flags +Fixed VU memory64 writes masks +Implemented INTC_STAT/MASK and DMAC_STAT for 64bits +Added/fixed SCMDs (2,3,1A) in cdvd +Vif0/1 regs are now mapped to hardware +Fixes in sio, sio2 +Destination Chain for SPR0 dma and added Vif masking +Now pad2 works in lle mode [tested with bios browser] +New SCMDs and MC commands +Fixed dmaIrq's for Source Chain mode +Fixed ret DMA op +Added a base interrupt delay for the dma7 (spu2) +Fixed pads. Now it should work okay most of the times +Changed the way we handle SPR TTE transfers + +MISC +---- +Added the possibility to load the System.map from ps2linux +Added patching system. *pnach files are used now +Added dev9 plugins +Savestates + + + ********************************* + *What's new in pcsx2 v0.41 * 9th release ( Update ) + ********************************* + +General +------- +This release fixes a minor issue with the DVD iso's not booting, as of now DVD iso booting +is fixed so please try all your games again !:) + +Hardware (lle) +-------- +Fixed bug in CDVD code for DvdReads, now DVD iso's should boot just fine. + + + ********************************* + *What's new in pcsx2 v0.4 * 9th release + ********************************* + +General +------- +This release is how we wanted the first pcsx2 release to be. Finally bios is working so +many things can happend from now on. Also "Bust a Move" seems to work and other games +like Kengo 2 goes much further. All of course is done in LLE now :) . + +CPUS +---- +fix the recompiler bug that made recompiler not to work in pcsx2 0.3 +new vu code. VU0 macromode should be perfect now. +new optimaze code for fpu +Rewrote VIF once again +bug fixes to MMI +reorganize recompiler + + +DMAS +---- +Improved SIF0,SIF1,SRP1 +Added IPU0,IP1 dmas + +IPU +--- +Added decoding and commands. Some samples are working. NO pss support yet! + +IOP +--- +improved the IOP stuff.IOP is functional under bios execution :) + +HLE +--- +more WIP in Threads .Much better now +more WIP in padman. + + +Hardware (lle) +-------- +ADDED SPU2 functions. SPU2 is now possible if someone implement a SPU2 plugin. +Changed a bit the GS protocol. Gs plugins need to modificate in order to work with 0.4 +SIO2 added .Pads seems to work . Memcard partial functional +CDVD emulation added. +IOP rootcounters fixed +IOP dmas implemented +MFIFO implemented + + + +General +------ +Fixed elf loader + + + ********************************* + *What's new in pcsx2 v0.3 * 8th release + ********************************* + + + +General +------- +This version of pcsx is the first that shows ingame progress from 1 game "Sven Goran's World Manager 2002".IT is the first +ps2 emu that reaches ingame :) . Also this version have Deci2 support (usefull only for developers althought) and several +bugs have been fixed. Enjoy ;) + + + +GUI +--- +-Added MiltuLingual support( English,Catalan,German,greek,italiano,romanian,spanish) + +CPUS +---- +-Fake BC0 opcodes in cop0 +-Trap instructions fixed in interpreter +-Fixed some fpu bugs in interpreter +-Fixed MMI bugs in interpreter +-VIF1 cmd now handles the i bit, still not 100% correct +-VIF1dma now handles 'from Memory' transfers +-More Unpack case in vif +-fixed several VIF1 bugs +-VIF0 fixed also + +Hardware +-------- +-8 bit DMAS +-mem128 read/write routines +-Implemented latency interrupt thingy +-Fixes to rootcounters +-FIFO fix +-IOPmem fix +-optimaze gs dma + +Debugging +--------- +-DECI 2 Protocol !! +-fix some stuff in pcsx2 debugger +-add cpu ops debug in debugger +-Logging to STDOUT added +-add more memory mapping for EE and IOP + +HLE +--- +-rewrote of HLE code for pads (padman-xpadman). This will solve some pad problems +-rewrote the HLE code for Loadmodule +-New INTC handling in HLE bios +-Implement VSyncSetFlag in HLE bios +-Added memory dummies in mcserv. Now memcards wil be appear as functional. +-sceCDReadIOPm in CDVD HLE +-Added dummy handles for mtapman901/3 +-new Threads at BIOS HLE. Still not finished + + + + ********************************* + *What's new in pcsx2 v0.2 * 7th release + ********************************* +General +------- +pcsx2 have now a more speedy recompiler using 3dnow-3dnow2-sse instructions. Vu macromode +have been recompiled with 3d now instructions so you can see more speed there if you have a +cpu that supports 3d now. The most speed is possible with an Athlon XP cpu or a Althon 4 mobile +More support for sse or probably for sse2 soon :) + + + +rewrite of MMI +fix bugs in fileio +fix counters +new thread HLE code +fixes to CDVD HLE code +fixes-adds to VU code More vu opcodes +add some more cpu opcodes +more ipu code +add 3dnow-3dnow2-sse instructions to recompiler + + + ********************************* + *What's new in pcsx2 v0.1 * 6th release + ********************************* + +General +------- +PSMS cd version seems to work. Pgen starts to work also.. (no roms seems to working althought) +and some games might boot now... This is the first ps2 emu that boots cds :) + +GUI +--- +Added command line parsing for main's argc +Added ps2 bios check for config dialog + + +Memory +------ +Some more adds to memory maps + +CPUS +---- +Implement VU flags + some more vu0-vu1 opcodes +Fix some VIF unpack cases +Some more opcodes to R5900 + +HLE +--- +better HLE + + +RPC services for +014D704Enaplink +0B001337cdvd +80000001fileio +80000003sysmem +80000592cdvdfsv +80000597cdvdfsv +80000595cdvdfsv ++for some more but mostly dummies + +CDVD iso parser (thanks Sjeep - hiryu) +support for SJDATA file system + + + ********************************* + *What's new in pcsx2 v0.042 * 5th release + ********************************* + +GENERAL COMMENTS +---------------- +Micromode works at the release. Also some more macromode demo should +work on this release.Enjoy ;) +NOTE: Logging has been disable from the release. If you need it +Mail me ( shadow@ngemu.com) + + +GUI +--- +-ADD CDVD plugin (partially) +-change a bit the controller plugin protocol +-change a bit the GS plugin protocol (for the VUmicromode transfers) + + +CPUS +---- +-FIXES to R5900 +-FIXES to FPU +-More work in recompiler +-ADDS+fixes opcodes for MMI +-Rewritten/updated iop code +-More work to micromode (vu0-vu1) + + + +DMA +--- +-More to VIFS DMA +-More to SIFS DMA + + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.038 * 4th release + ********************************* + + +GENERAL COMMENTS +---------------- +Vu0 appears functional now. (Most of the causes ) + + +CPUS +---- +Fixes to main R5900.Many opcodes fixed ( thanks Goldfinger) +Fixes to FPU +Add some Framework for the IPU +Add some more opcodes to the recompiler including FPU opcodes + + +Debugger +-------- +Logging system + + +BIOS HLE +-------- +some support for sjpcm.irx +Fixed fileio for dummy files + + +----------------------------------------------------------------------- + + ********************************* + *What's new in pcsx2 v0.036 * 3rd release + ********************************* + + +Debugger +------- +-Add VU0 - VU1 register window +-Add VU0 macromode in disasm (still not finished) +-Added support for Symbols + +GUI +--- +-Add SPU2 interface (very partial) +-change GS specifications a bit + +CPUS +---- +-Fixed some bugs in R5900.c +-Improve recompiler +-Add VIF0 - VIF1 (very partial) +-Add more VU0 macromode instructions +-Add IOP proccesor (partial) +-Add More opcodes in MMI +-better COP0 emulation (more tlbs) + +DMA +--- +-add Stratchpad DMAS +-add VIF dmas +-add SIF dmas (very partial) + +Memory +------ +-Total rewrite to support more HW + +BIOS HLE +-------- +Many more syscall is hle now. Compatibility increase a lot + + + +General +------ +Many stuff that we are not able to explain them in details :) + + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.031 * 2nd release + ********************************* +-New icon +-New logo +-Some startup work on VU0.Many VUO macromode opcodes +-Some more opcodes in the main cpu. MFSA,MTSA,SQC2,LQC2 +-More opcodes to the MMI. +-Finished R5900 FPU. +-pad emulation using HLE.. both pad1 + pad2 +-more fixes to Recompiler (still far from finish) +-add the 4 Couters(partial) +-add FIFO registers +-Add support for HOST + +----------------------------------------------------------------------- + ********************************* + *What's new in pcsx2 v0.026 * 1st release + ********************************* + +FIRST RELEASE ALL ARE NEW :) + diff --git a/pcsx2/Docs/devblog.txt b/pcsx2/Docs/devblog.txt new file mode 100644 index 0000000..130345c --- /dev/null +++ b/pcsx2/Docs/devblog.txt @@ -0,0 +1,273 @@ +Developers Blog +=============== + +This file is mainly an R&D document containing developers findings. The aim is + to have it as much accurate as possible. Each item has to contain a number(ID), + the name of developer, revisions history and a short description. +Also, this document will serve as a pinboard - will contain coding rules, + explanations on implementation of different parts of the emulator, suggestions, + questions and ideas. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 4 +[name] Florin +[desc] PS2 info dumping project +[hist] 2006-05-08 initial version + +The emulator needs some information from a Playstation2 console. +We used to require the 'bios' software. In order to get better results + more and more information was needed. So here are some guidelines + on what we need and what we don't need from the console. +Also, a new dumper and handling of these infos in the emu are in work. + +a. The so-called 'bios', is actualy rom0 found in consoles, devkits, + test-kits and PSX at address 0xBFC00000 on both EE and IOP. + [!] Note that on 75xxx the EE side bios mismatch zone fields, + so it is recomended to make a IOP side dump. +b. Rom1 and Erom contain DvdPlayer related software and are located + starting with 0xBE000000 on PS2s from 18000 and up. Over various + versions, the size of rom1 and size and position of erom changed. + They used to be dumped separately, the new dumper will simplify this, + there'll only one file containing both rom1 and erom (2M or 4M). + [!] Note that on 70xxx and 75xxx (PStwo's) the dumping of erom from EE + is not possible, the correct dump is done only from IOP! + [!] rom1 and erom are identical for same generation for all zones. + In order to be able to run the dvdplayer code in the emulator, it needs + to be pre-decrypted. EROMDRV and DVDELF will have some 'decrypt' patches. +c. NVM (Non Volatile Memory) is 1K of code and provide valuable info about + console model and region. 10000 and 15000 don't contain the model name. + PStwo's contain the zone codes making possible to have a single version + of the rom for all zones. +d. Rom2 is found only in Chinese PS2s (50009, 70009...) and contains + a font file: GB18030. It is located at 0xBE400000. It was (w/o + justification) assumed that it is as big as rom1. There is no need to + dump it on any other console than chinese. The size is to be calculated + from the filesystem (as rom0 and rom1, it has romfs). +e. BBA (BroadBand Adapter) info is not needed to be dumped. At least not + for the emulator itself, maybe for the DEV9 plugin. Anyway, it's just + a MAC address that can be made up. +f. The current dumper is reading CDVD Mecha version. This will be replaced + by a more complete information file that will contain the following info: + from [EE] + CPU revision - revision code from COP0->PRId register + easier read from (u16)GetCop0(15) + high byte is 0x2E for EE + low byte is: high nibble major, low nibble minor of revision + FPU revision - revision code from COP1->control register 0 + same description as for cpu PRId + VUs revision - hum, i'm not aware of any revision for them :( + VUs memory - local and micro memory sizes are not detected + GS revision - upper halfword in CSR register + high byte is ID = 0x55 + low bytes is major.minor (per nibbles) + GS mem - is 4M + IPU revision - hum, i'm not aware of any revision for IPU :( + Caches - instruction and data cache sizes are read from + COP0->Config register + easier read from GetCop0(16). + MEM - total RAM available + easier read with Syscall +127 - GetMemorySize() + the values are: 32M for console and test-kits, + 128M for devkits and 64M for PSX + the size is not roughly detected. As devkits have multiple + boot modes (128M or 64M). + from [IOP] + CPU revision - revision code from COP0->PRId register + high byte seems to be 0 + low byte is major.minor (per nibbles) + initial japs have major=1, + most of the consoles have major=2, + 75xxx have a new IOP processor with major=3 + Caches - are known to be 4K-I$; 1K-D$ + 0xFFFE0130 is CACHE_CONFIG register... + MEM - total RAM available + easier to read with QueryMemSize() + the values are: 2M for consoles and test-kits, + 8M for devkits and PSX + again, the size is incorrectly read :) + SPU mem - 2M (any method of detection?) + CDVD mecha - version of CDVD controller + Scmd 0x03 with subcode 0x00 (outsize=4) + the first byte is the MG-encryption code + second is major, third is minor, fourth is [2b completed] + meka - i don't know; not supported on early consoles + Scmd 0x03 with subcode 0x90 (outsize=1+1) + DEV9 revision- type of DEV9 device: 0x2x for PCMCIA, 0x3x for EXPBAY + *(vu16*)BF80146E + USB OHCI rev - Hc_revision of the OHCI controller + *(vu32*)0xBF801600 + ILINK rev/id - I'm not sure of this one, on ps2's that don't have + firewire anymore, the value is 0xFF; on 10000 is random + *(vu32*)0xBF808480 and *(vu32*)0xBF808500 (looks like mirror) + +g. The dumper will sign the dumped content, so John Doe cannot play easily + with the bios data ;) The emu works correctly with good data/food. + +h. I'm thinking of a method to check for modified content (dumps made with a + chipped console). Probably, it will be done in the emu and presented as a + warrning. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 3 +[name] auMatt +[desc] PS2 NVM Data not 100% +[hist] 2006-05-07 initial version + + v0-v8 v9- Bits Bytes +͹ +͹ +PS1 Disc Spd 0x300 0x2c0 +PS1 Texture 0x300 0x2c0 +Video Output 0x300 0x2c0 +SPDIF 0x310 0x2c0 0 +A/R 0x310 0x2c0 1 & 2 +Language 0x311 0x2c1 All +TimeZone 0x312 0x2c2 +Summer Time 0x312 0x2c2 3 +Time Format 0x312 0x2c2 5 +DateNotation 0x312 0x2c2 6 & 7 +TimeZone 0x313 0x2c3 All +TimeZone 0x315 0x2c5 All +Model Number 0x1a0 0x1b0 16 +Console ID 0x1c8 0x1f0 8 +ILink ID 0x1c0 0x1e0 8 +Date Stamp 0x180 16 +Date Stamp 0x1e0 16 +Date Stamp 0x1f0 16 +Rem. Control 0x2c4 5 +Checksum 0x31f 0x2cf All + +Checksum is calculated by the previous 15 bytes added together, then ANDed with 0xFF +Serial Number of Console can be obtained from bytes 7,6 & 5 of the Console ID in dec. + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 2 +[name] Florin +[desc] PS2 bios versioning +[hist] 2006-04-30 initial version + +MG zone - the MagicGate decryption zone. You can find the code as one of the bits + in the byte at offset +1C in MagicGate encrypted files +PS1 drv - the letter for PS1VERx files in PStwo rom0 +ROMVER - has the following format VVvvZTYYYYMMDD in 14 bytes + VV, vv are the version of the bios in BCD + Z is zone code, see below + T is type of the console: C - consumer console, D - devkit/test console + YYYYMMDD is date of the bios + - BxDATA-SYSTEM, BxEXEC-SYSTEM, BxEXEC-DVDPLAYER uses Z code in place of 'x' + I: default, Japan; A: Usa, Asia; E: Europe, Oceania, Russia; C: China +VERSTR - the code from that file in rom0 +OSDVER - VVvvZlng is the format of the file for scph5xxxx. in PStwo the last 4 letters + are read from NVM, offset +180 7 chars (ROMVER:1|OSDVER:4|VERSTR:1|DVDID:1) +mecha - version read from CDVD SCmd 0x03:0x00 + +The following table is far from complete... + + Japan USA AusNz UK EuropeKorea HK TaiwanRussiaChina Mexic +͹ +͹ +MG zone 0/J 1/U 3/O 2/E 2/E 4/A 4/A 4/A 5/R 6/C 7/M +PS1 drv J A E E E H H H E C A +ROMVER 0 J 1 A 2 E 2 E 2 E 1 H 1 H 1 H 2 E 3 C 1 A +VERSTR J A E E E J J J E J A +OSDVER 0 Jjpn1 Aeng2 Eeng2 Eeng2 Eeng5 Kkor6 Htch6 Htch4 Rrus3 Csch Aspa? +Ķ +v0 scph10000 Ķ + mecha0.12.0Ķ + ver0100JCĶ + date000117Ķ + scph15000 Ķ + mecha0.18.0Ķ + ver0101JCĶ + date000217Ķ + scph18000 Ķ + mecha0.22.0Ķ + ver0120JCĶ + date001027Ķ +͹ +v1 scph30000 30001 Ķ +v2 30000 30001 Ķ +v3 30000 30001 30002 30003 30004 Ķ +͹ +v4 scph30000 30001 30002 30003 30004 Ķ + mecha Ķ + ver 0120EC Ķ + date 000902 Ķ + 35000 35001 35002 35003 35004 35005 Ķ +͹ +v5 30000 30001 30002 30003 30004 30005 Ķ + scph30000R30001R30002R30003R30004R30005R30006R30007RĶ + mecha0.32.0 2.32.0 Ķ + ver0160JC 0160EC0160EC Ķ + date011004 011004011004 Ķ +v6 Ķ +͹ +v7 scph37000 Ķ + 39000 39001 39002 39003 39004 39005 39006 39007 39008 Ķ + mecha 1.36.0 Ķ + ver 0160AC Ķ + date 020207 Ķ + Ĵ39001NĴ39010N +Ķ +v8 scph39000 Ĵ39006 Ķ + mecha0.38.0 + ver0160JC + date020426 +͹ +v9 scph50000 50001 50002 50003 50004 50005N50006 50007 50008 50009 Ķ + Ĵ50001NĴ50010N + 55000 Ĵ55005N55006 55007 Ķ +Ķ +v10 scph 50001 50002 50003 50004 50006 50007 50009 50010 + mecha 4.54.04.??.0 6.??.0 + ver 0190EC 0190HC0190HC 0190CC + date 030623 030623030623 030623 +v11 50004 Mexic USA +ͻ +v12 scph70000 Ĵ70002 70003 70004 70005 70006 70007 70008 70009 Ĵ70011 70012 + mecha Ĵ3.62.02.62.02.??.0 4.64.0 5.??.0 Ĵ 1.60.0 + ver0200JCĴ0200EC0200EC0200EC 0200HC 0200EC Ĵ 0200AC + date040614Ĵ040614040614040614 040614 040614 Ĵ 040614 +v13 scph 70001 70002 70003 70004 ͼ +͹ +v14 scph75000 75001 75002 75003 75004 75005 75006 75007 75008 Ĵ75010 + mecha 1.66.03.66.0 Ĵ + ver 0220AC0220EC Ĵ + date 050620050620 Ĵ +Ľ + + +============================================================================== +============================================================================== +============================================================================== + +[ ID ] 1 +[name] Florin +[desc] CVS management rules +[hist] 2006-04-30 initial version + +Please do not commit on CVS temporary files or those made by development tools + (IDEs). Eg: *.suo/aps/opt/plg/ncb/exp +Keep it clean and before commiting a new module see the previous structure and + naming rules. If unsure about how to do any opperation please ASK. please ASK! +There's no rush ;) +Also, I'm considering switching to SVN, as CVS seems to be *abandoned* by + sourceforge.net +Any change to sources has to be commited to the public CVS. The risk of + stealing is faced by any open-source developer - the difference is the + quality! The original will always stand up ;) +Try not to break the source by your patches. Although linux and 64-bit versions + are not maintained atm, your changes should be done with all versions in mind. +Happy coding :) diff --git a/pcsx2/Docs/pcsx2_faq.txt b/pcsx2/Docs/pcsx2_faq.txt new file mode 100644 index 0000000..4b8cdb8 --- /dev/null +++ b/pcsx2/Docs/pcsx2_faq.txt @@ -0,0 +1,229 @@ + + PPPP CCCC SSS X X 2222 + P P C C S S X X 2 2 + P P C S X X 2 + P P C S X X 2 + P P C S X X 2 + P P C SSS X 2 + PPPP C S X X 2 + P C S X X 2 + P C S X X 2 + P C C S S X X 2 + P CCCC SSS X X 2222222 + +**************** +*PCSX2 FAQ v0.1* +**************** + +This FAQ has been written for PCSX2 v0.6 + +FAQ Written by: CKemu & shadow +_________________________________________________________ + +Q: What is PCSX2? + +A: PCSX2 is a WIP PS2 (PlayStation 2) emulator, written by +linuzappz, shadow, florin. basara, asadr, goldfinger. PCSX2 is +constantly WIP (work in progress), and is in the early +stages of development (so don't expect much yet ;) ). + +Q: Why doesn't XYZ game work? + +A: PCSX2 is able to get many games to show 'screens'. Some of the games can reach ingame +and less more can be consider playable. Speed is too slow on many of them so 'viewable' is +a beter way to describe it :) + + +Q: Why don't these games work? + +A: PCSX2 is in the early stages of development. It can run some games (many of them without glitches) +but the speed issue prevent us of making the emu more compatible. + +Q: Where abouts do I find these demos? + +A:You can find some demos at http://pcsx2.ngemu.com or +http://ps2dev.livemedia.com.au. There are proberbly more +sites with PS2 homebrew demos. + +Q: Does PCSX2 require a 'real' PS2 BIOS. + +A: PCSX2 can use a 'real' BIOS, and is preferable to HLE +BIOS as it is more compatible. But HLE does work well +with many homebrew demos. + +Q: Why not use HLE? + +A: HLE is a difficult thing to do for a PS2. Game +developers use their own modules for each game. That +would mean we would have to HLE each module. This would +be a massive task, and not a good idea, as emulating +the real BIOS will mean compatibility with all released +games. + +Q: Where do I get a BIOS? + +A: You can dump the BIOS from your own PS2, DO NOT ask us +or anyone else for a BIOS, the BIOS is copyright of SONY +and is illegal to download, so we won't help you with +that. + +Q: I try to run a game, or the BIOS, but nothing happens! + +A: If no BIOS screen shows from attempting to run a +CD/DVD, your BIOS maybe incorrect. Go to +'config>configure', and under the BIOS menu, check that +firstly you haven't got the HLE BIOS selected, if you do +change to a 'real' BIOS. If you have a 'real' BIOS +selected and it still doesn't work, check that NO +percentage is written next to the BIOS, if it is for +instance "40%", your BIOS is to small (by 60%), or +corrupt (by 60%), you may need to redump it. Also if no +'real' BIOS is listed, check its not compressed 'eg +*.zip / *.rar' and extract it to the BIOS dir (note +sub-folders NOT supported, it must be in /BIOS/). + +If that is not the case, your BIOS isn't an actual PS2 +BIOS. To ensure that doesn't happen, dump your own ;) + +Q: I see lots of glitches with games/demos, why? + +A: Incomplete emulation of the GS, Vector Units etc, this +is a WIP emulator, and will have many bugs for some time, +until more is known about the PS2 hardware. Things +generally improve with each release, so you never know, +it may be fixed in the next release. + +Q: How can I help fix these bugs? + +A: Report these bugs to us, post at the offical PCSX2 +forums at http://www.ngemu.com. Make a post describing +the bug/glitch, perhaps with a screenshot showing it, +and details on your system setup, what plugins your +using etc. + +If you find any other bugs, with regards to the debugger, +plugins, or differences between what you see in the +emulator and a real PS2, feel free to email us. + +Q: How can I help develop for PCSX2? + +A: You can find the open-source plugins at +http://pcsx2.ngemu.com , coding a GS plugin or and SPU2 +plugin would help us greatly. Also if you have any +technical information on the PS2, please email us, +anyhelp is greatly appreciated. + +Q: Your emulator sucks!! I don't want to use it! + +A: Then don't, buy a real PS2. If you don't like it, +just don't and there is no need to tell us you don't +like it, the PCSX2 team put alot of hardwork into this +emulator, and don't care to know. + +Q: Can you give me some more 'technical' answers? + +A: A technical FAQ would be massive, and take months to +write. Instead email shadow / linuz with your questions. + +Q: When is the next release? + +A: The next release will happen when there is something +to show, internal changes, and technical changes don't +mean anything to the user, if they don't see something. +Pestering us will make no difference :P + +Q: GSsoft is s..l..o..w!! + +A: Then use one of the OpenGL plugins found at our site +http://pcsx2.ngemu.com or the GStaris plugin +( http://gstaris.ngemu.com ). + +Q: The emulator even with GStaris / GSmax is slow! Why? + +A: First of all, the PS2 is a powerfull piece of +hardware, and will require a powerfull machine to achive +NEAR correct speeds, + +Given that PCSX2 does not run any 'complex' commercial +games, it is hard to judge the system requirements that +will be eventually needed. Plugins and Emulator will get +faster as new releases are made, but you can improve +preformance by turning OFF "Enable Console Output" and +"Enable Interpreter CPU" under 'config>CPU>' in the menu. + +Q: Do I need a DVD drive? + +A: Yes, if you want to read a DVDrom you will need a DVD + drive, many PS2 games are written to CDrom, so its not +essential, unless you have a DVD based game you wish to +try. + +You can also use 'Linuz's CDVD ISO' plugin to run PS2 +games in ISO / BIN format from your HDD. Note only +NTFS Format drives (eg not FAT32) can store greater than +4GB in a single file. + +Q: I hear no sound! + +A: SPU2 Plugins are being worked on by a few coders, but +as of now the only SPU2 plugin is nullSPU, which outputs +no sound, If you are a coder, and feel you can help with +SPU2, please email us. + +Q: Where can I get help!!! + +A: You can get help from the people over at +http://www.ngemu.com or on IRC. Using an IRC client, log +onto #PCSX2 or #NGEMU (EFnet). You can politly ask for +help there (No BIOS / ROM / ISO requests, or you shall be +banned). If you cannot get help there, email the PCSX2 +team. + +_________________________________________________________ + +This FAQ was based on shadow's original FAQ, so thanks to +him. This was written to clear up some of the basic +questions you may have, and I hope it was of help. + +Written with very little sleep and too much coffee, so +please excuse the mistakes, they will be fixed shortly :D + +************ +*Thanks to:* +************ + +The PCSX2 team for making me a betatester, and providing us +with a fantastic PS2 emulator, and the opportinity for me to +work on SPU2 (highly WIP :P ) + +shadow, Linuzappz, Absolute0, [Tyranid], F|res, Roor, +Goldfinger, Florin, basara, asadr, CpUmaster, snake785, +mike9010, bositman, DWatcher, Keith, Martin64.....and many +more I am sure :D + +My lady, Lucy. Without her I would be lost. + +Coffee, where would we be without coffee :D + +********** +*Contact:* +********** + +If you think I should add something to this FAQ, or you +spotted a bug, you can contact me (CKemu) via IRC in +the #PCSX2 (EFnet) channel. + +You can contact the authors via: +http://pcsx2.ngemu.com (homepage) +http://www.pcsx2.net (homepage) +http://www.ngemu.com (offical forums) + +or on IRC: + +#PCSX2 (EFnet) + +Enjoy PCSX2!! + +Best Regards CKemu ( http://www.ckemu.com ). + +/EOF/ \ No newline at end of file diff --git a/pcsx2/Docs/specs.tex b/pcsx2/Docs/specs.tex new file mode 100644 index 0000000..aca2581 --- /dev/null +++ b/pcsx2/Docs/specs.tex @@ -0,0 +1,159 @@ +\documentclass[10pt]{article} + +\begin{document} +\section{...stuff...} +-order the plugins are started\\ +-platform dependent stuff, calling convention\\ + +\section{Generic functions} +The following three functions will be present in all the plugin libraries, + in order to be recognized as valid PS2E plugins. They will help + the emulator to find a plugin capabilities. + +\subsection{PS2EgetLibType} +\begin{quote}\texttt{unsigned int} PS2EgetLibType(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibType] returns the type of the plugin. + In fact it indicates the APIs supported by the dynamic library. + The returned value can be one of: +\begin{itemize} +\item PS2E\_LT\_GS 0x01 +\item PS2E\_LT\_PAD 0x02 +\item PS2E\_LT\_SPU2 0x04 +\item PS2E\_LT\_CDVD 0x08 +\item PS2E\_LT\_DEV9 0x10 +\end{itemize} +Currently, these are the only plugin types supported. Note that the values + can be ORed. +\end{description} + + + +\subsection{PS2EgetLibVersion2} +\begin{quote}\texttt{unsigned int} PS2EgetLibVersion2(\texttt{unsigned int} + type);\end{quote} + +\begin{description} +\item[PS2EgetLibVersion2] returns a combination of version numbers. +Parameter \emph{type} is used to select the functions set for which + the emulator requests version information. See \texttt{PS2EgetLibType} + for the values of this parameter. + +The 5 APIs and their corresponding specs have changed over time. + In order to prevent crashes and incompatibilities, a spec version have + been introduced as the highest 16 bits of the returned value. +\begin{itemize} +\item PS2E\_GS\_VERSION 0x0002 +\item PS2E\_PAD\_VERSION 0x0002 +\item PS2E\_SPU2\_VERSION 0x0002 +\item PS2E\_CDVD\_VERSION 0x0003 +\item PS2E\_DEV9\_VERSION 0x0001 +\end{itemize} +Notice that when the specs do change \texttt{and} the compatibility is broken, + this version number is increased. The emulator loading code will support + only one version for a certain library type at a time. If the internal + version and plugin API version does not match, the plugin + will not be loaded nor used. + +The low half of the returned value reflects the version of the plugin itself. + A major.minor versioning scheme is used on the two bytes like this: +\begin{verbatim} +...//code +return (PS2E_CDVD_VERSION<<16) | (0<<8) | (67); //version 0.67 +\end{verbatim} +\end{description} + + + +\subsection{PS2EgetLibName} +\begin{quote}\texttt{char*} PS2EgetLibName(\texttt{void});\end{quote} + +\begin{description} +\item[PS2EgetLibName] returns a string that contains a short\footnote{ +less then 30 chars in one line} name. The string is stored + in the plugin and will be used to represent the plugin in a config dialog. +\end{description} + + + + + +\section{CDVD functions} +This section describes the functions that corresponds to CDVD\footnote{short for CD/DVD} +API - type PS2E\_LT\_CDVD(0x08). + These specs are for PS2E\_CDVD\_VERSION(0x0003). + +\subsection{CDVDinit} +\begin{quote}\texttt{int} CDVDinit(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDinit] does the initialization of the CDVD interface. + It is the first function called; so, it can be used to do all the + init stuff such as reading saved configuration, one-time hardware init and + preparing the internal structures, tables, etc\ldots + If an error is found the function will return -1, otherwise 0. +\end{description} + + + +\subsection{CDVDshutdown} +\begin{quote}\texttt{void} CDVDshutdown(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDshutdown] is called when the emulator is closed. Do now the freeing + operations. DO NOT FORGET TO FREE the resources used. The OS will probably + free the garbage left, but some pieces of hardware might need a + ``deinitialization'' procedure in order to work next time the emulator + is run. Imagine that the user will choose another plugin to run with + next time instead of yours, do not cause troubles. +\end{description} + + + +\subsection{CDVDopen} +\begin{quote}\texttt{int} CDVDopen(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDopen] is called when the emulation starts. + It is recommended that functions called from now on (until + \texttt{CDVDclose} is met) to spend few processing time. Avoid calling + blocking functions and if you do, the user should be notified visualy. + Report errors by return value and warrings using a log. + If an error is found the function will return -1 and the emulation stops, + otherwise 0. + +Do not report errors using message boxes while the emu runs, the GS plugin + might use a display mode that can cause troubles to windowing system + in showing your message. +\end{description} + + + +\subsection{CDVDclose} +\begin{quote}\texttt{void} CDVDclose(\texttt{void});\end{quote} + +\begin{description} +\item[CDVDclose] is called when the emulation is stopped. Some of the + resources that you aquired with \texttt{CDVDstart} have to be released now + in order that other programs to use them. If you locked the CD/DVD tray, + unlock it so the user can change the disc. +\end{description} + + + +\subsection{CDVDreadTrack} +\begin{quote}\texttt{int} CDVDreadTrack(\texttt{unsigned int} + lsn, \texttt{int} mode);\end{quote} + +\begin{description} +\item[CDVDreadTrack] is the function that performs the read of \texttt{a} + sector from the CD/DVD. Parameter \emph{lsn} specifies the absolute value + of the sector number in linear addressing mode without \emph{lead-in}\footnote{i.e.\ +without leading 150 sectors == 2 seconds}. Usualy, the plugin will read + a full sector of 2352 bytes in its internal buffer. + The second parameter tells what port of ... +\end{description} + +\end{document} + diff --git a/pcsx2/EEregs.h b/pcsx2/EEregs.h new file mode 100644 index 0000000..a25b709 --- /dev/null +++ b/pcsx2/EEregs.h @@ -0,0 +1,40 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __EEREGS_H__ +#define __EEREGS_H__ + +#define at cpuRegs.GPR.n.at +#define k0 cpuRegs.GPR.n.k0 +#define k1 cpuRegs.GPR.n.k1 +#define v0 cpuRegs.GPR.n.v0 +#define v1 cpuRegs.GPR.n.v1 +#define a0 cpuRegs.GPR.n.a0 +#define a1 cpuRegs.GPR.n.a1 +#define a2 cpuRegs.GPR.n.a2 +#define a3 cpuRegs.GPR.n.a3 +#define t0 cpuRegs.GPR.n.t0 +#define s0 cpuRegs.GPR.n.s0 +#define gp cpuRegs.GPR.n.gp +#define fp cpuRegs.GPR.n.s8 +#define sp cpuRegs.GPR.n.sp +#define ra cpuRegs.GPR.n.ra + +#define pc0 cpuRegs.pc + +#endif /* __EEREGS_H__ */ diff --git a/pcsx2/Elfheader.c b/pcsx2/Elfheader.c new file mode 100644 index 0000000..f189702 --- /dev/null +++ b/pcsx2/Elfheader.c @@ -0,0 +1,689 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include //2002-09-28 (Florin) +#include + +#include "Common.h" +#include "CDVDisodrv.h" + +u32 ElfCRC; + +typedef struct { + u8 e_ident[16]; //0x7f,"ELF" (ELF file identifier) + u16 e_type; //ELF type: 0=NONE, 1=REL, 2=EXEC, 3=SHARED, 4=CORE + u16 e_machine; //Processor: 8=MIPS R3000 + u32 e_version; //Version: 1=current + u32 e_entry; //Entry point address + u32 e_phoff; //Start of program headers (offset from file start) + u32 e_shoff; //Start of section headers (offset from file start) + u32 e_flags; //Processor specific flags = 0x20924001 noreorder, mips + u16 e_ehsize; //ELF header size (0x34 = 52 bytes) + u16 e_phentsize; //Program headers entry size + u16 e_phnum; //Number of program headers + u16 e_shentsize; //Section headers entry size + u16 e_shnum; //Number of section headers + u16 e_shstrndx; //Section header stringtable index +} ELF_HEADER; + +typedef struct { + u32 p_type; //see notes1 + u32 p_offset; //Offset from file start to program segment. + u32 p_vaddr; //Virtual address of the segment + u32 p_paddr; //Physical address of the segment + u32 p_filesz; //Number of bytes in the file image of the segment + u32 p_memsz; //Number of bytes in the memory image of the segment + u32 p_flags; //Flags for segment + u32 p_align; //Alignment. The address of 0x08 and 0x0C must fit this alignment. 0=no alignment +} ELF_PHR; + +/* +notes1 +------ +0=Inactive +1=Load the segment into memory, no. of bytes specified by 0x10 and 0x14 +2=Dynamic linking +3=Interpreter. The array element must specify a path name +4=Note. The array element must specify the location and size of aux. info +5=reserved +6=The array element must specify location and size of the program header table. +*/ + +typedef struct { + u32 sh_name; //No. to the index of the Section header stringtable index + u32 sh_type; //See notes2 + u32 sh_flags; //see notes3 + u32 sh_addr; //Section start address + u32 sh_offset; //Offset from start of file to section + u32 sh_size; //Size of section + u32 sh_link; //Section header table index link + u32 sh_info; //Info + u32 sh_addralign; //Alignment. The adress of 0x0C must fit this alignment. 0=no alignment. + u32 sh_entsize; //Fixed size entries. +} ELF_SHR; +/* +notes 2 +------- +Type: +0=Inactive +1=PROGBITS +2=SYMTAB symbol table +3=STRTAB string table +4=RELA relocation entries +5=HASH hash table +6=DYNAMIC dynamic linking information +7=NOTE +8=NOBITS +9=REL relocation entries +10=SHLIB +0x70000000=LOPROC processor specifc +0x7fffffff=HIPROC +0x80000000=LOUSER lower bound +0xffffffff=HIUSER upper bound + +notes 3 +------- +Section Flags: (1 bit, you may combine them like 3 = alloc & write permission) +1=Write section contains data the is be writeable during execution. +2=Alloc section occupies memory during execution +4=Exec section contains executable instructions +0xf0000000=Mask bits processor-specific +*/ + +typedef struct { + u32 st_name; + u32 st_value; + u32 st_size; + u8 st_info; + u8 st_other; + u16 st_shndx; +} Elf32_Sym; + +#define ELF32_ST_TYPE(i) ((i)&0xf) + +typedef struct { + u32 r_offset; + u32 r_info; +} Elf32_Rel; + +//unfinished!!!! + +char *sections_names; + +ELF_HEADER *elfHeader; +ELF_PHR *elfProgH; +ELF_SHR *elfSectH; +char *name; +u8 *elfdata; +u32 elfsize; + +struct stat sbuf; +struct TocEntry toc; + +//2002-09-19 (Florin) +char args[256]="ez.m2v"; //to be accessed by other files +unsigned int args_ptr; //a big value; in fact, it is an address + +//in a0 is passed the address of the command line args, +//i.e. a pointer to an area like this: +//+00 unknown/unused +//+04 argc; number of arguments +//+08 argv[0]; address of the first parameter - program name (char*) - +//+08 argv[1]; address of the second parameter (char*) | +//+0C argv[2]; and so on | +//........ | +//+08+4*argc the program name(first param) <-- +//+08+4*argc+strlen(argv[0]+1) the rest of params; i.e. a copy of 'args' +// see above 'char args[256];' +unsigned int parseCommandLine( char *filename ) +{ + if ( ( args_ptr != 0xFFFFFFFF ) && ( args_ptr > 264 ) ) + { // 4 + 4 + 256 + char * p; + int argc, + i; + + args_ptr -= 256; + if ( args_ptr < 0 ) + { + return 0; + } + args[ 255 ] = 0; + memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 ); //params 1, 2, etc copied + memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) ); +#ifdef _WIN32 + p = strrchr( filename, '\\' ); +#else //linux + p = strrchr( filename, '/' ); + if( p == NULL ) + p = strchr(filename, '\\'); +#endif + if ( p ) + { + p++; + } + else + { + p = filename; + } + args_ptr -= strlen( p ) + 1; + if ( args_ptr < 0 ) + { + return 0; + } + strcpy( (char*)&PS2MEM_BASE[ args_ptr ], p ); //fill param 0; i.e. name of the program + + for ( i = strlen( p ) + 1 + 256, argc = 0; i > 0; i-- ) + { + while ( i && ( ( PS2MEM_BASE[ args_ptr + i ] == 0 ) || ( PS2MEM_BASE[ args_ptr + i ] == 32 ) ) ) + { + i--; + } + if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ' ) + { + PS2MEM_BASE[ args_ptr + i + 1 ] = 0; + } + while ( i && ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i] != 32 ) ) + { + i--; + } + if ( ( PS2MEM_BASE[ args_ptr + i ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i ] != 32 ) ) + { //i==0 + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i; + } + else + { + if ( ( PS2MEM_BASE[ args_ptr + i + 1 ] != 0 ) && ( PS2MEM_BASE[ args_ptr + i + 1 ] != 32 ) ) + { + argc++; + if ( args_ptr - 4 - 4 - argc * 4 < 0 ) + { + return 0; + } + ((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1; + } + } + } + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args + ((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all + + return ( args_ptr - argc * 4 - 8 ); + } + + return 0; +} +//--------------- + +int readFile( char *Exepath, char *ptr, u32 offset, int size ) { + FILE *f; + int fi; + + if ((strnicmp( Exepath, "cdrom0:", strlen("cdrom0:")) == 0) || + (strnicmp( Exepath, "cdrom1:", strlen("cdrom0:")) == 0)) { + if ((u32)offset >= toc.fileSize) return -1; + fi = CDVDFS_open(Exepath + strlen("cdromN:"), 1);//RDONLY + if (fi < 0) return -1; + CDVDFS_lseek(fi, offset, SEEK_SET); + size = CDVDFS_read(fi, ptr, size); + CDVDFS_close(fi ); + } else { + f = fopen(Exepath, "rb"); + if (f == NULL) return -1; + if ( offset >= (u64)sbuf.st_size) return -1; + fseek(f, offset, SEEK_SET); + size = fread(ptr, 1, size, f); + fclose(f); + } + + return size; +} + +int loadHeaders( char *Exepath ) { + elfHeader = (ELF_HEADER*)elfdata; + + if ( ( elfHeader->e_shentsize != sizeof(ELF_SHR) ) && ( elfHeader->e_shnum > 0 ) ) { + SysMessage( "size of section header not standard\n" ); + } + + if((elfHeader->e_shnum * elfHeader->e_shentsize) != 0) { + elfSectH = (ELF_SHR *) malloc( elfHeader->e_shnum * elfHeader->e_shentsize ); + } else { + elfSectH = NULL; + } + + if ( ( elfHeader->e_phnum * elfHeader->e_phentsize ) != 0 ) { + elfProgH = (ELF_PHR *) malloc( elfHeader->e_phnum * elfHeader->e_phentsize ); + } else { + elfProgH = NULL; + } + +#ifdef ELF_LOG + ELF_LOG( "type: " ); +#endif + switch( elfHeader->e_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", elfHeader->e_type ); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG( "no file type" ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG( "relocatable" ); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG( "executable" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG( "\n" ); + ELF_LOG( "machine: " ); +#endif + switch ( elfHeader->e_machine ) + { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown" ); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG( "mips_rs3000" ); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("version: %d\n",elfHeader->e_version); + ELF_LOG("entry: %08x\n",elfHeader->e_entry); + ELF_LOG("flags: %08x\n",elfHeader->e_flags); + ELF_LOG("eh size: %08x\n",elfHeader->e_ehsize); + ELF_LOG("ph off: %08x\n",elfHeader->e_phoff); + ELF_LOG("ph entsiz: %08x\n",elfHeader->e_phentsize); + ELF_LOG("ph num: %08x\n",elfHeader->e_phnum); + ELF_LOG("sh off: %08x\n",elfHeader->e_shoff); + ELF_LOG("sh entsiz: %08x\n",elfHeader->e_shentsize); + ELF_LOG("sh num: %08x\n",elfHeader->e_shnum); + ELF_LOG("sh strndx: %08x\n",elfHeader->e_shstrndx); + + ELF_LOG("\n"); +#endif + + return TRUE; +} + + +BOOL loadProgramHeaders( char *Exepath ) +{ + int i; + + if ( elfHeader->e_phnum == 0 ) + { + return TRUE; + } + + // is this critical, or warning? + if ( elfHeader->e_phentsize != sizeof( ELF_PHR ) ) + { + SysMessage( "size of program header not standard\n" ); + } + + elfProgH = (ELF_PHR*)&elfdata[elfHeader->e_phoff]; + + for ( i = 0 ; i < elfHeader->e_phnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Program Header\n" ); + ELF_LOG( "type: " ); +#endif + switch ( elfProgH[ i ].p_type ) { + default: +#ifdef ELF_LOG + ELF_LOG( "unknown %x", (int)elfProgH[ i ].p_type ); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("load"); +#endif + if (elfProgH[ i ].p_offset < elfsize) { + int size; + + if ((elfProgH[ i ].p_filesz + elfProgH[ i ].p_offset) > elfsize) { + size = elfsize - elfProgH[ i ].p_offset; + } else { + size = elfProgH[ i ].p_filesz; + } + memcpy(&PS2MEM_BASE[elfProgH[ i ].p_paddr & 0x1ffffff], + &elfdata[elfProgH[ i ].p_offset], + size); +#ifdef ELF_LOG + ELF_LOG("\t*LOADED*"); +#endif + } + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("offset: %08x\n",(int)elfProgH[i].p_offset); + ELF_LOG("vaddr: %08x\n",(int)elfProgH[i].p_vaddr); + ELF_LOG("paddr: %08x\n",elfProgH[i].p_paddr); + ELF_LOG("file size: %08x\n",elfProgH[i].p_filesz); + ELF_LOG("mem size: %08x\n",elfProgH[i].p_memsz); + ELF_LOG("flags: %08x\n",elfProgH[i].p_flags); + ELF_LOG("palign: %08x\n",elfProgH[i].p_align); + ELF_LOG("\n"); +#endif + } + + return TRUE; +} + + +BOOL loadSectionHeaders( char * Exepath ) +{ + int i; + int i_st = -1; + int i_dt = -1; + + if (elfHeader->e_shnum == 0 || + elfHeader->e_shoff > elfsize) { + return TRUE; + } + + elfSectH = (ELF_SHR*)&elfdata[elfHeader->e_shoff]; + + if ( elfHeader->e_shstrndx < elfHeader->e_shnum ) { + sections_names = (char *)&elfdata[elfSectH[ elfHeader->e_shstrndx ].sh_offset]; + } + + for ( i = 0 ; i < elfHeader->e_shnum ; i++ ) { +#ifdef ELF_LOG + ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ elfSectH[ i ].sh_name ] ); +#endif + if ( elfSectH[i].sh_flags & 0x2 ) { + //2002-09-19 (Florin) + args_ptr = min( args_ptr, elfSectH[ i ].sh_addr & 0x1ffffff ); + //--------------- +/* if (elfSectH[i].sh_offset < elfsize) { + int size; + + if ((elfSectH[i].sh_size + elfSectH[i].sh_offset) > elfsize) { + size = elfsize - elfSectH[i].sh_offset; + } else { + size = elfSectH[i].sh_size; + } + memcpy(&PS2MEM_BASE[ elfSectH[ i ].sh_addr &0x1ffffff ], + &elfdata[elfSectH[i].sh_offset], + size); + } +#ifdef ELF_LOG + ELF_LOG( "\t*LOADED*" ); +#endif*/ + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("type: "); +#endif + switch ( elfSectH[ i ].sh_type ) + { + default: +#ifdef ELF_LOG + ELF_LOG("unknown %08x",elfSectH[i].sh_type); +#endif + break; + + case 0x0: +#ifdef ELF_LOG + ELF_LOG("null"); +#endif + break; + + case 0x1: +#ifdef ELF_LOG + ELF_LOG("progbits"); +#endif + break; + + case 0x2: +#ifdef ELF_LOG + ELF_LOG("symtab"); +#endif + break; + + case 0x3: +#ifdef ELF_LOG + ELF_LOG("strtab"); +#endif + break; + + case 0x4: +#ifdef ELF_LOG + ELF_LOG("rela"); +#endif + break; + + case 0x8: +#ifdef ELF_LOG + ELF_LOG("no bits"); +#endif + break; + + case 0x9: +#ifdef ELF_LOG + ELF_LOG("rel"); +#endif + break; + } +#ifdef ELF_LOG + ELF_LOG("\n"); + ELF_LOG("flags: %08x\n", elfSectH[i].sh_flags); + ELF_LOG("addr: %08x\n", elfSectH[i].sh_addr); + ELF_LOG("offset: %08x\n", elfSectH[i].sh_offset); + ELF_LOG("size: %08x\n", elfSectH[i].sh_size); + ELF_LOG("link: %08x\n", elfSectH[i].sh_link); + ELF_LOG("info: %08x\n", elfSectH[i].sh_info); + ELF_LOG("addralign: %08x\n", elfSectH[i].sh_addralign); + ELF_LOG("entsize: %08x\n", elfSectH[i].sh_entsize); +#endif + // dump symbol table + + if ( elfSectH[ i ].sh_type == 0x02 ) + { + i_st = i; + i_dt = elfSectH[i].sh_link; + } + } + + if ( ( i_st >= 0 ) && ( i_dt >= 0 ) ) + { + char * SymNames; + Elf32_Sym * eS; + + SymNames = (char*)&elfdata[elfSectH[ i_dt ].sh_offset]; + eS = (Elf32_Sym*)&elfdata[elfSectH[ i_st ].sh_offset]; + SysPrintf("found %d symbols\n", elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym )); + + for ( i = 1; i < (int)( elfSectH[ i_st ].sh_size / sizeof( Elf32_Sym ) ); i++ ) { + if ( ( eS[ i ].st_value != 0 ) && ( ELF32_ST_TYPE( eS[ i ].st_info ) == 2 ) ) { +// SysPrintf("%x:%s\n", eS[i].st_value, &SymNames[eS[i].st_name]); + disR5900AddSym( eS[i].st_value, &SymNames[ eS[ i ].st_name ] ); +/* if (!strcmp(&SymNames[eS[i].st_name], "sceSifCheckStatRpc")) { + psMu32(eS[i].st_value & 0x1ffffff) = (0x3b << 26) | 1; + SysPrintf("found sceSifCheckStatRpc!!\n"); + }*/ + } + } + } + + return TRUE; +} + +extern int LoadPatch(char *patchfile); +extern void LoadGameSpecificSettings(); + +int loadElfFile(char *filename) { + char str[256]; + char str2[256]; + u32 crc; + u32 i; + + SysPrintf("loadElfFile: %s\n", filename); + if (strnicmp( filename, "cdrom0:", strlen( "cdrom0:" ) ) && + strnicmp( filename, "cdrom1:", strlen( "cdrom1:" ) ) ) { + if ( stat( filename, &sbuf ) != 0 ) + return -1; + elfsize = sbuf.st_size; + } else { + CDVDFS_init( ); + if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 ) + return -1; + elfsize = toc.fileSize; + } + + SysPrintf("loadElfFile: %d\n", elfsize); + elfdata = (u8*)malloc(elfsize); + if (elfdata == NULL) return -1; + readFile(filename, (char*)elfdata, 0, elfsize); + +/* { + FILE *f = fopen("game.elf", "wb"); + fwrite(elfdata, 1, elfsize, f); + fclose(f); + }*/ + + //2002-09-19 (Florin) + args_ptr = 0xFFFFFFFF; //big value, searching for minimum + //------------------- + loadHeaders( filename ); + cpuRegs.pc = elfHeader->e_entry; //set pc to proper place + loadProgramHeaders( filename ); + loadSectionHeaders( filename ); + +#ifdef ELF_LOG + ELF_LOG( "PC set to: %8.8lx\n", cpuRegs.pc ); +#endif + cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; + cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok + + //2002-09-19 (Florin) + cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); + //--------------- + + for ( i = 0; i < 0x100000; i++ ) { + if ( strcmp( "rom0:OSDSYS", (char*)PSM( i ) ) == 0 ) { + strcpy( (char*)PSM( i ), filename ); + SysPrintf( "addr %x \"%s\" -> \"%s\"\n", i, "rom0:OSDSYS", filename ); + } + } + + //CRC + for (i=0, crc=0; i +#include "Common.h" +#include "R5900.h" +#include "InterTables.h" + +// Helper Macros +//**************************************************************** +#define _Ft_ ( ( cpuRegs.code >> 16 ) & 0x1F ) +#define _Fs_ ( ( cpuRegs.code >> 11 ) & 0x1F ) +#define _Fd_ ( ( cpuRegs.code >> 6 ) & 0x1F ) + +#define _FtValf_ fpuRegs.fpr[ _Ft_ ].f +#define _FsValf_ fpuRegs.fpr[ _Fs_ ].f +#define _FdValf_ fpuRegs.fpr[ _Fd_ ].f +#define _FAValf_ fpuRegs.ACC.f + +#define _ContVal_ fpuRegs.fprc[ 31 ] + +// Testing +#define _FtValUl_ fpuRegs.fpr[ _Ft_ ].UL +#define _FsValUl_ fpuRegs.fpr[ _Fs_ ].UL +#define _FdValUl_ fpuRegs.fpr[ _Fd_ ].UL +#define _FAValUl_ fpuRegs.ACC.UL + +//**************************************************************** + +void COP1() { +#ifdef FPU_LOG + FPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP1PrintTable[_Rs_](); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + + + +void LWC1() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);// ((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memRead32(addr, &fpuRegs.fpr[_Rt_].UL); +} + +void SWC1() { + s32 addr; + addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);//((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); + memWrite32(addr, fpuRegs.fpr[_Rt_].UL); +} + +void COP1_BC1() { + Int_COP1BC1PrintTable[_Rt_](); +} + +void COP1_S() { + Int_COP1SPrintTable[_Funct_](); +} + +void COP1_W() { + Int_COP1WPrintTable[_Funct_](); +} + +void COP1_Unknown() { +#ifdef FPU_LOG + FPU_LOG("Unknown FPU opcode called\n"); +#endif +} + + + +void MFC1() { + if ( !_Rt_ ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)_FsValUl_; +} + +void CFC1() { + if ( !_Rt_ || ( _Fs_ != 0 && _Fs_ != 31 ) ) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)fpuRegs.fprc[_Fs_]; +} + +void MTC1() { + _FsValUl_ = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +void CTC1() { + if(_Fs_!=31) return; + fpuRegs.fprc[_Fs_] = cpuRegs.GPR.r[_Rt_].UL[0]; +} + +#define C_cond_S(cond) \ + _ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \ + ( _ContVal_ | 0x00800000 ) : \ + ( _ContVal_ & ~0x00800000 ); + +void C_F() { _ContVal_ &= ~0x00800000;} //clears C regardless +void C_EQ() { C_cond_S(==); } +void C_LT() { C_cond_S(<); } +void C_LE() { C_cond_S(<=); } + +#define BC1(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } +void BC1F() { BC1(==); } +void BC1T() { BC1(!=); } + +#define BC1L(cond) \ + if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ + intDoBranch( _BranchTarget_ ); \ + } else cpuRegs.pc += 4; +void BC1FL() { BC1L(==); } // Equal to 0 +void BC1TL() { BC1L(!=); } // different from 0 + + +void ADD_S() { _FdValf_ = _FsValf_ + _FtValf_; } +void SUB_S() { _FdValf_ = _FsValf_ - _FtValf_; } +void MUL_S() { _FdValf_ = _FsValf_ * _FtValf_; } +void MOV_S() { _FdValf_ = _FsValf_; } +void NEG_S() { _FdValf_ = -_FsValf_; } +void ADDA_S() { _FAValf_ = _FsValf_ + _FtValf_; } +void SUBA_S() { _FAValf_ = _FsValf_ - _FtValf_; } +void MULA_S() { _FAValf_ = _FsValf_ * _FtValf_; } +void MADD_S() { _FdValf_ = _FAValf_ + ( _FsValf_ * _FtValf_ ); } +void MSUB_S() { _FdValf_ = _FAValf_ - ( _FsValf_ * _FtValf_ ); } +void MADDA_S() { _FAValf_ += _FsValf_ * _FtValf_; } +void MSUBA_S() { _FAValf_ -= _FsValf_ * _FtValf_; } +void ABS_S() { _FdValf_ = fpufabsf(_FsValf_); } +void MAX_S() { _FdValf_ = max( _FsValf_, _FtValf_ ); } +void MIN_S() { _FdValf_ = min( _FsValf_, _FtValf_ ); } +void DIV_S() { if ( _FtValf_ ) { _FdValf_ = _FsValf_ / _FtValf_; } } +void SQRT_S() { + //if ( _FtValf_ >= 0.0f ) { _FdValf_ = fpusqrtf( _FtValf_ ); } + //else { + _FdValf_ = fpusqrtf(fpufabsf(_FtValf_)); + //} +} +void CVT_S() { _FdValf_ = (float)(s32)_FsValUl_; } +void CVT_W() { + if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValUl_ = (s32)(float)_FsValf_; } + else if ( _FsValUl_ & 0x80000000 ) { _FdValUl_ = 0x80000000; } + else { _FdValUl_ = 0x7fffffff; } +} + +void RSQRT_S() { + if ( _FtValf_ >= 0.0f ) { + float tmp = fpusqrtf( _FtValf_ ); + if ( tmp != 0 ) { _FdValf_ = _FsValf_ / tmp; } + } +} + +//3322 2222 2222 1111 1111 1100 0000 0000 +//1098 7654 3210 9876 5432 1098 7654 3210 +//0000 0000 0000 0000 0000 0000 0000 0000 diff --git a/pcsx2/FPU2.cpp b/pcsx2/FPU2.cpp new file mode 100644 index 0000000..fbda9e9 --- /dev/null +++ b/pcsx2/FPU2.cpp @@ -0,0 +1,25 @@ +#include + +// sqrtf only defined in C++ +extern "C" { + +float (*fpusqrtf)(float fval) = 0; +float (*fpufabsf)(float fval) = 0; +float (*fpusinf)(float fval) = 0; +float (*fpucosf)(float fval) = 0; +float (*fpuexpf)(float fval) = 0; +float (*fpuatanf)(float fval) = 0; +float (*fpuatan2f)(float fvalx, float fvaly) = 0; + +void InitFPUOps() +{ + fpusqrtf = sqrtf; + fpufabsf = fabsf; + fpusinf = sinf; + fpucosf = cosf; + fpuexpf = expf; + fpuatanf = atanf; + fpuatan2f = atan2f; +} + +} diff --git a/pcsx2/FiFo.c b/pcsx2/FiFo.c new file mode 100644 index 0000000..37fddb4 --- /dev/null +++ b/pcsx2/FiFo.c @@ -0,0 +1,179 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "Hw.h" +#include "GS.h" + +#include + +////////////////////////////////////////////////////////////////////////// +/////////////////////////// Quick & dirty FIFO :D //////////////////////// +////////////////////////////////////////////////////////////////////////// +extern int FIFOto_write(u32* pMem, int size); +extern void FIFOfrom_readsingle(void *value); + +extern int g_nIPU0Data; +extern u8* g_pIPU0Pointer; +extern int FOreadpos; +// NOTE: cannot use XMM/MMX regs +void ReadFIFO(u32 mem, u64 *out) { + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("ReadFIFO VIF0 0x%08X\n", mem); +#endif + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else + if ((mem >= 0x10005000) && (mem < 0x10006000)) { + +#ifdef PCSX2_DEVBUILD + VIF_LOG("ReadFIFO VIF1 0x%08X\n", mem); + + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("reading from vif1 fifo when stalled\n"); + } +#endif + + if (vif1Regs->stat & 0x800000) { + if (--psHu32(D1_QWC) == 0) { + vif1Regs->stat&= ~0x1f000000; + } else { + } + } + out[0] = psHu64(mem ); + out[1] = psHu64(mem+8); + return; + } else if( (mem&0xfffff010) == 0x10007000) { + + if( g_nIPU0Data > 0 ) { + out[0] = *(u64*)(g_pIPU0Pointer); + out[1] = *(u64*)(g_pIPU0Pointer+8); + FOreadpos = (FOreadpos + 4) & 31; + g_nIPU0Data--; + g_pIPU0Pointer += 16; + } + return; + }else if ( (mem&0xfffff010) == 0x10007010) { + FIFOfrom_readsingle((void*)out); + return; + } + SysPrintf("ReadFIFO Unknown %x\n", mem); +} + +void ConstReadFIFO(u32 mem) +{ + // not done +} + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +extern HANDLE g_hGsEvent; +#else +extern pthread_cond_t g_condGsEvent; +#endif + +void WriteFIFO(u32 mem, u64 *value) { + int ret; + + if ((mem >= 0x10004000) && (mem < 0x10005000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF0 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + vif0ch->qwc += 1; + ret = VIF0transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10005000) && (mem < 0x10006000)) { +#ifdef VIF_LOG + VIF_LOG("WriteFIFO VIF1 0x%08X\n", mem); +#endif + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + if(vif1Regs->stat & VIF1_STAT_FDR) + SysPrintf("writing to fifo when fdr is set!\n"); + if( vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS) ) { + SysPrintf("writing to vif1 fifo when stalled\n"); + } +#endif + vif1ch->qwc += 1; + ret = VIF1transfer((u32*)value, 4, 0); + assert(ret == 0 ); // vif stall code not implemented + FreezeXMMRegs(0); + } + else if ((mem >= 0x10006000) && (mem < 0x10007000)) { + u64* data; +#ifdef GIF_LOG + GIF_LOG("WriteFIFO GIF 0x%08X\n", mem); +#endif + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + + if( CHECK_MULTIGS ) { + data = (u64*)GSRingBufCopy(NULL, 16, GS_RINGTYPE_P3); + + data[0] = value[0]; + data[1] = value[1]; + GSgifTransferDummy(2, (u32*)data, 1); + GSRINGBUF_DONECOPY(data, 16); + + if( !CHECK_DUALCORE ) { +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + SetEvent(g_hGsEvent); +#else + pthread_cond_signal(&g_condGsEvent); +#endif + } + } + else { + FreezeXMMRegs(1); + GSGIFTRANSFER3((u32*)value, 1); + FreezeXMMRegs(0); + } + + } else + if ((mem&0xfffff010) == 0x10007010) { +#ifdef IPU_LOG + IPU_LOG("WriteFIFO IPU_in[%d] <- %8.8X_%8.8X_%8.8X_%8.8X\n", (mem - 0x10007010)/8, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + //commiting every 16 bytes + while( FIFOto_write((void*)value, 1) == 0 ) { + SysPrintf("IPU sleeping\n"); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + } else { + SysPrintf("WriteFIFO Unknown %x\n", mem); + } +} + +void ConstWriteFIFO(u32 mem) { +} diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp new file mode 100644 index 0000000..2e162bd --- /dev/null +++ b/pcsx2/GS.cpp @@ -0,0 +1,1757 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// rewritten by zerofrog to add multithreading/gs caching to GS and VU1 + + +#if defined(_WIN32) +#include +#endif + +#include + +#include +#include + +using namespace std; + +extern "C" { + +#define PLUGINtypedefs // for GSgifTransfer1 + +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "zlib.h" +#include "Elfheader.h" +#include "Misc.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "VifDma.h" +#include "Memory.h" +#include "Hw.h" + +#include "ix86/ix86.h" +#include "iR5900.h" + +#include "Counters.h" +#include "GS.h" + +extern _GSinit GSinit; +extern _GSopen GSopen; +extern _GSclose GSclose; +extern _GSshutdown GSshutdown; +extern _GSvsync GSvsync; +extern _GSgifTransfer1 GSgifTransfer1; +extern _GSgifTransfer2 GSgifTransfer2; +extern _GSgifTransfer3 GSgifTransfer3; +extern _GSgetLastTag GSgetLastTag; +extern _GSgifSoftReset GSgifSoftReset; +extern _GSreadFIFO GSreadFIFO; +extern _GSreadFIFO2 GSreadFIFO2; + +extern _GSkeyEvent GSkeyEvent; +extern _GSchangeSaveState GSchangeSaveState; +extern _GSmakeSnapshot GSmakeSnapshot; +extern _GSmakeSnapshot2 GSmakeSnapshot2; +extern _GSirqCallback GSirqCallback; +extern _GSprintf GSprintf; +extern _GSsetBaseMem GSsetBaseMem; +extern _GSsetGameCRC GSsetGameCRC; +extern _GSsetFrameSkip GSsetFrameSkip; +extern _GSreset GSreset; +extern _GSwriteCSR GSwriteCSR; + +extern _PADupdate PAD1update, PAD2update; + +// could convert to pthreads only easily, just don't have the time +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +HANDLE g_hGsEvent = NULL, // set when path3 is ready to be processed + g_hVuGSExit = NULL; // set when thread needs to exit +HANDLE g_hGSOpen = NULL, g_hGSDone = NULL; +HANDLE g_hVuGsThread = NULL; + +DWORD WINAPI GSThreadProc(LPVOID lpParam); + +#else +pthread_cond_t g_condGsEvent = PTHREAD_COND_INITIALIZER; +sem_t g_semGsThread; +pthread_mutex_t g_mutexGsThread = PTHREAD_MUTEX_INITIALIZER; +int g_nGsThreadExit = 0; +pthread_t g_VuGsThread; + +void* GSThreadProc(void* idp); + +#endif + +int g_FFXHack=0; + +#ifdef PCSX2_DEVBUILD + +// GS Playback +int g_SaveGSStream = 0; // save GS stream; 1 - prepare, 2 - save +int g_nLeftGSFrames = 0; // when saving, number of frames left +gzFile g_fGSSave; + +// MTGS recording +FILE* g_fMTGSWrite = NULL, *g_fMTGSRead = NULL; +u32 g_MTGSDebug = 0, g_MTGSId = 0; +#endif + +u32 CSRw; +void gsWaitGS(); + +extern long pDsp; + +PCSX2_ALIGNED16(u8 g_MTGSMem[0x2000]); // mtgs has to have its own memory + +} // extern "C" + +#ifdef PCSX2_VIRTUAL_MEM +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +#else +#define gif ((DMACh*)&psH[0xA000]) +#endif + +#ifdef PCSX2_VIRTUAL_MEM +#define PS2GS_BASE(mem) ((PS2MEM_BASE+0x12000000)+(mem&0x13ff)) +#else +u8 g_RealGSMem[0x2000]; +#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) +#endif + +// dummy GS for processing SIGNAL, FINISH, and LABEL commands +typedef struct +{ + u32 nloop : 15; + u32 eop : 1; + u32 dummy0 : 16; + u32 dummy1 : 14; + u32 pre : 1; + u32 prim : 11; + u32 flg : 2; + u32 nreg : 4; + u32 regs[2]; + u32 curreg; +} GIFTAG; + +static GIFTAG g_path[3]; +static PCSX2_ALIGNED16(u8 s_byRegs[3][16]); + +// g_pGSRingPos == g_pGSWritePos => fifo is empty +u8* g_pGSRingPos = NULL, // cur pos ring is at + *g_pGSWritePos = NULL; // cur pos ee thread is at + +extern int g_nCounters[]; + +void gsInit() +{ + if( CHECK_MULTIGS ) { + +#ifdef _WIN32 + g_pGSRingPos = (u8*)VirtualAlloc(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); +#else + // setup linux vm + g_pGSRingPos = (u8*)SysMmap((uptr)GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE); +#endif + if( g_pGSRingPos != GS_RINGBUFFERBASE ) { + SysMessage("Cannot alloc GS ring buffer\n"); + exit(0); + } + + memcpy(g_MTGSMem, PS2MEM_GS, sizeof(g_MTGSMem)); + InterlockedExchangePointer((volatile PVOID*)&g_pGSWritePos, GS_RINGBUFFERBASE); + + if( GSsetBaseMem != NULL ) + GSsetBaseMem(g_MTGSMem); + +#ifdef _DEBUG + assert( g_fMTGSWrite == NULL && g_fMTGSRead == NULL ); + g_fMTGSWrite = fopen("mtgswrite.txt", "w"); + g_fMTGSRead = fopen("mtgsread.txt", "w"); +#endif + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + g_hGsEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + g_hVuGSExit = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSOpen = CreateEvent(NULL, FALSE, FALSE, NULL); + g_hGSDone = CreateEvent(NULL, FALSE, FALSE, NULL); + + SysPrintf("gsInit\n"); + + g_hVuGsThread = CreateThread(NULL, 0, GSThreadProc, NULL, 0, NULL); +#else + SysPrintf("gsInit\n"); + sem_init(&g_semGsThread, 0, 0); + + pthread_mutex_lock(&g_mutexGsThread); + if( pthread_create(&g_VuGsThread, NULL, GSThreadProc, NULL) != 0 ) { + SysMessage("Failed to create gsthread\n"); + exit(0); + } + + pthread_mutex_lock(&g_mutexGsThread); + pthread_mutex_unlock(&g_mutexGsThread); +#endif + } +} + +void gsWaitGS() +{ + while( g_pGSRingPos != g_pGSWritePos ) { +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } +} + +void gsShutdown() +{ + if( CHECK_MULTIGS ) { + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + SetEvent(g_hVuGSExit); + SysPrintf("Closing gs thread\n"); + WaitForSingleObject(g_hVuGsThread, INFINITE); + CloseHandle(g_hVuGsThread); + CloseHandle(g_hGsEvent); + CloseHandle(g_hVuGSExit); + CloseHandle(g_hGSOpen); + CloseHandle(g_hGSDone); +#else + InterlockedExchange((long*)&g_nGsThreadExit, 1); + sem_post(&g_semGsThread); + pthread_cond_signal(&g_condGsEvent); + SysPrintf("waiting for thread to terminate\n"); + pthread_join(g_VuGsThread, NULL); + + sem_destroy(&g_semGsThread); + + SysPrintf("thread terminated\n"); +#endif + +#ifdef _WIN32 + VirtualFree(GS_RINGBUFFERBASE, GS_RINGBUFFERSIZE, MEM_DECOMMIT|MEM_RELEASE); +#endif + +#ifdef _DEBUG + if( g_fMTGSWrite != NULL ) { + fclose(g_fMTGSWrite); + g_fMTGSWrite = NULL; + } + if( g_fMTGSRead != NULL ) { + fclose(g_fMTGSRead); + g_fMTGSRead = NULL; + } +#endif + } + else + GSclose(); +} + +typedef u8* PU8; + +u8* GSRingBufCopy(void* mem, u32 size, u32 type) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + assert( size < GS_RINGBUFFERSIZE ); + assert( writepos < GS_RINGBUFFEREND ); + assert( ((uptr)writepos & 15) == 0 ); + assert( (size&15) == 0); + + size += 16; + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos + size > GS_RINGBUFFEREND ) { + + // skip to beginning + while( writepos < tempbuf || tempbuf == GS_RINGBUFFERBASE ) { + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } + + // notify GS + if( writepos != GS_RINGBUFFEREND ) { + InterlockedExchangePointer((void**)writepos, GS_RINGTYPE_RESTART); + } + + InterlockedExchangePointer((void**)&g_pGSWritePos, GS_RINGBUFFERBASE); + writepos = GS_RINGBUFFERBASE; + } + else if( writepos + size == GS_RINGBUFFEREND ) { + while(tempbuf == GS_RINGBUFFERBASE && tempbuf != *(volatile PU8*)&g_pGSWritePos) { + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + } + + while( writepos < tempbuf && (writepos+size >= tempbuf || (writepos+size == GS_RINGBUFFEREND && tempbuf == GS_RINGBUFFERBASE)) ) { + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } + + // just copy + *(u32*)writepos = type|(((size-16)>>4)<<16); + return writepos+16; +} + +void GSRingBufSimplePacket(int type, int data0, int data1, int data2) +{ + u8* writepos = g_pGSWritePos; + u8* tempbuf; + + assert( writepos + 16 <= GS_RINGBUFFEREND ); + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + if( writepos < tempbuf && writepos+16 >= tempbuf ) { + + do { + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + tempbuf = *(volatile PU8*)&g_pGSRingPos; + + if( tempbuf == *(volatile PU8*)&g_pGSWritePos ) + break; + } while(writepos < tempbuf && writepos+16 >= tempbuf ); + } + + *(u32*)writepos = type; + *(int*)(writepos+4) = data0; + *(int*)(writepos+8) = data1; + *(int*)(writepos+12) = data2; + + writepos += 16; + if( writepos == GS_RINGBUFFEREND ) { + + while(tempbuf == GS_RINGBUFFERBASE && tempbuf != *(volatile PU8*)&g_pGSWritePos) { + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); +#ifdef _WIN32 + Sleep(1); +#else + usleep(500); +#endif + } + + tempbuf = *(volatile PU8*)&g_pGSRingPos; + } + + writepos = GS_RINGBUFFERBASE; + } + InterlockedExchangePointer((void**)&g_pGSWritePos, writepos); + + if( !CHECK_DUALCORE ) { + GS_SETEVENT(); + } +} + +void gsReset() +{ + SysPrintf("GIF reset\n"); + + // GSDX crashes + //if( GSreset ) GSreset(); + + if( CHECK_MULTIGS ) { +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + ResetEvent(g_hGsEvent); + ResetEvent(g_hVuGSExit); +#else + //TODO +#endif + g_pGSRingPos = g_pGSWritePos; + } + + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + +#ifndef PCSX2_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void gsGIFReset() +{ + memset(g_path, 0, sizeof(g_path)); + +#ifndef PCSX2_VIRTUAL_MEM + memset(g_RealGSMem, 0, 0x2000); +#endif + + if( GSgifSoftReset != NULL ) + GSgifSoftReset(7); + if( CHECK_MULTIGS ) + memset(g_path, 0, sizeof(g_path)); + +// else +// GSreset(); + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now + GSIMR = 0x7f00; + psHu32(GIF_STAT) = 0; + psHu32(GIF_CTRL) = 0; + psHu32(GIF_MODE) = 0; +} + +void CSRwrite(u32 value) +{ + CSRw |= value & ~0x60; + GSwriteCSR(CSRw); + + GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f); + + if( value & 0x100 ) { // FLUSH + //SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr); + } + + if (value & 0x200) { // resetGS + //GSCSRr = 0x400E; // The host FIFO neeeds to be empty too or GSsync will fail (saqib) + //GSIMR = 0xff00; + if( GSgifSoftReset != NULL ) { + GSgifSoftReset(7); + if( CHECK_MULTIGS ) { + memset(g_path, 0, sizeof(g_path)); + memset(s_byRegs, 0, sizeof(s_byRegs)); + } + } + else GSreset(); + + GSCSRr = 0x551B400F; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) + //Since when!! Refraction, since 4/21/06 (zerofrog) ok ill let you off, looks like theyre all set (ref) + GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 + + // and this too (fixed megaman ac) + //CSRw = (u32)GSCSRr; + GSwriteCSR(CSRw); + } +} + +static void IMRwrite(u32 value) { + GSIMR = (value & 0x1f00)|0x6000; + + // don't update mtgs mem +} + +void gsWrite8(u32 mem, u8 value) { + switch (mem) { + case 0x12001000: // GS_CSR + CSRwrite((CSRw & ~0x000000ff) | value); break; + case 0x12001001: // GS_CSR + CSRwrite((CSRw & ~0x0000ff00) | (value << 8)); break; + case 0x12001002: // GS_CSR + CSRwrite((CSRw & ~0x00ff0000) | (value << 16)); break; + case 0x12001003: // GS_CSR + CSRwrite((CSRw & ~0xff000000) | (value << 24)); break; + default: + *PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE8, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 8 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +extern void UpdateVSyncRate(); + +void gsWrite16(u32 mem, u16 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + + UpdateVSyncRate(); + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + + break; + + case 0x12001000: // GS_CSR + CSRwrite( (CSRw&0xffff0000) | value); + break; + case 0x12001002: // GS_CSR + CSRwrite( (CSRw&0xffff) | ((u32)value<<16)); + break; + case 0x12001010: // GS_IMR + SysPrintf("writing to IMR 16\n"); + IMRwrite(value); + break; + + default: + *(u16*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE16, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 16 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void gsWrite32(u32 mem, u32 value) +{ + assert( !(mem&3)); + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + *(u32*)PS2GS_BASE(mem) = value; + + UpdateVSyncRate(); + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + + break; + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u32*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + break; + + case 0x12001000: // GS_CSR + CSRwrite(value); + break; + + case 0x12001010: // GS_IMR + IMRwrite(value); + break; + default: + *(u32*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE32, mem&0x13ff, value, 0); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 32 at %8.8lx with data %8.8lx\n", mem, value); +#endif +} + +void gsWrite64(u32 mem, u64 value) { + + switch (mem) { + case 0x12000010: // GS_SMODE1 + if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL + else Config.PsxType &= ~1; // NTSC + UpdateVSyncRate(); + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, (u32)(value>>32)); + } + + break; + + case 0x12000020: // GS_SMODE2 + if(value & 0x1) Config.PsxType |= 2; // Interlaced + else Config.PsxType &= ~2; // Non-Interlaced + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, 0); + } + + break; + case 0x12001000: // GS_CSR + CSRwrite((u32)value); + break; + + case 0x12001010: // GS_IMR + IMRwrite((u32)value); + break; + + default: + *(u64*)PS2GS_BASE(mem) = value; + + if( CHECK_MULTIGS ) { + GSRingBufSimplePacket(GS_RINGTYPE_MEMWRITE64, mem&0x13ff, (u32)value, (u32)(value>>32)); + } + } + +#ifdef GIF_LOG + GIF_LOG("GS write 64 at %8.8lx with data %8.8lx_%8.8lx\n", mem, ((u32*)&value)[1], (u32)value); +#endif +} + +u8 gsRead8(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 8 %8.8lx, at %8.8lx\n", *(u8*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u8*)PS2GS_BASE(mem); +} + +u16 gsRead16(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 16 %8.8lx, at %8.8lx\n", *(u16*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + + return *(u16*)PS2GS_BASE(mem); +} + +u32 gsRead32(u32 mem) { + +#ifdef GIF_LOG + GIF_LOG("GS read 32 %8.8lx, at %8.8lx\n", *(u32*)(PS2MEM_BASE+(mem&~0xc00)), mem); +#endif + return *(u32*)PS2GS_BASE(mem); +} + +u64 gsRead64(u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", (u32)PS2GS_BASE(mem), mem); +#endif + return *(u64*)PS2GS_BASE(mem); +} + +void gsIrq() { + hwIntcIrq(0); +} + +static void GSRegHandlerSIGNAL(u32* data) +{ + GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + + if (!(GSCSRr & 0x1)) { + GSCSRr |= 1; // signal + //CSRw &= ~1; + + } + if (!(GSIMR&0x100) ) + gsIrq(); + +} + +static void GSRegHandlerFINISH(u32* data) +{ + + if (!(GSCSRr & 0x2)) { + //CSRw &= ~2; + GSCSRr |= 2; // finish + + } + if (!(GSIMR&0x200) ) + gsIrq(); +} + +static void GSRegHandlerLABEL(u32* data) +{ + GSSIGLBLID->LBLID = (GSSIGLBLID->LBLID&~data[1])|(data[0]&data[1]); +} + +typedef void (*GIFRegHandler)(u32* data); +static GIFRegHandler s_GSHandlers[3] = { GSRegHandlerSIGNAL, GSRegHandlerFINISH, GSRegHandlerLABEL }; + +// simulates a GIF tag +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size) +{ + int nreg, i, nloop; + u32 curreg; + u32 tempreg; + GIFTAG* ptag = &g_path[path]; + //if( path == 2 )psHu32(GIF_STAT) |= 0xE00; + if( path == 0 ) { + nloop = 0; + } + else { + nloop = ptag->nloop; + curreg = ptag->curreg; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + } + + while(size > 0) + { + if(nloop == 0) { + + ptag = (GIFTAG*)pMem; + nreg = ptag->nreg == 0 ? 16 : ptag->nreg; + + pMem+= 4; + size--; + + if(ptag->nloop == 0 ) { + if( path == 0 ) { + + if( ptag->eop ) + return size; + + // ffx hack + if( g_FFXHack ) + continue; + + return size; + } + + g_path[path].nloop = 0; + + // motogp graphics show + if( !ptag->eop ) + continue; + + return size; + } + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + s_byRegs[path][i] = tempreg&0xf; + } + + nloop = ptag->nloop; + curreg = 0; + } + + switch(ptag->flg) + { + case 0: // PACKED + { + for(; size > 0; size--, pMem += 4) + { + if( s_byRegs[path][curreg] == 0xe && (pMem[2]&0xff) >= 0x60 ) { + if( (pMem[2]&0xff) < 0x64 ) + s_GSHandlers[pMem[2]&0x3](pMem); + } + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 4; + break; + } + } + } + + if( nloop > 0 ) { + assert(size == 0); + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 1: // REGLIST + { + size *= 2; + + tempreg = ptag->regs[0]; + for(i = 0; i < nreg; ++i, tempreg >>= 4) { + + if( i == 8 ) tempreg = ptag->regs[1]; + assert( (tempreg&0xf) < 0x64 ); + s_byRegs[path][i] = tempreg&0xf; + } + + for(; size > 0; pMem+= 2, size--) + { + if( s_byRegs[path][curreg] >= 0x60 ) + s_GSHandlers[s_byRegs[path][curreg]&3](pMem); + + curreg++; + if (nreg == curreg) { + curreg = 0; + if( nloop-- <= 1 ) { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + + if( nloop > 0 ) { + assert(size == 0); + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop; + g_path[path].curreg = curreg; + return 0; + } + + break; + } + case 2: // GIF_IMAGE (FROM_VFRAM) + case 3: + { + // simulate + if( (int)size < nloop ) { + // midnight madness cares because the tag is 5 dwords + int* psrc = (int*)ptag; + int* pdst = (int*)&g_path[path]; + pdst[0] = psrc[0]; pdst[1] = psrc[1]; pdst[2] = psrc[2]; pdst[3] = psrc[3]; + g_path[path].nloop = nloop-size; + return 0; + } + else { + pMem += nloop*4; + size -= nloop; + nloop = 0; + } + break; + } + } + + if( path == 0 && ptag->eop ) { + g_path[0].nloop = 0; + return size; + } + } + //if( path == 2 && g_path[2].nloop == 0) psHu32(GIF_STAT) &= ~0xE00; + g_path[path] = *ptag; + g_path[path].curreg = curreg; + g_path[path].nloop = nloop; + + return size; +} +static int done=0; +static int amount = 16; +int gsInterrupt() { +#ifdef GIF_LOG + GIF_LOG("gsInterrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if((gif->chcr & 0x100) == 0){ + //SysPrintf("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x\n", gif->chcr, gif->qwc, done); + return 1; + } + if(gif->qwc > 0 || done == 0) { + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("gs dma masked\n"); + return 0; + } + + dmaGIF(); +#ifdef GSPATH3FIX + amount = 16; + if ((vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) || (gif->chcr & 0x100) == 0) return 1; + else +#endif + return 0; + } + + done = 0; + amount = 16; + gif->chcr &= ~0x100; + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 + hwDmacIrq(DMAC_GIF); + + return 1; +} + +static u64 s_gstag=0; // used for querying the last tag + +#define WRITERING_DMA(pMem, qwc) { \ + if( CHECK_MULTIGS) { \ + u8* pgsmem = GSRingBufCopy(pMem, (qwc)<<4, GS_RINGTYPE_P3); \ + if( pgsmem != NULL ) { \ + int sizetoread = (qwc)<<4; \ + u32 pendmem = (u32)gif->madr + sizetoread; \ + /* check if page of endmem is valid (dark cloud2) */ \ + if( dmaGetAddr(pendmem-16) == NULL ) { \ + pendmem = ((pendmem-16)&~0xfff)-16; \ + while(dmaGetAddr(pendmem) == NULL) { \ + pendmem = (pendmem&~0xfff)-16; \ + } \ + memcpy_fast(pgsmem, pMem, pendmem-(u32)gif->madr+16); \ + } \ + else memcpy_fast(pgsmem, pMem, sizetoread); \ + \ + GSRINGBUF_DONECOPY(pgsmem, sizetoread); \ + GSgifTransferDummy(2, pMem, qwc); \ + } \ + \ + if( !CHECK_DUALCORE ) GS_SETEVENT(); \ + } \ + else { \ + /*psHu32(GIF_STAT) |= 0xE00;*/ \ + FreezeMMXRegs(1); \ + FreezeXMMRegs(1); \ + GSGIFTRANSFER3(pMem, qwc); \ + /*if( GSgetLastTag != NULL ) { \ + GSgetLastTag(&s_gstag); \ + if( (s_gstag&0x7fff) == 0 ) psHu32(GIF_STAT) &= ~0xE00; \ + }*/ \ + } \ +} \ + +int _GIFchain() { +#ifdef GSPATH3FIX + u32 qwc = (psHu32(GIF_MODE) & 0x4) ? min(8, gif->qwc) : gif->qwc; +#else + u32 qwc = gif->qwc; +#endif + u32 *pMem; + + if (gif->qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) { + // reset path3, fixes dark cloud 2 + if( GSgifSoftReset != NULL ) + GSgifSoftReset(4); + if( CHECK_MULTIGS ) { + memset(&g_path[2], 0, sizeof(g_path[2])); + } + + SysPrintf("NULL GIFchain\n"); + return -1; + } + //if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1)SysPrintf("Pmem 0 == %x\n", pMem[0]); + WRITERING_DMA(pMem, qwc); + //if((psHu32(GIF_MODE) & 0x4)) amount -= qwc; + gif->madr+= qwc*16; + gif->qwc -= qwc; + return (qwc)*2; +} + +#define GIFchain() \ + if (gif->qwc) { \ + cycles+= _GIFchain(); /* guessing */ \ + } + +int gscount = 0; +static int prevcycles = 0; +static u32* prevtag = NULL; + +void dmaGIF() { + u32 *ptag; + int cycles=prevcycles; + u32 id; + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC ) { // GIF MFIFO + gifMFIFOInterrupt(); + return; + } + if( (psHu32(GIF_CTRL) & 8) ) { + // temporarily stop + SysPrintf("Gif dma temp paused?\n"); + return; + } + +/*SysPrintf("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + gif->chcr, gif->madr, gif->qwc, + gif->tadr, gif->asr0, gif->asr1);*/ + + +#ifndef GSPATH3FIX + if (psHu32(GIF_MODE) & 0x4) { + } else + if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1) { + gif->chcr &= ~0x100; + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + hwDmacIrq(2); + return; + } +#endif + + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && prevcycles != 0) { // STD == GIF + SysPrintf("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); + + if( gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) ) { + INT(2, cycles); + return; + } + prevcycles = 0; + gif->qwc = 0; + } + + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x8000; //FIFO full + psHu32(GIF_STAT)|= 0xE00; // OPH=1 | APATH=3 + psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) + +#ifdef GSPATH3FIX + if (vif1Regs->mskpath3 || psHu32(GIF_MODE) & 0x1){ + if((vif1.cmd & 0x7f) != 0x13 && (vif1.cmd & 0x7f) != 0x51 && (vif1.cmd & 0x7f) != 0x6)return; //If its none of the vif cmds related to path3 stuff/flusha return + //if(psHu32(GIF_MODE) & 0x4) {( + if(gif->qwc == 0){ + + //SysPrintf("QWC == 0, chcr %x\n", gif->chcr); + if((gif->chcr & 0xf0e) == 0x104){ + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return; + } + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + done = hwDmacSrcChainWithStack(gif, id); + } + } + GIFchain(); + + + if(done == 1 && gif->qwc == 0 || (gif->chcr & 0xc) == 0){ //INT(2, cycles); + //SysPrintf("Horray\n"); + done = 0; + gif->chcr &= ~0x100; + GSCSRr &= ~0xC000; //Clear FIFO stuff + GSCSRr |= 0x4000; //FIFO empty + psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 + psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 + hwDmacIrq(DMAC_GIF); + } + return; + } +#endif + /*if( prevcycles != 0 ) { + assert( prevtag != NULL ); + + ptag = prevtag; + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + // transfer interrupted, so continue + prevcycles = 0; + GIFchain(); + + if (gif->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + done = 1; + + } + }*/ + + // Transfer Dn_QWC from Dn_MADR to GIF + if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode + //gscount++; + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80 && (gif->chcr & 0xc) == 0) { + SysPrintf("DMA Stall Control on GIF normal\n"); + } + GIFchain(); + if(gif->qwc == 0 && (gif->chcr & 0xc) == 0)done = 1; + } + else { + // Chain Mode +#ifndef GSPATH3FIX + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + #endif + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return; + } + cycles+=2; // Add 1 cycles from the QW read for the tag + // Transfer dma tag if tte is set + if (gif->chcr & 0x40) { + //u32 temptag[4] = {0}; +#ifdef PCSX2_DEVBUILD + //SysPrintf("GIF TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + + //temptag[0] = ptag[2]; + //temptag[1] = ptag[3]; + //GSGIFTRANSFER3(ptag, 1); + } + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->madr = ptag[1]; //MADR = ADDR field + + + + done = hwDmacSrcChainWithStack(gif, id); +/*SysPrintf("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr);*/ + + if (!done && (psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) && id == 4) { + // stalled + SysPrintf("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); + prevcycles = cycles; + gif->tadr -= 16; + hwDmacIrq(13); + INT(2, cycles); + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return; + } + } + + GIFchain(); //Transfers the data set by the switch + + if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("GIF TIE\n"); + + // SysPrintf("GSdmaIrq Set\n"); + done = 1; + //gif->qwc = 0; + //break; + } +#ifndef GSPATH3FIX + } +#endif + } + + prevtag = NULL; + prevcycles = 0; + INT(2, cycles); + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +static int mfifocycles; + +int mfifoGIFrbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *src; + + /* Check if the transfer should wrap around the ring buffer */ + if ((gif->madr+gif->qwc*16) >= (maddr+msize)) { + int s1 = (maddr+msize) - gif->madr; + int s2 = gif->qwc*16 - s1; + + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + WRITERING_DMA(src, s1&~15); + + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + WRITERING_DMA(src, s2&~15); + + } else { + /* it doesn't, so just transfer 'qwc*16' words + from 'gif->madr' to GS */ + src = (u32*)PSM(gif->madr); + if (src == NULL) return -1; + + WRITERING_DMA(src, gif->qwc); + } + + gif->madr+= gif->qwc*16; + + + return 0; +} + +int mfifoGIFchain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16; + u32 *pMem; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (gif->qwc == 0) return 0; + + if (gif->madr >= maddr && + gif->madr <= (maddr+msize)) { + if (mfifoGIFrbTransfer() == -1) return -1; + } else { + pMem = (u32*)dmaGetAddr(gif->madr); + if (pMem == NULL) return -1; + + WRITERING_DMA(pMem, gif->qwc); + gif->madr+= gif->qwc*16; + } + + mfifocycles+= (gif->qwc) * 2; /* guessing */ + gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + gif->qwc = 0; + + return 0; +} + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) + +static int giftempqwc = 0; +static int g_gifCycles = 0; +static int gifqwc = 0; +static int gifdone = 0; + +void mfifoGIFtransfer(int qwc) { + u32 *ptag; + int id; + u32 temp = 0; + mfifocycles = 0; + gifqwc += qwc; + g_gifCycles = 0; + if(gifqwc == 0 || !(gif->chcr & 0x100)) { + //#ifdef PCSX2_DEVBUILD + /*if( gifqwc > 1 ) + SysPrintf("gif mfifo tadr==madr but qwc = %d\n", gifqwc);*/ + //#endif + //INT(11,50); + return; + } +/*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ +#ifdef GIF_LOG + GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); +#endif + + if((gif->chcr & 0x100) == 0)SysPrintf("MFIFO GIF not ready!\n"); + //while (qwc > 0 && done == 0) { + if(gif->qwc == 0){ + if(gif->tadr == spr0->madr) { + #ifdef PCSX2_DEVBUILD + /*if( gifqwc > 1 ) + SysPrintf("gif mfifo tadr==madr but qwc = %d\n", gifqwc);*/ + #endif + //hwDmacIrq(14); + return; + } + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + ptag = (u32*)dmaGetAddr(gif->tadr); + + id = (ptag[0] >> 28) & 0x7; + gif->qwc = (ptag[0] & 0xffff); + gif->madr = ptag[1]; + mfifocycles += 2; + + + /*if(gif->chcr & 0x40) { //Not used-doesnt work :P + ret = GIFtransfer(ptag+2, 2, 1); + assert(ret == 0 ); // gif stall code not implemented + }*/ + + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + + #ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr, gifqwc, spr0->madr); + #endif + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + if(gifqwc < gif->qwc && (gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->tadr += 16; + gifdone = 1; //End Transfer + break; + + case 1: // CNT - Transfer QWC following the tag. + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->madr = gif->tadr + 16; //Set MADR to QW after Tag + gif->tadr = gif->madr + (gif->qwc << 4); //Set TADR to QW following the data + gifdone = 0; + break; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + temp = gif->madr; //Temporarily Store ADDR + gif->madr = gif->tadr + 16; //Set MADR to QW following the tag + gif->tadr = temp; //Copy temporarily stored ADDR to Tag + gifdone = 0; + break; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + if(gifqwc < gif->qwc && (gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->tadr += 16; //Set TADR to next tag + gifdone = 0; + break; + + case 7: // End - Transfer QWC following the tag + if(gifqwc < gif->qwc && ((gif->tadr + 16) & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + //SysPrintf("Sliced GIF MFIFO Transfer %d\n", id); + return; + } + gif->madr = gif->tadr + 16; //Set MADR to data following the tag + gif->tadr = gif->madr + (gif->qwc << 4); //Set TADR to QW following the data + gifdone = 1; //End Transfer + break; + } + gifqwc--; + + //SysPrintf("GIF MFIFO qwc %d gif qwc %d, madr = %x, tadr = %x\n", qwc, gif->qwc, gif->madr, gif->tadr); + gif->tadr = psHu32(DMAC_RBOR) + (gif->tadr & psHu32(DMAC_RBSR)); + if((gif->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)){ + gif->madr = psHu32(DMAC_RBOR) + (gif->madr & psHu32(DMAC_RBSR)); + gifqwc -= gif->qwc; + } + } + + if (mfifoGIFchain() == -1) { + SysPrintf("dmaChain error %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], gif->qwc, id, gif->madr, gif->tadr); + gifdone = 1; + INT(11,mfifocycles+g_gifCycles); + } + + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoGIFtransfer: dmaIrq Set\n"); + //gifqwc = 0; + gifdone = 1; + } + +// if( (cpuRegs.interrupt & (1<<1)) && qwc > 0) { +// SysPrintf("gif mfifo interrupt %d\n", qwc); +// } + //} + + /*if(gifdone == 1) { + gifqwc = 0; + }*/ + INT(11,mfifocycles+g_gifCycles); + if(gifqwc == 0 && giftempqwc > 0) hwDmacIrq(14); + + //hwDmacIrq(1); +#ifdef SPR_LOG + SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); +#endif +} + +int gifMFIFOInterrupt() +{ + mfifocycles = 0; + + if(!(gif->chcr & 0x100)) return 1; + else if(gifqwc == 0 && gifdone == 0) return 1; + + if(gifdone == 0 && gifqwc != 0) { + mfifoGIFtransfer(0); + if(gif->qwc > 0) return 1; + else return 0; + } + if(gifdone == 0 || gif->qwc > 0) { + SysPrintf("Shouldnt go here\n"); + return 1; + } + gifdone = 0; + gif->chcr &= ~0x100; + hwDmacIrq(DMAC_GIF); + + return 1; +} + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +DWORD WINAPI GSThreadProc(LPVOID lpParam) +{ + HANDLE handles[2] = { g_hGsEvent, g_hVuGSExit }; + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + { + int ret; + HANDLE openhandles[2] = { g_hGSOpen, g_hVuGSExit }; + if( WaitForMultipleObjects(2, openhandles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + return 0; + } + ret = GSopen((void *)&pDsp, "PCSX2", 1); + GSCSRr = 0x551B400F; // 0x55190000 + SysPrintf("gsOpen done\n"); + if (ret != 0) { SysMessage ("Error Opening GS Plugin"); return (DWORD)-1; } + SetEvent(g_hGSDone); + } +#else +void* GSThreadProc(void* lpParam) +{ + // g_mutexGSThread already locked + SysPrintf("waiting for gsOpen\n"); + pthread_cond_wait(&g_condGsEvent, &g_mutexGsThread); + pthread_mutex_unlock(&g_mutexGsThread); + pthread_testcancel(); + if( g_nGsThreadExit ) + return NULL; + + int ret = GSopen((void *)&pDsp, "PCSX2", 1); + GSCSRr = 0x551B400F; // 0x55190000 + SysPrintf("gsOpen done\n"); + if (ret != 0) { + SysMessage ("Error Opening GS Plugin"); + return NULL; + } + + sem_post(&g_semGsThread); + pthread_mutex_unlock(&g_mutexGsThread); +#endif + + SysPrintf("Starting GS thread\n"); + u8* writepos; + u32 tag; + u32 counter = 0; + + while(1) { + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + if( !CHECK_DUALCORE ) { + if( WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0+1 ) { + GSclose(); + return 0; + } + } + else if( !(counter++ & 0xffff) ) { + if( WaitForSingleObject(g_hVuGSExit, 0) == WAIT_OBJECT_0 ) { + GSclose(); + return 0; + } + } +#else + if( !CHECK_DUALCORE ) { + sem_wait(&g_semGsThread); + if( g_nGsThreadExit ) { + GSclose(); + return 0; + } + } + else if( !(counter++ & 0xffff) ) { + if( g_nGsThreadExit ) { + GSclose(); + return 0; + } + } +#endif + + if( g_pGSRingPos != g_pGSWritePos ) { + + do { + writepos = *(volatile PU8*)&g_pGSWritePos; + + while( g_pGSRingPos != writepos ) { + + assert( g_pGSRingPos < GS_RINGBUFFEREND ); + // process until writepos + tag = *(u32*)g_pGSRingPos; + + switch( tag&0xffff ) { + case GS_RINGTYPE_RESTART: + InterlockedExchangePointer((volatile PVOID*)&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( GS_RINGBUFFERBASE == writepos ) + goto ExitGS; + + continue; + + case GS_RINGTYPE_P1: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer1((u32*)(g_pGSRingPos+16), 0); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + + case GS_RINGTYPE_P2: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer2((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_P3: + MTGS_RECREAD(g_pGSRingPos+16, ((tag>>16)<<4)); + GSgifTransfer3((u32*)(g_pGSRingPos+16), tag>>16); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16 + ((tag>>16)<<4)); + break; + case GS_RINGTYPE_VSYNC: + GSvsync(*(int*)(g_pGSRingPos+4)); + if( PAD1update != NULL ) PAD1update(0); + if( PAD2update != NULL ) PAD2update(1); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + + case GS_RINGTYPE_FRAMESKIP: + GSsetFrameSkip(*(int*)(g_pGSRingPos+4)); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE8: + g_MTGSMem[*(int*)(g_pGSRingPos+4)] = *(u8*)(g_pGSRingPos+8); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE16: + *(u16*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u16*)(g_pGSRingPos+8); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE32: + *(u32*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u32*)(g_pGSRingPos+8); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + case GS_RINGTYPE_MEMWRITE64: + *(u64*)(g_MTGSMem+*(int*)(g_pGSRingPos+4)) = *(u64*)(g_pGSRingPos+8); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + + case GS_RINGTYPE_VIFFIFO: + { + u64* pMem; + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + pMem = (u64*)dmaGetAddr(vif1ch->madr); + + if (pMem == NULL) { + psHu32(DMAC_STAT)|= 1<<15; + break; + } + + if( GSreadFIFO2 == NULL ) { + int size; + for (size=(tag>>16); size>0; size--) { + GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, tag>>16); + + // set incase read + psHu64(0x5000) = pMem[2*(tag>>16)-2]; + psHu64(0x5008) = pMem[2*(tag>>16)-1]; + } + + assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) ); + assert( vif1ch->qwc == (tag>>16) ); + + tag = (tag>>16) - (cpuRegs.cycle- *(u32*)(g_pGSRingPos+8)); + if( tag & 0x80000000 ) tag = 0; + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + + INT(1, tag); + InterlockedExchangeAdd((long*)&g_pGSRingPos, 16); + break; + } + + default: + + SysPrintf("GSThreadProc, bad packet writepos: %x g_pGSRingPos: %x, g_pGSWritePos: %x\n", writepos, g_pGSRingPos, g_pGSWritePos); + assert(0); + g_pGSRingPos = g_pGSWritePos; + //flushall(); + } + + assert( g_pGSRingPos <= GS_RINGBUFFEREND ); + if( g_pGSRingPos == GS_RINGBUFFEREND ) + InterlockedExchangePointer((volatile PVOID*)&g_pGSRingPos, GS_RINGBUFFERBASE); + + if( g_pGSRingPos == g_pGSWritePos ) { + break; + } + } +ExitGS: + ; + } while(g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos); + } + + // process vu1 + } + + return 0; +} + +int gsFreeze(gzFile f, int Mode) { + + gzfreeze(PS2MEM_GS, 0x2000); + gzfreeze(&CSRw, sizeof(CSRw)); + gzfreeze(g_path, sizeof(g_path)); + gzfreeze(s_byRegs, sizeof(s_byRegs)); + + return 0; +} + +#ifdef PCSX2_DEVBUILD + +struct GSStatePacket +{ + u32 type; + vector mem; +}; + +// runs the GS +void RunGSState(gzFile f) +{ + u32 newfield; + list< GSStatePacket > packets; + + while(!gzeof(f)) { + int type, size; + gzread(f, &type, sizeof(type)); + + if( type != GSRUN_VSYNC ) gzread(f, &size, 4); + + packets.push_back(GSStatePacket()); + GSStatePacket& p = packets.back(); + + p.type = type; + + if( type != GSRUN_VSYNC ) { + p.mem.resize(size*16); + gzread(f, &p.mem[0], size*16); + } + } + + list::iterator it = packets.begin(); + g_SaveGSStream = 3; + + int skipfirst = 1; + + // first extract the data + while(1) { + + switch(it->type) { + case GSRUN_TRANS1: + GSgifTransfer1((u32*)&it->mem[0], 0); + break; + case GSRUN_TRANS2: + GSgifTransfer2((u32*)&it->mem[0], it->mem.size()/16); + break; + case GSRUN_TRANS3: + GSgifTransfer3((u32*)&it->mem[0], it->mem.size()/16); + break; + case GSRUN_VSYNC: + // flip + newfield = (*(u32*)(PS2MEM_GS+0x1000)&0x2000) ? 0 : 0x2000; + *(u32*)(PS2MEM_GS+0x1000) = (*(u32*)(PS2MEM_GS+0x1000) & ~(1<<13)) | newfield; + + GSvsync(newfield); + SysUpdate(); + + if( g_SaveGSStream != 3 ) + return; + +// if( skipfirst ) { +// ++it; +// it = packets.erase(packets.begin(), it); +// skipfirst = 0; +// } + +// it = packets.begin(); +// continue; + break; + default: + assert(0); + } + + ++it; + if( it == packets.end() ) + it = packets.begin(); + } +} + +#endif + +#undef GIFchain + diff --git a/pcsx2/GS.h b/pcsx2/GS.h new file mode 100644 index 0000000..e15b1fa --- /dev/null +++ b/pcsx2/GS.h @@ -0,0 +1,229 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +typedef struct +{ + u32 SIGID; + u32 LBLID; +} GSRegSIGBLID; + +#define GSPATH3FIX + +#ifdef PCSX2_VIRTUAL_MEM +#define GSCSRr *((u64*)(PS2MEM_GS+0x1000)) +#define GSIMR *((u32*)(PS2MEM_GS+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(PS2MEM_GS+0x1080)) +#else +extern u8 g_RealGSMem[0x2000]; +#define GSCSRr *((u64*)(g_RealGSMem+0x1000)) +#define GSIMR *((u32*)(g_RealGSMem+0x1010)) +#define GSSIGLBLID ((GSRegSIGBLID*)(g_RealGSMem+0x1080)) +#endif + +#define GS_RINGBUFFERBASE (u8*)(0x10200000) +#define GS_RINGBUFFERSIZE 0x00300000 // 3Mb +#define GS_RINGBUFFEREND (u8*)(GS_RINGBUFFERBASE+GS_RINGBUFFERSIZE) + +#define GS_RINGTYPE_RESTART 0 +#define GS_RINGTYPE_P1 1 +#define GS_RINGTYPE_P2 2 +#define GS_RINGTYPE_P3 3 +#define GS_RINGTYPE_VSYNC 4 +#define GS_RINGTYPE_VIFFIFO 5 // GSreadFIFO2 +#define GS_RINGTYPE_FRAMESKIP 6 +#define GS_RINGTYPE_MEMWRITE8 7 +#define GS_RINGTYPE_MEMWRITE16 8 +#define GS_RINGTYPE_MEMWRITE32 9 +#define GS_RINGTYPE_MEMWRITE64 10 + +// if returns NULL, don't copy (memory is preserved) +u8* GSRingBufCopy(void* mem, u32 size, u32 type); +void GSRingBufSimplePacket(int type, int data0, int data1, int data2); + +extern u8* g_pGSWritePos; +#ifdef PCSX2_DEVBUILD + +// use for debugging MTGS +extern FILE* g_fMTGSWrite, *g_fMTGSRead; +extern u32 g_MTGSDebug, g_MTGSId; + +#define MTGS_RECWRITE(start, size) { \ + if( g_MTGSDebug & 1 ) { \ + u32* pstart = (u32*)(start); \ + u32 cursize = (u32)(size); \ + fprintf(g_fMTGSWrite, "*%x-%x (%d)\n", (u32)(uptr)(start), (u32)(size), ++g_MTGSId); \ + /*while(cursize > 0) { \ + fprintf(g_fMTGSWrite, "%x %x %x %x\n", pstart[0], pstart[1], pstart[2], pstart[3]); \ + pstart += 4; \ + cursize -= 16; \ + }*/ \ + if( g_MTGSDebug & 2 ) fflush(g_fMTGSWrite); \ + } \ +} \ + +#define MTGS_RECREAD(start, size) { \ + if( g_MTGSDebug & 1 ) { \ + u32* pstart = (u32*)(start); \ + u32 cursize = (u32)(size); \ + fprintf(g_fMTGSRead, "*%x-%x (%d)\n", (u32)(uptr)(start), (u32)(size), ++g_MTGSId); \ + /*while(cursize > 0) { \ + fprintf(g_fMTGSRead, "%x %x %x %x\n", pstart[0], pstart[1], pstart[2], pstart[3]); \ + pstart += 4; \ + cursize -= 16; \ + }*/ \ + if( g_MTGSDebug & 4 ) fflush(g_fMTGSRead); \ + } \ +} \ + +#else + +#define MTGS_RECWRITE 0&& +#define MTGS_RECREAD 0&& + +#endif + +// mem and size are the ones from GSRingBufCopy +#define GSRINGBUF_DONECOPY(mem, size) { \ + u8* temp = (u8*)(mem) + (size); \ + assert( temp <= GS_RINGBUFFEREND); \ + MTGS_RECWRITE(mem, size); \ + if( temp == GS_RINGBUFFEREND ) temp = GS_RINGBUFFERBASE; \ + InterlockedExchangePointer((void**)&g_pGSWritePos, temp); \ +} + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +#define GS_SETEVENT() SetEvent(g_hGsEvent) +#else +#include +#include +extern sem_t g_semGsThread; +#define GS_SETEVENT() sem_post(&g_semGsThread) +#endif + +u32 GSgifTransferDummy(int path, u32 *pMem, u32 size); + +void gsInit(); +void gsShutdown(); +void gsReset(); + +// used for resetting GIF fifo +void gsGIFReset(); + +void gsWrite8(u32 mem, u8 value); +void gsConstWrite8(u32 mem, int mmreg); + +void gsWrite16(u32 mem, u16 value); +void gsConstWrite16(u32 mem, int mmreg); + +void gsWrite32(u32 mem, u32 value); +void gsConstWrite32(u32 mem, int mmreg); + +void gsWrite64(u32 mem, u64 value); +void gsConstWrite64(u32 mem, int mmreg); + +void gsConstWrite128(u32 mem, int mmreg); + +u8 gsRead8(u32 mem); +int gsConstRead8(u32 x86reg, u32 mem, u32 sign); + +u16 gsRead16(u32 mem); +int gsConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 gsRead32(u32 mem); +int gsConstRead32(u32 x86reg, u32 mem); + +u64 gsRead64(u32 mem); +void gsConstRead64(u32 mem, int mmreg); + +void gsConstRead128(u32 mem, int xmmreg); + +void gsIrq(); +int gsInterrupt(); +void dmaGIF(); +void mfifoGIFtransfer(int qwc); +int gsFreeze(gzFile f, int Mode); +int _GIFchain(); +int gifMFIFOInterrupt(); + +// GS Playback +#define GSRUN_TRANS1 1 +#define GSRUN_TRANS2 2 +#define GSRUN_TRANS3 3 +#define GSRUN_VSYNC 4 + +#ifdef PCSX2_DEVBUILD + +extern int g_SaveGSStream; +extern int g_nLeftGSFrames; +extern gzFile g_fGSSave; + +#define GSGIFTRANSFER1(pMem, addr) { \ + if( g_SaveGSStream == 2) { \ + int type = GSRUN_TRANS1; \ + int size = (0x4000-(addr))/16; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &size, 4); \ + gzwrite(g_fGSSave, ((u8*)pMem)+(addr), size*16); \ + } \ + GSgifTransfer1(pMem, addr); \ +} + +#define GSGIFTRANSFER2(pMem, size) { \ + if( g_SaveGSStream == 2) { \ + int type = GSRUN_TRANS2; \ + int _size = size; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &_size, 4); \ + gzwrite(g_fGSSave, pMem, _size*16); \ + } \ + GSgifTransfer2(pMem, size); \ +} + +#define GSGIFTRANSFER3(pMem, size) { \ + if( g_SaveGSStream == 2 ) { \ + int type = GSRUN_TRANS3; \ + int _size = size; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + gzwrite(g_fGSSave, &_size, 4); \ + gzwrite(g_fGSSave, pMem, _size*16); \ + } \ + GSgifTransfer3(pMem, size); \ +} + +#define GSVSYNC() { \ + if( g_SaveGSStream == 2 ) { \ + int type = GSRUN_VSYNC; \ + gzwrite(g_fGSSave, &type, sizeof(type)); \ + } \ +} \ + +#else + +#define GSGIFTRANSFER1(pMem, size) GSgifTransfer1(pMem, size) +#define GSGIFTRANSFER2(pMem, size) GSgifTransfer2(pMem, size) +#define GSGIFTRANSFER3(pMem, size) GSgifTransfer3(pMem, size) +#define GSVSYNC() + +#endif + +void RunGSState(gzFile f); + +#endif diff --git a/pcsx2/Hw.c b/pcsx2/Hw.c new file mode 100644 index 0000000..64e6054 --- /dev/null +++ b/pcsx2/Hw.c @@ -0,0 +1,1471 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include + +#include "Common.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "PsxMem.h" +#include "IPU/IPU.h" +#include "GS.h" + +#include + +#ifndef PCSX2_VIRTUAL_MEM +u8 *psH; // hw mem +u16 *psHW; +u32 *psHL; +u64 *psHD; +#endif + +int b440 = 0; + +int b440table[] = { + 0, 31, 31, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0, 31, 31, 0, 0, + 31, 31, 0, 0 }; + +int hwInit() { + +#ifndef PCSX2_VIRTUAL_MEM + psH = (u8*)_aligned_malloc(0x00010000, 16); + if (psH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } +#endif + + b440 = 0; + gsInit(); + vif0Init(); + vif1Init(); + vifDmaInit(); + sifInit(); + sprInit(); + ipuInit(); + + return 0; +} + +void hwShutdown() { +#ifndef PCSX2_VIRTUAL_MEM + if (psH == NULL) return; + _aligned_free(psH); psH = NULL; +#endif + ipuShutdown(); +} + +void hwReset() +{ + memset(PS2MEM_HW+0x2000, 0, 0x0000e000); + + psHu32(0xf520) = 0x1201; + psHu32(0xf260) = 0x1D000060; + // i guess this is kinda a version, it's used by some bioses + psHu32(0xf590) = 0x1201; + + gsReset(); + ipuReset(); +} + +u8 hwRead8(u32 mem) +{ + u8 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(mem)); +#endif + + switch (mem) { + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem); + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u8)ret; + } + + if (mem < 0x10010000) + { + ret = psHu8(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 8 at %x\n",mem); +#endif + break; + } + + return ret; +} + +u16 hwRead16(u32 mem) +{ + u16 ret; + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif + +#ifdef SPR_LOG + SPR_LOG("Hardware read 16bit at %lx, ret %lx\n", mem, psHu16(mem)); +#endif + switch (mem) { + case 0x10000000: ret = (u16)rcntRcount(0); break; + case 0x10000010: ret = (u16)counters[0].mode; break; + case 0x10000020: ret = (u16)counters[0].target; break; + case 0x10000030: ret = (u16)counters[0].hold; break; + + case 0x10000800: ret = (u16)rcntRcount(1); break; + case 0x10000810: ret = (u16)counters[1].mode; break; + case 0x10000820: ret = (u16)counters[1].target; break; + case 0x10000830: ret = (u16)counters[1].hold; break; + + case 0x10001000: ret = (u16)rcntRcount(2); break; + case 0x10001010: ret = (u16)counters[2].mode; break; + case 0x10001020: ret = (u16)counters[2].target; break; + + case 0x10001800: ret = (u16)rcntRcount(3); break; + case 0x10001810: ret = (u16)counters[3].mode; break; + case 0x10001820: ret = (u16)counters[3].target; break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu16(mem) | 0x0102; + psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); + return (u16)ret; + } + if (mem < 0x10010000) { + ret = psHu16(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 16 at %x\n",mem); +#endif + break; + } + + return ret; +} + +u32 hwRead32(u32 mem) { + u32 ret; + +#ifdef SPR_LOG + SPR_LOG("Hardware read 32bit at %lx, ret %lx\n", mem, psHu32(mem)); +#endif + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead32(mem); + } + + // gauntlen uses 0x1001xxxx + switch (mem) { + case 0x10000000: return (u16)rcntRcount(0); + case 0x10000010: return (u16)counters[0].mode; + case 0x10000020: return (u16)counters[0].target; + case 0x10000030: return (u16)counters[0].hold; + + case 0x10000800: return (u16)rcntRcount(1); + case 0x10000810: return (u16)counters[1].mode; + case 0x10000820: return (u16)counters[1].target; + case 0x10000830: return (u16)counters[1].hold; + + case 0x10001000: return (u16)rcntRcount(2); + case 0x10001010: return (u16)counters[2].mode; + case 0x10001020: return (u16)counters[2].target; + + case 0x10001800: return (u16)rcntRcount(3); + case 0x10001810: return (u16)counters[3].mode; + case 0x10001820: return (u16)counters[3].target; + +#ifdef PCSX2_DEVBUILD + case 0x1000A000: + ret = psHu32(mem);//dma2 chcr + HW_LOG("Hardware read DMA2_CHCR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A010: + ret = psHu32(mem);//dma2 madr + HW_LOG("Hardware read DMA2_MADR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A020: + ret = psHu32(mem);//dma2 qwc + HW_LOG("Hardware readDMA2_QWC 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A030: + ret = psHu32(mem);//dma2 taddr + HW_LOG("Hardware read DMA2_TADDR 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A040: + ret = psHu32(mem);//dma2 asr0 + HW_LOG("Hardware read DMA2_ASR0 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A050: + ret = psHu32(mem);//dma2 asr1 + HW_LOG("Hardware read DMA2_ASR1 32bit at %lx, ret %lx\n", mem, ret); + break; + case 0x1000A080: + ret = psHu32(mem);//dma2 saddr + HW_LOG("Hardware read DMA2_SADDR 32 at %lx, ret %lx\n", mem, ret); + break; + case 0x1000B400: // dma4 chcr + ret = ((DMACh *)&PS2MEM_HW[0xb400])->chcr; + SPR_LOG("Hardware read IPU1_CHCR 32 at %lx, ret %x\n", mem, ret); + break; + + case 0x1000e010: // DMAC_STAT + HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); + return psHu32(0xe010); + case 0x1000f000: // INTC_STAT +// HW_LOG("INTC_STAT Read 32bit %x\n", psHu32(0xf000)); + return psHu32(0xf000); + case 0x1000f010: // INTC_MASK + HW_LOG("INTC_MASK Read 32bit %x\n", psHu32(0xf010)); + return psHu32(0xf010); +#endif + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + ret = 0; + break; + + case 0x1000f440: + + b440++; + switch (b440) { + case 3: case 6: case 9: case 10: + case 13: case 14: + case 17: case 18: + case 21: case 22: + case 25: case 26: + case 29: case 30: + ret = 0; break; + default: + ret = 0x1f; break; + } + break; + + case 0x1000f520: // DMAC_ENABLER +#ifdef HW_LOG + HW_LOG("DMAC_ENABLER Read 32bit %lx\n", psHu32(0xf590)); +#endif + return psHu32(0xf590); + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + // SIF Control Registers + /*1D000020 (word) - EE -> IOP status flag ( set to 0x10000 always ready ) + 1D000030 (word) - IOP -> EE status flag + 1D000040 (word) - See psxMem.c ( Initially set to 0xF00042 and reset to + to this value if 0x20 is written ) + 1D000060 (word) - used to detect whether the SIF interface exists + read must be 0x1D000060, or the top 20 bits must be zero + */ + // note, any changes you make in here, also make on recMemRead32 + if(mem ==0x1000f260) ret = 0; + else if(mem == 0x1000F240) { + ret = psHu32(mem) | 0xF0000102; + //psHu32(mem) &= ~0x4000; + } + else ret = psHu32(mem); +//#ifdef HW_LOG +// SysPrintf("sif %x(%x) Read 32bit %x\n", mem, 0xbd000000 | (mem & 0xf0),ret); +//#endif } + break; + + } + else if (mem < 0x10010000) { + ret = psHu32(mem); + } + else { + SysPrintf("32bit HW read of address 0x%x\n", mem); + ret = 0; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 32 at %lx, ret %lx\n", mem, ret); +#endif + break; + } + + return ret; +} + +u64 hwRead64(u32 mem) { + u64 ret; + + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuRead64(mem); + } + + switch (mem) { + default: + if (mem < 0x10010000) { + ret = psHu64(mem); + } + else ret = 0; +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 64 at %x\n",mem); +#endif + break; + } + + return ret; +} + +void hwRead128(u32 mem, u64 *out) { + if (mem >= 0x10004000 && mem < 0x10008000) { + ReadFIFO(mem, out); return; + } + + if (mem < 0x10010000) { + out[0] = psHu64(mem); + out[1] = psHu64(mem+8); + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware Read 128 at %x\n",mem); +#endif +} + +// dark cloud2 uses it +#define DmaExec8(name, num) { \ + psHu8(mem) = (u8)value; \ + if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { \ + /*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/ \ + dma##name(); \ + } \ +} + +char sio_buffer[1024]; +int sio_count; + +void hwWrite8(u32 mem, u8 value) { + +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite8 to %x\n", mem); +#endif + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, (counters[0].mode & 0xff00) | value); break; + case 0x10000011: rcntWmode(0, (counters[0].mode & 0xff) | value << 8); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, (counters[1].mode & 0xff00) | value); break; + case 0x10000811: rcntWmode(1, (counters[1].mode & 0xff) | value << 8); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, (counters[2].mode & 0xff00) | value); break; + case 0x10001011: rcntWmode(2, (counters[2].mode & 0xff) | value << 8); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, (counters[3].mode & 0xff00) | value); break; + case 0x10001811: rcntWmode(3, (counters[3].mode & 0xff) | value << 8); break; + case 0x10001820: rcntWtarget(3, value); break; + + case 0x1000f180: + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +// SysPrintf("%c", value); + break; + + case 0x10008001: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 +#ifdef DMA_LOG + DMA_LOG("VIF1dma %lx\n", value); +#endif + DmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value); +#endif + DmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma8 %lx\n", value); +#endif + DmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + psHu8(0xf592) = value; + psHu8(0xf522) = value; + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu8(mem) = value; + break; + case 0x40: + if(!(value & 0x100)) psHu32(mem) &= ~0x100; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + psHu8(mem) = value; + } +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value); +#endif + break; + } +} + +#define DmaExec16(name, num) { \ + psHu16(mem) = (u16)value; \ + if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + SysPrintf("16bit DMA Start\n"); \ + dma##name(); \ + } \ +} + +void hwWrite16(u32 mem, u16 value) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwWrite16 to %x\n", mem); +#endif + switch(mem) { + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec16(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec16(VIF1, 1); + break; + +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec16(GIF, 2); + break; +#ifdef HW_LOG + + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec16(IPU0, 3); + break; + +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec16(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec16(SIF0, 5); + break; + + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec16(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec16(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + psHu16(0xf592) = value; + psHu16(0xf522) = value; + break; + case 0x1000f130: + case 0x1000f132: + case 0x1000f410: + case 0x1000f412: + case 0x1000f430: + case 0x1000f432: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + psHu16(mem) = value; + break; + case 0x20: + psHu16(mem) |= value; + break; + case 0x30: + psHu16(mem) &= ~value; + break; + case 0x40: + assert( (mem&2)==0); + if(!(value & 0x100)) psHu16(mem) &= ~0x100; + else psHu16(mem) |= 0x100; + break; + case 0x60: + psHu16(mem) = 0; + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + +#ifndef PCSX2_VIRTUAL_MEM + if (mem < 0x10010000) +#endif + { + psHu16(mem) = value; + } + } + +#ifdef HW_LOG + HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value); +#endif +} + +#define DmaExec(name, num) { \ + /* why not allowing tags on sif0/sif2? */ \ + if(mem!= 0x1000c000 && mem != 0x1000c400 && mem != 0x1000c800) \ + psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; \ + else \ + psHu32(mem) = (u32)value; \ + if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ + dma##name(); \ + } \ +} + +void hwWrite32(u32 mem, u32 value) { + int i; + + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuWrite32(mem,value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case 0x10000000: rcntWcount(0, value); break; + case 0x10000010: rcntWmode(0, value); break; + case 0x10000020: rcntWtarget(0, value); break; + case 0x10000030: rcntWhold(0, value); break; + + case 0x10000800: rcntWcount(1, value); break; + case 0x10000810: rcntWmode(1, value); break; + case 0x10000820: rcntWtarget(1, value); break; + case 0x10000830: rcntWhold(1, value); break; + + case 0x10001000: rcntWcount(2, value); break; + case 0x10001010: rcntWmode(2, value); break; + case 0x10001020: rcntWtarget(2, value); break; + + case 0x10001800: rcntWcount(3, value); break; + case 0x10001810: rcntWmode(3, value); break; + case 0x10001820: rcntWtarget(3, value); break; + + case GIF_CTRL: + //SysPrintf("GIF_CTRL write %x\n", value); + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + return; + + case GIF_MODE: + // need to set GIF_MODE (hamster ball) +#ifdef GSPATH3FIX + SysPrintf("GIFMODE %x\n", value); +#endif + psHu32(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + SysPrintf("Gifstat write value = %x\n", value); + return; + + case 0x10008000: // dma0 - vif0 +#ifdef DMA_LOG + DMA_LOG("VIF0dma %lx\n", value); +#endif + DmaExec(VIF0, 0); + break; + +// Latest Fix for Florin by asadr (VIF1) + case 0x10009000: // dma1 - vif1 - chcr +#ifdef DMA_LOG + DMA_LOG("VIF1dma CHCR %lx\n", value); +#endif + DmaExec(VIF1, 1); + break; +#ifdef HW_LOG + case 0x10009010: // dma1 - vif1 - madr + HW_LOG("VIF1dma Madr %lx\n", value); + psHu32(mem) = value;//dma1 madr + break; + case 0x10009020: // dma1 - vif1 - qwc + HW_LOG("VIF1dma QWC %lx\n", value); + psHu32(mem) = value;//dma1 qwc + break; + case 0x10009030: // dma1 - vif1 - tadr + HW_LOG("VIF1dma TADR %lx\n", value); + psHu32(mem) = value;//dma1 tadr + break; + case 0x10009040: // dma1 - vif1 - asr0 + HW_LOG("VIF1dma ASR0 %lx\n", value); + psHu32(mem) = value;//dma1 asr0 + break; + case 0x10009050: // dma1 - vif1 - asr1 + HW_LOG("VIF1dma ASR1 %lx\n", value); + psHu32(mem) = value;//dma1 asr1 + break; + case 0x10009080: // dma1 - vif1 - sadr + HW_LOG("VIF1dma SADR %lx\n", value); + psHu32(mem) = value;//dma1 sadr + break; +#endif +// --------------------------------------------------- + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; +#ifdef HW_LOG + case 0x1000a010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a020: + psHu32(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a030: + psHu32(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a040: + psHu32(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a050: + psHu32(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); + break; + case 0x1000a080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b000: // dma3 - fromIPU +#ifdef DMA_LOG + DMA_LOG("IPU0dma %lx\n", value); +#endif + DmaExec(IPU0, 3); + break; +#ifdef HW_LOG + case 0x1000b010: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b020: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b030: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b080: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + case 0x1000b400: // dma4 - toIPU +#ifdef DMA_LOG + DMA_LOG("IPU1dma %lx\n", value); +#endif + DmaExec(IPU1, 4); + break; +#ifdef HW_LOG + case 0x1000b410: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b420: + psHu32(mem) = value;//dma2 madr + HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b430: + psHu32(mem) = value;//dma2 tadr + HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); + break; + case 0x1000b480: + psHu32(mem) = value;//dma2 saddr + HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); + break; +#endif + + case 0x1000c000: // dma5 - sif0 +#ifdef DMA_LOG + DMA_LOG("SIF0dma %lx\n", value); +#endif +// if (value == 0) psxSu32(0x30) = 0x40000; + DmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 +#ifdef DMA_LOG + DMA_LOG("SIF1dma %lx\n", value); +#endif + DmaExec(SIF1, 6); + break; + +#ifdef HW_LOG + case 0x1000c420: // dma6 - sif1 - qwc + HW_LOG("SIF1dma QWC = %lx\n", value); + psHu32(mem) = value; + break; +#endif + +#ifdef HW_LOG + case 0x1000c430: // dma6 - sif1 - tadr + HW_LOG("SIF1dma TADR = %lx\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000c800: // dma7 - sif2 +#ifdef DMA_LOG + DMA_LOG("SIF2dma %lx\n", value); +#endif + DmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR +#ifdef DMA_LOG + DMA_LOG("fromSPRdma %lx\n", value); +#endif + DmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR +#ifdef DMA_LOG + DMA_LOG("toSPRdma %lx\n", value); +#endif + DmaExec(SPR1, 9); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 32bit %x\n", value); + psHu32(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 32bit %x\n", value); +#endif + psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 + value = value >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (value & (1<=0x10002000) && (mem<=0x10002030)) { + ipuWrite64(mem, value); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + vif0Write32(mem, value); return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + vif1Write32(mem, value); return; + } + + switch (mem) { + case GIF_CTRL: +#ifdef PCSX2_DEVBUILD + SysPrintf("GIF_CTRL write 64\n", value); +#endif + psHu32(mem) = value & 0x8; + if(value & 0x1) { + gsGIFReset(); + //gsReset(); + } + else { + if( value & 8 ) psHu32(GIF_STAT) |= 8; + else psHu32(GIF_STAT) &= ~8; + } + + return; + + case GIF_MODE: +#ifdef GSPATH3FIX + SysPrintf("GIFMODE64 %x\n", value); +#endif + psHu64(GIF_MODE) = value; + if (value & 0x1) psHu32(GIF_STAT)|= 0x1; + else psHu32(GIF_STAT)&= ~0x1; + if (value & 0x4) psHu32(GIF_STAT)|= 0x4; + else psHu32(GIF_STAT)&= ~0x4; + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif +#ifdef DMA_LOG + DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value); +#endif + DmaExec(GIF, 2); + break; + +#ifdef HW_LOG + case 0x1000e000: // DMAC_CTRL + HW_LOG("DMAC_CTRL Write 64bit %x\n", value); + psHu64(mem) = value; + break; +#endif + + case 0x1000e010: // DMAC_STAT +#ifdef HW_LOG + HW_LOG("DMAC_STAT Write 64bit %x\n", value); +#endif + val32 = (u32)value; + psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 + val32 = val32 >> 16; + for (i=0; i<16; i++) { // reverse on 1 + if (val32 & (1<= 0x10004000 && mem < 0x10008000) { + WriteFIFO(mem, value); return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + psHu32(0xf590) = *(u32*)value; + psHu32(0xf520) = *(u32*)value; + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + + psHu64(mem ) = value[0]; + psHu64(mem+8) = value[1]; + +#ifdef PCSX2_DEVBUILD + HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status); +#endif + break; + } +} + +int intcInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu32(INTC_STAT)) == 0) { + SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); + return 1; + } + if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("intcInterrupt %x\n", psHu32(INTC_STAT) & psHu32(INTC_MASK)); +#endif + if(psHu32(INTC_STAT) & 0x2){ + counters[0].hold = rcntRcount(0); + counters[1].hold = rcntRcount(1); + } + + cpuException(0x400, cpuRegs.branch); + + return 1; +} + +int dmacTestInterrupt() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + return 1; +} + +int dmacInterrupt() +{ +if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; + + if ((psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) == 0) return 0; + + if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; + +#ifdef HW_LOG + HW_LOG("dmacInterrupt %x\n", (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)); +#endif + + cpuException(0x800, cpuRegs.branch); + return 1; +} + +void hwIntcIrq(int n) { + //if( psHu32(INTC_MASK) & (1<= (maddr+msize)) { + int s1 = (maddr+msize) - addr; + int s2 = size - s1; + + /* it does, so first copy 's1' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, s1/4); + memcpy_fast(dst, data, s1); + + /* and second copy 's2' bytes from '&data[s1]' to 'maddr' */ + dst = PSM(maddr); + if (dst == NULL) return -1; + Cpu->Clear(maddr, s2/4); + memcpy_fast(dst, &data[s1], s2); + } else { + //u32 * tempptr, * tempptr2; + + /* it doesn't, so just copy 'size' bytes from 'data' to 'addr' */ + dst = PSM(addr); + if (dst == NULL) return -1; + Cpu->Clear(addr, size/4); + memcpy_fast(dst, data, size); + } + + return 0; +} + + +int hwDmacSrcChainWithStack(DMACh *dma, int id) { + u32 temp,finalAddress; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 5: // Call - Transfer QWC following the tag, save succeeding tag + temp = dma->madr; //Temporarily Store ADDR + finalAddress = dma->tadr + 16 + (dma->qwc << 4); //Store Address of Succeeding tag + + if ((dma->chcr & 0x30) == 0x0) { //Check if ASR0 is empty + dma->asr0 = finalAddress; //If yes store Succeeding tag + dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address in call stack + }else if((dma->chcr & 0x30) == 0x10){ + dma->chcr = (dma->chcr & 0xffffffcf) | 0x20; //2 Addresses in call stack + dma->asr1 = finalAddress; //If no store Succeeding tag in ASR1 + }else { + SysPrintf("Call Stack Overflow (report if it fixes/breaks anything)\n"); + return 1; //Return done + } + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + dma->tadr = temp; //Set TADR to temporarily stored ADDR + return 0; + + case 6: // Ret - Transfer QWC following the tag, load next tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + if ((dma->chcr & 0x30) == 0x20) { //If ASR1 is NOT equal to 0 (Contains address) + dma->chcr = (dma->chcr & 0xffffffcf) | 0x10; //1 Address left in call stack + dma->tadr = dma->asr1; //Read ASR1 as next tag + dma->asr1 = 0; //Clear ASR1 + } else { //If ASR1 is empty (No address held) + if((dma->chcr & 0x30) == 0x10) { //Check if ASR0 is NOT equal to 0 (Contains address) + dma->chcr = (dma->chcr & 0xffffffcf); //No addresses left in call stack + dma->tadr = dma->asr0; //Read ASR0 as next tag + dma->asr0 = 0; //Clear ASR0 + } else { //Else if ASR1 and ASR0 are empty + //dma->tadr += 16; //Clear tag address - Kills Klonoa 2 + return 1; //End Transfer + } + } + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //comment out tadr fixes lemans + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} + +int hwDmacSrcChain(DMACh *dma, int id) { + u32 temp; + + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + dma->tadr += 16; + return 1; //End Transfer + + case 1: // CNT - Transfer QWC following the tag. + dma->madr = dma->tadr + 16; //Set MADR to QW after Tag + dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 0; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = dma->madr; //Temporarily Store ADDR + dma->madr = dma->tadr + 16; //Set MADR to QW following the tag + dma->tadr = temp; //Copy temporarily stored ADDR to Tag + return 0; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + dma->tadr += 16; //Set TADR to next tag + return 0; + + case 7: // End - Transfer QWC following the tag + dma->madr = dma->tadr + 16; //Set MADR to data following the tag + //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data + return 1; //End Transfer + } + + return -1; +} diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h new file mode 100644 index 0000000..8a7f244 --- /dev/null +++ b/pcsx2/Hw.h @@ -0,0 +1,419 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __HW_H__ +#define __HW_H__ + +#include "PS2Etypes.h" +#include + +#ifndef PCSX2_VIRTUAL_MEM +extern u8 *psH; // hw mem +extern u16 *psHW; +extern u32 *psHL; +extern u64 *psHD; +#endif + +#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff]) +#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff]) + +extern u32 g_nextBranchCycle; + +#define INT(n, ecycle) { \ + g_nextBranchCycle = min(g_nextBranchCycle, cpuRegs.cycle+ecycle); \ + cpuRegs.interrupt|= 1 << n; \ + cpuRegs.sCycle[n] = cpuRegs.cycle; \ + cpuRegs.eCycle[n] = ecycle; \ +} + +// VIF0 -- 0x10004000 -- psH[0x4000] +// VIF1 -- 0x10005000 -- psH[0x5000] +// GIF -- 0x10006000 -- psH[0x6000] +// IPUout -- 0x10007000 -- psH[0x7000] +// IPUin -- 0x10007010 -- psH[0x7010] + +void ReadFIFO(u32 mem, u64 *out); +void ConstReadFIFO(u32 mem); + +void WriteFIFO(u32 mem, u64 *value); +void ConstWriteFIFO(u32 mem); + + +// +// --- DMA --- +// + +typedef struct { + u32 chcr; + u32 null0[3]; + u32 madr; + u32 null1[3]; + u16 qwc; u16 pad; + u32 null2[3]; + u32 tadr; + u32 null3[3]; + u32 asr0; + u32 null4[3]; + u32 asr1; + u32 null5[11]; + u32 sadr; +} DMACh; + +// HW defines + +#define RCNT0_COUNT 0x10000000 +#define RCNT0_MODE 0x10000010 +#define RCNT0_TARGET 0x10000020 +#define RCNT0_HOLD 0x10000030 + +#define RCNT1_COUNT 0x10000800 +#define RCNT1_MODE 0x10000810 +#define RCNT1_TARGET 0x10000820 +#define RCNT1_HOLD 0x10000830 + +#define RCNT2_COUNT 0x10001000 +#define RCNT2_MODE 0x10001010 +#define RCNT2_TARGET 0x10001020 + +#define RCNT3_COUNT 0x10001800 +#define RCNT3_MODE 0x10001810 +#define RCNT3_TARGET 0x10001820 + +#define IPU_CMD 0x10002000 +#define IPU_CTRL 0x10002010 +#define IPU_BP 0x10002020 +#define IPU_TOP 0x10002030 + +#define GIF_CTRL 0x10003000 +#define GIF_MODE 0x10003010 +#define GIF_STAT 0x10003020 +#define GIF_TAG0 0x10003040 +#define GIF_TAG1 0x10003050 +#define GIF_TAG2 0x10003060 +#define GIF_TAG3 0x10003070 +#define GIF_CNT 0x10003080 +#define GIF_P3CNT 0x10003090 +#define GIF_P3TAG 0x100030A0 + +#define GIF_FIFO 0x10006000 + +#define IPUout_FIFO 0x10007000 +#define IPUin_FIFO 0x10007010 + +//VIF0 +#define D0_CHCR 0x10008000 +#define D0_MADR 0x10008010 +#define D0_QWC 0x10008020 + +//VIF1 +#define D1_CHCR 0x10009000 +#define D1_MADR 0x10009010 +#define D1_QWC 0x10009020 +#define D1_TADR 0x10009030 + +//GS +#define D2_CHCR 0x1000A000 +#define D2_MADR 0x1000A010 +#define D2_QWC 0x1000A020 +#define D2_TADR 0x1000A030 + +//fromIPU +#define D3_CHCR 0x1000B000 +#define D3_MADR 0x1000B010 +#define D3_QWC 0x1000B020 + +//toIPU +#define D4_CHCR 0x1000B400 +#define D4_MADR 0x1000B410 +#define D4_QWC 0x1000B420 +#define D4_TADR 0x1000B430 + +//SIF0 +#define D5_CHCR 0x1000C000 +#define D5_MADR 0x1000C010 +#define D5_QWC 0x1000C020 + +//SIF1 +#define D6_CHCR 0x1000C400 +#define D6_MADR 0x1000C410 +#define D6_QWC 0x1000C420 + +//SIF2 +#define D7_CHCR 0x1000C800 +#define D7_MADR 0x1000C810 +#define D7_QWC 0x1000C820 + +//fromSPR +#define D8_CHCR 0x1000D000 +#define D8_MADR 0x1000D010 +#define D8_QWC 0x1000D020 +#define D8_SADR 0x1000D080 + + +#define DMAC_CTRL 0x1000E000 +#define DMAC_STAT 0x1000E010 +#define DMAC_PCR 0x1000E020 +#define DMAC_SQWC 0x1000E030 +#define DMAC_RBSR 0x1000E040 +#define DMAC_RBOR 0x1000E050 +#define DMAC_STADR 0x1000E060 + +#define INTC_STAT 0x1000F000 +#define INTC_MASK 0x1000F010 + +#define SBUS_F220 0x1000F220 +#define SBUS_SMFLG 0x1000F230 +#define SBUS_F240 0x1000F240 + +#define DMAC_ENABLER 0x1000F520 +#define DMAC_ENABLEW 0x1000F590 + +#define SBFLG_IOPALIVE 0x10000 +#define SBFLG_IOPSYNC 0x40000 + +#define GS_PMODE 0x12000000 +#define GS_SMODE1 0x12000010 +#define GS_SMODE2 0x12000020 +#define GS_SRFSH 0x12000030 +#define GS_SYNCH1 0x12000040 +#define GS_SYNCH2 0x12000050 +#define GS_SYNCV 0x12000060 +#define GS_DISPFB1 0x12000070 +#define GS_DISPLAY1 0x12000080 +#define GS_DISPFB2 0x12000090 +#define GS_DISPLAY2 0x120000A0 +#define GS_EXTBUF 0x120000B0 +#define GS_EXTDATA 0x120000C0 +#define GS_EXTWRITE 0x120000D0 +#define GS_BGCOLOR 0x120000E0 +#define GS_CSR 0x12001000 +#define GS_IMR 0x12001010 +#define GS_BUSDIR 0x12001040 +#define GS_SIGLBLID 0x12001080 + +#define INTC_GS 0 +#define INTC_SBUS 1 +#define INTC_VBLANK_S 2 +#define INTC_VBLANK_E 3 +#define INTC_VIF0 4 +#define INTC_VIF1 5 +#define INTC_VU0 6 +#define INTC_VU1 7 +#define INTC_IPU 8 +#define INTC_TIM0 9 +#define INTC_TIM1 10 +#define INTC_TIM2 11 +#define INTC_TIM3 12 + +#define DMAC_STAT_SIS (1<<13) // stall condition +#define DMAC_STAT_MEIS (1<<14) // mfifo empty +#define DMAC_STAT_BEIS (1<<15) // bus error +#define DMAC_STAT_SIM (1<<29) // stall mask +#define DMAC_STAT_MEIM (1<<30) // mfifo mask + +#define DMAC_VIF0 0 +#define DMAC_VIF1 1 +#define DMAC_GIF 2 +#define DMAC_FROM_IPU 3 +#define DMAC_TO_IPU 4 +#define DMAC_SIF0 5 +#define DMAC_SIF1 6 +#define DMAC_SIF2 7 +#define DMAC_FROM_SPR 8 +#define DMAC_TO_SPR 9 +#define DMAC_ERROR 15 + +#define VIF0_STAT_VPS_W (1) +#define VIF0_STAT_VPS_D (2) +#define VIF0_STAT_VPS_T (3) +#define VIF0_STAT_VPS (3) +#define VIF0_STAT_VEW (1<<2) +#define VIF0_STAT_MRK (1<<6) +#define VIF0_STAT_DBF (1<<7) +#define VIF0_STAT_VSS (1<<8) +#define VIF0_STAT_VFS (1<<9) +#define VIF0_STAT_VIS (1<<10) +#define VIF0_STAT_INT (1<<11) +#define VIF0_STAT_ER0 (1<<12) +#define VIF0_STAT_ER1 (1<<13) + +#define VIF1_STAT_VPS_W (1) +#define VIF1_STAT_VPS_D (2) +#define VIF1_STAT_VPS_T (3) +#define VIF1_STAT_VPS (3) +#define VIF1_STAT_VEW (1<<2) +#define VIF1_STAT_VGW (1<<3) +#define VIF1_STAT_MRK (1<<6) +#define VIF1_STAT_DBF (1<<7) +#define VIF1_STAT_VSS (1<<8) +#define VIF1_STAT_VFS (1<<9) +#define VIF1_STAT_VIS (1<<10) +#define VIF1_STAT_INT (1<<11) +#define VIF1_STAT_ER0 (1<<12) +#define VIF1_STAT_ER1 (1<<13) +#define VIF1_STAT_FDR (1<<23) + +//DMA interrupts & masks +#define BEISintr (0x8000) +#define VIF0intr (0x10001) +#define VIF1intr (0x20002) +#define GIFintr (0x40004) +#define IPU0intr (0x80008) +#define IPU1intr (0x100010) +#define SIF0intr (0x200020) +#define SIF1intr (0x400040) +#define SIF2intr (0x800080) +#define SPR0intr (0x1000100) +#define SPR1intr (0x2000200) +#define SISintr (0x20002000) +#define MEISintr (0x40004000) + +#define DMAend(dma, num) { \ + dma->chcr &= ~0x100; \ + psHu32(DMAC_STAT)|= 1<>12 ].aPFNs == NULL ) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", mem); + return NULL; + } +#endif + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); +#endif + + return p; +} + +#else + +extern u8 *psS; //0.015 mb, scratch pad +extern uptr *memLUTR; + +extern __forceinline void *dmaGetAddr(u32 addr) { + u8 *ptr; + +/*#ifdef DMA_LOG + if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x\n", addr); } +#endif*/ + if (addr & 0x80000000) { // teh sux why the f00k 0xE0000000 + return (void*)&psS[addr & 0x3ff0]; + } + + ptr = (u8*)memLUTR[addr >> 12]; + if (ptr == NULL) { + SysPrintf("*PCSX2*: DMA error: %8.8x\n", addr); + return NULL; + } + return (void*)(ptr + (addr & 0xff0)); +} + +#endif + +int hwInit(); +void hwReset(); +void hwShutdown(); + +// hw read functions +u8 hwRead8 (u32 mem); +int hwConstRead8 (u32 x86reg, u32 mem, u32 sign); + +u16 hwRead16(u32 mem); +int hwConstRead16(u32 x86reg, u32 mem, u32 sign); + +u32 hwRead32(u32 mem); +int hwConstRead32(u32 x86reg, u32 mem); + +u64 hwRead64(u32 mem); +void hwConstRead64(u32 mem, int mmreg); + +void hwRead128(u32 mem, u64 *out); +void hwConstRead128(u32 mem, int xmmreg); + +// hw write functions +void hwWrite8 (u32 mem, u8 value); +void hwConstWrite8 (u32 mem, int mmreg); + +void hwWrite16(u32 mem, u16 value); +void hwConstWrite16(u32 mem, int mmreg); + +void hwWrite32(u32 mem, u32 value); +void hwConstWrite32(u32 mem, int mmreg); + +void hwWrite64(u32 mem, u64 value); +void hwConstWrite64(u32 mem, int mmreg); + +void hwWrite128(u32 mem, u64 *value); +void hwConstWrite128(u32 mem, int xmmreg); + +void hwIntcIrq(int n); +void hwDmacIrq(int n); + +int hwMFIFORead(u32 addr, u8 *data, int size); +int hwMFIFOWrite(u32 addr, u8 *data, int size); + +int hwDmacSrcChainWithStack(DMACh *dma, int id); +int hwDmacSrcChain(DMACh *dma, int id); + +int intcInterrupt(); +int dmacInterrupt(); + +#endif /* __HW_H__ */ diff --git a/pcsx2/IPU/IPU.c b/pcsx2/IPU/IPU.c new file mode 100644 index 0000000..1a41495 --- /dev/null +++ b/pcsx2/IPU/IPU.c @@ -0,0 +1,2007 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "IPU.h" +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +#include +#include + +#include "iR5900.h" +#include "coroutine.h" + +#ifdef _WIN32 +#define FASTCALL __fastcall +#else +#define FASTCALL +#endif + +#ifndef PCSX2_VIRTUAL_MEM +IPUregisters g_ipuRegsReal; +#endif + +#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000]) +#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400]) + +#define IPU_DMA_GIFSTALL 1 +#define IPU_DMA_TIE0 2 +#define IPU_DMA_TIE1 4 +#define IPU_DMA_ACTV1 8 +#define IPU_DMA_DOTIE1 16 +#define IPU_DMA_FIREINT0 32 +#define IPU_DMA_FIREINT1 64 +#define IPU_DMA_VIFSTALL 128 + +static int g_nDMATransfer = 0; +int g_nIPU0Data = 0; // data left to transfer +u8* g_pIPU0Pointer = NULL; +int g_nCmdPos[2] = {0}, g_nCmdIndex = 0; +int ipuCurCmd = 0xffffffff; + +// returns number of qw read +int FIFOfrom_write(u32 * value, int size); +void FIFOfrom_read(void *value,int size); +int FIFOto_read(void *value); +int FIFOto_write(u32* pMem, int size); +void FIFOto_clear(); + +int FOreadpos = 0, FOwritepos = 0; +static int FIreadpos = 0, FIwritepos = 0; +PCSX2_ALIGNED16(u32 fifo_input[32]); +PCSX2_ALIGNED16(u32 fifo_output[32]); + +void ReorderBitstream(); +u16 FillInternalBuffer(u32 * pointer, u32 advance); + +// the BP doesn't advance and returns -1 if there is no data to be read +tIPU_BP g_BP; +static coroutine_t s_routine; // used for executing BDEC/IDEC +static int s_RoutineDone = 0; +static u32 s_tempstack[0x4000]; // 64k + +void IPUCMD_WRITE(u32 val); +void IPUWorker(); +int IPU0dma(); +int IPU1dma(); + +// Color conversion stuff, the memory layout is a total hack +// convert_data_buffer is a pointer to the internal rgb struct (the first param in convert_init_t) +//char convert_data_buffer[sizeof(convert_rgb_t)]; +#ifdef __x86_64__ +char convert_data_buffer[0x24]; +#else +char convert_data_buffer[0x1C]; +#endif +convert_init_t convert_init={convert_data_buffer, sizeof(convert_data_buffer)}; +convert_t *convert; + +// Quantization matrix +static u8 niq[64], //non-intraquant matrix + iq[64]; //intraquant matrix +u16 vqclut[16]; //clut conversion table +static u8 s_thresh[2]; //thresholds for color conversions +int coded_block_pattern=0; +PCSX2_ALIGNED16(struct macroblock_8 mb8); +PCSX2_ALIGNED16(struct macroblock_16 mb16); +PCSX2_ALIGNED16(struct macroblock_rgb32 rgb32); +PCSX2_ALIGNED16(struct macroblock_rgb16 rgb16); + +u8 indx4[16*16/2]; +u32 mpeg2_inited; //mpeg2_idct_init() must be called only once +u8 PCT[]={'r', 'I', 'P', 'B', 'D', '-', '-', '-'}; +decoder_t g_decoder; //static, only to place it in bss +decoder_t tempdec; + +extern u8 mpeg2_scan_norm[64]; +extern u8 mpeg2_scan_alt[64]; + +PCSX2_ALIGNED16(u8 _readbits[80]); //local buffer (ring buffer) +u8* readbits = _readbits; // always can decrement by one 1qw + +#define SATURATE_4BITS(val) ((val)>15 ? 15 : (val)) + +void IPUProcessInterrupt() +{ + if( ipuRegs->ctrl.BUSY ) { + IPUWorker(); + } +} + +///////////////////////////////////////////////////////// +// Register accesses (run on EE thread) +int ipuInit() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + memset(&g_BP, 0, sizeof(g_BP)); + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + return 0; +} + +void ipuReset() +{ + memset(ipuRegs, 0, sizeof(IPUregisters)); + g_nDMATransfer = 0; +} + +void ipuShutdown() +{ +} + +int ipuFreeze(gzFile f, int Mode) { + IPUProcessInterrupt(); + + gzfreeze(ipuRegs, sizeof(IPUregisters)); + gzfreeze(&g_nDMATransfer, sizeof(g_nDMATransfer)); + gzfreeze(&FIreadpos, sizeof(FIreadpos)); + gzfreeze(&FIwritepos, sizeof(FIwritepos)); + gzfreeze(fifo_input, sizeof(fifo_input)); + gzfreeze(&FOreadpos, sizeof(FOreadpos)); + gzfreeze(&FOwritepos, sizeof(FOwritepos)); + gzfreeze(fifo_output, sizeof(fifo_output)); + gzfreeze(&g_BP, sizeof(g_BP)); + gzfreeze(niq, sizeof(niq)); + gzfreeze(iq, sizeof(niq)); + gzfreeze(vqclut, sizeof(vqclut)); + gzfreeze(s_thresh, sizeof(s_thresh)); + gzfreeze(&coded_block_pattern, sizeof(coded_block_pattern)); + gzfreeze(&g_decoder, sizeof(g_decoder)); + gzfreeze(mpeg2_scan_norm, sizeof(mpeg2_scan_norm)); + gzfreeze(mpeg2_scan_alt, sizeof(mpeg2_scan_alt)); + gzfreeze(g_nCmdPos, sizeof(g_nCmdPos)); + gzfreeze(&g_nCmdIndex, sizeof(g_nCmdIndex)); + gzfreeze(&ipuCurCmd, sizeof(ipuCurCmd)); + + gzfreeze(_readbits, sizeof(_readbits)); + + if( Mode == 0 ) { + int temp = readbits-_readbits; + gzfreeze(&temp, sizeof(temp)); + } + else { + int temp; + gzfreeze(&temp, sizeof(temp)); + readbits = _readbits; + } + + //other stuff + g_decoder.intra_quantizer_matrix =(u8*)iq; + g_decoder.non_intra_quantizer_matrix =(u8*)niq; + g_decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P + g_decoder.mb8 =&mb8; + g_decoder.mb16=&mb16; + g_decoder.rgb32=&rgb32; + g_decoder.rgb16=&rgb16; + g_decoder.stride=16; + + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + + return 0; +} + +BOOL ipuCanFreeze() +{ + return ipuCurCmd == 0xffffffff; +} + +u32 ipuRead32(u32 mem) +{ + IPUProcessInterrupt(); + + switch (mem){ + + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl.IFC = g_BP.IFC; + //ipuRegs->ctrl.OFC = min(g_nIPU0Data, 8); // check if transfering to ipu0 + ipuRegs->ctrl.CBP = coded_block_pattern; + +#ifdef IPU_LOG + if( !ipuRegs->ctrl.BUSY ) { + IPU_LOG("Ipu read32: IPU_CTRL=0x%08X %x\n", ipuRegs->ctrl._u32, cpuRegs.pc); + } +#endif + return ipuRegs->ctrl._u32; + + case 0x10002020: // IPU_BP + + ipuRegs->ipubp = g_BP.BP & 0x7f; + ipuRegs->ipubp |= g_BP.IFC<<8; + ipuRegs->ipubp |= (g_BP.FP+g_BP.bufferhasnew) << 16; + +#ifdef IPU_LOG + IPU_LOG("Ipu read32: IPU_BP=0x%08X\n", *(u32*)&g_BP); +#endif + return ipuRegs->ipubp; + } + + return *(u32*)(((u8*)ipuRegs)+(mem&0xff)); // ipu repeats every 0x100 +} + +u64 ipuRead64(u32 mem) +{ + IPUProcessInterrupt(); + +#ifdef PCSX2_DEVBUILD + if( mem == 0x10002010 ) { + SysPrintf("reading 64bit IPU ctrl\n"); + } + if( mem == 0x10002020 ) { + SysPrintf("reading 64bit IPU top\n"); + } +#endif + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + //if(!ipuRegs->cmd.BUSY){ + if( ipuRegs->cmd.DATA&0xffffff ) { + IPU_LOG("Ipu read64: IPU_CMD=BUSY=%x, DATA=%08X\n", ipuRegs->cmd.BUSY?1:0,ipuRegs->cmd.DATA); + } +#endif + //return *(u64*)&ipuRegs->cmd; + break; + + case 0x10002030: // IPU_TOP +#ifdef IPU_LOG + IPU_LOG("Ipu read64: IPU_TOP=%x, bp = %d\n",ipuRegs->top,g_BP.BP); +#endif + + //return *(u64*)&ipuRegs->top; + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu read64: Unknown=%x\n", mem); +#endif + break; + + } + return *(u64*)(((u8*)ipuRegs)+(mem&0xff)); +} + +#ifndef PCSX2_NORECBUILD + +#ifndef __x86_64__ + +int ipuConstRead32(u32 x86reg, u32 mem) +{ + int workingreg, tempreg, tempreg2; + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + +// if( !(x86reg&(MEM_XMMTAG|MEM_MMXTAG)) ) { +// if( x86reg == EAX ) { +// tempreg = ECX; +// tempreg2 = EDX; +// } +// else if( x86reg == ECX ) { +// tempreg = EAX; +// tempreg2 = EDX; +// } +// else if( x86reg == EDX ) { +// tempreg = EAX; +// tempreg2 = ECX; +// } +// +// workingreg = x86reg; +// } +// else { + workingreg = EAX; + tempreg = ECX; + tempreg2 = EDX; +// } + + switch (mem){ + + case 0x10002010: // IPU_CTRL + + MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(workingreg, ~0x3f0f); // save OFC + OR8MtoR(workingreg, (u32)&g_BP.IFC); + OR8MtoR(workingreg+4, (u32)&coded_block_pattern); // or ah, mem + +// MOV32MtoR(workingreg, (u32)&ipuRegs->ctrl._u32); +// AND32ItoR(workingreg, ~0x3fff); +// MOV32MtoR(tempreg, (u32)&g_nIPU0Data); +// MOV8MtoR(workingreg, (u32)&g_BP.IFC); +// +// CMP32ItoR(tempreg, 8); +// j8Ptr[5] = JLE8(0); +// MOV32ItoR(tempreg, 8); +// x86SetJ8( j8Ptr[5] ); +// SHL32ItoR(tempreg, 4); +// +// OR8MtoR(workingreg+4, (u32)&coded_block_pattern); // or ah, mem +// OR8RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ctrl._u32, workingreg); +#endif + // NOTE: not updating ipuRegs->ctrl +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + return 1; + + case 0x10002020: // IPU_BP + + assert( (u32)&g_BP.FP + 1 == (u32)&g_BP.bufferhasnew ); + + MOVZX32M8toR(workingreg, (u32)&g_BP.BP); + MOVZX32M8toR(tempreg, (u32)&g_BP.FP); + AND8ItoR(workingreg, 0x7f); + ADD8MtoR(tempreg, (u32)&g_BP.bufferhasnew); + MOV8MtoR(workingreg+4, (u32)&g_BP.IFC); + + SHL32ItoR(tempreg, 16); + OR32RtoR(workingreg, tempreg); + +#ifdef _DEBUG + MOV32RtoM((u32)&ipuRegs->ipubp, workingreg); +#endif + // NOTE: not updating ipuRegs->ipubp +// if( x86reg & MEM_XMMTAG ) SSE2_MOVD_R_to_XMM(x86reg&0xf, workingreg); +// else if( x86reg & MEM_MMXTAG ) MOVD32RtoMMX(x86reg&0xf, workingreg); + + return 1; + + default: + // ipu repeats every 0x100 + _eeReadConstMem32(x86reg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + return 0; + } + + return 0; +} + +void ipuConstRead64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (u32)(((u8*)ipuRegs)+(mem&0xff))); + else { + MOVQMtoR(mmreg, (u32)(((u8*)ipuRegs)+(mem&0xff))); + SetMMXstate(); + } +} + +#else + +int ipuConstRead32(u32 x86reg, u32 mem) +{ + assert(0); +} + +void ipuConstRead64(u32 mem, int mmreg) +{ + assert(0); +} + +#endif // __x86_64__ + +#endif // !defined(PCSX2_NORECBUILD) + +void ipuSoftReset() +{ + if (!mpeg2_inited){ + mpeg2_idct_init(); + convert=convert_rgb (CONVERT_RGB, 32); + convert(16, 16, 0, NULL, &convert_init); + memset(mb8.Y,0,sizeof(mb8.Y)); + memset(mb8.Cb,0,sizeof(mb8.Cb)); + memset(mb8.Cr,0,sizeof(mb8.Cr)); + memset(mb16.Y,0,sizeof(mb16.Y)); + memset(mb16.Cb,0,sizeof(mb16.Cb)); + memset(mb16.Cr,0,sizeof(mb16.Cr)); + mpeg2_inited=1; + } + FIFOto_clear(); + memset(fifo_output,0,sizeof(u32)*32); + FOwritepos = 0; + FOreadpos = 0; + coded_block_pattern = 0; + + ipuRegs->ctrl._u32 = 0; + g_BP.BP = 0; + g_BP.IFC = 0; + g_BP.FP = 0; + g_BP.bufferhasnew = 0; + ipuRegs->top = 0; + g_nCmdIndex = 0; + ipuCurCmd = 0xffffffff; + g_nCmdPos[0] = 0; g_nCmdPos[1] = 0; +} + +void ipuWrite32(u32 mem,u32 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: // IPU_CMD +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE(value); + break; + case 0x10002010: // IPU_CTRL + ipuRegs->ctrl._u32 = (value&0x47f30000)|(ipuRegs->ctrl._u32&0x8000ffff); + if (ipuRegs->ctrl.RST & 0x1) { // RESET + ipuSoftReset(); + } + +#ifdef IPU_LOG + IPU_LOG("Ipu write32: IPU_CTRL=0x%08X\n",value); +#endif + + break; + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write32: Unknown=%x\n", mem); +#endif + *(u32*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +void ipuWrite64(u32 mem, u64 value) +{ + IPUProcessInterrupt(); + + switch (mem){ + case 0x10002000: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: IPU_CMD=0x%08X\n",value); +#endif + IPUCMD_WRITE((u32)value); + break; + + default: +#ifdef IPU_LOG + IPU_LOG("Ipu write64: Unknown=%x\n", mem); +#endif + *(u64*)((u8*)ipuRegs + (mem&0xfff)) = value; + break; + } +} + +#ifndef PCSX2_NORECBUILD + +#ifndef __x86_64__ + +void ipuConstWrite32(u32 mem, int mmreg) +{ + iFlushCall(0); + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) PUSH32R(mmreg); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: // IPU_CMD + if( (mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + case 0x10002010: // IPU_CTRL + if( mmreg & MEM_EECONSTTAG ) { + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x47f30000; + + if( c & 0x40000000 ) { + CALLFunc((u32)ipuSoftReset); + } + else { + AND32ItoM((u32)&ipuRegs->ctrl._u32, 0x8000ffff); + OR32ItoM((u32)&ipuRegs->ctrl._u32, c); + } + } + else { + if( mmreg & MEM_XMMTAG ) SSE2_MOVD_XMM_to_R(EAX, mmreg&0xf); + else if( mmreg & MEM_MMXTAG ) MOVD32MMXtoR(EAX, mmreg&0xf); + else POP32R(EAX); + + MOV32MtoR(ECX, (u32)&ipuRegs->ctrl._u32); + AND32ItoR(EAX, 0x47f30000); + AND32ItoR(ECX, 0x8000ffff); + OR32RtoR(EAX, ECX); + MOV32RtoM((u32)&ipuRegs->ctrl._u32, EAX); + + TEST32ItoR(EAX, 0x40000000); + j8Ptr[5] = JZ8(0); + + // reset + CALLFunc((u32)ipuSoftReset); + + x86SetJ8( j8Ptr[5] ); + } + + break; + default: + if( !(mmreg & (MEM_XMMTAG|MEM_MMXTAG|MEM_EECONSTTAG)) ) POP32R(mmreg); + _eeWriteConstMem32((u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +void ipuConstWrite64(u32 mem, int mmreg) +{ + iFlushCall(0); + CALLFunc((u32)IPUProcessInterrupt); + + switch (mem){ + case 0x10002000: + _recPushReg(mmreg); + CALLFunc((u32)IPUCMD_WRITE); + ADD32ItoR(ESP, 4); + break; + + default: + _eeWriteConstMem64( (u32)((u8*)ipuRegs + (mem&0xfff)), mmreg); + break; + } +} + +#else + +void ipuConstWrite32(u32 mem, int mmreg) +{ + assert(0); +} + +void ipuConstWrite64(u32 mem, int mmreg) +{ + assert(0); +} + +#endif + +#endif + +/////////////////////////////////////////// +// IPU Commands (exec on worker thread only) + +static void ipuBCLR(u32 val) { + FIFOto_clear(); + g_BP.BP = val & 0x7F; + g_BP.FP = 0; + g_BP.IFC = 0; + ipuRegs->ctrl.BUSY = 0; + ipuRegs->cmd.BUSY = 0; +#ifdef IPU_LOG + IPU_LOG("Clear IPU input FIFO. Set Bit offset=0x%X\n", g_BP.BP); +#endif +} + +static BOOL ipuIDEC(u32 val) +{ + tIPU_CMD_IDEC idec={0, 0, 0, 0, 0, 0, 0, 0, 0}; + + *(u32*)&idec=val; +#ifdef IPU_LOG + IPU_LOG("IPU IDEC command.\n"); + if (idec.FB){ IPU_LOG(" Skip %d bits.",idec.FB);} + IPU_LOG(" Quantizer step code=0x%X.",idec.QSC); + if (idec.DTD==0){ IPU_LOG(" Does not decode DT."); + }else{ IPU_LOG(" Decodes DT.");} + if (idec.SGN==0){ IPU_LOG(" No bias."); + }else{ IPU_LOG(" Bias=128.");} + if (idec.DTE==1){ IPU_LOG(" Dither Enabled.");} + if (idec.OFM==0){ IPU_LOG(" Output format is RGB32."); + }else{ IPU_LOG(" Output format is RGB16.");} + IPU_LOG("\n"); +#endif + g_BP.BP+= idec.FB;//skip FB bits + //from IPU_CTRL + ipuRegs->ctrl.PCT = I_TYPE; //Intra DECoding;) + g_decoder.coding_type =ipuRegs->ctrl.PCT; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from IDEC value + g_decoder.quantizer_scale =idec.QSC; + g_decoder.frame_pred_frame_dct=!idec.DTD; + g_decoder.sgn =idec.SGN; + g_decoder.dte =idec.DTE; + g_decoder.ofm =idec.OFM; + //other stuff + g_decoder.dcr =1;//resets DC prediction value + + s_routine = so_create(mpeg2sliceIDEC, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + so_call(s_routine); + return s_RoutineDone; +} + +#ifdef _DEBUG +static int s_bdec=0; +#else +#define s_bdec 0 +#endif + +static BOOL ipuBDEC(u32 val) +{ + tIPU_CMD_BDEC bdec={0, 0, 0, 0, 0, 0, 0, 0}; + *(u32*)&bdec=val; + +#ifdef IPU_LOG + IPU_LOG("IPU BDEC(macroblock decode) command %x, num: 0x%x\n",cpuRegs.pc, s_bdec); + if (bdec.FB){ IPU_LOG(" Skip 0x%X bits.", bdec.FB);} + if (bdec.MBI){ IPU_LOG(" Intra MB.");} + else{ IPU_LOG(" Non-intra MB.");} + if (bdec.DCR){ IPU_LOG(" Resets DC prediction value.");} + else{ IPU_LOG(" Doesn't reset DC prediction value.");} + if (bdec.DT){ IPU_LOG(" Use field DCT.");} + else{ IPU_LOG(" Use frame DCT.");} + IPU_LOG(" Quantiser step=0x%X\n",bdec.QSC); +#endif + +#ifdef _DEBUG + s_bdec++; +#endif + + g_BP.BP+= bdec.FB;//skip FB bits + g_decoder.coding_type = I_TYPE; + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + g_decoder.q_scale_type =ipuRegs->ctrl.QST; + g_decoder.intra_vlc_format=ipuRegs->ctrl.IVF; + g_decoder.scan =ipuRegs->ctrl.AS ? mpeg2_scan_alt: mpeg2_scan_norm; + g_decoder.intra_dc_precision=ipuRegs->ctrl.IDP; + //from BDEC value + /* JayteeMaster: the quantizer (linear/non linear) depends on the q_scale_type */ + g_decoder.quantizer_scale =g_decoder.q_scale_type?non_linear_quantizer_scale [bdec.QSC]:bdec.QSC<<1; + g_decoder.macroblock_modes =bdec.DT ? DCT_TYPE_INTERLACED : 0; + g_decoder.dcr =bdec.DCR; + g_decoder.macroblock_modes|=bdec.MBI ? MACROBLOCK_INTRA : MACROBLOCK_PATTERN; + + memset(&mb8, 0, sizeof(struct macroblock_8)); + memset(&mb16, 0, sizeof(struct macroblock_16)); + + s_routine = so_create(mpeg2_slice, &s_RoutineDone, s_tempstack, sizeof(s_tempstack)); + assert( s_routine != NULL ); + so_call(s_routine); + return s_RoutineDone; +} + +static BOOL ipuVDEC(u32 val) { + + switch( g_nCmdPos[0] ) { + case 0: + ipuRegs->cmd.DATA = 0; + if( !getBits32((u8*)&g_decoder.bitstream_buf, 0) ) + return FALSE; + + g_decoder.bitstream_bits = -16; + BigEndian(g_decoder.bitstream_buf, g_decoder.bitstream_buf); + + //value = BigEndian(value); + switch((val >> 26) & 3){ + case 0://Macroblock Address Increment + g_decoder.mpeg1 =ipuRegs->ctrl.MP1; + ipuRegs->cmd.DATA = get_macroblock_address_increment(&g_decoder); + break; + case 1://Macroblock Type //known issues: no error detected + g_decoder.frame_pred_frame_dct=1;//prevent DCT_TYPE_INTERLACED + g_decoder.coding_type =ipuRegs->ctrl.PCT; + ipuRegs->cmd.DATA=get_macroblock_modes(&g_decoder); + break; + case 2://Motion Code //known issues: no error detected + ipuRegs->cmd.DATA=get_motion_delta(&g_decoder,0); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + case 3://DMVector + ipuRegs->cmd.DATA=get_dmv(&g_decoder); + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + break; + } + + //g_BP.BP += ipuRegs->cmd.DATA >> 16; + g_BP.BP+=(g_decoder.bitstream_bits+16); + if((int)g_BP.BP < 0) { + g_BP.BP += 128; + ReorderBitstream(); + } + + ipuRegs->cmd.DATA = (ipuRegs->cmd.DATA & 0xFFFF) | ((g_decoder.bitstream_bits+16) << 16); + ipuRegs->ctrl.ECD = (ipuRegs->cmd.DATA==0); + + case 1: + if( !getBits32((u8*)&ipuRegs->top, 0) ) { + g_nCmdPos[0] = 1; + return FALSE; + } + + BigEndian(ipuRegs->top, ipuRegs->top); + +#ifdef IPU_LOG + IPU_LOG("IPU VDEC command data 0x%x(0x%x). Skip 0x%X bits/Table=%d (%s), pct %d\n", + ipuRegs->cmd.DATA,ipuRegs->cmd.DATA >> 16,val & 0x3f, (val >> 26) & 3, (val >> 26) & 1 ? + ((val >> 26) & 2 ? "DMV" : "MBT") : (((val >> 26) & 2 ? "MC" : "MBAI")),ipuRegs->ctrl.PCT); +#endif + + return TRUE; + } + + assert(0); + return FALSE; +} + +static BOOL ipuFDEC(u32 val) +{ + if( !getBits32((u8*)&ipuRegs->cmd.DATA, 0) ) + return FALSE; + + BigEndian(ipuRegs->cmd.DATA, ipuRegs->cmd.DATA); + ipuRegs->top = ipuRegs->cmd.DATA; + return TRUE; +} + +static BOOL ipuSETIQ(u32 val) +{ + int i; + + if ((val >> 27) & 1){ + g_nCmdPos[0] += getBits((u8*)niq + g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); // 8*8*8 + +#ifdef IPU_LOG + IPU_LOG("Read non-intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + niq[i*8+0], niq[i*8+1], niq[i*8+2], niq[i*8+3], + niq[i*8+4], niq[i*8+5], niq[i*8+6], niq[i*8+7]); + } +#endif + }else{ + g_nCmdPos[0] += getBits((u8*)iq+8*g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); +#ifdef IPU_LOG + IPU_LOG("Read intra quantisation matrix from IPU FIFO.\n"); + for (i=0; i<8; i++){ + IPU_LOG("%02X %02X %02X %02X %02X %02X %02X %02X\n", + iq[i*8+0], iq[i*8+1], iq[i*8+2], iq[i*8+3], + iq[i*8+4], iq[i*8+5], iq[i*8+6], iq[i*8+7]); + } +#endif + } + + return g_nCmdPos[0] == 64; +} + +static BOOL ipuSETVQ(u32 val) +{ + g_nCmdPos[0] += getBits((u8*)vqclut+g_nCmdPos[0], 256-8*g_nCmdPos[0], 1); // 16*2*8 + + if( g_nCmdPos[0] == 32 ) { +#ifdef IPU_LOG + IPU_LOG("IPU SETVQ command.\nRead VQCLUT table from IPU FIFO.\n"); + IPU_LOG( + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n" + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d " + "%02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d %02d:%02d:%02d\n", + vqclut[0] >> 10, (vqclut[0] >> 5) & 0x1F, vqclut[0] & 0x1F, + vqclut[1] >> 10, (vqclut[1] >> 5) & 0x1F, vqclut[1] & 0x1F, + vqclut[2] >> 10, (vqclut[2] >> 5) & 0x1F, vqclut[2] & 0x1F, + vqclut[3] >> 10, (vqclut[3] >> 5) & 0x1F, vqclut[3] & 0x1F, + vqclut[4] >> 10, (vqclut[4] >> 5) & 0x1F, vqclut[4] & 0x1F, + vqclut[5] >> 10, (vqclut[5] >> 5) & 0x1F, vqclut[5] & 0x1F, + vqclut[6] >> 10, (vqclut[6] >> 5) & 0x1F, vqclut[6] & 0x1F, + vqclut[7] >> 10, (vqclut[7] >> 5) & 0x1F, vqclut[7] & 0x1F, + vqclut[8] >> 10, (vqclut[8] >> 5) & 0x1F, vqclut[8] & 0x1F, + vqclut[9] >> 10, (vqclut[9] >> 5) & 0x1F, vqclut[9] & 0x1F, + vqclut[10] >> 10, (vqclut[10] >> 5) & 0x1F, vqclut[10] & 0x1F, + vqclut[11] >> 10, (vqclut[11] >> 5) & 0x1F, vqclut[11] & 0x1F, + vqclut[12] >> 10, (vqclut[12] >> 5) & 0x1F, vqclut[12] & 0x1F, + vqclut[13] >> 10, (vqclut[13] >> 5) & 0x1F, vqclut[13] & 0x1F, + vqclut[14] >> 10, (vqclut[14] >> 5) & 0x1F, vqclut[14] & 0x1F, + vqclut[15] >> 10, (vqclut[15] >> 5) & 0x1F, vqclut[15] & 0x1F); +#endif + } + + return g_nCmdPos[0] == 32; +} + +// IPU Transfers are split into 8Qwords so we need to send ALL the data +static BOOL ipuCSC(u32 val) +{ + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + *(u32*)&csc=val; + +#ifdef IPU_LOG + IPU_LOG("IPU CSC(Colorspace conversion from YCbCr) command (%d).\n",csc.MBC); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is RGB32. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } +#endif + //SysPrintf("CSC\n"); + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 3072/8 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 3072-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 3072/8 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + if (csc.OFM){ + ipu_dither2(&rgb32, &rgb16, csc.DTE); + } + } + + if (csc.OFM){ + while(g_nCmdPos[1] < 32) + { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] <= 0 ) + return FALSE; + } + } + else { + while(g_nCmdPos[1] < 64) + { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb32)+4*g_nCmdPos[1], 64-g_nCmdPos[1]); + + if( g_nCmdPos[1] <= 0 ) + return FALSE; + } + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +// Todo - Need to add the same stop and start code as CSC +static BOOL ipuPACK(u32 val) { + tIPU_CMD_CSC csc ={0, 0, 0, 0, 0}; + + *(u32*)&csc=val; +#ifdef IPU_LOG + IPU_LOG("IPU PACK (Colorspace conversion from RGB32) command.\n"); + if (csc.OFM){ IPU_LOG("Output format is RGB16. ");} + else{ IPU_LOG("Output format is INDX4. ");} + if (csc.DTE){ IPU_LOG("Dithering enabled."); } + IPU_LOG("Number of macroblocks to be converted: %d\n", csc.MBC); +#endif + for (;g_nCmdIndex<(int)csc.MBC; g_nCmdIndex++){ + + if( g_nCmdPos[0] < 512 ) { + g_nCmdPos[0] += getBits((u8*)&mb8+g_nCmdPos[0], 512-8*g_nCmdPos[0], 1); + + if( g_nCmdPos[0] < 64 ) + return FALSE; + + ipu_csc(&mb8, &rgb32, 0); + ipu_dither2(&rgb32, &rgb16, csc.DTE); + if (csc.OFM){ + ipu_vq(&rgb16, indx4); + } + } + + if (csc.OFM) { + g_nCmdPos[1] += FIFOfrom_write(((u32*)&rgb16)+4*g_nCmdPos[1], 32-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 32 ) + return FALSE; + } + else { + g_nCmdPos[1] += FIFOfrom_write(((u32*)indx4)+4*g_nCmdPos[1], 8-g_nCmdPos[1]); + + if( g_nCmdPos[1] < 8 ) + return FALSE; + } + + g_nCmdPos[0] = 0; + g_nCmdPos[1] = 0; + } + + return TRUE; +} + +static void ipuSETTH(u32 val) { + s_thresh[0] = (val & 0xff); + s_thresh[1] = ((val>>16) & 0xff); +#ifdef IPU_LOG + IPU_LOG("IPU SETTH (Set threshold value)command %x.\n", val&0xff00ff); +#endif +} + +/////////////////////// +// IPU Worker Thread // +/////////////////////// +#define IPU_INTERRUPT(dma) { \ + hwIntcIrq(INTC_IPU); \ +} + +void IPUCMD_WRITE(u32 val) { + + // don't process anything if currently busy + if( ipuRegs->ctrl.BUSY ) { + // wait for thread + SysPrintf("IPU BUSY!\n"); + } + + ipuRegs->ctrl.ECD = 0; + ipuRegs->ctrl.SCD = 0; //clear ECD/SCD + ipuRegs->cmd.DATA = val; + g_nCmdPos[0] = 0; + + switch (ipuRegs->cmd.CMD) { + case SCE_IPU_BCLR: + ipuBCLR(val); + IPU_INTERRUPT(DMAC_TO_IPU); + return; + + case SCE_IPU_VDEC: + + g_BP.BP+= val & 0x3F; + + // check if enough data in queue + if( ipuVDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_FDEC: + +#ifdef IPU_LOG + IPU_LOG("IPU FDEC command. Skip 0x%X bits, FIFO 0x%X bytes, BP 0x%X, FP %d, CHCR 0x%x, %x\n", + val & 0x3f,g_BP.IFC,(int)g_BP.BP,g_BP.FP,((DMACh*)&PS2MEM_HW[0xb400])->chcr,cpuRegs.pc); +#endif + + g_BP.BP+= val & 0x3F; + + if( ipuFDEC(val) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0x80000000; + ipuRegs->topbusy = 0x80000000; + + break; + + case SCE_IPU_SETTH: + ipuSETTH(val); + hwIntcIrq(INTC_IPU); + return; + + case SCE_IPU_SETIQ: +#ifdef IPU_LOG + IPU_LOG("IPU SETIQ command.\n"); +#endif +#ifdef IPU_LOG + if (val & 0x3f){ + IPU_LOG("Skip %d bits.\n", val & 0x3f); + } +#endif + g_BP.BP+= val & 0x3F; + + if( ipuSETIQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( ipuSETVQ(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + return; + } + + break; + case SCE_IPU_CSC: + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuCSC(ipuRegs->cmd.DATA) ) { + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + IPU_INTERRUPT(DMAC_FROM_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + case SCE_IPU_PACK: + + g_nCmdPos[1] = 0; + g_nCmdIndex = 0; + FreezeMMXRegs(1); + + if( ipuPACK(ipuRegs->cmd.DATA) ) { + IPU_INTERRUPT(DMAC_TO_IPU); + FreezeMMXRegs(0); + return; + } + + FreezeMMXRegs(0); + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + if( ipuIDEC(val) ) { + // idec done, ipu0 done too + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + FreezeMMXRegs(0); + + return; + + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + if( ipuBDEC(val)) { + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + } + + ipuRegs->topbusy = 0x80000000; + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + FreezeMMXRegs(0); + + return; + } + + // have to resort to the thread + ipuCurCmd = val>>28; + ipuRegs->ctrl.BUSY = 1; + hwIntcIrq(INTC_IPU); +} + +void IPUWorker() +{ + assert( ipuRegs->ctrl.BUSY ); + + switch (ipuCurCmd) { + case SCE_IPU_VDEC: + if( !ipuVDEC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_FDEC: + if( !ipuFDEC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + ipuRegs->cmd.BUSY = 0; + ipuRegs->topbusy = 0; + + break; + + case SCE_IPU_SETIQ: + if( !ipuSETIQ(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + case SCE_IPU_SETVQ: + if( !ipuSETVQ(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + case SCE_IPU_CSC: + if( !ipuCSC(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + break; + case SCE_IPU_PACK: + if( !ipuPACK(ipuRegs->cmd.DATA) ) + { + hwIntcIrq(INTC_IPU); + return; + } + + break; + + case SCE_IPU_IDEC: + FreezeMMXRegs(1); + so_call(s_routine); + if( !s_RoutineDone ) { + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.OFC = 0; + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + // CHECK!: IPU0dma remains when IDEC is done, so we need to clear it + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + FreezeMMXRegs(0); + return; + case SCE_IPU_BDEC: + FreezeMMXRegs(1); + so_call(s_routine); + if(!s_RoutineDone) + { + //hwIntcIrq(INTC_IPU); + FreezeMMXRegs(0); + return; + } + + ipuRegs->ctrl.BUSY = 0; + ipuRegs->topbusy = 0; + ipuRegs->cmd.BUSY = 0; + ipuCurCmd = 0xffffffff; + if(ipu0dma->qwc > 0 && (ipu0dma->chcr & 0x100)) INT(DMAC_FROM_IPU,0); + + FreezeMMXRegs(0); + return; + + default: + SysPrintf("Unknown IPU command: %x\n", ipuRegs->cmd.CMD); + break; + } + + // success + ipuRegs->ctrl.BUSY = 0; + ipuCurCmd = 0xffffffff; + IPU_INTERRUPT(DMAC_TO_IPU); +} + +///////////////// +// Buffer reader + +// move the readbits queue +__forceinline void inc_readbits() +{ + readbits += 16; + if( readbits >= _readbits+64 ) { + + // move back + *(u64*)(_readbits) = *(u64*)(_readbits+64); + *(u64*)(_readbits+8) = *(u64*)(_readbits+72); + readbits = _readbits; + } +} + +// returns the pointer of readbits moved by 1 qword +__forceinline u8* next_readbits() +{ + return readbits + 16; +} + +// returns the pointer of readbits moved by 1 qword +u8* prev_readbits() +{ + if( readbits < _readbits+16 ) { + return _readbits+48-(readbits-_readbits); + } + + return readbits-16; +} + +void ReorderBitstream() +{ + readbits = prev_readbits(); + g_BP.bufferhasnew = 1; + //g_BP.FP++; +} + +// IPU has a 2qword internal buffer whose status is pointed by FP. +// If FP is 1, there's 1 qword in buffer. Second qword is only loaded +// incase there are less than 32bits available in the first qword. +// \return Number of bits available (clamps at 16 bits) +u16 FillInternalBuffer(u32 * pointer, u32 advance) +{ + if(g_BP.FP == 0) + { + if( FIFOto_read(next_readbits()) == 0 ) + return 0; + + g_BP.bufferhasnew = 0; + inc_readbits(); + g_BP.FP = 1; + } + else if(g_BP.FP < 2 && g_BP.bufferhasnew == 0) + { + // in reality, need only > 96, but IPU reads ahead + if( *(int*)pointer >= 96) { + if( FIFOto_read(next_readbits()) ) + { + g_BP.FP += 1; + }else if(*(int*)pointer >= 128) + return 0; + + } + } + + if(*(int*)pointer >= 128) + { + assert( g_BP.FP >= 1 || g_BP.bufferhasnew); + inc_readbits(); + + if(advance) + { + // Incase BDEC reorders bits, we need to make sure we have the old + // data backed up. So we store the last read qword into the 2nd slot + // of the internal buffer. After that we copy the new qword read in + // the 2nd slot to the 1st slot to be read. + if( !g_BP.bufferhasnew ) + g_BP.FP--; + g_BP.bufferhasnew = 0; + } + + *pointer &= 127; + } + + // fixed : added (g_BP.FP+g_BP.bufferhasnew)*128 as fp could have been 0 + return (g_BP.FP+g_BP.bufferhasnew) == 1 ? g_BP.FP*128-(*(int*)pointer) : 128; +} + +// whenever reading fractions of bytes. The low bits always come from the next byte +// while the high bits come from the current byte +u8 getBits32(u8 *address, u32 advance) +{ + register u32 mask, shift=0; + u8* readpos; + + // Check if the current BP has exceeded or reached the limit of 128 + if( FillInternalBuffer(&g_BP.BP,1) < 32 ) + return 0; + + readpos = readbits+(int)g_BP.BP/8; + + if (g_BP.BP & 7) { + + shift = g_BP.BP&7; + mask = (0xff>>shift); + mask = mask|(mask<<8)|(mask<<16)|(mask<<24); + + *(u32*)address = ((~mask&*(u32*)(readpos+1))>>(8-shift)) | (((mask)&*(u32*)readpos)<>shift); + mask = mask|(mask<<8); + + *(u16*)address = ((~mask&*(u16*)(readpos+1))>>(8-shift)) | (((mask)&*(u16*)readpos)<>shift); + + *(u8*)address = (((~mask)&readpos[1])>>(8-shift)) | (((mask)&*readpos)<> (pointer&7)) << + (8-howmuch-(pointer&7))) & 0xFF; + mask &= readbits[((pointer)>>3)]; + mask >>= 8-howmuch-(pointer&7); + pointer += howmuch; + size -= howmuch; + shift -= howmuch; + *address |= mask << shift; + } + + ++address; + } + else + { + u8* readmem; + while (size) + { + if( FillInternalBuffer(&pointer,advance) < 8 ) + return address-oldaddr; + + howmuch = min(128-pointer, size); + size -= howmuch; + + readmem = readbits + (pointer>>3); + pointer += howmuch; + howmuch >>= 3; + + while(howmuch >= 4) { + *(u32*)address = *(u32*)readmem; + howmuch -= 4; + address += 4; + readmem += 4; + } + + switch(howmuch) { + case 3: address[2] = readmem[2]; + case 2: address[1] = readmem[1]; + case 1: address[0] = readmem[0]; + case 0: + break; +#ifdef _MSC_VER + default: __assume(0); +#endif + } + + address += howmuch; + } + } + + // If not advance then reset the Reading buffer value + if(advance) g_BP.BP = pointer; + else readbits = oldbits; // restore the last pointer + + return address-oldaddr; +} + +///////////////////// CORE FUNCTIONS ///////////////// +void Skl_YUV_To_RGB32_MMX(u8 *RGB, const int Dst_BpS, const u8 *Y, const u8 *U, const u8 *V, + const int Src_BpS, const int Width, const int Height); + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn){ + int i; + u8* p = (u8*)rgb32; + + convert_init.start(convert_init.id, (u8*)rgb32, CONVERT_FRAME); + convert_init.copy(convert_init.id, (u8*)mb8->Y, (u8*)mb8->Cr, (u8*)mb8->Cb, 0); + + // do alpha processing +// if( cpucaps.hasStreamingSIMD2Extensions ) { +// int i; +// u8* p = (u8*)rgb32; +// +// __asm { +// movaps xmm6, s_thresh +// pshufd xmm7, xmm6, 0xee +// pshufd xmm6, xmm6, 0x44 +// pxor xmm5, xmm5 +// } +// +// for(i = 0; i < 64; i += 4, p += 64) { +// // process 2 qws at a time +// __asm { +// // extract 8 dwords +// mov edi, p +// movaps xmm0, qword ptr [edi] +// movaps xmm1, qword ptr [edi+16] +// movaps xmm2, qword ptr [edi+32] +// movaps xmm3, qword ptr [edi+48] +// +// +// } + // fixes suikoden5 + if( s_thresh[0] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + if( p[0] < s_thresh[0] && p[1] < s_thresh[0] && p[2] < s_thresh[0] ) + *(u32*)p = 0; + else + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else if( s_thresh[1] > 0 ) { + for(i = 0; i < 64*4; i++, p += 4) { + p[3] = (p[1] < s_thresh[1] && p[2] < s_thresh[1] && p[3] < s_thresh[1]) ? 0x40 : 0x80; + } + } + else { + for(i = 0; i < 64; i++, p += 16) { + p[3] = p[7] = p[11] = p[15] = 0x80; + } + } +} + +void ipu_dither2(struct macroblock_rgb32* rgb32, struct macroblock_rgb16 *rgb16, int dte) +{ + int i, j; + for(i = 0; i < 16; ++i) { + for(j = 0; j < 16; ++j) { + rgb16->c[i][j].r = rgb32->c[i][j].r>>3; + rgb16->c[i][j].g = rgb32->c[i][j].g>>3; + rgb16->c[i][j].b = rgb32->c[i][j].b>>3; + rgb16->c[i][j].a = rgb32->c[i][j].a==0x40; + } + } +} + +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte) +{ + //SysPrintf("IPU: Dither not implemented"); +} + +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4){ + SysPrintf("IPU: VQ not implemented"); +} + +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16){ + unsigned char *s=(unsigned char*)mb8; + signed short *d=(signed short*)mb16; + int i; + for (i=0; i< 256; i++) *d++ = *s++; //Y bias - 16 + for (i=0; i< 64; i++) *d++ = *s++; //Cr bias - 128 + for (i=0; i< 64; i++) *d++ = *s++; //Cb bias - 128 + /*for(i = 0; i < 384/(16*6); ++i, s += 16*4, d += 16*4) { + __m128i r0, r1, r2, r3, r4, r5, r6, r7; + + r0 = _mm_load_si128((__m128i*)s); + r2 = _mm_load_si128((__m128i*)s+1); + r4 = _mm_load_si128((__m128i*)s+2); + r6 = _mm_load_si128((__m128i*)s+3); + + // signed shift + r1 = _mm_srai_epi16(_mm_unpackhi_epi8(r0, r0), 8); + r0 = _mm_srai_epi16(_mm_unpacklo_epi8(r0, r0), 8); + r3 = _mm_srai_epi16(_mm_unpackhi_epi8(r2, r2), 8); + r2 = _mm_srai_epi16(_mm_unpacklo_epi8(r2, r2), 8); + r5 = _mm_srai_epi16(_mm_unpackhi_epi8(r4, r4), 8); + r4 = _mm_srai_epi16(_mm_unpacklo_epi8(r4, r4), 8); + r7 = _mm_srai_epi16(_mm_unpackhi_epi8(r6, r6), 8); + r6 = _mm_srai_epi16(_mm_unpacklo_epi8(r6, r6), 8); + + _mm_store_si128((__m128i*)d, r0); + _mm_store_si128((__m128i*)d+1, r1); + _mm_store_si128((__m128i*)d+2, r2); + _mm_store_si128((__m128i*)d+3, r3); + _mm_store_si128((__m128i*)d+4, r4); + _mm_store_si128((__m128i*)d+5, r5); + _mm_store_si128((__m128i*)d+6, r6); + _mm_store_si128((__m128i*)d+7, r7); + }*/ +} + +///////////////////// IPU DMA //////////////////////// +void FIFOto_clear() +{ + //assert( g_BP.IFC == 0 ); + //memset(fifo_input,0,sizeof(fifo_input)); + g_BP.IFC = 0; + FIreadpos = 0; + FIwritepos = 0; +} + +int FIFOto_read(void *value) +{ + // wait until enough data + if( g_BP.IFC == 0 ) { + if( IPU1dma() == 0 ) + return 0; + + assert( g_BP.IFC > 0 ); + } + + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_input[FIreadpos]; fifo_input[FIreadpos] = 0; + ((u32*)value)[1] = fifo_input[FIreadpos+1]; fifo_input[FIreadpos+1] = 0; + ((u32*)value)[2] = fifo_input[FIreadpos+2]; fifo_input[FIreadpos+2] = 0; + ((u32*)value)[3] = fifo_input[FIreadpos+3]; fifo_input[FIreadpos+3] = 0; + FIreadpos = (FIreadpos + 4) & 31; + g_BP.IFC--; + return 1; +} + +int FIFOto_write(u32* pMem, int size) +{ + int transsize; + int firsttrans = min(size, 8-(int)g_BP.IFC); + + g_BP.IFC+=firsttrans; + transsize = firsttrans; + + while(transsize-- > 0) { + fifo_input[FIwritepos] = pMem[0]; + fifo_input[FIwritepos+1] = pMem[1]; + fifo_input[FIwritepos+2] = pMem[2]; + fifo_input[FIwritepos+3] = pMem[3]; + FIwritepos = (FIwritepos+4)&31; + pMem +=4; + } + + return firsttrans; +} + +#define IPU1chain() { \ + if(ipu1dma->qwc > 0) \ + { \ + int qwc = ipu1dma->qwc; \ + pMem = (u32*)dmaGetAddr(ipu1dma->madr); \ + if (pMem == NULL) { SysPrintf("ipu1dma NULL!\n"); return totalqwc; } \ + qwc = FIFOto_write(pMem, qwc); \ + ipu1dma->madr += qwc<< 4; \ + ipu1dma->qwc -= qwc; \ + totalqwc += qwc; \ + if( ipu1dma->qwc > 0 ) { \ + g_nDMATransfer |= IPU_DMA_ACTV1; \ + return totalqwc; \ + } \ + } \ +} + +int IPU1dma() +{ + u32 *ptag, *pMem; + int done=0; + int ipu1cycles = 0; + int totalqwc = 0; + + assert( !(ipu1dma->chcr&0x40) ); + + if( !(ipu1dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc > 0 ) { + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (g_nDMATransfer&IPU_DMA_DOTIE1)) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + g_nDMATransfer &= ~(IPU_DMA_ACTV1|IPU_DMA_DOTIE1); + + if( (ipu1dma->chcr&0xc) == 0 ) { + INT(DMAC_TO_IPU, totalqwc*BIAS); + return totalqwc; + } + else { + u32 tag = ipu1dma->chcr; // upper bits describe current tag + + if ((ipu1dma->chcr & 0x80) && (tag&0x80000000)) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(tag&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); +#ifdef IPU_LOG + IPU_LOG("dmaIrq Set\n"); +#endif + INT(DMAC_TO_IPU, totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + + switch( tag&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, (1+totalqwc)*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, (1+totalqwc)*BIAS); + return totalqwc; + } + } + } + + if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) { // Normal Mode + //SysPrintf("ipu1 normal empty qwc?\n"); + return totalqwc; + } + + // Transfer Dn_QWC from Dn_MADR to GIF + + if ((ipu1dma->chcr & 0xc) == 0 || ipu1dma->qwc > 0) { // Normal Mode + IPU1chain(); + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + } + else { + // Chain Mode + //while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("IPU1 BUSERR\n"); + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return totalqwc; + } + ipu1cycles+=1; // Add 1 cycles from the QW read for the tag + + ipu1dma->chcr = ( ipu1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + ipu1dma->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + //ipu1dma->madr = ptag[1]; //MADR = ADDR field + +#ifdef IPU_LOG + IPU_LOG("dmaIPU1 dmaChain %8.8x_%8.8x size=%d, addr=%lx, fifosize=%x\n", + ptag[1], ptag[0], ipu1dma->qwc, ipu1dma->madr, 8 - g_BP.IFC); +#endif + + //done = hwDmacSrcChainWithStack(ipu1dma, id); + switch(ptag[0] & 0x70000000) { + case 0x00000000: // refe + // do not change tadr + ipu1dma->madr = ptag[1]; + done = 1; + break; + + case 0x10000000: // cnt + ipu1dma->madr = ipu1dma->tadr + 16; + // Set the taddr to the next tag + ipu1dma->tadr += 16 + (ipu1dma->qwc << 4); + break; + + case 0x20000000: // next + ipu1dma->madr = ipu1dma->tadr + 16; + ipu1dma->tadr = ptag[1]; + break; + + case 0x30000000: // ref + ipu1dma->madr = ptag[1]; + ipu1dma->tadr += 16; + break; + + case 0x70000000: // end + // do not change tadr + ipu1dma->madr = ipu1dma->tadr + 16; + done = 1; + break; + + default: + #ifdef IPU_LOG + IPU_LOG("ERROR: different transfer mode!, Please report to PCSX2 Team\n"); + #endif + break; + } + + if( ptag[0] & 0x80000000 ) + g_nDMATransfer |= IPU_DMA_DOTIE1; + else + g_nDMATransfer &= ~IPU_DMA_DOTIE1; + + IPU1chain(); + + if ((ipu1dma->chcr & 0x80) && (ptag[0]&0x80000000) && ipu1dma->qwc == 0) { //Check TIE bit of CHCR and IRQ bit of tag + SysPrintf("IPU1 TIE\n"); + + if( done ) { + ptag = (u32*)dmaGetAddr(ipu1dma->tadr); + + switch(ptag[0]&0x70000000) { + case 0x00000000: ipu1dma->tadr += 16; break; + case 0x70000000: ipu1dma->tadr = ipu1dma->madr; break; + } + + ipu1dma->chcr = (ipu1dma->chcr & 0xFFFF) | ( (*ptag) & 0xFFFF0000 ); + } + + INT(DMAC_TO_IPU, ipu1cycles+totalqwc*BIAS); + g_nDMATransfer |= IPU_DMA_TIE1; + return totalqwc; + } + //} + + if(ipu1dma->qwc == 0){ + switch( ptag[0]&0x70000000 ) + { + case 0x00000000: + ipu1dma->tadr += 16; + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + + case 0x70000000: + ipu1dma->tadr = ipu1dma->madr; + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; + } + } + } + + INT(DMAC_TO_IPU, (ipu1cycles+totalqwc)*BIAS); + return totalqwc; +} + + + + +int FIFOfrom_write(u32 *value,int size) +{ + int transsize; + int firsttrans; + + if((int)ipuRegs->ctrl.OFC >= 8) IPU0dma(); + + transsize = min(size,8-(int)ipuRegs->ctrl.OFC); + firsttrans = transsize; + + while(transsize-- > 0) { + fifo_output[FOwritepos] = ((u32*)value)[0]; + fifo_output[FOwritepos+1] = ((u32*)value)[1]; + fifo_output[FOwritepos+2] = ((u32*)value)[2]; + fifo_output[FOwritepos+3] = ((u32*)value)[3]; + FOwritepos = (FOwritepos+4)&31; + value += 4; + } + + ipuRegs->ctrl.OFC+=firsttrans; + IPU0dma(); + //SysPrintf("Written %d qwords, %d\n",firsttrans,ipuRegs->ctrl.OFC); + + return firsttrans; +} + +void FIFOfrom_read(void *value,int size) +{ + ipuRegs->ctrl.OFC -= size; + while(size > 0) + { + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_output[FOreadpos]; fifo_output[FOreadpos] = 0; + ((u32*)value)[1] = fifo_output[FOreadpos+1]; fifo_output[FOreadpos+1] = 0; + ((u32*)value)[2] = fifo_output[FOreadpos+2]; fifo_output[FOreadpos+2] = 0; + ((u32*)value)[3] = fifo_output[FOreadpos+3]; fifo_output[FOreadpos+3] = 0; + value = (u32*)value + 4; + FOreadpos = (FOreadpos + 4) & 31; + size--; + } +} + + +void FIFOfrom_readsingle(void *value) +{ + if(ipuRegs->ctrl.OFC > 0) + { + ipuRegs->ctrl.OFC --; + // transfer 1 qword, split into two transfers + ((u32*)value)[0] = fifo_output[FOreadpos]; fifo_output[FOreadpos] = 0; + ((u32*)value)[1] = fifo_output[FOreadpos+1]; fifo_output[FOreadpos+1] = 0; + ((u32*)value)[2] = fifo_output[FOreadpos+2]; fifo_output[FOreadpos+2] = 0; + ((u32*)value)[3] = fifo_output[FOreadpos+3]; fifo_output[FOreadpos+3] = 0; + FOreadpos = (FOreadpos + 4) & 31; + } +} + +int IPU0dma() +{ + int readsize; + void* pMem; + + int qwc = ipu0dma->qwc; + u32 chcr = ipu0dma->chcr; + + if( !(ipu0dma->chcr & 0x100) || (cpuRegs.interrupt & (1<qwc == 0) + return 0; + + assert( !(ipu0dma->chcr&0x40) ); + +#ifdef IPU_LOG + IPU_LOG("dmaIPU0 chcr = %lx, madr = %lx, qwc = %lx\n", + ipu0dma->chcr, ipu0dma->madr, ipu0dma->qwc); +#endif + + assert((ipu0dma->chcr & 0xC) == 0 ); + pMem = (u32*)dmaGetAddr(ipu0dma->madr); + readsize = min(ipu0dma->qwc, (int)ipuRegs->ctrl.OFC); + FIFOfrom_read(pMem,readsize); + ipu0dma->madr += readsize<< 4; + ipu0dma->qwc -= readsize; // note: qwc is u16 + if(ipu0dma->qwc == 0) { + if ((psHu32(DMAC_CTRL) & 0x30) == 0x30) { // STS == fromIPU + psHu32(DMAC_STADR) = ipu0dma->madr; + switch (psHu32(DMAC_CTRL) & 0xC0) { + case 0x80: // GIF + g_nDMATransfer |= IPU_DMA_GIFSTALL; + break; + case 0x40: // VIF + g_nDMATransfer |= IPU_DMA_VIFSTALL; + break; + } + } + INT(DMAC_FROM_IPU,readsize*BIAS); + + } + + return readsize; +} + +void dmaIPU0() // fromIPU +{ + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +void dmaIPU1() // toIPU +{ + IPU1dma(); + if( ipuRegs->ctrl.BUSY ) + IPUWorker(); +} + +extern void dmaGIF(); + +int ipu0Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu0Interrupt: %x\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT0 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT0; + } + + if( g_nDMATransfer & IPU_DMA_GIFSTALL ) { + // gif + g_nDMATransfer &= ~IPU_DMA_GIFSTALL; + if(((DMACh*)&PS2MEM_HW[0xA000])->chcr & 0x100) dmaGIF(); + } + + if( g_nDMATransfer & IPU_DMA_VIFSTALL ) { + // vif + g_nDMATransfer &= ~IPU_DMA_VIFSTALL; + if(((DMACh*)&PS2MEM_HW[0x9000])->chcr & 0x100)dmaVIF1(); + } + + if( g_nDMATransfer & IPU_DMA_TIE0 ) { + g_nDMATransfer &= ~IPU_DMA_TIE0; + } + + ipu0dma->chcr &= ~0x100; + + hwDmacIrq(DMAC_FROM_IPU); + + return 1; +} + +int ipu1Interrupt() { +#ifdef IPU_LOG + IPU_LOG("ipu1Interrupt %x:\n", cpuRegs.cycle); +#endif + + if( g_nDMATransfer & IPU_DMA_FIREINT1 ) { + hwIntcIrq(INTC_IPU); + g_nDMATransfer &= ~IPU_DMA_FIREINT1; + } + + if( g_nDMATransfer & IPU_DMA_TIE1 ) { + g_nDMATransfer &= ~IPU_DMA_TIE1; + }else + ipu1dma->chcr &= ~0x100; + + hwDmacIrq(DMAC_TO_IPU); + + return 1; +} diff --git a/pcsx2/IPU/IPU.h b/pcsx2/IPU/IPU.h new file mode 100644 index 0000000..e9bdc30 --- /dev/null +++ b/pcsx2/IPU/IPU.h @@ -0,0 +1,203 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IPU_H__ +#define __IPU_H__ + +#include "Common.h" +#ifdef _MSC_VER +#pragma pack(1) +#endif + +// +// Bitfield Structure +// +typedef union { + struct { + u32 OPTION : 28; // VDEC decoded value + u32 CMD : 4; // last command + u32 _BUSY; + }; + struct { + u32 DATA; + u32 BUSY; + }; +} tIPU_CMD; + +#define IPU_CTRL_IFC_M (0x0f<< 0) +#define IPU_CTRL_OFC_M (0x0f<< 4) +#define IPU_CTRL_CBP_M (0x3f<< 8) +#define IPU_CTRL_ECD_M (0x01<<14) +#define IPU_CTRL_SCD_M (0x01<<15) +#define IPU_CTRL_IDP_M (0x03<<16) +#define IPU_CTRL_AS_M (0x01<<20) +#define IPU_CTRL_IVF_M (0x01<<21) +#define IPU_CTRL_QST_M (0x01<<22) +#define IPU_CTRL_MP1_M (0x01<<23) +#define IPU_CTRL_PCT_M (0x07<<24) +#define IPU_CTRL_RST_M (0x01<<30) +#define IPU_CTRL_BUSY_M (0x01<<31) + +#define IPU_CTRL_IFC_O ( 0) +#define IPU_CTRL_OFC_O ( 4) +#define IPU_CTRL_CBP_O ( 8) +#define IPU_CTRL_ECD_O (14) +#define IPU_CTRL_SCD_O (15) +#define IPU_CTRL_IDP_O (16) +#define IPU_CTRL_AS_O (20) +#define IPU_CTRL_IVF_O (21) +#define IPU_CTRL_QST_O (22) +#define IPU_CTRL_MP1_O (23) +#define IPU_CTRL_PCT_O (24) +#define IPU_CTRL_RST_O (30) +#define IPU_CTRL_BUSY_O (31) + + +// +// Bitfield Structure +// +typedef union { + struct { + u32 IFC : 4; // Input FIFO counter + u32 OFC : 4; // Output FIFO counter + u32 CBP : 6; // Coded block pattern + u32 ECD : 1; // Error code pattern + u32 SCD : 1; // Start code detected + u32 IDP : 2; // Intra DC precision + u32 resv0 : 2; + u32 AS : 1; // Alternate scan + u32 IVF : 1; // Intra VLC format + u32 QST : 1; // Q scale step + u32 MP1 : 1; // MPEG1 bit strea + u32 PCT : 3; // Picture Type + u32 resv1 : 3; + u32 RST : 1; // Reset + u32 BUSY : 1; // Busy + }; + u32 _u32; +} tIPU_CTRL; + +#define IPU_BP_BP_M (0x7f<< 0) +#define IPU_BP_IFC_M (0x0f<< 8) +#define IPU_BP_FP_M (0x03<<16) + +#define IPU_BP_BP_O ( 0) +#define IPU_BP_IFC_O ( 8) +#define IPU_BP_FP_O (16) + + +// +// Bitfield Structure +// +typedef struct { + u32 BP; // Bit stream point + u16 IFC; // Input FIFO counter + u8 FP; // FIFO point + u8 bufferhasnew; +} tIPU_BP; + +#ifdef _WIN32 +#pragma pack() +#endif + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 3; + u32 DTD : 1; + u32 SGN : 1; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_IDEC; + +typedef struct { + u32 FB : 6; + u32 UN2 :10; + u32 QSC : 5; + u32 UN1 : 4; + u32 DT : 1; + u32 DCR : 1; + u32 MBI : 1; + u32 cmd : 4; +} tIPU_CMD_BDEC; + +typedef struct { + u32 MBC :11; + u32 UN2 :15; + u32 DTE : 1; + u32 OFM : 1; + u32 cmd : 4; +} tIPU_CMD_CSC; + +#define SCE_IPU_BCLR 0x0 +#define SCE_IPU_IDEC 0x1 +#define SCE_IPU_BDEC 0x2 +#define SCE_IPU_VDEC 0x3 +#define SCE_IPU_FDEC 0x4 +#define SCE_IPU_SETIQ 0x5 +#define SCE_IPU_SETVQ 0x6 +#define SCE_IPU_CSC 0x7 +#define SCE_IPU_PACK 0x8 +#define SCE_IPU_SETTH 0x9 + +typedef struct { + tIPU_CMD cmd; + u32 dummy0[2]; + tIPU_CTRL ctrl; + u32 dummy1[3]; + u32 ipubp; + u32 dummy2[3]; + u32 top; + u32 topbusy; + u32 dummy3[2]; +} IPUregisters, *PIPUregisters; + +#define ipuRegs ((IPUregisters*)(PS2MEM_HW+0x2000)) + +void dmaIPU0(); +void dmaIPU1(); + +int ipuInit(); +void ipuReset(); +void ipuShutdown(); +int ipuFreeze(gzFile f, int Mode); +BOOL ipuCanFreeze(); + +u32 ipuRead32(u32 mem); +int ipuConstRead32(u32 x86reg, u32 mem); + +u64 ipuRead64(u32 mem); +void ipuConstRead64(u32 mem, int mmreg); + +void ipuWrite32(u32 mem,u32 value); +void ipuConstWrite32(u32 mem, int mmreg); + +void ipuWrite64(u32 mem,u64 value); +void ipuConstWrite64(u32 mem, int mmreg); + +int ipu0Interrupt(); +int ipu1Interrupt(); + +u8 getBits32(u8 *address, u32 advance); +u8 getBits16(u8 *address, u32 advance); +u8 getBits8(u8 *address, u32 advance); +int getBits(u8 *address, u32 size, u32 advance); + +#endif diff --git a/pcsx2/IPU/Makefile.am b/pcsx2/IPU/Makefile.am new file mode 100644 index 0000000..e76e416 --- /dev/null +++ b/pcsx2/IPU/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I@srcdir@/../ -I@srcdir@/../x86 +noinst_LIBRARIES = libIPU.a + +libIPU_a_SOURCES = IPU.c yuv2rgb.c coroutine.c acoroutine.S + +SUBDIRS = mpeg2lib + +#libIPU_a_LIBADD = mpeg2lib/libmpeg2IPU.a \ No newline at end of file diff --git a/pcsx2/IPU/acoroutine.S b/pcsx2/IPU/acoroutine.S new file mode 100644 index 0000000..de1825d --- /dev/null +++ b/pcsx2/IPU/acoroutine.S @@ -0,0 +1,187 @@ +.intel_syntax + +.extern g_pCurrentRoutine + +#ifdef __x86_64__ + +#define FUNC_OFFSET 0 +#define STACK_OFFSET 8 +#define RBX_OFFSET 16 +#define RBP_OFFSET 24 +#define R12_OFFSET 32 +#define R13_OFFSET 40 +#define R14_OFFSET 48 +#define R15_OFFSET 56 +#define DATA_OFFSET 64 +#define RESTORE_OFFSET 72 + +.globl so_call + .type so_call, @function +so_call: + test dword ptr [%rdi+RESTORE_OFFSET], 1 + jnz so_call_RestoreRegs + mov [%rdi+RBP_OFFSET], %rbp + mov [%rdi+RBX_OFFSET], %rbx + mov [%rdi+R12_OFFSET], %r12 + mov [%rdi+R13_OFFSET], %r13 + mov [%rdi+R14_OFFSET], %r14 + mov [%rdi+R15_OFFSET], %r15 + mov dword ptr [%rdi+RESTORE_OFFSET], 1 + jmp so_call_CallFn +so_call_RestoreRegs: + // have to load and save at the same time + mov %rax, [%rdi+RBP_OFFSET] + mov %rcx, [%rdi+RBX_OFFSET] + mov %rdx, [%rdi+R12_OFFSET] + mov [%rdi+RBP_OFFSET], %rbp + mov [%rdi+RBX_OFFSET], %rbx + mov [%rdi+R12_OFFSET], %r12 + mov %rbp, %rax + mov %rbx, %rcx + mov %r12, %rdx + mov %rax, [%rdi+R13_OFFSET] + mov %rcx, [%rdi+R14_OFFSET] + mov %rdx, [%rdi+R15_OFFSET] + mov [%rdi+R13_OFFSET], %r13 + mov [%rdi+R14_OFFSET], %r14 + mov [%rdi+R15_OFFSET], %r15 + mov %r13, %rax + mov %r14, %rcx + mov %r15, %rdx + +so_call_CallFn: + mov [g_pCurrentRoutine], %rdi + + // swap the stack + mov %rax, [%rdi+STACK_OFFSET] + mov [%rdi+STACK_OFFSET], %rsp + mov %rsp, %rax + mov %rax, [%rdi+FUNC_OFFSET] + mov %rdi, [%rdi+DATA_OFFSET] + + jmp %rax + +.globl so_resume + .type so_resume, @function +so_resume: + mov %rdi, [g_pCurrentRoutine] + mov %rax, [%rdi+RBP_OFFSET] + mov %rcx, [%rdi+RBX_OFFSET] + mov %rdx, [%rdi+R12_OFFSET] + mov [%rdi+RBP_OFFSET], %rbp + mov [%rdi+RBX_OFFSET], %rbx + mov [%rdi+R12_OFFSET], %r12 + mov %rbp, %rax + mov %rbx, %rcx + mov %r12, %rdx + mov %rax, [%rdi+R13_OFFSET] + mov %rcx, [%rdi+R14_OFFSET] + mov %rdx, [%rdi+R15_OFFSET] + mov [%rdi+R13_OFFSET], %r13 + mov [%rdi+R14_OFFSET], %r14 + mov [%rdi+R15_OFFSET], %r15 + mov %r13, %rax + mov %r14, %rcx + mov %r15, %rdx + + // put the return address in pcalladdr + mov %rsi, [%rsp] + mov [%rdi], %rsi + add %rsp, 8 // remove the return address + + // swap stack pointers + mov %rax, [%rdi+STACK_OFFSET] + mov [%rdi+STACK_OFFSET], %rsp + mov %rsp, %rax + + ret + +.globl so_exit + .type so_exit, @function +so_exit: + mov %rdi, [g_pCurrentRoutine] + mov %rsp, [%rdi+STACK_OFFSET] + mov %rbp, [%rdi+RBP_OFFSET] + mov %rbx, [%rdi+RBX_OFFSET] + mov %r12, [%rdi+R12_OFFSET] + mov %r13, [%rdi+R13_OFFSET] + mov %r14, [%rdi+R14_OFFSET] + mov %r15, [%rdi+R15_OFFSET] + ret +#else + +.globl so_call + .type so_call, @function +so_call: + mov %eax, dword ptr [%esp+4] + test dword ptr [%eax+24], 1 + jnz RestoreRegs + mov [%eax+8], %ebx + mov [%eax+12], %esi + mov [%eax+16], %edi + mov [%eax+20], %ebp + mov dword ptr [%eax+24], 1 + jmp CallFn +RestoreRegs: + // have to load and save at the same time + mov %ecx, [%eax+8] + mov %edx, [%eax+12] + mov [%eax+8], %ebx + mov [%eax+12], %esi + mov %ebx, %ecx + mov %esi, %edx + mov %ecx, [%eax+16] + mov %edx, [%eax+20] + mov [%eax+16], %edi + mov [%eax+20], %ebp + mov %edi, %ecx + mov %ebp, %edx + +CallFn: + mov [g_pCurrentRoutine], %eax + mov %ecx, %esp + mov %esp, [%eax+4] + mov [%eax+4], %ecx + + jmp dword ptr [%eax] + +.globl so_resume + .type so_resume, @function +so_resume: + mov %eax, [g_pCurrentRoutine] + mov %ecx, [%eax+8] + mov %edx, [%eax+12] + mov [%eax+8], %ebx + mov [%eax+12], %esi + mov %ebx, %ecx + mov %esi, %edx + mov %ecx, [%eax+16] + mov %edx, [%eax+20] + mov [%eax+16], %edi + mov [%eax+20], %ebp + mov %edi, %ecx + mov %ebp, %edx + + // put the return address in pcalladdr + mov %ecx, [%esp] + mov [%eax], %ecx + add %esp, 4 // remove the return address + + // swap stack pointers + mov %ecx, [%eax+4] + mov [%eax+4], %esp + mov %esp, %ecx + ret + +.globl so_exit + .type so_exit, @function +so_exit: + mov %eax, [g_pCurrentRoutine] + mov %esp, [%eax+4] + mov %ebx, [%eax+8] + mov %esi, [%eax+12] + mov %edi, [%eax+16] + mov %ebp, [%eax+20] + ret + +#endif diff --git a/pcsx2/IPU/acoroutine.asm b/pcsx2/IPU/acoroutine.asm new file mode 100644 index 0000000..4214ed5 --- /dev/null +++ b/pcsx2/IPU/acoroutine.asm @@ -0,0 +1,140 @@ +; Pcsx2 - Pc Ps2 Emulator +; Copyright (C) 2002-2007 Pcsx2 Team +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. + +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +;; x86-64 coroutine fucntions +extern g_pCurrentRoutine:ptr + +.code + +so_call proc public + test dword ptr [rcx+88], 1 + jnz so_call_RestoreRegs + mov [rcx+24], rbp + mov [rcx+16], rbx + mov [rcx+32], r12 + mov [rcx+40], r13 + mov [rcx+48], r14 + mov [rcx+56], r15 + mov [rcx+64], rsi + mov [rcx+72], rdi + mov dword ptr [rcx+88], 1 + jmp so_call_CallFn +so_call_RestoreRegs: + ;; have to load and save at the same time + ;; rbp, rbx, r12 + mov rax, [rcx+24] + mov r8, [rcx+16] + mov rdx, [rcx+32] + mov [rcx+24], rbp + mov [rcx+16], rbx + mov [rcx+32], r12 + mov rbp, rax + mov rbx, r8 + mov r12, rdx + ;; r13, r14, r15 + mov rax, [rcx+40] + mov r8, [rcx+48] + mov rdx, [rcx+56] + mov [rcx+40], r13 + mov [rcx+48], r14 + mov [rcx+56], r15 + mov r13, rax + mov r14, r8 + mov r15, rdx + + ;; rsi, rdi + mov rax, [rcx+64] + mov rdx, [rcx+72] + mov [rcx+64], rsi + mov [rcx+72], rdi + mov rsi, rax + mov rdi, rdx + +so_call_CallFn: + mov [g_pCurrentRoutine], rcx + + ;; swap the stack + mov rax, [rcx+8] + mov [rcx+8], rsp + mov rsp, rax + mov rax, [rcx+0] + mov rcx, [rcx+80] + + jmp rax + +so_call endp + +; so_resume +so_resume proc public + ;; rbp, rbx, r12 + mov rcx, [g_pCurrentRoutine] + mov rax, [rcx+24] + mov r8, [rcx+16] + mov rdx, [rcx+32] + mov [rcx+24], rbp + mov [rcx+16], rbx + mov [rcx+32], r12 + mov rbp, rax + mov rbx, r8 + mov r12, rdx + ;; r13, r14, r15 + mov rax, [rcx+40] + mov r8, [rcx+48] + mov rdx, [rcx+56] + mov [rcx+40], r13 + mov [rcx+48], r14 + mov [rcx+56], r15 + mov r13, rax + mov r14, r8 + mov r15, rdx + ;; rsi, rdi + mov rax, [rcx+64] + mov rdx, [rcx+72] + mov [rcx+64], rsi + mov [rcx+72], rdi + mov rsi, rax + mov rdi, rdx + + ;; put the return address in pcalladdr + mov rax, [rsp] + mov [rcx], rax + add rsp, 8 ;; remove the return address + + ;; swap stack pointers + mov rax, [rcx+8] + mov [rcx+8], rsp + mov rsp, rax + + ret + +so_resume endp + +so_exit proc public + mov rcx, [g_pCurrentRoutine] + mov rsp, [rcx+8] + mov rbp, [rcx+24] + mov rbx, [rcx+16] + mov r12, [rcx+32] + mov r13, [rcx+40] + mov r14, [rcx+48] + mov r15, [rcx+56] + mov rsi, [rcx+64] + mov rdi, [rcx+72] + ret +so_exit endp + +end \ No newline at end of file diff --git a/pcsx2/IPU/coroutine.c b/pcsx2/IPU/coroutine.c new file mode 100644 index 0000000..f5253b7 --- /dev/null +++ b/pcsx2/IPU/coroutine.c @@ -0,0 +1,172 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PS2Etypes.h" +#include "coroutine.h" + +typedef struct s_coroutine { + void* pcalladdr; + void *pcurstack; +#ifdef __x86_64__ + uptr storerbx, storerbp, r12, r13, r14, r15; +#ifdef _MSC_VER + // msft also has rsi and rdi as non-volatile + uptr storersi, storerdi; +#endif + + void* data; +#else + uptr storeebx, storeesi, storeedi, storeebp; +#endif + int restore; // if nonzero, restore the registers + int alloc; + //struct s_coroutine *caller; + //struct s_coroutine *restarget; + +} coroutine; + +#define CO_STK_ALIGN 256 +#define CO_STK_COROSIZE ((sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1)) +#define CO_MIN_SIZE (4 * 1024) + +coroutine* g_pCurrentRoutine; + +coroutine_t so_create(void (*func)(void *), void *data, void *stack, int size) +{ + void* endstack; + int alloc = 0, r = CO_STK_COROSIZE; + coroutine *co; + + if ((size &= ~(sizeof(long) - 1)) < CO_MIN_SIZE) + return NULL; + if (!stack) { + size = (size + sizeof(coroutine) + CO_STK_ALIGN - 1) & ~(CO_STK_ALIGN - 1); + stack = malloc(size); + if (!stack) + return NULL; + alloc = size; + } + endstack = (char*)stack + size - 64; + co = stack; + stack = (char *) stack + CO_STK_COROSIZE; + *(void**)endstack = NULL; + *(void**)((char*)endstack+sizeof(void*)) = data; +#ifdef __x86_64__ + co->data = data; +#endif + co->alloc = alloc; + co->pcalladdr = (void*)func; + co->pcurstack = endstack; + return co; +} + +void so_delete(coroutine_t coro) +{ + coroutine *co = (coroutine *) coro; + assert( co != NULL ); + if (co->alloc) + free(co); +} + +// see acoroutines.S and acoroutines.asm for other asm implementations +#if defined(_MSC_VER) && !defined(__x86_64__) + +__declspec(naked) void so_call(coroutine_t coro) +{ + __asm { + mov eax, dword ptr [esp+4] + test dword ptr [eax+24], 1 + jnz RestoreRegs + mov [eax+8], ebx + mov [eax+12], esi + mov [eax+16], edi + mov [eax+20], ebp + mov dword ptr [eax+24], 1 + jmp CallFn +RestoreRegs: + // have to load and save at the same time + mov ecx, [eax+8] + mov edx, [eax+12] + mov [eax+8], ebx + mov [eax+12], esi + mov ebx, ecx + mov esi, edx + mov ecx, [eax+16] + mov edx, [eax+20] + mov [eax+16], edi + mov [eax+20], ebp + mov edi, ecx + mov ebp, edx + +CallFn: + mov [g_pCurrentRoutine], eax + mov ecx, esp + mov esp, [eax+4] + mov [eax+4], ecx + + jmp dword ptr [eax] + } +} + +__declspec(naked) void so_resume(void) +{ + __asm { + mov eax, [g_pCurrentRoutine] + mov ecx, [eax+8] + mov edx, [eax+12] + mov [eax+8], ebx + mov [eax+12], esi + mov ebx, ecx + mov esi, edx + mov ecx, [eax+16] + mov edx, [eax+20] + mov [eax+16], edi + mov [eax+20], ebp + mov edi, ecx + mov ebp, edx + + // put the return address in pcalladdr + mov ecx, [esp] + mov [eax], ecx + add esp, 4 // remove the return address + + // swap stack pointers + mov ecx, [eax+4] + mov [eax+4], esp + mov esp, ecx + ret + } +} + +__declspec(naked) void so_exit(void) +{ + __asm { + mov eax, [g_pCurrentRoutine] + mov esp, [eax+4] + mov ebx, [eax+8] + mov esi, [eax+12] + mov edi, [eax+16] + mov ebp, [eax+20] + ret + } +} +#endif diff --git a/pcsx2/IPU/coroutine.h b/pcsx2/IPU/coroutine.h new file mode 100644 index 0000000..4197cbd --- /dev/null +++ b/pcsx2/IPU/coroutine.h @@ -0,0 +1,39 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PCSX2_COROUTINE_LIB +#define PCSX2_COROUTINE_LIB + +#ifdef __cplusplus +extern "C" { +#endif + +// low level coroutine library +typedef void *coroutine_t; + +coroutine_t so_create(void (*func)(void *), void *data, void *stack, int size); +void so_delete(coroutine_t coro); +void so_call(coroutine_t coro); +void so_resume(void); +void so_exit(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pcsx2/IPU/idct_mmx.obj b/pcsx2/IPU/idct_mmx.obj new file mode 100644 index 0000000000000000000000000000000000000000..9f7d3136085bf4a54addc94ef8f77313e62d4963 GIT binary patch literal 11510 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 HNu%)(hlkEg literal 0 HcmV?d00001 diff --git a/pcsx2/IPU/mpeg2lib/Idct.c b/pcsx2/IPU/mpeg2lib/Idct.c new file mode 100644 index 0000000..c6f3ce8 --- /dev/null +++ b/pcsx2/IPU/mpeg2lib/Idct.c @@ -0,0 +1,301 @@ +/* + * idct.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//#include +#include "Common.h" + +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ +#define clp(val,res) res = (val < 0) ? 0 : ((val > 255) ? 255 : val); +#define clp2(val,res) res = (val < -255) ? -255 : ((val > 255) ? 255 : val); +/* idct main entry point */ +void (* mpeg2_idct_copy) (s16 * block, u8 * dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16 * dest, int stride); + +/* + * In legal streams, the IDCT output should be between -384 and +384. + * In corrupted streams, it is possible to force the IDCT output to go + * to +-3826 - this is the worst case for a column IDCT where the + * column inputs are 16-bit values. + */ +static u8 clip_lut[1024]; +#define CLIP(i) ((clip_lut+384)[(i)]) + +#if 0 +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + t0 = W0*d0 + W1*d1; \ + t1 = W0*d1 - W1*d0; \ +} while (0) +#else +#define BUTTERFLY(t0,t1,W0,W1,d0,d1) \ +do { \ + int tmp = W0 * (d0 + d1); \ + t0 = tmp + (W1 - W0) * d1; \ + t1 = tmp - (W1 + W0) * d0; \ +} while (0) +#endif + +static void idct_row (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + /* shortcut */ + if (!(block[1] | ((s32 *)block)[1] | ((s32 *)block)[2] | + ((s32 *)block)[3])) { + u32 tmp = (u16) (block[0] << 3); + tmp |= tmp << 16; + ((s32 *)block)[0] = tmp; + ((s32 *)block)[1] = tmp; + ((s32 *)block)[2] = tmp; + ((s32 *)block)[3] = tmp; + return; + } + + d0 = (block[0] << 11) + 128; + d1 = block[1]; + d2 = block[2] << 11; + d3 = block[3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[4]; + d1 = block[5]; + d2 = block[6]; + d3 = block[7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 -= t2; + t1 -= t3; + b1 = ((t0 + t1) * 181) >> 8; + b2 = ((t0 - t1) * 181) >> 8; + + block[0] = (a0 + b0) >> 8; + block[1] = (a1 + b1) >> 8; + block[2] = (a2 + b2) >> 8; + block[3] = (a3 + b3) >> 8; + block[4] = (a3 - b3) >> 8; + block[5] = (a2 - b2) >> 8; + block[6] = (a1 - b1) >> 8; + block[7] = (a0 - b0) >> 8; +} + +static void idct_col (s16 * const block) +{ + int d0, d1, d2, d3; + int a0, a1, a2, a3, b0, b1, b2, b3; + int t0, t1, t2, t3; + + d0 = (block[8*0] << 11) + 65536; + d1 = block[8*1]; + d2 = block[8*2] << 11; + d3 = block[8*3]; + t0 = d0 + d2; + t1 = d0 - d2; + BUTTERFLY (t2, t3, W6, W2, d3, d1); + a0 = t0 + t2; + a1 = t1 + t3; + a2 = t1 - t3; + a3 = t0 - t2; + + d0 = block[8*4]; + d1 = block[8*5]; + d2 = block[8*6]; + d3 = block[8*7]; + BUTTERFLY (t0, t1, W7, W1, d3, d0); + BUTTERFLY (t2, t3, W3, W5, d1, d2); + b0 = t0 + t2; + b3 = t1 + t3; + t0 = (t0 - t2) >> 8; + t1 = (t1 - t3) >> 8; + b1 = (t0 + t1) * 181; + b2 = (t0 - t1) * 181; + + block[8*0] = (a0 + b0) >> 17; + block[8*1] = (a1 + b1) >> 17; + block[8*2] = (a2 + b2) >> 17; + block[8*3] = (a3 + b3) >> 17; + block[8*4] = (a3 - b3) >> 17; + block[8*5] = (a2 - b2) >> 17; + block[8*6] = (a1 - b1) >> 17; + block[8*7] = (a0 - b0) >> 17; +} + +static void mpeg2_idct_copy_c (s16 * block, u8 * dest, + const int stride) +{ + int i; + + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = CLIP (block[0]); + dest[1] = CLIP (block[1]); + dest[2] = CLIP (block[2]); + dest[3] = CLIP (block[3]); + dest[4] = CLIP (block[4]); + dest[5] = CLIP (block[5]); + dest[6] = CLIP (block[6]); + dest[7] = CLIP (block[7]); + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void mpeg2_idct_add_c (const int last, s16 * block, + /*u8*/s16 * dest, const int stride) +{ + int i; + + if (last != 129 || (block[0] & 7) == 4) { + for (i = 0; i < 8; i++) + idct_row (block + 8 * i); + for (i = 0; i < 8; i++) + idct_col (block + i); + do { + dest[0] = block[0]; + dest[1] = block[1]; + dest[2] = block[2]; + dest[3] = block[3]; + dest[4] = block[4]; + dest[5] = block[5]; + dest[6] = block[6]; + dest[7] = block[7]; + + block[0] = 0; block[1] = 0; block[2] = 0; block[3] = 0; + block[4] = 0; block[5] = 0; block[6] = 0; block[7] = 0; + + dest += stride; + block += 8; + } while (--i); + } else { + int DC; + + DC = (block[0] + 4) >> 3; + block[0] = block[63] = 0; + i = 8; + do { + dest[0] = DC; + dest[1] = DC; + dest[2] = DC; + dest[3] = DC; + dest[4] = DC; + dest[5] = DC; + dest[6] = DC; + dest[7] = DC; + dest += stride; + } while (--i); + } +} + +u8 mpeg2_scan_norm[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +u8 mpeg2_scan_alt[64] = { + /* Alternate scan pattern */ + 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 +}; + +/* idct_mmx.c */ +void mpeg2_idct_copy_mmxext (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmxext (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_copy_mmx (s16 * block, u8 * dest, int stride); +void mpeg2_idct_add_mmx (int last, s16 * block, + s16 * dest, int stride); +void mpeg2_idct_mmx_init (void); + +void mpeg2_idct_init() +{ +#if !defined(_MSC_VER) || _MSC_VER < 1400 // ignore vc2005 and beyond + int i, j; + +/* if(hasMultimediaExtensions == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmx; + mpeg2_idct_add = mpeg2_idct_add_mmx; + mpeg2_idct_mmx_init (); + }else if(hasMultimediaExtensionsExt == 1) + { + mpeg2_idct_copy = mpeg2_idct_copy_mmxext; + mpeg2_idct_add = mpeg2_idct_add_mmxext; + mpeg2_idct_mmx_init (); + }else*/ + { + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } + } + +#else //blah vcnet2005 idiocity :D + int i,j; + mpeg2_idct_copy = mpeg2_idct_copy_c; + mpeg2_idct_add = mpeg2_idct_add_c; + for (i = -384; i < 640; i++) + clip_lut[i+384] = (i < 0) ? 0 : ((i > 255) ? 255 : i); + for (i = 0; i < 64; i++) { + j = mpeg2_scan_norm[i]; + mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + j = mpeg2_scan_alt[i]; + mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); + } +#endif +} diff --git a/pcsx2/IPU/mpeg2lib/Makefile.am b/pcsx2/IPU/mpeg2lib/Makefile.am new file mode 100644 index 0000000..93e7a87 --- /dev/null +++ b/pcsx2/IPU/mpeg2lib/Makefile.am @@ -0,0 +1,4 @@ +INCLUDES = -I@srcdir@/../ -I@srcdir@/../../ +noinst_LIBRARIES = libmpeg2IPU.a + +libmpeg2IPU_a_SOURCES = Idct.c Mpeg.c Mpeg.h Vlc.h \ No newline at end of file diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.c b/pcsx2/IPU/mpeg2lib/Mpeg.c new file mode 100644 index 0000000..84d1b8f --- /dev/null +++ b/pcsx2/IPU/mpeg2lib/Mpeg.c @@ -0,0 +1,1280 @@ +/* + * Mpeg.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Mpeg.h" +#include "Vlc.h" +#include "coroutine.h" + +extern void (* mpeg2_idct_copy) (s16 * block, u8* dest, int stride); +/* JayteeMaster: changed dest to 16 bit signed */ +extern void (* mpeg2_idct_add) (int last, s16 * block, + /*u8*/s16* dest, int stride); + +extern int FIFOfrom_write(u32* value, int size); + +/* JayteeMaster: remove static attribute */ +/*static */int non_linear_quantizer_scale [] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 18, 20, 22, + 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 104, 112 +}; + +extern tIPU_BP g_BP; + +/* Bitstream and buffer needs to be realocated inorder for sucessful + reading of the old data. Here the old data stored in the 2nd slot + of the internal buffer is copied to 1st slot, and the new data read + into 1st slot is copied to the 2nd slot. Which will later be copied + back to the 1st slot when 128bits have been read. +*/ +extern void ReorderBitstream(); + +int get_macroblock_modes (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int macroblock_modes; + const MBtab * tab; + + switch (decoder->coding_type) { + case I_TYPE: + + macroblock_modes = UBITS (bit_buf, 2); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_I + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if ((! (decoder->frame_pred_frame_dct)) && + (decoder->picture_structure == FRAME_PICTURE)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + + return macroblock_modes; + + case P_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + + tab = MB_P + (macroblock_modes>>1); + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case B_TYPE: + + macroblock_modes = UBITS (bit_buf, 6); + + if( macroblock_modes == 0 ) + return 0; // error + tab = MB_B + macroblock_modes; + DUMPBITS (bit_buf, bits, tab->len); + macroblock_modes = tab->modes; + + if (decoder->picture_structure != FRAME_PICTURE) { + if (! (macroblock_modes & MACROBLOCK_INTRA)) { + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + } + return macroblock_modes; + } else if (decoder->frame_pred_frame_dct) { + /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ + macroblock_modes |= MC_FRAME; + return macroblock_modes; + } else { + if (macroblock_modes & MACROBLOCK_INTRA) + goto intra; + macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; + DUMPBITS (bit_buf, bits, 2); + if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { + intra: + macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; + DUMPBITS (bit_buf, bits, 1); + } + return macroblock_modes; + } + + case D_TYPE: + + macroblock_modes = UBITS (bit_buf, 1); + if( macroblock_modes == 0 ) + return 0; // error + DUMPBITS (bit_buf, bits, 1); + return MACROBLOCK_INTRA; + + default: + return 0; + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_quantizer_scale (decoder_t * const decoder) +{ + int quantizer_scale_code; + + quantizer_scale_code = UBITS (decoder->bitstream_buf, 5); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 5); + + if (decoder->q_scale_type) return non_linear_quantizer_scale [quantizer_scale_code]; + else return quantizer_scale_code << 1; +} + +static int get_coded_block_pattern (decoder_t * const decoder) +{ + const CBPtab * tab; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + if (decoder->bitstream_buf >= 0x20000000) { + tab = CBP_7 + (UBITS (decoder->bitstream_buf, 7) - 16); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; + } + + tab = CBP_9 + UBITS (decoder->bitstream_buf, 9); + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, tab->len); + return tab->cbp; +} + +static int get_luma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_lum_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 3); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static int get_chroma_dc_dct_diff (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DCtab * tab; + int size; + int dc_diff; + + if (bit_buf < 0xf8000000) { + tab = DC_chrom_5 + UBITS (bit_buf, 5); + size = tab->size; + if (size) { + bits += tab->len + size; + bit_buf <<= tab->len; + dc_diff = + UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + bit_buf <<= size; + return dc_diff; + } else { + DUMPBITS (bit_buf, bits, 2); + return 0; + } + } + + tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); + size = tab->size; + DUMPBITS (bit_buf, bits, tab->len + 1); + NEEDBITS (bit_buf, bits, bit_ptr); + dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); + DUMPBITS (bit_buf, bits, size); + return dc_diff; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +#define SATURATE(val) \ +do { \ + if (((u32)(val + 2048) > 4095)) \ + val = SBITS (val, 1) ^ 2047; \ +} while (0) + +static void get_intra_block_B14 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static void get_intra_block_B15 (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + u32 bit_buf; + u8 * bit_ptr; + int bits; + s16 * dest; + + dest = decoder->DCTblock; + i = 0; + mismatch = ~dest[0]; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x04000000) { + + tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) { + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else { + /* end of block. I commented out this code because if we */ + /* dont exit here we will still exit at the later test :) */ + /* if (i >= 128) break; */ /* end of block */ + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) break; /* illegal, check against buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (SBITS (bit_buf, 12) * quantizer_scale * quant_matrix[i]) / 16; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + } + } else if (bit_buf >= 0x02000000) { + tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>28) != 0x6 ) + ipuRegs->ctrl.ECD = 1; + DUMPBITS (bit_buf, bits, 4); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_non_intra_block (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + int mismatch; + const DCTtab * tab; + s16 * dest; + + i = -1; + mismatch = 1; + dest = decoder->DCTblock; + + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = 2 * (SBITS (bit_buf, 12) + SBITS (bit_buf, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + SATURATE (val); + dest[j] = val; + mismatch ^= val; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + dest[63] ^= mismatch & 1; + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +static void get_mpeg1_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = 0; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (tab->level * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) >> 4; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; +} + +static int get_mpeg1_non_intra_block (decoder_t * const decoder) +{ + int i; + int j; + int val; + const u8 * scan = decoder->scan; + const u8 * quant_matrix = decoder->non_intra_quantizer_matrix; + int quantizer_scale = decoder->quantizer_scale; + const DCTtab * tab; + u32 bit_buf; + int bits; + u8 * bit_ptr; + s16 * dest; + + i = -1; + dest = decoder->DCTblock; + + bit_buf = decoder->bitstream_buf; + bits = decoder->bitstream_bits; + bit_ptr = decoder->bitstream_ptr; + + NEEDBITS (bit_buf, bits, bit_ptr); + if (bit_buf >= 0x28000000) { + tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); + goto entry_1; + } else + goto entry_2; + + while (1) { + if (bit_buf >= 0x28000000) { + + tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); + + entry_1: + i += tab->run; + if (i >= 64) + break; /* end of block */ + + normal_code: + j = scan[i]; + bit_buf <<= tab->len; + bits += tab->len + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = ((2*tab->level+1) * quantizer_scale * quant_matrix[i]) >> 5; + + /* oddification */ + val = (val - 1) | 1; + + /* if (bitstream_get (1)) val = -val; */ + val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); + + SATURATE (val); + dest[j] = val; + + bit_buf <<= 1; + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } + + entry_2: + if (bit_buf >= 0x04000000) { + + tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); + + i += tab->run; + if (i < 64) + goto normal_code; + + /* escape code */ + + i += UBITS (bit_buf << 6, 6) - 64; + if (i >= 64) + break; /* illegal, check needed to avoid buffer overflow */ + + j = scan[i]; + + DUMPBITS (bit_buf, bits, 12); + NEEDBITS (bit_buf, bits, bit_ptr); + val = SBITS (bit_buf, 8); + if (! (val & 0x7f)) { + DUMPBITS (bit_buf, bits, 8); + val = UBITS (bit_buf, 8) + 2 * val; + } + val = 2 * (val + SBITS (val, 1)) + 1; + /* JayteeMaster: 10 points! Replaced quant_matrix[j] by quant_matrix[i] as should be */ + val = (val * quantizer_scale * quant_matrix[i]) / 32; + + /* oddification */ + val = (val + ~SBITS (val, 1)) | 1; + + SATURATE (val); + dest[j] = val; + + DUMPBITS (bit_buf, bits, 8); + NEEDBITS (bit_buf, bits, bit_ptr); + + continue; + + } else if (bit_buf >= 0x02000000) { + tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00800000) { + tab = DCT_13 + (UBITS (bit_buf, 13) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else if (bit_buf >= 0x00200000) { + tab = DCT_15 + (UBITS (bit_buf, 15) - 16); + i += tab->run; + if (i < 64) + goto normal_code; + } else { + tab = DCT_16 + UBITS (bit_buf, 16); + bit_buf <<= 16; + GETWORD(&bit_buf,bits+16); + i += tab->run; + if (i < 64) + goto normal_code; + } + break; /* illegal, check needed to avoid buffer overflow */ + } + if( (bit_buf>>30) != 0x2 ) + ipuRegs->ctrl.ECD = 1; + + DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ + decoder->bitstream_buf = bit_buf; + decoder->bitstream_bits = bits; + return i; +} + +static void slice_intra_DCT (decoder_t * const decoder, const int cc, + u8 * const dest, const int stride) +{ + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + /* Get the intra DC coefficient and inverse quantize it */ + if (cc == 0) decoder->dc_dct_pred[0] += get_luma_dc_dct_diff (decoder); + else decoder->dc_dct_pred[cc] += get_chroma_dc_dct_diff (decoder); + decoder->DCTblock[0] = decoder->dc_dct_pred[cc] << (3 - decoder->intra_dc_precision); + + if (decoder->mpeg1) get_mpeg1_intra_block (decoder); + else if (decoder->intra_vlc_format){ + get_intra_block_B15 (decoder); + }else{ + get_intra_block_B14 (decoder); + } + + mpeg2_idct_copy (decoder->DCTblock, dest, stride); +} + +/* JayteeMaster: changed dest to 16 bit signed */ +static void slice_non_intra_DCT (decoder_t * const decoder, + /*u8*/s16 * const dest, const int stride){ + int last; + memset(decoder->DCTblock,0,sizeof(decoder->DCTblock)); + if (decoder->mpeg1) last = get_mpeg1_non_intra_block (decoder); + else last = get_non_intra_block (decoder); + + mpeg2_idct_add (last, decoder->DCTblock, dest, stride); +} + +extern int coded_block_pattern; +extern u8 FillInternalBuffer(u32 * pointer, u32 advance); +extern decoder_t g_decoder; +extern int g_nIPU0Data; // or 0x80000000 whenever transferring +extern u8* g_pIPU0Pointer; + +void mpeg2sliceIDEC(void* pdone) +{ + u32 read; + decoder_t * decoder = &g_decoder; + + *(int*)pdone = 0; + bitstream_init(decoder); + + decoder->dc_dct_pred[0] = + decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + decoder->mbc=0; + + if (UBITS (decoder->bitstream_buf, 2) == 0) + { + ipuRegs->ctrl.SCD = 0; + }else{ + while (1) { + int DCT_offset, DCT_stride; + int mba_inc; + const MBAtab * mba; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + decoder->macroblock_modes = get_macroblock_modes (decoder); + + /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */ + if (decoder->macroblock_modes & MACROBLOCK_QUANT)//only IDEC + decoder->quantizer_scale = get_quantizer_scale (decoder); + + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + + memset(decoder->mb8,0,sizeof(struct macroblock_8)); + memset(decoder->rgb32,0,sizeof(struct rgb32)); + + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + + // Send The MacroBlock via DmaIpuFrom + if (decoder->ofm==0){ + ipu_csc(decoder->mb8, decoder->rgb32, decoder->sgn); + + g_nIPU0Data = 64; + g_pIPU0Pointer = (u8*)decoder->rgb32; + while(g_nIPU0Data > 0) { + read = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ) + so_resume(); + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + else{ + //ipu_dither(decoder->mb8, decoder->rgb16, decoder->dte); + ipu_csc(decoder->mb8, decoder->rgb32, decoder->dte); + ipu_dither2(decoder->rgb32, decoder->rgb16, decoder->dte); + + g_nIPU0Data = 32; + g_pIPU0Pointer = (u8*)decoder->rgb16; + while(g_nIPU0Data > 0) { + read = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( read == 0 ){ + so_resume(); + } + else { + g_pIPU0Pointer += read*16; + g_nIPU0Data -= read; + } + } + } + decoder->mbc++; + } + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + + mba_inc = 0; + while (1) { + if (decoder->bitstream_buf >= 0x10000000) { + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + break; + } else if (decoder->bitstream_buf >= 0x03000000) { + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + break; + } else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + mba_inc += 33; + /* pass through */ + case 15: /* macroblock_stuffing (MPEG1 only) */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + continue; + default: /* end of slice/frame, or error? */ + { + int i; + ipuRegs->ctrl.SCD = 1; + ipuRegs->ctrl.ECD=0; + coded_block_pattern=decoder->coded_block_pattern; + + for (i=0; i<2; i++) { + u8 byte; + while(!getBits8(&byte, 0)) + so_resume(); + if (byte == 0) break; + g_BP.BP+= 8; + } + g_BP.BP-=32;//bitstream_init takes 32 bits + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + so_resume(); + } + BigEndian(ipuRegs->top, ipuRegs->top); + + *(int*)pdone = 1; + so_exit(); + } + } + } + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + mba_inc += mba->mba; + + if (mba_inc) { + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + do { + decoder->mbc++; + } while (--mba_inc); + } + } + } + + ipuRegs->ctrl.ECD=!ipuRegs->ctrl.SCD; + + coded_block_pattern=decoder->coded_block_pattern; + + g_BP.BP-=32;//bitstream_init takes 32 bits + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + so_resume(); + } + BigEndian(ipuRegs->top, ipuRegs->top); + + *(int*)pdone = 1; + so_exit(); +} + +void mpeg2_slice(void* pdone) +{ + int DCT_offset, DCT_stride; + u8 bit8=0; + u32 fp = g_BP.FP; + u32 bp; + decoder_t * decoder = &g_decoder; + u32 size = 0; + + *(int*)pdone = 0; + ipuRegs->ctrl.ECD = 0; + + memset(decoder->mb8,0,sizeof(struct macroblock_8)); + memset(decoder->mb16,0,sizeof(struct macroblock_16)); + + bitstream_init (decoder); + + if (decoder->dcr) + decoder->dc_dct_pred[0] = decoder->dc_dct_pred[1] = + decoder->dc_dct_pred[2] = 128 << decoder->intra_dc_precision; + + NEEDBITS (decoder->bitstream_buf, decoder->bitstream_bits, decoder->bitstream_ptr); + if (decoder->macroblock_modes & DCT_TYPE_INTERLACED) { + DCT_offset = decoder->stride; + DCT_stride = decoder->stride * 2; + } else { + DCT_offset = decoder->stride * 8; + DCT_stride = decoder->stride; + } + if (decoder->macroblock_modes & MACROBLOCK_INTRA) { + decoder->coded_block_pattern = 0x3F;//all 6 blocks + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + 8, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset, DCT_stride); + slice_intra_DCT (decoder, 0, (u8*)decoder->mb8->Y + DCT_offset + 8, DCT_stride); + slice_intra_DCT (decoder, 1, (u8*)decoder->mb8->Cb, decoder->stride>>1); + slice_intra_DCT (decoder, 2, (u8*)decoder->mb8->Cr, decoder->stride>>1); + ipu_copy(decoder->mb8,decoder->mb16); + } else { + if (decoder->macroblock_modes & MACROBLOCK_PATTERN) { + decoder->coded_block_pattern = get_coded_block_pattern (decoder); + /* JayteeMaster: changed from mb8 to mb16 and from u8 to s16 */ + if (decoder->coded_block_pattern & 0x20) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y, DCT_stride); + if (decoder->coded_block_pattern & 0x10) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x08) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset, DCT_stride); + if (decoder->coded_block_pattern & 0x04) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Y + DCT_offset + 8, DCT_stride); + if (decoder->coded_block_pattern & 0x2) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cb, decoder->stride>>1); + if (decoder->coded_block_pattern & 0x1) slice_non_intra_DCT (decoder, (s16*)decoder->mb16->Cr, decoder->stride>>1); + + } + } + + //Send The MacroBlock via DmaIpuFrom + size = 0; // Reset + + ipuRegs->ctrl.SCD=0; + coded_block_pattern=decoder->coded_block_pattern; + + //FillInternalBuffer(&g_BP.BP, 1); + + bp = g_BP.BP; + g_BP.BP+=decoder->bitstream_bits-16; + + // BP goes from 0 to 128, so negative values mean to read old buffer + // so we minus from 128 to get the correct BP + if((int)g_BP.BP < 0) { + g_BP.BP = 128 + (int)g_BP.BP; + + // After BP is positioned correctly, we need to reload the old buffer + // so that reading may continue properly + ReorderBitstream(); + } + + decoder->mbc = 1; + g_nIPU0Data = 48; + g_pIPU0Pointer = (u8*)decoder->mb16; + while(g_nIPU0Data > 0) { + size = FIFOfrom_write((u32*)g_pIPU0Pointer,g_nIPU0Data); + if( size == 0 ) + so_resume(); + else { + g_pIPU0Pointer += size*16; + g_nIPU0Data -= size; + } + } + + IPU_LOG("BDEC %x, %d\n",g_BP.BP,g_BP.FP); + + while( !getBits8((u8*)&bit8, 0) ) + so_resume(); + if (bit8==0) ipuRegs->ctrl.SCD = 1; + + while(!getBits32((u8*)&ipuRegs->top, 0)) + { + so_resume(); + } + BigEndian(ipuRegs->top, ipuRegs->top); + + *(int*)pdone = 1; + so_exit(); +} + +int get_motion_delta (decoder_t * const decoder, + const int f_code) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + int delta; + int sign; + const MVtab * tab; + + if ( (bit_buf & 0x80000000) ) { + DUMPBITS (bit_buf, bits, 1); + return 0x00010000; + } else if ( (bit_buf & 0xf0000000) || ((bit_buf & 0xfc000000)==0x0c000000) ) { + + tab = MV_4 + UBITS (bit_buf, 4); + delta = (tab->delta << f_code) + 1; + bits += tab->len + f_code + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) + delta += UBITS (bit_buf, f_code); + bit_buf <<= f_code; + + return (delta ^ sign) - sign; + + } else { + + tab = MV_10 + UBITS (bit_buf, 10); + delta = (tab->delta << f_code) + 1; + bits += tab->len + 1; + bit_buf <<= tab->len; + + sign = SBITS (bit_buf, 1); + bit_buf <<= 1; + + if (f_code) { + NEEDBITS (bit_buf, bits, bit_ptr); + delta += UBITS (bit_buf, f_code); + DUMPBITS (bit_buf, bits, f_code); + } + + return (delta ^ sign) - sign; + + } +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_dmv (decoder_t * const decoder) +{ +#define bit_buf (decoder->bitstream_buf) +#define bits (decoder->bitstream_bits) +#define bit_ptr (decoder->bitstream_ptr) + + const DMVtab * tab; + + tab = DMV_2 + UBITS (bit_buf, 2); + DUMPBITS (bit_buf, bits, tab->len); + return tab->dmv; +#undef bit_buf +#undef bits +#undef bit_ptr +} + +int get_macroblock_address_increment(decoder_t * const decoder){ + const MBAtab *mba; + + if (decoder->bitstream_buf >= 0x10000000) + mba = MBA_5 + (UBITS (decoder->bitstream_buf, 5) - 2); + else if (decoder->bitstream_buf >= 0x03000000) + mba = MBA_11 + (UBITS (decoder->bitstream_buf, 11) - 24); + else switch (UBITS (decoder->bitstream_buf, 11)) { + case 8: /* macroblock_escape */ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x23; + case 15: /* macroblock_stuffing (MPEG1 only) */ + if (decoder->mpeg1){ + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, 11); + return 0x22; + } + default: + return 0;//error + } + + DUMPBITS (decoder->bitstream_buf, decoder->bitstream_bits, mba->len); + return mba->mba + 1; +} diff --git a/pcsx2/IPU/mpeg2lib/Mpeg.h b/pcsx2/IPU/mpeg2lib/Mpeg.h new file mode 100644 index 0000000..551ea80 --- /dev/null +++ b/pcsx2/IPU/mpeg2lib/Mpeg.h @@ -0,0 +1,200 @@ +/* + * Mpeg.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MPEG_H__ +#define __MPEG_H__ + +#include "Common.h" + +/* macroblock modes */ +#define MACROBLOCK_INTRA 1 +#define MACROBLOCK_PATTERN 2 +#define MACROBLOCK_MOTION_BACKWARD 4 +#define MACROBLOCK_MOTION_FORWARD 8 +#define MACROBLOCK_QUANT 16 +#define DCT_TYPE_INTERLACED 32 +/* motion_type */ +#define MOTION_TYPE_SHIFT 6 +#define MOTION_TYPE_MASK (3*64) +#define MOTION_TYPE_BASE 64 +#define MC_FIELD (1*64) +#define MC_FRAME (2*64) +#define MC_16X8 (2*64) +#define MC_DMV (3*64) + +/* picture structure */ +#define TOP_FIELD 1 +#define BOTTOM_FIELD 2 +#define FRAME_PICTURE 3 + +/* picture coding type */ +#define I_TYPE 1 +#define P_TYPE 2 +#define B_TYPE 3 +#define D_TYPE 4 + +struct macroblock_8{ + unsigned char Y[16][16]; //0 + unsigned char Cb[8][8]; //1 + unsigned char Cr[8][8]; //2 +}; + +struct macroblock_16{ + short Y[16][16]; //0 + short Cb[8][8]; //1 + short Cr[8][8]; //2 +}; + +struct rgb32{ + unsigned char r, g, b, a; +}; + +struct macroblock_rgb32{ + struct rgb32 c[16][16]; +}; + +struct rgb16{ + unsigned short r:5, g:5, b:5, a:1; +}; + +struct macroblock_rgb16{ + struct rgb16 c[16][16]; +}; + +struct decoder_s { + /* first, state that carries information from one macroblock to the */ + /* next inside a slice, and is never used outside of mpeg2_slice() */ + + /* DCT coefficients - should be kept aligned ! */ + s16 DCTblock[64]; + + /* bit parsing stuff */ + u32 bitstream_buf; /* current 32 bit working set */ + int bitstream_bits; /* used bits in working set */ + u8 * bitstream_ptr; /* buffer with stream data; 128 bits buffer */ + + struct macroblock_8 *mb8; + struct macroblock_16 *mb16; + struct macroblock_rgb32 *rgb32; + struct macroblock_rgb16 *rgb16; + + int stride; + + /* predictor for DC coefficients in intra blocks */ + s16 dc_dct_pred[3]; + + int quantizer_scale; /* remove */ + int dmv_offset; /* remove */ + + /* now non-slice-specific information */ + + /* sequence header stuff */ + u8 *intra_quantizer_matrix; + u8 *non_intra_quantizer_matrix; + + /* picture header stuff */ + + /* what type of picture this is (I, P, B, D) */ + int coding_type; + + /* picture coding extension stuff */ + + /* quantization factor for intra dc coefficients */ + int intra_dc_precision; + /* top/bottom/both fields */ + int picture_structure; + /* bool to indicate all predictions are frame based */ + int frame_pred_frame_dct; + /* bool to indicate whether intra blocks have motion vectors */ + /* (for concealment) */ + int concealment_motion_vectors; + /* bit to indicate which quantization table to use */ + int q_scale_type; + /* bool to use different vlc tables */ + int intra_vlc_format; + /* used for DMV MC */ + int top_field_first; + // Pseudo Sign Offset + int sgn; + // Dither Enable + int dte; + // Output Format + int ofm; + // Macroblock count + int mbc; + // Macroblock type + int macroblock_modes; + // DC Reset + int dcr; + // Coded block pattern + int coded_block_pattern; + + /* stuff derived from bitstream */ + + /* pointer to the zigzag scan we're supposed to be using */ + const u8 * scan; + + int second_field; + + int mpeg1; +}; + +typedef struct decoder_s decoder_t; + +#define IDEC 0 +#define BDEC 1 +void mpeg2sliceIDEC(void* pdone); +void mpeg2_slice(void* pdone); +int get_macroblock_address_increment(decoder_t * const decoder); +int get_macroblock_modes (decoder_t * const decoder); +int get_motion_delta (decoder_t * const decoder, + const int f_code); +int get_dmv (decoder_t * const decoder); +extern int non_linear_quantizer_scale[]; // JayteeMaster: it is needed in Ipu.c + +void ipu_csc(struct macroblock_8 *mb8, struct macroblock_rgb32 *rgb32, int sgn); +void ipu_dither(struct macroblock_8 *mb8, struct macroblock_rgb16 *rgb16, int dte); +void ipu_dither2(struct macroblock_rgb32* rgb32, struct macroblock_rgb16 *rgb16, int dte); +void ipu_vq(struct macroblock_rgb16 *rgb16, u8* indx4); +void ipu_copy(struct macroblock_8 *mb8, struct macroblock_16 *mb16); + +int slice (decoder_t * const decoder, u8 * buffer); +/* idct.c */ +void mpeg2_idct_init (); + +#ifdef _MSC_VER +#define BigEndian(out, in) out = _byteswap_ulong(in) +#else +//#define BigEndian(out, in) \ +// __asm__(".intel_syntax\n" \ +// "bswap %0\n" \ +// ".att_syntax\n" : "=r"(out) : "0"(in) ) + +#define BigEndian(out, in) \ + out = (((((in) >> 24) & 0xFF) << 0) + ((((in) >> 16) & 0xFF) << 8) + \ + ((((in) >> 8) & 0xFF) << 16) + ((((in) >> 0) & 0xFF) << 24)); + +#endif + +#endif//__MPEG_H__ diff --git a/pcsx2/IPU/mpeg2lib/Vlc.h b/pcsx2/IPU/mpeg2lib/Vlc.h new file mode 100644 index 0000000..774d0b6 --- /dev/null +++ b/pcsx2/IPU/mpeg2lib/Vlc.h @@ -0,0 +1,441 @@ +/* + * vlc.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VLC_H__ +#define __VLC_H__ + +#include "IPU.h" +#include "coroutine.h" + +static u8 data[2]; +static u8 dword[4]; +static void GETWORD(u32 * bit_buf,int bits) +{ + while(!getBits16(data,1)) + so_resume(); + *bit_buf |= ((data[0] << 8) | data[1]) << (bits); +} + +static void bitstream_init (decoder_t * decoder){ + decoder->bitstream_bits = -16; + + while( !getBits32(dword, 1) ) + so_resume(); + + decoder->bitstream_buf = (dword[0] << 24) | (dword[1] << 16) | + (dword[2] << 8) |dword[3]; +} + +/* make sure that there are at least 16 valid bits in bit_buf */ +#define NEEDBITS(bit_buf,bits,bit_ptr) \ +do { \ + if (bits > 0) { \ + GETWORD(&bit_buf,bits); \ + bits -= 16; \ + } \ +} while (0) + +/* remove num valid bits from bit_buf */ +#define DUMPBITS(bit_buf,bits,num) \ +do { \ + /*IPU_LOG("DUMPBITS %d\n",num);*/ \ + bit_buf <<= (num); \ + bits += (num); \ +} while (0) + +/* take num bits from the high part of bit_buf and zero extend them */ +#define UBITS(bit_buf,num) (((u32)(bit_buf)) >> (32 - (num))) + +/* take num bits from the high part of bit_buf and sign extend them */ +#define SBITS(bit_buf,num) (((s32)(bit_buf)) >> (32 - (num))) + +typedef struct { + u8 modes; + u8 len; +} MBtab; + +typedef struct { + u8 delta; + u8 len; +} MVtab; + +typedef struct { + s8 dmv; + u8 len; +} DMVtab; + +typedef struct { + u8 cbp; + u8 len; +} CBPtab; + +typedef struct { + u8 size; + u8 len; +} DCtab; + +typedef struct { + u8 run; + u8 level; + u8 len; +} DCTtab; + +typedef struct { + u8 mba; + u8 len; +} MBAtab; + + +#define INTRA MACROBLOCK_INTRA +#define QUANT MACROBLOCK_QUANT + +static const MBtab MB_I [] = { + {INTRA|QUANT, 2}, {INTRA, 1} +}; + +#define MC MACROBLOCK_MOTION_FORWARD +#define CODED MACROBLOCK_PATTERN + +static const MBtab MB_P [] = { + {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, + {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, + {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} +}; + +#define FWD MACROBLOCK_MOTION_FORWARD +#define BWD MACROBLOCK_MOTION_BACKWARD +#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD + +static const MBtab MB_B [] = { + {0, 0}, {INTRA|QUANT, 6}, + {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, + {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, + {INTRA, 5}, {INTRA, 5}, + {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, + {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, + {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} +}; + +#undef INTRA +#undef QUANT +#undef MC +#undef CODED +#undef FWD +#undef BWD +#undef INTER + + +static const MVtab MV_4 [] = { + { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} +}; + +static const MVtab MV_10 [] = { + { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, + { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, + {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, + { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, + { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, + { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} +}; + + +static const DMVtab DMV_2 [] = { + { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} +}; + + +static const CBPtab CBP_7 [] = { + {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7}, + {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7}, + {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6}, + {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6}, + {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, + {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, + {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, + {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, + {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, + {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, + {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, + {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, + {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, + {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, + {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, + {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, + {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3} +}; + +static const CBPtab CBP_9 [] = { + {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9}, + {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9}, + {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8}, + {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8}, + {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8}, + {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8}, + {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8}, + {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8}, + {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8}, + {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8}, + {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8}, + {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8}, + {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8}, + {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8}, + {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8}, + {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8} +}; + +static const DCtab DC_lum_5 [] = { + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, + {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} +}; + +static const DCtab DC_chrom_5 [] = { + {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, + {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, + {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, + {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} +}; + +static const DCtab DC_long [] = { + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, + {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, + {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} +}; + + +static const DCTtab DCT_16 [] = { + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, + { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, + { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, + { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, + { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} +}; + +static const DCTtab DCT_15 [] = { + { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, + { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, + { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, + { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, + { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, + { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, + { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, + { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, + { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, + { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, + { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, + { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} +}; + +static const DCTtab DCT_13 [] = { + { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, + { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, + { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, + { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, + { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, + { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, + { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, + { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, + { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, + { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, + { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, + { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} +}; + +static const DCTtab DCT_B14_10 [] = { + { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, + { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} +}; + +static const DCTtab DCT_B14_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, + { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, + { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, + { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, + { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} +}; + +static const DCTtab DCT_B14AC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} +}; + +static const DCTtab DCT_B14DC_5 [] = { + { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, + { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, + { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} +}; + +static const DCTtab DCT_B15_10 [] = { + { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, + { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} +}; + +static const DCTtab DCT_B15_8 [] = { + { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, + { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, + { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, + { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, + { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, + { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, + { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, + { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, + { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, + { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, + { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, + { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, + { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} +}; + + +static const MBAtab MBA_5 [] = { + {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, + {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, + {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} +}; + +static const MBAtab MBA_11 [] = { + {32, 11}, {31, 11}, {30, 11}, {29, 11}, + {28, 11}, {27, 11}, {26, 11}, {25, 11}, + {24, 11}, {23, 11}, {22, 11}, {21, 11}, + {20, 10}, {20, 10}, {19, 10}, {19, 10}, + {18, 10}, {18, 10}, {17, 10}, {17, 10}, + {16, 10}, {16, 10}, {15, 10}, {15, 10}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {14, 8}, {14, 8}, {14, 8}, {14, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {13, 8}, {13, 8}, {13, 8}, {13, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {12, 8}, {12, 8}, {12, 8}, {12, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {11, 8}, {11, 8}, {11, 8}, {11, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + {10, 8}, {10, 8}, {10, 8}, {10, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, + { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} +}; +#endif//__VLC_H__ diff --git a/pcsx2/IPU/yuv2rgb.asm b/pcsx2/IPU/yuv2rgb.asm new file mode 100644 index 0000000..c571420 --- /dev/null +++ b/pcsx2/IPU/yuv2rgb.asm @@ -0,0 +1,242 @@ +;/******************************************************** +; * Some code. Copyright (C) 2003 by Pascal Massimino. * +; * All Rights Reserved. (http://skal.planet-d.net) * +; * For Educational/Academic use ONLY. See 'LICENSE.TXT'.* +; ********************************************************/ +;////////////////////////////////////////////////////////// +;// NASM macros +;////////////////////////////////////////////////////////// + +%ifdef LINUX + +;////////////////////////////////////////////////////////// +; LINUX / egcs / macros +;////////////////////////////////////////////////////////// + +%macro extrn 1 + extern %1 + %define %1 %1 +%endmacro +%macro globl 1 + global %1 + %define %1 %1 +%endmacro + +%macro DATA 0 +[section data align=16 write alloc USE32] +%endmacro +%macro TEXT 0 +[section text align=16 nowrite alloc exec USE32] +%endmacro + +%endif ; LINUX + +;////////////////////////////////////////////////////////// + +%ifdef WIN32 + +%macro extrn 1 + extern _%1 + %define %1 _%1 +%endmacro + +%macro globl 1 + global _%1 + %define %1 _%1 +%endmacro + +%macro DATA 0 +[section .data align=16 write alloc USE32] +%endmacro +%macro TEXT 0 +[section .text align=16 nowrite alloc exec USE32] +%endmacro + +%endif ; WIN32 + +;////////////////////////////////////////////////////////// +; +; MACRO for timing. NASM. +; Total additional code size is 0xb0. +; this keep code alignment right. + +extrn Skl_Cur_Count_ +extrn Skl_Print_Tics + +%macro SKL_USE_RDSTC 0 +extrn SKL_RDTSC_0_ASM +extrn SKL_RDTSC_1_ASM +extrn SKL_RDTSC_2_ASM +%endmacro +%define SKL_RDTSC_OFFSET 15 ; check value with skl_rdtsc.h... + +%macro SKL_RDTSC_IN 0 + SKL_USE_RDSTC + call SKL_RDTSC_0_ASM +.Skl_RDTSC_Loop_: + call SKL_RDTSC_1_ASM +%endmacro + +%macro SKL_RDTSC_OUT 0 + call SKL_RDTSC_2_ASM + dec dword [Skl_Cur_Count_] + jge near .Skl_RDTSC_Loop_ + push dword 53 + call Skl_Print_Tics +%endmacro + +;////////////////////////////////////////////////////////// + +globl Skl_YUV_To_RGB32_MMX + +;////////////////////////////////////////////////////////////////////// + + ; eax: *U + ; ebx: *V + ; esi: *Y + ; edx: Src_BpS + ; edi: *Dst + ; ebx: Dst_BpS + ; ecx: Counter + +%define RGBp esp+20 +%define Yp esp+16 +%define Up esp+12 +%define Vp esp+8 +%define xCnt esp+4 +%define yCnt esp+0 + +Skl_YUV_To_RGB32_MMX: + + push ebx + push esi + push edi + push ebp + + mov edi, [esp+4 +16] ; RGB + mov ebp, [esp+12 +16] ; Y + mov eax, [esp+16 +16] ; U + mov ebx, [esp+20 +16] ; V + mov edx, [esp+24 +16] ; Src_BpS + mov ecx, [esp+28 +16] ; Width + + lea edi, [edi+4*ecx] ; RGB += Width*sizeof(32b) + lea ebp, [ebp+ecx] ; ebp: Y1 = Y + Width + add edx, ebp ; edx: Y2 = Y1+ BpS + push edi ; [RGBp] + push ebp ; [Yp] + shr ecx, 1 ; Width/=2 + lea eax, [eax+ecx] ; U += W/2 + lea ebx, [ebx+ecx] ; V += W/2 + push eax ; [Up] + push ebx ; [Vp] + + neg ecx ; ecx = -Width/2 + push ecx ; save [xCnt] + push eax ; fake ([yCnt]) + + mov ecx, [esp+32 +40] ; Height + shr ecx, 1 ; /2 + + mov esi, [Up] + mov edi, [Vp] + + jmp .Go + +align 16 +.Loop_y + dec ecx + jg .Add + + add esp, 24 ; rid of all tmp + pop ebp + pop edi + pop esi + pop ebx + + ret + +align 16 +.Add + mov edi, [esp+8 +40] ; Dst_BpS + mov esi, [esp+24 +40] ; Src_BpS + mov edx, [RGBp] + mov ebp, [Yp] + lea edx, [edx+2*edi] ; RGB += 2*Dst_BpS + lea ebp, [ebp+2*esi] ; Y += 2*Src_BpS + mov [RGBp], edx + mov edi, [Vp] + mov [Yp], ebp ; Y1 + lea edx, [ebp+esi] ; Y2 + + lea edi, [edi+esi] ; V += Src_BpS + add esi, [Up] ; U += Src_BpS + mov [Vp], edi + mov [Up], esi + +.Go + mov [yCnt], ecx + mov ecx, [xCnt] + + ; 5210c@640x480 + +.Loop_x ; edi,esi: U,V; ebp,edx: Y1, Y2; ecx: xCnt + + ; R = Y + a.U + ; G = Y + c.V + b.U + ; B = Y + d.V + + movzx eax, byte [edi+ecx+0] + movzx ebx, byte [esi+ecx+0] + movq mm0, [Skl_YUV_Tab32_MMX+0*2048 + eax*8] + movzx eax, byte [edi+ecx+1] + paddw mm0, [Skl_YUV_Tab32_MMX+1*2048 + ebx*8] + movzx ebx, byte [esi+ecx+1] + movq mm4, [Skl_YUV_Tab32_MMX+0*2048 + eax*8] + movzx eax, byte [ebp + 2*ecx+0] + paddw mm4, [Skl_YUV_Tab32_MMX+1*2048 + ebx*8] + movzx ebx, byte [ebp + 2*ecx+1] + + movq mm1, mm0 + movq mm2, mm0 + movq mm3, mm0 + movq mm5, mm4 + movq mm6, mm4 + movq mm7, mm4 + + paddw mm0, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [ebp + 2*ecx+2] + paddw mm1, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + movzx ebx, byte [ebp + 2*ecx+3] + packuswb mm0, mm1 + paddw mm4, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [edx + 2*ecx+0] + paddw mm5, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + + packuswb mm4, mm5 + mov esi, [RGBp] + movzx ebx, byte [edx + 2*ecx+1] + movq [esi+8*ecx+0], mm0 ; 2x32b + movq [esi+8*ecx+8], mm4 ; 2x32b + + paddw mm2, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + movzx eax, byte [edx + 2*ecx+2] + paddw mm3, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + movzx ebx, byte [edx + 2*ecx+3] + packuswb mm2, mm3 + paddw mm6, [Skl_YUV_Tab32_MMX+2*2048 + eax*8] + add esi, [esp+8 +40] + paddw mm7, [Skl_YUV_Tab32_MMX+2*2048 + ebx*8] + + mov edi, [Vp] + packuswb mm6, mm7 + movq [esi+8*ecx+0], mm2 ; 2x32b + movq [esi+8*ecx+8], mm6 ; 2x32b + + add ecx, 2 + mov esi, [Up] + + jl near .Loop_x + + mov ecx, [yCnt] + jmp .Loop_y diff --git a/pcsx2/IPU/yuv2rgb.c b/pcsx2/IPU/yuv2rgb.c new file mode 100644 index 0000000..17d6c0c --- /dev/null +++ b/pcsx2/IPU/yuv2rgb.c @@ -0,0 +1,510 @@ +/* + * yuv2rgb.c + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "mpeg2lib/Mpeg.h" +#include "yuv2rgb.h" + +//#include "convert_internal.h" //START +typedef struct { + u8 * rgb_ptr; + int width; + int uv_stride, uv_stride_frame; + int rgb_stride, rgb_stride_frame; + void (* yuv2rgb) (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); +} convert_rgb_t; + +typedef void yuv2rgb_copy (void * id, u8 * const * src, + unsigned int v_offset); + +yuv2rgb_copy * yuv2rgb_init_mmxext (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mmx (int bpp, int mode); +yuv2rgb_copy * yuv2rgb_init_mlib (int bpp, int mode); +//#include "convert_internal.h" //END + +static u32 matrix_coefficients = 6; + +const s32 Inverse_Table_6_9[8][4] = { + {117504, 138453, 13954, 34903}, /*0 no sequence_display_extension */ + {117504, 138453, 13954, 34903}, /*1 ITU-R Rec. 709 (1990) */ + {104597, 132201, 25675, 53279}, /*2 unspecified */ + {104597, 132201, 25675, 53279}, /*3 reserved */ + {104448, 132798, 24759, 53109}, /*4 FCC */ + {104597, 132201, 25675, 53279}, /*5 ITU-R Rec. 624-4 System B, G */ + {104597, 132201, 25675, 53279}, /*6 SMPTE 170M */ + {117579, 136230, 16907, 35559} /*7 SMPTE 240M (1987) */ +}; + +typedef void yuv2rgb_c_internal (u8 *, u8 *, u8 *, u8 *, + void *, void *, int); + +void * table_rV[256]; +void * table_gU[256]; +int table_gV[256]; +void * table_bU[256]; + +#define _RGB(type,i) \ + U = pu[i]; \ + V = pv[i]; \ + r = (type *) table_rV[V]; \ + g = (type *) (((u8 *)table_gU[U]) + table_gV[V]); \ + b = (type *) table_bU[U]; + +#define DST(py,dst,i) \ + Y = py[2*i]; \ + dst[2*i] = r[Y] + g[Y] + b[Y]; \ + Y = py[2*i+1]; \ + dst[2*i+1] = r[Y] + g[Y] + b[Y]; + +#define DSTRGB(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = r[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = b[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = r[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = b[Y]; + +#define DSTBGR(py,dst,i) \ + Y = py[2*i]; \ + dst[6*i] = b[Y]; dst[6*i+1] = g[Y]; dst[6*i+2] = r[Y]; \ + Y = py[2*i+1]; \ + dst[6*i+3] = b[Y]; dst[6*i+4] = g[Y]; dst[6*i+5] = r[Y]; + +static void yuv2rgb_c_32 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u32 * r, * g, * b; + u32 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u32 *) _dst_1; + dst_2 = (u32 *) _dst_2; + + do { + _RGB (u32, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u32, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u32, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u32, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +/* This is very near from the yuv2rgb_c_32 code */ +static void yuv2rgb_c_24_rgb (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTRGB (py_1, dst_1, 0); + DSTRGB (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTRGB (py_2, dst_2, 1); + DSTRGB (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTRGB (py_1, dst_1, 2); + DSTRGB (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTRGB (py_2, dst_2, 3); + DSTRGB (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* only trivial mods from yuv2rgb_c_24_rgb */ +static void yuv2rgb_c_24_bgr (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u8 * r, * g, * b; + u8 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u8 *) _dst_1; + dst_2 = (u8 *) _dst_2; + + do { + _RGB (u8, 0); + DSTBGR (py_1, dst_1, 0); + DSTBGR (py_2, dst_2, 0); + + _RGB (u8, 1); + DSTBGR (py_2, dst_2, 1); + DSTBGR (py_1, dst_1, 1); + + _RGB (u8, 2); + DSTBGR (py_1, dst_1, 2); + DSTBGR (py_2, dst_2, 2); + + _RGB (u8, 3); + DSTBGR (py_2, dst_2, 3); + DSTBGR (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 24; + dst_2 += 24; + } while (--width); +} + +/* This is exactly the same code as yuv2rgb_c_32 except for the types of */ +/* r, g, b, dst_1, dst_2 */ +static void yuv2rgb_c_16 (u8 * py_1, u8 * py_2, + u8 * pu, u8 * pv, + void * _dst_1, void * _dst_2, int width) +{ + int U, V, Y; + u16 * r, * g, * b; + u16 * dst_1, * dst_2; + + width >>= 3; + dst_1 = (u16 *) _dst_1; + dst_2 = (u16 *) _dst_2; + + do { + _RGB (u16, 0); + DST (py_1, dst_1, 0); + DST (py_2, dst_2, 0); + + _RGB (u16, 1); + DST (py_2, dst_2, 1); + DST (py_1, dst_1, 1); + + _RGB (u16, 2); + DST (py_1, dst_1, 2); + DST (py_2, dst_2, 2); + + _RGB (u16, 3); + DST (py_2, dst_2, 3); + DST (py_1, dst_1, 3); + + pu += 4; + pv += 4; + py_1 += 8; + py_2 += 8; + dst_1 += 8; + dst_2 += 8; + } while (--width); +} + +static int div_round (int dividend, int divisor) +{ + if (dividend > 0) + return (dividend + (divisor>>1)) / divisor; + else + return -((-dividend + (divisor>>1)) / divisor); +} + +static yuv2rgb_c_internal * yuv2rgb_c_init (int order, int bpp) +{ + int i; + u8 table_Y[1024]; + u32 * table_32 = 0; + u16 * table_16 = 0; + u8 * table_8 = 0; + int entry_size = 0; + void * table_r = 0; + void * table_g = 0; + void * table_b = 0; + yuv2rgb_c_internal * yuv2rgb; + + int crv = Inverse_Table_6_9[matrix_coefficients][0]; + int cbu = Inverse_Table_6_9[matrix_coefficients][1]; + int cgu = -Inverse_Table_6_9[matrix_coefficients][2]; + int cgv = -Inverse_Table_6_9[matrix_coefficients][3]; + + for (i = 0; i < 1024; i++) { + int j; + + j = (76309 * (i - 384 - 16) + 32768) >> 16; + j = (j < 0) ? 0 : ((j > 255) ? 255 : j); + table_Y[i] = j; + } + + switch (bpp) { + case 32: + yuv2rgb = yuv2rgb_c_32; + + table_32 = (u32 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u32)); + + entry_size = sizeof (u32); + table_r = table_32 + 197; + table_b = table_32 + 197 + 685; + table_g = table_32 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) + ((u32 *) table_r)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 16 : 0); + for (i = -132; i < 256+132; i++) + ((u32 *) table_g)[i] = table_Y[i+384] << 8; + for (i = -232; i < 256+232; i++) + ((u32 *) table_b)[i] = + table_Y[i+384] << ((order == CONVERT_RGB) ? 0 : 16); + break; + + case 24: + yuv2rgb = (order == CONVERT_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; + + table_8 = (u8 *) malloc ((256 + 2*232) * sizeof (u8)); + + entry_size = sizeof (u8); + table_r = table_g = table_b = table_8 + 232; + + for (i = -232; i < 256+232; i++) + ((u8 * )table_b)[i] = table_Y[i+384]; + break; + + case 15: + case 16: + yuv2rgb = yuv2rgb_c_16; + + table_16 = (u16 *) malloc ((197 + 2*682 + 256 + 132) * + sizeof (u16)); + + entry_size = sizeof (u16); + table_r = table_16 + 197; + table_b = table_16 + 197 + 685; + table_g = table_16 + 197 + 2*682; + + for (i = -197; i < 256+197; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_r)[i] = j; + } + for (i = -132; i < 256+132; i++) { + int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3); + + ((u16 *)table_g)[i] = j << 5; + } + for (i = -232; i < 256+232; i++) { + int j = table_Y[i+384] >> 3; + + if (order == CONVERT_RGB) + j <<= ((bpp==16) ? 11 : 10); + + ((u16 *)table_b)[i] = j; + } + break; + + default: + fprintf (stderr, "%ibpp not supported by yuv2rgb\n", bpp); + exit (1); + } + + for (i = 0; i < 256; i++) { + table_rV[i] = (((u8 *)table_r) + + entry_size * div_round (crv * (i-128), 76309)); + table_gU[i] = (((u8 *)table_g) + + entry_size * div_round (cgu * (i-128), 76309)); + table_gV[i] = entry_size * div_round (cgv * (i-128), 76309); + table_bU[i] = (((u8 *)table_b) + + entry_size * div_round (cbu * (i-128), 76309)); + } + + return yuv2rgb; +} + +static void convert_yuv2rgb_c (void * _id, u8 * Y, u8 * Cr, u8 * Cb, + unsigned int v_offset) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + u8 * dst; + u8 * py; + u8 * pu; + u8 * pv; + int loop; + + dst = id->rgb_ptr + id->rgb_stride * v_offset; + py = Y; pu = Cr; pv = Cb; + + loop = 8; + do { + id->yuv2rgb (py, py + (id->uv_stride << 1), pu, pv, + dst, dst + id->rgb_stride, id->width); + py += id->uv_stride << 2; + pu += id->uv_stride; + pv += id->uv_stride; + dst += 2 * id->rgb_stride; + } while (--loop); +} + +static void convert_start (void * _id, u8 * dest, int flags) +{ + convert_rgb_t * id = (convert_rgb_t *) _id; + id->rgb_ptr = dest; + switch (flags) { + case CONVERT_BOTTOM_FIELD: + id->rgb_ptr += id->rgb_stride_frame; + /* break thru */ + case CONVERT_TOP_FIELD: + id->uv_stride = id->uv_stride_frame << 1; + id->rgb_stride = id->rgb_stride_frame << 1; + break; + default: + id->uv_stride = id->uv_stride_frame; + id->rgb_stride = id->rgb_stride_frame; + } +} + +static void convert_internal (int order, int bpp, int width, int height, + u32 accel, void * arg, + convert_init_t * result) +{ + convert_rgb_t * id = (convert_rgb_t *) result->id; + + if (!id) { + result->id_size = sizeof (convert_rgb_t); + } else { + id->width = width; + id->uv_stride_frame = width >> 1; + id->rgb_stride_frame = ((bpp + 7) >> 3) * width; + + result->buf_size[0] = id->rgb_stride_frame * height; + result->buf_size[1] = result->buf_size[2] = 0; + result->start = convert_start; + + result->copy = NULL; +#ifdef ARCH_X86 + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMXEXT)) { + result->copy = yuv2rgb_init_mmxext (order, bpp); + } + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_X86_MMX)) { + result->copy = yuv2rgb_init_mmx (order, bpp); + } +#endif +#ifdef LIBVO_MLIB + if ((result->copy == NULL) && (accel & MPEG2_ACCEL_MLIB)) { + result->copy = yuv2rgb_init_mlib (order, bpp); + } +#endif + if (result->copy == NULL) { + result->copy = convert_yuv2rgb_c; + id->yuv2rgb = yuv2rgb_c_init (order, bpp); + } + } +} + +void convert_rgb32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 32, width, height, accel, arg, result); +} + +void convert_rgb24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 24, width, height, accel, arg, result); +} + +void convert_rgb16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 16, width, height, accel, arg, result); +} + +void convert_rgb15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_RGB, 15, width, height, accel, arg, result); +} + +void convert_bgr32 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 32, width, height, accel, arg, result); +} + +void convert_bgr24 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 24, width, height, accel, arg, result); +} + +void convert_bgr16 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 16, width, height, accel, arg, result); +} + +void convert_bgr15 (int width, int height, u32 accel, void * arg, + convert_init_t * result) +{ + convert_internal (CONVERT_BGR, 15, width, height, accel, arg, result); +} + +convert_t* convert_rgb (int order, int bpp) +{ + if (order == CONVERT_RGB || order == CONVERT_BGR) + switch (bpp) { + case 32: return (order == CONVERT_RGB) ? convert_rgb32 : convert_bgr32; + case 24: return (order == CONVERT_RGB) ? convert_rgb24 : convert_bgr24; + case 16: return (order == CONVERT_RGB) ? convert_rgb16 : convert_bgr16; + case 15: return (order == CONVERT_RGB) ? convert_rgb15 : convert_bgr15; + } + return NULL; +} diff --git a/pcsx2/IPU/yuv2rgb.h b/pcsx2/IPU/yuv2rgb.h new file mode 100644 index 0000000..d9d4d9c --- /dev/null +++ b/pcsx2/IPU/yuv2rgb.h @@ -0,0 +1,57 @@ +/* + * yuv2rgb.h + * Copyright (C) 2000-2002 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * Modified by Florin for PCSX2 emu + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef YUV2RGB_H +#define YUV2RGB_H + +#define CONVERT_FRAME 0 +#define CONVERT_TOP_FIELD 1 +#define CONVERT_BOTTOM_FIELD 2 +#define CONVERT_BOTH_FIELDS 3 + +typedef struct convert_init_s { + void * id; + int id_size; + int buf_size[3]; + void (* start) (void * id, u8 * dest, int flags); + void (* copy) (void * id, u8 * Y, u8 * Cr, u8 * Cb, unsigned int v_offset); +} convert_init_t; + +typedef void convert_t (int width, int height, u32 accel, void * arg, + convert_init_t * result); + +convert_t convert_rgb32; +convert_t convert_rgb24; +convert_t convert_rgb16; +convert_t convert_rgb15; +convert_t convert_bgr32; +convert_t convert_bgr24; +convert_t convert_bgr16; +convert_t convert_bgr15; + +#define CONVERT_RGB 0 +#define CONVERT_BGR 1 +convert_t * convert_rgb (int order, int bpp); + +#endif /* YUV2RGB_H */ diff --git a/pcsx2/InterTables.c b/pcsx2/InterTables.c new file mode 100644 index 0000000..5f79905 --- /dev/null +++ b/pcsx2/InterTables.c @@ -0,0 +1,224 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//all tables for R5900 are define here.. + +#include "InterTables.h" + +void (*Int_OpcodePrintTable[64])() = +{ + SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, + ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, + COP0, COP1, COP2, UnknownOpcode, BEQL, BNEL, BLEZL, BGTZL, + DADDI, DADDIU, LDL, LDR, MMI, UnknownOpcode, LQ, SQ, + LB, LH, LWL, LW, LBU, LHU, LWR, LWU, + SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, + UnknownOpcode, LWC1, UnknownOpcode, PREF, UnknownOpcode,UnknownOpcode, LQC2, LD, + UnknownOpcode, SWC1, UnknownOpcode, UnknownOpcode, UnknownOpcode,UnknownOpcode, SQC2, SD +}; + + +void (*Int_SpecialPrintTable[64])() = +{ + SLL, UnknownOpcode, SRL, SRA, SLLV, UnknownOpcode, SRLV, SRAV, + JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, UnknownOpcode, SYNC, + MFHI, MTHI, MFLO, MTLO, DSLLV, UnknownOpcode, DSRLV, DSRAV, + MULT, MULTU, DIV, DIVU, UnknownOpcode,UnknownOpcode,UnknownOpcode,UnknownOpcode, + ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, + MFSA , MTSA , SLT, SLTU, DADD, DADDU, DSUB, DSUBU, + TGE, TGEU, TLT, TLTU, TEQ, UnknownOpcode, TNE, UnknownOpcode, + DSLL, UnknownOpcode, DSRL, DSRA, DSLL32, UnknownOpcode, DSRL32, DSRA32 +}; + +void (*Int_REGIMMPrintTable[32])() = { + BLTZ, BGEZ, BLTZL, BGEZL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + TGEI, TGEIU, TLTI, TLTIU, TEQI, UnknownOpcode, TNEI, UnknownOpcode, + BLTZAL, BGEZAL, BLTZALL, BGEZALL, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, + MTSAB, MTSAH , UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, UnknownOpcode, +}; + +void (*Int_MMIPrintTable[64])() = +{ + MADD, MADDU, MMI_Unknown, MMI_Unknown, PLZCW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI0, MMI2, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MFHI1, MTHI1, MFLO1, MTLO1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MULT1, MULTU1, DIV1, DIVU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MADD1, MADDU1, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI1 , MMI3, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHL, PMTHL, MMI_Unknown, MMI_Unknown, PSLLH, MMI_Unknown, PSRLH, PSRAH, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, PSLLW, MMI_Unknown, PSRLW, PSRAW, +}; + +void (*Int_MMI0PrintTable[32])() = +{ + PADDW, PSUBW, PCGTW, PMAXW, + PADDH, PSUBH, PCGTH, PMAXH, + PADDB, PSUBB, PCGTB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDSW, PSUBSW, PEXTLW, PPACW, + PADDSH, PSUBSH, PEXTLH, PPACH, + PADDSB, PSUBSB, PEXTLB, PPACB, + MMI_Unknown, MMI_Unknown, PEXT5, PPAC5, +}; + +void (*Int_MMI1PrintTable[32])() = +{ + MMI_Unknown, PABSW, PCEQW, PMINW, + PADSBH, PABSH, PCEQH, PMINH, + MMI_Unknown, MMI_Unknown, PCEQB, MMI_Unknown, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PADDUW, PSUBUW, PEXTUW, MMI_Unknown, + PADDUH, PSUBUH, PEXTUH, MMI_Unknown, + PADDUB, PSUBUB, PEXTUB, QFSRV, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, +}; + + +void (*Int_MMI2PrintTable[32])() = +{ + PMADDW, MMI_Unknown, PSLLVW, PSRLVW, + PMSUBW, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMFHI, PMFLO, PINTH, MMI_Unknown, + PMULTW, PDIVW, PCPYLD, MMI_Unknown, + PMADDH, PHMADH, PAND, PXOR, + PMSUBH, PHMSBH, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXEH, PREVH, + PMULTH, PDIVBW, PEXEW, PROT3W, +}; + +void (*Int_MMI3PrintTable[32])() = +{ + PMADDUW, MMI_Unknown, MMI_Unknown, PSRAVW, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + PMTHI, PMTLO, PINTEH, MMI_Unknown, + PMULTUW, PDIVUW, PCPYUD, MMI_Unknown, + MMI_Unknown, MMI_Unknown, POR, PNOR, + MMI_Unknown, MMI_Unknown, MMI_Unknown, MMI_Unknown, + MMI_Unknown, MMI_Unknown, PEXCH, PCPYH, + MMI_Unknown, MMI_Unknown, PEXCW, MMI_Unknown, +}; + +void (*Int_COP0PrintTable[32])() = +{ + MFC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, MTC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_BC0, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Func, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0BC0PrintTable[32])() = +{ + BC0F, BC0T, BC0FL, BC0TL, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, +}; + +void (*Int_COP0C0PrintTable[64])() = { + COP0_Unknown, TLBR, TLBWI, COP0_Unknown, COP0_Unknown, COP0_Unknown, TLBWR, COP0_Unknown, + TLBP, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + ERET, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, + EI, DI, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown, COP0_Unknown +}; + +void (*Int_COP1PrintTable[32])() = { + MFC1, COP1_Unknown, CFC1, COP1_Unknown, MTC1, COP1_Unknown, CTC1, COP1_Unknown, + COP1_BC1, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_S, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_W, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1BC1PrintTable[32])() = { + BC1F, BC1T, BC1FL, BC1TL, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, + COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, COP1_Unknown, +}; + +void (*Int_COP1SPrintTable[64])() = { +ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,RSQRT_S, COP1_Unknown, +ADDA_S, SUBA_S, MULA_S, COP1_Unknown,MADD_S, MSUB_S, MADDA_S, MSUBA_S, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,CVT_W, COP1_Unknown,COP1_Unknown,COP1_Unknown, +MAX_S, MIN_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +C_F, COP1_Unknown,C_EQ, COP1_Unknown,C_LT, COP1_Unknown,C_LE, COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + +void (*Int_COP1WPrintTable[64])() = { +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +CVT_S, COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown,COP1_Unknown, +}; + + +void (*Int_COP2PrintTable[32])() = { + COP2_Unknown, QMFC2, CFC2, COP2_Unknown, COP2_Unknown, QMTC2, CTC2, COP2_Unknown, + COP2_BC2, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, + COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, COP2_SPECIAL, +}; + +void (*Int_COP2BC2PrintTable[32])() = { + BC2F, BC2T, BC2FL, BC2TL, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, + COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, COP2_Unknown, +}; + +void (*Int_COP2SPECIAL1PrintTable[64])() = +{ + VADDx, VADDy, VADDz, VADDw, VSUBx, VSUBy, VSUBz, VSUBw, + VMADDx, VMADDy, VMADDz, VMADDw, VMSUBx, VMSUBy, VMSUBz, VMSUBw, + VMAXx, VMAXy, VMAXz, VMAXw, VMINIx, VMINIy, VMINIz, VMINIw, + VMULx, VMULy, VMULz, VMULw, VMULq, VMAXi, VMULi, VMINIi, + VADDq, VMADDq, VADDi, VMADDi, VSUBq, VMSUBq, VSUBi, VMSUBi, + VADD, VMADD, VMUL, VMAX, VSUB, VMSUB, VOPMSUB, VMINI, + VIADD, VISUB, VIADDI, COP2_Unknown,VIAND, VIOR, COP2_Unknown, COP2_Unknown, + VCALLMS, VCALLMSR, COP2_Unknown,COP2_Unknown,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2,COP2_SPECIAL2, +}; + +void (*Int_COP2SPECIAL2PrintTable[128])() = +{ + VADDAx ,VADDAy ,VADDAz ,VADDAw ,VSUBAx ,VSUBAy ,VSUBAz ,VSUBAw, + VMADDAx ,VMADDAy ,VMADDAz ,VMADDAw ,VMSUBAx ,VMSUBAy ,VMSUBAz ,VMSUBAw, + VITOF0 ,VITOF4 ,VITOF12 ,VITOF15 ,VFTOI0 ,VFTOI4 ,VFTOI12 ,VFTOI15, + VMULAx ,VMULAy ,VMULAz ,VMULAw ,VMULAq ,VABS ,VMULAi ,VCLIPw, + VADDAq ,VMADDAq ,VADDAi ,VMADDAi ,VSUBAq ,VMSUBAq ,VSUBAi ,VMSUBAi, + VADDA ,VMADDA ,VMULA ,COP2_Unknown,VSUBA ,VMSUBA ,VOPMULA ,VNOP, + VMOVE ,VMR32 ,COP2_Unknown,COP2_Unknown,VLQI ,VSQI ,VLQD ,VSQD, + VDIV ,VSQRT ,VRSQRT ,VWAITQ ,VMTIR ,VMFIR ,VILWR ,VISWR, + VRNEXT ,VRGET ,VRINIT ,VRXOR ,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, + COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown,COP2_Unknown, +}; diff --git a/pcsx2/InterTables.h b/pcsx2/InterTables.h new file mode 100644 index 0000000..5788826 --- /dev/null +++ b/pcsx2/InterTables.h @@ -0,0 +1,491 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef INTERTABLES_H +#define INTERTABLES_H + +extern void (*Int_OpcodePrintTable[64])(); +extern void (*Int_SpecialPrintTable[64])(); +extern void (*Int_REGIMMPrintTable[32])(); +extern void (*Int_MMIPrintTable[64])(); +extern void (*Int_MMI0PrintTable[32])(); +extern void (*Int_MMI1PrintTable[32])(); +extern void (*Int_MMI2PrintTable[32])(); +extern void (*Int_MMI3PrintTable[32])(); +extern void (*Int_COP0PrintTable[32])(); +extern void (*Int_COP0BC0PrintTable[32])(); +extern void (*Int_COP0C0PrintTable[64])(); +extern void (*Int_COP1PrintTable[32])(); +extern void (*Int_COP1BC1PrintTable[32])(); +extern void (*Int_COP1SPrintTable[64])(); +extern void (*Int_COP1WPrintTable[64])(); +extern void (*Int_COP2PrintTable[32])(); +extern void (*Int_COP2BC2PrintTable[32])(); +extern void (*Int_COP2SPECIAL1PrintTable[64])(); +extern void (*Int_COP2SPECIAL2PrintTable[128])(); + +void SPECIAL(); +void REGIMM(); +void UnknownOpcode(); +void COP0(); +void COP1(); +void COP2(); +void MMI_Unknown(); +void MMI(); +void MMI0(); +void MMI1(); +void MMI2(); +void MMI3(); +void COP0_Unknown(); +void COP0_BC0(); +void COP0_Func(); +void COP1_BC1(); +void COP1_S(); +void COP1_W(); +void COP1_Unknown(); +void COP2_BC2(); +void COP2_SPECIAL(); +void COP2_Unknown(); +void COP2_SPECIAL2(); + +// **********************Standard Opcodes************************** +void J(); +void JAL(); +void BEQ(); +void BNE(); +void BLEZ(); +void BGTZ(); +void ADDI(); +void ADDIU(); +void SLTI(); +void SLTIU(); +void ANDI(); +void ORI(); +void XORI(); +void LUI(); +void BEQL(); +void BNEL(); +void BLEZL(); +void BGTZL(); +void DADDI(); +void DADDIU(); +void LDL(); +void LDR(); +void LB(); +void LH(); +void LWL(); +void LW(); +void LBU(); +void LHU(); +void LWR(); +void LWU(); +void SB(); +void SH(); +void SWL(); +void SW(); +void SDL(); +void SDR(); +void SWR(); +void CACHE(); +void LWC1(); +void PREF(); +void LQC2(); +void LD(); +void SQC2(); +void SD(); +void LQ(); +void SQ(); +void SWC1(); +//***************end of standard opcodes************************* + + +//***************SPECIAL OPCODES********************************** +void SLL(); +void SRL(); +void SRA(); +void SLLV(); +void SRLV(); +void SRAV(); +void JR(); +void JALR(); +void SYSCALL(); +void BREAK(); +void SYNC(); +void MFHI(); +void MTHI(); +void MFLO(); +void MTLO(); +void DSLLV(); +void DSRLV(); +void DSRAV(); +void MULT(); +void MULTU(); +void DIV(); +void DIVU(); +void ADD(); +void ADDU(); +void SUB(); +void SUBU(); +void AND(); +void OR(); +void XOR(); +void NOR(); +void SLT(); +void SLTU(); +void DADD(); +void DADDU(); +void DSUB(); +void DSUBU(); +void TGE(); +void TGEU(); +void TLT(); +void TLTU(); +void TEQ(); +void TNE(); +void DSLL(); +void DSRL(); +void DSRA(); +void DSLL32(); +void DSRL32(); +void DSRA32(); +void MOVZ(); +void MOVN(); +void MFSA(); +void MTSA(); +//******************END OF SPECIAL OPCODES************************** + +//******************REGIMM OPCODES********************************** +void BLTZ(); +void BGEZ(); +void BLTZL(); +void BGEZL(); +void TGEI(); +void TGEIU(); +void TLTI(); +void TLTIU(); +void TEQI(); +void TNEI(); +void BLTZAL(); +void BGEZAL(); +void BLTZALL(); +void BGEZALL(); +void MTSAB(); +void MTSAH(); +//*****************END OF REGIMM OPCODES***************************** +//*****************MMI OPCODES********************************* +void MADD(); +void MADDU(); +void PLZCW(); +void MADD1(); +void MADDU1(); +void MFHI1(); +void MTHI1(); +void MFLO1(); +void MTLO1(); +void MULT1(); +void MULTU1(); +void DIV1(); +void DIVU1(); +void PMFHL(); +void PMTHL(); +void PSLLH(); +void PSRLH(); +void PSRAH(); +void PSLLW(); +void PSRLW(); +void PSRAW(); +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +void PADDW(); +void PSUBW(); +void PCGTW(); +void PMAXW(); +void PADDH(); +void PSUBH(); +void PCGTH(); +void PMAXH(); +void PADDB(); +void PSUBB(); +void PCGTB(); +void PADDSW(); +void PSUBSW(); +void PEXTLW(); +void PPACW(); +void PADDSH(); +void PSUBSH(); +void PEXTLH(); +void PPACH(); +void PADDSB(); +void PSUBSB(); +void PEXTLB(); +void PPACB(); +void PEXT5(); +void PPAC5(); +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** +void PABSW(); +void PCEQW(); +void PMINW(); +void PADSBH(); +void PABSH(); +void PCEQH(); +void PMINH(); +void PCEQB(); +void PADDUW(); +void PSUBUW(); +void PEXTUW(); +void PADDUH(); +void PSUBUH(); +void PEXTUH(); +void PADDUB(); +void PSUBUB(); +void PEXTUB(); +void QFSRV(); +//********END OF MMI1 OPCODES*********************************** +//*********MMI2 OPCODES*************************************** +void PMADDW(); +void PSLLVW(); +void PSRLVW(); +void PMSUBW(); +void PMFHI(); +void PMFLO(); +void PINTH(); +void PMULTW(); +void PDIVW(); +void PCPYLD(); +void PMADDH(); +void PHMADH(); +void PAND(); +void PXOR(); +void PMSUBH(); +void PHMSBH(); +void PEXEH(); +void PREVH(); +void PMULTH(); +void PDIVBW(); +void PEXEW(); +void PROT3W(); +//*****END OF MMI2 OPCODES*********************************** +//*************************MMI3 OPCODES************************ +void PMADDUW(); +void PSRAVW(); +void PMTHI(); +void PMTLO(); +void PINTEH(); +void PMULTUW(); +void PDIVUW(); +void PCPYUD(); +void POR(); +void PNOR(); +void PEXCH(); +void PCPYH(); +void PEXCW(); +//**********************END OF MMI3 OPCODES******************** +//**************************************************************************** +//** COP0 ** +//**************************************************************************** +void MFC0(); +void MTC0(); +void BC0F(); +void BC0T(); +void BC0FL(); +void BC0TL(); +void TLBR(); +void TLBWI(); +void TLBWR(); +void TLBP(); +void ERET(); +void DI(); +void EI(); +//**************************************************************************** +//** END OF COP0 ** +//**************************************************************************** +//**************************************************************************** +//** COP1 - Floating Point Unit (FPU) ** +//**************************************************************************** +void MFC1(); +void CFC1(); +void MTC1(); +void CTC1(); +void BC1F(); +void BC1T(); +void BC1FL(); +void BC1TL(); +void ADD_S(); +void SUB_S(); +void MUL_S(); +void DIV_S(); +void SQRT_S(); +void ABS_S(); +void MOV_S(); +void NEG_S(); +void RSQRT_S(); +void ADDA_S(); +void SUBA_S(); +void MULA_S(); +void MADD_S(); +void MSUB_S(); +void MADDA_S(); +void MSUBA_S(); +void CVT_W(); +void MAX_S(); +void MIN_S(); +void C_F(); +void C_EQ(); +void C_LT(); +void C_LE(); + void CVT_S(); +//**************************************************************************** +//** END OF COP1 ** +//**************************************************************************** +//**************************************************************************** +//** COP2 - (VU0) ** +//**************************************************************************** +void QMFC2(); +void CFC2(); +void QMTC2(); +void CTC2(); +void BC2F(); +void BC2T(); +void BC2FL(); +void BC2TL(); +//*****************SPECIAL 1 VUO TABLE******************************* +void VADDx(); +void VADDy(); +void VADDz(); +void VADDw(); +void VSUBx(); +void VSUBy(); +void VSUBz(); +void VSUBw(); +void VMADDx(); +void VMADDy(); +void VMADDz(); +void VMADDw(); +void VMSUBx(); +void VMSUBy(); +void VMSUBz(); +void VMSUBw(); +void VMAXx(); +void VMAXy(); +void VMAXz(); +void VMAXw(); +void VMINIx(); +void VMINIy(); +void VMINIz(); +void VMINIw(); +void VMULx(); +void VMULy(); +void VMULz(); +void VMULw(); +void VMULq(); +void VMAXi(); +void VMULi(); +void VMINIi(); +void VADDq(); +void VMADDq(); +void VADDi(); +void VMADDi(); +void VSUBq(); +void VMSUBq(); +void VSUBi(); +void VMSUBi(); +void VADD(); +void VMADD(); +void VMUL(); +void VMAX(); +void VSUB(); +void VMSUB(); +void VOPMSUB(); +void VMINI(); +void VIADD(); +void VISUB(); +void VIADDI(); +void VIAND(); +void VIOR(); +void VCALLMS(); +void VCALLMSR(); +//***********************************END OF SPECIAL1 VU0 TABLE***************************** +//******************************SPECIAL2 VUO TABLE***************************************** +void VADDAx(); +void VADDAy(); +void VADDAz(); +void VADDAw(); +void VSUBAx(); +void VSUBAy(); +void VSUBAz(); +void VSUBAw(); +void VMADDAx(); +void VMADDAy(); +void VMADDAz(); +void VMADDAw(); +void VMSUBAx(); +void VMSUBAy(); +void VMSUBAz(); +void VMSUBAw(); +void VITOF0(); +void VITOF4(); +void VITOF12(); +void VITOF15(); +void VFTOI0(); +void VFTOI4(); +void VFTOI12(); +void VFTOI15(); +void VMULAx(); +void VMULAy(); +void VMULAz(); +void VMULAw(); +void VMULAq(); +void VABS(); +void VMULAi(); +void VCLIPw(); +void VADDAq(); +void VMADDAq(); +void VADDAi(); +void VMADDAi(); +void VSUBAq(); +void VMSUBAq(); +void VSUBAi(); +void VMSUBAi(); +void VADDA(); +void VMADDA(); +void VMULA(); +void VSUBA(); +void VMSUBA(); +void VOPMULA(); +void VNOP(); +void VMOVE(); +void VMR32(); +void VLQI(); +void VSQI(); +void VLQD(); +void VSQD(); +void VDIV(); +void VSQRT(); +void VRSQRT(); +void VWAITQ(); +void VMTIR(); +void VMFIR(); +void VILWR(); +void VISWR(); +void VRNEXT(); +void VRGET(); +void VRINIT(); +void VRXOR(); +//************************************END OF SPECIAL2 ************ +#endif diff --git a/pcsx2/Interpreter.c b/pcsx2/Interpreter.c new file mode 100644 index 0000000..b1d49f7 --- /dev/null +++ b/pcsx2/Interpreter.c @@ -0,0 +1,1062 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "ix86/ix86.h" + +#include + +extern u32 maxrecmem; + +char *bios[256]={ +//0x00 + "RFU000_FullReset", "ResetEE", "SetGsCrt", "RFU003", + "Exit", "RFU005", "LoadExecPS2", "ExecPS2", + "RFU008", "RFU009", "AddSbusIntcHandler", "RemoveSbusIntcHandler", + "Interrupt2Iop", "SetVTLBRefillHandler", "SetVCommonHandler", "SetVInterruptHandler", +//0x10 + "AddIntcHandler", "RemoveIntcHandler", "AddDmacHandler", "RemoveDmacHandler", + "_EnableIntc", "_DisableIntc", "_EnableDmac", "_DisableDmac", + "_SetAlarm", "_ReleaseAlarm", "_iEnableIntc", "_iDisableIntc", + "_iEnableDmac", "_iDisableDmac", "_iSetAlarm", "_iReleaseAlarm", +//0x20 + "CreateThread", "DeleteThread", "StartThread", "ExitThread", + "ExitDeleteThread", "TerminateThread", "iTerminateThread", "DisableDispatchThread", + "EnableDispatchThread", "ChangeThreadPriority", "iChangeThreadPriority", "RotateThreadReadyQueue", + "iRotateThreadReadyQueue", "ReleaseWaitThread", "iReleaseWaitThread", "GetThreadId", +//0x30 + "ReferThreadStatus","iReferThreadStatus", "SleepThread", "WakeupThread", + "_iWakeupThread", "CancelWakeupThread", "iCancelWakeupThread", "SuspendThread", + "iSuspendThread", "ResumeThread", "iResumeThread", "JoinThread", + "RFU060", "RFU061", "EndOfHeap", "RFU063", +//0x40 + "CreateSema", "DeleteSema", "SignalSema", "iSignalSema", + "WaitSema", "PollSema", "iPollSema", "ReferSemaStatus", + "iReferSemaStatus", "RFU073", "SetOsdConfigParam", "GetOsdConfigParam", + "GetGsHParam", "GetGsVParam", "SetGsHParam", "SetGsVParam", +//0x50 + "RFU080_CreateEventFlag", "RFU081_DeleteEventFlag", + "RFU082_SetEventFlag", "RFU083_iSetEventFlag", + "RFU084_ClearEventFlag", "RFU085_iClearEventFlag", + "RFU086_WaitEventFlag", "RFU087_PollEventFlag", + "RFU088_iPollEventFlag", "RFU089_ReferEventFlagStatus", + "RFU090_iReferEventFlagStatus", "RFU091_GetEntryAddress", + "EnableIntcHandler_iEnableIntcHandler", + "DisableIntcHandler_iDisableIntcHandler", + "EnableDmacHandler_iEnableDmacHandler", + "DisableDmacHandler_iDisableDmacHandler", +//0x60 + "KSeg0", "EnableCache", "DisableCache", "GetCop0", + "FlushCache", "RFU101", "CpuConfig", "iGetCop0", + "iFlushCache", "RFU105", "iCpuConfig", "sceSifStopDma", + "SetCPUTimerHandler", "SetCPUTimer", "SetOsdConfigParam2", "SetOsdConfigParam2", +//0x70 + "GsGetIMR_iGsGetIMR", "GsGetIMR_iGsPutIMR", "SetPgifHandler", "SetVSyncFlag", + "RFU116", "print", "sceSifDmaStat_isceSifDmaStat", "sceSifSetDma_isceSifSetDma", + "sceSifSetDChain_isceSifSetDChain", "sceSifSetReg", "sceSifGetReg", "ExecOSD", + "Deci2Call", "PSMode", "MachineType", "GetMemorySize", +}; + +extern void (*LT_OpcodePrintTable[64])(); +int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef CPU_LOG +#define debugI() \ + if (Log) { CPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); } \ + if (cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1]) SysPrintf("R0 is not zero!!!!\n"); +#else +#define debugI() +#endif + +void execI() { + + cpuRegs.cycle++; + //cpuRegs.CP0.n.Count++; /*count every cycles.*/ + +#ifdef _DEBUG + if (memRead32(cpuRegs.pc, &cpuRegs.code) == -1) return; + debugI(); +#else + cpuRegs.code = *(u32 *)PSM(cpuRegs.pc); +#endif + + + cpuRegs.pc+= 4; +// if((cpuRegs.PERF.n.pccr & 0x80000020) == 0x80000020) cpuRegs.PERF.n.pcr0++; +// if((cpuRegs.PERF.n.pccr & 0x80008000) == 0x80008000) cpuRegs.PERF.n.pcr1++; + + Int_OpcodePrintTable[cpuRegs.code >> 26](); +} + +__inline void doBranch(u32 tar) { + branch2 = cpuRegs.branch = 1; + branchPC = tar; + execI(); + cpuRegs.branch = 0; + cpuRegs.pc = branchPC; + + IntcpuBranchTest(); +} + +void intDoBranch(u32 target) { + doBranch(target); +} + +void intSetBranch() { + branch2 = 1; +} + +void SPECIAL() {Int_SpecialPrintTable[_Funct_]();} +void REGIMM() {Int_REGIMMPrintTable[_Rt_](); } + + +void UnknownOpcode() { +#ifdef CPU_LOG + CPU_LOG("%8.8lx: Unknown opcode called\n", cpuRegs.pc); +#endif +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void ADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed!!!! +void ADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed !!! +void DADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void DADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im +void ANDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & (s64)_ImmU_; } // Rt = Rs And Im +void ORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | (s64)_ImmU_; } // Rt = Rs Or Im +void XORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ (s64)_ImmU_; } // Rt = Rs Xor Im +void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_); } // Rt = Rs < Im (signed) +void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_); } // Rt = Rs < Im (unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void ADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt (Exception on Integer Overflow) +void ADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt +void DADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void DADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } +void SUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs - Rt (Exception on Integer Overflow) +void SUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0]; } // Rd = Rs - Rt +void DSUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0];} +void DSUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0]; } +void AND() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs And Rt +void OR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Or Rt +void XOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Xor Rt +void NOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] =~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); }// Rd = Rs Nor Rt +void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]; } // Rd = Rs < Rt (signed) +void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs < Rt (unsigned) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void J() { +#ifdef _DEBUG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + doBranch(_JumpTarget_); +#ifdef _DEBUG + JumpCheckSym(temp, pc); +#endif +} + +void JAL() { +#ifdef _DEBUG + u32 temp = _JumpTarget_; + u32 pc = cpuRegs.pc; +#endif + _SetLink(31); doBranch(_JumpTarget_); +#ifdef _DEBUG + JumpCheckSym(temp, pc); +#endif +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void JR() { +#ifdef _DEBUG + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; + u32 pc = cpuRegs.pc; + int rs = _Rs_; +#endif + doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); +#ifdef _DEBUG + JumpCheckSym(temp, pc); + if (rs == 31) JumpCheckSymRet(pc); +#endif +} + +void JALR() { + u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; +#ifdef _DEBUG + u32 pc = cpuRegs.pc; +#endif + + if (_Rd_) { _SetLink(_Rd_); } + doBranch(temp); +#ifdef _DEBUG + JumpCheckSym(temp, pc); +#endif +} + + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void DIV() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +void MULT() { //different in ps2... + s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +void MULTU() { //different in ps2.. + u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.UD[0] = (s32)(res >> 32); + + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0]= cpuRegs.LO.UD[0]; //that is the difference +} + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void LUI() { + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void MFHI() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; } // Rd = Hi +void MFLO() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void MTHI() { cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Hi = Rs +void MTLO() { cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Lo = Rs + + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void SLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << _Sa_); } // Rd = Rt << sa +void DSLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << _Sa_); } +void DSLL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (_Sa_+32));} +void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) +void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_); } +void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32));} +void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) +void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_); } +void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32));} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void SLLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt << rs +void SRAV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (arithmetic) +void SRLV() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x1f));} // Rd = Rt >> rs (logical) +void DSLLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRAV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} +void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (cpuRegs.GPR.r[_Rs_].UL[0] &0x3f));} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) \ + if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \ + else IntcpuBranchTest(); + + +void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else IntcpuBranchTest(); + +#define RepZBranchLinki32(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else IntcpuBranchTest(); + +void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + +#define RepZBranchLinki32Likely(op) \ + _SetLink(31); \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + +#define RepBranchi32Likely(op) \ + if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \ + doBranch(_BranchTarget_); \ + } else { cpuRegs.pc +=4; IntcpuBranchTest(); } + + +void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt +void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt +void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0 +void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0 +void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0 +void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0 +void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link +void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void LB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead8RS(addr, &dummy); + } +} + +void LBU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead8RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead8RU(addr, &dummy); + } +} + +void LH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead16RS(addr, &dummy); + } +} + +void LHU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead16RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead16RU(addr, &dummy); + } +} + +void LW() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RS(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead32RS(addr, &dummy); + } +} + +void LWU() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead32RU(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead32RU(addr, &dummy); + } +} + +u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void LWL() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWL_MASK[shift]) | + (mem << LWL_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + */ +} + +u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 }; +u32 LWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void LWR() { + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (!_Rt_) return; + if (memRead32(addr & ~3, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] & LWR_MASK[shift]) | + (mem >> LWR_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + */ +} + +void LD() { + s32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + if (_Rt_) { + memRead64(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 dummy; + memRead64(addr, &dummy); + } +} + +u64 LDL_MASK[8] = { 0x00ffffffffffffffLL, 0x0000ffffffffffffLL, 0x000000ffffffffffLL, 0x00000000ffffffffLL, + 0x0000000000ffffffLL, 0x000000000000ffffLL, 0x00000000000000ffLL, 0x0000000000000000LL }; +u32 LDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void LDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDL_MASK[shift]) | + (mem << LDL_SHIFT[shift]); +} + +u64 LDR_MASK[8] = { 0x0000000000000000LL, 0xff00000000000000LL, 0xffff000000000000LL, 0xffffff0000000000LL, + 0xffffffff00000000LL, 0xffffffffff000000LL, 0xffffffffffff0000LL, 0xffffffffffffff00LL }; +u32 LDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void LDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (!_Rt_) return; + if (memRead64(addr & ~7, &mem) == -1) return; + cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDR_MASK[shift]) | + (mem >> LDR_SHIFT[shift]); +} + +void LQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + + if (_Rt_) { + memRead128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +void SB() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); +} + +void SH() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); +} + +void SW(){ + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); +} + +u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0x00000000 }; +u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +void SWL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] >> SWL_SHIFT[shift]) | + ( mem & SWL_MASK[shift]) ); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + */ +} + +u32 SWR_MASK[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; +u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +void SWR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 3; + u32 mem; + + if (memRead32(addr & ~3, &mem) == -1) return; + + memWrite32(addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] << SWR_SHIFT[shift]) | + ( mem & SWR_MASK[shift]) ); + + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + */ +} + +void SD() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite64(addr,cpuRegs.GPR.r[_Rt_].UD[0]); +} + +u64 SDL_MASK[8] = { 0xffffffffffffff00LL, 0xffffffffffff0000LL, 0xffffffffff000000LL, 0xffffffff00000000LL, + 0xffffff0000000000LL, 0xffff000000000000LL, 0xff00000000000000LL, 0x0000000000000000LL }; +u32 SDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void SDL() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] >> SDL_SHIFT[shift]) | + ( mem & SDL_MASK[shift]) ); +} + +u64 SDR_MASK[8] = { 0x0000000000000000LL, 0x00000000000000ffLL, 0x000000000000ffffLL, 0x0000000000ffffffLL, + 0x00000000ffffffffLL, 0x000000ffffffffffLL, 0x0000ffffffffffffLL, 0x00ffffffffffffffLL }; +u32 SDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void SDR() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 shift = addr & 7; + u64 mem; + + if (memRead64(addr & ~7, &mem) == -1) return; + + memWrite64(addr & ~7, (cpuRegs.GPR.r[_Rt_].UD[0] << SDR_SHIFT[shift]) | + ( mem & SDR_MASK[shift]) ); +} + +void SQ() { + u32 addr; + + addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + addr&=~0xf; + memWrite128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); +} + +/********************************************************* +* Conditional Move * +* Format: OP rd, rs, rt * +*********************************************************/ + +void MOVZ() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} +void MOVN() { + if (!_Rd_) return; + if (cpuRegs.GPR.r[_Rt_].UD[0] != 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + } +} + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ + +#include "Sifcmd.h" +/* +int __Deci2Call(int call, u32 *addr); +*/ +u32 *deci2addr = NULL; +u32 deci2handler; +char deci2buffer[256]; + +/* + * int Deci2Call(int, u_int *); + */ + +int __Deci2Call(int call, u32 *addr) { + if (call > 0x10) { + return -1; + } + + switch (call) { + case 1: // open + + deci2addr = (u32*)PSM(addr[1]); +#ifdef BIOS_LOG + BIOS_LOG("deci2open: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + deci2handler = addr[2]; + + return 1; + + case 2: // close + return 1; + + case 3: // reqsend + +#ifdef BIOS_LOG + BIOS_LOG("deci2reqsend: %x,%x,%x,%x: deci2addr: %x,%x,%x,buf=%x %x,%x,len=%x,%x\n", + addr[3], addr[2], addr[1], addr[0], + deci2addr[7], deci2addr[6], deci2addr[5], deci2addr[4], + deci2addr[3], deci2addr[2], deci2addr[1], deci2addr[0]); +#endif +// cpuRegs.pc = deci2handler; +// SysPrintf("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc)); + if (deci2addr == NULL) return 1; + if (deci2addr[1]>0xc){ + u8* pdeciaddr = (u8*)dmaGetAddr(deci2addr[4]+0xc); + if( pdeciaddr == NULL ) pdeciaddr = (u8*)PSM(deci2addr[4]+0xc); + else pdeciaddr += (deci2addr[4]+0xc)%16; + memcpy(deci2buffer, pdeciaddr, deci2addr[1]-0xc); + deci2buffer[deci2addr[1]-0xc>=255?255:deci2addr[1]-0xc]='\0'; + SysPrintf(deci2buffer); + } + deci2addr[3] = 0; + return 1; + + case 4: // poll +#ifdef BIOS_LOG + BIOS_LOG("deci2poll: %x,%x,%x,%x\n", + addr[3], addr[2], addr[1], addr[0]); +#endif + return 1; + + case 5: // exrecv + return 1; + + case 6: // exsend + return 1; + + case 0x10://kputs + SysPrintf("%s", PSM(*addr)); + return 1; + } + + return 0; +} + + +void SYSCALL() { +#ifdef BIOS_LOG + u8 call; + + if (cpuRegs.GPR.n.v1.SL[0] < 0) + call = (u8)(-cpuRegs.GPR.n.v1.SL[0]); + else call = cpuRegs.GPR.n.v1.UC[0]; + BIOS_LOG("Bios call: %s (%x)\n", bios[call], call); + if (call == 0x7c && cpuRegs.GPR.n.a0.UL[0] == 0x10) { + SysPrintf("%s", PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0]))); + } else + //if (call == 0x7c) SysPrintf("Deci2Call: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (call == 0x7c) __Deci2Call(cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0])); + if (call == 0x77) { + struct t_sif_dma_transfer *dmat; +// struct t_sif_cmd_header *hdr; +// struct t_sif_rpc_bind *bind; +// struct t_rpc_server_data *server; + int n_transfer; + u32 addr; +// int sid; + + n_transfer = cpuRegs.GPR.n.a1.UL[0] - 1; + if (n_transfer >= 0) { + addr = cpuRegs.GPR.n.a0.UL[0] + n_transfer * sizeof(struct t_sif_dma_transfer); + dmat = (struct t_sif_dma_transfer*)PSM(addr); + +#ifdef BIOS_LOG + BIOS_LOG("bios_%s: n_transfer=%d, size=%x, attr=%x, dest=%x, src=%x\n", + bios[cpuRegs.GPR.n.v1.UC[0]], n_transfer, + dmat->size, dmat->attr, + dmat->dest, dmat->src); +#endif + } +//Log=1; + } +#endif +// if (cpuRegs.GPR.n.v1.UD[0] == 0x77) Log=1; + cpuRegs.pc -= 4; + cpuException(0x20, cpuRegs.branch); +} + +void BREAK(void) { + cpuRegs.pc -= 4; + cpuException(0x24, cpuRegs.branch); +} + +void MFSA( void ) { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = (s64)cpuRegs.sa; +} + +void MTSA( void ) { + cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; +} + +void SYNC( void ) +{ +} + +void PREF( void ) +{ +} + + + +/********************************************************* +* Register trap * +* Format: OP rs, rt * +*********************************************************/ + +void TGE() { + if (cpuRegs.GPR.r[_Rs_].SD[0]>= cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEU() { + if (cpuRegs.GPR.r[_Rs_].UD[0]>= cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLT() { + if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQ() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNE() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Trap with immediate operand * +* Format: OP rs, rt * +*********************************************************/ + +void TGEI() { + + if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TGEIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] >= _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTI() { + if(cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TLTIU() { + if (cpuRegs.GPR.r[_Rs_].UD[0] < _ImmU_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TEQI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +void TNEI() { + if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) { + cpuException(EXC_CODE_Tr, cpuRegs.branch); + } +} + +/********************************************************* +* Sa intructions * +* Format: OP rs, rt * +*********************************************************/ + +void MTSAB() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3; +} + +void MTSAH() { + cpuRegs.sa = ((cpuRegs.GPR.r[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4; +} + + + +/////////////////////////////////////////// + +int intInit() { + //detect cpu for use the optimaze asm code + return 0; +} + +void intReset() { + cpuRegs.branch = 0; + branch2 = 0; +} + +void intExecute() { + for (;;) execI(); +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + + +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); +extern u32 vudump; +extern int vu0branch, vu1branch; + +void intExecuteVU0Block() { +int i; + +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) + break; + +#ifdef _DEBUG + prevbranch = vu0branch; +#endif + vu0Exec(&VU0); +#ifdef _DEBUG + if( (vudump&0x80) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + } + + if( i < 0 && (VU0.branch || VU0.ebit) ) { + // execute one more + vu0Exec(&VU0); + } +} + +void intExecuteVU1Block() { + + int i; +#ifdef _DEBUG + int prevbranch; +#endif + + for (i = 128; i--;) { + if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) + break; + +#ifdef _DEBUG + prevbranch = vu1branch; +#endif + vu1Exec(&VU1); +#ifdef _DEBUG + if( (vudump&8) && prevbranch == 1 ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + } + + if( i < 0 && (VU1.branch || VU1.ebit) ) { + // execute one more + vu1Exec(&VU1); + } +} + + +void intEnableVU0micro(int enable) { +} + +void intEnableVU1micro(int enable) { +} + +void intStep() { + execI(); +} + +void intClear(u32 Addr, u32 Size) { +} + +void intVU0Clear(u32 Addr, u32 Size) { +} + +void intVU1Clear(u32 Addr, u32 Size) { +} + +void intShutdown() { +} + +R5900cpu intCpu = { + intInit, + intReset, + intStep, + intExecute, + intExecuteBlock, + intExecuteVU0Block, + intExecuteVU1Block, + intEnableVU0micro, + intEnableVU1micro, + intClear, + intVU0Clear, + intVU1Clear, + intShutdown +}; + diff --git a/pcsx2/Linux/.pixmaps/pcsxAbout.xpm b/pcsx2/Linux/.pixmaps/pcsxAbout.xpm new file mode 100644 index 0000000..2ebc445 --- /dev/null +++ b/pcsx2/Linux/.pixmaps/pcsxAbout.xpm @@ -0,0 +1,334 @@ +/* XPM */ +static char *pcsxAbout[] = { +/* columns rows colors chars-per-pixel */ +"314 176 152 2", +" c #252d42", +". c #282e45", +"X c #282f48", +"o c #273046", +"O c #283046", +"+ c #2a334b", +"@ c #2d3650", +"# c #2e3853", +"$ c #303651", +"% c #303955", +"& c #333d5b", +"* c #383f57", +"= c #383e5d", +"- c #35405e", +"; c #39415d", +": c #364161", +"> c #384465", +", c #3a4668", +"< c #3e4866", +"1 c #3c496c", +"2 c #3e4b70", +"3 c #40475b", +"4 c #41485d", +"5 c #404767", +"6 c #424a63", +"7 c #434c6c", +"8 c #484f61", +"9 c #464e70", +"0 c #44506f", +"q c #4c5263", +"w c #465071", +"e c #495273", +"r c #4d5679", +"t c #4e5974", +"y c #4e587b", +"u c #515665", +"i c #535866", +"p c #545968", +"a c #595d69", +"s c #50577b", +"d c #505a75", +"f c #51597d", +"g c #5c606a", +"h c #55617f", +"j c #5a637b", +"k c #64666d", +"l c #65686e", +"z c #666870", +"x c #6b6d71", +"c c #6e7073", +"v c #767676", +"b c #545d81", +"n c #566085", +"m c #586185", +"M c #5b648a", +"N c #5e6883", +"B c #5e688d", +"V c #666d84", +"C c #606a8b", +"Z c #686f86", +"A c #626b93", +"S c #656f98", +"D c #687085", +"F c #6a738c", +"G c #667097", +"H c #667098", +"J c #6d7691", +"K c #6b749d", +"L c #6e7893", +"P c #72788c", +"I c #757d93", +"U c #6d76a0", +"Y c #6e78a1", +"T c #717ba4", +"R c #747ea8", +"E c #7c8397", +"W c #79829a", +"Q c #7680ab", +"! c #7a84ae", +"~ c #7c85b1", +"^ c #7e88b3", +"/ c #808080", +"( c #80838f", +") c #888888", +"_ c #808799", +"` c #82899d", +"' c gray57", +"] c gray60", +"[ c #858da3", +"{ c #858eba", +"} c #8d93a5", +"| c #8f95a8", +" . c #8690bc", +".. c #8891bd", +"X. c #9096a9", +"o. c #999ead", +"O. c #9aa0af", +"+. c #9ca2b4", +"@. c #a2a2a2", +"#. c #aaaaaa", +"$. c #a5a9b6", +"%. c #a7acba", +"&. c #a8adbc", +"*. c #aab0bf", +"=. c #bababa", +"-. c #8e96c3", +";. c #8e98c4", +":. c #9099c6", +">. c #959dca", +",. c #96a0cc", +"<. c #98a0cd", +"1. c #9ca5d1", +"2. c #a4add9", +"3. c #aab0c0", +"4. c #b3b6c2", +"5. c #b4b8c4", +"6. c #b6bbc8", +"7. c #adb5e1", +"8. c #b0b7e3", +"9. c #b0b8e3", +"0. c #bec2cb", +"q. c #bfc7ef", +"w. c #bfc7f0", +"e. c #c2c2c2", +"r. c #c0c3cd", +"t. c gray80", +"y. c #c2c6d1", +"u. c #ccced6", +"i. c #cdd0d7", +"p. c #ced1d9", +"a. c #d0d2d7", +"s. c #d4d5d9", +"d. c #dddddd", +"f. c #c0c7f0", +"g. c #c3cbf2", +"h. c #c8cef4", +"j. c #cad0f5", +"k. c #d9dbe1", +"l. c #d2d8f6", +"z. c #dbdff8", +"x. c #dce0f8", +"c. c gray90", +"v. c #e5e7eb", +"b. c #e6e8ec", +"n. c #eeeeee", +"m. c #e1e5f9", +"M. c #ebeefb", +"N. c #eff1fc", +"B. c #f2f3f5", +"V. c #f0f1fc", +"C. c #f7f8fd", +"Z. c #fefefe", +/* pixels */ +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 2 , , , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , > , > > , > , , : , , : , : , : , : > > > > : > > , : : : : > : : > : : : : : : : - : : - : - - : - - - - - - & - - & - - & & & & & & : & & & & & & & & & & & & & # # # # # & & # & # & # # & # # # # # # & # # & # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ X @ @ + @ @ + @ + @ + @ + + @ + + @ + + @ + + + + + + + + + + + + + + o + + o + + + o + X o X X + o o O O O O O X X O . . . . . . . . . o o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 2 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , , , 2 1 , 1 , , , , , 1 , , , , , , , , , , , , > , , , > , > : , , : : , , : , : , : > > , : : > > : : : , : : : : > : : : : : : : : : - : - - - : - - - - - - & - - & - - & : & : & : & & & & & & & & & # & & # & & & & & : & # # & # & # & & # # & & # & # # # # # # # # # # # # # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + + @ + + + + + + + + + + + + + + + o X + + o o + o + o + X X + + + o X o X X O O O O o o O X O . . . o o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 , 2 , 1 1 1 , 1 1 1 1 , , 1 , 1 1 , 1 1 , 1 , 1 , , , , , , , , , , , > , , > , , > , , , : , : : , : , > : , > > : : > > : > : : > : : : : : > - : : - : - - : : : - : - - - - - & - & & - & - & & & & & & & & & & & & & & & & & # & # : # # # & & & & & # & # # & & # & # # # # # # # # & # # % # @ # # @ # # @ % @ @ @ @ @ @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + @ + + + + + + + + + + + + + + + + o + + + + X + o + + o + o o @ + X + X o o o X + X O O O O X X . . . o o . . o . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 2 , 2 2 1 1 1 1 , , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , , > , , > , > , > , > : , , > , , , : , : > > : > > > : > : > : : > : : : : : : : : - : : - : : - - - - - - - - - - - - - - - - & : & & : & & & & & & & & & # & & & & & & & # & : # & # # & # # & # # & # # # & & & # # & # # # # # # # # # # @ # @ @ # @ % @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ + + @ + + @ + + + @ + + + + + + + X + + + + + X + o + + o + o o X X X o o + o X O O O O X O O O O . . . o . o . . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 2 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , > , : , : : : , : , > : , , : , : > > , : > : : , : , : : : : > : : : : : : : : - - - - - - - - - : & & - - - & & & : & & & & & & & & & & & & & & & & : # # & & # # & # & # & # & & # # & # # # # & # # & # # # # @ # % % # # # # @ # @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ @ + @ @ + @ + + @ + + @ + + + + + + + + + + + + + + + + + + o o @ X o + o + o + o + + X X O O + O O O . . O . . . o o o o o . o o . . . . ", +"9 2 2 2 w 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 , 1 , 1 , 1 , , , 1 1 1 , 1 , , , , , , , , , , , , > , > > , , , > , , , : , : , , : : , : > > : : : , : : : : : : > : : : : : : - : : : - : : - - - - - - - & - : - & - & - & & & & & & & & & & & & & & & # & : # # # : # & & # & # & # & # # & # & # & # & # # # # # # # # % # @ # # # @ # # @ # @ @ @ @ @ # @ @ @ @ X @ @ @ + + @ @ @ + + + + + @ + @ + + + @ + + + + + + + X + X + o + o X + + o o + o o o + o o o o o o O O O O O O O . . O . o . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , , 1 1 , 1 , 1 , 1 , , 1 , , , , , , , , , : , > , , , , > , > > , , , : , , : , : : > , : , : > > : , : : : > : : : : : : : : : : : : - : - : : : - - : - - - : & & - & - - - & : & & : & & & & & & & & & & & # & : & & : # : & & # & # & # & # & # # # # # # # # # # # # # # # # # # # @ @ # @ @ # @ # @ @ @ # @ @ @ @ @ X @ @ @ + + + @ + @ @ + @ + + + + + + @ + + + + + + + + + o + o + X + o + + + X o + + o o + o o + o O O O O O O . . O . o . . o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , , , , > , > , > , , > : , , > > , , : , > > > : > : > : : > : > : : > : : : : : : : : - : : - : - - - - - - - - - & : - - & - & & & : & & & & & : & & & & & & & & & & # # & # # & # & & # & # # & & # & # & # & # # & & # # # # & # # # # # # # # @ # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + X + o + o @ + o o + o o + o X + O O O O O O O O o o . . o o . . . o . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 2 , , , , , 1 , , 1 , , , , , , , , , , , , , , > , , > , , , , , , : , , : , , : > > , > > > > , : : , : : , : > : : : : : : > : : : - : - - : - - - - - - - - - : & & & & : & & : & & & & & & & & & & & & & # & # & # & # & & & # & # & # & # & # # & & # % # # & # # % @ & & @ & @ @ @ # @ @ # # @ @ @ @ @ @ @ @ # @ @ @ @ @ + @ + + @ @ + @ + @ @ + + @ + @ + + + + + + + + + + + o + + o + o + + + O + + O + + + X X o o o O O O O O X X O O O O O O . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 2 2 , 2 , , , , , , 1 , , , , , , , , , , , , , , , > , : , : , : , : , , : , > > : > : : > : : , : , : : : : > : : : : : : : : : : - : - : - - : - - - - - : & & : : & & : & & : & & & & & & & & & & & & & & & & & & & & # & # # & # & # & # & # # # % % # # # # # % @ @ @ @ @ % @ # # @ # @ # @ # # @ # @ X @ # X X # @ @ @ @ @ @ @ + + + @ + + + + + + + + + + + + + + + o + + + + o + + X + O O + + o O o X X X + o O X X X O O O O X . o O O O X o O . . o o o o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 1 1 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 , , 2 , 2 , 1 1 1 , 2 , , 1 , , , , , , , , , , , , , > , : : , , , : , , : : , > > : , : : : , , : : : , : > : , : , : : : : : - : : - : - : - - - - - - - & & : & : & & & & & & & : & & & & & & & & & & & & # & # & & & # & & # # & # # & & # # & # & # & # # # & & @ @ @ % @ @ % # @ @ @ # @ # @ @ @ # @ # X # # @ @ X @ @ @ @ @ + @ + @ + + @ + @ + + + + + + + + + + + + + + + X + X + + + o + o X o + X X X + o + + o O + O O O O O O X o o O O o . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 2 , 1 , , , , , , , , , , , 1 , , , , , , , , , > , , > , , , , : , , , : , , > , : , : , , : : : : , : : : : : : : : : : : : : : - : : - : - : - - - - - - : : : & & : & : & : & & & & & & # & & & & & & & & & & & & # & & # & & & # & & # # & & # # # # # & # # # @ @ & @ @ % # @ # # # @ @ # @ @ @ @ @ @ # # # @ @ @ @ @ + @ + + @ + + @ + @ + @ + + + @ + + + @ + + + + + + + + + + + + O + + + O + + X + o X X O O o o O O O O O O X X O X O O O o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 , , 1 , 2 1 , , , , , 1 , , , , , > , , , , , , > , : , , , , : , , : : , > > , : , : : > , : , : : : : : : : , : : : : : : : : : : : : - - - - - - - - & : & : & - & & & : & : & & & & & & & & & & & & & & & & # # & # & # & # & & & & # # # & # % & # & # # # # & # # & & @ % @ @ % @ @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + X + + + o + + X + + O + X + X + + O + O O O O O O O O O O O O . X O O o . o O . . o . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 2 1 , 1 , 1 1 , , , 1 1 , , , , , , , , , , , , , > , , , , , : , : , : , , , : > > : , : , > > : > > : , : , : : : : : : : : : : : : : : : - : : - : - - - - - & : & & & : : & & & & & & & & : & & & & & & # & # & & & & & # & & & & # # # # & & # & # # # # # # # # # # # @ @ % @ @ @ @ @ & @ @ # # @ @ @ @ @ @ @ @ @ X @ X @ @ + + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + + + + + O + + o X + + o O O O O O + O O O O O O O o O . O O . . O . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , : , : , , : , , : , , : , , > > , : > , : : : > > : , : , : : : : : : : : : : : : : : : - - : : - - - - - - : : & : : : & & : & & & : & & & # & & & & & & # & & & & & # & # & # # & & # & # & # # & # & # # & # # # # # # & @ @ @ % # # # # # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ + + @ + + @ + + @ @ + + + + + + + + + + + o + + + o + + o o + + o O + + O + X O + O O O O O O O O O X O o O O O X o . . . . . o . . . o ", +"e 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , , , , 1 , , 1 , , , , , , , , > , , , , , , , : , , , : , : , > > : > , : : , , : > > : : : : : , > : : : : : : : : : : : : : - - - - - - - - : & & - & & : & & & : & & & & & & & & & & & & & & & & # & & & & & # & & # & # & # & # # # & % & # # & # # # # # @ & % @ # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ + + @ + + + @ + + @ + + + + + + + + + + o + + X + + + + X X + X X + O O O + + O O O O O O O . X O . . . . . o . . o . . . . . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , 1 , 1 1 1 1 , , 1 > , 1 > , , 1 , , , , , , , , , , , , , , , , : : , , : > > > > > , > > > : : , : > : : > : > : > : : : : : : : - : - - - - - - - - - & - - : & & & & : - & & : & & & & : & & & & & & # & & & # & & & # & # & # & # & # & & # # # & # % % % % % % % % @ # # # # # @ @ @ # # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X X @ + + @ + + @ + + + + + + + + + + + O + + + o + o + + O + O O O + O + X O O + O + X O X o O . . . . o o . . . . o . O O O O ", +"2 2 2 2 2 2 2 e 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 1 1 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 1 1 1 , , 1 1 , , 1 , , , , , , , , , : , , , , : , , : , , , , : , > > > > : : > : , : > : : : , : : > : : : : : : : : - : : : - : : : - : - - - - - - & : : : & & - - & & : & & & & & & & & & & & & & & & & # & & & # % & # & # & # # # & # & # # % % % @ % @ % % @ % @ # # @ % # @ @ # @ @ @ @ @ @ @ X @ @ @ @ @ @ @ X @ X @ X @ @ + @ + + + + + + + + + + + + + + + + + O X + + o + X o O O O + O O O O O O X X O O O O O O . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 1 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , , , 1 , , , 1 , , , , , , , , , , : , : : , : , : , , : , : > > > > > > > > > > : > : : : : : : : : : > : : : : : : - : : - - - : - - - - - & : & & & : : & & - - & & & & - & & # : & & & & & & & & & # # & & & & # & # & # # & & # % # # # @ % % % @ % % @ % # # # @ % # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ + @ @ + @ + + + + + + + + + + + + O + + + + O + O O + + O + o + O + O + O o O + O O O O O O O X . . . o . . O O . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 , , 2 , , 1 , , 1 , 1 , , > 1 , , , , , , , , , , , , , , , , , , > , : , , , : > > > > > > > : : : , : > , : > > : > : : : : : : : : : : : - : : - - - - : - - - - : & : & & & - & & & & & & & & & & & # : # & # & & & & & & # # & % & & # # & % # & # # & % & % % % @ % % % # # # # # @ # @ # # @ @ # @ # @ @ @ @ @ @ @ @ X @ @ @ X @ @ @ X @ + @ + + + + + @ @ + + + X + + + + + + + O + + + + + o + + o + X + O O O O O X O O O O O X X . . . . o . X O o . . o O . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , , 2 , 1 , 1 , , 1 , 1 , 1 , , , , , , , , , > , , , : , : , , : , > , : , > , , , > > > > > > > > : > > : : > : > : > : : : : : : > - : > - : : - - : - - - - - - - & - & & & : & & & & - & & & & & & & & & # & & & & & # & & & # # & & & & # # # % % & % # % # # % # @ % % # # % % @ % @ # # # $ # @ # @ @ @ @ @ @ @ @ @ @ # @ @ + @ @ @ X @ X @ @ + @ @ + + + + + + + + + + + + + + X + + + O O + O O + O O + o O + O + O O O O + X O O O O O . o . . . . o . O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , 1 , , , , , , , , , , , , , , > , , , , > , > > > , : > > > > : > > > > > : > > : : : : > : > : : > : - - : - : - - : : - - - - - - - - - - : : & & : & - - & - & - & & & & & & : & & & # & & # & & & & # # # # & & & & % % % % % % # % % @ % % # % @ # # @ % # # @ # @ # @ @ # @ @ @ @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + + @ @ + + + + + + + + + + + + + + + + + + + + + + O + o + + O O O O + O O O O X O o O O . o O . o . . o O O O O O . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 , 1 1 , 1 , , , , , , , , , , , , , , , , , , : , , , , : , > > > > > > > > > > : > > > > : > : , : : : : > : : : : - > > - - - : - - : : - - - - - & : & : : & & : : & & & & & & & & & & & # & & # & & & & & & # & & & & # & # & # % % % % # # % & # % % % # # # # @ % # # # # # @ @ # # @ # @ @ @ @ @ # X @ @ @ @ @ @ @ X + @ X @ + @ @ + + + + + + + + + + + + + o + O + + O + O O + O O + + o o O + O O O + + O O O O O O X O . o . o o . . . . O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 2 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , : , , , : , : , : , , > > > > > > > > > > : : > > > : > : : > : : : : > : : > - - - - : - : : - - : - - - - : & : & & & : & & & - & & & : & & & & & & & & & & # & & # & # & & # & # & & # & % % % % & # % # % # % % % % # # % @ % @ $ # # @ # @ @ # @ @ @ @ @ @ @ @ @ @ X @ @ X @ + @ @ X @ + @ + + @ + @ + + + @ + + + + + + + + + + O + + + O + O + o X + O X + O O O O O O O O O O O . O o o . o o . . O O O . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , , 1 1 , 1 > 1 1 > 1 , , , , > , , , , , : , , : , , , , , > , > > > : , > > > > > > > > : > : , : , > : : : > : : : - : : : - : - : - : : - - - - - & : & : & & : & & & & & & : & & & & & : & & & : & & : & & & & # # & & # & # & # # & % % % % % % % # # # % % # # # % # @ % @ @ % @ # @ # @ # @ # @ @ @ @ # @ @ @ @ @ @ + + @ + + + @ + + + + + + @ + + @ + + + + X + + X + + O + + X X X + O + O O + + o o O O O O O O O O O X . . . o . . o . o . . . o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 1 1 2 1 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 1 > 1 > , , 1 , , , , , , , , , , , , , , > : , > > > > > , : , > : : > : > : > : : : : : > : : : : : : > : : : : : : - : - : - - - - - : & : & & : & & & : : & & & & & & & & # & & & & # & # # # & # & & # # & # & # & & % % % % % # % % % % # # # % # # @ @ % # # # # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + + @ @ + + @ @ + @ + + @ @ + + + + + + + + + + + + + X + + + + + + + X + O X O X X + O O O + O X O O O O O O . . o . o . O o O . o O O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 > 1 1 > , 1 , , , , , > , , , , , , > , : , > , > , > , , : , : > > : > > : > : , : , : : : > : : : : : : - : : : - - - - - - - - - - - : : & : : & : & & & & - & : & & & & & & & & : # & & & & # & & & & & & & & # & # # % % % % % % % # # # % % # # # # % @ # @ # # @ # # # @ @ # @ @ @ @ @ @ # # @ @ @ @ @ + + @ @ X + @ + + @ X + + + + + + + + + + + + + O + + + X X + X X O + O + O O X X O O O O X O O O O X o O . . o . . o . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , 1 , 1 1 , 1 1 > 1 , , , , , , , , : , , , : , : , , , > > > > > > > > > > > > > > > > : , : : : : , : : : > : : : : : : : - : : : : - - : - - - - & & : & & & : & : & & & & & & & & & & : # # # # & & # & & & # & # & # # # & # & # & % % % % % % % % # % % % % # # # % # # # @ # @ # @ @ @ @ @ @ @ # X @ # X @ @ X + @ @ @ + @ @ @ + @ + + + @ + + + + + + + + + + + + + + + X + O O + + O X X + + O + X O O + O X + O O O O o O . O . . . . o . o . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , 1 , , , 1 > , , , , , , > , , , , , , , , , , , > : > > > > : , > , : : > , : > > : : : , : : : : : : : : : : : : : - - : - : - - - - - - - : : & : : & - & & & - & : & & & & & & & & & & & & : & & & & # & & # & & & # % % % % % % % % % % % % % % # # # % % # % # % # # # # # @ # @ @ @ @ @ @ @ @ @ @ X # @ @ @ + @ + @ + + + @ + + + + @ + + + + + + + + + + O + + + O + + + + O + O + O O O O O + O + X O X O O O O O O O o o o o o . . . . . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , , , , , , , , , 1 , , , , , , , , , , , : , : : , , , , , > , > > , > : : , , : : , : > : : , : : : : , : : : : : : : : : : : - - - : - - - - - - & & : & & - : & : & & & & & & & & & & & & # & & & # # # & # & & % % & # % & % % % & % % % % % % # % # # # # # # # # # @ @ @ % @ # @ @ @ @ # @ @ @ @ @ X @ @ @ @ @ @ @ @ + @ @ X + @ + @ @ + + + + + + + + + + + + + + + O O + + + O O + O + O + + + O X O O O X O O O O O O O . O o o o . . . o . . . o o o o O ", +"2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , , , 1 , 1 , , , , , , , , , , , , , , , > , , , > , : , , , > > , > : , , > > > , : : : > > : : : : : : : : : : : : : : : : - : : : - - - - - - - - : & : & : & & & & & & & & & & & & & & & & & & & & # & & & & # & % & % & % & % & % % % % % % % % % # % # # % # # % @ # # @ # @ @ @ # # # @ @ @ @ @ @ @ @ @ @ @ # + + @ + @ @ + @ @ @ + + + @ + + + + + + + + + + + + + + + + + O + O + O O X + O O O O + O O O O O O O O O O O o O . . . o . . o o o . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , > , , > , , , > : , , > > , > > > > : > > > : > : , > : , : , : , : : : : : : , : : : - : - - : : - - : - - - - & : & : & - & : : & & : & & & & & & & & & & & & : # & & # : # # & % & # & # % % % & % % % % % % % # # % # # # # $ # # # @ % % # @ @ @ @ @ @ @ @ @ @ @ @ X # @ X @ @ @ + @ + @ + + + @ + + + + @ + @ + + + + + + + + O O + + + O + + O + + + O O + O + O O + O O O O O O O O O O . . O . . . o . . . . o o O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , > , , , > > > > > , > , > > , : , : , : > : : > > > > > : : > : : > : : : : : : : : : : : : : & : & & : - - : - & : & : # : : : # : : & & & : & @ - - - # - - - @ - - @ # - # # - - # # - # # # # % % - # # % % # # # # # # # # # # % # # @ % # # @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + + @ + + + + @ + @ + + + + + + + + + + + + + X X + + + + X + o + O + O O O + X O X o O + O O O O O O . . . . . o . . . . o o . o . O O ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , , 1 1 1 1 , , , , 1 , , 1 , , , , , , , , , , , , > 1 > 1 > 1 > > , > > , , : , > > : , , : : > : > : > : > > : : : : : : : : & : : : : : : : : : : - : & : : & : & : : : # # : : # # : : # - - # - @ - @ - - @ @ - - # - # # % # - # # % - - % % % # % # % % # & # # # # # # # # # # # @ @ # # @ # @ @ @ @ @ @ @ @ @ @ + @ @ # + @ @ + @ # @ @ + @ + + @ + @ + + + + + + + + + + + + X + + + o X + + O O + O O o o + o o o O O O O + O X X . . . o . . o . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 2 2 1 1 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , > , , , 1 > > 1 > > > > , : : , > > , : , : , , > > > > > : : : : > > : > : : : : : : - & : : : : : - & : & : & : & & : : # : : : # : : & : & & # - - - - - # - - - - - # - - # # - - # # - # - # % % % % % % % & # # # % # & # % @ % % # # # # @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ + + + + + + + @ + + + + + + + + + + + o + + + + o X + o + O + X o + o + + + O O O O O O O X o X O . o o . O X O . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 1 1 1 1 1 2 2 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , 1 1 , , 1 1 , , 1 , , , , , , , , , > > > > > > > , > , , , : > , : > : , : : : > > > : > > : : : : : : : > : : : : : : : : : : & : : & : & : : & : & : : # & : : & & # : # & - - # # - # - # @ # - @ # - # - - # - # # - # % # % % % % % % % # # # & # # # # @ % @ % # @ @ # # @ @ @ # @ @ @ @ @ @ @ @ + @ + + # @ @ + @ + @ + @ + @ + @ + + + + + + + + + + + + + + o + + X + + X + + X + + O + o o O O + O O O O O X o O . . o . X . X . o o . o O O O O ", +"2 2 2 2 2 2 0 2 2 2 2 2 1 2 2 1 2 1 2 2 2 1 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 1 , , , , 1 , , 1 1 , , , , 1 , , , , , , > > 1 > > > > , , > , : > > , , : , > , : > , > > > : : > : > : : > : : : : : : : : : : & : & : : : & & : - - & : & & : & : & & : : # : # : # @ - - - - # - - - @ - # - # - # # % # - # # # % & % % % % % % % # % # # # % # % % # # # # # # @ # @ # @ # @ @ @ @ @ @ @ @ @ @ @ # + # + + @ + + # @ + + + + + + + + + + + + + + + + + + + + + o + X + + + o o X O O O X O O O O O + X O O . X X . . O o . . . . . . o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , 1 , , , , , , , , , > , , , , , , , > , 1 : > > > , > , : : , : , > > : : > : : > > : > : : > : : : : : : : : : = : : : : & : & : : : & : : & : & & : & & : : # : & : : : - - @ - - - # @ - - # - - # # # - % - # # - - % % % % % % % % % % % % # # # % # # # # # @ # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ + @ + # # + @ + @ + + + + @ + # @ + + + + + + + + + o + + o X + + + + X X + o + + X + + O + O O O O O O O X . O o O O . o o . O . o o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 1 , 1 1 1 , , , 1 , , 1 , , , , , , , , > > , > > > 1 > , , : , , , > > , : : , : > , > > > > : : > : > : : > : > : : : : : : : : : : & & : : : - & - : & : & : : : & : # : & & & & # : - - @ - # - - - # - # @ # - # - # - # # # # - % % % % % % % % % # # # % % # # # # @ % @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ @ + @ + @ + + @ + + + + + + + + + + + + + + + + + X + + + + + X X X X + o X + O + + O + O O O O O O O O . O O o o . O . X o o . . o . . O O O O ", +"2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , , , , 1 , , 1 , 1 , , , , , , , , , , , > , , , , , 1 > > > , : , > > : , > , : > > > > : : : : > > > : > : > > : : : : : : : : : : : : : : : : : & : & : & : & & : & & & & # : : # : & & & # - - - - # # - - # - - - # - # - # # - - # # # % & % % % % # % % % % % % # # # # # @ % # # % @ # @ # @ @ @ @ + @ @ @ @ @ @ + @ + @ @ @ @ + @ # + + + # + @ + @ + + + + + + + + + + + + + X o + + + X + X + + o + X O O O O + O O O O O O O O O . . . . O O . . . . . O O ", +"2 2 2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 1 1 2 1 2 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , , 1 1 , , , 1 1 , , , 1 , , , , , , > , > , , > > , , , : , : , : : , : , : > : > , > > > : > : : : : : : : : : : : : : : - : - : - : - - - - - & : : & : & : : : : : : & : # & # : # - - - # - - # - - # - - # - # # & & # # & # & % % & # # & # # # # # - # # % # + - - + - + + - # @ @ @ # @ # @ @ + # # @ + @ + @ + + @ @ + @ + + + # + @ + + + + + + + + + + + o + + o + o + + + O O + O + O X X O X O O O + X O O O O O O X . . . . . o . . . o . o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 1 2 1 2 1 1 1 2 1 2 1 1 1 2 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , , 1 , , , , , 1 , , , , , , , , , , , , , > > 1 > : , , , , , , , : , , , > , > : > : : > > : > : : > : > : > : : : : : - - : - : - : - : - - : : & : & & & : # # : # : # : : : # - - # - - # - # @ # - # # - # # & # & & & # & # % & # & # % # % # # # # # # # # @ + + - O - + $ # # @ # @ @ @ @ # + @ + @ # @ @ + + # + @ + @ @ @ + + + @ + + + @ + + + + + + + + + + + + + + o + + + O + O + + + O + O X O X X O + O O O X O O . . . o o o . . . . . . . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 2 , 1 1 1 , , 1 1 1 1 , , 1 , 1 , , , 1 , , , , , , , , , , , > , , , > , > > , , : : , , : , : , : : > , : > : > : > > > : > > > : : > : : : : : : : : : : : - : - - : - & : & : & & : : # : : : : & : & : & & # - - # # # - - - # # - - # # - & # & # # & # & & & # # # & % % # # + - # # # # - + + + - O o + @ @ @ @ @ @ @ @ # # @ @ @ @ + @ # + @ @ @ + @ + + + @ + + @ + @ + + + + + + + + + + + + + + + o X + + X O + O O X + O + o o X X O O O O O X O O . . . o . . . . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , 1 , , , , , , , > , > , , , , > , , > , , : , , , : , , : , : , : > > : : : > : : > : : : : > : - : : : - : - : - : - - - - & : & : : & : : : # # : & & # : # : - - # - - - - # - - - - # - - # # & & # & # & # # % & # # % % # - # # # # # % # - @ - @ O - - + # @ # @ @ @ @ @ + @ @ # + # # @ + @ @ + + @ + @ # + + @ + + + + @ + + + + + + + + + o + + o + + + O X + O O + + O O O O X + X X O O O O + X O X O O o . . . o o o . o . o . o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 1 1 , 1 1 , 1 1 , , , 1 1 1 , 1 , , 1 1 , 1 , , , , , , , , , , > , > , , , > > > , : > , : , , : : , : , : : > : : , , : > > : : : : > : : : : : : : : : : - : - - - : - - - - - : & : & # : : : : # & : : : & # - # - - - @ @ - @ + - - # - # - & & & # # & # & # & # # % % % & - + # # - @ + - + - + @ + + - - # # # @ @ # @ @ # @ + + + @ @ @ @ @ + o @ @ @ @ + # + + + + + @ + + + + + + + + + + + + + + + o + + X O + O + O O O O O + + O + + + + O O + O O O O X X . . O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 2 2 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 , 1 1 , , 1 , , , 1 1 , , , , , , , , , , , , > , , , , , , , : , : , : , : : , : , > : : > > : : > > : : : : : : : : : : = : : - : : - - - - - - & & : : & : : # : : : & : & & : : - # - # - - - - - - - @ - # - # & # # & & # & # # # & & % # # # # + - + + + - @ @ @ + - - + + + @ # + # @ @ @ @ # + # @ # # + + + + # @ @ o + o + @ + + @ + + + + + + + + + + + + + o + o + + + O + X + O O O O + O + + + + + + + $ $ $ + $ + + + O O O O . . . . . . . o ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , , > , > , , > , > , , : : , , : , : , : , , : > : > : : : : > > : : : : : : : : : - : : : : : : - - : - - - - - - : & & : # : : # & # : # & & & & - - # - # - - # @ - - @ # - # - # & & # # & % & & # % % & % # % + - - + @ # + @ + - @ @ - + + - # @ # @ # @ @ @ + # + # @ + + @ @ + @ @ + @ @ + + + + + + + + + + @ + + + + + + + + o + + + o o + O O + O + O O + O + + @ + % % $ * # * * @ $ + + + O O O O o o o o . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 2 1 1 1 1 1 1 1 1 1 2 1 , 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , 1 , , , , , , , , , > , , , , , , > , > > , : , , , > > , : , : , : : , : , : , , : : : : : : : > : : : : : : : : - : - : - - : : - - - : & & : : & : & : : : : # : & : # & # - - - @ - - # - - @ - - # - - & # & & & # & # # & % # # # # & - @ + - + - - O - @ + - + - + + @ # # # + @ @ @ @ @ # # + # # @ + # @ @ + + @ @ @ + @ @ + + @ + + + + + + + + + + + + + + + + + O + + O + O + + + + + + % # * ; ; > : ; ; = * $ $ + + + O . . . . . o . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 2 1 1 2 2 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 , , , , 1 1 , 1 , , 1 1 , , , , , , , , , > , , , > , : , , , : , , : : , : , : , > : > : : , : > > : : : : : > : : : : : : : - : - : - - - - - - & - & : & : & & & : # : & & # : : & & & & & # & & & - 8 4 4 4 8 < 4 , , , < 4 4 4 8 4 4 4 4 4 4 4 4 4 4 4 4 8 4 4 - $ @ $ - + + - o # @ @ @ @ @ + @ + # @ + @ + # + @ @ + @ @ + @ + + + @ + + + @ + @ + + + + + + + + + + O + + + O + + X + + o + + + + + # = ; 5 7 2 e e e 1 7 < = # @ + + + O X . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 , 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 , 1 1 1 , , , , , , , , , , , , , , , , , , , > , > > , , : : , , : , , : , : , : > , : , > : : > : > : : : : : : : : : : - : : : : - : - - : - - : - : & : & & : & & & : & : & & & & & & & & & & & & 4 v v v v v v v v c v v v v v v v v v v v v v v v v v v v v v v k ; - + + - - $ # # @ # # @ # # @ @ @ @ @ @ + @ + @ @ + + @ @ + @ + @ + + @ + + + + + + O + + + + + + + O O + + O + X + o + O + + @ * * > 7 e s n M M m n f e 7 > * # + + O . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 > 1 , 1 1 , , , , , , , , , , , , , , , , , , , > , , , > , , , , , , : : , , : > , : > , : : , : > , : > : , : : : : : : : - : : : : : - : - : - - : - : & : : & : : & : & & & & : : & & & & & & & & & & # 4 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k $ @ O - $ @ # @ @ @ @ @ @ @ # @ # @ # # @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + + O + + X + o + o + + $ # * > w f M S U T R T K S m f 9 : * % + + O X . . . X . . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 , 2 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 1 , 1 , 1 , 1 1 , 1 , , 1 , , , , , , > > , , , : , , , : : , , , , : > > , : , : : , > : > : : : : : : : , : : : : : > - : - - - : - : - : - - : & : & & : & & & : & : & & & & & & & & & & & & & & & 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x ; - + O # @ @ # @ @ @ # @ + @ + + + # + @ + @ @ + @ + @ + + @ + + @ + + + + + + + + O + + X + O + + + + + + + X + + + @ $ ; > 0 f C K ! ..;.;.;. .~ Y B f 7 : * $ + O . . . . . X X X X X X X X X . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , 1 1 > 1 1 , , 1 > 1 > 1 , , , , , , , , , , , , , > > , , , : , , , : , > , > : , > > : > : : > : : > > : : : : , : : : - - : : : - : - - : - : & : & - : & : & & & : & & & & : & & & : & & & & & & # & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v l - # @ @ @ @ @ # @ @ @ @ @ + @ # + @ + @ @ + @ + @ + @ @ + + + + @ + @ + + + + + + + + + + O + + + O O X + + o X + + $ # ; 7 y A R { <.2.7.9.7.2.>.{ R A r 7 = $ $ + X O . O X + X X $ + + + X X X X ", +"2 2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 1 2 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , 1 1 1 1 > 1 1 , , , , 1 , 1 > , , , , , , , > > , , : , , , > : , : , : , , > , : , , : > : > : > , : : > : : : > : > : : : : > : : : - : - > - - : - : & : - : : & & : & : & & : : # & : # & & & & & & & & & < v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v k # $ # @ # @ @ @ @ @ @ @ @ @ @ @ @ # + @ @ + @ + @ + @ + @ + + + + @ + + + @ + + + + + + + + O + + + O + + O + + + % = , e M K ..1.9.w.j.j.j.w.7.1.{ Y M w 5 * $ + + O O . + + + $ $ $ $ $ * $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 1 , 1 > 1 1 , , 1 , , , 1 , , 1 , , , , , , , , , , > , , , , > : , , , , : > : > > : , , : : , , , : : , : : > , : : : : : : : - : : - : : : - : : - - : - - - & : & : : - & & & & & : : & & & # & & & & & & # 8 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 $ # @ @ @ # # # @ @ @ @ @ @ + @ + + # @ @ + @ @ + + + + + @ + @ + + + + + + + + + + + + + + + O + + + O + + + + # ; 7 f S ~ <.9.g.l.x.x.x.l.h.9.>.! G r 6 & $ + + O O + + + % * * = = 3 * * = $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , , 1 , 1 , 1 > , 1 > , , , , , , , , , , , , > > > , , , : , > > , , > > > : : , : > : : : , : : > : > : : : > : : : : : : : : : - - - - : - & : : & : & : & & & : & & : & & : # : # : & & & & & & & 0 v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v c # # @ # # @ + @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + @ + @ @ + + + + + + @ + + + + + + + + O + O + + O + o + o + + @ % : 7 n U ..2.w.l.m.M.N.M.m.l.w.2.{ Y b 9 = $ + + + + + $ % = > 6 7 9 9 9 7 5 5 = ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , 1 , , , , , 1 , , , , , > , > > , , , , , > , > , : , , : , : , : , : : > > : , : : > : : : : : : : : : : : - : - - - : : : & : & & & & : & & : - & : & # : : # : & : & & & & & & & & , D c v c v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 8 # @ @ # # @ # @ @ @ @ + @ @ @ + @ + @ @ + @ @ + @ + @ + @ + + + + + + + + + + + + + + + + + + + + O + + + + + * > e m T :.8.h.z.M.C.C.C.M.z.j.7.;.T M w ; $ $ X + $ $ * ; 7 w r b m M m b s 9 5 = % $ X $ . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > > > , , > > > , : : , : , : , : : , : > , : : : : > : > : > : : : : : - : - : > - & & : : : : : : & : & : : # - & & - & & : : # : & & & & & & & # : h l l l l l l l l l l l l l l l l l l l l l l v v v v v v v v v v v v v v v c @ # @ @ @ @ # + @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + @ + + + + @ + + + + + + # + @ @ + $ + + + + O + X + X + + $ & ; e C R :.9.h.m.V.Z.Z.Z.V.x.j.7.:.T M e 5 $ $ + + $ * : 7 r b S K T T T K A m s 7 3 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 2 1 2 1 2 1 2 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 , , , , 1 , , , , 1 , 1 , , , , 1 , , , , , , , > , > > , > , , > , , > , > , , : , : , : > , : > : : > : > : > : > : : : : > : : > - : - > - : : & : & : : & : & : & - - : & : & & & & # & : & & & & & & & & & & - & & # & # - # - - # & - % # - # # # & % % # g v v v v v v v v v v v v v v - - # @ @ @ @ @ @ @ @ @ @ @ + @ @ + + @ + @ + + @ X + @ + + + + @ + + + @ % # # # @ % $ % + + + + X + X + + + & > e M R ;.7.h.m.M.C.C.C.M.x.h.7.;.T M w ; * $ + $ * ; 7 s A T R ..-.-.-.{ ! K B s 7 3 $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , , , , , , , , , , , , , > > , > , > , > > , > > , > , : > , : , : , > : , : > : > > : : : : : : : : : : : - - : - : - - & : : : & : : & & - - - - & & - & & & : : : # # & & & & & # & & & & & & & & # & # - # # - # # # # # # & % % # # # @ g v v v v v v v v v v v v v i o @ @ # @ # @ @ + @ @ @ @ + @ + @ @ + @ + @ + @ @ + @ + @ + @ + @ @ # % # % % = # * * * @ # % $ + + + + + @ * ; w b K { 2.q.l.m.M.V.M.m.l.w.2.{ K b 7 ; $ $ $ $ = 6 r C R { >.2.2.8.7.2.>.{ Y C s 4 * * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , > , , > , , , : , : > , : : , : : > : : , : : > : : : > > : : > : : : : : - : : : > - - > : : & : : : & : : - : & : # - & & : # : & : : & & & & & & & & & # & # & & # & # - # # - # # % % & # # # & # & # # # - v v v v v v v v v v v v v c @ @ @ + # # @ # + + # @ @ @ @ @ + @ @ @ + @ + + X @ + + @ X + + @ $ % & = = : < < > : ; = # @ $ + + + + + $ # = 7 b S ~ <.9.h.l.z.x.x.l.h.9.>.~ G s 7 * % $ $ % 3 e m K { 1.8.f.h.j.h.f.8.1.{ U b r ; * . . . ", +"2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , , 1 1 1 , , , , , , , , , , , > , , , : , , > : > , > , > , > , : , > > > , : : , > > > > : : : > : : > : : : : : - : - - - - - : & : & : : & : & & : : : & & & & : & # & : # & & & & & & # & & & & & & & & # # - - # # - # - & % & % & # % # # # # p v v v v v v v v v v v v v - @ @ @ # + # + # # # @ + @ + @ + + @ @ @ + + + @ + @ + + @ @ @ # * = : 5 7 e e e e e 7 5 > = $ $ $ + + + + $ & , e b Y { 1.9.w.g.j.j.w.9.1.{ K M e : % % $ % = 7 s G R <.8.h.l.z.m.z.l.h.8.>.R A s 5 * + . . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 1 2 1 1 2 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , , 1 , 1 1 , , , , 1 1 , , , , , , , > , , > , > > , > , , , , > > > > > , , > , > : > > > : : > > : : : > : : : > : : : : : - > - > - - : - : - & : : & & : & : & # : : : & : & : # : & & & & & & & & & # & & & & & & & # - # # # # - % # & # % # # & % - # # ; v v v v v v v v v v v v v < @ @ @ @ @ # # # # + + @ @ + @ @ + @ + @ + @ + + + @ + @ + $ % % : 5 7 r b b M M M m f r 7 < = # $ + + + + $ % = 7 y A T { >.2.7.7.7.2.>.{ T A r 7 = * + % % = 7 b K .2.f.l.m.M.M.M.m.l.g.2...K b 7 . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 1 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , , , , , > , > , > > , > > : : , : > , : , : , : : > > : : > : > : : : : : : : : - - - : - - & : : : : & : : & : # - : - & & & # : : & # : & & & & & & & & & & & # # & # & - # # - - # # # % # & # # % # # # # # # l v v v v v v v v v v v v q - @ @ @ @ @ @ @ + @ # @ @ @ + @ @ @ + + @ + @ @ + + @ + $ % & : 5 w f M K K R Q R K S M b 9 5 = & $ + + + $ $ = > 7 b A Y ~ -.;.:.-.-.~ Y C f 9 > * $ + $ % : w b Y ;.8.h.z.M.C.C.C.M.z.j.2.-.T b 9 ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , 2 , 2 , , 1 , 1 , , , 1 , 1 , , , , , , , , , , , , , , > > > , , > > > > > > : , > : , : > > > > : > > : > > : : : > > : : : : : : : : : : : & : : & : : - & - - & & & : & E u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.v.u.} 6 % & & # & & # # # & % % % % % # # % # % # * i v v v v v v v v v v v v a - o - O + + + - + + + + + @ @ + @ @ + @ # + + + @ + $ @ @ # = < e f G Y ^ ..:.>.;...^ K S b 9 < = @ + + + + $ % = : 9 s M S K T R T K A m s 7 : * $ $ + $ $ ; e C T :.8.h.m.N.C.Z.C.N.x.h.8.:.T N w ; $ + O . . ", +"2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 2 , , 1 , 1 , , 1 , , , , , , , 1 , , , , , > , > , > , > , > > , > , > , > , : > : : , , : > : > : > : : : : : : : : : : : : : : : : & : : : : & : : & : & = - - : & & : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.E % & & # # & & & # & % % % % % % % % # # # q v v v v v v v v v v v v k o - @ @ - + + O - + - O - + @ + @ + + + + + @ + + @ @ @ $ ; ; 0 f A R .<.2.7.9.7.2.<...R C f 7 : # $ $ + + + $ % * 3 7 e s m M M m m f w 7 > * % $ + + + * ; w b T ;.8.g.z.M.C.Z.C.M.z.h.7...T b 9 * $ + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , > , > , > > > > > > > > : > : > , : : , > > > > > > : > : : : > : : : : : : : : : - & : & : & : : & : : : & : & : & & +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.E # & # & & # & # % % % % % % % % % % $ # 3 v v v v v v v v v v v v k - o O @ + O - - O @ + + + + + # @ @ # + # @ + + + @ + # % ; < r M Y .1.9.w.j.j.j.q.9.1...K M e 7 = $ + + + + + $ % = : < 5 w w e w 7 5 5 ; * % + + + + + $ ; 7 b K { 2.f.l.m.M.N.N.m.l.f.2.{ K b 9 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , , 1 , 1 1 , , , , , 1 , , , , , , , , , > , , , , , , > > 1 > > > , > , , > , > : : , : : > : : : : > : : > : : : : : : : : : : : : : - : : : & & : : & & : & : & : & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.m & & & # & # & & % % % % % % % % # # # 4 v v v v v v v v v v v v k o - - @ @ - O + + @ - o - + + # + + + @ + + @ # + + @ @ ; ; 0 f S ^ <.9.j.l.x.x.x.l.j.9.<.^ S s 7 = $ $ + + + + + $ @ # = = ; > ; ; ; = * % + + + + O + + $ * 7 r A { >.8.g.l.z.x.z.l.g.8.>.R S s 6 * $ O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 2 , 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 1 , , , 1 , 1 1 , , 1 , , , , , , , , > , , , , > , > 1 > , > > > > > , : , : , , : , > : > > > : > : > : : > : : : : : : : : : : - : : : & : : & & : : & : & : & & o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.k.# & & % % % # % % % % % % % % % # # # 4 v v v v v v v v v v v v k + O $ - + + + + # + + - + + @ @ + + + + + + + @ + + @ # ; ; w n Y ..2.g.l.m.M.N.M.m.l.f.2. .K m w ; * + + + + O + + O $ $ % % $ * % * $ $ $ + + O O O O + $ % 5 r b K { 1.8.f.g.h.h.f.8.1.{ Y b w : $ $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 1 1 2 1 1 2 2 2 , 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 , 1 1 1 1 1 , , 1 , , , , , , , , , , , , , > , , , > > , > , > > > , , > > > : , : , : : , : > > : > : > : > > : > : : : : : : : - : - : : - : & : : & : : & & : & : & = : o.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.L & # & % & & % % % % % % % % % % # % 4 v v v v v v v v v v v v k - O - + - + + - + # + + @ + + @ @ @ @ @ @ @ # + @ @ # # - > e M Q :.7.j.x.N.C.Z.C.M.x.h.8.:.Y B e > * % + + + X + + + + + + $ $ + $ + + + + + O X O O + + % = 5 s C U { >.2.8.8.8.2.>.{ T C s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 2 2 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , > > > > , > > > > > > , : , : , : : , > : > > : > : : : : : : : : : : : : : : : : : & : : : & : : : : & : & : : & & t D V V V N D V N V V V x V V V o.Z.Z.Z.Z.Z.Z.Z.Z.Z.0.# & & % % % % % % % % % % & % # % # 4 v v v v v v v v v v v v k - - o + + + @ @ + # # + + # + @ @ @ @ + @ + + @ + + # # - < r B Q :.9.j.x.N.C.Z.Z.B.m.j.9.>.Q B e > # @ + + X O + X X + + + + + + + O + O O O X X X O X O + $ % ; 7 f C K ! { ;.:.-.{ R Y C s 7 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 1 2 1 , 2 1 1 1 1 1 1 1 2 , 1 1 1 1 1 , 1 1 1 1 1 , 1 , 1 , , 1 , , , 1 1 , , , , , , > , , > , , , , , > , , > > , , > , > : , : , : , : : > > : : > : > : : > > : > : : : : : : : - : : : & : : : : & & : : & : & & : & & & - & & & - - - & & - & & & % # } Z.Z.Z.Z.Z.Z.Z.Z.Z.< # % & % & % % % % % % % # % % % % 8 v v v v v v v v v v v v k o O + - - o @ @ @ # + o - + @ @ + + + @ + @ + + @ @ # # - < e M Q ;.7.h.x.N.C.C.C.N.x.h.9.:.R M e > * + + + + O O O O X O + O O + O O O X O X O O O O O O + $ % 5 7 f b S K T T Y K S b s 7 > = $ + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 1 2 , 2 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , 1 , , , 1 , , , , , , , , > , , > , > , , > > , > > > > > > , , > > > > > > > > : > : > : > > - > : : : : : - : : : - - - : : - - - : & : : & : & : & : & : & - & & & & & & & & & # & & & & = v.Z.Z.Z.Z.Z.Z.Z.Z.P # % % & # # # # # & # # # # % # # i v v v v v v v v v v v v k @ @ - + @ @ @ @ @ @ + @ @ + @ @ + @ @ + @ + + + + $ + % = < w n Y ..2.f.l.m.N.B.N.x.l.f.2...U b 9 : # @ + + O O O O O O O O O O O O O O o . O O X O O O O O X + $ * ; 6 e r b m M b b r e 7 3 * $ + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 , , 1 2 2 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , 1 , , , 1 , , , , , , , , , , , , > , > , > , > , > , > , : : > : > , : : : > > > : > : : > : : > : : : : : : : > - > : & - : - : & & & & : : & & & & & & - & - & & & & & & & & & & & & # } Z.Z.Z.Z.Z.Z.Z.Z.o.& & # & # & & & # # & & # % # # # l v v v v v v v v v v v v u # @ + o - @ @ @ @ @ @ @ o - + @ @ + @ + + + @ @ + @ + % % ; 9 b H ^ <.9.h.l.x.x.x.l.g.8.<.! S b 7 = % @ + X O + + O + O O O + O O O X X o o O O X O O X + + $ * ; : 6 9 w e e 7 6 : * $ $ + X . ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 1 2 : , & 1 : 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 1 , , , , 1 , , , , 1 , , , , , , , , > , , > , , , , > > > > , > > > > , > > > , : : > > > > > > : > : > : > : : : : : : : : - : - - - : : - : : : : : & & & : & : & : - & & - - & & - & & & & & & & % & j Z.Z.Z.Z.Z.Z.Z.Z.u.% & % % & # # & # # # # # % % # - v v v v v v v v v v v v v q - o + @ @ @ @ @ @ @ @ + + @ + @ @ + + @ + @ + @ + + % # % ; 1 r M Y .1.9.f.j.j.j.q.9.2...K M r < = # @ + + O O O O O X + O O O O O O O X X O O o O . . X X + $ $ $ ; ; ; = = * * * $ + + X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 L J J L J W W W W W W B Q L L L C 7 2 1 1 1 1 1 1 , 1 1 1 1 1 1 , , , C J F J J F F L F F J J F J , , , , , > , , , > 9 F F F F F F F F F C F F F 2 , : > > > : : F D F D D D F 7 : : : - - : : : Z F Z Z Z Z Z - & : & & : : : & : & - & & & - & & - & & & & & & & & & & # & Z.Z.Z.Z.Z.Z.Z.Z.u.# # & % # # & # & # & # & % # % u v v v v v v v v v v v v v ; @ @ o - @ @ @ @ @ + @ @ @ @ @ @ + @ @ + @ + + + + + + $ % = > 1 b A R ..<.2.9.9.9.2.<. .R A f 1 ; * % + O + + O + O O + O O O O O O O X o o O O O O X . . X . X + + + + $ $ $ $ * $ $ + + + X . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.m.C.C.Z.Z.Z.Z.Z.b.J 1 1 1 1 1 1 1 1 , , 1 , 1 1 I b.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.> , , , , > , > w &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F : , : > : > > 6.Z.Z.Z.Z.Z.Z.` : : : > : : : I Z.Z.Z.Z.Z.Z.u.& : & & : : & : & & & & & - & & & & & & & & & & & & & & % & & B.Z.Z.Z.Z.Z.Z.Z.B.# & & # % & # & # # % % # # # - c v v v v v v v v v v v v v + + - # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ + @ + + @ + @ % # ; < w b A K ^ ..;.>.;...^ Y A f e < = @ + + + + O + O + O O O O O + O O O . O O O . o . . . . . . + + + + + + $ + + + O . . + . . O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.N.V.Z.Z.Z.Z.Z.Z.Z.Z.I 1 1 1 1 1 1 1 1 1 1 1 , [ Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , > , , , , k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.F > : > > > : > D Z.Z.Z.Z.Z.Z.r.: > : : : : > 6.Z.Z.Z.Z.Z.Z.I : : - : : & - & : & : & : & - - & & & - & & & & & & & & & % & u.Z.Z.Z.Z.Z.Z.Z.Z.& % % # & # & # % & % # # # @ a v v v v v v v v v v v v v k - - O @ @ - o @ @ @ @ + @ @ + + @ @ + + @ + @ + @ + + @ + @ % # ; 5 w b B S Y Y Q R Y S M s w < * % @ @ O O O + O O O + X + O O O O O O O o . O X O O o o . o . . . . . . O O O . + O O O O + + + + + + + + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 , 1 , 1 1 1 H Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , , &.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.F > , : > : : > > v.Z.Z.Z.Z.Z.Z.7 : : : : : 7 Z.Z.Z.Z.Z.Z.v.: : & & : & : - - & & : - & & & & & - & & & & & & & & & & & & & B.Z.Z.Z.Z.Z.Z.Z.B.# & % & # # # % # # # # # % i v v v v v v v v v v v v v v 4 - O + @ @ @ @ @ @ @ @ @ @ @ + + @ + @ @ + @ + @ + @ + + @ + # % = - > 7 r f m B B M n b e 7 > = % @ + + + O O O + O O O X O O O O O O O O O o . o o . . . . X . . . . . . X . . X . O + O X $ $ $ $ $ $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.3.1 1 1 1 1 1 1 1 , , p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , > y Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.C.F > : , : , : > : | Z.Z.Z.Z.Z.Z.` : : : : : ` Z.Z.Z.Z.Z.Z.o.: & : : & : : & - & : & : & - & - - & & & & & & & & # & & & # & Z.Z.Z.Z.Z.Z.Z.Z.s.i i i p p p i p i p p a k v v v v v v v v v v v v v v v c $ + + - # @ @ + @ @ @ @ + @ @ @ @ @ @ @ + @ + @ + @ + + @ + @ + % # = = > < 7 e e e e e 7 , > ; # $ @ + + O + + O X X + O + O O O O O O O O O O o X O . . O . . . o X . . O + + $ $ % * * 3 * 3 * * $ $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.k.L L L L L L +.Z.Z.Z.Z.Z.Z.B.1 1 1 1 , 2 , 1 1 C Z.Z.Z.Z.Z.Z.Z.+.J J J J P F F J J F , , , > , , &.Z.Z.Z.Z.Z.Z.k.W F F F F F F F F F 2 > > > : > : : : 0 B.Z.Z.Z.Z.Z.r.: : : : : k.Z.Z.Z.Z.Z.Z.7 : - : - - - : & : & - - - & - - - & = & & : & & & & # - # - & V Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v v v a - + @ @ - @ @ @ + @ @ o + # # @ @ @ @ + @ + @ + + @ + + @ + + @ $ $ % & = * : : < < > : ; * # % $ $ + + + O O O + X X O O X O X O + X O O X O O O O O . . o . X O o X X X X X $ % & 3 5 9 9 9 e 7 5 ; = % $ X X ", +"2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 1 2 +.Z.Z.Z.Z.Z.Z.W 1 1 1 1 1 1 1 1 &.Z.Z.Z.Z.Z.Z.+., , , , , , 1 , , , , , , , , , , b.Z.Z.Z.Z.Z.B.9 > > , > > > > > > > > > > : > > > > : > 5.Z.Z.Z.Z.Z.Z.7 : : : d Z.Z.Z.Z.Z.Z.4.- : - - - - - & : & : & - & & & & & & & & & & - & & & & & - # 8 0.Z.Z.Z.Z.Z.Z.Z.Z.e.v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ + O - O @ @ @ + - + - # + + @ @ + + + @ + @ @ + @ @ + @ @ @ + $ $ $ % % % = & & * * * # % % $ + + + O + O + X O + + O O + X X O O X X O X O O O O . O . o o O o X + + $ * = 5 9 s b b b b b s 9 7 = * $ O X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 2 e Z.Z.Z.Z.Z.Z.+.1 1 1 , 1 1 1 , p.Z.Z.Z.Z.Z.Z.w , 1 , , 1 , , , , , , , , , , , d Z.Z.Z.Z.Z.Z.&.> > > , > > > > > > > > > > > > : > > > : N Z.Z.Z.Z.Z.Z.` > - : %.Z.Z.Z.Z.Z.Z.C = - - - - - - & : & : - & - - & & : & : & & & & & & = & - & q / B.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v v u # - - O + - + @ @ @ + @ @ @ @ + # @ @ @ @ @ + o + @ + @ $ @ # # % # # $ # % # # * $ % # % $ $ $ + + + + X + X + O O O O O + X X + O O O O O O X O o X X o . . X X o O X O + $ * = 7 r b C S T T T K A b s 7 : * + X X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 1 1 1 2 1 2 0.Z.Z.Z.Z.Z.p., 1 1 1 1 , , 1 Z.Z.Z.Z.Z.Z.0., 1 1 , , , , 1 , , , , , > , , , F Z.Z.Z.Z.Z.Z.F , > > > > , > > > > > > > : > > > - > > : : k.Z.Z.Z.Z.Z.u.- - - v.Z.Z.Z.Z.Z.k.- - - : - - - - : & : & - & & & & - & & & & & & & & & % & # 8 v t.Z.Z.Z.Z.Z.Z.Z.Z.Z.) v v v v v v v v v v v v v v v v v v v v v v v v v v l * @ + + - O + O - @ @ @ @ @ + # # + @ o @ @ + @ + @ @ + $ # # % = = = ; * = & & & # $ @ + $ + + + + X + O + + O O O + O + O o X o o O O O O X X O O O O . o . . O O X X + + * = 7 s C Y { { -.-.-.{ ! K C s 7 * % $ O ", +"2 2 2 2 9 2 2 2 2 2 2 1 2 2 1 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 2 1 1 2 1 2 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , > , +.Z.Z.Z.Z.Z.Z.9 , > , > > , > > > > : > > > > > : > : - > > W Z.Z.Z.Z.Z.Z.t > I Z.Z.Z.Z.Z.Z._ - : - - - - - - & : & : & & - - - 5 V V V V V V V V V V V V =.d.Z.Z.Z.Z.Z.Z.Z.Z.Z.d.v v v v v v v v v v v v v v v v v v v v v v v v v v c ; # # + - - @ + + - + + + + + + + + + # + # + @ + @ @ @ # # # ; - > , < , 5 > : = = # % $ @ + + + + O O + X O O + + + + O O O O o O o O O O X O O X O O O O X o o . O . o O O + $ * 7 s C T { >.2.2.8.8.2.>.{ Y M s 7 * $ + ", +"2 2 2 2 2 2 2 2 2 2 9 2 2 1 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 7 1 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 , 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , > , , , , +.Z.Z.Z.Z.Z.Z., > > , > > > > > > > > > > : > > > > : > > > : B.Z.Z.Z.Z.Z.} - 6.Z.Z.Z.Z.Z.B.7 - - : - - - - - : & : & & : - e 4.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v v v v v v v v v v v v v v v v v v v v v v v v v ; $ # % + + O O - O - + - + - o + - + + + @ + + + @ # @ $ # = = > 7 1 9 e e e w 7 < : = # % @ + + + + O + + + + O O O O O + O + + O O O O O + X O o X X . X o o o . . O o o o O O O $ * : e m K { 1.8.f.h.j.h.f.8.1.{ K m 9 ; $ + ", +"2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 2 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , 1 , , 1 , , , , , , , , , +.Z.Z.Z.Z.Z.Z., , > > , , > > > > > > > > > > > : - > > - - > %.Z.Z.Z.Z.Z.k.1 Z.Z.Z.Z.Z.Z.5.- : - - - - - - - & : & : : - j B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.c.v v v v v v v v v v v v v v v v v v v v v v v v v k * % % $ # - + + - O - O + # @ - + - o - + @ @ + # # + + - # = : , 7 t b n M A M M b r 7 5 = % $ @ + + + + X + O O + O + O O + O O O O O O O O O O o O O O . o . . . . o . . X X X + $ * 5 r C ! >.8.h.l.z.z.z.l.g.9.>.~ C r 5 * + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 2 1 1 1 1 L Z.Z.Z.Z.Z.Z.1 1 1 1 , 1 1 , Z.Z.Z.Z.Z.Z.+., , , , , , , , , , , , , , , , , +.Z.Z.Z.Z.Z.Z.F > > , > > > > > > > > > > > > > > > > > > > : t Z.Z.Z.Z.Z.Z.+.Z.Z.Z.Z.Z.Z.r : - : - - - - - - : & - & & e B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.' v v v v v v v v v v v v v v v v v v v v v v v k 8 $ % $ $ @ + @ @ + - + + + - @ + o o - + + + # + # + + + @ @ & ; 7 e b M H Y R R R K S M b w , = * $ + + + O + X O + + O O + O O + O O + O O O O O O . o o O o o . o o . o . . o O + + = 7 f K .2.f.l.m.M.V.M.m.l.q.2.{ K f 7 = $ ", +"2 e 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 W Z.Z.Z.Z.Z.Z.1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , 1 , , , , 1 , , , , , , , I Z.Z.Z.Z.Z.Z.%., > , > > > > > > > : > : > > > : > : : > > > : u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- : - - : - - - - - - = - - = u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.#.v v c a p p q t p i p p u i i i u u u p u 6 4 & # # # # # # # # @ O @ @ - + + + - - O + + + + + + # + + @ @ @ - ; < 0 n A Y ^ -.:.>.:...^ T C f e < = @ + + + + + O + X + O + O O + + X O O O O O O O O O O O O . . o . . . o o . . . . . O + $ ; 9 m T ;.7.h.z.N.C.Z.C.M.z.h.7...T m 9 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 +.Z.Z.Z.Z.Z.b.1 1 1 1 1 , 1 1 Z.Z.Z.Z.Z.Z.+.1 1 1 , , , , , , , , , , , , , , N Z.Z.Z.Z.Z.Z.B.w > , , , > > > > , : > > > > > > : , > : - > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z._ : - - & - - - - - - - - & - V Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.n.' v v c - & % & # & % # % % # % % # % % # # $ % @ % # # # # # @ # @ @ - - @ + O - O o + + @ + - - + # + # @ $ # # ; ; 0 f A Q ..<.2.7.9.9.2.<. .Q A f 1 : * % @ + + X + X + O + O O O O O X O O O + O O O O O O o . o . . o . . . . . o . O O % ; e m T -.8.h.z.N.Z.Z.C.N.x.h.8.:.T m 9 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 1 1 2 2 1 1 1 p.Z.Z.Z.Z.Z.p.1 1 , 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+., , 1 , 1 , , 1 , 1 , , , > , , > , B.Z.Z.Z.Z.Z.Z.k.I F D F F F F N > : > : > : > : , : : > > : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: - : : : : : : - - - - & - - 0.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.u.u.u.u.s.d.d.d.d.d.d.t.=.O.v v v v ; % # % # % % % % % & % % % % # & # # % @ % % # # # # @ # @ # @ @ O @ + - O - + @ - + + + + @ @ @ + @ $ # - ; 1 t B Y .1.9.w.j.j.j.f.9.1. .T M r < = % + + + + O + O + O O + + O + X + X X X O O O O O O O X . . . . . o . . . X o . . . O $ $ = 9 m T ;.7.h.l.M.C.C.C.M.x.h.7.;.K m 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 1 1 1 2 1 n Z.Z.Z.Z.Z.Z.&.1 1 1 1 1 1 , , Z.Z.Z.Z.Z.Z.+.1 , , , , , , , , , , , , , , , , , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.Z.v.W > > > > : , : : > : : > > : O.Z.Z.Z.Z.Z.Z.Z.Z.Z.O.- : - : & : & - - - - - - - 5 Z.Z.Z.Z.Z.Z.Z.Z.Z.4.= & & & ; c v v v v v v v v v v v v k - & & # & % & % % % % % % # % # # & % % % % @ # # # # @ # # @ - O - @ + - + + @ @ @ + + - + + + @ @ @ @ # - ; 1 n H ^ 1.9.j.l.x.x.x.l.j.9.,.^ S b 7 ; % $ + + O + + O O + + O O + X O o X X + O O O O O O X X . . . . . . o . O O O + $ = 7 b K .2.f.l.m.M.N.M.m.l.f.2. .K h 7 = $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 1 2 2 2 1 0.Z.Z.Z.Z.Z.Z.W 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , 1 1 1 , , 1 , , , , , , , , , > d Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.! ; > > : : : > , : : : : : d Z.Z.Z.Z.Z.Z.Z.Z.Z.d : - : : & : : & : : : - - - I Z.Z.Z.Z.Z.Z.Z.Z.B.< & & & & - v v v v v v v v v v v v v q % % % % & % % % % & % % % % # & # # # # # # # # # # # # @ # # + + - O @ @ - + @ @ @ + - O + + @ @ @ @ @ # - ; e m Y -.2.q.l.x.M.N.M.m.l.q.2...Y m w : % % + O + + X + O O + + O O O O O + o o X X O O O O . O . . o o . . o o . . o . . O + $ * 6 s S R >.8.h.l.z.x.z.l.g.8.>.! S r 5 * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.[ +.+.+.+.+.p.Z.Z.Z.Z.Z.Z.B.1 1 1 1 1 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , > , 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.t > > , > , : : > : , > : : 6.Z.Z.Z.Z.Z.Z.Z.6.: - : - : : : & : : & & - & & o.Z.Z.Z.Z.Z.Z.Z.Z.4.& & & & & 4 v v v v v v v v v v v v v ; % % & % & % % & % # % % % % % # # # # # & # # # # # # # # @ @ @ @ @ @ - @ + O @ @ @ @ @ + - + @ + + @ # # - < e B Q ;.7.h.x.N.C.Z.C.M.x.j.7.;.R M e < ; # + + + X + O + X O O + + O + O X O O + O O o O O . O . . o o . . . . . . . . . O X $ * ; e b Y { <.8.f.g.j.h.f.7.<.{ Y b w ; $ + . ", +"2 2 2 r 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.+., 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , , 1 , , , , , , , , , , 0 k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.0.> > , : : : : > : : : , : 4.Z.Z.Z.Z.Z.Z.Z.4.: - - : & - : : & - & : - - & 0.Z.Z.Z.Z.Z.Z.Z.Z.E & & & & & q v v v v v v v v v v v v v - # & % % % % % % % % % & % % % # & & # # # # # # # # # # @ # @ - @ @ @ O O @ - + + @ @ + + + + @ + @ @ # @ ; < r B Q >.9.j.x.N.C.Z.Z.N.x.j.9.>.Q B e < = + @ + O + O + O + O + O O O O O O O + O O O O O O . . o . . o . . . . O . . O X + $ = 7 s C U .>.2.7.9.7.2.>.{ Y M r 5 * $ O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 7 2 2 1 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.e 1 1 1 1 1 , 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , 1 1 , 1 , , , , , , , , , > , , , , w 6.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.C.B.> - : : , : , : > : : : 7 B.Z.Z.Z.Z.Z.Z.Z.B.7 : : - : : & & : : : & & : & p.Z.Z.Z.Z.Z.Z.Z.Z.D - & & & * i v v v v v v v v v v v v z # & % % % & % % % % % % # # % % # # # # # # # # # # # # # # # @ + @ - O + - @ @ - + + # - + - o + @ @ @ $ - ; ; t B R ;.9.h.x.N.C.Z.C.N.x.j.7.:.Y M e < * # # + + + O X + O + O O + O + O O O O O O O o O O . . . . . o . . . . o . o X X X $ % = 7 f C K ! .;.:.;.{ ! K C s 7 ; % + O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.B.V 1 1 1 1 1 , 1 1 1 1 Z.Z.Z.Z.Z.Z.+., 1 , , , , , 1 , , , , , > , , , > , > , , 0 F F F F F F W 5.Z.Z.Z.Z.Z.Z.Z.I : > > : > > : > > : > | Z.Z.Z.Z.Z.Z.Z.Z.Z.} : : = : : - - : : & : : & : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & # a v v v v v v v v v v v v z - # & # & # - # # # & # % % % % # % # # % % # # # # # # # # # # @ # # @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ + @ * & < 9 M U -.2.w.l.m.M.N.N.x.l.g.2...K M w : = $ + + + + + O O + O O + O X O O X X X O O O O X O o o o o o . o . . . . . o o . O + $ * 3 7 r b S K T R K K A b r 7 * ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.p.Z.Z.Z.Z.Z.Z.Z.Z.B.6.n 1 1 1 1 1 1 1 1 1 , 1 Z.Z.Z.Z.Z.Z.+.1 , , 1 1 , , , , , , , , , , , , , , , ; , , , > > > > > > , I Z.Z.Z.Z.Z.Z.+.> : > : > : > : : : : v.Z.Z.Z.Z.Z.Z.Z.Z.Z.v.: : : : & - - : & : & : - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & - & - & p v v v v v v v v v v v v z # # # & # & # # & # & # % % % % # % % % # # # # # @ # # @ % # # # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ # # > 2 b H ^ 1.9.j.l.x.x.x.l.h.9.,.^ S f 7 ; = + + + O O O + + X + X + O + O O + o + O O O O X O X X o o X o . . . o o o . . . X O + + $ % = 5 w r b m M m f r e 6 ; * ", +"2 2 2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 1 1 Z.Z.Z.Z.Z.Z.p.2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , Z.Z.Z.Z.Z.Z.+., 1 , 1 1 , , , , , , , , , , > , , > > ; , , , , > > , > > > > b.Z.Z.Z.Z.Z.0.> : > > : > : : > > I Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.I : : : & : - & : : & & = : u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & g v v v v v v v v v v v v g # - # & & # - - # # # & % % % % % % % # % # % # # % # # # % @ # @ @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ + @ @ # * ; 1 r B T ..1.9.q.h.j.j.q.9.1. .Y M r < = $ + + + O + + O O + O + O + O O O O X o O O O O O O O O O . o o . . . X . X . O O O X $ % * ; 7 7 7 9 9 8 5 ; * + + ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.+., , , , , , , 1 , , , 1 , , , , , > , , , > , > > , > , > > , > 5.Z.Z.Z.Z.Z.p.> > > : > : > > : : p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.- - : : = : : : & : - - & p.Z.Z.Z.Z.Z.Z.Z.Z.V & - & & - p v v v v v v v v v v v v p - # - # # & # # & & # # % % % % % # # % % % # # # # # $ # @ @ $ @ # # @ @ # @ @ @ @ @ + @ @ @ @ # + @ + @ % # = , w f A Q ..1.2.7.9.9.2.<. .Q A b 7 ; = # + + + + O + + + O + O O O O + + O O O O X O O X O O X X O . O . . . o . . . . . O O X $ + % % % = ; ; * * * $ % ", +"2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , 1 1 , 1 , , , , , , , , > , > , , > , > , , > , : > > +.Z.Z.Z.Z.Z.u.: > > > > : > : : d Z.Z.Z.Z.Z.Z.u.Z.Z.Z.Z.Z.Z.t - : : & : : & : & & - & u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p - # - - & # - # # & & # & % % % % % % # # # # % % @ # @ % @ % @ # @ @ # @ # @ @ @ @ @ @ @ @ @ + + + @ + + # % # - < w n A R ^ ..>.>.>...^ Y A f 9 < = # % + + + O + O + O + + O + + O O O + X o X O O O O O O X . . o o . . . . O . . . + + $ $ $ $ $ $ $ $ $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 7 1 1 1 2 2 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 1 Z.Z.Z.Z.Z.Z.+., 1 1 , , , , , , , , , , , , , , , , , , > , > > > > > > , > > +.Z.Z.Z.Z.Z.p.> > : : > > : > , %.Z.Z.Z.Z.Z.Z.j v.Z.Z.Z.Z.Z.4.- : & : : - - : - - - - u.Z.Z.Z.Z.Z.Z.Z.Z.Z & & - & & p v v v v v v v v v v v v p # # # # # & # % & # # # % % % % # # # % # % # % # # # % @ # @ # @ # # @ # @ @ @ @ @ @ @ @ + @ + @ @ + # @ # # % = - 1 e f B H Y Y Q Y Y S M y e 5 ; # % + + + O O + + O O X O O O O O + O O o + X X O O O O O X O O o . . o . o . o o X o X . . . O X X O + + + + O X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 , , 1 1 1 , Z.Z.Z.Z.Z.Z.+.1 , , , , , 1 , , , , , , , , , , , , , , > , > , , > > > , : , +.Z.Z.Z.Z.Z.u.: > > : > > > : 1 B.Z.Z.Z.Z.Z.b.: %.Z.Z.Z.Z.Z.B.7 : : : & - - - - : & : p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p # - & % - # % % # # & & % % % % % % % # # # # # # # @ % % @ @ $ @ @ @ @ @ @ @ @ @ # @ @ @ @ + @ # + # + @ + @ % # = ; < 0 t f m B B B m f r w < = % % % + + + + + O + + + + O X O O + O + O o o O + O O O O O O X o o . . o . . . o X X . . X X . . X . O . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Z.Z.Z.Z.Z.Z.&., 1 , 1 1 , , , , 1 , , , , , , , , > , , , > , > > , , > > , , u.Z.Z.Z.Z.Z.%.> : > > : : : : ` Z.Z.Z.Z.Z.Z.| : d Z.Z.Z.Z.Z.Z.} : & & : - - : & - - & u.Z.Z.Z.Z.Z.Z.Z.Z.F & & & & & p v v v v v v v v v v v v p # - # # - # & % # & # # % % % % % # # # % # % # $ # % @ @ % @ % @ @ + - @ @ @ @ @ @ @ + @ @ @ # + # + @ + @ + + # % & ; > 7 0 w e r e e 1 < - ; * % + + + + O + + + O + + O + + O + O O O O O O O O O O O X X O X o . . o . X O . . . O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 b.Z.Z.Z.Z.Z.k., 1 1 , , , , , , , , , , , > , , , , , : , , : , > , > > > > 0 Z.Z.Z.Z.Z.Z.| , > : : > : > : v.Z.Z.Z.Z.Z.Z.t : : k.Z.Z.Z.Z.Z.v.: : & : : & : : - : & p.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v i = % % & # % & # - - @ - + - + - % % % % # % # # % # # # # # # % @ @ # @ # @ @ @ @ @ @ + @ @ @ + # + @ @ + + @ @ @ # # # - - ; > , > < > - ; % # # @ + + + + + + + + + + $ + + X + O + O O X O O X O O O O O O O . X O O X X X X X O + + X X X X X . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.f.1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0.Z.Z.Z.Z.Z.Z.J , , , , 1 , , 1 , , , , , , , , , , , , , , , > , > , > > , X.Z.Z.Z.Z.Z.Z.h > > > > > > , D Z.Z.Z.Z.Z.Z.k.: : : } Z.Z.Z.Z.Z.Z.I : : & & : & & - & - u.Z.Z.Z.Z.Z.Z.Z.Z.V & & & & & p v v v v v v v v v v v v p % # & # # & # & + + - + - + - + % # % # # % # # # # # # # @ + # - # @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ + # @ + + @ @ @ # # # # # - ; & ; % * # $ @ $ + + $ + + + $ + $ % $ + @ $ + @ + + O X + O + X + O O O X X . O O O X X O X O + + + $ + + + O O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 [ Z.Z.Z.Z.Z.Z.k.e , 1 1 , , , , , , , , , , , , , , , , , , , , > , > > > m B.Z.Z.Z.Z.Z.v.> > > > > : : > r.Z.Z.Z.Z.Z.Z.X.: : : d Z.Z.Z.Z.Z.Z.u.& : : : : & : & - & p.Z.Z.Z.Z.Z.Z.Z.Z.k.u.u.u.u.u.s.d.d.d.d.d.d.d.d.d.d.d.d.s.u.$.% & & # & # - + + - + - + - % # # # % % # # # # # # # # % # + @ @ @ @ @ @ @ # @ @ @ + # + # # + @ + @ @ @ + + + + # # @ @ # # # @ $ # $ @ @ + + + + + # @ $ * # * = & * * @ @ + + + + O O O O O O O O O O O . . O O O O + + $ $ $ * $ * $ $ $ + + . X . X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 1 1 1 , 1 e B.Z.Z.Z.Z.Z.Z.B.p.p.p.p.p.p.i.i.i.i., , , , , : N i.i.i.i.i.u.p.u.p.p.p.Z.Z.Z.Z.Z.Z.Z.O.: > > : : > > t Z.Z.Z.Z.Z.Z.Z.7 : : : - k.Z.Z.Z.Z.Z.Z.e : & : & : : - : & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.& % # & # & + - - + - @ - + % % # % # # % # % # # # # @ @ @ @ @ @ @ # @ # @ @ @ + @ # + # + + # + @ + + + @ @ @ + @ @ @ @ @ @ @ @ + @ + + + + + + @ @ @ * = ; > : 5 : ; = & # # % + + + O O O O O O X O O o . O O O + + $ % * * * ; = = = * * $ $ + O X . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 1 Z.Z.Z.Z.Z.Z.p.1 2 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 +.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , , , F Z.C.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.M.1 : > > > > : > %.Z.Z.Z.Z.Z.Z.r.: : : : : ` Z.Z.Z.Z.Z.Z.4.- - : : & & - : & p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.u.% % - - - - - @ - + O $ - - % % # # & % # # # # # # @ # @ # @ @ - # @ @ @ @ @ @ @ @ @ @ + @ + @ + + @ + @ + + + @ + + @ @ + $ + + $ + + + + + + + # * ; > 5 7 e w e e 9 7 5 : * * + + + + X O O O O O O O O O O + + $ $ % = : 5 9 9 e 9 9 5 ; * * @ X X X ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 Z.Z.Z.Z.Z.Z.p.1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , , 1 e k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , , , > , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : : > > : > > 7 B.Z.Z.Z.Z.Z.Z.` : : : : : 7 Z.Z.Z.Z.Z.Z.B.7 - & : & : - & & u.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.% % + $ + O @ - + - - + - + # # # # # # # # # # # % # # # @ @ @ + @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ @ + @ + @ @ + + + + + + + + + + + + + + + @ # $ % = > 0 e f m M M C b f e 9 : & $ $ + + X O O O O O X X O O O + + $ = = 6 e r b b C b b f e 6 ; & $ $ X ", +"2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 Z.Z.Z.Z.Z.Z.p.1 2 1 1 1 1 1 1 2 1 1 1 , 1 , 2 1 1 1 , 1 1 1 , , C k.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z., , > , , , F Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.W : , : , : > : > ` Z.Z.Z.Z.Z.Z.B.7 : : : : : : r.Z.Z.Z.Z.Z.Z.} - & : : & - & - p.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.- ; - - ; - - - - @ ; - - $ % # # # # # # # % % # # @ # # # - + @ @ # # @ @ @ @ @ + @ @ @ @ @ @ @ + + @ @ @ + @ + + @ + @ + + + + + + + + + @ $ * = < e s B G U R R T K G M s 9 5 = $ $ + O X X O X O O O X O + + $ * > 9 s m S K T T T K G m r 7 ; * $ X X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 p.p.p.p.p.p.3.1 2 2 1 2 1 1 1 1 1 1 1 2 2 1 , 1 1 1 1 1 1 1 , 1 1 , [ 0.p.p.p.p.p.p.p.p.p.p.p.p.p., , , , , > N p.p.p.u.u.u.p.u.p.u.p.p.p.p.&.d , , : , : > > > : %.u.p.u.p.u.p.+.: : : : : : - I u.u.u.p.u.u.4.- : : & : - - & I B.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.t.; 4 3 ; 3 3 ; 4 8 ; 4 4 ; 4 , > 4 4 4 4 4 < 3 3 3 3 3 3 3 3 - + @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ @ + @ @ + + + # + # + + + + $ + + + + + + + @ # ; > 0 f A K ! { ;.>.:...! Y A f w : * $ + + + O O O O O O O O + $ * : 7 s M Y ! .;.:.-.{ R Y C s 7 = % $ X . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 2 1 , 2 , 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , 1 , , > , , , , , , , , , , , , > , > , > > > > > , > : , , : , > , : : > > : : : , : : : > : : : : : : : : : : : - : : - : : & : & : - - - - - & V D V V V V V V V N V V E ] ] ] ] ] ] ] ] ] ] ] ] ] ] ' v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; O - o O - O O + $ O + - + - O @ @ + @ + @ + @ + + + @ + + @ + + @ + + + + + % + = : 7 f S T ..<.2.8.9.7.2.<.{ R B y 7 : * + + O O O O O X O + + + # : 7 s A Y { >.2.8.8.8.2.>.{ T A s 5 = $ + + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 2 2 1 2 1 1 2 1 1 1 1 1 2 1 1 , 1 2 , , 1 1 , 2 , 1 , 1 , , , , 1 , 1 , , 1 , , , , , , , , , > , , > , , , > > , > , > > > > , : : > , : : , : > > : : > : : > : : : > : : : : : : : - - - : : & & : & : : & - - & - & - & - - & & - & - - & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - o - - + + - O - - $ O + - + + @ @ + @ + + @ @ + @ + + + + + + + + + + + + + * = 5 e M K .1.9.g.h.h.j.q.9.1.{ Y M e > & @ + + O O O O O O O + @ * : e b U { <.7.f.h.h.h.f.8.1.{ K b e ; % X X . . ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 , 1 , 1 , 1 1 1 1 1 , , , , , , , , , , , , , , , , , , > , > > , > , > , > > > > > , , , : : > > : > : > : > : : , : > : : : : : : > : : : : - : - : : : : : & : : - - - - - - - & - & & - - & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ - o - O O - + + - + + @ O + + @ + @ @ + @ + + @ + + @ + + + + + + + + + + % # : 7 b S ! <.9.h.l.x.m.x.l.g.9.>.~ A b 7 = % + + X O O O O O O + % = 5 s S ! >.8.h.l.z.m.z.l.h.8.>.R S s 5 * $ + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 2 1 2 1 1 1 1 1 1 2 2 1 1 1 , 1 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 1 1 , , , 1 , , , , , , > , , , , , , , > > , : , > , > > : , : : , : : , > > > : : > : : : : > : : : > : : : : : : : - : : & : & : & : & & - & - - & & & & & & - & & & & & ; i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 O o - O - + O - o o + @ @ @ + @ @ + + + @ + @ + + @ + + + # + + + + + + + + # * > e m Y ..2.g.l.m.M.V.M.m.l.w.2.-.U b 7 ; % $ + O O O O O O + $ $ : 7 b U { 2.f.l.m.M.N.M.m.l.f.2.{ K b 7 * $ + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 1 1 , 1 , , 1 , , , , , , , , , , , , , > , > , , > , , > > > > > , > , > , > : , , : > : > > > : > > : > : : : > > : : : : - : : : : & : : & : : & : : : - - - & - & - - : & & & - & & & & & p v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 $ O - o - O - @ @ @ @ @ - O + + @ @ @ @ + @ + # + + @ + + + + + @ + + + + # $ & 5 e M T :.8.h.x.M.C.C.C.N.x.h.8.:.T m w : * $ + + O O O O X + + $ : w b R -.8.h.z.N.C.Z.C.M.z.h.7...T b e ; * + . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , , 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , > , > , , , , , , > > > > : , , > : , : , > > : > : : > : > : : : : : : : : : : : : - : : : : : & - : & & - - - - & - - & & - & - & & & & & & i v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v ; - - O + o O - @ @ @ @ @ + @ @ @ + + @ + @ @ + @ + + # + + @ + + + + + + + @ % & > r M R >.9.h.x.V.C.Z.C.N.m.h.9.:.R M e > $ + + O O O O X O + + * 3 w M R ;.9.h.m.B.C.Z.C.N.z.j.8.:.R b e ; % + . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 1 1 2 , 1 1 1 , 1 1 , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , > > , , , , > > , > > , > > > , : : , : , : : : > : > > : : : : : : : : : : : : : - : : : : - : & : : : : : & & - - - - & & - & & & - & & & & - & u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 o - - - - O O + - @ @ O - + @ @ @ @ + + @ + @ + + + + + + + + + @ + + + $ + @ = 5 e M R :.8.h.x.N.C.Z.C.M.x.j.7.;.T C e > * + + O O O O O O + + % ; w b R -.8.h.z.M.C.C.C.M.x.h.7.-.T b e = $ + . . ", +"2 2 r 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , , > > , , > > , > > > , : , , : , : , : > : : , : : : , > > : > : : : : : : : : : - : - : & : & : & : & - - - & - - & & - - - & - & - & % - ; v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v 3 - o O O + + - + O @ @ + + @ @ + + @ @ @ + @ + + @ @ + @ + @ + + + + + + + + @ * : e b K ..2.w.l.m.M.V.N.m.l.q.2. .K m 9 : # $ O O O X O O X O $ $ ; 7 b Y { 2.f.l.m.M.B.M.m.l.f.2.{ K f 9 * $ + . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , , , , , 1 , > , , , , > , , , , > , > > , > > > > : , , > : > > : > > > : > > > : : > > : : : : : : : : : - : : & : : - : - : : & : - & : & : - & : & - & & & & - & & & & - u p g z l l l l l l l l g l l k g l k k k k k k k k k k l l k l k k k k k k k k k k k k ; @ # @ # @ @ @ - + + - O O + @ @ @ + + @ + + @ @ + + + + + + + + + + + + + + % % : 7 f S ~ <.9.h.l.z.m.z.l.g.8.>.! G f 7 = $ + O O O O X O X + + $ * 7 s S ! >.8.h.l.z.z.z.l.h.8.>.! A s 5 % $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , , > , > > > , > > > , > > , > : : , , : > > : > > : : : > : : : > : : > : : : : : : : : : : & - : : & : : & - - & : & & : & - & & - & - & & & & & & & & & & & - & & & % % & - # - - - - @ - - @ - @ - @ - # @ - + - # - @ + + - + - # + # @ @ # @ @ @ @ @ @ + + + O + - - + @ + @ @ + @ + @ + @ + @ @ @ + + + + + + + + + @ $ = 5 r M T ..1.9.q.h.h.h.f.9.1. .T m e 5 * @ + + O O O O X + O + $ & : e M Y { 1.8.f.h.h.h.f.8.1.{ U b 9 5 * $ ", +"r 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 2 1 1 2 2 1 1 1 1 1 , 1 1 1 1 , , 1 1 1 , 1 , , 1 , , 1 , , , , , , , , , , , , , , , > , > > , , , > , , > > > > > , > , : : , , : > : > > > > > > : : : : : : : : : : : : & : : : : : & : : & : : : & : - : & & & - & & & & - & & & - & & & & - # % & % % & & & # - @ - @ + + - @ @ - + - + - - @ - + - # + - - + - + + + - - + + - O @ # # @ @ @ - - o - @ @ O + @ @ + @ @ @ + + + @ + + + + + @ + + + @ + + + # $ * : 9 f A T ..<.2.8.8.8.2.>.{ T A s 7 = * $ + O O O O O O O O + $ $ = 7 r A Y { >.2.8.8.7.2.>.{ T C s 5 = $ + ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 2 1 1 1 1 1 , 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 , 1 1 , , 1 1 1 , , 1 , , , , , , , , , , , , , > > , > > , , > > , : , : , > > : > > > > : : : : : > > : : : : : > : : : - : : : : & : : & : - & & & : & & & & : & & - - & & & & & - # & - # & - # & & & & & # & & # - @ - - - + - - + - @ - + # + + - + # - @ + - @ + - - + + + - $ @ @ # @ @ @ @ + + + @ @ + @ @ + @ @ + @ + + @ + + @ + + @ + + @ + + + + + + + $ % = 5 e f A K ! ..;.>.;.{ { Y A f 9 5 = # + O O O O X O O X O O X $ & ; 7 s C U ! { ;.:.;. .! U C s 7 ; % $ X ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , > > , > , , > > > > > , : : , : , > > > : > > : : : : : : : : : > : : : : : : : & : : : : : & : & & : - - - : - & & - - & & - - & & & & - - & & & & - & # % & # & # & - @ - @ - @ - # @ - + - @ # # - # - + - + @ + - - + + @ - + + + @ # @ # @ @ @ @ @ @ @ + + @ @ @ @ + @ @ + @ + @ + @ + + @ + + + + + + + + + + + @ $ # = 5 9 s M S K T R T U S M f w 5 * @ + + + O O O X O O o O O + + % * : 7 s m A K T T T K A m s 7 ; $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , > > , , , > , , > > > > , > > : , , : > : : , > > : > > > > : : : : : : : : : - : : : : : : & : & : : : : : : - & - & & : - & & - & & & & & & - # - # # & & # & & & & & & & # @ - @ - @ - @ @ - + @ @ - # - + # # # # @ - # + @ + - + + + - - @ $ - @ @ @ @ @ @ @ @ @ @ @ @ + @ @ @ + @ + @ + @ + + @ + + + @ + @ + + + + + + + $ % % = 5 9 e b m M C C b f e 7 : = $ @ + O O O O O + O X O X X + + $ = ; 7 e s b b m m b r e 6 = * $ ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , 1 1 1 1 1 1 1 , 1 , , , , , 1 , , , , , , , , , , , > , , , , > > > > , , > > > , , , : > , , : : > > : > : : > > > : > > : > : : : : : : : : & : : & : - : & : & - & & - - & & - & - & - - & & & & & - & & & & & & & # & & # & % - @ - @ - + @ - # @ - @ - @ - # # # + # - # - + + - - @ - + + + - @ + + @ @ @ @ @ - @ @ + O @ + @ + @ + @ + + @ @ + @ + + @ + + + @ + + + + + + + + @ $ % = : 5 7 e e e e w 7 5 ; * # % + + + O O O O O O O O X X O O + $ $ * = 5 6 9 e w w 9 6 3 * * $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , , , 1 , , 1 , , , , 1 , , , , , , , , , > , > , , > > , > > , > > > , : : , : : , : : > : > > : : > : > : : : : : : : : : : : : : : : : : & & : & : & : - - & - - & - & & & & & & - & & - # & & & & # & & & & & % & @ - @ - # - - @ - - + - # # @ @ - # - # + # # # - + + + - + - + + # @ # # @ @ @ + O @ @ @ - + @ @ + @ @ + @ + @ + @ + + + + @ + + + + + + + + + + + + @ @ % * & : 3 : > : : * = & $ $ + + O + O O O X O O O O O . X O O X + + % & * = = = ; = = * $ . $ . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 1 1 , , 1 1 , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , : > > > > , , : : , : , : > > , : : > : > : : : : : : : : : : : : : : : : - : : - & : - : : & : & & : & & & : & - & & & - & - & & & & & & & & & & # & & & & # & # & # & & & # & # # & & @ # & @ # @ & @ @ & @ & @ @ @ @ @ @ @ & @ @ @ @ @ # @ @ @ @ @ @ @ X @ @ + @ @ @ + @ + + @ + @ + + + + @ + + + + + + + + + + @ + @ @ # % % & % & & # @ @ @ + + + X X + O O O O X O O O O O O O O + + $ $ $ * $ * $ + $ + O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 2 1 1 2 2 2 1 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , : , , , : , , : > > , : , > : , > , , : : : : : > > > > > > : > > : : > : : > : - : : - - : - & : : & & - - : & : : & & : & & - & & & & & & & & & & & & & & # & & & & # & & & & # # & # # # & # & # # # # & @ & # % # # % & @ # # @ & # @ # # @ @ @ @ @ # @ @ @ @ # X @ @ @ @ @ + @ + @ + + @ @ + + + @ + + + + + + + + + + + + + + + o @ @ @ @ # # # @ @ + @ + + + X o o o o O O O O O O X X O O X X O O + + + + + + + + + + O O . . ", +"2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 , , 1 1 , , 1 , , , , 1 , , , , , , , , , , , , , : , > , , , > > , : : , : , , : , : , , > > : : > : > : : : : : : : : : : : : : : : - : : : - : : & - & : & : : & : : & - & - & & & & & & & & & & & & # & & & & & & # & # & & & & & # # # & & # @ & @ & @ @ # @ % # @ @ @ @ # # # @ @ @ & # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ + + + @ + + + @ @ + @ + @ + + + + + + + + + o + + X + + + @ + + + @ + + + + + + X o O O o X X O O O O O O O O O O . X O O . O O + + . O + . O o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 , , 1 1 , 1 , , 1 , , , , , , , , , , , , : , , , > , , , > , , , , : , : : : , , : : > : > > : > : > : > : > : : : : : : : : : - : - - : : - : : : : & : & & : & : & & & - & & - & - & & & & & & & & # & # & # & # & & & # # & # & # & # & # & @ & # # & # & # # # # & # # @ & @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ + @ @ @ @ @ + @ + + @ + + + + + + @ + + + + + + + @ o @ + + X o o + + o + + X + X X + o + O + X X + X O O O O X O O X X O . o O O . . . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , , , 1 , , , , , , , , , , , , , , , , , , > , > , : : , , , : , , , : : , , : : > > : : > > > : > > : : : : : : : : : : : : : - : : - - - - & : & & & : & & & & : & & - & & & & & & & & & & & & & & & & & & & & # # # & & & # & # # # & # # & & @ & # # # % # # % @ # # # # @ @ & @ @ @ @ @ @ @ @ @ @ X @ @ # @ @ @ @ + @ @ + @ + @ + + @ + + + + + + + + + + + + + + + o + o + o + + o + X + + o O O O O O o o o O O O O O O O o o O O X O X o . . . . . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 2 2 2 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 , , 1 1 , 1 , 1 , , 1 1 , 1 , , , , , , , : , , : , , > , , > , , , : , , , : : , , : , : , , : , , : : : > : : > > : : : : : - : - : : : - - - : - : : : : & : : & : : & : & : & - & & - & & & & & & & & & & & & # & & # & & & & & # # & # & # & # & & @ # @ @ @ & % # % # # & # # # # @ @ # @ @ @ @ @ @ @ @ @ # # @ @ X # X @ + @ + + @ + @ @ + @ + + + @ + + @ + + + + o + X @ + + + + + + + o + + + o o X + + O + o + O X O X O O O O O X o o X O O O . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , , 1 , 1 1 , , 1 , , , , , , , , , , , , , , > , : , , : , : , : : > , : : , : : : , : : > : > : : > : : > : : : : : : : : - : : - - - - : & : & : & : & : & & & - & & : & - & & & & & & & & & & & # & # # & # & & # & # & # & # & # % # @ # # & % # % @ # % # # # # # # @ # # @ @ & @ @ @ # @ @ @ @ # @ # X @ @ + @ + @ @ + @ + + @ + + @ @ + + + + + + + + + + + o o @ + + + X + + o o X o + + O O O O o + + o O O O O O O O X O O O O o X o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 2 2 1 1 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 , 1 , 1 , 1 1 , , , 1 , , , , , , , , , , , , , , : , > , , > , , , , : > , > , , , : , : , , : : > > : > : > : : : > : : : : : : : - - : - - : - : - & : & : & : & : & & : & & - & & & & - & & & & & & & & # & & & & & & & # & # & & # & # # # & & # & @ & # % % % % # # # % @ # # # # # @ # @ @ @ @ @ @ @ @ @ @ # X # & X @ @ @ @ + @ @ + @ @ + @ + + + + + + @ + + + + + + + X @ o + X + X + o + + + X o + O + + O O X o o O O O O X O X o o O X . . . . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , , , , 1 , , , , , , , , , , , , , , , : , : , > > > > > > > > > , : , : : > : : > : > : : : > : : : : : : : - : - : : : : & : & : & : & : & - - & - & - & - - & & & & & & & & & & & & & # & & & # & & # & & # # # & # & @ & # # @ & # # % # @ # # # # # @ # # # @ @ # # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + @ @ @ + + + + + + + + + + + X + + + + + X + + X + + + + + X + O O O O O + + X X O O O O O O X O . o . . X O O O O . . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 1 2 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , 1 , , 1 1 , , , , , , , , , , , , : , , : , , , , , , , , , : > > > > : > : , : > > > > > > : : > : : : : : : : : : : : - : - & - - : & : : & & : : & & & - & - & & & & & & & & & & & # & & # & # & & & # & & & # # & & & & # & # & @ & & # # % % & # & # # % @ % # # @ @ # @ @ @ @ @ @ @ @ @ @ @ @ # X # # X + @ + + + @ + @ + + + + + @ + @ + + + + + + + + + + + + + + X + + X o O O + X o + O O O O O + o O O O O O O X X . o o . o . o . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 1 1 2 1 2 1 2 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , > , , , , , > > : > > : , > > > > : , : : > > : : > : : : : : : > : : : : : : : - - : - : : : : & : : & : & : & : & : & : & & - & & & & & & & & & & & & & % & & & & & # & # & & # # # # & # # # & @ & & @ & # @ # # # % % @ & & X @ @ @ @ @ @ @ # @ # @ @ @ @ @ X @ @ @ @ + @ @ @ @ @ + + + @ + @ @ + + + @ + + + + + + + o + X + X + o + o X + + + O + o O O + + o + o O O O X + X O O o O O o o . . . O O . . o o O . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 1 2 1 2 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 , 1 1 , , 1 , 1 , 1 , 1 , 1 , , , , , 1 , , 1 , , , , , , : , , , : , : , , : , > , > , > > > > : : , : > : > > > : > > > : : : : : : : : - : : : : - : & : : : : & : & : & : & & : & & : - & & - & - & & & & & & & & & & & # & # & # & & & # & & & & # # & & @ & @ @ & # @ & # # % @ @ @ @ @ & & @ @ @ # # @ # @ @ @ @ @ @ @ @ X @ @ @ @ @ + + @ + + @ @ + + @ + + + @ + + + + + + + + + + + + + + + + + + o + o + + + O + O O X O X O O O X O X X O O . O . o o . . . O . . o o ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 1 1 1 1 1 , 1 1 1 , 1 1 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , , , : , > , > > , : , , > > > > > > > > > > : : > > > : : > : : : : : : : : : : : - : : - : & : & - - : & & : : & : & & & & & & & : & & & & & & & & & & & & & & # & & & # & & # & & # & & # # & # & @ # # # # # # # # # # @ & & @ @ @ @ & @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + + @ + + + + @ + + @ + + + + + + + + + + + + + + o + + o + + o O O + O X O O O O + O O O O O O O O O O O O O X X . . O o . o . o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 2 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 , , 1 , , , , , , , , , , , , , > > , , > , > , > , , , : , : > > > > : > > : > > > : : : : > : : > : > : : : : : : : : - - : : & : : - - - - : & & : & : : & : & & & & & & - & & & & & & # & & & & & & # # & # & & # # & # # & # & # @ & & @ @ & & # & # % # @ @ @ @ @ @ @ @ # @ # # @ @ @ @ X @ @ @ @ @ @ @ + @ + @ @ + @ @ + @ @ + + + + + + + @ + + + + + + + + + + + + + O + + O + O + X + + O O o O O + O O O O O O O O O O O O O X o O o . . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 1 2 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , 1 1 1 , 1 , 1 , , 1 , 1 , , , , , , , , , : , , , , , , > , > , > : , : , > > > > > > > > > > > > > : > > : > : : > : : : : : : : - : - : - - : - - - - & - & : & & & : & & & : & - & - & & & & & & & & & # # & # & & # & & # & # & & # & # # & # & # @ & # # # # # @ # % # @ @ @ @ & @ & @ @ @ # @ @ @ @ @ # @ @ @ @ @ X @ @ + @ + @ + @ + @ + + + @ + + + @ + + + + + + + + + o + + o + o + + O + O + O + O O O + O O O O O O O O O O O X o O O . O . X O o o o o . ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 1 , 1 , , , , , , , , , , , , , , , > , , > , , > , > , > , , , : > > > > > > > > : : : > > : > : : : > : : : : : : : : : - : - : : - - : - - : - : & : & : & & : & & & & & & & & & & & & & & & & & & & & & & & # & # & & # & # & # # & # & # @ # & @ & @ # # # # & @ & @ @ @ @ @ # @ # @ # @ @ @ @ @ @ # X @ @ @ @ @ + @ + @ + @ + + + @ + @ + + + + + + + + + + + + + + X + + + O O + O + O + O O + O + O + O O O O O X O X O O O . . O o O o . . . . . ", +"2 2 2 2 2 2 2 2 y 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 , 2 1 1 , , 1 , 1 , 1 1 , 1 1 , 1 , , , , , , , , , , , , , , : , , : , , : , , : , , , > , > > > : , : > > > : > : > : : > : : : > : : : : : > : : : : : - - - : : - - : - - - & : & & & : : - & - - & - & & & & & & & & & # & & & & # & # & # & & # & # & # & # # & # & # & & & # # & # # # # # # # # # # @ # # @ @ @ @ @ # @ @ @ @ X @ @ @ @ @ @ @ @ X @ X @ + @ + @ + + @ + + + @ + + + + + + O + + + + + + + + X O + O O O + O + O O o X O O O O O O O o o o X X o O X . O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 1 , 2 1 1 1 , 1 , 1 1 , , 1 , 1 , 1 1 , , 1 , , , , , , , , , , , , , , , , , > , : , : > , : , > , > > > > > > : > > : > : > : : > : : : : : : : : : : - - - - - - & : : & : & : : & & & & & & & - & & & & & & & & & & & & & # & & & & & & # & & # & # & # & # & # # # @ # # # # # # & # # # # # # # # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ @ @ X @ @ X @ @ X @ + @ + + + @ + + @ + + + X + + + + + + + + + X o + O + + O + + O + O O O X + O o O O O O O O o O O O O o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 1 1 1 1 1 1 , 2 1 1 1 , , 1 1 1 1 , 1 , , 1 , 1 , , 1 , 1 , , , , , , , , : , , , , , : > , : , , : , : : , > > > : > > > : > : > : > : : > : > > : : : : : : : - - : : : - - : & : - - & : - & : & : & - & & & & & & & & & & & & & & & & & # # & & # & & # # & # & # & & # # & & # # & # # # # # # # # # # # @ @ # # # # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ X @ X @ @ @ + + + + + + + + + + + + + + + + + + + O o + + + + O + O O O O o O O O + + O O O O O O O O X O O X O o o O . O O O O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 , 1 , 1 1 1 , 1 , , 1 , 1 , , , , 1 , , , , , , , , , , , , , , , , : , , , , , , : , > , , : , : > > > : : > > > : > : > : : : : : : : : : : : : : : : - - - - : - - - - : & : & & : & & & - - & & - & & & & & & & & & # & & & & & # & & & # & # & # & # # # & @ # & # # & # # # & # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ @ @ @ @ X @ + @ @ + @ + @ + + + + + + + + O + + + O + + X + o + + o + + + O + O O o O + O O X O O O O O X O O X O O O O O O . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 1 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , > , , > , , > : , : , > : , , : , : > > > : : > : > > : : > : : : : : : : - : : : - : - : - : - - - - - & : & & - & : : & - & & & & & & & & & & # & & & & & & & # # & & & # & & # & # & & # # & # # # # # & # # # & # # # # # & # # @ @ @ @ # @ # @ @ # @ @ @ X @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ + + @ @ + + + + + + + + + + + + X + + O + O + o + + X + O O O O O O O O + X O O O O O O O . . o . O O O O o O O o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 , 1 1 1 1 1 , 1 1 , 1 1 , 1 , 1 , 1 , 1 1 , 1 , , , , , , , , , , , > , , > , , : , > , , , : , : , : > > > > > > > > > > : > : > : : : : : : : : : : - : : - - - : - - - - - - : & & : & : & & - & & & - & - & & & & & & & & & & & # & & & & # # & # & & # & # & # & # # & # # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ @ @ @ @ X @ @ @ X + X @ @ X @ + + + + + + + + + + + + + + + + + + + + o + o + X + O + o O + X X + + O O O O O O X X O O O . X O . o . o o O O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 1 1 1 1 , 1 , 1 , 1 , , , , 1 , , , , , , , , , , , , , > , > > > , , : , : , , : > , > > > > > > : > > : : > : > : : : > : > : : : : : : - : : - - : - - - - - - : & : & & & : & & & & & - & & - & & & & & & & & & & & # & & # & # & & # & # # & & & # # # # # & # % & # # # # # # # # # # @ # # @ # # @ @ @ @ @ @ @ @ X @ @ @ @ @ X + @ X @ @ X @ + + @ + @ + + + + + + + + X + + + + O + + + + + + O + + O + X O O O O O + + O O O O O O O O . . o . o o . O o O o O O o ", +"2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 2 2 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 1 , 1 , 1 1 , , , , , , , , , , , , , , > > , , , > , : , , , : , : , , : > > > > > : > > : > > : : : : > : > : : : : : : : : - : : - : - - : - - - - & : & : : & & & : - & - & & & & & & & & & & # & & # & & # & # & & & # & # & & # # # # & & # & # % % # # # # # # # # # # # # @ @ # # @ @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + @ + + + + + @ + + + + + + + + + + + + + X + o + X + O o O + o + O + O O O O O O O O O O O . . O X . . . . o o o O O o O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 1 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 1 , 1 , 1 , 1 1 , 1 1 , , , , , , , , , , , , , : , , , , > , , > , , , : > , : : , : > > , > > : > > > > : : > : > : > : : : : : : : : : : : - : : : & : : & : : & : & : & : : & & & & - & - & & & & & & & & & & & & & & # & & & # & & # & & @ & # & # # # # & # & % # # % # # # & # # # # # # # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ X @ @ @ @ + @ + @ X + @ + + + @ + + @ + + + + + + O @ O + O + + + O + + X + O O + O O O O O X + X O O O O O X X o O O . . o . . . O o . . o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 1 , , 1 , 1 , 1 , , 1 , 1 , , , , , , , > , , > , > , > : , , , , , , : , > > > > > > > : : > > > > : : : : > : : : > : : : : : : : - : : : & : : : & : & : & : & & : & : & & & & & & & & & & & & & & # # & & & & # & & # & & # # & # & & # & & & & # # & # % # # # # @ # # # # @ # @ # # @ # @ @ @ @ @ @ @ @ @ @ @ @ @ @ X X @ @ @ @ + @ + @ + + + + + + + + @ + + + + + + + + O + o + + + O + X + O O O + O X + X O X O O O O O O O o . . . o . . . . o o o . . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 1 1 2 1 2 2 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , , 1 , 1 , , , , , , , , , , , > , , , , > : , : , > : , , > > , : > > > > > : > : > : : > > : : > : : : : : : - : - - : - : : : & : & & : : & : : & : & & - & - & & & & & & & & & & # & & & # & & & & # & & # & # & # & # # # # # # # # # # % # # # % # # # # # # # @ # @ # @ @ @ # @ @ @ # # @ @ @ @ @ @ @ @ @ @ @ + + @ + @ + + + @ + + + + + + + + + X + + + + + O + + O + O O + X O + + O + X o + + o O O O X O X X o . O o . o o o o . O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 1 1 1 1 2 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 1 1 , 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , , , , : , , > , , , , > , > > , : : > > > > > > > > : > : > > : > : : > : : : : - : : : : - - : & & - : : - : & : & & & & & : & & - & & : & & & & & & & & & & & & & # & # & & & # & & # & # & & # & # # & & # # # # & & # # # # # # # # # # @ @ @ # @ @ @ @ @ @ X @ @ @ @ X @ @ X @ @ @ X @ + @ + + @ + + @ + + + + + + + + + + + O + + + + O O + + X + O + O O O + X O O O O O O O X O O X o o . . . . o . o . o . o . O O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 1 1 , 1 , 1 , , , 1 , , , , 1 , , , , , , , , , , , , , : , , : : , > , > , : , : > : > > : : > > > : > : : > : : : : : : : : : - : : : : : : : : : & : & : : & : : & : & & & & & & - & & & & & & & & & & & & & & # # & & # & & # & # & # & & # & & # # # # # # % # % # # # # # # @ # # # # @ @ @ # @ @ # @ @ @ @ @ X X @ + @ + @ @ + + @ + + + + + @ + + + + + + + + + + + X + + + + + X + + X O O + O O O O O O O + o O O O + O O . . O . o o . . . . . . . o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 1 , , 1 , 1 , 1 , 1 1 , , , , 1 , , , , , , , , , , , , , , , , , : , , : , : > : , : , > > > : > > : : > : > : : : > : : : : : : : : : : : - : : & : & : & & : & & : & : & & & & - : & & & & & & & & & & & # & & & # # & & & # & # # & & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ # @ # # @ @ @ @ @ @ @ @ # @ @ + @ @ @ + @ @ + + @ @ + + + @ + + + + + + + + + + + + O + X + + + X O + + O + X + + O + O O + X O O O O O . O . O . . o o . . . o o . . . O O ", +"2 2 2 2 2 2 2 2 1 2 2 2 2 , 2 2 1 2 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 , 1 , , 1 1 , , , , , , 1 , , , , , , , : , : , : , , , : , > > > : > , : > > > > > > > : : : > : > : : > : : : : : : : : & : : & : & : - : & : & & : : & : & : & - & & - - & & & & & & & & & & & & # & & & & & # & & & & # & & # & # & # & # # & & # % # # # % % # # # # # @ @ @ # # @ @ @ @ @ @ @ X # @ @ @ X @ @ @ @ + @ + @ @ @ @ + + + + @ + @ + + + + + + + + + + + + O + + O + + O O + + O O O + O O O o O O O O O O O . . o o . . . . . o o o . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 2 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 , 1 1 , 1 1 , 1 , , 1 , 1 , , , 1 , , , , , , , , , , : , , , , , , > > , , > , , > , , : , > > > : > : > > > > : : > : > : : > : : : : : : : : : : : : - - : & : - : & & : & : & & - & & & - & & & & & & & # & & & & & & & # # & & # & # # & # # # & # & # # # & # # # # % % % % @ # # # # # # # # @ # @ # @ @ @ @ @ @ @ # @ @ # @ @ + + @ + @ + + + + @ + @ + + + + + + + + + + + + + + X + + O + + + O + + O O + O + O O O O O o O O O O O O . o . O . O o . . . o . o o O O ", +"2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 1 1 2 1 2 , 1 1 1 1 1 , 2 2 , 1 1 1 , 1 1 , , 1 1 , , 1 1 , , , , , 1 , , , , , , , , > , , > , > , > , : > , : , > : : , : > > > > > > : > > : : > : : : > : : : > : : : : : : - : - : - : & & : - & : : : & : & & : : & & & & & & : & & & & & & & & # & & & # & # & & & & # & # & # # & # # # & # & # # & # # # # # # # # # # # # @ @ - @ @ @ @ o - + o - @ @ @ @ @ @ @ + @ + + @ @ + @ + @ + @ + @ + + + + + + + + + + + + + + + + o + + X X + O + + X + + O O o O O O O O X X O X O X O o o O o O X X O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 1 2 1 1 2 1 2 1 1 2 , , 1 1 1 , 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , 1 , , 1 , , , , , , , , , , > , > , , , , , , : , , , > , > , : , > : > > : > > : > : : > : > : : : : : : : : : - : - - : : : : - : : & & & : : : & & : & : & & & & & & & & & & & & & & & & & & & & # # & & # & # & # # & & # # # & # # # # # & # # # # # # # # @ @ # + # @ o @ - o @ @ + @ @ @ + @ + @ @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + + + X + + + o + o + + O + O O X X O O O + O O O O O + O O o X O O O O X O O X O o o O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 2 1 1 1 2 , 2 1 2 1 1 1 2 , 1 , , 1 1 1 1 1 , 1 , 1 1 , 1 , 1 , , , , , , , , 1 , , , , > , , , > , > > , : , : : , , : > : , : : > > > > : > : > > : : : > : : : : : : : : : : : - : - : - : : & & : & & : & : & & & & & & : & & & & & & & & & & & & & & & # & & # # & & & # & # & # & & & # & & # # # # & # & # # # & # # # # # # # # + @ @ - @ - o @ @ @ @ @ @ @ + @ + @ @ + @ @ + + @ + @ + + + + + @ + + + + + + + + X X + + + + + + o o + O O O o + o X O O O + O O O O O O O X X o o O X o O X o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 2 1 1 1 1 2 1 1 1 1 1 , 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 1 , 1 , , 1 , , 1 , 1 , , , , , , , , , , , > , , , > , , , > , , > > , > > : , > > > > > > : > : : > > : : > : : > : : : : : - : : - : : : & : : - : & : & : & : & : : & & & & & & & & & & & & & & # & # & & & # & & & # & # & & # & # # # # # # # & # # # # # # # # # # # # # # # # @ + - @ @ @ o - + @ @ @ @ @ + o - + @ + @ @ + @ + + @ + + + @ @ + + + + + + + + + + + + + X + o + o + + O + + O + X + + o O O O O O O O O O O X X . . . . o O o O X . O O ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 2 2 1 1 2 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , 1 1 , 1 , 1 , 1 , , , , , , , , , , , , , > , , , , , > > , , : , , , : > > , > , : > > : > > : > > : > > : > : : : : : : > : : - : : : - : & : : & : & : & : & : & & : & & & & & & : & & & & & & & & & # & & & & & & # # & & & # & # & # & # & # # # # # & & # # # & # # # # # # # # # # @ + + - o + + @ o + @ @ + @ @ + + @ @ + @ @ + + @ @ @ + + + @ + + + + + + + + + + + X + + + + + X + X + O + O o O X + O O O O O O O O O O X O o . o O . . o o o . o . X O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 1 2 2 2 1 1 1 1 2 1 1 1 1 1 1 1 , 1 , , 1 1 1 1 1 , , 1 , 1 , , , , 1 1 , 1 1 1 , , , , , , , , , , : , , , > , , : , > , > , : : , : > > : > > > > : > > : : > : > > > : : : & : : : - : - - : - & : - - - : : & & : : & : & & : & & & & & & & & & # & & & & & & # & & & & & & # & & & # & # # # & & # & # # # # # # # # # # # # # # # # @ # - + o - - @ @ - - o @ @ @ + @ @ @ + + @ @ + @ + + + + @ + + + + + + + + + + + + + + + + X + X + X + O + O + + o O O + + + O + O O O O O o X O . X o o O o O X O o . . O . O ", +"y 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 1 2 1 1 1 1 1 2 1 2 , 1 1 1 2 2 1 1 1 1 1 1 1 1 1 , 1 1 1 1 , , 1 1 , 1 , , , , , , , , , , , , , , , : , > , , > > > > , > , > : , : : , : , , : : > > : : : : > : > : : : : : : : : : : : - : : - : : & : & : & & & : & & : & & : & & : & : & & & & & & & & & & # & # & # & # # # # & # # & & & & # # # & # & # & # & # # # # # # # # # # @ # # @ + @ @ @ @ @ @ o - @ @ @ @ + @ + @ @ + @ + @ + @ + @ + + @ + + + @ + + + + + + + X + + + + + X + O + O + o + + + X O O O + O O O O O O X O X . . . . o X O X . o . . O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 1 1 2 2 1 2 1 2 1 2 1 1 1 1 1 2 , 1 1 1 1 1 1 1 1 1 , 1 , , 1 , 1 1 , , 1 , , , 1 , , , , , , > , , , , > , , , , , , , , , : , : > , > , , : , > : > > > : > > > > : : : : : : : > : : : : : : : : - : : - : - : - - & : : & & & : & : & & & & & & & & & & & & & & & & & & & & & & & & & # & & # # # # & & # # & # # # # # # # # # & # # # # # # @ # @ - @ @ @ @ @ @ @ @ + @ @ @ @ @ # + @ @ @ + + @ + @ + + + + @ + + + + + + + + + + + + + o + + + X + O + O + o X O O + O O O O O O O O O O O O o . o . O o X . . . . O O . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 1 2 2 1 2 1 1 1 1 2 1 2 , 1 2 1 2 , 1 1 2 , 1 1 1 1 1 , 1 1 1 , 1 , 1 1 , 1 1 , , , , , , , , , , > , > , , , > > > , : , , , > , > : , , : > : , > > : > : > > > : : : : > > : : : : : : : : & : & : : & : - - - - & : & : & : - & & & : & & & & & & & & & & & # & & # & & & # & # # & & # # & # & & # # & # # # # # # # # # # # # # # # # # # # # - o # @ @ @ @ @ + @ @ @ @ + @ + + @ @ @ + + + + @ + + + + + @ + + @ + + + + + + + + o + o + + + O + X + O O + + O + O + O + O O O O O O O O O O X . . . . o o . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 1 1 1 1 1 2 1 1 1 1 , 2 , 1 , , 1 1 , 1 1 , 1 , , 1 , , , , , , , 1 , 1 , , , , , , , , , > , , , > , , , : > , : > , : : , > > : > > : > : : : : > > > : : : : : : : : : : : : : : : : - : - - - - - & : & & & - - : & & & & & & & & & & & & & & & & & & # & & & & & # & & & # & # & # & # # & & # & # & # # # # # # # # # # @ # # - @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ @ + @ @ @ @ @ @ + + @ + @ + + + + + + + + + + + + + + + + + o + X + + + + O O + O O O O O O O O O O X O O O X O X . . . . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 1 2 1 1 1 2 1 1 1 1 2 2 , 1 1 1 1 2 1 1 1 1 1 1 , 1 1 1 , , 1 1 , 1 , , 1 1 , 1 , , , , , , , , > , , , > > > > > : , : , > , , > , > > : : , > > > > : > > > : : : : > : : : : : : : : : : : & : : & - : & : - - - : : & - & & - & & & & - & & - & & & & & # & & & & & & # & # & & # & # # & # & # & # # & # # # # # & # & # # # # # # # # @ # @ o @ @ # # @ @ @ @ @ @ @ @ + @ @ + @ @ + @ + + + + + + + + + + + + + + + + + + o + + + o o + o + + O + O + O O O X + X + + O O + O O X O O O X O O X o o o o . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 2 1 1 2 1 2 1 2 1 2 1 1 1 1 2 , 1 , 1 1 1 1 , 1 1 , 1 , 1 , , 1 , , , , , , , , , , , , , , , > , , , > , , : , , > , : : , : , : , > : , : > : > : > : : > : > : > : : : : : : : : : : : : : : : & : : & - : & & : & : & - & : & : & & & & & & & & & & & & # & & # & & & & & & & # & # # & & # # & # # & # & # # # # # # # # # # # # @ # @ @ @ # @ @ @ @ @ @ @ @ @ @ @ @ + @ + + @ @ @ + @ @ + @ @ @ + @ + + + + + + + + + + + + + + + + + X + O + O + + + O O O O O O O X O O O O O O O X X O . . . . . o . o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 , , 1 , 1 , 1 , , 1 , 1 , 1 , , , , 1 , , , , , , , , > , > > > , , , : , , : , > : , > , : > > > : > : > > : > : : > : > : : > : : : : : : : & : & & : : & : & & - & : & : - & - & - & - & & - & & & & & & & & # & & & & # & & # & # & & # & # & # # & & # # # # & # # & # # # & # # # # # # # # # # @ # @ # @ @ @ @ @ @ + @ @ @ @ @ # @ + + + @ + + + + + + + + @ + @ @ + + + + + + + + o + + + X + + O + + O + O + O + O O X O X O O O X o o O O o O O X o . o . o . . . . ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 , 1 , 1 , 1 1 1 1 1 1 , , 1 1 , 1 , , 1 1 , , 1 , , , , , , , , , , , , , > , > , , : , , , > , : , : , > > : , > : : > : : > > : : : : : : : : : : : : : : : : : : : : - : : : : & : & - & & - & - & & & & & & & & & & & & & & & & & & & # & # & # # & # & # & & & # # & # # # # & # # & # # # # # # # # # @ @ @ # @ @ @ @ @ @ @ + @ @ @ @ + + @ + @ @ + @ + @ @ @ @ + + @ + + + + + + + + + + + o + + + o + + X O + O O + O O O O O O O + O O O O O O O o O O O o o o . o . . . . . ", +"2 2 y 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 2 1 2 2 2 1 1 1 2 , 2 1 1 1 1 1 1 2 , 1 1 , 1 1 1 1 1 1 , 1 1 , , , , , 1 , , , , , , , , , , , , , , , , > , , : , > , : : , , : , : : , , : : > > > > : > : : > : > > : : : : : : : : : & & : : & & : - - & : & & & - - & - & - & & & - & & & & & & & & & & # & & # & & & # # & & # & # & # # # & # # # & # # # # # # # # # # # # # # # # # # @ # @ @ @ @ @ @ @ + @ @ @ @ @ @ @ + @ @ + @ + + + @ + @ + + + + + + + + + + + + + + + + + + + X + + + X O O + + O X O O O + X O X O O O O O O O O O O . . o o . . o o ", +"2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 2 , 2 1 1 1 1 , 1 , , , 1 , , , 1 , 1 , , , , , , , , , , > , , > , > > , , > , , > , > > , , : , : > > : , : > > : : > > : > : : : : : : : : : : : - : : : : & : : : & : - - : : & : & - - - & & - - & & & & & & & & & & & & & & & & & # & # & # & & # & # & # # & # # # & # # # & # # # # # # # # # # # # # # @ @ # @ @ @ @ @ @ @ @ @ + @ + @ + @ + @ @ + @ @ + + @ + + + + + + + + + + + + + + o + + o + o + + X X + O + O + O + O + O X O O O O O O O O O O O . o . . . . . o o " +}; diff --git a/pcsx2/Linux/Config.c b/pcsx2/Linux/Config.c new file mode 100644 index 0000000..8116ef7 --- /dev/null +++ b/pcsx2/Linux/Config.c @@ -0,0 +1,146 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "Linux.h" + +#define GetValue(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%s", var); \ + } + +#define GetValuel(name, var) \ + tmp = strstr(data, name); \ + if (tmp != NULL) { \ + tmp+=strlen(name); \ + while ((*tmp == ' ') || (*tmp == '=')) tmp++; \ + if (*tmp != '\n') sscanf(tmp, "%x", &var); \ + } + +#define SetValue(name, var) \ + fprintf (f,"%s = %s\n", name, var); + +#define SetValuel(name, var) \ + fprintf (f,"%s = %x\n", name, var); + +int LoadConfig() { + struct stat buf; + FILE *f; + int size; + char *data,*tmp; + char strtemp[255]; + + if (stat(cfgfile, &buf) == -1) return -1; + size = buf.st_size; + + f = fopen(cfgfile,"r"); + if (f == NULL) return -1; + + data = (char*)malloc(size); + if (data == NULL) return -1; + + fread(data, 1, size, f); + fclose(f); + + GetValue("Bios", Config.Bios); + Config.Lang[0] = 0; + GetValue("Lang", Config.Lang); + GetValuel("Ps2Out", Config.PsxOut); + GetValuel("ThPriority", Config.ThPriority); + GetValue("PluginsDir", Config.PluginsDir); + GetValue("BiosDir", Config.BiosDir); + GetValue("Mcd1", Config.Mcd1); + GetValue("Mcd2", Config.Mcd2); + + // plugins + GetValue("GS", Config.GS); + GetValue("SPU2", Config.SPU2); + GetValue("CDVD", Config.CDVD); + GetValue("PAD1", Config.PAD1); + GetValue("PAD2", Config.PAD2); + GetValue("DEV9", Config.DEV9); + GetValue("USB", Config.USB); + GetValue("FW", Config.FW); + + + // cpu + GetValuel("Options", Config.Options); + GetValuel("SafeCnts", Config.SafeCnts); + + GetValuel("Patch", Config.Patch); + GetValuel("varLog", varLog); + + free(data); + +#ifdef ENABLE_NLS + if (Config.Lang[0]) { + extern int _nl_msg_cat_cntr; + + setenv("LANGUAGE", Config.Lang, 1); + ++_nl_msg_cat_cntr; + } +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + FILE *f; + + f = fopen(cfgfile,"w"); + if (f == NULL) return; + + // interface + SetValue("Bios", Config.Bios); + SetValue("Lang", Config.Lang); + SetValue("PluginsDir", Config.PluginsDir); + SetValue("BiosDir", Config.BiosDir); + SetValuel("Ps2Out", Config.PsxOut); + SetValuel("ThPriority", Config.ThPriority); + SetValue("Mcd1", Config.Mcd1); + SetValue("Mcd2", Config.Mcd2); + // plugins + SetValue("GS", Config.GS); + SetValue("SPU2", Config.SPU2); + SetValue("CDVD", Config.CDVD); + SetValue("PAD1", Config.PAD1); + SetValue("PAD2", Config.PAD2); + SetValue("DEV9", Config.DEV9); + SetValue("USB", Config.USB); + SetValue("FW", Config.FW); + //cpu + SetValuel("Options", Config.Options); + SetValuel("SafeCnts", Config.SafeCnts); + // misc + SetValuel("Patch", Config.Patch); + SetValuel("varLog", varLog); + + fclose(f); + + return; +} diff --git a/pcsx2/Linux/GtkGui.c b/pcsx2/Linux/GtkGui.c new file mode 100644 index 0000000..1e4c37f --- /dev/null +++ b/pcsx2/Linux/GtkGui.c @@ -0,0 +1,1604 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#include "support.h" +#include "callbacks.h" +#include "interface.h" +#include "Linux.h" + + +static int needReset = 1; +int confret; +int confplug=0; +extern int RunExe; + +_PS2EgetLibType PS2EgetLibType = NULL; +_PS2EgetLibVersion2 PS2EgetLibVersion2 = NULL; +_PS2EgetLibName PS2EgetLibName = NULL; + +// Helper Functions +void FindPlugins(); + +// Functions Callbacks +void OnFile_LoadElf(GtkMenuItem *menuitem, gpointer user_data); +void OnFile_Exit(GtkMenuItem *menuitem, gpointer user_data); +void OnEmu_Run(GtkMenuItem *menuitem, gpointer user_data); +void OnEmu_Reset(GtkMenuItem *menuitem, gpointer user_data); +void OnEmu_Arguments(GtkMenuItem *menuitem, gpointer user_data); +void OnConf_Gs(GtkMenuItem *menuitem, gpointer user_data); +void OnConf_Pads(GtkMenuItem *menuitem, gpointer user_data); +void OnConf_Cpu(GtkMenuItem *menuitem, gpointer user_data); +void OnConf_Conf(GtkMenuItem *menuitem, gpointer user_data); +void OnLanguage(GtkMenuItem *menuitem, gpointer user_data); +void OnHelp_Help(); +void OnHelp_About(GtkMenuItem *menuitem, gpointer user_data); + +GtkWidget *Window; +GtkWidget* pStatusBar = NULL; +GtkWidget *CmdLine; //2002-09-28 (Florin) +GtkWidget *ConfDlg; +GtkWidget *AboutDlg; +GtkWidget *DebugWnd; +GtkWidget *LogDlg; +GtkWidget *FileSel; + +GtkAccelGroup *AccelGroup; + +typedef struct { + GtkWidget *Combo; + GList *glist; + char plist[255][255]; + int plugins; +} PluginConf; + +PluginConf GSConfS; +PluginConf PAD1ConfS; +PluginConf PAD2ConfS; +PluginConf SPU2ConfS; +PluginConf CDVDConfS; +PluginConf DEV9ConfS; +PluginConf USBConfS; +PluginConf FWConfS; +PluginConf BiosConfS; + +void StartGui() { + GtkWidget *Menu; + GtkWidget *Item; + GtkWidget* vbox; + int i; + + add_pixmap_directory(".pixmaps"); + + Window = create_MainWindow(); + +#ifdef PCSX2_VIRTUAL_MEM + gtk_window_set_title(GTK_WINDOW(Window), "PCSX2 "PCSX2_VERSION" Watermoose VM"); +#else + gtk_window_set_title(GTK_WINDOW(Window), "PCSX2 "PCSX2_VERSION" Watermoose"); +#endif + +#ifndef NEW_LOGGING + Item = lookup_widget(Window, "GtkMenuItem_Logging"); + gtk_widget_set_sensitive(Item, FALSE); +#endif + + // status bar + pStatusBar = gtk_statusbar_new (); + gtk_box_pack_start (GTK_BOX(lookup_widget(Window, "status_box")), pStatusBar, TRUE, TRUE, 0); + gtk_widget_show (pStatusBar); + + gtk_statusbar_push(GTK_STATUSBAR(pStatusBar),0, + "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot"); + + // add all the languages + Item = lookup_widget(Window, "GtkMenuItem_Language"); + Menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(Item), Menu); + + for (i=0; iExecute(); +} + +void OnFile_RunCD(GtkMenuItem *menuitem, gpointer user_data) { + needReset = 1; + efile = 0; + RunExecute(1); +} + +void OnRunElf_Ok(GtkButton* button, gpointer user_data) { + gchar *File; + + File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(elfname, File); + gtk_widget_destroy(FileSel); + needReset = 1; + efile = 1; + RunExecute(1); +} + +void OnRunElf_Cancel(GtkButton* button, gpointer user_data) { + gtk_widget_destroy(FileSel); +} + +void OnFile_LoadElf(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new("Select Psx Elf File"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnFile_Exit(GtkMenuItem *menuitem, gpointer user_data) { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256]; + + // with this the problem with plugins that are linked with the pthread + // library is solved + + dir = opendir(Config.PluginsDir); + if (dir != NULL) { + while ((ent = readdir(dir)) != NULL) { + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) continue; + } + } + + printf(_("PCSX2 Quitting\n")); + if (UseGui) gtk_main_quit(); + SysClose(); + if (UseGui) gtk_exit(0); + else exit(0); +} + +void OnEmu_Run(GtkMenuItem *menuitem, gpointer user_data) +{ + if(needReset == 1) + RunExe = 1; + efile = 0; + RunExecute(1); +} + +void OnEmu_Reset(GtkMenuItem *menuitem, gpointer user_data) +{ + ResetPlugins(); + needReset = 1; + efile = 0; +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *Item; + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "GtkMenuItem_LoadSlot%d", i+1); + Item = lookup_widget(Window, str); + if (Slots[i] == -1) + gtk_widget_set_sensitive(Item, FALSE); + else + gtk_widget_set_sensitive(Item, TRUE); + } +} + +void UpdateMenuSlots(GtkMenuItem *menuitem, gpointer user_data) { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf(str, "sstates/%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); +/* if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %d"), num+1); + else sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1); + //StatusSet(Text); + + RunExecute(1); +} + +void OnStates_Load1(GtkMenuItem *menuitem, gpointer user_data) { States_Load(0); } +void OnStates_Load2(GtkMenuItem *menuitem, gpointer user_data) { States_Load(1); } +void OnStates_Load3(GtkMenuItem *menuitem, gpointer user_data) { States_Load(2); } +void OnStates_Load4(GtkMenuItem *menuitem, gpointer user_data) { States_Load(3); } +void OnStates_Load5(GtkMenuItem *menuitem, gpointer user_data) { States_Load(4); } + +void OnLoadOther_Ok(GtkButton* button, gpointer user_data) { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + + efile = 2; + RunExecute(0); + + ret = LoadState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Loaded State %s"), str); + else sprintf (Text, _("*PCSX*: Error Loading State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnLoadOther_Cancel(GtkButton* button, gpointer user_data) { + gtk_widget_destroy(FileSel); +} + +void OnStates_LoadOther(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnStates_Save1(GtkMenuItem *menuitem, gpointer user_data) { States_Save(0); } +void OnStates_Save2(GtkMenuItem *menuitem, gpointer user_data) { States_Save(1); } +void OnStates_Save3(GtkMenuItem *menuitem, gpointer user_data) { States_Save(2); } +void OnStates_Save4(GtkMenuItem *menuitem, gpointer user_data) { States_Save(3); } +void OnStates_Save5(GtkMenuItem *menuitem, gpointer user_data) { States_Save(4); } + +void OnSaveOther_Ok(GtkButton* button, gpointer user_data) { + gchar *File; + char str[256]; + char Text[256]; + int ret; + + File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(str, File); + gtk_widget_destroy(FileSel); + RunExecute(0); + + ret = SaveState(str); +/* if (ret == 0) + sprintf (Text, _("*PCSX*: Saved State %s"), str); + else sprintf (Text, _("*PCSX*: Error Saving State %s"), str); + GPU_displayText(Text);*/ + + Cpu->Execute(); +} + +void OnSaveOther_Cancel(GtkButton* button, gpointer user_data) { + gtk_widget_destroy(FileSel); +} + +void OnStates_SaveOther(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select State File")); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), "sstates/"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +//2002-09-28 (Florin) +void OnArguments_Ok(GtkButton *button, gpointer user_data) { + GtkWidget *widgetCmdLine; + char *str; + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + str = (char*)gtk_entry_get_text(GTK_ENTRY(widgetCmdLine)); + memcpy(args, str, 256); + + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnArguments_Cancel(GtkButton* button, gpointer user_data) { + gtk_widget_destroy(CmdLine); + gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnEmu_Arguments(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *widgetCmdLine; + + CmdLine = create_CmdLine(); + gtk_window_set_title(GTK_WINDOW(CmdLine), _("Program arguments")); + + widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE"); + gtk_entry_set_text(GTK_ENTRY(widgetCmdLine), args); + //args exported by ElfHeader.h + gtk_widget_show_all(CmdLine); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} +//------------------- + +void OnConf_Gs(GtkMenuItem *menuitem, gpointer user_data) +{ + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + GSconfigure(); + chdir(file); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Pads(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + PAD1configure(); + if (strcmp(Config.PAD1, Config.PAD2)) PAD2configure(); + chdir(file); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnConf_Spu2(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + SPU2configure(); + gtk_widget_set_sensitive(Window, TRUE); + chdir(file); +} + +void OnConf_Cdvd(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + CDVDconfigure(); + gtk_widget_set_sensitive(Window, TRUE); + chdir(file); +} + +void OnConf_Dev9(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + DEV9configure(); + gtk_widget_set_sensitive(Window, TRUE); + chdir(file); +} + +void OnConf_Usb(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + USBconfigure(); + gtk_widget_set_sensitive(Window, TRUE); + chdir(file); +} + +void OnConf_Fw(GtkMenuItem *menuitem, gpointer user_data) { + char file[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + gtk_widget_set_sensitive(Window, FALSE); + FWconfigure(); + gtk_widget_set_sensitive(Window, TRUE); + chdir(file); +} + +GtkWidget *CpuDlg; + +void OnCpu_Ok(GtkButton *button, gpointer user_data) { + GtkWidget *Btn; + long t; + u32 newopts = 0; + + Cpu->Shutdown(); + vu0Shutdown(); + vu1Shutdown(); + + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_EERec"))) ) { + newopts |= PCSX2_EEREC; + } + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_VU0rec"))) ) + newopts |= PCSX2_VU0REC; + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_VU1rec"))) ) + newopts |= PCSX2_VU1REC; + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_MTGS"))) ) + newopts |= PCSX2_GSMULTITHREAD; + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_CpuDC"))) ) + newopts |= PCSX2_DUALCORE; + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitNormal"))) ) + newopts |= PCSX2_FRAMELIMIT_NORMAL; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitLimit"))) ) + newopts |= PCSX2_FRAMELIMIT_LIMIT; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitFS"))) ) + newopts |= PCSX2_FRAMELIMIT_SKIP; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_VUSkip"))) ) + newopts |= PCSX2_FRAMELIMIT_VUSKIP; + + if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) { + Config.Options = newopts; + SaveConfig(); + SysMessage("Restart Pcsx2"); + exit(0); + } + + if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC; + + Config.Options = newopts; + + UpdateVSyncRate(); + SaveConfig(); + + cpuRestartCPU(); + + gtk_widget_destroy(CpuDlg); + + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + +void OnCpu_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); +} + + +void OnConf_Cpu(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *Btn; + + CpuDlg = create_CpuDlg(); + gtk_window_set_title(GTK_WINDOW(CpuDlg), _("Configuration")); + + if(!cpucaps.hasStreamingSIMDExtensions) { + Config.Options &= (PCSX2_VU0REC|PCSX2_VU1REC);//disable the config just in case + } + if(!cpucaps.hasMultimediaExtensions) { + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC);//return to interpreter mode + } + + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_EERec")), !!CHECK_EEREC); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_VU0rec")), !!CHECK_VU0REC); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_VU1rec")), !!CHECK_VU1REC); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_MTGS")), !!CHECK_MULTIGS); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkCheckButton_CpuDC")), !!CHECK_DUALCORE); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitNormal")), CHECK_FRAMELIMIT==PCSX2_FRAMELIMIT_NORMAL); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitLimit")), CHECK_FRAMELIMIT==PCSX2_FRAMELIMIT_LIMIT); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_LimitFS")), CHECK_FRAMELIMIT==PCSX2_FRAMELIMIT_SKIP); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(CpuDlg, "GtkRadioButton_VUSkip")), CHECK_FRAMELIMIT==PCSX2_FRAMELIMIT_VUSKIP); + + gtk_widget_show_all(CpuDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +#define FindComboText(combo,list,conf) \ + if (strlen(conf) > 0) { \ + int i; \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(conf, list[i-2])) { \ + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), list[i-1]); \ + break; \ + } \ + } \ + } + +#define GetComboText(combo,list,conf) \ + { \ + int i; \ + char *tmp = (char*)gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); \ + for (i=2;i<255;i+=2) { \ + if (!strcmp(tmp, list[i-1])) { \ + strcpy(conf, list[i-2]); \ + break; \ + } \ + } \ + } + +void OnConfConf_Ok(GtkButton *button, gpointer user_data) { + GetComboText(GSConfS.Combo, GSConfS.plist, Config.GS) + GetComboText(PAD1ConfS.Combo, PAD1ConfS.plist, Config.PAD1); + GetComboText(PAD2ConfS.Combo, PAD2ConfS.plist, Config.PAD2); + GetComboText(SPU2ConfS.Combo, SPU2ConfS.plist, Config.SPU2); + GetComboText(CDVDConfS.Combo, CDVDConfS.plist, Config.CDVD); + GetComboText(DEV9ConfS.Combo, DEV9ConfS.plist, Config.DEV9); + GetComboText(USBConfS.Combo, USBConfS.plist, Config.USB); + GetComboText(FWConfS.Combo, FWConfS.plist, Config.FW); + GetComboText(BiosConfS.Combo, BiosConfS.plist, Config.Bios); + + SaveConfig(); + + if (confplug == 0) { + ReleasePlugins(); + LoadPlugins(); + } + + needReset = 1; + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 1; +} + +void OnConfConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, TRUE); + gtk_main_quit(); + confret = 0; +} + +#define ConfPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + getcwd(file, ARRAYSIZE(file)); /* store current dir */ \ + chdir(Config.PluginsDir); /* change dirs so that plugins can find their config file*/ \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) conf(); \ + chdir(file); /* change back*/ \ + SysCloseLibrary(drv); + +#define TestPlugin(src, confs, plugin, name) \ + void *drv; \ + src conf; \ + int ret = 0; \ + char file[256]; \ + GetComboText(confs.Combo, confs.plist, plugin); \ + strcpy(file, Config.PluginsDir); \ + strcat(file, plugin); \ + drv = SysLoadLibrary(file); \ + if (drv == NULL) return; \ + conf = (src) SysLoadSym(drv, name); \ + if (SysLibError() == NULL) { \ + ret = conf(); \ + if (ret == 0) \ + SysMessage(_("This plugin reports that should work correctly")); \ + else SysMessage(_("This plugin reports that should not work correctly")); \ + } \ + SysCloseLibrary(drv); + +void OnConfConf_GsConf(GtkButton *button, gpointer user_data) { + ConfPlugin(_GSconfigure, GSConfS, Config.GS, "GSconfigure"); +} + +void OnConfConf_GsTest(GtkButton *button, gpointer user_data) { + TestPlugin(_GStest, GSConfS, Config.GS, "GStest"); +} + +void OnConfConf_GsAbout(GtkButton *button, gpointer user_data) { + ConfPlugin(_GSabout, GSConfS, Config.GS, "GSabout"); +} + +void OnConfConf_Pad1Conf(GtkButton *button, gpointer user_data) { + ConfPlugin(_PADconfigure, PAD1ConfS, Config.PAD1, "PADconfigure"); +} + +void OnConfConf_Pad1Test(GtkButton *button, gpointer user_data) { + TestPlugin(_PADtest, PAD1ConfS, Config.PAD1, "PADtest"); +} + +void OnConfConf_Pad1About(GtkButton *button, gpointer user_data) { + ConfPlugin(_PADabout, PAD1ConfS, Config.PAD1, "PADabout"); +} + +void OnConfConf_Pad2Conf(GtkButton *button, gpointer user_data) { + ConfPlugin(_PADconfigure, PAD2ConfS, Config.PAD2, "PADconfigure"); +} + +void OnConfConf_Pad2Test(GtkButton *button, gpointer user_data) { + TestPlugin(_PADtest, PAD2ConfS, Config.PAD2, "PADtest"); +} + +void OnConfConf_Pad2About(GtkButton *button, gpointer user_data) { + ConfPlugin(_PADabout, PAD2ConfS, Config.PAD2, "PADabout"); +} + +void OnConfConf_Spu2Conf(GtkButton *button, gpointer user_data) { + ConfPlugin(_SPU2configure, SPU2ConfS, Config.SPU2, "SPU2configure"); +} + +void OnConfConf_Spu2Test(GtkButton *button, gpointer user_data) { + TestPlugin(_SPU2test, SPU2ConfS, Config.SPU2, "SPU2test"); +} + +void OnConfConf_Spu2About(GtkButton *button, gpointer user_data) { + ConfPlugin(_SPU2about, SPU2ConfS, Config.SPU2, "SPU2about"); +} + +void OnConfConf_CdvdConf(GtkButton *button, gpointer user_data) { + ConfPlugin(_CDVDconfigure, CDVDConfS, Config.CDVD, "CDVDconfigure"); +} + +void OnConfConf_CdvdTest(GtkButton *button, gpointer user_data) { + TestPlugin(_CDVDtest, CDVDConfS, Config.CDVD, "CDVDtest"); +} + +void OnConfConf_CdvdAbout(GtkButton *button, gpointer user_data) { + ConfPlugin(_CDVDabout, CDVDConfS, Config.CDVD, "CDVDabout"); +} + +void OnConfConf_Dev9Conf(GtkButton *button, gpointer user_data) { + ConfPlugin(_DEV9configure, DEV9ConfS, Config.DEV9, "DEV9configure"); +} + +void OnConfConf_Dev9Test(GtkButton *button, gpointer user_data) { + TestPlugin(_DEV9test, DEV9ConfS, Config.DEV9, "DEV9test"); +} + +void OnConfConf_Dev9About(GtkButton *button, gpointer user_data) { + ConfPlugin(_DEV9about, DEV9ConfS, Config.DEV9, "DEV9about"); +} + +void OnConfConf_UsbConf(GtkButton *button, gpointer user_data) { + ConfPlugin(_USBconfigure, USBConfS, Config.USB, "USBconfigure"); +} + +void OnConfConf_UsbTest(GtkButton *button, gpointer user_data) { + TestPlugin(_USBtest, USBConfS, Config.USB, "USBtest"); +} + +void OnConfConf_UsbAbout(GtkButton *button, gpointer user_data) { + ConfPlugin(_USBabout, USBConfS, Config.USB, "USBabout"); +} + +void OnConfConf_FWConf(GtkButton *button, gpointer user_data) { + ConfPlugin(_FWconfigure, FWConfS, Config.FW, "FWconfigure"); +} + +void OnConfConf_FWTest(GtkButton *button, gpointer user_data) { + TestPlugin(_FWtest, FWConfS, Config.FW, "FWtest"); +} + +void OnConfConf_FWAbout(GtkButton *button, gpointer user_data) { + ConfPlugin(_FWabout, FWConfS, Config.FW, "FWabout"); +} + +#define ConfCreatePConf(name, type) \ + type##ConfS.Combo = lookup_widget(ConfDlg, "GtkCombo_" name); \ + gtk_combo_set_popdown_strings(GTK_COMBO(type##ConfS.Combo), type##ConfS.glist); \ + FindComboText(type##ConfS.Combo, type##ConfS.plist, Config.type); \ + +void UpdateConfDlg() { + FindPlugins(); + + ConfCreatePConf("Gs", GS); + ConfCreatePConf("Pad1", PAD1); + ConfCreatePConf("Pad2", PAD2); + ConfCreatePConf("Spu2", SPU2); + ConfCreatePConf("Cdvd", CDVD); + ConfCreatePConf("Dev9", DEV9); + ConfCreatePConf("Usb", USB); + ConfCreatePConf("FW", FW); + ConfCreatePConf("Bios", Bios); +} + +void OnPluginsPath_Ok() { + gchar *File; + + File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.PluginsDir, File); + if (Config.PluginsDir[strlen(Config.PluginsDir)-1] != '/') + strcat(Config.PluginsDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnPluginsPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_PluginsPath(GtkButton *button, gpointer user_data) { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Plugins Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnPluginsPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnBiosPath_Ok() { + gchar *File; + + File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(Config.BiosDir, File); + if (Config.BiosDir[strlen(Config.BiosDir)-1] != '/') + strcat(Config.BiosDir, "/"); + + UpdateConfDlg(); + + gtk_widget_destroy(FileSel); +} + +void OnBiosPath_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnConfConf_BiosPath(GtkButton *button, gpointer user_data) { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new(_("Select Bios Directory")); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnBiosPath_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnConf_Conf(GtkMenuItem *menuitem, gpointer user_data) { + FindPlugins(); + + ConfDlg = create_ConfDlg(); + gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configuration")); + + UpdateConfDlg(); + + gtk_widget_show_all(ConfDlg); + if (Window) gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +GtkWidget *CmdLine; +GtkWidget *ListDV; +GtkWidget *SetPCDlg, *SetPCEntry; +GtkWidget *SetBPADlg, *SetBPAEntry; +GtkWidget *SetBPCDlg, *SetBPCEntry; +GtkWidget *DumpCDlg, *DumpCTEntry, *DumpCFEntry; +GtkWidget *DumpRDlg, *DumpRTEntry, *DumpRFEntry; +GtkWidget *MemWriteDlg, *MemEntry, *DataEntry; +GtkAdjustment *DebugAdj; +static u32 dPC; +static u32 dBPA = -1; +static u32 dBPC = -1; +static char nullAddr[256]; +int DebugMode; // 0 - EE | 1 - IOP + +#include "R3000A.h" +#include "PsxMem.h" + +void UpdateDebugger() { + GtkWidget *item; + char *str; + int i; + GList *list = NULL; + u32 pc; + + DebugAdj->value = (gfloat)dPC/4; + + gtk_list_clear_items(GTK_LIST(ListDV), 0, 23); + + for (i=0; i<23; i++) { + u32 *mem; + pc = dPC + i*4; + if (DebugMode) { + mem = (u32*)PSXM(pc); + } else + mem = PSM(pc); + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", pc); str = nullAddr; } + else str = disR5900Fasm(*mem, pc); + item = gtk_list_item_new_with_label(str); + gtk_widget_show(item); + list = g_list_append(list, item); + } + gtk_list_append_items(GTK_LIST(ListDV), list); +} + +void OnDebug_Close(GtkButton *button, gpointer user_data) { + ClosePlugins(); + gtk_widget_destroy(DebugWnd); + gtk_main_quit(); + gtk_widget_set_sensitive(Window, TRUE); +} + +void OnDebug_ScrollChange(GtkAdjustment *adj) { + dPC = (u32)adj->value*4; + dPC&= ~0x3; + + UpdateDebugger(); +} + +void OnSetPC_Ok(GtkButton *button, gpointer user_data) { + char *str = (char*)gtk_entry_get_text(GTK_ENTRY(SetPCEntry)); + + sscanf(str, "%lx", &dPC); + dPC&= ~0x3; + + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetPC_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(SetPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetPC(GtkButton *button, gpointer user_data) { + SetPCDlg = create_SetPCDlg(); + + SetPCEntry = lookup_widget(SetPCDlg, "GtkEntry_dPC"); + + gtk_widget_show_all(SetPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPA_Ok(GtkButton *button, gpointer user_data) { + char *str = (char*)gtk_entry_get_text(GTK_ENTRY(SetBPAEntry)); + + sscanf(str, "%lx", &dBPA); + dBPA&= ~0x3; + + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPA_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(SetBPADlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPA(GtkButton *button, gpointer user_data) { + SetBPADlg = create_SetBPADlg(); + + SetBPAEntry = lookup_widget(SetBPADlg, "GtkEntry_BPA"); + + gtk_widget_show_all(SetBPADlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnSetBPC_Ok(GtkButton *button, gpointer user_data) { + char *str = (char*)gtk_entry_get_text(GTK_ENTRY(SetBPCEntry)); + + sscanf(str, "%lx", &dBPC); + + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); + UpdateDebugger(); +} + +void OnSetBPC_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(SetBPCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_SetBPC(GtkButton *button, gpointer user_data) { + SetBPCDlg = create_SetBPCDlg(); + + SetBPCEntry = lookup_widget(SetBPCDlg, "GtkEntry_BPC"); + + gtk_widget_show_all(SetBPCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_ClearBPs(GtkButton *button, gpointer user_data) { + dBPA = -1; + dBPC = -1; +} + +void OnDumpC_Ok(GtkButton *button, gpointer user_data) { + FILE *f; + char *str = (char*)gtk_entry_get_text(GTK_ENTRY(DumpCFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = (char*)gtk_entry_get_text(GTK_ENTRY(DumpCTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) { sprintf(nullAddr, "%8.8lX:\tNULL MEMORY", addrf); str = nullAddr; } + else str = disR5900Fasm(*mem, addrf); + + fprintf(f, "%s\n", str); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpC_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(DumpCDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_DumpCode(GtkButton *button, gpointer user_data) { + DumpCDlg = create_DumpCDlg(); + + DumpCFEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCF"); + DumpCTEntry = lookup_widget(DumpCDlg, "GtkEntry_DumpCT"); + + gtk_widget_show_all(DumpCDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDumpR_Ok(GtkButton *button, gpointer user_data) { + FILE *f; + char *str = (char*)gtk_entry_get_text(GTK_ENTRY(DumpRFEntry)); + u32 addrf, addrt; + + sscanf(str, "%lx", &addrf); addrf&=~0x3; + str = (char*)gtk_entry_get_text(GTK_ENTRY(DumpRTEntry)); + sscanf(str, "%lx", &addrt); addrt&=~0x3; + + f = fopen("dump.txt", "w"); + if (f == NULL) return; + + while (addrf != addrt) { + u32 *mem; + u32 out; + + if (DebugMode) { + mem = PSXM(addrf); + } else { + mem = PSM(addrf); + } + if (mem == NULL) out = 0; + else out = *mem; + + fwrite(&out, 4, 1, f); + addrf+= 4; + } + + fclose(f); + + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDumpR_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(DumpRDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_RawDump(GtkButton *button, gpointer user_data) { + DumpRDlg = create_DumpRDlg(); + + DumpRFEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRF"); + DumpRTEntry = lookup_widget(DumpRDlg, "GtkEntry_DumpRT"); + + gtk_widget_show_all(DumpRDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); +} + +void OnDebug_Step(GtkButton *button, gpointer user_data) { + Cpu->Step(); + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Skip(GtkButton *button, gpointer user_data) { + cpuRegs.pc+= 4; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +int HasBreakPoint(u32 pc) { + if (pc == dBPA) return 1; + if (DebugMode == 0) { + if ((cpuRegs.cycle - 10) <= dBPC && + (cpuRegs.cycle + 10) >= dBPC) return 1; + } else { + if ((psxRegs.cycle - 100) <= dBPC && + (psxRegs.cycle + 100) >= dBPC) return 1; + } + return 0; +} + +void OnDebug_Go(GtkButton *button, gpointer user_data) { + for (;;) { + if (HasBreakPoint(cpuRegs.pc)) break; + Cpu->Step(); + } + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_Log(GtkButton *button, gpointer user_data) { + Log = 1 - Log; +} + +void OnDebug_EEMode(GtkToggleButton *togglebutton, gpointer user_data) { + DebugMode = 0; + dPC = cpuRegs.pc; + UpdateDebugger(); +} + +void OnDebug_IOPMode(GtkToggleButton *togglebutton, gpointer user_data) { + DebugMode = 1; + dPC = psxRegs.pc; + UpdateDebugger(); +} + +void OnMemWrite32_Ok(GtkButton *button, gpointer user_data) { + char *mem = (char*)gtk_entry_get_text(GTK_ENTRY(MemEntry)); + char *data = (char*)gtk_entry_get_text(GTK_ENTRY(DataEntry)); + + printf("memWrite32: %s, %s\n", mem, data); + memWrite32(strtol(mem, (char**)NULL, 0), strtol(data, (char**)NULL, 0)); + + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnMemWrite32_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(MemWriteDlg); + gtk_main_quit(); + gtk_widget_set_sensitive(DebugWnd, TRUE); +} + +void OnDebug_memWrite32(GtkButton *button, gpointer user_data) { + MemWriteDlg = create_MemWrite32(); + + MemEntry = lookup_widget(MemWriteDlg, "GtkEntry_Mem"); + DataEntry = lookup_widget(MemWriteDlg, "GtkEntry_Data"); + + gtk_widget_show_all(MemWriteDlg); + gtk_widget_set_sensitive(DebugWnd, FALSE); + gtk_main(); + + UpdateDebugger(); +} + +void OnDebug_Debugger(GtkMenuItem *menuitem, gpointer user_data) { + GtkWidget *scroll; + + if (OpenPlugins(NULL) == -1) return; + if (needReset) { SysReset(); needReset = 0; } + + if (!efile) + efile=GetPS2ElfName(elfname); + if (efile) + loadElfFile(elfname); + efile=0; + + dPC = cpuRegs.pc; + + DebugWnd = create_DebugWnd(); + + ListDV = lookup_widget(DebugWnd, "GtkList_DisView"); + scroll = lookup_widget(DebugWnd, "GtkVScrollbar_VList"); + + DebugAdj = GTK_RANGE(scroll)->adjustment; + DebugAdj->lower = (gfloat)0x00000000/4; + DebugAdj->upper = (gfloat)0xffffffff/4; + DebugAdj->step_increment = (gfloat)1; + DebugAdj->page_increment = (gfloat)20; + DebugAdj->page_size = (gfloat)23; + + gtk_signal_connect(GTK_OBJECT(DebugAdj), + "value_changed", GTK_SIGNAL_FUNC(OnDebug_ScrollChange), + NULL); + + UpdateDebugger(); + + gtk_widget_show_all(DebugWnd); + gtk_widget_set_sensitive(Window, FALSE); + gtk_main(); +} + +void OnLogging_Ok(GtkButton *button, gpointer user_data) { + GtkWidget *Btn; + char str[32]; + int i, ret; + + for (i=0; i<17; i++) { + sprintf(str, "Log%d", i); + Btn = lookup_widget(LogDlg, str); + ret = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + if (ret) varLog|= 1<>8)&0xff ,version&0xff, (version>>24)&0xff); \ + type##ConfS.plugins+=2; \ + strcpy(type##ConfS.plist[type##ConfS.plugins-1], name); \ + strcpy(type##ConfS.plist[type##ConfS.plugins-2], ent->d_name); \ + type##ConfS.glist = g_list_append(type##ConfS.glist, type##ConfS.plist[type##ConfS.plugins-1]); \ +} + +void FindPlugins() { + DIR *dir; + struct dirent *ent; + void *Handle; + char plugin[256],name[256]; + + GSConfS.plugins = 0; CDVDConfS.plugins = 0; DEV9ConfS.plugins = 0; + PAD1ConfS.plugins = 0; PAD2ConfS.plugins = 0; SPU2ConfS.plugins = 0; + USBConfS.plugins = 0; FWConfS.plugins = 0; BiosConfS.plugins = 0; + GSConfS.glist = NULL; CDVDConfS.glist = NULL; DEV9ConfS.glist = NULL; + PAD1ConfS.glist = NULL; PAD2ConfS.glist = NULL; SPU2ConfS.glist = NULL; + USBConfS.glist = NULL; FWConfS.glist = NULL; BiosConfS.glist = NULL; + + dir = opendir(Config.PluginsDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.PluginsDir); + return; + } + while ((ent = readdir(dir)) != NULL) { + u32 version; + u32 type; + + sprintf (plugin, "%s%s", Config.PluginsDir, ent->d_name); + + if (strstr(plugin, ".so") == NULL) continue; + Handle = dlopen(plugin, RTLD_NOW); + if (Handle == NULL) { + printf("%s\n", dlerror()); continue; + } + + PS2EgetLibType = (_PS2EgetLibType) dlsym(Handle, "PS2EgetLibType"); + PS2EgetLibName = (_PS2EgetLibName) dlsym(Handle, "PS2EgetLibName"); + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) dlsym(Handle, "PS2EgetLibVersion2"); + if (PS2EgetLibType == NULL || PS2EgetLibName == NULL || PS2EgetLibVersion2 == NULL) + continue; + type = PS2EgetLibType(); + + if (type & PS2E_LT_GS) { + version = PS2EgetLibVersion2(PS2E_LT_GS); + if (((version >> 16)&0xff) == PS2E_GS_VERSION) { + ComboAddPlugin(GS); + } + else + SysPrintf("Plugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)dlsym(Handle, "PADquery"); + version = PS2EgetLibVersion2(PS2E_LT_PAD); + if (((version >> 16)&0xff) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(PAD1); + if (query() & 0x2) + ComboAddPlugin(PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2EgetLibVersion2(PS2E_LT_SPU2); + if (((version >> 16)&0xff) == PS2E_SPU2_VERSION) { + ComboAddPlugin(SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2EgetLibVersion2(PS2E_LT_CDVD); + if (((version >> 16)&0xff) == PS2E_CDVD_VERSION) { + ComboAddPlugin(CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2EgetLibVersion2(PS2E_LT_DEV9); + if (((version >> 16)&0xff) == PS2E_DEV9_VERSION) { + ComboAddPlugin(DEV9); + } else SysPrintf("DEV9Plugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2EgetLibVersion2(PS2E_LT_USB); + if (((version >> 16)&0xff) == PS2E_USB_VERSION) { + ComboAddPlugin(USB); + } else SysPrintf("USBPlugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2EgetLibVersion2(PS2E_LT_FW); + if (((version >> 16)&0xff) == PS2E_FW_VERSION) { + ComboAddPlugin(FW); + } else SysPrintf("FWPlugin %s: Version %x != %x\n", plugin, (version >> 16)&0xff, PS2E_FW_VERSION); + } + } + closedir(dir); + + dir = opendir(Config.BiosDir); + if (dir == NULL) { + SysMessage(_("Could not open '%s' directory"), Config.BiosDir); + return; + } + + while ((ent = readdir(dir)) != NULL) { + struct stat buf; + char description[50]; //2002-09-28 (Florin) + + sprintf (plugin, "%s%s", Config.BiosDir, ent->d_name); + if (stat(plugin, &buf) == -1) continue; +// if (buf.st_size < (1024*512)) continue; + if (buf.st_size > (1024*4096)) continue; //2002-09-28 (Florin) + if (!IsBIOS(ent->d_name, description)) continue;//2002-09-28 (Florin) + + BiosConfS.plugins+=2; + sprintf(description, "%s (%s)", description, ent->d_name); + strcpy(BiosConfS.plist[BiosConfS.plugins-1], description);//2002-09-28 (Florin) modified + strcpy(BiosConfS.plist[BiosConfS.plugins-2], ent->d_name); + BiosConfS.glist = g_list_append(BiosConfS.glist, BiosConfS.plist[BiosConfS.plugins-1]); + } + closedir(dir); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + if (!UseGui) { printf("%s\n",msg); return; } + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), _("PCSX2 Msg")); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label(_("Ok")); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + gtk_widget_grab_focus(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +void +on_patch_browser1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ +} + +void +on_patch_finder2_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ +} + +void +on_enable_console1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + Config.PsxOut=(int)gtk_check_menu_item_get_active((GtkCheckMenuItem*)menuitem); + SaveConfig(); +} + +void +on_enable_patches1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + Config.Patch=(int)gtk_check_menu_item_get_active((GtkCheckMenuItem*)menuitem); + SaveConfig(); +} diff --git a/pcsx2/Linux/Linux.h b/pcsx2/Linux/Linux.h new file mode 100644 index 0000000..cc966bb --- /dev/null +++ b/pcsx2/Linux/Linux.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + +#include "Common.h" + +typedef struct { + char lang[256]; +} _langs; + +_langs *langs; +unsigned int langsMax; + +extern int UseGui; +char cfgfile[256]; + +int LoadConfig(); +void SaveConfig(); + +void StartGui(); +void RunGui(); + +int Pcsx2Configure(); + +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); + +#endif /* __LINUX_H__ */ diff --git a/pcsx2/Linux/LnxMain.c b/pcsx2/Linux/LnxMain.c new file mode 100644 index 0000000..206048a --- /dev/null +++ b/pcsx2/Linux/LnxMain.c @@ -0,0 +1,616 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "Common.h" +#include "PsxCommon.h" +#include "Linux.h" + +int UseGui = 1; +int needReset = 1; +int RunExe = 0; +extern int g_SaveGSStream; +extern int g_ZeroGSOptions; + +#ifdef PCSX2_DEVBUILD + +TESTRUNARGS g_TestRun; +char* g_pRunGSState = NULL; + +#endif + +int main(int argc, char *argv[]) { + char *file = NULL; + char elfname[256]; + char *lang; + int runcd=0; + int efile = 0; + char* g_pRunGSState = NULL; + int i; + struct stat buf; + +#ifdef PCSX2_VIRTUAL_MEM + void* pmem = mmap(PS2MEM_BASE, 0x40000000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + + if( pmem != PS2MEM_BASE ) { + SysMessage("Failed to allocate virtual memory %x-%x. Use TLB build", + PS2MEM_BASE, PS2MEM_BASE+0x40000000); + return -1; + } +#endif + + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, "Langs"); + textdomain(PACKAGE); +#endif + + printf("\n"); + mkdir("inis", 0755); + + strcpy(cfgfile, "inis/pcsx2.cfg"); + +#ifdef PCSX2_DEVBUILD + memset(&g_TestRun, 0, sizeof(g_TestRun)); +#endif + + i = 1; + while(i < argc) { + char* token = argv[i++]; + + if( stricmp(token, "-help") == 0 || stricmp(token, "--help") == 0 || stricmp(token, "-h") == 0 ) { + char* phelpmsg = + "\tpcsx2 [options] [file]\n\n" + "-cfg [file] {configuration file}\n" + "-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n" + "-help {display this help file}\n" + "-nogui {Don't use gui when launching}\n" + "-loadgs [file} {Loads a gsstate}\n" + "\n" +#ifdef PCSX2_DEVBUILD + "Testing Options: \n" + "\t-frame [frame] {game will run up to this frame before exiting}\n" + "\t-image [name] {path and base name of image (do not include the .ext)}\n" + "\t-jpg {save images to jpg format}\n" + "\t-log [name] {log path to save log file in}\n" + "\t-logopt [hex] {log options in hex (see debug.h) }\n" + "\t-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n" + "\t-test {Triggers testing mode (only for dev builds)}\n" + "\n" +#endif + + "Load Plugins:\n" + "\t-cdvd [dllpath] {specify the dll load path of the CDVD plugin}\n" + "\t-gs [dllpath] {specify the dll load path of the GS plugin}\n" + "-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n" + "\t-spu [dllpath] {specify the dll load path of the SPU2 plugin}\n" + "\n"; + + //SysMessage(phelpmsg); + return 0; + } + else if( stricmp(token, "-efile") == 0 ) { + token = argv[i++]; + if( token != NULL ) { + efile = atoi(token); + } + } + else if( stricmp(token, "-nogui") == 0 ) { + UseGui = 0; + } + else if( stricmp(token, "-image") == 0 ) { + g_TestRun.pimagename = argv[i++]; + } + else if( stricmp(token, "-loadgs") == 0 ) { + g_pRunGSState = argv[i++]; + } + else if( stricmp(token, "-log") == 0 ) { + g_TestRun.plogname = argv[i++]; + } + else if( stricmp(token, "-logopt") == 0 ) { + token = argv[i++]; + if( token != NULL ) { + if( token[0] == '0' && token[1] == 'x' ) token += 2; + sscanf(token, "%x", &varLog); + } + } + else if( stricmp(token, "-pad") == 0 ) { + token = argv[i++]; + printf("-pad ignored\n"); + } + else if( stricmp(token, "-frame") == 0 ) { + token = argv[i++]; + if( token != NULL ) { + g_TestRun.frame = atoi(token); + } + } + else if( stricmp(token, "-numimages") == 0 ) { + token = argv[i++]; + if( token != NULL ) { + g_TestRun.numimages = atoi(token); + } + } + else if( stricmp(token, "-jpg") == 0 ) { + g_TestRun.jpgcapture = 1; + } + else if( stricmp(token, "-gs") == 0 ) { + token = argv[i++]; + g_TestRun.pgsdll = token; + } + else if( stricmp(token, "-cdvd") == 0 ) { + token = argv[i++]; + g_TestRun.pcdvddll = token; + } + else if( stricmp(token, "-spu") == 0 ) { + token = argv[i++]; + g_TestRun.pspudll = token; + } + else if( stricmp(token, "-loadgs") == 0 ) { + token = argv[i++]; + g_pRunGSState = token; + } + else if( stricmp(token, "-test") == 0 ) { + g_TestRun.enabled = 1; + } + else { + file = token; + printf("opening file %s\n", file); + } + } + +#ifdef PCSX2_DEVBUILD + g_TestRun.efile = efile; + g_TestRun.ptitle = file; +#endif + + if (LoadConfig() == -1) { + + if (UseGui) gtk_init(NULL, NULL); + + memset(&Config, 0, sizeof(Config)); + strcpy(Config.BiosDir, "bios/"); + strcpy(Config.PluginsDir, "plugins/"); + Config.Patch = 1; + + SysMessage(_("Pcsx2 needs to be configured")); + Pcsx2Configure(); + + return 0; + } + + // make gtk thread safe if using MTGS + if( CHECK_MULTIGS ) { + g_thread_init(NULL); + gdk_threads_init(); + } + + if (UseGui) gtk_init(NULL, NULL); + + if (Config.Lang[0] == 0) { + strcpy(Config.Lang, "en"); + } + + langs = (_langs*)malloc(sizeof(_langs)); + strcpy(langs[0].lang, "en"); + InitLanguages(); i=1; + while ((lang = GetLanguageNext()) != NULL) { + langs = (_langs*)realloc(langs, sizeof(_langs)*(i+1)); + strcpy(langs[i].lang, lang); + i++; + } + CloseLanguages(); + langsMax = i; + + if( Config.PsxOut ) { + // output the help commands + SysPrintf("\tF1 - save state\n"); + SysPrintf("\t(Shift +) F2 - cycle states\n"); + SysPrintf("\tF3 - load state\n"); + +#ifdef PCSX2_DEVBUILD + SysPrintf("\tF10 - dump performance counters\n"); + SysPrintf("\tF11 - save GS state\n"); + SysPrintf("\tF12 - dump hardware registers\n"); +#endif + } + + if (SysInit() == -1) return 1; + +#ifdef PCSX2_DEVBUILD + if( g_pRunGSState ) { + LoadGSState(g_pRunGSState); + SysClose(); + return 0; + } +#endif + + if (UseGui&&file==NULL) { + StartGui(); + return 0; + } + + if (OpenPlugins(file) == -1) { + return -1; + } + SysReset(); + + cpuExecuteBios(); + if (file) + strcpy(elfname, file); + if (!efile) + efile=GetPS2ElfName(elfname); + loadElfFile(elfname); + + if( GSsetGameCRC != NULL ) + GSsetGameCRC(ElfCRC, g_ZeroGSOptions); + + Cpu->Execute(); + + return 0; +} + +DIR *dir; + +void InitLanguages() { + dir = opendir("Langs"); +} + +char *GetLanguageNext() { + struct dirent *ent; + + if (dir == NULL) return NULL; + for (;;) { + ent = readdir(dir); + if (ent == NULL) return NULL; + + if (!strcmp(ent->d_name, ".")) continue; + if (!strcmp(ent->d_name, "..")) continue; + break; + } + + return ent->d_name; +} + +void CloseLanguages() { + if (dir) closedir(dir); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +void KeyEvent(keyEvent* ev) { + char Text[256]; + int ret; + static int shift = 0; + + if (ev == NULL) + return; + + if( GSkeyEvent != NULL ) + GSkeyEvent(ev); + + if( ev->event == KEYPRESS ) { + if( ev->key == XK_Shift_L || ev->key == XK_Shift_R ) + shift = 1; + } + else { + if (ev->event == KEYRELEASE) { + if( ev->key == XK_Shift_L || ev->key == XK_Shift_R ) + shift = 0; + } + + return; + } + + switch (ev->key) { + case XK_F1: ProcessFKeys(1, shift); break; + case XK_F2: ProcessFKeys(2, shift); break; + case XK_F3: ProcessFKeys(3, shift); break; + case XK_F4: ProcessFKeys(4, shift); break; + case XK_F5: ProcessFKeys(5, shift); break; + case XK_F6: ProcessFKeys(6, shift); break; + case XK_F7: ProcessFKeys(7, shift); break; + case XK_F8: ProcessFKeys(8, shift); break; + case XK_F9: ProcessFKeys(9, shift); break; + case XK_F10: ProcessFKeys(10, shift); break; + case XK_F11: ProcessFKeys(11, shift); break; + case XK_F12: ProcessFKeys(12, shift); break; + + case XK_Escape: + signal(SIGINT, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + +#ifdef PCSX2_DEVBUILD + if( g_SaveGSStream >= 3 ) { + // gs state + g_SaveGSStream = 4; + break; + } +#endif + + ClosePlugins(); + if (!UseGui) + exit(0); + RunGui(); + break; + default: + GSkeyEvent(ev); + break; + } +} + +int SysInit() { + mkdir("sstates", 0755); + mkdir("memcards", 0755); + +#ifdef EMU_LOG + mkdir("logs", 0755); + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.plogname != NULL ) + emuLog = fopen(g_TestRun.plogname, "w"); + if( emuLog == NULL ) + emuLog = fopen("logs/emuLog.txt","wb"); +#endif + + if( emuLog != NULL ) + setvbuf(emuLog, NULL, _IONBF, 0); +#endif + + if(cpuInit() == -1 ) + return -1; + + while (LoadPlugins() == -1) { + if (Pcsx2Configure() == 0) + exit(1); + } + + return 0; +} + +void SysReset() { + cpuReset(); +} + +void SysClose() { + cpuShutdown(); + ReleasePlugins(); + + if (emuLog != NULL) { + fclose(emuLog); + emuLog = NULL; + } +} + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + char* ptr, *src; + int len, i, j, s; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (Config.PsxOut == 0) { +#ifdef EMU_LOG +#ifndef LOG_STDOUT + if (emuLog != NULL && !(varLog & 0x80000000)) { + fprintf(emuLog, "%s", msg); + } +#endif +#endif + return; + } + + // due to various linux ways of writing lines, convert all \r\n to \n +// src = msg; +// while( (ptr = strstr(src, "\r\n")) != NULL ) { +// ptr[0] = 0; +// printf("%s\n", src); +// src = ptr+2; +// } +// +// if( src[0] != 0 ) +// printf("%s", src); + printf("%s", msg); + +#ifdef EMU_LOG +#ifndef LOG_STDOUT + if (emuLog != NULL && !(varLog & 0x80000000)) { + ptr = msg; len = strlen(msg); + for (i=0, j=0; ipname = (char*)malloc(20); + sprintf(pblock->pname, "/pcsx2_shm%d", s_nShmCounter++); + shm_unlink(pblock->pname); // unlink to make sure one can be created + pblock->fd = shm_open(pblock->pname, O_RDWR|O_CREAT, 0); + + if( pblock->fd < 0 ) { + perror("shm_open failed"); + SysMessage("Failed to create shared memory object %s\n", pblock->pname); + return -1; + } + + if( ftruncate(fd, size) < 0 ) { + perror("ftruncate failed"); + SysMessage("Failed to allocate 0x%x bytes to shm\n", size); + } + + pblock->size = size; + + return 0; +} + +void SysPhysicalFree(PSMEMORYBLOCK* pblock) +{ + assert( pblock != NULL ); + if( pblock->fd ) + close(pblock->fd); + if( pblock->pname ) { + shm_unlink(pblock->pname); + free(pblock->pname); + } + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); +} + +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + void* pmem; + assert(pblock != NULL && pblock->fd >= 0 && pblock->size >= size ); + pmem = mmap(base, size, PROT_READ|PROT_WRITE, MAP_SHARED, pblock->fd, 0); + + if( pmem != base ) { + + if( pmem == (void*)-1 ) { + munmap(base, size); + } + + SysPrintf("Failed to map memory at 0x%x of size 0x%x with shm %s\n", (uptr)base, (uptr)size, pblock->pname); + return -1; + } + + return 0; +} + +void SysVirtualFree(void* lpMemReserved, u32 size) +{ + if( munmap(lpMemReserved, size) < 0 ) + SysPrintf("Failed to unmap %x\n", lpMemReserved); +} + + +int SysMapUserPhysicalPages(void* Addr, uptr NumPages, PSMEMORYBLOCK* pblock, int pageoffset) +{ + void* pmem; + if( pblock == NULL ) { + // unmap + if( munmap(base, size) < 0 ) { + SysPrintf("SysMapUserPhysicalPages: Failed to unmap %x\n", Addr); + return 0; + } + } + else { + // map + pmem = mmap(Addr, NumPages*s_nPageSize, PROT_READ|PROT_WRITE, MAP_SHARED, pblock->fd, pageoffset*s_nPageSize); + if( pmem != base ) { + SysPrintf("SysMapUserPhysicalPages: Failed to map 0x%x, size=0x%x, offset=0x%x\n", + Addr, NumPages*s_nPageSize, pageoffset*s_nPageSize); + return 0; + } + } + + return 1; +} + +#endif diff --git a/pcsx2/Linux/Makefile.am b/pcsx2/Linux/Makefile.am new file mode 100644 index 0000000..84abfcf --- /dev/null +++ b/pcsx2/Linux/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I@srcdir@/../ + +bin_PROGRAMS = pcsx2 + +# the application source, library search path, and link libraries +pcsx2_SOURCES = Config.c interface.c GtkGui.c LnxMain.c support.c + +pcsx2_LDFLAGS = + +pcsx2_DEPENDENCIES = ../libpcsx2.a ../IPU/libIPU.a ../IPU/mpeg2lib/libmpeg2IPU.a ../RDebug/libRDebug.a ../tinyxml/libtinyxml.a + +pcsx2_LDADD = ../libpcsx2.a ../IPU/libIPU.a ../IPU/mpeg2lib/libmpeg2IPU.a ../RDebug/libRDebug.a ../tinyxml/libtinyxml.a + + +if RECBUILD +pcsx2_LDADD += ../x86/libx86recomp.a ../x86/ix86/libix86.a +pcsx2_DEPENDENCIES += ../x86/libx86recomp.a ../x86/ix86/libix86.a +endif + +pcsx2_DEPENDENCIES += ../DebugTools/libDebugTools.a +pcsx2_LDADD += ../DebugTools/libDebugTools.a \ No newline at end of file diff --git a/pcsx2/Linux/buildgui.sh b/pcsx2/Linux/buildgui.sh new file mode 100644 index 0000000..207e12f --- /dev/null +++ b/pcsx2/Linux/buildgui.sh @@ -0,0 +1,9 @@ +# builds the GUI C classes +mkdir temp +cp pcsx2.glade temp/ +cd temp +glade-2 --write-source pcsx2.glade +rm src/main.c +cp src/*.h src/*.c ../ +cd .. +/bin/rm -rf temp diff --git a/pcsx2/Linux/callbacks.h b/pcsx2/Linux/callbacks.h new file mode 100644 index 0000000..4bec544 --- /dev/null +++ b/pcsx2/Linux/callbacks.h @@ -0,0 +1,386 @@ +#include + + +void +OnDestroy (GtkObject *object, + gpointer user_data); + +void +OnFile_RunCD (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_LoadElf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Load5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_LoadOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save1 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save3 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save4 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_Save5 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnStates_SaveOther (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnFile_Exit (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Run (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Reset (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnEmu_Arguments (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Conf (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Gs (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Pads (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Spu2 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cdvd (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Dev9 (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Usb (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Fw (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnConf_Cpu (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_patch_browser1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_patch_finder2_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_enable_console1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_enable_patches1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_Debugger (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnDebug_Logging (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelp_About (GtkMenuItem *menuitem, + gpointer user_data); + +void +OnHelpAbout_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad2About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Pad1About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_GsAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Spu2About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9Conf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9Test (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Dev9About (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_CdvdAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_UsbAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWConf (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWTest (GtkButton *button, + gpointer user_data); + +void +OnConfConf_FWAbout (GtkButton *button, + gpointer user_data); + +void +OnConfConf_PluginsPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_BiosPath (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnCpu_Ok (GtkButton *button, + gpointer user_data); + +void +OnCpu_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDebug_EEMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnDebug_IOPMode (GtkToggleButton *togglebutton, + gpointer user_data); + +void +OnDebug_Step (GtkButton *button, + gpointer user_data); + +void +OnDebug_Skip (GtkButton *button, + gpointer user_data); + +void +OnDebug_Go (GtkButton *button, + gpointer user_data); + +void +OnDebug_Log (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPA (GtkButton *button, + gpointer user_data); + +void +OnDebug_SetBPC (GtkButton *button, + gpointer user_data); + +void +OnDebug_ClearBPs (GtkButton *button, + gpointer user_data); + +void +OnDebug_DumpCode (GtkButton *button, + gpointer user_data); + +void +OnDebug_RawDump (GtkButton *button, + gpointer user_data); + +void +OnDebug_Close (GtkButton *button, + gpointer user_data); + +void +OnDebug_memWrite32 (GtkButton *button, + gpointer user_data); + +void +OnSetPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPA_Cancel (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Ok (GtkButton *button, + gpointer user_data); + +void +OnSetBPC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpC_Cancel (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Ok (GtkButton *button, + gpointer user_data); + +void +OnDumpR_Cancel (GtkButton *button, + gpointer user_data); + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data); + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data); + +void +OnArguments_Ok (GtkButton *button, + gpointer user_data); + +void +OnArguments_Cancel (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Ok (GtkButton *button, + gpointer user_data); + +void +OnMemWrite32_Cancel (GtkButton *button, + gpointer user_data); diff --git a/pcsx2/Linux/interface.c b/pcsx2/Linux/interface.c new file mode 100644 index 0000000..2004b8d --- /dev/null +++ b/pcsx2/Linux/interface.c @@ -0,0 +1,2742 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_MainWindow (void) +{ + GtkWidget *MainWindow; + GtkWidget *vbox1; + GtkWidget *GtkMenuBar_Menu; + GtkWidget *GtkMenuItem_File; + GtkWidget *GtkMenuItem_File_menu; + GtkWidget *run_cd1; + GtkWidget *GtkMenuItem_LoadElf; + GtkWidget *separator2; + GtkWidget *states1; + GtkWidget *states1_menu; + GtkWidget *load1; + GtkWidget *load1_menu; + GtkWidget *slot_1; + GtkWidget *slot_3; + GtkWidget *slot_4; + GtkWidget *slot_5; + GtkWidget *slot_2; + GtkWidget *other1; + GtkWidget *save1; + GtkWidget *save1_menu; + GtkWidget *slot_6; + GtkWidget *slot_7; + GtkWidget *slot_8; + GtkWidget *slot_9; + GtkWidget *slot_10; + GtkWidget *other2; + GtkWidget *GtkMenuItem_Exit; + GtkWidget *GtkMenuItem_Emulator; + GtkWidget *GtkMenuItem_Emulator_menu; + GtkWidget *GtkMenuItem_Run; + GtkWidget *GtkMenuItem_Reset; + GtkWidget *GtkMenuItem_Arguments; + GtkWidget *GtkMenuItem_Configuration; + GtkWidget *GtkMenuItem_Configuration_menu; + GtkWidget *GtkMenuItem_PluginsBios; + GtkWidget *separator3; + GtkWidget *GtkMenuItem_Graphics; + GtkWidget *GtkMenuItem_Controllers; + GtkWidget *GtkMenuItem_Sound; + GtkWidget *GtkMenuItem_Cdvdrom; + GtkWidget *GtkMenuItem_Dev9; + GtkWidget *GtkMenuItem_USB; + GtkWidget *GtkMenuItem_FW; + GtkWidget *separator4; + GtkWidget *GtkMenuItem_Cpu; + GtkWidget *GtkMenuItem_Language; + GtkWidget *misc1; + GtkWidget *misc1_menu; + GtkWidget *patch_browser1; + GtkWidget *patch_finder2; + GtkWidget *separator7; + GtkWidget *enable_console1; + GtkWidget *enable_patches1; + GtkWidget *GtkMenuItem_Debug; + GtkWidget *GtkMenuItem_Debug_menu; + GtkWidget *GtkMenuItem_EnterDebugger; + GtkWidget *GtkMenuItem_Logging; + GtkWidget *GtkMenuItem_Help; + GtkWidget *GtkMenuItem_Help_menu; + GtkWidget *GtkMenuItem_About; + GtkWidget *image1; + GtkWidget *status_box; + + MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (MainWindow), _("PCSX")); + gtk_window_set_position (GTK_WINDOW (MainWindow), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (MainWindow), vbox1); + + GtkMenuBar_Menu = gtk_menu_bar_new (); + gtk_widget_show (GtkMenuBar_Menu); + gtk_box_pack_start (GTK_BOX (vbox1), GtkMenuBar_Menu, FALSE, FALSE, 0); + + GtkMenuItem_File = gtk_menu_item_new_with_mnemonic (_("_File")); + gtk_widget_show (GtkMenuItem_File); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_File); + + GtkMenuItem_File_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_File), GtkMenuItem_File_menu); + + run_cd1 = gtk_menu_item_new_with_mnemonic (_("_Run CD")); + gtk_widget_show (run_cd1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), run_cd1); + + GtkMenuItem_LoadElf = gtk_menu_item_new_with_mnemonic (_("_Load Elf")); + gtk_widget_show (GtkMenuItem_LoadElf); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_LoadElf); + + separator2 = gtk_separator_menu_item_new (); + gtk_widget_show (separator2); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), separator2); + gtk_widget_set_sensitive (separator2, FALSE); + + states1 = gtk_menu_item_new_with_mnemonic (_("States")); + gtk_widget_show (states1); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), states1); + + states1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (states1), states1_menu); + + load1 = gtk_menu_item_new_with_mnemonic (_("Load")); + gtk_widget_show (load1); + gtk_container_add (GTK_CONTAINER (states1_menu), load1); + + load1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (load1), load1_menu); + + slot_1 = gtk_menu_item_new_with_mnemonic (_("Slot 1")); + gtk_widget_show (slot_1); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_1); + + slot_3 = gtk_menu_item_new_with_mnemonic (_("Slot 2")); + gtk_widget_show (slot_3); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_3); + + slot_4 = gtk_menu_item_new_with_mnemonic (_("Slot 3")); + gtk_widget_show (slot_4); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_4); + + slot_5 = gtk_menu_item_new_with_mnemonic (_("Slot 4")); + gtk_widget_show (slot_5); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_5); + + slot_2 = gtk_menu_item_new_with_mnemonic (_("Slot 5")); + gtk_widget_show (slot_2); + gtk_container_add (GTK_CONTAINER (load1_menu), slot_2); + + other1 = gtk_menu_item_new_with_mnemonic (_("Other...")); + gtk_widget_show (other1); + gtk_container_add (GTK_CONTAINER (load1_menu), other1); + + save1 = gtk_menu_item_new_with_mnemonic (_("Save")); + gtk_widget_show (save1); + gtk_container_add (GTK_CONTAINER (states1_menu), save1); + + save1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (save1), save1_menu); + + slot_6 = gtk_menu_item_new_with_mnemonic (_("Slot 1")); + gtk_widget_show (slot_6); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_6); + + slot_7 = gtk_menu_item_new_with_mnemonic (_("Slot 2")); + gtk_widget_show (slot_7); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_7); + + slot_8 = gtk_menu_item_new_with_mnemonic (_("Slot 3")); + gtk_widget_show (slot_8); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_8); + + slot_9 = gtk_menu_item_new_with_mnemonic (_("Slot 4")); + gtk_widget_show (slot_9); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_9); + + slot_10 = gtk_menu_item_new_with_mnemonic (_("Slot 5")); + gtk_widget_show (slot_10); + gtk_container_add (GTK_CONTAINER (save1_menu), slot_10); + + other2 = gtk_menu_item_new_with_mnemonic (_("Other...")); + gtk_widget_show (other2); + gtk_container_add (GTK_CONTAINER (save1_menu), other2); + + GtkMenuItem_Exit = gtk_menu_item_new_with_mnemonic (_("E_xit")); + gtk_widget_show (GtkMenuItem_Exit); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_File_menu), GtkMenuItem_Exit); + + GtkMenuItem_Emulator = gtk_menu_item_new_with_mnemonic (_("_Run")); + gtk_widget_show (GtkMenuItem_Emulator); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Emulator); + + GtkMenuItem_Emulator_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Emulator), GtkMenuItem_Emulator_menu); + + GtkMenuItem_Run = gtk_menu_item_new_with_mnemonic (_("E_xecute")); + gtk_widget_show (GtkMenuItem_Run); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Run); + + GtkMenuItem_Reset = gtk_menu_item_new_with_mnemonic (_("Re_set")); + gtk_widget_show (GtkMenuItem_Reset); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Reset); + + GtkMenuItem_Arguments = gtk_menu_item_new_with_mnemonic (_("_Arguments")); + gtk_widget_show (GtkMenuItem_Arguments); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Emulator_menu), GtkMenuItem_Arguments); + + GtkMenuItem_Configuration = gtk_menu_item_new_with_mnemonic (_("_Config")); + gtk_widget_show (GtkMenuItem_Configuration); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Configuration); + + GtkMenuItem_Configuration_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Configuration), GtkMenuItem_Configuration_menu); + + GtkMenuItem_PluginsBios = gtk_menu_item_new_with_mnemonic (_("_Configure")); + gtk_widget_show (GtkMenuItem_PluginsBios); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_PluginsBios); + + separator3 = gtk_separator_menu_item_new (); + gtk_widget_show (separator3); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator3); + gtk_widget_set_sensitive (separator3, FALSE); + + GtkMenuItem_Graphics = gtk_menu_item_new_with_mnemonic (_("_Graphics")); + gtk_widget_show (GtkMenuItem_Graphics); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Graphics); + + GtkMenuItem_Controllers = gtk_menu_item_new_with_mnemonic (_("C_ontrollers")); + gtk_widget_show (GtkMenuItem_Controllers); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Controllers); + + GtkMenuItem_Sound = gtk_menu_item_new_with_mnemonic (_("_Sound")); + gtk_widget_show (GtkMenuItem_Sound); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Sound); + + GtkMenuItem_Cdvdrom = gtk_menu_item_new_with_mnemonic (_("_Cdvdrom")); + gtk_widget_show (GtkMenuItem_Cdvdrom); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cdvdrom); + + GtkMenuItem_Dev9 = gtk_menu_item_new_with_mnemonic (_("D_ev9")); + gtk_widget_show (GtkMenuItem_Dev9); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Dev9); + + GtkMenuItem_USB = gtk_menu_item_new_with_mnemonic (_("U_SB")); + gtk_widget_show (GtkMenuItem_USB); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_USB); + + GtkMenuItem_FW = gtk_menu_item_new_with_mnemonic (_("Fire_Wire")); + gtk_widget_show (GtkMenuItem_FW); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_FW); + + separator4 = gtk_separator_menu_item_new (); + gtk_widget_show (separator4); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), separator4); + gtk_widget_set_sensitive (separator4, FALSE); + + GtkMenuItem_Cpu = gtk_menu_item_new_with_mnemonic (_("C_pu")); + gtk_widget_show (GtkMenuItem_Cpu); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Configuration_menu), GtkMenuItem_Cpu); + + GtkMenuItem_Language = gtk_menu_item_new_with_mnemonic (_("_Language")); + gtk_widget_show (GtkMenuItem_Language); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Language); + + misc1 = gtk_menu_item_new_with_mnemonic (_("_Misc")); + gtk_widget_show (misc1); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), misc1); + + misc1_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (misc1), misc1_menu); + + patch_browser1 = gtk_menu_item_new_with_mnemonic (_("Patch _Browser")); + gtk_widget_show (patch_browser1); + gtk_container_add (GTK_CONTAINER (misc1_menu), patch_browser1); + + patch_finder2 = gtk_menu_item_new_with_mnemonic (_("Patch _Finder")); + gtk_widget_show (patch_finder2); + gtk_container_add (GTK_CONTAINER (misc1_menu), patch_finder2); + + separator7 = gtk_separator_menu_item_new (); + gtk_widget_show (separator7); + gtk_container_add (GTK_CONTAINER (misc1_menu), separator7); + gtk_widget_set_sensitive (separator7, FALSE); + + enable_console1 = gtk_check_menu_item_new_with_mnemonic (_("Enable _Console")); + gtk_widget_show (enable_console1); + gtk_container_add (GTK_CONTAINER (misc1_menu), enable_console1); + + enable_patches1 = gtk_check_menu_item_new_with_mnemonic (_("Enable _Patches")); + gtk_widget_show (enable_patches1); + gtk_container_add (GTK_CONTAINER (misc1_menu), enable_patches1); + + GtkMenuItem_Debug = gtk_menu_item_new_with_mnemonic (_("_Debug")); + gtk_widget_show (GtkMenuItem_Debug); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Debug); + + GtkMenuItem_Debug_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Debug), GtkMenuItem_Debug_menu); + + GtkMenuItem_EnterDebugger = gtk_menu_item_new_with_mnemonic (_("Enter Debugger ...")); + gtk_widget_show (GtkMenuItem_EnterDebugger); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_EnterDebugger); + + GtkMenuItem_Logging = gtk_menu_item_new_with_mnemonic (_("Logging")); + gtk_widget_show (GtkMenuItem_Logging); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Debug_menu), GtkMenuItem_Logging); + + GtkMenuItem_Help = gtk_menu_item_new_with_mnemonic (_("_Help")); + gtk_widget_show (GtkMenuItem_Help); + gtk_container_add (GTK_CONTAINER (GtkMenuBar_Menu), GtkMenuItem_Help); + + GtkMenuItem_Help_menu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (GtkMenuItem_Help), GtkMenuItem_Help_menu); + + GtkMenuItem_About = gtk_menu_item_new_with_mnemonic (_("&About...")); + gtk_widget_show (GtkMenuItem_About); + gtk_container_add (GTK_CONTAINER (GtkMenuItem_Help_menu), GtkMenuItem_About); + + image1 = create_pixmap (MainWindow, "pcsxAbout.bmp"); + gtk_widget_show (image1); + gtk_box_pack_start (GTK_BOX (vbox1), image1, TRUE, TRUE, 1); + + status_box = gtk_vbox_new (FALSE, 0); + gtk_widget_show (status_box); + gtk_box_pack_start (GTK_BOX (vbox1), status_box, TRUE, TRUE, 0); + + g_signal_connect ((gpointer) MainWindow, "destroy", + G_CALLBACK (OnDestroy), + NULL); + g_signal_connect ((gpointer) run_cd1, "activate", + G_CALLBACK (OnFile_RunCD), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_LoadElf, "activate", + G_CALLBACK (OnFile_LoadElf), + NULL); + g_signal_connect ((gpointer) slot_1, "activate", + G_CALLBACK (OnStates_Load1), + NULL); + g_signal_connect ((gpointer) slot_3, "activate", + G_CALLBACK (OnStates_Load2), + NULL); + g_signal_connect ((gpointer) slot_4, "activate", + G_CALLBACK (OnStates_Load3), + NULL); + g_signal_connect ((gpointer) slot_5, "activate", + G_CALLBACK (OnStates_Load4), + NULL); + g_signal_connect ((gpointer) slot_2, "activate", + G_CALLBACK (OnStates_Load5), + NULL); + g_signal_connect ((gpointer) other1, "activate", + G_CALLBACK (OnStates_LoadOther), + NULL); + g_signal_connect ((gpointer) slot_6, "activate", + G_CALLBACK (OnStates_Save1), + NULL); + g_signal_connect ((gpointer) slot_7, "activate", + G_CALLBACK (OnStates_Save2), + NULL); + g_signal_connect ((gpointer) slot_8, "activate", + G_CALLBACK (OnStates_Save3), + NULL); + g_signal_connect ((gpointer) slot_9, "activate", + G_CALLBACK (OnStates_Save4), + NULL); + g_signal_connect ((gpointer) slot_10, "activate", + G_CALLBACK (OnStates_Save5), + NULL); + g_signal_connect ((gpointer) other2, "activate", + G_CALLBACK (OnStates_SaveOther), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Exit, "activate", + G_CALLBACK (OnFile_Exit), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Run, "activate", + G_CALLBACK (OnEmu_Run), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Reset, "activate", + G_CALLBACK (OnEmu_Reset), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Arguments, "activate", + G_CALLBACK (OnEmu_Arguments), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_PluginsBios, "activate", + G_CALLBACK (OnConf_Conf), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Graphics, "activate", + G_CALLBACK (OnConf_Gs), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Controllers, "activate", + G_CALLBACK (OnConf_Pads), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Sound, "activate", + G_CALLBACK (OnConf_Spu2), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Cdvdrom, "activate", + G_CALLBACK (OnConf_Cdvd), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Dev9, "activate", + G_CALLBACK (OnConf_Dev9), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_USB, "activate", + G_CALLBACK (OnConf_Usb), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_FW, "activate", + G_CALLBACK (OnConf_Fw), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Cpu, "activate", + G_CALLBACK (OnConf_Cpu), + NULL); + g_signal_connect ((gpointer) patch_browser1, "activate", + G_CALLBACK (on_patch_browser1_activate), + NULL); + g_signal_connect ((gpointer) patch_finder2, "activate", + G_CALLBACK (on_patch_finder2_activate), + NULL); + g_signal_connect ((gpointer) enable_console1, "activate", + G_CALLBACK (on_enable_console1_activate), + NULL); + g_signal_connect ((gpointer) enable_patches1, "activate", + G_CALLBACK (on_enable_patches1_activate), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_EnterDebugger, "activate", + G_CALLBACK (OnDebug_Debugger), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_Logging, "activate", + G_CALLBACK (OnDebug_Logging), + NULL); + g_signal_connect ((gpointer) GtkMenuItem_About, "activate", + G_CALLBACK (OnHelp_About), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (MainWindow, MainWindow, "MainWindow"); + GLADE_HOOKUP_OBJECT (MainWindow, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuBar_Menu, "GtkMenuBar_Menu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_File, "GtkMenuItem_File"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_File_menu, "GtkMenuItem_File_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, run_cd1, "run_cd1"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_LoadElf, "GtkMenuItem_LoadElf"); + GLADE_HOOKUP_OBJECT (MainWindow, separator2, "separator2"); + GLADE_HOOKUP_OBJECT (MainWindow, states1, "states1"); + GLADE_HOOKUP_OBJECT (MainWindow, states1_menu, "states1_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, load1, "load1"); + GLADE_HOOKUP_OBJECT (MainWindow, load1_menu, "load1_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_1, "slot_1"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_3, "slot_3"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_4, "slot_4"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_5, "slot_5"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_2, "slot_2"); + GLADE_HOOKUP_OBJECT (MainWindow, other1, "other1"); + GLADE_HOOKUP_OBJECT (MainWindow, save1, "save1"); + GLADE_HOOKUP_OBJECT (MainWindow, save1_menu, "save1_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_6, "slot_6"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_7, "slot_7"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_8, "slot_8"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_9, "slot_9"); + GLADE_HOOKUP_OBJECT (MainWindow, slot_10, "slot_10"); + GLADE_HOOKUP_OBJECT (MainWindow, other2, "other2"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Exit, "GtkMenuItem_Exit"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Emulator, "GtkMenuItem_Emulator"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Emulator_menu, "GtkMenuItem_Emulator_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Run, "GtkMenuItem_Run"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Reset, "GtkMenuItem_Reset"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Arguments, "GtkMenuItem_Arguments"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Configuration, "GtkMenuItem_Configuration"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Configuration_menu, "GtkMenuItem_Configuration_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_PluginsBios, "GtkMenuItem_PluginsBios"); + GLADE_HOOKUP_OBJECT (MainWindow, separator3, "separator3"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Graphics, "GtkMenuItem_Graphics"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Controllers, "GtkMenuItem_Controllers"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Sound, "GtkMenuItem_Sound"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Cdvdrom, "GtkMenuItem_Cdvdrom"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Dev9, "GtkMenuItem_Dev9"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_USB, "GtkMenuItem_USB"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_FW, "GtkMenuItem_FW"); + GLADE_HOOKUP_OBJECT (MainWindow, separator4, "separator4"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Cpu, "GtkMenuItem_Cpu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Language, "GtkMenuItem_Language"); + GLADE_HOOKUP_OBJECT (MainWindow, misc1, "misc1"); + GLADE_HOOKUP_OBJECT (MainWindow, misc1_menu, "misc1_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, patch_browser1, "patch_browser1"); + GLADE_HOOKUP_OBJECT (MainWindow, patch_finder2, "patch_finder2"); + GLADE_HOOKUP_OBJECT (MainWindow, separator7, "separator7"); + GLADE_HOOKUP_OBJECT (MainWindow, enable_console1, "enable_console1"); + GLADE_HOOKUP_OBJECT (MainWindow, enable_patches1, "enable_patches1"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Debug, "GtkMenuItem_Debug"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Debug_menu, "GtkMenuItem_Debug_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_EnterDebugger, "GtkMenuItem_EnterDebugger"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Logging, "GtkMenuItem_Logging"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Help, "GtkMenuItem_Help"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_Help_menu, "GtkMenuItem_Help_menu"); + GLADE_HOOKUP_OBJECT (MainWindow, GtkMenuItem_About, "GtkMenuItem_About"); + GLADE_HOOKUP_OBJECT (MainWindow, image1, "image1"); + GLADE_HOOKUP_OBJECT (MainWindow, status_box, "status_box"); + + return MainWindow; +} + +GtkWidget* +create_AboutDlg (void) +{ + GtkWidget *AboutDlg; + GtkWidget *vbox2; + GtkWidget *hbox1; + GtkWidget *vbox4; + GtkWidget *GtkAbout_LabelVersion; + GtkWidget *frame1; + GtkWidget *vbox6; + GtkWidget *GtkAbout_LabelAuthors; + GtkWidget *pixmap1; + GtkWidget *frame2; + GtkWidget *vbox5; + GtkWidget *GtkAbout_LabelGreets; + GtkWidget *hbuttonbox1; + GtkWidget *GtkButton_Ok; + + AboutDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (AboutDlg), 10); + gtk_window_set_title (GTK_WINDOW (AboutDlg), _("Pcsx About")); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (AboutDlg), vbox2); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbox1, TRUE, TRUE, 0); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox4); + gtk_box_pack_start (GTK_BOX (hbox1), vbox4, TRUE, TRUE, 0); + + GtkAbout_LabelVersion = gtk_label_new (_("PCSX2\n\nVersion x.x")); + gtk_widget_show (GtkAbout_LabelVersion); + gtk_box_pack_start (GTK_BOX (vbox4), GtkAbout_LabelVersion, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GtkAbout_LabelVersion), GTK_JUSTIFY_CENTER); + + frame1 = gtk_frame_new (NULL); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox4), frame1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame1), 5); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (frame1), vbox6); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + GtkAbout_LabelAuthors = gtk_label_new (_("written by...")); + gtk_widget_show (GtkAbout_LabelAuthors); + gtk_box_pack_start (GTK_BOX (vbox6), GtkAbout_LabelAuthors, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GtkAbout_LabelAuthors), GTK_JUSTIFY_CENTER); + + pixmap1 = create_pixmap (AboutDlg, "pcsxAbout.xpm"); + gtk_widget_show (pixmap1); + gtk_box_pack_start (GTK_BOX (hbox1), pixmap1, TRUE, TRUE, 0); + + frame2 = gtk_frame_new (NULL); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox2), frame2, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame2), 5); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (frame2), vbox5); + gtk_container_set_border_width (GTK_CONTAINER (vbox5), 5); + + GtkAbout_LabelGreets = gtk_label_new (_("greets to...")); + gtk_widget_show (GtkAbout_LabelGreets); + gtk_box_pack_start (GTK_BOX (vbox5), GtkAbout_LabelGreets, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GtkAbout_LabelGreets), GTK_JUSTIFY_CENTER); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox1, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 30); + + GtkButton_Ok = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) GtkButton_Ok, "clicked", + G_CALLBACK (OnHelpAbout_Ok), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (AboutDlg, AboutDlg, "AboutDlg"); + GLADE_HOOKUP_OBJECT (AboutDlg, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (AboutDlg, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (AboutDlg, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT (AboutDlg, GtkAbout_LabelVersion, "GtkAbout_LabelVersion"); + GLADE_HOOKUP_OBJECT (AboutDlg, frame1, "frame1"); + GLADE_HOOKUP_OBJECT (AboutDlg, vbox6, "vbox6"); + GLADE_HOOKUP_OBJECT (AboutDlg, GtkAbout_LabelAuthors, "GtkAbout_LabelAuthors"); + GLADE_HOOKUP_OBJECT (AboutDlg, pixmap1, "pixmap1"); + GLADE_HOOKUP_OBJECT (AboutDlg, frame2, "frame2"); + GLADE_HOOKUP_OBJECT (AboutDlg, vbox5, "vbox5"); + GLADE_HOOKUP_OBJECT (AboutDlg, GtkAbout_LabelGreets, "GtkAbout_LabelGreets"); + GLADE_HOOKUP_OBJECT (AboutDlg, hbuttonbox1, "hbuttonbox1"); + GLADE_HOOKUP_OBJECT (AboutDlg, GtkButton_Ok, "GtkButton_Ok"); + + return AboutDlg; +} + +GtkWidget* +create_ConfDlg (void) +{ + GtkWidget *ConfDlg; + GtkWidget *vbox12; + GtkWidget *table2; + GtkWidget *GtkCombo_Pad1; + GList *GtkCombo_Pad1_items = NULL; + GtkWidget *combo_entry4; + GtkWidget *GtkCombo_Pad2; + GList *GtkCombo_Pad2_items = NULL; + GtkWidget *combo_entry5; + GtkWidget *hbuttonbox6; + GtkWidget *GtkButton_PAD2configure; + GtkWidget *GtkButton_PAD2test; + GtkWidget *GtkButton_PAD2about; + GtkWidget *hbuttonbox7; + GtkWidget *GtkButton_PAD1configure; + GtkWidget *GtkButton_PAD1test; + GtkWidget *GtkButton_PAD1about; + GtkWidget *hbuttonbox8; + GtkWidget *GtkButton_GSconfigure; + GtkWidget *GtkButton_GStest; + GtkWidget *GtkButton_GSabout; + GtkWidget *GtkLabel_Graphics; + GtkWidget *GtkLabel_FirstController; + GtkWidget *GtkLabel_SecondController; + GtkWidget *GtkCombo_Gs; + GList *GtkCombo_Gs_items = NULL; + GtkWidget *combo_entry2; + GtkWidget *GtkLabel_Sound; + GtkWidget *GtkCombo_Spu2; + GList *GtkCombo_Spu2_items = NULL; + GtkWidget *entry1; + GtkWidget *hbuttonbox12; + GtkWidget *GtkButton_SPU2configure; + GtkWidget *GtkButton_SPU2test; + GtkWidget *GtkButton_SPU2about; + GtkWidget *GtkCombo_Dev9; + GList *GtkCombo_Dev9_items = NULL; + GtkWidget *entry3; + GtkWidget *hbuttonbox21; + GtkWidget *GtkButton_DEV9configure; + GtkWidget *GtkButton_DEV9test; + GtkWidget *GtkButton_DEV9about; + GtkWidget *label23; + GtkWidget *GtkLabel_Cdvdrom; + GtkWidget *GtkCombo_Cdvd; + GList *GtkCombo_Cdvd_items = NULL; + GtkWidget *entry2; + GtkWidget *hbuttonbox13; + GtkWidget *GtkButton_CDVDconfigure; + GtkWidget *GtkButton_CDVDtest; + GtkWidget *GtkButton_CDVDabout; + GtkWidget *label29; + GtkWidget *GtkCombo_Usb; + GList *GtkCombo_Usb_items = NULL; + GtkWidget *entry4; + GtkWidget *hbuttonbox23; + GtkWidget *GtkButton_USBconfigure; + GtkWidget *GtkButton_USBtest; + GtkWidget *GtkButton_USBabout; + GtkWidget *GtkCombo_Bios; + GList *GtkCombo_Bios_items = NULL; + GtkWidget *combo_entry7; + GtkWidget *GtkCombo_FW; + GList *GtkCombo_FW_items = NULL; + GtkWidget *entry5; + GtkWidget *hbuttonbox24; + GtkWidget *GtkButton_FWconfigure; + GtkWidget *GtkButton_FWtest; + GtkWidget *GtkButton_FireWireabout; + GtkWidget *label30; + GtkWidget *GtkLabel_Bios; + GtkWidget *hbox5; + GtkWidget *hbuttonbox11; + GtkWidget *GtkButton_SelectPluginsDir; + GtkWidget *GtkButton_SelectBiosDir; + GtkWidget *hbuttonbox10; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + ConfDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (ConfDlg), 10); + gtk_window_set_title (GTK_WINDOW (ConfDlg), _("Conf")); + + vbox12 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox12); + gtk_container_add (GTK_CONTAINER (ConfDlg), vbox12); + + table2 = gtk_table_new (14, 2, FALSE); + gtk_widget_show (table2); + gtk_box_pack_start (GTK_BOX (vbox12), table2, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table2), 15); + + GtkCombo_Pad1 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Pad1)->popwin), + "GladeParentKey", GtkCombo_Pad1); + gtk_widget_show (GtkCombo_Pad1); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad1, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Pad1_items = g_list_append (GtkCombo_Pad1_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Pad1), GtkCombo_Pad1_items); + g_list_free (GtkCombo_Pad1_items); + + combo_entry4 = GTK_COMBO (GtkCombo_Pad1)->entry; + gtk_widget_show (combo_entry4); + gtk_entry_set_invisible_char (GTK_ENTRY (combo_entry4), 8226); + + GtkCombo_Pad2 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Pad2)->popwin), + "GladeParentKey", GtkCombo_Pad2); + gtk_widget_show (GtkCombo_Pad2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Pad2, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Pad2_items = g_list_append (GtkCombo_Pad2_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Pad2), GtkCombo_Pad2_items); + g_list_free (GtkCombo_Pad2_items); + + combo_entry5 = GTK_COMBO (GtkCombo_Pad2)->entry; + gtk_widget_show (combo_entry5); + gtk_entry_set_invisible_char (GTK_ENTRY (combo_entry5), 8226); + + hbuttonbox6 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox6); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox6, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + GtkButton_PAD2configure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_PAD2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2configure, GTK_CAN_DEFAULT); + + GtkButton_PAD2test = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_PAD2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2test, GTK_CAN_DEFAULT); + + GtkButton_PAD2about = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_PAD2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox6), GtkButton_PAD2about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD2about, GTK_CAN_DEFAULT); + + hbuttonbox7 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox7); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox7, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + GtkButton_PAD1configure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_PAD1configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1configure); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1configure, GTK_CAN_DEFAULT); + + GtkButton_PAD1test = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_PAD1test); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1test); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1test, GTK_CAN_DEFAULT); + + GtkButton_PAD1about = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_PAD1about); + gtk_container_add (GTK_CONTAINER (hbuttonbox7), GtkButton_PAD1about); + GTK_WIDGET_SET_FLAGS (GtkButton_PAD1about, GTK_CAN_DEFAULT); + + hbuttonbox8 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox8); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox8, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + GtkButton_GSconfigure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_GSconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_GSconfigure, GTK_CAN_DEFAULT); + + GtkButton_GStest = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_GStest); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GStest); + GTK_WIDGET_SET_FLAGS (GtkButton_GStest, GTK_CAN_DEFAULT); + + GtkButton_GSabout = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_GSabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox8), GtkButton_GSabout); + GTK_WIDGET_SET_FLAGS (GtkButton_GSabout, GTK_CAN_DEFAULT); + + GtkLabel_Graphics = gtk_label_new (_("Graphics")); + gtk_widget_show (GtkLabel_Graphics); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Graphics, 0, 1, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Graphics), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Graphics), 0, 0.5); + + GtkLabel_FirstController = gtk_label_new (_("First Controller")); + gtk_widget_show (GtkLabel_FirstController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_FirstController, 0, 1, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_FirstController), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_FirstController), 0, 0.5); + + GtkLabel_SecondController = gtk_label_new (_("Second Controller")); + gtk_widget_show (GtkLabel_SecondController); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_SecondController, 1, 2, 3, 4, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_SecondController), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_SecondController), 0, 0.5); + + GtkCombo_Gs = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Gs)->popwin), + "GladeParentKey", GtkCombo_Gs); + gtk_widget_show (GtkCombo_Gs); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Gs, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Gs_items = g_list_append (GtkCombo_Gs_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Gs), GtkCombo_Gs_items); + g_list_free (GtkCombo_Gs_items); + + combo_entry2 = GTK_COMBO (GtkCombo_Gs)->entry; + gtk_widget_show (combo_entry2); + gtk_entry_set_invisible_char (GTK_ENTRY (combo_entry2), 8226); + + GtkLabel_Sound = gtk_label_new (_("Sound")); + gtk_widget_show (GtkLabel_Sound); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Sound, 1, 2, 0, 1, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Sound), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Sound), 0, 0.5); + + GtkCombo_Spu2 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Spu2)->popwin), + "GladeParentKey", GtkCombo_Spu2); + gtk_widget_show (GtkCombo_Spu2); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Spu2, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Spu2_items = g_list_append (GtkCombo_Spu2_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Spu2), GtkCombo_Spu2_items); + g_list_free (GtkCombo_Spu2_items); + + entry1 = GTK_COMBO (GtkCombo_Spu2)->entry; + gtk_widget_show (entry1); + gtk_entry_set_invisible_char (GTK_ENTRY (entry1), 8226); + + hbuttonbox12 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox12); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox12, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + GtkButton_SPU2configure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_SPU2configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2configure); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2configure, GTK_CAN_DEFAULT); + + GtkButton_SPU2test = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_SPU2test); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2test); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2test, GTK_CAN_DEFAULT); + + GtkButton_SPU2about = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_SPU2about); + gtk_container_add (GTK_CONTAINER (hbuttonbox12), GtkButton_SPU2about); + GTK_WIDGET_SET_FLAGS (GtkButton_SPU2about, GTK_CAN_DEFAULT); + + GtkCombo_Dev9 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Dev9)->popwin), + "GladeParentKey", GtkCombo_Dev9); + gtk_widget_show (GtkCombo_Dev9); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Dev9, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Dev9_items = g_list_append (GtkCombo_Dev9_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Dev9), GtkCombo_Dev9_items); + g_list_free (GtkCombo_Dev9_items); + + entry3 = GTK_COMBO (GtkCombo_Dev9)->entry; + gtk_widget_show (entry3); + gtk_entry_set_invisible_char (GTK_ENTRY (entry3), 8226); + + hbuttonbox21 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox21); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox21, 0, 1, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + GtkButton_DEV9configure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_DEV9configure); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9configure); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9configure, GTK_CAN_DEFAULT); + + GtkButton_DEV9test = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_DEV9test); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9test); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9test, GTK_CAN_DEFAULT); + + GtkButton_DEV9about = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_DEV9about); + gtk_container_add (GTK_CONTAINER (hbuttonbox21), GtkButton_DEV9about); + GTK_WIDGET_SET_FLAGS (GtkButton_DEV9about, GTK_CAN_DEFAULT); + + label23 = gtk_label_new (_("Dev9")); + gtk_widget_show (label23); + gtk_table_attach (GTK_TABLE (table2), label23, 0, 1, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (label23), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label23), 0, 0.5); + + GtkLabel_Cdvdrom = gtk_label_new (_("Cdvdrom")); + gtk_widget_show (GtkLabel_Cdvdrom); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Cdvdrom, 1, 2, 6, 7, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Cdvdrom), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Cdvdrom), 0, 0.5); + + GtkCombo_Cdvd = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Cdvd)->popwin), + "GladeParentKey", GtkCombo_Cdvd); + gtk_widget_show (GtkCombo_Cdvd); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Cdvd, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Cdvd_items = g_list_append (GtkCombo_Cdvd_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Cdvd), GtkCombo_Cdvd_items); + g_list_free (GtkCombo_Cdvd_items); + + entry2 = GTK_COMBO (GtkCombo_Cdvd)->entry; + gtk_widget_show (entry2); + gtk_entry_set_invisible_char (GTK_ENTRY (entry2), 8226); + + hbuttonbox13 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox13); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox13, 1, 2, 8, 9, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + GtkButton_CDVDconfigure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_CDVDconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDconfigure, GTK_CAN_DEFAULT); + + GtkButton_CDVDtest = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_CDVDtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDtest); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDtest, GTK_CAN_DEFAULT); + + GtkButton_CDVDabout = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_CDVDabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox13), GtkButton_CDVDabout); + GTK_WIDGET_SET_FLAGS (GtkButton_CDVDabout, GTK_CAN_DEFAULT); + + label29 = gtk_label_new (_("Usb")); + gtk_widget_show (label29); + gtk_table_attach (GTK_TABLE (table2), label29, 0, 1, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (label29), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label29), 0, 0.5); + + GtkCombo_Usb = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Usb)->popwin), + "GladeParentKey", GtkCombo_Usb); + gtk_widget_show (GtkCombo_Usb); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Usb, 0, 1, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Usb_items = g_list_append (GtkCombo_Usb_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Usb), GtkCombo_Usb_items); + g_list_free (GtkCombo_Usb_items); + + entry4 = GTK_COMBO (GtkCombo_Usb)->entry; + gtk_widget_show (entry4); + gtk_entry_set_invisible_char (GTK_ENTRY (entry4), 8226); + + hbuttonbox23 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox23); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox23, 0, 1, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + GtkButton_USBconfigure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_USBconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_USBconfigure, GTK_CAN_DEFAULT); + + GtkButton_USBtest = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_USBtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBtest); + GTK_WIDGET_SET_FLAGS (GtkButton_USBtest, GTK_CAN_DEFAULT); + + GtkButton_USBabout = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_USBabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox23), GtkButton_USBabout); + GTK_WIDGET_SET_FLAGS (GtkButton_USBabout, GTK_CAN_DEFAULT); + + GtkCombo_Bios = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_Bios)->popwin), + "GladeParentKey", GtkCombo_Bios); + gtk_widget_show (GtkCombo_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_Bios, 1, 2, 13, 14, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_Bios_items = g_list_append (GtkCombo_Bios_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_Bios), GtkCombo_Bios_items); + g_list_free (GtkCombo_Bios_items); + + combo_entry7 = GTK_COMBO (GtkCombo_Bios)->entry; + gtk_widget_show (combo_entry7); + gtk_entry_set_invisible_char (GTK_ENTRY (combo_entry7), 8226); + + GtkCombo_FW = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (GtkCombo_FW)->popwin), + "GladeParentKey", GtkCombo_FW); + gtk_widget_show (GtkCombo_FW); + gtk_table_attach (GTK_TABLE (table2), GtkCombo_FW, 1, 2, 10, 11, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + GtkCombo_FW_items = g_list_append (GtkCombo_FW_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (GtkCombo_FW), GtkCombo_FW_items); + g_list_free (GtkCombo_FW_items); + + entry5 = GTK_COMBO (GtkCombo_FW)->entry; + gtk_widget_show (entry5); + gtk_entry_set_invisible_char (GTK_ENTRY (entry5), 8226); + + hbuttonbox24 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox24); + gtk_table_attach (GTK_TABLE (table2), hbuttonbox24, 1, 2, 11, 12, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + GtkButton_FWconfigure = gtk_button_new_with_mnemonic (_("Configure")); + gtk_widget_show (GtkButton_FWconfigure); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWconfigure); + GTK_WIDGET_SET_FLAGS (GtkButton_FWconfigure, GTK_CAN_DEFAULT); + + GtkButton_FWtest = gtk_button_new_with_mnemonic (_("Test")); + gtk_widget_show (GtkButton_FWtest); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FWtest); + GTK_WIDGET_SET_FLAGS (GtkButton_FWtest, GTK_CAN_DEFAULT); + + GtkButton_FireWireabout = gtk_button_new_with_mnemonic (_("About")); + gtk_widget_show (GtkButton_FireWireabout); + gtk_container_add (GTK_CONTAINER (hbuttonbox24), GtkButton_FireWireabout); + GTK_WIDGET_SET_FLAGS (GtkButton_FireWireabout, GTK_CAN_DEFAULT); + + label30 = gtk_label_new (_("FireWire")); + gtk_widget_show (label30); + gtk_table_attach (GTK_TABLE (table2), label30, 1, 2, 9, 10, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (label30), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label30), 0, 0.5); + + GtkLabel_Bios = gtk_label_new (_("Bios")); + gtk_widget_show (GtkLabel_Bios); + gtk_table_attach (GTK_TABLE (table2), GtkLabel_Bios, 1, 2, 12, 13, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Bios), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Bios), 0, 0.5); + + hbox5 = gtk_hbox_new (FALSE, 14); + gtk_widget_show (hbox5); + gtk_box_pack_start (GTK_BOX (vbox12), hbox5, TRUE, TRUE, 0); + + hbuttonbox11 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox11); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox11, FALSE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox11), GTK_BUTTONBOX_START); + + GtkButton_SelectPluginsDir = gtk_button_new_with_mnemonic (_("Select Plugins Dir")); + gtk_widget_show (GtkButton_SelectPluginsDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectPluginsDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectPluginsDir, GTK_CAN_DEFAULT); + + GtkButton_SelectBiosDir = gtk_button_new_with_mnemonic (_("Select Bios Dir")); + gtk_widget_show (GtkButton_SelectBiosDir); + gtk_container_add (GTK_CONTAINER (hbuttonbox11), GtkButton_SelectBiosDir); + GTK_WIDGET_SET_FLAGS (GtkButton_SelectBiosDir, GTK_CAN_DEFAULT); + + hbuttonbox10 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox10); + gtk_box_pack_start (GTK_BOX (hbox5), hbuttonbox10, TRUE, TRUE, 0); + + GtkButton_Ok = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox10), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) GtkButton_PAD2configure, "clicked", + G_CALLBACK (OnConfConf_Pad2Conf), + NULL); + g_signal_connect ((gpointer) GtkButton_PAD2test, "clicked", + G_CALLBACK (OnConfConf_Pad2Test), + NULL); + g_signal_connect ((gpointer) GtkButton_PAD2about, "clicked", + G_CALLBACK (OnConfConf_Pad2About), + NULL); + g_signal_connect ((gpointer) GtkButton_PAD1configure, "clicked", + G_CALLBACK (OnConfConf_Pad1Conf), + NULL); + g_signal_connect ((gpointer) GtkButton_PAD1test, "clicked", + G_CALLBACK (OnConfConf_Pad1Test), + NULL); + g_signal_connect ((gpointer) GtkButton_PAD1about, "clicked", + G_CALLBACK (OnConfConf_Pad1About), + NULL); + g_signal_connect ((gpointer) GtkButton_GSconfigure, "clicked", + G_CALLBACK (OnConfConf_GsConf), + NULL); + g_signal_connect ((gpointer) GtkButton_GStest, "clicked", + G_CALLBACK (OnConfConf_GsTest), + NULL); + g_signal_connect ((gpointer) GtkButton_GSabout, "clicked", + G_CALLBACK (OnConfConf_GsAbout), + NULL); + g_signal_connect ((gpointer) GtkButton_SPU2configure, "clicked", + G_CALLBACK (OnConfConf_Spu2Conf), + NULL); + g_signal_connect ((gpointer) GtkButton_SPU2test, "clicked", + G_CALLBACK (OnConfConf_Spu2Test), + NULL); + g_signal_connect ((gpointer) GtkButton_SPU2about, "clicked", + G_CALLBACK (OnConfConf_Spu2About), + NULL); + g_signal_connect ((gpointer) GtkButton_DEV9configure, "clicked", + G_CALLBACK (OnConfConf_Dev9Conf), + NULL); + g_signal_connect ((gpointer) GtkButton_DEV9test, "clicked", + G_CALLBACK (OnConfConf_Dev9Test), + NULL); + g_signal_connect ((gpointer) GtkButton_DEV9about, "clicked", + G_CALLBACK (OnConfConf_Dev9About), + NULL); + g_signal_connect ((gpointer) GtkButton_CDVDconfigure, "clicked", + G_CALLBACK (OnConfConf_CdvdConf), + NULL); + g_signal_connect ((gpointer) GtkButton_CDVDtest, "clicked", + G_CALLBACK (OnConfConf_CdvdTest), + NULL); + g_signal_connect ((gpointer) GtkButton_CDVDabout, "clicked", + G_CALLBACK (OnConfConf_CdvdAbout), + NULL); + g_signal_connect ((gpointer) GtkButton_USBconfigure, "clicked", + G_CALLBACK (OnConfConf_UsbConf), + NULL); + g_signal_connect ((gpointer) GtkButton_USBtest, "clicked", + G_CALLBACK (OnConfConf_UsbTest), + NULL); + g_signal_connect ((gpointer) GtkButton_USBabout, "clicked", + G_CALLBACK (OnConfConf_UsbAbout), + NULL); + g_signal_connect ((gpointer) GtkButton_FWconfigure, "clicked", + G_CALLBACK (OnConfConf_FWConf), + NULL); + g_signal_connect ((gpointer) GtkButton_FWtest, "clicked", + G_CALLBACK (OnConfConf_FWTest), + NULL); + g_signal_connect ((gpointer) GtkButton_FireWireabout, "clicked", + G_CALLBACK (OnConfConf_FWAbout), + NULL); + g_signal_connect ((gpointer) GtkButton_SelectPluginsDir, "clicked", + G_CALLBACK (OnConfConf_PluginsPath), + NULL); + g_signal_connect ((gpointer) GtkButton_SelectBiosDir, "clicked", + G_CALLBACK (OnConfConf_BiosPath), + NULL); + g_signal_connect ((gpointer) GtkButton_Ok, "clicked", + G_CALLBACK (OnConfConf_Ok), + NULL); + g_signal_connect ((gpointer) GtkButton_Cancel, "clicked", + G_CALLBACK (OnConfConf_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (ConfDlg, ConfDlg, "ConfDlg"); + GLADE_HOOKUP_OBJECT (ConfDlg, vbox12, "vbox12"); + GLADE_HOOKUP_OBJECT (ConfDlg, table2, "table2"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Pad1, "GtkCombo_Pad1"); + GLADE_HOOKUP_OBJECT (ConfDlg, combo_entry4, "combo_entry4"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Pad2, "GtkCombo_Pad2"); + GLADE_HOOKUP_OBJECT (ConfDlg, combo_entry5, "combo_entry5"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox6, "hbuttonbox6"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD2configure, "GtkButton_PAD2configure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD2test, "GtkButton_PAD2test"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD2about, "GtkButton_PAD2about"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox7, "hbuttonbox7"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD1configure, "GtkButton_PAD1configure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD1test, "GtkButton_PAD1test"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_PAD1about, "GtkButton_PAD1about"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox8, "hbuttonbox8"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_GSconfigure, "GtkButton_GSconfigure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_GStest, "GtkButton_GStest"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_GSabout, "GtkButton_GSabout"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_Graphics, "GtkLabel_Graphics"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_FirstController, "GtkLabel_FirstController"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_SecondController, "GtkLabel_SecondController"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Gs, "GtkCombo_Gs"); + GLADE_HOOKUP_OBJECT (ConfDlg, combo_entry2, "combo_entry2"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_Sound, "GtkLabel_Sound"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Spu2, "GtkCombo_Spu2"); + GLADE_HOOKUP_OBJECT (ConfDlg, entry1, "entry1"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox12, "hbuttonbox12"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_SPU2configure, "GtkButton_SPU2configure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_SPU2test, "GtkButton_SPU2test"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_SPU2about, "GtkButton_SPU2about"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Dev9, "GtkCombo_Dev9"); + GLADE_HOOKUP_OBJECT (ConfDlg, entry3, "entry3"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox21, "hbuttonbox21"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_DEV9configure, "GtkButton_DEV9configure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_DEV9test, "GtkButton_DEV9test"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_DEV9about, "GtkButton_DEV9about"); + GLADE_HOOKUP_OBJECT (ConfDlg, label23, "label23"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_Cdvdrom, "GtkLabel_Cdvdrom"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Cdvd, "GtkCombo_Cdvd"); + GLADE_HOOKUP_OBJECT (ConfDlg, entry2, "entry2"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox13, "hbuttonbox13"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_CDVDconfigure, "GtkButton_CDVDconfigure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_CDVDtest, "GtkButton_CDVDtest"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_CDVDabout, "GtkButton_CDVDabout"); + GLADE_HOOKUP_OBJECT (ConfDlg, label29, "label29"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Usb, "GtkCombo_Usb"); + GLADE_HOOKUP_OBJECT (ConfDlg, entry4, "entry4"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox23, "hbuttonbox23"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_USBconfigure, "GtkButton_USBconfigure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_USBtest, "GtkButton_USBtest"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_USBabout, "GtkButton_USBabout"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_Bios, "GtkCombo_Bios"); + GLADE_HOOKUP_OBJECT (ConfDlg, combo_entry7, "combo_entry7"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkCombo_FW, "GtkCombo_FW"); + GLADE_HOOKUP_OBJECT (ConfDlg, entry5, "entry5"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox24, "hbuttonbox24"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_FWconfigure, "GtkButton_FWconfigure"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_FWtest, "GtkButton_FWtest"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_FireWireabout, "GtkButton_FireWireabout"); + GLADE_HOOKUP_OBJECT (ConfDlg, label30, "label30"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkLabel_Bios, "GtkLabel_Bios"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbox5, "hbox5"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox11, "hbuttonbox11"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_SelectPluginsDir, "GtkButton_SelectPluginsDir"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_SelectBiosDir, "GtkButton_SelectBiosDir"); + GLADE_HOOKUP_OBJECT (ConfDlg, hbuttonbox10, "hbuttonbox10"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_Ok, "GtkButton_Ok"); + GLADE_HOOKUP_OBJECT (ConfDlg, GtkButton_Cancel, "GtkButton_Cancel"); + + return ConfDlg; +} + +GtkWidget* +create_CpuDlg (void) +{ + GtkWidget *CpuDlg; + GtkWidget *vbox8; + GtkWidget *hbox20; + GtkWidget *alignment1; + GtkWidget *vbox27; + GtkWidget *alignment3; + GtkWidget *frame8; + GtkWidget *alignment2; + GtkWidget *vbox28; + GtkWidget *GtkLabel_CpuVendor; + GtkWidget *GtkLabel_Family; + GtkWidget *GtkLabel_CpuSpeed; + GtkWidget *GtkLabel_Features; + GtkWidget *label35; + GtkWidget *GtkCheckButton_EERec; + GtkWidget *frame6; + GtkWidget *vbox26; + GtkWidget *GtkCheckButton_VU0rec; + GtkWidget *GtkCheckButton_VU1rec; + GtkWidget *label32; + GtkWidget *GtkCheckButton_MTGS; + GtkWidget *GtkCheckButton_CpuDC; + GtkWidget *frame9; + GtkWidget *alignment4; + GtkWidget *vbox29; + GtkWidget *GtkRadioButton_LimitNormal; + GSList *GtkRadioButton_LimitNormal_group = NULL; + GtkWidget *GtkRadioButton_LimitLimit; + GtkWidget *GtkRadioButton_LimitFS; + GtkWidget *GtkRadioButton_VUSkip; + GtkWidget *label41; + GtkWidget *hbuttonbox3; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + + CpuDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (CpuDlg), 5); + gtk_window_set_title (GTK_WINDOW (CpuDlg), _("Cpu")); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (CpuDlg), vbox8); + + hbox20 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox20); + gtk_box_pack_start (GTK_BOX (vbox8), hbox20, TRUE, TRUE, 0); + + alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment1); + gtk_box_pack_start (GTK_BOX (hbox20), alignment1, TRUE, TRUE, 0); + + vbox27 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox27); + gtk_container_add (GTK_CONTAINER (alignment1), vbox27); + + alignment3 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment3); + gtk_box_pack_start (GTK_BOX (vbox27), alignment3, TRUE, TRUE, 0); + + frame8 = gtk_frame_new (NULL); + gtk_widget_show (frame8); + gtk_container_add (GTK_CONTAINER (alignment3), frame8); + + alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment2); + gtk_container_add (GTK_CONTAINER (frame8), alignment2); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 0, 0, 12, 0); + + vbox28 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox28); + gtk_container_add (GTK_CONTAINER (alignment2), vbox28); + + GtkLabel_CpuVendor = gtk_label_new (_("CPU vendor")); + gtk_widget_show (GtkLabel_CpuVendor); + gtk_box_pack_start (GTK_BOX (vbox28), GtkLabel_CpuVendor, FALSE, FALSE, 0); + + GtkLabel_Family = gtk_label_new (_("Family")); + gtk_widget_show (GtkLabel_Family); + gtk_box_pack_start (GTK_BOX (vbox28), GtkLabel_Family, FALSE, FALSE, 0); + + GtkLabel_CpuSpeed = gtk_label_new (_("Cpu Speed")); + gtk_widget_show (GtkLabel_CpuSpeed); + gtk_box_pack_start (GTK_BOX (vbox28), GtkLabel_CpuSpeed, FALSE, FALSE, 0); + + GtkLabel_Features = gtk_label_new (_("Features")); + gtk_widget_show (GtkLabel_Features); + gtk_box_pack_start (GTK_BOX (vbox28), GtkLabel_Features, FALSE, FALSE, 0); + + label35 = gtk_label_new (""); + gtk_widget_show (label35); + gtk_frame_set_label_widget (GTK_FRAME (frame8), label35); + gtk_label_set_use_markup (GTK_LABEL (label35), TRUE); + + GtkCheckButton_EERec = gtk_check_button_new_with_mnemonic (_("EERec - EE/IOP recompiler")); + gtk_widget_show (GtkCheckButton_EERec); + gtk_box_pack_start (GTK_BOX (vbox8), GtkCheckButton_EERec, FALSE, FALSE, 0); + + frame6 = gtk_frame_new (NULL); + gtk_widget_show (frame6); + gtk_box_pack_start (GTK_BOX (vbox8), frame6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame6), 5); + + vbox26 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox26); + gtk_container_add (GTK_CONTAINER (frame6), vbox26); + gtk_container_set_border_width (GTK_CONTAINER (vbox26), 5); + + GtkCheckButton_VU0rec = gtk_check_button_new_with_mnemonic (_("VU0rec - enable recompiler for VU0 unit")); + gtk_widget_show (GtkCheckButton_VU0rec); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_VU0rec, FALSE, FALSE, 0); + + GtkCheckButton_VU1rec = gtk_check_button_new_with_mnemonic (_("VU1rec - enable recompiler for VU1 unit")); + gtk_widget_show (GtkCheckButton_VU1rec); + gtk_box_pack_start (GTK_BOX (vbox26), GtkCheckButton_VU1rec, FALSE, FALSE, 0); + + label32 = gtk_label_new (_("VU Recompilers - All options are set by default")); + gtk_widget_show (label32); + gtk_frame_set_label_widget (GTK_FRAME (frame6), label32); + + GtkCheckButton_MTGS = gtk_check_button_new_with_mnemonic (_("Multi threaded GS mode (MTGS)\n (faster on dual core/HT CPUs, requires pcsx2 restart)")); + gtk_widget_show (GtkCheckButton_MTGS); + gtk_box_pack_start (GTK_BOX (vbox8), GtkCheckButton_MTGS, FALSE, FALSE, 0); + + GtkCheckButton_CpuDC = gtk_check_button_new_with_mnemonic (_("Dual Core Mode (DC) - Much faster, but only valid with MTGS")); + gtk_widget_show (GtkCheckButton_CpuDC); + gtk_box_pack_start (GTK_BOX (vbox8), GtkCheckButton_CpuDC, FALSE, FALSE, 0); + + frame9 = gtk_frame_new (NULL); + gtk_widget_show (frame9); + gtk_box_pack_start (GTK_BOX (vbox8), frame9, TRUE, TRUE, 0); + + alignment4 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment4); + gtk_container_add (GTK_CONTAINER (frame9), alignment4); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment4), 0, 0, 12, 0); + + vbox29 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox29); + gtk_container_add (GTK_CONTAINER (alignment4), vbox29); + + GtkRadioButton_LimitNormal = gtk_radio_button_new_with_mnemonic (NULL, _("Normal - All frames are rendered as fast as possible")); + gtk_widget_show (GtkRadioButton_LimitNormal); + gtk_box_pack_start (GTK_BOX (vbox29), GtkRadioButton_LimitNormal, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitNormal), GtkRadioButton_LimitNormal_group); + GtkRadioButton_LimitNormal_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitNormal)); + + GtkRadioButton_LimitLimit = gtk_radio_button_new_with_mnemonic (NULL, _("Limit - Force frames to normal speeds if too fast")); + gtk_widget_show (GtkRadioButton_LimitLimit); + gtk_box_pack_start (GTK_BOX (vbox29), GtkRadioButton_LimitLimit, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitLimit), GtkRadioButton_LimitNormal_group); + GtkRadioButton_LimitNormal_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitLimit)); + + GtkRadioButton_LimitFS = gtk_radio_button_new_with_mnemonic (NULL, _("Frame Skip - In order to achieve normal speeds, \n some frames are skipped (faster).\n Fps displayed counts skipped frames too")); + gtk_widget_show (GtkRadioButton_LimitFS); + gtk_box_pack_start (GTK_BOX (vbox29), GtkRadioButton_LimitFS, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitFS), GtkRadioButton_LimitNormal_group); + GtkRadioButton_LimitNormal_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_LimitFS)); + + GtkRadioButton_VUSkip = gtk_radio_button_new_with_mnemonic (NULL, _("VU Skip - Same as Frame Skip, but tried to skip more. \n Artifacts might be present, but will be faster")); + gtk_widget_show (GtkRadioButton_VUSkip); + gtk_box_pack_start (GTK_BOX (vbox29), GtkRadioButton_VUSkip, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_VUSkip), GtkRadioButton_LimitNormal_group); + GtkRadioButton_LimitNormal_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_VUSkip)); + + label41 = gtk_label_new (_("Frame Limiting")); + gtk_widget_show (label41); + gtk_frame_set_label_widget (GTK_FRAME (frame9), label41); + gtk_label_set_use_markup (GTK_LABEL (label41), TRUE); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox8), hbuttonbox3, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox3), 30); + + GtkButton_Ok = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) GtkButton_Ok, "clicked", + G_CALLBACK (OnCpu_Ok), + NULL); + g_signal_connect ((gpointer) GtkButton_Cancel, "clicked", + G_CALLBACK (OnCpu_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (CpuDlg, CpuDlg, "CpuDlg"); + GLADE_HOOKUP_OBJECT (CpuDlg, vbox8, "vbox8"); + GLADE_HOOKUP_OBJECT (CpuDlg, hbox20, "hbox20"); + GLADE_HOOKUP_OBJECT (CpuDlg, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (CpuDlg, vbox27, "vbox27"); + GLADE_HOOKUP_OBJECT (CpuDlg, alignment3, "alignment3"); + GLADE_HOOKUP_OBJECT (CpuDlg, frame8, "frame8"); + GLADE_HOOKUP_OBJECT (CpuDlg, alignment2, "alignment2"); + GLADE_HOOKUP_OBJECT (CpuDlg, vbox28, "vbox28"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkLabel_CpuVendor, "GtkLabel_CpuVendor"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkLabel_Family, "GtkLabel_Family"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkLabel_CpuSpeed, "GtkLabel_CpuSpeed"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkLabel_Features, "GtkLabel_Features"); + GLADE_HOOKUP_OBJECT (CpuDlg, label35, "label35"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkCheckButton_EERec, "GtkCheckButton_EERec"); + GLADE_HOOKUP_OBJECT (CpuDlg, frame6, "frame6"); + GLADE_HOOKUP_OBJECT (CpuDlg, vbox26, "vbox26"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkCheckButton_VU0rec, "GtkCheckButton_VU0rec"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkCheckButton_VU1rec, "GtkCheckButton_VU1rec"); + GLADE_HOOKUP_OBJECT (CpuDlg, label32, "label32"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkCheckButton_MTGS, "GtkCheckButton_MTGS"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkCheckButton_CpuDC, "GtkCheckButton_CpuDC"); + GLADE_HOOKUP_OBJECT (CpuDlg, frame9, "frame9"); + GLADE_HOOKUP_OBJECT (CpuDlg, alignment4, "alignment4"); + GLADE_HOOKUP_OBJECT (CpuDlg, vbox29, "vbox29"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkRadioButton_LimitNormal, "GtkRadioButton_LimitNormal"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkRadioButton_LimitLimit, "GtkRadioButton_LimitLimit"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkRadioButton_LimitFS, "GtkRadioButton_LimitFS"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkRadioButton_VUSkip, "GtkRadioButton_VUSkip"); + GLADE_HOOKUP_OBJECT (CpuDlg, label41, "label41"); + GLADE_HOOKUP_OBJECT (CpuDlg, hbuttonbox3, "hbuttonbox3"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkButton_Ok, "GtkButton_Ok"); + GLADE_HOOKUP_OBJECT (CpuDlg, GtkButton_Cancel, "GtkButton_Cancel"); + + return CpuDlg; +} + +GtkWidget* +create_DebugWnd (void) +{ + GtkWidget *DebugWnd; + GtkWidget *vbox16; + GtkWidget *hbox16; + GtkWidget *GtkRadioButton_EE; + GSList *GtkRadioButton_EE_group = NULL; + GtkWidget *GtkRadioButton_IOP; + GtkWidget *hbox6; + GtkWidget *hbox7; + GtkWidget *scrolledwindow1; + GtkWidget *viewport1; + GtkWidget *GtkList_DisView; + GtkWidget *GtkVScrollbar_VList; + GtkWidget *vbox22; + GtkWidget *vbuttonbox2; + GtkWidget *button52; + GtkWidget *button53; + GtkWidget *button65; + GtkWidget *button64; + GtkWidget *vbuttonbox3; + GtkWidget *button58; + GtkWidget *button59; + GtkWidget *button60; + GtkWidget *button61; + GtkWidget *vbuttonbox1; + GtkWidget *button39; + GtkWidget *button40; + GtkWidget *button41; + GtkWidget *vbuttonbox4; + GtkWidget *button68; + GtkWidget *button69; + GtkWidget *button70; + + DebugWnd = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (DebugWnd), 5); + gtk_window_set_title (GTK_WINDOW (DebugWnd), _("PCSX2 Debugger")); + + vbox16 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox16); + gtk_container_add (GTK_CONTAINER (DebugWnd), vbox16); + gtk_container_set_border_width (GTK_CONTAINER (vbox16), 5); + + hbox16 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox16); + gtk_box_pack_start (GTK_BOX (vbox16), hbox16, TRUE, TRUE, 0); + + GtkRadioButton_EE = gtk_radio_button_new_with_mnemonic (NULL, _("EE Debug Mode")); + gtk_widget_show (GtkRadioButton_EE); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_EE, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_EE), GtkRadioButton_EE_group); + GtkRadioButton_EE_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_EE)); + + GtkRadioButton_IOP = gtk_radio_button_new_with_mnemonic (NULL, _("IOP Debug Mode")); + gtk_widget_show (GtkRadioButton_IOP); + gtk_box_pack_start (GTK_BOX (hbox16), GtkRadioButton_IOP, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (GtkRadioButton_IOP), GtkRadioButton_EE_group); + GtkRadioButton_EE_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (GtkRadioButton_IOP)); + + hbox6 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox16), hbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox6), 5); + + hbox7 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox7); + gtk_box_pack_start (GTK_BOX (hbox6), hbox7, TRUE, TRUE, 0); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow1); + gtk_box_pack_start (GTK_BOX (hbox7), scrolledwindow1, TRUE, TRUE, 0); + GTK_WIDGET_UNSET_FLAGS (scrolledwindow1, GTK_CAN_FOCUS); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER); + + viewport1 = gtk_viewport_new (NULL, NULL); + gtk_widget_show (viewport1); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); + + GtkList_DisView = gtk_tree_view_new (); + gtk_widget_show (GtkList_DisView); + gtk_container_add (GTK_CONTAINER (viewport1), GtkList_DisView); + GTK_WIDGET_UNSET_FLAGS (GtkList_DisView, GTK_CAN_FOCUS); + + GtkVScrollbar_VList = gtk_vscrollbar_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 412, 1, 20, 2))); + gtk_widget_show (GtkVScrollbar_VList); + gtk_box_pack_start (GTK_BOX (hbox7), GtkVScrollbar_VList, TRUE, TRUE, 0); + + vbox22 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox22); + gtk_box_pack_start (GTK_BOX (hbox6), vbox22, TRUE, TRUE, 0); + + vbuttonbox2 = gtk_vbutton_box_new (); + gtk_widget_show (vbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox2, TRUE, TRUE, 0); + + button52 = gtk_button_new_with_mnemonic (_("Step")); + gtk_widget_show (button52); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button52); + GTK_WIDGET_SET_FLAGS (button52, GTK_CAN_DEFAULT); + + button53 = gtk_button_new_with_mnemonic (_("Skip")); + gtk_widget_show (button53); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button53); + GTK_WIDGET_SET_FLAGS (button53, GTK_CAN_DEFAULT); + + button65 = gtk_button_new_with_mnemonic (_("Go")); + gtk_widget_show (button65); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button65); + GTK_WIDGET_SET_FLAGS (button65, GTK_CAN_DEFAULT); + + button64 = gtk_button_new_with_mnemonic (_("Log On/Off")); + gtk_widget_show (button64); + gtk_container_add (GTK_CONTAINER (vbuttonbox2), button64); + GTK_WIDGET_SET_FLAGS (button64, GTK_CAN_DEFAULT); + + vbuttonbox3 = gtk_vbutton_box_new (); + gtk_widget_show (vbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox3, TRUE, TRUE, 0); + + button58 = gtk_button_new_with_mnemonic (_("Set PC")); + gtk_widget_show (button58); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button58); + GTK_WIDGET_SET_FLAGS (button58, GTK_CAN_DEFAULT); + + button59 = gtk_button_new_with_mnemonic (_("Set BP Addr")); + gtk_widget_show (button59); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button59); + GTK_WIDGET_SET_FLAGS (button59, GTK_CAN_DEFAULT); + + button60 = gtk_button_new_with_mnemonic (_("Set BP Count")); + gtk_widget_show (button60); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button60); + GTK_WIDGET_SET_FLAGS (button60, GTK_CAN_DEFAULT); + + button61 = gtk_button_new_with_mnemonic (_("Clear BPs")); + gtk_widget_show (button61); + gtk_container_add (GTK_CONTAINER (vbuttonbox3), button61); + GTK_WIDGET_SET_FLAGS (button61, GTK_CAN_DEFAULT); + + vbuttonbox1 = gtk_vbutton_box_new (); + gtk_widget_show (vbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox22), vbuttonbox1, TRUE, TRUE, 0); + + button39 = gtk_button_new_with_mnemonic (_("Dump code")); + gtk_widget_show (button39); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button39); + GTK_WIDGET_SET_FLAGS (button39, GTK_CAN_DEFAULT); + + button40 = gtk_button_new_with_mnemonic (_("Raw Dump")); + gtk_widget_show (button40); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button40); + GTK_WIDGET_SET_FLAGS (button40, GTK_CAN_DEFAULT); + + button41 = gtk_button_new_with_mnemonic (_("Close")); + gtk_widget_show (button41); + gtk_container_add (GTK_CONTAINER (vbuttonbox1), button41); + GTK_WIDGET_SET_FLAGS (button41, GTK_CAN_DEFAULT); + + vbuttonbox4 = gtk_vbutton_box_new (); + gtk_widget_show (vbuttonbox4); + gtk_box_pack_start (GTK_BOX (hbox6), vbuttonbox4, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (vbuttonbox4), 10); + + button68 = gtk_button_new_with_mnemonic (_("memWrite32")); + gtk_widget_show (button68); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button68); + GTK_WIDGET_SET_FLAGS (button68, GTK_CAN_DEFAULT); + + button69 = gtk_button_new_with_mnemonic (_("button69")); + gtk_widget_show (button69); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button69); + GTK_WIDGET_SET_FLAGS (button69, GTK_CAN_DEFAULT); + + button70 = gtk_button_new_with_mnemonic (_("button70")); + gtk_widget_show (button70); + gtk_container_add (GTK_CONTAINER (vbuttonbox4), button70); + GTK_WIDGET_SET_FLAGS (button70, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) GtkRadioButton_EE, "toggled", + G_CALLBACK (OnDebug_EEMode), + NULL); + g_signal_connect ((gpointer) GtkRadioButton_IOP, "toggled", + G_CALLBACK (OnDebug_IOPMode), + NULL); + g_signal_connect ((gpointer) button52, "clicked", + G_CALLBACK (OnDebug_Step), + NULL); + g_signal_connect ((gpointer) button53, "clicked", + G_CALLBACK (OnDebug_Skip), + NULL); + g_signal_connect ((gpointer) button65, "clicked", + G_CALLBACK (OnDebug_Go), + NULL); + g_signal_connect ((gpointer) button64, "clicked", + G_CALLBACK (OnDebug_Log), + NULL); + g_signal_connect ((gpointer) button58, "clicked", + G_CALLBACK (OnDebug_SetPC), + NULL); + g_signal_connect ((gpointer) button59, "clicked", + G_CALLBACK (OnDebug_SetBPA), + NULL); + g_signal_connect ((gpointer) button60, "clicked", + G_CALLBACK (OnDebug_SetBPC), + NULL); + g_signal_connect ((gpointer) button61, "clicked", + G_CALLBACK (OnDebug_ClearBPs), + NULL); + g_signal_connect ((gpointer) button39, "clicked", + G_CALLBACK (OnDebug_DumpCode), + NULL); + g_signal_connect ((gpointer) button40, "clicked", + G_CALLBACK (OnDebug_RawDump), + NULL); + g_signal_connect ((gpointer) button41, "clicked", + G_CALLBACK (OnDebug_Close), + NULL); + g_signal_connect ((gpointer) button68, "clicked", + G_CALLBACK (OnDebug_memWrite32), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (DebugWnd, DebugWnd, "DebugWnd"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbox16, "vbox16"); + GLADE_HOOKUP_OBJECT (DebugWnd, hbox16, "hbox16"); + GLADE_HOOKUP_OBJECT (DebugWnd, GtkRadioButton_EE, "GtkRadioButton_EE"); + GLADE_HOOKUP_OBJECT (DebugWnd, GtkRadioButton_IOP, "GtkRadioButton_IOP"); + GLADE_HOOKUP_OBJECT (DebugWnd, hbox6, "hbox6"); + GLADE_HOOKUP_OBJECT (DebugWnd, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (DebugWnd, scrolledwindow1, "scrolledwindow1"); + GLADE_HOOKUP_OBJECT (DebugWnd, viewport1, "viewport1"); + GLADE_HOOKUP_OBJECT (DebugWnd, GtkList_DisView, "GtkList_DisView"); + GLADE_HOOKUP_OBJECT (DebugWnd, GtkVScrollbar_VList, "GtkVScrollbar_VList"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbox22, "vbox22"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbuttonbox2, "vbuttonbox2"); + GLADE_HOOKUP_OBJECT (DebugWnd, button52, "button52"); + GLADE_HOOKUP_OBJECT (DebugWnd, button53, "button53"); + GLADE_HOOKUP_OBJECT (DebugWnd, button65, "button65"); + GLADE_HOOKUP_OBJECT (DebugWnd, button64, "button64"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbuttonbox3, "vbuttonbox3"); + GLADE_HOOKUP_OBJECT (DebugWnd, button58, "button58"); + GLADE_HOOKUP_OBJECT (DebugWnd, button59, "button59"); + GLADE_HOOKUP_OBJECT (DebugWnd, button60, "button60"); + GLADE_HOOKUP_OBJECT (DebugWnd, button61, "button61"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbuttonbox1, "vbuttonbox1"); + GLADE_HOOKUP_OBJECT (DebugWnd, button39, "button39"); + GLADE_HOOKUP_OBJECT (DebugWnd, button40, "button40"); + GLADE_HOOKUP_OBJECT (DebugWnd, button41, "button41"); + GLADE_HOOKUP_OBJECT (DebugWnd, vbuttonbox4, "vbuttonbox4"); + GLADE_HOOKUP_OBJECT (DebugWnd, button68, "button68"); + GLADE_HOOKUP_OBJECT (DebugWnd, button69, "button69"); + GLADE_HOOKUP_OBJECT (DebugWnd, button70, "button70"); + + return DebugWnd; +} + +GtkWidget* +create_SetPCDlg (void) +{ + GtkWidget *SetPCDlg; + GtkWidget *vbox17; + GtkWidget *label9; + GtkWidget *hbox8; + GtkWidget *label10; + GtkWidget *GtkEntry_dPC; + GtkWidget *hbuttonbox14; + GtkWidget *button42; + GtkWidget *button43; + + SetPCDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (SetPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetPCDlg), _("SetPCDlg")); + + vbox17 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox17); + gtk_container_add (GTK_CONTAINER (SetPCDlg), vbox17); + gtk_container_set_border_width (GTK_CONTAINER (vbox17), 5); + + label9 = gtk_label_new (_("Set New PC Address (in Hex):")); + gtk_widget_show (label9); + gtk_box_pack_start (GTK_BOX (vbox17), label9, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label9), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label9), 0.1, 0.5); + + hbox8 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox8); + gtk_box_pack_start (GTK_BOX (vbox17), hbox8, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox8), 5); + + label10 = gtk_label_new (_("0x")); + gtk_widget_show (label10); + gtk_box_pack_start (GTK_BOX (hbox8), label10, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label10), GTK_JUSTIFY_CENTER); + + GtkEntry_dPC = gtk_entry_new (); + gtk_widget_show (GtkEntry_dPC); + gtk_box_pack_start (GTK_BOX (hbox8), GtkEntry_dPC, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_dPC), 8226); + + hbuttonbox14 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox14); + gtk_box_pack_start (GTK_BOX (vbox17), hbuttonbox14, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox14), 30); + + button42 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button42); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button42); + GTK_WIDGET_SET_FLAGS (button42, GTK_CAN_DEFAULT); + + button43 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button43); + gtk_container_add (GTK_CONTAINER (hbuttonbox14), button43); + GTK_WIDGET_SET_FLAGS (button43, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button42, "clicked", + G_CALLBACK (OnSetPC_Ok), + NULL); + g_signal_connect ((gpointer) button43, "clicked", + G_CALLBACK (OnSetPC_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (SetPCDlg, SetPCDlg, "SetPCDlg"); + GLADE_HOOKUP_OBJECT (SetPCDlg, vbox17, "vbox17"); + GLADE_HOOKUP_OBJECT (SetPCDlg, label9, "label9"); + GLADE_HOOKUP_OBJECT (SetPCDlg, hbox8, "hbox8"); + GLADE_HOOKUP_OBJECT (SetPCDlg, label10, "label10"); + GLADE_HOOKUP_OBJECT (SetPCDlg, GtkEntry_dPC, "GtkEntry_dPC"); + GLADE_HOOKUP_OBJECT (SetPCDlg, hbuttonbox14, "hbuttonbox14"); + GLADE_HOOKUP_OBJECT (SetPCDlg, button42, "button42"); + GLADE_HOOKUP_OBJECT (SetPCDlg, button43, "button43"); + + return SetPCDlg; +} + +GtkWidget* +create_SetBPADlg (void) +{ + GtkWidget *SetBPADlg; + GtkWidget *vbox18; + GtkWidget *label11; + GtkWidget *hbox9; + GtkWidget *label12; + GtkWidget *GtkEntry_BPA; + GtkWidget *hbuttonbox15; + GtkWidget *button44; + GtkWidget *button45; + + SetBPADlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (SetBPADlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPADlg), _("SetBreakPoint Addr")); + + vbox18 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox18); + gtk_container_add (GTK_CONTAINER (SetBPADlg), vbox18); + gtk_container_set_border_width (GTK_CONTAINER (vbox18), 5); + + label11 = gtk_label_new (_("Set New BP Address (in Hex):")); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox18), label11, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label11), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label11), 0.1, 0.5); + + hbox9 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox9); + gtk_box_pack_start (GTK_BOX (vbox18), hbox9, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox9), 5); + + label12 = gtk_label_new (_("0x")); + gtk_widget_show (label12); + gtk_box_pack_start (GTK_BOX (hbox9), label12, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label12), GTK_JUSTIFY_CENTER); + + GtkEntry_BPA = gtk_entry_new (); + gtk_widget_show (GtkEntry_BPA); + gtk_box_pack_start (GTK_BOX (hbox9), GtkEntry_BPA, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_BPA), 8226); + + hbuttonbox15 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox15); + gtk_box_pack_start (GTK_BOX (vbox18), hbuttonbox15, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox15), 30); + + button44 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button44); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button44); + GTK_WIDGET_SET_FLAGS (button44, GTK_CAN_DEFAULT); + + button45 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button45); + gtk_container_add (GTK_CONTAINER (hbuttonbox15), button45); + GTK_WIDGET_SET_FLAGS (button45, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button44, "clicked", + G_CALLBACK (OnSetBPA_Ok), + NULL); + g_signal_connect ((gpointer) button45, "clicked", + G_CALLBACK (OnSetBPA_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (SetBPADlg, SetBPADlg, "SetBPADlg"); + GLADE_HOOKUP_OBJECT (SetBPADlg, vbox18, "vbox18"); + GLADE_HOOKUP_OBJECT (SetBPADlg, label11, "label11"); + GLADE_HOOKUP_OBJECT (SetBPADlg, hbox9, "hbox9"); + GLADE_HOOKUP_OBJECT (SetBPADlg, label12, "label12"); + GLADE_HOOKUP_OBJECT (SetBPADlg, GtkEntry_BPA, "GtkEntry_BPA"); + GLADE_HOOKUP_OBJECT (SetBPADlg, hbuttonbox15, "hbuttonbox15"); + GLADE_HOOKUP_OBJECT (SetBPADlg, button44, "button44"); + GLADE_HOOKUP_OBJECT (SetBPADlg, button45, "button45"); + + return SetBPADlg; +} + +GtkWidget* +create_SetBPCDlg (void) +{ + GtkWidget *SetBPCDlg; + GtkWidget *vbox19; + GtkWidget *label13; + GtkWidget *hbox10; + GtkWidget *label14; + GtkWidget *GtkEntry_BPC; + GtkWidget *hbuttonbox16; + GtkWidget *button46; + GtkWidget *button47; + + SetBPCDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (SetBPCDlg), 5); + gtk_window_set_title (GTK_WINDOW (SetBPCDlg), _("SetBreakPoint Addr")); + + vbox19 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox19); + gtk_container_add (GTK_CONTAINER (SetBPCDlg), vbox19); + gtk_container_set_border_width (GTK_CONTAINER (vbox19), 5); + + label13 = gtk_label_new (_("Set New BP Count (in Hex):")); + gtk_widget_show (label13); + gtk_box_pack_start (GTK_BOX (vbox19), label13, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label13), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label13), 0.1, 0.5); + + hbox10 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox10); + gtk_box_pack_start (GTK_BOX (vbox19), hbox10, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox10), 5); + + label14 = gtk_label_new (_("0x")); + gtk_widget_show (label14); + gtk_box_pack_start (GTK_BOX (hbox10), label14, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label14), GTK_JUSTIFY_CENTER); + + GtkEntry_BPC = gtk_entry_new (); + gtk_widget_show (GtkEntry_BPC); + gtk_box_pack_start (GTK_BOX (hbox10), GtkEntry_BPC, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_BPC), 8226); + + hbuttonbox16 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox16); + gtk_box_pack_start (GTK_BOX (vbox19), hbuttonbox16, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox16), 30); + + button46 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button46); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button46); + GTK_WIDGET_SET_FLAGS (button46, GTK_CAN_DEFAULT); + + button47 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button47); + gtk_container_add (GTK_CONTAINER (hbuttonbox16), button47); + GTK_WIDGET_SET_FLAGS (button47, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button46, "clicked", + G_CALLBACK (OnSetBPC_Ok), + NULL); + g_signal_connect ((gpointer) button47, "clicked", + G_CALLBACK (OnSetBPC_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (SetBPCDlg, SetBPCDlg, "SetBPCDlg"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, vbox19, "vbox19"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, label13, "label13"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, hbox10, "hbox10"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, label14, "label14"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, GtkEntry_BPC, "GtkEntry_BPC"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, hbuttonbox16, "hbuttonbox16"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, button46, "button46"); + GLADE_HOOKUP_OBJECT (SetBPCDlg, button47, "button47"); + + return SetBPCDlg; +} + +GtkWidget* +create_DumpCDlg (void) +{ + GtkWidget *DumpCDlg; + GtkWidget *vbox20; + GtkWidget *label15; + GtkWidget *hbox11; + GtkWidget *label16; + GtkWidget *GtkEntry_DumpCF; + GtkWidget *hbox12; + GtkWidget *label17; + GtkWidget *GtkEntry_DumpCT; + GtkWidget *label21; + GtkWidget *hbuttonbox17; + GtkWidget *button48; + GtkWidget *button49; + + DumpCDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (DumpCDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpCDlg), _("Dump code")); + + vbox20 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox20); + gtk_container_add (GTK_CONTAINER (DumpCDlg), vbox20); + gtk_container_set_border_width (GTK_CONTAINER (vbox20), 5); + + label15 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_show (label15); + gtk_box_pack_start (GTK_BOX (vbox20), label15, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label15), 0.1, 0.5); + + hbox11 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox11); + gtk_box_pack_start (GTK_BOX (vbox20), hbox11, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox11), 5); + + label16 = gtk_label_new (_("From 0x")); + gtk_widget_show (label16); + gtk_box_pack_start (GTK_BOX (hbox11), label16, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label16), GTK_JUSTIFY_CENTER); + gtk_label_set_line_wrap (GTK_LABEL (label16), TRUE); + + GtkEntry_DumpCF = gtk_entry_new (); + gtk_widget_show (GtkEntry_DumpCF); + gtk_box_pack_start (GTK_BOX (hbox11), GtkEntry_DumpCF, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_DumpCF), 8226); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox12); + gtk_box_pack_start (GTK_BOX (vbox20), hbox12, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox12), 5); + + label17 = gtk_label_new (_("To 0x")); + gtk_widget_show (label17); + gtk_box_pack_start (GTK_BOX (hbox12), label17, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label17), GTK_JUSTIFY_CENTER); + + GtkEntry_DumpCT = gtk_entry_new (); + gtk_widget_show (GtkEntry_DumpCT); + gtk_box_pack_start (GTK_BOX (hbox12), GtkEntry_DumpCT, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_DumpCT), 8226); + + label21 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_show (label21); + gtk_box_pack_start (GTK_BOX (vbox20), label21, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label21), 0.1, 0.5); + + hbuttonbox17 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox17); + gtk_box_pack_start (GTK_BOX (vbox20), hbuttonbox17, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox17), 30); + + button48 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button48); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button48); + GTK_WIDGET_SET_FLAGS (button48, GTK_CAN_DEFAULT); + + button49 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button49); + gtk_container_add (GTK_CONTAINER (hbuttonbox17), button49); + GTK_WIDGET_SET_FLAGS (button49, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button48, "clicked", + G_CALLBACK (OnDumpC_Ok), + NULL); + g_signal_connect ((gpointer) button49, "clicked", + G_CALLBACK (OnDumpC_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (DumpCDlg, DumpCDlg, "DumpCDlg"); + GLADE_HOOKUP_OBJECT (DumpCDlg, vbox20, "vbox20"); + GLADE_HOOKUP_OBJECT (DumpCDlg, label15, "label15"); + GLADE_HOOKUP_OBJECT (DumpCDlg, hbox11, "hbox11"); + GLADE_HOOKUP_OBJECT (DumpCDlg, label16, "label16"); + GLADE_HOOKUP_OBJECT (DumpCDlg, GtkEntry_DumpCF, "GtkEntry_DumpCF"); + GLADE_HOOKUP_OBJECT (DumpCDlg, hbox12, "hbox12"); + GLADE_HOOKUP_OBJECT (DumpCDlg, label17, "label17"); + GLADE_HOOKUP_OBJECT (DumpCDlg, GtkEntry_DumpCT, "GtkEntry_DumpCT"); + GLADE_HOOKUP_OBJECT (DumpCDlg, label21, "label21"); + GLADE_HOOKUP_OBJECT (DumpCDlg, hbuttonbox17, "hbuttonbox17"); + GLADE_HOOKUP_OBJECT (DumpCDlg, button48, "button48"); + GLADE_HOOKUP_OBJECT (DumpCDlg, button49, "button49"); + + return DumpCDlg; +} + +GtkWidget* +create_DumpRDlg (void) +{ + GtkWidget *DumpRDlg; + GtkWidget *vbox21; + GtkWidget *label18; + GtkWidget *hbox13; + GtkWidget *label19; + GtkWidget *GtkEntry_DumpRF; + GtkWidget *hbox14; + GtkWidget *label20; + GtkWidget *GtkEntry_DumpRT; + GtkWidget *label22; + GtkWidget *hbuttonbox18; + GtkWidget *button50; + GtkWidget *button51; + + DumpRDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (DumpRDlg), 5); + gtk_window_set_title (GTK_WINDOW (DumpRDlg), _("Raw Dump")); + + vbox21 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox21); + gtk_container_add (GTK_CONTAINER (DumpRDlg), vbox21); + gtk_container_set_border_width (GTK_CONTAINER (vbox21), 5); + + label18 = gtk_label_new (_("Set Dump Addr (in Hex):")); + gtk_widget_show (label18); + gtk_box_pack_start (GTK_BOX (vbox21), label18, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label18), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label18), 0.1, 0.5); + + hbox13 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox13); + gtk_box_pack_start (GTK_BOX (vbox21), hbox13, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox13), 5); + + label19 = gtk_label_new (_("From 0x")); + gtk_widget_show (label19); + gtk_box_pack_start (GTK_BOX (hbox13), label19, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label19), GTK_JUSTIFY_CENTER); + gtk_label_set_line_wrap (GTK_LABEL (label19), TRUE); + + GtkEntry_DumpRF = gtk_entry_new (); + gtk_widget_show (GtkEntry_DumpRF); + gtk_box_pack_start (GTK_BOX (hbox13), GtkEntry_DumpRF, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_DumpRF), 8226); + + hbox14 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox14); + gtk_box_pack_start (GTK_BOX (vbox21), hbox14, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox14), 5); + + label20 = gtk_label_new (_("To 0x")); + gtk_widget_show (label20); + gtk_box_pack_start (GTK_BOX (hbox14), label20, FALSE, FALSE, 0); + + GtkEntry_DumpRT = gtk_entry_new (); + gtk_widget_show (GtkEntry_DumpRT); + gtk_box_pack_start (GTK_BOX (hbox14), GtkEntry_DumpRT, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_DumpRT), 8226); + + label22 = gtk_label_new (_("Dump File = \"dump.txt\"")); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (vbox21), label22, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label22), 0.1, 0.5); + + hbuttonbox18 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox18); + gtk_box_pack_start (GTK_BOX (vbox21), hbuttonbox18, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox18), 30); + + button50 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button50); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button50); + GTK_WIDGET_SET_FLAGS (button50, GTK_CAN_DEFAULT); + + button51 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button51); + gtk_container_add (GTK_CONTAINER (hbuttonbox18), button51); + GTK_WIDGET_SET_FLAGS (button51, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button50, "clicked", + G_CALLBACK (OnDumpR_Ok), + NULL); + g_signal_connect ((gpointer) button51, "clicked", + G_CALLBACK (OnDumpR_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (DumpRDlg, DumpRDlg, "DumpRDlg"); + GLADE_HOOKUP_OBJECT (DumpRDlg, vbox21, "vbox21"); + GLADE_HOOKUP_OBJECT (DumpRDlg, label18, "label18"); + GLADE_HOOKUP_OBJECT (DumpRDlg, hbox13, "hbox13"); + GLADE_HOOKUP_OBJECT (DumpRDlg, label19, "label19"); + GLADE_HOOKUP_OBJECT (DumpRDlg, GtkEntry_DumpRF, "GtkEntry_DumpRF"); + GLADE_HOOKUP_OBJECT (DumpRDlg, hbox14, "hbox14"); + GLADE_HOOKUP_OBJECT (DumpRDlg, label20, "label20"); + GLADE_HOOKUP_OBJECT (DumpRDlg, GtkEntry_DumpRT, "GtkEntry_DumpRT"); + GLADE_HOOKUP_OBJECT (DumpRDlg, label22, "label22"); + GLADE_HOOKUP_OBJECT (DumpRDlg, hbuttonbox18, "hbuttonbox18"); + GLADE_HOOKUP_OBJECT (DumpRDlg, button50, "button50"); + GLADE_HOOKUP_OBJECT (DumpRDlg, button51, "button51"); + + return DumpRDlg; +} + +GtkWidget* +create_Logging (void) +{ + GtkWidget *Logging; + GtkWidget *vbox23; + GtkWidget *hbox15; + GtkWidget *frame4; + GtkWidget *table3; + GtkWidget *Log0; + GtkWidget *Log1; + GtkWidget *Log2; + GtkWidget *Log3; + GtkWidget *Log4; + GtkWidget *Log5; + GtkWidget *Log6; + GtkWidget *Log7; + GtkWidget *Log8; + GtkWidget *Log9; + GtkWidget *Log10; + GtkWidget *Log11; + GtkWidget *Log12; + GtkWidget *Log13; + GtkWidget *Log15; + GtkWidget *Log14; + GtkWidget *Log16; + GtkWidget *Log31; + GtkWidget *Log; + GtkWidget *Log30; + GtkWidget *label33; + GtkWidget *frame5; + GtkWidget *table4; + GtkWidget *Log27; + GtkWidget *Log26; + GtkWidget *Log25; + GtkWidget *Log24; + GtkWidget *Log23; + GtkWidget *Log22; + GtkWidget *Log21; + GtkWidget *Log20; + GtkWidget *Log28; + GtkWidget *label34; + GtkWidget *hbuttonbox19; + GtkWidget *button66; + GtkWidget *button67; + + Logging = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (Logging), 5); + gtk_window_set_title (GTK_WINDOW (Logging), _("Logging")); + + vbox23 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox23); + gtk_container_add (GTK_CONTAINER (Logging), vbox23); + gtk_container_set_border_width (GTK_CONTAINER (vbox23), 5); + + hbox15 = gtk_hbox_new (FALSE, 5); + gtk_widget_show (hbox15); + gtk_box_pack_start (GTK_BOX (vbox23), hbox15, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox15), 5); + + frame4 = gtk_frame_new (NULL); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (hbox15), frame4, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame4), 5); + + table3 = gtk_table_new (8, 3, FALSE); + gtk_widget_show (table3); + gtk_container_add (GTK_CONTAINER (frame4), table3); + gtk_container_set_border_width (GTK_CONTAINER (table3), 5); + gtk_table_set_row_spacings (GTK_TABLE (table3), 5); + gtk_table_set_col_spacings (GTK_TABLE (table3), 5); + + Log0 = gtk_check_button_new_with_mnemonic (_("Cpu Log")); + gtk_widget_show (Log0); + gtk_table_attach (GTK_TABLE (table3), Log0, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log1 = gtk_check_button_new_with_mnemonic (_("Mem Log")); + gtk_widget_show (Log1); + gtk_table_attach (GTK_TABLE (table3), Log1, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log2 = gtk_check_button_new_with_mnemonic (_("Hw Log")); + gtk_widget_show (Log2); + gtk_table_attach (GTK_TABLE (table3), Log2, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log3 = gtk_check_button_new_with_mnemonic (_("Dma Log")); + gtk_widget_show (Log3); + gtk_table_attach (GTK_TABLE (table3), Log3, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log4 = gtk_check_button_new_with_mnemonic (_("Bios Log")); + gtk_widget_show (Log4); + gtk_table_attach (GTK_TABLE (table3), Log4, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log5 = gtk_check_button_new_with_mnemonic (_("Elf Log")); + gtk_widget_show (Log5); + gtk_table_attach (GTK_TABLE (table3), Log5, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log6 = gtk_check_button_new_with_mnemonic (_("Fpu Log")); + gtk_widget_show (Log6); + gtk_table_attach (GTK_TABLE (table3), Log6, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log7 = gtk_check_button_new_with_mnemonic (_("MMI Log")); + gtk_widget_show (Log7); + gtk_table_attach (GTK_TABLE (table3), Log7, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log8 = gtk_check_button_new_with_mnemonic (_("VU0 Log")); + gtk_widget_show (Log8); + gtk_table_attach (GTK_TABLE (table3), Log8, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log9 = gtk_check_button_new_with_mnemonic (_("Cop0 Log")); + gtk_widget_show (Log9); + gtk_table_attach (GTK_TABLE (table3), Log9, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log10 = gtk_check_button_new_with_mnemonic (_("Vif Log")); + gtk_widget_show (Log10); + gtk_table_attach (GTK_TABLE (table3), Log10, 1, 2, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log11 = gtk_check_button_new_with_mnemonic (_("SPR Log")); + gtk_widget_show (Log11); + gtk_table_attach (GTK_TABLE (table3), Log11, 1, 2, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log12 = gtk_check_button_new_with_mnemonic (_("GIF Log")); + gtk_widget_show (Log12); + gtk_table_attach (GTK_TABLE (table3), Log12, 1, 2, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log13 = gtk_check_button_new_with_mnemonic (_("Sif Log")); + gtk_widget_show (Log13); + gtk_table_attach (GTK_TABLE (table3), Log13, 1, 2, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log15 = gtk_check_button_new_with_mnemonic (_("VU Micro Log")); + gtk_widget_show (Log15); + gtk_table_attach (GTK_TABLE (table3), Log15, 1, 2, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log14 = gtk_check_button_new_with_mnemonic (_("IPU Log")); + gtk_widget_show (Log14); + gtk_table_attach (GTK_TABLE (table3), Log14, 1, 2, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log16 = gtk_check_button_new_with_mnemonic (_("RPC Log")); + gtk_widget_show (Log16); + gtk_table_attach (GTK_TABLE (table3), Log16, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log31 = gtk_check_button_new_with_mnemonic (_("Log to STDOUT")); + gtk_widget_show (Log31); + gtk_table_attach (GTK_TABLE (table3), Log31, 2, 3, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log = gtk_check_button_new_with_mnemonic (_("Log")); + gtk_widget_show (Log); + gtk_table_attach (GTK_TABLE (table3), Log, 2, 3, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log30 = gtk_check_button_new_with_mnemonic (_("SYMs Log")); + gtk_widget_show (Log30); + gtk_table_attach (GTK_TABLE (table3), Log30, 2, 3, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label33 = gtk_label_new (_("EE Logs")); + gtk_widget_show (label33); + gtk_frame_set_label_widget (GTK_FRAME (frame4), label33); + + frame5 = gtk_frame_new (NULL); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (hbox15), frame5, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame5), 5); + + table4 = gtk_table_new (8, 2, FALSE); + gtk_widget_show (table4); + gtk_container_add (GTK_CONTAINER (frame5), table4); + gtk_container_set_border_width (GTK_CONTAINER (table4), 5); + gtk_table_set_row_spacings (GTK_TABLE (table4), 5); + gtk_table_set_col_spacings (GTK_TABLE (table4), 5); + + Log27 = gtk_check_button_new_with_mnemonic (_("Cdr Log")); + gtk_widget_show (Log27); + gtk_table_attach (GTK_TABLE (table4), Log27, 0, 1, 7, 8, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log26 = gtk_check_button_new_with_mnemonic (_("Gte Log")); + gtk_widget_show (Log26); + gtk_table_attach (GTK_TABLE (table4), Log26, 0, 1, 6, 7, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log25 = gtk_check_button_new_with_mnemonic (_("Pad Log")); + gtk_widget_show (Log25); + gtk_table_attach (GTK_TABLE (table4), Log25, 0, 1, 5, 6, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log24 = gtk_check_button_new_with_mnemonic (_("Dma Log")); + gtk_widget_show (Log24); + gtk_table_attach (GTK_TABLE (table4), Log24, 0, 1, 4, 5, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log23 = gtk_check_button_new_with_mnemonic (_("Bios Log")); + gtk_widget_show (Log23); + gtk_table_attach (GTK_TABLE (table4), Log23, 0, 1, 3, 4, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log22 = gtk_check_button_new_with_mnemonic (_("Hw Log")); + gtk_widget_show (Log22); + gtk_table_attach (GTK_TABLE (table4), Log22, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log21 = gtk_check_button_new_with_mnemonic (_("Mem Log")); + gtk_widget_show (Log21); + gtk_table_attach (GTK_TABLE (table4), Log21, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log20 = gtk_check_button_new_with_mnemonic (_("IOP Log")); + gtk_widget_show (Log20); + gtk_table_attach (GTK_TABLE (table4), Log20, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + Log28 = gtk_check_button_new_with_mnemonic (_("GPU Log")); + gtk_widget_show (Log28); + gtk_table_attach (GTK_TABLE (table4), Log28, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label34 = gtk_label_new (_("IOP Logs")); + gtk_widget_show (label34); + gtk_frame_set_label_widget (GTK_FRAME (frame5), label34); + + hbuttonbox19 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox19); + gtk_box_pack_start (GTK_BOX (vbox23), hbuttonbox19, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox19), 30); + + button66 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button66); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button66); + GTK_WIDGET_SET_FLAGS (button66, GTK_CAN_DEFAULT); + + button67 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button67); + gtk_container_add (GTK_CONTAINER (hbuttonbox19), button67); + GTK_WIDGET_SET_FLAGS (button67, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button66, "clicked", + G_CALLBACK (OnLogging_Ok), + NULL); + g_signal_connect ((gpointer) button67, "clicked", + G_CALLBACK (OnLogging_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (Logging, Logging, "Logging"); + GLADE_HOOKUP_OBJECT (Logging, vbox23, "vbox23"); + GLADE_HOOKUP_OBJECT (Logging, hbox15, "hbox15"); + GLADE_HOOKUP_OBJECT (Logging, frame4, "frame4"); + GLADE_HOOKUP_OBJECT (Logging, table3, "table3"); + GLADE_HOOKUP_OBJECT (Logging, Log0, "Log0"); + GLADE_HOOKUP_OBJECT (Logging, Log1, "Log1"); + GLADE_HOOKUP_OBJECT (Logging, Log2, "Log2"); + GLADE_HOOKUP_OBJECT (Logging, Log3, "Log3"); + GLADE_HOOKUP_OBJECT (Logging, Log4, "Log4"); + GLADE_HOOKUP_OBJECT (Logging, Log5, "Log5"); + GLADE_HOOKUP_OBJECT (Logging, Log6, "Log6"); + GLADE_HOOKUP_OBJECT (Logging, Log7, "Log7"); + GLADE_HOOKUP_OBJECT (Logging, Log8, "Log8"); + GLADE_HOOKUP_OBJECT (Logging, Log9, "Log9"); + GLADE_HOOKUP_OBJECT (Logging, Log10, "Log10"); + GLADE_HOOKUP_OBJECT (Logging, Log11, "Log11"); + GLADE_HOOKUP_OBJECT (Logging, Log12, "Log12"); + GLADE_HOOKUP_OBJECT (Logging, Log13, "Log13"); + GLADE_HOOKUP_OBJECT (Logging, Log15, "Log15"); + GLADE_HOOKUP_OBJECT (Logging, Log14, "Log14"); + GLADE_HOOKUP_OBJECT (Logging, Log16, "Log16"); + GLADE_HOOKUP_OBJECT (Logging, Log31, "Log31"); + GLADE_HOOKUP_OBJECT (Logging, Log, "Log"); + GLADE_HOOKUP_OBJECT (Logging, Log30, "Log30"); + GLADE_HOOKUP_OBJECT (Logging, label33, "label33"); + GLADE_HOOKUP_OBJECT (Logging, frame5, "frame5"); + GLADE_HOOKUP_OBJECT (Logging, table4, "table4"); + GLADE_HOOKUP_OBJECT (Logging, Log27, "Log27"); + GLADE_HOOKUP_OBJECT (Logging, Log26, "Log26"); + GLADE_HOOKUP_OBJECT (Logging, Log25, "Log25"); + GLADE_HOOKUP_OBJECT (Logging, Log24, "Log24"); + GLADE_HOOKUP_OBJECT (Logging, Log23, "Log23"); + GLADE_HOOKUP_OBJECT (Logging, Log22, "Log22"); + GLADE_HOOKUP_OBJECT (Logging, Log21, "Log21"); + GLADE_HOOKUP_OBJECT (Logging, Log20, "Log20"); + GLADE_HOOKUP_OBJECT (Logging, Log28, "Log28"); + GLADE_HOOKUP_OBJECT (Logging, label34, "label34"); + GLADE_HOOKUP_OBJECT (Logging, hbuttonbox19, "hbuttonbox19"); + GLADE_HOOKUP_OBJECT (Logging, button66, "button66"); + GLADE_HOOKUP_OBJECT (Logging, button67, "button67"); + + return Logging; +} + +GtkWidget* +create_CmdLine (void) +{ + GtkWidget *CmdLine; + GtkWidget *vbox24; + GtkWidget *GtkLabel_Text; + GtkWidget *hbox17; + GtkWidget *GtkEntry_dCMDLINE; + GtkWidget *GtkLabel_Note; + GtkWidget *hbuttonbox20; + GtkWidget *GtkButton_Ok; + GtkWidget *GtkButton_Cancel; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + CmdLine = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (CmdLine), 5); + gtk_window_set_title (GTK_WINDOW (CmdLine), _("Program arguments")); + gtk_window_set_modal (GTK_WINDOW (CmdLine), TRUE); + + vbox24 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox24); + gtk_container_add (GTK_CONTAINER (CmdLine), vbox24); + gtk_container_set_border_width (GTK_CONTAINER (vbox24), 5); + + GtkLabel_Text = gtk_label_new (_("Fill in the command line arguments for opened program:")); + gtk_widget_show (GtkLabel_Text); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Text, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Text), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (GtkLabel_Text), 0.1, 0.5); + + hbox17 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox17); + gtk_box_pack_start (GTK_BOX (vbox24), hbox17, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox17), 5); + + GtkEntry_dCMDLINE = gtk_entry_new (); + gtk_widget_show (GtkEntry_dCMDLINE); + gtk_box_pack_start (GTK_BOX (hbox17), GtkEntry_dCMDLINE, TRUE, TRUE, 0); + gtk_tooltips_set_tip (tooltips, GtkEntry_dCMDLINE, _("If you don't know what to write leave it blank"), NULL); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_dCMDLINE), 8226); + + GtkLabel_Note = gtk_label_new (_("Note: this is intented for developers only.")); + gtk_widget_show (GtkLabel_Note); + gtk_box_pack_start (GTK_BOX (vbox24), GtkLabel_Note, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (GtkLabel_Note), GTK_JUSTIFY_CENTER); + + hbuttonbox20 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox20); + gtk_box_pack_start (GTK_BOX (vbox24), hbuttonbox20, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox20), 30); + + GtkButton_Ok = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (GtkButton_Ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Ok); + GTK_WIDGET_SET_FLAGS (GtkButton_Ok, GTK_CAN_DEFAULT); + + GtkButton_Cancel = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (GtkButton_Cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox20), GtkButton_Cancel); + GTK_WIDGET_SET_FLAGS (GtkButton_Cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) GtkButton_Ok, "clicked", + G_CALLBACK (OnArguments_Ok), + NULL); + g_signal_connect ((gpointer) GtkButton_Cancel, "clicked", + G_CALLBACK (OnArguments_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (CmdLine, CmdLine, "CmdLine"); + GLADE_HOOKUP_OBJECT (CmdLine, vbox24, "vbox24"); + GLADE_HOOKUP_OBJECT (CmdLine, GtkLabel_Text, "GtkLabel_Text"); + GLADE_HOOKUP_OBJECT (CmdLine, hbox17, "hbox17"); + GLADE_HOOKUP_OBJECT (CmdLine, GtkEntry_dCMDLINE, "GtkEntry_dCMDLINE"); + GLADE_HOOKUP_OBJECT (CmdLine, GtkLabel_Note, "GtkLabel_Note"); + GLADE_HOOKUP_OBJECT (CmdLine, hbuttonbox20, "hbuttonbox20"); + GLADE_HOOKUP_OBJECT (CmdLine, GtkButton_Ok, "GtkButton_Ok"); + GLADE_HOOKUP_OBJECT (CmdLine, GtkButton_Cancel, "GtkButton_Cancel"); + GLADE_HOOKUP_OBJECT_NO_REF (CmdLine, tooltips, "tooltips"); + + return CmdLine; +} + +GtkWidget* +create_MemWrite32 (void) +{ + GtkWidget *MemWrite32; + GtkWidget *vbox25; + GtkWidget *hbox18; + GtkWidget *label27; + GtkWidget *label25; + GtkWidget *GtkEntry_Mem; + GtkWidget *hbox19; + GtkWidget *label28; + GtkWidget *label26; + GtkWidget *GtkEntry_Data; + GtkWidget *hbuttonbox22; + GtkWidget *button71; + GtkWidget *button72; + + MemWrite32 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (MemWrite32), 5); + gtk_window_set_title (GTK_WINDOW (MemWrite32), _("memWrite32")); + + vbox25 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox25); + gtk_container_add (GTK_CONTAINER (MemWrite32), vbox25); + gtk_container_set_border_width (GTK_CONTAINER (vbox25), 5); + + hbox18 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox18); + gtk_box_pack_start (GTK_BOX (vbox25), hbox18, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + label27 = gtk_label_new (_("Address ")); + gtk_widget_show (label27); + gtk_box_pack_start (GTK_BOX (hbox18), label27, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label27), GTK_JUSTIFY_CENTER); + + label25 = gtk_label_new (_("0x")); + gtk_widget_show (label25); + gtk_box_pack_start (GTK_BOX (hbox18), label25, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label25), GTK_JUSTIFY_CENTER); + + GtkEntry_Mem = gtk_entry_new (); + gtk_widget_show (GtkEntry_Mem); + gtk_box_pack_start (GTK_BOX (hbox18), GtkEntry_Mem, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_Mem), 8226); + + hbox19 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox19); + gtk_box_pack_start (GTK_BOX (vbox25), hbox19, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox19), 5); + + label28 = gtk_label_new (_("Data ")); + gtk_widget_show (label28); + gtk_box_pack_start (GTK_BOX (hbox19), label28, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label28), GTK_JUSTIFY_CENTER); + + label26 = gtk_label_new (_("0x")); + gtk_widget_show (label26); + gtk_box_pack_start (GTK_BOX (hbox19), label26, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label26), GTK_JUSTIFY_CENTER); + + GtkEntry_Data = gtk_entry_new (); + gtk_widget_show (GtkEntry_Data); + gtk_box_pack_start (GTK_BOX (hbox19), GtkEntry_Data, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (GtkEntry_Data), 8226); + + hbuttonbox22 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox22); + gtk_box_pack_start (GTK_BOX (vbox25), hbuttonbox22, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox22), 30); + + button71 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button71); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button71); + GTK_WIDGET_SET_FLAGS (button71, GTK_CAN_DEFAULT); + + button72 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button72); + gtk_container_add (GTK_CONTAINER (hbuttonbox22), button72); + GTK_WIDGET_SET_FLAGS (button72, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button71, "clicked", + G_CALLBACK (OnMemWrite32_Ok), + NULL); + g_signal_connect ((gpointer) button72, "clicked", + G_CALLBACK (OnMemWrite32_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (MemWrite32, MemWrite32, "MemWrite32"); + GLADE_HOOKUP_OBJECT (MemWrite32, vbox25, "vbox25"); + GLADE_HOOKUP_OBJECT (MemWrite32, hbox18, "hbox18"); + GLADE_HOOKUP_OBJECT (MemWrite32, label27, "label27"); + GLADE_HOOKUP_OBJECT (MemWrite32, label25, "label25"); + GLADE_HOOKUP_OBJECT (MemWrite32, GtkEntry_Mem, "GtkEntry_Mem"); + GLADE_HOOKUP_OBJECT (MemWrite32, hbox19, "hbox19"); + GLADE_HOOKUP_OBJECT (MemWrite32, label28, "label28"); + GLADE_HOOKUP_OBJECT (MemWrite32, label26, "label26"); + GLADE_HOOKUP_OBJECT (MemWrite32, GtkEntry_Data, "GtkEntry_Data"); + GLADE_HOOKUP_OBJECT (MemWrite32, hbuttonbox22, "hbuttonbox22"); + GLADE_HOOKUP_OBJECT (MemWrite32, button71, "button71"); + GLADE_HOOKUP_OBJECT (MemWrite32, button72, "button72"); + + return MemWrite32; +} + diff --git a/pcsx2/Linux/interface.h b/pcsx2/Linux/interface.h new file mode 100644 index 0000000..5ddcaf7 --- /dev/null +++ b/pcsx2/Linux/interface.h @@ -0,0 +1,17 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_MainWindow (void); +GtkWidget* create_AboutDlg (void); +GtkWidget* create_ConfDlg (void); +GtkWidget* create_CpuDlg (void); +GtkWidget* create_DebugWnd (void); +GtkWidget* create_SetPCDlg (void); +GtkWidget* create_SetBPADlg (void); +GtkWidget* create_SetBPCDlg (void); +GtkWidget* create_DumpCDlg (void); +GtkWidget* create_DumpRDlg (void); +GtkWidget* create_Logging (void); +GtkWidget* create_CmdLine (void); +GtkWidget* create_MemWrite32 (void); diff --git a/pcsx2/Linux/pcsx2.glade b/pcsx2/Linux/pcsx2.glade new file mode 100644 index 0000000..8832416 --- /dev/null +++ b/pcsx2/Linux/pcsx2.glade @@ -0,0 +1,5235 @@ + + + + + + + True + PCSX + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + + True + False + 0 + + + + True + GTK_PACK_DIRECTION_LTR + GTK_PACK_DIRECTION_LTR + + + + True + _File + True + + + + + + + True + _Run CD + True + + + + + + + True + _Load Elf + True + + + + + + + True + + + + + + True + States + True + + + + + + + True + Load + True + + + + + + + True + Slot 1 + True + + + + + + + True + Slot 2 + True + + + + + + + True + Slot 3 + True + + + + + + + True + Slot 4 + True + + + + + + + True + Slot 5 + True + + + + + + + True + Other... + True + + + + + + + + + + + True + Save + True + + + + + + + True + Slot 1 + True + + + + + + + True + Slot 2 + True + + + + + + + True + Slot 3 + True + + + + + + + True + Slot 4 + True + + + + + + + True + Slot 5 + True + + + + + + + True + Other... + True + + + + + + + + + + + + + + + True + E_xit + True + + + + + + + + + + + True + _Run + True + + + + + + + True + E_xecute + True + + + + + + + True + Re_set + True + + + + + + + True + _Arguments + True + + + + + + + + + + + True + _Config + True + + + + + + + True + _Configure + True + + + + + + + True + + + + + + True + _Graphics + True + + + + + + + True + C_ontrollers + True + + + + + + + True + _Sound + True + + + + + + + True + _Cdvdrom + True + + + + + + + True + D_ev9 + True + + + + + + + True + U_SB + True + + + + + + + True + Fire_Wire + True + + + + + + + True + + + + + + True + C_pu + True + + + + + + + + + + + True + _Language + True + + + + + + True + _Misc + True + + + + + + + True + Patch _Browser + True + + + + + + + True + Patch _Finder + True + + + + + + + True + + + + + + True + Enable _Console + True + False + + + + + + + True + Enable _Patches + True + False + + + + + + + + + + + True + _Debug + True + + + + + + + True + Enter Debugger ... + True + + + + + + + True + Logging + True + + + + + + + + + + + True + _Help + True + + + + + + + True + &About... + True + + + + + + + + + + 0 + False + False + + + + + + True + pcsxAbout.bmp + 0.5 + 0.5 + 0 + 0 + + + 1 + True + True + + + + + + True + False + 0 + + + + + + + 0 + True + True + + + + + + + + 10 + True + Pcsx About + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + PCSX2 + +Version x.x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 0 + + + + True + written by... + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + pcsxAbout.xpm + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + 0 + True + True + + + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 0 + + + + True + greets to... + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 10 + True + Conf + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + 14 + 2 + False + 0 + 15 + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 0 + 1 + 4 + 5 + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 1 + 2 + 4 + 5 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 1 + 2 + 5 + 6 + fill + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + 1 + 5 + 6 + fill + fill + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + 1 + 2 + 3 + fill + + + + + + True + Graphics + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + + True + First Controller + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + + + + + + + + True + Second Controller + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 3 + 4 + + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 0 + 1 + 1 + 2 + + + + + + + True + Sound + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 1 + 2 + 1 + 2 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 0 + 1 + 7 + 8 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + 1 + 8 + 9 + fill + + + + + + True + Dev9 + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 6 + 7 + + + + + + + + True + Cdvdrom + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 6 + 7 + + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 1 + 2 + 7 + 8 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 1 + 2 + 8 + 9 + fill + fill + + + + + + True + Usb + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 9 + 10 + + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 0 + 1 + 10 + 11 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + 1 + 11 + 12 + fill + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 1 + 2 + 13 + 14 + + + + + + + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + + + 1 + 2 + 10 + 11 + + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Configure + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Test + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + About + True + GTK_RELIEF_NORMAL + True + + + + + + 1 + 2 + 11 + 12 + fill + fill + + + + + + True + FireWire + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 9 + 10 + + + + + + + + True + Bios + False + False + GTK_JUSTIFY_CENTER + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 12 + 13 + + + + + + + 0 + True + True + + + + + + True + False + 14 + + + + True + GTK_BUTTONBOX_START + 0 + + + + True + True + True + Select Plugins Dir + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Select Bios Dir + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + False + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + 5 + True + Cpu + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + CPU vendor + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Family + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Cpu Speed + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Features + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + EERec - EE/IOP recompiler + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + False + 0 + + + + True + True + VU0rec - enable recompiler for VU0 unit + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + VU1rec - enable recompiler for VU1 unit + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + + + True + VU Recompilers - All options are set by default + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + True + Multi threaded GS mode (MTGS) + (faster on dual core/HT CPUs, requires pcsx2 restart) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Dual Core Mode (DC) - Much faster, but only valid with MTGS + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + Normal - All frames are rendered as fast as possible + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Limit - Force frames to normal speeds if too fast + True + GTK_RELIEF_NORMAL + True + False + False + True + GtkRadioButton_LimitNormal + + + 0 + False + False + + + + + + True + True + Frame Skip - In order to achieve normal speeds, + some frames are skipped (faster). + Fps displayed counts skipped frames too + True + GTK_RELIEF_NORMAL + True + False + False + True + GtkRadioButton_LimitNormal + + + 0 + False + False + + + + + + True + True + VU Skip - Same as Frame Skip, but tried to skip more. + Artifacts might be present, but will be faster + True + GTK_RELIEF_NORMAL + True + False + False + True + GtkRadioButton_LimitNormal + + + 0 + False + False + + + + + + + + + + True + Frame Limiting + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + PCSX2 Debugger + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 0 + + + + True + False + 5 + + + + True + True + EE Debug Mode + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + True + IOP Debug Mode + True + GTK_RELIEF_NORMAL + True + False + False + True + GtkRadioButton_EE + + + + 0 + False + False + + + + + 0 + True + True + + + + + + 5 + True + False + 0 + + + + True + False + 0 + + + + True + GTK_POLICY_ALWAYS + GTK_POLICY_NEVER + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + True + False + False + True + False + False + False + + + + + + + 0 + True + True + + + + + + True + GTK_UPDATE_CONTINUOUS + False + 0 0 412 1 20 2 + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Step + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Skip + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Go + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Log On/Off + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Set PC + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Set BP Addr + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Set BP Count + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Clear BPs + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Dump code + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Raw Dump + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Close + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 10 + + + + True + True + True + memWrite32 + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + button69 + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + button70 + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + 5 + True + SetPCDlg + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Set New PC Address (in Hex): + False + False + GTK_JUSTIFY_CENTER + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + SetBreakPoint Addr + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Set New BP Address (in Hex): + False + False + GTK_JUSTIFY_CENTER + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + SetBreakPoint Addr + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Set New BP Count (in Hex): + False + False + GTK_JUSTIFY_CENTER + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + Dump code + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Set Dump Addr (in Hex): + False + False + GTK_JUSTIFY_LEFT + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + From 0x + False + False + GTK_JUSTIFY_CENTER + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + To 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + Dump File = "dump.txt" + False + False + GTK_JUSTIFY_LEFT + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + Raw Dump + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Set Dump Addr (in Hex): + False + False + GTK_JUSTIFY_CENTER + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + From 0x + False + False + GTK_JUSTIFY_CENTER + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + To 0x + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + Dump File = "dump.txt" + False + False + GTK_JUSTIFY_LEFT + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + Logging + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + 5 + True + False + 5 + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 8 + 3 + False + 5 + 5 + + + + True + True + Cpu Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + Mem Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + Hw Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + Dma Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + Bios Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + True + Elf Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + True + Fpu Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 6 + 7 + fill + + + + + + + True + True + MMI Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 7 + 8 + fill + + + + + + + True + True + VU0 Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + Cop0 Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + Vif Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + True + SPR Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + True + GIF Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 4 + 5 + fill + + + + + + + True + True + Sif Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 5 + 6 + fill + + + + + + + True + True + VU Micro Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 7 + 8 + fill + + + + + + + True + True + IPU Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 6 + 7 + fill + + + + + + + True + True + RPC Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + Log to STDOUT + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 2 + 3 + 5 + 6 + fill + + + + + + + True + True + Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 2 + 3 + 7 + 8 + fill + + + + + + + True + True + SYMs Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 2 + 3 + 6 + 7 + fill + + + + + + + + + True + EE Logs + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + 8 + 2 + False + 5 + 5 + + + + True + True + Cdr Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 7 + 8 + fill + + + + + + + True + True + Gte Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 6 + 7 + fill + + + + + + + True + True + Pad Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + True + Dma Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + True + Bios Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + Hw Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + Mem Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + IOP Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + GPU Log + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 1 + 2 + 0 + 1 + fill + + + + + + + + + True + IOP Logs + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + Program arguments + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + Fill in the command line arguments for opened program: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.10000000149 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + If you don't know what to write leave it blank + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + Note: this is intented for developers only. + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + memWrite32 + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + 5 + True + False + 2 + + + + True + Address + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + + 5 + True + False + 2 + + + + True + Data + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0x + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + diff --git a/pcsx2/Linux/support.c b/pcsx2/Linux/support.c new file mode 100644 index 0000000..00aff29 --- /dev/null +++ b/pcsx2/Linux/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/pcsx2/Linux/support.h b/pcsx2/Linux/support.h new file mode 100644 index 0000000..a32649e --- /dev/null +++ b/pcsx2/Linux/support.h @@ -0,0 +1,69 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# define Q_(String) g_strip_context ((String), gettext (String)) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define Q_(String) g_strip_context ((String), (String)) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/pcsx2/MMI.c b/pcsx2/MMI.c new file mode 100644 index 0000000..cef1d4a --- /dev/null +++ b/pcsx2/MMI.c @@ -0,0 +1,1475 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "InterTables.h" + + +void MMI() { +#ifdef MMI_LOG + MMI_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); +#endif + Int_MMIPrintTable[_Funct_](); +} + +void MMI0() { + Int_MMI0PrintTable[_Sa_](); +} + +void MMI1() { + Int_MMI1PrintTable[_Sa_](); +} + +void MMI2() { + Int_MMI2PrintTable[_Sa_](); +} + +void MMI3() { + Int_MMI3PrintTable[_Sa_](); +} + +void MMI_Unknown() { + SysPrintf ("Unknown MMI opcode called\n"); +} + +//*****************MMI OPCODES********************************* + +void MADD() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[0] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +void MADDU() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[0] | ((u64)cpuRegs.HI.UL[0] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[0] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[0]; +} + +#define _PLZCW(n) { \ + sign = cpuRegs.GPR.r[_Rs_].UL[n] >> 31; \ + for (i=30; i>=0; i--) { \ + if (((cpuRegs.GPR.r[_Rs_].UL[n] >> i) & 0x1) != sign) { \ + break; \ + } \ + } \ + cpuRegs.GPR.r[_Rd_].UL[n] = 30 - i; \ +} + +void PLZCW() { + int i; + u32 sign; + + if (!_Rd_) return; + + _PLZCW (0); + _PLZCW (1); +} + +void MADD1() { + s64 temp = (s64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]); + + cpuRegs.LO.SD[1] = (s32)(temp & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(temp >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MADDU1() { + u64 tempu = (u64)((u64)cpuRegs.LO.UL[2] | ((u64)cpuRegs.HI.UL[2] << 32)) + + ((u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]); + + cpuRegs.LO.SD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.LO.SD[1]; +} + +void MFHI1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[1]; +} + +void MFLO1() { + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MTHI1() { + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MTLO1() { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; +} + +void MULT1() { + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + + cpuRegs.LO.UD[1] = (s64)(s32)(temp & 0xffffffff); + cpuRegs.HI.UD[1] = (s64)(s32)(temp >> 32); + + /* Modified a bit . asadr */ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void MULTU1() { + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + + cpuRegs.LO.UD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.UD[1] = (s32)(tempu >> 32); + + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; +} + +void DIV1() { + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + cpuRegs.LO.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; + cpuRegs.HI.SD[1] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; + } +} + +void DIVU1() { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + } +} + +#define PMFHL_CLAMP(dst, src) \ + if ((int)src > (int)0x00007fff) dst = 0x7fff; \ + else \ + if ((int)src < (int)0xffff8000) dst = 0x8000; \ + else dst = (u16)src; + +void PMFHL() { + if (!_Rd_) return; + + switch (_Sa_) { + case 0x00: // LW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + break; + + case 0x01: // UW + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[3]; + break; + + case 0x02: // SLW + { + u64 TempU64 = ((u64)cpuRegs.HI.UL[0] << 32) | (u64)cpuRegs.LO.UL[0]; + if (TempU64 >= 0x000000007fffffffLL) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0x000000007fffffffLL; + } else if (TempU64 <= 0xffffffff80000000LL) { + cpuRegs.GPR.r[_Rd_].UD[0] = 0xffffffff80000000LL; + } else { + cpuRegs.GPR.r[_Rd_].UD[0] = (s64)cpuRegs.LO.SL[0]; + } + + TempU64 = ((u64)cpuRegs.HI.UL[2] << 32) | (u64)cpuRegs.LO.UL[2]; + if (TempU64 >= 0x000000007fffffffLL) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0x000000007fffffffLL; + } else if (TempU64 <= 0xffffffff80000000LL) { + cpuRegs.GPR.r[_Rd_].UD[1] = 0xffffffff80000000LL; + } else { + cpuRegs.GPR.r[_Rd_].UD[1] = (s64)cpuRegs.LO.SL[2]; + } + } + break; + + case 0x03: // LH + cpuRegs.GPR.r[_Rd_].US[0] = cpuRegs.LO.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = cpuRegs.LO.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = cpuRegs.HI.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = cpuRegs.HI.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = cpuRegs.LO.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = cpuRegs.LO.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = cpuRegs.HI.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = cpuRegs.HI.US[6]; + break; + + case 0x04: // SH + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[0], cpuRegs.LO.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[1], cpuRegs.LO.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[2], cpuRegs.HI.UL[0]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[3], cpuRegs.HI.UL[1]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[4], cpuRegs.LO.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[5], cpuRegs.LO.UL[3]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[6], cpuRegs.HI.UL[2]); + PMFHL_CLAMP(cpuRegs.GPR.r[_Rd_].US[7], cpuRegs.HI.UL[3]); + break; + } +} + +void PMTHL() { + if (_Sa_ != 0) return; + + cpuRegs.LO.UL[0] = cpuRegs.GPR.r[_Rs_].UL[0]; + cpuRegs.HI.UL[0] = cpuRegs.GPR.r[_Rs_].UL[1]; + cpuRegs.LO.UL[2] = cpuRegs.GPR.r[_Rs_].UL[2]; + cpuRegs.HI.UL[2] = cpuRegs.GPR.r[_Rs_].UL[3]; +} + +#define _PSLLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] << ( _Sa_ & 0xf ); + +void PSLLH() { + if (!_Rd_) return; + + _PSLLH(0); _PSLLH(1); _PSLLH(2); _PSLLH(3); + _PSLLH(4); _PSLLH(5); _PSLLH(6); _PSLLH(7); +} + +#define _PSRLH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].US[n] >> ( _Sa_ & 0xf ); + +void PSRLH () { + if (!_Rd_) return; + + _PSRLH(0); _PSRLH(1); _PSRLH(2); _PSRLH(3); + _PSRLH(4); _PSRLH(5); _PSRLH(6); _PSRLH(7); +} + +#define _PSRAH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rt_].SS[n] >> ( _Sa_ & 0xf ); + +void PSRAH() { + if (!_Rd_) return; + + _PSRAH(0); _PSRAH(1); _PSRAH(2); _PSRAH(3); + _PSRAH(4); _PSRAH(5); _PSRAH(6); _PSRAH(7); +} + +#define _PSLLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] << _Sa_; + +void PSLLW() { + if (!_Rd_) return; + + _PSLLW(0); _PSLLW(1); _PSLLW(2); _PSLLW(3); +} + +#define _PSRLW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].UL[n] >> _Sa_; + +void PSRLW() { + if (!_Rd_) return; + + _PSRLW(0); _PSRLW(1); _PSRLW(2); _PSRLW(3); +} + +#define _PSRAW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rt_].SL[n] >> _Sa_; + +void PSRAW() { + if (!_Rd_) return; + + _PSRAW(0); _PSRAW(1); _PSRAW(2); _PSRAW(3); +} + +//*****************END OF MMI OPCODES************************** +//*************************MMI0 OPCODES************************ + +#define _PADDW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] + cpuRegs.GPR.r[_Rt_].UL[n]; + +void PADDW() { + if (!_Rd_) return; + + _PADDW(0); _PADDW(1); _PADDW(2); _PADDW(3); +} + +#define _PSUBW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = cpuRegs.GPR.r[_Rs_].UL[n] - cpuRegs.GPR.r[_Rt_].UL[n]; + +void PSUBW() { + if (!_Rd_) return; + + _PSUBW(0); _PSUBW(1); _PSUBW(2); _PSUBW(3); +} + +#define _PCGTW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCGTW() { + if (!_Rd_) return; + + _PCGTW(0); _PCGTW(1); _PCGTW(2); _PCGTW(3); +} + +#define _PMAXW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] > cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].UL[n] : cpuRegs.GPR.r[_Rt_].UL[n]; + +void PMAXW() { + if (!_Rd_) return; + + _PMAXW(0); _PMAXW(1); _PMAXW(2); _PMAXW(3); +} + +#define _PADDH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] + cpuRegs.GPR.r[_Rt_].US[n]; + +void PADDH() { + if (!_Rd_) return; + + _PADDH(0); _PADDH(1); _PADDH(2); _PADDH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PSUBH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = cpuRegs.GPR.r[_Rs_].US[n] - cpuRegs.GPR.r[_Rt_].US[n]; + +void PSUBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PSUBH(4); _PSUBH(5); _PSUBH(6); _PSUBH(7); +} + +#define _PCGTH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + 0xFFFF : 0x0000; + +void PCGTH() { + if (!_Rd_) return; + + _PCGTH(0); _PCGTH(1); _PCGTH(2); _PCGTH(3); + _PCGTH(4); _PCGTH(5); _PCGTH(6); _PCGTH(7); +} + +#define _PMAXH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] > cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMAXH() { + if (!_Rd_) return; + + _PMAXH(0); _PMAXH(1); _PMAXH(2); _PMAXH(3); + _PMAXH(4); _PMAXH(5); _PMAXH(6); _PMAXH(7); +} + +#define _PADDB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] + cpuRegs.GPR.r[_Rt_].SC[n]; + +void PADDB() { + if (!_Rd_) return; + + _PADDB(0); _PADDB(1); _PADDB(2); _PADDB(3); + _PADDB(4); _PADDB(5); _PADDB(6); _PADDB(7); + _PADDB(8); _PADDB(9); _PADDB(10); _PADDB(11); + _PADDB(12); _PADDB(13); _PADDB(14); _PADDB(15); +} + +#define _PSUBB(n) \ + cpuRegs.GPR.r[_Rd_].SC[n] = cpuRegs.GPR.r[_Rs_].SC[n] - cpuRegs.GPR.r[_Rt_].SC[n]; + +void PSUBB() { + if (!_Rd_) return; + + _PSUBB(0); _PSUBB(1); _PSUBB(2); _PSUBB(3); + _PSUBB(4); _PSUBB(5); _PSUBB(6); _PSUBB(7); + _PSUBB(8); _PSUBB(9); _PSUBB(10); _PSUBB(11); + _PSUBB(12); _PSUBB(13); _PSUBB(14); _PSUBB(15); +} + +#define _PCGTB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].SC[n] > cpuRegs.GPR.r[_Rt_].SC[n]) ? \ + 0xFF : 0x00; + +void PCGTB() { + if (!_Rd_) return; + + _PCGTB(0); _PCGTB(1); _PCGTB(2); _PCGTB(3); + _PCGTB(4); _PCGTB(5); _PCGTB(6); _PCGTB(7); + _PCGTB(8); _PCGTB(9); _PCGTB(10); _PCGTB(11); + _PCGTB(12); _PCGTB(13); _PCGTB(14); _PCGTB(15); +} + +#define _PADDSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].SL[n] + (s64)cpuRegs.GPR.r[_Rt_].SL[n]; \ + if (sTemp64 > 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000LL) && (sTemp64 >= 0x100000000LL)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000LL; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PADDSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PADDSW(0); _PADDSW(1); _PADDSW(2); _PADDSW(3); +} + +#define _PSUBSW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 >= 0x7FFFFFFF) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x7FFFFFFF; \ + } else \ + if ((sTemp64 < 0x180000000LL) && (sTemp64 >= 0x100000000LL)) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x80000000LL; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (s32)sTemp64; \ + } + +void PSUBSW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBSW(0); _PSUBSW(1); _PSUBSW(2); _PSUBSW(3); +} + +void PEXTLW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[1]; +} + +void PPACW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rs.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[2]; +} + +#define _PADDSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] + (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 > 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_ ].US[n] = (s16)sTemp32; \ + } + +void PADDSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDSH(0); _PADDSH(1); _PADDSH(2); _PADDSH(3); + _PADDSH(4); _PADDSH(5); _PADDSH(6); _PADDSH(7); +} + +#define _PSUBSH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].SS[n] - (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + if (sTemp32 >= 0x7FFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x7FFF; \ + } else \ + if ((sTemp32 < 0x18000) && (sTemp32 >= 0x10000)) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x8000; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (s16)sTemp32; \ + } + +void PSUBSH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBSH(0); _PSUBSH(1); _PSUBSH(2); _PSUBSH(3); + _PSUBSH(4); _PSUBSH(5); _PSUBSH(6); _PSUBSH(7); +} + +void PEXTLH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[1]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[3]; +} + +void PPACH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[4] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[6] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PADDSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] + (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 > 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PADDSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PADDSB(0); _PADDSB(1); _PADDSB(2); _PADDSB(3); + _PADDSB(4); _PADDSB(5); _PADDSB(6); _PADDSB(7); + _PADDSB(8); _PADDSB(9); _PADDSB(10); _PADDSB(11); + _PADDSB(12); _PADDSB(13); _PADDSB(14); _PADDSB(15); +} + +#define _PSUBSB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].SC[n] - (s16)cpuRegs.GPR.r[_Rt_].SC[n]; \ + if (sTemp16 >= 0x7F) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x7F; \ + } else \ + if ((sTemp16 < 0x180) && (sTemp16 >= 0x100)) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x80; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (s8)sTemp16; \ + } + +void PSUBSB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBSB(0); _PSUBSB(1); _PSUBSB(2); _PSUBSB(3); + _PSUBSB(4); _PSUBSB(5); _PSUBSB(6); _PSUBSB(7); + _PSUBSB(8); _PSUBSB(9); _PSUBSB(10); _PSUBSB(11); + _PSUBSB(12); _PSUBSB(13); _PSUBSB(14); _PSUBSB(15); +} + +void PEXTLB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[1]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[1]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[3]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[3]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[5]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[5]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[6]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[7]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[7]; +} + +void PPACB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rt.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rt.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rt.UC[14]; + + cpuRegs.GPR.r[_Rd_].UC[8] = Rs.UC[0]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[2]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rs.UC[4]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[6]; + + cpuRegs.GPR.r[_Rd_].UC[12] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[14]; +} + +#define _PEXT5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x0000001F) << 3) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x000003E0) << 6) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00007C00) << 9) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] & 0x00008000) << 16); + +void PEXT5() { + if (!_Rd_) return; + + _PEXT5(0); _PEXT5(1); _PEXT5(2); _PEXT5(3); +} + +#define _PPAC5(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 3) & 0x0000001F) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 6) & 0x000003E0) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 9) & 0x00007C00) | \ + ((cpuRegs.GPR.r[_Rt_].UL[n] >> 16) & 0x00008000); + +void PPAC5() { + if (!_Rd_) return; + + _PPAC5(0); _PPAC5(1); _PPAC5(2); _PPAC5(3); +} + +//***END OF MMI0 OPCODES****************************************** +//**********MMI1 OPCODES************************************** + +#define _PABSW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = abs(cpuRegs.GPR.r[_Rt_].SL[n]); + +void PABSW() { + if (!_Rd_) return; + + _PABSW(0); _PABSW(1); _PABSW(2); _PABSW(3); +} + +#define _PCEQW(n) \ + cpuRegs.GPR.r[_Rd_].UL[n] = \ + (cpuRegs.GPR.r[_Rs_].UL[n] == cpuRegs.GPR.r[_Rt_].UL[n]) ? \ + 0xFFFFFFFF : 0x00000000; + +void PCEQW() { + if (!_Rd_) return; + + _PCEQW(0); _PCEQW(1); _PCEQW(2); _PCEQW(3); +} + +#define _PMINW(n) \ + cpuRegs.GPR.r[_Rd_].SL[n] = \ + (cpuRegs.GPR.r[_Rs_].SL[n] < cpuRegs.GPR.r[_Rt_].SL[n]) ? \ + cpuRegs.GPR.r[_Rs_].SL[n] : cpuRegs.GPR.r[_Rt_].SL[n]; + +void PMINW() { + if (!_Rd_) return; + + _PMINW(0); _PMINW(1); _PMINW(2); _PMINW(3); +} + +void PADSBH() { + if (!_Rd_) return; + + _PSUBH(0); _PSUBH(1); _PSUBH(2); _PSUBH(3); + _PADDH(4); _PADDH(5); _PADDH(6); _PADDH(7); +} + +#define _PABSH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = abs(cpuRegs.GPR.r[_Rt_].SS[n]); + +void PABSH() { + if (!_Rd_) return; + + _PABSH(0); _PABSH(1); _PABSH(2); _PABSH(3); + _PABSH(4); _PABSH(5); _PABSH(6); _PABSH(7); +} + +#define _PCEQH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].US[n] == cpuRegs.GPR.r[_Rt_].US[n]) ? 0xFFFF : 0x0000; + +void PCEQH() { + if (!_Rd_) return; + + _PCEQH(0); _PCEQH(1); _PCEQH(2); _PCEQH(3); + _PCEQH(4); _PCEQH(5); _PCEQH(6); _PCEQH(7); +} + +#define _PMINH(n) \ + cpuRegs.GPR.r[_Rd_].US[n] = \ + (cpuRegs.GPR.r[_Rs_].SS[n] < cpuRegs.GPR.r[_Rt_].SS[n]) ? \ + cpuRegs.GPR.r[_Rs_].US[n] : cpuRegs.GPR.r[_Rt_].US[n]; + +void PMINH() { + if (!_Rd_) return; + + _PMINH(0); _PMINH(1); _PMINH(2); _PMINH(3); + _PMINH(4); _PMINH(5); _PMINH(6); _PMINH(7); +} + +#define _PCEQB(n) \ + cpuRegs.GPR.r[_Rd_].UC[n] = (cpuRegs.GPR.r[_Rs_].UC[n] == \ + cpuRegs.GPR.r[_Rt_].UC[n]) ? 0xFF : 0x00; + +void PCEQB() { + if (!_Rd_) return; + + _PCEQB(0); _PCEQB(1); _PCEQB(2); _PCEQB(3); + _PCEQB(4); _PCEQB(5); _PCEQB(6); _PCEQB(7); + _PCEQB(8); _PCEQB(9); _PCEQB(10); _PCEQB(11); + _PCEQB(12); _PCEQB(13); _PCEQB(14); _PCEQB(15); +} + +#define _PADDUW(n) \ + tmp = (s64)cpuRegs.GPR.r[_Rs_].UL[n] + (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (tmp > 0xffffffff) \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0xffffffff; \ + else cpuRegs.GPR.r[_Rd_].UL[n] = (u32)tmp; + +void PADDUW () { + s64 tmp; + + if (!_Rd_) return; + + _PADDUW(0); _PADDUW(1); _PADDUW(2); _PADDUW(3); +} + +#define _PSUBUW(n) \ + sTemp64 = (s64)cpuRegs.GPR.r[_Rs_].UL[n] - (s64)cpuRegs.GPR.r[_Rt_].UL[n]; \ + if (sTemp64 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UL[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UL[n] = (u32)sTemp64; \ + } + +void PSUBUW() { + s64 sTemp64; + + if (!_Rd_) return; + + _PSUBUW(0); _PSUBUW(1); _PSUBUW(2); _PSUBUW(3); +} + +void PEXTUW() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rs.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[3]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rs.UL[3]; +} + +#define _PADDUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] + (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 > 0xFFFF) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0xFFFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PADDUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PADDUH(0); _PADDUH(1); _PADDUH(2); _PADDUH(3); + _PADDUH(4); _PADDUH(5); _PADDUH(6); _PADDUH(7); +} + +#define _PSUBUH(n) \ + sTemp32 = (s32)cpuRegs.GPR.r[_Rs_].US[n] - (s32)cpuRegs.GPR.r[_Rt_].US[n]; \ + if (sTemp32 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].US[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].US[n] = (u16)sTemp32; \ + } + +void PSUBUH() { + s32 sTemp32; + + if (!_Rd_) return; + + _PSUBUH(0); _PSUBUH(1); _PSUBUH(2); _PSUBUH(3); + _PSUBUH(4); _PSUBUH(5); _PSUBUH(6); _PSUBUH(7); +} + +void PEXTUH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PADDUB(n) \ + Temp16 = (u16)cpuRegs.GPR.r[_Rs_].UC[n] + (u16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (Temp16 > 0xFF) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0xFF; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)Temp16; \ + } + +void PADDUB() { + u16 Temp16; + + if (!_Rd_) return; + + _PADDUB(0); _PADDUB(1); _PADDUB(2); _PADDUB(3); + _PADDUB(4); _PADDUB(5); _PADDUB(6); _PADDUB(7); + _PADDUB(8); _PADDUB(9); _PADDUB(10); _PADDUB(11); + _PADDUB(12); _PADDUB(13); _PADDUB(14); _PADDUB(15); +} + +#define _PSUBUB(n) \ + sTemp16 = (s16)cpuRegs.GPR.r[_Rs_].UC[n] - (s16)cpuRegs.GPR.r[_Rt_].UC[n]; \ + if (sTemp16 <= 0x0) { \ + cpuRegs.GPR.r[_Rd_].UC[n] = 0x0; \ + } else { \ + cpuRegs.GPR.r[_Rd_].UC[n] = (u8)sTemp16; \ + } + +void PSUBUB() { + s16 sTemp16; + + if (!_Rd_) return; + + _PSUBUB(0); _PSUBUB(1); _PSUBUB(2); _PSUBUB(3); + _PSUBUB(4); _PSUBUB(5); _PSUBUB(6); _PSUBUB(7); + _PSUBUB(8); _PSUBUB(9); _PSUBUB(10); _PSUBUB(11); + _PSUBUB(12); _PSUBUB(13); _PSUBUB(14); _PSUBUB(15); +} + +void PEXTUB() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UC[0] = Rt.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[1] = Rs.UC[8]; + cpuRegs.GPR.r[_Rd_].UC[2] = Rt.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[3] = Rs.UC[9]; + cpuRegs.GPR.r[_Rd_].UC[4] = Rt.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[5] = Rs.UC[10]; + cpuRegs.GPR.r[_Rd_].UC[6] = Rt.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[7] = Rs.UC[11]; + cpuRegs.GPR.r[_Rd_].UC[8] = Rt.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[9] = Rs.UC[12]; + cpuRegs.GPR.r[_Rd_].UC[10] = Rt.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[11] = Rs.UC[13]; + cpuRegs.GPR.r[_Rd_].UC[12] = Rt.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[13] = Rs.UC[14]; + cpuRegs.GPR.r[_Rd_].UC[14] = Rt.UC[15]; + cpuRegs.GPR.r[_Rd_].UC[15] = Rs.UC[15]; +} + +void QFSRV() { // JayteeMaster: changed a bit to avoid screw up + GPR_reg Rd; + if (!_Rd_) return; + + if (cpuRegs.sa == 0) { + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; + } else { + if (cpuRegs.sa < 64) { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> cpuRegs.sa; + Rd.UD[1] = cpuRegs.GPR.r[_Rt_].UD[1] >> cpuRegs.sa; + Rd.UD[0]|= cpuRegs.GPR.r[_Rt_].UD[1] << (64 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[0] << (64 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } else { + /* + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + cpuRegs.GPR.r[_Rd_].UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_].UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + */ + Rd.UD[0] = cpuRegs.GPR.r[_Rt_].UD[1] >> (cpuRegs.sa - 64); + Rd.UD[1] = cpuRegs.GPR.r[_Rs_].UD[0] >> (cpuRegs.sa - 64); + Rd.UD[0]|= cpuRegs.GPR.r[_Rs_].UD[0] << (128 - cpuRegs.sa); + Rd.UD[1]|= cpuRegs.GPR.r[_Rs_].UD[1] << (128 - cpuRegs.sa); + cpuRegs.GPR.r[_Rd_] = Rd; + } + } +} + +//********END OF MMI1 OPCODES*********************************** + +//*********MMI2 OPCODES*************************************** + +#define _PMADDW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) + \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMADDW() { + _PMADDW(0, 0); + _PMADDW(1, 2); +} + +void PSLLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (s32)(cpuRegs.GPR.r[_Rt_].UL[2] << + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PSRLVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].UL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].UL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +#define _PMSUBW(dd, ss) { \ + s64 temp = (s64)((s64)cpuRegs.LO.SL[ss] | ((s64)cpuRegs.HI.SL[ss] << 32)) - \ + ((s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ +} + +void PMSUBW() { + _PMSUBW(0, 0); + _PMSUBW(1, 2); +} + +void PMFHI() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.HI.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.HI.UD[1]; +} + +void PMFLO() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.LO.UD[1]; +} + +void PINTH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[5]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[7]; +} + +#define _PMULTW(dd, ss) { \ + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[ss] * (s64)cpuRegs.GPR.r[_Rt_].SL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(temp & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(temp >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].SD[dd] = temp; \ + } \ +} + +void PMULTW() { + _PMULTW(0, 0); + _PMULTW(1, 2); +} + +#define _PDIVW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] / cpuRegs.GPR.r[_Rt_].SL[ss]; \ + cpuRegs.HI.SD[dd] = cpuRegs.GPR.r[_Rs_].SL[ss] % cpuRegs.GPR.r[_Rt_].SL[ss]; \ + } + +void PDIVW() { + _PDIVW(0, 0); + _PDIVW(1, 2); +} + +void PCPYLD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; +} + +void PMADDH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp; */ + + temp = cpuRegs.LO.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] + (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp; */ + + temp = cpuRegs.HI.UL[1] + (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp; */ + + temp = cpuRegs.LO.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] + (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /* if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp; */ + + temp = cpuRegs.HI.UL[3] + (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } + +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMADH(hlr, dd, n) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] + \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[n] = temp; */\ +} + +void PHMADH() { // JayteeMaster: changed a bit to avoid screw up. Also used 0,2,4,6 instead of 0,1,2,3 + _PHMADH(LO, 0, 0); + _PHMADH(HI, 0, 2); + _PHMADH(LO, 2, 4); + _PHMADH(HI, 2, 6); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PAND() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] & cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PXOR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] ^ cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PMSUBH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = cpuRegs.LO.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = cpuRegs.LO.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = cpuRegs.HI.UL[0] - (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = cpuRegs.HI.UL[1] - (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = cpuRegs.LO.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = cpuRegs.LO.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = cpuRegs.HI.UL[2] - (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = cpuRegs.HI.UL[3] - (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +// JayteeMaster: changed a bit to avoid screw up +#define _PHMSBH(hlr, dd, n, rdd) { \ + s32 temp = (s32)cpuRegs.GPR.r[_Rs_].SS[n+1] * (s32)cpuRegs.GPR.r[_Rt_].SS[n+1] - \ + (s32)cpuRegs.GPR.r[_Rs_].SS[n] * (s32)cpuRegs.GPR.r[_Rt_].SS[n]; \ + \ + cpuRegs.hlr.UL[dd] = temp; \ + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[rdd] = temp;*/ \ +} + +void PHMSBH() { // JayteeMaster: changed a bit to avoid screw up + _PHMSBH(LO, 0, 0, 0); + _PHMSBH(HI, 0, 2, 1); + _PHMSBH(LO, 2, 4, 2); + _PHMSBH(HI, 2, 6, 3); + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +void PEXEH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PREVH () { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[7]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PMULTH() { // JayteeMaster: changed a bit to avoid screw up + s32 temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[0] * (s32)cpuRegs.GPR.r[_Rt_].SS[0]; + cpuRegs.LO.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[0] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[1] * (s32)cpuRegs.GPR.r[_Rt_].SS[1]; + cpuRegs.LO.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[2] * (s32)cpuRegs.GPR.r[_Rt_].SS[2]; + cpuRegs.HI.UL[0] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[1] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[3] * (s32)cpuRegs.GPR.r[_Rt_].SS[3]; + cpuRegs.HI.UL[1] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[4] * (s32)cpuRegs.GPR.r[_Rt_].SS[4]; + cpuRegs.LO.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[2] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[5] * (s32)cpuRegs.GPR.r[_Rt_].SS[5]; + cpuRegs.LO.UL[3] = temp; + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[6] * (s32)cpuRegs.GPR.r[_Rt_].SS[6]; + cpuRegs.HI.UL[2] = temp; + /*if (_Rd_) cpuRegs.GPR.r[_Rd_].UL[3] = temp;*/ + + temp = (s32)cpuRegs.GPR.r[_Rs_].SS[7] * (s32)cpuRegs.GPR.r[_Rt_].SS[7]; + cpuRegs.HI.UL[3] = temp; + + if (_Rd_) { + cpuRegs.GPR.r[_Rd_].UL[0] = cpuRegs.LO.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = cpuRegs.HI.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[2] = cpuRegs.LO.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[3] = cpuRegs.HI.UL[2]; + } +} + +#define _PDIVBW(n) \ + cpuRegs.LO.UL[n] = (s32)(cpuRegs.GPR.r[_Rs_].SL[n] / cpuRegs.GPR.r[_Rt_].SS[0]); \ + cpuRegs.HI.UL[n] = (s16)(cpuRegs.GPR.r[_Rs_].SL[n] % cpuRegs.GPR.r[_Rt_].SS[0]); \ + +void PDIVBW() { + if (cpuRegs.GPR.r[_Rt_].US[0] == 0) return; + + _PDIVBW(0); _PDIVBW(1); _PDIVBW(2); _PDIVBW(3); +} + +void PEXEW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +void PROT3W() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//*****END OF MMI2 OPCODES*********************************** + +//*************************MMI3 OPCODES************************ + +#define _PMADDUW(dd, ss) { \ + u64 tempu = (u64)((u64)cpuRegs.LO.UL[ss] | ((u64)cpuRegs.HI.UL[ss] << 32)) + \ + ((u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]); \ + \ + cpuRegs.LO.SD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.SD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ +} + +void PMADDUW() { + _PMADDUW(0, 0); + _PMADDUW(1, 2); +} + +void PSRAVW() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rt_].SL[0] >> + (cpuRegs.GPR.r[_Rs_].UL[0] & 0x1F)); + cpuRegs.GPR.r[_Rd_].UD[1] = (cpuRegs.GPR.r[_Rt_].SL[2] >> + (cpuRegs.GPR.r[_Rs_].UL[2] & 0x1F)); +} + +void PMTHI() { + cpuRegs.HI.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PMTLO() { + cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; + cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UD[1]; +} + +void PINTEH() { + GPR_reg Rs, Rt; + + if (!_Rd_) return; + + Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rs.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[3] = Rs.US[2]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rs.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[7] = Rs.US[6]; +} + +#define _PMULTUW(dd, ss) { \ + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] * (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + \ + cpuRegs.LO.UD[dd] = (s32)(tempu & 0xffffffff); \ + cpuRegs.HI.UD[dd] = (s32)(tempu >> 32); \ + \ + if (_Rd_) { \ + cpuRegs.GPR.r[_Rd_].UD[dd] = tempu; \ + } \ +} + +void PMULTUW() { + _PMULTUW(0, 0); + _PMULTUW(1, 2); +} + +#define _PDIVUW(dd, ss) \ + if (cpuRegs.GPR.r[_Rt_].UL[ss] != 0) { \ + cpuRegs.LO.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] / (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + cpuRegs.HI.UD[dd] = (u64)cpuRegs.GPR.r[_Rs_].UL[ss] % (u64)cpuRegs.GPR.r[_Rt_].UL[ss]; \ + } + +void PDIVUW() { + _PDIVUW(0, 0); + _PDIVUW(1, 2); +} + +void PCPYUD() { + if (!_Rd_) return; + + // note: first _Rs_, since the other way when _Rd_ equals + // _Rs_ or _Rt_ this would screw up + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[1]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void POR() { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; + cpuRegs.GPR.r[_Rd_].UD[1] = cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void PNOR () { + if (!_Rd_) return; + + cpuRegs.GPR.r[_Rd_].UD[0] = ~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); + cpuRegs.GPR.r[_Rd_].UD[1] = ~(cpuRegs.GPR.r[_Rs_].UD[1] | cpuRegs.GPR.r[_Rt_].UD[1]); +} + +void PEXCH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[2]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[1]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[3]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[6]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[5]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[7]; +} + +void PCPYH() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].US[0] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[1] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[2] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[3] = Rt.US[0]; + cpuRegs.GPR.r[_Rd_].US[4] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[5] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[6] = Rt.US[4]; + cpuRegs.GPR.r[_Rd_].US[7] = Rt.US[4]; +} + +void PEXCW() { + GPR_reg Rt; + + if (!_Rd_) return; + + Rt = cpuRegs.GPR.r[_Rt_]; + cpuRegs.GPR.r[_Rd_].UL[0] = Rt.UL[0]; + cpuRegs.GPR.r[_Rd_].UL[1] = Rt.UL[2]; + cpuRegs.GPR.r[_Rd_].UL[2] = Rt.UL[1]; + cpuRegs.GPR.r[_Rd_].UL[3] = Rt.UL[3]; +} + +//**********************END OF MMI3 OPCODES******************** + +// obs: +// QFSRV not verified + diff --git a/pcsx2/Makefile.am b/pcsx2/Makefile.am new file mode 100644 index 0000000..24cd733 --- /dev/null +++ b/pcsx2/Makefile.am @@ -0,0 +1,29 @@ +AUTOMAKE_OPTIONS = foreign +INCLUDES = -I@srcdir@/x86/ +noinst_LIBRARIES = libpcsx2.a + +libpcsx2_a_SOURCES = \ +CdRom.c Decode_XA.h Mdec.h PsxBios.h R3000A.c Vif.h \ +CdRom.h EEregs.h PsxCommon.h R3000A.h VU0.c \ +CDVD.c Elfheader.c Memory.c PsxCounters.c R5900.c VU0.h \ +CDVD.h Elfheader.h Memory.h PsxCounters.h R5900.h VU0micro.c \ +CDVDiso.c FiFo.c Misc.c PsxDma.c Sif.c VU1micro.c \ +CDVDisodrv.c FPU2.cpp PsxDma.h Sifcmd.h VUflags.c \ +CDVDisodrv.h FPU.c MMI.c Sif.h VUflags.h \ +CDVDiso.h GS.cpp Patch.c Sio.c VU.h \ +CDVDlib.h GS.h Patch.h PsxHw.c Sio.h VUmicro.h \ +Common.h Hw.c Plugins.c PsxHw.h SPR.c VUops.c \ +COP0.c Hw.h Plugins.h PsxInterpreter.c SPR.h VUops.h \ +COP0.h Interpreter.c PS2Edefs.h PsxMem.c System.h \ +Counters.c InterTables.c PS2Etypes.h PsxMem.h Vif.c \ +Counters.h InterTables.h PsxBios2.h PsxSio2.c VifDma.c \ +Decode_XA.c Mdec.c PsxBios.c PsxSio2.h VifDma.h Cache.c \ +xmlpatchloader.cpp + +if RECBUILD +recdir = x86 +else +recdir= +endif + +SUBDIRS = $(recdir) . DebugTools IPU RDebug tinyxml Linux \ No newline at end of file diff --git a/pcsx2/Mdec.c b/pcsx2/Mdec.c new file mode 100644 index 0000000..babc7a9 --- /dev/null +++ b/pcsx2/Mdec.c @@ -0,0 +1,521 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This code was based on the FPSE v0.08 Mdec decoder*/ + +#include +#include + +#include "PsxCommon.h" +#include "Mdec.h" + +#define FIXED + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define FIX_1_082392200 (277) +#define FIX_1_414213562 (362) +#define FIX_1_847759065 (473) +#define FIX_2_613125930 (669) + +#define MULTIPLY(var,const) (DESCALE((var) * (const), CONST_BITS)) + +#define DEQUANTIZE(coef,quantval) (coef) + +#define DESCALE(x,n) ((x)>>(n)) +#define RANGE(n) (n) + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +static void idct1(int *block) +{ + int val = RANGE(DESCALE(block[0], PASS1_BITS+3)); + int i; + for(i=0;i>16)*(bcr&0xffff); + + if (cmd==0x60000000) { + } else + if (cmd==0x40000001) { + u8 *p = (u8*)PSXM(adr); + iqtab_init(iq_y,p); + iqtab_init(iq_uv,p+64); + } else + if ((cmd&0xf5ff0000)==0x30000000) { + mdec.rl = (u16*)PSXM(adr); + } + else { + } + + HW_DMA0_CHCR &= ~0x01000000; + psxDmaInterrupt(0); +} + +void psxDma1(u32 adr, u32 bcr, u32 chcr) { + int blk[DCTSIZE2*6]; + unsigned short *image; + int size; + +#ifdef CDR_LOG + CDR_LOG("DMA1 %lx %lx %lx (cmd = %lx)\n", adr, bcr, chcr, mdec.command); +#endif + + if (chcr!=0x01000200) return; + + size = (bcr>>16)*(bcr&0xffff); + image = (u16*)PSXM(adr); + if (mdec.command&0x08000000) { + for (;size>0;size-=(16*16)/2,image+=(16*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb15(blk,image); + } + } else { + for (;size>0;size-=(24*16)/2,image+=(24*16)) { + mdec.rl = rl2blk(blk,mdec.rl); + yuv2rgb24(blk,(u8 *)image); + } + } + + HW_DMA1_CHCR &= ~0x01000000; + psxDmaInterrupt(1); +} + + +#define RUNOF(a) ((a)>>10) +#define VALOF(a) (((int)(a)<<(32-10))>>(32-10)) + +static int zscan[DCTSIZE2] = { + 0 ,1 ,8 ,16,9 ,2 ,3 ,10, + 17,24,32,25,18,11,4 ,5 , + 12,19,26,33,40,48,41,34, + 27,20,13,6 ,7 ,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static int aanscales[DCTSIZE2] = { + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +void iqtab_init(int *iqtab,unsigned char *iq_y) +{ +#define CONST_BITS14 14 +#define IFAST_SCALE_BITS 2 + int i; + + for(i=0;i>(CONST_BITS14-IFAST_SCALE_BITS); + } +} + +#define NOP 0xfe00 +unsigned short* rl2blk(int *blk,unsigned short *mdec_rl) { + int i,k,q_scale,rl; + int *iqtab; + + memset (blk, 0, 6*DCTSIZE2*4); + iqtab = iq_uv; + for(i=0;i<6;i++) { // decode blocks (Cr,Cb,Y1,Y2,Y3,Y4) + if (i>1) iqtab = iq_y; + + // zigzag transformation + rl = *mdec_rl++; + q_scale = RUNOF(rl); + blk[0] = iqtab[0]*VALOF(rl); + for(k = 0;;) { + rl = *mdec_rl++; + if (rl==NOP) break; + k += RUNOF(rl)+1; // skip level zero-coefficients + if (k > 63) break; + blk[zscan[k]] = (VALOF(rl) * iqtab[k] * q_scale) / 8; // / 16; + } +// blk[0] = (blk[0] * iq_t[0] * 8) / 16; +// for(int j=1;j<64;j++) +// blk[j] = blk[j] * iq_t[j] * q_scale; + + // idct + idct(blk,k+1); + + blk+=DCTSIZE2; + } + return mdec_rl; +} + +#ifdef FIXED +#define MULR(a) ((((int)0x0000059B) * (a)) >> 10) +#define MULG(a) ((((int)0xFFFFFEA1) * (a)) >> 10) +#define MULG2(a) ((((int)0xFFFFFD25) * (a)) >> 10) +#define MULB(a) ((((int)0x00000716) * (a)) >> 10) +#else +#define MULR(a) ((int)((float)1.40200 * (a))) +#define MULG(a) ((int)((float)-0.3437 * (a))) +#define MULG2(a) ((int)((float)-0.7143 * (a))) +#define MULB(a) ((int)((float)1.77200 * (a))) +#endif + +#define MAKERGB15(r,g,b) ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) ) +#define ROUND(c) roundtbl[((c)+128+256)]//&0x3ff] +/*#define ROUND(c) round(c+128) +int round(int r) { + if (r<0) return 0; + if (r>255) return 255; + return r; +}*/ + +#define RGB15(n, Y) \ + image[n] = MAKERGB15(ROUND(Y + R),ROUND(Y + G),ROUND(Y + B)); + +#define RGB15BW(n, Y) \ + image[n] = MAKERGB15(ROUND(Y),ROUND(Y),ROUND(Y)); + +#define RGB24(n, Y) \ + image[n+2] = ROUND(Y + R); \ + image[n+1] = ROUND(Y + G); \ + image[n+0] = ROUND(Y + B); + +#define RGB24BW(n, Y) \ + image[n+2] = ROUND(Y); \ + image[n+1] = ROUND(Y); \ + image[n+0] = ROUND(Y); + +unsigned char roundtbl[256*3]; + +void round_init(void) { + int i; + for(i=0;i<256;i++) { + roundtbl[i]=0; + roundtbl[i+256]=i; + roundtbl[i+512]=255; + } +} + +void yuv2rgb15(int *blk,unsigned short *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(0, Yblk[0]); + RGB15(1, Yblk[1]); + RGB15(16, Yblk[8]); + RGB15(17, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB15(8, Yblk[DCTSIZE2+0]); + RGB15(9, Yblk[DCTSIZE2+1]); + RGB15(24, Yblk[DCTSIZE2+8]); + RGB15(25, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=2,Yblk+=2) { + RGB15BW(0, Yblk[0]); + RGB15BW(1, Yblk[1]); + RGB15BW(16, Yblk[8]); + RGB15BW(17, Yblk[9]); + + RGB15BW(8, Yblk[DCTSIZE2+0]); + RGB15BW(9, Yblk[DCTSIZE2+1]); + RGB15BW(24, Yblk[DCTSIZE2+8]); + RGB15BW(25, Yblk[DCTSIZE2+9]); + } + } +} + +void yuv2rgb24(int *blk,unsigned char *image) { + int x,y; + int *Yblk = blk+DCTSIZE2*2; + int Cb,Cr,R,G,B; + int *Cbblk = blk; + int *Crblk = blk+DCTSIZE2; + + if (!(Config.Mdec&0x1)) + for (y=0;y<16;y+=2,Crblk+=4,Cbblk+=4,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Crblk++,Cbblk++,Yblk+=2) { + Cr = *Crblk; + Cb = *Cbblk; + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(0, Yblk[0]); + RGB24(1*3, Yblk[1]); + RGB24(16*3, Yblk[8]); + RGB24(17*3, Yblk[9]); + + Cr = *(Crblk+4); + Cb = *(Cbblk+4); + R = MULR(Cr); + G = MULG(Cb) + MULG2(Cr); + B = MULB(Cb); + + RGB24(8*3, Yblk[DCTSIZE2+0]); + RGB24(9*3, Yblk[DCTSIZE2+1]); + RGB24(24*3, Yblk[DCTSIZE2+8]); + RGB24(25*3, Yblk[DCTSIZE2+9]); + } + } else + for (y=0;y<16;y+=2,Yblk+=8,image+=24*3) { + if (y==8) Yblk+=DCTSIZE2; + for (x=0;x<4;x++,image+=6,Yblk+=2) { + RGB24BW(0, Yblk[0]); + RGB24BW(1*3, Yblk[1]); + RGB24BW(16*3, Yblk[8]); + RGB24BW(17*3, Yblk[9]); + + RGB24BW(8*3, Yblk[DCTSIZE2+0]); + RGB24BW(9*3, Yblk[DCTSIZE2+1]); + RGB24BW(24*3, Yblk[DCTSIZE2+8]); + RGB24BW(25*3, Yblk[DCTSIZE2+9]); + } + } +} + +int mdecFreeze(gzFile f, int Mode) { + + gzfreeze(&mdec, sizeof(mdec)); + + gzfreezel(iq_y); + + gzfreezel(iq_uv); + + + + return 0; + +} + + + + diff --git a/pcsx2/Mdec.h b/pcsx2/Mdec.h new file mode 100644 index 0000000..33690c9 --- /dev/null +++ b/pcsx2/Mdec.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MDEC_H__ +#define __MDEC_H__ + +void mdecInit(); +void mdecWrite0(u32 data); +void mdecWrite1(u32 data); +u32 mdecRead0(); +u32 mdecRead1(); +void psxDma0(u32 madr, u32 bcr, u32 chcr); +void psxDma1(u32 madr, u32 bcr, u32 chcr); +int mdecFreeze(gzFile f, int Mode); + +#endif /* __MDEC_H__ */ diff --git a/pcsx2/Memory.c b/pcsx2/Memory.c new file mode 100644 index 0000000..48cc999 --- /dev/null +++ b/pcsx2/Memory.c @@ -0,0 +1,3238 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + +RAM +--- +0x00100000-0x01ffffff this is the physical address for the ram.its cached there +0x20100000-0x21ffffff uncached +0x30100000-0x31ffffff uncached & acceleretade +0xa0000000-0xa1ffffff MIRROR might...??? +0x80000000-0x81ffffff MIRROR might... ???? + +scratch pad +---------- +0x70000000-0x70003fff scratch pad + +BIOS +---- +0x1FC00000 - 0x1FFFFFFF un-cached +0x9FC00000 - 0x9FFFFFFF cached +0xBFC00000 - 0xBFFFFFFF un-cached +*/ + +////////// +// Rewritten by zerofrog(@gmail.com) to add os virtual memory +////////// + + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#pragma warning(disable:4799) // No EMMS at end of function + +#include +#include +#include +#include + +#include "Common.h" + +#ifdef PCSX2_NORECBUILD +#define REC_CLEARM(mem) +#else +#include "iR5900.h" +#endif + +#include "PsxMem.h" +#include "R3000A.h" +#include "PsxHw.h" +#include "VUmicro.h" +#include "GS.h" + +#ifdef ENABLECACHE +#include "Cache.h" +#endif + +#include + +extern u32 maxrecmem; + +extern void * memcpy_fast(void *dest, const void *src, size_t n); + +//#define FULLTLB +int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode + +u16 ba0R16(u32 mem) { +#ifdef MEM_LOG + //MEM_LOG("ba00000 Memory read16 address %x\n", mem); +#endif + +#ifdef PCSX2_VIRTUAL_MEM + if (mem == 0x1a000006) { +#else + if (mem == 0xba000006) { +#endif + static int ba6; + ba6++; + if (ba6 == 3) ba6 = 0; + return ba6; + } + return 0; +} + +///////////////////////////// +// VIRTUAL MEM START +///////////////////////////// +#ifdef PCSX2_VIRTUAL_MEM + +PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0}; + +#define PHYSICAL_ALLOC(ptr, size, block) { \ + if(SysPhysicalAlloc(size, &block) == -1 ) \ + goto eCleanupAndExit; \ + if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \ + goto eCleanupAndExit; \ +} \ + +#define PHYSICAL_FREE(ptr, size, block) { \ + SysVirtualFree(ptr, size); \ + SysPhysicalFree(&block); \ +} \ + +#ifdef _WIN32 // windows implementation of vm + +PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs) +{ + PSMEMORYMAP m; + m.aPFNs = aPFNs; + m.aVFNs = aVFNs; + return m; +} + +// only do vm hack for release +#ifndef PCSX2_DEVBUILD +#define VM_HACK +#endif + +static int XmmExtendedRegOffset = 160; + +// virtual memory blocks +PSMEMORYMAP *memLUT = NULL; + +#define VIRTUAL_ALLOC(base, size, Protection) { \ + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \ + if( lpMemReserved == NULL || base != lpMemReserved ) \ + { \ + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \ + goto eCleanupAndExit; \ + } \ +} \ + +#define VIRTUAL_FREE(ptr, size) { \ + VirtualFree(ptr, size, MEM_DECOMMIT); \ + VirtualFree(ptr, 0, MEM_RELEASE); \ +} \ + +static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 }; + +INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata) +{ + int i; + u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters; + + assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION); + + XmmExtendedRegOffset = 160; + + for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) { + if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) { + XmmExtendedRegOffset = i*4; + break; + } + } + + pexdata->ContextRecord->Eip += 7; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +#if _MSC_VER < 1400 +#define VC_HANDLER _except_handler3 +#else +#define VC_HANDLER _except_handler4 +#endif + +//C's default exception handler +EXCEPTION_DISPOSITION VC_HANDLER( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +char cpp_handler_instructions[5]; +BOOL saved_handler_instructions = FALSE; + +//Exception handler that replaces C's default handler. +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ); + +#pragma pack(1) +typedef struct _jmp_instr +{ + unsigned char jmp; + DWORD offset; +} jmp_instr; +#pragma pack() + +BOOL WriteMemory(void * loc, void * buffer, int size) +{ + DWORD o2; + HANDLE hProcess = GetCurrentProcess(); + + //change the protection of pages containing range of memory + //[loc, loc+size] to READ WRITE + DWORD old_protection; + + BOOL ret; + ret = VirtualProtectEx(hProcess, loc, size, + PAGE_READWRITE, &old_protection); + if(ret == FALSE) + return FALSE; + + ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL); + + //restore old protection + VirtualProtectEx(hProcess, loc, size, old_protection, &o2); + + return (ret == TRUE); +} + +BOOL ReadMemory(void *loc, void *buffer, DWORD size) +{ + HANDLE hProcess = GetCurrentProcess(); + DWORD bytes_read = 0; + BOOL ret; + ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read); + return (ret == TRUE && bytes_read == size); +} + +BOOL install_my_handler() +{ + void * my_hdlr = SysPageFaultExceptionFilter; + void * cpp_hdlr = VC_HANDLER; + + jmp_instr jmp_my_hdlr; + jmp_my_hdlr.jmp = 0xE9; + + //We actually calculate the offset from __CxxFrameHandler+5 + //as the jmp instruction is 5 byte length. + jmp_my_hdlr.offset = (char*)(my_hdlr) - + ((char*)(cpp_hdlr) + 5); + + if(!saved_handler_instructions) + { + if(!ReadMemory(cpp_hdlr, cpp_handler_instructions, + sizeof(cpp_handler_instructions))) + return FALSE; + saved_handler_instructions = TRUE; + } + + return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr)); +} + +BOOL restore_cpp_handler() +{ + if(!saved_handler_instructions) + return FALSE; + else + { + void *loc = VC_HANDLER; + return WriteMemory(loc, cpp_handler_instructions, + sizeof(cpp_handler_instructions)); + } +} + +int memInit() { + + int i; + LPVOID pExtraMem = NULL; + + // release the previous reserved mem + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); + + // allocate all virtual memory + PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY); + VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY); + PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM); + PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS); + VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS); + + VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE); + VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE); + + // reserve the left over 224Mb, don't map + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x02000000 ) + goto eCleanupAndExit; + + // reserve left over psx mem + pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_PSX+0x00200000 ) + goto eCleanupAndExit; + + // reserve gs mem + pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + if( pExtraMem != PS2MEM_BASE+0x20000000 ) + goto eCleanupAndExit; + + // special addrs mmap + VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE); + + // alloc virtual mappings + memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16); + memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000); + for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]); + for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]); + for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]); + for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]); + for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]); + + for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]); + + // map to other modes + memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP)); + + if (psxInit() == -1) + goto eCleanupAndExit; + + // figure out xmm reg offset +// __asm movups xmm0, s_testmem +// __try { +// u8* p = 0; +// __asm { +// mov eax, dword ptr [p] +// } +// } +// __except( FindXmmOffsetException( GetExceptionInformation() ) ) { +// } + +//#ifdef WIN32_FILE_MAPPING + if( !install_my_handler() ) { + SysPrintf("Failed to install custom exception handler!\n"); + return -1; + } +//#endif + + return 0; + +eCleanupAndExit: + if( pExtraMem != NULL ) + VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE); + memShutdown(); + return -1; +} + +void memShutdown() +{ + VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE); + VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE); + + PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_FREE(PS2MEM_ROM, 0x00400000); + VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000); + VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000); + VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000); + PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM); + PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs + + VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000); + VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000); + VIRTUAL_FREE(PS2MEM_GS, 0x00010000); + VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000); + + VIRTUAL_FREE(PS2MEM_B80, 0x00010000); + VIRTUAL_FREE(PS2MEM_BA0, 0x00010000); + + VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE); + + _aligned_free(memLUT); memLUT = NULL; + + // reserve mem + VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); +} + +#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7)) +#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4))) + +//NOTE: A lot of the code reading depends on the registers being less than 8 +// MOV8 88/8A +// MOV16 6689 +// MOV32 89/8B +// SSEMtoR64 120f +// SSERtoM64 130f +// SSEMtoR128 280f +// SSERtoM128 290f + +#define SKIP_WRITE(pexdata) { \ + switch(code&0xff) { \ + case 0x88: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + break; \ + case 0x66: \ + assert( code&0x800000 ); \ + assert( (code&0xffff) == 0x8966 ); \ + ContextRecord->Eip += 7; \ + break; \ + case 0x89: \ + assert( code&0x8000 ); \ + ContextRecord->Eip += 6; \ + break; \ + case 0x0f: /* 130f, 230f*/ \ + assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \ + assert( code&0x800000 ); \ + ContextRecord->Eip += 7; \ + break; \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +#define SKIP_READ(pexdata) { \ + switch(code&0xff) { \ + case 0x8A: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x66: \ + if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \ + else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \ + rd = (code>>(24+3))&7; \ + break; \ + case 0x8B: \ + if( !(code&0x8000) ) goto DefaultHandler; \ + ContextRecord->Eip += 6; \ + rd = (code>>(8+3))&7; \ + break; \ + case 0x0f: { \ + assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \ + if( !(code&0x800000) ) goto DefaultHandler; \ + ContextRecord->Eip += 7; \ + rd = (code>>(16+3))&7; \ + break; } \ + default: \ + goto DefaultHandler; \ + } \ +} \ + +EXCEPTION_DISPOSITION SysPageFaultExceptionFilter( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext + ) +{ + u32 addr; + + C_ASSERT(sizeof(ContextRecord->Eax) == 4); + + // If the exception is not a page fault, exit. + if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + { + // call old handler + EXCEPTION_DISPOSITION d; + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // get bad virtual address + addr = (u32)ExceptionRecord->ExceptionInformation[1]; + + if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) { + PSMEMORYMAP* pmap; + + pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12]; + + if( pmap->aPFNs == NULL ) { + // NOTE: this is a hack because the address is truncated and there's no way + // to tell what it's upper bits are (due to OS limitations). + pmap += 0x80000; + if( pmap->aPFNs == NULL ) { + pmap += 0x20000; + } + //else addr += 0x20000000; + } + + if( pmap->aPFNs != NULL ) { + LPVOID pnewaddr; + DWORD oldaddr = pmap->aVFNs[0]; + + if( pmap->aVFNs[0] != 0 ) { + // delete the current mapping + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0); + } + + assert( pmap->aPFNs[0] != 0 ); + + pmap->aVFNs[0] = addr&~0xfff; + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) ) + return ExceptionContinueExecution; + + // try allocing the virtual mem + pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) ) + return ExceptionContinueExecution; + + SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n", + addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]); + } + } + else { + // check if vumem + + if( (addr&0xffff4000) == 0x11000000 ) { + // vu0mem + SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL, 0); + + s_psVuMem.aVFNs[1] = addr&~0xfff; + SysMapUserPhysicalPages((void*)addr, 1, s_psVuMem.aPFNs, 1); + + return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION; + } + } + + { + // call old handler + EXCEPTION_DISPOSITION d; + +#ifdef VM_HACK + u32 code = *(u32*)ExceptionRecord->ExceptionAddress; + u32 rd = 0; + + if( ExceptionRecord->ExceptionInformation[0] ) { + //SKIP_WRITE(ptrs); + // shouldn't be writing + } + else { + SysPrintf("vmhack "); + SKIP_READ(ptrs); + //((u32*)&ContextRecord->Eax)[rd] = 0; + return ExceptionContinueExecution; + } + +DefaultHandler: +#endif + restore_cpp_handler(); + d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext); + install_my_handler(); + return d; + } + + // continue execution + return EXCEPTION_CONTINUE_EXECUTION; +} + +#else // linux implementation + +#define VIRTUAL_ALLOC(base, size, Protection) { \ + void* lpMemReserved = mmap( base, size, Protection, MAP_PRIVATE|MAP_ANONYMOUS ); \ + if( lpMemReserved == NULL || base != lpMemReserved ) \ + { \ + SysPrintf("Cannot reserve memory at 0x%8.8x(%x).\n", base, lpMemReserved); \ + perror("err"); \ + goto eCleanupAndExit; \ + } \ +} \ + +#define VIRTUAL_FREE(ptr, size) munmap(ptr, size) + +uptr *memLUT = NULL; + +int memInit() +{ +int i; + LPVOID pExtraMem = NULL; + + // release the previous reserved mem + munmap(PS2MEM_BASE, 0x40000000); + + // allocate all virtual memory + PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PROT_READ); + VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PROT_READ); + VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PROT_READ); + VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PROT_READ); + PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM); + PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PROT_READ|PROT_WRITE); + VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PROT_NONE); + VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PROT_READ|PROT_WRITE); + VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PROT_NONE); + VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PROT_NONE); + VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PROT_NONE); + + VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PROT_READ|PROT_WRITE); + VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PROT_READ|PROT_WRITE); + + // special addrs mmap + VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PROT_READ|PROT_WRITE); + + // alloc virtual mappings + memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memset(memLUT, 0, sizeof(uptr)*0x100000); + for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = PS2MEM_BASE+(i<<12); + for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = PS2MEM_BASE+0x10000000+(i<<12); + for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = PS2MEM_BASE+0x1c000000+(i<<12); + for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = PS2MEM_VU0MICRO; + for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = PS2MEM_VU0MEM; + for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = PS2MEM_VU1MICRO+(i<<12); + for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = PS2MEM_VU1MEM+(i<<12); + + for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = PS2MEM_SCRATCH+(i<<12); + + // map to other modes + memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(uptr)); + memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(uptr)); + + if (psxInit() == -1) + goto eCleanupAndExit; + +eCleanupAndExit: + memShutdown(); + return -1; +} + +void memShutdown() +{ + VIRTUAL_FREE(PS2MEM_BASE, 0x20000000); + VIRTUAL_FREE(PS2MEM_PSX, 0x00800000); + + PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM); + VIRTUAL_FREE(PS2MEM_ROM, 0x00400000); + VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000); + VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000); + VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000); + PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS); + PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw); + PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM); + PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem); + + VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs + + VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000); + VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000); + VIRTUAL_FREE(PS2MEM_GS, 0x00010000); + VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000); + VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000); + + VIRTUAL_FREE(PS2MEM_B80, 0x00010000); + VIRTUAL_FREE(PS2MEM_BA0, 0x00010000); + + VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE); + + _aligned_free(memLUT); memLUT = NULL; + + // reserve mem + if( mmap(PS2MEM_BASE, 0x40000000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) != PS2MEM_BASE ) { + SysPrintf("failed to reserve mem\n"); + } +} + +#endif // _WIN32 + +// Some games read/write between different addrs but same physical memory +// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog) +u32 VM_RETRANSLATE(u32 mem) +{ + u8* p, *pbase; + if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem + return PS2MEM_BASE_+mem; + + p = (u8*)dmaGetAddrBase(mem), *pbase; + +#ifdef _WIN32 + // do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often + if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) { + return PS2MEM_BASE_+mem; + } + + pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0]; + if( pbase != NULL ) + p = pbase + ((u32)p&0xfff); +#endif + + return (u32)p; +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { + + PSMEMORYMAP* pmap; + + if( vaddr == paddr ) + return; + + if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) { +#ifdef _WIN32 + pmap = &memLUT[vaddr >> 12]; + + if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs || + pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) { + + SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0); + pmap->aVFNs[0] = 0; + } + + *pmap = memLUT[paddr >> 12]; +#else + memLUT[vaddr>>12] = memLUT[paddr>>12]; +#endif + } +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + +#ifdef _WIN32 +// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) { +// Cpu->Clear(vaddr&~0xfff, 0x1000/4); +// if( memLUT[vaddr>>12].aVFNs != NULL ) { +// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL, 0 ); +// memLUT[vaddr>>12].aVFNs = NULL; +// memLUT[vaddr>>12].aPFNs = NULL; +// } +// } +#else + if( memLUT[vaddr>>12] != NULL ) { + SysVirtualFree(memLUT[vaddr>>12], 0x1000); + memLUT[vaddr>>12] = 0; + } +#endif +} + +u8 recMemRead8() +{ + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&~0xffff) ) { + case 0x1f400000: return psxHw4Read8(mem); + case 0x10000000: return hwRead8(mem); + case 0x1f800000: return psxHwRead8(mem); + case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00)); + case 0x14000000: + { + u32 ret = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u8*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +void _eeReadConstMem8(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-3); + assert(0); + } + else { + if( sign ) MOVSX32M8toR(mmreg, mem); + else MOVZX32M8toR(mmreg, mem); + } +} + +void _eeReadConstMem16(int mmreg, u32 mem, int sign) +{ + assert( !IS_XMMREG(mmreg)); + + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem-2); + assert(0); + } + else { + if( sign ) MOVSX32M16toR(mmreg, mem); + else MOVZX32M16toR(mmreg, mem); + } +} + +void _eeReadConstMem32(int mmreg, u32 mem) +{ + if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMtoMMX(mmreg&0xf, mem); + } + else MOV32MtoR(mmreg, mem); +} + +void _eeReadConstMem128(int mmreg, u32 mem) +{ + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQMtoR((mmreg>>4)&0xf, mem+8); + MOVQMtoR(mmreg&0xf, mem); + } + else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem); +} + +void _eeWriteConstMem8(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_EECONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV8RtoM(mem, mmreg); +} + +void _eeWriteConstMem16(u32 mem, int mmreg) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + if( IS_EECONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV16RtoM(mem, mmreg); +} + +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op) +{ + assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) ); + switch(op) { + case 0: // and + if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else AND16RtoM(mem, mmreg); + break; + case 1: // and + if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else OR16RtoM(mem, mmreg); + break; + default: assert(0); + } +} + +void _eeWriteConstMem32(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else MOV32RtoM(mem, mmreg); +} + +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op) +{ + switch(op) { + case 0: // and + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_PAND_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PANDMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + AND32RtoM(mem, mmreg&0xf); + } + break; + + case 1: // or + if( IS_XMMREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SSE2_POR_M128_to_XMM(mmreg&0xf, mem); + SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + _deleteEEreg((mmreg>>16)&0x1f, 1); + SetMMXstate(); + PORMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + OR32RtoM(mem, mmreg&0xf); + } + break; + + case 2: // not and + if( mmreg & MEM_XMMTAG ) { + _deleteEEreg(mmreg>>16, 1); + SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem); + SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf); + } + else if( mmreg & MEM_MMXTAG ) { + _deleteEEreg(mmreg>>16, 1); + PANDNMtoR(mmreg&0xf, mem); + MOVDMMXtoM(mem, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]); + } + else { + NOT32R(mmreg&0xf); + AND32RtoM(mem, mmreg&0xf); + } + break; + + default: assert(0); + } +} + +void _eeWriteConstMem64(u32 mem, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + } + else assert(0); +} + +void _eeWriteConstMem128(u32 mem, int mmreg) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVQRtoM(mem, mmreg&0xf); + MOVQRtoM(mem+8, (mmreg>>4)&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + SetMMXstate(); + MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]); + MOVQRtoM(mem+8, mmreg&0xf); + } + else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf); +} + +void _eeMoveMMREGtoR(x86IntRegType to, int mmreg) +{ + if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf); + else if( IS_MMXREG(mmreg) ) { + SetMMXstate(); + MOVD32MMXtoR(to, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]); + else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]); + else if( mmreg != to ) MOV32RtoR(to, mmreg); +} + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign); + case 0x1000: return hwConstRead8(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead8(x86reg, mem, sign); + case 0x1200: return gsConstRead8(x86reg, mem, sign); + case 0x1400: + { + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read8); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + return 1; + } + + default: + _eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +u16 recMemRead16() { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( mem>>16 ) { + case 0x1000: return hwRead16(mem); + case 0x1f80: return psxHwRead16(mem); + case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00)); + case 0x1800: return 0; + case 0x1a00: return ba0R16(mem); + case 0x1f90: + case 0x1f00: + return SPU2read(mem); + case 0x1400: + { + u32 ret = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret); + return ret; + } + + default: + return *(u16*)(PS2MEM_BASE+mem); + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return 0; +} + +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: return hwConstRead16(x86reg, mem, sign); + case 0x1f80: return psxHwConstRead16(x86reg, mem, sign); + case 0x1200: return gsConstRead16(x86reg, mem, sign); + case 0x1800: + if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else XOR32RtoR(x86reg, x86reg); + return 0; + case 0x1a00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)ba0R16); + ADD32ItoR(ESP, 4); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f90: + case 0x1f00: + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2read); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1400: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read16); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + default: + _eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign); + return 0; + } +} + +__declspec(naked) +u32 recMemRead32() { + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwread + cmp dx, 0x1f80 + je psxhwread + cmp dx, 0x1200 + je gsread + cmp dx, 0x1400 + je devread + + // default read + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +hwread: + { + __asm { + cmp ecx, 0x10002000 + jb counterread + + cmp ecx, 0x1000f260 + je hwsifpresetread + cmp ecx, 0x1000f240 + je hwsifsyncread + + cmp ecx, 0x10003000 + jb hwdefread2 + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + + // ipu +hwdefread2: + push ecx + call ipuRead32 + add esp, 4 + ret + + // sif +hwsifpresetread: + mov eax, 0 + ret +hwsifsyncread: + mov eax, dword ptr [0x1000F240+PS2MEM_BASE_] + or eax, 0xF0000102 + ret + } + +counterread: + { + static u32 mem, index; + + // counters + __asm mov mem, ecx + index = (mem>>11)&3; + + if( (mem&0x7ff) == 0 ) { + __asm { + push index + call rcntRcount + add esp, 4 + and eax, 0xffff + ret + } + } + + index = (u32)&counters[index] + ((mem>>2)&0xc); + + __asm { + mov eax, index + mov eax, dword ptr [eax] + movzx eax, ax + ret + } + } + } + +psxhwread: + __asm { + push ecx + call psxHwRead32 + add esp, 4 + ret + } + +gsread: + __asm { + and ecx, 0xfffff3ff + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + } + +devread: + __asm { + and ecx, 0xfbffffff + push ecx + call DEV9read32 + add esp, 4 + ret + } +} + +int recMemConstRead32(u32 x86reg, u32 mem) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&~0xffff) ) { + case 0x10000000: return hwConstRead32(x86reg, mem); + case 0x1f800000: return psxHwConstRead32(x86reg, mem); + case 0x12000000: return gsConstRead32(x86reg, mem); + case 0x14000000: + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9read32); + return 1; + + default: + _eeReadConstMem32(x86reg, VM_RETRANSLATE(mem)); + return 0; + } +} + +void recMemRead64(u64 *out) +{ + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: *out = hwRead64(mem); return; + case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return; + case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return; + + default: + //assert(0); + *out = *(u64*)(PS2MEM_BASE+mem); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead64(mem, mmreg); return; + case 0x12000000: gsConstRead64(mem, mmreg); return; + default: + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem)); + else { + MOVQMtoR(mmreg, VM_RETRANSLATE(mem)); + SetMMXstate(); + } + return; + } +} + +void recMemRead128(u64 *out) { + + register u32 mem; + __asm mov mem, ecx // already anded with ~0xa0000000 + + switch( (mem&0xffff0000) ) { + case 0x10000000: + hwRead128(mem, out); + return; + case 0x12000000: + out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); + out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8); + return; + case 0x11000000: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + default: + //assert(0); + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); +} + +void recMemConstRead128(u32 mem, int xmmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstRead128(mem, xmmreg); return; + case 0x12000000: gsConstRead128(mem, xmmreg); return; + default: + _eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem)); + return; + } +} + +void errwrite() +{ + int i, bit, tempeax; + __asm mov i, ecx + __asm mov tempeax, eax + __asm mov bit, edx + SysPrintf("Error write%d at %x\n", bit, i); + assert(0); + __asm mov eax, tempeax + __asm mov ecx, i +} + +void recMemWrite8() +{ + register u32 mem; + register u8 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, al + + switch( mem>>16 ) { + case 0x1f40: psxHw4Write8(mem, value); return; + case 0x1000: hwWrite8(mem, value); return; + case 0x1f80: psxHwWrite8(mem, value); return; + case 0x1200: gsWrite8(mem, value); return; + case 0x1400: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + *(u8*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite8(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0; + case 0x1000: hwConstWrite8(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0; + case 0x1200: gsConstWrite8(mem, mmreg); return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write8); + return 0; + + case 0x1100: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +void recMemWrite16() { + + register u32 mem; + register u16 value; + __asm mov mem, ecx // already anded with ~0xa0000000 + __asm mov value, ax + + switch( mem>>16 ) { + case 0x1000: hwWrite16(mem, value); return; + case 0x1f80: psxHwWrite16(mem, value); return; + case 0x1200: gsWrite16(mem, value); return; + case 0x1f90: + case 0x1f00: SPU2write(mem, value); return; + case 0x1400: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + +#ifdef _DEBUG + case 0x1100: assert(0); +#endif + default: + // vus, bad addrs, etc + *(u16*)(PS2MEM_BASE+mem) = value; + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +int recMemConstWrite16(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem>>16 ) { + case 0x1000: hwConstWrite16(mem, mmreg); return 0; + case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0; + case 0x1200: gsConstWrite16(mem, mmreg); return 0; + case 0x1f90: + case 0x1f00: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x1400: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write16); + return 0; + + case 0x1100: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +__declspec(naked) +void recMemWrite32() +{ + // ecx is address - already anded with ~0xa0000000 + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1f80 + je psxwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1400 + je devwrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + ret + +hwwrite: + push eax + push ecx + call hwWrite32 + add esp, 8 + ret +psxwrite: + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret +gswrite: + push eax + push ecx + call gsWrite32 + add esp, 8 + ret +devwrite: + and ecx, 0xfbffffff + push eax + push ecx + call DEV9write32 + add esp, 8 + ret +vuwrite: + // default write + mov dword ptr [ecx+PS2MEM_BASE_], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 1 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite32(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( mem&0xffff0000 ) { + case 0x10000000: hwConstWrite32(mem, mmreg); return 0; + case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0; + case 0x12000000: gsConstWrite32(mem, mmreg); return 0; + case 0x1f900000: + case 0x1f000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((u32)SPU2write); + return 0; + case 0x14000000: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem & ~0x04000000); + CALLFunc((u32)DEV9write32); + return 0; + + case 0x1100: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(1); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) void recMemWrite64() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + // default write + mov edx, 64 + call errwrite + +hwwrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call hwWrite64 + add esp, 12 + ret + +gswrite: + push dword ptr [eax+4] + push dword ptr [eax] + push ecx + call gsWrite64 + add esp, 12 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 2 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + ret + } +} + +int recMemConstWrite64(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem>>16) ) { + case 0x1000: hwConstWrite64(mem, mmreg); return 0; + case 0x1200: gsConstWrite64(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(2); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +__declspec(naked) +void recMemWrite128() +{ + __asm { + + mov edx, ecx + shr edx, 16 + cmp dx, 0x1000 + je hwwrite + cmp dx, 0x1200 + je gswrite + cmp dx, 0x1100 + je vuwrite + } + + __asm { + mov edx, 128 + call errwrite + +hwwrite: + + push eax + push ecx + call hwWrite128 + add esp, 8 + ret + +vuwrite: + mov ebx, dword ptr [eax] + mov edx, dword ptr [eax+4] + mov edi, dword ptr [eax+8] + mov eax, dword ptr [eax+12] + mov dword ptr [ecx+PS2MEM_BASE_], ebx + mov dword ptr [ecx+PS2MEM_BASE_+4], edx + mov dword ptr [ecx+PS2MEM_BASE_+8], edi + mov dword ptr [ecx+PS2MEM_BASE_+12], eax + + cmp ecx, 0x11004000 + jge vu1write + and ecx, 0x3ff8 + // clear vu0mem + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU0 + add esp, 8 + ret + +vu1write: + cmp ecx, 0x11008000 + jl vuend + cmp ecx, 0x1100c000 + jge vuend + // clear vu1mem + and ecx, 0x3ff8 + mov eax, Cpu + push 4 + push ecx + call [eax]Cpu.ClearVU1 + add esp, 8 +vuend: + + // default write + //movaps xmm7, qword ptr [eax] + + // removes possible exceptions and saves on remapping memory + // *might* be faster for certain games, no way to tell +// cmp ecx, 0x20000000 +// jb Write128 +// +// // look for better mapping +// mov edx, ecx +// shr edx, 12 +// shl edx, 3 +// add edx, memLUT +// mov edx, dword ptr [edx + 4] +// cmp edx, 0 +// je Write128 +// mov edx, dword ptr [edx] +// cmp edx, 0 +// je Write128 +// and ecx, 0xfff +// movaps qword ptr [ecx+edx], xmm7 +// jmp CheckOverwrite +//Write128: + //movaps qword ptr [ecx+PS2MEM_BASE_], xmm7 + ret + +gswrite: + sub esp, 8 + movlps xmm7, qword ptr [eax] + movlps qword ptr [esp], xmm7 + push ecx + call gsWrite64 + + // call again for upper 8 bytes + movlps xmm7, qword ptr [eax+8] + movlps qword ptr [esp+4], xmm7 + add [esp], 8 + call gsWrite64 + add esp, 12 + ret + } +} + +int recMemConstWrite128(u32 mem, int mmreg) +{ + mem = TRANSFORM_ADDR(mem); + + switch( (mem&0xffff0000) ) { + case 0x10000000: hwConstWrite128(mem, mmreg); return 0; + case 0x12000000: gsConstWrite128(mem, mmreg); return 0; + + case 0x1100: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + + if( mem < 0x11004000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU0); + ADD32ItoR(ESP, 8); + } + else if( mem >= 0x11008000 && mem < 0x1100c0000 ) { + PUSH32I(4); + PUSH32I(mem&0x3ff8); + CALLFunc((u32)Cpu->ClearVU1); + ADD32ItoR(ESP, 8); + } + return 0; + + default: + _eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg); + return 1; + } +} + +int memRead8 (u32 mem, u8 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = psxHw4Read8(mem); return 0; + case 0x10000000: *out = hwRead8(mem); return 0; + case 0x1f800000: *out = psxHwRead8(mem); return 0; + case 0x12000000: *out = gsRead8(mem); return 0; + case 0x14000000: + *out = DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (s8)hwRead8(mem); return 0; + case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (s8)gsRead8(mem); return 0; + case 0x14000000: + *out = (s8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0; + case 0x10000000: *out = (u8)hwRead8(mem); return 0; + case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0; + case 0x12000000: *out = (u8)gsRead8(mem); return 0; + case 0x14000000: + *out = (u8)DEV9read8(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u8*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead16(mem); return 0; + case 0x1f800000: *out = psxHwRead16(mem); return 0; + case 0x12000000: *out = gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = SPU2read(mem); return 0; + break; + case 0x14000000: + *out = DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s16)hwRead16(mem); return 0; + case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0; + case 0x12000000: *out = (s16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (s16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (s16)SPU2read(mem); return 0; + break; + case 0x14000000: + *out = (s16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u16)hwRead16(mem ); return 0; + case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0; + case 0x12000000: *out = (u16)gsRead16(mem); return 0; + case 0x18000000: *out = 0; return 0; + case 0x1a000000: *out = (u16)ba0R16(mem); return 0; + case 0x1f900000: + case 0x1f000000: + *out = (u16)SPU2read(mem ); return 0; + break; + case 0x14000000: + *out = (u16)DEV9read16(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u16*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead32(mem); return 0; + case 0x1f800000: *out = psxHwRead32(mem); return 0; + case 0x12000000: *out = gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (s32)hwRead32(mem); return 0; + case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (s32)gsRead32(mem); return 0; + case 0x14000000: + *out = (s32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(s32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = (u32)hwRead32(mem); return 0; + case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0; + case 0x12000000: *out = (u32)gsRead32(mem); return 0; + case 0x14000000: + *out = (u32)DEV9read32(mem & ~0x04000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out); + return 0; + + default: + *out = *(u32*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: *out = hwRead64(mem); return 0; + case 0x12000000: *out = gsRead64(mem); return 0; + + default: + *out = *(u64*)(PS2MEM_BASE+mem); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: + hwRead128(mem, out); + return 0; + case 0x12000000: + out[0] = gsRead64(mem); + out[1] = gsRead64(mem + 8); + return 0; + + default: + out[0] = *(u64*)(PS2MEM_BASE+mem); + out[1] = *(u64*)(PS2MEM_BASE+mem+8); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x1f400000: psxHw4Write8(mem, value); return; + case 0x10000000: hwWrite8(mem, value); return; + case 0x1f800000: psxHwWrite8(mem, value); return; + case 0x12000000: gsWrite8(mem, value); return; + case 0x14000000: + DEV9write8(mem & ~0x04000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value); + return; + + default: + *(u8*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite16(mem, value); return; + case 0x1f800000: psxHwWrite16(mem, value); return; + case 0x12000000: gsWrite16(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write16(mem & ~0x04000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value); + return; + + default: + *(u16*)(PS2MEM_BASE+mem) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~3); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite32(mem, value); return; + case 0x1f800000: psxHwWrite32(mem, value); return; + case 0x12000000: gsWrite32(mem, value); return; + case 0x1f900000: + case 0x1f000000: SPU2write(mem, value); return; + case 0x14000000: + DEV9write32(mem & ~0x4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value); + return; + + default: + *(u32*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite64(mem, value); return; + case 0x12000000: gsWrite64(mem, value); return; + + default: + *(u64*)(PS2MEM_BASE+mem) = value; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + + mem = TRANSFORM_ADDR(mem); + switch( (mem&~0xffff) ) { + case 0x10000000: hwWrite128(mem, value); return; + case 0x12000000: + gsWrite64(mem, value[0]); + gsWrite64(mem + 8, value[1]); + return; + + default: + *(u64*)(PS2MEM_BASE+mem) = value[0]; + *(u64*)(PS2MEM_BASE+mem+8) = value[1]; + + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + } + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +#else + +u8 *psM; //32mb Main Ram +u8 *psR; //4mb rom area +u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +u8 *psR2; // 0x00080000 +u8 *psER; // 0x001C0000 +u8 *psS; //0.015 mb, scratch pad + +uptr *memLUTR; +uptr *memLUTW; +uptr *memLUTRK; +uptr *memLUTWK; +uptr *memLUTRU; +uptr *memLUTWU; + +///////////////////////////// +// REGULAR MEM START +///////////////////////////// + +void memMapMem(u32 base) { + int i; + + for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12]; + for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12]; + for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12]; + for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12]; + for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12]; + for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12]; + for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12]; + + assert( ((uptr)VU0.Mem&15)==0 && ((uptr)VU0.Micro&15)==0); + for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure) + + for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm + for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2 + for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure) +} + +void memMapKernelMem() { + memMapMem(0xa0000); + memMapMem(0x80000); + memMapMem(0x00000); +} + +void memMapSupervisorMem() { +} + +void memMapUserMem() { +} + +int memInit() { + int i; + + psR = (u8*)_aligned_malloc(0x00400010, 16); + psR1 = (u8*)_aligned_malloc(0x00080010, 16); + psR2 = (u8*)_aligned_malloc(0x00080010, 16); + + if (psxInit() == -1) + return -1; + + memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16); + + psM = (u8*)_aligned_malloc(0x02000010, 16); + psER = (u8*)_aligned_malloc(0x001C0010, 16); + psS = (u8*)_aligned_malloc(0x00004010, 16); + if (memLUTRK == NULL || memLUTWK == NULL || + memLUTRU == NULL || memLUTWU == NULL || + psM == NULL || psR == NULL || psR1 == NULL || + psR2 == NULL || psER == NULL || psS == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(memLUTRK, 0, 0x100000 * 4); + memset(memLUTWK, 0, 0x100000 * 4); + memset(memLUTRU, 0, 0x100000 * 4); + memset(memLUTWU, 0, 0x100000 * 4); + + memset(psM, 0, 0x02000010); + memset(psR, 0, 0x00400010); + memset(psR1, 0, 0x00080010); + memset(psR2, 0, 0x00080010); + memset(psER, 0, 0x001C0010); + memset(psS, 0, 0x00004010); + + for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12]; + + for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12]; + for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12]; + + + memMapKernelMem(); + memMapSupervisorMem(); + memMapUserMem(); + + memSetKernelMode(); + +#ifdef ENABLECACHE + memset(pCache,0,sizeof(_cacheS)*64); +#endif + + return 0; +} + +void memShutdown() { + FREE(psM); + FREE(psR); + FREE(psR1); + FREE(psR2); + FREE(psER); + FREE(psS); + FREE(memLUTRK); + FREE(memLUTWK); + FREE(memLUTRU); + FREE(memLUTWU); +} + +void memSetPageAddr(u32 vaddr, u32 paddr) { +// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr); + + memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12]; + + memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12]; + memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12]; +} + +void memClearPageAddr(u32 vaddr) { +// SysPrintf("memClearPageAddr: %8.8x\n", vaddr); + + if ((vaddr & 0xffffc000) == 0x70000000) return; + memLUTRU[vaddr >> 12] = 0; + memLUTWU[vaddr >> 12] = 0; + +#ifdef FULLTLB + memLUTRK[vaddr >> 12] = 0; + memLUTWK[vaddr >> 12] = 0; +#endif +} + +int memRead8 (u32 mem, u8 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + u8 *tmp = readCache(mem); + *out = *(u8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RS (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(s8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (s8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead8RU (u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(u8 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u8 *)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (u8)hwRead8(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u8)psxHwRead8(mem & ~0xa0000000); return 0; + case 3: // psh4 + *out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u8)gsRead8(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u8)DEV9read8(mem & ~0xa4000000); + SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16(u32 mem, u16 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + u8 *tmp = readCache(mem); + *out = *(u16 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = ba0R16(mem); return 0; + case 6: // gsm + *out = gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(s16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (s16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (s16)ba0R16(mem); return 0; + case 6: // gsm + *out = (s16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (s16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead16RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(u16*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u16*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (u16)hwRead16(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u16)psxHwRead16(mem & ~0xa0000000); return 0; + case 4: // b80 +#ifdef MEM_LOG + MEM_LOG("b800000 Memory read16 address %x\n", mem); +#endif + *out = 0; return 0; + case 5: // ba0 + *out = (u16)ba0R16(mem); return 0; + case 6: // gsm + *out = (u16)gsRead16(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u16)DEV9read16(mem & ~0xa4000000); + SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out); + return 0; + case 8: // spu2 + *out = (u16)SPU2read(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32(u32 mem, u32 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + u8 *tmp = readCache(mem); + *out = *(u32 *)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + assert( (int)(uptr)p < 8 ); + + switch ((int)(uptr)p) { + case 1: // hwm + *out = hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RS(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(s32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(s32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (s32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (s32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (s32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (s32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead32RU(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + char *tmp = (char*)readCache(mem); + *out = *(u32*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u32*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = (u32)hwRead32(mem & ~0xa0000000); return 0; + case 2: // psh + *out = (u32)psxHwRead32(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = (u32)gsRead32(mem & ~0xa0000000); return 0; + case 7: // dev9 + *out = (u32)DEV9read32(mem & ~0xa4000000); + SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out); + return 0; + } + +#ifdef PCSX2_DEVBUILD + MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead64(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + u8 *tmp = readCache(mem); + *out = *(u64*)(tmp+(mem&0xf)); + return 0; + } +#endif + *out = *(u64*)(p + (mem & 0xfff)); + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + *out = hwRead64(mem & ~0xa0000000); return 0; + case 6: // gsm + *out = gsRead64(mem & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +int memRead128(u32 mem, u64 *out) { + char *p; + + p = (char *)(memLUTR[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && + (cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) { + u64 *tmp = (u64*)readCache(mem); + out[0] = tmp[0]; + out[1] = tmp[1]; + return 0; + } +#endif + p+= mem & 0xfff; + out[0] = ((u64*)p)[0]; + out[1] = ((u64*)p)[1]; + return 0; + } + + switch ((int)(uptr)p) { + case 1: // hwm + hwRead128(mem & ~0xa0000000, out); return 0; + case 6: // gsm + out[0] = gsRead64((mem ) & ~0xa0000000); + out[1] = gsRead64((mem+8) & ~0xa0000000); return 0; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem); +#endif + cpuTlbMissR(mem, cpuRegs.branch); + + return -1; +} + +void memWrite8 (u32 mem, u8 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) { + writeCache8(mem, value); + return; + } +#endif + *(u8 *)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&(~3)); +// PSXREC_CLEARM(mem & 0x1ffffc); + } + return; + } + + switch ((int)(uptr)p) { + case 1: // hwm + hwWrite8(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite8(mem & ~0xa0000000, value); return; + case 3: // psh4 + psxHw4Write8(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite8(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write8(mem & ~0xa4000000, value); + SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value); + return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite16(u32 mem, u16 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) { + writeCache16(mem, value); + return; + } +#endif + *(u16*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem&~1); + //PSXREC_CLEARM(mem & 0x1ffffe); + } + return; + } + + switch ((int)(uptr)p) { + case 1: // hwm + hwWrite16(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite16(mem & ~0xa0000000, value); return; + case 5: // ba0 +#ifdef MEM_LOG + MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value); +#endif + return; + case 6: // gsm + gsWrite16(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write16(mem & ~0xa4000000, value); + SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value); + return; + case 8: // spu2 + SPU2write(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite32(u32 mem, u32 value) +{ + char *p; + p = (char *)(memLUTW[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) + { + writeCache32(mem, value); + return; + } +#endif + *(u32*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); +// PSXREC_CLEARM(mem & 0x1fffff); + } + return; + } + + switch ((int)(uptr)p) { + case 1: // hwm + hwWrite32(mem & ~0xa0000000, value); + return; + case 2: // psh + psxHwWrite32(mem & ~0xa0000000, value); return; + case 6: // gsm + gsWrite32(mem & ~0xa0000000, value); return; + case 7: // dev9 + DEV9write32(mem & ~0xa4000000, value); + SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value); + return; + } +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite64(u32 mem, u64 value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((uptr)p > 0x10) { + #ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) { + writeCache64(mem, value); + return; + } + #endif + /* __asm __volatile ( + "movq %1, %%mm0\n" + "movq %%mm0, %0\n" + "emms\n" + : "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value) + );*/ + *(u64*)(p + (mem & 0xfff)) = value; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + } + return; + } + + + switch ((int)(uptr)p) { + case 1: // hwm + hwWrite64(mem & ~0xa0000000, value); + return; + case 6: // gsm + gsWrite64(mem & ~0xa0000000, value); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + +void memWrite128(u32 mem, u64 *value) { + char *p; + + p = (char *)(memLUTW[mem >> 12]); + if ((uptr)p > 0x10) { +#ifdef ENABLECACHE + if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) { + writeCache128(mem, value); + return; + } +#endif + p+= mem & 0xfff; + ((u64*)p)[0] = value[0]; + ((u64*)p)[1] = value[1]; + if (CHECK_EEREC) { + REC_CLEARM(mem); + REC_CLEARM(mem+4); + REC_CLEARM(mem+8); + REC_CLEARM(mem+12); + +/* PSXREC_CLEARM((mem) & 0x1fffff); + PSXREC_CLEARM((mem+4) & 0x1fffff); + PSXREC_CLEARM((mem+8) & 0x1fffff); + PSXREC_CLEARM((mem+12) & 0x1fffff);*/ + } + return; + } + + switch ((int)(uptr)p) { + case 1: // hwm + hwWrite128(mem & ~0xa0000000, value); + return; + case 6: // gsm + mem &= ~0xa0000000; + gsWrite64(mem, value[0]); + gsWrite64(mem+8, value[1]); return; + } + +#ifdef MEM_LOG + MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]); +#endif + cpuTlbMissW(mem, cpuRegs.branch); +} + + +#endif // PCSX2_VIRTUAL_MEM + +void loadBiosRom(char *ext, u8 *dest) { + struct stat buf; + char Bios1[256]; + char Bios[256]; + FILE *fp; + char *ptr; + int i; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + sprintf(Bios1, "%s.%s", Bios, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s", Bios); + ptr = Bios1; i = strlen(Bios1); + while (i > 0) { if (ptr[i] == '.') break; i--; } + ptr[i+1] = 0; + strcat(Bios1, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + + sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext); + if (stat(Bios1, &buf) != -1) { + fp = fopen(Bios1, "rb"); + fread(dest, 1, buf.st_size, fp); + fclose(fp); + return; + } + SysPrintf("\n\n\n"); + SysPrintf("**************\n"); + SysPrintf("%s NOT FOUND\n", ext); + SysPrintf("**************\n\n\n"); +} + +void memReset() { + struct stat buf; + char Bios[256]; + FILE *fp; + +#ifdef PCSX2_VIRTUAL_MEM + DWORD OldProtect; + memset(PS2MEM_BASE, 0, 0x02000000); + memset(PS2MEM_SCRATCH, 0, 0x00004000); +#else + memset(psM, 0, 0x02000000); + memset(psS, 0, 0x00004000); +#endif + + strcpy(Bios, Config.BiosDir); + strcat(Bios, Config.Bios); + + if (stat(Bios, &buf) == -1) { + SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios); + return; + } + +#ifdef PCSX2_VIRTUAL_MEM + +#ifdef _WIN32 + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#else + mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ|PROT_WRITE); + mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ|PROT_WRITE); + mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ|PROT_WRITE); + mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ|PROT_WRITE); +#endif + +#endif + + fp = fopen(Bios, "rb"); + fread(PS2MEM_ROM, 1, buf.st_size, fp); + fclose(fp); + + BiosVersion = GetBiosVersion(); + SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff); + + //injectIRX("host.irx"); //not fully tested; still buggy + + // reset memLUT + + loadBiosRom("rom1", PS2MEM_ROM1); + loadBiosRom("rom2", PS2MEM_ROM2); + loadBiosRom("erom", PS2MEM_EROM); + +#ifdef PCSX2_VIRTUAL_MEM + +#ifdef _WIN32 + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#else + mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ); + mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ); + mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ); + mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ); +#endif + +#endif +} + +void memSetKernelMode() { +#ifndef PCSX2_VIRTUAL_MEM + memLUTR = memLUTRK; + memLUTW = memLUTWK; +#endif + MemMode = 0; +} + +void memSetSupervisorMode() { +} + +void memSetUserMode() { +#ifdef FULLTLB +#ifndef PCSX2_VIRTUAL_MEM + memLUTR = memLUTRU; + memLUTW = memLUTWU; +#endif + MemMode = 2; +#endif +} + diff --git a/pcsx2/Memory.h b/pcsx2/Memory.h new file mode 100644 index 0000000..9cd8f08 --- /dev/null +++ b/pcsx2/Memory.h @@ -0,0 +1,265 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +////////// +// Rewritten by zerofrog to add os virtual memory +////////// + +#ifndef __MEMORY_H__ +#define __MEMORY_H__ + +//#define ENABLECACHE + +#define PS2MEM_BASE_ 0x18000000 +#define PS2MEM_PSX_ (PS2MEM_BASE_+0x1c000000) + +#ifdef PCSX2_VIRTUAL_MEM + +#ifdef _WIN32 +typedef struct _PSMEMORYMAP +{ + uptr* aPFNs, *aVFNs; +} PSMEMORYMAP; +#endif + +#define TRANSFORM_ADDR(memaddr) ( ((u32)(memaddr)>=0x40000000) ? ((memaddr)&~0xa0000000) : (memaddr) ) + +//new memory model +#define PS2MEM_BASE ((u8*)PS2MEM_BASE_) +#define PS2MEM_HW ((u8*)((u32)PS2MEM_BASE+0x10000000)) +#define PS2MEM_ROM ((u8*)((u32)PS2MEM_BASE+0x1fc00000)) +#define PS2MEM_ROM1 ((u8*)((u32)PS2MEM_BASE+0x1e000000)) +#define PS2MEM_ROM2 ((u8*)((u32)PS2MEM_BASE+0x1e400000)) +#define PS2MEM_EROM ((u8*)((u32)PS2MEM_BASE+0x1e040000)) +#define PS2MEM_PSX ((u8*)PS2MEM_PSX_) +#define PS2MEM_SCRATCH ((u8*)((u32)PS2MEM_BASE+0x50000000)) +#define PS2MEM_VU0MICRO ((u8*)((u32)PS2MEM_BASE+0x11000000)) +#define PS2MEM_VU0MEM ((u8*)((u32)PS2MEM_BASE+0x11004000)) +#define PS2MEM_VU1MICRO ((u8*)((u32)PS2MEM_BASE+0x11008000)) +#define PS2MEM_VU1MEM ((u8*)((u32)PS2MEM_BASE+0x1100c000)) + +// function for mapping memory +#define PS2MEM_PSXHW ((u8*)((u32)PS2MEM_BASE+0x1f800000)) +#define PS2MEM_PSXHW4 ((u8*)((u32)PS2MEM_BASE+0x1f400000)) +#define PS2MEM_GS ((u8*)((u32)PS2MEM_BASE+0x12000000)) +#define PS2MEM_DEV9 ((u8*)((u32)PS2MEM_BASE+0x14000000)) +#define PS2MEM_SPU2 ((u8*)((u32)PS2MEM_BASE+0x1f900000)) +#define PS2MEM_SPU2_ ((u8*)((u32)PS2MEM_BASE+0x1f000000)) // ? +#define PS2MEM_B80 ((u8*)((u32)PS2MEM_BASE+0x18000000)) +#define PS2MEM_BA0 ((u8*)((u32)PS2MEM_BASE+0x1a000000)) + +#define PSM(mem) (PS2MEM_BASE + TRANSFORM_ADDR(mem)) + +#else + +extern u8 *psM; //32mb Main Ram +extern u8 *psR; //4mb rom area +extern u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this) +extern u8 *psR2; // 0x00080000 +extern u8 *psER; // 0x001C0000 +extern u8 *psS; //0.015 mb, scratch pad + +#define PS2MEM_BASE psM +#define PS2MEM_HW psH +#define PS2MEM_ROM psR +#define PS2MEM_ROM1 psR1 +#define PS2MEM_ROM2 psR2 +#define PS2MEM_EROM psER +#define PS2MEM_SCRATCH psS + +extern u8 g_RealGSMem[0x2000]; +#define PS2MEM_GS g_RealGSMem + +//#define _PSM(mem) (memLUTR[(mem) >> 12] == 0 ? NULL : (void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define PSM(mem) ((void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) +#define FREE(ptr) _aligned_free(ptr) + +extern uptr *memLUTR; +extern uptr *memLUTW; +extern uptr *memLUTRK; +extern uptr *memLUTWK; +extern uptr *memLUTRU; +extern uptr *memLUTWU; + +#endif + +#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMs64(mem) (*(s64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu8(mem) (*(u8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu16(mem) (*(u16*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu32(mem) (*(u32*)&PS2MEM_BASE[(mem) & 0x1ffffff]) +#define psMu64(mem) (*(u64*)&PS2MEM_BASE[(mem) & 0x1ffffff]) + +#define psRs8(mem) (*(s8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs16(mem) (*(s16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs32(mem) (*(s32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRs64(mem) (*(s64*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu8(mem) (*(u8 *)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu16(mem) (*(u16*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu32(mem) (*(u32*)&PS2MEM_ROM[(mem) & 0x3fffff]) +#define psRu64(mem) (*(u64*)&PS2MEM_ROM[(mem) & 0x3fffff]) + +#define psR1s8(mem) (*(s8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s16(mem) (*(s16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s32(mem) (*(s32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1s64(mem) (*(s64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u8(mem) (*(u8 *)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u16(mem) (*(u16*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u32(mem) (*(u32*)&PS2MEM_ROM1[(mem) & 0x3ffff]) +#define psR1u64(mem) (*(u64*)&PS2MEM_ROM1[(mem) & 0x3ffff]) + +#define psR2s8(mem) (*(s8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s16(mem) (*(s16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s32(mem) (*(s32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2s64(mem) (*(s64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u8(mem) (*(u8 *)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u16(mem) (*(u16*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u32(mem) (*(u32*)&PS2MEM_ROM2[(mem) & 0x3ffff]) +#define psR2u64(mem) (*(u64*)&PS2MEM_ROM2[(mem) & 0x3ffff]) + +#define psERs8(mem) (*(s8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs16(mem) (*(s16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs32(mem) (*(s32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERs64(mem) (*(s64*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu8(mem) (*(u8 *)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu16(mem) (*(u16*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff]) +#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff]) + +#define psSs8(mem) (*(s8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs16(mem) (*(s16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs32(mem) (*(s32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSs64(mem) (*(s64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu8(mem) (*(u8 *)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu16(mem) (*(u16*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) +#define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) + +#define PSMs8(mem) (*(s8 *)PSM(mem)) +#define PSMs16(mem) (*(s16*)PSM(mem)) +#define PSMs32(mem) (*(s32*)PSM(mem)) +#define PSMs64(mem) (*(s64*)PSM(mem)) +#define PSMu8(mem) (*(u8 *)PSM(mem)) +#define PSMu16(mem) (*(u16*)PSM(mem)) +#define PSMu32(mem) (*(u32*)PSM(mem)) +#define PSMu64(mem) (*(u64*)PSM(mem)) + +int memInit(); +void memReset(); +void memSetKernelMode(); +void memSetSupervisorMode(); +void memSetUserMode(); +void memSetPageAddr(u32 vaddr, u32 paddr); +void memClearPageAddr(u32 vaddr); +void memShutdown(); + +int memRead8(u32 mem, u8 *out); +int memRead8RS(u32 mem, u64 *out); +int memRead8RU(u32 mem, u64 *out); +int memRead16(u32 mem, u16 *out); +int memRead16RS(u32 mem, u64 *out); +int memRead16RU(u32 mem, u64 *out); +int memRead32(u32 mem, u32 *out); +int memRead32RS(u32 mem, u64 *out); +int memRead32RU(u32 mem, u64 *out); +int memRead64(u32 mem, u64 *out); +int memRead128(u32 mem, u64 *out); +void memWrite8 (u32 mem, u8 value); +void memWrite16(u32 mem, u16 value); +void memWrite32(u32 mem, u32 value); +void memWrite64(u32 mem, u64 value); +void memWrite128(u32 mem, u64 *value); + +// recMemConstRead8, recMemConstRead16, recMemConstRead32 return 1 if a call was made, 0 otherwise +u8 recMemRead8(); +u16 recMemRead16(); +u32 recMemRead32(); +void recMemRead64(u64 *out); +void recMemRead128(u64 *out); + +// returns 1 if mem should be cleared +void recMemWrite8(); +void recMemWrite16(); +void recMemWrite32(); +void recMemWrite64(); +void recMemWrite128(); + +// VM only functions +#ifdef PCSX2_VIRTUAL_MEM + +void _eeReadConstMem8(int mmreg, u32 mem, int sign); +void _eeReadConstMem16(int mmreg, u32 mem, int sign); +void _eeReadConstMem32(int mmreg, u32 mem); +void _eeReadConstMem128(int mmreg, u32 mem); +void _eeWriteConstMem8(u32 mem, int mmreg); +void _eeWriteConstMem16(u32 mem, int mmreg); +void _eeWriteConstMem32(u32 mem, int mmreg); +void _eeWriteConstMem64(u32 mem, int mmreg); +void _eeWriteConstMem128(u32 mem, int mmreg); +void _eeMoveMMREGtoR(int to, int mmreg); + +// extra ops +void _eeWriteConstMem16OP(u32 mem, int mmreg, int op); +void _eeWriteConstMem32OP(u32 mem, int mmreg, int op); + +int recMemConstRead8(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead16(u32 x86reg, u32 mem, u32 sign); +int recMemConstRead32(u32 x86reg, u32 mem); +void recMemConstRead64(u32 mem, int mmreg); +void recMemConstRead128(u32 mem, int xmmreg); + +int recMemConstWrite8(u32 mem, int mmreg); +int recMemConstWrite16(u32 mem, int mmreg); +int recMemConstWrite32(u32 mem, int mmreg); +int recMemConstWrite64(u32 mem, int mmreg); +int recMemConstWrite128(u32 mem, int xmmreg); + +#else + +#define _eeReadConstMem8 0&& +#define _eeReadConstMem16 0&& +#define _eeReadConstMem32 0&& +#define _eeReadConstMem128 0&& +#define _eeWriteConstMem8 0&& +#define _eeWriteConstMem16 0&& +#define _eeWriteConstMem32 0&& +#define _eeWriteConstMem64 0&& +#define _eeWriteConstMem128 0&& +#define _eeMoveMMREGtoR 0&& + +// extra ops +#define _eeWriteConstMem16OP 0&& +#define _eeWriteConstMem32OP 0&& + +#define recMemConstRead8 0&& +#define recMemConstRead16 0&& +#define recMemConstRead32 0&& +#define recMemConstRead64 0&& +#define recMemConstRead128 0&& + +#define recMemConstWrite8 0&& +#define recMemConstWrite16 0&& +#define recMemConstWrite32 0&& +#define recMemConstWrite64 0&& +#define recMemConstWrite128 0&& + +#endif + +#endif diff --git a/pcsx2/Misc.c b/pcsx2/Misc.c new file mode 100644 index 0000000..f21a6ff --- /dev/null +++ b/pcsx2/Misc.c @@ -0,0 +1,1108 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "CDVDisodrv.h" +#include "VUmicro.h" +#ifdef _WIN32 +#include "RDebug/deci2.h" +#endif + +#include "VU.h" +#include "iCore.h" +#include "iVUzerorec.h" + +#include "GS.h" + +u32 dwSaveVersion = 0x7a30000e; +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; +extern int g_psxWriteOk; + +PcsxConfig Config; +u32 BiosVersion; +char CdromId[12]; + +char *LabelAuthors = { N_( + "PCSX2 a PS2 emulator\n\n" + "written by:\n" + "saqib, refraction, zerofrog,\n" + "shadow, linuzappz, florin,\n" + "nachbrenner, auMatt, loser, \n" + "alexey silinov, goldfinger,\n" + "\n" + "Webmasters: CKemu, Falcon4ever") +}; + +char *LabelGreets = { N_( + "Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n" + "Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n" + "Seta-San, Skarmeth, blackd_wd, _Demo_\n" + "\n" + "Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n" + "\n" + "Some betatester/support dudes: Belmont, bositman, ChaosCode, CKemu, crushtest," + "falcon4ever, GeneralPlot, jegHegy, parotaku, Prafull, Razorblade, Rudy_X, Seta-san") +}; + +static struct { + char *name; + u32 size; +} ioprps[]={ + {"IOPRP14", 43845}, + {"IOPRP142", 48109}, + {"IOPRP143", 58317}, + {"IOPRP144", 58525}, + {"IOPRP15", 82741}, + {"IOPRP151", 82917}, + {"IOPRP153", 82949}, + {"IOPRP16", 91909}, + {"IOPRP165", 98901}, + {"IOPRP20", 109809}, + {"IOPRP202", 110993}, + {"IOPRP205", 119797}, + {"IOPRP21", 126857}, + {"IOPRP211", 129577}, + {"IOPRP213", 129577}, + {"IOPRP214", 140945}, + {"IOPRP22", 199257}, + {"IOPRP221", 196937}, + {"IOPRP222", 198233}, + {"IOPRP224", 201065}, + {"IOPRP23", 230329}, + {"IOPRP234", 247641}, + {"IOPRP24", 251065}, + {"IOPRP241", 251049}, + {"IOPRP242", 252409}, + {"IOPRP243", 253201}, + {"IOPRP250", 264897}, + {"IOPRP252", 265233}, + {"IOPRP253", 267217}, + {"IOPRP254", 264449}, + {"IOPRP255", 264449}, + {"IOPRP260", 248945}, + {"IOPRP270", 249121}, + {"IOPRP271", 266817}, + {"IOPRP280", 269889}, + {"IOPRP300", 275345}, + {"DNAS280", 272753}, + {"DNAS270", 251729}, + {"DNAS271", 268977}, + {"DNAS300", 278641}, + {"DNAS280", 272705}, + {"DNAS255", 264945}, + {NULL, 0} +}; + +void GetRPCVersion(char *ioprp, char *rpcver){ + char *p=ioprp; int i; + struct TocEntry te; + + if (p && (CDVD_findfile(p+strlen("cdromN:"), &te) != -1)){ + for (i=0; ioprps[i].size>0; i++) + if (te.fileSize==ioprps[i].size) + break; + if (ioprps[i].size>0) + p=ioprps[i].name; + } + if (p && (p=strstr(p, "IOPRP")+strlen("IOPRP"))){ + for (i=0;(i<4) && p && (*p>='0') && (*p<='9');i++, p++) rpcver[i]=*p; + for ( ; i<4 ;i++ ) rpcver[i]='0'; + } +} + +u32 GetBiosVersion() { + unsigned int fileOffset=0; + char *ROMVER; + char vermaj[8]; + char vermin[8]; + struct romdir *rd; + u32 version; + int i; + + for (i=0; i<512*1024; i++) { + rd = (struct romdir*)&psRu8(i); + if (strncmp(rd->fileName, "RESET", 5) == 0) + break; /* found romdir */ + } + if (i == 512*1024) return -1; + + while(strlen(rd->fileName) > 0){ + if (strcmp(rd->fileName, "ROMVER") == 0){ // found romver + ROMVER = &psRs8(fileOffset); + + strncpy(vermaj, ROMVER+ 0, 2); vermaj[2] = 0; + strncpy(vermin, ROMVER+ 2, 2); vermin[2] = 0; + version = strtol(vermaj, (char**)NULL, 0) << 8; + version|= strtol(vermin, (char**)NULL, 0); + + return version; + } + + if ((rd->fileSize % 0x10)==0) + fileOffset += rd->fileSize; + else + fileOffset += (rd->fileSize + 0x10) & 0xfffffff0; + + rd++; + } + + return -1; +} + +//2002-09-22 (Florin) +int IsBIOS(char *filename, char *description){ + struct stat buf; + char Bios[260], ROMVER[14+1], zone[12+1]; + FILE *fp; + unsigned int fileOffset=0, found=FALSE; + struct romdir rd; + + strcpy(Bios, Config.BiosDir); + strcat(Bios, filename); + + if (stat(Bios, &buf) == -1) return FALSE; + + fp = fopen(Bios, "rb"); + if (fp == NULL) return FALSE; + + while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1)) + if (strcmp(rd.fileName, "RESET") == 0) + break; /* found romdir */ + + if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) { + fclose(fp); + return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img + } + + while(strlen(rd.fileName) > 0){ + if (strcmp(rd.fileName, "ROMVER") == 0){ // found romver + unsigned int filepos=ftell(fp); + fseek(fp, fileOffset, SEEK_SET); + if (fread(&ROMVER, 14, 1, fp) == 0) break; + fseek(fp, filepos, SEEK_SET);//go back + + switch(ROMVER[4]){ + case 'T':sprintf(zone, "T10K "); break; + case 'X':sprintf(zone, "Test ");break; + case 'J':sprintf(zone, "Japan "); break; + case 'A':sprintf(zone, "USA "); break; + case 'E':sprintf(zone, "Europe"); break; + case 'H':sprintf(zone, "HK "); break; + case 'P':sprintf(zone, "Free "); break; + case 'C':sprintf(zone, "China "); break; + default: sprintf(zone, "%c ",ROMVER[4]); break;//shoudn't show + } + sprintf(description, "%s vXX.XX(XX/XX/XXXX) %s", zone, + ROMVER[5]=='C'?"Console":ROMVER[5]=='D'?"Devel":""); + strncpy(description+ 8, ROMVER+ 0, 2);//ver major + strncpy(description+11, ROMVER+ 2, 2);//ver minor + strncpy(description+14, ROMVER+12, 2);//day + strncpy(description+17, ROMVER+10, 2);//month + strncpy(description+20, ROMVER+ 6, 4);//year + found = TRUE; + } + + if ((rd.fileSize % 0x10)==0) + fileOffset += rd.fileSize; + else + fileOffset += (rd.fileSize + 0x10) & 0xfffffff0; + + if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break; + } + fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize; + + fclose(fp); + + if (found) { + char percent[6]; + + if (buf.st_size<(int)fileOffset){ + sprintf(percent, " %d%%", buf.st_size*100/(int)fileOffset); + strcat(description, percent);//we force users to have correct bioses, + //not that lame scph10000 of 513KB ;-) + } + return TRUE; + } + + return FALSE; //fail quietly +} + +// LOAD STUFF + +#define ISODCL(from, to) (to - from + 1) + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [1]; +}; + +#define READTRACK(lsn) \ + if (CDVDreadTrack(lsn, CDVD_MODE_2352) == -1) return -1; \ + buf = CDVDgetBuffer(); if (buf == NULL) return -1; + +int LoadCdrom() { + return 0; +} + +int CheckCdrom() { + u8 *buf; + + READTRACK(16); + strncpy(CdromId, (char*)buf+52, 10); + + return 0; +} + +int GetPS2ElfName(char *name){ + FILE *fp; + int f; + char buffer[256];//if a file is longer...it should be shorter :D + char *pos; + static struct TocEntry tocEntry; + int i; + + CDVDFS_init(); + + // check if the file exists + if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){ + SysPrintf("SYSTEM.CNF not found\n"); + return 0;//could not find; not a PS/PS2 cdvd + } + + f=CDVDFS_open("SYSTEM.CNF;1", 1); + CDVDFS_read(f, buffer, 256); + CDVDFS_close(f); + + buffer[tocEntry.fileSize]='\0'; + +// SysPrintf( +// "---------------------SYSTEM.CNF---------------------\n" +// "%s" +// "----------------------------------------------------\n", buffer); + pos=strstr(buffer, "BOOT2"); + if (pos==NULL){ + pos=strstr(buffer, "BOOT"); + if (pos==NULL) { + SysPrintf("This is not a PS2 game!\n"); + return 0; + } + return 1; + } + pos+=strlen("BOOT2"); + while (pos && *pos && pos<=&buffer[255] + && (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z')) + pos++; + if (!pos || *pos==0) + return 0; + + sscanf(pos, "%s", name); + //SysPrintf("ELF name: '%s'\n", name); + + if (strncmp("cdrom0:\\", name, 8) == 0) { + strncpy(CdromId, name+8, 11); CdromId[11] = 0; + } + +// inifile_read(CdromId); + + fp = fopen("System.map", "r"); + if (fp) { + u32 addr; + + SysPrintf("Loading System.map\n", fp); + while (!feof(fp)) { + fseek(fp, 8, SEEK_CUR); + buffer[0] = '0'; buffer[1] = 'x'; + for (i=2; i<10; i++) buffer[i] = fgetc(fp); buffer[i] = 0; + addr = strtoul(buffer, (char**)NULL, 0); + fseek(fp, 3, SEEK_CUR); + for (i=0; i<256; i++) { + buffer[i] = fgetc(fp); + if (buffer[i] == '\n' || buffer[i] == 0) break; + } + if (buffer[i] == 0) break; + buffer[i] = 0; + + disR5900AddSym(addr, buffer); + } + fclose(fp); + } + + return 2; +} + +/*#define PSX_EXE 1 +#define CPE_EXE 2 +#define COFF_EXE 3 +#define INVALID_EXE 4 + +static int PSXGetFileType(FILE *f) { + unsigned long current; + unsigned long mybuf[2048]; + EXE_HEADER *exe_hdr; + FILHDR *coff_hdr; + + current = ftell(f); + fseek(f,0L,SEEK_SET); + fread(mybuf,2048,1,f); + fseek(f,current,SEEK_SET); + + exe_hdr = (EXE_HEADER *)mybuf; + if (memcmp(exe_hdr->id,"PS-X EXE",8)==0) + return PSX_EXE; + + if (mybuf[0]=='C' && mybuf[1]=='P' && mybuf[2]=='E') + return CPE_EXE; + + coff_hdr = (FILHDR *)mybuf; + if (coff_hdr->f_magic == 0x0162) + return COFF_EXE; + + return INVALID_EXE; +} + +int Load(char *ExePath) { + FILE *tmpFile; + EXE_HEADER tmpHead; + int type; + + strcpy(CdromId, "SLUS_999.99"); + + tmpFile = fopen(ExePath,"rb"); + if (tmpFile == NULL) { SysMessage("Error opening file: %s", ExePath); return 0; } + + type = PSXGetFileType(tmpFile); + switch (type) { + case PSX_EXE: + fread(&tmpHead,sizeof(EXE_HEADER),1,tmpFile); + fseek(tmpFile, 0x800, SEEK_SET); + fread((void *)PSXM(tmpHead.t_addr), tmpHead.t_size,1,tmpFile); + fclose(tmpFile); + psxRegs.pc = tmpHead.pc0; + psxRegs.GPR.n.gp = tmpHead.gp0; + psxRegs.GPR.n.sp = tmpHead.s_addr; + if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; + break; + case CPE_EXE: + SysMessage("Pcsx found that you wanna use a CPE file. CPE files not support yet"); + break; + case COFF_EXE: + SysMessage("Pcsx found that you wanna use a COFF file.COFF files not support yet"); + break; + case INVALID_EXE: + SysMessage("This file is not a psx file"); + break; + } + return 1; +} +*/ + +u16 logProtocol; +u8 logSource; +int connected=0; + +#define SYNC_LOGGING + +void __Log(char *fmt, ...) { +#ifdef EMU_LOG + va_list list; + static char tmp[2024]; //hm, should be enough + + va_start(list, fmt); +#ifdef _WIN32 + if (connected && logProtocol>=0 && logProtocol<0x10){ + vsprintf(tmp, fmt, list); + sendTTYP(logProtocol, logSource, tmp); + }//else //!!!!! is disabled, so the text goes to ttyp AND log +#endif + { +#ifndef LOG_STDOUT + if (varLog & 0x80000000) { + vsprintf(tmp, fmt, list); + SysPrintf(tmp); + } else if( emuLog != NULL ) { + vfprintf(emuLog, fmt, list); + } +#else //i assume that this will not be used (Florin) + vsprintf(tmp, fmt, list); + SysPrintf(tmp); +#endif + } + va_end(list); +#endif +} + +// STATES + +#define STATE_VERSION "STv6" +const char Pcsx2Header[32] = STATE_VERSION " PCSX2 v" PCSX2_VERSION; + +#define _PS2Esave(type) \ + if (type##freeze(FREEZE_SIZE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + \ + if (type##freeze(FREEZE_SAVE, &fP) == -1) { \ + gzclose(f); \ + return -1; \ + } \ + \ + gzwrite(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + gzwrite(f, fP.data, fP.size); \ + free(fP.data); \ + } + +#define _PS2Eload(type) \ + gzread(f, &fP.size, sizeof(fP.size)); \ + if (fP.size) { \ + fP.data = (s8*)malloc(fP.size); \ + if (fP.data == NULL) return -1; \ + gzread(f, fP.data, fP.size); \ + } \ + if (type##freeze(FREEZE_LOAD, &fP) == -1) { \ + /* skip */ \ + /*if (fP.size) free(fP.data); \ + gzclose(f); \ + return -1;*/ \ + } \ + if (fP.size) free(fP.data); + + +extern void gsWaitGS(); + +extern u32 g_nextBranchCycle, g_psxNextBranchCycle; + +int SaveState(char *file) { + + gzFile f; + freezeData fP; + + gsWaitGS(); + + SysPrintf("SaveState: %s\n", file); + f = gzopen(file, "wb"); + if (f == NULL) return -1; + + gzwrite(f, &dwSaveVersion, 4); + + gzwrite(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzwrite(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzwrite(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzwrite(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + + gzwrite(f, PS2MEM_HW, 0x00010000); // hardware memory + + gzwrite(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzwrite(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs] + gzwrite(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzwrite(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzwrite(f, &EEsCycle, sizeof(EEsCycle)); + gzwrite(f, &EEoCycle, sizeof(EEoCycle)); + gzwrite(f, &IOPoCycle, sizeof(IOPoCycle)); + gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + gzwrite(f, s_iLastPERFCycle, sizeof(u32)*2); + gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + //gzwrite(f, (void*)&ipuRegs, sizeof(IPUregisters)); // ipu regs + //hope didn't forgot any cpu.... + + rcntFreeze(f, 1); + gsFreeze(f, 1); + vu0Freeze(f, 1); + vu1Freeze(f, 1); + vif0Freeze(f, 1); + vif1Freeze(f, 1); + sifFreeze(f, 1); + ipuFreeze(f, 1); + + // iop now + gzwrite(f, psxM, 0x00200000); // 2 MB main memory + //gzwrite(f, psxP, 0x00010000); // pralell memory + gzwrite(f, psxH, 0x00010000); // hardware memory + //gzwrite(f, psxS, 0x00010000); // sif memory + + sioFreeze(f, 1); + cdrFreeze(f, 1); + cdvdFreeze(f, 1); + psxRcntFreeze(f, 1); + //mdecFreeze(f, 1); + sio2Freeze(f, 1); + + SysPrintf("Saving GS\n"); + _PS2Esave(GS); + SysPrintf("Saving SPU2\n"); + _PS2Esave(SPU2); + SysPrintf("Saving DEV9\n"); + _PS2Esave(DEV9); + SysPrintf("Saving USB\n"); + _PS2Esave(USB); + SysPrintf("Saving ok\n"); + + gzclose(f); + + return 0; +} + +extern u32 dumplog; +u32 s_vucount=0; + +int LoadState(char *file) { + + gzFile f; + freezeData fP; + int i; + u32 OldProtect; + u32 dwVer; + +#ifdef _DEBUG + s_vucount = 0; + //dumplog |= 2; +#endif + + SysPrintf("LoadState: %s\n", file); + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, &dwVer, 4); + + if( dwVer != dwSaveVersion ) { + + if( dwVer != 0x7a30000d ) { + gzclose(f); + SysPrintf("Save state wrong version\n"); + return 0; + } + } + + // stop and reset the system first + gsWaitGS(); + + for (i=0; i<48; i++) ClearTLB(i); + + Cpu->Reset(); +#ifndef PCSX2_NORECBUILD + recResetVU0(); + recResetVU1(); +#endif + psxCpu->Reset(); + + SysPrintf("Loading memory\n"); + +#ifdef PCSX2_VIRTUAL_MEM + // make sure can write + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect); +#endif + + gzread(f, PS2MEM_BASE, 0x02000000); // 32 MB main memory + gzread(f, PS2MEM_ROM, 0x00400000); // 4 mb rom memory + gzread(f, PS2MEM_ROM1,0x00040000); // 256kb rom1 memory + gzread(f, PS2MEM_SCRATCH, 0x00004000); // scratch pad + +#ifdef PCSX2_VIRTUAL_MEM + VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect); + VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect); +#endif + + gzread(f, PS2MEM_HW, 0x00010000); // hardware memory + + SysPrintf("Loading structs\n"); + gzread(f, (void*)&cpuRegs, sizeof(cpuRegs)); // cpu regs + COP0 + gzread(f, (void*)&psxRegs, sizeof(psxRegs)); // iop regs + gzread(f, (void*)&fpuRegs, sizeof(fpuRegs)); // fpu regs + gzread(f, (void*)&tlb, sizeof(tlb)); // tlbs + gzread(f, &EEsCycle, sizeof(EEsCycle)); + gzread(f, &EEoCycle, sizeof(EEoCycle)); + gzread(f, &IOPoCycle, sizeof(IOPoCycle)); + gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle)); + gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle)); + gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle)); + if( dwVer >= 0x7a30000e ) { + gzread(f, s_iLastPERFCycle, sizeof(u32)*2); + } + gzread(f, &g_psxWriteOk, sizeof(g_psxWriteOk)); + + rcntFreeze(f, 0); + gsFreeze(f, 0); + vu0Freeze(f, 0); + vu1Freeze(f, 0); + vif0Freeze(f, 0); + vif1Freeze(f, 0); + sifFreeze(f, 0); + ipuFreeze(f, 0); + + // iop now + SysPrintf("Loading iop mem\n"); + gzread(f, psxM, 0x00200000); // 2 MB main memory + //gzread(f, psxP, 0x00010000); // pralell memory + gzread(f, psxH, 0x00010000); // hardware memory + //gzread(f, psxS, 0x00010000); // sif memory + + SysPrintf("Loading iop stuff\n"); + sioFreeze(f, 0); + cdrFreeze(f, 0); + cdvdFreeze(f, 0); + psxRcntFreeze(f, 0); + //mdecFreeze(f, 0); + sio2Freeze(f, 0); + + SysPrintf("Loading GS\n"); + _PS2Eload(GS); + SysPrintf("Loading SPU2\n"); + _PS2Eload(SPU2); + SysPrintf("Loading DEV9\n"); + _PS2Eload(DEV9); + SysPrintf("Loading USB\n"); + _PS2Eload(USB); + + SysPrintf("Loading ok\n"); + + gzclose(f); + + //dumplog |= 4; + WriteCP0Status(cpuRegs.CP0.n.Status.val); + for (i=0; i<48; i++) WriteTLB(i); + + return 0; +} + +#ifdef PCSX2_DEVBUILD + +int SaveGSState(char *file) +{ + if( g_SaveGSStream ) return -1; + + SysPrintf("SaveGSState: %s\n", file); + g_fGSSave = gzopen(file, "wb"); + if (g_fGSSave == NULL) return -1; + + g_SaveGSStream = 1; + g_nLeftGSFrames = 2; + + gzwrite(g_fGSSave, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames)); + + return 0; +} + +extern long pDsp; +int LoadGSState(char *file) +{ + int ret; + char strfile[255]; + gzFile f; + freezeData fP; + + f = gzopen(file, "rb"); + if (f == NULL) { + + sprintf(strfile, "sstates/%s", file); + // try prefixing with sstates + f = gzopen(strfile, "rb"); + if( f == NULL ) { + SysPrintf("Failed to find gs state\n"); + return -1; + } + + file = strfile; + } + + SysPrintf("LoadGSState: %s\n", file); + + GSirqCallback(gsIrq); + ret = GSopen(&pDsp, "PCSX2", 0); + if (ret != 0) { + SysMessage (_("Error Opening GS Plugin")); + return -1; + } + + ret = PAD1open((void *)&pDsp); + + gzread(f, &g_nLeftGSFrames, sizeof(g_nLeftGSFrames)); + + gsFreeze(f, 0); + _PS2Eload(GS); + + RunGSState(f); + gzclose(f); + + GSclose(); + PAD1close(); + + return 0; +} + +#endif + +int CheckState(char *file) { + gzFile f; + char header[32]; + + f = gzopen(file, "rb"); + if (f == NULL) return -1; + + gzread(f, header, 32); + + gzclose(f); + + if (strncmp(STATE_VERSION " PCSX2", header, 10)) return -1; + + return 0; +} + + +typedef struct { + char id[8]; + char name[64]; +} LangDef; + +LangDef sLangs[] = { + { "ar_AR", N_("Arabic") }, + { "bg_BG", N_("Bulgarian") }, + { "ca_CA", N_("Catalan") }, + { "cz_CZ", N_("Czech") }, + { "du_DU", N_("Dutch") }, + { "de_DE", N_("German") }, + { "el_EL", N_("Greek") }, + { "en_US", N_("English") }, + { "fr_FR", N_("French") }, + { "hb_HB" , N_("Hebrew") }, + { "hu_HU", N_("Hungarian") }, + { "it_IT", N_("Italian") }, + { "ja_JA", N_("Japanese") }, + { "pe_PE", N_("Persian") }, + { "po_PO", N_("Portuguese") }, + { "po_BR", N_("Portuguese BR") }, + { "pl_PL" , N_("Polish") }, + { "ro_RO", N_("Romanian") }, + { "ru_RU", N_("Russian") }, + { "es_ES", N_("Spanish") }, + { "sh_SH" , N_("S-Chinese") }, + { "sw_SW", N_("Swedish") }, + { "tc_TC", N_("T-Chinese") }, + { "tr_TR", N_("Turkish") }, + { "", "" }, +}; + + +char *ParseLang(char *id) { + int i=0; + + while (sLangs[i].id[0] != 0) { + if (!strcmp(id, sLangs[i].id)) + return _(sLangs[i].name); + i++; + } + + return id; +} + +#define NUM_STATES 10 +int StatesC = 0; +extern void iDumpRegisters(u32 startpc, u32 temp); +extern void recExecuteVU0Block(void); +extern void recExecuteVU1Block(void); +extern void DummyExecuteVU1Block(void); +extern int LoadConfig(); +extern void SaveConfig(); +extern char strgametitle[256]; + +char* mystrlwr( char* string ) +{ + assert( string != NULL ); + while ( 0 != ( *string++ = (char)tolower( *string ) ) ); + return string; +} + +void ProcessFKeys(int fkey, int shift) +{ + char Text[256]; + int ret; + + assert(fkey >= 1 && fkey <= 12 ); + switch(fkey) { + case 1: + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = SaveState(Text); + break; + case 2: + if( shift ) + StatesC = (StatesC+NUM_STATES-1)%NUM_STATES; + else + StatesC = (StatesC+1)%NUM_STATES; + SysPrintf("*PCSX2*: Selected State %ld\n", StatesC); + if( GSchangeSaveState != NULL ) { + sprintf(Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + GSchangeSaveState(StatesC, Text); + } + break; + case 3: + sprintf (Text, "sstates/%8.8X.%3.3d", ElfCRC, StatesC); + ret = LoadState(Text); + break; + + case 4: + +#ifdef PCSX2_NORECBUILD + SysPrintf("frame skipping only valid for recompiler build\n"); +#else + // cycle + if( shift ) { + // previous + Config.Options = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_VUSKIP)&PCSX2_FRAMELIMIT_MASK); + } + else { + // next + Config.Options = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_LIMIT)&PCSX2_FRAMELIMIT_MASK); + } + + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_NORMAL: + if( GSsetFrameSkip != NULL ) GSsetFrameSkip(0); + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Normal - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_LIMIT: + if( GSsetFrameSkip != NULL ) GSsetFrameSkip(0); + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Limit - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_SKIP: + Cpu->ExecuteVU1Block = recExecuteVU1Block; + SysPrintf("Frame Skip - Frame Limit Mode Changed\n"); + break; + case PCSX2_FRAMELIMIT_VUSKIP: + SysPrintf("VU Skip - Frame Limit Mode Changed\n"); + break; + } + SaveConfig(); +#endif + break; + // note: VK_F5-VK_F7 are reserved for GS + case 8: + GSmakeSnapshot("snap/"); + break; + +#ifdef PCSX2_DEVBUILD + case 10: + { +#ifdef PCSX2_NORECBUILD + SysPrintf("Block performances times only valid for recompiler builds\n"); +#else + int num; + FILE* f; + BASEBLOCKEX** ppblocks = GetAllBaseBlocks(&num, 0); + + f = fopen("perflog.txt", "w"); + while(num-- > 0 ) { + if( ppblocks[0]->visited > 0 ) { + fprintf(f, "%u %u %u %u\n", ppblocks[0]->startpc, (u32)(ppblocks[0]->ltime.QuadPart / ppblocks[0]->visited), ppblocks[0]->visited, ppblocks[0]->size); + } + ppblocks[0]->visited = 0; + ppblocks[0]->ltime.QuadPart = 0; + ppblocks++; + } + fclose(f); + SysPrintf("perflog.txt written\n"); +#endif + break; + } + + case 11: + if( CHECK_MULTIGS ) { + SysPrintf("Cannot make gsstates in MTGS mode\n"); + } + else { + if( strgametitle[0] != 0 ) { + // only take the first two words + char name[255], temptitle[255], *tok; + sprintf(temptitle, "%s", strgametitle); + tok = strtok(strgametitle, " "); + sprintf(name, "%s_", mystrlwr(tok)); + tok = strtok(NULL, " "); + if( tok != NULL ) strcat(name, tok); + + sprintf(Text, "sstates/%s.%d.gs", name, StatesC); + } + else + sprintf(Text, "sstates/%8.8X.%d.gs", ElfCRC, StatesC); + + SaveGSState(Text); + } + break; + + case 12: +#ifndef PCSX2_NORECBUILD + iDumpRegisters(cpuRegs.pc, 0); + SysPrintf("hardware registers dumped EE:%x, IOP:%x\n", cpuRegs.pc, psxRegs.pc); +#endif + break; +#endif + } +} + +void injectIRX(char *filename){ + struct stat buf; + char path[260], name[260], *p, *q; + struct romdir *rd; + int iROMDIR=-1, iIOPBTCONF=-1, iBLANK=-1, i, filesize; + FILE *fp; + + strcpy(name, filename); + for (i=0; name[i] && name[i]!='.' && i<10; i++) name[i]=toupper(name[i]);name[i]=0; + + //phase 1: find ROMDIR in bios + for (p=(char*)PS2MEM_ROM; p<(char*)PS2MEM_ROM+0x80000; p++) + if (strncmp(p, "RESET", 5)==0) + break; + rd=(struct romdir*)p; + + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, name, strlen(name))==0)break; + if (rd[i].fileName[0])return;//already in;) + + //phase 2: make room in IOPBTCONF & ROMDIR + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, "ROMDIR", 6)==0)iROMDIR=i; + for (i=0; rd[i].fileName[0]; i++)if (strncmp(rd[i].fileName, "IOPBTCONF", 9)==0)iIOPBTCONF=i; + + for (i=0; rd[i].fileName[0]; i++)if (rd[i].fileName[0]=='-')break; iBLANK=i; + rd[iBLANK].fileSize-=DIRENTRY_SIZE+DIRENTRY_SIZE; + p=(char*)PS2MEM_ROM;for (i=0; iq){*((u64*)p)=*((u64*)p-4);*((u64*)p+1)=*((u64*)p-3);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iIOPBTCONF].fileSize+=DIRENTRY_SIZE; + + q=(char*)PS2MEM_ROM;for (i=0; i<=iROMDIR; i++) q+=(rd[i].fileSize+0xF)&(~0xF); + while (p >q){*((u64*)p)=*((u64*)p-2);*((u64*)p+1)=*((u64*)p-1);p-=DIRENTRY_SIZE;} + *((u64*)p)=*((u64*)p+1)=0;p-=DIRENTRY_SIZE;rd[iROMDIR].fileSize+=DIRENTRY_SIZE; + + //phase 3: add the name to the end of IOPBTCONF + p=(char*)PS2MEM_ROM;for (i=0; i +#include + +// compile-time assert +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#ifdef __x86_64__ +#define X86_32CODE(x) +#else +#define X86_32CODE(x) x +#endif + +#define PCSX2_GSMULTITHREAD 1 // uses multithreaded gs +#define PCSX2_DUALCORE 2 // speed up for dual cores +#define PCSX2_FRAMELIMIT 4 // limits frames to normal speeds +#define PCSX2_EEREC 0x10 +#define PCSX2_VU0REC 0x20 +#define PCSX2_VU1REC 0x40 +#define PCSX2_COP2REC 0x80 +#define PCSX2_FORCEABS 0x100 +#define PCSX2_FRAMELIMIT_MASK 0xc00 +#define PCSX2_FRAMELIMIT_NORMAL 0x000 +#define PCSX2_FRAMELIMIT_LIMIT 0x400 +#define PCSX2_FRAMELIMIT_SKIP 0x800 +#define PCSX2_FRAMELIMIT_VUSKIP 0xc00 + +#define CHECK_MULTIGS (Config.Options&PCSX2_GSMULTITHREAD) +#define CHECK_DUALCORE (Config.Options&PCSX2_DUALCORE) +#define CHECK_EEREC (Config.Options&PCSX2_EEREC) +#define CHECK_COP2REC (Config.Options&PCSX2_COP2REC) // goes with ee option +#define CHECK_FORCEABS 1// always on, (Config.Options&PCSX2_FORCEABS) + +#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK) + +//#ifdef PCSX2_DEVBUILD +#define CHECK_VU0REC (Config.Options&PCSX2_VU0REC) +#define CHECK_VU1REC (Config.Options&PCSX2_VU1REC) +//#else +//// force to VU recs all the time +//#define CHECK_VU0REC 1 +//#define CHECK_VU1REC 1 +// +//#endif + +typedef struct { + char Bios[256]; + char GS[256]; + char PAD1[256]; + char PAD2[256]; + char SPU2[256]; + char CDVD[256]; + char DEV9[256]; + char USB[256]; + char FW[256]; + char Mcd1[256]; + char Mcd2[256]; + char PluginsDir[256]; + char BiosDir[256]; + char Lang[256]; + u32 Options; // PCSX2_X options + int PsxOut; + int PsxType; + int Cdda; + int Mdec; + int Patch; + int ThPriority; + int SafeCnts; +} PcsxConfig; + +extern PcsxConfig Config; +extern u32 BiosVersion; +extern char CdromId[12]; + +#define gzfreeze(ptr, size) \ + if (Mode == 1) gzwrite(f, ptr, size); \ + else if (Mode == 0) gzread(f, ptr, size); + +#define gzfreezel(ptr) gzfreeze(ptr, sizeof(ptr)) + +int LoadCdrom(); +int CheckCdrom(); +int GetPS2ElfName(char*); + +extern char *LabelAuthors; +extern char *LabelGreets; +int SaveState(char *file); +int LoadState(char *file); +int CheckState(char *file); + +int SaveGSState(char *file); +int LoadGSState(char *file); + +char *ParseLang(char *id); +void ProcessFKeys(int fkey, int shift); // processes fkey related commands value 1-12 + +#ifdef _WIN32 + +void ListPatches (HWND hW); +int ReadPatch (HWND hW, char fileName[1024]); +char * lTrim (char *s); +BOOL Save_Patch_Proc( char * filename ); + +#else + +// functions that linux lacks +#define Sleep(seconds) usleep(1000*(seconds)) + +#include + +extern __forceinline u32 timeGetTime() +{ + struct timeb t; + ftime(&t); + return (u32)(t.time*1000+t.millitm); +} + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define BOOL int + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +#ifndef strnicmp +#define strnicmp strncasecmp +#endif + +#ifndef stricmp +#define stricmp strcasecmp +#endif + +#endif + +#define DIRENTRY_SIZE 16 + +#if defined(_MSC_VER) +#pragma pack(1) +#endif + +struct romdir{ + char fileName[10]; + u16 extInfoSize; + u32 fileSize; +#if defined(_MSC_VER) +}; //+22 +#else +} __attribute__((packed)); +#endif + +u32 GetBiosVersion(); +int IsBIOS(char *filename, char *description); + +// check to see if needs freezing +#ifdef PCSX2_NORECBUILD +#define FreezeMMXRegs(save) +#define FreezeXMMRegs(save) +#else +void FreezeXMMRegs_(int save); +extern u32 g_EEFreezeRegs; +#define FreezeXMMRegs(save) if( g_EEFreezeRegs ) { FreezeXMMRegs_(save); } + +#ifndef __x86_64__ +void FreezeMMXRegs_(int save); +#define FreezeMMXRegs(save) if( g_EEFreezeRegs ) { FreezeMMXRegs_(save); } +#else +#define FreezeMMXRegs(save) +#endif + +#endif + +// define a PCS2 specific memcpy and make sure it is used all in real-time code +#if _MSC_VER >= 1400 // vs2005+ uses xmm/mmx in memcpy +__forceinline void memcpy_pcsx2(void* dest, const void* src, size_t n) +{ + //FreezeMMXRegs(1); // mmx not used + FreezeXMMRegs(1); + memcpy(dest, src, n); + // have to be unfroze by parent call! +} +#else +#define memcpy_pcsx2 memcpy +#endif + +#ifdef PCSX2_NORECBUILD +#define memcpy_fast memcpy +#else + +#if defined(_WIN32) && !defined(__x86_64__) +// faster memcpy +void * memcpy_amd_(void *dest, const void *src, size_t n); +#define memcpy_fast memcpy_amd_ +#else +// for now disable linux fast memcpy +#define memcpy_fast memcpy_pcsx2 +#endif + +#endif + +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize); +void memxor_mmx(void* dst, const void* src1, int cmpsize); + +#ifdef _MSC_VER +#pragma pack() +#endif + +void __Log(char *fmt, ...); +void injectIRX(char *filename); + +#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) + +// declare linux equivalents +extern __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align) +{ + assert( align < 0x10000 ); + char* p = (char*)malloc(size+align); + int off = 2+align - ((int)(uptr)(p+2) % align); + + p += off; + *(u16*)(p-2) = off; + + return p; +} + +extern __forceinline void pcsx2_aligned_free(void* pmem) +{ + if( pmem != NULL ) { + char* p = (char*)pmem; + free(p - (int)*(u16*)(p-2)); + } +} + +#define _aligned_malloc pcsx2_aligned_malloc +#define _aligned_free pcsx2_aligned_free + +#endif + +// cross-platform atomic operations +#if defined (_WIN32) + +#ifndef __x86_64__ // for some reason x64 doesn't like this +LONG __cdecl _InterlockedIncrement(LONG volatile *Addend); +LONG __cdecl _InterlockedDecrement(LONG volatile *Addend); +LONG __cdecl _InterlockedCompareExchange(LPLONG volatile Dest, LONG Exchange, LONG Comp); +LONG __cdecl _InterlockedExchange(LPLONG volatile Target, LONG Value); +PVOID __cdecl _InterlockedExchangePointer(PVOID volatile* Target, PVOID Value); + +LONG __cdecl _InterlockedExchangeAdd(LPLONG volatile Addend, LONG Value); +LONG __cdecl _InterlockedAnd(LPLONG volatile Addend, LONG Value); +#endif + +#pragma intrinsic (_InterlockedExchange) +#define InterlockedExchange _InterlockedExchange + +#pragma intrinsic (_InterlockedExchangeAdd) +#define InterlockedExchangeAdd _InterlockedExchangeAdd + +#else + +typedef void* PVOID; + +/*inline unsigned long _Atomic_swap(unsigned long * __p, unsigned long __q) { + # if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) + return test_and_set(__p, __q); + # else + return __test_and_set(__p, (unsigned long)__q); + # endif + }*/ + +extern __forceinline void InterlockedExchangePointer(PVOID volatile* Target, void* Value) +{ +#ifdef __x86_64__ + __asm__ __volatile__(".intel_syntax\n" + "lock xchg [%0], %%rax\n" + ".att_syntax\n" : : "r"(Target), "a"(Value) : "memory" ); +#else + __asm__ __volatile__(".intel_syntax\n" + "lock xchg [%0], %%eax\n" + ".att_syntax\n" : : "r"(Target), "a"(Value) : "memory" ); +#endif +} + +extern __forceinline long InterlockedExchange(long volatile* Target, long Value) +{ + __asm__ __volatile__(".intel_syntax\n" + "lock xchg [%0], %%eax\n" + ".att_syntax\n" : : "r"(Target), "a"(Value) : "memory" ); +} + +extern __forceinline long InterlockedExchangeAdd(long volatile* Addend, long Value) +{ + __asm__ __volatile__(".intel_syntax\n" + "lock xadd [%0], %%eax\n" + ".att_syntax\n" : : "r"(Addend), "a"(Value) : "memory" ); +} + +#endif + +//#pragma intrinsic (_InterlockedExchange64) +//#define InterlockedExchange64 _InterlockedExchange64 +// +//#pragma intrinsic (_InterlockedExchangeAdd64) +//#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64 + +//#ifdef __x86_64__ +//#define InterlockedExchangePointerAdd InterlockedExchangeAdd64 +//#else +//#define InterlockedExchangePointerAdd InterlockedExchangeAdd +//#endif + +#endif /* __MISC_H__ */ + diff --git a/pcsx2/PS2Edefs.h b/pcsx2/PS2Edefs.h new file mode 100644 index 0000000..702dce6 --- /dev/null +++ b/pcsx2/PS2Edefs.h @@ -0,0 +1,834 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// call to give a hint to the PAD plugin to query for the keyboard state. A +// good plugin will query the OS for keyboard state ONLY in this function. +// This function is necessary when multithreading because otherwise +// the PAD plugin can get into deadlocks with the thread that really owns +// the window (and input). Note that PADupdate can be called from a different +// thread than the other functions, so mutex or other multithreading primitives +// have to be added to maintain data integrity. +void CALLBACK PADupdate(int pad); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); + +// all addresses passed by dma will be pointers to the array starting at baseaddr +// This function is necessary to successfully save and reload the spu2 state +void CALLBACK SPU2setDMABaseAddr(uptr baseaddr); + +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits) +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); +typedef void (CALLBACK* _PADupdate)(int pad); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2setDMABaseAddr)(uptr baseaddr); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgetLastTag GSgetLastTag; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; +_PADupdate PAD1update; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; +_PADupdate PAD2update; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2setDMABaseAddr SPU2setDMABaseAddr; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/pcsx2/PS2Etypes.h b/pcsx2/PS2Etypes.h new file mode 100644 index 0000000..1ad73e2 --- /dev/null +++ b/pcsx2/PS2Etypes.h @@ -0,0 +1,76 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif // _MSC_VER + +#if defined(__x86_64__) +typedef u64 uptr; +typedef s64 sptr; +#else +typedef u32 uptr; +typedef s32 sptr; +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/pcsx2/Patch.c b/pcsx2/Patch.c new file mode 100644 index 0000000..b72e2f3 --- /dev/null +++ b/pcsx2/Patch.c @@ -0,0 +1,415 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// +// Includes +// +#include +#include + +#include "PsxCommon.h" + +#ifdef _WIN32 +#include "windows/cheats/cheats.h" +#endif + +#include "Patch.h" + +int g_ZeroGSOptions=0; + +// +// Variables +// +PatchTextTable commands[] = +{ + { "comment", 1, patchFunc_comment }, + { "gametitle", 2, patchFunc_gametitle }, + { "patch", 3, patchFunc_patch }, + { "fastmemory", 4, patchFunc_fastmemory }, // enable for faster but bugger mem (mvc2 is faster) + { "roundmode", 5, patchFunc_roundmode }, // changes rounding mode for floating point + // syntax: roundmode=X,Y + // possible values for X,Y: NEAR, DOWN, UP, CHOP + // X - EE rounding mode (default is NEAR) + // Y - VU rounding mode (default is CHOP) + { "zerogs", 6, patchFunc_zerogs }, // zerogs=hex + { "", 0, NULL } +}; + +PatchTextTable dataType[] = +{ + { "byte", 1, NULL }, + { "short", 2, NULL }, + { "word", 3, NULL }, + { "double", 4, NULL }, + { "", 0, NULL } +}; + +PatchTextTable cpuCore[] = +{ + { "EE", 1, NULL }, + { "IOP", 2, NULL }, + { "", 0, NULL } +}; + +IniPatch patch[ MAX_PATCH ]; +int patchnumber; + + +// +// Function Implementations +// + +int PatchTableExecute( char * text1, char * text2, PatchTextTable * Table ) +{ + int i = 0; + + while ( Table[ i ].text[ 0 ] ) + { + if ( !strcmp( Table[ i ].text, text1 ) ) + { + if ( Table[ i ].func ) + { + Table[ i ].func( text1, text2 ); + } + break; + } + i++; + } + + return Table[ i ].code; +} + +void _applypatch(int place, IniPatch *p) { + if (p->placetopatch != place) return; + + if (p->enabled == 0) return; + + if (p->cpu == 1) { //EE + if (p->type == 1) { //byte + memWrite8(p->addr, (u8)p->data); + } else + if (p->type == 2) { //short + memWrite16(p->addr, (u16)p->data); + } else + if (p->type == 3) { //word + memWrite32(p->addr, (u32)p->data); + } else + if (p->type == 4) { //double + memWrite64(p->addr, p->data); + } + } else + if (p->cpu == 2) { //IOP + if (p->type == 1) { //byte + psxMemWrite8(p->addr, (u8)p->data); + } else + if (p->type == 2) { //short + psxMemWrite16(p->addr, (u16)p->data); + } else + if (p->type == 3) { //word + psxMemWrite32(p->addr, (u32)p->data); + } + } +} + +//this is for apply patches directly to memory +void applypatch(int place) { + int i; + + if (place == 0) { + SysPrintf(" patchnumber: %d\n", patchnumber); + } + + for ( i = 0; i < patchnumber; i++ ) { + _applypatch(place, &patch[i]); + } +} + +void patchFunc_comment( char * text1, char * text2 ) +{ + SysPrintf( "comment: %s \n", text2 ); +} + +char strgametitle[256] = {0}; + +void patchFunc_gametitle( char * text1, char * text2 ) +{ + SysPrintf( "gametitle: %s \n", text2 ); +#ifdef _WIN32 + sprintf(strgametitle,"%s",text2); + if (gApp.hConsole) SetConsoleTitle(strgametitle); +#endif +} + +extern int RunExe; + +void patchFunc_patch( char * cmd, char * param ) +{ + //patch=placetopatch,cpucore,address,type,data + char * pText; + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached: %s=%s\n", cmd, param ); + return; + } + + pText = strtok( param, "," ); + pText = param; +// inifile_trim( pText ); + + if(RunExe == 1) patch[ patchnumber ].placetopatch = 1; + else patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].cpu = PatchTableExecute( pText, NULL, cpuCore ); + if ( patch[ patchnumber ].cpu == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%X", &patch[ patchnumber ].addr ); + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + patch[ patchnumber ].type = PatchTableExecute( pText, NULL, dataType ); + if ( patch[ patchnumber ].type == 0 ) + { + SysPrintf( "Unrecognized patch '%s'\n", pText ); + return; + } + + pText = strtok( NULL, "," ); + inifile_trim( pText ); + sscanf( pText, "%I64X", &patch[ patchnumber ].data ); + + patch[ patchnumber ].enabled = 1; + + patchnumber++; +} + +//this routine is for execute the commands of the ini file +void inifile_command( char * cmd ) +{ + int code; + char command[ 256 ]; + char parameter[ 256 ]; + + // extract param part (after '=') + char * pEqual = strchr( cmd, '=' ); + + if ( ! pEqual ) + { + // fastmemory doesn't have = + pEqual = cmd+strlen(cmd); +// SysPrintf( "Ini file ERROR: unknow line: %s \n", cmd ); +// return; + } + + memset( command, 0, sizeof( command ) ); + memset( parameter, 0, sizeof( parameter ) ); + + strncpy( command, cmd, pEqual - cmd ); + strncpy( parameter, pEqual + 1, sizeof( parameter ) ); + + inifile_trim( command ); + inifile_trim( parameter ); + + code = PatchTableExecute( command, parameter, commands ); +} + +void inifile_trim( char * buffer ) +{ + char * pInit = buffer; + char * pEnd = NULL; + + while ( ( *pInit == ' ' ) || ( *pInit == '\t' ) ) //skip space + { + pInit++; + } + if ( ( pInit[ 0 ] == '/' ) && ( pInit[ 1 ] == '/' ) ) //remove comment + { + buffer[ 0 ] = '\0'; + return; + } + pEnd = pInit + strlen( pInit ) - 1; + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + while ( ( *pEnd == '\r' ) || ( *pEnd == '\n' ) || + ( *pEnd == ' ' ) || ( *pEnd == '\t' ) ) + { + pEnd--; + } + if ( pEnd <= pInit ) + { + buffer[ 0 ] = '\0'; + return; + } + memmove( buffer, pInit, pEnd - pInit + 1 ); + buffer[ pEnd - pInit + 1 ] = '\0'; +} + +void inisection_process( FILE * f1 ) +{ + char buffer[ 1024 ]; + while( fgets( buffer, sizeof( buffer ), f1 ) ) + { + inifile_trim( buffer ); + if ( buffer[ 0 ] ) + { + inifile_command( buffer ); + } + } +} + +//this routine is for reading the ini file + +void inifile_read( char * name ) +{ + FILE * f1; + char buffer[ 1024 ]; + + patchnumber = 0; +#ifdef _WIN32 + sprintf( buffer, "patches\\%s.pnach", name ); +#else + sprintf( buffer, "patches/%s.pnach", name ); +#endif + + f1 = fopen( buffer, "rt" ); + +#ifndef _WIN32 + if( !f1 ) { + // try all upper case because linux is case sensitive + char* pstart = buffer+8; + char* pend = buffer+strlen(buffer); + while(pstart != pend ) { + // stop at the first . since we only want to update the hex + if( *pstart == '.' ) + break; + *pstart++ = toupper(*pstart); + } + + f1 = fopen(buffer, "rt"); + } +#endif + + if( !f1 ) + { + SysPrintf( _( "patch file for this game not found. Can't apply any patches\n" )); + return; + } + + inisection_process( f1 ); + + fclose( f1 ); +} + +void resetpatch( void ) +{ + patchnumber = 0; +} + +int AddPatch(int Mode, int Place, int Address, int Size, u64 data) +{ + + if ( patchnumber >= MAX_PATCH ) + { + SysPrintf( "Patch ERROR: Maximum number of patches reached.\n"); + return -1; + } + + if(RunExe == 1) patch[patchnumber].placetopatch = 1; + else patch[patchnumber].placetopatch = Mode; + patch[patchnumber].cpu = Place; + patch[patchnumber].addr=Address; + patch[patchnumber].type=Size; + patch[patchnumber].data = data; + return patchnumber++; +} + +void patchFunc_fastmemory( char * cmd, char * param ) +{ +#ifndef PCSX2_NORECBUILD + // only valid for recompilers + SetFastMemory(1); +#endif +} + +void patchFunc_roundmode( char * cmd, char * param ) +{ + //roundmode = X,Y + int index; + char * pText; + + u32 eetype=0x0000; + u32 vutype=0x6000; + + index = 0; + pText = strtok( param, ", " ); + while(pText != NULL) { + u32 type = 0xffff; + if( stricmp(pText, "near") == 0 ) { + type = 0x0000; + } + else if( stricmp(pText, "down") == 0 ) { + type = 0x2000; + } + else if( stricmp(pText, "up") == 0 ) { + type = 0x4000; + } + else if( stricmp(pText, "chop") == 0 ) { + type = 0x6000; + } + + if( type == 0xffff ) { + printf("bad argument (%s) to round mode! skipping...\n", pText); + break; + } + + if( index == 0 ) eetype=type; + else vutype=type; + + if( index == 1 ) + break; + + index++; + pText = strtok(NULL, ", "); + } + + SetRoundMode(eetype,vutype); +} + +void patchFunc_zerogs(char* cmd, char* param) +{ + sscanf(param, "%x", &g_ZeroGSOptions); +} + +void SetRoundMode(u32 ee, u32 vu) +{ + // don't set a state for interpreter only +#ifndef PCSX2_NORECBUILD + SetCPUState(0x9f80|ee, 0x9f80|vu); +#endif +} diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h new file mode 100644 index 0000000..ea9d2b1 --- /dev/null +++ b/pcsx2/Patch.h @@ -0,0 +1,78 @@ +#ifndef __PATCH_H__ +#define __PATCH_H__ + +// +// Defines +// +#define MAX_PATCH 1024 + +#define IFIS(x,str) if(!strnicmp(x,str,sizeof(str)-1)) + +#define GETNEXT_PARAM() \ + while ( *param && ( *param != ',' ) ) param++; \ + if ( *param ) param++; \ + while ( *param && ( *param == ' ' ) ) param++; \ + if ( *param == 0 ) { SysPrintf( _( "Not enough params for inicommand\n" ) ); return; } + +// +// Typedefs +// +typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 ); + +typedef struct +{ + char * text; + int code; + PATCHTABLEFUNC func; +} PatchTextTable; + +typedef struct +{ + int enabled; + int group; + int type; + int cpu; + int placetopatch; + u32 addr; + u64 data; +} IniPatch; + +// +// Function prototypes +// +void patchFunc_comment( char * text1, char * text2 ); +void patchFunc_gametitle( char * text1, char * text2 ); +void patchFunc_patch( char * text1, char * text2 ); +void patchFunc_fastmemory( char * text1, char * text2 ); +void patchFunc_roundmode( char * text1, char * text2 ); +void patchFunc_zerogs( char * text1, char * text2 ); + +void inifile_trim( char * buffer ); + +// +// Variables +// +extern PatchTextTable commands[]; + +extern PatchTextTable dataType[]; + +extern PatchTextTable cpuCore[]; + +extern IniPatch patch[ MAX_PATCH ]; +extern int patchnumber; + + +void applypatch( int place ); +void inifile_read( char * name ); +void inifile_command( char * cmd ); +void resetpatch( void ); + +int AddPatch(int Mode, int Place, int Address, int Size, u64 data); + +void SetFastMemory(int); // iR5900LoadStore.c +void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR); + +void SetRoundMode(u32 ee, u32 vu); + +#endif /* __PATCH_H__ */ + diff --git a/pcsx2/Plugins.c b/pcsx2/Plugins.c new file mode 100644 index 0000000..6d483b6 --- /dev/null +++ b/pcsx2/Plugins.c @@ -0,0 +1,653 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "GS.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#endif + +#define CheckErr(func) \ + err = SysLibError(); \ + if (err != NULL) { SysMessage (_("%s: Error loading %s: %s"), filename, func, err); return -1; } + +#define LoadSym(dest, src, name, checkerr) \ + dest = (src) SysLoadSym(drv, name); if (checkerr == 1) CheckErr(name); \ + if (checkerr == 2) { err = SysLibError(); if (err != NULL) errval = 1; } + +#define TestPS2Esyms(type) { \ + _PS2EgetLibVersion2 PS2EgetLibVersion2; \ + SysLoadSym(drv, "PS2EgetLibType"); CheckErr("PS2EgetLibType"); \ + PS2EgetLibVersion2 = (_PS2EgetLibVersion2) SysLoadSym(drv, "PS2EgetLibVersion2"); CheckErr("PS2EgetLibVersion2"); \ + SysLoadSym(drv, "PS2EgetLibName"); CheckErr("PS2EgetLibName"); \ + if( ((PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff) != PS2E_##type##_VERSION) { \ + SysMessage (_("Can't load '%s', wrong PS2E version (%x != %x)"), filename, (PS2EgetLibVersion2(PS2E_LT_##type) >> 16)&0xff, PS2E_##type##_VERSION); return -1; \ + } \ +} + +static char *err; +static int errval; + +void *GSplugin; + +void CALLBACK GS_printf(int timeout, char *fmt, ...) { + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + SysPrintf(msg); +} + +s32 CALLBACK GS_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK GS_keyEvent(keyEvent *ev) {} +void CALLBACK GS_makeSnapshot(char *path) {} +void CALLBACK GS_irqCallback(void (*callback)()) {} +void CALLBACK GS_configure() {} +void CALLBACK GS_about() {} +long CALLBACK GS_test() { return 0; } + +#define LoadGSsym1(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 1); + +#define LoadGSsym0(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); \ + if (GS##dest == NULL) GS##dest = (_GS##dest) GS_##dest; + +#define LoadGSsymN(dest, name) \ + LoadSym(GS##dest, _GS##dest, name, 0); + +int LoadGSplugin(char *filename) { + void *drv; + + GSplugin = SysLoadLibrary(filename); + if (GSplugin == NULL) { SysMessage (_("Could Not Load GS Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = GSplugin; + TestPS2Esyms(GS); + LoadGSsym1(init, "GSinit"); + LoadGSsym1(shutdown, "GSshutdown"); + LoadGSsym1(open, "GSopen"); + LoadGSsym1(close, "GSclose"); + LoadGSsym1(gifTransfer1, "GSgifTransfer1"); + LoadGSsym1(gifTransfer2, "GSgifTransfer2"); + LoadGSsym1(gifTransfer3, "GSgifTransfer3"); + LoadGSsym1(readFIFO, "GSreadFIFO"); + LoadGSsymN(getLastTag, "GSgetLastTag"); + LoadGSsymN(readFIFO2, "GSreadFIFO2"); // optional + LoadGSsym1(vsync, "GSvsync"); + + LoadGSsym0(keyEvent, "GSkeyEvent"); + LoadGSsymN(changeSaveState, "GSchangeSaveState"); + LoadGSsymN(gifSoftReset, "GSgifSoftReset"); + LoadGSsym0(makeSnapshot, "GSmakeSnapshot"); + LoadGSsym0(irqCallback, "GSirqCallback"); + LoadGSsym0(printf, "GSprintf"); + LoadGSsym1(setBaseMem, "GSsetBaseMem"); + LoadGSsymN(setGameCRC, "GSsetGameCRC"); + LoadGSsym1(reset, "GSreset"); + LoadGSsym1(writeCSR, "GSwriteCSR"); + LoadGSsymN(makeSnapshot2,"GSmakeSnapshot2"); + LoadGSsymN(getDriverInfo,"GSgetDriverInfo"); + + LoadGSsymN(setFrameSkip, "GSsetFrameSkip"); + +#ifdef _WIN32 + LoadGSsymN(setWindowInfo,"GSsetWindowInfo"); +#endif + LoadGSsym0(freeze, "GSfreeze"); + LoadGSsym0(configure, "GSconfigure"); + LoadGSsym0(about, "GSabout"); + LoadGSsym0(test, "GStest"); + + return 0; +} + +void *PAD1plugin; + +void CALLBACK PAD1_configure() {} +void CALLBACK PAD1_about() {} +long CALLBACK PAD1_test() { return 0; } + +#define LoadPAD1sym1(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 1); + +#define LoadPAD1sym0(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); \ + if (PAD1##dest == NULL) PAD1##dest = (_PAD##dest) PAD1_##dest; + +#define LoadPAD1symN(dest, name) \ + LoadSym(PAD1##dest, _PAD##dest, name, 0); + +int LoadPAD1plugin(char *filename) { + void *drv; + + PAD1plugin = SysLoadLibrary(filename); + if (PAD1plugin == NULL) { SysMessage (_("Could Not Load PAD1 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD1plugin; + TestPS2Esyms(PAD); + LoadPAD1sym1(init, "PADinit"); + LoadPAD1sym1(shutdown, "PADshutdown"); + LoadPAD1sym1(open, "PADopen"); + LoadPAD1sym1(close, "PADclose"); + LoadPAD1sym1(keyEvent, "PADkeyEvent"); + LoadPAD1sym1(startPoll, "PADstartPoll"); + LoadPAD1sym1(poll, "PADpoll"); + LoadPAD1sym1(query, "PADquery"); + LoadPAD1symN(update, "PADupdate"); + + LoadPAD1symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD1sym0(configure, "PADconfigure"); + LoadPAD1sym0(about, "PADabout"); + LoadPAD1sym0(test, "PADtest"); + + return 0; +} + +void *PAD2plugin; + +void CALLBACK PAD2_configure() {} +void CALLBACK PAD2_about() {} +long CALLBACK PAD2_test() { return 0; } + +#define LoadPAD2sym1(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 1); + +#define LoadPAD2sym0(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); \ + if (PAD2##dest == NULL) PAD2##dest = (_PAD##dest) PAD2_##dest; + +#define LoadPAD2symN(dest, name) \ + LoadSym(PAD2##dest, _PAD##dest, name, 0); + +int LoadPAD2plugin(char *filename) { + void *drv; + + PAD2plugin = SysLoadLibrary(filename); + if (PAD2plugin == NULL) { SysMessage (_("Could Not Load PAD2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = PAD2plugin; + TestPS2Esyms(PAD); + LoadPAD2sym1(init, "PADinit"); + LoadPAD2sym1(shutdown, "PADshutdown"); + LoadPAD2sym1(open, "PADopen"); + LoadPAD2sym1(close, "PADclose"); + LoadPAD2sym1(keyEvent, "PADkeyEvent"); + LoadPAD2sym1(startPoll, "PADstartPoll"); + LoadPAD2sym1(poll, "PADpoll"); + LoadPAD2sym1(query, "PADquery"); + LoadPAD2symN(update, "PADupdate"); + + LoadPAD2symN(gsDriverInfo, "PADgsDriverInfo"); + LoadPAD2sym0(configure, "PADconfigure"); + LoadPAD2sym0(about, "PADabout"); + LoadPAD2sym0(test, "PADtest"); + + return 0; +} + +void *SPU2plugin; + +s32 CALLBACK SPU2_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK SPU2_configure() {} +void CALLBACK SPU2_about() {} +s32 CALLBACK SPU2_test() { return 0; } + +#define LoadSPU2sym1(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 1); + +#define LoadSPU2sym0(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); \ + if (SPU2##dest == NULL) SPU2##dest = (_SPU2##dest) SPU2_##dest; + +#define LoadSPU2symN(dest, name) \ + LoadSym(SPU2##dest, _SPU2##dest, name, 0); + +int LoadSPU2plugin(char *filename) { + void *drv; + + SPU2plugin = SysLoadLibrary(filename); + if (SPU2plugin == NULL) { SysMessage (_("Could Not Load SPU2 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = SPU2plugin; + TestPS2Esyms(SPU2); + LoadSPU2sym1(init, "SPU2init"); + LoadSPU2sym1(shutdown, "SPU2shutdown"); + LoadSPU2sym1(open, "SPU2open"); + LoadSPU2sym1(close, "SPU2close"); + LoadSPU2sym1(write, "SPU2write"); + LoadSPU2sym1(read, "SPU2read"); + LoadSPU2sym1(readDMA4Mem, "SPU2readDMA4Mem"); + LoadSPU2sym1(writeDMA4Mem, "SPU2writeDMA4Mem"); + LoadSPU2sym1(interruptDMA4,"SPU2interruptDMA4"); + LoadSPU2sym1(readDMA7Mem, "SPU2readDMA7Mem"); + LoadSPU2sym1(writeDMA7Mem, "SPU2writeDMA7Mem"); + LoadSPU2sym1(interruptDMA7,"SPU2interruptDMA7"); + LoadSPU2symN(setDMABaseAddr, "SPU2setDMABaseAddr"); + LoadSPU2sym1(ReadMemAddr, "SPU2ReadMemAddr"); + LoadSPU2sym1(WriteMemAddr, "SPU2WriteMemAddr"); + LoadSPU2sym1(irqCallback, "SPU2irqCallback"); + + LoadSPU2sym0(freeze, "SPU2freeze"); + LoadSPU2sym0(configure, "SPU2configure"); + LoadSPU2sym0(about, "SPU2about"); + LoadSPU2sym0(test, "SPU2test"); + LoadSPU2symN(async, "SPU2async"); + + return 0; +} + +void *CDVDplugin; + +void CALLBACK CDVD_configure() {} +void CALLBACK CDVD_about() {} +long CALLBACK CDVD_test() { return 0; } + +#define LoadCDVDsym1(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 1); + +#define LoadCDVDsym0(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + if (CDVD##dest == NULL) CDVD##dest = (_CDVD##dest) CDVD_##dest; + +#define LoadCDVDsymN(dest, name) \ + LoadSym(CDVD##dest, _CDVD##dest, name, 0); \ + +int LoadCDVDplugin(char *filename) { + void *drv; + + CDVDplugin = SysLoadLibrary(filename); + if (CDVDplugin == NULL) { SysMessage (_("Could Not Load CDVD Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = CDVDplugin; + TestPS2Esyms(CDVD); + LoadCDVDsym1(init, "CDVDinit"); + LoadCDVDsym1(shutdown, "CDVDshutdown"); + LoadCDVDsym1(open, "CDVDopen"); + LoadCDVDsym1(close, "CDVDclose"); + LoadCDVDsym1(readTrack, "CDVDreadTrack"); + LoadCDVDsym1(getBuffer, "CDVDgetBuffer"); + LoadCDVDsym1(readSubQ, "CDVDreadSubQ"); + LoadCDVDsym1(getTN, "CDVDgetTN"); + LoadCDVDsym1(getTD, "CDVDgetTD"); + LoadCDVDsym1(getTOC, "CDVDgetTOC"); + LoadCDVDsym1(getDiskType, "CDVDgetDiskType"); + LoadCDVDsym1(getTrayStatus, "CDVDgetTrayStatus"); + LoadCDVDsym1(ctrlTrayOpen, "CDVDctrlTrayOpen"); + LoadCDVDsym1(ctrlTrayClose, "CDVDctrlTrayClose"); + + LoadCDVDsym0(configure, "CDVDconfigure"); + LoadCDVDsym0(about, "CDVDabout"); + LoadCDVDsym0(test, "CDVDtest"); + LoadCDVDsymN(newDiskCB, "CDVDnewDiskCB"); + + return 0; +} + +void *DEV9plugin; + +s32 CALLBACK DEV9_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK DEV9_configure() {} +void CALLBACK DEV9_about() {} +long CALLBACK DEV9_test() { return 0; } + +#define LoadDEV9sym1(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 1); + +#define LoadDEV9sym0(dest, name) \ + LoadSym(DEV9##dest, _DEV9##dest, name, 0); \ + if (DEV9##dest == NULL) DEV9##dest = (_DEV9##dest) DEV9_##dest; + +int LoadDEV9plugin(char *filename) { + void *drv; + + DEV9plugin = SysLoadLibrary(filename); + if (DEV9plugin == NULL) { SysMessage (_("Could Not Load DEV9 Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = DEV9plugin; + TestPS2Esyms(DEV9); + LoadDEV9sym1(init, "DEV9init"); + LoadDEV9sym1(shutdown, "DEV9shutdown"); + LoadDEV9sym1(open, "DEV9open"); + LoadDEV9sym1(close, "DEV9close"); + LoadDEV9sym1(read8, "DEV9read8"); + LoadDEV9sym1(read16, "DEV9read16"); + LoadDEV9sym1(read32, "DEV9read32"); + LoadDEV9sym1(write8, "DEV9write8"); + LoadDEV9sym1(write16, "DEV9write16"); + LoadDEV9sym1(write32, "DEV9write32"); + LoadDEV9sym1(readDMA8Mem, "DEV9readDMA8Mem"); + LoadDEV9sym1(writeDMA8Mem, "DEV9writeDMA8Mem"); + LoadDEV9sym1(irqCallback, "DEV9irqCallback"); + LoadDEV9sym1(irqHandler, "DEV9irqHandler"); + + LoadDEV9sym0(freeze, "DEV9freeze"); + LoadDEV9sym0(configure, "DEV9configure"); + LoadDEV9sym0(about, "DEV9about"); + LoadDEV9sym0(test, "DEV9test"); + + return 0; +} + +void *USBplugin; + +s32 CALLBACK USB_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK USB_configure() {} +void CALLBACK USB_about() {} +long CALLBACK USB_test() { return 0; } + +#define LoadUSBsym1(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 1); + +#define LoadUSBsym0(dest, name) \ + LoadSym(USB##dest, _USB##dest, name, 0); \ + if (USB##dest == NULL) USB##dest = (_USB##dest) USB_##dest; + +int LoadUSBplugin(char *filename) { + void *drv; + + USBplugin = SysLoadLibrary(filename); + if (USBplugin == NULL) { SysMessage (_("Could Not Load USB Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = USBplugin; + TestPS2Esyms(USB); + LoadUSBsym1(init, "USBinit"); + LoadUSBsym1(shutdown, "USBshutdown"); + LoadUSBsym1(open, "USBopen"); + LoadUSBsym1(close, "USBclose"); + LoadUSBsym1(read8, "USBread8"); + LoadUSBsym1(read16, "USBread16"); + LoadUSBsym1(read32, "USBread32"); + LoadUSBsym1(write8, "USBwrite8"); + LoadUSBsym1(write16, "USBwrite16"); + LoadUSBsym1(write32, "USBwrite32"); + LoadUSBsym1(irqCallback, "USBirqCallback"); + LoadUSBsym1(irqHandler, "USBirqHandler"); + LoadUSBsym1(setRAM, "USBsetRAM"); + + LoadUSBsym0(freeze, "USBfreeze"); + LoadUSBsym0(configure, "USBconfigure"); + LoadUSBsym0(about, "USBabout"); + LoadUSBsym0(test, "USBtest"); + + return 0; +} +void *FWplugin; + +s32 CALLBACK FW_freeze(int mode, freezeData *data) { data->size = 0; return 0; } +void CALLBACK FW_configure() {} +void CALLBACK FW_about() {} +long CALLBACK FW_test() { return 0; } + +#define LoadFWsym1(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 1); + +#define LoadFWsym0(dest, name) \ + LoadSym(FW##dest, _FW##dest, name, 0); \ + if (FW##dest == NULL) FW##dest = (_FW##dest) FW_##dest; + +int LoadFWplugin(char *filename) { + void *drv; + + FWplugin = SysLoadLibrary(filename); + if (FWplugin == NULL) { SysMessage (_("Could Not Load FW Plugin '%s': %s"), filename, SysLibError()); return -1; } + drv = FWplugin; + TestPS2Esyms(FW); + LoadFWsym1(init, "FWinit"); + LoadFWsym1(shutdown, "FWshutdown"); + LoadFWsym1(open, "FWopen"); + LoadFWsym1(close, "FWclose"); + LoadFWsym1(read32, "FWread32"); + LoadFWsym1(write32, "FWwrite32"); + LoadFWsym1(irqCallback, "FWirqCallback"); + + LoadFWsym0(freeze, "FWfreeze"); + LoadFWsym0(configure, "FWconfigure"); + LoadFWsym0(about, "FWabout"); + LoadFWsym0(test, "FWtest"); + + return 0; +} +static int loadp=0; + +int InitPlugins() { + int ret; + + if( GSsetBaseMem ) { + + if( CHECK_MULTIGS ) { + extern u8 g_MTGSMem[]; + GSsetBaseMem(g_MTGSMem); + } + else { + GSsetBaseMem(PS2MEM_GS); + } + } + + ret = GSinit(); + if (ret != 0) { SysMessage (_("GSinit error: %d"), ret); return -1; } + ret = PAD1init(1); + if (ret != 0) { SysMessage (_("PAD1init error: %d"), ret); return -1; } + ret = PAD2init(2); + if (ret != 0) { SysMessage (_("PAD2init error: %d"), ret); return -1; } + ret = SPU2init(); + if (ret != 0) { SysMessage (_("SPU2init error: %d"), ret); return -1; } + ret = CDVDinit(); + if (ret != 0) { SysMessage (_("CDVDinit error: %d"), ret); return -1; } + ret = DEV9init(); + if (ret != 0) { SysMessage (_("DEV9init error: %d"), ret); return -1; } + ret = USBinit(); + if (ret != 0) { SysMessage (_("USBinit error: %d"), ret); return -1; } + ret = FWinit(); + if (ret != 0) { SysMessage (_("FWinit error: %d"), ret); return -1; } + return 0; +} + +void ShutdownPlugins() { + GSshutdown(); + PAD1shutdown(); + PAD2shutdown(); + SPU2shutdown(); + CDVDshutdown(); + DEV9shutdown(); + USBshutdown(); + FWshutdown(); +} + +int LoadPlugins() { + char Plugin[256]; + + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.GS); + if (LoadGSplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD1); + if (LoadPAD1plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.PAD2); + if (LoadPAD2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.SPU2); + if (LoadSPU2plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.CDVD); + if (LoadCDVDplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.DEV9); + if (LoadDEV9plugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.USB); + if (LoadUSBplugin(Plugin) == -1) return -1; + sprintf(Plugin, "%s%s", Config.PluginsDir, Config.FW); + if (LoadFWplugin(Plugin) == -1) return -1; + if (InitPlugins() == -1) return -1; + + loadp=1; + + return 0; +} + +uptr pDsp; +static pluginsopened = 0; +extern void spu2DMA4Irq(); +extern void spu2DMA7Irq(); +extern void spu2Irq(); + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +extern HANDLE g_hGSOpen, g_hGSDone; +#else +extern pthread_mutex_t g_mutexGsThread; +extern pthread_cond_t g_condGsEvent; +extern sem_t g_semGsThread; +#endif + +int OpenPlugins(const char* pTitleFilename) { + GSdriverInfo info; + int ret; + + if (loadp == 0) return -1; + +#ifndef _WIN32 + // change dir so that CDVD can find its config file + char file[255], pNewTitle[255]; + getcwd(file, ARRAYSIZE(file)); + chdir(Config.PluginsDir); + + if( pTitleFilename != NULL && pTitleFilename[0] != '/' ) { + // because we are changing the dir, we have to set a new title if it is a relative dir + sprintf(pNewTitle, "%s/%s", file, pTitleFilename); + pTitleFilename = pNewTitle; + } +#endif + + //first we need the data + if (CDVDnewDiskCB) CDVDnewDiskCB(cdvdNewDiskCB); + + ret = CDVDopen(pTitleFilename); + + if (ret != 0) { SysMessage (_("Error Opening CDVD Plugin")); goto OpenError; } + cdvdNewDiskCB(); + + //video + GSirqCallback(gsIrq); + + // make sure only call open once per instance + if( !pluginsopened ) { + if( CHECK_MULTIGS ) { +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + SetEvent(g_hGSOpen); + WaitForSingleObject(g_hGSDone, INFINITE); +#else + pthread_cond_signal(&g_condGsEvent); + sem_wait(&g_semGsThread); + pthread_mutex_lock(&g_mutexGsThread); + pthread_mutex_unlock(&g_mutexGsThread); SysPrintf("MTGS thread unlocked\n"); +#endif + } + else { + ret = GSopen((void *)&pDsp, "PCSX2", 0); + if (ret != 0) { SysMessage (_("Error Opening GS Plugin")); goto OpenError; } + } + } + + //then the user input + if (GSgetDriverInfo) { + GSgetDriverInfo(&info); + if (PAD1gsDriverInfo) PAD1gsDriverInfo(&info); + if (PAD2gsDriverInfo) PAD2gsDriverInfo(&info); + } + ret = PAD1open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD1 Plugin")); goto OpenError; } + ret = PAD2open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening PAD2 Plugin")); goto OpenError; } + + //the sound + + SPU2irqCallback(spu2Irq,spu2DMA4Irq,spu2DMA7Irq); + if( SPU2setDMABaseAddr != NULL ) + SPU2setDMABaseAddr((uptr)PSXM(0)); + ret = SPU2open((void*)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening SPU2 Plugin")); goto OpenError; } + + //and last the dev9 + DEV9irqCallback(dev9Irq); + dev9Handler = DEV9irqHandler(); + ret = DEV9open((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening DEV9 Plugin")); goto OpenError; } + + USBirqCallback(usbIrq); + usbHandler = USBirqHandler(); + USBsetRAM(psxM); + ret = USBopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening USB Plugin")); goto OpenError; } + + FWirqCallback(fwIrq); + ret = FWopen((void *)&pDsp); + if (ret != 0) { SysMessage (_("Error Opening FW Plugin")); goto OpenError; } + + pluginsopened = 1; +#ifdef __LINUX__ + chdir(file); +#endif + return 0; + +OpenError: +#ifdef __LINUX__ + chdir(file); +#endif + + return -1; +} + +extern void gsWaitGS(); + +void ClosePlugins() +{ + gsWaitGS(); + + CDVDclose(); + DEV9close(); + USBclose(); + FWclose(); + SPU2close(); + PAD1close(); + PAD2close(); +} + +void ResetPlugins() { + gsWaitGS(); + + ShutdownPlugins(); + InitPlugins(); +} + +void ReleasePlugins() { + if (loadp == 0) return; + + if (GSplugin == NULL || PAD1plugin == NULL || PAD2plugin == NULL || + SPU2plugin == NULL || CDVDplugin == NULL || DEV9plugin == NULL || + USBplugin == NULL || FWplugin == NULL) return; + + ShutdownPlugins(); + + SysCloseLibrary(GSplugin); GSplugin = NULL; + SysCloseLibrary(PAD1plugin); PAD1plugin = NULL; + SysCloseLibrary(PAD2plugin); PAD2plugin = NULL; + SysCloseLibrary(SPU2plugin); SPU2plugin = NULL; + SysCloseLibrary(CDVDplugin); CDVDplugin = NULL; + SysCloseLibrary(DEV9plugin); DEV9plugin = NULL; + SysCloseLibrary(USBplugin); USBplugin = NULL; + SysCloseLibrary(FWplugin); FWplugin = NULL; + loadp=0; +} diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h new file mode 100644 index 0000000..fb53b7f --- /dev/null +++ b/pcsx2/Plugins.h @@ -0,0 +1,32 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PLUGINS_H__ +#define __PLUGINS_H__ + +#define PLUGINtypedefs +#define PLUGINfuncs +#include "PS2Edefs.h" + +int LoadPlugins(); +void ReleasePlugins(); +int OpenPlugins(const char* pTitleFilename); +void ClosePlugins(); +void ResetPlugins(); + +#endif /* __PLUGINS_H__ */ diff --git a/pcsx2/PsxBios.c b/pcsx2/PsxBios.c new file mode 100644 index 0000000..2e1495e --- /dev/null +++ b/pcsx2/PsxBios.c @@ -0,0 +1,300 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "PsxCommon.h" + +char *biosA0n[256] = { +// 0x00 + "open", "lseek", "read", "write", + "close", "ioctl", "exit", "sys_a0_07", + "getc", "putc", "todigit", "atof", + "strtoul", "strtol", "abs", "labs", +// 0x10 + "atoi", "atol", "atob", "setjmp", + "longjmp", "strcat", "strncat", "strcmp", + "strncmp", "strcpy", "strncpy", "strlen", + "index", "rindex", "strchr", "strrchr", +// 0x20 + "strpbrk", "strspn", "strcspn", "strtok", + "strstr", "toupper", "tolower", "bcopy", + "bzero", "bcmp", "memcpy", "memset", + "memmove", "memcmp", "memchr", "rand", +// 0x30 + "srand", "qsort", "strtod", "malloc", + "free", "lsearch", "bsearch", "calloc", + "realloc", "InitHeap", "_exit", "getchar", + "putchar", "gets", "puts", "printf", +// 0x40 + "sys_a0_40", "LoadTest", "Load", "Exec", + "FlushCache", "InstallInterruptHandler", "GPU_dw", "mem2vram", + "SendGPUStatus", "GPU_cw", "GPU_cwb", "SendPackets", + "sys_a0_4c", "GetGPUStatus", "GPU_sync", "sys_a0_4f", +// 0x50 + "sys_a0_50", "LoadExec", "GetSysSp", "sys_a0_53", + "_96_init()", "_bu_init()", "_96_remove()", "sys_a0_57", + "sys_a0_58", "sys_a0_59", "sys_a0_5a", "dev_tty_init", + "dev_tty_open", "sys_a0_5d", "dev_tty_ioctl","dev_cd_open", +// 0x60 + "dev_cd_read", "dev_cd_close", "dev_cd_firstfile", "dev_cd_nextfile", + "dev_cd_chdir", "dev_card_open", "dev_card_read", "dev_card_write", + "dev_card_close", "dev_card_firstfile", "dev_card_nextfile","dev_card_erase", + "dev_card_undelete","dev_card_format", "dev_card_rename", "dev_card_6f", +// 0x70 + "_bu_init", "_96_init", "_96_remove", "sys_a0_73", + "sys_a0_74", "sys_a0_75", "sys_a0_76", "sys_a0_77", + "_96_CdSeekL", "sys_a0_79", "sys_a0_7a", "sys_a0_7b", + "_96_CdGetStatus", "sys_a0_7d", "_96_CdRead", "sys_a0_7f", +// 0x80 + "sys_a0_80", "sys_a0_81", "sys_a0_82", "sys_a0_83", + "sys_a0_84", "_96_CdStop", "sys_a0_86", "sys_a0_87", + "sys_a0_88", "sys_a0_89", "sys_a0_8a", "sys_a0_8b", + "sys_a0_8c", "sys_a0_8d", "sys_a0_8e", "sys_a0_8f", +// 0x90 + "sys_a0_90", "sys_a0_91", "sys_a0_92", "sys_a0_93", + "sys_a0_94", "sys_a0_95", "AddCDROMDevice", "AddMemCardDevide", + "DisableKernelIORedirection", "EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b", + "SetConf", "GetConf", "sys_a0_9e", "SetMem", +// 0xa0 + "_boot", "SystemError", "EnqueueCdIntr", "DequeueCdIntr", + "sys_a0_a4", "ReadSector", "get_cd_status", "bufs_cb_0", + "bufs_cb_1", "bufs_cb_2", "bufs_cb_3", "_card_info", + "_card_load", "_card_auto", "bufs_cd_4", "sys_a0_af", +// 0xb0 + "sys_a0_b0", "sys_a0_b1", "do_a_long_jmp", "sys_a0_b3", + "?? sub_function", +}; + +char *biosB0n[256] = { +// 0x00 + "SysMalloc", "sys_b0_01", "sys_b0_02", "sys_b0_03", + "sys_b0_04", "sys_b0_05", "sys_b0_06", "DeliverEvent", + "OpenEvent", "CloseEvent", "WaitEvent", "TestEvent", + "EnableEvent", "DisableEvent", "OpenTh", "CloseTh", +// 0x10 + "ChangeTh", "sys_b0_11", "InitPAD", "StartPAD", + "StopPAD", "PAD_init", "PAD_dr", "ReturnFromExecption", + "ResetEntryInt", "HookEntryInt", "sys_b0_1a", "sys_b0_1b", + "sys_b0_1c", "sys_b0_1d", "sys_b0_1e", "sys_b0_1f", +// 0x20 + "UnDeliverEvent", "sys_b0_21", "sys_b0_22", "sys_b0_23", + "sys_b0_24", "sys_b0_25", "sys_b0_26", "sys_b0_27", + "sys_b0_28", "sys_b0_29", "sys_b0_2a", "sys_b0_2b", + "sys_b0_2c", "sys_b0_2d", "sys_b0_2e", "sys_b0_2f", +// 0x30 + "sys_b0_30", "sys_b0_31", "open", "lseek", + "read", "write", "close", "ioctl", + "exit", "sys_b0_39", "getc", "putc", + "getchar", "putchar", "gets", "puts", +// 0x40 + "cd", "format", "firstfile", "nextfile", + "rename", "delete", "undelete", "AddDevice", + "RemoteDevice", "PrintInstalledDevices", "InitCARD", "StartCARD", + "StopCARD", "sys_b0_4d", "_card_write", "_card_read", +// 0x50 + "_new_card", "Krom2RawAdd", "sys_b0_52", "sys_b0_53", + "_get_errno", "_get_error", "GetC0Table", "GetB0Table", + "_card_chan", "sys_b0_59", "sys_b0_5a", "ChangeClearPAD", + "_card_status", "_card_wait", +}; + +char *biosC0n[256] = { +// 0x00 + "InitRCnt", "InitException", "SysEnqIntRP", "SysDeqIntRP", + "get_free_EvCB_slot", "get_free_TCB_slot", "ExceptionHandler", "InstallExeptionHandler", + "SysInitMemory", "SysInitKMem", "ChangeClearRCnt", "SystemError", + "InitDefInt", "sys_c0_0d", "sys_c0_0e", "sys_c0_0f", +// 0x10 + "sys_c0_10", "sys_c0_11", "InstallDevices", "FlushStfInOutPut", + "sys_c0_14", "_cdevinput", "_cdevscan", "_circgetc", + "_circputc", "ioabort", "sys_c0_1a", "KernelRedirect", + "PatchAOTable", +}; + +//#define r0 (psxRegs.GPR.n.r0) +#define at (psxRegs.GPR.n.at) +#define v0 (psxRegs.GPR.n.v0) +#define v1 (psxRegs.GPR.n.v1) +#define a0 (psxRegs.GPR.n.a0) +#define a1 (psxRegs.GPR.n.a1) +#define a2 (psxRegs.GPR.n.a2) +#define a3 (psxRegs.GPR.n.a3) +#define t0 (psxRegs.GPR.n.t0) +#define t1 (psxRegs.GPR.n.t1) +#define t2 (psxRegs.GPR.n.t2) +#define t3 (psxRegs.GPR.n.t3) +#define t4 (psxRegs.GPR.n.t4) +#define t5 (psxRegs.GPR.n.t5) +#define t6 (psxRegs.GPR.n.t6) +#define t7 (psxRegs.GPR.n.t7) +#define s0 (psxRegs.GPR.n.s0) +#define s1 (psxRegs.GPR.n.s1) +#define s2 (psxRegs.GPR.n.s2) +#define s3 (psxRegs.GPR.n.s3) +#define s4 (psxRegs.GPR.n.s4) +#define s5 (psxRegs.GPR.n.s5) +#define s6 (psxRegs.GPR.n.s6) +#define s7 (psxRegs.GPR.n.s7) +#define t8 (psxRegs.GPR.n.t6) +#define t9 (psxRegs.GPR.n.t7) +#define k0 (psxRegs.GPR.n.k0) +#define k1 (psxRegs.GPR.n.k1) +#define gp (psxRegs.GPR.n.gp) +#define sp (psxRegs.GPR.n.sp) +#define fp (psxRegs.GPR.n.s8) +#define ra (psxRegs.GPR.n.ra) +#define pc0 (psxRegs.pc) + +#define Ra0 ((char*)PSXM(a0)) +#define Ra1 ((char*)PSXM(a1)) +#define Ra2 ((char*)PSXM(a2)) +#define Ra3 ((char*)PSXM(a3)) +#define Rv0 ((char*)PSXM(v0)) +#define Rsp ((char*)PSXM(sp)) + +void bios_write() { // 0x35/0x03 + + + if (a0 == 1) { // stdout + char *ptr = Ra1; + + while (a2 > 0) { + SysPrintf(COLOR_RED "%c" COLOR_RESET, *ptr++); a2--; + } + pc0 = ra; return; + } +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("bios_%s: %x,%x,%x\n", biosB0n[0x35], a0, a1, a2); +#endif + + v0 = -1; + + pc0 = ra; +} + +void bios_printf() { // 3f + char tmp[1024]; + char tmp2[1024]; + unsigned long save[4]; + char *ptmp = tmp; + int n=1, i=0, j; + + memcpy(save, (char*)PSXM(sp), 4*4); + psxMu32(sp) = a0; + psxMu32(sp + 4) = a1; + psxMu32(sp + 8) = a2; + psxMu32(sp + 12) = a3; + + while (Ra0[i]) { + switch (Ra0[i]) { + case '%': + j = 0; + tmp2[j++] = '%'; +_start: + switch (Ra0[++i]) { + case '.': + case 'l': + tmp2[j++] = Ra0[i]; goto _start; + default: + if (Ra0[i] >= '0' && Ra0[i] <= '9') { + tmp2[j++] = Ra0[i]; + goto _start; + } + break; + } + tmp2[j++] = Ra0[i]; + tmp2[j] = 0; + + switch (Ra0[i]) { + case 'f': case 'F': + ptmp+= sprintf(ptmp, tmp2, (float)psxMu32(sp + n * 4)); n++; break; + case 'a': case 'A': + case 'e': case 'E': + case 'g': case 'G': + ptmp+= sprintf(ptmp, tmp2, (double)psxMu32(sp + n * 4)); n++; break; + case 'p': + case 'i': + case 'd': case 'D': + case 'o': case 'O': + case 'x': case 'X': + ptmp+= sprintf(ptmp, tmp2, (unsigned int)psxMu32(sp + n * 4)); n++; break; + case 'c': + ptmp+= sprintf(ptmp, tmp2, (unsigned char)psxMu32(sp + n * 4)); n++; break; + case 's': + ptmp+= sprintf(ptmp, tmp2, (char*)PSXM(psxMu32(sp + n * 4))); n++; break; + case '%': + *ptmp++ = Ra0[i]; break; + } + i++; + break; + default: + *ptmp++ = Ra0[i++]; + } + } + *ptmp = 0; + + memcpy((char*)PSXM(sp), save, 4*4); + + SysPrintf(COLOR_RED "%s" COLOR_RESET, tmp); + + pc0 = ra; +} + +void bios_putchar () { // 3d + char tmp[12]; + + sprintf (tmp,"%c",(char)a0); + SysPrintf(tmp); + + pc0 = ra; +} + +void bios_puts () { // 3e/3f + SysPrintf(Ra0); + + pc0 = ra; +} + +void (*biosA0[256])(); +void (*biosB0[256])(); +void (*biosC0[256])(); + +void psxBiosInit() { + int i; + + for(i = 0; i < 256; i++) { + biosA0[i] = NULL; + biosB0[i] = NULL; + biosC0[i] = NULL; + } + biosA0[0x3e] = bios_puts; + biosA0[0x3f] = bios_printf; + + biosB0[0x3d] = bios_putchar; + biosB0[0x3f] = bios_puts; + +} + +void psxBiosShutdown() { +} + diff --git a/pcsx2/PsxBios.h b/pcsx2/PsxBios.h new file mode 100644 index 0000000..1ac0fe7 --- /dev/null +++ b/pcsx2/PsxBios.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXBIOS_H__ +#define __PSXBIOS_H__ + +extern char *biosA0n[256]; +extern char *biosB0n[256]; +extern char *biosC0n[256]; + +void psxBiosInit(); +void psxBiosShutdown(); +void psxBiosException(); +void psxBiosFreeze(int Mode); + +extern void (*biosA0[256])(); +extern void (*biosB0[256])(); +extern void (*biosC0[256])(); + +#endif /* __PSXBIOS_H__ */ diff --git a/pcsx2/PsxBios2.h b/pcsx2/PsxBios2.h new file mode 100644 index 0000000..a0c6640 --- /dev/null +++ b/pcsx2/PsxBios2.h @@ -0,0 +1,94 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/***** sysmem imageInfo +00000800: 00 16 00 00 70 14 00 00 01 01 00 00 01 00 00 00 +0000 next: .word ? //00001600 +0004 name: .word ? //00001470 +0008 version: .half ? //0101 +000A flags: .half ? //---- +000C index: .half ? //0001 +000E field_E: .half ? //---- +00000810: 90 08 00 00 A0 94 00 00 30 08 00 00 40 0C 00 00 +0010 entry: .word ? //00000890 +0014 gp_value: .word ? //000094A0 +0018 p1_vaddr: .word ? //00000830 +001C text_size: .word ? //00000C40 +00000820: 40 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 +0020 data_size: .word ? //00000040 +0024 bss_size: .word ? //00000010 +0028 field_28: .word ? //-------- +002C field_2C: .word ? //-------- +*****/ + +#ifndef __PSX_BIOS_H__ +#define __PSX_BIOS_H__ + +typedef struct { + u32 next, //+00 + name; //+04 + u16 version, //+08 + flags, //+0A + index, //+0C + _unkE; //+0E + u32 entry, //+10 + _gp, //+14 + vaddr, //+18 + text_size, //+1C + data_size, //+20 + bss_size, //+24 + _pad28, //+28 + _pad2C; //+2C +} irxImageInfo; //=30 + +typedef struct { + int active; + u32 server; + u32 fhandler; +} _sifServer; + +#define SIF_SERVERS 32 + +_sifServer sifServer[SIF_SERVERS]; + +// max modules/funcs + +#define IRX_MODULES 64 +#define IRX_FUNCS 256 + +typedef struct { + u32 num; + u32 entry; +} irxFunc; + +typedef struct { + int active; + u32 name[2]; + irxFunc funcs[IRX_FUNCS]; +} irxModule; + +irxModule irxMod[IRX_MODULES]; + + +void iopModulesInit(); +int iopSetImportFunc(u32 *ptr); +int iopSetExportFunc(u32 *ptr); +void sifServerCall(u32 server, u32 num, char *bin, int insize, char *bout, int outsize); +void sifAddServer(u32 server, u32 fhandler); + +#endif diff --git a/pcsx2/PsxCommon.h b/pcsx2/PsxCommon.h new file mode 100644 index 0000000..3fc14d2 --- /dev/null +++ b/pcsx2/PsxCommon.h @@ -0,0 +1,46 @@ +/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOMMON_H__ +#define __PSXCOMMON_H__ + +#ifdef _WIN32 +#include +#endif + +#include "PS2Etypes.h" + +#include "System.h" +#include + +long LoadCdBios; +int cdOpenCase; + +#include "Plugins.h" +#include "R3000A.h" +#include "PsxMem.h" +#include "PsxHw.h" +#include "PsxBios.h" +#include "PsxDma.h" +#include "PsxCounters.h" +#include "CdRom.h" +#include "Sio.h" +#include "DebugTools/Debug.h" +#include "PsxSio2.h" +#include "CDVD.h" + +#endif /* __PSXCOMMON_H__ */ diff --git a/pcsx2/PsxCounters.c b/pcsx2/PsxCounters.c new file mode 100644 index 0000000..4aa0efa --- /dev/null +++ b/pcsx2/PsxCounters.c @@ -0,0 +1,631 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "PsxCommon.h" + +psxCounter psxCounters[8]; +u32 psxNextCounter, psxNextsCounter; +static int cnts = 6; +u8 psxhblankgate = 0; +u8 psxvblankgate = 0; +u8 psxcntmask = 0; + +static void psxRcntUpd16(u32 index) { + //psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[index].rate); + + //psxCounters[index].Cycle = (0xffff - psxCounters[index].count) * psxCounters[index].rate; + //psxCounters[index].CycleT = (psxCounters[index].target - psxCounters[index].count) * psxCounters[index].rate; +} + +static void psxRcntUpd32(u32 index) { + //psxCounters[index].sCycle = psxRegs.cycle; + psxCounters[index].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[index].rate); + + //psxCounters[index].Cycle = (0xfffee000 - psxCounters[index].count) * psxCounters[index].rate; + //psxCounters[index].CycleT = (psxCounters[index].target - psxCounters[index].count) * psxCounters[index].rate; +} + +static void psxRcntReset16(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd16(index); +} + +static void psxRcntReset32(u32 index) { + psxCounters[index].count = 0; + + psxCounters[index].mode&= ~0x18301C00; + psxRcntUpd32(index); +} + +static void psxRcntSet() { + u32 c; + int i; + + psxNextCounter = 0xffffffff; + psxNextsCounter = psxRegs.cycle; + + for (i=0; i<3; i++) { + c = (u32)(0xffff - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + //if(psxCounters[i].mode & 0x0800) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + for (i=3; i<6; i++) { + c = (u32)(0xfffee000 - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + //if(psxCounters[i].mode & 0x0800) continue; + c = (u32)(psxCounters[i].target - psxRcntCycles(i)) * psxCounters[i].rate; + if (c < psxNextCounter) { + psxNextCounter = c; + } + } + + c = (u32)(psxCounters[6].CycleT - (psxRegs.cycle - psxCounters[6].sCycleT)) ; + if (c < psxNextCounter) { + psxNextCounter = c; + } +} + + +void psxRcntInit() { + int i; + + memset(psxCounters, 0, sizeof(psxCounters)); + + for (i=0; i<3; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0x0; + } + for (i=3; i<6; i++) { + psxCounters[i].rate = 1; + psxCounters[i].mode|= 0x0400; + psxCounters[i].target = 0x0; + } + + psxCounters[0].interrupt = 0x10; + psxCounters[1].interrupt = 0x20; + psxCounters[2].interrupt = 0x40; + + psxCounters[3].interrupt = 0x04000; + psxCounters[4].interrupt = 0x08000; + psxCounters[5].interrupt = 0x10000; + + if (SPU2async != NULL) { + cnts = 7; + + psxCounters[6].rate = 1; + psxCounters[6].CycleT = 48000; + psxCounters[6].mode = 0x8; + } else cnts = 6; + + for (i=0; i<3; i++) + psxCounters[i].sCycleT = psxRegs.cycle; + for (i=3; i<6; i++) + psxCounters[i].sCycleT = psxRegs.cycle; + for (i=6; i> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxCounters[i].mode &= ~0x10000000; + psxRcntUpd16(i); + break; + case 0x3: //GATE_ON_Start + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxCounters[i].mode &= ~0x10000000; + psxRcntUpd32(i); + break; + case 0x3: //GATE_ON_Start + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} +void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts + int i = counter; + + if(counter < 3){ //Gates for 16bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + SysPrintf("PSX Gate %x\n", i); + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x3: //GATE_ON_Start + psxCounters[i].mode &= ~0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n"); + break; + } + } + + if(counter >= 3){ //Gates for 32bit counters + if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate + SysPrintf("PSX Gate %x\n", i); + switch((psxCounters[i].mode & 0x6) >> 1) { + case 0x0: //GATE_ON_count + psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x1: //GATE_ON_ClearStart + if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i); + psxCounters[i].mode &= ~0x10000000; + break; + case 0x2: //GATE_ON_Clear_OFF_Start + psxRcntReset32(i); + psxCounters[i].mode |= 0x10000000; + break; + case 0x3: //GATE_ON_Start + psxCounters[i].mode &= ~0x10000000; + break; + default: + SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n"); + break; + } + } +} + +void _testRcnt16target(int i) { + +#ifdef PSXCNT_LOG + PSXCNT_LOG("[%d] target 0x%x >= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount16(i), psxCounters[i].target); +#endif + + psxCounters[i].mode|= 0x0800; // Target flag + if(psxCounters[i].mode & 0x80) + if (psxCounters[i].mode & 0x10)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + if (psxCounters[i].mode & 0x10) // Target interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + + + if (psxCounters[i].mode & 0x08) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd16(i); + return; + } + if(!(psxCounters[i].mode & 0x40))psxcntmask |= (1<= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle) / psxCounters[i].rate, psxCounters[i].Cycle, psxRcntRcount16(i), psxCounters[i].count); +#endif + + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80) + psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxcntmask &= ~(1<= 0x%x (CycleT); count=0x%x, target=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycleT), psxCounters[i].CycleT, psxRcntRcount32(i), psxCounters[i].target); +#endif + + psxCounters[i].mode|= 0x0800; // Target flag + if(psxCounters[i].mode & 0x80) + if (psxCounters[i].mode & 0x10)psxCounters[i].mode&= ~0x0400; // Interrupt flag + + + if (psxCounters[i].mode & 0x10) // Target interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + + + if (psxCounters[i].mode & 0x8) { // Reset on target + psxCounters[i].count = 0; + psxRcntUpd32(i); + return; + } + if(!(psxCounters[i].mode & 0x40))psxcntmask |= (1<= 0x%x (Cycle); Rcount=0x%x, count=0x%x\n", i, (psxRegs.cycle - psxCounters[i].sCycle), psxCounters[i].Cycle, psxRcntRcount32(i), psxCounters[i].count); +#endif + + psxCounters[i].mode|= 0x1000; // Overflow flag + if (psxCounters[i].mode & 0x0020) { // Overflow interrupt + psxHu32(0x1070)|= psxCounters[i].interrupt; + if(psxCounters[i].mode & 0x80) + psxCounters[i].mode&= ~0x0400; // Interrupt flag + } + psxCounters[i].count = 0; + psxcntmask &= ~(1<= psxCounters[i].target){ + _testRcnt16target(i); + } + + if ((u32)psxRcntCycles(i) >= 0xffff) + _testRcnt16overflow(i); +} + +void _testRcnt32(int i) { + + if(!(psxHu32(0x1070) & psxCounters[i].interrupt)) { + psxCounters[i].mode &= ~0x1800; + psxCounters[i].mode |= 0x400; + } + if (!(psxcntmask & (1<= psxCounters[i].target){ + _testRcnt32target(i); + } + + if (psxRcntCycles(i) >= 0xfffee000) + _testRcnt32overflow(i); +} + +void psxRcntUpdate() { + int i; + for (i=0; i<=5; i++) { + psxCounters[i].count += (psxRegs.cycle - psxCounters[i].sCycleT) / psxCounters[i].rate; + psxCounters[i].sCycleT = psxRegs.cycle - (psxRegs.cycle % psxCounters[i].rate); + } + _testRcnt16(0); + _testRcnt16(1); + _testRcnt16(2); + _testRcnt32(3); + _testRcnt32(4); + _testRcnt32(5); + + if (cnts >= 7 && (psxRegs.cycle - psxCounters[6].sCycleT) >= psxCounters[6].CycleT) { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);//(u32)(psxRegs.cycle - psxNextsCounter)); + psxCounters[6].sCycleT = psxRegs.cycle; + } + + psxRcntSet(); +} + +void psxRcntWcount16(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif + SysPrintf("Write to 16bit count reg counter %x\n",index); + psxCounters[index].count = value & 0xffff; + SysPrintf("Counter %x count write %x\n", index, value); + psxRcntUpd16(index); + psxRcntSet(); +} + +void psxRcntWcount32(int index, u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCcount[%d] = %x\n", index, value); +#endif + SysPrintf("Write to 32bit count reg counter %x\n", index); + psxCounters[index].count = value; + SysPrintf("Counter %x count write %x\n", index, value); + psxRcntUpd32(index); + psxRcntSet(); +} + +void psxRcnt0Wmode(u32 value) { +#ifdef PSXCNT_LOG + //PSXCNT_LOG("IOP writeCmode[0] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 0 Value write %x\n", value & 0x1c00); + } + + psxCounters[0].mode = value; + psxCounters[0].mode|= 0x0400; + psxCounters[0].rate = 1; + psxcntmask &= ~(1); + if(value & 0x100) psxCounters[0].rate = PSXPIXEL; + + if(psxCounters[0].mode & 0x1){ + SysPrintf("Gate Check set on Counter 0\n"); + psxCounters[0].mode|= 0x1000000; + psxhblankgate |= 1; + }else + psxhblankgate &= ~1; + + psxCounters[0].count = 0; + psxRcntUpd16(0); + psxRcntSet(); + //} +} + +void psxRcnt1Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[1] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 1 Value write %x\n", value & 0x1c00); + } + + psxCounters[1].mode = value; + psxCounters[1].mode|= 0x0400; + psxCounters[1].rate = 1; + psxcntmask &= ~(1<<1); + if(value & 0x100)psxCounters[1].rate = PSXHBLANK; + + if(psxCounters[1].mode & 0x1){ + SysPrintf("Gate Check set on Counter 1\n"); + psxCounters[1].mode|= 0x1000000; + psxvblankgate |= 1<<1; + }else + psxvblankgate &= ~(1<<1); + + psxCounters[1].count = 0; + psxRcntUpd16(1); + psxRcntSet(); + //} +} + +void psxRcnt2Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[2] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 2 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<2); + psxCounters[2].mode = value; + psxCounters[2].mode|= 0x0400; + + switch(value & 0x200){ + case 0x200: + psxCounters[2].rate = 8; + break; + case 0x000: + psxCounters[2].rate = 1; + break; + } + + if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C2, disabling\n"); + psxCounters[2].mode|= 0x1000000; + } + // Need to set a rate and target + psxCounters[2].count = 0; + psxRcntUpd16(2); + psxRcntSet(); +} + +void psxRcnt3Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[3] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 3 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<3); + psxCounters[3].mode = value; + psxCounters[3].rate = 1; + psxCounters[3].mode|= 0x0400; + + if(value & 0x100)psxCounters[3].rate = PSXHBLANK; + + if(psxCounters[3].mode & 0x1){ + SysPrintf("Gate Check set on Counter 3\n"); + psxCounters[3].mode|= 0x1000000; + psxvblankgate |= 1<<3; + }else + psxvblankgate &= ~(1<<3); + + psxCounters[3].count = 0; + psxRcntUpd32(3); + psxRcntSet(); + //} +} + +void psxRcnt4Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[4] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 4 Value write %x\n", value & 0x1c00); + } + + psxcntmask &= ~(1<<4); + psxCounters[4].mode = value; + psxCounters[4].mode|= 0x0400; + + switch(value & 0x6000){ + case 0x0000: + psxCounters[4].rate = 1; + break; + case 0x2000: + psxCounters[4].rate = 8; + break; + case 0x4000: + psxCounters[4].rate = 16; + break; + case 0x6000: + psxCounters[4].rate = 256; + break; + } + // Need to set a rate and target + if((psxCounters[4].mode & 0x7) == 0x7 || (psxCounters[4].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C4, disabling\n"); + psxCounters[4].mode|= 0x1000000; + } + psxCounters[4].count = 0; + psxRcntUpd32(4); + psxRcntSet(); +} + +void psxRcnt5Wmode(u32 value) { +#ifdef PSXCNT_LOG + PSXCNT_LOG("IOP writeCmode[5] = %lx\n", value); +#endif + if (value & 0x1c00) { + SysPrintf("Counter 5 Value write %x\n", value & 0x1c00); + } + psxcntmask &= ~(1<<5); + psxCounters[5].mode = value; + psxCounters[5].mode|= 0x0400; + + switch(value & 0x6000){ + case 0x0000: + psxCounters[5].rate = 1; + break; + case 0x2000: + psxCounters[5].rate = 8; + break; + case 0x4000: + psxCounters[5].rate = 16; + break; + case 0x6000: + psxCounters[5].rate = 256; + break; + } + // Need to set a rate and target + if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1){ + SysPrintf("Gate set on IOP C5, disabling\n"); + psxCounters[5].mode|= 0x1000000; + } + psxCounters[5].count = 0; + psxRcntUpd32(5); + psxRcntSet(); +} + +void psxRcntWtarget16(int index, u32 value) { + //if(psxCounters[index].sCycleT > psxRegs.cycle) ReSyncTarget(index); +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget16[%ld] = %lx\n", index, value); +#endif + psxCounters[index].target = value & 0xffff; + psxRcntSet(); +} + +void psxRcntWtarget32(int index, u32 value) { + //if(psxCounters[index].sCycleT > psxRegs.cycle) ReSyncTarget(index); + psxCounters[index].target = value; + +#ifdef PSXCNT_LOG + PSXCNT_LOG("writeCtarget32[%ld] = %lx (count=%lx) ; sCycleT: %x CycleT: %x\n", + index, value, psxRcntRcount32(index), psxCounters[index].sCycleT, psxCounters[index].CycleT); +#endif + //if(index == 5) SysPrintf("Counter 5 tar set CT %x, Tar %x, mode %x, psx.cycle %x\n", psxCounters[index].CycleT + psxCounters[index].sCycleT, psxCounters[index].target, psxCounters[index].mode, psxRegs.cycle); + psxRcntSet(); +} + +u16 psxRcntRcount16(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u16)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +u32 psxRcntRcount32(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u32)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +u64 psxRcntCycles(int index) { + if(psxCounters[index].mode & 0x1000000) return psxCounters[index].count; + return (u64)(psxCounters[index].count + (psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); +} + +int psxRcntFreeze(gzFile f, int Mode) { + gzfreezel(psxCounters); + + return 0; +} diff --git a/pcsx2/PsxCounters.h b/pcsx2/PsxCounters.h new file mode 100644 index 0000000..2a616fb --- /dev/null +++ b/pcsx2/PsxCounters.h @@ -0,0 +1,55 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXCOUNTERS_H__ +#define __PSXCOUNTERS_H__ + +typedef struct { + u32 count, mode, target; + u32 rate, interrupt, otarget; + u32 sCycle, Cycle; + u32 sCycleT, CycleT; +} psxCounter; + +extern psxCounter psxCounters[8]; +extern u32 psxNextCounter, psxNextsCounter; + +void psxRcntInit(); +void psxRcntUpdate(); +void cntspu2async(); +void psxRcntWcount16(int index, u32 value); +void psxRcntWcount32(int index, u32 value); +void psxRcnt0Wmode(u32 value); +void psxRcnt1Wmode(u32 value); +void psxRcnt2Wmode(u32 value); +void psxRcnt3Wmode(u32 value); +void psxRcnt4Wmode(u32 value); +void psxRcnt5Wmode(u32 value); +void psxRcntWtarget16(int index, u32 value); +void psxRcntWtarget32(int index, u32 value); +u16 psxRcntRcount16(int index); +u32 psxRcntRcount32(int index); +u64 psxRcntCycles(int index); +int psxRcntFreeze(gzFile f, int Mode); + +void psxVSyncStart(); +void psxVSyncEnd(); +void psxCheckStartGate(int counter); +void psxCheckEndGate(int counter); + +#endif /* __PSXCOUNTERS_H__ */ diff --git a/pcsx2/PsxDma.c b/pcsx2/PsxDma.c new file mode 100644 index 0000000..a603d95 --- /dev/null +++ b/pcsx2/PsxDma.c @@ -0,0 +1,255 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "PsxCommon.h" +// Dma0/1 in Mdec.c +// Dma3 in CdRom.c +// Dma8 in PsxSpd.c +// Dma11/12 in PsxSio2.c +//static int spudmaenable[2]; +void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + + switch (chcr) { + case 0x01000201: //cpu to spu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2writeDMA4Mem((u16 *)PSXM(madr), size*2); + break; + case 0x01000200: //spu to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + SPU2readDMA4Mem((u16 *)PSXM(madr), size*2); + psxCpu->Clear(HW_DMA4_MADR, size); + break; + + default: + SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + + //spudmaenable[0] = size; +} + +int psxDma4Interrupt() { + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); + psxHu32(0x1070)|= 1<<9; + return 1; +} + +void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU + HW_DMA2_CHCR &= ~0x01000000; + psxDmaInterrupt(2); +} + +void psxDma6(u32 madr, u32 bcr, u32 chcr) { + u32 *mem = (u32 *)PSXM(madr); + +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr == 0x11000002) { + while (bcr--) { + *mem-- = (madr - 4) & 0xffffff; + madr -= 4; + } + mem++; *mem = 0xffffff; + } else { + // Unknown option +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + } + HW_DMA6_CHCR &= ~0x01000000; + psxDmaInterrupt(6); +} + +void psxDma7(u32 madr, u32 bcr, u32 chcr) { + int size; + + if(chcr & 0x400) SysPrintf("SPU 2 DMA 7 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if(chcr & 0x40000000) SysPrintf("SPU 2 DMA 7 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + if((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 7 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr); + + + switch (chcr) { + case 0x01000201: //cpu to spu2 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2writeDMA7Mem((u16 *)PSXM(madr), size*2); + break; + case 0x01000200: //spu2 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + //SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF)); + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + SPU2readDMA7Mem((u16 *)PSXM(madr), size*2); + psxCpu->Clear(HW_DMA7_MADR, size); + break; + default: + SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; + } + HW_DMA7_CHCR &= ~0x01000000; + +} + +int psxDma7Interrupt() { + + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); + return 1; + +} + +void psxDma9(u32 madr, u32 bcr, u32 chcr) { + + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc000]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR); +#endif + + psHu32(0x1000F240) |= 0x2000; + if (dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void psxDma10(u32 madr, u32 bcr, u32 chcr) { + DMACh *dma = (DMACh*)&PS2MEM_HW[0xc400]; + +#ifdef SIF_LOG + SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx\n", chcr, madr, bcr); +#endif + + psHu32(0x1000F240) |= 0x4000; + if (dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void psxDma8(u32 madr, u32 bcr, u32 chcr) { + int size; + + switch (chcr & 0x01000201) { + case 0x01000201: //cpu to dev9 transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9writeDMA8Mem((u32*)PSXM(madr), size*8); + break; + case 0x01000200: //dev9 to cpu transfer +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer + + DEV9readDMA8Mem((u32*)PSXM(madr), size*8); + break; +#ifdef PSXDMA_LOG + default: + PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); + break; +#endif + } + HW_DMA8_CHCR &= ~0x01000000; + psxDmaInterrupt2(1); +} + +int dev9Interrupt() { + if (dev9Handler == NULL) goto irq; + if (dev9Handler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<13; + //SBUS + hwIntcIrq(INTC_SBUS); + return 1; +} + +void dev9Irq(int cycles) { + PSX_INT(20, (PSXCLK/cycles)); +} + +int usbInterrupt() { + if (usbHandler == NULL) goto irq; + if (usbHandler() != 1) return 1; +irq: + psxHu32(0x1070)|= 1<<22; + //SBUS + hwIntcIrq(INTC_SBUS); + return 1; +} + +void usbIrq(int cycles) { + PSX_INT(21, (PSXCLK/cycles)); +} + +void fwIrq() { + psxHu32(0x1070)|= 1<<24; + //SBUS + hwIntcIrq(INTC_SBUS); +} + +void spu2DMA4Irq() { + SPU2interruptDMA4(); + //HW_DMA4_BCR = 0; + HW_DMA4_CHCR &= ~0x01000000; + psxDmaInterrupt(4); +} + +void spu2DMA7Irq() { + SPU2interruptDMA7(); + //HW_DMA7_BCR = 0; + HW_DMA7_CHCR &= ~0x01000000; + psxDmaInterrupt2(0); +} + +void spu2Irq() { + psxHu32(0x1070)|= 1<<9; + //SBUS + hwIntcIrq(INTC_SBUS); +} diff --git a/pcsx2/PsxDma.h b/pcsx2/PsxDma.h new file mode 100644 index 0000000..9db6f17 --- /dev/null +++ b/pcsx2/PsxDma.h @@ -0,0 +1,42 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXDMA_H__ +#define __PSXDMA_H__ + +void psxDma2(u32 madr, u32 bcr, u32 chcr); +void psxDma3(u32 madr, u32 bcr, u32 chcr); +void psxDma4(u32 madr, u32 bcr, u32 chcr); +void psxDma6(u32 madr, u32 bcr, u32 chcr); +void psxDma7(u32 madr, u32 bcr, u32 chcr); +void psxDma8(u32 madr, u32 bcr, u32 chcr); +void psxDma9(u32 madr, u32 bcr, u32 chcr); +void psxDma10(u32 madr, u32 bcr, u32 chcr); + +int psxDma4Interrupt(); +int psxDma7Interrupt(); +int dev9Interrupt(); +DEV9handler dev9Handler; +void dev9Irq(int cycles); +int usbInterrupt(); +USBhandler usbHandler; +void usbIrq(int cycles); +void fwIrq(); +void spu2Irq(); + +#endif /* __PSXDMA_H__ */ diff --git a/pcsx2/PsxHw.c b/pcsx2/PsxHw.c new file mode 100644 index 0000000..b285add --- /dev/null +++ b/pcsx2/PsxHw.c @@ -0,0 +1,1807 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +#include "iR5900.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#endif + +// NOTE: Any modifications to read/write fns should also go into their const counterparts + +void psxHwReset() { +/* if (Config.Sio) psxHu32(0x1070) |= 0x80; + if (Config.SpuIrq) psxHu32(0x1070) |= 0x200;*/ + + memset(psxH, 0, 0x10000); + +// mdecInit(); //intialize mdec decoder + cdrReset(); + cdvdReset(); + psxRcntInit(); + sioInit(); +// sio2Reset(); +} + +u8 psxHwRead8(u32 add) { + u8 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread8(add); + } + + switch (add) { + case 0x1f801040: hard = sioRead8();break; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + + case 0x1f80146e: // DEV9_R_REV + return DEV9read8(add); + +#ifdef PCSX2_DEVBUILD + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter read %x\n", add); + hard = psxHu8(add); + return hard; +#endif + + case 0x1f801800: hard = cdrRead0(); break; + case 0x1f801801: hard = cdrRead1(); break; + case 0x1f801802: hard = cdrRead2(); break; + case 0x1f801803: hard = cdrRead3(); break; + + case 0x1f803100: // PS/EE/IOP conf related + hard = 0x10; // Dram 2M + break; + + case 0x1F808264: + hard = sio2_fifoOut();//sio2 serial data feed/fifo_out +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read8 DATAOUT %08X\n", hard); +#endif + return hard; + + default: + hard = psxHu8(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +u16 psxHwRead16(u32 add) { + u16 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread16(add); + } + + switch (add) { +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 16bit read %x\n", psxHu16(0x1070)); + return psxHu16(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit read %x\n", psxHu16(0x1074)); + return psxHu16(0x1074); +#endif + + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801044: + hard = sio.StatReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f801048: + hard = sio.ModeReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104a: + hard = sio.CtrlReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + case 0x1f80104e: + hard = sio.BaudReg; +#ifdef PAD_LOG + PAD_LOG("sio read16 %lx; ret = %x\n", add&0xf, hard); +#endif + return hard; + + //Serial port stuff not support now ;P + // case 0x1f801050: hard = serial_read16(); break; + // case 0x1f801054: hard = serial_status_read(); break; + // case 0x1f80105a: hard = serial_control_read(); break; + // case 0x1f80105e: hard = serial_baud_read(); break; + + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801104: + hard = psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801114: + hard = psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read16: %x\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read16: %x\n", hard); +#endif + return hard; + case 0x1f801124: + hard = psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read16: %x\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read16: %x\n", hard); +#endif + return hard; + + case 0x1f80146e: // DEV9_R_REV + return DEV9read16(add); + + case 0x1f801480: + hard = (u16)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = psxCounters[3].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u16)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = psxCounters[4].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u16)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = psxCounters[5].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read16: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read16: %lx\n", hard); +#endif + return hard; + + case 0x1f801504: + hard = psxHu16(0x1504); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit read %lx\n", hard); +#endif + return hard; + case 0x1f801506: + hard = psxHu16(0x1506); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit read %lx\n", hard); +#endif + return hard; + //case 0x1f802030: hard = //int_2000???? + //case 0x1f802040: hard =//dip switches...?? + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + hard = SPU2read(add); + } else { + hard = psxHu16(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 16bit read at address %lx\n", add); +#endif + } + return hard; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit read at address %lx value %x\n", add, hard); +#endif + return hard; +} + +u32 psxHwRead32(u32 add) { + u32 hard; + + if (add >= 0x1f801600 && add < 0x1f801700) { + return USBread32(add); + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + return FWread32(add); + } + + switch (add) { + case 0x1f801040: + hard = sioRead8(); + hard|= sioRead8() << 8; + hard|= sioRead8() << 16; + hard|= sioRead8() << 24; +#ifdef PAD_LOG + PAD_LOG("sio read32 ;ret = %lx\n", hard); +#endif + return hard; + + // case 0x1f801050: hard = serial_read32(); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size read %lx\n", psxHu32(0x1060)); + return psxHu32(0x1060); +#endif +#ifdef PSXHW_LOG + case 0x1f801070: PSXHW_LOG("IREG 32bit read %x\n", psxHu32(0x1070)); + return psxHu32(0x1070); +#endif +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 32bit read %x\n", psxHu32(0x1074)); + return psxHu32(0x1074); +#endif + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + hard = psxHu32(0x1078); + psxHu32(0x1078) = 0; + return hard; + +/* case 0x1f801810: +// hard = GPU_readData(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit read %lx\n", hard); +#endif + return hard;*/ +/* case 0x1f801814: + hard = GPU_readStatus(); +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit read %lx\n", hard); +#endif + return hard; +*/ +/* case 0x1f801820: hard = mdecRead0(); break; + case 0x1f801824: hard = mdecRead1(); break; +*/ +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit read %lx\n", psxHu32(0x10a0)); + return HW_DMA2_MADR; + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit read %lx\n", psxHu32(0x10a4)); + return HW_DMA2_BCR; + case 0x1f8010a8: + PSXHW_LOG("DMA2 CHCR 32bit read %lx\n", psxHu32(0x10a8)); + return HW_DMA2_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit read %lx\n", psxHu32(0x10b0)); + return HW_DMA3_MADR; + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit read %lx\n", psxHu32(0x10b4)); + return HW_DMA3_BCR; + case 0x1f8010b8: + PSXHW_LOG("DMA3 CHCR 32bit read %lx\n", psxHu32(0x10b8)); + return HW_DMA3_CHCR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit read %lx\n", HW_DMA9_MADR); + return HW_DMA9_MADR; + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit read %lx\n", HW_DMA9_BCR); + return HW_DMA9_BCR; + case 0x1f801528: + PSXHW_LOG("DMA9 CHCR 32bit read %lx\n", HW_DMA9_CHCR); + return HW_DMA9_CHCR; + case 0x1f80152C: + PSXHW_LOG("DMA9 TADR 32bit read %lx\n", HW_DMA9_TADR); + return HW_DMA9_TADR; +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit read %lx\n", HW_DMA10_MADR); + return HW_DMA10_MADR; + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit read %lx\n", HW_DMA10_BCR); + return HW_DMA10_BCR; + case 0x1f801538: + PSXHW_LOG("DMA10 CHCR 32bit read %lx\n", HW_DMA10_CHCR); + return HW_DMA10_CHCR; +#endif + +// case 0x1f8010f0: PSXHW_LOG("DMA PCR 32bit read " << psxHu32(0x10f0)); +// return HW_DMA_PCR; // dma rest channel +#ifdef PSXHW_LOG + case 0x1f8010f4: + PSXHW_LOG("DMA ICR 32bit read %lx\n", HW_DMA_ICR); + return HW_DMA_ICR; +#endif +//SSBus registers + case 0x1f801000: + hard = psxHu32(0x1000); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801004: + hard = psxHu32(0x1004); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801008: + hard = psxHu32(0x1008); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80100C: + hard = psxHu32(0x100C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801010: + hard = psxHu32(0x1010); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS rom_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801014: + hard = psxHu32(0x1014); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801018: + hard = psxHu32(0x1018); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80101C: + hard = psxHu32(0x101C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801020: + hard = psxHu32(0x1020); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS com_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801400: + hard = psxHu32(0x1400); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801404: + hard = psxHu32(0x1404); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801408: + hard = psxHu32(0x1408); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80140C: + hard = psxHu32(0x140C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_addr 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801410: + hard = psxHu32(0x1410); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801414: + hard = psxHu32(0x1414); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_delay 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801418: + hard = psxHu32(0x1418); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f80141C: + hard = psxHu32(0x141C); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + case 0x1f801420: + hard = psxHu32(0x1420); +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit read %lx\n", hard); +#endif + return hard; + + case 0x1f8010f0: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR 32bit read %lx\n", HW_DMA_PCR); +#endif + return HW_DMA_PCR; + + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit read %lx\n", HW_DMA4_CHCR); +#endif + return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) + + // time for rootcounters :) + case 0x1f801100: + hard = (u16)psxRcntRcount16(0); +#ifdef PSXHW_LOG + PSXHW_LOG("T0 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801104: + hard = (u16)psxCounters[0].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801108: + hard = psxCounters[0].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T0 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801110: + hard = (u16)psxRcntRcount16(1); +#ifdef PSXHW_LOG + PSXHW_LOG("T1 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801114: + hard = (u16)psxCounters[1].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801118: + hard = psxCounters[1].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T1 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801120: + hard = (u16)psxRcntRcount16(2); +#ifdef PSXHW_LOG + PSXHW_LOG("T2 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801124: + hard = (u16)psxCounters[2].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801128: + hard = psxCounters[2].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T2 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801480: + hard = (u32)psxRcntRcount32(3); +#ifdef PSXHW_LOG + PSXHW_LOG("T3 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801484: + hard = (u16)psxCounters[3].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801488: + hard = psxCounters[3].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T3 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f801490: + hard = (u32)psxRcntRcount32(4); +#ifdef PSXHW_LOG + PSXHW_LOG("T4 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f801494: + hard = (u16)psxCounters[4].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f801498: + hard = psxCounters[4].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T4 target read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a0: + hard = (u32)psxRcntRcount32(5); +#ifdef PSXHW_LOG + PSXHW_LOG("T5 count read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a4: + hard = (u16)psxCounters[5].mode; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 mode read32: %lx\n", hard); +#endif + return hard; + case 0x1f8014a8: + hard = psxCounters[5].target; +#ifdef PSXHW_LOG + PSXHW_LOG("T5 target read32: %lx\n", hard); +#endif + return hard; + + case 0x1f801450: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("%08X ICFG 32bit read %x\n", psxRegs.pc, hard); +#endif + return hard; + + + case 0x1F8010C0: + HW_DMA4_MADR = SPU2ReadMemAddr(0); + return HW_DMA4_MADR; + + case 0x1f801500: + HW_DMA7_MADR = SPU2ReadMemAddr(1); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 MADR 32bit read %lx\n", HW_DMA7_MADR); +#endif + return HW_DMA7_MADR; // DMA7 madr + case 0x1f801504: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR 32bit read %lx\n", HW_DMA7_BCR); +#endif + return HW_DMA7_BCR; // DMA7 bcr + + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit read %lx\n", HW_DMA7_CHCR); +#endif + return HW_DMA7_CHCR; // DMA7 chcr (SPU2) + + case 0x1f801570: + hard = psxHu32(0x1570); +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit read %lx\n", hard); +#endif + return hard; +#ifdef PSXHW_LOG + case 0x1f801574: + PSXHW_LOG("DMA ICR2 32bit read %lx\n", HW_DMA_ICR2); + return HW_DMA_ICR2; +#endif + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + hard=sio2_getSend3((add-0x1F808200)/4); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read param[%d] (%lx)\n", (add-0x1F808200)/4, hard); +#endif + return hard; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + hard=sio2_getSend1((add-0x1F808240)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send1[%d] (%lx)\n", (add-0x1F808240)/8, hard); +#endif + return hard; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + hard=sio2_getSend2((add-0x1F808244)/8); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read send2[%d] (%lx)\n", (add-0x1F808244)/8, hard); +#endif + return hard; + + case 0x1F808268: + hard=sio2_getCtrl(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read CTRL (%lx)\n", hard); +#endif + return hard; + + case 0x1F80826C: + hard=sio2_getRecv1(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv1 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808270: + hard=sio2_getRecv2(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv2 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808274: + hard=sio2_getRecv3(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read Recv3 (%lx)\n", hard); +#endif + return hard; + + case 0x1F808278: + hard=sio2_get8278(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [8278] (%lx)\n", hard); +#endif + return hard; + + case 0x1F80827C: + hard=sio2_get827C(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read [827C] (%lx)\n", hard); +#endif + return hard; + + case 0x1F808280: + hard=sio2_getIntr(); +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 read INTR (%lx)\n", hard); +#endif + return hard; + + default: + hard = psxHu32(add); +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit read at address %lx: %lx\n", add, hard); +#endif + return hard; +} + +int g_pbufi; +s8 g_pbuf[1024]; + +#define DmaExec(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite8(u32 add, u8 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite8(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0xa) SysPrintf("8bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: sioWrite8(value); break; + // case 0x1f801050: serial_write8(value); break;//serial port + + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter write %x\n", add); + psxHu8(add) = value; + return; + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 8bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu8(0x1450) = value; + return; + + case 0x1f801800: cdrWrite0(value); break; + case 0x1f801801: cdrWrite1(value); break; + case 0x1f801802: cdrWrite2(value); break; + case 0x1f801803: cdrWrite3(value); break; + + case 0x1f80380c: + if (value == '\r') break; + if (value == '\n' || g_pbufi >= 1023) { + g_pbuf[g_pbufi++] = 0; g_pbufi = 0; + SysPrintf("%s\n", g_pbuf); break; + } + g_pbuf[g_pbufi++] = value; + break; + + case 0x1F808260: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write8 DATAIN <- %08X\n", value); +#endif + sio2_fifoIn(value);return;//serial data feed/fifo + + default: + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu8(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxHwWrite16(u32 add, u16 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite16(add, value); return; + } +#ifdef PCSX2_DEVBUILD + if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value); +#endif + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)(value>>8)); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801044: +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f801048: + sio.ModeReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104a: // control register + sioWriteCtrl16(value); +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + case 0x1f80104e: // baudrate register + sio.BaudReg = value; +#ifdef PAD_LOG + PAD_LOG ("sio write16 %lx, %x\n", add&0xf, value); +#endif + return; + + //serial port ;P + // case 0x1f801050: serial_write16(value); break; + // case 0x1f80105a: serial_control_write(value);break; + // case 0x1f80105e: serial_baud_write(value); break; + // case 0x1f801054: serial_status_write(value); break; + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 16bit write %x\n", value); +#endif +// if (Config.Sio) psxHu16(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200; + psxHu16(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value); + psxHu16(0x1074) = value; + return; +#endif + + case 0x1f8010c4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value); +#endif + psxHu16(0x10c4) = value; return; // DMA4 bcr_size + + case 0x1f8010c6: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value); +#endif + psxHu16(0x10c6) = value; return; // DMA4 bcr_count + + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(0, value); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 16bit write %x\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(0, value); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(1, value); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 16bit write %x\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(1, value); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 16bit write %x\n", value); +#endif + psxRcntWcount16(2, value); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 16bit write %x\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 16bit write %x\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 16bit write %lx\n", psxRegs.pc, value); } +#endif + psxHu16(0x1450) = value/* & (~0x8)*/; + return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 16bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 16bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 16bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 16bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 16bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f801504: + psxHu16(0x1504) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_size 16bit write %lx\n", value); +#endif + return; + case 0x1f801506: + psxHu16(0x1506) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 BCR_count 16bit write %lx\n", value); +#endif + return; + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + SPU2write(add, value); + return; + } + + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 16bit write at address %lx value %x\n", add, value); +#endif + return; + } + psxHu16(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 16bit write at address %lx value %x\n", add, value); +#endif +} + +#define DmaExec2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +void psxHwWrite32(u32 add, u32 value) { + if (add >= 0x1f801600 && add < 0x1f801700) { + USBwrite32(add, value); return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + FWwrite32(add, value); return; + } + switch (add) { + case 0x1f801040: + sioWrite8((u8)value); + sioWrite8((u8)((value&0xff) >> 8)); + sioWrite8((u8)((value&0xff) >> 16)); + sioWrite8((u8)((value&0xff) >> 24)); +#ifdef PAD_LOG + PAD_LOG("sio write32 %lx\n", value); +#endif + return; + // case 0x1f801050: serial_write32(value); break;//serial port +#ifdef PSXHW_LOG + case 0x1f801060: + PSXHW_LOG("RAM size write %lx\n", value); + psxHu32(add) = value; + return; // Ram size +#endif + + case 0x1f801070: +#ifdef PSXHW_LOG + PSXHW_LOG("IREG 32bit write %lx\n", value); +#endif +// if (Config.Sio) psxHu32(0x1070) |= 0x80; +// if (Config.SpuIrq) psxHu32(0x1070) |= 0x200; + psxHu32(0x1070) &= value; + return; +#ifdef PSXHW_LOG + case 0x1f801074: + PSXHW_LOG("IMASK 32bit write %lx\n", value); + psxHu32(0x1074) = value; + return; + + case 0x1f801078: + PSXHW_LOG("ICTRL 32bit write %lx\n", value); +// SysPrintf("ICTRL 32bit write %lx\n", value); + psxHu32(0x1078) = value; + return; +#endif + + //SSBus registers + case 0x1f801000: + psxHu32(0x1000) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801004: + psxHu32(0x1004) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801008: + psxHu32(0x1008) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f80100C: + psxHu32(0x100C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801010: + psxHu32(0x1010) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS rom_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801014: + psxHu32(0x1014) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801018: + psxHu32(0x1018) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f80101C: + psxHu32(0x101C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801020: + psxHu32(0x1020) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS com_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801400: + psxHu32(0x1400) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev1_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801404: + psxHu32(0x1404) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801408: + psxHu32(0x1408) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS dev5_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f80140C: + psxHu32(0x140C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_addr 32bit write %lx\n", value); +#endif + return; + case 0x1f801410: + psxHu32(0x1410) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801414: + psxHu32(0x1414) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS spu1_delay 32bit write %lx\n", value); +#endif + return; + case 0x1f801418: + psxHu32(0x1418) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f80141C: + psxHu32(0x141C) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; + case 0x1f801420: + psxHu32(0x1420) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("SSBUS 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f801080: + PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value); + HW_DMA0_MADR = value; return; // DMA0 madr + case 0x1f801084: + PSXHW_LOG("DMA0 BCR 32bit write %lx\n", value); + HW_DMA0_BCR = value; return; // DMA0 bcr +#endif + case 0x1f801088: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA0 CHCR 32bit write %lx\n", value); +#endif + HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +// DmaExec(0); + return; + +#ifdef PSXHW_LOG + case 0x1f801090: + PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value); + HW_DMA1_MADR = value; return; // DMA1 madr + case 0x1f801094: + PSXHW_LOG("DMA1 BCR 32bit write %lx\n", value); + HW_DMA1_BCR = value; return; // DMA1 bcr +#endif + case 0x1f801098: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA1 CHCR 32bit write %lx\n", value); +#endif + HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +// DmaExec(1); + return; + +#ifdef PSXHW_LOG + case 0x1f8010a0: + PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value); + HW_DMA2_MADR = value; return; // DMA2 madr + case 0x1f8010a4: + PSXHW_LOG("DMA2 BCR 32bit write %lx\n", value); + HW_DMA2_BCR = value; return; // DMA2 bcr +#endif + case 0x1f8010a8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA2 CHCR 32bit write %lx\n", value); +#endif + HW_DMA2_CHCR = value; // DMA2 chcr (GPU DMA) + DmaExec(2); + return; + +#ifdef PSXHW_LOG + case 0x1f8010b0: + PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value); + HW_DMA3_MADR = value; return; // DMA3 madr + case 0x1f8010b4: + PSXHW_LOG("DMA3 BCR 32bit write %lx\n", value); + HW_DMA3_BCR = value; return; // DMA3 bcr +#endif + case 0x1f8010b8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA3 CHCR 32bit write %lx\n", value); +#endif + HW_DMA3_CHCR = value; // DMA3 chcr (CDROM DMA) + DmaExec(3); + + return; + + case 0x1f8010c0: + PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value); + SPU2WriteMemAddr(0,value); + HW_DMA4_MADR = value; return; // DMA4 madr + case 0x1f8010c4: + PSXHW_LOG("DMA4 BCR 32bit write %lx\n", value); + HW_DMA4_BCR = value; return; // DMA4 bcr + case 0x1f8010c8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA4 CHCR 32bit write %lx\n", value); +#endif + HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) + DmaExec(4); + return; + +#if 0 + case 0x1f8010d0: break; //DMA5write_madr(); + case 0x1f8010d4: break; //DMA5write_bcr(); + case 0x1f8010d8: break; //DMA5write_chcr(); // Not yet needed?? +#endif + +#ifdef PSXHW_LOG + case 0x1f8010e0: + PSXHW_LOG("DMA6 MADR 32bit write %lx\n", value); + HW_DMA6_MADR = value; return; // DMA6 madr + case 0x1f8010e4: + PSXHW_LOG("DMA6 BCR 32bit write %lx\n", value); + HW_DMA6_BCR = value; return; // DMA6 bcr +#endif + case 0x1f8010e8: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA6 CHCR 32bit write %lx\n", value); +#endif + HW_DMA6_CHCR = value; // DMA6 chcr (OT clear) + DmaExec(6); + return; + + case 0x1f801500: + PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value); + SPU2WriteMemAddr(1,value); + HW_DMA7_MADR = value; return; // DMA7 madr + case 0x1f801504: + PSXHW_LOG("DMA7 BCR 32bit write %lx\n", value); + HW_DMA7_BCR = value; return; // DMA7 bcr + case 0x1f801508: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA7 CHCR 32bit write %lx\n", value); +#endif + HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) + DmaExec2(7); + return; + +#ifdef PSXHW_LOG + case 0x1f801510: + PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value); + HW_DMA8_MADR = value; return; // DMA8 madr + case 0x1f801514: + PSXHW_LOG("DMA8 BCR 32bit write %lx\n", value); + HW_DMA8_BCR = value; return; // DMA8 bcr +#endif + case 0x1f801518: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA8 CHCR 32bit write %lx\n", value); +#endif + HW_DMA8_CHCR = value; // DMA8 chcr (DEV9) + DmaExec2(8); + return; + +#ifdef PSXHW_LOG + case 0x1f801520: + PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value); + HW_DMA9_MADR = value; return; // DMA9 madr + case 0x1f801524: + PSXHW_LOG("DMA9 BCR 32bit write %lx\n", value); + HW_DMA9_BCR = value; return; // DMA9 bcr +#endif + case 0x1f801528: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA9 CHCR 32bit write %lx\n", value); +#endif + HW_DMA9_CHCR = value; // DMA9 chcr (SIF0) + DmaExec2(9); + return; +#ifdef PSXHW_LOG + case 0x1f80152c: + PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value); + HW_DMA9_TADR = value; return; // DMA9 tadr +#endif + +#ifdef PSXHW_LOG + case 0x1f801530: + PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value); + HW_DMA10_MADR = value; return; // DMA10 madr + case 0x1f801534: + PSXHW_LOG("DMA10 BCR 32bit write %lx\n", value); + HW_DMA10_BCR = value; return; // DMA10 bcr +#endif + case 0x1f801538: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA10 CHCR 32bit write %lx\n", value); +#endif + HW_DMA10_CHCR = value; // DMA10 chcr (SIF1) + DmaExec2(10); + return; + +#ifdef PSXHW_LOG + case 0x1f801540: + PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value); + HW_DMA11_MADR = value; return; + + case 0x1f801544: + PSXHW_LOG("DMA11 SIO2in BCR 32bit write %lx\n", value); + HW_DMA11_BCR = value; return; +#endif + case 0x1f801548: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA11 SIO2in CHCR 32bit write %lx\n", value); +#endif + HW_DMA11_CHCR = value; // DMA11 chcr (SIO2 in) + DmaExec2(11); + return; + +#ifdef PSXHW_LOG + case 0x1f801550: + PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value); + HW_DMA12_MADR = value; return; + + case 0x1f801554: + PSXHW_LOG("DMA12 SIO2out BCR 32bit write %lx\n", value); + HW_DMA12_BCR = value; return; +#endif + case 0x1f801558: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA12 SIO2out CHCR 32bit write %lx\n", value); +#endif + HW_DMA12_CHCR = value; // DMA12 chcr (SIO2 out) + DmaExec2(12); + return; + + case 0x1f801570: + psxHu32(0x1570) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("DMA PCR2 32bit write %lx\n", value); +#endif + return; +#ifdef PSXHW_LOG + case 0x1f8010f0: + PSXHW_LOG("DMA PCR 32bit write %lx\n", value); + HW_DMA_PCR = value; + return; +#endif + + case 0x1f8010f4: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR; + HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + + case 0x1f801574: +#ifdef PSXHW_LOG + PSXHW_LOG("DMA ICR2 32bit write %lx\n", value); +#endif + { + u32 tmp = (~value) & HW_DMA_ICR2; + HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp; + return; + } + +/* case 0x1f801810: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU DATA 32bit write %lx\n", value); +#endif + GPU_writeData(value); return; + case 0x1f801814: +#ifdef PSXHW_LOG + PSXHW_LOG("GPU STATUS 32bit write %lx\n", value); +#endif + GPU_writeStatus(value); return; +*/ +/* case 0x1f801820: + mdecWrite0(value); break; + case 0x1f801824: + mdecWrite1(value); break; +*/ + case 0x1f801100: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(0, value ); return; + case 0x1f801104: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 MODE 32bit write %lx\n", value); +#endif + psxRcnt0Wmode(value); return; + case 0x1f801108: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 0 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(0, value ); return; + + case 0x1f801110: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(1, value ); return; + case 0x1f801114: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 MODE 32bit write %lx\n", value); +#endif + psxRcnt1Wmode(value); return; + case 0x1f801118: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 1 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(1, value ); return; + + case 0x1f801120: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount16(2, value ); return; + case 0x1f801124: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 MODE 32bit write %lx\n", value); +#endif + psxRcnt2Wmode(value); return; + case 0x1f801128: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 2 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget16(2, value); return; + + case 0x1f801480: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(3, value); return; + case 0x1f801484: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 MODE 32bit write %lx\n", value); +#endif + psxRcnt3Wmode(value); return; + case 0x1f801488: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 3 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(3, value); return; + + case 0x1f801490: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(4, value); return; + case 0x1f801494: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 MODE 32bit write %lx\n", value); +#endif + psxRcnt4Wmode(value); return; + case 0x1f801498: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 4 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(4, value); return; + + case 0x1f8014a0: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 COUNT 32bit write %lx\n", value); +#endif + psxRcntWcount32(5, value); return; + case 0x1f8014a4: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 MODE 32bit write %lx\n", value); +#endif + psxRcnt5Wmode(value); return; + case 0x1f8014a8: +#ifdef PSXHW_LOG + PSXHW_LOG("COUNTER 5 TARGET 32bit write %lx\n", value); +#endif + psxRcntWtarget32(5, value); return; + + case 0x1f8014c0: +#ifdef PSXHW_LOG + PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value); +#endif + SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value); + break; + + case 0x1f801450: +#ifdef PSXHW_LOG + if (value) { PSXHW_LOG("%08X ICFG 32bit write %lx\n", psxRegs.pc, value); } +#endif +/* if (value && + psxSu32(0x20) == 0x20000 && + (psxSu32(0x30) == 0x20000 || + psxSu32(0x30) == 0x40000)) { // don't ask me why :P + psxSu32(0x20) = 0x10000; + psxSu32(0x30) = 0x10000; + }*/ + psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/; + return; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write param[%d] <- %lx\n", (add-0x1F808200)/4, value); +#endif + sio2_setSend3((add-0x1F808200)/4, value); return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send1[%d] <- %lx\n", (add-0x1F808240)/8, value); +#endif + sio2_setSend1((add-0x1F808240)/8, value); return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write send2[%d] <- %lx\n", (add-0x1F808244)/8, value); +#endif + sio2_setSend2((add-0x1F808244)/8, value); return; + + case 0x1F808268: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write CTRL <- %lx\n", value); +#endif + sio2_setCtrl(value); return; + + case 0x1F808278: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [8278] <- %lx\n", value); +#endif + sio2_set8278(value); return; + + case 0x1F80827C: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write [827C] <- %lx\n", value); +#endif + sio2_set827C(value); return; + + case 0x1F808280: +#ifdef PSXHW_LOG + PSXHW_LOG("SIO2 write INTR <- %lx\n", value); +#endif + sio2_setIntr(value); return; + + default: + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value); +#endif + return; + } + psxHu32(add) = value; +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 32bit write at address %lx value %lx\n", add, value); +#endif +} + +u8 psxHw4Read8(u32 add) { + u8 hard; + + switch (add) { + case 0x1f402004: return cdvdRead04(); + case 0x1f402005: return cdvdRead05(); + case 0x1f402006: return cdvdRead06(); + case 0x1f402007: return cdvdRead07(); + case 0x1f402008: return cdvdRead08(); + case 0x1f40200A: return cdvdRead0A(); + case 0x1f40200B: return cdvdRead0B(); + case 0x1f40200C: return cdvdRead0C(); + case 0x1f40200D: return cdvdRead0D(); + case 0x1f40200E: return cdvdRead0E(); + case 0x1f40200F: return cdvdRead0F(); + case 0x1f402013: return cdvdRead13(); + case 0x1f402015: return cdvdRead15(); + case 0x1f402016: return cdvdRead16(); + case 0x1f402017: return cdvdRead17(); + case 0x1f402018: return cdvdRead18(); + case 0x1f402020: return cdvdRead20(); + case 0x1f402021: return cdvdRead21(); + case 0x1f402022: return cdvdRead22(); + case 0x1f402023: return cdvdRead23(); + case 0x1f402024: return cdvdRead24(); + case 0x1f402028: return cdvdRead28(); + case 0x1f402029: return cdvdRead29(); + case 0x1f40202A: return cdvdRead2A(); + case 0x1f40202B: return cdvdRead2B(); + case 0x1f40202C: return cdvdRead2C(); + case 0x1f402030: return cdvdRead30(); + case 0x1f402031: return cdvdRead31(); + case 0x1f402032: return cdvdRead32(); + case 0x1f402033: return cdvdRead33(); + case 0x1f402034: return cdvdRead34(); + case 0x1f402038: return cdvdRead38(); + case 0x1f402039: return cdvdRead39(); + case 0x1f40203A: return cdvdRead3A(); + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unkwnown 8bit read at address %lx\n", add); +#endif + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + return 0; + } + +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit read at address %lx value %x\n", add, hard); +#endif + + return hard; +} + +void psxHw4Write8(u32 add, u8 value) { + switch (add) { + case 0x1f402004: cdvdWrite04(value); return; + case 0x1f402005: cdvdWrite05(value); return; + case 0x1f402006: cdvdWrite06(value); return; + case 0x1f402007: cdvdWrite07(value); return; + case 0x1f402008: cdvdWrite08(value); return; + case 0x1f40200A: cdvdWrite0A(value); return; + case 0x1f40200F: cdvdWrite0F(value); return; + case 0x1f402014: cdvdWrite14(value); return; + case 0x1f402016: + cdvdWrite16(value); + FreezeMMXRegs(0); + return; + case 0x1f402017: cdvdWrite17(value); return; + case 0x1f402018: cdvdWrite18(value); return; + case 0x1f40203A: cdvdWrite3A(value); return; + default: +#ifdef PSXHW_LOG + PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value); +#endif + SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value); + return; + } +#ifdef PSXHW_LOG + PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value); +#endif +} + +void psxDmaInterrupt(int n) { + if (HW_DMA_ICR & (1 << (16 + n))) { + HW_DMA_ICR|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (9 + n); + psxHu32(0x1070) |= 8; + + } +} + +void psxDmaInterrupt2(int n) { + if (HW_DMA_ICR2 & (1 << (16 + n))) { +/* if (HW_DMA_ICR2 & (1 << (24 + n))) { + SysPrintf("*PCSX2*: HW_DMA_ICR2 n=%d already set\n", n); + } + if (psxHu32(0x1070) & 8) { + SysPrintf("*PCSX2*: psxHu32(0x1070) 8 already set (n=%d)\n", n); + }*/ + HW_DMA_ICR2|= (1 << (24 + n)); + psxRegs.CP0.n.Cause |= 1 << (16 + n); + psxHu32(0x1070) |= 8; + } +} diff --git a/pcsx2/PsxHw.h b/pcsx2/PsxHw.h new file mode 100644 index 0000000..c0f4b64 --- /dev/null +++ b/pcsx2/PsxHw.h @@ -0,0 +1,117 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXHW_H__ +#define __PSXHW_H__ + +#define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA +#define HW_DMA0_BCR (psxHu32(0x1084)) +#define HW_DMA0_CHCR (psxHu32(0x1088)) + +#define HW_DMA1_MADR (psxHu32(0x1090)) // MDEC out DMA +#define HW_DMA1_BCR (psxHu32(0x1094)) +#define HW_DMA1_CHCR (psxHu32(0x1098)) + +#define HW_DMA2_MADR (psxHu32(0x10a0)) // GPU DMA +#define HW_DMA2_BCR (psxHu32(0x10a4)) +#define HW_DMA2_CHCR (psxHu32(0x10a8)) +#define HW_DMA2_TADR (psxHu32(0x10ac)) + +#define HW_DMA3_MADR (psxHu32(0x10b0)) // CDROM DMA +#define HW_DMA3_BCR (psxHu32(0x10b4)) +#define HW_DMA3_BCR_L16 (psxHu16(0x10b4)) +#define HW_DMA3_BCR_H16 (psxHu16(0x10b6)) +#define HW_DMA3_CHCR (psxHu32(0x10b8)) + +#define HW_DMA4_MADR (psxHu32(0x10c0)) // SPU DMA +#define HW_DMA4_BCR (psxHu32(0x10c4)) +#define HW_DMA4_CHCR (psxHu32(0x10c8)) +#define HW_DMA4_TADR (psxHu32(0x10cc)) + +#define HW_DMA6_MADR (psxHu32(0x10e0)) // GPU DMA (OT) +#define HW_DMA6_BCR (psxHu32(0x10e4)) +#define HW_DMA6_CHCR (psxHu32(0x10e8)) + +#define HW_DMA7_MADR (psxHu32(0x1500)) // SPU2 DMA +#define HW_DMA7_BCR (psxHu32(0x1504)) +#define HW_DMA7_CHCR (psxHu32(0x1508)) + +#define HW_DMA8_MADR (psxHu32(0x1510)) // DEV9 DMA +#define HW_DMA8_BCR (psxHu32(0x1514)) +#define HW_DMA8_CHCR (psxHu32(0x1518)) + +#define HW_DMA9_MADR (psxHu32(0x1520)) // SIF0 DMA +#define HW_DMA9_BCR (psxHu32(0x1524)) +#define HW_DMA9_CHCR (psxHu32(0x1528)) +#define HW_DMA9_TADR (psxHu32(0x152c)) + +#define HW_DMA10_MADR (psxHu32(0x1530)) // SIF1 DMA +#define HW_DMA10_BCR (psxHu32(0x1534)) +#define HW_DMA10_CHCR (psxHu32(0x1538)) + +#define HW_DMA11_MADR (psxHu32(0x1540)) // SIO2 in +#define HW_DMA11_BCR (psxHu32(0x1544)) +#define HW_DMA11_CHCR (psxHu32(0x1548)) + +#define HW_DMA12_MADR (psxHu32(0x1550)) // SIO2 out +#define HW_DMA12_BCR (psxHu32(0x1554)) +#define HW_DMA12_CHCR (psxHu32(0x1558)) + +#define HW_DMA_PCR (psxHu32(0x10f0)) +#define HW_DMA_ICR (psxHu32(0x10f4)) + +#define HW_DMA_PCR2 (psxHu32(0x1570)) +#define HW_DMA_ICR2 (psxHu32(0x1574)) + +#define PSX_INT(n, ecycle) \ + psxRegs.interrupt|= 1 << n; \ + g_psxNextBranchCycle = min(g_psxNextBranchCycle, psxRegs.cycle+ecycle); \ + psxRegs.sCycle[n] = psxRegs.cycle; \ + psxRegs.eCycle[n] = ecycle; + + +void psxHwReset(); +u8 psxHwRead8 (u32 add); +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign); + +u16 psxHwRead16(u32 add); +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign); + +u32 psxHwRead32(u32 add); +int psxHwConstRead32(u32 x86reg, u32 add); + +void psxHwWrite8 (u32 add, u8 value); +void psxHwConstWrite8(u32 add, int mmreg); + +void psxHwWrite16(u32 add, u16 value); +void psxHwConstWrite16(u32 add, int mmreg); + +void psxHwWrite32(u32 add, u32 value); +void psxHwConstWrite32(u32 add, int mmreg); + +u8 psxHw4Read8 (u32 add); +int psxHw4ConstRead8 (u32 x86reg, u32 add, u32 sign); + +void psxHw4Write8(u32 add, u8 value); +void psxHw4ConstWrite8(u32 add, int mmreg); + +int psxHwFreeze(gzFile f, int Mode); +void psxDmaInterrupt(int n); +void psxDmaInterrupt2(int n); + +#endif /* __PSXHW_H__ */ diff --git a/pcsx2/PsxInterpreter.c b/pcsx2/PsxInterpreter.c new file mode 100644 index 0000000..f7c4bb2 --- /dev/null +++ b/pcsx2/PsxInterpreter.c @@ -0,0 +1,797 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" +//#include "PsxBios2.h" + +static int branch = 0; +static int branch2 = 0; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +#ifdef _DEBUG +#define execI() { \ + psxRegs.code = PSXMu32(psxRegs.pc); \ + \ + if (Log) { \ + PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); \ + } \ + psxRegs.pc+= 4; \ + psxRegs.cycle++; \ + \ + psxBSC[psxRegs.code >> 26](); \ +} +#else +#define execI() { \ + psxRegs.code = PSXMu32(psxRegs.pc); \ + \ + psxRegs.pc+= 4; \ + psxRegs.cycle++; \ + \ + psxBSC[psxRegs.code >> 26](); \ +} +#endif + + +#define doBranch(tar) { \ + branch2 = branch = 1; \ + branchPC = tar; \ + execI(); \ + branch = 0; \ + psxRegs.pc = branchPC; \ + \ + psxBranchTest(); \ +} + +// Subsets +void (*psxBSC[64])(); +void (*psxSPC[64])(); +void (*psxREG[32])(); +void (*psxCP0[32])(); +void (*psxCP2[64])(); +void (*psxCP2BSC[32])(); + +extern void bios_write(); +extern void bios_printf(); + +typedef struct { + char name[8]; + char names[64][32]; + int maxn; +} irxlib; + +#define IRXLIBS 14 +irxlib irxlibs[32] = { +/*00*/ { { "sysmem" } , + { "start", "init_memory", "retonly", "return_addr_of_memsize", + "AllocSysMemory", "FreeSysMemory", "QueryMemSize", "QueryMaxFreeMemSize", + "QueryTotalFreeMemSize", "QueryBlockTopAddress", "QueryBlockSize", "retonly", + "retonly", "retonly", "Kprintf", "set_Kprintf" } , + 16 }, +/*01*/ { { "loadcore" } , + { "start", "retonly", "retonly_", "return_LibraryEntryTable", + "FlushIcache", "FlushDcache", "RegisterLibraryEntries", "ReleaseLibraryEntries", + "findFixImports", "restoreImports", "RegisterNonAutoLinkEntries", "QueryLibraryEntryTable", + "QueryBootMode", "RegisterBootMode", "setFlag", "resetFlag", + "linkModule", "unlinkModule", "retonly_", "retonly_", + "registerFunc", "jumpA0001B34", "read_header", "load_module", + "findImageInfo" }, + 25 }, +/*02*/ { { "excepman" } , + { "start", "reinit", "deinit", "getcommon", + "RegisterExceptionHandler", "RegisterPriorityExceptionHandler", + "RegisterDefaultExceptionHandler", "ReleaseExceptionHandler", + "ReleaseDefaultExceptionHandler" } , + 9 }, +/*03_4*/{ { "intrman" } , + { "start", "return_0", "deinit", "call3", + "RegisterIntrHandler", "ReleaseIntrHandler", "EnableIntr", "DisableIntr", + "CpuDisableIntr", "CpuEnableIntr", "syscall04", "syscall08", + "resetICTRL", "setICTRL", "syscall0C", "call15", + "call16", "CpuSuspendIntr", "CpuResumeIntr", "CpuSuspendIntr", + "CpuResumeIntr", "syscall10", "syscall14", "QueryIntrContext", + "QueryIntrStack", "iCatchMultiIntr", "retonly", "call27", + "set_h1", "reset_h1", "set_h2", "reset_h2" } , + 0x20 }, +/*05*/ { { "ssbusc" } , + { "start", "retonly", "return_0", "retonly", + "setTable1", "getTable1", "setTable2", "getTable2", + "setCOM_DELAY_1st", "getCOM_DELAY_1st", "setCOM_DELAY_2nd", "getCOM_DELAY_2nd", + "setCOM_DELAY_3rd", "getCOM_DELAY_3rd", "setCOM_DELAY_4th", "getCOM_DELAY_4th", + "setCOM_DELAY", "getCOM_DELAY" } , + 18 }, +/*06*/ { { "dmacman" } , + { "start", "retonly", "deinit", "retonly", + "SetD_MADR", "GetD_MADR", "SetD_BCR", "GetD_BCR", + "SetD_CHCR", "GetD_CHCR", "SetD_TADR", "GetD_TADR", + "Set_4_9_A", "Get_4_9_A", "SetDPCR", "GetDPCR", + "SetDPCR2", "GetDPCR2", "SetDPCR3", "GetDPCR3", + "SetDICR", "GetDICR", "SetDICR2", "GetDICR2", + "SetBF80157C", "GetBF80157C", "SetBF801578", "GetBF801578", + "SetDMA", "SetDMA_chainedSPU_SIF0", "SetDMA_SIF0", "SetDMA_SIF1", + "StartTransfer", "SetVal", "EnableDMAch", "DisableDMAch" } , + 36 }, +/*07_8*/{ { "timrman" } , + { "start", "retonly", "retonly", "call3", + "AllocHardTimer", "ReferHardTimer", "FreeHardTimer", "SetTimerMode", + "GetTimerStatus", "SetTimerCounter", "GetTimerCounter", "SetTimerCompare", + "GetTimerCompare", "SetHoldMode", "GetHoldMode", "GetHoldReg", + "GetHardTimerIntrCode" } , + 17 }, +/*09*/ { { "sysclib" } , + { "start", "reinit", "retonly", "retonly", + "setjmp", "longjmp", "toupper", "tolower", + "look_ctype_table", "get_ctype_table", "memchr", "memcmp", + "memcpy", "memmove", "memset", "bcmp", + "bcopy", "bzero", "prnt", "sprintf", + "strcat", "strchr", "strcmp", "strcpy", + "strcspn", "index", "rindex", "strlen", + "strncat", "strncmp", "strncpy", "strpbrk", + "strrchr", "strspn", "strstr", "strtok", + "strtol", "atob", "strtoul", "wmemcopy", + "wmemset", "vsprintf" } , + 0x2b }, +/*0A*/ { { "heaplib" } , + { "start", "retonly", "retonly", "retonly", + "CreateHeap", "DestroyHeap", "HeapMalloc", "HeapFree", + "HeapSize", "retonly", "retonly", "call11", + "call12", "call13", "call14", "call15", + "retonly", "retonly" } , + 18 }, +/*13*/ { { "stdio" } , + { "start", "unknown", "unknown", "unknown", + "printf" } , + 5 }, +/*14*/ { { "sifman" } , + { "start", "retonly", "deinit", "retonly", + "sceSif2Init", "sceSifInit", "sceSifSetDChain", "sceSifSetDma", + "sceSifDmaStat", "sceSifSend", "sceSifSendSync", "sceSifIsSending", + "sceSifSetSIF0DMA", "sceSifSendSync0", "sceSifIsSending0", "sceSifSetSIF1DMA", + "sceSifSendSync1", "sceSifIsSending1", "sceSifSetSIF2DMA", "sceSifSendSync2", + "sceSifIsSending2", "getEEIOPflags", "setEEIOPflags", "getIOPEEflags", + "setIOPEEflags", "getEErcvaddr", "getIOPrcvaddr", "setIOPrcvaddr", + "call28", "sceSifCheckInit", "setSif0CB", "resetSif0CB", + "retonly", "retonly", "retonly", "retonly" } , + 36 }, +/*16*/ { { "sifcmd" } , + { "start", "retonly", "deinit", "retonly", + "sceSifInitCmd", "sceSifExitCmd", "sceSifGetSreg", "sceSifSetSreg", + "sceSifSetCmdBuffer", "sceSifSetSysCmdBuffer", + "sceSifAddCmdHandler", "sceSifRemoveCmdHandler", + "sceSifSendCmd", "isceSifSendCmd", "sceSifInitRpc", "sceSifBindRpc", + "sceSifCallRpc", "sceSifRegisterRpc", + "sceSifCheckStatRpc", "sceSifSetRpcQueue", + "sceSifGetNextRequest", "sceSifExecRequest", + "sceSifRpcLoop", "sceSifGetOtherData", + "sceSifRemoveRpc", "sceSifRemoveRpcQueue", + "setSif1CB", "resetSif1CB", + "retonly", "retonly", "retonly", "retonly" } , + 32 }, +/*19*/ { { "cdvdman" } , + { "start", "retonly", "retonly", "retonly", + "sceCdInit", "sceCdStandby", "sceCdRead", "sceCdSeek", + "sceCdGetError", "sceCdGetToc", "sceCdSearchFile", "sceCdSync", + "sceCdGetDiskType", "sceCdDiskReady", "sceCdTrayReq", "sceCdStop", + "sceCdPosToInt", "sceCdIntToPos", "retonly", "call19", + "sceDvdRead", "sceCdCheckCmd", "_sceCdRI", "sceCdWriteILinkID", + "sceCdReadClock", "sceCdWriteRTC", "sceCdReadNVM", "sceCdWriteNVM", + "sceCdStatus", "sceCdApplySCmd", "setHDmode", "sceCdOpenConfig", + "sceCdCloseConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdReadKey", + "sceCdDecSet", "sceCdCallback", "sceCdPause", "sceCdBreak", + "call40", "sceCdReadConsoleID", "sceCdWriteConsoleID", "sceCdGetMecaconVersion", + "sceCdGetReadPos", "AudioDigitalOut", "sceCdNop", "_sceGetFsvRbuf", + "_sceCdstm0Cb", "_sceCdstm1Cb", "_sceCdSC", "_sceCdRC", + "sceCdForbidDVDP", "sceCdReadSubQ", "sceCdApplyNCmd", "AutoAdjustCtrl", + "sceCdStInit", "sceCdStRead", "sceCdStSeek", "sceCdStStart", + "sceCdStStat", "sceCdStStop" } , + 62 }, +/*??*/ { { "sio2man" } , + { "start", "retonly", "deinit", "retonly", + "set8268_ctrl", "get8268_ctrl", "get826C_recv1", "call7_send1", + "call8_send1", "call9_send2", "call10_send2", "get8270_recv2", + "call12_set_params", "call13_get_params", "get8274_recv3", "set8278", + "get8278", "set827C", "get827C", "set8260_datain", + "get8264_dataout", "set8280_intr", "get8280_intr", "signalExchange1", + "signalExchange2", "packetExchange" } , + 26 } +}; + +#define Ra0 ((char*)PSXM(psxRegs.GPR.n.a0)) +#define Ra1 ((char*)PSXM(psxRegs.GPR.n.a1)) +#define Ra2 ((char*)PSXM(psxRegs.GPR.n.a2)) +#define Ra3 ((char*)PSXM(psxRegs.GPR.n.a3)) + +char* intrname[]={ +"INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00 +"INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04 +"INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08 +"INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C +"INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10 +"INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14 +"INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18 +"INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C +"INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20 +"INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24 +"INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28 +"INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C +"INT_30", "INT_31", "INT_32", "INT_33", //30 +"INT_34", "INT_35", "INT_36", "INT_37", //34 +"INT_38", "INT_39", "INT_3A", "INT_3B", //38 +"INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C +"INT_MAX" //40 +}; + +void zeroEx() { + u32 pc; + u32 code; + char *lib; + char *fname = NULL; + int i; + + if (!Config.PsxOut) return; + + pc = psxRegs.pc; + while (PSXMu32(pc) != 0x41e00000) pc-=4; + + lib = (char*)PSXM(pc+12); + code = PSXMu32(psxRegs.pc - 4) & 0xffff; + + for (i=0; i= (u32)irxlibs[i].maxn) break; + + fname = irxlibs[i].names[code]; break; + } + } + +#ifdef PSXBIOS_LOG + {char libz[9]; memcpy(libz, lib, 8); libz[8]=0; + PSXBIOS_LOG("%s: %s (%x)" + " (%x, %x, %x, %x)" //comment this line to disable param showing + , libz, fname == NULL ? "unknown" : fname, code, + psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + } +#endif + +// Log=0; +// if (!strcmp(lib, "intrman") && code == 0x11) Log=1; +// if (!strcmp(lib, "sifman") && code == 0x5) Log=1; +// if (!strcmp(lib, "sifcmd") && code == 0x4) Log=1; +// if (!strcmp(lib, "thbase") && code == 0x6) Log=1; +/* + if (!strcmp(lib, "sifcmd") && code == 0xe) { + branchPC = psxRegs.GPR.n.ra; + psxRegs.GPR.n.v0 = 0; + return; + } +*/ + if (!strncmp(lib, "ioman", 5) && code == 7) { + if (psxRegs.GPR.n.a0 == 1) { + pc = psxRegs.pc; + bios_write(); + psxRegs.pc = pc; + } + } + + if (!strncmp(lib, "sysmem", 6) && code == 0xe) { + bios_printf(); + psxRegs.pc = psxRegs.GPR.n.ra; + } + + if (!strncmp(lib, "loadcore", 8) && code == 6) { + SysPrintf("loadcore RegisterLibraryEntries (%x): %8.8s\n", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12)); + } + + if (!strncmp(lib, "intrman", 7) && code == 4) { + SysPrintf("intrman RegisterIntrHandler (%x): intr %s, handler %x\n", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2); + } + + if (!strncmp(lib, "sifcmd", 6) && code == 17) { + SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1); + } + +#ifdef PSXBIOS_LOG + if (!strncmp(lib, "sysclib", 8)) { + switch (code) { + case 0x16: // strcmp + if (varLog & 0x00800000) EMU_LOG(" \"%s\": \"%s\"", Ra0, Ra1); + break; + + case 0x1e: // strncpy + if (varLog & 0x00800000) EMU_LOG(" \"%s\"", Ra1); + break; + } + } +#endif + +#ifdef PSXBIOS_LOG + if (varLog & 0x00800000) EMU_LOG("\n"); +#endif + +/* psxRegs.pc = branchPC; + pc = psxRegs.GPR.n.ra; + while (psxRegs.pc != pc) psxCpu->ExecuteBlock(); + +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("%s: %s (%x) END\n", lib, fname == NULL ? "unknown" : fname, code); +#endif*/ +} +/*/==========================================CALL LOG +char* getName(char *file, u32 addr){ + FILE *f; u32 a; + static char name[100]; + + f=fopen(file, "r"); + if (!f) + name[0]=0; + else{ + while (!feof(f)){ + fscanf(f, "%08X %s\r\n", &a, name); + if (a==addr)break; + } + fclose(f); + } + return name; +} + +void spyFunctions(){ + register irxImageInfo *iii; + if (psxRegs.pc >= 0x200000) return; + for (iii=(irxImageInfo*)PSXM(0x800); iii && iii->text_size; + iii=iii->next ? (irxImageInfo*)PSXM(iii->next) : NULL) + if (iii->vaddr<=psxRegs.pc && psxRegs.pcvaddr+iii->text_size+iii->data_size+iii->bss_size){ + if (strcmp("secrman_for_cex", PSXM(iii->name))==0){ + char *name=getName("secrman.fun", psxRegs.pc-iii->vaddr); + if (strncmp("__push_params", name, 13)==0){ + PAD_LOG(PSXM(psxRegs.GPR.n.a0), psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); + }else{ + PAD_LOG("secrman: %s (ra=%06X cycle=%d)\n", name, psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}}else + if (strcmp("mcman", PSXM(iii->name))==0){ + PAD_LOG("mcman: %s (ra=%06X cycle=%d)\n", getName("mcman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("padman", PSXM(iii->name))==0){ + PAD_LOG("padman: %s (ra=%06X cycle=%d)\n", getName("padman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else + if (strcmp("sio2man", PSXM(iii->name))==0){ + PAD_LOG("sio2man: %s (ra=%06X cycle=%d)\n", getName("sio2man.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);} + break; + } +} +*/ +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow) +void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im +void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im +void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im +void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im +void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed) +void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow) +void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt +void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow) +void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt +void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt +void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt +void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt +void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt +void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed) +void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +void psxDIV() { + if (_rRt_ != 0) { + _rLo_ = _i32(_rRs_) / _i32(_rRt_); + _rHi_ = _i32(_rRs_) % _i32(_rRt_); + } +} + +void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi +void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs +void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +void psxBREAK() { + // Break exception - psx rom doens't handles this + psxRegs.pc -= 4; + psxException(0x24, branch); +} + +void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); + +} + +void psxRFE() { +// SysPrintf("RFE\n"); + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +// Log=0; +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_); + +void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt +void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +void psxJ() { doBranch(_JumpTarget_); } +void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); /*spyFunctions();*/ } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +void psxJR() { doBranch(_u32(_rRs_)); } +void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); } + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +void psxLB() { + if (_Rt_) { + _rRt_ = (s8 )psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLBU() { + if (_Rt_) { + _rRt_ = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +void psxLH() { + if (_Rt_) { + _rRt_ = (s16)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLHU() { + if (_Rt_) { + _rRt_ = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +void psxLW() { + if (_Rt_) { + _rRt_ = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +void psxLWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) | + ( mem << (24 - shift) ); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + + */ +} + +void psxLWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) | + ( mem >> shift ); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + + */ +} + +void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +void psxSWL() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) | + ( mem & (0xffffff00 << shift) )); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + + */ +} + +void psxSWR() { + u32 shift = (_oB_ & 3) << 3; + u32 mem = psxMemRead32(_oB_ & 0xfffffffc); + + psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) | + (mem & (0x00ffffff >> (24 - shift)) ) ) ); + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } +void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } + +void psxMTC0() { _rFs_ = _u32(_rRt_); } +void psxCTC0() { _rFs_ = _u32(_rRt_); } + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +void psxNULL() { +SysPrintf("psx: Unimplemented op %x\n", psxRegs.code); +} + +void psxSPECIAL() { + psxSPC[_Funct_](); +} + +void psxREGIMM() { + psxREG[_Rt_](); +} + +void psxCOP0() { + psxCP0[_Rs_](); +} + +void psxCOP2() { + psxCP2[_Funct_](); +} + +void psxBASIC() { + psxCP2BSC[_Rs_](); +} + + +void (*psxBSC[64])() = { + psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, + psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , + psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL +}; + + +void (*psxSPC[64])() = { + psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV, + psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL, + psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL, + psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL, + psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR , + psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL +}; + +void (*psxREG[32])() = { + psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP0[32])() = { + psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +void (*psxCP2[64])() = { + psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08 + psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 + psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38 +}; + +void (*psxCP2BSC[32])() = { + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + + +/////////////////////////////////////////// + +static int intInit() { + return 0; +} + +static void intReset() { +} + +static void intExecute() { + for (;;) execI(); +} + +#ifdef _DEBUG +extern u32 psxdump; +extern void iDumpPsxRegisters(u32,u32); +#endif + +static void intExecuteBlock() { + while (EEsCycle > 0){ + branch2 = 0; + while (!branch2) { + execI(); + +#ifdef _DEBUG + if( psxdump & 16 ) { + iDumpPsxRegisters(psxRegs.pc,1); + } +#endif + } + } +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +}; diff --git a/pcsx2/PsxMem.c b/pcsx2/PsxMem.c new file mode 100644 index 0000000..23d5fe0 --- /dev/null +++ b/pcsx2/PsxMem.c @@ -0,0 +1,778 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" +#include "VU.h" +#include "iCore.h" +#include "iR3000A.h" + +extern u32 g_psxMaxRecMem; +int g_psxWriteOk=1; +static u32 writectrl; + +#ifdef PCSX2_VIRTUAL_MEM + +int psxMemInit() +{ + // all mem taken care by memInit + return 0; +} + +void psxMemReset() +{ + memset(psxM, 0, 0x00200000); +} + +void psxMemShutdown() +{ +} + +u8 psxMemRead8(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + break; + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + mem &= 0x1fffffff; + return psxHw4Read8(mem); + + case 0x1000: return DEV9read8(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u8*)PSXM(mem); + } +} + +u16 psxMemRead16(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu16(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu16(0x1000F240) | 0x0002; + case 0x60: return 0; + default: return *(u16*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1f90: + return SPU2read(mem & 0x1FFFFFFF); + case 0x1000: + return DEV9read16(mem & 0x1FFFFFFF); + + default: + assert( g_psxWriteOk ); + return *(u16*)PSXM(mem); + } +} + +u32 psxMemRead32(u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + break; + + case 0x1d00: +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, psxHu32(mem)); +#endif + switch(mem & 0xF0) + { + case 0x40: return psHu32(0x1000F240) | 0xF0000002; + case 0x60: return 0; + default: return *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)); + } + break; + + case 0x1fff: return g_psxWriteOk; + case 0x1000: + return DEV9read32(mem & 0x1FFFFFFF); + + default: + //assert(g_psxWriteOk); + if( mem == 0xfffe0130 ) + return writectrl; + else if( mem == 0xffffffff ) + return writectrl; + else if( g_psxWriteOk ) + return *(u32*)PSXM(mem); + else return 0; + } +} + +void psxMemWrite8(u32 mem, u8 value) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + break; + + case 0x1f40: + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + break; + + case 0x1d00: + SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + *(u8*)(PS2MEM_HW+0xf200+(mem&0xff)) = value; + break; + + case 0x1000: + DEV9write8(mem & 0x1fffffff, value); + return; + + default: + assert(g_psxWriteOk); + *(u8 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +void psxMemWrite16(u32 mem, u16 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + default: + assert(0); + } + return; + + case 0x1f90: + SPU2write(mem & 0x1FFFFFFF, value); return; + + case 0x1000: + DEV9write16(mem & 0x1fffffff, value); return; + default: + assert( g_psxWriteOk ); + *(u16 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + break; + } +} + +void psxMemWrite32(u32 mem, u32 value) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + break; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + default: + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + } + + return; + + case 0x1000: + DEV9write32(mem & 0x1fffffff, value); + return; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + g_psxWriteOk = 0; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + g_psxWriteOk = 1; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + break; + + default: + + if( g_psxWriteOk ) { + *(u32 *)PSXM(mem) = value; + psxCpu->Clear(mem&~3, 1); + } + + break; + } +} + +#else + +// TLB functions + +s8 *psxM; +s8 *psxP; +s8 *psxH; +s8 *psxS; +uptr *psxMemWLUT; +uptr *psxMemRLUT; + +int psxMemInit() +{ + int i; + + psxMemRLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + psxMemWLUT = (uptr*)_aligned_malloc(0x10000 * sizeof(uptr),16); + memset(psxMemRLUT, 0, 0x10000 * sizeof(uptr)); + memset(psxMemWLUT, 0, 0x10000 * sizeof(uptr)); + + psxM = (char*)SysMmap(PS2MEM_PSX_, 0x00200000); + psxP = (char*)SysMmap(PS2MEM_BASE_+0x1f000000, 0x00010000); + psxH = (char*)SysMmap(PS2MEM_BASE_+0x1f800000, 0x00010000); + psxS = (char*)SysMmap(PS2MEM_BASE_+0x1d000000, 0x00010000); + + assert( (uptr)psxM <= 0xffffffff && (uptr)psxP <= 0xffffffff && (uptr)psxH <= 0xffffffff && (uptr)psxS <= 0xffffffff); + + if (psxMemRLUT == NULL || psxMemWLUT == NULL || + psxM == NULL || psxP == NULL || psxH == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + memset(psxH, 0, 0x00010000); + memset(psxS, 0, 0x00010000); + + +// MemR + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemRLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0x9fc0] = (uptr)&PS2MEM_ROM[i << 16]; + for (i=0; i<0x0040; i++) psxMemRLUT[i + 0xbfc0] = (uptr)&PS2MEM_ROM[i << 16]; + + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0x9e00] = (uptr)&PS2MEM_ROM1[i << 16]; + for (i=0; i<0x0004; i++) psxMemRLUT[i + 0xbe00] = (uptr)&PS2MEM_ROM1[i << 16]; + + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; + for (i=0; i<0x0001; i++) psxMemRLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + +// MemW + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f00] = (uptr)&psxP[i << 16]; + + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1f80] = (uptr)&psxH[i << 16]; + for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbf80] = (uptr)&psxH[i << 16]; + +// for (i=0; i<0x0008; i++) psxMemWLUT[i + 0xbfc0] = (uptr)&psR[i << 16]; + +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0x1d00] = (uptr)&psxS[i << 16]; +// for (i=0; i<0x0001; i++) psxMemWLUT[i + 0xbd00] = (uptr)&psxS[i << 16]; + + return 0; +} + +void psxMemReset() { + memset(psxM, 0, 0x00200000); + memset(psxP, 0, 0x00010000); + //memset(psxS, 0, 0x00010000); +} + +void psxMemShutdown() +{ + SysMunmap((uptr)psxM, 0x00200000); psxM = NULL; + SysMunmap((uptr)psxP, 0x00010000); psxP = NULL; + SysMunmap((uptr)psxH, 0x00010000); psxH = NULL; + SysMunmap((uptr)psxS, 0x00010000); psxS = NULL; + _aligned_free(psxMemRLUT); + _aligned_free(psxMemWLUT); +} + +u8 psxMemRead8(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu8(mem); + else + return psxHwRead8(mem); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + return psxHw4Read8(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + return *(u8 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read8(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lb %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u16 psxMemRead16(u32 mem) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu16(mem); + else + return psxHwRead16(mem); + } else { + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u16 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu16(0x1000F200); + break; + case 0x10: + ret= psHu16(0x1000F210); + break; + case 0x40: + ret= psHu16(0x1000F240) | 0x0002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu16(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u16 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1F90) + return SPU2read(mem & 0x1FFFFFFF); + if (t == 0x1000) return DEV9read16(mem & 0x1FFFFFFF); +#ifdef PSXMEM_LOG + PSXMEM_LOG("err lh %8.8lx\n", mem); +#endif + return 0; + } + } +} + +u32 psxMemRead32(u32 mem) { + char *p; + u32 t; + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + return psxHu32(mem); + else + return psxHwRead32(mem); + } else { + //see also Hw.c + p = (char *)(psxMemRLUT[mem >> 16]); + if (p != NULL) { + if (t == 0x1d00) { + u32 ret; + switch(mem & 0xF0) + { + case 0x00: + ret= psHu32(0x1000F200); + break; + case 0x10: + ret= psHu32(0x1000F210); + break; + case 0x20: + ret= psHu32(0x1000F220); + break; + case 0x30: // EE Side + ret= psHu32(0x1000F230); + break; + case 0x40: + ret= psHu32(0x1000F240) | 0xF0000002; + break; + case 0x60: + ret = 0; + break; + default: + ret = psxHu32(mem); + break; + } +#ifdef SIF_LOG + SIF_LOG("Sif reg read %x value %x\n", mem, ret); +#endif + return ret; + } + return *(u32 *)(p + (mem & 0xffff)); + } else { + if (t == 0x1000) return DEV9read32(mem & 0x1FFFFFFF); + + if (mem != 0xfffe0130) { +#ifdef PSXMEM_LOG + if (g_psxWriteOk) PSXMEM_LOG("err lw %8.8lx\n", mem); +#endif + } else { + return writectrl; + } + return 0; + } + } +} + +void psxMemWrite8(u32 mem, u8 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu8(mem) = value; + else + psxHwWrite8(mem, value); + } else + if (t == 0x1f40) { + mem&= 0x1fffffff; + psxHw4Write8(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u8 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw8 [0x%08X]=0x%08X\n", mem, value); + if (t == 0x1d00) { + psxSu8(mem) = value; return; + } + if (t == 0x1000) { + DEV9write8(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sb %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite16(u32 mem, u16 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu16(mem) = value; + else + psxHwWrite16(mem, value); + } else { + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + if ((t & 0x1FFF)==0x1D00) SysPrintf("sw16 [0x%08X]=0x%08X\n", mem, value); + *(u16 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (t == 0x1d00) { + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu16(0x1000F210) = value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu16(0x1000F240) &= ~0xF000; + psHu16(0x1000F240) |= 0x2000; + } + + + if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + else psHu16(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu16(mem) = value; return; + } + if (t == 0x1F90) { + SPU2write(mem & 0x1FFFFFFF, value); return; + } + if (t == 0x1000) { + DEV9write16(mem & 0x1fffffff, value); return; + } +#ifdef PSXMEM_LOG + PSXMEM_LOG("err sh %8.8lx = %x\n", mem, value); +#endif + } + } +} + +void psxMemWrite32(u32 mem, u32 value) { + char *p; + u32 t; + + t = (mem >> 16) & 0x1fff; + if (t == 0x1f80) { + mem&= 0x1fffffff; + if (mem < 0x1f801000) + psxHu32(mem) = value; + else + psxHwWrite32(mem, value); + } else { + //see also Hw.c + p = (char *)(psxMemWLUT[mem >> 16]); + if (p != NULL) { + *(u32 *)(p + (mem & 0xffff)) = value; + psxCpu->Clear(mem&~3, 1); + } else { + if (mem != 0xfffe0130) { + if (t == 0x1d00) { +#ifdef MEM_LOG + MEM_LOG("iop Sif reg write %x value %x\n", mem, value); +#endif + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + psHu32(0x1000F210) = value; + return; + case 0x20: + // write to ps2 mem + psHu32(0x1000F220) &= ~value; + return; + case 0x30: + // write to ps2 mem + psHu32(0x1000F230) |= value; + return; + case 0x40: + { + u32 temp = value & 0xF0; + // write to ps2 mem + if(value & 0x20 || value & 0x80) + { + psHu32(0x1000F240) &= ~0xF000; + psHu32(0x1000F240) |= 0x2000; + } + + + if(psHu32(0x1000F240) & temp) psHu32(0x1000F240) &= ~temp; + else psHu32(0x1000F240) |= temp; + return; + } + case 0x60: + psHu32(0x1000F260) = 0; + return; + + } + psxSu32(mem) = value; + + // write to ps2 mem + if( (mem & 0xf0) != 0x60 ) + *(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value; + return; + } + if (t == 0x1000) { + DEV9write32(mem & 0x1fffffff, value); return; + } + + //if (!g_psxWriteOk) psxCpu->Clear(mem&~3, 1); +#ifdef PSXMEM_LOG + if (g_psxWriteOk) { PSXMEM_LOG("err sw %8.8lx = %x\n", mem, value); } +#endif + } else { + int i; + + writectrl = value; + switch (value) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + if (g_psxWriteOk == 0) break; + g_psxWriteOk = 0; + memset(psxMemWLUT + 0x0000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0x8000, 0, 0x80 * sizeof(uptr)); + memset(psxMemWLUT + 0xa000, 0, 0x80 * sizeof(uptr)); +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: writenot ok\n"); +#endif + break; + case 0x1e988: + case 0x1edd8: + if (g_psxWriteOk == 1) break; + g_psxWriteOk = 1; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0x8000] = (uptr)&psxM[(i & 0x1f) << 16]; + for (i=0; i<0x0080; i++) psxMemWLUT[i + 0xa000] = (uptr)&psxM[(i & 0x1f) << 16]; +#ifdef PSXMEM_LOG +// PSXMEM_LOG("writectrl: write ok\n"); +#endif + break; + default: +#ifdef PSXMEM_LOG + PSXMEM_LOG("unk %8.8lx = %x\n", mem, value); +#endif + break; + } + } + } + } +} + +#endif diff --git a/pcsx2/PsxMem.h b/pcsx2/PsxMem.h new file mode 100644 index 0000000..f20d430 --- /dev/null +++ b/pcsx2/PsxMem.h @@ -0,0 +1,113 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXMEMORY_H__ +#define __PSXMEMORY_H__ + +#ifdef PCSX2_VIRTUAL_MEM + +// VM +#define psxM PS2MEM_PSX +#define psxH PS2MEM_PSXHW + +#define PSXM(mem) ((mem&0x10000000)?PSM(mem):(PS2MEM_PSX+(mem&0x1fffff))) +#define _PSXM(mem) PSXM(mem) + +#else + +// TLB +extern s8 *psxM; +extern s8 *psxP; +extern s8 *psxH; +extern s8 *psxS; +extern uptr *psxMemWLUT; +extern uptr *psxMemRLUT; + +#define PSXM(mem) (psxMemRLUT[(mem) >> 16] == 0 ? NULL : (void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) +#define _PSXM(mem) ((void*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))) + +#define psxSs8(mem) psxS[(mem) & 0xffff] +#define psxSs16(mem) (*(s16*)&psxS[(mem) & 0xffff]) +#define psxSs32(mem) (*(s32*)&psxS[(mem) & 0xffff]) +#define psxSu8(mem) (*(u8*) &psxS[(mem) & 0xffff]) +#define psxSu16(mem) (*(u16*)&psxS[(mem) & 0xffff]) +#define psxSu32(mem) (*(u32*)&psxS[(mem) & 0xffff]) + +#endif + +#define psxMs8(mem) psxM[(mem) & 0x1fffff] +#define psxMs16(mem) (*(s16*)&psxM[(mem) & 0x1fffff]) +#define psxMs32(mem) (*(s32*)&psxM[(mem) & 0x1fffff]) +#define psxMu8(mem) (*(u8*) &psxM[(mem) & 0x1fffff]) +#define psxMu16(mem) (*(u16*)&psxM[(mem) & 0x1fffff]) +#define psxMu32(mem) (*(u32*)&psxM[(mem) & 0x1fffff]) +#define psxMu64(mem) (*(u64*)&psxM[(mem) & 0x1fffff]) + +#define psxPs8(mem) psxP[(mem) & 0xffff] +#define psxPs16(mem) (*(s16*)&psxP[(mem) & 0xffff]) +#define psxPs32(mem) (*(s32*)&psxP[(mem) & 0xffff]) +#define psxPu8(mem) (*(u8*) &psxP[(mem) & 0xffff]) +#define psxPu16(mem) (*(u16*)&psxP[(mem) & 0xffff]) +#define psxPu32(mem) (*(u32*)&psxP[(mem) & 0xffff]) + +#define psxHs8(mem) psxH[(mem) & 0xffff] +#define psxHs16(mem) (*(s16*)&psxH[(mem) & 0xffff]) +#define psxHs32(mem) (*(s32*)&psxH[(mem) & 0xffff]) +#define psxHu8(mem) (*(u8*) &psxH[(mem) & 0xffff]) +#define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff]) +#define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff]) + +#define PSXMs8(mem) (*(s8 *)_PSXM(mem)) +#define PSXMs16(mem) (*(s16*)_PSXM(mem)) +#define PSXMs32(mem) (*(s32*)_PSXM(mem)) +#define PSXMu8(mem) (*(u8 *)_PSXM(mem)) +#define PSXMu16(mem) (*(u16*)_PSXM(mem)) +#define PSXMu32(mem) (*(u32*)_PSXM(mem)) + +int psxMemInit(); +void psxMemReset(); +void psxMemShutdown(); + +u8 psxMemRead8 (u32 mem); +u16 psxMemRead16(u32 mem); +u32 psxMemRead32(u32 mem); +void psxMemWrite8 (u32 mem, u8 value); +void psxMemWrite16(u32 mem, u16 value); +void psxMemWrite32(u32 mem, u32 value); + +// x86reg and mmreg are always x86 regs +void psxRecMemRead8(); +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead16(); +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign); + +void psxRecMemRead32(); +int psxRecMemConstRead32(u32 x86reg, u32 mem); + +void psxRecMemWrite8(); +int psxRecMemConstWrite8(u32 mem, int mmreg); + +void psxRecMemWrite16(); +int psxRecMemConstWrite16(u32 mem, int mmreg); + +void psxRecMemWrite32(); +int psxRecMemConstWrite32(u32 mem, int mmreg); + + +#endif /* __PSXMEMORY_H__ */ diff --git a/pcsx2/PsxSio2.c b/pcsx2/PsxSio2.c new file mode 100644 index 0000000..bcebdbe --- /dev/null +++ b/pcsx2/PsxSio2.c @@ -0,0 +1,241 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PsxCommon.h" + +/* +w [8268]=0x3bc sio2_start/sio2man +r [8270] padman_start/padman + padman->7480[00]=bit4; + padman->7480[13]=bit5; + packetExchange(&703F8); +w [8268]|=0x0C; +........ +w [8268]|=0x01; + +only recv2 & dataout influences padman +*/ + +// 0xBF808200,0xBF808204,0xBF808208,0xBF80820C, +// 0xBF808210,0xBF808214,0xBF808218,0xBF80821C, packet->sendArray3 +// 0xBF808220,0xBF808224,0xBF808228,0xBF80822C, call12/13_s/getparams +// 0xBF808230,0xBF808234,0xBF808238,0xBF80823C, + +// 0xBF808240,0xBF808248,0xBF808250,0xBF808258, packet->sendArray1/call_7/8 +// 0xBF808244,0xBF80824C,0xBF808254,0xBF80825C, packet->sendArray2/call_9/10 + +// 0xBF808260, serial data/fifo in/out s/get8260_datain/out packet->sendbuf(nomem!) +// 0xBF808268, ctrl s/get8268_ctrl + +// 0xBF80826C, packet->recv1/2/3 get826C_recv1, get8270_recv2, get8274_recv3 +// 0xBF808270,0xBF808274, + +// 0xBF808278,0xBF80827C, s/get8278, s/get827C +// 0xBF808280 interrupt related s/get8280_intr + + +void sio2Reset() { + SysPrintf("Sio2 init\n"); + memset(&sio2, 0, sizeof(sio2)); + sio2.packet.recvVal1 = 0x1D100; // Nothing is connected at start +} + +u32 sio2_getRecv1() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv1 = %x\n",sio2.packet.recvVal1); +#endif + return sio2.packet.recvVal1; +} + +u32 sio2_getRecv2() { +#ifdef PAD_LOG + PAD_LOG("Reading Recv2 = %x\n",0xF); +#endif + return 0xF; +}//0, 0x10, 0x20, 0x10 | 0x20; bits 4 & 5 + +u32 sio2_getRecv3() { + if(sio2.packet.recvVal3 == 0x8C || sio2.packet.recvVal3 == 0x8b || + sio2.packet.recvVal3 == 0x83) + { +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio2.packet.recvVal3); +#endif + sio.packetsize = sio2.packet.recvVal3; + sio2.packet.recvVal3 = 0; // Reset + return sio.packetsize; + }else{ +#ifdef PAD_LOG + PAD_LOG("Reading Recv3 = %x\n",sio.packetsize << 16); +#endif + return sio.packetsize << 16; + } +} + +void sio2_setSend1(u32 index, u32 value){sio2.packet.sendArray1[index]=value;} //0->3 +u32 sio2_getSend1(u32 index){return sio2.packet.sendArray1[index];} //0->3 +void sio2_setSend2(u32 index, u32 value){sio2.packet.sendArray2[index]=value;} //0->3 +u32 sio2_getSend2(u32 index){return sio2.packet.sendArray2[index];} //0->3 + +void sio2_setSend3(u32 index, u32 value) +{ + int i; + sio2.packet.sendArray3[index]=value; +#ifdef PAD_LOG + if (index==15){ + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray1[i]);}PAD_LOG("\n"); + for (i=0; i<4; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray2[i]);}PAD_LOG("\n"); + for (i=0; i<8; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + for ( ; i<16; i++){PAD_LOG("0x%08X ", sio2.packet.sendArray3[i]);}PAD_LOG("\n"); + } +#endif +} //0->15 + +u32 sio2_getSend3(u32 index) {return sio2.packet.sendArray3[index];} //0->15 + +void sio2_setCtrl(u32 value){ + sio2.ctrl=value; + if (sio2.ctrl & 1){ //recv packet + //handle data that had been sent + + //trigger interupt for SIO2 + psxHu32(0x1070)|=0x20000; + //SBUS + hwIntcIrq(INTC_SBUS); + sio2.recvIndex=0; + sio2.ctrl &= ~1; + } else { // send packet + //clean up + sio2.packet.sendSize=0; //reset size + sio2.cmdport=0; + sio2.cmdlength=0; + sioWriteCtrl16(SIO_RESET); + } +} +u32 sio2_getCtrl(){return sio2.ctrl;} + +void sio2_setIntr(u32 value){sio2.intr=value;} +u32 sio2_getIntr(){ + return sio2.intr; +} + +void sio2_set8278(u32 value){sio2._8278=value;} +u32 sio2_get8278(){return sio2._8278;} +void sio2_set827C(u32 value){sio2._827C=value;} +u32 sio2_get827C(){return sio2._827C;} + +void sio2_fifoIn(u8 value){ + u16 ctrl=0x0002; + if (sio2.packet.sendArray3[sio2.cmdport] && (sio2.cmdlength==0)){//else do nothing! + + sio2.cmdlength=(sio2.packet.sendArray3[sio2.cmdport] >> 8) & 0x1FF; + ctrl &= ~0x2000; + ctrl |= (sio2.packet.sendArray3[sio2.cmdport] & 1) << 13; + //sioWriteCtrl16(SIO_RESET); + sioWriteCtrl16(ctrl); +#ifdef PSXDMA_LOG + PSXDMA_LOG("sio2_fifoIn: ctrl = %x, cmdlength = %x, cmdport = %d (%x)\n", ctrl, sio2.cmdlength, sio2.cmdport, sio2.packet.sendArray3[sio2.cmdport]); +#endif + sio2.cmdport++;//position in sendArray3 + } + if (sio2.cmdlength) sio2.cmdlength--; + +// sioWriteCtrl16(ctrl); + + sioWrite8(value); + if (sio2.packet.sendSize > BUFSIZE) {//asadr + SysPrintf("*PCSX2*: sendSize >= %d\n", BUFSIZE); + } else { + sio2.buf[sio2.packet.sendSize] = sioRead8(); + sio2.packet.sendSize++; + } +} + +u8 sio2_fifoOut(){ + if (sio2.recvIndex <= sio2.packet.sendSize){ + return sio2.buf[sio2.recvIndex++]; + } else { + SysPrintf("*PCSX2*: buffer overrun\n"); + } + return 0; // No Data +} + +///////////////////////////////////////////////// +//////////////////////////////////////////// DMA +///////////////////////////////////////////////// + +void psxDma11(u32 madr, u32 bcr, u32 chcr) { +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 11 - SIO2 in *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x01000201) return; + + bcr = ((bcr >> 16) * (bcr & 0xFFFF)) * 4; // 8 bits + while (bcr > 0) { + sio2_fifoIn(PSXMu8(madr)); + bcr--; madr++; + if(sio2.packet.sendSize == BUFSIZE) break; + } + HW_DMA11_MADR = madr; + PSX_INT(11,(bcr>>2)); // Interrupts should always occur at the end +} + +int psxDMA11Interrupt() +{ + HW_DMA11_CHCR &= ~0x01000000; + psxDmaInterrupt2(4); + return 1; +} + +void psxDma12(u32 madr, u32 bcr, u32 chcr) { +#ifdef PSXDMA_LOG + PSXDMA_LOG("*** DMA 12 - SIO2 out *** %lx addr = %lx size = %lx\n", chcr, madr, bcr); +#endif + + if (chcr != 0x41000200) return; + + sio2.recvIndex = 0; // Set To start; saqib + + bcr = ((bcr >> 16) * (bcr & 0xFFFF)) * 4; // 8 bits + + while (bcr > 0) { + PSXMu8(madr) = sio2_fifoOut(); + bcr--; madr++; + if(sio2.recvIndex == sio2.packet.sendSize) break; + } + HW_DMA12_MADR = madr; + PSX_INT(12,(bcr>>2)); // Interrupts should always occur at the end +} + +int psxDMA12Interrupt() +{ + HW_DMA12_CHCR &= ~0x01000000; + psxDmaInterrupt2(5); + return 1; +} + +int sio2Freeze(gzFile f, int Mode) { + gzfreeze(&sio2, sizeof(sio2)); + + return 0; +} + diff --git a/pcsx2/PsxSio2.h b/pcsx2/PsxSio2.h new file mode 100644 index 0000000..6f5aea8 --- /dev/null +++ b/pcsx2/PsxSio2.h @@ -0,0 +1,98 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PSXSIO2_H__ +#define __PSXSIO2_H__ + + +#define BUFSIZE 1024 + +//from sio2man.c + +struct SIO2_packet { + unsigned int recvVal1; // 0x00 + unsigned int sendArray1[4]; // 0x04-0x10 + unsigned int sendArray2[4]; // 0x14-0x20 + + unsigned int recvVal2; // 0x24 + + unsigned int sendArray3[16]; // 0x28-0x64 + + unsigned int recvVal3; // 0x68 + + int sendSize; // 0x6C + int recvSize; // 0x70 + + unsigned char *sendBuf; // 0x74 + unsigned char *recvBuf; // 0x78 + + unsigned int dmacAddress1; + unsigned int dmacSize1; + unsigned int dmacCount1; + unsigned int dmacAddress2; + unsigned int dmacSize2; + unsigned int dmacCount2; +}; + +typedef struct { + struct SIO2_packet packet; + u32 ctrl; + u32 intr; + u32 _8278, _827C; + int recvIndex; + u32 hackedRecv; + int cmdport; + int cmdlength; //length of a command sent to a port + //is less_equal than the dma send size + u8 buf[BUFSIZE]; +} sio2Struct; + +sio2Struct sio2; + +void sio2Reset(); +u32 sio2_getRecv1(); +u32 sio2_getRecv2(); +u32 sio2_getRecv3(); +void sio2_setSend1(u32 index, u32 value); //0->3 +u32 sio2_getSend1(u32 index); //0->3 +void sio2_setSend2(u32 index, u32 value); //0->3 +u32 sio2_getSend2(u32 index); //0->3 +void sio2_setSend3(u32 index, u32 value); //0->15 +u32 sio2_getSend3(u32 index); //0->15 + +void sio2_setCtrl(u32 value); +u32 sio2_getCtrl(); +void sio2_setIntr(u32 value); +u32 sio2_getIntr(); +void sio2_set8278(u32 value); +u32 sio2_get8278(); +void sio2_set827C(u32 value); +u32 sio2_get827C(); + +void sio2_fifoIn(u8 value); +u8 sio2_fifoOut(); + +void psxDma11(u32 madr, u32 bcr, u32 chcr); +void psxDma12(u32 madr, u32 bcr, u32 chcr); + +int psxDMA11Interrupt(); +int psxDMA12Interrupt(); +int sio2Freeze(gzFile f, int Mode); + +#endif /* __PSXSIO2_H__ */ + diff --git a/pcsx2/R3000A.c b/pcsx2/R3000A.c new file mode 100644 index 0000000..8685d8f --- /dev/null +++ b/pcsx2/R3000A.c @@ -0,0 +1,216 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "PsxCommon.h" + + +// used for constant propagation +R3000Acpu *psxCpu; +u32 g_psxConstRegs[32]; +u32 g_psxHasConstReg, g_psxFlushedConstReg; +u32 g_psxNextBranchCycle = 0; + +PCSX2_ALIGNED16(psxRegisters psxRegs); + +int psxInit() +{ + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + +#ifdef PCSX2_DEVBUILD + Log=0; +#endif + + if (psxMemInit() == -1) return -1; + + return psxCpu->Init(); +} + +void psxReset() { + + psxCpu->Reset(); + + psxMemReset(); + + memset(&psxRegs, 0, sizeof(psxRegs)); + + psxRegs.pc = 0xbfc00000; // Start in bootstrap + + psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1 + psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A + + psxHwReset(); + psxBiosInit(); + psxExecuteBios(); +} + +void psxShutdown() { + psxMemShutdown(); + psxBiosShutdown(); + psxSIOShutdown(); + psxCpu->Shutdown(); +} + +void psxException(u32 code, u32 bd) { +// PSXCPU_LOG("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); +// SysPrintf("psxException %x: %x, %x\n", code, psxHu32(0x1070), psxHu32(0x1074)); + // Set the Cause + psxRegs.CP0.n.Cause &= ~0x7f; + psxRegs.CP0.n.Cause |= code; + +#ifdef PSXCPU_LOG + if (bd) { PSXCPU_LOG("bd set\n"); } +#endif + // Set the EPC & PC + if (bd) { + psxRegs.CP0.n.Cause|= 0x80000000; + psxRegs.CP0.n.EPC = (psxRegs.pc - 4); + } else + psxRegs.CP0.n.EPC = (psxRegs.pc); + + if (psxRegs.CP0.n.Status & 0x400000) + psxRegs.pc = 0xbfc00180; + else + psxRegs.pc = 0x80000080; + + // Set the Status + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status &~0x3f) | + ((psxRegs.CP0.n.Status & 0xf) << 2); + + /*if ((((PSXMu32(psxRegs.CP0.n.EPC) >> 24) & 0xfe) == 0x4a)) { + // "hokuto no ken" / "Crash Bandicot 2" ... fix + PSXMu32(psxRegs.CP0.n.EPC)&= ~0x02000000; + }*/ + + if (Config.PsxOut && !CHECK_EEREC) { + u32 call = psxRegs.GPR.n.t1 & 0xff; + switch (psxRegs.pc & 0x1fffff) { + case 0xa0: +#ifdef PSXBIOS_LOG + if (call != 0x28 && call != 0xe) { + PSXBIOS_LOG("Bios call a0: %s (%x) %x,%x,%x,%x\n", biosA0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosA0[call]) + biosA0[call](); + break; + case 0xb0: +#ifdef PSXBIOS_LOG + if (call != 0x17 && call != 0xb) { + PSXBIOS_LOG("Bios call b0: %s (%x) %x,%x,%x,%x\n", biosB0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); } +#endif + if (biosB0[call]) + biosB0[call](); + break; + case 0xc0: +#ifdef PSXBIOS_LOG + PSXBIOS_LOG("Bios call c0: %s (%x) %x,%x,%x,%x\n", biosC0n[call], call, psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3); +#endif + if (biosC0[call]) + biosC0[call](); + break; + } + } + + /*if (psxRegs.CP0.n.Cause == 0x400 && (!(psxHu32(0x1450) & 0x8))) { + hwIntcIrq(1); + }*/ +} + +#define PSX_TESTINT(n, callback) \ + if (psxRegs.interrupt & (1 << n)) { \ + if ((int)(psxRegs.cycle - psxRegs.sCycle[n]) >= psxRegs.eCycle[n]) { \ + if (callback() == 1) { \ + psxRegs.interrupt&= ~(1 << n); \ + } \ + } \ + else if( (int)(g_psxNextBranchCycle - psxRegs.sCycle[n]) > psxRegs.eCycle[n] ) \ + g_psxNextBranchCycle = psxRegs.sCycle[n] + psxRegs.eCycle[n]; \ + } + +static void _psxTestInterrupts() { + PSX_TESTINT(4, psxDma4Interrupt); + PSX_TESTINT(7, psxDma7Interrupt); + + PSX_TESTINT(11, psxDMA11Interrupt); // SIO2 + PSX_TESTINT(12, psxDMA12Interrupt); // SIO2 + PSX_TESTINT(16, sioInterrupt); + PSX_TESTINT(17, cdrInterrupt); + PSX_TESTINT(18, cdrReadInterrupt); + PSX_TESTINT(19, cdvdReadInterrupt); + PSX_TESTINT(20, dev9Interrupt); + PSX_TESTINT(21, usbInterrupt); +} + +#define IOP_WAIT_CYCLE 64 + +void psxBranchTest() +{ + EEsCycle -= (psxRegs.cycle - IOPoCycle) << 3; + IOPoCycle = psxRegs.cycle; + if( EEsCycle > 0 ) + g_psxNextBranchCycle = psxRegs.cycle + min(IOP_WAIT_CYCLE, (EEsCycle>>3)); + else + g_psxNextBranchCycle = psxRegs.cycle; + + if ((int)(psxRegs.cycle - psxNextsCounter) >= psxNextCounter) + psxRcntUpdate(); + + if (psxRegs.interrupt) { + _psxTestInterrupts(); + } + +// if( (int)psxRegs.cycle-(int)g_psxNextBranchCycle > 0 ) +// g_psxNextBranchCycle = psxRegs.cycle+1; +// else + if( (int)(g_psxNextBranchCycle-psxNextsCounter) >= (u32)psxNextCounter ) + g_psxNextBranchCycle = (u32)psxNextsCounter+(u32)psxNextCounter; + + if (psxHu32(0x1078)) { + if(psxHu32(0x1070) & psxHu32(0x1074)){ + if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401) { +//#ifdef PSXCPU_LOG +// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074)); +//#endif + psxException(0, 0); + } + } + } +} + +void psxExecuteBios() { +/* while (psxRegs.pc != 0x80030000) + psxCpu->ExecuteBlock(); +#ifdef PSX_LOG + PSX_LOG("*BIOS END*\n"); +#endif*/ +} + +void psxRestartCPU() +{ + psxCpu->Shutdown(); + psxCpu = CHECK_EEREC ? &psxRec : &psxInt; + + if (psxCpu->Init() == -1) { + SysClose(); + exit(1); + } + psxCpu->Reset(); +} diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h new file mode 100644 index 0000000..be1f7f4 --- /dev/null +++ b/pcsx2/R3000A.h @@ -0,0 +1,213 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R3000A_H__ +#define __R3000A_H__ + +#include + +extern u32 g_psxNextBranchCycle; + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*Clear)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R3000Acpu; + +extern R3000Acpu *psxCpu; +extern R3000Acpu psxInt; +extern R3000Acpu psxRec; + +typedef union { + struct { + u32 r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra, hi, lo; // hi needs to be at index 32! don't change + } n; + u32 r[34]; /* Lo, Hi in r[33] and r[32] */ +} GPRRegs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare, + Status, Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Reserved3, + Reserved4, Reserved5, ECC, CacheErr, + TagLo, TagHi, ErrorEPC, Reserved6; + } n; + u32 r[32]; +} CP0Regs; + +typedef struct { + short x, y; +} SVector2D; + +typedef struct { + short z, pad; +} SVector2Dz; + +typedef struct { + short x, y, z, pad; +} SVector3D; + +typedef struct { + short x, y, z, pad; +} LVector3D; + +typedef struct { + unsigned char r, g, b, c; +} CBGR; + +typedef struct { + short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad; +} SMatrix3D; + +typedef union { + struct { + SVector3D v0, v1, v2; + CBGR rgb; + s32 otz; + s32 ir0, ir1, ir2, ir3; + SVector2D sxy0, sxy1, sxy2, sxyp; + SVector2Dz sz0, sz1, sz2, sz3; + CBGR rgb0, rgb1, rgb2; + s32 reserved; + s32 mac0, mac1, mac2, mac3; + u32 irgb, orgb; + s32 lzcs, lzcr; + } n; + u32 r[32]; +} CP2Data; + +typedef union { + struct { + SMatrix3D rMatrix; + s32 trX, trY, trZ; + SMatrix3D lMatrix; + s32 rbk, gbk, bbk; + SMatrix3D cMatrix; + s32 rfc, gfc, bfc; + s32 ofx, ofy; + s32 h; + s32 dqa, dqb; + s32 zsf3, zsf4; + s32 flag; + } n; + u32 r[32]; +} CP2Ctrl; + +typedef struct { + GPRRegs GPR; /* General Purpose Registers */ + CP0Regs CP0; /* Coprocessor0 Registers */ + CP2Data CP2D; /* Cop2 data registers */ + CP2Ctrl CP2C; /* Cop2 control registers */ + u32 pc; /* Program counter */ + u32 code; /* The instruction */ + u32 cycle; + u32 interrupt; + u32 sCycle[64]; + u32 eCycle[64]; + u32 _msflag[32]; + u32 _smflag[32]; +} psxRegisters; + +extern psxRegisters psxRegs; + +#define PSX_IS_CONST1(reg) ((reg)<32 && (g_psxHasConstReg&(1<<(reg)))) +#define PSX_IS_CONST2(reg1, reg2) ((g_psxHasConstReg&(1<<(reg1)))&&(g_psxHasConstReg&(1<<(reg2)))) +#define PSX_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_psxHasConstReg |= (1<<(reg)); \ + g_psxFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define PSX_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_psxHasConstReg &= ~(1<<(reg)); \ +} + +extern u32 g_psxConstRegs[32]; +extern u32 g_psxHasConstReg, g_psxFlushedConstReg; + +#ifndef _PC_ + +#define _i32(x) (s32)x +#define _u32(x) x + +#define _i16(x) (short)x +#define _u16(x) (unsigned short)x + +#define _i8(x) (char)x +#define _u8(x) (unsigned char)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ psxRegs.pc // The next PC to be executed + +#define _Funct_ ((psxRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((psxRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((psxRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((psxRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((psxRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((unsigned short)psxRegs.code) // The immediate part of the instruction register +#define _Target_ (psxRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((short)psxRegs.code) // sign-extended immediate +#define _ImmU_ (psxRegs.code&0xffff) // zero-extended immediate + +#define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register +#define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register +#define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register +#define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register +#define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register + +#define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register +#define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register +#define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register +#define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register + +#define _rHi_ psxRegs.GPR.n.hi // The HI register +#define _rLo_ psxRegs.GPR.n.lo // The LO register + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Imm_ * 4) + _PC_) // Calculates the target during a branch instruction +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((short)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; + +#endif + +int psxInit(); +void psxReset(); +void psxShutdown(); +void psxException(u32 code, u32 step); +void psxBranchTest(); +void psxExecuteBios(); +void psxRestartCPU(); + +#endif /* __R3000A_H__ */ diff --git a/pcsx2/R5900.c b/pcsx2/R5900.c new file mode 100644 index 0000000..9d56e95 --- /dev/null +++ b/pcsx2/R5900.c @@ -0,0 +1,598 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "Hw.h" +#include "DebugTools/Debug.h" +#include "R3000A.h" +#include "VUmicro.h" +#include "GS.h" + +static int inter; + +PCSX2_ALIGNED16(cpuRegisters cpuRegs); +PCSX2_ALIGNED16(fpuRegisters fpuRegs); +PCSX2_ALIGNED16(tlbs tlb[48]); +PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0}; + +u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0; +R5900cpu *Cpu; + +int EEsCycle; +u32 EEoCycle, IOPoCycle; +u32 bExecBIOS = 0; // set if the BIOS has already been executed + +extern u32 dwSaveVersion; + +int cpuInit() +{ + int ret; + + SysPrintf("PCSX2 v" PCSX2_VERSION " save ver: %x\n", dwSaveVersion); + /*SysPrintf("Color Legend: White - PCSX2 message\n"); + SysPrintf(COLOR_GREEN " Green - EE sio2 printf\n" COLOR_RESET); + SysPrintf(COLOR_RED " Red - IOP printf\n" COLOR_RESET);*/ + SysPrintf("EE pc offset: 0x%x, PSX pc offset: 0x%x\n", (u32)&cpuRegs.pc - (u32)&cpuRegs, (u32)&psxRegs.pc - (u32)&psxRegs); + + InitFPUOps(); + + cpuRegs.constzero = 0; +#ifdef PCSX2_NORECBUILD + Cpu = &intCpu; +#else + cpudetectInit(); + Cpu = CHECK_EEREC ? &recCpu : &intCpu; +#endif + + ret = Cpu->Init(); + if (ret == -1 && CHECK_EEREC) { + SysMessage(_("Error initializing Recompiler, switching to Interpreter")); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC); + Cpu = &intCpu; + ret = Cpu->Init(); + } + +#ifdef PCSX2_VIRTUAL_MEM + if (memInit() == -1) { + PROCESS_INFORMATION pi; + STARTUPINFO si; + char strdir[255], strexe[255]; + if( MessageBox(NULL, "Failed to allocate enough physical memory to run pcsx2. Try closing\n" + "down background programs, restarting windows, or buying more memory.\n\n" + "Launch TLB version of pcsx2 (pcsx2t.exe)?", "Memory Allocation Error", MB_YESNO) == IDYES ) { + + GetCurrentDirectory(ARRAYSIZE(strdir), strdir); + _snprintf(strexe, ARRAYSIZE(strexe), "%s\\pcsx2t.exe", strdir); + + memset(&si, 0, sizeof(si)); + + if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) { + _snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe); + MessageBox(NULL, strdir, "Failure", MB_OK); + } + else { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + } + + return -1; + } +#endif + if (hwInit() == -1) return -1; + if (vu0Init() == -1) return -1; + if (vu1Init() == -1) return -1; +#ifndef PCSX2_VIRTUAL_MEM + if (memInit() == -1) return -1; +#endif + +#ifdef PCSX2_DEVBUILD + Log = 0; +#endif + + return ret; +} + +void cpuReset() +{ + Cpu->Reset(); + + memReset(); + + memset(&cpuRegs, 0, sizeof(cpuRegs)); + memset(&fpuRegs, 0, sizeof(fpuRegs)); + memset(&tlb, 0, sizeof(tlb)); + + cpuRegs.pc = 0xbfc00000; ///set pc reg to stack + cpuRegs.CP0.n.Config = 0x440; + cpuRegs.CP0.n.Status.val = 0x70400004; //0x10900000 <-- wrong; // COP0 enabled | BEV = 1 | TS = 1 + cpuRegs.CP0.n.PRid = 0x00002e20; // PRevID = Revision ID, same as R5900 + fpuRegs.fprc[0] = 0x00002e00; // fpu Revision.. + fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control + + vu0Reset(); + vu1Reset(); + hwReset(); + vif0Reset(); + vif1Reset(); + rcntInit(); + psxReset(); +} + +void cpuShutdown() +{ + hwShutdown(); +// biosShutdown(); + psxShutdown(); + vu0Shutdown(); + vu1Shutdown(); + memShutdown(); + gsShutdown(); + disR5900FreeSyms(); + + Cpu->Shutdown(); +} + +void cpuException(u32 code, u32 bd) { + u32 offset; + cpuRegs.CP0.n.Cause = code & 0xffff; + + if(cpuRegs.CP0.n.Status.b.ERL == 0){ //Error Level 0-1 + if(((code & 0x7C) >= 0x8) && ((code & 0x7C) <= 0xC)) offset = 0x0; //TLB Refill + else if ((code & 0x7C) == 0x0) offset = 0x200; //Interrupt + else offset = 0x180; // Everything else + + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.BEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } else { //Error Level 2 + SysPrintf("FIX ME: Level 2 cpuException\n"); + if((code & 0x38000) <= 0x8000 ) { //Reset / NMI + cpuRegs.pc = 0xBFC00000; + SysPrintf("Reset request\n"); + UpdateCP0Status(); + return; + } else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter + else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug + else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code); + + if (cpuRegs.CP0.n.Status.b.EXL == 0) { + cpuRegs.CP0.n.Status.b.EXL = 1; + if (bd) { + SysPrintf("branch delay!!\n"); + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + cpuRegs.CP0.n.Cause |= 0x80000000; + } else { + cpuRegs.CP0.n.EPC = cpuRegs.pc; + cpuRegs.CP0.n.Cause &= ~0x80000000; + } + } else { + offset = 0x180; //Overrride the cause + SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code); + } + if (cpuRegs.CP0.n.Status.b.DEV == 0) { + cpuRegs.pc = 0x80000000 + offset; + } else { + cpuRegs.pc = 0xBFC00200 + offset; + } + } + UpdateCP0Status(); +} + +void cpuTlbMiss(u32 addr, u32 bd, u32 excode) { + SysPrintf("cpuTlbMiss %x, %x, status=%x, code=%x\n", cpuRegs.pc, cpuRegs.cycle, cpuRegs.CP0.n.Status.val, excode); + if (bd) { + SysPrintf("branch delay!!\n"); + } + + assert(0); // temporary + + cpuRegs.CP0.n.BadVAddr = addr; + cpuRegs.CP0.n.Context &= 0xFF80000F; + cpuRegs.CP0.n.Context |= (addr >> 9) & 0x007FFFF0; + cpuRegs.CP0.n.EntryHi = (addr & 0xFFFFE000) | (cpuRegs.CP0.n.EntryHi & 0x1FFF); + + cpuRegs.CP0.n.Cause = excode; + if (!(cpuRegs.CP0.n.Status.val & 0x2)) { // EXL bit + cpuRegs.CP0.n.EPC = cpuRegs.pc - 4; + } + + if ((cpuRegs.CP0.n.Status.val & 0x1) == 0) { + cpuRegs.pc = 0x80000000; + } else { + cpuRegs.pc = 0x80000180; + } + + cpuRegs.CP0.n.Status.b.EXL = 1; + UpdateCP0Status(); +// Log=1; varLog|= 0x40000000; +} + +void cpuTlbMissR(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBL); +} + +void cpuTlbMissW(u32 addr, u32 bd) { + cpuTlbMiss(addr, bd, EXC_CODE_TLBS); +} + +void JumpCheckSym(u32 addr, u32 pc) { +#if 0 +// if (addr == 0x80051770) { SysPrintf("Log!: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); Log=1; varLog|= 0x40000000; } + if (addr == 0x8002f150) { SysPrintf("printk: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (addr == 0x8002aba0) return; + if (addr == 0x8002f450) return; + if (addr == 0x800dd520) return; +// if (addr == 0x80049300) SysPrintf("register_blkdev: %x\n", cpuRegs.GPR.n.a0.UL[0]); + if (addr == 0x8013cb70) { SysPrintf("change_root: %x\n", cpuRegs.GPR.n.a0.UL[0]); } +// if (addr == 0x8013d1e8) { SysPrintf("Log!\n"); Log++; if (Log==2) exit(0); varLog|= 0x40000000; } +// if (addr == 0x00234e88) { SysPrintf("StoreImage\n"); Log=1; /*psMu32(0x234e88) = 0x03e00008; psMu32(0x234e8c) = 0;*/ } +#endif +/* if ((pc >= 0x00131D50 && + pc < 0x00132454) || + (pc >= 0x00786a90 && + pc < 0x00786ac8))*/ + /*if (varLog & 0x40000000) { + char *str; + char *strf; + + str = disR5900GetSym(addr); + if (str != NULL) { + strf = disR5900GetUpperSym(pc); + if (strf) { + SysPrintf("Func %8.8x: %s (called by %8.8x: %s)\n", addr, str, pc, strf); + } else { + SysPrintf("Func %8.8x: %s (called by %x)\n", addr, str, pc); + } + if (!strcmp(str, "printf")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + if (!strcmp(str, "printk")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); } + } + }*/ +} + +void JumpCheckSymRet(u32 addr) { + /*if (varLog & 0x40000000) { + char *str; + str = disR5900GetUpperSym(addr); + if (str != NULL) { + SysPrintf("Return : %s, v0=%8.8x\n", str, cpuRegs.GPR.n.v0.UL[0]); + } + }*/ +} + +__inline void _cpuTestMissingINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 && + psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + SysPrintf("*PCSX2*: Error, missing INTC Interrupt\n"); + } + } +} + +__inline void _cpuTestMissingDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 && + (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000)) { + if ((cpuRegs.interrupt & (1 << 31)) == 0) { + SysPrintf("*PCSX2*: Error, missing DMAC Interrupt\n"); + } + } +} + +void cpuTestMissingHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestMissingINTC(); + _cpuTestMissingDMAC(); +// _cpuTestTIMR(); + } +} + +#define TESTINT(n, callback) { \ + if ( (cpuRegs.interrupt & (1 << n)) ) { \ + if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \ + if (callback() == 1) { \ + cpuRegs.interrupt &= ~(1 << n); \ + } \ + } \ + else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \ + g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \ + } \ + } \ +} \ + +void _cpuTestInterrupts() { + + inter = cpuRegs.interrupt; + /* These are 'pcsx2 interrupts', they handle asynchronous stuff + that depends on the cycle timings */ + + TESTINT(0, vif0Interrupt); + TESTINT(10, vifMFIFOInterrupt); + TESTINT(1, vif1Interrupt); + TESTINT(11, gifMFIFOInterrupt); + TESTINT(2, gsInterrupt); + TESTINT(3, ipu0Interrupt); + TESTINT(4, ipu1Interrupt); + TESTINT(5, EEsif0Interrupt); + TESTINT(6, EEsif1Interrupt); + TESTINT(8, SPRFROMinterrupt); + TESTINT(9, SPRTOinterrupt); + + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + TESTINT(30, intcInterrupt); + TESTINT(31, dmacInterrupt); +} + +u32 s_iLastCOP0Cycle = 0; +u32 s_iLastPERFCycle[2] = {0,0}; + +static void _cpuTestTIMR() { + cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle; + s_iLastCOP0Cycle = cpuRegs.cycle; + + if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) { + cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0]; + s_iLastPERFCycle[0] = cpuRegs.cycle; + } + if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) { + cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1]; + s_iLastPERFCycle[1] = cpuRegs.cycle; + } + + if ( (cpuRegs.CP0.n.Status.val & 0x8000) && + cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) { + SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare); + cpuException(0x808000, cpuRegs.branch); + } +} + +#define EE_WAIT_CYCLE 512 + +// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates +u32 g_nextBranchCycle = 0; +u32 s_lastvsync[2]; +extern u8 g_globalXMMSaved; +X86_32CODE(extern u8 g_globalMMXSaved;) + +u32 loaded = 0; + +void cpuBranchTest() +{ +#ifndef PCSX2_NORECBUILD + assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) ); + g_EEFreezeRegs = 0; +#endif + +// if( !loaded && cpuRegs.cycle > 0x20000000 ) { +// char strstate[255]; +// sprintf(strstate, "sstates/%8.8X.002", ElfCRC); +// LoadState(strstate); +// loaded = 1; +// } + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + +#ifndef PCSX2_NORECBUILD + assert( !g_globalXMMSaved X86_32CODE(&& !g_globalMMXSaved) ); + g_EEFreezeRegs = 1; +#endif +} + +static void _cpuTestINTC() { + if (cpuRegs.CP0.n.Status.val & 0x400 ){ + if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) { + if ((cpuRegs.interrupt & (1 << 30)) == 0) { + INT(30,4); + } + } + } +} + +static void _cpuTestDMAC() { + if (cpuRegs.CP0.n.Status.val & 0x800 ){ + if (psHu16(0xe012) & psHu16(0xe010) || + psHu16(0xe010) & 0x8000) { + if ( (cpuRegs.interrupt & (1 << 31)) == 0) { + INT(31, 4); + } + } + } +} + +void cpuTestHwInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return; + _cpuTestINTC(); + _cpuTestDMAC(); + _cpuTestTIMR(); +} + +void cpuTestINTCInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestINTC(); + } +} + +void cpuTestDMACInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestDMAC(); + } +} + +void cpuTestTIMRInts() { + if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) { + _cpuTestTIMR(); + } +} + +void cpuExecuteBios() +{ + // filter CPU options + if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC; + else Config.Options &= ~PCSX2_COP2REC; + +#ifndef PCSX2_NORECBUILD + if( !cpucaps.hasStreamingSIMDExtensions ) { + Config.Options &= ~(PCSX2_VU1REC|PCSX2_VU0REC); + } +#endif + + // remove frame skipping if GS doesn't support it + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_SKIP: + case PCSX2_FRAMELIMIT_VUSKIP: + if( GSsetFrameSkip == NULL ) + Config.Options &= ~PCSX2_FRAMELIMIT_MASK; + break; + } + + SysPrintf("Using Frame Skipping: "); + switch(CHECK_FRAMELIMIT) { + case PCSX2_FRAMELIMIT_NORMAL: SysPrintf("Normal\n"); break; + case PCSX2_FRAMELIMIT_LIMIT: SysPrintf("Limit\n"); break; + case PCSX2_FRAMELIMIT_SKIP: SysPrintf("Skip\n"); break; + case PCSX2_FRAMELIMIT_VUSKIP: SysPrintf("VU Skip\n"); break; + } + + + SysPrintf("* PCSX2 *: ExecuteBios\n"); + + bExecBIOS = TRUE; + while (cpuRegs.pc != 0x00200008 && + cpuRegs.pc != 0x00100008) { + Cpu->ExecuteBlock(); + } + + bExecBIOS = FALSE; +// REC_CLEARM(0x00200008); +// REC_CLEARM(0x00100008); +// REC_CLEARM(cpuRegs.pc); + if( CHECK_EEREC ) Cpu->Reset(); + + SysPrintf("* PCSX2 *: ExecuteBios Complete\n"); + GSprintf(5, "PCSX2 v" PCSX2_VERSION "\nExecuteBios Complete\n"); +} + +void cpuRestartCPU() +{ +#ifdef PCSX2_NORECBUILD + Cpu = &intCpu; +#else + Cpu = CHECK_EEREC ? &recCpu : &intCpu; +#endif + + // restart vus + if (Cpu->Init() == -1) { + SysClose(); + exit(1); + } + + vu0Init(); + vu1Init(); + Cpu->Reset(); + psxRestartCPU(); +} + +// for interpreter only +void IntcpuBranchTest() +{ +#ifndef PCSX2_NORECBUILD + g_EEFreezeRegs = 0; +#endif + + g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE; + + if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter) + rcntUpdate(); + + if (cpuRegs.interrupt) + _cpuTestInterrupts(); + + if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter ) + g_nextBranchCycle = nextsCounter+nextCounter; + +//#ifdef CPU_LOG +// cpuTestMissingHwInts(); +//#endif + _cpuTestTIMR(); + + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + psxCpu->ExecuteBlock(); + + if (VU0.VI[REG_VPU_STAT].UL & 0x1) { + Cpu->ExecuteVU0Block(); + } + if (VU0.VI[REG_VPU_STAT].UL & 0x100) { + Cpu->ExecuteVU1Block(); + } + + if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 ) + g_nextBranchCycle = cpuRegs.cycle+1; + +#ifndef PCSX2_NORECBUILD + g_EEFreezeRegs = 1; +#endif +} diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h new file mode 100644 index 0000000..31ff9dc --- /dev/null +++ b/pcsx2/R5900.h @@ -0,0 +1,281 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __R5900_H__ +#define __R5900_H__ + +#include + +typedef struct { + int (*Init)(); + void (*Reset)(); + void (*Step)(); + void (*Execute)(); /* executes up to a break */ + void (*ExecuteBlock)(); /* executes up to a jump */ + void (*ExecuteVU0Block)(); /* executes up to a jump */ + void (*ExecuteVU1Block)(); /* executes up to a jump */ + void (*EnableVU0micro)(int enable); + void (*EnableVU1micro)(int enable); + void (*Clear)(u32 Addr, u32 Size); + void (*ClearVU0)(u32 Addr, u32 Size); + void (*ClearVU1)(u32 Addr, u32 Size); + void (*Shutdown)(); +} R5900cpu; + +extern R5900cpu *Cpu; +extern R5900cpu intCpu; +extern R5900cpu recCpu; +extern u32 bExecBIOS; + +typedef union { // Declare union type GPR register + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} GPR_reg; + +typedef union { + struct { + GPR_reg r0, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, s8, ra; + } n; + GPR_reg r[32]; +} GPRregs; + +typedef union { + struct { + u32 pccr, pcr0, pcr1, pad; + } n; + u32 r[4]; +} PERFregs; + +typedef union { + struct { + u32 Index, Random, EntryLo0, EntryLo1, + Context, PageMask, Wired, Reserved0, + BadVAddr, Count, EntryHi, Compare; + union { + struct { + int IE:1; + int EXL:1; + int ERL:1; + int KSU:2; + int unused0:3; + int IM:8; + int EIE:1; + int _EDI:1; + int CH:1; + int unused1:3; + int BEV:1; + int DEV:1; + int unused2:2; + int FR:1; + int unused3:1; + int CU:4; + } b; + u32 val; + } Status; + u32 Cause, EPC, PRid, + Config, LLAddr, WatchLO, WatchHI, + XContext, Reserved1, Reserved2, Debug, + DEPC, PerfCnt, ErrCtl, CacheErr, + TagLo, TagHi, ErrorEPC, DESAVE; + } n; + u32 r[32]; +} CP0regs; + +typedef struct { + GPRregs GPR; // GPR regs + // NOTE: don't change order since recompiler uses it + GPR_reg HI; + GPR_reg LO; // hi & log 128bit wide + CP0regs CP0; // is COP0 32bit? + u32 sa; // shift amount (32bit), needs to be 16 byte aligned + u32 constzero; // always 0, for MFSA + u32 pc; // Program counter, when changing offset in struct, check iR5900-X.S to make sure offset is correct + u32 code; // The instruction + PERFregs PERF; + u32 eCycle[32]; + u32 sCycle[32]; // for internal counters + u32 cycle; // calculate cpucycles.. + u32 interrupt; + int branch; + int opmode; // operating mode + u32 tempcycles; +} cpuRegisters; + +extern int EEsCycle; +extern u32 EEoCycle, IOPoCycle; +extern cpuRegisters cpuRegs; + +// used for optimization +typedef union { + u64 UD[1]; //64 bits + s64 SD[1]; + u32 UL[2]; + s32 SL[3]; + u16 US[4]; + s16 SS[4]; + u8 UC[8]; + s8 SC[8]; +} GPR_reg64; + +#define GPR_IS_CONST1(reg) ((reg)<32 && (g_cpuHasConstReg&(1<<(reg)))) +#define GPR_IS_CONST2(reg1, reg2) ((g_cpuHasConstReg&(1<<(reg1)))&&(g_cpuHasConstReg&(1<<(reg2)))) +#define GPR_SET_CONST(reg) { \ + if( (reg) < 32 ) { \ + g_cpuHasConstReg |= (1<<(reg)); \ + g_cpuFlushedConstReg &= ~(1<<(reg)); \ + } \ +} + +#define GPR_DEL_CONST(reg) { \ + if( (reg) < 32 ) g_cpuHasConstReg &= ~(1<<(reg)); \ +} + +extern GPR_reg64 g_cpuConstRegs[32]; +extern u32 g_cpuHasConstReg, g_cpuFlushedConstReg; + +typedef union { + float f; + u32 UL; +} FPRreg; + +typedef struct { + FPRreg fpr[32]; // 32bit floating point registers + u32 fprc[32]; // 32bit floating point control registers + FPRreg ACC; // 32 bit accumulator +} fpuRegisters; + +extern fpuRegisters fpuRegs; + + +typedef struct { + u32 PageMask,EntryHi; + u32 EntryLo0,EntryLo1; + u32 Mask, nMask; + u32 G; + u32 ASID; + u32 VPN2; + u32 PFN0; + u32 PFN1; +} tlbs; + +extern tlbs tlb[48]; + +#ifndef _PC_ + +#define _i64(x) (s64)x +#define _u64(x) (u64)x + +#define _i32(x) (s32)x +#define _u32(x) (u32)x + +#define _i16(x) (s16)x +#define _u16(x) (u16)x + +#define _i8(x) (s8)x +#define _u8(x) (u8)x + +/**** R3000A Instruction Macros ****/ +#define _PC_ cpuRegs.pc // The next PC to be executed + +#define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((cpuRegs.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((cpuRegs.code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((cpuRegs.code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ((u16)cpuRegs.code) // The immediate part of the instruction register +#define _Target_ (cpuRegs.code & 0x03ffffff) // The target part of the instruction register + +#define _Imm_ ((s16)cpuRegs.code) // sign-extended immediate +#define _ImmU_ (cpuRegs.code&0xffff) // zero-extended immediate + + +//#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +//#define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction + +#define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction +#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction + +#define _SetLink(x) cpuRegs.GPR.r[x].UD[0] = _PC_ + 4; // Sets the return address in the link register + +#endif + +int cpuInit(); +void cpuReset(); +void cpuShutdown(); +void cpuException(u32 code, u32 bd); +void cpuTlbMissR(u32 addr, u32 bd); +void cpuTlbMissW(u32 addr, u32 bd); +void IntcpuBranchTest(); +void cpuBranchTest(); +void cpuTestHwInts(); +void cpuTestINTCInts(); +void cpuTestDMACInts(); +void cpuTestTIMRInts(); +void _cpuTestInterrupts(); +void cpuExecuteBios(); +void cpuRestartCPU(); + +u32 VirtualToPhysicalR(u32 addr); +u32 VirtualToPhysicalW(u32 addr); + +void intDoBranch(u32 target); +void intSetBranch(); +void intExecuteVU0Block(); +void intExecuteVU1Block(); + +void JumpCheckSym(u32 addr, u32 pc); +void JumpCheckSymRet(u32 addr); + +extern u32 g_EEFreezeRegs; + +//exception code +#define EXC_CODE(x) ((x)<<2) + +#define EXC_CODE_Int EXC_CODE(0) +#define EXC_CODE_Mod EXC_CODE(1) /* TLB Modification exception */ +#define EXC_CODE_TLBL EXC_CODE(2) /* TLB Miss exception (load or instruction fetch) */ +#define EXC_CODE_TLBS EXC_CODE(3) /* TLB Miss exception (store) */ +#define EXC_CODE_AdEL EXC_CODE(4) +#define EXC_CODE_AdES EXC_CODE(5) +#define EXC_CODE_IBE EXC_CODE(6) +#define EXC_CODE_DBE EXC_CODE(7) +#define EXC_CODE_Sys EXC_CODE(8) +#define EXC_CODE_Bp EXC_CODE(9) +#define EXC_CODE_Ri EXC_CODE(10) +#define EXC_CODE_CpU EXC_CODE(11) +#define EXC_CODE_Ov EXC_CODE(12) +#define EXC_CODE_Tr EXC_CODE(13) +#define EXC_CODE_FPE EXC_CODE(15) +#define EXC_CODE_WATCH EXC_CODE(23) +#define EXC_CODE__MASK 0x0000007c +#define EXC_CODE__SHIFT 2 + +#define EXC_TLB_STORE 1 +#define EXC_TLB_LOAD 0 + + +#endif /* __R5900_H__ */ diff --git a/pcsx2/RDebug/Makefile.am b/pcsx2/RDebug/Makefile.am new file mode 100644 index 0000000..80aa6b0 --- /dev/null +++ b/pcsx2/RDebug/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I@srcdir@/../ +noinst_LIBRARIES = libRDebug.a + +libRDebug_a_SOURCES = \ +deci2.c deci2_dcmp.c deci2_drfp.h deci2_iloadp.h deci2_ttyp.c \ +deci2_dbgp.c deci2_dcmp.h deci2.h deci2_netmp.c deci2_ttyp.h \ +deci2_dbgp.h deci2_iloadp.c deci2_netmp.h \ No newline at end of file diff --git a/pcsx2/RDebug/deci2.c b/pcsx2/RDebug/deci2.c new file mode 100644 index 0000000..49add6e --- /dev/null +++ b/pcsx2/RDebug/deci2.c @@ -0,0 +1,26 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +void exchangeSD(DECI2_HEADER *h){ + u8 tmp =h->source; + h->source =h->destination; + h->destination =tmp; +} diff --git a/pcsx2/RDebug/deci2.h b/pcsx2/RDebug/deci2.h new file mode 100644 index 0000000..a26f49e --- /dev/null +++ b/pcsx2/RDebug/deci2.h @@ -0,0 +1,70 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2_H__ +#define __DECI2_H__ + +#include "Common.h" +#include "deci2_dcmp.h" +#include "deci2_iloadp.h" +#include "deci2_dbgp.h" +#include "deci2_netmp.h" +#include "deci2_ttyp.h" + +#define PROTO_DCMP 0x0001 +#define PROTO_ITTYP 0x0110 +#define PROTO_IDBGP 0x0130 +#define PROTO_ILOADP 0x0150 +#define PROTO_ETTYP 0x0220 +#define PROTO_EDBGP 0x0230 +#define PROTO_NETMP 0x0400 + + +#pragma pack(1) +typedef struct tag_DECI2_HEADER{ + u16 length, //+00 + _pad, //+02 + protocol; //+04 + char source, //+06 + destination;//+07 +} DECI2_HEADER; //=08 + +typedef struct tag_DECI2_DBGP_BRK{ + u32 address, //+00 + count; //+04 +} DECI2_DBGP_BRK; //=08 +#pragma pack() + +#define STOP 0 +#define RUN 1 + +extern DECI2_DBGP_BRK ebrk[32], ibrk[32]; +extern int ebrk_count, ibrk_count; +extern int runStatus, runCode, runCount; + +#ifdef _WIN32 +extern HANDLE runEvent; //i don't like this; +#endif + +extern int connected; + //when add linux code this might change + +int writeData(char *result); +void exchangeSD(DECI2_HEADER *h); + +#endif//__DECI2_H__ diff --git a/pcsx2/RDebug/deci2.txt b/pcsx2/RDebug/deci2.txt new file mode 100644 index 0000000..8cf7221 --- /dev/null +++ b/pcsx2/RDebug/deci2.txt @@ -0,0 +1,27 @@ +pcsx2 log->debugger tty mapping +Ŀ +Bios EE 0 IOP Bios +CPU & MMI & COP0 & FPU EE 1 IOP IOP cpu +VU0 & VUMicro EE 2 IOP HW +VIF EE 3 IOP GTE +GIF EE 4 IOP GPU +DMA EE 5 IOP DMA +HW & Unknown Memory EE 6 IOP Unknown Memory +ELF & Scratch pad EE 7 IOP PAD +IPU EE 8 IOP CDR +SIF & RPC services EE 9 IOP + +SysMessage EEKernelIOP SysMessage + +PRODG: 230,130, 120,121,122,110-119,11F,210-219,21F,410 +CW: 230,130,150,120,121, 210-219,21F,110-119,11F + +0400 PROTO_NETMP +0001 PROTO_DCMP + PROTO_MTWKS +012? PROTO_DRFP (%s) +0230 PROTO_ESDBG +0130 PROTO_ISDBG +011? PROTO_I%dTTY +021? PROTO_E%dTTY + diff --git a/pcsx2/RDebug/deci2_dbgp.c b/pcsx2/RDebug/deci2_dbgp.c new file mode 100644 index 0000000..879f573 --- /dev/null +++ b/pcsx2/RDebug/deci2_dbgp.c @@ -0,0 +1,414 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "VUmicro.h" +#include "deci2.h" + +typedef struct tag_DECI2_DBGP_HEADER{ + DECI2_HEADER h; //+00 + u16 id; //+08 + u8 type, //+0A + code, //+0B + result, //+0C + count; //+0D + u16 _pad; //+0E +} DECI2_DBGP_HEADER; //=10 + +typedef struct tag_DECI2_DBGP_CONF{ + u32 major_ver, //+00 + minor_ver, //+04 + target_id, //+08 + _pad, //+0C + mem_align, //+10 + _pad2, //+14 + reg_size, //+18 + nreg, //+1C + nbrkpt, //+20 + ncont, //+24 + nstep, //+28 + nnext, //+2C + mem_limit_align, //+30 + mem_limit_size, //+34 + run_stop_state, //+38 + hdbg_area_addr, //+3C + hdbg_area_size; //+40 +} DECI2_DBGP_CONF; //=44 + +DECI2_DBGP_CONF +cpu={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu0={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +vu1={3, 0, PROTO_EDBGP, 0, 0x41F, 1, 7, 32, 32, 1, 0xFF, 0xFF, 0x1F, 0x400, 2, 0x80020c70, 0x100}, +iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 32, 1, 0x00, 0x00, 0x07, 0x200, 1, 0x0001E670, 0x100}; +//iop={3, 0, PROTO_IDBGP, 0, 0x00F, 1, 5, 62, 0, 1, 0x00, 0x00, 0x07, 0x200, 0, 0x00006940, 0x100}; + +#pragma pack(2) +typedef struct tag_DECI2_DBGP_EREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u64 value[2]; //+04 +} DECI2_DBGP_EREG; //=14 + +typedef struct tag_DECI2_DBGP_IREG{ + u8 kind, //+00 + number; //+01 + u16 _pad; //+02 + u32 value; //+04 +} DECI2_DBGP_IREG; //=08 + +typedef struct tag_DECI2_DBGP_MEM{ + u8 space, //+00 + align; //+01 + u16 _pad; //+02 + u32 address; //+04 + u32 length; //+08 +} DECI2_DBGP_MEM; //=0C + +typedef struct tag_DECI2_DBGP_RUN{ + u32 entry, //+00 + gp, //+04 + _pad, //+08 + _pad1, //+0C + argc; //+10 + u32 argv[0]; //+14 +} DECI2_DBGP_RUN; //=14 +#pragma pack() + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy){ + DECI2_DBGP_HEADER *in=(DECI2_DBGP_HEADER*)inbuffer, + *out=(DECI2_DBGP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DBGP_HEADER); + DECI2_DBGP_EREG *eregs=(DECI2_DBGP_EREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_IREG *iregs=(DECI2_DBGP_IREG*)((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_MEM *mem =(DECI2_DBGP_MEM*) ((u8*)out+sizeof(DECI2_DBGP_HEADER)); + DECI2_DBGP_RUN *run =(DECI2_DBGP_RUN*) ((u8*)in+sizeof(DECI2_DBGP_HEADER)); + static char line[1024]; + int i, s; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + //out->h.length=sizeof(DECI2_DBGP_HEADER); + out->type++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->type){ + case 0x00://ok + sprintf(line, "%s/GETCONF", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I'){ + memcpy(data, &iop, sizeof(DECI2_DBGP_CONF)); + }else + switch(in->id){ + case 0:memcpy(data, &cpu, sizeof(DECI2_DBGP_CONF));break; + case 1:memcpy(data, &vu0, sizeof(DECI2_DBGP_CONF));break; + case 2:memcpy(data, &vu1, sizeof(DECI2_DBGP_CONF));break; + } + break; + case 0x02://ok + sprintf(line, "%s/2", in->id==0?"CPU":in->id==1?"VU0":"VU1"); + break; + case 0x04://ok + sprintf(line, "%s/GETREG count=%d kind[0]=%d number[0]=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:iregs[i].value=psxRegs.GPR.n.lo;break; + case 1:iregs[i].value=psxRegs.GPR.n.hi;break; + } + break; + case 2:iregs[i].value=psxRegs.GPR.r[iregs[i].number]; break; + case 3: + if (iregs[i].number==14) psxRegs.CP0.n.EPC=psxRegs.pc; + iregs[i].value=psxRegs.CP0.r[iregs[i].number]; + break; + case 6:iregs[i].value=psxRegs.CP2D.r[iregs[i].number]; break; + case 7:iregs[i].value=psxRegs.CP2C.r[iregs[i].number]; break; + default: + iregs[0].value++;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(eregs[i].value, &cpuRegs.GPR.r[eregs[i].number], 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(eregs[i].value, &cpuRegs.HI.UD[0], 8);break; + case 1:memcpy(eregs[i].value, &cpuRegs.LO.UD[0], 8);break; + case 2:memcpy(eregs[i].value, &cpuRegs.HI.UD[1], 8);break; + case 3:memcpy(eregs[i].value, &cpuRegs.LO.UD[1], 8);break; + case 4:memcpy(eregs[i].value, &cpuRegs.sa, 4); break; + } + case 2: + if (eregs[i].number==14) cpuRegs.CP0.n.EPC=cpuRegs.pc; + memcpy(eregs[i].value, &cpuRegs.CP0.r[eregs[i].number], 4); + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(eregs[i].value, &fpuRegs.fpr[eregs[i].number], 4);break; + case 6:memcpy(eregs[i].value, &fpuRegs.fprc[eregs[i].number], 4);break; + case 7:memcpy(eregs[i].value, &VU0.VF[eregs[i].number], 16);break; + case 8:memcpy(eregs[i].value, &VU0.VI[eregs[i].number], 4);break; + case 9:memcpy(eregs[i].value, &VU1.VF[eregs[i].number], 16);break; + case 10:memcpy(eregs[i].value, &VU1.VI[eregs[i].number], 4);break; + default: + eregs[0].value[0]++;//dummy; might be assert(0) + } + break; + case 0x06://ok + sprintf(line, "%s/PUTREG count=%d kind[0]=%d number[0]=%d value=%016I64X_%016I64X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count, eregs[0].kind, eregs[0].number, eregs[0].value[1], eregs[0].value[0]); + if (in->h.destination=='I'){ + for (i=0; icount; i++) + switch (iregs[i].kind){ + case 1:switch (iregs[i].number){ + case 0:psxRegs.GPR.n.lo=iregs[i].value;break; + case 1:psxRegs.GPR.n.hi=iregs[i].value;break; + } + break; + case 2:psxRegs.GPR.r[iregs[i].number]=iregs[i].value; break; + case 3: + psxRegs.CP0.r[iregs[i].number]=iregs[i].value; + if (iregs[i].number==14) psxRegs.pc=psxRegs.CP0.n.EPC; + break; + case 6:psxRegs.CP2D.r[iregs[i].number]=iregs[i].value; break; + case 7:psxRegs.CP2C.r[iregs[i].number]=iregs[i].value; break; + default: + ;//dummy; might be assert(0) + } + }else + for (i=0; icount; i++) + switch (eregs[i].kind){ + case 0:memcpy(&cpuRegs.GPR.r[eregs[i].number], eregs[i].value, 16);break; + case 1: + switch(eregs[i].number){ + case 0:memcpy(&cpuRegs.HI.UD[0], eregs[i].value, 8);break; + case 1:memcpy(&cpuRegs.LO.UD[0], eregs[i].value, 8);break; + case 2:memcpy(&cpuRegs.HI.UD[1], eregs[i].value, 8);break; + case 3:memcpy(&cpuRegs.LO.UD[1], eregs[i].value, 8);break; + case 4:memcpy(&cpuRegs.sa, eregs[i].value, 4); break; + } + break; + case 2: + memcpy(&cpuRegs.CP0.r[eregs[i].number], eregs[i].value, 4); + if (eregs[i].number==14) cpuRegs.pc=cpuRegs.CP0.n.EPC; + break; + case 3:break;//performance counter 32x3 + case 4:break;//hw debug reg 32x8 + case 5:memcpy(&fpuRegs.fpr[eregs[i].number], eregs[i].value, 4);break; + case 6:memcpy(&fpuRegs.fprc[eregs[i].number], eregs[i].value, 4);break; + case 7:memcpy(&VU0.VF[eregs[i].number], eregs[i].value, 16);break; + case 8:memcpy(&VU0.VI[eregs[i].number], eregs[i].value, 4);break; + case 9:memcpy(&VU1.VF[eregs[i].number], eregs[i].value, 16);break; + case 10:memcpy(&VU1.VI[eregs[i].number], eregs[i].value, 4);break; + default: + ;//dummy; might be assert(0) + } + break; + case 0x08://ok + sprintf(line, "%s/RDMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)out+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSXM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(data, PSM(mem->address), mem->length); + else + if ((((mem->address & 0x1FFFFFFF)>128*1024*1024) || ((mem->address & 0x1FFFFFFF)<32*1024*1024)) && PSM(mem->address & 0x1FFFFFFF)) + memcpy(data, PSM(mem->address & 0x1FFFFFFF), mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(data, &VU0.Mem[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Mem[mem->address & 0x3FFF], mem->length); + break; + case 2: + if (in->id==1) + memcpy(data, &VU0.Micro[mem->address & 0xFFF], mem->length); + else + memcpy(data, &VU1.Micro[mem->address & 0x3FFF], mem->length); + break; + } + out->h.length=mem->length+data-(u8*)out; + break; + case 0x0a://ok + sprintf(line, "%s/WRMEM %08X/%X", + in->id==0?"CPU":in->id==1?"VU0":"VU1", mem->address, mem->length); + data=(u8*)in+ //kids: don't try this at home! :D + ((sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM)+(1 << mem->align) - 1) & (0xFFFFFFFF << mem->align)); + if (mem->length==4 && *(int*)data==0x0000000D) + strcat(line, " BREAKPOINT"); + if ((mem->address & ((1 << mem->align)-1)) || + (mem->length & ((1 << mem->align)-1))){ + out->result=1; + strcat(line, " ALIGN ERROR"); + break; + } + if (in->h.destination=='I') + if (PSXM(mem->address & 0x1FFFFFFF)) + memcpy(PSXM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + break; + } + else + switch(mem->space){ + case 0: + if ((mem->address & 0xF0000000) == 0x70000000) + memcpy(PSM(mem->address), data, mem->length); + else + if (PSM(mem->address & 0x1FFFFFFF)) + memcpy(PSM(mem->address & 0x1FFFFFFF), data, mem->length); + else{ + out->result=0x11; + strcat(line, " ADDRESS ERROR"); + } + break; + case 1: + if (in->id==1) + memcpy(&VU0.Mem[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Mem[mem->address & 0x3FFF], data, mem->length); + break; + case 2: + if (in->id==1) + memcpy(&VU0.Micro[mem->address & 0xFFF], data, mem->length); + else + memcpy(&VU1.Micro[mem->address & 0x3FFF], data, mem->length); + break; + } + out->h.length=sizeof(DECI2_DBGP_HEADER)+sizeof(DECI2_DBGP_MEM); + break; + case 0x10://ok + sprintf(line, "%s/GETBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + data=(u8*)out+sizeof(DECI2_DBGP_HEADER); + if (in->h.destination=='I') memcpy(data, ibrk, out->count=ibrk_count); + else memcpy(data, ebrk, out->count=ebrk_count); + out->h.length=sizeof(DECI2_DBGP_HEADER)+out->count*sizeof(DECI2_DBGP_BRK); + break; + case 0x12://ok [does not break on iop brkpts] + sprintf(line, "%s/PUTBRKPT count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + out->h.length=sizeof(DECI2_DBGP_HEADER); + if (in->count>32){ + out->result=1; + strcat(line, "TOO MANY"); + break; + } + if (in->h.destination=='I') memcpy(ibrk, data, ibrk_count=in->count); + else memcpy(ebrk, data, ebrk_count=in->count); + out->count=0; + break; + case 0x14://ok, [w/o iop] + sprintf(line, "%s/BREAK count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->count); + if (in->h.destination=='I') + ; + else{ + out->result = ( InterlockedExchange(&runStatus, STOP)==STOP ? + 0x20 : 0x21 ); + out->code=0xFF; + Sleep(50); + } + break; + case 0x16://ok, [w/o iop] + sprintf(line, "%s/CONTINUE code=%s count=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", + in->code==0?"CONT":in->code==1?"STEP":"NEXT", in->count); + if (in->h.destination=='I') + ; + else{ + InterlockedExchange(&runStatus, STOP); + Sleep(100);//first get the run thread to Wait state + runCount=in->count; + runCode=in->code; +#ifdef _WIN32 + SetEvent(runEvent);//kick it +#endif + } + break; + case 0x18://ok [without argc/argv stuff] + sprintf(line, "%s/RUN code=%d count=%d entry=0x%08X gp=0x%08X argc=%d", + in->id==0?"CPU":in->id==1?"VU0":"VU1", in->code, in->count, + run->entry, run->gp, run->argc); + cpuRegs.CP0.n.EPC=cpuRegs.pc=run->entry; + cpuRegs.GPR.n.gp.UL[0]=run->gp; +// threads_array[0].argc = run->argc; + for (i=0, s=0; i<(int)run->argc; i++) s+=run->argv[i]; + memcpy(PSM(0), &run->argv[run->argc], s); +// threads_array[0].argstring = 0; + InterlockedExchange(&runStatus, STOP); + Sleep(1000);//first get the run thread to Wait state + runCount=0; + runCode=0xFF; +#ifdef _WIN32 + SetEvent(runEvent);//awake it +#endif + out->h.length=sizeof(DECI2_DBGP_HEADER); + break; + default: + sprintf(line, "type=0x%02X code=%d count=%d [unknown]", in->type, in->code, in->count); + } + sprintf(message, "[DBGP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + sprintf(eepc, "%08X", cpuRegs.pc); + sprintf(ioppc, "%08X", psxRegs.pc); + sprintf(eecy, "%d", cpuRegs.cycle); + sprintf(iopcy, "%d", psxRegs.cycle); + writeData(outbuffer); +} + +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count){ + static DECI2_DBGP_HEADER tmp; + tmp.h.length =sizeof(DECI2_DBGP_HEADER); + tmp.h._pad =0; + tmp.h.protocol =( source=='E' ? PROTO_EDBGP : PROTO_IDBGP ); + tmp.h.source =source; + tmp.h.destination='H'; + tmp.id =id; + tmp.type =0x15; + tmp.code =code; + tmp.result =result; + tmp.count =count; + tmp._pad =0; + writeData((char*)&tmp); +} diff --git a/pcsx2/RDebug/deci2_dbgp.h b/pcsx2/RDebug/deci2_dbgp.h new file mode 100644 index 0000000..ab28c21 --- /dev/null +++ b/pcsx2/RDebug/deci2_dbgp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DBGP_H__ +#define __DECI2DBGP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DBGP(char *inbuffer, char *outbuffer, char *message, char *eepc, char *ioppc, char *eecy, char *iopcy); +void sendBREAK(u8 source, u16 id, u8 code, u8 result, u8 count); + +#endif//__DECI2DBGP_H__ diff --git a/pcsx2/RDebug/deci2_dcmp.c b/pcsx2/RDebug/deci2_dcmp.c new file mode 100644 index 0000000..9348040 --- /dev/null +++ b/pcsx2/RDebug/deci2_dcmp.c @@ -0,0 +1,83 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +typedef struct tag_DECI2_DCMP_CONNECT{ + u8 result, //+00 + _pad[3];//+01 + u64 EEboot, //+04 + IOPboot;//+0C +} DECI2_DCMP_CONNECT; //=14 + +typedef struct tag_DECI2_DCMP_ECHO{ + u16 identifier, //+00 + sequence; //+02 + u8 data[32]; //+04 +} DECI2_DCMP_ECHO; //=24 + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + DECI2_DCMP_CONNECT *connect=(DECI2_DCMP_CONNECT*)data; + DECI2_DCMP_ECHO *echo =(DECI2_DCMP_ECHO*)data; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ +/* case 0: + sprintf(message, " [DCMP] type=CONNECT code=%s EEboot=0x%I64X IOP=0x%I64X", + in->code==0?"CONNECT":"DISCONNECT", connect->EEboot, connect->IOPboot); + data=(u8*)out+sizeof(DECI2_DCMP_HEADER); + connect=(DECI2_DCMP_CONNECT*)data; + connect->result=0; + break; + case 1: + sprintf(message, " [DCMP] type=ECHO id=%X seq=%X", echo->identifier, echo->sequence); + exchangeSD(&out->h); + break; +// not implemented, not needed? + default: + sprintf(message, " [DCMP] type=%d[unknown]", in->type); +*/ } + out->code++; +} + +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size){ + static char tmp[100]; + ((DECI2_DCMP_HEADER*)tmp)->h.length =sizeof(DECI2_DCMP_HEADER)+size; + ((DECI2_DCMP_HEADER*)tmp)->h._pad =0; + ((DECI2_DCMP_HEADER*)tmp)->h.protocol =protocol; + ((DECI2_DCMP_HEADER*)tmp)->h.source =source; + ((DECI2_DCMP_HEADER*)tmp)->h.destination=destination; + ((DECI2_DCMP_HEADER*)tmp)->type =type; + ((DECI2_DCMP_HEADER*)tmp)->code =code; + ((DECI2_DCMP_HEADER*)tmp)->_pad =0; + memcpy(&tmp[sizeof(DECI2_DCMP_HEADER)], data, size); + writeData(tmp); +} \ No newline at end of file diff --git a/pcsx2/RDebug/deci2_dcmp.h b/pcsx2/RDebug/deci2_dcmp.h new file mode 100644 index 0000000..18e2c80 --- /dev/null +++ b/pcsx2/RDebug/deci2_dcmp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DCMP_H__ +#define __DECI2DCMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message); +void sendDCMP(u16 protocol, u8 source, u8 destination, u8 type, u8 code, char *data, int size); + +#endif//__DECI2DCMP_H__ diff --git a/pcsx2/RDebug/deci2_drfp.c b/pcsx2/RDebug/deci2_drfp.c new file mode 100644 index 0000000..64b2670 --- /dev/null +++ b/pcsx2/RDebug/deci2_drfp.c @@ -0,0 +1,48 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_DCMP_HEADER{ + DECI2_HEADER h; //+00 + u8 type, //+08 + code; //+09 + u16 _pad; //+0A +} DECI2_DCMP_HEADER; //=0C + +extern char d2_message[100]; + +void D2_DCMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_DCMP_HEADER *in=(DECI2_DCMP_HEADER*)inbuffer, + *out=(DECI2_DCMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_DCMP_HEADER); + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_DCMP_HEADER); + switch(in->type){ + case 4://[OK] + sprintf(message, " [DCMP] code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + break; + default: + sprintf(message, " [DCMP] code=%d[unknown] result=%d", netmp->code, netmp->result); + } + result->code++; + result->result=0; //ok +} diff --git a/pcsx2/RDebug/deci2_drfp.h b/pcsx2/RDebug/deci2_drfp.h new file mode 100644 index 0000000..eb90970 --- /dev/null +++ b/pcsx2/RDebug/deci2_drfp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2DRFP_H__ +#define __DECI2DRFP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2DRFP_H__ \ No newline at end of file diff --git a/pcsx2/RDebug/deci2_iloadp.c b/pcsx2/RDebug/deci2_iloadp.c new file mode 100644 index 0000000..d761e8b --- /dev/null +++ b/pcsx2/RDebug/deci2_iloadp.c @@ -0,0 +1,106 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "PsxCommon.h" +#include "PsxBios2.h" +#include "deci2.h" + +typedef struct tag_DECI2_ILOADP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 cmd + action, //+09 + result, //+0A + stamp; //+0B + u32 moduleId; //+0C +} DECI2_ILOADP_HEADER; //=10 + +typedef struct tag_DECI2_ILOADP_INFO{ + u16 version, //+00 + flags; //+02 + u32 module_address, //+04 + text_size, //+08 + data_size, //+0C + bss_size, //+10 + _pad[3]; //+14 +} DECI2_ILOADP_INFO; + +void writeInfo(DECI2_ILOADP_INFO *info, + u16 version, u16 flags, u32 module_address, + u32 text_size, u32 data_size, u32 bss_size){ + info->version =version; + info->flags =flags; + info->module_address=module_address; + info->text_size =text_size; + info->data_size =data_size; + info->bss_size =bss_size; + info->_pad[0]=info->_pad[1]=info->_pad[2]=0; +} + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message){ + DECI2_ILOADP_HEADER *in=(DECI2_ILOADP_HEADER*)inbuffer, + *out=(DECI2_ILOADP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_ILOADP_HEADER); + irxImageInfo *iii; + static char line[1024]; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_ILOADP_HEADER); + out->code++; + out->result=0; //ok + exchangeSD((DECI2_HEADER*)out); + switch(in->code){ + case 0: + sprintf(line, "code=START action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 2: + sprintf(line, "code=REMOVE action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + case 4: + sprintf(line, "code=LIST action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for (iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0, data+=4) + *(u32*)data=iii->index; + + out->h.length=data-(u8*)out; + break; + case 6: + sprintf(line, "code=INFO action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + data=(u8*)out+sizeof(DECI2_ILOADP_HEADER); + for(iii=(irxImageInfo*)PSXM(0x800); iii; iii=iii->next?(irxImageInfo*)PSXM(iii->next):0) + if (iii->index==in->moduleId){ + writeInfo((DECI2_ILOADP_INFO*)data, + iii->version, iii->flags, iii->vaddr, iii->text_size, iii->data_size, iii->bss_size); + data+=sizeof(DECI2_ILOADP_INFO); + strcpy(data, PSXM(iii->name)); + data+=strlen(PSXM(iii->name))+4; + data=(char*)((int)data & 0xFFFFFFFC); + break; + + } + out->h.length=data-(u8*)out; + break; + case 8: + sprintf(line, "code=WATCH action=%d stamp=%d moduleId=0x%X", in->action, in->stamp, in->moduleId); + break; + default: + sprintf(line, "code=%d[unknown]", in->code); + } + sprintf(message, "[ILOADP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); + writeData(outbuffer); +} diff --git a/pcsx2/RDebug/deci2_iloadp.h b/pcsx2/RDebug/deci2_iloadp.h new file mode 100644 index 0000000..a55b046 --- /dev/null +++ b/pcsx2/RDebug/deci2_iloadp.h @@ -0,0 +1,27 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2ILOADP_H__ +#define __DECI2ILOADP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_ILOADP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2ILOADP_H__ diff --git a/pcsx2/RDebug/deci2_netmp.c b/pcsx2/RDebug/deci2_netmp.c new file mode 100644 index 0000000..472dfc5 --- /dev/null +++ b/pcsx2/RDebug/deci2_netmp.c @@ -0,0 +1,134 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_NETMP_HEADER{ + DECI2_HEADER h; //+00 + u8 code, //+08 + result; //+09 +} DECI2_NETMP_HEADER; //=0A + +typedef struct tag_DECI2_NETMP_CONNECT{ + u8 priority, //+00 + _pad; //+01 + u16 protocol; //+02 +} DECI2_NETMP_CONNECT; //=04 + +char d2_message[100]; +int d2_count=1; +DECI2_NETMP_CONNECT d2_connect[50]={0xFF, 0, 0x400}; + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message){ + DECI2_NETMP_HEADER *in=(DECI2_NETMP_HEADER*)inbuffer, + *out=(DECI2_NETMP_HEADER*)outbuffer; + u8 *data=(u8*)in+sizeof(DECI2_NETMP_HEADER); + DECI2_NETMP_CONNECT *connect=(DECI2_NETMP_CONNECT*)data; //connect + int i, n; + static char p[100], line[1024]; + u64 EEboot, IOPboot; //reset + u16 node; + + memcpy(outbuffer, inbuffer, 128*1024);//BUFFERSIZE + out->h.length=sizeof(DECI2_NETMP_HEADER); + out->code++; + out->result=0; //ok + switch(in->code){ + case 0: + n=(in->h.length-sizeof(DECI2_NETMP_HEADER)) / sizeof(DECI2_NETMP_CONNECT); + sprintf(line, "code=CONNECT"); + for (i=0; ih.length=data-(u8*)out; + writeData(outbuffer); + + node=(u16)'I'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=(u16)'E'; + sendDCMP(PROTO_DCMP, 'H', 'H', 2, 0, (char*)&node, sizeof(node)); + + node=PROTO_ILOADP; + sendDCMP(PROTO_DCMP, 'I', 'H', 2, 1, (char*)&node, sizeof(node)); + + for (i=0; i<10; i++){ + node=PROTO_ETTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+i; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + } + node=PROTO_ETTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + + node=PROTO_ITTYP+0xF; + sendDCMP(PROTO_DCMP, 'E', 'H', 2, 1, (char*)&node, sizeof(node)); + break; + case 4://[OK] + sprintf(line, "code=MESSAGE %s", data);//null terminated by the memset with 0 call + strcpy(d2_message, data); + writeData(outbuffer); + break; + case 6://[ok] + sprintf(line, "code=STATUS"); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER)+2; + /* + memcpy(data, d2_connect, 1*sizeof(DECI2_NETMP_CONNECT)); + data+=1*sizeof(DECI2_NETMP_CONNECT); + *(u32*)data=1;//quite fast;) + data+=4; + memcpy(data, d2_message, strlen(d2_message)); + data+=strlen(d2_message); + *(u32*)data=0;//null end the string on a word boundary + data+=3;data=(u8*)((int)data & 0xFFFFFFFC);*/ + + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + case 8: + sprintf(line, "code=KILL protocol=0x%04X", *(u16*)data); + writeData(outbuffer); + break; + case 10: + sprintf(line, "code=VERSION %s", data); + data=(u8*)out+sizeof(DECI2_NETMP_HEADER); + strcpy(data, "0.2.0");data+=strlen("0.2.0");//emu version;) + out->h.length=data-(u8*)out; + writeData(outbuffer); + break; + default: + sprintf(line, "code=%d[unknown] result=%d", in->code, in->result); + writeData(outbuffer); + } + sprintf(message, "[NETMP %c->%c/%04X] %s", in->h.source, in->h.destination, in->h.length, line); +} diff --git a/pcsx2/RDebug/deci2_netmp.h b/pcsx2/RDebug/deci2_netmp.h new file mode 100644 index 0000000..760224d --- /dev/null +++ b/pcsx2/RDebug/deci2_netmp.h @@ -0,0 +1,27 @@ + /* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2NETMP_H__ +#define __DECI2NETMP_H__ + +#include "Common.h" +#include "deci2.h" + +void D2_NETMP(char *inbuffer, char *outbuffer, char *message); + +#endif//__DECI2NETMP_H__ diff --git a/pcsx2/RDebug/deci2_ttyp.c b/pcsx2/RDebug/deci2_ttyp.c new file mode 100644 index 0000000..ce66e2f --- /dev/null +++ b/pcsx2/RDebug/deci2_ttyp.c @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "deci2.h" + +typedef struct tag_DECI2_TTYP_HEADER{ + DECI2_HEADER h; //+00 + u32 flushreq; //+08 + u8 data[0]; //+0C +} DECI2_TTYP_HEADER; //=0C + +void sendTTYP(u16 protocol, u8 source, char *data){ + static char tmp[2048]; + ((DECI2_TTYP_HEADER*)tmp)->h.length =sizeof(DECI2_TTYP_HEADER)+strlen(data); + ((DECI2_TTYP_HEADER*)tmp)->h._pad =0; + ((DECI2_TTYP_HEADER*)tmp)->h.protocol =protocol +(source=='E' ? PROTO_ETTYP : PROTO_ITTYP); + ((DECI2_TTYP_HEADER*)tmp)->h.source =source; + ((DECI2_TTYP_HEADER*)tmp)->h.destination='H'; + ((DECI2_TTYP_HEADER*)tmp)->flushreq =0; + if (((DECI2_TTYP_HEADER*)tmp)->h.length>2048) + SysMessage("TTYP: Buffer overflow"); + else + memcpy(&tmp[sizeof(DECI2_TTYP_HEADER)], data, strlen(data)); + //writeData(tmp); +} \ No newline at end of file diff --git a/pcsx2/RDebug/deci2_ttyp.h b/pcsx2/RDebug/deci2_ttyp.h new file mode 100644 index 0000000..8d27146 --- /dev/null +++ b/pcsx2/RDebug/deci2_ttyp.h @@ -0,0 +1,28 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DECI2TTYP_H__ +#define __DECI2TTYP_H__ + +#include "Common.h" +#include "deci2.h" + +//void D2_(char *inbuffer, char *outbuffer, char *message); +void sendTTYP(u16 protocol, u8 source, char *data); + +#endif//__DECI2TTYP_H__ diff --git a/pcsx2/RDebug/iloadp.txt b/pcsx2/RDebug/iloadp.txt new file mode 100644 index 0000000..c8b6c68 --- /dev/null +++ b/pcsx2/RDebug/iloadp.txt @@ -0,0 +1,32 @@ +ILOADP_MODULE_INFO{ + u16 flags Ŀ <Ŀ + u16 version < + u32 addr + u32 sz_text + u32 sz_data + u32 sz_bss + u32 reserved1 + u32 reserved2 + u32 reserved3 + u8* name +}; + +ILOADP_HDR{ + u8 cmd + u8 action + u8 result + u8 stamp + u32 module_id +}; + +ILOADP_START(cmd==00) +------------------------------------------ +ILOADP_HDR_START{ + ILOADP_HDR hdr //+00 + u8* modulename //+10 //asciiz +}; //=10+strlen(modulename)+1 +action 0D(IOP_LOAD_IRX) +modulename host:E:\TEMP2\GCC\share\SIO2D.IRX + +action 02(IOP_RUN) +modulename E:\TEMP2\GCC\share\SIO2D.IRX param diff --git a/pcsx2/SPR.c b/pcsx2/SPR.c new file mode 100644 index 0000000..a2101b3 --- /dev/null +++ b/pcsx2/SPR.c @@ -0,0 +1,403 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "Common.h" +#include "SPR.h" + +#include "iR5900.h" + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) + +void sprInit() { +} + +//__inline static void SPR0transfer(u32 *data, int size) { +///* while (size > 0) { +//#ifdef SPR_LOG +// SPR_LOG("SPR1transfer: %x\n", *data); +//#endif +// data++; size--; +// }*/ +// size <<= 2; +// if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO +// (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO +// hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } else { +// u32 * p = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; +// //WriteCodeSSE2(p,data,size >> 4); +// memcpy_fast((u8*)data, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size); +// } +// spr0->sadr+= size; +//} + +static void TestClearVUs(u32 madr, u32 size) +{ + if( madr >= 0x11000000 ) { + if( madr < 0x11004000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu0\n"); +#endif + Cpu->ClearVU0(madr&0xfff, size); + } + else if( madr >= 0x11008000 && madr < 0x1100c000 ) { +#ifdef _DEBUG + SysPrintf("scratch pad clearing vu1\n"); +#endif + Cpu->ClearVU1(madr&0x3fff, size); + } + } +} + +int _SPR0chain() { + u32 qwc = spr0->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr0->madr); + if (pMem == NULL) return -1; + + //SPR0transfer(pMem, qwc << 2); + qwc <<= 4; + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + spr0->madr += (spr0->qwc * 16); + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + } else { + memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], qwc); + + Cpu->Clear(spr0->madr, qwc>>2); + // clear VU mem also! + TestClearVUs(spr0->madr, qwc>>2); + + spr0->madr += qwc; + } + spr0->sadr += qwc; + + spr0->qwc = 0; + return (qwc>>4) * BIAS; // bus is 1/2 the ee speed +} + +#define SPR0chain() \ + if (spr0->qwc) { \ + cycles += _SPR0chain(); \ +/* cycles+= spr0->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR0interleave() { + int qwc = spr0->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + //SysPrintf("dmaSPR0 interleave\n"); +#ifdef SPR_LOG + SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx\n", + spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr); +#endif + while (qwc > 0) { + spr0->qwc = min(tqwc, qwc); qwc-= spr0->qwc; + pMem = (u32*)dmaGetAddr(spr0->madr); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO + (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } else { + Cpu->Clear(spr0->madr, spr0->qwc<<2); + // clear VU mem also! + TestClearVUs(spr0->madr, spr0->qwc<<2); + + memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); + } + cycles += tqwc * BIAS; + spr0->sadr+= spr0->qwc * 16; + spr0->madr+= (sqwc+spr0->qwc)*16; //qwc-= sqwc; + } + + spr0->qwc = 0; + INT(8, cycles); +} + +void _dmaSPR0() { + u32 *ptag; + int id; + int cycles = 0; + int done = 0; + + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR0 stall %d\n", (psHu32(DMAC_CTRL)>>6)&3); + } + + if ((spr0->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR0interleave(); + return; + } + + // Transfer Dn_QWC from SPR to Dn_MADR + + + + if ((spr0->chcr & 0xc) == 0 || spr0->qwc > 0) { // Normal Mode + SPR0chain(); + INT(8, cycles); + + return; + } + + // Destination Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; + spr0->sadr+= 16; + + // Transfer dma tag if tte is set +// if (spr0->chcr & 0x40) SPR0transfer(ptag, 4); + + spr0->chcr = ( spr0->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr0->madr = ptag[1]; //MADR = ADDR field + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr0->qwc, id, spr0->madr); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR + SysPrintf("SPR stall control\n"); + } + + switch (id) { + case 0: // CNTS - Transfer QWC following the tag (Stall Control) + if ((psHu32(DMAC_CTRL) & 0x30) == 0x20 ) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register + break; + + case 1: // CNT - Transfer QWC following the tag. + break; + + case 7: // End - Transfer QWC following the tag + done = 1; //End Transfer + break; + } + SPR0chain(); + if (spr0->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag + //SysPrintf("SPR0 TIE\n"); + done = 1; + spr0->qwc = 0; + break; + } + + +/* if (spr0->chcr & 0x80 && ptag[0] >> 31) { +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return; + }*/ + } + + INT(8, cycles); + +} + +int SPRFROMinterrupt() +{ + spr0->chcr&= ~0x100; + hwDmacIrq(8); + return 1; +} +extern int vifqwc; + +extern void mfifoGIFtransfer(int); +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) +void dmaSPR0() { // fromSPR + int qwc = spr0->qwc; +#ifdef SPR_LOG + SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx\n", + spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); +#endif + + _dmaSPR0(); + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) { // GIF MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + //SysPrintf("mfifoGIFtransfer %x madr %x, tadr %x\n", gif->chcr, gif->madr, gif->tadr); + if(gif->chcr & 0x100)mfifoGIFtransfer(qwc); + } else + if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + //SysPrintf("mfifoVIF1transfer %x madr %x, tadr %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr); + //vifqwc+= qwc; + mfifoVIF1transfer(qwc); + } + + FreezeMMXRegs(0); + FreezeXMMRegs(0); +} + +__inline static void SPR1transfer(u32 *data, int size) { +/* { + int i; + for (i=0; isadr+i*4) & 0x3fff, data[i] ); +#endif + } + }*/ + //Cpu->Clear(spr1->sadr, size); // why? + memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2); + + spr1->sadr+= size << 2; +} + +int _SPR1chain() { + u32 qwc = spr1->qwc; + u32 *pMem; + + if (qwc == 0) return 0; + + pMem = (u32*)dmaGetAddr(spr1->madr); + if (pMem == NULL) return -1; + + SPR1transfer(pMem, qwc << 2); + spr1->madr+= spr1->qwc << 4; + spr1->qwc = 0; + return (qwc) * BIAS; +} + +#define SPR1chain() \ + if (spr1->qwc) { \ + cycles += _SPR1chain(); \ +/* cycles+= spr1->qwc / BIAS;*/ /* guessing */ \ + } + +void _SPR1interleave() { + int qwc = spr1->qwc; + int sqwc = psHu32(DMAC_SQWC) & 0xff; + int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; + int cycles = 0; + u32 *pMem; + tqwc = tqwc ? tqwc : 256; + sqwc = sqwc ? sqwc : 256; + +#ifdef SPR_LOG + SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx\n", + spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr); +#endif + while (qwc > 0) { + spr1->qwc = min(tqwc, qwc); qwc-= spr1->qwc; + pMem = (u32*)dmaGetAddr(spr1->madr); + memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc <<4); + spr1->sadr += spr1->qwc * 16; + cycles += spr1->qwc * BIAS; + spr1->madr+= (sqwc + spr1->qwc) * 16; //qwc-= sqwc; + } + + spr1->qwc = 0; + INT(9, cycles); + +} + +void dmaSPR1() { // toSPR + u32 *ptag; + int id, done=0; + int cycles = 0; + +#ifdef SPR_LOG + SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" + " tadr = 0x%x, sadr = 0x%x\n", + spr1->chcr, spr1->madr, spr1->qwc, + spr1->tadr, spr1->sadr); +#endif + + if ((spr1->chcr & 0xc) == 0x8) { // Interleave Mode + _SPR1interleave(); + FreezeMMXRegs(0); + return; + } + + + if ((spr1->chcr & 0xc) == 0 || spr1->qwc > 0) { // Normal Mode + // Transfer Dn_QWC from Dn_MADR to SPR1 + SPR1chain(); + INT(9, cycles); + FreezeMMXRegs(0); + return; + } + + // Chain Mode + + while (done == 0) { // Loop while Dn_CHCR.STR is 1 + ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("SPR1 Tag BUSERR\n"); + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + done = 1; + break; + } + spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr1->madr = ptag[1]; //MADR = ADDR field + + // Transfer dma tag if tte is set + if (spr1->chcr & 0x40) { +#ifdef SPR_LOG + SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); +#endif + SPR1transfer(ptag, 4); //Transfer Tag + + } + + + +#ifdef SPR_LOG + SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx\n", + ptag[1], ptag[0], spr1->qwc, id, spr1->madr); +#endif + + done = hwDmacSrcChain(spr1, id); + SPR1chain(); //Transfers the data set by the switch + + if (spr1->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef SPR_LOG + SPR_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("SPR1 TIE\n"); + spr1->qwc = 0; + break; + } + } + + + INT(9, cycles); + FreezeMMXRegs(0); +} + +int SPRTOinterrupt() +{ + spr1->chcr &= ~0x100; + hwDmacIrq(9); + return 1; +} + diff --git a/pcsx2/SPR.h b/pcsx2/SPR.h new file mode 100644 index 0000000..7ae0a57 --- /dev/null +++ b/pcsx2/SPR.h @@ -0,0 +1,29 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPR_H__ +#define __SPR_H__ + +#include "Common.h" + +void sprInit(); +void dmaSPR0(); +void dmaSPR1(); +int SPRFROMinterrupt(); +int SPRTOinterrupt(); +#endif /* __SPR_H__ */ diff --git a/pcsx2/Sif.c b/pcsx2/Sif.c new file mode 100644 index 0000000..7e10c28 --- /dev/null +++ b/pcsx2/Sif.c @@ -0,0 +1,616 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "Common.h" +#include "PsxCommon.h" +#include "Sif.h" +#include "Sifcmd.h" + +#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000]) +#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) +#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) + +#define FIFO_SIF0_W 128 +#define FIFO_SIF1_W 128 + +typedef struct { + u32 fifoData[FIFO_SIF0_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; + struct sifData sifData; +} _sif0; + +typedef struct { + u32 fifoData[FIFO_SIF1_W]; + int fifoReadPos; + int fifoWritePos; + int fifoSize; + int chain; + int end; + int tagMode; + int counter; +} _sif1; + +_sif0 sif0; +_sif1 sif1; + +int sifInit() { + memset(&sif0, 0, sizeof(sif0)); + memset(&sif1, 0, sizeof(sif1)); + + return 0; +} + +void SIF0write(u32 *from, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoWritePos)) { + int wP0 = (FIFO_SIF0_W-sif0.fifoWritePos); + int wP1 = words - wP0; + memcpy_fast(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2); + memcpy_fast(&sif0.fifoData[0], &from[wP0], wP1 << 2); + sif0.fifoWritePos = wP1; + } + else + { + memcpy_fast(&sif0.fifoData[sif0.fifoWritePos], from, words << 2); + sif0.fifoWritePos += words; + } + + sif0.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 + %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoWritePos); +#endif + +/* if (sif0.fifoSize == FIFO_SIF0_W) { + Cpu->ExecuteBlock(); + }*/ +} + +void SIF0read(u32 *to, int words) +{ + if(words > (FIFO_SIF0_W-sif0.fifoReadPos)) + { + int wP0 = (FIFO_SIF0_W-sif0.fifoReadPos); + int wP1 = words - wP0; + memcpy_fast(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2); + memcpy_fast(&to[wP0], &sif0.fifoData[0], wP1 << 2); + sif0.fifoReadPos = wP1; + } + else + { + memcpy_fast(to, &sif0.fifoData[sif0.fifoReadPos], words << 2); + sif0.fifoReadPos += words; + } + + sif0.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF0 - %d = %d (pos=%d)\n", words, sif0.fifoSize, sif0.fifoReadPos); +#endif +} + +void SIF1write(u32 *from, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoWritePos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoWritePos); + int wP1 = words - wP0; + memcpy_fast(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2); + memcpy_fast(&sif1.fifoData[0], &from[wP0], wP1 << 2); + sif1.fifoWritePos = wP1; + } + else + { + memcpy_fast(&sif1.fifoData[sif1.fifoWritePos], from, words << 2); + sif1.fifoWritePos += words; + } + + sif1.fifoSize += words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 + %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoWritePos); +#endif + +/* if (sif1.fifoSize == FIFO_SIF1_W) { + psxCpu->ExecuteBlock(); + }*/ +} + +void SIF1read(u32 *to, int words) +{ + if(words > (FIFO_SIF1_W-sif1.fifoReadPos)) + { + int wP0 = (FIFO_SIF1_W-sif1.fifoReadPos); + int wP1 = words - wP0; + memcpy_fast(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2); + memcpy_fast(&to[wP0], &sif1.fifoData[0], wP1 << 2); + sif1.fifoReadPos = wP1; + } + else + { + memcpy_fast(to, &sif1.fifoData[sif1.fifoReadPos], words << 2); + sif1.fifoReadPos += words; + } + + sif1.fifoSize -= words; +#ifdef SIF_LOG + SIF_LOG(" SIF1 - %d = %d (pos=%d)\n", words, sif1.fifoSize, sif1.fifoReadPos); +#endif +} + +void SIF0Dma() +{ + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + +#ifdef SIF_LOG + SIF_LOG("SIF0 DMA start...\n"); +#endif + + do + { + notDone = 0; + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + if(HW_DMA9_CHCR & 0x01000000) // If EE SIF0 is enabled + { + int size = sif0.counter; //HW_DMA9_BCR >> 16; + + if(size == 0) // If there's no more to transfer + { + // Note.. add normal mode here + if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA + { +#ifdef SIF_LOG + SIF_LOG(" IOP SIF Stopped\n"); +#endif + + // Stop & signal interrupts on IOP + HW_DMA9_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + sif0.sifData.data = 0; + } + else if(FIFO_SIF1_W-sif0.fifoSize >= 2) // Chain mode + { + // Process DMA tag at HW_DMA9_TADR + sif0.sifData = *(struct sifData *)PSXM(HW_DMA9_TADR); + + sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4. + + SIF0write((u32*)PSXM(HW_DMA9_TADR+8), 4); + + //psxCycles += 2; + + HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF; + HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2; + //HW_DMA9_BCR = (sif0.sifData.words << 16) | 1; + sif0.counter = sif0.sifData.words & 0xFFFFFF; + notDone = 1; + +#ifdef SIF_LOG + SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)\n", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.sifData.words, sif0.sifData.data); +#endif + if(sif0.sifData.data & 0x40000000) + { +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + } + else + { +#ifdef SIF_LOG + SIF_LOG(" CNT %08X, %08X\n", sif0.sifData.data, sif0.sifData.words); +#endif + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int wTransfer = sif0.counter; // HW_DMA9_BCR >> 16; + + if (wTransfer > (FIFO_SIF0_W-sif0.fifoSize)) + wTransfer = (FIFO_SIF0_W-sif0.fifoSize); + +#ifdef SIF_LOG + SIF_LOG("+++++++++++ %lX of %lX\n", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/ ); +#endif + + SIF0write((u32*)PSXM(HW_DMA9_MADR), wTransfer); + HW_DMA9_MADR += wTransfer << 2; + //HW_DMA9_BCR = (HW_DMA9_BCR & 0xFFFF) | (((HW_DMA9_BCR >> 16) - wTransfer)<<16); + //psxCycles += (wTransfer / 4) * BIAS; + sif0.counter -= wTransfer; + + notDone = 1; + } + } + + if(sif0dma->chcr & 0x100) // If EE SIF enabled and there's something to transfer + { + int size = sif0dma->qwc; + if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) { // STS == fromSIF0 + SysPrintf("SIF0 stall control\n"); + } + if(size > 0) // If we're reading something continue to do so + { + if(sif0.fifoSize > 0) + { + int readSize = size; + + if(readSize > (sif0.fifoSize/4)) + readSize = (sif0.fifoSize/4); + + //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X\n", readSize, sif0dma->madr); +#ifdef SIF_LOG + SIF_LOG("----------- %lX of %lX\n", readSize << 2, size << 2 ); +#endif + + _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); + + SIF0read((u32*)ptag, readSize*4); + Cpu->Clear(sif0dma->madr, readSize*4); + + //cycles += readSize * BIAS; + sif0dma->qwc -= readSize; + sif0dma->madr += readSize << 4; + + notDone = 1; + } + } + else + { + if(sif0.chain && sif0dma->chcr & 0x80000000) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" EE SIF interrupt\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.end) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" EE SIF end\n"); +#endif + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + notDone = 0; + } + else if(sif0.fifoSize >= 4) // Read a tag + { + static PCSX2_ALIGNED16(u32 tag[4]); + SIF0read((u32*)&tag[0], 4); // Tag + + sif0dma->qwc = (u16)tag[0]; + sif0dma->madr = tag[1]; + sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000); + +#ifdef SIF_LOG + SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)\n", sif0dma->madr, sif0dma->qwc, (tag[0]>>28)&3, (tag[0]>>31)&1, tag[1], tag[0]); +#endif + if ((psHu32(DMAC_CTRL) & 0x30) != 0 && ((tag[0]>>28)&3) == 0)psHu32(DMAC_STADR) = sif0dma->madr + (sif0dma->qwc * 16); + notDone = 1; + sif0.chain = 1; + if(tag[0] & 0x40000000) + sif0.end = 1; + + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +void SIF1Dma() +{ + int id; + u32 *ptag; + int notDone; + //int cycles = 0, psxCycles = 0; + + do + { + notDone = 0; + + if(sif1dma->chcr & 0x100) // If EE SIF1 is enabled + { + if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0) { // STS == fromSIF1 + SysPrintf("SIF1 stall control\n"); + } + + if(sif1dma->qwc == 0) // If there's no more to transfer + { + if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA + { + // Stop & signal interrupts on EE + sif1dma->chcr &= ~0x100; + hwDmacIrq(6); + sif1.chain = 0; + sif1.end = 0; + } + else // Chain mode + { + // Process DMA tag at sif1dma->tadr + notDone = 1; + _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); + sif1dma->chcr = ( sif1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); // Copy the tag + sif1dma->qwc = (u16)ptag[0]; + + if (sif1dma->chcr & 0x40) { + SysPrintf("SIF1 TTE\n"); + SIF1write(ptag+2, 2); + } + + sif1.chain = 1; + id = (ptag[0] >> 28) & 0x7; + + switch(id) + { + case 0: // refe +#ifdef SIF_LOG + SIF_LOG(" REFE %08X\n", ptag[1]); +#endif + sif1.end = 1; + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 1: // cnt +#ifdef SIF_LOG + SIF_LOG(" CNT\n"); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + case 2: // next +#ifdef SIF_LOG + SIF_LOG(" NEXT %08X\n", ptag[1]); +#endif + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = ptag[1]; + break; + + case 3: // ref + case 4: // refs +#ifdef SIF_LOG + SIF_LOG(" REF %08X\n", ptag[1]); +#endif + sif1dma->madr = ptag[1]; + sif1dma->tadr += 16; + break; + + case 7: // end +#ifdef SIF_LOG + SIF_LOG(" END\n"); +#endif + sif1.end = 1; + sif1dma->madr = sif1dma->tadr + 16; + sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4); + break; + + default: + SysPrintf("Bad addr1 source chain\n"); + } + } + } + else // There's some data ready to transfer into the fifo.. + { + int qwTransfer = sif1dma->qwc; + u32 *data; + + notDone = 1; + + _dmaGetAddr(sif1dma, data, sif1dma->madr, 6); + + if(qwTransfer > (FIFO_SIF1_W-sif1.fifoSize)/4) // Copy part of sif1dma into FIFO + qwTransfer = (FIFO_SIF1_W-sif1.fifoSize)/4; + + SIF1write(data, qwTransfer << 2); + + sif1dma->madr += qwTransfer << 4; + //cycles += qwTransfer * BIAS; + sif1dma->qwc -= qwTransfer; + } + } + + if(HW_DMA10_CHCR & 0x01000000 ) // If IOP SIF enabled and there's something to transfer + { + int size = sif1.counter; + + if(size > 0) // If we're reading something continue to do so + { + if(sif1.fifoSize > 0) + { + int readSize = size; + + if(readSize > sif1.fifoSize) + readSize = sif1.fifoSize; + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF doing transfer %04X to %08X\n", readSize, HW_DMA10_MADR); +#endif + + SIF1read((u32*)PSXM(HW_DMA10_MADR), readSize); + psxCpu->Clear(HW_DMA10_MADR, readSize); + //psxCycles += readSize / 4; + sif1.counter = size-readSize; + HW_DMA10_MADR += readSize << 2; + notDone = 1; + } + } + + if(size <= 0 || sif1.fifoSize == 0) + { + if(sif1.tagMode & 0x80) // Stop on tag IRQ + { + // Tag interrupt +#ifdef SIF_LOG + SIF_LOG(" IOP SIF interrupt\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.tagMode & 0x40) // Stop on tag END + { + // End tag. +#ifdef SIF_LOG + SIF_LOG(" IOP SIF end\n"); +#endif + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + sif1.tagMode = 0; + notDone = 0; + } + else if(sif1.fifoSize >= 4) // Read a tag + { + struct sifData d; + + SIF1read((u32*)&d, 4); + +#ifdef SIF_LOG + SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d\n", d.data & 0xffffff, d.words, (d.data>>28)&7, (d.data>>31)&1); +#endif + HW_DMA10_MADR = d.data & 0xffffff; + sif1.counter = d.words; + sif1.tagMode = (d.data >> 24) & 0xFF; + notDone = 1; + } + } + } + }while(notDone); + + FreezeMMXRegs(0); +} + +int sif0Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(9, 0x800); + return 0; + }*/ + + psxDmaInterrupt2(2); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int sif1Interrupt() { + /*if (psxHu32(0x1070) & 8) { + PSX_INT(10, 0x800); + return 0; + }*/ + + HW_DMA10_CHCR &= ~0x01000000; //reset TR flag + psxDmaInterrupt2(3); + //hwIntcIrq(INTC_SBUS); + return 1; +} + +int EEsif0Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<5)) { + INT(5, 0x800); + return 0; + }*/ + sif0dma->chcr &= ~0x100; + hwDmacIrq(5); + + return 1; +} + +int EEsif1Interrupt() { + /*if (psHu32(DMAC_STAT) & (1<<6)) { + INT(6, 0x800); + return 0; + }*/ + hwDmacIrq(6); + + return 1; +} + +void dmaSIF0() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr); +#endif + + if (sif0.fifoReadPos != sif0.fifoWritePos) { + SysPrintf("warning, sif0.fifoReadPos != sif0.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x2000; + if(sif0dma->chcr & 0x100 && HW_DMA9_CHCR & 0x01000000) { + hwIntcIrq(INTC_SBUS); + SIF0Dma(); + psHu32(0x1000F240) &= ~0x20; + psHu32(0x1000F240) &= ~0x2000; + } +} + +void dmaSIF1() { + +#ifdef SIF_LOG + SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx\n", + sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr); +#endif + + if (sif1.fifoReadPos != sif1.fifoWritePos) { + SysPrintf("warning, sif1.fifoReadPos != sif1.fifoWritePos\n"); + } + psHu32(0x1000F240) |= 0x4000; + if(sif1dma->chcr & 0x100 && HW_DMA10_CHCR & 0x01000000) { + SIF1Dma(); + psHu32(0x1000F240) &= ~0x40; + psHu32(0x1000F240) &= ~0x100; + psHu32(0x1000F240) &= ~0x4000; + } +} + +void dmaSIF2() { + +#ifdef SIF_LOG + SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx\n", + sif2dma->chcr, sif2dma->madr, sif2dma->qwc); +#endif + + sif2dma->chcr&= ~0x100; + hwDmacIrq(7); + SysPrintf("*PCSX2*: dmaSIF2\n"); +} + + +int sifFreeze(gzFile f, int Mode) { + gzfreeze(&sif0, sizeof(sif0)); + gzfreeze(&sif1, sizeof(sif1)); + return 0; +} diff --git a/pcsx2/Sif.h b/pcsx2/Sif.h new file mode 100644 index 0000000..e381605 --- /dev/null +++ b/pcsx2/Sif.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIF_H__ +#define __SIF_H__ + +#include "Common.h" + +struct sifData{ + int data, + words, + count, + addr; +}; + +int eeSifTransfer; + +DMACh *sif0ch; +DMACh *sif1ch; +DMACh *sif2ch; + +int sifInit(); +void SIF0Dma(); +void SIF1Dma(); +void dmaSIF0(); +void dmaSIF1(); +void dmaSIF2(); +int EEsif1Interrupt(); +int EEsif0Interrupt(); +int EEsif2Interrupt(); +int sifFreeze(gzFile f, int Mode); + + +#endif /* __SIF_H__ */ diff --git a/pcsx2/Sifcmd.h b/pcsx2/Sifcmd.h new file mode 100644 index 0000000..b953fed --- /dev/null +++ b/pcsx2/Sifcmd.h @@ -0,0 +1,193 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SIFCMD_H__ +#define __SIFCMD_H__ + +/* from sifcmd.h */ + +#define SYSTEM_CMD 0x80000000 + +struct t_sif_cmd_header +{ + u32 size; + void *dest; + int command; + u32 unknown; +}; + +struct t_sif_dma_transfer +{ + void *src, + *dest; + int size; + int attr; +}; + +struct t_sif_handler +{ + void (*handler) ( void *a, void *b); + void *buff; +}; + +#define SYSTEM_CMD_CHANGE_SADDR 0x80000000 +#define SYSTEM_CMD_INIT_CMD 0x80000002 +struct t_sif_saddr{ + struct t_sif_cmd_header hdr; //+00 + void *newaddr; //+10 +}; //=14 + +#define SYSTEM_CMD_SET_SREG 0x80000001 +struct t_sif_sreg{ + struct t_sif_cmd_header hdr; //+00 + int index; //+10 + unsigned int value; //+14 +}; //=18 + +#define SYSTEM_CMD_RESET 0x80000003 +struct t_sif_reset{ + struct t_sif_cmd_header hdr; //+00 + int size, //+10 + flag; //+14 + char data[80]; //+18 +}; //=68 + +/* end of sifcmd.h */ + +/* from sifsrpc.h */ + +struct t_sif_rpc_rend +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_client_data *client; /* 7 */ + u32 command; /* 8 */ + struct t_rpc_server_data *server; /* 9 */ + void *buff, /* 10 */ + *buff2; /* 11 */ +}; + +struct t_sif_rpc_other_data +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + + struct t_rpc_receive_data *receive; /* 07 */ + void *src; /* 08 */ + void *dest; /* 09 */ + int size; /* 10 */ +}; + +struct t_sif_rpc_bind +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ +}; + +struct t_sif_rpc_call +{ + struct t_sif_cmd_header sifcmd; + int rec_id; /* 04 */ + void *pkt_addr; /* 05 */ + int rpc_id; /* 06 */ + struct t_rpc_client_data *client; /* 07 */ + int rpc_number; /* 08 */ + int send_size; /* 09 */ + void *receive; /* 10 */ + int rec_size; /* 11 */ + int has_async_ef; /* 12 */ + struct t_rpc_server_data *server; /* 13 */ +}; + +struct t_rpc_server_data +{ + int command; /* 04 00 */ + + void * (*func)(u32, void *, int); /* 05 01 */ + void *buff; /* 06 02 */ + int size; /* 07 03 */ + + void * (*func2)(u32, void *, int); /* 08 04 */ + void *buff2; /* 09 05 */ + int size2; /* 10 06 */ + + struct t_rpc_client_data *client; /* 11 07 */ + void *pkt_addr; /* 12 08 */ + int rpc_number; /* 13 09 */ + + void *receive; /* 14 10 */ + int rec_size; /* 15 11 */ + int has_async_ef; /* 16 12 */ + int rec_id; /* 17 13 */ + + struct t_rpc_server_data *link; /* 18 14 */ + struct r_rpc_server_data *next; /* 19 15 */ + struct t_rpc_data_queue *queued_object; /* 20 16 */ +}; + + +struct t_rpc_header +{ + void *pkt_addr; /* 04 00 */ + u32 rpc_id; /* 05 01 */ + int sema_id; /* 06 02 */ + u32 mode; /* 07 03 */ +}; + + +struct t_rpc_client_data +{ + struct t_rpc_header hdr; + u32 command; /* 04 08 */ + void *buff, /* 05 09 */ + *buff2; /* 06 10 */ + void (*end_function) ( void *); /* 07 11 */ + void *end_param; /* 08 12*/ + struct t_rpc_server_data *server; /* 09 13 */ +}; + +struct t_rpc_receive_data +{ + struct t_rpc_header hdr; + void *src, /* 04 */ + *dest; /* 05 */ + int size; /* 06 */ +}; + +struct t_rpc_data_queue +{ + int thread_id, /* 00 */ + active; /* 01 */ + struct t_rpc_server_data *svdata_ref, /* 02 */ + *start, /* 03 */ + *end; /* 04 */ + struct t_rpc_data_queue *next; /* 05 */ +}; + +/* end of sifrpc.h */ + +#endif//__SIFCMD_H__ diff --git a/pcsx2/Sio.c b/pcsx2/Sio.c new file mode 100644 index 0000000..9fdbe62 --- /dev/null +++ b/pcsx2/Sio.c @@ -0,0 +1,590 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "PsxCommon.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#endif + +FILE * MemoryCard1, * MemoryCard2; + +// *** FOR WORKS ON PADS AND MEMORY CARDS ***** + +const unsigned char buf1[] = {0x25, 0x46, 0x01, 0x31, 0x00, 0xA2, 0x11, 0x01, 0xE1};//{0x64, 0x23, 0x2, 0x43, 0x0, 0xa2, 0x11, 0x1, 0xb4}; +const unsigned char buf2[] = {0xC5, 0xBD, 0x66, 0x00, 0x59, 0x44, 0x01, 0x02, 0x00};//{0x6d, 0x21, 0x30, 0x0, 0x55, 0x19, 0x2, 0x2, 0x30}; +const unsigned char buf4[] = {0x02, 0x9A, 0x9E, 0x06, 0x6D, 0x3C, 0xF0, 0x7E, 0xDF};//{0xa3, 0x5d, 0x2f, 0xa2, 0xd8, 0x7c, 0x5b, 0x35, 0xb9}; +const unsigned char buff[] = {0xC2, 0x39, 0x6F, 0x27, 0xC8, 0xDF, 0x2A, 0x23, 0xAD};//{0xf3, 0x9b, 0x32, 0x87, 0x31, 0xda, 0x9d, 0x10, 0xbb}; +const unsigned char buf11[] = {0xA8, 0x42, 0x5D, 0x87, 0x65, 0x32, 0x6F, 0xE8, 0xE0};//{0x39, 0xd2, 0xb9, 0x5c, 0xcf, 0x31, 0x2d, 0x23, 0xfe}; +const unsigned char buf13[] = {0x46, 0x31, 0xFC, 0x97, 0xA8, 0x6D, 0xE2, 0x12, 0x29};//{0x20, 0x2e, 0xd7, 0x99, 0x92, 0x29, 0x4a, 0x12, 0xa3}; + +const unsigned char cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; +struct mc_command_0x26_tag mc_command_0x26= + {'+', 512, 16, 0x4000, 0x52, 'Z'};//sizeof()==11 + +// clk cycle byte +// 4us * 8bits = ((PSXCLK / 1000000) * 32) / BIAS; (linuzappz) +#define SIO_INT() PSX_INT(16, PSXCLK/250000); /*270;*/ + +void _ReadMcd(char *data, u32 adr, int size) { + ReadMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +void _SaveMcd(char *data, u32 adr, int size) { + SaveMcd(sio.CtrlReg&0x2000?2:1, data, adr, size); +} + +unsigned char xor(unsigned char *buf, unsigned int length){ + register unsigned char i, x; + + for (x=0, i=0; i>13)+1, value); +#endif + } + sio.mc_command=value; + if (sio.mc_command!=0x21 && sio.mc_command!=0x22 && sio.mc_command!=0x23 && + (sio.mc_command!=0xF0) && (sio.mc_command!=0xF1) && (sio.mc_command!=0xF2)) { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + } + return; + case 99://as is... + sio.packetsize++; + sio.parp++; + switch(sio.mc_command) + { + case 0x21: + case 0x22: + case 0x23: + if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0; + if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8; + if (sio.parp==4)sio.sector|=(value & 0xFF)<<16; + if (sio.parp==5)sio.sector|=(value & 0xFF)<<24; + if (sio.parp==6) + { +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0x%02X sio.sector 0x%04X\n", + ((sio.CtrlReg&0x2000)>>13)+1, sio.mc_command, sio.sector); +#endif + } + break; + case 0x27: + if(sio.parp==2) { + sio.terminator = value; + sio.buf[4] = value; + } + break; + case 0x28: + if(sio.parp == 2) { + sio.buf[2] = '+'; + if(value == 0) { + sio.buf[4] = 0xFF; + sio.buf[3] = sio.terminator; + }else{ + sio.buf[4] = 0x5A; + sio.buf[3] = sio.terminator; + } + } + break; + case 0x42: + if (sio.parp==2) { + sio.bufcount=5+value; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + sio.buf[sio.bufcount]=sio.terminator; + } else + if ((sio.parp>2) && (sio.parp>13)+1, value, xor(&sio.buf[3], sio.bufcount-5)); +#endif + } + } + break; + case 0x43: + if (sio.parp==2){ + sio.bufcount=value+5; + sio.buf[3]='+'; + _ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value); + if(sio.mode==2) { + int j; + for(j=0; j < value; j++) + sio.buf[4+j] = ~sio.buf[4+j]; + } + sio.k+=value; + sio.buf[sio.bufcount-1]=xor(&sio.buf[4], value); + sio.buf[sio.bufcount]=sio.terminator; + } + break; + case 0x82: + if(sio.parp==2) { + sio.buf[2]='+'; + sio.buf[3]=sio.terminator; + } + break; + case 0xF0: + if (sio.parp==2) + { + u32 flag=0; +#ifdef MEMCARDS_LOG + MEMCARDS_LOG("MC(%d) command 0xF0:0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value); +#endif + switch(value){ + case 1: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf1,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 2: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf2,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 4: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf4,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 6: + case 7: + case 11: + flag=0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + break;//IN + case 15: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buff,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 17: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf11,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + case 19: + flag = 0; + sio.bufcount=13; + memset(sio.buf, 0xFF, sio.bufcount+1); + memcpy(&sio.buf[4],buf13,9);//xor value for OUT data + sio.buf[3]='+'; + break;//OUT + default: + sio.bufcount=4; + memset(sio.buf, 0xFF, sio.bufcount+1); + sio.buf[sio.bufcount-1]='+'; + } + + if ((sio.bufcount==13) && flag){ + sio.buf[sio.bufcount-1] = 0;//xor value for OUT data + sio.buf[3]='+'; + } + sio.buf[sio.bufcount]=sio.terminator; + } + break; + } + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + return; + } + + switch (sio.mtapst) { + case 0x1: + sio.packetsize++; + sio.parp = 1; + SIO_INT(); + switch(value) { + case 0x12: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x13: sio.mtapst = 2; sio.bufcount = 5; break; + case 0x21: sio.mtapst = 2; sio.bufcount = 6; break; + } + sio.buf[sio.bufcount]='Z'; + sio.buf[sio.bufcount-1]='+'; + return; + case 0x2: + sio.packetsize++; + sio.parp++; + if (sio.bufcount<=sio.parp) sio.mcdst = 0; + SIO_INT(); + return; + } + + switch (value) { + case 0x01: // start pad + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + + switch (sio.CtrlReg&0x2002) { + case 0x0002: sio.buf[0] = PAD1startPoll(1); break; + case 0x2002: sio.buf[0] = PAD2startPoll(2); break; + } + + sio.bufcount = 2; + sio.parp = 0; + sio.padst = 1; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x21: // start mtap + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio.mtapst = 1; + sio2.packet.recvVal1 = 0x1D100; // Mtap is not connected :) + SIO_INT(); + return; + + case 0x61: // start remote control sensor + sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty + sio.StatReg |= RX_RDY; // Transfer is Ready + sio.parp = 0; + sio.packetsize = 1; // Count this one too ! :P + sio2.packet.recvVal1 = 0x1100; // Pad is present + SIO_INT(); + return; + + case 0x81: // start memcard + sio.StatReg &= ~TX_EMPTY; + sio.StatReg |= RX_RDY; + memcpy(sio.buf, cardh, 4); + sio.parp = 0; + sio.bufcount = 3; + sio.mcdst = 1; + sio.packetsize = 1; + sio.rdwr = 0; + sio2.packet.recvVal1 = 0x1100; // Memcard1 is present + SIO_INT(); + return; + } +} + +void sioWriteCtrl16(unsigned short value) { + sio.CtrlReg = value & ~RESET_ERR; + if (value & RESET_ERR) sio.StatReg &= ~IRQ; + if ((sio.CtrlReg & SIO_RESET) || (!sio.CtrlReg)) { + sio.mtapst = 0; sio.padst = 0; sio.mcdst = 0; sio.parp = 0; + sio.StatReg = TX_RDY | TX_EMPTY; + psxRegs.interrupt&= ~(1<<16); + } +} + +int sioInterrupt() { +#ifdef PAD_LOG + PAD_LOG("Sio Interrupt\n"); +#endif + sio.StatReg|= IRQ; + psxHu32(0x1070)|=0x80; + return 1; +} + +FILE *LoadMcd(int mcd) { + char str[256]; + FILE *f; + + if (mcd == 1) { + strcpy(str, Config.Mcd1); + } else { + strcpy(str, Config.Mcd2); + } + if (*str == 0) sprintf(str, "memcards/Mcd00%d.ps2", mcd); + f = fopen(str, "r+b"); + if (f == NULL) { + CreateMcd(str); + f = fopen(str, "r+b"); + } + if (f == NULL) { + SysMessage (_("Failed loading MemCard %s"), str); return NULL; + } + + return f; +} + +void SeekMcd(FILE *f, u32 adr) { + u32 size; + + fseek(f, 0, SEEK_END); size = ftell(f); + if (size == MCD_SIZE + 64) + fseek(f, adr + 64, SEEK_SET); + else if (size == MCD_SIZE + 3904) + fseek(f, adr + 3904, SEEK_SET); + else + fseek(f, adr, SEEK_SET); +} + +void ReadMcd(int mcd, char *data, u32 adr, int size) { + if(mcd == 1) + { + if (MemoryCard1 == NULL) { + memset(data, 0, size); + return; + } + SeekMcd(MemoryCard1, adr); + fread(data, 1, size, MemoryCard1); + } + else + { + if (MemoryCard2 == NULL) { + memset(data, 0, size); + return; + } + SeekMcd(MemoryCard2, adr); + fread(data, 1, size, MemoryCard2); + } +} + +void SaveMcd(int mcd, char *data, u32 adr, int size) { + if(mcd == 1) + { + SeekMcd(MemoryCard1, adr); + fwrite(data, 1, size, MemoryCard1); + } + else + { + SeekMcd(MemoryCard2, adr); + fwrite(data, 1, size, MemoryCard2); + } +} + +void CreateMcd(char *mcd) { + FILE *fp; + int i=0, j=0; + int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; + + fp = fopen(mcd, "wb"); + if (fp == NULL) return; + for(i=0; i < 16384; i++) + { + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 128; j++) fputc(0x00,fp); + for(j=0; j < 16; j++) fputc(enc[j],fp); + } + fclose(fp); +} + +int sioFreeze(gzFile f, int Mode) { + gzfreeze(&sio, sizeof(sio)); + + return 0; +} + + diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h new file mode 100644 index 0000000..5aa9d97 --- /dev/null +++ b/pcsx2/Sio.h @@ -0,0 +1,115 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _SIO_H_ +#define _SIO_H_ + +typedef struct { + u16 StatReg; + u16 ModeReg; + u16 CtrlReg; + u16 BaudReg; + + u8 buf[256]; + u32 bufcount; + u32 parp; + u32 mcdst,rdwr; + u8 adrH,adrL; + u32 padst; + u32 mtapst; + u32 packetsize; + + u8 terminator; + u8 mode; + u8 mc_command; + u32 lastsector; + u32 sector; + u32 k; +} _sio; +_sio sio; + +#define MCD_SIZE (1024 * 8 * 16) +#define MC2_SIZE (1024 * 528 * 16) + +// Status Flags +#define TX_RDY 0x0001 +#define RX_RDY 0x0002 +#define TX_EMPTY 0x0004 +#define PARITY_ERR 0x0008 +#define RX_OVERRUN 0x0010 +#define FRAMING_ERR 0x0020 +#define SYNC_DETECT 0x0040 +#define DSR 0x0080 +#define CTS 0x0100 +#define IRQ 0x0200 + +// Control Flags +#define TX_PERM 0x0001 +#define DTR 0x0002 +#define RX_PERM 0x0004 +#define BREAK 0x0008 +#define RESET_ERR 0x0010 +#define RTS 0x0020 +#define SIO_RESET 0x0040 + +int Mcd1Size, Mcd2Size; + +int sioInit(); +void sioShutdown(); +void psxSIOShutdown(); +unsigned char sioRead8(); +void sioWrite8(unsigned char value); +void sioWriteCtrl16(unsigned short value); +int sioInterrupt(); +int sioFreeze(gzFile f, int Mode); + +FILE *LoadMcd(int mcd); +void ReadMcd(int mcd, char *data, u32 adr, int size); +void SaveMcd(int mcd, char *data, u32 adr, int size); +void CreateMcd(char *mcd); + +typedef struct { + char Title[48]; + char ID[14]; + char Name[16]; + int IconCount; + short Icon[16*16*3]; + unsigned char Flags; +} McdBlock; + +#ifdef _MSC_VER +#pragma pack(1) +#endif +struct mc_command_0x26_tag{ + u8 field_151; //+02 flags + u16 sectorSize; //+03 divide to it + u16 field_2C; //+05 divide to it + u32 mc_size; //+07 + u8 xor; //+0b don't forget to recalculate it!!! + u8 Z; //+0c +#ifdef _MSC_VER +}; +#pragma pack() +#else +} __attribute__((packed)); +#endif + +void GetMcdBlockInfo(int mcd, int block, McdBlock *info); + +#endif diff --git a/pcsx2/Stats.c b/pcsx2/Stats.c new file mode 100644 index 0000000..27b7da3 --- /dev/null +++ b/pcsx2/Stats.c @@ -0,0 +1,71 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "Stats.h" + +void statsOpen() { + stats.vsyncCount = 0; + stats.vsyncTime = time(NULL); + stats.eeCycles = 0; + stats.eeSCycle = 0; + stats.iopCycles = 0; + stats.iopSCycle = 0; +} + +void statsClose() { + time_t t; + FILE *f; + + t = time(NULL) - stats.vsyncTime; +#ifdef _WIN32 + f = fopen("logs\\stats.txt", "w"); +#else + f = fopen("logs/stats.txt", "w"); +#endif + if (!f) { SysPrintf("Can't open stats.txt\n"); return; } + fprintf(f, "-- PCSX2 v%s statics--\n\n", PCSX2_VERSION); + fprintf(f, "Ran for %d seconds\n", t); + fprintf(f, "Total VSyncs: %d (%s)\n", stats.vsyncCount, Config.PsxType ? "PAL" : "NTSC"); +#ifndef __x86_64__ + fprintf(f, "VSyncs per Seconds: %g\n", (double)stats.vsyncCount / t); +#endif + fprintf(f, "Total EE Instructions Executed: %lld\n", stats.eeCycles); + fprintf(f, "Total IOP Instructions Executed: %lld\n", stats.iopCycles); + if (!CHECK_EEREC) fprintf(f, "Interpreter Mode\n"); + else fprintf(f, "Recompiler Mode: VUrec1 %s, VUrec0 %s\n", + CHECK_VU1REC ? "Enabled" : "Disabled", CHECK_VU0REC ? "Enabled" : "Disabled"); + fclose(f); +} + +void statsVSync() { + static u64 accum = 0, accumvu1 = 0; + static u32 frame = 0; + + stats.eeCycles+= cpuRegs.cycle - stats.eeSCycle; + stats.eeSCycle = cpuRegs.cycle; + stats.iopCycles+= psxRegs.cycle - stats.iopSCycle; + stats.iopSCycle = psxRegs.cycle; + stats.vsyncCount++; + stats.vif1count = 0; + stats.vu1count = 0; +} diff --git a/pcsx2/Stats.h b/pcsx2/Stats.h new file mode 100644 index 0000000..a914e6b --- /dev/null +++ b/pcsx2/Stats.h @@ -0,0 +1,43 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __STATS_H__ +#define __STATS_H__ + +#include + +typedef struct { + time_t vsyncTime; + u32 vsyncCount; + u32 eeCycles; + u32 eeSCycle; + u32 iopCycles; + u32 iopSCycle; + + u32 ticko; + u32 framecount; + u32 vu1count; + u32 vif1count; +} Stats; +Stats stats; + +void statsOpen(); +void statsClose(); +void statsVSync(); + +#endif /* __STATS_H__ */ diff --git a/pcsx2/System.h b/pcsx2/System.h new file mode 100644 index 0000000..ace4b61 --- /dev/null +++ b/pcsx2/System.h @@ -0,0 +1,64 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +int SysInit(); // Init mem and plugins +void SysReset(); // Resets mem +void SysPrintf(char *fmt, ...); // Printf used by bios syscalls +void SysMessage(char *fmt, ...); // Message used to print msg to users +void SysUpdate(); // Called on VBlank (to update i.e. pads) +void SysRunGui(); // Returns to the Gui +void SysClose(); // Close mem and plugins +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void *SysMmap(uptr base, u32 size); +void SysMunmap(uptr base, u32 size); + +#ifdef PCSX2_VIRTUAL_MEM + +typedef struct _PSMEMORYBLOCK +{ +#ifdef _WIN32 + int NumberPages; + uptr* aPFNs; + uptr* aVFNs; // virtual pages that own the physical pages +#else + int fd; // file descriptor + char* pname; // given name + int size; // size of allocated region +#endif +} PSMEMORYBLOCK; + +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock); +void SysPhysicalFree(PSMEMORYBLOCK* pblock); +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock); +void SysVirtualFree(void* lpMemReserved, u32 size); + +// returns 1 if successful, 0 otherwise +int SysMapUserPhysicalPages(void* Addr, uptr NumPages, uptr* pblock, int pageoffset); + +// call to enable physical page allocation +//BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); + +#endif + +#endif /* __SYSTEM_H__ */ diff --git a/pcsx2/VU.h b/pcsx2/VU.h new file mode 100644 index 0000000..3b8221d --- /dev/null +++ b/pcsx2/VU.h @@ -0,0 +1,181 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU_H__ +#define __VU_H__ + +#define REG_STATUS_FLAG 16 +#define REG_MAC_FLAG 17 +#define REG_CLIP_FLAG 18 +#define REG_ACC_FLAG 19 // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) +#define REG_R 20 +#define REG_I 21 +#define REG_Q 22 +#define REG_P 23 //only exists in micromode +#define REG_VF0_FLAG 24 // dummy flag that indicates VF0 is read (nothing to do with VI[24]) +#define REG_TPC 26 +#define REG_CMSAR0 27 +#define REG_FBRST 28 +#define REG_VPU_STAT 29 +#define REG_CMSAR1 31 + +enum VUStatus { + VU_Ready = 0, + VU_Run = 1, + VU_Stop = 2, +}; + +typedef union { + struct { + float x,y,z,w; + } f; + struct { + u32 x,y,z,w; + } i; + + float F[4]; + + u64 UD[2]; //128 bits + s64 SD[2]; + u32 UL[4]; + s32 SL[4]; + u16 US[8]; + s16 SS[8]; + u8 UC[16]; + s8 SC[16]; +} VECTOR; + +typedef union { + float F; + s32 SL; + u32 UL; + s16 SS[2]; + u16 US[2]; + s8 SC[4]; + u8 UC[4]; +} REG_VI; + +#define VUFLAG_BREAKONMFLAG 0x00000001 +#define VUFLAG_MFLAGSET 0x00000002 + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; + u32 statusflag; +} fdivPipe; + +typedef struct { + int enable; + REG_VI reg; + u32 sCycle; + u32 Cycle; +} efuPipe; + +typedef struct { + int enable; + int reg; + int xyzw; + u32 sCycle; + u32 Cycle; + u32 macflag; + u32 statusflag; + u32 clipflag; +} fmacPipe; + +typedef struct _VURegs { + VECTOR VF[32]; + REG_VI VI[32]; + VECTOR ACC; + REG_VI q; + REG_VI p; + + u32 macflag; + u32 statusflag; + u32 clipflag; + + u32 cycle; + u32 flags; + + void (*vuExec)(struct _VURegs*); + VIFregisters *vifRegs; + + u8 *Mem; + u8 *Micro; + + u32 code; + u32 maxmem; + u32 maxmicro; + + u16 branch; + u16 ebit; + u32 branchpc; + + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + +} VURegs; + +#define VUPIPE_NONE 0 +#define VUPIPE_FMAC 1 +#define VUPIPE_FDIV 2 +#define VUPIPE_EFU 3 +#define VUPIPE_IALU 4 +#define VUPIPE_BRANCH 5 +#define VUPIPE_XGKICK 6 + +#define VUREG_READ 0x1 +#define VUREG_WRITE 0x2 + +typedef struct { + u8 pipe; // if 0xff, COP2 + u8 VFwrite; + u8 VFwxyzw; + u8 VFr0xyzw; + u8 VFr1xyzw; + u8 VFread0; + u8 VFread1; + u32 VIwrite; + u32 VIread; + int cycles; +} _VURegsNum; + +extern VURegs* g_pVU1; +extern VURegs VU0; + +#define VU1 (*g_pVU1) + +extern __forceinline u32* GET_VU_MEM(VURegs* VU, u32 addr) +{ + if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); + + if( addr >= 0x4200 ) return &VU1.VI[(addr>>2)&0x1f].UL; + + return (u32*)(VU0.Mem+(addr&0x0fff)); +} + + +// various fixes to enable per game (all are off by default) +#define VUFIX_SIGNEDZERO 1 +#define VUFIX_EXTRAFLAGS 2 +#define VUFIX_XGKICKDELAY2 4 +extern int g_VUGameFixes; + +#endif /* __VU_H__ */ diff --git a/pcsx2/VU0.c b/pcsx2/VU0.c new file mode 100644 index 0000000..752f30e --- /dev/null +++ b/pcsx2/VU0.c @@ -0,0 +1,401 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO + -Fix the flags Proper as they aren't handle now.. + -Add BC Table opcodes + -Add Interlock in QMFC2,QMTC2,CFC2,CTC2 + -Finish instruction set + -Bug Fixes!!! +*/ + +#include +#include +#include +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUops.h" +#include "VUmicro.h" + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _X (cpuRegs.code>>24) & 0x1 +#define _Y (cpuRegs.code>>23) & 0x1 +#define _Z (cpuRegs.code>>22) & 0x1 +#define _W (cpuRegs.code>>21) & 0x1 + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) + +#include "VUflags.h" + +PCSX2_ALIGNED16(VURegs VU0); + +void COP2() { +#ifdef VU0_LOG + VU0_LOG("%s\n", disR5900Fasm(cpuRegs.code, cpuRegs.pc)); +#endif + Int_COP2PrintTable[_Rs_](); +} + +void COP2_BC2() { Int_COP2BC2PrintTable[_Rt_]();} +void COP2_SPECIAL() { Int_COP2SPECIAL1PrintTable[_Funct_]();} + +void COP2_SPECIAL2() { + Int_COP2SPECIAL2PrintTable[(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c)](); +} + +void COP2_Unknown() +{ +#ifdef CPU_LOG + CPU_LOG("Unknown COP2 opcode called\n"); +#endif +} + +void LQC2() { + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)cpuRegs.code; + if (_Ft_) { + memRead128(addr, &VU0.VF[_Ft_].UD[0]); + } else { + u64 val[2]; + memRead128(addr, val); + } +} + +// Asadr.Changed +void SQC2() { + u32 addr = _Imm_ + cpuRegs.GPR.r[_Rs_].UL[0]; + memWrite64(addr, VU0.VF[_Ft_].UD[0]); + memWrite64(addr+8,VU0.VF[_Ft_].UD[1]); +} + + +//**************************************************************************** +void _vu0WaitMicro() { + int startcycle; + if ((VU0.VI[REG_VPU_STAT].UL & 0x1) == 0) { + return; + } + + startcycle = VU0.cycle; + + VU0.flags|= VUFLAG_BREAKONMFLAG; + VU0.flags&= ~VUFLAG_MFLAGSET; + + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU0Block(); + // knockout kings 2002 loops here + if( VU0.cycle-startcycle > 0x1000 ) { + SysPrintf("VU0 wait stall (email zero if gfx are bad)\n"); + break; + } + } while ((VU0.VI[REG_VPU_STAT].UL & 0x1) && (VU0.flags & VUFLAG_MFLAGSET) == 0); + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + + //NEW + cpuRegs.cycle += (VU0.cycle-startcycle)*2; + VU0.flags&= ~VUFLAG_BREAKONMFLAG; +} + + +void QMFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UD[0] = VU0.VF[_Fs_].UD[0]; + cpuRegs.GPR.r[_Rt_].UD[1] = VU0.VF[_Fs_].UD[1]; +} + +void QMTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + VU0.VF[_Fs_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0]; + VU0.VF[_Fs_].UD[1] = cpuRegs.GPR.r[_Rt_].UD[1]; +} + +void CFC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Rt_ == 0) return; + cpuRegs.GPR.r[_Rt_].UL[0] = VU0.VI[_Fs_].UL; + if(VU0.VI[_Fs_].UL & 0x80000000) + cpuRegs.GPR.r[_Rt_].UL[1] = 0xffffffff; + else + cpuRegs.GPR.r[_Rt_].UL[1] = 0; +} + +void CTC2() { + if (cpuRegs.code & 1) { + _vu0WaitMicro(); + } + if (_Fs_ == 0) return; + + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + VU0.VI[REG_FBRST].UL = cpuRegs.GPR.r[_Rt_].UL[0] & 0x0C0C; + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x1) { // VU0 Force Break + SysPrintf("fixme: VU0 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x2) { // VU0 Reset + //SysPrintf("fixme: VU0 Reset\n"); + vu0ResetRegs(); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x100) { // VU1 Force Break + SysPrintf("fixme: VU1 Force Break\n"); + } + if (cpuRegs.GPR.r[_Rt_].UL[0] & 0x200) { // VU1 Reset +// SysPrintf("fixme: VU1 Reset\n"); + vu1ResetRegs(); + } + break; + case REG_CMSAR1: // REG_CMSAR1 + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100) ) { + VU1.VI[REG_TPC].UL = cpuRegs.GPR.r[_Rt_].US[0]; + vu1ExecMicro(VU1.VI[REG_TPC].UL); // Execute VU1 Micro SubRoutine + } + break; + default: + VU0.VI[_Fs_].UL = cpuRegs.GPR.r[_Rt_].UL[0]; + break; + } +} + +//--------------------------------------------------------------------------------------- + + +#define SYNCMSFLAGS() VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; VU0.VI[REG_MAC_FLAG].UL = VU0.macflag; +#define SYNCFDIV() VU0.VI[REG_Q].UL = VU0.q.UL; VU0.VI[REG_STATUS_FLAG].UL = VU0.statusflag; + +void VABS() { VU0.code = cpuRegs.code; _vuABS(&VU0); } +void VADD() { VU0.code = cpuRegs.code; _vuADD(&VU0); SYNCMSFLAGS(); } +void VADDi() { VU0.code = cpuRegs.code; _vuADDi(&VU0); SYNCMSFLAGS(); } +void VADDq() { VU0.code = cpuRegs.code; _vuADDq(&VU0); SYNCMSFLAGS(); } +void VADDx() { VU0.code = cpuRegs.code; _vuADDx(&VU0); SYNCMSFLAGS(); } +void VADDy() { VU0.code = cpuRegs.code; _vuADDy(&VU0); SYNCMSFLAGS(); } +void VADDz() { VU0.code = cpuRegs.code; _vuADDz(&VU0); SYNCMSFLAGS(); } +void VADDw() { VU0.code = cpuRegs.code; _vuADDw(&VU0); SYNCMSFLAGS(); } +void VADDA() { VU0.code = cpuRegs.code; _vuADDA(&VU0); SYNCMSFLAGS(); } +void VADDAi() { VU0.code = cpuRegs.code; _vuADDAi(&VU0); SYNCMSFLAGS(); } +void VADDAq() { VU0.code = cpuRegs.code; _vuADDAq(&VU0); SYNCMSFLAGS(); } +void VADDAx() { VU0.code = cpuRegs.code; _vuADDAx(&VU0); SYNCMSFLAGS(); } +void VADDAy() { VU0.code = cpuRegs.code; _vuADDAy(&VU0); SYNCMSFLAGS(); } +void VADDAz() { VU0.code = cpuRegs.code; _vuADDAz(&VU0); SYNCMSFLAGS(); } +void VADDAw() { VU0.code = cpuRegs.code; _vuADDAw(&VU0); SYNCMSFLAGS(); } +void VSUB() { VU0.code = cpuRegs.code; _vuSUB(&VU0); SYNCMSFLAGS(); } +void VSUBi() { VU0.code = cpuRegs.code; _vuSUBi(&VU0); SYNCMSFLAGS(); } +void VSUBq() { VU0.code = cpuRegs.code; _vuSUBq(&VU0); SYNCMSFLAGS(); } +void VSUBx() { VU0.code = cpuRegs.code; _vuSUBx(&VU0); SYNCMSFLAGS(); } +void VSUBy() { VU0.code = cpuRegs.code; _vuSUBy(&VU0); SYNCMSFLAGS(); } +void VSUBz() { VU0.code = cpuRegs.code; _vuSUBz(&VU0); SYNCMSFLAGS(); } +void VSUBw() { VU0.code = cpuRegs.code; _vuSUBw(&VU0); SYNCMSFLAGS(); } +void VSUBA() { VU0.code = cpuRegs.code; _vuSUBA(&VU0); SYNCMSFLAGS(); } +void VSUBAi() { VU0.code = cpuRegs.code; _vuSUBAi(&VU0); SYNCMSFLAGS(); } +void VSUBAq() { VU0.code = cpuRegs.code; _vuSUBAq(&VU0); SYNCMSFLAGS(); } +void VSUBAx() { VU0.code = cpuRegs.code; _vuSUBAx(&VU0); SYNCMSFLAGS(); } +void VSUBAy() { VU0.code = cpuRegs.code; _vuSUBAy(&VU0); SYNCMSFLAGS(); } +void VSUBAz() { VU0.code = cpuRegs.code; _vuSUBAz(&VU0); SYNCMSFLAGS(); } +void VSUBAw() { VU0.code = cpuRegs.code; _vuSUBAw(&VU0); SYNCMSFLAGS(); } +void VMUL() { VU0.code = cpuRegs.code; _vuMUL(&VU0); SYNCMSFLAGS(); } +void VMULi() { VU0.code = cpuRegs.code; _vuMULi(&VU0); SYNCMSFLAGS(); } +void VMULq() { VU0.code = cpuRegs.code; _vuMULq(&VU0); SYNCMSFLAGS(); } +void VMULx() { VU0.code = cpuRegs.code; _vuMULx(&VU0); SYNCMSFLAGS(); } +void VMULy() { VU0.code = cpuRegs.code; _vuMULy(&VU0); SYNCMSFLAGS(); } +void VMULz() { VU0.code = cpuRegs.code; _vuMULz(&VU0); SYNCMSFLAGS(); } +void VMULw() { VU0.code = cpuRegs.code; _vuMULw(&VU0); SYNCMSFLAGS(); } +void VMULA() { VU0.code = cpuRegs.code; _vuMULA(&VU0); SYNCMSFLAGS(); } +void VMULAi() { VU0.code = cpuRegs.code; _vuMULAi(&VU0); SYNCMSFLAGS(); } +void VMULAq() { VU0.code = cpuRegs.code; _vuMULAq(&VU0); SYNCMSFLAGS(); } +void VMULAx() { VU0.code = cpuRegs.code; _vuMULAx(&VU0); SYNCMSFLAGS(); } +void VMULAy() { VU0.code = cpuRegs.code; _vuMULAy(&VU0); SYNCMSFLAGS(); } +void VMULAz() { VU0.code = cpuRegs.code; _vuMULAz(&VU0); SYNCMSFLAGS(); } +void VMULAw() { VU0.code = cpuRegs.code; _vuMULAw(&VU0); SYNCMSFLAGS(); } +void VMADD() { VU0.code = cpuRegs.code; _vuMADD(&VU0); SYNCMSFLAGS(); } +void VMADDi() { VU0.code = cpuRegs.code; _vuMADDi(&VU0); SYNCMSFLAGS(); } +void VMADDq() { VU0.code = cpuRegs.code; _vuMADDq(&VU0); SYNCMSFLAGS(); } +void VMADDx() { VU0.code = cpuRegs.code; _vuMADDx(&VU0); SYNCMSFLAGS(); } +void VMADDy() { VU0.code = cpuRegs.code; _vuMADDy(&VU0); SYNCMSFLAGS(); } +void VMADDz() { VU0.code = cpuRegs.code; _vuMADDz(&VU0); SYNCMSFLAGS(); } +void VMADDw() { VU0.code = cpuRegs.code; _vuMADDw(&VU0); SYNCMSFLAGS(); } +void VMADDA() { VU0.code = cpuRegs.code; _vuMADDA(&VU0); SYNCMSFLAGS(); } +void VMADDAi() { VU0.code = cpuRegs.code; _vuMADDAi(&VU0); SYNCMSFLAGS(); } +void VMADDAq() { VU0.code = cpuRegs.code; _vuMADDAq(&VU0); SYNCMSFLAGS(); } +void VMADDAx() { VU0.code = cpuRegs.code; _vuMADDAx(&VU0); SYNCMSFLAGS(); } +void VMADDAy() { VU0.code = cpuRegs.code; _vuMADDAy(&VU0); SYNCMSFLAGS(); } +void VMADDAz() { VU0.code = cpuRegs.code; _vuMADDAz(&VU0); SYNCMSFLAGS(); } +void VMADDAw() { VU0.code = cpuRegs.code; _vuMADDAw(&VU0); SYNCMSFLAGS(); } +void VMSUB() { VU0.code = cpuRegs.code; _vuMSUB(&VU0); SYNCMSFLAGS(); } +void VMSUBi() { VU0.code = cpuRegs.code; _vuMSUBi(&VU0); SYNCMSFLAGS(); } +void VMSUBq() { VU0.code = cpuRegs.code; _vuMSUBq(&VU0); SYNCMSFLAGS(); } +void VMSUBx() { VU0.code = cpuRegs.code; _vuMSUBx(&VU0); SYNCMSFLAGS(); } +void VMSUBy() { VU0.code = cpuRegs.code; _vuMSUBy(&VU0); SYNCMSFLAGS(); } +void VMSUBz() { VU0.code = cpuRegs.code; _vuMSUBz(&VU0); SYNCMSFLAGS(); } +void VMSUBw() { VU0.code = cpuRegs.code; _vuMSUBw(&VU0); SYNCMSFLAGS(); } +void VMSUBA() { VU0.code = cpuRegs.code; _vuMSUBA(&VU0); SYNCMSFLAGS(); } +void VMSUBAi() { VU0.code = cpuRegs.code; _vuMSUBAi(&VU0); SYNCMSFLAGS(); } +void VMSUBAq() { VU0.code = cpuRegs.code; _vuMSUBAq(&VU0); SYNCMSFLAGS(); } +void VMSUBAx() { VU0.code = cpuRegs.code; _vuMSUBAx(&VU0); SYNCMSFLAGS(); } +void VMSUBAy() { VU0.code = cpuRegs.code; _vuMSUBAy(&VU0); SYNCMSFLAGS(); } +void VMSUBAz() { VU0.code = cpuRegs.code; _vuMSUBAz(&VU0); SYNCMSFLAGS(); } +void VMSUBAw() { VU0.code = cpuRegs.code; _vuMSUBAw(&VU0); SYNCMSFLAGS(); } +void VMAX() { VU0.code = cpuRegs.code; _vuMAX(&VU0); } +void VMAXi() { VU0.code = cpuRegs.code; _vuMAXi(&VU0); } +void VMAXx() { VU0.code = cpuRegs.code; _vuMAXx(&VU0); } +void VMAXy() { VU0.code = cpuRegs.code; _vuMAXy(&VU0); } +void VMAXz() { VU0.code = cpuRegs.code; _vuMAXz(&VU0); } +void VMAXw() { VU0.code = cpuRegs.code; _vuMAXw(&VU0); } +void VMINI() { VU0.code = cpuRegs.code; _vuMINI(&VU0); } +void VMINIi() { VU0.code = cpuRegs.code; _vuMINIi(&VU0); } +void VMINIx() { VU0.code = cpuRegs.code; _vuMINIx(&VU0); } +void VMINIy() { VU0.code = cpuRegs.code; _vuMINIy(&VU0); } +void VMINIz() { VU0.code = cpuRegs.code; _vuMINIz(&VU0); } +void VMINIw() { VU0.code = cpuRegs.code; _vuMINIw(&VU0); } +void VOPMULA() { VU0.code = cpuRegs.code; _vuOPMULA(&VU0); SYNCMSFLAGS(); } +void VOPMSUB() { VU0.code = cpuRegs.code; _vuOPMSUB(&VU0); SYNCMSFLAGS(); } +void VNOP() { VU0.code = cpuRegs.code; _vuNOP(&VU0); } +void VFTOI0() { VU0.code = cpuRegs.code; _vuFTOI0(&VU0); } +void VFTOI4() { VU0.code = cpuRegs.code; _vuFTOI4(&VU0); } +void VFTOI12() { VU0.code = cpuRegs.code; _vuFTOI12(&VU0); } +void VFTOI15() { VU0.code = cpuRegs.code; _vuFTOI15(&VU0); } +void VITOF0() { VU0.code = cpuRegs.code; _vuITOF0(&VU0); } +void VITOF4() { VU0.code = cpuRegs.code; _vuITOF4(&VU0); } +void VITOF12() { VU0.code = cpuRegs.code; _vuITOF12(&VU0); } +void VITOF15() { VU0.code = cpuRegs.code; _vuITOF15(&VU0); } +void VCLIPw() { VU0.code = cpuRegs.code; _vuCLIP(&VU0); VU0.VI[REG_CLIP_FLAG].UL = VU0.clipflag; } + +void VDIV() { VU0.code = cpuRegs.code; _vuDIV(&VU0); SYNCFDIV(); } +void VSQRT() { VU0.code = cpuRegs.code; _vuSQRT(&VU0); SYNCFDIV(); } +void VRSQRT() { VU0.code = cpuRegs.code; _vuRSQRT(&VU0); SYNCFDIV(); } +void VIADD() { VU0.code = cpuRegs.code; _vuIADD(&VU0); } +void VIADDI() { VU0.code = cpuRegs.code; _vuIADDI(&VU0); } +void VIADDIU() { VU0.code = cpuRegs.code; _vuIADDIU(&VU0); } +void VIAND() { VU0.code = cpuRegs.code; _vuIAND(&VU0); } +void VIOR() { VU0.code = cpuRegs.code; _vuIOR(&VU0); } +void VISUB() { VU0.code = cpuRegs.code; _vuISUB(&VU0); } +void VISUBIU() { VU0.code = cpuRegs.code; _vuISUBIU(&VU0); } +void VMOVE() { VU0.code = cpuRegs.code; _vuMOVE(&VU0); } +void VMFIR() { VU0.code = cpuRegs.code; _vuMFIR(&VU0); } +void VMTIR() { VU0.code = cpuRegs.code; _vuMTIR(&VU0); } +void VMR32() { VU0.code = cpuRegs.code; _vuMR32(&VU0); } +void VLQ() { VU0.code = cpuRegs.code; _vuLQ(&VU0); } +void VLQD() { VU0.code = cpuRegs.code; _vuLQD(&VU0); } +void VLQI() { VU0.code = cpuRegs.code; _vuLQI(&VU0); } +void VSQ() { VU0.code = cpuRegs.code; _vuSQ(&VU0); } +void VSQD() { VU0.code = cpuRegs.code; _vuSQD(&VU0); } +void VSQI() { VU0.code = cpuRegs.code; _vuSQI(&VU0); } +void VILW() { VU0.code = cpuRegs.code; _vuILW(&VU0); } +void VISW() { VU0.code = cpuRegs.code; _vuISW(&VU0); } +void VILWR() { VU0.code = cpuRegs.code; _vuILWR(&VU0); } +void VISWR() { VU0.code = cpuRegs.code; _vuISWR(&VU0); } +void VRINIT() { VU0.code = cpuRegs.code; _vuRINIT(&VU0); } +void VRGET() { VU0.code = cpuRegs.code; _vuRGET(&VU0); } +void VRNEXT() { VU0.code = cpuRegs.code; _vuRNEXT(&VU0); } +void VRXOR() { VU0.code = cpuRegs.code; _vuRXOR(&VU0); } +void VWAITQ() { VU0.code = cpuRegs.code; _vuWAITQ(&VU0); } +void VFSAND() { VU0.code = cpuRegs.code; _vuFSAND(&VU0); } +void VFSEQ() { VU0.code = cpuRegs.code; _vuFSEQ(&VU0); } +void VFSOR() { VU0.code = cpuRegs.code; _vuFSOR(&VU0); } +void VFSSET() { VU0.code = cpuRegs.code; _vuFSSET(&VU0); } +void VFMAND() { VU0.code = cpuRegs.code; _vuFMAND(&VU0); } +void VFMEQ() { VU0.code = cpuRegs.code; _vuFMEQ(&VU0); } +void VFMOR() { VU0.code = cpuRegs.code; _vuFMOR(&VU0); } +void VFCAND() { VU0.code = cpuRegs.code; _vuFCAND(&VU0); } +void VFCEQ() { VU0.code = cpuRegs.code; _vuFCEQ(&VU0); } +void VFCOR() { VU0.code = cpuRegs.code; _vuFCOR(&VU0); } +void VFCSET() { VU0.code = cpuRegs.code; _vuFCSET(&VU0); } +void VFCGET() { VU0.code = cpuRegs.code; _vuFCGET(&VU0); } +void VXITOP() { VU0.code = cpuRegs.code; _vuXITOP(&VU0); } + +#define CP2COND (/*(VU0.VI[REG_VPU_STAT].US[0] & 1) | */((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1)) + +#define BC2(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } + +void BC2F() { BC2(== 0);} +void BC2T() { BC2(== 1);} + +#define BC2L(cond) \ + if (CP2COND cond) { \ + intDoBranch(_BranchTarget_); \ + } else cpuRegs.pc+= 4; + +void BC2FL() { BC2L(== 0);} +void BC2TL() { BC2L(== 1);} + +void vu0Finish() +{ + if( (VU0.VI[REG_VPU_STAT].UL & 0x1) ) { + int i = 0; + while(i++ < 32) { + Cpu->ExecuteVU0Block(); + if(!(VU0.VI[REG_VPU_STAT].UL & 0x1)) + break; + } + + if(VU0.VI[REG_VPU_STAT].UL & 0x1) { + VU0.VI[REG_VPU_STAT].UL &= ~1; +#ifdef PCSX2_DEVBUILD + SysPrintf("VU0 stall\n"); +#endif + } + } +} + +void VCALLMS() { + + vu0Finish(); + vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void VCALLMSR() { + vu0Finish(); + vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +#ifndef _MSC_VER + +u32* GET_VU_MEM(VURegs* VU, u32 addr) +{ + if( VU == g_pVU1 ) return (u32*)(VU1.Mem+(addr&0x3fff)); + + if( addr >= 0x4200 ) return &VU1.VI[(addr>>2)&0x1f].UL; + + return (u32*)(VU0.Mem+(addr&0x0fff)); +} + +#endif diff --git a/pcsx2/VU0.h b/pcsx2/VU0.h new file mode 100644 index 0000000..5a8bc6d --- /dev/null +++ b/pcsx2/VU0.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU0_H__ +#define __VU0_H__ + +#include "VU.h" +#define Lcode cpuRegs.code + +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); + +void recResetVU0( void ); + +void vu0Finish(); + +extern VURegs VU0; + +extern char *recMemVU0; /* VU0 blocks */ +extern char *recVU0; /* VU1 mem */ +extern char *recVU0mac; +extern char *recVU0status; +extern char *recVU0clip; +extern char *recVU0Q; +extern char *recVU0cycles; +extern char* recVU0XMMRegs; +extern char *recPtrVU0; + +extern u32 vu0recpcold; + +#endif /* __VU0_H__ */ diff --git a/pcsx2/VU0micro.c b/pcsx2/VU0micro.c new file mode 100644 index 0000000..09f6447 --- /dev/null +++ b/pcsx2/VU0micro.c @@ -0,0 +1,738 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef _WIN32 +#pragma warning(disable:4113) +#endif + +#ifdef PCSX2_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +extern PSMEMORYMAP *memLUT; +#endif + +#define VF_VAL(x) ((x==0x80000000)?0:(x)) + +void iDumpVU0Registers() +{ + int i; + + for(i = 1; i < 32; ++i) { + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), + VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F); + else if( i == REG_MAC_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0xff); + else if( i == REG_STATUS_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0x03); + else if( i == REG_CLIP_FLAG ) __Log("0\n"); + else __Log("%x\n", VU0.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); +} + +int vu0Init() +{ +#ifdef PCSX2_VIRTUAL_MEM + // unmap all vu0 pages + SysMapUserPhysicalPages(PS2MEM_VU0MICRO, 16, NULL, 0); + + // mirror 4 times + VU0.Micro = PS2MEM_VU0MICRO; + memLUT[0x11000].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11000].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11001].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11001].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11002].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11002].aVFNs = &s_psVuMem.aVFNs[0]; + memLUT[0x11003].aPFNs = &s_psVuMem.aPFNs[0]; memLUT[0x11003].aVFNs = &s_psVuMem.aVFNs[0]; + + // since vuregisters are mapped in vumem0, go to diff addr, but mapping to same physical addr + VU0.Mem = VirtualAlloc((void*)0x11000000, 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE); + + if( VU0.Mem != (void*)0x11000000 ) { + SysPrintf("Failed to alloc vu0mem 0x11000000 %d\n", GetLastError()); + return -1; + } + + memLUT[0x11004].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11004].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11005].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11005].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11006].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11006].aVFNs = &s_psVuMem.aVFNs[1]; + memLUT[0x11007].aPFNs = &s_psVuMem.aPFNs[1]; memLUT[0x11007].aVFNs = &s_psVuMem.aVFNs[1]; + + // map only registers + SysMapUserPhysicalPages(VU0.Mem+0x4000, 1, s_psVuMem.aPFNs, 2); +#else + VU0.Mem = (u8*)_aligned_malloc(0x4000+sizeof(VURegs), 16); // for VU1 + VU0.Micro = (u8*)_aligned_malloc(4*1024, 16); + memset(VU0.Mem, 0, 0x4000+sizeof(VURegs)); + memset(VU0.Micro, 0, 4*1024); +#endif + + +// VU0.VF = (VECTOR*)_aligned_malloc(32*sizeof(VECTOR), 16); +// VU0.VI = (REG_VI*)_aligned_malloc(32*sizeof(REG_VI), 16); +// if (VU0.VF == NULL || VU0.VI == NULL) { +// SysMessage(_("Error allocating memory")); return -1; +// } + + /* this is kinda tricky, maxmem is set to 0x4400 here, + tho it's not 100% accurate, since the mem goes from + 0x0000 - 0x1000 (Mem) and 0x4000 - 0x4400 (VU1 Regs), + i guess it shouldn't be a problem, + at least hope so :) (linuz) + */ + VU0.maxmem = 0x4400-4; + VU0.maxmicro = 4*1024-4; + VU0.vuExec = vu0Exec; + VU0.vifRegs = vif0Regs; + +#ifndef PCSX2_NORECBUILD + if( CHECK_VU0REC ) { + SuperVUInit(0); + } +#endif + + vu0Reset(); + + return 0; +} + +void vu0Shutdown() +{ +#ifndef PCSX2_NORECBUILD + if( CHECK_VU0REC ) { + SuperVUDestroy(0); + } +#endif + +#ifdef PCSX2_VIRTUAL_MEM + if( !SysMapUserPhysicalPages(VU0.Mem, 16, NULL, 0) ) + SysPrintf("err releasing vu0 mem %d\n", GetLastError()); + if( VirtualFree(VU0.Mem, 0, MEM_RELEASE) == 0 ) + SysPrintf("err freeing vu0 %d\n", GetLastError()); +#else + _aligned_free(VU0.Mem); + _aligned_free(VU0.Micro); +#endif + + VU0.Mem = NULL; + VU0.Micro = NULL; +// _aligned_free(VU0.VF); VU0.VF = NULL; +// _aligned_free(VU0.VI); VU0.VI = NULL; +} + +void vu0ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff; // stop vu0 + VU0.VI[REG_FBRST].UL &= ~0xff; // stop vu0 + vif0Regs->stat &= ~4; +} + +void vu0Reset() +{ + memset(&VU0.ACC, 0, sizeof(VECTOR)); + memset(VU0.VF, 0, sizeof(VECTOR)*32); + memset(VU0.VI, 0, sizeof(REG_VI)*32); + VU0.VF[0].f.x = 0.0f; + VU0.VF[0].f.y = 0.0f; + VU0.VF[0].f.z = 0.0f; + VU0.VF[0].f.w = 1.0f; + VU0.VI[0].UL = 0; + memset(VU0.Mem, 0, 4*1024); + memset(VU0.Micro, 0, 4*1024); + + recResetVU0(); +} + +void recResetVU0( void ) +{ +#ifndef PCSX2_NORECBUILD + if( CHECK_VU0REC ) { + SuperVUReset(0); + } +#endif +} + +void vu0Freeze(gzFile f, int Mode) { + gzfreeze(&VU0.ACC, sizeof(VECTOR)); + gzfreeze(&VU0.code, sizeof(u32)); + gzfreeze(VU0.Mem, 4*1024); + gzfreeze(VU0.Micro, 4*1024); + gzfreeze(VU0.VF, 32*sizeof(VECTOR)); + gzfreeze(VU0.VI, 32*sizeof(REG_VI)); +} + + +void VU0MI_XGKICK() { +} + +void VU0MI_XTOP() { +} + +void vu0ExecMicro(u32 addr) { +#ifdef VUM_LOG + VUM_LOG("vu0ExecMicro %x\n", addr); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x1; + VU0.VI[REG_VPU_STAT].UL&= ~0xAE; + if (addr != -1) VU0.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU0); + Cpu->ExecuteVU0Block(); +} + +void _vu0ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU0); + VU0_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu0ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU0); + VU0_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); +int vu0branch = 0; +void _vu0Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU0.VI[REG_TPC].UL >= VU0.maxmicro){ + #ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + VU->cycle++; + return; + } + + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { + VU->ebit = 2; + } + if (ptr[1] & 0x20000000) { /* M flag */ + VU->flags|= VUFLAG_MFLAGSET; +// SysPrintf("fixme: M flag set\n"); + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x4) { + VU0.VI[REG_VPU_STAT].UL|= 0x2; + hwIntcIrq(INTC_VU0); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x8) { + VU0.VI[REG_VPU_STAT].UL|= 0x4; + hwIntcIrq(INTC_VU0); + } + } + + VU->code = ptr[1]; + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu0ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + memset(&lregs, 0, sizeof(lregs)); + } else { + VU->code = ptr[0]; + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vu0branch = lregs.pipe == VUPIPE_BRANCH; + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU0.VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu0ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu0ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + + if (!(ptr[1] & 0x80000000)) + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + VU->branch--; + if (VU->branch == 0) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x1; /* E flag */ + vif0Regs->stat&= ~0x4; + } + } +} + +void vu0Exec(VURegs* VU) { +// u32 *ptr; + + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU0 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x1; + } else { + _vu0Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU0, VU0); +_vuRegsTables(VU0, VU0regs); + +void VU0unknown() { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU0regsunknown(_VURegsNum *VUregsn) { + assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0MI_ABS() { _vuABS(&VU0); } +void VU0MI_ADD() { _vuADD(&VU0); } +void VU0MI_ADDi() { _vuADDi(&VU0); } +void VU0MI_ADDq() { _vuADDq(&VU0); } +void VU0MI_ADDx() { _vuADDx(&VU0); } +void VU0MI_ADDy() { _vuADDy(&VU0); } +void VU0MI_ADDz() { _vuADDz(&VU0); } +void VU0MI_ADDw() { _vuADDw(&VU0); } +void VU0MI_ADDA() { _vuADDA(&VU0); } +void VU0MI_ADDAi() { _vuADDAi(&VU0); } +void VU0MI_ADDAq() { _vuADDAq(&VU0); } +void VU0MI_ADDAx() { _vuADDAx(&VU0); } +void VU0MI_ADDAy() { _vuADDAy(&VU0); } +void VU0MI_ADDAz() { _vuADDAz(&VU0); } +void VU0MI_ADDAw() { _vuADDAw(&VU0); } +void VU0MI_SUB() { _vuSUB(&VU0); } +void VU0MI_SUBi() { _vuSUBi(&VU0); } +void VU0MI_SUBq() { _vuSUBq(&VU0); } +void VU0MI_SUBx() { _vuSUBx(&VU0); } +void VU0MI_SUBy() { _vuSUBy(&VU0); } +void VU0MI_SUBz() { _vuSUBz(&VU0); } +void VU0MI_SUBw() { _vuSUBw(&VU0); } +void VU0MI_SUBA() { _vuSUBA(&VU0); } +void VU0MI_SUBAi() { _vuSUBAi(&VU0); } +void VU0MI_SUBAq() { _vuSUBAq(&VU0); } +void VU0MI_SUBAx() { _vuSUBAx(&VU0); } +void VU0MI_SUBAy() { _vuSUBAy(&VU0); } +void VU0MI_SUBAz() { _vuSUBAz(&VU0); } +void VU0MI_SUBAw() { _vuSUBAw(&VU0); } +void VU0MI_MUL() { _vuMUL(&VU0); } +void VU0MI_MULi() { _vuMULi(&VU0); } +void VU0MI_MULq() { _vuMULq(&VU0); } +void VU0MI_MULx() { _vuMULx(&VU0); } +void VU0MI_MULy() { _vuMULy(&VU0); } +void VU0MI_MULz() { _vuMULz(&VU0); } +void VU0MI_MULw() { _vuMULw(&VU0); } +void VU0MI_MULA() { _vuMULA(&VU0); } +void VU0MI_MULAi() { _vuMULAi(&VU0); } +void VU0MI_MULAq() { _vuMULAq(&VU0); } +void VU0MI_MULAx() { _vuMULAx(&VU0); } +void VU0MI_MULAy() { _vuMULAy(&VU0); } +void VU0MI_MULAz() { _vuMULAz(&VU0); } +void VU0MI_MULAw() { _vuMULAw(&VU0); } +void VU0MI_MADD() { _vuMADD(&VU0); } +void VU0MI_MADDi() { _vuMADDi(&VU0); } +void VU0MI_MADDq() { _vuMADDq(&VU0); } +void VU0MI_MADDx() { _vuMADDx(&VU0); } +void VU0MI_MADDy() { _vuMADDy(&VU0); } +void VU0MI_MADDz() { _vuMADDz(&VU0); } +void VU0MI_MADDw() { _vuMADDw(&VU0); } +void VU0MI_MADDA() { _vuMADDA(&VU0); } +void VU0MI_MADDAi() { _vuMADDAi(&VU0); } +void VU0MI_MADDAq() { _vuMADDAq(&VU0); } +void VU0MI_MADDAx() { _vuMADDAx(&VU0); } +void VU0MI_MADDAy() { _vuMADDAy(&VU0); } +void VU0MI_MADDAz() { _vuMADDAz(&VU0); } +void VU0MI_MADDAw() { _vuMADDAw(&VU0); } +void VU0MI_MSUB() { _vuMSUB(&VU0); } +void VU0MI_MSUBi() { _vuMSUBi(&VU0); } +void VU0MI_MSUBq() { _vuMSUBq(&VU0); } +void VU0MI_MSUBx() { _vuMSUBx(&VU0); } +void VU0MI_MSUBy() { _vuMSUBy(&VU0); } +void VU0MI_MSUBz() { _vuMSUBz(&VU0); } +void VU0MI_MSUBw() { _vuMSUBw(&VU0); } +void VU0MI_MSUBA() { _vuMSUBA(&VU0); } +void VU0MI_MSUBAi() { _vuMSUBAi(&VU0); } +void VU0MI_MSUBAq() { _vuMSUBAq(&VU0); } +void VU0MI_MSUBAx() { _vuMSUBAx(&VU0); } +void VU0MI_MSUBAy() { _vuMSUBAy(&VU0); } +void VU0MI_MSUBAz() { _vuMSUBAz(&VU0); } +void VU0MI_MSUBAw() { _vuMSUBAw(&VU0); } +void VU0MI_MAX() { _vuMAX(&VU0); } +void VU0MI_MAXi() { _vuMAXi(&VU0); } +void VU0MI_MAXx() { _vuMAXx(&VU0); } +void VU0MI_MAXy() { _vuMAXy(&VU0); } +void VU0MI_MAXz() { _vuMAXz(&VU0); } +void VU0MI_MAXw() { _vuMAXw(&VU0); } +void VU0MI_MINI() { _vuMINI(&VU0); } +void VU0MI_MINIi() { _vuMINIi(&VU0); } +void VU0MI_MINIx() { _vuMINIx(&VU0); } +void VU0MI_MINIy() { _vuMINIy(&VU0); } +void VU0MI_MINIz() { _vuMINIz(&VU0); } +void VU0MI_MINIw() { _vuMINIw(&VU0); } +void VU0MI_OPMULA() { _vuOPMULA(&VU0); } +void VU0MI_OPMSUB() { _vuOPMSUB(&VU0); } +void VU0MI_NOP() { _vuNOP(&VU0); } +void VU0MI_FTOI0() { _vuFTOI0(&VU0); } +void VU0MI_FTOI4() { _vuFTOI4(&VU0); } +void VU0MI_FTOI12() { _vuFTOI12(&VU0); } +void VU0MI_FTOI15() { _vuFTOI15(&VU0); } +void VU0MI_ITOF0() { _vuITOF0(&VU0); } +void VU0MI_ITOF4() { _vuITOF4(&VU0); } +void VU0MI_ITOF12() { _vuITOF12(&VU0); } +void VU0MI_ITOF15() { _vuITOF15(&VU0); } +void VU0MI_CLIP() { _vuCLIP(&VU0); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0MI_DIV() { _vuDIV(&VU0); } +void VU0MI_SQRT() { _vuSQRT(&VU0); } +void VU0MI_RSQRT() { _vuRSQRT(&VU0); } +void VU0MI_IADD() { _vuIADD(&VU0); } +void VU0MI_IADDI() { _vuIADDI(&VU0); } +void VU0MI_IADDIU() { _vuIADDIU(&VU0); } +void VU0MI_IAND() { _vuIAND(&VU0); } +void VU0MI_IOR() { _vuIOR(&VU0); } +void VU0MI_ISUB() { _vuISUB(&VU0); } +void VU0MI_ISUBIU() { _vuISUBIU(&VU0); } +void VU0MI_MOVE() { _vuMOVE(&VU0); } +void VU0MI_MFIR() { _vuMFIR(&VU0); } +void VU0MI_MTIR() { _vuMTIR(&VU0); } +void VU0MI_MR32() { _vuMR32(&VU0); } +void VU0MI_LQ() { _vuLQ(&VU0); } +void VU0MI_LQD() { _vuLQD(&VU0); } +void VU0MI_LQI() { _vuLQI(&VU0); } +void VU0MI_SQ() { _vuSQ(&VU0); } +void VU0MI_SQD() { _vuSQD(&VU0); } +void VU0MI_SQI() { _vuSQI(&VU0); } +void VU0MI_ILW() { _vuILW(&VU0); } +void VU0MI_ISW() { _vuISW(&VU0); } +void VU0MI_ILWR() { _vuILWR(&VU0); } +void VU0MI_ISWR() { _vuISWR(&VU0); } +void VU0MI_RINIT() { _vuRINIT(&VU0); } +void VU0MI_RGET() { _vuRGET(&VU0); } +void VU0MI_RNEXT() { _vuRNEXT(&VU0); } +void VU0MI_RXOR() { _vuRXOR(&VU0); } +void VU0MI_WAITQ() { _vuWAITQ(&VU0); } +void VU0MI_FSAND() { _vuFSAND(&VU0); } +void VU0MI_FSEQ() { _vuFSEQ(&VU0); } +void VU0MI_FSOR() { _vuFSOR(&VU0); } +void VU0MI_FSSET() { _vuFSSET(&VU0); } +void VU0MI_FMAND() { _vuFMAND(&VU0); } +void VU0MI_FMEQ() { _vuFMEQ(&VU0); } +void VU0MI_FMOR() { _vuFMOR(&VU0); } +void VU0MI_FCAND() { _vuFCAND(&VU0); } +void VU0MI_FCEQ() { _vuFCEQ(&VU0); } +void VU0MI_FCOR() { _vuFCOR(&VU0); } +void VU0MI_FCSET() { _vuFCSET(&VU0); } +void VU0MI_FCGET() { _vuFCGET(&VU0); } +void VU0MI_IBEQ() { _vuIBEQ(&VU0); } +void VU0MI_IBGEZ() { _vuIBGEZ(&VU0); } +void VU0MI_IBGTZ() { _vuIBGTZ(&VU0); } +void VU0MI_IBLTZ() { _vuIBLTZ(&VU0); } +void VU0MI_IBLEZ() { _vuIBLEZ(&VU0); } +void VU0MI_IBNE() { _vuIBNE(&VU0); } +void VU0MI_B() { _vuB(&VU0); } +void VU0MI_BAL() { _vuBAL(&VU0); } +void VU0MI_JR() { _vuJR(&VU0); } +void VU0MI_JALR() { _vuJALR(&VU0); } +void VU0MI_MFP() { _vuMFP(&VU0); } +void VU0MI_WAITP() { _vuWAITP(&VU0); } +void VU0MI_ESADD() { _vuESADD(&VU0); } +void VU0MI_ERSADD() { _vuERSADD(&VU0); } +void VU0MI_ELENG() { _vuELENG(&VU0); } +void VU0MI_ERLENG() { _vuERLENG(&VU0); } +void VU0MI_EATANxy() { _vuEATANxy(&VU0); } +void VU0MI_EATANxz() { _vuEATANxz(&VU0); } +void VU0MI_ESUM() { _vuESUM(&VU0); } +void VU0MI_ERCPR() { _vuERCPR(&VU0); } +void VU0MI_ESQRT() { _vuESQRT(&VU0); } +void VU0MI_ERSQRT() { _vuERSQRT(&VU0); } +void VU0MI_ESIN() { _vuESIN(&VU0); } +void VU0MI_EATAN() { _vuEATAN(&VU0); } +void VU0MI_EEXP() { _vuEEXP(&VU0); } +void VU0MI_XITOP() { _vuXITOP(&VU0); } + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU0, VUregsn); } +void VU0regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU0, VUregsn); } +void VU0regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU0, VUregsn); } +void VU0regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU0, VUregsn); } +void VU0regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU0, VUregsn); } +void VU0regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU0, VUregsn); } +void VU0regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU0, VUregsn); } +void VU0regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU0, VUregsn); } +void VU0regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU0, VUregsn); } +void VU0regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU0, VUregsn); } +void VU0regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU0, VUregsn); } +void VU0regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU0, VUregsn); } +void VU0regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU0, VUregsn); } +void VU0regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU0, VUregsn); } +void VU0regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU0, VUregsn); } +void VU0regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU0, VUregsn); } +void VU0regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU0, VUregsn); } +void VU0regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU0, VUregsn); } +void VU0regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU0, VUregsn); } +void VU0regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU0, VUregsn); } +void VU0regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU0, VUregsn); } +void VU0regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU0, VUregsn); } +void VU0regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU0, VUregsn); } +void VU0regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU0, VUregsn); } +void VU0regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU0, VUregsn); } +void VU0regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU0, VUregsn); } +void VU0regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU0, VUregsn); } +void VU0regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU0, VUregsn); } +void VU0regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU0, VUregsn); } +void VU0regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU0, VUregsn); } +void VU0regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU0, VUregsn); } +void VU0regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU0, VUregsn); } +void VU0regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU0, VUregsn); } +void VU0regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU0, VUregsn); } +void VU0regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU0, VUregsn); } +void VU0regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU0, VUregsn); } +void VU0regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU0, VUregsn); } +void VU0regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU0, VUregsn); } +void VU0regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU0, VUregsn); } +void VU0regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU0, VUregsn); } +void VU0regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU0, VUregsn); } +void VU0regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU0, VUregsn); } +void VU0regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU0, VUregsn); } +void VU0regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU0, VUregsn); } +void VU0regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU0, VUregsn); } +void VU0regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU0, VUregsn); } +void VU0regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU0, VUregsn); } +void VU0regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU0, VUregsn); } +void VU0regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU0, VUregsn); } +void VU0regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU0, VUregsn); } +void VU0regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU0, VUregsn); } +void VU0regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU0, VUregsn); } +void VU0regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU0, VUregsn); } +void VU0regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU0, VUregsn); } +void VU0regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU0, VUregsn); } +void VU0regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU0, VUregsn); } +void VU0regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU0, VUregsn); } +void VU0regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU0, VUregsn); } +void VU0regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU0, VUregsn); } +void VU0regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU0, VUregsn); } +void VU0regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU0, VUregsn); } +void VU0regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU0, VUregsn); } +void VU0regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU0, VUregsn); } +void VU0regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU0, VUregsn); } +void VU0regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU0, VUregsn); } +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU0, VUregsn); } +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU0, VUregsn); } +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU0, VUregsn); } +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU0, VUregsn); } +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU0, VUregsn); } +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU0, VUregsn); } +void VU0regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU0, VUregsn); } +void VU0regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU0, VUregsn); } +void VU0regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU0, VUregsn); } +void VU0regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU0, VUregsn); } +void VU0regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU0, VUregsn); } +void VU0regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU0, VUregsn); } +void VU0regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU0, VUregsn); } +void VU0regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU0, VUregsn); } +void VU0regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU0, VUregsn); } +void VU0regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU0, VUregsn); } +void VU0regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU0, VUregsn); } +void VU0regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU0, VUregsn); } +void VU0regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU0, VUregsn); } +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU0, VUregsn); } +void VU0regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU0, VUregsn); } +void VU0regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU0, VUregsn); } +void VU0regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU0, VUregsn); } +void VU0regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU0, VUregsn); } +void VU0regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU0, VUregsn); } +void VU0regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU0, VUregsn); } +void VU0regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU0, VUregsn); } +void VU0regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU0, VUregsn); } +void VU0regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU0, VUregsn); } +void VU0regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU0, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU0, VUregsn); } +void VU0regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU0, VUregsn); } +void VU0regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU0, VUregsn); } +void VU0regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU0, VUregsn); } +void VU0regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU0, VUregsn); } +void VU0regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU0, VUregsn); } +void VU0regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU0, VUregsn); } +void VU0regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU0, VUregsn); } +void VU0regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU0, VUregsn); } +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU0, VUregsn); } +void VU0regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU0, VUregsn); } +void VU0regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU0, VUregsn); } +void VU0regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU0, VUregsn); } +void VU0regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU0, VUregsn); } +void VU0regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU0, VUregsn); } +void VU0regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU0, VUregsn); } +void VU0regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU0, VUregsn); } +void VU0regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU0, VUregsn); } +void VU0regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU0, VUregsn); } +void VU0regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU0, VUregsn); } +void VU0regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU0, VUregsn); } +void VU0regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU0, VUregsn); } +void VU0regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU0, VUregsn); } +void VU0regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU0, VUregsn); } +void VU0regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU0, VUregsn); } +void VU0regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU0, VUregsn); } +void VU0regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU0, VUregsn); } +void VU0regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU0, VUregsn); } +void VU0regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU0, VUregsn); } +void VU0regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU0, VUregsn); } +void VU0regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU0, VUregsn); } +void VU0regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU0, VUregsn); } +void VU0regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU0, VUregsn); } +void VU0regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU0, VUregsn); } +void VU0regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU0, VUregsn); } +void VU0regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU0, VUregsn); } +void VU0regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU0, VUregsn); } +void VU0regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU0, VUregsn); } +void VU0regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU0, VUregsn); } +void VU0regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU0, VUregsn); } +void VU0regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU0, VUregsn); } +void VU0regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU0, VUregsn); } +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU0, VUregsn); } +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU0, VUregsn); } +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU0, VUregsn); } +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU0, VUregsn); } +void VU0regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU0, VUregsn); } +void VU0regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU0, VUregsn); } +void VU0regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU0, VUregsn); } +void VU0regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU0, VUregsn); } +void VU0regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU0, VUregsn); } +void VU0regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU0, VUregsn); } +void VU0regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU0, VUregsn); } +void VU0regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU0, VUregsn); } +void VU0regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU0, VUregsn); } +void VU0regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU0, VUregsn); } +void VU0regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU0, VUregsn); } +void VU0regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU0, VUregsn); } +void VU0regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU0, VUregsn); } +void VU0regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU0, VUregsn); } +void VU0regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU0, VUregsn); } +void VU0regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU0, VUregsn); } +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU0, VUregsn); } +void VU0regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU0, VUregsn); } +void VU0regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU0, VUregsn); } +void VU0regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU0, VUregsn); } +void VU0regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU0, VUregsn); } +void VU0regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU0, VUregsn); } +void VU0regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU0, VUregsn); } diff --git a/pcsx2/VU1micro.c b/pcsx2/VU1micro.c new file mode 100644 index 0000000..c4e660a --- /dev/null +++ b/pcsx2/VU1micro.c @@ -0,0 +1,698 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include + +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "VUops.h" +#include "VUflags.h" +#include "iVU1micro.h" + +#include "iVUzerorec.h" + +VURegs* g_pVU1; + +#ifdef PCSX2_VIRTUAL_MEM +extern PSMEMORYBLOCK s_psVuMem; +#endif + +#ifdef _WIN32 +#pragma warning(disable:4113) +#endif + +#ifdef PCSX2_DEVBUILD +u32 vudump = 0; +#endif + +#define VF_VAL(x) ((x==0x80000000)?0:(x)) + +void iDumpVU1Registers() +{ + int i; +// static int icount = 0; +// __Log("%x\n", icount); + for(i = 1; i < 32; ++i) { +// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2], +// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]); + //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); + //else __Log("%x\n", VU1.VI[i].UL); + else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); +} + +int vu1Init() +{ + assert( VU0.Mem != NULL ); + g_pVU1 = (VURegs*)(VU0.Mem + 0x4000); + +#ifdef PCSX2_VIRTUAL_MEM + VU1.Mem = PS2MEM_VU1MEM; + VU1.Micro = PS2MEM_VU1MICRO; +#else + VU1.Mem = (u8*)_aligned_malloc(16*1024, 16); + VU1.Micro = (u8*)_aligned_malloc(16*1024, 16); + if (VU1.Mem == NULL || VU1.Micro == NULL) { + SysMessage(_("Error allocating memory")); return -1; + } + memset(VU1.Mem, 0,16*1024); + memset(VU1.Micro, 0,16*1024); +#endif + + VU1.maxmem = -1;//16*1024-4; + VU1.maxmicro = 16*1024-4; +// VU1.VF = (VECTOR*)(VU0.Mem + 0x4000); +// VU1.VI = (REG_VI*)(VU0.Mem + 0x4200); + VU1.vuExec = vu1Exec; + VU1.vifRegs = vif1Regs; + +#ifndef PCSX2_NORECBUILD + if( CHECK_VU1REC ) { + recVU1Init(); + } +#endif + + vu1Reset(); + + return 0; +} + +void vu1Shutdown() { +#ifndef PCSX2_NORECBUILD + if( CHECK_VU1REC ) { + recVU1Shutdown(); + } +#endif +} + +void vu1ResetRegs() +{ + VU0.VI[REG_VPU_STAT].UL &= ~0xff00; // stop vu1 + VU0.VI[REG_FBRST].UL &= ~0xff00; // stop vu1 + vif1Regs->stat &= ~4; +} + +void vu1Reset() { + memset(&VU1.ACC, 0, sizeof(VECTOR)); + memset(VU1.VF, 0, sizeof(VECTOR)*32); + memset(VU1.VI, 0, sizeof(REG_VI)*32); + VU1.VF[0].f.x = 0.0f; + VU1.VF[0].f.y = 0.0f; + VU1.VF[0].f.z = 0.0f; + VU1.VF[0].f.w = 1.0f; + VU1.VI[0].UL = 0; + memset(VU1.Mem, 0, 16*1024); + memset(VU1.Micro, 0, 16*1024); + +#ifndef PCSX2_NORECBUILD + recResetVU1(); +#endif +} + +void vu1Freeze(gzFile f, int Mode) { + gzfreeze(&VU1.ACC, sizeof(VECTOR)); + gzfreeze(&VU1.code, sizeof(u32)); + gzfreeze(VU1.Mem, 16*1024); + gzfreeze(VU1.Micro, 16*1024); + gzfreeze(VU1.VF, 32*sizeof(VECTOR)); + gzfreeze(VU1.VI, 32*sizeof(REG_VI)); +} + +static int count; + +void vu1ExecMicro(u32 addr) +{ +#ifdef VUM_LOG + VUM_LOG("vu1ExecMicro %x\n", addr); + VUM_LOG("vu1ExecMicro %x (count=%d)\n", addr, count++); +#endif + VU0.VI[REG_VPU_STAT].UL|= 0x100; + VU0.VI[REG_VPU_STAT].UL&= ~0x7E000; + vif1Regs->stat|= 0x4; + if (addr != -1) VU1.VI[REG_TPC].UL = addr; + _vuExecMicroDebug(VU1); + + FreezeXMMRegs(1); + //do { + Cpu->ExecuteVU1Block(); + //} while(VU0.VI[REG_VPU_STAT].UL & 0x100); + // rec can call vu1ExecMicro + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void _vu1ExecUpper(VURegs* VU, u32 *ptr) { + VU->code = ptr[1]; + IdebugUPPER(VU1); + VU1_UPPER_OPCODE[VU->code & 0x3f](); +} + +void _vu1ExecLower(VURegs* VU, u32 *ptr) { + VU->code = ptr[0]; + IdebugLOWER(VU1); + VU1_LOWER_OPCODE[VU->code >> 25](); +} + +extern void _vuFlushAll(VURegs* VU); + +int vu1branch = 0; + +void _vu1Exec(VURegs* VU) { + _VURegsNum lregs; + _VURegsNum uregs; + VECTOR _VF; + VECTOR _VFc; + REG_VI _VI; + REG_VI _VIc; + u32 *ptr; + int vfreg; + int vireg; + int discard=0; + + if(VU1.VI[REG_TPC].UL >= VU1.maxmicro){ +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + ptr = (u32*)&VU->Micro[VU->VI[REG_TPC].UL]; + VU->VI[REG_TPC].UL+=8; + + if (ptr[1] & 0x40000000) { /* E flag */ + VU->ebit = 2; + } + if (ptr[1] & 0x10000000) { /* D flag */ + if (VU0.VI[REG_FBRST].UL & 0x400) { + VU0.VI[REG_VPU_STAT].UL|= 0x200; + hwIntcIrq(INTC_VU1); + } + } + if (ptr[1] & 0x08000000) { /* T flag */ + if (VU0.VI[REG_FBRST].UL & 0x800) { + VU0.VI[REG_VPU_STAT].UL|= 0x400; + hwIntcIrq(INTC_VU1); + } + } + +#ifdef VUM_LOG + if (Log) { + VUM_LOG("VU->cycle = %d (flags st=%x;mac=%x;clip=%x,q=%f)\n", VU->cycle, VU->statusflag, VU->macflag, VU->clipflag, VU->q.F); + } +#endif + + VU->code = ptr[1]; + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + _vuTestUpperStalls(VU, &uregs); + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + _vu1ExecUpper(VU, ptr); + + VU->VI[REG_I].UL = ptr[0]; + } else { + VU->code = ptr[0]; + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + _vuTestLowerStalls(VU, &lregs); + + vu1branch = lregs.pipe == VUPIPE_BRANCH; + + vfreg = 0; vireg = 0; + if (uregs.VFwrite) { + if (lregs.VFwrite == uregs.VFwrite) { +// SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VFread0 == uregs.VFwrite || + lregs.VFread1 == uregs.VFwrite) { +// SysPrintf("saving reg %d at pc=%x\n", i, VU->VI[REG_TPC].UL); + _VF = VU->VF[uregs.VFwrite]; + vfreg = uregs.VFwrite; + } + } + if (uregs.VIread & (1 << REG_CLIP_FLAG)) { + if (lregs.VIwrite & (1 << REG_CLIP_FLAG)) { + SysPrintf("*PCSX2*: Warning, VI write to the same reg in both lower/upper cycle\n"); + discard = 1; + } + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + _VI = VU->VI[REG_CLIP_FLAG]; + vireg = REG_CLIP_FLAG; + } + } + + _vu1ExecUpper(VU, ptr); + + if (discard == 0) { + if (vfreg) { + _VFc = VU->VF[vfreg]; + VU->VF[vfreg] = _VF; + } + if (vireg) { + _VIc = VU->VI[vireg]; + VU->VI[vireg] = _VI; + } + + _vu1ExecLower(VU, ptr); + + if (vfreg) { + VU->VF[vfreg] = _VFc; + } + if (vireg) { + VU->VI[vireg] = _VIc; + } + } + } + _vuAddUpperStalls(VU, &uregs); + _vuAddLowerStalls(VU, &lregs); + + _vuTestPipes(VU); + + if (VU->branch > 0) { + if (VU->branch-- == 1) { + VU->VI[REG_TPC].UL = VU->branchpc; + } + } + + if( VU->ebit > 0 ) { + if( VU->ebit-- == 1 ) { + _vuFlushAll(VU); + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + vif1Regs->stat&= ~0x4; + } + } +} + +void vu1Exec(VURegs* VU) { + if (VU->VI[REG_TPC].UL >= VU->maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + } else { + _vu1Exec(VU); + } + VU->cycle++; +#ifdef CPU_LOG + if (VU->VI[0].UL != 0) SysPrintf("VI[0] != 0!!!!\n"); + if (VU->VF[0].f.x != 0.0f) SysPrintf("VF[0].x != 0.0!!!!\n"); + if (VU->VF[0].f.y != 0.0f) SysPrintf("VF[0].y != 0.0!!!!\n"); + if (VU->VF[0].f.z != 0.0f) SysPrintf("VF[0].z != 0.0!!!!\n"); + if (VU->VF[0].f.w != 1.0f) SysPrintf("VF[0].w != 1.0!!!!\n"); +#endif +} + +_vuTables(VU1, VU1); +_vuRegsTables(VU1, VU1regs); + +void VU1unknown(_VURegsNum *VUregsn) { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + +void VU1regsunknown(_VURegsNum *VUregsn) { + //assert(0); +#ifdef CPU_LOG + CPU_LOG("Unknown VU micromode opcode called\n"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1MI_ABS() { _vuABS(&VU1); } +void VU1MI_ADD() { _vuADD(&VU1); } +void VU1MI_ADDi() { _vuADDi(&VU1); } +void VU1MI_ADDq() { _vuADDq(&VU1); } +void VU1MI_ADDx() { _vuADDx(&VU1); } +void VU1MI_ADDy() { _vuADDy(&VU1); } +void VU1MI_ADDz() { _vuADDz(&VU1); } +void VU1MI_ADDw() { _vuADDw(&VU1); } +void VU1MI_ADDA() { _vuADDA(&VU1); } +void VU1MI_ADDAi() { _vuADDAi(&VU1); } +void VU1MI_ADDAq() { _vuADDAq(&VU1); } +void VU1MI_ADDAx() { _vuADDAx(&VU1); } +void VU1MI_ADDAy() { _vuADDAy(&VU1); } +void VU1MI_ADDAz() { _vuADDAz(&VU1); } +void VU1MI_ADDAw() { _vuADDAw(&VU1); } +void VU1MI_SUB() { _vuSUB(&VU1); } +void VU1MI_SUBi() { _vuSUBi(&VU1); } +void VU1MI_SUBq() { _vuSUBq(&VU1); } +void VU1MI_SUBx() { _vuSUBx(&VU1); } +void VU1MI_SUBy() { _vuSUBy(&VU1); } +void VU1MI_SUBz() { _vuSUBz(&VU1); } +void VU1MI_SUBw() { _vuSUBw(&VU1); } +void VU1MI_SUBA() { _vuSUBA(&VU1); } +void VU1MI_SUBAi() { _vuSUBAi(&VU1); } +void VU1MI_SUBAq() { _vuSUBAq(&VU1); } +void VU1MI_SUBAx() { _vuSUBAx(&VU1); } +void VU1MI_SUBAy() { _vuSUBAy(&VU1); } +void VU1MI_SUBAz() { _vuSUBAz(&VU1); } +void VU1MI_SUBAw() { _vuSUBAw(&VU1); } +void VU1MI_MUL() { _vuMUL(&VU1); } +void VU1MI_MULi() { _vuMULi(&VU1); } +void VU1MI_MULq() { _vuMULq(&VU1); } +void VU1MI_MULx() { _vuMULx(&VU1); } +void VU1MI_MULy() { _vuMULy(&VU1); } +void VU1MI_MULz() { _vuMULz(&VU1); } +void VU1MI_MULw() { _vuMULw(&VU1); } +void VU1MI_MULA() { _vuMULA(&VU1); } +void VU1MI_MULAi() { _vuMULAi(&VU1); } +void VU1MI_MULAq() { _vuMULAq(&VU1); } +void VU1MI_MULAx() { _vuMULAx(&VU1); } +void VU1MI_MULAy() { _vuMULAy(&VU1); } +void VU1MI_MULAz() { _vuMULAz(&VU1); } +void VU1MI_MULAw() { _vuMULAw(&VU1); } +void VU1MI_MADD() { _vuMADD(&VU1); } +void VU1MI_MADDi() { _vuMADDi(&VU1); } +void VU1MI_MADDq() { _vuMADDq(&VU1); } +void VU1MI_MADDx() { _vuMADDx(&VU1); } +void VU1MI_MADDy() { _vuMADDy(&VU1); } +void VU1MI_MADDz() { _vuMADDz(&VU1); } +void VU1MI_MADDw() { _vuMADDw(&VU1); } +void VU1MI_MADDA() { _vuMADDA(&VU1); } +void VU1MI_MADDAi() { _vuMADDAi(&VU1); } +void VU1MI_MADDAq() { _vuMADDAq(&VU1); } +void VU1MI_MADDAx() { _vuMADDAx(&VU1); } +void VU1MI_MADDAy() { _vuMADDAy(&VU1); } +void VU1MI_MADDAz() { _vuMADDAz(&VU1); } +void VU1MI_MADDAw() { _vuMADDAw(&VU1); } +void VU1MI_MSUB() { _vuMSUB(&VU1); } +void VU1MI_MSUBi() { _vuMSUBi(&VU1); } +void VU1MI_MSUBq() { _vuMSUBq(&VU1); } +void VU1MI_MSUBx() { _vuMSUBx(&VU1); } +void VU1MI_MSUBy() { _vuMSUBy(&VU1); } +void VU1MI_MSUBz() { _vuMSUBz(&VU1); } +void VU1MI_MSUBw() { _vuMSUBw(&VU1); } +void VU1MI_MSUBA() { _vuMSUBA(&VU1); } +void VU1MI_MSUBAi() { _vuMSUBAi(&VU1); } +void VU1MI_MSUBAq() { _vuMSUBAq(&VU1); } +void VU1MI_MSUBAx() { _vuMSUBAx(&VU1); } +void VU1MI_MSUBAy() { _vuMSUBAy(&VU1); } +void VU1MI_MSUBAz() { _vuMSUBAz(&VU1); } +void VU1MI_MSUBAw() { _vuMSUBAw(&VU1); } +void VU1MI_MAX() { _vuMAX(&VU1); } +void VU1MI_MAXi() { _vuMAXi(&VU1); } +void VU1MI_MAXx() { _vuMAXx(&VU1); } +void VU1MI_MAXy() { _vuMAXy(&VU1); } +void VU1MI_MAXz() { _vuMAXz(&VU1); } +void VU1MI_MAXw() { _vuMAXw(&VU1); } +void VU1MI_MINI() { _vuMINI(&VU1); } +void VU1MI_MINIi() { _vuMINIi(&VU1); } +void VU1MI_MINIx() { _vuMINIx(&VU1); } +void VU1MI_MINIy() { _vuMINIy(&VU1); } +void VU1MI_MINIz() { _vuMINIz(&VU1); } +void VU1MI_MINIw() { _vuMINIw(&VU1); } +void VU1MI_OPMULA() { _vuOPMULA(&VU1); } +void VU1MI_OPMSUB() { _vuOPMSUB(&VU1); } +void VU1MI_NOP() { _vuNOP(&VU1); } +void VU1MI_FTOI0() { _vuFTOI0(&VU1); } +void VU1MI_FTOI4() { _vuFTOI4(&VU1); } +void VU1MI_FTOI12() { _vuFTOI12(&VU1); } +void VU1MI_FTOI15() { _vuFTOI15(&VU1); } +void VU1MI_ITOF0() { _vuITOF0(&VU1); } +void VU1MI_ITOF4() { _vuITOF4(&VU1); } +void VU1MI_ITOF12() { _vuITOF12(&VU1); } +void VU1MI_ITOF15() { _vuITOF15(&VU1); } +void VU1MI_CLIP() { _vuCLIP(&VU1); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1MI_DIV() { _vuDIV(&VU1); } +void VU1MI_SQRT() { _vuSQRT(&VU1); } +void VU1MI_RSQRT() { _vuRSQRT(&VU1); } +void VU1MI_IADD() { _vuIADD(&VU1); } +void VU1MI_IADDI() { _vuIADDI(&VU1); } +void VU1MI_IADDIU() { _vuIADDIU(&VU1); } +void VU1MI_IAND() { _vuIAND(&VU1); } +void VU1MI_IOR() { _vuIOR(&VU1); } +void VU1MI_ISUB() { _vuISUB(&VU1); } +void VU1MI_ISUBIU() { _vuISUBIU(&VU1); } +void VU1MI_MOVE() { _vuMOVE(&VU1); } +void VU1MI_MFIR() { _vuMFIR(&VU1); } +void VU1MI_MTIR() { _vuMTIR(&VU1); } +void VU1MI_MR32() { _vuMR32(&VU1); } +void VU1MI_LQ() { _vuLQ(&VU1); } +void VU1MI_LQD() { _vuLQD(&VU1); } +void VU1MI_LQI() { _vuLQI(&VU1); } +void VU1MI_SQ() { _vuSQ(&VU1); } +void VU1MI_SQD() { _vuSQD(&VU1); } +void VU1MI_SQI() { _vuSQI(&VU1); } +void VU1MI_ILW() { _vuILW(&VU1); } +void VU1MI_ISW() { _vuISW(&VU1); } +void VU1MI_ILWR() { _vuILWR(&VU1); } +void VU1MI_ISWR() { _vuISWR(&VU1); } +void VU1MI_RINIT() { _vuRINIT(&VU1); } +void VU1MI_RGET() { _vuRGET(&VU1); } +void VU1MI_RNEXT() { _vuRNEXT(&VU1); } +void VU1MI_RXOR() { _vuRXOR(&VU1); } +void VU1MI_WAITQ() { _vuWAITQ(&VU1); } +void VU1MI_FSAND() { _vuFSAND(&VU1); } +void VU1MI_FSEQ() { _vuFSEQ(&VU1); } +void VU1MI_FSOR() { _vuFSOR(&VU1); } +void VU1MI_FSSET() { _vuFSSET(&VU1); } +void VU1MI_FMAND() { _vuFMAND(&VU1); } +void VU1MI_FMEQ() { _vuFMEQ(&VU1); } +void VU1MI_FMOR() { _vuFMOR(&VU1); } +void VU1MI_FCAND() { _vuFCAND(&VU1); } +void VU1MI_FCEQ() { _vuFCEQ(&VU1); } +void VU1MI_FCOR() { _vuFCOR(&VU1); } +void VU1MI_FCSET() { _vuFCSET(&VU1); } +void VU1MI_FCGET() { _vuFCGET(&VU1); } +void VU1MI_IBEQ() { _vuIBEQ(&VU1); } +void VU1MI_IBGEZ() { _vuIBGEZ(&VU1); } +void VU1MI_IBGTZ() { _vuIBGTZ(&VU1); } +void VU1MI_IBLTZ() { _vuIBLTZ(&VU1); } +void VU1MI_IBLEZ() { _vuIBLEZ(&VU1); } +void VU1MI_IBNE() { _vuIBNE(&VU1); } +void VU1MI_B() { _vuB(&VU1); } +void VU1MI_BAL() { _vuBAL(&VU1); } +void VU1MI_JR() { _vuJR(&VU1); } +void VU1MI_JALR() { _vuJALR(&VU1); } +void VU1MI_MFP() { _vuMFP(&VU1); } +void VU1MI_WAITP() { _vuWAITP(&VU1); } +void VU1MI_ESADD() { _vuESADD(&VU1); } +void VU1MI_ERSADD() { _vuERSADD(&VU1); } +void VU1MI_ELENG() { _vuELENG(&VU1); } +void VU1MI_ERLENG() { _vuERLENG(&VU1); } +void VU1MI_EATANxy() { _vuEATANxy(&VU1); } +void VU1MI_EATANxz() { _vuEATANxz(&VU1); } +void VU1MI_ESUM() { _vuESUM(&VU1); } +void VU1MI_ERCPR() { _vuERCPR(&VU1); } +void VU1MI_ESQRT() { _vuESQRT(&VU1); } +void VU1MI_ERSQRT() { _vuERSQRT(&VU1); } +void VU1MI_ESIN() { _vuESIN(&VU1); } +void VU1MI_EATAN() { _vuEATAN(&VU1); } +void VU1MI_EEXP() { _vuEEXP(&VU1); } +void VU1MI_XITOP() { _vuXITOP(&VU1); } +void VU1MI_XGKICK() { _vuXGKICK(&VU1); } +void VU1MI_XTOP() { _vuXTOP(&VU1); } + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn) { _vuRegsABS(&VU1, VUregsn); } +void VU1regsMI_ADD(_VURegsNum *VUregsn) { _vuRegsADD(&VU1, VUregsn); } +void VU1regsMI_ADDi(_VURegsNum *VUregsn) { _vuRegsADDi(&VU1, VUregsn); } +void VU1regsMI_ADDq(_VURegsNum *VUregsn) { _vuRegsADDq(&VU1, VUregsn); } +void VU1regsMI_ADDx(_VURegsNum *VUregsn) { _vuRegsADDx(&VU1, VUregsn); } +void VU1regsMI_ADDy(_VURegsNum *VUregsn) { _vuRegsADDy(&VU1, VUregsn); } +void VU1regsMI_ADDz(_VURegsNum *VUregsn) { _vuRegsADDz(&VU1, VUregsn); } +void VU1regsMI_ADDw(_VURegsNum *VUregsn) { _vuRegsADDw(&VU1, VUregsn); } +void VU1regsMI_ADDA(_VURegsNum *VUregsn) { _vuRegsADDA(&VU1, VUregsn); } +void VU1regsMI_ADDAi(_VURegsNum *VUregsn) { _vuRegsADDAi(&VU1, VUregsn); } +void VU1regsMI_ADDAq(_VURegsNum *VUregsn) { _vuRegsADDAq(&VU1, VUregsn); } +void VU1regsMI_ADDAx(_VURegsNum *VUregsn) { _vuRegsADDAx(&VU1, VUregsn); } +void VU1regsMI_ADDAy(_VURegsNum *VUregsn) { _vuRegsADDAy(&VU1, VUregsn); } +void VU1regsMI_ADDAz(_VURegsNum *VUregsn) { _vuRegsADDAz(&VU1, VUregsn); } +void VU1regsMI_ADDAw(_VURegsNum *VUregsn) { _vuRegsADDAw(&VU1, VUregsn); } +void VU1regsMI_SUB(_VURegsNum *VUregsn) { _vuRegsSUB(&VU1, VUregsn); } +void VU1regsMI_SUBi(_VURegsNum *VUregsn) { _vuRegsSUBi(&VU1, VUregsn); } +void VU1regsMI_SUBq(_VURegsNum *VUregsn) { _vuRegsSUBq(&VU1, VUregsn); } +void VU1regsMI_SUBx(_VURegsNum *VUregsn) { _vuRegsSUBx(&VU1, VUregsn); } +void VU1regsMI_SUBy(_VURegsNum *VUregsn) { _vuRegsSUBy(&VU1, VUregsn); } +void VU1regsMI_SUBz(_VURegsNum *VUregsn) { _vuRegsSUBz(&VU1, VUregsn); } +void VU1regsMI_SUBw(_VURegsNum *VUregsn) { _vuRegsSUBw(&VU1, VUregsn); } +void VU1regsMI_SUBA(_VURegsNum *VUregsn) { _vuRegsSUBA(&VU1, VUregsn); } +void VU1regsMI_SUBAi(_VURegsNum *VUregsn) { _vuRegsSUBAi(&VU1, VUregsn); } +void VU1regsMI_SUBAq(_VURegsNum *VUregsn) { _vuRegsSUBAq(&VU1, VUregsn); } +void VU1regsMI_SUBAx(_VURegsNum *VUregsn) { _vuRegsSUBAx(&VU1, VUregsn); } +void VU1regsMI_SUBAy(_VURegsNum *VUregsn) { _vuRegsSUBAy(&VU1, VUregsn); } +void VU1regsMI_SUBAz(_VURegsNum *VUregsn) { _vuRegsSUBAz(&VU1, VUregsn); } +void VU1regsMI_SUBAw(_VURegsNum *VUregsn) { _vuRegsSUBAw(&VU1, VUregsn); } +void VU1regsMI_MUL(_VURegsNum *VUregsn) { _vuRegsMUL(&VU1, VUregsn); } +void VU1regsMI_MULi(_VURegsNum *VUregsn) { _vuRegsMULi(&VU1, VUregsn); } +void VU1regsMI_MULq(_VURegsNum *VUregsn) { _vuRegsMULq(&VU1, VUregsn); } +void VU1regsMI_MULx(_VURegsNum *VUregsn) { _vuRegsMULx(&VU1, VUregsn); } +void VU1regsMI_MULy(_VURegsNum *VUregsn) { _vuRegsMULy(&VU1, VUregsn); } +void VU1regsMI_MULz(_VURegsNum *VUregsn) { _vuRegsMULz(&VU1, VUregsn); } +void VU1regsMI_MULw(_VURegsNum *VUregsn) { _vuRegsMULw(&VU1, VUregsn); } +void VU1regsMI_MULA(_VURegsNum *VUregsn) { _vuRegsMULA(&VU1, VUregsn); } +void VU1regsMI_MULAi(_VURegsNum *VUregsn) { _vuRegsMULAi(&VU1, VUregsn); } +void VU1regsMI_MULAq(_VURegsNum *VUregsn) { _vuRegsMULAq(&VU1, VUregsn); } +void VU1regsMI_MULAx(_VURegsNum *VUregsn) { _vuRegsMULAx(&VU1, VUregsn); } +void VU1regsMI_MULAy(_VURegsNum *VUregsn) { _vuRegsMULAy(&VU1, VUregsn); } +void VU1regsMI_MULAz(_VURegsNum *VUregsn) { _vuRegsMULAz(&VU1, VUregsn); } +void VU1regsMI_MULAw(_VURegsNum *VUregsn) { _vuRegsMULAw(&VU1, VUregsn); } +void VU1regsMI_MADD(_VURegsNum *VUregsn) { _vuRegsMADD(&VU1, VUregsn); } +void VU1regsMI_MADDi(_VURegsNum *VUregsn) { _vuRegsMADDi(&VU1, VUregsn); } +void VU1regsMI_MADDq(_VURegsNum *VUregsn) { _vuRegsMADDq(&VU1, VUregsn); } +void VU1regsMI_MADDx(_VURegsNum *VUregsn) { _vuRegsMADDx(&VU1, VUregsn); } +void VU1regsMI_MADDy(_VURegsNum *VUregsn) { _vuRegsMADDy(&VU1, VUregsn); } +void VU1regsMI_MADDz(_VURegsNum *VUregsn) { _vuRegsMADDz(&VU1, VUregsn); } +void VU1regsMI_MADDw(_VURegsNum *VUregsn) { _vuRegsMADDw(&VU1, VUregsn); } +void VU1regsMI_MADDA(_VURegsNum *VUregsn) { _vuRegsMADDA(&VU1, VUregsn); } +void VU1regsMI_MADDAi(_VURegsNum *VUregsn) { _vuRegsMADDAi(&VU1, VUregsn); } +void VU1regsMI_MADDAq(_VURegsNum *VUregsn) { _vuRegsMADDAq(&VU1, VUregsn); } +void VU1regsMI_MADDAx(_VURegsNum *VUregsn) { _vuRegsMADDAx(&VU1, VUregsn); } +void VU1regsMI_MADDAy(_VURegsNum *VUregsn) { _vuRegsMADDAy(&VU1, VUregsn); } +void VU1regsMI_MADDAz(_VURegsNum *VUregsn) { _vuRegsMADDAz(&VU1, VUregsn); } +void VU1regsMI_MADDAw(_VURegsNum *VUregsn) { _vuRegsMADDAw(&VU1, VUregsn); } +void VU1regsMI_MSUB(_VURegsNum *VUregsn) { _vuRegsMSUB(&VU1, VUregsn); } +void VU1regsMI_MSUBi(_VURegsNum *VUregsn) { _vuRegsMSUBi(&VU1, VUregsn); } +void VU1regsMI_MSUBq(_VURegsNum *VUregsn) { _vuRegsMSUBq(&VU1, VUregsn); } +void VU1regsMI_MSUBx(_VURegsNum *VUregsn) { _vuRegsMSUBx(&VU1, VUregsn); } +void VU1regsMI_MSUBy(_VURegsNum *VUregsn) { _vuRegsMSUBy(&VU1, VUregsn); } +void VU1regsMI_MSUBz(_VURegsNum *VUregsn) { _vuRegsMSUBz(&VU1, VUregsn); } +void VU1regsMI_MSUBw(_VURegsNum *VUregsn) { _vuRegsMSUBw(&VU1, VUregsn); } +void VU1regsMI_MSUBA(_VURegsNum *VUregsn) { _vuRegsMSUBA(&VU1, VUregsn); } +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn) { _vuRegsMSUBAi(&VU1, VUregsn); } +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn) { _vuRegsMSUBAq(&VU1, VUregsn); } +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn) { _vuRegsMSUBAx(&VU1, VUregsn); } +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn) { _vuRegsMSUBAy(&VU1, VUregsn); } +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn) { _vuRegsMSUBAz(&VU1, VUregsn); } +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn) { _vuRegsMSUBAw(&VU1, VUregsn); } +void VU1regsMI_MAX(_VURegsNum *VUregsn) { _vuRegsMAX(&VU1, VUregsn); } +void VU1regsMI_MAXi(_VURegsNum *VUregsn) { _vuRegsMAXi(&VU1, VUregsn); } +void VU1regsMI_MAXx(_VURegsNum *VUregsn) { _vuRegsMAXx(&VU1, VUregsn); } +void VU1regsMI_MAXy(_VURegsNum *VUregsn) { _vuRegsMAXy(&VU1, VUregsn); } +void VU1regsMI_MAXz(_VURegsNum *VUregsn) { _vuRegsMAXz(&VU1, VUregsn); } +void VU1regsMI_MAXw(_VURegsNum *VUregsn) { _vuRegsMAXw(&VU1, VUregsn); } +void VU1regsMI_MINI(_VURegsNum *VUregsn) { _vuRegsMINI(&VU1, VUregsn); } +void VU1regsMI_MINIi(_VURegsNum *VUregsn) { _vuRegsMINIi(&VU1, VUregsn); } +void VU1regsMI_MINIx(_VURegsNum *VUregsn) { _vuRegsMINIx(&VU1, VUregsn); } +void VU1regsMI_MINIy(_VURegsNum *VUregsn) { _vuRegsMINIy(&VU1, VUregsn); } +void VU1regsMI_MINIz(_VURegsNum *VUregsn) { _vuRegsMINIz(&VU1, VUregsn); } +void VU1regsMI_MINIw(_VURegsNum *VUregsn) { _vuRegsMINIw(&VU1, VUregsn); } +void VU1regsMI_OPMULA(_VURegsNum *VUregsn) { _vuRegsOPMULA(&VU1, VUregsn); } +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn) { _vuRegsOPMSUB(&VU1, VUregsn); } +void VU1regsMI_NOP(_VURegsNum *VUregsn) { _vuRegsNOP(&VU1, VUregsn); } +void VU1regsMI_FTOI0(_VURegsNum *VUregsn) { _vuRegsFTOI0(&VU1, VUregsn); } +void VU1regsMI_FTOI4(_VURegsNum *VUregsn) { _vuRegsFTOI4(&VU1, VUregsn); } +void VU1regsMI_FTOI12(_VURegsNum *VUregsn) { _vuRegsFTOI12(&VU1, VUregsn); } +void VU1regsMI_FTOI15(_VURegsNum *VUregsn) { _vuRegsFTOI15(&VU1, VUregsn); } +void VU1regsMI_ITOF0(_VURegsNum *VUregsn) { _vuRegsITOF0(&VU1, VUregsn); } +void VU1regsMI_ITOF4(_VURegsNum *VUregsn) { _vuRegsITOF4(&VU1, VUregsn); } +void VU1regsMI_ITOF12(_VURegsNum *VUregsn) { _vuRegsITOF12(&VU1, VUregsn); } +void VU1regsMI_ITOF15(_VURegsNum *VUregsn) { _vuRegsITOF15(&VU1, VUregsn); } +void VU1regsMI_CLIP(_VURegsNum *VUregsn) { _vuRegsCLIP(&VU1, VUregsn); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn) { _vuRegsDIV(&VU1, VUregsn); } +void VU1regsMI_SQRT(_VURegsNum *VUregsn) { _vuRegsSQRT(&VU1, VUregsn); } +void VU1regsMI_RSQRT(_VURegsNum *VUregsn) { _vuRegsRSQRT(&VU1, VUregsn); } +void VU1regsMI_IADD(_VURegsNum *VUregsn) { _vuRegsIADD(&VU1, VUregsn); } +void VU1regsMI_IADDI(_VURegsNum *VUregsn) { _vuRegsIADDI(&VU1, VUregsn); } +void VU1regsMI_IADDIU(_VURegsNum *VUregsn) { _vuRegsIADDIU(&VU1, VUregsn); } +void VU1regsMI_IAND(_VURegsNum *VUregsn) { _vuRegsIAND(&VU1, VUregsn); } +void VU1regsMI_IOR(_VURegsNum *VUregsn) { _vuRegsIOR(&VU1, VUregsn); } +void VU1regsMI_ISUB(_VURegsNum *VUregsn) { _vuRegsISUB(&VU1, VUregsn); } +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn) { _vuRegsISUBIU(&VU1, VUregsn); } +void VU1regsMI_MOVE(_VURegsNum *VUregsn) { _vuRegsMOVE(&VU1, VUregsn); } +void VU1regsMI_MFIR(_VURegsNum *VUregsn) { _vuRegsMFIR(&VU1, VUregsn); } +void VU1regsMI_MTIR(_VURegsNum *VUregsn) { _vuRegsMTIR(&VU1, VUregsn); } +void VU1regsMI_MR32(_VURegsNum *VUregsn) { _vuRegsMR32(&VU1, VUregsn); } +void VU1regsMI_LQ(_VURegsNum *VUregsn) { _vuRegsLQ(&VU1, VUregsn); } +void VU1regsMI_LQD(_VURegsNum *VUregsn) { _vuRegsLQD(&VU1, VUregsn); } +void VU1regsMI_LQI(_VURegsNum *VUregsn) { _vuRegsLQI(&VU1, VUregsn); } +void VU1regsMI_SQ(_VURegsNum *VUregsn) { _vuRegsSQ(&VU1, VUregsn); } +void VU1regsMI_SQD(_VURegsNum *VUregsn) { _vuRegsSQD(&VU1, VUregsn); } +void VU1regsMI_SQI(_VURegsNum *VUregsn) { _vuRegsSQI(&VU1, VUregsn); } +void VU1regsMI_ILW(_VURegsNum *VUregsn) { _vuRegsILW(&VU1, VUregsn); } +void VU1regsMI_ISW(_VURegsNum *VUregsn) { _vuRegsISW(&VU1, VUregsn); } +void VU1regsMI_ILWR(_VURegsNum *VUregsn) { _vuRegsILWR(&VU1, VUregsn); } +void VU1regsMI_ISWR(_VURegsNum *VUregsn) { _vuRegsISWR(&VU1, VUregsn); } +void VU1regsMI_RINIT(_VURegsNum *VUregsn) { _vuRegsRINIT(&VU1, VUregsn); } +void VU1regsMI_RGET(_VURegsNum *VUregsn) { _vuRegsRGET(&VU1, VUregsn); } +void VU1regsMI_RNEXT(_VURegsNum *VUregsn) { _vuRegsRNEXT(&VU1, VUregsn); } +void VU1regsMI_RXOR(_VURegsNum *VUregsn) { _vuRegsRXOR(&VU1, VUregsn); } +void VU1regsMI_WAITQ(_VURegsNum *VUregsn) { _vuRegsWAITQ(&VU1, VUregsn); } +void VU1regsMI_FSAND(_VURegsNum *VUregsn) { _vuRegsFSAND(&VU1, VUregsn); } +void VU1regsMI_FSEQ(_VURegsNum *VUregsn) { _vuRegsFSEQ(&VU1, VUregsn); } +void VU1regsMI_FSOR(_VURegsNum *VUregsn) { _vuRegsFSOR(&VU1, VUregsn); } +void VU1regsMI_FSSET(_VURegsNum *VUregsn) { _vuRegsFSSET(&VU1, VUregsn); } +void VU1regsMI_FMAND(_VURegsNum *VUregsn) { _vuRegsFMAND(&VU1, VUregsn); } +void VU1regsMI_FMEQ(_VURegsNum *VUregsn) { _vuRegsFMEQ(&VU1, VUregsn); } +void VU1regsMI_FMOR(_VURegsNum *VUregsn) { _vuRegsFMOR(&VU1, VUregsn); } +void VU1regsMI_FCAND(_VURegsNum *VUregsn) { _vuRegsFCAND(&VU1, VUregsn); } +void VU1regsMI_FCEQ(_VURegsNum *VUregsn) { _vuRegsFCEQ(&VU1, VUregsn); } +void VU1regsMI_FCOR(_VURegsNum *VUregsn) { _vuRegsFCOR(&VU1, VUregsn); } +void VU1regsMI_FCSET(_VURegsNum *VUregsn) { _vuRegsFCSET(&VU1, VUregsn); } +void VU1regsMI_FCGET(_VURegsNum *VUregsn) { _vuRegsFCGET(&VU1, VUregsn); } +void VU1regsMI_IBEQ(_VURegsNum *VUregsn) { _vuRegsIBEQ(&VU1, VUregsn); } +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn) { _vuRegsIBGEZ(&VU1, VUregsn); } +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn) { _vuRegsIBGTZ(&VU1, VUregsn); } +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn) { _vuRegsIBLTZ(&VU1, VUregsn); } +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn) { _vuRegsIBLEZ(&VU1, VUregsn); } +void VU1regsMI_IBNE(_VURegsNum *VUregsn) { _vuRegsIBNE(&VU1, VUregsn); } +void VU1regsMI_B(_VURegsNum *VUregsn) { _vuRegsB(&VU1, VUregsn); } +void VU1regsMI_BAL(_VURegsNum *VUregsn) { _vuRegsBAL(&VU1, VUregsn); } +void VU1regsMI_JR(_VURegsNum *VUregsn) { _vuRegsJR(&VU1, VUregsn); } +void VU1regsMI_JALR(_VURegsNum *VUregsn) { _vuRegsJALR(&VU1, VUregsn); } +void VU1regsMI_MFP(_VURegsNum *VUregsn) { _vuRegsMFP(&VU1, VUregsn); } +void VU1regsMI_WAITP(_VURegsNum *VUregsn) { _vuRegsWAITP(&VU1, VUregsn); } +void VU1regsMI_ESADD(_VURegsNum *VUregsn) { _vuRegsESADD(&VU1, VUregsn); } +void VU1regsMI_ERSADD(_VURegsNum *VUregsn) { _vuRegsERSADD(&VU1, VUregsn); } +void VU1regsMI_ELENG(_VURegsNum *VUregsn) { _vuRegsELENG(&VU1, VUregsn); } +void VU1regsMI_ERLENG(_VURegsNum *VUregsn) { _vuRegsERLENG(&VU1, VUregsn); } +void VU1regsMI_EATANxy(_VURegsNum *VUregsn) { _vuRegsEATANxy(&VU1, VUregsn); } +void VU1regsMI_EATANxz(_VURegsNum *VUregsn) { _vuRegsEATANxz(&VU1, VUregsn); } +void VU1regsMI_ESUM(_VURegsNum *VUregsn) { _vuRegsESUM(&VU1, VUregsn); } +void VU1regsMI_ERCPR(_VURegsNum *VUregsn) { _vuRegsERCPR(&VU1, VUregsn); } +void VU1regsMI_ESQRT(_VURegsNum *VUregsn) { _vuRegsESQRT(&VU1, VUregsn); } +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn) { _vuRegsERSQRT(&VU1, VUregsn); } +void VU1regsMI_ESIN(_VURegsNum *VUregsn) { _vuRegsESIN(&VU1, VUregsn); } +void VU1regsMI_EATAN(_VURegsNum *VUregsn) { _vuRegsEATAN(&VU1, VUregsn); } +void VU1regsMI_EEXP(_VURegsNum *VUregsn) { _vuRegsEEXP(&VU1, VUregsn); } +void VU1regsMI_XITOP(_VURegsNum *VUregsn) { _vuRegsXITOP(&VU1, VUregsn); } +void VU1regsMI_XGKICK(_VURegsNum *VUregsn) { _vuRegsXGKICK(&VU1, VUregsn); } +void VU1regsMI_XTOP(_VURegsNum *VUregsn) { _vuRegsXTOP(&VU1, VUregsn); } diff --git a/pcsx2/VUflags.c b/pcsx2/VUflags.c new file mode 100644 index 0000000..5050f46 --- /dev/null +++ b/pcsx2/VUflags.c @@ -0,0 +1,95 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +/*****************************************/ +/* NEW FLAGS */ //By asadr. Thnkx F|RES :p +/*****************************************/ + + +__inline void vuUpdateDI(VURegs * VU) { +// u32 Flag_S = 0; +// u32 Flag_I = 0; +// u32 Flag_D = 0; +// +// /* +// FLAG D - I +// */ +// Flag_I = (VU->statusflag >> 4) & 0x1; +// Flag_D = (VU->statusflag >> 5) & 0x1; +// +// VU->statusflag|= (Flag_I | (VU0.VI[REG_STATUS_FLAG].US[0] >> 4)) << 10; +// VU->statusflag|= (Flag_D | (VU0.VI[REG_STATUS_FLAG].US[0] >> 5)) << 11; +} + +#define VU_MAC_UPDATE(name, shift) \ +u32 name(VURegs * VU, float f) { \ + u32 v = *(u32*)&f; \ + int exp = (v >> 23) & 0xff; \ + u32 s = v & 0x80000000; \ + \ + if (s) VU->macflag |= 0x0010<macflag &= ~(0x0010<macflag = (VU->macflag & ~(0x1100<macflag = (VU->macflag&~(0x1000<macflag = (VU->macflag&~(0x0100<macflag = (VU->macflag & ~(0x1101<macflag&= ~(0x1111<macflag & 0x000F) newflag = 0x1; + if (VU->macflag & 0x00F0) newflag |= 0x2; + if (VU->macflag & 0x0F00) newflag |= 0x4; + if (VU->macflag & 0xF000) newflag |= 0x8; + VU->statusflag = (VU->statusflag&0xc30)|newflag|((VU->statusflag&0xf)<<6); +} diff --git a/pcsx2/VUflags.h b/pcsx2/VUflags.h new file mode 100644 index 0000000..37338a5 --- /dev/null +++ b/pcsx2/VUflags.h @@ -0,0 +1,38 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUFLAGS_H__ +#define __VUFLAGS_H__ + +#include "VU.h" + +void vuUpdateDI(VURegs * VU); +u32 VU_MACx_UPDATE(VURegs * VU, float x); +u32 VU_MACy_UPDATE(VURegs * VU, float y); +u32 VU_MACz_UPDATE(VURegs * VU, float z); +u32 VU_MACw_UPDATE(VURegs * VU, float w); +void VU_MACx_CLEAR(VURegs * VU); +void VU_MACy_CLEAR(VURegs * VU); +void VU_MACz_CLEAR(VURegs * VU); +void VU_MACw_CLEAR(VURegs * VU); +void VU_STAT_UPDATE(VURegs * VU); + + +#endif + + diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h new file mode 100644 index 0000000..1f56703 --- /dev/null +++ b/pcsx2/VUmicro.h @@ -0,0 +1,1266 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VUMICRO_H__ +#define __VUMICRO_H__ + +#include "VU.h" + +void iDumpVU0Registers(); +void iDumpVU1Registers(); + +//both for VU0 VU1 micromode + +extern void (*VU0_LOWER_OPCODE[128])(); +extern void (*VU0_UPPER_OPCODE[64])(); + +extern void (*VU0_UPPER_FD_00_TABLE[32])(); +extern void (*VU0_UPPER_FD_01_TABLE[32])(); +extern void (*VU0_UPPER_FD_10_TABLE[32])(); +extern void (*VU0_UPPER_FD_11_TABLE[32])(); + +extern void (*VU0regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU0regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU0regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +extern void (*VU1_LOWER_OPCODE[128])(); +extern void (*VU1_UPPER_OPCODE[64])(); + +extern void (*VU1_UPPER_FD_00_TABLE[32])(); +extern void (*VU1_UPPER_FD_01_TABLE[32])(); +extern void (*VU1_UPPER_FD_10_TABLE[32])(); +extern void (*VU1_UPPER_FD_11_TABLE[32])(); + +extern void (*VU1regs_LOWER_OPCODE[128])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_OPCODE[64])(_VURegsNum *VUregsn); + +extern void (*VU1regs_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn); +extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn); + +// VU0 +int vu0Init(); +void vu0Reset(); +void vu0ResetRegs(); +void vu0Freeze(gzFile f, int Mode); +void vu0Shutdown(); +void vu0ExecMicro(u32 addr); +void vu0Exec(VURegs* VU); +void vu0Finish(); +void recResetVU0( void ); + +// VU1 +int vu1Init(); +void vu1Reset(); +void vu1ResetRegs(); +void recResetVU1( void ); +void vu1Freeze(gzFile f, int Mode); +void vu1Shutdown(); +void vu1ExecMicro(u32 addr); +void vu1Exec(VURegs* VU); + +void VU0_UPPER_FD_00(); +void VU0_UPPER_FD_01(); +void VU0_UPPER_FD_10(); +void VU0_UPPER_FD_11(); + +void VU0LowerOP(); +void VU0LowerOP_T3_00(); +void VU0LowerOP_T3_01(); +void VU0LowerOP_T3_10(); +void VU0LowerOP_T3_11(); + +void VU0unknown(); + +void VU1_UPPER_FD_00(); +void VU1_UPPER_FD_01(); +void VU1_UPPER_FD_10(); +void VU1_UPPER_FD_11(); + +void VU1LowerOP(); +void VU1LowerOP_T3_00(); +void VU1LowerOP_T3_01(); +void VU1LowerOP_T3_10(); +void VU1LowerOP_T3_11(); + +void VU1unknown(); + +void VU0regs_UPPER_FD_00(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_01(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_10(_VURegsNum *VUregsn); +void VU0regs_UPPER_FD_11(_VURegsNum *VUregsn); + +void VU0regsLowerOP(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_00(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_01(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_10(_VURegsNum *VUregsn); +void VU0regsLowerOP_T3_11(_VURegsNum *VUregsn); + +void VU0regsunknown(_VURegsNum *VUregsn); + +void VU1regs_UPPER_FD_00(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_01(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_10(_VURegsNum *VUregsn); +void VU1regs_UPPER_FD_11(_VURegsNum *VUregsn); + +void VU1regsLowerOP(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_00(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_01(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_10(_VURegsNum *VUregsn); +void VU1regsLowerOP_T3_11(_VURegsNum *VUregsn); + +void VU1regsunknown(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void VU0MI_ABS(); +void VU0MI_ADD(); +void VU0MI_ADDi(); +void VU0MI_ADDq(); +void VU0MI_ADDx(); +void VU0MI_ADDy(); +void VU0MI_ADDz(); +void VU0MI_ADDw(); +void VU0MI_ADDA(); +void VU0MI_ADDAi(); +void VU0MI_ADDAq(); +void VU0MI_ADDAx(); +void VU0MI_ADDAy(); +void VU0MI_ADDAz(); +void VU0MI_ADDAw(); +void VU0MI_SUB(); +void VU0MI_SUBi(); +void VU0MI_SUBq(); +void VU0MI_SUBx(); +void VU0MI_SUBy(); +void VU0MI_SUBz(); +void VU0MI_SUBw(); +void VU0MI_SUBA(); +void VU0MI_SUBAi(); +void VU0MI_SUBAq(); +void VU0MI_SUBAx(); +void VU0MI_SUBAy(); +void VU0MI_SUBAz(); +void VU0MI_SUBAw(); +void VU0MI_MUL(); +void VU0MI_MULi(); +void VU0MI_MULq(); +void VU0MI_MULx(); +void VU0MI_MULy(); +void VU0MI_MULz(); +void VU0MI_MULw(); +void VU0MI_MULA(); +void VU0MI_MULAi(); +void VU0MI_MULAq(); +void VU0MI_MULAx(); +void VU0MI_MULAy(); +void VU0MI_MULAz(); +void VU0MI_MULAw(); +void VU0MI_MADD(); +void VU0MI_MADDi(); +void VU0MI_MADDq(); +void VU0MI_MADDx(); +void VU0MI_MADDy(); +void VU0MI_MADDz(); +void VU0MI_MADDw(); +void VU0MI_MADDA(); +void VU0MI_MADDAi(); +void VU0MI_MADDAq(); +void VU0MI_MADDAx(); +void VU0MI_MADDAy(); +void VU0MI_MADDAz(); +void VU0MI_MADDAw(); +void VU0MI_MSUB(); +void VU0MI_MSUBi(); +void VU0MI_MSUBq(); +void VU0MI_MSUBx(); +void VU0MI_MSUBy(); +void VU0MI_MSUBz(); +void VU0MI_MSUBw(); +void VU0MI_MSUBA(); +void VU0MI_MSUBAi(); +void VU0MI_MSUBAq(); +void VU0MI_MSUBAx(); +void VU0MI_MSUBAy(); +void VU0MI_MSUBAz(); +void VU0MI_MSUBAw(); +void VU0MI_MAX(); +void VU0MI_MAXi(); +void VU0MI_MAXx(); +void VU0MI_MAXy(); +void VU0MI_MAXz(); +void VU0MI_MAXw(); +void VU0MI_MINI(); +void VU0MI_MINIi(); +void VU0MI_MINIx(); +void VU0MI_MINIy(); +void VU0MI_MINIz(); +void VU0MI_MINIw(); +void VU0MI_OPMULA(); +void VU0MI_OPMSUB(); +void VU0MI_NOP(); +void VU0MI_FTOI0(); +void VU0MI_FTOI4(); +void VU0MI_FTOI12(); +void VU0MI_FTOI15(); +void VU0MI_ITOF0(); +void VU0MI_ITOF4(); +void VU0MI_ITOF12(); +void VU0MI_ITOF15(); +void VU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0MI_DIV(); +void VU0MI_SQRT(); +void VU0MI_RSQRT(); +void VU0MI_IADD(); +void VU0MI_IADDI(); +void VU0MI_IADDIU(); +void VU0MI_IAND(); +void VU0MI_IOR(); +void VU0MI_ISUB(); +void VU0MI_ISUBIU(); +void VU0MI_MOVE(); +void VU0MI_MFIR(); +void VU0MI_MTIR(); +void VU0MI_MR32(); +void VU0MI_LQ(); +void VU0MI_LQD(); +void VU0MI_LQI(); +void VU0MI_SQ(); +void VU0MI_SQD(); +void VU0MI_SQI(); +void VU0MI_ILW(); +void VU0MI_ISW(); +void VU0MI_ILWR(); +void VU0MI_ISWR(); +void VU0MI_LOI(); +void VU0MI_RINIT(); +void VU0MI_RGET(); +void VU0MI_RNEXT(); +void VU0MI_RXOR(); +void VU0MI_WAITQ(); +void VU0MI_FSAND(); +void VU0MI_FSEQ(); +void VU0MI_FSOR(); +void VU0MI_FSSET(); +void VU0MI_FMAND(); +void VU0MI_FMEQ(); +void VU0MI_FMOR(); +void VU0MI_FCAND(); +void VU0MI_FCEQ(); +void VU0MI_FCOR(); +void VU0MI_FCSET(); +void VU0MI_FCGET(); +void VU0MI_IBEQ(); +void VU0MI_IBGEZ(); +void VU0MI_IBGTZ(); +void VU0MI_IBLEZ(); +void VU0MI_IBLTZ(); +void VU0MI_IBNE(); +void VU0MI_B(); +void VU0MI_BAL(); +void VU0MI_JR(); +void VU0MI_JALR(); +void VU0MI_MFP(); +void VU0MI_WAITP(); +void VU0MI_ESADD(); +void VU0MI_ERSADD(); +void VU0MI_ELENG(); +void VU0MI_ERLENG(); +void VU0MI_EATANxy(); +void VU0MI_EATANxz(); +void VU0MI_ESUM(); +void VU0MI_ERCPR(); +void VU0MI_ESQRT(); +void VU0MI_ERSQRT(); +void VU0MI_ESIN(); +void VU0MI_EATAN(); +void VU0MI_EEXP(); +void VU0MI_XGKICK(); +void VU0MI_XTOP(); +void VU0MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU0regsMI_ABS(_VURegsNum *VUregsn); +void VU0regsMI_ADD(_VURegsNum *VUregsn); +void VU0regsMI_ADDi(_VURegsNum *VUregsn); +void VU0regsMI_ADDq(_VURegsNum *VUregsn); +void VU0regsMI_ADDx(_VURegsNum *VUregsn); +void VU0regsMI_ADDy(_VURegsNum *VUregsn); +void VU0regsMI_ADDz(_VURegsNum *VUregsn); +void VU0regsMI_ADDw(_VURegsNum *VUregsn); +void VU0regsMI_ADDA(_VURegsNum *VUregsn); +void VU0regsMI_ADDAi(_VURegsNum *VUregsn); +void VU0regsMI_ADDAq(_VURegsNum *VUregsn); +void VU0regsMI_ADDAx(_VURegsNum *VUregsn); +void VU0regsMI_ADDAy(_VURegsNum *VUregsn); +void VU0regsMI_ADDAz(_VURegsNum *VUregsn); +void VU0regsMI_ADDAw(_VURegsNum *VUregsn); +void VU0regsMI_SUB(_VURegsNum *VUregsn); +void VU0regsMI_SUBi(_VURegsNum *VUregsn); +void VU0regsMI_SUBq(_VURegsNum *VUregsn); +void VU0regsMI_SUBx(_VURegsNum *VUregsn); +void VU0regsMI_SUBy(_VURegsNum *VUregsn); +void VU0regsMI_SUBz(_VURegsNum *VUregsn); +void VU0regsMI_SUBw(_VURegsNum *VUregsn); +void VU0regsMI_SUBA(_VURegsNum *VUregsn); +void VU0regsMI_SUBAi(_VURegsNum *VUregsn); +void VU0regsMI_SUBAq(_VURegsNum *VUregsn); +void VU0regsMI_SUBAx(_VURegsNum *VUregsn); +void VU0regsMI_SUBAy(_VURegsNum *VUregsn); +void VU0regsMI_SUBAz(_VURegsNum *VUregsn); +void VU0regsMI_SUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MUL(_VURegsNum *VUregsn); +void VU0regsMI_MULi(_VURegsNum *VUregsn); +void VU0regsMI_MULq(_VURegsNum *VUregsn); +void VU0regsMI_MULx(_VURegsNum *VUregsn); +void VU0regsMI_MULy(_VURegsNum *VUregsn); +void VU0regsMI_MULz(_VURegsNum *VUregsn); +void VU0regsMI_MULw(_VURegsNum *VUregsn); +void VU0regsMI_MULA(_VURegsNum *VUregsn); +void VU0regsMI_MULAi(_VURegsNum *VUregsn); +void VU0regsMI_MULAq(_VURegsNum *VUregsn); +void VU0regsMI_MULAx(_VURegsNum *VUregsn); +void VU0regsMI_MULAy(_VURegsNum *VUregsn); +void VU0regsMI_MULAz(_VURegsNum *VUregsn); +void VU0regsMI_MULAw(_VURegsNum *VUregsn); +void VU0regsMI_MADD(_VURegsNum *VUregsn); +void VU0regsMI_MADDi(_VURegsNum *VUregsn); +void VU0regsMI_MADDq(_VURegsNum *VUregsn); +void VU0regsMI_MADDx(_VURegsNum *VUregsn); +void VU0regsMI_MADDy(_VURegsNum *VUregsn); +void VU0regsMI_MADDz(_VURegsNum *VUregsn); +void VU0regsMI_MADDw(_VURegsNum *VUregsn); +void VU0regsMI_MADDA(_VURegsNum *VUregsn); +void VU0regsMI_MADDAi(_VURegsNum *VUregsn); +void VU0regsMI_MADDAq(_VURegsNum *VUregsn); +void VU0regsMI_MADDAx(_VURegsNum *VUregsn); +void VU0regsMI_MADDAy(_VURegsNum *VUregsn); +void VU0regsMI_MADDAz(_VURegsNum *VUregsn); +void VU0regsMI_MADDAw(_VURegsNum *VUregsn); +void VU0regsMI_MSUB(_VURegsNum *VUregsn); +void VU0regsMI_MSUBi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBw(_VURegsNum *VUregsn); +void VU0regsMI_MSUBA(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU0regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU0regsMI_MAX(_VURegsNum *VUregsn); +void VU0regsMI_MAXi(_VURegsNum *VUregsn); +void VU0regsMI_MAXx(_VURegsNum *VUregsn); +void VU0regsMI_MAXy(_VURegsNum *VUregsn); +void VU0regsMI_MAXz(_VURegsNum *VUregsn); +void VU0regsMI_MAXw(_VURegsNum *VUregsn); +void VU0regsMI_MINI(_VURegsNum *VUregsn); +void VU0regsMI_MINIi(_VURegsNum *VUregsn); +void VU0regsMI_MINIx(_VURegsNum *VUregsn); +void VU0regsMI_MINIy(_VURegsNum *VUregsn); +void VU0regsMI_MINIz(_VURegsNum *VUregsn); +void VU0regsMI_MINIw(_VURegsNum *VUregsn); +void VU0regsMI_OPMULA(_VURegsNum *VUregsn); +void VU0regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU0regsMI_NOP(_VURegsNum *VUregsn); +void VU0regsMI_FTOI0(_VURegsNum *VUregsn); +void VU0regsMI_FTOI4(_VURegsNum *VUregsn); +void VU0regsMI_FTOI12(_VURegsNum *VUregsn); +void VU0regsMI_FTOI15(_VURegsNum *VUregsn); +void VU0regsMI_ITOF0(_VURegsNum *VUregsn); +void VU0regsMI_ITOF4(_VURegsNum *VUregsn); +void VU0regsMI_ITOF12(_VURegsNum *VUregsn); +void VU0regsMI_ITOF15(_VURegsNum *VUregsn); +void VU0regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void VU0regsMI_DIV(_VURegsNum *VUregsn); +void VU0regsMI_SQRT(_VURegsNum *VUregsn); +void VU0regsMI_RSQRT(_VURegsNum *VUregsn); +void VU0regsMI_IADD(_VURegsNum *VUregsn); +void VU0regsMI_IADDI(_VURegsNum *VUregsn); +void VU0regsMI_IADDIU(_VURegsNum *VUregsn); +void VU0regsMI_IAND(_VURegsNum *VUregsn); +void VU0regsMI_IOR(_VURegsNum *VUregsn); +void VU0regsMI_ISUB(_VURegsNum *VUregsn); +void VU0regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU0regsMI_MOVE(_VURegsNum *VUregsn); +void VU0regsMI_MFIR(_VURegsNum *VUregsn); +void VU0regsMI_MTIR(_VURegsNum *VUregsn); +void VU0regsMI_MR32(_VURegsNum *VUregsn); +void VU0regsMI_LQ(_VURegsNum *VUregsn); +void VU0regsMI_LQD(_VURegsNum *VUregsn); +void VU0regsMI_LQI(_VURegsNum *VUregsn); +void VU0regsMI_SQ(_VURegsNum *VUregsn); +void VU0regsMI_SQD(_VURegsNum *VUregsn); +void VU0regsMI_SQI(_VURegsNum *VUregsn); +void VU0regsMI_ILW(_VURegsNum *VUregsn); +void VU0regsMI_ISW(_VURegsNum *VUregsn); +void VU0regsMI_ILWR(_VURegsNum *VUregsn); +void VU0regsMI_ISWR(_VURegsNum *VUregsn); +void VU0regsMI_LOI(_VURegsNum *VUregsn); +void VU0regsMI_RINIT(_VURegsNum *VUregsn); +void VU0regsMI_RGET(_VURegsNum *VUregsn); +void VU0regsMI_RNEXT(_VURegsNum *VUregsn); +void VU0regsMI_RXOR(_VURegsNum *VUregsn); +void VU0regsMI_WAITQ(_VURegsNum *VUregsn); +void VU0regsMI_FSAND(_VURegsNum *VUregsn); +void VU0regsMI_FSEQ(_VURegsNum *VUregsn); +void VU0regsMI_FSOR(_VURegsNum *VUregsn); +void VU0regsMI_FSSET(_VURegsNum *VUregsn); +void VU0regsMI_FMAND(_VURegsNum *VUregsn); +void VU0regsMI_FMEQ(_VURegsNum *VUregsn); +void VU0regsMI_FMOR(_VURegsNum *VUregsn); +void VU0regsMI_FCAND(_VURegsNum *VUregsn); +void VU0regsMI_FCEQ(_VURegsNum *VUregsn); +void VU0regsMI_FCOR(_VURegsNum *VUregsn); +void VU0regsMI_FCSET(_VURegsNum *VUregsn); +void VU0regsMI_FCGET(_VURegsNum *VUregsn); +void VU0regsMI_IBEQ(_VURegsNum *VUregsn); +void VU0regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU0regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU0regsMI_IBNE(_VURegsNum *VUregsn); +void VU0regsMI_B(_VURegsNum *VUregsn); +void VU0regsMI_BAL(_VURegsNum *VUregsn); +void VU0regsMI_JR(_VURegsNum *VUregsn); +void VU0regsMI_JALR(_VURegsNum *VUregsn); +void VU0regsMI_MFP(_VURegsNum *VUregsn); +void VU0regsMI_WAITP(_VURegsNum *VUregsn); +void VU0regsMI_ESADD(_VURegsNum *VUregsn); +void VU0regsMI_ERSADD(_VURegsNum *VUregsn); +void VU0regsMI_ELENG(_VURegsNum *VUregsn); +void VU0regsMI_ERLENG(_VURegsNum *VUregsn); +void VU0regsMI_EATANxy(_VURegsNum *VUregsn); +void VU0regsMI_EATANxz(_VURegsNum *VUregsn); +void VU0regsMI_ESUM(_VURegsNum *VUregsn); +void VU0regsMI_ERCPR(_VURegsNum *VUregsn); +void VU0regsMI_ESQRT(_VURegsNum *VUregsn); +void VU0regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU0regsMI_ESIN(_VURegsNum *VUregsn); +void VU0regsMI_EATAN(_VURegsNum *VUregsn); +void VU0regsMI_EEXP(_VURegsNum *VUregsn); +void VU0regsMI_XGKICK(_VURegsNum *VUregsn); +void VU0regsMI_XTOP(_VURegsNum *VUregsn); +void VU0regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1MI_ABS(); +void VU1MI_ADD(); +void VU1MI_ADDi(); +void VU1MI_ADDq(); +void VU1MI_ADDx(); +void VU1MI_ADDy(); +void VU1MI_ADDz(); +void VU1MI_ADDw(); +void VU1MI_ADDA(); +void VU1MI_ADDAi(); +void VU1MI_ADDAq(); +void VU1MI_ADDAx(); +void VU1MI_ADDAy(); +void VU1MI_ADDAz(); +void VU1MI_ADDAw(); +void VU1MI_SUB(); +void VU1MI_SUBi(); +void VU1MI_SUBq(); +void VU1MI_SUBx(); +void VU1MI_SUBy(); +void VU1MI_SUBz(); +void VU1MI_SUBw(); +void VU1MI_SUBA(); +void VU1MI_SUBAi(); +void VU1MI_SUBAq(); +void VU1MI_SUBAx(); +void VU1MI_SUBAy(); +void VU1MI_SUBAz(); +void VU1MI_SUBAw(); +void VU1MI_MUL(); +void VU1MI_MULi(); +void VU1MI_MULq(); +void VU1MI_MULx(); +void VU1MI_MULy(); +void VU1MI_MULz(); +void VU1MI_MULw(); +void VU1MI_MULA(); +void VU1MI_MULAi(); +void VU1MI_MULAq(); +void VU1MI_MULAx(); +void VU1MI_MULAy(); +void VU1MI_MULAz(); +void VU1MI_MULAw(); +void VU1MI_MADD(); +void VU1MI_MADDi(); +void VU1MI_MADDq(); +void VU1MI_MADDx(); +void VU1MI_MADDy(); +void VU1MI_MADDz(); +void VU1MI_MADDw(); +void VU1MI_MADDA(); +void VU1MI_MADDAi(); +void VU1MI_MADDAq(); +void VU1MI_MADDAx(); +void VU1MI_MADDAy(); +void VU1MI_MADDAz(); +void VU1MI_MADDAw(); +void VU1MI_MSUB(); +void VU1MI_MSUBi(); +void VU1MI_MSUBq(); +void VU1MI_MSUBx(); +void VU1MI_MSUBy(); +void VU1MI_MSUBz(); +void VU1MI_MSUBw(); +void VU1MI_MSUBA(); +void VU1MI_MSUBAi(); +void VU1MI_MSUBAq(); +void VU1MI_MSUBAx(); +void VU1MI_MSUBAy(); +void VU1MI_MSUBAz(); +void VU1MI_MSUBAw(); +void VU1MI_MAX(); +void VU1MI_MAXi(); +void VU1MI_MAXx(); +void VU1MI_MAXy(); +void VU1MI_MAXz(); +void VU1MI_MAXw(); +void VU1MI_MINI(); +void VU1MI_MINIi(); +void VU1MI_MINIx(); +void VU1MI_MINIy(); +void VU1MI_MINIz(); +void VU1MI_MINIw(); +void VU1MI_OPMULA(); +void VU1MI_OPMSUB(); +void VU1MI_NOP(); +void VU1MI_FTOI0(); +void VU1MI_FTOI4(); +void VU1MI_FTOI12(); +void VU1MI_FTOI15(); +void VU1MI_ITOF0(); +void VU1MI_ITOF4(); +void VU1MI_ITOF12(); +void VU1MI_ITOF15(); +void VU1MI_CLIP(); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1MI_DIV(); +void VU1MI_SQRT(); +void VU1MI_RSQRT(); +void VU1MI_IADD(); +void VU1MI_IADDI(); +void VU1MI_IADDIU(); +void VU1MI_IAND(); +void VU1MI_IOR(); +void VU1MI_ISUB(); +void VU1MI_ISUBIU(); +void VU1MI_MOVE(); +void VU1MI_MFIR(); +void VU1MI_MTIR(); +void VU1MI_MR32(); +void VU1MI_LQ(); +void VU1MI_LQD(); +void VU1MI_LQI(); +void VU1MI_SQ(); +void VU1MI_SQD(); +void VU1MI_SQI(); +void VU1MI_ILW(); +void VU1MI_ISW(); +void VU1MI_ILWR(); +void VU1MI_ISWR(); +void VU1MI_LOI(); +void VU1MI_RINIT(); +void VU1MI_RGET(); +void VU1MI_RNEXT(); +void VU1MI_RXOR(); +void VU1MI_WAITQ(); +void VU1MI_FSAND(); +void VU1MI_FSEQ(); +void VU1MI_FSOR(); +void VU1MI_FSSET(); +void VU1MI_FMAND(); +void VU1MI_FMEQ(); +void VU1MI_FMOR(); +void VU1MI_FCAND(); +void VU1MI_FCEQ(); +void VU1MI_FCOR(); +void VU1MI_FCSET(); +void VU1MI_FCGET(); +void VU1MI_IBEQ(); +void VU1MI_IBGEZ(); +void VU1MI_IBGTZ(); +void VU1MI_IBLTZ(); +void VU1MI_IBLEZ(); +void VU1MI_IBNE(); +void VU1MI_B(); +void VU1MI_BAL(); +void VU1MI_JR(); +void VU1MI_JALR(); +void VU1MI_MFP(); +void VU1MI_WAITP(); +void VU1MI_ESADD(); +void VU1MI_ERSADD(); +void VU1MI_ELENG(); +void VU1MI_ERLENG(); +void VU1MI_EATANxy(); +void VU1MI_EATANxz(); +void VU1MI_ESUM(); +void VU1MI_ERCPR(); +void VU1MI_ESQRT(); +void VU1MI_ERSQRT(); +void VU1MI_ESIN(); +void VU1MI_EATAN(); +void VU1MI_EEXP(); +void VU1MI_XGKICK(); +void VU1MI_XTOP(); +void VU1MI_XITOP(); + +/***************************************** + VU1 Micromode Upper instructions +*****************************************/ + +void VU1regsMI_ABS(_VURegsNum *VUregsn); +void VU1regsMI_ADD(_VURegsNum *VUregsn); +void VU1regsMI_ADDi(_VURegsNum *VUregsn); +void VU1regsMI_ADDq(_VURegsNum *VUregsn); +void VU1regsMI_ADDx(_VURegsNum *VUregsn); +void VU1regsMI_ADDy(_VURegsNum *VUregsn); +void VU1regsMI_ADDz(_VURegsNum *VUregsn); +void VU1regsMI_ADDw(_VURegsNum *VUregsn); +void VU1regsMI_ADDA(_VURegsNum *VUregsn); +void VU1regsMI_ADDAi(_VURegsNum *VUregsn); +void VU1regsMI_ADDAq(_VURegsNum *VUregsn); +void VU1regsMI_ADDAx(_VURegsNum *VUregsn); +void VU1regsMI_ADDAy(_VURegsNum *VUregsn); +void VU1regsMI_ADDAz(_VURegsNum *VUregsn); +void VU1regsMI_ADDAw(_VURegsNum *VUregsn); +void VU1regsMI_SUB(_VURegsNum *VUregsn); +void VU1regsMI_SUBi(_VURegsNum *VUregsn); +void VU1regsMI_SUBq(_VURegsNum *VUregsn); +void VU1regsMI_SUBx(_VURegsNum *VUregsn); +void VU1regsMI_SUBy(_VURegsNum *VUregsn); +void VU1regsMI_SUBz(_VURegsNum *VUregsn); +void VU1regsMI_SUBw(_VURegsNum *VUregsn); +void VU1regsMI_SUBA(_VURegsNum *VUregsn); +void VU1regsMI_SUBAi(_VURegsNum *VUregsn); +void VU1regsMI_SUBAq(_VURegsNum *VUregsn); +void VU1regsMI_SUBAx(_VURegsNum *VUregsn); +void VU1regsMI_SUBAy(_VURegsNum *VUregsn); +void VU1regsMI_SUBAz(_VURegsNum *VUregsn); +void VU1regsMI_SUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MUL(_VURegsNum *VUregsn); +void VU1regsMI_MULi(_VURegsNum *VUregsn); +void VU1regsMI_MULq(_VURegsNum *VUregsn); +void VU1regsMI_MULx(_VURegsNum *VUregsn); +void VU1regsMI_MULy(_VURegsNum *VUregsn); +void VU1regsMI_MULz(_VURegsNum *VUregsn); +void VU1regsMI_MULw(_VURegsNum *VUregsn); +void VU1regsMI_MULA(_VURegsNum *VUregsn); +void VU1regsMI_MULAi(_VURegsNum *VUregsn); +void VU1regsMI_MULAq(_VURegsNum *VUregsn); +void VU1regsMI_MULAx(_VURegsNum *VUregsn); +void VU1regsMI_MULAy(_VURegsNum *VUregsn); +void VU1regsMI_MULAz(_VURegsNum *VUregsn); +void VU1regsMI_MULAw(_VURegsNum *VUregsn); +void VU1regsMI_MADD(_VURegsNum *VUregsn); +void VU1regsMI_MADDi(_VURegsNum *VUregsn); +void VU1regsMI_MADDq(_VURegsNum *VUregsn); +void VU1regsMI_MADDx(_VURegsNum *VUregsn); +void VU1regsMI_MADDy(_VURegsNum *VUregsn); +void VU1regsMI_MADDz(_VURegsNum *VUregsn); +void VU1regsMI_MADDw(_VURegsNum *VUregsn); +void VU1regsMI_MADDA(_VURegsNum *VUregsn); +void VU1regsMI_MADDAi(_VURegsNum *VUregsn); +void VU1regsMI_MADDAq(_VURegsNum *VUregsn); +void VU1regsMI_MADDAx(_VURegsNum *VUregsn); +void VU1regsMI_MADDAy(_VURegsNum *VUregsn); +void VU1regsMI_MADDAz(_VURegsNum *VUregsn); +void VU1regsMI_MADDAw(_VURegsNum *VUregsn); +void VU1regsMI_MSUB(_VURegsNum *VUregsn); +void VU1regsMI_MSUBi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBw(_VURegsNum *VUregsn); +void VU1regsMI_MSUBA(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAi(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAq(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAx(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAy(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAz(_VURegsNum *VUregsn); +void VU1regsMI_MSUBAw(_VURegsNum *VUregsn); +void VU1regsMI_MAX(_VURegsNum *VUregsn); +void VU1regsMI_MAXi(_VURegsNum *VUregsn); +void VU1regsMI_MAXx(_VURegsNum *VUregsn); +void VU1regsMI_MAXy(_VURegsNum *VUregsn); +void VU1regsMI_MAXz(_VURegsNum *VUregsn); +void VU1regsMI_MAXw(_VURegsNum *VUregsn); +void VU1regsMI_MINI(_VURegsNum *VUregsn); +void VU1regsMI_MINIi(_VURegsNum *VUregsn); +void VU1regsMI_MINIx(_VURegsNum *VUregsn); +void VU1regsMI_MINIy(_VURegsNum *VUregsn); +void VU1regsMI_MINIz(_VURegsNum *VUregsn); +void VU1regsMI_MINIw(_VURegsNum *VUregsn); +void VU1regsMI_OPMULA(_VURegsNum *VUregsn); +void VU1regsMI_OPMSUB(_VURegsNum *VUregsn); +void VU1regsMI_NOP(_VURegsNum *VUregsn); +void VU1regsMI_FTOI0(_VURegsNum *VUregsn); +void VU1regsMI_FTOI4(_VURegsNum *VUregsn); +void VU1regsMI_FTOI12(_VURegsNum *VUregsn); +void VU1regsMI_FTOI15(_VURegsNum *VUregsn); +void VU1regsMI_ITOF0(_VURegsNum *VUregsn); +void VU1regsMI_ITOF4(_VURegsNum *VUregsn); +void VU1regsMI_ITOF12(_VURegsNum *VUregsn); +void VU1regsMI_ITOF15(_VURegsNum *VUregsn); +void VU1regsMI_CLIP(_VURegsNum *VUregsn); + +/***************************************** + VU1 Micromode Lower instructions +*****************************************/ + +void VU1regsMI_DIV(_VURegsNum *VUregsn); +void VU1regsMI_SQRT(_VURegsNum *VUregsn); +void VU1regsMI_RSQRT(_VURegsNum *VUregsn); +void VU1regsMI_IADD(_VURegsNum *VUregsn); +void VU1regsMI_IADDI(_VURegsNum *VUregsn); +void VU1regsMI_IADDIU(_VURegsNum *VUregsn); +void VU1regsMI_IAND(_VURegsNum *VUregsn); +void VU1regsMI_IOR(_VURegsNum *VUregsn); +void VU1regsMI_ISUB(_VURegsNum *VUregsn); +void VU1regsMI_ISUBIU(_VURegsNum *VUregsn); +void VU1regsMI_MOVE(_VURegsNum *VUregsn); +void VU1regsMI_MFIR(_VURegsNum *VUregsn); +void VU1regsMI_MTIR(_VURegsNum *VUregsn); +void VU1regsMI_MR32(_VURegsNum *VUregsn); +void VU1regsMI_LQ(_VURegsNum *VUregsn); +void VU1regsMI_LQD(_VURegsNum *VUregsn); +void VU1regsMI_LQI(_VURegsNum *VUregsn); +void VU1regsMI_SQ(_VURegsNum *VUregsn); +void VU1regsMI_SQD(_VURegsNum *VUregsn); +void VU1regsMI_SQI(_VURegsNum *VUregsn); +void VU1regsMI_ILW(_VURegsNum *VUregsn); +void VU1regsMI_ISW(_VURegsNum *VUregsn); +void VU1regsMI_ILWR(_VURegsNum *VUregsn); +void VU1regsMI_ISWR(_VURegsNum *VUregsn); +void VU1regsMI_LOI(_VURegsNum *VUregsn); +void VU1regsMI_RINIT(_VURegsNum *VUregsn); +void VU1regsMI_RGET(_VURegsNum *VUregsn); +void VU1regsMI_RNEXT(_VURegsNum *VUregsn); +void VU1regsMI_RXOR(_VURegsNum *VUregsn); +void VU1regsMI_WAITQ(_VURegsNum *VUregsn); +void VU1regsMI_FSAND(_VURegsNum *VUregsn); +void VU1regsMI_FSEQ(_VURegsNum *VUregsn); +void VU1regsMI_FSOR(_VURegsNum *VUregsn); +void VU1regsMI_FSSET(_VURegsNum *VUregsn); +void VU1regsMI_FMAND(_VURegsNum *VUregsn); +void VU1regsMI_FMEQ(_VURegsNum *VUregsn); +void VU1regsMI_FMOR(_VURegsNum *VUregsn); +void VU1regsMI_FCAND(_VURegsNum *VUregsn); +void VU1regsMI_FCEQ(_VURegsNum *VUregsn); +void VU1regsMI_FCOR(_VURegsNum *VUregsn); +void VU1regsMI_FCSET(_VURegsNum *VUregsn); +void VU1regsMI_FCGET(_VURegsNum *VUregsn); +void VU1regsMI_IBEQ(_VURegsNum *VUregsn); +void VU1regsMI_IBGEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBGTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLTZ(_VURegsNum *VUregsn); +void VU1regsMI_IBLEZ(_VURegsNum *VUregsn); +void VU1regsMI_IBNE(_VURegsNum *VUregsn); +void VU1regsMI_B(_VURegsNum *VUregsn); +void VU1regsMI_BAL(_VURegsNum *VUregsn); +void VU1regsMI_JR(_VURegsNum *VUregsn); +void VU1regsMI_JALR(_VURegsNum *VUregsn); +void VU1regsMI_MFP(_VURegsNum *VUregsn); +void VU1regsMI_WAITP(_VURegsNum *VUregsn); +void VU1regsMI_ESADD(_VURegsNum *VUregsn); +void VU1regsMI_ERSADD(_VURegsNum *VUregsn); +void VU1regsMI_ELENG(_VURegsNum *VUregsn); +void VU1regsMI_ERLENG(_VURegsNum *VUregsn); +void VU1regsMI_EATANxy(_VURegsNum *VUregsn); +void VU1regsMI_EATANxz(_VURegsNum *VUregsn); +void VU1regsMI_ESUM(_VURegsNum *VUregsn); +void VU1regsMI_ERCPR(_VURegsNum *VUregsn); +void VU1regsMI_ESQRT(_VURegsNum *VUregsn); +void VU1regsMI_ERSQRT(_VURegsNum *VUregsn); +void VU1regsMI_ESIN(_VURegsNum *VUregsn); +void VU1regsMI_EATAN(_VURegsNum *VUregsn); +void VU1regsMI_EEXP(_VURegsNum *VUregsn); +void VU1regsMI_XGKICK(_VURegsNum *VUregsn); +void VU1regsMI_XTOP(_VURegsNum *VUregsn); +void VU1regsMI_XITOP(_VURegsNum *VUregsn); + +/***************************************** + VU Micromode Tables/Opcodes defs macros +*****************************************/ + + +#define _vuTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])() = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])() = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])() = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])() = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])() = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])() = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_ADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])() = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00() { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](); \ +} \ + \ + void PREFIX##_UPPER_FD_01() { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_10() { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##_UPPER_FD_11() { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP() { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](); \ +} \ + \ + void PREFIX##LowerOP_T3_00() { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_01() { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_10() { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](); \ +} \ + \ + void PREFIX##LowerOP_T3_11() { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](); \ +} + +#define _vuRegsTables(VU, PREFIX) \ + \ +void (*PREFIX##_LOWER_OPCODE[128])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_LQ , PREFIX##MI_SQ , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ILW , PREFIX##MI_ISW , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADDIU, PREFIX##MI_ISUBIU, PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_FCEQ , PREFIX##MI_FCSET , PREFIX##MI_FCAND, PREFIX##MI_FCOR, /* 0x10 */ \ + PREFIX##MI_FSEQ , PREFIX##MI_FSSET , PREFIX##MI_FSAND, PREFIX##MI_FSOR, \ + PREFIX##MI_FMEQ , PREFIX##unknown , PREFIX##MI_FMAND, PREFIX##MI_FMOR, \ + PREFIX##MI_FCGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_B , PREFIX##MI_BAL , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##MI_JR , PREFIX##MI_JALR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBEQ , PREFIX##MI_IBNE , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IBLTZ , PREFIX##MI_IBGTZ , PREFIX##MI_IBLEZ, PREFIX##MI_IBGEZ, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x40*/ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x50 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x60 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x70 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_00_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MOVE , PREFIX##MI_LQI , PREFIX##MI_DIV , PREFIX##MI_MTIR, \ + PREFIX##MI_RNEXT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_MFP , PREFIX##MI_XTOP , PREFIX##MI_XGKICK, \ + PREFIX##MI_ESADD , PREFIX##MI_EATANxy, PREFIX##MI_ESQRT, PREFIX##MI_ESIN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_01_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_MR32 , PREFIX##MI_SQI , PREFIX##MI_SQRT , PREFIX##MI_MFIR, \ + PREFIX##MI_RGET , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##MI_XITOP, PREFIX##unknown, \ + PREFIX##MI_ERSADD, PREFIX##MI_EATANxz, PREFIX##MI_ERSQRT, PREFIX##MI_EATAN, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_10_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_LQD , PREFIX##MI_RSQRT, PREFIX##MI_ILWR, \ + PREFIX##MI_RINIT , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ELENG , PREFIX##MI_ESUM , PREFIX##MI_ERCPR, PREFIX##MI_EEXP, \ +}; \ + \ + void (*PREFIX##LowerOP_T3_11_OPCODE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##MI_SQD , PREFIX##MI_WAITQ, PREFIX##MI_ISWR, \ + PREFIX##MI_RXOR , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_ERLENG, PREFIX##unknown , PREFIX##MI_WAITP, PREFIX##unknown, \ +}; \ + \ + void (*PREFIX##LowerOP_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x10 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x20 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##MI_IADD , PREFIX##MI_ISUB , PREFIX##MI_IADDI, PREFIX##unknown, /* 0x30 */ \ + PREFIX##MI_IAND , PREFIX##MI_IOR , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##LowerOP_T3_00, PREFIX##LowerOP_T3_01, PREFIX##LowerOP_T3_10, PREFIX##LowerOP_T3_11, \ +}; \ + \ + void (*PREFIX##_UPPER_OPCODE[64])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDx , PREFIX##MI_ADDy , PREFIX##MI_ADDz , PREFIX##MI_ADDw, \ + PREFIX##MI_SUBx , PREFIX##MI_SUBy , PREFIX##MI_SUBz , PREFIX##MI_SUBw, \ + PREFIX##MI_MADDx , PREFIX##MI_MADDy , PREFIX##MI_MADDz , PREFIX##MI_MADDw, \ + PREFIX##MI_MSUBx , PREFIX##MI_MSUBy , PREFIX##MI_MSUBz , PREFIX##MI_MSUBw, \ + PREFIX##MI_MAXx , PREFIX##MI_MAXy , PREFIX##MI_MAXz , PREFIX##MI_MAXw, /* 0x10 */ \ + PREFIX##MI_MINIx , PREFIX##MI_MINIy , PREFIX##MI_MINIz , PREFIX##MI_MINIw, \ + PREFIX##MI_MULx , PREFIX##MI_MULy , PREFIX##MI_MULz , PREFIX##MI_MULw, \ + PREFIX##MI_MULq , PREFIX##MI_MAXi , PREFIX##MI_MULi , PREFIX##MI_MINIi, \ + PREFIX##MI_ADDq , PREFIX##MI_MADDq , PREFIX##MI_ADDi , PREFIX##MI_MADDi, /* 0x20 */ \ + PREFIX##MI_SUBq , PREFIX##MI_MSUBq , PREFIX##MI_SUBi , PREFIX##MI_MSUBi, \ + PREFIX##MI_ADD , PREFIX##MI_MADD , PREFIX##MI_MUL , PREFIX##MI_MAX, \ + PREFIX##MI_SUB , PREFIX##MI_MSUB , PREFIX##MI_OPMSUB, PREFIX##MI_MINI, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, /* 0x30 */ \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown, \ + PREFIX##_UPPER_FD_00, PREFIX##_UPPER_FD_01, PREFIX##_UPPER_FD_10, PREFIX##_UPPER_FD_11, \ +}; \ + \ + void (*PREFIX##_UPPER_FD_00_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAx, PREFIX##MI_SUBAx , PREFIX##MI_MADDAx, PREFIX##MI_MSUBAx, \ + PREFIX##MI_ITOF0, PREFIX##MI_FTOI0, PREFIX##MI_MULAx , PREFIX##MI_MULAq , \ + PREFIX##MI_ADDAq, PREFIX##MI_SUBAq, PREFIX##MI_ADDA , PREFIX##MI_SUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_01_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAy , PREFIX##MI_SUBAy , PREFIX##MI_MADDAy, PREFIX##MI_MSUBAy, \ + PREFIX##MI_ITOF4 , PREFIX##MI_FTOI4 , PREFIX##MI_MULAy , PREFIX##MI_ABS , \ + PREFIX##MI_MADDAq, PREFIX##MI_MSUBAq, PREFIX##MI_MADDA , PREFIX##MI_MSUBA , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_10_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAz , PREFIX##MI_SUBAz , PREFIX##MI_MADDAz, PREFIX##MI_MSUBAz, \ + PREFIX##MI_ITOF12, PREFIX##MI_FTOI12, PREFIX##MI_MULAz , PREFIX##MI_MULAi , \ + PREFIX##MI_ADDAi, PREFIX##MI_SUBAi , PREFIX##MI_MULA , PREFIX##MI_OPMULA, \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + void (*PREFIX##_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn) = { \ + PREFIX##MI_ADDAw , PREFIX##MI_SUBAw , PREFIX##MI_MADDAw, PREFIX##MI_MSUBAw, \ + PREFIX##MI_ITOF15, PREFIX##MI_FTOI15, PREFIX##MI_MULAw , PREFIX##MI_CLIP , \ + PREFIX##MI_MADDAi, PREFIX##MI_MSUBAi, PREFIX##unknown , PREFIX##MI_NOP , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ + PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , PREFIX##unknown , \ +}; \ + \ + \ + \ + void PREFIX##_UPPER_FD_00(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_00_TABLE[(VU.code >> 6) & 0x1f ](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_01(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_01_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_10(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_10_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##_UPPER_FD_11(_VURegsNum *VUregsn) { \ + PREFIX##_UPPER_FD_11_TABLE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_OPCODE[VU.code & 0x3f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_00(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_00_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_01(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_01_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_10(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_10_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} \ + \ + void PREFIX##LowerOP_T3_11(_VURegsNum *VUregsn) { \ + PREFIX##LowerOP_T3_11_OPCODE[(VU.code >> 6) & 0x1f](VUregsn); \ +} + + +#ifdef VUM_LOG + +#define IdebugUPPER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroUF(VU.code, VU.VI[REG_TPC].UL)); } +#define IdebugLOWER(VU) \ + if (Log) { VUM_LOG("%s\n", dis##VU##MicroLF(VU.code, VU.VI[REG_TPC].UL)); } + +#else + +#define IdebugUPPER(VU) +#define IdebugLOWER(VU) + +#endif + +#ifdef VUM_LOG +#define _vuExecMicroDebug(VU) \ + VUM_LOG("_vuExecMicro: %8.8x\n", VU.VI[REG_TPC].UL); +#else +#define _vuExecMicroDebug(VU) +#endif + +#include "VUops.h" + +#endif + diff --git a/pcsx2/VUops.c b/pcsx2/VUops.c new file mode 100644 index 0000000..72f0645 --- /dev/null +++ b/pcsx2/VUops.c @@ -0,0 +1,2955 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "VUops.h" +#include "GS.h" + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU->code>>24) & 0x1) +#define _Y ((VU->code>>23) & 0x1) +#define _Z ((VU->code>>22) & 0x1) +#define _W ((VU->code>>21) & 0x1) + +#define _XYZW ((VU->code>>21) & 0xF) + +#define _Fsf_ ((VU->code >> 21) & 0x03) +#define _Ftf_ ((VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + + +VECTOR RDzero; + +void _vuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } +} + +void _vuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } +#endif + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } +} + +void _vuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing EFU pipe\n"); } +#endif + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } +} + +// called at end of program +void _vuFlushAll(VURegs* VU) +{ + int nRepeat = 1, i; + + do { + nRepeat = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + nRepeat = 1; + + if ((VU->cycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FMAC pipe[%d] (macflag=%x)\n", i, VU->fmac[i].macflag); } +#endif + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; + } + } + + if (VU->fdiv.enable ) { + + nRepeat = 1; + + if ((VU->cycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { + #ifdef VUM_LOG + if (Log) { VUM_LOG("flushing FDIV pipe\n"); } + #endif + nRepeat = 1; + VU->fdiv.enable = 0; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; + } + } + + if (VU->efu.enable) { + + nRepeat = 1; + + if ((VU->cycle - VU->efu.sCycle) >= VU->efu.Cycle) { + #ifdef VUM_LOG + // if (Log) { VUM_LOG("flushing EFU pipe\n"); } + #endif + nRepeat = 1; + VU->efu.enable = 0; + VU->VI[REG_P].UL = VU->efu.reg.UL; + } + } + + VU->cycle++; + + } while(nRepeat); +} + +void _vuTestPipes(VURegs * VU) { + _vuFMACflush(VU); + _vuFDIVflush(VU); + _vuEFUflush(VU); +} + +void _vuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + VU->fmac[i].xyzw & xyzw) break; + } + + if (i == 8) return; + + cycle = VU->fmac[i].Cycle - (VU->cycle - VU->fmac[i].sCycle) + 1; // add 1 delay! (fixes segaclassics bad geom) + VU->fmac[i].enable = 0; + VU->VI[REG_MAC_FLAG].UL = VU->fmac[i].macflag; + VU->VI[REG_STATUS_FLAG].UL = VU->fmac[i].statusflag; + VU->VI[REG_CLIP_FLAG].UL = VU->fmac[i].clipflag; +#ifdef VUM_LOG + if (Log) { VUM_LOG("FMAC[%d] stall %d\n", i, cycle); } +#endif + VU->cycle+= cycle; + _vuTestPipes(VU); +} + +void _vuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { +// SysPrintf("*PCSX2*: error , out of fmacs %d\n", VU->cycle); + } + +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FMAC pipe[%d]; xyzw=%x\n", i, xyzw); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = VU->cycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].reg = reg; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].macflag = VU->macflag; + VU->fmac[i].statusflag = VU->statusflag; + VU->fmac[i].clipflag = VU->clipflag; +} + +void _vuFDIVAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG + if (Log) { VUM_LOG("adding FDIV pipe\n"); } +#endif + VU->fdiv.enable = 1; + VU->fdiv.sCycle = VU->cycle; + VU->fdiv.Cycle = cycles; + VU->fdiv.reg.F = VU->q.F; + VU->fdiv.statusflag = VU->statusflag; +} + +void _vuEFUAdd(VURegs * VU, int cycles) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding EFU pipe\n"); } +#endif + VU->efu.enable = 1; + VU->efu.sCycle = VU->cycle; + VU->efu.Cycle = cycles; + VU->efu.reg.F = VU->p.F; +} + +void _vuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (VU->cycle - VU->fdiv.sCycle); +#ifdef VUM_LOG + if (Log) { VUM_LOG("waiting FDIV pipe %d\n", cycle); } +#endif + VU->fdiv.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_Q].UL = VU->fdiv.reg.UL; + VU->VI[REG_STATUS_FLAG].UL = VU->fdiv.statusflag; +} + +void _vuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (VU->cycle - VU->efu.sCycle); +#ifdef VUM_LOG +// if (Log) { VUM_LOG("waiting EFU pipe %d\n", cycle); } +#endif + VU->efu.enable = 0; + VU->cycle+= cycle; + VU->VI[REG_P].UL = VU->efu.reg.UL; +} + +void _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFread0) { + _vuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _vuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } +} + +void _vuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _vuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { + _vuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _vuFMACAdd(VU, 0, 0); + } +} + +void _vuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushFDIV(VU); +} + +void _vuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_Q)) { + _vuFDIVAdd(VU, VUregsn->cycles); + } +} + + +void _vuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _vuFlushEFU(VU); +} + +void _vuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VIwrite & (1 << REG_P)) { + _vuEFUAdd(VU, VUregsn->cycles); + } +} + +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + } +} + +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuTestEFUStalls(VU, VUregsn); break; + } +} + +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + } +} + +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _vuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _vuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _vuAddEFUStalls(VU, VUregsn); break; + } +} + + +/******************************/ +/* VU Upper instructions */ +/******************************/ +static u32 d; + +float vuDouble(u32 f) +{ + switch(f & 0x7f800000){ + case 0x0: + f &= 0x80000000; + return *(float*)&f; + break; + case 0x7f800000: + d = (f & 0x80000000)|0x7f7fffff; + return *(float*)&d; + break; + default: + return *(float*)&f; + break; + } +} + +void _vuABS(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X){ VU->VF[_Ft_].f.x = fpufabsf(vuDouble(VU->VF[_Fs_].i.x)); } + if (_Y){ VU->VF[_Ft_].f.y = fpufabsf(vuDouble(VU->VF[_Fs_].i.y)); } + if (_Z){ VU->VF[_Ft_].f.z = fpufabsf(vuDouble(VU->VF[_Fs_].i.z)); } + if (_W){ VU->VF[_Ft_].f.w = fpufabsf(vuDouble(VU->VF[_Fs_].i.w)); } +}/*Reworked from define to function. asadr*/ + + +void _vuADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_I].UL));} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_I].UL));} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_I].UL));} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_I].UL));} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + fty);} else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + fty);} else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + fty);} else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + fty);} else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ti); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ti); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ti); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ti); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAq(VURegs * VU) { + float tf = vuDouble(VU->VI[REG_Q].UL); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tf); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tf); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tf); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tf); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + +void _vuADDAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) + tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) + tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) + tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) + tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*Reworked from define to function. asadr*/ + + +void _vuSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + + +void _vuSUBA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tx); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tx); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tx); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - ty); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - ty); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - ty); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - ty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tz); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tz); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tz); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) - tw); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) - tw); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) - tw); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) - tw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}//updated 10/05/03 shadow + +void _vuMUL(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftx); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftx); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftx); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftx); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * fty); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * fty); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * fty); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * fty); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftz); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftz); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftz); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftz); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X){ dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * ftw); } else VU_MACx_CLEAR(VU); + if (_Y){ dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * ftw); } else VU_MACy_CLEAR(VU); + if (_Z){ dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * ftw); } else VU_MACz_CLEAR(VU); + if (_W){ dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * ftw); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + + +void _vuMULA(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave I reg in ti. asadr */ +void _vuMULAi(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave Q reg in ti. asadr */ +void _vuMULAq(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +/* No need to presave X reg in ti. asadr */ +void _vuMULAx(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAy(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAz(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMULAw(VURegs * VU) { + if (_X){ VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACx_CLEAR(VU); + if (_Y){ VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACy_CLEAR(VU); + if (_Z){ VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACz_CLEAR(VU); + if (_W){ VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w)); } else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 8/05/03 shadow */ + +void _vuMADD(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + + +void _vuMADDi(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +/* No need to presave . asadr */ +void _vuMADDq(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftx)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftx)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftx)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * fty)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * fty)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * fty)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * fty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftz)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftz)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftz)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * ftw)); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * ftw)); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * ftw)); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * ftw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 10/05/03 shadow */ + +void _vuMADDA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + (vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * ti)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * ti)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * ti)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * ti)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 10/05/03 shadow*/ + +void _vuMADDAq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * tq)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * tq)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * tq)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * tq)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 10/05/03 shadow*/ + +void _vuMADDAx(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAy(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAz(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMADDAw(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) + ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) + ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) + ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) + ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last update 11/05/03 shadow*/ + +void _vuMSUB(VURegs * VU) { + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBi(VURegs * VU) { + float ti = vuDouble(VU->VI[REG_I].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ti ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ti ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ti ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ti ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBq(VURegs * VU) { + float tq = vuDouble(VU->VI[REG_Q].UL); + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tq ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tq ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tq ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tq ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBx(VURegs * VU) { + float ftx; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx=vuDouble(VU->VF[_Ft_].i.x); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftx ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftx ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftx ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftx ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBy(VURegs * VU) { + float fty; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + fty=vuDouble(VU->VF[_Ft_].i.y); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * fty ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * fty ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * fty ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * fty ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBz(VURegs * VU) { + float ftz; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftz=vuDouble(VU->VF[_Ft_].i.z); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftz ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftz ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftz ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftz ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + +void _vuMSUBw(VURegs * VU) { + float ftw; + VECTOR * dst; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftw=vuDouble(VU->VF[_Ft_].i.w); + if (_X) dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ftw ) ); else VU_MACx_CLEAR(VU); + if (_Y) dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ftw ) ); else VU_MACy_CLEAR(VU); + if (_Z) dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ftw ) ); else VU_MACz_CLEAR(VU); + if (_W) dst->i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ftw ) ); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/* last update 11/05/03 shadow */ + + +void _vuMSUBA(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.x))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.y))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.z))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VF[_Ft_].i.w))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAi(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_I].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_I].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_I].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_I].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAq(VURegs * VU) { + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * vuDouble(VU->VI[REG_Q].UL))); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAx(VURegs * VU) { + float tx = vuDouble(VU->VF[_Ft_].i.x); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tx)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tx)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tx)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tx)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAy(VURegs * VU) { + float ty = vuDouble(VU->VF[_Ft_].i.y); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * ty)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * ty)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * ty)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * ty)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAz(VURegs * VU) { + float tz = vuDouble(VU->VF[_Ft_].i.z); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tz)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tz)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tz)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tz)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +void _vuMSUBAw(VURegs * VU) { + float tw = vuDouble(VU->VF[_Ft_].i.w); + + if (_X) VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - ( vuDouble(VU->VF[_Fs_].i.x) * tw)); else VU_MACx_CLEAR(VU); + if (_Y) VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - ( vuDouble(VU->VF[_Fs_].i.y) * tw)); else VU_MACy_CLEAR(VU); + if (_Z) VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - ( vuDouble(VU->VF[_Fs_].i.z) * tw)); else VU_MACz_CLEAR(VU); + if (_W) VU->ACC.i.w = VU_MACw_UPDATE(VU, vuDouble(VU->ACC.i.w) - ( vuDouble(VU->VF[_Fs_].i.w) * tw)); else VU_MACw_CLEAR(VU); + VU_STAT_UPDATE(VU); +}/*last updated 11/05/03 shadow*/ + +u32 _MAX(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? b : a; + } else { // +b + return b; + } + } else { // +a + if (b & 0x80000000) { // -b + return a; + } else { // +b + return (a & 0x7fffffff) > (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMAX(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMAXi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMAXx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMAXy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMAXz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMAXw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MAX(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MAX(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MAX(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MAX(VU->VF[_Fs_].i.w, ftw); +} + +u32 _MINI(u32 a, u32 b) { + if (a & 0x80000000) { // -a + if (b & 0x80000000) { // -b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? b : a; + } else { // +b + return a; + } + } else { // +a + if (b & 0x80000000) { // -b + return b; + } else { // +b + return (a & 0x7fffffff) < (b & 0x7fffffff) ? a : b; + } + } + + return 0; +} + +void _vuMINI(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, (s32)VU->VF[_Ft_].i.x); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, (s32)VU->VF[_Ft_].i.y); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, (s32)VU->VF[_Ft_].i.z); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, (s32)VU->VF[_Ft_].i.w); +}//checked 13/05/03 shadow + +void _vuMINIi(VURegs * VU) { + if (_Fd_ == 0) return; + + /* ft is bc */ + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, VU->VI[REG_I].UL); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, VU->VI[REG_I].UL); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, VU->VI[REG_I].UL); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, VU->VI[REG_I].UL); +}//checked 13/05/03 shadow + +void _vuMINIx(VURegs * VU) { + s32 ftx; + if (_Fd_ == 0) return; + + ftx=(s32)VU->VF[_Ft_].i.x; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftx); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftx); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftx); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftx); +} +//checked 13/05/03 shadow + +void _vuMINIy(VURegs * VU) { + s32 fty; + if (_Fd_ == 0) return; + + fty=(s32)VU->VF[_Ft_].i.y; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, fty); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, fty); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, fty); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, fty); +}//checked 13/05/03 shadow + +void _vuMINIz(VURegs * VU) { + s32 ftz; + if (_Fd_ == 0) return; + + ftz=(s32)VU->VF[_Ft_].i.z; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftz); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftz); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftz); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftz); +} + +void _vuMINIw(VURegs * VU) { + s32 ftw; + if (_Fd_ == 0) return; + + ftw=(s32)VU->VF[_Ft_].i.w; + if (_X) VU->VF[_Fd_].i.x = _MINI(VU->VF[_Fs_].i.x, ftw); + if (_Y) VU->VF[_Fd_].i.y = _MINI(VU->VF[_Fs_].i.y, ftw); + if (_Z) VU->VF[_Fd_].i.z = _MINI(VU->VF[_Fs_].i.z, ftw); + if (_W) VU->VF[_Fd_].i.w = _MINI(VU->VF[_Fs_].i.w, ftw); +} + +void _vuOPMULA(VURegs * VU) { + VU->ACC.i.x = VU_MACx_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Ft_].i.z)); + VU->ACC.i.y = VU_MACy_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Ft_].i.x)); + VU->ACC.i.z = VU_MACz_UPDATE(VU, vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Ft_].i.y)); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuOPMSUB(VURegs * VU) { + VECTOR * dst; + float ftx, fty, ftz; + float fsx, fsy, fsz; + if (_Fd_ == 0) dst = &RDzero; + else dst = &VU->VF[_Fd_]; + + ftx = vuDouble(VU->VF[_Ft_].i.x); fty = vuDouble(VU->VF[_Ft_].i.y); ftz = vuDouble(VU->VF[_Ft_].i.z); + fsx = vuDouble(VU->VF[_Fs_].i.x); fsy = vuDouble(VU->VF[_Fs_].i.y); fsz = vuDouble(VU->VF[_Fs_].i.z); + dst->i.x = VU_MACx_UPDATE(VU, vuDouble(VU->ACC.i.x) - fsy * ftz); + dst->i.y = VU_MACy_UPDATE(VU, vuDouble(VU->ACC.i.y) - fsz * ftx); + dst->i.z = VU_MACz_UPDATE(VU, vuDouble(VU->ACC.i.z) - fsx * fty); + VU_STAT_UPDATE(VU); +}/*last updated 8/05/03 shadow*/ + +void _vuNOP(VURegs * VU) { +} + +void _vuFTOI0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)vuDouble(VU->VF[_Fs_].i.x); + if (_Y) VU->VF[_Ft_].SL[1] = (s32)vuDouble(VU->VF[_Fs_].i.y); + if (_Z) VU->VF[_Ft_].SL[2] = (s32)vuDouble(VU->VF[_Fs_].i.z); + if (_W) VU->VF[_Ft_].SL[3] = (s32)vuDouble(VU->VF[_Fs_].i.w); +} + +void _vuFTOI4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int4(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int4(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int4(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int4(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int12(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int12(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int12(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int12(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuFTOI15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = float_to_int15(vuDouble(VU->VF[_Fs_].i.x)); + if (_Y) VU->VF[_Ft_].SL[1] = float_to_int15(vuDouble(VU->VF[_Fs_].i.y)); + if (_Z) VU->VF[_Ft_].SL[2] = float_to_int15(vuDouble(VU->VF[_Fs_].i.z)); + if (_W) VU->VF[_Ft_].SL[3] = float_to_int15(vuDouble(VU->VF[_Fs_].i.w)); +} + +void _vuITOF0(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = (float)VU->VF[_Fs_].SL[0]; + if (_Y) VU->VF[_Ft_].f.y = (float)VU->VF[_Fs_].SL[1]; + if (_Z) VU->VF[_Ft_].f.z = (float)VU->VF[_Fs_].SL[2]; + if (_W) VU->VF[_Ft_].f.w = (float)VU->VF[_Fs_].SL[3]; +} + +void _vuITOF4(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int4_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int4_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int4_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int4_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF12(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int12_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int12_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int12_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int12_to_float(VU->VF[_Fs_].SL[3]); +} + +void _vuITOF15(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].f.x = int15_to_float(VU->VF[_Fs_].SL[0]); + if (_Y) VU->VF[_Ft_].f.y = int15_to_float(VU->VF[_Fs_].SL[1]); + if (_Z) VU->VF[_Ft_].f.z = int15_to_float(VU->VF[_Fs_].SL[2]); + if (_W) VU->VF[_Ft_].f.w = int15_to_float(VU->VF[_Fs_].SL[3]); +} + +/* Different type of clipping by presaving w. asadr */ +void _vuCLIP(VURegs * VU) { + float value = fpufabsf(vuDouble(VU->VF[_Ft_].i.w)); + + VU->clipflag <<= 6; + if ( vuDouble(VU->VF[_Fs_].i.x) > +value ) VU->clipflag|= 0x01; + if ( vuDouble(VU->VF[_Fs_].i.x) < -value ) VU->clipflag|= 0x02; + if ( vuDouble(VU->VF[_Fs_].i.y) > +value ) VU->clipflag|= 0x04; + if ( vuDouble(VU->VF[_Fs_].i.y) < -value ) VU->clipflag|= 0x08; + if ( vuDouble(VU->VF[_Fs_].i.z) > +value ) VU->clipflag|= 0x10; + if ( vuDouble(VU->VF[_Fs_].i.z) < -value ) VU->clipflag|= 0x20; + VU->clipflag = VU->clipflag & 0xFFFFFF; + VU->VI[REG_CLIP_FLAG].UL = VU->clipflag; + + +}/*last update 16/07/05 refraction - Needs checking */ + + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuDIV(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft == 0.0) { + if (fs == 0.0) { + VU->statusflag |= 0x10; + } else { + VU->statusflag |= 0x20; + } + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } else { + VU->q.F = fs / ft; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + +void _vuSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + +// _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if (ft < 0.0 ) + VU->statusflag |= 0x10; + VU->q.F = fpusqrtf(fpufabsf(ft)); + VU->q.F = vuDouble(VU->q.UL); +} //last update 15/01/06 zerofrog + + +/* Eminent Bug - Dvisior == 0 Check Missing ( D Flag Not Set ) */ +/* REFIXED....ASADR; rerefixed....zerofrog */ +void _vuRSQRT(VURegs * VU) { + float ft = vuDouble(VU->VF[_Ft_].UL[_Ftf_]); + float fs = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + float temp; + +// _vuFMACTestStall(VU, _Fs_); _vuFMACTestStall(VU, _Ft_); + VU->statusflag = (VU->statusflag&0xfcf)|((VU->statusflag&0x30)<<6); + + if ( ft == 0.0 ) { + VU->statusflag |= 0x20; + + if( fs != 0 ) { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0xFF7FFFFF; + } else { + VU->q.UL = 0x7F7FFFFF; + } + } + else { + if ((VU->VF[_Ft_].UL[_Ftf_] & 0x80000000) ^ + (VU->VF[_Fs_].UL[_Fsf_] & 0x80000000)) { + VU->q.UL = 0x80000000; + } else { + VU->q.UL = 0; + } + + VU->statusflag |= 0x10; + } + + } else { + if (ft < 0.0) { + VU->statusflag |= 0x10; + } + + temp = fpusqrtf(fpufabsf(ft)); + VU->q.F = fs / temp; + VU->q.F = vuDouble(VU->q.UL); + } +} //last update 15/01/06 zerofrog + + +void _vuIADDI(VURegs * VU) { + s16 imm = ((VU->code >> 6) & 0x1f); + imm = ((imm & 0x10 ? 0xfff0 : 0) | (imm & 0xf)); + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + imm; +}//last checked 17/05/03 shadow NOTE: not quite sure about that + +void _vuIADDIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] + (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +}//last checked 17/05/03 shadow + +void _vuIADD(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] + VU->VI[_Ft_].SS[0]; +}//last checked 17/05/03 shadow + +void _vuIAND(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] & VU->VI[_Ft_].US[0]; +}//last checked 17/05/03 shadow + +void _vuIOR(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].US[0] = VU->VI[_Fs_].US[0] | VU->VI[_Ft_].US[0]; +} + +void _vuISUB(VURegs * VU) { + if(_Fd_ == 0) return; + VU->VI[_Fd_].SS[0] = VU->VI[_Fs_].SS[0] - VU->VI[_Ft_].SS[0]; +} + +void _vuISUBIU(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].SS[0] = VU->VI[_Fs_].SS[0] - (((VU->code >> 10) & 0x7800) | (VU->code & 0x7ff)); +} + +void _vuMOVE(VURegs * VU) { + if(_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VF[_Fs_].UL[0]; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VF[_Fs_].UL[1]; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VF[_Fs_].UL[2]; + if (_W) VU->VF[_Ft_].UL[3] = VU->VF[_Fs_].UL[3]; +}//last checked 17/05/03 shadow + +void _vuMFIR(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].SL[0] = (s32)VU->VI[_Fs_].SS[0]; + if (_Y) VU->VF[_Ft_].SL[1] = (s32)VU->VI[_Fs_].SS[0]; + if (_Z) VU->VF[_Ft_].SL[2] = (s32)VU->VI[_Fs_].SS[0]; + if (_W) VU->VF[_Ft_].SL[3] = (s32)VU->VI[_Fs_].SS[0]; +} + +// Big bug!!! mov from fs to ft not ft to fs. asadr +void _vuMTIR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = *(u16*)&VU->VF[_Fs_].F[_Fsf_]; +} + +void _vuMR32(VURegs * VU) { + u32 tx; + if (_Ft_ == 0) return; + + tx = VU->VF[_Fs_].i.x; + if (_X) VU->VF[_Ft_].i.x = VU->VF[_Fs_].i.y; + if (_Y) VU->VF[_Ft_].i.y = VU->VF[_Fs_].i.z; + if (_Z) VU->VF[_Ft_].i.z = VU->VF[_Fs_].i.w; + if (_W) VU->VF[_Ft_].i.w = tx; +}//last updated 23/10/03 linuzappz + +void _vuLQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQD( VURegs * VU ) { + u32 addr; + u32 *ptr; + + if (_Fs_ != 0) VU->VI[_Fs_].US[0]--; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; +} + +void _vuLQI(VURegs * VU) { + if (_Ft_) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; + if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; + if (_Z) VU->VF[_Ft_].UL[2] = ptr[2]; + if (_W) VU->VF[_Ft_].UL[3] = ptr[3]; + } + if (_Fs_ != 0) VU->VI[_Fs_].US[0]++; +} + +/* addr is now signed. Asadr */ +void _vuSQ(VURegs * VU) { + s16 imm; + u16 addr; + u32 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Ft_].SS[0]) * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQD(VURegs * VU) { + u32 addr; + u32 *ptr; + + if(_Ft_ != 0) VU->VI[_Ft_].US[0]--; + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; +} + +void _vuSQI(VURegs * VU) { + u32 addr; + u32 *ptr; + + addr = VU->VI[_Ft_].US[0] * 16; + ptr = (u32*)GET_VU_MEM(VU, addr); + if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; + if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; + if (_Z) ptr[2] = VU->VF[_Fs_].UL[2]; + if (_W) ptr[3] = VU->VF[_Fs_].UL[3]; + if(_Ft_ != 0) VU->VI[_Ft_].US[0]++; +} + +/* addr now signed. asadr */ +void _vuILW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISW(VURegs * VU) { + s16 imm; + u16 addr; + u16 *ptr; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +void _vuILWR(VURegs * VU) { + u32 addr; + u16 *ptr; + if (_Ft_ == 0) return; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) VU->VI[_Ft_].US[0] = ptr[0]; + if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; + if (_Z) VU->VI[_Ft_].US[0] = ptr[4]; + if (_W) VU->VI[_Ft_].US[0] = ptr[6]; +} + +void _vuISWR(VURegs * VU) { + u32 addr; + u16 *ptr; + + addr = VU->VI[_Fs_].US[0] * 16; + ptr = (u16*)GET_VU_MEM(VU, addr); + if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } + if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } + if (_Z) { ptr[4] = VU->VI[_Ft_].US[0]; ptr[5] = 0; } + if (_W) { ptr[6] = VU->VI[_Ft_].US[0]; ptr[7] = 0; } +} + +/* code contributed by _Riff_ + +The following code implements a Galois form M-series LFSR that can be configured to have a width from 0 to 32. +A Galois field can be represented as G(X) = g_m * X^m + g_(m-1) * X^(m-1) + ... + g_1 * X^1 + g0. +A Galois form M-Series LFSR represents a Galois field where g0 = g_m = 1 and the generated set contains 2^M - 1 values. +In modulo-2 arithmetic, addition is replaced by XOR and multiplication is replaced by AND. +The code is written in such a way that the polynomial lsb (g0) should be set to 0 and g_m is not represented. +As an example for setting the polynomial variable correctly, the 23-bit M-series generating polynomial X^23+X^14 + would be specified as (1 << 14). +*/ + + +//The two-tap 23 stage M-series polynomials are x23+x18 and x23+x14 ((1 << 18) and (1 << 14), respectively). +//The reverse sequences can be generated by x23+x(23-18) and x23+x(23-14) ((1 << 9) and (1 << 5), respectively) +u32 poly = 1 << 5; + +void SetPoly(u32 newPoly) { + poly = poly & ~1; +} + +void AdvanceLFSR(VURegs * VU) { + // code from www.project-fao.org + int x = (VU->VI[REG_R].UL >> 4) & 1; + int y = (VU->VI[REG_R].UL >> 22) & 1; + VU->VI[REG_R].UL <<= 1; + VU->VI[REG_R].UL ^= x ^ y; + VU->VI[REG_R].UL = (VU->VI[REG_R].UL&0x7fffff)|0x3f800000; +} +// old +// u32 lfsr = VU->VI[REG_R].UL & 0x007FFFFF; +// u32 oldlfsr = lfsr; +// lfsr <<= 1; +// if (oldlfsr & 0x00400000) { +// lfsr ^= poly; +// lfsr |= 1; +// } +// +// VU->VI[REG_R].UL = 0x3F800000 | (lfsr & 0x007FFFFF); + +void _vuRINIT(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | (VU->VF[_Fs_].UL[_Fsf_] & 0x007FFFFF); +} + +void _vuRGET(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRNEXT(VURegs * VU) { + if (_Ft_ == 0) return; + AdvanceLFSR(VU); + if (_X) VU->VF[_Ft_].UL[0] = VU->VI[REG_R].UL; + if (_Y) VU->VF[_Ft_].UL[1] = VU->VI[REG_R].UL; + if (_Z) VU->VF[_Ft_].UL[2] = VU->VI[REG_R].UL; + if (_W) VU->VF[_Ft_].UL[3] = VU->VI[REG_R].UL; +} + +void _vuRXOR(VURegs * VU) { + VU->VI[REG_R].UL = 0x3F800000 | ((VU->VI[REG_R].UL ^ VU->VF[_Fs_].UL[_Fsf_]) & 0x007FFFFF); +} + +void _vuWAITQ(VURegs * VU) { +} + +void _vuFSAND(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) & imm; +} + +void _vuFSEQ(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + if((VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) == imm) VU->VI[_Ft_].US[0] = 1; + else VU->VI[_Ft_].US[0] = 0; +} + +void _vuFSOR(VURegs * VU) { + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_STATUS_FLAG].US[0] & 0xFFF) | imm; +} + +void _vuFSSET(VURegs * VU) { + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + VU->statusflag = (imm & 0xFC0) | (VU->VI[REG_STATUS_FLAG].US[0] & 0x3F); +} + +void _vuFMAND(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[_Fs_].US[0] & (VU->VI[REG_MAC_FLAG].UL & 0xFFFF); +} + +void _vuFMEQ(VURegs * VU) { + if(_Ft_ == 0) return; + if((VU->VI[REG_MAC_FLAG].UL & 0xFFFF) == VU->VI[_Fs_].US[0]){ + VU->VI[_Ft_].US[0] =1;} else { VU->VI[_Ft_].US[0] =0; } +} + +void _vuFMOR(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (VU->VI[REG_MAC_FLAG].UL & 0xFFFF) | VU->VI[_Fs_].US[0]; +} + +void _vuFCAND(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) & (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCEQ(VURegs * VU) { + if((VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) == (VU->code & 0xFFFFFF)) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCOR(VURegs * VU) { + u32 hold = (VU->VI[REG_CLIP_FLAG].UL & 0xFFFFFF) | ( VU->code & 0xFFFFFF); + if(hold == 0xFFFFFF) VU->VI[1].US[0] = 1; + else VU->VI[1].US[0] = 0; +} + +void _vuFCSET(VURegs * VU) { + VU->clipflag = (u32) (VU->code & 0xFFFFFF); + VU->VI[REG_CLIP_FLAG].UL = (u32) (VU->code & 0xFFFFFF); +} + +void _vuFCGET(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->VI[REG_CLIP_FLAG].UL & 0x0FFF; +} + +s32 _branchAddr(VURegs * VU) { + s32 bpc = VU->VI[REG_TPC].SL + _Imm11_ * 8; + if (bpc < 0) { + bpc = VU->VI[REG_TPC].SL + _UImm11_ * 8; + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void _setBranch(VURegs * VU, u32 bpc) { + VU->branch = 2; + VU->branchpc = bpc; +// VU->vuExec(VU); +// VU->VI[REG_TPC].UL = bpc; +} + +void _vuIBEQ(VURegs * VU) { + if (VU->VI[_Ft_].US[0] == VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] >= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBGTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] > 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLEZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] <= 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBLTZ(VURegs * VU) { + if (VU->VI[_Fs_].SS[0] < 0) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuIBNE(VURegs * VU) { + if (VU->VI[_Ft_].US[0] != VU->VI[_Fs_].US[0]) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); + } +} + +void _vuB(VURegs * VU) { + s32 bpc = _branchAddr(VU); + _setBranch(VU, bpc); +} + +void _vuBAL(VURegs * VU) { + s32 bpc = _branchAddr(VU); + + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuJR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + _setBranch(VU, bpc); +} + +void _vuJALR(VURegs * VU) { + u32 bpc = VU->VI[_Fs_].US[0] * 8; + if (_Ft_) { + VU->VI[_Ft_].US[0] = (VU->VI[REG_TPC].UL + 8)/8; + } + + _setBranch(VU, bpc); +} + +void _vuMFP(VURegs * VU) { + if (_Ft_ == 0) return; + + if (_X) VU->VF[_Ft_].i.x = VU->VI[REG_P].UL; + if (_Y) VU->VF[_Ft_].i.y = VU->VI[REG_P].UL; + if (_Z) VU->VF[_Ft_].i.z = VU->VI[REG_P].UL; + if (_W) VU->VF[_Ft_].i.w = VU->VI[REG_P].UL; +} + +void _vuWAITP(VURegs * VU) { +} + +void _vuESADD(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + VU->p.F = p; +} + +void _vuERSADD(VURegs * VU) { + float p = (vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x)) + (vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y)) + (vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z)); + if (p != 0.0) + p = 1.0f / p; + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to value being -ve for sqrt *asadr */ +void _vuELENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if(p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERLENG(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) * vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) * vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) * vuDouble(VU->VF[_Fs_].i.z); + if (p >= 0) { + p = fpusqrtf(p); + if (p != 0) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxy(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.y), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuEATANxz(VURegs * VU) { + float p = 0; + if(vuDouble(VU->VF[_Fs_].i.x) != 0) { + p = fpuatan2f(vuDouble(VU->VF[_Fs_].i.z), vuDouble(VU->VF[_Fs_].i.x)); + } + VU->p.F = p; +} + +void _vuESUM(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].i.x) + vuDouble(VU->VF[_Fs_].i.y) + vuDouble(VU->VF[_Fs_].i.z) + vuDouble(VU->VF[_Fs_].i.w); + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERCPR(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p != 0){ + p = 1.0 / p; + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to Value being -ve for sqrt *asadr */ +void _vuESQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0){ + p = fpusqrtf(p); + } + VU->p.F = p; +} + +/* Fixed. Could have caused crash due to divisor being = 0 *asadr */ +void _vuERSQRT(VURegs * VU) { + float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]); + if (p >= 0) { + p = fpusqrtf(p); + if (p) { + p = 1.0f / p; + } + } + VU->p.F = p; +} + +void _vuESIN(VURegs * VU) { + float p = fpusinf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEATAN(VURegs * VU) { + float p = fpuatanf(vuDouble(VU->VF[_Fs_].UL[_Fsf_])); + VU->p.F = p; +} + +void _vuEEXP(VURegs * VU) { + float p = fpuexpf(-(vuDouble(VU->VF[_Fs_].UL[_Fsf_]))); + VU->p.F = p; +} + +void _vuXITOP(VURegs * VU) { + if (_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = VU->vifRegs->itop; +} + +//extern u32 vudump; +//static void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 56 ) { +// __Log("xgkick %d\n", scount); +// vudump |= 8; +// } +//} + +void _vuXGKICK(VURegs * VU) +{ + // flush all pipelines first (in the right order) + _vuFlushAll(VU); + //countfn(); + GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); +} + +void _vuXTOP(VURegs * VU) { + if(_Ft_ == 0) return; + VU->VI[_Ft_].US[0] = (u16)VU->vifRegs->top; +} + +#define GET_VF0_FLAG(reg) (((reg)==0)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_I)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1 << REG_Q)|(ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (ACC?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_I)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = (1<VIread = (1 << REG_Q)|GET_VF0_FLAG(_Fs_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= _XYZW; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFwxyzw= _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|((readacc||_XYZW!=15)?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Ft_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw = 0xff; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0); \ +} + +#define VUREGS_IDISIT(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Fd_; \ + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); \ +} + +#define VUREGS_ITIS(OP) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_IALU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << _Ft_; \ + VUregsn->VIread = 1 << _Fs_; \ +} + +#define VUREGS_PFS(OP, _cycles) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + VUregsn->pipe = VUPIPE_EFU; \ + VUregsn->VFwrite = 0; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VIwrite = 1 << REG_P; \ + VUregsn->VIread = GET_VF0_FLAG(_Fs_); \ + VUregsn->cycles = _cycles; \ +} + + + +VUREGS_FTFS(ABS); + +VUREGS_FDFSFT(ADD, 0); +VUREGS_FDFSI(ADDi, 0); +VUREGS_FDFSQ(ADDq, 0); +VUREGS_FDFSFTx(ADDx, 0); +VUREGS_FDFSFTy(ADDy, 0); +VUREGS_FDFSFTz(ADDz, 0); +VUREGS_FDFSFTw(ADDw, 0); + +VUREGS_ACCFSFT(ADDA, 0); +VUREGS_ACCFSI(ADDAi, 0); +VUREGS_ACCFSQ(ADDAq, 0); +VUREGS_ACCFSFTx(ADDAx, 0); +VUREGS_ACCFSFTy(ADDAy, 0); +VUREGS_ACCFSFTz(ADDAz, 0); +VUREGS_ACCFSFTw(ADDAw, 0); + +VUREGS_FDFSFT(SUB, 0); +VUREGS_FDFSI(SUBi, 0); +VUREGS_FDFSQ(SUBq, 0); +VUREGS_FDFSFTx(SUBx, 0); +VUREGS_FDFSFTy(SUBy, 0); +VUREGS_FDFSFTz(SUBz, 0); +VUREGS_FDFSFTw(SUBw, 0); + +VUREGS_ACCFSFT(SUBA, 0); +VUREGS_ACCFSI(SUBAi, 0); +VUREGS_ACCFSQ(SUBAq, 0); +VUREGS_ACCFSFTx(SUBAx, 0); +VUREGS_ACCFSFTy(SUBAy, 0); +VUREGS_ACCFSFTz(SUBAz, 0); +VUREGS_ACCFSFTw(SUBAw, 0); + +#define VUREGS_FDFSFTxyzw_MUL(OP, ACC, xyzw) \ +void _vuRegs##OP(VURegs * VU, _VURegsNum *VUregsn) { \ + if( _Ft_ == 0 && xyzw > 1 && _XYZW == 0xf ) { /* resetting to 0 */ \ + VUregsn->pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = 0; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = 0; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = (ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = ACC?0:_Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = (ACC?(1<VIread = GET_VF0_FLAG(_Fs_)|((ACC&&(_XYZW!=15))?(1<pipe = VUPIPE_FMAC; \ + VUregsn->VFwrite = _Fd_; \ + VUregsn->VFwxyzw = _XYZW; \ + VUregsn->VFread0 = _Fs_; \ + VUregsn->VFr0xyzw= _XYZW; \ + VUregsn->VFread1 = _Ft_; \ + VUregsn->VFr1xyzw= xyzw; \ + VUregsn->VIwrite = 0; \ + VUregsn->VIread = (1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<VIread &= ~(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 1<VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Fd_; + VUregsn->VFwxyzw= 0xE; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0xE; + VUregsn->VIwrite = 0; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1<pipe = VUPIPE_NONE; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_FTFS(FTOI0); +VUREGS_FTFS(FTOI4); +VUREGS_FTFS(FTOI12); +VUREGS_FTFS(FTOI15); +VUREGS_FTFS(ITOF0); +VUREGS_FTFS(ITOF4); +VUREGS_FTFS(ITOF12); +VUREGS_FTFS(ITOF15); + +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xE; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 0x1; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_)|(1 << REG_CLIP_FLAG); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFr0xyzw = 0; + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw = 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 6; +} + +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = _Ft_; + VUregsn->VFr1xyzw= 1 << (3-_Ftf_); + VUregsn->VIwrite = 1 << REG_Q; + VUregsn->VIread = GET_VF0_FLAG(_Fs_)|GET_VF0_FLAG(_Ft_); + VUregsn->cycles = 12; +} + +VUREGS_ITIS(IADDI); +VUREGS_ITIS(IADDIU); +VUREGS_IDISIT(IADD); +VUREGS_IDISIT(IAND); +VUREGS_IDISIT(IOR); +VUREGS_IDISIT(ISUB); +VUREGS_ITIS(ISUBIU); + +VUREGS_FTFS(MOVE); + +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +VUREGS_FTFS(MR32); + +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Fs_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << _Ft_)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = (1 << _Ft_); + VUregsn->VIread = (1 << _Fs_); +} + +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = GET_VF0_FLAG(_Fs_); +} + +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = 1 << REG_R; +} + +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_R; + VUregsn->VIread = (1 << REG_R)|GET_VF0_FLAG(_Fs_); +} + +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FDIV; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_STATUS_FLAG; +} + +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_STATUS_FLAG; + VUregsn->VIread = 0;//1 << REG_STATUS_FLAG; this kills speed +} + +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = (1 << REG_MAC_FLAG) | (1 << _Fs_); +} + +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << 1; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << REG_CLIP_FLAG; + VUregsn->VIread = 0; +} + +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << REG_CLIP_FLAG; +} + +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = (1 << _Fs_) | (1 << _Ft_); +} + +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_BRANCH; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << REG_P; +} + +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_EFU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 0; +} + +VUREGS_PFS(ESADD, 10); +VUREGS_PFS(ERSADD, 17); +VUREGS_PFS(ELENG, 17); +VUREGS_PFS(ERLENG, 23); +VUREGS_PFS(EATANxy, 53); +VUREGS_PFS(EATANxz, 53); +VUREGS_PFS(ESUM, 11); +VUREGS_PFS(ERCPR, 11); +VUREGS_PFS(ESQRT, 11); +VUREGS_PFS(ERSQRT, 17); +VUREGS_PFS(ESIN, 28); +VUREGS_PFS(EATAN, 53); +VUREGS_PFS(EEXP, 43); + +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} + +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_XGKICK; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 0; + VUregsn->VIread = 1 << _Fs_; +} + +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_IALU; + VUregsn->VFwrite = 0; + VUregsn->VFread0 = 0; + VUregsn->VFread1 = 0; + VUregsn->VIwrite = 1 << _Ft_; + VUregsn->VIread = 0; +} diff --git a/pcsx2/VUops.h b/pcsx2/VUops.h new file mode 100644 index 0000000..0b4a0f9 --- /dev/null +++ b/pcsx2/VUops.h @@ -0,0 +1,393 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VU1OPS_H__ +#define __VU1OPS_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +#include "VU.h" + +#define float_to_int4(x) (s32)((float)x * (1.0f / 0.0625f)) +#define float_to_int12(x) (s32)((float)x * (1.0f / 0.000244140625f)) +#define float_to_int15(x) (s32)((float)x * (1.0f / 0.000030517578125)) + +#define int4_to_float(x) (float)((float)x * 0.0625f) +#define int12_to_float(x) (float)((float)x * 0.000244140625f) +#define int15_to_float(x) (float)((float)x * 0.000030517578125) + +#define MAC_Reset( VU ) VU->VI[REG_MAC_FLAG].UL = VU->VI[REG_MAC_FLAG].UL & (~0xFFFF) + +void _vuSetCycleFlags(VURegs * VU); +void _vuFlushFDIV(VURegs * VU); +void _vuFlushEFU(VURegs * VU); +void _vuTestPipes(VURegs * VU); +void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuABS(VURegs * VU); +void _vuADD(VURegs * VU); +void _vuADDi(VURegs * VU); +void _vuADDq(VURegs * VU); +void _vuADDx(VURegs * VU); +void _vuADDy(VURegs * VU); +void _vuADDz(VURegs * VU); +void _vuADDw(VURegs * VU); +void _vuADDA(VURegs * VU); +void _vuADDAi(VURegs * VU); +void _vuADDAq(VURegs * VU); +void _vuADDAx(VURegs * VU); +void _vuADDAy(VURegs * VU); +void _vuADDAz(VURegs * VU); +void _vuADDAw(VURegs * VU); +void _vuSUB(VURegs * VU); +void _vuSUBi(VURegs * VU); +void _vuSUBq(VURegs * VU); +void _vuSUBx(VURegs * VU); +void _vuSUBy(VURegs * VU); +void _vuSUBz(VURegs * VU); +void _vuSUBw(VURegs * VU); +void _vuSUBA(VURegs * VU); +void _vuSUBAi(VURegs * VU); +void _vuSUBAq(VURegs * VU); +void _vuSUBAx(VURegs * VU); +void _vuSUBAy(VURegs * VU); +void _vuSUBAz(VURegs * VU); +void _vuSUBAw(VURegs * VU); +void _vuMUL(VURegs * VU); +void _vuMULi(VURegs * VU); +void _vuMULq(VURegs * VU); +void _vuMULx(VURegs * VU); +void _vuMULy(VURegs * VU); +void _vuMULz(VURegs * VU); +void _vuMULw(VURegs * VU); +void _vuMULA(VURegs * VU); +void _vuMULAi(VURegs * VU); +void _vuMULAq(VURegs * VU); +void _vuMULAx(VURegs * VU); +void _vuMULAy(VURegs * VU); +void _vuMULAz(VURegs * VU); +void _vuMULAw(VURegs * VU); +void _vuMADD(VURegs * VU) ; +void _vuMADDi(VURegs * VU); +void _vuMADDq(VURegs * VU); +void _vuMADDx(VURegs * VU); +void _vuMADDy(VURegs * VU); +void _vuMADDz(VURegs * VU); +void _vuMADDw(VURegs * VU); +void _vuMADDA(VURegs * VU); +void _vuMADDAi(VURegs * VU); +void _vuMADDAq(VURegs * VU); +void _vuMADDAx(VURegs * VU); +void _vuMADDAy(VURegs * VU); +void _vuMADDAz(VURegs * VU); +void _vuMADDAw(VURegs * VU); +void _vuMSUB(VURegs * VU); +void _vuMSUBi(VURegs * VU); +void _vuMSUBq(VURegs * VU); +void _vuMSUBx(VURegs * VU); +void _vuMSUBy(VURegs * VU); +void _vuMSUBz(VURegs * VU) ; +void _vuMSUBw(VURegs * VU) ; +void _vuMSUBA(VURegs * VU); +void _vuMSUBAi(VURegs * VU); +void _vuMSUBAq(VURegs * VU); +void _vuMSUBAx(VURegs * VU); +void _vuMSUBAy(VURegs * VU); +void _vuMSUBAz(VURegs * VU); +void _vuMSUBAw(VURegs * VU); +void _vuMAX(VURegs * VU); +void _vuMAXi(VURegs * VU); +void _vuMAXx(VURegs * VU); +void _vuMAXy(VURegs * VU); +void _vuMAXz(VURegs * VU); +void _vuMAXw(VURegs * VU); +void _vuMINI(VURegs * VU); +void _vuMINIi(VURegs * VU); +void _vuMINIx(VURegs * VU); +void _vuMINIy(VURegs * VU); +void _vuMINIz(VURegs * VU); +void _vuMINIw(VURegs * VU); +void _vuOPMULA(VURegs * VU); +void _vuOPMSUB(VURegs * VU); +void _vuNOP(VURegs * VU); +void _vuFTOI0(VURegs * VU); +void _vuFTOI4(VURegs * VU); +void _vuFTOI12(VURegs * VU); +void _vuFTOI15(VURegs * VU); +void _vuITOF0(VURegs * VU) ; +void _vuITOF4(VURegs * VU) ; +void _vuITOF12(VURegs * VU); +void _vuITOF15(VURegs * VU); +void _vuCLIP(VURegs * VU); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuDIV(VURegs * VU); +void _vuSQRT(VURegs * VU); +void _vuRSQRT(VURegs * VU); +void _vuIADDI(VURegs * VU); +void _vuIADDIU(VURegs * VU); +void _vuIADD(VURegs * VU); +void _vuIAND(VURegs * VU); +void _vuIOR(VURegs * VU); +void _vuISUB(VURegs * VU); +void _vuISUBIU(VURegs * VU); +void _vuMOVE(VURegs * VU); +void _vuMFIR(VURegs * VU); +void _vuMTIR(VURegs * VU); +void _vuMR32(VURegs * VU); +void _vuLQ(VURegs * VU) ; +void _vuLQD(VURegs * VU); +void _vuLQI(VURegs * VU); +void _vuSQ(VURegs * VU); +void _vuSQD(VURegs * VU); +void _vuSQI(VURegs * VU); +void _vuILW(VURegs * VU); +void _vuISW(VURegs * VU); +void _vuILWR(VURegs * VU); +void _vuISWR(VURegs * VU); +void _vuLOI(VURegs * VU); +void _vuRINIT(VURegs * VU); +void _vuRGET(VURegs * VU); +void _vuRNEXT(VURegs * VU); +void _vuRXOR(VURegs * VU); +void _vuWAITQ(VURegs * VU); +void _vuFSAND(VURegs * VU); +void _vuFSEQ(VURegs * VU); +void _vuFSOR(VURegs * VU); +void _vuFSSET(VURegs * VU); +void _vuFMAND(VURegs * VU); +void _vuFMEQ(VURegs * VU); +void _vuFMOR(VURegs * VU); +void _vuFCAND(VURegs * VU); +void _vuFCEQ(VURegs * VU); +void _vuFCOR(VURegs * VU); +void _vuFCSET(VURegs * VU); +void _vuFCGET(VURegs * VU); +void _vuIBEQ(VURegs * VU); +void _vuIBGEZ(VURegs * VU); +void _vuIBGTZ(VURegs * VU); +void _vuIBLEZ(VURegs * VU); +void _vuIBLTZ(VURegs * VU); +void _vuIBNE(VURegs * VU); +void _vuB(VURegs * VU); +void _vuBAL(VURegs * VU); +void _vuJR(VURegs * VU); +void _vuJALR(VURegs * VU); +void _vuMFP(VURegs * VU); +void _vuWAITP(VURegs * VU); +void _vuESADD(VURegs * VU); +void _vuERSADD(VURegs * VU); +void _vuELENG(VURegs * VU); +void _vuERLENG(VURegs * VU); +void _vuEATANxy(VURegs * VU); +void _vuEATANxz(VURegs * VU); +void _vuESUM(VURegs * VU); +void _vuERCPR(VURegs * VU); +void _vuESQRT(VURegs * VU); +void _vuERSQRT(VURegs * VU); +void _vuESIN(VURegs * VU); +void _vuEATAN(VURegs * VU); +void _vuEEXP(VURegs * VU); +void _vuXITOP(VURegs * VU); +void _vuXGKICK(VURegs * VU); +void _vuXTOP(VURegs * VU); + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +void _vuRegsABS(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMUL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMULAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMADDAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAq(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMSUBAw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAX(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMAXw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIi(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIx(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMINIw(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMULA(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsOPMSUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsNOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFTOI15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF0(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF4(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF12(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsITOF15(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCLIP(VURegs * VU, _VURegsNum *VUregsn); +/******************************/ +/* VU Lower instructions */ +/******************************/ +void _vuRegsDIV(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADDIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISUBIU(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMOVE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsSQI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISW(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsILWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsISWR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsLOI(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRINIT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRNEXT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsRXOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFSSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFMOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCAND(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCOR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCSET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsFCGET(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBEQ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBGTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLEZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBLTZ(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsIBNE(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsB(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsBAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsJALR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsMFP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsWAITP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSADD(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsELENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERLENG(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxy(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATANxz(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESUM(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERCPR(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsERSQRT(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsESIN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEATAN(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsEEXP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXITOP(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXGKICK(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsXTOP(VURegs * VU, _VURegsNum *VUregsn); + +#endif diff --git a/pcsx2/Vif.c b/pcsx2/Vif.c new file mode 100644 index 0000000..87ba7a8 --- /dev/null +++ b/pcsx2/Vif.c @@ -0,0 +1,1055 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +VIFregisters *_vifRegs; +u32* _vifMaskRegs = NULL; +PCSX2_ALIGNED16(u32 g_vifRow0[4]); +PCSX2_ALIGNED16(u32 g_vifCol0[4]); +PCSX2_ALIGNED16(u32 g_vifRow1[4]); +PCSX2_ALIGNED16(u32 g_vifCol1[4]); +u32* _vifRow = NULL, *_vifCol = NULL; + +vifStruct *_vif; + +static int n; +static int i; + +__inline static int _limit( int a, int max ) +{ + return ( a > max ? max : a ); +} + +#define _UNPACKpart( offnum, func ) \ + if ( ( size > 0 ) && ( _vifRegs->offset == offnum ) ) { \ + func; \ + size--; \ + _vifRegs->offset++; \ + } + +#define _UNPACKpart_nosize( offnum, func ) \ + if ( ( _vifRegs->offset == offnum ) ) { \ + func; \ + _vifRegs->offset++; \ + } + +static void _writeX( u32 *dest, u32 data ) +{ + //int n; + + switch ( _vif->cl ) { + case 0: n = 0; break; + case 1: n = 8; break; + case 2: n = 16; break; + default: n = 24; break; + } +/*#ifdef GIF_LOG + GIF_LOG("_writeX %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r0; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +/*#ifdef GIF_LOG + GIF_LOG("_writeX-done : Data %x : Row %x\n", *dest, _vifRegs->r0); +#endif*/ +} + +static void _writeY( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 2; break; + case 1: n = 10; break; + case 2: n = 18; break; + default: n = 26; break; + } +/*#ifdef GIF_LOG + GIF_LOG("_writeY %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Y!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r1; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } + +/*#ifdef GIF_LOG + GIF_LOG("_writeY-done : Data %x : Row %x\n", *dest, _vifRegs->r1); +#endif*/ +} + +static void _writeZ( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 4; break; + case 1: n = 12; break; + case 2: n = 20; break; + default: n = 28; break; + } +/*#ifdef GIF_LOG + GIF_LOG("_writeZ %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Z!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r2; break; + case 2: + switch ( _vif->cl ) + { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void _writeW( u32 *dest, u32 data ) +{ + //int n; + switch ( _vif->cl ) { + case 0: n = 6; break; + case 1: n = 14; break; + case 2: n = 22; break; + default: n = 30; break; + } +/*#ifdef GIF_LOG + GIF_LOG("_writeW %x = %x (writecycle=%d; mask %x; mode %d)\n", (u32)dest-(u32)VU1.Mem, data, _vif->cl, ( _vifRegs->mask >> n ) & 0x3,_vifRegs->mode); +#endif*/ + switch ( ( _vifRegs->mask >> n ) & 0x3 ) { + case 0: + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew W!\n"); + *dest = data; + break; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } + break; + case 1: *dest = _vifRegs->r3; break; + case 2: + switch ( _vif->cl ) { + case 0: *dest = _vifRegs->c0; break; + case 1: *dest = _vifRegs->c1; break; + case 2: *dest = _vifRegs->c2; break; + default: *dest = _vifRegs->c3; break; + } + break; + } +} + +static void writeX( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeX(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r0; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r0 = data + _vifRegs->r0; + *dest = _vifRegs->r0; + } else { + *dest = data; + } +/*#ifdef GIF_LOG + GIF_LOG("writeX %8.8x : Mode %d, r0 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r0,data); +#endif*/ +} + +static void writeY( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeY(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Y!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r1; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r1 = data + _vifRegs->r1; + *dest = _vifRegs->r1; + } else { + *dest = data; + } +/*#ifdef GIF_LOG + GIF_LOG("writeY %8.8x : Mode %d, r1 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r1,data); +#endif*/ +} + +static void writeZ( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeZ(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew Z!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r2; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r2 = data + _vifRegs->r2; + *dest = _vifRegs->r2; + } else { + *dest = data; + } +/*#ifdef GIF_LOG + GIF_LOG("writeZ %8.8x : Mode %d, r2 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r2,data); +#endif*/ +} + +static void writeW( u32 *dest, u32 data ) { + if (_vifRegs->code & 0x10000000) { _writeW(dest, data); return; } + if((_vif->cmd & 0x6F) == 0x6f) { + //SysPrintf("Phew X!\n"); + *dest = data; + return; + } + if (_vifRegs->mode == 1) { + *dest = data + _vifRegs->r3; + } else + if (_vifRegs->mode == 2) { + _vifRegs->r3 = data + _vifRegs->r3; + *dest = _vifRegs->r3; + } else { + *dest = data; + } +/*#ifdef GIF_LOG + GIF_LOG("writeW %8.8x : Mode %d, r3 = %x, data %8.8x\n", *dest,_vifRegs->mode,_vifRegs->r3,data); +#endif*/ +} + +void UNPACK_S_32(u32 *dest, u32 *data) { + writeX(dest++, *data); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_S_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data) ); + _UNPACKpart(1, writeY(dest++, *data) ); + _UNPACKpart(2, writeZ(dest++, *data) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (uptr)data - (uptr)_data; +} + +#define _UNPACK_S_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_S_16s( u32 *dest, u32 *data ) { + _UNPACK_S_16( s16 ); +} + +void UNPACK_S_16u( u32 *dest, u32 *data ) { + _UNPACK_S_16( u16 ); +} + +#define _UNPACK_S_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata) ); \ + _UNPACKpart(1, writeY(dest++, *sdata) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)sdata - (uptr)data; + +int UNPACK_S_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(s16); +} + +int UNPACK_S_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_16part(u16); +} + +#define _UNPACK_S_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_S_8s(u32 *dest, u32 *data) { + _UNPACK_S_8(s8); +} + +void UNPACK_S_8u(u32 *dest, u32 *data) { + _UNPACK_S_8(u8); +} + +#define _UNPACK_S_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata) ); \ + _UNPACKpart(1, writeY(dest++, *cdata) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)cdata - (uptr)data; + +int UNPACK_S_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(s8); +} + +int UNPACK_S_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_S_8part(u8); +} + +void UNPACK_V2_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data); + writeZ(dest++, *data); + writeW(dest++, *data++); + +} + +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++)); + _UNPACKpart(1, writeY(dest++, *data++)); + _UNPACKpart_nosize(2, writeZ(dest++, 0)); + _UNPACKpart_nosize(3, writeW(dest++, 0)); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (uptr)data - (uptr)_data; +} + +#define _UNPACK_V2_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); \ + + +void UNPACK_V2_16s(u32 *dest, u32 *data) { + _UNPACK_V2_16(s16); +} + +void UNPACK_V2_16u(u32 *dest, u32 *data) { + _UNPACK_V2_16(u16); +} + +#define _UNPACK_V2_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)sdata - (uptr)data; + +int UNPACK_V2_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(s16); +} + +int UNPACK_V2_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_16part(u16); +} + +#define _UNPACK_V2_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_V2_8s(u32 *dest, u32 *data) { + _UNPACK_V2_8(s8); +} + +void UNPACK_V2_8u(u32 *dest, u32 *data) { + _UNPACK_V2_8(u8); +} + +#define _UNPACK_V2_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart_nosize(2,writeZ(dest++, 0)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)cdata - (uptr)data; + +int UNPACK_V2_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(s8); +} + +int UNPACK_V2_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V2_8part(u8); +} + +void UNPACK_V3_32(u32 *dest, u32 *data) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data); + writeW(dest++, *data++); +} + +int UNPACK_V3_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++); ); + _UNPACKpart(1, writeY(dest++, *data++); ); + _UNPACKpart(2, writeZ(dest++, *data++); ); + _UNPACKpart_nosize(3, writeW(dest++, 0); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (uptr)data - (uptr)_data; +} + +#define _UNPACK_V3_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata); \ + writeW(dest++, *sdata++); + +void UNPACK_V3_16s(u32 *dest, u32 *data) { + _UNPACK_V3_16(s16); +} + +void UNPACK_V3_16u(u32 *dest, u32 *data) { + _UNPACK_V3_16(u16); +} + +#define _UNPACK_V3_16part(format) \ + format *sdata = (format*)data; \ + \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++)); \ + _UNPACKpart(1, writeY(dest++, *sdata++)); \ + _UNPACKpart(2, writeZ(dest++, *sdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)sdata - (uptr)data; + +int UNPACK_V3_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(s16); +} + +int UNPACK_V3_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_16part(u16); +} + +#define _UNPACK_V3_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata); \ + writeW(dest++, *cdata++); + +void UNPACK_V3_8s(u32 *dest, u32 *data) { + _UNPACK_V3_8(s8); +} + +void UNPACK_V3_8u(u32 *dest, u32 *data) { + _UNPACK_V3_8(u8); +} + +#define _UNPACK_V3_8part(format) \ + format *cdata = (format*)data; \ + while(size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++)); \ + _UNPACKpart(1, writeY(dest++, *cdata++)); \ + _UNPACKpart(2, writeZ(dest++, *cdata++)); \ + _UNPACKpart_nosize(3,writeW(dest++, 0)); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)cdata - (uptr)data; + +int UNPACK_V3_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(s8); +} + +int UNPACK_V3_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V3_8part(u8); +} + +void UNPACK_V4_32( u32 *dest, u32 *data ) { + writeX(dest++, *data++); + writeY(dest++, *data++); + writeZ(dest++, *data++); + writeW(dest++, *data++); +} + +int UNPACK_V4_32part(u32 *dest, u32 *data, int size) { + u32 *_data = data; + while (size > 0) { + _UNPACKpart(0, writeX(dest++, *data++) ); + _UNPACKpart(1, writeY(dest++, *data++) ); + _UNPACKpart(2, writeZ(dest++, *data++) ); + _UNPACKpart(3, writeW(dest++, *data++) ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + return (uptr)data - (uptr)_data; +} + +#define _UNPACK_V4_16(format) \ + format *sdata = (format*)data; \ + \ + \ + writeX(dest++, *sdata++); \ + writeY(dest++, *sdata++); \ + writeZ(dest++, *sdata++); \ + writeW(dest++, *sdata++); + +void UNPACK_V4_16s(u32 *dest, u32 *data) { + _UNPACK_V4_16(s16); +} + +void UNPACK_V4_16u(u32 *dest, u32 *data) { + _UNPACK_V4_16(u16); +} + +#define _UNPACK_V4_16part(format) \ + format *sdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *sdata++) ); \ + _UNPACKpart(1, writeY(dest++, *sdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *sdata++) ); \ + _UNPACKpart(3, writeW(dest++, *sdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)sdata - (uptr)data; + +int UNPACK_V4_16spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(s16); +} + +int UNPACK_V4_16upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_16part(u16); +} + +#define _UNPACK_V4_8(format) \ + format *cdata = (format*)data; \ + \ + \ + writeX(dest++, *cdata++); \ + writeY(dest++, *cdata++); \ + writeZ(dest++, *cdata++); \ + writeW(dest++, *cdata++); + +void UNPACK_V4_8s(u32 *dest, u32 *data) { + _UNPACK_V4_8(s8); +} + +void UNPACK_V4_8u(u32 *dest, u32 *data) { + _UNPACK_V4_8(u8); +} + +#define _UNPACK_V4_8part(format) \ + format *cdata = (format*)data; \ + while (size > 0) { \ + _UNPACKpart(0, writeX(dest++, *cdata++) ); \ + _UNPACKpart(1, writeY(dest++, *cdata++) ); \ + _UNPACKpart(2, writeZ(dest++, *cdata++) ); \ + _UNPACKpart(3, writeW(dest++, *cdata++) ); \ + if (_vifRegs->offset == 4) _vifRegs->offset = 0; \ + } \ + return (uptr)cdata - (uptr)data; + +int UNPACK_V4_8spart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(s8); +} + +int UNPACK_V4_8upart(u32 *dest, u32 *data, int size) { + _UNPACK_V4_8part(u8); +} + +void UNPACK_V4_5(u32 *dest, u32 *data) { + u16 *sdata = (u16*)data; + u32 rgba; + + rgba = *sdata++; + writeX(dest++, (rgba & 0x001f) << 3); + writeY(dest++, (rgba & 0x03e0) >> 2); + writeZ(dest++, (rgba & 0x7c00) >> 7); + writeW(dest++, (rgba & 0x8000) >> 8); +} + +int UNPACK_V4_5part(u32 *dest, u32 *data, int size) { + u16 *sdata = (u16*)data; + u32 rgba; + + while (size > 0) { + rgba = *sdata++; + _UNPACKpart(0, writeX(dest++, (rgba & 0x001f) << 3); ); + _UNPACKpart(1, writeY(dest++, (rgba & 0x03e0) >> 2); ); + _UNPACKpart(2, writeZ(dest++, (rgba & 0x7c00) >> 7); ); + _UNPACKpart(3, writeW(dest++, (rgba & 0x8000) >> 8); ); + if (_vifRegs->offset == 4) _vifRegs->offset = 0; + } + + return (uptr)sdata - (uptr)data; +} + +static int cycles; +extern int g_vifCycles; +int vifqwc = 0; +int mfifoVIF1rbTransfer() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *src; + + + + /* Check if the transfer should wrap around the ring buffer */ + if ((vif1ch->madr+(vif1ch->qwc << 4)) >= (maddr+msize)) { + int s1 = (maddr+msize) - vif1ch->madr; + int s2 = (vif1ch->qwc << 4) - s1; + + +/*#ifdef GIF_LOG + GIF_LOG("Split\n"); +#endif*/ + /* it does, so first copy 's1' bytes from 'addr' to 'data' */ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + if(vif1.vifstalled == 1){ + ret = VIF1transfer(src+vif1.irqoffset, s1/4-vif1.irqoffset, 0); + }else + ret = VIF1transfer(src, s1>>2, 0); + //assert(ret == 0 ); // vif stall code not implemented + if(ret == -2) return ret; + + if(vif1ch->madr > (maddr+msize)) SysPrintf("Copied too much VIF! %x\n", vif1ch->madr); + /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ + vif1ch->madr = maddr; + src = (u32*)PSM(maddr); + if (src == NULL) return -1; + ret = VIF1transfer(src, s2>>2, 0); + //assert(ret == 0 ); // vif stall code not implemented + } else { + /* it doesn't, so just transfer 'qwc*4' words + from 'vif1ch->madr' to VIF1 */ +/*#ifdef GIF_LOG + GIF_LOG("Straight\n"); +#endif*/ + src = (u32*)PSM(vif1ch->madr); + if (src == NULL) return -1; + if(vif1.vifstalled == 1) + ret = VIF1transfer(src+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + else + ret = VIF1transfer(src, vif1ch->qwc << 2, 0); + if(ret == -2) return ret; + vif1ch->madr = psHu32(DMAC_RBOR) + (vif1ch->madr & psHu32(DMAC_RBSR)); + //assert(ret == 0 ); // vif stall code not implemented + } + + //vif1ch->madr+= (vif1ch->qwc << 4); + + + return ret; +} + +int mfifoVIF1chain() { + u32 maddr = psHu32(DMAC_RBOR); + int msize = psHu32(DMAC_RBSR)+16, ret; + u32 *pMem; + int mfifoqwc = vif1ch->qwc; + + /* Is QWC = 0? if so there is nothing to transfer */ + if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0; + + + if (vif1ch->madr >= maddr && + vif1ch->madr <= (maddr+msize)) { +/*#ifdef GIF_LOG + GIF_LOG("Ring Buffer\n"); +#endif*/ + //SysPrintf("MFIFO QWC %x, VIF QWC %x oldqwc %x\n", vifqwc, vif1ch->qwc, mfifoqwc); + ret = mfifoVIF1rbTransfer(); + //vifqwc -= (mfifoqwc - vif1ch->qwc); + //SysPrintf("end MFIFO QWC %x, VIF QWC %x oldqwc %x taken from vifqwc %x\n", vifqwc, vif1ch->qwc, mfifoqwc, (mfifoqwc - vif1ch->qwc)); + } else { + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) return -1; +/*#ifdef GIF_LOG + GIF_LOG("Other src\n"); +#endif*/ + if(vif1.vifstalled == 1){ + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + }else + ret = VIF1transfer(pMem, vif1ch->qwc << 2, 0); + + //assert(ret == 0 ); // vif stall code not implemented + //vif1ch->madr+= (vif1ch->qwc << 4); + } + + cycles+= (mfifoqwc - vif1ch->qwc) * BIAS; /* guessing */ + + + //vif1ch->qwc = 0; + //if(vif1.vifstalled == 1) SysPrintf("Vif1 MFIFO stalls not implemented\n"); + // + //vif1.vifstalled = 0; + + return ret; +} + +#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) +static int tempqwc = 0; + +void mfifoVIF1transfer(int qwc) { + u32 *ptag; + int id; + int done = 0, ret; + u32 temp = 0; + cycles = 0; + vifqwc += qwc; + g_vifCycles = 0; + + if(qwc > 0){ +#ifdef GIF_LOG + GIF_LOG("Added %x qw to mfifo, total now %x\n", qwc, vifqwc); +#endif + } + + //if(qwc > 0) SysPrintf("Added %x to MFIFO, new total %x\n", qwc, vifqwc); + //if(vifqwc == 0) return; + //if(vif1.vifstalled == 1 && (vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)))return; + /*if(vifqwc == 0) { + //#ifdef PCSX2_DEVBUILD + /*if( vifqwc > 1 ) + SysPrintf("vif mfifo tadr==madr but qwc = %d\n", vifqwc);*/ + //#endif + + //INT(10,50); + /* return; + }*/ + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ +/*#ifdef GIF_LOG + GIF_LOG("mfifoVIF1transfer %x madr %x, tadr %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr); +#endif*/ + + //if((vif1ch->chcr & 0x100) == 0)SysPrintf("MFIFO VIF1 not ready!\n"); + //while (qwc > 0 && done == 0) { + if(vif1ch->qwc == 0){ + if(vif1ch->tadr == spr0->madr) { + + #ifdef PCSX2_DEVBUILD + /*if( vifqwc > 1 ) + SysPrintf("vif mfifo tadr==madr but qwc = %d\n", vifqwc);*/ + #endif + //hwDmacIrq(14); + return; + } + + ptag = (u32*)dmaGetAddr(vif1ch->tadr); + + id = (ptag[0] >> 28) & 0x7; + vif1ch->qwc = (ptag[0] & 0xffff); + vif1ch->madr = ptag[1]; + cycles += 2; + + + //SysPrintf("Tag read MFIFO QWC %x, VIF QWC %x\n", vifqwc, vif1ch->qwc); + if (vif1ch->chcr & 0x40) { + if(vif1.vifstalled == 1 && vif1.stallontag == 1) ret = VIF1transfer(ptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on Stall + else if(vif1.vifstalled == 0)ret = VIF1transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -2) { +#ifdef GIF_LOG + GIF_LOG("MFIFO Stallon tag\n"); +#endif + //SysPrintf("Tag MFIFO QWC %x, VIF QWC %x\n", vifqwc, vif1ch->qwc); + //vif1.vifstalled = 1; + INT(10,cycles+g_vifCycles); + return; //IRQ set by VIFTransfer + } else { + vif1.vifstalled = 0; + vif1.stallontag = 0; + } + } + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); + +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr); +#endif + vifqwc--; + + // if(vif1.vifstalled == 0){ + switch (id) { + case 0: // Refe - Transfer Packet According to ADDR field + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); + vif1.done = 2; //End Transfer + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 1: // CNT - Transfer QWC following the tag. + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 2: // Next - Transfer QWC following tag. TADR = ADDR + temp = vif1ch->madr; //Temporarily Store ADDR + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag + vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 3: // Ref - Transfer QWC from ADDR field + case 4: // Refs - Transfer QWC from ADDR field (Stall Control) + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag + vif1.done = 0; + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + + case 7: // End - Transfer QWC following the tag + vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag + vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data + vif1.done = 2; //End Transfer + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)) { + if(vifqwc < vif1ch->qwc) return; + } + break; + } +#ifdef GIF_LOG + GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr, vifqwc, spr0->madr); + #endif + + //SysPrintf("VIF1 MFIFO qwc %d vif1 qwc %d, madr = %x, tadr = %x\n", qwc, vif1ch->qwc, vif1ch->madr, vif1ch->tadr); + + if((vif1ch->madr & ~psHu32(DMAC_RBSR)) == psHu32(DMAC_RBOR)){ + vifqwc -= vif1ch->qwc; + } + //} + if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { +#ifdef GIF_LOG + GIF_LOG("dmaIrq Set\n"); +#endif + //SysPrintf("mfifoVIF1transfer: dmaIrq Set\n"); + //vifqwc = 0; + vif1.done = 2; + } + //if(vif1ch->qwc == 0 && vifqwc > 0 && done == 0) mfifoVIF1transfer(0); + } + + ret = mfifoVIF1chain(); + if (ret == -1) { + SysPrintf("dmaChain error %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); + vif1.done = 1; + INT(10,cycles+g_vifCycles); + } + if(ret == -2){ + //SysPrintf("VIF MFIFO Stall\n"); + //vif1.vifstalled = 1; +#ifdef GIF_LOG + GIF_LOG("MFIFO Stall\n"); +#endif + INT(10,cycles+g_vifCycles); + return; + } + + + +// if( (cpuRegs.interrupt & (1<<1)) && qwc > 0) { +// SysPrintf("vif1 mfifo interrupt %d\n", qwc); +// } + //} + + /*if(vif1.done == 1) { + vifqwc = 0; + }*/ + + //SysPrintf("vifqwc %x, vif1ch->qwc %x, vifstalled %x, vifdone %x\n", vifqwc, vif1ch->qwc, vif1.vifstalled, vif1.done); + if(vif1.done == 2 && vif1ch->qwc == 0) vif1.done = 1; + if(vifqwc == 0 && vif1.done == 0 && vif1.vifstalled == 0) hwDmacIrq(14); + INT(10,cycles+g_vifCycles); + + // if(vifqwc == 0) vif1Regs->stat&= ~0x1F000000; // FQC=0 + //hwDmacIrq(1); + /*if(((spr0->madr - vif1ch->tadr) >> 4) != vifqwc) SysPrintf("oh noes! madr diff %x, qwc %x\n", ((spr0->madr - vif1ch->tadr) >> 4), vifqwc); + else SysPrintf("Evens up :)\n");*/ + + //if(vifqwc & 0xFFF00000) SysPrintf("Negative QWC?!! %x\n", vifqwc); +#ifdef GIF_LOG + GIF_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x\n", vif1ch->chcr, vif1ch->madr, vif1ch->tadr, vifqwc); +#endif +} + +int vifMFIFOInterrupt() +{ + + if(!(vif1ch->chcr & 0x100)) return 1; + if(vif1.vifstalled == 1 && (vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS))) { + if(vif1.irq) { + vif1Regs->stat|= VIF1_STAT_INT; + hwIntcIrq(5); + --vif1.irq; + } + return 1; + } + + if(vif1.done != 1) { + mfifoVIF1transfer(0); + FreezeMMXRegs(0); + FreezeXMMRegs(0); + if(vifqwc == 0 && vif1.done != 1) return 1; + else { + if((vif1ch->madr == spr0->madr && vif1ch->tadr == spr0->madr) && vif1.done == 0) return 1; + else return 0; + } + } else if(vif1.done != 1) return 1; + + vif1.done = 0; + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); +#ifdef GIF_LOG + GIF_LOG("vif mfifo dma end\n"); +#endif +// vif1ch->chcr &= ~0x100; + vif1Regs->stat&= ~0x1F000000; // FQC=0 +// hwDmacIrq(DMAC_VIF1); +// +// if (vif1.irq > 0) { +// vif1.irq--; +// hwIntcIrq(5); // VIF1 Intc +// } + return 1; +} diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h new file mode 100644 index 0000000..5f687c0 --- /dev/null +++ b/pcsx2/Vif.h @@ -0,0 +1,108 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __VIF_H__ +#define __VIF_H__ + +typedef struct { + u8 cl, wl; + u8 pad[2]; +} vifCycle; + +typedef struct { + u32 stat; + u32 pad0[3]; + u32 fbrst; + u32 pad1[3]; + u32 err; + u32 pad2[3]; + u32 mark; + u32 pad3[3]; + vifCycle cycle; //data write cycle + u32 pad4[3]; + u32 mode; + u32 pad5[3]; + u32 num; + u32 pad6[3]; + u32 mask; + u32 pad7[3]; + u32 code; + u32 pad8[3]; + u32 itops; + u32 pad9[3]; + u32 base; // Not used in VIF0 + u32 pad10[3]; + u32 ofst; // Not used in VIF0 + u32 pad11[3]; + u32 tops; // Not used in VIF0 + u32 pad12[3]; + u32 itop; + u32 pad13[3]; + u32 top; // Not used in VIF0 + u32 pad14[3]; + u32 mskpath3; + u32 pad15[3]; + u32 r0; // row0 register + u32 pad16[3]; + u32 r1; // row1 register + u32 pad17[3]; + u32 r2; // row2 register + u32 pad18[3]; + u32 r3; // row3 register + u32 pad19[3]; + u32 c0; // col0 register + u32 pad20[3]; + u32 c1; // col1 register + u32 pad21[3]; + u32 c2; // col2 register + u32 pad22[3]; + u32 c3; // col3 register + u32 pad23[3]; + u32 offset; // internal UNPACK offset + u32 addr; +} VIFregisters; + +#define vif0Regs ((VIFregisters*)&PS2MEM_HW[0x3800]) +#define vif1Regs ((VIFregisters*)&PS2MEM_HW[0x3c00]) + +void dmaVIF0(); +void dmaVIF1(); +void mfifoVIF1transfer(int qwc); +int VIF0transfer(u32 *data, int size, int istag); +int VIF1transfer(u32 *data, int size, int istag); +int vifMFIFOInterrupt(); + +#ifndef PCSX2_NORECBUILD +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask); +#else +#define SetNewMask 0&& +#endif + +#define XMM_R0 xmm0 +#define XMM_R1 xmm1 +#define XMM_R2 xmm2 +#define XMM_WRITEMASK xmm3 +#define XMM_ROWMASK xmm4 +#define XMM_ROWCOLMASK xmm5 +#define XMM_ROW xmm6 +#define XMM_COL xmm7 + +#define XMM_R3 XMM_COL + + +#endif /* __VIF_H__ */ diff --git a/pcsx2/VifDma.c b/pcsx2/VifDma.c new file mode 100644 index 0000000..3d81d32 --- /dev/null +++ b/pcsx2/VifDma.c @@ -0,0 +1,2456 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Common.h" +#include "Vif.h" +#include "VUmicro.h" +#include "GS.h" + +#include "VifDma.h" + +#include + +#define gif ((DMACh*)&PS2MEM_HW[0xA000]) + +// Extern variables +extern VIFregisters *_vifRegs; +extern vifStruct *_vif; +extern u32* _vifMaskRegs; +extern u32 g_vifRow0[4], g_vifCol0[4], g_vifRow1[4], g_vifCol1[4]; +extern u32* _vifRow, *_vifCol; + +vifStruct vif0, vif1; + +PCSX2_ALIGNED16(u32 g_vif1Masks[64]); +PCSX2_ALIGNED16(u32 g_vif0Masks[64]); +u32 g_vif1HasMask3[4] = {0}, g_vif0HasMask3[4] = {0}; + +// Generic constants +static const unsigned int VIF0intc = 4; +static const unsigned int VIF1intc = 5; +static const unsigned int VIF0dmanum = 0; +static const unsigned int VIF1dmanum = 1; + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +extern HANDLE g_hGsEvent; +#else +extern pthread_cond_t g_condGsEvent; +#endif + +int g_vifCycles = 0; +extern void * memcpy_fast(void *dest, const void *src, size_t n); + +typedef void (*UNPACKFUNCTYPE)( u32 *dest, u32 *data ); +typedef int (*UNPACKPARTFUNCTYPE)( u32 *dest, u32 *data, int size ); +void (*Vif1CMDTLB[82])(); +void (*Vif0CMDTLB[75])(); +int (*Vif1TransTLB[128])(u32 *data, int size); +int (*Vif0TransTLB[128])(u32 *data, int size); + +typedef struct { + UNPACKFUNCTYPE funcU; + UNPACKFUNCTYPE funcS; + UNPACKPARTFUNCTYPE funcUpart; + UNPACKPARTFUNCTYPE funcSpart; + + int bsize; // currently unused + int dsize; // byte size of one channel + int gsize; // size of data in bytes used for each write cycle + int qsize; // used for unpack parts, num of vectors that + // will be decompressed from data for 1 cycle +} VIFUnpackFuncTable; + +/* block size; data size; group size; qword size; */ +#define _UNPACK_TABLE32(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name, UNPACK_##name, \ + UNPACK_##name##part, UNPACK_##name##part, \ + bsize, dsize, gsize, qsize }, + +#define _UNPACK_TABLE(name, bsize, dsize, gsize, qsize) \ + { UNPACK_##name##u, UNPACK_##name##s, \ + UNPACK_##name##upart, UNPACK_##name##spart, \ + bsize, dsize, gsize, qsize }, + +// Main table for function unpacking +static const VIFUnpackFuncTable VIFfuncTable[16] = { + _UNPACK_TABLE32(S_32, 1, 4, 4, 4) // 0x0 - S-32 + _UNPACK_TABLE(S_16, 2, 2, 2, 4) // 0x1 - S-16 + _UNPACK_TABLE(S_8, 4, 1, 1, 4) // 0x2 - S-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x3 + + _UNPACK_TABLE32(V2_32, 24, 4, 8, 2) // 0x4 - V2-32 + _UNPACK_TABLE(V2_16, 12, 2, 4, 2) // 0x5 - V2-16 + _UNPACK_TABLE(V2_8, 6, 1, 2, 2) // 0x6 - V2-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0x7 + + _UNPACK_TABLE32(V3_32, 36, 4, 12, 3) // 0x8 - V3-32 + _UNPACK_TABLE(V3_16, 18, 2, 6, 3) // 0x9 - V3-16 + _UNPACK_TABLE(V3_8, 9, 1, 3, 3) // 0xA - V3-8 + { NULL, NULL, NULL, NULL, 0, 0, 0, 0 }, // 0xB + + _UNPACK_TABLE32(V4_32, 48, 4, 16, 4) // 0xC - V4-32 + _UNPACK_TABLE(V4_16, 24, 2, 8, 4) // 0xD - V4-16 + _UNPACK_TABLE(V4_8, 12, 1, 4, 4) // 0xE - V4-8 + _UNPACK_TABLE32(V4_5, 6, 2, 2, 4) // 0xF - V4-5 +}; + + + +#if !defined(PCSX2_NORECBUILD) + +typedef struct { + // regular 0, 1, 2; mask 0, 1, 2 + UNPACKPARTFUNCTYPE funcU[9], funcS[9]; +} VIFSSEUnpackTable; + +#define DECL_UNPACK_TABLE_SSE(name, sign) \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Regular_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_Mask_2(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1(u32* dest, u32* data, int dmasize); \ +extern int UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2(u32* dest, u32* data, int dmasize); \ + +#define _UNPACK_TABLE_SSE(name, sign) \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Regular_2, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_Mask_2, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_0, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_1, \ + UNPACK_SkippingWrite_##name##_##sign##_WriteMask_2 \ + +#define _UNPACK_TABLE_SSE_NULL \ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + +// Main table for function unpacking +DECL_UNPACK_TABLE_SSE(S_32, u); +DECL_UNPACK_TABLE_SSE(S_16, u); +DECL_UNPACK_TABLE_SSE(S_8, u); +DECL_UNPACK_TABLE_SSE(S_16, s); +DECL_UNPACK_TABLE_SSE(S_8, s); + +DECL_UNPACK_TABLE_SSE(V2_32, u); +DECL_UNPACK_TABLE_SSE(V2_16, u); +DECL_UNPACK_TABLE_SSE(V2_8, u); +DECL_UNPACK_TABLE_SSE(V2_16, s); +DECL_UNPACK_TABLE_SSE(V2_8, s); + +DECL_UNPACK_TABLE_SSE(V3_32, u); +DECL_UNPACK_TABLE_SSE(V3_16, u); +DECL_UNPACK_TABLE_SSE(V3_8, u); +DECL_UNPACK_TABLE_SSE(V3_16, s); +DECL_UNPACK_TABLE_SSE(V3_8, s); + +DECL_UNPACK_TABLE_SSE(V4_32, u); +DECL_UNPACK_TABLE_SSE(V4_16, u); +DECL_UNPACK_TABLE_SSE(V4_8, u); +DECL_UNPACK_TABLE_SSE(V4_16, s); +DECL_UNPACK_TABLE_SSE(V4_8, s); +DECL_UNPACK_TABLE_SSE(V4_5, u); + +static const VIFSSEUnpackTable VIFfuncTableSSE[16] = { + { _UNPACK_TABLE_SSE(S_32, u), _UNPACK_TABLE_SSE(S_32, u) }, + { _UNPACK_TABLE_SSE(S_16, u), _UNPACK_TABLE_SSE(S_16, s) }, + { _UNPACK_TABLE_SSE(S_8, u), _UNPACK_TABLE_SSE(S_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V2_32, u), _UNPACK_TABLE_SSE(V2_32, u) }, + { _UNPACK_TABLE_SSE(V2_16, u), _UNPACK_TABLE_SSE(V2_16, s) }, + { _UNPACK_TABLE_SSE(V2_8, u), _UNPACK_TABLE_SSE(V2_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V3_32, u), _UNPACK_TABLE_SSE(V3_32, u) }, + { _UNPACK_TABLE_SSE(V3_16, u), _UNPACK_TABLE_SSE(V3_16, s) }, + { _UNPACK_TABLE_SSE(V3_8, u), _UNPACK_TABLE_SSE(V3_8, s) }, + { _UNPACK_TABLE_SSE_NULL, _UNPACK_TABLE_SSE_NULL }, + + { _UNPACK_TABLE_SSE(V4_32, u), _UNPACK_TABLE_SSE(V4_32, u) }, + { _UNPACK_TABLE_SSE(V4_16, u), _UNPACK_TABLE_SSE(V4_16, s) }, + { _UNPACK_TABLE_SSE(V4_8, u), _UNPACK_TABLE_SSE(V4_8, s) }, + { _UNPACK_TABLE_SSE(V4_5, u), _UNPACK_TABLE_SSE(V4_5, u) }, +}; + +#endif + + +__forceinline void vif0FLUSH() { + int _cycles; + _cycles = VU0.cycle; + + vu0Finish(); + g_vifCycles+= (VU0.cycle - _cycles)*BIAS; +} + +__forceinline void vif1FLUSH() { + int _cycles; + _cycles = VU1.cycle; + + if( VU0.VI[REG_VPU_STAT].UL & 0x100 ) { + FreezeXMMRegs(1); + do { + Cpu->ExecuteVU1Block(); + } while(VU0.VI[REG_VPU_STAT].UL & 0x100); + +// FreezeXMMRegs(0); +// FreezeMMXRegs(0); + + g_vifCycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +void vifDmaInit() { +} + +__inline static int _limit( int a, int max ) { + return ( a > max ? max : a ); +} + +void DummyExecuteVU1Block(void) +{ + VU0.VI[ REG_VPU_STAT ].UL &= ~0x100; + VU1.vifRegs->stat &= ~4; // also reset the bit (grandia 3 works) +} + +//#define VIFUNPACKDEBUG //enable unpack debugging output + +static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int VIFdmanum){ + const VIFUnpackFuncTable *unpack; + vifStruct *vif; + unpack = &VIFfuncTable[ unpackType ]; +// varLog |= 0x00000400; + if (VIFdmanum == 0) vif = &vif0; + else vif = &vif1; + + switch(unpackType){ + case 0x0: + vif->tag.addr += size*4; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-32 skip, size = %d\n", size); +#endif + break; + case 0x1: + vif->tag.addr += size*8; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-16 skip, size = %d\n", size); +#endif + break; + case 0x2: + vif->tag.addr += size*16; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing S-8 skip, size = %d\n", size); +#endif + break; + case 0x4: + vif->tag.addr += size + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-32 skip, size = %d\n", size); +#endif + break; + case 0x5: + vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-16 skip, size = %d\n", size); +#endif + break; + case 0x6: + vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V2-8 skip, size = %d\n", size); +#endif + break; + case 0x8: + vif->tag.addr += size + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-32 skip, size = %d\n", size); +#endif + break; + case 0x9: + vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-16 skip, size = %d\n", size); +#endif + break; + case 0xA: + vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 4); +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V3-8 skip, size = %d\n", size); +#endif + break; + case 0xC: + vif->tag.addr += size; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-32 skip, size = %d, CL = %d, WL = %d\n", size, vif1Regs->cycle.cl, vif1Regs->cycle.wl); +#endif + break; + case 0xD: + vif->tag.addr += size * 2; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-16 skip, size = %d\n", size); +#endif + break; + case 0xE: + vif->tag.addr += size * 4; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-8 skip, size = %d\n", size); +#endif + break; + case 0xF: + vif->tag.addr += size * 8; +#ifdef VIFUNPACKDEBUG + SysPrintf("Processing V4-5 skip, size = %d\n", size); +#endif + break; + default: + SysPrintf("Invalid unpack type %x\n", unpackType); + break; + } +} + +#ifdef _MSC_VER +//#define __MMX__ +//#define __SSE__ +#include +#include +#endif + +static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdmanum) { + u32 *dest; + unsigned int unpackType; + UNPACKFUNCTYPE func; + UNPACKPARTFUNCTYPE funcP; + const VIFUnpackFuncTable *ft; + vifStruct *vif; + VIFregisters *vifRegs; + VURegs * VU; + u8 *cdata = (u8*)data; + int memsize; + +#ifdef _MSC_VER + _mm_prefetch((char*)data, _MM_HINT_NTA); +#endif + + if (VIFdmanum == 0) { + VU = &VU0; + vif = &vif0; + vifRegs = vif0Regs; + memsize = 0x1000; + assert( v->addr < 0x1000 ); + v->addr &= 0xfff; + } else { + + VU = &VU1; + vif = &vif1; + vifRegs = vif1Regs; + memsize = 0x4000; + assert( v->addr < 0x4000 ); + v->addr &= 0x3fff; + + if( Cpu->ExecuteVU1Block == DummyExecuteVU1Block ) { + // don't process since the frame is dummy + vif->tag.addr += (size / (VIFfuncTable[ vif->cmd & 0xf ].gsize* vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + return; + } + } + + dest = (u32*)(VU->Mem + v->addr); + +#ifdef VIF_LOG + VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); +#endif + +/* if (vifRegs->cycle.cl > vifRegs->cycle.wl) { + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + }*/ +#ifdef _DEBUG + if (v->size != size) { +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: warning v->size != size\n"); +#endif + } + if ((v->addr+size*4) > memsize) { + SysPrintf("*PCSX2*: fixme unpack overflow\n"); + SysPrintf( "VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x\n", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr ); + } +#endif + // The unpack type + unpackType = v->cmd & 0xf; + /*if (v->size != size) { + SysPrintf("*PCSX2*: v->size = %d, size = %d mode = %x\n", v->size, size, unpackType); + }*/ +#ifdef VIFUNPACKDEBUG + if (size == 0) { + SysPrintf("*PCSX2*: Unpack %x with size 0!! v->size = %d cl = %d, wl = %d, mode %d mask %x\n", v->cmd, v->size, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->mode, vifRegs->mask); + //return; + } +#endif + + if(unpackType == 0xC && vifRegs->cycle.cl == vifRegs->cycle.wl) { + // v4-32 + if(vifRegs->mode == 0 && !(vifRegs->code & 0x10000000)){ + if (v->size != size)ProcessMemSkip(size << 2, unpackType, VIFdmanum); + + memcpy_fast((u8*)dest, cdata, size << 2); + size = 0; + return; + } + } + +#ifdef _MSC_VER + _mm_prefetch((char*)data+128, _MM_HINT_NTA); +#endif + _vifRegs = (VIFregisters*)vifRegs; + _vifMaskRegs = VIFdmanum ? g_vif1Masks : g_vif0Masks; + _vif = vif; + _vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; + + // Unpacking + //vif->wl = 0; vif->cl = 0; + + size<<= 2; +#ifdef _DEBUG + memsize = size; +#endif + if( _vifRegs->offset > 0) { + int destinc, unpacksize; +#ifdef VIFUNPACKDEBUG + SysPrintf("aligning packet size = %d offset %d addr %x\n", size, vifRegs->offset, vif->tag.addr); +#endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + if(vifRegs->offset < (u32)ft->qsize){ + unpacksize = (ft->qsize - vifRegs->offset); + } else { + unpacksize = 0; + SysPrintf("Unpack align offset = 0\n"); + } + destinc = 4 - vifRegs->offset; + funcP(dest, (u32*)cdata, unpacksize); + size -= unpacksize*ft->dsize; + cdata += unpacksize*ft->dsize; + + vifRegs->num--; + ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { + if(vifRegs->cycle.cl != vifRegs->cycle.wl){ + dest += ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + destinc; + vif->tag.addr += (destinc<<2) + ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + } else { + dest += destinc; + vif->tag.addr += destinc << 2; + } + vif->cl = 0; + } + else { + dest += destinc; + vif->tag.addr += destinc << 2; + } +#ifdef VIFUNPACKDEBUG + SysPrintf("aligning packet done size = %d offset %d addr %x\n", size, vifRegs->offset, vif->tag.addr); +#endif + //} + if (v->size != ((size>>2) - (unpacksize*ft->dsize)))ProcessMemSkip(size, unpackType, VIFdmanum); + //skipmeminc += (((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2)*4) * skipped; + } else if (v->size != (size>>2))ProcessMemSkip(size, unpackType, VIFdmanum); + + if (vifRegs->cycle.cl >= vifRegs->cycle.wl && size > 0 && vifRegs->num > 0) { // skipping write + +#ifdef _DEBUG + static s_count=0; +#endif + u32* olddest = dest; + ft = &VIFfuncTable[ unpackType ]; + + if( vif->cl != 0 ) { + // continuation from last stream + int incdest; + + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + 4; + while (size >= ft->gsize && vifRegs->num > 0) { + funcP( dest, (u32*)cdata, ft->qsize); + cdata += ft->gsize; + size -= ft->gsize; + + vifRegs->num--; + ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { + dest += incdest; + break; + } + + dest += 4; + } + + // have to update + _vifRow[0] = _vifRegs->r0; + _vifRow[1] = _vifRegs->r1; + _vifRow[2] = _vifRegs->r2; + _vifRow[3] = _vifRegs->r3; + vif->cl = 0; + } + +#if !defined(PCSX2_NORECBUILD) + + if( size > 0 && vifRegs->num > 0 && !(v->addr&0xf) && cpucaps.hasStreamingSIMD2Extensions ) { + const UNPACKPARTFUNCTYPE* pfn; + int writemask; + //static LARGE_INTEGER lbase, lfinal; + //QueryPerformanceCounter(&lbase); + u32 oldcycle = -1; + FreezeXMMRegs(1); + +// u16 tempdata[4] = { 0x8000, 0x7fff, 0x1010, 0xd0d0 }; +// vifRegs->cycle.cl = 4; +// vifRegs->cycle.wl = 1; +// SetNewMask(g_vif1Masks, g_vif1HasMask3, 0x3f, ~0x3f); +// memset(dest, 0xcd, 64*4); +// VIFfuncTableSSE[1].funcS[6](dest, (u32*)tempdata, 8); + +#ifdef _MSC_VER + +#ifdef __x86_64__ + _vifCol = VIFdmanum ? g_vifCol1 : g_vifCol0; +#else + if( VIFdmanum ) { + __asm movaps XMM_ROW, qword ptr [g_vifRow1] + __asm movaps XMM_COL, qword ptr [g_vifCol1] + } + else { + __asm movaps XMM_ROW, qword ptr [g_vifRow0] + __asm movaps XMM_COL, qword ptr [g_vifCol0] + } +#endif + +#else + if( VIFdmanum ) { + __asm__(".intel_syntax\n" + "movaps %%xmm6, qword ptr [%0]\n" + "movaps %%xmm7, qword ptr [%1]\n" + ".att_syntax\n" : :"r"(g_vifRow1), "r"(g_vifCol1) ); + } + else { + __asm__(".intel_syntax\n" + "movaps %%xmm6, qword ptr [%0]\n" + "movaps %%xmm7, qword ptr [%1]\n" + ".att_syntax\n" : : "r"(g_vifRow0), "r"(g_vifCol0) ); + } +#endif + + if( vifRegs->cycle.cl == 0 || vifRegs->cycle.wl == 0 || (vifRegs->cycle.cl == vifRegs->cycle.wl && !(vifRegs->code&0x10000000)) ) { + oldcycle = *(u32*)&vifRegs->cycle; + vifRegs->cycle.cl = vifRegs->cycle.wl = 1; + } + + size = min(size, (int)vifRegs->num*ft->gsize); + pfn = vif->usn ? VIFfuncTableSSE[unpackType].funcU: VIFfuncTableSSE[unpackType].funcS; + writemask = VIFdmanum ? g_vif1HasMask3[min(vifRegs->cycle.wl,3)] : g_vif0HasMask3[min(vifRegs->cycle.wl,3)]; + writemask = pfn[(((vifRegs->code & 0x10000000)>>28)<mode](dest, (u32*)cdata, size); + + if( oldcycle != -1 ) *(u32*)&vifRegs->cycle = oldcycle; + + // if size is left over, update the src,dst pointers + if( writemask > 0 ) { + int left; + left = (size-writemask)/ft->gsize; + cdata += size-writemask; + dest = (u32*)((u8*)dest + ((left/vifRegs->cycle.wl)*vifRegs->cycle.cl + left%vifRegs->cycle.wl)*16); + vifRegs->num -= left; + } + else vifRegs->num -= size/ft->gsize; + + vif->tag.addr += (size / (ft->gsize* vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + + // check for left over write cycles (so can spill to next transfer) + _vif->cl = (size % (ft->gsize*vifRegs->cycle.wl)) / ft->gsize; + + size = writemask; + + _vifRegs->r0 = _vifRow[0]; + _vifRegs->r1 = _vifRow[1]; + _vifRegs->r2 = _vifRow[2]; + _vifRegs->r3 = _vifRow[3]; + //QueryPerformanceCounter(&lfinal); + //((LARGE_INTEGER*)g_nCounters)->QuadPart += lfinal.QuadPart - lbase.QuadPart; + } + else +#endif // !PCSX2_NORECBUILD + { + int incdest; + + // Assigning the normal upack function, the part type is assigned later + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + + incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl)<<2) + 4; + + //SysPrintf("slow vif\n"); + //if(skipped > 0) skipped = 0; + vif->tag.addr += (size / (ft->gsize*vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + + while (size >= ft->gsize && vifRegs->num > 0) { + funcP( dest, (u32*)cdata, ft->qsize); + cdata += ft->gsize; + size -= ft->gsize; + + vifRegs->num--; + //SysPrintf("%d transferred, remaining %d, vifnum %d\n", ft->gsize, size, vifRegs->num); + ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { + dest += incdest; + vif->cl = 0; + } + else + { + dest += 4; + } + } + + // have to update + _vifRow[0] = _vifRegs->r0; + _vifRow[1] = _vifRegs->r1; + _vifRow[2] = _vifRegs->r2; + _vifRow[3] = _vifRegs->r3; + } + + // used for debugging vif +// { +// int i, j, k; +// u32* curdest = olddest; +// FILE* ftemp = fopen("temp.txt", s_count?"a+":"w"); +// fprintf(ftemp, "%x %x %x\n", s_count, size, vif->tag.addr); +// fprintf(ftemp, "%x %x %x\n", vifRegs->code>>24, vifRegs->mode, *(u32*)&vifRegs->cycle); +// fprintf(ftemp, "row: %x %x %x %x\n", _vifRow[0], _vifRow[1], _vifRow[2], _vifRow[3]); +// //fprintf(ftemp, "row2: %x %x %x %x\n", _vifRegs->r0, _vifRegs->r1, _vifRegs->r2, _vifRegs->r3); +// +// for(i = 0; i < memsize; ) { +// for(k = 0; k < vifRegs->cycle.wl; ++k) { +// for(j = 0; j <= ((vifRegs->code>>26)&3); ++j) { +// fprintf(ftemp, "%x ", curdest[4*k+j]); +// } +// } +// +// fprintf(ftemp, "\n"); +// curdest += 4*vifRegs->cycle.cl; +// i += (((vifRegs->code>>26)&3)+1)*ft->dsize*vifRegs->cycle.wl; +// } +// fclose(ftemp); +// } +// s_count++; + + if( size >= ft->dsize && vifRegs->num > 0) { + #ifdef VIF_LOG + VIF_LOG("warning, end with size = %d\n", size); + #endif + // SSE doesn't handle such small data + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; + #ifdef VIFUNPACKDEBUG + SysPrintf("end with size %x dsize = %x last cdata %x\n", size, ft->dsize, (u32)cdata); + #endif + while (size >= ft->dsize) { + /* unpack one qword */ + funcP(dest, (u32*)cdata, 1); + dest += 1; + size -= ft->dsize; + } + #ifdef VIFUNPACKDEBUG + SysPrintf("leftover done, size %d, vifnum %d, addr %x\n", size, vifRegs->num, vif->tag.addr); + #endif + } + + } + else if (vifRegs->cycle.cl < vifRegs->cycle.wl) { /* filling write */ +#ifdef VIF_LOG + VIF_LOG("*PCSX2*: filling write\n"); +#endif + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + funcP = vif->usn ? ft->funcUpart : ft->funcSpart; +#ifdef VIFUNPACKDEBUG + SysPrintf("filling write %d cl %d, wl %d\n", vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl); +#endif + while (size >= ft->gsize || vifRegs->num > 0) { + if (vif->cl == vifRegs->cycle.wl) { + vif->cl = 0; + } + // + if (vif->cl < vifRegs->cycle.cl) { /* unpack one qword */ + funcP( dest, (u32*)cdata, ft->qsize); + cdata += ft->gsize; + size -= ft->gsize; + vif->cl++; + vifRegs->num--; + if (vif->cl == vifRegs->cycle.wl) { + vif->cl = 0; + } + } + else + { + funcP( dest, (u32*)cdata, ft->qsize); + //cdata += ft->gsize; + //size -= ft->gsize; + vif->tag.addr += 16; + vifRegs->num--; + ++vif->cl; + + } + dest += 4; + //++vif->wl; + if(vifRegs->num == 0) break; + } + } + + if(vifRegs->num == 0 && size > 3) SysPrintf("Size = %x, Vifnum = 0!\n", size); +} + +static void vuExecMicro( u32 addr, const unsigned int VIFdmanum ) +{ + int _cycles; + VURegs * VU; + //void (*_vuExecMicro)(); + +// MessageBox(NULL, "3d doesn't work\n", "Query", MB_OK); +// return; + + if (VIFdmanum == 0) { + //_vuExecMicro = Cpu->ExecuteVU0Block; + VU = &VU0; + vif0FLUSH(); + } else { + //_vuExecMicro = Cpu->ExecuteVU1Block; + VU = &VU1; + vif1FLUSH(); + } + + VU->vifRegs->itop = VU->vifRegs->itops; + + if (VIFdmanum == 1) { + /* in case we're handling a VIF1 execMicro + set the top with the tops value */ + VU->vifRegs->top = VU->vifRegs->tops; + + /* is DBF flag set in VIF_STAT? */ + if (VU->vifRegs->stat & 0x80) { + /* it is, so set tops with base + ofst + and clear stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base; + VU->vifRegs->stat &= ~0x80; + } else { + /* it is not, so set tops with base + and set the stat DBF flag */ + VU->vifRegs->tops = VU->vifRegs->base + VU->vifRegs->ofst; + VU->vifRegs->stat |= 0x80; + } + } + + if (VIFdmanum == 0) { + _cycles = VU0.cycle; + vu0ExecMicro(addr); + // too much delay + //g_vifCycles+= (VU0.cycle - _cycles)*BIAS; + } else { + _cycles = VU1.cycle; + vu1ExecMicro(addr); + // too much delay + //g_vifCycles+= (VU1.cycle - _cycles)*BIAS; + } +} + +u8 s_maskwrite[256]; +void vif0Init() +{ + + u32 i; + + for(i = 0; i < 256; ++i ) { + s_maskwrite[i] = ((i&3)==3)||((i&0xc)==0xc)||((i&0x30)==0x30)||((i&0xc0)==0xc0); + } + + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); +} + +__inline void vif0UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + if(vif0Regs->cycle.wl == 0 && vif0Regs->cycle.wl < vif0Regs->cycle.cl){ + SysPrintf("Vif0 CL %d, WL %d\n", vif0Regs->cycle.cl, vif0Regs->cycle.wl); + vif0.cmd &= ~0x7f; + return; + } + + vif0FLUSH(); + + vl = (vif0.cmd ) & 0x3; + vn = (vif0.cmd >> 2) & 0x3; + vif0.tag.addr = (data[0] & 0x3ff) << 4; + vif0.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + vif0Regs->num = vifNum; + + if ( vif0Regs->cycle.wl <= vif0Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif0Regs->cycle.cl * (vifNum / vif0Regs->cycle.wl) + + _limit( vifNum % vif0Regs->cycle.wl, vif0Regs->cycle.cl ); + + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + + vif0.wl = 0; vif0.cl = 0; + vif0.tag.cmd = vif0.cmd; + vif0.tag.size = len; + vif0Regs->offset = 0; +} + +__inline void _vif0mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif0mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU0.Micro + addr, data, size << 2)) { + memcpy_fast(VU0.Micro + addr, data, size << 2); + Cpu->ClearVU0(addr, size); + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int Vif0TransNull(u32 *data, int size){ // Shouldnt go here + SysPrintf("VIF0 Shouldnt go here CMD = %x\n", vif0Regs->code); + vif0.cmd = 0; + return 0; +} +static int Vif0TransSTMask(u32 *data, int size){ // STMASK + SetNewMask(g_vif0Masks, g_vif0HasMask3, data[0], vif0Regs->mask); + vif0Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif0Regs->mask); +#endif + vif0.tag.size = 0; + vif0.cmd = 0; + return 1; +} + +static int Vif0TransSTRow(u32 *data, int size){ // STROW + int ret; + + u32* pmem = &vif0Regs->r0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifRow0+vif0.tag.addr; + assert( vif0.tag.addr < 4 ); + ret = min(4-vif0.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; +#ifdef _MSC_VER + default: __assume(0); +#endif + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + if(vif0.tag.size == 0) vif0.cmd = 0; + + return ret; +} + +static int Vif0TransSTCol(u32 *data, int size){ // STCOL + int ret; + + u32* pmem = &vif0Regs->c0+(vif0.tag.addr<<2); + u32* pmem2 = g_vifCol0+vif0.tag.addr; + ret = min(4-vif0.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; +#ifdef _MSC_VER + default: __assume(0); +#endif + } + vif0.tag.addr += ret; + vif0.tag.size -= ret; + if(vif0.tag.size == 0) vif0.cmd = 0; + return ret; +} + +static int Vif0TransMPG(u32 *data, int size){ // MPG + if (size < vif0.tag.size) { + _vif0mpgTransfer(vif0.tag.addr, data, size); + vif0.tag.addr += size << 2; + vif0.tag.size -= size; + return size; + } else { + int ret; + _vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); + ret = vif0.tag.size; + vif0.tag.size = 0; + vif0.cmd = 0; + return ret; + } +} + +static int Vif0TransUnpack(u32 *data, int size){ // UNPACK + if (size < vif0.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif0.tag, size, VIF0dmanum); + // g_vifCycles+= size >> 1; + //vif0.tag.addr += size << 2; + vif0.tag.size -= size; + return size; + } else { + int ret; + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + //g_vifCycles+= vif0.tag.size >> 1; + ret = vif0.tag.size; + vif0.tag.size = 0; + vif0.cmd = 0; + return ret; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif0 CMD Base Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void Vif0CMDNop(){ // NOP + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTCycl(){ // STCYCL + vif0Regs->cycle.cl = (u8)vif0Regs->code; + vif0Regs->cycle.wl = (u8)(vif0Regs->code >> 8); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDITop(){ // ITOP + vif0Regs->itops = vif0Regs->code & 0x3ff; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTMod(){ // STMOD + vif0Regs->mode = vif0Regs->code & 0x3; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMark(){ // MARK + vif0Regs->mark = (u16)vif0Regs->code; + vif0Regs->stat |= VIF0_STAT_MRK; + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDFlushE(){ // FLUSHE + vif0FLUSH(); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMSCALF(){ //MSCAL/F + vuExecMicro( (u16)(vif0Regs->code) << 3, VIF0dmanum ); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDMSCNT(){ // MSCNT + vuExecMicro( -1, VIF0dmanum ); + vif0.cmd &= ~0x7f; +} + +static void Vif0CMDSTMask(){ // STMASK + vif0.tag.size = 1; +} + +static void Vif0CMDSTRowCol(){// STROW / STCOL + vif0.tag.addr = 0; + vif0.tag.size = 4; +} + +static void Vif0CMDMPGTransfer(){ // MPG + int vifNum; + vif0FLUSH(); + vifNum = (u8)(vif0Regs->code >> 16); + if (vifNum == 0) vifNum = 256; + vif0.tag.addr = (u16)(vif0Regs->code) << 3; + vif0.tag.size = vifNum * 2; +} + +static void Vif0CMDNull(){ // invalid opcode + // if ME1, then force the vif to interrupt + vif0.cmd = (vif0Regs->err&0x40)?0x80:0; + if ((vif0Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif0.cmd ); + vif0Regs->stat |= 1 << 13; + } +} + +int VIF0transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + //vif0.irqoffset = 0; +#ifdef VIF_LOG + VIF_LOG( "VIF0transfer: size %x (vif0.cmd %x)\n", size, vif0.cmd ); +#endif + + //return 0; + if(vif0.savedtag){ + vif0.cmd = vif0.savedtag; + vif0.savedtag = 0; + } + //vif0.irq = 0; + while (size > 0) { + + if((vif0.cmd & 0x70) == 0x50 && istag) { + vif0.savedtag = vif0.cmd; + vif0.cmd = 0; + continue; + } + if((vif0.cmd & 0x70) == 0x40 && istag && size < 2) { + vif0.savedtag = vif0.cmd; + vif0.cmd = 0; + continue; + } + if (vif0.cmd & 0x7f) { + //vif0Regs->stat |= VIF0_STAT_VPS_T; + ret = Vif0TransTLB[(vif0.cmd & 0x7f)](data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif0Regs->stat &= ~VIF0_STAT_VPS_T; + continue; + } + + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + + // if interrupt and new cmd is NOT MARK + if(vif0.irq && ((vif0Regs->code >> 24) & 0x7f) != 0x7 && vif0.tag.size == 0) { + if(vif0.tag.size > 0) SysPrintf("Stall when vif0 tagsize %x code %x\n", vif0.tag.size, vif0.cmd); + break; + } + vif0.cmd = (data[0] >> 24); + vif0Regs->code = data[0]; + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif0.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + //vif0Regs->stat |= VIF0_STAT_VPS_D; + if ((vif0.cmd & 0x60) == 0x60) { + vif0UNPACK(data); + } else { + //vif0CMD(data, size); + Vif0CMDTLB[(vif0.cmd & 0x7f)](); + } + //vif0Regs->stat &= ~VIF0_STAT_VPS_D; + if(vif0.tag.size > 0) vif0Regs->stat |= VIF0_STAT_VPS_W; + ++data; + --size; + ++transferred; + + if ((vif0.cmd & 0x80) && !(vif0Regs->err & 0x1) && ((vif0Regs->code >> 24) & 0x7f) != 0x7 ) { //i bit on vifcode and not masked by VIF0_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif0.cmd, psHu32(INTC_MASK) ); +#endif + + vif0Regs->stat|= VIF0_STAT_VIS; + ++vif0.irq; + vif0.cmd &= 0x7f; + if(istag) vif0.stallontag = 1; + } + if(vif0.irq && ((vif0Regs->code >> 24) & 0x7f) != 0x7 && vif0.tag.size == 0) { + break; + } + } + + // use tag.size because some game doesn't like .cmd + //if( !vif0.cmd ) + if( !vif0.tag.size ) + vif0Regs->stat &= ~VIF0_STAT_VPS_W; + + if (vif0.irq > 0) { + vif0.vifstalled = 1; + + // spiderman doesn't break on qw boundaries + vif0.irqoffset = transferred%4; // cannot lose the offset + + if( istag ) { + return -2; + } + + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + //SysPrintf("Stall on vif0, FromSPR = %x, Vif0MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif0ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + return -2; + } + + if( !istag ) { + transferred = transferred >> 2; + vif0ch->madr+= (transferred << 4); + vif0ch->qwc-= transferred; + } + vif0.vifstalled = 0; + return 0; +} + +int _VIF0chain() { + u32 *pMem; + u32 qwc = vif0ch->qwc; + u32 ret; + + if (vif0ch->qwc == 0 && vif0.vifstalled == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif0ch->madr); + if (pMem == NULL) + return -1; + + if( vif0.vifstalled ) { + ret = VIF0transfer(pMem+vif0.irqoffset, vif0ch->qwc*4-vif0.irqoffset, 0); + } + else { + ret = VIF0transfer(pMem, vif0ch->qwc*4, 0); + } + /*vif0ch->madr+= (vif0ch->qwc << 4); + vif0ch->qwc-= qwc;*/ + g_vifCycles+= (qwc-vif0ch->qwc)*BIAS; /* guessing */ + return ret; +} + + +int _chainVIF0() { + int id; + u32 *ptag; + //int done=0; + int ret; + + ptag = (u32*)dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR + if (ptag == NULL) { //Is ptag empty? + SysPrintf("Vif0 Tag BUSERR\n"); + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif0ch->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + vif0ch->madr = ptag[1]; //MADR = ADDR field + g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + vif0ch->chcr = ( vif0ch->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + + if (vif0ch->chcr & 0x40) { + if(vif0.vifstalled == 1) ret = VIF0transfer(ptag+(2+vif0.irqoffset), 2-vif0.irqoffset, 1); //Transfer Tag on stall + else ret = VIF0transfer(ptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + //SysPrintf("VIF0 Stall on tag %x\n", vif0.irqoffset); + //vif0.vifstalled = 1; + return vif0.done; //IRQ set by VIFTransfer + } + } + + vif0.done |= hwDmacSrcChainWithStack(vif0ch, id); + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + ptag[1], ptag[0], vif0ch->qwc, id, vif0ch->madr, vif0ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif0ch, id); + ret = _VIF0chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + //vif0.vifstalled = 1; + return vif0.done; + } + + //if(id == 7)vif0ch->tadr = vif0ch->madr; + + vif0.vifstalled = 0; + + if ((vif0ch->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF0 TIE\n"); + //SysPrintf( "VIF0dmaIrq Set\n" ); + //vif0ch->qwc = 0; + //vif0Regs->stat|= VIF0_STAT_VIS; //Set the Tag Interrupt flag of VIF0_STAT + vif0.done = 1; + return vif0.done; //End Transfer + } + return vif0.done; //Return Done +} + +static int _vif0Interrupt() { + int ret; + +#ifdef VIF_LOG + VIF_LOG("vif0Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + if(vif0.vifstalled == 1) { + if(vif0.irq) { + vif0Regs->stat|= VIF0_STAT_INT; + hwIntcIrq(VIF0intc); + --vif0.irq; + } + vif0Regs->stat&= ~0xF000000; // FQC=0 + if(vif0.done == 1 && vif0ch->qwc == 0 && vif0.irqoffset == 0) { + //SysPrintf("Vif0 Stall, done = 1 qwc = 0 irqoffset = %x, tell ref\n", vif0.irqoffset); + vif0.vifstalled = 0; + } else + return 1; + } + if (vif0ch->chcr & 0x4 && vif0.done == 0 && vif0.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif0 dma masked\n"); + return 0; + } + + g_vifCycles = 0; + if(vif0ch->qwc > 0) _VIF0chain(); + ret = _chainVIF0(); + INT(0, g_vifCycles); + return 0; + //if(ret!=2) + /*else*/ //return 1; + } + + + + + vif0ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF0); + vif0Regs->stat&= ~0xF000000; // FQC=0 + + return 1; +} + +// Vif1 Data Transfer Table +int (*Vif0TransTLB[128])(u32 *data, int size) = +{ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x7*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0xF*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x17*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x1F*/ + Vif0TransSTMask , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x27*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x2F*/ + Vif0TransSTRow , Vif0TransSTCol , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x37*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x3F*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x47*/ + Vif0TransNull , Vif0TransNull , Vif0TransMPG , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x4F*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x57*/ + Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , Vif0TransNull , /*0x5F*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x67*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , /*0x6F*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , /*0x77*/ + Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransNull , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack , Vif0TransUnpack /*0x7F*/ +}; + +// Vif1 CMD Table +void (*Vif0CMDTLB[75])() = +{ + Vif0CMDNop , Vif0CMDSTCycl , Vif0CMDNull , Vif0CMDNull , Vif0CMDITop , Vif0CMDSTMod , Vif0CMDNull, Vif0CMDMark , /*0x7*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0xF*/ + Vif0CMDFlushE , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull, Vif0CMDMSCALF, Vif0CMDMSCALF, Vif0CMDNull , Vif0CMDMSCNT, /*0x17*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x1F*/ + Vif0CMDSTMask , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x27*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x2F*/ + Vif0CMDSTRowCol, Vif0CMDSTRowCol, Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x37*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x3F*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , Vif0CMDNull , /*0x47*/ + Vif0CMDNull , Vif0CMDNull , Vif0CMDMPGTransfer +}; + +int vif0Interrupt() { + + int ret; + + ret = _vif0Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF0() { + +#ifdef VIF_LOG + VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif0ch->chcr, vif0ch->madr, vif0ch->qwc, + vif0ch->tadr, vif0ch->asr0, vif0ch->asr1 ); +#endif + + /* Check if there is a pending irq */ + /*if (vif0.irq > 0) { + vif0.irq--; + hwIntcIrq(VIF0intc); + return; + }*/ +// if(vif0ch->qwc > 0) { +// _VIF0chain(); +// INT(0, g_vifCycles); +// } + g_vifCycles = 0; + + + vif0Regs->stat|= 0x8000000; // FQC=8 + + if (!(vif0ch->chcr & 0x4) || vif0ch->qwc > 0) { // Normal Mode + vif0ch->chcr &= 0xffff; + if(_VIF0chain() == -2) { + SysPrintf("Stall on normal\n"); + //vif0.vifstalled = 1; + return; + } + vif0.done = 1; + INT(0, g_vifCycles); + return; + } + +/* if (_VIF0chain() != 0) { + INT(0, g_vifCycles); + return; + }*/ + // Chain Mode + vif0.done = 0; + _vif0Interrupt(); + INT(0, g_vifCycles); +} + +void dmaVIF0() +{ + _dmaVIF0(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif0Write32(u32 mem, u32 value) { + if (mem == 0x10003830) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF0_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF0_STAT and set mark with 'value' */ + vif0Regs->stat&= ~VIF0_STAT_MRK; + vif0Regs->mark = value; + } else + if (mem == 0x10003810) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF0_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif0 Reset\n"); + memset(&vif0, 0, sizeof(vif0)); + vif0ch->qwc = 0; //? + psHu64(0x10004000) = 0; + psHu64(0x10004008) = 0; + vif0.done = 1; + vif0Regs->err = 0; + vif0Regs->stat&= ~0xF000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif0Regs->stat |= VIF0_STAT_VFS; + SysPrintf("vif0 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif0Regs->stat |= VIF0_STAT_VSS; + //SysPrintf("Vif0 Stop\n"); + //dmaVIF0(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif0Regs->stat & (VIF0_STAT_INT|VIF0_STAT_VSS|VIF0_STAT_VIS|VIF0_STAT_VFS)) { + cancel = 1; + } + + vif0Regs->stat &= ~(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | + VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); + if (cancel) { + //SysPrintf("VIF0 Stall Resume\n"); + if( vif0.vifstalled ) { + // loop necessary for spiderman + if(vif0.stallontag == 1){ + //SysPrintf("Sorting VIF0 Stall on tag\n"); + _chainVIF0(); + } else _VIF0chain(); + + FreezeXMMRegs(0); + FreezeMMXRegs(0); + INT(0, g_vifCycles); // Gets the timing right - Flatout + } + } + } + } else + if (mem == 0x10003820) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF0_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF0_ERR with 'value' */ + vif0Regs->err = value; + } else{ + SysPrintf("Unknown Vif0 write to %x\n", mem); + if( mem >= 0x10003900 && mem < 0x10003980 ) { + + assert( (mem&0xf) == 0 ); + if( mem < 0x10003940 ) g_vifRow0[(mem>>4)&3] = value; + else g_vifCol0[(mem>>4)&3] = value; + } else psHu32(mem) = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif0Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif0, 0, sizeof(vif0)); + memset(vif0Regs, 0, sizeof(vif0Regs)); + SetNewMask(g_vif0Masks, g_vif0HasMask3, 0, 0xffffffff); + psHu64(0x10004000) = 0; + psHu64(0x10004008) = 0; + vif0.done = 1; + vif0Regs->stat&= ~0xF000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif0Freeze(gzFile f, int Mode) { + gzfreeze(&vif0, sizeof(vif0)); + if (Mode == 0) + SetNewMask(g_vif0Masks, g_vif0HasMask3, vif0Regs->mask, ~vif0Regs->mask); + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + + +void vif1Init() { + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); +} + +__inline void vif1UNPACK(u32 *data) { + int vifNum; + int vl, vn; + int len; + + if(vif1Regs->cycle.wl == 0 && vif1Regs->cycle.wl < vif1Regs->cycle.cl){ + SysPrintf("Vif1 CL %d, WL %d\n", vif1Regs->cycle.cl, vif1Regs->cycle.wl); + vif1.cmd &= ~0x7f; + return; + } + vif1FLUSH(); + + vl = (vif1.cmd ) & 0x3; + vn = (vif1.cmd >> 2) & 0x3; + vif1.tag.addr = (data[0] & 0x3ff); + vif1.usn = (data[0] >> 14) & 0x1; + vifNum = (data[0] >> 16) & 0xff; + if ( vifNum == 0 ) vifNum = 256; + vif1Regs->num = vifNum; + + if ( vif1Regs->cycle.wl <= vif1Regs->cycle.cl ) { + len = ((( 32 >> vl ) * ( vn + 1 )) * vifNum + 31) >> 5; + } else { + int n = vif1Regs->cycle.cl * (vifNum / vif1Regs->cycle.wl) + + _limit( vifNum % vif1Regs->cycle.wl, vif1Regs->cycle.cl ); + len = ( ((( 32 >> vl ) * ( vn + 1 )) * n) + 31 ) >> 5; + } + if ( ( data[0] >> 15) & 0x1 ) { + vif1.tag.addr += vif1Regs->tops; + } + vif1.wl = 0; vif1.cl = 0; + vif1.tag.addr <<= 4; + + vif1.tag.addr &= 0x3fff; + vif1.tag.cmd = vif1.cmd; + vif1.tag.size = len; + vif1Regs->offset = 0; +} + +__inline void _vif1mpgTransfer(u32 addr, u32 *data, int size) { +/* SysPrintf("_vif1mpgTransfer addr=%x; size=%x\n", addr, size); + { + FILE *f = fopen("vu1.raw", "wb"); + fwrite(data, 1, size*4, f); + fclose(f); + }*/ + if (memcmp(VU1.Micro + addr, data, size << 2)) { + memcpy_fast(VU1.Micro + addr, data, size << 2); + Cpu->ClearVU1(addr, size); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 Data Transfer Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static int Vif1TransNull(u32 *data, int size){ // Shouldnt go here + SysPrintf("Shouldnt go here CMD = %x\n", vif1Regs->code); + vif1.cmd = 0; + return 0; +} +static int Vif1TransSTMask(u32 *data, int size){ // STMASK + SetNewMask(g_vif1Masks, g_vif1HasMask3, data[0], vif1Regs->mask); + vif1Regs->mask = data[0]; +#ifdef VIF_LOG + VIF_LOG("STMASK == %x\n", vif1Regs->mask); +#endif + vif1.tag.size = 0; + vif1.cmd = 0; + return 1; +} + +static int Vif1TransSTRow(u32 *data, int size){ + int ret; + + u32* pmem = &vif1Regs->r0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifRow1+vif1.tag.addr; + assert( vif1.tag.addr < 4 ); + ret = min(4-vif1.tag.addr, size); + assert( ret > 0 ); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; +#ifdef _MSC_VER + default: __assume(0); +#endif + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + if(vif1.tag.size == 0) vif1.cmd = 0; + + return ret; +} + +static int Vif1TransSTCol(u32 *data, int size){ + int ret; + + u32* pmem = &vif1Regs->c0+(vif1.tag.addr<<2); + u32* pmem2 = g_vifCol1+vif1.tag.addr; + ret = min(4-vif1.tag.addr, size); + switch(ret) { + case 4: pmem[12] = data[3]; pmem2[3] = data[3]; + case 3: pmem[8] = data[2]; pmem2[2] = data[2]; + case 2: pmem[4] = data[1]; pmem2[1] = data[1]; + case 1: pmem[0] = data[0]; pmem2[0] = data[0]; break; +#ifdef _MSC_VER + default: __assume(0); +#endif + } + vif1.tag.addr += ret; + vif1.tag.size -= ret; + if(vif1.tag.size == 0) vif1.cmd = 0; + return ret; +} + +static int Vif1TransMPG(u32 *data, int size){ + if (size < vif1.tag.size) { + _vif1mpgTransfer(vif1.tag.addr, data, size); + vif1.tag.addr += size << 2; + vif1.tag.size -= size; + return size; + } else { + int ret; + _vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + return ret; + } +} + +static int Vif1TransDirectHL(u32 *data, int size){ + int ret; + + while(gif->chcr & 0x100 && vif1Regs->mskpath3 && vif1.cmd == 0x51){ + gsInterrupt(); // Finish the path3 transfers + if((psHu32(GIF_STAT) & 0xE00) == 0) break; + } + + if (size < vif1.tag.size) { + vif1.tag.size-= size; + ret = size; + } else { + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + } + + if( CHECK_MULTIGS ) { + u8* gsmem = GSRingBufCopy(data, ret<<2, GS_RINGTYPE_P2); + if( gsmem != NULL ) { + memcpy_fast(gsmem, data, ret<<2); + GSRINGBUF_DONECOPY(gsmem, ret<<2); + GSgifTransferDummy(1, data, ret>>2); + } + + if( !CHECK_DUALCORE ) GS_SETEVENT(); + } + else { + FreezeMMXRegs(1); + FreezeXMMRegs(1); + GSGIFTRANSFER2(data, (ret >> 2)); + } + return ret; +} + +static int Vif1TransUnpack(u32 *data, int size){ + if (size < vif1.tag.size) { + /* size is less that the total size, transfer is + 'in pieces' */ + VIFunpack(data, &vif1.tag, size, VIF1dmanum); + // g_vifCycles+= size >> 1; + //vif1.tag.addr += size << 2; + vif1.tag.size -= size; + return size; + } else { + int ret; + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + //g_vifCycles+= vif1.tag.size >> 1; + ret = vif1.tag.size; + vif1.tag.size = 0; + vif1.cmd = 0; + return ret; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 CMD Base Commands +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static void Vif1CMDNop(){ // NOP + vif1.cmd &= ~0x7f; +} +static void Vif1CMDSTCycl(){ // STCYCL + vif1Regs->cycle.cl = (u8)vif1Regs->code; + vif1Regs->cycle.wl = (u8)(vif1Regs->code >> 8); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDOffset(){ // OFFSET + vif1Regs->ofst = vif1Regs->code & 0x3ff; + vif1Regs->stat &= ~0x80; + vif1Regs->tops = vif1Regs->base; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDBase(){ // BASE + vif1Regs->base = vif1Regs->code & 0x3ff; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDITop(){ // ITOP + vif1Regs->itops = vif1Regs->code & 0x3ff; + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDSTMod(){ // STMOD + vif1Regs->mode = vif1Regs->code & 0x3; + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDMskPath3(){ // MSKPATH3 + vif1Regs->mskpath3 = (vif1Regs->code >> 15) & 0x1; + //SysPrintf("VIF MSKPATH3 %x\n", vif1Regs->mskpath3); +#ifdef GSPATH3FIX + + if ( (vif1Regs->code >> 15) & 0x1 ) { + psHu32(GIF_STAT) |= 0x2; + } else { + + //if(gif->chcr & 0x100 && (psHu32(GIF_STAT)& 0xE00)) gsInterrupt(); + if(gif->chcr & 0x100) gsInterrupt(); // Finish the transfer first + psHu32(GIF_STAT) &= ~0x2; + } +#else + if ( vif1Regs->mskpath3 ) { + if(gif->qwc) _GIFchain(); // Finish the transfer first + psHu32(GIF_STAT) |= 0x2; + } else { + psHu32(GIF_STAT) &= ~0x2; + if(gif->qwc) _GIFchain(); // Finish the transfer first + } +#endif + vif1.cmd &= ~0x7f; +} + +static void Vif1CMDMark(){ // MARK + vif1Regs->mark = (u16)vif1Regs->code; + vif1Regs->stat |= VIF1_STAT_MRK; + vif1.cmd &= ~0x7f; +} +static void Vif1CMDFlush(){ // FLUSH/E/A + + if((vif1.cmd & 0x7f) == 0x13) { + //SysPrintf("FlushA\n"); + while((gif->chcr & 0x100)){ + gsInterrupt(); // Finish the path3 transfers + if((psHu32(GIF_STAT) & 0xE00) == 0) break; + } + } + vif1FLUSH(); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDMSCALF(){ //MSCAL/F + vuExecMicro( (u16)(vif1Regs->code) << 3, VIF1dmanum ); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDMSCNT(){ // MSCNT + vuExecMicro( -1, VIF1dmanum ); + vif1.cmd &= ~0x7f; +} +static void Vif1CMDSTMask(){ // STMASK + vif1.tag.size = 1; +} +static void Vif1CMDSTRowCol(){// STROW / STCOL + vif1.tag.addr = 0; + vif1.tag.size = 4; +} + +static void Vif1CMDMPGTransfer(){ // MPG + int vifNum; + vif1FLUSH(); + vifNum = (u8)(vif1Regs->code >> 16); + if (vifNum == 0) vifNum = 256; + vif1.tag.addr = (u16)(vif1Regs->code) << 3; + vif1.tag.size = vifNum * 2; +} +static void Vif1CMDDirectHL(){ // DIRECT/HL + int vifImm; + vifImm = (u16)vif1Regs->code; + if (vifImm == 0) { + vif1.tag.size = 65536 << 2; + } else { + vif1.tag.size = vifImm << 2; + } +} +static void Vif1CMDNull(){ // invalid opcode + // if ME1, then force the vif to interrupt + vif1.cmd = (vif1Regs->err&0x40)?0x80:0; + if ((vif1Regs->err & 0x6) == 0) { //Ignore vifcode and tag mismatch error + SysPrintf( "UNKNOWN VifCmd: %x\n", vif1.cmd ); + vif1Regs->stat |= 1 << 13; + } +} + +// Vif1 Data Transfer Table + +int (*Vif1TransTLB[128])(u32 *data, int size) = +{ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x7*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0xF*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x17*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x1F*/ + Vif1TransSTMask , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x27*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x2F*/ + Vif1TransSTRow , Vif1TransSTCol , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x37*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x3F*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x47*/ + Vif1TransNull , Vif1TransNull , Vif1TransMPG , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x4F*/ + Vif1TransDirectHL, Vif1TransDirectHL, Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x57*/ + Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , Vif1TransNull , /*0x5F*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x67*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , /*0x6F*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , /*0x77*/ + Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransNull , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack , Vif1TransUnpack /*0x7F*/ +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Vif1 CMD Table +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void (*Vif1CMDTLB[82])() = +{ + Vif1CMDNop , Vif1CMDSTCycl , Vif1CMDOffset , Vif1CMDBase , Vif1CMDITop , Vif1CMDSTMod , Vif1CMDMskPath3, Vif1CMDMark , /*0x7*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0xF*/ + Vif1CMDFlush , Vif1CMDFlush , Vif1CMDNull , Vif1CMDFlush, Vif1CMDMSCALF, Vif1CMDMSCALF, Vif1CMDNull , Vif1CMDMSCNT, /*0x17*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x1F*/ + Vif1CMDSTMask , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x27*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x2F*/ + Vif1CMDSTRowCol, Vif1CMDSTRowCol, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x37*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x3F*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x47*/ + Vif1CMDNull , Vif1CMDNull , Vif1CMDMPGTransfer, Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , Vif1CMDNull , /*0x4F*/ + Vif1CMDDirectHL, Vif1CMDDirectHL +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int VIF1transfer(u32 *data, int size, int istag) { + int ret; + int transferred=vif1.vifstalled ? vif1.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) + //vif1.irqoffset = 0; +#ifdef VIF_LOG + VIF_LOG( "VIF1transfer: size %x (vif1.cmd %x)\n", size, vif1.cmd ); +#endif + + //return 0; + if(vif1.savedtag){ + vif1.cmd = vif1.savedtag; + vif1.savedtag = 0; + } + //vif1.irq = 0; + while (size > 0 /*&& transferred < 32*/) { + // Need to split up the transfers else GTA SA will bork - 8QW a time + + if((vif1.cmd & 0x70) == 0x50 && istag) { + vif1.savedtag = vif1.cmd; + vif1.cmd = 0; + continue; + } + if((vif1.cmd & 0x70) == 0x40 && istag && size < 2) { + vif1.savedtag = vif1.cmd; + vif1.cmd = 0; + continue; + } + if (vif1.cmd & 0x7f) { + //vif1Regs->stat |= VIF1_STAT_VPS_T; + ret = Vif1TransTLB[(vif1.cmd & 0x7f)](data, size); + data+= ret; size-= ret; + transferred+= ret; + //vif1Regs->stat &= ~VIF1_STAT_VPS_T; + continue; + } + + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + + // if interrupt and new cmd is NOT MARK + if(vif1.irq && ((vif1Regs->code >> 24) & 0x7f) != 0x7 && vif1.tag.size == 0) { + if(vif1.tag.size > 0) SysPrintf("Stall when vif1 tagsize %x code %x\n", vif1.tag.size, vif1.cmd); + break; + } + + vif1.cmd = (data[0] >> 24); + vif1Regs->code = data[0]; + +#ifdef VIF_LOG + VIF_LOG( "VIFtransfer: cmd %x, num %x, imm %x, size %x\n", vif1.cmd, (data[0] >> 16) & 0xff, data[0] & 0xffff, size ); +#endif + //vif1Regs->stat |= VIF1_STAT_VPS_D; + if ((vif1.cmd & 0x60) == 0x60) { + vif1UNPACK(data); + } else { + //vif1CMD(data, size); + Vif1CMDTLB[(vif1.cmd & 0x7f)](); + } + //vif1Regs->stat &= ~VIF1_STAT_VPS_D; + if(vif1.tag.size > 0) vif1Regs->stat |= VIF1_STAT_VPS_W; + ++data; + --size; + ++transferred; + + if ((vif1.cmd & 0x80) && !(vif1Regs->err & 0x1) && ((vif1Regs->code >> 24) & 0x7f) != 0x7 ) { //i bit on vifcode and not masked by VIF1_ERR +#ifdef VIF_LOG + VIF_LOG( "Interrupt on VIFcmd: %x (INTC_MASK = %x)\n", vif1.cmd, psHu32(INTC_MASK) ); +#endif + /*if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ + SysPrintf("VIF1 Stall on MFIFO, not implemented!\n"); + }*/ + vif1Regs->stat|= VIF1_STAT_VIS; + ++vif1.irq; + vif1.cmd &= 0x7f; + if(istag) vif1.stallontag = 1; + } + if(vif1.irq && ((vif1Regs->code >> 24) & 0x7f) != 0x7 && vif1.tag.size == 0 /*|| (vif1.cmd == 0x6 && !istag)*/) { + // if((vif1.cmd == 0x6 && !istag && vif1Regs->mskpath3 == 0) && (gif->chcr & 0x100)) INT(2, 4); + break; + } + } + + // use tag.size because some game doesn't like .cmd + //if( !vif1.cmd ) + if( !vif1.tag.size ) + vif1Regs->stat &= ~VIF1_STAT_VPS_W; + + if (vif1.irq > 0) { + vif1.vifstalled = 1; + // spiderman doesn't break on qw boundaries + vif1.irqoffset = transferred%4; // cannot lose the offset + if( istag ) { + return -2; + } + + + + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + //SysPrintf("Stall on vif1, FromSPR = %x, Vif1MADR = %x Sif0MADR = %x STADR = %x\n", psHu32(0x1000d010), vif1ch->madr, psHu32(0x1000c010), psHu32(DMAC_STADR)); + return -2; + } + vif1.vifstalled = 0; + vif1.stallontag = 0; + + if( !istag ) { + /*if(transferred & 0x3) vif1.irqoffset = transferred%4; + else vif1.irqoffset = 0;*/ + + transferred = transferred >> 2; + vif1ch->madr+= (transferred << 4); + vif1ch->qwc-= transferred; + + //if(vif1ch->qwc > 0 && size != 0) vif1.vifstalled = 1; + + } + g_vifCycles+= (transferred)*BIAS; /* guessing */ + + return 0; +} + +int _VIF1chain() { + u32 *pMem; + u32 qwc = vif1ch->qwc; + u32 ret; + + + if (vif1ch->qwc == 0 && vif1.vifstalled == 0) return 0; + + pMem = (u32*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) + return -1; + +#ifdef VIF_LOG + VIF_LOG("dmaChain size=%d, madr=%lx, tadr=%lx\n", + vif1ch->qwc, vif1ch->madr, vif1ch->tadr); +#endif + if( vif1.vifstalled ) { + ret = VIF1transfer(pMem+vif1.irqoffset, vif1ch->qwc*4-vif1.irqoffset, 0); + } + else { + ret = VIF1transfer(pMem, vif1ch->qwc*4, 0); + } + /*vif1ch->madr+= (vif1ch->qwc << 4); + vif1ch->qwc-= qwc;*/ + + return ret; +} + +static int prevvifcycles = 0; +static u32* prevviftag = NULL; +u32 *vifptag; +int _chainVIF1() { + int id; + //int done=0; + int ret; + //g_vifCycles = prevvifcycles; + + vifptag = (u32*)dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR + if (vifptag == NULL) { //Is ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vifptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + return -1; //Return -1 as an error has occurred + } + + id = (vifptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag + vif1ch->qwc = (u16)vifptag[0]; //QWC set to lower 16bits of the tag + vif1ch->madr = vifptag[1]; //MADR = ADDR field + g_vifCycles+=1; // Add 1 g_vifCycles from the QW read for the tag + + vif1ch->chcr = ( vif1ch->chcr & 0xFFFF ) | ( (*vifptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + // Transfer dma tag if tte is set + + + + + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + vifptag[1], vifptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + + //} else + + + if (!vif1.done && (psHu32(DMAC_CTRL) & 0xC0) == 0x40 && id == 4) { // STD == VIF1 + vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); + // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall + if( (vif1ch->madr + vif1ch->qwc * 16) >= psHu32(DMAC_STADR) ) { + // stalled + + //SysPrintf("Vif1 Stalling %x, %x, DMA_CTRL = %x\n",vif1ch->madr, psHu32(DMAC_STADR), psHu32(DMAC_CTRL)); + /*prevvifcycles = g_vifCycles; + prevviftag = vifptag;*/ + hwDmacIrq(13); + vif1ch->tadr -= 16; + FreezeMMXRegs(0); + FreezeXMMRegs(0); + return 0; + } + } + prevvifcycles = 0; + + if (vif1ch->chcr & 0x40) { + if(vif1.vifstalled == 1) ret = VIF1transfer(vifptag+(2+vif1.irqoffset), 2-vif1.irqoffset, 1); //Transfer Tag on stall + else ret = VIF1transfer(vifptag+2, 2, 1); //Transfer Tag + if (ret == -1) return -1; //There has been an error + if (ret == -2) { + //SysPrintf("VIF1 Stall on tag %x\n", vif1.irqoffset); + return 0; //IRQ set by VIFTransfer + } + } + if((psHu32(DMAC_CTRL) & 0xC0) != 0x40 || id != 4) + vif1.done |= hwDmacSrcChainWithStack(vif1ch, id); + +#ifdef VIF_LOG + VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n", + vifptag[1], vifptag[0], vif1ch->qwc, id, vif1ch->madr, vif1ch->tadr); +#endif + + //done |= hwDmacSrcChainWithStack(vif1ch, id); + ret = _VIF1chain(); //Transfers the data set by the switch + if (ret == -1) { return -1; } //There's been an error + if (ret == -2) { //IRQ has been set by VifTransfer + return 0; + } + + + if ((vif1ch->chcr & 0x80) && (vifptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG( "dmaIrq Set\n" ); +#endif + //SysPrintf("VIF1 TIE\n"); + //SysPrintf( "VIF1dmaIrq Set\n" ); + //vif1ch->qwc = 0; + //vif1Regs->stat|= VIF1_STAT_VIS; //Set the Tag Interrupt flag of VIF1_STAT + vif1.done = 1; + return 0; //End Transfer + } + return vif1.done; //Return Done +} + +static int _vif1Interrupt() { + +#ifdef VIF_LOG + VIF_LOG("vif1Interrupt: %8.8x\n", cpuRegs.cycle); +#endif + + g_vifCycles = 0; + + if(vif1.vifstalled == 1 && (vif1Regs->stat & (VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS))) { + if(vif1.irq) { + vif1Regs->stat|= VIF1_STAT_INT; + hwIntcIrq(VIF1intc); + --vif1.irq; + } + + vif1Regs->stat&= ~0x1F000000; // FQC=0 + // One game doesnt like vif stalling at end, cant remember what. + if(vif1ch->qwc > 0 || vif1.irqoffset != 0) return 1; + } + if((vif1ch->chcr & 0x100) == 0) { + prevviftag = NULL; + prevvifcycles = 0; + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); + vif1Regs->stat&= ~0x1F000000; // FQC=0 + return 1; + } + /*if(vif1ch->qwc > 0){ + _VIF1chain(); + INT(1, g_vifCycles); + return 0; + }*/ + if (vif1ch->chcr & 0x4 && vif1.done == 0 && vif1.vifstalled == 0) { + + if( !(psHu32(DMAC_CTRL) & 0x1) ) { + SysPrintf("vif1 dma masked\n"); + return 0; + } + + g_vifCycles = 0; + + _chainVIF1(); + INT(1, g_vifCycles); + return 0; + } + + + + //if((gif->chcr & 0x100) && vif1Regs->mskpath3) gsInterrupt(); + prevviftag = NULL; + prevvifcycles = 0; + vif1ch->chcr &= ~0x100; + hwDmacIrq(DMAC_VIF1); + vif1Regs->stat&= ~0x1F000000; // FQC=0 + + return 1; +} + +int vif1Interrupt() { + + int ret; + + ret = _vif1Interrupt(); + //FreezeXMMRegs(0); + //FreezeMMXRegs(0); + + return ret; +} + +void _dmaVIF1() { + +#ifdef VIF_LOG + VIF_LOG("dmaVIF1 chcr = %lx, madr = %lx, qwc = %lx\n" + " tadr = %lx, asr0 = %lx, asr1 = %lx\n", + vif1ch->chcr, vif1ch->madr, vif1ch->qwc, + vif1ch->tadr, vif1ch->asr0, vif1ch->asr1 ); +#endif + + /*if ((psHu32(DMAC_CTRL) & 0xC0)) { + SysPrintf("DMA Stall Control %x\n",(psHu32(DMAC_CTRL) & 0xC0)); + }*/ + /* Check if there is a pending irq */ + /*if (vif1.irq > 0) { + vif1.irq--; + hwIntcIrq(VIF1intc); + return; + }*/ +// if(vif1ch->qwc > 0) { +// _VIF1chain(); +// INT(1, g_vifCycles); +// } + vif1.done = 0; + g_vifCycles = 0; + + /*if( prevvifcycles != 0 ) { + int stallret = 0; + assert( prevviftag != NULL ); + + vifptag = prevviftag; + // transfer interrupted, so continue + //_VIF1chain(); + _chainVIF1(); + + if (vif1ch->chcr & 0x80 && vifptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag +#ifdef VIF_LOG + VIF_LOG("dmaIrq Set\n"); +#endif + vif1.done = 1; + INT(1, g_vifCycles); + return; + } + //vif1.done = 1; + INT(1, g_vifCycles); + return; + }*/ + + if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) { // VIF MFIFO + vifMFIFOInterrupt(); + return; + } + +#ifdef PCSX2_DEVBUILD + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { // STD == VIF1 + //SysPrintf("VIF Stall Control Source = %x, Drain = %x\n", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3); + //return; + } +#endif + + + vif1Regs->stat|= 0x10000000; // FQC=16 + + if (!(vif1ch->chcr & 0x4) || vif1ch->qwc > 0) { // Normal Mode + vif1ch->chcr &= 0xffff; + if ((psHu32(DMAC_CTRL) & 0xC0) == 0x40) { + SysPrintf("DMA Stall Control on VIF1 normal\n"); + } + if ((vif1ch->chcr & 0x1)) { // to Memory + if(_VIF1chain() == -2) { + SysPrintf("Stall on normal\n"); + vif1.vifstalled = 1; + return; + } + INT(1, g_vifCycles); + } else { // from Memory + + if( CHECK_MULTIGS ) { + u8* pTempMem, *pEndMem; + + u8* pMem = GSRingBufCopy(NULL, 0, GS_RINGTYPE_VIFFIFO); + *(u32*)(pMem-16) = GS_RINGTYPE_VIFFIFO|(vif1ch->qwc<<16); // hack + *(u32*)(pMem-12) = vif1ch->madr; + *(u32*)(pMem-8) = cpuRegs.cycle; + + // touch all the pages to make sure they are in memory + pTempMem = dmaGetAddr(vif1ch->madr); + pEndMem = (u8*)((uptr)(pTempMem + vif1ch->qwc*16 + 0xfff)&~0xfff); + pTempMem = (u8*)((uptr)pTempMem&~0xfff); + while(pTempMem < pEndMem ) { + pTempMem[0] = 0; + pTempMem += 0x1000; + } + + GSRINGBUF_DONECOPY(pMem, 0); + + if( !CHECK_DUALCORE ) + GS_SETEVENT(); + + // wait is, the safest option + } + else { + + int size; + u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); + if (pMem == NULL) { //Is ptag empty? + SysPrintf("Vif1 Tag BUSERR\n"); + psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + vif1.done = 1; + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, g_vifCycles); + return; //Return -1 as an error has occurred + } + + if( GSreadFIFO2 == NULL ) { + for (size=vif1ch->qwc; size>0; --size) { + if (size > 1) GSreadFIFO((u64*)&PS2MEM_HW[0x5000]); + pMem[0] = psHu64(0x5000); + pMem[1] = psHu64(0x5008); pMem+= 2; + } + } + else { + GSreadFIFO2(pMem, vif1ch->qwc); + + // set incase read + psHu64(0x5000) = pMem[2*vif1ch->qwc-2]; + psHu64(0x5008) = pMem[2*vif1ch->qwc-1]; + } + + + vif1Regs->stat&= ~0x1f000000; + vif1ch->qwc = 0; + INT(1, g_vifCycles); + } + } + vif1.done = 1; + return; + } + +/* if (_VIF1chain() != 0) { + INT(1, g_vifCycles); + return; + }*/ + + // Chain Mode + vif1.done = 0; + INT(1, g_vifCycles); +} + +void dmaVIF1() +{ + _dmaVIF1(); + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +void vif1Write32(u32 mem, u32 value) { + if (mem == 0x10003c30) { // MARK +#ifdef VIF_LOG + VIF_LOG("VIF1_MARK write32 0x%8.8x\n", value); +#endif + /* Clear mark flag in VIF1_STAT and set mark with 'value' */ + vif1Regs->stat&= ~VIF1_STAT_MRK; + vif1Regs->mark = value; + } else + if (mem == 0x10003c10) { // FBRST +#ifdef VIF_LOG + VIF_LOG("VIF1_FBRST write32 0x%8.8x\n", value); +#endif + if (value & 0x1) { + /* Reset VIF */ + //SysPrintf("Vif1 Reset\n"); + memset(&vif1, 0, sizeof(vif1)); + vif1ch->qwc = 0; //? + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->err = 0; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + if (value & 0x2) { + /* Force Break the VIF */ + /* I guess we should stop the VIF dma here + but not 100% sure (linuz) */ + vif1Regs->stat |= VIF1_STAT_VFS; + SysPrintf("vif1 force break\n"); + } + if (value & 0x4) { + /* Stop VIF */ + /* Not completly sure about this, can't remember what game + used this, but 'draining' the VIF helped it, instead of + just stoppin the VIF (linuz) */ + vif1Regs->stat |= VIF1_STAT_VSS; + //SysPrintf("Vif1 Stop\n"); + //dmaVIF1(); // Drain the VIF --- VIF Stops as not to outstrip dma source (refraction) + //FreezeXMMRegs(0); + } + if (value & 0x8) { + int cancel = 0; + + /* Cancel stall, first check if there is a stall to cancel, + and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + cancel = 1; + } + + vif1Regs->stat &= ~(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | + VIF1_STAT_INT | VIF1_STAT_ER0 | VIF1_STAT_ER1); + if (cancel) { + //SysPrintf("VIF1 Stall Resume\n"); + if( vif1.vifstalled ) { + // loop necessary for spiderman + if((psHu32(DMAC_CTRL) & 0xC) == 0x8){ + //vif1.vifstalled = 0; + //SysPrintf("MFIFO Stall\n"); + INT(10, 0); + }else { + if(vif1.stallontag == 1){ + //SysPrintf("Sorting VIF Stall on tag\n"); + _chainVIF1(); + } else _VIF1chain(); + //vif1.vifstalled = 0; + FreezeXMMRegs(0); + FreezeMMXRegs(0); + INT(1, g_vifCycles); // Gets the timing right - Flatout + } + } + } + } + } else + if (mem == 0x10003c20) { // ERR +#ifdef VIF_LOG + VIF_LOG("VIF1_ERR write32 0x%8.8x\n", value); +#endif + /* Set VIF1_ERR with 'value' */ + vif1Regs->err = value; + } else + if (mem == 0x10003c00) { // STAT +#ifdef VIF_LOG + VIF_LOG("VIF1_STAT write32 0x%8.8x\n", value); +#endif + +#ifdef PCSX2_DEVBUILD + /* Only FDR bit is writable, so mask the rest */ + if( (vif1Regs->stat & VIF1_STAT_FDR) ^ (value & VIF1_STAT_FDR) ) { + // different so can't be stalled + if (vif1Regs->stat & (VIF1_STAT_INT|VIF1_STAT_VSS|VIF1_STAT_VIS|VIF1_STAT_VFS)) { + SysPrintf("changing dir when vif1 fifo stalled\n"); + } + } +#endif + + vif1Regs->stat = (vif1Regs->stat & ~VIF1_STAT_FDR) | (value & VIF1_STAT_FDR); + if (vif1Regs->stat & VIF1_STAT_FDR) { + vif1Regs->stat|= 0x01000000; + } else { + vif1ch->qwc = 0; + vif1.vifstalled = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + } + } + else + if (mem == 0x10003c50) { // MODE + vif1Regs->mode = value; + } + else { + SysPrintf("Unknown Vif1 write to %x\n", mem); + if( mem >= 0x10003d00 && mem < 0x10003d80 ) { + assert( (mem&0xf) == 0 ); + if( mem < 0x10003d40) g_vifRow1[(mem>>4)&3] = value; + else g_vifCol1[(mem>>4)&3] = value; + } else psHu32(mem) = value; + } + + /* Other registers are read-only so do nothing for them */ +} + +void vif1Reset() { + /* Reset the whole VIF, meaning the internal pcsx2 vars + and all the registers */ + memset(&vif1, 0, sizeof(vif1)); + memset(vif1Regs, 0, sizeof(vif1Regs)); + SetNewMask(g_vif1Masks, g_vif1HasMask3, 0, 0xffffffff); + psHu64(0x10005000) = 0; + psHu64(0x10005008) = 0; + vif1.done = 1; + vif1Regs->stat&= ~0x1F000000; // FQC=0 + FreezeXMMRegs(0); + FreezeMMXRegs(0); +} + +int vif1Freeze(gzFile f, int Mode) { + gzfreeze(&vif1, sizeof(vif1)); + if (Mode == 0) + SetNewMask(g_vif1Masks, g_vif1HasMask3, vif1Regs->mask, ~vif1Regs->mask); + + return 0; +} diff --git a/pcsx2/VifDma.h b/pcsx2/VifDma.h new file mode 100644 index 0000000..694e949 --- /dev/null +++ b/pcsx2/VifDma.h @@ -0,0 +1,118 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIFDMA_H__ +#define __VIFDMA_H__ + +typedef struct { + int addr; + int size; + int cmd; + u16 wl; + u16 cl; +} vifCode; + +// NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito +typedef struct { + vifCode tag; + int cmd; + int irq; + int cl; + int wl; + u8 usn; + u8 done; + u8 vifstalled; + u8 stallontag; + u8 irqoffset; // 32bit offset where next vif code is + u32 savedtag; +} vifStruct; + +extern vifStruct vif0, vif1; + +#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000]) +#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000]) + +void UNPACK_S_32( u32 *dest, u32 *data ); +int UNPACK_S_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_S_16u( u32 *dest, u32 *data ); +int UNPACK_S_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_16s( u32 *dest, u32 *data ); +int UNPACK_S_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_S_8u( u32 *dest, u32 *data ); +int UNPACK_S_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_S_8s( u32 *dest, u32 *data ); +int UNPACK_S_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_32( u32 *dest, u32 *data ); +int UNPACK_V2_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_16u( u32 *dest, u32 *data ); +int UNPACK_V2_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_16s( u32 *dest, u32 *data ); +int UNPACK_V2_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V2_8u( u32 *dest, u32 *data ); +int UNPACK_V2_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V2_8s( u32 *dest, u32 *data ); +int UNPACK_V2_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_32( u32 *dest, u32 *data ); +int UNPACK_V3_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_16u( u32 *dest, u32 *data ); +int UNPACK_V3_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_16s( u32 *dest, u32 *data ); +int UNPACK_V3_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V3_8u( u32 *dest, u32 *data ); +int UNPACK_V3_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V3_8s( u32 *dest, u32 *data ); +int UNPACK_V3_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_32( u32 *dest, u32 *data ); +int UNPACK_V4_32part( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_16u( u32 *dest, u32 *data ); +int UNPACK_V4_16upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_16s( u32 *dest, u32 *data ); +int UNPACK_V4_16spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_8u( u32 *dest, u32 *data ); +int UNPACK_V4_8upart( u32 *dest, u32 *data, int size ); +void UNPACK_V4_8s( u32 *dest, u32 *data ); +int UNPACK_V4_8spart( u32 *dest, u32 *data, int size ); + +void UNPACK_V4_5( u32 *dest, u32 *data ); +int UNPACK_V4_5part( u32 *dest, u32 *data, int size ); + +void vifDmaInit(); +void vif0Init(); +void vif1Init(); +int vif0Interrupt(); +int vif1Interrupt(); + +void vif0Write32(u32 mem, u32 value); +void vif1Write32(u32 mem, u32 value); + +void vif0Reset(); +void vif1Reset(); +int vif0Freeze(gzFile f, int Mode); +int vif1Freeze(gzFile f, int Mode); + +#endif diff --git a/pcsx2/build.sh b/pcsx2/build.sh new file mode 100644 index 0000000..a71496e --- /dev/null +++ b/pcsx2/build.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +echo --------------- +echo Building Pcsx2 +echo --------------- + +if [ $# -gt 0 ] && [ $1 = "all" ] +then + +aclocal +automake +autoconf +./configure ${PCSX2OPTIONS} +make clean +make install + +else + +make $@ + +#if [ $? -ne 0 ] +#then +#exit 1 +#fi + +#if [ $# -eq 0 ] || [ $1 != "clean" ] +#then +#make install +#fi + +fi + +if [ $? -ne 0 ] +then +exit 1 +fi diff --git a/pcsx2/cheatscpp.h b/pcsx2/cheatscpp.h new file mode 100644 index 0000000..0918189 --- /dev/null +++ b/pcsx2/cheatscpp.h @@ -0,0 +1,31 @@ +#ifndef CHEATSCPP_H_INCLUDED +#define CHEATSCPP_H_INCLUDED + +class Group +{ +public: + string title; + bool enabled; + int parentIndex; + + Group(int nParent,bool nEnabled, string &nTitle); + +}; + +class Patch +{ +public: + string title; + int group; + bool enabled; + int patchIndex; + + Patch(int patch, int grp, bool en, string &ttl); + + Patch operator =(const Patch&p); +}; + +extern vector groups; +extern vector patches; + +#endif//CHEATSCPP_H_INCLUDED diff --git a/pcsx2/configure.ac b/pcsx2/configure.ac new file mode 100644 index 0000000..6d435c1 --- /dev/null +++ b/pcsx2/configure.ac @@ -0,0 +1,134 @@ +AC_INIT(pcsx2,0.9.3,zerofrog@gmail.com) + +AM_INIT_AUTOMAKE(pcsx2,0.9.3) + +AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) + +AC_PROG_RANLIB + +dnl necessary for compiling assembly +AM_PROG_AS + +CFLAGS= +CPPFLAGS= +CXXFLAGS= +CCASFLAGS= + +dnl Check for debug build +AC_MSG_CHECKING(debug build) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), + debug=$enableval,debug=no) +if test "x$debug" == xyes +then + AC_DEFINE(_DEBUG,1,[_DEBUG]) + CFLAGS+=" -g " + CPPFLAGS+=" -g " + CXXFLAGS+=" -g " + CCASFLAGS+=" -D_DEBUG -g " + MYOBJDIR="Debug" +else + AC_DEFINE(NDEBUG,1,[NDEBUG]) + CFLAGS+=" -O2 -fomit-frame-pointer " + CPPFLAGS+=" -O2 -fomit-frame-pointer " + CXXFLAGS+=" -O2 -fomit-frame-pointer " + MYOBJDIR="Release" +fi +AC_MSG_RESULT($debug) + +AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) + +dnl Check for dev build +AC_MSG_CHECKING(for development build) +AC_ARG_ENABLE(devbuild, AC_HELP_STRING([--enable-devbuild], [Special Build for developers that simplifies testing and adds extra checks]), + devbuild=$enableval,devbuild=no) +if test "x$devbuild" == xyes +then + AC_DEFINE(PCSX2_DEVBUILD,1,[PCSX2_DEVBUILD]) + MYOBJDIR=$MYOBJDIR"Dev" +fi +AC_MSG_RESULT($devbuild) + +dnl Check for virtual memory build +AC_MSG_CHECKING(for virtual memory build) +AC_ARG_ENABLE(vmbuild, AC_HELP_STRING([--enable-vmbuild], [Adds low level virtual memory support to run pcsx2 faster]), + vmbuild=$enableval,vmbuild=no) +if test "x$vmbuild" == xyes +then + AC_DEFINE(PCSX2_VIRTUAL_MEM,1,[PCSX2_VIRTUAL_MEM]) + MYOBJDIR=$MYOBJDIR"VM" +fi +AC_MSG_RESULT($vmbuild) + +dnl Check for recompilation +AC_MSG_CHECKING(for using platform dependent recompilers) +AC_ARG_ENABLE(recbuild, AC_HELP_STRING([--disable-recbuild], [Disable all architecture dependent recompilers]), + recbuild=$enableval,recbuild=yes) +if test "x$recbuild" == xno +then + AC_DEFINE(PCSX2_NORECBUILD,1,[PCSX2_NORECBUILD]) +fi +AC_MSG_RESULT($recbuild) +AM_CONDITIONAL(RECBUILD, test x$recbuild = xyes) + +dnl Check for 64bit CPU +AC_MSG_CHECKING(for a x86-64 CPU) +dnl if test "$build_os" == "target_os" +dnl then +AC_TRY_RUN([ +int main() +{ +int a = 0; +int*pa = &a; +asm(".intel_syntax\n" + "mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + ".att_syntax\n" + : : "r"(pa) : "%rax"); +return 0; +} +],cpu64=yes,cpu64=no,) +dnl else +dnl cpu64=no +dnl fi +if test "x$cpu64" == xyes +then +AC_DEFINE(__x86_64__,1,[__x86_64__]) +fi +AC_MSG_RESULT($cpu64) +AM_CONDITIONAL(X86_64, test x$cpu64 = xyes) + +dnl gtk +AC_MSG_CHECKING(gtk+) +AC_CHECK_PROG(GTK_CONFIG, pkg-config, pkg-config) +LIBS+=$(pkg-config --libs gtk+-2.0 gthread-2.0) + +dnl AC_CHECK_LIB(pthread,main,[LIBS="$LIBS -lpthread"]) +AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"]) +AC_CHECK_LIB(z,main,[LIBS="$LIBS -lz"]) + +AC_CHECK_HEADER([libintl.h], [AC_DEFINE(ENABLE_NLS,1,[__x86_64__])]) + +AC_OUTPUT([ + Makefile + DebugTools/Makefile + Linux/Makefile + IPU/Makefile + IPU/mpeg2lib/Makefile + RDebug/Makefile + tinyxml/Makefile + x86/Makefile + x86/ix86/Makefile + zlib/Makefile + ]) + +dnl bindir = pcsx2exe + +echo "Configuration:" +echo " Target system type: $target" +echo " x86-64 build? $cpu64" +echo " Debug build? $debug" +echo " Dev build? $devbuild" +echo " Recompilers enabled? $recbuild" +echo " Virtual memory build? $vmbuild" diff --git a/pcsx2/depcomp b/pcsx2/depcomp new file mode 100644 index 0000000..88b3a13 --- /dev/null +++ b/pcsx2/depcomp @@ -0,0 +1,529 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/pcsx2/install-sh b/pcsx2/install-sh new file mode 100644 index 0000000..4d4a951 --- /dev/null +++ b/pcsx2/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/pcsx2/missing b/pcsx2/missing new file mode 100644 index 0000000..894e786 --- /dev/null +++ b/pcsx2/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/pcsx2/mkinstalldirs b/pcsx2/mkinstalldirs new file mode 100644 index 0000000..259dbfc --- /dev/null +++ b/pcsx2/mkinstalldirs @@ -0,0 +1,158 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2005-06-29.22 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/pcsx2/pcsxAbout.bmp b/pcsx2/pcsxAbout.bmp new file mode 100644 index 0000000000000000000000000000000000000000..da33bb08f4a3c365d835b0972a7dfbc43f8b01a2 GIT binary patch literal 251192 zcmce<2bf*QaVDz$-m@%<0U(ic1_Ff6XIuWB6)Z}& zf+bNDGjg68OaulwgF(#506~HPk<-lFI5~$q=lxaHU8l}DcZQI@eT%Qztgim6y1M$D z|Mm&@&Tst3M?U)BK1Kf?!hg5ozwiIMPkrhP{{QbjH6FG6yXE>%eTx3`|AKWROd08A z5t2=4R0%`htP$C0LKtHr06U^LbO3QEL&OZNRSd>m- zsEI1Axi@j)#kzcNm@cak&syt1;>03FwgAY|yrpT~%xvlS^zs|i%Wq1ryd||_bZRA+ zH50Sdvvcd`<<`y3uA7rvHz!*?D_b)Qb$!k4SJ&NDxBi~G+I#Ca+*iNh{)SBtG;De> zwdLW|)<;s?9!+igTzdOs=^anxcRkj!`;q3|kF@N0q<72Apynoj2-%P{FpbIziWHcF zp_ei;2p3nuzAL_(YA!>>YW0~E#8B|+T$E_C5H6y^L{OMVYUE^Sd)2cDf>(eDv8Eyg zEKOjf*xs0|-c(QzRwK%!H?N^td)duJ%&j-kFf7ax05MxN^j+n@7LNRR|GqpN>~34m&k6j}6Yizb)8l22!rd^)q}*V2nW zlUi~;mm5+`Zb&V?DZS#B^vY40wG*=yQ*sqkvK5oF<&$#d6Vv5W>MG~fRozOZdVc-7 z+w0fe(NKF=YQx7ep6LB+3Afgo}v%c3k=TN5!%){0RN&N&YkkCa zEy(Ad1}2}>=KE7y9!PC{D6{RM<{kI7>_oZ0W!D3(yB;XijC99RI2TTuhAM*eCgtR0 z)iBnjwlP;$uU%rBY+A4`qJnL&mE%b^6I2+SB>g0Z5R9w+!8wer`d2}NA**7MC{hF& z3o^hukSL|8vKm^AmC1=5b^dUT_3DVC7reUFUeS}QXwqEME6Issyr5QAP|sGGl;KT= zR<}hkoYJIzD2)znCuQZBp$ovTh4iWtLRf4b7%woGs1SE9CbBvvdqbJfSOzwfTODO6 zfaDXsRX4QN-rBI}vki-{XWC&30{^VIIlXeUl+=n*nbl*mYbWt8XmX}}>eY(5L_SsX zJ^$QUzwXZZ+PlC%e)ID{ddq{@{N%SkM9f3v^I*&FhugQ`=?@`ucoYp%r&+XjsQl=} zMNlVUGn&9*{Ah}tZS(*TrI<^EL&a&4F`2>};y6)nF+k|SA3354@&53T_|Y47nX%mL z%qloP35||eRB+)LE14AZI=iHy^cL4kkY;u|ktCip*SRAq6f_v^5)GQ7;o7-18tT;| zo^8{*6)V*USWQH4F(Ru*1w}$rR4J<|y#g?>a0;qaL4#3^2)3yj6~szyB|NRIttzbm zfMWb{=vFP-CCc*ueQ?M8;Pls9w?5dg__Gae=W}Cf*~s*&(P0rHT0J&XHZfa1xuIg_ zm5O=bpQ}~#uU6kyS93=l?|;d8lR2qurZl_%jY+ z7YoV8?_`~k;H9ax?+w?&CPZWfC%YsJs|VQoj6`UicmNHmdI;BrpTC;+5MxHEx^579 z7xQO=s_Uqzi4zQ-G|_<~8jDmv)rGhn7yecgWvNT1oT`_!7m{+=Nh!ZjNvP+0G z1cs7c z>c=TfsM-ZXCv&eL#k2Z!qiD=F0HcH-F$|q}WNZla93p)fsv%c!u5(mZtVeIfuMe&t z6MX!)!TEopLKO5cZa&jJXHPy+VQgyUnAGaAb!9WIfPY+}3$d%!^XqC*ZmnN8zoGVa zDjV)dZN8_jdR~6ZovnKwMgjS>?YbYAdv1;rn*=E_Q>Z2zwo7F6T0vzoq^1;gqQ`~` z>Ot0Bnr2)$k)o;7I8{#rsUIGTFeu)SG!-BAUKdnYS~mwblHbt&BQUrcg# z>2;0EuWMcX+5SzFgX$ZYrFj$`P93TSo=MhX@UF`TCbkg|HUlPjac(mSSq(+6O(z(D z?ILhAQQGTrq5=EVg#d30jeZEwq6>T#QcfVNlr~oigu}g6)eokMFCI_ zgDKjje!S3KdR=ZA$mhDuQYsL%pqW~NrvTTrzwsM=?|r#|j|TA>^K6e6D-R!@41b2!8aF0f=xR@WN}f~-xEwaK2Vr72x@EY_n}01gH~ z5^1fH0Pjabbv{{7NB zE(k_;Fzdv~8lH>LbcvJD96qlb#8%{k{~lcaPH^FyRL*^)jx^>r^}B{lat_-;SfF>90|o>Y$IUt<8u{; z?G4?OZ31N!H58=Q-0Q4FDM;2!CM5vW0+Xg&Q+1oLa+x%G>p@&;{L&>#l@&v-xLA$C z#0hoz+)5Xj$RQWii<4L#GY@_Gg;1X&C|&{!v*AOv9#keP?=UG88N!3rP^{c=x?Vg} zb*Nx<=&XhqJ?v$NWG;D2j?PB~F21(UA@aHW&%vc{2baE8IQ`A0xBn^k<~Kk=skL)c z*aCU}iLlV>ao8aBT-p}rnjzW^yZ^j#%N?z+K8`I=VcpGvQ)?BAA4izSX^BGN%BE=64;j>2?FGoDEUSm!gGPrl`^^GgQGs-+pfW{P}CR~W+ zOULF{-k4u;eQxEAjjL|#F1vxwSqes1HX4a`X^ct1_27jNE4#LAy#P?B3yOVesZ zhCYdmfq|5wVD+P2qESN!@KeSGsRg*EDm6tiDQTi+L53hXhUaG33tKVtf{Q`&U~EGZ zKZIt0CMZq>?`5awrn-$FHF7l+=e8E-2>>}{r3;K*iIRrUL0OOHZ+$EK>euR4jBQwcGt^^CJJ{Dc1mDEfEhlRls%N*p{$$6ld;QXwNDxnK;u@jLlF5}KNr*ae6PFBg zejHek9;_ZBc;6cv8ek~`4sBI0&Sg-UNYqu$4TF`}x2?H8yX<-*pJmr4i||ioDFM=4 z14I0?>Lw|mpn(cAFA7FRi5?_jsG3rSQP@5ziy@`&a#OQYFwX68&YKRQ!6b)3mlofv znUoQoH*q2uHi2FM8e!;4eO{wr++M2_V^ZTsQDGP-am@7rG;yVONPf&fNw;ysA;58% zxaFafK1HJ@B52d$V*@3c5qzvyW>-{cCSLVfy7PSQ>p|VW23MX6u09o9eya2Ew{vfO zEBE$y(p!JGZpjUGOGh-|Ml_L+D|874dHGFk2fiC;nW5Xg%@?m!-rMrp<2~Ev^5(~c z5$5NU0tPZN>!MCn32)cnaLCbrDO(*hA=KQ^L))I~(?gSwr6VPu%<>!ZD;@cOf^w^F zYAw0RoXd%UiXS#Z!LC97OQhO*8zyhj75OFni_aTr`ZcI;m@YBU&ir5f?WK{|Xa3~v&8v;Mst3yH$xF4Qr@aDqMt0feL5 zG>Q|CR9k=v?|WU-!h9D@)Uy-3f9p+Pm7f`W{gEK`!=Uba!PV~tb>AI4|J~+y|2hBm zx4}ORmG=<;EE|zpF*37iRC>*LDIg-DqrS|+q4}mrPs84?HEzGRuxXEt zVzwz2fKLU%%*1083~h}E=b5cEfN(f=s2Bx^E7T#5~Y6w9JWhqt|@01F&O2PXsJA_!tC~^$wKq`oyqLQ50Y_L+hk|tI&j5%Q9L@;V4 zf-0Q{jl|4Ikuh-66#!CVUD~w0;>~IR6Q$s-tQxCK%E&o6!JDArpRrnC3XTb3 z)35uqXN#m!>LXR@Rm=eHAx0t-3KyoMQ@T2XrLN!!olFG^FI3cxsf4UaBqszViq(p!ht6=W@f(OP}RgijtqxEHk)S)G{Dcab;k z64`f!IaSQ{Y&G%A7o$q+xnGb>z3aF{z=p3=a%eheDf5Ag!IZ0Ex-6nrkO%8Nbmd< zy3zwJX9rr(7Fy5sUVWweOhwPxDwK{xKWKg9uiD=Ho3=N<*1YYvnra^$TsO*{ICg?D z+0IU>;vbShM4pbcnO!A2pPPw)sNB+2a&w`YN0fMMt%;I^XctB34?HV~UTZa1jey0Q z_NsG%iQe`qfRz5!wn}m9%zbR32cxk_!4FkCu3+1UXI@8L$|66qB*PiQqL|QwMS3~e z3ymnXONH1JRIh>sKxy^bbV~n2Ns19co9Zg5(JlzFUNoJ?`xme%EqE9Wx?)Ia;^OPo z`-A+?g3OPD%)e1d{iy5s4{+s`-}j@`rY~djQ@3JN1Ag;o^{DKc(b?4~qZ|vZ8rit% z@usc6nO}c@|B7+CIppLpVU~lA`8YMlNgJP^{V0e5!m*$thotSOqu1(HbgSaJP=e?7Fux= z=taoK^9+$sM9BcsEWZhR9xBW~jcaZJ1+|ym9A+{(3k}Q$98;nh(IgMEs76l7h>1V- zFpAY%*#;1i`Iq885h(x%lXy^T(Ev15#b_6VD1N;*)k-ljE3bzMSxK)73RVpZ&cE2I z3A$p%cZGQ4&Gm0o^* zW(D8GK#lWj<%rD6k-mmt$_nbrt{hRQj>W@K+2E0xFjppK${3nH_%MN9Zxj!57z&~vmR#A00TP(^g z0AdvtI4#j$Jvar)b?DH#ipj|)PaF?2+|bfAt0QjJxe9`}hR~o1fSQO*wefEarOVGG=ANKv&I; zbmuw!L)!o3e#+%1eP@2$wEstq2Y#G=^{?w!jt2Rl&a4@eA@Ug$Dc~R4?c5x#iE!vK znPVOiT%BGqvc1g2oQxA1DK^xivf9Rat+|x}vnH{1q~2&sEm&+tQ&hkH=7H*wEhQs} zc|fyLh>E?eN*0KDh*GrN)WA)n1Q9XqSQyK>)x&7+rR zSHZbOdcEgR!#PJ2T~tSxAf`dD(-^SDSaTXn92&O@P@(pg0A>BneN`jd%5KiBLiR>9 ztr=NR3c@#i6dV&=7n%EFWmQ7BB^bs}XwD|rj)dFLR%FyN7B@e^m71$yV^(?iUWH+G zj2xdboLsXXhh%)jC;P{W*NzFUe3SU6@fo6^re_B0pKd+$&I_7|%q2FXSkoloTC;6Ec==jw{czWW_s%g9rX9?vw-O6M+iWBm zg@lzO>Ha(@sMb3turJ=wXG1XR**9Y_=K(%-Xdp#S*wQhnUD_)Fum=D_|2(2Jos!Mn zfgST>nhI7y=IEL{ZrH`6xTwUxk4K{=uolH=Fzhhmfqkk~IIbYM*Ui*~jYkZx+!HiC zO9l6TnyB=hd%F4HPnr%rlYQmSg?t)TkIR&dbL3M>LYC_c--srLAr^8(gr*i{C((d> zaN$s>kpOru5+`a6*a;G_&wv9+)31AoLI}x@hSdY z&Uq9z?5?1XS{&*_6uIhjy*MdCo&oa^7qN!*=+Z)a9uLMlpD5BL0&7NscJifTa2E*o zq8ry>BOw#l>C23CE(ezg;nK^sn!9B( zU7<#k?*kAk>z3t#np^Oph6jSY1o(+yWSd!t`3GqP1@%|^>FdzqM{Cj7j^aa6z>u-4 z^m9~0nxijj9)nqM1mhh#B@ZWHHBo#_&>^fKvcw75cBw(Kb)9&+>EKTr4?UCG@WuL-qv}_U zORpJ6gi|`6Sg3ToE7%M1<1ni6s0$P%EToUd94YaWGLRA;)~_1Xj@uLxznf`nIsCF} zZ#Y?#Tgd}34(6?jf(fH(=j4dFfYpOdi}f#~*jl`87&W-=7VPuom^b7jcf;fqu;e2g z;%G#91_D#c%?->jB&*=4Ny!JcTo^!qf@Bpviv*?16R`sLr}(5;uago%kgAj{xoq&F z$dn~5qF0PI9mX$&=*4pp*(YDSTntgY^C<_0?~3`PB^Xs$H>$hx7Hs@*rx9Pu(TuO8R1WJ^x+to0=a4+v_JW_hqgayw|bh?3jT;^9fhDS)j2A%@u7@4NeRdS{d z$pC9&WxGbCx8771!S_0I-=uLF5I2vmsaS=!vE|Svx#}n%1>!{>sNl_5P8a=^I%XSP z6t_TlU7z;eH}_SmlTpEj(S`&P`k{Jl4uQEAm^HZ;S$ta0R!(~OWqXIm!#@Dmf=Naq znxt(~10*iK-uqI}zA$KcA!vDCO8B#e$J%3WaYE1p=@u?CfAMg)Rke9I+ z;s;@L3mR<059Q@_z)c|{q6jq+hBrT$nptR#KN+6YsH}n-Ub~>SDyVHt6Kg8W3!u=p zwfy?GeA?2t;rL^h?{OKKu0wIy3u*8ui{ClqQfj;}+P)RMX#tLha~?c0rtZS_=}W z76I3){Wa0^i=3Mwr0F!K%f+Bb?h;tsM2~Ov z8356vmf|#ibn5kPWeC9!1rz7$N?>9lN-H}jk_SH`jpFkl;Ps<|i~mUc)B0l23JQ85 zXnvvlW*(|GvV)cVK3KiK@FODE>=rv|x@fWLNu8kb|tKg2dF5D|q>=Y@_OLE$o? zWVGA-$mlj68!+`shE3|iTyZZjS|l@}2cK0L#lj*v^d4g7Y9-;h-q2@X&1k&xC+~sN zTL*k#b8TgRz^`&N;y$D48bP=PtP(Pe^a|S;<^dpt5oYBmvBD2g;+rqN&>Io;E5@8z zI0~`3V_Rm8;Hmg^m$`%qk;4OZI6IFQKmHh2L+4F=+FD%s(FLz7LMhcQKd9uH9QrO7 zGXpe8tBkIQBt&YkkPs1*k}wjMKyC=IK+8n;C&5M7gm+ij6M+Muc%qSP7?aR=BtCwz1p*xF&Da}53a>C0HdfTasC zac(`Vzj<))UBo$UF9&Te1+6ayZ7&9y7ut?Ji_K5|-KQGLX4K=mr6rzl90g4x^1()^ z1lM2mPz;14wa}5@6gd{+UVc))dQ5wTUyImGHL6&U3WH#~2=A9bCn!#&8Ic8PYVoGd z1+4z1H}uczFTn3H! zEV}6GS>p8TYYp8%isYySz@zZ50gp~$|3h1#NMSA_ji(@9FMo3qy`Z3;>e0bQGgF$v zFiqPfvc=0Bq4(1XJ$nr~R}&SAx=JcVV{7%Gg6$nf7QD5JX>6DJNh+T}wi)d@>5% zh<1V+wfCuj}Fj2}x@ebQaKvQd6N_Mx$;chmZ_s&12rQ z%j#9>2O{UAv9)L_#fPkXjMDK;kM`)0W{p3#rHLaPq=B!iM2c*9gj=HLO9)%x&LgHB zq97t7vA%v;RLC&776I#G=x z)vdaU2>_^u!Qt{*J!EOBLo19X&cTnspy1+*Yx;3u(s(Z7O%ZRxg@~|ebVP&&$_fR^ z#1TLkgONqKajeU#3eL*w(TsJ4`Lr>!XCM`<0(tPMu#prQDCW?_UQnc3zqk}C|>3bF(i-PtA%s(&VDOmTZ=bH{chl{U=T1>*-{sOfbeTjUwNvJ>+XeN4Ak_zWWe4O<0?$~LVW3m#p` zRES%#O7R2R0x7qm@#GKpc&DM#5iD z0|2!M2JAEn5SRdPe$jAl+X?2Ua&^Vn(+i1zn%DZYxFq=FoMz!CXlEVEs%<(Ca`3RN zII(^NZ#6^7*0ah29?AszHu9Kh@8BOXKWm+$D>RxW$-%admpjXkvhWlVSV z*kDsEd$9@n-q=hvdzvLmjt3_*6T^!)GVxZb5nJi9&ef+NwHXt%SM_oXaBS(-_`^^5 zBT%3nsfB;6jBhNC!Pj+L-u&a>(dT-P{{v4WNLXou1kIFG`@vAo_5Crz&;n3Xw5N{9@EE-n#UnTT|$ zIXf8+7PWFnQJT8Ao}Fu)MKBD&b@YXQ2)dTi&1a$@s{1d$)O_UmreiOscl=&GZGNWU zPrBzSre;yVLKP%a6ZfB^{F8~j7sO3NN8{QnHEf+b1PK*gB4|^=(q;8trg=g3%}}0}RgJ4`{UVF4K886hA3*d>PHrsE&!V%ov^BK#vJ zp&_ZmJ7hQtk5!k|>(=Rq1d7<&}&r>z`)|XCdD4VMMldGIY1^k2kk35Ah#VbJLQSd}w zYI-!!yyTh3y{4Ee9apI3ImY6&^VKdlYs7DIC`gz8#ME4J44yO!^K*CRoF6xe_U#W*1o zF4C(Q6>P8g7gq$J(Jw3+UAF>1f5&Wt+7_fy^eb=4R^HZmdPQ$`SAY9E{T=TObiOyx zwZFehxaja;;Y8h=UqAHB=!?rI4AhRNP&c6-?*q2MvrGUf2BU$gIRu@!IJ7=pHsFWH zqS~iOU=ed3PD~K)3A10YVEXa1=CLDbdZn8bn!(m0!_@&i$GMf z;NJ^k3Q{^Ef+`u`QRUOCVbcU-{|rL{y7I+t~c z;pGUSuG0%gpII~-_ukWM=r3UMUxN~XR)qgb6#g>!%}sm$u;as}_`%C`aAcZEPeFwbK{P@FzLdwiT&$2Hi~eFB0<_(0;Zaa7+Qdnhj3`|)|KdE zy{Z(S+Dr%k-s8wl^pC}i#3f=kzg&*+GqA^TCV?aTgSP1y85ZB1$ zm~_d+wu9gA{AgLnhl@HsSk!rPc~9NOf%bO`y|@HBGC1&I+vSR*FHAb}!bI@T;pZoP zym(?;E#(EKEM6VOa@B zG|4(NWKt4pvbJ;^-`&p_@{ybQ%0Cn&Zs~Vb^U1C!OC&APeCkYHeqyPxU|AQRMw|Ac za_Cuoimgwwvnr|_3L~!6B;lC`op5H+7~J*3vp{l2L%Mf^QZ!OlYm3uh!BN?eN?e5}@aIy#H|z_~;;CGY&rpz%)XCgwgQ{ z9rod$Wn?~aO=cuUII%=6K5DkoQTeuT2T>`nB9H=do6HR?I^ z{J1XTS-}Jl=bBGVj!y*v6h`3Q^%HQ1oX&lJ`tv!? zbi{06n}Av7p+lYcC&@?x<1XJTNCOsIrXajbSi-mKrN(W1VIdLZ@gfJ4FB^w|X$m+s z++_98^_nmb<`jSl>HXY83~Qt*04q!Wp$WUhiTDxOr&KU9kT}udoWOY3#nD1mBnb-e zvS=g>apGVT!8vCZ6Z5#Tn3`8t(o*uej7hJZ-hT9%&XX&NcDQtad`_)m&8n`COPk;Q z*2zW0Hb>n4XYyfOh4C&3T-2}z*_#;2vkSxLS@TZ<0xqf_R_W%h%XDqvPaa6J_bWsd zn}sy3(#p|jbuPujV?(@9apXS*-7A@Vmb$uqNza)D&F?R0JoK~Fy1TLYNmtIw*UUx{ z{vn}iCcppV-U5mf5s?zeXL2T_pvn32NrjDx<%_S>(9?;{;uB^UO+{!swEry=2RBV@ ztD1ll-xs(20O9a0bb7i+G8Mw$sAl#U&lH581#l#Tzrbkq+7yAnQGnC1k`2i}Jx1hO z-)$h?*{VpDReY|AK(U-tH zlfgp5KSDtVpPO`P<)ko-nw1a?tQS;-5~C&r+)K3Q*IM_77ifKE62ji@$Ct zpWaY0D^tzn1KJ@LnuD4y!Q|y1dJB|Nj>W)qf6jT3J3ta%dwwQ3Zm8WpsQgoKHOiEK3yTb>bm72xrncECLGa()@IJ+}3|f9g72 zCc7P_9WYPl$0g9WAAk8u>HJG8r(9Y!6%@qeLo9^5&{TLA1PZ#iVp89RNx@c5kqbkD zk)(N9x{?5^hb*bEN;+b_UUTLA_|z#r%p{L14xKU@i6|{VW$hA;))101LL#Nqc2K`A zHfDH^IoBqHjpGL2_#AOgCvHA#y>#H};+EqJaPud#?aK`nGtyNcoH_Y*RB|XR;}$es ze@T&-5-ky}#Y@rjrnD6P%EsivMjx$ADjA#8Cz4zoFXx3xkxWe|XsvWC#i+1l5^sCl zn*(&W+`Y&|PwV7lhte~^1n>iXeuS9^e`%To;tgdR;uBV~U}eFmMw_Hz59t!QSI@65 za2Wa~l^-3;-!(mrJJd4|+ z;BaW~N=?Lb7>u7aY5W22&4qT(EFLcfO$eg=c;V=aYv$sa7pTVVc1T!*YpzZ%U1zJB z-unB?E5=`1HSO~1X+lA`3r+k(mtao7?dSu~PCB)CQg1C&5Dh(Qd#@jd{OVQc6>8oe8WkGF4a7`W# zcb?DuP0+o{Z+@7C+Lv~pT?q1NJoJ;)x;s;qvoqCmbL-~j*K9a_S)p&bH>nsf zp|xt_KuF^}aavH6=&ao;Yi2|+Fqed4`tTfaDRO6x^J$XooT!HV6D+E6vBeH}ZVEUu zqD&+jm>XJ@0?@g5x0@#s)hro*W(hdQ6_&@L{&?Xn4cmUN>-1XYAEKSE(G8f{^5e=50+$K|FedQnW?I|*&5=Uu&kR$H-CtBVkO)TIY#2$QKo!KzG7+t7kWBz zj2??H){KR%&0%0kpUx_pB2{jkjBC%18hSQ|w*rcA4j$MsCr}q-gk(S(DmZQdu`vHg zGX$^_KUbo96|53Jro>c(;Z$%e1ii$72ph{M_TV#DQxOv=Geh^rz;R^EFxK=7r%v1| z0H!BkZ1kuHyJ}XBJLG|i0u(u{pv)tJ)E_SzbMmE;rxuNG+V?MAXUgSLi}pN3K5IKq zuZ0qupZ4P~)s@b;x@z3jRTHnQo^p}-2NZN_$rPp_<)6t1pLY~=?4?O<)&5A{I)#=- zY6;S6AloiQs$P4oAhOly^r2LJayScv!;J9T0F;mz^7LBck z>Q%i=N?k#3HAP)nfcmjW$mGWdrh@1#GT9Z=NYg6SJf@5_bu8$wekbU{#TWR83xxJ% zJ!co;;wyjP`>C4SK|a~_^YgX75CzT8RpaI}y?mI(`-i^p?I0qhBp2l?rxiA1%5v`b zrIDzTvFR*gf+AJ0fTBtZP?-;vuJx0dVd(WFQ|N^O-wXvy9YQ{-l1Y|EL{?Uz<{BcI zu&e>qO!BtWD?at%pdZu)gGYx>Q#!G!0(Uz(bvgw*S(Q}~m^4wx1+xkksm>v&D|LhGXCV^$sa8kceebI%)3u@H@s5lIy=~N zsnB_*FZ~7)4()k}cBq`K;!>U8^f;bo)~%UH6hvjxmDO|!b_w@_R!@^%(81?D3(-Xx zZG>!|5H6H%P&F`|5OnRaRK>25DJpL5Y?HAX&vjQ`H9<@?Yu%-((Ftm1RFFK_<`h0VtVvRam6lkqZ3;#;F%xY< z5RApgdewO#fCsdv8DcDAyw`Dmg0Jjkcec^YM) z^K7B(LSObhA{_9~*{bfd)l{Fa?fBrOO!;(hK7L!TZp|b|L2E!klj&YGm(xq99(#H6 z!52U~#5`OJ1x*GEU0O9|kXDLALM?)vm_x}$do5T1v09uV<(>YyDzxPd3{ZVS|Zb#dzl3!9F;nA!4ps%Bnh{cZUT zw-fVFO$8TU^yIx7uOrgy&`d;BdoJSZGPgS-M#@)BFKp(y$c!{XX-Z(KjKwLTYOe}O zSW+Wk)LOPq#p#TbJuRHW?!m~%u1MmQ%{GmS72IXaqzZ^j8V2{Hs=!=o6M zr3uf>Jop(md~WJ1Qtrpxh>KX+T0MDSlb&B*uoBz1GPrsiAbK`7lD#iGtM| zG@`V1($H$eMDU`wa#EA*-8!{y>+d$d|MTA5+l4MBoQ{))j#C3vKt5**UFQm2=L_AJ z`kRh+UD!aIpK~=R-4`}BzxJnTe7~4Jl~9C&z(QQsOcDOUP3dzhroF#lif0}nA|jsy z&rROg_PgbXFs9wQn;`mPY8t}HkTQ$sPgBZi)3#8^Du zj~ZIM_z~yOOF@$`zNvT>)JkBHrne<0Q-Ymy@h6po&K0=e@)uvrgSKV# zufH87x8aWbMkdhB*Y zgQmz_r>NH$`d-o#U^4heMyH2^ZbarEmK`aTP0m+L?%oicCQXMmnk6R)O!FXu&zns` z#6uL|vdy+}|9*|2cOEnhY@3Y}n^ zlLPH12HHP@Q0VxWcRptdo#zIqU^{eiu;*%j%ZctwTe{9xWAlSLx8XtD;m5jb!FpZA zMrh4sx)4(eT0QOj%4zSvJmmnkKrcjy2%3G*O+L9~O7BLdpfEyN6q&D)ivoT%<<=qG z4yBKe;?K|!?=>+b03jwZ=rCOoKhx>4#s1$S^1-$T{G=7)(^yOM%TMD>w*`Gh2T zaXRNKrr^+u@l3Ji6wrld65EDE#s6K%z$XK@CHpG#sCcmQK-RkU; z0z9j-_$bqRuD*iHD@Q)!9~Pp9D+;^xr^wO36< zgW7fZ;bK8bFYf7G_=NnIFa$@9=`WCH+c8=gA1#=k3WNNbF@@X zrO$405{|+Fgd=)@8_P7E3FGaekZlx(rc=h2Okh4pXT|2?TOf!JaGF{}g)a27A+m&P%-wZ#KR1hjj7fX$Om?vZo+o zA)%m)d@tx6c0miK9(W!bp()r1dHw+rP1*O{l%p?CX|0(S?3iH=WCi4zj#Hu{jmNlNpK!H;V7sK5tOcW1+oyMLn3k`ciem{cATjeW3(+P-H1xKl zkPk4-9*$(_`?f?xj*Col3gob9Wdc)ihHMTQo@o>e%0*?0N220a$LSMOr)dS5j%bSO z&7va%f-f$BcJQj+SW4y_Uk=XUhrZ7Q{BN*3mtA)kEI4nRA@W(q{6n{Z2J=hWPvFVd;_Tl43jWD%x+lN+Ztzdz z77{=~^5##jhTei^3KAl6HMT>tBa%%~rfOElhM6u}nV=*D@kC;?@!LuH={Q@4xw%OG z1;FW5y&tHsbvizP@N86Ztf}+1v0|U-kg@Kf3c7@K;{g`3&}eeCh`KF9n0=gWy~c zTtwaV@y|1rv+)jm8ozVJB~v~P0%|@&rq-1*1+7613YvCt^>nb%`IXa;EttBWcR{ij zBAK{|c0s7|Os&Yu+Uf6@8K79rwaCAM$+fsmVu}t_RGG9DO&pAb%nllU6tu4hT9*c` zOQ_~uQ2&)heDU=RU3_i0E5G?(Fi+za)KrLnKs!|Cc|lodZnl~)$9PA?EHnpSkS}ce zWfB{Y(;r$x%}e!SXv}*yPH(KD!zRlI51&)hRAxPWw4vYtW8MJm#0BM()LJ1W!k7Y5 za(eZ^%tL-qWE6Y?a^Yr$tN9yq6dqoS>fWd))QoF74$U;(L2IWU>&1;++};80y!yG| z_%{aAuLc9{N;om0(Akiyy+4h==0;zrA#!fU6~s0~6l&B zB8w`e*LU?0`Mlkiez!0EUSH!;TznO}FVJO|-}wyoT@DK8g2A&vfW04TP|$@SxDo^n zeW~^Nt&gWl#_=v_Y8rZwFQFMzM6 z4<$ zzy8$}e%l0h3N+q4q%U94*D*W`$zI6qh(J3iAR_!gM`4=`jd~W18^&pxqL+zSS->%k&PBaJ zkg}7;>e)1-v1+;;D#ARWEX*SmR6$3S@P=m(<`Cv0`Hg+(xyx~jgE^|Kc`*|0g0IZ95X)(nUtHQ@o*J9vwDVzBGhVBa4N zUR_`4Nfm+s1+)_@Nk#h`4{K}9NiT!4H-SOJ9*BHW?-Kc>_xEKE_G1gweL5(Ba6Srx zlT1FKAY5~Sc`gLOC1xIMen39;*a8JXV^FxKsYF#f2QuoE(q6R&rdzIj2C^EMy`U)LYoj&qcatyV63djSeG@_ zE)k?l3{|#WNjc^LO>3Bx6%ccUvvqp#%H2Wkxu9if(6X4zlAr~DZFwnQd@X1?^3%+g zM>Cu5%Y$>a-QTqB0Tc*$@{oQef66SonHM)eji zQ&UZ>>7DGHHMpG~wBfAB5#l(9cmPcy1QEEGKgEboq?CCw@f#u0r`FP8Mg=58UDQO) zL_|u`L~VIEdiT-~DlEirgVT3XXms!o;zYCo6Q*BBo=D^r(N>x!Y42AvRdZAH-rWRj+fuj*Upfw-{<+%wa_er-R!qTM znro(0z(r1ZKYG|J(OPg!qfKDExlAE!N|yzwM$BWi^)n0P)0f`Yhn-K;p+fhOVBq~A z_%H}g1i>l4?E(3Kd1TuI=Be|{1M*38X$*pV_l4Ej+I!RZ^%YQ%99LdQH%qFbxI5yU$JiXvwthO}zB9`doI-CIK}SReHhY z+%$oqB6zkfg7H3+U7`^W+NmppqgOwbM(Ikt;>UEPd+3p37VJi z#n+SGIOl<;?GL)L?fzWtZ8`c17}dl=Bs)67MkvcyWK=~uu6*Dr#Gh8nAOSxoRZd}Z_CW4ni+EXI})HXUDzgGd*+#*DyQODMFePwVW5;E zwBs@8VnBqB*boOKaSM}-)YOzBUr6C#TGq`#sC>Nflrf#yj5HOPoysbZ(jQtR;M0U3 zqeK7JZx>EIJ)8 zxA_)>ZwP@5_Y}GRa=@O&^n{gf9`@zC(pA}qw%JC1F zry0ycL^POL)OG?tHUCm}_wV4!E58-Y^N=e$9>OCq<{x|oL%s+`HSdLlg8X)fFUr6| zotx)!V9`i)IvSOREs={}YsJUrD`3|<8;{uVqBRZ-)Q)_-AkB<#;yhx`p(7_*QsqWZ ztU`s9j;4gHw4TA-MF1HZqf-F%-8cCv90emX0Qu?}UHIS&C&DXIbk=ruB>Nm zZd#uXP}H-}o_Y=qXEW^__T+#r|=mO-^ zQ;>^%j?1S@nl!D_%Wle=f7Zh)mTiKm2?UkJ&|3i}hH9eYVe5wrnhyUkyY12J)(0E6Kis_I;U-_`$yY6Z^NaRB z{6#PpWK+aDB3y#a&#t=_1-}tgz;6n<#A;L`m|%(k)JkD0z+8Ks&;G5mu&YE%JN9&L z>lbhm5!K*4DxdD;^6B~QUv5A4%s>lnk0k!}wdFQ_E?o{h<(4E1oDb>(|Z@7GesTd8uS3c0nI4n{n_ZrXZpn5`=$H?|Xha zy6|i2bV$%q!I6iDho1=PwM%5iI}>9|dGKH{i8Q^fQ*u+CNDjl%y(_1YB~uUFYi&gi z&4IKg-W!G{%&g4j2Qvr$ruWKEXy?Uin3H8*&Z=t@ z{Q!tzfSI0lAYex%O{!DaDtp>-%;TF(HNr?Ug_lz0DnzV&FDbOx(&VEsoo$!0rN<0DM)rc zJ*{WjK3bC7@qZvibV~=H;5c{6aeIfJ?But8vHjT7{kbE_w}31SweJ5WuFLq0o7ugI z&lid|8eY6<7BrlZwesfF3z?fC()SMORsk}Qcu?i+;H@Wvd>P;B0jZ*#@o)IxRKZOMXvHX((d%l9rPkzTE%{w1$a^;c6&G+zEQ0e<$U?Iq$AYmc;E_{TDa9uXPumcG+lcmv% zg+0s^Y!}T!66@R!Y@dV60i6Dh0qDdJ3-f^Mf*yY}h)VfP;SHjW3X(t!?3ZvMnZmn3>t@hh3tdXPtU5te#$c3$#4$kN=&?~8#tD?6 zCvM5mpDB34vgh{T%s&T%xb2J$k6d%nRU!USITByE}eC$WY)!!S)ibUFU{Eh;tbjXy$H^kA%!$A&e-?D z3}EOhFhW6Y3Y-?qSBqvz0bw>IhcfqQO;*vO4$0h)62qV=FcGv)>YW|9nAB&rd?E; zcR$v+?LoTu0`o{M-$i8>5-y^;*0E4_{cRnaZ}n%K4=)yvHf_LGb^w1w$?TxS8tt4* z+n#D#cbxkfW*!xoj%Fzr0VDK6ltMJ(Y6v15^6|YwRvui`O8hhP2>&=1LNF8wGhxg6 z+5Ox75+ib&f;pUIMz+?R2$<#}!CmEnlRximI@2={bO!;*M+(SCh)9?Rbx&8i z<3erIn}3<9y*E`hk*^f!sSRYjPncPMZ}Xdf(Q{>I(1-Kum-si>*OJ}*czyLsY?yZI&$ZuQ8{2jqhb zE@2+I)RNr}(gMQ4K1T|!xumE@g#N*vi>>>=o~HLVrhH$Rzs z_d*-*AYhlqmcH-dQclVBc= z!A-U@L-r{hxM0RB#Z28@o0e=7}t5WIEAfOcn@F2k@oo8NnOBG4SEP;W=`5XIoc) z(9H!D)H4|JkL-VX`dT~cUu)j~t?Y&ez%#@=^rU76uC^d&YUa1R`4`<6Y71RB?|#L9 znZpat?)cktd%tz=m8Uv)e<8r@E5(n-=%UN97cRG*yU11}wpMTDsOM`LUD6H;!q4kn zS-`iNaaS4FT(a$v`#jk8$eu@-2ZYnb1xybCwFshAIzr;xx=t@eZn2+a{-NW|AAYm( zXR2^j1^&6ZcGl%G+5(|`ykgdog){dN?GWeq!tzTq-+N)^N6TjQZe{jZ+=N(A_5)JF6b^#K6FKf zT~N06j*hMK!|7mj7hbVBx?W9%#LSbDE;kDaeqQ$$ywEs1O<%E}?bq5ZdbY}Fz&u1g z;2bItv}n@_3{#}VtE>VJFpQ#HCtq`;CV$^e;(^?{VUD9;1Rq}onW>vjw3n~5cFqW1 ze|+G`*LyE*>~6l?)!mEI-Q7cVZ=t)7Sg5Dq_@}$j+mSoceB?*j&5zNeVK5Iqk+I*y z?H!_>+Ztc_gU(aS@nYexNIJ%>z5d|YU4MUm?>8>K{@vUw|5vcbPb4-+ny;CiGzAku znj<+}=%}qbHtf0J2h}baOU|#zDBf!KtpN%i_~Jg&`+pg9f51B&?0G;w$~>~GQQFZx zrek;BW(pAr7lDOf0(?(jdUp=L&WF7vKJV}Y=|n*|4snPQ1%Z5|fPyZS&ISdYSvC9U zqFJDz{h%OI4!krA&3!M<`f%y2_D%DGJsLj*TuS(w=IdqAtA=JOR*Vnz#zd6lL6qJV zX=IdWm%_wEo5_&WbLdJPa$wHG+{}i1K3MzkiE>vyguM3QQ5G*XMIP9?$K3 zJiqIS<~=B%r?U6+joTjr|KR=)@eh6f)Ugo06pt%1x+vp9@&@{KvI1VarBwL5NoFKM z(aS`Vp$bN8@qp%@TL*T`!+9->OSR`8CL;Q}E1&+f^eFf{K|&giIx0yMSAvv0%=U`X z)r^6h#vdL6^Dxi2I@*+R8`sV0q0cYBh<1WjDHD`b;M~F6_@JFv?l0{Blit(Iy0Ra3 zw&gn8o4QasnrZXX+0oVA-Q7Dt#@b3%wJKZunofoY#mvDCe7zmLb11nM* zfMA?0A3s)>L&#Z~^Gh%e>3xQV>_=>o=k3#ix4#@@Hu%dcz1osJk6zS*c5p2lD={t- z3IYrD721zCzwyWEim7S5{^7}o)`gEl+67UWeYtG5P|(@cvyUwT+fX_1GSLpmhYHD{ zrdc4U){R0zk}jVpmtjttlQo}7VHlWC`;bn&EiySgMpGR@Cak1)&#i+yZ#`G_;E9Sy zPgXqoQN<%DXR5(GPo%beKD+Y?&`xgW6S-YaH0~zaY2N!JmEDiKuU&wDq!0_~b_f(C zEQIaQUHF-x&TY55<4Pls#KwtAY7`t1+(c;Gvu;kNn)t_ktqg=iYyhR>9HO9V$1}^<>JSN%I3jTbtb>pGjScD2-XwWc~-Go5Yuu8tOPPj~Mi_CFoD zk6TZy$nX7Xy5=^b8rtn(Yll}QCxLu&Tb^h;@}oXH%qrky`Jex<^5w7n$(L^YA738v z#?K}Pdt=kFA9m4+$JaVxC@d7NI{=@Ei4GC59jc4 zjtfJK1(=k`Ks>H^*fXzf>zyacK|7D0tOWl&dZy;F)V3!wJ3gP@{zP`?=V|}5>+|{D zpq(!?zw!l;Ps=M`Xxi~eGYN6w8I8d9%pcr!Yum=Tw3?CP$S35VYW}#Xnj;({WWw?s5Qr0qRpv0UP#sbb z%S1I&JYK*&E{5Z;)A}#f5(RlKLRWL`+`jG1JdS*ZSWrv~0D49<69+@#t*`VR|9;oS zEgk9iJ91|_a;H1Y`)UfQs32PgLYaEd>fCb2K#UyP{wq5GeIq^u+Anc<+M6F%tR%AEaOB`P^H z&XvqL1`2Y!AmN|c2NujZuz=+KFV8->U=IG`3?+(E?N4o)7tPdaG*MnD2`MsnpH=D7 znsRHLNYjpDhjTHoiL+93FA&Ddp>XTf+6O+WeC(sj&z(f6dhEi6$5Y!spWg9gX6KXn z-CxMO2I!NnPJkXycDA#*#d$2u?p>d z***CkU!sR%pdc>zd%-9;sOl@{U<*XMpz=B3AFvR1LC2QN+5eI!A8dYze_YxB@*I?l zWkNx>xzox`K{BICo|+^9fXI{usdzO}7z9ZRJJDrw-qcY2FkVJc3|Sc`q3lUqszR%<~(~uYR%RwJ$Z%#n%HU z^et4SAdnAlhy3LjuEnU}+ZlyjIzbz`#LOBwc9)xFn_QopaG;ZS?(2yKBfCpz+H zJDVJ>9s%Rhgo=z^S}0AA>F$Bi)|Zc zyDcssRD53e47jEAO#(;~M8i#F#;!QYrf65FS111X(L=?7#kn}~a@geuMI^LRTtwh? z3EuyQpcAhKUE@En5VlD|LAYweg&4L#xC8_L;BGcSwP~m&E-P@RXFhNbeOx8^qXBofI`pSL%@BBg6@u%C*u4}vW zO53H^+Ah7?e);wGD{r)8|3egXpgnaAoP%9Z>zUf7ec#S)|Mz%!hkH9IkPo);cyqga za=K=I(`$d!d1}Q#+qr8zRsLte3f^t%IXTL#*eweNWd_u|ZbWoKLsl-uzOK*?Vp2l8Z8-AY6rk zf^Y{3TOeG5VgCdE!8=7w!Qj=755A8_^C{esuBM|@N~U@q4mt48)$%!4%87r3f{rbj z>nO<4&fJ3w=Yf9?E+k?9f_W!b&g-4I z6SFlaN%U>p_1&}2d^7*-H}e5Lr?=0)vKQb}faI?z2)dR?3cCxVp2BD~@}-FXkn@En z4;g~Q3IYUCING*_iY5p61Bt_xbB!CWpa&P}mM8EL?f4eNUj|15F(G_~tf^Vq(FpKOk(nsNBtqXZW&%ZCWP~;qMaC2v$(*_wdHcSTo@fq2&{SRS zCLEW1kLWYM`<8D)W=|_n2oNN(XyA`Afq*}Fz6eh?QtG+#vA<|03?crHhOLEvsg!qZ zyNMu(tf22-gBA3}_b+~W)6owIZOG=4oQRtazJD|DM?ughV^YOqohmZ~3j}0NG6T;p zqG58fr%qMT+D5zt6BQ|Eg+hyDPM$B2D?Bz`I_cbw`R8^lIKOk@xg877?pS!ec(K1? ziLYWwz*QKmDh#>`LsbMjoR&pB%kc0a;m`gV3_%1$#uidoBq&7qGbL3zQQeYu-|TKk zCrv4e>{8dbfwHmT-8W-_$jsm*bWV;-tYbI-E752}m%tE8OfX-`C9x z@y;x@B^@xi>JJs6d;Mj4aWNc87!eT&IKVI%KUBM{xApPl@wZ~p5Ga}uq$?9 zPyFJ(*rgKSPvUA-;(A@8qb_!_D028UfB8BuqRKeKg0%zuL3jtJTHF33P`ohS{^~%m z{oCKn%DylD1y_Kb{$P9h!dJ1wuST1n!Sm7)&z+&lb%EWJ0z1Ye@K`&IR}x087f}{h za(jslErb!E8IxVD=W{ekn{QWF3VHGkZ3`2Pe~6NUFtp+D&86zXUj0w!z!oRc{v9S! ztRQ${5{S;n9~`dHM}!8WRblt7r=*`Hn@jAc02@urr)lGn)E1!S=(q}iF z{D{zoU`HX(&5S=_-rV;7m;>+LeDuRHiGAZ7w>=Ou1e<9FYmZa}MBdOMX>y~@RFopQ z9I>vcGMW-4&|NeWm~(FD!t=Wp0)j5?S=?1x0PyiwE)BYuh1^S#!qv;7HOpc(%VV|6 z;eUm2^0j{^r4m5UjG)*;2nWF;0`f?LN5&sT9ICv9*V^u?-C;8j(_u|iA!I!+xess6 z(*g+y;AU4zFo9pF2S?UUpu^<&ha$;vgvjCJvU~f@C^Ev#;a$P{<+Xi{e)I~zB(#g~ zJ*M&BM*$|rqC1bX2^c(p9nbvUrh5|Yuf$G$5;^@v^vstrq_bZmk`p5c+8w*NFMhc^ ze$@p!eDIZ^YqM|n6!x(GgJI`;6yEvje*t!4tuOZ7@cegQk@yaG&9{mS^$bMMrY~;8 z34XNs*+~5(;p#iWu3N(ut3#C528w3j$@W3Kd65}AXnR>@T7+Zszom+3$Pvh4+Nx~j zpiM=?m%8Rs6WC+YRS+hr&P&la;sb&_vz;rSa5(x~r;Fm%VgeZ#OhQ0n|KK@uyz7CN z&Tb6%9*iA)j3RhAMxo8D61E~i5TVdb*S@?75QI3-sZYiLb6VeH{e|+@ z_r@Ig5Fee;L!ja7aT&slR7&Y`6fu!RE-7Dw2pGO0GJKvi@H3pe{!p!PgOw95?V5jX z=c4nwBrU#DwAfdusmM?f z1C$UMCM%&v@xhRtoD1N{_d_`6E{%y5jivi8tLI|yj2U*%>}$Luap)J(WA8*yejGXZ zG4klCzei7h8ao3N`U?0Hhw*c%ICgd$J}DWjzSp;R7RQs>+M(e2|BvL~J0sfoc+ZtR z!+rmz!z^`o4fPI0P9vI)PjkS@BG~cVg_kSCm1`Jz)`Tn9g(}x0g-hnrlU?SPSF@45 zy}>leY}YJ8ue&fsNk$d#UUMm`vZ{}=)lC&!E$FISxIg&M$h0a2laqZ(0^B;;u{Sx# zo^eumP5xW{Y!gUAKn8#CatDkb;14uhrmvh0pG=+ktq(sUj0eefjG?G%h-dQu5O>vQ$CeP#C^8MF5}A0_0Y^D zFHic@| zgkb+vFAsZGL~B;W>Q=^TSHc9sYo}!YhzX<(A%-Aj2(cAJ;DfJ254k4Lno5W5zDa*< zj+rhZZb_Gn!}o%)BK{o$K^lm5YGMb#fdmkMB>>S7WMD)QTq*)0laZ97JOQk}zzd-q zK@cV8(537Uyv5(MAIM`S8MhDog|Wl#seN_pldVrj+y4+g`flXd`;p`C
#6CXrR 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%0A&bFGJ^?ZxKwaSay%~z|BlTbA{G+_QCqA8wMysG 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 yT^R{P!VvN=U0F-&j(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, '\0' }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/pcsx2/tinyxml/tinystr.h b/pcsx2/tinyxml/tinystr.h new file mode 100644 index 0000000..3c2aa9d --- /dev/null +++ b/pcsx2/tinyxml/tinystr.h @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/pcsx2/tinyxml/tinyxml.cpp b/pcsx2/tinyxml/tinyxml.cpp new file mode 100644 index 0000000..1bd61cd --- /dev/null +++ b/pcsx2/tinyxml/tinyxml.cpp @@ -0,0 +1,1866 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + + +bool TiXmlBase::condenseWhiteSpace = true; + +void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + return 0; + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return &node->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const char* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s ); + } + else { + *i = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const std::string* s = Attribute( name ); + if ( i ) + { + if ( s ) { + *i = atoi( s->c_str() ); + } + else { + *i = 0; + } + } + return s; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const char* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s ); + } + else { + *d = 0; + } + } + return s; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const std::string* s = Attribute( name ); + if ( d ) + { + if ( s ) { + *d = atof( s->c_str() ); + } + else { + *d = 0; + } + } + return s; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + return node->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); + #else + sprintf( buf, "%d", val ); + #endif + SetAttribute( name, buf ); +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + std::ostringstream oss; + oss << val; + SetAttribute( name, oss.str() ); +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); + #else + sprintf( buf, "%f", val ); + #endif + SetAttribute( name, buf ); +} + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING _name( cname ); + TIXML_STRING _value( cvalue ); + #else + const char* _name = cname; + const char* _value = cvalue; + #endif + + TiXmlAttribute* node = attributeSet.Find( _name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( _value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + // See STL_STRING_BUG below. + //StringToBuffer buf( value ); + + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + // See STL_STRING_BUG below. +// StringToBuffer buf( value ); +// +// if ( buf.buffer && SaveFile( buf.buffer ) ) +// return true; +// +// return false; + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // Add an extra string to avoid the crash. + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = fopen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length == 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve( length ); + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + const char* lastPos = buf; + const char* p = buf; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + if ( *p == 0xa ) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append( lastPos, (p-lastPos+1) ); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert( p <= (buf+length) ); + } + else if ( *p == 0xd ) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ( (p-lastPos) > 0 ) { + data.append( lastPos, p-lastPos ); // do not add the CR + } + data += (char)0xa; // a proper newline + + if ( *(p+1) == 0xa ) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert( p <= (buf+length) ); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert( p <= (buf+length) ); + } + } + else { + ++p; + } + } + // Handle any left over characters. + if ( p-lastPos ) { + data.append( lastPos, p-lastPos ); + } + delete [] buf; + buf = 0; + + Parse( data.c_str(), 0, encoding ); + + if ( Error() ) + return false; + else + return true; +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = fopen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorDesc = errorDesc.c_str (); + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + PutString( name, &n ); + PutString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( sscanf( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); + #else + sprintf (buf, "%lf", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + PutString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} +*/ +#endif + + +const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + +/* +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} +*/ + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + buffer += text.Value(); + } + else + { + DoIndent(); + buffer += text.Value(); + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/pcsx2/tinyxml/tinyxml.h b/pcsx2/tinyxml/tinyxml.h new file mode 100644 index 0000000..5391236 --- /dev/null +++ b/pcsx2/tinyxml/tinyxml.h @@ -0,0 +1,1776 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 2; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simple called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& doc ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& doc ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& element ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& declaration ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& text ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& comment ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& unknown ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Puts a string to a stream, expanding entities as it goes. + // Note this should not contian the '<', '>', etc, or they will be transformed into entities! + static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + + #endif + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + #ifdef TIXML_USE_STL + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + TiXmlDocument* doc = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + p = ReadText( p, &value, false, endTag, false, encoding ); + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + +// int tabsize = 4; +// if ( document ) +// tabsize = document->TabSize(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i +#include + +#include "resource.h" +#include "AboutDlg.h" +#include "Common.h" + +#define IDC_STATIC (-1) + +HWND hW; +HBITMAP hBMP, hSilverBMP; + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + hBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + hSilverBMP = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PS2SILVER)); + + hW = CreateWindow("STATIC", "", WS_VISIBLE | WS_CHILD | SS_BITMAP, + 230, 10, 211, 110, hDlg, (HMENU)IDC_STATIC, GetModuleHandle(NULL), NULL); + SendMessage(hW, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBMP); + + SetWindowText(hDlg, _("About")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_TEXT), _("PCSX2 EMU\n")); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_AUTHORS), _(LabelAuthors)); + Static_SetText(GetDlgItem(hDlg, IDC_PCSX_ABOUT_GREETS), _(LabelGreets)); + return TRUE; + + case WM_COMMAND: + switch(wParam) { + case IDOK: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/pcsx2/windows/AboutDlg.h b/pcsx2/windows/AboutDlg.h new file mode 100644 index 0000000..1a209be --- /dev/null +++ b/pcsx2/windows/AboutDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PCSX2_ABOUTDLG_H_ +#define _PCSX2_ABOUTDLG_H_ + +LRESULT WINAPI AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif diff --git a/pcsx2/windows/Cdrom02.ico b/pcsx2/windows/Cdrom02.ico new file mode 100644 index 0000000000000000000000000000000000000000..07588baeaa79ee6acf726e73fb70937a1dadb53e GIT binary patch literal 12862 zcmeHO>(f_d75()kE6fWRf~lFNF^(DOq=`*Kw`shE;~15usFWItiKUlh5G4rAsI13nq&$ zn@r|UCX+?@0X6v}e#pl+Z_Z@GpZM&fNB+m_Vf!fR*u$m*15oqCk91@z8&FR0H|bl| zGOhS`>uYo?WsSjTl)mm*9sL9ASabl@Ael04Q_M%>@V@}*mLN@zp2+#=?`^t{4Us7; z+lSgi@Y9E4*rBgaD%@O2+>rI_S{1<>I|3{31P^gM5+kw5H4z{*$^&HymP&VnVe$ol z30pEQDCf#hy~}MlD35M&SjK$rK~MXj%>+0i0MD9f$Tc=2!L$a93If+qDY1H*pfTXMX2}`~d1=YTogYDW=>WM?bI)WwDBp?>0|YOe@Y9e)8c1*41j8dBA2? zlS#m>^PSAMASpxd>+3_{_A318nYIGy<5#?OMh;4qFY*-^d~mS7AHiYsj!<={!JNuMNXg%|ax_u3h-1fyX5lJ`S$}?Am^yg?B52ct&9imH+&&l&{ zJM-1295POulfRL(t)eH+B$fbsmdxeHpX{wCBrC5305)S z58P=7Rd?6{uY>4d?qHRz<1ylUj4B=@MMx&R(+=Ej`%x zJQ09k;p5yXS;#Ya9Bn;{CnDAzM z`)2kmjY$&xjG9qCrt;SjAR}c|fVXa9z3n{##%X3Se|@f#Jj_+{04l9g0MM+OlSWye zzj>p*xy;_Wkwpx!tN@K;XdfV@hdT!9(~WHw zAd63!)6=WdD?ln8C|D7@ZR)k!dyTz*jqSbG0En;UNJgWtG!EuZB^>gQCT^Hpt=J`V zL8p&bq}Q#&$d))t!L$YW+D}-odl#PW+79NQ{WfiDka+gn=@^6hSAT4%SG>RaBSRG| z9!#tT^MBGLUsnbMi);XeMDicl9@Gz6uS8FP6|oCG>8OMLy=(~MNfb%_uirP;Qq~?- zjP(lJQ9fkY6A2NoLugvWxJQy?yKx2^d)5kiIIh^YRM?^{dG^GkV>dj>MwrBUcAzFU&%gujq(e0k&x4) zmL6$e__nE@50K2q%Qv>oh}Q?d7p`DDWy^#KxVqeSUC#deWvmW6zsnhQZ41U$VqD1q zW8yF*6MQ~|Cu$Qu?GA(axm5M^fs z^J&AfT|5|{k#xd%`IbnJ{oFV0xl6qgXso+d=qjv2yfXkyc21v&$*bzHJgO@<8T z7pv!#;n_=U$0hdcH@pJuzzD2SpfBUetOY?pKkQuOF(hJi%6Ok?pEB{OKOPv&pKix9-@eFD+q|}aJwPzx(V-dT+oniE!4&(Mi|m;TjlC{0 z6~FDGQR0_WcpdT7ducDUr!TOlzZP9U3~;|j`30H`z0q?%b-q3IRo0W|v&tw?b*x7D zn5V9Y%FNDh{fa$_I?uMAR{$^=junG(lrOW@d4S6ZaIS4RxAZON*jAOubGYKx!6^9| zDFS3pG7;>FvyJuTD2->^7BJ$0eHgf$7clr(6>YoME7Jv4Z8fUgXNRkIl2XHqEn5bIAZ?7vL(y1Lml1ldWZ%SEk1~wr-9e;ubjidgn0`fb;@R zzKFGQ4PTcGUFWWEPh=Q^V&05$2*WN|-YVD}Tl)ppI&@(OG&&Em9*Oe=pxMTXo?3aA zzYa^!=lm_k%aaIGzpIcXVJP*)+Rs~4k4`ZVh|E=j!P{nA-vT#VITRAvre3elbDJiQ ze$G&9y$cUADOh_F^{fC~1)jdm!*X?^hf+3p*pL|ibP@{znoj<+Wh)Iv$;ybUis7$N n`PAcpb11c{#lWfW9typ-^%X;YTBH31;@<&$`v3pWzreo$+!n*^ literal 0 HcmV?d00001 diff --git a/pcsx2/windows/ConfigDlg.c b/pcsx2/windows/ConfigDlg.c new file mode 100644 index 0000000..49e487c --- /dev/null +++ b/pcsx2/windows/ConfigDlg.c @@ -0,0 +1,502 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include //2002-09-22 (Florin) +#include "common.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +#define ComboAddPlugin(hw, str) { \ + sprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff); \ + lp = (char *)malloc(strlen(FindData.cFileName)+8); \ + sprintf(lp, "%s", FindData.cFileName); \ + i = ComboBox_AddString(hw, tmpStr); \ + ComboBox_SetItemData(hw, i, lp); \ + if (stricmp(str, lp)==0) \ + ComboBox_SetCurSel(hw, i); \ +} + +BOOL OnConfigureDialog(HWND hW) { + WIN32_FIND_DATA FindData; + HANDLE Find; + HANDLE Lib; + _PS2EgetLibType PS2E_GetLibType; + _PS2EgetLibName PS2E_GetLibName; + _PS2EgetLibVersion2 PS2E_GetLibVersion2; + HWND hWC_GS=GetDlgItem(hW,IDC_LISTGS); + HWND hWC_PAD1=GetDlgItem(hW,IDC_LISTPAD1); + HWND hWC_PAD2=GetDlgItem(hW,IDC_LISTPAD2); + HWND hWC_SPU2=GetDlgItem(hW,IDC_LISTSPU2); + HWND hWC_CDVD=GetDlgItem(hW,IDC_LISTCDVD); + HWND hWC_DEV9=GetDlgItem(hW,IDC_LISTDEV9); + HWND hWC_USB=GetDlgItem(hW,IDC_LISTUSB); + HWND hWC_FW=GetDlgItem(hW,IDC_LISTFW); + HWND hWC_BIOS=GetDlgItem(hW,IDC_LISTBIOS); + char tmpStr[256]; + char *lp; + int i; + + strcpy(tmpStr, Config.PluginsDir); + strcat(tmpStr, "*.dll"); + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + sprintf(tmpStr,"%s%s", Config.PluginsDir, FindData.cFileName); + Lib = LoadLibrary(tmpStr); + if (Lib == NULL) { SysPrintf("%s: %d\n", tmpStr, GetLastError()); continue; } + + PS2E_GetLibType = (_PS2EgetLibType) GetProcAddress((HMODULE)Lib,"PS2EgetLibType"); + PS2E_GetLibName = (_PS2EgetLibName) GetProcAddress((HMODULE)Lib,"PS2EgetLibName"); + PS2E_GetLibVersion2 = (_PS2EgetLibVersion2) GetProcAddress((HMODULE)Lib,"PS2EgetLibVersion2"); + + if (PS2E_GetLibType != NULL && PS2E_GetLibName != NULL && PS2E_GetLibVersion2 != NULL) { + u32 version; + long type; + + type = PS2E_GetLibType(); + if (type & PS2E_LT_GS) { + version = PS2E_GetLibVersion2(PS2E_LT_GS); + if ( ((version >> 16)&0xff) == PS2E_GS_VERSION) { + ComboAddPlugin(hWC_GS, Config.GS); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, 0xff&(version >> 16), PS2E_GS_VERSION); + } + if (type & PS2E_LT_PAD) { + _PADquery query; + + query = (_PADquery)GetProcAddress((HMODULE)Lib, "PADquery"); + version = PS2E_GetLibVersion2(PS2E_LT_PAD); + if (((version >> 16)&0xff) == PS2E_PAD_VERSION && query) { + if (query() & 0x1) + ComboAddPlugin(hWC_PAD1, Config.PAD1); + if (query() & 0x2) + ComboAddPlugin(hWC_PAD2, Config.PAD2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_PAD_VERSION); + } + if (type & PS2E_LT_SPU2) { + version = PS2E_GetLibVersion2(PS2E_LT_SPU2); + if ( ((version >> 16)&0xff) == PS2E_SPU2_VERSION) { + ComboAddPlugin(hWC_SPU2, Config.SPU2); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_SPU2_VERSION); + } + if (type & PS2E_LT_CDVD) { + version = PS2E_GetLibVersion2(PS2E_LT_CDVD); + if (((version >> 16)&0xff) == PS2E_CDVD_VERSION) { + ComboAddPlugin(hWC_CDVD, Config.CDVD); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_CDVD_VERSION); + } + if (type & PS2E_LT_DEV9) { + version = PS2E_GetLibVersion2(PS2E_LT_DEV9); + if (((version >> 16)&0xff) == PS2E_DEV9_VERSION) { + ComboAddPlugin(hWC_DEV9, Config.DEV9); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_DEV9_VERSION); + } + if (type & PS2E_LT_USB) { + version = PS2E_GetLibVersion2(PS2E_LT_USB); + if (((version >> 16)&0xff) == PS2E_USB_VERSION) { + ComboAddPlugin(hWC_USB, Config.USB); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_USB_VERSION); + } + if (type & PS2E_LT_FW) { + version = PS2E_GetLibVersion2(PS2E_LT_FW); + if (((version >> 16)&0xff) == PS2E_FW_VERSION) { + ComboAddPlugin(hWC_FW, Config.FW); + } else SysPrintf("Plugin %s: Version %x != %x\n", FindData.cFileName, (version >> 16)&0xff, PS2E_FW_VERSION); + } + } + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + +// BIOS + + /*lp=(char *)malloc(strlen("HLE") + 1); + sprintf(lp, "HLE"); + i=ComboBox_AddString(hWC_BIOS, _("Internal HLE Bios")); + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, lp)==0) + ComboBox_SetCurSel(hWC_BIOS, i);*/ + + strcpy(tmpStr, Config.BiosDir); + strcat(tmpStr, "*"); + Find=FindFirstFile(tmpStr, &FindData); + + do { + char description[50]; //2002-09-22 (Florin) + if (Find==INVALID_HANDLE_VALUE) break; + if (!strcmp(FindData.cFileName, ".")) continue; + if (!strcmp(FindData.cFileName, "..")) continue; +// if (FindData.nFileSizeLow < 1024 * 512) continue; + if (FindData.nFileSizeLow > 1024 * 4096) continue; //2002-09-22 (Florin) + if (!IsBIOS(FindData.cFileName, description)) continue;//2002-09-22 (Florin) + lp = (char *)malloc(strlen(FindData.cFileName)+8); + sprintf(lp, "%s", (char *)FindData.cFileName); + i = ComboBox_AddString(hWC_BIOS, description); //2002-09-22 (Florin) modified + ComboBox_SetItemData(hWC_BIOS, i, lp); + if (stricmp(Config.Bios, FindData.cFileName)==0) + ComboBox_SetCurSel(hWC_BIOS, i); + } while (FindNextFile(Find,&FindData)); + + if (Find!=INVALID_HANDLE_VALUE) FindClose(Find); + + if (ComboBox_GetCurSel(hWC_GS) == -1) + ComboBox_SetCurSel(hWC_GS, 0); + if (ComboBox_GetCurSel(hWC_PAD1) == -1) + ComboBox_SetCurSel(hWC_PAD1, 0); + if (ComboBox_GetCurSel(hWC_PAD2) == -1) + ComboBox_SetCurSel(hWC_PAD2, 0); + if (ComboBox_GetCurSel(hWC_SPU2) == -1) + ComboBox_SetCurSel(hWC_SPU2, 0); + if (ComboBox_GetCurSel(hWC_CDVD) == -1) + ComboBox_SetCurSel(hWC_CDVD, 0); + if (ComboBox_GetCurSel(hWC_DEV9) == -1) + ComboBox_SetCurSel(hWC_DEV9, 0); + if (ComboBox_GetCurSel(hWC_USB) == -1) + ComboBox_SetCurSel(hWC_USB, 0); + if (ComboBox_GetCurSel(hWC_FW) == -1) + ComboBox_SetCurSel(hWC_FW, 0); + if (ComboBox_GetCurSel(hWC_BIOS) == -1) + ComboBox_SetCurSel(hWC_BIOS, 0); + + return TRUE; +} + +#define CleanCombo(item) \ + hWC = GetDlgItem(hW, item); \ + iCnt = ComboBox_GetCount(hWC); \ + for (i=0; i +#include +#include +#include + +#include "Common.h" +#include "VUmicro.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + +#include "ix86/ix86.h" + +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char cpuspeedc[20]; + char features[256]; + u32 newopts; + + switch(uMsg) { + case WM_INITDIALOG: + SetWindowText(hW, _("Cpu Config")); + SetDlgItemText(hW, IDC_VENDORINPUT,cpuinfo.x86ID ); + SetDlgItemText(hW, IDC_FAMILYINPUT, cpuinfo.x86Fam); + sprintf(cpuspeedc,"%d MHZ",cpuinfo.cpuspeed); + SetDlgItemText(hW, IDC_CPUSPEEDINPUT, cpuspeedc); + Static_SetText(GetDlgItem(hW, IDC_VENDORNAME), _("CPU Vendor")); + Static_SetText(GetDlgItem(hW, IDC_FAMILYNAME), _("Family")); + Static_SetText(GetDlgItem(hW, IDC_CPUSPEEDNAME), _("CPU Speed")); + Static_SetText(GetDlgItem(hW, IDC_FEATURESNAME), _("Features")); + Static_SetText(GetDlgItem(hW, IDC_CPU_EEREC), _("EERec - EE/IOP recompiler (need MMX/SSE)")); + Static_SetText(GetDlgItem(hW, IDC_CPU_VUGROUP), _("VU Recompilers - All options are set by default")); + Static_SetText(GetDlgItem(hW, IDC_CPU_VU0REC), _("VU0rec - enable recompiler for VU0 unit")); + Static_SetText(GetDlgItem(hW, IDC_CPU_VU1REC), _("VU1rec - enable recompiler for VU1 unit")); + Static_SetText(GetDlgItem(hW, IDC_CPU_GSMULTI), _("Multi threaded GS mode (MTGS)\n(faster on dual core/HT procs, requires pcsx2 restart)")); + Static_SetText(GetDlgItem(hW, IDC_CPU_MULTI), _("Dual Core Mode (DC) - Much faster but only valid with MTGS")); + Static_SetText(GetDlgItem(hW, IDC_FRAMELIMIT), _("Frame Limiting")); + Static_SetText(GetDlgItem(hW, IDC_CPU_FL_NORMAL), _("Normal - All frames are rendered as fast as possible.")); + Static_SetText(GetDlgItem(hW, IDC_CPU_FL_LIMIT), _("Limit - Force frames to normal speeds if too fast.")); + Static_SetText(GetDlgItem(hW, IDC_CPU_FL_SKIP), _("Frame Skip - In order to achieve normal speeds,\nsome frames are skipped (fast).\nFps displayed counts skipped frames too.")); + Static_SetText(GetDlgItem(hW, IDC_CPU_FL_SKIPVU), _("VU Skip - Same as 'Frame Skip', but tries to skip more.\nArtifacts might be present, but will be faster.")); + Button_SetText(GetDlgItem(hW, IDOK), _("OK")); + Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel")); + //features[0]=':'; + //strcat(features,""); + strcpy(features,""); + if(cpucaps.hasMultimediaExtensions) strcat(features,"MMX"); + if(cpucaps.hasStreamingSIMDExtensions) strcat(features,",SSE"); + if(cpucaps.hasStreamingSIMD2Extensions) strcat(features,",SSE2"); + if(cpucaps.hasStreamingSIMD3Extensions) strcat(features,",SSE3"); +// if(cpucaps.has3DNOWInstructionExtensions) strcat(features,",3DNOW"); +// if(cpucaps.has3DNOWInstructionExtensionsExt)strcat(features,",3DNOW+"); + if(cpucaps.hasAMD64BitArchitecture) strcat(features,",x86-64"); + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + if(!cpucaps.hasStreamingSIMDExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILERVU),FALSE);//disable checkbox if no SSE2 found + Config.Options &= (PCSX2_VU0REC|PCSX2_VU1REC);//disable the config just in case + } + if(!cpucaps.hasMultimediaExtensions) + { + EnableWindow(GetDlgItem(hW,IDC_RADIORECOMPILER),FALSE); + Config.Options &= ~(PCSX2_EEREC|PCSX2_VU0REC|PCSX2_VU1REC|PCSX2_COP2REC);//return to interpreter mode + + } + SetDlgItemText(hW, IDC_FEATURESINPUT, features); + + CheckDlgButton(hW, IDC_CPU_EEREC, !!CHECK_EEREC); + +//#ifdef PCSX2_DEVBUILD + CheckDlgButton(hW, IDC_CPU_VU0REC, !!CHECK_VU0REC); + CheckDlgButton(hW, IDC_CPU_VU1REC, !!CHECK_VU1REC); +//#else +// // don't show +// ShowWindow(GetDlgItem(hW, IDC_CPU_VUGROUP), SW_HIDE); +// ShowWindow(GetDlgItem(hW, IDC_CPU_VU0REC), SW_HIDE); +// ShowWindow(GetDlgItem(hW, IDC_CPU_VU1REC), SW_HIDE); +//#endif + + CheckDlgButton(hW, IDC_CPU_GSMULTI, !!CHECK_MULTIGS); + CheckDlgButton(hW, IDC_CPU_MULTI, !!CHECK_DUALCORE); + + CheckRadioButton(hW,IDC_CPU_FL_NORMAL, IDC_CPU_FL_NORMAL+3, IDC_CPU_FL_NORMAL+(CHECK_FRAMELIMIT>>10)); + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + + case IDOK: + Cpu->Shutdown(); + vu0Shutdown(); + vu1Shutdown(); + + newopts = 0; + + if( SendDlgItemMessage(hW,IDC_CPU_EEREC,BM_GETCHECK,0,0) ) newopts |= PCSX2_EEREC; + +#ifdef PCSX2_DEVBUILD + if( SendDlgItemMessage(hW,IDC_CPU_VU0REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU0REC; + if( SendDlgItemMessage(hW,IDC_CPU_VU1REC,BM_GETCHECK,0,0) ) newopts |= PCSX2_VU1REC; +#else + newopts |= PCSX2_VU0REC|PCSX2_VU1REC; +#endif + + if( SendDlgItemMessage(hW,IDC_CPU_GSMULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_GSMULTITHREAD; + if( SendDlgItemMessage(hW,IDC_CPU_MULTI,BM_GETCHECK,0,0) ) newopts |= PCSX2_DUALCORE; + if( SendDlgItemMessage(hW,IDC_CPU_FRAMELIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT; + + if( SendDlgItemMessage(hW,IDC_CPU_FL_NORMAL,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_NORMAL; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_LIMIT,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_LIMIT; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIP,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_SKIP; + else if( SendDlgItemMessage(hW,IDC_CPU_FL_SKIPVU,BM_GETCHECK,0,0) ) newopts |= PCSX2_FRAMELIMIT_VUSKIP; + + if( (Config.Options&PCSX2_GSMULTITHREAD) ^ (newopts&PCSX2_GSMULTITHREAD) ) { + Config.Options = newopts; + SaveConfig(); + MessageBox(NULL, "Restart Pcsx2", "Query", MB_OK); + exit(0); + } + + if( newopts & PCSX2_EEREC ) newopts |= PCSX2_COP2REC; + + Config.Options = newopts; + + UpdateVSyncRate(); + SaveConfig(); + + cpuRestartCPU(); + EndDialog(hW, TRUE); + return TRUE; + } + } + return FALSE; +} diff --git a/pcsx2/windows/DebugMemory.c b/pcsx2/windows/DebugMemory.c new file mode 100644 index 0000000..f033bc7 --- /dev/null +++ b/pcsx2/windows/DebugMemory.c @@ -0,0 +1,239 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Common.h" +#include "resource.h" + + +unsigned long memory_addr; +BOOL mem_inupdate = FALSE; +HWND memoryhWnd,hWnd_memscroll,hWnd_memorydump; +unsigned long memory_patch; +unsigned long data_patch; + +///MEMORY DUMP +unsigned char Debug_Read8(unsigned long addr)//just for anycase.. +{ +#ifdef _WIN32 + __try + { +#endif + u8 val8; + memRead8(addr, &val8); + return val8; +#ifdef _WIN32 + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return 0; + } +#endif +} + + +void RefreshMemory(void) +{ + int x, y; + unsigned long addr; + unsigned char b; + + char buf[128], text[32], temp[8]; + + + + addr = memory_addr; + + if (!mem_inupdate) + { + sprintf(buf, "%08X", addr); + SetDlgItemText(memoryhWnd, IDC_MEMORY_ADDR, buf); + } + + SendMessage(hWnd_memorydump, LB_RESETCONTENT, 0, 0); + + for (y = 0; y < 21; y++) + { + memset(text, 0, 32); + sprintf(buf, "%08X: ", addr); + + for (x = 0; x < 16; x++) + { + b = Debug_Read8(addr++); + + sprintf(temp, "%02X ", b); + strcat(buf, temp); + + if (b < 32 || b > 127) b = 32; + sprintf(temp, "%c", b); + strcat(text, temp); + + + if (x == 7) strcat(buf, " "); + } + + strcat(buf, " "); + strcat(buf, text); + + SendMessage(hWnd_memorydump, LB_ADDSTRING, 0, (LPARAM)buf); + } +} + + +BOOL APIENTRY DumpMemProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], buf[128]; + u32 start_pc, end_pc, addr; + u8 data; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMPMEM_START, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_END, buf); + SetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, "dump.raw"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMPMEM_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMPMEM_FNAME, fname, 128); + fp = fopen(fname, "wb"); + if (fp == NULL) + { + SysMessage("Can't open file '%s' for writing!\n", fname); + } + else + { + for (addr = start_pc; addr < end_pc; addr ++) { + memRead8( addr, &data ); + fwrite(&data, 1, 1, fp); + } + + fclose(fp); + } + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + + + +BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + char buf[16]; + switch (message) + { + case WM_INITDIALOG: + memory_addr = cpuRegs.pc; + sprintf(buf, "%08X", memory_addr); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + memory_patch= 0; + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf); + data_patch=0; + sprintf(buf, "%08X", data_patch); + SetDlgItemText(hDlg, IDC_DATA_PATCH, buf); + hWnd_memorydump = GetDlgItem(hDlg, IDC_MEMORY_DUMP); + hWnd_memscroll = GetDlgItem(hDlg, IDC_MEM_SCROLL); + + + + SendMessage(hWnd_memorydump, LB_INITSTORAGE, 11, 1280); + SendMessage(hWnd_memscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_memscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + RefreshMemory(); + return TRUE; + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + case SB_LINEDOWN: memory_addr += 0x00000010; RefreshMemory(); break; + case SB_LINEUP: memory_addr -= 0x00000010; RefreshMemory(); break; + case SB_PAGEDOWN: memory_addr += 0x00000150; RefreshMemory(); break; + case SB_PAGEUP: memory_addr -= 0x00000150; RefreshMemory(); break; + } + + return TRUE; + + case WM_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + + + case WM_COMMAND: + if (HIWORD(wParam) == EN_UPDATE) + { + mem_inupdate = TRUE; + GetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf, 9); + buf[8] = 0; + + sscanf(buf, "%x", &memory_addr); + RefreshMemory(); + mem_inupdate = FALSE; + return TRUE; + } + + switch (LOWORD(wParam)) { + case IDC_PATCH: + GetDlgItemText(hDlg, IDC_ADDRESS_PATCH, buf, 9);//32bit address + buf[8] = 0; + sscanf(buf, "%x", &memory_patch); + GetDlgItemText(hDlg, IDC_DATA_PATCH, buf, 9);//32 bit data only for far + buf[8] = 0; + sscanf(buf, "%x", &data_patch); + memWrite32( memory_patch, data_patch ); + sprintf(buf, "%08X", memory_patch); + SetDlgItemText(hDlg, IDC_MEMORY_ADDR, buf); + RefreshMemory(); + return TRUE; + + case IDC_DUMPRAW: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMPMEM), hDlg, (DLGPROC)DumpMemProc); + + return TRUE; + + case IDC_MEMORY_CLOSE: + EndDialog(hDlg, TRUE ); + return TRUE; + } + break; + } + + return FALSE; +} diff --git a/pcsx2/windows/Debugger.c b/pcsx2/windows/Debugger.c new file mode 100644 index 0000000..ac5a260 --- /dev/null +++ b/pcsx2/windows/Debugger.c @@ -0,0 +1,560 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "Common.h" +#include "win32.h" +#include "PsxMem.h" +#include "R3000A.h" + +extern void (*IOP_DEBUG_BSC[64])(char *buf); +extern void UpdateR5900op(); +void RefreshIOPDebugger(void); +extern int ISR3000A;//for disasm +HWND hWnd_debugdisasm, hWnd_debugscroll,hWnd_IOP_debugdisasm, hWnd_IOP_debugscroll; +unsigned long DebuggerPC = 0; +HWND hRegDlg;//for debug registers.. +HWND debughWnd; +unsigned long DebuggerIOPPC=0; +HWND hIOPDlg;//IOP debugger + + +void RefreshDebugAll()//refresh disasm and register window +{ + RefreshDebugger(); + RefreshIOPDebugger(); + UpdateRegs(); + + +} + +void MakeDebugOpcode(void) +{ + memRead32( opcode_addr, &cpuRegs.code ); +} + +void MakeIOPDebugOpcode(void) +{ + psxRegs.code = PSXMu32( opcode_addr); +} + +BOOL HasBreakpoint() +{ + int t; + + for (t = 0; t < NUM_BREAKPOINTS; t++) + { + switch (bkpt_regv[t].type) { + case 1: // exec + if (cpuRegs.pc == bkpt_regv[t].value) return TRUE; + break; + + case 2: // count + if ((cpuRegs.cycle - 10) <= bkpt_regv[t].value && + (cpuRegs.cycle + 10) >= bkpt_regv[t].value) return TRUE; + break; + } + } + return FALSE; + +} +BOOL APIENTRY JumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + unsigned long temp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_JUMP_PC, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_JUMP_PC, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &temp); + + temp &= 0xFFFFFFFC; + DebuggerPC = temp - 0x00000038; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +extern void EEDumpRegs(FILE * fp); +extern void IOPDumpRegs(FILE * fp); +BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char start[16], end[16], fname[128], tmp[128], buf[128]; + unsigned long start_pc, end_pc, temp; + + FILE *fp; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", cpuRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_START, buf); + SetDlgItemText(hDlg, IDC_DUMP_END, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt"); + + sprintf(buf, "%08X", psxRegs.pc); + SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf); + SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt"); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_DUMP_START, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_END, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAME, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"EE DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + + + opcode_addr=temp; + MakeDebugOpcode(); + OpcodePrintTable[(cpuRegs.code) >> 26](tmp); + if (HasBreakpoint(temp)) + { + sprintf(buf, "*%08X %08X: %s", temp, cpuRegs.code, tmp); + } + else + { + sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp); + } + + fprintf(fp, "%s\n", buf); + } + + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"EE REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + EEDumpRegs(fp); + fclose(fp); + } + + + + GetDlgItemText(hDlg, IDC_DUMP_STARTIOP, start, 9); + start[8] = 0; + sscanf(start, "%x", &start_pc); + start_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_ENDIOP, end, 9); + end[8] = 0; + sscanf(end, "%x", &end_pc); + end_pc &= 0xFFFFFFFC; + + GetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, fname, 128); + fp = fopen(fname, "wt"); + if (fp == NULL) + { + //MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK); + } + else + { + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"IOP DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + for (temp = start_pc; temp <= end_pc; temp += 4) + { + opcode_addr=temp; + MakeIOPDebugOpcode(); + IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp); + sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp); + fprintf(fp, "%s\n", buf); + } + + fprintf(fp,"\n\n\n----------------------------------\n"); + fprintf(fp,"IOP REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n"); + fprintf(fp,"----------------------------------\n"); + IOPDumpRegs(fp); + fclose(fp); + } + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpexecProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[0].value); + SetDlgItemText(hDlg, IDC_EXECBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_EXECBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[0].value); + bkpt_regv[0].type = 1; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +BOOL APIENTRY BpcntProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[16]; + + switch (message) + { + case WM_INITDIALOG: + sprintf(buf, "%08X", bkpt_regv[1].value); + SetDlgItemText(hDlg, IDC_CNTBP, buf); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + GetDlgItemText(hDlg, IDC_CNTBP, buf, 9); + + buf[8] = 0; + sscanf(buf, "%x", &bkpt_regv[1].value); + bkpt_regv[1].type = 2; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} +HINSTANCE m2_hInst; +HWND m2_hWnd; +HWND hIopDlg; + +LRESULT CALLBACK IOP_DISASM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + hWnd_IOP_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM_IOP); + hWnd_IOP_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL_IOP); + + SendMessage(hWnd_IOP_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_IOP_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_IOP_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + RefreshIOPDebugger(); + return (TRUE); + case WM_VSCROLL: + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerIOPPC += 0x00000004; RefreshIOPDebugger(); break; + case SB_LINEUP: DebuggerIOPPC -= 0x00000004; RefreshIOPDebugger(); break; + case SB_PAGEDOWN: DebuggerIOPPC += 0x00000029; RefreshIOPDebugger(); break; + case SB_PAGEUP: DebuggerIOPPC -= 0x00000029; RefreshIOPDebugger(); break; + } + return TRUE; + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +int CreatePropertySheet2(HWND hwndOwner) +{ + PROPSHEETPAGE psp[1]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m2_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_IOP_DEBUG); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)IOP_DISASM; + psp[0].pszTitle = "Iop Disasm"; + psp[0].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m2_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "IOP Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); +} + +BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + FARPROC jmpproc, dumpproc; + FARPROC bpexecproc, bpcntproc; + u32 oldpc = 0; + + switch (message) + { + case WM_INITDIALOG: + ShowCursor(TRUE); + + SetWindowText(hDlg, "R5900 Debugger"); + debughWnd=hDlg; + DebuggerPC = 0; + // Clear all breakpoints. + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + + hWnd_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM); + hWnd_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL); + + SendMessage(hWnd_debugdisasm, LB_INITSTORAGE, 29, 1131); + SendMessage(hWnd_debugscroll, SBM_SETRANGE, 0, MAXLONG); + SendMessage(hWnd_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE); + + hRegDlg = (HWND)CreatePropertySheet(hDlg); + hIopDlg = (HWND)CreatePropertySheet2(hDlg); + UpdateRegs(); + SetWindowPos(hRegDlg, NULL, 425, 0, 600, 515,0 ); + SetWindowPos(hIopDlg, NULL, 0 ,515,600,230,0); + RefreshDebugger(); + + + + RefreshIOPDebugger(); + return TRUE; + + case WM_VSCROLL: + + switch ((int) LOWORD(wParam)) + { + + case SB_LINEDOWN: DebuggerPC += 0x00000004; RefreshDebugAll(); break; + case SB_LINEUP: DebuggerPC -= 0x00000004; RefreshDebugAll(); break; + case SB_PAGEDOWN: DebuggerPC += 0x00000074; RefreshDebugAll(); break; + case SB_PAGEUP: DebuggerPC -= 0x00000074; RefreshDebugAll(); break; + } + + + + + return TRUE; + + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_DEBUG_STEP: + oldpc = psxRegs.pc; + Cpu->Step(); + while(oldpc == psxRegs.pc) Cpu->Step(); + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_SKIP: + cpuRegs.pc+= 4; + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_GO: + for (;;) { + if (HasBreakpoint()) { + Cpu->Step(); + break; + } + Cpu->Step(); + } + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_LOG: +#ifdef PCSX2_DEVBUILD + Log = 1 - Log; +#endif + return TRUE; + + case IDC_DEBUG_RESETTOPC: + DebuggerPC = 0; + RefreshDebugAll(); + return TRUE; + + case IDC_DEBUG_JUMP: + jmpproc = MakeProcInstance((FARPROC)JumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_JUMP), debughWnd, (DLGPROC)jmpproc); + FreeProcInstance(jmpproc); + + RefreshDebugAll(); + return TRUE; + case IDC_CPUOP: + + UpdateR5900op(); + return TRUE; + + case IDC_DEBUG_BP_EXEC: + bpexecproc = MakeProcInstance((FARPROC)BpexecProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPEXEC), debughWnd, (DLGPROC)bpexecproc); + FreeProcInstance(bpexecproc); + + return TRUE; + + case IDC_DEBUG_BP_COUNT: + bpcntproc = MakeProcInstance((FARPROC)BpcntProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPCNT), debughWnd, (DLGPROC)bpcntproc); + FreeProcInstance(bpcntproc); + return TRUE; + + case IDC_DEBUG_BP_CLEAR: + memset(bkpt_regv, 0, sizeof(bkpt_regv)); + return TRUE; + + case IDC_DEBUG_DUMP: + dumpproc = MakeProcInstance((FARPROC)DumpProc, MainhInst); + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMP), debughWnd, (DLGPROC)dumpproc); + FreeProcInstance(dumpproc); + return TRUE; + + case IDC_DEBUG_MEMORY: + DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), debughWnd, (DLGPROC)MemoryProc); + return TRUE; + + case IDC_DEBUG_CLOSE: + + EndDialog(hRegDlg ,TRUE); + EndDialog(hDlg,TRUE); + EndDialog(hIopDlg,TRUE); + + ClosePlugins(); + + return TRUE; + } + break; + } + + return FALSE; +} + +void RefreshDebugger(void) +{ + unsigned long t; + int cnt; + + + + if (DebuggerPC == 0) + DebuggerPC = cpuRegs.pc; //- 0x00000038; + + SendMessage(hWnd_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerPC, cnt = 0; t < (DebuggerPC + 0x00000074); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 *mem = (u32*)PSM(t); + char *str; + if (mem == NULL) { + char nullAddr[256]; + sprintf(nullAddr, "%8.8lx 00000000: NULL MEMORY", t); str = nullAddr; + } else { + str = disR5900Fasm(*mem, t); + } + SendMessage(hWnd_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} + +void RefreshIOPDebugger(void) +{ + unsigned long t; + int cnt; + + DebuggerIOPPC = psxRegs.pc; //- 0x00000038; + + SendMessage(hWnd_IOP_debugdisasm, LB_RESETCONTENT, 0, 0); + + for (t = DebuggerIOPPC, cnt = 0; t < (DebuggerIOPPC + 0x00000029); t += 0x00000004, cnt++) + { + // Make the opcode. + u32 mem = PSXMu32(t); + char *str = disR3000Fasm(mem, t); + SendMessage(hWnd_IOP_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str); + } + +} diff --git a/pcsx2/windows/Debugger.h b/pcsx2/windows/Debugger.h new file mode 100644 index 0000000..d4e3d20 --- /dev/null +++ b/pcsx2/windows/Debugger.h @@ -0,0 +1,54 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#define NUM_BREAKPOINTS 8 + +extern void (*OpcodePrintTable[64])(char *buf); + +extern BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + + +extern BOOL APIENTRY MemoryProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern void RefreshDebugger(void); + +unsigned long opcode_addr; + +typedef struct +{ + int type; + unsigned long value; +} breakpoints; + +breakpoints bkpt_regv[NUM_BREAKPOINTS]; + + + +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +void UpdateRegs(void); +int CreatePropertySheet(HWND hwndOwner); diff --git a/pcsx2/windows/Debugreg.c b/pcsx2/windows/Debugreg.c new file mode 100644 index 0000000..3edc325 --- /dev/null +++ b/pcsx2/windows/Debugreg.c @@ -0,0 +1,1483 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 +#include +#include + +#include "resource.h" +#include "Debugger.h" +#include "Debug.h" +#include "R5900.h" +#include "R3000a.h" +#include "VUmicro.h" + +HINSTANCE m_hInst; +HWND m_hWnd; +char text1[256]; + + +/*R3000a registers handle */ +static HWND IOPGPR0Handle=NULL; +static HWND IOPGPR1Handle=NULL; +static HWND IOPGPR2Handle=NULL; +static HWND IOPGPR3Handle=NULL; +static HWND IOPGPR4Handle=NULL; +static HWND IOPGPR5Handle=NULL; +static HWND IOPGPR6Handle=NULL; +static HWND IOPGPR7Handle=NULL; +static HWND IOPGPR8Handle=NULL; +static HWND IOPGPR9Handle=NULL; +static HWND IOPGPR10Handle=NULL; +static HWND IOPGPR11Handle=NULL; +static HWND IOPGPR12Handle=NULL; +static HWND IOPGPR13Handle=NULL; +static HWND IOPGPR14Handle=NULL; +static HWND IOPGPR15Handle=NULL; +static HWND IOPGPR16Handle=NULL; +static HWND IOPGPR17Handle=NULL; +static HWND IOPGPR18Handle=NULL; +static HWND IOPGPR19Handle=NULL; +static HWND IOPGPR20Handle=NULL; +static HWND IOPGPR21Handle=NULL; +static HWND IOPGPR22Handle=NULL; +static HWND IOPGPR23Handle=NULL; +static HWND IOPGPR24Handle=NULL; +static HWND IOPGPR25Handle=NULL; +static HWND IOPGPR26Handle=NULL; +static HWND IOPGPR27Handle=NULL; +static HWND IOPGPR28Handle=NULL; +static HWND IOPGPR29Handle=NULL; +static HWND IOPGPR30Handle=NULL; +static HWND IOPGPR31Handle=NULL; +static HWND IOPGPRPCHandle=NULL; +static HWND IOPGPRHIHandle=NULL; +static HWND IOPGPRLOHandle=NULL; + +/*R5900 registers handle */ +static HWND GPR0Handle=NULL; +static HWND GPR1Handle=NULL; +static HWND GPR2Handle=NULL; +static HWND GPR3Handle=NULL; +static HWND GPR4Handle=NULL; +static HWND GPR5Handle=NULL; +static HWND GPR6Handle=NULL; +static HWND GPR7Handle=NULL; +static HWND GPR8Handle=NULL; +static HWND GPR9Handle=NULL; +static HWND GPR10Handle=NULL; +static HWND GPR11Handle=NULL; +static HWND GPR12Handle=NULL; +static HWND GPR13Handle=NULL; +static HWND GPR14Handle=NULL; +static HWND GPR15Handle=NULL; +static HWND GPR16Handle=NULL; +static HWND GPR17Handle=NULL; +static HWND GPR18Handle=NULL; +static HWND GPR19Handle=NULL; +static HWND GPR20Handle=NULL; +static HWND GPR21Handle=NULL; +static HWND GPR22Handle=NULL; +static HWND GPR23Handle=NULL; +static HWND GPR24Handle=NULL; +static HWND GPR25Handle=NULL; +static HWND GPR26Handle=NULL; +static HWND GPR27Handle=NULL; +static HWND GPR28Handle=NULL; +static HWND GPR29Handle=NULL; +static HWND GPR30Handle=NULL; +static HWND GPR31Handle=NULL; +static HWND GPRPCHandle=NULL; +static HWND GPRHIHandle=NULL; +static HWND GPRLOHandle=NULL; +/*end of r3000a registers handle */ +/*cop0 registers here */ +static HWND COP00Handle=NULL; +static HWND COP01Handle=NULL; +static HWND COP02Handle=NULL; +static HWND COP03Handle=NULL; +static HWND COP04Handle=NULL; +static HWND COP05Handle=NULL; +static HWND COP06Handle=NULL; +static HWND COP07Handle=NULL; +static HWND COP08Handle=NULL; +static HWND COP09Handle=NULL; +static HWND COP010Handle=NULL; +static HWND COP011Handle=NULL; +static HWND COP012Handle=NULL; +static HWND COP013Handle=NULL; +static HWND COP014Handle=NULL; +static HWND COP015Handle=NULL; +static HWND COP016Handle=NULL; +static HWND COP017Handle=NULL; +static HWND COP018Handle=NULL; +static HWND COP019Handle=NULL; +static HWND COP020Handle=NULL; +static HWND COP021Handle=NULL; +static HWND COP022Handle=NULL; +static HWND COP023Handle=NULL; +static HWND COP024Handle=NULL; +static HWND COP025Handle=NULL; +static HWND COP026Handle=NULL; +static HWND COP027Handle=NULL; +static HWND COP028Handle=NULL; +static HWND COP029Handle=NULL; +static HWND COP030Handle=NULL; +static HWND COP031Handle=NULL; +static HWND COP0PCHandle=NULL; +static HWND COP0HIHandle=NULL; +static HWND COP0LOHandle=NULL; +/*end of cop0 registers */ +/*cop1 registers here */ +static HWND COP10Handle=NULL; +static HWND COP11Handle=NULL; +static HWND COP12Handle=NULL; +static HWND COP13Handle=NULL; +static HWND COP14Handle=NULL; +static HWND COP15Handle=NULL; +static HWND COP16Handle=NULL; +static HWND COP17Handle=NULL; +static HWND COP18Handle=NULL; +static HWND COP19Handle=NULL; +static HWND COP110Handle=NULL; +static HWND COP111Handle=NULL; +static HWND COP112Handle=NULL; +static HWND COP113Handle=NULL; +static HWND COP114Handle=NULL; +static HWND COP115Handle=NULL; +static HWND COP116Handle=NULL; +static HWND COP117Handle=NULL; +static HWND COP118Handle=NULL; +static HWND COP119Handle=NULL; +static HWND COP120Handle=NULL; +static HWND COP121Handle=NULL; +static HWND COP122Handle=NULL; +static HWND COP123Handle=NULL; +static HWND COP124Handle=NULL; +static HWND COP125Handle=NULL; +static HWND COP126Handle=NULL; +static HWND COP127Handle=NULL; +static HWND COP128Handle=NULL; +static HWND COP129Handle=NULL; +static HWND COP130Handle=NULL; +static HWND COP131Handle=NULL; +static HWND COP1C0Handle=NULL; +static HWND COP1C1Handle=NULL; +static HWND COP1ACCHandle=NULL; +/*end of cop1 registers */ +/*cop2 floating registers*/ +static HWND VU0F00Handle=NULL; +static HWND VU0F01Handle=NULL; +static HWND VU0F02Handle=NULL; +static HWND VU0F03Handle=NULL; +static HWND VU0F04Handle=NULL; +static HWND VU0F05Handle=NULL; +static HWND VU0F06Handle=NULL; +static HWND VU0F07Handle=NULL; +static HWND VU0F08Handle=NULL; +static HWND VU0F09Handle=NULL; +static HWND VU0F10Handle=NULL; +static HWND VU0F11Handle=NULL; +static HWND VU0F12Handle=NULL; +static HWND VU0F13Handle=NULL; +static HWND VU0F14Handle=NULL; +static HWND VU0F15Handle=NULL; +static HWND VU0F16Handle=NULL; +static HWND VU0F17Handle=NULL; +static HWND VU0F18Handle=NULL; +static HWND VU0F19Handle=NULL; +static HWND VU0F20Handle=NULL; +static HWND VU0F21Handle=NULL; +static HWND VU0F22Handle=NULL; +static HWND VU0F23Handle=NULL; +static HWND VU0F24Handle=NULL; +static HWND VU0F25Handle=NULL; +static HWND VU0F26Handle=NULL; +static HWND VU0F27Handle=NULL; +static HWND VU0F28Handle=NULL; +static HWND VU0F29Handle=NULL; +static HWND VU0F30Handle=NULL; +static HWND VU0F31Handle=NULL; +/*end of cop2 floating registers*/ +/*cop2 control registers */ +static HWND VU0C00Handle=NULL; +static HWND VU0C01Handle=NULL; +static HWND VU0C02Handle=NULL; +static HWND VU0C03Handle=NULL; +static HWND VU0C04Handle=NULL; +static HWND VU0C05Handle=NULL; +static HWND VU0C06Handle=NULL; +static HWND VU0C07Handle=NULL; +static HWND VU0C08Handle=NULL; +static HWND VU0C09Handle=NULL; +static HWND VU0C10Handle=NULL; +static HWND VU0C11Handle=NULL; +static HWND VU0C12Handle=NULL; +static HWND VU0C13Handle=NULL; +static HWND VU0C14Handle=NULL; +static HWND VU0C15Handle=NULL; +static HWND VU0C16Handle=NULL; +static HWND VU0C17Handle=NULL; +static HWND VU0C18Handle=NULL; +static HWND VU0C19Handle=NULL; +static HWND VU0C20Handle=NULL; +static HWND VU0C21Handle=NULL; +static HWND VU0C22Handle=NULL; +static HWND VU0C23Handle=NULL; +static HWND VU0C24Handle=NULL; +static HWND VU0C25Handle=NULL; +static HWND VU0C26Handle=NULL; +static HWND VU0C27Handle=NULL; +static HWND VU0C28Handle=NULL; +static HWND VU0C29Handle=NULL; +static HWND VU0C30Handle=NULL; +static HWND VU0C31Handle=NULL; +static HWND VU0ACCHandle=NULL; +/*end of cop2 control registers */ +/*vu1 floating registers*/ +static HWND VU1F00Handle=NULL; +static HWND VU1F01Handle=NULL; +static HWND VU1F02Handle=NULL; +static HWND VU1F03Handle=NULL; +static HWND VU1F04Handle=NULL; +static HWND VU1F05Handle=NULL; +static HWND VU1F06Handle=NULL; +static HWND VU1F07Handle=NULL; +static HWND VU1F08Handle=NULL; +static HWND VU1F09Handle=NULL; +static HWND VU1F10Handle=NULL; +static HWND VU1F11Handle=NULL; +static HWND VU1F12Handle=NULL; +static HWND VU1F13Handle=NULL; +static HWND VU1F14Handle=NULL; +static HWND VU1F15Handle=NULL; +static HWND VU1F16Handle=NULL; +static HWND VU1F17Handle=NULL; +static HWND VU1F18Handle=NULL; +static HWND VU1F19Handle=NULL; +static HWND VU1F20Handle=NULL; +static HWND VU1F21Handle=NULL; +static HWND VU1F22Handle=NULL; +static HWND VU1F23Handle=NULL; +static HWND VU1F24Handle=NULL; +static HWND VU1F25Handle=NULL; +static HWND VU1F26Handle=NULL; +static HWND VU1F27Handle=NULL; +static HWND VU1F28Handle=NULL; +static HWND VU1F29Handle=NULL; +static HWND VU1F30Handle=NULL; +static HWND VU1F31Handle=NULL; +/*end of vu1 floating registers*/ +/*vu1 control registers */ +static HWND VU1C00Handle=NULL; +static HWND VU1C01Handle=NULL; +static HWND VU1C02Handle=NULL; +static HWND VU1C03Handle=NULL; +static HWND VU1C04Handle=NULL; +static HWND VU1C05Handle=NULL; +static HWND VU1C06Handle=NULL; +static HWND VU1C07Handle=NULL; +static HWND VU1C08Handle=NULL; +static HWND VU1C09Handle=NULL; +static HWND VU1C10Handle=NULL; +static HWND VU1C11Handle=NULL; +static HWND VU1C12Handle=NULL; +static HWND VU1C13Handle=NULL; +static HWND VU1C14Handle=NULL; +static HWND VU1C15Handle=NULL; +static HWND VU1C16Handle=NULL; +static HWND VU1C17Handle=NULL; +static HWND VU1C18Handle=NULL; +static HWND VU1C19Handle=NULL; +static HWND VU1C20Handle=NULL; +static HWND VU1C21Handle=NULL; +static HWND VU1C22Handle=NULL; +static HWND VU1C23Handle=NULL; +static HWND VU1C24Handle=NULL; +static HWND VU1C25Handle=NULL; +static HWND VU1C26Handle=NULL; +static HWND VU1C27Handle=NULL; +static HWND VU1C28Handle=NULL; +static HWND VU1C29Handle=NULL; +static HWND VU1C30Handle=NULL; +static HWND VU1C31Handle=NULL; +static HWND VU1ACCHandle=NULL; +/*end of vu1 control registers */ + +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +//comctl32 lib must add to project.. +int CreatePropertySheet(HWND hwndOwner) +{ + + PROPSHEETPAGE psp[7]; + PROPSHEETHEADER psh; + + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_USETITLE; + psp[0].hInstance = m_hInst; + psp[0].pszTemplate = MAKEINTRESOURCE( IDD_GPREGS); + psp[0].pszIcon = NULL; + psp[0].pfnDlgProc =(DLGPROC)R5900reg; + psp[0].pszTitle = "R5900"; + psp[0].lParam = 0; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = PSP_USETITLE; + psp[1].hInstance = m_hInst; + psp[1].pszTemplate = MAKEINTRESOURCE( IDD_CP0REGS ); + psp[1].pszIcon = NULL; + psp[1].pfnDlgProc =(DLGPROC)COP0reg; + psp[1].pszTitle = "COP0"; + psp[1].lParam = 0; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = PSP_USETITLE; + psp[2].hInstance = m_hInst; + psp[2].pszTemplate = MAKEINTRESOURCE( IDD_CP1REGS ); + psp[2].pszIcon = NULL; + psp[2].pfnDlgProc =(DLGPROC)COP1reg; + psp[2].pszTitle = "COP1"; + psp[2].lParam = 0; + + psp[3].dwSize = sizeof(PROPSHEETPAGE); + psp[3].dwFlags = PSP_USETITLE; + psp[3].hInstance = m_hInst; + psp[3].pszTemplate = MAKEINTRESOURCE( IDD_VU0REGS ); + psp[3].pszIcon = NULL; + psp[3].pfnDlgProc =(DLGPROC)COP2Freg; + psp[3].pszTitle = "COP2F"; + psp[3].lParam = 0; + + psp[4].dwSize = sizeof(PROPSHEETPAGE); + psp[4].dwFlags = PSP_USETITLE; + psp[4].hInstance = m_hInst; + psp[4].pszTemplate = MAKEINTRESOURCE( IDD_VU0INTEGER ); + psp[4].pszIcon = NULL; + psp[4].pfnDlgProc =(DLGPROC)COP2Creg; + psp[4].pszTitle = "COP2C"; + psp[4].lParam = 0; + + psp[5].dwSize = sizeof(PROPSHEETPAGE); + psp[5].dwFlags = PSP_USETITLE; + psp[5].hInstance = m_hInst; + psp[5].pszTemplate = MAKEINTRESOURCE( IDD_VU1REGS ); + psp[5].pszIcon = NULL; + psp[5].pfnDlgProc =(DLGPROC)VU1Freg; + psp[5].pszTitle = "VU1F"; + psp[5].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_VU1INTEGER ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)VU1Creg; + psp[6].pszTitle = "VU1C"; + psp[6].lParam = 0; + + psp[6].dwSize = sizeof(PROPSHEETPAGE); + psp[6].dwFlags = PSP_USETITLE; + psp[6].hInstance = m_hInst; + psp[6].pszTemplate = MAKEINTRESOURCE( IDD_IOPREGS ); + psp[6].pszIcon = NULL; + psp[6].pfnDlgProc =(DLGPROC)R3000reg; + psp[6].pszTitle = "R3000"; + psp[6].lParam = 0; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS; + psh.hwndParent =hwndOwner; + psh.hInstance = m_hInst; + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "Debugger"; + psh.nStartPage = 0; + psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + + return (PropertySheet(&psh)); + +} +LRESULT CALLBACK R3000reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + IOPGPR0Handle=GetDlgItem(hDlg,IDC_IOPGPR0); + IOPGPR1Handle=GetDlgItem(hDlg,IDC_IOPGPR1); + IOPGPR2Handle=GetDlgItem(hDlg,IDC_IOPGPR2); + IOPGPR3Handle=GetDlgItem(hDlg,IDC_IOPGPR3); + IOPGPR4Handle=GetDlgItem(hDlg,IDC_IOPGPR4); + IOPGPR5Handle=GetDlgItem(hDlg,IDC_IOPGPR5); + IOPGPR6Handle=GetDlgItem(hDlg,IDC_IOPGPR6); + IOPGPR7Handle=GetDlgItem(hDlg,IDC_IOPGPR7); + IOPGPR8Handle=GetDlgItem(hDlg,IDC_IOPGPR8); + IOPGPR9Handle=GetDlgItem(hDlg,IDC_IOPGPR9); + IOPGPR10Handle=GetDlgItem(hDlg,IDC_IOPGPR10); + IOPGPR11Handle=GetDlgItem(hDlg,IDC_IOPGPR11); + IOPGPR12Handle=GetDlgItem(hDlg,IDC_IOPGPR12); + IOPGPR13Handle=GetDlgItem(hDlg,IDC_IOPGPR13); + IOPGPR14Handle=GetDlgItem(hDlg,IDC_IOPGPR14); + IOPGPR15Handle=GetDlgItem(hDlg,IDC_IOPGPR15); + IOPGPR16Handle=GetDlgItem(hDlg,IDC_IOPGPR16); + IOPGPR17Handle=GetDlgItem(hDlg,IDC_IOPGPR17); + IOPGPR18Handle=GetDlgItem(hDlg,IDC_IOPGPR18); + IOPGPR19Handle=GetDlgItem(hDlg,IDC_IOPGPR19); + IOPGPR20Handle=GetDlgItem(hDlg,IDC_IOPGPR20); + IOPGPR21Handle=GetDlgItem(hDlg,IDC_IOPGPR21); + IOPGPR22Handle=GetDlgItem(hDlg,IDC_IOPGPR22); + IOPGPR23Handle=GetDlgItem(hDlg,IDC_IOPGPR23); + IOPGPR24Handle=GetDlgItem(hDlg,IDC_IOPGPR24); + IOPGPR25Handle=GetDlgItem(hDlg,IDC_IOPGPR25); + IOPGPR26Handle=GetDlgItem(hDlg,IDC_IOPGPR26); + IOPGPR27Handle=GetDlgItem(hDlg,IDC_IOPGPR27); + IOPGPR28Handle=GetDlgItem(hDlg,IDC_IOPGPR28); + IOPGPR29Handle=GetDlgItem(hDlg,IDC_IOPGPR29); + IOPGPR30Handle=GetDlgItem(hDlg,IDC_IOPGPR30); + IOPGPR31Handle=GetDlgItem(hDlg,IDC_IOPGPR31); + IOPGPRPCHandle=GetDlgItem(hDlg,IDC_IOPGPR_PC); + IOPGPRHIHandle=GetDlgItem(hDlg,IDC_IOPGPR_HI); + IOPGPRLOHandle=GetDlgItem(hDlg,IDC_IOPGPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK R5900reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + GPR0Handle=GetDlgItem(hDlg,IDC_GPR0); + GPR1Handle=GetDlgItem(hDlg,IDC_GPR1); + GPR2Handle=GetDlgItem(hDlg,IDC_GPR2); + GPR3Handle=GetDlgItem(hDlg,IDC_GPR3); + GPR4Handle=GetDlgItem(hDlg,IDC_GPR4); + GPR5Handle=GetDlgItem(hDlg,IDC_GPR5); + GPR6Handle=GetDlgItem(hDlg,IDC_GPR6); + GPR7Handle=GetDlgItem(hDlg,IDC_GPR7); + GPR8Handle=GetDlgItem(hDlg,IDC_GPR8); + GPR9Handle=GetDlgItem(hDlg,IDC_GPR9); + GPR10Handle=GetDlgItem(hDlg,IDC_GPR10); + GPR11Handle=GetDlgItem(hDlg,IDC_GPR11); + GPR12Handle=GetDlgItem(hDlg,IDC_GPR12); + GPR13Handle=GetDlgItem(hDlg,IDC_GPR13); + GPR14Handle=GetDlgItem(hDlg,IDC_GPR14); + GPR15Handle=GetDlgItem(hDlg,IDC_GPR15); + GPR16Handle=GetDlgItem(hDlg,IDC_GPR16); + GPR17Handle=GetDlgItem(hDlg,IDC_GPR17); + GPR18Handle=GetDlgItem(hDlg,IDC_GPR18); + GPR19Handle=GetDlgItem(hDlg,IDC_GPR19); + GPR20Handle=GetDlgItem(hDlg,IDC_GPR20); + GPR21Handle=GetDlgItem(hDlg,IDC_GPR21); + GPR22Handle=GetDlgItem(hDlg,IDC_GPR22); + GPR23Handle=GetDlgItem(hDlg,IDC_GPR23); + GPR24Handle=GetDlgItem(hDlg,IDC_GPR24); + GPR25Handle=GetDlgItem(hDlg,IDC_GPR25); + GPR26Handle=GetDlgItem(hDlg,IDC_GPR26); + GPR27Handle=GetDlgItem(hDlg,IDC_GPR27); + GPR28Handle=GetDlgItem(hDlg,IDC_GPR28); + GPR29Handle=GetDlgItem(hDlg,IDC_GPR29); + GPR30Handle=GetDlgItem(hDlg,IDC_GPR30); + GPR31Handle=GetDlgItem(hDlg,IDC_GPR31); + GPRPCHandle=GetDlgItem(hDlg,IDC_GPR_PC); + GPRHIHandle=GetDlgItem(hDlg,IDC_GPR_HI); + GPRLOHandle=GetDlgItem(hDlg,IDC_GPR_LO); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP0reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP00Handle=GetDlgItem(hDlg,IDC_CP00); + COP01Handle=GetDlgItem(hDlg,IDC_CP01); + COP02Handle=GetDlgItem(hDlg,IDC_CP02); + COP03Handle=GetDlgItem(hDlg,IDC_CP03); + COP04Handle=GetDlgItem(hDlg,IDC_CP04); + COP05Handle=GetDlgItem(hDlg,IDC_CP05); + COP06Handle=GetDlgItem(hDlg,IDC_CP06); + COP07Handle=GetDlgItem(hDlg,IDC_CP07); + COP08Handle=GetDlgItem(hDlg,IDC_CP08); + COP09Handle=GetDlgItem(hDlg,IDC_CP09); + COP010Handle=GetDlgItem(hDlg,IDC_CP010); + COP011Handle=GetDlgItem(hDlg,IDC_CP011); + COP012Handle=GetDlgItem(hDlg,IDC_CP012); + COP013Handle=GetDlgItem(hDlg,IDC_CP013); + COP014Handle=GetDlgItem(hDlg,IDC_CP014); + COP015Handle=GetDlgItem(hDlg,IDC_CP015); + COP016Handle=GetDlgItem(hDlg,IDC_CP016); + COP017Handle=GetDlgItem(hDlg,IDC_CP017); + COP018Handle=GetDlgItem(hDlg,IDC_CP018); + COP019Handle=GetDlgItem(hDlg,IDC_CP019); + COP020Handle=GetDlgItem(hDlg,IDC_CP020); + COP021Handle=GetDlgItem(hDlg,IDC_CP021); + COP022Handle=GetDlgItem(hDlg,IDC_CP022); + COP023Handle=GetDlgItem(hDlg,IDC_CP023); + COP024Handle=GetDlgItem(hDlg,IDC_CP024); + COP025Handle=GetDlgItem(hDlg,IDC_CP025); + COP026Handle=GetDlgItem(hDlg,IDC_CP026); + COP027Handle=GetDlgItem(hDlg,IDC_CP027); + COP028Handle=GetDlgItem(hDlg,IDC_CP028); + COP029Handle=GetDlgItem(hDlg,IDC_CP029); + COP030Handle=GetDlgItem(hDlg,IDC_CP030); + COP031Handle=GetDlgItem(hDlg,IDC_CP031); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP1reg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + COP10Handle=GetDlgItem(hDlg,IDC_FP0); + COP11Handle=GetDlgItem(hDlg,IDC_FP1); + COP12Handle=GetDlgItem(hDlg,IDC_FP2); + COP13Handle=GetDlgItem(hDlg,IDC_FP3); + COP14Handle=GetDlgItem(hDlg,IDC_FP4); + COP15Handle=GetDlgItem(hDlg,IDC_FP5); + COP16Handle=GetDlgItem(hDlg,IDC_FP6); + COP17Handle=GetDlgItem(hDlg,IDC_FP7); + COP18Handle=GetDlgItem(hDlg,IDC_FP8); + COP19Handle=GetDlgItem(hDlg,IDC_FP9); + COP110Handle=GetDlgItem(hDlg,IDC_FP10); + COP111Handle=GetDlgItem(hDlg,IDC_FP11); + COP112Handle=GetDlgItem(hDlg,IDC_FP12); + COP113Handle=GetDlgItem(hDlg,IDC_FP13); + COP114Handle=GetDlgItem(hDlg,IDC_FP14); + COP115Handle=GetDlgItem(hDlg,IDC_FP15); + COP116Handle=GetDlgItem(hDlg,IDC_FP16); + COP117Handle=GetDlgItem(hDlg,IDC_FP17); + COP118Handle=GetDlgItem(hDlg,IDC_FP18); + COP119Handle=GetDlgItem(hDlg,IDC_FP19); + COP120Handle=GetDlgItem(hDlg,IDC_FP20); + COP121Handle=GetDlgItem(hDlg,IDC_FP21); + COP122Handle=GetDlgItem(hDlg,IDC_FP22); + COP123Handle=GetDlgItem(hDlg,IDC_FP23); + COP124Handle=GetDlgItem(hDlg,IDC_FP24); + COP125Handle=GetDlgItem(hDlg,IDC_FP25); + COP126Handle=GetDlgItem(hDlg,IDC_FP26); + COP127Handle=GetDlgItem(hDlg,IDC_FP27); + COP128Handle=GetDlgItem(hDlg,IDC_FP28); + COP129Handle=GetDlgItem(hDlg,IDC_FP29); + COP130Handle=GetDlgItem(hDlg,IDC_FP30); + COP131Handle=GetDlgItem(hDlg,IDC_FP31); + COP1C0Handle=GetDlgItem(hDlg,IDC_FCR0); + COP1C1Handle=GetDlgItem(hDlg,IDC_FCR31); + COP1ACCHandle=GetDlgItem(hDlg,IDC_FPU_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +LRESULT CALLBACK COP2Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0F00Handle=GetDlgItem(hDlg,IDC_VU0_VF00); + VU0F01Handle=GetDlgItem(hDlg,IDC_VU0_VF01); + VU0F02Handle=GetDlgItem(hDlg,IDC_VU0_VF02); + VU0F03Handle=GetDlgItem(hDlg,IDC_VU0_VF03); + VU0F04Handle=GetDlgItem(hDlg,IDC_VU0_VF04); + VU0F05Handle=GetDlgItem(hDlg,IDC_VU0_VF05); + VU0F06Handle=GetDlgItem(hDlg,IDC_VU0_VF06); + VU0F07Handle=GetDlgItem(hDlg,IDC_VU0_VF07); + VU0F08Handle=GetDlgItem(hDlg,IDC_VU0_VF08); + VU0F09Handle=GetDlgItem(hDlg,IDC_VU0_VF09); + VU0F10Handle=GetDlgItem(hDlg,IDC_VU0_VF10); + VU0F11Handle=GetDlgItem(hDlg,IDC_VU0_VF11); + VU0F12Handle=GetDlgItem(hDlg,IDC_VU0_VF12); + VU0F13Handle=GetDlgItem(hDlg,IDC_VU0_VF13); + VU0F14Handle=GetDlgItem(hDlg,IDC_VU0_VF14); + VU0F15Handle=GetDlgItem(hDlg,IDC_VU0_VF15); + VU0F16Handle=GetDlgItem(hDlg,IDC_VU0_VF16); + VU0F17Handle=GetDlgItem(hDlg,IDC_VU0_VF17); + VU0F18Handle=GetDlgItem(hDlg,IDC_VU0_VF18); + VU0F19Handle=GetDlgItem(hDlg,IDC_VU0_VF19); + VU0F20Handle=GetDlgItem(hDlg,IDC_VU0_VF20); + VU0F21Handle=GetDlgItem(hDlg,IDC_VU0_VF21); + VU0F22Handle=GetDlgItem(hDlg,IDC_VU0_VF22); + VU0F23Handle=GetDlgItem(hDlg,IDC_VU0_VF23); + VU0F24Handle=GetDlgItem(hDlg,IDC_VU0_VF24); + VU0F25Handle=GetDlgItem(hDlg,IDC_VU0_VF25); + VU0F26Handle=GetDlgItem(hDlg,IDC_VU0_VF26); + VU0F27Handle=GetDlgItem(hDlg,IDC_VU0_VF27); + VU0F28Handle=GetDlgItem(hDlg,IDC_VU0_VF28); + VU0F29Handle=GetDlgItem(hDlg,IDC_VU0_VF29); + VU0F30Handle=GetDlgItem(hDlg,IDC_VU0_VF30); + VU0F31Handle=GetDlgItem(hDlg,IDC_VU0_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK COP2Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU0C00Handle=GetDlgItem(hDlg,IDC_VU0_VI00); + VU0C01Handle=GetDlgItem(hDlg,IDC_VU0_VI01); + VU0C02Handle=GetDlgItem(hDlg,IDC_VU0_VI02); + VU0C03Handle=GetDlgItem(hDlg,IDC_VU0_VI03); + VU0C04Handle=GetDlgItem(hDlg,IDC_VU0_VI04); + VU0C05Handle=GetDlgItem(hDlg,IDC_VU0_VI05); + VU0C06Handle=GetDlgItem(hDlg,IDC_VU0_VI06); + VU0C07Handle=GetDlgItem(hDlg,IDC_VU0_VI07); + VU0C08Handle=GetDlgItem(hDlg,IDC_VU0_VI08); + VU0C09Handle=GetDlgItem(hDlg,IDC_VU0_VI09); + VU0C10Handle=GetDlgItem(hDlg,IDC_VU0_VI10); + VU0C11Handle=GetDlgItem(hDlg,IDC_VU0_VI11); + VU0C12Handle=GetDlgItem(hDlg,IDC_VU0_VI12); + VU0C13Handle=GetDlgItem(hDlg,IDC_VU0_VI13); + VU0C14Handle=GetDlgItem(hDlg,IDC_VU0_VI14); + VU0C15Handle=GetDlgItem(hDlg,IDC_VU0_VI15); + VU0C16Handle=GetDlgItem(hDlg,IDC_VU0_VI16); + VU0C17Handle=GetDlgItem(hDlg,IDC_VU0_VI17); + VU0C18Handle=GetDlgItem(hDlg,IDC_VU0_VI18); + VU0C19Handle=GetDlgItem(hDlg,IDC_VU0_VI19); + VU0C20Handle=GetDlgItem(hDlg,IDC_VU0_VI20); + VU0C21Handle=GetDlgItem(hDlg,IDC_VU0_VI21); + VU0C22Handle=GetDlgItem(hDlg,IDC_VU0_VI22); + VU0C23Handle=GetDlgItem(hDlg,IDC_VU0_VI23); + VU0C24Handle=GetDlgItem(hDlg,IDC_VU0_VI24); + VU0C25Handle=GetDlgItem(hDlg,IDC_VU0_VI25); + VU0C26Handle=GetDlgItem(hDlg,IDC_VU0_VI26); + VU0C27Handle=GetDlgItem(hDlg,IDC_VU0_VI27); + VU0C28Handle=GetDlgItem(hDlg,IDC_VU0_VI28); + VU0C29Handle=GetDlgItem(hDlg,IDC_VU0_VI29); + VU0C30Handle=GetDlgItem(hDlg,IDC_VU0_VI30); + VU0C31Handle=GetDlgItem(hDlg,IDC_VU0_VI31); + VU0ACCHandle=GetDlgItem(hDlg,IDC_VU0_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + + +LRESULT CALLBACK VU1Freg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1F00Handle=GetDlgItem(hDlg,IDC_VU1_VF00); + VU1F01Handle=GetDlgItem(hDlg,IDC_VU1_VF01); + VU1F02Handle=GetDlgItem(hDlg,IDC_VU1_VF02); + VU1F03Handle=GetDlgItem(hDlg,IDC_VU1_VF03); + VU1F04Handle=GetDlgItem(hDlg,IDC_VU1_VF04); + VU1F05Handle=GetDlgItem(hDlg,IDC_VU1_VF05); + VU1F06Handle=GetDlgItem(hDlg,IDC_VU1_VF06); + VU1F07Handle=GetDlgItem(hDlg,IDC_VU1_VF07); + VU1F08Handle=GetDlgItem(hDlg,IDC_VU1_VF08); + VU1F09Handle=GetDlgItem(hDlg,IDC_VU1_VF09); + VU1F10Handle=GetDlgItem(hDlg,IDC_VU1_VF10); + VU1F11Handle=GetDlgItem(hDlg,IDC_VU1_VF11); + VU1F12Handle=GetDlgItem(hDlg,IDC_VU1_VF12); + VU1F13Handle=GetDlgItem(hDlg,IDC_VU1_VF13); + VU1F14Handle=GetDlgItem(hDlg,IDC_VU1_VF14); + VU1F15Handle=GetDlgItem(hDlg,IDC_VU1_VF15); + VU1F16Handle=GetDlgItem(hDlg,IDC_VU1_VF16); + VU1F17Handle=GetDlgItem(hDlg,IDC_VU1_VF17); + VU1F18Handle=GetDlgItem(hDlg,IDC_VU1_VF18); + VU1F19Handle=GetDlgItem(hDlg,IDC_VU1_VF19); + VU1F20Handle=GetDlgItem(hDlg,IDC_VU1_VF20); + VU1F21Handle=GetDlgItem(hDlg,IDC_VU1_VF21); + VU1F22Handle=GetDlgItem(hDlg,IDC_VU1_VF22); + VU1F23Handle=GetDlgItem(hDlg,IDC_VU1_VF23); + VU1F24Handle=GetDlgItem(hDlg,IDC_VU1_VF24); + VU1F25Handle=GetDlgItem(hDlg,IDC_VU1_VF25); + VU1F26Handle=GetDlgItem(hDlg,IDC_VU1_VF26); + VU1F27Handle=GetDlgItem(hDlg,IDC_VU1_VF27); + VU1F28Handle=GetDlgItem(hDlg,IDC_VU1_VF28); + VU1F29Handle=GetDlgItem(hDlg,IDC_VU1_VF29); + VU1F30Handle=GetDlgItem(hDlg,IDC_VU1_VF30); + VU1F31Handle=GetDlgItem(hDlg,IDC_VU1_VF31); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} +LRESULT CALLBACK VU1Creg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + VU1C00Handle=GetDlgItem(hDlg,IDC_VU1_VI00); + VU1C01Handle=GetDlgItem(hDlg,IDC_VU1_VI01); + VU1C02Handle=GetDlgItem(hDlg,IDC_VU1_VI02); + VU1C03Handle=GetDlgItem(hDlg,IDC_VU1_VI03); + VU1C04Handle=GetDlgItem(hDlg,IDC_VU1_VI04); + VU1C05Handle=GetDlgItem(hDlg,IDC_VU1_VI05); + VU1C06Handle=GetDlgItem(hDlg,IDC_VU1_VI06); + VU1C07Handle=GetDlgItem(hDlg,IDC_VU1_VI07); + VU1C08Handle=GetDlgItem(hDlg,IDC_VU1_VI08); + VU1C09Handle=GetDlgItem(hDlg,IDC_VU1_VI09); + VU1C10Handle=GetDlgItem(hDlg,IDC_VU1_VI10); + VU1C11Handle=GetDlgItem(hDlg,IDC_VU1_VI11); + VU1C12Handle=GetDlgItem(hDlg,IDC_VU1_VI12); + VU1C13Handle=GetDlgItem(hDlg,IDC_VU1_VI13); + VU1C14Handle=GetDlgItem(hDlg,IDC_VU1_VI14); + VU1C15Handle=GetDlgItem(hDlg,IDC_VU1_VI15); + VU1C16Handle=GetDlgItem(hDlg,IDC_VU1_VI16); + VU1C17Handle=GetDlgItem(hDlg,IDC_VU1_VI17); + VU1C18Handle=GetDlgItem(hDlg,IDC_VU1_VI18); + VU1C19Handle=GetDlgItem(hDlg,IDC_VU1_VI19); + VU1C20Handle=GetDlgItem(hDlg,IDC_VU1_VI20); + VU1C21Handle=GetDlgItem(hDlg,IDC_VU1_VI21); + VU1C22Handle=GetDlgItem(hDlg,IDC_VU1_VI22); + VU1C23Handle=GetDlgItem(hDlg,IDC_VU1_VI23); + VU1C24Handle=GetDlgItem(hDlg,IDC_VU1_VI24); + VU1C25Handle=GetDlgItem(hDlg,IDC_VU1_VI25); + VU1C26Handle=GetDlgItem(hDlg,IDC_VU1_VI26); + VU1C27Handle=GetDlgItem(hDlg,IDC_VU1_VI27); + VU1C28Handle=GetDlgItem(hDlg,IDC_VU1_VI28); + VU1C29Handle=GetDlgItem(hDlg,IDC_VU1_VI29); + VU1C30Handle=GetDlgItem(hDlg,IDC_VU1_VI30); + VU1C31Handle=GetDlgItem(hDlg,IDC_VU1_VI31); + VU1ACCHandle=GetDlgItem(hDlg,IDC_VU1_ACC); + UpdateRegs(); + return (TRUE); + break; + case WM_COMMAND: + + switch(LOWORD(wParam)) + { + case (IDOK || IDCANCEL): + EndDialog(hDlg,TRUE); + return(TRUE); + break; + + } + break; + } + + return(FALSE); +} + +void UpdateRegs(void) +{ + + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[0]); + SendMessage(IOPGPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[1]); + SendMessage(IOPGPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[2]); + SendMessage(IOPGPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[3]); + SendMessage(IOPGPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[4]); + SendMessage(IOPGPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[5]); + SendMessage(IOPGPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[6]); + SendMessage(IOPGPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[7]); + SendMessage(IOPGPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[8]); + SendMessage(IOPGPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[9]); + SendMessage(IOPGPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[10]); + SendMessage(IOPGPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[11]); + SendMessage(IOPGPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[12]); + SendMessage(IOPGPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[13]); + SendMessage(IOPGPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[14]); + SendMessage(IOPGPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[15]); + SendMessage(IOPGPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[16]); + SendMessage(IOPGPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[17]); + SendMessage(IOPGPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[18]); + SendMessage(IOPGPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[19]); + SendMessage(IOPGPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[20]); + SendMessage(IOPGPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[21]); + SendMessage(IOPGPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[22]); + SendMessage(IOPGPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[23]); + SendMessage(IOPGPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[24]); + SendMessage(IOPGPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[25]); + SendMessage(IOPGPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[26]); + SendMessage(IOPGPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[27]); + SendMessage(IOPGPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[28]); + SendMessage(IOPGPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[29]); + SendMessage(IOPGPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[30]); + SendMessage(IOPGPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[31]); + SendMessage(IOPGPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",psxRegs.pc ); + SendMessage(IOPGPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[32]); + SendMessage(IOPGPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X\0",psxRegs.GPR.r[33]); + SendMessage(IOPGPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[0].UL[3],cpuRegs.GPR.r[0].UL[2],cpuRegs.GPR.r[0].UL[1],cpuRegs.GPR.r[0].UL[0] ); + SendMessage(GPR0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[1].UL[3], cpuRegs.GPR.r[1].UL[2],cpuRegs.GPR.r[1].UL[1],cpuRegs.GPR.r[1].UL[0] ); + SendMessage(GPR1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[2].UL[3],cpuRegs.GPR.r[2].UL[2], cpuRegs.GPR.r[2].UL[1],cpuRegs.GPR.r[2].UL[0]); + SendMessage(GPR2Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[3].UL[3],cpuRegs.GPR.r[3].UL[2], cpuRegs.GPR.r[3].UL[1],cpuRegs.GPR.r[3].UL[0] ); + SendMessage(GPR3Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[4].UL[3],cpuRegs.GPR.r[4].UL[2], cpuRegs.GPR.r[4].UL[1],cpuRegs.GPR.r[4].UL[0] ); + SendMessage(GPR4Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[5].UL[3],cpuRegs.GPR.r[5].UL[2],cpuRegs.GPR.r[5].UL[1], cpuRegs.GPR.r[5].UL[0] ); + SendMessage(GPR5Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[6].UL[3],cpuRegs.GPR.r[6].UL[2], cpuRegs.GPR.r[6].UL[1], cpuRegs.GPR.r[6].UL[0]); + SendMessage(GPR6Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[7].UL[3], cpuRegs.GPR.r[7].UL[2],cpuRegs.GPR.r[7].UL[1],cpuRegs.GPR.r[7].UL[0] ); + SendMessage(GPR7Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[8].UL[3],cpuRegs.GPR.r[8].UL[2],cpuRegs.GPR.r[8].UL[1],cpuRegs.GPR.r[8].UL[0] ); + SendMessage(GPR8Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[9].UL[3],cpuRegs.GPR.r[9].UL[2],cpuRegs.GPR.r[9].UL[1], cpuRegs.GPR.r[9].UL[0] ); + SendMessage(GPR9Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[10].UL[3],cpuRegs.GPR.r[10].UL[2],cpuRegs.GPR.r[10].UL[1],cpuRegs.GPR.r[10].UL[0] ); + SendMessage(GPR10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[11].UL[3],cpuRegs.GPR.r[11].UL[2],cpuRegs.GPR.r[11].UL[1],cpuRegs.GPR.r[11].UL[0] ); + SendMessage(GPR11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[12].UL[3],cpuRegs.GPR.r[12].UL[2],cpuRegs.GPR.r[12].UL[1],cpuRegs.GPR.r[12].UL[0] ); + SendMessage(GPR12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[13].UL[3],cpuRegs.GPR.r[13].UL[2],cpuRegs.GPR.r[13].UL[1],cpuRegs.GPR.r[13].UL[0] ); + SendMessage(GPR13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[14].UL[3],cpuRegs.GPR.r[14].UL[2],cpuRegs.GPR.r[14].UL[1],cpuRegs.GPR.r[14].UL[0] ); + SendMessage(GPR14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[15].UL[3],cpuRegs.GPR.r[15].UL[2],cpuRegs.GPR.r[15].UL[1],cpuRegs.GPR.r[15].UL[0] ); + SendMessage(GPR15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[16].UL[3],cpuRegs.GPR.r[16].UL[2],cpuRegs.GPR.r[16].UL[1],cpuRegs.GPR.r[16].UL[0] ); + SendMessage(GPR16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[17].UL[3],cpuRegs.GPR.r[17].UL[2],cpuRegs.GPR.r[17].UL[1],cpuRegs.GPR.r[17].UL[0] ); + SendMessage(GPR17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[18].UL[3],cpuRegs.GPR.r[18].UL[2],cpuRegs.GPR.r[18].UL[1],cpuRegs.GPR.r[18].UL[0] ); + SendMessage(GPR18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[19].UL[3],cpuRegs.GPR.r[19].UL[2],cpuRegs.GPR.r[19].UL[1],cpuRegs.GPR.r[19].UL[0] ); + SendMessage(GPR19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[20].UL[3],cpuRegs.GPR.r[20].UL[2],cpuRegs.GPR.r[20].UL[1],cpuRegs.GPR.r[20].UL[0] ); + SendMessage(GPR20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[21].UL[3],cpuRegs.GPR.r[21].UL[2],cpuRegs.GPR.r[21].UL[1],cpuRegs.GPR.r[21].UL[0] ); + SendMessage(GPR21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[22].UL[3],cpuRegs.GPR.r[22].UL[2],cpuRegs.GPR.r[22].UL[1],cpuRegs.GPR.r[22].UL[0] ); + SendMessage(GPR22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[23].UL[3],cpuRegs.GPR.r[23].UL[2],cpuRegs.GPR.r[23].UL[1],cpuRegs.GPR.r[23].UL[0] ); + SendMessage(GPR23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[24].UL[3],cpuRegs.GPR.r[24].UL[2],cpuRegs.GPR.r[24].UL[1],cpuRegs.GPR.r[24].UL[0] ); + SendMessage(GPR24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[25].UL[3],cpuRegs.GPR.r[25].UL[2],cpuRegs.GPR.r[25].UL[1],cpuRegs.GPR.r[25].UL[0] ); + SendMessage(GPR25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[26].UL[3],cpuRegs.GPR.r[26].UL[2],cpuRegs.GPR.r[26].UL[1],cpuRegs.GPR.r[26].UL[0] ); + SendMessage(GPR26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[27].UL[3],cpuRegs.GPR.r[27].UL[2],cpuRegs.GPR.r[27].UL[1],cpuRegs.GPR.r[27].UL[0] ); + SendMessage(GPR27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[28].UL[3],cpuRegs.GPR.r[28].UL[2],cpuRegs.GPR.r[28].UL[1],cpuRegs.GPR.r[28].UL[0] ); + SendMessage(GPR28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[29].UL[3],cpuRegs.GPR.r[29].UL[2],cpuRegs.GPR.r[29].UL[1],cpuRegs.GPR.r[29].UL[0] ); + SendMessage(GPR29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[30].UL[3],cpuRegs.GPR.r[30].UL[2],cpuRegs.GPR.r[30].UL[1],cpuRegs.GPR.r[30].UL[0] ); + SendMessage(GPR30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.GPR.r[31].UL[3],cpuRegs.GPR.r[31].UL[2],cpuRegs.GPR.r[31].UL[1],cpuRegs.GPR.r[31].UL[0] ); + SendMessage(GPR31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.pc ); + SendMessage(GPRPCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2] ,cpuRegs.HI.UL[1] ,cpuRegs.HI.UL[0] ); + SendMessage(GPRHIHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"0x%08X_%08X_%08X_%08X\0\0",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0] ); + SendMessage(GPRLOHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[0] ); + SendMessage(COP00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[1]); + SendMessage(COP01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[2]); + SendMessage(COP02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[3]); + SendMessage(COP03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[4]); + SendMessage(COP04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[5]); + SendMessage(COP05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[6]); + SendMessage(COP06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[7]); + SendMessage(COP07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[8]); + SendMessage(COP08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[9]); + SendMessage(COP09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[10]); + SendMessage(COP010Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[11]); + SendMessage(COP011Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[12]); + SendMessage(COP012Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[13]); + SendMessage(COP013Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[14]); + SendMessage(COP014Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[15]); + SendMessage(COP015Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[16]); + SendMessage(COP016Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[17]); + SendMessage(COP017Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[18]); + SendMessage(COP018Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[19]); + SendMessage(COP019Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[20]); + SendMessage(COP020Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[21]); + SendMessage(COP021Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[22]); + SendMessage(COP022Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[23]); + SendMessage(COP023Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[24]); + SendMessage(COP024Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[25]); + SendMessage(COP025Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[26]); + SendMessage(COP026Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[27]); + SendMessage(COP027Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[28]); + SendMessage(COP028Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[29]); + SendMessage(COP029Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[30]); + SendMessage(COP030Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",cpuRegs.CP0.r[31]); + SendMessage(COP031Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f",fpuRegs.fpr[0].f ); + SendMessage(COP10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[1].f); + SendMessage(COP11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[2].f); + SendMessage(COP12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[3].f); + SendMessage(COP13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[4].f); + SendMessage(COP14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[5].f); + SendMessage(COP15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[6].f); + SendMessage(COP16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[7].f); + SendMessage(COP17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[8].f); + SendMessage(COP18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[9].f); + SendMessage(COP19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[10].f); + SendMessage(COP110Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[11].f); + SendMessage(COP111Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[12].f); + SendMessage(COP112Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[13].f); + SendMessage(COP113Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[14].f); + SendMessage(COP114Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[15].f); + SendMessage(COP115Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[16].f); + SendMessage(COP116Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[17].f); + SendMessage(COP117Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[18].f); + SendMessage(COP118Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[19].f); + SendMessage(COP119Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[20].f); + SendMessage(COP120Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[21].f); + SendMessage(COP121Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[22].f); + SendMessage(COP122Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[23].f); + SendMessage(COP123Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[24].f); + SendMessage(COP124Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[25].f); + SendMessage(COP125Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[26].f); + SendMessage(COP126Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[27].f); + SendMessage(COP127Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[28].f); + SendMessage(COP128Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[29].f); + SendMessage(COP129Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[30].f); + SendMessage(COP130Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.fpr[31].f); + SendMessage(COP131Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[0]); + SendMessage(COP1C0Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",fpuRegs.fprc[31]); + SendMessage(COP1C1Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f",fpuRegs.ACC.f); + SendMessage(COP1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[0].f.w,VU0.VF[0].f.z,VU0.VF[0].f.y,VU0.VF[0].f.x ); + SendMessage(VU0F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[1].f.w,VU0.VF[1].f.z,VU0.VF[1].f.y,VU0.VF[1].f.x ); + SendMessage(VU0F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[2].f.w,VU0.VF[2].f.z,VU0.VF[2].f.y,VU0.VF[2].f.x ); + SendMessage(VU0F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[3].f.w,VU0.VF[3].f.z,VU0.VF[3].f.y,VU0.VF[3].f.x ); + SendMessage(VU0F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[4].f.w,VU0.VF[4].f.z,VU0.VF[4].f.y,VU0.VF[4].f.x ); + SendMessage(VU0F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[5].f.w,VU0.VF[5].f.z,VU0.VF[5].f.y,VU0.VF[5].f.x); + SendMessage(VU0F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[6].f.w,VU0.VF[6].f.z,VU0.VF[6].f.y,VU0.VF[6].f.x ); + SendMessage(VU0F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[7].f.w,VU0.VF[7].f.z,VU0.VF[7].f.y,VU0.VF[7].f.x ); + SendMessage(VU0F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[8].f.w,VU0.VF[8].f.z,VU0.VF[8].f.y,VU0.VF[8].f.x ); + SendMessage(VU0F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[9].f.w,VU0.VF[9].f.z,VU0.VF[9].f.y,VU0.VF[9].f.x ); + SendMessage(VU0F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[10].f.w,VU0.VF[10].f.z,VU0.VF[10].f.y,VU0.VF[10].f.x ); + SendMessage(VU0F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[11].f.w,VU0.VF[11].f.z,VU0.VF[11].f.y,VU0.VF[11].f.x ); + SendMessage(VU0F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[12].f.w,VU0.VF[12].f.z,VU0.VF[12].f.y,VU0.VF[12].f.x ); + SendMessage(VU0F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[13].f.w,VU0.VF[13].f.z,VU0.VF[13].f.y,VU0.VF[13].f.x ); + SendMessage(VU0F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[14].f.w,VU0.VF[14].f.z,VU0.VF[14].f.y,VU0.VF[14].f.x ); + SendMessage(VU0F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[15].f.w,VU0.VF[15].f.z,VU0.VF[15].f.y,VU0.VF[15].f.x ); + SendMessage(VU0F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[16].f.w,VU0.VF[16].f.z,VU0.VF[16].f.y,VU0.VF[16].f.x ); + SendMessage(VU0F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[17].f.w,VU0.VF[17].f.z,VU0.VF[17].f.y,VU0.VF[17].f.x ); + SendMessage(VU0F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[18].f.w,VU0.VF[18].f.z,VU0.VF[18].f.y,VU0.VF[18].f.x ); + SendMessage(VU0F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[19].f.w,VU0.VF[19].f.z,VU0.VF[19].f.y,VU0.VF[19].f.x ); + SendMessage(VU0F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[20].f.w,VU0.VF[20].f.z,VU0.VF[20].f.y,VU0.VF[20].f.x ); + SendMessage(VU0F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[21].f.w,VU0.VF[21].f.z,VU0.VF[21].f.y,VU0.VF[21].f.x ); + SendMessage(VU0F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[22].f.w,VU0.VF[22].f.z,VU0.VF[22].f.y,VU0.VF[22].f.x ); + SendMessage(VU0F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[23].f.w,VU0.VF[23].f.z,VU0.VF[23].f.y,VU0.VF[23].f.x ); + SendMessage(VU0F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[24].f.w,VU0.VF[24].f.z,VU0.VF[24].f.y,VU0.VF[24].f.x ); + SendMessage(VU0F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[25].f.w,VU0.VF[25].f.z,VU0.VF[25].f.y,VU0.VF[25].f.x ); + SendMessage(VU0F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[26].f.w,VU0.VF[26].f.z,VU0.VF[26].f.y,VU0.VF[26].f.x ); + SendMessage(VU0F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[27].f.w,VU0.VF[27].f.z,VU0.VF[27].f.y,VU0.VF[27].f.x ); + SendMessage(VU0F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[28].f.w,VU0.VF[28].f.z,VU0.VF[28].f.y,VU0.VF[28].f.x ); + SendMessage(VU0F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[29].f.w,VU0.VF[29].f.z,VU0.VF[29].f.y,VU0.VF[29].f.x ); + SendMessage(VU0F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[30].f.w,VU0.VF[30].f.z,VU0.VF[30].f.y,VU0.VF[30].f.x ); + SendMessage(VU0F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU0.VF[31].f.w,VU0.VF[31].f.z,VU0.VF[31].f.y,VU0.VF[31].f.x ); + SendMessage(VU0F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU0.VI[0] ); + SendMessage(VU0C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[1]); + SendMessage(VU0C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[2]); + SendMessage(VU0C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[3]); + SendMessage(VU0C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[4]); + SendMessage(VU0C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[5]); + SendMessage(VU0C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[6]); + SendMessage(VU0C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[7]); + SendMessage(VU0C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[8]); + SendMessage(VU0C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[9]); + SendMessage(VU0C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[10]); + SendMessage(VU0C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[11]); + SendMessage(VU0C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[12]); + SendMessage(VU0C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[13]); + SendMessage(VU0C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[14]); + SendMessage(VU0C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[15]); + SendMessage(VU0C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[16]); + SendMessage(VU0C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[17]); + SendMessage(VU0C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[18]); + SendMessage(VU0C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[19]); + SendMessage(VU0C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[20]); + SendMessage(VU0C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[21]); + SendMessage(VU0C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[22]); + SendMessage(VU0C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[23]); + SendMessage(VU0C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[24]); + SendMessage(VU0C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[25]); + SendMessage(VU0C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[26]); + SendMessage(VU0C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[27]); + SendMessage(VU0C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[28]); + SendMessage(VU0C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[29]); + SendMessage(VU0C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[30]); + SendMessage(VU0C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU0.VI[31]); + SendMessage(VU0C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU0.ACC.f.w,VU0.ACC.f.z,VU0.ACC.f.y,VU0.ACC.f.x ); + SendMessage(VU0ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[0].f.w,VU1.VF[0].f.z,VU1.VF[0].f.y,VU1.VF[0].f.x ); + SendMessage(VU1F00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[1].f.w,VU1.VF[1].f.z,VU1.VF[1].f.y,VU1.VF[1].f.x ); + SendMessage(VU1F01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[2].f.w,VU1.VF[2].f.z,VU1.VF[2].f.y,VU1.VF[2].f.x ); + SendMessage(VU1F02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[3].f.w,VU1.VF[3].f.z,VU1.VF[3].f.y,VU1.VF[3].f.x ); + SendMessage(VU1F03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[4].f.w,VU1.VF[4].f.z,VU1.VF[4].f.y,VU1.VF[4].f.x ); + SendMessage(VU1F04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[5].f.w,VU1.VF[5].f.z,VU1.VF[5].f.y,VU1.VF[5].f.x); + SendMessage(VU1F05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[6].f.w,VU1.VF[6].f.z,VU1.VF[6].f.y,VU1.VF[6].f.x ); + SendMessage(VU1F06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[7].f.w,VU1.VF[7].f.z,VU1.VF[7].f.y,VU1.VF[7].f.x ); + SendMessage(VU1F07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[8].f.w,VU1.VF[8].f.z,VU1.VF[8].f.y,VU1.VF[8].f.x ); + SendMessage(VU1F08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[9].f.w,VU1.VF[9].f.z,VU1.VF[9].f.y,VU1.VF[9].f.x ); + SendMessage(VU1F09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[10].f.w,VU1.VF[10].f.z,VU1.VF[10].f.y,VU1.VF[10].f.x ); + SendMessage(VU1F10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[11].f.w,VU1.VF[11].f.z,VU1.VF[11].f.y,VU1.VF[11].f.x ); + SendMessage(VU1F11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[12].f.w,VU1.VF[12].f.z,VU1.VF[12].f.y,VU1.VF[12].f.x ); + SendMessage(VU1F12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[13].f.w,VU1.VF[13].f.z,VU1.VF[13].f.y,VU1.VF[13].f.x ); + SendMessage(VU1F13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[14].f.w,VU1.VF[14].f.z,VU1.VF[14].f.y,VU1.VF[14].f.x ); + SendMessage(VU1F14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[15].f.w,VU1.VF[15].f.z,VU1.VF[15].f.y,VU1.VF[15].f.x ); + SendMessage(VU1F15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[16].f.w,VU1.VF[16].f.z,VU1.VF[16].f.y,VU1.VF[16].f.x ); + SendMessage(VU1F16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[17].f.w,VU1.VF[17].f.z,VU1.VF[17].f.y,VU1.VF[17].f.x ); + SendMessage(VU1F17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[18].f.w,VU1.VF[18].f.z,VU1.VF[18].f.y,VU1.VF[18].f.x ); + SendMessage(VU1F18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[19].f.w,VU1.VF[19].f.z,VU1.VF[19].f.y,VU1.VF[19].f.x ); + SendMessage(VU1F19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[20].f.w,VU1.VF[20].f.z,VU1.VF[20].f.y,VU1.VF[20].f.x ); + SendMessage(VU1F20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[21].f.w,VU1.VF[21].f.z,VU1.VF[21].f.y,VU1.VF[21].f.x ); + SendMessage(VU1F21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[22].f.w,VU1.VF[22].f.z,VU1.VF[22].f.y,VU1.VF[22].f.x ); + SendMessage(VU1F22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[23].f.w,VU1.VF[23].f.z,VU1.VF[23].f.y,VU1.VF[23].f.x ); + SendMessage(VU1F23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[24].f.w,VU1.VF[24].f.z,VU1.VF[24].f.y,VU1.VF[24].f.x ); + SendMessage(VU1F24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[25].f.w,VU1.VF[25].f.z,VU1.VF[25].f.y,VU1.VF[25].f.x ); + SendMessage(VU1F25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[26].f.w,VU1.VF[26].f.z,VU1.VF[26].f.y,VU1.VF[26].f.x ); + SendMessage(VU1F26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[27].f.w,VU1.VF[27].f.z,VU1.VF[27].f.y,VU1.VF[27].f.x ); + SendMessage(VU1F27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[28].f.w,VU1.VF[28].f.z,VU1.VF[28].f.y,VU1.VF[28].f.x ); + SendMessage(VU1F28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[29].f.w,VU1.VF[29].f.z,VU1.VF[29].f.y,VU1.VF[29].f.x ); + SendMessage(VU1F29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[30].f.w,VU1.VF[30].f.z,VU1.VF[30].f.y,VU1.VF[30].f.x ); + SendMessage(VU1F30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + sprintf(text1,"%f_%f_%f_%f\0",VU1.VF[31].f.w,VU1.VF[31].f.z,VU1.VF[31].f.y,VU1.VF[31].f.x ); + SendMessage(VU1F31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + + wsprintf(text1,"%x",VU1.VI[0] ); + SendMessage(VU1C00Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[1]); + SendMessage(VU1C01Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[2]); + SendMessage(VU1C02Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[3]); + SendMessage(VU1C03Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[4]); + SendMessage(VU1C04Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[5]); + SendMessage(VU1C05Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[6]); + SendMessage(VU1C06Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[7]); + SendMessage(VU1C07Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[8]); + SendMessage(VU1C08Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[9]); + SendMessage(VU1C09Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[10]); + SendMessage(VU1C10Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[11]); + SendMessage(VU1C11Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[12]); + SendMessage(VU1C12Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[13]); + SendMessage(VU1C13Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[14]); + SendMessage(VU1C14Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[15]); + SendMessage(VU1C15Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[16]); + SendMessage(VU1C16Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[17]); + SendMessage(VU1C17Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[18]); + SendMessage(VU1C18Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[19]); + SendMessage(VU1C19Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[20]); + SendMessage(VU1C20Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[21]); + SendMessage(VU1C21Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[22]); + SendMessage(VU1C22Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[23]); + SendMessage(VU1C23Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[24]); + SendMessage(VU1C24Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[25]); + SendMessage(VU1C25Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[26]); + SendMessage(VU1C26Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[27]); + SendMessage(VU1C27Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[28]); + SendMessage(VU1C28Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[29]); + SendMessage(VU1C29Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[30]); + SendMessage(VU1C30Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + wsprintf(text1,"%x",VU1.VI[31]); + SendMessage(VU1C31Handle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + + sprintf(text1,"%f_%f_%f_%f\0",VU1.ACC.f.w,VU1.ACC.f.z,VU1.ACC.f.y,VU1.ACC.f.x ); + SendMessage(VU1ACCHandle,WM_SETTEXT,0,(LPARAM)(LPCTSTR)text1); + +} + + +void EEDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x_%x_%x_%x",cpuRegs.GPR.r[i].UL[3],cpuRegs.GPR.r[i].UL[2],cpuRegs.GPR.r[i].UL[1],cpuRegs.GPR.r[i].UL[0]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",cpuRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.HI.UL[3],cpuRegs.HI.UL[2],cpuRegs.HI.UL[1],cpuRegs.HI.UL[0]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x_%x_%x_%x",cpuRegs.LO.UL[3],cpuRegs.LO.UL[2],cpuRegs.LO.UL[1],cpuRegs.LO.UL[0]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + + + for(i = 0; i < 32; i++) + { + sprintf(text1,"0x%x",cpuRegs.CP0.r[i]); + sprintf(text2,"COP0 Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } +} + +void IOPDumpRegs(FILE * fp) +{ + char text2[256]; + int i; + for(i = 0; i < 32; i++) + { + sprintf(text1,"%x",psxRegs.GPR.r[i]); + sprintf(text2,"GPR Register %d: ",i+1); + fprintf(fp,text2); + fprintf(fp,text1); + fprintf(fp,"\n"); + } + sprintf(text1,"0x%x",psxRegs.pc); + fprintf(fp,"PC Register : "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[32]); + fprintf(fp,"GPR Register HI: "); + fprintf(fp,text1); + fprintf(fp,"\n"); + sprintf(text1,"%x",psxRegs.GPR.r[33]); + fprintf(fp,"GPR Register LO: "); + fprintf(fp,text1); + fprintf(fp,"\n"); +} diff --git a/pcsx2/windows/McdsDlg.c b/pcsx2/windows/McdsDlg.c new file mode 100644 index 0000000..f425919 --- /dev/null +++ b/pcsx2/windows/McdsDlg.c @@ -0,0 +1,124 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "plugins.h" +#include "resource.h" +#include "Win32.h" + + +HWND mcdDlg; + + +void Open_Mcd_Proc(HWND hW, int mcd) { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[1024]; + char *str; + + memset(szFileName, 0, sizeof(szFileName)); + memset(szFileTitle, 0, sizeof(szFileTitle)); + memset(szFilter, 0, sizeof(szFilter)); + + + strcpy(szFilter, _("Ps2 Memory Card (*.ps2)")); + str = szFilter + strlen(szFilter) + 1; + strcpy(str, "*.ps2"); + + str+= strlen(str) + 1; + strcpy(str, _("All Files")); + str+= strlen(str) + 1; + strcpy(str, "*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hW; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = "memcards"; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "MC2"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD1 : IDC_MCD2), szFileName); + } +} + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + mcdDlg = hW; + + SetWindowText(hW, _("Memcard Manager")); + + Button_SetText(GetDlgItem(hW, IDOK), _("OK")); + Button_SetText(GetDlgItem(hW, IDCANCEL), _("Cancel")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL1), _("Select Mcd")); + Button_SetText(GetDlgItem(hW, IDC_MCDSEL2), _("Select Mcd")); + + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1")); + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2")); + + if (!strlen(Config.Mcd1)) strcpy(Config.Mcd1, "memcards\\Mcd001.ps2"); + if (!strlen(Config.Mcd2)) strcpy(Config.Mcd2, "memcards\\Mcd002.ps2"); + Edit_SetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1); + Edit_SetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2); + + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_MCDSEL1: + Open_Mcd_Proc(hW, 1); + return TRUE; + case IDC_MCDSEL2: + Open_Mcd_Proc(hW, 2); + return TRUE; + case IDCANCEL: + EndDialog(hW,FALSE); + + return TRUE; + case IDOK: + Edit_GetText(GetDlgItem(hW,IDC_MCD1), Config.Mcd1, 256); + Edit_GetText(GetDlgItem(hW,IDC_MCD2), Config.Mcd2, 256); + + SaveConfig(); + + EndDialog(hW,TRUE); + + return TRUE; + } + case WM_DESTROY: + return TRUE; + } + return FALSE; +} + diff --git a/pcsx2/windows/McdsDlg.h b/pcsx2/windows/McdsDlg.h new file mode 100644 index 0000000..c911430 --- /dev/null +++ b/pcsx2/windows/McdsDlg.h @@ -0,0 +1,24 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2004 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MCDSDLG_H__ +#define __MCDSDLG_H__ + +BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __MCDSDLG_H__ */ diff --git a/pcsx2/windows/PatchBrowser.c b/pcsx2/windows/PatchBrowser.c new file mode 100644 index 0000000..ec664c7 --- /dev/null +++ b/pcsx2/windows/PatchBrowser.c @@ -0,0 +1,352 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************** +* +* patchbrowser.c contains all the src of patchbrowser window +* no interaction with emulation code +***************************/ + +#include +#include +#include "Common.h" +#include "win32.h" +#include "resource.h" + +/* + * TODO: + * - not topmost + * - resize stuff + * - ask to save in exit (check if changed) + */ +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + int tmpi,i; + char fileName[MAX_PATH], *tmpStr; + FILE *fp; + + switch(uMsg) { + + case WM_INITDIALOG: + SetWindowText(hW, _("Patches Browser")); + Button_SetText(GetDlgItem(hW,IDC_REFRESHPATCHLIST), _("Refresh List")); + Button_SetText(GetDlgItem(hW,IDC_NEWPATCH), _("New Patch")); + Button_SetText(GetDlgItem(hW,IDC_SAVEPATCH), _("Save Patch")); + Button_SetText(GetDlgItem(hW,IDC_EXITPB), _("Exit")); + Static_SetText(GetDlgItem(hW,IDC_GAMENAMESEARCH), _("Search game name patch:")); + //List Patches + ListPatches ((HWND) hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + + case IDC_NEWPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"a")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't create the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + fclose(fp); + i = MessageBox(hW,(LPCTSTR)"File created sucessfully.\nClear textbox?",NULL,(UINT)(MB_YESNO|MB_ICONQUESTION)); + if (i==IDYES) SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)""); + + return TRUE; + + case IDC_SAVEPATCH: + + i = Save_Patch_Proc(fileName); + if ( i == FALSE || (fp = fopen(fileName,"w")) == NULL ) { + MessageBox(hW,(LPCTSTR)"Couldn't save the file.",NULL,(UINT)MB_ICONERROR); + return FALSE; + } + + tmpi = SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_GETLINECOUNT, (WPARAM)NULL, (LPARAM)NULL); + i=0; + for (;tmpi>=0;tmpi--) + i += SendDlgItemMessage(hW, IDC_PATCHTEXT, EM_LINELENGTH, (WPARAM)tmpi, (LPARAM)NULL); + + tmpStr = (char *) malloc(i); + sprintf(tmpStr,""); + SendDlgItemMessage(hW, IDC_PATCHTEXT, WM_GETTEXT, (WPARAM)i, (LPARAM)tmpStr); + + //remove \r + for (i=0,tmpi=0; tmpStr[i]!='\0'; i++) + if (tmpStr[i] != '\r') + tmpStr[tmpi++] = tmpStr[i]; + tmpStr[tmpi] = '\0'; + + fputs(tmpStr,fp); + + fclose(fp); + free(tmpStr); + + MessageBox(hW,(LPCTSTR)"File saved sucessfully.",NULL,(UINT)MB_ICONINFORMATION); + + return TRUE; + + case IDC_REFRESHPATCHLIST: + + //List Patches + ListPatches ((HWND) hW); + + return TRUE; + + case IDC_EXITPB: + + //Close Dialog + EndDialog(hW, FALSE); + + return TRUE; + + case IDC_PATCHCRCLIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + return ReadPatch ((HWND) hW, fileName); + + case IDC_PATCHNAMELIST: + + //Get selected item + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETCURSEL, 0, 0); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_GETTEXT, (WPARAM)tmpi, (LPARAM)fileName); + + //another small hack :p + //eg. SOCOM Demo PAL (7dd01dd9.pnach) + for (i=0;i<(int)strlen(fileName);i++) + if (fileName[i] == '(') tmpi = i; + + sprintf(fileName,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + fileName[tmpi+1],fileName[tmpi+2],fileName[tmpi+3], + fileName[tmpi+4],fileName[tmpi+5],fileName[tmpi+6], + fileName[tmpi+7],fileName[tmpi+8],fileName[tmpi+9], + fileName[tmpi+10],fileName[tmpi+11],fileName[tmpi+12], + fileName[tmpi+13],fileName[tmpi+14]); + + //sanity check + if (fileName[tmpi+15] != ')') return FALSE; + + return ReadPatch ((HWND) hW, fileName); + + case IDC_SEARCHPATCHTEXT: + + //get text + SendDlgItemMessage(hW, IDC_SEARCHPATCHTEXT, EM_GETLINE, 0, (LPARAM)fileName); + //search + tmpi = SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)fileName); + //select match item + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, LB_SETCURSEL, (WPARAM)tmpi, (LPARAM)NULL); + + return TRUE; + } + return TRUE; + + case WM_CLOSE: + EndDialog(hW, FALSE); + break; + + } + return FALSE; +} +void ListPatches (HWND hW) { + + int i, tmpi, filesize, totalPatch=0, totalSize=0; + char tmpStr[MAX_PATH], *fileData; + WIN32_FIND_DATA FindData; + HANDLE Find; + FILE *fp; + + //clear listbox's + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + SendDlgItemMessage(hW, IDC_PATCHNAMELIST, (UINT)LB_RESETCONTENT, (WPARAM)NULL, (LPARAM)NULL); + + //sprintf(tmpStr,"%s*.pnach", Config.PatchDir) + sprintf(tmpStr, "patches\\*.pnach"); + + Find = FindFirstFile(tmpStr, &FindData); + + do { + if (Find==INVALID_HANDLE_VALUE) break; + + sprintf(tmpStr,"%s", FindData.cFileName); + + //add file name to crc list + SendDlgItemMessage(hW, IDC_PATCHCRCLIST, (UINT) LB_ADDSTRING, (WPARAM)NULL, (LPARAM)tmpStr); + + //sprintf(tmpStr,"%s%s", Config.PatchDir, FindData.cFileName) + sprintf(tmpStr,"patches\\%s", FindData.cFileName); + + fp = fopen(tmpStr, "r"); + if (fp == NULL) break; + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + totalSize += filesize; + fseek(fp, 0, SEEK_SET); + + fileData = (char *) malloc(filesize+1024); + sprintf(fileData,""); + + //read file + while((tmpi=fgetc(fp)) != EOF) + sprintf(fileData,"%s%c",fileData,tmpi); + + //small hack :p + for(i=0;ii;tmpi--) + fileData[tmpi] = fileData[tmpi-1]; + fileData[i] = '\r'; + fileData[i+1] = '\n'; + i++; + } + } + + SetDlgItemText(hW, IDC_PATCHTEXT, (LPCTSTR)fileData); + + sprintf(fileData,""); + fclose(fp); + + return TRUE; +} + + +//Left Trim (remove the spaces at the left of a string) +char * lTrim (char *s) { + int count=0,i,tmpi; + + for (i=0;i<(int)strlen(s); i++) { + if (s[i] == ' ') count++; + else { + for (tmpi=0;tmpi<(int)strlen(s);tmpi++) + s[tmpi] = s[tmpi+count]; + break; + } + } + return s; +} + + +BOOL Save_Patch_Proc( char * filename ) { + + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "Patch Files (*.pnach)\0*.pnach\0ALL Files (*.*)\0*.*"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "TXT"; + ofn.Flags = OFN_EXPLORER | OFN_LONGNAMES | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + if ( GetSaveFileName( &ofn ) ) { + + strcpy( filename, szFileName ); + + return TRUE; + } + else { + return FALSE; + } +} diff --git a/pcsx2/windows/RDebugger.c b/pcsx2/windows/RDebugger.c new file mode 100644 index 0000000..576cc57 --- /dev/null +++ b/pcsx2/windows/RDebugger.c @@ -0,0 +1,375 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "resource.h" +#include "Debugger.h" +#include "RDebugger.h" +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "../rdebug/deci2.h" + +u32 port=8510; +SOCKET serversocket, remote; +char message[1024]; //message to add to listbox + +int runStatus=STOP, runCode=0, runCount=1; +HANDLE runEvent=NULL; + +DECI2_DBGP_BRK ebrk[32], + ibrk[32]; +int ebrk_count=0, + ibrk_count=0; + +int debuggedCpu=0; //default is to debug EE cpu; IOP=1 +u32 breakAddress=0; //disabled; ie. you cannot use address 0 for a breakpoint +u32 breakCycle=0; //disabled; ie. you cannot stop after 0 cycles + +int CreateSocket(HWND hDlg, int port){ + WSADATA wsadata; + SOCKADDR_IN saServer; + + if (WSAStartup( MAKEWORD(1, 1), &wsadata) || + ((serversocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET)){ + MessageBox(hDlg, "Could not create socket\n[Is TCP/IP installed? WinSock 1.1 or above?]", 0, MB_OK); + return FALSE; + } + sprintf(message, "[PCSX2] %s status=%s", wsadata.szDescription, wsadata.szSystemStatus); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + saServer.sin_family = AF_INET; + saServer.sin_addr.S_un.S_addr = INADDR_ANY; // accept any address + saServer.sin_port = htons(port); // port to listen to + + if (bind(serversocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr))==SOCKET_ERROR){ + sprintf(message, "Could not bind to port %d\n" + "[Is there another server running on that port?]", port); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Port %d is opened", port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + // SOMAXCONN connections in queque? maybe 1 is enough... + if (listen(serversocket, SOMAXCONN) == SOCKET_ERROR){ + sprintf(message, "Listening for a connection failed\n" + "[dunno?]"); + MessageBox(hDlg, message, 0, MB_OK); + closesocket(serversocket); + return FALSE; + } + sprintf(message, "[PCSX2] Listening for a connection to establish..."); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + + cpuRegs.CP0.n.EPC=cpuRegs.pc; + psxRegs.CP0.n.EPC=psxRegs.pc; + sprintf(message, "%08X", cpuRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), message); + sprintf(message, "%08X", psxRegs.pc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), message); + sprintf(message, "%d", cpuRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), message); + sprintf(message, "%d", psxRegs.cycle); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), message); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGEE), (debuggedCpu==0)); + Button_SetCheck(GetDlgItem(hDlg, IDC_DEBUGIOP), (debuggedCpu==1)); + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAT), 8); //8 hex digits + Edit_LimitText(GetDlgItem(hDlg, IDC_STOPAFTER), 10);//10 decimal digits + sprintf(message, "%08X", breakAddress); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAT), message); + sprintf(message, "%d", breakCycle); + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), message); + + Button_Enable(GetDlgItem(hDlg, IDC_DEBUGIOP), FALSE);//////////////////////// + + return TRUE; +} + +int readData(char *buffer){ + int r, count=0; + u8 *p=buffer; + + memset(buffer, 0, BUFFERSIZE); + while (((count+= r = recv(remote, p, BUFFERSIZE, 0))!=INVALID_SOCKET) && + (count<*(u16*)buffer)) + p+=r; + + if (r==INVALID_SOCKET) + return 0; + + return count; +} + +int writeData(char *result){ + int r;/*, i; + static char l[300], p[10]; + DECI2_HEADER *header=(DECI2_HEADER*)result; +*/ + r = send(remote, result, *(u16*)result, 0); + if (r==SOCKET_ERROR) + return 0; +/* + sprintf(l, "size=%d, src=%c dst=%c proto=0x%04X ", + header->length-8, header->source, header->destination, header->protocol); + for (i=8; i<*(u16*)result; i++){ + sprintf(p, "%02X ", result[i]); + strcat(l, p); + } + SysMessage(l); +*/ + return r; +} + +DWORD WINAPI ServingFunction(LPVOID lpParam){ + static u8 buffer[BUFFERSIZE], //a big buffer + result[BUFFERSIZE], //a big buffer + eepc[9], ioppc[9], eecy[15], iopcy[15]; + SOCKADDR_IN saClient; + HWND hDlg=(HWND)lpParam; + DWORD size=sizeof(struct sockaddr); + int exit=FALSE; + + if ((remote = accept(serversocket, (struct sockaddr*)&saClient, &size))==INVALID_SOCKET){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Commmunication lost. THE END"); + return FALSE; + } + sprintf(message, "[PCSX2] Connected to %d.%d.%d.%d on remote port %d", + saClient.sin_addr.S_un.S_un_b.s_b1, + saClient.sin_addr.S_un.S_un_b.s_b2, + saClient.sin_addr.S_un.S_un_b.s_b3, + saClient.sin_addr.S_un.S_un_b.s_b4, + saClient.sin_port); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Start serving..."); + connected=1;//from this point on, all log stuff goes to ttyp + + //sendBREAK('E', 0, 0xff, 0x21, 1); //do not enable this unless you know what you are doing! + while (!exit && readData(buffer)){ + DECI2_HEADER *header=(DECI2_HEADER*)buffer; + + switch(header->protocol){ + case 0x0000:exit=TRUE; break; + case PROTO_DCMP:D2_DCMP(buffer, result, message); break; +// case 0x0120:D2_DRFP_EE(buffer, result, message); break; +// case 0x0121:D2_DRFP_IOP(buffer, result, message); break; +// case 0x0122:break; + case PROTO_IDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy); break; +// case 0x0140:break; + case PROTO_ILOADP:D2_ILOADP(buffer, result, message); break; + case PROTO_EDBGP:D2_DBGP(buffer, result, message, eepc, ioppc, eecy, iopcy);break; +// case 0x0240:break; + case PROTO_NETMP:D2_NETMP(buffer, result, message); break; + default: + sprintf(message, "[DECI2 %c->%c/%04X] Protocol=0x%04X", + header->source, header->destination, + header->length, header->protocol); + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + continue; + } + if (exit==FALSE){ + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), message); + Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), eepc); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), ioppc); + Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), eecy); + Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), iopcy); + } + } + connected=0; + + ListBox_AddString(GetDlgItem(hDlg, IDC_COMMUNICATION), "[PCSX2] Connection closed. THE END"); + return TRUE; +} + +DWORD WINAPI Run2(LPVOID lpParam){ + HWND hDlg=(HWND)lpParam; + static char pc[9]; + int i; + + while (1){ + if (runStatus==RUN){ + if (PSMu32(cpuRegs.pc)==0x0000000D){ + sendBREAK('E', 0, runCode, 0x22, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((runCode==2) && (//next + ((PSMu32(cpuRegs.pc) & 0xFC000000)==0x0C000000) ||//JAL + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x00000009) ||//JALR + ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C) //SYSCALL + )){u32 tmppc=cpuRegs.pc, skip=(PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C ? 4 : 8; + while (cpuRegs.pc!=tmppc+skip) + Cpu->Step(); + }else + Cpu->Step(); //use this with breakpoints & step-by-step +// Cpu->ExecuteBlock(); //use this to run faster, but not for stepping +// sprintf(pc, "%08X", cpuRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_EEPC), pc); +// sprintf(pc, "%08X", psxRegs.pc);Edit_SetText(GetDlgItem(hDlg, IDC_IOPPC), pc); +// sprintf(pc, "%d", cpuRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_EECYCLE), pc); +// sprintf(pc, "%d", psxRegs.cycle);Edit_SetText(GetDlgItem(hDlg, IDC_IOPCYCLE), pc); + if (runCount!=0 && --runCount==0){ + sendBREAK('E', 0, runCode, 0x23, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakAddress) && (breakAddress==cpuRegs.pc)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + continue; + } + if ((breakCycle) && (breakCycle==cpuRegs.cycle)){ + sendBREAK('E', 0, runCode, 0x21, runCount); + InterlockedExchange(&runStatus, STOP); + breakCycle=0; + Edit_SetText(GetDlgItem(hDlg, IDC_STOPAFTER), "0"); + continue; + } + for (i=0; i +#include +#include + +#define BUFFERSIZE (128*1024) + +extern LRESULT WINAPI RemoteDebuggerParamsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +extern LRESULT WINAPI RemoteDebuggerProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/pcsx2/windows/VCprojects/pcsx2_2003.sln b/pcsx2/windows/VCprojects/pcsx2_2003.sln new file mode 100644 index 0000000..04b5737 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2003.sln @@ -0,0 +1,72 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2003.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSogl", "..\..\..\plugins\gs\zerogs\opengl\Win32\zerogsogl.vcproj", "{2D4E85B2-F47F-4D65-B091-701E5C031DAC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spu2PeopsSound", "..\..\..\plugins\spu2\PeopsSPU2\spu2PeopsSound.vcproj", "{F9E64144-301B-48BC-8D35-A2686DBB1982}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2null", "..\..\..\plugins\spu2\SPU2null\Src\SPU2null.vcproj", "{4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Debug TLB = Debug TLB + Release = Release + Release (to Public) = Release (to Public) + Release TLB = Release TLB + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.ActiveCfg = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB.Build.0 = Debut TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release.Build.0 = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).ActiveCfg = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public).Build.0 = Release (to Public)|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB.Build.0 = Release TLB|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release.ActiveCfg = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release.Build.0 = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public).ActiveCfg = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public).Build.0 = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB.ActiveCfg = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB.Build.0 = Release (to Public)|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug TLB.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug TLB.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release.Build.0 = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release (to Public).ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release (to Public).Build.0 = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release TLB.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release TLB.Build.0 = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Debug.ActiveCfg = Debug|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Debug.Build.0 = Debug|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Debug TLB.ActiveCfg = Debug|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Debug TLB.Build.0 = Debug|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release.ActiveCfg = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release.Build.0 = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release (to Public).ActiveCfg = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release (to Public).Build.0 = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release TLB.ActiveCfg = Release|Win32 + {4DA8FB7A-A7C5-4FF9-82FA-BA385F3B3D00}.Release TLB.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/pcsx2/windows/VCprojects/pcsx2_2003.vcproj b/pcsx2/windows/VCprojects/pcsx2_2003.vcproj new file mode 100644 index 0000000..39a0b46 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2003.vcproj @@ -0,0 +1,1311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcsx2/windows/VCprojects/pcsx2_2005.sln b/pcsx2/windows/VCprojects/pcsx2_2005.sln new file mode 100644 index 0000000..c2aec05 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2005.sln @@ -0,0 +1,76 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSogl", "..\..\..\plugins\gs\zerogs\opengl\Win32\zerogsogl_2005.vcproj", "{2D4E85B2-F47F-4D65-B091-701E5C031DAC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spu2PeopsSound", "..\..\..\plugins\spu2\PeopsSPU2\spu2PeopsSound_2005.vcproj", "{F9E64144-301B-48BC-8D35-A2686DBB1982}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroSPU2", "..\..\..\plugins\spu2\zerospu2\ZeroSPU2_2005.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroPAD", "..\..\..\plugins\pad\zeropad\Windows\ZeroPAD_2005.vcproj", "{CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug TLB|Win32 = Debug TLB|Win32 + Debug|Win32 = Debug|Win32 + Release (to Public)|Win32 = Release (to Public)|Win32 + Release TLB|Win32 = Release TLB|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.ActiveCfg = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.Build.0 = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public)|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public)|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.Build.0 = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB|Win32.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB|Win32.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|Win32.ActiveCfg = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|Win32.Build.0 = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB|Win32.ActiveCfg = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB|Win32.Build.0 = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.ActiveCfg = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.Build.0 = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug TLB|Win32.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug TLB|Win32.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|Win32.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|Win32.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release (to Public)|Win32.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release (to Public)|Win32.Build.0 = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release TLB|Win32.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release TLB|Win32.Build.0 = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|Win32.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|Win32.Build.0 = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug TLB|Win32.ActiveCfg = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug TLB|Win32.Build.0 = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.Build.0 = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release (to Public)|Win32.ActiveCfg = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release (to Public)|Win32.Build.0 = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release TLB|Win32.ActiveCfg = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release TLB|Win32.Build.0 = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.ActiveCfg = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.Build.0 = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Debug TLB|Win32.ActiveCfg = Debug|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Debug TLB|Win32.Build.0 = Debug|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Debug|Win32.ActiveCfg = Debug|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Debug|Win32.Build.0 = Debug|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release (to Public)|Win32.ActiveCfg = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release (to Public)|Win32.Build.0 = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release TLB|Win32.ActiveCfg = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release TLB|Win32.Build.0 = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release|Win32.ActiveCfg = Release|Win32 + {CDD9DB83-3BD9-4ED8-BB83-399A2F65F022}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/pcsx2/windows/VCprojects/pcsx2_2005.vcproj b/pcsx2/windows/VCprojects/pcsx2_2005.vcproj new file mode 100644 index 0000000..5991e00 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2005.vcproj @@ -0,0 +1,1562 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcsx2/windows/VCprojects/pcsx2_2005_x64.sln b/pcsx2/windows/VCprojects/pcsx2_2005_x64.sln new file mode 100644 index 0000000..3194cd5 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2005_x64.sln @@ -0,0 +1,82 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2", "pcsx2_2005_x64.vcproj", "{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSogl", "..\..\..\plugins\gs\zerogs\opengl\Win32\zerogsogl_2005_x64.vcproj", "{2D4E85B2-F47F-4D65-B091-701E5C031DAC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2null", "..\..\..\plugins\spu2\SPU2null\Src\SPU2null_2005_x64.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug TLB|Win32 = Debug TLB|Win32 + Debug TLB|x64 = Debug TLB|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release (to Public)|Win32 = Release (to Public)|Win32 + Release (to Public)|x64 = Release (to Public)|x64 + Release TLB|Win32 = Release TLB|Win32 + Release TLB|x64 = Release TLB|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.ActiveCfg = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|Win32.Build.0 = Debug TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|x64.ActiveCfg = Debug TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug TLB|x64.Build.0 = Debug TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|Win32.Build.0 = Debug|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|x64.ActiveCfg = Debug|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Debug|x64.Build.0 = Debug|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public)|Win32.ActiveCfg = Release TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public)|x64.ActiveCfg = Release TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release (to Public)|x64.Build.0 = Release TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.ActiveCfg = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|Win32.Build.0 = Release TLB|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|x64.ActiveCfg = Release TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release TLB|x64.Build.0 = Release TLB|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.ActiveCfg = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|Win32.Build.0 = Release|Win32 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|x64.ActiveCfg = Release|x64 + {1CEFD830-2B76-4596-A4EE-BCD7280A60BD}.Release|x64.Build.0 = Release|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB|Win32.ActiveCfg = Debug|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB|x64.ActiveCfg = Debug|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug TLB|x64.Build.0 = Debug|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.ActiveCfg = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|Win32.Build.0 = Debug|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|x64.ActiveCfg = Debug|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Debug|x64.Build.0 = Debug|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|Win32.ActiveCfg = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|Win32.Build.0 = Release (to Public)|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|x64.ActiveCfg = Release (to Public)|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release (to Public)|x64.Build.0 = Release (to Public)|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB|Win32.ActiveCfg = Release (to Public)|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB|x64.ActiveCfg = Release (to Public)|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release TLB|x64.Build.0 = Release (to Public)|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.ActiveCfg = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|Win32.Build.0 = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|x64.ActiveCfg = Release|x64 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release|x64.Build.0 = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug TLB|Win32.ActiveCfg = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug TLB|x64.ActiveCfg = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug TLB|x64.Build.0 = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.Build.0 = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|x64.ActiveCfg = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|x64.Build.0 = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release (to Public)|Win32.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release (to Public)|x64.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release (to Public)|x64.Build.0 = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release TLB|Win32.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release TLB|x64.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release TLB|x64.Build.0 = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.ActiveCfg = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.Build.0 = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|x64.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/pcsx2/windows/VCprojects/pcsx2_2005_x64.vcproj b/pcsx2/windows/VCprojects/pcsx2_2005_x64.vcproj new file mode 100644 index 0000000..5a01b42 --- /dev/null +++ b/pcsx2/windows/VCprojects/pcsx2_2005_x64.vcproj @@ -0,0 +1,2245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcsx2/windows/Win32.h b/pcsx2/windows/Win32.h new file mode 100644 index 0000000..607396d --- /dev/null +++ b/pcsx2/windows/Win32.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIN32_H__ +#define __WIN32_H__ + +extern int needReset; + +AppData gApp; +HWND hStatusWnd; + +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); +void CreateMainWindow(int nCmdShow); +void RunGui(); +int LoadConfig(); +void SaveConfig(); + +BOOL Open_File_Proc(char *filename); +BOOL Pcsx2Configure(HWND hWnd); +void RunExecute(int run); +void InitLanguages(); +char *GetLanguageNext(); +void CloseLanguages(); +void ChangeLanguage(char *lang); +void OpenConsole(); +void CloseConsole(); +#define StatusSet(text) SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text); + +//patch browser window +BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +//cpu dialog window +BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + diff --git a/pcsx2/windows/WinMain.c b/pcsx2/windows/WinMain.c new file mode 100644 index 0000000..404868c --- /dev/null +++ b/pcsx2/windows/WinMain.c @@ -0,0 +1,1912 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define WINVER 0x0500 + +#if _WIN32_WINNT < 0x0500 +#define _WIN32_WINNT 0x0500 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Common.h" +#include "PsxCommon.h" +#include "win32.h" +#include "resource.h" +#include "debugger.h" +#include "rdebugger.h" +#include "AboutDlg.h" +#include "McdsDlg.h" + +#include "VU.h" +#include "iCore.h" +#include "iVUzerorec.h" + +#include "cheats/cheats.h" + +#define COMPILEDATE __DATE__ + +static int efile; +char filename[256]; +extern int g_SaveGSStream; + +static int AccBreak = 0; +int needReset = 1; +unsigned int langsMax; +typedef struct { + char lang[256]; +} _langs; +_langs *langs = NULL; + +int UseGui = 1; +int nDisableSC = 0; // screensaver +int firstRun=1; +int RunExe = 0; +void OpenConsole() { + COORD csize; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + SMALL_RECT srect; + + if (gApp.hConsole) return; + AllocConsole(); + SetConsoleTitle(_("Ps2 Output")); + csize.X = 100; + csize.Y = 1024; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), csize); + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + srect = csbiInfo.srWindow; + srect.Right = srect.Left + 99; + srect.Bottom = srect.Top + 64; + SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &srect); + gApp.hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} + +void CloseConsole() { + if (gApp.hConsole == NULL) return; + FreeConsole(); gApp.hConsole = NULL; +} +void strcatz(char *dst, char *src) { + int len = strlen(dst) + 1; + strcpy(dst + len, src); +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);//forward def +//------------------- + +extern int g_ZeroGSOptions; +void RunExecute(int run) { + SetThreadPriority(GetCurrentThread(), Config.ThPriority); + SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); + nDisableSC = 1; + + if (needReset == 1) { + SysReset(); + } + + if( UseGui ) + AccBreak = 1; + + DestroyWindow(gApp.hWnd); + gApp.hWnd = NULL; + + if (OpenPlugins(g_TestRun.ptitle) == -1) { + CreateMainWindow(SW_SHOWNORMAL); + return; + } + + if (needReset == 1) { + if(RunExe == 0)cpuExecuteBios(); + //if (efile == 2) + if(!efile)efile=GetPS2ElfName(filename); + //if (efile) + loadElfFile(filename); + + RunExe = 0; + efile=0; + needReset = 0; + } + + // this needs to be called for every new game! (note: sometimes launching games through bios will give a crc of 0) + if( GSsetGameCRC != NULL ) + GSsetGameCRC(ElfCRC, g_ZeroGSOptions); + + if (run) Cpu->Execute(); +} + +int Slots[5] = { -1, -1, -1, -1, -1 }; + +void ResetMenuSlots() { + int i; + + for (i=0; i<5; i++) { + if (Slots[i] == -1) + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED); + else + EnableMenuItem(GetSubMenu(gApp.hMenu, 0), ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED); + } +} + +void UpdateMenuSlots() { + char str[256]; + int i; + + for (i=0; i<5; i++) { + sprintf (str, "sstates\\%8.8X.%3.3d", ElfCRC, i); + Slots[i] = CheckState(str); + } +} + +void States_Load(int num) { + char Text[256]; + int ret; + + efile = 0; + RunExecute(0); + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = LoadState(Text); + if (ret == 0) + sprintf (Text, _("*PCSX2*: Loaded State %d"), num+1); + else sprintf (Text, _("*PCSX2*: Error Loading State %d"), num+1); + StatusSet(Text); + + Cpu->Execute(); +} + +void States_Save(int num) { + char Text[256]; + int ret; + + + sprintf (Text, "sstates\\%8.8X.%3.3d", ElfCRC, num); + ret = SaveState(Text); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %d"), num+1); + else sprintf(Text, _("*PCSX2*: Error Saving State %d"), num+1); + StatusSet(Text); + + RunExecute(1); +} + +void OnStates_LoadOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + efile = 2; + RunExecute(0); + + ret = LoadState(szFileName); + + if (ret == 0) + sprintf(Text, _("*PCSX2*: Saving State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Saving State %s"), szFileName); + StatusSet(Text); + + Cpu->Execute(); + } +} + +void OnStates_Save1() { States_Save(0); } +void OnStates_Save2() { States_Save(1); } +void OnStates_Save3() { States_Save(2); } +void OnStates_Save4() { States_Save(3); } +void OnStates_Save5() { States_Save(4); } + +char* g_pRunGSState = NULL; + +void OnStates_SaveOther() { + OPENFILENAME ofn; + char szFileName[256]; + char szFileTitle[256]; + char szFilter[256]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + strcpy(szFilter, _("PCSX2 State Format")); + strcatz(szFilter, "*.*;*.*"); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "EXE"; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + char Text[256]; + int ret; + + ret = SaveState(szFileName); + if (ret == 0) + sprintf(Text, _("*PCSX2*: Loaded State %s"), szFileName); + else sprintf(Text, _("*PCSX2*: Error Loading State %s"), szFileName); + StatusSet(Text); + + RunExecute(1); + } +} + +#ifdef PCSX2_DEVBUILD + +TESTRUNARGS g_TestRun; + +static int ParseCommandLine(char* pcmd) +{ + const char* pdelim = " \t\r\n"; + char* token = strtok(pcmd, pdelim); + + g_TestRun.efile = 0; + + while(token != NULL) { + + if( stricmp(token, "-help") == 0) { + const char* phelpmsg = + "pcsx2 [options] [file]\n\n" + "-cfg [file] {configuration file}\n" + "-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n" + "-help {display this help file}\n" + "-nogui {Don't use gui when launching}\n" + "-loadgs [file} {Loads a gsstate}\n" + "\n" +#ifdef PCSX2_DEVBUILD + "Testing Options: \n" + "\t-frame [frame] {game will run up to this frame before exiting}\n" + "\t-image [name] {path and base name of image (do not include the .ext)}\n" + "\t-jpg {save images to jpg format}\n" + "\t-log [name] {log path to save log file in}\n" + "\t-logopt [hex] {log options in hex (see debug.h) }\n" + "\t-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n" + "\t-test {Triggers testing mode (only for dev builds)}\n" + "\n" +#endif + + "Load Plugins:\n" + "\t-cdvd [dllpath] {specify the dll load path of the CDVD plugin}\n" + "\t-gs [dllpath] {specify the dll load path of the GS plugin}\n" + "-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n" + "\t-spu [dllpath] {specify the dll load path of the SPU2 plugin}\n" + "\n"; + + printf("%s", phelpmsg); + MessageBox(NULL,phelpmsg,"Help", MB_OK); + return -1; + } + else if( stricmp(token, "-nogui") == 0 ) { + UseGui = 0; + } + else if( stricmp(token, "-image") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pimagename = token; + } + else if( stricmp(token, "-log") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.plogname = token; + } + else if( stricmp(token, "-logopt") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + if( token[0] == '0' && token[1] == 'x' ) token += 2; + sscanf(token, "%x", &varLog); + } + } + else if( stricmp(token, "-pad") == 0 ) { + token = strtok(NULL, pdelim); + printf("-pad ignored\n"); + } + else if( stricmp(token, "-frame") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.frame = atoi(token); + } + } + else if( stricmp(token, "-numimages") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.numimages = atoi(token); + } + } + else if( stricmp(token, "-efile") == 0 ) { + token = strtok(NULL, pdelim); + if( token != NULL ) { + g_TestRun.efile = atoi(token); + } + } + else if( stricmp(token, "-jpg") == 0 ) { + g_TestRun.jpgcapture = 1; + } + else if( stricmp(token, "-gs") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pgsdll = token; + } + else if( stricmp(token, "-cdvd") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pcdvddll = token; + } + else if( stricmp(token, "-spu") == 0 ) { + token = strtok(NULL, pdelim); + g_TestRun.pspudll = token; + } + else if( stricmp(token, "-loadgs") == 0 ) { + token = strtok(NULL, pdelim); + g_pRunGSState = token; + } + else { + g_TestRun.ptitle = token; + printf("opening file %s\n", token); + } + + if( token == NULL ) { + printf("invalid args\n"); + return -1; + } + + token = strtok(NULL, pdelim); + } + + return 0; +} + +#endif +extern void LoadPatch(char *crc); + +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable); + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char *lang; + int i; + +#ifdef PCSX2_VIRTUAL_MEM + LPVOID lpMemReserved; +#endif + + InitCommonControls(); + pInstance=hInstance; + FirstShow=true; + +#ifdef PCSX2_VIRTUAL_MEM + + if( !SysLoggedSetLockPagesPrivilege( GetCurrentProcess(), TRUE ) ) + return -1; + + lpMemReserved = VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS); + + if( lpMemReserved == NULL || lpMemReserved!= PS2MEM_BASE ) { + char str[255]; + sprintf(str, "Cannot allocate mem addresses %x-%x, err: %d", PS2MEM_BASE, PS2MEM_BASE+0x40000000, GetLastError()); + MessageBox(NULL, str, "SysError", MB_OK); + return -1; + } +#endif + + gApp.hInstance = hInstance; + gApp.hMenu = NULL; + gApp.hWnd = NULL; + gApp.hConsole = NULL; + +#ifdef ENABLE_NLS + bindtextdomain(PACKAGE, "Langs\\"); + textdomain(PACKAGE); +#endif + + if (LoadConfig() == -1) { + memset(&Config, 0, sizeof(Config)); + //strcpy(Config.Bios, "HLE"); + strcpy(Config.BiosDir, "Bios\\"); + strcpy(Config.PluginsDir, "Plugins\\"); + Config.Patch = 1; + + SysMessage(_("Pcsx2 needs to be configured")); + Pcsx2Configure(NULL); + + return 0; + } + if (Config.Lang[0] == 0) { + strcpy(Config.Lang, "en_US"); + } + + langs = (_langs*)malloc(sizeof(_langs)); + strcpy(langs[0].lang, "en_US"); + InitLanguages(); i=1; + while ((lang = GetLanguageNext()) != NULL) { + langs = (_langs*)realloc(langs, sizeof(_langs)*(i+1)); + strcpy(langs[i].lang, lang); + i++; + } + CloseLanguages(); + langsMax = i; + + if (Config.PsxOut) OpenConsole(); + + memset(&g_TestRun, 0, sizeof(g_TestRun)); + + if( lpCmdLine == NULL || *lpCmdLine == 0 ) + SysPrintf("-help to see arguments\n"); + else if( ParseCommandLine(lpCmdLine) == -1 ) { + return 2; + } + + if( g_TestRun.pgsdll ) + _snprintf(Config.GS, sizeof(Config.GS), "%s", g_TestRun.pgsdll); + if( g_TestRun.pcdvddll ) + _snprintf(Config.CDVD, sizeof(Config.CDVD), "%s", g_TestRun.pcdvddll); + if( g_TestRun.pspudll ) + _snprintf(Config.SPU2, sizeof(Config.SPU2), "%s", g_TestRun.pspudll); + + if (SysInit() == -1) return 1; + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.enabled || g_TestRun.ptitle != NULL ) { + // run without ui + UseGui = 0; + _snprintf(filename, sizeof(filename), "%s", g_TestRun.ptitle); + needReset = 1; + efile = g_TestRun.efile; + RunExecute(1); + SysClose(); + return 0; // success! + } +#endif + +#ifdef PCSX2_DEVBUILD + if( g_pRunGSState ) { + LoadGSState(g_pRunGSState); + SysClose(); + return 0; + } +#endif + + CreateMainWindow(nCmdShow); + + if( Config.PsxOut ) { + // output the help commands + SysPrintf("\tF1 - save state\n"); + SysPrintf("\t(Shift +) F2 - cycle states\n"); + SysPrintf("\tF3 - load state\n"); + +#ifdef PCSX2_DEVBUILD + SysPrintf("\tF10 - dump performance counters\n"); + SysPrintf("\tF11 - save GS state\n"); + SysPrintf("\tF12 - dump hardware registers\n"); +#endif + } + + LoadPatch("default"); + +// needReset = 1; +// efile = 0; +// RunExecute(1); + + RunGui(); + +#ifdef PCSX2_VIRTUAL_MEM + VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE); +#endif + + return 0; +} + +void RunGui() { + MSG msg; + + for (;;) { + if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + Sleep(10); + } +} + +void CALLBACK KeyEvent(keyEvent* ev) +{ + if (ev == NULL) return; + if (ev->event == KEYRELEASE) { + GSkeyEvent(ev); return; + } + if (ev->event != KEYPRESS) return; + + int shift = !!(GetKeyState(VK_SHIFT)&0x8000); + + switch (ev->key) { + case VK_F1: ProcessFKeys(1, shift); break; + case VK_F2: ProcessFKeys(2, shift); break; + case VK_F3: ProcessFKeys(3, shift); break; + case VK_F4: ProcessFKeys(4, shift); break; + case VK_F5: ProcessFKeys(5, shift); break; + case VK_F6: ProcessFKeys(6, shift); break; + case VK_F7: ProcessFKeys(7, shift); break; + case VK_F8: ProcessFKeys(8, shift); break; + case VK_F9: ProcessFKeys(9, shift); break; + case VK_F10: ProcessFKeys(10, shift); break; + case VK_F11: ProcessFKeys(11, shift); break; + case VK_F12: ProcessFKeys(12, shift); break; + + case VK_ESCAPE: +#ifdef PCSX2_DEVBUILD + if( g_SaveGSStream >= 3 ) { + // gs state + g_SaveGSStream = 4; + break; + } +#endif + + ClosePlugins(); + + if( !UseGui ) { + // not using GUI and user just quit, so exit + exit(0); + } + + CreateMainWindow(SW_SHOWNORMAL); + RunGui(); + nDisableSC = 0; + break; + default: + GSkeyEvent(ev); + break; + } +} + +#ifdef PCSX2_DEVBUILD + +BOOL APIENTRY LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { + int i; + switch (message) { + case WM_INITDIALOG: + for (i=0; i<32; i++) + if (varLog & (1<= ID_LANGS && LOWORD(wParam) <= (ID_LANGS + langsMax)) { + AccBreak = 1; + DestroyWindow(gApp.hWnd); + ChangeLanguage(langs[LOWORD(wParam) - ID_LANGS].lang); + CreateMainWindow(SW_NORMAL); + return TRUE; + } + } + break; + case WM_DESTROY: + if (!AccBreak) { + SysClose(); + DeleteObject(hbitmap_background); + PostQuitMessage(0); + exit(0); + } else AccBreak = 0; + return TRUE; + + case WM_SYSCOMMAND: + if( nDisableSC && (wParam== SC_SCREENSAVE || wParam == SC_MONITORPOWER) ) { + return FALSE; + } + else + return DefWindowProc(hWnd, msg, wParam, lParam); + break; + + case WM_QUIT: + if (Config.PsxOut) CloseConsole(); + exit(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + return FALSE; +} + +#define _ADDSUBMENU(menu, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDSUBMENU(menun, string) \ + _ADDSUBMENU(gApp.hMenu, menun, string); + +#define ADDSUBMENUS(submn, menun, string) \ + submenu[menun] = CreatePopupMenu(); \ + InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); + +#define ADDMENUITEM(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDMENUITEMC(menun, string, id) \ + item.fType = MFT_STRING; \ + item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ + item.fState = MFS_ENABLED | MFS_CHECKED; \ + item.wID = id; \ + sprintf(buf, string); \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +#define ADDSEPARATOR(menun) \ + item.fMask = MIIM_TYPE; \ + item.fType = MFT_SEPARATOR; \ + InsertMenuItem(submenu[menun], 0, TRUE, &item); + +void CreateMainMenu() { + MENUITEMINFO item; + HMENU submenu[5]; + char buf[256]; + int i; + + item.cbSize = sizeof(MENUITEMINFO); + item.dwTypeData = buf; + item.cch = 256; + + gApp.hMenu = CreateMenu(); + + //submenu = CreatePopupMenu(); + //AppendMenu(gApp.hMenu, MF_STRING | MF_POPUP, (UINT)submenu, _("&File")); + ADDSUBMENU(0, _("&File")); + ADDMENUITEM(0, _("E&xit"), ID_FILE_EXIT); + ADDSEPARATOR(0); + ADDSUBMENUS(0, 1, _("&States")); + ADDSEPARATOR(0); + ADDMENUITEM(0, _("&Open ELF File"), ID_FILEOPEN); + ADDMENUITEM(0, _("&Run CD/DVD"), ID_FILE_RUNCD); + ADDSUBMENUS(1, 3, _("&Save")); + ADDSUBMENUS(1, 2, _("&Load")); + ADDMENUITEM(2, _("&Other..."), ID_FILE_STATES_LOAD_OTHER); + ADDMENUITEM(2, _("Slot &5"), ID_FILE_STATES_LOAD_SLOT5); + ADDMENUITEM(2, _("Slot &4"), ID_FILE_STATES_LOAD_SLOT4); + ADDMENUITEM(2, _("Slot &3"), ID_FILE_STATES_LOAD_SLOT3); + ADDMENUITEM(2, _("Slot &2"), ID_FILE_STATES_LOAD_SLOT2); + ADDMENUITEM(2, _("Slot &1"), ID_FILE_STATES_LOAD_SLOT1); + ADDMENUITEM(3, _("&Other..."), ID_FILE_STATES_SAVE_OTHER); + ADDMENUITEM(3, _("Slot &5"), ID_FILE_STATES_SAVE_SLOT5); + ADDMENUITEM(3, _("Slot &4"), ID_FILE_STATES_SAVE_SLOT4); + ADDMENUITEM(3, _("Slot &3"), ID_FILE_STATES_SAVE_SLOT3); + ADDMENUITEM(3, _("Slot &2"), ID_FILE_STATES_SAVE_SLOT2); + ADDMENUITEM(3, _("Slot &1"), ID_FILE_STATES_SAVE_SLOT1); + + ADDSUBMENU(0, _("&Run")); + + ADDSUBMENUS(0, 1, _("&Process Priority")); + ADDMENUITEM(1, _("&Low"), ID_PROCESSLOW ); + ADDMENUITEM(1, _("High"), ID_PROCESSHIGH); + ADDMENUITEM(1, _("Normal"), ID_PROCESSNORMAL); + ADDMENUITEM(0,_("&Arguments"), ID_RUN_CMDLINE); + ADDMENUITEM(0,_("Re&set"), ID_RUN_RESET); + ADDMENUITEM(0,_("E&xecute"), ID_RUN_EXECUTE); + + ADDSUBMENU(0,_("&Config")); +#ifdef PCSX2_DEVBUILD +// ADDMENUITEM(0,_("&Advanced"), ID_CONFIG_ADVANCED); +#endif + ADDMENUITEM(0,_("&Patches"), ID_PATCHBROWSER); + ADDMENUITEM(0,_("C&pu"), ID_CONFIG_CPU); + ADDMENUITEM(0,_("&Memcards"), ID_CONFIG_MEMCARDS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("Fire&Wire"), ID_CONFIG_FW); + ADDMENUITEM(0,_("U&SB"), ID_CONFIG_USB); + ADDMENUITEM(0,_("D&ev9"), ID_CONFIG_DEV9); + ADDMENUITEM(0,_("C&dvdrom"), ID_CONFIG_CDVDROM); + ADDMENUITEM(0,_("&Sound"), ID_CONFIG_SOUND); + ADDMENUITEM(0,_("C&ontrollers"), ID_CONFIG_CONTROLLERS); + ADDMENUITEM(0,_("&Graphics"), ID_CONFIG_GRAPHICS); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("&Configure"), ID_CONFIG_CONFIGURE); + + ADDSUBMENU(0,_("&Language")); + + for (i=langsMax-1; i>=0; i--) { + if (!strcmp(Config.Lang, langs[i].lang)) { + ADDMENUITEMC(0,ParseLang(langs[i].lang), ID_LANGS + i); + } else { + ADDMENUITEM(0,ParseLang(langs[i].lang), ID_LANGS + i); + } + } + +#ifdef PCSX2_DEVBUILD + ADDSUBMENU(0, _("&Debug")); + ADDMENUITEM(0,_("&Logging"), ID_DEBUG_LOGGING); + ADDMENUITEM(0,_("Memory Dump"), ID_DEBUG_MEMORY_DUMP); + ADDMENUITEM(0,_("&Remote Debugging"), ID_DEBUG_REMOTEDEBUGGING); + ADDMENUITEM(0,_("Enter &Debugger..."), ID_DEBUG_ENTERDEBUGGER); +#endif + + ADDSUBMENU(0, _("&Misc")); + ADDMENUITEM(0,_("Enable &Patches"), ID_PATCHES); + ADDMENUITEM(0,_("Enable &Console"), ID_CONSOLE); + ADDSEPARATOR(0); + ADDMENUITEM(0,_("Patch &Finder..."), ID_CHEAT_FINDER_SHOW); + ADDMENUITEM(0,_("Patch &Browser..."), ID_CHEAT_BROWSER_SHOW); + + + ADDSUBMENU(0, _("&Help")); + ADDMENUITEM(0,_("&Compatibility List..."), ID_HELP_HELP); + ADDMENUITEM(0,_("&About..."), ID_HELP_ABOUT); + +#ifndef PCSX2_DEVBUILD + EnableMenuItem(GetSubMenu(gApp.hMenu, 4), ID_DEBUG_LOGGING, MF_GRAYED); +#endif +} + +void CreateMainWindow(int nCmdShow) { + WNDCLASS wc; + HWND hWnd; + char buf[256]; + char COMPILER[20]=""; + BITMAP bm; + RECT rect; + int w, h; + +#ifdef _MSC_VER + sprintf(COMPILER, "(VC%d)", (_MSC_VER+100)/200);//hacky:) works for VC6 & VC.NET +#elif __BORLANDC__ + sprintf(COMPILER, "(BC)"); +#endif + /* Load Background Bitmap from the ressource */ + hbitmap_background = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(SPLASH_LOGO)); + + wc.lpszClassName = "PCSX2 Main"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = gApp.hInstance; + wc.hIcon = LoadIcon(gApp.hInstance, MAKEINTRESOURCE(IDI_ICON)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_MENUTEXT); + wc.lpszMenuName = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + + RegisterClass(&wc); + GetObject(hbitmap_background, sizeof(bm), &bm); + + { +#ifdef PCSX2_VIRTUAL_MEM + const char* pvm = "VM"; +#else + const char* pvm = "non VM"; +#endif + +#ifdef PCSX2_DEVBUILD + sprintf(buf, _("PCSX2 %s Watermoose - %s Compile Date - %s %s"), PCSX2_VERSION, pvm, COMPILEDATE, COMPILER); +#else + sprintf(buf, _("PCSX2 %s Watermoose - %s"), PCSX2_VERSION, pvm); +#endif + } + + hWnd = CreateWindow("PCSX2 Main", + buf, WS_OVERLAPPED | WS_SYSMENU, + 20, 20, 320, 240, NULL, NULL, + gApp.hInstance, NULL); + + gApp.hWnd = hWnd; + ResetMenuSlots(); + CreateMainMenu(); + + SetMenu(gApp.hWnd, gApp.hMenu); + if(Config.ThPriority==THREAD_PRIORITY_NORMAL) CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_HIGHEST) CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); + if(Config.ThPriority==THREAD_PRIORITY_LOWEST) CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); + if(Config.PsxOut) CheckMenuItem(gApp.hMenu,ID_CONSOLE,MF_CHECKED); + if(Config.Patch) CheckMenuItem(gApp.hMenu,ID_PATCHES,MF_CHECKED); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "PCSX2 %s", PCSX2_VERSION); + StatusSet(buf); + + w = bm.bmWidth; h = bm.bmHeight; + GetWindowRect(hStatusWnd, &rect); + h+= rect.bottom - rect.top; + GetMenuItemRect(hWnd, gApp.hMenu, 0, &rect); + h+= rect.bottom - rect.top; + MoveWindow(hWnd, 20, 20, w, h, TRUE); + + DestroyWindow(hStatusWnd); + hStatusWnd = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd, 100); + sprintf(buf, "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot", PCSX2_VERSION); + StatusSet(buf); + ShowWindow(hWnd, nCmdShow); + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} + +BOOL Open_File_Proc(char * filename) { + OPENFILENAME ofn; + char szFileName[ 256 ]; + char szFileTitle[ 256 ]; + char * filter = "ELF Files (*.ELF)\0*.ELF\0ALL Files (*.*)\0*.*\0"; + + memset( &szFileName, 0, sizeof( szFileName ) ); + memset( &szFileTitle, 0, sizeof( szFileTitle ) ); + + ofn.lStructSize = sizeof( OPENFILENAME ); + ofn.hwndOwner = gApp.hWnd; + ofn.lpstrFilter = filter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = 256; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = 256; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = "ELF"; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName(&ofn)) { + struct stat buf; + + if (stat(szFileName, &buf) != 0) { + return FALSE; + } + + strcpy(filename, szFileName); + return TRUE; + } + + return FALSE; +} + +//2002-09-20 (Florin) +BOOL APIENTRY CmdlineProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + SetWindowText(hDlg, _("Program arguments")); + + Button_SetText(GetDlgItem(hDlg, IDOK), _("OK")); + Button_SetText(GetDlgItem(hDlg, IDCANCEL), _("Cancel")); + Static_SetText(GetDlgItem(hDlg, IDC_TEXT), _("Fill in the command line arguments for opened program:")); + Static_SetText(GetDlgItem(hDlg, IDC_TIP), _("Tip: If you don't know what to write\nleave it blank")); + + SetDlgItemText(hDlg, IDC_CMDLINE, args); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK) + { + char tmp[256]; + + GetDlgItemText(hDlg, IDC_CMDLINE, tmp, 256); + + ZeroMemory(args, 256); + strcpy(args, tmp); + args[255]=0; + + EndDialog(hDlg, TRUE); + } else if (LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + } + return TRUE; + } + + return FALSE; +} + +WIN32_FIND_DATA lFindData; +HANDLE lFind; +int lFirst; + +void InitLanguages() { + lFind = FindFirstFile("Langs\\*", &lFindData); + lFirst = 1; +} + +char *GetLanguageNext() { + for (;;) { + if (!strcmp(lFindData.cFileName, ".")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + if (!strcmp(lFindData.cFileName, "..")) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + continue; + } + break; + } + if (lFirst == 0) { + if (FindNextFile(lFind, &lFindData) == FALSE) + return NULL; + } else lFirst = 0; + if (lFind==INVALID_HANDLE_VALUE) return NULL; + + return lFindData.cFileName; +} + +void CloseLanguages() { + if (lFind!=INVALID_HANDLE_VALUE) FindClose(lFind); +} + +void ChangeLanguage(char *lang) { + strcpy(Config.Lang, lang); + SaveConfig(); + LoadConfig(); +} + +//------------------- + +static int sinit=0; + +int SysInit() { + CreateDirectory("memcards", NULL); + CreateDirectory("sstates", NULL); +#ifdef EMU_LOG + CreateDirectory("logs", NULL); + +#ifdef PCSX2_DEVBUILD + if( g_TestRun.plogname != NULL ) + emuLog = fopen(g_TestRun.plogname, "w"); + if( emuLog == NULL ) + emuLog = fopen("logs\\emuLog.txt","w"); +#endif + + if( emuLog != NULL ) + setvbuf(emuLog, NULL, _IONBF, 0); + +#endif + if (cpuInit() == -1) return -1; + + while (LoadPlugins() == -1) { + if (Pcsx2Configure(NULL) == FALSE) { + exit(1); + } + } + + sinit=1; + + return 0; +} + +void SysReset() { + if (sinit == 0) return; + StatusSet(_("Resetting...")); + cpuReset(); + StatusSet(_("Ready")); +} + + +void SysClose() { + if (sinit == 0) return; + cpuShutdown(); + ReleasePlugins(); + sinit=0; +} + +int concolors[] = { + 0, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_GREEN | FOREGROUND_RED, + FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_BLUE, + FOREGROUND_RED | FOREGROUND_GREEN, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE +}; + +void SysPrintf(char *fmt, ...) { + va_list list; + char msg[512]; + char *ptr; + DWORD tmp; + int len, s; + int i, j; + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + msg[511] = '\0'; + va_end(list); + + if (Config.PsxOut == 0) { +#ifdef EMU_LOG +#ifndef LOG_STDOUT + if (emuLog != NULL && !(varLog & 0x80000000)) { + fprintf(emuLog, "%s", msg); + } +#endif +#endif + return; + } + + ptr = msg; len = strlen(msg); + for (i=0, j=0; i 0x7ffe) // String is too large + return FALSE; + } + + // Store the string. + pLsaString->Buffer = (WCHAR *)pwszString; + pLsaString->Length = (USHORT)dwLen * sizeof(WCHAR); + pLsaString->MaximumLength= (USHORT)(dwLen+1) * sizeof(WCHAR); + + return TRUE; +} + +PLSA_TRANSLATED_SID2 GetSIDInformation (LPWSTR AccountName,LSA_HANDLE PolicyHandle) +{ + LSA_UNICODE_STRING lucName; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + PLSA_REFERENCED_DOMAIN_LIST lrdlDomainList; + //LSA_TRUST_INFORMATION myDomain; + NTSTATUS ntsResult; + PWCHAR DomainString = NULL; + + // Initialize an LSA_UNICODE_STRING with the name. + if (!InitLsaString(&lucName, AccountName)) + { + wprintf(L"Failed InitLsaString\n"); + return NULL; + } + + ntsResult = LsaLookupNames2( + PolicyHandle, // handle to a Policy object + 0, + 1, // number of names to look up + &lucName, // pointer to an array of names + &lrdlDomainList, // receives domain information + <sTranslatedSID // receives relative SIDs + ); + if (0 != ntsResult) + { + wprintf(L"Failed LsaLookupNames - %lu \n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + + // Get the domain the account resides in. +// myDomain = lrdlDomainList->Domains[ltsTranslatedSID->DomainIndex]; +// DomainString = (PWCHAR) LocalAlloc(LPTR, myDomain.Name.Length + 1); +// wcsncpy(DomainString, myDomain.Name.Buffer, myDomain.Name.Length); + + // Display the relative Id. +// wprintf(L"Relative Id is %lu in domain %ws.\n", +// ltsTranslatedSID->RelativeId, +// DomainString); + + LsaFreeMemory(lrdlDomainList); + + return ltsTranslatedSID; +} + +BOOL AddPrivileges(PSID AccountSID, LSA_HANDLE PolicyHandle, BOOL bAdd) +{ + LSA_UNICODE_STRING lucPrivilege; + NTSTATUS ntsResult; + + // Create an LSA_UNICODE_STRING for the privilege name(s). + if (!InitLsaString(&lucPrivilege, L"SeLockMemoryPrivilege")) + { + wprintf(L"Failed InitLsaString\n"); + return FALSE; + } + + if( bAdd ) { + ntsResult = LsaAddAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID. + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + } + else { + ntsResult = LsaRemoveAccountRights( + PolicyHandle, // An open policy handle. + AccountSID, // The target SID + FALSE, + &lucPrivilege, // The privilege(s). + 1 // Number of privileges. + ); + } + + if (ntsResult == 0) + { + wprintf(L"Privilege added.\n"); + } + else + { + int err = LsaNtStatusToWinError(ntsResult); + char str[255]; + _snprintf(str, 255, "Privilege was not added - %lu \n", LsaNtStatusToWinError(ntsResult)); + MessageBox(NULL, str, "Privilege error", MB_OK); + return FALSE; + } + + return TRUE; +} + +#define TARGET_SYSTEM_NAME L"mysystem" +LSA_HANDLE GetPolicyHandle() +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR SystemName[] = TARGET_SYSTEM_NAME; + USHORT SystemNameLength; + LSA_UNICODE_STRING lusSystemName; + NTSTATUS ntsResult; + LSA_HANDLE lsahPolicyHandle; + + // Object attributes are reserved, so initialize to zeroes. + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + //Initialize an LSA_UNICODE_STRING to the server name. + SystemNameLength = wcslen(SystemName); + lusSystemName.Buffer = SystemName; + lusSystemName.Length = SystemNameLength * sizeof(WCHAR); + lusSystemName.MaximumLength = (SystemNameLength+1) * sizeof(WCHAR); + + // Get a handle to the Policy object. + ntsResult = LsaOpenPolicy( + NULL, //Name of the target system. + &ObjectAttributes, //Object attributes. + POLICY_ALL_ACCESS, //Desired access permissions. + &lsahPolicyHandle //Receives the policy handle. + ); + + if (ntsResult != 0) + { + // An error occurred. Display it as a win32 error code. + wprintf(L"OpenPolicy returned %lu\n", + LsaNtStatusToWinError(ntsResult)); + return NULL; + } + return lsahPolicyHandle; +} + + +/***************************************************************** + LoggedSetLockPagesPrivilege: a function to obtain, if possible, or + release the privilege of locking physical pages. + + Inputs: + + HANDLE hProcess: Handle for the process for which the + privilege is needed + + BOOL bEnable: Enable (TRUE) or disable? + + Return value: TRUE indicates success, FALSE failure. + +*****************************************************************/ +BOOL SysLoggedSetLockPagesPrivilege ( HANDLE hProcess, BOOL bEnable) +{ + struct { + u32 Count; + LUID_AND_ATTRIBUTES Privilege [1]; + } Info; + + HANDLE Token; + BOOL Result; + + // Open the token. + + Result = OpenProcessToken ( hProcess, + TOKEN_ADJUST_PRIVILEGES, + & Token); + + if( Result != TRUE ) { + SysPrintf( "Cannot open process token.\n" ); + return FALSE; + } + + // Enable or disable? + + Info.Count = 1; + if( bEnable ) + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + } + else + { + Info.Privilege[0].Attributes = SE_PRIVILEGE_REMOVED; + } + + // Get the LUID. + Result = LookupPrivilegeValue ( NULL, + SE_LOCK_MEMORY_NAME, + &(Info.Privilege[0].Luid)); + + if( Result != TRUE ) + { + SysPrintf( "Cannot get privilege value for %s.\n", SE_LOCK_MEMORY_NAME ); + return FALSE; + } + + // Adjust the privilege. + + Result = AdjustTokenPrivileges ( Token, FALSE, + (PTOKEN_PRIVILEGES) &Info, + 0, NULL, NULL); + + // Check the result. + if( Result != TRUE ) + { + SysPrintf ("Cannot adjust token privileges, error %u.\n", GetLastError() ); + return FALSE; + } + else + { + if( GetLastError() != ERROR_SUCCESS ) + { + + BOOL bSuc = FALSE; + LSA_HANDLE policy; + PLSA_TRANSLATED_SID2 ltsTranslatedSID; + +// if( !DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_USERNAME), gApp.hWnd, (DLGPROC)UserNameProc) ) +// return FALSE; + DWORD len = sizeof(s_szUserName); + GetUserNameW(s_szUserName, &len); + + policy = GetPolicyHandle(); + + if( policy != NULL ) { + + ltsTranslatedSID = GetSIDInformation(s_szUserName, policy); + + if( ltsTranslatedSID != NULL ) { + bSuc = AddPrivileges(ltsTranslatedSID->Sid, policy, bEnable); + LsaFreeMemory(ltsTranslatedSID); + } + + LsaClose(policy); + } + + if( bSuc ) { + // Get the LUID. + LookupPrivilegeValue ( NULL, SE_LOCK_MEMORY_NAME, &(Info.Privilege[0].Luid)); + + bSuc = AdjustTokenPrivileges ( Token, FALSE, (PTOKEN_PRIVILEGES) &Info, 0, NULL, NULL); + } + + if( bSuc ) { + if( MessageBox(NULL, "PCSX2 just changed your SE_LOCK_MEMORY privilege in order to gain access to physical memory.\n" + "Log off/on and run pcsx2 again. Do you want to log off?\n", + "Privilege changed query", MB_YESNO) == IDYES ) { + ExitWindows(EWX_LOGOFF, 0); + } + } + else { + MessageBox(NULL, "Failed adding SE_LOCK_MEMORY privilege, please check the local policy.\n" + "Go to security settings->Local Policies->User Rights. There should be a \"Lock pages in memory\".\n" + "Add your user to that and log off/on. This enables pcsx2 to run at real-time by allocating physical memory.\n" + "Also can try Control Panel->Local Security Policy->... (this does not work on Windows XP Home)\n" + "(zerofrog)\n", "Virtual Memory Access Denied", MB_OK); + return FALSE; + } + } + } + + CloseHandle( Token ); + + return TRUE; +} + +static u32 s_dwPageSize = 0; +int SysPhysicalAlloc(u32 size, PSMEMORYBLOCK* pblock) +{ +//#ifdef WIN32_FILE_MAPPING +// assert(0); +//#endif + ULONG_PTR NumberOfPagesInitial; // initial number of pages requested + int PFNArraySize; // memory to request for PFN array + BOOL bResult; + + assert( pblock != NULL ); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); + + if( s_dwPageSize == 0 ) { + SYSTEM_INFO sSysInfo; // useful system information + GetSystemInfo(&sSysInfo); // fill the system information structure + s_dwPageSize = sSysInfo.dwPageSize; + + if( s_dwPageSize != 0x1000 ) { + SysMessage("Error! OS page size must be 4Kb!\n" + "If for some reason the OS cannot have 4Kb pages, then run the TLB build."); + return -1; + } + } + + // Calculate the number of pages of memory to request. + pblock->NumberPages = (size+s_dwPageSize-1)/s_dwPageSize; + PFNArraySize = pblock->NumberPages * sizeof (ULONG_PTR); + + pblock->aPFNs = (ULONG_PTR *) HeapAlloc (GetProcessHeap (), 0, PFNArraySize); + + if (pblock->aPFNs == NULL) { + SysPrintf("Failed to allocate on heap.\n"); + goto eCleanupAndExit; + } + + // Allocate the physical memory. + NumberOfPagesInitial = pblock->NumberPages; + bResult = AllocateUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( bResult != TRUE ) + { + SysPrintf("Cannot allocate physical pages, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + if( NumberOfPagesInitial != pblock->NumberPages ) + { + SysPrintf("Allocated only %p of %p pages.\n", pblock->NumberPages, NumberOfPagesInitial ); + goto eCleanupAndExit; + } + + pblock->aVFNs = (ULONG_PTR*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); + + return 0; + +eCleanupAndExit: + SysPhysicalFree(pblock); + return -1; +} + +void SysPhysicalFree(PSMEMORYBLOCK* pblock) +{ + assert( pblock != NULL ); + + // Free the physical pages. + FreeUserPhysicalPages( GetCurrentProcess(), &pblock->NumberPages, pblock->aPFNs ); + + if( pblock->aPFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aPFNs); + if( pblock->aVFNs != NULL ) HeapFree(GetProcessHeap(), 0, pblock->aVFNs); + memset(pblock, 0, sizeof(PSMEMORYBLOCK)); +} + +int SysVirtualPhyAlloc(void* base, u32 size, PSMEMORYBLOCK* pblock) +{ + BOOL bResult; + int i; + + LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE ); + if( lpMemReserved == NULL || base != lpMemReserved ) + { + SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); + goto eCleanupAndExit; + } + + // Map the physical memory into the window. + bResult = MapUserPhysicalPages( base, pblock->NumberPages, pblock->aPFNs ); + + for(i = 0; i < pblock->NumberPages; ++i) + pblock->aVFNs[i] = (ULONG_PTR)base + 0x1000*i; + + if( bResult != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to map, error %u.\n", GetLastError() ); + goto eCleanupAndExit; + } + + return 0; + +eCleanupAndExit: + SysVirtualFree(base, size); + return -1; +} + +void SysVirtualFree(void* lpMemReserved, u32 size) +{ + // unmap + if( MapUserPhysicalPages( lpMemReserved, (size+s_dwPageSize-1)/s_dwPageSize, NULL ) != TRUE ) + { + SysPrintf("MapUserPhysicalPages failed to unmap, error %u.\n", GetLastError() ); + return; + } + + // Free virtual memory. + VirtualFree( lpMemReserved, 0, MEM_RELEASE ); +} + +int SysMapUserPhysicalPages(void* Addr, uptr NumPages, uptr* pfn, int pageoffset) +{ + BOOL bResult = MapUserPhysicalPages(Addr, NumPages, pfn+pageoffset); + +#ifdef _DEBUG + //if( !bResult ) + //__Log("Failed to map user pages: 0x%x:0x%x, error = %d\n", Addr, NumPages, GetLastError()); +#endif + + return bResult; +} + +#else + +#endif diff --git a/pcsx2/windows/afxresmw.h b/pcsx2/windows/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/pcsx2/windows/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/pcsx2/windows/cheats/browser.cpp b/pcsx2/windows/cheats/browser.cpp new file mode 100644 index 0000000..c031f8e --- /dev/null +++ b/pcsx2/windows/cheats/browser.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include +#include + +using namespace std; + +#include "../cheatscpp.h" + +extern "C" { +#include "windows/resource.h" +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "Memory.h" + +#include "cheats.h" +#include "../../patch.h" +} + +HWND hWndBrowser; + +HTREEITEM AddTreeItem(HWND treeview, HTREEITEM parent, const char *name, LPARAM lp) +{ + TVINSERTSTRUCT node={ + parent, + 0, + { + TVIF_TEXT, + NULL, + TVIS_EXPANDED, + TVIS_EXPANDED, + const_cast(name), + 0, + 0, + 0, + 0, + lp, + 1 + } + }; + + return TreeView_InsertItem(treeview,&node); +} + +HTREEITEM AddGroups(HWND treeview, HTREEITEM parent, int parentIndex) +{ + HTREEITEM p=NULL; + for(unsigned int i=0;i0) + { + AddTreeItem(treeview,p,patches[j].title.c_str(),0x01000000|j); + } + } + } + } + } + return p; +} + +BOOL CALLBACK BrowserProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + int wmId,wmEvent; + + switch(uMsg) + { + + case WM_PAINT: + return FALSE; + case WM_INITDIALOG: + hWndBrowser=hWnd; + { + //Add groups to the Treeview + HTREEITEM root=AddGroups(GetDlgItem(hWnd,IDC_GROUPS),0, -1); + TreeView_SetItemState(GetDlgItem(hWnd,IDC_GROUPS),root,TVIS_EXPANDED|TVIS_EXPANDEDONCE|TVIS_EXPANDPARTIAL|TVIS_BOLD,0x00F0); + } + break; + + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDOK: + EndDialog(hWnd,1); + break; + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void ShowCheats(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_CHEATS),hParent,(DLGPROC)BrowserProc,1); +} diff --git a/pcsx2/windows/cheats/cheats.cpp b/pcsx2/windows/cheats/cheats.cpp new file mode 100644 index 0000000..86ae108 --- /dev/null +++ b/pcsx2/windows/cheats/cheats.cpp @@ -0,0 +1,600 @@ +#include +#include +#include +#include + +#include + +extern "C" { +#include "windows/resource.h" +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "Memory.h" + +#include "cheats.h" +#include "../../patch.h" +} + +class result +{ +public: + u32 address; + result(u32 addr): + address(addr) + { + } +}; + +char *sizenames[4]={"char","short","word","double"}; + +char mtext[100]; + +HINSTANCE pInstance; + +int TSelect; + +bool Unsigned; +int Source; +int Compare; +int Size; +int CompareTo; + +u64 CompareValue; + +std::vector results; + +//int mresults; + +bool FirstSearch; + +bool FirstShow; + +char olds[0x02000000]; + +char tn[100]; +char to[100]; +char tv[100]; + +#ifdef PCSX2_VIRTUAL_MEM +u8 *mptr[2]={PS2MEM_BASE,PS2MEM_PSX}; +#else +char *mptr[2]; +extern "C" extern s8 *psxM; +#endif + +int msize[2]={0x02000000,0x00200000}; + +int lticks; + +HWND hWndFinder; + +LVCOLUMN cols[3]={ + {LVCF_TEXT|LVCF_WIDTH,0,60,"Address",0,0,0}, + {LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM,0,60,"Old V",1,0,0}, + {LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM,0,60,"New V",2,0,0} +}; + +LVITEM item[3]={ + {LVIF_TEXT|LVIF_STATE,0,0,0,0,tn,0,0,0,0}, + {LVIF_TEXT|LVIF_STATE,0,1,0,0,to,0,0,0,0}, + {LVIF_TEXT|LVIF_STATE,0,2,0,0,tv,0,0,0,0} +}; + +void DoEvents() +{ + MSG msg; + while(PeekMessage(&msg,0,0,0,PM_REMOVE)!=0) + DispatchMessage(&msg); +} + +void UpdateStatus() +{ + int nticks=GetTickCount(); + if((nticks-lticks)>250) + { + int nshown=ListView_GetItemCount(GetDlgItem(hWndFinder,IDC_RESULTS)); + sprintf(mtext,"%d matches found (%d shown).",results.size(),nshown); + SetWindowText(GetDlgItem(hWndFinder,IDC_MATCHES),mtext); + lticks=nticks; + DoEvents(); + } +} + +void SearchReset() +{ + memcpy(olds,mptr[Source],msize[Source]); + FirstSearch=true; + + results.clear(); + +} + +int AddResult(u32 addr) +{ + result nr=result(addr); + results.push_back(nr); + return 1; +} + +bool CompareAny(u64 val,u64 cto) +{ + + if(Unsigned) + { + switch(Size) + { + case 0: + val=(u8)val; + cto=(u8)cto; + break; + case 1: + val=(u16)val; + cto=(u16)cto; + break; + case 2: + val=(u32)val; + cto=(u32)cto; + break; + case 3: + break; + default:return false; + } + switch(Compare) + { + case 0: /* EQ */ + return val==cto; + case 1: /* GT */ + return val> cto; + case 2: /* LT */ + return val< cto; + case 3: /* GE */ + return val>=cto; + case 4: /* LE */ + return val<=cto; + default:/* NE */ + return val!=cto; + } + } + else + { + switch(Size) + { + case 0: + val=(s8)val; + cto=(s8)cto; + break; + case 1: + val=(s16)val; + cto=(s16)cto; + break; + case 2: + val=(s32)val; + cto=(s32)cto; + break; + case 3: + break; + default:return false; + } + switch(Compare) + { + case 0: /* EQ */ + return (s64)val==(s64)cto; + case 1: /* GT */ + return (s64)val> (s64)cto; + case 2: /* LT */ + return (s64)val< (s64)cto; + case 3: /* GE */ + return (s64)val>=(s64)cto; + case 4: /* LE */ + return (s64)val<=(s64)cto; + default:/* NE */ + return (s64)val!=(s64)cto; + } + } +} + +void SearchFirst() +{ + int MSize=1< oldr=std::vector(results); + + results.clear(); + + for(i=0;i", + Source?"IOP":"EE", + tn, + sizenames[Size]); + + SetWindowText(GetDlgItem(hWnd,IDC_ADDR),tn); + SetWindowText(GetDlgItem(hWnd,IDC_VALUE),tv); + SetWindowText(GetDlgItem(hWnd,IDC_NAME),to); + + break; + } + } + + + break; + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDOK: + GetWindowText(GetDlgItem(hWnd,IDC_VALUE),tv,100); + value=_atoi64(tv); + AddPatch(1,Source+1,results[Selected].address,Size+1,value); + + EndDialog(hWnd,1); + break; + + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void AddCheat(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR retret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ADD),hParent,(DLGPROC)AddCheatProc,(LPARAM)hParent); +} + +void AddResults(HWND hWnd) +{ + int i,mresults; + u64 sizemask=(1<<(1<32768) { + mresults=32768; + } + + ListView_DeleteAllItems(GetDlgItem(hWnd,IDC_RESULTS)); + + for(i=0;i32768) { + sprintf(mtext,"%d matches found (32768 shown).",results.size()); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),mtext); + } + else { + sprintf(mtext,"%d matches found.",results.size()); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),mtext); + } + +} + +BOOL CALLBACK FinderProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + int wmId,wmEvent; + LRESULT lStyle; + + switch(uMsg) + { + + case WM_PAINT: + INIT_CHECK(IDC_UNSIGNED,Unsigned); + return FALSE; + case WM_INITDIALOG: + +#ifndef PCSX2_VIRTUAL_MEM + mptr[0]=(char*)psM; + mptr[1]=psxM; +#endif + + + hWndFinder=hWnd; + + ENABLE_CONTROL(IDC_VALUE,false); + + GROUP_INIT(IDC_EE,Source); + GROUP_SELECT(IDC_EE); + GROUP_SELECT(IDC_IOP); + + GROUP_INIT(IDC_OLD,CompareTo); + GROUP_SELECT(IDC_OLD); + GROUP_SELECT(IDC_SET); + ENABLE_CONTROL(IDC_VALUE,(CompareTo!=0)); + + GROUP_INIT(IDC_EQ,Compare); + GROUP_SELECT(IDC_EQ); + GROUP_SELECT(IDC_GT); + GROUP_SELECT(IDC_LT); + GROUP_SELECT(IDC_GE); + GROUP_SELECT(IDC_LE); + GROUP_SELECT(IDC_NE); + + GROUP_INIT(IDC_8B,Size); + GROUP_SELECT(IDC_8B); + GROUP_SELECT(IDC_16B); + GROUP_SELECT(IDC_32B); + GROUP_SELECT(IDC_64B); + + INIT_CHECK(IDC_UNSIGNED,Unsigned); + + //Listview Init + lStyle = SendMessage(GetDlgItem(hWnd,IDC_RESULTS), LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); + SendMessage(GetDlgItem(hWnd,IDC_RESULTS), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lStyle | LVS_EX_FULLROWSELECT); + + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),0,&cols[0]); + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),1,&cols[1]); + ListView_InsertColumn(GetDlgItem(hWnd,IDC_RESULTS),2,&cols[2]); + + if(FirstShow) + { + SearchReset(); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),"ready to search."); + FirstShow=false; + } + else { + AddResults(hWnd); + } + + break; + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDCANCEL: + EndDialog(hWnd,1); + break; + + case IDC_ADD: + AddCheat(pInstance,hWnd); + break; + + case IDC_RESET: + ENABLE_CONTROL(IDC_EE, true); + ENABLE_CONTROL(IDC_IOP, true); + ENABLE_CONTROL(IDC_LRESULTS,true); + ENABLE_CONTROL(IDC_STATUS, true); + ENABLE_CONTROL(IDC_UNSIGNED,true); + ENABLE_CONTROL(IDC_8B, true); + ENABLE_CONTROL(IDC_16B, true); + ENABLE_CONTROL(IDC_32B, true); + ENABLE_CONTROL(IDC_64B, true); + SetWindowText(GetDlgItem(hWnd,IDC_MATCHES),"ready to search."); + SearchReset(); + ListView_DeleteAllItems(GetDlgItem(hWnd,IDC_RESULTS)); + break; + + case IDC_SEARCH: + GetWindowText(GetDlgItem(hWnd,IDC_VALUE),mtext,100); + CompareValue=atoi(mtext); + ENABLE_CONTROL(IDC_SEARCH, false); + ENABLE_CONTROL(IDC_RESET, false); + ENABLE_CONTROL(IDC_ADD, false); + ENABLE_CONTROL(IDCANCEL, false); + if(FirstSearch) { + ENABLE_CONTROL(IDC_EE, false); + ENABLE_CONTROL(IDC_IOP, false); + ENABLE_CONTROL(IDC_LRESULTS,false); + ENABLE_CONTROL(IDC_STATUS, false); + ENABLE_CONTROL(IDC_UNSIGNED,false); + ENABLE_CONTROL(IDC_8B, false); + ENABLE_CONTROL(IDC_16B, false); + ENABLE_CONTROL(IDC_32B, false); + ENABLE_CONTROL(IDC_64B, false); + SearchFirst(); + } + else SearchMore(); + + AddResults(hWnd); + + memcpy(olds,mptr[Source],msize[Source]); + + ENABLE_CONTROL(IDC_SEARCH, true); + ENABLE_CONTROL(IDC_RESET, true); + ENABLE_CONTROL(IDC_ADD, true); + ENABLE_CONTROL(IDCANCEL, true); + + break; + + HANDLE_CHECK(IDC_UNSIGNED,Unsigned); + + HANDLE_GROUP_ITEM(IDC_EE); + HANDLE_GROUP_ITEM(IDC_IOP); + BEGIN_GROUP_HANDLER(IDC_EE,Source); + GROUP_SELECT(IDC_EE); + GROUP_SELECT(IDC_IOP); + break; + + HANDLE_GROUP_ITEM(IDC_OLD); + HANDLE_GROUP_ITEM(IDC_SET); + BEGIN_GROUP_HANDLER(IDC_OLD,CompareTo); + GROUP_SELECT(IDC_OLD); + GROUP_SELECT(IDC_SET); + ENABLE_CONTROL(IDC_VALUE,(CompareTo!=0)); + break; + + HANDLE_GROUP_ITEM(IDC_EQ); + HANDLE_GROUP_ITEM(IDC_GT); + HANDLE_GROUP_ITEM(IDC_LT); + HANDLE_GROUP_ITEM(IDC_GE); + HANDLE_GROUP_ITEM(IDC_LE); + HANDLE_GROUP_ITEM(IDC_NE); + BEGIN_GROUP_HANDLER(IDC_EQ,Compare); + GROUP_SELECT(IDC_EQ); + GROUP_SELECT(IDC_GT); + GROUP_SELECT(IDC_LT); + GROUP_SELECT(IDC_GE); + GROUP_SELECT(IDC_LE); + GROUP_SELECT(IDC_NE); + break; + + HANDLE_GROUP_ITEM(IDC_8B); + HANDLE_GROUP_ITEM(IDC_16B); + HANDLE_GROUP_ITEM(IDC_32B); + HANDLE_GROUP_ITEM(IDC_64B); + BEGIN_GROUP_HANDLER(IDC_8B,Size); + GROUP_SELECT(IDC_8B); + GROUP_SELECT(IDC_16B); + GROUP_SELECT(IDC_32B); + GROUP_SELECT(IDC_64B); + break; + + default: + return FALSE; + } + break; + default: + return FALSE; + } + return TRUE; +} + +void ShowFinder(HINSTANCE hInstance, HWND hParent) +{ + INT_PTR ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_FINDER),hParent,(DLGPROC)FinderProc,1); +} diff --git a/pcsx2/windows/cheats/cheats.h b/pcsx2/windows/cheats/cheats.h new file mode 100644 index 0000000..e4242da --- /dev/null +++ b/pcsx2/windows/cheats/cheats.h @@ -0,0 +1,19 @@ +#ifndef CHEATS_H_INCLUDED +#define CHEATS_H_INCLUDED + +#ifndef __cplusplus +typedef enum ebool +{ + false, + true +} bool; +#endif + +extern HINSTANCE pInstance; +extern bool FirstShow; + +void AddCheat(HINSTANCE hInstance, HWND hParent); +void ShowFinder(HINSTANCE hInstance, HWND hParent); +void ShowCheats(HINSTANCE hInstance, HWND hParent); + +#endif//CHEATS_H_INCLUDED diff --git a/pcsx2/windows/ini.c b/pcsx2/windows/ini.c new file mode 100644 index 0000000..d5c949a --- /dev/null +++ b/pcsx2/windows/ini.c @@ -0,0 +1,173 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* +15-09-2004 : file rewriten for work with inis (shadow) +*/ + +#include +#include +#include +#include "Common.h" +#include "win32.h" +#include + +int LoadConfig() { + FILE *fp; + +#ifdef ENABLE_NLS + char text[256]; + extern int _nl_msg_cat_cntr; +#endif + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return -1; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + fp=fopen("inis\\pcsx2.ini","rt");//check if pcsx2.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + return -1; + } + fclose(fp); + //interface + GetPrivateProfileString("Interface", "Bios", NULL, szValue, 256, szIniFile); + strcpy(Conf->Bios, szValue); + GetPrivateProfileString("Interface", "Lang", NULL, szValue, 256, szIniFile); + strcpy(Conf->Lang, szValue); + GetPrivateProfileString("Interface", "Ps2Out", NULL, szValue, 20, szIniFile); + Conf->PsxOut = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "ThPriority", NULL, szValue, 20, szIniFile); + Conf->ThPriority = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Interface", "PluginsDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->PluginsDir, szValue); + GetPrivateProfileString("Interface", "BiosDir", NULL, szValue, 256, szIniFile); + strcpy(Conf->BiosDir, szValue); + GetPrivateProfileString("Interface", "Mcd1", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd1, szValue); + GetPrivateProfileString("Interface", "Mcd2", NULL, szValue, 256, szIniFile); + strcpy(Conf->Mcd2, szValue); + //plugins + GetPrivateProfileString("Plugins", "GS", NULL, szValue, 256, szIniFile); + strcpy(Conf->GS, szValue); + GetPrivateProfileString("Plugins", "SPU2", NULL, szValue, 256, szIniFile); + strcpy(Conf->SPU2, szValue); + GetPrivateProfileString("Plugins", "CDVD", NULL, szValue, 256, szIniFile); + strcpy(Conf->CDVD, szValue); + GetPrivateProfileString("Plugins", "PAD1", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD1, szValue); + GetPrivateProfileString("Plugins", "PAD2", NULL, szValue, 256, szIniFile); + strcpy(Conf->PAD2, szValue); + GetPrivateProfileString("Plugins", "DEV9", NULL, szValue, 256, szIniFile); + strcpy(Conf->DEV9, szValue); + GetPrivateProfileString("Plugins", "USB", NULL, szValue, 256, szIniFile); + strcpy(Conf->USB, szValue); + GetPrivateProfileString("Plugins", "FW", NULL, szValue, 256, szIniFile); + strcpy(Conf->FW, szValue); + //cpu + GetPrivateProfileString("Cpu Options", "Options", NULL, szValue, 20, szIniFile); + Conf->Options= (u32)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Cpu Options", "SafeCnts", NULL, szValue, 20, szIniFile); + Conf->SafeCnts = strtoul(szValue, NULL, 0); + + //Misc + GetPrivateProfileString("Misc", "Patch", NULL, szValue, 20, szIniFile); + Conf->Patch = strtoul(szValue, NULL, 10); + +#ifdef PCSX2_DEVBUILD + GetPrivateProfileString("Misc", "varLog", NULL, szValue, 20, szIniFile); + varLog = strtoul(szValue, NULL, 16); +#endif + +#ifdef ENABLE_NLS + sprintf(text, "LANGUAGE=%s", Conf->Lang); +#ifdef _WIN32 + gettext_putenv(text); +#else + putenv(text); +#endif +#endif + + return 0; +} + +///////////////////////////////////////////////////////// + +void SaveConfig() { + + PcsxConfig *Conf = &Config; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)gApp.hInstance), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\pcsx2.ini"); + //interface + sprintf(szValue,"%s",Conf->Bios); + WritePrivateProfileString("Interface","Bios",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Lang); + WritePrivateProfileString("Interface","Lang",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PluginsDir); + WritePrivateProfileString("Interface","PluginsDir",szValue,szIniFile); + sprintf(szValue,"%s",Conf->BiosDir); + WritePrivateProfileString("Interface","BiosDir",szValue,szIniFile); + sprintf(szValue,"%u",Conf->PsxOut); + WritePrivateProfileString("Interface","Ps2Out",szValue,szIniFile); + sprintf(szValue,"%u",Conf->ThPriority); + WritePrivateProfileString("Interface","ThPriority",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd1); + WritePrivateProfileString("Interface","Mcd1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->Mcd2); + WritePrivateProfileString("Interface","Mcd2",szValue,szIniFile); + //plugins + sprintf(szValue,"%s",Conf->GS); + WritePrivateProfileString("Plugins","GS",szValue,szIniFile); + sprintf(szValue,"%s",Conf->SPU2); + WritePrivateProfileString("Plugins","SPU2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->CDVD); + WritePrivateProfileString("Plugins","CDVD",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD1); + WritePrivateProfileString("Plugins","PAD1",szValue,szIniFile); + sprintf(szValue,"%s",Conf->PAD2); + WritePrivateProfileString("Plugins","PAD2",szValue,szIniFile); + sprintf(szValue,"%s",Conf->DEV9); + WritePrivateProfileString("Plugins","DEV9",szValue,szIniFile); + sprintf(szValue,"%s",Conf->USB); + WritePrivateProfileString("Plugins","USB",szValue,szIniFile); + sprintf(szValue,"%s",Conf->FW); + WritePrivateProfileString("Plugins","FW",szValue,szIniFile); + //cpu + sprintf(szValue,"%u", Conf->Options); + WritePrivateProfileString("Cpu Options","Options",szValue,szIniFile); + sprintf(szValue,"%u",Conf->SafeCnts); + WritePrivateProfileString("Cpu Options","SafeCnts",szValue,szIniFile); + //Misc + sprintf(szValue,"%u",Conf->Patch); + WritePrivateProfileString("Misc","Patch",szValue,szIniFile); + sprintf(szValue,"%x",varLog); + WritePrivateProfileString("Misc","varLog",szValue,szIniFile); + + +} + diff --git a/pcsx2/windows/libs/gnu_gettext.lib b/pcsx2/windows/libs/gnu_gettext.lib new file mode 100644 index 0000000000000000000000000000000000000000..8b3885a56b2f9d31a261c89fbd0e31d15fc51c14 GIT binary patch literal 2916 zcmcIm%}*0S6#s1t6sieCjfr2dB!s{PNNJ%MHH)HwP(D)1#miW_1)4xhuow>{UOD)e zcr=_1C;tEshIsPefwS?z4d2_H*-nSjr35CKop~QSZ{GX8H#7au^1Fr27x7WMzD=dm zQxlV^#6&&Y9+UL=cv8;Z#Q}5!(LtcY0b=_==ds_rW&y7s(nvktEBgVB+)ud+F}JY1 zl+B5m*DJ5GbIZA9XHiX1+<#N( zZ&?ITv(`hx2nds~MvAP4(uZe8SYaqbL%!h8^YZlDhcqK+!%qAzB>!0 z!fxe#WxZ+-Wryv|+~T|^H9xnB!GH1!J}xmY;O!pIFa@Vj+1{Z|pY*li>`d8IX!0&2 zP`*2Wx9?5G@w{YPQN>BJ4lxkuq-q@I5Aa7eULANYDIOwtOW!M3^tDz-B9#j6jf@rX zD&w2CN8Tx{Mw#P!qS{BxoN>kF%=w}SIdbOQTt-|5<0rI}3vaKuku{;GN+La}#m+xf zevt(q@y4y7bc;@VHvo2F&Uu}vjpXl;Ja zaLr~cKDBMK#D|gjZZNQeL5E_QR8SiB9+54Mr>I?I#?olnw`A~$tM~08+2M0W1UIE= z%Amu&QpIg}^?J3lK4TO7^Zk!*F$rj%vLVHS>w*CX+ CYG_^n literal 0 HcmV?d00001 diff --git a/pcsx2/windows/libs/libintlmsc.h b/pcsx2/windows/libs/libintlmsc.h new file mode 100644 index 0000000..588e5c8 --- /dev/null +++ b/pcsx2/windows/libs/libintlmsc.h @@ -0,0 +1,116 @@ +/* This file is part of a Windows32 DLL Interface to: + GNU gettext - internationalization aids + Copyright (C) 1996, 1998 Free Software Foundation, Inc. + + This file was written by Franco Bez + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* REPLACEMENT FOR ORIGINAL LIBINTL.H for use with Windows32 */ + +#if !defined(__LIBINTL_H_INCLUDED) +#define __LIBINTL_H_INCLUDED + +#if defined(__cplusplus) +extern "C" { +#endif + +/* See if we allready know what we want static or dll linkage or none at all*/ +#if defined DONT_USE_GETTEXT || ( defined USE_SAFE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) || ( defined USE_GETTEXT_DLL && defined USE_SAFE_GETTEXT_DLL ) || ( defined USE_GETTEXT_DLL && defined USE_GETTEXT_STATIC ) +/* TWO IS HARDLY POSSIBLE */ +#undef USE_GETTEXT_DLL +#undef USE_GETTEXT_STATIC +#undef USE_SAFE_GETTEXT_DLL +#endif /* MORE THAN ONE - OR NONE AT ALL */ + +#if !defined USE_GETTEXT_DLL && !defined USE_SAFE_GETTEXT_DLL && !defined USE_GETTEXT_STATIC && !defined DONT_USE_GETTEXT +/* not explicitly defined so try to guess it - + if GNUC is used - we use static linkage by default + because at the moment this is the only plattform + for which a static lib is available + else we use the DLL built with GNUC */ +# if defined __GNUC__ +# define USE_GETTEXT_STATIC +# else +# define USE_GETTEXT_DLL +# endif /* __GNUC__ */ +#endif /* NONE */ + +/* NOW ONLY ONE OF + DONT_USE_GETTEXT , USE_GETTEXT_DLL , USE_SAFE_GETTEXT_DLL , USE_GETTEXT_STATIC + IS DEFINED */ + +#if defined USE_GETTEXT_DLL +/* exported functions in DLL gnu_gettext.dll + you should link with import library + -lgnu_gettext (for mingw32) OR gnu_gettext.lib (MSVC) */ +__declspec(dllimport) char *gettext(const char *__msgid); +__declspec(dllimport) char *dgettext(const char *__domainname,const char *__msgid); +__declspec(dllimport) char *dcgettext(const char *__domainname,const char *__msgid, int __category); +__declspec(dllimport) char *textdomain(const char *__domainname); +__declspec(dllimport) char *bindtextdomain(const char *__domainname,const char *__dirname); +/* calling _putenv from within the DLL */ +__declspec(dllexport) int gettext_putenv(const char *envstring); +#endif /* DLL */ + +#if defined USE_SAFE_GETTEXT_DLL +/* Uses DLL gnu_gettext.dll ONLY if present, otherwise NO translation will take place + you should link with "safe_gettext_dll.o -lstdc++" see README for safe_gettext_dll for Details */ +/* The safe gettext functions */ +extern char *gettext(const char *szMsgId); +extern char *dgettext(const char *szDomain,const char *szMsgId); +extern char *dcgettext(const char *szDomain,const char *szMsgId,int iCategory); +extern char *textdomain(const char *szDomain); +extern char *bindtextdomain(const char *szDomain,const char *szDirectory); +/* calling _putenv from within the DLL */ +extern int gettext_putenv(const char *envstring); +#endif /* SAFE DLL */ + +#if defined USE_GETTEXT_STATIC +/* exported functions in static library libintl.a + and supporting macros + you should link with -lintl (mingw32) */ +extern char *gettext__(const char *__msgid); +extern char *dgettext__(const char *__domainname,const char *__msgid); +extern char *dcgettext__(const char *__domainname,const char *__msgid, int __category); +extern char *textdomain__(const char *__domainname); +extern char *bindtextdomain__(const char *__domainname,const char *__dirname); +#define gettext(szMsgId) gettext__(szMsgId) +#define dgettext(szDomain,szMsgId) dgettext__(szDomain,szMsgId) +#define dcgettext(szDomain,szMsgId,iCategory) dcgettext__(szDomain,szMsgId,iCategory) +#define textdomain(szDomain) textdomain__(szDomain) +#define bindtextdomain(szDomain,szDirectory) bindtextdomain__(szDomain,szDirectory) +// dummy - for static linkage - calling _putenv from within the DLL +#define gettext_putenv(a) _putenv(a) +#endif /* STATIC */ + +#if defined DONT_USE_GETTEXT +/* DON'T USE GETTEXT AT ALL + MAKROS TO MAKE CODE COMPILE WELL, BUT GETTEXT WILL NOT BE USESD +*/ +# define gettext(Msgid) (Msgid) +# define dgettext(Domainname, Msgid) (Msgid) +# define dcgettext(Domainname, Msgid, Category) (Msgid) +# define textdomain(Domainname) ((char *) Domainname) +# define bindtextdomain(Domainname, Dirname) ((char *) Dirname) +// dummy - for static linkage - calling _putenv from within the DLL +# define gettext_putenv(a) _putenv(a) +#endif /* DON'T USE AT ALL */ + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /*!defined(__LIBINTL_H_INCLUDED)*/ diff --git a/pcsx2/windows/libs/pthread.h b/pcsx2/windows/libs/pthread.h new file mode 100644 index 0000000..a0add29 --- /dev/null +++ b/pcsx2/windows/libs/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,7,0,0 +#define PTW32_VERSION_STRING "2, 7, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/pcsx2/windows/libs/pthreadVC2.lib b/pcsx2/windows/libs/pthreadVC2.lib new file mode 100644 index 0000000000000000000000000000000000000000..b447a8b71ec31903598669991dac05f24ace9f25 GIT binary patch literal 29280 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 literal 0 HcmV?d00001 diff --git a/pcsx2/windows/libs/sched.h b/pcsx2/windows/libs/sched.h new file mode 100644 index 0000000..10ecb5d --- /dev/null +++ b/pcsx2/windows/libs/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/pcsx2/windows/libs/semaphore.h b/pcsx2/windows/libs/semaphore.h new file mode 100644 index 0000000..ea42ce3 --- /dev/null +++ b/pcsx2/windows/libs/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/pcsx2/windows/mingw/Makefile.win b/pcsx2/windows/mingw/Makefile.win new file mode 100644 index 0000000..7449952 --- /dev/null +++ b/pcsx2/windows/mingw/Makefile.win @@ -0,0 +1,348 @@ +# Project: pcsx2 +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//pcsx2_private.res +OBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LINKOBJ = Obj//AboutDlg.o Obj//ConfigDlg.o Obj//CpuDlg.o Obj//Debugger.o Obj//DebugMemory.o Obj//Debugreg.o Obj//ini.o Obj//McdsDlg.o Obj//PatchBrowser.o Obj//RDebugger.o Obj//WinMain.o Obj//Idct.o Obj//IPU.o Obj//Mpeg.o Obj//yuv2rgb.o Obj//cpuopsDebug.o Obj//DisR3000A.o Obj//DisR3000asm.o Obj//DisR5900.o Obj//DisR5900asm.o Obj//DisVU0Micro.o Obj//DisVU1Micro.o Obj//adler32.o Obj//compress.o Obj//crc32.o Obj//deflate.o Obj//gzio.o Obj//infback.o Obj//inffast.o Obj//inflate.o Obj//inftrees.o Obj//trees.o Obj//uncompr.o Obj//zutil.o Obj//iR5900Arit.o Obj//iR5900AritImm.o Obj//iR5900Branch.o Obj//iR5900Jump.o Obj//iR5900LoadStore.o Obj//iR5900Move.o Obj//iR5900MultDiv.o Obj//iR5900Shift.o Obj//iCP0.o Obj//iFPU.o Obj//iMMI.o Obj//iR3000A.o Obj//iR5900.o Obj//iVU0micro.o Obj//iVU1micro.o Obj//iVUmicro.o Obj//recCOP2.o Obj//ix86.o Obj//ix86_3dnow.o Obj//ix86_cpudetect.o Obj//ix86_fpu.o Obj//ix86_mmx.o Obj//ix86_sse.o Obj//CDVD.o Obj//CDVDiso.o Obj//CDVDisodrv.o Obj//COP0.o Obj//Counters.o Obj//Decode_XA.o Obj//Elfheader.o Obj//FiFo.o Obj//FPU.o Obj//GS.o Obj//Gte.o Obj//Hw.o Obj//Interpreter.o Obj//InterTables.o Obj//Mdec.o Obj//Memory.o Obj//Misc.o Obj//MMI.o Obj//Patch.o Obj//Plugins.o Obj//PsxBios.o Obj//PsxCounters.o Obj//PsxDma.o Obj//PsxGPU.o Obj//PsxHw.o Obj//PsxInterpreter.o Obj//PsxMem.o Obj//PsxSio2.o Obj//R3000A.o Obj//R5900.o Obj//Sif.o Obj//Sio.o Obj//SPR.o Obj//Stats.o Obj//Vif.o Obj//VifDma.o Obj//VU0.o Obj//VU0micro.o Obj//VU1micro.o Obj//VUflags.o Obj//VUops.o Obj//Cache.o Obj//CdRom.o Obj//deci2.o Obj//deci2_dbgp.o Obj//deci2_dcmp.o Obj//deci2_iloadp.o Obj//deci2_netmp.o Obj//deci2_ttyp.o $(RES) +LIBS = -mwindows -Wall -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -s +INCS = -I"../../" -I"C:/Documents and Settings/shadow/Desktop/Npcsx2" -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +CXXINCS = -I"../../" -I"../../zlib" -I"../../DebugTools" -I"../../IPU" -I"../../x86" -I"../../ix86-32" -I"../" +BIN = pcsx2.exe +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -D__WIN32__ -D__MINGW32__ -O3 -fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing -m128bit-long-double -mfpmath=sse -march=athlon64 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before pcsx2.exe all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o "pcsx2.exe" $(LIBS) + +Obj//AboutDlg.o: ../AboutDlg.c + $(CC) -c ../AboutDlg.c -o Obj//AboutDlg.o $(CFLAGS) + +Obj//ConfigDlg.o: ../ConfigDlg.c + $(CC) -c ../ConfigDlg.c -o Obj//ConfigDlg.o $(CFLAGS) + +Obj//CpuDlg.o: ../CpuDlg.c + $(CC) -c ../CpuDlg.c -o Obj//CpuDlg.o $(CFLAGS) + +Obj//Debugger.o: ../Debugger.c + $(CC) -c ../Debugger.c -o Obj//Debugger.o $(CFLAGS) + +Obj//DebugMemory.o: ../DebugMemory.c + $(CC) -c ../DebugMemory.c -o Obj//DebugMemory.o $(CFLAGS) + +Obj//Debugreg.o: ../Debugreg.c + $(CC) -c ../Debugreg.c -o Obj//Debugreg.o $(CFLAGS) + +Obj//ini.o: ../ini.c + $(CC) -c ../ini.c -o Obj//ini.o $(CFLAGS) + +Obj//McdsDlg.o: ../McdsDlg.c + $(CC) -c ../McdsDlg.c -o Obj//McdsDlg.o $(CFLAGS) + +Obj//PatchBrowser.o: ../PatchBrowser.c + $(CC) -c ../PatchBrowser.c -o Obj//PatchBrowser.o $(CFLAGS) + +Obj//RDebugger.o: ../RDebugger.c + $(CC) -c ../RDebugger.c -o Obj//RDebugger.o $(CFLAGS) + +Obj//WinMain.o: ../WinMain.c + $(CC) -c ../WinMain.c -o Obj//WinMain.o $(CFLAGS) + +Obj//Idct.o: ../../IPU/Idct.c + $(CC) -c ../../IPU/Idct.c -o Obj//Idct.o $(CFLAGS) + +Obj//IPU.o: ../../IPU/IPU.c + $(CC) -c ../../IPU/IPU.c -o Obj//IPU.o $(CFLAGS) + +Obj//Mpeg.o: ../../IPU/Mpeg.c + $(CC) -c ../../IPU/Mpeg.c -o Obj//Mpeg.o $(CFLAGS) + +Obj//yuv2rgb.o: ../../IPU/yuv2rgb.c + $(CC) -c ../../IPU/yuv2rgb.c -o Obj//yuv2rgb.o $(CFLAGS) + +Obj//cpuopsDebug.o: ../../DebugTools/cpuopsDebug.c + $(CC) -c ../../DebugTools/cpuopsDebug.c -o Obj//cpuopsDebug.o $(CFLAGS) + +Obj//DisR3000A.o: ../../DebugTools/DisR3000A.c + $(CC) -c ../../DebugTools/DisR3000A.c -o Obj//DisR3000A.o $(CFLAGS) + +Obj//DisR3000asm.o: ../../DebugTools/DisR3000asm.c + $(CC) -c ../../DebugTools/DisR3000asm.c -o Obj//DisR3000asm.o $(CFLAGS) + +Obj//DisR5900.o: ../../DebugTools/DisR5900.c + $(CC) -c ../../DebugTools/DisR5900.c -o Obj//DisR5900.o $(CFLAGS) + +Obj//DisR5900asm.o: ../../DebugTools/DisR5900asm.c + $(CC) -c ../../DebugTools/DisR5900asm.c -o Obj//DisR5900asm.o $(CFLAGS) + +Obj//DisVU0Micro.o: ../../DebugTools/DisVU0Micro.c + $(CC) -c ../../DebugTools/DisVU0Micro.c -o Obj//DisVU0Micro.o $(CFLAGS) + +Obj//DisVU1Micro.o: ../../DebugTools/DisVU1Micro.c + $(CC) -c ../../DebugTools/DisVU1Micro.c -o Obj//DisVU1Micro.o $(CFLAGS) + +Obj//adler32.o: ../../zlib/adler32.c + $(CC) -c ../../zlib/adler32.c -o Obj//adler32.o $(CFLAGS) + +Obj//compress.o: ../../zlib/compress.c + $(CC) -c ../../zlib/compress.c -o Obj//compress.o $(CFLAGS) + +Obj//crc32.o: ../../zlib/crc32.c + $(CC) -c ../../zlib/crc32.c -o Obj//crc32.o $(CFLAGS) + +Obj//deflate.o: ../../zlib/deflate.c + $(CC) -c ../../zlib/deflate.c -o Obj//deflate.o $(CFLAGS) + +Obj//gzio.o: ../../zlib/gzio.c + $(CC) -c ../../zlib/gzio.c -o Obj//gzio.o $(CFLAGS) + +Obj//infback.o: ../../zlib/infback.c + $(CC) -c ../../zlib/infback.c -o Obj//infback.o $(CFLAGS) + +Obj//inffast.o: ../../zlib/inffast.c + $(CC) -c ../../zlib/inffast.c -o Obj//inffast.o $(CFLAGS) + +Obj//inflate.o: ../../zlib/inflate.c + $(CC) -c ../../zlib/inflate.c -o Obj//inflate.o $(CFLAGS) + +Obj//inftrees.o: ../../zlib/inftrees.c + $(CC) -c ../../zlib/inftrees.c -o Obj//inftrees.o $(CFLAGS) + +Obj//trees.o: ../../zlib/trees.c + $(CC) -c ../../zlib/trees.c -o Obj//trees.o $(CFLAGS) + +Obj//uncompr.o: ../../zlib/uncompr.c + $(CC) -c ../../zlib/uncompr.c -o Obj//uncompr.o $(CFLAGS) + +Obj//zutil.o: ../../zlib/zutil.c + $(CC) -c ../../zlib/zutil.c -o Obj//zutil.o $(CFLAGS) + +Obj//iR5900Arit.o: ../../ix86-32/iR5900Arit.c + $(CC) -c ../../ix86-32/iR5900Arit.c -o Obj//iR5900Arit.o $(CFLAGS) + +Obj//iR5900AritImm.o: ../../ix86-32/iR5900AritImm.c + $(CC) -c ../../ix86-32/iR5900AritImm.c -o Obj//iR5900AritImm.o $(CFLAGS) + +Obj//iR5900Branch.o: ../../ix86-32/iR5900Branch.c + $(CC) -c ../../ix86-32/iR5900Branch.c -o Obj//iR5900Branch.o $(CFLAGS) + +Obj//iR5900Jump.o: ../../ix86-32/iR5900Jump.c + $(CC) -c ../../ix86-32/iR5900Jump.c -o Obj//iR5900Jump.o $(CFLAGS) + +Obj//iR5900LoadStore.o: ../../ix86-32/iR5900LoadStore.c + $(CC) -c ../../ix86-32/iR5900LoadStore.c -o Obj//iR5900LoadStore.o $(CFLAGS) + +Obj//iR5900Move.o: ../../ix86-32/iR5900Move.c + $(CC) -c ../../ix86-32/iR5900Move.c -o Obj//iR5900Move.o $(CFLAGS) + +Obj//iR5900MultDiv.o: ../../ix86-32/iR5900MultDiv.c + $(CC) -c ../../ix86-32/iR5900MultDiv.c -o Obj//iR5900MultDiv.o $(CFLAGS) + +Obj//iR5900Shift.o: ../../ix86-32/iR5900Shift.c + $(CC) -c ../../ix86-32/iR5900Shift.c -o Obj//iR5900Shift.o $(CFLAGS) + +Obj//iCP0.o: ../../x86/iCP0.c + $(CC) -c ../../x86/iCP0.c -o Obj//iCP0.o $(CFLAGS) + +Obj//iFPU.o: ../../x86/iFPU.c + $(CC) -c ../../x86/iFPU.c -o Obj//iFPU.o $(CFLAGS) + +Obj//iMMI.o: ../../x86/iMMI.c + $(CC) -c ../../x86/iMMI.c -o Obj//iMMI.o $(CFLAGS) + +Obj//iR3000A.o: ../../x86/iR3000A.c + $(CC) -c ../../x86/iR3000A.c -o Obj//iR3000A.o $(CFLAGS) + +Obj//iR5900.o: ../../x86/iR5900.c + $(CC) -c ../../x86/iR5900.c -o Obj//iR5900.o $(CFLAGS) + +Obj//iVU0micro.o: ../../x86/iVU0micro.c + $(CC) -c ../../x86/iVU0micro.c -o Obj//iVU0micro.o $(CFLAGS) + +Obj//iVU1micro.o: ../../x86/iVU1micro.c + $(CC) -c ../../x86/iVU1micro.c -o Obj//iVU1micro.o $(CFLAGS) + +Obj//iVUmicro.o: ../../x86/iVUmicro.c + $(CC) -c ../../x86/iVUmicro.c -o Obj//iVUmicro.o $(CFLAGS) + +Obj//recCOP2.o: ../../x86/recCOP2.c + $(CC) -c ../../x86/recCOP2.c -o Obj//recCOP2.o $(CFLAGS) + +Obj//ix86.o: ../../x86/ix86/ix86.c + $(CC) -c ../../x86/ix86/ix86.c -o Obj//ix86.o $(CFLAGS) + +Obj//ix86_3dnow.o: ../../x86/ix86/ix86_3dnow.c + $(CC) -c ../../x86/ix86/ix86_3dnow.c -o Obj//ix86_3dnow.o $(CFLAGS) + +Obj//ix86_cpudetect.o: ../../x86/ix86/ix86_cpudetect.c + $(CC) -c ../../x86/ix86/ix86_cpudetect.c -o Obj//ix86_cpudetect.o $(CFLAGS) + +Obj//ix86_fpu.o: ../../x86/ix86/ix86_fpu.c + $(CC) -c ../../x86/ix86/ix86_fpu.c -o Obj//ix86_fpu.o $(CFLAGS) + +Obj//ix86_mmx.o: ../../x86/ix86/ix86_mmx.c + $(CC) -c ../../x86/ix86/ix86_mmx.c -o Obj//ix86_mmx.o $(CFLAGS) + +Obj//ix86_sse.o: ../../x86/ix86/ix86_sse.c + $(CC) -c ../../x86/ix86/ix86_sse.c -o Obj//ix86_sse.o $(CFLAGS) + +Obj//CDVD.o: ../../CDVD.c + $(CC) -c ../../CDVD.c -o Obj//CDVD.o $(CFLAGS) + +Obj//CDVDiso.o: ../../CDVDiso.c + $(CC) -c ../../CDVDiso.c -o Obj//CDVDiso.o $(CFLAGS) + +Obj//CDVDisodrv.o: ../../CDVDisodrv.c + $(CC) -c ../../CDVDisodrv.c -o Obj//CDVDisodrv.o $(CFLAGS) + +Obj//COP0.o: ../../COP0.c + $(CC) -c ../../COP0.c -o Obj//COP0.o $(CFLAGS) + +Obj//Counters.o: ../../Counters.c + $(CC) -c ../../Counters.c -o Obj//Counters.o $(CFLAGS) + +Obj//Decode_XA.o: ../../Decode_XA.c + $(CC) -c ../../Decode_XA.c -o Obj//Decode_XA.o $(CFLAGS) + +Obj//Elfheader.o: ../../Elfheader.c + $(CC) -c ../../Elfheader.c -o Obj//Elfheader.o $(CFLAGS) + +Obj//FiFo.o: ../../FiFo.c + $(CC) -c ../../FiFo.c -o Obj//FiFo.o $(CFLAGS) + +Obj//FPU.o: ../../FPU.c + $(CC) -c ../../FPU.c -o Obj//FPU.o $(CFLAGS) + +Obj//GS.o: ../../GS.c + $(CC) -c ../../GS.c -o Obj//GS.o $(CFLAGS) + +Obj//Gte.o: ../../Gte.c + $(CC) -c ../../Gte.c -o Obj//Gte.o $(CFLAGS) + +Obj//Hw.o: ../../Hw.c + $(CC) -c ../../Hw.c -o Obj//Hw.o $(CFLAGS) + +Obj//Interpreter.o: ../../Interpreter.c + $(CC) -c ../../Interpreter.c -o Obj//Interpreter.o $(CFLAGS) + +Obj//InterTables.o: ../../InterTables.c + $(CC) -c ../../InterTables.c -o Obj//InterTables.o $(CFLAGS) + +Obj//Mdec.o: ../../Mdec.c + $(CC) -c ../../Mdec.c -o Obj//Mdec.o $(CFLAGS) + +Obj//Memory.o: ../../Memory.c + $(CC) -c ../../Memory.c -o Obj//Memory.o $(CFLAGS) + +Obj//Misc.o: ../../Misc.c + $(CC) -c ../../Misc.c -o Obj//Misc.o $(CFLAGS) + +Obj//MMI.o: ../../MMI.c + $(CC) -c ../../MMI.c -o Obj//MMI.o $(CFLAGS) + +Obj//Patch.o: ../../Patch.c + $(CC) -c ../../Patch.c -o Obj//Patch.o $(CFLAGS) + +Obj//Plugins.o: ../../Plugins.c + $(CC) -c ../../Plugins.c -o Obj//Plugins.o $(CFLAGS) + +Obj//PsxBios.o: ../../PsxBios.c + $(CC) -c ../../PsxBios.c -o Obj//PsxBios.o $(CFLAGS) + +Obj//PsxCounters.o: ../../PsxCounters.c + $(CC) -c ../../PsxCounters.c -o Obj//PsxCounters.o $(CFLAGS) + +Obj//PsxDma.o: ../../PsxDma.c + $(CC) -c ../../PsxDma.c -o Obj//PsxDma.o $(CFLAGS) + +Obj//PsxGPU.o: ../../PsxGPU.c + $(CC) -c ../../PsxGPU.c -o Obj//PsxGPU.o $(CFLAGS) + +Obj//PsxHw.o: ../../PsxHw.c + $(CC) -c ../../PsxHw.c -o Obj//PsxHw.o $(CFLAGS) + +Obj//PsxInterpreter.o: ../../PsxInterpreter.c + $(CC) -c ../../PsxInterpreter.c -o Obj//PsxInterpreter.o $(CFLAGS) + +Obj//PsxMem.o: ../../PsxMem.c + $(CC) -c ../../PsxMem.c -o Obj//PsxMem.o $(CFLAGS) + +Obj//PsxSio2.o: ../../PsxSio2.c + $(CC) -c ../../PsxSio2.c -o Obj//PsxSio2.o $(CFLAGS) + +Obj//R3000A.o: ../../R3000A.c + $(CC) -c ../../R3000A.c -o Obj//R3000A.o $(CFLAGS) + +Obj//R5900.o: ../../R5900.c + $(CC) -c ../../R5900.c -o Obj//R5900.o $(CFLAGS) + +Obj//Sif.o: ../../Sif.c + $(CC) -c ../../Sif.c -o Obj//Sif.o $(CFLAGS) + +Obj//Sio.o: ../../Sio.c + $(CC) -c ../../Sio.c -o Obj//Sio.o $(CFLAGS) + +Obj//SPR.o: ../../SPR.c + $(CC) -c ../../SPR.c -o Obj//SPR.o $(CFLAGS) + +Obj//Stats.o: ../../Stats.c + $(CC) -c ../../Stats.c -o Obj//Stats.o $(CFLAGS) + +Obj//Vif.o: ../../Vif.c + $(CC) -c ../../Vif.c -o Obj//Vif.o $(CFLAGS) + +Obj//VifDma.o: ../../VifDma.c + $(CC) -c ../../VifDma.c -o Obj//VifDma.o $(CFLAGS) + +Obj//VU0.o: ../../VU0.c + $(CC) -c ../../VU0.c -o Obj//VU0.o $(CFLAGS) + +Obj//VU0micro.o: ../../VU0micro.c + $(CC) -c ../../VU0micro.c -o Obj//VU0micro.o $(CFLAGS) + +Obj//VU1micro.o: ../../VU1micro.c + $(CC) -c ../../VU1micro.c -o Obj//VU1micro.o $(CFLAGS) + +Obj//VUflags.o: ../../VUflags.c + $(CC) -c ../../VUflags.c -o Obj//VUflags.o $(CFLAGS) + +Obj//VUops.o: ../../VUops.c + $(CC) -c ../../VUops.c -o Obj//VUops.o $(CFLAGS) + +Obj//Cache.o: ../../Cache.c + $(CC) -c ../../Cache.c -o Obj//Cache.o $(CFLAGS) + +Obj//CdRom.o: ../../CdRom.c + $(CC) -c ../../CdRom.c -o Obj//CdRom.o $(CFLAGS) + +Obj//deci2.o: ../../RDebug/deci2.c + $(CC) -c ../../RDebug/deci2.c -o Obj//deci2.o $(CFLAGS) + +Obj//deci2_dbgp.o: ../../RDebug/deci2_dbgp.c + $(CC) -c ../../RDebug/deci2_dbgp.c -o Obj//deci2_dbgp.o $(CFLAGS) + +Obj//deci2_dcmp.o: ../../RDebug/deci2_dcmp.c + $(CC) -c ../../RDebug/deci2_dcmp.c -o Obj//deci2_dcmp.o $(CFLAGS) + +Obj//deci2_iloadp.o: ../../RDebug/deci2_iloadp.c + $(CC) -c ../../RDebug/deci2_iloadp.c -o Obj//deci2_iloadp.o $(CFLAGS) + +Obj//deci2_netmp.o: ../../RDebug/deci2_netmp.c + $(CC) -c ../../RDebug/deci2_netmp.c -o Obj//deci2_netmp.o $(CFLAGS) + +Obj//deci2_ttyp.o: ../../RDebug/deci2_ttyp.c + $(CC) -c ../../RDebug/deci2_ttyp.c -o Obj//deci2_ttyp.o $(CFLAGS) + +Obj//pcsx2_private.res: pcsx2_private.rc ../pcsx2.rc + $(WINDRES) -i pcsx2_private.rc --input-format=rc -o Obj//pcsx2_private.res -O coff --include-dir ../../ --include-dir ../ --include-dir ../mingw diff --git a/pcsx2/windows/mingw/afxres.h b/pcsx2/windows/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/pcsx2/windows/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/pcsx2/windows/mingw/pcsx2.dev b/pcsx2/windows/mingw/pcsx2.dev new file mode 100644 index 0000000..db8fafb --- /dev/null +++ b/pcsx2/windows/mingw/pcsx2.dev @@ -0,0 +1,2116 @@ +[Project] +FileName=pcsx2.dev +Name=pcsx2 +UnitCount=205 +Type=0 +Ver=1 +ObjFiles= +Includes=../..;../../zlib;../../DebugTools;../../IPU;../../x86;../../ix86-32;..;../RDebug +Libs= +PrivateResource=pcsx2_private.rc +ResourceIncludes=../../;../;..\mingw +MakeIncludes= +Compiler=-v_@@_-D__WIN32___@@_-D__MINGW32__ _@@_-Wall _@@_-O3 ${-fomit-frame-pointer -finline-functions -fno-exceptions -ffast-math -fno-strict-aliasing} -mfpmath=sse -march=athlon64_@@_ _@@_ +CppCompiler= +Linker=-lcomctl32 _@@_-lwsock32 _@@_-lwinmm _@@_-lgdi32 _@@_-lcomdlg32 _@@__@@_-m128bit-long-double_@@_ +IsCpp=0 +Icon= +ExeOutput=../ +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=pcsx2.exe +HostApplication= +Folders=cpu,DebugTools,DECI2,GUI,Hardware,IOP_CPU,IPU,ix86,ix86/x86,ix86-32,misc,plugins,Sif,zlib +CommandLine= +UseCustomMakefile=0 +CustomMakefile=..\Makefile +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=..\AboutDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\AboutDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\ConfigDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\CpuDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\Debugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\Debugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\DebugMemory.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\Debugreg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\ini.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\McdsDlg.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=..\McdsDlg.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=..\PatchBrowser.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=..\pcsx2.rc +Folder=GUI +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=..\RDebugger.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=..\RDebugger.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=..\resource.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=..\Win32.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=..\WinMain.c +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=afxres.h +CompileCpp=0 +Folder=GUI +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=..\..\IPU\Idct.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=..\..\IPU\IPU.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=..\..\IPU\IPU.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=..\..\IPU\Mpeg.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=..\..\IPU\Mpeg.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=..\..\IPU\Vlc.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=..\..\IPU\yuv2rgb.c +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=..\..\IPU\yuv2rgb.h +CompileCpp=0 +Folder=IPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=..\..\DebugTools\cpuopsDebug.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=..\..\DebugTools\cpuopsDebug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=..\..\DebugTools\Debug.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=..\..\DebugTools\DisASM.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=..\..\DebugTools\DisR3000A.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=..\..\DebugTools\DisR3000asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=..\..\DebugTools\DisR5900.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=..\..\DebugTools\DisR5900asm.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=..\..\DebugTools\DisVU0Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=..\..\DebugTools\DisVU1Micro.c +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=..\..\DebugTools\DisVUmicro.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=..\..\DebugTools\DisVUops.h +CompileCpp=0 +Folder=DebugTools +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=..\..\zlib\adler32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=..\..\zlib\compress.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=..\..\zlib\crc32.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=..\..\zlib\crc32.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=..\..\zlib\deflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=..\..\zlib\deflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=..\..\zlib\gzio.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=..\..\zlib\infback.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=..\..\zlib\inffast.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=..\..\zlib\inffast.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=..\..\zlib\inffixed.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=..\..\zlib\inflate.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=..\..\zlib\inflate.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit53] +FileName=..\..\zlib\inftrees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=..\..\zlib\inftrees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=..\..\zlib\trees.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=..\..\zlib\trees.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=..\..\zlib\uncompr.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=..\..\zlib\zconf.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=..\..\zlib\zlib.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=..\..\zlib\zutil.c +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=..\..\zlib\zutil.h +CompileCpp=0 +Folder=zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit62] +FileName=..\..\ix86-32\iR5900Arit.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit63] +FileName=..\..\ix86-32\iR5900Arit.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit64] +FileName=..\..\ix86-32\iR5900AritImm.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit65] +FileName=..\..\ix86-32\iR5900AritImm.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit66] +FileName=..\..\ix86-32\iR5900Branch.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit67] +FileName=..\..\ix86-32\iR5900Branch.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit68] +FileName=..\..\ix86-32\iR5900Jump.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit69] +FileName=..\..\ix86-32\iR5900Jump.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit70] +FileName=..\..\ix86-32\iR5900LoadStore.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit71] +FileName=..\..\ix86-32\iR5900LoadStore.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit72] +FileName=..\..\ix86-32\iR5900Move.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit73] +FileName=..\..\ix86-32\iR5900Move.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit74] +FileName=..\..\ix86-32\iR5900MultDiv.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit75] +FileName=..\..\ix86-32\iR5900MultDiv.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit76] +FileName=..\..\ix86-32\iR5900Shift.c +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=..\..\ix86-32\iR5900Shift.h +CompileCpp=0 +Folder=ix86-32 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit78] +FileName=..\..\x86\iCP0.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=..\..\x86\iCP0.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit80] +FileName=..\..\x86\iFPU.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit81] +FileName=..\..\x86\iFPU.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit82] +FileName=..\..\x86\iMMI.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit83] +FileName=..\..\x86\iMMI.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit84] +FileName=..\..\x86\iR3000A.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit85] +FileName=..\..\x86\iR5900.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit86] +FileName=..\..\x86\iR5900.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit87] +FileName=..\..\x86\iVU0micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit88] +FileName=..\..\x86\iVU0micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit89] +FileName=..\..\x86\iVU1micro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit90] +FileName=..\..\x86\iVU1micro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit91] +FileName=..\..\x86\iVUmicro.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit92] +FileName=..\..\x86\iVUmicro.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit93] +FileName=..\..\x86\iVUops.h +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit94] +FileName=..\..\x86\recCOP2.c +CompileCpp=0 +Folder=ix86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit95] +FileName=..\..\x86\ix86\ix86.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit96] +FileName=..\..\x86\ix86\ix86.h +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit97] +FileName=..\..\x86\ix86\ix86_3dnow.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit98] +FileName=..\..\x86\ix86\ix86_cpudetect.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit99] +FileName=..\..\x86\ix86\ix86_fpu.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit100] +FileName=..\..\x86\ix86\ix86_mmx.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit101] +FileName=..\..\x86\ix86\ix86_sse.c +CompileCpp=0 +Folder=ix86/x86 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit102] +FileName=..\..\CDVD.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit103] +FileName=..\..\CDVD.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit104] +FileName=..\..\CDVDiso.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit105] +FileName=..\..\CDVDiso.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit106] +FileName=..\..\CDVDisodrv.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit107] +FileName=..\..\CDVDisodrv.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit108] +FileName=..\..\CDVDlib.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit109] +FileName=..\..\Common.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit110] +FileName=..\..\COP0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit111] +FileName=..\..\COP0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit112] +FileName=..\..\Counters.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit113] +FileName=..\..\Counters.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit114] +FileName=..\..\Decode_XA.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit115] +FileName=..\..\Decode_XA.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit116] +FileName=..\..\EEregs.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit117] +FileName=..\..\Elfheader.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit118] +FileName=..\..\Elfheader.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit119] +FileName=..\..\FiFo.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit120] +FileName=..\..\FPU.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit121] +FileName=..\..\GS.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit122] +FileName=..\..\GS.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit123] +FileName=..\..\Gte.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit124] +FileName=..\..\Gte.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit125] +FileName=..\..\Hw.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit126] +FileName=..\..\Hw.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit127] +FileName=..\..\Interpreter.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit128] +FileName=..\..\InterTables.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit129] +FileName=..\..\InterTables.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit130] +FileName=..\..\Mdec.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit131] +FileName=..\..\Mdec.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit132] +FileName=..\..\Memory.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit133] +FileName=..\..\Memory.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit134] +FileName=..\..\Misc.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit135] +FileName=..\..\Misc.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit136] +FileName=..\..\MMI.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit137] +FileName=..\..\Patch.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit138] +FileName=..\..\Patch.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit139] +FileName=..\..\Plugins.c +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit140] +FileName=..\..\Plugins.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit141] +FileName=..\..\PS2Edefs.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit142] +FileName=..\..\PS2Etypes.h +CompileCpp=0 +Folder=plugins +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit143] +FileName=..\..\PsxBios2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit144] +FileName=..\..\PsxBios.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit145] +FileName=..\..\PsxBios.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit146] +FileName=..\..\PsxCommon.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit147] +FileName=..\..\PsxCounters.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit148] +FileName=..\..\PsxCounters.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit149] +FileName=..\..\PsxDma.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit150] +FileName=..\..\PsxDma.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit151] +FileName=..\..\PsxGPU.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit152] +FileName=..\..\PsxGPU.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit153] +FileName=..\..\PsxHw.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit154] +FileName=..\..\PsxHw.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit155] +FileName=..\..\PsxInterpreter.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit156] +FileName=..\..\PsxMem.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit157] +FileName=..\..\PsxMem.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit158] +FileName=..\..\PsxSio2.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit159] +FileName=..\..\PsxSio2.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit160] +FileName=..\..\R3000A.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit161] +FileName=..\..\R3000A.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit162] +FileName=..\..\R5900.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit163] +FileName=..\..\R5900.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit164] +FileName=..\..\Sif.c +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit165] +FileName=..\..\Sif.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit166] +FileName=..\..\Sifcmd.h +CompileCpp=0 +Folder=Sif +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit167] +FileName=..\..\Sio.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit168] +FileName=..\..\Sio.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit169] +FileName=..\..\SPR.c +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit170] +FileName=..\..\SPR.h +CompileCpp=0 +Folder=Hardware +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit171] +FileName=..\..\Stats.c +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit172] +FileName=..\..\Stats.h +CompileCpp=0 +Folder=misc +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit173] +FileName=..\..\System.h +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit174] +FileName=..\..\Vif.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit175] +FileName=..\..\Vif.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=..\..\VifDma.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit177] +FileName=..\..\VifDma.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit178] +FileName=..\..\VU0.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit179] +FileName=..\..\VU0.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit180] +FileName=..\..\VU0micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit181] +FileName=..\..\VU1micro.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit182] +FileName=..\..\VU.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit183] +FileName=..\..\VUflags.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit184] +FileName=..\..\VUflags.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit185] +FileName=..\..\VUmicro.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit186] +FileName=..\..\VUops.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit187] +FileName=..\..\VUops.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit188] +FileName=..\..\Cache.c +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit189] +FileName=..\..\Cache.h +CompileCpp=0 +Folder=cpu +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit190] +FileName=..\..\CdRom.c +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit191] +FileName=..\..\CdRom.h +CompileCpp=0 +Folder=IOP_CPU +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit192] +FileName=..\Cdrom02.ico +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit193] +FileName=..\..\pcsxAbout.bmp +Folder=GUI +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit194] +FileName=..\..\RDebug\deci2.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit195] +FileName=..\..\RDebug\deci2.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit196] +FileName=..\..\RDebug\deci2_dbgp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit197] +FileName=..\..\RDebug\deci2_dbgp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit198] +FileName=..\..\RDebug\deci2_dcmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit199] +FileName=..\..\RDebug\deci2_dcmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit202] +FileName=..\..\RDebug\deci2_netmp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit203] +FileName=..\..\RDebug\deci2_netmp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit204] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit205] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit206] +FileName=..\..\RDebug\deci2_ttyp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit207] +FileName=..\..\RDebug\deci2_ttyp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit200] +FileName=..\..\RDebug\deci2_iloadp.c +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit201] +FileName=..\..\RDebug\deci2_iloadp.h +CompileCpp=0 +Folder=DECI2 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/pcsx2/windows/mingw/pcsx2.layout b/pcsx2/windows/mingw/pcsx2.layout new file mode 100644 index 0000000..eb0d940 --- /dev/null +++ b/pcsx2/windows/mingw/pcsx2.layout @@ -0,0 +1,1424 @@ +[Editor_0] +CursorCol=1 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_1] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_4] +CursorCol=1 +CursorRow=95 +TopLine=54 +LeftChar=1 +Open=1 +Top=1 +[Editor_3] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_5] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_6] +CursorCol=2 +CursorRow=239 +TopLine=193 +LeftChar=1 +Open=0 +Top=0 +[Editor_8] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_9] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_7] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_10] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_11] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_12] +CursorCol=1 +CursorRow=19 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_13] +CursorCol=20 +CursorRow=172 +TopLine=132 +LeftChar=1 +Open=0 +Top=0 +[Editor_14] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_15] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_16] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_17] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_2] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_19] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_20] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_22] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_23] +CursorCol=1 +CursorRow=175 +TopLine=146 +LeftChar=1 +Open=0 +Top=0 +[Editor_24] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_25] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_26] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_21] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_27] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_28] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_29] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_31] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_30] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_32] +CursorCol=48 +CursorRow=360 +TopLine=315 +LeftChar=1 +Open=0 +Top=0 +[Editor_33] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_34] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_35] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_36] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_37] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_38] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_39] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_40] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_41] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_42] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_43] +CursorCol=8 +CursorRow=841 +TopLine=812 +LeftChar=1 +Open=0 +Top=0 +[Editor_44] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_45] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_46] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_47] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_48] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_49] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_50] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_51] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_52] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_53] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_54] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_55] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_56] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_57] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_58] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_59] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_60] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_61] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_62] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_63] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_64] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_65] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_66] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_67] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_68] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_69] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_70] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_71] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_72] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_73] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_74] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_75] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_76] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_77] +CursorCol=18 +CursorRow=24 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_78] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_79] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_80] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_81] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_82] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_83] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_84] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_85] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_86] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_87] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_88] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_89] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_90] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_91] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_92] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_93] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_113] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_114] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_189] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_190] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_187] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_188] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_135] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_143] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_126] +CursorCol=1 +CursorRow=515 +TopLine=496 +LeftChar=1 +Open=0 +Top=0 +[Editor_127] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_128] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_133] +CursorCol=1 +CursorRow=684 +TopLine=643 +LeftChar=1 +Open=0 +Top=0 +[Editor_134] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_136] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_137] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_138] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_139] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_140] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_141] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_145] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_144] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_142] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_146] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_147] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_150] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_152] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_154] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_132] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_148] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_149] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_151] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_153] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_155] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_156] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_157] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_158] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_159] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_160] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_161] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_162] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_173] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_174] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_175] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_176] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_181] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_177] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_178] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_179] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_180] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_182] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_183] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_184] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_185] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_186] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_119] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_131] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_124] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_125] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_122] +CursorCol=17 +CursorRow=207 +TopLine=197 +LeftChar=1 +Open=0 +Top=0 +[Editor_123] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_129] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_130] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_163] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_164] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_166] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_167] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_109] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_110] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_192] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_170] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_168] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_169] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_165] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_111] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_112] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_101] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_102] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_103] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_104] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_105] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_106] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_107] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_115] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_116] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_117] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_118] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_120] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_121] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_171] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Focused=-1 +Order=-1 +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_94] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_95] +Open=0 +Top=0 +[Editor_96] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_97] +Open=1 +Top=0 +CursorCol=28 +CursorRow=477 +TopLine=439 +LeftChar=1 +[Editor_98] +Open=0 +Top=0 +[Editor_99] +Open=0 +Top=0 +CursorCol=1 +CursorRow=337 +TopLine=296 +LeftChar=1 +[Editor_100] +Open=0 +Top=0 +[Editor_108] +Open=0 +Top=0 +CursorCol=3 +CursorRow=3 +TopLine=1 +LeftChar=1 +[Editor_172] +Open=0 +Top=0 +[Editor_191] +Open=0 +Top=0 +[Editor_193] +Open=0 +Top=0 +CursorCol=20 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_194] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_195] +Open=0 +Top=0 +CursorCol=1 +CursorRow=349 +TopLine=1 +LeftChar=1 +[Editor_196] +Open=0 +Top=0 +[Editor_197] +Open=0 +Top=0 +CursorCol=6 +CursorRow=42 +TopLine=37 +LeftChar=1 +[Editor_198] +Open=0 +Top=0 +CursorCol=6 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_199] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_200] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_201] +Open=0 +Top=0 +CursorCol=21 +CursorRow=133 +TopLine=89 +LeftChar=1 +[Editor_202] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_203] +Open=0 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_204] +Open=0 +Top=0 +CursorCol=9 +CursorRow=27 +TopLine=1 +LeftChar=1 +[Editor_205] +Open=1 +Top=0 +CursorCol=21 +CursorRow=40 +TopLine=1 +LeftChar=1 +[Editor_206] +Open=0 +Top=0 diff --git a/pcsx2/windows/mingw/pcsx2_private.h b/pcsx2/windows/mingw/pcsx2_private.h new file mode 100644 index 0000000..38d3841 --- /dev/null +++ b/pcsx2/windows/mingw/pcsx2_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef PCSX2_PRIVATE_H +#define PCSX2_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*PCSX2_PRIVATE_H*/ diff --git a/pcsx2/windows/mingw/pcsx2_private.rc b/pcsx2/windows/mingw/pcsx2_private.rc new file mode 100644 index 0000000..aea0afe --- /dev/null +++ b/pcsx2/windows/mingw/pcsx2_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "../pcsx2.rc" + diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc new file mode 100644 index 0000000..d1e6187 --- /dev/null +++ b/pcsx2/windows/pcsx2.rc @@ -0,0 +1,1537 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CMDLINE DIALOG 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Program arguments" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,36,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,99,37,50,14 + CTEXT "Tip: If you don't know what to write\nleave it blank", + IDC_TIP,7,56,172,19,WS_BORDER + EDITTEXT IDC_CMDLINE,7,17,172,14,ES_AUTOHSCROLL + LTEXT "Fill in the command line arguments for opened program:", + IDC_TEXT,7,7,174,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CMDLINE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CP0REGS DIALOG 0, 0, 267, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP0 " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CP00,48,7,51,12,ES_READONLY + LTEXT "Index",-1,7,9,18,8 + EDITTEXT IDC_CP01,48,21,51,12,ES_READONLY + LTEXT "Random",-1,7,23,28,8 + EDITTEXT IDC_CP02,48,35,51,12,ES_READONLY + LTEXT "EntryLo0",-1,7,37,29,8 + EDITTEXT IDC_CP03,48,49,51,12,ES_READONLY + LTEXT "EntryLo1",-1,7,51,29,8 + EDITTEXT IDC_CP04,48,63,51,12,ES_READONLY + LTEXT "Context",-1,7,65,25,8 + EDITTEXT IDC_CP05,48,77,51,12,ES_READONLY + LTEXT "PageMask",-1,7,79,35,8 + EDITTEXT IDC_CP06,48,91,51,12,ES_READONLY + LTEXT "Wired",-1,7,93,20,8 + EDITTEXT IDC_CP07,48,105,51,12,ES_READONLY + EDITTEXT IDC_CP08,48,119,51,12,ES_READONLY + LTEXT "BadVAddr",-1,7,121,33,8 + EDITTEXT IDC_CP09,48,133,52,12,ES_READONLY + LTEXT "Count",-1,7,135,20,8 + EDITTEXT IDC_CP010,48,147,51,12,ES_READONLY + LTEXT "EntryHi",-1,7,149,24,8 + EDITTEXT IDC_CP011,48,161,52,12,ES_READONLY + LTEXT "Compare",-1,7,163,29,8 + EDITTEXT IDC_CP012,48,175,51,12,ES_READONLY + LTEXT "Status",-1,7,177,21,8 + EDITTEXT IDC_CP013,48,189,51,12,ES_READONLY + LTEXT "Cause",-1,7,191,21,8 + EDITTEXT IDC_CP014,48,203,51,12,ES_READONLY + LTEXT "EPC",-1,7,205,15,8 + EDITTEXT IDC_CP015,48,218,51,12,ES_READONLY + LTEXT "PRId",-1,7,219,17,8 + EDITTEXT IDC_CP016,191,7,51,12,ES_READONLY + LTEXT "Config",-1,145,9,21,8 + EDITTEXT IDC_CP017,191,21,51,12,ES_READONLY + EDITTEXT IDC_CP018,191,35,51,12,ES_READONLY + EDITTEXT IDC_CP019,191,49,51,12,ES_READONLY + EDITTEXT IDC_CP020,191,63,51,12,ES_READONLY + EDITTEXT IDC_CP021,191,77,51,12,ES_READONLY + EDITTEXT IDC_CP022,191,91,51,12,ES_READONLY + EDITTEXT IDC_CP023,191,105,51,12,ES_READONLY + EDITTEXT IDC_CP024,191,119,51,12,ES_READONLY + EDITTEXT IDC_CP025,191,133,51,12,ES_READONLY + EDITTEXT IDC_CP026,191,147,51,12,ES_READONLY + LTEXT "Debug",-1,147,122,22,8 + EDITTEXT IDC_CP027,191,161,51,12,ES_READONLY + LTEXT "Perf",-1,149,136,14,8 + EDITTEXT IDC_CP028,191,175,51,12,ES_READONLY + LTEXT "TagLo",-1,145,177,22,8 + EDITTEXT IDC_CP029,191,189,51,12,ES_READONLY + LTEXT "TagHi",-1,145,191,20,8 + EDITTEXT IDC_CP030,191,203,51,12,ES_READONLY + LTEXT "ErrorEPC",-1,145,205,30,8 + EDITTEXT IDC_CP031,191,218,51,12,ES_READONLY +END + +IDD_DEBUG DIALOGEX 0, 0, 281, 297 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Debugger" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM,7,28,198,235,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Close",IDC_DEBUG_CLOSE,223,249,50,14 + PUSHBUTTON "Step",IDC_DEBUG_STEP,223,36,50,14 + PUSHBUTTON "Skip",IDC_DEBUG_SKIP,223,54,50,14 + PUSHBUTTON "Go",IDC_DEBUG_GO,223,19,50,14 + PUSHBUTTON "Bkpt on Exec",IDC_DEBUG_BP_EXEC,223,129,50,14 + SCROLLBAR IDC_DEBUG_SCROLL,205,28,11,235,SBS_VERT + PUSHBUTTON "Jump to ADDR",IDC_DEBUG_JUMP,223,112,50,14 + PUSHBUTTON "Un/Set Log",IDC_DEBUG_LOG,223,71,50,14 + PUSHBUTTON "Bkpt on Count",IDC_DEBUG_BP_COUNT,223,145,50,14 + PUSHBUTTON "Dump code",IDC_DEBUG_DUMP,223,194,50,14 + PUSHBUTTON "Clear Bkpts",IDC_DEBUG_BP_CLEAR,223,162,50,14 + PUSHBUTTON "Dump memory",IDC_DEBUG_MEMORY,223,211,50,14 + PUSHBUTTON "Cpu ops",IDC_CPUOP,223,227,50,14 + PUSHBUTTON "Reset to PC",IDC_DEBUG_RESETTOPC,223,96,50,14 +END + +IDD_DUMP DIALOGEX 0, 0, 386, 96 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump code" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_DUMP_START,73,14,82,13 + EDITTEXT IDC_DUMP_END,73,29,82,13 + EDITTEXT IDC_DUMP_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,87,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,227,73,50,14 + LTEXT "Start PC Address:",IDC_STATIC,19,17,52,8 + LTEXT "End PC Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 + GROUPBOX "EE",IDC_STATIC,14,6,167,64 + EDITTEXT IDC_DUMP_STARTIOP,255,15,82,13 + EDITTEXT IDC_DUMP_ENDIOP,255,30,82,13 + EDITTEXT IDC_DUMP_FNAMEIOP,255,50,82,13,ES_AUTOHSCROLL + LTEXT "Start PC Address:",IDC_STATIC,201,18,52,8 + LTEXT "End PC Address:",IDC_STATIC,201,33,50,8 + LTEXT "Filename:",IDC_STATIC,201,54,31,8 + GROUPBOX "IOP",IDC_STATIC,195,7,167,63 +END + +IDD_GPREGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "R5900 Main registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_GPR0,22,7,166,12,ES_READONLY + LTEXT "R0",-1,7,9,10,8 + EDITTEXT IDC_GPR1,22,21,166,12,ES_READONLY + LTEXT "AT",-1,7,23,10,8 + EDITTEXT IDC_GPR2,22,35,166,12,ES_READONLY + LTEXT "V0",-1,7,37,10,8 + EDITTEXT IDC_GPR3,22,49,166,12,ES_READONLY + LTEXT "V1",-1,7,51,10,8 + EDITTEXT IDC_GPR4,22,63,166,12,ES_READONLY + LTEXT "A0",-1,7,65,10,8 + EDITTEXT IDC_GPR5,22,77,166,12,ES_READONLY + LTEXT "A1",-1,7,79,10,8 + EDITTEXT IDC_GPR6,22,91,166,12,ES_READONLY + LTEXT "A2",-1,7,93,10,8 + EDITTEXT IDC_GPR7,22,105,166,12,ES_READONLY + LTEXT "A3",-1,7,107,10,8 + EDITTEXT IDC_GPR8,22,119,166,12,ES_READONLY + LTEXT "T0",-1,7,121,10,8 + EDITTEXT IDC_GPR9,22,133,166,12,ES_READONLY + LTEXT "T1",-1,7,135,10,8 + EDITTEXT IDC_GPR10,22,147,166,12,ES_READONLY + LTEXT "T2",-1,7,149,10,8 + EDITTEXT IDC_GPR11,22,161,166,12,ES_READONLY + LTEXT "T3",-1,7,163,10,8 + EDITTEXT IDC_GPR12,22,175,166,12,ES_READONLY + LTEXT "T4",-1,7,177,10,8 + EDITTEXT IDC_GPR13,22,189,166,12,ES_READONLY + LTEXT "T5",-1,7,191,10,8 + EDITTEXT IDC_GPR14,22,203,166,12,ES_READONLY + LTEXT "T6",-1,7,205,10,8 + EDITTEXT IDC_GPR15,22,218,166,12,ES_READONLY + LTEXT "T7",-1,7,219,10,8 + EDITTEXT IDC_GPR16,214,7,165,12,ES_READONLY + LTEXT "S0",-1,196,10,10,8 + EDITTEXT IDC_GPR17,214,20,166,12,ES_READONLY + LTEXT "S1",-1,196,22,10,8 + EDITTEXT IDC_GPR18,214,35,166,12,ES_READONLY + LTEXT "S2",-1,196,36,10,8 + EDITTEXT IDC_GPR19,214,49,165,12,ES_READONLY + LTEXT "S3",-1,196,52,10,8 + EDITTEXT IDC_GPR20,214,63,165,12,ES_READONLY + LTEXT "S4",-1,196,66,10,8 + EDITTEXT IDC_GPR21,214,76,165,12,ES_READONLY + LTEXT "S5",-1,196,80,10,8 + EDITTEXT IDC_GPR22,214,91,165,12,ES_READONLY + LTEXT "S6",-1,196,94,10,8 + EDITTEXT IDC_GPR23,214,105,165,12,ES_READONLY + LTEXT "S7",-1,196,108,10,8 + EDITTEXT IDC_GPR24,214,119,165,12,ES_READONLY + LTEXT "T8",-1,196,121,10,8 + EDITTEXT IDC_GPR25,214,132,165,12,ES_READONLY + LTEXT "T9",-1,196,135,10,8 + EDITTEXT IDC_GPR26,214,147,165,12,ES_READONLY + LTEXT "K0",-1,196,149,10,8 + EDITTEXT IDC_GPR27,214,161,165,12,ES_READONLY + LTEXT "K1",-1,196,163,10,8 + EDITTEXT IDC_GPR28,214,175,165,12,ES_READONLY + LTEXT "GP",-1,196,178,11,8 + EDITTEXT IDC_GPR29,214,188,165,12,ES_READONLY + LTEXT "SP",-1,196,190,10,8 + EDITTEXT IDC_GPR30,214,203,165,12,ES_READONLY + LTEXT "S8",-1,196,205,10,8 + EDITTEXT IDC_GPR31,214,217,165,12,ES_READONLY + LTEXT "RA",-1,196,220,11,8 + EDITTEXT IDC_GPR_PC,20,260,57,12,ES_READONLY + LTEXT "PC",-1,7,263,10,8 + EDITTEXT IDC_GPR_HI,21,238,167,12,ES_READONLY + LTEXT "HI",-1,7,241,8,8 + LTEXT "LO",-1,196,241,10,8 + EDITTEXT IDC_GPR_LO,214,238,165,12,ES_READONLY +END + +IDD_JUMP DIALOG 0, 0, 175, 64 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Jump to specific address" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_JUMP_PC,73,14,82,13 + DEFPUSHBUTTON "OK",IDOK,25,43,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,42,50,14 + LTEXT "Enter new PC Address:",IDC_STATIC,3,18,70,8 +END + +IDD_MEMORY DIALOG 0, 0, 317, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Memory" +FONT 8, "Courier" +BEGIN + EDITTEXT IDC_MEMORY_ADDR,54,7,97,12 + PUSHBUTTON "Close",IDC_MEMORY_CLOSE,266,7,42,14 + LTEXT "Address:",IDC_STATIC,14,8,34,8 + LISTBOX IDC_MEMORY_DUMP,3,29,300,169,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_TABSTOP + SCROLLBAR IDC_MEM_SCROLL,303,29,9,172,SBS_VERT + GROUPBOX "Memory Patch",IDC_STATIC,3,204,307,57 + EDITTEXT IDC_ADDRESS_PATCH,124,220,97,12 + EDITTEXT IDC_DATA_PATCH,124,242,97,12 + LTEXT "Address",IDC_STATIC,84,222,40,8 + LTEXT "Data",IDC_STATIC,85,244,39,8 + PUSHBUTTON "Patch It",IDC_PATCH,238,230,64,16 + PUSHBUTTON "Raw dump",IDC_DUMPRAW,204,7,50,14 +END + +IDD_VU1INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1 Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU1_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU1_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU1_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU1_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU1_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU1_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU1_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU1_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU1_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU1_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU1_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU1_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU1_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU1_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU1_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU1_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU1_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU1_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU1_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU1_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU1_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU1_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU1_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU1_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU1_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU1_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU1_VI27,172,161,89,12,WS_DISABLED + LTEXT "P register",IDC_STATIC,124,108,30,8 + EDITTEXT IDC_VU1_VI28,172,175,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI29,172,189,89,12,WS_DISABLED + EDITTEXT IDC_VU1_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU1_VI31,172,218,89,12,WS_DISABLED + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU1_ACC,78,239,166,12,ES_READONLY +END + +IDD_VU0REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU0_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU0_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU0_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU0_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU0_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU0_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU0_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU0_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU0_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU0_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU0_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU0_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU0_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU0_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU0_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU0_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU0_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU0_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU0_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU0_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU0_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU0_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU0_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU0_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU0_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU0_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU0_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU0_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU0_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU0_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU0_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_CP1REGS DIALOG 0, 0, 357, 237 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "COP1 Registers " +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_FP0,29,7,89,12,WS_DISABLED + LTEXT "FP0",IDC_STATIC,7,9,14,8 + EDITTEXT IDC_FP1,29,21,89,12,WS_DISABLED + LTEXT "FP1",IDC_STATIC,7,23,14,8 + EDITTEXT IDC_FP2,29,35,89,12,WS_DISABLED + LTEXT "FP2",IDC_STATIC,7,37,14,8 + EDITTEXT IDC_FP3,29,49,89,12,WS_DISABLED + LTEXT "FP3",IDC_STATIC,7,51,14,8 + EDITTEXT IDC_FP4,29,63,89,12,WS_DISABLED + LTEXT "FP4",IDC_STATIC,7,65,14,8 + EDITTEXT IDC_FP5,29,77,89,12,WS_DISABLED + LTEXT "FP5",IDC_STATIC,7,79,14,8 + EDITTEXT IDC_FP6,29,91,89,12,WS_DISABLED + LTEXT "FP6",IDC_STATIC,7,93,14,8 + EDITTEXT IDC_FP7,29,105,89,12,WS_DISABLED + LTEXT "FP7",IDC_STATIC,7,107,14,8 + EDITTEXT IDC_FP8,29,119,89,12,WS_DISABLED + LTEXT "FP8",IDC_STATIC,7,121,14,8 + EDITTEXT IDC_FP9,29,133,89,12,WS_DISABLED + LTEXT "FP9",IDC_STATIC,7,135,14,8 + EDITTEXT IDC_FP10,29,147,89,12,WS_DISABLED + LTEXT "FP10",IDC_STATIC,7,149,18,8 + EDITTEXT IDC_FP11,29,161,89,12,WS_DISABLED + LTEXT "FP11",IDC_STATIC,7,163,18,8 + EDITTEXT IDC_FP12,29,175,89,12,WS_DISABLED + LTEXT "FP12",IDC_STATIC,7,177,18,8 + EDITTEXT IDC_FP13,29,189,89,12,WS_DISABLED + LTEXT "FP13",IDC_STATIC,7,191,18,8 + EDITTEXT IDC_FP14,29,203,89,12,WS_DISABLED + LTEXT "FP14",IDC_STATIC,7,205,18,8 + EDITTEXT IDC_FP15,29,218,89,12,WS_DISABLED + LTEXT "FP15",IDC_STATIC,7,219,18,8 + EDITTEXT IDC_FP16,145,7,89,12,WS_DISABLED + LTEXT "FP16",IDC_STATIC,123,9,18,8 + EDITTEXT IDC_FP17,145,21,89,12,WS_DISABLED + LTEXT "FP17",IDC_STATIC,123,23,18,8 + EDITTEXT IDC_FP18,145,35,89,12,WS_DISABLED + LTEXT "FP18",IDC_STATIC,123,37,18,8 + EDITTEXT IDC_FP19,145,49,89,12,WS_DISABLED + LTEXT "FP19",IDC_STATIC,123,51,18,8 + EDITTEXT IDC_FP20,145,63,89,12,WS_DISABLED + LTEXT "FP20",IDC_STATIC,123,65,18,8 + EDITTEXT IDC_FP21,145,77,89,12,WS_DISABLED + LTEXT "FP21",IDC_STATIC,123,79,18,8 + EDITTEXT IDC_FP22,145,91,89,12,WS_DISABLED + LTEXT "FP22",IDC_STATIC,123,93,18,8 + EDITTEXT IDC_FP23,145,105,89,12,WS_DISABLED + LTEXT "FP23",IDC_STATIC,123,107,18,8 + EDITTEXT IDC_FP24,145,119,89,12,WS_DISABLED + LTEXT "FP24",IDC_STATIC,123,121,18,8 + EDITTEXT IDC_FP25,145,133,89,12,WS_DISABLED + LTEXT "FP25",IDC_STATIC,123,135,18,8 + EDITTEXT IDC_FP26,145,147,89,12,WS_DISABLED + LTEXT "FP26",IDC_STATIC,123,149,18,8 + EDITTEXT IDC_FP27,145,161,89,12,WS_DISABLED + LTEXT "FP27",IDC_STATIC,123,163,18,8 + EDITTEXT IDC_FP28,145,175,89,12,WS_DISABLED + LTEXT "FP28",IDC_STATIC,123,177,18,8 + EDITTEXT IDC_FP29,145,189,89,12,WS_DISABLED + LTEXT "FP29",IDC_STATIC,123,191,18,8 + EDITTEXT IDC_FP30,145,203,89,12,WS_DISABLED + LTEXT "FP30",IDC_STATIC,123,205,18,8 + EDITTEXT IDC_FP31,145,218,89,12,WS_DISABLED + LTEXT "FP31",IDC_STATIC,123,219,18,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,244,8,1, + 223 + LTEXT "Implementation/Revision Reg",IDC_STATIC,253,9,94,8 + EDITTEXT IDC_FCR0,298,21,50,12,WS_DISABLED + LTEXT "FCR0",IDC_STATIC,253,23,19,8 + LTEXT "Control/Status Register",IDC_STATIC,253,37,74,8 + EDITTEXT IDC_FCR31,298,49,50,12,WS_DISABLED + LTEXT "FCR31",IDC_STATIC,253,51,23,8 + LTEXT "Accumulator",IDC_STATIC,256,68,43,14 + EDITTEXT IDC_FPU_ACC,299,68,49,12,ES_AUTOHSCROLL | WS_DISABLED +END + +IDD_VU0INTEGER DIALOG 0, 0, 357, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VUO Integer & Control Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU0_VI00,29,7,89,12,WS_DISABLED + LTEXT "VI00",IDC_STATIC,7,9,16,8 + EDITTEXT IDC_VU0_VI01,29,21,89,12,WS_DISABLED + LTEXT "VI01",IDC_STATIC,7,23,16,8 + EDITTEXT IDC_VU0_VI02,29,35,89,12,WS_DISABLED + LTEXT "VI02",IDC_STATIC,7,37,16,8 + EDITTEXT IDC_VU0_VI03,29,49,89,12,WS_DISABLED + LTEXT "VI03",IDC_STATIC,7,51,16,8 + EDITTEXT IDC_VU0_VI04,29,63,89,12,WS_DISABLED + LTEXT "VI04",IDC_STATIC,7,65,16,8 + EDITTEXT IDC_VU0_VI05,29,77,89,12,WS_DISABLED + LTEXT "VI05",IDC_STATIC,7,79,16,8 + EDITTEXT IDC_VU0_VI06,29,91,89,12,WS_DISABLED + LTEXT "VI06",IDC_STATIC,7,93,16,8 + EDITTEXT IDC_VU0_VI07,29,105,89,12,WS_DISABLED + LTEXT "VI07",IDC_STATIC,7,107,16,8 + EDITTEXT IDC_VU0_VI08,29,119,89,12,WS_DISABLED + LTEXT "VI08",IDC_STATIC,7,121,16,8 + EDITTEXT IDC_VU0_VI09,29,133,89,12,WS_DISABLED + LTEXT "VI09",IDC_STATIC,7,135,16,8 + EDITTEXT IDC_VU0_VI10,29,147,89,12,WS_DISABLED + LTEXT "VI10",IDC_STATIC,7,149,16,8 + EDITTEXT IDC_VU0_VI11,29,161,89,12,WS_DISABLED + LTEXT "VI11",IDC_STATIC,7,163,16,8 + EDITTEXT IDC_VU0_VI12,29,175,89,12,WS_DISABLED + LTEXT "VI12",IDC_STATIC,7,177,16,8 + EDITTEXT IDC_VU0_VI13,29,189,89,12,WS_DISABLED + LTEXT "VI13",IDC_STATIC,7,191,16,8 + EDITTEXT IDC_VU0_VI14,29,203,89,12,WS_DISABLED + LTEXT "VI14",IDC_STATIC,7,205,16,8 + EDITTEXT IDC_VU0_VI15,29,218,89,12,WS_DISABLED + LTEXT "VI15",IDC_STATIC,7,219,16,8 + EDITTEXT IDC_VU0_VI16,172,7,89,12,WS_DISABLED + LTEXT "Status Flag",IDC_STATIC,123,9,36,8 + EDITTEXT IDC_VU0_VI17,172,21,89,12,WS_DISABLED + LTEXT "MAC Flag",IDC_STATIC,123,23,32,8 + EDITTEXT IDC_VU0_VI18,172,35,89,12,WS_DISABLED + LTEXT "Clipping Flag",IDC_STATIC,123,37,41,8 + EDITTEXT IDC_VU0_VI19,172,49,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,51,8,8 + EDITTEXT IDC_VU0_VI20,172,63,89,12,WS_DISABLED + LTEXT "R register",IDC_STATIC,123,65,31,8 + EDITTEXT IDC_VU0_VI21,172,77,89,12,WS_DISABLED + LTEXT "I register",IDC_STATIC,123,79,28,8 + EDITTEXT IDC_VU0_VI22,172,91,89,12,WS_DISABLED + LTEXT "Q register",IDC_STATIC,123,93,31,8 + EDITTEXT IDC_VU0_VI23,172,105,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,107,8,8 + EDITTEXT IDC_VU0_VI24,172,119,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,121,8,8 + EDITTEXT IDC_VU0_VI25,172,133,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,135,8,8 + EDITTEXT IDC_VU0_VI26,172,147,89,12,WS_DISABLED + LTEXT "TPC register",IDC_STATIC,123,149,40,8 + EDITTEXT IDC_VU0_VI27,172,161,89,12,WS_DISABLED + LTEXT "CMSAR0 reg",IDC_STATIC,123,163,42,8 + EDITTEXT IDC_VU0_VI28,172,175,89,12,WS_DISABLED + LTEXT "FBRST register",IDC_STATIC,123,177,49,8 + EDITTEXT IDC_VU0_VI29,172,189,89,12,WS_DISABLED + LTEXT "VPU-STAT reg",IDC_STATIC,123,191,48,8 + EDITTEXT IDC_VU0_VI30,172,203,89,12,WS_DISABLED + LTEXT "",IDC_STATIC,123,205,8,8 + EDITTEXT IDC_VU0_VI31,172,218,89,12,WS_DISABLED + LTEXT "CMSAR1 reg",IDC_STATIC,123,219,42,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT | SS_SUNKEN,273,7,1, + 222 + LTEXT "Accumulator",IDC_STATIC,27,238,43,14 + EDITTEXT IDC_VU0_ACC,78,239,166,12,ES_READONLY + LTEXT "P register",IDC_STATIC,124,108,30,8 +END + +IDD_VU1REGS DIALOG 0, 0, 391, 279 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "VU1Floating Point Registers" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_VU1_VF00,28,7,166,12,ES_READONLY + LTEXT "VF00",-1,7,9,18,8 + EDITTEXT IDC_VU1_VF01,28,21,166,12,ES_READONLY + LTEXT "VF01",-1,7,23,18,8 + EDITTEXT IDC_VU1_VF02,28,35,166,12,ES_READONLY + LTEXT "VF02",-1,7,37,18,8 + EDITTEXT IDC_VU1_VF03,28,49,166,12,ES_READONLY + LTEXT "VF03",-1,7,51,18,8 + EDITTEXT IDC_VU1_VF04,28,63,166,12,ES_READONLY + LTEXT "VF04",-1,7,65,18,8 + EDITTEXT IDC_VU1_VF05,28,77,166,12,ES_READONLY + LTEXT "VF05",-1,7,79,18,8 + EDITTEXT IDC_VU1_VF06,28,91,166,12,ES_READONLY + LTEXT "VF06",-1,7,93,18,8 + EDITTEXT IDC_VU1_VF07,28,105,166,12,ES_READONLY + LTEXT "VF07",-1,7,107,18,8 + EDITTEXT IDC_VU1_VF08,28,119,166,12,ES_READONLY + LTEXT "VF08",-1,7,121,18,8 + EDITTEXT IDC_VU1_VF09,28,133,166,12,ES_READONLY + LTEXT "VF09",-1,7,135,18,8 + EDITTEXT IDC_VU1_VF10,28,147,166,12,ES_READONLY + LTEXT "VF10",-1,7,149,18,8 + EDITTEXT IDC_VU1_VF11,28,161,166,12,ES_READONLY + LTEXT "VF11",-1,7,163,18,8 + EDITTEXT IDC_VU1_VF12,28,175,166,12,ES_READONLY + LTEXT "VF12",-1,7,177,18,8 + EDITTEXT IDC_VU1_VF13,28,189,166,12,ES_READONLY + LTEXT "VF13",-1,7,191,18,8 + EDITTEXT IDC_VU1_VF14,28,203,166,12,ES_READONLY + LTEXT "VF14",-1,7,205,18,8 + EDITTEXT IDC_VU1_VF15,28,218,166,12,ES_READONLY + LTEXT "VF15",-1,7,219,18,8 + EDITTEXT IDC_VU1_VF16,214,7,165,12,ES_READONLY + LTEXT "VF16",-1,196,10,18,8 + EDITTEXT IDC_VU1_VF17,214,20,166,12,ES_READONLY + LTEXT "VF17",-1,196,22,18,8 + EDITTEXT IDC_VU1_VF18,214,35,166,12,ES_READONLY + LTEXT "VF18",-1,196,36,18,8 + EDITTEXT IDC_VU1_VF19,214,49,165,12,ES_READONLY + LTEXT "VF19",-1,196,52,18,8 + EDITTEXT IDC_VU1_VF20,214,63,165,12,ES_READONLY + LTEXT "VF20",-1,196,66,18,8 + EDITTEXT IDC_VU1_VF21,214,76,165,12,ES_READONLY + LTEXT "VF21",-1,196,80,18,8 + EDITTEXT IDC_VU1_VF22,214,91,165,12,ES_READONLY + LTEXT "VF22",-1,196,94,18,8 + EDITTEXT IDC_VU1_VF23,214,105,165,12,ES_READONLY + LTEXT "VF23",-1,196,108,18,8 + EDITTEXT IDC_VU1_VF24,214,119,165,12,ES_READONLY + LTEXT "VF24",-1,196,121,18,8 + EDITTEXT IDC_VU1_VF25,214,132,165,12,ES_READONLY + LTEXT "VF25",-1,196,135,18,8 + EDITTEXT IDC_VU1_VF26,214,147,165,12,ES_READONLY + LTEXT "VF26",-1,196,149,18,8 + EDITTEXT IDC_VU1_VF27,214,161,165,12,ES_READONLY + LTEXT "VF27",-1,196,163,18,8 + EDITTEXT IDC_VU1_VF28,214,175,165,12,ES_READONLY + LTEXT "VF28",-1,196,178,18,8 + EDITTEXT IDC_VU1_VF29,214,188,165,12,ES_READONLY + LTEXT "VF29",-1,196,190,18,8 + EDITTEXT IDC_VU1_VF30,214,203,165,12,ES_READONLY + LTEXT "VF30",-1,196,205,18,8 + EDITTEXT IDC_VU1_VF31,214,217,165,12,ES_READONLY + LTEXT "VF31",-1,196,220,18,8 +END + +IDD_RDEBUGPARAMS DIALOGEX 0, 0, 174, 58 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,37,50,14 + EDITTEXT IDC_PORT,127,7,40,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Accept connections on TCP/IP port:",IDC_STATIC,7,7,120, + 10 + CONTROL "Debug Bios",IDC_DEBUGBIOS,"Button",BS_AUTOCHECKBOX | + BS_LEFTTEXT | WS_TABSTOP,7,22,50,10 +END + +IDD_RDEBUG DIALOGEX 0, 0, 254, 271 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Remote Debugging" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "E&xit",IDOK,199,251,48,14 + LISTBOX IDC_COMMUNICATION,7,7,240,211,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + PUSHBUTTON "&Clear",IDC_CLEAR,199,229,48,14 + EDITTEXT IDC_EEPC,74,229,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPPC,132,229,52,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "EE pc address:\t IOP pc address:",IDC_STATIC,77,219,113, + 9 + CONTROL "Debug EE",IDC_DEBUGEE,"Button",BS_AUTORADIOBUTTON,77, + 255,48,10 + CONTROL "Debug IOP",IDC_DEBUGIOP,"Button",BS_AUTORADIOBUTTON | + BS_LEFTTEXT,132,254,50,11 + EDITTEXT IDC_STOPAT,7,229,56,13,ES_AUTOHSCROLL + EDITTEXT IDC_STOPAFTER,7,252,56,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Break at (hex addr):",IDC_STATIC,7,219,67,8 + LTEXT "Break after (cycles):",IDC_STATIC,7,243,66,8 + EDITTEXT IDC_EECYCLE,74,241,52,12,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_IOPCYCLE,132,241,52,12,ES_AUTOHSCROLL | ES_READONLY +END + +IDD_MCDCONF DIALOG 0, 0, 407, 197 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Memcard Manager" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,285,175,50,14 + PUSHBUTTON "Cancel",IDCANCEL,345,175,50,14 + EDITTEXT IDC_MCD1,10,155,160,14,ES_AUTOHSCROLL + EDITTEXT IDC_MCD2,235,155,160,14,ES_AUTOHSCROLL + PUSHBUTTON "Select Mcd",IDC_MCDSEL1,10,135,50,14 + PUSHBUTTON "Select Mcd",IDC_MCDSEL2,235,135,50,14 + GROUPBOX "Memory Card 2",IDC_FRAMEMCD2,230,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT1,65,135,50,14 + GROUPBOX "Memory Card 1",IDC_FRAMEMCD1,5,5,170,125 + PUSHBUTTON "Format Mcd",IDC_FORMAT2,290,135,50,14 + CONTROL "List3",IDC_LIST1,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,15,160,110 + CONTROL "List3",IDC_LIST2,"SysListView32",LVS_REPORT | + LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,235,15,160,110 + PUSHBUTTON "Reload Mcd",IDC_RELOAD1,120,135,50,14 + PUSHBUTTON "Reload Mcd",IDC_RELOAD2,345,135,50,14 + PUSHBUTTON "-> Copy ->",IDC_COPYTO2,180,30,45,14 + PUSHBUTTON "<- Copy <-",IDC_COPYTO1,180,50,45,14 + PUSHBUTTON "Paste",IDC_PASTE,180,70,45,14 + PUSHBUTTON "<- Un/Delete",IDC_DELETE1,180,90,45,14 + PUSHBUTTON "Un/Delete ->",IDC_DELETE2,180,110,45,14 +END + +IDD_DUMPMEM DIALOG 0, 0, 175, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Dump memory" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DUMPMEM_START,73,14,82,13 + EDITTEXT IDC_DUMPMEM_END,73,29,82,13 + EDITTEXT IDC_DUMPMEM_FNAME,73,50,82,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,25,74,50,14 + PUSHBUTTON "Cancel",IDCANCEL,101,74,50,14 + LTEXT "Start Address:",IDC_STATIC,19,17,52,8 + LTEXT "End Address:",IDC_STATIC,19,32,50,8 + LTEXT "Filename:",IDC_STATIC,19,53,31,8 +END + +IDD_DIALOGBAR DIALOGEX 0, 0, 330, 16 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "TODO: layout dialog bar",IDC_STATIC,126,4,77,8 +END + +IDD_IOPREGS DIALOGEX 0, 0, 417, 295 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "IOP Main Registers" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_IOPGPR0,22,20,166,12,ES_READONLY + LTEXT "R0",-1,7,23,10,8 + EDITTEXT IDC_IOPGPR1,22,34,166,12,ES_READONLY + LTEXT "AT",-1,7,36,10,8 + EDITTEXT IDC_IOPGPR2,22,49,166,12,ES_READONLY + LTEXT "V0",-1,7,50,10,8 + EDITTEXT IDC_IOPGPR3,22,63,166,12,ES_READONLY + LTEXT "V1",-1,7,65,10,8 + EDITTEXT IDC_IOPGPR4,22,76,166,12,ES_READONLY + LTEXT "A0",-1,7,79,10,8 + EDITTEXT IDC_IOPGPR5,22,90,166,12,ES_READONLY + LTEXT "A1",-1,7,92,10,8 + EDITTEXT IDC_IOPGPR6,22,105,166,12,ES_READONLY + LTEXT "A2",-1,7,106,10,8 + EDITTEXT IDC_IOPGPR7,22,119,166,12,ES_READONLY + LTEXT "A3",-1,7,121,10,8 + EDITTEXT IDC_IOPGPR8,22,132,166,12,ES_READONLY + LTEXT "T0",-1,7,135,10,8 + EDITTEXT IDC_IOPGPR9,22,146,166,12,ES_READONLY + LTEXT "T1",-1,7,148,10,8 + EDITTEXT IDC_IOPGPR10,22,161,166,12,ES_READONLY + LTEXT "T2",-1,7,162,10,8 + EDITTEXT IDC_IOPGPR11,22,175,166,12,ES_READONLY + LTEXT "T3",-1,7,177,10,8 + EDITTEXT IDC_IOPGPR12,22,188,166,12,ES_READONLY + LTEXT "T4",-1,7,191,10,8 + EDITTEXT IDC_IOPGPR13,22,202,166,12,ES_READONLY + LTEXT "T5",-1,7,204,10,8 + EDITTEXT IDC_IOPGPR14,22,217,166,12,ES_READONLY + LTEXT "T6",-1,7,218,10,8 + EDITTEXT IDC_IOPGPR15,22,231,166,12,ES_READONLY + LTEXT "T7",-1,7,233,10,8 + EDITTEXT IDC_IOPGPR16,214,20,165,12,ES_READONLY + LTEXT "S0",-1,196,23,10,8 + EDITTEXT IDC_IOPGPR17,214,34,166,12,ES_READONLY + LTEXT "S1",-1,196,36,10,8 + EDITTEXT IDC_IOPGPR18,214,49,166,12,ES_READONLY + LTEXT "S2",-1,196,50,10,8 + EDITTEXT IDC_IOPGPR19,214,63,165,12,ES_READONLY + LTEXT "S3",-1,196,66,10,8 + EDITTEXT IDC_IOPGPR20,214,76,165,12,ES_READONLY + LTEXT "S4",-1,196,79,10,8 + EDITTEXT IDC_IOPGPR21,214,90,165,12,ES_READONLY + LTEXT "S5",-1,196,94,10,8 + EDITTEXT IDC_IOPGPR22,214,105,165,12,ES_READONLY + LTEXT "S6",-1,196,108,10,8 + EDITTEXT IDC_IOPGPR23,214,119,165,12,ES_READONLY + LTEXT "S7",-1,196,122,10,8 + EDITTEXT IDC_IOPGPR24,214,132,165,12,ES_READONLY + LTEXT "T8",-1,196,135,10,8 + EDITTEXT IDC_IOPGPR25,214,146,165,12,ES_READONLY + LTEXT "T9",-1,196,148,10,8 + EDITTEXT IDC_IOPGPR26,214,161,165,12,ES_READONLY + LTEXT "K0",-1,196,162,10,8 + EDITTEXT IDC_IOPGPR27,214,175,165,12,ES_READONLY + LTEXT "K1",-1,196,177,10,8 + EDITTEXT IDC_IOPGPR28,214,188,165,12,ES_READONLY + LTEXT "GP",-1,196,191,11,8 + EDITTEXT IDC_IOPGPR29,214,202,165,12,ES_READONLY + LTEXT "SP",-1,196,204,10,8 + EDITTEXT IDC_IOPGPR30,214,217,165,12,ES_READONLY + LTEXT "S8",-1,196,218,10,8 + EDITTEXT IDC_IOPGPR31,214,231,165,12,ES_READONLY + LTEXT "RA",-1,196,234,11,8 + EDITTEXT IDC_IOPGPR_PC,20,272,57,12,ES_READONLY + LTEXT "PC",-1,7,276,10,8 + EDITTEXT IDC_IOPGPR_HI,21,252,167,12,ES_READONLY + LTEXT "HI",-1,7,255,8,8 + LTEXT "LO",-1,196,255,10,8 + EDITTEXT IDC_IOPGPR_LO,214,252,165,12,ES_READONLY +END + +IDD_USERNAME DIALOGEX 0, 0, 186, 79 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Enter User Name" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,58,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,58,50,14 + LTEXT "Pcsx2 needs to allocate physical memory in order to execute faster. Enter the windows username you wish this privilege to be enabled for.", + IDC_STATIC,7,7,172,25 + EDITTEXT IDC_USER_NAME,73,37,106,13,ES_AUTOHSCROLL + LTEXT "User Name:",IDC_STATIC,7,41,38,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DEBUG, DIALOG + BEGIN + BOTTOMMARGIN, 282 + END + + IDD_RDEBUGPARAMS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 167 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + END + + IDD_RDEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 247 + TOPMARGIN, 7 + BOTTOMMARGIN, 265 + END + + IDD_MCDCONF, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 240 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_DIALOGBAR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 323 + TOPMARGIN, 7 + BOTTOMMARGIN, 9 + END + + IDD_IOPREGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 410 + TOPMARGIN, 7 + BOTTOMMARGIN, 284 + END + + IDD_USERNAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 72 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_PS2SILVER BITMAP "ps2_silver.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUT_DIALOG DIALOGEX 0, 0, 431, 270 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_ACCEPTFILES +CAPTION "About" +FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,205,250,50,14 + CTEXT "PCSX2 \nVersion x.x",IDC_PCSX_ABOUT_TEXT,55,10,45,15,0, + WS_EX_TRANSPARENT + CTEXT "PCSX2 a PS2 Emulator...",IDC_PCSX_ABOUT_AUTHORS,9,36, + 135,92,0,WS_EX_TRANSPARENT + CTEXT "Greets to...",IDC_PCSX_ABOUT_GREETS,88,158,311,77 + GROUPBOX "",IDC_STATIC,5,29,145,113 + GROUPBOX "",IDC_STATIC,77,148,333,91 + CONTROL 132,IDC_PS2SILVER_RECT,"Static",SS_BITMAP,0,167,70,74 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + ABOUT_DIALOG, DIALOG + BEGIN + RIGHTMARGIN, 429 + BOTTOMMARGIN, 264 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +SPLASH_LOGO BITMAP "..\\pcsxAbout.bmp" +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_FINDER DIALOGEX 3, 1, 262, 212 +STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU +CAPTION "Cheat Finder" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "Results",IDC_RESULTS,"SysListView32",LVS_REPORT | + WS_TABSTOP,96,15,161,153,WS_EX_CLIENTEDGE + GROUPBOX "Values of size",IDC_STATIC,5,44,86,45 + CHECKBOX "Unsigned",IDC_UNSIGNED,11,74,70,10,NOT WS_TABSTOP + CONTROL "64bits",IDC_64B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 48,64,33,10 + CONTROL "32bits",IDC_32B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 48,54,33,10 + CONTROL "16bits",IDC_16B,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,64,33,10 + CONTROL "8bits",IDC_8B,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11, + 54,33,10 + PUSHBUTTON "Close",IDCANCEL,208,192,49,15,NOT WS_TABSTOP + PUSHBUTTON "Search",IDC_SEARCH,96,192,49,15,NOT WS_TABSTOP + GROUPBOX "Comapred to",IDC_STATIC,5,162,86,45 + EDITTEXT IDC_VALUE,21,192,65,12,ES_AUTOHSCROLL | NOT WS_TABSTOP + CONTROL "Specific Value",IDC_SET,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,182,75,10 + CONTROL "Old Value",IDC_OLD,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,172,75,10 + GROUPBOX "Search in",IDC_STATIC,5,5,86,35 + CONTROL "Smaller or equal",IDC_LE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,139,75,10 + CONTROL "Greater or equal",IDC_GE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,129,75,10 + CONTROL "Smaller",IDC_LT,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,120,75,10 + CONTROL "Greater",IDC_GT,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,110,75,10 + CONTROL "Equal",IDC_EQ,"Button",BS_AUTORADIOBUTTON | WS_GROUP,11, + 101,75,10 + PUSHBUTTON "Reset",IDC_RESET,96,172,49,15,NOT WS_TABSTOP + PUSHBUTTON "Add",IDC_ADD,208,172,49,15,NOT WS_TABSTOP + RTEXT "1 match found.",IDC_MATCHES,125,5,132,10,NOT WS_GROUP + LTEXT "Results:",IDC_STATIC,96,5,29,10,NOT WS_GROUP + CONTROL "EE RAM",IDC_EE,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,15,43,10 + CONTROL "IOP RAM",IDC_IOP,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 11,25,43,10 + CONTROL "Not equal",IDC_NE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,11,148,75,10 + GROUPBOX "being",IDC_STATIC,5,92,86,67 +END + +IDD_ADD DIALOGEX 3, 1, 145, 74 +STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU +CAPTION "Add Cheat" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + PUSHBUTTON "OK",IDOK,37,54,49,15,NOT WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,91,54,49,15,NOT WS_TABSTOP + LTEXT "Cheat Name",IDC_STATIC,5,30,75,10,NOT WS_GROUP + LTEXT "New Value",IDC_STATIC,69,5,70,10,NOT WS_GROUP + LTEXT "Address",IDC_STATIC,5,5,59,10,NOT WS_GROUP + EDITTEXT IDC_NAME,5,39,134,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + EDITTEXT IDC_VALUE,69,15,70,12,ES_AUTOHSCROLL | NOT WS_TABSTOP + EDITTEXT IDC_ADDR,5,15,59,12,ES_AUTOHSCROLL | NOT WS_TABSTOP +END + +IDD_CHEATS DIALOGEX 0, 0, 232, 222 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,119,201,50,14 + PUSHBUTTON "Cancel",IDCANCEL,175,201,50,14 + CONTROL "",IDC_GROUPS,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_EDITLABELS | TVS_CHECKBOXES | + WS_TABSTOP,7,7,218,126,WS_EX_CLIENTEDGE + CONTROL "",IDC_PATCHES,"SysListView32",LVS_REPORT | WS_TABSTOP,7, + 139,218,57,WS_EX_CLIENTEDGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CHEATS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 225 + TOPMARGIN, 7 + BOTTOMMARGIN, 215 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Spanish resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 317, 244 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_LISTGS,10,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGGS,10,35,45,12 + PUSHBUTTON "Test...",IDC_TESTGS,60,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTGS,110,35,45,12 + COMBOBOX IDC_LISTSPU2,166,15,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGSPU2,165,35,45,12 + PUSHBUTTON "Test...",IDC_TESTSPU2,215,35,45,12 + PUSHBUTTON "About...",IDC_ABOUTSPU2,265,35,43,12 + COMBOBOX IDC_LISTCDVD,10,105,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGCDVD,10,125,43,12 + PUSHBUTTON "Test...",IDC_TESTCDVD,60,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTCDVD,110,125,45,12 + COMBOBOX IDC_LISTBIOS,165,196,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,207,223,50,14 + PUSHBUTTON "Cancel",IDCANCEL,260,223,50,14 + CTEXT "Graphics",IDC_GRAPHICS,50,5,62,10,SS_CENTERIMAGE + CTEXT "Sound",IDC_SOUND,200,5,71,10,SS_CENTERIMAGE + CTEXT "Cdvdrom",IDC_CDVDROM,55,95,56,10,SS_CENTERIMAGE + CTEXT "Bios",IDC_BIOS,208,185,61,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD1,10,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD1,10,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD1,60,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD1,110,80,45,12 + CTEXT "Second Controller",IDC_SECONDCONTROLLER,191,50,90,10, + SS_CENTERIMAGE + COMBOBOX IDC_LISTPAD2,166,60,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGPAD2,165,80,45,12 + PUSHBUTTON "Test...",IDC_TESTPAD2,215,80,45,12 + PUSHBUTTON "About...",IDC_ABOUTPAD2,265,80,45,12 + CTEXT "First Controller",IDC_FIRSTCONTROLLER,41,50,82,10, + SS_CENTERIMAGE + PUSHBUTTON "Set Bios Directory",IDC_BIOSDIR,14,223,134,14 + PUSHBUTTON "Set Plugins Directory",IDC_PLUGINSDIR,14,204,134,14 + COMBOBOX IDC_LISTDEV9,165,105,145,74,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGDEV9,165,125,43,12 + PUSHBUTTON "Test...",IDC_TESTDEV9,215,125,45,12 + PUSHBUTTON "About...",IDC_ABOUTDEV9,265,125,45,12 + CTEXT "Dev9",IDC_DEV9,221,95,30,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTUSB,10,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGUSB,10,170,43,12 + PUSHBUTTON "Test...",IDC_TESTUSB,60,170,45,12 + PUSHBUTTON "About...",IDC_ABOUTUSB,110,170,45,12 + CTEXT "Usb",IDC_USB,59,140,47,10,SS_CENTERIMAGE + COMBOBOX IDC_LISTFW,165,151,145,74,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Configure...",IDC_CONFIGFW,165,169,43,12 + PUSHBUTTON "Test...",IDC_TESTFW,214,169,45,12 + PUSHBUTTON "About...",IDC_ABOUTFW,265,169,45,12 + CTEXT "FireWire",IDC_FW,206,141,60,8 +END + +IDD_BPEXEC DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Exec" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EXECBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Address:",IDC_STATIC,5,13,84,8 +END + +IDD_BPCNT DIALOG 0, 0, 182, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "BreakPoint on Count" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CNTBP,92,10,82,13 + DEFPUSHBUTTON "OK",IDOK,30,40,50,14 + PUSHBUTTON "Cancel",IDCANCEL,100,40,50,14 + LTEXT "Enter BreakPoint Count:",IDC_STATIC,5,13,77,8 +END + +IDD_ADVANCED DIALOGEX 0, 0, 177, 69 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Advanced" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,47,50,14 + PUSHBUTTON "Cancel",IDCANCEL,121,47,50,14 + CONTROL "Enable Reg Caching",IDC_REGCACHING,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,15,81,10 + GROUPBOX "",IDC_STATIC,2,7,168,38 + PUSHBUTTON "Reset",IDC_ADVRESET,5,47,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 237 + HORZGUIDE, 169 + END + + IDD_BPEXEC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 6 + BOTTOMMARGIN, 54 + END + + IDD_BPCNT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + IDD_ADVANCED, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON "Cdrom02.ico" +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Greek resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ELL) +#ifdef _WIN32 +LANGUAGE LANG_GREEK, SUBLANG_DEFAULT +#pragma code_page(1253) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_PATCHBROWSER DIALOGEX 0, 0, 487, 282 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | + WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Patches Browser" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "New Patch",IDC_NEWPATCH,112,257,60,14 + EDITTEXT IDC_PATCHTEXT,113,95,354,153,ES_MULTILINE | + ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + PUSHBUTTON "Save Patch",IDC_SAVEPATCH,186,257,60,14,WS_DISABLED + PUSHBUTTON "Refresh List",IDC_REFRESHPATCHLIST,21,257,60,14 + LISTBOX IDC_PATCHCRCLIST,19,95,69,153,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_PATCHNAMELIST,17,34,452,50,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Search game name patch:",IDC_GAMENAMESEARCH,17,16,101,9 + EDITTEXT IDC_SEARCHPATCHTEXT,109,14,295,12,ES_AUTOHSCROLL + PUSHBUTTON "Exit",IDC_EXITPB,411,257,59,14 +END + +IDD_LOGGING DIALOGEX 0, 0, 263, 177 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Logging" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,206,156,50,14 + CONTROL "Cpu log",IDC_CPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,5,53,10 + CONTROL "COP0 log",IDC_COP0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,20,59,10 + CONTROL "FPU log",IDC_FPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,35,55,10 + CONTROL "MMI log",IDC_MMILOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,50,55,10 + CONTROL "VUO log",IDC_VU0LOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,65,56,10 + CONTROL "Bios log",IDC_BIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,80,54,10 + CONTROL "DMA log",IDC_DMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,5,95,57,10 + CONTROL "HW log",IDC_HWLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 5,110,53,10 + CONTROL "Unknown Memory log",IDC_MEMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,5,84,10 + CONTROL "Elf log",IDC_ELFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,20,35,10 + CONTROL "VIF log",IDC_VIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,35,38,10 + CONTROL "Scratch pad log",IDC_SPRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,50,66,10 + CONTROL "Gif log",IDC_GIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,65,49,10 + CONTROL "SIF log",IDC_SIFLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,80,51,10 + GROUPBOX "IOP",IDC_STATIC,161,7,95,127 + CONTROL "IOP cpu log",IDC_IOPLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,15,67,10 + CONTROL "HW log",IDC_IOPHWLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,30,53,10 + CONTROL "Bios log",IDC_IOPBIOSLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,45,41,10 + CONTROL "Unknown Memory log",IDC_IOPMEMLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,165,60,85,10 + CONTROL "IPU log",IDC_IPULOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,95,39,10 + CONTROL "DMA log",IDC_IOPDMALOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,75,67,10 + CONTROL "PAD log",IDC_IOPPADLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,90,53,10 + CONTROL "CDR log",IDC_IOPCDRLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,104,43,10 + CONTROL "VUMicro log",IDC_VUMICROLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,110,55,10 + CONTROL "RPC services log",IDC_RPCSERVICES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,5,125,67,10 + CONTROL "Log to STDOUT",IDC_STDOUTPUTLOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,75,125,68,10 + CONTROL "Log",IDC_LOGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,5, + 140,28,10 + CONTROL "Symbols log",IDC_SYMLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,75,140,53,10 + CONTROL "Counters log",IDC_IOPCNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,118,55,10 + CONTROL "EE Counters log",IDC_EECNTLOG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,165,139,73,11 +END + +IDD_IOP_DEBUG DIALOGEX 0, 0, 358, 107 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Debug" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_DISASM_IOP,7,7,330,92,LBS_USETABSTOPS | + LBS_NOINTEGRALHEIGHT | WS_TABSTOP,WS_EX_TRANSPARENT + SCROLLBAR IDC_DEBUG_SCROLL_IOP,340,7,11,93,SBS_VERT +END + +IDD_CPUDLG DIALOGEX 0, 0, 250, 377 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "EERec - EE/IOP recompiler (need MMX/SSE)", + IDC_CPU_EEREC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7, + 103,236,18 + CONTROL "VU0rec - enable recompiler for VU0 unit",IDC_CPU_VU0REC, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,15, + 127,219,18 + CONTROL "VU1rec - enable recompiler for VU1 unit",IDC_CPU_VU1REC, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,15, + 144,228,18 + CONTROL "Multi threaded GS mode (MTGS)\n (faster on dual core/HT procs, requires pcsx2 restart)", + IDC_CPU_GSMULTI,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,166,236,30 + CONTROL "Dual Core Mode (DC) - Much faster but only valid with MTGS", + IDC_CPU_MULTI,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | + WS_TABSTOP,7,199,236,26 + CONTROL "Normal - All frames are rendered as fast as possible.", + IDC_CPU_FL_NORMAL,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE | WS_GROUP,14,236,221,17 + CONTROL "Limit - Force frames to normal speeds if too fast.", + IDC_CPU_FL_LIMIT,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE,14,254,222,22 + CONTROL "Frame Skip - In order to achieve normal speeds,\n some frames are skipped (fast).\n Fps displayed counts skipped frames too.", + IDC_CPU_FL_SKIP,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE,15,277,221,35 + CONTROL "VU Skip - Same as 'Frame Skip', but tries to skip more.\n Artifacts might be present, but will be faster.", + IDC_CPU_FL_SKIPVU,"Button",BS_AUTORADIOBUTTON | + BS_MULTILINE,15,314,220,31 + DEFPUSHBUTTON "OK",IDOK,59,356,61,14 + PUSHBUTTON "Cancel",IDCANCEL,131,356,61,14,NOT WS_TABSTOP + LTEXT "CPU Vendor",IDC_VENDORNAME,12,23,88,8 + LTEXT "Family",IDC_FAMILYNAME,12,41,88,8 + LTEXT "Cpu Speed",IDC_CPUSPEEDNAME,12,60,88,8 + LTEXT "",IDC_VENDORINPUT,112,24,124,8 + LTEXT "",IDC_FAMILYINPUT,112,41,124,8 + LTEXT "",IDC_FEATURESINPUT,111,79,124,8 + LTEXT "",IDC_CPUSPEEDINPUT,111,61,124,8 + GROUPBOX "VU Recompilers - All options are set by default", + IDC_CPU_VUGROUP,7,119,236,46 + GROUPBOX "Frame Limiting",IDC_FRAMELIMIT,7,225,236,127 + LTEXT "Features",IDC_FEATURESNAME,12,78,88,8 + GROUPBOX "",IDC_STATIC,7,7,236,90 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_LOGGING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 256 + TOPMARGIN, 7 + BOTTOMMARGIN, 170 + END + + IDD_IOP_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 351 + TOPMARGIN, 7 + BOTTOMMARGIN, 100 + END + + IDD_CPUDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 370 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Greek resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/pcsx2/windows/ps2_silver.bmp b/pcsx2/windows/ps2_silver.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cb58820cdf1d734c0f8889bde4b6023e9feb4e12 GIT binary patch literal 37974 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 literal 0 HcmV?d00001 diff --git a/pcsx2/windows/resource.h b/pcsx2/windows/resource.h new file mode 100644 index 0000000..9578ac5 --- /dev/null +++ b/pcsx2/windows/resource.h @@ -0,0 +1,677 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pcsx2.rc +// +#define IDR_MENU 101 +#define IDD_CONFIG 101 +#define IDD_MCDCONF 102 +#define IDD_BPEXEC 103 +#define ABOUT_DIALOG 104 +#define IDD_BPCNT 105 +#define IDD_DEBUG 108 +#define IDI_ICON 108 +#define IDD_MEMORY 110 +#define IDD_VU0REGS 111 +#define IDD_JUMP 112 +#define SPLASH_LOGO 113 +#define IDD_VU0INTEGER 113 +#define IDD_GPREGS 114 +#define IDD_CP0REGS 115 +#define IDD_CP1REGS 116 +#define IDD_VU1INTEGER 117 +#define IDD_VU1REGS 118 +#define IDD_LOGGING 119 +#define IDD_CMDLINE 120 +#define IDD_RDEBUGPARAMS 121 +#define ID_DEBUG_REMOTEDEBUGGING 122 +#define IDD_RDEBUG 123 +#define IDD_DIALOGBAR 124 +#define IDD_IOP_DEBUG 125 +#define IDD_CPUDLG 126 +#define IDD_ADVANCED 127 +#define IDD_IOPREGS 128 +#define IDD_USERNAME 129 +#define IDB_PS2SILVER 132 +#define IDD_CHEATS 133 +#define IDD_DUMP 136 +#define IDD_DUMPMEM 137 +#define IDD_PATCHBROWSER 138 +#define IDD_FINDER 174 +#define IDD_ADD 175 +#define IDC_MEM_SCROLL 1001 +#define IDC_EXECBP 1001 +#define IDC_CNTBP 1002 +#define IDC_MCD2 1004 +#define IDC_VU0_VF00 1005 +#define IDC_MCD1 1005 +#define IDC_VU0_VF01 1006 +#define IDC_MCDSEL1 1006 +#define IDC_VU0_VF02 1007 +#define IDC_MCDSEL2 1007 +#define IDC_VU0_VF03 1008 +#define IDC_VU0_VF04 1009 +#define IDC_DEBUG_DISASM 1010 +#define IDC_VU0_VF05 1010 +#define IDC_VU0_VF06 1011 +#define IDC_VU0_VF07 1012 +#define IDC_VU0_VF08 1013 +#define IDC_PCSX_ABOUT_TEXT 1014 +#define IDC_PSXOUT 1014 +#define IDC_VU0_VF09 1014 +#define IDC_CPU 1015 +#define IDC_VU0_VF10 1015 +#define IDC_VSYNCHACK 1016 +#define IDC_VU0_VF11 1016 +#define IDC_VU0_VF12 1017 +#define IDC_VU0_VF13 1018 +#define IDC_VU0_VF14 1019 +#define IDC_CP07 1020 +#define IDC_VU0_VF15 1020 +#define IDC_VU0_VF16 1021 +#define IDC_VU0_VF17 1022 +#define IDC_VU0_VF18 1023 +#define IDC_VU0_VF19 1024 +#define IDC_VU0_VF20 1025 +#define IDC_VU0_VF21 1026 +#define IDC_VU0_VF22 1027 +#define IDC_VU0_VF23 1028 +#define IDC_DEBUG_CLOSE 1029 +#define IDC_VU0_VF24 1029 +#define IDC_DEBUG_STEP 1030 +#define IDC_VU0_VF25 1030 +#define IDC_DEBUG_SKIP 1031 +#define IDC_VU0_VF26 1031 +#define IDC_DEBUG_GO 1032 +#define IDC_VU0_VF27 1032 +#define IDC_DEBUG_BP_EXEC 1033 +#define IDC_VU0_VF28 1033 +#define IDC_CP021 1034 +#define IDC_DEBUG_SCROLL 1034 +#define IDC_VU0_VF29 1034 +#define IDC_CP022 1035 +#define IDC_DEBUG_RESETTOPC 1035 +#define IDC_VU0_VF30 1035 +#define IDC_CP023 1036 +#define IDC_FPU_ACC 1036 +#define IDC_DEBUG_JUMP 1036 +#define IDC_MEMORY_CLOSE 1036 +#define IDC_VU0_VF31 1036 +#define IDC_CP024 1037 +#define IDC_DEBUG_BREAK 1037 +#define IDC_MEMORY_ADDR 1037 +#define IDC_DEBUG_LOG 1037 +#define IDC_CP025 1038 +#define IDC_MEMORY_DUMP 1038 +#define IDC_DEBUG_BP_COUNT 1038 +#define IDC_VU0_VI00 1038 +#define IDC_DEBUG_L1 1039 +#define IDC_VU0_VI01 1039 +#define IDC_ADDRESS_PATCH 1039 +#define IDC_DEBUG_L2 1040 +#define IDC_VU0_VI02 1040 +#define IDC_DATA_PATCH 1040 +#define IDC_DEBUG_L3 1041 +#define IDC_VU0_VI03 1041 +#define IDC_FRAMEMCD1 1041 +#define IDC_DEBUG_L4 1042 +#define IDC_VU0_VI04 1042 +#define IDC_FRAMEMCD2 1042 +#define IDC_DEBUG_L5 1043 +#define IDC_VU0_VI05 1043 +#define IDC_CP031 1044 +#define IDC_DEBUG_L6 1044 +#define IDC_VU0_VI06 1044 +#define IDC_DEBUG_L7 1045 +#define IDC_VU0_VI07 1045 +#define IDC_DEBUG_L8 1046 +#define IDC_VU0_VI08 1046 +#define IDC_DEBUG_L9 1047 +#define IDC_GPR0 1047 +#define IDC_VU0_VI09 1047 +#define IDC_DEBUG_L10 1048 +#define IDC_GPR1 1048 +#define IDC_VU0_VI10 1048 +#define IDC_DEBUG_L11 1049 +#define IDC_GPR2 1049 +#define IDC_VU0_VI11 1049 +#define IDC_DEBUG_L12 1050 +#define IDC_GPR3 1050 +#define IDC_VU0_VI12 1050 +#define IDC_DEBUG_L13 1051 +#define IDC_GPR4 1051 +#define IDC_VU0_VI13 1051 +#define IDC_DEBUG_L14 1052 +#define IDC_GPR5 1052 +#define IDC_LISTGS 1052 +#define IDC_VU0_VI14 1052 +#define IDC_DEBUG_L15 1053 +#define IDC_GPR6 1053 +#define IDC_LISTSPU 1053 +#define IDC_VU0_VI15 1053 +#define IDC_LISTSPU2 1053 +#define IDC_DEBUG_L16 1054 +#define IDC_GPR7 1054 +#define IDC_LISTCDR 1054 +#define IDC_VU0_VI16 1054 +#define IDC_LISTCDVD 1054 +#define IDC_DEBUG_L17 1055 +#define IDC_GPR8 1055 +#define IDC_LISTBIOS 1055 +#define IDC_VU0_VI17 1055 +#define IDC_DEBUG_L18 1056 +#define IDC_GPR9 1056 +#define IDC_CONFIGGS 1056 +#define IDC_VU0_VI18 1056 +#define IDC_DEBUG_L19 1057 +#define IDC_GPR10 1057 +#define IDC_TESTGS 1057 +#define IDC_VU0_VI19 1057 +#define IDC_DEBUG_L20 1058 +#define IDC_ABOUTGS 1058 +#define IDC_VU0_VI20 1058 +#define IDC_DEBUG_L21 1059 +#define IDC_CONFIGSPU 1059 +#define IDC_VU0_VI21 1059 +#define IDC_CONFIGSPU2 1059 +#define IDC_DEBUG_L22 1060 +#define IDC_TESTSPU 1060 +#define IDC_VU0_VI22 1060 +#define IDC_TESTSPU2 1060 +#define IDC_DEBUG_L23 1061 +#define IDC_ABOUTSPU 1061 +#define IDC_VU0_VI23 1061 +#define IDC_ABOUTSPU2 1061 +#define IDC_DEBUG_L24 1062 +#define IDC_CONFIGCDR 1062 +#define IDC_VU0_VI24 1062 +#define IDC_CONFIGCDVD 1062 +#define IDC_DEBUG_L25 1063 +#define IDC_GPR11 1063 +#define IDC_TESTCDR 1063 +#define IDC_VU0_VI25 1063 +#define IDC_TESTCDVD 1063 +#define IDC_DEBUG_L26 1064 +#define IDC_ABOUTCDR 1064 +#define IDC_VU0_VI26 1064 +#define IDC_ABOUTCDVD 1064 +#define IDC_DEBUG_L27 1065 +#define IDC_VU0_VI27 1065 +#define IDC_LISTDEV9 1065 +#define IDC_DEBUG_L28 1066 +#define IDC_LISTPAD 1066 +#define IDC_LISTPAD1 1066 +#define IDC_VU0_VI28 1066 +#define IDC_DEBUG_L29 1067 +#define IDC_CONFIGPAD 1067 +#define IDC_CONFIGPAD1 1067 +#define IDC_VU0_VI29 1067 +#define IDC_DEBUG_R1 1068 +#define IDC_GPR12 1068 +#define IDC_TESTPAD 1068 +#define IDC_TESTPAD1 1068 +#define IDC_VU0_VI30 1068 +#define IDC_DEBUG_R2 1069 +#define IDC_GPR13 1069 +#define IDC_ABOUTPAD 1069 +#define IDC_ABOUTPAD1 1069 +#define IDC_VU0_VI31 1069 +#define IDC_DEBUG_R3 1070 +#define IDC_GPR14 1070 +#define IDC_LISTPAD2 1070 +#define IDC_VU0_ACC 1070 +#define IDC_DEBUG_R4 1071 +#define IDC_GPR15 1071 +#define IDC_CONFIGPAD2 1071 +#define IDC_VU1_VF00 1071 +#define IDC_DEBUG_R5 1072 +#define IDC_GPR16 1072 +#define IDC_TESTPAD2 1072 +#define IDC_VU1_VF01 1072 +#define IDC_DEBUG_R6 1073 +#define IDC_GPR17 1073 +#define IDC_ABOUTPAD2 1073 +#define IDC_VU1_VF02 1073 +#define IDC_DEBUG_R7 1074 +#define IDC_GPR18 1074 +#define IDC_VU1_VF03 1074 +#define IDC_CONFIGDEV9 1074 +#define IDC_DEBUG_R8 1075 +#define IDC_GPR19 1075 +#define IDC_VU1_VF04 1075 +#define IDC_TESTDEV9 1075 +#define IDC_DEBUG_R9 1076 +#define IDC_GPR20 1076 +#define IDC_VU1_VF05 1076 +#define IDC_ABOUTDEV9 1076 +#define IDC_DEBUG_R10 1077 +#define IDC_GPR21 1077 +#define IDC_VU1_VF06 1077 +#define IDC_LISTUSB 1077 +#define IDC_DEBUG_R11 1078 +#define IDC_GPR22 1078 +#define IDC_VU1_VF07 1078 +#define IDC_CONFIGUSB 1078 +#define IDC_DEBUG_R12 1079 +#define IDC_GPR23 1079 +#define IDC_VU1_VF08 1079 +#define IDC_TESTUSB 1079 +#define IDC_DEBUG_R13 1080 +#define IDC_GPR24 1080 +#define IDC_VU1_VF09 1080 +#define IDC_ABOUTUSB 1080 +#define IDC_DEBUG_R14 1081 +#define IDC_GPR25 1081 +#define IDC_VU1_VF10 1081 +#define IDC_LISTFW 1081 +#define IDC_DEBUG_R15 1082 +#define IDC_GPR26 1082 +#define IDC_VU1_VF11 1082 +#define IDC_CONFIGFW 1082 +#define IDC_DEBUG_R16 1083 +#define IDC_GPR27 1083 +#define IDC_VU1_VF12 1083 +#define IDC_TESTFW 1083 +#define IDC_DEBUG_R17 1084 +#define IDC_GPR28 1084 +#define IDC_VU1_VF13 1084 +#define IDC_ABOUTFW 1084 +#define IDC_DEBUG_R18 1085 +#define IDC_GPR29 1085 +#define IDC_VU1_VF14 1085 +#define IDC_DEBUG_R19 1086 +#define IDC_GPR30 1086 +#define IDC_VU1_VF15 1086 +#define IDC_DEBUG_R20 1087 +#define IDC_GPR31 1087 +#define IDC_VU1_VF16 1087 +#define IDC_DEBUG_R21 1088 +#define IDC_VU1_VF17 1088 +#define IDC_DEBUG_R22 1089 +#define IDC_GPR_PC 1089 +#define IDC_VU1_VF18 1089 +#define IDC_DEBUG_R23 1090 +#define IDC_VU1_VF19 1090 +#define IDC_DEBUG_R24 1091 +#define IDC_GPR_HI 1091 +#define IDC_VU1_VF20 1091 +#define IDC_DEBUG_R25 1092 +#define IDC_GPR_LO 1092 +#define IDC_VU1_VF21 1092 +#define IDC_CP00 1093 +#define IDC_DEBUG_R26 1093 +#define IDC_VU1_VF22 1093 +#define IDC_CP01 1094 +#define IDC_DEBUG_R27 1094 +#define IDC_VU1_VF23 1094 +#define IDC_CP02 1095 +#define IDC_DEBUG_R28 1095 +#define IDC_VU1_VF24 1095 +#define IDC_CP03 1096 +#define IDC_DEBUG_R29 1096 +#define IDC_VU1_VF25 1096 +#define IDC_CP04 1097 +#define IDC_DEBUG_DUMP 1097 +#define IDC_JUMP_PC 1097 +#define IDC_VU1_VF26 1097 +#define IDC_CP05 1098 +#define IDC_DEBUG_DUMPRAW 1098 +#define IDC_DUMP_END 1098 +#define IDC_VU1_VF27 1098 +#define IDC_DEBUG_LOGGING 1098 +#define IDC_DEBUG_MEMORY 1098 +#define IDC_CP06 1099 +#define IDC_DUMP_FNAME 1099 +#define IDC_DEBUG_BP_CLEAR 1099 +#define IDC_VU1_VF28 1099 +#define IDC_CP08 1100 +#define IDC_VU1_VF29 1100 +#define IDC_DUMP_ENDIOP 1100 +#define IDC_CP09 1101 +#define IDC_VU1_VF30 1101 +#define IDC_DUMP_FNAMEIOP 1101 +#define IDC_CP010 1102 +#define IDC_VU1_VF31 1102 +#define IDC_CP011 1103 +#define IDC_VU1_VI00 1103 +#define IDC_CP012 1104 +#define IDC_VU1_VI01 1104 +#define IDC_CP013 1105 +#define IDC_VU1_VI02 1105 +#define IDC_CP014 1106 +#define IDC_VU1_VI03 1106 +#define IDC_CP015 1107 +#define IDC_VU1_VI04 1107 +#define IDC_CP016 1108 +#define IDC_VU1_VI05 1108 +#define IDC_CP017 1109 +#define IDC_VU1_VI06 1109 +#define IDC_CP018 1110 +#define IDC_VU1_VI07 1110 +#define IDC_CP019 1111 +#define IDC_VU1_VI08 1111 +#define IDC_CP020 1112 +#define IDC_VU1_VI09 1112 +#define IDC_CP026 1113 +#define IDC_VU1_VI10 1113 +#define IDC_CP027 1114 +#define IDC_VU1_VI11 1114 +#define IDC_CP028 1115 +#define IDC_VU1_VI12 1115 +#define IDC_CP029 1116 +#define IDC_VU1_VI13 1116 +#define IDC_CP030 1117 +#define IDC_VU1_VI14 1117 +#define IDC_FP0 1118 +#define IDC_VU1_VI15 1118 +#define IDC_FP1 1119 +#define IDC_VU1_VI16 1119 +#define IDC_FP2 1120 +#define IDC_VU1_VI17 1120 +#define IDC_FP3 1121 +#define IDC_VU1_VI18 1121 +#define IDC_FP4 1122 +#define IDC_VU1_VI19 1122 +#define IDC_FP5 1123 +#define IDC_VU1_VI20 1123 +#define IDC_FP6 1124 +#define IDC_VU1_VI21 1124 +#define IDC_FP7 1125 +#define IDC_VU1_VI22 1125 +#define IDC_FP8 1126 +#define IDC_VU1_VI23 1126 +#define IDC_FP9 1127 +#define IDC_VU1_VI24 1127 +#define IDC_FP10 1128 +#define IDC_VU1_VI25 1128 +#define IDC_FP11 1129 +#define IDC_VU1_VI26 1129 +#define IDC_FP12 1130 +#define IDC_VU1_VI27 1130 +#define IDC_FP13 1131 +#define IDC_VU1_VI28 1131 +#define IDC_FP14 1132 +#define IDC_VU1_VI29 1132 +#define IDC_FP15 1133 +#define IDC_VU1_VI30 1133 +#define IDC_FP16 1134 +#define IDC_VU1_VI31 1134 +#define IDC_FP17 1135 +#define IDC_VU1_ACC 1135 +#define IDC_FP18 1136 +#define IDC_FP19 1137 +#define IDC_FP20 1138 +#define IDC_FP21 1139 +#define IDC_FP22 1140 +#define IDC_FP23 1141 +#define IDC_FP24 1142 +#define IDC_FP25 1143 +#define IDC_FP26 1144 +#define IDC_FP27 1145 +#define IDC_FP28 1146 +#define IDC_FP29 1147 +#define IDC_FP30 1148 +#define IDC_FP31 1149 +#define IDC_FCR0 1150 +#define IDC_FCR31 1151 +#define IDC_CMDLINE 1155 +#define IDC_PORT 1157 +#define IDC_COMMUNICATION 1158 +#define IDC_CLEAR 1160 +#define IDC_DEBUGBIOS 1161 +#define IDC_EEPC 1162 +#define IDC_IOPPC 1163 +#define IDC_PCSX_ABOUT_GREETS 1163 +#define IDC_PCSX_ABOUT_AUTHORS 1164 +#define IDC_EECYCLE 1164 +#define IDC_GRAPHICS 1165 +#define IDC_IOPCYCLE 1165 +#define IDC_SOUND 1166 +#define IDC_FIRSTCONTROLLER 1167 +#define IDC_SECONDCONTROLLER 1168 +#define IDC_CDVDROM 1169 +#define IDC_BIOS 1170 +#define IDC_MISCOPTIONS 1171 +#define IDC_DEV9 1171 +#define IDC_DUMP_START 1172 +#define IDC_TIP 1172 +#define IDC_USB 1172 +#define IDC_TEXT 1173 +#define IDC_DUMP_STARTIOP 1173 +#define IDC_CPUOP 1175 +#define IDC_DEBUGEE 1176 +#define IDC_DEBUGIOP 1177 +#define IDC_STOPAT 1178 +#define IDC_STOPAFTER 1179 +#define IDC_PATCH 1180 +#define IDC_REGCACHE 1181 +#define IDC_RECOPTIONS 1182 +#define IDC_PADHACK 1183 +#define IDC_VUREC 1184 +#define IDC_LOGS 1186 +#define IDDELREG 1187 +#define IDC_TAB_DEBUG 1188 +#define IDC_DUMPMEM_FNAME 1188 +#define IDC_DUMPMEM_END 1189 +#define IDC_DUMPMEM_START 1190 +#define IDC_DUMPRAW 1191 +#define IDC_DEBUG_DISASM_IOP 1193 +#define IDC_DEBUG_SCROLL_IOP 1194 +#define IDC_THPRIORITY 1195 +#define IDC_EXITPB 1196 +#define IDC_CPUOPTION 1196 +#define IDC_VENDORNAME 1197 +#define IDC_FAMILYNAME 1198 +#define IDC_CPUSPEEDNAME 1199 +#define IDC_FEATURESNAME 1200 +#define IDC_VENDORINPUT 1201 +#define IDC_FAMILYINPUT 1202 +#define IDC_CPUSPEEDINPUT 1203 +#define IDC_FEATURESINPUT 1204 +#define IDC_RADIOINTEPRETER 1205 +#define IDC_RADIORECOMPILER 1206 +#define IDC_RADIORECOMPILERVU 1207 +#define IDC_REGCACHING 1208 +#define IDC_INTERLACEHACK 1210 +#define IDC_SAFECOUNTERS 1211 +#define IDC_IOPCLK 1213 +#define IDC_ADVRESET 1214 +#define IDC_FASTIOPCLK 1215 +#define IDC_CHECK2 1217 +#define IDC_SPU2HACK 1218 +#define IDC_VSYNCRATE 1219 +#define IDC_IOPGPR0 1220 +#define IDC_IOPGPR1 1221 +#define IDC_IOPGPR2 1222 +#define IDC_IOPGPR16 1223 +#define IDC_IOPGPR17 1224 +#define IDC_IOPGPR18 1225 +#define IDC_IOPGPR19 1226 +#define IDC_IOPGPR20 1227 +#define IDC_IOPGPR21 1228 +#define IDC_IOPGPR22 1229 +#define IDC_IOPGPR23 1230 +#define IDC_IOPGPR24 1231 +#define IDC_IOPGPR25 1232 +#define IDC_IOPGPR26 1233 +#define IDC_IOPGPR27 1234 +#define IDC_IOPGPR28 1235 +#define IDC_IOPGPR29 1236 +#define IDC_IOPGPR30 1237 +#define IDC_IOPGPR31 1238 +#define IDC_IOPGPR_LO 1239 +#define IDC_IOPGPR_HI 1240 +#define IDC_IOPGPR_PC 1241 +#define IDC_IOPGPR15 1242 +#define IDC_IOPGPR14 1243 +#define IDC_IOPGPR13 1244 +#define IDC_IOPGPR12 1245 +#define IDC_IOPGPR11 1246 +#define IDC_IOPGPR10 1247 +#define IDC_IOPGPR9 1248 +#define IDC_IOPGPR8 1249 +#define IDC_IOPGPR7 1250 +#define IDC_IOPGPR6 1251 +#define IDC_IOPGPR5 1252 +#define IDC_IOPGPR4 1253 +#define IDC_BIOSDIR 1254 +#define IDC_IOPGPR3 1254 +#define IDC_PLUGINSDIR 1255 +#define IDC_EDIT2 1256 +#define IDC_BIAS 1256 +#define IDC_USER_NAME 1257 +#define IDC_CPU_MULTI 1258 +#define IDC_CPU_MULTI2 1259 +#define IDC_CPU_GSMULTI 1259 +#define IDC_PS2SILVER_RECT 1259 +#define IDC_CPU_MULTI3 1260 +#define IDC_CPU_FRAMELIMIT 1260 +#define IDC_CPU_FRAMELIMIT2 1261 +#define IDC_CPU_EEREC 1262 +#define IDC_CPU_VU1REC 1263 +#define IDC_CHECK4 1264 +#define IDC_CPU_VU0REC 1264 +#define IDC_CPU_FL_NORMAL 1265 +#define IDC_IDC_CPU_FL_LIMIT 1266 +#define IDC_CPU_FL_LIMIT 1266 +#define IDC_CPU_FL_SKIP 1267 +#define IDC_CPU_FL_SKIPVU 1268 +#define IDC_CPU_VUGROUP 1269 +#define IDC_MONTHCALENDAR1 1270 +#define IDC_GROUPS 1272 +#define IDC_PATCHES 1273 +#define IDC_LOG 1500 +#define IDC_CPULOG 1500 +#define IDC_MEMLOG 1501 +#define IDC_HWLOG 1502 +#define IDC_DMALOG 1503 +#define IDC_BIOSLOG 1504 +#define IDC_ELFLOG 1505 +#define IDC_FPULOG 1506 +#define IDC_MMILOG 1507 +#define IDC_VU0LOG 1508 +#define IDC_COP0LOG 1509 +#define IDC_VIFLOG 1510 +#define IDC_SPRLOG 1511 +#define IDC_GIFLOG 1512 +#define IDC_SIFLOG 1513 +#define IDC_IPULOG 1514 +#define IDC_VUMICROLOG 1515 +#define IDC_RPCSERVICES 1516 +#define IDC_IOPLOG 1520 +#define IDC_IOPMEMLOG 1521 +#define IDC_IOPHWLOG 1522 +#define IDC_IOPBIOSLOG 1523 +#define IDC_IOPDMALOG 1524 +#define IDC_IOPPADLOG 1525 +#define IDC_IOPGTELOG 1526 +#define IDC_IOPCDRLOG 1527 +#define IDC_IOPGPULOG 1527 +#define IDC_IOPCNTLOG 1529 +#define IDC_EECNTLOG 1530 +#define IDC_SYMLOG 1531 +#define IDC_STDOUTPUTLOG 1532 +#define IDC_SEARCH 1701 +#define IDC_VALUE 1702 +#define IDC_OLD 1703 +#define IDC_SET 1704 +#define IDC_EQ 1705 +#define IDC_GT 1706 +#define IDC_LT 1707 +#define IDC_GE 1708 +#define IDC_LE 1709 +#define IDC_NE 1710 +#define IDC_EE 1711 +#define IDC_IOP 1712 +#define IDC_RESET 1713 +#define IDC_ADD 1714 +#define IDC_LRESULTS 1715 +#define IDC_STATUS 1716 +#define IDC_FW 1716 +#define IDC_FRAMELIMIT 1716 +#define IDC_UNSIGNED 1717 +#define IDC_8B 1718 +#define IDC_16B 1719 +#define IDC_32B 1720 +#define IDC_64B 1721 +#define IDC_RESULTS 1722 +#define IDC_NAME 1723 +#define IDC_ADDR 1725 +#define IDC_MATCHES 1726 +#define ID_FILEOPEN 40001 +#define ID_DEBUG_MEMORY_DUMP 40002 +#define ID_FILE_EXIT 40003 +#define ID_RUN_EXECUTE 40004 +#define ID_RUN_RESET 40005 +#define ID_HELP_ABOUT 40006 +#define ID_CONFIG_CONFIGURE 40007 +#define ID_CONFIG_CPU 40008 +#define ID_CONFIG_GRAPHICS 40009 +#define ID_CONFIG_CONTROLLERS 40010 +#define ID_DEBUG_LOGGING 40011 +#define ID_CONFIG_SOUND 40012 +#define ID_CONFIG_CDVDROM 40013 +#define ID_RUN_CMDLINE 40014 +#define ID_FILE_RUNCD 40015 +#define ID_DEBUG_ENTERDEBUGGER 40016 +#define ID_CONFIG_DEV9 40017 +#define ID_FILE_STATES_LOAD_SLOT1 40018 +#define ID_FILE_STATES_LOAD_SLOT2 40019 +#define ID_FILE_STATES_LOAD_SLOT3 40020 +#define ID_FILE_STATES_LOAD_SLOT4 40021 +#define ID_FILE_STATES_LOAD_SLOT5 40022 +#define ID_FILE_STATES_LOAD_OTHER 40023 +#define ID_FILE_STATES_SAVE_SLOT1 40024 +#define ID_FILE_STATES_SAVE_SLOT2 40025 +#define ID_FILE_STATES_SAVE_SLOT3 40026 +#define ID_FILE_STATES_SAVE_SLOT4 40027 +#define ID_FILE_STATES_SAVE_SLOT5 40028 +#define ID_FILE_STATES_SAVE_OTHER 40029 +#define ID_CONFIG_FW 40030 +#define ID_CONFIG_USB 40031 +#define ID_CONFIG_MEMCARDS 40032 +#define IDC_FORMAT1 40033 +#define IDC_FORMAT2 40034 +#define IDC_LIST1 40035 +#define IDC_LIST2 40036 +#define IDC_RELOAD1 40037 +#define IDC_RELOAD2 40038 +#define IDC_COPYTO2 40039 +#define IDC_COPYTO1 40040 +#define IDC_PASTE 40041 +#define IDC_DELETE1 40042 +#define IDC_DELETE2 40043 +#define ID_PATCHBROWSER 40044 +#define ID_NEWPATCH 40045 +#define IDC_NEWPATCH 40045 +#define IDC_PATCHTEXT 40046 +#define IDC_SAVEPATCH 40047 +#define IDC_REFRESHPATCHLIST 40048 +#define IDC_PATCHCRCLIST 40049 +#define IDC_PATCHNAMELIST 40050 +#define IDC_GAMENAMESEARCH 40051 +#define IDC_SEARCHPATCHTEXT 40052 +#define ID_PROCESSLOW 40053 +#define ID_PROCESSNORMAL 40054 +#define ID_PROCESSHIGH 40055 +#define ID_CONSOLE 40056 +#define ID_PATCHES 40057 +#define ID_CONFIG_ADVANCED 40058 +#define ID_INTERLACEHACK 40059 +#define ID_SAFECNTS 40060 +#define ID_SPU2HACK 40061 +#define ID_VSYNCRATE 40062 +#define ID_HELP_HELP 40063 +#define ID_CHEAT_FINDER_SHOW 40100 +#define ID_CHEAT_BROWSER_SHOW 40101 +#define ID_LANGS 50000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 134 +#define _APS_NEXT_COMMAND_VALUE 40018 +#define _APS_NEXT_CONTROL_VALUE 1275 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/pcsx2/x86/Makefile.am b/pcsx2/x86/Makefile.am new file mode 100644 index 0000000..bfdbe8c --- /dev/null +++ b/pcsx2/x86/Makefile.am @@ -0,0 +1,22 @@ +INCLUDES = -I@srcdir@/../ +noinst_LIBRARIES = libx86recomp.a + +# have to add the sources instead of making a library since the linking is complicated +if X86_64 +archfiles = ix86-64/iR5900-64.c ix86-64/iR5900AritImm-64.c ix86-64/iR5900Jump-64.c \ +ix86-64/iR5900Move-64.c ix86-64/iR5900Shift-64.c ix86-64/iR5900Arit-64.c ix86-64/iR5900Branch-64.c \ +ix86-64/iR5900LoadStore-64.c ix86-64/iR5900MultDiv-64.c ix86-64/iCore-64.cpp ix86-64/aR5900-64.S +else +archfiles = ix86-32/iR5900-32.c ix86-32/iR5900AritImm.c ix86-32/iR5900Jump.c \ +ix86-32/iR5900Move.c ix86-32/iR5900Shift.c ix86-32/iR5900Arit.c ix86-32/iR5900Branch.c \ +ix86-32/iR5900LoadStore.c ix86-32/iR5900MultDiv.c ix86-32/iCore-32.cpp ix86-32/aR5900-32.S +endif + +libx86recomp_a_SOURCES = iCOP2.c iCP0.c iFPU.c iHw.c iMMI.c iPsxHw.c iPsxMem.c \ +ir5900tables.c iVU0micro.c iVU1micro.c iVUmicro.c \ +iCore.cpp iGS.cpp iR3000A.cpp iR3000Atables.cpp iVif.cpp iVUzerorec.cpp \ +fast_routines.S aR3000A.S aVUzerorec.S aVif.S $(archfiles) + +libx86recomp_a_DEPENDENCIES = ix86/libix86.a + +SUBDIRS = ix86 diff --git a/pcsx2/x86/README b/pcsx2/x86/README new file mode 100644 index 0000000..437ee9a --- /dev/null +++ b/pcsx2/x86/README @@ -0,0 +1,12 @@ +PCSX2 x86 Recompilers - zerofrog(@gmail.com) + +There are two types of x86 recompilers: x86-32 and x86-64. The code that both of them share is in the x86/ directory. Code for x86-32 is in the ix86-32/ and same goes for x86-64. The ix86/ dirctory contains the low level translation of x86 instructions to actual code, it is written to be used for both architectures. There are a lot of places where it was hard to separate 32bit from 64bit recompilers, so a lot of functions are surrounded by "#if(n)def __x86_64__" statements. + +It would be simple if the story ended here, but hte x86 recompilers use a lot of low level assembly routines, meaning that assembly has to be compiled for both windows x32/x64 versions and linux x32/x64 versions. + +For windows, the masm assembler is used (*.asm files) +For linux, gcc is used (*.S files) + +Both assemblers use very different syntax, also some routines in x86-64 differ a lot from their 32bit counterparts. Therefore, you might see the same function implemented up to 4 times in assembly. + +(no, it's not fun maintaining 4 versions of the same thing... and it might be easier to use nasm, but that probably has its own unforseeable problems) \ No newline at end of file diff --git a/pcsx2/x86/aR3000A.S b/pcsx2/x86/aR3000A.S new file mode 100644 index 0000000..7a6ac0d --- /dev/null +++ b/pcsx2/x86/aR3000A.S @@ -0,0 +1,440 @@ +// iR3000A.c assembly routines +// zerofrog(@gmail.com) +.intel_syntax + +.extern psxRegs +.extern psxRecLUT +.extern psxRecRecompile +.extern b440 +.extern b440table + +#define PS2MEM_BASE_ 0x18000000 // has to match Memory.h + +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +#define BASEBLOCK_SIZE 2 // in dwords +#define PCOFFSET 0x208 + +#define PSX_MEMMASK 0x5fffffff + +#ifdef __x86_64__ + +.globl recCheckF440 + .type recCheckF440, @function +recCheckF440: + add dword ptr [b440], 1 + mov %eax, dword ptr [b440] + sub %eax, 3 + mov %edx, 31 + + cmp %eax, 27 + ja WriteVal + shl %eax, 2 + cdqe + mov %edx, dword ptr [%rax+b440table] + +WriteVal: + mov %rax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [%rax], %edx + ret + +#define REG_PC %edi +#define REG_BLOCK %r12 +#define REG_BLOCKd %r12d + +.extern EEsCycle + +.globl R3000AExecute + .type R3000AExecute, @function +R3000AExecute: + + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + //while (EEsCycle > 0) { +Execute_CheckCycles: + cmp dword ptr [EEsCycle], 0 + jle Execute_Exit + + // calc PSX_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [psxRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + mov %r8d, [REG_BLOCK+4] + mov %r9d, REG_PC + and %r8d, 0x5fffffff + and %r9d, 0x5fffffff + cmp %r8d, %r9d + jne Execute_Recompile + mov %edx, [REG_BLOCK] + and %rdx, 0xfffffff // pFnptr + jnz Execute_Function + +Execute_Recompile: + call psxRecRecompile + mov %edx, [REG_BLOCK] + and %rdx, 0xfffffff // pFnptr + +Execute_Function: + call %rdx + + jmp Execute_CheckCycles + +Execute_Exit: + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + ret + + +// jumped to when invalid psxpc address +.globl psxDispatcher + .type psxDispatcher, @function +psxDispatcher: + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + push %rdx + + // calc PSX_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [psxRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // check if startpc&PSX_MEMMASK == psxRegs.pc&PSX_MEMMASK + mov %eax, REG_PC + mov %edx, [REG_BLOCK+BLOCKTYPE_STARTPC] + and %eax, PSX_MEMMASK // remove higher bits + and %edx, PSX_MEMMASK + cmp %eax, %edx + je psxDispatcher_CheckPtr + + // recompile + call psxRecRecompile +psxDispatcher_CheckPtr: + mov REG_BLOCKd, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test REG_BLOCKd, REG_BLOCKd + jnz psxDispatcher_CallFn + // throw an exception + int 10 + +psxDispatcher_CallFn: +#endif + + and REG_BLOCK, 0x0fffffff + mov %rdx, REG_BLOCK + pop %rcx // x86Ptr to mod + sub %rdx, %rcx + sub %rdx, 4 + mov [%rcx], %edx + + jmp REG_BLOCK + +.globl psxDispatcherClear + .type psxDispatcherClear, @function +psxDispatcherClear: + // %EDX contains the current psxpc + mov dword ptr [psxRegs + PCOFFSET], %edx + mov %eax, %edx + + // calc PSX_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov REG_BLOCKd, %edx + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // check if startpc&PSX_MEMMASK == psxRegs.pc&PSX_MEMMASK + mov REG_PC, %edx + mov %eax, REG_PC + mov %edx, [REG_BLOCK+BLOCKTYPE_STARTPC] + and %eax, PSX_MEMMASK // remove higher bits + and %edx, PSX_MEMMASK + cmp %eax, %edx + jne psxDispatcherClear_Recompile + + mov %eax, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test %eax, %eax + jnz psxDispatcherClear_CallFn + // throw an exception + int 10 + +psxDispatcherClear_CallFn: +#endif + + and %rax, 0x0fffffff + jmp %rax + +psxDispatcherClear_Recompile: + call psxRecRecompile + mov %eax, dword ptr [REG_BLOCK] + + // r15 holds the prev x86 pointer + and %rax, 0x0fffffff + mov byte ptr [%r15], 0xe9 // jmp32 + mov %rdx, %rax + sub %rdx, %r15 + sub %rdx, 5 + mov [%r15+1], %edx + + jmp %rax + +// called when jumping to variable psxpc address +.globl psxDispatcherReg + .type psxDispatcherReg, @function +psxDispatcherReg: + + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov %eax, dword ptr [psxRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // check if startpc == psxRegs.pc + cmp REG_PC, dword ptr [REG_BLOCK+BLOCKTYPE_STARTPC] + jne psxDispatcherReg_recomp + + mov REG_BLOCKd, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test %eax, %eax + jnz psxDispatcherReg_CallFn2 + // throw an exception + int 10 +psxDispatcherReg_CallFn2: +#endif + and REG_BLOCK, 0x0fffffff + jmp REG_BLOCK // fnptr + +psxDispatcherReg_recomp: + call psxRecRecompile + + mov %eax, dword ptr [REG_BLOCK] + and %rax, 0x0fffffff + jmp %rax // fnprt + +#else // not x86-64 + +.globl recCheckF440 + .type recCheckF440, @function +recCheckF440: + add dword ptr [b440], 1 + mov %eax, [b440] + sub %eax, 3 + mov %edx, 31 + + cmp %eax, 27 + ja WriteVal + shl %eax, 2 + mov %edx, dword ptr [%eax+b440table] + +WriteVal: + mov %eax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [%eax], %edx + ret + +#define REG_PC %ecx +#define REG_BLOCK %esi + +// jumped to when invalid psxpc address +.globl psxDispatcher + .type psxDispatcher, @function +psxDispatcher: + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + push %edx + + // calc PSX_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [psxRegs + PCOFFSET] + mov REG_BLOCK, %eax + mov REG_PC, %eax + shr %eax, 16 + and REG_BLOCK, 0xffff + shl %eax, 2 + add %eax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, dword ptr [%eax] + + // check if startpc&PSX_MEMMASK == psxRegs.pc&PSX_MEMMASK + mov %eax, REG_PC + mov %edx, [REG_BLOCK+BLOCKTYPE_STARTPC] + and %eax, PSX_MEMMASK // remove higher bits + and %edx, PSX_MEMMASK + cmp %eax, %edx + je psxDispatcher_CheckPtr + + // recompile + push REG_BLOCK + push REG_PC // psxpc + call psxRecRecompile + add %esp, 4 // pop old param + pop REG_BLOCK +psxDispatcher_CheckPtr: + mov REG_BLOCK, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test REG_BLOCK, REG_BLOCK + jnz psxDispatcher_CallFn + // throw an exception + int 10 + +psxDispatcher_CallFn: +#endif + + and REG_BLOCK, 0x0fffffff + mov %edx, REG_BLOCK + pop %ecx // x86Ptr to mod + sub %edx, %ecx + sub %edx, 4 + mov dword ptr [%ecx], %edx + + jmp REG_BLOCK + +.globl psxDispatcherClear + .type psxDispatcherClear, @function +psxDispatcherClear: + // %EDX contains the current psxpc + mov dword ptr [psxRegs + PCOFFSET], %edx + + // calc PSX_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, %edx + mov REG_BLOCK, %edx + shr %eax, 16 + and REG_BLOCK, 0xffff + shl %eax, 2 + add %eax, [psxRecLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, dword ptr [%eax]; + + // check if startpc&PSX_MEMMASK == psxRegs.pc&PSX_MEMMASK + mov %eax, %edx + mov REG_PC, %edx + mov %edx, [REG_BLOCK+BLOCKTYPE_STARTPC] + and %eax, PSX_MEMMASK // remove higher bits + and %edx, PSX_MEMMASK + cmp %eax, %edx + jne psxDispatcherClear_Recompile + + add %esp, 4 // ignore stack + mov %eax, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test %eax, %eax + jnz psxDispatcherClear_CallFn + // throw an exception + int 10 + +psxDispatcherClear_CallFn: +#endif + + and %eax, 0x0fffffff + jmp %eax + +psxDispatcherClear_Recompile: + push REG_BLOCK + push REG_PC + call psxRecRecompile + add %esp, 4 // pop old param + pop REG_BLOCK + mov %eax, dword ptr [REG_BLOCK] + + pop %ecx // old fnptr + + and %eax, 0x0fffffff + mov byte ptr [%ecx], 0xe9 // jmp32 + mov %edx, %eax + sub %edx, %ecx + sub %edx, 5 + mov dword ptr [%ecx+1], %edx + + jmp %eax + +// called when jumping to variable psxpc address +.globl psxDispatcherReg + .type psxDispatcherReg, @function +psxDispatcherReg: + + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov %edx, dword ptr [psxRegs+PCOFFSET] + mov %ecx, %edx + + shr %edx, 14 + and %edx, 0xfffffffc + add %edx, [psxRecLUT] + mov %edx, dword ptr [%edx] + + mov %eax, %ecx + and %eax, 0xfffc + // %edx += 2*%eax + shl %eax, 1 + add %edx, %eax + + // check if startpc == psxRegs.pc + mov %eax, %ecx + //and %eax, 0x5fffffff // remove higher bits + cmp %eax, dword ptr [%edx+BLOCKTYPE_STARTPC] + jne psxDispatcherReg_recomp + + mov %eax, dword ptr [%edx] + +#ifdef _DEBUG + test %eax, %eax + jnz psxDispatcherReg_CallFn2 + // throw an exception + int 10 +psxDispatcherReg_CallFn2: +#endif + and %eax, 0x0fffffff + jmp %eax // fnptr + +psxDispatcherReg_recomp: + sub %esp, 8 + mov dword ptr [%esp+4], %edx + mov dword ptr [%esp], %ecx + call psxRecRecompile + mov %edx, dword ptr [%esp+4] + add %esp, 8 + + mov %eax, dword ptr [%edx] + and %eax, 0x0fffffff + jmp %eax // fnptr + +#endif diff --git a/pcsx2/x86/aVUzerorec.S b/pcsx2/x86/aVUzerorec.S new file mode 100644 index 0000000..11ede0c --- /dev/null +++ b/pcsx2/x86/aVUzerorec.S @@ -0,0 +1,158 @@ +// iR3000A.c assembly routines +// zerofrog(@gmail.com) +.intel_syntax + +.extern svudispfntemp +.extern s_TotalVUCycles +.extern s_callstack +.extern s_vu1esp +.extern s_writeQ +.extern s_writeP +.extern g_curdebugvu +.extern SuperVUGetProgram +.extern SuperVUCleanupProgram +.extern g_sseVUMXCSR +.extern g_sseMXCSR + +// SuperVUExecuteProgram(u32 startpc, int vuindex) +.globl SuperVUExecuteProgram + .type SuperVUExecuteProgram, @function +SuperVUExecuteProgram: +#ifdef __x86_64__ + mov %rax, [%rsp] + mov dword ptr [s_TotalVUCycles], 0 + add %rsp, 8 + mov [s_callstack], %rax + call SuperVUGetProgram + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + // function arguments + push %rdi + push %rsi + +#ifdef _DEBUG + mov s_vu1esp, %rsp +#endif + + ldmxcsr g_sseVUMXCSR + mov dword ptr [s_writeQ], 0xffffffff + mov dword ptr [s_writeP], 0xffffffff + jmp %rax +#else + mov %eax, [%esp] + mov dword ptr s_TotalVUCycles, 0 + add %esp, 4 + mov dword ptr [s_callstack], %eax + call SuperVUGetProgram + mov s_vu1ebp, %ebp + mov s_vu1esi, %esi + mov s_vuedi, %edi + mov s_vuebx, %ebx +#ifdef _DEBUG + mov s_vu1esp, %esp +#endif + + ldmxcsr g_sseVUMXCSR + mov dword ptr s_writeQ, 0xffffffff + mov dword ptr s_writeP, 0xffffffff + jmp %eax +#endif // __x86_64__ + + +.globl SuperVUEndProgram + .type SuperVUEndProgram, @function +SuperVUEndProgram: + // restore cpu state + ldmxcsr g_sseMXCSR + +#ifdef __x86_64__ +#ifdef _DEBUG + sub s_vu1esp, %rsp +#endif + + // function arguments for SuperVUCleanupProgram + pop %rsi + pop %rdi + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp +#else + mov %ebp, s_vu1ebp + mov %esi, s_vu1esi + mov %edi, s_vuedi + mov %ebx, s_vuebx + +#ifdef _DEBUG + sub s_vu1esp, %esp +#endif +#endif + + call SuperVUCleanupProgram + jmp [s_callstack] // so returns correctly + + +.globl svudispfn + .type svudispfn, @function +svudispfn: +#ifdef __x86_64__ + mov [g_curdebugvu], %rax + push %rax + push %rcx + push %rdx + push %rbp + push %rsi + push %rdi + push %rbx + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + + call svudispfntemp + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rbx + pop %rdi + pop %rsi + pop %rbp + pop %rdx + pop %rcx + pop %rax +#else + mov [g_curdebugvu], %eax + mov s_saveecx, %ecx + mov s_saveedx, %edx + mov s_saveebx, %ebx + mov s_saveesi, %esi + mov s_saveedi, %edi + mov s_saveebp, %ebp + + call svudispfntemp + + mov %ecx, s_saveecx + mov %edx, s_saveedx + mov %ebx, s_saveebx + mov %esi, s_saveesi + mov %edi, s_saveedi + mov %ebp, s_saveebp +#endif + ret diff --git a/pcsx2/x86/aVif.S b/pcsx2/x86/aVif.S new file mode 100644 index 0000000..23dc23c --- /dev/null +++ b/pcsx2/x86/aVif.S @@ -0,0 +1,1590 @@ +/*Pcsx2 - Pc Ps2 Emulator + Copyright (C) 2002-2007 Pcsx2 Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +.intel_syntax + +.extern _vifRegs +.extern _vifMaskRegs +.extern _vifRow + +#ifdef __x86_64__ +#define VIF_SRC %rsi +#define VIF_INC %rcx +#define VIF_DST %rdi +#define VIF_SIZE %edx +#define VIF_TMPADDR %rax +#define VIF_SAVEEBX %r8 +#define VIF_SAVEEBXd %r8d +#else +#define VIF_SRC %esi +#define VIF_INC %ecx +#define VIF_DST %edi +#define VIF_SIZE %edx +#define VIF_TMPADDR %eax +#define VIF_SAVEEBX %ebx +#define VIF_SAVEEBXd %ebx +#endif + +#define XMM_R0 %xmm0 +#define XMM_R1 %xmm1 +#define XMM_R2 %xmm2 +#define XMM_WRITEMASK %xmm3 +#define XMM_ROWMASK %xmm4 +#define XMM_ROWCOLMASK %xmm5 +#define XMM_ROW %xmm6 +#define XMM_COL %xmm7 + +#define XMM_R3 XMM_COL + +// writing masks +#define UNPACK_Write0_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ + MOVDQA qword ptr [VIF_DST+DEST_OFFSET], r0; + +#define UNPACK_Write1_Regular(r0, CL, DEST_OFFSET, MOVDQA) \ + MOVDQA qword ptr [VIF_DST], r0; \ + add VIF_DST, VIF_INC; \ + +#define UNPACK_Write0_Mask UNPACK_Write0_Regular +#define UNPACK_Write1_Mask UNPACK_Write1_Regular + +// masked write (dest needs to be in edi) +#define UNPACK_Write0_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ + movdqa XMM_WRITEMASK, qword ptr [VIF_TMPADDR + 64*(CL) + 48]; \ + pand r0, XMM_WRITEMASK; \ + pandn XMM_WRITEMASK, qword ptr [VIF_DST]; \ + por r0, XMM_WRITEMASK; \ + MOVDQA qword ptr [VIF_DST], r0; \ + add VIF_DST, 16; \ + +// masked write (dest needs to be in edi) +#define UNPACK_Write1_WriteMask(r0, CL, DEST_OFFSET, MOVDQA) \ + movdqa XMM_WRITEMASK, qword ptr [VIF_TMPADDR + 64*(0) + 48]; \ + pand r0, XMM_WRITEMASK; \ + pandn XMM_WRITEMASK, qword ptr [VIF_DST]; \ + por r0, XMM_WRITEMASK; \ + MOVDQA qword ptr [VIF_DST], r0; \ + add VIF_DST, VIF_INC; \ + +#define UNPACK_Mask_SSE_0(r0) \ + pand r0, XMM_WRITEMASK; \ + por r0, XMM_ROWCOLMASK; \ + +// once a qword is uncomprssed, applies masks and saves +// note: modifying XMM_WRITEMASK +// dest = row + write (only when mask=0), otherwise write +#define UNPACK_Mask_SSE_1(r0) \ + pand r0, XMM_WRITEMASK; \ + por r0, XMM_ROWCOLMASK; \ + pand XMM_WRITEMASK, XMM_ROW; \ + paddd r0, XMM_WRITEMASK; \ + +// dest = row + write (only when mask=0), otherwise write +// row = row + write (only when mask = 0), otherwise row +#define UNPACK_Mask_SSE_2(r0) \ + pand r0, XMM_WRITEMASK; \ + pand XMM_WRITEMASK, XMM_ROW; \ + paddd XMM_ROW, r0; \ + por r0, XMM_ROWCOLMASK; \ + paddd r0, XMM_WRITEMASK; \ + +#define UNPACK_WriteMask_SSE_0 UNPACK_Mask_SSE_0 +#define UNPACK_WriteMask_SSE_1 UNPACK_Mask_SSE_1 +#define UNPACK_WriteMask_SSE_2 UNPACK_Mask_SSE_2 + +#define UNPACK_Regular_SSE_0(r0) + +#define UNPACK_Regular_SSE_1(r0) \ + paddd r0, XMM_ROW; \ + +#define UNPACK_Regular_SSE_2(r0) \ + paddd r0, XMM_ROW; \ + movdqa XMM_ROW, r0; \ + +// setting up masks +#define UNPACK_Setup_Mask_SSE(CL) \ + mov VIF_TMPADDR, _vifMaskRegs; \ + movdqa XMM_ROWMASK, qword ptr [VIF_TMPADDR + 64*(CL) + 16]; \ + movdqa XMM_ROWCOLMASK, qword ptr [VIF_TMPADDR + 64*(CL) + 32]; \ + movdqa XMM_WRITEMASK, qword ptr [VIF_TMPADDR + 64*(CL)]; \ + pand XMM_ROWMASK, XMM_ROW; \ + pand XMM_ROWCOLMASK, XMM_COL; \ + por XMM_ROWCOLMASK, XMM_ROWMASK; \ + +#define UNPACK_Start_Setup_Mask_SSE_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Start_Setup_Mask_SSE_1(CL) \ + mov VIF_TMPADDR, _vifMaskRegs; \ + movdqa XMM_ROWMASK, qword ptr [VIF_TMPADDR + 64*(CL) + 16]; \ + movdqa XMM_ROWCOLMASK, qword ptr [VIF_TMPADDR + 64*(CL) + 32]; \ + pand XMM_ROWMASK, XMM_ROW; \ + pand XMM_ROWCOLMASK, XMM_COL; \ + por XMM_ROWCOLMASK, XMM_ROWMASK; \ + +#define UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Setup_Mask_SSE_0_1(CL) +#define UNPACK_Setup_Mask_SSE_1_1(CL) \ + mov VIF_TMPADDR, _vifMaskRegs; \ + movdqa XMM_WRITEMASK, qword ptr [VIF_TMPADDR + 64*(0)]; \ + +// ignore CL, since vif.cycle.wl == 1 +#define UNPACK_Setup_Mask_SSE_2_1(CL) \ + mov VIF_TMPADDR, _vifMaskRegs; \ + movdqa XMM_ROWMASK, qword ptr [VIF_TMPADDR + 64*(0) + 16]; \ + movdqa XMM_ROWCOLMASK, qword ptr [VIF_TMPADDR + 64*(0) + 32]; \ + movdqa XMM_WRITEMASK, qword ptr [VIF_TMPADDR + 64*(0)]; \ + pand XMM_ROWMASK, XMM_ROW; \ + pand XMM_ROWCOLMASK, XMM_COL; \ + por XMM_ROWCOLMASK, XMM_ROWMASK; \ + +#define UNPACK_Setup_Mask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_Mask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) + +// write mask always destroys XMM_WRITEMASK, so 0_0 = 1_0 +#define UNPACK_Setup_WriteMask_SSE_0_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_1_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_2_0(CL) UNPACK_Setup_Mask_SSE(CL) +#define UNPACK_Setup_WriteMask_SSE_0_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_1_1(CL) UNPACK_Setup_Mask_SSE_1_1(CL) +#define UNPACK_Setup_WriteMask_SSE_2_1(CL) UNPACK_Setup_Mask_SSE_2_1(CL) + +#define UNPACK_Start_Setup_WriteMask_SSE_0(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_1(CL) UNPACK_Start_Setup_Mask_SSE_1(CL) +#define UNPACK_Start_Setup_WriteMask_SSE_2(CL) UNPACK_Start_Setup_Mask_SSE_2(CL) + +#define UNPACK_Start_Setup_Regular_SSE_0(CL) +#define UNPACK_Start_Setup_Regular_SSE_1(CL) +#define UNPACK_Start_Setup_Regular_SSE_2(CL) +#define UNPACK_Setup_Regular_SSE_0_0(CL) +#define UNPACK_Setup_Regular_SSE_1_0(CL) +#define UNPACK_Setup_Regular_SSE_2_0(CL) +#define UNPACK_Setup_Regular_SSE_0_1(CL) +#define UNPACK_Setup_Regular_SSE_1_1(CL) +#define UNPACK_Setup_Regular_SSE_2_1(CL) + +#define UNPACK_INC_DST_0_Regular(qw) add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Regular(qw) +#define UNPACK_INC_DST_0_Mask(qw) add VIF_DST, (16*qw) +#define UNPACK_INC_DST_1_Mask(qw) +#define UNPACK_INC_DST_0_WriteMask(qw) +#define UNPACK_INC_DST_1_WriteMask(qw) + +// unpacks for 1,2,3,4 elements (V3 uses this directly) +#define UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType) \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4) + +// V3 uses this directly +#define UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType) \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3); \ + +#define UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType) \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(2); \ + +#define UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType) \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(1); \ + +// S-32 +// only when cl==1 +#define UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R3, qword ptr [VIF_SRC]; \ + \ + pshufd XMM_R0, XMM_R3, 0; \ + pshufd XMM_R1, XMM_R3, 0x55; \ + pshufd XMM_R2, XMM_R3, 0xaa; \ + pshufd XMM_R3, XMM_R3, 0xff; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_S_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R2, qword ptr [VIF_SRC]; \ + \ + pshufd XMM_R0, XMM_R2, 0; \ + pshufd XMM_R1, XMM_R2, 0x55; \ + pshufd XMM_R2, XMM_R2, 0xaa; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_S_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_S_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_S_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_S_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R1, qword ptr [VIF_SRC]; \ + \ + pshufd XMM_R0, XMM_R1, 0; \ + pshufd XMM_R1, XMM_R1, 0x55; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_S_32SSE_2A UNPACK_S_32SSE_2 + +#define UNPACK_S_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + pshufd XMM_R0, XMM_R0, 0; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_S_32SSE_1A UNPACK_S_32SSE_1 + +// S-16 +#define UNPACK_S_16SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R3, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R3, XMM_R3; \ + UNPACK_RIGHTSHIFT XMM_R3, 16; \ + \ + pshufd XMM_R0, XMM_R3, 0; \ + pshufd XMM_R1, XMM_R3, 0x55; \ + pshufd XMM_R2, XMM_R3, 0xaa; \ + pshufd XMM_R3, XMM_R3, 0xff; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_S_16SSE_4A UNPACK_S_16SSE_4 + +#define UNPACK_S_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R2, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R2, XMM_R2; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + pshufd XMM_R0, XMM_R2, 0; \ + pshufd XMM_R1, XMM_R2, 0x55; \ + pshufd XMM_R2, XMM_R2, 0xaa; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + add VIF_SRC, 6; \ + +#define UNPACK_S_16SSE_3A UNPACK_S_16SSE_3 + +#define UNPACK_S_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R1, dword ptr [VIF_SRC]; \ + punpcklwd XMM_R1, XMM_R1; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + \ + pshufd XMM_R0, XMM_R1, 0; \ + pshufd XMM_R1, XMM_R1, 0x55; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_S_16SSE_2A UNPACK_S_16SSE_2 + +#define UNPACK_S_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + pshufd XMM_R0, XMM_R0, 0; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 2; \ + +#define UNPACK_S_16SSE_1A UNPACK_S_16SSE_1 + +// S-8 +#define UNPACK_S_8SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R3, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R3, XMM_R3; \ + punpcklwd XMM_R3, XMM_R3; \ + UNPACK_RIGHTSHIFT XMM_R3, 24; \ + \ + pshufd XMM_R0, XMM_R3, 0; \ + pshufd XMM_R1, XMM_R3, 0x55; \ + pshufd XMM_R2, XMM_R3, 0xaa; \ + pshufd XMM_R3, XMM_R3, 0xff; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_S_8SSE_4A UNPACK_S_8SSE_4 + +#define UNPACK_S_8SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R2, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R2, XMM_R2; \ + punpcklwd XMM_R2, XMM_R2; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + pshufd XMM_R0, XMM_R2, 0; \ + pshufd XMM_R1, XMM_R2, 0x55; \ + pshufd XMM_R2, XMM_R2, 0xaa; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 3; \ + +#define UNPACK_S_8SSE_3A UNPACK_S_8SSE_3 + +#define UNPACK_S_8SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R1, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R1, XMM_R1; \ + punpcklwd XMM_R1, XMM_R1; \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + \ + pshufd XMM_R0, XMM_R1, 0; \ + pshufd XMM_R1, XMM_R1, 0x55; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 2; \ + +#define UNPACK_S_8SSE_2A UNPACK_S_8SSE_2 + +#define UNPACK_S_8SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + pshufd XMM_R0, XMM_R0, 0; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + inc VIF_SRC; \ + +#define UNPACK_S_8SSE_1A UNPACK_S_8SSE_1 + +// V2-32 +#define UNPACK_V2_32SSE_4A(CL, TOTALCL, MaskType, ModeType) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + MOVDQA XMM_R2, qword ptr [VIF_SRC+16]; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + pshufd XMM_R3, XMM_R2, 0xee; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V2_32SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+8]; \ + movq XMM_R2, qword ptr [VIF_SRC+16]; \ + movq XMM_R3, qword ptr [VIF_SRC+24]; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V2_32SSE_3A(CL, TOTALCL, MaskType, ModeType) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R2, qword ptr [VIF_SRC+16]; \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V2_32SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+8]; \ + movq XMM_R2, qword ptr [VIF_SRC+16]; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V2_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+8]; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V2_32SSE_2A UNPACK_V2_32SSE_2 + +#define UNPACK_V2_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V2_32SSE_1A UNPACK_V2_32SSE_1 + +// V2-16 +#define UNPACK_V2_16SSE_4A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + punpckhwd XMM_R2, qword ptr [VIF_SRC]; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + pshufd XMM_R3, XMM_R2, 0xee; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + add VIF_SRC, 16; \ + +#define UNPACK_V2_16SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpckhwd XMM_R2, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + pshufd XMM_R3, XMM_R2, 0xee; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V2_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + punpckhwd XMM_R2, qword ptr [VIF_SRC]; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V2_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpckhwd XMM_R2, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V2_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V2_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V2_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, dword ptr [VIF_SRC]; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_V2_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +// V2-8 +#define UNPACK_V2_8SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + punpckhwd XMM_R2, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + pshufd XMM_R3, XMM_R2, 0xee; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V2_8SSE_4A UNPACK_V2_8SSE_4 + +#define UNPACK_V2_8SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + punpckhwd XMM_R2, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 6; \ + +#define UNPACK_V2_8SSE_3A UNPACK_V2_8SSE_3 + +#define UNPACK_V2_8SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + pshufd XMM_R1, XMM_R0, 0xee; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_V2_8SSE_2A UNPACK_V2_8SSE_2 + +#define UNPACK_V2_8SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 2; \ + +#define UNPACK_V2_8SSE_1A UNPACK_V2_8SSE_1 + +// V3-32 +// midnight club 2 crashes because reading a qw at +36 is out of bounds +#define UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+12]; \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+0); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + MOVDQA XMM_R3, qword ptr [VIF_SRC+32]; \ + movdqu XMM_R2, qword ptr [VIF_SRC+24]; \ + psrldq XMM_R3, 4; \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+3); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R3); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R3, CL+3, 48, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(4); \ + \ + add VIF_SRC, 48; \ + +#define UNPACK_V3_32SSE_4A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_4(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_4x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+12]; \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R0); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R0, CL, 0, movdqa); \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+1); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R1); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R1, CL+1, 16, movdqa); \ + \ + movdqu XMM_R2, qword ptr [VIF_SRC+24]; \ + \ + UNPACK_Setup_##MaskType##_SSE_##ModeType##_##TOTALCL##(CL+2); \ + UNPACK_##MaskType##_SSE_##ModeType##(XMM_R2); \ + UNPACK_Write##TOTALCL##_##MaskType##(XMM_R2, CL+2, 32, movdqa); \ + \ + UNPACK_INC_DST_##TOTALCL##_##MaskType##(3); \ + \ + add VIF_SRC, 36; \ + +#define UNPACK_V3_32SSE_3A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_3(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_3x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+12]; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V3_32SSE_2A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_2(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_2x(CL, TOTALCL, MaskType, ModeType, movdqu) + +#define UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, MOVDQA) \ + MOVDQA XMM_R0, qword ptr [VIF_SRC]; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V3_32SSE_1A(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqa) +#define UNPACK_V3_32SSE_1(CL, TOTALCL, MaskType, ModeType) UNPACK_V3_32SSE_1x(CL, TOTALCL, MaskType, ModeType, movdqu) + +// V3-16 +#define UNPACK_V3_16SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+6]; \ + \ + punpcklwd XMM_R0, XMM_R0; \ + movq XMM_R2, qword ptr [VIF_SRC+12]; \ + punpcklwd XMM_R1, XMM_R1; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + movq XMM_R3, qword ptr [VIF_SRC+18]; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + punpcklwd XMM_R2, XMM_R2; \ + punpcklwd XMM_R3, XMM_R3; \ + \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + UNPACK_RIGHTSHIFT XMM_R3, 16; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V3_16SSE_4A UNPACK_V3_16SSE_4 + +#define UNPACK_V3_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+6]; \ + \ + punpcklwd XMM_R0, XMM_R0; \ + movq XMM_R2, qword ptr [VIF_SRC+12]; \ + punpcklwd XMM_R1, XMM_R1; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 18; \ + +#define UNPACK_V3_16SSE_3A UNPACK_V3_16SSE_3 + +#define UNPACK_V3_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+6]; \ + \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R1, XMM_R1; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V3_16SSE_2A UNPACK_V3_16SSE_2 + +#define UNPACK_V3_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 6; \ + +#define UNPACK_V3_16SSE_1A UNPACK_V3_16SSE_1 + +// V3-8 +#define UNPACK_V3_8SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R1, qword ptr [VIF_SRC]; \ + movq XMM_R3, qword ptr [VIF_SRC+6]; \ + \ + punpcklbw XMM_R1, XMM_R1; \ + punpcklbw XMM_R3, XMM_R3; \ + punpcklwd XMM_R0, XMM_R1; \ + psrldq XMM_R1, 6; \ + punpcklwd XMM_R2, XMM_R3; \ + psrldq XMM_R3, 6; \ + punpcklwd XMM_R1, XMM_R1; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + punpcklwd XMM_R3, XMM_R3; \ + \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R3, 24; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V3_8SSE_4A UNPACK_V3_8SSE_4 + +#define UNPACK_V3_8SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, word ptr [VIF_SRC]; \ + movd XMM_R1, dword ptr [VIF_SRC+3]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + movd XMM_R2, dword ptr [VIF_SRC+6]; \ + punpcklbw XMM_R1, XMM_R1; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklbw XMM_R2, XMM_R2; \ + \ + punpcklwd XMM_R1, XMM_R1; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 9 \ + +#define UNPACK_V3_8SSE_3A UNPACK_V3_8SSE_3 + +#define UNPACK_V3_8SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + movd XMM_R1, dword ptr [VIF_SRC+3]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklbw XMM_R1, XMM_R1; \ + \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R1, XMM_R1; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 6; \ + +#define UNPACK_V3_8SSE_2A UNPACK_V3_8SSE_2 + +#define UNPACK_V3_8SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 3; \ + +#define UNPACK_V3_8SSE_1A UNPACK_V3_8SSE_1 + +// V4-32 +#define UNPACK_V4_32SSE_4A(CL, TOTALCL, MaskType, ModeType) \ + movdqa XMM_R0, qword ptr [VIF_SRC]; \ + movdqa XMM_R1, qword ptr [VIF_SRC+16]; \ + movdqa XMM_R2, qword ptr [VIF_SRC+32]; \ + movdqa XMM_R3, qword ptr [VIF_SRC+48]; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 64; \ + +#define UNPACK_V4_32SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+16]; \ + movdqu XMM_R2, qword ptr [VIF_SRC+32]; \ + movdqu XMM_R3, qword ptr [VIF_SRC+48]; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 64; \ + +#define UNPACK_V4_32SSE_3A(CL, TOTALCL, MaskType, ModeType) \ + movdqa XMM_R0, qword ptr [VIF_SRC]; \ + movdqa XMM_R1, qword ptr [VIF_SRC+16]; \ + movdqa XMM_R2, qword ptr [VIF_SRC+32]; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 48; \ + +#define UNPACK_V4_32SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+16]; \ + movdqu XMM_R2, qword ptr [VIF_SRC+32]; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 48; \ + +#define UNPACK_V4_32SSE_2A(CL, TOTALCL, MaskType, ModeType) \ + movdqa XMM_R0, qword ptr [VIF_SRC]; \ + movdqa XMM_R1, qword ptr [VIF_SRC+16]; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V4_32SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R1, qword ptr [VIF_SRC+16]; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V4_32SSE_1A(CL, TOTALCL, MaskType, ModeType) \ + movdqa XMM_R0, qword ptr [VIF_SRC]; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V4_32SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +// V4-16 +#define UNPACK_V4_16SSE_4A(CL, TOTALCL, MaskType, ModeType) \ + \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + punpckhwd XMM_R1, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R2, qword ptr [VIF_SRC+16]; \ + punpckhwd XMM_R3, qword ptr [VIF_SRC+16]; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + UNPACK_RIGHTSHIFT XMM_R3, 16; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V4_16SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + movdqu XMM_R2, qword ptr [VIF_SRC+16]; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpckhwd XMM_R3, XMM_R2; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + UNPACK_RIGHTSHIFT XMM_R3, 16; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 32; \ + +#define UNPACK_V4_16SSE_3A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + punpckhwd XMM_R1, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R2, qword ptr [VIF_SRC+16]; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V4_16SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R2, qword ptr [VIF_SRC+16]; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + UNPACK_RIGHTSHIFT XMM_R2, 16; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 24; \ + +#define UNPACK_V4_16SSE_2A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + punpckhwd XMM_R1, qword ptr [VIF_SRC]; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V4_16SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movq XMM_R1, qword ptr [VIF_SRC+8]; \ + \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R1, XMM_R1; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + UNPACK_RIGHTSHIFT XMM_R1, 16; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V4_16SSE_1A(CL, TOTALCL, MaskType, ModeType) \ + punpcklwd XMM_R0, qword ptr [VIF_SRC]; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V4_16SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 16; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +// V4-8 +#define UNPACK_V4_8SSE_4A(CL, TOTALCL, MaskType, ModeType) \ + punpcklbw XMM_R0, qword ptr [VIF_SRC]; \ + punpckhbw XMM_R2, qword ptr [VIF_SRC]; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpckhwd XMM_R3, XMM_R2; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R3, 24; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V4_8SSE_4(CL, TOTALCL, MaskType, ModeType) \ + movdqu XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpckhbw XMM_R2, XMM_R0; \ + punpcklbw XMM_R0, XMM_R0; \ + \ + punpckhwd XMM_R3, XMM_R2; \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R3, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 16; \ + +#define UNPACK_V4_8SSE_3A(CL, TOTALCL, MaskType, ModeType) \ + punpcklbw XMM_R0, qword ptr [VIF_SRC]; \ + punpckhbw XMM_R2, qword ptr [VIF_SRC]; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V4_8SSE_3(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + movd XMM_R2, dword ptr [VIF_SRC+8]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklbw XMM_R2, XMM_R2; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + UNPACK_RIGHTSHIFT XMM_R2, 24; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 12; \ + +#define UNPACK_V4_8SSE_2A(CL, TOTALCL, MaskType, ModeType) \ + punpcklbw XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V4_8SSE_2(CL, TOTALCL, MaskType, ModeType) \ + movq XMM_R0, qword ptr [VIF_SRC]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + UNPACK_RIGHTSHIFT XMM_R1, 24; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V4_8SSE_1A(CL, TOTALCL, MaskType, ModeType) \ + punpcklbw XMM_R0, qword ptr [VIF_SRC]; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_V4_8SSE_1(CL, TOTALCL, MaskType, ModeType) \ + movd XMM_R0, dword ptr [VIF_SRC]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + UNPACK_RIGHTSHIFT XMM_R0, 24; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +// V4-5 +.extern s_TempDecompress + +#define DECOMPRESS_RGBA(OFFSET) \ + mov %bl, %al; \ + shl %bl, 3; \ + mov byte ptr [s_TempDecompress+OFFSET], %bl; \ + \ + mov %bx, %ax; \ + shr %bx, 2; \ + and %bx, 0xf8; \ + mov byte ptr [s_TempDecompress+OFFSET+1], %bl; \ + \ + mov %bx, %ax; \ + shr %bx, 7; \ + and %bx, 0xf8; \ + mov byte ptr [s_TempDecompress+OFFSET+2], %bl; \ + mov %bx, %ax; \ + shr %bx, 8; \ + and %bx, 0x80; \ + mov byte ptr [s_TempDecompress+OFFSET+3], %bl; \ + +#define UNPACK_V4_5SSE_4(CL, TOTALCL, MaskType, ModeType) \ + mov %eax, dword ptr [VIF_SRC]; \ + DECOMPRESS_RGBA(0); \ + \ + shr %eax, 16; \ + DECOMPRESS_RGBA(4); \ + \ + mov %eax, dword ptr [VIF_SRC+4]; \ + DECOMPRESS_RGBA(8); \ + \ + shr %eax, 16; \ + DECOMPRESS_RGBA(12); \ + \ + movdqa XMM_R0, qword ptr [s_TempDecompress]; \ + \ + punpckhbw XMM_R2, XMM_R0; \ + punpcklbw XMM_R0, XMM_R0; \ + \ + punpckhwd XMM_R3, XMM_R2; \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + psrld XMM_R0, 24; \ + psrld XMM_R1, 24; \ + psrld XMM_R2, 24; \ + psrld XMM_R3, 24; \ + \ + UNPACK4_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 8; \ + +#define UNPACK_V4_5SSE_4A UNPACK_V4_5SSE_4 + +#define UNPACK_V4_5SSE_3(CL, TOTALCL, MaskType, ModeType) \ + mov %eax, dword ptr [VIF_SRC]; \ + DECOMPRESS_RGBA(0); \ + \ + shr %eax, 16; \ + DECOMPRESS_RGBA(4); \ + \ + mov %eax, dword ptr [VIF_SRC]; \ + DECOMPRESS_RGBA(8); \ + \ + movdqa XMM_R0, qword ptr [s_TempDecompress]; \ + \ + punpckhbw XMM_R2, XMM_R0; \ + punpcklbw XMM_R0, XMM_R0; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + punpcklwd XMM_R2, XMM_R2; \ + \ + psrld XMM_R0, 24; \ + psrld XMM_R1, 24; \ + psrld XMM_R2, 24; \ + \ + UNPACK3_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 6; \ + +#define UNPACK_V4_5SSE_3A UNPACK_V4_5SSE_3 + +#define UNPACK_V4_5SSE_2(CL, TOTALCL, MaskType, ModeType) \ + mov %eax, dword ptr [VIF_SRC]; \ + DECOMPRESS_RGBA(0); \ + \ + shr %eax, 16; \ + DECOMPRESS_RGBA(4); \ + \ + movq XMM_R0, qword ptr [s_TempDecompress]; \ + \ + punpcklbw XMM_R0, XMM_R0; \ + \ + punpckhwd XMM_R1, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + psrld XMM_R0, 24; \ + psrld XMM_R1, 24; \ + \ + UNPACK2_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 4; \ + +#define UNPACK_V4_5SSE_2A UNPACK_V4_5SSE_2 + +#define UNPACK_V4_5SSE_1(CL, TOTALCL, MaskType, ModeType) \ + mov %ax, word ptr [VIF_SRC]; \ + DECOMPRESS_RGBA(0) \ + \ + movd XMM_R0, dword ptr [s_TempDecompress]; \ + punpcklbw XMM_R0, XMM_R0; \ + punpcklwd XMM_R0, XMM_R0; \ + \ + psrld XMM_R0, 24; \ + \ + UNPACK1_SSE(CL, TOTALCL, MaskType, ModeType); \ + \ + add VIF_SRC, 2; \ + +#define UNPACK_V4_5SSE_1A UNPACK_V4_5SSE_1 + +#pragma warning(disable:4731) + +#define SAVE_ROW_REG_BASE \ + mov VIF_TMPADDR, _vifRow; \ + movdqa qword ptr [VIF_TMPADDR], XMM_ROW; \ + mov VIF_TMPADDR, _vifRegs; \ + movss dword ptr [VIF_TMPADDR+0x100], XMM_ROW; \ + psrldq XMM_ROW, 4; \ + movss dword ptr [VIF_TMPADDR+0x110], XMM_ROW; \ + psrldq XMM_ROW, 4; \ + movss dword ptr [VIF_TMPADDR+0x120], XMM_ROW; \ + psrldq XMM_ROW, 4; \ + movss dword ptr [VIF_TMPADDR+0x130], XMM_ROW; \ + +#define SAVE_NO_REG + +#ifdef __x86_64__ +#define INIT_ARGS() + +#define POP_REGS() + +#define INC_STACK(reg) add %esp, 8; + +#else + +// 32 bit versions have the args on the stack +#define INIT_ARGS() \ + push %edi; \ + push %esi; \ + push %ebx; \ + mov VIF_DST, dword ptr [%esp+4+12]; \ + mov VIF_SRC, dword ptr [%esp+8+12]; \ + mov VIF_SIZE, dword ptr [%esp+12+12]; \ + + +#define POP_REGS() \ + pop %ebx; \ + pop %esi; \ + pop %edi; \ + +#define INC_STACK(reg) add %esp, 4; + +#endif + +// qsize - bytes of compressed size of 1 decompressed qword +// int UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType(u32* dest, u32* data, int dmasize) + +#define defUNPACK_SkippingWrite(name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG) \ +.globl UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType; \ + .type UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType, @function; \ +UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType: \ + INIT_ARGS(); \ + mov VIF_TMPADDR, _vifRegs; \ + movzx VIF_INC, byte ptr [VIF_TMPADDR + 0x40]; \ + movzx VIF_SAVEEBX, byte ptr [VIF_TMPADDR + 0x41]; \ + sub VIF_INC, VIF_SAVEEBX; \ + shl VIF_INC, 4; \ + \ + cmp VIF_SAVEEBXd, 1; \ + je name##_##sign##_##MaskType##_##ModeType##_WL1; \ + cmp VIF_SAVEEBXd, 2; \ + je name##_##sign##_##MaskType##_##ModeType##_WL2; \ + cmp VIF_SAVEEBXd, 3; \ + je name##_##sign##_##MaskType##_##ModeType##_WL3; \ + jmp name##_##sign##_##MaskType##_##ModeType##_WL4; \ + \ +name##_##sign##_##MaskType##_##ModeType##_WL1: \ + UNPACK_Start_Setup_##MaskType##_SSE_##ModeType##(0); \ + \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Done3; \ + \ + add VIF_INC, 16; \ + \ + /* first align VIF_SRC to 16 bytes */ \ +name##_##sign##_##MaskType##_##ModeType##_C1_Align16: \ + \ + test VIF_SRC, 15; \ + jz name##_##sign##_##MaskType##_##ModeType##_C1_UnpackAligned; \ + \ + UNPACK_##name##SSE_1(0, 1, MaskType, ModeType); \ + \ + cmp VIF_SIZE, (2*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_DoneWithDec; \ + sub VIF_SIZE, qsize; \ + jmp name##_##sign##_##MaskType##_##ModeType##_C1_Align16; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_UnpackAligned: \ + \ + cmp VIF_SIZE, (2*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Unpack1; \ + cmp VIF_SIZE, (3*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Unpack2; \ + cmp VIF_SIZE, (4*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Unpack3; \ + prefetchnta [VIF_SRC + 64]; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_Unpack4: \ + UNPACK_##name##SSE_4A(0, 1, MaskType, ModeType); \ + \ + cmp VIF_SIZE, (8*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_DoneUnpack4; \ + sub VIF_SIZE, (4*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C1_Unpack4; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_DoneUnpack4: \ + \ + sub VIF_SIZE, (4*qsize); \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Done3; \ + cmp VIF_SIZE, (2*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Unpack1; \ + cmp VIF_SIZE, (3*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C1_Unpack2; \ + /* fall through */ \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_Unpack3: \ + UNPACK_##name##SSE_3A(0, 1, MaskType, ModeType); \ + \ + sub VIF_SIZE, (3*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C1_Done3; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_Unpack2: \ + UNPACK_##name##SSE_2A(0, 1, MaskType, ModeType); \ + \ + sub VIF_SIZE, (2*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C1_Done3; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C1_Unpack1: \ + UNPACK_##name##SSE_1A(0, 1, MaskType, ModeType); \ +name##_##sign##_##MaskType##_##ModeType##_C1_DoneWithDec: \ + sub VIF_SIZE, qsize; \ +name##_##sign##_##MaskType##_##ModeType##_C1_Done3: \ + SAVE_ROW_REG; \ + mov %eax, VIF_SIZE; \ + POP_REGS(); \ + ret; \ + \ +name##_##sign##_##MaskType##_##ModeType##_WL2: \ + cmp VIF_SIZE, (2*qsize); \ + \ + jl name##_##sign##_##MaskType##_##ModeType##_C2_Done3; \ +name##_##sign##_##MaskType##_##ModeType##_C2_Unpack: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + add VIF_DST, VIF_INC; /* take into account wl */ \ + cmp VIF_SIZE, (4*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C2_Done2; \ + sub VIF_SIZE, (2*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C2_Unpack; /* unpack next */ \ + \ +name##_##sign##_##MaskType##_##ModeType##_C2_Done2: \ + sub VIF_SIZE, (2*qsize); \ +name##_##sign##_##MaskType##_##ModeType##_C2_Done3: \ + cmp VIF_SIZE, qsize; \ + /* execute left over qw */ \ + jl name##_##sign##_##MaskType##_##ModeType##_C2_Done4; \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ + \ + sub VIF_SIZE, qsize; \ +name##_##sign##_##MaskType##_##ModeType##_C2_Done4: \ + \ + SAVE_ROW_REG; \ + mov %eax, VIF_SIZE; \ + POP_REGS(); \ + ret; \ + \ +name##_##sign##_##MaskType##_##ModeType##_WL3: \ + cmp VIF_SIZE, (3*qsize); \ + \ + jl name##_##sign##_##MaskType##_##ModeType##_C3_Done5; \ +name##_##sign##_##MaskType##_##ModeType##_C3_Unpack: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + \ + add VIF_DST, VIF_INC; /* take into account wl */ \ + cmp VIF_SIZE, (6*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C3_Done2; \ + sub VIF_SIZE, (3*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C3_Unpack; /* unpack next */ \ +name##_##sign##_##MaskType##_##ModeType##_C3_Done2: \ + sub VIF_SIZE, (3*qsize); \ +name##_##sign##_##MaskType##_##ModeType##_C3_Done5: \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C3_Done4; \ + \ + /* execute left over qw */ \ + cmp VIF_SIZE, (2*qsize); \ + jl name##_##sign##_##MaskType##_##ModeType##_C3_Done3; \ + \ + /* process 2 qws */ \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + sub VIF_SIZE, (2*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C3_Done4; \ +name##_##sign##_##MaskType##_##ModeType##_C3_Done3: \ + /* process 1 qw */ \ + sub VIF_SIZE, qsize; \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType); \ +name##_##sign##_##MaskType##_##ModeType##_C3_Done4: \ + SAVE_ROW_REG; \ + mov %eax, VIF_SIZE; \ + POP_REGS(); \ + ret; \ + \ +name##_##sign##_##MaskType##_##ModeType##_WL4: /* >= 4 */ \ + sub VIF_SAVEEBX, 3; \ + push VIF_INC; \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C4_Done; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C4_Unpack: \ + cmp VIF_SIZE, (3*qsize); \ + jge name##_##sign##_##MaskType##_##ModeType##_C4_Unpack3; \ + cmp VIF_SIZE, (2*qsize); \ + jge name##_##sign##_##MaskType##_##ModeType##_C4_Unpack2; \ + \ + UNPACK_##name##SSE_1(0, 0, MaskType, ModeType) \ + \ + /* not enough data left */ \ + sub VIF_SIZE, qsize; \ + jmp name##_##sign##_##MaskType##_##ModeType##_C4_Done; \ +name##_##sign##_##MaskType##_##ModeType##_C4_Unpack2: \ + UNPACK_##name##SSE_2(0, 0, MaskType, ModeType); \ + \ + /* not enough data left */ \ + sub VIF_SIZE, (2*qsize); \ + jmp name##_##sign##_##MaskType##_##ModeType##_C4_Done; \ +name##_##sign##_##MaskType##_##ModeType##_C4_Unpack3: \ + UNPACK_##name##SSE_3(0, 0, MaskType, ModeType); \ + \ + sub VIF_SIZE, (3*qsize); \ + /* more data left, process 1qw at a time */ \ + mov VIF_INC, VIF_SAVEEBX; \ + \ +name##_##sign##_##MaskType##_##ModeType##_C4_UnpackX: \ + /* check if any data left */ \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C4_Done; \ + \ + UNPACK_##name##SSE_1(3, 0, MaskType, ModeType); \ + \ + sub VIF_SIZE, qsize; \ + cmp VIF_INC, 1; \ + je name##_##sign##_##MaskType##_##ModeType##_C4_DoneLoop; \ + sub VIF_INC, 1; \ + jmp name##_##sign##_##MaskType##_##ModeType##_C4_UnpackX; \ +name##_##sign##_##MaskType##_##ModeType##_C4_DoneLoop: \ + add VIF_DST, [%esp]; /* take into account wl */ \ + cmp VIF_SIZE, qsize; \ + jl name##_##sign##_##MaskType##_##ModeType##_C4_Done; \ + jmp name##_##sign##_##MaskType##_##ModeType##_C4_Unpack; /* unpack next */ \ +name##_##sign##_##MaskType##_##ModeType##_C4_Done: \ + \ + SAVE_ROW_REG; \ + INC_STACK(); \ + mov %eax, VIF_SIZE; \ + POP_REGS(); \ + ret; \ + +#define UNPACK_RIGHTSHIFT psrld +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, u, SAVE_ROW_REG_BASE) \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE) \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, u, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE) \ + +defUNPACK_SkippingWrite2(S_32, 4) +defUNPACK_SkippingWrite2(S_16, 2) +defUNPACK_SkippingWrite2(S_8, 1) +defUNPACK_SkippingWrite2(V2_32, 8) +defUNPACK_SkippingWrite2(V2_16, 4) +defUNPACK_SkippingWrite2(V2_8, 2) +defUNPACK_SkippingWrite2(V3_32, 12) +defUNPACK_SkippingWrite2(V3_16, 6) +defUNPACK_SkippingWrite2(V3_8, 3) +defUNPACK_SkippingWrite2(V4_32, 16) +defUNPACK_SkippingWrite2(V4_16, 8) +defUNPACK_SkippingWrite2(V4_8, 4) +defUNPACK_SkippingWrite2(V4_5, 2) + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 + +#define UNPACK_RIGHTSHIFT psrad +#define defUNPACK_SkippingWrite2(name, qsize) \ + defUNPACK_SkippingWrite(name, Mask, 0, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Regular, 0, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Regular, 1, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Regular, 2, qsize, s, SAVE_ROW_REG_BASE) \ + defUNPACK_SkippingWrite(name, Mask, 1, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE) \ + defUNPACK_SkippingWrite(name, WriteMask, 0, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, WriteMask, 1, qsize, s, SAVE_NO_REG) \ + defUNPACK_SkippingWrite(name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE) \ + +defUNPACK_SkippingWrite2(S_16, 2) +defUNPACK_SkippingWrite2(S_8, 1) +defUNPACK_SkippingWrite2(V2_16, 4) +defUNPACK_SkippingWrite2(V2_8, 2) +defUNPACK_SkippingWrite2(V3_16, 6) +defUNPACK_SkippingWrite2(V3_8, 3) +defUNPACK_SkippingWrite2(V4_16, 8) +defUNPACK_SkippingWrite2(V4_8, 4) + +#undef UNPACK_RIGHTSHIFT +#undef defUNPACK_SkippingWrite2 diff --git a/pcsx2/x86/aVif.asm b/pcsx2/x86/aVif.asm new file mode 100644 index 0000000..f5e25f6 --- /dev/null +++ b/pcsx2/x86/aVif.asm @@ -0,0 +1,1898 @@ +; Pcsx2 - Pc Ps2 Emulator +; Copyright (C) 2002-2007 Pcsx2 Team +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. + +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +;; Fast VIF assembly routines for UNPACK zerofrog(@gmail.com) +;; NOTE: This file is used to build aVif_proc-[32/64].asm because ml has a very +;; weak preprocessor. To generate the files, install nasm and run the following command: +;; aVif_proc-32.asm: nasmw -e aVif.asm > aVif_proc-32.asm +;; aVif_proc-64.asm: nasmw -e -D__x86_64__ aVif.asm > aVif_proc-64.asm +;; once the files are built, remove all lines starting with %line +;; and remove the brackets from the exports + +%ifndef __x86_64__ +.686 +.model flat, c +.mmx +.xmm +%endif + +extern _vifRegs:abs +extern _vifMaskRegs:abs +extern _vifRow:abs +extern _vifCol:abs +extern s_TempDecompress:abs + + +.code + + +%ifdef __x86_64__ +%define VIF_SRC rdx +%define VIF_INC rdi +%define VIF_DST rcx +%define VIF_SIZE r8d +%define VIF_TMPADDR rax +%define VIF_SAVEEBX r9 +%define VIF_SAVEEBXd r9d +%else +%define VIF_SRC esi +%define VIF_INC ecx +%define VIF_DST edi +%define VIF_SIZE edx +%define VIF_TMPADDR eax +%define VIF_SAVEEBX ebx +%define VIF_SAVEEBXd ebx +%endif + +%define XMM_R0 xmm0 +%define XMM_R1 xmm1 +%define XMM_R2 xmm2 +%define XMM_WRITEMASK xmm3 +%define XMM_ROWMASK xmm4 +%define XMM_ROWCOLMASK xmm5 +%define XMM_ROW xmm6 +%define XMM_COL xmm7 +%define XMM_R3 XMM_COL + +;; writing masks +UNPACK_Write0_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [VIF_DST+DEST_OFFSET], r0 + endm + +UNPACK_Write1_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [VIF_DST], r0 + add VIF_DST, VIF_INC + endm + +UNPACK_Write0_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write0_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + +UNPACK_Write1_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write1_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + +;; masked write (dest needs to be in edi) +UNPACK_Write0_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + ;; masked write (dest needs to be in edi) + movdqa XMM_WRITEMASK, [VIF_TMPADDR + 64*(CL) + 48] + pand r0, XMM_WRITEMASK + pandn XMM_WRITEMASK, [VIF_DST] + por r0, XMM_WRITEMASK + MOVDQA [VIF_DST], r0 + add VIF_DST, 16 + endm + +;; masked write (dest needs to be in edi) +UNPACK_Write1_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + ;; masked write (dest needs to be in edi) + movdqa XMM_WRITEMASK, [VIF_TMPADDR + 64*(0) + 48] + pand r0, XMM_WRITEMASK + pandn XMM_WRITEMASK, [VIF_DST] + por r0, XMM_WRITEMASK + MOVDQA [VIF_DST], r0 + add VIF_DST, VIF_INC + endm + +UNPACK_Mask_SSE_0 macro r0 + pand r0, XMM_WRITEMASK + por r0, XMM_ROWCOLMASK + endm + +;; once a qword is uncomprssed, applies masks and saves +;; note: modifying XMM_WRITEMASK +;; dest = row + write (only when mask=0), otherwise write +UNPACK_Mask_SSE_1 macro r0 + ;; dest = row + write (only when mask=0), otherwise write + pand r0, XMM_WRITEMASK + por r0, XMM_ROWCOLMASK + pand XMM_WRITEMASK, XMM_ROW + paddd r0, XMM_WRITEMASK + endm + +;; dest = row + write (only when mask=0), otherwise write +;; row = row + write (only when mask = 0), otherwise row +UNPACK_Mask_SSE_2 macro r0 + ;; dest = row + write (only when mask=0), otherwise write + ;; row = row + write (only when mask = 0), otherwise row + pand r0, XMM_WRITEMASK + pand XMM_WRITEMASK, XMM_ROW + paddd XMM_ROW, r0 + por r0, XMM_ROWCOLMASK + paddd r0, XMM_WRITEMASK + endm + +UNPACK_WriteMask_SSE_0 macro r0 + UNPACK_Mask_SSE_0 r0 + endm +UNPACK_WriteMask_SSE_1 macro r0 + UNPACK_Mask_SSE_1 r0 + endm +UNPACK_WriteMask_SSE_2 macro r0 + UNPACK_Mask_SSE_2 r0 + endm + +UNPACK_Regular_SSE_0 macro r0 + endm + +UNPACK_Regular_SSE_1 macro r0 + paddd r0, XMM_ROW + endm + +UNPACK_Regular_SSE_2 macro r0 + paddd r0, XMM_ROW + movdqa XMM_ROW, r0 + endm + +;; setting up masks +UNPACK_Setup_Mask_SSE macro CL + mov VIF_TMPADDR, [_vifMaskRegs] + movdqa XMM_ROWMASK, [VIF_TMPADDR + 64*(CL) + 16] + movdqa XMM_ROWCOLMASK, [VIF_TMPADDR + 64*(CL) + 32] + movdqa XMM_WRITEMASK, [VIF_TMPADDR + 64*(CL)] + pand XMM_ROWMASK, XMM_ROW + pand XMM_ROWCOLMASK, XMM_COL + por XMM_ROWCOLMASK, XMM_ROWMASK + endm + +UNPACK_Start_Setup_Mask_SSE_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + +UNPACK_Start_Setup_Mask_SSE_1 macro CL + mov VIF_TMPADDR, [_vifMaskRegs] + movdqa XMM_ROWMASK, [VIF_TMPADDR + 64*(CL) + 16] + movdqa XMM_ROWCOLMASK, [VIF_TMPADDR + 64*(CL) + 32] + pand XMM_ROWMASK, XMM_ROW + pand XMM_ROWCOLMASK, XMM_COL + por XMM_ROWCOLMASK, XMM_ROWMASK + endm + +UNPACK_Start_Setup_Mask_SSE_2 macro CL + endm + +UNPACK_Setup_Mask_SSE_0_1 macro CL + endm +UNPACK_Setup_Mask_SSE_1_1 macro CL + mov VIF_TMPADDR, [_vifMaskRegs] + movdqa XMM_WRITEMASK, [VIF_TMPADDR + 64*(0)] + endm + +;; ignore CL, since vif.cycle.wl == 1 +UNPACK_Setup_Mask_SSE_2_1 macro CL + ;; ignore CL, since vif.cycle.wl == 1 + mov VIF_TMPADDR, [_vifMaskRegs] + movdqa XMM_ROWMASK, [VIF_TMPADDR + 64*(0) + 16] + movdqa XMM_ROWCOLMASK, [VIF_TMPADDR + 64*(0) + 32] + movdqa XMM_WRITEMASK, [VIF_TMPADDR + 64*(0)] + pand XMM_ROWMASK, XMM_ROW + pand XMM_ROWCOLMASK, XMM_COL + por XMM_ROWCOLMASK, XMM_ROWMASK + endm + +UNPACK_Setup_Mask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + +;; write mask always destroys XMM_WRITEMASK, so 0_0 = 1_0 +UNPACK_Setup_WriteMask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_0_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_1_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_2_1 macro CL + UNPACK_Setup_Mask_SSE_2_1 CL + endm + +UNPACK_Start_Setup_WriteMask_SSE_0 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_1 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_2 macro CL + UNPACK_Start_Setup_Mask_SSE_2 CL + endm + +UNPACK_Start_Setup_Regular_SSE_0 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_1 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_2 macro CL + endm +UNPACK_Setup_Regular_SSE_0_0 macro CL + endm +UNPACK_Setup_Regular_SSE_1_0 macro CL + endm +UNPACK_Setup_Regular_SSE_2_0 macro CL + endm +UNPACK_Setup_Regular_SSE_0_1 macro CL + endm +UNPACK_Setup_Regular_SSE_1_1 macro CL + endm +UNPACK_Setup_Regular_SSE_2_1 macro CL + endm + +UNPACK_INC_DST_0_Regular macro qw + add VIF_DST, (16*qw) + endm +UNPACK_INC_DST_1_Regular macro qw + endm +UNPACK_INC_DST_0_Mask macro qw + add VIF_DST, (16*qw) + endm +UNPACK_INC_DST_1_Mask macro qw + endm +UNPACK_INC_DST_0_WriteMask macro qw + endm +UNPACK_INC_DST_1_WriteMask macro qw + endm + +;; unpacks for 1,2,3,4 elements (V3 uses this directly) +UNPACK4_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R3 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R3, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + endm + +;; V3 uses this directly +UNPACK3_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + endm + +UNPACK2_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R1, CL+1, 16, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 2 + endm + +UNPACK1_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 1 + endm + +;; S-32 +;; only when cl==1 +UNPACK_S_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R3, [VIF_SRC] + + pshufd XMM_R0, XMM_R3, 0 + pshufd XMM_R1, XMM_R3, 055h + pshufd XMM_R2, XMM_R3, 0aah + pshufd XMM_R3, XMM_R3, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_S_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R2, [VIF_SRC] + + pshufd XMM_R0, XMM_R2, 0 + pshufd XMM_R1, XMM_R2, 055h + pshufd XMM_R2, XMM_R2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_S_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R1, QWORD PTR [VIF_SRC] + + pshufd XMM_R0, XMM_R1, 0 + pshufd XMM_R1, XMM_R1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_S_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + pshufd XMM_R0, XMM_R0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_S_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; S-16 +UNPACK_S_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R3, QWORD PTR [VIF_SRC] + punpcklwd XMM_R3, XMM_R3 + UNPACK_RIGHTSHIFT XMM_R3, 16 + + pshufd XMM_R0, XMM_R3, 0 + pshufd XMM_R1, XMM_R3, 055h + pshufd XMM_R2, XMM_R3, 0aah + pshufd XMM_R3, XMM_R3, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_S_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R2, QWORD PTR [VIF_SRC] + punpcklwd XMM_R2, XMM_R2 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + pshufd XMM_R0, XMM_R2, 0 + pshufd XMM_R1, XMM_R2, 055h + pshufd XMM_R2, XMM_R2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + add VIF_SRC, 6 + endm + +UNPACK_S_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R1, dword ptr [VIF_SRC] + punpcklwd XMM_R1, XMM_R1 + UNPACK_RIGHTSHIFT XMM_R1, 16 + + pshufd XMM_R0, XMM_R1, 0 + pshufd XMM_R1, XMM_R1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_S_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 16 + pshufd XMM_R0, XMM_R0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 2 + endm + +UNPACK_S_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; S-8 +UNPACK_S_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R3, dword ptr [VIF_SRC] + punpcklbw XMM_R3, XMM_R3 + punpcklwd XMM_R3, XMM_R3 + UNPACK_RIGHTSHIFT XMM_R3, 24 + + pshufd XMM_R0, XMM_R3, 0 + pshufd XMM_R1, XMM_R3, 055h + pshufd XMM_R2, XMM_R3, 0aah + pshufd XMM_R3, XMM_R3, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_S_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R2, dword ptr [VIF_SRC] + punpcklbw XMM_R2, XMM_R2 + punpcklwd XMM_R2, XMM_R2 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + pshufd XMM_R0, XMM_R2, 0 + pshufd XMM_R1, XMM_R2, 055h + pshufd XMM_R2, XMM_R2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 3 + endm + +UNPACK_S_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R1, dword ptr [VIF_SRC] + punpcklbw XMM_R1, XMM_R1 + punpcklwd XMM_R1, XMM_R1 + UNPACK_RIGHTSHIFT XMM_R1, 24 + + pshufd XMM_R0, XMM_R1, 0 + pshufd XMM_R1, XMM_R1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 2 + endm + +UNPACK_S_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + pshufd XMM_R0, XMM_R0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + inc VIF_SRC + endm + +UNPACK_S_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; V2-32 +UNPACK_V2_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + MOVDQA XMM_R0, [VIF_SRC] + MOVDQA XMM_R2, [VIF_SRC+16] + + pshufd XMM_R1, XMM_R0, 0eeh + pshufd XMM_R3, XMM_R2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V2_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+8] + movq XMM_R2, QWORD PTR [VIF_SRC+16] + movq XMM_R3, QWORD PTR [VIF_SRC+24] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V2_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + MOVDQA XMM_R0, [VIF_SRC] + movq XMM_R2, QWORD PTR [VIF_SRC+16] + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V2_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+8] + movq XMM_R2, QWORD PTR [VIF_SRC+16] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V2_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+8] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V2_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V2_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; V2-16 +UNPACK_V2_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + punpckhwd XMM_R2, [VIF_SRC] + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + pshufd XMM_R3, XMM_R2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + add VIF_SRC, 16 + endm + +UNPACK_V2_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + + punpckhwd XMM_R2, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + pshufd XMM_R3, XMM_R2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V2_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + punpckhwd XMM_R2, [VIF_SRC] + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V2_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + + punpckhwd XMM_R2, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V2_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + UNPACK_RIGHTSHIFT XMM_R0, 16 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V2_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 16 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V2_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + UNPACK_RIGHTSHIFT XMM_R0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_V2_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +;; V2-8 +UNPACK_V2_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + + punpcklbw XMM_R0, XMM_R0 + punpckhwd XMM_R2, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + pshufd XMM_R3, XMM_R2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V2_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + + punpcklbw XMM_R0, XMM_R0 + punpckhwd XMM_R2, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 6 + endm + +UNPACK_V2_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + ;; move the lower 64 bits down + pshufd XMM_R1, XMM_R0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_V2_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 2 + endm + +UNPACK_V2_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; V3-32 +UNPACK_V3_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R1, CL+1, 16, movdqa + + ;; midnight club 2 crashes because reading a qw at +36 is out of bounds + MOVDQA XMM_R3, [VIF_SRC+32] + movdqu XMM_R2, [VIF_SRC+24] + psrldq XMM_R3, 4 + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R3 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R3, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + + add VIF_SRC, 48 + endm + +UNPACK_V3_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R1, CL+1, 16, movdqa + + movdqu XMM_R2, [VIF_SRC+24] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) XMM_R2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) XMM_R2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + + add VIF_SRC, 36 + endm + +UNPACK_V3_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_2x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+12] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V3_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_1x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA XMM_R0, [VIF_SRC] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V3_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +;; V3-16 +UNPACK_V3_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+6] + + punpcklwd XMM_R0, XMM_R0 + movq XMM_R2, QWORD PTR [VIF_SRC+12] + punpcklwd XMM_R1, XMM_R1 + UNPACK_RIGHTSHIFT XMM_R0, 16 + movq XMM_R3, QWORD PTR [VIF_SRC+18] + UNPACK_RIGHTSHIFT XMM_R1, 16 + punpcklwd XMM_R2, XMM_R2 + punpcklwd XMM_R3, XMM_R3 + + UNPACK_RIGHTSHIFT XMM_R2, 16 + UNPACK_RIGHTSHIFT XMM_R3, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V3_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+6] + + punpcklwd XMM_R0, XMM_R0 + movq XMM_R2, QWORD PTR [VIF_SRC+12] + punpcklwd XMM_R1, XMM_R1 + UNPACK_RIGHTSHIFT XMM_R0, 16 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R1, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 18 + endm + +UNPACK_V3_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+6] + + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R1, XMM_R1 + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V3_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 6 + endm + +UNPACK_V3_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; V3-8 +UNPACK_V3_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R1, QWORD PTR [VIF_SRC] + movq XMM_R3, QWORD PTR [VIF_SRC+6] + + punpcklbw XMM_R1, XMM_R1 + punpcklbw XMM_R3, XMM_R3 + punpcklwd XMM_R0, XMM_R1 + psrldq XMM_R1, 6 + punpcklwd XMM_R2, XMM_R3 + psrldq XMM_R3, 6 + punpcklwd XMM_R1, XMM_R1 + UNPACK_RIGHTSHIFT XMM_R0, 24 + punpcklwd XMM_R3, XMM_R3 + + UNPACK_RIGHTSHIFT XMM_R2, 24 + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R3, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V3_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + movd XMM_R1, dword ptr [VIF_SRC+3] + + punpcklbw XMM_R0, XMM_R0 + movd XMM_R2, dword ptr [VIF_SRC+6] + punpcklbw XMM_R1, XMM_R1 + punpcklwd XMM_R0, XMM_R0 + punpcklbw XMM_R2, XMM_R2 + + punpcklwd XMM_R1, XMM_R1 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 9 + endm + +UNPACK_V3_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + movd XMM_R1, dword ptr [VIF_SRC+3] + + punpcklbw XMM_R0, XMM_R0 + punpcklbw XMM_R1, XMM_R1 + + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R1, XMM_R1 + + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 6 + endm + +UNPACK_V3_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 3 + endm + +UNPACK_V3_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; V4-32 +UNPACK_V4_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + movdqa XMM_R0, [VIF_SRC] + movdqa XMM_R1, [VIF_SRC+16] + movdqa XMM_R2, [VIF_SRC+32] + movdqa XMM_R3, [VIF_SRC+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 64 + endm + +UNPACK_V4_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+16] + movdqu XMM_R2, [VIF_SRC+32] + movdqu XMM_R3, [VIF_SRC+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 64 + endm + +UNPACK_V4_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + movdqa XMM_R0, [VIF_SRC] + movdqa XMM_R1, [VIF_SRC+16] + movdqa XMM_R2, [VIF_SRC+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 48 + endm + +UNPACK_V4_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+16] + movdqu XMM_R2, [VIF_SRC+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 48 + endm + +UNPACK_V4_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + movdqa XMM_R0, [VIF_SRC] + movdqa XMM_R1, [VIF_SRC+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V4_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + movdqu XMM_R1, [VIF_SRC+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V4_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + movdqa XMM_R0, [VIF_SRC] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V4_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +;; V4-16 +UNPACK_V4_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + + punpcklwd XMM_R0, [VIF_SRC] + punpckhwd XMM_R1, [VIF_SRC] + punpcklwd XMM_R2, [VIF_SRC+16] + punpckhwd XMM_R3, [VIF_SRC+16] + + UNPACK_RIGHTSHIFT XMM_R1, 16 + UNPACK_RIGHTSHIFT XMM_R3, 16 + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V4_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + movdqu XMM_R2, [VIF_SRC+16] + + punpckhwd XMM_R1, XMM_R0 + punpckhwd XMM_R3, XMM_R2 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R1, 16 + UNPACK_RIGHTSHIFT XMM_R3, 16 + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 32 + endm + +UNPACK_V4_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + punpckhwd XMM_R1, [VIF_SRC] + punpcklwd XMM_R2, [VIF_SRC+16] + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R1, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V4_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + movq XMM_R2, QWORD PTR [VIF_SRC+16] + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R1, 16 + UNPACK_RIGHTSHIFT XMM_R2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 24 + endm + +UNPACK_V4_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + punpckhwd XMM_R1, [VIF_SRC] + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V4_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movq XMM_R1, QWORD PTR [VIF_SRC+8] + + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R1, XMM_R1 + + UNPACK_RIGHTSHIFT XMM_R0, 16 + UNPACK_RIGHTSHIFT XMM_R1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V4_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd XMM_R0, [VIF_SRC] + UNPACK_RIGHTSHIFT XMM_R0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V4_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +;; V4-8 +UNPACK_V4_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklbw XMM_R0, [VIF_SRC] + punpckhbw XMM_R2, [VIF_SRC] + + punpckhwd XMM_R1, XMM_R0 + punpckhwd XMM_R3, XMM_R2 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R3, 24 + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V4_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu XMM_R0, [VIF_SRC] + + punpckhbw XMM_R2, XMM_R0 + punpcklbw XMM_R0, XMM_R0 + + punpckhwd XMM_R3, XMM_R2 + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R3, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R1, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 16 + endm + +UNPACK_V4_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklbw XMM_R0, [VIF_SRC] + punpckhbw XMM_R2, [VIF_SRC] + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V4_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + movd XMM_R2, dword ptr [VIF_SRC+8] + + punpcklbw XMM_R0, XMM_R0 + punpcklbw XMM_R2, XMM_R2 + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R0, 24 + UNPACK_RIGHTSHIFT XMM_R2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 12 + endm + +UNPACK_V4_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklbw XMM_R0, [VIF_SRC] + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V4_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq XMM_R0, QWORD PTR [VIF_SRC] + + punpcklbw XMM_R0, XMM_R0 + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + UNPACK_RIGHTSHIFT XMM_R1, 24 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V4_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklbw XMM_R0, [VIF_SRC] + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_V4_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd XMM_R0, dword ptr [VIF_SRC] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + UNPACK_RIGHTSHIFT XMM_R0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +;; V4-5 +DECOMPRESS_RGBA macro OFFSET + mov bl, al + shl bl, 3 + mov byte ptr [s_TempDecompress+OFFSET], bl + + mov bx, ax + shr bx, 2 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+1], bl + + mov bx, ax + shr bx, 7 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+2], bl + mov bx, ax + shr bx, 8 + and bx, 080h + mov byte ptr [s_TempDecompress+OFFSET+3], bl + endm + +UNPACK_V4_5SSE_4 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [VIF_SRC] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [VIF_SRC+4] + DECOMPRESS_RGBA 8 + + shr eax, 16 + DECOMPRESS_RGBA 12 + + ;; have to use movaps instead of movdqa +%ifdef __x86_64__ + movdqa XMM_R0, XMMWORD PTR [s_TempDecompress] +%else + movaps XMM_R0, [s_TempDecompress] +%endif + + punpckhbw XMM_R2, XMM_R0 + punpcklbw XMM_R0, XMM_R0 + + punpckhwd XMM_R3, XMM_R2 + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + psrld XMM_R0, 24 + psrld XMM_R1, 24 + psrld XMM_R2, 24 + psrld XMM_R3, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 8 + endm + +UNPACK_V4_5SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_3 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [VIF_SRC] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [VIF_SRC] + DECOMPRESS_RGBA 8 + + ;; have to use movaps instead of movdqa +%ifdef __x86_64__ + movdqa XMM_R0, XMMWORD PTR [s_TempDecompress] +%else + movaps XMM_R0, [s_TempDecompress] +%endif + + punpckhbw XMM_R2, XMM_R0 + punpcklbw XMM_R0, XMM_R0 + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + punpcklwd XMM_R2, XMM_R2 + + psrld XMM_R0, 24 + psrld XMM_R1, 24 + psrld XMM_R2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 6 + endm + +UNPACK_V4_5SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_2 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [VIF_SRC] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + movq XMM_R0, QWORD PTR [s_TempDecompress] + + punpcklbw XMM_R0, XMM_R0 + + punpckhwd XMM_R1, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + psrld XMM_R0, 24 + psrld XMM_R1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 4 + endm + +UNPACK_V4_5SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_1 macro CL, TOTALCL, MaskType, ModeType + mov ax, word ptr [VIF_SRC] + DECOMPRESS_RGBA 0 + + movd XMM_R0, DWORD PTR [s_TempDecompress] + punpcklbw XMM_R0, XMM_R0 + punpcklwd XMM_R0, XMM_R0 + + psrld XMM_R0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add VIF_SRC, 2 + endm + +UNPACK_V4_5SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_1 CL, TOTALCL, MaskType, ModeType + endm + +;; save the row reg +SAVE_ROW_REG_BASE macro + mov VIF_TMPADDR, [_vifRow] + movdqa [VIF_TMPADDR], XMM_ROW + mov VIF_TMPADDR, [_vifRegs] + movss dword ptr [VIF_TMPADDR+0100h], XMM_ROW + psrldq XMM_ROW, 4 + movss dword ptr [VIF_TMPADDR+0110h], XMM_ROW + psrldq XMM_ROW, 4 + movss dword ptr [VIF_TMPADDR+0120h], XMM_ROW + psrldq XMM_ROW, 4 + movss dword ptr [VIF_TMPADDR+0130h], XMM_ROW + endm + +SAVE_NO_REG macro + endm + +%ifdef __x86_64__ + +INIT_ARGS macro + mov rax, qword ptr [_vifRow] + mov r9, qword ptr [_vifCol] + movaps xmm6, XMMWORD PTR [rax] + movaps xmm7, XMMWORD PTR [r9] + endm + +INC_STACK macro reg + add esp, 8 + endm + +%else + +%define STACKOFFSET 12 + +;; 32 bit versions have the args on the stack +INIT_ARGS macro + mov VIF_DST, dword ptr [esp+4+STACKOFFSET] + mov VIF_SRC, dword ptr [esp+8+STACKOFFSET] + mov VIF_SIZE, dword ptr [esp+12+STACKOFFSET] + endm + +INC_STACK macro reg + add esp, 4 + endm + +%endif + +;; qsize - bytes of compressed size of 1 decompressed qword +;; int UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType(u32* dest, u32* data, int dmasize) +defUNPACK_SkippingWrite macro name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType) proc public +%ifdef __x86_64__ + push rdi +%else + push edi + push esi + push ebx +%endif + INIT_ARGS + mov VIF_TMPADDR, [_vifRegs] + movzx VIF_INC, byte ptr [VIF_TMPADDR + 040h] + movzx VIF_SAVEEBX, byte ptr [VIF_TMPADDR + 041h] + sub VIF_INC, VIF_SAVEEBX + shl VIF_INC, 4 + + cmp VIF_SAVEEBXd, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1) + cmp VIF_SAVEEBXd, 2 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2) + cmp VIF_SAVEEBXd, 3 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1): + @CatStr(UNPACK_Start_Setup_, MaskType, _SSE_, ModeType) 0 + + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + + add VIF_INC, 16 + + ;; first align VIF_SRC to 16 bytes +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16): + + test VIF_SRC, 15 + jz @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned) + + @CatStr(UNPACK_, name, SSE_1) 0, 1, MaskType, ModeType + + cmp VIF_SIZE, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec) + sub VIF_SIZE, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned): + + cmp VIF_SIZE, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp VIF_SIZE, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + cmp VIF_SIZE, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3) + prefetchnta [VIF_SRC + 64] + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4): + @CatStr(UNPACK_, name, SSE_4A) 0, 1, MaskType, ModeType + + cmp VIF_SIZE, (8*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4) + sub VIF_SIZE, (4*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4): + + sub VIF_SIZE, (4*qsize) + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + cmp VIF_SIZE, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp VIF_SIZE, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + ;; fall through + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3): + @CatStr(UNPACK_, name, SSE_3A) 0, 1, MaskType, ModeType + + sub VIF_SIZE, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2): + @CatStr(UNPACK_, name, SSE_2A) 0, 1, MaskType, ModeType + + sub VIF_SIZE, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1): + @CatStr(UNPACK_, name, SSE_1A) 0, 1, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec): + sub VIF_SIZE, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3): + SAVE_ROW_REG + mov eax, VIF_SIZE +%ifdef __x86_64__ + pop rdi +%else + pop ebx + pop esi + pop edi +%endif + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2): + cmp VIF_SIZE, (2*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + ;; take into account wl + add VIF_DST, VIF_INC + cmp VIF_SIZE, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2) + sub VIF_SIZE, (2*qsize) + ;; unpack next + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2): + sub VIF_SIZE, (2*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3): + cmp VIF_SIZE, qsize + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4) + + ;; execute left over qw + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + sub VIF_SIZE, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4): + + SAVE_ROW_REG + mov eax, VIF_SIZE +%ifdef __x86_64__ + pop rdi +%else + pop ebx + pop esi + pop edi +%endif + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3): + cmp VIF_SIZE, (3*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + add VIF_DST, VIF_INC + cmp VIF_SIZE, (6*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2) + sub VIF_SIZE, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2): + sub VIF_SIZE, (3*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5): + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) + + cmp VIF_SIZE, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3) + + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + sub VIF_SIZE, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3): + sub VIF_SIZE, qsize + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4): + SAVE_ROW_REG + mov eax, VIF_SIZE +%ifdef __x86_64__ + pop rdi +%else + pop ebx + pop esi + pop edi +%endif + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4): + sub VIF_SAVEEBX, 3 + push VIF_INC + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack): + cmp VIF_SIZE, (3*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3) + cmp VIF_SIZE, (2*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2) + + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + ;; not enough data left + sub VIF_SIZE, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + ;; not enough data left + sub VIF_SIZE, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + ;; more data left, process 1qw at a time + sub VIF_SIZE, (3*qsize) + mov VIF_INC, VIF_SAVEEBX + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX): + + ;; check if any data left + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + + @CatStr(UNPACK_, name, SSE_1) 3, 0, MaskType, ModeType + + sub VIF_SIZE, qsize + cmp VIF_INC, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop) + sub VIF_INC, 1 + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop): + add VIF_DST, [esp] + cmp VIF_SIZE, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done): + + SAVE_ROW_REG + INC_STACK() + mov eax, VIF_SIZE + +%ifdef __x86_64__ + pop rdi +%else + pop ebx + pop esi + pop edi +%endif + ret +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType endp) +endm + +UNPACK_RIGHTSHIFT macro reg, shift + psrld reg, shift + endm + +defUNPACK_SkippingWrite2 macro name, qsize + defUNPACK_SkippingWrite name, Regular, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2 S_32, 4 +defUNPACK_SkippingWrite2 S_16, 2 +defUNPACK_SkippingWrite2 S_8, 1 +defUNPACK_SkippingWrite2 V2_32, 8 +defUNPACK_SkippingWrite2 V2_16, 4 +defUNPACK_SkippingWrite2 V2_8, 2 +defUNPACK_SkippingWrite2 V3_32, 12 +defUNPACK_SkippingWrite2 V3_16, 6 +defUNPACK_SkippingWrite2 V3_8, 3 +defUNPACK_SkippingWrite2 V4_32, 16 +defUNPACK_SkippingWrite2 V4_16, 8 +defUNPACK_SkippingWrite2 V4_8, 4 +defUNPACK_SkippingWrite2 V4_5, 2 + +UNPACK_RIGHTSHIFT macro reg, shift + psrad reg, shift + endm + + +defUNPACK_SkippingWrite2a macro name, qsize + defUNPACK_SkippingWrite name, Mask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2a S_16, 2 +defUNPACK_SkippingWrite2a S_8, 1 +defUNPACK_SkippingWrite2a V2_16, 4 +defUNPACK_SkippingWrite2a V2_8, 2 +defUNPACK_SkippingWrite2a V3_16, 6 +defUNPACK_SkippingWrite2a V3_8, 3 +defUNPACK_SkippingWrite2a V4_16, 8 +defUNPACK_SkippingWrite2a V4_8, 4 + +end diff --git a/pcsx2/x86/fast_routines.S b/pcsx2/x86/fast_routines.S new file mode 100644 index 0000000..61f1f2b --- /dev/null +++ b/pcsx2/x86/fast_routines.S @@ -0,0 +1,351 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Fast assembly routines for x86-64 +// zerofrog(@gmail.com) +.intel_syntax +.extern g_EEFreezeRegs +.extern FreezeMMXRegs_ + +// mmx memcmp implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +// u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +#ifdef __x86_64__ +#define MEMCMP_SRC1 %rdi +#define MEMCMP_SRC2 %rsi +#define MEMCMP_SIZE %edx +#else +#define MEMCMP_SRC1 %edx +#define MEMCMP_SRC2 %esi +#define MEMCMP_SIZE %ecx +#endif + +.globl memcmp_mmx + .type memcmp_mmx, @function +memcmp_mmx: +#ifndef __x86_64__ + // make sure mmx regs are stored + // FreezeMMXRegs(1); + cmp dword ptr [g_EEFreezeRegs], 0 + je memcmp_mmx_begin + push 1 + call FreezeMMXRegs_ + add %esp, 4 + +memcmp_mmx_begin: + push %esi + mov MEMCMP_SRC1, dword ptr [%esp+8] + mov MEMCMP_SRC2, dword ptr [%esp+12] + mov MEMCMP_SIZE, dword ptr [%esp+16] +#endif + + cmp MEMCMP_SIZE, 32 + jl memcmp_Done4 + + // custom test first 8 to make sure things are ok + movq %mm0, [MEMCMP_SRC2] + movq %mm1, [MEMCMP_SRC2+8] + pcmpeqd %mm0, [MEMCMP_SRC1] + pcmpeqd %mm1, [MEMCMP_SRC1+8] + pand %mm0, %mm1 + movq %mm2, [MEMCMP_SRC2+16] + pmovmskb %eax, %mm0 + movq %mm3, [MEMCMP_SRC2+24] + + // check if eq + cmp %eax, 0xff + je memcmp_NextComp + mov %eax, 1 + jmp memcmp_End + +memcmp_NextComp: + pcmpeqd %mm2, [MEMCMP_SRC1+16] + pcmpeqd %mm3, [MEMCMP_SRC1+24] + pand %mm2, %mm3 + pmovmskb %eax, %mm2 + + sub MEMCMP_SIZE, 32 + add MEMCMP_SRC2, 32 + add MEMCMP_SRC1, 32 + + // check if eq + cmp %eax, 0xff + je memcmp_ContinueTest + mov %eax, 1 + jmp memcmp_End + + cmp MEMCMP_SIZE, 64 + jl memcmp_Done8 + +memcmp_Cmp8: + movq %mm0, [MEMCMP_SRC2] + movq %mm1, [MEMCMP_SRC2+8] + movq %mm2, [MEMCMP_SRC2+16] + movq %mm3, [MEMCMP_SRC2+24] + movq %mm4, [MEMCMP_SRC2+32] + movq %mm5, [MEMCMP_SRC2+40] + movq %mm6, [MEMCMP_SRC2+48] + movq %mm7, [MEMCMP_SRC2+56] + pcmpeqd %mm0, [MEMCMP_SRC1] + pcmpeqd %mm1, [MEMCMP_SRC1+8] + pcmpeqd %mm2, [MEMCMP_SRC1+16] + pcmpeqd %mm3, [MEMCMP_SRC1+24] + pand %mm0, %mm1 + pcmpeqd %mm4, [MEMCMP_SRC1+32] + pand %mm0, %mm2 + pcmpeqd %mm5, [MEMCMP_SRC1+40] + pand %mm0, %mm3 + pcmpeqd %mm6, [MEMCMP_SRC1+48] + pand %mm0, %mm4 + pcmpeqd %mm7, [MEMCMP_SRC1+56] + pand %mm0, %mm5 + pand %mm0, %mm6 + pand %mm0, %mm7 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je memcmp_Continue + mov %eax, 1 + jmp memcmp_End + +memcmp_Continue: + sub MEMCMP_SIZE, 64 + add MEMCMP_SRC2, 64 + add MEMCMP_SRC1, 64 +memcmp_ContinueTest: + cmp MEMCMP_SIZE, 64 + jge memcmp_Cmp8 + +memcmp_Done8: + test MEMCMP_SIZE, 0x20 + jz memcmp_Done4 + movq %mm0, [MEMCMP_SRC2] + movq %mm1, [MEMCMP_SRC2+8] + movq %mm2, [MEMCMP_SRC2+16] + movq %mm3, [MEMCMP_SRC2+24] + pcmpeqd %mm0, [MEMCMP_SRC1] + pcmpeqd %mm1, [MEMCMP_SRC1+8] + pcmpeqd %mm2, [MEMCMP_SRC1+16] + pcmpeqd %mm3, [MEMCMP_SRC1+24] + pand %mm0, %mm1 + pand %mm0, %mm2 + pand %mm0, %mm3 + pmovmskb %eax, %mm0 + sub MEMCMP_SIZE, 32 + add MEMCMP_SRC2, 32 + add MEMCMP_SRC1, 32 + + // check if eq + cmp %eax, 0xff + je memcmp_Done4 + mov %eax, 1 + jmp memcmp_End + +memcmp_Done4: + cmp MEMCMP_SIZE, 24 + jne memcmp_Done2 + movq %mm0, [MEMCMP_SRC2] + movq %mm1, [MEMCMP_SRC2+8] + movq %mm2, [MEMCMP_SRC2+16] + pcmpeqd %mm0, [MEMCMP_SRC1] + pcmpeqd %mm1, [MEMCMP_SRC1+8] + pcmpeqd %mm2, [MEMCMP_SRC1+16] + pand %mm0, %mm1 + pand %mm0, %mm2 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je memcmp_Done + mov %eax, 1 + jmp memcmp_End + +memcmp_Done2: + cmp MEMCMP_SIZE, 16 + jne memcmp_Done1 + + movq %mm0, [MEMCMP_SRC2] + movq %mm1, [MEMCMP_SRC2+8] + pcmpeqd %mm0, [MEMCMP_SRC1] + pcmpeqd %mm1, [MEMCMP_SRC1+8] + pand %mm0, %mm1 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je memcmp_Done + mov %eax, 1 + jmp memcmp_End + +memcmp_Done1: + cmp MEMCMP_SIZE, 8 + jne memcmp_Done + + mov %eax, [MEMCMP_SRC2] + mov MEMCMP_SRC2, [MEMCMP_SRC2+4] + cmp %eax, [MEMCMP_SRC1] + je memcmp_Next + mov %eax, 1 + jmp memcmp_End + +memcmp_Next: + cmp MEMCMP_SRC2, [MEMCMP_SRC1+4] + je memcmp_Done + mov %eax, 1 + jmp memcmp_End + +memcmp_Done: + xor %eax, %eax + +memcmp_End: + emms +#ifndef __x86_64__ + pop %esi +#endif + ret + +// memxor_mmx +#ifdef __x86_64__ +#define MEMXOR_SRC1 %rdi +#define MEMXOR_SRC2 %rsi +#define MEMXOR_SIZE %edx +#else +#define MEMXOR_SRC1 %edx +#define MEMXOR_SRC2 %esi +#define MEMXOR_SIZE %ecx +#endif + +.globl memxor_mmx + .type memxor_mmx, @function +memxor_mmx: +#ifndef __x86_64__ + // make sure mmx regs are stored + // FreezeMMXRegs(1); + cmp dword ptr [g_EEFreezeRegs], 0 + je memxor_mmx_begin + push 1 + call FreezeMMXRegs_ + add %esp, 4 + +memxor_mmx_begin: + push %esi + mov MEMXOR_SRC1, dword ptr [%esp+8] + mov MEMXOR_SRC2, dword ptr [%esp+12] + mov MEMXOR_SIZE, dword ptr [%esp+16] +#endif + cmp MEMXOR_SIZE, 64 + jl memxor_Setup4 + + movq %mm0, [MEMXOR_SRC2] + movq %mm1, [MEMXOR_SRC2+8] + movq %mm2, [MEMXOR_SRC2+16] + movq %mm3, [MEMXOR_SRC2+24] + movq %mm4, [MEMXOR_SRC2+32] + movq %mm5, [MEMXOR_SRC2+40] + movq %mm6, [MEMXOR_SRC2+48] + movq %mm7, [MEMXOR_SRC2+56] + sub MEMXOR_SIZE, 64 + add MEMXOR_SRC2, 64 + cmp MEMXOR_SIZE, 64 + jl memxor_End8 + +memxor_Cmp8: + pxor %mm0, [MEMXOR_SRC2] + pxor %mm1, [MEMXOR_SRC2+8] + pxor %mm2, [MEMXOR_SRC2+16] + pxor %mm3, [MEMXOR_SRC2+24] + pxor %mm4, [MEMXOR_SRC2+32] + pxor %mm5, [MEMXOR_SRC2+40] + pxor %mm6, [MEMXOR_SRC2+48] + pxor %mm7, [MEMXOR_SRC2+56] + + sub MEMXOR_SIZE, 64 + add MEMXOR_SRC2, 64 + cmp MEMXOR_SIZE, 64 + jge memxor_Cmp8 + +memxor_End8: + pxor %mm0, %mm4 + pxor %mm1, %mm5 + pxor %mm2, %mm6 + pxor %mm3, %mm7 + + cmp MEMXOR_SIZE, 32 + jl memxor_End4 + pxor %mm0, [MEMXOR_SRC2] + pxor %mm1, [MEMXOR_SRC2+8] + pxor %mm2, [MEMXOR_SRC2+16] + pxor %mm3, [MEMXOR_SRC2+24] + sub MEMXOR_SIZE, 32 + add MEMXOR_SRC2, 32 + jmp memxor_End4 + +memxor_Setup4: + cmp MEMXOR_SIZE, 32 + jl memxor_Setup2 + + movq %mm0, [MEMXOR_SRC2] + movq %mm1, [MEMXOR_SRC2+8] + movq %mm2, [MEMXOR_SRC2+16] + movq %mm3, [MEMXOR_SRC2+24] + sub MEMXOR_SIZE, 32 + add MEMXOR_SRC2, 32 + +memxor_End4: + pxor %mm0, %mm2 + pxor %mm1, %mm3 + + cmp MEMXOR_SIZE, 16 + jl memxor_End2 + pxor %mm0, [MEMXOR_SRC2] + pxor %mm1, [MEMXOR_SRC2+8] + sub MEMXOR_SIZE, 16 + add MEMXOR_SRC2, 16 + jmp memxor_End2 + +memxor_Setup2: + cmp MEMXOR_SIZE, 16 + jl memxor_Setup1 + + movq %mm0, [MEMXOR_SRC2] + movq %mm1, [MEMXOR_SRC2+8] + sub MEMXOR_SIZE, 16 + add MEMXOR_SRC2, 16 + +memxor_End2: + pxor %mm0, %mm1 + + cmp MEMXOR_SIZE, 8 + jl memxor_End1 + pxor %mm0, [MEMXOR_SRC2] +memxor_End1: + movq [MEMXOR_SRC1], %mm0 + jmp memxor_End + +memxor_Setup1: + movq %mm0, [MEMXOR_SRC2] + movq [MEMXOR_SRC1], %mm0 +memxor_End: + emms +#ifndef __x86_64__ + pop %esi +#endif + ret diff --git a/pcsx2/x86/fast_routines.cpp b/pcsx2/x86/fast_routines.cpp new file mode 100644 index 0000000..b754796 --- /dev/null +++ b/pcsx2/x86/fast_routines.cpp @@ -0,0 +1,595 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +//#include + +// Inline assembly syntax for use with Visual C++ +extern "C" { + +#ifdef _WIN32 +#include +#endif + +#include "PS2Etypes.h" +#include "Misc.h" + +#if defined(_MSC_VER) && !defined(__x86_64__) + +#ifdef _DEBUG +extern char g_globalMMXLocked, g_globalMMXSaved; + +void checkregs() +{ + assert( !g_globalMMXLocked || g_globalMMXSaved ); +} +#endif + +void * memcpy_amd_(void *dest, const void *src, size_t n) +{ + FreezeMMXRegs(1); + +#ifdef _DEBUG + __asm call checkregs +#endif + + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + push esi + mov ecx, cmpsize + mov edx, src1 + mov esi, src2 + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je ContinueTest + mov eax, 1 + jmp End + + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pcmpeqd mm4, [edx+32] + pand mm0, mm2 + pcmpeqd mm5, [edx+40] + pand mm0, mm3 + pcmpeqd mm6, [edx+48] + pand mm0, mm4 + pcmpeqd mm7, [edx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edx, 64 +ContinueTest: + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je Done4 + mov eax, 1 + jmp End + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov esi, [esi+4] + cmp eax, [edx] + je Next + mov eax, 1 + jmp End + +Next: + cmp esi, [edx+4] + setne al + jmp End + +Done: + xor eax, eax + +End: + pop esi + emms + } +} + + +// returns the xor of all elements, cmpsize has to be mult of 8 +void memxor_mmx(void* dst, const void* src1, int cmpsize) +{ + FreezeMMXRegs(1); + assert( (cmpsize&7) == 0 ); + + __asm { + mov ecx, cmpsize + mov eax, src1 + mov edx, dst + + cmp ecx, 64 + jl Setup4 + + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + movq mm4, [eax+32] + movq mm5, [eax+40] + movq mm6, [eax+48] + movq mm7, [eax+56] + sub ecx, 64 + add eax, 64 + cmp ecx, 64 + jl End8 + +Cmp8: + pxor mm0, [eax] + pxor mm1, [eax+8] + pxor mm2, [eax+16] + pxor mm3, [eax+24] + pxor mm4, [eax+32] + pxor mm5, [eax+40] + pxor mm6, [eax+48] + pxor mm7, [eax+56] + + sub ecx, 64 + add eax, 64 + cmp ecx, 64 + jge Cmp8 + +End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp ecx, 32 + jl End4 + pxor mm0, [eax] + pxor mm1, [eax+8] + pxor mm2, [eax+16] + pxor mm3, [eax+24] + sub ecx, 32 + add eax, 32 + jmp End4 + +Setup4: + cmp ecx, 32 + jl Setup2 + + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + sub ecx, 32 + add eax, 32 + +End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp ecx, 16 + jl End2 + pxor mm0, [eax] + pxor mm1, [eax+8] + sub ecx, 16 + add eax, 16 + jmp End2 + +Setup2: + cmp ecx, 16 + jl Setup1 + + movq mm0, [eax] + movq mm1, [eax+8] + sub ecx, 16 + add eax, 16 + +End2: + pxor mm0, mm1 + + cmp ecx, 8 + jl End1 + pxor mm0, [eax] +End1: + movq [edx], mm0 + jmp End + +Setup1: + movq mm0, [eax] + movq [edx], mm0 +End: + emms + } +} + +#endif + +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iCOP2.c b/pcsx2/x86/iCOP2.c new file mode 100644 index 0000000..beda688 --- /dev/null +++ b/pcsx2/x86/iCOP2.c @@ -0,0 +1,861 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#include +#include +#include +#include "Common.h" +#include "DebugTools/Debug.h" +#include "R5900.h" +#include "InterTables.h" +#include "VUmicro.h" +#include "iVU0micro.h" +#include "iVUmicro.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// cycle cycles statusflag macflag clipflag +_vuopinfo g_cop2info = {0, 0, 1, 1, 1, 0, 0}; + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define _Fsf_ ((cpuRegs.code >> 21) & 0x03) +#define _Ftf_ ((cpuRegs.code >> 23) & 0x03) +#define _Cc_ (cpuRegs.code & 0x03) + +#define REC_COP2_FUNC(f, delreg) \ + void f(); \ + void rec##f() { \ + SysPrintf("cop2 "#f" called\n"); \ + X86_32CODE(SetFPUstate()); \ + MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((uptr)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_NOCONST); \ + CALLFunc((uptr)f); \ + _freeX86regs(); \ + branch = 2; \ +} + +#define INTERPRETATE_COP2_FUNC(f) \ +void recV##f() { \ + MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((uptr)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((uptr)V##f); \ + _freeX86regs(); \ +} + +#define REC_COP2_VU0(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +extern u32 dumplog; +#define REC_COP2_VU0_Q(f) \ +void recV##f() { \ + recVU0MI_##f(); \ + _freeX86regs(); \ +} + +void rec_C2UNK() +{ + SysPrintf("Cop2 bad opcode:%x\n",cpuRegs.code); +} + +void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) +{ + SysPrintf("Cop2 bad _vuRegs code:%x\n",cpuRegs.code); +} + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn); + +void (*recCOP2t[32])(); +void (*recCOP2_BC2t[32])(); +void (*recCOP2SPECIAL1t[64])(); +void (*recCOP2SPECIAL2t[128])(); + +void recCOP2(); +void recCOP2_SPECIAL(); +void recCOP2_BC2(); +void recCOP2_SPECIAL2(); + +extern void _vu0WaitMicro(); + +static void recCFC2() +{ + int mmreg, creg; + + if (cpuRegs.code & 1) { + iFlushCall(IS_X8664?(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86):FLUSH_NOCONST); + CALLFunc((uptr)_vu0WaitMicro); + } + + if(!_Rt_) return; + + _deleteGPRtoXMMreg(_Rt_, 2); + +#ifdef __x86_64__ + mmreg = _allocX86reg(-1, X86TYPE_GPR, _Rt_, MODE_WRITE); + + if( (creg = _checkX86reg(X86TYPE_VI, _Fs_, MODE_READ)) >= 0 ) { + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // zero extending + MOVZX64R16toR(mmreg, creg); + } + else { + // sign extend, use full 32 bits + MOV32RtoR(mmreg, creg); + SHL64ItoR(mmreg, 32); + SAR64ItoR(mmreg, 32); + } + } + else { + // just move + MOV32RtoR(mmreg, creg); + EEINST_RESETHASLIVE1(_Rt_); + } + } + else { + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // zero extending + MOVZX64M16toR(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL); + } + else { + // sign extend, use full 32 bits + MOV32MtoR(RAX, (uptr)&VU0.VI[ _Fs_ ].UL); + CDQE(); + MOV64RtoR(mmreg, RAX); + } + } + else { + // just move + MOV32MtoR(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL); + EEINST_RESETHASLIVE1(_Rt_); + } + } +#else + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE)) >= 0 ) { + + if( _Fs_ >= 16 ) { + MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL); + + if( EEINST_ISLIVE1(_Rt_) ) { + _signExtendGPRtoMMX(mmreg, _Rt_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + else { + MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL); + } + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (uptr)&VU0.VI[ _Fs_ ].UL); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + if( _Fs_ < 16 ) { + // no sign extending + MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1],0); + } + else { + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } +#endif + + _eeOnWriteReg(_Rt_, 1); +} + +static void recCTC2() +{ + int mmreg; + + if (cpuRegs.code & 1) { + iFlushCall(IS_X8664?(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86):FLUSH_NOCONST); + CALLFunc((uptr)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( GPR_IS_CONST1(_Rt_) ) { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + + if( g_cpuConstRegs[_Rt_].UL[0] & 0x202 ) + iFlushCall(FLUSH_FREE_TEMPX86); + _deleteX86reg(X86TYPE_VI, REG_FBRST, 2); + + if( g_cpuConstRegs[_Rt_].UL[0] & 2 ) { + CALLFunc((uptr)vu0ResetRegs); + } + + if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 ) { + CALLFunc((uptr)vu1ResetRegs); + } + + MOV16ItoM((uptr)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c); + break; + + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(IS_X8664?FLUSH_FREE_TEMPX86:FLUSH_NOCONST); // since CALLFunc + assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 && + _checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 ); + + // ignore if VU1 is operating + TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + MOV32ItoM((uptr)&VU1.VI[REG_TPC].UL, g_cpuConstRegs[_Rt_].UL[0]&0xffff); + // Execute VU1 Micro SubRoutine + _callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff); + + x86SetJ8( j8Ptr[0] ); + break; + default: + if( _Fs_ < 16 ) + assert( (g_cpuConstRegs[_Rt_].UL[0]&0xffff0000)==0); + +#ifdef __x86_64__ + if( (mmreg = _checkX86reg(X86TYPE_VI, _Fs_, MODE_WRITE)) >= 0 ) + MOV32ItoR(mmreg, g_cpuConstRegs[_Rt_].UL[0]); + else +#else + MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); +#endif + + // a lot of games have vu0 spinning on some integer + // then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck) + iFlushCall(IS_X8664?(FLUSH_FREE_TEMPX86|FLUSH_FREE_VU0):FLUSH_NOCONST); + TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 1); + j8Ptr[0] = JZ8(0); + CALLFunc((uptr)Cpu->ExecuteVU0Block); + +#ifdef __x86_64__ + _callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 0); +#else + PUSH32I(0); + CALLFunc((uptr)FreezeXMMRegs_); + CALLFunc((uptr)FreezeMMXRegs_); + ADD32ItoR(ESP, 4); +#endif + x86SetJ8(j8Ptr[0]); + break; + } + } + else { + switch(_Fs_) { + case REG_MAC_FLAG: // read-only + case REG_TPC: // read-only + case REG_VPU_STAT: // read-only + break; + case REG_FBRST: + iFlushCall(FLUSH_FREE_TEMPX86); + assert( _checkX86reg(X86TYPE_VI, REG_FBRST, 0) < 0 ); + + _eeMoveGPRtoR(EAX, _Rt_); + + TEST32ItoR(EAX,0x2); + j8Ptr[0] = JZ8(0); + CALLFunc((uptr)vu0ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX,0x200); + j8Ptr[0] = JZ8(0); + CALLFunc((uptr)vu1ResetRegs); + _eeMoveGPRtoR(EAX, _Rt_); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EAX,0x0C0C); + MOV16RtoM((uptr)&VU0.VI[REG_FBRST].UL,EAX); + break; + case REG_CMSAR1: // REG_CMSAR1 + + iFlushCall(IS_X8664?FLUSH_FREE_TEMPX86:FLUSH_NOCONST); // since CALLFunc + + // ignore if VU1 is operating + TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); + j8Ptr[0] = JNZ8(0); + + _eeMoveGPRtoR(EAX, _Rt_); + MOV16RtoM((uptr)&VU1.VI[REG_TPC].UL,EAX); + + _callFunctionArg1((uptr)vu1ExecMicro, MEM_X86TAG|EAX, 0); // Execute VU1 Micro SubRoutine + + x86SetJ8( j8Ptr[0] ); + break; + default: +#ifdef __x86_64__ + if( (mmreg = _checkX86reg(X86TYPE_VI, _Fs_, MODE_WRITE)) >= 0 ) + _eeMoveGPRtoR(mmreg, _Rt_); + else +#else + _eeMoveGPRtoM((uptr)&VU0.VI[_Fs_].UL,_Rt_); +#endif + + // a lot of games have vu0 spinning on some integer + // then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck) + iFlushCall(IS_X8664?(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86):FLUSH_NOCONST); + TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 1); + j8Ptr[0] = JZ8(0); + CALLFunc((uptr)Cpu->ExecuteVU0Block); + +#ifdef __x86_64__ + _callFunctionArg1((uptr)FreezeXMMRegs_, MEM_CONSTTAG, 0); +#else + PUSH32I(0); + CALLFunc((uptr)FreezeXMMRegs_); + CALLFunc((uptr)FreezeMMXRegs_); + ADD32ItoR(ESP, 4); +#endif + x86SetJ8(j8Ptr[0]); + break; + } + } +} + +static void recQMFC2(void) +{ + int t0reg, fsreg; + _xmmregs temp; + + if (cpuRegs.code & 1) { + iFlushCall(IS_X8664?(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86):FLUSH_NOCONST); + CALLFunc((uptr)_vu0WaitMicro); + } + + if(!_Rt_) return; + +#ifndef __x86_64__ + _deleteMMXreg(MMX_GPR+_Rt_, 2); +#endif + + _deleteX86reg(X86TYPE_GPR, _Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + + // could 'borrow' the reg + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ); + + if( fsreg >= 0 ) { + if( xmmregs[fsreg].mode & MODE_WRITE ) { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg); + + // change regs + temp = xmmregs[t0reg]; + xmmregs[t0reg] = xmmregs[fsreg]; + xmmregs[fsreg] = temp; + } + else { + // swap regs + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + + xmmregs[fsreg] = xmmregs[t0reg]; + xmmregs[t0reg].inuse = 0; + } + } + else { + t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( t0reg >= 0 ) { + SSE_MOVAPS_M128_to_XMM( t0reg, (uptr)&VU0.VF[_Fs_].UD[0]); + } + else { + _recMove128MtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], (uptr)&VU0.VF[_Fs_].UL[0]); + } + } + + _clearNeededXMMregs(); +} + +static void recQMTC2() +{ + int mmreg, fsreg; + + if (cpuRegs.code & 1) { + iFlushCall(IS_X8664?(FLUSH_FREE_VU0|FLUSH_FREE_TEMPX86):FLUSH_NOCONST); + CALLFunc((uptr)_vu0WaitMicro); + } + + if(!_Fs_) return; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg); + } + else { + // swap regs + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((uptr)&cpuRegs.GPR.r[_Rt_], mmreg); + + xmmregs[mmreg] = xmmregs[fsreg]; + xmmregs[mmreg].mode = MODE_WRITE; + xmmregs[fsreg].inuse = 0; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + + if( (xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) + SSE_MOVAPS_XMM_to_M128((uptr)&cpuRegs.GPR.r[_Rt_], mmreg); + + // swap regs + xmmregs[mmreg].type = XMMTYPE_VFREG; + xmmregs[mmreg].VU = 0; + xmmregs[mmreg].reg = _Fs_; + xmmregs[mmreg].mode = MODE_WRITE; + g_xmmtypes[mmreg] = XMMT_FPS; + } + } + else { + fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE); + + if( fsreg >= 0 ) { +#ifdef __x86_64__ + if( (mmreg = _checkX86reg(X86TYPE_GPR, _Rt_, MODE_READ)) >= 0) { + SSE2_MOVQ_R_to_XMM(fsreg, mmreg); + SSE_MOVHPS_M64_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); + } +#else + if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg); + SSE_MOVHPS_M64_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); + } +#endif + else { + if( GPR_IS_CONST1( _Rt_ ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 ); + _flushConstReg(_Rt_); + } + + SSE_MOVAPS_M128_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + } + } + else { + _deleteEEreg(_Rt_, 0); + _recMove128MtoM((uptr)&VU0.VF[_Fs_].UL[0], (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + } + + _clearNeededXMMregs(); +} + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls) +{ + _vuRegsCOP22(&VU0, &pinst->vuregs); + if( !dostalls ) return; + + _recvuTestLowerStalls(&VU0, &pinst->vuregs); + + switch(VU0.code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU0.code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + pinst->vuregs.VIwrite |= (1<> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + pinst->vuregs.VIwrite |= (1<vuregs.VIwrite |= (1<vuregs.VIwrite & (1 << REG_CLIP_FLAG)) { + _recAddWriteBack(vucycle+4, 1<vuregs.VIwrite & (1 << REG_Q)) { + _recAddWriteBack(vucycle+pinst->vuregs.cycles, 1<cycle = vucycle; + _recvuAddLowerStalls(&VU0, &pinst->vuregs); + _recvuTestPipes(&VU0); + + vucycle++; +} + +////////////////////////////////////////////////////////////////////////// +// BC2: Instructions +////////////////////////////////////////////////////////////////////////// +REC_COP2_FUNC(BC2F, 0); +REC_COP2_FUNC(BC2T, 0); +REC_COP2_FUNC(BC2FL, 0); +REC_COP2_FUNC(BC2TL, 0); + +////////////////////////////////////////////////////////////////////////// +// Special1 instructions +////////////////////////////////////////////////////////////////////////// +//TODO: redirect all the opcodes to the ivu0micro same functions +REC_COP2_VU0(IADD); +REC_COP2_VU0(IADDI); +REC_COP2_VU0(ISUB); +REC_COP2_VU0(IOR); +REC_COP2_VU0(IAND); +REC_COP2_VU0(OPMSUB); +REC_COP2_VU0(MADDq); +REC_COP2_VU0(MADDi); +REC_COP2_VU0(MSUBq); +REC_COP2_VU0(MSUBi); +REC_COP2_VU0(SUBi); +REC_COP2_VU0(SUBq); +REC_COP2_VU0(MULi); +REC_COP2_VU0(MULq); +REC_COP2_VU0(MAXi); +REC_COP2_VU0(MINIi); +REC_COP2_VU0(MUL); +REC_COP2_VU0(MAX); +REC_COP2_VU0(MADD); +REC_COP2_VU0(MSUB); + +REC_COP2_VU0(MINIx); +REC_COP2_VU0(MINIy); +REC_COP2_VU0(MINIz); +REC_COP2_VU0(MINIw); + +REC_COP2_VU0(MAXx); +REC_COP2_VU0(MAXy); +REC_COP2_VU0(MAXz); +REC_COP2_VU0(MAXw); + +REC_COP2_VU0(MULx); +REC_COP2_VU0(MULy); +REC_COP2_VU0(MULz); +REC_COP2_VU0(MULw); + +REC_COP2_VU0(ADD); +REC_COP2_VU0(ADDi); +REC_COP2_VU0(ADDq); +REC_COP2_VU0(ADDx); +REC_COP2_VU0(ADDy); +REC_COP2_VU0(ADDz); +REC_COP2_VU0(ADDw); + +REC_COP2_VU0(SUBx); +REC_COP2_VU0(SUBy); +REC_COP2_VU0(SUBz); +REC_COP2_VU0(SUBw); + +REC_COP2_VU0(MADDx); +REC_COP2_VU0(MADDy); +REC_COP2_VU0(MADDz); +REC_COP2_VU0(MADDw); + +REC_COP2_VU0(MSUBx); +REC_COP2_VU0(MSUBy); +REC_COP2_VU0(MSUBz); +REC_COP2_VU0(MSUBw); + +REC_COP2_VU0(SUB); +REC_COP2_VU0(MINI); + +////////////////////////////////////////////////////////////////////////// +// Special2 instructions +////////////////////////////////////////////////////////////////////////// + +REC_COP2_VU0(CLIP); +REC_COP2_VU0(LQI); +REC_COP2_VU0(SQI); +REC_COP2_VU0(LQD); +REC_COP2_VU0(SQD); +REC_COP2_VU0(MTIR); +REC_COP2_VU0(MFIR); +REC_COP2_VU0(ILWR); +REC_COP2_VU0(ISWR); +REC_COP2_VU0(RINIT); +REC_COP2_VU0(RXOR); +REC_COP2_VU0(RNEXT); +REC_COP2_VU0(RGET); + +REC_COP2_VU0(ITOF0); +REC_COP2_VU0(ITOF4); +REC_COP2_VU0(ITOF12); +REC_COP2_VU0(ITOF15); +REC_COP2_VU0(FTOI0); +REC_COP2_VU0(FTOI4); +REC_COP2_VU0(FTOI12); +REC_COP2_VU0(FTOI15); +REC_COP2_VU0(MADDA); +REC_COP2_VU0(MSUBA); +REC_COP2_VU0(MADDAi); +REC_COP2_VU0(MADDAq); +REC_COP2_VU0(MADDAx); +REC_COP2_VU0(MADDAy); +REC_COP2_VU0(MADDAz); +REC_COP2_VU0(MADDAw); +REC_COP2_VU0(MSUBAi); +REC_COP2_VU0(MSUBAq); +REC_COP2_VU0(MSUBAx); +REC_COP2_VU0(MSUBAy); +REC_COP2_VU0(MSUBAz); +REC_COP2_VU0(MSUBAw); +REC_COP2_VU0(ADDAi); +REC_COP2_VU0(ADDA); +REC_COP2_VU0(SUBA); +REC_COP2_VU0(MULA); +REC_COP2_VU0(ADDAq); +REC_COP2_VU0(ADDAx); +REC_COP2_VU0(ADDAy); +REC_COP2_VU0(ADDAz); +REC_COP2_VU0(ADDAw); +REC_COP2_VU0(SUBAi); +REC_COP2_VU0(SUBAq); +REC_COP2_VU0(SUBAx); +REC_COP2_VU0(SUBAy); +REC_COP2_VU0(SUBAz); +REC_COP2_VU0(SUBAw); +REC_COP2_VU0(MULAi); +REC_COP2_VU0(MULAq); +REC_COP2_VU0(MULAx); +REC_COP2_VU0(MULAy); +REC_COP2_VU0(MULAz); +REC_COP2_VU0(MULAw); +REC_COP2_VU0(OPMULA); +REC_COP2_VU0(MOVE); +REC_COP2_VU0_Q(DIV); +REC_COP2_VU0_Q(SQRT); +REC_COP2_VU0_Q(RSQRT); +REC_COP2_VU0(MR32); +REC_COP2_VU0(ABS); + +void recVNOP(){} +void recVWAITQ(){} +INTERPRETATE_COP2_FUNC(CALLMS); +INTERPRETATE_COP2_FUNC(CALLMSR); + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn); +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn); + +// information +void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= 0xf; +} + +void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIread = 1<<_Fs_; +} + +void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VFwrite = _Fs_; + VUregsn->VFwxyzw= 0xf; +} + +void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->VIwrite = 1<<_Fs_; +} + +void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, + _vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL, +}; + +void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw, + _vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw, + _vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw, + _vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi, + _vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi, + _vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI, + _vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK, + _vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2, +}; + +void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = { + _vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw, + _vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw, + _vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15, + _vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP, + _vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi, + _vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP, + _vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD, + _vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR, + _vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, + _vuRegs_C2UNK ,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK,_vuRegs_C2UNK, +}; + +void _vuRegsCOP22(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2t[_Rs_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL(VURegs * VU, _VURegsNum *VUregsn) +{ + _vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn); +} + +void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn) +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + _vuRegsCOP2SPECIAL2t[opc](VU, VUregsn); +} + +// recompilation +void (*recCOP2t[32])() = { + rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, + recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, + recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, +}; + +void (*recCOP2_BC2t[32])() = { + recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, +}; + +void (*recCOP2SPECIAL1t[64])() = { + recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, + recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, + recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, + recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, + recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, + recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, + recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, + recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2, +}; + +void (*recCOP2SPECIAL2t[128])() = { + recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw, + recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw, + recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15, + recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP, + recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi, + recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP, + recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD, + recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR, + recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, + rec_C2UNK ,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK,rec_C2UNK, +}; + +void recCOP22() +{ + cinfo = &g_cop2info; + g_VUregs = &g_pCurInstInfo->vuregs; + VU0.code = cpuRegs.code; + g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2 + recCOP2t[_Rs_](); +#ifndef __x86_64__ + _freeX86regs(); +#endif +} + +void recCOP2_SPECIAL() +{ + recCOP2SPECIAL1t[_Funct_](); +} + +void recCOP2_BC2() +{ + recCOP2_BC2t[_Rt_](); +} + +void recCOP2_SPECIAL2() +{ + int opc=(cpuRegs.code & 0x3) | ((cpuRegs.code >> 4) & 0x7c); + recCOP2SPECIAL2t[opc](); +} + +#endif diff --git a/pcsx2/x86/iCP0.c b/pcsx2/x86/iCP0.c new file mode 100644 index 0000000..bfbd5eb --- /dev/null +++ b/pcsx2/x86/iCP0.c @@ -0,0 +1,347 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iCP0.h" + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +#ifndef CP0_RECOMPILE + +REC_SYS(MFC0); +REC_SYS(MTC0); +REC_SYS(BC0F); +REC_SYS(BC0T); +REC_SYS(BC0FL); +REC_SYS(BC0TL); +REC_SYS(TLBR); +REC_SYS(TLBWI); +REC_SYS(TLBWR); +REC_SYS(TLBP); +REC_SYS(ERET); +REC_SYS(DI); +REC_SYS(EI); + +#else + +//////////////////////////////////////////////////// +//REC_SYS(MTC0); +//////////////////////////////////////////////////// +REC_SYS(BC0F); +//////////////////////////////////////////////////// +REC_SYS(BC0T); +//////////////////////////////////////////////////// +REC_SYS(BC0FL); +//////////////////////////////////////////////////// +REC_SYS(BC0TL); +//////////////////////////////////////////////////// +REC_SYS(TLBR); +//////////////////////////////////////////////////// +REC_SYS(TLBWI); +//////////////////////////////////////////////////// +REC_SYS(TLBWR); +//////////////////////////////////////////////////// +REC_SYS(TLBP); +//////////////////////////////////////////////////// +REC_SYS(ERET); +//////////////////////////////////////////////////// +REC_SYS(DI); +//////////////////////////////////////////////////// +REC_SYS(EI); + +//////////////////////////////////////////////////// +extern u32 s_iLastCOP0Cycle; +extern u32 s_iLastPERFCycle[2]; + +void recMFC0( void ) +{ + int mmreg; + + if ( ! _Rt_ ) return; + + if( _Rd_ == 9 ) { + MOV32MtoR( EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ] ); + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + ADD32RtoR(EAX, ECX); + SUB32MtoR(EAX, (uptr)&s_iLastCOP0Cycle); + MOV32RtoM((uptr)&s_iLastCOP0Cycle, ECX); + MOV32RtoM((uptr)&cpuRegs.CP0.r[ _Rd_ ], EAX); + + _deleteEEreg(_Rt_, 0); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else EEINST_RESETHASLIVE1(_Rt_); + return; + } + if( _Rd_ == 25 ) { + + _deleteEEreg(_Rt_, 0); + switch(_Imm_ & 0x3F){ + case 0: + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pccr); break; + case 1: + // check if needs to be incremented + MOV32MtoR(ECX, (uptr)&cpuRegs.PERF.n.pccr); + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr0); + AND32ItoR(ECX, 0x800003E0); + + CMP32ItoR(ECX, 0x80000020); + j8Ptr[0] = JNE8(0); + + MOV32MtoR(EDX, (uptr)&cpuRegs.cycle); + SUB32MtoR(EAX, (uptr)&s_iLastPERFCycle[0]); + ADD32RtoR(EAX, EDX); + MOV32RtoM((uptr)&s_iLastPERFCycle[0], EDX); + MOV32RtoM((uptr)&cpuRegs.PERF.n.pcr0, EAX); + + x86SetJ8(j8Ptr[0]); + break; + case 3: + // check if needs to be incremented + MOV32MtoR(ECX, (uptr)&cpuRegs.PERF.n.pccr); + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr1); + AND32ItoR(ECX, 0x800F8000); + + CMP32ItoR(ECX, 0x80008000); + j8Ptr[0] = JNE8(0); + + MOV32MtoR(EDX, (uptr)&cpuRegs.cycle); + SUB32MtoR(EAX, (uptr)&s_iLastPERFCycle[1]); + ADD32RtoR(EAX, EDX); + MOV32RtoM((uptr)&s_iLastPERFCycle[1], EDX); + MOV32RtoM((uptr)&cpuRegs.PERF.n.pcr1, EAX); + + x86SetJ8(j8Ptr[0]); + + break; + } + + MOV32RtoM( (uptr)&cpuRegs.CP0.r[ _Rt_ ], EAX ); + +#ifdef PCSX2_DEVBUILD + SysPrintf("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); +#endif + return; + } + + _eeOnWriteReg(_Rt_, 1); + + if( EEINST_ISLIVE1(_Rt_) ) { + _deleteEEreg(_Rt_, 0); + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]); + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], EAX); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + +#ifndef __x86_64__ + if( (mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (uptr)&cpuRegs.CP0.r[ _Rd_ ]); + SetMMXstate(); + } + else +#endif + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0) { + + if( EEINST_ISLIVE2(_Rt_) ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((uptr)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + } + else { + SSE_MOVLPS_M64_to_XMM(mmreg, (uptr)&cpuRegs.CP0.r[ _Rd_ ]); + } + } + else { + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.r[ _Rd_ ]); + if(_Rd_ == 12) AND32ItoR(EAX, 0xf0c79c1f); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX); + if(EEINST_ISLIVE1(_Rt_)) { + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + } + } + } +} + +void updatePCCR() +{ + // read the old pccr and update pcr0/1 + MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pccr); + MOV32RtoR(EDX, EAX); + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + + AND32ItoR(EAX, 0x800003E0); + CMP32ItoR(EAX, 0x80000020); + j8Ptr[0] = JNE8(0); + MOV32MtoR(EAX, (uptr)&s_iLastPERFCycle[0]); + ADD32RtoM((uptr)&cpuRegs.PERF.n.pcr0, ECX); + SUB32RtoM((uptr)&cpuRegs.PERF.n.pcr0, EAX); + x86SetJ8(j8Ptr[0]); + + AND32ItoR(EDX, 0x800F8000); + CMP32ItoR(EDX, 0x80008000); + j8Ptr[0] = JNE8(0); + MOV32MtoR(EAX, (uptr)&s_iLastPERFCycle[1]); + ADD32RtoM((uptr)&cpuRegs.PERF.n.pcr1, ECX); + SUB32RtoM((uptr)&cpuRegs.PERF.n.pcr1, EAX); + x86SetJ8(j8Ptr[0]); +} + +void recMTC0() +{ + if( GPR_IS_CONST1(_Rt_) ) { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + _callFunctionArg1((uptr)WriteCP0Status, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]); + break; + case 9: + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + MOV32RtoM((uptr)&s_iLastCOP0Cycle, ECX); + MOV32ItoM((uptr)&cpuRegs.CP0.r[9], g_cpuConstRegs[_Rt_].UL[0]); + break; + case 25: + SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); + switch(_Imm_ & 0x3F){ + case 0: + + updatePCCR(); + MOV32ItoM((uptr)&cpuRegs.PERF.n.pccr, g_cpuConstRegs[_Rt_].UL[0]); + + // update the cycles + MOV32RtoM((uptr)&s_iLastPERFCycle[0], ECX); + MOV32RtoM((uptr)&s_iLastPERFCycle[1], ECX); + break; + case 1: + MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); + MOV32ItoM((uptr)&cpuRegs.PERF.n.pcr0, g_cpuConstRegs[_Rt_].UL[0]); + MOV32RtoM((uptr)&s_iLastPERFCycle[0], EAX); + break; + case 3: + MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); + MOV32ItoM((uptr)&cpuRegs.PERF.n.pcr1, g_cpuConstRegs[_Rt_].UL[0]); + MOV32RtoM((uptr)&s_iLastPERFCycle[1], EAX); + break; + } + break; + default: + MOV32ItoM((uptr)&cpuRegs.CP0.r[_Rd_], g_cpuConstRegs[_Rt_].UL[0]); + break; + } + } + else { + switch (_Rd_) { + case 12: + iFlushCall(FLUSH_NODESTROY); + //_flushCachedRegs(); //NOTE: necessary? + _callFunctionArg1((uptr)WriteCP0Status, MEM_GPRTAG|_Rt_, 0); + break; + case 9: + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + _eeMoveGPRtoM((uptr)&cpuRegs.CP0.r[9], _Rt_); + MOV32RtoM((uptr)&s_iLastCOP0Cycle, ECX); + break; + case 25: + SysPrintf("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x\n", + cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F); + switch(_Imm_ & 0x3F){ + case 0: + updatePCCR(); + _eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pccr, _Rt_); + + // update the cycles + MOV32RtoM((uptr)&s_iLastPERFCycle[0], ECX); + MOV32RtoM((uptr)&s_iLastPERFCycle[1], ECX); + break; + case 1: + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + _eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr0, _Rt_); + MOV32RtoM((uptr)&s_iLastPERFCycle[0], ECX); + break; + case 3: + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + _eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr1, _Rt_); + MOV32RtoM((uptr)&s_iLastPERFCycle[1], ECX); + break; + } + break; + default: + _eeMoveGPRtoM((uptr)&cpuRegs.CP0.r[_Rd_], _Rt_); + break; + } + } +} + +/*void rec(COP0) { +} + +void rec(BC0F) { +} + +void rec(BC0T) { +} + +void rec(BC0FL) { +} + +void rec(BC0TL) { +} + +void rec(TLBR) { +} + +void rec(TLBWI) { +} + +void rec(TLBWR) { +} + +void rec(TLBP) { +} + +void rec(ERET) { +} +*/ + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iCP0.h b/pcsx2/x86/iCP0.h new file mode 100644 index 0000000..5ee0203 --- /dev/null +++ b/pcsx2/x86/iCP0.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ICP0_H__ +#define __ICP0_H__ + +/********************************************************* +* COP0 opcodes * +* * +*********************************************************/ + +void recMFC0( void ); +void recMTC0( void ); +void recBC0F( void ); +void recBC0T( void ); +void recBC0FL( void ); +void recBC0TL( void ); +void recTLBR( void ); +void recTLBWI( void ); +void recTLBWR( void ); +void recTLBP( void ); +void recERET( void ); +void recDI( void ); +void recEI( void ); + +#endif diff --git a/pcsx2/x86/iCore.cpp b/pcsx2/x86/iCore.cpp new file mode 100644 index 0000000..82a7e41 --- /dev/null +++ b/pcsx2/x86/iCore.cpp @@ -0,0 +1,1436 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +extern "C" { + +#if defined(_WIN32) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 g_x86AllocCounter = 0; +u16 g_xmmAllocCounter = 0; + +EEINST* g_pCurInstInfo = NULL; + +u32 g_cpuRegHasLive1 = 0, g_cpuPrevRegHasLive1 = 0; // set if upper 32 bits are live +u32 g_cpuRegHasSignExt = 0, g_cpuPrevRegHasSignExt = 0; // set if upper 32 bits are the sign extension of the lower integer + +// used to make sure regs don't get changed while in recompiler +// use FreezeMMXRegs, FreezeXMMRegs +u8 g_globalXMMSaved = 0; +u32 g_recWriteback = 0; + +#ifdef _DEBUG +char g_globalXMMLocked = 0; +#endif + +_xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; +PCSX2_ALIGNED16(u64 g_globalXMMData[2*XMMREGS];) + +// X86 caching +_x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; + +} // end extern "C" + +#include +using namespace std; + +//void _eeSetLoadStoreReg(int gprreg, u32 offset, int x86reg) +//{ +// int regs[2] = {ESI, EDI}; +// +// int i = _checkX86reg(X86TYPE_MEMOFFSET, gprreg, MODE_WRITE); +// if( i < 0 ) { +// for(i = 0; i < 2; ++i) { +// if( !x86regs[regs[i]].inuse ) break; +// } +// +// assert( i < 2 ); +// i = regs[i]; +// } +// +// if( i != x86reg ) MOV32RtoR(x86reg, i); +// x86regs[i].extra = offset; +//} + +//int _eeGeLoadStoreReg(int gprreg, int* poffset) +//{ +// int i = _checkX86reg(X86TYPE_MEMOFFSET, gprreg, MODE_READ); +// if( i >= 0 ) return -1; +// +// if( poffset ) *poffset = x86regs[i].extra; +// return i; +//} + +// XMM Caching +#define VU_VFx_ADDR(x) (uptr)&VU->VF[x].UL[0] +#define VU_ACCx_ADDR (uptr)&VU->ACC.UL[0] + +static int s_xmmchecknext = 0; + +void _initXMMregs() { + memset(xmmregs, 0, sizeof(xmmregs)); + g_xmmAllocCounter = 0; + s_xmmchecknext = 0; +} + +__forceinline void* _XMMGetAddr(int type, int reg, VURegs *VU) +{ + if (type == XMMTYPE_VFREG ) return (void*)VU_VFx_ADDR(reg); + else if (type == XMMTYPE_ACC ) return (void*)VU_ACCx_ADDR; + else if (type == XMMTYPE_GPRREG) { + if( reg < 32 ) + assert( !(g_cpuHasConstReg & (1<regs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { + _freeXMMreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; iregs[xmmregs[i].reg] & EEINST_XMM) ) { + _freeXMMreg(i); + return i; + } + } + } + + tempi = -1; + bestcount = 0xffff; + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + xmmregs[i].needed = 1; + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ) ) { + SSE_MOVAPS_M128_to_XMM(i, VU_VFx_ADDR(vfreg)); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_VFREG; + xmmregs[xmmreg].reg = vfreg; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_VFx_ADDR(xmmregs[xmmreg].reg)); + } + + return xmmreg; +} + +int _checkXMMreg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 ) { + // requested specific reg, so return that instead + if( i != xmmreg ) { + if( xmmregs[i].mode & MODE_READ ) readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= xmmregs[i].mode&MODE_WRITE; + xmmregs[i].inuse = 0; + break; + } + } + + if( !(xmmregs[i].mode & MODE_READ) && (mode&MODE_READ)) { + SSE_MOVAPS_M128_to_XMM(i, VU_ACCx_ADDR); + xmmregs[i].mode |= MODE_READ; + } + + g_xmmtypes[i] = XMMT_FPS; + xmmregs[i].counter = g_xmmAllocCounter++; // update counter + xmmregs[i].needed = 1; + xmmregs[i].mode|= mode; + return i; + } + + if (xmmreg == -1) { + xmmreg = _getFreeXMMreg(); + } + else { + _freeXMMreg(xmmreg); + } + + g_xmmtypes[xmmreg] = XMMT_FPS; + xmmregs[xmmreg].inuse = 1; + xmmregs[xmmreg].type = XMMTYPE_ACC; + xmmregs[xmmreg].mode = mode; + xmmregs[xmmreg].needed = 1; + xmmregs[xmmreg].VU = XMM_CONV_VU(VU); + xmmregs[xmmreg].counter = g_xmmAllocCounter++; + xmmregs[xmmreg].reg = 0; + + if (mode & MODE_READ) { + if( readfromreg >= 0 ) SSE_MOVAPS_XMM_to_XMM(xmmreg, readfromreg); + else SSE_MOVAPS_M128_to_XMM(xmmreg, VU_ACCx_ADDR); + } + + return xmmreg; +} + +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode) { + int i; + + for (i=0; i= 0 ) { + // transfer + if (cpucaps.hasStreamingSIMD2Extensions ) { + + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(xmmreg, mmxreg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(xmmreg, xmmreg); + SSE2_PUNPCKHQDQ_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + + if( mmxregs[mmxreg].mode & MODE_WRITE ) { + + // instead of setting to write, just flush to mem + if( !(mode & MODE_WRITE) ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], mmxreg); + } + //xmmregs[xmmreg].mode |= MODE_WRITE; + } + + // don't flush + mmxregs[mmxreg].inuse = 0; + } + else { + _freeMMXreg(mmxreg); + SSEX_MOVDQA_M128_to_XMM(xmmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } +#else + if( (mmxreg = _checkX86reg(X86TYPE_GPR, gprreg, 0)) >= 0 ) { + SSE2_MOVQ_R_to_XMM(xmmreg, mmxreg); + SSE_MOVHPS_M64_to_XMM(xmmreg, (uptr)&cpuRegs.GPR.r[gprreg].UL[0]); + + // read only, instead of setting to write, just flush to mem + if( !(mode&MODE_WRITE) && (x86regs[mmxreg].mode & MODE_WRITE) ) { + MOV64RtoM((uptr)&cpuRegs.GPR.r[gprreg].UL[0], mmxreg); + } + + x86regs[mmxreg].inuse = 0; + } +#endif + else + { + SSEX_MOVDQA_M128_to_XMM(xmmreg, (uptr)&cpuRegs.GPR.r[gprreg].UL[0]); + } + } + } + else { +#ifndef __x86_64__ + _deleteMMXreg(MMX_GPR+gprreg, 0); +#else + _deleteX86reg(X86TYPE_GPR, gprreg, 0); +#endif + } + + return xmmreg; +} + +int _allocFPACCtoXMMreg(int xmmreg, int mode) +{ + int i; + if( !cpucaps.hasStreamingSIMDExtensions ) return -1; + + for (i=0; iregs[xmmregs[i].reg]&EEINST_USED) ) { + return 1; + } + } + } + return 0; +} + +void _moveXMMreg(int xmmreg) +{ + int i; + if( !xmmregs[xmmreg].inuse ) return; + + for (i=0; iregs[gprreg] & EEINST_XMM ) return _allocGPRtoXMMreg(-1, gprreg, mode); + + return _checkXMMreg(XMMTYPE_GPRREG, gprreg, mode); +} + +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode) +{ + if( pinst->fpuregs[fpureg] & EEINST_XMM ) return _allocFPtoXMMreg(-1, fpureg, mode); + + return _checkXMMreg(XMMTYPE_FPREG, fpureg, mode); +} + +int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode) +{ + if( pinst->regs[gprreg] & EEINST_USED ) + return _allocX86reg(-1, X86TYPE_GPR, gprreg, mode); + + return _checkX86reg(X86TYPE_GPR, gprreg, mode); +} + +void _recClearInst(EEINST* pinst) +{ + memset(&pinst->regs[0], EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2, sizeof(pinst->regs)); + memset(&pinst->fpuregs[0], EEINST_LIVE0, sizeof(pinst->fpuregs)); + memset(&pinst->info, 0, sizeof(EEINST)-sizeof(pinst->regs)-sizeof(pinst->fpuregs)); +} + +// returns nonzero value if reg has been written between [startpc, endpc-4] +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg) +{ + int i, inst = 1; + while(size-- > 0) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == xmmtype && pinst->writeReg[i] == reg ) + return inst; + } + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == xmmtype && pinst->readReg[i] == reg ) + return inst; + } + ++inst; + pinst++; + } + + return 0; +} + +void _recFillRegister(EEINST* pinst, int type, int reg, int write) +{ + int i = 0; + if( write ) { + for(i = 0; i < ARRAYSIZE(pinst->writeType); ++i) { + if( pinst->writeType[i] == XMMTYPE_TEMP ) { + pinst->writeType[i] = type; + pinst->writeReg[i] = reg; + return; + } + } + assert(0); + } + else { + for(i = 0; i < ARRAYSIZE(pinst->readType); ++i) { + if( pinst->readType[i] == XMMTYPE_TEMP ) { + pinst->readType[i] = type; + pinst->readReg[i] = reg; + return; + } + } + assert(0); + } +} + +void SetMMXstate() { +#ifdef __x86_64__ + assert(0); +#else + x86FpuState = MMX_STATE; +#endif +} + +// Writebacks // +void _recClearWritebacks() +{ +} + +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent) +{ +} + +EEINSTWRITEBACK* _recCheckWriteBack(int cycle) +{ + return NULL; +} + +#ifdef _MSC_VER +extern "C" BOOL install_my_handler(); +typedef void (*TESTFNPTR)(); +#endif + +extern "C" void cpudetectSSE3(void* pfnCallSSE3) +{ + cpucaps.hasStreamingSIMD3Extensions = 1; + +#ifdef _MSC_VER + __try { + //__asm call pfnCallSSE3; + ((TESTFNPTR)pfnCallSSE3)(); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + cpucaps.hasStreamingSIMD3Extensions = 0; +#ifdef PCSX2_VIRTUAL_MEM + // necessary since can potentially kill the custom handler + install_my_handler(); +#endif + } +#else // linux + // exception handling doesn't work, so disable for x86 builds of linux + +#ifndef __x86_64__ + cpucaps.hasStreamingSIMD3Extensions = 0; +#endif +// try { +// __asm__("call *%0" : : "m"(pfnCallSSE3) ); +// } +// catch(...) { +// SysPrintf("no SSE3 found\n"); +// cpucaps.hasStreamingSIMD3Extensions = 0; +// } +#endif +} + +struct BASEBLOCKS +{ + // 0 - ee, 1 - iop + inline void Add(BASEBLOCKEX*); + inline void Remove(BASEBLOCKEX*); + inline int Get(u32 startpc); + inline void Reset(); + + inline BASEBLOCKEX** GetAll(int* pnum); + + vector blocks; +}; + +void BASEBLOCKS::Add(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + + switch(blocks.size()) { + case 0: + blocks.push_back(pex); + return; + case 1: + assert( blocks.front()->startpc != pex->startpc ); + + if( blocks.front()->startpc < pex->startpc ) { + blocks.push_back(pex); + } + else blocks.insert(blocks.begin(), pex); + + return; + + default: + { + int imin = 0, imax = blocks.size(), imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > pex->startpc ) imax = imid; + else imin = imid+1; + } + + assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc ); + if( imin > 0 ) assert( blocks[imin-1]->startpc < pex->startpc ); + blocks.insert(blocks.begin()+imin, pex); + + return; + } + } +} + +int BASEBLOCKS::Get(u32 startpc) +{ + switch(blocks.size()) { + case 1: + return 0; + case 2: + return blocks.front()->startpc < startpc; + + default: + { + int imin = 0, imax = blocks.size()-1, imid; + + while(imin < imax) { + imid = (imin+imax)>>1; + + if( blocks[imid]->startpc > startpc ) imax = imid; + else if( blocks[imid]->startpc == startpc ) return imid; + else imin = imid+1; + } + + assert( blocks[imin]->startpc == startpc ); + return imin; + } + } +} + +void BASEBLOCKS::Remove(BASEBLOCKEX* pex) +{ + assert( pex != NULL ); + int i = Get(pex->startpc); + assert( blocks[i] == pex ); + blocks.erase(blocks.begin()+i); +} + +void BASEBLOCKS::Reset() +{ + blocks.resize(0); + blocks.reserve(512); +} + +BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum) +{ + assert( pnum != NULL ); + *pnum = blocks.size(); + return &blocks[0]; +} + +static BASEBLOCKS s_vecBaseBlocksEx[2]; + +void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Add(pex); +} + +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu) +{ + return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)]; +} + +void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu) +{ + s_vecBaseBlocksEx[cpu].Remove(pex); +} + +void ResetBaseBlockEx(int cpu) +{ + s_vecBaseBlocksEx[cpu].Reset(); +} + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu) +{ + return s_vecBaseBlocksEx[cpu].GetAll(pnum); +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iCore.h b/pcsx2/x86/iCore.h new file mode 100644 index 0000000..4e12397 --- /dev/null +++ b/pcsx2/x86/iCore.h @@ -0,0 +1,486 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// NOTE: x86-64 recompiler doesn't support mmx +#ifndef _PCSX2_CORE_RECOMPILER_ +#define _PCSX2_CORE_RECOMPILER_ + +#include "ix86/ix86.h" +#include "iVUmicro.h" + +#if defined(__x86_64__) && defined(_MSC_VER) +// xp64 has stack shadow memory +#define REC_INC_STACK 48 +#else +#define REC_INC_STACK 0 +#endif + +// used to keep block information +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +typedef struct _BASEBLOCK +{ + u32 pFnptr : 28; + u32 uType : 4; + u32 startpc; +} BASEBLOCK; + +C_ASSERT( sizeof(BASEBLOCK) == 8 ); + +// extra block info (only valid for start of fn) +typedef struct _BASEBLOCKEX +{ + u16 size; // size in dwords + u16 dummy; + u32 startpc; // for debugging? + +#ifdef PCSX2_DEVBUILD + u32 visited; // number of times called + LARGE_INTEGER ltime; // regs it assumes to have set already +#endif + +} BASEBLOCKEX; + +#define GET_BLOCKTYPE(b) ((b)->Type) +#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + +#define X86TYPE_TEMP 0 +#define X86TYPE_GPR 1 +#define X86TYPE_VI 2 +#define X86TYPE_MEMOFFSET 3 +#define X86TYPE_VIMEMOFFSET 4 +#define X86TYPE_VUQREAD 5 +#define X86TYPE_VUPREAD 6 +#define X86TYPE_VUQWRITE 7 +#define X86TYPE_VUPWRITE 8 +#define X86TYPE_PSX 9 +#define X86TYPE_PCWRITEBACK 10 +#define X86TYPE_VUJUMP 12 // jump from random mem (g_recWriteback) +#define X86TYPE_VITEMP 13 +#define X86TYPE_FNARG 14 // function parameter, max is 4 + +#define X86TYPE_VU1 0x80 + +#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u8 type; // X86TYPE_ + u16 counter; + u32 extra; // extra info assoc with the reg +} _x86regs; + +extern _x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; + +uptr _x86GetAddr(int type, int reg); +void _initX86regs(); +int _getFreeX86reg(int mode); +int _allocX86reg(int x86reg, int type, int reg, int mode); +void _deleteX86reg(int type, int reg, int flush); +int _checkX86reg(int type, int reg, int mode); +void _addNeededX86reg(int type, int reg); +void _clearNeededX86regs(); +void _freeX86reg(int x86reg); +void _flushX86regs(); +void _freeX86regs(); +void _freeX86tempregs(); +u8 _hasFreeX86reg(); + +// see MEM_X defines for argX format +void _callPushArg(u32 arg, uptr argmem, x86IntRegType X86ARG); /// X86ARG is ignored for 32bit recs +void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem); +void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem); +void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem); + +// when using mmx/xmm regs, use; 0 is load +// freezes no matter the state +void FreezeXMMRegs_(int save); + +void _flushCachedRegs(); +void _flushConstRegs(); +void _flushConstReg(int reg); + +// return type: 0 - const, 1 - mmx, 2 - xmm +#define PROCESS_EE_MMX 0x01 +#define PROCESS_EE_XMM 0x02 + +// currently only used in FPU +#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem +#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem + +// not used in VU recs +#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs +#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs +#define PROCESS_EE_LO 0x40 // lo reg is valid +#define PROCESS_EE_HI 0x80 // hi reg is valid +#define PROCESS_EE_ACC 0x40 // acc reg is valid + +// used in VU recs +#define PROCESS_VU_UPDATEFLAGS 0x10 +#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation +#define PROCESS_VU_COP2 0x80 // simple cop2 + +#define EEREC_S (((info)>>8)&0xf) +#define EEREC_T (((info)>>12)&0xf) +#define EEREC_D (((info)>>16)&0xf) +#define EEREC_LO (((info)>>20)&0xf) +#define EEREC_HI (((info)>>24)&0xf) +#define EEREC_ACC (((info)>>20)&0xf) +#define EEREC_TEMP (((info)>>24)&0xf) + +#define PROCESS_EE_SET_S(reg) ((reg)<<8) +#define PROCESS_EE_SET_T(reg) ((reg)<<12) +#define PROCESS_EE_SET_D(reg) ((reg)<<16) +#define PROCESS_EE_SET_LO(reg) ((reg)<<20) +#define PROCESS_EE_SET_HI(reg) ((reg)<<24) +#define PROCESS_EE_SET_ACC(reg) ((reg)<<20) + +#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg) +#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24) + +// special info not related to above flags +#define PROCESS_CONSTS 1 +#define PROCESS_CONSTT 2 + +#define XMM_CONV_VU(VU) (VU==&VU1) + +#define XMMTYPE_TEMP 0 // has to be 0 +#define XMMTYPE_VFREG 1 +#define XMMTYPE_ACC 2 +#define XMMTYPE_FPREG 3 +#define XMMTYPE_FPACC 4 +#define XMMTYPE_GPRREG 5 + +// lo and hi regs +#define XMMGPR_LO 33 +#define XMMGPR_HI 32 +#define XMMFPU_ACC 32 + +typedef struct { + u8 inuse; + u8 reg; + u8 type; + u8 mode; + u8 needed; + u8 VU; // 0 = VU0, 1 = VU1 + u16 counter; +} _xmmregs; + +void _initXMMregs(); +int _getFreeXMMreg(); +int _allocTempXMMreg(XMMSSEType type, int xmmreg); +int _allocVFtoXMMreg(VURegs *VU, int xmmreg, int vfreg, int mode); +int _allocFPtoXMMreg(int xmmreg, int fpreg, int mode); +int _allocGPRtoXMMreg(int xmmreg, int gprreg, int mode); +int _allocACCtoXMMreg(VURegs *VU, int xmmreg, int mode); +int _allocFPACCtoXMMreg(int xmmreg, int mode); +int _checkXMMreg(int type, int reg, int mode); +void _addNeededVFtoXMMreg(int vfreg); +void _addNeededACCtoXMMreg(); +void _addNeededFPtoXMMreg(int fpreg); +void _addNeededFPACCtoXMMreg(); +void _addNeededGPRtoXMMreg(int gprreg); +void _clearNeededXMMregs(); +void _deleteVFtoXMMreg(int reg, int vu, int flush); +void _deleteACCtoXMMreg(int vu, int flush); +void _deleteGPRtoXMMreg(int reg, int flush); +void _deleteFPtoXMMreg(int reg, int flush); +void _freeXMMreg(int xmmreg); +void _moveXMMreg(int xmmreg); // instead of freeing, moves it to a diff location +void _flushXMMregs(); +u8 _hasFreeXMMreg(); +void _freeXMMregs(); +int _getNumXMMwrite(); + +// Constants used for controlling iFlushCall, _psxFlushCall +#define FLUSH_CACHED_REGS 1 +#define FLUSH_FLUSH_XMM 2 +#define FLUSH_FREE_XMM 4 // both flushes and frees +#define FLUSH_FLUSH_MMX 8 +#define FLUSH_FREE_MMX 16 // both flushes and frees +#define FLUSH_FLUSH_ALLX86 32 // flush x86 +#define FLUSH_FREE_TEMPX86 64 // flush and free temporary x86 regs +#define FLUSH_FREE_ALLX86 128 // free all x86 regs +#define FLUSH_FREE_VU0 0x100 // free all vu0 related regs + +#define FLUSH_EVERYTHING 0xfff +// no freeing, used when callee won't destroy mmx/xmm regs +#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX|FLUSH_FLUSH_ALLX86) +// used when regs aren't going to be changed be callee +#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX|FLUSH_FREE_TEMPX86) + +#ifdef __x86_64__ +#define IS_X8664 1 +#else +#define IS_X8664 0 +#endif + +// Note: All functions with _ee prefix are for EE only + +// finds where the GPR is stored and moves lower 32 bits to EAX +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr); +void _eeMoveGPRtoM(u32 to, int fromgpr); +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr); + +void _psxMoveGPRtoR(x86IntRegType to, int fromgpr); +void _psxMoveGPRtoM(u32 to, int fromgpr); +void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr); + +// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs +void _recPushReg(int mmreg); + +void _signExtendSFtoM(u32 mem); + +// returns new index of reg, lower 32 bits already in mmx +// shift is used when the data is in the top bits of the mmx reg to begin with +// a negative shift is for sign extension +int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns true if reg destroyed + +// Defines for passing register info + +// only valid during writes. If write128, then upper 64bits are in an mmxreg +// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f) +#define MEM_EECONSTTAG 0x0100 // argument is a GPR and comes from g_cpuConstRegs +#define MEM_PSXCONSTTAG 0x0200 +#define MEM_MEMORYTAG 0x0400 +// mmreg is mmxreg +#define MEM_MMXTAG 0x0800 +// mmreg is xmmreg +#define MEM_XMMTAG 0x8000 +#define MEM_X86TAG 0x4000 // ignored most of the time +#define MEM_GPRTAG 0x2000 // argument is a GPR reg +#define MEM_CONSTTAG 0x1000 // argument is a const + +#define IS_EECONSTREG(reg) (reg>=0&&((reg)&MEM_EECONSTTAG)) +#define IS_PSXCONSTREG(reg) (reg>=0&&((reg)&MEM_PSXCONSTTAG)) +#define IS_MMXREG(reg) (reg>=0&&((reg)&MEM_MMXTAG)) +#define IS_XMMREG(reg) (reg>=0&&((reg)&MEM_XMMTAG)) +#define IS_X86REG(reg) (reg>=0&&((reg)&MEM_X86TAG)) +#define IS_GPRREG(reg) (reg>=0&&((reg)&MEM_GPRTAG)) +#define IS_CONSTREG(reg) (reg>=0&&((reg)&MEM_CONSTTAG)) +#define IS_MEMORYREG(reg) (reg>=0&&((reg)&MEM_MEMORYTAG)) + +////////////////////// +// Instruction Info // +////////////////////// +#define EEINST_LIVE0 1 // if var is ever used (read or write) +#define EEINST_LIVE1 2 // if cur var's next 32 bits are needed +#define EEINST_LIVE2 4 // if cur var's next 64 bits are needed +#define EEINST_LASTUSE 8 // if var isn't written/read anymore +#define EEINST_MMX 0x10 // var will be used in mmx ops +#define EEINST_XMM 0x20 // var will be used in xmm ops (takes precedence +#define EEINST_USED 0x40 + +#define EEINSTINFO_COP1 1 +#define EEINSTINFO_COP2 2 +#define EEINSTINFO_NOREC 4 // if set, inst is recompiled alone +#define EEINSTINFO_COREC 8 // if set, inst is recompiled with another similar inst +#define EEINSTINFO_MMX EEINST_MMX +#define EEINSTINFO_XMM EEINST_XMM + +typedef struct _EEINST +{ + u8 regs[34]; // includes HI/LO (HI=32, LO=33) + u8 fpuregs[33]; // ACC=32 + u8 info; // extra info, if 1 inst is COP1, 2 inst is COP2. Also uses EEINST_MMX|EEINST_XMM + + // uses XMMTYPE_ flags; if type == XMMTYPE_TEMP, not used + u8 writeType[3], writeReg[3]; // reg written in this inst, 0 if no reg + u8 readType[4], readReg[4]; + + // valid if info & EEINSTINFO_COP2 + int cycle; // cycle of inst (at offset from block) + _VURegsNum vuregs; + + u8 numpeeps; // number of peephole optimizations +} EEINST; + +extern EEINST* g_pCurInstInfo; // info for the cur instruction +void _recClearInst(EEINST* pinst); + +// returns the number of insts + 1 until written (0 if not written) +int _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg); +// returns the number of insts + 1 until used (0 if not used) +int _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg); +void _recFillRegister(EEINST* pinst, int type, int reg, int write); + +#define EEINST_ISLIVE64(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)) +#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) +#define EEINST_ISLIVE1(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE1) +#define EEINST_ISLIVE2(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE2) + +#define FPUINST_ISLIVE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0) +#define FPUINST_LASTUSE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE) + +// if set, then the variable at this inst really has its upper 32 bits valid +// The difference between EEINST_LIVE1 is that the latter is used in back propagation +// The former is set at recompile time. +#define EEINST_RESETHASLIVE1(reg) { if( (reg) < 32 ) g_cpuRegHasLive1 &= ~(1<<(reg)); } +#define EEINST_HASLIVE1(reg) (g_cpuPrevRegHasLive1&(1<<(reg))) + +#define EEINST_SETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt |= (1<<(reg)); } +#define EEINST_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); } +#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg))) + +// writeback inst (used for cop2) +typedef struct _EEINSTWRITEBACK +{ + int cycle; + u32 viwrite; // mask of written viregs (REG_STATUS_FLAG and REG_MAC_FLAG are treated the same) + EEINST* parent; +} EEINSTWRITEBACK; + +void _recClearWritebacks(); +void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent); + +// if cycle == -1, returns the next writeback (used for flushing) +EEINSTWRITEBACK* _recCheckWriteBack(int cycle); + +extern u32 g_recWriteback; // used for jumps +extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1; +extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt; + +extern u8 g_globalXMMSaved; +extern _xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; + +#ifdef _DEBUG +extern char g_globalXMMLocked; +#endif + +// allocates only if later insts use XMM, otherwise checks +int _allocCheckGPRtoXMM(EEINST* pinst, int gprreg, int mode); +int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode); + +// allocates only if later insts use this register +int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode); + +// 0 - ee, 1 - iop +void AddBaseBlockEx(BASEBLOCKEX*, int cpu); +void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu); +BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu); +void ResetBaseBlockEx(int cpu); + +BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu); + +#define MODE_READ 1 +#define MODE_WRITE 2 +#define MODE_READHALF 4 // read only low 64 bits +#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF +#define MODE_VUZ 0x10 // z only doesn't work for now +#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory) +#define MODE_NOFLUSH 0x20 // can't flush reg to mem +#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg +#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx + +void SetMMXstate(); +void cpudetectSSE3(void* pfnCallSSE3); + +void _recMove128MtoM(u32 to, u32 from); + +#ifndef __x86_64__ +///////////////////// +// MMX x86-32 only // +///////////////////// + +#define FPU_STATE 0 +#define MMX_STATE 1 + +void FreezeMMXRegs_(int save); +void SetFPUstate(); + +// max is 0x7f, when 0x80 is set, need to flush reg +#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index] +#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0; +#define MMX_GPR 0 +#define MMX_HI XMMGPR_HI +#define MMX_LO XMMGPR_LO +#define MMX_FPUACC 34 +#define MMX_FPU 64 +#define MMX_COP0 96 +#define MMX_TEMP 0x7f + +#define MMX_IS32BITS(x) (((x)>=MMX_FPU&&(x)= MMX_GPR && (x) < MMX_GPR+34) + +typedef struct { + u8 inuse; + u8 reg; // value of 0 - not used + u8 mode; + u8 needed; + u16 counter; +} _mmxregs; + +void _initMMXregs(); +int _getFreeMMXreg(); +int _allocMMXreg(int MMXreg, int reg, int mode); +void _addNeededMMXreg(int reg); +int _checkMMXreg(int reg, int mode); +void _clearNeededMMXregs(); +void _deleteMMXreg(int reg, int flush); +void _freeMMXreg(int mmxreg); +void _moveMMXreg(int mmxreg); // instead of freeing, moves it to a diff location +void _flushMMXregs(); +u8 _hasFreeMMXreg(); +void _freeMMXregs(); +int _getNumMMXwrite(); + +int _signExtendMtoMMX(x86MMXRegType to, u32 mem); +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg); +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode); + +void _recMove128RmOffsettoM(u32 to, u32 offset); +void _recMove128MtoRmOffset(u32 offset, u32 from); + +// op = 0, and +// op = 1, or +// op = 2, xor +// op = 3, nor (the 32bit versoins only do OR) +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); + +// returns new index of reg, lower 32 bits already in mmx +// shift is used when the data is in the top bits of the mmx reg to begin with +// a negative shift is for sign extension +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift); + +extern u8 g_globalMMXSaved; +extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS]; +extern u16 x86FpuState, iCWstate; + +#ifdef _DEBUG +extern char g_globalMMXLocked; +#endif + +#else + +void LogicalOp64RtoR(x86IntRegType to, x86IntRegType from, int op); +void LogicalOp64RtoM(uptr to, x86IntRegType from, int op); +void LogicalOp64MtoR(x86IntRegType to, uptr from, int op); + +#endif // __x86_64__ + +void LogicalOp32RtoM(uptr to, x86IntRegType from, int op); +void LogicalOp32MtoR(x86IntRegType to, uptr from, int op); +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +void LogicalOp32ItoM(uptr to, u32 from, int op); + +#endif diff --git a/pcsx2/x86/iFPU.c b/pcsx2/x86/iFPU.c new file mode 100644 index 0000000..e46556b --- /dev/null +++ b/pcsx2/x86/iFPU.c @@ -0,0 +1,1427 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iFPU.h" + +#define REC_FPUBRANCH(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((uptr)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((uptr)f); \ + branch = 2; \ +} + +#define REC_FPUFUNC(f) \ + void f(); \ + void rec##f() { \ + MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \ + MOV32ItoM((uptr)&cpuRegs.pc, pc); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc((uptr)f); \ +} + +/********************************************************* +* COP1 opcodes * +* * +*********************************************************/ + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +extern u32 g_minvals[4], g_maxvals[4]; + +//////////////////////////////////////////////////// +void recMFC1(void) { + int regt, regs; + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + if( regs >= 0 ) { + _deleteGPRtoXMMreg(_Rt_, 2); + +#ifdef __x86_64__ + regt = _allocCheckGPRtoX86(g_pCurInstInfo, _Rt_, MODE_WRITE); + + if( regt >= 0 ) { + + if(EEINST_ISLIVE1(_Rt_)) { + SSE2_MOVD_XMM_to_R(RAX, regs); + // sign extend + CDQE(); + MOV64RtoR(regt, RAX); + } + else { + SSE2_MOVD_XMM_to_R(regt, regs); + EEINST_RESETHASLIVE1(_Rt_); + } + } +#else + regt = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + + if( regt >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regt, regs); + + if(EEINST_ISLIVE1(_Rt_)) _signExtendGPRtoMMX(regt, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } +#endif + else { + if(EEINST_ISLIVE1(_Rt_)) { + _signExtendXMMtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs, 0); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + SSE_MOVSS_XMM_to_M32((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], regs); + } + } + } +#ifndef __x86_64__ + else if( (regs = _checkMMXreg(MMX_FPU+_Fs_, MODE_READ)) >= 0 ) { + // convert to mmx reg + mmxregs[regs].reg = MMX_GPR+_Rt_; + mmxregs[regs].mode |= MODE_READ|MODE_WRITE; + _signExtendGPRtoMMX(regs, _Rt_, 0); + } +#endif + else { + regt = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((uptr)&cpuRegs.GPR.r[_Rt_].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } +#ifdef __x86_64__ + else if( (regt = _allocCheckGPRtoX86(g_pCurInstInfo, _Rt_, MODE_WRITE)) >= 0 ) { + + if(EEINST_ISLIVE1(_Rt_)) { + MOV32MtoR( RAX, (uptr)&fpuRegs.fpr[ _Fs_ ].UL ); + CDQE(); + MOV64RtoR(regt, RAX); + } + else { + MOV32MtoR( regt, (uptr)&fpuRegs.fpr[ _Fs_ ].UL ); + EEINST_RESETHASLIVE1(_Rt_); + } + } + else +#endif + { + + _deleteEEreg(_Rt_, 0); + MOV32MtoR( EAX, (uptr)&fpuRegs.fpr[ _Fs_ ].UL ); + + if(EEINST_ISLIVE1(_Rt_)) { +#ifdef __x86_64__ + CDQE(); + MOV64RtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX); +#else + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + } +} + +//////////////////////////////////////////////////// +void recCFC1(void) +{ + if ( ! _Rt_ ) return; + + _eeOnWriteReg(_Rt_, 1); + + MOV32MtoR( EAX, (uptr)&fpuRegs.fprc[ _Fs_ ] ); + _deleteEEreg(_Rt_, 0); + + if(EEINST_ISLIVE1(_Rt_)) { +#ifdef __x86_64__ + CDQE(); + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +#else + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } +} + +//////////////////////////////////////////////////// +void recMTC1(void) +{ + if( GPR_IS_CONST1(_Rt_) ) { + _deleteFPtoXMMreg(_Fs_, 0); + MOV32ItoM((uptr)&fpuRegs.fpr[ _Fs_ ].UL, g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + if( g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE ) { + // transfer the reg directly + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteFPtoXMMreg(_Fs_, 2); + _allocFPtoXMMreg(mmreg, _Fs_, MODE_WRITE); + } + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) SSE_MOVSS_XMM_to_XMM(mmreg2, mmreg); + else SSE_MOVSS_XMM_to_M32((uptr)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } +#ifndef __x86_64__ + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + + if( cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + if( mmreg2 >= 0 ) { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(mmreg2, mmreg); + } + else { + SetMMXstate(); + MOVDMMXtoM((uptr)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } + else { + _deleteFPtoXMMreg(_Fs_, 0); + SetMMXstate(); + MOVDMMXtoM((uptr)&fpuRegs.fpr[ _Fs_ ].UL, mmreg); + } + } +#endif + else { + int mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Fs_, MODE_WRITE); + + if( mmreg2 >= 0 ) SSE_MOVSS_M32_to_XMM(mmreg2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else { + MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + MOV32RtoM((uptr)&fpuRegs.fpr[ _Fs_ ].UL, EAX); + } + } + } +} + +//////////////////////////////////////////////////// +void recCTC1( void ) +{ + if( GPR_IS_CONST1(_Rt_)) { + MOV32ItoM((uptr)&fpuRegs.fprc[ _Fs_ ], g_cpuConstRegs[_Rt_].UL[0]); + } + else { + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) { + SSEX_MOVD_XMM_to_M32((uptr)&fpuRegs.fprc[ _Fs_ ], mmreg); + } +#ifdef __x86_64__ + else if( (mmreg = _checkX86reg(X86TYPE_GPR, _Rt_, MODE_READ)) >= 0 ) { + MOV32RtoM((uptr)&fpuRegs.fprc[ _Fs_ ], mmreg); + } +#else + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((uptr)&fpuRegs.fprc[ _Fs_ ], mmreg); + SetMMXstate(); + } +#endif + else { + _deleteGPRtoXMMreg(_Rt_, 1); + +#ifdef __x86_64__ + _deleteX86reg(X86TYPE_GPR, _Rt_, 1); +#else + _deleteMMXreg(MMX_GPR+_Rt_, 1); +#endif + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (uptr)&fpuRegs.fprc[ _Fs_ ], EAX ); + } + } +} + +//////////////////////////////////////////////////// +void recCOP1_BC1() +{ + recCP1BC1[_Rt_](); +} + +static u32 _mxcsr = 0x7F80; +static u32 _mxcsrs; +static u32 fpucw = 0x007f; +static u32 fpucws = 0; + +//////////////////////////////////////////////////// +void SaveCW(int type) { + if (iCWstate & type) return; + + if (type == 2) { +// SSE_STMXCSR((uptr)&_mxcsrs); +// SSE_LDMXCSR((uptr)&_mxcsr); + } else { + FNSTCW( (uptr)&fpucws ); + FLDCW( (uptr)&fpucw ); + } + iCWstate|= type; +} + +//////////////////////////////////////////////////// +void LoadCW( void ) { + if (iCWstate == 0) return; + + if (iCWstate & 2) { + //SSE_LDMXCSR((uptr)&_mxcsrs); + } + if (iCWstate & 1) { + FLDCW( (uptr)&fpucws ); + } + iCWstate = 0; +} + +//////////////////////////////////////////////////// +void recCOP1_S( void ) +{ +#ifndef __x86_64__ + if( !EE_FPU_REGCACHING || !cpucaps.hasStreamingSIMD2Extensions) { + _freeMMXreg(6); + _freeMMXreg(7); + } +#endif + recCP1S[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +void recCOP1_W( void ) +{ +#ifndef __x86_64__ + if( !EE_FPU_REGCACHING ) { + _freeMMXreg(6); + _freeMMXreg(7); + } +#endif + recCP1W[ _Funct_ ]( ); +} + +#ifndef FPU_RECOMPILE + + +REC_FPUFUNC(ADD_S); +REC_FPUFUNC(SUB_S); +REC_FPUFUNC(MUL_S); +REC_FPUFUNC(DIV_S); +REC_FPUFUNC(SQRT_S); +REC_FPUFUNC(RSQRT_S); +REC_FPUFUNC(ABS_S); +REC_FPUFUNC(MOV_S); +REC_FPUFUNC(NEG_S); +REC_FPUFUNC(ADDA_S); +REC_FPUFUNC(SUBA_S); +REC_FPUFUNC(MULA_S); +REC_FPUFUNC(MADD_S); +REC_FPUFUNC(MSUB_S); +REC_FPUFUNC(MADDA_S); +REC_FPUFUNC(MSUBA_S); +REC_FPUFUNC(CVT_S); +REC_FPUFUNC(CVT_W); +REC_FPUFUNC(MIN_S); +REC_FPUFUNC(MAX_S); +REC_FPUBRANCH(BC1F); +REC_FPUBRANCH(BC1T); +REC_FPUBRANCH(BC1FL); +REC_FPUBRANCH(BC1TL); +REC_FPUFUNC(C_F); +REC_FPUFUNC(C_EQ); +REC_FPUFUNC(C_LE); +REC_FPUFUNC(C_LT); + +#else + +// define the FPU ops using the x86 FPU. x86-64 doesn't use FPU +#ifndef __x86_64__ + +void SetQFromStack(u32 mem) +{ + write16(0xe5d9); + FNSTSWtoAX(); + write8(0x9e); + j8Ptr[0] = JAE8(0); // jnc + + // sign bit is in bit 9 of EAX + FSTP(0); // pop + AND32ItoR(EAX, 0x200); + SHL32ItoR(EAX, 22); + OR32MtoR(EAX, (uptr)&g_maxvals[0]); + MOV32RtoM(mem, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + // just pop + FSTP32(mem); + x86SetJ8(j8Ptr[1]); +} + +void recC_EQ_(int info) +{ + SetFPUstate(); + + FLD32( (uptr)&fpuRegs.fpr[_Fs_].f); + FCOMP32( (uptr)&fpuRegs.fpr[_Ft_].f); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004000 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (uptr)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (uptr)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +void recC_LT_(int info) +{ + SetFPUstate(); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00000100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (uptr)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (uptr)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[1] ); +} + +void recC_LE_(int info) +{ + SetFPUstate(); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FCOMP32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FNSTSWtoAX( ); + TEST32ItoR( EAX, 0x00004100 ); + j8Ptr[ 0 ] = JE8( 0 ); + OR32ItoM( (uptr)&fpuRegs.fprc[ 31 ], 0x00800000 ); + j8Ptr[ 1 ] = JMP8( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + AND32ItoM( (uptr)&fpuRegs.fprc[ 31 ], ~0x00800000 ); + + x86SetJ8( j8Ptr[ 1 ] ); +} + +void recADD_S_(int info) { + SetFPUstate(); + + SaveCW(1); + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recMUL_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recDIV_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + SetQFromStack( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recSQRT_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recABS_S_(int info) +{ + MOV32MtoR( EAX, (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + AND32ItoR( EAX, 0x7fffffff ); + MOV32RtoM( (uptr)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +void recMOV_S_(int info) +{ + MOV32MtoR( EAX, (uptr)&fpuRegs.fpr[ _Fs_ ].UL ); + MOV32RtoM( (uptr)&fpuRegs.fpr[ _Fd_ ].UL, EAX ); +} + +void recNEG_S_(int info) +{ + MOV32MtoR( EAX,(uptr)&fpuRegs.fpr[ _Fs_ ].f ); + XOR32ItoR( EAX, 0x80000000 ); + MOV32RtoM( (uptr)&fpuRegs.fpr[ _Fd_ ].f, EAX ); +} + +void recRSQRT_S_(int info) +{ + static u32 tmp; + + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSQRT( ); + FSTP32( (uptr)&tmp ); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FDIV32( (uptr)&tmp ); + SetQFromStack( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); + +// FLD32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); +// FSQRT( ); +// FSTP32( (uptr)&tmp ); +// +// MOV32MtoR( EAX, (uptr)&tmp ); +// OR32RtoR( EAX, EAX ); +// j8Ptr[ 0 ] = JE8( 0 ); +// FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); +// FDIV32( (uptr)&tmp ); +// FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +// x86SetJ8( j8Ptr[ 0 ] ); +} + +void recADDA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FADD32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.ACC.f ); +} + +void recSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FSUB32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.ACC.f ); +} + +void recMULA_S_(int info) { + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSTP32( (uptr)&fpuRegs.ACC.f ); +} + +void recMADD_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (uptr)&fpuRegs.ACC.f ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recMADDA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FADD32( (uptr)&fpuRegs.ACC.f ); + FSTP32( (uptr)&fpuRegs.ACC.f ); +} + +void recMSUB_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.ACC.f ); + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recMSUBA_S_(int info) +{ + SetFPUstate(); + SaveCW(1); + + FLD32( (uptr)&fpuRegs.ACC.f ); + FLD32( (uptr)&fpuRegs.fpr[ _Fs_ ].f ); + FMUL32( (uptr)&fpuRegs.fpr[ _Ft_ ].f ); + FSUBP( ); + FSTP32( (uptr)&fpuRegs.ACC.f ); +} + +void recCVT_S_(int info) +{ + SetFPUstate(); + FILD32( (uptr)&fpuRegs.fpr[ _Fs_ ].UL ); + FSTP32( (uptr)&fpuRegs.fpr[ _Fd_ ].f ); +} + +void recMAX_S_(int info) +{ + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MAX_S ); +} + +void recMIN_S_(int info) { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)MIN_S ); +} + +#endif + +//////////////////////////////////////////////////// +void recC_EQ_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (uptr)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (uptr)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + j8Ptr[0] = JZ8(0); + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((uptr)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); +} + +FPURECOMPILE_CONSTCODE(C_EQ, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_F() +{ + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); +} + +//////////////////////////////////////////////////// +void recC_LT_xmm(int info) +{ + // assumes that inputs are valid + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (uptr)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (uptr)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JB8(0); + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((uptr)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JBE8(0); + OR32ItoM((uptr)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +FPURECOMPILE_CONSTCODE(C_LT, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recC_LE_xmm(int info ) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: SSE_UCOMISS_M32_to_XMM(EEREC_S, (uptr)&fpuRegs.fpr[_Ft_]); break; + case PROCESS_EE_T: SSE_UCOMISS_M32_to_XMM(EEREC_T, (uptr)&fpuRegs.fpr[_Fs_]); break; + default: SSE_UCOMISS_XMM_to_XMM(EEREC_S, EEREC_T); break; + } + + //write8(0x9f); // lahf + //TEST16ItoR(EAX, 0x4400); + if( info & PROCESS_EE_S ) { + j8Ptr[0] = JBE8(0); + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + OR32ItoM((uptr)&fpuRegs.fprc[31], 0x00800000); + x86SetJ8(j8Ptr[1]); + } + else { + j8Ptr[0] = JB8(0); + OR32ItoM((uptr)&fpuRegs.fprc[31], 0x00800000); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + AND32ItoM( (uptr)&fpuRegs.fprc[31], ~0x00800000 ); + x86SetJ8(j8Ptr[1]); + } +} + +FPURECOMPILE_CONSTCODE(C_LE, XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +static void (*recComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_ADDSS_XMM_to_XMM, SSE_MULSS_XMM_to_XMM, SSE_MAXSS_XMM_to_XMM, SSE_MINSS_XMM_to_XMM }; + +static void (*recComOpM32_to_XMM[] )(x86SSERegType, uptr) = { + SSE_ADDSS_M32_to_XMM, SSE_MULSS_M32_to_XMM, SSE_MAXSS_M32_to_XMM, SSE_MINSS_M32_to_XMM }; + +void recCommutativeOp(int info, int regd, int op) { + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd == EEREC_S) recComOpM32_to_XMM[op](regd, (uptr)&fpuRegs.fpr[_Ft_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpM32_to_XMM[op](regd, (uptr)&fpuRegs.fpr[_Ft_]); + } + break; + case PROCESS_EE_T: + if (regd == EEREC_T) recComOpM32_to_XMM[op](regd, (uptr)&fpuRegs.fpr[_Fs_]); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_T); + recComOpM32_to_XMM[op](regd, (uptr)&fpuRegs.fpr[_Fs_]); + } + break; + default: + if (regd == EEREC_S) { + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + else if (regd == EEREC_T) { + recComOpXMM_to_XMM[op](regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } +} + +static void (*recNonComOpXMM_to_XMM[] )(x86SSERegType, x86SSERegType) = { + SSE_SUBSS_XMM_to_XMM, SSE_DIVSS_XMM_to_XMM }; + +static void (*recNonComOpM32_to_XMM[] )(x86SSERegType, uptr) = { + SSE_SUBSS_M32_to_XMM, SSE_DIVSS_M32_to_XMM }; + +int recNonCommutativeOp(int info, int regd, int op) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if (regd != EEREC_S) SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpM32_to_XMM[op](regd, (uptr)&fpuRegs.fpr[_Ft_]); + break; + case PROCESS_EE_T: + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_M32_to_XMM(t0reg, (uptr)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](t0reg, EEREC_T); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_M32_to_XMM(regd, (uptr)&fpuRegs.fpr[_Fs_]); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + default: + if (regd == EEREC_S) { + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } else + if (regd == EEREC_T) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + recNonComOpXMM_to_XMM[op](t0reg, regd); + + // swap regs + xmmregs[t0reg] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + return t0reg; + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + recNonComOpXMM_to_XMM[op](regd, EEREC_T); + } + break; + } + + return regd; +} + +void recADD_S_xmm(int info) { + recCommutativeOp(info, EEREC_D, 0); +} + +FPURECOMPILE_CONSTCODE(ADD_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recSUB_S_xmm(int info) +{ + recNonCommutativeOp(info, EEREC_D, 0); +} + +FPURECOMPILE_CONSTCODE(SUB_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recMUL_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 1); +} + +FPURECOMPILE_CONSTCODE(MUL_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recDIV_S_xmm(int info) +{ + int regd = recNonCommutativeOp(info, EEREC_D, 1); + SSE_MAXSS_M32_to_XMM(regd, (uptr)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(regd, (uptr)&g_maxvals[0]); + +// _freeXMMreg(EEREC_D); +// MOV32MtoR(EAX, (uptr)&fpuRegs.fpr[_Fd_]); +// AND32ItoR(EAX, 0x7f800000); +// CMP32ItoR(EAX, 0x7f800000); +// j8Ptr[0] = JNE8(0); +// MOV32ItoM((uptr)&fpuRegs.fpr[_Fd_], 0); +// x86SetJ8(j8Ptr[0]); +} + +FPURECOMPILE_CONSTCODE(DIV_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +static u32 PCSX2_ALIGNED16(s_neg[4]) = { 0x80000000, 0, 0, 0 }; +static u32 PCSX2_ALIGNED16(s_pos[4]) = { 0x7fffffff, 0, 0, 0 }; + +void recSQRT_S_xmm(int info) +{ + if( info & PROCESS_EE_T ) { + if( CHECK_FORCEABS ) { + if( EEREC_D == EEREC_T ) SSE_ANDPS_M128_to_XMM(EEREC_D, (uptr)&s_pos[0]); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&s_pos[0]); + SSE_ANDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( CHECK_FORCEABS ) { + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Ft_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (uptr)&s_pos[0]); + + SSE_SQRTSS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Ft_]); + } + } +} + +FPURECOMPILE_CONSTCODE(SQRT_S, XMMINFO_WRITED|XMMINFO_READT); + +void recABS_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_D, (uptr)&s_pos[0]); + } + else { + if( _Fs_ == _Fd_ ) { + AND32ItoM((uptr)&fpuRegs.fpr[_Fs_], 0x7fffffff); + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode &= ~MODE_WRITE; + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + SSE_ANDPS_M128_to_XMM(EEREC_D, (uptr)&s_pos[0]); + } + } +} + +FPURECOMPILE_CONSTCODE(ABS_S, XMMINFO_WRITED|XMMINFO_READS); + +void recMOV_S_xmm(int info) +{ + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + } +} + +FPURECOMPILE_CONSTCODE(MOV_S, XMMINFO_WRITED|XMMINFO_READS); + +void recNEG_S_xmm(int info) { + if( info & PROCESS_EE_S ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + } + + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&s_neg[0]); +} + +FPURECOMPILE_CONSTCODE(NEG_S, XMMINFO_WRITED|XMMINFO_READS); + +void recRSQRT_S_xmm(int info) +{ + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_RSQRTSS_M32_to_XMM(t0reg, (uptr)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_RSQRTSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Ft_]); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + + break; + case PROCESS_EE_T: + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + break; + default: + if( EEREC_D == EEREC_S ) { + int t0reg; + if( g_pCurInstInfo->regs[_Ft_]&EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + } + + SSE_RSQRTSS_XMM_to_XMM(t0reg, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + break; + } + + SSE_MAXSS_M32_to_XMM(EEREC_D, (uptr)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_D, (uptr)&g_maxvals[0]); +} + +FPURECOMPILE_CONSTCODE(RSQRT_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recADDA_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_ACC, 0); +} + +FPURECOMPILE_CONSTCODE(ADDA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recSUBA_S_xmm(int info) { + recNonCommutativeOp(info, EEREC_ACC, 0); +} + +FPURECOMPILE_CONSTCODE(SUBA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMULA_S_xmm(int info) { + recCommutativeOp(info, EEREC_ACC, 1); +} + +FPURECOMPILE_CONSTCODE(MULA_S, XMMINFO_WRITEACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(uptr)&fpuRegs.fpr[_Ft_]:(uptr)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + SSE_MULSS_M32_to_XMM(regd, mreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (uptr)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (uptr)&fpuRegs.ACC); + } + break; + default: + if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (uptr)&fpuRegs.ACC); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + if( info & PROCESS_EE_ACC ) { + assert( regd != EEREC_ACC ); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else SSE_ADDSS_M32_to_XMM(regd, (uptr)&fpuRegs.ACC); + } + else if( (info&PROCESS_EE_ACC) && regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_ADDSS_XMM_to_XMM(regd, t0reg); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + if( info & PROCESS_EE_ACC ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else SSE_ADDSS_M32_to_XMM(regd, (uptr)&fpuRegs.ACC); + } + break; + } +} + +void recMADD_S_xmm(int info) +{ + recMADDtemp(info, EEREC_D); +} + +FPURECOMPILE_CONSTCODE(MADD_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMADDA_S_xmm(int info) +{ + recMADDtemp(info, EEREC_ACC); +} + +FPURECOMPILE_CONSTCODE(MADDA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBtemp(int info, int regd) +{ + int vreg; + u32 mreg; + + if( !(info&PROCESS_EE_ACC)) { + int regacc = _allocFPACCtoXMMreg(-1, MODE_WRITE|MODE_READ); + info |= PROCESS_EE_SET_ACC(regacc)|PROCESS_EE_ACC; + } + + switch(info & (PROCESS_EE_S|PROCESS_EE_T) ) { + case PROCESS_EE_S: + case PROCESS_EE_T: + vreg = (info&PROCESS_EE_S)?EEREC_S:EEREC_T; + mreg = (info&PROCESS_EE_S)?(uptr)&fpuRegs.fpr[_Ft_]:(uptr)&fpuRegs.fpr[_Fs_]; + + if (regd == vreg) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_M32_to_XMM(regd, mreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg; + if( g_pCurInstInfo->regs[(info&PROCESS_EE_S)?_Fs_:_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(vreg); + t0reg = vreg; + SSE_MULSS_M32_to_XMM(t0reg, mreg); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, vreg); + SSE_MULSS_M32_to_XMM(vreg, mreg); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[vreg]; + xmmregs[vreg].inuse = 0; + + t0reg = vreg; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_M32_to_XMM(regd, mreg); + SSE_MULSS_XMM_to_XMM(regd, vreg); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + + break; + default: + if (regd == EEREC_S) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if (regd == EEREC_T) { + assert( regd != EEREC_ACC ); + _freeXMMreg(EEREC_ACC); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + else if( regd == EEREC_ACC ) { + int t0reg ; + if( g_pCurInstInfo->regs[_Fs_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_S); + t0reg = EEREC_S; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_T); + } + else if( g_pCurInstInfo->regs[_Ft_] & EEINST_LASTUSE ) { + _freeXMMreg(EEREC_T); + t0reg = EEREC_T; + SSE_MULSS_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + SSE_MOVSS_XMM_to_XMM(t0reg, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_S, EEREC_T); + + // swap regs for better timing + xmmregs[t0reg] = xmmregs[EEREC_S]; + xmmregs[EEREC_S].inuse = 0; + + t0reg = EEREC_S; + } + + SSE_SUBSS_XMM_to_XMM(regd, t0reg); + } + else { + if( regd != EEREC_ACC ) { + _freeXMMreg(EEREC_ACC); + xmmregs[EEREC_ACC] = xmmregs[regd]; + xmmregs[regd].inuse = 0; + } + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, regd); + } + break; + } +} + +void recMSUB_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_D); +} + +FPURECOMPILE_CONSTCODE(MSUB_S, XMMINFO_WRITED|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recMSUBA_S_xmm(int info) +{ + recMSUBtemp(info, EEREC_ACC); +} + +FPURECOMPILE_CONSTCODE(MSUBA_S, XMMINFO_WRITEACC|XMMINFO_READACC|XMMINFO_READS|XMMINFO_READT); + +void recCVT_S_xmm(int info) +{ + if( !(info&PROCESS_EE_S) || (EEREC_D != EEREC_S && !(info&PROCESS_EE_MODEWRITES)) ) { + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( info&PROCESS_EE_MODEWRITES ) { + if( xmmregs[EEREC_S].reg == _Fs_ ) + _deleteFPtoXMMreg(_Fs_, 1); + else { + // force sync + SSE_MOVSS_XMM_to_M32((uptr)&fpuRegs.fpr[_Fs_], EEREC_S); + } + } + SSE_CVTSI2SS_M32_to_XMM(EEREC_D, (uptr)&fpuRegs.fpr[_Fs_]); + xmmregs[EEREC_D].mode |= MODE_WRITE; // in the case that _Fs_ == _Fd_ + } + } +} + +FPURECOMPILE_CONSTCODE(CVT_S, XMMINFO_WRITED|XMMINFO_READS); + +//////////////////////////////////////////////////// +void recCVT_W() +{ + if( cpucaps.hasStreamingSIMDExtensions ) { + int t0reg; + int regs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + + if( regs >= 0 ) { + t0reg = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t0reg); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CVTTSS2SI_XMM_to_R32(EAX, regs); + } + else SSE_CVTTSS2SI_M32_to_R32(EAX, (uptr)&fpuRegs.fpr[ _Fs_ ]); + + _deleteFPtoXMMreg(_Fd_, 2); + + CMP32ItoR(EAX, 0x80000000); + j8Ptr[0] = JNE8(0); + + // need to detect if reg is positive + if( regs >= 0 ) { + SSE_UCOMISS_XMM_to_XMM(regs, t0reg); + j8Ptr[2] = JB8(0); + } + else { + TEST32ItoM((uptr)&fpuRegs.fpr[_Fs_], 0x80000000); + j8Ptr[2] = JNZ8(0); + } + + MOV32ItoM((uptr)&fpuRegs.fpr[_Fd_], 0x7fffffff); + j8Ptr[1] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[2] ); + MOV32RtoM((uptr)&fpuRegs.fpr[_Fd_], EAX); + + x86SetJ8( j8Ptr[1] ); + } +#ifndef __x86_64__ + else { + MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); + iFlushCall(FLUSH_EVERYTHING); + _flushConstRegs(); + CALLFunc((uptr)CVT_W); + } +#endif +} + +void recMAX_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 2); +} + +FPURECOMPILE_CONSTCODE(MAX_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +void recMIN_S_xmm(int info) +{ + recCommutativeOp(info, EEREC_D, 3); +} + +FPURECOMPILE_CONSTCODE(MIN_S, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//////////////////////////////////////////////////// +void recBC1F( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBC1T( void ) { + u32 branchTo = (s32)_Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + //j32Ptr[1] = JMP32(0); + + x86SetJ32(j32Ptr[0]); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + //x86SetJ32(j32Ptr[1]); +} + +//////////////////////////////////////////////////// +void recBC1FL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JNZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBC1TL( void ) { + u32 branchTo = _Imm_ * 4 + pc; + + _eeFlushAllUnused(); + MOV32MtoR(EAX, (uptr)&fpuRegs.fprc[31]); + TEST32ItoR(EAX, 0x00800000); + j32Ptr[0] = JZ32(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + x86SetJ32(j32Ptr[0]); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iFPU.h b/pcsx2/x86/iFPU.h new file mode 100644 index 0000000..0d94bff --- /dev/null +++ b/pcsx2/x86/iFPU.h @@ -0,0 +1,60 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IFPU_H__ +#define __IFPU_H__ + +void recMFC1( void ); +void recCFC1( void ); +void recMTC1( void ); +void recCTC1( void ); +void recCOP1_BC1( void ); +void recCOP1_S( void ); +void recCOP1_W( void ); +void recC_EQ( void ); +void recC_F( void ); +void recC_LT( void ); +void recC_LE( void ); +void recADD_S( void ); +void recSUB_S( void ); +void recMUL_S( void ); +void recDIV_S( void ); +void recSQRT_S( void ); +void recABS_S( void ); +void recMOV_S( void ); +void recNEG_S( void ); +void recRSQRT_S( void ); +void recADDA_S( void ); +void recSUBA_S( void ); +void recMULA_S( void ); +void recMADD_S( void ); +void recMSUB_S( void ); +void recMADDA_S( void ); +void recMSUBA_S( void ); +void recCVT_S( void ); +void recCVT_W( void ); +void recMAX_S( void ); +void recMIN_S( void ); +void recBC1F( void ); +void recBC1T( void ); +void recBC1FL( void ); +void recBC1TL( void ); + +#endif + + diff --git a/pcsx2/x86/iGS.cpp b/pcsx2/x86/iGS.cpp new file mode 100644 index 0000000..88954f1 --- /dev/null +++ b/pcsx2/x86/iGS.cpp @@ -0,0 +1,515 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2007 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#if defined(_WIN32) +#include +#endif + +#include + +#include +#include + +using namespace std; + +extern "C" { +#include "PS2Etypes.h" +#include "zlib.h" +#include "Elfheader.h" +#include "Misc.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "VifDma.h" +#include "Memory.h" +#include "Hw.h" + +#include "ix86/ix86.h" +#include "iR5900.h" + +#include "Counters.h" +#include "GS.h" + +extern u32 CSRw; + +} + +void CSRwrite(u32 value); + +#ifdef PCSX2_VIRTUAL_MEM +#define PS2GS_BASE(mem) ((PS2MEM_BASE+0x12000000)+(mem&0x13ff)) +#else +extern u8 g_RealGSMem[0x2000]; +#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) +#endif + +void gsConstWrite8(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12001000: // GS_CSR + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32MtoR(ECX, (uptr)&CSRw); + AND32ItoR(EAX, 0xff<<(mem&3)*8); + AND32ItoR(ECX, ~(0xff<<(mem&3)*8)); + OR32ItoR(EAX, ECX); + _callFunctionArg1((uptr)CSRwrite, EAX|MEM_X86TAG, 0); + break; + default: + _eeWriteConstMem8( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callFunctionArg3((uptr)GSRingBufSimplePacket, MEM_CONSTTAG, MEM_CONSTTAG, mmreg, + GS_RINGTYPE_MEMWRITE8, mem&0x13ff, 0); + } + break; + } +} + +void recSetSMODE1() +{ + iFlushCall(0); + AND32ItoR(EAX, 0x6000); + CMP32ItoR(EAX, 0x6000); + j8Ptr[5] = JNE8(0); + + // PAL + OR32ItoM( (uptr)&Config.PsxType, 1); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // NTSC + AND32ItoM( (uptr)&Config.PsxType, ~1 ); + + x86SetJ8( j8Ptr[6] ); + CALLFunc((uptr)UpdateVSyncRate); +} + +void recSetSMODE2() +{ + TEST32ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // Interlaced + OR32ItoM( (uptr)&Config.PsxType, 2); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + + // Non-Interlaced + AND32ItoM( (uptr)&Config.PsxType, ~2 ); + + x86SetJ8( j8Ptr[6] ); +} + +void gsConstWrite16(u32 mem, int mmreg) +{ + switch (mem&~3) { + case 0x12000010: // GS_SMODE1 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE16, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + + } + + break; + + case 0x12000020: // GS_SMODE2 + assert( !(mem&3)); + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem16( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE16, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12001000: // GS_CSR + + assert( !(mem&2) ); + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + + MOV32MtoR(ECX, (uptr)&CSRw); + AND32ItoR(EAX, 0xffff<<(mem&2)*8); + AND32ItoR(ECX, ~(0xffff<<(mem&2)*8)); + OR32ItoR(EAX, ECX); + _callFunctionArg1((uptr)CSRwrite, EAX|MEM_X86TAG, 0); + break; + + default: + _eeWriteConstMem16( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + _callFunctionArg3((uptr)GSRingBufSimplePacket, MEM_CONSTTAG, MEM_CONSTTAG, mmreg, + GS_RINGTYPE_MEMWRITE16, mem&0x13ff, 0); + } + + break; + } +} + +// (value&0x1f00)|0x6000 +void gsConstWriteIMR(int mmreg) +{ + const u32 mem = 0x12001010; + if( mmreg & MEM_XMMTAG ) { + SSE2_MOVD_XMM_to_M32((uptr)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((uptr)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((uptr)PS2GS_BASE(mem), 0x6000); + } +#ifndef __x86_64__ + else if( mmreg & MEM_MMXTAG ) { + SetMMXstate(); + MOVDMMXtoM((uptr)PS2GS_BASE(mem), mmreg&0xf); + AND32ItoM((uptr)PS2GS_BASE(mem), 0x1f00); + OR32ItoM((uptr)PS2GS_BASE(mem), 0x6000); + } +#endif + else if( mmreg & MEM_EECONSTTAG ) { + MOV32ItoM( (uptr)PS2GS_BASE(mem), (g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]&0x1f00)|0x6000); + } + else { + AND32ItoR(mmreg, 0x1f00); + OR32ItoR(mmreg, 0x6000); + MOV32RtoM( (uptr)PS2GS_BASE(mem), mmreg ); + } + + // IMR doesn't need to be updated in MTGS mode +} + +void gsConstWrite32(u32 mem, int mmreg) { + + switch (mem) { + + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12001000: // GS_CSR + iFlushCall(0); + _callFunctionArg1((uptr)CSRwrite, mmreg, 0); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + default: + _eeWriteConstMem32( (uptr)PS2GS_BASE(mem), mmreg ); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callFunctionArg3((uptr)GSRingBufSimplePacket, MEM_CONSTTAG, MEM_CONSTTAG, mmreg, + GS_RINGTYPE_MEMWRITE32, mem&0x13ff, 0); + } + + break; + } +} + +void gsConstWrite64(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem64((uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12001000: // GS_CSR + iFlushCall(0); + _callFunctionArg1((uptr)CSRwrite, mmreg, 0); + break; + + case 0x12001010: // GS_IMR + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem64((uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem)+4, X86ARG4); + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem), X86ARG3); + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE64, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 16); +#endif + } + + break; + } +} + +void gsConstWrite128(u32 mem, int mmreg) +{ + switch (mem) { + case 0x12000010: // GS_SMODE1 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE1(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12000020: // GS_SMODE2 + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem128( (uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) + _callPushArg(MEM_X86TAG|EAX, 0, X86ARG3); + + recSetSMODE2(); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE32, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 12); +#endif + } + + break; + + case 0x12001000: // GS_CSR + iFlushCall(0); + _callFunctionArg1((uptr)CSRwrite, mmreg, 0); + break; + + case 0x12001010: // GS_IMR + // (value&0x1f00)|0x6000 + gsConstWriteIMR(mmreg); + break; + + default: + _eeWriteConstMem128( (uptr)PS2GS_BASE(mem), mmreg); + + if( CHECK_MULTIGS ) { + iFlushCall(0); + + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem)+4, X86ARG4); + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem), X86ARG3); + _callPushArg(MEM_CONSTTAG, mem&0x13ff, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE64, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 16); +#endif + + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem)+12, X86ARG4); + _callPushArg(MEM_MEMORYTAG, (uptr)PS2GS_BASE(mem)+8, X86ARG3); + _callPushArg(MEM_CONSTTAG, (mem&0x13ff)+8, X86ARG2); + _callPushArg(MEM_CONSTTAG, GS_RINGTYPE_MEMWRITE64, X86ARG1); + CALLFunc((uptr)GSRingBufSimplePacket); +#ifndef __x86_64__ + ADD32ItoR(ESP, 16); +#endif + } + + break; + } +} + +int gsConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 8 %8.8lx (%8.8x), at %8.8lx\n", (uptr)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem8(x86reg, (uptr)PS2GS_BASE(mem), sign); + return 0; +} + +int gsConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 16 %8.8lx (%8.8x), at %8.8lx\n", (uptr)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem16(x86reg, (uptr)PS2GS_BASE(mem), sign); + return 0; +} + +int gsConstRead32(u32 x86reg, u32 mem) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 32 %8.8lx (%8.8x), at %8.8lx\n", (uptr)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem32(x86reg, (uptr)PS2GS_BASE(mem)); + return 0; +} + +void gsConstRead64(u32 mem, int mmreg) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 64 %8.8lx (%8.8x), at %8.8lx\n", (uptr)PS2GS_BASE(mem), mem); +#endif + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (uptr)PS2GS_BASE(mem)); + else { +#ifndef __x86_64__ + MOVQMtoR(mmreg, (uptr)PS2GS_BASE(mem)); + SetMMXstate(); +#else + assert(0); +#endif + } +} + +void gsConstRead128(u32 mem, int xmmreg) +{ +#ifdef GIF_LOG + GIF_LOG("GS read 128 %8.8lx (%8.8x), at %8.8lx\n", (uptr)PS2GS_BASE(mem), mem); +#endif + _eeReadConstMem128( xmmreg, (uptr)PS2GS_BASE(mem)); +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iHw.c b/pcsx2/x86/iHw.c new file mode 100644 index 0000000..74ec4c8 --- /dev/null +++ b/pcsx2/x86/iHw.c @@ -0,0 +1,1235 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2007 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "iR5900.h" +#include "VUmicro.h" +#include "PsxMem.h" +#include "IPU/IPU.h" +#include "GS.h" + +#ifndef PCSX2_VIRTUAL_MEM +extern u8 *psH; // hw mem +extern u16 *psHW; +extern u32 *psHL; +extern u64 *psHD; +#endif + +extern int b440; +extern int b440table[]; +extern char sio_buffer[1024]; +extern int sio_count; + +int hwConstRead8(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10008000 ) + SysPrintf("hwRead8 to %x\n", mem); +#endif + + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else) + XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + _eeReadConstMem8(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign); + //psHu32(mem) &= ~0x4000; + return 0; + } + } + + if (mem < 0x10010000) + { + _eeReadConstMem8(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else ) + XOR32RtoR(x86reg, x86reg); + } + + return 0; +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((uptr)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +static u32 s_regreads[3] = {0x010200000, 0xbfff0000, 0xF0000102}; +int hwConstRead16(u32 x86reg, u32 mem, u32 sign) +{ +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10002000 && mem < 0x10008000 ) + SysPrintf("hwRead16 to %x\n", mem); +#endif +#ifdef PCSX2_DEVBUILD + if( mem >= 0x10000000 && mem < 0x10002000 ){ +#ifdef EECNT_LOG + EECNT_LOG("cnt read to %x\n", mem); +#endif + } +#endif + + switch (mem) { + case 0x10000000: + PUSH32I(0); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem16(x86reg, (uptr)&counters[0].mode, sign); + return 0; + case 0x10000020: + _eeReadConstMem16(x86reg, (uptr)&counters[0].mode, sign); + return 0; + case 0x10000030: + _eeReadConstMem16(x86reg, (uptr)&counters[0].hold, sign); + return 0; + + case 0x10000800: + PUSH32I(1); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10000810: + _eeReadConstMem16(x86reg, (uptr)&counters[1].mode, sign); + return 0; + + case 0x10000820: + _eeReadConstMem16(x86reg, (uptr)&counters[1].target, sign); + return 0; + + case 0x10000830: + _eeReadConstMem16(x86reg, (uptr)&counters[1].hold, sign); + return 0; + + case 0x10001000: + PUSH32I(2); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001010: + _eeReadConstMem16(x86reg, (uptr)&counters[2].mode, sign); + return 0; + + case 0x10001020: + _eeReadConstMem16(x86reg, (uptr)&counters[2].target, sign); + return 0; + + case 0x10001800: + PUSH32I(3); + CONSTREAD16_CALL(rcntRcount); + ADD32ItoR(ESP, 4); + return 1; + + case 0x10001810: + _eeReadConstMem16(x86reg, (uptr)&counters[3].mode, sign); + return 0; + + case 0x10001820: + _eeReadConstMem16(x86reg, (uptr)&counters[3].target, sign); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else ) + XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + MMXONLY(if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff] - 2); + PORMtoR(x86reg&0xf, (uptr)&s_regreads[0]); + PANDMtoR(x86reg&0xf, (uptr)&s_regreads[1]); + } + else ) + { + if( sign ) MOVSX32M16toR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + else MOVZX32M16toR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + + OR32ItoR(x86reg, 0x0102); + AND32ItoR(x86reg, ~0x4000); + } + return 0; + } + } + if (mem < 0x10010000) { + _eeReadConstMem16(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign); + } + else { + MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); + else ) + XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +#ifdef PCSX2_VIRTUAL_MEM + +#if defined(_MSC_VER) && !defined(__x86_64__) +__declspec(naked) void recCheckF440() +{ + __asm { + add b440, 1 + mov eax, b440 + sub eax, 3 + mov edx, 31 + + cmp eax, 27 + ja WriteVal + shl eax, 2 + mov edx, dword ptr [eax+b440table] + +WriteVal: + mov eax, PS2MEM_BASE_+0x1000f440 + mov dword ptr [eax], edx + ret + } +} +#else +void recCheckF440(); +#endif + +void iMemRead32Check() +{ + // test if 0xf440 + if( bExecBIOS ) { + u8* ptempptr[2]; + CMP32ItoR(ECX, 0x1000f440); + ptempptr[0] = JNE8(0); + +// // increment and test +// INC32M((uptr)&b440); +// MOV32MtoR(EAX, (uptr)&b440); +// SUB32ItoR(EAX, 3); +// MOV32ItoR(EDX, 31); +// +// CMP32ItoR(EAX, 27); +// +// // look up table +// ptempptr[1] = JA8(0); +// SHL32ItoR(EAX, 2); +// ADD32ItoR(EAX, (int)b440table); +// MOV32RmtoR(EDX, EAX); +// +// x86SetJ8( ptempptr[1] ); +// +// MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); + CALLFunc((uptr)recCheckF440); + + x86SetJ8( ptempptr[0] ); + } +} + +#endif + +int hwConstRead32(u32 x86reg, u32 mem) +{ + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + return ipuConstRead32(x86reg, mem); + } + + switch (mem) { + case 0x10000000: + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 count read = %x\n", rcntRcount(0)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10000010: + _eeReadConstMem32(x86reg, (uptr)&counters[0].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 mode read = %x\n", counters[0].mode); +#endif + return 0; + case 0x10000020: + _eeReadConstMem32(x86reg, (uptr)&counters[0].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 0 target read = %x\n", counters[0].target); +#endif + return 0; + case 0x10000030: + _eeReadConstMem32(x86reg, (uptr)&counters[0].hold); + return 0; + + case 0x10000800: + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 count read = %x\n", rcntRcount(1)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10000810: + _eeReadConstMem32(x86reg, (uptr)&counters[1].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 mode read = %x\n", counters[1].mode); +#endif + return 0; + case 0x10000820: + _eeReadConstMem32(x86reg, (uptr)&counters[1].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 1 target read = %x\n", counters[1].target); +#endif + return 0; + case 0x10000830: + _eeReadConstMem32(x86reg, (uptr)&counters[1].hold); + return 0; + + case 0x10001000: + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 count read = %x\n", rcntRcount(2)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10001010: + _eeReadConstMem32(x86reg, (uptr)&counters[2].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 mode read = %x\n", counters[2].mode); +#endif + return 0; + case 0x10001020: + _eeReadConstMem32(x86reg, (uptr)&counters[2].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 2 target read = %x\n", counters[2].target); +#endif + return 0; + case 0x10001030: + _eeReadConstMem32(x86reg, (uptr)&counters[2].hold); + return 0; + + case 0x10001800: + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)rcntRcount); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 count read = %x\n", rcntRcount(3)); +#endif + ADD32ItoR(ESP, 4); + return 1; + case 0x10001810: + _eeReadConstMem32(x86reg, (uptr)&counters[3].mode); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 mode read = %x\n", counters[3].mode); +#endif + return 0; + case 0x10001820: + _eeReadConstMem32(x86reg, (uptr)&counters[3].target); +#ifdef EECNT_LOG + EECNT_LOG("Counter 3 target read = %x\n", counters[3].target); +#endif + return 0; + case 0x10001830: + _eeReadConstMem32(x86reg, (uptr)&counters[3].hold); + return 0; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);) + else XOR32RtoR(x86reg, x86reg); + return 0; + + case 0x1000f440: + //iMemRead32Check(); + // increment and test + INC32M((uptr)&b440); + MOV32MtoR(EAX, (uptr)&b440); + SUB32ItoR(EAX, 3); + MOV32ItoR(EDX, 31); + + CMP32ItoR(EAX, 27); + + // look up table + j8Ptr[8] = JA8(0); + SHL32ItoR(EAX, 2); + ADD32ItoR(EAX, (int)b440table); + MOV32RmtoR(EDX, EAX); + + x86SetJ8( j8Ptr[8] ); + + MOV32RtoM( (uptr)PS2MEM_HW+0xf440, EDX); + + if( IS_XMMREG(x86reg) ) SSE2_MOVD_R_to_XMM(x86reg&0xf, EDX); + MMXONLY(else if( IS_MMXREG(x86reg) ) MOVD32RtoMMX(x86reg&0xf, EDX);) + else MOV32RtoR(x86reg, EDX); + + return 0; + + case 0x1000f520: // DMAC_ENABLER + _eeReadConstMem32(x86reg, (uptr)&PS2MEM_HW[0xf590]); + return 0; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + if(mem == 0x1000f260) { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);) + else XOR32RtoR(x86reg, x86reg); + return 0; + } + else if(mem == 0x1000F240) { + + if( IS_XMMREG(x86reg) ) { + SSEX_MOVD_M32_to_XMM(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + SSEX_POR_M128_to_XMM(x86reg&0xf, (uptr)&s_regreads[2]); + } + MMXONLY(else if( IS_MMXREG(x86reg) ) { + MOVDMtoMMX(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + PORMtoR(x86reg&0xf, (uptr)&s_regreads[2]); + }) + else { + MOV32MtoR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + OR32ItoR(x86reg, 0xF0000102); + } + return 0; + } + } + + if (mem < 0x10010000) { + _eeReadConstMem32(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]); + } + else { + if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); + MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);) + else XOR32RtoR(x86reg, x86reg); + } + + return 0; + } +} + +void hwConstRead64(u32 mem, int mmreg) { + if ((mem>=0x10002000) && (mem<0x10003000)) { + ipuConstRead64(mem, mmreg); + return; + } + + if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (uptr)PSM(mem)); + else { + X86_64ASSERT(); + MMXONLY(MOVQMtoR(mmreg, (uptr)PSM(mem)); + SetMMXstate();) + } +} + +PCSX2_ALIGNED16(u32 s_TempFIFO[4]); +void hwConstRead128(u32 mem, int xmmreg) { + if (mem >= 0x10004000 && mem < 0x10008000) { + iFlushCall(0); + PUSH32I((uptr)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((uptr)ReadFIFO); + ADD32ItoR(ESP, 8); + _eeReadConstMem128( xmmreg, (uptr)&s_TempFIFO[0]); + return; + } + + _eeReadConstMem128( xmmreg, (uptr)PSM(mem)); +} + +// when writing imm +#define recDmaExecI8(name, num) { \ + MOV8ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \ + TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((uptr)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec8(name, num) { \ + iFlushCall(0); \ + if( IS_EECONSTREG(mmreg) ) { \ + recDmaExecI8(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem8((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST8ItoR(EAX, 1); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((uptr)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +static void PrintDebug(u8 value) +{ + if (value == '\n') { + sio_buffer[sio_count] = 0; + SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer); + sio_count = 0; + } else { + if (sio_count < 1023) { + sio_buffer[sio_count++] = value; + } + } +} + +#define CONSTWRITE_CALLTIMER(name, index, bit) { \ + if( !IS_EECONSTREG(mmreg) ) { \ + if( bit == 8 ) MOVZX32R8toR(mmreg&0xf, mmreg&0xf); \ + else if( bit == 16 ) MOVZX32R16toR(mmreg&0xf, mmreg&0xf); \ + } \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + PUSH32I(index); \ + CALLFunc((uptr)name); \ + ADD32ItoR(ESP, 8); \ +} \ + +#define CONSTWRITE_TIMERS(bit) \ + case 0x10000000: CONSTWRITE_CALLTIMER(rcntWcount, 0, bit); break; \ + case 0x10000010: CONSTWRITE_CALLTIMER(rcntWmode, 0, bit); break; \ + case 0x10000020: CONSTWRITE_CALLTIMER(rcntWtarget, 0, bit); break; \ + case 0x10000030: CONSTWRITE_CALLTIMER(rcntWhold, 0, bit); break; \ + \ + case 0x10000800: CONSTWRITE_CALLTIMER(rcntWcount, 1, bit); break; \ + case 0x10000810: CONSTWRITE_CALLTIMER(rcntWmode, 1, bit); break; \ + case 0x10000820: CONSTWRITE_CALLTIMER(rcntWtarget, 1, bit); break; \ + case 0x10000830: CONSTWRITE_CALLTIMER(rcntWhold, 1, bit); break; \ + \ + case 0x10001000: CONSTWRITE_CALLTIMER(rcntWcount, 2, bit); break; \ + case 0x10001010: CONSTWRITE_CALLTIMER(rcntWmode, 2, bit); break; \ + case 0x10001020: CONSTWRITE_CALLTIMER(rcntWtarget, 2, bit); break; \ + \ + case 0x10001800: CONSTWRITE_CALLTIMER(rcntWcount, 3, bit); break; \ + case 0x10001810: CONSTWRITE_CALLTIMER(rcntWmode, 3, bit); break; \ + case 0x10001820: CONSTWRITE_CALLTIMER(rcntWtarget, 3, bit); break; \ + +void hwConstWrite8(u32 mem, int mmreg) +{ + switch (mem) { + CONSTWRITE_TIMERS(8) + + case 0x1000f180: + _recPushReg(mmreg); \ + iFlushCall(0); + CALLFunc((uptr)PrintDebug); + ADD32ItoR(ESP, 4); + break; + + case 0x10008001: // dma0 - vif0 + recDmaExec8(VIF0, 0); + break; + + case 0x10009001: // dma1 - vif1 + recDmaExec8(VIF1, 1); + break; + + case 0x1000a001: // dma2 - gif + recDmaExec8(GIF, 2); + break; + + case 0x1000b001: // dma3 - fromIPU + recDmaExec8(IPU0, 3); + break; + + case 0x1000b401: // dma4 - toIPU + recDmaExec8(IPU1, 4); + break; + + case 0x1000c001: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec8(SIF0, 5); + break; + + case 0x1000c401: // dma6 - sif1 + recDmaExec8(SIF1, 6); + break; + + case 0x1000c801: // dma7 - sif2 + recDmaExec8(SIF2, 7); + break; + + case 0x1000d001: // dma8 - fromSPR + recDmaExec8(SPR0, 8); + break; + + case 0x1000d401: // dma9 - toSPR + recDmaExec8(SPR1, 9); + break; + + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem8( (uptr)&PS2MEM_HW[0xf522], mmreg ); + _eeWriteConstMem8( (uptr)&PS2MEM_HW[0xf592], mmreg ); + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem8( (uptr)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x40: + if( IS_EECONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JNZ8(0); + AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100); + x86SetJ8(j8Ptr[5]); + } + break; + } + return; + } + assert( (mem&0xff0f) != 0xf200 ); + + switch(mem&~3) { + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: +#ifdef PCSX2_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem8((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } + + break; + } +} + +#define recDmaExecI16(name, num) { \ + MOV16ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ + if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \ + TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((uptr)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec16(name, num) { \ + iFlushCall(0); \ + if( IS_EECONSTREG(mmreg) ) { \ + recDmaExecI16(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + _eeWriteConstMem16((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST16ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((uptr)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +void hwConstWrite16(u32 mem, int mmreg) +{ + switch(mem&~3) { + CONSTWRITE_TIMERS(16) + case 0x10008000: // dma0 - vif0 + recDmaExec16(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec16(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec16(GIF, 2); + break; + case 0x1000b000: // dma3 - fromIPU + recDmaExec16(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec16(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec16(SIF0, 5); + break; + case 0x1000c002: + //? + break; + case 0x1000c400: // dma6 - sif1 + recDmaExec16(SIF1, 6); + break; + case 0x1000c800: // dma7 - sif2 + recDmaExec16(SIF2, 7); + break; + case 0x1000c802: + //? + break; + case 0x1000d000: // dma8 - fromSPR + recDmaExec16(SPR0, 8); + break; + case 0x1000d400: // dma9 - toSPR + recDmaExec16(SPR1, 9); + break; + case 0x1000f592: // DMAC_ENABLEW + _eeWriteConstMem16((uptr)&PS2MEM_HW[0xf522], mmreg); + _eeWriteConstMem16((uptr)&PS2MEM_HW[0xf592], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem16OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + if( IS_EECONSTREG(mmreg) ) { + AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else { + NOT32R(mmreg&0xf); + AND16RtoM((uptr)&PS2MEM_HW[mem&0xffff], mmreg&0xf); + } + break; + case 0x40: + if( IS_EECONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100); + } + else { + OR16ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST16ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR16ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + _eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef PCSX2_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + } +} + +// when writing an Imm +#define recDmaExecI(name, num) { \ + u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \ + if(mem!= 0x1000c000 && mem != 0x1000c800) MOV16ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], c); \ + else MOV32ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], c); \ + if( c & 0x100 ) { \ + TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + CALLFunc((uptr)dma##name); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define recDmaExec(name, num) { \ + iFlushCall(0); \ + if( IS_EECONSTREG(mmreg) ) { \ + recDmaExecI(name, num); \ + } \ + else { \ + _eeMoveMMREGtoR(EAX, mmreg); \ + if(mem!= 0x1000c000 && mem != 0x1000c800) { \ + if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \ + MOV16RtoM((uptr)&PS2MEM_HW[(mem) & 0xffff], EAX); \ + } \ + else { \ + _eeWriteConstMem16((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + } \ + } \ + else _eeWriteConstMem32((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ + \ + TEST16ItoR(EAX, 0x100); \ + j8Ptr[5] = JZ8(0); \ + TEST32ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ + j8Ptr[6] = JZ8(0); \ + \ + CALLFunc((uptr)dma##name); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ + } \ +} \ + +#define CONSTWRITE_CALLTIMER32(name, index, bit) { \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + PUSH32I(index); \ + CALLFunc((uptr)name); \ + ADD32ItoR(ESP, 8); \ +} \ + +void hwConstWrite32(u32 mem, int mmreg) +{ + //IPU regs + if ((mem>=0x10002000) && (mem<0x10003000)) { + //psHu32(mem) = value; + ipuConstWrite32(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((uptr)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((uptr)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x10000000: CONSTWRITE_CALLTIMER32(rcntWcount, 0, bit); break; + case 0x10000010: CONSTWRITE_CALLTIMER32(rcntWmode, 0, bit); break; + case 0x10000020: CONSTWRITE_CALLTIMER32(rcntWtarget, 0, bit); break; + case 0x10000030: CONSTWRITE_CALLTIMER32(rcntWhold, 0, bit); break; + + case 0x10000800: CONSTWRITE_CALLTIMER32(rcntWcount, 1, bit); break; + case 0x10000810: CONSTWRITE_CALLTIMER32(rcntWmode, 1, bit); break; + case 0x10000820: CONSTWRITE_CALLTIMER32(rcntWtarget, 1, bit); break; + case 0x10000830: CONSTWRITE_CALLTIMER32(rcntWhold, 1, bit); break; + + case 0x10001000: CONSTWRITE_CALLTIMER32(rcntWcount, 2, bit); break; + case 0x10001010: CONSTWRITE_CALLTIMER32(rcntWmode, 2, bit); break; + case 0x10001020: CONSTWRITE_CALLTIMER32(rcntWtarget, 2, bit); break; + + case 0x10001800: CONSTWRITE_CALLTIMER32(rcntWcount, 3, bit); break; + case 0x10001810: CONSTWRITE_CALLTIMER32(rcntWmode, 3, bit); break; + case 0x10001820: CONSTWRITE_CALLTIMER32(rcntWtarget, 3, bit); break; + + case GIF_CTRL: + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((uptr)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((uptr)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + return; + + case GIF_STAT: // stat is readonly + return; + + case 0x10008000: // dma0 - vif0 + recDmaExec(VIF0, 0); + break; + + case 0x10009000: // dma1 - vif1 - chcr + recDmaExec(VIF1, 1); + break; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000b000: // dma3 - fromIPU + recDmaExec(IPU0, 3); + break; + case 0x1000b400: // dma4 - toIPU + recDmaExec(IPU1, 4); + break; + case 0x1000c000: // dma5 - sif0 + //if (value == 0) psxSu32(0x30) = 0x40000; + recDmaExec(SIF0, 5); + break; + + case 0x1000c400: // dma6 - sif1 + recDmaExec(SIF1, 6); + break; + + case 0x1000c800: // dma7 - sif2 + recDmaExec(SIF2, 7); + break; + + case 0x1000d000: // dma8 - fromSPR + recDmaExec(SPR0, 8); + break; + + case 0x1000d400: // dma9 - toSPR + recDmaExec(SPR1, 9); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((uptr)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((uptr)&PS2MEM_HW[0xf000], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + _eeMoveMMREGtoR(EAX, mmreg); + iFlushCall(0); + XOR16RtoM((uptr)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((uptr)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg); + return; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + if ((mem & 0xffffff0f) == 0x1000f200) { + u32 at = mem & 0xf0; + switch(at) + { + case 0x00: + _eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + break; + case 0x20: + _eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 1); + break; + case 0x30: + _eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + case 0x40: + if( IS_EECONSTREG(mmreg) ) { + if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { + AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100); + } + else { + OR32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100); + } + } + else { + _eeMoveMMREGtoR(EAX, mmreg); + TEST32ItoR(EAX, 0x100); + j8Ptr[5] = JZ8(0); + OR32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100); + + x86SetJ8( j8Ptr[6] ); + } + + break; + case 0x60: + MOV32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0); + break; + } + return; + } + +#ifdef PCSX2_VIRTUAL_MEM + //NOTE: this might cause crashes, but is more correct + _eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg); +#else + if (mem < 0x10010000) + { + _eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + } +#endif + break; + } +} + +void hwConstWrite64(u32 mem, int mmreg) +{ + if ((mem>=0x10002000) && (mem<=0x10002030)) { + ipuConstWrite64(mem, mmreg); + return; + } + + if ((mem>=0x10003800) && (mem<0x10003c00)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((uptr)vif0Write32); + ADD32ItoR(ESP, 8); + return; + } + if ((mem>=0x10003c00) && (mem<0x10004000)) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(mem); + CALLFunc((uptr)vif1Write32); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case GIF_CTRL: + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + TEST8ItoR(EAX, 1); + j8Ptr[5] = JZ8(0); + + // reset GS + CALLFunc((uptr)gsGIFReset); + j8Ptr[6] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND32I8toR(EAX, 8); + MOV32RtoM((uptr)&PS2MEM_HW[mem&0xffff], EAX); + + TEST16ItoR(EAX, 8); + j8Ptr[5] = JZ8(0); + OR8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], 8); + j8Ptr[7] = JMP8(0); + + x86SetJ8( j8Ptr[5] ); + AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~8); + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + return; + + case GIF_MODE: + _eeMoveMMREGtoR(EAX, mmreg); + _eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg); + + AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~5); + AND8ItoR(EAX, 5); + OR8RtoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], EAX); + break; + + case GIF_STAT: // stat is readonly + return; + + case 0x1000a000: // dma2 - gif + recDmaExec(GIF, 2); + break; + + case 0x1000e010: // DMAC_STAT + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX); + + SHR32ItoR(EAX, 16); + XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX); + + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((uptr)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + break; + + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg); + break; + + case 0x1000f000: // INTC_STAT + _eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 2); + break; + + case 0x1000f010: // INTC_MASK + + _eeMoveMMREGtoR(EAX, mmreg); + + iFlushCall(0); + XOR16RtoM((uptr)&PS2MEM_HW[0xf010], EAX); + + MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val); + AND32ItoR(EAX, 0x10007); + CMP32ItoR(EAX, 0x10001); + j8Ptr[5] = JNE8(0); + CALLFunc((uptr)cpuTestDMACInts); + + x86SetJ8( j8Ptr[5] ); + + break; + + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + default: + + _eeWriteConstMem64((uptr)PSM(mem), mmreg); + break; + } +} + +void hwConstWrite128(u32 mem, int mmreg) +{ + if (mem >= 0x10004000 && mem < 0x10008000) { + _eeWriteConstMem128((uptr)&s_TempFIFO[0], mmreg); + iFlushCall(0); + PUSH32I((uptr)&s_TempFIFO[0]); + PUSH32I(mem); + CALLFunc((uptr)WriteFIFO); + ADD32ItoR(ESP, 8); + return; + } + + switch (mem) { + case 0x1000f590: // DMAC_ENABLEW + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg); + _eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg); + break; + case 0x1000f130: + case 0x1000f410: + case 0x1000f430: + break; + + default: + +#ifdef PCSX2_VIRTUAL_MEM + _eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg); +#else + if (mem < 0x10010000) + _eeWriteConstMem128((uptr)&PS2MEM_HW[mem&0xffff], mmreg); +#endif + break; + } +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iMMI.c b/pcsx2/x86/iMMI.c new file mode 100644 index 0000000..0304076 --- /dev/null +++ b/pcsx2/x86/iMMI.c @@ -0,0 +1,3393 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* cached MMI opcodes * +* * +*********************************************************/ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" + +#ifndef MMI_RECOMPILE + +REC_FUNC( PLZCW, _Rd_ ); + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +REC_FUNC( PMFHL, _Rd_ ); +REC_FUNC( PMTHL, _Rd_ ); + +REC_FUNC( PSRLW, _Rd_ ); +REC_FUNC( PSRLH, _Rd_ ); + +REC_FUNC( PSRAH, _Rd_ ); +REC_FUNC( PSRAW, _Rd_ ); + +REC_FUNC( PSLLH, _Rd_ ); +REC_FUNC( PSLLW, _Rd_ ); + +#else + +void recPLZCW() +{ + int regd = -1; + int regs = 0; + + if ( ! _Rd_ ) return; + + if( GPR_IS_CONST1(_Rs_) ) { + _eeOnWriteReg(_Rd_, 0); + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + + for(regs = 0; regs < 2; ++regs) { + u32 val = g_cpuConstRegs[_Rs_].UL[regs]; + + if( val != 0 ) { + u32 setbit = val&0x80000000; + g_cpuConstRegs[_Rd_].UL[regs] = 0; + val <<= 1; + + while((val & 0x80000000) == setbit) { + g_cpuConstRegs[_Rd_].UL[regs]++; + val <<= 1; + } + } + else { + g_cpuConstRegs[_Rd_].UL[regs] = 31; + } + } + return; + } + + _eeOnWriteReg(_Rd_, 0); + + if( (regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE2_MOVD_XMM_to_R(EAX, regs); + regs |= MEM_XMMTAG; + } +#ifndef __x86_64__ + else if( (regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVD32MMXtoR(EAX, regs); + SetMMXstate(); + regs |= MEM_MMXTAG; + } +#endif + else { + MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + regs = 0; + } + + if( EEINST_ISLIVE1(_Rd_) ) + _deleteEEreg(_Rd_, 0); +#ifndef __x86_64__ + else { + if( (regd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) < 0 ) { + _deleteEEreg(_Rd_, 0); + } + } +#endif + + // first word + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 31); + } +#ifndef __x86_64__ + else { + SetMMXstate(); + PCMPEQDRtoR(regd, regd); + PSRLQItoR(regd, 59); + } +#endif + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + if( EEINST_ISLIVE1(_Rd_) || regd < 0 ) { + MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } +#ifndef __x86_64__ + else { + SetMMXstate(); + MOVD32RtoMMX(regd, ECX); + } +#endif + + x86SetJ8(j8Ptr[1]); + + // second word + if( EEINST_ISLIVE1(_Rd_) ) { + if( regs >= 0 && (regs & MEM_XMMTAG) ) { + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + SSE2_MOVD_XMM_to_R(EAX, regs&0xf); + SSE2_PSHUFD_XMM_to_XMM(regs&0xf, regs&0xf, 0x4e); + } +#ifndef __x86_64__ + else if( regs >= 0 && (regs & MEM_MMXTAG) ) { + PSHUFWRtoR(regs, regs, 0x4e); + MOVD32MMXtoR(EAX, regs&0xf); + PSHUFWRtoR(regs&0xf, regs&0xf, 0x4e); + SetMMXstate(); + } +#endif + else MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + + TEST32RtoR(EAX, EAX); + j8Ptr[0] = JNZ8(0); + + // zero, so put 31 + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 31); + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + TEST32ItoR(EAX, 0x80000000); + j8Ptr[0] = JZ8(0); + NOT32R(EAX); + x86SetJ8(j8Ptr[0]); + + // not zero + x86SetJ8(j8Ptr[0]); + BSRRtoR(EAX, EAX); + MOV32ItoR(ECX, 30); + SUB32RtoR(ECX, EAX); + MOV32RtoM((uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX); + x86SetJ8(j8Ptr[1]); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + + GPR_DEL_CONST(_Rd_); +} + +static u32 PCSX2_ALIGNED16(s_CmpMasks[]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPMFHL() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) + + int t0reg; + + switch (_Sa_) { + case 0x00: // LW + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + break; + + case 0x01: // UW + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0xdd); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0xdd); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x02: // SLW + // fall to interp + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + iFlushCall(FLUSH_CACHED_REGS); // since calling CALLFunc + CALLFunc( (u32)PMFHL ); + break; + + case 0x03: // LH + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + break; + + case 0x04: // SH + if( EEREC_D == EEREC_HI ) { + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x72); + } + else { + if( EEREC_D != EEREC_LO ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + SSE2_PACKSSDW_XMM_to_XMM(EEREC_D, EEREC_HI); + + // shuffle so a1a0b1b0->a1b1a0b0 + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); + } + break; + default: + SysPrintf("PMFHL??\n"); + assert(0); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMFHL, _Rd_ ); +} + +void recPMTHL() +{ + SysPrintf("PMTHL email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PMTHL, 0 ); +} + +#ifndef MMI0_RECOMPILE + +REC_FUNC( MMI0, _Rd_ ); + +#endif + +#ifndef MMI1_RECOMPILE + +REC_FUNC( MMI1, _Rd_ ); + +#endif + +#ifndef MMI2_RECOMPILE + +REC_FUNC( MMI2, _Rd_ ); + +#endif + +#ifndef MMI3_RECOMPILE + +REC_FUNC( MMI3, _Rd_ ); + +#endif + +#ifdef __x86_64__ + +#define MMX_ALLOC_TEMP1(code) +#define MMX_ALLOC_TEMP2(code) +#define MMX_ALLOC_TEMP3(code) +#define MMX_ALLOC_TEMP4(code) + +#else + +// MMX helper routines +#define MMX_ALLOC_TEMP1(code) { \ + int t0reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ +} \ + +#define MMX_ALLOC_TEMP2(code) { \ + int t0reg, t1reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ +} \ + +#define MMX_ALLOC_TEMP3(code) { \ + int t0reg, t1reg, t2reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ +} \ + +#define MMX_ALLOC_TEMP4(code) { \ + int t0reg, t1reg, t2reg, t3reg; \ + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t2reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + t3reg = _allocMMXreg(-1, MMX_TEMP, 0); \ + code; \ + _freeMMXreg(t0reg); \ + _freeMMXreg(t1reg); \ + _freeMMXreg(t2reg); \ + _freeMMXreg(t3reg); \ +} \ + +#endif // __x86_64__ + +//////////////////////////////////////////////////// +void recPSRLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLWItoR( t0reg, _Sa_&0xf ); + PSRLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRLW( void ) +{ + if( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRLDItoR( t0reg, _Sa_ ); + PSRLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRAWItoR( t0reg, _Sa_&0xf ); + PSRAWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSRAW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSRADItoR( t0reg, _Sa_ ); + PSRADItoR( t1reg, _Sa_ ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLH( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( (_Sa_&0xf) == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLWItoR( t0reg, _Sa_&0xf ); + PSLLWItoR( t1reg, _Sa_&0xf ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSLLW( void ) +{ + if ( !_Rd_ ) return; + + CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + if( _Sa_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + return; + } + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); + CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSLLDItoR( t0reg, _Sa_ ); + PSLLDItoR( t1reg, _Sa_ ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +/* +void recMADD( void ) +{ +} + +void recMADDU( void ) +{ +} + +void recPLZCW( void ) +{ +} +*/ + +#ifdef MMI0_RECOMPILE + +void recMMI0( void ) +{ + recMMI0t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI1_RECOMPILE + +void recMMI1( void ) +{ + recMMI1t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI2_RECOMPILE + +void recMMI2( void ) +{ + recMMI2t[ _Sa_ ]( ); +} + +#endif + +#ifdef MMI3_RECOMPILE + +void recMMI3( void ) +{ + recMMI3t[ _Sa_ ]( ); +} + +#endif + +#endif + +/********************************************************* +* MMI0 opcodes * +* * +*********************************************************/ +#ifndef MMI0_RECOMPILE + +REC_FUNC( PADDB, _Rd_); +REC_FUNC( PADDH, _Rd_); +REC_FUNC( PADDW, _Rd_); +REC_FUNC( PADDSB, _Rd_); +REC_FUNC( PADDSH, _Rd_); +REC_FUNC( PADDSW, _Rd_); +REC_FUNC( PSUBB, _Rd_); +REC_FUNC( PSUBH, _Rd_); +REC_FUNC( PSUBW, _Rd_); +REC_FUNC( PSUBSB, _Rd_); +REC_FUNC( PSUBSH, _Rd_); +REC_FUNC( PSUBSW, _Rd_); + +REC_FUNC( PMAXW, _Rd_); +REC_FUNC( PMAXH, _Rd_); + +REC_FUNC( PCGTW, _Rd_); +REC_FUNC( PCGTH, _Rd_); +REC_FUNC( PCGTB, _Rd_); + +REC_FUNC( PEXTLW, _Rd_); + +REC_FUNC( PPACW, _Rd_); +REC_FUNC( PEXTLH, _Rd_); +REC_FUNC( PPACH, _Rd_); +REC_FUNC( PEXTLB, _Rd_); +REC_FUNC( PPACB, _Rd_); +REC_FUNC( PEXT5, _Rd_); +REC_FUNC( PPAC5, _Rd_); + +#else + +//////////////////////////////////////////////////// +void recPMAXW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMAXW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPACW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(((_Rs_!=0||!cpucaps.hasStreamingSIMD2Extensions)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + + // swap mmx regs.. don't ask + xmmregs[t0reg] = xmmregs[EEREC_D]; + xmmregs[EEREC_D].inuse = 0; + } + } + } + else { + if( EEREC_D != EEREC_S ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x88 ); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x88 ); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); //Copy this one cos it could get overwritten + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[2]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], ECX); //This is where we bring it back + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +void recPPACH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSHUFLW_XMM_to_XMM(t0reg, EEREC_S, 0x88); + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(t0reg, t0reg, 0x88); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PSRLDQ_I8_to_XMM(t0reg, 4); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 4); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + else { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, t0reg, 0x88); + } + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[6]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[4]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +//////////////////////////////////////////////////// +void recPPACB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, EEREC_D); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(t0reg, 8); + SSE2_PSLLW_I8_to_XMM(EEREC_D, 8); + SSE2_PSRLW_I8_to_XMM(t0reg, 8); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + + SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PPACB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXT5() +{ + SysPrintf("PEXT5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PEXT5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPPAC5() +{ + SysPrintf("PPAC5 email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PPAC5, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMAXH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + if( cpucaps.hasStreamingSIMDExtensions ) { + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + SSE_PMAXSW_MM_to_MM( t0reg, t1reg ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMAXSW_MM_to_MM( t2reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) + } + else { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PMAXH ); + } +} + +//////////////////////////////////////////////////// +void recPCGTB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PCMPGTBRtoR( t0reg, t1reg ); + + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPGTBRtoR( t2reg, t3reg); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTWRtoR( t0reg, t1reg ); + PCMPGTWRtoR( t2reg, t3reg); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCGTW( void ) +{ + //TODO:optimize RS | RT== 0 + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D != EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + PCMPGTDRtoR( t0reg, t1reg ); + PCMPGTDRtoR( t2reg, t3reg); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSBRtoR( t0reg, t2reg); + PADDSBRtoR( t1reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDSWRtoR( t0reg, t2reg); + PADDSWRtoR( t1reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + + //SysPrintf("PADDSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PADDSW ); +} + +//////////////////////////////////////////////////// +void recPSUBSB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSBRtoR( t0reg, t2reg); + PSUBSBRtoR( t1reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBSWRtoR( t0reg, t2reg); + PSUBSWRtoR( t1reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBSW( void ) +{ + if ( ! _Rd_ ) return; + +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) +//CPU_SSE_XMMCACHE_END + //SysPrintf("PSUBSW email zero if abnormal behavior\n"); + + if( _Rd_ ) _deleteEEreg(_Rd_, 0); + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + _flushConstRegs(); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PSUBSW ); +} + +//////////////////////////////////////////////////// +void recPADDB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDBRtoR( t0reg, t2reg ); + PADDBRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDWRtoR( t0reg, t2reg ); + PADDWRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + else if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDDRtoR( t0reg, t2reg ); + PADDDRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBBRtoR( t0reg, t2reg ); + PSUBBRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBWRtoR( t0reg, t2reg ); + PSUBWRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPSUBW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PSUBDRtoR( t0reg, t2reg); + PSUBDRtoR( t1reg, t3reg); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPEXTLW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); +} + +void recPEXTLB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + //SysPrintf("PEXTLB\n"); + //Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[7]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[7]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[6]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[6]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[5]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[5]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[4]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[4]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[3]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[3]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[2]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[2]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[1]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[1]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[0]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[0]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); +} + +void recPEXTLH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but quicker than int + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[3]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[7], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[3]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[6], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[2]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[5], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[4], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[1]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[2], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[0]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); + MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[0], EAX); +} + +#endif + +/********************************************************* +* MMI1 opcodes * +* * +*********************************************************/ +#ifndef MMI1_RECOMPILE + +REC_FUNC( PABSW, _Rd_); +REC_FUNC( PABSH, _Rd_); + +REC_FUNC( PMINW, _Rd_); +REC_FUNC( PADSBH, _Rd_); +REC_FUNC( PMINH, _Rd_); +REC_FUNC( PCEQB, _Rd_); +REC_FUNC( PCEQH, _Rd_); +REC_FUNC( PCEQW, _Rd_); + +REC_FUNC( PADDUB, _Rd_); +REC_FUNC( PADDUH, _Rd_); +REC_FUNC( PADDUW, _Rd_); + +REC_FUNC( PSUBUB, _Rd_); +REC_FUNC( PSUBUH, _Rd_); +REC_FUNC( PSUBUW, _Rd_); + +REC_FUNC( PEXTUW, _Rd_); +REC_FUNC( PEXTUH, _Rd_); +REC_FUNC( PEXTUB, _Rd_); +REC_FUNC( QFSRV, _Rd_); + +#else + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(int s_MaskHighBitD[4]) = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; +PCSX2_ALIGNED16(int s_MaskHighBitW[4]) = { 0x80008000, 0x80008000, 0x80008000, 0x80008000 }; + +void recPABSW() +{ + if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPABSH() +{ +if( !_Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(t0reg, 15); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _deleteEEreg(_Rt_, 1); + _deleteEEreg(_Rd_, 0); + _flushConstRegs(); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PABSW ); +} + +//////////////////////////////////////////////////// +void recPMINW() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, EEREC_S); + + if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, t1reg); + _freeXMMreg(t1reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, t0reg); + SSEX_PANDN_XMM_to_XMM(t0reg, EEREC_T); + } + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMINW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPADSBH() +{ + SysPrintf("PADSBH email zero if abnormal behavior\n"); + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int t0reg; + + if( EEREC_S == EEREC_T ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_D); + // reset lower bits to 0s + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 8); + return; + } + + t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + if( EEREC_D == EEREC_S ) { + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PADDW_XMM_to_XMM(t0reg, EEREC_S); + } + + // t0reg - adds, EEREC_D - subs + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE(PADSBH, _Rd_); +} + +//////////////////////////////////////////////////// +void recPADDUW() +{ +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rt_ == 0 ) { + if( _Rs_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( _Rs_ == 0 ) { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + int t2reg = _allocTempXMMreg(XMMT_INT, -1); + + if( _hasFreeXMMreg() ) { + int t3reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t3reg, EEREC_T); + SSE2_PUNPCKLDQ_XMM_to_XMM(t1reg, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t2reg, t0reg); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(t3reg, t0reg); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t3reg); + _freeXMMreg(t3reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(t2reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + + SSE2_MOVQ_XMM_to_XMM(t1reg, EEREC_S); + SSE2_PSRLDQ_I8_to_XMM(t2reg, 8); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 8); + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0xE8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xE8); + SSE2_PADDQ_XMM_to_XMM(t1reg, EEREC_D); + SSE2_PADDQ_XMM_to_XMM(t2reg, t0reg); + SSEX_PXOR_XMM_to_XMM(t0reg, t0reg); + } + + SSE2_PSHUFD_XMM_to_XMM(t1reg, t1reg, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t2reg, t2reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t1reg); + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, t2reg); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t2reg); + SSE2_PCMPGTD_XMM_to_XMM(t1reg, t0reg); + SSEX_POR_XMM_to_XMM(EEREC_D, t1reg); + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + } + +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUB() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUB, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PSUBUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSUBUW() +{ + SysPrintf("PSUBUW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSUBUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXTUH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXTUH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recQFSRV() +{ + u8* pshift1, *pshift2, *poldptr, *pnewptr; + + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + MOV32MtoR(EAX, (uptr)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + + poldptr = x86Ptr; + x86Ptr += 6; + + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 0); + pshift1 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((uptr)pshift1, EAX); + x86Ptr = pnewptr; + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + MOV32MtoR(EAX, (uptr)&cpuRegs.sa); + SHR32ItoR(EAX, 3); + MOV32ItoR(ECX, 16); + SUB32RtoR(ECX, EAX); + + poldptr = x86Ptr; + x86Ptr += 12; + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSRLDQ_I8_to_XMM(t0reg, 0); + pshift1 = x86Ptr-1; + + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLDQ_I8_to_XMM(EEREC_D, 0); + pshift2 = x86Ptr-1; + + pnewptr = x86Ptr; + x86Ptr = poldptr; + + MOV8RtoM((uptr)pshift1, EAX); + MOV8RtoM((uptr)pshift2, ECX); + + x86Ptr = pnewptr; + + SSEX_POR_XMM_to_XMM(EEREC_D, t0reg); + + _freeXMMreg(t0reg); + } + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( QFSRV, _Rd_ ); +} + + +void recPEXTUB( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction - Crude but faster than int + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[8]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[8]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[9]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[9]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[10]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[10]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[11]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[11]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[12]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[12]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[13]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[13]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[14]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[14]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[15]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); + MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[15]); + MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); +} + +//////////////////////////////////////////////////// +void recPEXTUW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + if( _Rs_ == 0 ) { + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 2 ] ); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 2 ] ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 3 ] ); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 3 ] ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); +} + +//////////////////////////////////////////////////// +void recPMINH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + if( cpucaps.hasStreamingSIMDExtensions ) { + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + SSE_PMINSW_MM_to_MM( t0reg, t2reg ); + SSE_PMINSW_MM_to_MM( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) + } + else { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc( (u32)PMINH ); + } +} + +//////////////////////////////////////////////////// +void recPCEQB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQBRtoR( t0reg, t2reg ); + PCMPEQBRtoR( t1reg, t3reg ); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQWRtoR( t0reg, t2reg ); + PCMPEQWRtoR( t1reg, t3reg ); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCEQW( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t0reg, t2reg ); + PCMPEQDRtoR( t1reg, t3reg ); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUB( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + if( _Rt_ ) { + if( EEREC_D == EEREC_S ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if( EEREC_D != EEREC_S ) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSBRtoR( t0reg, t2reg ); + PADDUSBRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPADDUH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP4( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PADDUSWRtoR( t0reg, t2reg ); + PADDUSWRtoR( t1reg, t3reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +#endif +/********************************************************* +* MMI2 opcodes * +* * +*********************************************************/ +#ifndef MMI2_RECOMPILE + +REC_FUNC( PMFHI, _Rd_); +REC_FUNC( PMFLO, _Rd_); +REC_FUNC( PCPYLD, _Rd_); +REC_FUNC( PAND, _Rd_); +REC_FUNC( PXOR, _Rd_); + +REC_FUNC( PMADDW, _Rd_); +REC_FUNC( PSLLVW, _Rd_); +REC_FUNC( PSRLVW, _Rd_); +REC_FUNC( PMSUBW, _Rd_); +REC_FUNC( PINTH, _Rd_); +REC_FUNC( PMULTW, _Rd_); +REC_FUNC( PDIVW, _Rd_); +REC_FUNC( PMADDH, _Rd_); +REC_FUNC( PHMADH, _Rd_); +REC_FUNC( PMSUBH, _Rd_); +REC_FUNC( PHMSBH, _Rd_); +REC_FUNC( PEXEH, _Rd_); +REC_FUNC( PREVH, _Rd_); +REC_FUNC( PMULTH, _Rd_); +REC_FUNC( PDIVBW, _Rd_); +REC_FUNC( PEXEW, _Rd_); +REC_FUNC( PROT3W, _Rd_ ); + +#else + +//////////////////////////////////////////////////// +void recPMADDW() +{ + SysPrintf("PMADDW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMADDW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSLLVW() +{ + SysPrintf("PSLLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSLLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPSRLVW() +{ + SysPrintf("PSRLVW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PSRLVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBW() +{ + SysPrintf("PMSUBW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); +//CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) +// int t0reg = _allocTempXMMreg(XMMT_INT, -1); +// +// if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); +// else { +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); +// SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); +// } +// +// // add from LO/HI +// SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSUBQ_XMM_to_XMM(EEREC_LO, EEREC_D); +// +// // get the signs +// SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +// SSE2_PSRAD_I8_to_XMM(t0reg, 31); +// +// // interleave +// SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); +// SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); +// SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); +// +// SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); +// SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); +// +// _freeXMMreg(t0reg); +//CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTW() +{ + SysPrintf("PMULTW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + REC_FUNC_INLINE( PMULTW, _Rd_ ); +} +//////////////////////////////////////////////////// +void recPDIVW() +{ + SysPrintf("PDIVW email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + REC_FUNC_INLINE( PDIVW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPDIVBW() +{ + SysPrintf("PDIVBW email zero if abnormal behavior\n"); + REC_FUNC_INLINE( PDIVBW, _Rd_ ); //-- +} + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(int s_mask[4]) = {~0, 0, ~0, 0}; + +void recPHMADH() +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _Rd_ ? EEREC_D : _allocTempXMMreg(XMMT_INT, -1); + + if( t0reg == EEREC_S ) { + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + if( t0reg == EEREC_T ) { + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + } + else { + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + } + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + } + else { + if( t0reg != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_T); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + } + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + SSE2_PAND_M128_to_XMM(EEREC_LO, (u32)s_mask); + SSE2_PAND_M128_to_XMM(EEREC_HI, (u32)s_mask); + + if( !_Rd_ ) _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMADH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMSUBH() +{ + SysPrintf("PMSUBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PSUBD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMSUBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPHMSBH() +{ + SysPrintf("PHMSBH email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, EEREC_LO); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); // 0,2,1,3, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); // 4,6,5,7, L->H + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, t0reg); + + SSE2_PUNPCKLDQ_XMM_to_XMM(t0reg, EEREC_HI); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + + SSE2_PSUBD_XMM_to_XMM(EEREC_LO, t0reg); + + if( _Rd_ ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); + } + + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_LO, 0xf5); + + _freeXMMreg(t0reg); + +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PHMSBH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXEH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xc6); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPREVH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x17); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x17); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PREVH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPINTH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_MOVHLPS_XMM_to_XMM(t0reg, EEREC_S); + if( EEREC_D != EEREC_T ) SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //Done - Refraction + MOV16MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[4]); + MOV16MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].US[1]); + MOV16MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); + MOV16MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); + + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[2], EBX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[4], ECX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[0], EDX); + + MOV16MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[5]); + MOV16MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rs_].US[6]); + MOV16MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rs_].US[7]); + MOV16MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].US[3]); + + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[5], EBX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[7], ECX); + MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[6], EDX); +} + +void recPEXEW( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPROT3W( void ) +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc9); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[1]); + MOV32MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV32MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[3]); + + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); +} + +void recPMULTH( void ) +{ +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(EEREC_LO, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(EEREC_HI, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_LO); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_LO, EEREC_HI); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(t0reg, EEREC_HI); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, t0reg, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_HI); + } + + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_LO, t0reg); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(!_Rt_ || !_Rs_) { + MOV32ItoM( (uptr)&cpuRegs.LO.UL[0], 0); + MOV32ItoM( (uptr)&cpuRegs.LO.UL[1], 0); + MOV32ItoM( (uptr)&cpuRegs.LO.UL[2], 0); + MOV32ItoM( (uptr)&cpuRegs.LO.UL[3], 0); + MOV32ItoM( (uptr)&cpuRegs.HI.UL[0], 0); + MOV32ItoM( (uptr)&cpuRegs.HI.UL[1], 0); + MOV32ItoM( (uptr)&cpuRegs.HI.UL[2], 0); + MOV32ItoM( (uptr)&cpuRegs.HI.UL[3], 0); + + if( _Rd_ ) { + MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], 0); + MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], 0); + MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], 0); + } + return; + } + + //Done - Refraction + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[3], EAX); + + if (_Rd_) { + MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[2]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[2]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +void recPMFHI( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_HI); +CPU_SSE_XMMCACHE_END + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.HI.UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.HI.UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMFLO( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.LO.UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.LO.UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPAND( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PANDMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PANDMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPXOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + if( EEREC_D == EEREC_T ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else if( EEREC_D == EEREC_S ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PXORMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PXORMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYLD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READS)|XMMINFO_READT) + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rs_ == 0 ) { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + else if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + else { + if( EEREC_D == EEREC_T ) SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0x44); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t1reg ); + SetMMXstate(); + ) +} + + +void recPMADDH( void ) +{ +CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + int t1reg = _allocTempXMMreg(XMMT_INT, -1); + + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSEX_MOVDQA_XMM_to_XMM(t1reg, EEREC_S); + + SSE2_PMULLW_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PMULHW_XMM_to_XMM(t1reg, EEREC_T); + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, t0reg); + + // 0-3 + SSE2_PUNPCKLWD_XMM_to_XMM(t0reg, t1reg); + // 4-7 + SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, t1reg); + SSEX_MOVDQA_XMM_to_XMM(t1reg, t0reg); + + // 0,1,4,5, L->H + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + // 2,3,6,7, L->H + SSE2_PUNPCKHQDQ_XMM_to_XMM(t1reg, EEREC_D); + + SSE2_PADDD_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PADDD_XMM_to_XMM(EEREC_HI, t1reg); + + if( _Rd_ ) { + // 0,2,4,6, L->H + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_HI, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + } + + _freeXMMreg(t0reg); + _freeXMMreg(t1reg); + +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if(_Rt_ && _Rs_){ + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[0]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[0]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.LO.UL[0], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[1]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[1]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.LO.UL[1], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[2]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[2]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.HI.UL[0], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[3]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[3]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.HI.UL[1], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[4]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[4]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.LO.UL[2], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[5]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[5]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.LO.UL[3], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[6]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[6]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.HI.UL[2], EAX); + + MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[7]); + MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[7]); + IMUL32RtoR( EAX, ECX); + ADD32RtoM( (uptr)&cpuRegs.HI.UL[3], EAX); + + } + + if (_Rd_) { + MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[0]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[2]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); + MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[2]); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); + } +} + +#endif +/********************************************************* +* MMI3 opcodes * +* * +*********************************************************/ +#ifndef MMI3_RECOMPILE + +REC_FUNC( PMADDUW, _Rd_); +REC_FUNC( PSRAVW, _Rd_); +REC_FUNC( PMTHI, _Rd_); +REC_FUNC( PMTLO, _Rd_); +REC_FUNC( PINTEH, _Rd_); +REC_FUNC( PMULTUW, _Rd_); +REC_FUNC( PDIVUW, _Rd_); +REC_FUNC( PCPYUD, _Rd_); +REC_FUNC( POR, _Rd_); +REC_FUNC( PNOR, _Rd_); +REC_FUNC( PCPYH, _Rd_); +REC_FUNC( PEXCW, _Rd_); +REC_FUNC( PEXCH, _Rd_); + +#else + +//////////////////////////////////////////////////// +REC_FUNC( PSRAVW, _Rd_ ); + +//////////////////////////////////////////////////// +PCSX2_ALIGNED16(u32 s_tempPINTEH[4]) = {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; + +void recPINTEH() +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + + int t0reg = -1; + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + if( EEREC_D != EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PAND_M128_to_XMM(EEREC_D, (u32)s_tempPINTEH); + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D != EEREC_S ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_S, 0xa0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xa0); + } + else if( EEREC_D == EEREC_T ) { + assert( EEREC_D != EEREC_S ); + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D != EEREC_S) SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_T); + SSE2_PSLLD_I8_to_XMM(t0reg, 16); + SSE2_PSLLD_I8_to_XMM(EEREC_D, 16); + SSE2_PSRLD_I8_to_XMM(t0reg, 16); + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); + } + } + + if( t0reg >= 0 ) _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PINTEH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMULTUW() +{ + SysPrintf("PMULTUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + REC_FUNC_INLINE( PMULTUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPMADDUW() +{ + SysPrintf("PMADDUW email zero if abnormal behavior\n"); +CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( EEREC_D == EEREC_S ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PMULUDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + + // add from LO/HI + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_HI, EEREC_HI, 0x88); + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, EEREC_HI); + SSE2_PADDQ_XMM_to_XMM(EEREC_D, EEREC_LO); + + // get the signs + SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSRAD_I8_to_XMM(t0reg, 31); + + // interleave + SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_D, 0xd8); + SSE2_PSHUFD_XMM_to_XMM(t0reg, t0reg, 0xd8); + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_LO); + + SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_LO, t0reg); + SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); + + _freeXMMreg(t0reg); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PMADDUW, _Rd_ ); +} + +//////////////////////////////////////////////////// +//do EEINST_SETSIGNEXT +REC_FUNC( PDIVUW, _Rd_ ); + +//////////////////////////////////////////////////// +void recPEXCW() +{ + if (!_Rd_) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCW, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPEXCH( void ) +{ + if (!_Rd_) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); +CPU_SSE_XMMCACHE_END + + REC_FUNC_INLINE( PEXCH, _Rd_ ); +} + +//////////////////////////////////////////////////// +void recPNOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + } + else { + if( EEREC_D == EEREC_T ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + if( _Rt_ != 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + else if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg); + SSEX_PXOR_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); + } + else { + SSE2_PCMPEQD_XMM_to_XMM( EEREC_D, EEREC_D ); + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + + if( EEREC_D == EEREC_S ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + if( EEREC_S != EEREC_T ) SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + + SSE2_PCMPEQD_XMM_to_XMM( t0reg, t0reg ); + SSEX_PXOR_XMM_to_XMM( EEREC_D, t0reg ); + _freeXMMreg(t0reg); + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP3( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + PORMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + PCMPEQDRtoR( t2reg, t2reg ); + PXORRtoR( t0reg, t2reg ); + PXORRtoR( t1reg, t2reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTHI( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITEHI) + SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_HI, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.HI.UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.HI.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPMTLO( void ) +{ +CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITELO) + SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(XMMGPR_LO, 0); + _deleteGPRtoXMMreg(_Rs_, 1); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.LO.UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.LO.UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYUD( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START(XMMINFO_READS|((cpucaps.hasStreamingSIMD2Extensions&&_Rs_==0)?0:XMMINFO_READT)|XMMINFO_WRITED) + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + } + else { + if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + //TODO + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + } + else { + if( EEREC_D == EEREC_S ) { + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_T, 0xee); + } + else if( EEREC_D == EEREC_T ) { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPOR( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + + if( _Rs_ == 0 ) { + if( _Rt_ == 0 ) { + SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); + } + else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( _Rt_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D == EEREC_S ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( _Rs_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + else if( _Rt_ == 0 ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + if( EEREC_S != EEREC_T ) { + SSEX_POR_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + } +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + MMX_ALLOC_TEMP2( + MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); + if ( _Rt_ != 0 ) + { + PORMtoR ( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PORMtoR ( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + } + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); + MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); + SetMMXstate(); + ) +} + +//////////////////////////////////////////////////// +void recPCPYH( void ) +{ + if ( ! _Rd_ ) return; + +CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0); + SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0); +CPU_SSE_XMMCACHE_END + + _flushCachedRegs(); + _deleteEEreg(_Rd_, 0); + + //PUSH32R( EBX ); + MOVZX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + MOV32RtoR( ECX, EAX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EAX, ECX ); + MOVZX32M16toR( EDX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); + MOV32RtoR( ECX, EDX ); + SHL32ItoR( ECX, 16 ); + OR32RtoR( EDX, ECX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], EDX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EDX ); + //POP32R( EBX ); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iMMI.h b/pcsx2/x86/iMMI.h new file mode 100644 index 0000000..c69b6bc --- /dev/null +++ b/pcsx2/x86/iMMI.h @@ -0,0 +1,133 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/********************************************************* +* MMI opcodes * +* * +*********************************************************/ +#ifndef __IMMI_H__ +#define __IMMI_H__ + +void recMADD(); +void recMADDU(); +void recPLZCW(); +void recMMI0(); +void recMMI1(); +void recMMI2(); +void recMMI3(); +void recMADD1(); +void recMADDU1(); +void recPMFHL(); +void recPMTHL(); +void recPMAXW(); +void recPMINW(); +void recPPACW(); +void recPEXTLH(); +void recPPACH(); +void recPEXTLB(); +void recPPACB(); +void recPEXT5(); +void recPPAC5(); +void recPABSW(); +void recPADSBH(); +void recPABSH(); +void recPADDUW(); +void recPSUBUW(); +void recPSUBUH(); +void recPEXTUH(); +void recPSUBUB(); +void recPEXTUB(); +void recQFSRV(); +void recPMADDW(); +void recPSLLVW(); +void recPSRLVW(); +void recPMSUBW(); +void recPINTH(); +void recPMULTW(); +void recPDIVW(); +void recPMADDH(); +void recPHMADH(); +void recPMSUBH(); +void recPHMSBH(); +void recPEXEH(); +void recPREVH(); +void recPMULTH(); +void recPDIVBW(); +void recPEXEW(); +void recPROT3W(); +void recPMADDUW(); +void recPSRAVW(); +void recPINTEH(); +void recPMULTUW(); +void recPDIVUW(); +void recPEXCH(); +void recPEXCW(); + +void recPSRLH(); +void recPSRLW(); +void recPSRAH(); +void recPSRAW(); +void recPSLLH(); +void recPSLLW(); +void recMTHI1(); +void recMTLO1(); +void recMFHI1(); +void recMFLO1(); +void recMULT1(); +void recMULTU1(); +void recDIV1(); +void recDIVU1(); +void recPMAXH(); +void recPCGTB(); +void recPCGTH(); +void recPCGTW(); +void recPADDSB(); +void recPADDSH(); +void recPADDSW(); +void recPSUBSB(); +void recPSUBSH(); +void recPSUBSW(); +void recPADDB(); +void recPADDH(); +void recPADDW(); +void recPSUBB(); +void recPSUBH(); +void recPSUBW(); +void recPEXTLW(); +void recPEXTUW(); +void recPMINH(); +void recPCEQB(); +void recPCEQH(); +void recPCEQW(); +void recPADDUB(); +void recPADDUH(); +void recPMFHI(); +void recPMFLO(); +void recPAND(); +void recPXOR(); +void recPCPYLD(); +void recPNOR(); +void recPMTHI(); +void recPMTLO(); +void recPCPYUD(); +void recPOR(); +void recPCPYH(); + +#endif + + diff --git a/pcsx2/x86/iPsxHw.c b/pcsx2/x86/iPsxHw.c new file mode 100644 index 0000000..ed1f546 --- /dev/null +++ b/pcsx2/x86/iPsxHw.c @@ -0,0 +1,1163 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include + +#include "PsxCommon.h" +#include "iR5900.h" + +extern int g_pbufi; +extern s8 g_pbuf[1024]; + +#define CONSTREAD8_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((uptr)name); \ + if( sign ) MOVSX32R8toR(EAX, EAX); \ + else MOVZX32R8toR(EAX, EAX); \ +} \ + +static u32 s_16 = 0x10; + +int psxHwConstRead8(u32 x86reg, u32 add, u32 sign) { + + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD8_CALL(USBread8); + // since calling from different dll, esp already changed + return 1; + } + + switch (add) { + case 0x1f801040: + CONSTREAD8_CALL(sioRead8); + return 1; + // case 0x1f801050: hard = serial_read8(); break;//for use of serial port ignore for now + +#ifdef PCSX2_DEVBUILD + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter read %x\n", add); + _eeReadConstMem8(x86reg, (uptr)&psxH[(add) & 0xffff], sign); + return 0; +#endif + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD8_CALL(DEV9read8); + return 1; + + case 0x1f801800: CONSTREAD8_CALL(cdrRead0); return 1; + case 0x1f801801: CONSTREAD8_CALL(cdrRead1); return 1; + case 0x1f801802: CONSTREAD8_CALL(cdrRead2); return 1; + case 0x1f801803: CONSTREAD8_CALL(cdrRead3); return 1; + + case 0x1f803100: // PS/EE/IOP conf related + if( IS_XMMREG(x86reg) ) SSEX_MOVD_M32_to_XMM(x86reg&0xf, (uptr)&s_16); + MMXONLY(else if( IS_MMXREG(x86reg) ) MOVDMtoMMX(x86reg&0xf, (uptr)&s_16);) + else MOV32ItoR(x86reg, 0x10); + return 0; + + case 0x1F808264: //sio2 serial data feed/fifo_out + CONSTREAD8_CALL(sio2_fifoOut); + return 1; + + default: + _eeReadConstMem8(x86reg, (uptr)&psxH[(add) & 0xffff], sign); + return 0; + } +} + +#define CONSTREAD16_CALL(name) { \ + iFlushCall(0); \ + CALLFunc((uptr)name); \ + if( sign ) MOVSX32R16toR(EAX, EAX); \ + else MOVZX32R16toR(EAX, EAX); \ +} \ + +void psxConstReadCounterMode16(int x86reg, int index, int sign) +{ + if( IS_MMXREG(x86reg) ) { + X86_64ASSERT(); + MMXONLY(MOV16MtoR(ECX, (uptr)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (uptr)&psxCounters[index].mode - 2);) + } + else { + if( sign ) MOVSX32M16toR(ECX, (uptr)&psxCounters[index].mode); + else MOVZX32M16toR(ECX, (uptr)&psxCounters[index].mode); + + MOV32RtoR(x86reg, ECX); + } + + //AND16ItoR(ECX, ~0x1800); + //OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +int psxHwConstRead16(u32 x86reg, u32 add, u32 sign) { + if (add >= 0x1f801600 && add < 0x1f801700) { + PUSH32I(add); + CONSTREAD16_CALL(USBread16); + return 1; + } + + switch (add) { + + case 0x1f801040: + iFlushCall(0); + CALLFunc((uptr)sioRead8); + PUSHR(EAX); + CALLFunc((uptr)sioRead8); + POPR(ECX); + AND32ItoR(ECX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoR(EAX, ECX); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + return 1; + + case 0x1f801044: + _eeReadConstMem16(x86reg, (uptr)&sio.StatReg, sign); + return 0; + + case 0x1f801048: + _eeReadConstMem16(x86reg, (uptr)&sio.ModeReg, sign); + return 0; + + case 0x1f80104a: + _eeReadConstMem16(x86reg, (uptr)&sio.CtrlReg, sign); + return 0; + + case 0x1f80104e: + _eeReadConstMem16(x86reg, (uptr)&sio.BaudReg, sign); + return 0; + + // counters[0] + case 0x1f801100: + PUSH32I(0); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode16(x86reg, 0, sign); + return 0; + + case 0x1f801108: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[0].target, sign); + return 0; + + // counters[1] + case 0x1f801110: + PUSH32I(1); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode16(x86reg, 1, sign); + return 0; + + case 0x1f801118: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[1].target, sign); + return 0; + + // counters[2] + case 0x1f801120: + PUSH32I(2); + CONSTREAD16_CALL(psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode16(x86reg, 2, sign); + return 0; + + case 0x1f801128: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[2].target, sign); + return 0; + + case 0x1f80146e: // DEV9_R_REV + PUSH32I(add); + CONSTREAD16_CALL(DEV9read16); + return 1; + + // counters[3] + case 0x1f801480: + PUSH32I(3); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode16(x86reg, 3, sign); + return 0; + + case 0x1f801488: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[3].target, sign); + return 0; + + // counters[4] + case 0x1f801490: + PUSH32I(4); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode16(x86reg, 4, sign); + return 0; + + case 0x1f801498: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[4].target, sign); + return 0; + + // counters[5] + case 0x1f8014a0: + PUSH32I(5); + CONSTREAD16_CALL(psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode16(x86reg, 5, sign); + return 0; + + case 0x1f8014a8: + _eeReadConstMem16(x86reg, (uptr)&psxCounters[5].target, sign); + return 0; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + + PUSH32I(add); + CONSTREAD16_CALL(SPU2read); + return 1; + } else { + _eeReadConstMem16(x86reg, (uptr)&psxH[(add) & 0xffff], sign); + return 0; + } + } +} + +void psxConstReadCounterMode32(int x86reg, int index) +{ + if( IS_MMXREG(x86reg) ) { + X86_64ASSERT(); + MMXONLY(MOV16MtoR(ECX, (uptr)&psxCounters[index].mode); + MOVDMtoMMX(x86reg&0xf, (uptr)&psxCounters[index].mode);) + } + else { + MOVZX32M16toR(ECX, (uptr)&psxCounters[index].mode); + MOV32RtoR(x86reg, ECX); + } + + //AND16ItoR(ECX, ~0x1800); + //OR16ItoR(ECX, 0x400); + MOV16RtoM(psxCounters[index].mode, ECX); +} + +static u32 s_tempsio; +int psxHwConstRead32(u32 x86reg, u32 add) { + if (add >= 0x1f801600 && add < 0x1f801700) { + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)USBread32); + return 1; + } + if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)FWread32); + return 1; + } + + switch (add) { + case 0x1f801040: + iFlushCall(0); + CALLFunc((uptr)sioRead8); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&s_tempsio, EAX); + CALLFunc((uptr)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 8); + OR32RtoM((uptr)&s_tempsio, EAX); + + // 3rd + CALLFunc((uptr)sioRead8); + AND32ItoR(EAX, 0xff); + SHL32ItoR(EAX, 16); + OR32RtoM((uptr)&s_tempsio, EAX); + + // 4th + CALLFunc((uptr)sioRead8); + SHL32ItoR(EAX, 24); + OR32MtoR(EAX, (uptr)&s_tempsio); + return 1; + + //case 0x1f801050: hard = serial_read32(); break;//serial port + case 0x1f801078: +#ifdef PSXHW_LOG + PSXHW_LOG("ICTRL 32bit read %x\n", psxHu32(0x1078)); +#endif + _eeReadConstMem32(x86reg, (uptr)&psxH[add&0xffff]); + MOV32ItoM((uptr)&psxH[add&0xffff], 0); + return 0; + + // counters[0] + case 0x1f801100: + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801104: + psxConstReadCounterMode32(x86reg, 0); + return 0; + + case 0x1f801108: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[0].target); + return 0; + + // counters[1] + case 0x1f801110: + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801114: + psxConstReadCounterMode32(x86reg, 1); + return 0; + + case 0x1f801118: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[1].target); + return 0; + + // counters[2] + case 0x1f801120: + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)psxRcntRcount16); + ADD32ItoR(ESP, 4); + return 1; + case 0x1f801124: + psxConstReadCounterMode32(x86reg, 2); + return 0; + + case 0x1f801128: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[2].target); + return 0; + + // counters[3] + case 0x1f801480: + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801484: + psxConstReadCounterMode32(x86reg, 3); + return 0; + + case 0x1f801488: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[3].target); + return 0; + + // counters[4] + case 0x1f801490: + iFlushCall(0); + PUSH32I(4); + CALLFunc((uptr)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f801494: + psxConstReadCounterMode32(x86reg, 4); + return 0; + + case 0x1f801498: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[4].target); + return 0; + + // counters[5] + case 0x1f8014a0: + iFlushCall(0); + PUSH32I(5); + CALLFunc((uptr)psxRcntRcount32); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1f8014a4: + psxConstReadCounterMode32(x86reg, 5); + return 0; + + case 0x1f8014a8: + _eeReadConstMem32(x86reg, (uptr)&psxCounters[5].target); + return 0; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((uptr)sio2_getSend3); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F80825C: + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((uptr)sio2_getSend1); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F808258: + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((uptr)sio2_getSend2); + ADD32ItoR(ESP, 4); + return 1; + + case 0x1F808268: + iFlushCall(0); + CALLFunc((uptr)sio2_getCtrl); + return 1; + + case 0x1F80826C: + iFlushCall(0); + CALLFunc((uptr)sio2_getRecv1); + return 1; + + case 0x1F808270: + iFlushCall(0); + CALLFunc((uptr)sio2_getRecv2); + return 1; + + case 0x1F808274: + iFlushCall(0); + CALLFunc((uptr)sio2_getRecv3); + return 1; + + case 0x1F808278: + iFlushCall(0); + CALLFunc((uptr)sio2_get8278); + return 1; + + case 0x1F80827C: + iFlushCall(0); + CALLFunc((uptr)sio2_get827C); + return 1; + + case 0x1F808280: + iFlushCall(0); + CALLFunc((uptr)sio2_getIntr); + return 1; + + case 0x1F801C00: + iFlushCall(0); + CALLFunc((uptr)SPU2ReadMemAddr(0)); + return 1; + + case 0x1F801500: + iFlushCall(0); + CALLFunc((uptr)SPU2ReadMemAddr(1)); + return 1; + + default: + _eeReadConstMem32(x86reg, (uptr)&psxH[(add) & 0xffff]); + return 0; + } +} + +#define CONSTWRITE_CALL(name) { \ + _recPushReg(mmreg); \ + iFlushCall(0); \ + CALLFunc((uptr)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void Write8PrintBuffer(u8 value) +{ + if (value == '\r') return; + if (value == '\n' || g_pbufi >= 1023) { + g_pbuf[g_pbufi++] = 0; g_pbufi = 0; + SysPrintf("%s\n", g_pbuf); return; + } + g_pbuf[g_pbufi++] = value; +} + +void psxHwConstWrite8(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)USBwrite8); + return; + } + + switch (add) { + case 0x1f801040: + CONSTWRITE_CALL(sioWrite8); break; + //case 0x1f801050: serial_write8(value); break;//serial port + case 0x1f801100: + case 0x1f801104: + case 0x1f801108: + case 0x1f801110: + case 0x1f801114: + case 0x1f801118: + case 0x1f801120: + case 0x1f801124: + case 0x1f801128: + case 0x1f801480: + case 0x1f801484: + case 0x1f801488: + case 0x1f801490: + case 0x1f801494: + case 0x1f801498: + case 0x1f8014a0: + case 0x1f8014a4: + case 0x1f8014a8: + SysPrintf("8bit counter write %x\n", add); + _eeWriteConstMem8((uptr)&psxH[(add) & 0xffff], mmreg); + return; + case 0x1f801800: CONSTWRITE_CALL(cdrWrite0); break; + case 0x1f801801: CONSTWRITE_CALL(cdrWrite1); break; + case 0x1f801802: CONSTWRITE_CALL(cdrWrite2); break; + case 0x1f801803: CONSTWRITE_CALL(cdrWrite3); break; + case 0x1f80380c: CONSTWRITE_CALL(Write8PrintBuffer); break; + case 0x1F808260: CONSTWRITE_CALL(sio2_fifoIn); break; + + default: + _eeWriteConstMem8((uptr)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +void psxHwConstWrite16(u32 add, int mmreg) { + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)USBwrite16); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 3); + return; + case 0x1f801044: + return; + case 0x1f801048: + _eeWriteConstMem16((uptr)&sio.ModeReg, mmreg); + return; + case 0x1f80104a: // control register + CONSTWRITE_CALL(sioWriteCtrl16); + return; + case 0x1f80104e: // baudrate register + _eeWriteConstMem16((uptr)&sio.BaudReg, mmreg); + return; + + case 0x1f801070: + _eeWriteConstMem16OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); + return; + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + default: + if (add>=0x1f801c00 && add<0x1f801e00) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)SPU2write); + // leave esp alone + return; + } + + _eeWriteConstMem16((uptr)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +#define recDmaExec(n) { \ + iFlushCall(0); \ + if( n > 6 ) \ + TEST32ItoM((uptr)&HW_DMA_PCR2, 8 << ((n-7) * 4)); \ + else \ + TEST32ItoM((uptr)&HW_DMA_PCR, 8 << (n * 4)); \ + j8Ptr[5] = JZ8(0); \ + MOV32MtoR(EAX, (uptr)&HW_DMA##n##_CHCR); \ + TEST32ItoR(EAX, 0x01000000); \ + j8Ptr[6] = JZ8(0); \ + \ + _callFunctionArg3((uptr)psxDma##n, MEM_CONSTTAG, MEM_CONSTTAG, MEM_X86TAG, (uptr)&HW_DMA##n##_MADR, (uptr)&HW_DMA##n##_BCR, EAX); \ + \ + x86SetJ8( j8Ptr[5] ); \ + x86SetJ8( j8Ptr[6] ); \ +} \ + +#define CONSTWRITE_CALL32(name) { \ + iFlushCall(0); \ + _recPushReg(mmreg); \ + CALLFunc((uptr)name); \ + ADD32ItoR(ESP, 4); \ +} \ + +void psxHwConstWrite32(u32 add, int mmreg) +{ + if (add >= 0x1f801600 && add < 0x1f801700) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)USBwrite32); + return; + } + if (add >= 0x1f808400 && add <= 0x1f808550) { + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(add); + CALLFunc((uptr)FWwrite32); + return; + } + + switch (add) { + case 0x1f801040: + _recPushReg(mmreg); + iFlushCall(0); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 1); + CALLFunc((uptr)sioWrite8); + ADD32ItoR(ESP, 1); + return; + + case 0x1f801070: + _eeWriteConstMem32OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); // and + return; + +// case 0x1f801088: +// HW_DMA0_CHCR = value; // DMA0 chcr (MDEC in DMA) +//// DmaExec(0); +// return; + +// case 0x1f801098: +// HW_DMA1_CHCR = value; // DMA1 chcr (MDEC out DMA) +//// DmaExec(1); +// return; + + case 0x1f8010a8: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(2); + return; + + case 0x1f8010b8: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(3); + return; + + case 0x1f8010c8: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(4); + return; + + case 0x1f8010e8: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(6); + return; + + case 0x1f801508: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(7); + return; + + case 0x1f801518: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(8); + return; + + case 0x1f801528: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(9); + return; + + case 0x1f801538: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(10); + return; + + case 0x1f801548: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(11); + return; + + case 0x1f801558: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + recDmaExec(12); + return; + + case 0x1f8010f4: + case 0x1f801574: + { + // u32 tmp = (~value) & HW_DMA_ICR; + _eeMoveMMREGtoR(EAX, mmreg); + MOV32RtoR(ECX, EAX); + NOT32R(ECX); + AND32MtoR(ECX, (uptr)&psxH[(add) & 0xffff]); + + // HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp; + XOR32RtoR(EAX, ECX); + AND32ItoR(EAX, 0xffffff); + XOR32RtoR(EAX, ECX); + MOV32RtoM((uptr)&psxH[(add) & 0xffff], EAX); + return; + } + + // counters[0] + case 0x1f801100: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + case 0x1f801104: + CONSTWRITE_CALL32(psxRcnt0Wmode); + return; + case 0x1f801108: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[1] + case 0x1f801110: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801114: + CONSTWRITE_CALL32(psxRcnt1Wmode); + return; + + case 0x1f801118: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[2] + case 0x1f801120: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)psxRcntWcount16); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801124: + CONSTWRITE_CALL32(psxRcnt2Wmode); + return; + + case 0x1f801128: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(2); + CALLFunc((uptr)psxRcntWtarget16); + ADD32ItoR(ESP, 8); + return; + + // counters[3] + case 0x1f801480: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801484: + CONSTWRITE_CALL32(psxRcnt3Wmode); + return; + + case 0x1f801488: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(3); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[4] + case 0x1f801490: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f801494: + CONSTWRITE_CALL32(psxRcnt4Wmode); + return; + + case 0x1f801498: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(4); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + // counters[5] + case 0x1f8014a0: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((uptr)psxRcntWcount32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014a4: + CONSTWRITE_CALL32(psxRcnt5Wmode); + return; + + case 0x1f8014a8: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(5); + CALLFunc((uptr)psxRcntWtarget32); + ADD32ItoR(ESP, 8); + return; + + case 0x1f8014c0: + SysPrintf("RTC_HOLDMODE 32bit write\n"); + break; + + case 0x1F808200: + case 0x1F808204: + case 0x1F808208: + case 0x1F80820C: + case 0x1F808210: + case 0x1F808214: + case 0x1F808218: + case 0x1F80821C: + case 0x1F808220: + case 0x1F808224: + case 0x1F808228: + case 0x1F80822C: + case 0x1F808230: + case 0x1F808234: + case 0x1F808238: + case 0x1F80823C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808200)/4); + CALLFunc((uptr)sio2_setSend3); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808240: + case 0x1F808248: + case 0x1F808250: + case 0x1F808258: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808240)/8); + CALLFunc((uptr)sio2_setSend1); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808244: + case 0x1F80824C: + case 0x1F808254: + case 0x1F80825C: + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I((add-0x1F808244)/8); + CALLFunc((uptr)sio2_setSend2); + ADD32ItoR(ESP, 8); + return; + + case 0x1F808268: CONSTWRITE_CALL32(sio2_setCtrl); return; + case 0x1F808278: CONSTWRITE_CALL32(sio2_set8278); return; + case 0x1F80827C: CONSTWRITE_CALL32(sio2_set827C); return; + case 0x1F808280: CONSTWRITE_CALL32(sio2_setIntr); return; + + case 0x1F8010C0: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(0); + CALLFunc((uptr)SPU2WriteMemAddr); + return; + + case 0x1F801500: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + _recPushReg(mmreg); + iFlushCall(0); + PUSH32I(1); + CALLFunc((uptr)SPU2WriteMemAddr); + return; + default: + _eeWriteConstMem32((uptr)&psxH[(add) & 0xffff], mmreg); + return; + } +} + +int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) { + switch (add) { + case 0x1f402004: CONSTREAD8_CALL((u32)cdvdRead04); return 1; + case 0x1f402005: CONSTREAD8_CALL((u32)cdvdRead05); return 1; + case 0x1f402006: CONSTREAD8_CALL((u32)cdvdRead06); return 1; + case 0x1f402007: CONSTREAD8_CALL((u32)cdvdRead07); return 1; + case 0x1f402008: CONSTREAD8_CALL((u32)cdvdRead08); return 1; + case 0x1f40200A: CONSTREAD8_CALL((u32)cdvdRead0A); return 1; + case 0x1f40200B: CONSTREAD8_CALL((u32)cdvdRead0B); return 1; + case 0x1f40200C: CONSTREAD8_CALL((u32)cdvdRead0C); return 1; + case 0x1f40200D: CONSTREAD8_CALL((u32)cdvdRead0D); return 1; + case 0x1f40200E: CONSTREAD8_CALL((u32)cdvdRead0E); return 1; + case 0x1f40200F: CONSTREAD8_CALL((u32)cdvdRead0F); return 1; + case 0x1f402013: CONSTREAD8_CALL((u32)cdvdRead13); return 1; + case 0x1f402015: CONSTREAD8_CALL((u32)cdvdRead15); return 1; + case 0x1f402016: CONSTREAD8_CALL((u32)cdvdRead16); return 1; + case 0x1f402017: CONSTREAD8_CALL((u32)cdvdRead17); return 1; + case 0x1f402018: CONSTREAD8_CALL((u32)cdvdRead18); return 1; + case 0x1f402020: CONSTREAD8_CALL((u32)cdvdRead20); return 1; + case 0x1f402021: CONSTREAD8_CALL((u32)cdvdRead21); return 1; + case 0x1f402022: CONSTREAD8_CALL((u32)cdvdRead22); return 1; + case 0x1f402023: CONSTREAD8_CALL((u32)cdvdRead23); return 1; + case 0x1f402024: CONSTREAD8_CALL((u32)cdvdRead24); return 1; + case 0x1f402028: CONSTREAD8_CALL((u32)cdvdRead28); return 1; + case 0x1f402029: CONSTREAD8_CALL((u32)cdvdRead29); return 1; + case 0x1f40202A: CONSTREAD8_CALL((u32)cdvdRead2A); return 1; + case 0x1f40202B: CONSTREAD8_CALL((u32)cdvdRead2B); return 1; + case 0x1f40202C: CONSTREAD8_CALL((u32)cdvdRead2C); return 1; + case 0x1f402030: CONSTREAD8_CALL((u32)cdvdRead30); return 1; + case 0x1f402031: CONSTREAD8_CALL((u32)cdvdRead31); return 1; + case 0x1f402032: CONSTREAD8_CALL((u32)cdvdRead32); return 1; + case 0x1f402033: CONSTREAD8_CALL((u32)cdvdRead33); return 1; + case 0x1f402034: CONSTREAD8_CALL((u32)cdvdRead34); return 1; + case 0x1f402038: CONSTREAD8_CALL((u32)cdvdRead38); return 1; + case 0x1f402039: CONSTREAD8_CALL((u32)cdvdRead39); return 1; + case 0x1f40203A: CONSTREAD8_CALL((u32)cdvdRead3A); return 1; + default: + SysPrintf("*Unkwnown 8bit read at address %lx\n", add); + XOR32RtoR(x86reg, x86reg); + return 0; + } +} + +void psxHw4ConstWrite8(u32 add, int mmreg) { + switch (add) { + case 0x1f402004: CONSTWRITE_CALL(cdvdWrite04); return; + case 0x1f402005: CONSTWRITE_CALL(cdvdWrite05); return; + case 0x1f402006: CONSTWRITE_CALL(cdvdWrite06); return; + case 0x1f402007: CONSTWRITE_CALL(cdvdWrite07); return; + case 0x1f402008: CONSTWRITE_CALL(cdvdWrite08); return; + case 0x1f40200A: CONSTWRITE_CALL(cdvdWrite0A); return; + case 0x1f40200F: CONSTWRITE_CALL(cdvdWrite0F); return; + case 0x1f402014: CONSTWRITE_CALL(cdvdWrite14); return; + case 0x1f402016: + MMXONLY(_freeMMXregs();) + CONSTWRITE_CALL(cdvdWrite16); + return; + case 0x1f402017: CONSTWRITE_CALL(cdvdWrite17); return; + case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return; + case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return; + default: + SysPrintf("*Unknown 8bit write at address %lx\n", add); + return; + } +} + +#endif // PCSX2_NORECBUILD + diff --git a/pcsx2/x86/iPsxMem.c b/pcsx2/x86/iPsxMem.c new file mode 100644 index 0000000..ec3e1b2 --- /dev/null +++ b/pcsx2/x86/iPsxMem.c @@ -0,0 +1,869 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "PsxCommon.h" +#include "VU.h" +#include "iCore.h" +#include "iR3000A.h" + +extern u32 g_psxMaxRecMem; +extern int g_psxWriteOk; +static u32 writectrl; + +#ifdef PCSX2_VIRTUAL_MEM + +#ifdef _DEBUG + +#define ASSERT_WRITEOK \ +{ \ + __asm cmp g_psxWriteOk, 1 \ + __asm je WriteOk \ + __asm int 10 \ +} \ +WriteOk: \ + +#else +#define ASSERT_WRITEOK +#endif + +__declspec(naked) void psxRecMemRead8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f40 + je hw4read + cmp dx, 0x1000 + je devread + cmp dx, 0x1f00 + je spuread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead8 + add esp, 4 + ret + +hw4read: + push ecx + call psxHw4Read8 + add esp, 4 + ret + +devread: + push ecx + call DEV9read8 + // stack already incremented + ret + +spuread: + push ecx + call SPU2read + // stack already incremented + ret + } +} + +int psxRecMemConstRead8(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + return psxHwConstRead8(x86reg, mem&0x1fffffff, sign); + +#ifdef _DEBUG + case 0x1d00: assert(0); +#endif + + case 0x1f40: + return psxHw4ConstRead8(x86reg, mem&0x1fffffff, sign); + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9read8); + if( sign ) MOVSX32R8toR(x86reg, EAX); + else MOVZX32R8toR(x86reg, EAX); + return 0; + + default: + _eeReadConstMem8(x86reg, (u32)PSXM(mem), sign); + return 0; + } +} + +__declspec(naked) void psxRecMemRead16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1f90 + je spuread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead16 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 2 + jmp End +Sif60: + xor eax, eax + jmp End + +spuread: + push ecx + call SPU2read + // stack already incremented + +End: + ret + +devread: + push ecx + call DEV9read16 + // stack already incremented + ret + } +} + +int psxRecMemConstRead16(u32 x86reg, u32 mem, u32 sign) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead16(x86reg, mem&0x1fffffff, sign); + + case 0x1d00: + + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xF240, sign); + OR32ItoR(x86reg, 0x0002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem16(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0), sign); + break; + } + return 0; + + case 0x1f90: + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)SPU2read); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9read16); + if( sign ) MOVSX32R16toR(x86reg, EAX); + else MOVZX32R16toR(x86reg, EAX); + return 0; + + default: + assert( g_psxWriteOk ); + _eeReadConstMem16(x86reg, (u32)PSXM(mem), sign); + return 0; + } + + return 0; +} + +__declspec(naked) void psxRecMemRead32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwread + cmp dx, 0x1d00 + je sifread + cmp dx, 0x1000 + je devread + cmp ecx, 0x1ffe0130 + je WriteCtrlRead + } + + ASSERT_WRITEOK + + __asm { +memread: + // rom reads, has to be PS2MEM_BASE_ + mov eax, dword ptr [ecx+PS2MEM_BASE_] + ret + +hwread: + cmp cx, 0x1000 + jb memread + + push ecx + call psxHwRead32 + add esp, 4 + ret + +sifread: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + + // do the read from ps2 mem + mov eax, dword ptr [edx+PS2MEM_BASE_+0x1000f200] + + cmp dl, 0x40 + jne End + + // 0x40 + or eax, 0xf0000002 + jmp End +Sif60: + xor eax, eax +End: + ret + +devread: + push ecx + call DEV9read32 + // stack already incremented + ret + +WriteCtrlRead: + mov eax, writectrl + ret + } +} + +int psxRecMemConstRead32(u32 x86reg, u32 mem) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: return psxHwConstRead32(x86reg, mem&0x1fffffff); + + case 0x1d00: + switch(mem & 0xF0) + { + case 0x40: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xF240); + OR32ItoR(x86reg, 0xf0000002); + break; + case 0x60: + XOR32RtoR(x86reg, x86reg); + break; + default: + _eeReadConstMem32(x86reg, (u32)PS2MEM_HW+0xf200+(mem&0xf0)); + break; + } + return 0; + + case 0x1000: + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9read32); + return 1; + + default: + if( mem == 0xfffe0130 ) + MOV32MtoR(x86reg, (uptr)&writectrl); + else { + XOR32RtoR(x86reg, x86reg); + CMP32ItoM((uptr)&g_psxWriteOk, 0); + CMOVNE32MtoR(x86reg, (u32)PSXM(mem)); + } + + return 0; + } +} + +__declspec(naked) void psxRecMemWrite8() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f40 + je hw4write + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov byte ptr [ecx+PS2MEM_BASE_], al + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite8 + add esp, 8 + ret + +hw4write: + push eax + push ecx + call psxHw4Write8 + add esp, 8 + ret + +devwrite: + push eax + push ecx + call DEV9write8 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite8(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + + switch(t) { + case 0x1f80: + psxHwConstWrite8(mem&0x1fffffff, mmreg); + return 0; + case 0x1f40: + psxHw4ConstWrite8(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + assert(0); + _eeWriteConstMem8((u32)(PS2MEM_HW+0xf200+(mem&0xff)), mmreg); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9write8); + return 0; + + default: + _eeWriteConstMem8((u32)PSXM(mem), mmreg); + return 1; + } +} + +__declspec(naked) void psxRecMemWrite16() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1f90 + je spuwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + } + + ASSERT_WRITEOK + + __asm { +memwrite: + // rom writes, has to be PS2MEM_BASE_ + mov word ptr [ecx+PS2MEM_BASE_], ax + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite16 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], ax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif60: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +spuwrite: + push eax + push ecx + call SPU2write + // stack alwritey incremented + ret + +devwrite: + push eax + push ecx + call DEV9write16 + // stack alwritey incremented + ret + } +} + +int psxRecMemConstWrite16(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite16(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem16((u32)(PS2MEM_HW+0xf210), mmreg); + return 0; + case 0x40: + { + // delete x86reg + _eeMoveMMREGtoR(EAX, mmreg); + + assert( mmreg != EBX ); + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1f90: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)SPU2write); + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9write16); + return 0; + + default: + _eeWriteConstMem16((u32)PSXM(mem), mmreg); + return 1; + } +} + +__declspec(naked) void psxRecMemWrite32() +{ + __asm { + mov edx, ecx + shr edx, 16 + cmp dx, 0x1f80 + je hwwrite + cmp dx, 0x1d00 + je sifwrite + cmp dx, 0x1000 + je devwrite + cmp dx, 0x1ffe + je WriteCtrl + } + + __asm { + // rom writes, has to be PS2MEM_BASE_ + test g_psxWriteOk, 1 + jz endwrite + +memwrite: + mov dword ptr [ecx+PS2MEM_BASE_], eax +endwrite: + ret + +hwwrite: + cmp cx, 0x1000 + jb memwrite + + push eax + push ecx + call psxHwWrite32 + add esp, 8 + ret + +sifwrite: + mov edx, ecx + and edx, 0xf0 + cmp dl, 0x60 + je Sif60 + cmp dl, 0x40 + je Sif40 + cmp dl, 0x30 + je Sif30 + cmp dl, 0x20 + je Sif20 + + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret + +Sif40: + mov bx, word ptr [edx+PS2MEM_BASE_+0x1000f200] + test ax, 0xa0 + jz Sif40_2 + // psHu16(0x1000F240) &= ~0xF000; + // psHu16(0x1000F240) |= 0x2000; + and bx, 0x0fff + or bx, 0x2000 + +Sif40_2: + // if(psHu16(0x1000F240) & temp) psHu16(0x1000F240) &= ~temp; + // else psHu16(0x1000F240) |= temp; + and ax, 0xf0 + test bx, ax + jz Sif40_3 + + not ax + and bx, ax + jmp Sif40_4 +Sif40_3: + or bx, ax +Sif40_4: + mov word ptr [edx+PS2MEM_BASE_+0x1000f200], bx + ret + +Sif30: + or dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif20: + not eax + and dword ptr [edx+PS2MEM_BASE_+0x1000f200], eax + ret +Sif60: + mov dword ptr [edx+PS2MEM_BASE_+0x1000f200], 0 + ret + +devwrite: + push eax + push ecx + call DEV9write32 + // stack alwritey incremented + ret + +WriteCtrl: + cmp ecx, 0x1ffe0130 + jne End + + mov writectrl, eax + + cmp eax, 0x800 + je SetWriteNotOk + cmp eax, 0x804 + je SetWriteNotOk + cmp eax, 0xc00 + je SetWriteNotOk + cmp eax, 0xc04 + je SetWriteNotOk + cmp eax, 0xcc0 + je SetWriteNotOk + cmp eax, 0xcc4 + je SetWriteNotOk + cmp eax, 0x0c4 + je SetWriteNotOk + + // test ok + cmp eax, 0x1e988 + je SetWriteOk + cmp eax, 0x1edd8 + je SetWriteOk + +End: + ret + +SetWriteNotOk: + mov g_psxWriteOk, 0 + ret +SetWriteOk: + mov g_psxWriteOk, 1 + ret + } +} + +int psxRecMemConstWrite32(u32 mem, int mmreg) +{ + u32 t = (mem >> 16) & 0x1fff; + switch(t) { + case 0x1f80: + psxHwConstWrite32(mem&0x1fffffff, mmreg); + return 0; + + case 0x1d00: + switch (mem & 0xf0) { + case 0x10: + // write to ps2 mem + _eeWriteConstMem32((u32)PS2MEM_HW+0xf210, mmreg); + return 0; + case 0x20: + // write to ps2 mem + // delete x86reg + if( IS_PSXCONSTREG(mmreg) ) { + AND32ItoM((u32)PS2MEM_HW+0xf220, ~g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else { + NOT32R(mmreg); + AND32RtoM((u32)PS2MEM_HW+0xf220, mmreg); + } + return 0; + case 0x30: + // write to ps2 mem + _eeWriteConstMem32OP((u32)PS2MEM_HW+0xf230, mmreg, 1); + return 0; + case 0x40: + { + // delete x86reg + assert( mmreg != EBX ); + + _eeMoveMMREGtoR(EAX, mmreg); + + MOV16MtoR(EBX, (u32)PS2MEM_HW+0xf240); + TEST16ItoR(EAX, 0xa0); + j8Ptr[0] = JZ8(0); + + AND16ItoR(EBX, 0x0fff); + OR16ItoR(EBX, 0x2000); + + x86SetJ8(j8Ptr[0]); + + AND16ItoR(EAX, 0xf0); + TEST16RtoR(EAX, 0xf0); + j8Ptr[0] = JZ8(0); + + NOT32R(EAX); + AND16RtoR(EBX, EAX); + j8Ptr[1] = JMP8(0); + + x86SetJ8(j8Ptr[0]); + OR16RtoR(EBX, EAX); + + x86SetJ8(j8Ptr[1]); + + MOV16RtoM((u32)PS2MEM_HW+0xf240, EBX); + + return 0; + } + case 0x60: + MOV32ItoM((u32)(PS2MEM_HW+0xf260), 0); + return 0; + default: + assert(0); + } + return 0; + + case 0x1000: + _recPushReg(mmreg); + PUSH32I(mem&0x1fffffff); + CALLFunc((uptr)DEV9write32); + return 0; + + case 0x1ffe: + if( mem == 0xfffe0130 ) { + u8* ptrs[9]; + + _eeWriteConstMem32((uptr)&writectrl, mmreg); + + if( IS_PSXCONSTREG(mmreg) ) { + switch (g_psxConstRegs[(mmreg>>16)&0x1f]) { + case 0x800: case 0x804: + case 0xc00: case 0xc04: + case 0xcc0: case 0xcc4: + case 0x0c4: + MOV32ItoM((uptr)&g_psxWriteOk, 0); + break; + case 0x1e988: + case 0x1edd8: + MOV32ItoM((uptr)&g_psxWriteOk, 1); + break; + default: + assert(0); + } + } + else { + // not ok + CMP32ItoR(mmreg, 0x800); + ptrs[0] = JE8(0); + CMP32ItoR(mmreg, 0x804); + ptrs[1] = JE8(0); + CMP32ItoR(mmreg, 0xc00); + ptrs[2] = JE8(0); + CMP32ItoR(mmreg, 0xc04); + ptrs[3] = JE8(0); + CMP32ItoR(mmreg, 0xcc0); + ptrs[4] = JE8(0); + CMP32ItoR(mmreg, 0xcc4); + ptrs[5] = JE8(0); + CMP32ItoR(mmreg, 0x0c4); + ptrs[6] = JE8(0); + + // ok + CMP32ItoR(mmreg, 0x1e988); + ptrs[7] = JE8(0); + CMP32ItoR(mmreg, 0x1edd8); + ptrs[8] = JE8(0); + + x86SetJ8(ptrs[0]); + x86SetJ8(ptrs[1]); + x86SetJ8(ptrs[2]); + x86SetJ8(ptrs[3]); + x86SetJ8(ptrs[4]); + x86SetJ8(ptrs[5]); + x86SetJ8(ptrs[6]); + MOV32ItoM((uptr)&g_psxWriteOk, 0); + ptrs[0] = JMP8(0); + + x86SetJ8(ptrs[7]); + x86SetJ8(ptrs[8]); + MOV32ItoM((uptr)&g_psxWriteOk, 1); + + x86SetJ8(ptrs[0]); + } + } + return 0; + + default: + TEST8ItoM((uptr)&g_psxWriteOk, 1); + j8Ptr[0] = JZ8(0); + _eeWriteConstMem32((u32)PSXM(mem), mmreg); + x86SetJ8(j8Ptr[0]); + return 1; + } +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp new file mode 100644 index 0000000..3515042 --- /dev/null +++ b/pcsx2/x86/iR3000A.cpp @@ -0,0 +1,1469 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking Jan06 +// and added reg caching, const propagation, block analysis Jun06 +// zerofrog(@gmail.com) +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#else +#include +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "zlib.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "iR3000A.h" +#include "PsxCounters.h" + +extern u32 psxNextCounter, psxNextsCounter; +u32 g_psxMaxRecMem = 0; +extern char *disRNameGPR[]; +extern char* disR3000Fasm(u32 code, u32 pc); + +void psxRecRecompile(u32 startpc); + +uptr *psxRecLUT; +} + + +#define PSX_NUMBLOCKS (1<<12) +#define MAPBASE 0x48000000 +#define RECMEM_SIZE (8*1024*1024) + +#define PSX_MEMMASK 0x5fffffff // mask when comparing two pcs + +// R3000A statics +int psxreclog = 0; + +static u32 s_BranchCount = 0; +static char *recMem; // the recompiled blocks will be here +static BASEBLOCK *recRAM; // and the ptr to the blocks here +static BASEBLOCK *recROM; // and here +static BASEBLOCK *recROM1; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr; +u32 psxpc; // recompiler psxpc +int psxbranch; // set for branch +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what psxpc the current block ends + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +static u32 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_psxBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch); +void psxRecompileNextInstruction(int delayslot); + +extern void (*rpsxBSC[64])(); +extern void (*rpsxBSC_co[64])(); +void rpsxpropBSC(EEINST* prev, EEINST* pinst); + +#ifdef _DEBUG +extern "C" { +u32 psxdump = 0; +} +#else +#define psxdump 0 +#endif + +#define PSX_GETBLOCK(x) PC_GETBLOCK_(x, psxRecLUT) + +#define PSXREC_CLEARM(mem) { \ + if ((mem) < g_psxMaxRecMem && psxRecLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PSX_GETBLOCK(mem); \ + if( *(u32*)p ) psxRecClearMem(p); \ + } \ +} \ + +BASEBLOCKEX* PSX_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+PSX_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 1); +} + +//////////////////////////////////////////////////// +static void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ], command[256]; + u32 i, j; + EEINST* pcur; + u8 used[34]; + int numused, count; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, psxpc, psxRegs.cycle ); +#ifdef _WIN32 + CreateDirectory("dumps", NULL); +sprintf( filename, "dumps\\psxdump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/psxdump%.8X.txt", startpc); +#endif + + fflush( stdout ); + + f = fopen( filename, "w" ); + assert( f != NULL ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR3000Fasm( *(u32*)PSXM( i ), i ) ); + } + + // write the instruction info + fprintf(f, "\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&count tempdump", filename ); +#else + sprintf( command, "objdump -D --target=binary --architecture=i386 -M intel mydump1 | cat %s - > tempdump", filename ); +#endif + system( command ); + sprintf(command, "mv tempdump %s", filename); + system(command); + f = fopen( filename, "a+" ); +#endif +} + +u8 _psxLoadWritesRs(u32 tempcode) +{ + switch(tempcode>>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _psxIsLoadStore(u32 tempcode) +{ + switch(tempcode>>26) { + case 32: case 33: case 34: case 35: case 36: case 37: case 38: + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + return 1; + } + return 0; +} + +void _psxFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( psxpc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && PSX_IS_CONST1(i) ) _psxFlushConstReg(i); + else { + _deleteX86reg(X86TYPE_PSX, i, 1); + } + } +} + +int _psxFlushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_psxHasConstReg & (1< 0 ); + + // make sure right GPR was saved + assert( g_psxHasConstReg == s_saveHasConstReg || (g_psxHasConstReg ^ s_saveHasConstReg) == (1< 0) { + pblock = PSX_GETBLOCK(psxRegs.pc); + + if ( !pblock->pFnptr || (pblock->startpc&PSX_MEMMASK) != (psxRegs.pc&PSX_MEMMASK) ) { + psxRecRecompile(psxRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + +#ifdef _DEBUG + + fnptr = (u8*)pblock->pFnptr; + +#ifdef _MSC_VER + + __asm { + // save data + mov oldesi, esi; + mov s_uSaveESP, esp; + sub s_uSaveESP, 8; + push ebp; + + call fnptr; // jump into function + // restore data + pop ebp; + mov esi, oldesi; + } + +#else // linux + + __asm__("movl %%esi, %0\n" + "movl %%esp, %1\n" + "sub $8, %%esp\n" + "push %%ebp\n" + "call *%2\n" + "pop %%ebp\n" + "movl %0, %%esi\n" : "=m"(oldesi), "=m"(s_uSaveESP) : "c"(fnptr) : ); +#endif // _MSC_VER + +#else + ((R3000AFNPTR)pblock->pFnptr)(); +#endif + } +} + +#else +extern "C" void R3000AExecute(); +#endif + +extern u32 g_psxNextBranchCycle; +u32 g_psxlastpc = 0; + +#if defined(_MSC_VER) && !defined(__x86_64__) + +static u32 g_temp; + +// jumped to when invalid psxpc address +__declspec(naked,noreturn) void psxDispatcher() +{ + // EDX contains the current psxpc to jump to, stack contains the jump addr to modify + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc&PSX_MEMMASK == psxRegs.pc&PSX_MEMMASK + mov ecx, psxRegs.pc + mov edx, [eax+BLOCKTYPE_STARTPC]; + and ecx, PSX_MEMMASK // remove higher bits + and edx, PSX_MEMMASK + cmp ecx, edx + je CheckPtr + + // recompile + push psxRegs.pc // psxpc + call psxRecRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new psxpc +// and eax, 0x0fffffff +// mov ecx, psxRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void psxDispatcherClear() +{ + // EDX contains the current psxpc + __asm mov psxRegs.pc, edx + __asm push edx + + // calc PSX_GETBLOCK + s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + + if( (s_pDispatchBlock->startpc&PSX_MEMMASK) == (psxRegs.pc&PSX_MEMMASK) ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call psxRecRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable psxpc address +__declspec(naked,noreturn) void psxDispatcherReg() +{ + __asm { + //s_pDispatchBlock = PSX_GETBLOCK(psxRegs.pc); + mov edx, psxRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, psxRecLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == psxRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_temp, eax + assert( g_temp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call psxRecRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +#else // _MSC_VER + +#ifdef __cplusplus +extern "C" { +#endif + +void psxDispatcher(); +void psxDispatcherClear(); +void psxDispatcherReg(); + +#ifdef __cplusplus +} +#endif + +#endif // _MSC_VER + +static void recClear(u32 Addr, u32 Size) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + PSXREC_CLEARM(Addr); + } +} + +#ifdef __x86_64__ +#define EE_MIN_BLOCK_BYTES 16 +#else +#define EE_MIN_BLOCK_BYTES 15 +#endif + +void rpsxMemConstClear(u32 mem) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !psxRecLUT[mem>>16] ) + return; + + CMP32ItoM((uptr)PSX_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + _callFunctionArg1((uptr)psxRecClearMem, MEM_CONSTTAG, (uptr)PSX_GETBLOCK(mem)); + x86SetJ8(j8Ptr[6]); +} + +void psxRecClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + psxRecClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + assert( (uptr)x86Ptr <= 0xffffffff ); +#ifdef __x86_64__ + MOV32ItoR(R15, (uptr)x86Ptr); // will be replaced by JMP32 +#else + PUSH32I((uptr)x86Ptr); +#endif + JMP32((uptr)psxDispatcherClear - ( (uptr)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PSX_GETBLOCK(p->startpc); + pexblock = PSX_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((uptr)psxDispatcherClear - ( (uptr)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 1); + pexblock->size = 0; + pexblock->startpc = 0; +} + +void psxSetBranchReg(u32 reg) +{ + psxbranch = 1; + + if( reg != 0xffffffff ) { + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, reg); + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((uptr)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (uptr)&g_recWriteback); + MOV32RtoM((uptr)&psxRegs.pc, EAX); + } + } + + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(0xffffffff, 1); + + JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 )); +} + +void psxSetBranchImm( u32 imm ) +{ + u32* ptr; + psxbranch = 1; + assert( imm ); + + // end the current block + MOV32ItoM( (uptr)&psxRegs.pc, imm ); + _psxFlushCall(FLUSH_EVERYTHING); + iPsxBranchTest(imm, imm <= psxpc); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (uptr)JMP32((uptr)psxDispatcher - ( (uptr)x86Ptr + 5 )); +} + +#define USE_FAST_BRANCHES 0 + +static void iPsxBranchTest(u32 newpc, u32 cpuBranch) +{ + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (uptr)&psxRegs.cycle); + ADD32ItoR(ECX, s_psxBlockCycles*17/16); // greater mult factor causes nfsmw to crash + MOV32RtoM((uptr)&psxRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((uptr)&psxRegs.cycle, s_psxBlockCycles*17/16); + return; + } + + SUB32MtoR(ECX, (uptr)&g_psxNextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + CALLFunc((uptr)psxBranchTest); + + CMP32ItoM((uptr)&EEsCycle, 0); + j8Ptr[2] = JG8(0); + if( REC_INC_STACK ) + ADD64ItoR(ESP, REC_INC_STACK); + RET2(); + x86SetJ8( j8Ptr[2] ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((uptr)&psxRegs.pc, newpc); + JNE32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + +static int *s_pCode; + +#if !defined(_MSC_VER) || !defined(__x86_64__) +static void checkcodefn() +{ + int pctemp; + +#ifdef _MSC_VER + __asm mov pctemp, eax; +#else + __asm__("movl %%eax, %0" : : "m"(pctemp) ); +#endif + SysPrintf("iop code changed! %x\n", pctemp); +} +#endif + +void rpsxSYSCALL() +{ + MOV32ItoM( (uptr)&psxRegs.code, psxRegs.code ); + MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4); + _psxFlushCall(FLUSH_NODESTROY); + + _callFunctionArg2((uptr)psxException, MEM_CONSTTAG, MEM_CONSTTAG, 0x20, psxbranch==1); + + CMP32ItoM((uptr)&psxRegs.pc, psxpc-4); + j8Ptr[0] = JE8(0); + ADD32ItoM((uptr)&psxRegs.cycle, s_psxBlockCycles); + JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + + //if (!psxbranch) psxbranch = 2; +} + +u32 psxRecompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PSX_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( psxpc == pblock->startpc ) + return 0; + } + + return 1; +} + +void psxRecompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + + BASEBLOCK* pblock = PSX_GETBLOCK(psxpc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && psxpc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PSX_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((uptr)&psxRegs.pc, psxpc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((uptr)pexblock->pOldFnptr - ((uptr)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((uptr)pblock->pFnptr - ((uptr)x86Ptr + 5)); + psxbranch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == psxpc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + psxRecClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", psxpc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + +#ifdef _DEBUG + MOV32ItoR(EAX, psxpc); +#endif + + s_pCode = (int *)PSXM( psxpc ); + assert(s_pCode); + + psxRegs.code = *(int *)s_pCode; + s_psxBlockCycles++; + psxpc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((uptr)s_pCode, psxRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, psxpc); +// CALLFunc((uptr)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +//#endif + + + g_pCurInstInfo++; + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + assert(0); +// recBSC_co[cpuRegs.code>>26](); +// psxpc += 4; +// s_psxBlockCycles++; +// g_pCurInstInfo++; + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + rpsxBSC[ psxRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //_psxFlushUnusedConstReg(); + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + _clearNeededX86regs(); +} + +static void recExecute() { + for (;;) R3000AExecute(); +} + +static void recExecuteBlock() { + R3000AExecute(); +} + +extern "C" +void iDumpPsxRegisters(u32 startpc, u32 temp) +{ + int i; + const char* pstr = temp ? "t" : ""; + + __Log("%spsxreg: %x %x\n", pstr, startpc, *(u32*)PSXM(0x6cc14)); + for(i = 0; i < 34; i+=2) __Log("%spsx%d: %x %x\n", pstr, i, psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); + __Log("%scycle: %x %x %x %x; counters %x %x\n", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, IOPoCycle, + (uptr)psxNextsCounter, (uptr)psxNextCounter); + + for(i = 0; i < 7; ++i) __Log("%scounter%d: %x %x %x\n", pstr, i, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT); +// for(i = 0; i < 32; ++i) { +// __Log("int%d: %x %x\n", i, psxRegs.sCycle[i], psxRegs.eCycle[i]); +// } +} + +void iDumpPsxRegisters(u32 startpc); + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0; + const int skip = 0; + + if( (psxdump&2) ) {//&& lastrec != g_psxlastpc ) { + curcount++; + + if( curcount > skip ) { + iDumpPsxRegisters(g_psxlastpc, 1); + curcount = 0; + } + + lastrec = g_psxlastpc; + } +} + +u32 s_psxrecblocks[] = {0}; + +void psxRecRecompile(u32 startpc) +{ + u32 i; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + +#ifdef _DEBUG + //psxdump |= 4; + if( psxdump & 4 ) + iDumpPsxRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if (((uptr)recPtr - (uptr)recMem) >= (RECMEM_SIZE - 0x10000)) + recReset(); + + s_pCurBlock = PSX_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + psxRecClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PSX_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < PSX_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%PSX_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%PSX_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%PSX_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + + psxbranch = 0; + + s_pCurBlock->startpc = startpc; + s_pCurBlock->pFnptr = (u32)(uptr)x86Ptr; + s_psxBlockCycles = 0; + + // reset recomp state variables + psxpc = startpc; + s_saveConstGPRreg = 0; + g_psxHasConstReg = g_psxFlushedConstReg = 1; + + _initX86regs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((uptr)&g_psxlastpc, psxpc); + CALLFunc((uptr)printfn); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + + while(1) { + BASEBLOCK* pblock = PSX_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + psxRegs.code = *(int *)PSXM(i); + + switch(psxRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ == 0 || _Rt_ == 1 || _Rt_ == 16 || _Rt_ == 17 ) { + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + psxRegs.code = *(int *)PSXM(i-4); + pcur[-1] = pcur[0]; + rpsxpropBSC(pcur-1, pcur); + pcur--; + } + } + + // peephole optimizations // +// { +// g_pCurInstInfo = s_pInstCache; +// +// for(i = startpc; i < s_nEndBlock-4; i += 4) { +// g_pCurInstInfo++; +// if( psxRecompileCodeSafe(i) ) { +// u32 curcode = *(u32*)PSXM(i); +// u32 nextcode = *(u32*)PSXM(i+4); +// if( _psxIsLoadStore(curcode) && _psxIsLoadStore(nextcode) && (curcode>>26) == (nextcode>>26) && rpsxBSC_co[curcode>>26] != NULL ) { +// +// // rs has to be the same, and cannot be just written +// if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_psxLoadWritesRs(curcode) ) { +// +// // good enough +// g_pCurInstInfo[0].info |= EEINSTINFO_COREC; +// g_pCurInstInfo[0].numpeeps = 1; +// g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; +// g_pCurInstInfo++; +// i += 4; +// continue; +// } +// } +// } +// } +// } + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_psxrecblocks); ++i) { + if( startpc == s_psxrecblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (psxdump & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + g_pCurInstInfo = s_pInstCache; + while (!psxbranch && psxpc < s_nEndBlock) { + psxRecompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (psxdump & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (psxpc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (psxpc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 1); + + if( !(psxpc&0x10000000) ) + g_psxMaxRecMem = max( (psxpc&~0xa0000000), g_psxMaxRecMem ); + + if( psxbranch == 2 ) { + _psxFlushCall(FLUSH_EVERYTHING); + + iPsxBranchTest(0xffffffff, 1); + + JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 )); + } + else { + assert( psxbranch != 3 ); + if( psxbranch ) assert( !willbranch3 ); + else ADD32ItoM((uptr)&psxRegs.cycle, s_psxBlockCycles*17/16); + + if( willbranch3 ) { + BASEBLOCK* pblock = PSX_GETBLOCK(s_nEndBlock); + assert( psxpc == s_nEndBlock ); + _psxFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((uptr)&psxRegs.pc, psxpc); + JMP32((uptr)pblock->pFnptr - ((uptr)x86Ptr + 5)); + psxbranch = 3; + } + else if( !psxbranch ) { + // didn't branch, but had to stop + MOV32ItoM( (uptr)&psxRegs.pc, psxpc ); + + _psxFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + //JMP32((uptr)psxDispatcherReg - ( (uptr)x86Ptr + 5 )); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+RECMEM_SIZE ); + + recPtr = x86Ptr; + + assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); + + if( !psxbranch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PSX_GETBLOCK(psxpc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != psxpc ) + psxRecRecompile(psxpc); + + // could have reset + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = (u32)((uptr)s_pCurBlock->pFnptr - ( (uptr)ptr + 4 )); + } + else { + psxRecRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } + else + assert( s_pCurBlock->pFnptr != 0 ); +} + +R3000Acpu psxRec = { + recInit, + recReset, + recExecute, + recExecuteBlock, + recClear, + recShutdown +}; + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iR3000A.h b/pcsx2/x86/iR3000A.h new file mode 100644 index 0000000..21befca --- /dev/null +++ b/pcsx2/x86/iR3000A.h @@ -0,0 +1,99 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _R3000A_SUPERREC_ +#define _R3000A_SUPERREC_ + +extern void __Log(char *fmt, ...); + +// to be consistent with EE +#define PSX_HI XMMGPR_HI +#define PSX_LO XMMGPR_LO + +extern uptr *psxRecLUT; + +u8 _psxLoadWritesRs(u32 tempcode); +u8 _psxIsLoadStore(u32 tempcode); + +void _psxFlushAllUnused(); +int _psxFlushUnusedConstReg(); +void _psxFlushCachedRegs(); +void _psxFlushConstReg(int reg); +void _psxFlushConstRegs(); + +void _psxDeleteReg(int reg, int flush); +void _psxFlushCall(int flushtype); + +void _psxOnWriteReg(int reg); +void PSX_CHECK_SAVE_REG(int reg); + +extern u32 psxpc; // recompiler pc +extern int psxbranch; // set for branch + +void psxSaveBranchState(); +void psxLoadBranchState(); + +void psxSetBranchReg(u32 reg); +void psxSetBranchImm( u32 imm ); +void psxRecompileNextInstruction(int delayslot); + +typedef void (*R3000AFNPTR)(); +typedef void (*R3000AFNPTR_INFO)(int info); + +void psxRecClearMem(BASEBLOCK* p); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define PSXRECOMPILE_CONSTCODE0(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst0(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_); \ +} \ + +// rt = rs op imm16 +#define PSXRECOMPILE_CONSTCODE1(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst1(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// rd = rt op sa +#define PSXRECOMPILE_CONSTCODE2(fn) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst2(rpsx##fn##_const, rpsx##fn##_); \ +} \ + +// [lo,hi] = rt op rs +#define PSXRECOMPILE_CONSTCODE3(fn, LOHI) \ +void rpsx##fn(void) \ +{ \ + psxRecompileCodeConst3(rpsx##fn##_const, rpsx##fn##_consts, rpsx##fn##_constt, rpsx##fn##_, LOHI); \ +} \ + +// rd = rs op rt +void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode); +// rt = rs op imm16 +void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// rd = rt op sa +void psxRecompileCodeConst2(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode); +// [lo,hi] = rt op rs +void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, R3000AFNPTR_INFO consttcode, R3000AFNPTR_INFO noconstcode, int LOHI); + +#endif diff --git a/pcsx2/x86/iR3000Atables.cpp b/pcsx2/x86/iR3000Atables.cpp new file mode 100644 index 0000000..0b739d8 --- /dev/null +++ b/pcsx2/x86/iR3000Atables.cpp @@ -0,0 +1,2051 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +extern "C" { +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "Memory.h" +#include "Misc.h" +#include "Vif.h" +#include "VU.h" + +#include "R3000A.h" +#include "PsxMem.h" + +#include "ix86/ix86.h" + +#include "iCore.h" +#include "iR3000A.h" + +extern void psxLWL(); +extern void psxLWR(); +extern void psxSWL(); +extern void psxSWR(); + +extern int g_psxWriteOk; +extern u32 g_psxMaxRecMem; +} + +// R3000A instruction implementation +#define REC_FUNC(f) \ +void psx##f(); \ +static void rpsx##f() { \ + MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \ + _psxFlushCall(FLUSH_EVERYTHING); \ + /*MOV32ItoM((u32)&psxRegs.pc, (u32)pc);*/ \ + CALLFunc((uptr)psx##f); \ + PSX_DEL_CONST(_Rt_); \ +/* branch = 2; */\ +} + +//// +void rpsxADDIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] + _Imm_; +} + +// adds a constant to sreg and puts into dreg +void rpsxADDconst(int dreg, int sreg, u32 off, int info) +{ + if (sreg) { + if (sreg == dreg) { + ADD32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + if (off) ADD32ItoR(EAX, off); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], off); + } +} + +void rpsxADDIU_(int info) +{ + // Rt = Rs + Im + if (!_Rt_) return; + rpsxADDconst(_Rt_, _Rs_, _Imm_, info); +} + +PSXRECOMPILE_CONSTCODE1(ADDIU); + +void rpsxADDI() { rpsxADDIU(); } + +//// SLTI +void rpsxSLTI_const() +{ + g_psxConstRegs[_Rt_] = *(int*)&g_psxConstRegs[_Rs_] < _Imm_; +} + +void rpsxSLTconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETL8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTI_(int info) { rpsxSLTconst(info, _Rt_, _Rs_, _Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTI); + +//// SLTIU +void rpsxSLTIU_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] < _ImmU_; +} + +void rpsxSLTUconst(int info, int dreg, int sreg, int imm) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[sreg], imm); + SETB8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); +} + +void rpsxSLTIU_(int info) { rpsxSLTUconst(info, _Rt_, _Rs_, (s32)_Imm_); } + +PSXRECOMPILE_CONSTCODE1(SLTIU); + +//// ANDI +void rpsxANDI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] & _ImmU_; +} + +void rpsxANDconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + AND32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + AND32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } else { + MOV32ItoM((uptr)&psxRegs.GPR.r[dreg], 0); + } +} + +void rpsxANDI_(int info) { rpsxANDconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ANDI); + +//// ORI +void rpsxORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] | _ImmU_; +} + +void rpsxORconst(int info, int dreg, int sreg, u32 imm) +{ + if (imm) { + if (sreg == dreg) { + OR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + OR32ItoR (EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxORI_(int info) { rpsxORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(ORI); + +void rpsxXORI_const() +{ + g_psxConstRegs[_Rt_] = g_psxConstRegs[_Rs_] ^ _ImmU_; +} + +void rpsxXORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm == 0xffffffff ) { + if( dreg == sreg ) { + NOT32M((uptr)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } + else if (imm) { + + if (sreg == dreg) { + XOR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[sreg]); + XOR32ItoR(EAX, imm); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], EAX); + } + } + else { + if( dreg != sreg ) { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxXORI_(int info) { rpsxXORconst(info, _Rt_, _Rs_, _ImmU_); } + +PSXRECOMPILE_CONSTCODE1(XORI); + +void rpsxLUI() +{ + if(!_Rt_) return; + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + PSX_SET_CONST(_Rt_); + g_psxConstRegs[_Rt_] = psxRegs.code << 16; +} + +void rpsxADDU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] + g_psxConstRegs[_Rt_]; +} + +void rpsxADDU_consts(int info) { rpsxADDconst(_Rd_, _Rt_, g_psxConstRegs[_Rs_], info); } +void rpsxADDU_constt(int info) +{ + info |= PROCESS_EE_SET_S(EEREC_T); + rpsxADDconst(_Rd_, _Rs_, g_psxConstRegs[_Rt_], info); +} + +void rpsxADDU_(int info) +{ + if (_Rs_ && _Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else if (_Rs_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + } else if (_Rt_) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + } else { + XOR32RtoR(EAX, EAX); + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(ADDU); + +void rpsxADD() { rpsxADDU(); } + + +void rpsxSUBU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] - g_psxConstRegs[_Rt_]; +} + +void rpsxSUBU_consts(int info) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSUBU_constt(int info) { rpsxADDconst(_Rd_, _Rs_, -(int)g_psxConstRegs[_Rt_], info); } + +void rpsxSUBU_(int info) +{ + // Rd = Rs - Rt + if (!_Rd_) return; + + if( _Rd_ == _Rs_ ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SUB32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); + } +} + +PSXRECOMPILE_CONSTCODE0(SUBU); + +void rpsxSUB() { rpsxSUBU(); } + +void rpsxLogicalOp(int info, int op) +{ + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[vreg]); + LogicalOp32RtoM((uptr)&psxRegs.GPR.r[_Rd_], ECX, op); + if( op == 3 ) + NOT32M((uptr)&psxRegs.GPR.r[_Rd_]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + LogicalOp32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_], op); + if( op == 3 ) + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], ECX); + } +} + +void rpsxAND_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] & g_psxConstRegs[_Rt_]; +} + +void rpsxAND_consts(int info) { rpsxANDconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxAND_constt(int info) { rpsxANDconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxAND_(int info) { rpsxLogicalOp(info, 0); } + +PSXRECOMPILE_CONSTCODE0(AND); + +void rpsxOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]; +} + +void rpsxOR_consts(int info) { rpsxORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxOR_constt(int info) { rpsxORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxOR_(int info) { rpsxLogicalOp(info, 1); } + +PSXRECOMPILE_CONSTCODE0(OR); + +//// XOR +void rpsxXOR_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] ^ g_psxConstRegs[_Rt_]; +} + +void rpsxXOR_consts(int info) { rpsxXORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxXOR_constt(int info) { rpsxXORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxXOR_(int info) { rpsxLogicalOp(info, 2); } + +PSXRECOMPILE_CONSTCODE0(XOR); + +//// NOR +void rpsxNOR_const() +{ + g_psxConstRegs[_Rd_] = ~(g_psxConstRegs[_Rs_] | g_psxConstRegs[_Rt_]); +} + +void rpsxNORconst(int info, int dreg, int sreg, u32 imm) +{ + if( imm ) { + if( dreg == sreg ) { + OR32ItoM((uptr)&psxRegs.GPR.r[dreg], imm); + NOT32M((uptr)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + OR32ItoR(ECX, imm); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } + else { + if( dreg == sreg ) { + NOT32M((uptr)&psxRegs.GPR.r[dreg]); + } + else { + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[sreg]); + NOT32R(ECX); + MOV32RtoM((uptr)&psxRegs.GPR.r[dreg], ECX); + } + } +} + +void rpsxNOR_consts(int info) { rpsxNORconst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_]); } +void rpsxNOR_constt(int info) { rpsxNORconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxNOR_(int info) { rpsxLogicalOp(info, 3); } + +PSXRECOMPILE_CONSTCODE0(NOR); + +//// SLT +void rpsxSLT_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rs_] < *(int*)&g_psxConstRegs[_Rt_]; +} + +void rpsxSLT_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETG8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLT_constt(int info) { rpsxSLTconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLT_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SETL8R (EAX); + AND32ItoR(EAX, 0xff); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLT); + +//// SLTU +void rpsxSLTU_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rs_] < g_psxConstRegs[_Rt_]; +} + +void rpsxSLTU_consts(int info) +{ + XOR32RtoR(EAX, EAX); + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], g_psxConstRegs[_Rs_]); + SETA8R(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLTU_constt(int info) { rpsxSLTUconst(info, _Rd_, _Rs_, g_psxConstRegs[_Rt_]); } +void rpsxSLTU_(int info) +{ + // Rd = Rs < Rt (unsigned) + if (!_Rd_) return; + + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + SBB32RtoR(EAX, EAX); + NEG32R (EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLTU); + +//// MULT +void rpsxMULT_const() +{ + u64 res = (s64)((s64)*(int*)&g_psxConstRegs[_Rs_] * (s64)*(int*)&g_psxConstRegs[_Rt_]); + + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTsuperconst(int info, int sreg, int imm, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32ItoR(EAX, imm); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[sreg]); + else MUL32M ((uptr)&psxRegs.GPR.r[sreg]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULTsuper(int info, int sign) +{ + // Lo/Hi = Rs * Rt (signed) + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + if( sign ) IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + else MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); +} + +void rpsxMULT_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 1); } +void rpsxMULT_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 1); } +void rpsxMULT_(int info) { rpsxMULTsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(MULT, 1); + +//// MULTU +void rpsxMULTU_const() +{ + u64 res = (u64)((u64)g_psxConstRegs[_Rs_] * (u64)g_psxConstRegs[_Rt_]); + + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, (u32)((res >> 32) & 0xffffffff)); + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, (u32)(res & 0xffffffff)); +} + +void rpsxMULTU_consts(int info) { rpsxMULTsuperconst(info, _Rt_, g_psxConstRegs[_Rs_], 0); } +void rpsxMULTU_constt(int info) { rpsxMULTsuperconst(info, _Rs_, g_psxConstRegs[_Rt_], 0); } +void rpsxMULTU_(int info) { rpsxMULTsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(MULTU, 1); + +//// DIV +void rpsxDIV_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = *(int*)&g_psxConstRegs[_Rs_] / *(int*)&g_psxConstRegs[_Rt_]; + hi = *(int*)&g_psxConstRegs[_Rs_] % *(int*)&g_psxConstRegs[_Rt_]; + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVsuperconsts(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rs_]; + + if( imm ) { + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32ItoR(EAX, imm); + + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); + } + else { + XOR32RtoR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxDIVsuperconstt(int info, int sign) +{ + u32 imm = g_psxConstRegs[_Rt_]; + + if( imm ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32ItoR(ECX, imm); + //CDQ(); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + } +} + +void rpsxDIVsuper(int info, int sign) +{ + // Lo/Hi = Rs / Rt (signed) + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]); + CMP32ItoR(ECX, 0); + j8Ptr[0] = JE8(0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + + if( sign ) { + CDQ(); + IDIV32R (ECX); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R(ECX); + } + + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX); + x86SetJ8(j8Ptr[0]); +} + +void rpsxDIV_consts(int info) { rpsxDIVsuperconsts(info, 1); } +void rpsxDIV_constt(int info) { rpsxDIVsuperconstt(info, 1); } +void rpsxDIV_(int info) { rpsxDIVsuper(info, 1); } + +PSXRECOMPILE_CONSTCODE3(DIV, 1); + +//// DIVU +void rpsxDIVU_const() +{ + u32 lo, hi; + + if (g_psxConstRegs[_Rt_] != 0) { + lo = g_psxConstRegs[_Rs_] / g_psxConstRegs[_Rt_]; + hi = g_psxConstRegs[_Rs_] % g_psxConstRegs[_Rt_]; + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, hi); + MOV32ItoM((uptr)&psxRegs.GPR.n.lo, lo); + } +} + +void rpsxDIVU_consts(int info) { rpsxDIVsuperconsts(info, 0); } +void rpsxDIVU_constt(int info) { rpsxDIVsuperconstt(info, 0); } +void rpsxDIVU_(int info) { rpsxDIVsuper(info, 0); } + +PSXRECOMPILE_CONSTCODE3(DIVU, 1); + +//// LoadStores +#ifdef PCSX2_VIRTUAL_MEM + +// VM load store functions (fastest) + +//#define REC_SLOWREAD +//#define REC_SLOWWRITE + +int _psxPrepareReg(int gprreg) +{ + return 0; +} + +static u32 s_nAddMemOffset = 0; + +#define SET_HWLOC() { \ + x86SetJ8(j8Ptr[0]); \ + SHR32ItoR(ECX, 3); \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ +} \ + +int rpsxSetMemLocation(int regs, int mmreg) +{ + s_nAddMemOffset = 0; + MOV32MtoR( ECX, (int)&psxRegs.GPR.r[ regs ] ); + + if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); + + SHL32ItoR(ECX, 3); + j8Ptr[0] = JS8(0); + SHR32ItoR(ECX, 3); + AND32ItoR(ECX, 0x1fffff); // 2Mb + return 1; +} + +void recLoad32(u32 bit, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _psxOnWriteReg(_Rt_); + mmreg = EAX; + + switch(bit) { + case 8: ineax = psxRecMemConstRead8(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); break; + case 16: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 2 == 0 ); + ineax = psxRecMemConstRead16(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); + break; + case 32: + assert( (g_psxConstRegs[_Rs_]+_Imm_) % 4 == 0 ); + ineax = psxRecMemConstRead32(mmreg, g_psxConstRegs[_Rs_]+_Imm_); + break; + } + + if( _Rt_ ) MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)psxRecMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)psxRecMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + CALLFunc( (int)psxRecMemRead32 ); + break; + } + + x86SetJ8(j8Ptr[1]); + } + + if( _Rt_ ) + MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX ); + } +} + +void rpsxLB() { recLoad32(8, 1); } +void rpsxLBU() { recLoad32(8, 0); } +void rpsxLH() { recLoad32(16, 1); } +void rpsxLHU() { recLoad32(16, 0); } +void rpsxLW() { recLoad32(32, 0); } + +extern void rpsxMemConstClear(u32 mem); + +// check if mem is executable, and clear it +__declspec(naked) void rpsxWriteMemClear() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, psxRecLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call psxRecClearMem + add esp, 4 +ClearRet: + ret + } +} + +extern u32 s_psxBlockCycles; +void recStore(int bit) +{ +#ifdef REC_SLOWWRITE + _psxFlushConstReg(_Rs_); +#else + if( PSX_IS_CONST1( _Rs_ ) ) { + u8* pjmpok; + u32 addr = g_psxConstRegs[_Rs_]+_Imm_; + int doclear = 0; + + if( !(addr & 0x10000000) ) { + // check g_psxWriteOk + CMP32ItoM((uptr)&g_psxWriteOk, 0); + pjmpok = JE8(0); + } + + switch(bit) { + case 8: + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite8(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite8(addr, EAX); + } + + break; + + case 16: + assert( (addr)%2 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite16(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite16(addr, EAX); + } + + break; + + case 32: + assert( (addr)%4 == 0 ); + if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite32(addr, MEM_PSXCONSTTAG|(_Rt_<<16)); + else { + _psxMoveGPRtoR(EAX, _Rt_); + doclear = psxRecMemConstWrite32(addr, EAX); + } + + break; + } + + if( !(addr & 0x10000000) ) { + if( doclear ) rpsxMemConstClear((addr)&~3); + x86SetJ8(pjmpok); + } + } + else +#endif + { + int dohw; + int mmregs = _psxPrepareReg(_Rs_); + dohw = rpsxSetMemLocation(_Rs_, mmregs); + + CMP32ItoM((uptr)&g_psxWriteOk, 0); + u8* pjmpok = JE8(0); + + if( PSX_IS_CONST1( _Rt_ ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 16: MOV16ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + case 32: MOV32ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break; + } + } + else { + switch(bit) { + case 8: + MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV8RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 16: + MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV16RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + + case 32: + MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset); + break; + } + } + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (uptr)&g_psxMaxRecMem); + + j8Ptr[1] = JAE8(0); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + CALLFunc((u32)rpsxWriteMemClear); + + if( dohw ) { + j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( PSX_IS_CONST1(_Rt_) ) { + switch(bit) { + case 8: MOV8ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 16: MOV16ItoR(EAX, g_psxConstRegs[_Rt_]); break; + case 32: MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); break; + } + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 16: MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + case 32: MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break; + } + } + + if( s_nAddMemOffset != 0 ) ADD32ItoR(ECX, s_nAddMemOffset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)psxRecMemWrite8 ); break; + case 16: CALLFunc( (int)psxRecMemWrite16 ); break; + case 32: CALLFunc( (int)psxRecMemWrite32 ); break; + } + + x86SetJ8(j8Ptr[2]); + } + + x86SetJ8(j8Ptr[1]); + x86SetJ8(pjmpok); + } +} + +void rpsxSB() { recStore(8); } +void rpsxSH() { recStore(16); } +void rpsxSW() { recStore(32); } + +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +#else + +// TLB loadstore functions (slower +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(SWL); +REC_FUNC(SWR); + +static void rpsxLB() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg1((uptr)psxMemRead8, X86ARG1|MEM_X86TAG, 0); + if (_Rt_) { + MOVSX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLBU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg1((uptr)psxMemRead8, X86ARG1|MEM_X86TAG, 0); + if (_Rt_) { + MOVZX32R8toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLH() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg1((uptr)psxMemRead16, X86ARG1|MEM_X86TAG, 0); + if (_Rt_) { + MOVSX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLHU() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg1((uptr)psxMemRead16, X86ARG1|MEM_X86TAG, 0); + if (_Rt_) { + MOVZX32R16toR(EAX, EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + PSX_DEL_CONST(_Rt_); +} + +static void rpsxLW() +{ + _psxDeleteReg(_Rs_, 1); + _psxOnWriteReg(_Rt_); + _psxDeleteReg(_Rt_, 0); + + _psxFlushCall(FLUSH_EVERYTHING); + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + + TEST32ItoR(X86ARG1, 0x10000000); + j8Ptr[0] = JZ8(0); + + _callFunctionArg1((uptr)psxMemRead32, X86ARG1|MEM_X86TAG, 0); + if (_Rt_) { + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); + } + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + // read from psM directly + AND32ItoR(X86ARG1, 0x0fffffff); + ADD32ItoR(X86ARG1, (uptr)psxM); + + MOV32RmtoR( X86ARG1, X86ARG1 ); + MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], X86ARG1); + + x86SetJ8(j8Ptr[1]); + PSX_DEL_CONST(_Rt_); +} + +static void rpsxSB() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg2((uptr)psxMemWrite8, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]); +} + +static void rpsxSH() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg2((uptr)psxMemWrite16, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]); +} + +static void rpsxSW() +{ + _psxDeleteReg(_Rs_, 1); + _psxDeleteReg(_Rt_, 1); + + MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]); + if (_Imm_) ADD32ItoR(X86ARG1, _Imm_); + _callFunctionArg2((uptr)psxMemWrite32, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]); +} + +#endif // end load store + +//// SLL +void rpsxSLL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << _Sa_; +} + +// shifttype: 0 - sll, 1 - srl, 2 - sra +void rpsxShiftConst(int info, int rdreg, int rtreg, int imm, int shifttype) +{ + imm &= 0x1f; + if (imm) { + if( rdreg == rtreg ) { + switch(shifttype) { + case 0: SHL32ItoM((uptr)&psxRegs.GPR.r[rdreg], imm); break; + case 1: SHR32ItoM((uptr)&psxRegs.GPR.r[rdreg], imm); break; + case 2: SAR32ItoM((uptr)&psxRegs.GPR.r[rdreg], imm); break; + } + } + else { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[rtreg]); + switch(shifttype) { + case 0: SHL32ItoR(EAX, imm); break; + case 1: SHR32ItoR(EAX, imm); break; + case 2: SAR32ItoR(EAX, imm); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[rdreg], EAX); + } + } + else { + if( rdreg != rtreg ) { + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[rtreg]); + MOV32RtoM((uptr)&psxRegs.GPR.r[rdreg], EAX); + } + } +} + +void rpsxSLL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 0); } +PSXRECOMPILE_CONSTCODE2(SLL); + +//// SRL +void rpsxSRL_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRL_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 1); } +PSXRECOMPILE_CONSTCODE2(SRL); + +//// SRA +void rpsxSRA_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> _Sa_; +} + +void rpsxSRA_(int info) { rpsxShiftConst(info, _Rd_, _Rt_, _Sa_, 2); } +PSXRECOMPILE_CONSTCODE2(SRA); + +//// SLLV +void rpsxSLLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] << (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxShiftVconsts(int info, int shifttype) +{ + rpsxShiftConst(info, _Rd_, _Rt_, g_psxConstRegs[_Rs_], shifttype); +} + +void rpsxShiftVconstt(int info, int shifttype) +{ + MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + switch(shifttype) { + case 0: SHL32CLtoR(EAX); break; + case 1: SHR32CLtoR(EAX); break; + case 2: SAR32CLtoR(EAX); break; + } + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxSLLV_consts(int info) { rpsxShiftVconsts(info, 0); } +void rpsxSLLV_constt(int info) { rpsxShiftVconstt(info, 0); } +void rpsxSLLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHL32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SLLV); + +//// SRLV +void rpsxSRLV_const() +{ + g_psxConstRegs[_Rd_] = g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRLV_consts(int info) { rpsxShiftVconsts(info, 1); } +void rpsxSRLV_constt(int info) { rpsxShiftVconstt(info, 1); } +void rpsxSRLV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SHR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRLV); + +//// SRAV +void rpsxSRAV_const() +{ + g_psxConstRegs[_Rd_] = *(int*)&g_psxConstRegs[_Rt_] >> (g_psxConstRegs[_Rs_]&0x1f); +} + +void rpsxSRAV_consts(int info) { rpsxShiftVconsts(info, 2); } +void rpsxSRAV_constt(int info) { rpsxShiftVconstt(info, 2); } +void rpsxSRAV_(int info) +{ + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]); + SAR32CLtoR(EAX); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +PSXRECOMPILE_CONSTCODE0(SRAV); + +extern void rpsxSYSCALL(); + +void rpsxBREAK() { +} + +void rpsxMFHI() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTHI() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX); + } +} + +void rpsxMFLO() +{ + if (!_Rd_) return; + + _psxOnWriteReg(_Rd_); + _psxDeleteReg(_Rd_, 0); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX); +} + +void rpsxMTLO() +{ + if( PSX_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&psxRegs.GPR.n.hi, g_psxConstRegs[_Rs_]); + } + else { + _psxDeleteReg(_Rs_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]); + MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX); + } +} + +void rpsxJ() +{ + // j target + u32 newpc = _Target_ * 4 + (psxpc & 0xf0000000); + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJAL() +{ + u32 newpc = (_Target_ << 2) + ( psxpc & 0xf0000000 ); + _psxDeleteReg(31, 0); + PSX_SET_CONST(31); + g_psxConstRegs[31] = psxpc + 4; + + psxRecompileNextInstruction(1); + psxSetBranchImm(newpc); +} + +void rpsxJR() +{ + psxSetBranchReg(_Rs_); +} + +void rpsxJALR() +{ + // jalr Rs + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _psxMoveGPRtoR(ESI, _Rs_); + + if ( _Rd_ ) + { + _psxDeleteReg(_Rd_, 0); + PSX_SET_CONST(_Rd_); + g_psxConstRegs[_Rd_] = psxpc + 4; + } + + psxRecompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((uptr)&psxRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (uptr)&g_recWriteback); + MOV32RtoM((uptr)&psxRegs.pc, EAX); + } + + psxSetBranchReg(0xffffffff); +} + +//// BEQ +static void* s_pbranchjmp; +static u32 s_do32 = 0; + +#define JUMPVALID(pjmp) (( x86Ptr - (s8*)pjmp ) <= 0x80) + +void rpsxSetBranchEQ(int info, int process) +{ + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (uptr)&psxRegs.GPR.r[ _Rt_ ], g_psxConstRegs[_Rs_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (uptr)&psxRegs.GPR.r[ _Rs_ ], g_psxConstRegs[_Rt_] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } + else { + MOV32MtoR( EAX, (uptr)&psxRegs.GPR.r[ _Rs_ ] ); + CMP32MtoR( EAX, (uptr)&psxRegs.GPR.r[ _Rt_ ] ); + if( s_do32 ) s_pbranchjmp = JNE32( 0 ); + else s_pbranchjmp = JNE8( 0 ); + } +} + +void rpsxBEQ_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] == g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + } + else + { + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + psxSaveBranchState(); + + rpsxSetBranchEQ(info, process); + + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + } +} + +void rpsxBEQ_(int info) { rpsxBEQ_process(info, 0); } +void rpsxBEQ_consts(int info) { rpsxBEQ_process(info, PROCESS_CONSTS); } +void rpsxBEQ_constt(int info) { rpsxBEQ_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BEQ, 0); + +//// BNE +void rpsxBNE_const() +{ + u32 branchTo; + + if( g_psxConstRegs[_Rs_] != g_psxConstRegs[_Rt_] ) + branchTo = ((s32)_Imm_ * 4) + psxpc; + else + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); +} + +void rpsxBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + if ( _Rs_ == _Rt_ ) + { + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + return; + } + + _psxFlushAllUnused(); + s8* prevx86 = x86Ptr; + s_do32 = 0; + rpsxSetBranchEQ(info, process); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(s_pbranchjmp) ) { + x86SetJ8A( (u8*)s_pbranchjmp ); + } + else { + x86Ptr = prevx86; + s_do32 = 1; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + rpsxSetBranchEQ(info, process); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( (u32*)s_pbranchjmp ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +void rpsxBNE_(int info) { rpsxBNE_process(info, 0); } +void rpsxBNE_consts(int info) { rpsxBNE_process(info, PROCESS_CONSTS); } +void rpsxBNE_constt(int info) { rpsxBNE_process(info, PROCESS_CONSTT); } +PSXRECOMPILE_CONSTCODE3(BNE, 0); + +//// BLTZ +void rpsxBLTZ() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZ +void rpsxBGEZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLTZAL +void rpsxBLTZAL() +{ + // Branch if Rs < 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] >= 0 ) + branchTo = psxpc+4; + else { + PSX_SET_CONST(_Rt_); + g_psxConstRegs[31] = psxpc+4; + } + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JL8(0); + + psxSaveBranchState(); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JL32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BGEZAL +void rpsxBGEZAL() +{ + u32 branchTo = ((s32)_Imm_ * 4) + psxpc; + + _psxFlushConstReg(31); + _psxDeleteReg(31, 0); + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( g_psxConstRegs[_Rs_] < 0 ) + branchTo = psxpc+4; + else MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JGE8(0); + + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JGE32(0); + MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + // recopy the next inst + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + + psxSetBranchImm(branchTo); +} + +//// BLEZ +void rpsxBLEZ() +{ + // Branch if Rs <= 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] > 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JLE8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JLE32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +//// BGTZ +void rpsxBGTZ() +{ + // Branch if Rs > 0 + u32 branchTo = (s32)_Imm_ * 4 + psxpc; + + _psxFlushAllUnused(); + + if( PSX_IS_CONST1(_Rs_) ) { + if( (int)g_psxConstRegs[_Rs_] <= 0 ) + branchTo = psxpc+4; + + psxRecompileNextInstruction(1); + psxSetBranchImm( branchTo ); + return; + } + + _psxDeleteReg(_Rs_, 1); + _clearNeededX86regs(); + + CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); + s8* prevx86 = x86Ptr; + u8* pjmp = JG8(0); + + psxSaveBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + + if( JUMPVALID(pjmp) ) { + x86SetJ8A( pjmp ); + } + else { + x86Ptr = prevx86; + psxpc -= 4; + psxRegs.code = *(u32*)PSXM( psxpc - 4 ); + psxLoadBranchState(); + u32* pjmp32 = JG32(0); + psxRecompileNextInstruction(1); + psxSetBranchImm(psxpc); + x86SetJ32A( pjmp32 ); + } + + psxpc -= 4; + psxLoadBranchState(); + psxRecompileNextInstruction(1); + psxSetBranchImm(branchTo); +} + +void rpsxMFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxCFC0() +{ + // Rt = Cop0->Rd + if (!_Rt_) return; + + _psxOnWriteReg(_Rt_); + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]); + MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX); +} + +void rpsxMTC0() +{ + // Cop0->Rd = Rt + if( PSX_IS_CONST1(_Rt_) ) { + MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], g_psxConstRegs[_Rt_]); + } + else { + _psxDeleteReg(_Rt_, 1); + MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]); + MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX); + } +} + +void rpsxCTC0() +{ + // Cop0->Rd = Rt + rpsxMTC0(); +} + +void rpsxRFE() +{ + MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status); + MOV32RtoR(ECX, EAX); + AND32ItoR(EAX, 0xfffffff0); + AND32ItoR(ECX, 0x3c); + SHR32ItoR(ECX, 2); + OR32RtoR (EAX, ECX); + MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX); +} + +// R3000A tables +extern void (*rpsxBSC[64])(); +extern void (*rpsxSPC[64])(); +extern void (*rpsxREG[32])(); +extern void (*rpsxCP0[32])(); +extern void (*rpsxCP2[64])(); +extern void (*rpsxCP2BSC[32])(); + +static void rpsxSPECIAL() { rpsxSPC[_Funct_](); } +static void rpsxREGIMM() { rpsxREG[_Rt_](); } +static void rpsxCOP0() { rpsxCP0[_Rs_](); } +static void rpsxBASIC() { rpsxCP2BSC[_Rs_](); } + +static void rpsxNULL() { + SysPrintf("psxUNK: %8.8x\n", psxRegs.code); +} + +void (*rpsxBSC[64])() = { + rpsxSPECIAL, rpsxREGIMM, rpsxJ , rpsxJAL , rpsxBEQ , rpsxBNE , rpsxBLEZ, rpsxBGTZ, + rpsxADDI , rpsxADDIU , rpsxSLTI, rpsxSLTIU, rpsxANDI, rpsxORI , rpsxXORI, rpsxLUI , + rpsxCOP0 , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxLB , rpsxLH , rpsxLWL , rpsxLW , rpsxLBU , rpsxLHU , rpsxLWR , rpsxNULL, + rpsxSB , rpsxSH , rpsxSWL , rpsxSW , rpsxNULL, rpsxNULL, rpsxSWR , rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxSPC[64])() = { + rpsxSLL , rpsxNULL, rpsxSRL , rpsxSRA , rpsxSLLV , rpsxNULL , rpsxSRLV, rpsxSRAV, + rpsxJR , rpsxJALR, rpsxNULL, rpsxNULL, rpsxSYSCALL, rpsxBREAK, rpsxNULL, rpsxNULL, + rpsxMFHI, rpsxMTHI, rpsxMFLO, rpsxMTLO, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxMULT, rpsxMULTU, rpsxDIV, rpsxDIVU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxADD , rpsxADDU, rpsxSUB , rpsxSUBU, rpsxAND , rpsxOR , rpsxXOR , rpsxNOR , + rpsxNULL, rpsxNULL, rpsxSLT , rpsxSLTU, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL +}; + +void (*rpsxREG[32])() = { + rpsxBLTZ , rpsxBGEZ , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxBLTZAL, rpsxBGEZAL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL , rpsxNULL , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +void (*rpsxCP0[32])() = { + rpsxMFC0, rpsxNULL, rpsxCFC0, rpsxNULL, rpsxMTC0, rpsxNULL, rpsxCTC0, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxRFE , rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL +}; + +// coissued insts +void (*rpsxBSC_co[64] )() = { + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, + rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, rpsxNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpsxpropSetRead(reg) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpsxpropSetWrite(reg) { \ + prev->regs[reg] &= ~EEINST_LIVE0; \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +void rpsxpropBSC(EEINST* prev, EEINST* pinst); +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst); +void rpsxpropCP0(EEINST* prev, EEINST* pinst); +void rpsxpropCP2(EEINST* prev, EEINST* pinst); + +//SPECIAL, REGIMM, J , JAL , BEQ , BNE , BLEZ, BGTZ, +//ADDI , ADDIU , SLTI, SLTIU, ANDI, ORI , XORI, LUI , +//COP0 , NULL , COP2, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//LB , LH , LWL , LW , LBU , LHU , LWR , NULL, +//SB , SH , SWL , SW , NULL, NULL, SWR , NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL , NULL, NULL, NULL, NULL +void rpsxpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(psxRegs.code >> 26) { + case 0: rpsxpropSPECIAL(prev, pinst); break; + case 1: rpsxpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpsxpropSetWrite(31); + break; + case 4: // beq + case 5: // bne + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 6: // blez + case 7: // bgtz + rpsxpropSetRead(_Rs_); + break; + + case 15: // lui + rpsxpropSetWrite(_Rt_); + break; + + case 16: rpsxpropCP0(prev, pinst); break; + case 18: assert(0); break; + + // stores + case 40: case 41: case 42: case 43: case 46: + rpsxpropSetRead(_Rt_); + rpsxpropSetRead(_Rs_); + break; + + default: + rpsxpropSetWrite(_Rt_); + rpsxpropSetRead(_Rs_); + break; + } +} + +//SLL , NULL, SRL , SRA , SLLV , NULL , SRLV, SRAV, +//JR , JALR, NULL, NULL, SYSCALL, BREAK, NULL, NULL, +//MFHI, MTHI, MFLO, MTLO, NULL , NULL , NULL, NULL, +//MULT, MULTU, DIV, DIVU, NULL , NULL , NULL, NULL, +//ADD , ADDU, SUB , SUBU, AND , OR , XOR , NOR , +//NULL, NULL, SLT , SLTU, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL, +//NULL, NULL, NULL, NULL, NULL , NULL , NULL, NULL +void rpsxpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rt_); + break; + + case 8: // JR + rpsxpropSetRead(_Rs_); + break; + case 9: // JALR + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_HI); + break; + case 17: // mthi + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + break; + case 18: // mflo + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(PSX_LO); + break; + case 19: // mtlo + rpsxpropSetWrite(PSX_LO); + rpsxpropSetRead(_Rs_); + break; + + case 24: // mult + case 25: // multu + case 26: // div + case 27: // divu + rpsxpropSetWrite(PSX_LO); + rpsxpropSetWrite(PSX_HI); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpsxpropSetWrite(_Rd_); + if( _Rs_ ) rpsxpropSetRead(_Rs_); + if( _Rt_ ) rpsxpropSetRead(_Rt_); + break; + + default: + rpsxpropSetWrite(_Rd_); + rpsxpropSetRead(_Rs_); + rpsxpropSetRead(_Rt_); + break; + } +} + +//BLTZ , BGEZ , NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL, +//BLTZAL, BGEZAL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL , NULL , NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpsxpropSetRead(_Rs_); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpsxpropSetRead(_Rs_); + break; + + default: + assert(0); + break; + } +} + +//MFC0, NULL, CFC0, NULL, MTC0, NULL, CTC0, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//RFE , NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +void rpsxpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + case 2: // cfc0 + rpsxpropSetWrite(_Rt_); + break; + + case 4: // mtc0 + case 6: // ctc0 + rpsxpropSetRead(_Rt_); + break; + case 16: // rfe + break; + default: + assert(0); + } +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iR5900.h b/pcsx2/x86/iR5900.h new file mode 100644 index 0000000..2ed71fa --- /dev/null +++ b/pcsx2/x86/iR5900.h @@ -0,0 +1,254 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900_H__ +#define __IR5900_H__ + +#include "VU.h" +#include "iCore.h" + +// these might not work anymore +#define ARITHMETICIMM_RECOMPILE +#define ARITHMETIC_RECOMPILE +#define MULTDIV_RECOMPILE +#define SHIFT_RECOMPILE +#define BRANCH_RECOMPILE +#define JUMP_RECOMPILE +#define LOADSTORE_RECOMPILE +#define MOVE_RECOMPILE +#define MMI_RECOMPILE +#define MMI0_RECOMPILE +#define MMI1_RECOMPILE +#define MMI2_RECOMPILE +#define MMI3_RECOMPILE +#define FPU_RECOMPILE +#define CP0_RECOMPILE +#define CP2_RECOMPILE + +#define EE_CONST_PROP // rec2 - enables constant propagation (faster) +#define EE_FPU_REGCACHING 1 + +#define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT) + +void recClearMem(BASEBLOCK* p); +#define REC_CLEARM(mem) { \ + if ((mem) < maxrecmem && recLUT[(mem) >> 16]) { \ + BASEBLOCK* p = PC_GETBLOCK(mem); \ + if( *(u32*)p ) recClearMem(p); \ + } \ +} \ + +extern u32 pc; +extern int branch; +extern uptr* recLUT; + +extern u32 pc; // recompiler pc +extern int branch; // set for branch +extern u32 target; // branch target +extern u16 x86FpuState; +extern u16 iCWstate; +extern u32 s_nBlockCycles; // cycles of current block recompiling + +#define REC_FUNC_INLINE( f, delreg ) \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); + +#define REC_FUNC( f, delreg ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + if( (delreg) > 0 ) _deleteEEreg(delreg, 0); \ + CALLFunc( (u32)f ); \ + } + +#define REC_SYS( f ) \ + void f( void ); \ + void rec##f( void ) \ + { \ + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); \ + MOV32ItoM( (u32)&cpuRegs.pc, pc ); \ + iFlushCall(FLUSH_EVERYTHING); \ + CALLFunc( (u32)f ); \ + branch = 2; \ + } + +// used when processing branches +void SaveBranchState(); +void LoadBranchState(); + +void recompileNextInstruction(int delayslot); +void SetBranchReg( u32 reg ); +void SetBranchImm( u32 imm ); + +void iFlushCall(int flushtype); +void SaveCW(); +void LoadCW(); + +extern void (*recBSC[64])(); +extern void (*recSPC[64])(); +extern void (*recREG[32])(); +extern void (*recCP0[32])(); +extern void (*recCP0BC0[32])(); +extern void (*recCP0C0[64])(); +extern void (*recCP1[32])(); +extern void (*recCP1BC1[32])(); +extern void (*recCP1S[64])(); +extern void (*recCP1W[64])(); +extern void (*recMMIt[64])(); +extern void (*recMMI0t[32])(); +extern void (*recMMI1t[32])(); +extern void (*recMMI2t[32])(); +extern void (*recMMI3t[32])(); + +u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg + +void _eeFlushAllUnused(); +void _eeOnWriteReg(int reg, int signext); + +// totally deletes from const, xmm, and mmx entries +// if flush is 1, also flushes to memory +// if 0, only flushes if not an xmm reg (used when overwriting lower 64bits of reg) +void _deleteEEreg(int reg, int flush); + +// allocates memory on the instruction size and returns the pointer +void* recAllocStackMem(int size, int align); + +////////////////////////////////////// +// Templates for code recompilation // +////////////////////////////////////// +typedef void (*R5900FNPTR)(); +typedef void (*R5900FNPTR_INFO)(int info); + +#define EERECOMPILE_CODE0(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeRecompileCode0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_, xmminfo); \ +} \ + +#define EERECOMPILE_CODEX(codename, fn) \ +void rec##fn(void) \ +{ \ + codename(rec##fn##_const, rec##fn##_); \ +} \ + +// +// MMX/XMM caching helpers +// + +// rd = rs op rt +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo); +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rt op rs (SPECIAL) +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode); + +// +// non mmx/xmm version, slower +// +// rd = rs op rt +#define EERECOMPILE_CONSTCODE0(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst0(rec##fn##_const, rec##fn##_consts, rec##fn##_constt, rec##fn##_); \ +} \ + +// rt = rs op imm16 +#define EERECOMPILE_CONSTCODE1(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst1(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op sa +#define EERECOMPILE_CONSTCODE2(fn) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConst2(rec##fn##_const, rec##fn##_); \ +} \ + +// rd = rt op rs +#define EERECOMPILE_CONSTCODESPECIAL(fn, mult) \ +void rec##fn(void) \ +{ \ + eeRecompileCodeConstSPECIAL(rec##fn##_const, rec##fn##_, mult); \ +} \ + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode); +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode); +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT); + +// XMM caching helpers +#define XMMINFO_READLO 0x01 +#define XMMINFO_READHI 0x02 +#define XMMINFO_WRITELO 0x04 +#define XMMINFO_WRITEHI 0x08 +#define XMMINFO_WRITED 0x10 +#define XMMINFO_READD 0x20 +#define XMMINFO_READS 0x40 +#define XMMINFO_READT 0x80 +#define XMMINFO_READD_LO 0x100 // if set and XMMINFO_READD is set, reads only low 64 bits of D +#define XMMINFO_READACC 0x200 +#define XMMINFO_WRITEACC 0x400 + +#define CPU_SSE_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMDExtensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_SSE2_XMMCACHE_START(xmminfo) \ + if (cpucaps.hasStreamingSIMD2Extensions) \ + { \ + int info = eeRecompileCodeXMM(xmminfo); \ + +#define CPU_SSE_XMMCACHE_END \ + _clearNeededXMMregs(); \ + return; \ + } \ + +#ifdef __x86_64__ +#define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeFPURecompileCode(rec##fn##_xmm, NULL, xmminfo); \ +} +#else +#define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ +void rec##fn(void) \ +{ \ + eeFPURecompileCode(rec##fn##_xmm, rec##fn##_, xmminfo); \ +} +#endif + +// rd = rs op rt (all regs need to be in xmm) +int eeRecompileCodeXMM(int xmminfo); +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo); + +#endif // __IR5900_H__ diff --git a/pcsx2/x86/iR5900Arit.h b/pcsx2/x86/iR5900Arit.h new file mode 100644 index 0000000..5fcd64d --- /dev/null +++ b/pcsx2/x86/iR5900Arit.h @@ -0,0 +1,45 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARIT_H__ +#define __IR5900ARIT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +void recADD( void ); +void recADDU( void ); +void recDADD( void ); +void recDADDU( void ); +void recSUB( void ); +void recSUBU( void ); +void recDSUB( void ); +void recDSUBU( void ); +void recAND( void ); +void recOR( void ); +void recXOR( void ); +void recNOR( void ); +void recSLT( void ); +void recSLTU( void ); + +#endif diff --git a/pcsx2/x86/iR5900AritImm.h b/pcsx2/x86/iR5900AritImm.h new file mode 100644 index 0000000..4bd7a0c --- /dev/null +++ b/pcsx2/x86/iR5900AritImm.h @@ -0,0 +1,41 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900ARITIMM_H__ +#define __IR5900ARITIMM_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +void recADDI( void ); +void recADDIU( void ); +void recDADDI( void ); +void recDADDIU( void ); +void recANDI( void ); +void recORI( void ); +void recXORI( void ); + +void recSLTI( void ); +void recSLTIU( void ); + +#endif diff --git a/pcsx2/x86/iR5900Branch.h b/pcsx2/x86/iR5900Branch.h new file mode 100644 index 0000000..3370b8a --- /dev/null +++ b/pcsx2/x86/iR5900Branch.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900BRANCH_H__ +#define __IR5900BRANCH_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recBEQ( void ); +void recBEQL( void ); +void recBNE( void ); +void recBNEL( void ); +void recBLTZ( void ); +void recBLTZL( void ); +void recBLTZAL( void ); +void recBLTZALL( void ); +void recBGTZ( void ); +void recBGTZL( void ); +void recBLEZ( void ); +void recBLEZL( void ); +void recBGEZ( void ); +void recBGEZL( void ); +void recBGEZAL( void ); +void recBGEZALL( void ); + +#endif diff --git a/pcsx2/x86/iR5900Jump.h b/pcsx2/x86/iR5900Jump.h new file mode 100644 index 0000000..d35f87c --- /dev/null +++ b/pcsx2/x86/iR5900Jump.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900JUMP_H__ +#define __IR5900JUMP_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ + +void recJ( void ); +void recJAL( void ); +void recJR( void ); +void recJALR( void ); + +#endif diff --git a/pcsx2/x86/iR5900LoadStore.h b/pcsx2/x86/iR5900LoadStore.h new file mode 100644 index 0000000..50e29e8 --- /dev/null +++ b/pcsx2/x86/iR5900LoadStore.h @@ -0,0 +1,90 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900LOADSTORE_H__ +#define __IR5900LOADSTORE_H__ +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +void recLB( void ); +void recLBU( void ); +void recLH( void ); +void recLHU( void ); +void recLW( void ); +void recLWU( void ); +void recLWL( void ); +void recLWR( void ); +void recLD( void ); +void recLDR( void ); +void recLDL( void ); +void recLQ( void ); +void recSB( void ); +void recSH( void ); +void recSW( void ); +void recSWL( void ); +void recSWR( void ); +void recSD( void ); +void recSDL( void ); +void recSDR( void ); +void recSQ( void ); +void recLWC1( void ); +void recSWC1( void ); +void recLQC2( void ); +void recSQC2( void ); + +// coissues +#ifdef PCSX2_VIRTUAL_MEM +void recLB_co( void ); +void recLBU_co( void ); +void recLH_co( void ); +void recLHU_co( void ); +void recLW_co( void ); +void recLWU_co( void ); +void recLWL_co( void ); +void recLWR_co( void ); +void recLD_co( void ); +void recLDR_co( void ); +void recLDL_co( void ); +void recLQ_co( void ); +void recSB_co( void ); +void recSH_co( void ); +void recSW_co( void ); +void recSWL_co( void ); +void recSWR_co( void ); +void recSD_co( void ); +void recSDL_co( void ); +void recSDR_co( void ); +void recSQ_co( void ); +void recLWC1_co( void ); +void recSWC1_co( void ); +void recLQC2_co( void ); +void recSQC2_co( void ); + +// coissue-X +void recLD_coX(int num); +void recLQ_coX(int num); +void recLWC1_coX(int num); +void recSD_coX(int num); +void recSQ_coX(int num); +void recSWC1_coX(int num); + +#endif + +#endif diff --git a/pcsx2/x86/iR5900Move.h b/pcsx2/x86/iR5900Move.h new file mode 100644 index 0000000..ae501e3 --- /dev/null +++ b/pcsx2/x86/iR5900Move.h @@ -0,0 +1,33 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MOVE_H__ +#define __IR5900MOVE_H__ + +#include "Common.h" +#include "InterTables.h" + +void recLUI( void ); +void recMFLO( void ); +void recMFHI( void ); +void recMTLO( void ); +void recMTHI( void ); +void recMOVN( void ); +void recMOVZ( void ); + +#endif diff --git a/pcsx2/x86/iR5900MultDiv.h b/pcsx2/x86/iR5900MultDiv.h new file mode 100644 index 0000000..243fd5c --- /dev/null +++ b/pcsx2/x86/iR5900MultDiv.h @@ -0,0 +1,35 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900MULTDIV_H__ +#define __IR5900MULTDIV_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ + +void recMULT( void ); +void recMULTU( void ); +void recDIV( void ); +void recDIVU( void ); + +#endif diff --git a/pcsx2/x86/iR5900Shift.h b/pcsx2/x86/iR5900Shift.h new file mode 100644 index 0000000..b7b3592 --- /dev/null +++ b/pcsx2/x86/iR5900Shift.h @@ -0,0 +1,47 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IR5900SHIFT_H__ +#define __IR5900SHIFT_H__ + +#include "Common.h" +#include "InterTables.h" + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ + +void recSLL( void ); +void recSRL( void ); +void recSRA( void ); +void recDSLL( void ); +void recDSRL( void ); +void recDSRA( void ); +void recDSLL32( void ); +void recDSRL32( void ); +void recDSRA32( void ); + +void recSLLV( void ); +void recSRLV( void ); +void recSRAV( void ); +void recDSLLV( void ); +void recDSRLV( void ); +void recDSRAV( void ); + +#endif diff --git a/pcsx2/x86/iVU0micro.c b/pcsx2/x86/iVU0micro.c new file mode 100644 index 0000000..9aa999c --- /dev/null +++ b/pcsx2/x86/iVU0micro.c @@ -0,0 +1,777 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +static VURegs * const VU = (VURegs*)&VU0; + +//u32 vu0time = 0; +//static LARGE_INTEGER vu0base, vu0final; + +#ifdef PCSX2_DEVBUILD +extern u32 vudump; +#endif + +static u32 vuprogcount = 0; + +void recExecuteVU0Block( void ) +{ + //SysPrintf("executeVU0 %x\n", VU0.VI[ REG_TPC ].UL); + //QueryPerformanceCounter(&vu0base); + + assert( VU0.VI[REG_VPU_STAT].UL & 1 ); + +#ifdef _DEBUG + vuprogcount++; + +// __Log("VU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); + + //vudump |= 0x10; + //vudump |= 0x80; + + if( (vudump&0x80) && !CHECK_VU0REC ) { + __Log("tVU: %x\n", VU0.VI[ REG_TPC ].UL); + iDumpVU0Registers(); + } +#endif + + //while( (VU0.VI[ REG_VPU_STAT ].UL&1) ) { + if( CHECK_VU0REC) { + FreezeXMMRegs(1); + SuperVUExecuteProgram(VU0.VI[ REG_TPC ].UL&0xfff, 0); + } + else { + intExecuteVU0Block(); + } + //} + +// __Log("eVU: %x %x\n", VU0.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU0Registers(); +// QueryPerformanceCounter(&vu0final); +// vu0time += (u32)(vu0final.QuadPart-vu0final.QuadPart); +} + +void recClearVU0( u32 Addr, u32 Size ) +{ + if( CHECK_VU0REC ) { + SuperVUClear(Addr, Size*4, 0); + } +} + +void (*recVU0_LOWER_OPCODE[128])() = { + recVU0MI_LQ , recVU0MI_SQ , recVU0unknown , recVU0unknown, + recVU0MI_ILW , recVU0MI_ISW , recVU0unknown , recVU0unknown, + recVU0MI_IADDIU, recVU0MI_ISUBIU, recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_FCEQ , recVU0MI_FCSET , recVU0MI_FCAND, recVU0MI_FCOR, /* 0x10 */ + recVU0MI_FSEQ , recVU0MI_FSSET , recVU0MI_FSAND, recVU0MI_FSOR, + recVU0MI_FMEQ , recVU0unknown , recVU0MI_FMAND, recVU0MI_FMOR, + recVU0MI_FCGET , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_B , recVU0MI_BAL , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0MI_JR , recVU0MI_JALR , recVU0unknown , recVU0unknown, + recVU0MI_IBEQ , recVU0MI_IBNE , recVU0unknown , recVU0unknown, + recVU0MI_IBLTZ , recVU0MI_IBGTZ , recVU0MI_IBLEZ, recVU0MI_IBGEZ, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x40*/ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x50 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x60 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x70 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, +}; + +void (*recVU0LowerOP_T3_00_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MOVE , recVU0MI_LQI , recVU0MI_DIV , recVU0MI_MTIR, + recVU0MI_RNEXT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_MFP , recVU0unknown , recVU0unknown, + recVU0MI_ESADD , recVU0MI_EATANxy, recVU0MI_ESQRT, recVU0MI_ESIN, +}; + +void (*recVU0LowerOP_T3_01_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_MR32 , recVU0MI_SQI , recVU0MI_SQRT , recVU0MI_MFIR, + recVU0MI_RGET , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0MI_XITOP, recVU0unknown, + recVU0MI_ERSADD, recVU0MI_EATANxz, recVU0MI_ERSQRT, recVU0MI_EATAN, +}; + +void (*recVU0LowerOP_T3_10_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_LQD , recVU0MI_RSQRT, recVU0MI_ILWR, + recVU0MI_RINIT , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ELENG , recVU0MI_ESUM , recVU0MI_ERCPR, recVU0MI_EEXP, +}; + +void (*recVU0LowerOP_T3_11_OPCODE[32])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0MI_SQD , recVU0MI_WAITQ, recVU0MI_ISWR, + recVU0MI_RXOR , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_ERLENG, recVU0unknown , recVU0MI_WAITP, recVU0unknown, +}; + +void (*recVU0LowerOP_OPCODE[64])() = { + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x10 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x20 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0MI_IADD , recVU0MI_ISUB , recVU0MI_IADDI, recVU0unknown, /* 0x30 */ + recVU0MI_IAND , recVU0MI_IOR , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0LowerOP_T3_00, recVU0LowerOP_T3_01, recVU0LowerOP_T3_10, recVU0LowerOP_T3_11, +}; + +void (*recVU0_UPPER_OPCODE[64])() = { + recVU0MI_ADDx , recVU0MI_ADDy , recVU0MI_ADDz , recVU0MI_ADDw, + recVU0MI_SUBx , recVU0MI_SUBy , recVU0MI_SUBz , recVU0MI_SUBw, + recVU0MI_MADDx , recVU0MI_MADDy , recVU0MI_MADDz , recVU0MI_MADDw, + recVU0MI_MSUBx , recVU0MI_MSUBy , recVU0MI_MSUBz , recVU0MI_MSUBw, + recVU0MI_MAXx , recVU0MI_MAXy , recVU0MI_MAXz , recVU0MI_MAXw, /* 0x10 */ + recVU0MI_MINIx , recVU0MI_MINIy , recVU0MI_MINIz , recVU0MI_MINIw, + recVU0MI_MULx , recVU0MI_MULy , recVU0MI_MULz , recVU0MI_MULw, + recVU0MI_MULq , recVU0MI_MAXi , recVU0MI_MULi , recVU0MI_MINIi, + recVU0MI_ADDq , recVU0MI_MADDq , recVU0MI_ADDi , recVU0MI_MADDi, /* 0x20 */ + recVU0MI_SUBq , recVU0MI_MSUBq , recVU0MI_SUBi , recVU0MI_MSUBi, + recVU0MI_ADD , recVU0MI_MADD , recVU0MI_MUL , recVU0MI_MAX, + recVU0MI_SUB , recVU0MI_MSUB , recVU0MI_OPMSUB, recVU0MI_MINI, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, /* 0x30 */ + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown, + recVU0_UPPER_FD_00, recVU0_UPPER_FD_01, recVU0_UPPER_FD_10, recVU0_UPPER_FD_11, +}; + +void (*recVU0_UPPER_FD_00_TABLE[32])() = { + recVU0MI_ADDAx, recVU0MI_SUBAx , recVU0MI_MADDAx, recVU0MI_MSUBAx, + recVU0MI_ITOF0, recVU0MI_FTOI0, recVU0MI_MULAx , recVU0MI_MULAq , + recVU0MI_ADDAq, recVU0MI_SUBAq, recVU0MI_ADDA , recVU0MI_SUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_01_TABLE[32])() = { + recVU0MI_ADDAy , recVU0MI_SUBAy , recVU0MI_MADDAy, recVU0MI_MSUBAy, + recVU0MI_ITOF4 , recVU0MI_FTOI4 , recVU0MI_MULAy , recVU0MI_ABS , + recVU0MI_MADDAq, recVU0MI_MSUBAq, recVU0MI_MADDA , recVU0MI_MSUBA , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_10_TABLE[32])() = { + recVU0MI_ADDAz , recVU0MI_SUBAz , recVU0MI_MADDAz, recVU0MI_MSUBAz, + recVU0MI_ITOF12, recVU0MI_FTOI12, recVU0MI_MULAz , recVU0MI_MULAi , + recVU0MI_ADDAi, recVU0MI_SUBAi , recVU0MI_MULA , recVU0MI_OPMULA, + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void (*recVU0_UPPER_FD_11_TABLE[32])() = { + recVU0MI_ADDAw , recVU0MI_SUBAw , recVU0MI_MADDAw, recVU0MI_MSUBAw, + recVU0MI_ITOF15, recVU0MI_FTOI15, recVU0MI_MULAw , recVU0MI_CLIP , + recVU0MI_MADDAi, recVU0MI_MSUBAi, recVU0unknown , recVU0MI_NOP , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , + recVU0unknown , recVU0unknown , recVU0unknown , recVU0unknown , +}; + +void recVU0_UPPER_FD_00( void ) +{ + recVU0_UPPER_FD_00_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_01( void ) +{ + recVU0_UPPER_FD_01_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_10( void ) +{ + recVU0_UPPER_FD_10_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0_UPPER_FD_11( void ) +{ + recVU0_UPPER_FD_11_TABLE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP( void ) +{ + recVU0LowerOP_OPCODE[ VU0.code & 0x3f ]( ); +} + +void recVU0LowerOP_T3_00( void ) +{ + recVU0LowerOP_T3_00_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_01( void ) +{ + recVU0LowerOP_T3_01_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_10( void ) +{ + recVU0LowerOP_T3_10_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + +void recVU0LowerOP_T3_11( void ) +{ + recVU0LowerOP_T3_11_OPCODE[ ( VU0.code >> 6 ) & 0x1f ]( ); +} + + +void recVU0unknown( void ) +{ +#ifdef CPU_LOG + CPU_LOG("Unknown VU0 micromode opcode calledn"); +#endif +} + + + +/****************************************/ +/* VU Micromode Upper instructions */ +/****************************************/ + +#ifdef RECOMPILE_VUMI_ABS +void recVU0MI_ABS() { recVUMI_ABS(VU, VUREC_INFO); } +#else +void recVU0MI_ABS() { REC_VUOP(VU0, ABS); } +#endif + +#ifdef RECOMPILE_VUMI_ADD +void recVU0MI_ADD() { recVUMI_ADD(VU, VUREC_INFO); } +void recVU0MI_ADDi() { recVUMI_ADDi(VU, VUREC_INFO); } +void recVU0MI_ADDq() { recVUMI_ADDq(VU, VUREC_INFO); } +void recVU0MI_ADDx() { recVUMI_ADDx(VU, VUREC_INFO); } +void recVU0MI_ADDy() { recVUMI_ADDy(VU, VUREC_INFO); } +void recVU0MI_ADDz() { recVUMI_ADDz(VU, VUREC_INFO); } +void recVU0MI_ADDw() { recVUMI_ADDw(VU, VUREC_INFO); } +#else +void recVU0MI_ADD() { REC_VUOP(VU0, ADD); } +void recVU0MI_ADDi() { REC_VUOP(VU0, ADDi); } +void recVU0MI_ADDq() { REC_VUOP(VU0, ADDq); } +void recVU0MI_ADDx() { REC_VUOP(VU0, ADDx); } +void recVU0MI_ADDy() { REC_VUOP(VU0, ADDy); } +void recVU0MI_ADDz() { REC_VUOP(VU0, ADDz); } +void recVU0MI_ADDw() { REC_VUOP(VU0, ADDw); } +#endif + +#ifdef RECOMPILE_VUMI_ADDA +void recVU0MI_ADDA() { recVUMI_ADDA(VU, VUREC_INFO); } +void recVU0MI_ADDAi() { recVUMI_ADDAi(VU, VUREC_INFO); } +void recVU0MI_ADDAq() { recVUMI_ADDAq(VU, VUREC_INFO); } +void recVU0MI_ADDAx() { recVUMI_ADDAx(VU, VUREC_INFO); } +void recVU0MI_ADDAy() { recVUMI_ADDAy(VU, VUREC_INFO); } +void recVU0MI_ADDAz() { recVUMI_ADDAz(VU, VUREC_INFO); } +void recVU0MI_ADDAw() { recVUMI_ADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_ADDA() { REC_VUOP(VU0, ADDA); } +void recVU0MI_ADDAi() { REC_VUOP(VU0, ADDAi); } +void recVU0MI_ADDAq() { REC_VUOP(VU0, ADDAq); } +void recVU0MI_ADDAx() { REC_VUOP(VU0, ADDAx); } +void recVU0MI_ADDAy() { REC_VUOP(VU0, ADDAy); } +void recVU0MI_ADDAz() { REC_VUOP(VU0, ADDAz); } +void recVU0MI_ADDAw() { REC_VUOP(VU0, ADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_SUB +void recVU0MI_SUB() { recVUMI_SUB(VU, VUREC_INFO); } +void recVU0MI_SUBi() { recVUMI_SUBi(VU, VUREC_INFO); } +void recVU0MI_SUBq() { recVUMI_SUBq(VU, VUREC_INFO); } +void recVU0MI_SUBx() { recVUMI_SUBx(VU, VUREC_INFO); } +void recVU0MI_SUBy() { recVUMI_SUBy(VU, VUREC_INFO); } +void recVU0MI_SUBz() { recVUMI_SUBz(VU, VUREC_INFO); } +void recVU0MI_SUBw() { recVUMI_SUBw(VU, VUREC_INFO); } +#else +void recVU0MI_SUB() { REC_VUOP(VU0, SUB); } +void recVU0MI_SUBi() { REC_VUOP(VU0, SUBi); } +void recVU0MI_SUBq() { REC_VUOP(VU0, SUBq); } +void recVU0MI_SUBx() { REC_VUOP(VU0, SUBx); } +void recVU0MI_SUBy() { REC_VUOP(VU0, SUBy); } +void recVU0MI_SUBz() { REC_VUOP(VU0, SUBz); } +void recVU0MI_SUBw() { REC_VUOP(VU0, SUBw); } +#endif + +#ifdef RECOMPILE_VUMI_SUBA +void recVU0MI_SUBA() { recVUMI_SUBA(VU, VUREC_INFO); } +void recVU0MI_SUBAi() { recVUMI_SUBAi(VU, VUREC_INFO); } +void recVU0MI_SUBAq() { recVUMI_SUBAq(VU, VUREC_INFO); } +void recVU0MI_SUBAx() { recVUMI_SUBAx(VU, VUREC_INFO); } +void recVU0MI_SUBAy() { recVUMI_SUBAy(VU, VUREC_INFO); } +void recVU0MI_SUBAz() { recVUMI_SUBAz(VU, VUREC_INFO); } +void recVU0MI_SUBAw() { recVUMI_SUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_SUBA() { REC_VUOP(VU0, SUBA); } +void recVU0MI_SUBAi() { REC_VUOP(VU0, SUBAi); } +void recVU0MI_SUBAq() { REC_VUOP(VU0, SUBAq); } +void recVU0MI_SUBAx() { REC_VUOP(VU0, SUBAx); } +void recVU0MI_SUBAy() { REC_VUOP(VU0, SUBAy); } +void recVU0MI_SUBAz() { REC_VUOP(VU0, SUBAz); } +void recVU0MI_SUBAw() { REC_VUOP(VU0, SUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MUL +void recVU0MI_MUL() { recVUMI_MUL(VU, VUREC_INFO); } +void recVU0MI_MULi() { recVUMI_MULi(VU, VUREC_INFO); } +void recVU0MI_MULq() { recVUMI_MULq(VU, VUREC_INFO); } +void recVU0MI_MULx() { recVUMI_MULx(VU, VUREC_INFO); } +void recVU0MI_MULy() { recVUMI_MULy(VU, VUREC_INFO); } +void recVU0MI_MULz() { recVUMI_MULz(VU, VUREC_INFO); } +void recVU0MI_MULw() { recVUMI_MULw(VU, VUREC_INFO); } +#else +void recVU0MI_MUL() { REC_VUOP(VU0, MUL); } +void recVU0MI_MULi() { REC_VUOP(VU0, MULi); } +void recVU0MI_MULq() { REC_VUOP(VU0, MULq); } +void recVU0MI_MULx() { REC_VUOP(VU0, MULx); } +void recVU0MI_MULy() { REC_VUOP(VU0, MULy); } +void recVU0MI_MULz() { REC_VUOP(VU0, MULz); } +void recVU0MI_MULw() { REC_VUOP(VU0, MULw); } +#endif + +#ifdef RECOMPILE_VUMI_MULA +void recVU0MI_MULA() { recVUMI_MULA(VU, VUREC_INFO); } +void recVU0MI_MULAi() { recVUMI_MULAi(VU, VUREC_INFO); } +void recVU0MI_MULAq() { recVUMI_MULAq(VU, VUREC_INFO); } +void recVU0MI_MULAx() { recVUMI_MULAx(VU, VUREC_INFO); } +void recVU0MI_MULAy() { recVUMI_MULAy(VU, VUREC_INFO); } +void recVU0MI_MULAz() { recVUMI_MULAz(VU, VUREC_INFO); } +void recVU0MI_MULAw() { recVUMI_MULAw(VU, VUREC_INFO); } +#else +void recVU0MI_MULA() { REC_VUOP(VU0, MULA); } +void recVU0MI_MULAi() { REC_VUOP(VU0, MULAi); } +void recVU0MI_MULAq() { REC_VUOP(VU0, MULAq); } +void recVU0MI_MULAx() { REC_VUOP(VU0, MULAx); } +void recVU0MI_MULAy() { REC_VUOP(VU0, MULAy); } +void recVU0MI_MULAz() { REC_VUOP(VU0, MULAz); } +void recVU0MI_MULAw() { REC_VUOP(VU0, MULAw); } +#endif + +#ifdef RECOMPILE_VUMI_MADD +void recVU0MI_MADD() { recVUMI_MADD(VU, VUREC_INFO); } +void recVU0MI_MADDi() { recVUMI_MADDi(VU, VUREC_INFO); } +void recVU0MI_MADDq() { recVUMI_MADDq(VU, VUREC_INFO); } +void recVU0MI_MADDx() { recVUMI_MADDx(VU, VUREC_INFO); } +void recVU0MI_MADDy() { recVUMI_MADDy(VU, VUREC_INFO); } +void recVU0MI_MADDz() { recVUMI_MADDz(VU, VUREC_INFO); } +void recVU0MI_MADDw() { recVUMI_MADDw(VU, VUREC_INFO); } +#else +void recVU0MI_MADD() { REC_VUOP(VU0, MADD); } +void recVU0MI_MADDi() { REC_VUOP(VU0, MADDi); } +void recVU0MI_MADDq() { REC_VUOP(VU0, MADDq); } +void recVU0MI_MADDx() { REC_VUOP(VU0, MADDx); } +void recVU0MI_MADDy() { REC_VUOP(VU0, MADDy); } +void recVU0MI_MADDz() { REC_VUOP(VU0, MADDz); } +void recVU0MI_MADDw() { REC_VUOP(VU0, MADDw); } +#endif + +#ifdef RECOMPILE_VUMI_MADDA +void recVU0MI_MADDA() { recVUMI_MADDA(VU, VUREC_INFO); } +void recVU0MI_MADDAi() { recVUMI_MADDAi(VU, VUREC_INFO); } +void recVU0MI_MADDAq() { recVUMI_MADDAq(VU, VUREC_INFO); } +void recVU0MI_MADDAx() { recVUMI_MADDAx(VU, VUREC_INFO); } +void recVU0MI_MADDAy() { recVUMI_MADDAy(VU, VUREC_INFO); } +void recVU0MI_MADDAz() { recVUMI_MADDAz(VU, VUREC_INFO); } +void recVU0MI_MADDAw() { recVUMI_MADDAw(VU, VUREC_INFO); } +#else +void recVU0MI_MADDA() { REC_VUOP(VU0, MADDA); } +void recVU0MI_MADDAi() { REC_VUOP(VU0, MADDAi); } +void recVU0MI_MADDAq() { REC_VUOP(VU0, MADDAq); } +void recVU0MI_MADDAx() { REC_VUOP(VU0, MADDAx); } +void recVU0MI_MADDAy() { REC_VUOP(VU0, MADDAy); } +void recVU0MI_MADDAz() { REC_VUOP(VU0, MADDAz); } +void recVU0MI_MADDAw() { REC_VUOP(VU0, MADDAw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUB +void recVU0MI_MSUB() { recVUMI_MSUB(VU, VUREC_INFO); } +void recVU0MI_MSUBi() { recVUMI_MSUBi(VU, VUREC_INFO); } +void recVU0MI_MSUBq() { recVUMI_MSUBq(VU, VUREC_INFO); } +void recVU0MI_MSUBx() { recVUMI_MSUBx(VU, VUREC_INFO); } +void recVU0MI_MSUBy() { recVUMI_MSUBy(VU, VUREC_INFO); } +void recVU0MI_MSUBz() { recVUMI_MSUBz(VU, VUREC_INFO); } +void recVU0MI_MSUBw() { recVUMI_MSUBw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUB() { REC_VUOP(VU0, MSUB); } +void recVU0MI_MSUBi() { REC_VUOP(VU0, MSUBi); } +void recVU0MI_MSUBq() { REC_VUOP(VU0, MSUBq); } +void recVU0MI_MSUBx() { REC_VUOP(VU0, MSUBx); } +void recVU0MI_MSUBy() { REC_VUOP(VU0, MSUBy); } +void recVU0MI_MSUBz() { REC_VUOP(VU0, MSUBz); } +void recVU0MI_MSUBw() { REC_VUOP(VU0, MSUBw); } +#endif + +#ifdef RECOMPILE_VUMI_MSUBA +void recVU0MI_MSUBA() { recVUMI_MSUBA(VU, VUREC_INFO); } +void recVU0MI_MSUBAi() { recVUMI_MSUBAi(VU, VUREC_INFO); } +void recVU0MI_MSUBAq() { recVUMI_MSUBAq(VU, VUREC_INFO); } +void recVU0MI_MSUBAx() { recVUMI_MSUBAx(VU, VUREC_INFO); } +void recVU0MI_MSUBAy() { recVUMI_MSUBAy(VU, VUREC_INFO); } +void recVU0MI_MSUBAz() { recVUMI_MSUBAz(VU, VUREC_INFO); } +void recVU0MI_MSUBAw() { recVUMI_MSUBAw(VU, VUREC_INFO); } +#else +void recVU0MI_MSUBA() { REC_VUOP(VU0, MSUBA); } +void recVU0MI_MSUBAi() { REC_VUOP(VU0, MSUBAi); } +void recVU0MI_MSUBAq() { REC_VUOP(VU0, MSUBAq); } +void recVU0MI_MSUBAx() { REC_VUOP(VU0, MSUBAx); } +void recVU0MI_MSUBAy() { REC_VUOP(VU0, MSUBAy); } +void recVU0MI_MSUBAz() { REC_VUOP(VU0, MSUBAz); } +void recVU0MI_MSUBAw() { REC_VUOP(VU0, MSUBAw); } +#endif + +#ifdef RECOMPILE_VUMI_MAX +void recVU0MI_MAX() { recVUMI_MAX(VU, VUREC_INFO); } +void recVU0MI_MAXi() { recVUMI_MAXi(VU, VUREC_INFO); } +void recVU0MI_MAXx() { recVUMI_MAXx(VU, VUREC_INFO); } +void recVU0MI_MAXy() { recVUMI_MAXy(VU, VUREC_INFO); } +void recVU0MI_MAXz() { recVUMI_MAXz(VU, VUREC_INFO); } +void recVU0MI_MAXw() { recVUMI_MAXw(VU, VUREC_INFO); } +#else +void recVU0MI_MAX() { REC_VUOP(VU0, MAX); } +void recVU0MI_MAXi() { REC_VUOP(VU0, MAXi); } +void recVU0MI_MAXx() { REC_VUOP(VU0, MAXx); } +void recVU0MI_MAXy() { REC_VUOP(VU0, MAXy); } +void recVU0MI_MAXz() { REC_VUOP(VU0, MAXz); } +void recVU0MI_MAXw() { REC_VUOP(VU0, MAXw); } +#endif + +#ifdef RECOMPILE_VUMI_MINI +void recVU0MI_MINI() { recVUMI_MINI(VU, VUREC_INFO); } +void recVU0MI_MINIi() { recVUMI_MINIi(VU, VUREC_INFO); } +void recVU0MI_MINIx() { recVUMI_MINIx(VU, VUREC_INFO); } +void recVU0MI_MINIy() { recVUMI_MINIy(VU, VUREC_INFO); } +void recVU0MI_MINIz() { recVUMI_MINIz(VU, VUREC_INFO); } +void recVU0MI_MINIw() { recVUMI_MINIw(VU, VUREC_INFO); } +#else +void recVU0MI_MINI() { REC_VUOP(VU0, MINI); } +void recVU0MI_MINIi() { REC_VUOP(VU0, MINIi); } +void recVU0MI_MINIx() { REC_VUOP(VU0, MINIx); } +void recVU0MI_MINIy() { REC_VUOP(VU0, MINIy); } +void recVU0MI_MINIz() { REC_VUOP(VU0, MINIz); } +void recVU0MI_MINIw() { REC_VUOP(VU0, MINIw); } +#endif + +#ifdef RECOMPILE_VUMI_FTOI +void recVU0MI_FTOI0() { recVUMI_FTOI0(VU, VUREC_INFO); } +void recVU0MI_FTOI4() { recVUMI_FTOI4(VU, VUREC_INFO); } +void recVU0MI_FTOI12() { recVUMI_FTOI12(VU, VUREC_INFO); } +void recVU0MI_FTOI15() { recVUMI_FTOI15(VU, VUREC_INFO); } +void recVU0MI_ITOF0() { recVUMI_ITOF0(VU, VUREC_INFO); } +void recVU0MI_ITOF4() { recVUMI_ITOF4(VU, VUREC_INFO); } +void recVU0MI_ITOF12() { recVUMI_ITOF12(VU, VUREC_INFO); } +void recVU0MI_ITOF15() { recVUMI_ITOF15(VU, VUREC_INFO); } +#else +void recVU0MI_FTOI0() { REC_VUOP(VU0, FTOI0); } +void recVU0MI_FTOI4() { REC_VUOP(VU0, FTOI4); } +void recVU0MI_FTOI12() { REC_VUOP(VU0, FTOI12); } +void recVU0MI_FTOI15() { REC_VUOP(VU0, FTOI15); } +void recVU0MI_ITOF0() { REC_VUOP(VU0, ITOF0); } +void recVU0MI_ITOF4() { REC_VUOP(VU0, ITOF4); } +void recVU0MI_ITOF12() { REC_VUOP(VU0, ITOF12); } +void recVU0MI_ITOF15() { REC_VUOP(VU0, ITOF15); } +#endif + +void recVU0MI_OPMULA() { recVUMI_OPMULA(VU, VUREC_INFO); } +void recVU0MI_OPMSUB() { recVUMI_OPMSUB(VU, VUREC_INFO); } +void recVU0MI_NOP() { } +void recVU0MI_CLIP() { recVUMI_CLIP(VU, VUREC_INFO); } + +/*****************************************/ +/* VU Micromode Lower instructions */ +/*****************************************/ + +#ifdef RECOMPILE_VUMI_MISC + +void recVU0MI_MTIR() { recVUMI_MTIR(VU, VUREC_INFO); } +void recVU0MI_MR32() { recVUMI_MR32(VU, VUREC_INFO); } +void recVU0MI_MFIR() { recVUMI_MFIR(VU, VUREC_INFO); } +void recVU0MI_MOVE() { recVUMI_MOVE(VU, VUREC_INFO); } +void recVU0MI_WAITQ() { recVUMI_WAITQ(VU, VUREC_INFO); } +void recVU0MI_MFP() { recVUMI_MFP(VU, VUREC_INFO); } +void recVU0MI_WAITP() { SysPrintf("vu0 wait p?\n"); } + +#else + +void recVU0MI_MOVE() { REC_VUOP(VU0, MOVE); } +void recVU0MI_MFIR() { REC_VUOP(VU0, MFIR); } +void recVU0MI_MTIR() { REC_VUOP(VU0, MTIR); } +void recVU0MI_MR32() { REC_VUOP(VU0, MR32); } +void recVU0MI_WAITQ() { } +void recVU0MI_MFP() { REC_VUOP(VU0, MFP); } +void recVU0MI_WAITP() { REC_VUOP(VU0, WAITP); } + +#endif + +#ifdef RECOMPILE_VUMI_MATH + +void recVU0MI_SQRT() { recVUMI_SQRT(VU, VUREC_INFO); } +void recVU0MI_RSQRT() { recVUMI_RSQRT(VU, VUREC_INFO); } +void recVU0MI_DIV() { recVUMI_DIV(VU, VUREC_INFO); } + +#else + +void recVU0MI_DIV() { REC_VUOP(VU0, DIV);} +void recVU0MI_SQRT() { REC_VUOP(VU0, SQRT); } +void recVU0MI_RSQRT() { REC_VUOP(VU0, RSQRT); } + +#endif + +#ifdef RECOMPILE_VUMI_E + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { recVUMI_ELENG(VU, VUREC_INFO); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#else + +void recVU0MI_ESADD() { REC_VUOP(VU0, ESADD); } +void recVU0MI_ERSADD() { REC_VUOP(VU0, ERSADD); } +void recVU0MI_ELENG() { REC_VUOP(VU0, ELENG); } +void recVU0MI_ERLENG() { REC_VUOP(VU0, ERLENG); } +void recVU0MI_EATANxy() { REC_VUOP(VU0, EATANxy); } +void recVU0MI_EATANxz() { REC_VUOP(VU0, EATANxz); } +void recVU0MI_ESUM() { REC_VUOP(VU0, ESUM); } +void recVU0MI_ERCPR() { REC_VUOP(VU0, ERCPR); } +void recVU0MI_ESQRT() { REC_VUOP(VU0, ESQRT); } +void recVU0MI_ERSQRT() { REC_VUOP(VU0, ERSQRT); } +void recVU0MI_ESIN() { REC_VUOP(VU0, ESIN); } +void recVU0MI_EATAN() { REC_VUOP(VU0, EATAN); } +void recVU0MI_EEXP() { REC_VUOP(VU0, EEXP); } + +#endif + +#ifdef RECOMPILE_VUMI_X + +void recVU0MI_XITOP() { recVUMI_XITOP(VU, VUREC_INFO); } +void recVU0MI_XGKICK() { recVUMI_XGKICK(VU, VUREC_INFO); } +void recVU0MI_XTOP() { recVUMI_XTOP(VU, VUREC_INFO); } + +#else + +void recVU0MI_XITOP() { REC_VUOP(VU0, XITOP); } +void recVU0MI_XGKICK() { REC_VUOP(VU0, XGKICK);} +void recVU0MI_XTOP() { REC_VUOP(VU0, XTOP);} + +#endif + +#ifdef RECOMPILE_VUMI_RANDOM + +void recVU0MI_RINIT() { recVUMI_RINIT(VU, VUREC_INFO); } +void recVU0MI_RGET() { recVUMI_RGET(VU, VUREC_INFO); } +void recVU0MI_RNEXT() { recVUMI_RNEXT(VU, VUREC_INFO); } +void recVU0MI_RXOR() { recVUMI_RXOR(VU, VUREC_INFO); } + +#else + +void recVU0MI_RINIT() { REC_VUOP(VU0, RINIT); } +void recVU0MI_RGET() { REC_VUOP(VU0, RGET); } +void recVU0MI_RNEXT() { REC_VUOP(VU0, RNEXT); } +void recVU0MI_RXOR() { REC_VUOP(VU0, RXOR); } + +#endif + +#ifdef RECOMPILE_VUMI_FLAG + +void recVU0MI_FSAND() { recVUMI_FSAND(VU, VUREC_INFO); } +void recVU0MI_FSEQ() { recVUMI_FSEQ(VU, VUREC_INFO); } +void recVU0MI_FSOR() { recVUMI_FSOR(VU, VUREC_INFO); } +void recVU0MI_FSSET() { recVUMI_FSSET(VU, VUREC_INFO); } +void recVU0MI_FMEQ() { recVUMI_FMEQ(VU, VUREC_INFO); } +void recVU0MI_FMOR() { recVUMI_FMOR(VU, VUREC_INFO); } +void recVU0MI_FCEQ() { recVUMI_FCEQ(VU, VUREC_INFO); } +void recVU0MI_FCOR() { recVUMI_FCOR(VU, VUREC_INFO); } +void recVU0MI_FCSET() { recVUMI_FCSET(VU, VUREC_INFO); } +void recVU0MI_FCGET() { recVUMI_FCGET(VU, VUREC_INFO); } +void recVU0MI_FCAND() { recVUMI_FCAND(VU, VUREC_INFO); } +void recVU0MI_FMAND() { recVUMI_FMAND(VU, VUREC_INFO); } + +#else + +void recVU0MI_FSAND() { REC_VUOP(VU0, FSAND); } +void recVU0MI_FSEQ() { REC_VUOP(VU0, FSEQ); } +void recVU0MI_FSOR() { REC_VUOP(VU0, FSOR); } +void recVU0MI_FSSET() { REC_VUOP(VU0, FSSET); } +void recVU0MI_FMAND() { REC_VUOP(VU0, FMAND); } +void recVU0MI_FMEQ() { REC_VUOP(VU0, FMEQ); } +void recVU0MI_FMOR() { REC_VUOP(VU0, FMOR); } +void recVU0MI_FCAND() { REC_VUOP(VU0, FCAND); } +void recVU0MI_FCEQ() { REC_VUOP(VU0, FCEQ); } +void recVU0MI_FCOR() { REC_VUOP(VU0, FCOR); } +void recVU0MI_FCSET() { REC_VUOP(VU0, FCSET); } +void recVU0MI_FCGET() { REC_VUOP(VU0, FCGET); } + +#endif + +#ifdef RECOMPILE_VUMI_LOADSTORE + +void recVU0MI_LQ() { recVUMI_LQ(VU, VUREC_INFO); } +void recVU0MI_LQD() { recVUMI_LQD(VU, VUREC_INFO); } +void recVU0MI_LQI() { recVUMI_LQI(VU, VUREC_INFO); } +void recVU0MI_SQ() { recVUMI_SQ(VU, VUREC_INFO); } +void recVU0MI_SQD() { recVUMI_SQD(VU, VUREC_INFO); } +void recVU0MI_SQI() { recVUMI_SQI(VU, VUREC_INFO); } +void recVU0MI_ILW() { recVUMI_ILW(VU, VUREC_INFO); } +void recVU0MI_ISW() { recVUMI_ISW(VU, VUREC_INFO); } +void recVU0MI_ILWR() { recVUMI_ILWR(VU, VUREC_INFO); } +void recVU0MI_ISWR() { recVUMI_ISWR(VU, VUREC_INFO); } + +#else + +void recVU0MI_LQ() { REC_VUOP(VU0, LQ); } +void recVU0MI_LQD() { REC_VUOP(VU0, LQD); } +void recVU0MI_LQI() { REC_VUOP(VU0, LQI); } +void recVU0MI_SQ() { REC_VUOP(VU0, SQ); } +void recVU0MI_SQD() { REC_VUOP(VU0, SQD); } +void recVU0MI_SQI() { REC_VUOP(VU0, SQI); } +void recVU0MI_ILW() { REC_VUOP(VU0, ILW); } +void recVU0MI_ISW() { REC_VUOP(VU0, ISW); } +void recVU0MI_ILWR() { REC_VUOP(VU0, ILWR); } +void recVU0MI_ISWR() { REC_VUOP(VU0, ISWR); } + +#endif + +#ifdef RECOMPILE_VUMI_ARITHMETIC + +void recVU0MI_IADD() { recVUMI_IADD(VU, VUREC_INFO); } +void recVU0MI_IADDI() { recVUMI_IADDI(VU, VUREC_INFO); } +void recVU0MI_IADDIU() { recVUMI_IADDIU(VU, VUREC_INFO); } +void recVU0MI_IOR() { recVUMI_IOR(VU, VUREC_INFO); } +void recVU0MI_ISUB() { recVUMI_ISUB(VU, VUREC_INFO); } +void recVU0MI_IAND() { recVUMI_IAND(VU, VUREC_INFO); } +void recVU0MI_ISUBIU() { recVUMI_ISUBIU(VU, VUREC_INFO); } + +#else + +void recVU0MI_IADD() { REC_VUOP(VU0, IADD); } +void recVU0MI_IADDI() { REC_VUOP(VU0, IADDI); } +void recVU0MI_IADDIU() { REC_VUOP(VU0, IADDIU); } +void recVU0MI_IOR() { REC_VUOP(VU0, IOR); } +void recVU0MI_ISUB() { REC_VUOP(VU0, ISUB); } +void recVU0MI_IAND() { REC_VUOP(VU0, IAND); } +void recVU0MI_ISUBIU() { REC_VUOP(VU0, ISUBIU); } + +#endif + +#ifdef RECOMPILE_VUMI_BRANCH + +void recVU0MI_IBEQ() { recVUMI_IBEQ(VU, VUREC_INFO); } +void recVU0MI_IBGEZ() { recVUMI_IBGEZ(VU, VUREC_INFO); } +void recVU0MI_IBLTZ() { recVUMI_IBLTZ(VU, VUREC_INFO); } +void recVU0MI_IBLEZ() { recVUMI_IBLEZ(VU, VUREC_INFO); } +void recVU0MI_IBGTZ() { recVUMI_IBGTZ(VU, VUREC_INFO); } +void recVU0MI_IBNE() { recVUMI_IBNE(VU, VUREC_INFO); } +void recVU0MI_B() { recVUMI_B(VU, VUREC_INFO); } +void recVU0MI_BAL() { recVUMI_BAL(VU, VUREC_INFO); } +void recVU0MI_JR() { recVUMI_JR(VU, VUREC_INFO); } +void recVU0MI_JALR() { recVUMI_JALR(VU, VUREC_INFO); } + +#else + +void recVU0MI_IBEQ() { REC_VUOP(VU0, IBEQ); } +void recVU0MI_IBGEZ() { REC_VUOP(VU0, IBGEZ); } +void recVU0MI_IBGTZ() { REC_VUOP(VU0, IBGTZ); } +void recVU0MI_IBLTZ() { REC_VUOP(VU0, IBLTZ); } +void recVU0MI_IBLEZ() { REC_VUOP(VU0, IBLEZ); } +void recVU0MI_IBNE() { REC_VUOP(VU0, IBNE); } +void recVU0MI_B() { REC_VUOP(VU0, B); } +void recVU0MI_BAL() { REC_VUOP(VU0, BAL); } +void recVU0MI_JR() { REC_VUOP(VU0, JR); } +void recVU0MI_JALR() { REC_VUOP(VU0, JALR); } + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iVU0micro.h b/pcsx2/x86/iVU0micro.h new file mode 100644 index 0000000..1b3c1c5 --- /dev/null +++ b/pcsx2/x86/iVU0micro.h @@ -0,0 +1,229 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU0MICRO_H__ +#define __IVU0MICRO_H__ + +void recResetVU0(); +void recExecuteVU0Block( void ); +void recClearVU0( u32 Addr, u32 Size ); + +extern void (*recVU0_LOWER_OPCODE[128])(); +extern void (*recVU0_UPPER_OPCODE[64])(); + +extern void (*recVU0_UPPER_FD_00_TABLE[32])(); +extern void (*recVU0_UPPER_FD_01_TABLE[32])(); +extern void (*recVU0_UPPER_FD_10_TABLE[32])(); +extern void (*recVU0_UPPER_FD_11_TABLE[32])(); + +extern void (*recVU1_LOWER_OPCODE[128])(); +extern void (*recVU1_UPPER_OPCODE[64])(); + +extern void (*recVU1_UPPER_FD_00_TABLE[32])(); +extern void (*recVU1_UPPER_FD_01_TABLE[32])(); +extern void (*recVU1_UPPER_FD_10_TABLE[32])(); +extern void (*recVU1_UPPER_FD_11_TABLE[32])(); + +void recVU0_UPPER_FD_00(); +void recVU0_UPPER_FD_01(); +void recVU0_UPPER_FD_10(); +void recVU0_UPPER_FD_11(); + +void recVU0LowerOP(); +void recVU0LowerOP_T3_00(); +void recVU0LowerOP_T3_01(); +void recVU0LowerOP_T3_10(); +void recVU0LowerOP_T3_11(); + +void recVU0unknown(); + + + +/***************************************** + VU0 Micromode Upper instructions +*****************************************/ + +void recVU0MI_ABS(); +void recVU0MI_ADD(); +void recVU0MI_ADDi(); +void recVU0MI_ADDq(); +void recVU0MI_ADDx(); +void recVU0MI_ADDy(); +void recVU0MI_ADDz(); +void recVU0MI_ADDw(); +void recVU0MI_ADDA(); +void recVU0MI_ADDAi(); +void recVU0MI_ADDAq(); +void recVU0MI_ADDAx(); +void recVU0MI_ADDAy(); +void recVU0MI_ADDAz(); +void recVU0MI_ADDAw(); +void recVU0MI_SUB(); +void recVU0MI_SUBi(); +void recVU0MI_SUBq(); +void recVU0MI_SUBx(); +void recVU0MI_SUBy(); +void recVU0MI_SUBz(); +void recVU0MI_SUBw(); +void recVU0MI_SUBA(); +void recVU0MI_SUBAi(); +void recVU0MI_SUBAq(); +void recVU0MI_SUBAx(); +void recVU0MI_SUBAy(); +void recVU0MI_SUBAz(); +void recVU0MI_SUBAw(); +void recVU0MI_MUL(); +void recVU0MI_MULi(); +void recVU0MI_MULq(); +void recVU0MI_MULx(); +void recVU0MI_MULy(); +void recVU0MI_MULz(); +void recVU0MI_MULw(); +void recVU0MI_MULA(); +void recVU0MI_MULAi(); +void recVU0MI_MULAq(); +void recVU0MI_MULAx(); +void recVU0MI_MULAy(); +void recVU0MI_MULAz(); +void recVU0MI_MULAw(); +void recVU0MI_MADD(); +void recVU0MI_MADDi(); +void recVU0MI_MADDq(); +void recVU0MI_MADDx(); +void recVU0MI_MADDy(); +void recVU0MI_MADDz(); +void recVU0MI_MADDw(); +void recVU0MI_MADDA(); +void recVU0MI_MADDAi(); +void recVU0MI_MADDAq(); +void recVU0MI_MADDAx(); +void recVU0MI_MADDAy(); +void recVU0MI_MADDAz(); +void recVU0MI_MADDAw(); +void recVU0MI_MSUB(); +void recVU0MI_MSUBi(); +void recVU0MI_MSUBq(); +void recVU0MI_MSUBx(); +void recVU0MI_MSUBy(); +void recVU0MI_MSUBz(); +void recVU0MI_MSUBw(); +void recVU0MI_MSUBA(); +void recVU0MI_MSUBAi(); +void recVU0MI_MSUBAq(); +void recVU0MI_MSUBAx(); +void recVU0MI_MSUBAy(); +void recVU0MI_MSUBAz(); +void recVU0MI_MSUBAw(); +void recVU0MI_MAX(); +void recVU0MI_MAXi(); +void recVU0MI_MAXx(); +void recVU0MI_MAXy(); +void recVU0MI_MAXz(); +void recVU0MI_MAXw(); +void recVU0MI_MINI(); +void recVU0MI_MINIi(); +void recVU0MI_MINIx(); +void recVU0MI_MINIy(); +void recVU0MI_MINIz(); +void recVU0MI_MINIw(); +void recVU0MI_OPMULA(); +void recVU0MI_OPMSUB(); +void recVU0MI_NOP(); +void recVU0MI_FTOI0(); +void recVU0MI_FTOI4(); +void recVU0MI_FTOI12(); +void recVU0MI_FTOI15(); +void recVU0MI_ITOF0(); +void recVU0MI_ITOF4(); +void recVU0MI_ITOF12(); +void recVU0MI_ITOF15(); +void recVU0MI_CLIP(); + +/***************************************** + VU0 Micromode Lower instructions +*****************************************/ + +void recVU0MI_DIV(); +void recVU0MI_SQRT(); +void recVU0MI_RSQRT(); +void recVU0MI_IADD(); +void recVU0MI_IADDI(); +void recVU0MI_IADDIU(); +void recVU0MI_IAND(); +void recVU0MI_IOR(); +void recVU0MI_ISUB(); +void recVU0MI_ISUBIU(); +void recVU0MI_MOVE(); +void recVU0MI_MFIR(); +void recVU0MI_MTIR(); +void recVU0MI_MR32(); +void recVU0MI_LQ(); +void recVU0MI_LQD(); +void recVU0MI_LQI(); +void recVU0MI_SQ(); +void recVU0MI_SQD(); +void recVU0MI_SQI(); +void recVU0MI_ILW(); +void recVU0MI_ISW(); +void recVU0MI_ILWR(); +void recVU0MI_ISWR(); +void recVU0MI_RINIT(); +void recVU0MI_RGET(); +void recVU0MI_RNEXT(); +void recVU0MI_RXOR(); +void recVU0MI_WAITQ(); +void recVU0MI_FSAND(); +void recVU0MI_FSEQ(); +void recVU0MI_FSOR(); +void recVU0MI_FSSET(); +void recVU0MI_FMAND(); +void recVU0MI_FMEQ(); +void recVU0MI_FMOR(); +void recVU0MI_FCAND(); +void recVU0MI_FCEQ(); +void recVU0MI_FCOR(); +void recVU0MI_FCSET(); +void recVU0MI_FCGET(); +void recVU0MI_IBEQ(); +void recVU0MI_IBGEZ(); +void recVU0MI_IBGTZ(); +void recVU0MI_IBLEZ(); +void recVU0MI_IBLTZ(); +void recVU0MI_IBNE(); +void recVU0MI_B(); +void recVU0MI_BAL(); +void recVU0MI_JR(); +void recVU0MI_JALR(); +void recVU0MI_MFP(); +void recVU0MI_WAITP(); +void recVU0MI_ESADD(); +void recVU0MI_ERSADD(); +void recVU0MI_ELENG(); +void recVU0MI_ERLENG(); +void recVU0MI_EATANxy(); +void recVU0MI_EATANxz(); +void recVU0MI_ESUM(); +void recVU0MI_ERCPR(); +void recVU0MI_ESQRT(); +void recVU0MI_ERSQRT(); +void recVU0MI_ESIN(); +void recVU0MI_EATAN(); +void recVU0MI_EEXP(); +void recVU0MI_XITOP(); + +#endif /* __IVU0MICRO_H__ */ diff --git a/pcsx2/x86/iVU1micro.c b/pcsx2/x86/iVU1micro.c new file mode 100644 index 0000000..3df7e49 --- /dev/null +++ b/pcsx2/x86/iVU1micro.c @@ -0,0 +1,212 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VU.h" +#include "VUmicro.h" +#include "iVUmicro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "VUops.h" + +#include "iVUzerorec.h" + +// TODO: there's a bug in spyro start menu where release vurec works but debug vurec breaks + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +#define VU ((VURegs*)&VU1) + +u32 vu1recpcold = -1; +u32 vu1reccountold = -1; + +static _vuopinfo _opinfo[256]; + +//Lower/Upper instructions can use that.. +#define _Ft_ ((VU1.code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU1.code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU1.code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X ((VU1.code>>24) & 0x1) +#define _Y ((VU1.code>>23) & 0x1) +#define _Z ((VU1.code>>22) & 0x1) +#define _W ((VU1.code>>21) & 0x1) + +#define _Fsf_ ((VU1.code >> 21) & 0x03) +#define _Ftf_ ((VU1.code >> 23) & 0x03) + + +#define VU1_VFx_ADDR(x) (uptr)&VU1.VF[x].UL[0] +#define VU1_VFy_ADDR(x) (uptr)&VU1.VF[x].UL[1] +#define VU1_VFz_ADDR(x) (uptr)&VU1.VF[x].UL[2] +#define VU1_VFw_ADDR(x) (uptr)&VU1.VF[x].UL[3] + +#define VU1_REGR_ADDR (uptr)&VU1.VI[REG_R] +#define VU1_REGI_ADDR (uptr)&VU1.VI[REG_I] +#define VU1_REGQ_ADDR (uptr)&VU1.VI[REG_Q] +#define VU1_REGMAC_ADDR (uptr)&VU1.VI[REG_MAC_FLAG] + +#define VU1_VI_ADDR(x) (uptr)&VU1.VI[x].UL + +#define VU1_ACCx_ADDR (uptr)&VU1.ACC.UL[0] +#define VU1_ACCy_ADDR (uptr)&VU1.ACC.UL[1] +#define VU1_ACCz_ADDR (uptr)&VU1.ACC.UL[2] +#define VU1_ACCw_ADDR (uptr)&VU1.ACC.UL[3] + +static void VU1RecompileBlock(void); + +void recVU1Init() +{ + SuperVUInit(1); +} + +void recVU1Shutdown() +{ + SuperVUDestroy(1); +} + +void recResetVU1( void ) { + + if( CHECK_VU1REC ) { + SuperVUReset(1); + } + + vu1recpcold = 0; +#ifndef __x86_64__ + x86FpuState = FPU_STATE; +#endif + iCWstate = 0; + + branch = 0; +} + +static void iDumpBlock() +{ + FILE *f; + char filename[ 256 ]; + u32 *mem; + u32 i; + +#ifdef _WIN32 + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/vu%.4X.txt", VU1.VI[ REG_TPC ].UL ); +#endif + SysPrintf( "dump1 %x => %x (%s)\n", VU1.VI[ REG_TPC ].UL, pc, filename ); + + f = fopen( filename, "wb" ); + for ( i = VU1.VI[REG_TPC].UL; i < pc; i += 8 ) { + char* pstr; + mem = (u32*)&VU1.Micro[i]; + + pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%x: %-40s ", i, pstr); + + pstr = disVU1MicroLF( mem[0], i ); + fprintf(f, "%s\n", pstr); + } + fclose( f ); +} + +u32 g_VUProgramId = 0; + +#ifdef PCSX2_DEVBUILD +static u32 vuprogcount = 0; +extern u32 vudump; +#endif + +void recExecuteVU1Block(void) +{ +#ifdef _DEBUG + vuprogcount++; + + if( vudump & 8 ) { + __Log("start vu1: %x %x\n", VU1.VI[ REG_TPC ].UL, vuprogcount); + } +#endif + + if (CHECK_VU1REC) + { + if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { +#ifdef CPU_LOG + SysPrintf("VU1 memory overflow!!: %x\n", VU->VI[REG_TPC].UL); +#endif + VU0.VI[REG_VPU_STAT].UL&= ~0x100; + VU->cycle++; + return; + } + + assert( (VU1.VI[ REG_TPC ].UL&7) == 0 ); + + //__Log("prog: %x %x %x\n", vuprogcount, *(int*)0x1883a740, *(int*)0x18fe5fe0); + //for(i = 1; i < 32; ++i) __Log("vf%d: %x %x %x %x, vi: %x\n", i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + + //if( VU1.VI[ REG_TPC ].UL == 0x670 ) { +// __Log("VU: %x %x\n", VU1.VI[ REG_TPC ].UL, vuprogcount); +// iDumpVU1Registers(); +// vudump |= 8; + + // while loop needed since not always will return finished + do { + SuperVUExecuteProgram(VU1.VI[ REG_TPC ].UL, 1); + } + while( VU0.VI[ REG_VPU_STAT ].UL&0x100 ); + +// __Log("eVU: %x\n", VU1.VI[ REG_TPC ].UL); +// iDumpVU1Registers(); + } + else { +#ifdef _DEBUG + if( (vudump&8) ) { + __Log("tVU: %x\n", VU1.VI[ REG_TPC ].UL); + iDumpVU1Registers(); + } +#endif + + while(VU0.VI[ REG_VPU_STAT ].UL&0x100) + intExecuteVU1Block(); + } +} + +void recClearVU1( u32 Addr, u32 Size ) { + assert( (Addr&7) == 0 ); + + if( CHECK_VU1REC ) { + SuperVUClear(Addr, Size*4, 1); + } +} + +#endif diff --git a/pcsx2/x86/iVU1micro.h b/pcsx2/x86/iVU1micro.h new file mode 100644 index 0000000..cd83b5c --- /dev/null +++ b/pcsx2/x86/iVU1micro.h @@ -0,0 +1,31 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVU1MICRO_H__ +#define __IVU1MICRO_H__ + +void recVU1Init(); +void recVU1Shutdown(); +void recResetVU1(); +void recExecuteVU1Block( void ); +void recClearVU1( u32 Addr, u32 Size ); + +extern u32 vudump; +void iDumpVU1Registers(); + +#endif /* __IVU1MICRO_H__ */ diff --git a/pcsx2/x86/iVUmicro.c b/pcsx2/x86/iVUmicro.c new file mode 100644 index 0000000..6c1c040 --- /dev/null +++ b/pcsx2/x86/iVUmicro.c @@ -0,0 +1,4910 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "GS.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "VUmicro.h" +#include "VUflags.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "iVUops.h" +#include "iVUzerorec.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +int vucycle; +int vucycleold; +_vuopinfo *cinfo = NULL; + +//Lower/Upper instructions can use that.. +#define _Ft_ (( VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ (( VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ (( VU->code >> 6) & 0x1F) // The sa part of the instruction register + +#define _X (( VU->code>>24) & 0x1) +#define _Y (( VU->code>>23) & 0x1) +#define _Z (( VU->code>>22) & 0x1) +#define _W (( VU->code>>21) & 0x1) + +#define _XYZW_SS (_X+_Y+_Z+_W==1) + +#define _Fsf_ (( VU->code >> 21) & 0x03) +#define _Ftf_ (( VU->code >> 23) & 0x03) + +#define _Imm11_ (s32)(VU->code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) +#define _UImm11_ (s32)(VU->code & 0x7ff) + +#define VU_VFx_ADDR(x) (uptr)&VU->VF[x].UL[0] +#define VU_VFy_ADDR(x) (uptr)&VU->VF[x].UL[1] +#define VU_VFz_ADDR(x) (uptr)&VU->VF[x].UL[2] +#define VU_VFw_ADDR(x) (uptr)&VU->VF[x].UL[3] + +#define VU_REGR_ADDR (uptr)&VU->VI[REG_R] +#define VU_REGQ_ADDR (uptr)&VU->VI[REG_Q] +#define VU_REGMAC_ADDR (uptr)&VU->VI[REG_MAC_FLAG] + +#define VU_VI_ADDR(x, read) GetVIAddr(VU, x, read, info) + +#define VU_ACCx_ADDR (uptr)&VU->ACC.UL[0] +#define VU_ACCy_ADDR (uptr)&VU->ACC.UL[1] +#define VU_ACCz_ADDR (uptr)&VU->ACC.UL[2] +#define VU_ACCw_ADDR (uptr)&VU->ACC.UL[3] + +#define _X_Y_Z_W ((( VU->code >> 21 ) & 0xF ) ) + +PCSX2_ALIGNED16(float recMult_float_to_int4[4]) = { 16.0, 16.0, 16.0, 16.0 }; +PCSX2_ALIGNED16(float recMult_float_to_int12[4]) = { 4096.0, 4096.0, 4096.0, 4096.0 }; +PCSX2_ALIGNED16(float recMult_float_to_int15[4]) = { 32768.0, 32768.0, 32768.0, 32768.0 }; + +PCSX2_ALIGNED16(float recMult_int_to_float4[4]) = { 0.0625f, 0.0625f, 0.0625f, 0.0625f }; +PCSX2_ALIGNED16(float recMult_int_to_float12[4]) = { 0.000244140625, 0.000244140625, 0.000244140625, 0.000244140625 }; +PCSX2_ALIGNED16(float recMult_int_to_float15[4]) = { 0.000030517578125, 0.000030517578125, 0.000030517578125, 0.000030517578125 }; +static s32 bpc; +_VURegsNum* g_VUregs = NULL; +u8 g_MACFlagTransform[256] = {0}; // used to flip xyzw bits + +static int SSEmovMask[ 16 ][ 4 ] = +{ +{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +{ 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }, +{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } +}; + +#define VU_SWAPSRC 0xf090 // don't touch + +#define _vuIsRegSwappedWithTemp() (VU_SWAPSRC & (1<<_X_Y_Z_W)) + +// use for allocating vi regs +#define ALLOCTEMPX86(mode) _allocX86reg(-1, X86TYPE_TEMP, 0, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ALLOCVI(vi, mode) _allocX86reg(-1, X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), vi, ((info&PROCESS_VU_SUPER)?0:MODE_NOFRAME)|mode) +#define ADD_VI_NEEDED(vi) _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), vi); + +// 1 - src, 0 - dest wzyx +void VU_MERGE0(int dest, int src) { // 0000 +} +void VU_MERGE1(int dest, int src) { // 1000 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc4); +} +void VU_MERGE2(int dest, int src) { // 0100 + SSE_MOVHLPS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x64); +} +void VU_MERGE3(int dest, int src) { // 1100 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE4(int dest, int src) { // 0010s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE5(int dest, int src) { // 1010 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xd8); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd8); +} +void VU_MERGE6(int dest, int src) { // 0110 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x9c); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x78); +} +void VU_MERGE7(int dest, int src) { // 1110s + SSE_MOVSS_XMM_to_XMM(src, dest); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE8(int dest, int src) { // 0001 + SSE_MOVSS_XMM_to_XMM(dest, src); +} +void VU_MERGE9(int dest, int src) { // 1001 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xc9); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0xd2); +} +void VU_MERGE10(int dest, int src) { // 0101 + SSE_SHUFPS_XMM_to_XMM(dest, src, 0x8d); + SSE_SHUFPS_XMM_to_XMM(dest, dest, 0x72); +} +void VU_MERGE11(int dest, int src) { // 1101 + SSE_MOVSS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(dest, src, 0xe4); +} +void VU_MERGE12(int dest, int src) { // 0011s + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xe4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE13(int dest, int src) { // 1011s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0x64); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE14(int dest, int src) { // 0111s + SSE_MOVHLPS_XMM_to_XMM(dest, src); + SSE_SHUFPS_XMM_to_XMM(src, dest, 0xc4); + SSE_MOVAPS_XMM_to_XMM(dest, src); +} +void VU_MERGE15(int dest, int src) { // 1111s + SSE_MOVAPS_XMM_to_XMM(dest, src); +} + +typedef void (*VUMERGEFN)(int dest, int src); +static VUMERGEFN s_VuMerge[16] = { + VU_MERGE0, VU_MERGE1, VU_MERGE2, VU_MERGE3, + VU_MERGE4, VU_MERGE5, VU_MERGE6, VU_MERGE7, + VU_MERGE8, VU_MERGE9, VU_MERGE10, VU_MERGE11, + VU_MERGE12, VU_MERGE13, VU_MERGE14, VU_MERGE15 }; + +#define VU_MERGE_REGS(dest, src) { \ + if( dest != src ) s_VuMerge[_X_Y_Z_W](dest, src); \ +} \ + +#define VU_MERGE_REGS_CUSTOM(dest, src, xyzw) { \ + if( dest != src ) s_VuMerge[xyzw](dest, src); \ +} \ + +void _unpackVF_xyzw(int dstreg, int srcreg, int xyzw) +{ + // don't use pshufd + if( dstreg == srcreg || !cpucaps.hasStreamingSIMD3Extensions) { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + switch (xyzw) { + case 0: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x00); break; + case 1: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); break; + case 2: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xaa); break; + case 3: SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); break; + } + } + else { + switch (xyzw) { + case 0: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 1: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVLHPS_XMM_to_XMM(dstreg, dstreg); + break; + case 2: + SSE3_MOVSLDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + case 3: + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + break; + } + } +} + +void _unpackVFSS_xyzw(int dstreg, int srcreg, int xyzw) +{ + switch (xyzw) { + case 0: + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + break; + case 1: + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0x55); + } + break; + case 2: + SSE_MOVHLPS_XMM_to_XMM(dstreg, srcreg); + break; + case 3: + if( cpucaps.hasStreamingSIMD3Extensions && dstreg != srcreg ) { + SSE3_MOVSHDUP_XMM_to_XMM(dstreg, srcreg); + SSE_MOVHLPS_XMM_to_XMM(dstreg, dstreg); + } + else { + if( dstreg != srcreg ) SSE_MOVAPS_XMM_to_XMM(dstreg, srcreg); + SSE_SHUFPS_XMM_to_XMM(dstreg, dstreg, 0xff); + } + break; + } +} + +void _vuFlipRegSS(VURegs * VU, int reg) +{ + assert( _XYZW_SS ); + if( _Y ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xe1); + else if( _Z ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0xc6); + else if( _W ) SSE_SHUFPS_XMM_to_XMM(reg, reg, 0x27); +} + +void _vuMoveSS(VURegs * VU, int dstreg, int srcreg) +{ + assert( _XYZW_SS ); + if( _Y ) _unpackVFSS_xyzw(dstreg, srcreg, 1); + else if( _Z ) _unpackVFSS_xyzw(dstreg, srcreg, 2); + else if( _W ) _unpackVFSS_xyzw(dstreg, srcreg, 3); + else _unpackVFSS_xyzw(dstreg, srcreg, 0); +} + +void _recvuFMACflush(VURegs * VU) { + int i; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + + if ((vucycle - VU->fmac[i].sCycle) >= VU->fmac[i].Cycle) { +#ifdef VUM_LOG +// if (Log) { VUM_LOG("flushing FMAC pipe[%d]\n", i); } +#endif + VU->fmac[i].enable = 0; + } + } +} + +void _recvuFDIVflush(VURegs * VU) { + if (VU->fdiv.enable == 0) return; + + if ((vucycle - VU->fdiv.sCycle) >= VU->fdiv.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->fdiv.enable = 0; + } +} + +void _recvuEFUflush(VURegs * VU) { + if (VU->efu.enable == 0) return; + + if ((vucycle - VU->efu.sCycle) >= VU->efu.Cycle) { +// SysPrintf("flushing FDIV pipe\n"); + VU->efu.enable = 0; + } +} + +void _recvuTestPipes(VURegs * VU) { + _recvuFMACflush(VU); + _recvuFDIVflush(VU); + _recvuEFUflush(VU); +} + +void _recvuFMACTestStall(VURegs * VU, int reg, int xyzw) { + int cycle; + int i; + u32 mask = 0; + + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 0) continue; + if (VU->fmac[i].reg == reg && + (VU->fmac[i].xyzw & xyzw)) break; + } + + if (i == 8) return; + + // do a perchannel delay + // old code +// cycle = VU->fmac[i].Cycle - (vucycle - VU->fmac[i].sCycle); + + // new code + mask = 4; // w +// if( VU->fmac[i].xyzw & 1 ) mask = 4; // w +// else if( VU->fmac[i].xyzw & 2 ) mask = 3; // z +// else if( VU->fmac[i].xyzw & 4 ) mask = 2; // y +// else { +// assert(VU->fmac[i].xyzw & 8 ); +// mask = 1; // x +// } + +// mask = 0; +// if( VU->fmac[i].xyzw & 1 ) mask++; // w +// else if( VU->fmac[i].xyzw & 2 ) mask++; // z +// else if( VU->fmac[i].xyzw & 4 ) mask++; // y +// else if( VU->fmac[i].xyzw & 8 ) mask++; // x + + assert( (int)VU->fmac[i].sCycle < (int)vucycle ); + cycle = 0; + if( vucycle - VU->fmac[i].sCycle < mask ) + cycle = mask - (vucycle - VU->fmac[i].sCycle); + + VU->fmac[i].enable = 0; + vucycle+= cycle; + _recvuTestPipes(VU); +} + +void _recvuFMACAdd(VURegs * VU, int reg, int xyzw) { + int i; + + /* find a free fmac pipe */ + for (i=0; i<8; i++) { + if (VU->fmac[i].enable == 1) continue; + break; + } + if (i==8) { + SysPrintf("*PCSX2*: error , out of fmacs\n"); + } + +#ifdef VUM_LOG +// if (Log) { VUM_LOG("adding FMAC pipe[%d]; reg %d\n", i, reg); } +#endif + VU->fmac[i].enable = 1; + VU->fmac[i].sCycle = vucycle; + VU->fmac[i].Cycle = 3; + VU->fmac[i].xyzw = xyzw; + VU->fmac[i].reg = reg; +} + +void _recvuFDIVAdd(VURegs * VU, int cycles) { +// SysPrintf("adding FDIV pipe\n"); + VU->fdiv.enable = 1; + VU->fdiv.sCycle = vucycle; + VU->fdiv.Cycle = cycles; +} + +void _recvuEFUAdd(VURegs * VU, int cycles) { +// SysPrintf("adding EFU pipe\n"); + VU->efu.enable = 1; + VU->efu.sCycle = vucycle; + VU->efu.Cycle = cycles; +} + +void _recvuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + + if( VUregsn->VFread0 && (VUregsn->VFread0 == VUregsn->VFread1) ) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw|VUregsn->VFr1xyzw); + } + else { + if (VUregsn->VFread0) { + _recvuFMACTestStall(VU, VUregsn->VFread0, VUregsn->VFr0xyzw); + } + if (VUregsn->VFread1) { + _recvuFMACTestStall(VU, VUregsn->VFread1, VUregsn->VFr1xyzw); + } + } +} + +void _recvuAddFMACStalls(VURegs * VU, _VURegsNum *VUregsn) { + if (VUregsn->VFwrite) { + _recvuFMACAdd(VU, VUregsn->VFwrite, VUregsn->VFwxyzw); + } else + if (VUregsn->VIwrite & (1 << REG_CLIP_FLAG)) { +// SysPrintf("REG_CLIP_FLAG pipe\n"); + _recvuFMACAdd(VU, -REG_CLIP_FLAG, 0); + } else { + _recvuFMACAdd(VU, 0, 0); + } +} + +void _recvuFlushFDIV(VURegs * VU) { + int cycle; + + if (VU->fdiv.enable == 0) return; + + cycle = VU->fdiv.Cycle - (vucycle - VU->fdiv.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->fdiv.enable = 0; + vucycle+= cycle; +} + +void _recvuFlushEFU(VURegs * VU) { + int cycle; + + if (VU->efu.enable == 0) return; + + cycle = VU->efu.Cycle - (vucycle - VU->efu.sCycle); +// SysPrintf("waiting FDIV pipe %d\n", cycle); + VU->efu.enable = 0; + vucycle+= cycle; +} + +void _recvuTestFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushFDIV(VU); +} + +void _recvuTestEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + _recvuFlushEFU(VU); +} + +void _recvuAddFDIVStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_Q)) { + _recvuFDIVAdd(VU, VUregsn->cycles); + } +} + +void _recvuAddEFUStalls(VURegs * VU, _VURegsNum *VUregsn) { +// _vuTestFMACStalls(VURegs * VU, _VURegsNum *VUregsn); + if (VUregsn->VIwrite & (1 << REG_P)) { + _recvuEFUAdd(VU, VUregsn->cycles); + } +} + +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + } +} + +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuTestFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuTestFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuTestEFUStalls(VU, VUregsn); break; + } +} + +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + } +} + +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) { + switch (VUregsn->pipe) { + case VUPIPE_FMAC: _recvuAddFMACStalls(VU, VUregsn); break; + case VUPIPE_FDIV: _recvuAddFDIVStalls(VU, VUregsn); break; + case VUPIPE_EFU: _recvuAddEFUStalls(VU, VUregsn); break; + } +} + + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs) +{ + _VURegsNum* lregs; + _VURegsNum* uregs; + int *ptr; + + lregs = pCodeRegs; + uregs = pCodeRegs+1; + + ptr = (int*)&VU->Micro[pc]; + pc += 8; + + if (ptr[1] & 0x40000000) { // EOP + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](uregs); + } + + _recvuTestUpperStalls(VU, uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + break; + + default: + info->statusflag = 4; + info->macflag = 4; + break; + } + + if (uregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (uregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + info->cycle = vucycle; + memset(lregs, 0, sizeof(lregs)); + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](lregs); + } + + _recvuTestLowerStalls(VU, lregs); + info->cycle = vucycle; + + if (lregs->pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs->VIwrite & (1 << REG_Q)) { + info->q |= 4; + info->cycles = lregs->cycles; + info->pqinst = (VU->code&2)>>1; // rsqrt is 2 + } + else if (lregs->pipe == VUPIPE_FDIV) { + info->q |= 8|1; + info->pqinst = 0; + } + + if (lregs->VIwrite & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 4; + info->cycles = lregs->cycles; + + switch( VU->code & 0xff ) { + case 0xfd: info->pqinst = 0; break; //eatan + case 0x7c: info->pqinst = 0; break; //eatanxy + case 0x7d: info->pqinst = 0; break; //eatanzy + case 0xfe: info->pqinst = 1; break; //eexp + case 0xfc: info->pqinst = 2; break; //esin + case 0x3f: info->pqinst = 3; break; //erleng + case 0x3e: info->pqinst = 4; break; //eleng + case 0x3d: info->pqinst = 4; break; //ersadd + case 0xbd: info->pqinst = 4; break; //ersqrt + case 0xbe: info->pqinst = 5; break; //ercpr + case 0xbc: info->pqinst = 5; break; //esqrt + case 0x7e: info->pqinst = 5; break; //esum + case 0x3c: info->pqinst = 6; break; //esadd + default: assert(0); + } + } + else if (lregs->pipe == VUPIPE_EFU) { + info->p |= 8|1; + } + + if (lregs->VIread & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_READ; + if (lregs->VIread & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_READ; + + if (lregs->VIwrite & (1 << REG_STATUS_FLAG)) info->statusflag|= VUOP_WRITE; + if (lregs->VIwrite & (1 << REG_MAC_FLAG)) info->macflag|= VUOP_WRITE; + + if (lregs->VIread & (1 << REG_Q)) { + info->q |= 2; + } + + if (lregs->VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= 2; + } + + _recvuAddLowerStalls(VU, lregs); + } + _recvuAddUpperStalls(VU, uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +// Analyze an op - first pass +void _vurecAnalyzeOp(VURegs *VU, _vuopinfo *info) { + _VURegsNum lregs; + _VURegsNum uregs; + int *ptr; + +// SysPrintf("_vurecAnalyzeOp %x; %p\n", pc, info); + ptr = (int*)&VU->Micro[pc]; + pc += 8; + +/* SysPrintf("_vurecAnalyzeOp Upper: %s\n", disVU1MicroUF( ptr[1], pc ) ); + if ((ptr[1] & 0x80000000) == 0) { + SysPrintf("_vurecAnalyzeOp Lower: %s\n", disVU1MicroLF( ptr[0], pc ) ); + }*/ + if (ptr[1] & 0x40000000) { + branch |= 8; + } + + VU->code = ptr[1]; + if (VU == &VU1) { + VU1regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + } else { + VU0regs_UPPER_OPCODE[VU->code & 0x3f](&uregs); + } + + _recvuTestUpperStalls(VU, &uregs); + switch(VU->code & 0x3f) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1d: case 0x1f: + case 0x2b: case 0x2f: + break; + + case 0x3c: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3d: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3e: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + case 0x3f: + switch ((VU->code >> 6) & 0x1f) { + case 0x4: case 0x5: case 0x7: case 0xb: + break; + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + break; + + default: + info->statusflag|= VUOP_WRITE; + info->macflag|= VUOP_WRITE; + break; + } + + if (uregs.VIwrite & (1 << REG_CLIP_FLAG)) { + info->clipflag |= VUOP_WRITE; + } + + if (uregs.VIread & (1 << REG_Q)) { + info->q |= VUOP_READ; + } + + if (uregs.VIread & (1 << REG_P)) { + assert( VU == &VU1 ); + info->p |= VUOP_READ; + } + + /* check upper flags */ + if (ptr[1] & 0x80000000) { /* I flag */ + info->cycle = vucycle; + + } else { + + VU->code = ptr[0]; + if (VU == &VU1) { + VU1regs_LOWER_OPCODE[VU->code >> 25](&lregs); + } else { + VU0regs_LOWER_OPCODE[VU->code >> 25](&lregs); + } + + _recvuTestLowerStalls(VU, &lregs); + info->cycle = vucycle; + + if (lregs.pipe == VUPIPE_BRANCH) { + branch |= 1; + } + + if (lregs.VIwrite & (1 << REG_Q)) { +// SysPrintf("write to Q\n"); + info->q |= VUOP_WRITE; + info->cycles = lregs.cycles; + } + else if (lregs.pipe == VUPIPE_FDIV) { + info->q |= 8|1; + } + + if (lregs.VIwrite & (1 << REG_P)) { +// SysPrintf("write to P\n"); + info->p |= VUOP_WRITE; + info->cycles = lregs.cycles; + } + else if (lregs.pipe == VUPIPE_EFU) { + assert( VU == &VU1 ); + info->p |= 8|1; + } + + if (lregs.VIread & (1 << REG_CLIP_FLAG)) { + info->clipflag|= VUOP_READ; + } + + if (lregs.VIread & (1 << REG_STATUS_FLAG)) { + info->statusflag|= VUOP_READ; + } + + if (lregs.VIread & (1 << REG_MAC_FLAG)) { + info->macflag|= VUOP_READ; + } + + _recvuAddLowerStalls(VU, &lregs); + } + _recvuAddUpperStalls(VU, &uregs); + + _recvuTestPipes(VU); + + vucycle++; +} + +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs) +{ + int info = 0; + int vfread0=-1, vfread1 = -1, vfwrite = -1, vfacc = -1, vftemp=-1; + + assert( regs != NULL ); + + if( regs->VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<VFread0 ) vfread0 = _allocVFtoXMMreg(VU, -1, regs->VFread0, MODE_READ); + else if( regs->VIread & (1<VFread1 ) vfread1 = _allocVFtoXMMreg(VU, -1, regs->VFread1, MODE_READ); + else if( (regs->VIread & (1<VFr1xyzw != 0xff) vfread1 = _allocVFtoXMMreg(VU, -1, 0, MODE_READ); + + if( regs->VIread & (1<VIwrite&(1<VIwrite & (1<VFwxyzw != 0xf?MODE_READ:0)); + } + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwrite, MODE_WRITE|(regs->VFwxyzw != 0xf?MODE_READ:0)); + } + + if( vfacc>= 0 ) info |= PROCESS_EE_SET_ACC(vfacc); + if( vfwrite >= 0 ) { + if( regs->VFwrite == _Ft_ && vfread1 < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite); + } + else { + assert( regs->VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite); + } + } + + if( vfread0 >= 0 ) info |= PROCESS_EE_SET_S(vfread0); + if( vfread1 >= 0 ) info |= PROCESS_EE_SET_T(vfread1); + + vftemp = _allocTempXMMreg(XMMT_FPS, -1); + info |= PROCESS_VU_SET_TEMP(vftemp); + + if( regs->VIwrite & (1 << REG_CLIP_FLAG) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + int t1reg = _allocTempXMMreg(XMMT_FPS, -1); + int t2reg = _allocTempXMMreg(XMMT_FPS, -1); + + info |= PROCESS_EE_SET_D(t1reg); + info |= PROCESS_EE_SET_ACC(t2reg); + + _freeXMMreg(t1reg); // don't need + _freeXMMreg(t2reg); // don't need + } + else if( regs->VIwrite & (1<statusflag & 1 ) info |= PROCESS_VU_UPDATEFLAGS; + if( cinfo->macflag & 1) info |= PROCESS_VU_UPDATEFLAGS; + + if( regs->pipe == 0xff ) info |= PROCESS_VU_COP2; + + return info; +} + +// returns the correct VI addr +u32 GetVIAddr(VURegs * VU, int reg, int read, int info) +{ + if( info & PROCESS_VU_SUPER ) return SuperVUGetVIAddr(reg, read); + if( info & PROCESS_VU_COP2 ) return (uptr)&VU->VI[reg].UL; + + if( read != 1 ) { + if( reg == REG_MAC_FLAG ) return (uptr)&VU->macflag; + if( reg == REG_CLIP_FLAG ) return (uptr)&VU->clipflag; + if( reg == REG_STATUS_FLAG ) return (uptr)&VU->statusflag; + if( reg == REG_Q ) return (uptr)&VU->q; + if( reg == REG_P ) return (uptr)&VU->p; + } + + return (uptr)&VU->VI[reg].UL; +} + +// gets a temp reg that is not EEREC_TEMP +int _vuGetTempXMMreg(int info) +{ + int t1reg = -1; + + if( _hasFreeXMMreg() ) { + t1reg = _allocTempXMMreg(XMMT_FPS, -1); + if( t1reg == EEREC_TEMP && _hasFreeXMMreg() ) { + int t = _allocTempXMMreg(XMMT_FPS, -1); + _freeXMMreg(t1reg); + t1reg = t; + _freeXMMreg(t1reg); + } + else { + _freeXMMreg(t1reg); + t1reg = -1; + } + } + + return t1reg; +} + +PCSX2_ALIGNED16(u32 g_minvals[4]) = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}; +PCSX2_ALIGNED16(u32 g_maxvals[4]) = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}; + +static PCSX2_ALIGNED16(int const_clip[]) = { + 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + +static PCSX2_ALIGNED16(u32 s_FloatMinMax[]) = { + 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, + 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff, + 0, 0, 0, 0 }; + +static PCSX2_ALIGNED16(float s_fones[]) = { 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f }; +static PCSX2_ALIGNED16(u32 s_mask[]) = {0x7fffff, 0x7fffff, 0x7fffff, 0x7fffff }; +static PCSX2_ALIGNED16(u32 s_expmask[]) = {0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000}; + +void CheckForOverflowSS_(int fdreg, int t0reg) +{ + assert( t0reg != fdreg ); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDSS_XMM_to_XMM(t0reg, fdreg); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVSS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNESS_M32_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow_(int fdreg, int t0reg, int keepxyzw) +{ +// SSE_MAXPS_M128_to_XMM(fdreg, (u32)g_minvals); +// SSE_MINPS_M128_to_XMM(fdreg, (u32)g_maxvals); + + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, fdreg); + // for partial masks, sometimes regs can be integers + if( keepxyzw != 15 ) + SSE_ORPS_M128_to_XMM(t0reg, (uptr)&SSEmovMask[15-keepxyzw][0]); + SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); + +// SSE_MOVAPS_M128_to_XMM(t0reg, (u32)s_expmask); +// SSE_ANDPS_XMM_to_XMM(t0reg, fdreg); +// SSE_CMPNEPS_M128_to_XMM(t0reg, (u32)s_expmask); +// //SSE_ORPS_M128_to_XMM(t0reg, (u32)g_minvals); +// SSE_ANDPS_XMM_to_XMM(fdreg, t0reg); +} + +void CheckForOverflow(VURegs *VU, int info, int regd) +{ + if( CHECK_FORCEABS && EEREC_TEMP != regd) { + // changing the order produces different results (tektag) + CheckForOverflow_(regd, EEREC_TEMP, _X_Y_Z_W); + } +} + +// if unordered replaces with 0x7f7fffff (note, loses sign) +void ClampUnordered(int regd, int t0reg, int dosign) +{ + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE_CMPORDPS_XMM_to_XMM(t0reg, regd); + SSE_ANDPS_XMM_to_XMM(regd, t0reg); + SSE_ANDNPS_M128_to_XMM(t0reg, (u32)g_maxvals); + SSE_ORPS_XMM_to_XMM(regd, t0reg); +} + +//__declspec(naked) void temp() +//{ +// __asm ret +//} + +// VU Flags +// NOTE: flags don't compute under/over flows since it is highly unlikely +// that games used them. Including them will lower performance. +void recUpdateFlags(VURegs * VU, int reg, int info) +{ + u32 flagmask; + u8* pjmp; + u32 macaddr, stataddr, prevstataddr; + int x86macflag, x86newflag, x86oldflag; + const static u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + if( !(info & PROCESS_VU_UPDATEFLAGS) ) + return; + + flagmask = macarr[_X_Y_Z_W]; + macaddr = VU_VI_ADDR(REG_MAC_FLAG, 0); + stataddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + prevstataddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + if( stataddr == 0 ) { + stataddr = prevstataddr; + } + //assert( stataddr != 0); + + + // 20 insts + x86newflag = ALLOCTEMPX86(MODE_8BITREG); + x86macflag = ALLOCTEMPX86(0); + x86oldflag = ALLOCTEMPX86(0); + + // can do with 8 bits since only computing zero/sign flags + if( EEREC_TEMP != reg ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_CMPEQPS_XMM_to_XMM(EEREC_TEMP, reg); + + MOV32MtoR(x86oldflag, prevstataddr); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + XOR32RtoR(EAX, EAX); + + if( !(g_VUGameFixes&VUFIX_SIGNEDZERO) ) { + SSE_ANDNPS_XMM_to_XMM(EEREC_TEMP, reg); // necessary! + } + + AND32ItoR(x86newflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + if( !(g_VUGameFixes&VUFIX_SIGNEDZERO) ) SSE_MOVMSKPS_XMM_to_R32(x86macflag, EEREC_TEMP); // sign + else SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // sign + + SHL32ItoR(x86newflag, 4); + AND32ItoR(x86macflag, 0x0f&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + OR32RtoR(x86macflag, x86newflag); + } + else { + SSE_MOVMSKPS_XMM_to_R32(x86macflag, reg); // mask is < 0 (including 80000000) + + MOV32MtoR(x86oldflag, prevstataddr); + XOR32RtoR(EAX, EAX); + + SSE_CMPEQPS_M128_to_XMM(EEREC_TEMP, (uptr)&s_FloatMinMax[8]); + + SSE_MOVMSKPS_XMM_to_R32(x86newflag, EEREC_TEMP); // zero + + if( !(g_VUGameFixes&VUFIX_SIGNEDZERO) ) { + NOT32R(x86newflag); + AND32RtoR(x86macflag, x86newflag); + } + + AND32ItoR(x86macflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 2); + x86SetJ8(pjmp); + + if( !(g_VUGameFixes&VUFIX_SIGNEDZERO) ) { + NOT32R(x86newflag); + } + + AND32ItoR(x86newflag, 0xf&flagmask); + pjmp = JZ8(0); + OR32ItoR(EAX, 1); + x86SetJ8(pjmp); + + SHL32ItoR(x86newflag, 4); + OR32RtoR(x86macflag, x86newflag); + } + + // x86macflag - new untransformed mac flag, EAX - new status bits, x86oldflag - old status flag + // x86macflag = zero_wzyx | sign_wzyx + MOV8RmtoROffset(x86newflag, x86macflag, (u32)g_MACFlagTransform); // transform + MOV32RtoR(x86macflag, x86oldflag); + SHL32ItoR(x86macflag, 6); + OR32RtoR(x86oldflag, x86macflag); + + if( macaddr != 0 ) { + + // has to write full 32 bits! + MOV8RtoM(macaddr, x86newflag); + + // vampire night breaks with (g_VUGameFixes&VUFIX_EXTRAFLAGS), crazi taxi needs it + if( (g_VUGameFixes&VUFIX_EXTRAFLAGS) && flagmask != 0xf ) { + MOV8MtoR(x86newflag, VU_VI_ADDR(REG_MAC_FLAG, 2)); // get previous written + AND8ItoR(x86newflag, ~g_MACFlagTransform[(flagmask|(flagmask<<4))]); + OR8RtoM(macaddr, x86newflag); + } + } + + AND32ItoR(x86oldflag, 0x0c0); + OR32RtoR(x86oldflag, EAX); + MOV32RtoM(stataddr, x86oldflag); + + _freeX86reg(x86macflag); + _freeX86reg(x86newflag); + _freeX86reg(x86oldflag); +} + +/******************************/ +/* VU Upper instructions */ +/******************************/ + +static PCSX2_ALIGNED16(int const_abs_table[16][4]) = +{ + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0xffffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0xffffffff, 0x7fffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0xffffffff }, + { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff }, +}; + +void recVUMI_ABS(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_ANDPS_M128_to_XMM(EEREC_T, (uptr)&const_abs_table[ _X_Y_Z_W ][ 0 ] ); + } +} + +PCSX2_ALIGNED16(float s_two[4]) = {0,0,0,2}; + +void recVUMI_ADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_two); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_two); + } + } + else { + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + +// if( _Fd_ == 0 && (_Fs_ == 0 || _Ft_ == 0) ) +// info |= PROCESS_VU_UPDATEFLAGS; + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADD_iq(VURegs *VU, uptr addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_D, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_ADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _Ft_ == 0 && xyzw < 3 ) { + // just move + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if( _Fs_ == 0 && !_W ) { + // just move + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + +// SSE_MOVAPS_XMM_to_M128((u32)s_tempmem, EEREC_TEMP); +// SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); +// SSE_CMPNLTPS_M128_to_XMM(EEREC_TEMP, (u32)s_FloatMinMax); +// SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_tempmem); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _X_Y_Z_W != 0xf || EEREC_D == EEREC_S || EEREC_D == EEREC_TEMP) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } else { + if( EEREC_D == EEREC_TEMP ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_D == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_ADDi(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDq(VURegs *VU, int info) { recVUMI_ADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDx(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 0, info); } +void recVUMI_ADDy(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 1, info); } +void recVUMI_ADDz(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 2, info); } +void recVUMI_ADDw(VURegs *VU, int info) { recVUMI_ADD_xyzw(VU, 3, info); } + +void recVUMI_ADDA(VURegs *VU, int info) +{ + if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + assert( EEREC_ACC != EEREC_TEMP ); + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(EEREC_ACC, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC, 0x00); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( _Fs_ == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_ADDSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || EEREC_ACC == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } else { + if( EEREC_ACC == EEREC_S ) SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + else { + _unpackVF_xyzw(EEREC_ACC, EEREC_T, xyzw); + SSE_ADDPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + } + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_ADDAi(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_ADDAq(VURegs *VU, int info) { recVUMI_ADDA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_ADDAx(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 0, info); } +void recVUMI_ADDAy(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 1, info); } +void recVUMI_ADDAz(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 2, info); } +void recVUMI_ADDAw(VURegs *VU, int info) { recVUMI_ADDA_xyzw(VU, 3, info); } + +void recVUMI_SUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_D, (uptr)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Ft_ > 0 || _W ) SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + // neopets works better with this? + //CheckForOverflow(info, EEREC_D); +} + +void recVUMI_SUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if (EEREC_D != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +static PCSX2_ALIGNED16(s_unaryminus[4]) = {0x80000000, 0, 0, 0}; + +void recVUMI_SUB_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, xyzw); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_T ) { + if( _Fs_ > 0 ) SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_XORPS_M128_to_XMM(EEREC_D, (u32)s_unaryminus); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } +// else if( _XYZW_SS && xyzw == 0 ) { +// if( EEREC_D == EEREC_S ) { +// if( EEREC_D == EEREC_T ) { +// SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_D, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } +// else if( EEREC_D == EEREC_T ) { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// else { +// _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Y?1:(_Z?2:3)); +// _vuFlipRegSS(VU, EEREC_D); +// SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); +// SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); +// _vuFlipRegSS(VU, EEREC_D); +// } +// } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_D, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + } + else { + if( EEREC_D == EEREC_TEMP ) { + SSE_XORPS_M128_to_XMM(EEREC_D, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + if( EEREC_D != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_SUBi(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBq(VURegs *VU, int info) { recVUMI_SUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBx(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 0, info); } +void recVUMI_SUBy(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 1, info); } +void recVUMI_SUBz(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 2, info); } +void recVUMI_SUBw(VURegs *VU, int info) { recVUMI_SUB_xyzw(VU, 3, info); } + +void recVUMI_SUBA(VURegs *VU, int info) +{ + if( EEREC_S == EEREC_T ) { + if (_X_Y_Z_W != 0xf) SSE_ANDPS_M128_to_XMM(EEREC_ACC, (uptr)&SSEmovMask[15-_X_Y_Z_W][0]); + else SSE_XORPS_XMM_to_XMM(EEREC_ACC, EEREC_ACC); + } + else if( _X_Y_Z_W == 8 ) { + if (EEREC_ACC == EEREC_S) SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if (EEREC_ACC == EEREC_T) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + else { + if( EEREC_ACC == EEREC_S ) SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + else if( EEREC_ACC == EEREC_T ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_iq(VURegs *VU, int addr, int info) +{ + if( _XYZW_SS ) { + if( EEREC_ACC == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + _vuFlipRegSS(VU, EEREC_ACC); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_M32_to_XMM(EEREC_ACC, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_ACC); + SSE_SUBSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_ACC); + } + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBA_xyzw(VURegs *VU, int xyzw, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( xyzw == 0 ) { + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_T); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBSS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_ACC, t1reg); + _freeXMMreg(t1reg); + } + else { + // negate + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_ACC, EEREC_TEMP); + } + } + else { + if( EEREC_ACC != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_ACC, EEREC_S); + SSE_SUBPS_XMM_to_XMM(EEREC_ACC, EEREC_TEMP); + } + } + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_SUBAi(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_SUBAq(VURegs *VU, int info) { recVUMI_SUBA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_SUBAx(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 0, info); } +void recVUMI_SUBAy(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 1, info); } +void recVUMI_SUBAz(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 2, info); } +void recVUMI_SUBAw(VURegs *VU, int info) { recVUMI_SUBA_xyzw(VU, 3, info); } + +void recVUMI_MUL_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W == 1 && (_Ft_ == 0 || _Fs_==0) ) { // W + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, _Ft_ ? EEREC_T : EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( _Fd_ == _Fs_ && _Fs_ == _Ft_ && _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MULSS_XMM_to_XMM(EEREC_D, EEREC_D); + _vuFlipRegSS(VU, EEREC_D); + } + else if( _X_Y_Z_W == 8 ) { + if (regd == EEREC_S) SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + else if (regd == EEREC_T) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + } + } +} + +void recVUMI_MUL_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _XYZW_SS ) { + if( regd == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, EEREC_S); + } + else if( regd == EEREC_S ) { + _vuFlipRegSS(VU, regd); + SSE_MULSS_M32_to_XMM(regd, addr); + _vuFlipRegSS(VU, regd); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + if( xyzw < 3 ) { + if (_X_Y_Z_W != 0xf) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + SSE_XORPS_XMM_to_XMM(regd, regd); + } + } + else { + assert(xyzw==3); + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else if( regd != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + } + } + else if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + if( xyzw == 0 ) { + if( regd == EEREC_T ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_TEMP ) SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + else if (regd == EEREC_S) SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + } + } + } +} + +void recVUMI_MUL(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MUL_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + // spacefisherman needs overflow checking on MULi.z + if( addr == VU_REGQ_ADDR || _Z ) + CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MUL_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MULi(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULq(VURegs *VU, int info) { recVUMI_MUL_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULx(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 0, info); } +void recVUMI_MULy(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 1, info); } +void recVUMI_MULz(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 2, info); } +void recVUMI_MULw(VURegs *VU, int info) { recVUMI_MUL_xyzw(VU, 3, info); } + +void recVUMI_MULA( VURegs *VU, int info ) +{ + recVUMI_MUL_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_iq(VURegs *VU, int addr, int info) +{ + recVUMI_MUL_iq_toD(VU, addr, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULA_xyzw(VURegs *VU, int xyzw, int info) +{ + recVUMI_MUL_xyzw_toD(VU, xyzw, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MULAi(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MULAq(VURegs *VU, int info) { recVUMI_MULA_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MULAx(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 0, info); } +void recVUMI_MULAy(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 1, info); } +void recVUMI_MULAz(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 2, info); } +void recVUMI_MULAw(VURegs *VU, int info) { recVUMI_MULA_xyzw(VU, 3, info); } + +void recVUMI_MADD_toD(VURegs *VU, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + SSE_MOVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if (regd == EEREC_T) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if (regd == EEREC_S) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } +} + +void recVUMI_MADD_iq_toD(VURegs *VU, int addr, int regd, int info) +{ + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_ACC ) { + if( _Fs_ == 0 ) { + // add addr to w + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + else { + assert( EEREC_TEMP < XMMREGS ); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else if( regd == EEREC_S ) { + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_S); + SSE_MULSS_M32_to_XMM(regd, addr); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + } + else { + if( _Fs_ == 0 ) { + // add addr to w + if( _W ) { + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + SSE_ADDSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x27); + } + + return; + } + + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + } + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_M32_to_XMM(regd, addr); + SSE_SHUFPS_XMM_to_XMM(regd, regd, 0x00); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD_xyzw_toD(VURegs *VU, int xyzw, int regd, int info) +{ + if( _Ft_ == 0 ) { + + if( xyzw == 3 ) { + // just add + if( _X_Y_Z_W == 8 ) { + if( regd == EEREC_S ) SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_S); + } + } + else { + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_S ) SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_S); + } + } + } + } + else { + // just move acc to regd + if( _X_Y_Z_W != 0xf ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + + return; + } + + if( _X_Y_Z_W == 8 ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if( regd == EEREC_ACC ) { + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULSS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + SSE_MOVSS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDSS_XMM_to_XMM(regd, EEREC_TEMP); + } + } + else { + if( _X_Y_Z_W != 0xf || regd == EEREC_ACC || regd == EEREC_TEMP || regd == EEREC_S ) + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + + if (_X_Y_Z_W != 0xf) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + + VU_MERGE_REGS(regd, EEREC_TEMP); + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + else { + _unpackVF_xyzw(regd, EEREC_T, xyzw); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_ADDPS_XMM_to_XMM(regd, EEREC_ACC); + } + } + } +} + +void recVUMI_MADD(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MADD_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_iq_toD(VU, addr, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MADD_xyzw(VURegs *VU, int xyzw, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MADD_xyzw_toD(VU, xyzw, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); + + // super bust-a-move arrows + CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MADDi(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MADDq(VURegs *VU, int info) { recVUMI_MADD_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MADDx(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 0, info); } +void recVUMI_MADDy(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 1, info); } +void recVUMI_MADDz(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 2, info); } +void recVUMI_MADDw(VURegs *VU, int info) { recVUMI_MADD_xyzw(VU, 3, info); } + +void recVUMI_MADDA( VURegs *VU, int info ) +{ + recVUMI_MADD_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAi( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_VI_ADDR(REG_I, 1), EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAq( VURegs *VU , int info) +{ + recVUMI_MADD_iq_toD( VU, VU_REGQ_ADDR, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAx( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 0, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAy( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 1, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAz( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 2, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MADDAw( VURegs *VU , int info) +{ + recVUMI_MADD_xyzw_toD(VU, 3, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUB_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + VU_MERGE_REGS(regd, t1reg); + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_S ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (uptr)&const_clip[4]); + } + else if( regd == EEREC_T ) { + assert( regd != EEREC_ACC ); + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (uptr)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MOVAPS_XMM_to_XMM(regd, EEREC_S); + SSE_MULPS_XMM_to_XMM(regd, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (uptr)&const_clip[4]); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_temp_toD(VURegs *VU, int regd, int info) +{ + if (_X_Y_Z_W != 0xf) { + int t1reg = _vuGetTempXMMreg(info); + + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + if( t1reg >= 0 ) { + SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_ACC); + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + + if( regd != EEREC_TEMP ) { + VU_MERGE_REGS(regd, t1reg); + } + else + SSE_MOVAPS_XMM_to_XMM(regd, t1reg); + + _freeXMMreg(t1reg); + } + else { + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS(regd, EEREC_TEMP); + } + } + else { + if( regd == EEREC_ACC ) { + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + else if( regd == EEREC_S ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_TEMP); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (uptr)&const_clip[4]); + } + else if( regd == EEREC_TEMP ) { + SSE_MULPS_XMM_to_XMM(regd, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_XORPS_M128_to_XMM(regd, (uptr)&const_clip[4]); + } + else { + if( regd != EEREC_ACC ) SSE_MOVAPS_XMM_to_XMM(regd, EEREC_ACC); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SUBPS_XMM_to_XMM(regd, EEREC_TEMP); + } + } +} + +void recVUMI_MSUB_iq_toD(VURegs *VU, int regd, int addr, int info) +{ + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB_xyzw_toD(VURegs *VU, int regd, int xyzw, int info) +{ + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + recVUMI_MSUB_temp_toD(VU, regd, info); +} + +void recVUMI_MSUB(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_toD(VU, EEREC_D, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUB_iq(VURegs *VU, int addr, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_iq_toD(VU, EEREC_D, addr, info); + recUpdateFlags(VU, EEREC_D, info); + + if( addr == VU_REGQ_ADDR ) CheckForOverflow(VU, info, EEREC_D); +} + +void recVUMI_MSUBi(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MSUBq(VURegs *VU, int info) { recVUMI_MSUB_iq(VU, VU_REGQ_ADDR, info); } +void recVUMI_MSUBx(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 0, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBy(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 1, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBz(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 2, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBw(VURegs *VU, int info) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + recVUMI_MSUB_xyzw_toD(VU, EEREC_D, 3, info); + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_MSUBA( VURegs *VU, int info ) +{ + recVUMI_MSUB_toD(VU, EEREC_ACC, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAi( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_VI_ADDR(REG_I, 1), info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAq( VURegs *VU, int info ) +{ + recVUMI_MSUB_iq_toD( VU, EEREC_ACC, VU_REGQ_ADDR, info ); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAx( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 0, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAy( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 1, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAz( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 2, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MSUBAw( VURegs *VU, int info ) +{ + recVUMI_MSUB_xyzw_toD(VU, EEREC_ACC, 3, info); + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_MAX(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MAX_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MAX_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + else if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MAXSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) { + if( _X_Y_Z_W & 1 ) { + // w included, so insert the whole reg + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (uptr)&VU->VF[0].UL[0]); + } + else { + // w not included, can zero out + SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + } + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + } + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( _Fs_ == 0 && _Ft_ == 0 ) { + if( xyzw < 3 ) SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + else SSE_MOVAPS_M128_to_XMM(EEREC_D, (u32)s_fones); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MAXPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } + } +} + +void recVUMI_MAXi(VURegs *VU, int info) { recVUMI_MAX_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MAXx(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 0, info); } +void recVUMI_MAXy(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 1, info); } +void recVUMI_MAXz(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 2, info); } +void recVUMI_MAXw(VURegs *VU, int info) { recVUMI_MAX_xyzw(VU, 3, info); } + +void recVUMI_MINI(VURegs *VU, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if (EEREC_D == EEREC_S) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if (EEREC_D == EEREC_T) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if( EEREC_D == EEREC_S ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_T, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + else if( EEREC_D == EEREC_T ) { + // need for GT4 vu0rec + ClampUnordered(EEREC_S, EEREC_TEMP, 0); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + else { + SSE_MOVAPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } +} + +void recVUMI_MINI_iq(VURegs *VU, int addr, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _XYZW_SS ) { + if( EEREC_D == EEREC_TEMP ) { + _vuFlipRegSS(VU, EEREC_S); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else if( EEREC_D == EEREC_S ) { + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( _X ) { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_M32_to_XMM(EEREC_D, addr); + } + else { + _vuMoveSS(VU, EEREC_TEMP, EEREC_S); + _vuFlipRegSS(VU, EEREC_D); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_D); + } + } + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if(EEREC_D == EEREC_S) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_D, addr); + SSE_SHUFPS_XMM_to_XMM(EEREC_D, EEREC_D, 0x00); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINI_xyzw(VURegs *VU, int xyzw, int info) +{ + if ( _Fd_ == 0 ) return; + + if( _X_Y_Z_W == 8 ) { + if( EEREC_D == EEREC_TEMP ) { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + + // have to flip over EEREC_D if computing flags! + if( (info & PROCESS_VU_UPDATEFLAGS) ) + _vuFlipRegSS(VU, EEREC_D); + } + else { + if( xyzw == 0 ) { + if( EEREC_D == EEREC_S ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_S); + else { + SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_T); + } + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_T, xyzw); + if( EEREC_D != EEREC_S ) SSE_MOVSS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE_MINSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + } + } + else if (_X_Y_Z_W != 0xf) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_D, EEREC_TEMP); + } + else { + if (EEREC_D == EEREC_S) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + } + else { + _unpackVF_xyzw(EEREC_D, EEREC_T, xyzw); + SSE_MINPS_XMM_to_XMM(EEREC_D, EEREC_S); + } + } +} + +void recVUMI_MINIi(VURegs *VU, int info) { recVUMI_MINI_iq(VU, VU_VI_ADDR(REG_I, 1), info); } +void recVUMI_MINIx(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 0, info); } +void recVUMI_MINIy(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 1, info); } +void recVUMI_MINIz(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 2, info); } +void recVUMI_MINIw(VURegs *VU, int info) { recVUMI_MINI_xyzw(VU, 3, info); } + +void recVUMI_OPMULA( VURegs *VU, int info ) +{ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xD2); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T ); + + VU_MERGE_REGS_CUSTOM(EEREC_ACC, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_ACC ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_ACC, info); +} + +void recVUMI_OPMSUB( VURegs *VU, int info ) +{ + if( !_Fd_ ) info |= PROCESS_EE_SET_D(EEREC_TEMP); + + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM( EEREC_T, EEREC_T, 0xD2 ); // EEREC_T = WYXZ + SSE_SHUFPS_XMM_to_XMM( EEREC_TEMP, EEREC_TEMP, 0xC9 ); // EEREC_TEMP = WXZY + SSE_MULPS_XMM_to_XMM( EEREC_TEMP, EEREC_T); + + // negate and add + SSE_XORPS_M128_to_XMM(EEREC_TEMP, (uptr)&const_clip[4]); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_ACC); + VU_MERGE_REGS_CUSTOM(EEREC_D, EEREC_TEMP, 14); + + // revert EEREC_T + if( EEREC_T != EEREC_D ) + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xC9); + + recUpdateFlags(VU, EEREC_D, info); +} + +void recVUMI_NOP( VURegs *VU, int info ) +{ +} + +void recVUMI_FTOI0(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_FTOIX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if (EEREC_T != EEREC_S) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + else SSE2EMU_CVTPS2DQ_XMM_to_XMM(EEREC_T, EEREC_T); + } +} + +void recVUMI_FTOI4( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (uptr)&recMult_float_to_int4[0], info); } +void recVUMI_FTOI12( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (uptr)&recMult_float_to_int12[0], info); } +void recVUMI_FTOI15( VURegs *VU, int info ) { recVUMI_FTOIX(VU, (uptr)&recMult_float_to_int15[0], info); } + +void recVUMI_ITOF0( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + else { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + } +} + +void recVUMI_ITOFX(VURegs *VU, int addr, int info) +{ + if ( _Ft_ == 0 ) return; + + if (_X_Y_Z_W != 0xf) { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_TEMP, VU_VFx_ADDR( _Fs_ )); + } + + SSE_MULPS_M128_to_XMM(EEREC_TEMP, addr); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } else { + if(cpucaps.hasStreamingSIMD2Extensions) SSE2_CVTDQ2PS_XMM_to_XMM(EEREC_T, EEREC_S); + else { + _deleteVFtoXMMreg(_Fs_, VU==&VU1, 1); + SSE2EMU_CVTDQ2PS_M128_to_XMM(EEREC_T, VU_VFx_ADDR( _Fs_ )); + xmmregs[EEREC_T].mode |= MODE_WRITE; + } + + SSE_MULPS_M128_to_XMM(EEREC_T, addr); + } +} + +void recVUMI_ITOF4( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (uptr)&recMult_int_to_float4[0], info); } +void recVUMI_ITOF12( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (uptr)&recMult_int_to_float12[0], info); } +void recVUMI_ITOF15( VURegs *VU, int info ) { recVUMI_ITOFX(VU, (uptr)&recMult_int_to_float15[0], info); } + +void recVUMI_CLIP(VURegs *VU, int info) +{ + int t1reg = EEREC_D; + int t2reg = EEREC_ACC; + int x86temp0, x86temp1; + + u32 clipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + u32 prevclipaddr = VU_VI_ADDR(REG_CLIP_FLAG, 2); + + if( clipaddr == 0 ) { + // battle star has a clip right before fcset + SysPrintf("skipping vu clip\n"); + return; + } + assert( clipaddr != 0 ); + assert( t1reg != t2reg && t1reg != EEREC_TEMP && t2reg != EEREC_TEMP ); + + x86temp1 = ALLOCTEMPX86(MODE_8BITREG); + x86temp0 = ALLOCTEMPX86(0); + + if( _Ft_ == 0 ) { + // all 1s + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (uptr)&s_fones[0]); + SSE_MOVAPS_M128_to_XMM(t1reg, (uptr)&s_fones[4]); + + MOV32MtoR(EAX, prevclipaddr); + } + else { + _unpackVF_xyzw(EEREC_TEMP, EEREC_T, 3); + SSE_XORPS_XMM_to_XMM(t1reg, t1reg); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (int)const_clip); + + MOV32MtoR(EAX, prevclipaddr); + + SSE_SUBPS_XMM_to_XMM(t1reg, EEREC_TEMP); + } + + SSE_CMPLTPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_CMPNLEPS_XMM_to_XMM(t1reg, EEREC_S); + + SHL32ItoR(EAX, 6); + + SSE_MOVAPS_XMM_to_XMM(t2reg, EEREC_TEMP); + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, t1reg); + SSE_UNPCKHPS_XMM_to_XMM(t2reg, t1reg); + SSE_MOVMSKPS_XMM_to_R32(x86temp0, EEREC_TEMP); // -y,+y,-x,+x + SSE_MOVMSKPS_XMM_to_R32(x86temp1, t2reg); // -w,+w,-z,+z + + AND32ItoR(EAX, 0xffffff); + + AND8ItoR(x86temp1, 0x3); + SHL32ItoR(x86temp1, 4); + OR32RtoR(EAX, x86temp0); + OR32RtoR(EAX, x86temp1); + + MOV32RtoM(clipaddr, EAX); + if( !(info&(PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) MOV32RtoM((uptr)&VU->VI[REG_CLIP_FLAG], EAX); + + _freeXMMreg(t1reg); + _freeXMMreg(t2reg); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); +} + +/******************************/ +/* VU Lower instructions */ +/******************************/ + +void recVUMI_DIV(VURegs *VU, int info) +{ + if( _Fs_ == 0 ) { + + if( _Ft_ == 0 ) { + if( _Fsf_ < 3 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0); + else if( _Ftf_ < 0 ) MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x7f7fffff); + else MOV32ItoM(VU_VI_ADDR(REG_Q, 0), 0x3f800000); + return; + } + + if( _Fsf_ == 3 ) { // = 1 + // don't use RCPSS (very bad precision) + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[0].UL[3]); + + if( _Ftf_ == 0 || (xmmregs[EEREC_T].mode & MODE_WRITE) ) { + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[_Ft_].UL[_Ftf_]); + } + } + else { // = 0 + MOV32ItoR(VU_VI_ADDR(REG_Q, 0), 0); + return; + } + } + else { + if( _Fsf_ == 0 ) SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + else _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(2*_Ftf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + + // revert + if( _Ftf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, (0xe4e4>>(8-2*_Ftf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_maxvals[0]); + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_minvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_SQRT( VURegs *VU, int info ) +{ + if( _Ftf_ ) { + if( xmmregs[EEREC_T].mode & MODE_WRITE ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[_Ft_].UL[_Ftf_]); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + } + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void recVUMI_RSQRT(VURegs *VU, int info) +{ + if( _Ftf_ ) { + SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + _unpackVF_xyzw(EEREC_TEMP, EEREC_TEMP, _Ftf_); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (u32)const_clip); + SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_T); + } + + if( _Fs_ == 0 ) { + if( _Fsf_ == 3 ) SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + + //if( !CHECK_FORCEABS ) { + SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_minvals[0]); + SSE_MINSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_maxvals[0]); + //} + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_Q, 0), EEREC_TEMP); +} + +void _addISIMMtoIT(VURegs *VU, s16 imm, int info) +{ + int fsreg = -1, ftreg; + if (_Ft_ == 0) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32ItoR(ftreg, imm&0xffff); + return; + } + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if (ftreg == fsreg) { + if (imm != 0 ) { + ADD16ItoR(ftreg, imm); + } + } else { + if( imm ) { + LEA32RtoR(ftreg, fsreg, imm); + MOVZX32R16toR(ftreg, ftreg); + } + else MOV32RtoR(ftreg, fsreg); + } +} + +void recVUMI_IADDI(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code >> 6 ) & 0x1f; + imm = ( imm & 0x10 ? 0xfff0 : 0) | ( imm & 0xf ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADDIU(VURegs *VU, int info) +{ + int imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + _addISIMMtoIT(VU, imm, info); +} + +void recVUMI_IADD( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else { + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) ADD32RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) ADD32RtoR(fdreg, fsreg); + else LEA16RRtoR(fdreg, fsreg, ftreg); + MOVZX32R16toR(fdreg, fdreg); // neeed since don't know if fdreg's upper bits are 0 + } +} + +void recVUMI_IAND( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Fs_ == 0 ) || ( _Ft_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) AND16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) AND16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, ftreg); + AND32RtoR(fdreg, fsreg); + } +} + +void recVUMI_IOR( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) OR16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) OR16RtoR(fdreg, fsreg); + else { + MOV32RtoR(fdreg, fsreg); + OR32RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUB( VURegs *VU, int info ) +{ + int fdreg, fsreg = -1, ftreg = -1; + if ( _Fd_ == 0 ) return; + + if ( ( _Ft_ == 0 ) && ( _Fs_ == 0 ) ) { + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + XOR32RtoR(fdreg, fdreg); + return; + } + + ADD_VI_NEEDED(_Fs_); + ADD_VI_NEEDED(_Ft_); + fdreg = ALLOCVI(_Fd_, MODE_WRITE); + + if ( _Fs_ == 0 ) + { + if( (ftreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, MODE_READ)) >= 0 ) { + if( fdreg != ftreg ) MOV32RtoR(fdreg, ftreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Ft_, 1)); + } + NEG16R(fdreg); + } + else if ( _Ft_ == 0 ) + { + if( (fsreg = _checkX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, MODE_READ)) >= 0 ) { + if( fdreg != fsreg ) MOV32RtoR(fdreg, fsreg); + } + else { + MOVZX32M16toR(fdreg, VU_VI_ADDR(_Fs_, 1)); + } + } + else + { + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if( fdreg == fsreg ) SUB16RtoR(fdreg, ftreg); + else if( fdreg == ftreg ) { + SUB16RtoR(fdreg, fsreg); + NEG16R(fdreg); + } + else { + MOV32RtoR(fdreg, fsreg); + SUB16RtoR(fdreg, ftreg); + } + } +} + +void recVUMI_ISUBIU( VURegs *VU, int info ) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = ( ( VU->code >> 10 ) & 0x7800 ) | ( VU->code & 0x7ff ); + imm = -imm; + _addISIMMtoIT(VU, (u32)imm & 0xffff, info); +} + +void recVUMI_MOVE( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + } +} + +void recVUMI_MFIR( VURegs *VU, int info ) +{ + static u32 s_temp; + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Fs_, 1); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + if( _XYZW_SS ) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + _vuFlipRegSS(VU, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE2_MOVD_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_TEMP, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } else { + SSE2_MOVD_M32_to_XMM(EEREC_T, VU_VI_ADDR(_Fs_, 1)-2); + SSE2_PSRAD_I8_to_XMM(EEREC_T, 16); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } + else { + MOVSX32M16toR(EAX, VU_VI_ADDR(_Fs_, 1)); + MOV32RtoM((uptr)&s_temp, EAX); + + if( _X_Y_Z_W != 0xf ) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, (uptr)&s_temp); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } + } +} + +void recVUMI_MTIR( VURegs *VU, int info ) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|((VU==&VU1)?X86TYPE_VU1:0), _Ft_, 2); + + if( _Fsf_ == 0 ) { + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_S); + } + else { + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(_Ft_, 0), EEREC_TEMP); + } + + AND32ItoM(VU_VI_ADDR(_Ft_, 0), 0xffff); +} + +void recVUMI_MR32( VURegs *VU, int info ) +{ + if (_Ft_ == 0) return; + + if (_X_Y_Z_W != 0xf) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x39); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + if( EEREC_T != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(EEREC_T, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x39); + } +} + +// if x86reg < 0, reads directly from offset +void _loadEAX(VURegs *VU, int x86reg, uptr offset, int info) +{ + assert( offset < 0x80000000 ); + + if( x86reg >= 0 ) { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + + case 8: // X + SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } + else { + switch(_X_Y_Z_W) { + case 3: // ZW + SSE_MOVHPS_M64_to_XMM(EEREC_T, offset+8); + break; + case 6: // YZ + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0x9c); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); + break; + case 8: // X + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, offset); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + break; + case 9: // XW + SSE_SHUFPS_M128_to_XMM(EEREC_T, offset, 0xc9); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); + break; + case 12: // XY + SSE_MOVLPS_M64_to_XMM(EEREC_T, offset); + break; + case 15: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_T, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_T, offset); + break; + default: + if( VU == &VU1 ) SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + break; + } + } +} + +int recVUTransformAddr(int x86reg, VURegs* VU, int vireg, int imm) +{ + u8* pjmp[2]; + if( x86reg == EAX ) { + if (imm) ADD32ItoR(x86reg, imm); + } + else { + if( imm ) LEA32RtoR(EAX, x86reg, imm); + else MOV32RtoR(EAX, x86reg); + } + + if( VU == &VU1 ) { + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0x3fff); + } + else { + // if addr >= 4200, reads integers + CMP32ItoR(EAX, 0x420); + pjmp[0] = JL8(0); + AND32ItoR(EAX, 0x1f); + SHL32ItoR(EAX, 2); + OR32ItoR(EAX, 0x4200); + + pjmp[1] = JMP8(0); + x86SetJ8(pjmp[0]); + SHL32ItoR(EAX, 4); + AND32ItoR(EAX, 0xfff); // can be removed + + x86SetJ8(pjmp[1]); + } + + return EAX; +} + +void recVUMI_LQ(VURegs *VU, int info) +{ + s16 imm; + + if ( _Ft_ == 0 ) return; + + imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); + if (_Fs_ == 0) { + _loadEAX(VU, -1, (uptr)GET_VU_MEM(VU, (u32)imm*16), info); + } else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem, info); + } +} + +void recVUMI_LQD( VURegs *VU, int info ) +{ + int fsreg; + + if ( _Fs_ != 0 ) { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + SUB16ItoR( fsreg, 1 ); + } + + if ( _Ft_ == 0 ) return; + + if ( _Fs_ == 0 ) { + _loadEAX(VU, -1, (uptr)VU->Mem, info); + } else { + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem, info); + } +} + +void recVUMI_LQI(VURegs *VU, int info) +{ + int fsreg; + + if ( _Ft_ == 0 ) { + if( _Fs_ != 0 ) { + if( (fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_WRITE|MODE_READ)) >= 0 ) { + ADD16ItoR(fsreg, 1); + } + else { + ADD16ItoM( VU_VI_ADDR( _Fs_, 0 ), 1 ); + } + } + return; + } + + if (_Fs_ == 0) { + _loadEAX(VU, -1, (uptr)VU->Mem, info); + } else { + fsreg = ALLOCVI(_Fs_, MODE_READ|MODE_WRITE); + _loadEAX(VU, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem, info); + ADD16ItoR( fsreg, 1 ); + } +} + +void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) +{ + int t1reg; + assert( offset < 0x80000000 ); + + if( _Fs_ == 0 ) { + if( _XYZW_SS ) { + u32 c = _W ? 0x3f800000 : 0; + if( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); + else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c); + } + else { + int zeroreg = (x86reg == EAX) ? ALLOCTEMPX86(0) : EAX; + + XOR32RtoR(zeroreg, zeroreg); + if( x86reg >= 0 ) { + if( _X ) MOV32RtoRmOffset(x86reg, zeroreg, offset); + if( _Y ) MOV32RtoRmOffset(x86reg, zeroreg, offset+4); + if( _Z ) MOV32RtoRmOffset(x86reg, zeroreg, offset+8); + if( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12); + } + else { + if( _X ) MOV32RtoM(offset, zeroreg); + if( _Y ) MOV32RtoM(offset+4, zeroreg); + if( _Z ) MOV32RtoM(offset+8, zeroreg); + if( _W ) MOV32ItoM(offset+12, 0x3f800000); + } + + if( zeroreg != EAX ) _freeX86reg(zeroreg); + } + return; + } + + switch(_X_Y_Z_W) { + case 1: // W + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0x27); + break; + case 2: // Z + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + break; + case 3: // ZW + if( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S); + break; + case 4: // Y + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xe1); + break; + case 6: // YZ + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xc9); + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); + else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_S); + SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xd2); + break; + case 8: // X + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + break; + case 9: // XW + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); + + if( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + + if( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); + + break; + case 12: // XY + if( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + break; + + case 14: // XYZ + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + if( x86reg >= 0 ) { + SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + } + else { + SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); + SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); + } + break; + case 15: // XYZW + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); + } + } + break; + default: + + // EEREC_D is a temp reg + // find the first nonwrite reg + t1reg = _vuGetTempXMMreg(info); + + if( t1reg < 0 ) { + for(t1reg = 0; t1reg < XMMREGS; ++t1reg) { + if( xmmregs[t1reg].inuse && !(xmmregs[t1reg].mode&MODE_WRITE) ) break; + } + + if( t1reg == XMMREGS ) t1reg = -1; + else { + if( t1reg != EEREC_S ) _allocTempXMMreg(XMMT_FPS, t1reg); + } + } + + if( t1reg >= 0 ) { + // found a temp reg + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + if( t1reg != EEREC_S ) SSE_MOVAPS_XMM_to_XMM(t1reg, EEREC_S); + + VU_MERGE_REGS(EEREC_TEMP, t1reg); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + } + + if( t1reg != EEREC_S ) _freeXMMreg(t1reg); + else { + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (uptr)&VU->VF[_Fs_]); + } + } + else { + // do it with one reg + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + else { + if( offset & 15 ) SSE_MOVUPS_M128_to_XMM(EEREC_TEMP, offset); + else SSE_MOVAPS_M128_to_XMM(EEREC_TEMP, offset); + } + } + + VU_MERGE_REGS(EEREC_TEMP, EEREC_S); + + if( VU == &VU1 ) { + if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + else { + if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_TEMP, offset); + else { + if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_TEMP); + else SSE_MOVAPS_XMM_to_M128(offset, EEREC_TEMP); + } + } + + // read back the data + SSE_MOVAPS_M128_to_XMM(EEREC_S, (uptr)&VU->VF[_Fs_]); + } + + break; + } +} + +void recVUMI_SQ(VURegs *VU, int info) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if ( _Ft_ == 0 ) { + _saveEAX(VU, -1, (uptr)GET_VU_MEM(VU, (int)imm * 16), info); + } + else { + int ftreg = ALLOCVI(_Ft_, MODE_READ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, imm), (uptr)VU->Mem, info); + } +} + +void recVUMI_SQD(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (uptr)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + SUB16ItoR( ftreg, 1 ); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (uptr)VU->Mem, info); + } +} + +void recVUMI_SQI(VURegs *VU, int info) +{ + if (_Ft_ == 0) { + _saveEAX(VU, -1, (uptr)VU->Mem, info); + } else { + int ftreg = ALLOCVI(_Ft_, MODE_READ|MODE_WRITE); + _saveEAX(VU, recVUTransformAddr(ftreg, VU, _Ft_, 0), (uptr)VU->Mem, info); + + ADD16ItoR( ftreg, 1 ); + } +} + +void recVUMI_ILW(VURegs *VU, int info) +{ + int ftreg; + s16 imm, off; + + if ( _Ft_ == 0 ) return; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (uptr)GET_VU_MEM(VU, (int)imm * 16 + off) ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem + off); + } +} + +void recVUMI_ISW( VURegs *VU, int info ) +{ + s16 imm; + + imm = ( VU->code & 0x400) ? ( VU->code & 0x3ff) | 0xfc00 : ( VU->code & 0x3ff); + + if (_Fs_ == 0) { + uptr off = (uptr)GET_VU_MEM(VU, (int)imm * 16); + int ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_X) MOV32RtoM(off, ftreg); + if (_Y) MOV32RtoM(off+4, ftreg); + if (_Z) MOV32RtoM(off+8, ftreg); + if (_W) MOV32RtoM(off+12, ftreg); + } + else { + int x86reg, fsreg, ftreg; + + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12); + } +} + +void recVUMI_ILWR( VURegs *VU, int info ) +{ + int off, ftreg; + + if ( _Ft_ == 0 ) return; + + if (_X) off = 0; + else if (_Y) off = 4; + else if (_Z) off = 8; + else if (_W) off = 12; + + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + if ( _Fs_ == 0 ) { + MOVZX32M16toR( ftreg, (uptr)VU->Mem + off ); + } + else { + int fsreg = ALLOCVI(_Fs_, MODE_READ); + MOVZX32Rm16toROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem + off); + } +} + +void recVUMI_ISWR( VURegs *VU, int info ) +{ + int ftreg; + ADD_VI_NEEDED(_Fs_); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + if (_Fs_ == 0) { + if (_X) MOV32RtoM((uptr)VU->Mem, ftreg); + if (_Y) MOV32RtoM((uptr)VU->Mem+4, ftreg); + if (_Z) MOV32RtoM((uptr)VU->Mem+8, ftreg); + if (_W) MOV32RtoM((uptr)VU->Mem+12, ftreg); + } + else { + int x86reg; + int fsreg = ALLOCVI(_Fs_, MODE_READ); + x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0); + + if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem); + if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4); + if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8); + if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12); + } +} + +void recVUMI_RINIT(VURegs *VU, int info) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 2); + + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (uptr)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (uptr)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + MOV32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR( rreg, 0x7f << 23 ); + } +} + +void recVUMI_RGET(VURegs *VU, int info) +{ + if ( _Ft_ == 0 ) return; + + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + + if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_REGR_ADDR); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +void recVUMI_RNEXT( VURegs *VU, int info ) +{ + int rreg, x86temp0, x86temp1; + if ( _Ft_ == 0) return; + + rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + x86temp0 = ALLOCTEMPX86(0); + x86temp1 = ALLOCTEMPX86(0); + + // code from www.project-fao.org + MOV32MtoR(rreg, VU_REGR_ADDR); + MOV32RtoR(x86temp0, rreg); + SHR32ItoR(x86temp0, 4); + AND32ItoR(x86temp0, 1); + + MOV32RtoR(x86temp1, rreg); + SHR32ItoR(x86temp1, 22); + AND32ItoR(x86temp1, 1); + + SHL32ItoR(rreg, 1); + XOR32RtoR(x86temp0, x86temp1); + XOR32RtoR(rreg, x86temp0); + AND32ItoR(rreg, 0x7fffff); + OR32ItoR(rreg, 0x3f800000); + + _freeX86reg(x86temp0); + _freeX86reg(x86temp1); + + recVUMI_RGET(VU, info); +} + +void recVUMI_RXOR( VURegs *VU, int info ) +{ + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode & MODE_NOFLUSH) ) { + _deleteX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), REG_R, 1); + _unpackVFSS_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + + SSE_XORPS_M128_to_XMM(EEREC_TEMP, VU_REGR_ADDR); + SSE_ANDPS_M128_to_XMM(EEREC_TEMP, (u32)s_mask); + SSE_ORPS_M128_to_XMM(EEREC_TEMP, (u32)s_fones); + SSE_MOVSS_XMM_to_M32(VU_REGR_ADDR, EEREC_TEMP); + } + else { + int rreg = ALLOCVI(REG_R, MODE_WRITE|MODE_READ); + + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + XOR32MtoR( rreg, VU_VFx_ADDR( _Fs_ ) + 4 * _Fsf_ ); + AND32ItoR( rreg, 0x7fffff ); + OR32ItoR ( rreg, 0x3f800000 ); + } +} + +void recVUMI_WAITQ( VURegs *VU, int info ) +{ +// if( info & PROCESS_VU_SUPER ) { +// //CALLFunc(waitqfn); +// SuperVUFlush(0, 1); +// } +} + +void recVUMI_FSAND( VURegs *VU, int info ) +{ + int ftreg; + u16 imm; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV32MtoR(ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1)); + AND32ItoR( ftreg, 0xFF&imm ); // yes 0xff not 0xfff since only first 8 bits are valid! +} + +void recVUMI_FSEQ( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if ( _Ft_ == 0 ) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( EAX, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + XOR32RtoR(ftreg, ftreg); + + CMP16ItoR(EAX, imm); + SETE8R(ftreg); +} + +void recVUMI_FSOR( VURegs *VU, int info ) +{ + int ftreg; + u32 imm; + if(_Ft_ == 0) return; + + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7ff); + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( ftreg, VU_VI_ADDR(REG_STATUS_FLAG, 1) ); + OR32ItoR( ftreg, imm ); +} + +void recVUMI_FSSET(VURegs *VU, int info) +{ + u32 writeaddr = VU_VI_ADDR(REG_STATUS_FLAG, 0); + u32 prevaddr = VU_VI_ADDR(REG_STATUS_FLAG, 2); + + u16 imm = 0; + imm = (((VU->code >> 21 ) & 0x1) << 11) | (VU->code & 0x7FF); + + MOV32MtoR(EAX, prevaddr); + AND32ItoR(EAX, 0x3f); + if ((imm&0xfc0) != 0) OR32ItoR(EAX, imm & 0xFC0); + + MOV32RtoM(writeaddr ? writeaddr : prevaddr, EAX); +} + +void recVUMI_FMAND( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + + if( fsreg >= 0 ) { + if( ftreg != fsreg ) MOV32RtoR(ftreg, fsreg); + } + else MOV8MtoR(ftreg, VU_VI_ADDR(_Fs_, 1)); + + //AND16MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + AND8MtoR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + MOVZX32R8toR(ftreg, ftreg); +} + +void recVUMI_FMEQ( VURegs *VU, int info ) +{ + int ftreg, fsreg; + if ( _Ft_ == 0 ) return; + + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + // really 8 since not doing under/over flows + CMP8MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(EAX); + MOVZX32R8toR(ftreg, EAX); + } + else { + ADD_VI_NEEDED(_Fs_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + + XOR32RtoR(ftreg, ftreg); + + CMP8MtoR(fsreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + SETE8R(ftreg); + } +} + +void recVUMI_FMOR( VURegs *VU, int info ) +{ + int fsreg, ftreg; + if ( _Ft_ == 0 ) return; + + if( _Fs_ == 0 ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_8BITREG); + MOVZX32M8toR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + if( _Ft_ == _Fs_ ) { + ftreg = ALLOCVI(_Ft_, MODE_WRITE|MODE_READ|MODE_8BITREG); + OR8MtoR(ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + } + else { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOVZX32M8toR( ftreg, VU_VI_ADDR(REG_MAC_FLAG, 1)); + + if( fsreg >= 0 ) { + OR16RtoR( ftreg, fsreg); + } + else { + OR16MtoR( ftreg, VU_VI_ADDR(_Fs_, 1)); + } + } +} + +void recVUMI_FCAND( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + XOR32RtoR(ftreg, ftreg); + AND32ItoR( EAX, VU->code & 0xFFFFFF ); + SETNZ8R(ftreg); +} + +void recVUMI_FCEQ( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + CMP32ItoR( EAX, VU->code&0xffffff ); + SETE8R(ftreg); +} + +void recVUMI_FCOR( VURegs *VU, int info ) +{ + int ftreg = ALLOCVI(1, MODE_WRITE|MODE_8BITREG); + + MOV32MtoR( EAX, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + //AND32ItoR( EAX, 0xffffff); + XOR32RtoR(ftreg, ftreg); + OR32ItoR( EAX, (VU->code & 0xFFFFFF)|0xff000000 ); + ADD32ItoR(EAX, 1); + + // set to 1 if EAX is 0 + SETZ8R(ftreg); +} + +void recVUMI_FCSET( VURegs *VU, int info ) +{ + u32 addr = VU_VI_ADDR(REG_CLIP_FLAG, 0); + + MOV32ItoM(addr ? addr : VU_VI_ADDR(REG_CLIP_FLAG, 2), VU->code&0xffffff ); + + if( !(info & (PROCESS_VU_SUPER|PROCESS_VU_COP2)) ) + MOV32ItoM( VU_VI_ADDR(REG_CLIP_FLAG, 1), VU->code&0xffffff ); +} + +void recVUMI_FCGET( VURegs *VU, int info ) +{ + int ftreg; + if(_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + + MOV32MtoR(ftreg, VU_VI_ADDR(REG_CLIP_FLAG, 1)); + AND32ItoR(ftreg, 0x0fff); +} + +// SuperVU branch fns are in ivuzerorec.cpp +static s32 _recbranchAddr(VURegs * VU) +{ + bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + if (VU == &VU1) { + bpc&= 0x3fff; + } else { + bpc&= 0x0fff; + } + + return bpc; +} + +void recVUMI_IBEQ(VURegs *VU, int info) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBGTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + + // supervu will take care of the rest + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLEZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBLTZ( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16ItoR( fsreg, 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_IBNE( VURegs *VU, int info ) +{ + int fsreg, ftreg; + ADD_VI_NEEDED(_Ft_); + fsreg = ALLOCVI(_Fs_, MODE_READ); + ftreg = ALLOCVI(_Ft_, MODE_READ); + + bpc = _recbranchAddr(VU); + + MOV16ItoM( VU_VI_ADDR(REG_TPC, 0), (int)pc ); + CMP16RtoR( fsreg, ftreg ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV16ItoM((uptr)&VU->branch, 2); + MOV32ItoM((uptr)&VU->branchpc, bpc); + + // only jump when not E bit + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +void recVUMI_B(VURegs *VU, int info) +{ + // supervu will take care of the rest + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + branch |= 3; +} + +void recVUMI_BAL( VURegs *VU, int info ) +{ + bpc = _recbranchAddr(VU); + + MOV32ItoM(VU_VI_ADDR(REG_TPC, 0), bpc); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_JR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + branch |= 3; +} + +void recVUMI_JALR(VURegs *VU, int info) +{ + // fsreg cannot be ESP + int fsreg = ALLOCVI(_Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + MOV32RtoM(VU_VI_ADDR(REG_TPC, 0), EAX); + + if ( _Ft_ ) { + int ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOV16ItoR( ftreg, (pc+8)>>3 ); + } + + branch |= 3; +} + +void recVUMI_MFP(VURegs *VU, int info) +{ + if (_Ft_ == 0) return; + + if( _XYZW_SS ) { + _vuFlipRegSS(VU, EEREC_T); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); + _vuFlipRegSS(VU, EEREC_T); + } + else if (_X_Y_Z_W != 0xf) { + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0); + VU_MERGE_REGS(EEREC_T, EEREC_TEMP); + } + else { + SSE_MOVSS_M32_to_XMM(EEREC_T, VU_VI_ADDR(REG_P, 1)); + SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0); + } +} + +static PCSX2_ALIGNED16(float s_tempmem[4]); + +void recVUMI_WAITP(VURegs *VU, int info) +{ +// if( info & PROCESS_VU_SUPER ) +// SuperVUFlush(1, 1); +} + +// in all EFU insts, EEREC_D is a temp reg +void vuSqSumXYZ(int regd, int regs, int regtemp) +{ + SSE_MOVAPS_XMM_to_XMM(regtemp, regs); + SSE_MULPS_XMM_to_XMM(regtemp, regtemp); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(regd, regtemp); + SSE_ADDPS_XMM_to_XMM(regd, regtemp); // regd.z = x+y+z + SSE_MOVHLPS_XMM_to_XMM(regd, regd); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(regd, regtemp); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + SSE_SHUFPS_XMM_to_XMM(regtemp, regtemp, 0x55); + SSE_ADDSS_XMM_to_XMM(regd, regtemp); + } +} + +void recVUMI_ESADD( VURegs *VU, int info) +{ + assert( VU == &VU1 ); + if( EEREC_TEMP != EEREC_D ) { + vuSqSumXYZ(EEREC_TEMP, EEREC_S, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); + } + else { + // special code to reset P + MOV32ItoM(VU_VI_ADDR(REG_P, 0), 0); + } +} + +void recVUMI_ERSADD( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + // almost same as vuSqSumXYZ + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_MULPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE3_HADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); // EEREC_D.z = x+y+z + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[0].UL[3]); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_D); // move to x + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + SSE_ADDSS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[0].UL[3]); + } + + // don't use RCPSS (very bad precision) + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ELENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERLENG( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + vuSqSumXYZ(EEREC_D, EEREC_S, EEREC_TEMP); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_EATANxy( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((uptr)&s_tempmem[0]); + FLD32((uptr)&s_tempmem[1]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((uptr)&VU->VF[_Fs_].UL[0]); + FLD32((uptr)&VU->VF[_Fs_].UL[1]); + } + + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATANxz( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + FLD32((uptr)&s_tempmem[0]); + FLD32((uptr)&s_tempmem[2]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((uptr)&VU->VF[_Fs_].UL[0]); + FLD32((uptr)&VU->VF[_Fs_].UL[2]); + } + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_ESUM( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( cpucaps.hasStreamingSIMD3Extensions ) { + SSE_MOVAPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + SSE3_HADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + SSE_ADDPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); // y+w, x+z + SSE_UNPCKLPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); // y+w, y+w, x+z, x+z + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_ADDSS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ERCPR( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + SSE_MOVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[0].UL[3]); + + // don't use RCPSS (very bad precision) + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(2*_Fsf_))&0xff); + SSE_DIVSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + // revert + if( _Fsf_ ) SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, (0xe4e4>>(8-2*_Fsf_))&0xff); + } + else { + SSE_DIVSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[_Fs_].UL[_Fsf_]); + } + + CheckForOverflowSS_(EEREC_TEMP, EEREC_D); + //SSE_MINSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_maxvals[0]); + //SSE_MAXSS_M32_to_XMM(EEREC_TEMP, (uptr)&g_minvals[0]); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + } + else { + SSE_SQRTSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[_Fs_].UL[_Fsf_]); + } + } + else SSE_SQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +//#ifdef _MSC_VER +// +//static u32 s_saveecx, s_saveedx, s_saveebx, s_saveesi, s_saveedi, s_saveebp; +//float tempsqrt = 0; +//extern float vuDouble(u32 f); +//__declspec(naked) void tempERSQRT() +//{ +// __asm { +// mov s_saveecx, ecx +// mov s_saveedx, edx +// mov s_saveebx, ebx +// mov s_saveesi, esi +// mov s_saveedi, edi +// mov s_saveebp, ebp +// } +// +// if (tempsqrt >= 0) { +// tempsqrt = fpusqrtf(tempsqrt); +// if (tempsqrt) { +// tempsqrt = 1.0f / tempsqrt; +// } +// tempsqrt = vuDouble(*(u32*)&tempsqrt); +// } +// +// __asm { +// mov ecx, s_saveecx +// mov edx, s_saveedx +// mov ebx, s_saveebx +// mov esi, s_saveesi +// mov edi, s_saveedi +// mov ebp, s_saveebp +// ret +// } +//} +//#endif + +void recVUMI_ERSQRT( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + +// if( _Fsf_ ) { +// if( xmmregs[EEREC_S].mode & MODE_WRITE ) { +// _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); +// SSE_MOVSS_XMM_to_M32((uptr)&tempsqrt, EEREC_TEMP); +// } +// else { +// MOV32MtoR(EAX, (uptr)&VU->VF[_Fs_].UL[_Fsf_]); +// MOV32RtoM((uptr)&tempsqrt, EAX); +// } +// } +// else { +// SSE_MOVSS_XMM_to_M32((uptr)&tempsqrt, EEREC_S); +// } +// +// +// CALLFunc((uptr)tempERSQRT); +// MOV32MtoR(EAX, (uptr)&tempsqrt); +// MOV32RtoM(VU_VI_ADDR(REG_P, 0), EAX); + + // need to explicitly check for 0 (naruto ultimate ninja) + if( _Fsf_ ) { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + _unpackVF_xyzw(EEREC_TEMP, EEREC_S, _Fsf_); + //SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + //SSE_CMPNESS_XMM_to_XMM(EEREC_D, EEREC_TEMP); + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + //SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + else { + //SSE_XORPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); + //CMP32ItoM((uptr)&VU->VF[_Fs_].UL[_Fsf_], 0); + //j8Ptr[0] = JE8(0); + SSE_RSQRTSS_M32_to_XMM(EEREC_TEMP, (uptr)&VU->VF[_Fs_].UL[_Fsf_]); + //x86SetJ8(j8Ptr[0]); + } + } + else { + SSE_RSQRTSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); + //SSE_XORPS_XMM_to_XMM(EEREC_D, EEREC_D); + //SSE_CMPNESS_XMM_to_XMM(EEREC_D, EEREC_S); + //SSE_ANDPS_XMM_to_XMM(EEREC_TEMP, EEREC_D); + } + + SSE_MOVSS_XMM_to_M32(VU_VI_ADDR(REG_P, 0), EEREC_TEMP); +} + +void recVUMI_ESIN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((uptr)&s_tempmem[2], EEREC_S); + } + FLD32((uptr)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FLD32((uptr)&VU->VF[_Fs_].UL[_Fsf_]); + } + + FSIN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EATAN( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((uptr)&s_tempmem[2], EEREC_S); + } + FLD32((uptr)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + } + + FLD1(); + FLD32((uptr)&VU->VF[_Fs_].UL[_Fsf_]); + FPATAN(); + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_EEXP( VURegs *VU, int info ) +{ + assert( VU == &VU1 ); + + FLDL2E(); + + if( (xmmregs[EEREC_S].mode & MODE_WRITE) && (xmmregs[EEREC_S].mode&MODE_NOFLUSH) ) { + switch(_Fsf_) { + case 0: SSE_MOVSS_XMM_to_M32((u32)s_tempmem, EEREC_S); + case 1: SSE_MOVLPS_XMM_to_M64((u32)s_tempmem, EEREC_S); + default: SSE_MOVHPS_XMM_to_M64((uptr)&s_tempmem[2], EEREC_S); + } + FMUL32((uptr)&s_tempmem[_Fsf_]); + } + else { + if( xmmregs[EEREC_S].mode & MODE_WRITE ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[_Fs_], EEREC_S); + xmmregs[EEREC_S].mode &= ~MODE_WRITE; + } + + FMUL32((uptr)&VU->VF[_Fs_].UL[_Fsf_]); + } + + // basically do 2^(log_2(e) * val) + FLD(0); + FRNDINT(); + FXCH(1); + FSUB32Rto0(1); + F2XM1(); + FLD1(); + FADD320toR(1); + FSCALE(); + FSTP(1); + + FSTP32(VU_VI_ADDR(REG_P, 0)); +} + +void recVUMI_XITOP( VURegs *VU, int info ) +{ + int ftreg; + if (_Ft_ == 0) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (uptr)&VU->vifRegs->itop ); +} + +void recVUMI_XTOP( VURegs *VU, int info ) +{ + int ftreg; + if ( _Ft_ == 0 ) return; + + ftreg = ALLOCVI(_Ft_, MODE_WRITE); + MOVZX32M16toR( ftreg, (uptr)&VU->vifRegs->top ); +} + +#if defined(_WIN32) && !defined(WIN32_PTHREADS) +extern HANDLE g_hGsEvent; +#else +extern pthread_cond_t g_condGsEvent; +#endif + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) +{ + u32 size; + int left; + u8* pmem; + u32* data = (u32*)((u8*)pMem + (addr&0x3fff)); + + static int scount = 0; + ++scount; + + size = GSgifTransferDummy(0, data, 0x4000>>4); + + size = 0x4000-(size<<4); + + // can't exceed 0x4000 + left = addr+size-0x4000; + if( left > 0 ) size -= left; + assert( size > 0 );//&& addr+size <= 0x4000 ); + + pmem = GSRingBufCopy(NULL, size, GS_RINGTYPE_P1); + assert( pmem != NULL ); + + memcpy_fast(pmem, (u8*)pMem+addr, size); +// if( left > 0 ) { +// memcpy_fast(pmem+size-left, (u8*)pMem, left); +// } + GSRINGBUF_DONECOPY(pmem, size); + + if( !CHECK_DUALCORE ) { +#if defined(_WIN32) && !defined(WIN32_PTHREADS) + SetEvent(g_hGsEvent); +#else + pthread_cond_signal(&g_condGsEvent); +#endif + } +} + +void recVUMI_XGKICK( VURegs *VU, int info ) +{ + int fsreg = ALLOCVI(_Fs_, MODE_READ); + _freeX86reg(fsreg); + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + + iFlushCall(FLUSH_NOCONST); + + _callPushArg(MEM_X86TAG, fsreg, X86ARG2); + _callPushArg(MEM_CONSTTAG, (uptr)VU->Mem, X86ARG1); + + if( CHECK_MULTIGS ) { + CALLFunc((uptr)VU1XGKICK_MTGSTransfer); +#ifndef __x86_64__ + ADD32ItoR(ESP, 8); +#endif + } + else { + CALLFunc((uptr)GSgifTransfer1); + } +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/iVUmicro.h b/pcsx2/x86/iVUmicro.h new file mode 100644 index 0000000..2e38d50 --- /dev/null +++ b/pcsx2/x86/iVUmicro.h @@ -0,0 +1,274 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __IVUMICRO_H__ +#define __IVUMICRO_H__ + +#define VU0_MEMSIZE 0x1000 +#define VU1_MEMSIZE 0x4000 + +#define RECOMPILE_VUMI_ABS +#define RECOMPILE_VUMI_SUB +#define RECOMPILE_VUMI_SUBA +#define RECOMPILE_VUMI_MADD +#define RECOMPILE_VUMI_MADDA +#define RECOMPILE_VUMI_MSUB +#define RECOMPILE_VUMI_MSUBA + +#define RECOMPILE_VUMI_ADD +#define RECOMPILE_VUMI_ADDA +#define RECOMPILE_VUMI_MUL +#define RECOMPILE_VUMI_MULA +#define RECOMPILE_VUMI_MAX +#define RECOMPILE_VUMI_MINI +#define RECOMPILE_VUMI_FTOI + +#define RECOMPILE_VUMI_MATH +#define RECOMPILE_VUMI_MISC +#define RECOMPILE_VUMI_E +#define RECOMPILE_VUMI_X +#define RECOMPILE_VUMI_RANDOM +#define RECOMPILE_VUMI_FLAG +#define RECOMPILE_VUMI_BRANCH +#define RECOMPILE_VUMI_ARITHMETIC +#define RECOMPILE_VUMI_LOADSTORE + +#ifdef __x86_64__ +#undef RECOMPILE_VUMI_X +#endif + +u32 GetVIAddr(VURegs * VU, int reg, int read, int info); // returns the correct VI addr +void recUpdateFlags(VURegs * VU, int reg, int info); + +void _recvuTestPipes(VURegs * VU); +void _recvuFlushFDIV(VURegs * VU); +void _recvuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn); +void _recvuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn); + +#define VUOP_READ 2 +#define VUOP_WRITE 4 + +// save on mem +typedef struct { + int cycle; + int cycles; + u8 statusflag; + u8 macflag; + u8 clipflag; + u8 dummy; + u8 q; + u8 p; + u16 pqinst; // bit of instruction specifying index (srec only) +} _vuopinfo; +extern _vuopinfo *cinfo; + +void SuperVUAnalyzeOp(VURegs *VU, _vuopinfo *info, _VURegsNum* pCodeRegs); + +// allocates all the necessary regs and returns the indices +int eeVURecompileCode(VURegs *VU, _VURegsNum* regs); + +void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr); // used for MTGS in XGKICK + +extern _VURegsNum* g_VUregs; + +#define SWAP(x, y) *(u32*)&y ^= *(u32*)&x ^= *(u32*)&y ^= *(u32*)&x; +#define VUREC_INFO eeVURecompileCode(VU, g_VUregs) + +extern int vucycle; +extern int vucycleold; + + +/***************************************** + VU Micromode Upper instructions +*****************************************/ + +void recVUMI_ABS(VURegs *vuRegs, int info); +void recVUMI_ADD(VURegs *vuRegs, int info); +void recVUMI_ADDi(VURegs *vuRegs, int info); +void recVUMI_ADDq(VURegs *vuRegs, int info); +void recVUMI_ADDx(VURegs *vuRegs, int info); +void recVUMI_ADDy(VURegs *vuRegs, int info); +void recVUMI_ADDz(VURegs *vuRegs, int info); +void recVUMI_ADDw(VURegs *vuRegs, int info); +void recVUMI_ADDA(VURegs *vuRegs, int info); +void recVUMI_ADDAi(VURegs *vuRegs, int info); +void recVUMI_ADDAq(VURegs *vuRegs, int info); +void recVUMI_ADDAx(VURegs *vuRegs, int info); +void recVUMI_ADDAy(VURegs *vuRegs, int info); +void recVUMI_ADDAz(VURegs *vuRegs, int info); +void recVUMI_ADDAw(VURegs *vuRegs, int info); +void recVUMI_SUB(VURegs *vuRegs, int info); +void recVUMI_SUBi(VURegs *vuRegs, int info); +void recVUMI_SUBq(VURegs *vuRegs, int info); +void recVUMI_SUBx(VURegs *vuRegs, int info); +void recVUMI_SUBy(VURegs *vuRegs, int info); +void recVUMI_SUBz(VURegs *vuRegs, int info); +void recVUMI_SUBw(VURegs *vuRegs, int info); +void recVUMI_SUBA(VURegs *vuRegs, int info); +void recVUMI_SUBAi(VURegs *vuRegs, int info); +void recVUMI_SUBAq(VURegs *vuRegs, int info); +void recVUMI_SUBAx(VURegs *vuRegs, int info); +void recVUMI_SUBAy(VURegs *vuRegs, int info); +void recVUMI_SUBAz(VURegs *vuRegs, int info); +void recVUMI_SUBAw(VURegs *vuRegs, int info); +void recVUMI_MUL(VURegs *vuRegs, int info); +void recVUMI_MULi(VURegs *vuRegs, int info); +void recVUMI_MULq(VURegs *vuRegs, int info); +void recVUMI_MULx(VURegs *vuRegs, int info); +void recVUMI_MULy(VURegs *vuRegs, int info); +void recVUMI_MULz(VURegs *vuRegs, int info); +void recVUMI_MULw(VURegs *vuRegs, int info); +void recVUMI_MULA(VURegs *vuRegs, int info); +void recVUMI_MULAi(VURegs *vuRegs, int info); +void recVUMI_MULAq(VURegs *vuRegs, int info); +void recVUMI_MULAx(VURegs *vuRegs, int info); +void recVUMI_MULAy(VURegs *vuRegs, int info); +void recVUMI_MULAz(VURegs *vuRegs, int info); +void recVUMI_MULAw(VURegs *vuRegs, int info); +void recVUMI_MADD(VURegs *vuRegs, int info); +void recVUMI_MADDi(VURegs *vuRegs, int info); +void recVUMI_MADDq(VURegs *vuRegs, int info); +void recVUMI_MADDx(VURegs *vuRegs, int info); +void recVUMI_MADDy(VURegs *vuRegs, int info); +void recVUMI_MADDz(VURegs *vuRegs, int info); +void recVUMI_MADDw(VURegs *vuRegs, int info); +void recVUMI_MADDA(VURegs *vuRegs, int info); +void recVUMI_MADDAi(VURegs *vuRegs, int info); +void recVUMI_MADDAq(VURegs *vuRegs, int info); +void recVUMI_MADDAx(VURegs *vuRegs, int info); +void recVUMI_MADDAy(VURegs *vuRegs, int info); +void recVUMI_MADDAz(VURegs *vuRegs, int info); +void recVUMI_MADDAw(VURegs *vuRegs, int info); +void recVUMI_MSUB(VURegs *vuRegs, int info); +void recVUMI_MSUBi(VURegs *vuRegs, int info); +void recVUMI_MSUBq(VURegs *vuRegs, int info); +void recVUMI_MSUBx(VURegs *vuRegs, int info); +void recVUMI_MSUBy(VURegs *vuRegs, int info); +void recVUMI_MSUBz(VURegs *vuRegs, int info); +void recVUMI_MSUBw(VURegs *vuRegs, int info); +void recVUMI_MSUBA(VURegs *vuRegs, int info); +void recVUMI_MSUBAi(VURegs *vuRegs, int info); +void recVUMI_MSUBAq(VURegs *vuRegs, int info); +void recVUMI_MSUBAx(VURegs *vuRegs, int info); +void recVUMI_MSUBAy(VURegs *vuRegs, int info); +void recVUMI_MSUBAz(VURegs *vuRegs, int info); +void recVUMI_MSUBAw(VURegs *vuRegs, int info); +void recVUMI_MAX(VURegs *vuRegs, int info); +void recVUMI_MAXi(VURegs *vuRegs, int info); +void recVUMI_MAXx(VURegs *vuRegs, int info); +void recVUMI_MAXy(VURegs *vuRegs, int info); +void recVUMI_MAXz(VURegs *vuRegs, int info); +void recVUMI_MAXw(VURegs *vuRegs, int info); +void recVUMI_MINI(VURegs *vuRegs, int info); +void recVUMI_MINIi(VURegs *vuRegs, int info); +void recVUMI_MINIx(VURegs *vuRegs, int info); +void recVUMI_MINIy(VURegs *vuRegs, int info); +void recVUMI_MINIz(VURegs *vuRegs, int info); +void recVUMI_MINIw(VURegs *vuRegs, int info); +void recVUMI_OPMULA(VURegs *vuRegs, int info); +void recVUMI_OPMSUB(VURegs *vuRegs, int info); +void recVUMI_NOP(VURegs *vuRegs, int info); +void recVUMI_FTOI0(VURegs *vuRegs, int info); +void recVUMI_FTOI4(VURegs *vuRegs, int info); +void recVUMI_FTOI12(VURegs *vuRegs, int info); +void recVUMI_FTOI15(VURegs *vuRegs, int info); +void recVUMI_ITOF0(VURegs *vuRegs, int info); +void recVUMI_ITOF4(VURegs *vuRegs, int info); +void recVUMI_ITOF12(VURegs *vuRegs, int info); +void recVUMI_ITOF15(VURegs *vuRegs, int info); +void recVUMI_CLIP(VURegs *vuRegs, int info); + +/***************************************** + VU Micromode Lower instructions +*****************************************/ + +void recVUMI_DIV(VURegs *vuRegs, int info); +void recVUMI_SQRT(VURegs *vuRegs, int info); +void recVUMI_RSQRT(VURegs *vuRegs, int info); +void recVUMI_IADD(VURegs *vuRegs, int info); +void recVUMI_IADDI(VURegs *vuRegs, int info); +void recVUMI_IADDIU(VURegs *vuRegs, int info); +void recVUMI_IAND(VURegs *vuRegs, int info); +void recVUMI_IOR(VURegs *vuRegs, int info); +void recVUMI_ISUB(VURegs *vuRegs, int info); +void recVUMI_ISUBIU(VURegs *vuRegs, int info); +void recVUMI_MOVE(VURegs *vuRegs, int info); +void recVUMI_MFIR(VURegs *vuRegs, int info); +void recVUMI_MTIR(VURegs *vuRegs, int info); +void recVUMI_MR32(VURegs *vuRegs, int info); +void recVUMI_LQ(VURegs *vuRegs, int info); +void recVUMI_LQD(VURegs *vuRegs, int info); +void recVUMI_LQI(VURegs *vuRegs, int info); +void recVUMI_SQ(VURegs *vuRegs, int info); +void recVUMI_SQD(VURegs *vuRegs, int info); +void recVUMI_SQI(VURegs *vuRegs, int info); +void recVUMI_ILW(VURegs *vuRegs, int info); +void recVUMI_ISW(VURegs *vuRegs, int info); +void recVUMI_ILWR(VURegs *vuRegs, int info); +void recVUMI_ISWR(VURegs *vuRegs, int info); +void recVUMI_LOI(VURegs *vuRegs, int info); +void recVUMI_RINIT(VURegs *vuRegs, int info); +void recVUMI_RGET(VURegs *vuRegs, int info); +void recVUMI_RNEXT(VURegs *vuRegs, int info); +void recVUMI_RXOR(VURegs *vuRegs, int info); +void recVUMI_WAITQ(VURegs *vuRegs, int info); +void recVUMI_FSAND(VURegs *vuRegs, int info); +void recVUMI_FSEQ(VURegs *vuRegs, int info); +void recVUMI_FSOR(VURegs *vuRegs, int info); +void recVUMI_FSSET(VURegs *vuRegs, int info); +void recVUMI_FMAND(VURegs *vuRegs, int info); +void recVUMI_FMEQ(VURegs *vuRegs, int info); +void recVUMI_FMOR(VURegs *vuRegs, int info); +void recVUMI_FCAND(VURegs *vuRegs, int info); +void recVUMI_FCEQ(VURegs *vuRegs, int info); +void recVUMI_FCOR(VURegs *vuRegs, int info); +void recVUMI_FCSET(VURegs *vuRegs, int info); +void recVUMI_FCGET(VURegs *vuRegs, int info); +void recVUMI_IBEQ(VURegs *vuRegs, int info); +void recVUMI_IBGEZ(VURegs *vuRegs, int info); +void recVUMI_IBGTZ(VURegs *vuRegs, int info); +void recVUMI_IBLTZ(VURegs *vuRegs, int info); +void recVUMI_IBLEZ(VURegs *vuRegs, int info); +void recVUMI_IBNE(VURegs *vuRegs, int info); +void recVUMI_B(VURegs *vuRegs, int info); +void recVUMI_BAL(VURegs *vuRegs, int info); +void recVUMI_JR(VURegs *vuRegs, int info); +void recVUMI_JALR(VURegs *vuRegs, int info); +void recVUMI_MFP(VURegs *vuRegs, int info); +void recVUMI_WAITP(VURegs *vuRegs, int info); +void recVUMI_ESADD(VURegs *vuRegs, int info); +void recVUMI_ERSADD(VURegs *vuRegs, int info); +void recVUMI_ELENG(VURegs *vuRegs, int info); +void recVUMI_ERLENG(VURegs *vuRegs, int info); +void recVUMI_EATANxy(VURegs *vuRegs, int info); +void recVUMI_EATANxz(VURegs *vuRegs, int info); +void recVUMI_ESUM(VURegs *vuRegs, int info); +void recVUMI_ERCPR(VURegs *vuRegs, int info); +void recVUMI_ESQRT(VURegs *vuRegs, int info); +void recVUMI_ERSQRT(VURegs *vuRegs, int info); +void recVUMI_ESIN(VURegs *vuRegs, int info); +void recVUMI_EATAN(VURegs *vuRegs, int info); +void recVUMI_EEXP(VURegs *vuRegs, int info); +void recVUMI_XGKICK(VURegs *vuRegs, int info); +void recVUMI_XTOP(VURegs *vuRegs, int info); +void recVUMI_XITOP(VURegs *vuRegs, int info); +void recVUMI_XTOP( VURegs *VU , int info); + +#endif /* __IVUMICRO_H__ */ diff --git a/pcsx2/x86/iVUops.h b/pcsx2/x86/iVUops.h new file mode 100644 index 0000000..736c4f9 --- /dev/null +++ b/pcsx2/x86/iVUops.h @@ -0,0 +1,44 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef _WIN32 +#pragma warning(disable:4244) +#endif + +#define REC_VUOP(VU, f) { \ + _freeXMMregs(&VU); \ + X86_32CODE(_freeMMXregs(); SetFPUstate();) \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUOPFLAGS(VU, f) { \ + _freeXMMregs(&VU); \ + X86_32CODE(_freeMMXregs(); SetFPUstate();) \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + CALLFunc((u32)VU##MI_##f); \ +} + +#define REC_VUBRANCH(VU, f) { \ + _freeXMMregs(&VU); \ + X86_32CODE(_freeMMXregs(); SetFPUstate();) \ + MOV32ItoM((u32)&VU.code, (u32)VU.code); \ + MOV32ItoM((u32)&VU.VI[REG_TPC].UL, (u32)pc); \ + CALLFunc((u32)VU##MI_##f); \ + branch = 1; \ +} diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp new file mode 100644 index 0000000..577bd5a --- /dev/null +++ b/pcsx2/x86/iVUzerorec.cpp @@ -0,0 +1,4182 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define PLUGINtypedefs // for GSgifTransfer1 + +#if defined(_WIN32) +#include +#else +#include +#include +#endif + +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "zlib.h" +#include "Misc.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" + +#include "Memory.h" +#include "Hw.h" +#include "GS.h" + +#include "ix86/ix86.h" +#include "iR5900.h" + +#include "iVUzerorec.h" + +// temporary externs +extern u32 vudump; +extern void iDumpVU0Registers(); +extern void iDumpVU1Registers(); + +extern char* disVU1MicroUF(u32 code, u32 pc); +extern char* disVU1MicroLF(u32 code, u32 pc); + +extern _GSgifTransfer1 GSgifTransfer1; + +#ifdef __cplusplus +} +#endif + +#include +#include +#include +#include +using namespace std; + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +// SuperVURec optimization options, uncomment only for debugging purposes +#define SUPERVU_CACHING // vu programs are saved and queried via CRC (might query the wrong program) + // disable when in doubt +#define SUPERVU_X86CACHING // use x86reg caching (faster) +#define SUPERVU_WRITEBACKS // don't flush the writebacks after every block + +#ifndef _DEBUG +#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) +#endif + +#define VU_EXESIZE 0x00800000 + +#define _Imm11_ ((s32)(vucode & 0x400 ? 0xfffffc00 | (vucode & 0x3ff) : vucode & 0x3ff)&0x3fff) +#define _UImm11_ ((s32)(vucode & 0x7ff)&0x3fff) + +#define _Ft_ ((VU->code >> 16) & 0x1F) // The rt part of the instruction register +#define _Fs_ ((VU->code >> 11) & 0x1F) // The rd part of the instruction register +#define _Fd_ ((VU->code >> 6) & 0x1F) // The sa part of the instruction register + +static const u32 QWaitTimes[] = { 6, 12 }; +static const u32 PWaitTimes[] = { 53, 43, 28, 23, 17, 11, 10 }; + +static u32 s_vuInfo; // info passed into rec insts + +static const u32 s_MemSize[2] = {VU0_MEMSIZE, VU1_MEMSIZE}; +static char* s_recVUMem = NULL, *s_recVUPtr = NULL; + +// tables +extern void (*recSVU_UPPER_OPCODE[64])(); +extern void (*recSVU_LOWER_OPCODE[128])(); + +#define INST_Q_READ 0x0001 // flush Q +#define INST_P_READ 0x0002 // flush P +#define INST_BRANCH_DELAY 0x0004 +#define INST_CLIP_WRITE 0x0040 // inst writes CLIP in the future +#define INST_STATUS_WRITE 0x0080 +#define INST_MAC_WRITE 0x0100 +#define INST_Q_WRITE 0x0200 +#define INST_DUMMY_ 0x8000 +#define INST_DUMMY 0x83c0 + +#define VFFREE_INVALID0 0x80000000 // (vffree[i]&0xf) is invalid + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +union VURecRegs +{ + struct { + u16 reg; + u16 type; + }; + u32 id; +}; + +#define SUPERVU_XGKICKDELAY 1 // yes this is needed as default (wipeout) + +class VuBaseBlock; + +struct VuFunctionHeader +{ + struct RANGE + { + RANGE() : pmem(NULL) {} + + u16 start, size; + void* pmem; // all the mem + }; + + VuFunctionHeader() : pprogfunc(NULL), startpc(0xffffffff) {} + ~VuFunctionHeader() { + for(vector::iterator it = ranges.begin(); it != ranges.end(); ++it) { + free(it->pmem); + } + } + + // returns true if the checksum for the current mem is the same as this fn + bool IsSame(void* pmem); + + u32 startpc; + void* pprogfunc; + + vector ranges; +}; + +struct VuBlockHeader +{ + VuBaseBlock* pblock; + u32 delay; +}; + +// one vu inst (lower and upper) +class VuInstruction +{ +public: + VuInstruction() { memset(this, 0, sizeof(VuInstruction)); nParentPc = -1; } + + int nParentPc; // used for syncing with flag writes, -1 for no parent + + _vuopinfo info; + + _VURegsNum regs[2]; // [0] - lower, [1] - upper + u32 livevars[2]; // live variables right before this inst, [0] - inst, [1] - float + u32 addvars[2]; // live variables to add + u32 usedvars[2]; // set if var is used in the future including vars used in this inst + u32 keepvars[2]; + u16 pqcycles; // the number of cycles to stall if function writes to the regs + u16 type; // INST_ + + u32 pClipWrite, pMACWrite, pStatusWrite; // addrs to write the flags + u32 vffree[2]; + s8 vfwrite[2], vfread0[2], vfread1[2], vfacc[2]; + s8 vfflush[2]; // extra flush regs + + int SetCachedRegs(int upper, u32 vuxyz); + void Recompile(list::iterator& itinst, u32 vuxyz); +}; + +#define BLOCKTYPE_EOP 0x01 // at least one of the children of the block contains eop (or the block itself) +#define BLOCKTYPE_FUNCTION 0x02 +#define BLOCKTYPE_HASEOP 0x04 // last inst of block is an eop +#define BLOCKTYPE_MACFLAGS 0x08 +#define BLOCKTYPE_ANALYZED 0x40 +#define BLOCKTYPE_IGNORE 0x80 // special for recursive fns +#define BLOCKTYPE_ANALYZEDPARENT 0x100 + +// base block used when recompiling +class VuBaseBlock +{ +public: + typedef list LISTBLOCKS; + + VuBaseBlock(); + + // returns true if the leads to a EOP (ALL VU blocks must ret true) + void AssignVFRegs(); + void AssignVIRegs(int parent); + + // returns true if only xyz of the reg has been used so far + u32 GetModeXYZW(u32 curpc, int vfreg); + + list::iterator GetInstIterAtPc(int instpc); + void GetInstsAtPc(int instpc, list& listinsts); + + void Recompile(); + + u16 type; // BLOCKTYPE_ + u16 id; + u16 startpc; + u16 endpc; // first inst not in block + void* pcode; // x86 code pointer + void* pendcode; // end of the x86 code pointer + int cycles; + list insts; + list parents; + LISTBLOCKS blocks; // blocks branches to + u32* pChildJumps[4]; // addrs that need to be filled with the children's start addrs + // if highest bit is set, addr needs to be relational + u32 vuxyz; // corresponding bit is set if reg's xyz channels are used only + u32 vuxy; // corresponding bit is set if reg's xyz channels are used only + + _xmmregs startregs[XMMREGS], endregs[XMMREGS]; + int nStartx86, nEndx86; // indices into s_vecRegArray + + int allocX86Regs; +}; + +struct WRITEBACK +{ + void InitInst(VuInstruction* pinst, int cycle) const + { + u32 write = viwrite[0]|viwrite[1]; + pinst->type = ((write&(1<nParentPc = nParentPc; + pinst->info.cycle = cycle; + for(int i = 0; i < 2; ++i) { + pinst->regs[i].VIwrite = viwrite[i]; + pinst->regs[i].VIread = viread[i]; + } + } + + static int SortWritebacks(const WRITEBACK& w1, const WRITEBACK& w2) { + return w1.cycle < w2.cycle; + } + + int nParentPc; + int cycle; + u32 viwrite[2]; + u32 viread[2]; +}; + +struct VUPIPELINES +{ + fmacPipe fmac[8]; + fdivPipe fdiv; + efuPipe efu; + list< WRITEBACK > listWritebacks; +}; + +VuBaseBlock::VuBaseBlock() +{ + type = 0; endpc = 0; cycles = 0; pcode = NULL; id = 0; + memset(pChildJumps, 0, sizeof(pChildJumps)); + memset(startregs, 0, sizeof(startregs)); + memset(endregs, 0, sizeof(endregs)); + allocX86Regs = nStartx86 = nEndx86 = -1; +} + +#define SUPERVU_STACKSIZE 0x1000 + +static list s_listVUHeaders[2]; +static list* s_plistCachedHeaders[2]; +static VuFunctionHeader** recVUHeaders[2] = {NULL}; +static VuBlockHeader* recVUBlocks[2] = {NULL}; +static u8* recVUStack = NULL, *recVUStackPtr = NULL; +static vector<_x86regs> s_vecRegArray(128); + +static VURegs* VU = NULL; +static list s_listBlocks; +static u32 s_vu = 0; +static u32 s_UnconditionalDelay = 0; // 1 if there are two sequential branches and the last is unconditional + +// Global functions +extern "C" void* SuperVUGetProgram(u32 startpc, int vuindex); +extern "C" void SuperVUCleanupProgram(u32 startpc, int vuindex); +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex); +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc, const VUPIPELINES& pipes); +static void SuperVUInitLiveness(VuBaseBlock* pblock); +static void SuperVULivenessAnalysis(); +static void SuperVUEliminateDeadCode(); +static void SuperVUAssignRegs(); + +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg); +#define SuperVUFreeXMMreg 0&& +void SuperVUFreeXMMregs(u32* livevars); + +static u32* SuperVUStaticAlloc(u32 size); +static void SuperVURecompile(); +extern "C" void SuperVUEndProgram(); + +// allocate VU resources +void SuperVUInit(int vuindex) +{ + if( vuindex < 0 ) { + // upper 4 bits cannot be nonzero! + s_recVUMem = (char*)SysMmap(0x0c000000, VU_EXESIZE); + if( (uptr)s_recVUMem > 0x80000000 ) + SysPrintf("bad SuperVU alloc %x\n", s_recVUMem); + memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + recVUStack = new u8[SUPERVU_STACKSIZE * 4]; + } + else { + recVUHeaders[vuindex] = new VuFunctionHeader* [s_MemSize[vuindex]/8]; + recVUBlocks[vuindex] = new VuBlockHeader[s_MemSize[vuindex]/8]; + s_plistCachedHeaders[vuindex] = new list[s_MemSize[vuindex]/8]; + } +} + +// destroy VU resources +void SuperVUDestroy(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUDestroy(0); + SuperVUDestroy(1); + SysMunmap((uptr)s_recVUMem, VU_EXESIZE); + s_recVUPtr = NULL; + delete[] recVUStack; recVUStack = NULL; + } + else { + delete[] recVUHeaders[vuindex]; recVUHeaders[vuindex] = NULL; + delete[] recVUBlocks[vuindex]; recVUBlocks[vuindex] = NULL; + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + delete[] s_plistCachedHeaders[vuindex]; s_plistCachedHeaders[vuindex] = NULL; + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// reset VU +void SuperVUReset(int vuindex) +{ + list::iterator it; + + if( vuindex < 0 ) { + SuperVUReset(0); + SuperVUReset(1); + + //memset(s_recVUMem, 0xcd, VU_EXESIZE); + s_recVUPtr = s_recVUMem; + + memset(recVUStack, 0, SUPERVU_STACKSIZE); + } + else { + if( recVUHeaders[vuindex] ) memset( recVUHeaders[vuindex], 0, sizeof(VuFunctionHeader*) * (s_MemSize[vuindex]/8) ); + if( recVUBlocks[vuindex] ) memset( recVUBlocks[vuindex], 0, sizeof(VuBlockHeader) * (s_MemSize[vuindex]/8) ); + + if( s_plistCachedHeaders[vuindex] != NULL ) { + for(u32 j = 0; j < s_MemSize[vuindex]/8; ++j) { + FORIT(it, s_plistCachedHeaders[vuindex][j]) delete *it; + s_plistCachedHeaders[vuindex][j].clear(); + } + } + + FORIT(it, s_listVUHeaders[vuindex]) delete *it; + s_listVUHeaders[vuindex].clear(); + } +} + +// clear the block and any joining blocks +void SuperVUClear(u32 startpc, u32 size, int vuindex) +{ + vector::iterator itrange; + list::iterator it = s_listVUHeaders[vuindex].begin(); + u32 endpc = startpc+size; + while( it != s_listVUHeaders[vuindex].end() ) { + + // for every fn, check if it has code in the range + FORIT(itrange, (*it)->ranges) { + if( startpc < (u32)itrange->start+itrange->size && itrange->start < endpc ) + break; + } + + if( itrange != (*it)->ranges.end() ) { + recVUHeaders[vuindex][(*it)->startpc/8] = NULL; +#ifdef SUPERVU_CACHING + list* plist = &s_plistCachedHeaders[vuindex][(*it)->startpc/8]; + plist->push_back(*it); + if( plist->size() > 10 ) { + // list is too big, delete + delete plist->front(); + plist->pop_front(); + } + it = s_listVUHeaders[vuindex].erase(it); +#else + delete *it; + it = s_listVUHeaders[vuindex].erase(it); +#endif + } + else ++it; + } +} + +static VuFunctionHeader* s_pFnHeader = NULL; +static VuBaseBlock* s_pCurBlock = NULL; +static VuInstruction* s_pCurInst = NULL; +static u32 s_StatusRead = 0, s_MACRead = 0, s_ClipRead = 0; // read addrs +static u32 s_PrevStatusWrite = 0, s_PrevMACWrite = 0, s_PrevClipWrite = 0, s_PrevIWrite = 0; +static u32 s_WriteToReadQ = 0; + +extern "C" { +u32 s_TotalVUCycles; // total cycles since start of program execution +} + +int SuperVUGetLiveness(int vfreg) +{ + assert( s_pCurInst != NULL ); + if( vfreg == 32 ) return ((s_pCurInst->livevars[0]&(1<usedvars[0]&(1<livevars[0]&(1<usedvars[0]&(1<livevars[1]&(1<usedvars[1]&(1<pStatusWrite); + assert(!read || addr != 0); + return addr; + } + case REG_MAC_FLAG: + { + return (read==2) ? s_PrevMACWrite : (read ? s_MACRead : s_pCurInst->pMACWrite); + } + case REG_CLIP_FLAG: + { + u32 addr = (read==2) ? s_PrevClipWrite : (read ? s_ClipRead : s_pCurInst->pClipWrite); + assert( !read || addr != 0 ); + return addr; + } + case REG_Q: return (read || s_WriteToReadQ) ? (uptr)&VU->VI[REG_Q] : (uptr)&VU->q; + case REG_P: return read ? (uptr)&VU->VI[REG_P] : (uptr)&VU->p; + case REG_I: return s_PrevIWrite; + } + + return (uptr)&VU->VI[reg]; +} + +void SuperVUDumpBlock(list& blocks, int vuindex) +{ + FILE *f; + char filename[ 256 ], str[256]; + u32 *mem; + u32 i; + static int gid = 0; + +#ifdef _WIN32 + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/svu%c_%.4X.txt", s_vu?'1':'0', s_pFnHeader->startpc ); +#endif + //SysPrintf( "dump1 %x => %s\n", s_pFnHeader->startpc, filename ); + + f = fopen( filename, "w" ); + + fprintf(f, "Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); + fprintf(f, "Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" + "%.2x - mac_write, %.2x -qflush\n", + INST_Q_READ, INST_P_READ, INST_CLIP_WRITE, INST_STATUS_WRITE, INST_MAC_WRITE, INST_Q_WRITE); + fprintf(f, "XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); + + list::iterator itblock; + list::iterator itinst; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + FORIT(itblock, blocks) { + fprintf(f, "block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', + (*itblock)->startpc, (*itblock)->endpc-8); + FORIT(itchild, (*itblock)->blocks) { + fprintf(f, "%x ", (*itchild)->startpc); + } + fprintf(f, "; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], + (*itblock)->vuxy&(*itblock)->insts.front().usedvars[1]); + + itinst = (*itblock)->insts.begin(); + i = (*itblock)->startpc; + while(itinst != (*itblock)->insts.end() ) { + assert( i <= (*itblock)->endpc ); + if( itinst->type & INST_DUMMY ) { + if( itinst->nParentPc >= 0 && !(itinst->type&INST_DUMMY_)) { + // search for the parent + fprintf(f, "writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); + } + } + else { + mem = (u32*)&VU->Micro[i]; + char* pstr = disVU1MicroUF( mem[1], i+4 ); + fprintf(f, "%.4x: %-40s", i, pstr); + if( mem[1] & 0x80000000 ) fprintf(f, " I=%f(%.8x)\n", *(float*)mem, mem[0]); + else fprintf(f, "%s\n", disVU1MicroLF( mem[0], i )); + i += 8; + } + + ++itinst; + } + + fprintf(f, "\n"); + + _x86regs* pregs; + if( (*itblock)->nStartx86 >= 0 || (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "X86: AX CX DX BX SP BP SI DI\n"); + } + + if( (*itblock)->nStartx86 >= 0 ) { + pregs = &s_vecRegArray[(*itblock)->nStartx86]; + fprintf(f, "STR: "); + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + if( (*itblock)->nEndx86 >= 0 ) { + fprintf(f, "END: "); + pregs = &s_vecRegArray[(*itblock)->nEndx86]; + for(i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); + else fprintf(f, "-1 "); + } + fprintf(f, "\n"); + } + + itinst = (*itblock)->insts.begin(); + for ( i = (*itblock)->startpc; i < (*itblock)->endpc; ++itinst ) { + + if( itinst->type & INST_DUMMY ) { + } + else { + sprintf(str, "%.4x:%x f:%.8x_%.8x", i, itinst->type, itinst->livevars[1], itinst->usedvars[1]); + fprintf(f, "%-46s i:%.8x_%.8x c:%d pq:%d\n", str, + itinst->livevars[0], itinst->usedvars[0], (int)itinst->info.cycle, (int)itinst->pqcycles ); + + sprintf(str, "XMM r0:%d r1:%d w:%d a:%d t:%x;", + itinst->vfread0[1], itinst->vfread1[1], itinst->vfwrite[1], itinst->vfacc[1], itinst->vffree[1]); + fprintf(f, "%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, + itinst->vfread0[0], itinst->vfread1[0], itinst->vfwrite[0], itinst->vfacc[0], itinst->vffree[0]); + i += 8; + } + } + +#ifdef __LINUX__ + // dump the asm + if( (*itblock)->pcode != NULL ) { + char command[255]; + FILE* fasm = fopen( "mydump1", "wb" ); + //SysPrintf("writing: %x, %x\n", (*itblock)->startpc, (uptr)(*itblock)->pendcode - (uptr)(*itblock)->pcode); + fwrite( (*itblock)->pcode, 1, (uptr)(*itblock)->pendcode - (uptr)(*itblock)->pcode, fasm ); + fclose( fasm ); +#ifdef __x86_64__ + sprintf( command, "objdump -D --target=binary --architecture=i386:x86-64 -M intel mydump1 > tempdump"); +#else + sprintf( command, "objdump -D --target=binary --architecture=i386 -M intel mydump1 > tempdump"); +#endif + system( command ); + fasm = fopen("tempdump", "r"); + // read all of it and write it to f + fseek(fasm, 0, SEEK_END); + vector vbuffer(ftell(fasm)); + fseek(fasm, 0, SEEK_SET); + fread(&vbuffer[0], vbuffer.size(), 1, fasm); + + fprintf(f, "\n\n"); + fwrite(&vbuffer[0], vbuffer.size(), 1, f); + fclose(fasm); + } +#endif + + fprintf(f, "\n---------------\n"); + } + + fclose( f ); +} + +static LARGE_INTEGER svubase, svufinal; +static u32 svutime; + +// uncomment to count svu exec time +//#define SUPERVU_COUNT +u32 SuperVUGetRecTimes(int clear) +{ + u32 temp = svutime; + if( clear ) svutime = 0; + return temp; +} + +// Private methods +void* SuperVUGetProgram(u32 startpc, int vuindex) +{ + assert( startpc < s_MemSize[vuindex] ); + assert( (startpc%8) == 0 ); + assert( recVUHeaders[vuindex] != NULL ); + VuFunctionHeader** pheader = &recVUHeaders[vuindex][startpc/8]; + + if( *pheader == NULL ) { +#ifdef _DEBUG +// if( vuindex ) VU1.VI[REG_TPC].UL = startpc; +// else VU0.VI[REG_TPC].UL = startpc; +// __Log("VU: %x\n", startpc); +// iDumpVU1Registers(); +// vudump |= 2; +#endif + + // measure run time + //QueryPerformanceCounter(&svubase); + +#ifdef SUPERVU_CACHING + void* pmem = (vuindex&1) ? VU1.Micro : VU0.Micro; + // check if program exists in cache + list::iterator it; + FORIT(it, s_plistCachedHeaders[vuindex][startpc/8]) { + if( (*it)->IsSame(pmem) ) { + // found, transfer to regular lists + void* pfn = (*it)->pprogfunc; + recVUHeaders[vuindex][startpc/8] = *it; + s_listVUHeaders[vuindex].push_back(*it); + s_plistCachedHeaders[vuindex][startpc/8].erase(it); + return pfn; + } + } +#endif + + *pheader = SuperVURecompileProgram(startpc, vuindex); + + if( *pheader == NULL ) { + assert( s_TotalVUCycles > 0 ); + if( vuindex ) VU1.VI[REG_TPC].UL = startpc; + else VU0.VI[REG_TPC].UL = startpc; + return (void*)SuperVUEndProgram; + } + + //QueryPerformanceCounter(&svufinal); + //svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); + + assert( (*pheader)->pprogfunc != NULL ); + } + + assert( (*pheader)->startpc == startpc ); + + return (*pheader)->pprogfunc; +} + +bool VuFunctionHeader::IsSame(void* pmem) +{ +#ifdef SUPERVU_CACHING + //u32 checksum[2]; + vector::iterator it; + FORIT(it, ranges) { + //memxor_mmx(checksum, (u8*)pmem+it->start, it->size); + //if( checksum[0] != it->checksum[0] || checksum[1] != it->checksum[1] ) + // return false; + if( memcmp_mmx((u8*)pmem+it->start, it->pmem, it->size) ) + return false; + } +#endif + return true; +} + +list::iterator VuBaseBlock::GetInstIterAtPc(int instpc) +{ + assert( instpc >= 0 ); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + if( it != insts.end() ) + return it; + + assert( 0 ); + return insts.begin(); +} + +void VuBaseBlock::GetInstsAtPc(int instpc, list& listinsts) +{ + assert( instpc >= 0 ); + + listinsts.clear(); + + u32 curpc = startpc; + list::iterator it; + for(it = insts.begin(); it != insts.end(); ++it) { + if( it->type & INST_DUMMY ) + continue; + + if( curpc == instpc ) + break; + curpc += 8; + } + + if( it != insts.end() ) { + listinsts.push_back(&(*it)); + return; + } + + // look for the pc in other blocks + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + if( *itblock == this ) + continue; + + if( instpc >= (*itblock)->startpc && instpc < (*itblock)->endpc ) { + listinsts.push_back(&(*(*itblock)->GetInstIterAtPc(instpc))); + } + } + + assert(listinsts.size()>0); +} + +static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex) +{ + assert( vuindex < 2 ); + assert( s_recVUPtr != NULL ); + //SysPrintf("svu%c rec: %x\n", '0'+vuindex, startpc); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)s_recVUPtr - (uptr)s_recVUMem ) >= VU_EXESIZE-0x40000 ) { + //SysPrintf("SuperVU reset mem\n"); + SuperVUReset(-1); + if( s_TotalVUCycles > 0 ) { + // already executing, so return NULL + return NULL; + } + } + + list::iterator itblock; + + s_vu = vuindex; + VU = s_vu ? &VU1 : &VU0; + s_pFnHeader = new VuFunctionHeader(); + s_listVUHeaders[vuindex].push_back(s_pFnHeader); + s_pFnHeader->startpc = startpc; + + memset( recVUBlocks[s_vu], 0, sizeof(VuBlockHeader) * (s_MemSize[s_vu]/8) ); + + // analyze the global graph + s_listBlocks.clear(); + VUPIPELINES pipes; + memset(pipes.fmac, 0, sizeof(pipes.fmac)); + memset(&pipes.fdiv, 0, sizeof(pipes.fdiv)); + memset(&pipes.efu, 0, sizeof(pipes.efu)); + SuperVUBuildBlocks(NULL, startpc, pipes); + + // fill parents + VuBaseBlock::LISTBLOCKS::iterator itchild; + FORIT(itblock, s_listBlocks) { + FORIT(itchild, (*itblock)->blocks) + (*itchild)->parents.push_back(*itblock); + + //(*itblock)->type &= ~(BLOCKTYPE_IGNORE|BLOCKTYPE_ANALYZED); + } + + assert( s_listBlocks.front()->startpc == startpc ); + s_listBlocks.front()->type |= BLOCKTYPE_FUNCTION; + + FORIT(itblock, s_listBlocks) { + SuperVUInitLiveness(*itblock); + } + + SuperVULivenessAnalysis(); + SuperVUEliminateDeadCode(); + SuperVUAssignRegs(); + +#ifdef _DEBUG + if( (s_vu && (vudump&1)) || (!s_vu && (vudump&16)) ) + SuperVUDumpBlock(s_listBlocks, s_vu); +#endif + + // code generation + x86SetPtr(s_recVUPtr); + _initXMMregs(); + branch = 0; + + SuperVURecompile(); + + s_recVUPtr = x86Ptr; + + // set the function's range + VuFunctionHeader::RANGE r; + s_pFnHeader->ranges.reserve(s_listBlocks.size()); + + FORIT(itblock, s_listBlocks) { + r.start = (*itblock)->startpc; + r.size = (*itblock)->endpc-(*itblock)->startpc; +#ifdef SUPERVU_CACHING + //memxor_mmx(r.checksum, &VU->Micro[r.start], r.size); + r.pmem = malloc(r.size); + memcpy_fast(r.pmem, &VU->Micro[r.start], r.size); +#endif + s_pFnHeader->ranges.push_back(r); + } + +#if defined(_DEBUG) && defined(__LINUX__) + // dump at the end to capture the actual code + if( (s_vu && (vudump&1)) || (!s_vu && (vudump&16)) ) + SuperVUDumpBlock(s_listBlocks, s_vu); +#endif + + // destroy + for(list::iterator itblock = s_listBlocks.begin(); itblock != s_listBlocks.end(); ++itblock) { + delete *itblock; + } + s_listBlocks.clear(); + + assert( s_recVUPtr < s_recVUMem+VU_EXESIZE ); + + return s_pFnHeader; +} + +static int _recbranchAddr(u32 vucode) { + u32 bpc = pc + (_Imm11_ << 3); + if (bpc < 0) { + bpc = pc + (_UImm11_ << 3); + } + bpc &= (s_MemSize[s_vu]-1); + + return bpc; +} + +// return inst that flushes everything +static VuInstruction SuperVUFlushInst() +{ + VuInstruction inst; + // don't need to raed q/p + inst.type = INST_DUMMY_;//|INST_Q_READ|INST_P_READ; + return inst; +} + +void SuperVUAddWritebacks(VuBaseBlock* pblock, const list& listWritebacks) +{ +#ifdef SUPERVU_WRITEBACKS + // regardless of repetition, add the pipes (for selfloops) + list::const_iterator itwriteback = listWritebacks.begin(); + list::iterator itinst = pblock->insts.begin(), itinst2; + + while(itwriteback != listWritebacks.end()) { + if( itinst != pblock->insts.end() && itinst->info.cycle < itwriteback->cycle ) { + ++itinst; + continue; + } + + itinst2 = pblock->insts.insert(itinst, VuInstruction()); + itwriteback->InitInst(&(*itinst2), vucycle); + ++itwriteback; + } +#endif +} + +static VuBaseBlock* SuperVUBuildBlocks(VuBaseBlock* parent, u32 startpc, const VUPIPELINES& pipes) +{ + // check if block already exists + VuBlockHeader* pbh = &recVUBlocks[s_vu][startpc/8]; + if( pbh->pblock != NULL ) { + + VuBaseBlock* pblock = pbh->pblock; + list::iterator itinst; + + if( pblock->startpc == startpc ) { + SuperVUAddWritebacks(pblock, pipes.listWritebacks); + return pblock; + } + + // have to divide the blocks, pnewblock is first block + assert( startpc > pblock->startpc ); + assert( startpc < pblock->endpc ); + + u32 dummyinst = (startpc-pblock->startpc)>>3; + + // count inst non-dummy insts + itinst = pblock->insts.begin(); + u32 inst = 0; + int cycleoff = 0; + + while(dummyinst > 0) { + if( itinst->type & INST_DUMMY ) + ++itinst; + else { + cycleoff = itinst->info.cycle; + ++itinst; + --dummyinst; + } + } + + // NOTE: still leaves insts with their writebacks in different blocks + while( itinst->type & INST_DUMMY ) + ++itinst; + + // the difference in cycles between dummy insts (naruto utlimate ninja) + int cyclediff = 0; + if( parent == pblock ) + cyclediff = itinst->info.cycle-cycleoff; + cycleoff = itinst->info.cycle; + + // new block + VuBaseBlock* pnewblock = new VuBaseBlock(); + s_listBlocks.push_back(pnewblock); + + pnewblock->startpc = startpc; + pnewblock->endpc = pblock->endpc; + pnewblock->cycles = pblock->cycles-cycleoff+cyclediff; + + pnewblock->blocks.splice(pnewblock->blocks.end(), pblock->blocks); + pnewblock->insts.splice(pnewblock->insts.end(), pblock->insts, itinst, pblock->insts.end()); + pnewblock->type = pblock->type; + + // any writebacks in the next 3 cycles also belong to original block + for(itinst = pnewblock->insts.begin(); itinst != pnewblock->insts.end(); ) { + if( (itinst->type & INST_DUMMY) && itinst->nParentPc >= 0 && itinst->nParentPc < (int)startpc ) { + + if( !(itinst->type & INST_Q_WRITE) ) + pblock->insts.push_back(*itinst); + itinst = pnewblock->insts.erase(itinst); + continue; + } + + ++itinst; + } + + pbh = &recVUBlocks[s_vu][startpc/8]; + for(u32 inst = startpc; inst < pblock->endpc; inst += 8) { + if( pbh->pblock == pblock ) + pbh->pblock = pnewblock; + ++pbh; + } + + FORIT(itinst, pnewblock->insts) + itinst->info.cycle -= cycleoff; + + SuperVUAddWritebacks(pnewblock, pipes.listWritebacks); + + // old block + pblock->blocks.push_back(pnewblock); + pblock->endpc = startpc; + pblock->cycles = cycleoff; + pblock->type &= BLOCKTYPE_MACFLAGS; + //pblock->insts.push_back(SuperVUFlushInst()); //don't need + + return pnewblock; + } + + VuBaseBlock* pblock = new VuBaseBlock(); + s_listBlocks.push_back(pblock); + + int i = 0; + branch = 0; + pc = startpc; + pblock->startpc = startpc; + + // clear stalls (might be a prob) + memcpy(VU->fmac, pipes.fmac, sizeof(pipes.fmac)); + memcpy(&VU->fdiv, &pipes.fdiv, sizeof(pipes.fdiv)); + memcpy(&VU->efu, &pipes.efu, sizeof(pipes.efu)); +// memset(VU->fmac, 0, sizeof(VU->fmac)); +// memset(&VU->fdiv, 0, sizeof(VU->fdiv)); +// memset(&VU->efu, 0, sizeof(VU->efu)); + + vucycle = 0; + + u8 macflags = 0; + + list< WRITEBACK > listWritebacks; + list< WRITEBACK >::iterator itwriteback; + list::iterator itinst; + u32 hasSecondBranch = 0; + u32 needFullStatusFlag = 0; + +#ifdef SUPERVU_WRITEBACKS + listWritebacks = pipes.listWritebacks; +#endif + + // first analysis pass for status flags + while(1) { + u32* ptr = (u32*)&VU->Micro[pc]; + pc += 8; + int prevbranch = branch; + + if( ptr[1] & 0x40000000 ) + branch = 1; + + if( !(ptr[1] & 0x80000000) ) { // not I + switch( ptr[0]>>25 ) { + case 0x24: // jr + case 0x25: // jalr + case 0x20: // B + case 0x21: // BAL + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + branch = 1; + break; + + case 0x14: // fseq + case 0x17: // fsor + //needFullStatusFlag = 2; + break; + + case 0x16: // fsand + if( (ptr[0]&0xc0) ) { + // sometimes full sticky bits are needed (simple series 2000 - oane chapara) + //SysPrintf("needSticky: %x-%x\n", s_pFnHeader->startpc, startpc); + needFullStatusFlag = 2; + } + break; + } + } + + if( prevbranch ) + break; + + if( pc >= s_MemSize[s_vu] ) { + SysPrintf("inf vu0 prog %x\n", startpc); + break; + } + } + + // second full pass + pc = startpc; + branch = 0; + + while(1) { + + if( pc == s_MemSize[s_vu] ) { + branch |= 8; + break; + } + + if( !branch && pbh->pblock != NULL ) { + pblock->blocks.push_back(pbh->pblock); + break; + } + + int prevbranch = branch; + + if( !prevbranch ) { + pbh->pblock = pblock; + } + else assert( prevbranch || pbh->pblock == NULL); + + pblock->insts.push_back(VuInstruction()); + + VuInstruction* pinst = &pblock->insts.back(); + SuperVUAnalyzeOp(VU, &pinst->info, pinst->regs); + + if( prevbranch ) { + if( pinst->regs[0].pipe == VUPIPE_BRANCH ) + hasSecondBranch = 1; + pinst->type |= INST_BRANCH_DELAY; + } + + // check write back + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ) { + if( pinst->info.cycle >= itwriteback->cycle ) { + itinst = pblock->insts.insert(--pblock->insts.end(), VuInstruction()); + itwriteback->InitInst(&(*itinst), pinst->info.cycle); + itwriteback = listWritebacks.erase(itwriteback); + } + else ++itwriteback; + } + + // add new writebacks + WRITEBACK w = {0}; + const u32 allflags = (1<regs[j].VIwrite & allflags; + + if( pinst->info.macflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.statusflag & VUOP_WRITE ) w.viwrite[1] |= (1<info.macflag|pinst->info.statusflag) & VUOP_READ ) + macflags = 1; + if( pinst->regs[0].VIread & ((1<VIwrite |= lregs->VIwrite & (1<info.statusflag&VUOP_WRITE)&&!(pinst->regs[0].VIwrite&(1<regs[j].VIread & allflags; + + if( (pinst->regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIread&(1<regs[j].VIwrite&(1<regs[j].VIread &= ~(1<regs[j].VIwrite &= ~allflags; + } + + if( pinst->info.macflag & VUOP_READ) w.viread[1] |= 1<info.statusflag & VUOP_READ) w.viread[1] |= 1<info.cycle+4; + listWritebacks.push_back(w); + } + + if( pinst->info.q&VUOP_READ ) pinst->type |= INST_Q_READ; + if( pinst->info.p&VUOP_READ ) pinst->type |= INST_P_READ; + + if( pinst->info.q&VUOP_WRITE ) { + pinst->pqcycles = QWaitTimes[pinst->info.pqinst]+1; + + memset(&w, 0, sizeof(w)); + w.nParentPc = pc-8; + w.cycle = pinst->info.cycle+pinst->pqcycles; + w.viwrite[0] = 1<info.p&VUOP_WRITE ) + pinst->pqcycles = PWaitTimes[pinst->info.pqinst]+1; + + if( prevbranch ) { + break; + } + + // make sure there is always a branch + // sensible soccer overflows on vu0, so increase the limit... + if( (s_vu==1 && i >= 0x799) || (s_vu==0 && i >= 0x201) ) { + SysPrintf("VuRec base block doesn't terminate!\n"); + assert(0); + break; + } + + i++; + pbh++; + } + + if( macflags ) + pblock->type |= BLOCKTYPE_MACFLAGS; + + pblock->endpc = pc; + u32 lastpc = pc; + + pblock->cycles = vucycle; + +#ifdef SUPERVU_WRITEBACKS + if( !branch || (branch&8) ) +#endif + { + // flush writebacks + if( listWritebacks.size() > 0 ) { + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + + listWritebacks.clear(); + } + } + + if( !branch ) + return pblock; + + if( branch & 8 ) { + // what if also a jump? + pblock->type |= BLOCKTYPE_EOP|BLOCKTYPE_HASEOP; + + // add an instruction to flush p and q (if written) + pblock->insts.push_back(SuperVUFlushInst()); + return pblock; + } + + // it is a (cond) branch or a jump + u32 vucode = *(u32*)(VU->Micro+lastpc-16); + int bpc = _recbranchAddr(vucode)-8; + + VUPIPELINES newpipes; + memcpy(newpipes.fmac, VU->fmac, sizeof(newpipes.fmac)); + memcpy(&newpipes.fdiv, &VU->fdiv, sizeof(newpipes.fdiv)); + memcpy(&newpipes.efu, &VU->efu, sizeof(newpipes.efu)); + + for(i = 0; i < 8; ++i) newpipes.fmac[i].sCycle -= vucycle; + newpipes.fdiv.sCycle -= vucycle; + newpipes.efu.sCycle -= vucycle; + + if( listWritebacks.size() > 0 ) { + bool bFlushWritebacks = (vucode>>25)==0x24||(vucode>>25)==0x25||(vucode>>25)==0x20||(vucode>>25)==0x21; + + listWritebacks.sort(WRITEBACK::SortWritebacks); + for(itwriteback = listWritebacks.begin(); itwriteback != listWritebacks.end(); ++itwriteback) { + if( itwriteback->viwrite[0] & (1<cycle <= vucycle || bFlushWritebacks ) { + pblock->insts.push_back(VuInstruction()); + itwriteback->InitInst(&pblock->insts.back(), vucycle); + } + else { + newpipes.listWritebacks.push_back(*itwriteback); + newpipes.listWritebacks.back().cycle -= vucycle; + } + } + } + + u32 firstbranch = vucode>>25; + switch(firstbranch) { + case 0x24: // jr + pblock->type |= BLOCKTYPE_EOP; // jump out of procedure, since not returning, set EOP + pblock->insts.push_back(SuperVUFlushInst()); + break; + + case 0x25: // jalr + { + // linking, so will return to procedure + pblock->insts.push_back(SuperVUFlushInst()); + + VuBaseBlock* pjumpblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + + pblock->blocks.push_back(pjumpblock); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + assert( pblock != NULL ); + pblock->blocks.push_back(pbranchblock); + + // if has a second branch that is B or BAL, skip this + u32 secondbranch = (*(u32*)(VU->Micro+lastpc-8))>>25; + if( !hasSecondBranch || (secondbranch != 0x21 && secondbranch != 0x20) ) { + pbranchblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + } + + break; + } + default: + assert(pblock->blocks.size() == 1); + break; + } + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + if( hasSecondBranch ) { + u32 vucode = *(u32*)(VU->Micro+lastpc-8); + pc = lastpc; + int bpc = _recbranchAddr(vucode); + + switch(vucode>>25) { + case 0x24: // jr + SysPrintf("svurec bad jr jump!\n"); + assert(0); + break; + + case 0x25: // jalr + { + SysPrintf("svurec bad jalr jump!\n"); + assert(0); + break; + } + case 0x20: // B + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x21: // BAL + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // replace instead of pushing a new block + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + break; + } + case 0x28: // IBEQ + case 0x2f: // IBGEZ + case 0x2d: // IBGTZ + case 0x2e: // IBLEZ + case 0x2c: // IBLTZ + case 0x29: // IBNE + { + VuBaseBlock* pbranchblock = SuperVUBuildBlocks(pblock, bpc, newpipes); + + // update pblock since could have changed + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + + // only add the block if the previous branch doesn't include the next instruction (ie, if a direct jump) + if( firstbranch == 0x24 || firstbranch == 0x25 || firstbranch == 0x20 || firstbranch == 0x21 ) { + pbranchblock = SuperVUBuildBlocks(pblock, lastpc, newpipes); + + pblock = recVUBlocks[s_vu][lastpc/8-2].pblock; + pblock->blocks.push_back(pbranchblock); + } + + break; + } + default: + assert(0); + } + } + + return recVUBlocks[s_vu][startpc/8].pblock; +} + +static void SuperVUInitLiveness(VuBaseBlock* pblock) +{ + list::iterator itinst, itnext; + + assert( pblock->insts.size() > 0 ); + + for(itinst = pblock->insts.begin(); itinst != pblock->insts.end(); ++itinst) { + + if( itinst->type & INST_DUMMY_ ) { + itinst->addvars[0] = itinst->addvars[1] = 0xffffffff; + itinst->livevars[0] = itinst->livevars[1] = 0xffffffff; + itinst->keepvars[0] = itinst->keepvars[1] = 0xffffffff; + itinst->usedvars[0] = itinst->usedvars[1] = 0; + } + else { + itinst->addvars[0] = itinst->regs[0].VIread | itinst->regs[1].VIread; + itinst->addvars[1] = (itinst->regs[0].VFread0 ? (1 << itinst->regs[0].VFread0) : 0) | + (itinst->regs[0].VFread1 ? (1 << itinst->regs[0].VFread1) : 0) | + (itinst->regs[1].VFread0 ? (1 << itinst->regs[1].VFread0) : 0) | + (itinst->regs[1].VFread1 ? (1 << itinst->regs[1].VFread1) : 0); + + // vf0 is not handled by VFread + if( !itinst->regs[0].VFread0 && (itinst->regs[0].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[1].VFread0 && (itinst->regs[1].VIread & (1<addvars[1] |= 1; + if( !itinst->regs[0].VFread1 && (itinst->regs[0].VIread & (1<regs[0].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + if( !itinst->regs[1].VFread1 && (itinst->regs[1].VIread & (1<regs[1].VFr1xyzw != 0xff ) itinst->addvars[1] |= 1; + + + u32 vfwrite = 0; + if( itinst->regs[0].VFwrite != 0 ) { + if( itinst->regs[0].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[0].VFwrite; + else vfwrite |= 1<regs[0].VFwrite; + } + if( itinst->regs[1].VFwrite != 0 ) { + if( itinst->regs[1].VFwxyzw != 0xf ) itinst->addvars[1] |= 1<regs[1].VFwrite; + else vfwrite |= 1<regs[1].VFwrite; + } + if( (itinst->regs[1].VIwrite & (1<regs[1].VFwxyzw != 0xf ) + itinst->addvars[1] |= 1<regs[0].VIwrite|itinst->regs[1].VIwrite); + + itinst->usedvars[0] = itinst->addvars[0]|viwrite; + itinst->usedvars[1] = itinst->addvars[1]|vfwrite; + +// itinst->addvars[0] &= ~viwrite; +// itinst->addvars[1] &= ~vfwrite; + itinst->keepvars[0] = ~viwrite; + itinst->keepvars[1] = ~vfwrite; + } + } + + itinst = --pblock->insts.end(); + while( itinst != pblock->insts.begin() ) { + itnext = itinst; --itnext; + + itnext->usedvars[0] |= itinst->usedvars[0]; + itnext->usedvars[1] |= itinst->usedvars[1]; + + itinst = itnext; + } +} + +u32 COMPUTE_LIVE(u32 R, u32 K, u32 L) +{ + u32 live = R | ((L)&(K)); + // speciall process mac and status flags + // only propagate liveness if doesn't write to the flag + if( !(L&(1<::reverse_iterator itblock; + list::iterator itinst, itnext; + VuBaseBlock::LISTBLOCKS::iterator itchild; + + u32 livevars[2]; + + do { + changed = FALSE; + for(itblock = s_listBlocks.rbegin(); itblock != s_listBlocks.rend(); ++itblock) { + + u32 newlive; + VuBaseBlock* pb = *itblock; + + // the last inst relies on the neighbor's insts + itinst = --pb->insts.end(); + + if( pb->blocks.size() > 0 ) { + livevars[0] = 0; livevars[1] = 0; + for( itchild = pb->blocks.begin(); itchild != pb->blocks.end(); ++itchild) { + VuInstruction& front = (*itchild)->insts.front(); + livevars[0] |= front.livevars[0]; + livevars[1] |= front.livevars[1]; + } + + newlive = COMPUTE_LIVE(itinst->addvars[0], itinst->keepvars[0], livevars[0]); + if( itinst->livevars[0] != newlive ) { + changed = TRUE; + itinst->livevars[0] = newlive; + } + + newlive = COMPUTE_LIVE(itinst->addvars[1], itinst->keepvars[1], livevars[1]); + if( itinst->livevars[1] != newlive ) { + changed = TRUE; + itinst->livevars[1] = newlive; + } + } + + while( itinst != pb->insts.begin() ) { + + itnext = itinst; --itnext; + + newlive = COMPUTE_LIVE(itnext->addvars[0], itnext->keepvars[0], itinst->livevars[0]); + + if( itnext->livevars[0] != newlive ) { + changed = TRUE; + itnext->livevars[0] = newlive; + itnext->livevars[1] = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + } + else { + newlive = COMPUTE_LIVE(itnext->addvars[1], itnext->keepvars[1], itinst->livevars[1]); + if( itnext->livevars[1] != newlive ) { + changed = TRUE; + itnext->livevars[1] = newlive; + } + } + + itinst = itnext; + } + +// if( (livevars[0] | itinst->livevars[0]) != itinst->livevars[0] ) { +// changed = TRUE; +// itinst->livevars[0] |= livevars[0]; +// } +// if( (livevars[1] | itinst->livevars[1]) != itinst->livevars[1] ) { +// changed = TRUE; +// itinst->livevars[1] |= livevars[1]; +// } +// +// while( itinst != pb->insts.begin() ) { +// +// itnext = itinst; --itnext; +// if( (itnext->livevars[0] | (itinst->livevars[0] & itnext->keepvars[0])) != itnext->livevars[0] ) { +// changed = TRUE; +// itnext->livevars[0] |= itinst->livevars[0] & itnext->keepvars[0]; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// else if( (itnext->livevars[1] | (itinst->livevars[1] & itnext->keepvars[1])) != itnext->livevars[1] ) { +// changed = TRUE; +// itnext->livevars[1] |= itinst->livevars[1] & itnext->keepvars[1]; +// } +// +// itinst = itnext; +// } + } + + } while(changed); +} + +static void SuperVUEliminateDeadCode() +{ + list::iterator itblock; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itinst, itnext; + list listParents; + list::iterator itparent; + + FORIT(itblock, s_listBlocks) { + +#ifdef _DEBUG + u32 startpc = (*itblock)->startpc; + u32 curpc = startpc; +#endif + + itnext = (*itblock)->insts.begin(); + itinst = itnext++; + while(itnext != (*itblock)->insts.end() ) { + if( itinst->type & (INST_CLIP_WRITE|INST_MAC_WRITE|INST_STATUS_WRITE) ) { + itinst->regs[0].VIwrite &= itnext->livevars[0]; + itinst->regs[1].VIwrite &= itnext->livevars[0]; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + (*itblock)->GetInstsAtPc(itinst->nParentPc, listParents); + int removetype = 0; + + FORIT(itparent, listParents) { + VuInstruction* parent = *itparent; + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; + // parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; + // parent->regs[0].VIwrite &= ~(1<regs[1].VIwrite &= ~(1<regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~removetype; + if( itinst->type == 0 ) { + itnext = (*itblock)->insts.erase(itinst); + itinst = itnext++; + continue; + } + } +#ifdef _DEBUG + else curpc += 8; +#endif + itinst = itnext; + ++itnext; + } + + if( itinst->type & INST_DUMMY ) { + // last inst with the children + u32 mask = 0; + for(itchild = (*itblock)->blocks.begin(); itchild != (*itblock)->blocks.end(); ++itchild) { + mask |= (*itchild)->insts.front().livevars[0]; + } + itinst->regs[0].VIwrite &= mask; + itinst->regs[1].VIwrite &= mask; + u32 viwrite = itinst->regs[0].VIwrite|itinst->regs[1].VIwrite; + + if( itinst->nParentPc >= 0 ) { + + (*itblock)->GetInstsAtPc(itinst->nParentPc, listParents); + int removetype = 0; + + FORIT(itparent, listParents) { + VuInstruction* parent = *itparent; + + if( viwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.macflag && (itinst->type & INST_MAC_WRITE) ) { + if( !(viwrite&(1<info.macflag = 0; +#ifndef SUPERVU_WRITEBACKS + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<info.statusflag && (itinst->type & INST_STATUS_WRITE)) { + if( !(viwrite&(1<info.statusflag = 0; +#ifndef SUPERVU_WRITEBACKS + assert( !(parent->regs[0].VIwrite & (1<regs[1].VIwrite & (1<regs[0].VIwrite |= (itinst->regs[0].VIwrite&(1<regs[1].VIwrite |= (itinst->regs[1].VIwrite&(1<type &= ~removetype; + if( itinst->type == 0 ) { + (*itblock)->insts.erase(itinst); + } + } + } + } +} + +// assigns xmm/x86 regs to all instructions, ignore mode field +// returns true if changed +bool AlignStartRegsToEndRegs(_xmmregs* startregs, const list& parents) +{ + list::const_iterator itblock, itblock2; + int bestscore; + _xmmregs bestregs; + bool bchanged = false; + + // find the best merge of regs that minimizes writes/reads + for(int i = 0; i < XMMREGS; ++i) { + + bestscore = 1000; + memset(&bestregs, 0, sizeof(bestregs)); + + FORIT(itblock, parents) { + int curscore = 0; + if( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->endregs[i].inuse ) { + int type = (*itblock)->endregs[i].type; + int reg = (*itblock)->endregs[i].reg; + + FORIT(itblock2, parents) { + if( (*itblock2)->type & BLOCKTYPE_ANALYZED ) { + if( (*itblock2)->endregs[i].inuse ) { + if( (*itblock2)->endregs[i].type != type || (*itblock2)->endregs[i].reg != reg ) { + curscore += 1; + } + } + else curscore++; + } + } + } + + if( curscore < 1 && curscore < bestscore ) { + memcpy(&bestregs, &(*itblock)->endregs[i], sizeof(bestregs)); + bestscore = curscore; + } + } + + if( bestscore < 1 ) { + if( startregs[i].inuse == bestregs.inuse ) { + if( bestregs.inuse && (startregs[i].type != bestregs.type || startregs[i].reg != bestregs.reg) ) + bchanged = true; + } + else bchanged = true; + + memcpy(&startregs[i], &bestregs, sizeof(bestregs)); + FORIT(itblock, parents) memcpy(&(*itblock)->endregs[i], &bestregs, sizeof(bestregs)); + } + else { + if( startregs[i].inuse ) bchanged = true; + startregs[i].inuse = 0; + FORIT(itblock, parents) (*itblock)->endregs[i].inuse = 0; + } + } + + return bchanged; +} + +void VuBaseBlock::AssignVFRegs() +{ + int i; + VuBaseBlock::LISTBLOCKS::iterator itchild; + list::iterator itblock; + list::iterator itinst, itnext, itinst2; + + // init the start regs + if( type & BLOCKTYPE_ANALYZED ) return; // nothing changed + memcpy(xmmregs, startregs, sizeof(xmmregs)); + + if( type & BLOCKTYPE_ANALYZED ) { + // check if changed + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse != startregs[i].inuse ) + break; + if( xmmregs[i].inuse && (xmmregs[i].reg != startregs[i].reg || xmmregs[i].type != startregs[i].type) ) + break; + } + + if( i == XMMREGS ) return; // nothing changed + } + + s8* oldX86 = x86Ptr; + + FORIT(itinst, insts) { + + if( itinst->type & INST_DUMMY ) + continue; + + // reserve, go from upper to lower + int lastwrite = -1; + + for(i = 1; i >= 0; --i) { + _VURegsNum* regs = itinst->regs+i; + + // redo the counters so that the proper regs are released + for(int j = 0; j < XMMREGS; ++j) { + if( xmmregs[j].inuse ) { + if( xmmregs[j].type == XMMTYPE_VFREG ) { + int count = 0; + itinst2 = itinst; + + if( i ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg ) { + itinst2 = insts.end(); + break; + } + else { + ++count; + ++itinst2; + } + } + + while(itinst2 != insts.end() ) { + if( itinst2->regs[0].VFread0 == xmmregs[j].reg || itinst2->regs[0].VFread1 == xmmregs[j].reg || itinst2->regs[0].VFwrite == xmmregs[j].reg || + itinst2->regs[1].VFread0 == xmmregs[j].reg || itinst2->regs[1].VFread1 == xmmregs[j].reg || itinst2->regs[1].VFwrite == xmmregs[j].reg) + break; + + ++count; + ++itinst2; + } + xmmregs[j].counter = 1000-count; + } + else { + assert( xmmregs[j].type == XMMTYPE_ACC ); + + int count = 0; + itinst2 = itinst; + + if( i ) ++itinst2; // acc isn't used in lower insts + + while(itinst2 != insts.end() ) { + assert( !((itinst2->regs[0].VIread|itinst2->regs[0].VIwrite) & (1<regs[1].VIread|itinst2->regs[1].VIwrite) & (1<VFread0 ) _addNeededVFtoXMMreg(regs->VFread0); + if( regs->VFread1 ) _addNeededVFtoXMMreg(regs->VFread1); + if( regs->VFwrite ) _addNeededVFtoXMMreg(regs->VFwrite); + if( regs->VIread & (1<VIread & (1<vfread0[i] = itinst->vfread1[i] = itinst->vfwrite[i] = itinst->vfacc[i] = -1; + itinst->vfflush[i] = -1; + + if( regs->VFread0 ) itinst->vfread0[i] = _allocVFtoXMMreg(VU, -1, regs->VFread0, 0); + else if( regs->VIread & (1<vfread0[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VFread1 ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, regs->VFread1, 0); + else if( (regs->VIread & (1<VFr1xyzw != 0xff ) itinst->vfread1[i] = _allocVFtoXMMreg(VU, -1, 0, 0); + if( regs->VIread & (1<vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + + int reusereg = -1; // 0 - VFwrite, 1 - VFAcc + + if( regs->VFwrite ) { + assert( !(regs->VIwrite&(1<VFwxyzw == 0xf ) { + itinst->vfwrite[i] = _checkXMMreg(XMMTYPE_VFREG, regs->VFwrite, 0); + if( itinst->vfwrite[i] < 0 ) reusereg = 0; + } + else { + itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + else if( regs->VIwrite & (1<VFwxyzw == 0xf ) { + itinst->vfacc[i] = _checkXMMreg(XMMTYPE_ACC, 0, 0); + if( itinst->vfacc[i] < 0 ) reusereg = 1; + } + else { + itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + } + } + + if( reusereg >= 0 ) { + // reuse + itnext = itinst; itnext++; + + u8 type = reusereg ? XMMTYPE_ACC : XMMTYPE_VFREG; + u8 reg = reusereg ? 0 : regs->VFwrite; + + if( itinst->vfacc[i] >= 0 && lastwrite != itinst->vfacc[i] && + (itnext == insts.end() || ((regs->VIread&(1<usedvars[0]&(1<livevars[0]&(1<livevars[0]&(1<vfacc[i]); + xmmregs[itinst->vfacc[i]].inuse = 1; + xmmregs[itinst->vfacc[i]].reg = reg; + xmmregs[itinst->vfacc[i]].type = type; + xmmregs[itinst->vfacc[i]].mode = 0; + itinst->vfwrite[i] = itinst->vfacc[i]; + } + else if( itinst->vfread0[i] >= 0 && lastwrite != itinst->vfread0[i] && + (itnext == insts.end() || (regs->VFread0 > 0 && (!(itnext->usedvars[1]&(1<VFread0)) || !(itnext->livevars[1]&(1<VFread0))))) ) { + + if(itnext == insts.end() || (itnext->livevars[1]®s->VFread0)) _freeXMMreg(itinst->vfread0[i]); + xmmregs[itinst->vfread0[i]].inuse = 1; + xmmregs[itinst->vfread0[i]].reg = reg; + xmmregs[itinst->vfread0[i]].type = type; + xmmregs[itinst->vfread0[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread0[i]; + else itinst->vfwrite[i] = itinst->vfread0[i]; + } + else if( itinst->vfread1[i] >= 0 && lastwrite != itinst->vfread1[i] && + (itnext == insts.end() || (regs->VFread1 > 0 && (!(itnext->usedvars[1]&(1<VFread1)) || !(itnext->livevars[1]&(1<VFread1))))) ) { + + if(itnext == insts.end() || (itnext->livevars[1]®s->VFread1)) _freeXMMreg(itinst->vfread1[i]); + xmmregs[itinst->vfread1[i]].inuse = 1; + xmmregs[itinst->vfread1[i]].reg = reg; + xmmregs[itinst->vfread1[i]].type = type; + xmmregs[itinst->vfread1[i]].mode = 0; + if( reusereg ) itinst->vfacc[i] = itinst->vfread1[i]; + else itinst->vfwrite[i] = itinst->vfread1[i]; + } + else { + if( reusereg ) itinst->vfacc[i] = _allocACCtoXMMreg(VU, -1, 0); + else itinst->vfwrite[i] = _allocVFtoXMMreg(VU, -1, regs->VFwrite, 0); + } + } + + if( itinst->vfwrite[i] >= 0 ) lastwrite = itinst->vfwrite[i]; + else if( itinst->vfacc[i] >= 0 ) lastwrite = itinst->vfacc[i]; + + // always alloc at least 1 temp reg + int free0 = (i||regs->VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<vfwrite[1] >= 0 && (itinst->vfread0[0]==itinst->vfwrite[1]||itinst->vfread1[0]==itinst->vfwrite[1]) ) { + itinst->vfflush[i] = _allocTempXMMreg(XMMT_FPS, -1); + } + + if( i == 1 && (regs->VIwrite & (1<VIwrite & (1<vfflush[i] >= 0 ) _freeXMMreg(itinst->vfflush[i]); + if( free0 >= 0 ) _freeXMMreg(free0); + + itinst->vffree[i] = (free0&0xf)|(free1<<8)|(free2<<16); + if( free0 == -1 ) itinst->vffree[i] |= VFFREE_INVALID0; + + _clearNeededXMMregs(); + } + } + + assert( x86Ptr == oldX86 ); + u32 analyzechildren = !(type&BLOCKTYPE_ANALYZED); + type |= BLOCKTYPE_ANALYZED; + + //memset(endregs, 0, sizeof(endregs)); + + if( analyzechildren ) { + FORIT(itchild, blocks) (*itchild)->AssignVFRegs(); + } +} + +struct MARKOVBLANKET +{ + list parents; + list children; +}; + +static MARKOVBLANKET s_markov; + +void VuBaseBlock::AssignVIRegs(int parent) +{ + const int maxregs = 6; + + if( parent ) { + if( (type&BLOCKTYPE_ANALYZEDPARENT) ) + return; + + type |= BLOCKTYPE_ANALYZEDPARENT; + s_markov.parents.push_back(this); + for(LISTBLOCKS::iterator it = blocks.begin(); it != blocks.end(); ++it) { + (*it)->AssignVIRegs(0); + } + return; + } + + if( (type&BLOCKTYPE_ANALYZED) ) + return; + + // child + assert( allocX86Regs == -1 ); + allocX86Regs = s_vecRegArray.size(); + s_vecRegArray.resize(allocX86Regs+X86REGS); + + _x86regs* pregs = &s_vecRegArray[allocX86Regs]; + memset(pregs, 0, sizeof(_x86regs)*X86REGS); + + assert( parents.size() > 0 ); + + list::iterator itparent; + u32 usedvars = insts.front().usedvars[0]; + u32 livevars = insts.front().livevars[0]; + + if( parents.size() > 0 ) { + u32 usedvars2 = 0xffffffff; + FORIT(itparent, parents) usedvars2 &= (*itparent)->insts.front().usedvars[0]; + usedvars |= usedvars2; + } + + usedvars &= livevars; + + // currently order doesn't matter + int num = 0; + + if( usedvars ) { + for(int i = 1; i < 16; ++i) { + if( usedvars & (1<= maxregs ) break; + } + } + } + + if( num < maxregs) { + livevars &= ~usedvars; + livevars &= insts.back().usedvars[0]; + + if( livevars ) { + for(int i = 1; i < 16; ++i) { + if( livevars & (1<= maxregs) break; + } + } + } + } + + s_markov.children.push_back(this); + type |= BLOCKTYPE_ANALYZED; + FORIT(itparent, parents) { + (*itparent)->AssignVIRegs(1); + } +} + +u32 VuBaseBlock::GetModeXYZW(u32 curpc, int vfreg) +{ + if( vfreg <= 0 ) return false; + + list::iterator itinst = insts.begin(); + advance(itinst, (curpc-startpc)/8); + + u8 mxy = 1; + u8 mxyz = 1; + + while(itinst != insts.end()) { + for(int i = 0; i < 2; ++i ) { + if( itinst->regs[i].VFwrite == vfreg ) { + if( itinst->regs[i].VFwxyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFwxyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread0 == vfreg ) { + if( itinst->regs[i].VFr0xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr0xyzw != 0xc ) mxy = 0; + } + if( itinst->regs[i].VFread1 == vfreg ) { + if( itinst->regs[i].VFr1xyzw != 0xe ) mxyz = 0; + if( itinst->regs[i].VFr1xyzw != 0xc ) mxy = 0; + } + + if( !mxy && !mxyz ) return 0; + } + ++itinst; + } + + return (mxy?MODE_VUXY:0)|(mxyz?MODE_VUXYZ:0); +} + +static void SuperVUAssignRegs() +{ + list::iterator itblock, itblock2; + + // assign xyz regs +// FORIT(itblock, s_listBlocks) { +// (*itblock)->vuxyz = 0; +// (*itblock)->vuxy = 0; +// +// for(int i = 0; i < 32; ++i) { +// u32 mode = (*itblock)->GetModeXYZW((*itblock)->startpc, i); +// if( mode & MODE_VUXYZ ) { +// if( mode & MODE_VUZ ) (*itblock)->vuxyz |= 1<vuxy |= 1<type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->AssignVFRegs(); + + // VI assignments, find markov blanket for each node in the graph + // then allocate regs based on the commonly used ones +#ifdef SUPERVU_X86CACHING + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~(BLOCKTYPE_ANALYZED|BLOCKTYPE_ANALYZEDPARENT); + s_vecRegArray.resize(0); + u8 usedregs[16]; + + // note: first block always has to start with no alloc regs + bool bfirst = true; + + FORIT(itblock, s_listBlocks) { + + if( !((*itblock)->type & BLOCKTYPE_ANALYZED) ) { + + if( (*itblock)->parents.size() == 0 ) { + (*itblock)->type |= BLOCKTYPE_ANALYZED; + bfirst = false; + continue; + } + + s_markov.children.clear(); + s_markov.parents.clear(); + (*itblock)->AssignVIRegs(0); + + // assign the regs + int regid = s_vecRegArray.size(); + s_vecRegArray.resize(regid+X86REGS); + + _x86regs* mergedx86 = &s_vecRegArray[regid]; + memset(mergedx86, 0, sizeof(_x86regs)*X86REGS); + + if( !bfirst ) { + *(u32*)usedregs = *((u32*)usedregs+1) = *((u32*)usedregs+2) = *((u32*)usedregs+3) = 0; + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->allocX86Regs >= 0 ); + _x86regs* pregs = &s_vecRegArray[(*itblock2)->allocX86Regs]; + for(int i = 0; i < X86REGS; ++i) { + if( pregs[i].inuse && pregs[i].reg < 16) { + //assert( pregs[i].reg < 16); + usedregs[pregs[i].reg]++; + } + } + } + + int num = 1; + for(int i = 0; i < 16; ++i) { + if( usedregs[i] == s_markov.children.size() ) { + // use + mergedx86[num].inuse = 1; + mergedx86[num].reg = i; + mergedx86[num].type = (s_vu?X86TYPE_VU1:0)|X86TYPE_VI; + mergedx86[num].mode = MODE_READ; + if( ++num >= X86REGS ) + break; + if( num == ESP ) + ++num; + } + } + + FORIT(itblock2, s_markov.children) { + assert( (*itblock2)->nStartx86 == -1 ); + (*itblock2)->nStartx86 = regid; + } + + FORIT(itblock2, s_markov.parents) { + assert( (*itblock2)->nEndx86 == -1 ); + (*itblock2)->nEndx86 = regid; + } + } + + bfirst = false; + } + } +#endif +} + +////////////////// +// Recompilation +////////////////// + +extern "C" { +// cycles in which the last Q,P regs were finished (written to VU->VI[]) +// the write occurs before the instruction is executed at that cycle +// compare with s_TotalVUCycles +// if less than 0, already flushed +int s_writeQ, s_writeP; + +// declare the saved registers +uptr s_vu1esp, s_callstack;//, s_vu1esp +#ifndef __x86_64__ +uptr s_vu1ebp, s_vuebx, s_vuedi, s_vu1esi; +#endif + +} + +static int s_recWriteQ, s_recWriteP; // wait times during recompilation +static int s_needFlush; // first bit - Q, second bit - P, third bit - Q has been written, fourth bit - P has been written + +static u32 s_ssecsr; +static int s_JumpX86; +static int s_ScheduleXGKICK = 0, s_XGKICKReg = -1; + +extern "C" u32 g_sseVUMXCSR, g_sseMXCSR; + +void recSVUMI_XGKICK_( VURegs *VU ); + +void SuperVUCleanupProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +#endif + +#ifdef _DEBUG + assert( s_vu1esp == 0 ); +#endif + + VU = vuindex ? &VU1 : &VU0; + VU->cycle += s_TotalVUCycles; + if( (int)s_writeQ > 0 ) VU->VI[REG_Q] = VU->q; + if( (int)s_writeP > 0 ) { + assert(VU == &VU1); + VU1.VI[REG_P] = VU1.p; // only VU1 + } +} + +#if defined(_MSC_VER) && !defined(__x86_64__) + +// entry point of all vu programs from emulator calls +__declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex) +{ +#ifdef SUPERVU_COUNT + QueryPerformanceCounter(&svubase); +#endif + __asm { + mov eax, dword ptr [esp] + mov s_TotalVUCycles, 0 // necessary to be here! + add esp, 4 + mov s_callstack, eax + call SuperVUGetProgram + + // save cpu state + mov s_vu1ebp, ebp + mov s_vu1esi, esi // have to save even in Release + mov s_vuedi, edi // have to save even in Release + mov s_vuebx, ebx + } +#ifdef _DEBUG + __asm { + mov s_vu1esp, esp + } +#endif + + __asm { + //stmxcsr s_ssecsr + ldmxcsr g_sseVUMXCSR + + // init vars + mov s_writeQ, 0xffffffff + mov s_writeP, 0xffffffff + + jmp eax + } +} + +// exit point of all vu programs +__declspec(naked) static void SuperVUEndProgram() +{ + __asm { + // restore cpu state + ldmxcsr g_sseMXCSR + + mov ebp, s_vu1ebp + mov esi, s_vu1esi + mov edi, s_vuedi + mov ebx, s_vuebx + } + +#ifdef _DEBUG + __asm { + sub s_vu1esp, esp + } +#endif + + __asm { + call SuperVUCleanupProgram + jmp s_callstack // so returns correctly + } +} + +#else // _MSC_VER + +extern "C" void svudispfn(); + +#endif + +// Flushes P/Q regs +void SuperVUFlush(int p, int wait) +{ + u8* pjmp[3]; + if( !(s_needFlush&(1<info.cycle < recwait ) return; + + if( recwait == 0 ) { + // write didn't happen this block + MOV32MtoR(EAX, p ? (uptr)&s_writeP : (uptr)&s_writeQ); + OR32RtoR(EAX, EAX); + pjmp[0] = JS8(0); + + if( s_pCurInst->info.cycle ) SUB32ItoR(EAX, s_pCurInst->info.cycle); + + // if writeQ <= total+offset + if( !wait ) { // only write back if time is up + CMP32MtoR(EAX, (uptr)&s_TotalVUCycles); + pjmp[1] = JG8(0); + } + else { + // add (writeQ-total-offset) to s_TotalVUCycles + // necessary? + CMP32MtoR(EAX, (uptr)&s_TotalVUCycles); + pjmp[2] = JLE8(0); + MOV32RtoM((uptr)&s_TotalVUCycles, EAX); + x86SetJ8(pjmp[2]); + } + } + else if( wait && s_pCurInst->info.cycle < recwait ) { + ADD32ItoM((uptr)&s_TotalVUCycles, recwait); + } + + MOV32MtoR(EAX, SuperVUGetVIAddr(p?REG_P:REG_Q, 0)); + MOV32ItoM(p ? (uptr)&s_writeP : (uptr)&s_writeQ, 0x80000000); + MOV32RtoM(SuperVUGetVIAddr(p?REG_P:REG_Q, 1), EAX); + + if( recwait == 0 ) { + if( !wait ) x86SetJ8(pjmp[1]); + x86SetJ8(pjmp[0]); + } + + if( wait || (!p && recwait == 0 && s_pCurInst->info.cycle >= 12) || (!p && recwait > 0 && s_pCurInst->info.cycle >= recwait ) ) + s_needFlush &= ~(1<::iterator itblock; + + FORIT(itblock, s_listBlocks) (*itblock)->type &= ~BLOCKTYPE_ANALYZED; + s_listBlocks.front()->Recompile(); + // make sure everything compiled + FORIT(itblock, s_listBlocks) assert( ((*itblock)->type & BLOCKTYPE_ANALYZED) && (*itblock)->pcode != NULL ); + + // link all blocks + FORIT(itblock, s_listBlocks) { + VuBaseBlock::LISTBLOCKS::iterator itchild; + + assert( (*itblock)->blocks.size() <= ARRAYSIZE((*itblock)->pChildJumps) ); + + int i = 0; + FORIT(itchild, (*itblock)->blocks) { + + if( (u32)(uptr)(*itblock)->pChildJumps[i] == 0xffffffff ) + continue; + + if( (*itblock)->pChildJumps[i] == NULL ) { + VuBaseBlock* pchild = *itchild; + + SysPrintf("1\n"); + if( pchild->type & BLOCKTYPE_HASEOP) { + assert( pchild->blocks.size() == 0); + + AND32ItoM( (uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (uptr)&VU->vifRegs->stat, ~0x4 ); + + MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); + } + // only other case is when there are two branches + else assert( (*itblock)->insts.back().regs[0].pipe == VUPIPE_BRANCH ); + + continue; + } + + if( (u32)(uptr)(*itblock)->pChildJumps[i] & 0x80000000 ) { + // relative + assert( (uptr)(*itblock)->pChildJumps[i] <= 0xffffffff); + (*itblock)->pChildJumps[i] = (u32*)((uptr)(*itblock)->pChildJumps[i] & 0x7fffffff); + *(*itblock)->pChildJumps[i] = (uptr)(*itchild)->pcode - ((uptr)(*itblock)->pChildJumps[i] + 4); + } + else *(*itblock)->pChildJumps[i] = (uptr)(*itchild)->pcode; + + ++i; + } + } + + s_pFnHeader->pprogfunc = s_listBlocks.front()->pcode; +} + +static u32 s_svulast = 0, s_vufnheader; +extern "C" u32 s_vucount; +u32 g_vu1lastrec = 0, skipparent = -1; +static u32 badaddrs[][2] = {0,0xffff}; +extern "C" { + +#ifndef __x86_64__ +u32 s_saveecx, s_saveedx, s_saveebx, s_saveesi, s_saveedi, s_saveebp; +#endif + +u32 g_curdebugvu; +} + +//extern "C" float vuDouble(u32 f); + +#if defined(_MSC_VER) && !defined(__x86_64__) +__declspec(naked) static void svudispfn() +{ + static u32 i; + + __asm { + mov g_curdebugvu, eax + mov s_saveecx, ecx + mov s_saveedx, edx + mov s_saveebx, ebx + mov s_saveesi, esi + mov s_saveedi, edi + mov s_saveebp, ebp + } +#else +extern "C" void svudispfntemp() +{ + static u32 i; +#endif + +// VU1.VF[7].F[0] = vuDouble(VU1.VF[7].UL[0]); +// VU1.VF[7].F[1] = vuDouble(VU1.VF[7].UL[1]); +// VU1.VF[7].F[2] = vuDouble(VU1.VF[7].UL[2]); +// VU1.VF[7].F[3] = vuDouble(VU1.VF[7].UL[3]); + + if( ((vudump&8) && g_curdebugvu) || ((vudump&0x80) && !g_curdebugvu) ) { //&& g_vu1lastrec != g_vu1last ) { + + if( skipparent != g_vu1lastrec ) { + for(i = 0; i < ARRAYSIZE(badaddrs); ++i) { + if( s_svulast == badaddrs[i][1] && g_vu1lastrec == badaddrs[i][0] ) + break; + } + + if( i == ARRAYSIZE(badaddrs) ) + { + //static int curesp; + //__asm mov curesp, esp + __Log("tVU: %x\n", s_svulast, s_vucount); + if( g_curdebugvu ) iDumpVU1Registers(); + else iDumpVU0Registers(); + s_vucount++; + } + } + + g_vu1lastrec = s_svulast; + } + +#if defined(_MSC_VER) && !defined(__x86_64__) + __asm { + mov ecx, s_saveecx + mov edx, s_saveedx + mov ebx, s_saveebx + mov esi, s_saveesi + mov edi, s_saveedi + mov ebp, s_saveebp + ret + } +#endif +} + +// frees an xmmreg depending on the liveness info of hte current inst +//void SuperVUFreeXMMreg(int xmmreg, int xmmtype, int reg) +//{ +// if( !xmmregs[xmmreg].inuse ) return; +// if( xmmregs[xmmreg].type == xmmtype && xmmregs[xmmreg].reg == reg ) return; +// +// if( s_pNextInst == NULL ) { +// // last inst, free +// _freeXMMreg(xmmreg); +// return; +// } +// +// if( xmmregs[xmmreg].type == XMMTYPE_VFREG ) { +// if( (s_pCurInst->livevars[1]|s_pNextInst->livevars[1]) & (1<livevars[0]|s_pNextInst->livevars[0]) & (1<VF[xmmregs[i].reg] : (uptr)&VU->ACC; + + if( xmmregs[i].mode & MODE_VUZ ) { + SSE_MOVHPS_XMM_to_M64(addr, (x86SSERegType)i); + SSE_SHUFPS_M128_to_XMM((x86SSERegType)i, addr, 0xc4); + } + else SSE_MOVHPS_M64_to_XMM((x86SSERegType)i, addr+8); + + xmmregs[i].mode &= ~MODE_VUXYZ; + } + + _freeXMMreg(i); + } + } + } + + //_freeXMMregs(); +} + +//void timeout() { SysPrintf("VU0 timeout\n"); } +void SuperVUTestVU0Condition(u32 incstack) +{ + if( s_vu ) return; // vu0 only + + CMP32ItoM((uptr)&s_TotalVUCycles, 512); // sometimes games spin on vu0, so be careful with this value + // woody hangs if too high + +#ifndef __x86_64__ + // x86-64 doesn't use a stack + if( incstack ) { + u8* ptr = JB8(0); + + if( incstack ) ADD32ItoR(ESP, incstack); + //CALLFunc((u32)timeout); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); + + x86SetJ8(ptr); + } + else +#endif + { + JAE32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 6 ) ); + } +} + +void VuBaseBlock::Recompile() +{ + if( type & BLOCKTYPE_ANALYZED ) return; + + x86Align(16); + pcode = x86Ptr; + +#ifdef _DEBUG + MOV32ItoM((uptr)&s_vufnheader, s_pFnHeader->startpc); + MOV32ItoM((uptr)&VU->VI[REG_TPC], startpc); + MOV32ItoM((uptr)&s_svulast, startpc); + list::iterator itparent; + for(itparent = parents.begin(); itparent != parents.end(); ++itparent) { + if( (*itparent)->blocks.size()==1 && (*itparent)->blocks.front()->startpc == startpc && + ((*itparent)->insts.size() < 2 || (----(*itparent)->insts.end())->regs[0].pipe != VUPIPE_BRANCH) ) { + MOV32ItoM((uptr)&skipparent, (*itparent)->startpc); + break; + } + } + + if( itparent == parents.end() ) MOV32ItoM((uptr)&skipparent, -1); + + MOV32ItoR(EAX, s_vu); + CALLFunc((uptr)svudispfn); +#endif + + s_pCurBlock = this; + s_needFlush = 3; + pc = startpc; + branch = 0; + s_recWriteQ = s_recWriteP = 0; + s_XGKICKReg = -1; + s_ScheduleXGKICK = 0; + + s_ClipRead = s_PrevClipWrite = (uptr)&VU->VI[REG_CLIP_FLAG]; + s_StatusRead = s_PrevStatusWrite = (uptr)&VU->VI[REG_STATUS_FLAG]; + s_MACRead = s_PrevMACWrite = (uptr)&VU->VI[REG_MAC_FLAG]; + s_PrevIWrite = (uptr)&VU->VI[REG_I]; + s_JumpX86 = 0; + s_UnconditionalDelay = 0; + + memcpy(xmmregs, startregs, sizeof(xmmregs)); +#ifdef SUPERVU_X86CACHING + if( nStartx86 >= 0 ) + memcpy(x86regs, &s_vecRegArray[nStartx86], sizeof(x86regs)); + else _initX86regs(); +#else + _initX86regs(); +#endif + + list::iterator itinst; + FORIT(itinst, insts) { + s_pCurInst = &(*itinst); + if( s_JumpX86 > 0 ) { + if( !x86regs[s_JumpX86].inuse ) { + // load + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_READ); + } + x86regs[s_JumpX86].needed = 1; + } +#ifdef __x86_64__ + // check X86ARG1 + if( x86regs[X86ARG1].inuse && x86regs[X86ARG1].type == X86TYPE_FNARG ) { + x86regs[X86ARG1].needed = 1; + } +#endif + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) { + assert( x86regs[s_XGKICKReg].inuse ); + x86regs[s_XGKICKReg].needed = 1; + } + itinst->Recompile(itinst, vuxyz); + + if( s_ScheduleXGKICK > 0 ) { + if( s_ScheduleXGKICK-- == 1 ) { + recSVUMI_XGKICK_(VU); + } + } + } + assert( pc == endpc ); + assert( s_ScheduleXGKICK == 0 ); + + // flush flags + if( s_PrevClipWrite != (uptr)&VU->VI[REG_CLIP_FLAG] ) { + MOV32MtoR(EAX, s_PrevClipWrite); + MOV32RtoM((uptr)&VU->VI[REG_CLIP_FLAG], EAX); + } + if( s_PrevStatusWrite != (uptr)&VU->VI[REG_STATUS_FLAG] ) { + // only lower 8 bits valid! + MOVZX32M8toR(EAX, s_PrevStatusWrite); + MOV32RtoM((uptr)&VU->VI[REG_STATUS_FLAG], EAX); + } + if( s_PrevMACWrite != (uptr)&VU->VI[REG_MAC_FLAG] ) { + // only lower 8 bits valid! + MOVZX32M8toR(EAX, s_PrevMACWrite); + MOV32RtoM((uptr)&VU->VI[REG_MAC_FLAG], EAX); + } + if( s_PrevIWrite != (uptr)&VU->VI[REG_I] ) { + MOV32ItoM((uptr)&VU->VI[REG_I], *(u32*)s_PrevIWrite); // never changes + } + + ADD32ItoM((uptr)&s_TotalVUCycles, cycles); + + // compute branches, jumps, eop + if( type & BLOCKTYPE_HASEOP ) { + // end + _freeXMMregs(); + _freeX86regs(); + AND32ItoM( (uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag + AND32ItoM( (uptr)&VU->vifRegs->stat, ~0x4 ); + if( !branch ) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); + } + else { + + u32 livevars[2] = {0}; + + list::iterator lastinst = GetInstIterAtPc(endpc-8); + lastinst++; + + if( lastinst != insts.end() ) { + livevars[0] = lastinst->livevars[0]; + livevars[1] = lastinst->livevars[1]; + } + else { + // take from children + if( blocks.size() > 0 ) { + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + livevars[0] |= (*itchild)->insts.front().livevars[0]; + livevars[1] |= (*itchild)->insts.front().livevars[1]; + } + } + else { + livevars[0] = ~0; + livevars[1] = ~0; + } + } + + SuperVUFreeXMMregs(livevars); + + // get rid of any writes, otherwise _freeX86regs will write + x86regs[s_JumpX86].mode &= ~MODE_WRITE; + +#ifdef __x86_64__ + bool bValidX86Arg = false; // if false, then use _x86GetAddr(X86TYPE_FNARG, reg); + if( x86regs[X86ARG1].inuse ) { + bValidX86Arg = true; + if( x86regs[X86ARG1].type==X86TYPE_FNARG ) + x86regs[X86ARG1].mode &= ~MODE_WRITE; + } +#endif + + if( branch == 1 ) { + if( !x86regs[s_JumpX86].inuse ) { + assert( x86regs[s_JumpX86].type == X86TYPE_VUJUMP ); + s_JumpX86 = 0xffffffff; // notify to jump from g_recWriteback + } + } + + // align VI regs +#ifdef SUPERVU_X86CACHING + if( nEndx86 >= 0 ) { + _x86regs* endx86 = &s_vecRegArray[nEndx86]; + for(int i = 0; i < X86REGS; ++i) { + if( endx86[i].inuse ) { + + if( s_JumpX86 == i && x86regs[s_JumpX86].inuse ) { + x86regs[s_JumpX86].inuse = 0; + x86regs[EAX].inuse = 1; + MOV32RtoR(EAX, s_JumpX86); + s_JumpX86 = EAX; + } + + if( x86regs[i].inuse ) { + if( x86regs[i].type == endx86[i].type && x86regs[i].reg == endx86[i].reg ) { + _freeX86reg(i); + // will continue to use it + continue; + } + + if( x86regs[i].type == (X86TYPE_VI|(s_vu?X86TYPE_VU1:0)) ) { +#ifdef SUPERVU_INTERCACHING + if( livevars[0] & (1<code & 0x400 ? 0xfffffc00 | (VU->code & 0x3ff) : VU->code & 0x3ff) << 3; +// ADD32ItoRmOffset(ESP, delta, 0); +#ifndef __x86_64__ + ADD32ItoR(ESP, 8); // restore +#endif + pChildJumps[0] = (u32*)((uptr)JMP32(0)|0x80000000); + + break; + } + case 0: + case 3: // unconditional branch + pChildJumps[s_UnconditionalDelay] = (u32*)((uptr)JMP32(0)|0x80000000); + break; + + default: +#ifdef PCSX2_DEVBUILD + SysPrintf("Bad branch %x\n", branch); +#endif + assert(0); + break; + } + } + + pendcode = x86Ptr; + type |= BLOCKTYPE_ANALYZED; + + LISTBLOCKS::iterator itchild; + FORIT(itchild, blocks) { + (*itchild)->Recompile(); + } +} + +#define GET_VUXYZMODE(reg) 0//((vuxyz&(1<<(reg)))?MODE_VUXYZ:0) + +int VuInstruction::SetCachedRegs(int upper, u32 vuxyz) +{ + if( vfread0[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread0[upper], XMMTYPE_VFREG, regs[upper].VFread0); + _allocVFtoXMMreg(VU, vfread0[upper], regs[upper].VFread0, MODE_READ|GET_VUXYZMODE(regs[upper].VFread0)); + } + if( vfread1[upper] >= 0 ) { + SuperVUFreeXMMreg(vfread1[upper], XMMTYPE_VFREG, regs[upper].VFread1); + _allocVFtoXMMreg(VU, vfread1[upper], regs[upper].VFread1, MODE_READ|GET_VUXYZMODE(regs[upper].VFread1)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIread&(1<= 0 ) { + assert( regs[upper].VFwrite > 0); + SuperVUFreeXMMreg(vfwrite[upper], XMMTYPE_VFREG, regs[upper].VFwrite); + _allocVFtoXMMreg(VU, vfwrite[upper], regs[upper].VFwrite, + MODE_WRITE|(regs[upper].VFwxyzw != 0xf?MODE_READ:0)|GET_VUXYZMODE(regs[upper].VFwrite)); + } + if( vfacc[upper] >= 0 && (regs[upper].VIwrite&(1<= 0 ) info |= PROCESS_EE_SET_S(vfread0[upper]); + if( vfread1[upper] >= 0 ) info |= PROCESS_EE_SET_T(vfread1[upper]); + if( vfacc[upper] >= 0 ) info |= PROCESS_VU_SET_ACC(vfacc[upper]); + if( vfwrite[upper] >= 0 ) { + if( regs[upper].VFwrite == _Ft_ && vfread1[upper] < 0 ) { + info |= PROCESS_EE_SET_T(vfwrite[upper]); + } + else { + assert( regs[upper].VFwrite == _Fd_ ); + info |= PROCESS_EE_SET_D(vfwrite[upper]); + } + } + + if( !(vffree[upper]&VFFREE_INVALID0) ) { + SuperVUFreeXMMreg(vffree[upper]&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vffree[upper]&0xf); + } + info |= PROCESS_VU_SET_TEMP(vffree[upper]&0xf); + + if( vfflush[upper] >= 0 ) { + SuperVUFreeXMMreg(vfflush[upper], XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, vfflush[upper]); + } + + if( upper && (regs[upper].VIwrite & (1 << REG_CLIP_FLAG)) ) { + // CLIP inst, need two extra temp registers, put it EEREC_D and EEREC_ACC + assert( vfwrite[upper] == -1 ); + SuperVUFreeXMMreg((vffree[upper]>>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + + SuperVUFreeXMMreg((vffree[upper]>>16)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>16)&0xf); + info |= PROCESS_EE_SET_ACC((vffree[upper]>>16)&0xf); + + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + _freeXMMreg((vffree[upper]>>16)&0xf); // don't need anymore + } + else if( regs[upper].VIwrite & (1<>8)&0xf, XMMTYPE_TEMP, 0); + _allocTempXMMreg(XMMT_FPS, (vffree[upper]>>8)&0xf); + info |= PROCESS_EE_SET_D((vffree[upper]>>8)&0xf); + _freeXMMreg((vffree[upper]>>8)&0xf); // don't need anymore + } + + if( vfflush[upper] >= 0 ) _freeXMMreg(vfflush[upper]); + if( !(vffree[upper]&VFFREE_INVALID0) ) + _freeXMMreg(vffree[upper]&0xf); // don't need anymore + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<::iterator& itinst, u32 vuxyz) +{ + static PCSX2_ALIGNED16(VECTOR _VF); + static PCSX2_ALIGNED16(VECTOR _VFc); + u32 *ptr; + u8* pjmp; + int vfregstore=0, viregstore=0; + + assert( s_pCurInst == this); + s_WriteToReadQ = 0; + + ptr = (u32*)&VU->Micro[ pc ]; + + if( type & INST_Q_READ ) + SuperVUFlush(0, (ptr[0] == 0x800003bf)||!!(regs[0].VIwrite & (1<startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_ClipRead = (uptr)&VU->VI[REG_CLIP_FLAG]; + else { + s_ClipRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pClipWrite; + } + } + + // before modifying, check if they will ever be read + if( s_pCurBlock->type & BLOCKTYPE_MACFLAGS ) { + if( type & INST_STATUS_WRITE ) { + + if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_StatusRead = (uptr)&VU->VI[REG_STATUS_FLAG]; + else { + s_StatusRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pStatusWrite; + } + } + if( type & INST_MAC_WRITE ) { + + if( nParentPc < s_pCurBlock->startpc || nParentPc >= (int)pc ) + // reading from out of this block, so already flushed to mem + s_MACRead = (uptr)&VU->VI[REG_MAC_FLAG]; + else { + s_MACRead = s_pCurBlock->GetInstIterAtPc(nParentPc)->pMACWrite; + } + } + } + + assert( s_ClipRead != 0 ); + assert( s_MACRead != 0 ); + assert( s_StatusRead != 0 ); + return; + } + +#ifdef _DEBUG +// CMP32ItoM((u32)ptr, ptr[0]); +// j8Ptr[0] = JNE8(0); +// CMP32ItoM((u32)(ptr+1), ptr[1]); +// j8Ptr[1] = JNE8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[0] ); +// x86SetJ8( j8Ptr[1] ); +// _callFunctionArg3((uptr)checkvucodefn, MEM_CONSTTAG, MEM_CONSTTAG, MEM_CONSTTAG, pc, s_vu, ptr[0]); +// x86SetJ8( j8Ptr[ 2 ] ); + + MOV32ItoR(EAX, pc); +#endif + + assert( !(type & (INST_CLIP_WRITE|INST_STATUS_WRITE|INST_MAC_WRITE)) ); + pc += 8; + + list::const_iterator itinst2; + + if( (regs[0].VIwrite|regs[1].VIwrite) & ((1<type & BLOCKTYPE_MACFLAGS ) { + if( pMACWrite == 0 ) { + pMACWrite = (uptr)SuperVUStaticAlloc(4); + } + if( pStatusWrite == 0 ) + pStatusWrite = (uptr)SuperVUStaticAlloc(4); + } + else { + assert( s_StatusRead == (uptr)&VU->VI[REG_STATUS_FLAG] ); + assert( s_MACRead == (uptr)&VU->VI[REG_MAC_FLAG] ); + pMACWrite = s_MACRead; + pStatusWrite = s_StatusRead; + } + } + + if( pClipWrite == 0 && ((regs[0].VIwrite|regs[1].VIwrite) & (1<insts.end() ) { + if( (itinst2->regs[0].VIread|itinst2->regs[0].VIwrite|itinst2->regs[1].VIread|itinst2->regs[1].VIwrite) && (1<flags, VUFLAG_MFLAGSET); + } + if (ptr[1] & 0x10000000) { // D flag + TEST32ItoM((uptr)&VU0.VI[REG_FBRST].UL, s_vu?0x400:0x004); + u8* ptr = JZ8(0); + OR32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x200:0x002); + _callFunctionArg1((uptr)hwIntcIrq, MEM_CONSTTAG, s_vu?INTC_VU1:INTC_VU0); + x86SetJ8(ptr); + } + if (ptr[1] & 0x08000000) { // T flag + TEST32ItoM((uptr)&VU0.VI[REG_FBRST].UL, s_vu?0x800:0x008); + u8* ptr = JZ8(0); + OR32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, s_vu?0x400:0x004); + _callFunctionArg1((uptr)hwIntcIrq, MEM_CONSTTAG, s_vu?INTC_VU1:INTC_VU0); + x86SetJ8(ptr); + } + + // check upper flags + if (ptr[1] & 0x80000000) { // I flag + + assert( !(regs[0].VIwrite & ((1<code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + + s_PrevIWrite = (uptr)ptr; + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + else { + if( regs[0].VIwrite & (1<insts.end()); + u32* codeptr2 = ptr+2; + + while(itinst2 != s_pCurBlock->insts.end() ) { + if( !(itinst2->type & INST_DUMMY) && ((itinst2->regs[0].VIwrite&(1<type & INST_Q_WRITE) && itinst2->nParentPc == pc-8 ) { + break; + } + if( itinst2->type & INST_Q_READ ) { + cacheq = 1; + break; + } + if( itinst2->type & INST_DUMMY ) { + ++itinst2; + continue; + } + codeptr2 += 2; + ++itinst2; + } + + if( itinst2 == s_pCurBlock->insts.end() ) + cacheq = 1; + + int x86temp = -1; + if( cacheq ) + x86temp = _allocX86reg(-1, X86TYPE_TEMP, 0, 0); + + // new is written so flush old + // if type & INST_Q_READ, already flushed + if( !(type & INST_Q_READ) && s_recWriteQ == 0 ) MOV32MtoR(EAX, (uptr)&s_writeQ); + + if( cacheq ) + MOV32MtoR(x86temp, (uptr)&s_TotalVUCycles); + + if( !(type & INST_Q_READ) ) { + if( s_recWriteQ == 0 ) { + OR32RtoR(EAX, EAX); + pjmp = JS8(0); + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + x86SetJ8(pjmp); + } + else if( s_needFlush & 1 ) { + MOV32MtoR(EAX, SuperVUGetVIAddr(REG_Q, 0)); + MOV32RtoM(SuperVUGetVIAddr(REG_Q, 1), EAX); + s_needFlush &= ~1; + } + } + + // write new Q + if( cacheq ) { + assert(s_pCurInst->pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((uptr)&s_writeQ, x86temp); + s_needFlush |= 1; + } + else { + // won't be writing back + s_WriteToReadQ = 1; + s_needFlush &= ~1; + MOV32ItoM((uptr)&s_writeQ, 0x80000001); + } + + s_recWriteQ = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + if( x86temp >= 0 ) + _freeX86reg(x86temp); + } + + if( regs[0].VIwrite & (1<pqcycles>1); + ADD32ItoR(x86temp, s_pCurInst->info.cycle+s_pCurInst->pqcycles); + MOV32RtoM((uptr)&s_writeP, x86temp); + s_needFlush |= 2; + + s_recWriteP = s_pCurInst->info.cycle+s_pCurInst->pqcycles; + + _freeX86reg(x86temp); + } + + if( ptr[0] == 0x800003bf ) // waitq + SuperVUFlush(0, 1); + + if( ptr[0] == 0x800007bf ) // waitp + SuperVUFlush(1, 1); + +#ifdef PCSX2_DEVBUILD + if ( regs[1].VIread & regs[0].VIwrite & ~((1<startpc); + } +#endif + + u32 modewrite = 0; + if( vfwrite[1] >= 0 && xmmregs[vfwrite[1]].inuse && xmmregs[vfwrite[1]].type == XMMTYPE_VFREG && xmmregs[vfwrite[1]].reg == regs[1].VFwrite ) + modewrite = xmmregs[vfwrite[1]].mode & MODE_WRITE; + + VU->code = ptr[1]; + s_vuInfo = SetCachedRegs(1, vuxyz); + + if (vfwrite[1] >= 0) { + assert( regs[1].VFwrite > 0 ); + + if (vfwrite[0] == vfwrite[1]) { + //SysPrintf("*PCSX2*: Warning, VF write to the same reg in both lower/upper cycle %x\n", s_pCurBlock->startpc); + } + + if (vfread0[0] == vfwrite[1] || vfread1[0] == vfwrite[1] ) { + assert( regs[0].VFread0 == regs[1].VFwrite || regs[0].VFread1 == regs[1].VFwrite ); + assert( vfflush[0] >= 0 ); + if( modewrite ) { + SSE_MOVAPS_XMM_to_M128((uptr)&VU->VF[regs[1].VFwrite], (x86SSERegType)vfwrite[1]); + } + vfregstore = 1; + } + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + recSVU_UPPER_OPCODE[ VU->code & 0x3f ](); + _clearNeededXMMregs(); + _clearNeededX86regs(); + + // necessary because status can be set by both upper and lower + if( regs[1].VIwrite & (1<code = ptr[0]; + s_vuInfo = SetCachedRegs(0, vuxyz); + + if( vfregstore ) { + // load + SSE_MOVAPS_M128_to_XMM(vfflush[0], (uptr)&VU->VF[regs[1].VFwrite]); + + assert( xmmregs[vfwrite[1]].mode & MODE_WRITE ); + + // replace with vfflush + if( _Fs_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_S(0xf); + s_vuInfo |= PROCESS_EE_SET_S(vfflush[0]); + } + if( _Ft_ == regs[1].VFwrite ) { + s_vuInfo &= ~PROCESS_EE_SET_T(0xf); + s_vuInfo |= PROCESS_EE_SET_T(vfflush[0]); + } + + xmmregs[vfflush[0]].mode |= MODE_NOFLUSH|MODE_WRITE; // so that lower inst doesn't flush + } + + if( s_JumpX86 > 0 ) x86regs[s_JumpX86].needed = 1; + if( s_ScheduleXGKICK && s_XGKICKReg > 0 ) x86regs[s_XGKICKReg].needed = 1; + + // check if inst before branch and the write is the same as the read in the branch (wipeout) + int oldreg=0; +// if( pc == s_pCurBlock->endpc-16 ) { +// itinst2 = itinst; ++itinst2; +// if( itinst2->regs[0].pipe == VUPIPE_BRANCH && (itinst->regs[0].VIwrite&itinst2->regs[0].VIread) ) { +// +// CALLFunc((u32)branchfn); +// assert( itinst->regs[0].VIwrite & 0xffff ); +// SysPrintf("vi write before branch\n"); +// for(s_CacheVIReg = 0; s_CacheVIReg < 16; ++s_CacheVIReg) { +// if( itinst->regs[0].VIwrite & (1<endpc-8 && s_CacheVIReg >= 0 ) { +// assert( s_CacheVIX86 > 0 && x86regs[s_CacheVIX86].inuse && x86regs[s_CacheVIX86].reg == s_CacheVIReg && x86regs[s_CacheVIX86].type == X86TYPE_VITEMP ); +// +// oldreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), s_CacheVIReg, MODE_READ); +// x86regs[s_CacheVIX86].needed = 1; +// assert( x86regs[oldreg].mode & MODE_WRITE ); +// +// x86regs[s_CacheVIX86].type = X86TYPE_VI|(s_vu?X86TYPE_VU1:0); +// x86regs[oldreg].type = X86TYPE_VITEMP; +// } + + recSVU_LOWER_OPCODE[ VU->code >> 25 ](); + +// if( pc == s_pCurBlock->endpc-8 && s_CacheVIReg >= 0 ) { +// // revert +// x86regs[s_CacheVIX86].inuse = 0; +// x86regs[oldreg].type = X86TYPE_VI|(s_vu?X86TYPE_VU1:0); +// } + + _clearNeededXMMregs(); + _clearNeededX86regs(); + } + + // clip is always written so ok + if( (regs[0].VIwrite|regs[1].VIwrite) & (1<code); + int curjump = 0; + + if( s_pCurInst->type & INST_BRANCH_DELAY ) { + assert( (branch&0x17)!=0x10 && (branch&0x17)!=4 ); // no jump handlig for now + + if( (branch & 0x7) == 3 ) { + // previous was a direct jump + curjump = 1; + } + else if( branch & 1 ) curjump = 2; + } + + assert( s_JumpX86 > 0 ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr-1; + + if( !(s_pCurInst->type & INST_BRANCH_DELAY) ) { + j8Ptr[1] = JMP8(0); + x86SetJ8( j8Ptr[ 0 ] ); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), pc+8); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr-1; + + x86SetJ8( j8Ptr[ 1 ] ); + } + else + x86SetJ8( j8Ptr[ 0 ] ); + + branch |= 1; +} + +// supervu specific insts +void recSVUMI_IBQ_prep() +{ + int fsreg, ftreg; + + if( _Fs_ == 0 ) { + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( ftreg >= 0 ) { + CMP16ItoR( ftreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Ft_, 1), 0); + } + else if( _Ft_ == 0 ) { + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR( fsreg, 0 ); + } + else CMP16ItoM(SuperVUGetVIAddr(_Fs_, 1), 0); + } + else { + _addNeededX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_); + fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + ftreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Ft_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + if( ftreg >= 0 ) { + CMP16RtoR( fsreg, ftreg ); + } + else CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + else if( ftreg >= 0 ) { + CMP16MtoR(ftreg, SuperVUGetVIAddr(_Fs_, 1)); + } + else { + fsreg = _allocX86reg(-1, X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + CMP16MtoR(fsreg, SuperVUGetVIAddr(_Ft_, 1)); + } + } +} + +void recSVUMI_IBEQ() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JNE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JL8( 0 ); + } + + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBGTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JLE8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JLE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLEZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + CMP16ItoR(fsreg, 0); + j8Ptr[ 0 ] = JG8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JG8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBLTZ() +{ + int fsreg = _checkX86reg(X86TYPE_VI|(VU==&VU1?X86TYPE_VU1:0), _Fs_, MODE_READ); + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + + if( fsreg >= 0 ) { + OR16RtoR(fsreg, fsreg); + j8Ptr[ 0 ] = JNS8( 0 ); + } + else { + CMP16ItoM( SuperVUGetVIAddr(_Fs_, 1), 0x0 ); + j8Ptr[ 0 ] = JGE8( 0 ); + } + recSVUMI_BranchHandle(); +} + +void recSVUMI_IBNE() +{ + recSVUMI_IBQ_prep(); + j8Ptr[ 0 ] = JE8( 0 ); + recSVUMI_BranchHandle(); +} + +void recSVUMI_B() +{ + // supervu will take care of the rest + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; + s_UnconditionalDelay = 1; + } + + branch |= 3; +} + +void recSVUMI_BAL() +{ + int bpc = _recbranchAddr(VU->code); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); + + // loops to self, so check condition + if( bpc == s_pCurBlock->startpc && s_vu == 0 ) { + SuperVUTestVU0Condition(0); + } + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( s_pCurBlock->blocks.size() > 1 ) { + s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); + MOV32ItoR(s_JumpX86, 0); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; + s_UnconditionalDelay = 1; + } + + branch |= 3; +} + +void recSVUMI_JR() +{ + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { +#ifdef __x86_64__ + _allocX86reg(X86ARG1, X86TYPE_FNARG, 0, MODE_READ|MODE_WRITE); + MOV32RtoR(X86ARG1, EAX); +#else + PUSH32I(s_vu); + PUSH32R(EAX); +#endif + } + branch |= 0x10; // 0x08 is reserved +} + +void recSVUMI_JALR() +{ + _addNeededX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_); + + int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + LEA32RStoR(EAX, fsreg, 3); + CWDE(); // necessary, charlie and chocolate factory gives bad addrs, but graphics are ok + + if ( _Ft_ ) { + _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); + MOV16ItoM( SuperVUGetVIAddr(_Ft_, 0), (pc+8)>>3 ); + } + + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); + + if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { +#ifdef __x86_64__ + _allocX86reg(X86ARG1, X86TYPE_FNARG, 0, MODE_READ|MODE_WRITE); + MOV32RtoR(X86ARG1, EAX); +#else + PUSH32I(s_vu); + PUSH32R(EAX); +#endif + } + + branch |= 4; +} + +#ifdef SUPERVU_COUNT +void StopSVUCounter() +{ + QueryPerformanceCounter(&svufinal); + svutime += (u32)(svufinal.QuadPart-svubase.QuadPart); +} + +void StartSVUCounter() +{ + QueryPerformanceCounter(&svubase); +} +#endif + +#ifdef PCSX2_DEVBUILD +void vu1xgkick(u32* pMem, u32 addr) +{ + assert( addr < 0x4000 ); +#ifdef _DEBUG + static int scount = 0; + //static int curesp; + //__asm mov curesp, esp; + scount++; + if( vudump & 8 ) { + __Log("xgkick 0x%x (%d)\n", addr, scount); + } +#endif + + GSGIFTRANSFER1(pMem, addr); +} + +//extern u32 vudump; +//void countfn() +//{ +// static int scount = 0; +// scount++; +// +// if( scount > 16 ) { +// __Log("xgkick %d\n", scount); +// vudump |= 8; +// } +//} + +#endif + +void recSVUMI_XGKICK_( VURegs *VU ) +{ + assert( s_XGKICKReg > 0 && x86regs[s_XGKICKReg].inuse && x86regs[s_XGKICKReg].type == X86TYPE_VITEMP); + + x86regs[s_XGKICKReg].inuse = 0; // so free doesn't flush + _freeX86regs(); + _freeXMMregs(); + +#ifdef __x86_64__ + if( X86ARG2 != s_XGKICKReg ) + MOV32RtoR(X86ARG2, s_XGKICKReg); + MOV32ItoR(X86ARG1, (uptr)VU->Mem); +#else + PUSH32R(s_XGKICKReg); + PUSH32I((uptr)VU->Mem); +#endif + +#ifdef SUPERVU_COUNT + CALLFunc((u32)StopSVUCounter); +#endif + + //CALLFunc((u32)countfn); + + if( CHECK_MULTIGS ) { + CALLFunc((uptr)VU1XGKICK_MTGSTransfer); +#ifndef __x86_64__ + ADD32ItoR(ESP, 8); +#endif + } + else { +#ifdef PCSX2_DEVBUILD + CALLFunc((uptr)vu1xgkick); +#ifndef __x86_64__ + ADD32ItoR(ESP, 8); +#endif +#else + CALLFunc((uptr)GSgifTransfer1); +#endif + } + +#ifdef SUPERVU_COUNT + CALLFunc((uptr)StartSVUCounter); +#endif + + s_ScheduleXGKICK = 0; +} + +void recSVUMI_XGKICK( VURegs *VU, int info ) +{ + if( s_ScheduleXGKICK ) { + // second xgkick, so launch the first + recSVUMI_XGKICK_(VU); + } + + int fsreg = _allocX86reg(X86ARG2, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); + _freeX86reg(fsreg); // flush + x86regs[fsreg].inuse = 1; + x86regs[fsreg].type = X86TYPE_VITEMP; + x86regs[fsreg].needed = 1; + x86regs[fsreg].mode = MODE_WRITE|MODE_READ; + SHL32ItoR(fsreg, 4); + AND32ItoR(fsreg, 0x3fff); + s_XGKICKReg = fsreg; + + if( !SUPERVU_XGKICKDELAY || pc == s_pCurBlock->endpc ) { + recSVUMI_XGKICK_(VU); + } + else { + if( g_VUGameFixes & VUFIX_XGKICKDELAY2 ) + s_ScheduleXGKICK = min((u32)4, (s_pCurBlock->endpc-pc)/8); + else + s_ScheduleXGKICK = 2; + } +} + +// upper inst +void recSVUMI_ABS() { recVUMI_ABS(VU, s_vuInfo); } + +void recSVUMI_ADD() { recVUMI_ADD(VU, s_vuInfo); } +void recSVUMI_ADDi() { recVUMI_ADDi(VU, s_vuInfo); } +void recSVUMI_ADDq() { recVUMI_ADDq(VU, s_vuInfo); } +void recSVUMI_ADDx() { recVUMI_ADDx(VU, s_vuInfo); } +void recSVUMI_ADDy() { recVUMI_ADDy(VU, s_vuInfo); } +void recSVUMI_ADDz() { recVUMI_ADDz(VU, s_vuInfo); } +void recSVUMI_ADDw() { recVUMI_ADDw(VU, s_vuInfo); } + +void recSVUMI_ADDA() { recVUMI_ADDA(VU, s_vuInfo); } +void recSVUMI_ADDAi() { recVUMI_ADDAi(VU, s_vuInfo); } +void recSVUMI_ADDAq() { recVUMI_ADDAq(VU, s_vuInfo); } +void recSVUMI_ADDAx() { recVUMI_ADDAx(VU, s_vuInfo); } +void recSVUMI_ADDAy() { recVUMI_ADDAy(VU, s_vuInfo); } +void recSVUMI_ADDAz() { recVUMI_ADDAz(VU, s_vuInfo); } +void recSVUMI_ADDAw() { recVUMI_ADDAw(VU, s_vuInfo); } + +void recSVUMI_SUB() { recVUMI_SUB(VU, s_vuInfo); } +void recSVUMI_SUBi() { recVUMI_SUBi(VU, s_vuInfo); } +void recSVUMI_SUBq() { recVUMI_SUBq(VU, s_vuInfo); } +void recSVUMI_SUBx() { recVUMI_SUBx(VU, s_vuInfo); } +void recSVUMI_SUBy() { recVUMI_SUBy(VU, s_vuInfo); } +void recSVUMI_SUBz() { recVUMI_SUBz(VU, s_vuInfo); } +void recSVUMI_SUBw() { recVUMI_SUBw(VU, s_vuInfo); } + +void recSVUMI_SUBA() { recVUMI_SUBA(VU, s_vuInfo); } +void recSVUMI_SUBAi() { recVUMI_SUBAi(VU, s_vuInfo); } +void recSVUMI_SUBAq() { recVUMI_SUBAq(VU, s_vuInfo); } +void recSVUMI_SUBAx() { recVUMI_SUBAx(VU, s_vuInfo); } +void recSVUMI_SUBAy() { recVUMI_SUBAy(VU, s_vuInfo); } +void recSVUMI_SUBAz() { recVUMI_SUBAz(VU, s_vuInfo); } +void recSVUMI_SUBAw() { recVUMI_SUBAw(VU, s_vuInfo); } + +void recSVUMI_MUL() { recVUMI_MUL(VU, s_vuInfo); } +void recSVUMI_MULi() { recVUMI_MULi(VU, s_vuInfo); } +void recSVUMI_MULq() { recVUMI_MULq(VU, s_vuInfo); } +void recSVUMI_MULx() { recVUMI_MULx(VU, s_vuInfo); } +void recSVUMI_MULy() { recVUMI_MULy(VU, s_vuInfo); } +void recSVUMI_MULz() { recVUMI_MULz(VU, s_vuInfo); } +void recSVUMI_MULw() { recVUMI_MULw(VU, s_vuInfo); } + +void recSVUMI_MULA() { recVUMI_MULA(VU, s_vuInfo); } +void recSVUMI_MULAi() { recVUMI_MULAi(VU, s_vuInfo); } +void recSVUMI_MULAq() { recVUMI_MULAq(VU, s_vuInfo); } +void recSVUMI_MULAx() { recVUMI_MULAx(VU, s_vuInfo); } +void recSVUMI_MULAy() { recVUMI_MULAy(VU, s_vuInfo); } +void recSVUMI_MULAz() { recVUMI_MULAz(VU, s_vuInfo); } +void recSVUMI_MULAw() { recVUMI_MULAw(VU, s_vuInfo); } + +void recSVUMI_MADD() { recVUMI_MADD(VU, s_vuInfo); } +void recSVUMI_MADDi() { recVUMI_MADDi(VU, s_vuInfo); } +void recSVUMI_MADDq() { recVUMI_MADDq(VU, s_vuInfo); } +void recSVUMI_MADDx() { recVUMI_MADDx(VU, s_vuInfo); } +void recSVUMI_MADDy() { recVUMI_MADDy(VU, s_vuInfo); } +void recSVUMI_MADDz() { recVUMI_MADDz(VU, s_vuInfo); } +void recSVUMI_MADDw() { recVUMI_MADDw(VU, s_vuInfo); } + +void recSVUMI_MADDA() { recVUMI_MADDA(VU, s_vuInfo); } +void recSVUMI_MADDAi() { recVUMI_MADDAi(VU, s_vuInfo); } +void recSVUMI_MADDAq() { recVUMI_MADDAq(VU, s_vuInfo); } +void recSVUMI_MADDAx() { recVUMI_MADDAx(VU, s_vuInfo); } +void recSVUMI_MADDAy() { recVUMI_MADDAy(VU, s_vuInfo); } +void recSVUMI_MADDAz() { recVUMI_MADDAz(VU, s_vuInfo); } +void recSVUMI_MADDAw() { recVUMI_MADDAw(VU, s_vuInfo); } + +void recSVUMI_MSUB() { recVUMI_MSUB(VU, s_vuInfo); } +void recSVUMI_MSUBi() { recVUMI_MSUBi(VU, s_vuInfo); } +void recSVUMI_MSUBq() { recVUMI_MSUBq(VU, s_vuInfo); } +void recSVUMI_MSUBx() { recVUMI_MSUBx(VU, s_vuInfo); } +void recSVUMI_MSUBy() { recVUMI_MSUBy(VU, s_vuInfo); } +void recSVUMI_MSUBz() { recVUMI_MSUBz(VU, s_vuInfo); } +void recSVUMI_MSUBw() { recVUMI_MSUBw(VU, s_vuInfo); } + +void recSVUMI_MSUBA() { recVUMI_MSUBA(VU, s_vuInfo); } +void recSVUMI_MSUBAi() { recVUMI_MSUBAi(VU, s_vuInfo); } +void recSVUMI_MSUBAq() { recVUMI_MSUBAq(VU, s_vuInfo); } +void recSVUMI_MSUBAx() { recVUMI_MSUBAx(VU, s_vuInfo); } +void recSVUMI_MSUBAy() { recVUMI_MSUBAy(VU, s_vuInfo); } +void recSVUMI_MSUBAz() { recVUMI_MSUBAz(VU, s_vuInfo); } +void recSVUMI_MSUBAw() { recVUMI_MSUBAw(VU, s_vuInfo); } + +void recSVUMI_MAX() { recVUMI_MAX(VU, s_vuInfo); } +void recSVUMI_MAXi() { recVUMI_MAXi(VU, s_vuInfo); } +void recSVUMI_MAXx() { recVUMI_MAXx(VU, s_vuInfo); } +void recSVUMI_MAXy() { recVUMI_MAXy(VU, s_vuInfo); } +void recSVUMI_MAXz() { recVUMI_MAXz(VU, s_vuInfo); } +void recSVUMI_MAXw() { recVUMI_MAXw(VU, s_vuInfo); } + +void recSVUMI_MINI() { recVUMI_MINI(VU, s_vuInfo); } +void recSVUMI_MINIi() { recVUMI_MINIi(VU, s_vuInfo); } +void recSVUMI_MINIx() { recVUMI_MINIx(VU, s_vuInfo); } +void recSVUMI_MINIy() { recVUMI_MINIy(VU, s_vuInfo); } +void recSVUMI_MINIz() { recVUMI_MINIz(VU, s_vuInfo); } +void recSVUMI_MINIw() { recVUMI_MINIw(VU, s_vuInfo); } + +void recSVUMI_FTOI0() { recVUMI_FTOI0(VU, s_vuInfo); } +void recSVUMI_FTOI4() { recVUMI_FTOI4(VU, s_vuInfo); } +void recSVUMI_FTOI12() { recVUMI_FTOI12(VU, s_vuInfo); } +void recSVUMI_FTOI15() { recVUMI_FTOI15(VU, s_vuInfo); } +void recSVUMI_ITOF0() { recVUMI_ITOF0(VU, s_vuInfo); } +void recSVUMI_ITOF4() { recVUMI_ITOF4(VU, s_vuInfo); } +void recSVUMI_ITOF12() { recVUMI_ITOF12(VU, s_vuInfo); } +void recSVUMI_ITOF15() { recVUMI_ITOF15(VU, s_vuInfo); } + +void recSVUMI_OPMULA() { recVUMI_OPMULA(VU, s_vuInfo); } +void recSVUMI_OPMSUB() { recVUMI_OPMSUB(VU, s_vuInfo); } +void recSVUMI_NOP() { } +void recSVUMI_CLIP() { recVUMI_CLIP(VU, s_vuInfo); } + +// lower inst +void recSVUMI_MTIR() { recVUMI_MTIR(VU, s_vuInfo); } +void recSVUMI_MR32() { recVUMI_MR32(VU, s_vuInfo); } +void recSVUMI_MFIR() { recVUMI_MFIR(VU, s_vuInfo); } +void recSVUMI_MOVE() { recVUMI_MOVE(VU, s_vuInfo); } +void recSVUMI_WAITQ() { recVUMI_WAITQ(VU, s_vuInfo); } +void recSVUMI_MFP() { recVUMI_MFP(VU, s_vuInfo); } +void recSVUMI_WAITP() { recVUMI_WAITP(VU, s_vuInfo); } + +void recSVUMI_SQRT() { recVUMI_SQRT(VU, s_vuInfo); } +void recSVUMI_RSQRT() { recVUMI_RSQRT(VU, s_vuInfo); } +void recSVUMI_DIV() { recVUMI_DIV(VU, s_vuInfo); } + +void recSVUMI_ESADD() { recVUMI_ESADD(VU, s_vuInfo); } +void recSVUMI_ERSADD() { recVUMI_ERSADD(VU, s_vuInfo); } +void recSVUMI_ELENG() { recVUMI_ELENG(VU, s_vuInfo); } +void recSVUMI_ERLENG() { recVUMI_ERLENG(VU, s_vuInfo); } +void recSVUMI_EATANxy() { recVUMI_EATANxy(VU, s_vuInfo); } +void recSVUMI_EATANxz() { recVUMI_EATANxz(VU, s_vuInfo); } +void recSVUMI_ESUM() { recVUMI_ESUM(VU, s_vuInfo); } +void recSVUMI_ERCPR() { recVUMI_ERCPR(VU, s_vuInfo); } +void recSVUMI_ESQRT() { recVUMI_ESQRT(VU, s_vuInfo); } +void recSVUMI_ERSQRT() { recVUMI_ERSQRT(VU, s_vuInfo); } +void recSVUMI_ESIN() { recVUMI_ESIN(VU, s_vuInfo); } +void recSVUMI_EATAN() { recVUMI_EATAN(VU, s_vuInfo); } +void recSVUMI_EEXP() { recVUMI_EEXP(VU, s_vuInfo); } + +void recSVUMI_XITOP() { recVUMI_XITOP(VU, s_vuInfo); } +void recSVUMI_XGKICK() { recSVUMI_XGKICK(VU, s_vuInfo); } +void recSVUMI_XTOP() { recVUMI_XTOP(VU, s_vuInfo); } + +void recSVUMI_RINIT() { recVUMI_RINIT(VU, s_vuInfo); } +void recSVUMI_RGET() { recVUMI_RGET(VU, s_vuInfo); } +void recSVUMI_RNEXT() { recVUMI_RNEXT(VU, s_vuInfo); } +void recSVUMI_RXOR() { recVUMI_RXOR(VU, s_vuInfo); } + +void recSVUMI_FSAND() { recVUMI_FSAND(VU, s_vuInfo); } +void recSVUMI_FSEQ() { recVUMI_FSEQ(VU, s_vuInfo); } +void recSVUMI_FSOR() { recVUMI_FSOR(VU, s_vuInfo); } +void recSVUMI_FSSET() { recVUMI_FSSET(VU, s_vuInfo); } +void recSVUMI_FMEQ() { recVUMI_FMEQ(VU, s_vuInfo); } +void recSVUMI_FMOR() { recVUMI_FMOR(VU, s_vuInfo); } +void recSVUMI_FCEQ() { recVUMI_FCEQ(VU, s_vuInfo); } +void recSVUMI_FCOR() { recVUMI_FCOR(VU, s_vuInfo); } +void recSVUMI_FCSET() { recVUMI_FCSET(VU, s_vuInfo); } +void recSVUMI_FCGET() { recVUMI_FCGET(VU, s_vuInfo); } +void recSVUMI_FCAND() { recVUMI_FCAND(VU, s_vuInfo); } +void recSVUMI_FMAND() { recVUMI_FMAND(VU, s_vuInfo); } + +void recSVUMI_LQ() { recVUMI_LQ(VU, s_vuInfo); } +void recSVUMI_LQD() { recVUMI_LQD(VU, s_vuInfo); } +void recSVUMI_LQI() { recVUMI_LQI(VU, s_vuInfo); } +void recSVUMI_SQ() { recVUMI_SQ(VU, s_vuInfo); } +void recSVUMI_SQD() { recVUMI_SQD(VU, s_vuInfo); } +void recSVUMI_SQI() { recVUMI_SQI(VU, s_vuInfo); } +void recSVUMI_ILW() { recVUMI_ILW(VU, s_vuInfo); } +void recSVUMI_ISW() { recVUMI_ISW(VU, s_vuInfo); } +void recSVUMI_ILWR() { recVUMI_ILWR(VU, s_vuInfo); } +void recSVUMI_ISWR() { recVUMI_ISWR(VU, s_vuInfo); } + +void recSVUMI_IADD() { recVUMI_IADD(VU, s_vuInfo); } +void recSVUMI_IADDI() { recVUMI_IADDI(VU, s_vuInfo); } +void recSVUMI_IADDIU() { recVUMI_IADDIU(VU, s_vuInfo); } +void recSVUMI_IOR() { recVUMI_IOR(VU, s_vuInfo); } +void recSVUMI_ISUB() { recVUMI_ISUB(VU, s_vuInfo); } +void recSVUMI_IAND() { recVUMI_IAND(VU, s_vuInfo); } +void recSVUMI_ISUBIU() { recVUMI_ISUBIU(VU, s_vuInfo); } + +void recSVU_UPPER_FD_00( void ); +void recSVU_UPPER_FD_01( void ); +void recSVU_UPPER_FD_10( void ); +void recSVU_UPPER_FD_11( void ); +void recSVULowerOP( void ); +void recSVULowerOP_T3_00( void ); +void recSVULowerOP_T3_01( void ); +void recSVULowerOP_T3_10( void ); +void recSVULowerOP_T3_11( void ); +void recSVUunknown( void ); + +void (*recSVU_LOWER_OPCODE[128])() = { + recSVUMI_LQ , recSVUMI_SQ , recSVUunknown , recSVUunknown, + recSVUMI_ILW , recSVUMI_ISW , recSVUunknown , recSVUunknown, + recSVUMI_IADDIU, recSVUMI_ISUBIU, recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_FCEQ , recSVUMI_FCSET , recSVUMI_FCAND, recSVUMI_FCOR, /* 0x10 */ + recSVUMI_FSEQ , recSVUMI_FSSET , recSVUMI_FSAND, recSVUMI_FSOR, + recSVUMI_FMEQ , recSVUunknown , recSVUMI_FMAND, recSVUMI_FMOR, + recSVUMI_FCGET , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_B , recSVUMI_BAL , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUMI_JR , recSVUMI_JALR , recSVUunknown , recSVUunknown, + recSVUMI_IBEQ , recSVUMI_IBNE , recSVUunknown , recSVUunknown, + recSVUMI_IBLTZ , recSVUMI_IBGTZ , recSVUMI_IBLEZ, recSVUMI_IBGEZ, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x40*/ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x50 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x60 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x70 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, +}; + +void (*recSVULowerOP_T3_00_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MOVE , recSVUMI_LQI , recSVUMI_DIV , recSVUMI_MTIR, + recSVUMI_RNEXT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_MFP , recSVUMI_XTOP , recSVUMI_XGKICK, + recSVUMI_ESADD , recSVUMI_EATANxy, recSVUMI_ESQRT, recSVUMI_ESIN, +}; + +void (*recSVULowerOP_T3_01_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_MR32 , recSVUMI_SQI , recSVUMI_SQRT , recSVUMI_MFIR, + recSVUMI_RGET , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUMI_XITOP, recSVUunknown, + recSVUMI_ERSADD, recSVUMI_EATANxz, recSVUMI_ERSQRT, recSVUMI_EATAN, +}; + +void (*recSVULowerOP_T3_10_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_LQD , recSVUMI_RSQRT, recSVUMI_ILWR, + recSVUMI_RINIT , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ELENG , recSVUMI_ESUM , recSVUMI_ERCPR, recSVUMI_EEXP, +}; + +void (*recSVULowerOP_T3_11_OPCODE[32])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUMI_SQD , recSVUMI_WAITQ, recSVUMI_ISWR, + recSVUMI_RXOR , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_ERLENG, recSVUunknown , recSVUMI_WAITP, recSVUunknown, +}; + +void (*recSVULowerOP_OPCODE[64])() = { + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x10 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x20 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUMI_IADD , recSVUMI_ISUB , recSVUMI_IADDI, recSVUunknown, /* 0x30 */ + recSVUMI_IAND , recSVUMI_IOR , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVULowerOP_T3_00, recSVULowerOP_T3_01, recSVULowerOP_T3_10, recSVULowerOP_T3_11, +}; + +void (*recSVU_UPPER_OPCODE[64])() = { + recSVUMI_ADDx , recSVUMI_ADDy , recSVUMI_ADDz , recSVUMI_ADDw, + recSVUMI_SUBx , recSVUMI_SUBy , recSVUMI_SUBz , recSVUMI_SUBw, + recSVUMI_MADDx , recSVUMI_MADDy , recSVUMI_MADDz , recSVUMI_MADDw, + recSVUMI_MSUBx , recSVUMI_MSUBy , recSVUMI_MSUBz , recSVUMI_MSUBw, + recSVUMI_MAXx , recSVUMI_MAXy , recSVUMI_MAXz , recSVUMI_MAXw, /* 0x10 */ + recSVUMI_MINIx , recSVUMI_MINIy , recSVUMI_MINIz , recSVUMI_MINIw, + recSVUMI_MULx , recSVUMI_MULy , recSVUMI_MULz , recSVUMI_MULw, + recSVUMI_MULq , recSVUMI_MAXi , recSVUMI_MULi , recSVUMI_MINIi, + recSVUMI_ADDq , recSVUMI_MADDq , recSVUMI_ADDi , recSVUMI_MADDi, /* 0x20 */ + recSVUMI_SUBq , recSVUMI_MSUBq , recSVUMI_SUBi , recSVUMI_MSUBi, + recSVUMI_ADD , recSVUMI_MADD , recSVUMI_MUL , recSVUMI_MAX, + recSVUMI_SUB , recSVUMI_MSUB , recSVUMI_OPMSUB, recSVUMI_MINI, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, /* 0x30 */ + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown, + recSVU_UPPER_FD_00, recSVU_UPPER_FD_01, recSVU_UPPER_FD_10, recSVU_UPPER_FD_11, +}; + +void (*recSVU_UPPER_FD_00_TABLE[32])() = { + recSVUMI_ADDAx, recSVUMI_SUBAx , recSVUMI_MADDAx, recSVUMI_MSUBAx, + recSVUMI_ITOF0, recSVUMI_FTOI0, recSVUMI_MULAx , recSVUMI_MULAq , + recSVUMI_ADDAq, recSVUMI_SUBAq, recSVUMI_ADDA , recSVUMI_SUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_01_TABLE[32])() = { + recSVUMI_ADDAy , recSVUMI_SUBAy , recSVUMI_MADDAy, recSVUMI_MSUBAy, + recSVUMI_ITOF4 , recSVUMI_FTOI4 , recSVUMI_MULAy , recSVUMI_ABS , + recSVUMI_MADDAq, recSVUMI_MSUBAq, recSVUMI_MADDA , recSVUMI_MSUBA , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_10_TABLE[32])() = { + recSVUMI_ADDAz , recSVUMI_SUBAz , recSVUMI_MADDAz, recSVUMI_MSUBAz, + recSVUMI_ITOF12, recSVUMI_FTOI12, recSVUMI_MULAz , recSVUMI_MULAi , + recSVUMI_ADDAi, recSVUMI_SUBAi , recSVUMI_MULA , recSVUMI_OPMULA, + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void (*recSVU_UPPER_FD_11_TABLE[32])() = { + recSVUMI_ADDAw , recSVUMI_SUBAw , recSVUMI_MADDAw, recSVUMI_MSUBAw, + recSVUMI_ITOF15, recSVUMI_FTOI15, recSVUMI_MULAw , recSVUMI_CLIP , + recSVUMI_MADDAi, recSVUMI_MSUBAi, recSVUunknown , recSVUMI_NOP , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , + recSVUunknown , recSVUunknown , recSVUunknown , recSVUunknown , +}; + +void recSVU_UPPER_FD_00( void ) +{ + recSVU_UPPER_FD_00_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_01( void ) +{ + recSVU_UPPER_FD_01_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_10( void ) +{ + recSVU_UPPER_FD_10_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVU_UPPER_FD_11( void ) +{ + recSVU_UPPER_FD_11_TABLE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP( void ) +{ + recSVULowerOP_OPCODE[ VU->code & 0x3f ]( ); +} + +void recSVULowerOP_T3_00( void ) +{ + recSVULowerOP_T3_00_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_01( void ) +{ + recSVULowerOP_T3_01_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_10( void ) +{ + recSVULowerOP_T3_10_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVULowerOP_T3_11( void ) +{ + recSVULowerOP_T3_11_OPCODE[ ( VU->code >> 6 ) & 0x1f ]( ); +} + +void recSVUunknown( void ) +{ + SysPrintf("Unknown SVU micromode opcode called\n"); +} + +#endif // PCX2_NORECBUILD diff --git a/pcsx2/x86/iVUzerorec.h b/pcsx2/x86/iVUzerorec.h new file mode 100644 index 0000000..693aa96 --- /dev/null +++ b/pcsx2/x86/iVUzerorec.h @@ -0,0 +1,49 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Super VU recompiler - author: zerofrog(@gmail.com) + +#ifndef VU1_SUPER_RECOMPILER +#define VU1_SUPER_RECOMPILER + +#ifdef __cplusplus +extern "C" { +#endif + +void SuperVUInit(int vuindex); // if vuindex is -1, inits the global VU resources +void SuperVUDestroy(int vuindex); // if vuindex is -1, destroys everything +void SuperVUReset(int vuindex); // if vuindex is -1, resets everything + +void SuperVUExecuteProgram(u32 startpc, int vuindex); +void SuperVUClear(u32 startpc, u32 size, int vuindex); + +u32 SuperVUGetRecTimes(int clear); + +// read = 0, will write to reg +// read = 1, will read from reg +// read = 2, addr of previously written reg (used for status and clip flags) +u32 SuperVUGetVIAddr(int reg, int read); + +// if p == 0, flush q else flush p; if wait is != 0, waits for p/q +void SuperVUFlush(int p, int wait); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pcsx2/x86/iVif.cpp b/pcsx2/x86/iVif.cpp new file mode 100644 index 0000000..6c89089 --- /dev/null +++ b/pcsx2/x86/iVif.cpp @@ -0,0 +1,158 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Common.h" +#include "ix86/ix86.h" +#include "Vif.h" +#include "VUmicro.h" + +#include + +extern VIFregisters *_vifRegs; +extern u32* _vifMaskRegs; +extern u32* _vifRow, _vifCol; + +// sse2 highly optimized vif (~200 separate functions are built) zerofrog(@gmail.com) +extern u32 g_vif1Masks[48], g_vif0Masks[48]; +extern u32 g_vif1HasMask3[4], g_vif0HasMask3[4]; + +//static const u32 writearr[4] = { 0xffffffff, 0, 0, 0 }; +//static const u32 rowarr[4] = { 0, 0xffffffff, 0, 0 }; +//static const u32 colarr[4] = { 0, 0, 0xffffffff, 0 }; +//static const u32 updatearr[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0 }; + +// arranged in writearr, rowarr, colarr, updatearr +static PCSX2_ALIGNED16(u32 s_maskarr[16][4]) = { + 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, + 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff, + 0xffff0000, 0x00000000, 0x0000ffff, 0xffffffff, + 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, + 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff, + 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, + 0x00000000, 0xffff0000, 0x00000000, 0xffff0000, + 0x0000ffff, 0x00000000, 0xffff0000, 0xffffffff, + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, + 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x00000000, 0x00000000, 0x0000ffff, + 0x00000000, 0x0000ffff, 0x00000000, 0x0000ffff, + 0x00000000, 0x00000000, 0x0000ffff, 0x0000ffff, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +extern u8 s_maskwrite[256]; +PCSX2_ALIGNED16(u32 s_TempDecompress[4]) = {0}; + +#if defined(_MSC_VER) // gcc functions can be found in iVif.S + +#include +#include + +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask) +{ + u32 i; + u32 prev = 0; + if( !cpucaps.hasStreamingSIMD2Extensions ) return; + FreezeXMMRegs(1); + + for(i = 0; i < 4; ++i, mask >>= 8, oldmask >>= 8, vif1masks += 16) { + + prev |= s_maskwrite[mask&0xff];//((mask&3)==3)||((mask&0xc)==0xc)||((mask&0x30)==0x30)||((mask&0xc0)==0xc0); + hasmask[i] = prev; + + if( (mask&0xff) != (oldmask&0xff) ) { + __m128i r0, r1, r2, r3; + r0 = _mm_load_si128((__m128i*)&s_maskarr[mask&15][0]); + r2 = _mm_unpackhi_epi16(r0, r0); + r0 = _mm_unpacklo_epi16(r0, r0); + + r1 = _mm_load_si128((__m128i*)&s_maskarr[(mask>>4)&15][0]); + r3 = _mm_unpackhi_epi16(r1, r1); + r1 = _mm_unpacklo_epi16(r1, r1); + + _mm_storel_pi((__m64*)&vif1masks[0], *(__m128*)&r0); + _mm_storel_pi((__m64*)&vif1masks[2], *(__m128*)&r1); + _mm_storeh_pi((__m64*)&vif1masks[4], *(__m128*)&r0); + _mm_storeh_pi((__m64*)&vif1masks[6], *(__m128*)&r1); + + _mm_storel_pi((__m64*)&vif1masks[8], *(__m128*)&r2); + _mm_storel_pi((__m64*)&vif1masks[10], *(__m128*)&r3); + _mm_storeh_pi((__m64*)&vif1masks[12], *(__m128*)&r2); + _mm_storeh_pi((__m64*)&vif1masks[14], *(__m128*)&r3); + } + } +} + +#else // gcc + +void SetNewMask(u32* vif1masks, u32* hasmask, u32 mask, u32 oldmask) +{ + u32 i; + u32 prev = 0; + if( !cpucaps.hasStreamingSIMD2Extensions ) return; + FreezeXMMRegs(1); + + for(i = 0; i < 4; ++i, mask >>= 8, oldmask >>= 8, vif1masks += 16) { + + prev |= s_maskwrite[mask&0xff];//((mask&3)==3)||((mask&0xc)==0xc)||((mask&0x30)==0x30)||((mask&0xc0)==0xc0); + hasmask[i] = prev; + + if( (mask&0xff) != (oldmask&0xff) ) { + u8* p0 = (u8*)&s_maskarr[mask&15][0]; + u8* p1 = (u8*)&s_maskarr[(mask>>4)&15][0]; + + __asm__(".intel_syntax\n" + "movaps %%xmm0, [%0]\n" + "movaps %%xmm1, [%1]\n" + "movaps %%xmm2, %%xmm0\n" + "punpcklwd %%xmm0, %%xmm0\n" + "punpckhwd %%xmm2, %%xmm2\n" + "movaps %%xmm3, %%xmm1\n" + "punpcklwd %%xmm1, %%xmm1\n" + "punpckhwd %%xmm3, %%xmm3\n" + "movq [%2], %%xmm0\n" + "movq [%2+8], %%xmm1\n" + "movhps [%2+16], %%xmm0\n" + "movhps [%2+24], %%xmm1\n" + "movq [%2+32], %%xmm2\n" + "movq [%2+40], %%xmm3\n" + "movhps [%2+48], %%xmm2\n" + "movhps [%2+56], %%xmm3\n" + ".att_syntax\n" : : "r"(p0), "r"(p1), "r"(vif1masks) ); + } + } +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ir5900tables.c b/pcsx2/x86/ir5900tables.c new file mode 100644 index 0000000..ef3ea93 --- /dev/null +++ b/pcsx2/x86/ir5900tables.c @@ -0,0 +1,1285 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Holds instruction tables for the r5900 recompiler + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" + +//////////////////////////////////////////////////// +static void recNULL( void ) +{ + SysPrintf("EE: Unimplemented op %x\n", cpuRegs.code); +} + +//////////////////////////////////////////////////// +static void recREGIMM( void ) +{ + recREG[ _Rt_ ]( ); +} + +//////////////////////////////////////////////////// +static void recSPECIAL( void ) +{ + recSPC[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0( void ) +{ + recCP0[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0BC0( void ) +{ + recCP0BC0[ ( cpuRegs.code >> 16 ) & 0x03 ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP0C0( void ) +{ + recCP0C0[ _Funct_ ]( ); +} + +//////////////////////////////////////////////////// +static void recCOP1( void ) { + recCP1[ _Rs_ ]( ); +} + +//////////////////////////////////////////////////// +static void recMMI( void ) +{ + recMMIt[ _Funct_ ]( ); +} + + +/********************************************************** +* UNHANDLED YET OPCODES +* +**********************************************************/ + +//////////////////////////////////////////////////// +//REC_SYS(PREF); +//////////////////////////////////////////////////// +//REC_SYS(MFSA); +//////////////////////////////////////////////////// +//REC_SYS(MTSA); +//////////////////////////////////////////////////// +REC_SYS(TGE); +//////////////////////////////////////////////////// +REC_SYS(TGEU); +//////////////////////////////////////////////////// +REC_SYS(TLT); +//////////////////////////////////////////////////// +REC_SYS(TLTU); +//////////////////////////////////////////////////// +REC_SYS(TEQ); +//////////////////////////////////////////////////// +REC_SYS(TNE); +//////////////////////////////////////////////////// +REC_SYS(TGEI); +//////////////////////////////////////////////////// +REC_SYS(TGEIU); +//////////////////////////////////////////////////// +REC_SYS(TLTI); +//////////////////////////////////////////////////// +REC_SYS(TLTIU); +//////////////////////////////////////////////////// +REC_SYS(TEQI); +//////////////////////////////////////////////////// +REC_SYS(TNEI); +//////////////////////////////////////////////////// +//REC_SYS(MTSAB); +//////////////////////////////////////////////////// +//REC_SYS(MTSAH); +//////////////////////////////////////////////////// +REC_SYS(CACHE); + +/* +void recTGE( void ) +{ +} + +void recTGEU( void ) +{ +} + +void recTLT( void ) +{ +} + +void recTLTU( void ) +{ +} + +void recTEQ( void ) +{ +} + +void recTNE( void ) +{ +} + +void recTGEI( void ) +{ +} + +void recTGEIU( void ) +{ +} + +void recTLTI( void ) +{ +} + +void recTLTIU( void ) +{ +} + +void recTEQI( void ) +{ +} + +void recTNEI( void ) +{ +} + +*/ + +///////////////////////////////// +// Foward-Prob Function Tables // +///////////////////////////////// +extern void recCOP2( void ); +extern void recSYSCALL( void ); +extern void recBREAK( void ); +extern void recPREF( void ); +extern void recSYNC( void ); +extern void recMFSA( void ); +extern void recMTSA( void ); +extern void recMTSAB( void ); +extern void recMTSAH( void ); + +void (*recBSC[64] )() = { + recSPECIAL, recREGIMM, recJ, recJAL, recBEQ, recBNE, recBLEZ, recBGTZ, + recADDI, recADDIU, recSLTI, recSLTIU, recANDI, recORI, recXORI, recLUI, + recCOP0, recCOP1, recCOP2, recNULL, recBEQL, recBNEL, recBLEZL, recBGTZL, + recDADDI, recDADDIU, recLDL, recLDR, recMMI, recNULL, recLQ, recSQ, + recLB, recLH, recLWL, recLW, recLBU, recLHU, recLWR, recLWU, + recSB, recSH, recSWL, recSW, recSDL, recSDR, recSWR, recCACHE, + recNULL, recLWC1, recNULL, recPREF, recNULL, recNULL, recLQC2, recLD, + recNULL, recSWC1, recNULL, recNULL, recNULL, recNULL, recSQC2, recSD +}; + +#ifdef PCSX2_VIRTUAL_MEM +// coissued insts +void (*recBSC_co[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recLDL_co, recLDR_co, recNULL, recNULL, recLQ_co, recSQ_co, + recLB_co, recLH_co, recLWL_co, recLW_co, recLBU_co, recLHU_co, recLWR_co, recLWU_co, + recSB_co, recSH_co, recSWL_co, recSW_co, recSDL_co, recSDR_co, recSWR_co, recNULL, + recNULL, recLWC1_co, recNULL, recNULL, recNULL, recNULL, recLQC2_co, recLD_co, + recNULL, recSWC1_co, recNULL, recNULL, recNULL, recNULL, recSQC2_co, recSD_co +}; +#endif + +void (*recSPC[64] )() = { + recSLL, recNULL, recSRL, recSRA, recSLLV, recNULL, recSRLV, recSRAV, + recJR, recJALR, recMOVZ, recMOVN, recSYSCALL, recBREAK, recNULL, recSYNC, + recMFHI, recMTHI, recMFLO, recMTLO, recDSLLV, recNULL, recDSRLV, recDSRAV, + recMULT, recMULTU, recDIV, recDIVU, recNULL, recNULL, recNULL, recNULL, + recADD, recADDU, recSUB, recSUBU, recAND, recOR, recXOR, recNOR, + recMFSA, recMTSA, recSLT, recSLTU, recDADD, recDADDU, recDSUB, recDSUBU, + recTGE, recTGEU, recTLT, recTLTU, recTEQ, recNULL, recTNE, recNULL, + recDSLL, recNULL, recDSRL, recDSRA, recDSLL32, recNULL, recDSRL32, recDSRA32 +}; + +void (*recREG[32] )() = { + recBLTZ, recBGEZ, recBLTZL, recBGEZL, recNULL, recNULL, recNULL, recNULL, + recTGEI, recTGEIU, recTLTI, recTLTIU, recTEQI, recNULL, recTNEI, recNULL, + recBLTZAL, recBGEZAL, recBLTZALL, recBGEZALL, recNULL, recNULL, recNULL, recNULL, + recMTSAB, recMTSAH, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0[32] )() = { + recMFC0, recNULL, recNULL, recNULL, recMTC0, recNULL, recNULL, recNULL, + recCOP0BC0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP0C0, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0BC0[32] )() = { + recBC0F, recBC0T, recBC0FL, recBC0TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP0C0[64] )() = { + recNULL, recTLBR, recTLBWI, recNULL, recNULL, recNULL, recTLBWR, recNULL, + recTLBP, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recERET, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recEI, recDI, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1[32] )() = { + recMFC1, recNULL, recCFC1, recNULL, recMTC1, recNULL, recCTC1, recNULL, + recCOP1_BC1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCOP1_S, recNULL, recNULL, recNULL, recCOP1_W, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1BC1[32] )() = { + recBC1F, recBC1T, recBC1FL, recBC1TL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1S[64] )() = { + recADD_S, recSUB_S, recMUL_S, recDIV_S, recSQRT_S, recABS_S, recMOV_S, recNEG_S, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recRSQRT_S, recNULL, + recADDA_S, recSUBA_S, recMULA_S, recNULL, recMADD_S, recMSUB_S, recMADDA_S, recMSUBA_S, + recNULL, recNULL, recNULL, recNULL, recCVT_W, recNULL, recNULL, recNULL, + recMAX_S, recMIN_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recC_F, recNULL, recC_EQ, recNULL, recC_LT, recNULL, recC_LE, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recCP1W[64] )() = { + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recCVT_S, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMIt[64] )() = { + recMADD, recMADDU, recNULL, recNULL, recPLZCW, recNULL, recNULL, recNULL, + recMMI0, recMMI2, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMFHI1, recMTHI1, recMFLO1, recMTLO1, recNULL, recNULL, recNULL, recNULL, + recMULT1, recMULTU1, recDIV1, recDIVU1, recNULL, recNULL, recNULL, recNULL, + recMADD1, recMADDU1, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recMMI1 , recMMI3, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, + recPMFHL, recPMTHL, recNULL, recNULL, recPSLLH, recNULL, recPSRLH, recPSRAH, + recNULL, recNULL, recNULL, recNULL, recPSLLW, recNULL, recPSRLW, recPSRAW, +}; + +void (*recMMI0t[32] )() = { + recPADDW, recPSUBW, recPCGTW, recPMAXW, + recPADDH, recPSUBH, recPCGTH, recPMAXH, + recPADDB, recPSUBB, recPCGTB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDSW, recPSUBSW, recPEXTLW, recPPACW, + recPADDSH, recPSUBSH, recPEXTLH, recPPACH, + recPADDSB, recPSUBSB, recPEXTLB, recPPACB, + recNULL, recNULL, recPEXT5, recPPAC5, +}; + +void (*recMMI1t[32] )() = { + recNULL, recPABSW, recPCEQW, recPMINW, + recPADSBH, recPABSH, recPCEQH, recPMINH, + recNULL, recNULL, recPCEQB, recNULL, + recNULL, recNULL, recNULL, recNULL, + recPADDUW, recPSUBUW, recPEXTUW, recNULL, + recPADDUH, recPSUBUH, recPEXTUH, recNULL, + recPADDUB, recPSUBUB, recPEXTUB, recQFSRV, + recNULL, recNULL, recNULL, recNULL, +}; + +void (*recMMI2t[32] )() = { + recPMADDW, recNULL, recPSLLVW, recPSRLVW, + recPMSUBW, recNULL, recNULL, recNULL, + recPMFHI, recPMFLO, recPINTH, recNULL, + recPMULTW, recPDIVW, recPCPYLD, recNULL, + recPMADDH, recPHMADH, recPAND, recPXOR, + recPMSUBH, recPHMSBH, recNULL, recNULL, + recNULL, recNULL, recPEXEH, recPREVH, + recPMULTH, recPDIVBW, recPEXEW, recPROT3W, +}; + +void (*recMMI3t[32] )() = { + recPMADDUW, recNULL, recNULL, recPSRAVW, + recNULL, recNULL, recNULL, recNULL, + recPMTHI, recPMTLO, recPINTEH, recNULL, + recPMULTUW, recPDIVUW, recPCPYUD, recNULL, + recNULL, recNULL, recPOR, recPNOR, + recNULL, recNULL, recNULL, recNULL, + recNULL, recNULL, recPEXCH, recPCPYH, + recNULL, recNULL, recPEXCW, recNULL, +}; + +//////////////////////////////////////////////// +// Back-Prob Function Tables - Gathering Info // +//////////////////////////////////////////////// +#define rpropSetRead(reg, mask) { \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + prev->regs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->regs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 0); \ +} \ + +#define rpropSetWrite0(reg, mask, live) { \ + prev->regs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->regs[reg] & EEINST_USED) ) \ + pinst->regs[reg] |= EEINST_LASTUSE; \ + pinst->regs[reg] |= EEINST_USED; \ + prev->regs[reg] |= EEINST_USED; \ + _recFillRegister(pinst, XMMTYPE_GPRREG, reg, 1); \ +} + +#define rpropSetWrite(reg, mask) { \ + rpropSetWrite0(reg, mask, EEINST_LIVE0); \ +} \ + +#define rpropSetFast(write1, read1, read2, mask) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ +} \ + +#define rpropSetLOHI(write1, read1, read2, mask, lo, hi) { \ + if( write1 ) { rpropSetWrite(write1, mask); } \ + if( (lo) & MODE_WRITE ) { rpropSetWrite(XMMGPR_LO, mask); } \ + if( (hi) & MODE_WRITE ) { rpropSetWrite(XMMGPR_HI, mask); } \ + if( read1 ) { rpropSetRead(read1, mask); } \ + if( read2 ) { rpropSetRead(read2, mask); } \ + if( (lo) & MODE_READ ) { rpropSetRead(XMMGPR_LO, mask); } \ + if( (hi) & MODE_READ ) { rpropSetRead(XMMGPR_HI, mask); } \ +} \ + +// FPU regs +#define rpropSetFPURead(reg, mask) { \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + prev->fpuregs[reg] |= EEINST_LIVE0|(mask)|EEINST_USED; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + if( reg ) pinst->info = ((mask)&(EEINST_MMX|EEINST_XMM)); \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 0); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 0); \ +} \ + +#define rpropSetFPUWrite0(reg, mask, live) { \ + prev->fpuregs[reg] &= ~((mask)|live|EEINST_XMM|EEINST_MMX); \ + if( !(pinst->fpuregs[reg] & EEINST_USED) ) \ + pinst->fpuregs[reg] |= EEINST_LASTUSE; \ + pinst->fpuregs[reg] |= EEINST_USED; \ + prev->fpuregs[reg] |= EEINST_USED; \ + if( reg == XMMFPU_ACC ) _recFillRegister(pinst, XMMTYPE_FPACC, 0, 1); \ + else _recFillRegister(pinst, XMMTYPE_FPREG, reg, 1); \ +} + +#define rpropSetFPUWrite(reg, mask) { \ + rpropSetFPUWrite0(reg, mask, EEINST_LIVE0); \ +} \ + + +void rpropBSC(EEINST* prev, EEINST* pinst); +void rpropSPECIAL(EEINST* prev, EEINST* pinst); +void rpropREGIMM(EEINST* prev, EEINST* pinst); +void rpropCP0(EEINST* prev, EEINST* pinst); +void rpropCP1(EEINST* prev, EEINST* pinst); +void rpropCP2(EEINST* prev, EEINST* pinst); +void rpropMMI(EEINST* prev, EEINST* pinst); +void rpropMMI0(EEINST* prev, EEINST* pinst); +void rpropMMI1(EEINST* prev, EEINST* pinst); +void rpropMMI2(EEINST* prev, EEINST* pinst); +void rpropMMI3(EEINST* prev, EEINST* pinst); + +#define EEINST_REALXMM (cpucaps.hasStreamingSIMDExtensions?EEINST_XMM:0) + +//SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, +//ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, +//COP0, COP1, COP2, NULL, BEQL, BNEL, BLEZL, BGTZL, +//DADDI, DADDIU, LDL, LDR, MMI, NULL, LQ, SQ, +//LB, LH, LWL, LW, LBU, LHU, LWR, LWU, +//SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, +//NULL, LWC1, NULL, PREF, NULL, NULL, LQC2, LD, +//NULL, SWC1, NULL, NULL, NULL, NULL, SQC2, SD +void rpropBSC(EEINST* prev, EEINST* pinst) +{ + switch(cpuRegs.code >> 26) { + case 0: rpropSPECIAL(prev, pinst); break; + case 1: rpropREGIMM(prev, pinst); break; + case 2: // j + break; + case 3: // jal + rpropSetWrite(31, EEINST_LIVE1); + break; + case 4: // beq + case 5: // bne + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0); + break; + + case 20: // beql + case 21: // bnel + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= (cpucaps.hasStreamingSIMD2Extensions?(EEINST_REALXMM|EEINST_MMX):0); + break; + + case 6: // blez + case 7: // bgtz + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 22: // blezl + case 23: // bgtzl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // daddi + case 25: // daddiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|((_Rs_!=0&&cpucaps.hasStreamingSIMD2Extensions)?EEINST_MMX:0)); + break; + + case 8: // addi + case 9: // addiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + break; + + case 10: // slti + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + case 11: // sltiu + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 12: // andi + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, (_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 13: // ori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + case 14: // xori + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=_Rt_?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 15: // lui + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 16: rpropCP0(prev, pinst); break; + case 17: rpropCP1(prev, pinst); break; + case 18: rpropCP2(prev, pinst); break; + + // loads + case 34: // lwl + case 38: // lwr + case 26: // ldl + case 27: // ldr + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 28: rpropMMI(prev, pinst); break; + + case 30: // lq + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 31: // sq + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + // 4 byte stores + case 40: case 41: case 42: case 43: case 46: + rpropSetRead(_Rt_, 0); + rpropSetRead(_Rs_, 0); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 44: // sdl + case 45: // sdr + case 63: // sd + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX|EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 49: // lwc1 + rpropSetFPUWrite(_Rt_, EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 57: // swc1 + rpropSetFPURead(_Rt_, EEINST_REALXMM); + rpropSetRead(_Rs_, 0); + break; + + case 54: // lqc2 + case 62: // sqc2 + rpropSetRead(_Rs_, 0); + break; + + default: + rpropSetWrite(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|(_Rs_!=0?EEINST_MMX:0)); + break; + } +} + +//SLL, NULL, SRL, SRA, SLLV, NULL, SRLV, SRAV, +//JR, JALR, MOVZ, MOVN, SYSCALL, BREAK, NULL, SYNC, +//MFHI, MTHI, MFLO, MTLO, DSLLV, NULL, DSRLV, DSRAV, +//MULT, MULTU, DIV, DIVU, NULL, NULL, NULL, NULL, +//ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, +//MFSA, MTSA, SLT, SLTU, DADD, DADDU, DSUB, DSUBU, +//TGE, TGEU, TLT, TLTU, TEQ, NULL, TNE, NULL, +//DSLL, NULL, DSRL, DSRA, DSLL32, NULL, DSRL32, DSRA32 +void rpropSPECIAL(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(_Funct_) { + case 0: // SLL + case 2: // SRL + case 3: // SRA + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 4: // sllv + case 6: // srlv + case 7: // srav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_MMX); + break; + + case 8: // JR + rpropSetRead(_Rs_, 0); + break; + case 9: // JALR + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + break; + + case 10: // movz + case 11: // movn + // do not write _Rd_! + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + rpropSetRead(_Rd_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + _recFillRegister(pinst, XMMTYPE_GPRREG, _Rd_, 1); + break; + + case 12: // syscall + case 13: // break + _recClearInst(prev); + prev->info = 0; + break; + case 15: // sync + break; + + case 16: // mfhi + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_REALXMM)|EEINST_LIVE1); + break; + case 17: // mthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, (pinst->regs[_Rd_]&EEINST_MMX|EEINST_REALXMM)|EEINST_LIVE1); + break; + case 19: // mtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 20: // dsllv + case 22: // dsrlv + case 23: // dsrav + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + + case 24: // mult + // can do unsigned mult only if HI isn't used + //temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE0|EEINST_LIVE1))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + temp = 0; + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + case 26: // div + case 27: // divu + rpropSetWrite(XMMGPR_LO, EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE1); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_REALXMM|EEINST_MMX; + break; + + case 32: // add + case 33: // addu + case 34: // sub + case 35: // subu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ ) rpropSetRead(_Rs_, 0); + if( _Rt_ ) rpropSetRead(_Rt_, 0); + pinst->info |= EEINST_MMX; + break; + + case 36: // and + case 37: // or + case 38: // xor + case 39: // nor + // if rd == rs or rt, keep live1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|EEINST_MMX); + break; + + case 40: // mfsa + rpropSetWrite(_Rd_, EEINST_LIVE1); + break; + case 41: // mtsa + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + break; + + case 42: // slt + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 43: // sltu + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + break; + + case 44: // dadd + case 45: // daddu + case 46: // dsub + case 47: // dsubu + rpropSetWrite(_Rd_, EEINST_LIVE1); + if( _Rs_ == 0 || _Rt_ == 0 ) { + // just a copy, so don't force mmx + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)); + } + else { + rpropSetRead(_Rs_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (pinst->regs[_Rd_]&EEINST_LIVE1)|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + } + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + // traps + case 48: case 49: case 50: case 51: case 52: case 54: + rpropSetRead(_Rs_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1); + break; + + case 56: // dsll + case 58: // dsrl + case 59: // dsra + case 62: // dsrl32 + case 63: // dsra32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE1|(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + case 60: // dsll32 + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + pinst->info |= EEINST_MMX; + break; + + default: + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_MMX); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_MMX); + break; + } +} + +//BLTZ, BGEZ, BLTZL, BGEZL, NULL, NULL, NULL, NULL, +//TGEI, TGEIU, TLTI, TLTIU, TEQI, NULL, TNEI, NULL, +//BLTZAL, BGEZAL, BLTZALL, BGEZALL, NULL, NULL, NULL, NULL, +//MTSAB, MTSAH, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropREGIMM(EEINST* prev, EEINST* pinst) +{ + switch(_Rt_) { + case 0: // bltz + case 1: // bgez + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + case 2: // bltzl + case 3: // bgezl + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + rpropSetRead(_Rs_, EEINST_LIVE1); + pinst->info |= EEINST_MMX; + pinst->info |= EEINST_REALXMM; + break; + + // traps + case 8: + case 9: + case 10: + case 11: + case 12: + case 14: + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 16: // bltzal + case 17: // bgezal + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 18: // bltzall + case 19: // bgezall + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + // do not write 31 + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mtsab + case 25: // mtsah + rpropSetRead(_Rs_, 0); + break; + default: + assert(0); + break; + } +} + +//MFC0, NULL, NULL, NULL, MTC0, NULL, NULL, NULL, +//COP0BC0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//COP0C0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP0(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc0 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 4: + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 8: // cop0bc0 + _recClearInst(prev); + prev->info = 0; + break; + case 16: // cop0c0 + _recClearInst(prev); + prev->info = 0; + break; + } +} + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +//ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, RSQRT_S, NULL, +//ADDA_S, SUBA_S, MULA_S, NULL, MADD_S, MSUB_S, MADDA_S, MSUBA_S, +//NULL, NULL, NULL, NULL, CVT_W, NULL, NULL, NULL, +//MAX_S, MIN_S, NULL, NULL, NULL, NULL, NULL, NULL, +//C_F, NULL, C_EQ, NULL, C_LT, NULL, C_LE, NULL, +//NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +void rpropCP1(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 0: // mfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + case 2: // cfc1 + rpropSetWrite(_Rt_, EEINST_LIVE1|EEINST_REALXMM|EEINST_MMX); + break; + case 4: // mtc1 + rpropSetFPUWrite(_Fs_, EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 6: // ctc1 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM|EEINST_MMX); + break; + case 8: // bc1 + // reset since don't know which path to go + _recClearInst(prev); + prev->info = 0; + break; + case 16: + // floating point ops + pinst->info |= EEINST_REALXMM; + switch( _Funct_ ) { + case 0: // add.s + case 1: // sub.s + case 2: // mul.s + case 3: // div.s + case 22: // rsqrt.s + case 40: // max.s + case 41: // min.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 4: // sqrt.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 5: // abs.s + case 6: // mov.s + case 7: // neg.s + case 36: // cvt.w + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + case 24: // adda.s + case 25: // suba.s + case 26: // mula.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + case 28: // madd.s + case 29: // msub.s + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + + case 30: // madda.s + case 31: // msuba.s + rpropSetFPUWrite(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(XMMFPU_ACC, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + + case 48: // c.f + case 50: // c.eq + case 52: // c.lt + case 54: // c.le + rpropSetFPURead(_Fs_, EEINST_REALXMM); + rpropSetFPURead(_Ft_, EEINST_REALXMM); + break; + default: assert(0); + } + break; + case 20: + assert( _Funct_ == 32 ); // CVT.S.W + rpropSetFPUWrite(_Fd_, EEINST_REALXMM); + rpropSetFPURead(_Fs_, EEINST_REALXMM); + break; + default: + assert(0); + } +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +void rpropCP2(EEINST* prev, EEINST* pinst) +{ + switch(_Rs_) { + case 1: // qmfc2 + rpropSetWrite(_Rt_, EEINST_LIVE2|EEINST_LIVE1); + break; + + case 2: // cfc2 + rpropSetWrite(_Rt_, EEINST_LIVE1); + break; + + case 5: // qmtc2 + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 6: // ctc2 + rpropSetRead(_Rt_, 0); + break; + + case 8: // bc2 + break; + + default: + // vu macro mode insts + pinst->info |= 2; + break; + } +} + +//MADD, MADDU, NULL, NULL, PLZCW, NULL, NULL, NULL, +//MMI0, MMI2, NULL, NULL, NULL, NULL, NULL, NULL, +//MFHI1, MTHI1, MFLO1, MTLO1, NULL, NULL, NULL, NULL, +//MULT1, MULTU1, DIV1, DIVU1, NULL, NULL, NULL, NULL, +//MADD1, MADDU1, NULL, NULL, NULL, NULL, NULL, NULL, +//MMI1 , MMI3, NULL, NULL, NULL, NULL, NULL, NULL, +//PMFHL, PMTHL, NULL, NULL, PSLLH, NULL, PSRLH, PSRAH, +//NULL, NULL, NULL, NULL, PSLLW, NULL, PSRLW, PSRAW, +void rpropMMI(EEINST* prev, EEINST* pinst) +{ + int temp; + switch(cpuRegs.code&0x3f) { + case 0: // madd + case 1: // maddu + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 4: // plzcw + rpropSetFast(_Rd_, _Rs_, 0, EEINST_LIVE1); + break; + case 8: rpropMMI0(prev, pinst); break; + case 9: rpropMMI2(prev, pinst); break; + + case 16: // mfhi1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM); + rpropSetRead(XMMGPR_HI, temp|EEINST_LIVE2); + break; + case 17: // mthi1 + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + case 18: // mflo1 + rpropSetWrite(_Rd_, EEINST_LIVE1); + temp = ((pinst->regs[_Rd_]&(EEINST_MMX|EEINST_REALXMM))?EEINST_MMX:EEINST_REALXMM); + rpropSetRead(XMMGPR_LO, temp|EEINST_LIVE2); + break; + case 19: // mtlo1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, EEINST_LIVE1); + break; + + case 24: // mult1 + temp = (pinst->regs[XMMGPR_HI]&(EEINST_LIVE2))?0:(cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0); + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, temp); + rpropSetRead(_Rt_, temp); + pinst->info |= temp; + break; + case 25: // multu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetWrite(_Rd_, EEINST_LIVE1); + rpropSetRead(_Rs_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + rpropSetRead(_Rt_, (cpucaps.hasStreamingSIMD2Extensions?EEINST_MMX:0)); + if( cpucaps.hasStreamingSIMD2Extensions ) pinst->info |= EEINST_MMX; + break; + + case 26: // div1 + case 27: // divu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetRead(_Rs_, 0); + rpropSetRead(_Rt_, 0); + //pinst->info |= EEINST_REALXMM|EEINST_MMX; + break; + + case 32: // madd1 + case 33: // maddu1 + rpropSetWrite0(XMMGPR_LO, EEINST_LIVE2, 0); + rpropSetWrite0(XMMGPR_HI, EEINST_LIVE2, 0); + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2); + break; + + case 40: rpropMMI1(prev, pinst); break; + case 41: rpropMMI3(prev, pinst); break; + + case 48: // pmfhl + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 49: // pmthl + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +//recPADDW, PSUBW, PCGTW, PMAXW, +//PADDH, PSUBH, PCGTH, PMAXH, +//PADDB, PSUBB, PCGTB, NULL, +//NULL, NULL, NULL, NULL, +//PADDSW, PSUBSW, PEXTLW, PPACW, +//PADDSH, PSUBSH, PEXTLH, PPACH, +//PADDSB, PSUBSB, PEXTLB, PPACB, +//NULL, NULL, PEXT5, PPAC5, +void rpropMMI0(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 16: // paddsw + case 17: // psubsw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextlw + case 22: // pextlh + case 26: // pextlb + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + + case 30: // pext5 + case 31: // ppac5 + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI1(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 1: // pabsw + case 5: // pabsh + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 17: // psubuw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2); + break; + + case 18: // pextuw + case 22: // pextuh + case 26: // pextub + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI2(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmaddw + case 4: // pmsubw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 2: // psllvw + case 3: // psllvw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + case 8: // pmfhi + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 9: // pmflo + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 10: // pinth + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 12: // pmultw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyld + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE1|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE1|EEINST_REALXMM); + break; + case 16: // pmaddh + case 17: // phmadh + case 20: // pmsubh + case 21: // phmsbh + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + + case 26: // pexeh + case 27: // prevh + case 30: // pexew + case 31: // prot3w + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + case 28: // pmulth + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE); + break; + case 29: // pdivbw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +void rpropMMI3(EEINST* prev, EEINST* pinst) +{ + switch((cpuRegs.code>>6)&0x1f) { + case 0: // pmadduw + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_READ|MODE_WRITE, MODE_READ|MODE_WRITE); + break; + case 3: // psravw + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE2); + break; + + case 8: // pmthi + rpropSetWrite(XMMGPR_HI, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 9: // pmtlo + rpropSetWrite(XMMGPR_LO, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + case 12: // pmultuw, + rpropSetLOHI(_Rd_, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM, MODE_WRITE, MODE_WRITE); + break; + case 13: // pdivuw + rpropSetLOHI(0, _Rs_, _Rt_, EEINST_LIVE2|EEINST_LIVE1, MODE_WRITE, MODE_WRITE); + break; + case 14: // pcpyud + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rs_, EEINST_LIVE2|EEINST_REALXMM); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_REALXMM); + break; + + case 26: // pexch + case 27: // pcpyh + case 30: // pexcw + rpropSetWrite(_Rd_, EEINST_LIVE2|EEINST_LIVE1); + rpropSetRead(_Rt_, EEINST_LIVE2|EEINST_LIVE1|EEINST_REALXMM); + break; + + default: + rpropSetFast(_Rd_, _Rs_, _Rt_, EEINST_LIVE1|EEINST_LIVE2|EEINST_REALXMM); + break; + } +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/aR5900-32.S b/pcsx2/x86/ix86-32/aR5900-32.S new file mode 100644 index 0000000..a13737b --- /dev/null +++ b/pcsx2/x86/ix86-32/aR5900-32.S @@ -0,0 +1,216 @@ +// iR5900.c assembly routines +// zerofrog(@gmail.com) +.intel_syntax + +.extern cpuRegs +.extern recRecompile +//.extern recLUT +.extern lbase +.extern s_pCurBlock_ltime + +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +#define BASEBLOCK_SIZE 2 // in dwords +#define PCOFFSET 0x2a8 + +#define REG_PC %ecx +#define REG_BLOCK %esi + +.globl Dispatcher + .type Dispatcher, @function +Dispatcher: + # EDX contains the jump addr to modify + push %edx + + # calc PC_GETBLOCK + # ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [cpuRegs + PCOFFSET] + mov REG_BLOCK, %eax + mov REG_PC, %eax + shr %eax, 16 + and REG_BLOCK, 0xffff + shl %eax, 2 + add %eax, dword ptr [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, dword ptr [%eax] + + // check if startpc == cpuRegs.pc + //and %ecx, 0x5fffffff // remove higher bits + cmp REG_PC, dword ptr [REG_BLOCK+BLOCKTYPE_STARTPC] + je Dispatcher_CheckPtr + + // recompile + push REG_BLOCK + push REG_PC // pc + call recRecompile + add %esp, 4 // pop old param + pop REG_BLOCK +Dispatcher_CheckPtr: + mov REG_BLOCK, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test REG_BLOCK, REG_BLOCK + jnz Dispatcher_CallFn + // throw an exception + int 10 + +Dispatcher_CallFn: +#endif + + and REG_BLOCK, 0x0fffffff + mov %edx, REG_BLOCK + pop %ecx // x86Ptr to mod + sub %edx, %ecx + sub %edx, 4 + mov dword ptr [%ecx], %edx + + jmp REG_BLOCK + +.globl DispatcherClear + .type DispatcherClear, @function +DispatcherClear: + // EDX contains the current pc + mov dword ptr [cpuRegs + PCOFFSET], %edx + + // calc PC_GETBLOCK + # ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, %edx + mov REG_BLOCK, %edx + shr %eax, 16 + and REG_BLOCK, 0xffff + shl %eax, 2 + add %eax, dword ptr [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, dword ptr [%eax] + + cmp %edx, dword ptr [REG_BLOCK + 4] + jne DispatcherClear_Recompile + + add %esp, 4 // ignore stack + mov %eax, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test %eax, %eax + jnz DispatcherClear_CallFn + # throw an exception + int 10 + +DispatcherClear_CallFn: +#endif + + and %eax, 0x0fffffff + jmp %eax + +DispatcherClear_Recompile: + push REG_BLOCK + push %edx + call recRecompile + add %esp, 4 // pop old param + pop REG_BLOCK + mov %eax, dword ptr [REG_BLOCK] + + pop %ecx // old fnptr + + and %eax, 0x0fffffff + mov byte ptr [%ecx], 0xe9 // jmp32 + mov %edx, %eax + sub %edx, %ecx + sub %edx, 5 + mov dword ptr [%ecx+1], %edx + + jmp %eax + + +// called when jumping to variable pc address +.globl DispatcherReg + .type DispatcherReg, @function +DispatcherReg: + + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov %edx, dword ptr [cpuRegs+PCOFFSET] + mov %ecx, %edx + + shr %edx, 14 + and %edx, 0xfffffffc + add %edx, [recLUT] + mov %edx, dword ptr [%edx] + + mov %eax, %ecx + and %eax, 0xfffc + // %edx += 2*%eax + shl %eax, 1 + add %edx, %eax + + // check if startpc == cpuRegs.pc + mov %eax, %ecx + //and %eax, 0x5fffffff // remove higher bits + cmp %eax, dword ptr [%edx+BLOCKTYPE_STARTPC] + jne DispatcherReg_recomp + + mov %eax, dword ptr [%edx] + +#ifdef _DEBUG + test %eax, %eax + jnz CallFn2 + # throw an exception + int 10 + +CallFn2: + +#endif + + and %eax, 0x0fffffff + jmp %eax // fnptr + +DispatcherReg_recomp: + sub %esp, 8 + mov dword ptr [%esp+4], %edx + mov dword ptr [%esp], %ecx + call recRecompile + mov %edx, dword ptr [%esp+4] + add %esp, 8 + + mov %eax, dword ptr [%edx] + and %eax, 0x0fffffff + jmp %eax // fnptr + + +.globl _StartPerfCounter + .type _StartPerfCounter, @function +_StartPerfCounter: + + push %eax + push %ebx + push %ecx + + rdtsc + mov dword ptr [lbase], %eax + mov dword ptr [lbase + 4], %edx + + pop %ecx + pop %ebx + pop %eax + ret + +.globl _StopPerfCounter + .type _StopPerfCounter, @function +_StopPerfCounter: + + push %eax + push %ebx + push %ecx + + rdtsc + + sub %eax, dword ptr [lbase] + sbb %edx, dword ptr [lbase + 4] + mov %ecx, s_pCurBlock_ltime + add %eax, dword ptr [%ecx] + adc %edx, dword ptr [%ecx + 4] + mov dword ptr [%ecx], %eax + mov dword ptr [%ecx + 4], %edx + pop %ecx + pop %ebx + pop %eax + ret diff --git a/pcsx2/x86/ix86-32/aVif_proc-32.asm b/pcsx2/x86/ix86-32/aVif_proc-32.asm new file mode 100644 index 0000000..7d86b02 --- /dev/null +++ b/pcsx2/x86/ix86-32/aVif_proc-32.asm @@ -0,0 +1,1800 @@ + +.686 +.model flat, c +.mmx +.xmm + + +extern _vifRegs:ptr +extern _vifMaskRegs:ptr +extern _vifRow:ptr +extern s_TempDecompress:ptr + + +.code + +UNPACK_Write0_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [edi+DEST_OFFSET], r0 + endm + +UNPACK_Write1_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [edi], r0 + add edi, ecx + endm + +UNPACK_Write0_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write0_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + +UNPACK_Write1_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write1_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + + +UNPACK_Write0_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + + movdqa xmm3, [eax + 64*(CL) + 48] + pand r0, xmm3 + pandn xmm3, [edi] + por r0, xmm3 + MOVDQA [edi], r0 + add edi, 16 + endm + + +UNPACK_Write1_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + + movdqa xmm3, [eax + 64*(0) + 48] + pand r0, xmm3 + pandn xmm3, [edi] + por r0, xmm3 + MOVDQA [edi], r0 + add edi, ecx + endm + +UNPACK_Mask_SSE_0 macro r0 + pand r0, xmm3 + por r0, xmm5 + endm + + + + +UNPACK_Mask_SSE_1 macro r0 + + pand r0, xmm3 + por r0, xmm5 + pand xmm3, xmm6 + paddd r0, xmm3 + endm + + + +UNPACK_Mask_SSE_2 macro r0 + + + pand r0, xmm3 + pand xmm3, xmm6 + paddd xmm6, r0 + por r0, xmm5 + paddd r0, xmm3 + endm + +UNPACK_WriteMask_SSE_0 macro r0 + UNPACK_Mask_SSE_0 r0 + endm +UNPACK_WriteMask_SSE_1 macro r0 + UNPACK_Mask_SSE_1 r0 + endm +UNPACK_WriteMask_SSE_2 macro r0 + UNPACK_Mask_SSE_2 r0 + endm + +UNPACK_Regular_SSE_0 macro r0 + endm + +UNPACK_Regular_SSE_1 macro r0 + paddd r0, xmm6 + endm + +UNPACK_Regular_SSE_2 macro r0 + paddd r0, xmm6 + movdqa xmm6, r0 + endm + + +UNPACK_Setup_Mask_SSE macro CL + mov eax, [_vifMaskRegs] + movdqa xmm4, [eax + 64*(CL) + 16] + movdqa xmm5, [eax + 64*(CL) + 32] + movdqa xmm3, [eax + 64*(CL)] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Start_Setup_Mask_SSE_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + +UNPACK_Start_Setup_Mask_SSE_1 macro CL + mov eax, [_vifMaskRegs] + movdqa xmm4, [eax + 64*(CL) + 16] + movdqa xmm5, [eax + 64*(CL) + 32] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Start_Setup_Mask_SSE_2 macro CL + endm + +UNPACK_Setup_Mask_SSE_0_1 macro CL + endm +UNPACK_Setup_Mask_SSE_1_1 macro CL + mov eax, [_vifMaskRegs] + movdqa xmm3, [eax + 64*(0)] + endm + + +UNPACK_Setup_Mask_SSE_2_1 macro CL + + mov eax, [_vifMaskRegs] + movdqa xmm4, [eax + 64*(0) + 16] + movdqa xmm5, [eax + 64*(0) + 32] + movdqa xmm3, [eax + 64*(0)] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Setup_Mask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + + +UNPACK_Setup_WriteMask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_0_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_1_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_2_1 macro CL + UNPACK_Setup_Mask_SSE_2_1 CL + endm + +UNPACK_Start_Setup_WriteMask_SSE_0 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_1 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_2 macro CL + UNPACK_Start_Setup_Mask_SSE_2 CL + endm + +UNPACK_Start_Setup_Regular_SSE_0 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_1 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_2 macro CL + endm +UNPACK_Setup_Regular_SSE_0_0 macro CL + endm +UNPACK_Setup_Regular_SSE_1_0 macro CL + endm +UNPACK_Setup_Regular_SSE_2_0 macro CL + endm +UNPACK_Setup_Regular_SSE_0_1 macro CL + endm +UNPACK_Setup_Regular_SSE_1_1 macro CL + endm +UNPACK_Setup_Regular_SSE_2_1 macro CL + endm + +UNPACK_INC_DST_0_Regular macro qw + add edi, (16*qw) + endm +UNPACK_INC_DST_1_Regular macro qw + endm +UNPACK_INC_DST_0_Mask macro qw + add edi, (16*qw) + endm +UNPACK_INC_DST_1_Mask macro qw + endm +UNPACK_INC_DST_0_WriteMask macro qw + endm +UNPACK_INC_DST_1_WriteMask macro qw + endm + + +UNPACK4_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm7 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm7, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + endm + + +UNPACK3_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + endm + +UNPACK2_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 2 + endm + +UNPACK1_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 1 + endm + + + +UNPACK_S_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm7, [esi] + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_S_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm2, [esi] + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_S_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm1, QWORD PTR [esi] + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_S_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_S_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_S_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm7, QWORD PTR [esi] + punpcklwd xmm7, xmm7 + UNPACK_RIGHTSHIFT xmm7, 16 + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_S_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm2, QWORD PTR [esi] + punpcklwd xmm2, xmm2 + UNPACK_RIGHTSHIFT xmm2, 16 + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + add esi, 6 + endm + +UNPACK_S_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm1, dword ptr [esi] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm1, 16 + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_S_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 2 + endm + +UNPACK_S_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_S_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movd xmm7, dword ptr [esi] + punpcklbw xmm7, xmm7 + punpcklwd xmm7, xmm7 + UNPACK_RIGHTSHIFT xmm7, 24 + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_S_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd xmm2, dword ptr [esi] + punpcklbw xmm2, xmm2 + punpcklwd xmm2, xmm2 + UNPACK_RIGHTSHIFT xmm2, 24 + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 3 + endm + +UNPACK_S_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm1, dword ptr [esi] + punpcklbw xmm1, xmm1 + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm1, 24 + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 2 + endm + +UNPACK_S_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + inc esi + endm + +UNPACK_S_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V2_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + MOVDQA xmm0, [esi] + MOVDQA xmm2, [esi+16] + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V2_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+8] + movq xmm2, QWORD PTR [esi+16] + movq xmm7, QWORD PTR [esi+24] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V2_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + MOVDQA xmm0, [esi] + movq xmm2, QWORD PTR [esi+16] + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V2_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+8] + movq xmm2, QWORD PTR [esi+16] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V2_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+8] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V2_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V2_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V2_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + punpckhwd xmm2, [esi] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + add esi, 16 + endm + +UNPACK_V2_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V2_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + punpckhwd xmm2, [esi] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V2_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V2_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + UNPACK_RIGHTSHIFT xmm0, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V2_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V2_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_V2_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + + +UNPACK_V2_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + + punpcklbw xmm0, xmm0 + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V2_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + + punpcklbw xmm0, xmm0 + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 6 + endm + +UNPACK_V2_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_V2_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 2 + endm + +UNPACK_V2_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V3_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [esi] + movdqu xmm1, [esi+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + + MOVDQA xmm7, [esi+32] + movdqu xmm2, [esi+24] + psrldq xmm7, 4 + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm7 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm7, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + + add esi, 48 + endm + +UNPACK_V3_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [esi] + movdqu xmm1, [esi+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + movdqu xmm2, [esi+24] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + + add esi, 36 + endm + +UNPACK_V3_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_2x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [esi] + movdqu xmm1, [esi+12] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V3_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_1x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [esi] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V3_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqu + endm + + +UNPACK_V3_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+6] + + punpcklwd xmm0, xmm0 + movq xmm2, QWORD PTR [esi+12] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 16 + movq xmm7, QWORD PTR [esi+18] + UNPACK_RIGHTSHIFT xmm1, 16 + punpcklwd xmm2, xmm2 + punpcklwd xmm7, xmm7 + + UNPACK_RIGHTSHIFT xmm2, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V3_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+6] + + punpcklwd xmm0, xmm0 + movq xmm2, QWORD PTR [esi+12] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 16 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 18 + endm + +UNPACK_V3_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+6] + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V3_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 6 + endm + +UNPACK_V3_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V3_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm1, QWORD PTR [esi] + movq xmm7, QWORD PTR [esi+6] + + punpcklbw xmm1, xmm1 + punpcklbw xmm7, xmm7 + punpcklwd xmm0, xmm1 + psrldq xmm1, 6 + punpcklwd xmm2, xmm7 + psrldq xmm7, 6 + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 24 + punpcklwd xmm7, xmm7 + + UNPACK_RIGHTSHIFT xmm2, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm7, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V3_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + movd xmm1, dword ptr [esi+3] + + punpcklbw xmm0, xmm0 + movd xmm2, dword ptr [esi+6] + punpcklbw xmm1, xmm1 + punpcklwd xmm0, xmm0 + punpcklbw xmm2, xmm2 + + punpcklwd xmm1, xmm1 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 9 + endm + +UNPACK_V3_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + movd xmm1, dword ptr [esi+3] + + punpcklbw xmm0, xmm0 + punpcklbw xmm1, xmm1 + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 6 + endm + +UNPACK_V3_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 3 + endm + +UNPACK_V3_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V4_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [esi] + movdqa xmm1, [esi+16] + movdqa xmm2, [esi+32] + movdqa xmm7, [esi+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 64 + endm + +UNPACK_V4_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + movdqu xmm1, [esi+16] + movdqu xmm2, [esi+32] + movdqu xmm7, [esi+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 64 + endm + +UNPACK_V4_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [esi] + movdqa xmm1, [esi+16] + movdqa xmm2, [esi+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 48 + endm + +UNPACK_V4_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + movdqu xmm1, [esi+16] + movdqu xmm2, [esi+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 48 + endm + +UNPACK_V4_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [esi] + movdqa xmm1, [esi+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V4_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + movdqu xmm1, [esi+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V4_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [esi] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V4_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + + +UNPACK_V4_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + + punpcklwd xmm0, [esi] + punpckhwd xmm1, [esi] + punpcklwd xmm2, [esi+16] + punpckhwd xmm7, [esi+16] + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V4_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + movdqu xmm2, [esi+16] + + punpckhwd xmm1, xmm0 + punpckhwd xmm7, xmm2 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 32 + endm + +UNPACK_V4_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + punpckhwd xmm1, [esi] + punpcklwd xmm2, [esi+16] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V4_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + movq xmm2, QWORD PTR [esi+16] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 24 + endm + +UNPACK_V4_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + punpckhwd xmm1, [esi] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V4_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movq xmm1, QWORD PTR [esi+8] + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V4_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [esi] + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V4_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + + +UNPACK_V4_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [esi] + punpckhbw xmm2, [esi] + + punpckhwd xmm1, xmm0 + punpckhwd xmm7, xmm2 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm7, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V4_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [esi] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm7, xmm2 + punpckhwd xmm1, xmm0 + punpcklwd xmm2, xmm2 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm7, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 16 + endm + +UNPACK_V4_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [esi] + punpckhbw xmm2, [esi] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V4_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + movd xmm2, dword ptr [esi+8] + + punpcklbw xmm0, xmm0 + punpcklbw xmm2, xmm2 + + punpckhwd xmm1, xmm0 + punpcklwd xmm2, xmm2 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 12 + endm + +UNPACK_V4_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [esi] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V4_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [esi] + + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V4_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [esi] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_V4_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [esi] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + + +DECOMPRESS_RGBA macro OFFSET + mov bl, al + shl bl, 3 + mov byte ptr [s_TempDecompress+OFFSET], bl + + mov bx, ax + shr bx, 2 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+1], bl + + mov bx, ax + shr bx, 7 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+2], bl + mov bx, ax + shr bx, 8 + and bx, 080h + mov byte ptr [s_TempDecompress+OFFSET+3], bl + endm + +UNPACK_V4_5SSE_4 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [esi] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [esi+4] + DECOMPRESS_RGBA 8 + + shr eax, 16 + DECOMPRESS_RGBA 12 + + ;; have to use movaps instead of movdqa + movaps xmm0, [s_TempDecompress] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm7, xmm2 + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + psrld xmm0, 24 + psrld xmm1, 24 + psrld xmm2, 24 + psrld xmm7, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 8 + endm + +UNPACK_V4_5SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_3 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [esi] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [esi] + DECOMPRESS_RGBA 8 + + ;; have to use movaps instead of movdqa + movaps xmm0, [s_TempDecompress] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + psrld xmm0, 24 + psrld xmm1, 24 + psrld xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 6 + endm + +UNPACK_V4_5SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_2 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [esi] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + movq xmm0, QWORD PTR [s_TempDecompress] + + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + psrld xmm0, 24 + psrld xmm1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 4 + endm + +UNPACK_V4_5SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_1 macro CL, TOTALCL, MaskType, ModeType + mov ax, word ptr [esi] + DECOMPRESS_RGBA 0 + + movd xmm0, DWORD PTR [s_TempDecompress] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + + psrld xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add esi, 2 + endm + +UNPACK_V4_5SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +SAVE_ROW_REG_BASE macro + mov eax, [_vifRow] + movdqa [eax], xmm6 + mov eax, [_vifRegs] + movss dword ptr [eax+0100h], xmm6 + psrldq xmm6, 4 + movss dword ptr [eax+0110h], xmm6 + psrldq xmm6, 4 + movss dword ptr [eax+0120h], xmm6 + psrldq xmm6, 4 + movss dword ptr [eax+0130h], xmm6 + endm + +SAVE_NO_REG macro + endm + +INIT_ARGS macro + mov edi, dword ptr [esp+4+12] + mov esi, dword ptr [esp+8+12] + mov edx, dword ptr [esp+12+12] + endm + +INC_STACK macro reg + add esp, 4 + endm + + + + + +defUNPACK_SkippingWrite macro name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType) proc public + push edi + push esi + push ebx + + INIT_ARGS + mov eax, [_vifRegs] + movzx ecx, byte ptr [eax + 040h] + movzx ebx, byte ptr [eax + 041h] + sub ecx, ebx + shl ecx, 4 + + cmp ebx, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1) + cmp ebx, 2 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2) + cmp ebx, 3 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1): + @CatStr(UNPACK_Start_Setup_, MaskType, _SSE_, ModeType) 0 + + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + + add ecx, 16 + + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16): + + test esi, 15 + jz @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned) + + @CatStr(UNPACK_, name, SSE_1) 0, 1, MaskType, ModeType + + cmp edx, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec) + sub edx, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned): + + cmp edx, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp edx, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + cmp edx, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3) + prefetchnta [esi + 64] + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4): + @CatStr(UNPACK_, name, SSE_4A) 0, 1, MaskType, ModeType + + cmp edx, (8*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4) + sub edx, (4*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4): + + sub edx, (4*qsize) + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + cmp edx, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp edx, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3): + @CatStr(UNPACK_, name, SSE_3A) 0, 1, MaskType, ModeType + + sub edx, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2): + @CatStr(UNPACK_, name, SSE_2A) 0, 1, MaskType, ModeType + + sub edx, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1): + @CatStr(UNPACK_, name, SSE_1A) 0, 1, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec): + sub edx, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3): + SAVE_ROW_REG + mov eax, edx + pop ebx + pop esi + pop edi + + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2): + cmp edx, (2*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + + add edi, ecx + cmp edx, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2) + sub edx, (2*qsize) + + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2): + sub edx, (2*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3): + cmp edx, qsize + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4) + + + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + sub edx, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4): + + SAVE_ROW_REG + mov eax, edx + pop ebx + pop esi + pop edi + + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3): + cmp edx, (3*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + add edi, ecx + cmp edx, (6*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2) + sub edx, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2): + sub edx, (3*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5): + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) + + cmp edx, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3) + + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + sub edx, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3): + sub edx, qsize + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4): + SAVE_ROW_REG + mov eax, edx + pop ebx + pop esi + pop edi + + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4): + sub ebx, 3 + push ecx + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack): + cmp edx, (3*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3) + cmp edx, (2*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2) + + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + + sub edx, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + + sub edx, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + + sub edx, (3*qsize) + mov ecx, ebx + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX): + + + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + + @CatStr(UNPACK_, name, SSE_1) 3, 0, MaskType, ModeType + + sub edx, qsize + cmp ecx, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop) + sub ecx, 1 + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop): + add edi, [esp] + cmp edx, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done): + + SAVE_ROW_REG + INC_STACK() + mov eax, edx + pop ebx + pop esi + pop edi + + ret +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType endp) +endm + +UNPACK_RIGHTSHIFT macro reg, shift + psrld reg, shift + endm + +defUNPACK_SkippingWrite2 macro name, qsize + defUNPACK_SkippingWrite name, Regular, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2 S_32, 4 +defUNPACK_SkippingWrite2 S_16, 2 +defUNPACK_SkippingWrite2 S_8, 1 +defUNPACK_SkippingWrite2 V2_32, 8 +defUNPACK_SkippingWrite2 V2_16, 4 +defUNPACK_SkippingWrite2 V2_8, 2 +defUNPACK_SkippingWrite2 V3_32, 12 +defUNPACK_SkippingWrite2 V3_16, 6 +defUNPACK_SkippingWrite2 V3_8, 3 +defUNPACK_SkippingWrite2 V4_32, 16 +defUNPACK_SkippingWrite2 V4_16, 8 +defUNPACK_SkippingWrite2 V4_8, 4 +defUNPACK_SkippingWrite2 V4_5, 2 + +UNPACK_RIGHTSHIFT macro reg, shift + psrad reg, shift + endm + + +defUNPACK_SkippingWrite2a macro name, qsize + defUNPACK_SkippingWrite name, Mask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2a S_16, 2 +defUNPACK_SkippingWrite2a S_8, 1 +defUNPACK_SkippingWrite2a V2_16, 4 +defUNPACK_SkippingWrite2a V2_8, 2 +defUNPACK_SkippingWrite2a V3_16, 6 +defUNPACK_SkippingWrite2a V3_8, 3 +defUNPACK_SkippingWrite2a V4_16, 8 +defUNPACK_SkippingWrite2a V4_8, 4 + +end diff --git a/pcsx2/x86/ix86-32/iCore-32.cpp b/pcsx2/x86/ix86-32/iCore-32.cpp new file mode 100644 index 0000000..0394ebb --- /dev/null +++ b/pcsx2/x86/ix86-32/iCore-32.cpp @@ -0,0 +1,1205 @@ +#include +#include +#include +#include + +extern "C" { + +#if defined(_WIN32) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 x86FpuState, iCWstate; +u16 g_mmxAllocCounter = 0; + +// used to make sure regs don't get changed while in recompiler +// use FreezeMMXRegs, FreezeXMMRegs +u8 g_globalMMXSaved = 0; + +#ifdef _DEBUG +char g_globalMMXLocked = 0; +#endif + +PCSX2_ALIGNED16(u64 g_globalMMXData[8]); + +// X86 caching +extern _x86regs x86regs[X86REGS]; +int g_x86checknext; +extern u16 g_x86AllocCounter; + +} // end extern "C" + +#include +using namespace std; + +// use special x86 register allocation for ia32 +#ifndef __x86_64__ + +void _initX86regs() { + memset(x86regs, 0, sizeof(x86regs)); + g_x86AllocCounter = 0; + g_x86checknext = 0; +} + +u32 _x86GetAddr(int type, int reg) +{ + switch(type&~X86TYPE_VU1) { + case X86TYPE_GPR: return (u32)&cpuRegs.GPR.r[reg]; + case X86TYPE_VI: { + //assert( reg < 16 || reg == REG_R ); + return (type&X86TYPE_VU1)?(u32)&VU1.VI[reg]:(u32)&VU0.VI[reg]; + } + case X86TYPE_MEMOFFSET: return 0; + case X86TYPE_VIMEMOFFSET: return 0; + case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_Q]:(u32)&VU0.VI[REG_Q]; + case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_P]; + case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.q:(u32)&VU0.q; + case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.p:(u32)&VU0.p; + case X86TYPE_PSX: return (u32)&psxRegs.GPR.r[reg]; + case X86TYPE_PCWRITEBACK: + return (u32)&g_recWriteback; + case X86TYPE_VUJUMP: + return (u32)&g_recWriteback; + default: assert(0); + } + + return 0; +} + +int _getFreeX86reg(int mode) +{ + int i, tempi; + u32 bestcount = 0x10000; + + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + + for (i=0; i= maxreg ) continue; + if( (mode&MODE_NOFRAME) && reg==EBP ) continue; + + if (x86regs[reg].inuse == 0) { + g_x86checknext = (reg+1)%X86REGS; + return reg; + } + } + + tempi = -1; + for (i=1; i= 0 && reg < 32 ); + +// if( X86_ISVI(type) ) +// assert( reg < 16 || reg == REG_R ); + + // don't alloc EAX and ESP,EBP if MODE_NOFRAME + int oldmode = mode; + int noframe = mode&MODE_NOFRAME; + int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + mode &= ~(MODE_NOFRAME|MODE_8BITREG); + int readfromreg = -1; + + if( type != X86TYPE_TEMP ) { + + if( maxreg < X86REGS ) { + // make sure reg isn't in the higher regs + + for(i = maxreg; i < X86REGS; ++i) { + if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) continue; + + if( mode & MODE_READ ) { + readfromreg = i; + x86regs[i].inuse = 0; + break; + } + else if( mode & MODE_WRITE ) { + x86regs[i].inuse = 0; + break; + } + } + } + + for (i=1; i= maxreg) ) { + if( x86regs[i].mode & MODE_READ ) + readfromreg = i; + //if( xmmregs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + + if( x86reg >= 0 ) { + // requested specific reg, so return that instead + if( i != x86reg ) { + if( x86regs[i].mode & MODE_READ ) readfromreg = i; + //if( x86regs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + } + + if( type != X86TYPE_TEMP && !(x86regs[i].mode & MODE_READ) && (mode&MODE_READ)) { + + if( type == X86TYPE_GPR ) _flushConstReg(reg); + + if( X86_ISVI(type) && reg < 16 ) MOVZX32M16toR(i, _x86GetAddr(type, reg)); + else MOV32MtoR(i, _x86GetAddr(type, reg)); + + x86regs[i].mode |= MODE_READ; + } + + x86regs[i].needed = 1; + x86regs[i].mode|= mode; + return i; + } + } + + if (x86reg == -1) { + x86reg = _getFreeX86reg(oldmode); + } + else { + _freeX86reg(x86reg); + } + + x86regs[x86reg].type = type; + x86regs[x86reg].reg = reg; + x86regs[x86reg].mode = mode; + x86regs[x86reg].needed = 1; + x86regs[x86reg].inuse = 1; + + if( mode & MODE_READ ) { + if( readfromreg >= 0 ) MOV32RtoR(x86reg, readfromreg); + else { + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) { + XOR32RtoR(x86reg, x86reg); + } + else { + _flushConstReg(reg); + _deleteMMXreg(MMX_GPR+reg, 1); + _deleteGPRtoXMMreg(reg, 1); + + _eeMoveGPRtoR(x86reg, reg); + + _deleteMMXreg(MMX_GPR+reg, 0); + _deleteGPRtoXMMreg(reg, 0); + } + } + else { + if( X86_ISVI(type) && reg < 16 ) { + if( reg == 0 ) XOR32RtoR(x86reg, x86reg); + else MOVZX32M16toR(x86reg, _x86GetAddr(type, reg)); + } + else MOV32MtoR(x86reg, _x86GetAddr(type, reg)); + } + } +} + + return x86reg; +} + +int _checkX86reg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 && x86reg < X86REGS ); + + if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { + x86regs[x86reg].mode &= ~MODE_WRITE; + + if( X86_ISVI(x86regs[x86reg].type) && x86regs[x86reg].reg < 16 ) { + MOV16RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + else + MOV32RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + + x86regs[x86reg].inuse = 0; +} + +void _freeX86regs() { + int i; + + for (i=0; i= MMX_GPR && reg < MMX_GPR+32 ) return &cpuRegs.GPR.r[reg&31]; + if( reg >= MMX_FPU && reg < MMX_FPU+32 ) return &fpuRegs.fpr[reg&31]; + if( reg >= MMX_COP0 && reg < MMX_COP0+32 ) return &cpuRegs.CP0.r[reg&31]; + + assert( 0 ); + return NULL; +} + +int _getFreeMMXreg() +{ + int i, tempi; + u32 bestcount = 0x10000; + + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) { + _freeMMXreg(i); + return i; + } + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + _freeMMXreg(i); + return i; + } + } + } + + // check for future xmm usage + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) { + _freeMMXreg(i); + return i; + } + } + } + + tempi = -1; + for (i=0; i= 0 ) { + if (cpucaps.hasStreamingSIMD2Extensions) { + SSE_MOVHPS_XMM_to_M64((u32)_MMXGetAddr(reg)+8, xmmreg); + if( mode & MODE_READ ) + SSE2_MOVDQ2Q_XMM_to_MM(mmxreg, xmmreg); + + if( xmmregs[xmmreg].mode & MODE_WRITE ) + mmxregs[mmxreg].mode |= MODE_WRITE; + + // don't flush + xmmregs[xmmreg].inuse = 0; + } + else { + _freeXMMreg(xmmreg); + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + + } + } + else { + if( MMX_ISGPR(reg) ) { + if(mode&(MODE_READHALF|MODE_READ)) _flushConstReg(reg-MMX_GPR); + } + + if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) ) { + MOVDMtoMMX(mmxreg, (u32)_MMXGetAddr(reg)); + } + else if( mode & MODE_READ ) { + MOVQMtoR(mmxreg, (u32)_MMXGetAddr(reg)); + } + } + } + + return mmxreg; +} + +int _checkMMXreg(int reg, int mode) +{ + int i; + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !EEINST_ISLIVE64(mmxregs[i].reg-MMX_GPR) ) { + return 1; + } + } + } + + // check for dead regs + for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { + if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + return 1; + } + } + } + + return 0; +} + +void _freeMMXreg(int mmxreg) +{ + assert( mmxreg < MMXREGS ); + if (!mmxregs[mmxreg].inuse) return; + + if (mmxregs[mmxreg].mode & MODE_WRITE ) { + + if( mmxregs[mmxreg].reg >= MMX_GPR && mmxregs[mmxreg].reg < MMX_GPR+32 ) + assert( !(g_cpuHasConstReg & (1<<(mmxregs[mmxreg].reg-MMX_GPR))) ); + + assert( mmxregs[mmxreg].reg != MMX_GPR ); + + if( MMX_IS32BITS(mmxregs[mmxreg].reg) ) + MOVDMMXtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + else + MOVQRtoM((u32)_MMXGetAddr(mmxregs[mmxreg].reg), mmxreg); + + SetMMXstate(); + } + + mmxregs[mmxreg].mode &= ~MODE_WRITE; + mmxregs[mmxreg].inuse = 0; +} + +void _moveMMXreg(int mmxreg) +{ + int i; + if( !mmxregs[mmxreg].inuse ) return; + + for (i=0; i>16)&0x1f].UL[0]); + } + else if( IS_PSXCONSTREG(arg) ) { + PUSH32I(g_psxConstRegs[(arg>>16)&0x1f]); + } + else if( IS_MEMORYREG(arg) ) PUSH32M(argmem); + else { + assert( (arg&0xfff0) == 0 ); + // assume it is a GPR reg + PUSH32R(arg&0xf); + } +} + +void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem) +{ + _callPushArg(arg1, arg1mem, -1); + CALLFunc((uptr)fn); + ADD32ItoR(ESP, 4); +} + +void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem) +{ + _callPushArg(arg2, arg2mem, -1); + _callPushArg(arg1, arg1mem, -1); + CALLFunc((uptr)fn); + ADD32ItoR(ESP, 8); +} + +void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem) +{ + _callPushArg(arg3, arg3mem, -1); + _callPushArg(arg2, arg2mem, -1); + _callPushArg(arg1, arg1mem, -1); + CALLFunc((uptr)fn); + ADD32ItoR(ESP, 12); +} + +// EE +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoR( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) { + SSE2_MOVD_XMM_to_R(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) { + MOVD32MMXtoR(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + } + } +} + +void _eeMoveGPRtoM(u32 to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_M32(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVDMMXtoM(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoM(to, EAX ); + } + } +} + +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 ); + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_Rm(to, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) { + MOVD32MMXtoRm(to, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] ); + MOV32RtoRm(to, EAX ); + } + } +} + +void _recPushReg(int mmreg) +{ + if( IS_XMMREG(mmreg) ) { + SUB32ItoR(ESP, 4); + SSEX_MOVD_XMM_to_Rm(ESP, mmreg&0xf); + } + else if( IS_MMXREG(mmreg) ) { + SUB32ItoR(ESP, 4); + MOVD32MMXtoRm(ESP, mmreg&0xf); + } + else if( IS_EECONSTREG(mmreg) ) { + PUSH32I(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); + } + else if( IS_PSXCONSTREG(mmreg) ) { + PUSH32I(g_psxConstRegs[(mmreg>>16)&0x1f]); + } + else { + assert( (mmreg&0xfff0) == 0 ); + PUSH32R(mmreg); + } +} + +void _signExtendSFtoM(u32 mem) +{ + LAHF(); + SAR16ItoR(EAX, 15); + CWDE(); + MOV32RtoM(mem, EAX ); +} + +int _signExtendMtoMMX(x86MMXRegType to, u32 mem) +{ + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, mem); + MOVQRtoR(to, t0reg); + PSRADItoR(t0reg, 31); + PUNPCKLDQRtoR(to, t0reg); + _freeMMXreg(t0reg); + return to; +} + +int _signExtendGPRMMXtoMMX(x86MMXRegType to, u32 gprreg, x86MMXRegType from, u32 gprfromreg) +{ + assert( to >= 0 && from >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + EEINST_RESETHASLIVE1(gprreg); + if( to != from ) MOVQRtoR(to, from); + return to; + } + + if( to == from ) return _signExtendGPRtoMMX(to, gprreg, 0); + if( !(g_pCurInstInfo->regs[gprfromreg]&EEINST_LASTUSE) ) { + if( EEINST_ISLIVE64(gprfromreg) ) { + MOVQRtoR(to, from); + return _signExtendGPRtoMMX(to, gprreg, 0); + } + } + + // from is free for use + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + + if( EEINST_ISLIVE64(gprfromreg) ) { + _freeMMXreg(from); + } + + MOVQRtoR(to, from); + PSRADItoR(from, 31); + PUNPCKLDQRtoR(to, from); + return to; + } + else { + MOVQRtoR(to, from); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], from); + PSRADItoR(from, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], from); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift) +{ + assert( to >= 0 && shift >= 0 ); + if( !EEINST_ISLIVE1(gprreg) ) { + if( shift > 0 ) PSRADItoR(to, shift); + EEINST_RESETHASLIVE1(gprreg); + return to; + } + + SetMMXstate(); + + if( g_pCurInstInfo->regs[gprreg] & EEINST_MMX ) { + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, to); + PSRADItoR(to, 31); + if( shift > 0 ) PSRADItoR(t0reg, shift); + PUNPCKLDQRtoR(t0reg, to); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[to]; + mmxregs[to].inuse = 0; + return t0reg; + } + else { + // will be used in the future as mmx + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + + // read again + MOVQMtoR(to, (u32)&cpuRegs.GPR.r[gprreg].UL[0]); + mmxregs[to].mode &= ~MODE_WRITE; + return to; + } + } + else { + if( shift > 0 ) PSRADItoR(to, shift); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[0], to); + PSRADItoR(to, 31); + MOVDMMXtoM((u32)&cpuRegs.GPR.r[gprreg].UL[1], to); + mmxregs[to].inuse = 0; + return -1; + } + + assert(0); +} + +int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode) +{ + if( pinst->regs[reg] & EEINST_MMX ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + + return _checkMMXreg(MMX_GPR+reg, mode); +} + +void _recMove128MtoM(u32 to, u32 from) +{ + MOV32MtoR(EAX, from); + MOV32MtoR(EDX, from+4); + MOV32RtoM(to, EAX); + MOV32RtoM(to+4, EDX); + MOV32MtoR(EAX, from+8); + MOV32MtoR(EDX, from+12); + MOV32RtoM(to+8, EAX); + MOV32RtoM(to+12, EDX); +} + +void _recMove128RmOffsettoM(u32 to, u32 offset) +{ + MOV32RmtoROffset(EAX, ECX, offset); + MOV32RmtoROffset(EDX, ECX, offset+4); + MOV32RtoM(to, EAX); + MOV32RtoM(to+4, EDX); + MOV32RmtoROffset(EAX, ECX, offset+8); + MOV32RmtoROffset(EDX, ECX, offset+12); + MOV32RtoM(to+8, EAX); + MOV32RtoM(to+12, EDX); +} + +void _recMove128MtoRmOffset(u32 offset, u32 from) +{ + MOV32MtoR(EAX, from); + MOV32MtoR(EDX, from+4); + MOV32RtoRmOffset(ECX, EAX, offset); + MOV32RtoRmOffset(ECX, EDX, offset+4); + MOV32MtoR(EAX, from+8); + MOV32MtoR(EDX, from+12); + MOV32RtoRmOffset(ECX, EAX, offset+8); + MOV32RtoRmOffset(ECX, EDX, offset+12); +} + +static PCSX2_ALIGNED16(u32 s_ones[2]) = {0xffffffff, 0xffffffff}; + +void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op) +{ + switch(op) { + case 0: PANDRtoR(to, from); break; + case 1: PORRtoR(to, from); break; + case 2: PXORRtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOpMtoR(x86MMXRegType to, u32 from, int op) +{ + switch(op) { + case 0: PANDMtoR(to, from); break; + case 1: PORMtoR(to, from); break; + case 2: PXORMtoR(to, from); break; + case 3: + PORRtoR(to, from); + PXORMtoR(to, (u32)&s_ones[0]); + break; + } +} + +void LogicalOp32RtoM(u32 to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND32RtoM(to, from); break; + case 1: OR32RtoM(to, from); break; + case 2: XOR32RtoM(to, from); break; + case 3: OR32RtoM(to, from); break; + } +} + +void LogicalOp32MtoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32MtoR(to, from); break; + case 1: OR32MtoR(to, from); break; + case 2: XOR32MtoR(to, from); break; + case 3: OR32MtoR(to, from); break; + } +} + +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoR(to, from); break; + case 1: OR32ItoR(to, from); break; + case 2: XOR32ItoR(to, from); break; + case 3: OR32ItoR(to, from); break; + } +} + +void LogicalOp32ItoM(u32 to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoM(to, from); break; + case 1: OR32ItoM(to, from); break; + case 2: XOR32ItoM(to, from); break; + case 3: OR32ItoM(to, from); break; + } +} diff --git a/pcsx2/x86/ix86-32/iR5900-32.c b/pcsx2/x86/ix86-32/iR5900-32.c new file mode 100644 index 0000000..92239b9 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900-32.c @@ -0,0 +1,3295 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 +// Recompiled completely rewritten to add block level recompilation/reg-caching/ +// liveness analysis/constant propagation Apr06 (zerofrog@gmail.com) + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "VU.h" +#include "VUmicro.h" + +#include "iVUzerorec.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +u32 maxrecmem = 0; +uptr *recLUT; + +#define X86 +#define RECSTACK_SIZE 0x00010000 + +#define EE_NUMBLOCKS (1<<15) + +static char *recMem = NULL; // the recompiled blocks will be here +static char* recStack = NULL; // stack mem +static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here +static BASEBLOCK *recROM = NULL; // and here +static BASEBLOCK *recROM1 = NULL; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr = NULL, *recStackPtr = NULL; +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_EEFreezeRegs = 0; // if set, should freeze the regs + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what pc the current block ends +static u32 s_nHasDelay = 0; + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +extern void (*recBSC[64])(); +extern void (*recBSC_co[64])(); +void rpropBSC(EEINST* prev, EEINST* pinst); + +// save states for branches +static u16 s_savex86FpuState, s_saveiCWstate; +static GPR_reg64 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_nBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +void recCOP2RecompileInst(); +int recCOP2AnalyzeBlock(u32 startpc, u32 endpc); +void recCOP2EndBlock(void); + +#ifdef _DEBUG +u32 dumplog = 0; +#else +#define dumplog 0 +#endif + +u32 pc; // recompiler pc +int branch; // set for branch + +#ifdef PCSX2_DEVBUILD +LARGE_INTEGER lbase = {0}, lfinal = {0}; +static u32 s_startcount = 0; +#endif + +char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +char *txt1 = "REG[%d] = %x_%x\n"; +char *txt2 = "M32 = %x\n"; + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls); // reccop2.c +static void iBranchTest(u32 newpc, u32 cpuBranch); +void recRecompile( u32 startpc ); +void recCOP22( void ); + +BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 0); +} + +//////////////////////////////////////////////////// +void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + extern char *disRNameGPR[]; + u8 used[34]; + u8 fpuused[33]; + int numused, count, fpunumused; + + SysPrintf( "dump1 %x:%x, %x\n", startpc, pc, cpuRegs.cycle ); +#ifdef _WIN32 + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\dump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/dump%.8X.txt", startpc); +#endif + + fflush( stdout ); +// f = fopen( "dump1", "wb" ); +// fwrite( ptr, 1, (u32)x86Ptr - (u32)ptr, f ); +// fclose( f ); +// +// sprintf( command, "objdump -D --target=binary --architecture=i386 dump1 > %s", filename ); +// system( command ); + + f = fopen( filename, "w" ); + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR5900Fasm( PSMu32( i ), i ) ); + } + + // write the instruction info + + fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memset(fpuused, 0, sizeof(fpuused)); + fpunumused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count>26) { + case 26: // ldl + case 27: // ldr + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 55: // LD + case 30: // lq + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _eeIsLoadStoreCoIssue(u32 firstcode, u32 secondcode) +{ + switch(firstcode>>26) { + case 34: // lwl + return (secondcode>>26)==38; + case 38: // lwr + return (secondcode>>26)==34; + case 42: // swl + return (secondcode>>26)==46; + case 46: // swr + return (secondcode>>26)==42; + case 26: // ldl + return (secondcode>>26)==27; + case 27: // ldr + return (secondcode>>26)==26; + case 44: // sdl + return (secondcode>>26)==45; + case 45: // sdr + return (secondcode>>26)==44; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + + // stores + case 40: case 41: case 43: + case 63: // sd + return (secondcode>>26)==(firstcode>>26); + + case 30: // lq + case 31: // sq + case 49: // lwc1 + case 57: // swc1 + case 54: // lqc2 + case 62: // sqc2 + return (secondcode>>26)==(firstcode>>26)&&cpucaps.hasStreamingSIMDExtensions; + } + return 0; +} + +u8 _eeIsLoadStoreCoX(u32 tempcode) +{ + switch( tempcode>>26 ) { + case 30: case 31: case 49: case 57: case 55: case 63: + return 1; + } + return 0; +} + +void _eeFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( pc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && GPR_IS_CONST1(i) ) _flushConstReg(i); + else { + _deleteMMXreg(MMX_GPR+i, 1); + _deleteGPRtoXMMreg(i, 1); + } + } + + //TODO when used info is done for FPU and VU0 + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse && xmmregs[i].type != XMMTYPE_GPRREG ) + _freeXMMreg(i); + } +} + +u32* _eeGetConstReg(int reg) +{ + assert( GPR_IS_CONST1( reg ) ); + + if( g_cpuFlushedConstReg & (1<regs[xmmregs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, xmmregs[i].reg) ) { + _freeXMMreg(i); + xmmregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushMMXunused() +{ + int i; + for (i=0; iregs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR) ) { + _freeMMXreg(i); + mmxregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_cpuHasConstReg & (1<regs[reg]&EEINST_LASTUSE) ) { + if( usemmx ) return _allocMMXreg(-1, MMX_GPR+reg, mode); + return _allocGPRtoXMMreg(-1, reg, mode); + } + + return -1; +} + +#define PROCESS_EE_SETMODES(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET(mmreg) ((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo +// core of reg caching +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) +{ + int mmreg1, mmreg2, mmreg3, mmtemp, moded; + + if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; + + if( xmminfo&XMMINFO_WRITED) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( xmminfo & XMMINFO_WRITED ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + } + if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededMMXreg(MMX_GPR+MMX_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededMMXreg(MMX_GPR+MMX_HI); + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_MMX) { +// mmreg1 = _allocMMXreg(-1, MMX_GPR+vreg, MODE_READ); +// _addNeededMMXreg(MMX_GPR+vreg); +// } + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVE64(vreg)) ) { + if( EEINST_ISLIVE64(vreg) ) { + _freeMMXreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_MMX; + + // do it all in mmx + if( mmreg1 < 0 ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + // check for last used, if so don't alloc a new MMX reg + if( xmminfo & XMMINFO_WRITED ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg3 = _checkMMXreg(MMX_GPR+_Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_)) ) { + if( EEINST_ISLIVE64(_Rt_) ) { + _freeMMXreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg2].inuse = 1; + mmxregs[mmreg2].reg = _Rd_; + mmxregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rs_)) ) { + if( EEINST_ISLIVE64(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocMMXreg(-1, MMX_GPR+_Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(MMX_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(MMX_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 1); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); + _addNeededGPRtoXMMreg(_Rs_); + _addNeededGPRtoXMMreg(_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { +// mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); +// _addNeededGPRtoXMMreg(vreg); +// } + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { + _freeXMMreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_XMM; + + // do it all in xmm + if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg2].inuse = 1; + xmmregs[mmreg2].reg = _Rd_; + xmmregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteMMXreg(MMX_GPR+_Rd_, (xmminfo&XMMINFO_READD)?0:2); + + // don't delete, fn will take care of them +// if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { +// _deleteGPRtoXMMreg(XMMGPR_LO, (xmminfo&XMMINFO_READLO)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_LO, (xmminfo&XMMINFO_READLO)?1:0); +// } +// if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { +// _deleteGPRtoXMMreg(XMMGPR_HI, (xmminfo&XMMINFO_READHI)?1:0); +// _deleteMMXreg(MMX_GPR+MMX_HI, (xmminfo&XMMINFO_READHI)?1:0); +// } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rt_ ) return; + + CHECK_SAVE_REG(_Rt_); + _eeProcessHasLive(_Rt_, 0); + EEINST_RESETSIGNEXT(_Rt_); + + if( GPR_IS_CONST1(_Rs_) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _deleteGPRtoXMMreg(_Rt_, 2); + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rt_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rs_) ) { + if( EEINST_ISLIVE64(_Rs_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteGPRtoXMMreg(_Rt_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rt_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rt_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + _deleteMMXreg(MMX_GPR+_Rt_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rt_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 2); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rd_ ) return; + + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + + if( GPR_IS_CONST1(_Rt_) ) { + _deleteMMXreg(MMX_GPR+_Rd_, 2); + _deleteGPRtoXMMreg(_Rd_, 2); + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + // test if should write mmx + if( g_pCurInstInfo->info & EEINST_MMX ) { + + // no const regs + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_MMX|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new MMX reg + _addNeededMMXreg(MMX_GPR+_Rd_); + mmreg2 = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { + if( EEINST_ISLIVE64(_Rt_) ) { + _freeMMXreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteGPRtoXMMreg(_Rd_, 2); + mmxregs[mmreg1].inuse = 1; + mmxregs[mmreg1].reg = _Rd_; + mmxregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + } + + SetMMXstate(); + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededMMXregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededMMXregs(); + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 2); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt op rs +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode) +{ + assert(0); + // for now, don't support xmm + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + multicode(0); +} + +// Simple Code Templates // + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rd_, 0); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rt_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rt_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 0); + + if( GPR_IS_CONST1(_Rs_) ) { + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST1(_Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT) +{ + assert(0); + // for now, don't support xmm + if( MULT ) { + CHECK_SAVE_REG(_Rd_); + _deleteGPRtoXMMreg(_Rd_, 0); + } + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTS); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + multicode(0); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); +} + +// EE XMM allocation code +int eeRecompileCodeXMM(int xmminfo) +{ + int info = PROCESS_EE_XMM; + + // save state + if( xmminfo & XMMINFO_WRITED ) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + // flush consts + if( xmminfo & XMMINFO_READT ) { + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + } + if( xmminfo & XMMINFO_READS) { + if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rs_); + } + } + + if( xmminfo & XMMINFO_WRITED ) { + GPR_DEL_CONST(_Rd_); + } + + // add needed + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + _addNeededGPRtoXMMreg(XMMGPR_LO); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + _addNeededGPRtoXMMreg(XMMGPR_HI); + } + if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); + if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); + if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); + + // allocate + if( xmminfo & XMMINFO_READS) { + int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); + } + if( xmminfo & XMMINFO_READT) { + int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); + } + + if( xmminfo & XMMINFO_WRITED ) { + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); + + int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); + + if( regd < 0 ) { + if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(EEREC_T); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_T].inuse = 1; + xmmregs[EEREC_T].reg = _Rd_; + xmmregs[EEREC_T].mode = readd; + regd = EEREC_T; + } + else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(EEREC_S); + _deleteMMXreg(MMX_GPR+_Rd_, 2); + xmmregs[EEREC_S].inuse = 1; + xmmregs[EEREC_S].reg = _Rd_; + xmmregs[EEREC_S].mode = readd; + regd = EEREC_S; + } + else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); + } + + info |= PROCESS_EE_SET_D(regd); + } + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); + info |= PROCESS_EE_LO; + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); + info |= PROCESS_EE_HI; + } + return info; +} + +// EE COP1(FPU) XMM allocation code +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define PROCESS_EE_SETMODES_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// rd = rs op rt +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo) +{ + int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; + + if( EE_FPU_REGCACHING && cpucaps.hasStreamingSIMDExtensions ) { + int info = PROCESS_EE_XMM; + + if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); + if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); + if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); + + if( xmminfo & XMMINFO_READT ) { + if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); + else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); + } + + if( xmminfo & XMMINFO_READS ) { + if( (!(xmminfo&XMMINFO_READT)||mmregt>=0) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) + mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); + } + + if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES_XMM(mmregs); + if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET_XMM(mmregt); + + if( xmminfo & XMMINFO_READD ) { + assert( xmminfo & XMMINFO_WRITED ); + mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); + } + + if( xmminfo & XMMINFO_READACC ) { + if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); + else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); + } + + if( xmminfo & XMMINFO_WRITEACC ) { + + // check for last used, if so don't alloc a new XMM reg + int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); + + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); + + if( mmregacc < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = 0; + xmmregs[mmregt].mode = readacc; + xmmregs[mmregt].type = XMMTYPE_FPACC; + mmregacc = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteMMXreg(MMX_FPU+XMMFPU_ACC, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = 0; + xmmregs[mmregs].mode = readacc; + xmmregs[mmregs].type = XMMTYPE_FPACC; + mmregacc = mmregs; + } + else mmregacc = _allocFPACCtoXMMreg(-1, readacc); + } + + xmmregs[mmregacc].mode |= MODE_WRITE; + } + else if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); + + if( mmregd < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = _Fd_; + xmmregs[mmregt].mode = readd; + mmregd = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = _Fd_; + xmmregs[mmregs].mode = readd; + mmregd = mmregs; + } + else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { + if( FPUINST_ISLIVE(XMMFPU_ACC) ) + _freeXMMreg(mmregacc); + _deleteMMXreg(MMX_FPU+_Fd_, 2); + xmmregs[mmregacc].inuse = 1; + xmmregs[mmregacc].reg = _Fd_; + xmmregs[mmregacc].mode = readd; + xmmregs[mmregacc].type = XMMTYPE_FPREG; + mmregd = mmregacc; + } + else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + } + } + + assert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); + + if( xmminfo & XMMINFO_WRITED ) { + assert( mmregd >= 0 ); + info |= PROCESS_EE_SET_D(mmregd); + } + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { + if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; + else assert( !(xmminfo&XMMINFO_WRITEACC)); + } + + if( xmminfo & XMMINFO_READS ) { + if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; + } + if( xmminfo & XMMINFO_READT ) { + if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; + } + + // at least one must be in xmm + if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { + assert( mmregs >= 0 || mmregt >= 0 ); + } + + xmmcode(info); + _clearNeededXMMregs(); + return; + } + + if( xmminfo & XMMINFO_READS ) _deleteFPtoXMMreg(_Fs_, 0); + if( xmminfo & XMMINFO_READT ) _deleteFPtoXMMreg(_Ft_, 0); + if( xmminfo & (XMMINFO_READD|XMMINFO_WRITED) ) _deleteFPtoXMMreg(_Fd_, 0); + if( xmminfo & (XMMINFO_READACC|XMMINFO_WRITEACC) ) _deleteFPtoXMMreg(XMMFPU_ACC, 0); + fpucode(0); +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +//////////////////////////////////////////////////// +extern u8 g_MACFlagTransform[256]; // for vus + +u32 g_sseMXCSR = 0x9f80; // disable all exception, round to 0, flush to 0 +u32 g_sseVUMXCSR = 0xff80; + +void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR) +{ + // SSE STATE // + // WARNING: do not touch unless you know what you are doing + + if( cpucaps.hasStreamingSIMDExtensions ) { + g_sseMXCSR = sseMXCSR; + g_sseVUMXCSR = sseVUMXCSR; + // do NOT set Denormals-Are-Zero flag (charlie and chocfac messes up) + //g_sseMXCSR = 0x9f80; // changing the rounding mode to 0x2000 (near) kills grandia III! + // changing the rounding mode to 0x0000 or 0x4000 totally kills gitaroo + // so... grandia III wins (you can change individual games with the 'roundmode' patch command) + +#ifdef _MSC_VER + __asm ldmxcsr g_sseMXCSR; // set the new sse control +#else + __asm__("ldmxcsr %0" : : "m"(g_sseMXCSR) ); +#endif + //g_sseVUMXCSR = g_sseMXCSR|0x6000; + } +} + +#define REC_CACHEMEM 0x01000000 + +int recInit( void ) +{ + int i; + const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + + recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 ); + memset( recLUT, 0, 0x010000 * sizeof(uptr) ); + + // can't have upper 4 bits nonzero! + recMem = (char*)SysMmap(0x0d000000, REC_CACHEMEM); + + // 32 alignment necessary + recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK)); + recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK)); + recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK)); + recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16); + recStack = (char*)malloc( RECSTACK_SIZE ); + + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize ); + + if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) { + SysMessage( _( "Error allocating memory" ) ); + return -1; + } + + for ( i = 0x0000; i < 0x0200; i++ ) + { + recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0040; i++ ) + { + recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0004; i++ ) + { + recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + } + + memcpy( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); + memcpy( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); + + memset(recMem, 0xcd, REC_CACHEMEM); + memset(recStack, 0, RECSTACK_SIZE); + + // SSE3 detection, manually create the code + x86SetPtr(recMem); + SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0); + RET(); + + cpudetectSSE3(recMem); + + SysPrintf( "x86Init: \n" ); + SysPrintf( "\tCPU vender name = %s\n", cpuinfo.x86ID ); + SysPrintf( "\tFamilyID = %x\n", cpuinfo.x86StepID ); + SysPrintf( "\tx86Family = %s\n", cpuinfo.x86Fam ); + SysPrintf( "\tCPU speed = %d.%03d Ghz\n", cpuinfo.cpuspeed / 1000, cpuinfo.cpuspeed%1000); + SysPrintf( "\tx86PType = %s\n", cpuinfo.x86Type ); + SysPrintf( "\tx86Flags = %8.8x\n", cpuinfo.x86Flags ); + SysPrintf( "\tx86EFlags = %8.8x\n", cpuinfo.x86EFlags ); + SysPrintf( "Features: \n" ); + SysPrintf( "\t%sDetected MMX\n", cpucaps.hasMultimediaExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE\n", cpucaps.hasStreamingSIMDExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE2\n", cpucaps.hasStreamingSIMD2Extensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE3\n", cpucaps.hasStreamingSIMD3Extensions ? "" : "Not " ); + + if ( cpuinfo.x86ID[0] == 'A' ) //AMD cpu + { + SysPrintf( " Extented AMD Features: \n" ); + SysPrintf( "\t%sDetected MMX2\n", cpucaps.hasMultimediaExtensionsExt ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW\n", cpucaps.has3DNOWInstructionExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW2\n", cpucaps.has3DNOWInstructionExtensionsExt ? "" : "Not " ); + } + if ( !( cpucaps.hasMultimediaExtensions ) ) + { + SysMessage( _( "Processor doesn't supports MMX, can't run recompiler without that" ) ); + return -1; + } + + x86FpuState = FPU_STATE; + + SuperVUInit(-1); + + for(i = 0; i < 256; ++i) { + g_MACFlagTransform[i] = macarr[i>>4]|(macarr[i&15]<<4); + } + + SetCPUState(g_sseMXCSR, g_sseVUMXCSR); + + return 0; +} + +//////////////////////////////////////////////////// +void recReset( void ) { +#ifdef PCSX2_DEVBUILD + SysPrintf("EE Recompiler data reset\n"); +#endif + + s_nNextBlock = 0; + maxrecmem = 0; + memset( recRAM, 0, sizeof(BASEBLOCK)/4*0x02000000 ); + memset( recROM, 0, sizeof(BASEBLOCK)/4*0x00400000 ); + memset( recROM1, 0, sizeof(BASEBLOCK)/4*0x00040000 ); + memset( recBlocks, 0, sizeof(BASEBLOCKEX)*EE_NUMBLOCKS ); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); + ResetBaseBlockEx(0); + +#ifdef _MSC_VER + __asm emms; +#else + __asm__("emms"); +#endif + +#ifdef _DEBUG + // don't clear since save states won't work + //memset(recMem, 0xcd, REC_CACHEMEM); +#endif + + recPtr = recMem; + recStackPtr = recStack; + x86FpuState = FPU_STATE; + iCWstate = 0; + + branch = 0; +} + +void recShutdown( void ) +{ + if ( recMem == NULL ) { + return; + } + + _aligned_free( recLUT ); + SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL; + _aligned_free( recRAM ); recRAM = NULL; + _aligned_free( recROM ); recROM = NULL; + _aligned_free( recROM1 ); recROM1 = NULL; + _aligned_free( recBlocks ); recBlocks = NULL; + free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0; + + SuperVUDestroy(-1); + + x86Shutdown( ); +} + +void recEnableVU0micro(int enable) { +} + +void recEnableVU1micro(int enable) { +} + +#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code +static u32 s_uSaveESP = 0, s_uSaveEBP; + +static void execute( void ) +{ +#ifdef _DEBUG + u8* fnptr; + u32 oldesi; +#else + R5900FNPTR pfn; +#endif + BASEBLOCK* pblock = PC_GETBLOCK(cpuRegs.pc); + + if ( !pblock->pFnptr || pblock->startpc != cpuRegs.pc ) { + recRecompile(cpuRegs.pc); + } + + assert( pblock->pFnptr != 0 ); + g_EEFreezeRegs = 1; + + // skip the POPs +#ifdef _DEBUG + fnptr = (u8*)pblock->pFnptr; + +#ifdef _MSC_VER + __asm { + // save data + mov oldesi, esi + mov s_uSaveESP, esp + sub s_uSaveESP, 8 + mov s_uSaveEBP, ebp + push ebp + + call fnptr // jump into function + // restore data + pop ebp + mov esi, oldesi + } +#else + + __asm__("movl %%esi, %0\n" + "movl %%esp, %1\n" + "sub $8, %1\n" + "push %%ebp\n" + "call *%2\n" + "pop %%ebp\n" + "movl %0, %%esi\n" : "=m"(oldesi), "=m"(s_uSaveESP) : "c"(fnptr) ); +#endif // _MSC_VER + +#else + +#ifdef _MSC_VER + pfn = ((R5900FNPTR)pblock->pFnptr); + // use call instead of pfn() + __asm call pfn; +#else + ((R5900FNPTR)pblock->pFnptr)(); +#endif + +#endif + + g_EEFreezeRegs = 0; +} + +void recStep( void ) { +} + +void recExecute( void ) { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);//ABOVE_NORMAL_PRIORITY_CLASS); + //SetThreadAffinityMask(GetCurrentThread(), 0); + if( Config.Options & PCSX2_EEREC ) Config.Options |= PCSX2_COP2REC; + + for (;;) + execute(); +} + +void recExecuteBlock( void ) { + execute(); +} + +//////////////////////////////////////////////////// +extern u32 g_nextBranchCycle; + +u32 g_lastpc = 0; +u32 g_EEDispatchTemp; +u32 s_pCurBlock_ltime; + +#ifdef _MSC_VER + +// jumped to when invalid pc address +__declspec(naked,noreturn) void Dispatcher() +{ + // EDX contains the jump addr to modify + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + __asm { + mov eax, s_pDispatchBlock + + // check if startpc == cpuRegs.pc + mov ecx, cpuRegs.pc + //and ecx, 0x5fffffff // remove higher bits + cmp ecx, dword ptr [eax+BLOCKTYPE_STARTPC] + je CheckPtr + + // recompile + push cpuRegs.pc // pc + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock +CheckPtr: + mov eax, dword ptr [eax] + } + +#ifdef _DEBUG + __asm mov g_EEDispatchTemp, eax + assert( g_EEDispatchTemp ); +#endif + +// __asm { +// test eax, 0x40000000 // BLOCKTYPE_NEEDCLEAR +// jz Done +// // move new pc +// and eax, 0x0fffffff +// mov ecx, cpuRegs.pc +// mov dword ptr [eax+1], ecx +// } + __asm { + and eax, 0x0fffffff + mov edx, eax + pop ecx // x86Ptr to mod + sub edx, ecx + sub edx, 4 + mov dword ptr [ecx], edx + + jmp eax + } +} + +__declspec(naked,noreturn) void DispatcherClear() +{ + // EDX contains the current pc + __asm mov cpuRegs.pc, edx + __asm push edx + + // calc PC_GETBLOCK + s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + + if( s_pDispatchBlock->startpc == cpuRegs.pc ) { + assert( s_pDispatchBlock->pFnptr != 0 ); + + // already modded the code, jump to the new place + __asm { + pop edx + add esp, 4 // ignore stack + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + and eax, 0x0fffffff + jmp eax + } + } + + __asm { + call recRecompile + add esp, 4 // pop old param + mov eax, s_pDispatchBlock + mov eax, dword ptr [eax] + + pop ecx // old fnptr + + and eax, 0x0fffffff + mov byte ptr [ecx], 0xe9 // jmp32 + mov edx, eax + sub edx, ecx + sub edx, 5 + mov dword ptr [ecx+1], edx + + jmp eax + } +} + +// called when jumping to variable pc address +__declspec(naked,noreturn) void DispatcherReg() +{ + __asm { + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc); + mov edx, cpuRegs.pc + mov ecx, edx + } + + __asm { + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + mov edx, dword ptr [edx] + + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // check if startpc == cpuRegs.pc + mov eax, ecx + //and eax, 0x5fffffff // remove higher bits + cmp eax, dword ptr [edx+BLOCKTYPE_STARTPC] + jne recomp + + mov eax, dword ptr [edx] + } + +#ifdef _DEBUG + __asm mov g_EEDispatchTemp, eax + assert( g_EEDispatchTemp ); +#endif + + __asm { + and eax, 0x0fffffff + jmp eax // fnptr + +recomp: + sub esp, 8 + mov dword ptr [esp+4], edx + mov dword ptr [esp], ecx + call recRecompile + mov edx, dword ptr [esp+4] + add esp, 8 + + mov eax, dword ptr [edx] + and eax, 0x0fffffff + jmp eax // fnptr + } +} + +#ifdef PCSX2_DEVBUILD +__declspec(naked) void _StartPerfCounter() +{ + __asm { + push eax + push ebx + push ecx + + rdtsc + mov dword ptr [offset lbase], eax + mov dword ptr [offset lbase + 4], edx + + pop ecx + pop ebx + pop eax + ret + } +} + +__declspec(naked) void _StopPerfCounter() +{ + __asm { + push eax + push ebx + push ecx + + rdtsc + + sub eax, dword ptr [offset lbase] + sbb edx, dword ptr [offset lbase + 4] + mov ecx, s_pCurBlock_ltime + add eax, dword ptr [ecx] + adc edx, dword ptr [ecx + 4] + mov dword ptr [ecx], eax + mov dword ptr [ecx + 4], edx + pop ecx + pop ebx + pop eax + ret + } +} + +#endif // PCSX2_DEVBUILD + +#else // _MSC_VER + +extern void Dispatcher(); +extern void DispatcherClear(); +extern void DispatcherReg(); +extern void _StartPerfCounter(); +extern void _StopPerfCounter(); + +#endif + +//////////////////////////////////////////////////// +void recClear64(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 16)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); +} + +void recClear128(BASEBLOCK* p) +{ + int left = 4 - ((u32)p % 32)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); + if( left > 2 && *(u32*)(p+2) ) recClearMem(p+2); + if( left > 3 && *(u32*)(p+3) ) recClearMem(p+3); +} + +void recClear( u32 Addr, u32 Size ) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + REC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 15 + +void recClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + // necessary since recompiler doesn't call femms/emms +#ifdef _MSC_VER + if (cpucaps.has3DNOWInstructionExtensions) __asm femms; + else __asm emms; +#else + if( cpucaps.has3DNOWInstructionExtensions )__asm__("femms"); + else __asm__("emms"); +#endif + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + recClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + PUSH32I((u32)x86Ptr); // will be replaced by JMP32 + JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PC_GETBLOCK(p->startpc); + pexblock = PC_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 0); + pexblock->size = 0; + pexblock->startpc = 0; +} + +// check for end of bios +void CheckForBIOSEnd() +{ + MOV32MtoR(EAX, (int)&cpuRegs.pc); + + CMP32ItoR(EAX, 0x00200008); + j8Ptr[0] = JE8(0); + + CMP32ItoR(EAX, 0x00100008); + j8Ptr[1] = JE8(0); + + // return + j8Ptr[2] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[1] ); + + // bios end + RET2(); + + x86SetJ8( j8Ptr[2] ); +} + +static int *s_pCode; + +void SetBranchReg( u32 reg ) +{ + branch = 1; + + if( reg != 0xffffffff ) { +// if( GPR_IS_CONST1(reg) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[reg].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+reg, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ reg ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, reg); + + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + } + +// CMP32ItoM((u32)&cpuRegs.pc, 0); +// j8Ptr[5] = JNE8(0); +// CALLFunc((u32)tempfn); +// x86SetJ8( j8Ptr[5] ); + + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); +} + +void SetBranchImm( u32 imm ) +{ + u32* ptr; + branch = 1; + + assert( imm ); + + // end the current block + MOV32ItoM( (u32)&cpuRegs.pc, imm ); + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(imm, imm <= pc); + if( bExecBIOS ) CheckForBIOSEnd(); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((u32)Dispatcher - ( (u32)x86Ptr + 5 )); +} + +void SaveBranchState() +{ + s_savex86FpuState = x86FpuState; + s_saveiCWstate = iCWstate; + s_savenBlockCycles = s_nBlockCycles; + s_saveConstGPRreg = 0xffffffff; // indicate searching + s_saveHasConstReg = g_cpuHasConstReg; + s_saveFlushedConstReg = g_cpuFlushedConstReg; + s_psaveInstInfo = g_pCurInstInfo; + s_saveRegHasLive1 = g_cpuRegHasLive1; + s_saveRegHasSignExt = g_cpuRegHasSignExt; + + // save all mmx regs + memcpy(s_saveMMXregs, mmxregs, sizeof(mmxregs)); + memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); +} + +void LoadBranchState() +{ + x86FpuState = s_savex86FpuState; + iCWstate = s_saveiCWstate; + s_nBlockCycles = s_savenBlockCycles; + + if( s_saveConstGPRreg != 0xffffffff ) { + assert( s_saveConstGPRreg > 0 ); + + // make sure right GPR was saved + assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<ltime); + CALLFunc((u32)_StopPerfCounter); + } +#endif +} + +#define USE_FAST_BRANCHES 0 + +//void testfpu() +//{ +// int i; +// for(i = 0; i < 32; ++i ) { +// if( fpuRegs.fpr[i].UL== 0x7f800000 || fpuRegs.fpr[i].UL == 0xffc00000) { +// SysPrintf("bad fpu: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// +// if( VU0.VF[i].UL[0] == 0xffc00000 || //(VU0.VF[i].UL[1]&0xffc00000) == 0xffc00000 || +// VU0.VF[i].UL[0] == 0x7f800000) { +// SysPrintf("bad vu0: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// } +//} + +//static void cleanup() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +static void iBranchTest(u32 newpc, u32 cpuBranch) +{ +#ifdef PCSX2_DEVBUILD + if( s_startcount ) { + StopPerfCounter(); + ADD32ItoM( (u32)&s_pCurBlockEx->visited, 1 ); + } +#endif + +#ifdef _DEBUG + //CALLFunc((u32)testfpu); +#endif + + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (int)&cpuRegs.cycle); + ADD32ItoR(ECX, s_nBlockCycles*9/8); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI + MOV32RtoM((int)&cpuRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + return; + } + + SUB32MtoR(ECX, (int)&g_nextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + // has to be in the middle of Save/LoadBranchState + CALLFunc( (int)cpuBranchTest ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((int)&cpuRegs.pc, newpc); + JNE32((u32)DispatcherReg - ( (u32)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + + +//////////////////////////////////////////////////// +#ifndef CP2_RECOMPILE + +REC_SYS(COP2); + +#else + +void recCOP2( void ) +{ +#ifdef CPU_LOG + CPU_LOG( "Recompiling COP2:%s\n", disR5900Fasm( cpuRegs.code, cpuRegs.pc ) ); +#endif + + if ( !cpucaps.hasStreamingSIMDExtensions ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + g_cpuHasConstReg = 1; // reset all since COP2 can change regs + CALLFunc( (u32)COP2 ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + } + else + { + recCOP22( ); + } +} + +#endif + +//////////////////////////////////////////////////// +void recSYSCALL( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)SYSCALL ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +void recBREAK( void ) { + MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BREAK ); + + CMP32ItoM((int)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((u32)&cpuRegs.cycle, s_nBlockCycles); + RET(); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +//static void recCACHE( void ) { +// MOV32ItoM( (u32)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (u32)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (u32)CACHE ); +// //branch = 2; +// +// CMP32ItoM((int)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// RET(); +// x86SetJ8(j8Ptr[0]); +//} + + +void recPREF( void ) +{ +} + +void recSYNC( void ) +{ +} + +void recMFSA( void ) +{ + int mmreg; + if (!_Rd_) return; + + mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + if( mmreg >= 0 ) { + SSE_MOVLPS_M64_to_XMM(mmreg, (u32)&cpuRegs.sa); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE)) >= 0 ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.sa); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.sa); + _deleteEEreg(_Rd_, 0); + MOV32RtoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], 0); + } +} + +void recMTSA( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + } + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.sa, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { + MOVDMMXtoM((u32)&cpuRegs.sa, mmreg); + SetMMXstate(); + } + else { + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } + } +} + +void recMTSAB( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0xF); + XOR32ItoR(EAX, _Imm_&0xf); + SHL32ItoR(EAX, 3); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +void recMTSAH( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((u32)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0x7); + XOR32RtoR(EAX, _Imm_&0x7); + SHL32ItoR(EAX, 4); + MOV32RtoM((u32)&cpuRegs.sa, EAX); + } +} + +static void checkcodefn() +{ + int pctemp; + +#ifdef _MSC_VER + __asm mov pctemp, eax; +#else + __asm__("movl %%eax, %0" : "=m"(pctemp) ); +#endif + + SysPrintf("code changed! %x\n", pctemp); + assert(0); +} + +void checkpchanged(u32 startpc) +{ + assert(0); +} + +//#ifdef _DEBUG +//#define CHECK_XMMCHANGED() CALLFunc((u32)checkxmmchanged); +//#else +//#define CHECK_XMMCHANGED() +//#endif +// +//static void checkxmmchanged() +//{ +// assert( !g_globalMMXSaved ); +// assert( !g_globalXMMSaved ); +//} + +u32 recompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PC_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pc == pblock->startpc ) + return 0; + } + + return 1; +} + +void recompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + int i, count; + + BASEBLOCK* pblock = PC_GETBLOCK(pc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && pc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == pc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + recClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", pc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSM( pc ); + assert(s_pCode); + +#ifdef _DEBUG + MOV32ItoR(EAX, pc); +#endif + + cpuRegs.code = *(int *)s_pCode; + s_nBlockCycles++; + pc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, cpuRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, pc); +// CALLFunc((u32)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +// +// if( !delayslot ) { +// CMP32ItoM((u32)&cpuRegs.pc, s_pCurBlockEx->startpc); +// j8Ptr[0] = JB8(0); +// CMP32ItoM((u32)&cpuRegs.pc, pc); +// j8Ptr[1] = JA8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[ 0 ] ); +// x86SetJ8( j8Ptr[ 1 ] ); +// PUSH32I(s_pCurBlockEx->startpc); +// CALLFunc((u32)checkpchanged); +// ADD32ItoR(ESP, 4); +// x86SetJ8( j8Ptr[ 2 ] ); +// } +//#endif + + g_pCurInstInfo++; + + // reorder register priorities +// for(i = 0; i < X86REGS; ++i) { +// if( x86regs[i].inuse ) { +// if( count > 0 ) mmxregs[i].counter = 1000-count; +// else mmxregs[i].counter = 0; +// } +// } + + for(i = 0; i < MMXREGS; ++i) { + if( mmxregs[i].inuse ) { + assert( MMX_ISGPR(mmxregs[i].reg) ); + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR); + if( count > 0 ) mmxregs[i].counter = 1000-count; + else mmxregs[i].counter = 0; + } + } + + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); + if( count > 0 ) xmmregs[i].counter = 1000-count; + else xmmregs[i].counter = 0; + } + } + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + +#ifdef PCSX2_VIRTUAL_MEM + if( g_pCurInstInfo->numpeeps > 1 ) { + switch(cpuRegs.code>>26) { + case 30: recLQ_coX(g_pCurInstInfo->numpeeps); break; + case 31: recSQ_coX(g_pCurInstInfo->numpeeps); break; + case 49: recLWC1_coX(g_pCurInstInfo->numpeeps); break; + case 57: recSWC1_coX(g_pCurInstInfo->numpeeps); break; + case 55: recLD_coX(g_pCurInstInfo->numpeeps); break; + case 63: recSD_coX(g_pCurInstInfo->numpeeps); break; + default: + assert(0); + } + + pc += g_pCurInstInfo->numpeeps*4; + s_nBlockCycles += g_pCurInstInfo->numpeeps; + g_pCurInstInfo += g_pCurInstInfo->numpeeps; + } + else { + recBSC_co[cpuRegs.code>>26](); + pc += 4; + s_nBlockCycles++; + g_pCurInstInfo++; + } +#else + assert(0); +#endif + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + + // if this instruction is a jump or a branch, exit right away + if( delayslot ) { + switch(cpuRegs.code>>26) { + case 1: + switch(_Rt_) { + case 0: case 1: case 2: case 3: case 0x10: case 0x11: case 0x12: case 0x13: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + return; + } + break; + + case 2: case 3: case 4: case 5: case 6: case 7: case 0x14: case 0x15: case 0x16: case 0x17: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + return; + } + } + recBSC[ cpuRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //if( !_flushUnusedConstReg() ) { + int flushed = 0; + if( _getNumMMXwrite() > 3 ) flushed = _flushMMXunused(); + if( !flushed && _getNumXMMwrite() > 2 ) _flushXMMunused(); + s_bFlushReg = !flushed; +// } +// else s_bFlushReg = 0; + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + //CHECK_XMMCHANGED(); + _clearNeededX86regs(); + _clearNeededMMXregs(); + _clearNeededXMMregs(); + +// _freeXMMregs(); +// _freeMMXregs(); +// _flushCachedRegs(); +// g_cpuHasConstReg = 0; +} + +//__declspec(naked) void iDummyBlock() +//{ +//// g_lastpc = cpuRegs.pc; +//// +//// do { +//// cpuRegs.cycle = g_nextBranchCycle; +//// cpuBranchTest(); +//// } while(g_lastpc == cpuRegs.pc); +//// +//// __asm jmp DispatcherReg +// __asm { +//RepDummy: +// add cpuRegs.cycle, 9 +// call cpuBranchTest +// cmp cpuRegs.pc, 0x81fc0 +// je RepDummy +// jmp DispatcherReg +// } +//} + +//////////////////////////////////////////////////// +#include "R3000A.h" +#include "PsxCounters.h" +#include "PsxMem.h" +extern tIPU_BP g_BP; + +extern u32 psxdump; +extern u32 psxNextCounter, psxNextsCounter; +extern void iDumpPsxRegisters(u32 startpc, u32 temp); +extern Counter counters[6]; + +void iDumpRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + extern char *disRNameGPR[]; + + __Log("%sreg: %x %x\n", pstr, startpc, cpuRegs.interrupt); + for(i = 1; i < 32; ++i) __Log("%s: %x_%x_%x_%x\n", disRNameGPR[i], cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x\n", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x\n", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x\n", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x\n", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + __Log("%svfACC: %x %x %x %x\n", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x\n", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x\n", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("cyc11: %x %x; vu0: %x, vu1: %x\n", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x\n", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x\n", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + } + __Log("VIF0_STAT = %x, VIF1_STAT = %x\n", psHu32(0x3800), psHu32(0x3C00)); + __Log("ipu %x %x %x %x; bp: %x %x %x %x\n", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x\n", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + for(i = 0; i < ARRAYSIZE(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x\n", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x\n", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x\n", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x\n", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +} + +extern u32 psxdump; + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0, count2 = 0; + const int skip = 0; + static int i; + + assert( !g_globalMMXSaved ); + assert( !g_globalXMMSaved ); + +#ifdef _DEBUG + //__asm stmxcsr i + //assert( i = g_sseMXCSR ); +#endif + + if( (dumplog&2) ) {//&& lastrec != g_lastpc ) { + + curcount++; + + if( curcount > skip ) { + iDumpRegisters(g_lastpc, 1); + curcount = 0; + } + + lastrec = g_lastpc; + } +} + +u32 s_recblocks[] = {0}; + +void badespfn() { + assert(0); + SysPrintf("Bad esp!\n"); +} + +#define OPTIMIZE_COP2 0//CHECK_VU0REC + +void recRecompile( u32 startpc ) +{ + u32 i = 0; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + u32 usecop2; + +#ifdef _DEBUG + //dumplog |= 4; + if( dumplog & 4 ) + iDumpRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) { + recReset(); + } + if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) { +#ifdef _DEBUG + SysPrintf("stack reset\n"); +#endif + recReset(); + } + + s_pCurBlock = PC_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + recClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < EE_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_pCurBlock->startpc = startpc; + + // slower +// if( startpc == 0x81fc0 ) { +// +// MOV32MtoR(ECX, (u32)&g_nextBranchCycle); +// MOV32RtoM((u32)&cpuRegs.cycle, ECX); +// //ADD32ItoR(ECX, 9); +// //ADD32ItoM((u32)&cpuRegs.cycle, 512); +// CALLFunc((u32)cpuBranchTest); +// CMP32ItoM((u32)&cpuRegs.pc, 0x81fc0); +// JE8(s_pCurBlock->pFnptr - (u32)(x86Ptr+2) ); +// JMP32((u32)DispatcherReg - (u32)(x86Ptr+5)); +// +// pc = startpc + 9*4; +// assert( (pc-startpc)>>2 <= 0xffff ); +// s_pCurBlockEx->size = (pc-startpc)>>2; +// +// for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // don't overwrite if delay slot +// if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { +// s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; +// s_pCurBlock[i].startpc = s_pCurBlock->startpc; +// } +// +// // set the block ptr +// AddBaseBlockEx(s_pCurBlockEx, 0); +// +// if( !(pc&0x10000000) ) +// maxrecmem = max( (pc&~0xa0000000), maxrecmem ); +// +// recPtr = x86Ptr; +// return; +// } + + branch = 0; + + // reset recomp state variables + s_nBlockCycles = 0; + pc = startpc; + x86FpuState = FPU_STATE; + iCWstate = 0; + s_saveConstGPRreg = 0; + g_cpuHasConstReg = g_cpuFlushedConstReg = 1; + g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; + g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; + _recClearWritebacks(); + assert( g_cpuConstRegs[0].UD[0] == 0 ); + + _initX86regs(); + _initXMMregs(); + _initMMXregs(); + +#ifdef _DEBUG + // for debugging purposes + MOV32ItoM((u32)&g_lastpc, pc); + CALLFunc((u32)printfn); + +// CMP32MtoR(EBP, (u32)&s_uSaveEBP); +// j8Ptr[0] = JE8(0); +// CALLFunc((u32)badespfn); +// x86SetJ8(j8Ptr[0]); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + s_nHasDelay = 0; + + while(1) { + BASEBLOCK* pblock = PC_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + cpuRegs.code = *(int *)PSM(i); + + switch(cpuRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + s_nHasDelay = 1; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) { + // branches + if( _Rt_ == 2 && _Rt_ == 3 && _Rt_ == 18 && _Rt_ == 19 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nHasDelay = 1; + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + case 20: case 21: case 22: case 23: + + if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + + case 16: // cp0 + if( _Rs_ == 16 ) { + if( _Funct_ == 24 ) { // eret + s_nEndBlock = i+4; + goto StartRecomp; + } + } + + break; + case 17: // cp1 + case 18: // cp2 + if( _Rs_ == 8 ) { + // BC1F, BC1T, BC1FL, BC1TL + // BC2F, BC2T, BC2FL, BC2TL + if( _Rt_ >= 2 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + break; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + cpuRegs.code = *(int *)PSM(i-4); + pcur[-1] = pcur[0]; + rpropBSC(pcur-1, pcur); + pcur--; + } + } + + // analyze instructions // + { + usecop2 = 0; + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock; i += 4) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(i); + + // cop2 // + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + + if( !usecop2 ) { + // init + if( OPTIMIZE_COP2 ) { + memset(VU0.fmac,0,sizeof(VU0.fmac)); + memset(&VU0.fdiv,0,sizeof(VU0.fdiv)); + memset(&VU0.efu,0,sizeof(VU0.efu)); + } + vucycle = 0; + usecop2 = 1; + } + + VU0.code = cpuRegs.code; + _cop2AnalyzeOp(g_pCurInstInfo, OPTIMIZE_COP2); + continue; + } + + if( usecop2 ) vucycle++; + + // peephole optimizations // +#ifdef PCSX2_VIRTUAL_MEM + if( i < s_nEndBlock-4 && recompileCodeSafe(i) ) { + u32 curcode = cpuRegs.code; + u32 nextcode = *(u32*)PSM(i+4); + if( _eeIsLoadStoreCoIssue(curcode, nextcode) && recBSC_co[curcode>>26] != NULL ) { + + // rs has to be the same, and cannot be just written + if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_eeLoadWritesRs(curcode) ) { + + if( _eeIsLoadStoreCoX(curcode) && ((nextcode>>16)&0x1f) != ((curcode>>21)&0x1f) ) { + // see how many stores there are + u32 j; + // use xmmregs since only supporting lwc1,lq,swc1,sq + for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + u32 nncode = *(u32*)PSM(j); + if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || + _eeLoadWritesRs(nncode)) + break; + } + + if( j > i+8 ) { + u32 num = (j-i)>>2; // number of stores that can coissue + assert( num <= XMMREGS ); + + g_pCurInstInfo[0].numpeeps = num-1; + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + + while(i < j-4) { + g_pCurInstInfo++; + g_pCurInstInfo[0].info |= EEINSTINFO_NOREC; + i += 4; + } + + continue; + } + + // fall through + } + + // unaligned loadstores + + // if LWL, check if LWR and that offsets are +3 away + switch(curcode >> 26) { + case 0x22: // LWL + if( (nextcode>>26) != 0x26 || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x26: // LWR + if( (nextcode>>26) != 0x22 || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x2a: // SWL + if( (nextcode>>26) != 0x2e || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x2e: // SWR + if( (nextcode>>26) != 0x2a || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x1a: // LDL + if( (nextcode>>26) != 0x1b || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x1b: // LWR + if( (nextcode>>26) != 0x1aa || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + + case 0x2c: // SWL + if( (nextcode>>26) != 0x2d || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x2d: // SWR + if( (nextcode>>26) != 0x2c || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + } + + // good enough + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + g_pCurInstInfo[0].numpeeps = 1; + g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; + g_pCurInstInfo++; + i += 4; + continue; + } + } + } +#endif // end peephole + } + + if( usecop2 ) { + // add necessary mac writebacks + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock-4; i += 4) { + g_pCurInstInfo++; + + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + } + } + } + } + + // perf counters // +#ifdef PCSX2_DEVBUILD + s_startcount = 0; +// if( pc+32 < s_nEndBlock ) { +// // only blocks with more than 8 insts +// //PUSH32I((u32)&lbase); +// //CALLFunc((u32)QueryPerformanceCounter); +// lbase.QuadPart = GetCPUTick(); +// s_startcount = 1; +// } +#endif + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (dumplog & 1) ) //|| usecop2 ) + iDumpBlock(startpc, recPtr); +#endif + + // finally recompile // + g_pCurInstInfo = s_pInstCache; + while (!branch && pc < s_nEndBlock) { + recompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (pc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (pc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 0); +// if( p[1].startpc == p[0].startpc + 4 ) { +// assert( p[1].pFnptr != 0 ); +// // already fn in place, so add to list +// AddBaseBlockEx(s_pCurBlockEx, 0); +// } +// else +// *(BASEBLOCKEX**)(p+1) = pex; +// } + + //PC_SETBLOCKEX(s_pCurBlock, s_pCurBlockEx); + + if( !(pc&0x10000000) ) + maxrecmem = max( (pc&~0xa0000000), maxrecmem ); + + if( branch == 2 ) { + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((u32)DispatcherReg - ( (u32)x86Ptr + 5 )); + } + else { + assert( branch != 3 ); + if( branch ) assert( !willbranch3 ); + else ADD32ItoM((int)&cpuRegs.cycle, s_nBlockCycles*9/8); + + if( willbranch3 ) { + BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); + assert( pc == s_nEndBlock ); + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((u32)&cpuRegs.pc, pc); + JMP32((u32)pblock->pFnptr - ((u32)x86Ptr + 5)); + branch = 3; + } + else if( !branch ) { + // didn't branch, but had to stop + MOV32ItoM( (u32)&cpuRegs.pc, pc ); + + iFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+REC_CACHEMEM ); + assert( recStackPtr < recStack+RECSTACK_SIZE ); + assert( x86FpuState == 0 ); + + recPtr = x86Ptr; + + assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); + + if( !branch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PC_GETBLOCK(pc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != pc ) + recRecompile(pc); + + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (u32)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R5900cpu recCpu = { + recInit, + recReset, + recStep, + recExecute, + recExecuteBlock, + recExecuteVU0Block, + recExecuteVU1Block, + recEnableVU0micro, + recEnableVU1micro, + recClear, + recClearVU0, + recClearVU1, + recShutdown +}; + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900Arit.c b/pcsx2/x86/ix86-32/iR5900Arit.c new file mode 100644 index 0000000..bda9ea2 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900Arit.c @@ -0,0 +1,2001 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +// NOTE: The reason ADD/SUB/etc are so large is because they are very commonly +// used and recompiler needs to cover ALL possible usages to minimize code size (zerofrog) + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#elif defined(EE_CONST_PROP) + +//// ADD +void recADD_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0]; +} + +void recADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] ) { + u32* ptempmem; + + ptempmem = _eeGetConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(vreg) ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, mmreg, vreg); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[ creg ].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(vreg) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[creg].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)_eeGetConstReg(creg)); + PADDDMtoR(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == vreg ) { + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( g_cpuConstRegs[ creg ].UL[0] ) + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[0] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +// s is constant +void recADD_consts(int info) +{ + recADD_constv(info, _Rs_, _Rt_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rt_); +} + +// t is constant +void recADD_constt(int info) +{ + recADD_constv(info, _Rt_, _Rs_); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); +} + +// nothing is constant +void recADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PADDDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDDRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDDRtoR(EEREC_D, EEREC_S); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PADDDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( _Rd_ == _Rs_ ) { + if( _Rd_ == _Rt_ ) SHL32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 1); // mult by 2 + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + } + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + + return; + } + else if( _Rd_ == _Rt_ ) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( _Rs_ != _Rt_ ) ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else SHL32ItoR(EAX, 1); // mult by 2 + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// ADDU +void recADDU( void ) +{ + recADD( ); +} + +//// DADD +void recDADD_const( void ) +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDADD_constv(int info, int creg, int vreg) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ creg ].UD[0] ) { + + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PADDQMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + if( g_cpuConstRegs[ creg ].UD[0] ) PADDQMtoR(mmreg, (u32)_eeGetConstReg(creg)); + } + else { + + if( g_cpuConstRegs[ creg ].UL[0] == 0 && g_cpuConstRegs[ creg ].UL[1] == 0 && _hasFreeMMXreg() ) { + // copy + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + if( EEINST_ISLIVE1(_Rd_) ) MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + else { + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + if( _Rd_ == vreg ) { + + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ creg ].UL[ 0 ] || g_cpuConstRegs[ creg ].UL[ 1 ]) ) { + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + ADC32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ creg ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + ADD32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ creg ].UL[ 0 ] ); + } + + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + ADD32ItoR( EAX, g_cpuConstRegs[ creg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32ItoR( EDX, g_cpuConstRegs[ creg ].UL[ 1 ] ); + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDADD_consts(int info) +{ + recDADD_constv(info, _Rs_, _Rt_); +} + +void recDADD_constt(int info) +{ + recDADD_constv(info, _Rt_, _Rs_); +} + +void recDADD_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PADDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PADDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_T); + PADDQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( _Rs_ != _Rt_ ) PADDQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else PSLLQItoR(mmreg, 1); // mult by 2 + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 1 ] ); + ADD32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT); + +//// DADDU +void recDADDU( void ) +{ + recDADD( ); +} + +//// SUB + +void recSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0]; +} + +void recSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rs_ ].UL[0] ) { + + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVDMtoMMX(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBDRtoR(EEREC_D, EEREC_T); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(t0reg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + } + else { + if( _Rd_ == _Rt_ ) { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) SUB32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rs_ ].UL[ 0 ]); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + NEG32R(EAX); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +void recSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + if( g_cpuConstRegs[ _Rt_ ].UL[0] ) { + + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBDMtoR(EEREC_D, (u32)ptempmem); + + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + // just move and sign extend + if( EEINST_HASLIVE1(_Rs_) ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + else { + _signExtendGPRMMXtoMMX(EEREC_D, _Rd_, EEREC_S, _Rs_); + } + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && (!EEINST_ISLIVE1(_Rd_) || !g_cpuConstRegs[_Rt_].UL[0]) ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + if( EEINST_HASLIVE1(_Rs_) && EEINST_ISLIVE1(_Rd_) ) { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[_Rt_].UL[0] ) { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PSUBDMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) { + _signExtendMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + else { + MOVDMtoMMX(mmreg, (u32)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } + else { + if( _Rd_ == _Rs_ ) { + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + SUB32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[ _Rt_ ].UL[ 0 ]); + + if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } + } +} + +void recSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rd_); + + if( info & PROCESS_EE_MMX ) { + + if( EEREC_D == EEREC_S ) PSUBDRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBDRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + info = (info&~PROCESS_EE_SET_D(0xf))|PROCESS_EE_SET_D(t0reg); + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBDRtoR(EEREC_D, EEREC_T); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + // sign extend + _signExtendGPRtoMMX(EEREC_D, _Rd_, 0); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && !EEINST_ISLIVE1(_Rd_)) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + EEINST_RESETHASLIVE1(_Rd_); + MOVDMtoMMX(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[0] ); + PSUBDMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[0] ); + } + else { + if( !EEINST_ISLIVE1(_Rd_) ) { + if( _Rd_ == _Rs_) { + EEINST_RESETHASLIVE1(_Rd_); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SUBU +void recSUBU( void ) +{ + recSUB( ); +} + +//// DSUB +void recDSUB_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0]; +} + +void recDSUB_consts(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rs_ ].UD[0] ) { + + // flush + if( EEREC_D != EEREC_T ) { + MOVQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (u32)_eeGetConstReg(_Rs_)); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + else { + // just move and sign extend + if( EEREC_D != EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + PSUBQRtoR(EEREC_D, EEREC_T); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (u32)_eeGetConstReg(_Rs_)); + PSUBQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( g_cpuConstRegs[ _Rs_ ].UL[ 0 ] || g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ) { + MOV32ItoR( EAX, g_cpuConstRegs[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoR( EDX, g_cpuConstRegs[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + + if( !EEINST_ISLIVE1(_Rd_) ) + EEINST_RESETHASLIVE1(_Rd_); + } + else { + + if( _Rd_ == _Rt_ ) { + // negate _Rt_ all in memory + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + NEG32M((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + ADC32ItoR(EDX, 0); + NEG32R(EDX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + NEG32M((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ]); + } + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + // take negative of 64bit number + NEG32R(EAX); + + if( EEINST_ISLIVE1(_Rd_) ) { + ADC32ItoR(EDX, 0); + NEG32R(EDX); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else { + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_constt(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( g_cpuConstRegs[ _Rt_ ].UD[0] ) { + + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PSUBQMtoR(EEREC_D, (u32)_eeGetConstReg(_Rt_)); + } + else { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( g_cpuConstRegs[_Rt_].UD[0] ) PSUBQMtoR(mmreg, (u32)_eeGetConstReg(_Rt_)); + } + else { + + if( _Rd_ == _Rs_ ) { + if( EEINST_ISLIVE1(_Rd_) && (g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ]) ) { + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + SBB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + else if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ) { + EEINST_RESETHASLIVE1(_Rd_); + SUB32ItoM( (u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + } + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if( g_cpuConstRegs[ _Rt_ ].UL[ 0 ] || g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ) { + SUB32ItoR( EAX, g_cpuConstRegs[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32ItoR( EDX, g_cpuConstRegs[ _Rt_ ].UL[ 1 ] ); + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recDSUB_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( EEREC_D == EEREC_S ) PSUBQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PSUBQRtoR(t0reg, EEREC_T); + + // swap mmx regs.. don't ask + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + MOVQRtoR(EEREC_D, EEREC_S); + PSUBQRtoR(EEREC_D, EEREC_T); + } + } + else { + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int mmreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rs_].UL[ 0 ]); + PSUBQMtoR(mmreg, (int)&cpuRegs.GPR.r[_Rt_].UL[ 0 ]); + } + else { + if( _Rd_ == _Rs_ ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + SUB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rd_) ) + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSUBU +void recDSUBU( void ) +{ + recDSUB( ); +} + +//// AND +void recAND_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0]; +} + +void recAND_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PANDMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + PXORRtoR(EEREC_D, EEREC_D); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PANDMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + else { + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + + if( _Rd_ == vreg ) { + AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] != 0xffffffff ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + AND32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) + AND32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + else { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ], 0); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, 0); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recAND_consts(int info) +{ + recAND_constv(info, _Rs_, _Rt_); +} + +void recAND_constt(int info) +{ + recAND_constv(info, _Rt_, _Rs_); +} + +void recLogicalOp(int info, int op) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( EEREC_D == EEREC_S ) LogicalOpRtoR(EEREC_D, EEREC_T, op); + else if( EEREC_D == EEREC_T ) LogicalOpRtoR(EEREC_D, EEREC_S, op); + else { + MOVQRtoR(EEREC_D, EEREC_S); + LogicalOpRtoR(EEREC_D, EEREC_T, op); + } + } + else if( (g_pCurInstInfo->regs[_Rs_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + int rsreg, rtreg, rdreg; + _addNeededMMXreg(MMX_GPR+_Rs_); + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + rsreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rs_, MODE_READ); + rtreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_READ); + SetMMXstate(); + + if( rdreg == rsreg ) { + if( rtreg >= 0 ) LogicalOpRtoR(rdreg, rtreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ], op); + } + else { + if( rdreg != rtreg ) { + if( rtreg >= 0 ) MOVQRtoR(rdreg, rtreg); + else MOVQMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rt_ ]); + } + + if( rsreg >= 0 ) LogicalOpRtoR(rdreg, rsreg, op); + else LogicalOpMtoR(rdreg, (int)&cpuRegs.GPR.r[ _Rs_ ], op); + } + } + else { + if( _Rd_ == _Rs_ || _Rd_ == _Rt_ ) { + int vreg = _Rd_ == _Rs_ ? _Rt_ : _Rs_; + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX, op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ] + 4, EDX, op ); + if( op == 3 ) { + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32M((int)&cpuRegs.GPR.r[ _Rd_ ]+4); + } + + if( !EEINST_ISLIVE1(_Rd_) ) EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ] + 4 ); + LogicalOp32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ], op ); + if( EEINST_ISLIVE1(_Rd_) ) + LogicalOp32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rt_ ] + 4, op ); + + if( op == 3 ) { + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + } + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } +} + +void recAND_(int info) +{ + recLogicalOp(info, 0); +} + +EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// OR +void recOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]; +} + +void recOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) OR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recOR_consts(int info) +{ + recOR_constv(info, _Rs_, _Rt_); +} + +void recOR_constt(int info) +{ + recOR_constv(info, _Rt_, _Rs_); +} + +void recOR_(int info) +{ + recLogicalOp(info, 1); +} + +EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// XOR +void recXOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0]; +} + +void recXOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + _flushConstReg(creg); + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PXORMtoR(EEREC_D, (u32)&cpuRegs.GPR.r[creg].UL[0] ); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + PXORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + } + } + else { + if( _Rd_ == vreg ) { + XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) XOR32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + + if( g_cpuConstRegs[ creg ].UL[0] ) XOR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) XOR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recXOR_consts(int info) +{ + recXOR_constv(info, _Rs_, _Rt_); +} + +void recXOR_constt(int info) +{ + recXOR_constv(info, _Rt_, _Rs_); +} + +void recXOR_(int info) +{ + recLogicalOp(info, 2); +} + +EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// NOR +void recNOR_const() +{ + g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]); +} + +void recNOR_constv(int info, int creg, int vreg) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + int mmreg = vreg == _Rt_ ? EEREC_T : EEREC_S; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( g_cpuConstRegs[ creg ].UL[0] || g_cpuConstRegs[ creg ].UL[1] ) { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + PORMtoR(EEREC_D, (u32)_eeGetConstReg(creg)); + } + else { + if( EEREC_D != mmreg ) MOVQRtoR(EEREC_D, mmreg); + } + + // take the NOT + PCMPEQDRtoR( t0reg,t0reg); + PXORRtoR( EEREC_D,t0reg); + _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) || (_Rd_ != vreg && _hasFreeMMXreg()) ) { + int rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[vreg].UL[0] ); + PCMPEQDRtoR( t0reg,t0reg); + if( g_cpuConstRegs[ creg ].UD[0] ) PORMtoR(rdreg, (u32)_eeGetConstReg(creg) ); + + // take the NOT + PXORRtoR( rdreg,t0reg); + + _freeMMXreg(t0reg); + } + else { + if( _Rd_ == vreg ) { + NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) NOT32M((int)&cpuRegs.GPR.r[ vreg ].UL[1]); + + if( g_cpuConstRegs[creg].UL[0] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[0], ~g_cpuConstRegs[creg].UL[0]); + if( EEINST_ISLIVE1(_Rd_) ) { + if( g_cpuConstRegs[creg].UL[1] ) AND32ItoM((int)&cpuRegs.GPR.r[ vreg ].UL[1], ~g_cpuConstRegs[creg].UL[1]); + } + else + EEINST_RESETHASLIVE1(_Rd_); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ vreg ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ vreg ] + 4 ); + if( g_cpuConstRegs[ creg ].UL[0] ) OR32ItoR(EAX, g_cpuConstRegs[ creg ].UL[0]); + if( g_cpuConstRegs[ creg ].UL[1] && EEINST_ISLIVE1(_Rd_) ) OR32ItoR(ECX, g_cpuConstRegs[ creg ].UL[1]); + NOT32R(EAX); + if( EEINST_ISLIVE1(_Rd_) ) + NOT32R(ECX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ], EAX); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ]+4, ECX); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } +} + +void recNOR_consts(int info) +{ + recNOR_constv(info, _Rs_, _Rt_); +} + +void recNOR_constt(int info) +{ + recNOR_constv(info, _Rt_, _Rs_); +} + +void recNOR_(int info) +{ + recLogicalOp(info, 3); +} + +EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SLT - test with silent hill, lemans +void recSLT_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0]; +} + +static u32 s_sltconst = 0x80000000; +static u32 s_sltconst64[2] = {0, 0x80000000}; +u32 s_sltone = 1; + +void recSLTs_consts(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( g_cpuConstRegs[_Rs_].UL[1] == (g_cpuConstRegs[_Rs_].SL[0]<0?0xffffffff:0) && EEINST_ISSIGNEXT(_Rt_) ) { + // just compare the lower values + if( sign ) { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDMtoR(EEREC_D, (u32)_eeGetConstReg(_Rs_)); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rs_].UL[0]^0x80000000; + ptempmem[1] = 0; + + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORMtoR(EEREC_D, (u32)&s_sltconst); + } + + PCMPGTDMtoR(EEREC_D, (u32)ptempmem); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + + // fall through + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + } + } + + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + j8Ptr[1] = JBE8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +// SLT with one operand coming from mem (compares only low 32 bits) +void recSLTmemconstt(int regd, int regs, u32 mem, int sign) +{ + // just compare the lower values + int t0reg; + + if( sign ) { + if( regd == regs ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, mem); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQMtoR(regd, mem); + PCMPGTDRtoR(regd, regs); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + } + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( regd == regs ) { + MOVQMtoR(t0reg, mem); + PXORMtoR(regs, (u32)&s_sltconst); + PCMPGTDRtoR(t0reg, regs); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[regd]; + mmxregs[regd].inuse = 0; + } + else { + MOVQRtoR(t0reg, regs); + MOVQMtoR(regd, mem); + PXORMtoR(t0reg, (u32)&s_sltconst); + PCMPGTDRtoR(regd, t0reg); + + PUNPCKLDQRtoR(regd, regd); + PSRLQItoR(regd, 63); + _freeMMXreg(t0reg); + } + } +} + +void recSLTs_constt(int info, int sign) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + if( _Rs_ == _Rt_ ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( EEINST_ISSIGNEXT(_Rs_) && g_cpuConstRegs[_Rt_].UL[1] == (g_cpuConstRegs[_Rt_].SL[0]<0?0xffffffff:0) ) { + // just compare the lower values + if( sign ) { + recSLTmemconstt(EEREC_D, EEREC_S, (u32)_eeGetConstReg(_Rt_), 1); + } + else { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = g_cpuConstRegs[_Rt_].UL[0]^0x80000000; + ptempmem[1] = 0; + + recSLTmemconstt(EEREC_D, EEREC_S, (u32)ptempmem, 0); + } + + return; + } + else { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + + // fall through + } + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + CMP32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLTs_(int info, int sign) +{ + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_D, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + + if( sign ) { + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + } + else { + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + } + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_D, EEREC_D); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLT_consts(int info) +{ + recSLTs_consts(info, 1); +} + +void recSLT_constt(int info) +{ + recSLTs_constt(info, 1); +} + +void recSLT_(int info) +{ + int t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 1); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 1); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + // just compare the lower values + if( EEREC_D == EEREC_S ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + PCMPGTDRtoR(t0reg, EEREC_S); + + PUNPCKLDQRtoR(t0reg, t0reg); + PSRLQItoR(t0reg, 63); + + // swap regs + mmxregs[t0reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PCMPGTDRtoR(EEREC_D, EEREC_S); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + } +} + +EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +// SLTU - test with silent hill, lemans +void recSLTU_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0]; +} + +void recSLTU_consts(int info) +{ + recSLTs_consts(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_constt(int info) +{ + recSLTs_constt(info, 0); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLTU_(int info) +{ + int t1reg; + + assert( !(info & PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rd_); + + if( !(info & PROCESS_EE_MMX) ) { + recSLTs_(info, 0); + return; + } + + if( EEREC_S == EEREC_T ) { + PXORRtoR(EEREC_D, EEREC_D); + return; + } + + if( !EEINST_ISSIGNEXT(_Rs_) || !EEINST_ISSIGNEXT(_Rt_) ) { + // need to compare total 64 bit value + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_D].mode |= MODE_WRITE; // in case EEREC_D was just flushed + recSLTs_(info, 0); + return; + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOVDMtoMMX(t1reg, (u32)&s_sltconst); + + if( EEREC_D == EEREC_S ) { + PXORRtoR(EEREC_S, t1reg); + PXORRtoR(t1reg, EEREC_T); + PCMPGTDRtoR(t1reg, EEREC_S); + + PUNPCKLDQRtoR(t1reg, t1reg); + PSRLQItoR(t1reg, 63); + + // swap regs + mmxregs[t1reg] = mmxregs[EEREC_D]; + mmxregs[EEREC_D].inuse = 0; + } + else { + if( EEREC_D != EEREC_T ) { + MOVDMtoMMX(EEREC_D, (u32)&s_sltconst); + PXORRtoR(t1reg, EEREC_S); + PXORRtoR(EEREC_D, EEREC_T); + } + else { + PXORRtoR(EEREC_D, t1reg); + PXORRtoR(t1reg, EEREC_S); + } + + PCMPGTDRtoR(EEREC_D, t1reg); + + PUNPCKLDQRtoR(EEREC_D, EEREC_D); + PSRLQItoR(EEREC_D, 63); + + _freeMMXreg(t1reg); + } +} + +EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + ADD32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + ADC32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) +{ + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + SUB32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SBB32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) +{ + if ( ! _Rd_ ) + { + return; + } + if ( ( _Rt_ == 0 ) || ( _Rs_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PANDRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + +} + +//////////////////////////////////////////////////// +void recOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0x0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0x0 ); + } + else if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } + else + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PORRtoR( MM0, MM1 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + } +} + +//////////////////////////////////////////////////// +void recXOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0x0); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0x0); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + MOVQMtoR( MM1, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0, MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recNOR( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ],0xffffffff); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ],0xffffffff); + return; + } + + if ( _Rs_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + if ( _Rt_ == 0 ) + { + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + PCMPEQDRtoR( MM1,MM1); + PORMtoR( MM0,(int)&cpuRegs.GPR.r[ _Rt_ ] ); + PXORRtoR( MM0,MM1); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ],MM0); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +// test with silent hill, lemans +void recSLT( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JG8( 0 ); + j8Ptr[2] = JL8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) +{ + MOV32ItoR(EAX, 1); + + if( _Rs_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0); + j8Ptr[0] = JA8( 0 ); + j8Ptr[2] = JB8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + j8Ptr[1] = JA8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else if( _Rt_ == 0 ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + else { + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + MOV32MtoR(ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + } + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900AritImm.c b/pcsx2/x86/ix86-32/iR5900AritImm.c new file mode 100644 index 0000000..a15fd8d --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900AritImm.c @@ -0,0 +1,663 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#elif defined(EE_CONST_PROP) + +//// ADDI +void recADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SL[0] + _Imm_; +} + +void recADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + EEINST_SETSIGNEXT(_Rt_); + EEINST_SETSIGNEXT(_Rs_); + + if( info & PROCESS_EE_MMX ) { + if( _Imm_ != 0 ) { + + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDDMtoR(EEREC_T, (u32)ptempmem); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(EEREC_T, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + + if( EEINST_ISLIVE1(_Rt_) ) + _signExtendGPRMMXtoMMX(EEREC_T, _Rt_, EEREC_S, _Rs_); + else + EEINST_RESETHASLIVE1(_Rt_); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && (_Rt_ != _Rs_) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + if( _Imm_ != 0 ) { + u32* ptempmem = recAllocStackMem(4, 4); + ptempmem[0] = _Imm_; + + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDDMtoR(rtreg, (u32)ptempmem); + + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + // just move and sign extend + if( !EEINST_HASLIVE1(_Rs_) ) { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendGPRtoMMX(rtreg, _Rt_, 0); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + } + } + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + if( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + else EEINST_RESETHASLIVE1(_Rt_); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rt_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, ADDI); + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI_const( void ) +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] + _Imm_; +} + +void recDADDI_(int info) +{ + assert( !(info&PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + assert( cpucaps.hasStreamingSIMD2Extensions ); + + if( _Imm_ != 0 ) { + + // flush + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + PADDQMtoR(EEREC_T, (u32)ptempmem); + } + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + int rtreg; + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _Imm_; + ptempmem[1] = _Imm_ >= 0 ? 0 : 0xffffffff; + + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + SetMMXstate(); + + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PADDQMtoR(rtreg, (u32)ptempmem); + } + else { + if( _Rt_ == _Rs_ ) { + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + ADC32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], _Imm_<0?0xffffffff:0); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + + if( EEINST_ISLIVE1(_Rt_) ) { + ADC32ItoR( EDX, _Imm_ < 0?0xffffffff:0); + } + } + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +EERECOMPILE_CODEX(eeRecompileCode1, DADDI); + +//// DADDIU +void recDADDIU( void ) +{ + recDADDI( ); +} + +//// SLTIU +void recSLTIU_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < (u64)(_Imm_); +} + +extern void recSLTmemconstt(int regd, int regs, u32 mem, int sign); +extern u32 s_sltone; + +void recSLTIU_(int info) +{ + if( info & PROCESS_EE_MMX ) { + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = ((s32)(_Imm_))^0x80000000; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 0); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTIU); + +//// SLTI +void recSLTI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < (s64)(_Imm_); +} + +void recSLTI_(int info) +{ + if( info & PROCESS_EE_MMX) { + + if( EEINST_ISSIGNEXT(_Rs_) ) { + u32* ptempmem = recAllocStackMem(8,4); + ptempmem[0] = _Imm_; + ptempmem[1] = 0; + recSLTmemconstt(EEREC_T, EEREC_S, (u32)ptempmem, 1); + EEINST_SETSIGNEXT(_Rt_); + return; + } + + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + mmxregs[EEREC_T].mode |= MODE_WRITE; // in case EEREC_T==EEREC_S + } + + // test silent hill if modding + if( info & PROCESS_EE_MMX ) MOVDMtoMMX(EEREC_T, (u32)&s_sltone); + else MOV32ItoR(EAX, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + if( info & PROCESS_EE_MMX ) PXORRtoR(EEREC_T, EEREC_T); + else XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + + if( !(info & PROCESS_EE_MMX) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + EEINST_SETSIGNEXT(_Rt_); +} + +EERECOMPILE_CODEX(eeRecompileCode1, SLTI); + +//// ANDI +void recANDI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & (s64)_ImmU_; +} + +extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op); +extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op); +extern void LogicalOp32RtoM(u32 to, x86IntRegType from, int op); +extern void LogicalOp32MtoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoR(x86IntRegType to, u32 from, int op); +extern void LogicalOp32ItoM(u32 to, u32 from, int op); + +void recLogicalOpI(int info, int op) +{ + if( info & PROCESS_EE_MMX ) { + SetMMXstate(); + + if( _ImmU_ != 0 ) { + u32* ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + LogicalOpMtoR(EEREC_T, (u32)ptempmem, op); + } + else { + if( op == 0 ) PXORRtoR(EEREC_T, EEREC_T); + else { + if( EEREC_T != EEREC_S ) MOVQRtoR(EEREC_T, EEREC_S); + } + } + return; + } + + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) && ((_Rt_ != _Rs_) || (_ImmU_==0)) ) { + int rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + u32* ptempmem; + + SetMMXstate(); + + ptempmem = recAllocStackMem(8, 8); + ptempmem[0] = _ImmU_; + ptempmem[1] = 0; + + if( op == 0 ) { + if ( _ImmU_ != 0 ) { + if( _ImmU_ == 0xffff ) { + // take a shortcut + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] - 2); + PSRLDItoR(rtreg, 16); + } + else { + MOVDMtoMMX(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + PANDMtoR(rtreg, (u32)ptempmem); + } + } + else PXORRtoR(rtreg, rtreg); + } + else { + MOVQMtoR(rtreg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + if ( _ImmU_ != 0 ) LogicalOpMtoR(rtreg, (u32)ptempmem, op); + } + } + else { + if ( _ImmU_ != 0 ) + { + if( _Rt_ == _Rs_ ) { + LogicalOp32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_, op); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + LogicalOp32ItoR( EAX, _ImmU_, op); + if( op != 0 && EEINST_ISLIVE1(_Rt_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + + if( op == 0 ) { + if( EEINST_ISLIVE1(_Rt_ ) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rt_); + } + } + else + { + if( op == 0 ) { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + } + else { + if( _Rt_ != _Rs_ ) { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rt_ ) ) + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + } + } + + if( !EEINST_ISLIVE1(_Rt_) ) EEINST_RESETHASLIVE1(_Rt_); + } + } +} + +void recANDI_(int info) +{ + recLogicalOpI(info, 0); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ANDI); + +//////////////////////////////////////////////////// +void recORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | (s64)_ImmU_; +} + +void recORI_(int info) +{ + recLogicalOpI(info, 1); +} + +EERECOMPILE_CODEX(eeRecompileCode1, ORI); + +//////////////////////////////////////////////////// +void recXORI_const() +{ + g_cpuConstRegs[_Rt_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ (s64)_ImmU_; +} + +void recXORI_(int info) +{ + recLogicalOpI(info, 2); +} + +EERECOMPILE_CODEX(eeRecompileCode1, XORI); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) +{ +#ifdef __x86_64_ + if ( ! _Rt_ ) + { + return; + } + + MOV64MtoR( RAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +#else + if ( ! _Rt_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + if ( _Imm_ < 0 ) + { + ADC32ItoR( EDX, 0xffffffff ); + } + else + { + ADC32ItoR( EDX, 0 ); + } + } + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +#endif +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) + return; + + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JB8( 0 ); + j8Ptr[2] = JA8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + return; + + // test silent hill if modding + MOV32ItoR(EAX, 1); + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], _Imm_ >= 0 ? 0 : 0xffffffff); + j8Ptr[0] = JL8( 0 ); + j8Ptr[2] = JG8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], (s32)_Imm_ ); + j8Ptr[1] = JB8(0); + + x86SetJ8(j8Ptr[2]); + XOR32RtoR(EAX, EAX); + + x86SetJ8(j8Ptr[0]); + x86SetJ8(j8Ptr[1]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); +} + +//////////////////////////////////////////////////// +void recANDI( void ) +{ + if ( ! _Rt_ ) + { + return; + } + if ( _ImmU_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } + +} + +//////////////////////////////////////////////////// +static u64 _imm = 0; // temp immediate + +void recORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recXORI( void ) +{ + if ( ! _Rt_ ) + return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + if ( _ImmU_ != 0 ) + { + MOV32ItoM( (int)&_imm, _ImmU_ ); + MOVQMtoR( MM1, (int)&_imm ); + PXORRtoR( MM0, MM1 ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rt_ ], MM0 ); + SetMMXstate(); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900Branch.c b/pcsx2/x86/ix86-32/iR5900Branch.c new file mode 100644 index 0000000..40991c0 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900Branch.c @@ -0,0 +1,1093 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + +#if defined(EE_CONST_PROP) + +void recSetBranchEQ(int info, int bne, int process) +{ + if( info & PROCESS_EE_MMX ) { + int t0reg; + + SetMMXstate(); + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + if( t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + PCMPEQDMtoR(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeMMXreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rs_) ) { + _deleteMMXreg(_Rs_, 1); + mmxregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + PCMPEQDRtoR(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { + _deleteMMXreg(_Rt_, 1); + mmxregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + PCMPEQDRtoR(t0reg, EEREC_S); + } + else { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, EEREC_S); + PCMPEQDRtoR(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeMMXreg(t0reg); + } + + PMOVMSKBMMXtoR(EAX, t0reg); + + _eeFlushAllUnused(); + + CMP8ItoR( EAX, 0xff ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( info & PROCESS_EE_XMM ) { + int t0reg; + + if( process & PROCESS_CONSTS ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_T); + } + + _flushConstReg(_Rs_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + + + if( t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + else if( process & PROCESS_CONSTT ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + } + + _flushConstReg(_Rt_); + SSE2_PCMPEQD_M128_to_XMM(t0reg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + + if( t0reg != EEREC_S ) _freeXMMreg(t0reg); + } + else { + + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _deleteGPRtoXMMreg(_Rs_, 1); + xmmregs[EEREC_S].inuse = 0; + t0reg = EEREC_S; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + else if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_) ) { + _deleteGPRtoXMMreg(_Rt_, 1); + xmmregs[EEREC_T].inuse = 0; + t0reg = EEREC_T; + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_S); + } + else { + t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE2_MOVQ_XMM_to_XMM(t0reg, EEREC_S); + SSE2_PCMPEQD_XMM_to_XMM(t0reg, EEREC_T); + } + + if( t0reg != EEREC_S && t0reg != EEREC_T ) _freeXMMreg(t0reg); + } + + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _eeFlushAllUnused(); + + AND8ItoR(EAX, 3); + CMP8ItoR( EAX, 0x3 ); + + if( bne ) j32Ptr[ 1 ] = JE32( 0 ); + else j32Ptr[ 0 ] = j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + + _eeFlushAllUnused(); + + if( bne ) { + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + } + + x86SetJ8( j8Ptr[0] ); + } + else { + // beq + if( process & PROCESS_CONSTS ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else if( process & PROCESS_CONSTT ) { + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + } + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +void recSetBranchL(int ltz) +{ + int regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + SetMMXstate(); + + PXORRtoR(t0reg, t0reg); + PCMPGTDRtoR(t0reg, regs); + PMOVMSKBMMXtoR(EAX, t0reg); + + _freeMMXreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 0x80 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + + if( regs >= 0 ) { + + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + SSE_XORPS_XMM_to_XMM(t0reg, t0reg); + SSE2_PCMPGTD_XMM_to_XMM(t0reg, regs); + SSE_MOVMSKPS_XMM_to_R32(EAX, t0reg); + + _freeXMMreg(t0reg); + _eeFlushAllUnused(); + + TEST8ItoR( EAX, 2 ); + + if( ltz ) j32Ptr[ 0 ] = JZ32( 0 ); + else j32Ptr[ 0 ] = JNZ32( 0 ); + + return; + } + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + if( ltz ) j32Ptr[ 0 ] = JGE32( 0 ); + else j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); +} + +//// BEQ +void recBEQ_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBEQ_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +void recBEQ_(int info) { recBEQ_process(info, 0); } +void recBEQ_consts(int info) { recBEQ_process(info, PROCESS_CONSTS); } +void recBEQ_constt(int info) { recBEQ_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQ, XMMINFO_READS|XMMINFO_READT); + +//// BNE +void recBNE_const() +{ + u32 branchTo; + + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) + branchTo = ((s32)_Imm_ * 4) + pc; + else + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); +} + +void recBNE_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + recSetBranchEQ(info, 1, process); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +void recBNE_(int info) { recBNE_process(info, 0); } +void recBNE_consts(int info) { recBNE_process(info, PROCESS_CONSTS); } +void recBNE_constt(int info) { recBNE_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNE, XMMINFO_READS|XMMINFO_READT); + +//// BEQL +void recBEQL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] == g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBEQL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +void recBEQL_(int info) { recBEQL_process(info, 0); } +void recBEQL_consts(int info) { recBEQL_process(info, PROCESS_CONSTS); } +void recBEQL_constt(int info) { recBEQL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BEQL, XMMINFO_READS|XMMINFO_READT); + +//// BNEL +void recBNEL_const() +{ + if( g_cpuConstRegs[_Rs_].SD[0] != g_cpuConstRegs[_Rt_].SD[0] ) { + u32 branchTo = ((s32)_Imm_ * 4) + pc; + recompileNextInstruction(1); + SetBranchImm(branchTo); + } + else { + SetBranchImm( pc+4 ); + } +} + +void recBNEL_process(int info, int process) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + recSetBranchEQ(info, 0, process); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +void recBNEL_(int info) { recBNEL_process(info, 0); } +void recBNEL_consts(int info) { recBNEL_process(info, PROCESS_CONSTS); } +void recBNEL_constt(int info) { recBNEL_process(info, PROCESS_CONSTT); } + +EERECOMPILE_CODE0(BNEL, XMMINFO_READS|XMMINFO_READT); + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +//void recBLTZAL( void ) +//{ +// SysPrintf("BLTZAL\n"); +// _eeFlushAllUnused(); +// MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (int)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (int)BLTZAL ); +// branch = 2; +//} + +//////////////////////////////////////////////////// +void recBLTZAL(int info) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + SysPrintf("BLTZAL\n"); + _eeOnWriteReg(31, 0); + _eeFlushAllUnused(); + + _deleteEEreg(31, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[0], pc+4); + MOV32ItoM((u32)&cpuRegs.GPR.r[31].UL[1], 0); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + _eeFlushAllUnused(); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#else + + +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + CMP32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j32Ptr[ 1 ] = JE32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 0 ] = JNE32( 0 ); + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CMP32RtoR( ECX, EDX ); + j32Ptr[ 1 ] = JNE32( 0 ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + x86SetJ32( j32Ptr[ 1 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (int)BGEZALL ); + branch = 2; +} + +#endif + +//// BLEZ +void recBLEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JL8( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//// BGTZ +void recBGTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j8Ptr[ 0 ] = JG8( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ8( j8Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZ() +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JL32( 0 ); + j32Ptr[ 1 ] = JG32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JNZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], 0 ); + j32Ptr[ 0 ] = JG32( 0 ); + j32Ptr[ 1 ] = JL32( 0 ); + + CMP32ItoM( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], 0 ); + j32Ptr[ 2 ] = JZ32( 0 ); + + x86SetJ32( j32Ptr[ 0 ] ); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 1 ] ); + x86SetJ32( j32Ptr[ 2 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(1); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + recSetBranchL(0); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900Jump.c b/pcsx2/x86/ix86-32/iR5900Jump.c new file mode 100644 index 0000000..e28f28e --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900Jump.c @@ -0,0 +1,136 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +// recompiler reworked to add dynamic linking zerofrog(@gmail.com) Jan06 + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + // SET_FPUSTATE; + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + _deleteEEreg(31, 0); + GPR_SET_CONST(31); + g_cpuConstRegs[31].UL[0] = pc + 4; + g_cpuConstRegs[31].UL[1] = 0; + + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, _Rs_); + // uncomment when there are NO instructions that need to call interpreter +// int mmreg; +// if( GPR_IS_CONST1(_Rs_) ) +// MOV32ItoM( (u32)&cpuRegs.pc, g_cpuConstRegs[_Rs_].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((u32)&cpuRegs.pc, mmreg); +// } +// else if( (mmreg = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ)) >= 0 ) { +// MOVDMMXtoM((u32)&cpuRegs.pc, mmreg); +// SetMMXstate(); +// } +// else { +// MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// MOV32RtoM((u32)&cpuRegs.pc, EAX); +// } +// } + + if ( _Rd_ ) + { + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + g_cpuConstRegs[_Rd_].UL[0] = pc + 4; + g_cpuConstRegs[_Rd_].UL[1] = 0; + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + + SetBranchReg(0xffffffff); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900LoadStore.c b/pcsx2/x86/ix86-32/iR5900LoadStore.c new file mode 100644 index 0000000..48807c9 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900LoadStore.c @@ -0,0 +1,4297 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +void SetFastMemory(int bSetFast) {} + +#else + +PCSX2_ALIGNED16(u64 retValues[2]); +extern u32 maxrecmem; +static u32 s_bCachingMem = 0; +static u32 s_nAddMemOffset = 0; +static u32 s_tempaddr = 0; + +void _eeOnLoadWrite(int reg) +{ + int regt; + + if( !reg ) return; + + _eeOnWriteReg(reg, 1); + regt = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ); + + if( regt >= 0 ) { + if( xmmregs[regt].mode & MODE_WRITE ) { + if( cpucaps.hasStreamingSIMD2Extensions && (reg != _Rs_) ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(regt, regt); + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + else SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[reg].UL[2], regt); + } + xmmregs[regt].inuse = 0; + } +} + +#ifdef PCSX2_VIRTUAL_MEM + +extern void iMemRead32Check(); + +#define _Imm_co_ (*(s16*)PSM(pc)) + +// perf counters +#ifdef PCSX2_DEVBUILD +extern void StartPerfCounter(); +extern void StopPerfCounter(); +#else +#define StartPerfCounter() +#define StopPerfCounter() +#endif + +//////////////////////////////////////////////////// +//#define REC_SLOWREAD +//#define REC_SLOWWRITE +#define REC_FORCEMMX 0 + +// if sp, always mem write +int _eeIsMemWrite() { return _Rs_==29||_Rs_== 31||_Rs_==26||_Rs_==27; } // sp, ra, k0, k1 +// gp can be 1000a020 (jak1) + +void recTransferX86ToReg(int x86reg, int gprreg, int sign) +{ + //if( !REC_FORCEMMX ) assert( _checkMMXreg(MMX_GPR+gprreg, MODE_WRITE) == -1 ); + if( sign ) { + if( x86reg == EAX && EEINST_ISLIVE1(gprreg) ) CDQ(); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + + if(EEINST_ISLIVE1(gprreg)) { + if( x86reg == EAX ) MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], EDX ); + else { + SAR32ItoR(x86reg, 31); + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], x86reg ); + } + } + else { + EEINST_RESETHASLIVE1(gprreg); + } + } + else { + MOV32RtoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], x86reg ); + if(EEINST_ISLIVE1(gprreg)) MOV32ItoM( (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(gprreg); + } +} + +#ifdef _DEBUG +void testaddrs() +{ + register int tempaddr; + + __asm mov tempaddr, ecx + //__asm mov incaddr, edx + + assert( (tempaddr < 0x40000000) || (tempaddr&0xd0000000)==0x50000000 || (tempaddr >= 0x80000000 && tempaddr < 0xc0000000) ); + //assert( (tempaddr>>28) == ((tempaddr+incaddr)>>28) ); + + __asm mov ecx, tempaddr +} +#endif + +#define SET_HWLOC() { \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[2]); \ + else x86SetJ8(j8Ptr[0]); \ + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[3]); \ + else x86SetJ8(j8Ptr[3]); \ + if (x86FpuState==MMX_STATE) { \ + if (cpucaps.has3DNOWInstructionExtensions) FEMMS(); \ + else EMMS(); \ + } \ + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); \ + if( s_bCachingMem & 4 ) AND32ItoR(ECX, 0x5fffffff); \ +} \ + +static u16 g_MemMasks0[16] = {0x00f0, 0x80f1, 0x00f2, 0x00f3, + 0x00f1, 0x00f5, 0x00f1, 0x00f5, + 0x00f5, 0x80f5, 0x00f5, 0x80f5, + 0x00f1, 0x00f1, 0x00f1, 0x00f5 }; +static u16 g_MemMasks8[16] = {0x0080, 0x8081, 0x0082, 0x0083, + 0x0081, 0x0085, 0x0081, 0x0085, + 0x0085, 0x8085, 0x0085, 0x8085, + 0x0081, 0x0081, 0x0081, 0x0085 }; +static u16 g_MemMasks16[16] ={0x0000, 0x8001, 0x0002, 0x0003, + 0x0001, 0x0005, 0x0001, 0x0005, + 0x0005, 0x8005, 0x0005, 0x8005, + 0x0001, 0x0001, 0x0001, 0x0005 }; + +static int s_bFastMemory = 0; +void SetFastMemory(int bSetFast) +{ + s_bFastMemory = bSetFast; + if( bSetFast) { + g_MemMasks0[0] = 0x00f0; g_MemMasks0[1] = 0x80f1; g_MemMasks0[2] = 0x00f0; g_MemMasks0[3] = 0x00f1; + g_MemMasks8[0] = 0x0080; g_MemMasks8[1] = 0x8081; g_MemMasks8[2] = 0x0080; g_MemMasks8[3] = 0x0081; + g_MemMasks16[0] = 0x0000; g_MemMasks16[1] = 0x8001; g_MemMasks16[2] = 0x0000; g_MemMasks16[3] = 0x0001; + } + else { + g_MemMasks0[0] = 0x00f0; g_MemMasks0[1] = 0x80f1; g_MemMasks0[2] = 0x00f2; g_MemMasks0[3] = 0x00f3; + g_MemMasks8[0] = 0x0080; g_MemMasks8[1] = 0x8081; g_MemMasks8[2] = 0x0082; g_MemMasks8[3] = 0x0083; + g_MemMasks16[0] = 0x0000; g_MemMasks16[1] = 0x8001; g_MemMasks16[2] = 0x0002; g_MemMasks16[3] = 0x0003; + } +} + +void assertmem() +{ + __asm mov s_tempaddr, ecx + __asm mov s_bCachingMem, edx + SysPrintf("%x(%x) not mem write!\n", s_tempaddr, s_bCachingMem); + assert(0); +} + +int _eePrepareReg(int gprreg) +{ + int mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + + if( mmreg >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + mmreg |= MEM_XMMTAG; + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + if( mmxregs[mmreg].mode&MODE_WRITE ) mmreg |= MEM_MMXTAG; + else { + mmxregs[mmreg].needed = 0; // coX can possibly use all regs + mmreg = 0; + } + } + else { + mmreg = 0; + } + + return mmreg; +} + +int _eePrepareReg_coX(int gprreg, int num) +{ + int mmreg = _eePrepareReg(gprreg); + + if( (mmreg&MEM_MMXTAG) && num == 7 ) { + if( mmxregs[mmreg&0xf].mode & MODE_WRITE ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[gprreg], mmreg&0xf); + mmxregs[mmreg&0xf].mode &= ~MODE_WRITE; + mmxregs[mmreg&0xf].needed = 0; + } + } + + return mmreg; +} + +// returns true if should also include harware writes +int recSetMemLocation(int regs, int imm, int mmreg, int msize, int j32) +{ + s_bCachingMem = j32 ? 2 : 0; + s_nAddMemOffset = 0; + + //int num; + if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) { + SSE2_MOVD_XMM_to_R(ECX, mmreg&0xf); + } + else if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) { + MOVD32MMXtoR(ECX, mmreg&0xf); + SetMMXstate(); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ regs ].UL[ 0 ] ); + } + + if ( imm != 0 ) ADD32ItoR( ECX, imm ); + + LoadCW(); + +#ifdef _DEBUG + //CALLFunc((u32)testaddrs); +#endif + + + // 32bit version (faster?) +// MOV32RtoR(EAX, ECX); +// ROR32ItoR(ECX, 28); +// SHR32ItoR(EAX, 28); +// MOV32RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 2); +// AND8RtoR(ECX, EAX); +// ROR32ItoR(ECX, 4); +// // do extra alignment masks here +// OR32RtoR(EAX, EAX); + + if( _eeIsMemWrite() ) { + u8* ptr; + CMP32ItoR(ECX, 0x40000000); + ptr = JB8(0); + if( msize == 1 ) AND32ItoR(ECX, 0x5ffffff8); + else if( msize == 2 ) AND32ItoR(ECX, 0x5ffffff0); + else AND32ItoR(ECX, 0x5fffffff); + x86SetJ8(ptr); + if( msize == 1 ) AND8ItoR(ECX, 0xf8); + else if( msize == 2 ) AND8ItoR(ECX, 0xf0); +#ifdef _DEBUG + MOV32RtoR(EAX, ECX); + SHR32ItoR(EAX, 28); + CMP32ItoR(EAX, 1); + ptr = JNE8(0); + MOV32ItoR(EDX, _Rs_); + CALLFunc((u32)assertmem); + x86SetJ8(ptr); +#endif + return 0; + } + else { + // 16 bit version + MOV32RtoR(EAX, ECX); + ROR32ItoR(ECX, 28); + SHR32ItoR(EAX, 28); + MOV16RmSOffsettoR(EAX, EAX, msize == 2 ? (u32)&g_MemMasks16[0] : (msize == 1 ? (u32)&g_MemMasks8[0] : (u32)&g_MemMasks0[0]), 1); + AND8RtoR(ECX, EAX); + ROR32ItoR(ECX, 4); + + OR16RtoR(EAX, EAX); + + if( s_bCachingMem & 2 ) j32Ptr[2] = j32Ptr[3] = JS32(0); + else j8Ptr[0] = j8Ptr[3] = JS8(0); + } + + return 1; +} + + +void recLoad32(u32 bit, u32 imm, u32 sign) +{ + int mmreg = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // do const processing + int ineax = 0; + + _eeOnLoadWrite(_Rt_); + if( bit == 32 ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_MMXTAG; + else mmreg = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + mmreg = EAX; + } + + switch(bit) { + case 8: ineax = recMemConstRead8(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); break; + case 16: + assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 2 == 0 ); + ineax = recMemConstRead16(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm, sign); + break; + case 32: + // used by LWL/LWR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 4 == 0 ); + ineax = recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+imm); + break; + } + + if( ineax || !(mmreg&MEM_MMXTAG) ) { + if( mmreg&MEM_MMXTAG ) mmxregs[mmreg&0xf].inuse = 0; + recTransferX86ToReg(EAX, _Rt_, sign); + } + else { + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + + if( REC_FORCEMMX ) mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + else _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, imm, mmregs, 0, 0); + + if( mmreg >= 0 ) { + MOVD32RmOffsettoMMX(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset-(32-bit)/8); + if( sign ) _signExtendGPRtoMMX(mmreg&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg&0xf, 32-bit); + } + else { + switch(bit) { + case 8: + if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 16: + if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + case 32: + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + else MOVZX32R8toR(EAX, EAX); + break; + case 16: + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + else MOVZX32R16toR(EAX, EAX); + break; + case 32: + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + if( mmreg >= 0 ) { + if( EEINST_ISLIVE1(_Rt_) ) MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[_Rt_]); + else MOVD32RtoMMX(mmreg, EAX); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLoad32_co(u32 bit, u32 sign) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax = 0; + u32 written = 0; + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + + if( bit == 32 ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_MMXTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_MMXTAG; + else mmreg2 = EAX; + } + else { + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + mmreg1 = EBX; + mmreg2 = EAX; + } + + // do const processing + switch(bit) { + case 8: + if( recMemConstRead8(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead8(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 16: + if( recMemConstRead16(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_, sign) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead16(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, sign); + break; + case 32: + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_MMXTAG ) mmxregs[mmreg1&0xf].inuse = 0; + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + break; + } + + if( !written && _Rt_ ) { + if( mmreg1&MEM_MMXTAG ) { + assert( mmxregs[mmreg1&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg1&0xf, _Rt_, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg1&0xf, 32-bit); + } + else recTransferX86ToReg(mmreg1, _Rt_, sign); + } + if( nextrt ) { + g_pCurInstInfo++; + if( !ineax && (mmreg2 & MEM_MMXTAG) ) { + assert( mmxregs[mmreg2&0xf].mode & MODE_WRITE ); + if( sign ) _signExtendGPRtoMMX(mmreg2&0xf, nextrt, 32-bit); + else if( bit < 32 ) PSRLDItoR(mmreg2&0xf, 32-bit); + } + else { + if( mmreg2&MEM_MMXTAG ) mmxregs[mmreg2&0xf].inuse = 0; + recTransferX86ToReg(mmreg2, nextrt, sign); + } + g_pCurInstInfo--; + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + assert( !REC_FORCEMMX ); + + _eeOnLoadWrite(_Rt_); + _eeOnLoadWrite(nextrt); + _deleteEEreg(_Rt_, 0); + _deleteEEreg(nextrt, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + switch(bit) { + case 8: + if( sign ) { + MOVSX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm8toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 16: + if( sign ) { + MOVSX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOVZX32Rm16toROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + break; + case 32: + MOV32RmtoROffset(EBX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + break; + } + + if ( _Rt_ ) recTransferX86ToReg(EBX, _Rt_, sign); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + switch(bit) { + case 8: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead8 ); + if( sign ) MOVSX32R8toR(EAX, EAX); + break; + case 16: + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead16 ); + if( sign ) MOVSX32R16toR(EAX, EAX); + break; + case 32: + MOV32RtoM((u32)&s_tempaddr, ECX); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + MOV32MtoR(ECX, (u32)&s_tempaddr); + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, sign); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + break; + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( nextrt ) { + g_pCurInstInfo++; + recTransferX86ToReg(EAX, nextrt, sign); + g_pCurInstInfo--; + } + } +} + +void recLB( void ) { recLoad32(8, _Imm_, 1); } +void recLB_co( void ) { recLoad32_co(8, 1); } +void recLBU( void ) { recLoad32(8, _Imm_, 0); } +void recLBU_co( void ) { recLoad32_co(8, 0); } +void recLH( void ) { recLoad32(16, _Imm_, 1); } +void recLH_co( void ) { recLoad32_co(16, 1); } +void recLHU( void ) { recLoad32(16, _Imm_, 0); } +void recLHU_co( void ) { recLoad32_co(16, 0); } +void recLW( void ) { recLoad32(32, _Imm_, 1); } +void recLW_co( void ) { recLoad32_co(32, 1); } +void recLWU( void ) { recLoad32(32, _Imm_, 0); } +void recLWU_co( void ) { recLoad32_co(32, 0); } + +//////////////////////////////////////////////////// + +// paired with LWR +void recLWL_co(void) { recLoad32(32, _Imm_-3, 1); } + +void recLWL( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, 24-shift*8); + AND32ItoR(ECX, (0xffffff>>(shift*8))); + OR32RtoR(EAX, ECX); + + if ( _Rt_ ) recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) { + // mem << LWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHL32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff); + SAR32CLtoR(EDX); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(EDX, ECX); + + // combine + OR32RtoR(EAX, EDX); + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// + +// paired with LWL +void recLWR_co(void) { recLoad32(32, _Imm_, 1); } + +void recLWR( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + if( _Rt_ ) { + u32 shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + _eeMoveGPRtoR(ECX, _Rt_); + SHL32ItoR(EAX, shift*8); + AND32ItoR(ECX, (0xffffff00<<(24-shift*8))); + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + iMemRead32Check(); + + PUSH32R(ECX); + AND32ItoR(ECX, ~3); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + + x86SetJ8(j8Ptr[1]); + } + + if ( _Rt_ ) + { + // mem << LWL_SHIFT[shift] + MOV32RtoR(ECX, EDX); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 3); // *8 + SHR32CLtoR(EAX); + + // mov temp and compute _rt_ & LWL_MASK[shift] + MOV32RtoR(EDX, ECX); + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + _eeMoveGPRtoR(ECX, _Rt_); + AND32RtoR(ECX, EDX); + + // combine + OR32RtoR(EAX, ECX); + + recTransferX86ToReg(EAX, _Rt_, 1); + } + } +} + +//////////////////////////////////////////////////// +void recLoad64(u32 imm, int align) +{ + int mmreg; + int mask = align ? ~7 : ~0; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + // also used by LDL/LDR + //assert( (g_cpuConstRegs[_Rs_].UL[0]+imm) % 8 == 0 ); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg); + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + if( !_hasFreeMMXreg() && _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ|MODE_WRITE); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, mmreg|0x8000); + assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + recMemConstRead64((g_cpuConstRegs[_Rs_].UL[0]+imm)&mask, t0reg); + + if( _Rt_ ) { + SetMMXstate(); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UD[0], t0reg); + } + + _freeMMXreg(t0reg); + } + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( _Rt_ && mmreg >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + MOVQRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + + SetMMXstate(); + } + else if( _Rt_ && (mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ)) >= 0 ) { + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + SSE_MOVLPSRmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + SSE_MOVLPS_M64_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + ADD32ItoR(ESP, 4); + } + } + else { + int t0reg = _Rt_ ? _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE) : -1; + + dohw = recSetMemLocation(_Rs_, imm, mmregs, align, 0); + + if( t0reg >= 0 ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + SetMMXstate(); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + if( _Rt_ ) { + //_deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + ADD32ItoR(ESP, 4); + + if( t0reg >= 0 ) MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); +} + +void recLD(void) { recLoad64(_Imm_, 1); } + +void recLD_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLD(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int mmreg1 = -1, mmreg2 = -1, t0reg = -1, t1reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + if( nextrt ) _eeOnWriteReg(nextrt, 0); + + if( _Rt_ ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 < 0 ) { + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg1 >= 0 ) mmreg1 |= 0x8000; + } + + if( mmreg1 < 0 && _hasFreeMMXreg() ) mmreg1 = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE); + } + + if( nextrt ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 < 0 ) { + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE|MODE_READ); + if( mmreg2 >= 0 ) mmreg2 |= 0x8000; + } + + if( mmreg2 < 0 && _hasFreeMMXreg() ) mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_WRITE); + } + + if( mmreg1 < 0 || mmreg2 < 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( mmreg1 < 0 && mmreg2 < 0 && _hasFreeMMXreg() ) { + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + else t1reg = t0reg; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 1, 0); + + if( mmreg1 >= 0 ) { + if( mmreg1 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _Rt_ ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], t0reg); + } + } + + if( mmreg2 >= 0 ) { + if( mmreg2 & 0x8000 ) SSE_MOVLPSRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + else MOVQRmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( nextrt ) { + MOVQRmtoROffset(t1reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ], t1reg); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg1 >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg1 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg1, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + if( _Rt_ ) { + _deleteEEreg(_Rt_, 0); + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else PUSH32I( (int)&retValues[0] ); + + CALLFunc( (int)recMemRead64 ); + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + + if( mmreg2 >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + + if( mmreg2 & 0x8000 ) SSE_MOVLPS_M64_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + else MOVQMtoR(mmreg2, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ]); + } + else { + if( nextrt ) { + _deleteEEreg(nextrt, 0); + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[ nextrt ].UD[ 0 ], 0 ); + } + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead64 ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + if( mmreg1 < 0 || mmreg2 < 0 || !(mmreg1&0x8000) || !(mmreg2&0x8000) ) SetMMXstate(); + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + if( t0reg != t1reg && t1reg >= 0 ) _freeMMXreg(t1reg); + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +void recLD_coX( int num ) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLD(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLD(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + if( _Rt_ ) _eeOnWriteReg(_Rt_, 0); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _eeOnWriteReg(nextrts[i], 0); + } + + if( _Rt_ ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg < 0 ) { + mmreg = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE|MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + } + else mmreg |= MEM_MMXTAG; + } + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckGPRtoMMX(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + if( mmregs[i] < 0 ) { + mmregs[i] = _allocCheckGPRtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE|MODE_READ); + if( mmregs[i] >= 0 ) mmregs[i] |= MEM_XMMTAG; + else mmregs[i] = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_WRITE)|MEM_MMXTAG; + } + else mmregs[i] |= MEM_MMXTAG; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 1, 0); + + if( mmreg >= 0 ) { + if( mmreg & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + else MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + u32 off = PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + + if( mmregs[i] >= 0 ) { + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPSRmtoROffset(mmregs[i]&0xf, ECX, off); + else MOVQRmtoROffset(mmregs[i]&0xf, ECX, off); + } + } + + if( dohw ) { + if( (s_bCachingMem & 2) || num > 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( mmreg >= 0 ) { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc( (int)recMemRead64 ); + + if( mmreg & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + else MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ]); + } + else { + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead64 ); + } + + for(i = 0; i < num; ++i ) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( mmregs[i] >= 0 ) { + MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + CALLFunc( (int)recMemRead64 ); + + if( mmregs[i] & MEM_XMMTAG ) SSE_MOVLPS_M64_to_XMM(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + else MOVQMtoR(mmregs[i]&0xf, (int)&cpuRegs.GPR.r[ nextrts[i] ].UD[ 0 ]); + } + else { + MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead64 ); + } + } + + ADD32ItoR(ESP, 4); + + if( (s_bCachingMem & 2) || num > 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + + _clearNeededMMXregs(); + _clearNeededXMMregs(); + } +} + +//////////////////////////////////////////////////// +void recLDL_co(void) { + recLoad64(_Imm_-7, 0); } + +void recLDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR_co(void) { recLoad64(_Imm_, 0); } + +void recLDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + else { + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + } + + if( _Rt_ ) + _deleteEEreg(_Rt_, _Rt_==_Rs_); + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + int mmreg = -1; +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + // malice hits this + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Rt_ ) { + if( (g_pCurInstInfo->regs[_Rt_]&EEINST_XMM) || !(g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) ) { + _deleteMMXreg(MMX_GPR+_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + else { + int t0reg; + _deleteGPRtoXMMreg(_Rt_, 2); + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_WRITE)|MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + mmreg |= t0reg<<4; + } + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + } + + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + if( !_Rt_ ) _freeXMMreg(mmreg); + if( IS_MMXREG(mmreg) ) { + // flush temp + assert( mmxregs[mmreg&0xf].mode & MODE_WRITE ); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], (mmreg>>4)&0xf); + _freeMMXreg((mmreg>>4)&0xf); + } + else assert( xmmregs[mmreg&0xf].mode & MODE_WRITE ); + } + else +#endif + { + int dohw; + int mmregs; + int t0reg = -1; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) + _flushConstReg(_Rs_); + + mmregs = _eePrepareReg(_Rs_); + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + // check if can process mmx + if( _hasFreeMMXreg() ) { + mmreg = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) { + mmreg |= MEM_MMXTAG; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg < 0 ) { + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + } + } + + if( mmreg < 0 ) { + _deleteEEreg(_Rt_, 1); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg >= 0 && (mmreg & MEM_MMXTAG) ) MOVQMtoR(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else if( mmreg >= 0 && (mmreg & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + ADD32ItoR(ESP, 4); + } + } + else { + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQ_co( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc); + recLQ(); + g_pCurInstInfo--; // incremented later + } + else +#endif + { + int dohw; + int t0reg = -1; + int mmregs = _eePrepareReg(_Rs_); + + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1 = -1, mmreg2 = -1; + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + + if( _hasFreeMMXreg() ) { + mmreg1 = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) { + mmreg1 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+_Rt_, 2); + + if( mmreg1 < 0 ) { + mmreg1 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + } + } + + if( nextrt ) { + _eeOnWriteReg(nextrt, 0); + + if( _hasFreeMMXreg() ) { + mmreg2 = _allocCheckGPRtoMMX(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) { + mmreg2 |= MEM_MMXTAG; + if( t0reg < 0 ) t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + } + } + else _deleteMMXreg(MMX_GPR+nextrt, 2); + + if( mmreg2 < 0 ) { + mmreg2 = _allocGPRtoXMMreg(-1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + } + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Rt_ ) { + if( mmreg1 >= 0 && (mmreg1 & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOVQRmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[2], t0reg); + } + else if( mmreg1 >= 0 && (mmreg1 & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg1&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( nextrt ) { + if( mmreg2 >= 0 && (mmreg2 & MEM_MMXTAG) ) { + MOVQRmtoROffset(t0reg, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOVQRmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQRtoM((u32)&cpuRegs.GPR.r[nextrt].UL[2], t0reg); + } + else if( mmreg2 >= 0 && (mmreg2 & MEM_XMMTAG) ) { + SSEX_MOVDQARmtoROffset(mmreg2&0xf, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + _recMove128RmOffsettoM((u32)&cpuRegs.GPR.r[nextrt].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrt].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead128 ); + + if( _Rt_) { + if( mmreg1 >= 0 && (mmreg1 & MEM_MMXTAG) ) MOVQMtoR(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]); + else if( mmreg1 >= 0 && (mmreg1 & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg1&0xf, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + if( nextrt ) { + if( mmreg2 >= 0 && (mmreg2 & MEM_MMXTAG) ) MOVQMtoR(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ]); + else if( mmreg2 >= 0 && (mmreg2 & MEM_XMMTAG) ) SSEX_MOVDQA_M128_to_XMM(mmreg2&0xf, (int)&cpuRegs.GPR.r[ nextrt ].UL[ 0 ] ); + } + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg); + } +} + +// coissues more than 2 LQs +void recLQ_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + recLQ(); + + for(i = 0; i < num; ++i) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(pc+i*4); + recLQ(); + } + + g_pCurInstInfo -= num; // incremented later + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + if( _Rt_ ) _deleteMMXreg(MMX_GPR+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + if( nextrts[i] ) _deleteMMXreg(MMX_GPR+nextrts[i], 2); + } + + if( _Rt_ ) { + _eeOnWriteReg(_Rt_, 0); + mmreg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + for(i = 0; i < num; ++i) { + if( nextrts[i] ) { + _eeOnWriteReg(nextrts[i], 0); + mmregs[i] = _allocGPRtoXMMreg(-1, nextrts[i], MODE_WRITE); + } + else mmregs[i] = -1; + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 2, 1); + + if( _Rt_ ) SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + u32 off = s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_; + if( nextrts[i] ) SSEX_MOVDQARmtoROffset(mmregs[i], ECX, PS2MEM_BASE_+off&~0xf); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Rt_ ) PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + if( _Rt_) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + + if( nextrts[i] ) MOV32ItoRmOffset(ESP, (int)&cpuRegs.GPR.r[nextrts[i]].UL[0], 0); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0); + CALLFunc( (int)recMemRead128 ); + if( nextrts[i] ) SSEX_MOVDQA_M128_to_XMM(mmregs[i], (int)&cpuRegs.GPR.r[ nextrts[i] ].UL[ 0 ] ); + } + + ADD32ItoR(ESP, 4); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +extern void recClear64(BASEBLOCK* p); +extern void recClear128(BASEBLOCK* p); + +// check if clearing executable code, size is in dwords +void recMemConstClear(u32 mem, u32 size) +{ + // NOTE! This assumes recLUT never changes its mapping + if( !recLUT[mem>>16] ) + return; + + //iFlushCall(0); // just in case + + // check if mem is executable, and clear it + //CMP32ItoM((u32)&maxrecmem, mem); + //j8Ptr[5] = JBE8(0); + + // can clear now + if( size == 1 ) { + CMP32ItoM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JE8(0); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClearMem); + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[6]); + } + else if( size == 2 ) { + // need to clear 8 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+8, 0); + j8Ptr[7] = JNE8(0); + + j8Ptr[8] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[6] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear64); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[8] ); + } + else { + assert( size == 4 ); + // need to clear 16 bytes + + CMP32I8toM((u32)PC_GETBLOCK(mem), 0); + j8Ptr[6] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK), 0); + j8Ptr[7] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*2, 0); + j8Ptr[8] = JNE8(0); + + CMP32I8toM((u32)PC_GETBLOCK(mem)+sizeof(BASEBLOCK)*3, 0); + j8Ptr[9] = JNE8(0); + + j8Ptr[10] = JMP8(0); + + // call clear + x86SetJ8( j8Ptr[6] ); + x86SetJ8( j8Ptr[7] ); + x86SetJ8( j8Ptr[8] ); + x86SetJ8( j8Ptr[9] ); + + PUSH32I((u32)PC_GETBLOCK(mem)); + CALLFunc((u32)recClear128); + ADD32ItoR(ESP, 4); + + x86SetJ8( j8Ptr[10] ); + } + + //x86SetJ8(j8Ptr[5]); +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear32() +{ + _asm { + mov edx, ecx + shr edx, 14 + and dl, 0xfc + add edx, recLUT + test dword ptr [edx], 0xffffffff + jnz Clear32 + ret +Clear32: + // recLUT[mem>>16] + (mem&0xfffc) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + cmp dword ptr [edx], 0 + je ClearRet + sub esp, 4 + mov dword ptr [esp], edx + call recClearMem + add esp, 4 +ClearRet: + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear64() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear64 + ret +Clear64: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check both blocks + cmp dword ptr [edx], 0 + jne DoClear0 + cmp dword ptr [edx+8], 0 + jne DoClear1 + ret + +DoClear1: + add edx, 8 +DoClear0: + sub esp, 4 + mov dword ptr [esp], edx + call recClear64 + add esp, 4 + ret + } +} + +// check if mem is executable, and clear it +__declspec(naked) void recWriteMemClear128() +{ + __asm { + // check if mem is executable, and clear it + mov edx, ecx + shr edx, 14 + and edx, 0xfffffffc + add edx, recLUT + cmp dword ptr [edx], 0 + jne Clear128 + ret +Clear128: + // recLUT[mem>>16] + (mem&0xffff) + mov edx, dword ptr [edx] + mov eax, ecx + and eax, 0xfffc + // edx += 2*eax + shl eax, 1 + add edx, eax + + // note: have to check all 4 blocks + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + add edx, 8 + cmp dword ptr [edx], 0 + jne DoClear + ret + +DoClear: + sub esp, 4 + mov dword ptr [esp], edx + call recClear128 + add esp, 4 + ret + } +} + +void recStore_raw(EEINST* pinst, int bit, int x86reg, int gprreg, u32 offset) +{ + if( bit == 128 ) { + int mmreg; + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + + SetMMXstate(); + } + else { + + if( GPR_IS_CONST1( gprreg ) ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + + if( _hasFreeMMXreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + SetMMXstate(); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + + if( _hasFreeMMXreg() ) { + int t0reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOVQRtoRmOffset(ECX, t0reg, PS2MEM_BASE_+offset+8); + _freeMMXreg(t0reg); + } + else { + MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); +// MOVQMtoR(mmreg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); +// MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset+8); + } + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 2 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 3 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+12); + } + } + } + return; + } + + if( GPR_IS_CONST1( gprreg ) ) { + switch(bit) { + case 8: MOV8ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 16: MOV16ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 32: MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); break; + case 64: + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[0], PS2MEM_BASE_+offset); + MOV32ItoRmOffset(ECX, g_cpuConstRegs[gprreg].UL[1], PS2MEM_BASE_+offset+4); + break; + } + } + else { + int mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ); + if( mmreg < 0 ) { + mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ); + if( mmreg >= 0 ) mmreg |= 0x8000; + } + + if( bit == 64 ) { + //sd + if( mmreg >= 0 ) { + if( mmreg & 0x8000 ) { + SSE_MOVLPSRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVQRtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + if( (mmreg = _allocCheckGPRtoMMX(pinst, gprreg, MODE_READ)) >= 0 ) { + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_GPR+gprreg, MODE_READ); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+offset); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+offset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+offset+4); + } + } + } + else if( bit == 32 ) { + // sw + if( mmreg >= 0 ) { + if( mmreg & 0x8000) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + } + else { + MOVD32MMXtoRmOffset(ECX, mmreg&0xf, PS2MEM_BASE_+offset); + SetMMXstate(); + } + } + else { + MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); + } + } + else { + // sb, sh + if( mmreg >= 0) { + if( mmreg & 0x8000) { + if( !(xmmregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + else { + if( !(mmxregs[mmreg&0xf].mode&MODE_WRITE) ) mmreg = -1; + } + } + + if( mmreg >= 0) { + if( mmreg & 0x8000 ) SSE2_MOVD_XMM_to_R(x86reg, mmreg&0xf); + else { + MOVD32MMXtoR(x86reg, mmreg&0xf); + SetMMXstate(); + } + } + else { + switch(bit) { + case 8: MOV8MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(x86reg, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + + switch(bit) { + case 8: MOV8RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 16: MOV16RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + case 32: MOV32RtoRmOffset(ECX, x86reg, PS2MEM_BASE_+offset); break; + } + } + } +} + +void recStore_call(int bit, int gprreg, u32 offset) +{ + // some type of hardware write + if( GPR_IS_CONST1( gprreg ) ) { + if( bit == 128 ) { + if( gprreg > 0 ) { + assert( _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ) == -1 ); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], g_cpuConstRegs[gprreg].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 1 ], g_cpuConstRegs[gprreg].UL[1]); + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + if( !(g_cpuFlushedConstReg&(1<= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else if( bit == 64 ) { + // sd + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVLPS_XMM_to_M64((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + } + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0) { + if( mmxregs[mmreg].mode & MODE_WRITE ) { + MOVQRtoM((int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ], mmreg); + SetMMXstate(); + } + } + + MOV32ItoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); + } + else { + // sb, sh, sw + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, gprreg, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE) ) { + SSE2_MOVD_XMM_to_R(EAX, mmreg); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE)) { + MOVD32MMXtoR(EAX, mmreg); + SetMMXstate(); + } + else { + switch(bit) { + case 8: MOV8MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 16: MOV16MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + case 32: MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ gprreg ].UL[ 0 ]); break; + } + } + } + } + + if( offset != 0 ) ADD32ItoR(ECX, offset); + + // some type of hardware write + switch(bit) { + case 8: CALLFunc( (int)recMemWrite8 ); break; + case 16: CALLFunc( (int)recMemWrite16 ); break; + case 32: CALLFunc( (int)recMemWrite32 ); break; + case 64: CALLFunc( (int)recMemWrite64 ); break; + case 128: CALLFunc( (int)recMemWrite128 ); break; + } +} + +int _eePrepConstWrite128(int gprreg) +{ + int mmreg = 0; + + if( GPR_IS_CONST1(gprreg) ) { + if( gprreg ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + _freeMMXreg(mmreg); + mmreg |= (gprreg<<16)|MEM_EECONSTTAG; + } + else { + mmreg = _allocTempXMMreg(XMMT_INT, -1); + SSEX_PXOR_XMM_to_XMM(mmreg, mmreg); + _freeXMMreg(mmreg); + mmreg |= MEM_XMMTAG; + } + } + else { + if( (mmreg = _checkMMXreg(MMX_GPR+gprreg, MODE_READ)) >= 0 ) { + int mmregtemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmregtemp, (u32)&cpuRegs.GPR.r[gprreg].UL[2]); + mmreg |= (mmregtemp<<4)|MEM_MMXTAG; + _freeMMXreg(mmregtemp); + } + else mmreg = _allocGPRtoXMMreg(-1, gprreg, MODE_READ)|MEM_XMMTAG; + } + + return mmreg; +} + +void recStore(int bit, u32 imm, int align) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+imm; + int doclear = 0; + StopPerfCounter(); + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite8(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 16: + assert( (addr)%2 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite16(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + + break; + case 32: + // used by SWL/SWR + //assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( doclear ) { + recMemConstClear((addr)&~3, 1); + } + break; + case 64: + { + //assert( (addr)%8 == 0 ); + int mask = align ? ~7 : ~0; + + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite64(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else { + mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + doclear = recMemConstWrite64(addr&mask, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + + if( doclear ) { + recMemConstClear((addr)&~7, 2); + } + + break; + } + case 128: + //assert( (addr)%16 == 0 ); + + if( recMemConstWrite128((addr)&~15, _eePrepConstWrite128(_Rt_)) ) { + CMP32ItoM((u32)&maxrecmem, addr); + j8Ptr[0] = JB8(0); + recMemConstClear((addr)&~15, 4); + x86SetJ8(j8Ptr[0]); + } + + break; + } + + StartPerfCounter(); + } + else +#endif + { + int dohw; + int mmregs; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, imm, mmregs, align ? bit/64 : 0, 0); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + + if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[4] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + if( bit < 32 || !align ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[5] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + StopPerfCounter(); + recStore_call(bit, _Rt_, s_nAddMemOffset); + StartPerfCounter(); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recStore_co(int bit, int align) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 addr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_; + u32 coaddr = g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_; + int mmreg, t0reg = -1, mmreg2; + int doclear = 0; + + switch(bit) { + case 8: + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite8(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite8(addr, EAX); + } + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite8(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite8(coaddr, EAX); + } + break; + case 16: + assert( (addr)%2 == 0 ); + assert( (coaddr)%2 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) doclear |= recMemConstWrite16(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear |= recMemConstWrite16(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite16(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite16(coaddr, EAX); + } + break; + case 32: + assert( (addr)%4 == 0 ); + if( GPR_IS_CONST1(_Rt_) ) doclear = recMemConstWrite32(addr, MEM_EECONSTTAG|(_Rt_<<16)); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_XMMTAG|(_Rt_<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ)) >= 0 ) { + doclear = recMemConstWrite32(addr, mmreg|MEM_MMXTAG|(_Rt_<<16)); + } + else { + _eeMoveGPRtoR(EAX, _Rt_); + doclear = recMemConstWrite32(addr, EAX); + } + + if( GPR_IS_CONST1(nextrt) ) doclear |= recMemConstWrite32(coaddr, MEM_EECONSTTAG|(nextrt<<16)); + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_XMMTAG|(nextrt<<16)); + } + else if( (mmreg = _checkMMXreg(MMX_GPR+nextrt, MODE_READ)) >= 0 ) { + doclear |= recMemConstWrite32(coaddr, mmreg|MEM_MMXTAG|(nextrt<<16)); + } + else { + _eeMoveGPRtoR(EAX, nextrt); + doclear |= recMemConstWrite32(coaddr, EAX); + } + + break; + case 64: + { + int mask = align ? ~7 : ~0; + //assert( (addr)%8 == 0 ); + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + + if( GPR_IS_CONST1(nextrt) ) mmreg2 = MEM_EECONSTTAG|(nextrt<<16); + else if( (mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, nextrt, MODE_READ)) >= 0 ) { + mmreg2 |= MEM_XMMTAG|(nextrt<<16); + } + else mmreg2 = _allocMMXreg(-1, MMX_GPR+nextrt, MODE_READ)|MEM_MMXTAG|(nextrt<<16); + + doclear = recMemConstWrite64((addr)&mask, mmreg); + doclear |= recMemConstWrite64((coaddr)&mask, mmreg2); + doclear <<= 1; + break; + } + case 128: + assert( (addr)%16 == 0 ); + + mmreg = _eePrepConstWrite128(_Rt_); + mmreg2 = _eePrepConstWrite128(nextrt); + doclear = recMemConstWrite128((addr)&~15, mmreg); + doclear |= recMemConstWrite128((coaddr)&~15, mmreg2); + doclear <<= 2; + break; + } + + if( doclear ) { + u8* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+(_Imm_ < _Imm_co_ ? _Imm_ : _Imm_co_)); + ptr = JB8(0); + recMemConstClear((addr)&~(doclear*4-1), doclear); + recMemConstClear((coaddr)&~(doclear*4-1), doclear); + x86SetJ8A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + int off = _Imm_co_-_Imm_; + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align ? bit/64 : 0, bit==128); + + recStore_raw(g_pCurInstInfo, bit, EAX, _Rt_, s_nAddMemOffset); + recStore_raw(g_pCurInstInfo+1, bit, EBX, nextrt, s_nAddMemOffset+off); + + // clear the writes, do only one camera (with the lowest addr) + if( off < 0 ) ADD32ItoR(ECX, s_nAddMemOffset+off); + else if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset); + CMP32MtoR(ECX, (u32)&maxrecmem); + + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( off < 0 ) ADD32ItoR(ECX, -off); + else ADD32ItoR(ECX, off); + + if( bit < 32 ) AND8ItoR(ECX, 0xfc); + if( bit <= 32 ) CALLFunc((u32)recWriteMemClear32); + else if( bit == 64 ) CALLFunc((u32)recWriteMemClear64); + else CALLFunc((u32)recWriteMemClear128); + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(bit, _Rt_, s_nAddMemOffset); + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(bit, nextrt, s_nAddMemOffset+_Imm_co_-_Imm_); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + } + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing +} + +void recSB( void ) { recStore(8, _Imm_, 1); } +void recSB_co( void ) { recStore_co(8, 1); } +void recSH( void ) { recStore(16, _Imm_, 1); } +void recSH_co( void ) { recStore_co(16, 1); } +void recSW( void ) { recStore(32, _Imm_, 1); } +void recSW_co( void ) { recStore_co(32, 1); } + +//////////////////////////////////////////////////// +void recSWL_co(void) { recStore(32, _Imm_-3, 0); } + +void recSWL( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0xffffff00<<(shift*8)); + SHR32ItoR(ECX, 24-shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem >> SWL_SHIFT[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + SHR32CLtoR(EBX); + + // mov temp and compute _rt_ & SWL_MASK[shift] + MOV32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0xffffff00); + SHL32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +//////////////////////////////////////////////////// +void recSWR_co(void) { recStore(32, _Imm_, 0); } + +void recSWR( void ) +{ +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int shift = (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&3; + + recMemConstRead32(EAX, (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3); + + _eeMoveGPRtoR(ECX, _Rt_); + AND32ItoR(EAX, 0x00ffffff>>(24-shift*8)); + SHL32ItoR(ECX, shift*8); + OR32RtoR(EAX, ECX); + + if( recMemConstWrite32((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, EAX) ) + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~3, 1); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + XOR32RtoR(EDI, EDI); + + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // repeat + MOV32ItoR(EDX, 0x3); + AND32RtoR(EDX, ECX); + AND32ItoR(ECX, ~3); + SHL32ItoR(EDX, 3); // *8 + + PUSH32R(ECX); + PUSH32R(EDX); + CALLFunc( (int)recMemRead32 ); + POP32R(EDX); + MOV8ItoR(EDI, 0xff); + + x86SetJ8(j8Ptr[1]); + } + + _eeMoveGPRtoR(EBX, _Rt_); + + // oldmem is in EAX + // mem << SWR_SHIFT[shift] + MOV32RtoR(ECX, EDX); + SHL32CLtoR(EBX); + + // mov temp and compute _rt_ & SWR_MASK[shift] + MOV32ItoR(ECX, 24); + SUB32RtoR(ECX, EDX); + MOV32ItoR(EDX, 0x00ffffff); + SHR32CLtoR(EDX); + AND32RtoR(EAX, EDX); + + // combine + OR32RtoR(EAX, EBX); + + POP32R(ECX); + + // read the old mem again + TEST32RtoR(EDI, EDI); + j8Ptr[0] = JNZ8(0); + + // manual write + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + + j8Ptr[1] = JMP8(0); + x86SetJ8(j8Ptr[0]); + + CALLFunc( (int)recMemWrite32 ); + + x86SetJ8(j8Ptr[1]); + } +} + +void recSD( void ) { recStore(64, _Imm_, 1); } +void recSD_co( void ) { recStore_co(64, 1); } + +// coissues more than 2 SDs +void recSD_coX(int num, int align) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + u32 mask = align ? ~7 : ~0; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + if( GPR_IS_CONST1(_Rt_) ) mmreg = MEM_EECONSTTAG|(_Rt_<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(_Rt_<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ)|MEM_MMXTAG|(_Rt_<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&mask, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + if( GPR_IS_CONST1(nextrts[i]) ) mmreg = MEM_EECONSTTAG|(nextrts[i]<<16); + else if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, nextrts[i], MODE_READ)) >= 0 ) { + mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + } + else mmreg = _allocMMXreg(-1, MMX_GPR+nextrts[i], MODE_READ)|MEM_MMXTAG|(nextrts[i]<<16); + doclear |= recMemConstWrite64((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&mask, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~7, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~7, 2); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, align, 1); + + recStore_raw(g_pCurInstInfo, 64, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 64, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear64); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear64); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(64, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(64, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +//////////////////////////////////////////////////// +void recSDL_co(void) { recStore(64, _Imm_-7, 0); } + +void recSDL( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR_co(void) { recStore(64, _Imm_, 0); } + +void recSDR( void ) +{ + iFlushCall(FLUSH_NOCONST); + + if( GPR_IS_CONST1( _Rs_ ) ) { + // flush temporarily + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + //MOV32ItoM((int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + } + + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) { recStore(128, _Imm_, 1); } +void recSQ_co( void ) { recStore_co(128, 1); } + +// coissues more than 2 SQs +void recSQ_coX(int num) +{ + int i; + int mmreg = -1; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int minimm = _Imm_; + int t0reg = -1; + int doclear = 0; + + mmreg = _eePrepConstWrite128(_Rt_); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + for(i = 0; i < num; ++i) { + int imm = (*(s16*)PSM(pc+i*4)); + if( minimm > imm ) minimm = imm; + + mmreg = _eePrepConstWrite128(nextrts[i]); + doclear |= recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+imm)&~15, mmreg); + } + + if( doclear ) { + u32* ptr; + CMP32ItoM((u32)&maxrecmem, g_cpuConstRegs[_Rs_].UL[0]+minimm); + ptr = JB32(0); + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, 4); + + for(i = 0; i < num; ++i) { + recMemConstClear((g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)))&~15, 4); + } + x86SetJ32A(ptr); + } + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg_coX(_Rs_, num); + int minoff = 0; + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 1); + + recStore_raw(g_pCurInstInfo, 128, EAX, _Rt_, s_nAddMemOffset); + + for(i = 0; i < num; ++i) { + recStore_raw(g_pCurInstInfo+i+1, 128, EAX, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + // clear the writes + minoff = _Imm_; + for(i = 0; i < num; ++i) { + if( minoff > (*(s16*)PSM(pc+i*4)) ) minoff = (*(s16*)PSM(pc+i*4)); + } + + if( s_nAddMemOffset || minoff != _Imm_ ) ADD32ItoR(ECX, s_nAddMemOffset+minoff-_Imm_); + CMP32MtoR(ECX, (u32)&maxrecmem); + if( s_bCachingMem & 2 ) j32Ptr[5] = JAE32(0); + else j8Ptr[1] = JAE8(0); + + MOV32RtoM((u32)&s_tempaddr, ECX); + if( minoff != _Imm_ ) ADD32ItoR(ECX, _Imm_-minoff); + CALLFunc((u32)recWriteMemClear128); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + if( minoff != (*(s16*)PSM(pc+i*4)) ) ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-minoff); + CALLFunc((u32)recWriteMemClear128); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + recStore_call(128, _Rt_, s_nAddMemOffset); + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + recStore_call(128, nextrts[i], s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[5]); + else x86SetJ8(j8Ptr[1]); + + _clearNeededMMXregs(); // needed since allocing + _clearNeededXMMregs(); // needed since allocing + } +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + mmreg = EAX; + } + + if( !(mmreg&MEM_XMMTAG) ) + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + else +#endif + { + int dohw; + int regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + iMemRead32Check(); + CALLFunc( (int)recMemRead32 ); + + if( regt >= 0 ) SSE2_MOVD_R_to_XMM(regt, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recLWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + u32 written = 0; + int ineax, mmreg1, mmreg2; + + mmreg1 = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg1 >= 0 ) mmreg1 |= MEM_XMMTAG; + else mmreg1 = EBX; + + mmreg2 = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + if( mmreg2 >= 0 ) mmreg2 |= MEM_XMMTAG; + else mmreg2 = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg1, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg1&MEM_XMMTAG ) xmmregs[mmreg1&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmreg2, g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_); + + if( !written ) { + if( !(mmreg1&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + } + + if( ineax || !(mmreg2 & MEM_XMMTAG) ) { + if( mmreg2&MEM_XMMTAG ) xmmregs[mmreg2&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int regt, regtnext; + int mmregs = _eePrepareReg(_Rs_); + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + regt = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + regtnext = _allocCheckFPUtoXMM(g_pCurInstInfo+1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( regt >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regt, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + if( regtnext >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(regtnext, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + PUSH32R(ECX); + CALLFunc( (int)recMemRead32 ); + POP32R(ECX); + + if( regt >= 0 ) { + SSE2_MOVD_R_to_XMM(regt, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + ADD32ItoR(ECX, _Imm_co_-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( regtnext >= 0 ) { + SSE2_MOVD_R_to_XMM(regtnext, EAX); + } + else { + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recLWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int ineax; + u32 written = 0; + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+_Imm_) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + // recompile two at a time + for(i = 0; i < num-1; i += 2) { + nextrts[0] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + nextrts[1] = ((*(u32*)(PSM(pc+i*4+4)) >> 16) & 0x1F); + + written = 0; + mmregs[0] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[0], MODE_WRITE); + if( mmregs[0] >= 0 ) mmregs[0] |= MEM_XMMTAG; + else mmregs[0] = EBX; + + mmregs[1] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+2, nextrts[1], MODE_WRITE); + if( mmregs[1] >= 0 ) mmregs[1] |= MEM_XMMTAG; + else mmregs[1] = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmregs[0], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmregs[0]&MEM_XMMTAG ) xmmregs[mmregs[0]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + written = 1; + } + ineax = recMemConstRead32(mmregs[1], g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4+4))); + + if( !written ) { + if( !(mmregs[0]&MEM_XMMTAG) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[0] ].UL, EBX ); + } + + if( ineax || !(mmregs[1] & MEM_XMMTAG) ) { + if( mmregs[1]&MEM_XMMTAG ) xmmregs[mmregs[1]&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[1] ].UL, EAX ); + } + } + + if( i < num ) { + // one left + int nextrt = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrt, MODE_WRITE); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG; + else mmreg = EAX; + + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 4 == 0 ); + if( recMemConstRead32(mmreg, g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4))) ) { + if( mmreg&MEM_XMMTAG ) xmmregs[mmreg&0xf].inuse = 0; + MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EBX ); + written = 1; + } + else if( !IS_XMMREG(mmreg) ) MOV32RtoM( (int)&fpuRegs.fpr[ nextrt ].UL, EAX ); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + + _deleteMMXreg(MMX_FPU+_Rt_, 2); + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + _deleteMMXreg(MMX_FPU+nextrts[i], 2); + } + + mmreg = _allocCheckFPUtoXMM(g_pCurInstInfo, _Rt_, MODE_WRITE); + + for(i = 0; i < num; ++i) { + mmregs[i] = _allocCheckFPUtoXMM(g_pCurInstInfo+i+1, nextrts[i], MODE_WRITE); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0 ) { + SSEX_MOVD_RmOffset_to_XMM(mmregs[i], ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32RmtoROffset(EAX, ECX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + CALLFunc( (int)recMemRead32 ); + + if( mmreg >= 0 ) SSE2_MOVD_R_to_XMM(mmreg, EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ _Rt_ ].UL, EAX ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + CALLFunc( (int)recMemRead32 ); + + if( mmregs[i] >= 0 ) SSE2_MOVD_R_to_XMM(mmregs[i], EAX); + else MOV32RtoM( (int)&fpuRegs.fpr[ nextrts[i] ].UL, EAX ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32(j32Ptr[4]); + else x86SetJ8(j8Ptr[2]); + } + } +} + +void recSWC1_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + int mmreg; + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrt<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_, mmreg); + } + else +#endif + { + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + int mmreg1, mmreg2; + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + assert( _checkMMXreg(MMX_FPU+nextrt, MODE_READ) == -1 ); + + mmreg1 = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_FPREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 0, 0); + + if(mmreg1 >= 0 ) { + if( mmreg2 >= 0 ) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + else { + if( mmreg2 >= 0 ) { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32MtoR(EDX, (int)&fpuRegs.fpr[ nextrt ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg1 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg1); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + if( mmreg2 >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg2); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrt ].UL); + CALLFunc( (int)recMemWrite32 ); + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +void recSWC1_coX(int num) +{ + int i; + int mmreg = -1; + int mmregs[XMMREGS]; + int nextrts[XMMREGS]; + + assert( num > 1 && num < XMMREGS ); + + for(i = 0; i < num; ++i) { + nextrts[i] = ((*(u32*)(PSM(pc+i*4)) >> 16) & 0x1F); + } + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%4 == 0 ); + + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(_Rt_<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+_Imm_, mmreg); + + for(i = 0; i < num; ++i) { + mmreg = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + if( mmreg >= 0 ) mmreg |= MEM_XMMTAG|(nextrts[i]<<16); + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + mmreg = EAX; + } + recMemConstWrite32(g_cpuConstRegs[_Rs_].UL[0]+(*(s16*)PSM(pc+i*4)), mmreg); + } + } + else +#endif + { + int dohw; + int mmregS = _eePrepareReg_coX(_Rs_, num); + + assert( _checkMMXreg(MMX_FPU+_Rt_, MODE_READ) == -1 ); + mmreg = _checkXMMreg(XMMTYPE_FPREG, _Rt_, MODE_READ); + + for(i = 0; i < num; ++i) { + assert( _checkMMXreg(MMX_FPU+nextrts[i], MODE_READ) == -1 ); + mmregs[i] = _checkXMMreg(XMMTYPE_FPREG, nextrts[i], MODE_READ); + } + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregS, 0, 1); + + if( mmreg >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + } + + for(i = 0; i < num; ++i) { + if( mmregs[i] >= 0) { + SSEX_MOVD_XMM_to_RmOffset(ECX, mmregs[i], PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + else { + MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+(*(s16*)PSM(pc+i*4))-_Imm_); + } + } + + if( dohw ) { + if( s_bCachingMem & 2 ) j32Ptr[4] = JMP32(0); + else j8Ptr[2] = JMP8(0); + + SET_HWLOC(); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + // some type of hardware write + if( mmreg >= 0) SSE2_MOVD_XMM_to_R(EAX, mmreg); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ _Rt_ ].UL); + CALLFunc( (int)recMemWrite32 ); + + for(i = 0; i < num; ++i) { + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, (*(s16*)PSM(pc+i*4))-_Imm_); + if( mmregs[i] >= 0 && (xmmregs[mmregs[i]].mode&MODE_WRITE) ) SSE2_MOVD_XMM_to_R(EAX, mmregs[i]); + else MOV32MtoR(EAX, (int)&fpuRegs.fpr[ nextrts[i] ].UL); + CALLFunc( (int)recMemWrite32 ); + } + + if( s_bCachingMem & 2 ) x86SetJ32A(j32Ptr[4]); + else x86SetJ8A(j8Ptr[2]); + } + } +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else mmreg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + + if( !_Ft_ ) _freeXMMreg(mmreg); + } + else +#endif + { + int dohw, mmregs; + + if( !cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + if( _Ft_ ) { + s8* rawreadptr = x86Ptr; + + if( mmreg >= 0 ) { + SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + _recMove128RmOffsettoM((u32)&VU0.VF[_Ft_].UL[0], PS2MEM_BASE_+s_nAddMemOffset); + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + CALLFunc( (int)recMemRead128 ); + if( mmreg >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0] ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + else { + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + ADD32ItoR(ESP, 4); + + x86SetJ8(j8Ptr[1]); + } + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +void recLQC2_co( void ) +{ + int mmreg1 = -1, mmreg2 = -1, t0reg = -1; + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + +#ifdef REC_SLOWREAD + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_) % 16 == 0 ); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + else t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg1 >= 0 ? mmreg1 : t0reg); + + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + else if( t0reg < 0 ) t0reg = _allocTempXMMreg(XMMT_FPS, -1); + recMemConstRead128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_)&~15, mmreg2 >= 0 ? mmreg2 : t0reg); + + if( t0reg >= 0 ) _freeXMMreg(t0reg); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + if( _Ft_ ) mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_WRITE); + if( nextrt ) mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_WRITE); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + if( mmreg1 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg1, ECX, PS2MEM_BASE_+s_nAddMemOffset); + if( mmreg2 >= 0 ) SSEX_MOVDQARmtoROffset(mmreg2, ECX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + + if( dohw ) { + j8Ptr[1] = JMP8(0); + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + MOV32RtoM((u32)&s_tempaddr, ECX); + + if( _Ft_ ) PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + else PUSH32I( (int)&retValues[0] ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg1 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0] ); + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + if( nextrt ) MOV32ItoRmOffset(ESP, (int)&VU0.VF[nextrt].UD[0], 0 ); + else MOV32ItoRmOffset(ESP, (int)&retValues[0], 0 ); + CALLFunc( (int)recMemRead128 ); + + if( mmreg2 >= 0 ) SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0] ); + + ADD32ItoR(ESP, 4); + x86SetJ8(j8Ptr[1]); + } + } + + _clearNeededXMMregs(); // needed since allocing +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + int mmreg; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg); + } + else +#endif + { + s8* rawreadptr; + int dohw, mmregs; + + if( cpucaps.hasStreamingSIMDExtensions && GPR_IS_CONST1( _Rs_ ) ) { + _flushConstReg(_Rs_); + } + + mmregs = _eePrepareReg(_Rs_); + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg); + } + else if( _hasFreeMMXreg() ) { + mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { + + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg); + } + } + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +void recSQC2_co( void ) +{ + int nextrt = ((*(u32*)(PSM(pc)) >> 16) & 0x1F); + int mmreg1, mmreg2; + +#ifdef REC_SLOWWRITE + _flushConstReg(_Rs_); +#else + if( GPR_IS_CONST1( _Rs_ ) ) { + assert( (g_cpuConstRegs[_Rs_].UL[0]+_Imm_)%16 == 0 ); + + mmreg1 = _allocVFtoXMMreg(&VU0, -1, _Ft_, MODE_READ)|MEM_XMMTAG; + mmreg2 = _allocVFtoXMMreg(&VU0, -1, nextrt, MODE_READ)|MEM_XMMTAG; + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_)&~15, mmreg1); + recMemConstWrite128((g_cpuConstRegs[_Rs_].UL[0]+_Imm_co_)&~15, mmreg2); + } + else +#endif + { + s8* rawreadptr; + int dohw; + int mmregs = _eePrepareReg(_Rs_); + + mmreg1 = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ); + mmreg2 = _checkXMMreg(XMMTYPE_VFREG, nextrt, MODE_READ); + + dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); + + rawreadptr = x86Ptr; + + if( mmreg1 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + } + else { + if( _hasFreeXMMreg() ) { + mmreg1 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + _freeXMMreg(mmreg1); + } + else if( _hasFreeMMXreg() ) { + mmreg1 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UD[0]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset); + MOVQMtoR(mmreg1, (int)&VU0.VF[_Ft_].UL[2]); + MOVQRtoRmOffset(ECX, mmreg1, PS2MEM_BASE_+s_nAddMemOffset+8); + SetMMXstate(); + _freeMMXreg(mmreg1); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+4); + MOV32MtoR(EAX, (int)&VU0.VF[_Ft_].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[_Ft_].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+12); + } + } + + if( mmreg2 >= 0 ) { + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + } + else { + if( _hasFreeXMMreg() ) { + mmreg2 = _allocTempXMMreg(XMMT_FPS, -1); + SSEX_MOVDQA_M128_to_XMM(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + SSEX_MOVDQARtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + _freeXMMreg(mmreg2); + } + else if( _hasFreeMMXreg() ) { + mmreg2 = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UD[0]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOVQMtoR(mmreg2, (int)&VU0.VF[nextrt].UL[2]); + MOVQRtoRmOffset(ECX, mmreg2, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + SetMMXstate(); + _freeMMXreg(mmreg2); + } + else { + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[0]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[1]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+4); + MOV32MtoR(EAX, (int)&VU0.VF[nextrt].UL[2]); + MOV32MtoR(EDX, (int)&VU0.VF[nextrt].UL[3]); + MOV32RtoRmOffset(ECX, EAX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+8); + MOV32RtoRmOffset(ECX, EDX, PS2MEM_BASE_+s_nAddMemOffset+_Imm_co_-_Imm_+12); + } + } + + if( dohw ) { + j8Ptr[1] = JMP8(0); + + SET_HWLOC(); + + // check if writing to VUs + CMP32ItoR(ECX, 0x11000000); + JAE8(rawreadptr - (x86Ptr+2)); + + // some type of hardware write + if( mmreg1 >= 0) { + if( xmmregs[mmreg1].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[_Ft_].UD[0], mmreg1); + } + } + + MOV32RtoM((u32)&s_tempaddr, ECX); + + MOV32ItoR(EAX, (int)&VU0.VF[_Ft_].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + if( mmreg2 >= 0) { + if( xmmregs[mmreg2].mode & MODE_WRITE ) { + SSEX_MOVDQA_XMM_to_M128((int)&VU0.VF[nextrt].UD[0], mmreg2); + } + } + + MOV32MtoR(ECX, (u32)&s_tempaddr); + ADD32ItoR(ECX, _Imm_co_-_Imm_); + + MOV32ItoR(EAX, (int)&VU0.VF[nextrt].UD[0]); + CALLFunc( (int)recMemWrite128 ); + + x86SetJ8A(j8Ptr[1]); + } + } +} + +#else + +PCSX2_ALIGNED16(u32 dummyValue[4]); + +void SetFastMemory(int bSetFast) +{ + // nothing +} + +//////////////////////////////////////////////////// +void recLB( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVSX32R8toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLBU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead8 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R8toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLH( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOVSX32R16toR( EAX, EAX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLHU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32I( (int)&dummyValue[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memRead16 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0] ); + MOVZX32R16toR( EAX, EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLW( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWU( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&dummyValue[0]); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); + if ( _Rt_ ) + { + u8* linkEnd; + TEST32RtoR( EAX, EAX ); + linkEnd = JNZ8( 0 ); + MOV32MtoR( EAX, (int)&dummyValue[0]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + x86SetJ8( linkEnd ); + } +} + +//////////////////////////////////////////////////// +void recLWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWL ); +} + +//////////////////////////////////////////////////// +void recLWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LWR ); +} + +//////////////////////////////////////////////////// +extern void MOV64RmtoR( x86IntRegType to, x86IntRegType from ); + +void recLD( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead64 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recLDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDL ); +} + +//////////////////////////////////////////////////// +void recLDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)LDR ); +} + +//////////////////////////////////////////////////// +void recLQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _eeOnLoadWrite(_Rt_); + EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension + _deleteEEreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + AND32ItoR( EAX, ~0xf ); + + if ( _Rt_ ) + { + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); + +} + +//////////////////////////////////////////////////// +void recSB( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite8 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSH( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite16 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSW( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWL ); +} + +//////////////////////////////////////////////////// +void recSWR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SWR ); +} + +//////////////////////////////////////////////////// +void recSD( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + PUSH32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite64 ); + ADD32ItoR( ESP, 12 ); +} + +//////////////////////////////////////////////////// +void recSDL( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDL ); +} + +//////////////////////////////////////////////////// +void recSDR( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32ItoM( (int)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (int)&cpuRegs.pc, pc ); + CALLFunc( (int)SDR ); +} + +//////////////////////////////////////////////////// +void recSQ( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + AND32ItoR( EAX, ~0xf ); + + PUSH32I( (int)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +/********************************************************* +* Load and store for COP1 * +* Format: OP rt, offset(base) * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memRead32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSWC1( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteFPtoXMMreg(_Rt_, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32M( (int)&fpuRegs.fpr[ _Rt_ ].UL ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite32 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +void recLQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 2); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_); + } + + if ( _Rt_ ) + { + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + } + else + { + PUSH32I( (int)&dummyValue[0] ); + } + PUSH32R( EAX ); + CALLFunc( (int)memRead128 ); + ADD32ItoR( ESP, 8 ); +} + +//////////////////////////////////////////////////// +void recSQC2( void ) +{ + _deleteEEreg(_Rs_, 1); + _deleteVFtoXMMreg(_Ft_, 0, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + { + ADD32ItoR( EAX, _Imm_ ); + } + + PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); + PUSH32R( EAX ); + CALLFunc( (int)memWrite128 ); + ADD32ItoR( ESP, 8 ); +} + +#endif + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900Move.c b/pcsx2/x86/ix86-32/iR5900Move.c new file mode 100644 index 0000000..eb63b0c --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900Move.c @@ -0,0 +1,841 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +#elif defined(EE_CONST_PROP) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//// LUI +void recLUI(int info) +{ + int mmreg; + if(!_Rt_) return; + + _eeOnWriteReg(_Rt_, 1); + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE)) >= 0 ) { + if( xmmregs[mmreg].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rt_].UL[2], mmreg); + } + xmmregs[mmreg].inuse = 0; + } + + _deleteEEreg(_Rt_, 0); + GPR_SET_CONST(_Rt_); + g_cpuConstRegs[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); +} + +//////////////////////////////////////////////////// +void recMFHILO(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + assert( regd != reghi ); + + xmmregs[regd].inuse = 0; + + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_MOVQ_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + else { + SSE_MOVLPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[0], reghi); + } + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((u32)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SSE2_MOVDQ2Q_XMM_to_MM(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + SSE2_MOVQ_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + reghi = _checkMMXreg(MMX_GPR+xmmhilo, MODE_READ); + + if( reghi >= 0 ) { + + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], regd); + } + xmmregs[regd].inuse = 0; + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + SetMMXstate(); + + if( regd >= 0 ) { + MOVQRtoR(regd, reghi); + } + else { + _deleteEEreg(_Rd_, 0); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + else SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 0 ] : (int)&cpuRegs.LO.UL[ 0 ]); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 1 ] : (int)&cpuRegs.LO.UL[ 1 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else + EEINST_RESETHASLIVE1(_Rd_); + } + } + } + } +} + +void recMTHILO(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + assert( reghi != regs ); + + if( cpucaps.hasStreamingSIMD2Extensions ) { + _deleteGPRtoXMMreg(_Rs_, 0); + SSE2_PUNPCKHQDQ_XMM_to_XMM(reghi, reghi); + SSE2_PUNPCKLQDQ_XMM_to_XMM(regs, reghi); + + // swap regs + xmmregs[regs] = xmmregs[reghi]; + xmmregs[reghi].inuse = 0; + xmmregs[regs].mode |= MODE_WRITE; + } + else { + SSE2EMU_MOVSD_XMM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_READ); + + if( regs >= 0 ) { + + if( EEINST_ISLIVE2(xmmhilo) ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64(addrhilo+8, reghi); + } + xmmregs[reghi].inuse = 0; + MOVQRtoM(addrhilo, regs); + } + else { + SetMMXstate(); + SSE2_MOVQ2DQ_MM_to_XMM(reghi, regs); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + else { + _flushConstReg(_Rs_); + SSE_MOVLPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + xmmregs[reghi].mode |= MODE_WRITE; + } + } + } + else { + reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, xmmhilo, MODE_WRITE); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + //SetMMXstate(); + SSE2_MOVDQ2Q_XMM_to_MM(reghi, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoR(reghi, regs); + } + else { + _flushConstReg(_Rs_); + MOVQMtoR(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + } + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+4, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo, EAX ); + MOV32RtoM( addrhilo+4, EDX ); + } + } + } + } + } +} + +void recMFHI( void ) +{ + recMFHILO(1); +} + +void recMFLO( void ) +{ + recMFHILO(0); +} + +void recMTHI( void ) +{ + recMTHILO(1); +} + +void recMTLO( void ) +{ + recMTHILO(0); +} + +//////////////////////////////////////////////////// +void recMFHILO1(int hi) +{ + int reghi, regd, xmmhilo; + if ( ! _Rd_ ) + return; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + reghi = _checkXMMreg(XMMTYPE_GPRREG, xmmhilo, MODE_READ); + + _eeOnWriteReg(_Rd_, 0); + + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ|MODE_WRITE); + + if( reghi >= 0 ) { + if( regd >= 0 ) { + SSEX_MOVHLPS_XMM_to_XMM(regd, reghi); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + _deleteEEreg(_Rd_, 0); + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], reghi); + } + } + else { + if( regd >= 0 ) { + if( EEINST_ISLIVE2(_Rd_) ) { + if( cpucaps.hasStreamingSIMD2Extensions ) { + SSE2_PUNPCKHQDQ_M128_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 0 ] : (int)&cpuRegs.LO.UD[ 0 ]); + SSE2_PSHUFD_XMM_to_XMM(regd, regd, 0x4e); + } + else { + SSE_MOVLPS_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + } + else { + SSE2_MOVQ_M64_to_XMM(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + + xmmregs[regd].mode |= MODE_WRITE; + } + else { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + SetMMXstate(); + MOVQMtoR(regd, hi ? (int)&cpuRegs.HI.UD[ 1 ] : (int)&cpuRegs.LO.UD[ 1 ]); + } + else { + _deleteEEreg(_Rd_, 0); + MOV32MtoR( EAX, hi ? (int)&cpuRegs.HI.UL[ 2 ] : (int)&cpuRegs.LO.UL[ 2 ]); + MOV32MtoR( EDX, hi ? (int)&cpuRegs.HI.UL[ 3 ] : (int)&cpuRegs.LO.UL[ 3 ]); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + } + } +} + +void recMTHILO1(int hi) +{ + int reghi, regs, xmmhilo; + u32 addrhilo; + + xmmhilo = hi ? XMMGPR_HI : XMMGPR_LO; + addrhilo = hi ? (int)&cpuRegs.HI.UD[0] : (int)&cpuRegs.LO.UD[0]; + + regs = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ); + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, xmmhilo, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + if( regs >= 0 ) { + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_XMM_to_XMM(reghi, regs); + else SSE_MOVLHPS_XMM_to_XMM(reghi, regs); + } + else { + _deleteEEreg(_Rs_, 1); + if( cpucaps.hasStreamingSIMD2Extensions ) SSE2_PUNPCKLQDQ_M128_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ]); + else SSE_MOVHPS_M64_to_XMM(reghi, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ]); + + } + } + else { + if( regs >= 0 ) { + SSE2_MOVQ_XMM_to_M64(addrhilo+8, regs); + } + else { + regs = _checkMMXreg(MMX_GPR+_Rs_, MODE_WRITE); + + if( regs >= 0 ) { + SetMMXstate(); + MOVQRtoM(addrhilo+8, regs); + } + else { + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM(addrhilo+8, g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM(addrhilo+12, g_cpuConstRegs[_Rs_].UL[1] ); + } + else { + _deleteEEreg(_Rs_, 1); + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM( addrhilo+8, EAX ); + MOV32RtoM( addrhilo+12, EDX ); + } + } + } + } +} + +void recMFHI1( void ) +{ + recMFHILO1(1); +} + +void recMFLO1( void ) +{ + recMFHILO1(0); +} + +void recMTHI1( void ) +{ + recMTHILO1(1); +} + +void recMTLO1( void ) +{ + recMTHILO1(0); +} + +//// MOVZ +void recMOVZtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +static PCSX2_ALIGNED16(s_zero[4]) = {0,0,0xffffffff, 0xffffffff}; + +void recMOVZtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVZtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + if( info & PROCESS_EE_MMX ) { + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + return; + } + + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVZtemp_(int info) +{ + int t0reg = -1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JNE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVZtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVZ() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + else { + if (g_cpuConstRegs[_Rt_].UD[0] == 0) { + g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; + g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + return; + } + } + + recMOVZtemp(); +} + +//// MOVN +void recMOVNtemp_const() +{ + GPR_DEL_CONST(_Rd_); + _deleteEEreg(_Rd_, 1); + _eeOnWriteReg(_Rd_, 0); + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rs_].UL[1]); + } +} + +void recMOVNtemp_consts(int info) +{ + if( info & PROCESS_EE_MMX ) { + + u32* mem; + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + if( g_cpuFlushedConstReg & (1<<_Rs_) ) mem = &cpuRegs.GPR.r[_Rs_].UL[0]; + else { + mem = recAllocStackMem(8,8); + + mem[0] = g_cpuConstRegs[_Rs_].UL[0]; + mem[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + + MOVQMtoR(EEREC_D, (u32)mem); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1] ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +void recMOVNtemp_constt(int info) +{ + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + if( _hasFreeXMMreg() ) { + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + } +} + +void recMOVNtemp_(int info) +{ + int t0reg=-1; + + if( info & PROCESS_EE_MMX ) { + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + PXORRtoR(t0reg, t0reg); + PCMPEQDRtoR(t0reg, EEREC_T); + PMOVMSKBMMXtoR(EAX, t0reg); + CMP8ItoR(EAX, 0xff); + j8Ptr[ 0 ] = JE8( 0 ); + + MOVQRtoR(EEREC_D, EEREC_S); + x86SetJ8( j8Ptr[ 0 ] ); + + _freeMMXreg(t0reg); + return; + } + + if( _hasFreeXMMreg() ) + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + if( t0reg >= 0 ) { + MOVQMtoR(t0reg, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], t0reg); + _freeMMXreg(t0reg); + } + else { + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + MOV32MtoR(EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ]); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); + } + + x86SetJ8( j8Ptr[ 0 ] ); + + SetMMXstate(); +} + +EERECOMPILE_CODE0(MOVNtemp, XMMINFO_READS|XMMINFO_READD|XMMINFO_READD|XMMINFO_WRITED); + +void recMOVN() +{ + if( _Rs_ == _Rd_ ) + return; + + if( GPR_IS_CONST1(_Rd_) ) { + + if( !GPR_IS_CONST2(_Rs_, _Rt_) ) { + // remove the const, since move is conditional + _deleteEEreg(_Rd_, 0); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[0], g_cpuConstRegs[_Rd_].UL[0]); + MOV32ItoM((u32)&cpuRegs.GPR.r[_Rd_].UL[1], g_cpuConstRegs[_Rd_].UL[1]); + } + else { + if (g_cpuConstRegs[_Rt_].UD[0] != 0) { + g_cpuConstRegs[_Rd_].UL[0] = g_cpuConstRegs[_Rs_].UL[0]; + g_cpuConstRegs[_Rd_].UL[1] = g_cpuConstRegs[_Rs_].UL[1]; + } + return; + } + } + + recMOVNtemp(); +} + +#else + +//////////////////////////////////////////////////// +void recLUI( void ) +{ + if(!_Rt_) return; + if ( _Imm_ < 0 ) + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0xffffffff ); //V + } + else + { + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (u32)_Imm_ << 16 ); //U + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); //V + } +} + +//////////////////////////////////////////////////// +void recMFHI( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.HI.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMFLO( void ) +{ + + if ( ! _Rd_ ) + { + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.LO.UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTHI( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.HI.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMTLO( void ) +{ + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + MOVQRtoM( (int)&cpuRegs.LO.UD[ 0 ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recMOVZ( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JNZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( EDX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recMOVN( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + j8Ptr[ 0 ] = JZ8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], ECX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900MultDiv.c b/pcsx2/x86/ix86-32/iR5900MultDiv.c new file mode 100644 index 0000000..7a25562 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900MultDiv.c @@ -0,0 +1,957 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC( MULT1 ); +REC_FUNC( MULTU1 ); + +REC_FUNC(DIV); +REC_FUNC(DIVU); +REC_FUNC( DIV1 ); +REC_FUNC( DIVU1 ); + +REC_FUNC( MADD ); +REC_FUNC( MADDU ); +REC_FUNC( MADD1 ); +REC_FUNC( MADDU1 ); + +#elif defined(EE_CONST_PROP) + +// if upper is 1, write in upper 64 bits of LO/HI +void recWritebackHILO(int info, int writed, int upper) +{ + int regd, reglo = -1, reghi, savedlo = 0; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + MOV32RtoR( ECX, EDX ); + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + + _deleteMMXreg(XMMGPR_LO, 2); + + if( (reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ)) >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + + xmmregs[reglo].inuse = 0; + reglo = -1; + } + + CDQ(); + MOV32RtoM( loaddr, EAX ); + MOV32RtoM( loaddr+4, EDX ); + savedlo = 1; + } + + if ( writed && _Rd_ ) + { + _eeOnWriteReg(_Rd_, 1); + + regd = -1; + if( g_pCurInstInfo->regs[_Rd_] & EEINST_MMX ) { + + if( savedlo ) { + regd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + MOVQMtoR(regd, loaddr); + } + } + else if( g_pCurInstInfo->regs[_Rd_] & EEINST_XMM ) { + if( savedlo ) { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE|MODE_READ); + if( regd >= 0 ) { + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + regd |= 0x8000; + } + } + } + + if( regd < 0 ) { + _deleteEEreg(_Rd_, 0); + + if( EEINST_ISLIVE1(_Rd_) && !savedlo ) CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + + if( EEINST_ISLIVE1(_Rd_) ) { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else EEINST_RESETHASLIVE1(_Rd_); + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + _deleteMMXreg(XMMGPR_HI, 2); + + if( (reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ)) >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + else SSE_MOVHPS_XMM_to_M64(hiaddr+8, reghi); + } + + xmmregs[reghi].inuse = 0; + reghi = -1; + } + + MOV32RtoM(hiaddr, ECX ); + SAR32ItoR(ECX, 31); + MOV32RtoM(hiaddr+4, ECX ); + } +} + +void recWritebackHILOMMX(int info, int regsource, int writed, int upper) +{ + int regd, t0reg, t1reg = -1; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + SetMMXstate(); + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, regsource); + PSRADItoR(t0reg, 31); // shift in 0s + + if( (g_pCurInstInfo->regs[XMMGPR_LO] & testlive) || (writed && _Rd_) ) { + if( (g_pCurInstInfo->regs[XMMGPR_HI] & testlive) ) + { + if( !_hasFreeMMXreg() ) { + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + } + + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t1reg, regsource); + } + + PUNPCKLDQRtoR(regsource, t0reg); + } + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + int reglo; + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + MOVQRtoR(reglo, regsource); + } + else { + reglo = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_LO, MODE_READ); + + MOVQRtoM(loaddr, regsource); + + if( reglo >= 0 ) { + if( xmmregs[reglo].mode & MODE_WRITE ) { + if( upper ) SSE2_MOVQ_XMM_to_M64(loaddr-8, reglo); + else SSE_MOVHPS_XMM_to_M64(loaddr+8, reglo); + } + xmmregs[reglo].inuse = 0; + reglo = -1; + } + } + } + + if ( writed && _Rd_ ) + { + regd = _allocCheckGPRtoMMX(g_pCurInstInfo, _Rd_, MODE_WRITE); + + if( regd >= 0 ) { + if( regd != regsource ) MOVQRtoR(regd, regsource); + } + else { + regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_READ); + + if( regd >= 0 ) { + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + // lo written + SSE_MOVLPS_M64_to_XMM(regd, loaddr); + xmmregs[regd].mode |= MODE_WRITE; + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + + if( xmmregs[regd].mode & MODE_WRITE ) { + SSE_MOVHPS_XMM_to_M64((int)&cpuRegs.GPR.r[_Rd_].UL[2], regd); + } + + xmmregs[regd].inuse = 0; + } + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], regsource); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + int mmreg = -1, reghi; + + if( t1reg >= 0 ) { + PUNPCKHDQRtoR(t1reg, t0reg); + mmreg = t1reg; + } + else { + // can't modify regsource + PUNPCKHDQRtoR(t0reg, regsource); + mmreg = t0reg; + PSHUFWRtoR(t0reg, t0reg, 0x4e); + } + + if( upper ) { + reghi = _checkXMMreg(XMMTYPE_GPRREG, XMMGPR_HI, MODE_READ); + if( reghi >= 0 ) { + if( xmmregs[reghi].mode & MODE_WRITE ) SSE2_MOVQ_XMM_to_M64(hiaddr-8, reghi); + } + + xmmregs[reghi].inuse = 0; + MOVQRtoM(hiaddr, mmreg); + } + else { + _deleteGPRtoXMMreg(XMMGPR_HI, 2); + _deleteMMXreg(MMX_GPR+MMX_HI, 2); + mmxregs[mmreg].mode = MODE_WRITE; + mmxregs[mmreg].reg = MMX_GPR+MMX_HI; + + if( t1reg >= 0 ) t1reg = -1; + else t0reg = -1; + } + } + + if( t0reg >= 0 ) _freeMMXreg(t0reg&0xf); + if( t1reg >= 0 ) _freeMMXreg(t1reg&0xf); +} + +void recWritebackConstHILO(u64 res, int writed, int upper) +{ + int reglo, reghi; + u32 loaddr = (int)&cpuRegs.LO.UL[ upper ? 2 : 0 ]; + u32 hiaddr = (int)&cpuRegs.HI.UL[ upper ? 2 : 0 ]; + u8 testlive = upper?EEINST_LIVE2:EEINST_LIVE0; + + if( g_pCurInstInfo->regs[XMMGPR_LO] & testlive ) { + if( !upper && (reglo = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + MOVQMtoR(reglo, (u32)ptr); + } + else { + reglo = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_LO, MODE_WRITE|MODE_READ); + + if( reglo >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res & 0xffffffff; + ptr[1] = (res&0x80000000)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reglo, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reglo, (u32)ptr); + } + else { + MOV32ItoM(loaddr, res & 0xffffffff); + MOV32ItoM(loaddr+4, (res&0x80000000)?0xffffffff:0); + } + } + } + + if( g_pCurInstInfo->regs[XMMGPR_HI] & testlive ) { + + if( !upper && (reghi = _allocCheckGPRtoMMX(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE)) >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + MOVQMtoR(reghi, (u32)ptr); + } + else { + reghi = _allocCheckGPRtoXMM(g_pCurInstInfo, XMMGPR_HI, MODE_WRITE|MODE_READ); + + if( reghi >= 0 ) { + u32* ptr = recAllocStackMem(8, 8); + ptr[0] = res >> 32; + ptr[1] = (res>>63)?0xffffffff:0; + if( upper ) SSE_MOVHPS_M64_to_XMM(reghi, (u32)ptr); + else SSE_MOVLPS_M64_to_XMM(reghi, (u32)ptr); + } + else { + _deleteEEreg(XMMGPR_HI, 0); + MOV32ItoM(hiaddr, res >> 32); + MOV32ItoM(hiaddr+4, (res>>63)?0xffffffff:0); + } + } + } + + if (!writed || !_Rd_) return; + g_cpuConstRegs[_Rd_].UD[0] = (s32)(res & 0xffffffff); //that is the difference +} + +//// MULT +void recMULT_const() +{ + s64 res = (s64)g_cpuConstRegs[_Rs_].SL[0] * (s64)g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process); +void recMULTsuper(int info, int upper, int process) +{ + assert( !(info&PROCESS_EE_MMX) ); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + recWritebackHILO(info, 1, upper); +} + +//void recMULT_process(int info, int process) +//{ +// if( EEINST_ISLIVE64(XMMGPR_HI) || !(info&PROCESS_EE_MMX) ) { +// recMULTsuper(info, 0, process); +// } +// else { +// // EEREC_D isn't set +// int mmregd; +// +// if( _Rd_ ) { +// assert(EEREC_D == 0); +// mmregd = _checkMMXreg(MMX_GPR+_Rd_, MODE_WRITE); +// +// if( mmregd < 0 ) { +// if( !(process&PROCESS_CONSTS) && ((g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE)||!EEINST_ISLIVE64(_Rs_)) ) { +// _freeMMXreg(EEREC_S); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_S].inuse = 1; +// mmxregs[EEREC_S].reg = _Rd_; +// mmxregs[EEREC_S].mode = MODE_WRITE; +// mmregd = EEREC_S; +// } +// else if( !(process&PROCESS_CONSTT) && ((g_pCurInstInfo->regs[_Rt_]&EEINST_LASTUSE)||!EEINST_ISLIVE64(_Rt_)) ) { +// _freeMMXreg(EEREC_T); +// _deleteGPRtoXMMreg(_Rd_, 2); +// mmxregs[EEREC_T].inuse = 1; +// mmxregs[EEREC_T].reg = _Rd_; +// mmxregs[EEREC_T].mode = MODE_WRITE; +// mmregd = EEREC_T; +// } +// else mmregd = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); +// } +// +// info |= PROCESS_EE_SET_D(mmregd); +// } +// recMULTUsuper(info, 0, process); +// } +// +// // sometimes _Rd_ can be const +// if( _Rd_ ) _eeOnWriteReg(_Rd_, 1); +//} + +void recMULT_(int info) +{ + //recMULT_process(info, 0); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, 0); + } + else recMULTUsuper(info, 0, 0); +} + +void recMULT_consts(int info) +{ + //recMULT_process(info, PROCESS_CONSTS); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTS); + } + else recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULT_constt(int info) +{ + //recMULT_process(info, PROCESS_CONSTT); + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 0, PROCESS_CONSTT); + } + else recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't set XMMINFO_WRITED|XMMINFO_WRITELO|XMMINFO_WRITEHI +EERECOMPILE_CODE0(MULT, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// MULTU +void recMULTU_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 0); +} + +void recMULTUsuper(int info, int upper, int process) +{ + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( (info & PROCESS_EE_MMX) && cpucaps.hasStreamingSIMD2Extensions ) { + + if( !_Rd_ ) { + // need some temp reg + int t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + assert( EEREC_D == 0 ); + info |= PROCESS_EE_SET_D(t0reg); + } + + if( process & PROCESS_CONSTS ) { + u32* ptempmem = _eeGetConstReg(_Rs_); + if( EEREC_D != EEREC_T ) MOVQRtoR(EEREC_D, EEREC_T); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else if( process & PROCESS_CONSTT ) { + u32* ptempmem = _eeGetConstReg(_Rt_); + if( EEREC_D != EEREC_S ) MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQMtoR(EEREC_D, (u32)ptempmem); + } + else { + if( EEREC_D == EEREC_S ) PMULUDQRtoR(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) PMULUDQRtoR(EEREC_D, EEREC_S); + else { + MOVQRtoR(EEREC_D, EEREC_S); + PMULUDQRtoR(EEREC_D, EEREC_T); + } + } + + recWritebackHILOMMX(info, EEREC_D, 1, upper); + + if( !_Rd_ ) _freeMMXreg(EEREC_D); + return; + } + + if( info & PROCESS_EE_MMX ) { + if( info & PROCESS_EE_MODEWRITES ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rs_].UL[0], EEREC_S); + if( mmxregs[EEREC_S].reg == MMX_GPR+_Rs_ ) mmxregs[EEREC_S].mode &= ~MODE_WRITE; + } + if( info & PROCESS_EE_MODEWRITET ) { + MOVQRtoM((u32)&cpuRegs.GPR.r[_Rt_].UL[0], EEREC_T); + if( mmxregs[EEREC_T].reg == MMX_GPR+_Rt_ ) mmxregs[EEREC_T].mode &= ~MODE_WRITE; + } + _deleteMMXreg(MMX_GPR+_Rd_, 0); + } + + if( process & PROCESS_CONSTS ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if( process & PROCESS_CONSTT) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EDX, EEREC_S); + MUL32R(EDX); + } + else + MUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + if( info & PROCESS_EE_MMX ) { + MOVD32MMXtoR(EAX, EEREC_S); + MOVD32MMXtoR(EDX, EEREC_T); + MUL32R(EDX); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + } + + recWritebackHILO(info, 1, upper); +} + +void recMULTU_(int info) +{ + recMULTUsuper(info, 0, 0); +} + +void recMULTU_consts(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTS); +} + +void recMULTU_constt(int info) +{ + recMULTUsuper(info, 0, PROCESS_CONSTT); +} + +// don't specify XMMINFO_WRITELO or XMMINFO_WRITEHI, that is taken care of +EERECOMPILE_CODE0(MULTU, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULT1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULT1_(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, 0); + } + else recMULTUsuper(info, 1, 0); +} + +void recMULT1_consts(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTS); + } + else recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULT1_constt(int info) +{ + if( (g_pCurInstInfo->regs[XMMGPR_HI]&EEINST_LIVE2) || !(info&PROCESS_EE_MMX) ) { + recMULTsuper(info, 1, PROCESS_CONSTT); + } + else recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULT1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//////////////////////////////////////////////////// +void recMULTU1_const() +{ + u64 res = (u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO(res, 1, 1); +} + +void recMULTU1_(int info) +{ + recMULTUsuper(info, 1, 0); +} + +void recMULTU1_consts(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTS); +} + +void recMULTU1_constt(int info) +{ + recMULTUsuper(info, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(MULTU1, XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)); + +//// DIV +void recDIV_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVsuper(int info, int sign, int upper, int process) +{ + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( process & PROCESS_CONSTT ) { + if( !g_cpuConstRegs[_Rt_].UL[0] ) + return; + MOV32ItoR( ECX, g_cpuConstRegs[_Rt_].UL[0] ); + } + else { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + } + + if( process & PROCESS_CONSTS ) + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + + if( sign ) { + CDQ(); + IDIV32R( ECX ); + } + else { + XOR32RtoR( EDX, EDX ); + DIV32R( ECX ); + } + if( !(process & PROCESS_CONSTT) ) x86SetJ8( j8Ptr[ 0 ] ); + + // need to execute regardless of bad divide + recWritebackHILO(info, 0, upper); +} + +void recDIV_(int info) +{ + recDIVsuper(info, 1, 0, 0); +} + +void recDIV_consts(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTS); +} + +void recDIV_constt(int info) +{ + recDIVsuper(info, 1, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +//// DIVU +void recDIVU_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 0); + } +} + +void recDIVU_(int info) +{ + recDIVsuper(info, 0, 0, 0); +} + +void recDIVU_consts(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTS); +} + +void recDIVU_constt(int info) +{ + recDIVsuper(info, 0, 0, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI); + +void recDIV1_const() +{ + if (g_cpuConstRegs[_Rt_].SL[0] != 0) { + s32 quot = g_cpuConstRegs[_Rs_].SL[0] / g_cpuConstRegs[_Rt_].SL[0]; + s32 rem = g_cpuConstRegs[_Rs_].SL[0] % g_cpuConstRegs[_Rt_].SL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIV1_(int info) +{ + recDIVsuper(info, 1, 1, 0); +} + +void recDIV1_consts(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTS); +} + +void recDIV1_constt(int info) +{ + recDIVsuper(info, 1, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIV1, XMMINFO_READS|XMMINFO_READT); + +void recDIVU1_const() +{ + if (g_cpuConstRegs[_Rt_].UL[0] != 0) { + u32 quot = g_cpuConstRegs[_Rs_].UL[0] / g_cpuConstRegs[_Rt_].UL[0]; + u32 rem = g_cpuConstRegs[_Rs_].UL[0] % g_cpuConstRegs[_Rt_].UL[0]; + + recWritebackConstHILO((u64)quot|((u64)rem<<32), 0, 1); + } +} + +void recDIVU1_(int info) +{ + recDIVsuper(info, 0, 1, 0); +} + +void recDIVU1_consts(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTS); +} + +void recDIVU1_constt(int info) +{ + recDIVsuper(info, 0, 1, PROCESS_CONSTT); +} + +EERECOMPILE_CODE0(DIVU1, XMMINFO_READS|XMMINFO_READT); + +//do EEINST_SETSIGNEXT +REC_FUNC( MADD, _Rd_ ); + +static PCSX2_ALIGNED16(u32 s_MaddMask[]) = { 0x80000000, 0, 0x80000000, 0 }; + +void recMADDU() +{ + _eeOnWriteReg(_Rd_, 1); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + u64 result = ((u64)g_cpuConstRegs[_Rs_].UL[0] * (u64)g_cpuConstRegs[_Rt_].UL[0]); + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + + // dadd + MOV32MtoR( EAX, (int)&cpuRegs.LO.UL[ 0 ] ); + MOV32MtoR( ECX, (int)&cpuRegs.HI.UL[ 0 ] ); + ADD32ItoR( EAX, (u32)result&0xffffffff ); + ADC32ItoR( ECX, (u32)(result>>32) ); + CDQ(); + if( _Rd_) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); + return; + } + + _deleteEEreg(XMMGPR_LO, 1); + _deleteEEreg(XMMGPR_HI, 1); + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteMMXreg(MMX_GPR+_Rs_, 1); + _deleteMMXreg(MMX_GPR+_Rt_, 1); + + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + else if ( GPR_IS_CONST1(_Rt_) ) { + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + + MOV32RtoR( ECX, EDX ); + ADD32MtoR( EAX, (u32)&cpuRegs.LO.UL[0] ); + ADC32MtoR( ECX, (u32)&cpuRegs.HI.UL[0] ); + CDQ(); + if( _Rd_ ) { + _deleteEEreg(_Rd_, 0); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + + MOV32RtoM( (int)&cpuRegs.LO.UL[0], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[1], EDX ); + + MOV32RtoM( (int)&cpuRegs.HI.UL[0], ECX ); + MOV32RtoR(EAX, ECX); + CDQ(); + MOV32RtoM( (int)&cpuRegs.HI.UL[1], EDX ); +} + +void recMADD1() +{ + SysPrintf("MADD1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + REC_FUNC_INLINE( MADD1, _Rd_ ); +} + +void recMADDU1() +{ + SysPrintf("MADDU1 email zero if abnormal behavior\n"); + EEINST_SETSIGNEXT(_Rs_); + EEINST_SETSIGNEXT(_Rt_); + if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); + _deleteEEreg(XMMGPR_LO, 0); + _deleteEEreg(XMMGPR_HI, 0); + REC_FUNC_INLINE( MADDU1, _Rd_ ); +} + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); + +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (int)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); + +} + +REC_FUNC( MULT1, _Rd_ ); +REC_FUNC( MULTU1, _Rd_ ); +REC_FUNC( DIV1, _Rd_ ); +REC_FUNC( DIVU1, _Rd_ ); + +REC_FUNC( MADD, _Rd_ ); +REC_FUNC( MADDU, _Rd_ ); +REC_FUNC( MADD1, _Rd_ ); +REC_FUNC( MADDU1, _Rd_ ); + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-32/iR5900Shift.c b/pcsx2/x86/ix86-32/iR5900Shift.c new file mode 100644 index 0000000..ff6ad41 --- /dev/null +++ b/pcsx2/x86/ix86-32/iR5900Shift.c @@ -0,0 +1,1353 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#elif defined(EE_CONST_PROP) + +//// SLL +void recSLL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << _Sa_); +} + +void recSLLs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( g_pCurInstInfo->regs[_Rd_]&EEINST_MMX ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + if( EEINST_ISLIVE1(_Rd_) ) _signExtendGPRtoMMX(rdreg, _Rd_, 0); + else EEINST_RESETHASLIVE1(_Rd_); + } +} + +void recSLL_(int info) +{ + recSLLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SLL); + +//// SRL +void recSRL_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> _Sa_); +} + +void recSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + // rdreg already sign extended + PSLLQItoR(rdreg, 32); + PSRLQItoR(rdreg, 32+sa); +// t0reg = _allocMMXreg(-1, MMX_TEMP, 0); +// +// // it is a signed shift +// PSRLDItoR(rdreg, sa); +// MOVQRtoR(t0reg, rdreg); +// PSRADItoR(t0reg, 31); +// +// take lower dword of rdreg and lower dword of t0reg +// PUNPCKLDQRtoR(rdreg, t0reg); +// _freeMMXreg(t0reg); + } +} + +void recSRL_(int info) +{ + recSRLs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRL); + +//// SRA +void recSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> _Sa_); +} + +void recSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + MOVDMtoMMX(rtreg, (u32)&cpuRegs.GPR.r[_Rt_].UL[0]); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) SAR32ItoR( EAX, sa); + + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADItoR(rdreg, sa); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(rdreg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(t0reg, rdreg); + + // swap regs + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recSRA_(int info) +{ + recSRAs_(info, _Sa_); + EEINST_SETSIGNEXT(_Rd_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, SRA); + +//////////////////////////////////////////////////// +void recDSLL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << _Sa_); +} + +void recDSLLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa); +} + +void recDSLL_(int info) +{ + recDSLLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL); + +//////////////////////////////////////////////////// +void recDSRL_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> _Sa_); +} + +void recDSRLs_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa); +} + +void recDSRL_(int info) +{ + recDSRLs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL); + +//// DSRA +void recDSRA_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> _Sa_); +} + +void recDSRAs_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, sa); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLQItoR(rdreg, sa); + return; + } + + if ( sa != 0 ) { + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + PSRADItoR(t0reg, sa); + PSRLQItoR(rdreg, sa); + + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + } +} + +void recDSRA_(int info) +{ + recDSRAs_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA); + +///// DSLL32 +void recDSLL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (_Sa_+32)); +} + +void recDSLL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( sa != 0 ) + { + SHL32ItoR( EAX, sa ); + } + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSLLQItoR(rdreg, sa+32); +} + +void recDSLL32_(int info) +{ + recDSLL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSLL32); + +//// DSRL32 +void recDSRL32_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (_Sa_+32)); +} + +void recDSRL32s_(int info, int sa) +{ + int rtreg, rdreg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + if ( sa != 0 ) SHR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + PSRLQItoR(rdreg, sa+32); +} + +void recDSRL32_(int info) +{ + recDSRL32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRL32); + +//// DSRA32 +void recDSRA32_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (u64)(g_cpuConstRegs[_Rt_].SD[0] >> (_Sa_+32)); +} + +void recDSRA32s_(int info, int sa) +{ + int rtreg, rdreg, t0reg; + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + rtreg = EEREC_T; + rdreg = EEREC_D; + } + else if( (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + } + else { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ( ); + if ( sa != 0 ) SAR32ItoR( EAX, sa ); + + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + if( EEINST_ISLIVE1(_Rd_) ) MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + else EEINST_RESETHASLIVE1(_Rd_); + return; + } + + if( rtreg != rdreg ) MOVQRtoR(rdreg, rtreg); + + if( EEINST_ISSIGNEXT(_Rt_) && EEINST_HASLIVE1(_Rt_) ) { + PSRADItoR(rdreg, 31); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + if( sa ) PSRADItoR(rdreg, sa); + PUNPCKHDQRtoR(rdreg, rdreg); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(t0reg, rtreg); + + // it is a signed shift + if( sa ) { + PSRADItoR(rdreg, sa); + PSRADItoR(t0reg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + } + else { + // better timing + PSRADItoR(rdreg, 31); + + // take higher dword of rdreg and lower dword of t0reg + PUNPCKHDQRtoR(t0reg, rdreg); + + // swap + mmxregs[t0reg] = mmxregs[rdreg]; + mmxregs[rdreg].inuse = 0; + } +} + +void recDSRA32_(int info) +{ + recDSRA32s_(info, _Sa_); +} + +EERECOMPILE_CODEX(eeRecompileCode2, DSRA32); + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +PCSX2_ALIGNED16(u32 s_sa[4]) = {0x1f, 0, 0x3f, 0}; + +int recSetShiftV(int info, int* rsreg, int* rtreg, int* rdreg, int* rstemp, int forcemmx, int shift64) +{ + assert( !(info & PROCESS_EE_XMM) ); + + if( info & PROCESS_EE_MMX ) { + *rtreg = EEREC_T; + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVE64(_Rs_)) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else if( forcemmx || (g_pCurInstInfo->regs[_Rt_]&EEINST_MMX) || (g_pCurInstInfo->regs[_Rd_]&EEINST_MMX) ) { + _addNeededMMXreg(MMX_GPR+_Rt_); + _addNeededMMXreg(MMX_GPR+_Rd_); + *rtreg = _allocMMXreg(-1, MMX_GPR+_Rt_, MODE_READ); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + else { + return 0; + } + + if( *rtreg != *rdreg ) MOVQRtoR(*rdreg, *rtreg); + return 1; +} + +void recSetConstShiftV(int info, int* rsreg, int* rdreg, int* rstemp, int shift64) +{ + if( info & PROCESS_EE_MMX ) { + *rdreg = EEREC_D; + *rsreg = EEREC_S; + + // make sure to take only low 5 bits of *rsreg + if( !(g_pCurInstInfo->regs[_Rs_]&EEINST_LASTUSE) && EEINST_ISLIVE64(_Rs_) ) { + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOVQRtoR(*rstemp, *rsreg); + *rsreg = *rstemp; + } + else { + if( *rsreg != *rdreg ) { + _freeMMXreg(*rsreg); + mmxregs[*rsreg].inuse = 0; + } + } + + PANDMtoR(*rsreg, (u32)&s_sa[shift64?2:0]); + + + if( EEREC_D == EEREC_S ) { + // need to be separate + int mmreg = _allocMMXreg(-1, MMX_TEMP, 0); + *rdreg = mmreg; + mmxregs[mmreg] = mmxregs[EEREC_S]; + mmxregs[EEREC_S].inuse = 0; + } + } + else { + _addNeededMMXreg(MMX_GPR+_Rd_); + *rdreg = _allocMMXreg(-1, MMX_GPR+_Rd_, MODE_WRITE); + SetMMXstate(); + + *rstemp = _allocMMXreg(-1, MMX_TEMP, 0); + MOV32MtoR(EAX, (u32)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND32ItoR(EAX, shift64?0x3f:0x1f); + MOVD32RtoMMX(*rstemp, EAX); + *rsreg = *rstemp; + } + + _flushConstReg(_Rt_); +} + +void recMoveSignToRd(int info) +{ + if( EEINST_ISLIVE1(_Rd_) ) { + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + else { + EEINST_RESETHASLIVE1(_Rd_); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + } + + if( info & PROCESS_EE_MMX ) { + mmxregs[EEREC_D].inuse = 0; + } +} + +//// SLLV +void recSLLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSLLV_consts(int info) +{ + recSLLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info & PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSLLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSLLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRLV +void recSRLV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].UL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRLV_consts(int info) +{ + recSRLs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRLDRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRLDRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// SRAV +void recSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s32)(g_cpuConstRegs[_Rt_].SL[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x1f)); +} + +void recSRAV_consts(int info) +{ + recSRAs_(info, g_cpuConstRegs[_Rs_].UL[0]&0x1f); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_constt(int info) +{ + if( (info & PROCESS_EE_MMX) && (info&PROCESS_EE_MODEWRITES) ) MOVD32MMXtoR(ECX, EEREC_S); + else MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + + MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + + recMoveSignToRd(info); + EEINST_SETSIGNEXT(_Rd_); +} + +void recSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg; + EEINST_SETSIGNEXT(_Rd_); + + if( recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 0, 0) == 0 ) { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + return; + } + + if( !EEINST_ISLIVE1(_Rd_) ) { + EEINST_RESETHASLIVE1(_Rd_); + PSRADRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); + return; + } + + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + + // it is a signed shift + PSRADRtoR(rdreg, rsreg); + MOVQRtoR(t0reg, rdreg); + PSRADItoR(t0reg, 31); + + // take lower dword of rdreg and lower dword of t0reg + PUNPCKLDQRtoR(rdreg, t0reg); + _freeMMXreg(t0reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(SRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSLLV +void recDSLLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] << (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSLLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSLLs_(info, sa); + else recDSLL32s_(info, sa-32); +} + +void recDSLLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSLLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSLLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSLLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRLV +void recDSRLV_const() +{ + g_cpuConstRegs[_Rd_].UD[0] = (u64)(g_cpuConstRegs[_Rt_].UD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRLV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRLs_(info, sa); + else recDSRL32s_(info, sa-32); +} + +void recDSRLV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1; + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRLV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1; + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PSRLQRtoR(rdreg, rsreg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRLV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +//// DSRAV +void recDSRAV_const() +{ + g_cpuConstRegs[_Rd_].SD[0] = (s64)(g_cpuConstRegs[_Rt_].SD[0] >> (g_cpuConstRegs[_Rs_].UL[0] &0x3f)); +} + +void recDSRAV_consts(int info) +{ + int sa = g_cpuConstRegs[_Rs_].UL[0]&0x3f; + if( sa < 32 ) recDSRAs_(info, sa); + else recDSRA32s_(info, sa-32); +} + +void recDSRAV_constt(int info) +{ + int rsreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + + recSetConstShiftV(info, &rsreg, &rdreg, &rstemp, 1); + + MOVQMtoR(rdreg, (u32)&cpuRegs.GPR.r[_Rt_]); + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +void recDSRAV_(int info) +{ + int rsreg, rtreg, rdreg, rstemp = -1, t0reg, t1reg; + t0reg = _allocMMXreg(-1, MMX_TEMP, 0); + t1reg = _allocMMXreg(-1, MMX_TEMP, 0); + recSetShiftV(info, &rsreg, &rtreg, &rdreg, &rstemp, 1, 1); + + PXORRtoR(t0reg, t0reg); + + // calc high bit + MOVQRtoR(t1reg, rdreg); + PCMPGTDRtoR(t0reg, rdreg); + PUNPCKHDQRtoR(t0reg, t0reg); // shift to lower + + // shift highest bit, 64 - eax + MOV32ItoR(EAX, 64); + MOVD32RtoMMX(t1reg, EAX); + PSUBDRtoR(t1reg, rsreg); + + // right logical shift + PSRLQRtoR(rdreg, rsreg); + PSLLQRtoR(t0reg, t1reg); // highest bits + + PORRtoR(rdreg, t0reg); + + _freeMMXreg(t0reg); + _freeMMXreg(t1reg); + if( rstemp != -1 ) _freeMMXreg(rstemp); +} + +EERECOMPILE_CODE0(DSRAV, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED); + +#else + +//////////////////////////////////////////////////// +void recDSRA( void ) +{ + if( !_Rd_ ) return; //? + + if ( _Sa_ != 0 ) { + // it is a signed shift + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoR(MM1, MM0); + PSRADItoR(MM0, _Sa_); + PSRLQItoR(MM1, _Sa_); + + PUNPCKHDQRtoR(MM0, MM0); // shift to lower + // take lower dword of MM1 and lower dword of MM0 + + PUNPCKLDQRtoR(MM1, MM0); + + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM1); + } + else { + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSRA32(void) +{ + if( !_Rd_ ) return; //? + + MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + CDQ(); + + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_ ); + } + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX); + MOV32RtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX); +} + +//////////////////////////////////////////////////// +void recSLL( void ) +{ + if ( ! _Rd_ ) + return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHL32ItoR( EAX, _Sa_ ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SHR32ItoR( EAX, _Sa_); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRA( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) + { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recDSLL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSLLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL( void ) +{ + if ( ! _Rd_ ) + { + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Sa_ != 0 ) + { + PSRLQItoR( MM0, _Sa_ ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); +} + +//////////////////////////////////////////////////// +void recDSLL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); + return; + } + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSLLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) +{ + if ( ! _Rd_ ) + { + return; + } + + + if ( _Sa_ == 0 ) + { + MOV32MtoR( EAX,(int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); + MOV32ItoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], 0 ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + return; + } + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + PSRLQItoR( MM0, _Sa_ + 32 ); + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + +//////////////////////////////////////////////////// + + +//////////////////////////////////////////////////// +void recSLLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRLV( void ) +{ + + if ( ! _Rd_ ) return; + + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +void recSRAV( void ) +{ + if ( ! _Rd_ ) return; + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + +} + +//////////////////////////////////////////////////// +static u64 _sa = 0; +void recDSLLV( void ) +{ + if ( ! _Rd_ ) return; + + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSLLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) +{ + if ( ! _Rd_ ) return; + MOVQMtoR( MM0, (int)&cpuRegs.GPR.r[ _Rt_ ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOV32RtoM( (int)&_sa, EAX ); + PSRLQMtoR( MM0, (int)&_sa ); + } + MOVQRtoM( (int)&cpuRegs.GPR.r[ _Rd_ ], MM0 ); + SetMMXstate(); + +} +//////////////////////////////////////////////////////////////// +void recDSRAV( void ) +{ + MOVQMtoR(MM0, (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + if ( _Rs_ != 0 ) { + PXORRtoR(MM1, MM1); + + // calc high bit + MOVQRtoR(MM2, MM0); + PUNPCKHDQRtoR(MM2, MM2); // shift to lower + PCMPGTDRtoR(MM1, MM2); + + // it is a signed shift + MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ] ); + AND32ItoR( EAX, 0x3f); + MOVD32RtoMMX(MM2, EAX); // amount to shift + NOT32R(EAX); + ADD32ItoR(EAX, 65); + + // right logical shift + PSRLQRtoR(MM0, MM2); + + // shift highest bit, 64 - eax + MOVD32RtoMMX(MM2, EAX); + PSLLQRtoR(MM1, MM2); // highest bits + + PORRtoR(MM0, MM1); + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + else { + MOVQRtoM((int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], MM0); + } + + SetMMXstate(); +} +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/aR3000A-64.asm b/pcsx2/x86/ix86-64/aR3000A-64.asm new file mode 100644 index 0000000..ff4aafc --- /dev/null +++ b/pcsx2/x86/ix86-64/aR3000A-64.asm @@ -0,0 +1,209 @@ +extern psxRegs:abs +extern psxRecLUT:abs +extern psxRecRecompile:near +extern b440:abs +extern b440table:abs +extern EEsCycle:abs + +.code + +recCheckF440 proc public + add dword ptr [b440], 1 + mov eax, dword ptr [b440] + sub eax, 3 + mov edx, 31 + + cmp eax, 27 + ja WriteVal + shl eax, 2 + cdqe + mov edx, dword ptr [rax+b440table] + +WriteVal: + mov dword ptr [18000000h+01000f440h], edx + ret +recCheckF440 endp + +R3000AInterceptor proc public + sub rsp, 48 + jmp rdx +R3000AInterceptor endp + +R3000AExecute proc public + + ;;while (EEsCycle > 0) { + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + +Execute_CheckCycles: + cmp dword ptr [EEsCycle], 0 + jle Execute_Exit + + ;;if ( !pblock->pFnptr || (pblock->startpc&PSX_MEMMASK) != (psxRegs.pc&PSX_MEMMASK) ) + ;; psxRecRecompile(psxRegs.pc); + + mov eax, dword ptr [psxRegs + 0208h] + mov ecx, eax + mov r12d, eax + shl rax, 32 + shr rax, 48 + and r12, 0fffch + shl rax, 3 + add rax, [psxRecLUT] + shl r12, 1 + add r12, [rax] + + mov r8d, [r12+4] + mov r9d, ecx + and r8d, 05fffffffh + and r9d, 05fffffffh + cmp r8d, r9d + jne Execute_Recompile + mov edx, [r12] + and rdx, 0fffffffh ;; pFnptr + jnz Execute_Function + +Execute_Recompile: + call psxRecRecompile + mov edx, [r12] + and rdx, 0fffffffh ;; pFnptr + +Execute_Function: + call R3000AInterceptor + + jmp Execute_CheckCycles + +Execute_Exit: + pop r15 + pop r14 + pop r13 + pop r12 + pop rdi + pop rsi + pop rbp + pop rbx + ret + +R3000AExecute endp + +psxDispatcher proc public + + mov [rsp+40], rdx + + mov eax, dword ptr [psxRegs + 0208h] + mov ecx, eax + mov r12d, eax + shl rax, 32 + shr rax, 48 + and r12, 0fffch + shl rax, 3 + add rax, [psxRecLUT] + shl r12, 1 + add r12, [rax] + + + mov eax, ecx + mov edx, [r12+4] + and eax, 5fffffffh + and edx, 5fffffffh + cmp eax, edx + je psxDispatcher_CheckPtr + + call psxRecRecompile +psxDispatcher_CheckPtr: + mov r12d, dword ptr [r12] + + and r12, 00fffffffh + mov rdx, r12 + mov rcx, [rsp+40] + sub rdx, rcx + sub rdx, 4 + mov [rcx], edx + + jmp r12 +psxDispatcher endp + +psxDispatcherClear proc public + + mov dword ptr [psxRegs + 0208h], edx + mov eax, edx + + + + mov r12d, edx + shl rax, 32 + shr rax, 48 + and r12, 0fffch + shl rax, 3 + add rax, [psxRecLUT] + shl r12, 1 + add r12, [rax] + + + mov ecx, edx + mov eax, ecx + mov edx, [r12+4] + and eax, 5fffffffh + and edx, 5fffffffh + cmp eax, edx + jne psxDispatcherClear_Recompile + + mov eax, dword ptr [r12] + + and rax, 00fffffffh + jmp rax + +psxDispatcherClear_Recompile: + call psxRecRecompile + mov eax, dword ptr [r12] + + + and rax, 00fffffffh + mov byte ptr [r15], 0e9h + mov rdx, rax + sub rdx, r15 + sub rdx, 5 + mov [r15+1], edx + + jmp rax +psxDispatcherClear endp + + +psxDispatcherReg proc public + + mov eax, dword ptr [psxRegs + 0208h] + mov ecx, eax + mov r12d, eax + shl rax, 32 + shr rax, 48 + and r12, 0fffch + shl rax, 3 + add rax, [psxRecLUT] + shl r12, 1 + add r12, [rax] + + + cmp ecx, dword ptr [r12+4] + jne psxDispatcherReg_recomp + + mov r12d, dword ptr [r12] + + and r12, 00fffffffh + jmp r12 + +psxDispatcherReg_recomp: + call psxRecRecompile + + mov eax, dword ptr [r12] + and rax, 00fffffffh + jmp rax + +psxDispatcherReg endp + +end diff --git a/pcsx2/x86/ix86-64/aR5900-64.S b/pcsx2/x86/ix86-64/aR5900-64.S new file mode 100644 index 0000000..0d1c447 --- /dev/null +++ b/pcsx2/x86/ix86-64/aR5900-64.S @@ -0,0 +1,255 @@ +// iR5900.c assembly routines +// zerofrog(@gmail.com) +.intel_syntax + +.extern cpuRegs +.extern recRecompile +.extern recLUT +.extern lbase +.extern s_pCurBlock_ltime +.extern g_EEFreezeRegs + +#define BLOCKTYPE_STARTPC 4 // startpc offset +#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot + +#define BASEBLOCK_SIZE 2 // in dwords +#define PCOFFSET 0x2a8 + +#define REG_PC %edi +#define REG_BLOCK %r14 // preserved across calls +#define REG_BLOCKd %r14d + +.globl R5900Execute + .type R5900Execute, @function +R5900Execute: + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + + // calc PC_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [cpuRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // g_EEFreezeRegs = 1; + mov dword ptr [g_EEFreezeRegs], 1 + + cmp REG_PC, [REG_BLOCK+4] + jne Execute_Recompile + mov %edx, [REG_BLOCK] + and %rdx, 0xfffffff // pFnptr + jnz Execute_Function + +Execute_Recompile: + call recRecompile + mov %edx, [REG_BLOCK] + and %rdx, 0xfffffff // pFnptr + +Execute_Function: + call %rdx + + // g_EEFreezeRegs = 0; + mov dword ptr [g_EEFreezeRegs], 0 + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + + ret + +.globl Dispatcher + .type Dispatcher, @function +Dispatcher: + // EDX contains the jump addr to modify + push %rdx + + // calc PC_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov %eax, dword ptr [cpuRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // check if startpc == cpuRegs.pc + //and %ecx, 0x5fffffff // remove higher bits + cmp REG_PC, dword ptr [REG_BLOCK+BLOCKTYPE_STARTPC] + je Dispatcher_CheckPtr + + // recompile + call recRecompile +Dispatcher_CheckPtr: + mov REG_BLOCKd, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test REG_BLOCKd, REG_BLOCKd + jnz Dispatcher_CallFn + // throw an exception + int 10 + +Dispatcher_CallFn: +#endif + + and REG_BLOCK, 0x0fffffff + mov %rdx, REG_BLOCK + pop %rcx // x86Ptr to mod + sub %rdx, %rcx + sub %rdx, 4 + mov [%rcx], %edx + + jmp REG_BLOCK + + +.globl DispatcherClear + .type DispatcherClear, @function +DispatcherClear: + // EDX contains the current pc + mov dword ptr [cpuRegs + PCOFFSET], %edx + mov %eax, %edx + + // calc PC_GETBLOCK + // ((BASEBLOCK*)(recLUT[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff))) + mov REG_BLOCKd, %edx + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + cmp %edx, dword ptr [REG_BLOCK + BLOCKTYPE_STARTPC] + jne DispatcherClear_Recompile + + mov %eax, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test %eax, %eax + jnz DispatcherClear_CallFn + // throw an exception + int 10 + +DispatcherClear_CallFn: +#endif + + and %rax, 0x0fffffff + jmp %rax + +DispatcherClear_Recompile: + mov REG_PC, %edx + call recRecompile + mov %eax, dword ptr [REG_BLOCK] + + // r15 holds the prev x86 pointer + and %rax, 0x0fffffff + mov byte ptr [%r15], 0xe9 // jmp32 + mov %rdx, %rax + sub %rdx, %r15 + sub %rdx, 5 + mov [%r15+1], %edx + + jmp %rax + + + +// called when jumping to variable pc address +.globl DispatcherReg + .type DispatcherReg, @function +DispatcherReg: + //s_pDispatchBlock = PC_GETBLOCK(cpuRegs.pc) + mov %eax, dword ptr [cpuRegs + PCOFFSET] + mov REG_PC, %eax + mov REG_BLOCKd, %eax + shl %rax, 32 + shr %rax, 48 + and REG_BLOCK, 0xfffc + shl %rax, 3 + add %rax, [recLUT] + shl REG_BLOCK, 1 + add REG_BLOCK, [%rax] + + // check if startpc == cpuRegs.pc + //and %eax, 0x5fffffff // remove higher bits + cmp REG_PC, dword ptr [REG_BLOCK+BLOCKTYPE_STARTPC] + jne DispatcherReg_recomp + + mov REG_BLOCKd, dword ptr [REG_BLOCK] + +#ifdef _DEBUG + test REG_BLOCKd, REG_BLOCKd + jnz CallFn2 + // throw an exception + int 10 + +CallFn2: + +#endif + + and REG_BLOCK, 0x0fffffff + jmp REG_BLOCK // fnptr + +DispatcherReg_recomp: + call recRecompile + + mov %eax, dword ptr [REG_BLOCK] + and %rax, 0x0fffffff + jmp %rax // fnptr + + +.globl _StartPerfCounter + .type _StartPerfCounter, @function +_StartPerfCounter: + + push %rax + push %rbx + push %rcx + + rdtsc + mov dword ptr [lbase], %eax + mov dword ptr [lbase + 4], %edx + + pop %rcx + pop %rbx + pop %rax + ret + +.globl _StopPerfCounter + .type _StopPerfCounter, @function +_StopPerfCounter: + + push %rax + push %rbx + push %rcx + + rdtsc + + sub %eax, dword ptr [lbase] + sbb %edx, dword ptr [lbase + 4] + mov %ecx, s_pCurBlock_ltime + add %eax, dword ptr [%ecx] + adc %edx, dword ptr [%ecx + 4] + mov dword ptr [%ecx], %eax + mov dword ptr [%ecx + 4], %edx + pop %rcx + pop %rbx + pop %rax + ret diff --git a/pcsx2/x86/ix86-64/aR5900-64.asm b/pcsx2/x86/ix86-64/aR5900-64.asm new file mode 100644 index 0000000..4f026c9 --- /dev/null +++ b/pcsx2/x86/ix86-64/aR5900-64.asm @@ -0,0 +1,261 @@ +extern cpuRegs:abs +extern recRecompile:near +extern recLUT:abs +extern lbase:abs +extern s_pCurBlock_ltime:abs + +extern g_globalXMMData:abs +extern g_globalXMMSaved:abs +extern g_EEFreezeRegs:abs + +.code + +FreezeXMMRegs_ proc public + ;;assert( g_EEFreezeRegs ); + test ecx, ecx + jz XMMRestore + + cmp byte ptr [g_globalXMMSaved], 0 + jne XMMSaveEnd + + mov byte ptr [g_globalXMMSaved], 1 + + movaps xmmword ptr [g_globalXMMData + 000h], xmm0 + movaps xmmword ptr [g_globalXMMData + 010h], xmm1 + movaps xmmword ptr [g_globalXMMData + 020h], xmm2 + movaps xmmword ptr [g_globalXMMData + 030h], xmm3 + movaps xmmword ptr [g_globalXMMData + 040h], xmm4 + movaps xmmword ptr [g_globalXMMData + 050h], xmm5 + movaps xmmword ptr [g_globalXMMData + 060h], xmm6 + movaps xmmword ptr [g_globalXMMData + 070h], xmm7 + +XMMSaveEnd: + ret + +XMMRestore: + + cmp byte ptr [g_globalXMMSaved], 0 + je XMMSaveEnd + + mov byte ptr [g_globalXMMSaved], 0 + + ;; TODO: really need to backup all regs? + movaps xmm0, xmmword ptr [g_globalXMMData + 000h] + movaps xmm1, xmmword ptr [g_globalXMMData + 010h] + movaps xmm2, xmmword ptr [g_globalXMMData + 020h] + movaps xmm3, xmmword ptr [g_globalXMMData + 030h] + movaps xmm4, xmmword ptr [g_globalXMMData + 040h] + movaps xmm5, xmmword ptr [g_globalXMMData + 050h] + movaps xmm6, xmmword ptr [g_globalXMMData + 060h] + movaps xmm7, xmmword ptr [g_globalXMMData + 070h] + +XMMRestoreEnd: + ret + +FreezeXMMRegs_ endp + +R5900Interceptor proc public + sub rsp, 48 + jmp rdx +R5900Interceptor endp + +R5900Execute proc public + + push rbx + push rbp + push rsi + push rdi + push r12 + push r13 + push r14 + push r15 + + ;;BASEBLOCK* pblock = PC_GETBLOCK(cpuRegs.pc); + mov eax, dword ptr [cpuRegs + 02a8h] + mov ecx, eax + mov r14d, eax + shl rax, 32 + shr rax, 48 + and r14, 0fffch + shl rax, 3 + add rax, [recLUT] + shl r14, 1 + add r14, [rax] + + ;; g_EEFreezeRegs = 1; + mov dword ptr [g_EEFreezeRegs], 1 + + cmp ecx, [r14+4] + jne Execute_Recompile + mov edx, [r14] + and rdx, 0fffffffh ;; pFnptr + jnz Execute_Function + +Execute_Recompile: + call recRecompile + mov edx, [r14] + and rdx, 0fffffffh ;; pFnptr + +Execute_Function: + call R5900Interceptor + + ;; g_EEFreezeRegs = 0; + mov dword ptr [g_EEFreezeRegs], 0 + + pop r15 + pop r14 + pop r13 + pop r12 + pop rdi + pop rsi + pop rbp + pop rbx + + ret + +R5900Execute endp + +Dispatcher proc public + + mov [rsp+40], rdx + + mov eax, dword ptr [cpuRegs + 02a8h] + mov ecx, eax + mov r14d, eax + shl rax, 32 + shr rax, 48 + and r14, 0fffch + shl rax, 3 + add rax, [recLUT] + shl r14, 1 + add r14, [rax] + + + + cmp ecx, dword ptr [r14+4] + je Dispatcher_CheckPtr + + + call recRecompile +Dispatcher_CheckPtr: + mov r14d, dword ptr [r14] + + and r14, 0fffffffh + mov rdx, r14 + mov rcx, [rsp+40] + sub rdx, rcx + sub rdx, 4 + mov [rcx], edx + + jmp r14 +Dispatcher endp + +DispatcherClear proc public + + mov dword ptr [cpuRegs + 02a8h], edx + mov eax, edx + + + + mov r14d, edx + shl rax, 32 + shr rax, 48 + and r14, 0fffch + shl rax, 3 + add rax, [recLUT] + shl r14, 1 + add r14, [rax] + + cmp edx, dword ptr [r14 + 4] + jne DispatcherClear_Recompile + + mov eax, dword ptr [r14] + + and rax, 0fffffffh + jmp rax + +DispatcherClear_Recompile: + mov ecx, edx + call recRecompile + mov eax, dword ptr [r14] + + + and rax, 0fffffffh + mov byte ptr [r15], 0e9h + mov rdx, rax + sub rdx, r15 + sub rdx, 5 + mov [r15+1], edx + + jmp rax +DispatcherClear endp + + + +DispatcherReg proc public + + mov eax, dword ptr [cpuRegs + 02a8h] + mov ecx, eax + mov r14d, eax + shl rax, 32 + shr rax, 48 + and r14, 0fffch + shl rax, 3 + add rax, [recLUT] + shl r14, 1 + add r14, [rax] + + + + cmp ecx, dword ptr [r14+4] + jne DispatcherReg_recomp + + mov r14d, dword ptr [r14] + + and r14, 0fffffffh + jmp r14 + +DispatcherReg_recomp: + call recRecompile + + mov eax, dword ptr [r14] + and rax, 0fffffffh + jmp rax +DispatcherReg endp + +_StartPerfCounter proc public + push rax + push rbx + push rcx + + rdtsc + mov dword ptr [lbase], eax + mov dword ptr [lbase + 4], edx + + pop rcx + pop rbx + pop rax + ret +_StartPerfCounter endp + +_StopPerfCounter proc public + push rax + push rbx + push rcx + + rdtsc + + sub eax, dword ptr [lbase] + sbb edx, dword ptr [lbase + 4] + mov ecx, [s_pCurBlock_ltime] + add eax, dword ptr [ecx] + adc edx, dword ptr [ecx + 4] + mov dword ptr [ecx], eax + mov dword ptr [ecx + 4], edx + pop rcx + pop rbx + pop rax + ret +_StopPerfCounter endp + +end diff --git a/pcsx2/x86/ix86-64/aVUzerorec-64.asm b/pcsx2/x86/ix86-64/aVUzerorec-64.asm new file mode 100644 index 0000000..9a7452e --- /dev/null +++ b/pcsx2/x86/ix86-64/aVUzerorec-64.asm @@ -0,0 +1,110 @@ +;; iR3000A.c assembly routines +;; zerofrog(@gmail.com) +extern svudispfntemp:near +extern s_TotalVUCycles:abs +extern s_callstack:ptr +extern s_vu1esp:abs +extern s_writeQ:abs +extern s_writeP:abs +extern g_curdebugvu:abs +extern SuperVUGetProgram:near +extern SuperVUCleanupProgram:near +extern g_sseVUMXCSR:abs +extern g_sseMXCSR:abs + +.code + +;; SuperVUExecuteProgram(u32 startpc, int vuindex) +SuperVUExecuteProgram proc public + mov rax, [rsp] + mov dword ptr [s_TotalVUCycles], 0 + + sub rsp, 48-8+80 + mov [rsp+48], rcx + mov [rsp+56], rdx + + mov [s_callstack], rax + + call SuperVUGetProgram + + mov [rsp+64], rbp + mov [rsp+72], rsi + mov [rsp+80], rdi + mov [rsp+88], rbx + mov [rsp+96], r12 + mov [rsp+104], r13 + mov [rsp+112], r14 + mov [rsp+120], r15 + + ;; _DEBUG + ;;mov [s_vu1esp], rsp + + ldmxcsr [g_sseVUMXCSR] + mov dword ptr [s_writeQ], 0ffffffffh + mov dword ptr [s_writeP], 0ffffffffh + jmp rax +SuperVUExecuteProgram endp + +SuperVUEndProgram proc public + ;; restore cpu state + ldmxcsr [g_sseMXCSR] + + mov rcx, [rsp+48] + mov rdx, [rsp+56] + mov rbp, [rsp+64] + mov rsi, [rsp+72] + mov rdi, [rsp+80] + mov rbx, [rsp+88] + mov r12, [rsp+96] + mov r13, [rsp+104] + mov r14, [rsp+112] + mov r15, [rsp+120] + + ;; _DEBUG + ;;sub [s_vu1esp], rsp + + add rsp, 128-32 + call SuperVUCleanupProgram + add rsp, 32 + jmp [s_callstack] ;; so returns correctly +SuperVUEndProgram endp + +svudispfn proc public + mov [g_curdebugvu], rax + push rcx + push rdx + push rbp + push rsi + push rdi + push rbx + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + + sub rsp, 32 + call svudispfntemp + add rsp, 32 + + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbx + pop rdi + pop rsi + pop rbp + pop rdx + pop rcx + ret +svudispfn endp + +end diff --git a/pcsx2/x86/ix86-64/aVif_proc-64.asm b/pcsx2/x86/ix86-64/aVif_proc-64.asm new file mode 100644 index 0000000..41bf682 --- /dev/null +++ b/pcsx2/x86/ix86-64/aVif_proc-64.asm @@ -0,0 +1,1787 @@ +extern _vifRegs:abs +extern _vifMaskRegs:abs +extern _vifRow:abs +extern _vifCol:abs +extern s_TempDecompress:abs + + +.code + +UNPACK_Write0_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [rcx+DEST_OFFSET], r0 + endm + +UNPACK_Write1_Regular macro r0, CL, DEST_OFFSET, MOVDQA + MOVDQA [rcx], r0 + add rcx, rdi + endm + +UNPACK_Write0_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write0_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + +UNPACK_Write1_Mask macro r0, CL, DEST_OFFSET, MOVDQA + UNPACK_Write1_Regular r0, CL, DEST_OFFSET, MOVDQA + endm + + +UNPACK_Write0_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + + movdqa xmm3, [rax + 64*(CL) + 48] + pand r0, xmm3 + pandn xmm3, [rcx] + por r0, xmm3 + MOVDQA [rcx], r0 + add rcx, 16 + endm + + +UNPACK_Write1_WriteMask macro r0, CL, DEST_OFFSET, MOVDQA + + movdqa xmm3, [rax + 64*(0) + 48] + pand r0, xmm3 + pandn xmm3, [rcx] + por r0, xmm3 + MOVDQA [rcx], r0 + add rcx, rdi + endm + +UNPACK_Mask_SSE_0 macro r0 + pand r0, xmm3 + por r0, xmm5 + endm + + + + +UNPACK_Mask_SSE_1 macro r0 + + pand r0, xmm3 + por r0, xmm5 + pand xmm3, xmm6 + paddd r0, xmm3 + endm + + + +UNPACK_Mask_SSE_2 macro r0 + + + pand r0, xmm3 + pand xmm3, xmm6 + paddd xmm6, r0 + por r0, xmm5 + paddd r0, xmm3 + endm + +UNPACK_WriteMask_SSE_0 macro r0 + UNPACK_Mask_SSE_0 r0 + endm +UNPACK_WriteMask_SSE_1 macro r0 + UNPACK_Mask_SSE_1 r0 + endm +UNPACK_WriteMask_SSE_2 macro r0 + UNPACK_Mask_SSE_2 r0 + endm + +UNPACK_Regular_SSE_0 macro r0 + endm + +UNPACK_Regular_SSE_1 macro r0 + paddd r0, xmm6 + endm + +UNPACK_Regular_SSE_2 macro r0 + paddd r0, xmm6 + movdqa xmm6, r0 + endm + + +UNPACK_Setup_Mask_SSE macro CL + mov rax, [_vifMaskRegs] + movdqa xmm4, [rax + 64*(CL) + 16] + movdqa xmm5, [rax + 64*(CL) + 32] + movdqa xmm3, [rax + 64*(CL)] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Start_Setup_Mask_SSE_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + +UNPACK_Start_Setup_Mask_SSE_1 macro CL + mov rax, [_vifMaskRegs] + movdqa xmm4, [rax + 64*(CL) + 16] + movdqa xmm5, [rax + 64*(CL) + 32] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Start_Setup_Mask_SSE_2 macro CL + endm + +UNPACK_Setup_Mask_SSE_0_1 macro CL + endm +UNPACK_Setup_Mask_SSE_1_1 macro CL + mov rax, [_vifMaskRegs] + movdqa xmm3, [rax + 64*(0)] + endm + + +UNPACK_Setup_Mask_SSE_2_1 macro CL + + mov rax, [_vifMaskRegs] + movdqa xmm4, [rax + 64*(0) + 16] + movdqa xmm5, [rax + 64*(0) + 32] + movdqa xmm3, [rax + 64*(0)] + pand xmm4, xmm6 + pand xmm5, xmm7 + por xmm5, xmm4 + endm + +UNPACK_Setup_Mask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_Mask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm + + +UNPACK_Setup_WriteMask_SSE_0_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_1_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_2_0 macro CL + UNPACK_Setup_Mask_SSE CL + endm +UNPACK_Setup_WriteMask_SSE_0_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_1_1 macro CL + UNPACK_Setup_Mask_SSE_1_1 CL + endm + +UNPACK_Setup_WriteMask_SSE_2_1 macro CL + UNPACK_Setup_Mask_SSE_2_1 CL + endm + +UNPACK_Start_Setup_WriteMask_SSE_0 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_1 macro CL + UNPACK_Start_Setup_Mask_SSE_1 CL + endm +UNPACK_Start_Setup_WriteMask_SSE_2 macro CL + UNPACK_Start_Setup_Mask_SSE_2 CL + endm + +UNPACK_Start_Setup_Regular_SSE_0 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_1 macro CL + endm +UNPACK_Start_Setup_Regular_SSE_2 macro CL + endm +UNPACK_Setup_Regular_SSE_0_0 macro CL + endm +UNPACK_Setup_Regular_SSE_1_0 macro CL + endm +UNPACK_Setup_Regular_SSE_2_0 macro CL + endm +UNPACK_Setup_Regular_SSE_0_1 macro CL + endm +UNPACK_Setup_Regular_SSE_1_1 macro CL + endm +UNPACK_Setup_Regular_SSE_2_1 macro CL + endm + +UNPACK_INC_DST_0_Regular macro qw + add rcx, (16*qw) + endm +UNPACK_INC_DST_1_Regular macro qw + endm +UNPACK_INC_DST_0_Mask macro qw + add rcx, (16*qw) + endm +UNPACK_INC_DST_1_Mask macro qw + endm +UNPACK_INC_DST_0_WriteMask macro qw + endm +UNPACK_INC_DST_1_WriteMask macro qw + endm + + +UNPACK4_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm7 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm7, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + endm + + +UNPACK3_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + endm + +UNPACK2_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 2 + endm + +UNPACK1_SSE macro CL, TOTALCL, MaskType, ModeType + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 1 + endm + + + +UNPACK_S_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm7, [rdx] + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_S_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm2, [rdx] + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_S_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_S_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_S_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm1, QWORD PTR [rdx] + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_S_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_S_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_S_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm7, QWORD PTR [rdx] + punpcklwd xmm7, xmm7 + UNPACK_RIGHTSHIFT xmm7, 16 + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_S_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm2, QWORD PTR [rdx] + punpcklwd xmm2, xmm2 + UNPACK_RIGHTSHIFT xmm2, 16 + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + add rdx, 6 + endm + +UNPACK_S_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm1, dword ptr [rdx] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm1, 16 + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_S_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 2 + endm + +UNPACK_S_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_S_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movd xmm7, dword ptr [rdx] + punpcklbw xmm7, xmm7 + punpcklwd xmm7, xmm7 + UNPACK_RIGHTSHIFT xmm7, 24 + + pshufd xmm0, xmm7, 0 + pshufd xmm1, xmm7, 055h + pshufd xmm2, xmm7, 0aah + pshufd xmm7, xmm7, 0ffh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_S_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd xmm2, dword ptr [rdx] + punpcklbw xmm2, xmm2 + punpcklwd xmm2, xmm2 + UNPACK_RIGHTSHIFT xmm2, 24 + + pshufd xmm0, xmm2, 0 + pshufd xmm1, xmm2, 055h + pshufd xmm2, xmm2, 0aah + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 3 + endm + +UNPACK_S_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm1, dword ptr [rdx] + punpcklbw xmm1, xmm1 + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm1, 24 + + pshufd xmm0, xmm1, 0 + pshufd xmm1, xmm1, 055h + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 2 + endm + +UNPACK_S_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_S_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + pshufd xmm0, xmm0, 0 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + inc rdx + endm + +UNPACK_S_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_S_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V2_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + MOVDQA xmm0, [rdx] + MOVDQA xmm2, [rdx+16] + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V2_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+8] + movq xmm2, QWORD PTR [rdx+16] + movq xmm7, QWORD PTR [rdx+24] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V2_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + MOVDQA xmm0, [rdx] + movq xmm2, QWORD PTR [rdx+16] + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V2_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+8] + movq xmm2, QWORD PTR [rdx+16] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V2_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+8] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V2_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V2_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_32SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V2_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + punpckhwd xmm2, [rdx] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + add rdx, 16 + endm + +UNPACK_V2_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V2_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + punpckhwd xmm2, [rdx] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V2_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V2_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + UNPACK_RIGHTSHIFT xmm0, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V2_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V2_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_V2_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + + +UNPACK_V2_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + + punpcklbw xmm0, xmm0 + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + + pshufd xmm1, xmm0, 0eeh + pshufd xmm7, xmm2, 0eeh + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V2_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + + punpcklbw xmm0, xmm0 + punpckhwd xmm2, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 6 + endm + +UNPACK_V2_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + + pshufd xmm1, xmm0, 0eeh + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_V2_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V2_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 2 + endm + +UNPACK_V2_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V2_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V3_32SSE_4x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [rdx] + movdqu xmm1, [rdx+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+0 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + + MOVDQA xmm7, [rdx+32] + movdqu xmm2, [rdx+24] + psrldq xmm7, 4 + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+3 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm7 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm7, CL+3, 48, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 4 + + add rdx, 48 + endm + +UNPACK_V3_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_4x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_3x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [rdx] + movdqu xmm1, [rdx+12] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm0 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm0, CL, 0, movdqa + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+1 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm1 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm1, CL+1, 16, movdqa + + movdqu xmm2, [rdx+24] + + @CatStr(UNPACK_Setup_, MaskType, _SSE_, ModeType, _, TOTALCL) CL+2 + @CatStr(UNPACK_, MaskType, _SSE_, ModeType) xmm2 + @CatStr(UNPACK_Write, TOTALCL, _, MaskType) xmm2, CL+2, 32, movdqa + + @CatStr(UNPACK_INC_DST_, TOTALCL, _, MaskType) 3 + + add rdx, 36 + endm + +UNPACK_V3_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_3x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_2x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [rdx] + movdqu xmm1, [rdx+12] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V3_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_2x CL, TOTALCL, MaskType, ModeType, movdqu + endm + +UNPACK_V3_32SSE_1x macro CL, TOTALCL, MaskType, ModeType, MOVDQA + MOVDQA xmm0, [rdx] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V3_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqa + endm +UNPACK_V3_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_32SSE_1x CL, TOTALCL, MaskType, ModeType, movdqu + endm + + +UNPACK_V3_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+6] + + punpcklwd xmm0, xmm0 + movq xmm2, QWORD PTR [rdx+12] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 16 + movq xmm7, QWORD PTR [rdx+18] + UNPACK_RIGHTSHIFT xmm1, 16 + punpcklwd xmm2, xmm2 + punpcklwd xmm7, xmm7 + + UNPACK_RIGHTSHIFT xmm2, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V3_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+6] + + punpcklwd xmm0, xmm0 + movq xmm2, QWORD PTR [rdx+12] + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 16 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 18 + endm + +UNPACK_V3_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+6] + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V3_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 6 + endm + +UNPACK_V3_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_16SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V3_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movq xmm1, QWORD PTR [rdx] + movq xmm7, QWORD PTR [rdx+6] + + punpcklbw xmm1, xmm1 + punpcklbw xmm7, xmm7 + punpcklwd xmm0, xmm1 + psrldq xmm1, 6 + punpcklwd xmm2, xmm7 + psrldq xmm7, 6 + punpcklwd xmm1, xmm1 + UNPACK_RIGHTSHIFT xmm0, 24 + punpcklwd xmm7, xmm7 + + UNPACK_RIGHTSHIFT xmm2, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm7, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V3_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + movd xmm1, dword ptr [rdx+3] + + punpcklbw xmm0, xmm0 + movd xmm2, dword ptr [rdx+6] + punpcklbw xmm1, xmm1 + punpcklwd xmm0, xmm0 + punpcklbw xmm2, xmm2 + + punpcklwd xmm1, xmm1 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 9 + endm + +UNPACK_V3_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + movd xmm1, dword ptr [rdx+3] + + punpcklbw xmm0, xmm0 + punpcklbw xmm1, xmm1 + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 6 + endm + +UNPACK_V3_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V3_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 3 + endm + +UNPACK_V3_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V3_8SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +UNPACK_V4_32SSE_4A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [rdx] + movdqa xmm1, [rdx+16] + movdqa xmm2, [rdx+32] + movdqa xmm7, [rdx+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 64 + endm + +UNPACK_V4_32SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + movdqu xmm1, [rdx+16] + movdqu xmm2, [rdx+32] + movdqu xmm7, [rdx+48] + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 64 + endm + +UNPACK_V4_32SSE_3A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [rdx] + movdqa xmm1, [rdx+16] + movdqa xmm2, [rdx+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 48 + endm + +UNPACK_V4_32SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + movdqu xmm1, [rdx+16] + movdqu xmm2, [rdx+32] + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 48 + endm + +UNPACK_V4_32SSE_2A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [rdx] + movdqa xmm1, [rdx+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V4_32SSE_2 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + movdqu xmm1, [rdx+16] + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V4_32SSE_1A macro CL, TOTALCL, MaskType, ModeType + movdqa xmm0, [rdx] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V4_32SSE_1 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + + +UNPACK_V4_16SSE_4A macro CL, TOTALCL, MaskType, ModeType + + punpcklwd xmm0, [rdx] + punpckhwd xmm1, [rdx] + punpcklwd xmm2, [rdx+16] + punpckhwd xmm7, [rdx+16] + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V4_16SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + movdqu xmm2, [rdx+16] + + punpckhwd xmm1, xmm0 + punpckhwd xmm7, xmm2 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm7, 16 + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 32 + endm + +UNPACK_V4_16SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + punpckhwd xmm1, [rdx] + punpcklwd xmm2, [rdx+16] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V4_16SSE_3 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + movq xmm2, QWORD PTR [rdx+16] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + UNPACK_RIGHTSHIFT xmm2, 16 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 24 + endm + +UNPACK_V4_16SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + punpckhwd xmm1, [rdx] + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V4_16SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movq xmm1, QWORD PTR [rdx+8] + + punpcklwd xmm0, xmm0 + punpcklwd xmm1, xmm1 + + UNPACK_RIGHTSHIFT xmm0, 16 + UNPACK_RIGHTSHIFT xmm1, 16 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V4_16SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklwd xmm0, [rdx] + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V4_16SSE_1 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 16 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + + +UNPACK_V4_8SSE_4A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [rdx] + punpckhbw xmm2, [rdx] + + punpckhwd xmm1, xmm0 + punpckhwd xmm7, xmm2 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm7, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V4_8SSE_4 macro CL, TOTALCL, MaskType, ModeType + movdqu xmm0, [rdx] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm7, xmm2 + punpckhwd xmm1, xmm0 + punpcklwd xmm2, xmm2 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm7, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm1, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 16 + endm + +UNPACK_V4_8SSE_3A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [rdx] + punpckhbw xmm2, [rdx] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V4_8SSE_3 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + movd xmm2, dword ptr [rdx+8] + + punpcklbw xmm0, xmm0 + punpcklbw xmm2, xmm2 + + punpckhwd xmm1, xmm0 + punpcklwd xmm2, xmm2 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + UNPACK_RIGHTSHIFT xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 12 + endm + +UNPACK_V4_8SSE_2A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [rdx] + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V4_8SSE_2 macro CL, TOTALCL, MaskType, ModeType + movq xmm0, QWORD PTR [rdx] + + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + UNPACK_RIGHTSHIFT xmm1, 24 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V4_8SSE_1A macro CL, TOTALCL, MaskType, ModeType + punpcklbw xmm0, [rdx] + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_V4_8SSE_1 macro CL, TOTALCL, MaskType, ModeType + movd xmm0, dword ptr [rdx] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + UNPACK_RIGHTSHIFT xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + + +DECOMPRESS_RGBA macro OFFSET + mov bl, al + shl bl, 3 + mov byte ptr [s_TempDecompress+OFFSET], bl + + mov bx, ax + shr bx, 2 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+1], bl + + mov bx, ax + shr bx, 7 + and bx, 0f8h + mov byte ptr [s_TempDecompress+OFFSET+2], bl + mov bx, ax + shr bx, 8 + and bx, 080h + mov byte ptr [s_TempDecompress+OFFSET+3], bl + endm + +UNPACK_V4_5SSE_4 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [rdx] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [rdx+4] + DECOMPRESS_RGBA 8 + + shr eax, 16 + DECOMPRESS_RGBA 12 + + + movdqa xmm0, XMMWORD PTR [s_TempDecompress] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm7, xmm2 + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + psrld xmm0, 24 + psrld xmm1, 24 + psrld xmm2, 24 + psrld xmm7, 24 + + UNPACK4_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 8 + endm + +UNPACK_V4_5SSE_4A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_4 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_3 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [rdx] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + mov eax, dword ptr [rdx] + DECOMPRESS_RGBA 8 + + + movdqa xmm0, XMMWORD PTR [s_TempDecompress] + + punpckhbw xmm2, xmm0 + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + punpcklwd xmm2, xmm2 + + psrld xmm0, 24 + psrld xmm1, 24 + psrld xmm2, 24 + + UNPACK3_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 6 + endm + +UNPACK_V4_5SSE_3A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_3 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_2 macro CL, TOTALCL, MaskType, ModeType + mov eax, dword ptr [rdx] + DECOMPRESS_RGBA 0 + + shr eax, 16 + DECOMPRESS_RGBA 4 + + movq xmm0, QWORD PTR [s_TempDecompress] + + punpcklbw xmm0, xmm0 + + punpckhwd xmm1, xmm0 + punpcklwd xmm0, xmm0 + + psrld xmm0, 24 + psrld xmm1, 24 + + UNPACK2_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 4 + endm + +UNPACK_V4_5SSE_2A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_2 CL, TOTALCL, MaskType, ModeType + endm + +UNPACK_V4_5SSE_1 macro CL, TOTALCL, MaskType, ModeType + mov ax, word ptr [rdx] + DECOMPRESS_RGBA 0 + + movd xmm0, DWORD PTR [s_TempDecompress] + punpcklbw xmm0, xmm0 + punpcklwd xmm0, xmm0 + + psrld xmm0, 24 + + UNPACK1_SSE CL, TOTALCL, MaskType, ModeType + + add rdx, 2 + endm + +UNPACK_V4_5SSE_1A macro CL, TOTALCL, MaskType, ModeType + UNPACK_V4_5SSE_1 CL, TOTALCL, MaskType, ModeType + endm + + +SAVE_ROW_REG_BASE macro + mov rax, [_vifRow] + movdqa [rax], xmm6 + mov rax, [_vifRegs] + movss dword ptr [rax+0100h], xmm6 + psrldq xmm6, 4 + movss dword ptr [rax+0110h], xmm6 + psrldq xmm6, 4 + movss dword ptr [rax+0120h], xmm6 + psrldq xmm6, 4 + movss dword ptr [rax+0130h], xmm6 + endm + +SAVE_NO_REG macro + endm + + + +INIT_ARGS macro + mov rax, qword ptr [_vifRow] + mov r9, qword ptr [_vifCol] + movaps xmm6, XMMWORD PTR [rax] + movaps xmm7, XMMWORD PTR [r9] + endm + +INC_STACK macro reg + add esp, 8 + endm + + + +defUNPACK_SkippingWrite macro name, MaskType, ModeType, qsize, sign, SAVE_ROW_REG +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType) proc public + + push rdi + INIT_ARGS + mov rax, [_vifRegs] + movzx rdi, byte ptr [rax + 040h] + movzx r9, byte ptr [rax + 041h] + sub rdi, r9 + shl rdi, 4 + + cmp r9d, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1) + cmp r9d, 2 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2) + cmp r9d, 3 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL1): + @CatStr(UNPACK_Start_Setup_, MaskType, _SSE_, ModeType) 0 + + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + + add rdi, 16 + + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16): + + test rdx, 15 + jz @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned) + + @CatStr(UNPACK_, name, SSE_1) 0, 1, MaskType, ModeType + + cmp r8d, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec) + sub r8d, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Align16) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_UnpackAligned): + + cmp r8d, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp r8d, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + cmp r8d, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3) + prefetchnta [rdx + 64] + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4): + @CatStr(UNPACK_, name, SSE_4A) 0, 1, MaskType, ModeType + + cmp r8d, (8*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4) + sub r8d, (4*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack4) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneUnpack4): + + sub r8d, (4*qsize) + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + cmp r8d, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1) + cmp r8d, (3*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2) + + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack3): + @CatStr(UNPACK_, name, SSE_3A) 0, 1, MaskType, ModeType + + sub r8d, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack2): + @CatStr(UNPACK_, name, SSE_2A) 0, 1, MaskType, ModeType + + sub r8d, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Unpack1): + @CatStr(UNPACK_, name, SSE_1A) 0, 1, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_DoneWithDec): + sub r8d, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C1_Done3): + SAVE_ROW_REG + mov eax, r8d + + pop rdi + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL2): + cmp r8d, (2*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + + add rcx, rdi + cmp r8d, (4*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2) + sub r8d, (2*qsize) + + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Unpack) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done2): + sub r8d, (2*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done3): + cmp r8d, qsize + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4) + + + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + sub r8d, qsize +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C2_Done4): + + SAVE_ROW_REG + mov eax, r8d + + pop rdi + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL3): + cmp r8d, (3*qsize) + + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + add rcx, rdi + cmp r8d, (6*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2) + sub r8d, (3*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done2): + sub r8d, (3*qsize) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done5): + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) + + cmp r8d, (2*qsize) + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3) + + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + sub r8d, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done3): + sub r8d, qsize + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C3_Done4): + SAVE_ROW_REG + mov eax, r8d + + pop rdi + + ret + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _WL4): + sub r9, 3 + push rdi + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack): + cmp r8d, (3*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3) + cmp r8d, (2*qsize) + jge @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2) + + @CatStr(UNPACK_, name, SSE_1) 0, 0, MaskType, ModeType + + + sub r8d, qsize + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack2): + @CatStr(UNPACK_, name, SSE_2) 0, 0, MaskType, ModeType + + + sub r8d, (2*qsize) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack3): + @CatStr(UNPACK_, name, SSE_3) 0, 0, MaskType, ModeType + + + sub r8d, (3*qsize) + mov rdi, r9 + +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX): + + + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + + @CatStr(UNPACK_, name, SSE_1) 3, 0, MaskType, ModeType + + sub r8d, qsize + cmp rdi, 1 + je @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop) + sub rdi, 1 + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_UnpackX) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_DoneLoop): + add rcx, [esp] + cmp r8d, qsize + jl @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done) + jmp @CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Unpack) +@CatStr(name, _, sign, _, MaskType, _, ModeType, _C4_Done): + + SAVE_ROW_REG + INC_STACK() + mov eax, r8d + + + pop rdi + ret +@CatStr(UNPACK_SkippingWrite_, name, _, sign, _, MaskType, _, ModeType endp) +endm + +UNPACK_RIGHTSHIFT macro reg, shift + psrld reg, shift + endm + +defUNPACK_SkippingWrite2 macro name, qsize + defUNPACK_SkippingWrite name, Regular, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, u, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, u, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, u, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2 S_32, 4 +defUNPACK_SkippingWrite2 S_16, 2 +defUNPACK_SkippingWrite2 S_8, 1 +defUNPACK_SkippingWrite2 V2_32, 8 +defUNPACK_SkippingWrite2 V2_16, 4 +defUNPACK_SkippingWrite2 V2_8, 2 +defUNPACK_SkippingWrite2 V3_32, 12 +defUNPACK_SkippingWrite2 V3_16, 6 +defUNPACK_SkippingWrite2 V3_8, 3 +defUNPACK_SkippingWrite2 V4_32, 16 +defUNPACK_SkippingWrite2 V4_16, 8 +defUNPACK_SkippingWrite2 V4_8, 4 +defUNPACK_SkippingWrite2 V4_5, 2 + +UNPACK_RIGHTSHIFT macro reg, shift + psrad reg, shift + endm + + +defUNPACK_SkippingWrite2a macro name, qsize + defUNPACK_SkippingWrite name, Mask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Regular, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, Mask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, Mask, 2, qsize, s, SAVE_ROW_REG_BASE + defUNPACK_SkippingWrite name, WriteMask, 0, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 1, qsize, s, SAVE_NO_REG + defUNPACK_SkippingWrite name, WriteMask, 2, qsize, s, SAVE_ROW_REG_BASE + endm + +defUNPACK_SkippingWrite2a S_16, 2 +defUNPACK_SkippingWrite2a S_8, 1 +defUNPACK_SkippingWrite2a V2_16, 4 +defUNPACK_SkippingWrite2a V2_8, 2 +defUNPACK_SkippingWrite2a V3_16, 6 +defUNPACK_SkippingWrite2a V3_8, 3 +defUNPACK_SkippingWrite2a V4_16, 8 +defUNPACK_SkippingWrite2a V4_8, 4 + +end diff --git a/pcsx2/x86/ix86-64/fast_routines-64.asm b/pcsx2/x86/ix86-64/fast_routines-64.asm new file mode 100644 index 0000000..e85c531 --- /dev/null +++ b/pcsx2/x86/ix86-64/fast_routines-64.asm @@ -0,0 +1,294 @@ +; Pcsx2 - Pc Ps2 Emulator +; Copyright (C) 2002-2007 Pcsx2 Team +; +; This program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2 of the License, or +; (at your option) any later version. + +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, write to the Free Software +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +;; Fast assembly routines for x86-64 masm compiler +;; zerofrog(@gmail.com) +.code + +;; mmx memcmp implementation, size has to be a multiple of 8 +;; returns 0 is equal, nonzero value if not equal +;; ~10 times faster than standard memcmp +;; (zerofrog) +;; u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +memcmp_mmx proc public + + cmp r8d, 32 + jl memcmp_Done4 + + ;; custom test first 8 to make sure things are ok + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + movq mm2, [rdx+16] + pmovmskb eax, mm0 + movq mm3, [rdx+24] + + ;; check if eq + cmp eax, 0ffh + je memcmp_NextComp + mov eax, 1 + jmp memcmp_End + +memcmp_NextComp: + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ;; check if eq + cmp eax, 0ffh + je memcmp_ContinueTest + mov eax, 1 + jmp memcmp_End + + cmp r8d, 64 + jl memcmp_Done8 + +memcmp_Cmp8: + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + movq mm4, [rdx+32] + movq mm5, [rdx+40] + movq mm6, [rdx+48] + movq mm7, [rdx+56] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pcmpeqd mm4, [rcx+32] + pand mm0, mm2 + pcmpeqd mm5, [rcx+40] + pand mm0, mm3 + pcmpeqd mm6, [rcx+48] + pand mm0, mm4 + pcmpeqd mm7, [rcx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + ;; check if eq + cmp eax, 0ffh + je memcmp_Continue + mov eax, 1 + jmp memcmp_End + +memcmp_Continue: + sub r8d, 64 + add rdx, 64 + add rcx, 64 +memcmp_ContinueTest: + cmp r8d, 64 + jge memcmp_Cmp8 + +memcmp_Done8: + test r8d, 020h + jz memcmp_Done4 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ;; check if eq + cmp eax, 0ffh + je memcmp_Done4 + mov eax, 1 + jmp memcmp_End + +memcmp_Done4: + cmp r8d, 24 + jne memcmp_Done2 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + ;; check if eq + cmp eax, 0ffh + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done2: + cmp r8d, 16 + jne memcmp_Done1 + + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + ;; check if eq + cmp eax, 0ffh + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done1: + cmp r8d, 8 + jne memcmp_Done + + mov eax, [rdx] + mov rdx, [rdx+4] + cmp eax, [rcx] + je memcmp_Next + mov eax, 1 + jmp memcmp_End + +memcmp_Next: + cmp rdx, [rcx+4] + je memcmp_Done + mov eax, 1 + jmp memcmp_End + +memcmp_Done: + xor eax, eax + +memcmp_End: + emms + ret +memcmp_mmx endp + +;; memxor_mmx +memxor_mmx proc public + + cmp r8d, 64 + jl memxor_Setup4 + + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + movq mm4, [rdx+32] + movq mm5, [rdx+40] + movq mm6, [rdx+48] + movq mm7, [rdx+56] + sub r8d, 64 + add rdx, 64 + cmp r8d, 64 + jl memxor_End8 + +memxor_Cmp8: + pxor mm0, [rdx] + pxor mm1, [rdx+8] + pxor mm2, [rdx+16] + pxor mm3, [rdx+24] + pxor mm4, [rdx+32] + pxor mm5, [rdx+40] + pxor mm6, [rdx+48] + pxor mm7, [rdx+56] + + sub r8d, 64 + add rdx, 64 + cmp r8d, 64 + jge memxor_Cmp8 + +memxor_End8: + pxor mm0, mm4 + pxor mm1, mm5 + pxor mm2, mm6 + pxor mm3, mm7 + + cmp r8d, 32 + jl memxor_End4 + pxor mm0, [rdx] + pxor mm1, [rdx+8] + pxor mm2, [rdx+16] + pxor mm3, [rdx+24] + sub r8d, 32 + add rdx, 32 + jmp memxor_End4 + +memxor_Setup4: + cmp r8d, 32 + jl memxor_Setup2 + + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + sub r8d, 32 + add rdx, 32 + +memxor_End4: + pxor mm0, mm2 + pxor mm1, mm3 + + cmp r8d, 16 + jl memxor_End2 + pxor mm0, [rdx] + pxor mm1, [rdx+8] + sub r8d, 16 + add rdx, 16 + jmp memxor_End2 + +memxor_Setup2: + cmp r8d, 16 + jl memxor_Setup1 + + movq mm0, [rdx] + movq mm1, [rdx+8] + sub r8d, 16 + add rdx, 16 + +memxor_End2: + pxor mm0, mm1 + + cmp r8d, 8 + jl memxor_End1 + pxor mm0, [rdx] +memxor_End1: + movq [rcx], mm0 + jmp memxor_End + +memxor_Setup1: + movq mm0, [rdx] + movq [rcx], mm0 +memxor_End: + emms + ret + +memxor_mmx endp + +end \ No newline at end of file diff --git a/pcsx2/x86/ix86-64/iCore-64.cpp b/pcsx2/x86/ix86-64/iCore-64.cpp new file mode 100644 index 0000000..0e00222 --- /dev/null +++ b/pcsx2/x86/ix86-64/iCore-64.cpp @@ -0,0 +1,703 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +extern "C" { + +#if defined(_WIN32) +#include +#endif + +#include "PS2Etypes.h" +#include "System.h" +#include "R5900.h" +#include "Vif.h" +#include "VU.h" +#include "ix86/ix86.h" +#include "iCore.h" +#include "R3000A.h" + +u16 x86FpuState, iCWstate; +u16 g_mmxAllocCounter = 0; + +// X86 caching +extern _x86regs x86regs[X86REGS]; +extern u16 g_x86AllocCounter; + +} // end extern "C" + +u32 g_recFnArgs[4]; + +#include +using namespace std; + +// use special x86 register allocation for ia32 +void _initX86regs() { + memset(x86regs, 0, sizeof(x86regs)); + g_x86AllocCounter = 0; +} + +uptr _x86GetAddr(int type, int reg) +{ + switch(type&~X86TYPE_VU1) { + case X86TYPE_GPR: return (uptr)&cpuRegs.GPR.r[reg]; + case X86TYPE_VI: { + //assert( reg < 16 || reg == REG_R ); + return (type&X86TYPE_VU1)?(uptr)&VU1.VI[reg]:(uptr)&VU0.VI[reg]; + } + case X86TYPE_MEMOFFSET: return 0; + case X86TYPE_VIMEMOFFSET: return 0; + case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(uptr)&VU1.VI[REG_Q]:(uptr)&VU0.VI[REG_Q]; + case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(uptr)&VU1.VI[REG_P]:(uptr)&VU0.VI[REG_P]; + case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(uptr)&VU1.q:(uptr)&VU0.q; + case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(uptr)&VU1.p:(uptr)&VU0.p; + case X86TYPE_PSX: return (uptr)&psxRegs.GPR.r[reg]; + case X86TYPE_PCWRITEBACK: + return (uptr)&g_recWriteback; + case X86TYPE_VUJUMP: + return (uptr)&g_recWriteback; + case X86TYPE_FNARG: + return (uptr)&g_recFnArgs[reg]; + default: assert(0); + } + + return 0; +} + +int _getFreeX86reg(int mode) +{ + int i, tempi; + u32 bestcount = 0x10000; + x86IntRegType* pregs = (mode&MODE_8BITREG)?g_x868bitregs:g_x86allregs; + int maxreg = (mode&MODE_8BITREG)?ARRAYSIZE(g_x868bitregs):ARRAYSIZE(g_x86allregs); + + if( !(mode&MODE_8BITREG) && (mode&0x80000000) ) { + // prioritize the temp registers + for (i=0; i= 0 && reg < 32 ); + +// if( X86_ISVI(type) ) +// assert( reg < 16 || reg == REG_R ); + + // don't alloc EAX and ESP,EBP if MODE_NOFRAME + int oldmode = mode; + int noframe = mode&MODE_NOFRAME; + int mode8bit = mode&MODE_8BITREG; + x86IntRegType* pregs = (mode&MODE_8BITREG)?g_x868bitregs:g_x86allregs; + int maxreg = (mode&MODE_8BITREG)?ARRAYSIZE(g_x868bitregs):ARRAYSIZE(g_x86allregs); + mode &= ~(MODE_NOFRAME|MODE_8BITREG); + int readfromreg = -1; + + + if( type != X86TYPE_TEMP ) { + + if( mode8bit ) { + // make sure reg isn't in the non8bit regs + + for(j = 0; j < ARRAYSIZE(g_x86non8bitregs); ++j) { + int i = g_x86non8bitregs[j]; + if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) + continue; + + if( mode & MODE_READ ) { + readfromreg = i; + x86regs[i].inuse = 0; + break; + } + else if( mode & MODE_WRITE ) { + x86regs[i].inuse = 0; + break; + } + } + } + + for (j=0; j= 0 ) { + // requested specific reg, so return that instead + if( i != x86reg ) { + if( x86regs[i].mode & MODE_READ ) readfromreg = i; + //if( x86regs[i].mode & MODE_WRITE ) mode |= MODE_WRITE; + mode |= x86regs[i].mode&MODE_WRITE; + x86regs[i].inuse = 0; + break; + } + } + + if( type != X86TYPE_TEMP && !(x86regs[i].mode & MODE_READ) && (mode&MODE_READ)) { + + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) XOR64RtoR(i, i); + else { + if( GPR_IS_CONST1(reg) ) + MOV64ItoR(i, g_cpuConstRegs[reg].UD[0]); + else + MOV64MtoR(i, _x86GetAddr(type, reg)); + } + } + else if( X86_ISVI(type) && reg < 16 ) MOVZX32M16toR(i, _x86GetAddr(type, reg)); + else // the rest are 32 bit + MOV32MtoR(i, _x86GetAddr(type, reg)); + + x86regs[i].mode |= MODE_READ; + } + + x86regs[i].needed = 1; + x86regs[i].mode|= mode; + return i; + } + } + + // currently only gpr regs are const + if( type == X86TYPE_GPR && (mode & MODE_WRITE) && reg < 32 ) { + //assert( !(g_cpuHasConstReg & (1<= 0 ) MOV64RtoR(x86reg, readfromreg); + else { + if( type == X86TYPE_GPR ) { + + if( reg == 0 ) { + if( mode & MODE_READ ) + XOR64RtoR(x86reg, x86reg); + return x86reg; + } + + int xmmreg; + if( (xmmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, 0)) >= 0 ) { + // destroy the xmm reg, but don't flush + SSE_MOVHPS_XMM_to_M64(_x86GetAddr(type, reg)+8, xmmreg); + + if( mode & MODE_READ ) + SSE2_MOVQ_XMM_to_R(x86reg, xmmreg); + + if( xmmregs[xmmreg].mode & MODE_WRITE ) + x86regs[x86reg].mode |= MODE_WRITE; + + // don't flush + xmmregs[xmmreg].inuse = 0; + } + else { + if( mode & MODE_READ ) { + if( GPR_IS_CONST1(reg) ) + MOV64ItoR(x86reg, g_cpuConstRegs[reg].UD[0]); + else + MOV64MtoR(x86reg, _x86GetAddr(type, reg)); + } + } + } + else if( mode & MODE_READ ) { + if( X86_ISVI(type) && reg < 16 ) { + if( reg == 0 ) XOR32RtoR(x86reg, x86reg); + else MOVZX32M16toR(x86reg, _x86GetAddr(type, reg)); + } + else MOV32MtoR(x86reg, _x86GetAddr(type, reg)); + } + } + + return x86reg; +} + +int _checkX86reg(int type, int reg, int mode) +{ + int i; + + for (i=0; i= 0 && x86reg < X86REGS ); + + if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { + + if( x86regs[x86reg].type == X86TYPE_GPR ) + MOV64RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + if( X86_ISVI(x86regs[x86reg].type) && x86regs[x86reg].reg < 16 ) + MOV16RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + else + MOV32RtoM(_x86GetAddr(x86regs[x86reg].type, x86regs[x86reg].reg), x86reg); + } + + x86regs[x86reg].mode &= ~MODE_WRITE; + x86regs[x86reg].inuse = 0; +} + +void _flushX86regs() +{ + int i; + + for (i=0; iregs[x86regs[i].reg]&EEINST_USED) ) { + return 1; + } + } + } + return 0; +} + +// EE +void _eeMoveGPRtoR(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV64ItoR( to, g_cpuConstRegs[fromgpr].UD[0] ); + else { + int mmreg; + + if( (mmreg = _checkX86reg(X86TYPE_GPR, fromgpr, MODE_READ)) >= 0) { + MOV64RtoR(to, mmreg); + } + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) { + SSE2_MOVQ_XMM_to_R(to, mmreg); + } + else { + MOV64MtoR(to, (uptr)&cpuRegs.GPR.r[ fromgpr ].UD[ 0 ] ); + } + } +} + +// 32 bit move +void _eeMoveGPRtoM(u32 to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] ); + else { + int mmreg; + + if( (mmreg = _checkX86reg(X86TYPE_GPR, fromgpr, MODE_READ)) >= 0 ) { + MOV32RtoM(to, mmreg); + } + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_M32(to, mmreg); + } + else { + MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ fromgpr ].UD[ 0 ] ); + MOV32RtoM(to, EAX ); + } + } +} + +void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr) +{ + if( GPR_IS_CONST1(fromgpr) ) + MOV64ItoRmOffset( to, g_cpuConstRegs[fromgpr].UD[0], 0 ); + else { + int mmreg; + + if( (mmreg = _checkX86reg(X86TYPE_GPR, fromgpr, MODE_READ)) >= 0 ) { + MOV64RtoRmOffset(to, mmreg, 0); + } + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) { + SSEX_MOVD_XMM_to_Rm(to, mmreg); + } + else { + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[ fromgpr ].UD[ 0 ] ); + MOV64RtoRmOffset(to, RAX, 0 ); + } + } +} + +void _callPushArg(u32 arg, uptr argmem, x86IntRegType X86ARG) +{ + if( IS_X86REG(arg) ) { + if( (arg&0xff) != X86ARG ) { + _freeX86reg(X86ARG); + MOV64RtoR(X86ARG, (arg&0xf)); + } + } + else if( IS_GPRREG(arg) ) { + _allocX86reg(X86ARG, X86TYPE_GPR, arg&0xff, MODE_READ); + } + else if( IS_CONSTREG(arg) ) { + _freeX86reg(X86ARG); + MOV32ItoR(X86ARG, argmem); + } + else if( IS_EECONSTREG(arg) ) { + _freeX86reg(X86ARG); + MOV32ItoR(X86ARG, g_cpuConstRegs[(arg>>16)&0x1f].UD[0]); + } + else if( IS_PSXCONSTREG(arg) ) { + _freeX86reg(X86ARG); + MOV32ItoR(X86ARG, g_psxConstRegs[(arg>>16)&0x1f]); + } + else if( IS_MEMORYREG(arg) ) { + _freeX86reg(X86ARG); + MOV64MtoR(X86ARG, argmem); + } + else if( IS_XMMREG(arg) ) { + _freeX86reg(X86ARG); + SSEX_MOVD_XMM_to_Rm(X86ARG, arg&0xf); + } + else { + assert((arg&0xfff0)==0); + _freeX86reg(X86ARG); + MOV64RtoR(X86ARG, (arg&0xf)); + } +} + +void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem) +{ + _callPushArg(arg1, arg1mem, X86ARG1); + CALLFunc((uptr)fn); +} + +void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem) +{ + _callPushArg(arg1, arg1mem, X86ARG1); + _callPushArg(arg2, arg2mem, X86ARG2); + CALLFunc((uptr)fn); +} + +void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem) +{ + _callPushArg(arg1, arg1mem, X86ARG1); + _callPushArg(arg2, arg2mem, X86ARG2); + _callPushArg(arg3, arg3mem, X86ARG3); + CALLFunc((uptr)fn); +} + +void _recPushReg(int mmreg) +{ + assert(0); +} + +void _signExtendSFtoM(u32 mem) +{ + assert(0); +} + +void _recMove128MtoM(u32 to, u32 from) +{ + MOV64MtoR(RAX, from); + MOV64RtoM(to, RAX); + MOV64MtoR(RAX, from+8); + MOV64RtoM(to+8, RAX); +} + +void _recMove128RmOffsettoM(u32 to, u32 offset) +{ + MOV64RmOffsettoR(RAX, RCX, offset); + MOV64RtoM(to, RAX); + MOV64RmOffsettoR(RAX, RCX, offset+8); + MOV64RtoM(to+8, RAX); +} + +void _recMove128MtoRmOffset(u32 offset, u32 from) +{ + MOV64MtoR(RAX, from); + MOV64RtoRmOffset(RCX, RAX, offset); + MOV64MtoR(RAX, from+8); + MOV64RtoRmOffset(RCX, RAX, offset+8); +} + +// 32 bit +void LogicalOp32RtoM(uptr to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND32RtoM(to, from); break; + case 1: OR32RtoM(to, from); break; + case 2: XOR32RtoM(to, from); break; + case 3: OR32RtoM(to, from); break; + } +} + +void LogicalOp32MtoR(x86IntRegType to, uptr from, int op) +{ + switch(op) { + case 0: AND32MtoR(to, from); break; + case 1: OR32MtoR(to, from); break; + case 2: XOR32MtoR(to, from); break; + case 3: OR32MtoR(to, from); break; + } +} + +void LogicalOp32ItoR(x86IntRegType to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoR(to, from); break; + case 1: OR32ItoR(to, from); break; + case 2: XOR32ItoR(to, from); break; + case 3: OR32ItoR(to, from); break; + } +} + +void LogicalOp32ItoM(uptr to, u32 from, int op) +{ + switch(op) { + case 0: AND32ItoM(to, from); break; + case 1: OR32ItoM(to, from); break; + case 2: XOR32ItoM(to, from); break; + case 3: OR32ItoM(to, from); break; + } +} + +// 64 bit +void LogicalOp64RtoR(x86IntRegType to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND64RtoR(to, from); break; + case 1: OR64RtoR(to, from); break; + case 2: XOR64RtoR(to, from); break; + case 3: OR64RtoR(to, from); break; + } +} + +void LogicalOp64RtoM(uptr to, x86IntRegType from, int op) +{ + switch(op) { + case 0: AND64RtoM(to, from); break; + case 1: OR64RtoM(to, from); break; + case 2: XOR64RtoM(to, from); break; + case 3: OR64RtoM(to, from); break; + } +} + +void LogicalOp64MtoR(x86IntRegType to, uptr from, int op) +{ + switch(op) { + case 0: AND64MtoR(to, from); break; + case 1: OR64MtoR(to, from); break; + case 2: XOR64MtoR(to, from); break; + case 3: OR64MtoR(to, from); break; + } +} + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900-64.c b/pcsx2/x86/ix86-64/iR5900-64.c new file mode 100644 index 0000000..579223f --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900-64.c @@ -0,0 +1,2754 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2005 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// 64 bit recompiler - difference between 32bit is that mmx is gone +// and x86 regs are now cached (also fancier block linking) (zerofrog) + +// liveness analysis/constant propagation Apr06 (zerofrog@gmail.com) +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include + +#include "Common.h" +#include "Memory.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "iR5900AritImm.h" +#include "iR5900Arit.h" +#include "iR5900MultDiv.h" +#include "iR5900Shift.h" +#include "iR5900Branch.h" +#include "iR5900Jump.h" +#include "iR5900LoadStore.h" +#include "iR5900Move.h" +#include "iMMI.h" +#include "iFPU.h" +#include "iCP0.h" +#include "iVUmicro.h" +#include "iVU0micro.h" +#include "iVU1micro.h" +#include "VU.h" +#include "VUmicro.h" + +#include "iVUzerorec.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +u32 maxrecmem = 0; +uptr *recLUT=NULL; + +#define X86 +#define RECSTACK_SIZE 0x00010000 + +#define EE_NUMBLOCKS (1<<15) + +static char *recMem = NULL; // the recompiled blocks will be here +static char* recStack = NULL; // stack mem +static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here +static BASEBLOCK *recROM = NULL; // and here +static BASEBLOCK *recROM1 = NULL; // also here +static BASEBLOCKEX *recBlocks = NULL; +static char *recPtr = NULL, *recStackPtr = NULL; +static EEINST* s_pInstCache = NULL; +static u32 s_nInstCacheSize = 0; + +u32 g_EEFreezeRegs = 0; // if set, should freeze the regs + +static BASEBLOCK* s_pCurBlock = NULL; +static BASEBLOCKEX* s_pCurBlockEx = NULL; +static BASEBLOCK* s_pDispatchBlock = NULL; +static u32 s_nEndBlock = 0; // what pc the current block ends +static u32 s_nHasDelay = 0; + +static u32 s_nNextBlock = 0; // next free block in recBlocks + +extern void (*recBSC[64])(); +extern void (*recBSC_co[64])(); +extern void rpropBSC(EEINST* prev, EEINST* pinst); + +// save states for branches +static u16 s_savex86FpuState, s_saveiCWstate; +static GPR_reg64 s_ConstGPRreg; +static u32 s_saveConstGPRreg = 0, s_saveHasConstReg = 0, s_saveFlushedConstReg = 0, s_saveRegHasLive1 = 0, s_saveRegHasSignExt = 0; +static EEINST* s_psaveInstInfo = NULL; + +u32 s_nBlockCycles = 0; // cycles of current block recompiling +static u32 s_savenBlockCycles = 0; + +void recCOP2RecompileInst(); +int recCOP2AnalyzeBlock(u32 startpc, u32 endpc); +void recCOP2EndBlock(void); + +#ifdef _DEBUG +u32 dumplog = 0; +#else +#define dumplog 0 +#endif + +u32 pc; // recompiler pc +int branch; // set for branch + +#ifdef PCSX2_DEVBUILD +LARGE_INTEGER lbase = {0}, lfinal = {0}; +static u32 s_startcount = 0; +#endif + +void _cop2AnalyzeOp(EEINST* pinst, int dostalls); // reccop2.c +static void iBranchTest(u32 newpc, u32 cpuBranch); +void recRecompile( u32 startpc ); +void recCOP22( void ); + +BASEBLOCKEX* PC_GETBLOCKEX(BASEBLOCK* p) +{ +// BASEBLOCKEX* pex = *(BASEBLOCKEX**)(p+1); +// if( pex >= recBlocks && pex < recBlocks+EE_NUMBLOCKS ) +// return pex; + + // otherwise, use the sorted list + return GetBaseBlockEx(p->startpc, 0); +} + +//////////////////////////////////////////////////// +void iDumpBlock( int startpc, char * ptr ) +{ + FILE *f; + char filename[ 256 ]; + u32 i, j; + EEINST* pcur; + extern char *disRNameGPR[]; + u8 used[34]; + u8 fpuused[33]; + int numused, count, fpunumused; + char command[256]; + + SysPrintf( "dump %x:%x, %x\n", startpc, pc, cpuRegs.cycle ); +#ifdef _WIN32 + CreateDirectory("dumps", NULL); + sprintf( filename, "dumps\\dump%.8X.txt", startpc); +#else + mkdir("dumps", 0755); + sprintf( filename, "dumps/dump%.8X.txt", startpc); +#endif + + fflush( stdout ); + + f = fopen( filename, "w" ); + + for ( i = startpc; i < s_nEndBlock; i += 4 ) { + fprintf( f, "%s\n", disR5900Fasm( PSMu32( i ), i ) ); + } + + // write the instruction info + + fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nxmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_XMM, EEINST_USED); + + memset(used, 0, sizeof(used)); + numused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memset(fpuused, 0, sizeof(fpuused)); + fpunumused = 0; + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%2d ", i); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%2d ", i); + } + fprintf(f, "\n"); + + fprintf(f, " "); + for(i = 0; i < ARRAYSIZE(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(i = 0; i < ARRAYSIZE(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(j = 0; j < ARRAYSIZE(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count tempdump", filename ); + system( command ); + sprintf(command, "mv tempdump %s", filename); + system(command); + f = fopen( filename, "a+" ); +#endif +} + +u8 _eeLoadWritesRs(u32 tempcode) +{ + switch(tempcode>>26) { + case 26: // ldl + case 27: // ldr + case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: + case 55: // LD + case 30: // lq + return ((tempcode>>21)&0x1f)==((tempcode>>16)&0x1f); // rs==rt + } + return 0; +} + +u8 _eeIsLoadStoreCoIssue(u32 firstcode, u32 secondcode) +{ + switch(firstcode>>26) { + case 34: // lwl + return (secondcode>>26)==38; + case 38: // lwr + return (secondcode>>26)==34; + case 42: // swl + return (secondcode>>26)==46; + case 46: // swr + return (secondcode>>26)==42; + case 26: // ldl + return (secondcode>>26)==27; + case 27: // ldr + return (secondcode>>26)==26; + case 44: // sdl + return (secondcode>>26)==45; + case 45: // sdr + return (secondcode>>26)==44; + + case 32: case 33: case 35: case 36: case 37: case 39: + case 55: // LD + + // stores + case 40: case 41: case 43: + case 63: // sd + return (secondcode>>26)==(firstcode>>26); + + case 30: // lq + case 31: // sq + case 49: // lwc1 + case 57: // swc1 + case 54: // lqc2 + case 62: // sqc2 + return (secondcode>>26)==(firstcode>>26)&&cpucaps.hasStreamingSIMDExtensions; + } + return 0; +} + +u8 _eeIsLoadStoreCoX(u32 tempcode) +{ + switch( tempcode>>26 ) { + case 30: case 31: case 49: case 57: case 55: case 63: + return 1; + } + return 0; +} + +void _eeFlushAllUnused() +{ + int i; + for(i = 0; i < 34; ++i) { + if( pc < s_nEndBlock ) { + if( (g_pCurInstInfo[1].regs[i]&EEINST_USED) ) + continue; + } + else if( (g_pCurInstInfo[0].regs[i]&EEINST_USED) ) + continue; + + if( i < 32 && GPR_IS_CONST1(i) ) _flushConstReg(i); + else { + _deleteGPRtoXMMreg(i, 1); + } + } + + //TODO when used info is done for FPU and VU0 + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse && xmmregs[i].type != XMMTYPE_GPRREG ) + _freeXMMreg(i); + } + for(i = 0; i < X86REGS; ++i) { + if( x86regs[i].inuse && x86regs[i].type != X86TYPE_GPR ) + _freeX86reg(i); + } +} + +u32* _eeGetConstReg(int reg) +{ + assert( GPR_IS_CONST1( reg ) ); + + if( g_cpuFlushedConstReg & (1<regs[xmmregs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, xmmregs[i].reg) ) { + _freeXMMreg(i); + xmmregs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushX86unused() +{ + int i; + for (i=0; iregs[x86regs[i].reg]&EEINST_USED) ) { + if( !_recIsRegWritten(g_pCurInstInfo+1, (s_nEndBlock-pc)/4, XMMTYPE_GPRREG, x86regs[i].reg) ) { + _freeX86reg(i); + x86regs[i].inuse = 1; + return 1; + } + } + } + + return 0; +} + +int _flushUnusedConstReg() +{ + int i; + for(i = 1; i < 32; ++i) { + if( (g_cpuHasConstReg & (1<>31) == g_cpuConstRegs[i].SL[1] ) + MOV64I32toM((uptr)&cpuRegs.GPR.r[i].UD[0], g_cpuConstRegs[i].UL[0]); + else { + MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]); + MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]); + } + + g_cpuFlushedConstReg |= 1<>31) == g_cpuConstRegs[reg].SL[1] ) + MOV64I32toM((uptr)&cpuRegs.GPR.r[reg].UD[0], g_cpuConstRegs[reg].UL[0]); + else { + MOV32ItoM((uptr)&cpuRegs.GPR.r[reg].UL[0], g_cpuConstRegs[reg].UL[0]); + MOV32ItoM((uptr)&cpuRegs.GPR.r[reg].UL[1], g_cpuConstRegs[reg].UL[1]); + } + + g_cpuFlushedConstReg |= (1<>31) == g_cpuConstRegs[i].SL[1] ) + MOV64I32toM((uptr)&cpuRegs.GPR.r[i].UD[0], g_cpuConstRegs[i].UL[0]); + else { + MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]); + MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]); + } + g_cpuFlushedConstReg |= 1<regs[reg]&EEINST_LASTUSE) ) { + if( usex86 ) return _allocX86reg(-1, X86TYPE_GPR, reg, mode); + return _allocGPRtoXMMreg(-1, reg, mode); + } + + return -1; +} + +#define PROCESS_EE_SETMODES(mmreg) 0//((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET(mmreg) 0//((mmxregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// ignores XMMINFO_READS, XMMINFO_READT, and XMMINFO_READD_LO from xmminfo +// core of reg caching +void eeRecompileCode0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode, int xmminfo) +{ + int mmreg1, mmreg2, mmreg3, mmtemp, moded; + + if ( ! _Rd_ && (xmminfo&XMMINFO_WRITED) ) return; + + if( xmminfo&XMMINFO_WRITED) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( xmminfo & XMMINFO_WRITED ) { + _deleteGPRtoXMMreg(_Rd_, 2); + } + if( xmminfo&XMMINFO_WRITED ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + moded = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) _addNeededGPRtoXMMreg(XMMGPR_LO); + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) _addNeededGPRtoXMMreg(XMMGPR_HI); + _addNeededGPRtoXMMreg(_Rs_); + _addNeededGPRtoXMMreg(_Rt_); + + if( GPR_IS_CONST1(_Rs_) || GPR_IS_CONST1(_Rt_) ) { + int creg = GPR_IS_CONST1(_Rs_) ? _Rs_ : _Rt_; + int vreg = creg == _Rs_ ? _Rt_ : _Rs_; + +// if(g_pCurInstInfo->regs[vreg]&EEINST_XMM) { +// mmreg1 = _allocGPRtoXMMreg(-1, vreg, MODE_READ); +// _addNeededGPRtoXMMreg(vreg); +// } + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, vreg, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM; + + if( GPR_IS_CONST1(_Rs_) ) info |= PROCESS_EE_SETMODET(mmreg1); + else info |= PROCESS_EE_SETMODES(mmreg1); + + if( xmminfo & XMMINFO_WRITED ) { + + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( !(xmminfo&XMMINFO_READD) && mmreg3 < 0 && ((g_pCurInstInfo->regs[vreg] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(vreg)) ) { + _freeXMMreg(mmreg1); + if( GPR_IS_CONST1(_Rs_) ) info &= ~PROCESS_EE_MODEWRITET; + else info &= ~PROCESS_EE_MODEWRITES; + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else if( mmreg3 < 0 ) mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + if( creg == _Rs_ ) constscode(info|PROCESS_EE_SET_T(mmreg1)); + else consttcode(info|PROCESS_EE_SET_S(mmreg1)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + else { + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + mmreg2 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 || mmreg2 >= 0 ) { + int info = PROCESS_EE_XMM; + + // do it all in xmm + if( mmreg1 < 0 ) mmreg1 = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + if( mmreg2 < 0 ) mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + + info |= PROCESS_EE_SETMODES(mmreg1)|PROCESS_EE_SETMODET(mmreg2); + + if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg3 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, moded); + + if( mmreg3 < 0 ) { + if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(mmreg2); + info &= ~PROCESS_EE_MODEWRITET; + xmmregs[mmreg2].inuse = 1; + xmmregs[mmreg2].reg = _Rd_; + xmmregs[mmreg2].mode = moded; + mmreg3 = mmreg2; + } + else if( !(xmminfo&XMMINFO_READD) && ((g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = moded; + mmreg3 = mmreg1; + } + else mmreg3 = _allocGPRtoXMMreg(-1, _Rd_, moded); + } + + info |= PROCESS_EE_SET_D(mmreg3); + } + + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + mmtemp = eeProcessHILO(XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_LO(mmtemp); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + mmtemp = eeProcessHILO(XMMGPR_HI, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0), 0); + if( mmtemp >= 0 ) info |= PROCESS_EE_SET_HI(mmtemp); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + if( xmminfo & XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + if( xmminfo&XMMINFO_WRITED ) + _deleteGPRtoXMMreg(_Rd_, (xmminfo&XMMINFO_READD)?0:2); + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + if( xmminfo&XMMINFO_WRITED ) GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCode1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rt_ ) return; + + CHECK_SAVE_REG(_Rt_); + _eeProcessHasLive(_Rt_, 0); + EEINST_RESETSIGNEXT(_Rt_); + + if( GPR_IS_CONST1(_Rs_) ) { + _deleteGPRtoXMMreg(_Rt_, 2); + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rs_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODES(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rt_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITES; + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rt_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_S(mmreg1)|PROCESS_EE_SET_T(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rt_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCode2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + int mmreg1, mmreg2; + if ( ! _Rd_ ) return; + + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + + if( GPR_IS_CONST1(_Rt_) ) { + _deleteGPRtoXMMreg(_Rd_, 2); + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + // test if should write xmm, mirror to mmx code + if( g_pCurInstInfo->info & EEINST_XMM ) { + + // no const regs + mmreg1 = _allocCheckGPRtoXMM(g_pCurInstInfo, _Rt_, MODE_READ); + + if( mmreg1 >= 0 ) { + int info = PROCESS_EE_XMM|PROCESS_EE_SETMODET(mmreg1); + + // check for last used, if so don't alloc a new XMM reg + _addNeededGPRtoXMMreg(_Rd_); + mmreg2 = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE); + + if( mmreg2 < 0 ) { + if( (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVE64(_Rt_) ) { + _freeXMMreg(mmreg1); + info &= ~PROCESS_EE_MODEWRITET; + xmmregs[mmreg1].inuse = 1; + xmmregs[mmreg1].reg = _Rd_; + xmmregs[mmreg1].mode = MODE_WRITE|MODE_READ; + mmreg2 = mmreg1; + } + else mmreg2 = _allocGPRtoXMMreg(-1, _Rd_, MODE_WRITE); + } + + noconstcode(info|PROCESS_EE_SET_T(mmreg1)|PROCESS_EE_SET_D(mmreg2)); + _clearNeededXMMregs(); + GPR_DEL_CONST(_Rd_); + return; + } + + _clearNeededXMMregs(); + } + + // regular x86 + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 2); + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt op rs +void eeRecompileCode3(R5900FNPTR constcode, R5900FNPTR_INFO multicode) +{ + assert(0); + // for now, don't support xmm + _deleteEEreg(_Rs_, 1); + _deleteEEreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + return; + } + + multicode(0); +} + +// Simple Code Templates // + +// rd = rs op rt +void eeRecompileCodeConst0(R5900FNPTR constcode, R5900FNPTR_INFO constscode, R5900FNPTR_INFO consttcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + constscode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + consttcode(0); + GPR_DEL_CONST(_Rd_); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rt = rs op imm16 +void eeRecompileCodeConst1(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rt_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rt_); + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 0); + + if( GPR_IS_CONST1(_Rs_) ) { + GPR_SET_CONST(_Rt_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rt_); +} + +// rd = rt op sa +void eeRecompileCodeConst2(R5900FNPTR constcode, R5900FNPTR_INFO noconstcode) +{ + if ( ! _Rd_ ) return; + + // for now, don't support xmm + CHECK_SAVE_REG(_Rd_); + + _deleteGPRtoXMMreg(_Rt_, 1); + _deleteGPRtoXMMreg(_Rd_, 0); + + if( GPR_IS_CONST1(_Rt_) ) { + GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + noconstcode(0); + GPR_DEL_CONST(_Rd_); +} + +// rd = rt MULT rs (SPECIAL) +void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode, int MULT) +{ + assert(0); + // for now, don't support xmm + if( MULT ) { + CHECK_SAVE_REG(_Rd_); + _deleteGPRtoXMMreg(_Rd_, 0); + } + + _deleteGPRtoXMMreg(_Rs_, 1); + _deleteGPRtoXMMreg(_Rt_, 1); + + if( GPR_IS_CONST2(_Rs_, _Rt_) ) { + if( MULT && _Rd_ ) GPR_SET_CONST(_Rd_); + constcode(); + return; + } + + if( GPR_IS_CONST1(_Rs_) ) { + //multicode(PROCESS_EE_CONSTS); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + if( GPR_IS_CONST1(_Rt_) ) { + //multicode(PROCESS_EE_CONSTT); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); + return; + } + + multicode(0); + if( MULT && _Rd_ ) GPR_DEL_CONST(_Rd_); +} + +// EE XMM allocation code +int eeRecompileCodeXMM(int xmminfo) +{ + int info = PROCESS_EE_XMM; + + // save state + if( xmminfo & XMMINFO_WRITED ) { + CHECK_SAVE_REG(_Rd_); + _eeProcessHasLive(_Rd_, 0); + EEINST_RESETSIGNEXT(_Rd_); + } + + // flush consts + if( xmminfo & XMMINFO_READT ) { + if( GPR_IS_CONST1( _Rt_ ) && !(g_cpuFlushedConstReg&(1<<_Rt_)) ) { + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], g_cpuConstRegs[_Rt_].UL[0]); + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], g_cpuConstRegs[_Rt_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rt_); + } + } + if( xmminfo & XMMINFO_READS) { + if( GPR_IS_CONST1( _Rs_ ) && !(g_cpuFlushedConstReg&(1<<_Rs_)) ) { + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ], g_cpuConstRegs[_Rs_].UL[0]); + MOV32ItoM((uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ], g_cpuConstRegs[_Rs_].UL[1]); + g_cpuFlushedConstReg |= (1<<_Rs_); + } + } + + if( xmminfo & XMMINFO_WRITED ) { + GPR_DEL_CONST(_Rd_); + } + + // add needed + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + _addNeededGPRtoXMMreg(XMMGPR_LO); + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + _addNeededGPRtoXMMreg(XMMGPR_HI); + } + if( xmminfo & XMMINFO_READS) _addNeededGPRtoXMMreg(_Rs_); + if( xmminfo & XMMINFO_READT) _addNeededGPRtoXMMreg(_Rt_); + if( xmminfo & XMMINFO_WRITED ) _addNeededGPRtoXMMreg(_Rd_); + + // allocate + if( xmminfo & XMMINFO_READS) { + int reg = _allocGPRtoXMMreg(-1, _Rs_, MODE_READ); + info |= PROCESS_EE_SET_S(reg)|PROCESS_EE_SETMODES(reg); + } + if( xmminfo & XMMINFO_READT) { + int reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_READ); + info |= PROCESS_EE_SET_T(reg)|PROCESS_EE_SETMODET(reg); + } + + if( xmminfo & XMMINFO_WRITED ) { + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?((xmminfo&XMMINFO_READD_LO)?(MODE_READ|MODE_READHALF):MODE_READ):0); + + int regd = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, readd); + + if( regd < 0 ) { + if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READT) && (_Rt_ == 0 || (g_pCurInstInfo->regs[_Rt_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rt_)) ) { + _freeXMMreg(EEREC_T); + _deleteX86reg(X86TYPE_GPR, _Rd_, 2); + xmmregs[EEREC_T].inuse = 1; + xmmregs[EEREC_T].reg = _Rd_; + xmmregs[EEREC_T].mode = readd; + regd = EEREC_T; + } + else if( !(xmminfo&XMMINFO_READD) && (xmminfo & XMMINFO_READS) && (_Rs_ == 0 || (g_pCurInstInfo->regs[_Rs_] & EEINST_LASTUSE) || !EEINST_ISLIVEXMM(_Rs_)) ) { + _freeXMMreg(EEREC_S); + _deleteX86reg(X86TYPE_GPR, _Rd_, 2); + xmmregs[EEREC_S].inuse = 1; + xmmregs[EEREC_S].reg = _Rd_; + xmmregs[EEREC_S].mode = readd; + regd = EEREC_S; + } + else regd = _allocGPRtoXMMreg(-1, _Rd_, readd); + } + + info |= PROCESS_EE_SET_D(regd); + } + if( xmminfo & (XMMINFO_READLO|XMMINFO_WRITELO) ) { + info |= PROCESS_EE_SET_LO(_allocGPRtoXMMreg(-1, XMMGPR_LO, ((xmminfo&XMMINFO_READLO)?MODE_READ:0)|((xmminfo&XMMINFO_WRITELO)?MODE_WRITE:0))); + info |= PROCESS_EE_LO; + } + if( xmminfo & (XMMINFO_READHI|XMMINFO_WRITEHI) ) { + info |= PROCESS_EE_SET_HI(_allocGPRtoXMMreg(-1, XMMGPR_HI, ((xmminfo&XMMINFO_READHI)?MODE_READ:0)|((xmminfo&XMMINFO_WRITEHI)?MODE_WRITE:0))); + info |= PROCESS_EE_HI; + } + return info; +} + +// EE COP1(FPU) XMM allocation code +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +#define PROCESS_EE_SETMODES_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITES:0) +#define PROCESS_EE_SETMODET_XMM(mmreg) ((xmmregs[mmreg].mode&MODE_WRITE)?PROCESS_EE_MODEWRITET:0) + +// rd = rs op rt +void eeFPURecompileCode(R5900FNPTR_INFO xmmcode, R5900FNPTR_INFO fpucode, int xmminfo) +{ + int mmregs=-1, mmregt=-1, mmregd=-1, mmregacc=-1; + if( EE_FPU_REGCACHING && cpucaps.hasStreamingSIMDExtensions ) { + int info = PROCESS_EE_XMM; + + if( xmminfo & XMMINFO_READS ) _addNeededFPtoXMMreg(_Fs_); + if( xmminfo & XMMINFO_READT ) _addNeededFPtoXMMreg(_Ft_); + if( xmminfo & (XMMINFO_WRITED|XMMINFO_READD) ) _addNeededFPtoXMMreg(_Fd_); + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) _addNeededFPACCtoXMMreg(); + + if( xmminfo & XMMINFO_READT ) { + if( g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE ) mmregt = _checkXMMreg(XMMTYPE_FPREG, _Ft_, MODE_READ); + else mmregt = _allocFPtoXMMreg(-1, _Ft_, MODE_READ); + } + + if( xmminfo & XMMINFO_READS ) { + if( (!(xmminfo&XMMINFO_READT)||mmregt>=0) && (g_pCurInstInfo->fpuregs[_Fs_] & EEINST_LASTUSE) ) + mmregs = _checkXMMreg(XMMTYPE_FPREG, _Fs_, MODE_READ); + else mmregs = _allocFPtoXMMreg(-1, _Fs_, MODE_READ); + } + + if( mmregs >= 0 ) info |= PROCESS_EE_SETMODES_XMM(mmregs); + if( mmregt >= 0 ) info |= PROCESS_EE_SETMODET_XMM(mmregt); + + if( xmminfo & XMMINFO_READD ) { + assert( xmminfo & XMMINFO_WRITED ); + mmregd = _allocFPtoXMMreg(-1, _Fd_, MODE_READ); + } + + if( xmminfo & XMMINFO_READACC ) { + if( !(xmminfo&XMMINFO_WRITEACC) && (g_pCurInstInfo->fpuregs[_Ft_] & EEINST_LASTUSE) ) + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, MODE_READ); + else mmregacc = _allocFPACCtoXMMreg(-1, MODE_READ); + } + + if( xmminfo & XMMINFO_WRITEACC ) { + + // check for last used, if so don't alloc a new XMM reg + int readacc = MODE_WRITE|((xmminfo&XMMINFO_READACC)?MODE_READ:0); + + mmregacc = _checkXMMreg(XMMTYPE_FPACC, 0, readacc); + + if( mmregacc < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = 0; + xmmregs[mmregt].mode = readacc; + xmmregs[mmregt].type = XMMTYPE_FPACC; + mmregacc = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = 0; + xmmregs[mmregs].mode = readacc; + xmmregs[mmregs].type = XMMTYPE_FPACC; + mmregacc = mmregs; + } + else mmregacc = _allocFPACCtoXMMreg(-1, readacc); + } + + xmmregs[mmregacc].mode |= MODE_WRITE; + } + else if( xmminfo & XMMINFO_WRITED ) { + // check for last used, if so don't alloc a new XMM reg + int readd = MODE_WRITE|((xmminfo&XMMINFO_READD)?MODE_READ:0); + if( xmminfo&XMMINFO_READD ) mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + else mmregd = _checkXMMreg(XMMTYPE_FPREG, _Fd_, readd); + + if( mmregd < 0 ) { + if( (xmminfo&XMMINFO_READT) && mmregt >= 0 && (FPUINST_LASTUSE(_Ft_) || !FPUINST_ISLIVE(_Ft_)) ) { + if( FPUINST_ISLIVE(_Ft_) ) { + _freeXMMreg(mmregt); + info &= ~PROCESS_EE_MODEWRITET; + } + xmmregs[mmregt].inuse = 1; + xmmregs[mmregt].reg = _Fd_; + xmmregs[mmregt].mode = readd; + mmregd = mmregt; + } + else if( (xmminfo&XMMINFO_READS) && mmregs >= 0 && (FPUINST_LASTUSE(_Fs_) || !FPUINST_ISLIVE(_Fs_)) ) { + if( FPUINST_ISLIVE(_Fs_) ) { + _freeXMMreg(mmregs); + info &= ~PROCESS_EE_MODEWRITES; + } + xmmregs[mmregs].inuse = 1; + xmmregs[mmregs].reg = _Fd_; + xmmregs[mmregs].mode = readd; + mmregd = mmregs; + } + else if( (xmminfo&XMMINFO_READACC) && mmregacc >= 0 && (FPUINST_LASTUSE(XMMFPU_ACC) || !FPUINST_ISLIVE(XMMFPU_ACC)) ) { + if( FPUINST_ISLIVE(XMMFPU_ACC) ) + _freeXMMreg(mmregacc); + xmmregs[mmregacc].inuse = 1; + xmmregs[mmregacc].reg = _Fd_; + xmmregs[mmregacc].mode = readd; + xmmregs[mmregacc].type = XMMTYPE_FPREG; + mmregd = mmregacc; + } + else mmregd = _allocFPtoXMMreg(-1, _Fd_, readd); + } + } + + assert( mmregs >= 0 || mmregt >= 0 || mmregd >= 0 || mmregacc >= 0 ); + + if( xmminfo & XMMINFO_WRITED ) { + assert( mmregd >= 0 ); + info |= PROCESS_EE_SET_D(mmregd); + } + if( xmminfo & (XMMINFO_WRITEACC|XMMINFO_READACC) ) { + if( mmregacc >= 0 ) info |= PROCESS_EE_SET_ACC(mmregacc)|PROCESS_EE_ACC; + else assert( !(xmminfo&XMMINFO_WRITEACC)); + } + + if( xmminfo & XMMINFO_READS ) { + if( mmregs >= 0 ) info |= PROCESS_EE_SET_S(mmregs)|PROCESS_EE_S; + } + if( xmminfo & XMMINFO_READT ) { + if( mmregt >= 0 ) info |= PROCESS_EE_SET_T(mmregt)|PROCESS_EE_T; + } + + // at least one must be in xmm + if( (xmminfo & (XMMINFO_READS|XMMINFO_READT)) == (XMMINFO_READS|XMMINFO_READT) ) { + assert( mmregs >= 0 || mmregt >= 0 ); + } + + xmmcode(info); + _clearNeededXMMregs(); + return; + } + + if( xmminfo & XMMINFO_READS ) _deleteFPtoXMMreg(_Fs_, 0); + if( xmminfo & XMMINFO_READT ) _deleteFPtoXMMreg(_Ft_, 0); + if( xmminfo & (XMMINFO_READD|XMMINFO_WRITED) ) _deleteFPtoXMMreg(_Fd_, 0); + if( xmminfo & (XMMINFO_READACC|XMMINFO_WRITEACC) ) _deleteFPtoXMMreg(XMMFPU_ACC, 0); + fpucode(0); +} + +#undef _Ft_ +#undef _Fs_ +#undef _Fd_ + +//////////////////////////////////////////////////// +extern u8 g_MACFlagTransform[256]; // for vus + +u32 g_sseMXCSR = 0x9f80; // disable all exception, round to 0, flush to 0 +u32 g_sseVUMXCSR = 0xff80; + +#if defined(_MSC_VER) +#include +#endif + +void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR) +{ + // SSE STATE // + // WARNING: do not touch unless you know what you are doing + + if( cpucaps.hasStreamingSIMDExtensions ) { + g_sseMXCSR = sseMXCSR; + g_sseVUMXCSR = sseVUMXCSR; + // do NOT set Denormals-Are-Zero flag (charlie and chocfac messes up) + //g_sseMXCSR = 0x9f80; // changing the rounding mode to 0x2000 (near) kills grandia III! + // changing the rounding mode to 0x0000 or 0x4000 totally kills gitaroo + // so... grandia III wins (you can change individual games with the 'roundmode' patch command) + +#ifdef _MSC_VER + _mm_setcsr(g_sseMXCSR); // set the new sse control +#else + __asm__("ldmxcsr %0" : : "m"(g_sseMXCSR) ); +#endif + //g_sseVUMXCSR = g_sseMXCSR|0x6000; + } +} + +extern BOOL install_my_handler(); + +#define REC_CACHEMEM 0x01000000 + +int recInit( void ) +{ + int i; + u32 startaddr; + const u8 macarr[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + + startaddr = 0x0d000000; + while(!(startaddr & 0xf0000000)) { + recMem = (char*)SysMmap(startaddr, REC_CACHEMEM); + if( (uptr)recMem & 0xf0000000 ) { + SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL; + startaddr += 0x00100000; + continue; + } + else break; + } + + if( (uptr)recMem & 0xf0000000 ) { + SysPrintf("R5900 bad rec memory allocation\n"); + return 1; + } + + recLUT = (uptr*) _aligned_malloc( 0x010000 * sizeof(uptr), 16 ); + memset( recLUT, 0, 0x010000 * sizeof(uptr) ); + + // 32 alignment necessary + recRAM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x02000000 , 4*sizeof(BASEBLOCK)); + recROM = (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00400000 , 4*sizeof(BASEBLOCK)); + recROM1= (BASEBLOCK*) _aligned_malloc( sizeof(BASEBLOCK)/4*0x00040000 , 4*sizeof(BASEBLOCK)); + recBlocks = (BASEBLOCKEX*) _aligned_malloc( sizeof(BASEBLOCKEX)*EE_NUMBLOCKS, 16); + recStack = (char*)malloc( RECSTACK_SIZE ); + + s_nInstCacheSize = 128; + s_pInstCache = (EEINST*)malloc( sizeof(EEINST) * s_nInstCacheSize ); + + if ( recBlocks == NULL || recRAM == NULL || recROM == NULL || recROM1 == NULL || recMem == NULL || recLUT == NULL ) { + SysMessage( _( "Error allocating memory" ) ); + return -1; + } + + for ( i = 0x0000; i < 0x0200; i++ ) + { + recLUT[ i + 0x0000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x2000 ] = (uptr)&recRAM[ i << 14 ]; + recLUT[ i + 0x3000 ] = (uptr)&recRAM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0040; i++ ) + { + recLUT[ i + 0x1fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0x9fc0 ] = (uptr)&recROM[ i << 14 ]; + recLUT[ i + 0xbfc0 ] = (uptr)&recROM[ i << 14 ]; + } + + for ( i = 0x0000; i < 0x0004; i++ ) + { + recLUT[ i + 0x1e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0x9e00 ] = (uptr)&recROM1[ i << 14 ]; + recLUT[ i + 0xbe00 ] = (uptr)&recROM1[ i << 14 ]; + } + + memcpy( recLUT + 0x8000, recLUT, 0x2000 * sizeof(uptr) ); + memcpy( recLUT + 0xa000, recLUT, 0x2000 * sizeof(uptr) ); + + memset(recMem, 0xcd, REC_CACHEMEM); + memset(recStack, 0, RECSTACK_SIZE); + + // SSE3 detection, manually create the code + x86SetPtr(recMem); + SSE3_MOVSLDUP_XMM_to_XMM(XMM0, XMM0); + RET(); + cpudetectSSE3(recMem); + + SysPrintf( "x86Init: \n" ); + SysPrintf( "\tCPU vender name = %s\n", cpuinfo.x86ID ); + SysPrintf( "\tFamilyID = %x\n", cpuinfo.x86StepID ); + SysPrintf( "\tx86Family = %s\n", cpuinfo.x86Fam ); + SysPrintf( "\tCPU speed = %d.%03d Ghz\n", cpuinfo.cpuspeed / 1000, cpuinfo.cpuspeed%1000); + SysPrintf( "\tx86PType = %s\n", cpuinfo.x86Type ); + SysPrintf( "\tx86Flags = %8.8x\n", cpuinfo.x86Flags ); + SysPrintf( "\tx86EFlags = %8.8x\n", cpuinfo.x86EFlags ); + SysPrintf( "Features: \n" ); + SysPrintf( "\t%sDetected MMX\n", cpucaps.hasMultimediaExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE\n", cpucaps.hasStreamingSIMDExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE2\n", cpucaps.hasStreamingSIMD2Extensions ? "" : "Not " ); + SysPrintf( "\t%sDetected SSE3\n", cpucaps.hasStreamingSIMD3Extensions ? "" : "Not " ); + + if ( cpuinfo.x86ID[0] == 'A' ) //AMD cpu + { + SysPrintf( " Extented AMD Features: \n" ); + SysPrintf( "\t%sDetected MMX2\n", cpucaps.hasMultimediaExtensionsExt ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW\n", cpucaps.has3DNOWInstructionExtensions ? "" : "Not " ); + SysPrintf( "\t%sDetected 3DNOW2\n", cpucaps.has3DNOWInstructionExtensionsExt ? "" : "Not " ); + } + if ( !( cpucaps.hasMultimediaExtensions ) ) + { + SysMessage( _( "Processor doesn't supports MMX, can't run recompiler without that" ) ); + return -1; + } + + SuperVUInit(-1); + + for(i = 0; i < 256; ++i) { + g_MACFlagTransform[i] = macarr[i>>4]|(macarr[i&15]<<4); + } + + SetCPUState(g_sseMXCSR, g_sseVUMXCSR); + + return 0; +} + +//////////////////////////////////////////////////// +void recReset( void ) { +#ifdef PCSX2_DEVBUILD + SysPrintf("EE Recompiler data reset\n"); +#endif + + s_nNextBlock = 0; + maxrecmem = 0; + memset( recRAM, 0, sizeof(BASEBLOCK)/4*0x02000000 ); + memset( recROM, 0, sizeof(BASEBLOCK)/4*0x00400000 ); + memset( recROM1, 0, sizeof(BASEBLOCK)/4*0x00040000 ); + memset( recBlocks, 0, sizeof(BASEBLOCKEX)*EE_NUMBLOCKS ); + if( s_pInstCache ) memset( s_pInstCache, 0, sizeof(EEINST)*s_nInstCacheSize ); + ResetBaseBlockEx(0); + +#ifdef _DEBUG + // don't clear since save states won't work + //memset(recMem, 0xcd, REC_CACHEMEM); +#endif + + recPtr = recMem; + recStackPtr = recStack; + iCWstate = 0; + + branch = 0; +} + +void recShutdown( void ) +{ + if ( recMem == NULL ) { + return; + } + + _aligned_free( recLUT ); + SysMunmap((uptr)recMem, REC_CACHEMEM); recMem = NULL; + _aligned_free( recRAM ); recRAM = NULL; + _aligned_free( recROM ); recROM = NULL; + _aligned_free( recROM1 ); recROM1 = NULL; + _aligned_free( recBlocks ); recBlocks = NULL; + free( s_pInstCache ); s_pInstCache = NULL; s_nInstCacheSize = 0; + + SuperVUDestroy(-1); + + x86Shutdown( ); +} + +void recEnableVU0micro(int enable) { +} + +void recEnableVU1micro(int enable) { +} + +void R5900Execute(); + +void recStep( void ) { +} + +void recExecute( void ) { + //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);//ABOVE_NORMAL_PRIORITY_CLASS); + //SetThreadAffinityMask(GetCurrentThread(), 0); + if( Config.Options & PCSX2_EEREC ) Config.Options |= PCSX2_COP2REC; + + for (;;) + R5900Execute(); +} + +void recExecuteBlock( void ) { + R5900Execute(); +} + +//////////////////////////////////////////////////// +extern u32 g_nextBranchCycle; + +u32 g_lastpc = 0; +u32 g_EEDispatchTemp; +u32 s_pCurBlock_ltime; + +extern void Dispatcher(); +extern void DispatcherClear(); +extern void DispatcherReg(); +extern void _StartPerfCounter(); +extern void _StopPerfCounter(); + +//////////////////////////////////////////////////// +void recClear64(BASEBLOCK* p) +{ + int left = 4 - ((uptr)p % 16)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); +} + +void recClear128(BASEBLOCK* p) +{ + int left = 4 - ((uptr)p % 32)/sizeof(BASEBLOCK); + recClearMem(p); + + if( left > 1 && *(u32*)(p+1) ) recClearMem(p+1); + if( left > 2 && *(u32*)(p+2) ) recClearMem(p+2); + if( left > 3 && *(u32*)(p+3) ) recClearMem(p+3); +} + +void recClear( u32 Addr, u32 Size ) +{ + u32 i; + for(i = 0; i < Size; ++i, Addr+=4) { + REC_CLEARM(Addr); + } +} + +#define EE_MIN_BLOCK_BYTES 16 + +void recClearMem(BASEBLOCK* p) +{ + BASEBLOCKEX* pexblock; + BASEBLOCK* pstart; + int lastdelay; + + assert( p != NULL ); + + if( p->uType & BLOCKTYPE_DELAYSLOT ) { + recClearMem(p-1); + if( p->pFnptr == 0 ) + return; + } + + assert( p->pFnptr != 0 ); + assert( p->startpc ); + + x86Ptr = (s8*)p->pFnptr; + + // there is a small problem: mem can be ored with 0xa<<28 or 0x8<<28, and don't know which + MOV32ItoR(EDX, p->startpc); + assert( (uptr)x86Ptr <= 0xffffffff ); + MOV32ItoR(R15, (uptr)x86Ptr); // will be replaced by JMP32 + JMP32((uptr)DispatcherClear - ( (uptr)x86Ptr + 5 )); + assert( x86Ptr == (s8*)p->pFnptr + EE_MIN_BLOCK_BYTES ); + + pstart = PC_GETBLOCK(p->startpc); + pexblock = PC_GETBLOCKEX(pstart); + assert( pexblock->startpc == pstart->startpc ); + +// if( pexblock->pOldFnptr ) { +// // have to mod oldfnptr too +// x86Ptr = pexblock->pOldFnptr; +// +// MOV32ItoR(EDX, p->startpc); +// JMP32((u32)DispatcherClear - ( (u32)x86Ptr + 5 )); +// } +// else +// pexblock->pOldFnptr = (u8*)p->pFnptr; + + // don't delete if last is delay + lastdelay = pexblock->size; + if( pstart[pexblock->size-1].uType & BLOCKTYPE_DELAYSLOT ) { + assert( pstart[pexblock->size-1].pFnptr != pstart->pFnptr ); + if( pstart[pexblock->size-1].pFnptr != 0 ) { + pstart[pexblock->size-1].uType = 0; + --lastdelay; + } + } + + memset(pstart, 0, lastdelay*sizeof(BASEBLOCK)); + + RemoveBaseBlockEx(pexblock, 0); + pexblock->size = 0; + pexblock->startpc = 0; +} + +// check for end of bios +void CheckForBIOSEnd() +{ + MOV32MtoR(EAX, (uptr)&cpuRegs.pc); + + CMP32ItoR(EAX, 0x00200008); + j8Ptr[0] = JE8(0); + + CMP32ItoR(EAX, 0x00100008); + j8Ptr[1] = JE8(0); + + // return + j8Ptr[2] = JMP8(0); + + x86SetJ8( j8Ptr[0] ); + x86SetJ8( j8Ptr[1] ); + + // bios end + if( REC_INC_STACK ) + ADD64ItoR(RSP, REC_INC_STACK); + RET2(); + + x86SetJ8( j8Ptr[2] ); +} + +static int *s_pCode; + +void SetBranchReg( u32 reg ) +{ + branch = 1; + + if( reg != 0xffffffff ) { +// if( GPR_IS_CONST1(reg) ) +// MOV32ItoM( (uptr)&cpuRegs.pc, g_cpuConstRegs[reg].UL[0] ); +// else { +// int mmreg; +// +// if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, reg, MODE_READ)) >= 0 ) { +// SSE_MOVSS_XMM_to_M32((uptr)&cpuRegs.pc, mmreg); +// } +// else { +// MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[ reg ].UL[ 0 ] ); +// MOV32RtoM((uptr)&cpuRegs.pc, EAX); +// } +// } + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, reg); + + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((uptr)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (uptr)&g_recWriteback); + MOV32RtoM((uptr)&cpuRegs.pc, EAX); + } + } + +// CMP32ItoM((uptr)&cpuRegs.pc, 0); +// j8Ptr[5] = JNE8(0); +// CALLFunc((uptr)tempfn); +// x86SetJ8( j8Ptr[5] ); + + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr + 5 )); +} + +void SetBranchImm( u32 imm ) +{ + u32* ptr; + branch = 1; + + assert( imm ); + + // end the current block + MOV32ItoM( (uptr)&cpuRegs.pc, imm ); + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(imm, imm <= pc); + if( bExecBIOS ) CheckForBIOSEnd(); + + MOV32ItoR(EDX, 0); + ptr = (u32*)(x86Ptr-4); + *ptr = (u32)JMP32((uptr)Dispatcher - ( (uptr)x86Ptr + 5 )); +} + +void SaveBranchState() +{ + s_savex86FpuState = x86FpuState; + s_saveiCWstate = iCWstate; + s_savenBlockCycles = s_nBlockCycles; + s_saveConstGPRreg = 0xffffffff; // indicate searching + s_saveHasConstReg = g_cpuHasConstReg; + s_saveFlushedConstReg = g_cpuFlushedConstReg; + s_psaveInstInfo = g_pCurInstInfo; + s_saveRegHasLive1 = g_cpuRegHasLive1; + s_saveRegHasSignExt = g_cpuRegHasSignExt; + + // save all mmx regs + memcpy(s_saveXMMregs, xmmregs, sizeof(xmmregs)); + memcpy(s_saveX86regs, x86regs, sizeof(x86regs)); +} + +void LoadBranchState() +{ + x86FpuState = s_savex86FpuState; + iCWstate = s_saveiCWstate; + s_nBlockCycles = s_savenBlockCycles; + + if( s_saveConstGPRreg != 0xffffffff ) { + assert( s_saveConstGPRreg > 0 ); + + // make sure right GPR was saved + assert( g_cpuHasConstReg == s_saveHasConstReg || (g_cpuHasConstReg ^ s_saveHasConstReg) == (1<ltime); + CALLFunc((uptr)_StopPerfCounter); + } +#endif +} + +#define USE_FAST_BRANCHES 0 + +//void testfpu() +//{ +// int i; +// for(i = 0; i < 32; ++i ) { +// if( fpuRegs.fpr[i].UL== 0x7f800000 || fpuRegs.fpr[i].UL == 0xffc00000) { +// SysPrintf("bad fpu: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// +// if( VU0.VF[i].UL[0] == 0xffc00000 || //(VU0.VF[i].UL[1]&0xffc00000) == 0xffc00000 || +// VU0.VF[i].UL[0] == 0x7f800000) { +// SysPrintf("bad vu0: %x %x %x\n", i, cpuRegs.cycle, g_lastpc); +// } +// } +//} + +//static void cleanup() +//{ +// assert( !g_globalXMMSaved ); +//} + +static void iBranchTest(u32 newpc, u32 cpuBranch) +{ +#ifdef PCSX2_DEVBUILD + if( s_startcount ) { + StopPerfCounter(); + ADD32ItoM( (uptr)&s_pCurBlockEx->visited, 1 ); + } +#endif + +#ifdef _DEBUG + //CALLFunc((uptr)testfpu); +#endif + + if( !USE_FAST_BRANCHES || cpuBranch ) { + MOV32MtoR(ECX, (uptr)&cpuRegs.cycle); + ADD32ItoR(ECX, s_nBlockCycles*9/8); // NOTE: mulitply cycles here, 6/5 ratio stops pal ffx from randomly crashing, but crashes jakI + MOV32RtoM((uptr)&cpuRegs.cycle, ECX); // update cycles + } + else { + ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles*9/8); + return; + } + + SUB32MtoR(ECX, (uptr)&g_nextBranchCycle); + + // check if should branch + j8Ptr[0] = JS8( 0 ); + + // has to be in the middle of Save/LoadBranchState + CALLFunc( (int)cpuBranchTest ); + + if( newpc != 0xffffffff ) { + CMP32ItoM((uptr)&cpuRegs.pc, newpc); + JNE32((uptr)DispatcherReg - ( (uptr)x86Ptr + 6 )); + } + + x86SetJ8( j8Ptr[0] ); +} + + +//////////////////////////////////////////////////// +#ifndef CP2_RECOMPILE + +REC_SYS(COP2); + +#else + +void recCOP2( void ) +{ +#ifdef CPU_LOG + CPU_LOG( "Recompiling COP2:%s\n", disR5900Fasm( cpuRegs.code, cpuRegs.pc ) ); +#endif + + if ( !cpucaps.hasStreamingSIMDExtensions ) { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + g_cpuHasConstReg = 1; // reset all since COP2 can change regs + CALLFunc( (u32)COP2 ); + + CMP32ItoM((uptr)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles); + JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + } + else + { + recCOP22( ); + } +} + +#endif + +//////////////////////////////////////////////////// +void recSYSCALL( void ) { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_NODESTROY); + CALLFunc( (u32)SYSCALL ); + + CMP32ItoM((uptr)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles); + JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr + 5 )); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +void recBREAK( void ) { + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BREAK ); + + CMP32ItoM((uptr)&cpuRegs.pc, pc); + j8Ptr[0] = JE8(0); + ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles); + + if( REC_INC_STACK ) + ADD64ItoR(RSP, REC_INC_STACK); + RET(); + x86SetJ8(j8Ptr[0]); + //branch = 2; +} + +//////////////////////////////////////////////////// +//static void recCACHE( void ) { +// MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); +// MOV32ItoM( (uptr)&cpuRegs.pc, pc ); +// iFlushCall(FLUSH_EVERYTHING); +// CALLFunc( (u32)CACHE ); +// //branch = 2; +// +// CMP32ItoM((uptr)&cpuRegs.pc, pc); +// j8Ptr[0] = JE8(0); +// RET(); +// x86SetJ8(j8Ptr[0]); +//} + + +void recPREF( void ) +{ +} + +void recSYNC( void ) +{ +} + +void recMFSA( void ) +{ + int mmreg; + if (!_Rd_) return; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rd_, MODE_WRITE)) >= 0 ) { + SSE_MOVLPS_M64_to_XMM(mmreg, (uptr)&cpuRegs.sa); + } + else { + MOV64MtoR(RAX, (uptr)&cpuRegs.sa); + _deleteEEreg(_Rd_, 0); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + //else { + // mmreg = _allocX86reg(-1, X86TYPE_GPR, _Rd_, MODE_WRITE); + // MOV64MtoR(mmreg, (uptr)&cpuRegs.sa); + //} +} + +void recMTSA( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&cpuRegs.sa, g_cpuConstRegs[_Rs_].UL[0] ); + } + else { + int mmreg; + + if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rs_, MODE_READ)) >= 0 ) { + SSE_MOVSS_XMM_to_M32((uptr)&cpuRegs.sa, mmreg); + } + else { + MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV32RtoM((uptr)&cpuRegs.sa, EAX); + } + } +} + +void recMTSAB( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0xF) ^ (_Imm_ & 0xF)) << 3); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0xF); + XOR32ItoR(EAX, _Imm_&0xf); + SHL32ItoR(EAX, 3); + MOV32RtoM((uptr)&cpuRegs.sa, EAX); + } +} + +void recMTSAH( void ) +{ + if( GPR_IS_CONST1(_Rs_) ) { + MOV32ItoM((uptr)&cpuRegs.sa, ((g_cpuConstRegs[_Rs_].UL[0] & 0x7) ^ (_Imm_ & 0x7)) << 4); + } + else { + _eeMoveGPRtoR(EAX, _Rs_); + AND32ItoR(EAX, 0x7); + XOR32RtoR(EAX, _Imm_&0x7); + SHL32ItoR(EAX, 4); + MOV32RtoM((uptr)&cpuRegs.sa, EAX); + } +} + +#if !defined(_MSC_VER) +static void checkcodefn() +{ + int pctemp; + + __asm__("movl %%eax, %0" : "=m"(pctemp) ); + + SysPrintf("code changed! %x\n", pctemp); + assert(0); +} +#endif + +void checkpchanged(u32 startpc) +{ + assert(0); +} + +//#ifdef _DEBUG +//#define CHECK_XMMCHANGED() CALLFunc((uptr)checkxmmchanged); +//#else +//#define CHECK_XMMCHANGED() +//#endif +// +//static void checkxmmchanged() +//{ +// assert( !g_globalXMMSaved ); +//} + +u32 recompileCodeSafe(u32 temppc) +{ + BASEBLOCK* pblock = PC_GETBLOCK(temppc); + + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + if( pc == pblock->startpc ) + return 0; + } + + return 1; +} + +void recompileNextInstruction(int delayslot) +{ + static u8 s_bFlushReg = 1; + int i, count; + + BASEBLOCK* pblock = PC_GETBLOCK(pc); + + // need *ppblock != s_pCurBlock because of branches + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( !delayslot && pc == pblock->startpc ) { + // code already in place, so jump to it and exit recomp + assert( PC_GETBLOCKEX(pblock)->startpc == pblock->startpc ); + + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((uptr)&cpuRegs.pc, pc); + +// if( pexblock->pOldFnptr ) { +// // code already in place, so jump to it and exit recomp +// JMP32((u32)pexblock->pOldFnptr - ((u32)x86Ptr + 5)); +// branch = 3; +// return; +// } + + JMP32((uptr)pblock->pFnptr - ((uptr)x86Ptr + 5)); + branch = 3; + return; + } + else { + + if( !(delayslot && pblock->startpc == pc) ) { + s8* oldX86 = x86Ptr; + //__Log("clear block %x\n", pblock->startpc); + recClearMem(pblock); + x86Ptr = oldX86; + if( delayslot ) + SysPrintf("delay slot %x\n", pc); + } + } + } + + if( delayslot ) + pblock->uType = BLOCKTYPE_DELAYSLOT; + + s_pCode = (int *)PSM( pc ); + assert(s_pCode); + +#ifdef _DEBUG + MOV32ItoR(EAX, pc); +#endif + + cpuRegs.code = *(int *)s_pCode; + s_nBlockCycles++; + pc += 4; + +//#ifdef _DEBUG +// CMP32ItoM((u32)s_pCode, cpuRegs.code); +// j8Ptr[0] = JE8(0); +// MOV32ItoR(EAX, pc); +// CALLFunc((uptr)checkcodefn); +// x86SetJ8( j8Ptr[ 0 ] ); +// +// if( !delayslot ) { +// CMP32ItoM((uptr)&cpuRegs.pc, s_pCurBlockEx->startpc); +// j8Ptr[0] = JB8(0); +// CMP32ItoM((uptr)&cpuRegs.pc, pc); +// j8Ptr[1] = JA8(0); +// j8Ptr[2] = JMP8(0); +// x86SetJ8( j8Ptr[ 0 ] ); +// x86SetJ8( j8Ptr[ 1 ] ); +// PUSH32I(s_pCurBlockEx->startpc); +// CALLFunc((uptr)checkpchanged); +// ADD32ItoR(ESP, 4); +// x86SetJ8( j8Ptr[ 2 ] ); +// } +//#endif + + g_pCurInstInfo++; + + // reorder register priorities + for(i = 0; i < X86REGS; ++i) { + if( x86regs[i].inuse ) { + if( x86regs[i].type == X86TYPE_GPR ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, x86regs[i].reg); + if( count > 0 ) x86regs[i].counter = 1000-count; + else x86regs[i].counter = 0; + } + else x86regs[i].counter = 0; + } + } + + for(i = 0; i < XMMREGS; ++i) { + if( xmmregs[i].inuse ) { + count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); + if( count > 0 ) xmmregs[i].counter = 1000-count; + else xmmregs[i].counter = 0; + } + } + + // peephole optimizations + if( g_pCurInstInfo->info & EEINSTINFO_COREC ) { + +#ifdef PCSX2_VIRTUAL_MEM + if( g_pCurInstInfo->numpeeps > 1 ) { + switch(cpuRegs.code>>26) { + case 30: recLQ_coX(g_pCurInstInfo->numpeeps); break; + case 31: recSQ_coX(g_pCurInstInfo->numpeeps); break; + case 49: recLWC1_coX(g_pCurInstInfo->numpeeps); break; + case 57: recSWC1_coX(g_pCurInstInfo->numpeeps); break; + case 55: recLD_coX(g_pCurInstInfo->numpeeps); break; + case 63: recSD_coX(g_pCurInstInfo->numpeeps); break; + default: + assert(0); + } + + pc += g_pCurInstInfo->numpeeps*4; + s_nBlockCycles += g_pCurInstInfo->numpeeps; + g_pCurInstInfo += g_pCurInstInfo->numpeeps; + } + else { + recBSC_co[cpuRegs.code>>26](); + pc += 4; + s_nBlockCycles++; + g_pCurInstInfo++; + } +#else + assert(0); +#endif + } + else { + assert( !(g_pCurInstInfo->info & EEINSTINFO_NOREC) ); + + // if this instruction is a jump or a branch, exit right away + if( delayslot ) { + switch(cpuRegs.code>>26) { + case 1: + switch(_Rt_) { + case 0: case 1: case 2: case 3: case 0x10: case 0x11: case 0x12: case 0x13: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededXMMregs(); + return; + } + break; + + case 2: case 3: case 4: case 5: case 6: case 7: case 0x14: case 0x15: case 0x16: case 0x17: + SysPrintf("branch %x in delay slot!\n", cpuRegs.code); + _clearNeededX86regs(); + _clearNeededXMMregs(); + return; + } + } + recBSC[ cpuRegs.code >> 26 ](); + } + + if( !delayslot ) { + if( s_bFlushReg ) { + //if( !_flushUnusedConstReg() ) { + int flushed = 0; + if( !flushed && _getNumXMMwrite() > 2 ) _flushXMMunused(); + s_bFlushReg = !flushed; +// } +// else s_bFlushReg = 0; + } + else s_bFlushReg = 1; + } + else s_bFlushReg = 1; + + //CHECK_XMMCHANGED(); + _clearNeededX86regs(); + _clearNeededXMMregs(); + + // for now + _freeXMMregs(); + _flushCachedRegs(); + g_cpuHasConstReg = 0; +} + +//////////////////////////////////////////////////// +#include "R3000A.h" +#include "PsxCounters.h" +#include "PsxMem.h" +extern tIPU_BP g_BP; + +extern u32 psxdump; +extern u32 psxNextCounter, psxNextsCounter; +extern void iDumpPsxRegisters(u32 startpc, u32 temp); +extern Counter counters[6]; + +void iDumpRegisters(u32 startpc, u32 temp) +{ + int i; + char* pstr = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + extern char *disRNameGPR[]; + + __Log("%sreg: %x %x\n", pstr, startpc, cpuRegs.interrupt); + for(i = 1; i < 32; ++i) __Log("%s: %x_%x_%x_%x\n", disRNameGPR[i], cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x\n", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x\n", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x\n", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x\n", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + __Log("%svfACC: %x %x %x %x\n", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x\n", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x\n", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("cyc11: %x %x; vu0: %x, vu1: %x\n", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x\n", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x\n", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + } + __Log("VIF0_STAT = %x, VIF1_STAT = %x\n", psHu32(0x3800), psHu32(0x3C00)); + __Log("ipu %x %x %x %x; bp: %x %x %x %x\n", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x\n", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + for(i = 0; i < ARRAYSIZE(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x\n", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x\n", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x\n", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x\n", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +} + +extern u32 psxdump; + +static void printfn() +{ + static int lastrec = 0; + static int curcount = 0, count2 = 0; + const int skip = 0; + static int i; + + assert( !g_globalXMMSaved ); + +#ifdef _DEBUG + //__asm stmxcsr i + //assert( i = g_sseMXCSR ); +#endif + + if( (dumplog&2) ) {//&& lastrec != g_lastpc ) { + + curcount++; + + if( curcount > skip ) { + iDumpRegisters(g_lastpc, 1); + curcount = 0; + } + + lastrec = g_lastpc; + } +} + +u32 s_recblocks[] = {0}; + +void badespfn() { + assert(0); + SysPrintf("Bad esp!\n"); +} + +#define OPTIMIZE_COP2 0//CHECK_VU0REC + +void recRecompile( u32 startpc ) +{ + u32 i = 0; + u32 branchTo; + u32 willbranch3 = 0; + u32* ptr; + u32 usecop2; + +#ifdef _DEBUG + //dumplog |= 4; + if( dumplog & 4 ) + iDumpRegisters(startpc, 0); +#endif + + assert( startpc ); + + // if recPtr reached the mem limit reset whole mem + if ( ( (uptr)recPtr - (uptr)recMem ) >= REC_CACHEMEM-0x40000 || dumplog == 0xffffffff) { + recReset(); + } + if ( ( (uptr)recStackPtr - (uptr)recStack ) >= RECSTACK_SIZE-0x100 ) { +#ifdef _DEBUG + SysPrintf("stack reset\n"); +#endif + recReset(); + } + + s_pCurBlock = PC_GETBLOCK(startpc); + + if( s_pCurBlock->pFnptr ) { + // clear if already taken + assert( s_pCurBlock->startpc < startpc ); + recClearMem(s_pCurBlock); + } + + if( s_pCurBlock->startpc == startpc ) { + s_pCurBlockEx = PC_GETBLOCKEX(s_pCurBlock); + assert( s_pCurBlockEx->startpc == startpc ); + } + else { + s_pCurBlockEx = NULL; + for(i = 0; i < EE_NUMBLOCKS; ++i) { + if( recBlocks[(i+s_nNextBlock)%EE_NUMBLOCKS].size == 0 ) { + s_pCurBlockEx = recBlocks+(i+s_nNextBlock)%EE_NUMBLOCKS; + s_nNextBlock = (i+s_nNextBlock+1)%EE_NUMBLOCKS; + break; + } + } + + if( s_pCurBlockEx == NULL ) { + //SysPrintf("ee reset (blocks)\n"); + recReset(); + s_nNextBlock = 0; + s_pCurBlockEx = recBlocks; + } + + s_pCurBlockEx->startpc = startpc; + } + + x86SetPtr( recPtr ); + x86Align(16); + recPtr = x86Ptr; + + assert( (uptr)x86Ptr <= 0xffffffff ); + s_pCurBlock->pFnptr = (u32)x86Ptr; + s_pCurBlock->startpc = startpc; + + branch = 0; + + // reset recomp state variables + s_nBlockCycles = 0; + pc = startpc; + iCWstate = 0; + s_saveConstGPRreg = 0; + g_cpuHasConstReg = g_cpuFlushedConstReg = 1; + g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff; + g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0; + _recClearWritebacks(); + assert( g_cpuConstRegs[0].UD[0] == 0 ); + + _initX86regs(); + _initXMMregs(); + +#ifdef _DEBUG + //CMP64MtoR(RSP, (uptr)&s_uSaveESP); + //j8Ptr[0] = JE8(0); + //CALLFunc((uptr)badespfn); + //x86SetJ8(j8Ptr[0]); + + // for debugging purposes + MOV32ItoM((uptr)&g_lastpc, pc); + CALLFunc((uptr)printfn); +#endif + + // go until the next branch + i = startpc; + s_nEndBlock = 0xffffffff; + s_nHasDelay = 0; + + while(1) { + BASEBLOCK* pblock = PC_GETBLOCK(i); + if( pblock->pFnptr != 0 && pblock->startpc != s_pCurBlock->startpc ) { + + if( i == pblock->startpc ) { + // branch = 3 + willbranch3 = 1; + s_nEndBlock = i; + break; + } + } + + cpuRegs.code = *(int *)PSM(i); + + switch(cpuRegs.code >> 26) { + case 0: // special + + if( _Funct_ == 8 || _Funct_ == 9 ) { // JR, JALR + s_nEndBlock = i + 8; + s_nHasDelay = 1; + goto StartRecomp; + } + + break; + case 1: // regimm + + if( _Rt_ < 4 || (_Rt_ >= 16 && _Rt_ < 20) ) { + // branches + if( _Rt_ == 2 && _Rt_ == 3 && _Rt_ == 18 && _Rt_ == 19 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + + break; + + case 2: // J + case 3: // JAL + s_nHasDelay = 1; + s_nEndBlock = i + 8; + goto StartRecomp; + + // branches + case 4: case 5: case 6: case 7: + case 20: case 21: case 22: case 23: + + if( (cpuRegs.code >> 26) >= 20 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + + case 16: // cp0 + if( _Rs_ == 16 ) { + if( _Funct_ == 24 ) { // eret + s_nEndBlock = i+4; + goto StartRecomp; + } + } + + break; + case 17: // cp1 + case 18: // cp2 + if( _Rs_ == 8 ) { + // BC1F, BC1T, BC1FL, BC1TL + // BC2F, BC2T, BC2FL, BC2TL + if( _Rt_ >= 2 ) s_nHasDelay = 1; + else s_nHasDelay = 2; + + branchTo = _Imm_ * 4 + i + 4; + if( branchTo > startpc && branchTo < i ) s_nEndBlock = branchTo; + else s_nEndBlock = i+8; + + goto StartRecomp; + } + break; + } + + i += 4; + } + +StartRecomp: + + // rec info // + { + EEINST* pcur; + + if( s_nInstCacheSize < (s_nEndBlock-startpc)/4+1 ) { + free(s_pInstCache); + s_nInstCacheSize = (s_nEndBlock-startpc)/4+10; + s_pInstCache = (EEINST*)malloc(sizeof(EEINST)*s_nInstCacheSize); + assert( s_pInstCache != NULL ); + } + + pcur = s_pInstCache + (s_nEndBlock-startpc)/4; + _recClearInst(pcur); + pcur->info = 0; + + for(i = s_nEndBlock; i > startpc; i -= 4 ) { + cpuRegs.code = *(int *)PSM(i-4); + pcur[-1] = pcur[0]; + rpropBSC(pcur-1, pcur); + pcur--; + } + } + + // analyze instructions // + { + usecop2 = 0; + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock; i += 4) { + g_pCurInstInfo++; + cpuRegs.code = *(u32*)PSM(i); + + // cop2 // + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + + if( !usecop2 ) { + // init + if( OPTIMIZE_COP2 ) { + memset(VU0.fmac,0,sizeof(VU0.fmac)); + memset(&VU0.fdiv,0,sizeof(VU0.fdiv)); + memset(&VU0.efu,0,sizeof(VU0.efu)); + } + vucycle = 0; + usecop2 = 1; + } + + VU0.code = cpuRegs.code; + _cop2AnalyzeOp(g_pCurInstInfo, OPTIMIZE_COP2); + continue; + } + + if( usecop2 ) vucycle++; + + // peephole optimizations // +#ifdef PCSX2_VIRTUAL_MEM + if( i < s_nEndBlock-4 && recompileCodeSafe(i) ) { + u32 curcode = cpuRegs.code; + u32 nextcode = *(u32*)PSM(i+4); + if( _eeIsLoadStoreCoIssue(curcode, nextcode) && recBSC_co[curcode>>26] != NULL ) { + + // rs has to be the same, and cannot be just written + if( ((curcode >> 21) & 0x1F) == ((nextcode >> 21) & 0x1F) && !_eeLoadWritesRs(curcode) ) { + + if( _eeIsLoadStoreCoX(curcode) && ((nextcode>>16)&0x1f) != ((curcode>>21)&0x1f) ) { + // see how many stores there are + u32 j; + // use xmmregs since only supporting lwc1,lq,swc1,sq + for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + u32 nncode = *(u32*)PSM(j); + if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || + _eeLoadWritesRs(nncode)) + break; + } + + if( j > i+8 ) { + u32 num = (j-i)>>2; // number of stores that can coissue + assert( num <= XMMREGS ); + + g_pCurInstInfo[0].numpeeps = num-1; + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + + while(i < j-4) { + g_pCurInstInfo++; + g_pCurInstInfo[0].info |= EEINSTINFO_NOREC; + i += 4; + } + + continue; + } + + // fall through + } + + // unaligned loadstores + + // if LWL, check if LWR and that offsets are +3 away + switch(curcode >> 26) { + case 0x22: // LWL + if( (nextcode>>26) != 0x26 || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x26: // LWR + if( (nextcode>>26) != 0x22 || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x2a: // SWL + if( (nextcode>>26) != 0x2e || ((s16)nextcode)+3 != (s16)curcode ) + continue; + break; + case 0x2e: // SWR + if( (nextcode>>26) != 0x2a || ((s16)nextcode) != (s16)curcode+3 ) + continue; + break; + + case 0x1a: // LDL + if( (nextcode>>26) != 0x1b || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x1b: // LWR + if( (nextcode>>26) != 0x1aa || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + + case 0x2c: // SWL + if( (nextcode>>26) != 0x2d || ((s16)nextcode)+7 != (s16)curcode ) + continue; + break; + case 0x2d: // SWR + if( (nextcode>>26) != 0x2c || ((s16)nextcode) != (s16)curcode+7 ) + continue; + break; + } + + // good enough + g_pCurInstInfo[0].info |= EEINSTINFO_COREC; + g_pCurInstInfo[0].numpeeps = 1; + g_pCurInstInfo[1].info |= EEINSTINFO_NOREC; + g_pCurInstInfo++; + i += 4; + continue; + } + } + } +#endif // end peephole + } + + if( usecop2 ) { + // add necessary mac writebacks + g_pCurInstInfo = s_pInstCache; + + for(i = startpc; i < s_nEndBlock-4; i += 4) { + g_pCurInstInfo++; + + if( g_pCurInstInfo->info & EEINSTINFO_COP2 ) { + } + } + } + } + + // perf counters // +#ifdef PCSX2_DEVBUILD + s_startcount = 0; +// if( pc+32 < s_nEndBlock ) { +// // only blocks with more than 8 insts +// //PUSH32I((uptr)&lbase); +// //CALLFunc((uptr)QueryPerformanceCounter); +// lbase.QuadPart = GetCPUTick(); +// s_startcount = 1; +// } +#endif + +#ifdef _DEBUG + // dump code + for(i = 0; i < ARRAYSIZE(s_recblocks); ++i) { + if( startpc == s_recblocks[i] ) { + iDumpBlock(startpc, recPtr); + } + } + + if( (dumplog & 1) ) //|| usecop2 ) + iDumpBlock(startpc, recPtr); +#endif + + // finally recompile // + g_pCurInstInfo = s_pInstCache; + while (!branch && pc < s_nEndBlock) { + recompileNextInstruction(0); + } + +#ifdef _DEBUG + if( (dumplog & 1) ) + iDumpBlock(startpc, recPtr); +#endif + + assert( (pc-startpc)>>2 <= 0xffff ); + s_pCurBlockEx->size = (pc-startpc)>>2; + + for(i = 1; i < (u32)s_pCurBlockEx->size-1; ++i) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // don't overwrite if delay slot + if( i < (u32)s_pCurBlockEx->size && !(s_pCurBlock[i].uType & BLOCKTYPE_DELAYSLOT) ) { + s_pCurBlock[i].pFnptr = s_pCurBlock->pFnptr; + s_pCurBlock[i].startpc = s_pCurBlock->startpc; + } + + // set the block ptr + AddBaseBlockEx(s_pCurBlockEx, 0); +// if( p[1].startpc == p[0].startpc + 4 ) { +// assert( p[1].pFnptr != 0 ); +// // already fn in place, so add to list +// AddBaseBlockEx(s_pCurBlockEx, 0); +// } +// else +// *(BASEBLOCKEX**)(p+1) = pex; +// } + + //PC_SETBLOCKEX(s_pCurBlock, s_pCurBlockEx); + + if( !(pc&0x10000000) ) + maxrecmem = max( (pc&~0xa0000000), maxrecmem ); + + if( branch == 2 ) { + iFlushCall(FLUSH_EVERYTHING); + + iBranchTest(0xffffffff, 1); + if( bExecBIOS ) CheckForBIOSEnd(); + + JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr + 5 )); + } + else { + assert( branch != 3 ); + if( branch ) assert( !willbranch3 ); + else ADD32ItoM((uptr)&cpuRegs.cycle, s_nBlockCycles*9/8); + + if( willbranch3 ) { + BASEBLOCK* pblock = PC_GETBLOCK(s_nEndBlock); + assert( pc == s_nEndBlock ); + iFlushCall(FLUSH_EVERYTHING); + MOV32ItoM((uptr)&cpuRegs.pc, pc); + JMP32((uptr)pblock->pFnptr - ((uptr)x86Ptr + 5)); + branch = 3; + } + else if( !branch ) { + // didn't branch, but had to stop + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + + iFlushCall(FLUSH_EVERYTHING); + + ptr = JMP32(0); + } + } + + assert( x86Ptr >= (s8*)s_pCurBlock->pFnptr + EE_MIN_BLOCK_BYTES ); + assert( x86Ptr < recMem+REC_CACHEMEM ); + assert( recStackPtr < recStack+RECSTACK_SIZE ); + assert( x86FpuState == 0 ); + + recPtr = x86Ptr; + + assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); + + if( !branch ) { + BASEBLOCK* pcurblock = s_pCurBlock; + u32 nEndBlock = s_nEndBlock; + s_pCurBlock = PC_GETBLOCK(pc); + assert( ptr != NULL ); + + if( s_pCurBlock->startpc != pc ) + recRecompile(pc); + + if( pcurblock->startpc == startpc ) { + assert( pcurblock->pFnptr ); + assert( s_pCurBlock->startpc == nEndBlock ); + *ptr = s_pCurBlock->pFnptr - ( (uptr)ptr + 4 ); + } + else { + recRecompile(startpc); + assert( pcurblock->pFnptr != 0 ); + } + } +} + +R5900cpu recCpu = { + recInit, + recReset, + recStep, + recExecute, + recExecuteBlock, + recExecuteVU0Block, + recExecuteVU1Block, + recEnableVU0micro, + recEnableVU1micro, + recClear, + recClearVU0, + recClearVU1, + recShutdown +}; + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900Arit-64.c b/pcsx2/x86/ix86-64/iR5900Arit-64.c new file mode 100644 index 0000000..851ec8f --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900Arit-64.c @@ -0,0 +1,212 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ + +#ifndef ARITHMETIC_RECOMPILE + +REC_FUNC(ADD); +REC_FUNC(ADDU); +REC_FUNC(DADD); +REC_FUNC(DADDU); +REC_FUNC(SUB); +REC_FUNC(SUBU); +REC_FUNC(DSUB); +REC_FUNC(DSUBU); +REC_FUNC(AND); +REC_FUNC(OR); +REC_FUNC(XOR); +REC_FUNC(NOR); +REC_FUNC(SLT); +REC_FUNC(SLTU); + +#else + +//////////////////////////////////////////////////// +void recADD( void ) { + if (!_Rd_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Rt_ != 0) { + ADD32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDU( void ) +{ + recADD( ); +} + +//////////////////////////////////////////////////// +void recDADD( void ) { + if (!_Rd_) return; + + MOV64MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + ADD64MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); +} + +//////////////////////////////////////////////////// +void recDADDU( void ) +{ + recDADD( ); +} + +//////////////////////////////////////////////////// +void recSUB( void ) { + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + SUB32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSUBU( void ) +{ + recSUB( ); +} + +//////////////////////////////////////////////////// +void recDSUB( void ) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Rt_ != 0 ) { + SUB64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + } + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSUBU( void ) +{ + recDSUB( ); +} + +//////////////////////////////////////////////////// +void recAND( void ) { + if (!_Rd_) return; + + if (_Rt_ == _Rd_) { // Rd&= Rs + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else if (_Rs_ == _Rd_) { // Rd&= Rt + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + AND64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } else { // Rd = Rs & Rt + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + AND64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +} + +//////////////////////////////////////////////////// +void recOR( void ) { + if (!_Rd_) return; + + if ( ( _Rs_ == 0 ) && ( _Rt_ == 0 ) ) { + XOR64RtoR(RAX, RAX); + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[0], RAX ); + } else if ( _Rs_ == 0 ) { + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else if ( _Rt_ == 0 ) { + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } + else { + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); + } +} + +//////////////////////////////////////////////////// +void recXOR( void ) { + if (!_Rd_) return; + + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + XOR64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +//////////////////////////////////////////////////// +void recNOR( void ) { + if (!_Rd_) return; + + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + OR64MtoR(RAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + NOT64R(RAX); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +//////////////////////////////////////////////////// +void recSLT( void ) { + if (!_Rd_) return; + + MOV64MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + SETL8R (EAX); + AND64I32toR(EAX, 0xff); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); +} + +//////////////////////////////////////////////////// +void recSLTU( void ) { + if (!_Rd_) return; + + MOV64MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); + CMP64MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + SBB64RtoR(EAX, EAX); + NEG64R (EAX); + MOV64RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], RAX); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900AritImm-64.c b/pcsx2/x86/ix86-64/iR5900AritImm-64.c new file mode 100644 index 0000000..5810dfc --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900AritImm-64.c @@ -0,0 +1,168 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +#ifndef ARITHMETICIMM_RECOMPILE + +REC_FUNC(ADDI); +REC_FUNC(ADDIU); +REC_FUNC(DADDI); +REC_FUNC(DADDIU); +REC_FUNC(ANDI); +REC_FUNC(ORI); +REC_FUNC(XORI); + +REC_FUNC(SLTI); +REC_FUNC(SLTIU); + +#else + +//////////////////////////////////////////////////// +void recADDI( void ) { + if (!_Rt_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if (_Imm_ != 0) { + ADD32ItoR( EAX, _Imm_ ); + } + + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recADDIU( void ) +{ + recADDI( ); +} + +//////////////////////////////////////////////////// +void recDADDI( void ) { + int rsreg; + int rtreg; + + if (!_Rt_) return; + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD64ItoR( EAX, _Imm_ ); + } + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDADDIU( void ) +{ + recDADDI( ); +} + +//////////////////////////////////////////////////// +void recSLTIU( void ) +{ + if ( ! _Rt_ ) return; + + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64I32toR(RAX, _Imm_); + SETB8R (EAX); + AND64I32toR(EAX, 0xff); + MOV64RtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recSLTI( void ) +{ + if ( ! _Rt_ ) + return; + + MOV64MtoR(RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + CMP64I32toR(RAX, _Imm_); + SETL8R (EAX); + AND64I32toR(EAX, 0xff); + MOV64RtoM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX); +} + +//////////////////////////////////////////////////// +void recANDI( void ) { + if (!_Rt_) return; + + if ( _ImmU_ != 0 ) { + if (_Rs_ == _Rt_) { + MOV32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + AND32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _ImmU_ ); + } + else { + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( EAX, _ImmU_ ); + MOV32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], EAX ); + } + } + else { + MOV32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ], 0 ); + MOV32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], 0 ); + } +} + +//////////////////////////////////////////////////// +void recORI( void ) { + if (!_Rt_) return; + + if (_Rs_ == _Rt_) { + OR32ItoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], _ImmU_ ); + } else { + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + if ( _ImmU_ != 0 ) { + OR64ItoR( RAX, _ImmU_ ); + } + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); + } +} + +//////////////////////////////////////////////////// +void recXORI( void ) { + if (!_Rt_) return; + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); + XOR64ItoR( RAX, _ImmU_ ); + MOV64RtoM( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ], RAX ); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900Branch-64.c b/pcsx2/x86/ix86-64/iR5900Branch-64.c new file mode 100644 index 0000000..01b1464 --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900Branch-64.c @@ -0,0 +1,536 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#ifndef BRANCH_RECOMPILE + +REC_SYS(BEQ); +REC_SYS(BEQL); +REC_SYS(BNE); +REC_SYS(BNEL); +REC_SYS(BLTZ); +REC_SYS(BGTZ); +REC_SYS(BLEZ); +REC_SYS(BGEZ); +REC_SYS(BGTZL); +REC_SYS(BLTZL); +REC_SYS(BLTZAL); +REC_SYS(BLTZALL); +REC_SYS(BLEZL); +REC_SYS(BGEZL); +REC_SYS(BGEZAL); +REC_SYS(BGEZALL); + +#else + +u32 target; +//////////////////////////////////////////////////// +void recBEQ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededX86regs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + else + { + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); + } +} + +//////////////////////////////////////////////////// +void recBNE( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + if ( _Rs_ == _Rt_ ) + { + _clearNeededX86regs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm(pc); + return; + } + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLTZAL( void ) +{ + SysPrintf("BLTZAL\n"); + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BLTZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZAL( void ) +{ + SysPrintf("BGEZAL\n"); + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BGEZAL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBLEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + _deleteEEreg(_Rs_, 1); + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JGE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JLE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZ( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + branchTo = pc+4; + + recompileNextInstruction(1); + SetBranchImm( branchTo ); + return; + } + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JG32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + pc -= 4; + LoadBranchState(); + recompileNextInstruction(1); + + SetBranchImm(pc); +} + +/********************************************************* +* Register branch logic Likely * +* Format: OP rs, offset * +*********************************************************/ + +//////////////////////////////////////////////////// +void recBLEZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] <= 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededX86regs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JL32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] > 0) ) + SetBranchImm( pc + 4); + else { + _clearNeededX86regs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + _deleteEEreg(_Rs_, 1); + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JGE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] < 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JLE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBGEZL( void ) +{ +u32 branchTo = ((s32)_Imm_ * 4) + pc; + + _eeFlushAllUnused(); + + if( GPR_IS_CONST1(_Rs_) ) { + if( !(g_cpuConstRegs[_Rs_].SD[0] >= 0) ) + SetBranchImm( pc + 4); + else { + recompileNextInstruction(1); + SetBranchImm( branchTo ); + } + return; + } + + XOR64RtoR(RAX, RAX); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ]); + j32Ptr[ 0 ] = JG32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBLTZALL( void ) +{ + SysPrintf("BLTZALL\n"); + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BLTZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBGEZALL( void ) +{ + SysPrintf("BGEZALL\n"); + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + iFlushCall(FLUSH_EVERYTHING); + CALLFunc( (u32)BGEZALL ); + branch = 2; +} + +//////////////////////////////////////////////////// +void recBEQL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); + + x86SetJ32( j32Ptr[ 0 ] ); + + LoadBranchState(); + SetBranchImm(pc); +} + +//////////////////////////////////////////////////// +void recBNEL( void ) +{ + u32 branchTo = ((s32)_Imm_ * 4) + pc; + + MOV64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + CMP64MtoR( RAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + j32Ptr[ 0 ] = JNE32( 0 ); + + _clearNeededX86regs(); + _clearNeededXMMregs(); + + SaveBranchState(); + SetBranchImm(pc+4); + + x86SetJ32( j32Ptr[ 0 ] ); + + // recopy the next inst + LoadBranchState(); + recompileNextInstruction(1); + SetBranchImm(branchTo); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900Jump-64.c b/pcsx2/x86/ix86-64/iR5900Jump-64.c new file mode 100644 index 0000000..8eba163 --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900Jump-64.c @@ -0,0 +1,113 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +#ifndef JUMP_RECOMPILE + +REC_SYS(J); +REC_SYS(JAL); +REC_SYS(JR); +REC_SYS(JALR); + +#else + +//////////////////////////////////////////////////// +void recJ( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +//////////////////////////////////////////////////// +void recJAL( void ) +{ + u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 ); + _deleteEEreg(31, 0); + GPR_SET_CONST(31); + g_cpuConstRegs[31].UL[0] = pc + 4; + g_cpuConstRegs[31].UL[1] = 0; + + recompileNextInstruction(1); + SetBranchImm(newpc); +} + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ + +//////////////////////////////////////////////////// +void recJR( void ) +{ + SetBranchReg( _Rs_ ); +} + +//////////////////////////////////////////////////// +void recJALR( void ) +{ + _allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE); + _eeMoveGPRtoR(ESI, _Rs_); + + if ( _Rd_ ) { + _deleteEEreg(_Rd_, 0); + GPR_SET_CONST(_Rd_); + g_cpuConstRegs[_Rd_].UL[0] = pc + 4; + g_cpuConstRegs[_Rd_].UL[1] = 0; + } + + _clearNeededX86regs(); + _clearNeededXMMregs(); + recompileNextInstruction(1); + + if( x86regs[ESI].inuse ) { + assert( x86regs[ESI].type == X86TYPE_PCWRITEBACK ); + MOV32RtoM((int)&cpuRegs.pc, ESI); + x86regs[ESI].inuse = 0; + } + else { + MOV32MtoR(EAX, (u32)&g_recWriteback); + MOV32RtoM((int)&cpuRegs.pc, EAX); + } + + SetBranchReg(0xffffffff); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900LoadStore-64.c b/pcsx2/x86/ix86-64/iR5900LoadStore-64.c new file mode 100644 index 0000000..136c300 --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900LoadStore-64.c @@ -0,0 +1,422 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" +#include "VU0.h" + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +#ifndef LOADSTORE_RECOMPILE + +REC_FUNC(LB); +REC_FUNC(LBU); +REC_FUNC(LH); +REC_FUNC(LHU); +REC_FUNC(LW); +REC_FUNC(LWU); +REC_FUNC(LWL); +REC_FUNC(LWR); +REC_FUNC(LD); +REC_FUNC(LDR); +REC_FUNC(LDL); +REC_FUNC(LQ); +REC_FUNC(SB); +REC_FUNC(SH); +REC_FUNC(SW); +REC_FUNC(SWL); +REC_FUNC(SWR); +REC_FUNC(SD); +REC_FUNC(SDL); +REC_FUNC(SDR); +REC_FUNC(SQ); +REC_FUNC(LWC1); +REC_FUNC(SWC1); +REC_FUNC(LQC2); +REC_FUNC(SQC2); + +void SetFastMemory(int bSetFast) {} + +#else + +static int s_bFastMemory = 0; +void SetFastMemory(int bSetFast) +{ + s_bFastMemory = bSetFast; +} + +u64 retValue; +u64 dummyValue[ 4 ]; + +//////////////////////////////////////////////////// +void recLB( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc( (uptr)memRead8RS ); +} + +//////////////////////////////////////////////////// +void recLBU( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + iFlushCall(FLUSH_EVERYTHING); + CALLFunc((uptr)memRead8RU ); +} + +//////////////////////////////////////////////////// +void recLH( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ){ + ADD32ItoR( X86ARG1, _Imm_ ); + } + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + iFlushCall(FLUSH_EVERYTHING); + CALLFunc((uptr)memRead16RS ); +} + +//////////////////////////////////////////////////// +void recLHU( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc((uptr)memRead16RU ); +} + +void tests() { + SysPrintf("Err\n"); +} + +//////////////////////////////////////////////////// +void recLW( void ) { + int rsreg; + int rtreg; + int t0reg; + int t1reg; + int t2reg; + + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc((uptr)memRead32RS ); +} + +//////////////////////////////////////////////////// +void recLWU( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc((uptr)memRead32RU ); +} + +void recLWL( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)LWL ); +} + +void recLWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)LWR ); +} + +void recLD( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } + else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc((uptr)memRead64 ); +} + +void recLDL( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)LDL ); +} + +void recLDR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)LDR ); +} + +void recLQ( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_); + } + AND32ItoR( X86ARG1, ~0xf ); + + if ( _Rt_ ) { + MOV64ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + } else { + MOV64ItoR( X86ARG2, (uptr)&dummyValue ); + } + CALLFunc((uptr)memRead128 ); +} + +//////////////////////////////////////////////////// +void recSB( void ) { + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_); + } + MOV32MtoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc((uptr)memWrite8 ); +} + +void recSH( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + MOV32MtoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc((uptr)memWrite16 ); +} + +void recSW( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + MOV32MtoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc((uptr)memWrite32 ); +} + +void recSWL( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)SWL ); +} + +void recSWR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)SWR ); +} + +void recSD( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + MOV64MtoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc((uptr)memWrite64 ); +} + +void recSDL( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)SDL ); +} + +void recSDR( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); + MOV32ItoM( (uptr)&cpuRegs.pc, pc ); + CALLFunc((uptr)SDR ); +} + +void recSQ( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) { + ADD32ItoR( X86ARG1, _Imm_ ); + } + AND32ItoR( X86ARG1, ~0xf ); + + MOV32ItoR( X86ARG2, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); + CALLFunc((uptr)memWrite128 ); +} + +#define _Ft_ _Rt_ +#define _Fs_ _Rd_ +#define _Fd_ _Sa_ + +// Load and store for COP1 +// Format: OP rt, offset(base) +void recLWC1( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( X86ARG1, _Imm_ ); + MOV64ItoR( X86ARG2, (uptr)&fpuRegs.fpr[ _Ft_ ].UL ); + + CALLFunc((uptr)memRead32 ); +} + +void recSWC1( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( X86ARG1, _Imm_ ); + + MOV32MtoR( X86ARG2, (uptr)&fpuRegs.fpr[ _Ft_ ].UL ); + + CALLFunc((uptr)memWrite32 ); +} + +void recLQC2( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( X86ARG1, _Imm_); + + if ( _Rt_ ) + MOV64ItoR(X86ARG2, (uptr)&VU0.VF[_Ft_].UD[0] ); + else + MOV64ItoR(X86ARG2, (uptr)&dummyValue ); + + CALLFunc((uptr)memRead128 ); +} + +void recSQC2( void ) +{ + iFlushCall(FLUSH_EVERYTHING); + + MOV32MtoR( X86ARG1, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + if ( _Imm_ != 0 ) + ADD32ItoR( X86ARG1, _Imm_ ); + + MOV64ItoR(X86ARG2, (uptr)&VU0.VF[_Ft_].UD[0] ); + + CALLFunc((uptr)memWrite128 ); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900Move-64.c b/pcsx2/x86/ix86-64/iR5900Move-64.c new file mode 100644 index 0000000..bc31f4f --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900Move-64.c @@ -0,0 +1,84 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef MOVE_RECOMPILE + +REC_FUNC(LUI); +REC_FUNC(MFLO); +REC_FUNC(MFHI); +REC_FUNC(MTLO); +REC_FUNC(MTHI); +REC_FUNC(MOVZ); +REC_FUNC(MOVN); + +REC_FUNC( MFHI1 ); +REC_FUNC( MFLO1 ); +REC_FUNC( MTHI1 ); +REC_FUNC( MTLO1 ); + +#else +REC_FUNC(MFLO, _Rd_); +REC_FUNC(MFHI, _Rd_); +REC_FUNC(MTLO, 0); +REC_FUNC(MTHI, 0); +REC_FUNC(MOVZ, _Rd_); +REC_FUNC(MOVN, _Rd_); + +REC_FUNC( MFHI1, _Rd_ ); +REC_FUNC( MFLO1, _Rd_ ); +REC_FUNC( MTHI1, 0 ); +REC_FUNC( MTLO1, 0 ); + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ + +//////////////////////////////////////////////////// +void recLUI( void ) { + int rtreg; + + if (!_Rt_) return; + + MOV64I32toM((uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], (s32)(_Imm_ << 16)); +} + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900MultDiv-64.c b/pcsx2/x86/ix86-64/iR5900MultDiv-64.c new file mode 100644 index 0000000..36d68d9 --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900MultDiv-64.c @@ -0,0 +1,163 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +#ifndef MULTDIV_RECOMPILE + +REC_FUNC(MULT); +REC_FUNC(MULTU); +REC_FUNC( MULT1 ); +REC_FUNC( MULTU1 ); + +REC_FUNC(DIV); +REC_FUNC(DIVU); +REC_FUNC( DIV1 ); +REC_FUNC( DIVU1 ); + +REC_FUNC( MADD ); +REC_FUNC( MADDU ); +REC_FUNC( MADD1 ); +REC_FUNC( MADDU1 );; + +#else + +//////////////////////////////////////////////////// +void recMULT( void ) +{ + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + IMUL32M( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ ) + { + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recMULTU( void ) +{ + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + MUL32M( (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 1 ], EDX ); + if ( _Rd_ != 0 ) + { + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); + } + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 1 ], EDX ); +} + +REC_FUNC( MULT1, _Rd_ ); +REC_FUNC( MULTU1, _Rd_ ); + +//////////////////////////////////////////////////// +void recDIV( void ) +{ + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); +// XOR32RtoR( EDX,EDX ); + CDQ(); + IDIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX, ECX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 1 ], EDX ); + + x86SetJ8( j8Ptr[ 0 ] ); +} + +//////////////////////////////////////////////////// +void recDIVU( void ) +{ + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + OR32RtoR( ECX, ECX ); + j8Ptr[ 0 ] = JE8( 0 ); + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + XOR32RtoR( EDX, EDX ); + // CDQ(); + DIV32R( ECX ); + + MOV32RtoR( ECX, EDX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.LO.UL[ 1 ], EDX ); + + MOV32RtoR( EAX,ECX ); + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 0 ], ECX ); + MOV32RtoM( (uptr)&cpuRegs.HI.UL[ 1 ], EDX ); + x86SetJ8( j8Ptr[ 0 ] ); +} + +REC_FUNC( DIV1, _Rd_ ); +REC_FUNC( DIVU1, _Rd_ ); + +REC_FUNC( MADD, _Rd_ ); +REC_FUNC( MADDU, _Rd_ ); +REC_FUNC( MADD1, _Rd_ ); +REC_FUNC( MADDU1, _Rd_ ); + +#endif + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86-64/iR5900Shift-64.c b/pcsx2/x86/ix86-64/iR5900Shift-64.c new file mode 100644 index 0000000..e1ca9a7 --- /dev/null +++ b/pcsx2/x86/ix86-64/iR5900Shift-64.c @@ -0,0 +1,263 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include + +#include "Common.h" +#include "InterTables.h" +#include "ix86/ix86.h" +#include "iR5900.h" + + +#ifdef _WIN32 +#pragma warning(disable:4244) +#pragma warning(disable:4761) +#endif + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +#ifndef SHIFT_RECOMPILE + +REC_FUNC(SLL); +REC_FUNC(SRL); +REC_FUNC(SRA); +REC_FUNC(DSLL); +REC_FUNC(DSRL); +REC_FUNC(DSRA); +REC_FUNC(DSLL32); +REC_FUNC(DSRL32); +REC_FUNC(DSRA32); + +REC_FUNC(SLLV); +REC_FUNC(SRLV); +REC_FUNC(SRAV); +REC_FUNC(DSLLV); +REC_FUNC(DSRLV); +REC_FUNC(DSRAV); + +#else + + +//////////////////////////////////////////////////// +void recDSRA( void ) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSRA32(void) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SAR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recSLL(void) { + if (!_Rd_) return; + + MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHL32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +} + +//////////////////////////////////////////////////// +void recSRL(void) { + if (!_Rd_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); + if (_Sa_ != 0) { + SHR32ItoR(EAX, _Sa_); + } + CDQ(); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EDX); +} + +//////////////////////////////////////////////////// +void recSRA(void) { + if (!_Rd_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SAR32ItoR( EAX, _Sa_); + } + CDQ(); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDSLL(void) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHL64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSRL( void ) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Sa_ != 0 ) { + SHR64ItoR( RAX, _Sa_ ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSLL32(void) { + + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHL64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSRL32( void ) { + + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + SHR64ItoR( RAX, _Sa_ + 32 ); + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ + + +//////////////////////////////////////////////////// +void recSLLV( void ) { + if (!_Rd_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHL32CLtoR( EAX ); + } + CDQ(); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRLV( void ) { + if (!_Rd_) return; + + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SHR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recSRAV( void ) { + if (!_Rd_) return; + + MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x1f ); + SAR32CLtoR( EAX ); + } + CDQ( ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); + MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EDX ); +} + +//////////////////////////////////////////////////// +void recDSLLV( void ) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHL64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSRLV( void ) { + + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SHR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +//////////////////////////////////////////////////// +void recDSRAV( void ) { + if (!_Rd_) return; + + MOV64MtoR( RAX, (u64)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); + if ( _Rs_ != 0 ) + { + MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); + AND32ItoR( ECX, 0x3f ); + SAR64CLtoR( RAX ); + } + MOV64RtoM( (u64)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], RAX ); +} + +#endif + + +#endif // PCSX2_NORECBUILD diff --git a/pcsx2/x86/ix86/Makefile.am b/pcsx2/x86/ix86/Makefile.am new file mode 100644 index 0000000..b54ef7a --- /dev/null +++ b/pcsx2/x86/ix86/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I@srcdir@/.. -I@srcdir@/../../ +noinst_LIBRARIES = libix86.a + +libix86_a_SOURCES = ix86_3dnow.c ix86.c ix86_cpudetect.c ix86_fpu.c ix86.h ix86_sse.c + +if X86_64 +else +libix86_a_SOURCES += ix86_mmx.c +endif diff --git a/pcsx2/x86/ix86/ix86.c b/pcsx2/x86/ix86/ix86.c new file mode 100644 index 0000000..25684a1 --- /dev/null +++ b/pcsx2/x86/ix86/ix86.c @@ -0,0 +1,3261 @@ +/* + * ix86 core v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + */ + +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include +#include "ix86.h" + +#define SWAP(x, y) { *(u32*)&y ^= *(u32*)&x; *(u32*)&x ^= *(u32*)&y; *(u32*)&y ^= *(u32*)&x; } + +#ifdef __x86_64__ + +#ifdef _MSC_VER +// visual studio calling convention +x86IntRegType g_x86savedregs[] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15 }; +x86IntRegType g_x86tempregs[] = { R8, R9, R10, R11, RDX, RCX }; + +// arranged in savedreg -> tempreg order +x86IntRegType g_x86allregs[14] = { RBX, RBP, RSI, RDI, R12, R13, R14, R15, R8, R9, R10, R11, RDX, RCX }; + +#else +// standard calling convention + +// registers saved by calling functions (no need to flush them across calls) +x86IntRegType g_x86savedregs[] = { RBX, RBP, R12, R13, R14, R15 }; +// temp registers that need to be saved across calls +x86IntRegType g_x86tempregs[] = { RCX, RDX, R8, R9, R10, R11, RSI, RDI }; + +// arranged in savedreg -> tempreg order +x86IntRegType g_x86allregs[14] = { RBX, RBP, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11, RSI, RDI }; + +#endif + +x86IntRegType g_x868bitregs[11] = { RBX, R12, R13, R14, R15, RCX, RDX, R8, R9, R10, R11 }; +x86IntRegType g_x86non8bitregs[3] = { RBP, RSI, RDI }; + +#endif // __x86_64__ + +s8 *x86Ptr; +u8 *j8Ptr[32]; +u32 *j32Ptr[32]; + +extern void SysPrintf(char *fmt, ...); + +void WriteRmOffset(x86IntRegType to, int offset) +{ + if( (to&7) == ESP ) { + if( offset == 0 ) { + ModRM( 0, 0, 4 ); + ModRM( 0, ESP, 4 ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, 0, 4 ); + ModRM( 0, ESP, 4 ); + write8(offset); + } + else { + ModRM( 2, 0, 4 ); + ModRM( 0, ESP, 4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, 0, to ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, 0, to ); + write8(offset); + } + else { + ModRM( 2, 0, to ); + write32(offset); + } + } +} + +void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset) +{ + if ((from&7) == ESP) { + if( offset == 0 ) { + ModRM( 0, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write8(offset); + } + else { + ModRM( 2, to, 0x4 ); + SibSB( 0, 0x4, 0x4 ); + write32(offset); + } + } + else { + if( offset == 0 ) { + ModRM( 0, to, from ); + } + else if( offset < 128 && offset >= -128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } + } +} + +// This function is just for rec debugging purposes +void CheckX86Ptr( void ) +{ +} + +void write64( u64 val ) +{ +#ifdef _DEBUG + CheckX86Ptr( ); +#endif + + *(u64*)x86Ptr = val; + x86Ptr += 8; +} + +void ModRM( int mod, int rm, int reg ) +{ + write8( ( mod << 6 ) | ( (rm & 7) << 3 ) | ( reg & 7 ) ); +} + +void SibSB( int ss, int rm, int index ) +{ + write8( ( ss << 6 ) | ( rm << 3 ) | ( index ) ); +} + +void SET8R( int cc, int to ) +{ + RexB(0, to); + write8( 0x0F ); + write8( cc ); + write8( 0xC0 | ( to ) ); +} + +u8* J8Rel( int cc, int to ) +{ + write8( cc ); + write8( to ); + return x86Ptr - 1; +} + +u16* J16Rel( int cc, u32 to ) +{ + write16( 0x0F66 ); + write8( cc ); + write16( to ); + return (u16*)( x86Ptr - 2 ); +} + +u32* J32Rel( int cc, u32 to ) +{ + write8( 0x0F ); + write8( cc ); + write32( to ); + return (u32*)( x86Ptr - 4 ); +} + +void CMOV32RtoR( int cc, int to, int from ) +{ + RexRB(0,to, from); + write8( 0x0F ); + write8( cc ); + ModRM( 3, to, from ); +} + +void CMOV32MtoR( int cc, int to, uptr from ) +{ + RexR(0, to); + write8( 0x0F ); + write8( cc ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////////////////////// +void x86SetPtr( char* ptr ) +{ + x86Ptr = ptr; +} + +//////////////////////////////////////////////////// +void x86Shutdown( void ) +{ +} + +//////////////////////////////////////////////////// +void x86SetJ8( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - (s8*)j8 ) - 1; + + if ( jump > 0x7f ) { + assert(0); + SysPrintf( "j8 greater than 0x7f!!\n" ); + } + + if( ((uptr)x86Ptr&0xf) > 4 ) { + + uptr newjump = jump + 16-((uptr)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +void x86SetJ16( u16 *j16 ) +{ + // doesn't work + u32 jump = ( x86Ptr - (s8*)j16 ) - 2; + + if ( jump > 0x7fff ) { + assert(0); + SysPrintf( "j16 greater than 0x7fff!!\n" ); + } + *j16 = (u16)jump; +} + +void x86SetJ16A( u16 *j16 ) +{ + if( ((uptr)x86Ptr&0xf) > 4 ) { + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + x86SetJ16(j16); +} + +//////////////////////////////////////////////////// +void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (s8*)j32 ) - 4; +} + +void x86SetJ32A( u32* j32 ) +{ + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + x86SetJ32(j32); +} + +//////////////////////////////////////////////////// +void x86Align( int bytes ) +{ + // fordward align + x86Ptr = (s8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) ); +} + +/********************/ +/* IX86 intructions */ +/********************/ + +void STC( void ) +{ + write8( 0xF9 ); +} + +void CLC( void ) +{ + write8( 0xF8 ); +} + +//////////////////////////////////// +// mov instructions / +//////////////////////////////////// + +/* mov r64 to r64 */ +void MOV64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r64 to m64 */ +void MOV64RtoM( uptr to, x86IntRegType from ) +{ + RexR(1, from); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( (u32)MEMADDR(to, 4) ); +} + +/* mov m64 to r64 */ +void MOV64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( (u32)MEMADDR(from, 4) ); +} + +/* mov imm32 to m64 */ +void MOV64I32toM(uptr to, u32 from ) +{ + Rex(1, 0, 0, 0); + write8( 0xC7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// mov imm64 to r64 +void MOV64ItoR( x86IntRegType to, u64 from) +{ + RexB(1, to); + write8( 0xB8 | (to & 0x7) ); + write64( from ); +} + +/* mov imm32 to r64 */ +void MOV64I32toR( x86IntRegType to, s32 from ) +{ + RexB(1, to); + write8( 0xC7 ); + ModRM( 0, 0, to ); + write32( from ); +} + +// mov imm64 to [r64+off] +void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset) +{ + RexB(1,to); + write8( 0xC7 ); + WriteRmOffset(to, offset); + write32(from); +} + +// mov [r64+offset] to r64 +void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1, to, from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, offset); +} + +/* mov [r64][r64*scale] to r64 */ +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(1, to, from2, from); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +/* mov r64 to [r64+offset] */ +void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset ) +{ + RexRB(1,from,to); + write8( 0x89 ); + WriteRmOffsetFrom(from, to, offset); +} + +/* mov r64 to [r64][r64*scale] */ +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(1, to, from2, from); + write8( 0x89 ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + + +/* mov r32 to r32 */ +void MOV32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x89 ); + ModRM( 3, from, to ); +} + +/* mov r32 to m32 */ +void MOV32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0, from); + write8( 0x89 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mov m32 to r32 */ +void MOV32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0, to); + write8( 0x8B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* mov [r32] to r32 */ +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ) { + RexRB(0, to, from); + write8(0x8B); + WriteRmOffsetFrom(to, from, 0); +} + +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) { + RexRB(0, to, from); + write8( 0x8B ); + WriteRmOffsetFrom(to, from, offset); +} + +/* mov [r32+r32*scale] to r32 */ +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { + RexRXB(0,to,from2,from); + write8( 0x8B ); + ModRM( 0, to, 0x4 ); + SibSB(scale, from2, from ); +} + +// mov r32 to [r32<> 3); + if ( to == EAX) { + write8( 0x05 ); + } else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add m64 to r64 */ +void ADD64MtoR( x86IntRegType to, uptr from ) +{ + Rex(1, to >> 3, 0, 0); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* add r64 to r64 */ +void ADD64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add imm32 to r32 */ +void ADD32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0, to); + if ( to == EAX) { + write8( 0x05 ); + } + else { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +/* add imm32 to m32 */ +void ADD32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +// add imm32 to [r32+off] +void ADD32ItoRmOffset( x86IntRegType to, u32 from, int offset) +{ + RexB(0,to); + write8( 0x81 ); + WriteRmOffset(to,offset); + write32(from); +} + +/* add r32 to r32 */ +void ADD32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x01 ); + ModRM( 3, from, to ); +} + +/* add r32 to m32 */ +void ADD32RtoM(uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m32 to r32 */ +void ADD32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add r16 to r16 +void ADD16RtoR( x86IntRegType to , x86IntRegType from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x03 ); + ModRM( 3, to, from ); +} + +/* add imm16 to r16 */ +void ADD16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + RexB(0,to); + if ( to == EAX) + { + write8( 0x05 ); + } + else + { + write8( 0x81 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +/* add imm16 to m16 */ +void ADD16ItoM( uptr to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* add r16 to m16 */ +void ADD16RtoM(uptr to, x86IntRegType from ) +{ + write8( 0x66 ); + RexR(0,from); + write8( 0x01 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* add m16 to r16 */ +void ADD16MtoR( x86IntRegType to, uptr from ) +{ + write8( 0x66 ); + RexR(0,to); + write8( 0x03 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// add m8 to r8 +void ADD8MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x02 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* adc imm32 to r32 */ +void ADC32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x15 ); + } + else { + write8( 0x81 ); + ModRM( 3, 2, to ); + } + write32( from ); +} + +/* adc imm32 to m32 */ +void ADC32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* adc r32 to r32 */ +void ADC32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x11 ); + ModRM( 3, from, to ); +} + +/* adc m32 to r32 */ +void ADC32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x13 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// adc r32 to m32 +void ADC32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x11 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r32 */ +void INC32R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x40 + to ); +} + +/* inc m32 */ +void INC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* inc r16 */ +void INC16R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x66 ); + write8( 0x40 + to ); +} + +/* inc m16 */ +void INC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 4) ); +} + + +/* sub imm32 to r64 */ +void SUB64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x2D ); + } + else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub r64 to r64 */ +void SUB64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m64 to r64 */ +void SUB64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sub imm32 to r32 */ +void SUB32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x2D ); + } + else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write32( from ); +} + +/* sub imm32 to m32 */ +void SUB32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sub r32 to r32 */ +void SUB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0, from, to); + write8( 0x29 ); + ModRM( 3, from, to ); +} + +/* sub m32 to r32 */ +void SUB32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// sub r32 to m32 +void SUB32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x29 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// sub r16 to r16 +void SUB16RtoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x2b ); + ModRM( 3, to, from ); +} + +/* sub imm16 to r16 */ +void SUB16ItoR( x86IntRegType to, u16 from ) { + write8( 0x66 ); + RexB(0,to); + if ( to == EAX ) { + write8( 0x2D ); + } else { + write8( 0x81 ); + ModRM( 3, 5, to ); + } + write16( from ); +} + +/* sub imm16 to m16 */ +void SUB16ItoM( uptr to, u16 from ) { + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* sub m16 to r16 */ +void SUB16MtoR( x86IntRegType to, uptr from ) { + write8( 0x66 ); + RexR(0,to); + write8( 0x2B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r64 to r64 */ +void SBB64RtoR( x86IntRegType to, x86IntRegType from ) { + RexRB(1, from,to); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb imm32 to r32 */ +void SBB32ItoR( x86IntRegType to, u32 from ) { + RexB(0,to); + if ( to == EAX ) { + write8( 0x1D ); + } else { + write8( 0x81 ); + ModRM( 3, 3, to ); + } + write32( from ); +} + +/* sbb imm32 to m32 */ +void SBB32ItoM( uptr to, u32 from ) { + write8( 0x81 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* sbb r32 to r32 */ +void SBB32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x19 ); + ModRM( 3, from, to ); +} + +/* sbb m32 to r32 */ +void SBB32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x1B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* sbb r32 to m32 */ +void SBB32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x19 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* dec r32 */ +void DEC32R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x48 + to ); +} + +/* dec m32 */ +void DEC32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* dec r16 */ +void DEC16R( x86IntRegType to ) +{ + X86_64ASSERT(); + write8( 0x66 ); + write8( 0x48 + to ); +} + +/* dec m16 */ +void DEC16M( u32 to ) +{ + write8( 0x66 ); + write8( 0xFF ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* mul eax by r32 to edx:eax */ +void MUL32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 4, from ); +} + +/* imul eax by r32 to edx:eax */ +void IMUL32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 5, from ); +} + +/* mul eax by m32 to edx:eax */ +void MUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul eax by m32 to edx:eax */ +void IMUL32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* imul r32 by r32 to r32 */ +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write16( 0xAF0F ); + ModRM( 3, to, from ); +} + +/* div eax by r32 to edx:eax */ +void DIV32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 6, from ); +} + +/* idiv eax by r32 to edx:eax */ +void IDIV32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 7, from ); +} + +/* div eax by m32 to edx:eax */ +void DIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* idiv eax by m32 to edx:eax */ +void IDIV32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +//////////////////////////////////// +// shifting instructions / +//////////////////////////////////// + +/* shl imm8 to r64 */ +void SHL64ItoR( x86IntRegType to, u8 from ) +{ + RexB(1, to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 4, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl cl to r64 */ +void SHL64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +/* shr imm8 to r64 */ +void SHR64ItoR( x86IntRegType to, u8 from ) +{ + RexB(1,to); + if ( from == 1 ) { + write8( 0xD1 ); + ModRM( 3, 5, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); +} + +/* shr cl to r64 */ +void SHR64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +/* shl imm8 to r32 */ +void SHL32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0, to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shl imm8 to m32 */ +void SHL32ItoM( uptr to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); + } +} + +/* shl cl to r32 */ +void SHL32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 4, to ); +} + +// shl imm8 to r16 +void SHL16ItoR( x86IntRegType to, u8 from ) +{ + write8(0x66); + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC1 ); + ModRM( 3, 4, to ); + write8( from ); +} + +// shl imm8 to r8 +void SHL8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE0 | (to & 0x7) ); + return; + } + write8( 0xC0 ); + ModRM( 3, 4, to ); + write8( from ); +} + +/* shr imm8 to r32 */ +void SHR32ItoR( x86IntRegType to, u8 from ) { + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC1 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* shr imm8 to m32 */ +void SHR32ItoM( uptr to, u8 from ) +{ + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 4) ); + } + else + { + write8( 0xC1 ); + ModRM( 0, 5, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); + } +} + +/* shr cl to r32 */ +void SHR32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 5, to ); +} + +// shr imm8 to r8 +void SHR8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD0 ); + write8( 0xE8 | (to & 0x7) ); + } + else + { + write8( 0xC0 ); + ModRM( 3, 5, to ); + write8( from ); + } +} + +/* sar imm8 to r64 */ +void SAR64ItoR( x86IntRegType to, u8 from ) +{ + RexB(1,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar cl to r64 */ +void SAR64CLtoR( x86IntRegType to ) +{ + RexB(1, to); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +/* sar imm8 to r32 */ +void SAR32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +/* sar imm8 to m32 */ +void SAR32ItoM( uptr to, u8 from ) +{ + write8( 0xC1 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* sar cl to r32 */ +void SAR32CLtoR( x86IntRegType to ) +{ + RexB(0,to); + write8( 0xD3 ); + ModRM( 3, 7, to ); +} + +// sar imm8 to r16 +void SAR16ItoR( x86IntRegType to, u8 from ) +{ + write8(0x66); + RexB(0,to); + if ( from == 1 ) + { + write8( 0xD1 ); + ModRM( 3, 7, to ); + return; + } + write8( 0xC1 ); + ModRM( 3, 7, to ); + write8( from ); +} + +void ROR32ItoR( x86IntRegType to,u8 from ) +{ + RexB(0,to); + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xc8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xc8 | to ); + write8( from ); + } +} + +void RCR32ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( from == 1 ) { + write8( 0xd1 ); + write8( 0xd8 | to ); + } + else + { + write8( 0xc1 ); + write8( 0xd8 | to ); + write8( from ); + } +} + +// shld imm8 to r32 +void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + RexRB(0,from,to); + write8( 0x0F ); + write8( 0xA4 ); + ModRM( 3, from, to ); + write8( shift ); +} + +// shrd imm8 to r32 +void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + RexRB(0,from,to); + write8( 0x0F ); + write8( 0xAC ); + ModRM( 3, from, to ); + write8( shift ); +} + +//////////////////////////////////// +// logical instructions / +//////////////////////////////////// + +/* or imm32 to r32 */ +void OR64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x0D ); + } else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or m64 to r64 */ +void OR64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* or r64 to r64 */ +void OR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +// or r32 to m64 +void OR64RtoM(uptr to, x86IntRegType from ) +{ + RexR(1,from); + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* or imm32 to r32 */ +void OR32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write32( from ); +} + +/* or imm32 to m32 */ +void OR32ItoM(uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* or r32 to r32 */ +void OR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +/* or r32 to m32 */ +void OR32RtoM(uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* or m32 to r32 */ +void OR32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to r16 +void OR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,from,to); + write8( 0x09 ); + ModRM( 3, from, to ); +} + +// or imm16 to r16 +void OR16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x0D ); + } + else { + write8( 0x81 ); + ModRM( 3, 1, to ); + } + write16( from ); +} + +// or imm16 to m316 +void OR16ItoM( uptr to, u16 from ) +{ + write8(0x66); + write8( 0x81 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* or m16 to r16 */ +void OR16MtoR( x86IntRegType to, uptr from ) +{ + write8(0x66); + RexR(0,to); + write8( 0x0B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// or r16 to m16 +void OR16RtoM( uptr to, x86IntRegType from ) +{ + write8(0x66); + RexR(0,from); + write8( 0x09 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or r8 to r8 +void OR8RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x08 ); + ModRM( 3, from, to ); +} + +// or r8 to m8 +void OR8RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x08 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// or imm8 to m8 +void OR8ItoM( uptr to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 1, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +// or m8 to r8 +void OR8MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x0A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor imm32 to r64 */ +void XOR64ItoR( x86IntRegType to, u32 from ) +{ + RexB(1,to); + if ( to == EAX ) { + write8( 0x35 ); + } else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor r64 to r64 */ +void XOR64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor m64 to r64 */ +void XOR64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* xor r64 to m64 */ +void XOR64RtoM( uptr to, x86IntRegType from ) +{ + RexR(1,from); + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* xor imm32 to r32 */ +void XOR32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write32( from ); +} + +/* xor imm32 to m32 */ +void XOR32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* xor r32 to r32 */ +void XOR32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r16 to r16 */ +void XOR16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + RexRB(0,from,to); + write8( 0x31 ); + ModRM( 3, from, to ); +} + +/* xor r32 to m32 */ +void XOR32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* xor m32 to r32 */ +void XOR32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x33 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// xor imm16 to r16 +void XOR16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x35 ); + } + else { + write8( 0x81 ); + ModRM( 3, 6, to ); + } + write16( from ); +} + +// xor r16 to m16 +void XOR16RtoM( uptr to, x86IntRegType from ) +{ + write8(0x66); + RexR(0,from); + write8( 0x31 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and imm32 to r64 */ +void AND64I32toR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and m64 to r64 */ +void AND64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* and r64 to m64 */ +void AND64RtoM( uptr to, x86IntRegType from ) +{ + RexR(1, from); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and r64 to r64 */ +void AND64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1, from, to); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and imm32 to m64 */ +void AND64I32toM( uptr to, u32 from ) +{ + Rex(1,0,0,0); + write8( 0x81 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* and imm32 to r32 */ +void AND32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write32( from ); +} + +/* and sign ext imm8 to r32 */ +void AND32I8toR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 3, 0x4, to ); + write8( from ); +} + +/* and imm32 to m32 */ +void AND32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* and sign ext imm8 to m32 */ +void AND32I8toM( uptr to, u8 from ) +{ + write8( 0x83 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* and r32 to r32 */ +void AND32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x21 ); + ModRM( 3, from, to ); +} + +/* and r32 to m32 */ +void AND32RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m32 to r32 */ +void AND32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// and r16 to r16 +void AND16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,to,from); + write8( 0x23 ); + ModRM( 3, to, from ); +} + +/* and imm16 to r16 */ +void AND16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) { + write8( 0x25 ); + } else { + write8( 0x81 ); + ModRM( 3, 0x4, to ); + } + write16( from ); +} + +/* and imm16 to m16 */ +void AND16ItoM( uptr to, u16 from ) +{ + write8( 0x8166 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* and r16 to m16 */ +void AND16RtoM( uptr to, x86IntRegType from ) +{ + write8( 0x66 ); + RexR(0,from); + write8( 0x21 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m16 to r16 */ +void AND16MtoR( x86IntRegType to, uptr from ) +{ + write8( 0x66 ); + RexR(0,to); + write8( 0x23 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* and imm8 to r8 */ +void AND8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x24 ); + } else { + write8( 0x80 ); + ModRM( 3, 0x4, to ); + } + write8( from ); +} + +/* and imm8 to m8 */ +void AND8ItoM( uptr to, u8 from ) +{ + write8( 0x80 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +// and r8 to r8 +void AND8RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,to,from); + write8( 0x22 ); + ModRM( 3, to, from ); +} + +/* and r8 to m8 */ +void AND8RtoM( uptr to, x86IntRegType from ) +{ + RexR(0,from); + write8( 0x20 ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* and m8 to r8 */ +void AND8MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x22 ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* not r64 */ +void NOT64R( x86IntRegType from ) +{ + RexB(1, from); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +/* not r32 */ +void NOT32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 2, from ); +} + +// not m32 +void NOT32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r64 */ +void NEG64R( x86IntRegType from ) +{ + RexB(1, from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +/* neg r32 */ +void NEG32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +void NEG32M( u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 3, DISP32 ); + write32( MEMADDR(from, 4)); +} + +/* neg r16 */ +void NEG16R( x86IntRegType from ) +{ + write8( 0x66 ); + RexB(0,from); + write8( 0xF7 ); + ModRM( 3, 3, from ); +} + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +u8* JMP( uptr to ) { + uptr jump = ( x86Ptr - (s8*)to ) - 1; + + if ( jump > 0x7f ) { + assert( to <= 0xffffffff ); + return (u8*)JMP32( to ); + } else { + return (u8*)JMP8( to ); + } +} + +/* jmp rel8 */ +u8* JMP8( u8 to ) +{ + write8( 0xEB ); + write8( to ); + return x86Ptr - 1; +} + +/* jmp rel32 */ +u32* JMP32( uptr to ) +{ + assert( (sptr)to <= 0x7fffffff && (sptr)to >= -0x7fffffff ); + write8( 0xE9 ); + write32( to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32/r64 */ +void JMPR( x86IntRegType to ) +{ + RexB(0, to); + write8( 0xFF ); + ModRM( 3, 4, to ); +} + +// jmp m32 +void JMP32M( uptr to ) +{ + write8( 0xFF ); + ModRM( 0, 4, DISP32 ); + write32( MEMADDR(to, 4)); +} + +/* jp rel8 */ +u8* JP8( u8 to ) { + return J8Rel( 0x7A, to ); +} + +/* jnp rel8 */ +u8* JNP8( u8 to ) { + return J8Rel( 0x7B, to ); +} + +/* je rel8 */ +u8* JE8( u8 to ) { + return J8Rel( 0x74, to ); +} + +/* jz rel8 */ +u8* JZ8( u8 to ) +{ + return J8Rel( 0x74, to ); +} + +/* js rel8 */ +u8* JS8( u8 to ) +{ + return J8Rel( 0x78, to ); +} + +/* jns rel8 */ +u8* JNS8( u8 to ) +{ + return J8Rel( 0x79, to ); +} + +/* jg rel8 */ +u8* JG8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jge rel8 */ +u8* JGE8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jl rel8 */ +u8* JL8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* ja rel8 */ +u8* JA8( u8 to ) +{ + return J8Rel( 0x77, to ); +} + +u8* JAE8( u8 to ) +{ + return J8Rel( 0x73, to ); +} + +/* jb rel8 */ +u8* JB8( u8 to ) +{ + return J8Rel( 0x72, to ); +} + +/* jbe rel8 */ +u8* JBE8( u8 to ) +{ + return J8Rel( 0x76, to ); +} + +/* jle rel8 */ +u8* JLE8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jne rel8 */ +u8* JNE8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jnz rel8 */ +u8* JNZ8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jng rel8 */ +u8* JNG8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jnge rel8 */ +u8* JNGE8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* jnl rel8 */ +u8* JNL8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jnle rel8 */ +u8* JNLE8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jo rel8 */ +u8* JO8( u8 to ) +{ + return J8Rel( 0x70, to ); +} + +/* jno rel8 */ +u8* JNO8( u8 to ) +{ + return J8Rel( 0x71, to ); +} + +// jb rel8 +u16* JB16( u16 to ) +{ + return J16Rel( 0x82, to ); +} + +// jb rel32 +u32* JB32( u32 to ) +{ + return J32Rel( 0x82, to ); +} + +/* je rel32 */ +u32* JE32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jz rel32 */ +u32* JZ32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jg rel32 */ +u32* JG32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jge rel32 */ +u32* JGE32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jl rel32 */ +u32* JL32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jle rel32 */ +u32* JLE32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jae rel32 */ +u32* JAE32( u32 to ) +{ + return J32Rel( 0x83, to ); +} + +/* jne rel32 */ +u32* JNE32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jnz rel32 */ +u32* JNZ32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jng rel32 */ +u32* JNG32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jnge rel32 */ +u32* JNGE32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jnl rel32 */ +u32* JNL32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jnle rel32 */ +u32* JNLE32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jo rel32 */ +u32* JO32( u32 to ) +{ + return J32Rel( 0x80, to ); +} + +/* jno rel32 */ +u32* JNO32( u32 to ) +{ + return J32Rel( 0x81, to ); +} + +// js rel32 +u32* JS32( u32 to ) +{ + return J32Rel( 0x88, to ); +} + + +/* call func */ +void CALLFunc( uptr func ) +{ + func -= ( (uptr)x86Ptr + 5 ); + assert( (sptr)func <= 0x7fffffff && (sptr)func >= -0x7fffffff ); + CALL32(func); +} + +/* call rel32 */ +void CALL32( u32 to ) +{ + write8( 0xE8 ); + write32( to ); +} + +/* call r32 */ +void CALL32R( x86IntRegType to ) +{ + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call r64 */ +void CALL64R( x86IntRegType to ) +{ + RexB(0, to); + write8( 0xFF ); + ModRM( 3, 2, to ); +} + +/* call m32 */ +void CALL32M( u32 to ) +{ + write8( 0xFF ); + ModRM( 0, 2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +//////////////////////////////////// +// misc instructions / +//////////////////////////////////// + +/* cmp imm32 to r64 */ +void CMP64I32toR( x86IntRegType to, u32 from ) +{ + RexB(1, to); + if ( to == EAX ) { + write8( 0x3D ); + } + else { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp m64 to r64 */ +void CMP64MtoR( x86IntRegType to, uptr from ) +{ + RexR(1, to); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp r64 to r64 +void CMP64RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(1,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp imm32 to r32 */ +void CMP32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) { + write8( 0x3D ); + } + else { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write32( from ); +} + +/* cmp imm32 to m32 */ +void CMP32ItoM( uptr to, u32 from ) +{ + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* cmp r32 to r32 */ +void CMP32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m32 to r32 */ +void CMP32MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to [r32] +void CMP32I8toRm( x86IntRegType to, u8 from) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 0, 7, to ); + write8(from); +} + +// cmp imm32 to [r32+off] +void CMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) +{ + RexB(0,to); + write8( 0x83 ); + ModRM( 1, 7, to ); + write8(off); + write8(from); +} + +// cmp imm8 to [r32] +void CMP32I8toM( uptr to, u8 from) +{ + write8( 0x83 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* cmp imm16 to r16 */ +void CMP16ItoR( x86IntRegType to, u16 from ) +{ + write8( 0x66 ); + RexB(0,to); + if ( to == EAX ) + { + write8( 0x3D ); + } + else + { + write8( 0x81 ); + ModRM( 3, 7, to ); + } + write16( from ); +} + +/* cmp imm16 to m16 */ +void CMP16ItoM( uptr to, u16 from ) +{ + write8( 0x66 ); + write8( 0x81 ); + ModRM( 0, 7, DISP32 ); + write32( MEMADDR(to, 6) ); + write16( from ); +} + +/* cmp r16 to r16 */ +void CMP16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8( 0x66 ); + RexRB(0,from,to); + write8( 0x39 ); + ModRM( 3, from, to ); +} + +/* cmp m16 to r16 */ +void CMP16MtoR( x86IntRegType to, uptr from ) +{ + write8( 0x66 ); + RexR(0,to); + write8( 0x3B ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// cmp imm8 to r8 +void CMP8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0x3C ); + } + else + { + write8( 0x80 ); + ModRM( 3, 7, to ); + } + write8( from ); +} + +// cmp m8 to r8 +void CMP8MtoR( x86IntRegType to, uptr from ) +{ + RexR(0,to); + write8( 0x3A ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* test imm32 to r32 */ +void TEST32ItoR( x86IntRegType to, u32 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write32( from ); +} + +void TEST32ItoM( uptr to, u32 from ) +{ + write8( 0xF7 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 8) ); + write32( from ); +} + +/* test r32 to r32 */ +void TEST32RtoR( x86IntRegType to, x86IntRegType from ) +{ + RexRB(0,from,to); + write8( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm32 to [r32] +void TEST32ItoRm( x86IntRegType to, u32 from ) +{ + RexB(0,to); + write8( 0xF7 ); + ModRM( 0, 0, to ); + write32(from); +} + +// test imm16 to r16 +void TEST16ItoR( x86IntRegType to, u16 from ) +{ + write8(0x66); + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA9 ); + } + else + { + write8( 0xF7 ); + ModRM( 3, 0, to ); + } + write16( from ); +} + +// test r16 to r16 +void TEST16RtoR( x86IntRegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0,from,to); + write16( 0x85 ); + ModRM( 3, from, to ); +} + +// test imm8 to r8 +void TEST8ItoR( x86IntRegType to, u8 from ) +{ + RexB(0,to); + if ( to == EAX ) + { + write8( 0xA8 ); + } + else + { + write8( 0xF6 ); + ModRM( 3, 0, to ); + } + write8( from ); +} + +// test imm8 to r8 +void TEST8ItoM( uptr to, u8 from ) +{ + write8( 0xF6 ); + ModRM( 0, 0, DISP32 ); + write32( MEMADDR(to, 5) ); + write8( from ); +} + +/* sets r8 */ +void SETS8R( x86IntRegType to ) +{ + SET8R( 0x98, to ); +} + +/* setl r8 */ +void SETL8R( x86IntRegType to ) +{ + SET8R( 0x9C, to ); +} + +// setge r8 +void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); } +// setg r8 +void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); } +// seta r8 +void SETA8R( x86IntRegType to ) { SET8R(0x97, to); } +// setae r8 +void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); } +/* setb r8 */ +void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); } +/* setb r8 */ +void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); } +// setz r8 +void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); } +// sete r8 +void SETE8R( x86IntRegType to ) { SET8R(0x94, to); } + +/* push imm32 */ +void PUSH32I( u32 from ) +{ + X86_64ASSERT(); + write8( 0x68 ); + write32( from ); +} + +#ifdef __x86_64__ + +/* push r32 */ +void PUSH32R( x86IntRegType from ) +{ + RexB(0,from); + write8( 0x51 | from ); +} + +/* push m32 */ +void PUSH32M( uptr from ) +{ + write8( 0xFF ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pop r64 */ +void POP64R( x86IntRegType from ) { + RexB(0,from); + write8( 0x59 | from ); +} + +void PUSHR(x86IntRegType from) { PUSH32R(from); } +void POPR(x86IntRegType from) { POP64R(from); } + +#else + +/* push r32 */ +void PUSH32R( x86IntRegType from ) { write8( 0x50 | from ); } + +/* push m32 */ +void PUSH32M( u32 from ) +{ + write8( 0xFF ); + ModRM( 0, 6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pop r32 */ +void POP32R( x86IntRegType from ) { write8( 0x58 | from ); } + +/* pushad */ +void PUSHA32( void ) { write8( 0x60 ); } + +/* popad */ +void POPA32( void ) { write8( 0x61 ); } + +void PUSHR(x86IntRegType from) { PUSH32R(from); } +void POPR(x86IntRegType from) { POP32R(from); } + +#endif + + +/* pushfd */ +void PUSHFD( void ) { write8( 0x9C ); } +/* popfd */ +void POPFD( void ) { write8( 0x9D ); } + +void RET( void ) { write8( 0xC3 ); } +void RET2( void ) { write16( 0xc3f3 ); } + +void CBW( void ) { write16( 0x9866 ); } +void CWD( void ) { write8( 0x98 ); } +void CDQ( void ) { write8( 0x99 ); } +void CWDE() { write8(0x98); } + +#ifdef __x86_64__ +void CDQE( void ) { RexR(1,0); write8( 0x98 ); } +#endif + +void LAHF() { write8(0x9f); } +void SAHF() { write8(0x9e); } + +void BT32ItoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0xBA0F ); + write8( 0xE0 | to ); + write8( from ); +} + +void BSRRtoR(x86IntRegType to, x86IntRegType from) +{ + write16( 0xBD0F ); + ModRM( 3, from, to ); +} + +void BSWAP32R( x86IntRegType to ) +{ + write8( 0x0F ); + write8( 0xC8 + to ); +} + +// to = from + offset +void LEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) +{ + write8(0x66); + LEA32RtoR(to, from, offset); +} + +void LEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset) +{ + RexRB(0,to,from); + write8(0x8d); + + if( (from&7) == ESP ) { + if( offset == 0 ) { + ModRM(1, to, from); + write8(0x24); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(0x24); + write8(offset); + } + else { + ModRM(2, to, from); + write8(0x24); + write32(offset); + } + } + else { + if( offset == 0 && from != EBP && from!=ESP ) { + ModRM(0, to, from); + } + else if( offset < 128 ) { + ModRM(1, to, from); + write8(offset); + } + else { + ModRM(2, to, from); + write32(offset); + } + } +} + +// to = from0 + from1 +void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + write8(0x66); + LEA32RRtoR(to, from0, from1); +} + +void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + RexRXB(0, to, from0, from1); + write8(0x8d); + if( (from0&7) == EBP || (from1&7) == EBP ) { + + if( (from0&7) == EBP ) SWAP(from0, from1); + ModRM(1, to, 4); + ModRM(0, from0, from1); + write8(0); + } + else { + ModRM(0, to, 4); + ModRM(0, from0, from1); + } +} + +// to = from << scale (max is 3) +void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + write8(0x66); + LEA32RStoR(to, from, scale); +} + +void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + if( to == from ) { + SHL32ItoR(to, scale); + return; + } + + if( from != ESP ) { + RexRXB(0,to,from,0); + write8(0x8d); + ModRM(0, to, 4); + ModRM(scale, from, 5); + write32(0); + } + else { + assert( to != ESP ); + MOV32RtoR(to, from); + LEA32RStoR(to, to, scale); + } +} + +#endif diff --git a/pcsx2/x86/ix86/ix86.h b/pcsx2/x86/ix86/ix86.h new file mode 100644 index 0000000..b52c858 --- /dev/null +++ b/pcsx2/x86/ix86/ix86.h @@ -0,0 +1,1768 @@ +/* + * ix86 definitions v0.6.2 + * Authors: linuzappz + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "PS2Etypes.h" // Basic types header + +#ifdef __x86_64__ +#define XMMREGS 16 +#define X86REGS 16 +#else +#define XMMREGS 8 +#define X86REGS 8 +#endif + +#define MMXREGS 8 + +#define SIB 4 +#define DISP32 5 + +// general types +typedef int x86IntRegType; +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 + +#ifdef __x86_64__ +#define RAX 0 +#define RBX 3 +#define RCX 1 +#define RDX 2 +#define RSI 6 +#define RDI 7 +#define RBP 5 +#define RSP 4 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define X86_TEMP RAX // don't allocate anything + +#ifdef _MSC_VER +extern x86IntRegType g_x86savedregs[8]; +extern x86IntRegType g_x86tempregs[6]; +#else +extern x86IntRegType g_x86savedregs[6]; +extern x86IntRegType g_x86tempregs[8]; +#endif + +extern x86IntRegType g_x86allregs[14]; // all registers that can be used by the recs +extern x86IntRegType g_x868bitregs[11]; +extern x86IntRegType g_x86non8bitregs[3]; + +#ifdef _MSC_VER +#define X86ARG1 RCX +#define X86ARG2 RDX +#define X86ARG3 R8 +#define X86ARG4 R9 +#else +#define X86ARG1 RDI +#define X86ARG2 RSI +#define X86ARG3 RDX +#define X86ARG4 RCX +#endif + +#else + +#define X86ARG1 EAX +#define X86ARG2 ECX +#define X86ARG3 EDX +#define X86ARG4 EBX + +#endif // __x86_64__ + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; + +typedef enum +{ + XMMT_INT = 0, // integer (sse2 only) + XMMT_FPS = 1, // floating point + //XMMT_FPD = 3, // double +} XMMSSEType; + +extern XMMSSEType g_xmmtypes[XMMREGS]; + +void cpudetectInit( void );//this is all that needs to be called and will fill up the below structs + +//cpu capabilities structure +typedef struct { + u32 hasFloatingPointUnit; + u32 hasVirtual8086ModeEnhancements; + u32 hasDebuggingExtensions; + u32 hasPageSizeExtensions; + u32 hasTimeStampCounter; + u32 hasModelSpecificRegisters; + u32 hasPhysicalAddressExtension; + u32 hasCOMPXCHG8BInstruction; + u32 hasAdvancedProgrammableInterruptController; + u32 hasSEPFastSystemCall; + u32 hasMemoryTypeRangeRegisters; + u32 hasPTEGlobalFlag; + u32 hasMachineCheckArchitecture; + u32 hasConditionalMoveAndCompareInstructions; + u32 hasFGPageAttributeTable; + u32 has36bitPageSizeExtension; + u32 hasProcessorSerialNumber; + u32 hasCFLUSHInstruction; + u32 hasDebugStore; + u32 hasACPIThermalMonitorAndClockControl; + u32 hasMultimediaExtensions; + u32 hasFastStreamingSIMDExtensionsSaveRestore; + u32 hasStreamingSIMDExtensions; + u32 hasStreamingSIMD2Extensions; + u32 hasSelfSnoop; + u32 hasHyperThreading; + u32 hasThermalMonitor; + u32 hasIntel64BitArchitecture; + u32 hasStreamingSIMD3Extensions; + //that is only for AMDs + u32 hasMultimediaExtensionsExt; + u32 hasAMD64BitArchitecture; + u32 has3DNOWInstructionExtensionsExt; + u32 has3DNOWInstructionExtensions; +} CAPABILITIES; + +extern CAPABILITIES cpucaps; + +typedef struct { + + u32 x86Family; // Processor Family + u32 x86Model; // Processor Model + u32 x86PType; // Processor Type + u32 x86StepID; // Stepping ID + u32 x86Flags; // Feature Flags + u32 x86EFlags; // Extended Feature Flags + //all the above returns hex values + s8 x86ID[16]; // Vendor ID //the vendor creator (in %s) + s8 x86Type[20]; //cpu type in char format //the cpu type (in %s) + s8 x86Fam[50]; // family in char format //the original cpu name string (in %s) + u32 cpuspeed; // speed of cpu //this will give cpu speed (in %d) +} CPUINFO; + +extern CPUINFO cpuinfo; + +extern s8 *x86Ptr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + + +#ifdef __x86_64__ +#define X86_64ASSERT() assert(0) +#define MEMADDR(addr, oplen) ((addr) - ((u64)x86Ptr + ((u64)oplen))) +#else +#define X86_64ASSERT() +#define MEMADDR(addr, oplen) (addr) +#endif + +#ifdef __x86_64__ +#define Rex( w, r, x, b ) write8( 0x40 | ((w) << 3) | ((r) << 2) | ((x) << 1) | (b) ); +#define RexR(w, reg) if( w||(reg)>=8 ) { Rex(w, (reg)>=8, 0, 0); } +#define RexB(w, base) if( w||(base)>=8 ) { Rex(w, 0, 0, (base)>=8); } +#define RexRB(w, reg, base) if( w || (reg) >= 8 || (base)>=8 ) { Rex(w, (reg)>=8, 0, (base)>=8); } +#define RexRXB(w, reg, index, base) if( w||(reg) >= 8 || (index) >= 8 || (base) >= 8 ) { \ + Rex(w, (reg)>=8, (index)>=8, (base)>=8); \ + } +#else +#define Rex(w,r,x,b) assert(0); +#define RexR(w, reg) if( w||(reg)>=8 ) assert(0); +#define RexB(w, base) if( w||(base)>=8 ) assert(0); +#define RexRB(w, reg, base) if( w||(reg) >= 8 || (base)>=8 ) assert(0); +#define RexRXB(w, reg, index, base) if( w||(reg) >= 8 || (index) >= 8 || (base) >= 8 ) assert(0); +#endif + +void write8( int val ); +void write16( int val ); +void write32( u32 val ); +void write64( u64 val ); + + +void x86SetPtr( char *ptr ); +void x86Shutdown( void ); + +void x86SetJ8( u8 *j8 ); +void x86SetJ8A( u8 *j8 ); +void x86SetJ16( u16 *j16 ); +void x86SetJ16A( u16 *j16 ); +void x86SetJ32( u32 *j32 ); +void x86SetJ32A( u32 *j32 ); + +void x86Align( int bytes ); +u64 GetCPUTick( void ); + +// General Helper functions +void ModRM( int mod, int rm, int reg ); +void SibSB( int ss, int rm, int index ); +void SET8R( int cc, int to ); +u8* J8Rel( int cc, int to ); +u32* J32Rel( int cc, u32 to ); +void CMOV32RtoR( int cc, int to, int from ); +void CMOV32MtoR( int cc, int to, uptr from ); + +//****************** +// IX86 intructions +//****************** + +// +// * scale values: +// * 0 - *1 +// * 1 - *2 +// * 2 - *4 +// * 3 - *8 +// + +void STC( void ); +void CLC( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r64 to r64 +void MOV64RtoR( x86IntRegType to, x86IntRegType from ); +// mov r64 to m64 +void MOV64RtoM( uptr to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, uptr from ); +// mov sign ext imm32 to m64 +void MOV64I32toM( uptr to, u32 from ); +// mov sign ext imm32 to r64 +void MOV64I32toR( x86IntRegType to, s32 from); +// mov imm64 to r64 +void MOV64ItoR( x86IntRegType to, u64 from); +// mov imm64 to [r64+off] +void MOV64ItoRmOffset( x86IntRegType to, u32 from, int offset); +// mov [r64+offset] to r64 +void MOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset ); +// mov [r64][r64*scale] to r64 +void MOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); +// mov r64 to [r64+offset] +void MOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset ); +// mov r64 to [r64][r64*scale] +void MOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( uptr to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, uptr from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +void MOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ); +// mov [r32][r32< subtract ST(0) from ST(1), store in ST(1) and POP stack +void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +void FDIV320toR( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src), pop stack, store in ST(src) +void FDIV320toRP( x86IntRegType src ); + +// fadd m32 to fpu reg stack +void FADD32( u32 from ); +// fsub m32 to fpu reg stack +void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +void FDIV32( u32 from ); +// fcomi st, st( i) +void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +void FCOM32( u32 from ); +// fabs fpu reg stack +void FABS( void ); +// fsqrt fpu reg stack +void FSQRT( void ); +// ftan fpu reg stack +void FPATAN( void ); +// fsin fpu reg stack +void FSIN( void ); +// fchs fpu reg stack +void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +void FCMOVNU32( x86IntRegType from ); +void FCOMP32( u32 from ); +void FNSTSWtoAX( void ); + +// probably a little extreme here, but x86-64 should NOT use MMX +#ifdef __x86_64__ + +#define MMXONLY(code) + +#else + +#define MMXONLY(code) code + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, uptr from ); +// movq r64 to m64 +void MOVQRtoM( uptr to, x86MMXRegType from ); + +// pand r64 to r64 +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +void PANDMtoR( x86MMXRegType to, uptr from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, uptr from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, uptr from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, uptr from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, uptr from ); +// psllq imm8 to r64 +void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +void PSRLQMtoR( x86MMXRegType to, uptr from ); +// psrlq imm8 to r64 +void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +void PADDUSBMtoR( x86MMXRegType to, uptr from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, uptr from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, uptr from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, uptr from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, uptr from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, uptr from ); +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDMtoR( x86MMXRegType to, uptr from ); + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, uptr from ); +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, uptr from ); +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDMtoR( x86MMXRegType to, uptr from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDMtoR( x86MMXRegType to, uptr from ); +void PSRLWItoR( x86MMXRegType to, u8 from ); +void PSRLDItoR( x86MMXRegType to, u8 from ); +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSLLWItoR( x86MMXRegType to, u8 from ); +void PSLLDItoR( x86MMXRegType to, u8 from ); +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSRAWItoR( x86MMXRegType to, u8 from ); +void PSRADItoR( x86MMXRegType to, u8 from ); +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQMtoR( x86MMXRegType to, uptr from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKHDQMtoR( x86MMXRegType to, uptr from ); +void MOVQ64ItoR( x86MMXRegType reg, u64 i ); //Prototype.Todo add all consts to end of block.not after jr $+8 +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void MOVDMtoMMX( x86MMXRegType to, uptr from ); +void MOVDMMXtoM( uptr to, x86MMXRegType from ); +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ); +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ); +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ); +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ); +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8); +void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8); +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from); + +// emms +void EMMS( void ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word 64bits +//********************************************************************************** +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from); +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from); + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from); + +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + +#endif // !__x86_64__ + +//********************* +// SSE instructions * +//********************* +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ); +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ); + +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from ); +void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from ); +void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ); + +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ); +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ); +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ); + +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ); + +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ); +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); + +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from ); + +void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +#ifndef __x86_64__ +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ); +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); +#endif +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ); +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from); +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from); +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ); +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +// VectorPath +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +void SSE_STMXCSR( uptr from ); +void SSE_LDMXCSR( uptr from ); + + +//********************* +// SSE 2 Instructions* +//********************* +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from); +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from); +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr from ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +// mult by half words +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from); +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr from); + + +//**********************************************************************************/ +//PMOVMSKB: Create 16bit mask from signs of 8bit integers +//********************************************************************************** +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from); +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ); +void SSE_PINSRW_R32_to_XMM(x86SSERegType from, x86IntRegType to, u8 imm8 ); + + +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from ); +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ); +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr from ); +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ); +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +#ifdef __x86_64__ +void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from ); +#endif + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr from ); + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from); + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from); +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from); +//********************* +// SSE-X - uses both SSE,SSE2 code and tries to keep consistensies between the data +// Uses g_xmmtypes to infer the correct type. +//********************* +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ); +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ); +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ); +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr from ); +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ); + +void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr from ); +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from); +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from); + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, uptr from ); +void PFCMPGTMtoR( x86IntRegType to, uptr from ); +void PFCMPGEMtoR( x86IntRegType to, uptr from ); +void PFADDMtoR( x86IntRegType to, uptr from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, uptr from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, uptr from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, uptr from ); +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PF2IDMtoR( x86IntRegType to, uptr from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, uptr from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, uptr from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, uptr from ); +void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, uptr from); +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from); +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ); +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset ); + +#ifndef __x86_64__ +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); +#endif + +/* SSE2 emulated functions for SSE CPU's by kekko*/ + +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ); +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); + +//////////////////////////////////////////////////// +#ifdef _DEBUG +#define WRITECHECK() CheckX86Ptr() +#else +#define WRITECHECK() +#endif + +#define write8(val ) { \ + *(u8*)x86Ptr = (u8)val; \ + x86Ptr++; \ +} \ + +#define write16(val ) \ +{ \ + *(u16*)x86Ptr = (u16)val; \ + x86Ptr += 2; \ +} \ + +#define write32( val ) \ +{ \ + *(u32*)x86Ptr = val; \ + x86Ptr += 4; \ +} \ + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/pcsx2/x86/ix86/ix86_3dnow.c b/pcsx2/x86/ix86/ix86_3dnow.c new file mode 100644 index 0000000..d35e16d --- /dev/null +++ b/pcsx2/x86/ix86/ix86_3dnow.c @@ -0,0 +1,188 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "ix86.h" + +/**********************/ +/* 3DNOW instructions */ +/**********************/ + +/* femms */ +void FEMMS( void ) +{ + write16( 0x0E0F ); +} + +void PFCMPEQMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB0 ); +} + +void PFCMPGTMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA0 ); +} + +void PFCMPGEMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x90 ); +} + +void PFADDMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9E ); +} + +void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9E ); +} + +void PFSUBMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x9A ); +} + +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x9A ); +} + +void PFMULMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xB4 ); +} + +void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB4 ); +} + +void PFRCPMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x96 ); +} + +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x96 ); +} + +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA6 ); +} + +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xB6 ); +} + +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x97 ); +} + +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA7 ); +} + +void PF2IDMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x1D ); +} + +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x1D ); +} + +void PI2FDMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x0D ); +} + +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x0D ); +} + +void PFMAXMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0xA4 ); +} + +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0xA4 ); +} + +void PFMINMtoR( x86IntRegType to, uptr from ) +{ + write16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + write32( from ); + write8( 0x94 ); +} + +void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + write16( 0x0F0F ); + ModRM( 3, to, from ); + write8( 0x94 ); +} + +#endif diff --git a/pcsx2/x86/ix86/ix86_cpudetect.c b/pcsx2/x86/ix86/ix86_cpudetect.c new file mode 100644 index 0000000..2cd6222 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_cpudetect.c @@ -0,0 +1,480 @@ +/* Cpudetection lib + * Copyright (C) 2002-2003 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if defined (_WIN32) +#include +#endif + +#include +#include + +#include "ix86.h" + +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +CAPABILITIES cpucaps; +CPUINFO cpuinfo; + +#define cpuid(cmd,a,b,c,d) \ + __asm__ __volatile__("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) : "0" (cmd)) + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag=1; + +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (_MSC_VER) + +#ifdef __x86_64__ + assert(0); +#else // __x86_64__ + __asm + { + push ebx; + push edi; + + pushfd; + pop eax; + mov edx, eax; + xor eax, 1 << 21; + push eax; + popfd; + pushfd; + pop eax; + xor eax, edx; + mov flag, eax; + } + if ( ! flag ) + { + return -1; + } + + __asm + { + mov eax, cmd; + cpuid; + mov edi, [regs] + mov [edi], eax; + mov [edi+4], ebx; + mov [edi+8], ecx; + mov [edi+12], edx; + + pop edi; + pop ebx; + } +#endif // __x86_64__ + return 0; + + +#else + +#ifndef __x86_64__ + // see if we can use cpuid + __asm__ __volatile__ ( + "sub $0x18, %%esp\n" + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%edx\n" + "xor $0x200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%eax\n" + "mov %%eax, %0\n" + "add $0x18, %%esp\n" + : "=r"(flag) : + ); +#endif + + if ( !flag ) + return -1; + + cpuid(cmd, regs[0], regs[1], regs[2], regs[3]); + +#endif // _MSC_VER +} + +u64 GetCPUTick( void ) +{ +#if defined (_MSC_VER) && _MSC_VER >= 1400 + + return __rdtsc(); + +#elif defined(__MSCW32__) && !defined(__x86_64__) + + __asm rdtsc; + +#else + + u32 _a, _d; + __asm__ __volatile__ ("rdtsc" : "=a"(_a), "=d"(_d)); + return (u64)_a | ((u64)_d << 32); + +#endif +} + +#if defined __LINUX__ + +#include +#include + +#endif + +s64 CPUSpeedHz( unsigned int time ) +{ + s64 timeStart, + timeStop; + s64 startTick, + endTick; + s64 overhead; + + if( ! cpucaps.hasTimeStampCounter ) + { + return 0; //check if function is supported + } + + overhead = GetCPUTick() - GetCPUTick(); + + timeStart = timeGetTime( ); + while( timeGetTime( ) == timeStart ) + { + timeStart = timeGetTime( ); + } + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + for(;;) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > time ) + { + endTick = GetCPUTick( ); + break; + } + } + + return (s64)( ( endTick - startTick ) + ( overhead ) ); +} + +//////////////////////////////////////////////////// +void cpudetectInit( void ) +{ + u32 regs[ 4 ]; + u32 cmds; + u32 AMDspeed; + s8 AMDspeedString[10]; + int cputype=0; // Cpu type + //AMD 64 STUFF + u32 x86_64_8BITBRANDID; + u32 x86_64_12BITBRANDID; + memset( cpuinfo.x86ID, 0, sizeof( cpuinfo.x86ID ) ); + cpuinfo.x86Family = 0; + cpuinfo.x86Model = 0; + cpuinfo.x86PType = 0; + cpuinfo.x86StepID = 0; + cpuinfo.x86Flags = 0; + cpuinfo.x86EFlags = 0; + + if ( iCpuId( 0, regs ) == -1 ) return; + + cmds = regs[ 0 ]; + ((u32*)cpuinfo.x86ID)[ 0 ] = regs[ 1 ]; + ((u32*)cpuinfo.x86ID)[ 1 ] = regs[ 3 ]; + ((u32*)cpuinfo.x86ID)[ 2 ] = regs[ 2 ]; + if ( cmds >= 0x00000001 ) + { + if ( iCpuId( 0x00000001, regs ) != -1 ) + { + cpuinfo.x86StepID = regs[ 0 ] & 0xf; + cpuinfo.x86Model = (regs[ 0 ] >> 4) & 0xf; + cpuinfo.x86Family = (regs[ 0 ] >> 8) & 0xf; + cpuinfo.x86PType = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[1] & 0xff; + cpuinfo.x86Flags = regs[ 3 ]; + } + } + if ( iCpuId( 0x80000000, regs ) != -1 ) + { + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + if ( iCpuId( 0x80000001, regs ) != -1 ) + { + x86_64_12BITBRANDID = regs[1] & 0xfff; + cpuinfo.x86EFlags = regs[ 3 ]; + + } + } + } + switch(cpuinfo.x86PType) + { + case 0: + strcpy( cpuinfo.x86Type, "Standard OEM"); + break; + case 1: + strcpy( cpuinfo.x86Type, "Overdrive"); + break; + case 2: + strcpy( cpuinfo.x86Type, "Dual"); + break; + case 3: + strcpy( cpuinfo.x86Type, "Reserved"); + break; + default: + strcpy( cpuinfo.x86Type, "Unknown"); + break; + } + if ( cpuinfo.x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p + if ( cpuinfo.x86ID[ 0 ] == 'A' ){ cputype=1;} + + if ( cputype == 0 ) //intel cpu + { + if( ( cpuinfo.x86Family >= 7 ) && ( cpuinfo.x86Family < 15 ) ) + { + strcpy( cpuinfo.x86Fam, "Intel P6 family (Not PIV and Higher then PPro" ); + } + else + { + switch( cpuinfo.x86Family ) + { + // Start at 486 because if it's below 486 there is no cpuid instruction + case 4: + strcpy( cpuinfo.x86Fam, "Intel 486" ); + break; + case 5: + switch( cpuinfo.x86Model ) + { + case 4: + case 8: // 0.25 m + strcpy( cpuinfo.x86Fam, "Intel Pentium (MMX)"); + break; + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium" ); + } + break; + case 6: + switch( cpuinfo.x86Model ) + { + case 0: // Pentium pro (P6 A-Step) + case 1: // Pentium pro + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro" ); + break; + + case 2: // 66 MHz FSB + case 5: // Xeon/Celeron (0.25 m) + case 6: // Internal L2 cache + strcpy( cpuinfo.x86Fam, "Intel Pentium II" ); + break; + + case 7: // Xeon external L2 cache + case 8: // Xeon/Celeron with 256 KB on-die L2 cache + case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache + case 11: // Xeon/Celeron with Tualatin core, on-die cache + strcpy( cpuinfo.x86Fam, "Intel Pentium III" ); + break; + case 15: // Core 2 Duo Allendale/Conroe + strcpy( cpuinfo.x86Fam, "Intel Core 2 Duo" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium Pro (Unknown)" ); + } + break; + case 15: + switch( cpuinfo.x86Model ) + { + case 0: // Willamette (A-Step) + case 1: // Willamette + strcpy( cpuinfo.x86Fam, "Willamette Intel Pentium IV" ); + break; + case 2: // Northwood + strcpy( cpuinfo.x86Fam, "Northwood Intel Pentium IV" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "Intel Pentium IV (Unknown)" ); + break; + } + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown Intel CPU" ); + } + } + } + else if ( cputype == 1 ) //AMD cpu + { + if( cpuinfo.x86Family >= 7 ) + { + if((x86_64_12BITBRANDID !=0) || (x86_64_8BITBRANDID !=0)) + { + if(x86_64_8BITBRANDID == 0 ) + { + switch((x86_64_12BITBRANDID >>6)& 0x3f) + { + case 4: + strcpy(cpuinfo.x86Fam,"AMD Athlon(tm) 64 Processor"); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 12: + strcpy(cpuinfo.x86Fam,"AMD Opteron(tm) Processor"); + break; + case 5: + strcpy( cpuinfo.x86Fam, "AMD Athlon X2 Processor" ); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(cpuinfo.x86Fam,AMDspeedString); + break; + case 44: + strcpy( cpuinfo.x86Fam, "AMD Opteron(tm) Dual Core Processor" ); + break; + default: + strcpy(cpuinfo.x86Fam,"Unknown AMD 64 proccesor"); + + } + } + else //8bit brand id is non zero + { + strcpy(cpuinfo.x86Fam,"Unsupported yet AMD64 cpu"); + } + } + else + { + strcpy( cpuinfo.x86Fam, "AMD K7+ Processor" ); + } + } + else + { + switch ( cpuinfo.x86Family ) + { + case 4: + switch( cpuinfo.x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( cpuinfo.x86Fam, "AMD 5x86 Processor" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( cpuinfo.x86Fam, "AMD 486 Processor" ); + break; + + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + + } + break; + + case 5: + switch( cpuinfo.x86Model) + { + case 0: // SSA 5 (75, 90 and 100 Mhz) + case 1: // 5k86 (PR 120 and 133 MHz) + case 2: // 5k86 (PR 166 MHz) + case 3: // K5 5k86 (PR 200 MHz) + strcpy( cpuinfo.x86Fam, "AMD K5 Processor" ); + break; + + case 6: + case 7: // (0.25 m) + case 8: // K6-2 + case 9: // K6-III + case 14: // K6-2+ / K6-III+ + strcpy( cpuinfo.x86Fam, "AMD K6 Series Processor" ); + break; + + default: + strcpy( cpuinfo.x86Fam, "AMD Unknown Processor" ); + } + break; + case 6: + strcpy( cpuinfo.x86Fam, "AMD Athlon XP Processor" ); + break; + default: + strcpy( cpuinfo.x86Fam, "Unknown AMD CPU" ); + } + } + } + //capabilities + cpucaps.hasFloatingPointUnit = ( cpuinfo.x86Flags >> 0 ) & 1; + cpucaps.hasVirtual8086ModeEnhancements = ( cpuinfo.x86Flags >> 1 ) & 1; + cpucaps.hasDebuggingExtensions = ( cpuinfo.x86Flags >> 2 ) & 1; + cpucaps.hasPageSizeExtensions = ( cpuinfo.x86Flags >> 3 ) & 1; + cpucaps.hasTimeStampCounter = ( cpuinfo.x86Flags >> 4 ) & 1; + cpucaps.hasModelSpecificRegisters = ( cpuinfo.x86Flags >> 5 ) & 1; + cpucaps.hasPhysicalAddressExtension = ( cpuinfo.x86Flags >> 6 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 7 ) & 1; + cpucaps.hasCOMPXCHG8BInstruction = ( cpuinfo.x86Flags >> 8 ) & 1; + cpucaps.hasAdvancedProgrammableInterruptController = ( cpuinfo.x86Flags >> 9 ) & 1; + cpucaps.hasSEPFastSystemCall = ( cpuinfo.x86Flags >> 11 ) & 1; + cpucaps.hasMemoryTypeRangeRegisters = ( cpuinfo.x86Flags >> 12 ) & 1; + cpucaps.hasPTEGlobalFlag = ( cpuinfo.x86Flags >> 13 ) & 1; + cpucaps.hasMachineCheckArchitecture = ( cpuinfo.x86Flags >> 14 ) & 1; + cpucaps.hasConditionalMoveAndCompareInstructions = ( cpuinfo.x86Flags >> 15 ) & 1; + cpucaps.hasFGPageAttributeTable = ( cpuinfo.x86Flags >> 16 ) & 1; + cpucaps.has36bitPageSizeExtension = ( cpuinfo.x86Flags >> 17 ) & 1; + cpucaps.hasProcessorSerialNumber = ( cpuinfo.x86Flags >> 18 ) & 1; + cpucaps.hasCFLUSHInstruction = ( cpuinfo.x86Flags >> 19 ) & 1; + cpucaps.hasDebugStore = ( cpuinfo.x86Flags >> 21 ) & 1; + cpucaps.hasACPIThermalMonitorAndClockControl = ( cpuinfo.x86Flags >> 22 ) & 1; + cpucaps.hasMultimediaExtensions = ( cpuinfo.x86Flags >> 23 ) & 1; //mmx + cpucaps.hasFastStreamingSIMDExtensionsSaveRestore = ( cpuinfo.x86Flags >> 24 ) & 1; + cpucaps.hasStreamingSIMDExtensions = ( cpuinfo.x86Flags >> 25 ) & 1; //sse + cpucaps.hasStreamingSIMD2Extensions = ( cpuinfo.x86Flags >> 26 ) & 1; //sse2 + cpucaps.hasSelfSnoop = ( cpuinfo.x86Flags >> 27 ) & 1; + cpucaps.hasHyperThreading = ( cpuinfo.x86Flags >> 28 ) & 1; + cpucaps.hasThermalMonitor = ( cpuinfo.x86Flags >> 29 ) & 1; + cpucaps.hasIntel64BitArchitecture = ( cpuinfo.x86Flags >> 30 ) & 1; + //that is only for AMDs + cpucaps.hasMultimediaExtensionsExt = ( cpuinfo.x86EFlags >> 22 ) & 1; //mmx2 + cpucaps.hasAMD64BitArchitecture = ( cpuinfo.x86EFlags >> 29 ) & 1; //64bit cpu + cpucaps.has3DNOWInstructionExtensionsExt = ( cpuinfo.x86EFlags >> 30 ) & 1; //3dnow+ + cpucaps.has3DNOWInstructionExtensions = ( cpuinfo.x86EFlags >> 31 ) & 1; //3dnow + cpuinfo.cpuspeed = (u32 )(CPUSpeedHz( 1000 ) / 1000000); +} diff --git a/pcsx2/x86/ix86/ix86_fpu.c b/pcsx2/x86/ix86/ix86_fpu.c new file mode 100644 index 0000000..ccabb84 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_fpu.c @@ -0,0 +1,274 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include +#include "ix86.h" + +/********************/ +/* FPU instructions */ +/********************/ + +/* fild m32 to fpu reg stack */ +void FILD32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fistp m32 from fpu reg stack */ +void FISTP32( u32 from ) +{ + write8( 0xDB ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fld m32 to fpu reg stack */ +void FLD32( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// fld st(i) +void FLD(int st) { write16(0xc0d9+(st<<8)); } + +void FLD1() { write16(0xe8d9); } +void FLDL2E() { write16(0xead9); } + +/* fst m32 from fpu reg stack */ +void FST32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +/* fstp m32 from fpu reg stack */ +void FSTP32( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +// fstp st(i) +void FSTP(int st) { write16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +void FLDCW( u32 from ) +{ + write8( 0xD9 ); + ModRM( 0, 0x5, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fnstcw fpu control word to m16 */ +void FNSTCW( u32 to ) +{ + write8( 0xD9 ); + ModRM( 0, 0x7, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void FNSTSWtoAX( void ) +{ + write16( 0xE0DF ); +} + +void FXAM() +{ + write16(0xe5d9); +} + +void FDECSTP() { write16(0xf6d9); } +void FRNDINT() { write16(0xfcd9); } +void FXCH(int st) { write16(0xc8d9+(st<<8)); } +void F2XM1() { write16(0xf0d9); } +void FSCALE() { write16(0xfdd9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +void FADD32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +void FADD320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +void FSUB32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +void FSUB320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +void FSUBP( void ) +{ + write8( 0xDE ); + write8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +void FMUL32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +void FMUL320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +void FDIV32Rto0( x86IntRegType src ) +{ + write8( 0xD8 ); + write8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +void FDIV320toR( x86IntRegType src ) +{ + write8( 0xDC ); + write8( 0xF8 + src ); +} + +void FDIV320toRP( x86IntRegType src ) +{ + write8( 0xDE ); + write8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +void FADD32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x0, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fsub m32 to fpu reg stack */ +void FSUB32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x4, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fmul m32 to fpu reg stack */ +void FMUL32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x1, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fdiv m32 to fpu reg stack */ +void FDIV32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x6, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fabs fpu reg stack */ +void FABS( void ) +{ + write16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +void FSQRT( void ) +{ + write16( 0xFAD9 ); +} + +void FPATAN(void) { write16(0xf3d9); } +void FSIN(void) { write16(0xfed9); } + +/* fchs fpu reg stack */ +void FCHS( void ) +{ + write16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +void FCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +void FCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +void FUCOMI( x86IntRegType src ) +{ + write8( 0xDB ); + write8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +void FUCOMIP( x86IntRegType src ) +{ + write8( 0xDF ); + write8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +void FCOM32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* fcomp m32 to fpu reg stack */ +void FCOMP32( u32 from ) +{ + write8( 0xD8 ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +#define FCMOV32( low, high ) \ + { \ + write8( low ); \ + write8( high + from ); \ + } + +void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } + +#endif diff --git a/pcsx2/x86/ix86/ix86_mmx.c b/pcsx2/x86/ix86/ix86_mmx.c new file mode 100644 index 0000000..dd23f97 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_mmx.c @@ -0,0 +1,636 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include "ix86.h" + +#include + +/********************/ +/* MMX instructions */ +/********************/ + +// r64 = mm + +/* movq m64 to r64 */ +void MOVQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0x6F0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movq r64 to m64 */ +void MOVQRtoM( uptr to, x86MMXRegType from ) +{ + write16( 0x7F0F ); + ModRM( 0, from, DISP32 ); + write32(MEMADDR(to, 4)); +} + +/* pand r64 to r64 */ +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDB0F ); + ModRM( 3, to, from ); +} + +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDF0F ); + ModRM( 3, to, from ); +} + +/* por r64 to r64 */ +void PORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEB0F ); + ModRM( 3, to, from ); +} + +/* pxor r64 to r64 */ +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEF0F ); + ModRM( 3, to, from ); +} + +/* psllq r64 to r64 */ +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF30F ); + ModRM( 3, to, from ); +} + +/* psllq m64 to r64 */ +void PSLLQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xF30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psllq imm8 to r64 */ +void PSLLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 6, to); + write8( from ); +} + +/* psrlq r64 to r64 */ +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD30F ); + ModRM( 3, to, from ); +} + +/* psrlq m64 to r64 */ +void PSRLQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xD30F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* psrlq imm8 to r64 */ +void PSRLQItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x730F ); + ModRM( 3, 2, to); + write8( from ); +} + +/* paddusb r64 to r64 */ +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDC0F ); + ModRM( 3, to, from ); +} + +/* paddusb m64 to r64 */ +void PADDUSBMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xDC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddusw r64 to r64 */ +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xDD0F ); + ModRM( 3, to, from ); +} + +/* paddusw m64 to r64 */ +void PADDUSWMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xDD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddb r64 to r64 */ +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFC0F ); + ModRM( 3, to, from ); +} + +/* paddb m64 to r64 */ +void PADDBMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xFC0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddw r64 to r64 */ +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFD0F ); + ModRM( 3, to, from ); +} + +/* paddw m64 to r64 */ +void PADDWMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xFD0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* paddd r64 to r64 */ +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFE0F ); + ModRM( 3, to, from ); +} + +/* paddd m64 to r64 */ +void PADDDMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xFE0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* emms */ +void EMMS( void ) +{ + write16( 0x770F ); +} + +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xEC0F ); + ModRM( 3, to, from ); +} + +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xED0F ); + ModRM( 3, to, from ); +} + +// paddq m64 to r64 (sse2 only?) +void PADDQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xD40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// paddq r64 to r64 (sse2 only?) +void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD40F ); + ModRM( 3, to, from ); +} + +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE80F ); + ModRM( 3, to, from ); +} + +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE90F ); + ModRM( 3, to, from ); +} + + +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF80F ); + ModRM( 3, to, from ); +} + +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF90F ); + ModRM( 3, to, from ); +} + +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFA0F ); + ModRM( 3, to, from ); +} + +void PSUBDMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xFA0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD80F ); + ModRM( 3, to, from ); +} + +void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD90F ); + ModRM( 3, to, from ); +} + +// psubq m64 to r64 (sse2 only?) +void PSUBQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xFB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// psubq r64 to r64 (sse2 only?) +void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xFB0F ); + ModRM( 3, to, from ); +} + +// pmuludq m64 to r64 (sse2 only?) +void PMULUDQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xF40F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +// pmuludq r64 to r64 (sse2 only?) +void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF40F ); + ModRM( 3, to, from ); +} + +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x740F ); + ModRM( 3, to, from ); +} + +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x750F ); + ModRM( 3, to, from ); +} + +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x760F ); + ModRM( 3, to, from ); +} + +void PCMPEQDMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0x760F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x640F ); + ModRM( 3, to, from ); +} + +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x650F ); + ModRM( 3, to, from ); +} + +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x660F ); + ModRM( 3, to, from ); +} + +void PCMPGTDMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0x660F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PSRLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( from ); +} + +void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xD20F ); + ModRM( 3, to, from ); +} + +void PSLLWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( from ); +} + +void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xF20F ); + ModRM( 3, to, from ); +} + +void PSRAWItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADItoR( x86MMXRegType to, u8 from ) +{ + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( from ); +} + +void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0xE20F ); + ModRM( 3, to, from ); +} + +/* por m64 to r64 */ +void PORMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xEB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pxor m64 to r64 */ +void PXORMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xEF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* pand m64 to r64 */ +void PANDMtoR( x86MMXRegType to, uptr from ) +{ + //u64 rip = (u64)x86Ptr + 7; + write16( 0xDB0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PANDNMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0xDF0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6A0F ); + ModRM( 3, to, from ); +} + +void PUNPCKHDQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0x6A0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x620F ); + ModRM( 3, to, from ); +} + +void PUNPCKLDQMtoR( x86MMXRegType to, uptr from ) +{ + write16( 0x620F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void MOVQ64ItoR( x86MMXRegType reg, u64 i ) +{ + MOVQMtoR( reg, ( u32 )(x86Ptr) + 2 + 7 ); + JMP8( 8 ); + write64( i ); +} + +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) +{ + write16( 0x6F0F ); + ModRM( 3, to, from ); +} + +void MOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6F0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7F0F ); + + if( offset < 128 ) { + ModRM( 1, from , to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +/* movd m32 to r64 */ +void MOVDMtoMMX( x86MMXRegType to, uptr from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +/* movd r64 to m32 */ +void MOVDMMXtoM( uptr to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, DISP32 ); + write32( MEMADDR(to, 4) ); +} + +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 3, to, from ); +} + +void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) +{ + write16( 0x6E0F ); + ModRM( 0, to, from ); +} + +void MOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) +{ + write16( 0x6E0F ); + + if( offset < 128 ) { + ModRM( 1, to, from ); + write8(offset); + } + else { + ModRM( 2, to, from ); + write32(offset); + } +} + +void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 3, from, to ); +} + +void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) +{ + write16( 0x7E0F ); + ModRM( 0, from, to ); + if( to >= 4 ) { + // no idea why + assert( to == ESP ); + write8(0x24); + } + +} + +void MOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) +{ + write16( 0x7E0F ); + + if( offset < 128 ) { + ModRM( 1, from, to ); + write8(offset); + } + else { + ModRM( 2, from, to ); + write32(offset); + } +} + +///* movd r32 to r64 */ +//void MOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x6E0F ); +// ModRM( 3, to, from ); +//} +// +///* movq r64 to r32 */ +//void MOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) +//{ +// write16( 0x7E0F ); +// ModRM( 3, from, to ); +//} + +// untested +void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x630F ); + ModRM( 3, to, from ); +} + +void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) +{ + write16( 0x6B0F ); + ModRM( 3, to, from ); +} + +void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) +{ + write16( 0xD70F ); + ModRM( 3, to, from ); +} + +void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) +{ + if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); + write16( 0xc40f ); + ModRM( 3, to, from ); + write8( imm8 ); +} + +void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) +{ + write16(0x700f); + ModRM( 3, to, from ); + write8(imm8); +} + +void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8) +{ + write16( 0x700f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); + write8(imm8); +} + +void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) +{ + write16(0xf70f); + ModRM( 3, to, from ); +} + +#endif diff --git a/pcsx2/x86/ix86/ix86_sse.c b/pcsx2/x86/ix86/ix86_sse.c new file mode 100644 index 0000000..f3dff33 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_sse.c @@ -0,0 +1,1477 @@ +// stop compiling if NORECBUILD build (only for Visual Studio) +#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD)) + +#include +#include "ix86.h" + +PCSX2_ALIGNED16(unsigned int p[4]); +PCSX2_ALIGNED16(unsigned int p2[4]); +PCSX2_ALIGNED16(float f[4]); + + +XMMSSEType g_xmmtypes[XMMREGS] = {0}; + +/********************/ +/* SSE instructions */ +/********************/ + +#define SSEMtoR( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS ) ; \ + RexR(0, to); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSERtoM( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( from < XMMREGS) ; \ + RexR(0, from); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSE_SS_MtoR( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS ) ; \ + write8( 0xf3 ); \ + RexR(0, to); \ + write16( code ); \ + ModRM( 0, to, DISP32 ); \ + write32( MEMADDR(from, 4 + overb) ); \ + +#define SSE_SS_RtoM( code, overb ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( from < XMMREGS) ; \ + write8( 0xf3 ); \ + RexR(0, from); \ + write16( code ); \ + ModRM( 0, from, DISP32 ); \ + write32( MEMADDR(to, 4 + overb) ); \ + +#define SSERtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + RexRB(0, to, from); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define SSEMtoR66( code ) \ + write8( 0x66 ); \ + SSEMtoR( code, 0 ); + +#define SSERtoM66( code ) \ + write8( 0x66 ); \ + SSERtoM( code, 0 ); + +#define SSERtoR66( code ) \ + write8( 0x66 ); \ + SSERtoR( code ); + +#define _SSERtoR66( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0x66 ); \ + RexRB(0, from, to); \ + write16( code ); \ + ModRM( 3, from, to ); + +#define SSE_SS_RtoR( code ) \ + assert( cpucaps.hasStreamingSIMDExtensions ); \ + assert( to < XMMREGS && from < XMMREGS) ; \ + write8( 0xf3 ); \ + RexRB(0, to, from); \ + write16( code ); \ + ModRM( 3, to, from ); + +#define CMPPSMtoR( op ) \ + SSEMtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPPSRtoR( op ) \ + SSERtoR( 0xc20f ); \ + write8( op ); + +#define CMPSSMtoR( op ) \ + SSE_SS_MtoR( 0xc20f, 1 ); \ + write8( op ); + +#define CMPSSRtoR( op ) \ + SSE_SS_RtoR( 0xc20f ); \ + write8( op ); + + + +void WriteRmOffset(x86IntRegType to, int offset); +void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset); + +/* movups [r32][r32*scale] to xmm1 */ +void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRXB(0, to, from2, from); + write16( 0x100f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups xmm1 to [r32][r32*scale] */ +void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRXB(1, to, from2, from); + write16( 0x110f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movups [r32] to r32 */ +void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x100f ); + ModRM( 0, to, from ); +} + +/* movups r32 to [r32] */ +void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x110f ); + ModRM( 0, from, to ); +} + +/* movlps [r32] to r32 */ +void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(1, to, from); + write16( 0x120f ); + ModRM( 0, to, from ); +} + +void SSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x120f ); + WriteRmOffsetFrom(to, from, offset); +} + +/* movaps r32 to [r32] */ +void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x130f ); + ModRM( 0, from, to ); +} + +void SSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x130f ); + WriteRmOffsetFrom(from, to, offset); +} + +/* movaps [r32][r32*scale] to xmm1 */ +void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions && from != EBP ); + RexRXB(0, to, from2, from); + write16( 0x280f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +/* movaps xmm1 to [r32][r32*scale] */ +void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) +{ + assert( cpucaps.hasStreamingSIMDExtensions && from != EBP ); + RexRXB(0, to, from2, from); + write16( 0x290f ); + ModRM( 0, to, 0x4 ); + SibSB( scale, from2, from ); +} + +// movaps [r32+offset] to r32 +void SSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x280f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movaps r32 to [r32+offset] +void SSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x290f ); + WriteRmOffsetFrom(from, to, offset); +} + +// movdqa [r32+offset] to r32 +void SSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write8(0x66); + RexRB(0, to, from); + write16( 0x6f0f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movdqa r32 to [r32+offset] +void SSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + write8(0x66); + RexRB(0, from, to); + write16( 0x7f0f ); + WriteRmOffsetFrom(from, to, offset); +} + +// movups [r32+offset] to r32 +void SSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + RexRB(0, to, from); + write16( 0x100f ); + WriteRmOffsetFrom(to, from, offset); +} + +// movups r32 to [r32+offset] +void SSE_MOVUPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16( 0x110f ); + WriteRmOffsetFrom(from, to, offset); +} + +//**********************************************************************************/ +//MOVAPS: Move aligned Packed Single Precision FP values * +//********************************************************************************** +void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); } +void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); } +void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x280f ); } + +void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); } +void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } + +void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVSD_XMM_to_XMM(to, from); + else { + write8(0xf2); + SSERtoR( 0x100f); + } +} + +void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_M64_to_XMM(to, from); + else { + write8(0xf3); SSEMtoR( 0x7e0f, 0); + } +} + +void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ_XMM_to_XMM(to, from); + else { + write8(0xf3); SSERtoR( 0x7e0f); + } +} + +void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE_MOVLPS_XMM_to_M64(to, from); + else { + SSERtoM66(0xd60f); + } +} + +#ifndef __x86_64__ +void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVDQ2Q_XMM_to_MM(to, from); + else { + write8(0xf2); + SSERtoR( 0xd60f); + } +} +void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) SSE2EMU_MOVQ2DQ_MM_to_XMM(to, from); + else { + write8(0xf3); + SSERtoR( 0xd60f); + } +} +#endif + +//**********************************************************************************/ +//MOVSS: Move Scalar Single-Precision FP value * +//********************************************************************************** +void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x100f, 0 ); } +void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); } +void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0xf3); + RexRB(0, from, to); + write16(0x110f); + ModRM(0, from, to); +} + +void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x100f ); } + +void SSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + write8(0xf3); + RexRB(0, to, from); + write16( 0x100f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + write8(0xf3); + RexRB(0, from, to); + write16(0x110f); + WriteRmOffsetFrom(from, to, offset); +} + +void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); } +//**********************************************************************************/ +//MOVLPS: Move low Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x120f, 0 ); } +void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); } + +void SSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x120f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + RexRB(0, from, to); + write16(0x130f); + WriteRmOffsetFrom(from, to, offset); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHPS: Move High Packed Single-Precision FP * +//********************************************************************************** +void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x160f, 0 ); } +void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); } + +void SSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, to, from); + write16( 0x160f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + assert( cpucaps.hasStreamingSIMDExtensions ); + RexRB(0, from, to); + write16(0x170f); + WriteRmOffsetFrom(from, to, offset); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVLHPS: Moved packed Single-Precision FP low to high * +//********************************************************************************** +void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVHLPS: Moved packed Single-Precision FP High to Low * +//********************************************************************************** +void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDPS: Logical Bit-wise AND for Single FP * +//********************************************************************************** +void SSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x540f, 0 ); } +void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x540f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ANDNPS : Logical Bit-wise AND NOT of Single-precision FP values * +//********************************************************************************** +void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x550f, 0 ); } +void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x550f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RCPPS : Packed Single-Precision FP Reciprocal * +//********************************************************************************** +void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x530f ); } +void SSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x530f, 0 ); } + +void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x530f); } +void SSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR(0x530f, 0); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ORPS : Bit-wise Logical OR of Single-Precision FP Data * +//********************************************************************************** +void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x560f, 0 ); } +void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x560f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//XORPS : Bitwise Logical XOR of Single-Precision FP Values * +//********************************************************************************** +void SSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x570f, 0 ); } +void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x570f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDPS : ADD Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x580f, 0 ); } +void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x580f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//ADDSS : ADD Scalar Single-Precision FP Values * +//********************************************************************************** +void SSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x580f, 0 ); } +void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x580f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBPS: Packed Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5c0f, 0 ); } +void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5c0f ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SUBSS : Scalar Single-Precision FP Subtract * +//********************************************************************************** +void SSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5c0f, 0 ); } +void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5c0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULPS : Packed Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x590f, 0 ); } +void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MULSS : Scalar Single-Precision FP Multiply * +//********************************************************************************** +void SSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x590f, 0 ); } +void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x590f ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Packed Single-Precission FP compare (CMPccPS) * +//********************************************************************************** +//missing SSE_CMPPS_I8_to_XMM +// SSE_CMPPS_M32_to_XMM +// SSE_CMPPS_XMM_to_XMM +void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 0 ); } +void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } +void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 1 ); } +void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } +void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 2 ); } +void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } +void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 3 ); } +void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } +void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 4 ); } +void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } +void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 5 ); } +void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } +void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 6 ); } +void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } +void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 7 ); } +void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 7 ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//Scalar Single-Precission FP compare (CMPccSS) * +//********************************************************************************** +//missing SSE_CMPSS_I8_to_XMM +// SSE_CMPSS_M32_to_XMM +// SSE_CMPSS_XMM_to_XMM +void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 0 ); } +void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } +void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 1 ); } +void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } +void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 2 ); } +void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } +void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 3 ); } +void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } +void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 4 ); } +void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } +void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 5 ); } +void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } +void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 6 ); } +void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } +void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 7 ); } +void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } + +void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ) +{ + RexR(0, to); + write16( 0x2e0f ); + ModRM( 0, to, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + RexRB(0, to, from); + write16( 0x2e0f ); + ModRM( 3, to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x520f, 0 ); } +void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x520f ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//RSQRTSS : Scalar Single-Precision FP Square Root Reciprocal * +//********************************************************************************** +void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x520f, 0 ); } +void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x520f ); } + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTPS : Packed Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x510f, 0 ); } +void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x510f ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SQRTSS : Scalar Single-Precision FP Square Root * +//********************************************************************************** +void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x510f, 0 ); } +void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SS_RtoR( 0x510f ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXPS: Return Packed Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5f0f, 0 ); } +void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5f0f ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MAXSS: Return Scalar Single-Precision FP Maximum * +//********************************************************************************** +void SSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } +void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } + +#ifndef __x86_64__ +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * +//********************************************************************************** +void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x2a0f, 0 ); } +void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); } + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTPS2PI: Packed Single FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ) { SSEMtoR( 0x2d0f, 0 ); } +void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } +#endif + +void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { write8(0xf3); SSEMtoR(0x2c0f, 0); } +void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) +{ + write8(0xf3); + RexRB(0, to, from); + write16(0x2c0f); + ModRM(3, to, from); +} + +void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x2a0f, 0); } +void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) +{ + write8(0xf3); + RexRB(0, to, from); + write16(0x2a0f); + ModRM(3, to, from); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * +//********************************************************************************** +void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5b0f, 0 ); } +void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); } + +//**********************************************************************************/ +//CVTPS2DQ: Packed Single Precision FP to Packed Signed INT32 Conversion * +//********************************************************************************** +void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x5b0f ); } +void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } + +void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { write8(0xf3); SSERtoR(0x5b0f); } +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINPS: Return Packed Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5d0f, 0 ); } +void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5d0f ); } + +////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MINSS: Return Scalar Single-Precision FP Minimum * +//********************************************************************************** +void SSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } +void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } + +#ifndef __x86_64__ +/////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMAXSW: Packed Signed Integer Word Maximum * +//********************************************************************************** +//missing + // SSE_PMAXSW_M64_to_MM +// SSE2_PMAXSW_M128_to_XMM +// SSE2_PMAXSW_XMM_to_XMM +void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEE0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PMINSW: Packed Signed Integer Word Minimum * +//********************************************************************************** +//missing + // SSE_PMINSW_M64_to_MM +// SSE2_PMINSW_M128_to_XMM +// SSE2_PMINSW_XMM_to_XMM +void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEA0F ); } +#endif + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//SHUFPS: Shuffle Packed Single-Precision FP Values * +//********************************************************************************** +void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8( imm8 ); } +void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } + +void SSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ) +{ + RexRB(0, to, from); + write16(0xc60f); + WriteRmOffsetFrom(to, from, offset); + write8(imm8); +} + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSHUFD: Shuffle Packed DoubleWords * +//********************************************************************************** +void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_PSHUFD_XMM_to_XMM(to, from, imm8); + } + else { + SSERtoR66( 0x700F ); + write8( imm8 ); + } +} +void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR66( 0x700F ); write8( imm8 ); } + +void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF2); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { write8(0xF2); SSEMtoR(0x700F, 1); write8(imm8); } +void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF3); SSERtoR(0x700F); write8(imm8); } +void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { write8(0xF3); SSEMtoR(0x700F, 1); write8(imm8); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR(0x140f, 0); } +void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x140F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//UNPCKHPS: Unpack and Interleave High Packed Single-Precision FP Data * +//********************************************************************************** +void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR(0x150f, 0); } +void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x150F ); } + +//////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVPS : Packed Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5e0F, 0 ); } +void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5e0F ); } + +////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//DIVSS : Scalar Single-Precision FP Divide * +//********************************************************************************** +void SSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5e0F, 0 ); } +void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5e0F ); } + +///////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//STMXCSR : Store Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_STMXCSR( uptr from ) { + write16( 0xAE0F ); + ModRM( 0, 0x3, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//LDMXCSR : Load Streaming SIMD Extension Control/Status * +//********************************************************************************** +void SSE_LDMXCSR( uptr from ) { + write16( 0xAE0F ); + ModRM( 0, 0x2, DISP32 ); + write32( MEMADDR(from, 4) ); +} + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PADDB,PADDW,PADDD : Add Packed Integers * +//********************************************************************************** +void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); } +void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFC0F ); } +void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } +void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFD0F ); } +void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } +void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFE0F ); } + +void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } +void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr from ) { SSEMtoR66( 0xD40F ); } + +/////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x640F ); } +void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x640F ); } +void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } +void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x650F ); } +void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } +void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x660F ); } +void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } +void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x740F ); } +void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } +void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x750F ); } +void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_XMM_to_XMM(to, from); + } + else { + SSERtoR66( 0x760F ); + } +} + +void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE_CMPEQPS_M128_to_XMM(to, from); + } + else { + SSEMtoR66( 0x760F ); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); } +void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); } + +//////////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); } +void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF80F ); } +void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } +void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF90F ); } +void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } +void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFA0F ); } +void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } +void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFB0F ); } + +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66(0x6E0F); } +void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_R_to_XMM(to, from); + } + else { + SSERtoR66(0x6E0F); + } +} + +void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + write8(0x66); + RexRB(0, to, from); + write16( 0x6e0f ); + ModRM( 0, to, from); +} + +void SSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + write8(0x66); + RexRB(0, to, from); + write16( 0x6e0f ); + WriteRmOffsetFrom(to, from, offset); +} + +void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); } +void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_R(to, from); + } + else { + _SSERtoR66(0x7E0F); + } +} + +void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + write8(0x66); + RexRB(0, from, to); + write16( 0x7e0f ); + ModRM( 0, from, to ); +} + +void SSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( !cpucaps.hasStreamingSIMD2Extensions ) { + SSE2EMU_MOVD_XMM_to_RmOffset(to, from, offset); + } + else { + write8(0x66); + RexRB(0, from, to); + write16( 0x7e0f ); + WriteRmOffsetFrom(from, to, offset); + } +} + +#ifdef __x86_64__ +void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from ) +{ + assert( from < XMMREGS); + write8( 0x66 ); + RexRB(1, from, to); + write16( 0x7e0f ); + ModRM( 3, from, to ); +} + +void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from ) +{ + assert( to < XMMREGS); + write8(0x66); + RexRB(1, to, from); + write16( 0x6e0f ); + ModRM( 3, to, from ); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } +void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEB0F ); } + +// logical and to &= from +void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDB0F ); } +void SSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDB0F ); } + +// to = (~to) & from +void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDF0F ); } +void SSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDF0F ); } + +///////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PXOR : SSE Bitwise XOR * +//********************************************************************************** +void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEF0F ); } +void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEF0F ) }; +/////////////////////////////////////////////////////////////////////////////////////// + +void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from) {SSEMtoR66(0x6F0F); } +void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ){SSERtoM66(0x7F0F);} +void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSERtoR66(0x6F0F); } + +void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xF3); SSEMtoR(0x6F0F, 0); } +void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from) { write8(0xF3); SSERtoM(0x7F0F, 0); } +void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { write8(0xF3); SSERtoR(0x6F0F); } + +// shift right logical + +void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } +void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD10F); } +void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); } +void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD20F); } +void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); } +void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD30F); } +void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 2 , to ); + write8( imm8 ); +} + +void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 3 , to ); + write8( imm8 ); +} + +// shift right arithmetic + +void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); } +void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xE10F); } +void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE20F); } +void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xE20F); } +void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 4 , to ); + write8( imm8 ); +} + +// shift left logical + +void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); } +void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF10F); } +void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x710F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); } +void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF20F); } +void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x720F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); } +void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF30F); } +void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 6 , to ); + write8( imm8 ); +} + +void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) +{ + write8( 0x66 ); + RexB(0, to); + write16( 0x730F ); + ModRM( 3, 7 , to ); + write8( imm8 ); +} + + +void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEE0F ); } +void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEE0F ); } + +void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDE0F ); } +void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDE0F ); } + +void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEA0F ); } +void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEA0F ); } + +void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xDA0F ); } +void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xDA0F ); } + +// + +void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xEC0F ); } +void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xEC0F ); } + +void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xED0F ); } +void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xED0F ); } + +void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE80F ); } +void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE80F ); } + +void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xE90F ); } +void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ){ SSEMtoR66( 0xE90F ); } + +void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } +void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD80F ); } +void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } +void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD90F ); } + +void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } +void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDC0F ); } +void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } +void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDD0F ); } + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x630F ); } +void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x630F ); } +void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } +void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6B0F ); } + +void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } +void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x670F ); } + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x600F ); } +void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x600F ); } + +void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } +void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x680F ); } + +void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } +void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x610F ); } +void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } +void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x690F ); } + +void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } +void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x620F ); } +void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } +void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6A0F ); } + +void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } +void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6C0F ); } + +void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } +void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6D0F ); } + +void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } +void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xD50F ); } +void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } +void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xE50F ); } + +void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } +void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xF40F ); } + +void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); } + +void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); } +void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); } + +void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf2); SSERtoR( 0x7c0f ); } +void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from){ write8(0xf2); SSEMtoR( 0x7c0f, 0 ); } + +void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { + write8(0xf3); + RexRB(0, to, from); + write16( 0x120f); + ModRM( 3, to, from ); +} + +void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x120f, 0); } +void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x160f); } +void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x160f, 0); } + +// SSE-X +void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset); + else SSE_MOVAPSRmtoROffset(to, from, offset); +} + +void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset); + else SSE_MOVAPSRtoRmOffset(to, from, offset); +} + +void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +void SSEX_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); + else SSE_MOVSS_M32_to_XMM(to, from); +} + +void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); + else SSE_MOVSS_XMM_to_M32(to, from); +} + +void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from); + else SSE_MOVSS_XMM_to_Rm(to, from); +} + +void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset); + else SSE_MOVSS_RmOffset_to_XMM(to, from, offset); +} + +void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset); + else SSE_MOVSS_XMM_to_RmOffset(to, from, offset); +} + +void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); + else SSE_ORPS_M128_to_XMM(to, from); +} + +void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); + else SSE_ORPS_XMM_to_XMM(to, from); +} + +void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); + else SSE_XORPS_M128_to_XMM(to, from); +} + +void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); + else SSE_XORPS_XMM_to_XMM(to, from); +} + +void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); + else SSE_ANDPS_M128_to_XMM(to, from); +} + +void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); + else SSE_ANDPS_XMM_to_XMM(to, from); +} + +void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); + else SSE_ANDNPS_M128_to_XMM(to, from); +} + +void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); + else SSE_ANDNPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); + else SSE_UNPCKLPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); + else SSE_UNPCKLPS_XMM_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); + else SSE_UNPCKHPS_M128_to_XMM(to, from); +} + +void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); + else SSE_UNPCKHPS_XMM_to_XMM(to, from); +} + +void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( cpucaps.hasStreamingSIMD2Extensions && g_xmmtypes[from] == XMMT_INT ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); + if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); + } + else { + SSE_MOVHLPS_XMM_to_XMM(to, from); + } +} + +// SSE2 emulation +void SSE2EMU_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_SHUFPS_XMM_to_XMM(to, from, 0x4e); + SSE_SHUFPS_XMM_to_XMM(to, to, 0x4e); +} + +void SSE2EMU_MOVQ_M64_to_XMM( x86SSERegType to, uptr from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE_MOVLPS_M64_to_XMM(to, from); +} + +void SSE2EMU_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from) +{ + SSE_XORPS_XMM_to_XMM(to, to); + SSE2EMU_MOVSD_XMM_to_XMM(to, from); +} + +void SSE2EMU_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + MOV32RmtoROffset(EAX, from, offset); + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, EAX); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} + +void SSE2EMU_MOVD_XMM_to_RmOffset(x86IntRegType to, x86SSERegType from, int offset ) +{ + SSE_MOVSS_XMM_to_M32((u32)p, from); + MOV32MtoR(EAX, (u32)p); + MOV32RtoRmOffset(to, EAX, offset); +} + +#ifndef __x86_64__ +extern void SetMMXstate(); + +void SSE2EMU_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) +{ + SSE_MOVLPS_XMM_to_M64((u32)p, from); + MOVQMtoR(to, (u32)p); + SetMMXstate(); +} + +void SSE2EMU_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) +{ + MOVQRtoM((u32)p, from); + SSE_MOVLPS_M64_to_XMM(to, (u32)p); + SetMMXstate(); +} +#endif + +/****************************************************************************/ +/* SSE2 Emulated functions for SSE CPU's by kekko */ +/****************************************************************************/ +void SSE2EMU_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { + MOV32ItoR(EAX, (u32)&p); + MOV32ItoR(EBX, (u32)&p2); + SSE_MOVUPSRtoRm(EAX, from); + + MOV32ItoR(ECX, (u32)imm8); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 2); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 4); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + ADD32ItoR(EBX, 4); + MOV32ItoR(ECX, (u32)imm8); + SHR32ItoR(ECX, 6); + AND32ItoR(ECX, 3); + SHL32ItoR(ECX, 2); + ADD32RtoR(ECX, EAX); + MOV32RmtoR(ECX, ECX); + MOV32RtoRm(EBX, ECX); + + SUB32ItoR(EBX, 12); + + SSE_MOVUPSRmtoR(to, EBX); +} + +void SSE2EMU_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { + MOV32ItoR(to, (u32)&p); + SSE_MOVUPSRtoRm(to, from); + MOV32RmtoR(to, to); +} + +#ifndef __x86_64__ +extern void SetFPUstate(); +extern void _freeMMXreg(int mmxreg); +#endif + +void SSE2EMU_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { +#ifndef __x86_64__ + SetFPUstate(); + _freeMMXreg(7); +#endif + SSE_MOVAPS_XMM_to_M128((u32)f, from); + + FLD32((u32)&f[0]); + FISTP32((u32)&p2[0]); + FLD32((u32)&f[1]); + FISTP32((u32)&p2[1]); + FLD32((u32)&f[2]); + FISTP32((u32)&p2[2]); + FLD32((u32)&f[3]); + FISTP32((u32)&p2[3]); + + SSE_MOVAPS_M128_to_XMM(to, (u32)p2); +} + +void SSE2EMU_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { +#ifndef __x86_64__ + SetFPUstate(); + _freeMMXreg(7); +#endif + FILD32((u32)from); + FSTP32((u32)&f[0]); + FILD32((u32)from+4); + FSTP32((u32)&f[1]); + FILD32((u32)from+8); + FSTP32((u32)&f[2]); + FILD32((u32)from+12); + FSTP32((u32)&f[3]); + + SSE_MOVAPS_M128_to_XMM(to, (u32)f); +} + +void SSE2EMU_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { + MOV32ItoR(EAX, (u32)&p); + SSE_MOVUPSRtoRm(EAX, from); + MOV32RmtoR(EAX, EAX); + MOV32RtoM(to, EAX); +} + +void SSE2EMU_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { + MOV32ItoM((u32)p+4, 0); + MOV32ItoM((u32)p+8, 0); + MOV32RtoM((u32)p, from); + MOV32ItoM((u32)p+12, 0); + SSE_MOVAPS_M128_to_XMM(to, (u32)p); +} + +#endif diff --git a/pcsx2/xmlpatchloader.cpp b/pcsx2/xmlpatchloader.cpp new file mode 100644 index 0000000..0dc18d1 --- /dev/null +++ b/pcsx2/xmlpatchloader.cpp @@ -0,0 +1,376 @@ +#include +#include +#include +#include + +using namespace std; +extern "C" int g_ZeroGSOptions; + +#include "tinyxml/tinyxml.h" + +extern "C" { +# include "PS2Etypes.h" +# include "Patch.h" + +# ifdef _WIN32 +# include + struct AppData { + HWND hWnd; // Main window handle + HINSTANCE hInstance; // Application instance + HMENU hMenu; // Main window menu + HANDLE hConsole; + } extern gApp; +# endif + + void SysPrintf(char *fmt, ...); + int LoadPatch(char *patchfile); +} + +#if !defined(_WIN32) && !defined(__MINGW32__) +#ifndef strnicmp +#define strnicmp strncasecmp +#endif + +#ifndef stricmp +#define stricmp strcasecmp +#endif +#endif + +#include "../cheatscpp.h" + +int LoadGroup(TiXmlNode *group, int parent); + +Group::Group(int nParent,bool nEnabled, string &nTitle): + parentIndex(nParent),enabled(nEnabled),title(nTitle) +{ +} + +Patch::Patch(int patch, int grp, bool en, string &ttl): + title(ttl), + group(grp), + enabled(en), + patchIndex(patch) +{ +} + +Patch Patch::operator =(const Patch&p) +{ + title.assign(p.title); + group=p.group; + enabled=p.enabled; + patchIndex=p.patchIndex; + return *this; +} + + +vector groups; +vector patches; + +int LoadPatch(char *crc) +{ + char pfile[256]; + sprintf(pfile,"patches\\%s.xml",crc); + + patchnumber=0; + + TiXmlDocument doc( pfile ); + bool loadOkay = doc.LoadFile(); + if ( !loadOkay ) + { + SysPrintf("XML Patch Loader: Could not load file '%s'. Error='%s'.\n", pfile, doc.ErrorDesc() ); + return -1; + } + + TiXmlNode *root = doc.FirstChild("GAME"); + if(!root) + { + SysPrintf("XML Patch Loader: Root node is not GAME, invalid patch file.\n"); + return -1; + } + + TiXmlElement *rootelement = root->ToElement(); + + const char *title=rootelement->Attribute("title"); + if(title) + SysPrintf("XML Patch Loader: Game Title: %s\n",title); + + int result=LoadGroup(root,-1); + if(result) { + patchnumber=0; + return result; + } + +#ifdef _WIN32 + if (gApp.hConsole) + { + if(title) + SetConsoleTitle(title); + else + SetConsoleTitle(""); + } + +#endif + + return 0; +} + + +int LoadGroup(TiXmlNode *group,int gParent) +{ + + TiXmlElement *groupelement = group->ToElement(); + + const char *gtitle=groupelement->Attribute("title"); + if(gtitle) + SysPrintf("XML Patch Loader: Group Title: %s\n",gtitle); + + const char *enable=groupelement->Attribute("enabled"); + bool gEnabled=true; + if(enable) + { + if(strcmp(enable,"false")==0) + { + SysPrintf("XML Patch Loader: Group is disabled.\n"); + gEnabled=false; + } + } + + TiXmlNode *comment = group->FirstChild("COMMENT"); + if(comment) + { + TiXmlElement *cmelement = comment->ToElement(); + const char *comment = cmelement->GetText(); + if(comment) + SysPrintf("XML Patch Loader: Group Comment:\n%s\n---\n",comment); + } + + string t; + + if(gtitle) + t.assign(gtitle); + else + t.clear(); + + Group gp=Group(gParent,gEnabled,t); + groups.push_back(gp); + + int gIndex=groups.size()-1; + + +#ifndef PCSX2_NORECBUILD + // only valid for recompilers + TiXmlNode *fastmemory=group->FirstChild("FASTMEMORY"); + if(fastmemory!=NULL) + SetFastMemory(1); +#endif + + TiXmlNode *zerogs=group->FirstChild("ZEROGS"); + if(zerogs!=NULL) + { + TiXmlElement *rm=zerogs->ToElement(); + const char* pid = rm->FirstAttribute()->Value(); + if( pid != NULL ) sscanf(pid, "%x", &g_ZeroGSOptions); + else SysPrintf("zerogs attribute wrong"); + } + + TiXmlNode *roundmode=group->FirstChild("ROUNDMODE"); + if(roundmode!=NULL) + { + int eetype=0x0000; + int vutype=0x6000; + + TiXmlElement *rm=roundmode->ToElement(); + if(rm!=NULL) + { + const char *eetext=rm->Attribute("ee"); + const char *vutext=rm->Attribute("vu"); + + if(eetext != NULL) { + eetype = 0xffff; + if( stricmp(eetext, "near") == 0 ) { + eetype = 0x0000; + } + else if( stricmp(eetext, "down") == 0 ) { + eetype = 0x2000; + } + else if( stricmp(eetext, "up") == 0 ) { + eetype = 0x4000; + } + else if( stricmp(eetext, "chop") == 0 ) { + eetype = 0x6000; + } + } + + if(vutext != NULL) { + vutype = 0xffff; + if( stricmp(vutext, "near") == 0 ) { + vutype = 0x0000; + } + else if( stricmp(vutext, "down") == 0 ) { + vutype = 0x2000; + } + else if( stricmp(vutext, "up") == 0 ) { + vutype = 0x4000; + } + else if( stricmp(vutext, "chop") == 0 ) { + vutype = 0x6000; + } + } + } + if(( eetype == 0xffff )||( vutype == 0xffff )) { + printf("XML Patch Loader: WARNING: Invalid value in ROUNDMODE.\n"); + } + else { + SetRoundMode(eetype,vutype); + } + } + + TiXmlNode *cpatch = group->FirstChild("PATCH"); + while(cpatch) + { + TiXmlElement *celement = cpatch->ToElement(); + if(!celement) + { + SysPrintf("XML Patch Loader: ERROR: Couldn't convert node to element.\n" ); + return -1; + } + + + const char *ptitle=celement->Attribute("title"); + const char *penable=celement->Attribute("enabled"); + const char *applymode=celement->Attribute("applymode"); + const char *place=celement->Attribute("place"); + const char *address=celement->Attribute("address"); + const char *size=celement->Attribute("size"); + const char *value=celement->Attribute("value"); + + if(ptitle) { + SysPrintf("XML Patch Loader: Patch title: %s\n", ptitle); + } + + bool penabled=gEnabled; + if(penable) + { + if(strcmp(penable,"false")==0) + { + SysPrintf("XML Patch Loader: Patch is disabled.\n"); + penabled=false; + } + } + + if(!applymode) applymode="frame"; + if(!place) place="EE"; + if(!address) { + SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain an address.\n"); + return -1; + } + if(!value) { + SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain a value.\n"); + return -1; + } + if(!size) { + SysPrintf("XML Patch Loader: WARNING: Patch doesn't contain the size. Trying to deduce from the value size.\n"); + switch(strlen(value)) + { + case 8: + case 7: + case 6: + case 5: + size="32"; + break; + case 4: + case 3: + size="16"; + break; + case 2: + case 1: + size="8"; + break; + case 0: + size="0"; + break; + default: + size="64"; + break; + } + } + + if(strcmp(applymode,"startup")==0) + { + patch[patchnumber].placetopatch=0; + } else + if(strcmp(applymode,"vsync")==0) + { + patch[patchnumber].placetopatch=1; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid applymode attribute.\n"); + patchnumber=0; + return -1; + } + + if(strcmp(place,"EE")==0) + { + patch[patchnumber].cpu=1; + } else + if(strcmp(place,"IOP")==0) + { + patch[patchnumber].cpu=2; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid place attribute.\n"); + patchnumber=0; + return -1; + } + + if(strcmp(size,"64")==0) + { + patch[patchnumber].type=4; + } else + if(strcmp(size,"32")==0) + { + patch[patchnumber].type=3; + } else + if(strcmp(size,"16")==0) + { + patch[patchnumber].type=2; + } else + if(strcmp(size,"8")==0) + { + patch[patchnumber].type=1; + } else + { + SysPrintf("XML Patch Loader: ERROR: Invalid size attribute.\n"); + patchnumber=0; + return -1; + } + + sscanf( address, "%X", &patch[ patchnumber ].addr ); + sscanf( value, "%I64X", &patch[ patchnumber ].data ); + + patch[patchnumber].enabled=penabled?1:0; + + string pt; + + if(ptitle) + pt.assign(ptitle); + else + pt.clear(); + + Patch p=Patch(patchnumber,gIndex,penabled,pt); + patches.push_back(p); + + patchnumber++; + + cpatch = cpatch->NextSibling("PATCH"); + } + + cpatch = group->FirstChild("GROUP"); + while(cpatch) { + int result=LoadGroup(cpatch,gIndex); + if(result) return result; + cpatch = cpatch->NextSibling("GROUP"); + } + + return 0; +} diff --git a/pcsx2/zlib/ChangeLog b/pcsx2/zlib/ChangeLog new file mode 100644 index 0000000..85b8253 --- /dev/null +++ b/pcsx2/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Lvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/pcsx2/zlib/Makefile.am b/pcsx2/zlib/Makefile.am new file mode 100644 index 0000000..ff26496 --- /dev/null +++ b/pcsx2/zlib/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libpcsx2zlib.a + +libpcsx2zlib_a_SOURCES = \ +adler32.c crc32.c deflate.h inffast.c inflate.c inftrees.h trees.h zlib.h \ +crc32.h gzio.c inffast.h inflate.h uncompr.c zutil.c \ +compress.c deflate.c infback.c inffixed.h inftrees.c trees.c zconf.h zutil.h diff --git a/pcsx2/zlib/README b/pcsx2/zlib/README new file mode 100644 index 0000000..718aab2 --- /dev/null +++ b/pcsx2/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/pcsx2/zlib/adler32.c b/pcsx2/zlib/adler32.c new file mode 100644 index 0000000..bc0842f --- /dev/null +++ b/pcsx2/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/pcsx2/zlib/compress.c b/pcsx2/zlib/compress.c new file mode 100644 index 0000000..e7ea2c5 --- /dev/null +++ b/pcsx2/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/pcsx2/zlib/crc32.c b/pcsx2/zlib/crc32.c new file mode 100644 index 0000000..aa8b984 --- /dev/null +++ b/pcsx2/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/pcsx2/zlib/crc32.h b/pcsx2/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/pcsx2/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/pcsx2/zlib/deflate.c b/pcsx2/zlib/deflate.c new file mode 100644 index 0000000..efe7b63 --- /dev/null +++ b/pcsx2/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/pcsx2/zlib/deflate.h b/pcsx2/zlib/deflate.h new file mode 100644 index 0000000..26775e9 --- /dev/null +++ b/pcsx2/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/pcsx2/zlib/gzio.c b/pcsx2/zlib/gzio.c new file mode 100644 index 0000000..4cfd64f --- /dev/null +++ b/pcsx2/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/pcsx2/zlib/infback.c b/pcsx2/zlib/infback.c new file mode 100644 index 0000000..5cf5d22 --- /dev/null +++ b/pcsx2/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/pcsx2/zlib/inffast.c b/pcsx2/zlib/inffast.c new file mode 100644 index 0000000..63aa440 --- /dev/null +++ b/pcsx2/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/pcsx2/zlib/inffast.h b/pcsx2/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/pcsx2/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/pcsx2/zlib/inffixed.h b/pcsx2/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/pcsx2/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/pcsx2/zlib/inflate.c b/pcsx2/zlib/inflate.c new file mode 100644 index 0000000..71fe3cc --- /dev/null +++ b/pcsx2/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/pcsx2/zlib/inflate.h b/pcsx2/zlib/inflate.h new file mode 100644 index 0000000..b696512 --- /dev/null +++ b/pcsx2/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/pcsx2/zlib/inftrees.c b/pcsx2/zlib/inftrees.c new file mode 100644 index 0000000..55fd27b --- /dev/null +++ b/pcsx2/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/pcsx2/zlib/inftrees.h b/pcsx2/zlib/inftrees.h new file mode 100644 index 0000000..1dbfe53 --- /dev/null +++ b/pcsx2/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/pcsx2/zlib/trees.c b/pcsx2/zlib/trees.c new file mode 100644 index 0000000..d0bce9f --- /dev/null +++ b/pcsx2/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/pcsx2/zlib/trees.h b/pcsx2/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/pcsx2/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/pcsx2/zlib/uncompr.c b/pcsx2/zlib/uncompr.c new file mode 100644 index 0000000..82ebef7 --- /dev/null +++ b/pcsx2/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/pcsx2/zlib/zconf.h b/pcsx2/zlib/zconf.h new file mode 100644 index 0000000..b073c9e --- /dev/null +++ b/pcsx2/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/pcsx2/zlib/zlib.h b/pcsx2/zlib/zlib.h new file mode 100644 index 0000000..d54ac94 --- /dev/null +++ b/pcsx2/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/pcsx2/zlib/zutil.c b/pcsx2/zlib/zutil.c new file mode 100644 index 0000000..db137f8 --- /dev/null +++ b/pcsx2/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/pcsx2/zlib/zutil.h b/pcsx2/zlib/zutil.h new file mode 100644 index 0000000..e300f7c --- /dev/null +++ b/pcsx2/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/build.sh b/plugins/build.sh new file mode 100644 index 0000000..bb2ab17 --- /dev/null +++ b/plugins/build.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +curdir=`pwd` + +cd ${curdir}/gs +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/cdvd +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/dev9 +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/fw +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/pad +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/spu2 +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/usb +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi diff --git a/plugins/cdvd/CDVDbin/CDVDbin.dll b/plugins/cdvd/CDVDbin/CDVDbin.dll new file mode 100644 index 0000000000000000000000000000000000000000..3b2e798e60eeb8c459747aaaa13f211e3f5176da GIT binary patch literal 69632 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDbin/readme.ps1.txt b/plugins/cdvd/CDVDbin/readme.ps1.txt new file mode 100644 index 0000000..7fd7f29 --- /dev/null +++ b/plugins/cdvd/CDVDbin/readme.ps1.txt @@ -0,0 +1,52 @@ +CDiso FPSE plugin +================= + +This software is distributed "AS IS" and the authors decline all responsability for all damages (hardware, software and economic) derived by the use of this software. + + +What's this? +------------ +This plugin allows you to load in FPSE ISO images of games directly from your hard-disk. +There is no need of any configiration, just select it: when you run FPSE it will pop up a dialog where you can choose the image to load. + + +Install +------- +Put CDiso.dll in the plugin directory of FPSE. +Select the plugin with the FPSE config tool. + + +What's new +---------- +1.0: first release... it compiles & works (at least on my sistem) :-) + + +Known issues +------------ +If you move around the "Select iso" dialog it will close and you will have to restart FPSE. + + +Notes +----- +I'm not an experienced programmer and I don't want to take credit of work that I've not done... +The plugin is _heavily_ based on the sources of CDctrl plugin (I think by LDChen) found on Bero's page (www.geocities.co.jp/Playtown/2004) and on the open source cdriso PSEmu plugin for linux by Linuzappz. +They've done most of the work, I've introduced most of the bugs ;-) + + +Sources +------- +I've decided to release the sources of the plugin and you should have found them togheter with the dll and this readme. +The sources are not covered by any license so you can do with them whatever you want, but if you find a bug or implement a new feature it would be very nice if you let me know and if you help me to improve this plugin instead of starting another one... This is the best I can do at the moment and having some feedback would help me to learn programming better! + +To compile you'll need the FPSE SDK that can be found at the FPSE site: +http://fpse.emuunlim.com + + +Thanks to the FPSE team and to all the PSX emulation scene. + + +_xobro_@tin.it + + + + diff --git a/plugins/cdvd/CDVDbin/readme.txt b/plugins/cdvd/CDVDbin/readme.txt new file mode 100644 index 0000000..ba5ec0a --- /dev/null +++ b/plugins/cdvd/CDVDbin/readme.txt @@ -0,0 +1,94 @@ +CDVDbin v0.67 +--------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Using: +----- + Place the file "CDVDbin.dll" in the Plugins directory + of the Emulator to use it. + If you have a cdaudio image, go to config dialog of the plugin and check + "Force CD Audio on detection failure". CDDA support is limmited in this + version. + +Note: +----- +-I'm using a method for detection of images that can lead to misdetections. + So, if the plugin shows a dialog box that says that the image is an ISO + and you KNOW it is a BIN (2352 bytes/sector) or BIN that is in fact an ISO, + please notice me. +-The detection might work on some other image formats. You can check the + "Debug messages" box in config dialog and then open the image using + "All files" filter. If the image works and it is not a *known* type, + please notice me. +-Officialy known types: (bytes/sec) + bin(+cue), //2352 + toc info file + iso, //2048 (it is not recommended to use such) + img(+ccd+sub), //2352 + toc info file + subchannel file + bwi, //2353 (i don't know much about this type) + mdf(+mds), //2352/2448 + toc info file (2448-2352=96 => full subchannel) + nrg //2048/2352/2448 as mdf type, the subq info is in the file, + at the end of the image there are toc infos +-A splitted image is a sequence of files that have a common name and a trailing + number. The number starts from 0 or 1. To choose such an image in Open dialog, + select "All Files" filter and pick one of the splits. + +Thanks: +------ + Xobro, this is a port of his FPSE cd plugin + Linuzappz + +Changes: +------- + v0.67: + * Up to date to the latest CDVD specs v3 (0.4.3) + * Bugfix for small files + + v0.66: + * Added "All Files" filter + * Added some CDDA support :P + * Support for splitted image files + * Support for *.mds + + v0.65: + * Up to date to the latest CDVD specs v2 (0.4.0) + * Added support for RAW+SUBQ images (2352+96=2448 bytes/sector) + * Easier detection, ready for subq;) + + v0.64: + * Up to date to the latest CDVD specs + * Better detection of images (ISO2048/RAW2352) + This allows one to use an incomplete/bad image + * Added *.nrg support (Nero images) + + v0.63: + * Added *.bwi to open dialog (Blind Write images) + + v0.62: + * Small fix to file pointer in order to handle + big files (64bit pointer). (hi bositman;) + + v0.61: + * Added *.img to open dialog (CloneCD images) + + v0.6: + * Changed for PS2E Definitions v0.2.9 (beta) specs; CDVDopen() + * Fixed OFN_NOCHANGEDIR issue; thx linuzappz;) + + v0.5: + * Added a config dialog + + v0.4: + + v0.3: + * Automatic iso/bin detection + + v0.2: + + v0.1: + * First Release/Port + * Tested with Pcsx2 + + Email: diff --git a/plugins/cdvd/CDVDbin/src/CDVD.h b/plugins/cdvd/CDVDbin/src/CDVD.h new file mode 100644 index 0000000..41179fb --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVD.h @@ -0,0 +1,90 @@ +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#include + +#define CDVDdefs +#include "PS2Edefs.h" + +/* some structs from libcdvd by Hiryu & Sjeep (C) 2002 */ + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +#endif /* __CDVD_H__ */ \ No newline at end of file diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.c b/plugins/cdvd/CDVDbin/src/CDVDbin.c new file mode 100644 index 0000000..18be273 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.c @@ -0,0 +1,679 @@ + /****************************************************************************\ + * CDVDbin PLUGIN for PS2 emus (PCSX2) based on + * CDiso PLUGIN for FPSE + * + * + * AUTHOR: Xobro, mail: _xobro_@tin.it + * + * WHAT'S NEW: It compiles and it seems to work! ;-) + * + * TO DO: cue/ccd reading; tracks stuff; + * subchannel reading + * registry or ini save of iso/bin name + * detection of other types of CD/DVD + * proper audio support + * + * PORTED BY FLORIN + * +\****************************************************************************/ + +#include +#include +#include + +#include "CDVD.h" +#include "resource.h" + +///////////////////////////////////////////////////////////////// +// Internal variables & defines +///////////////////////////////////////////////////////////////// +#define OpenFile(a) CreateFile(a, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,\ + NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) + +static HANDLE hinstance = (HANDLE)-1; + +#define RAW_SECTOR_SIZE 2352 +#define DATA_SECTOR_SIZE 2048 // not used at the moment +#define RAWQ_SECTOR_SIZE (RAW_SECTOR_SIZE+96) +//#define ?_SECTOR_SIZE (RAW_SECTOR_SIZE+16) + +//#define MSF2SECT(m,s,f) (((m)*60+(s)-2)*75+(f)) + +#define INT2BCD(a) ((a)/10*16+(a)%10) + +static HANDLE hISOFile; + +#define MAXFILENAMELENGHT 512 +char ISOFileName[MAXFILENAMELENGHT] = {0}, format[MAXFILENAMELENGHT] = {0}; + +static int sectorsize, //0==2048; 1==2352; 2==2448 + offset, cdtype, cdtraystatus, debug=0, forcecdda=0; + +static u8 readBuffer[RAWQ_SECTOR_SIZE], *pbuffer, *subqbuffer; +static u32 first, last, crt; +static __int64 unitsize; +static cdvdTN diskInfo={0, 0}; +static cdvdTD tracks[100]; + +s32 msf_to_lba(u8 m, u8 s, u8 f) { + u32 lsn; + lsn = f; + lsn+=(s - 2) * 75; + lsn+= m * 75 * 60; + return lsn; +} + +void lba_to_msf(s32 lba, u8* m, u8* s, u8* f) { + lba += 150; + *m = lba / (60*75); + *s = (lba / 75) % 60; + *f = lba % 75; +} + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + +///////////////////////////////////////////////////////////////// +// generic plugin stuff +///////////////////////////////////////////////////////////////// +const unsigned char version = PS2E_CDVD_VERSION; // CDVD library v2 +const unsigned char revision = VERSION; +const unsigned char build = BUILD; // increase that with each version + +static char *libraryName = "CDVDbin Driver"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_CDVD; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return version<<16|revision<<8|build; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "CDVDbin Msg", 0); +} + +///////////////////////////////////////////////////////////////// +// CDVDinit: plugin init +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDinit() { + //some defaults + hISOFile = NULL; + cdtype=CDVD_TYPE_NODISC; // no image loaded + cdtraystatus=CDVD_TRAY_OPEN; // no image loaded + sectorsize=0; // *bad* value + offset=0; // no offset in the file + // till the beginning of the data + return 0; +} + +HANDLE detectMultipleSplits(__int64 *filesize){ + __int64 size; + HANDLE h; + int len, filenamelen=strlen(ISOFileName); + + first=last=0; + + for (len=filenamelen; len && ISOFileName[len-1]>='0' && ISOFileName[len-1]<='9'; len--); + ISOFileName[len]=0; + len=filenamelen-len; + if (len){ + sprintf(format, "%s%%0%dd", ISOFileName, len); + + for (first=0; first<2; first++){//check for first if it is 0 or 1 + sprintf(ISOFileName, format, first); + if ((h = OpenFile(ISOFileName)) != INVALID_HANDLE_VALUE){ + for (last=first; h != INVALID_HANDLE_VALUE; h = OpenFile(ISOFileName)){ + (*(u32*)(&size))=GetFileSize(h, ((u32*)(&size))+1); + *filesize+=size; + CloseHandle(h); + sprintf(ISOFileName, format, ++last); + } + last--; + if (last>first && debug) + SysMessage("Found multiple files (%d->%d) with format:\n\"%s\"\n" + "Total size=%I64d / Unit size=%I64d", + first, last, format, *filesize, (*filesize-size)/(last-first)); + break; + } + } + if (first == 2) return INVALID_HANDLE_VALUE; + }else + strcpy(format, ISOFileName); + + sprintf(ISOFileName, format, crt=first); + return OpenFile(ISOFileName); +} + +int detect(__int64 filesize){ + register struct cdVolDesc *volDesc; + register u32 sectors; + + if (CDVDreadTrack(16, CDVD_MODE_2048) == -1) { + SysMessage("file too small"); + return CDVD_TYPE_ILLEGAL; + } + volDesc = (struct cdVolDesc *)CDVDgetBuffer(); + if (memcmp(volDesc->volID, "CD001", 5)) + return CDVD_TYPE_DETCT; + + if (memcmp(volDesc->sysIdName, "PLAYSTATION", 11)) + SysMessage("Warrning: Not a Playstation disc?"); + + sectors=(u32)(filesize / sectorsize); + + diskInfo.strack =1; + diskInfo.etrack =1; + memset(tracks, 0, sizeof(cdvdTD) * 100); + tracks[0].lsn=sectors-offset; + tracks[0].type =(volDesc->rootToc.tocSize == DATA_SECTOR_SIZE) ? + CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD; //simple & lame detection:p + + tracks[1].lsn=0; + tracks[1].type =CDVD_MODE2_TRACK; + + if (debug || (filesize % sectorsize)) + SysMessage("%s (%d bytes/sector - offset=%d) %s %simage detected\n" + "Datasize: %I64d\n" + "Sectors: %d LSN:%d\n%s", + offset ? "NRG" : + sectorsize==DATA_SECTOR_SIZE ? "ISO" : + sectorsize==RAW_SECTOR_SIZE ? "RAW" : "RAW+SUBQ", + sectorsize, offset, + volDesc->rootToc.tocSize == DATA_SECTOR_SIZE ? "CD" : "DVD", + last>first ? "splitted " : "", + filesize, sectors, + tracks[0].lsn, + filesize % sectorsize ? "Warrning: Truncated!" : ""); + + return tracks[0].type; +} + +///////////////////////////////////////////////////////////////// +// CDVDopen: CD hw init +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDopen() { + __int64 filesize=0; + + OPENFILENAME ofn = {sizeof(OPENFILENAME), // size + NULL, // owner + NULL, // hInstance + "CD/DVD images (*.bin;*.iso;*.img;*.bwi;*.mdf;*.nrg)\0*.bin;*.iso;*.img;*.bwi;*.mdf;*.nrg\0" + "RAW(2352) CD/DVD images (*.bin;*.img;*.bwi;*.mdf)\0*.bin;*.img;*.bwi;*.mdf\0" + "ISO(2048) CD/DVD images (*.iso)\0*.iso\0" + "NERO CD/DVD images (*.nrg)\0*.nrg\0" + "All Files (*.*)\0*.*\0" + ,// filter + 0, // custom filter + 0, // max custom filter + 0, // filter index + (char *)&ISOFileName, // file name + MAXFILENAMELENGHT, // max filename lenght + 0, // file title + 0, // max file title + NULL, // initial dir + "Select a CD/DVD image...", // title + OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,// flags + 0, // file offset + 0, // file extension + 0, // def ext + 0, // cust data + 0, // hook + 0}; // template + + //clean any old stuff + if (hISOFile){ + CloseHandle(hISOFile); + hISOFile = NULL; + } + + cdtype=CDVD_TYPE_NODISC; // no image loaded + cdtraystatus=CDVD_TRAY_OPEN; // no image loaded + + if (!ISOFileName[0]) + if(!GetOpenFileName(&ofn)) //Common open file dialog + return 0; + //no image/dusc loaded => null plugin + + //detect & open the selected file (or first if more than 1) + hISOFile = detectMultipleSplits(&filesize); + + cdtraystatus=CDVD_TRAY_CLOSE; + cdtype=CDVD_TYPE_UNKNOWN; + + if (hISOFile == INVALID_HANDLE_VALUE){ + SysMessage("error opening the file\n"); + cdtype=CDVD_TYPE_ILLEGAL; + return 0; + } + + (*(u32*)(&unitsize))=GetFileSize(hISOFile, ((u32*)(&unitsize))+1); + if (!filesize) filesize=unitsize;//in case of non-splitted images + + sectorsize=DATA_SECTOR_SIZE; offset=0; //ISO 2048 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + sectorsize=RAW_SECTOR_SIZE; offset=0; //RAW 2352 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + sectorsize=RAWQ_SECTOR_SIZE; offset=0; //RAWQ 2448 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + filesize-=156;//ending junk + + sectorsize=DATA_SECTOR_SIZE; offset=150; //NERO ISO 2048 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + sectorsize=RAW_SECTOR_SIZE; offset=150; //NERO RAW 2352 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + sectorsize=RAWQ_SECTOR_SIZE; offset=150; //NERO RAWQ 2448 detection + cdtype=detect(filesize); + if (cdtype!=CDVD_TYPE_DETCT) return 0; + + if (forcecdda && (filesize>RAW_SECTOR_SIZE)){ + u32 sectors=(u32)(filesize/(sectorsize=RAW_SECTOR_SIZE)); + offset=0; //FIXME: offset for nero images + + memset(tracks, 0, sizeof(cdvdTD) * 100); + diskInfo.strack =1; + diskInfo.etrack =1; + tracks[0].lsn=sectors-offset; + tracks[0].type =cdtype=CDVD_TYPE_CDDA;//DVDV; + + tracks[1].lsn=0; + tracks[1].type =CDVD_AUDIO_TRACK; + + if (debug) + SysMessage("CDDA (%d bytes/sector - offset=%d) image\n" + "Datasize: %I64d\n" + "Sectors: %d LSN:%d\n", + sectorsize, offset, + filesize, sectors, + tracks[0].lsn); + return 0; + } + + //nothing detected + SysMessage("The file you picked is not a usable cd/dvd image\n"); + CloseHandle(hISOFile); + hISOFile=NULL; + cdtraystatus=CDVD_TRAY_OPEN; + cdtype=CDVD_TYPE_NODISC; + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDclose: CD shutdown +///////////////////////////////////////////////////////////////// +void CALLBACK CDVDclose() { + CloseHandle(hISOFile); + CDVDinit(); +} + +///////////////////////////////////////////////////////////////// +// CDVDshutdown: plugin shutdown +///////////////////////////////////////////////////////////////// +void CALLBACK CDVDshutdown() { +} + +///////////////////////////////////////////////////////////////// +// CDVDreadTrack: read 1(one) sector/frame (2352 bytes) +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + u32 nbytesRead, chunk; + s32 Ret; + __int64 filepos; + + pbuffer = readBuffer; + subqbuffer = readBuffer+RAW_SECTOR_SIZE; + + memset(readBuffer, 0, RAWQ_SECTOR_SIZE); + + //if no iso selected act as a null CD plugin + if (hISOFile == NULL) + return 0; + + // Set the file pointer at the right sector + filepos=(__int64)(lsn+offset)*sectorsize; + chunk=(u32)(filepos / unitsize); + filepos-=chunk * unitsize; + chunk+=first; + if (chunk!=crt){ + crt=chunk; + CloseHandle(hISOFile); + sprintf(ISOFileName, format, crt); + hISOFile=OpenFile(ISOFileName); + } + SetFilePointer (hISOFile, + *(u32*)(&filepos), + ((u32*)(&filepos))+1, + FILE_BEGIN); + + Ret = ReadFile(hISOFile, + readBuffer+(sectorsize==DATA_SECTOR_SIZE?12+12:0), + sectorsize, &nbytesRead, NULL); + + if (Ret && nbytesRead < (u32)sectorsize && crtctrl = 4; + subq->mode = 1; + subq->trackNum = itob(1); + subq->trackIndex= itob(1); + + lba_to_msf(lsn, &min, &sec, &frm); + subq->trackM = itob(min); + subq->trackS = itob(sec); + subq->trackF = itob(frm); + + subq->pad = 0; + + lba_to_msf(lsn + (2*75), &min, &sec, &frm); + subq->discM = itob(min); + subq->discS = itob(sec); + subq->discF = itob(frm); + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDgetTN: tracks number +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + //if no iso selected act as a null CD plugin + if (hISOFile == NULL){ + Buffer->strack = 1; + Buffer->etrack = 1; + return 0; + } + + //should be read from .cue + memcpy(Buffer, &diskInfo, sizeof(cdvdTN)); + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDgetTD: track start end addresses +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer) { + //if no iso selected act as a null CD plugin + if (hISOFile == NULL) + return -1; + + if (Track>diskInfo.etrack) + return -1; + + memcpy(Buffer, &tracks[Track], sizeof(cdvdTD)); + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDgetTOC: get comlpete toc +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDgetTOC(void* toc) { + u8 type = CDVDgetDiskType(); + u8* tocBuff = (u8*)toc; + + if( type == CDVD_TYPE_DVDV || + type == CDVD_TYPE_PS2DVD) + { + // get dvd structure format + // scsi command 0x43 + memset(tocBuff, 0, 2048); + // fake it + tocBuff[ 0] = 0x04; + tocBuff[ 1] = 0x02; + tocBuff[ 2] = 0xF2; + tocBuff[ 3] = 0x00; + tocBuff[ 4] = 0x86; + tocBuff[ 5] = 0x72; + + tocBuff[16] = 0x00; + tocBuff[17] = 0x03; + tocBuff[18] = 0x00; + tocBuff[19] = 0x00; + } + else if(type == CDVD_TYPE_CDDA || + type == CDVD_TYPE_PS2CDDA || + type == CDVD_TYPE_PS2CD || + type == CDVD_TYPE_PSCDDA || + type == CDVD_TYPE_PSCD) + { + // cd toc + // (could be replaced by 1 command that reads the full toc) + u8 min, sec, frm; + s32 i, err; + cdvdTN diskInfo; + cdvdTD trackInfo; + memset(tocBuff, 0, 1024); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + tocBuff[0] = 0x41; + tocBuff[1] = 0x00; + + //Number of FirstTrack + tocBuff[2] = 0xA0; + tocBuff[7] = itob(diskInfo.strack); + + //Number of LastTrack + tocBuff[12] = 0xA1; + tocBuff[17] = itob(diskInfo.etrack); + + //DiskLength + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[22] = 0xA2; + tocBuff[27] = itob(min); + tocBuff[28] = itob(sec); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) + { + err = CDVDgetTD(i, &trackInfo); + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[i*10+30] = trackInfo.type; + tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number + tocBuff[i*10+37] = itob(min); + tocBuff[i*10+38] = itob(sec); + tocBuff[i*10+39] = itob(frm); + } + } + else + return -1; + + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDgetDiskType: type of the disc: CD/DVD +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDgetDiskType() { + if (debug) SysMessage("CDVDgetType() == %02X", cdtype); + return cdtype; +} + +///////////////////////////////////////////////////////////////// +// CDVDgetTrayStatus: the status of the tray +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDgetTrayStatus() { + if (debug) SysMessage("CDVDgetTrayStatus() == %02X", cdtraystatus); + return cdtraystatus; +} + +///////////////////////////////////////////////////////////////// +// CDVDctrlTrayOpen: open the disc tray +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDctrlTrayOpen() { + return 0; +} + +///////////////////////////////////////////////////////////////// +// CDVDctrlTrayClose: close the disc tray +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDctrlTrayClose() { + return 0; +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + OPENFILENAME ofn = {sizeof(OPENFILENAME), // size + NULL, // owner + NULL, // hInstance + "CD/DVD images (*.bin;*.iso;*.img;*.bwi;*.mdf;*.nrg)\0*.bin;*.iso;*.img;*.bwi;*.mdf;*.nrg\0" + "RAW(2352) CD/DVD images (*.bin;*.img;*.bwi;*.mdf)\0*.bin;*.img;*.bwi;*.mdf\0" + "ISO(2048) CD/DVD images (*.iso)\0*.iso\0" + "NERO CD/DVD images (*.nrg)\0*.nrg\0" + "All Files (*.*)\0*.*\0" + ,// filter + 0, // custom filter + 0, // max custom filter + 0, // filter index + (char *)&ISOFileName, // file name + MAXFILENAMELENGHT, // max filename lenght + 0, // file title + 0, // max file title + NULL, // initial dir + "Select a CD/DVD image...",// title + OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,// flags + 0, // file offset + 0, // file extension + 0, // def ext + 0, // cust data + 0, // hook + 0}; // template + + switch(uMsg) { + case WM_INITDIALOG: + CheckDlgButton(hW, IDC_DEBUG, debug ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hW, IDC_CDDA, forcecdda ? BST_CHECKED : BST_UNCHECKED); + if (ISOFileName && *ISOFileName){ + SetDlgItemText(hW, IDC_FILE, ISOFileName); + CheckDlgButton(hW, IDC_FILE, BST_CHECKED); + }else + CheckDlgButton(hW, IDC_FILE, BST_UNCHECKED); + return TRUE; + + case WM_COMMAND: + switch(HIWORD(wParam)){ + case BN_CLICKED: + switch(LOWORD(wParam)) { + case IDC_FILE: + if (!IsDlgButtonChecked(hW, IDC_FILE)){ + CheckDlgButton(hW, IDC_FILE, BST_UNCHECKED); + ISOFileName[0]='\0'; + SetDlgItemText(hW, IDC_FILE, "Choose a CD/DVD bin or iso image..."); + }else{ + if (GetOpenFileName(&ofn)){ + CheckDlgButton(hW, IDC_FILE, BST_CHECKED); + SetDlgItemText(hW, IDC_FILE, ISOFileName); + }else + CheckDlgButton(hW, IDC_FILE, BST_UNCHECKED); + } + return TRUE; + + case IDOK: + debug=IsDlgButtonChecked(hW, IDC_DEBUG); + forcecdda=IsDlgButtonChecked(hW, IDC_CDDA); + EndDialog(hW, FALSE); + return TRUE; + } + } + + } + return FALSE; +} + +///////////////////////////////////////////////////////////////// +// CDVDconfigure: config dialog, if any... +///////////////////////////////////////////////////////////////// +void CALLBACK CDVDconfigure(){ + DialogBox(hinstance, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +///////////////////////////////////////////////////////////////// +// CDVDabout: about dialog, if any... +///////////////////////////////////////////////////////////////// +void CALLBACK CDVDabout() { + SysMessage("%s %d.%d\n" + "PS1 version by: Xobro, mail: _xobro_@tin.it\n" + "PS2 version by: Florin, mail: florin@ngemu.com", libraryName, revision, build); +} + +///////////////////////////////////////////////////////////////// +// CDVDtest: test hw and report if it works +///////////////////////////////////////////////////////////////// +s32 CALLBACK CDVDtest() { + FILE *f; + + if (cdtype==CDVD_TYPE_ILLEGAL) + return -1; + + if (*ISOFileName == 0) + return 0; + + f = fopen(ISOFileName, "rb"); + if (f == NULL) + return -1; + fclose(f); + + return 0; //if (sectorsize==2048) return 40;//PSE_CDR_WARN_LAMECD; +} + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved){ + hinstance = (HINSTANCE)hModule; + return TRUE; +} diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.def b/plugins/cdvd/CDVDbin/src/CDVDbin.def new file mode 100644 index 0000000..5264ca2 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.def @@ -0,0 +1,29 @@ +; CDVDbin.def : Declares the module parameters for the DLL. + +LIBRARY "CDVDbin" +DESCRIPTION 'CDVD BIN/ISO Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + CDVDinit @5 + CDVDshutdown @6 + CDVDopen @7 + CDVDclose @8 + CDVDreadTrack @9 + CDVDgetBuffer @10 + CDVDreadSubQ @11 + CDVDgetTN @12 + CDVDgetTD @13 + CDVDgetTOC @14 + CDVDgetDiskType @15 + CDVDgetTrayStatus @16 + CDVDctrlTrayOpen @17 + CDVDctrlTrayClose @18 + + CDVDconfigure @19 + CDVDtest @20 + CDVDabout @21 + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.dsp b/plugins/cdvd/CDVDbin/src/CDVDbin.dsp new file mode 100644 index 0000000..64d8708 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="CDVDbin" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=CDVDBIN - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "CDVDbin.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "CDVDbin.mak" CFG="CDVDBIN - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "CDVDbin - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "CDVDbin - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "CDVDbin - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDBIN_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDBIN_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=67 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\CDVDbin.dll" + +!ELSEIF "$(CFG)" == "CDVDbin - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "CDVDbin___Win32_Debug" +# PROP BASE Intermediate_Dir "CDVDbin___Win32_Debug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "CDVDbin___Win32_Debug" +# PROP Intermediate_Dir "CDVDbin___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDBIN_EXPORTS" /D "__WIN32__" /FD /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MT /W3 /GX /Od /D "WIN32" /D "DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDBIN_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=67 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"D:\TEMP2\emus\pcsx2.042\Plugins\CDVDbin.dll" +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\CDVDbin.dll" + +!ENDIF + +# Begin Target + +# Name "CDVDbin - Win32 Release" +# Name "CDVDbin - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\CDVDbin.c +# End Source File +# Begin Source File + +SOURCE=.\CDVDbin.def +# End Source File +# Begin Source File + +SOURCE=.\CDVDbin.rc +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="C:\Program Files\Microsoft Visual Studio\Vc98\Include\Basetsd.h" +# End Source File +# Begin Source File + +SOURCE=.\CDVD.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Etypes.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\readme.ps1.txt +# End Source File +# Begin Source File + +SOURCE=..\readme.txt +# End Source File +# End Target +# End Project diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.dsw b/plugins/cdvd/CDVDbin/src/CDVDbin.dsw new file mode 100644 index 0000000..e44885f --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "CDVDbin"=".\CDVDbin.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.ncb b/plugins/cdvd/CDVDbin/src/CDVDbin.ncb new file mode 100644 index 0000000000000000000000000000000000000000..e24d9bc91177ce1670460d38f80b9b57eebe8af8 GIT binary patch literal 52224 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.rc b/plugins/cdvd/CDVDbin/src/CDVDbin.rc new file mode 100644 index 0000000..8503a3d --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.rc @@ -0,0 +1,151 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 266, 68 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Configure CDVDbin" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Close",IDOK,209,47,50,14 + CONTROL "Choose a CD/DVD bin or iso image...",IDC_FILE,"Button", + BS_AUTOCHECKBOX | BS_PUSHLIKE | BS_MULTILINE | + WS_TABSTOP,7,20,252,21 + LTEXT "Click this to choose an image to use or else you will be asked for one at runtime:", + IDC_STATIC,7,7,252,11 + CONTROL "Debug Messages",IDC_DEBUG,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,51,69,10 + CONTROL "Force CD Audio on detection failure",IDC_CDDA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,79,51,125,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 259 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,6,6 + PRODUCTVERSION 1,0,6,6 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "simple and easy bin/iso plugin; thanks Xobro; it is not optimised in either way; it is for testing & to serve as a template\0" + VALUE "CompanyName", "-\0" + VALUE "FileDescription", "CDVDbin\0" + VALUE "FileVersion", "1, 0, 6, 7\0" + VALUE "InternalName", "CDVDbin\0" + VALUE "LegalCopyright", "Copyright 2002-2003\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "CDVDbin.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "CDVDbin/iso plugin for PSX2\0" + VALUE "ProductVersion", "1, 0, 6, 7\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.sln b/plugins/cdvd/CDVDbin/src/CDVDbin.sln new file mode 100644 index 0000000..ab5d55e --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDbin", "CDVDbin.vcproj", "{50921BF5-D9DE-4264-92CF-7001E117CFC3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.ActiveCfg = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.Build.0 = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.ActiveCfg = Release|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.sln.old b/plugins/cdvd/CDVDbin/src/CDVDbin.sln.old new file mode 100644 index 0000000..0e67c48 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.sln.old @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDbin", "CDVDbin.vcproj", "{50921BF5-D9DE-4264-92CF-7001E117CFC3}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.ActiveCfg = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.Build.0 = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.ActiveCfg = Release|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.suo b/plugins/cdvd/CDVDbin/src/CDVDbin.suo new file mode 100644 index 0000000000000000000000000000000000000000..401ec8daa3331d8918a546ba7d14937ed6533632 GIT binary patch literal 8704 zcmeHMOKclO82+84G-=ZG{h&ZGO<$D8IB81LRs}V7l156J5~oQIkt*BSv~C@5u-%uM zN2NvV~)nFhJf(e6Q=s9?EB4Jv%Uo5^IXMiEpO;2zq6 zJK(j>mf<3ll=oub5@0>B0oVv!3Ty%{12zLGbK(Nr+dD8MCVpx0O1C6XCglR8TRyCn zMOm9)UE;IXe*Nf&iElph)MDIaDiL55hV*v_$13-b&Ht_g>JaeXIbMOP@Yd@0FW=7kDth!)cj< zTw+Ql#rW7RHJ&w?k2YH_efsSlAVJ$PWuoia2Wb1JFW?&4&%M^;bh#33tAJb+d07iw z2V4)lAGiU?u@BniMwAcR^+!-{0=57*1GfOT0=EIT10MzM06qrX3Dh*XRze%v+U<6$ zCI9IjpWnOi_Dg^szIvc8&jtAXK41XPG3b0;*&_8mh4-k8%UR$U`hzk8j3}EJLvIqj zV>anr%{l70_~i*{!>IhxPJZXgzn+WslK=+QI*x!l6CNcAOP&-jtSyF>(W8vX0P0cI zpTd|4<$Fiamcq)z80D1^+Rk9rG4y-ICx_vihwxiz(*{?!r#^fBHXKQMvS)M_mRIxZi2eOk&lPeoj*?9Xf@+C`JUp6XUa? zo;jK9!~SzGNt>W1E%9LJr3?t=X&hr>9Q!f>UUJr?-{(UQ=fa1@o%RLRx+-}x9#Vh& zkcA)7Bp?T+Lw2L|yLzJ7FZM)LkEX%z-B50u`@2ftsmp+I^;{=E*SzIHxXxs@*JO`s zpZCA*p|-ErGKb1Gc`jlZe%Tv@UPWPPleT6#b^ZwYQm}zyp1=?NW4>T%UwQh+GX(P$ zLNWR}7Yt(8)4{@Ih-msA5_S zxt#$unt=9O5};SeU*Y}|+Csf*J{dmHs=eNA_am}l1ZmH1z)9Ni>z2DN(`{9o_ zE^UiUcBsbYYa8OX8(Icm$UJxJ`loMpduWAp2l?qGjx&tWQ{Xa%n85Re2Rk{N=05Ee zRtx+;|jVHlg@R9&B$Bsh+ z^wE~zp2?-P4$7$uTu0%tc)~W2RrB^Ej@cUJ3YGM#++92fqq2uX`O z?%0{fU1NRl>!d{BIhMC8<9S?K9%xFffHB6pZ{U9CTY%HH=3gEGte(Ck1uZ5I=WHHl zW|~~dOu+q%GNMZ256|R!Chdor2lMpD%$qW`yfwKf4x~@oG-8&;M_auQq4>lecocFW z)i9)E05v~WT*&3w_V5|SrYhpUbN%@mHe>pd4a=*b@5QWjw&C6z_DFlDJ?2}+eA!%S ze^8kIvFnUy%%>9IusWO9w;I)aujyCok9n`RENGmKMGbGjOr(=$Tq%8BFq~Ey_mX1+ z{oYXYq%o;pmj+|uxOu|cJswM&Nv?ePfEkI!4ezKC@%EU>N%eU{-rJIZIXPt}j6_;> zE**^}#?5o7-0-?X!vp=CtT_;mO-0Oba@;!gyaVT{sFVlf{X6}x21=;|mZE^Dy50kfTDd!=_)!`knrt9xa9JfVX{VsEBEw zT?)~2x39P9)18;QekXk$@A_2sWP+3PZW2Y`*MdGzSF0+Z--)q|*97i=Dl2vFv^x{9 z#ua)p{x_kM>3ucp&*iq(|3A6=#|to8>ZEc!g~;Q~Sh@c1#ccZjpMn!t(4lp&-1R%B e?rT~3%-4&Cx?g;$_gZ|U@20bFq5l8hfqwzgnS!AJ literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj b/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj new file mode 100644 index 0000000..8f3ea90 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj.old b/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj.old new file mode 100644 index 0000000..5f24ecd --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin.vcproj.old @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin_2003.sln b/plugins/cdvd/CDVDbin/src/CDVDbin_2003.sln new file mode 100644 index 0000000..75d28e9 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin_2003.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDbin", "CDVDbin_2003.vcproj", "{50921BF5-D9DE-4264-92CF-7001E117CFC3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.ActiveCfg = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug.Build.0 = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.ActiveCfg = Release|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin_2003.vcproj b/plugins/cdvd/CDVDbin/src/CDVDbin_2003.vcproj new file mode 100644 index 0000000..8f3ea90 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin_2003.vcproj @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.sln b/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.sln new file mode 100644 index 0000000..883127d --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDbin", "CDVDbin_vsnet2005beta1.vcproj", "{50921BF5-D9DE-4264-92CF-7001E117CFC3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug|Win32.ActiveCfg = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug|Win32.Build.0 = Debug|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release|Win32.ActiveCfg = Release|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release|Win32.Build.0 = Release|Win32 + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {50921BF5-D9DE-4264-92CF-7001E117CFC3}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.vcproj b/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.vcproj new file mode 100644 index 0000000..01339df --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbin_vsnet2005beta1.vcproj @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDbin/src/CDVDbinro.rc b/plugins/cdvd/CDVDbin/src/CDVDbinro.rc new file mode 100644 index 0000000..38da02e --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/CDVDbinro.rc @@ -0,0 +1,141 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Romanian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ROM) +#ifdef _WIN32 +LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 267, 69 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Configurare CDVDbin" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "nchide",IDOK,210,48,50,14 + CONTROL "Alegei o imagine bin sau iso de CD/DVD...",IDC_FILE, + "Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | BS_MULTILINE | + WS_TABSTOP,7,20,253,21 + LTEXT "Apas pentru a alege o imagine de folosit sau altfel vei fi ntrebat n timpul rulrii:", + IDC_STATIC,7,7,253,11 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 260 + TOPMARGIN, 7 + BOTTOMMARGIN, 62 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,6,1 + PRODUCTVERSION 1,0,6,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "041804b0" + BEGIN + VALUE "Comments", "plugin simplu de bin/iso; mulumiri lui Xobro; nu e optimizat de nici un fel; a fost fcut pentru teste si s serveasc de exemplu" + VALUE "CompanyName", "-" + VALUE "FileDescription", "CDVDbin" + VALUE "FileVersion", "1, 0, 6, 1" + VALUE "InternalName", "CDVDbin" + VALUE "LegalCopyright", "Copyright 2002" + VALUE "OriginalFilename", "CDVDbin.dll" + VALUE "ProductName", "plugin CDVDbin/iso pentru PSX2" + VALUE "ProductVersion", "1, 0, 6, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x418, 1200 + END +END + +#endif // Romanian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/cdvd/CDVDbin/src/PS2Edefs.h b/plugins/cdvd/CDVDbin/src/PS2Edefs.h new file mode 100644 index 0000000..2380136 --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/PS2Edefs.h @@ -0,0 +1,723 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.9 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetCSR(u64 *csr); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetCSR)(u64 * csr); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetCSR GSsetCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDbin/src/PS2Etypes.h b/plugins/cdvd/CDVDbin/src/PS2Etypes.h new file mode 100644 index 0000000..1ff2b7c --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) || defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDbin/src/resource.h b/plugins/cdvd/CDVDbin/src/resource.h new file mode 100644 index 0000000..b4142cb --- /dev/null +++ b/plugins/cdvd/CDVDbin/src/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by CDVDbin.rc +// +#define IDD_CONFIG 101 +#define IDC_FILE 1000 +#define IDC_DEBUG 1001 +#define IDC_CDDA 1002 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/cdvd/CDVDdraft/Src/AboutBox.cpp b/plugins/cdvd/CDVDdraft/Src/AboutBox.cpp new file mode 100644 index 0000000..4f73dd8 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/AboutBox.cpp @@ -0,0 +1,43 @@ +// AboutBox.cpp : implementation file +// + +#include "stdafx.h" +#include "cdvddraft.h" +#include "AboutBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAboutBox dialog + + +CAboutBox::CAboutBox(CWnd* pParent /*=NULL*/) + : CDialog(CAboutBox::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAboutBox) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CAboutBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutBox) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAboutBox, CDialog) + //{{AFX_MSG_MAP(CAboutBox) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAboutBox message handlers diff --git a/plugins/cdvd/CDVDdraft/Src/AboutBox.h b/plugins/cdvd/CDVDdraft/Src/AboutBox.h new file mode 100644 index 0000000..5c70402 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/AboutBox.h @@ -0,0 +1,46 @@ +#if !defined(AFX_ABOUTBOX_H__D58937A1_2304_11D7_8E29_0050DA15DE89__INCLUDED_) +#define AFX_ABOUTBOX_H__D58937A1_2304_11D7_8E29_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AboutBox.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CAboutBox dialog + +class CAboutBox : public CDialog +{ +// Construction +public: + CAboutBox(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAboutBox) + enum { IDD = IDD_ABOUT }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutBox) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAboutBox) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ABOUTBOX_H__D58937A1_2304_11D7_8E29_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/Config.cpp b/plugins/cdvd/CDVDdraft/Src/Config.cpp new file mode 100644 index 0000000..426681e --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/Config.cpp @@ -0,0 +1,172 @@ +// Config.cpp : implementation file +// + +#include "stdafx.h" +#include "cdvddraft.h" +#include "Config.h" +#include + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CConfig dialog + + +CConfig::CConfig(CWnd* pParent /*=NULL*/) + : CDialog(CConfig::IDD, pParent) +{ + //{{AFX_DATA_INIT(CConfig) + m_nInterface = 0; + m_nBuffMode = 0; + m_nDrive = 0; + m_nReadMode = 0; + //}}AFX_DATA_INIT +} + +void CConfig::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CConfig) + DDX_Control(pDX, IDC_DRIVE, m_ctrlDrive); + DDX_CBIndex(pDX, IDC_INTERFACE, m_nInterface); + DDX_CBIndex(pDX, IDC_PREFETCH, m_nBuffMode); + DDX_CBIndex(pDX, IDC_DRIVE, m_nDrive); + DDX_CBIndex(pDX, IDC_READMODE, m_nReadMode); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CConfig, CDialog) + //{{AFX_MSG_MAP(CConfig) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CConfig message handlers +BOOL CConfig::OnInitDialog() +{ + int nResult = CDialog::OnInitDialog(); + + TRACE("on init dialog.\n"); + int curr_intf = (CDVD_INTERFACE_TYPE) + cdvd_init(CDVD_INTF_UNKNOWN); + + int init_okay = CDVD_ERROR_FAIL; + + if(curr_intf == CDVD_INTF_UNKNOWN) + { + if(CCdvd::Aspi_CheckValidInstallation() + == CDVD_ERROR_SUCCESS) + { + init_okay = cdvd_init(CDVD_INTF_ASPI); + TRACE("config: init_aspi: %ld\n", init_okay); + } + else if(CCdvd::GetWin32OSType() == WINNTNEW) + { + TRACE("config: init_ioctl: %ld\n", init_okay); + init_okay = cdvd_init(CDVD_INTF_IOCTL); + } + else + { + curr_intf = CDVD_INTF_UNKNOWN; + TRACE("config: init_unknown: %ld\n", init_okay); + } + } + // else already either init to ioctl or aspi + else + { + TRACE("config: already previously init.\n"); + init_okay = CDVD_ERROR_SUCCESS; + } + + if(init_okay == CDVD_ERROR_SUCCESS) + { + ADAPTERINFO info; + int ndrives = cdvd_getnumdrives(); + + if(ndrives > 0) + { + for(int i = 0; i < ndrives; i++) + { + CString str; + info = cdvd_getadapterdetail(i); + str.Format(_T(" %d:%d:%d %s"), + info.ha, info.id, info.lun, info.name + ); + TRACE("str: %s\n", str); + m_ctrlDrive.InsertString(i, str); + } + } + else + { + MessageBox(_T("Unable to locate c/dvd drives on this computer\n"), + _T("Drive Error"), + MB_OK|MB_ICONERROR); + } + + if(curr_intf == CDVD_INTF_UNKNOWN && + init_okay == CDVD_ERROR_SUCCESS) + cdvd_shutdown(); + } + + LoadConfig(); + + return TRUE; +} + +void CConfig::OnOK() +{ + SaveConfig(); + CDialog::OnOK(); +} + +///////////////////////////////////////////////////////////////////////////// +// save/load stuff +BOOL CConfig::SaveConfig() +{ + CRegKey rKey; + + if(rKey.Create(HKEY_CURRENT_USER, PLUGIN_REG_PATH) == ERROR_SUCCESS) + { + UpdateData(TRUE); + if(m_nDrive != -1) + { + rKey.SetValue(m_nDrive, _T("DriveNum")); + rKey.SetValue(m_nBuffMode, _T("BuffMode")); + rKey.SetValue(m_nInterface, _T("Interface")); + rKey.SetValue(m_nReadMode, _T("ReadMode")); + } + rKey.Close(); + } + + return TRUE; +} + +BOOL CConfig::LoadConfig() +{ + CRegKey rKey; + + if(rKey.Create(HKEY_CURRENT_USER, PLUGIN_REG_PATH) == ERROR_SUCCESS) + { + DWORD val; + + if(rKey.QueryValue(val, _T("DriveNum")) == ERROR_SUCCESS) + m_nDrive = val; + if(rKey.QueryValue(val, _T("BuffMode")) == ERROR_SUCCESS) + m_nBuffMode = val; + if(rKey.QueryValue(val, _T("Interface")) == ERROR_SUCCESS) + m_nInterface = val; + if(rKey.QueryValue(val, _T("ReadMode")) == ERROR_SUCCESS) + m_nReadMode = val; + + UpdateData(FALSE); + rKey.Close(); + } + + return TRUE; +} diff --git a/plugins/cdvd/CDVDdraft/Src/Config.h b/plugins/cdvd/CDVDdraft/Src/Config.h new file mode 100644 index 0000000..5fee7f2 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/Config.h @@ -0,0 +1,54 @@ +#if !defined(AFX_CONFIG_H__A5E8FC61_C0A7_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CONFIG_H__A5E8FC61_C0A7_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Config.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CConfig dialog + +class CConfig : public CDialog +{ +// Construction +public: + CConfig(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CConfig) + enum { IDD = IDD_CONFIG }; + CComboBox m_ctrlDrive; + int m_nInterface; + int m_nBuffMode; + int m_nDrive; + int m_nReadMode; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CConfig) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + virtual BOOL SaveConfig(); + virtual BOOL LoadConfig(); + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CConfig) + // NOTE: the ClassWizard will add member functions here + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONFIG_H__A5E8FC61_C0A7_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/PS2Edefs.h b/plugins/cdvd/CDVDdraft/Src/PS2Edefs.h new file mode 100644 index 0000000..2380136 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/PS2Edefs.h @@ -0,0 +1,723 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.9 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetCSR(u64 *csr); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetCSR)(u64 * csr); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetCSR GSsetCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDdraft/Src/PS2Etypes.h b/plugins/cdvd/CDVDdraft/Src/PS2Etypes.h new file mode 100644 index 0000000..3a63c58 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDdraft/Src/ReadMe.txt b/plugins/cdvd/CDVDdraft/Src/ReadMe.txt new file mode 100644 index 0000000..69fa721 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/ReadMe.txt @@ -0,0 +1,66 @@ +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : cdvddraft +======================================================================== + + +AppWizard has created this cdvddraft DLL for you. This DLL not only +demonstrates the basics of using the Microsoft Foundation classes but +is also a starting point for writing your DLL. + +This file contains a summary of what you will find in each of the files that +make up your cdvddraft DLL. + +cdvddraft.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +cdvddraft.h + This is the main header file for the DLL. It declares the + CCdvddraftApp class. + +cdvddraft.cpp + This is the main DLL source file. It contains the class CCdvddraftApp. + + +cdvddraft.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +cdvddraft.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + +res\cdvddraft.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + +cdvddraft.def + This file contains information about the DLL that must be + provided to run with Microsoft Windows. It defines parameters + such as the name and description of the DLL. It also exports + functions from the DLL. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named cdvddraft.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDdraft/Src/StdAfx.cpp b/plugins/cdvd/CDVDdraft/Src/StdAfx.cpp new file mode 100644 index 0000000..e6db747 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// cdvddraft.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/plugins/cdvd/CDVDdraft/Src/StdAfx.h b/plugins/cdvd/CDVDdraft/Src/StdAfx.h new file mode 100644 index 0000000..ebaf2ce --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/StdAfx.h @@ -0,0 +1,41 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A0D50EAA_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_STDAFX_H__A0D50EAA_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC Automation classes +#endif // _AFX_NO_OLE_SUPPORT + + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A0D50EAA_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/aspi.cpp b/plugins/cdvd/CDVDdraft/Src/aspi.cpp new file mode 100644 index 0000000..5720c31 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/aspi.cpp @@ -0,0 +1,842 @@ +// Aspi.cpp: implementation of the aspi methods +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "cdvd.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +#define MOVESCSIDWORD(pdwSrc,pdwDst) \ +{\ + ((PBYTE)(pdwDst))[0] = ((PBYTE)(pdwSrc))[3];\ + ((PBYTE)(pdwDst))[1] = ((PBYTE)(pdwSrc))[2];\ + ((PBYTE)(pdwDst))[2] = ((PBYTE)(pdwSrc))[1];\ + ((PBYTE)(pdwDst))[3] = ((PBYTE)(pdwSrc))[0];\ +} + +#define MOVESCSIWORD(pwSrc,pwDst) \ +{\ + ((PBYTE)(pwDst))[0] = ((PBYTE)(pwSrc))[1];\ + ((PBYTE)(pwDst))[1] = ((PBYTE)(pwSrc))[0];\ +} + + +/***********************************************************/ +/* ASPI Init/Shutdown related methods */ +/***********************************************************/ + +// using MFC classes, no aspi in other systems. +int CCdvd::Aspi_CheckValidInstallation() +{ + int retval = CDVD_ERROR_FAIL; + + CFileStatus fstat; + TCHAR szDir[MAX_PATH]; + + if(GetSystemDirectory(szDir,MAX_PATH)) + { + CString directory = szDir; + WIN32OSTYPE ostype = GetWin32OSType(); + + if(ostype != WINNTNEW && ostype != WINNTOLD) + { + if(CFile::GetStatus(directory+_T("\\wnaspi32.dll"), fstat) && + CFile::GetStatus(directory+_T("\\winaspi.dll"), fstat) && + CFile::GetStatus(directory+_T("\\iosubsys\\apix.vxd"), fstat)) + { + retval = CDVD_ERROR_SUCCESS; + } + } + else + { + if(CFile::GetStatus(directory+_T("\\wnaspi32.dll"), fstat) && + CFile::GetStatus(directory+_T("\\drivers\\aspi32.sys"), fstat)) + { + retval = CDVD_ERROR_SUCCESS; + } + } + } + else + { + // are you crazy? o_O, no fucking windows directory? o_O + retval = CDVD_ERROR_FAIL; + } + + return retval; + +} + +// called once to init Aspi +int CCdvd::Aspi_Init() +{ + int retval = CDVD_ERROR_FAIL; + if(m_bAspiInitialized) + return CDVD_ERROR_SUCCESS; + + if(Aspi_CheckValidInstallation() == CDVD_ERROR_SUCCESS) + { + if((m_hAspi = AfxLoadLibrary("WNASPI32")) != NULL) + { + SendASPI32Command = (CDROMSendASPI32Command) GetProcAddress(m_hAspi,"SendASPI32Command"); + GetASPI32SupportInfo = (CDROMGetASPI32SupportInfo) GetProcAddress(m_hAspi,"GetASPI32SupportInfo"); + + if(SendASPI32Command != NULL && + GetASPI32SupportInfo != NULL) + { + UI32 support_info = GetASPI32SupportInfo(); + if( HIBYTE(LOWORD(support_info)) != SS_COMP && + HIBYTE(LOWORD(support_info)) != SS_NO_ADAPTERS ) + { + Aspi_Shutdown(); + } + else + { + if(InitializeBuffers() == CDVD_ERROR_SUCCESS) + { + if(Aspi_ScsiBusScan() == CDVD_ERROR_SUCCESS) + { + SetCurrentBuffer(0); + m_bAspiInitialized = TRUE; + retval = CDVD_ERROR_SUCCESS; + GetNumSectors = Aspi_GetNumSectors; + GetToc = Aspi_GetToc; + // GetHeader = Aspi_GetHeader; + SetSpeed = Aspi_SetSpeed; + Stop = Aspi_Stop; + SetSectorSize = Aspi_SetSectorSize; + Play = Aspi_Play; + TestReady = Aspi_TestReady; + ReadSector = Dummy_T4; + UpdateInterfaceObject(); + } + } + } + } + else + { + Aspi_Shutdown(); + } + } + } + + return retval; +} + +// shuts down aspi +int CCdvd::Aspi_Shutdown() +{ + int retval = CDVD_ERROR_SUCCESS; + + // gota detect the read_mode first before i do this + // but just reset to 2048 for now. + Aspi_SetSectorSize(CDVD_SECTOR_SIZE_DVD); + + // the old ASPI drivers suck shit to hell and damnation, + // freeing them up immediately after init will crash sometimes + ::Sleep(200); + + if(m_hAspi != NULL) + AfxFreeLibrary(m_hAspi); + m_hAspi = NULL; + + SendASPI32Command = NULL; + GetASPI32SupportInfo = NULL; + + GetNumSectors = Dummy_T1; + GetToc = Dummy_T1; + Stop = Dummy_T1; + Play = Dummy_T3; + TestReady = Dummy_T1; +// GetHeader = Dummy_T1; + SetSpeed = Dummy_T2; + SetSectorSize = Dummy_T2; + ReadSector = Dummy_T4; + UpdateInterfaceObject(); + + ShutdownBuffers(); + + m_bAspiInitialized = FALSE; + + return retval; +} + +// open a drive for reading +int CCdvd::Aspi_OpenDrive(int drv_num) +{ + int retval = CDVD_ERROR_SUCCESS; + CloseDrive(); + m_nCurrentDrive = drv_num; + + return retval; +} + +// dummy for now +int CCdvd::Aspi_CloseDrive() +{ + int retval = CDVD_ERROR_SUCCESS; + m_nCurrentDrive = -1; + + return retval; +} + +// get srb status +int CCdvd::Aspi_GetSrbStatus(int srb_num) +{ + int retval = CDVD_SRB_ERROR; + switch(m_nCurrentReadMode) + { + case CDVD_READ_MMC: retval = m_srbReadCd [srb_num].SRB_Status; break; + case CDVD_READ_SCSI10: retval = m_srbRead10 [srb_num].SRB_Status; break; + case CDVD_READ_D8: retval = m_srbReadMat [srb_num].SRB_Status; break; + case CDVD_READ_D410: retval = m_srbReadSony[srb_num].SRB_Status; break; + case CDVD_READ_D412: retval = m_srbReadNec [srb_num].SRB_Status; break; + default: break; + } + + if(retval == SS_COMP) retval = CDVD_SRB_COMPLETED; + else if(retval == SS_PENDING) retval = CDVD_SRB_PENDING; + else //if(retval == SS_ERR) + retval = CDVD_SRB_ERROR; + + return retval; +} + +// set read mode +int CCdvd::Aspi_SetReadMode(CDVD_READ_MODE read_mode) +{ + int retval = CDVD_ERROR_SUCCESS; + + switch(read_mode) + { + case CDVD_READ_MMC: ReadSector = Aspi_ReadSector_mmc; break; + case CDVD_READ_SCSI10: TRACE("cdvdlib: setting scsi10 readmode.\n"); + ReadSector = Aspi_ReadSector_scsi10; + if(((this)->*(SetSectorSize))((m_nMmcDataMode == CDVD_MMC_DATAMODE_RAW) ? + CDVD_SECTOR_SIZE_CD : CDVD_SECTOR_SIZE_DVD) != CDVD_ERROR_SUCCESS) + { + retval = CDVD_ERROR_FAIL; + } + break; + case CDVD_READ_D8: ReadSector = Aspi_ReadSector_matsu; break; + case CDVD_READ_D410: ReadSector = Aspi_ReadSector_sony; break; + case CDVD_READ_D412: ReadSector = Aspi_ReadSector_nec; break; + default: retval = CDVD_ERROR_FAIL; break; + } + + UpdateInterfaceObject(); + + return retval; +} + +// search for scsi adapters with c/dvd drives. +int CCdvd::Aspi_ScsiBusScan() +{ + int retval = CDVD_ERROR_SUCCESS; + + SRB_HAInquiry srbHAInquiry; + m_nDrives = 0; + memset(m_drvDetails, 0, CDVD_MAX_SUPPORTED_DRIVES * sizeof(ADAPTERINFO)); + memset(&srbHAInquiry, 0, sizeof (SRB_HAInquiry) ); + + srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY; + srbHAInquiry.SRB_HaId = 0; + + SendASPI32Command ((LPSRB) &srbHAInquiry); + if (srbHAInquiry.SRB_Status != SS_COMP) + { + return CDVD_ERROR_FAIL; + } + + UI08 HA_Count = srbHAInquiry.HA_Count; + srbHAInquiry.HA_ManagerId[16] = 0; + + for (UI08 HA_num = 0; HA_num < HA_Count; HA_num++) + { + char szHA_num[10]; + itoa((int) HA_num, szHA_num, 10); + memset(&srbHAInquiry, 0, sizeof(SRB_HAInquiry)); + srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY; + srbHAInquiry.SRB_HaId = HA_num; + + SendASPI32Command ((LPSRB) &srbHAInquiry); + if (srbHAInquiry.SRB_Status != SS_COMP) + { + return CDVD_ERROR_FAIL; + } + else + { + srbHAInquiry.HA_Identifier[16] = 0; + for (UI08 SCSI_Id = 0; SCSI_Id < 8; SCSI_Id++) + { + char szSCSI_Id[10]; + itoa ((int) SCSI_Id, szSCSI_Id, 10); + for(UI08 SCSI_Lun = 0; SCSI_Lun < 8; SCSI_Lun++) + { + char szSCSI_Lun[10]; + itoa ((int) SCSI_Lun, szSCSI_Lun, 10); + + SRB_GDEVBlock srbGDEVBlock; + memset(&srbGDEVBlock, 0, sizeof(srbGDEVBlock)); + srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; + srbGDEVBlock.SRB_HaId = HA_num; + srbGDEVBlock.SRB_Target = SCSI_Id; + srbGDEVBlock.SRB_Lun = SCSI_Lun; + SendASPI32Command ((LPSRB) &srbGDEVBlock); + if (srbGDEVBlock.SRB_Status != SS_COMP || + srbGDEVBlock.SRB_DeviceType != DTYPE_CDROM) continue; + + char temp[40]; + if(Aspi_ScsiInquiry(HA_num, SCSI_Id, SCSI_Lun, temp) == CDVD_ERROR_SUCCESS) + { + if(m_nDrives < CDVD_MAX_SUPPORTED_DRIVES) + { + TRACE("drive %ld: [%ld:%ld:%ld] - %s %s\n", m_nDrives, HA_num, SCSI_Id, SCSI_Lun, + m_drvDetails[m_nDrives].hostname, + temp); + m_drvDetails[m_nDrives].ha = HA_num; + m_drvDetails[m_nDrives].id = SCSI_Id; + m_drvDetails[m_nDrives].lun = SCSI_Lun; + strcpy(m_drvDetails[m_nDrives].hostname, (const char*) srbHAInquiry.HA_Identifier); + strcpy(m_drvDetails[m_nDrives].name, temp); + ++m_nDrives; + } + else + { + break; + } + } + else + { + retval = CDVD_ERROR_FAIL; + break; + } + } + } + } + } + + return retval; +} + +// retrieve ha info +int CCdvd::Aspi_ScsiInquiry(UI08 ha, UI08 id, UI08 lun, char *destination) +{ + int retval = CDVD_ERROR_SUCCESS; + + UI08 buffer[36]; + SRB_ExecSCSICmd srb; + + memset(buffer, 0x20, sizeof(buffer)); + memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = ha; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_Target = id; + srb.SRB_Lun = lun; + srb.SRB_BufLen = 36; + srb.SRB_BufPointer = buffer; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = 6; + srb.CDBByte[0] = SCSI_INQUIRY; + srb.CDBByte[4] = 36; // allocation length per buffer + + if (Aspi_ExecuteSrb(srb, NULL, 0) == CDVD_ERROR_SUCCESS) + { + memcpy(destination, buffer + 8, 27); + destination[27] = '\0'; + } + else + { + destination[0] = '\0'; + } + + return retval; +} + +/***********************************************************/ +/* ASPI Execute SRB */ +/***********************************************************/ +// if HANDLE = NULL, SRB is synchronous, else its asynchronous +int CCdvd::Aspi_ExecuteSrb(SRB_ExecSCSICmd &srbExec, HANDLE *handle, int nretry) +{ + int retval = CDVD_ERROR_SUCCESS; + + ++nretry; + // lets do sync with handle == NULL + if(handle == NULL) + { + TRACE("executing synchronous SRB.\n"); + while(nretry) + { + HANDLE heventExec = CreateEvent( NULL, TRUE, FALSE, NULL ); + if(heventExec) // do event based notification + { + srbExec.SRB_Flags |= SRB_EVENT_NOTIFY; + srbExec.SRB_PostProc = (LPVOID)heventExec; + + DWORD dwASPIStatus = SendASPI32Command((LPSRB) &srbExec); + if(dwASPIStatus == SS_ERR) + { + CloseHandle(heventExec); + return CDVD_ERROR_FAIL; + } + + if(dwASPIStatus == SS_PENDING) + { + WaitForSingleObject(heventExec, INFINITE); + } + CloseHandle(heventExec); + } + else // do shitty polling + { + SendASPI32Command((LPSRB)&srbExec); + while(srbExec.SRB_Status == SS_PENDING); + } + + TRACE("SRB_Status: %ld\n", srbExec.SRB_Status); + if( srbExec.SRB_Status != SS_COMP ) + { + if(nretry-- && + (srbExec.SRB_TargStat != STATUS_CHKCOND || + (srbExec.SenseArea[2] & 0x0F) != KEY_UNITATT) ) + { + UI08 sense = srbExec.SenseArea[2] & 0x0F; + UI08 asc = srbExec.SenseArea[12]; + UI08 ascq = srbExec.SenseArea[13]; + TRACE("sensekey: %02Xh, %02Xh, %02Xh\n", sense, asc, ascq); + continue; + } + } + else + { + // we're done. + break; + } + } + } + else + { + TRACE("executing asynchronous SRB.\n"); + + ResetEvent(*handle); + srbExec.SRB_Flags |= SRB_EVENT_NOTIFY; + srbExec.SRB_PostProc = *handle; + + DWORD dwASPIStatus = SendASPI32Command((LPSRB) &srbExec); + + if(dwASPIStatus == SS_ERR) + { + SetEvent(*handle); + TRACE("SRB unrecoverable error.\n"); + return CDVD_ERROR_FAIL; + } + + if(dwASPIStatus == SS_PENDING) + { + TRACE("SRB Pending completion.\n"); + return CDVD_ERROR_PENDING; + } + + TRACE("SRB completed immediately.\n"); + } + + if(nretry == 0) retval = CDVD_ERROR_FAIL; + return retval; +} + +/***********************************************************/ +/* ASPI C/DVD Methods */ +/***********************************************************/ + +// read using mmc 0xbe command +int CCdvd::Aspi_ReadSector_mmc(int sect, HANDLE *handle) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + m_srbReadCd[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; + m_srbReadCd[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + m_srbReadCd[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; + m_srbReadCd[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; + m_srbReadCd[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; + m_srbReadCd[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; + m_srbReadCd[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + m_srbReadCd[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; + + m_srbReadCd[m_nCurrentBuffer].SRB_CDBLen = 12; + m_srbReadCd[m_nCurrentBuffer].CDBByte[0] = 0xBE; + m_srbReadCd[m_nCurrentBuffer].CDBByte[1] = 0x00; + m_srbReadCd[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); + m_srbReadCd[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); + m_srbReadCd[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); + m_srbReadCd[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); + m_srbReadCd[m_nCurrentBuffer].CDBByte[6] = 0x00; + m_srbReadCd[m_nCurrentBuffer].CDBByte[7] = 0x00; + m_srbReadCd[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; + m_srbReadCd[m_nCurrentBuffer].CDBByte[9] = (UI08) m_nMmcDataMode; + m_srbReadCd[m_nCurrentBuffer].CDBByte[10] = 0x00; + m_srbReadCd[m_nCurrentBuffer].CDBByte[11] = 0x00; + + return Aspi_ExecuteSrb(m_srbReadCd[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); +} + +// read using scsi-10 (0x28) command, size is dependent on SetSectorSize +int CCdvd::Aspi_ReadSector_scsi10(int sect, HANDLE *handle) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + m_srbRead10[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; + m_srbRead10[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + m_srbRead10[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN;// | SRB_ENABLE_RESIDUAL_COUNT; + m_srbRead10[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; + m_srbRead10[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; + m_srbRead10[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; + m_srbRead10[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + m_srbRead10[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; + + m_srbRead10[m_nCurrentBuffer].SRB_CDBLen = 10; + m_srbRead10[m_nCurrentBuffer].CDBByte[0] = 0x28; + m_srbRead10[m_nCurrentBuffer].CDBByte[1] = 0x00; + m_srbRead10[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); + m_srbRead10[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); + m_srbRead10[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); + m_srbRead10[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); + m_srbRead10[m_nCurrentBuffer].CDBByte[6] = 0x00; + m_srbRead10[m_nCurrentBuffer].CDBByte[7] = 0x00; + m_srbRead10[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; + m_srbRead10[m_nCurrentBuffer].CDBByte[9] = 0x00; + + return Aspi_ExecuteSrb(m_srbRead10[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); +} + +// read using proprietary matsushita command, heck if it works +int CCdvd::Aspi_ReadSector_matsu(int sect, HANDLE *handle) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + m_srbReadMat[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; + m_srbReadMat[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + m_srbReadMat[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; + m_srbReadMat[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; + m_srbReadMat[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; + m_srbReadMat[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; + m_srbReadMat[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + m_srbReadMat[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; + + m_srbReadMat[m_nCurrentBuffer].SRB_CDBLen = 12; + m_srbReadMat[m_nCurrentBuffer].CDBByte[0] = 0xd4; + m_srbReadMat[m_nCurrentBuffer].CDBByte[1] = 0x00; + m_srbReadMat[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); + m_srbReadMat[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); + m_srbReadMat[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); + m_srbReadMat[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); + m_srbReadMat[m_nCurrentBuffer].CDBByte[6] = 0x00; + m_srbReadMat[m_nCurrentBuffer].CDBByte[7] = 0x00; + m_srbReadMat[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; + m_srbReadMat[m_nCurrentBuffer].CDBByte[9] = 0x00; + m_srbReadMat[m_nCurrentBuffer].CDBByte[10] = 0x00; + m_srbReadMat[m_nCurrentBuffer].CDBByte[11] = 0x00; + + return Aspi_ExecuteSrb(m_srbReadMat[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); +} + +// read using proprietary sony command, heck if it works +int CCdvd::Aspi_ReadSector_sony(int sect, HANDLE *handle) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + m_srbReadSony[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; + m_srbReadSony[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + m_srbReadSony[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; + m_srbReadSony[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; + m_srbReadSony[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; + m_srbReadSony[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; + m_srbReadSony[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + m_srbReadSony[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; + + m_srbReadSony[m_nCurrentBuffer].SRB_CDBLen = 12; + m_srbReadSony[m_nCurrentBuffer].CDBByte[0] = 0xd8; + m_srbReadSony[m_nCurrentBuffer].CDBByte[1] = 0x00; + m_srbReadSony[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); + m_srbReadSony[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); + m_srbReadSony[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); + m_srbReadSony[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); + m_srbReadSony[m_nCurrentBuffer].CDBByte[6] = 0x00; + m_srbReadSony[m_nCurrentBuffer].CDBByte[7] = 0x00; + m_srbReadSony[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; + m_srbReadSony[m_nCurrentBuffer].CDBByte[9] = 0x00; + m_srbReadSony[m_nCurrentBuffer].CDBByte[10] = 0x00; + m_srbReadSony[m_nCurrentBuffer].CDBByte[11] = 0x00; + + return Aspi_ExecuteSrb(m_srbReadSony[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); +} + +// read using proprietary nec command, heck if it works +int CCdvd::Aspi_ReadSector_nec(int sect, HANDLE *handle) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + m_srbReadNec[m_nCurrentBuffer].SRB_Cmd = SC_EXEC_SCSI_CMD; + m_srbReadNec[m_nCurrentBuffer].SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + m_srbReadNec[m_nCurrentBuffer].SRB_Flags = SRB_DIR_IN | SRB_ENABLE_RESIDUAL_COUNT; + m_srbReadNec[m_nCurrentBuffer].SRB_Target = m_drvDetails[m_nCurrentDrive].id; + m_srbReadNec[m_nCurrentBuffer].SRB_BufPointer = m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer; + m_srbReadNec[m_nCurrentBuffer].SRB_BufLen = m_ReadBuffer[m_nCurrentBuffer].AB_BufLen; + m_srbReadNec[m_nCurrentBuffer].SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + m_srbReadNec[m_nCurrentBuffer].SRB_SenseLen = SENSE_LEN; + + m_srbReadNec[m_nCurrentBuffer].SRB_CDBLen = 10; + m_srbReadNec[m_nCurrentBuffer].CDBByte[0] = 0xd4; + m_srbReadNec[m_nCurrentBuffer].CDBByte[1] = 0x00; + m_srbReadNec[m_nCurrentBuffer].CDBByte[2] = HIBYTE(HIWORD(sect)); + m_srbReadNec[m_nCurrentBuffer].CDBByte[3] = LOBYTE(HIWORD(sect)); + m_srbReadNec[m_nCurrentBuffer].CDBByte[4] = HIBYTE(LOWORD(sect)); + m_srbReadNec[m_nCurrentBuffer].CDBByte[5] = LOBYTE(LOWORD(sect)); + m_srbReadNec[m_nCurrentBuffer].CDBByte[6] = 0x00; + m_srbReadNec[m_nCurrentBuffer].CDBByte[7] = 0x00; + m_srbReadNec[m_nCurrentBuffer].CDBByte[8] = CDVD_NUM_SECTORS_PER_BUFF; + m_srbReadNec[m_nCurrentBuffer].CDBByte[9] = 0x00; + + return Aspi_ExecuteSrb(m_srbReadNec[m_nCurrentBuffer], handle, CDVD_MAX_RETRY); +} + +// retrieve number of sectors present in c/dvd media +int CCdvd::Aspi_GetNumSectors() +{ + _ASSERT(m_bAspiInitialized == TRUE); + + SRB_ExecSCSICmd srb; + UI08 capacity[8]; + UI32 max_sector; + + memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_BufLen = 8; + srb.SRB_BufPointer = capacity; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = 10; + + srb.CDBByte[0] = SCSI_RD_CAPAC; + + + if(Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY) + != CDVD_ERROR_SUCCESS) + return 0; // no sectors found + + MOVESCSIDWORD(&capacity[0], &max_sector); + + return max_sector+1; +} + +// retrieve TOC data +int CCdvd::Aspi_GetToc() +{ + _ASSERT(m_bAspiInitialized == TRUE); + + SRB_ExecSCSICmd srb; + UI08 buff[804]; + memset(buff, 0, sizeof(buff)); + memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_BufPointer = buff; + srb.SRB_BufLen = sizeof(buff); + srb.SRB_CDBLen = 10; + srb.CDBByte[0] = SCSI_READ_TOC; + srb.CDBByte[6] = 0; + srb.CDBByte[7] = 0x03; + srb.CDBByte[8] = 0x24; + + if(Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY) + != CDVD_ERROR_SUCCESS) + return CDVD_ERROR_FAIL; + + if(ExtractTocData(buff) != CDVD_ERROR_SUCCESS) + return CDVD_ERROR_FAIL; + + return CDVD_ERROR_SUCCESS; +} + +// set cdrom speed +int CCdvd::Aspi_SetSpeed(int speed) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + SRB_ExecSCSICmd srb; + UI16 kbSpeed = 0xFFFF; + switch(speed) + { + case 0: kbSpeed = 0xFFFF; break; + case 1: kbSpeed = 176; break; + case 2: kbSpeed = 353; break; + case 3: kbSpeed = 528; break; + case 4: kbSpeed = 706; break; + case 5: kbSpeed = 1400; break; + case 6: kbSpeed = 2800; break; + default: kbSpeed = 0xFFFF; break; // max + } + + memset(&srb,0,sizeof(srb)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_Flags = SRB_DIR_OUT; //|SRB_ENABLE_RESIDUAL_COUNT; + srb.SRB_SenseLen = SENSE_LEN; + + srb.SRB_CDBLen = 12; + srb.CDBByte[0] = 0xBB; + srb.CDBByte[2] = HIBYTE(kbSpeed); + srb.CDBByte[3] = LOBYTE(kbSpeed); + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} + +// used for scsi only, sets sector size (i.e, 2352, 2048) +int CCdvd::Aspi_SetSectorSize(int sect_size) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + TRACE("sectorsize: %ld\n", sect_size); + MODESELHEADER mh; + SRB_ExecSCSICmd srb; + + memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); + memset (&mh, 0, sizeof(MODESELHEADER)); + + mh.block_desc_length = 0x08; + mh.block_length_med = HIBYTE(LOWORD(sect_size)); + mh.block_length_lo = LOBYTE(LOWORD(sect_size)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_Flags = SRB_DIR_OUT; + srb.SRB_BufLen = sizeof(mh); + srb.SRB_BufPointer = (UI08 *) &mh; + srb.SRB_CDBLen = 6; + srb.CDBByte[0] = 0x15; + srb.CDBByte[1] = 0x10; + srb.CDBByte[4] = 0x0C; + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} + +// start cddda playback, dunno if it works right really.. :p +int CCdvd::Aspi_Play(int sect_start, int sect_stop) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + SRB_ExecSCSICmd srb; + + memset( &srb, 0, sizeof(SRB_ExecSCSICmd) ); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = 12; + + srb.CDBByte[0] = 0xa5; + srb.CDBByte[2] = HIBYTE(HIWORD(sect_start)); + srb.CDBByte[3] = LOBYTE(HIWORD(sect_start)); + srb.CDBByte[4] = HIBYTE(LOWORD(sect_start)); + srb.CDBByte[5] = LOBYTE(LOWORD(sect_start)); + srb.CDBByte[6] = HIBYTE(HIWORD(sect_stop)); + srb.CDBByte[7] = LOBYTE(HIWORD(sect_stop)); + srb.CDBByte[8] = HIBYTE(LOWORD(sect_stop)); + srb.CDBByte[9] = LOBYTE(LOWORD(sect_stop)); +// srb.CDBByte[10] = 0x8F; + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} + +// stop cdda playback, dunno if it works right really.. :p +int CCdvd::Aspi_Stop() +{ + _ASSERT(m_bAspiInitialized == TRUE); + + SRB_ExecSCSICmd srb; + + memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = 10; + srb.CDBByte[0] = 0x4E; + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} + +// detect if media/LUN is ready, legacy command, +// can prolly be substituted with GetMediaType(), with some modifs +int CCdvd::Aspi_TestReady() +{ + SRB_ExecSCSICmd srb; + + memset (&srb, 0, sizeof(SRB_ExecSCSICmd)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = 6; + srb.CDBByte[0] = SCSI_TST_U_RDY; + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} + +// retrieve feature details +int CCdvd::Aspi_GetConfiguration(UI16 feature, UI08 *dest, UI32 dest_size) +{ + _ASSERT(m_bAspiInitialized == TRUE); + + int retval = CDVD_ERROR_SUCCESS; + + SRB_ExecSCSICmd srb; + memset(&srb, 0, sizeof(SRB_ExecSCSICmd)); + memset(dest, 0, dest_size); + + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = m_drvDetails[m_nCurrentDrive].ha; + srb.SRB_Target = m_drvDetails[m_nCurrentDrive].id; + srb.SRB_Lun = m_drvDetails[m_nCurrentDrive].lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_BufPointer = dest; + srb.SRB_BufLen = dest_size; + + srb.SRB_CDBLen = 12; + srb.CDBByte[0] = 0x46; + srb.CDBByte[1] = 0x02; // return a single feature set ONLY. + srb.CDBByte[2] = HIBYTE(feature); + srb.CDBByte[3] = LOBYTE(feature); + srb.CDBByte[7] = HIBYTE(dest_size); + srb.CDBByte[8] = LOBYTE(dest_size); + + return Aspi_ExecuteSrb(srb, NULL, CDVD_MAX_RETRY); +} diff --git a/plugins/cdvd/CDVDdraft/Src/bitmap1.bmp b/plugins/cdvd/CDVDdraft/Src/bitmap1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0067b8dda25c09f18a64b4921c8d7a1aaa401658 GIT binary patch literal 3726 zcma)4T9J?T`QCY@ zi6Z<4UlO8d$+7j;`tQ=mS8vT#O0$5h>;XS^I(RGWr>XX^x5c$JXQHp>NYNs2TAqsF1- zE?YkP1k49dl_nIiMs+AaZ{+@j^(@*&l~VnBce!(0lz9VbT?b@1Nn0Ajqr?V~}7u7x}*w(c=ca;&kx%%Eei+T>QhZhdia8^dvrMiD1xY=o>D zA8);%dt@zom%7^y*9Du^KiMQ_{4y(|^u;ehcJ8yCx9|)l->nP!n&32TRJ#KVLtK1s z$JTC6HePv6%X7=t6v$7|=Dz=X$CAc)Ij@TKzF`)DM5#S4yrDkpe(1Dib>2H{Bj>gj z+hZV{7v3M+z~)=sM=7o;T4E6*o2nJ`4j1fCf)%)CAB&ny9n$^ZPC= zc&mnPatwPiC=WhkM~15^;9A97Y#3#XYsZ!_um@+MJtv3`24Ft$LR$y6yNcCbI>F}4 zcErnN=F^XKgJPB_Agz~hpuY6lYO;A}b0!Z|=E|uTrJUq zG6+7UT0XeDtsdk03RZ0^k|~guvH^CZG%SM4Lp?YazXb+J62bZThubbfqu}l zjs?38BMtNPH`Yp>sr;6L#hFnR6^IVuSo$^$T4(U`glBMsVk5rWvUxmXP4>!5=Jev4 z(N~C?HP&hY<}d+UM5}7SyNb;V8%m$*U)-6%7E@%-f&xtv*m}Z>T{K0A2nVLo=7H=M zv~>~Q2TSb(tNQ9O*0J)`8TMv14i#pBT5add@7TFx)0#9_d1t{os!>jy;j93MVjoHN zIS=du@x~GP?GKL}66AR?Jqbv3_5@Z0G90Y(kxLy5FQ+?uVM7UyFnqzz6vHm2rgm&S z?E2aU7Lu~nG03LfrXJ{kL{ztNHv#x#j>8Rjr6jV-~VPI zPQ2~3+GyZ2rKWEk?uLDlj;6^I+hNn<@rWg@aZ*&phUQB@_Ir&Q=zKGguT68#l-nNo zen|-^Ip;N}YwR=~2`9#(gq9ah7{UoJwZyetuCeN~h5ZjM4xSsrYts-St=P#KnDHZ8%A~-9m-G4qGe~y zrGd~1#J56~8Q-;qmz$7YDpZyWIP`(-px)c%Q3PzpI)w8x?BnB6?TJPElp3(rh;CGs z(A&|J8y80b?)^GVV2kkwPMB+1TfDQ2r6Qe22d^FoN8PH3dK$S2Wm&jeTw#a4i_@% literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDdraft/Src/cdvd.cpp b/plugins/cdvd/CDVDdraft/Src/cdvd.cpp new file mode 100644 index 0000000..f8d4347 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvd.cpp @@ -0,0 +1,616 @@ +// Cdvd.cpp: implementation of the CCdvd class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "Cdvd.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +#if defined(CDVD_SIMPLE_INTERFACE) +// our fuckup method of interfacing ;p +CCdvd OBJECT_HOLDER_CDVD; +CDVD_INTF_FUNC_T1 FUNCTION_GETNUMSECTORS; +CDVD_INTF_FUNC_T1 FUNCTION_GETTOC; +CDVD_INTF_FUNC_T1 FUNCTION_TESTREADY; +CDVD_INTF_FUNC_T2 FUNCTION_SETSPEED; +CDVD_INTF_FUNC_T1 FUNCTION_STOP; +CDVD_INTF_FUNC_T2 FUNCTION_SETSECTORSIZE; +CDVD_INTF_FUNC_T3 FUNCTION_PLAY; +CDVD_INTF_FUNC_T4 FUNCTION_READSECTOR; + +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CCdvd::CCdvd() +{ + m_hIoctlDrv = NULL; + m_hAspi = NULL; + m_bAspiInitialized = FALSE; + m_bIoctlInitialized = FALSE; + m_bDriveOpened = FALSE; + m_nCurrentDrive = -1; + m_nCurrentBuffer = 0; + m_nDrives = 0; + m_IntfType = CDVD_INTF_UNKNOWN; + m_nMmcDataMode = CDVD_MMC_DATAMODE_RAW; + m_nCurrentReadMode = CDVD_READ_MMC; + + memset(m_drvDetails, 0, CDVD_MAX_SUPPORTED_DRIVES * sizeof(ADAPTERINFO)); + memset(m_srbReadCd, 0, CDVD_NUM_BUFFERS * sizeof(SRB_ExecSCSICmd)); + memset(m_srbRead10, 0, CDVD_NUM_BUFFERS * sizeof(SRB_ExecSCSICmd)); + memset(m_srbReadMat, 0, CDVD_NUM_BUFFERS * sizeof(SRB_ExecSCSICmd)); + memset(m_srbReadSony, 0, CDVD_NUM_BUFFERS * sizeof(SRB_ExecSCSICmd)); + memset(m_srbReadNec, 0, CDVD_NUM_BUFFERS * sizeof(SRB_ExecSCSICmd)); + memset(m_sptwbReadCd, 0, CDVD_NUM_BUFFERS * sizeof(SPTD_WITH_SENSE_BUFF)); + memset(m_sptwbRead10, 0, CDVD_NUM_BUFFERS * sizeof(SPTD_WITH_SENSE_BUFF)); + memset(m_sptwbReadMat, 0, CDVD_NUM_BUFFERS * sizeof(SPTD_WITH_SENSE_BUFF)); + memset(m_sptwbReadSony, 0, CDVD_NUM_BUFFERS * sizeof(SPTD_WITH_SENSE_BUFF)); + memset(m_sptwbReadNec, 0, CDVD_NUM_BUFFERS * sizeof(SPTD_WITH_SENSE_BUFF)); + + memset(&m_tocDetails, 0, sizeof(TOCDATA)); + + GetNumSectors = Dummy_T1; + GetToc = Dummy_T1; + Stop = Dummy_T1; + Play = Dummy_T3; + TestReady = Dummy_T1; +// GetHeader = Dummy_T1; + SetSpeed = Dummy_T2; + SetSectorSize = Dummy_T2; + ReadSector = Dummy_T4; + + UpdateInterfaceObject(); +} + +CCdvd::~CCdvd() +{ + CloseDrive(); + Shutdown(); +} + +// based on msdn example +WIN32OSTYPE CCdvd::GetWin32OSType() +{ + WIN32OSTYPE wintype; + UI32 version; + OSVERSIONINFO *osvi; + + version = GetVersion(); + if(version < 0x80000000) + { + osvi = (OSVERSIONINFO *) malloc(sizeof(OSVERSIONINFO)); + if (osvi) + { + memset(osvi, 0, sizeof(OSVERSIONINFO)); + osvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(osvi); + if (osvi->dwMajorVersion >= 4L) + wintype = WINNTNEW; + else + wintype = WINNTOLD; + + free(osvi); + } + } + else if (LOBYTE(LOWORD(version)) < 4L) + wintype = WIN32S; + else + wintype = WIN95; + + return wintype; +} + +// Initializes an interface, only one should be initialized. :) +int CCdvd::Init(CDVD_INTERFACE_TYPE intf_type) +{ + int retval = CDVD_ERROR_SUCCESS; + + switch(intf_type) + { + case CDVD_INTF_ASPI: + m_IntfType = CDVD_INTF_ASPI; + Aspi_Init(); + break; + //case CDVD_INTF_IOCTL: + // m_IntfType = CDVD_INTF_IOCTL; + // Ioctl_Init(); + // break; + case CDVD_INTF_UNKNOWN: + if(m_bAspiInitialized) + retval = CDVD_INTF_ASPI; + else + if(m_bIoctlInitialized) retval = CDVD_INTF_IOCTL; + else + retval = CDVD_INTF_UNKNOWN; + break; + + default: + retval = CDVD_ERROR_FAIL; + break; + } + + return retval; +} + +// shutsdown previously opened interface +int CCdvd::Shutdown() +{ + int retval = CDVD_ERROR_SUCCESS; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: + Aspi_Shutdown(); + break; + //case CDVD_INTF_IOCTL: + // Ioctl_Shutdown(); + // break; + default: break; + } + + m_IntfType = CDVD_INTF_UNKNOWN; + + return retval; +} + +// retrieve number of c/dvd drives +int CCdvd::GetNumDrives() const +{ + return m_nDrives; +} + +// open a drive for reading +int CCdvd::OpenDrive(int drv_num) +{ + int retval = CDVD_ERROR_FAIL; + _ASSERT(drv_num < CDVD_MAX_SUPPORTED_DRIVES); + + // run-time check, for now. + if(drv_num > (int) m_nDrives) + return CDVD_ERROR_FAIL; + + m_bDriveOpened = FALSE; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: + if(Aspi_OpenDrive(drv_num) == CDVD_ERROR_SUCCESS) + { + m_bDriveOpened = TRUE; + retval = CDVD_ERROR_SUCCESS; + } + break; + //case CDVD_INTF_IOCTL: + // if(Ioctl_OpenDrive(drv_num) == CDVD_ERROR_SUCCESS) + // { + // m_bDriveOpened = TRUE; + // retval = CDVD_ERROR_SUCCESS; + // } + default: break; + } + + return retval; +} + +// close a previously opened drive +int CCdvd::CloseDrive() +{ + int retval = CDVD_ERROR_SUCCESS; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: Aspi_CloseDrive(); break; + //case CDVD_INTF_IOCTL: Ioctl_CloseDrive(); break; + default: break; + } + + return retval; +} + +// allocate and initialize buffers for BOTH aspi and ioctl +int CCdvd::InitializeBuffers() +{ + int retval = CDVD_ERROR_SUCCESS; + UI32 result = 0xFFFFFFFF; + for(int i=0; i < CDVD_NUM_BUFFERS; i++) + { + if(m_ReadBuffer[i].AB_BufPointer != NULL) continue; + m_ReadBuffer[i].AB_BufLen = CDVD_NUM_SECTORS_PER_BUFF * CDVD_SECTOR_SIZE_CD; + m_ReadBuffer[i].AB_BufPointer = (PBYTE) VirtualAlloc + ( + NULL, + m_ReadBuffer[i].AB_BufLen, + MEM_COMMIT, + PAGE_READWRITE + ); + + result &= (UI32) m_ReadBuffer[i].AB_BufPointer; + if(m_ReadBuffer[i].AB_BufPointer != NULL) + memset(m_ReadBuffer[i].AB_BufPointer, 0, m_ReadBuffer[i].AB_BufLen); + } + + if(result == 0) + { + ShutdownBuffers(); + retval = CDVD_ERROR_FAIL; + TRACE("unable to allocate all buffers\n"); + } + + return retval; +} + +// free-up previously allocated buffers +int CCdvd::ShutdownBuffers() +{ + int retval = CDVD_ERROR_SUCCESS; + + for(int i=0; i < CDVD_NUM_BUFFERS; i++) + { + if(m_ReadBuffer[i].AB_BufPointer != NULL) + VirtualFree( m_ReadBuffer[i].AB_BufPointer, 0, MEM_RELEASE ); + m_ReadBuffer[i].AB_BufPointer = NULL; + m_ReadBuffer[i].AB_BufLen = 0; + } + + return retval; +} + +// set the current buffer to be used +// only 2! at the moment +int CCdvd::SetCurrentBuffer(int buf_num) +{ + int retval = CDVD_ERROR_SUCCESS; + if(buf_num >= CDVD_NUM_BUFFERS) + return CDVD_ERROR_FAIL; + + m_nCurrentBuffer = buf_num; + + return retval; +} + +// this is terribly WRONG :P, but i dont care, works most of the time :p +int CCdvd::ExtractTocData(UI08 *buffer) +{ + int retval = CDVD_ERROR_SUCCESS; + LPTOCDATA pdata = (LPTOCDATA) buffer; + + memcpy(&m_tocDetails, buffer, sizeof(TOCDATA)); + + int total_tracks = 0; + int mediatype = GetCdvdMediaType(); + + UI32 numRead = ((UI32) pdata->datalen_byte1) << 8 | (UI32) (pdata->datalen_byte0); + SetCurrentBuffer(0); + + memset(&m_trkDetails, 0, sizeof(DECODEDTRACKINFO)); + + int offset = 4; + for(int i = 0; i < pdata->last_track_num; i++) + { + offset = i*8+4; + LPTOCTRACKDESCRIPTOR pdesc = (LPTOCTRACKDESCRIPTOR) (buffer + offset); + + UI32 start_track = ((UI32) pdesc->lba_byte3) << 24 | + ((UI32) pdesc->lba_byte2) << 16 | + ((UI32) pdesc->lba_byte1) << 8 | + (UI32) pdesc->lba_byte0; + + // track types, 0x00 - cdda, 0x01 - data, 0x02 - cdxa + UI08 tracktype = 0; + if(mediatype == CDVD_MEDIATYPE_DVD) + { + tracktype = 0x01; // data sector + } + else if(((this)->*(ReadSector))(start_track, NULL) == CDVD_ERROR_SUCCESS) + { + tracktype = (UI08) * (m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer+15); + } + else + { + // skip setting info for this track, and try to proceed with others + ++total_tracks; + continue; + } + // okay, something is fucked.. just lie and say its a cdda :p + if(tracktype > 2) tracktype = 0; + + m_trkDetails.track_offset[i] = start_track; + m_trkDetails.track_type[i] = tracktype; + + TRACE("track %ld -> start_at: %ld with type: %ld\n", i, start_track, tracktype); + ++total_tracks; + } + + if(total_tracks) m_trkDetails.total_tracks = total_tracks; + + return retval; +} + +// set read mode (i.e. mmc, scsi10 etc). +// Note: only mmc and scsi10 is enabled +// i've disabled all goddamn proprietary read modes +// on this version (sony, nec, matsushita) +int CCdvd::SetReadMode(CDVD_READ_MODE read_mode, int data_mode) +{ + _ASSERT(read_mode >= CDVD_READ_MMC && read_mode <= CDVD_READ_SCSI10); + + m_nCurrentReadMode = read_mode; + m_nMmcDataMode = data_mode; + + int retval = CDVD_ERROR_SUCCESS; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: + retval = Aspi_SetReadMode(read_mode); + break; + //case CDVD_INTF_IOCTL: + // retval = Ioctl_SetReadMode(); + // break; + default: + retval = CDVD_ERROR_FAIL; + break; + } + + return CDVD_ERROR_SUCCESS; +} + +// returns CDVD_ERROR_PENDING if SS_PENDING, CDVD_ERROR_SUCCESS if SS_COMP +// and CDVD_ERROR_FAIL if you are a dumbass and you haven't set any read_mode +int CCdvd::GetSrbStatus(int srb_num) +{ + int retval = CDVD_ERROR_SUCCESS; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: + retval = Aspi_GetSrbStatus(srb_num); + break; + //case CDVD_INTF_IOCTL: + // retval = Ioctl_GetSrbStatus(srb_num); + // break; + default: + retval = CDVD_ERROR_FAIL; + break; + } + + return retval; +} + +int CCdvd::GetCdvdConfiguration(UI16 feature, UI08 *dest, UI32 dest_size) +{ + int retval = CDVD_ERROR_SUCCESS; + switch(m_IntfType) + { + case CDVD_INTF_ASPI: + retval = Aspi_GetConfiguration(feature, dest, dest_size); + break; + //case CDVD_INTF_IOCTL: + // retval = Ioctl_GetConfiguration(feature, dest, dest_size); + // break; + default: + retval = CDVD_ERROR_FAIL; + break; + } + + return retval; +} + +const UI16 CDVD_FEATURE_READCD = 0x001E; +const UI16 CDVD_FEATURE_READDVD = 0x001F; + +// as the name says +int CCdvd::GetCdvdDriveType() +{ + int drivetype = CDVD_DRIVETYPE_UNKNOWN; + UI08 buffer[1024]; + UI16 feature_available = 0; + BOOL is_cdromdrive = FALSE; + BOOL is_dvddrive = FALSE; + + if(GetCdvdConfiguration(CDVD_FEATURE_READCD, buffer, sizeof(buffer)) + == CDVD_ERROR_SUCCESS) + { + feature_available = (UI16) buffer[8] << 8 | (UI16) buffer[9]; + if(feature_available == CDVD_FEATURE_READCD) + { + is_cdromdrive = TRUE; + } + } + + if(GetCdvdConfiguration(CDVD_FEATURE_READDVD, buffer, sizeof(buffer)) + == CDVD_ERROR_SUCCESS) + { + feature_available = (UI16) buffer[8] << 8 | (UI16) buffer[9]; + if(feature_available == CDVD_FEATURE_READDVD) + { + is_dvddrive = TRUE; + } + } + + if(is_dvddrive && is_cdromdrive) drivetype = CDVD_DRIVETYPE_CDVD; + if(is_dvddrive && !is_cdromdrive) drivetype = CDVD_DRIVETYPE_DVD; + if(!is_dvddrive && is_cdromdrive) drivetype = CDVD_DRIVETYPE_CD; + + return drivetype; +} + +// as the naem says +int CCdvd::GetCdvdMediaType() +{ + int mediatype = CDVD_MEDIATYPE_UNKNOWN; + UI08 buffer[1024]; + UI08 media; + + if(GetCdvdConfiguration(CDVD_FEATURE_READCD, buffer, sizeof(buffer)) + == CDVD_ERROR_SUCCESS) + { + media = buffer[10] & 0x01; // current loaded media is a cdrom if "Current" bit is on + if(media) + { + return CDVD_MEDIATYPE_CD; + } + } + + if(GetCdvdConfiguration(CDVD_FEATURE_READDVD, buffer, sizeof(buffer)) + == CDVD_ERROR_SUCCESS) + { + media = buffer[10] & 0x01; // current loaded media is a dvd if "Current" bit is on + if(media) + { + return CDVD_MEDIATYPE_DVD; + } + } + + return mediatype; +} + +// automatically detect read_mode as well as set it. +int CCdvd::DetectAndSetReadMode() +{ +#define CHECKMODE(m) memset(m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer, 0xCC, m_ReadBuffer[m_nCurrentBuffer].AB_BufLen); \ + SetReadMode((m), m_nMmcDataMode);\ + if(((this)->*(ReadSector))(0, NULL) == CDVD_ERROR_SUCCESS){\ + if(*((UI32*) m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer) != 0xCCCCCCCC){\ + TRACE("data: %08Xh, detected read mode: %ld\n", *((UI32*) m_ReadBuffer[m_nCurrentBuffer].AB_BufPointer), (m));\ + return (m);\ + }\ + } + + int retval = CDVD_ERROR_FAIL; + if(GetCdvdDriveType() != CDVD_DRIVETYPE_UNKNOWN) + { + int mediatype = GetCdvdMediaType(); + if(mediatype != CDVD_MEDIATYPE_UNKNOWN) // no freaking media present dipshit + { + if(mediatype == CDVD_MEDIATYPE_DVD) + { + m_nMmcDataMode = CDVD_MMC_DATAMODE_USER; + } + else if(mediatype == CDVD_MEDIATYPE_CD) + { + m_nMmcDataMode = CDVD_MMC_DATAMODE_RAW; + } + + // start checking which one will work; + + SetCurrentBuffer(0); + + // lets try scsi10 first, since scsi10/scsi12 is mandatory for dvd's + if(((this)->*(SetSectorSize))((m_nMmcDataMode == CDVD_MMC_DATAMODE_RAW) ? + CDVD_SECTOR_SIZE_CD : CDVD_SECTOR_SIZE_DVD) == CDVD_ERROR_SUCCESS) + { + CHECKMODE(CDVD_READ_SCSI10); + } + + // then check for mmc + CHECKMODE(CDVD_READ_MMC); + // mmc doesnt work? lets try the others + + TRACE("cdvdlib: failed to retrieve mode. \n"); + // disabled all other read_modes for now. + //CHECKMODE(CDVD_READ_D8); + //CHECKMODE(CDVD_READ_D410); + //CHECKMODE(CDVD_READ_D412); + } + } + + return retval; +} + +// update the global interface for some magic +void CCdvd::UpdateInterfaceObject() +{ +#if defined(CDVD_SIMPLE_INTERFACE) + + FUNCTION_GETNUMSECTORS = GetNumSectors; + FUNCTION_GETTOC = GetToc; + FUNCTION_TESTREADY = TestReady; + FUNCTION_SETSPEED = SetSpeed; + FUNCTION_STOP = Stop; + FUNCTION_SETSECTORSIZE = SetSectorSize; + FUNCTION_PLAY = Play; + FUNCTION_READSECTOR = ReadSector; + +#endif + +} + +TOCDATA CCdvd::GetTocData() +{ + TOCDATA dummy; + + if(m_nCurrentDrive == -1) + { + memset(&dummy, 0, sizeof(TOCDATA)); + return dummy; + } + + return m_tocDetails; +} + +DECODEDTRACKINFO CCdvd::GetTrackDetail() +{ + DECODEDTRACKINFO dummy; + + if(m_nCurrentDrive == -1) + { + memset(&dummy, 0, sizeof(DECODEDTRACKINFO)); + return dummy; + } + + return m_trkDetails; +} + +UI08 *CCdvd::GetBufferAddress(int buff_num) const +{ + _ASSERT(buff_num < CDVD_NUM_BUFFERS); + + return m_ReadBuffer[buff_num].AB_BufPointer; +} + +ADAPTERINFO CCdvd::GetAdapterDetail(int drv_num) +{ + _ASSERT(drv_num < CDVD_MAX_SUPPORTED_DRIVES); + ADAPTERINFO dummy; + + if(m_nDrives == 0) + { + memset(&dummy, 0, sizeof(ADAPTERINFO)); + return dummy; + } + + return m_drvDetails[drv_num]; +} + + +/***********************************************************/ +/* DUMMY C/DVD Methods */ +/***********************************************************/ +int CCdvd::Dummy_T1() +{ + TRACE("cdvdlib: dummy_t1\n"); + return CDVD_ERROR_UNINITIALIZED; +} + +int CCdvd::Dummy_T2(int a) +{ + TRACE("cdvdlib: dummy_t2\n"); + return CDVD_ERROR_UNINITIALIZED; +} + +int CCdvd::Dummy_T3(int a, int b) +{ + TRACE("cdvdlib: dummy_t3\n"); + return CDVD_ERROR_UNINITIALIZED; +} + +int CCdvd::Dummy_T4(int a, HANDLE *b) +{ + TRACE("cdvdlib: dummy_t4\n"); + return CDVD_ERROR_UNINITIALIZED; +} + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvd.h b/plugins/cdvd/CDVDdraft/Src/cdvd.h new file mode 100644 index 0000000..affd775 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvd.h @@ -0,0 +1,252 @@ +// Cdvd.h: interface for the CCdvd class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CDVD_H__1189B8A5_BC21_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CDVD_H__1189B8A5_BC21_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include +#include +#include +#include "winaspi/wnaspi32.h" +#include "winaspi/scsidefs.h" +#include "constants.h" +#include "typedefs.h" + +#define CDVD_SIMPLE_INTERFACE + +// [normal sequence of operation] +// 1. [open] +// Init -> GetNumDrives -> OpenDrive -> SetReadMode -> (DO WHATEVER, read, toc, etc) +// 2. [close] +// CloseDrive -> Shutdown; +// 3. [synchrounous read] +// ReadSector -> (verify if successful) +// 4. [asynchronous read] +// ReadSector -> GetSrbStatus -> (verify if successful) + +// CDVD class, don't complain. +class CCdvd +{ + // public interfaces only +public: + + int Init(CDVD_INTERFACE_TYPE intf_type); // initialize an interface, closes previously opened one. + int Shutdown(); // shutsdown an interface + int GetNumDrives() const; // get num of c/dvd drives available + int OpenDrive(int drv_num); // open a drive + int CloseDrive(); // close previously opened drive + int SetCurrentBuffer(int buf_num); // currently there are ONLY 2! + + // call, when doing asynchronous requests to retrieve an srb status (i.e. buffer0 = srb0) + // the return value is only valid when an asynchronous read was previously issued + int GetSrbStatus(int srb_num); + + // manually set read_mode, if mmc mode is specified, data_filter is also set. + // data_mode can be CDVD_MMC_DATAMODE_RAW / CDVD_MMC_DATAMODE_USER + // note that CDVD_MMC_DATAMODE_USER should always be used for DVD medias, + // and the only read_mode's enabled are CDVD_READ_MMC and CDVD_READ_SCSI10 + // i've disabled all the other modes in this version (unlike the previous one.) + int SetReadMode(CDVD_READ_MODE read_mode, int data_mode = CDVD_MMC_DATAMODE_RAW); + + // determine drive type + int GetCdvdDriveType(); + + // determine media type + int GetCdvdMediaType(); + + // automatically detect media type, read_type and set it. + // returns detected read mode, else CDVD_ERROR_FAIL if error + int DetectAndSetReadMode(); + + UI08 *GetBufferAddress(int buff_num) const; + + CDVD_INTF_FUNC_T1 GetNumSectors; + CDVD_INTF_FUNC_T1 GetToc; + CDVD_INTF_FUNC_T1 TestReady; + CDVD_INTF_FUNC_T2 SetSpeed; + CDVD_INTF_FUNC_T1 Stop; + CDVD_INTF_FUNC_T2 SetSectorSize; + CDVD_INTF_FUNC_T3 Play; + CDVD_INTF_FUNC_T4 ReadSector; + + ADAPTERINFO GetAdapterDetail(int drv_num); + + // for both gettrackdetail and gettocdata + // only valid if there was previous call to GetToc; + DECODEDTRACKINFO GetTrackDetail(); + TOCDATA GetTocData(); + + // auxilliary function + static WIN32OSTYPE GetWin32OSType(); + static int Aspi_CheckValidInstallation(); + +protected: + + int Aspi_Init(); + int Aspi_Shutdown(); + int Aspi_OpenDrive (int drv_num); + int Aspi_CloseDrive (); + int Aspi_GetSrbStatus (int srb_num); + int Aspi_GetNumSectors(); + int Aspi_TestReady (); // legacy + int Aspi_GetToc (); // legacy + //int Aspi_GetHeader (); + int Aspi_SetSpeed (int speed); + int Aspi_Stop (); + int Aspi_SetSectorSize(int sect_size); + int Aspi_Play (int sect_start, int sect_stop); + int Aspi_SetReadMode (CDVD_READ_MODE read_mode); + + // if handle is not NULL, then the read is asynchronous + int Aspi_ReadSector_mmc (int sect, HANDLE *handle = NULL); + int Aspi_ReadSector_scsi10 (int sect, HANDLE *handle = NULL); + int Aspi_ReadSector_matsu (int sect, HANDLE *handle = NULL); + int Aspi_ReadSector_sony (int sect, HANDLE *handle = NULL); + int Aspi_ReadSector_nec (int sect, HANDLE *handle = NULL); + + // retrieve a configuration from the cdvd drive + int Aspi_GetConfiguration(UI16 feature, UI08 *dest, UI32 dest_size); + + int Ioctl_Init(); + int Ioctl_Shutdown(); + int Ioctl_OpenDrive (int drv_num); + int Ioctl_CloseDrive (); + int Ioctl_GetSrbStatus (int srb_num); + int Ioctl_GetNumSectors(); + int Ioctl_TestReady (); // legacy + int Ioctl_GetToc (); // legacy + //int Ioctl_GetHeader (); + int Ioctl_SetSpeed (int speed); + int Ioctl_Stop (); + int Ioctl_SetSectorSize(int sect_size); + int Ioctl_Play (int sect_start, int sect_stop); + int Ioctl_SetReadMode (CDVD_READ_MODE read_mode); + + // if handle is not NULL, read is still NOT ASYNCHRONOUS, + // stupid IOCTL BLOCKS OVERLAPPED OPERATIONS -_- + int Ioctl_ReadSector_mmc (int sect, HANDLE *handle = NULL); + int Ioctl_ReadSector_scsi10 (int sect, HANDLE *handle = NULL); + int Ioctl_ReadSector_matsu (int sect, HANDLE *handle = NULL); + int Ioctl_ReadSector_sony (int sect, HANDLE *handle = NULL); + int Ioctl_ReadSector_nec (int sect, HANDLE *handle = NULL); + + // retrieve a configuration from the cdvd drive + int Ioctl_GetConfiguration(UI16 feature, UI08 *dest, UI32 dest_size); + + // dummy functions, used for init only so that stupid mofu's + // calling no-initialized interfaces won't crash + int Dummy_T1(); + int Dummy_T2(int a); + int Dummy_T3(int a, int b); + int Dummy_T4(int a, HANDLE *b = NULL); + +protected: + int Aspi_ScsiBusScan(); + int Aspi_ScsiInquiry(UI08 ha, UI08 id, UI08 lun, char *destination); + int Aspi_ExecuteSrb(SRB_ExecSCSICmd &srbExec, HANDLE *handle, int nretry); + + int Ioctl_ScsiBusScan(); + int Ioctl_AddAdapter(int adptr_num, UI08 *buffer); + + int InitializeBuffers(); + int ShutdownBuffers(); + int ExtractTocData(UI08 *buffer); + int GetCdvdConfiguration(UI16 feature, UI08 *dest, UI32 dest_size); + + void UpdateInterfaceObject(); + +protected: + + ADAPTERINFO m_drvDetails[CDVD_MAX_SUPPORTED_DRIVES]; + TOCDATA m_tocDetails ; + DECODEDTRACKINFO m_trkDetails; + + SI32 m_nCurrentDrive; + SI32 m_nCurrentBuffer; + + HANDLE m_hIoctlDrv; + HINSTANCE m_hAspi; + BOOL m_bAspiInitialized; + BOOL m_bIoctlInitialized; + BOOL m_bDriveOpened; + UI32 m_nDrives; + SI32 m_nMmcDataMode; + + CDVD_INTERFACE_TYPE m_IntfType; + CDVD_READ_MODE m_nCurrentReadMode; + +protected: + + CDROMSendASPI32Command SendASPI32Command; + CDROMGetASPI32SupportInfo GetASPI32SupportInfo; + ASPI32BUFF m_ReadBuffer[CDVD_NUM_BUFFERS]; // our buffers + + // SRB's for ASPI + SRB_ExecSCSICmd m_srbReadCd [CDVD_NUM_BUFFERS]; + SRB_ExecSCSICmd m_srbRead10 [CDVD_NUM_BUFFERS]; + SRB_ExecSCSICmd m_srbReadMat [CDVD_NUM_BUFFERS]; + SRB_ExecSCSICmd m_srbReadSony[CDVD_NUM_BUFFERS]; + SRB_ExecSCSICmd m_srbReadNec [CDVD_NUM_BUFFERS]; + + // SRB's for IOCTL + SPTD_WITH_SENSE_BUFF m_sptwbReadCd [CDVD_NUM_BUFFERS]; + SPTD_WITH_SENSE_BUFF m_sptwbRead10 [CDVD_NUM_BUFFERS]; + SPTD_WITH_SENSE_BUFF m_sptwbReadMat [CDVD_NUM_BUFFERS]; + SPTD_WITH_SENSE_BUFF m_sptwbReadSony[CDVD_NUM_BUFFERS]; + SPTD_WITH_SENSE_BUFF m_sptwbReadNec [CDVD_NUM_BUFFERS]; + +public: + CCdvd(); + virtual ~CCdvd(); + +}; + +#if defined(CDVD_SIMPLE_INTERFACE) +// declare our global interface functions ;P +EXTERN CCdvd OBJECT_HOLDER_CDVD; +EXTERN CDVD_INTF_FUNC_T1 FUNCTION_GETNUMSECTORS; +EXTERN CDVD_INTF_FUNC_T1 FUNCTION_GETTOC; +EXTERN CDVD_INTF_FUNC_T1 FUNCTION_TESTREADY; +EXTERN CDVD_INTF_FUNC_T2 FUNCTION_SETSPEED; +EXTERN CDVD_INTF_FUNC_T1 FUNCTION_STOP; +EXTERN CDVD_INTF_FUNC_T2 FUNCTION_SETSECTORSIZE; +EXTERN CDVD_INTF_FUNC_T3 FUNCTION_PLAY; +EXTERN CDVD_INTF_FUNC_T4 FUNCTION_READSECTOR; + +// this is where the weird shit starts +// wrap C++ to C, who said i didn't obfuscate :P + +#define cdvd_getnumsectors (OBJECT_HOLDER_CDVD.*FUNCTION_GETNUMSECTORS) +#define cdvd_gettoc (OBJECT_HOLDER_CDVD.*FUNCTION_GETTOC) +#define cdvd_testready (OBJECT_HOLDER_CDVD.*FUNCTION_TESTREADY) +#define cdvd_setspeed (OBJECT_HOLDER_CDVD.*FUNCTION_SETSPEED) +#define cdvd_stop (OBJECT_HOLDER_CDVD.*FUNCTION_STOP) +#define cdvd_setsectorsize (OBJECT_HOLDER_CDVD.*FUNCTION_SETSECTORSIZE) +#define cdvd_play (OBJECT_HOLDER_CDVD.*FUNCTION_PLAY) +#define cdvd_readsector (OBJECT_HOLDER_CDVD.*FUNCTION_READSECTOR) + +#define cdvd_init (OBJECT_HOLDER_CDVD.Init) +#define cdvd_shutdown (OBJECT_HOLDER_CDVD.Shutdown) +#define cdvd_getnumdrives (OBJECT_HOLDER_CDVD.GetNumDrives) +#define cdvd_opendrive (OBJECT_HOLDER_CDVD.OpenDrive) +#define cdvd_closedrive (OBJECT_HOLDER_CDVD.CloseDrive) +#define cdvd_setcurrentbuffer (OBJECT_HOLDER_CDVD.SetCurrentBuffer) +#define cdvd_getsrbstatus (OBJECT_HOLDER_CDVD.GetSrbStatus) +#define cdvd_setreadmode (OBJECT_HOLDER_CDVD.SetReadMode) +#define cdvd_getmediatype (OBJECT_HOLDER_CDVD.GetCdvdMediaType) +#define cdvd_getdrivetype (OBJECT_HOLDER_CDVD.GetCdvdDriveType) +#define cdvd_getadapterdetail (OBJECT_HOLDER_CDVD.GetAdapterDetail) +#define cdvd_gettocdata (OBJECT_HOLDER_CDVD.GetTocData) +#define cdvd_gettrackdetail (OBJECT_HOLDER_CDVD.GetTrackDetail) +#define cdvd_detectandsetreadmode (OBJECT_HOLDER_CDVD.DetectAndSetReadMode) +#define cdvd_getbufferaddress (OBJECT_HOLDER_CDVD.GetBufferAddress) + +#endif + +#endif // !defined(AFX_CDVD_H__1189B8A5_BC21_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/cdvdcompat.cpp b/plugins/cdvd/CDVDdraft/Src/cdvdcompat.cpp new file mode 100644 index 0000000..8340227 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvdcompat.cpp @@ -0,0 +1,194 @@ +// cdvdcompat.cpp: implementation of the cdvdcompat class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "cdvddraft.h" +#include "cdvdcompat.h" +#include "cdvdmisc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +/////////////////////////////////////////////////////////////////////////// +// test cdrom-from old interface ;p // +// added for psemupro compatibility and testing only! // +// although, its seems more stable than my old one hehe.. // +/////////////////////////////////////////////////////////////////////////// + +static char *libraryName = "PSEmuPro (C/DVD) Compatibility Driver"; +const unsigned char version = 1; +const unsigned char revision = 0; +const unsigned char build = 22; + +#define INT2BCD(n) ((n)/10)*16 + (n)%10 +#define BCD2INT(n) ((n & 0x0F) + 10 * ( (n & 0xF0) >> 4)) +#define MSF2SECT(m,s,f) (((m)*60 + (s) - 2)*75 + (f) ) +#define SECT2MSF(sect,m,s,f){ (f) =(UI08)(sect%75);(s) =(UI08)(((sect - (f))/75)%60);(m) = (UI08)((((sect - (f))/75)-(s))/60); } +#define NORMALIZE(m,s,f) { while((f) >= 75){ (f) -= 75; (s) += 1; } while((s) >= 60){ (s) -= 60; (m) += 1;} } + +/*************************************************************************/ +/* psemupro library identifier functions */ +/*************************************************************************/ +char * CALLBACK PSEgetLibName() +{ + return libraryName; +} + +unsigned int CALLBACK PSEgetLibType() +{ + return 1; // PSE_LT_CDR +} + +unsigned int CALLBACK PSEgetLibVersion() +{ + return version<<16|revision<<8|build; +} + +/*************************************************************************/ +/* psemupro config/test functions */ +/*************************************************************************/ + +int CALLBACK CDRconfigure(void) +{ + CDVDconfigure(); + return CDVD_ERROR_SUCCESS; +} + +void CALLBACK CDRabout(void) +{ + CDVDabout(); +} + +int CALLBACK CDRtest(void) +{ + return CDVDtest(); +} + +/*************************************************************************/ +/* psemupro library init/shutdown functions */ +/*************************************************************************/ + +int CALLBACK CDRinit() +{ + return CDVDinit(); +} + +int CALLBACK CDRshutdown() +{ + CDVDshutdown(); + return CDVD_ERROR_SUCCESS; +} + +int CALLBACK CDRopen() +{ + return CDVDopen(); +} + +int CALLBACK CDRclose() +{ + CDVDclose(); + return CDVD_ERROR_SUCCESS; +} + +/*************************************************************************/ +/* psemupro library cdrom functions */ +/*************************************************************************/ + +int CALLBACK CDRgetTN(cdvdTN *buffer) +{ + return CDVDgetTN(buffer); +} + +int CALLBACK CDRgetTD(unsigned char track, unsigned char *buffer) +{ +/* cdvdTD td; + + int retval = CDVDgetTD(track, &td); + + if(retval == CDVD_ERROR_FAIL) + return CDVD_ERROR_FAIL; + + //SECT2MSF(retval, m, s, f); + + NORMALIZE(td.minute, td.second, td.frame); + + buffer[0] = INT2BCD(td.minute); + buffer[2] = INT2BCD(td.frame); + + if(track == 0) + { + buffer[1] = INT2BCD(td.second); + } + else + { + // (add 0:2:0 to convert to pysical addr) + buffer[1] = INT2BCD(td.second+2); + }*/ + + return CDVD_ERROR_SUCCESS; +} + +int CALLBACK CDRreadTrack(unsigned char *time) +{ + int lsn = MSF2SECT(BCD2INT(time[0]), BCD2INT(time[1]), BCD2INT(time[2])); + + return CDVDreadTrack(lsn, CDVD_MODE_2352); +} + +unsigned char *CALLBACK CDRgetBuffer(void) +{ + return (CDVDgetBuffer() + 12); +} + +// heck if i know if this works -_- +int CALLBACK CDRplay(unsigned char *sector) +{ + flush_all(); + int sect = MSF2SECT(sector[0], sector[1], sector[2]); + cdvd_play(sect, 0xFFFFFF); + + return CDVD_ERROR_SUCCESS; +} + +int CALLBACK CDRstop(void) +{ + flush_all(); + cdvd_stop(); + + return CDVD_ERROR_SUCCESS; +} + +/*************************************************************************/ +/* psemupro library extended functions */ +/*************************************************************************/ +typedef struct tagCDRSTAT +{ + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; // current playing time + +} CDRSTAT, *LPCDRSTAT; + +int CALLBACK CDRgetStatus(LPCDRSTAT stat) +{ + memset(stat, 0, sizeof(CDRSTAT)); + + stat->Type = 0x01; //always data for now.. + + if(cdvd_testready() != CDVD_ERROR_SUCCESS) + { + stat->Type = 0xff; + stat->Status |= 0x10; + } + else + { + // new disc, flush cashe markers + flush_all(); + } + + return CDVD_ERROR_SUCCESS; +} diff --git a/plugins/cdvd/CDVDdraft/Src/cdvdcompat.h b/plugins/cdvd/CDVDdraft/Src/cdvdcompat.h new file mode 100644 index 0000000..b99cb05 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvdcompat.h @@ -0,0 +1,20 @@ +// cdvdcompat.h: interface for the cdvdcompat class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CDVDCOMPAT_H__0980F843_C2E7_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CDVDCOMPAT_H__0980F843_C2E7_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class cdvdcompat +{ +public: + cdvdcompat(); + virtual ~cdvdcompat(); + +}; + +#endif // !defined(AFX_CDVDCOMPAT_H__0980F843_C2E7_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.aps b/plugins/cdvd/CDVDdraft/Src/cdvddraft.aps new file mode 100644 index 0000000000000000000000000000000000000000..8e31285b90e0b8eeda410e39fd5c2641280fdee8 GIT binary patch literal 38612 zcmbt-37BJ7b>``I8_5++5y%84o{y9rX51dITU%`=1hhO=DXo%(r0NX^eeLeH>51K~ zl-sBP6NzT2VwtH-)?qRUB?c95hh=}I!noji#AD!n>`1WYLR_QpE@OL^rVDPIBnGaO>Wuo%Ux12fq zw6kY7PTzLPe!6Mn3`m8?`!eoRUNdB6T&rBJrHylUUA%ka%(w%S28=$2QRS)d2AW2ILtHP^fBvPf66OQ~0?b=Qh5j$JlG4^}w|>IDbKZJ4gqPb$Z8wcBj^C^lFW2ld|+MI>7nd z=@z@SG9A7#djs7-@P#rtP%gDQy<)w#(&*KLYL_ybS%g%lBM#JUwt(aml5voBZDo~x z6%>|ruu`+zZLR@aQee&ji;a^&stU;)q||Izf_4}Y|W~ok3Fkq*4D(F>CHi~N~HU$>y^h60( zYbOFNG?S}S(LmKYqEc(DXg}FHnz}CMm3FPw3fjt@3yhOnF<7%*3mVRb6kWab3q7S0?FC70wN`;(FtJ*MW)PwKwCyf^R^76;{-`iF_4LoqpQ5 zH=3#n>jayGH4Ub!wM>zXnyGIlZY|@1tC-|RIbi5v7Cg!Db-j~5l#5P=sM0r3+xRe* zQF_r%jvs`319iCVqJ~sze${*f3ze{kHfDk;(63v#S^8-mLD5DbVxE3OC97Ji2N(>FbM(64y&uU=~$)t(mUQ$E;f1?5`NL~N0M&*JT%6%NNg-ZK3k zi*$lInxai;k^aDf>y1iNN25f4Xr0?Z=v<~hQqISb$ma2=o62YCPo;aY-7YqCADhi* z>C+M`7dz!5=FOaQ`5gV3#Jb$~so8=;^YrI2R80yLTA;s>Xs1=L>8!}l(_botyK6oB zW)Fo7eJ*kiP8f0_OP^P+-23yG7@Sa1E9B@4)}0Gg&2bGE8j1!__A^ySEhc3GgWDwj%7En;>jxQp~Pg{b8Kh7p}n^BMZOa^|kGXPvY34dq;I zw%0IItRiR?z(R(`3TPrjYmE*jJYivBmP_A?Fx4iw_Nnn8ht<-zT@0xSvpk340@|w?-13O`zs6w9 zL3q^S!1IXwG)^#+n>-><2h1!XlFp%Mzj=Uh6hoed3v@6BpK3POYAW4%43$?T;=J@z zaa*862YA-S16_}o0VUlHVdX$6i|~4Cz0-@pETt{j4kGsgU1i;i>)obka!ZKKj72+Z z=+(j!T0$m2*kbi!dnK?~maZ09O?RM6*&IE@I#+@&##L3COW8clS_IW7&{Kz{Y=ItX zff6q_R2eO0=jn%|j8b`lEUc|zCK=|9jqbxdV)2ASG*Ta~!omCk>pWYTmXWQGkVrTj zETfh@QUcu2xQLcfLH@l2!n(1HO8sLDxU1dk!q|0soieYgSO^w-^cV@OHT4{ z0G#Z|SB`FUKu&4|=IJI0a)fpNt3xc%5eaj&C5*vS!clvwW)>(b5$GN;nbyfbk>@1V zEq0F9O?{}M)bkcx!zyC6R##(QHCv^53sr*7(PFub33s!t2GDAyNQ)Nd`7BR&kq%z7 z)6Ev*`JIKb^f(KlHUoj0MtjTAPg-ofp{D*E8A#02<1G|Qh)Hu z+3q5M;6yoSb)jid;xG{jEHhFMd88awEom)SLw5Ue^0Z

lhGxLV;E-p~aK^W`m=o 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 wcw9d=LU{K)_y12X#Cn= g_sectstart[i] && + rq_sector < (g_sectstart[i] + CDVD_NUM_SECTORS_PER_BUFF) + && g_sectstart[i] != -1) + { + rq_isinbuff = TRUE; + g_current_buffnum = i; + break; + } + } + + if(rq_isinbuff == TRUE) + { + // bufffilled? else + if(g_filled[g_current_buffnum] == FALSE) + { + int ret = WaitForSingleObject(g_handle[g_current_buffnum], INFINITE); // ->> check error here! + if(g_status[g_current_buffnum] == CDVD_ERROR_FAIL || + cdvd_getsrbstatus(g_current_buffnum) != CDVD_SRB_COMPLETED) // there was an error + { + TRACE("CDVDreadTrack: error srb not completed1 stat: %ld, srb: %ld\n", g_status[g_current_buffnum], + cdvd_getsrbstatus(g_current_buffnum)); + TRACE("CDVDreadTrack: waitret: %ld, extended: %ld\n", ret, GetLastError()); + //----------------------------------------- + // one last try, we might get lucky :p + cdvd_setcurrentbuffer(g_current_buffnum); + g_status[g_current_buffnum] = cdvd_readsector(rq_sector, NULL); + if(g_status[g_current_buffnum] != CDVD_ERROR_SUCCESS) + return CDVD_ERROR_FAIL; + else + return CDVD_ERROR_SUCCESS; + //----------------------------------------- + //return CDVD_ERROR_FAIL; + } + + g_filled[g_current_buffnum] = TRUE; + } + + int sect_in_buff = rq_sector - g_sectstart[g_current_buffnum]; + + // okay, just send another async read (prefetch) + // ONLY supports 2 buffers + if(g_current_buffmode == CDVD_BUFFER_ASYNC) + { + int altbuff = !g_current_buffnum; + if(g_sectstart[g_current_buffnum] > g_sectstart[altbuff]) + { + TRACE("CDVDreadTrack: sending prefetch.\n"); + WaitForSingleObject(g_handle[altbuff], INFINITE); + g_sectstart[altbuff] = g_sectstart[g_current_buffnum] + CDVD_NUM_SECTORS_PER_BUFF; + cdvd_setcurrentbuffer(altbuff); + _ASSERTE(g_handle[altbuff] != NULL); + g_status[altbuff] = cdvd_readsector(g_sectstart[altbuff], &g_handle[altbuff]); + g_filled[altbuff] = FALSE; + } + } + + g_current_buff = cdvd_getbufferaddress(g_current_buffnum); + static const UI32 mode_pad[] = {0, 12, 24, 24}; + + if(g_current_medtype == CDVD_MEDIATYPE_DVD) + { + g_request_offset = sect_in_buff * CDVD_SECTOR_SIZE_DVD; + } + else + { + g_request_offset = (sect_in_buff * CDVD_SECTOR_SIZE_CD) + mode_pad[mode]; + } + + return CDVD_ERROR_SUCCESS; + } + else + { + for(int i=0; i < max_loop; i++) + { + // wait for any previous srb's pending + if(g_filled[i] == FALSE && + cdvd_getsrbstatus(i) == CDVD_SRB_PENDING) + WaitForSingleObject(g_handle[i], INFINITE); + + g_sectstart[i] = rq_sector + (CDVD_NUM_SECTORS_PER_BUFF * i); + cdvd_setcurrentbuffer(i); + _ASSERTE(g_handle[i] != NULL); + g_status[i] = cdvd_readsector(g_sectstart[i], &g_handle[i]); + + if(g_current_buffmode == CDVD_BUFFER_SYNC) + { + WaitForSingleObject(g_handle[i], INFINITE); + if(g_status[g_current_buffnum] == CDVD_ERROR_FAIL || + cdvd_getsrbstatus(i) != CDVD_SRB_COMPLETED) + { + TRACE("CDVDreadTrack: error srb not completed1 stat: %ld, srb: %ld\n", g_status[i], + cdvd_getsrbstatus(i)); + return CDVD_ERROR_FAIL; + } + g_filled[i] = TRUE; + } + else + { + g_filled[i] = FALSE; + } + } + } + } + + return CDVD_ERROR_SUCCESS; +} + +// getbuffer, retrieve previously read sector buffer +unsigned char *CALLBACK CDVDgetBuffer() +{ + return (g_current_buff + g_request_offset); +} + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + // fake it + u8 min, sec, frm; + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = itob(1); + subq->trackIndex= itob(1); + + lba_to_msf(lsn, &min, &sec, &frm); + subq->trackM = itob(min); + subq->trackS = itob(sec); + subq->trackF = itob(frm); + + subq->pad = 0; + + lba_to_msf(lsn + (2*75), &min, &sec, &frm); + subq->discM = itob(min); + subq->discS = itob(sec); + subq->discF = itob(frm); + return 0; +} + +// retrieve track number +int CALLBACK CDVDgetTN(cdvdTN *buffer) +{ + CHECKLIBRARYOPENED(); + + if(cdvd_gettoc() != CDVD_ERROR_SUCCESS) + return CDVD_ERROR_FAIL; + + g_current_tocdata = cdvd_gettocdata(); + + if(g_current_tocdata.first_track_num == 0 || + g_current_tocdata.last_track_num == 0) + { + //fail? then lie ;P + buffer->strack = 1; + buffer->etrack = 1; + return CDVD_ERROR_SUCCESS; // TODO: or fail??? + } + + buffer->strack = g_current_tocdata.first_track_num; + buffer->etrack = g_current_tocdata.last_track_num; + + //printf("s: %ld, e: %ld\n", buffer->strack, buffer->etrack); + return CDVD_ERROR_SUCCESS; +} + +// retrives total sects OR offset of track +int CALLBACK CDVDgetTD(unsigned char track, cdvdTD *buffer) +{ + CHECKLIBRARYOPENED(); + + if(track == 0) + { + buffer->lsn = cdvd_getnumsectors(); + buffer->type = 0x00; // well, dunno if its even needed here. + + return CDVD_ERROR_SUCCESS; + } + + if(track > 0xAA) // max tracks per session + return CDVD_ERROR_FAIL; + if(cdvd_gettoc() != CDVD_ERROR_SUCCESS) + return CDVD_ERROR_FAIL; + + g_current_trkinfo = cdvd_gettrackdetail(); + + // okay, not sure if you need to add a 0:2:0 lead-in for cds? + buffer->lsn = g_current_trkinfo.track_offset[track-1]; + + switch(g_current_medtype) + { + case CDVD_MEDIATYPE_DVD: + buffer->type = CDVD_MODE1_TRACK; // always data track + break; + case CDVD_MEDIATYPE_CD: + switch(g_current_trkinfo.track_type[track-1]) + { + case 0x01: buffer->type = CDVD_MODE1_TRACK; break; + case 0x02: buffer->type = CDVD_MODE2_TRACK; break; + default: buffer->type = CDVD_AUDIO_TRACK; break; // for 0x00 and everything else + } + break; + default: + buffer->type = CDVD_AUDIO_TRACK; // lets lie. + break; + } + + return CDVD_ERROR_SUCCESS; //g_current_trkinfo.track_offset[track-1]; +} + +s32 CALLBACK CDVDgetTOC(void* toc) { + u8 type = CDVDgetDiskType(); + u8* tocBuff = (u8*)toc; + + if( type == CDVD_TYPE_DVDV || + type == CDVD_TYPE_PS2DVD) + { + // get dvd structure format + // scsi command 0x43 + memset(tocBuff, 0, 2048); + // fake it + tocBuff[ 0] = 0x04; + tocBuff[ 1] = 0x02; + tocBuff[ 2] = 0xF2; + tocBuff[ 3] = 0x00; + tocBuff[ 4] = 0x86; + tocBuff[ 5] = 0x72; + + tocBuff[16] = 0x00; + tocBuff[17] = 0x03; + tocBuff[18] = 0x00; + tocBuff[19] = 0x00; + } + else if(type == CDVD_TYPE_CDDA || + type == CDVD_TYPE_PS2CDDA || + type == CDVD_TYPE_PS2CD || + type == CDVD_TYPE_PSCDDA || + type == CDVD_TYPE_PSCD) + { + // cd toc + // (could be replaced by 1 command that reads the full toc) + u8 min, sec, frm; + s32 i, err; + cdvdTN diskInfo; + cdvdTD trackInfo; + memset(tocBuff, 0, 1024); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + tocBuff[0] = 0x41; + tocBuff[1] = 0x00; + + //Number of FirstTrack + tocBuff[2] = 0xA0; + tocBuff[7] = itob(diskInfo.strack); + + //Number of LastTrack + tocBuff[12] = 0xA1; + tocBuff[17] = itob(diskInfo.etrack); + + //DiskLength + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[22] = 0xA2; + tocBuff[27] = itob(min); + tocBuff[28] = itob(sec); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) + { + err = CDVDgetTD(i, &trackInfo); + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[i*10+30] = trackInfo.type; + tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number + tocBuff[i*10+37] = itob(min); + tocBuff[i*10+38] = itob(sec); + tocBuff[i*10+39] = itob(frm); + } + } + else + return -1; + + return 0; +} + +// return bogus data for now +int CALLBACK CDVDgetDiskType() +{ + CHECKLIBRARYOPENED(); + + int mediatype = cdvd_getmediatype(); + + // TODO: need to retrieve dvd subtype here + if(mediatype == CDVD_MEDIATYPE_DVD) + return CDVD_TYPE_PS2DVD; + + // TODO: need to retrieve cd subtype here + if(mediatype == CDVD_MEDIATYPE_CD) + return CDVD_TYPE_PS2CD; + + return CDVD_TYPE_UNKNOWN; +} + +// return bogus data for now +int CALLBACK CDVDgetTrayStatus() +{ + CHECKLIBRARYOPENED(); + + return CDVD_TRAY_CLOSE; +} + +s32 CALLBACK CDVDctrlTrayOpen() { + return 0; +} +s32 CALLBACK CDVDctrlTrayClose() { + return 0; +} + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.def b/plugins/cdvd/CDVDdraft/Src/cdvddraft.def new file mode 100644 index 0000000..27cd348 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.def @@ -0,0 +1,49 @@ +; cdvddraft.def : Declares the module parameters for the DLL. + +LIBRARY "cdvddraft" +DESCRIPTION 'cdvddraft Windows Dynamic Link Library' + +EXPORTS + ; Explicit exports can go here + + CDVDinit + CDVDshutdown + CDVDopen + CDVDclose + CDVDreadTrack + CDVDgetBuffer + CDVDreadSubQ + CDVDgetTN + CDVDgetTD + CDVDgetTOC + + CDVDconfigure + CDVDtest + CDVDabout + CDVDgetDiskType + CDVDgetTrayStatus + CDVDctrlTrayOpen + CDVDctrlTrayClose + + PS2EgetLibType + PS2EgetLibName + PS2EgetLibVersion2 + + PSEgetLibType + PSEgetLibName + PSEgetLibVersion + + CDRinit + CDRshutdown + CDRopen + CDRclose + CDRconfigure + CDRabout + CDRtest + CDRgetTN + CDRgetTD + CDRreadTrack + CDRgetBuffer + CDRplay + CDRstop + CDRgetStatus diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.dep b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dep new file mode 100644 index 0000000..7456158 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dep @@ -0,0 +1,138 @@ +# Microsoft Developer Studio Generated Dependency File, included by cdvddraft.mak + +.\Config.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\cdvddraft.h"\ + ".\Config.h"\ + ".\constants.h"\ + ".\PS2Edefs.h"\ + ".\PS2Etypes.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\AboutBox.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\AboutBox.h"\ + ".\cdvd.h"\ + ".\cdvddraft.h"\ + ".\constants.h"\ + ".\PS2Edefs.h"\ + ".\PS2Etypes.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\cdvdcompat.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\cdvdcompat.h"\ + ".\cdvddraft.h"\ + ".\cdvdmisc.h"\ + ".\constants.h"\ + ".\PS2Edefs.h"\ + ".\PS2Etypes.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\cdvddraft.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\AboutBox.h"\ + ".\cdvd.h"\ + ".\cdvddraft.h"\ + ".\cdvdmisc.h"\ + ".\Config.h"\ + ".\constants.h"\ + ".\PS2Edefs.h"\ + ".\PS2Etypes.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\cdvddraft.rc : \ + ".\bitmap1.bmp"\ + ".\res\cdvddraft.rc2"\ + + +.\cdvdmisc.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\cdvddraft.h"\ + ".\cdvdmisc.h"\ + ".\constants.h"\ + ".\PS2Edefs.h"\ + ".\PS2Etypes.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\StdAfx.cpp : \ + "..\mssdk\include\basetsd.h"\ + ".\StdAfx.h"\ + + +.\aspi.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\constants.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\cdvd.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\constants.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + + +.\ioctl.cpp : \ + "..\program files\microsoft visual studio\vc98\include\devioctl.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddcdrm.h"\ + "..\program files\microsoft visual studio\vc98\include\ntdddisk.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddscsi.h"\ + "..\program files\microsoft visual studio\vc98\include\ntddstor.h"\ + ".\cdvd.h"\ + ".\constants.h"\ + ".\typedefs.h"\ + ".\winaspi\scsidefs.h"\ + ".\winaspi\wnaspi32.h"\ + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsp b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsp new file mode 100644 index 0000000..9e9b93a --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsp @@ -0,0 +1,219 @@ +# Microsoft Developer Studio Project File - Name="cdvddraft" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=cdvddraft - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cdvddraft.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cdvddraft.mak" CFG="cdvddraft - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cdvddraft - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "cdvddraft - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cdvddraft - Win32 Release" + +# PROP BASE Use_MFC 6 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 6 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /def:".\cdvddraft.def" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "cdvddraft - Win32 Debug" + +# PROP BASE Use_MFC 6 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 6 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__MSCW32__" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__MSCW32__" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /def:".\cdvddraft.def" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "cdvddraft - Win32 Release" +# Name "cdvddraft - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "config" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Config.cpp +# End Source File +# Begin Source File + +SOURCE=.\Config.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\AboutBox.cpp +# End Source File +# Begin Source File + +SOURCE=.\cdvdcompat.cpp +# End Source File +# Begin Source File + +SOURCE=.\cdvddraft.cpp +# End Source File +# Begin Source File + +SOURCE=.\cdvddraft.def +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\cdvddraft.rc +# End Source File +# Begin Source File + +SOURCE=.\cdvdmisc.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\AboutBox.h +# End Source File +# Begin Source File + +SOURCE=.\cdvddraft.h +# End Source File +# Begin Source File + +SOURCE=.\cdvdmisc.h +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\cdvddraft.rc2 +# End Source File +# End Group +# Begin Group "cdvdlib" + +# PROP Default_Filter "" +# Begin Group "headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\cdvd.h +# End Source File +# Begin Source File + +SOURCE=.\constants.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Etypes.h +# End Source File +# Begin Source File + +SOURCE=.\typedefs.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\aspi.cpp +# End Source File +# Begin Source File + +SOURCE=.\cdvd.cpp +# End Source File +# Begin Source File + +SOURCE=.\ioctl.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsw b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsw new file mode 100644 index 0000000..6ebcb10 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cdvddraft"=".\cdvddraft.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.h b/plugins/cdvd/CDVDdraft/Src/cdvddraft.h new file mode 100644 index 0000000..615ff3d --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.h @@ -0,0 +1,56 @@ +// cdvddraft.h : main header file for the CDVDDRAFT DLL +// + +#if !defined(AFX_CDVDDRAFT_H__A0D50EA8_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CDVDDRAFT_H__A0D50EA8_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#define __WIN32__ + +#include "resource.h" // main symbols +#include "ps2etypes.h" +#include "ps2edefs.h" + +#include "cdvd.h" + +#define PLUGIN_REG_PATH _T("Software\\PS2EPlugin\\CDVD\\CdvdXeven") + +/*************************************************************************/ +/* ps2emu library identifier functions */ +/*************************************************************************/ + +unsigned int CALLBACK PS2EgetLibType(); +char *CALLBACK PS2EgetLibName(); +unsigned int CALLBACK PS2EgetLibVersion2(unsigned int type); + +/*************************************************************************/ +/* ps2emu config/test functions */ +/*************************************************************************/ + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +int CALLBACK CDVDtest(); + +/*************************************************************************/ +/* ps2emu library c/dvd functions */ +/*************************************************************************/ + +int CALLBACK CDVDinit(); +void CALLBACK CDVDshutdown(); +int CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +int CALLBACK CDVDreadTrack(unsigned int lsn, int mode); +unsigned char *CALLBACK CDVDgetBuffer(); +int CALLBACK CDVDgetTN(cdvdTN *buffer); +int CALLBACK CDVDgetTD(unsigned char track, cdvdTD *buffer); +int CALLBACK CDVDgetType(); +int CALLBACK CDVDgetTrayStatus(); + +#endif // !defined(AFX_CDVDDRAFT_H__A0D50EA8_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.opt b/plugins/cdvd/CDVDdraft/Src/cdvddraft.opt new file mode 100644 index 0000000000000000000000000000000000000000..aaf488626627ebab6643d50318d1e6b35bb4745d GIT binary patch literal 65024 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.plg b/plugins/cdvd/CDVDdraft/Src/cdvddraft.plg new file mode 100644 index 0000000..3751e46 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.plg @@ -0,0 +1,68 @@ + + +

+

Build Log

+

+--------------------Configuration: cdvddraft - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release/cdvddraft.res" /d "NDEBUG" /d "_AFXDLL" "C:\cdvddraft\cdvddraft.rc"" +Creating temporary file "C:\WINDOWS\TEMP\RSP4241.TMP" with contents +[ +/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Fp"Release/cdvddraft.pch" /Yu"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"C:\cdvddraft\Config.cpp" +"C:\cdvddraft\AboutBox.cpp" +"C:\cdvddraft\cdvdcompat.cpp" +"C:\cdvddraft\cdvddraft.cpp" +"C:\cdvddraft\cdvdmisc.cpp" +"C:\cdvddraft\aspi.cpp" +"C:\cdvddraft\cdvd.cpp" +"C:\cdvddraft\ioctl.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP4241.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP4242.TMP" with contents +[ +/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /Fp"Release/cdvddraft.pch" /Yc"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"C:\cdvddraft\StdAfx.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP4242.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP4243.TMP" with contents +[ +/nologo /subsystem:windows /dll /incremental:no /pdb:"Release/cdvddraft.pdb" /machine:I386 /def:".\cdvddraft.def" /out:"Release/cdvddraft.dll" /implib:"Release/cdvddraft.lib" +.\Release\Config.obj +.\Release\AboutBox.obj +.\Release\cdvdcompat.obj +.\Release\cdvddraft.obj +.\Release\cdvdmisc.obj +.\Release\StdAfx.obj +.\Release\aspi.obj +.\Release\cdvd.obj +.\Release\ioctl.obj +.\Release\cdvddraft.res +] +Creating command line "link.exe @C:\WINDOWS\TEMP\RSP4243.TMP" +

Output Window

+Compiling resources... +Compiling... +StdAfx.cpp +Compiling... +Config.cpp +AboutBox.cpp +cdvdcompat.cpp +cdvddraft.cpp +cdvdmisc.cpp +aspi.cpp +cdvd.cpp +ioctl.cpp +Generating Code... +Linking... +link: executing 'C:\PROGRA~1\MICROS~5\VC98\BIN\link.exe' + Creating library Release/cdvddraft.lib and object Release/cdvddraft.exp + + + +

Results

+cdvddraft.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft.rc b/plugins/cdvd/CDVDdraft/Src/cdvddraft.rc new file mode 100644 index 0000000..a1ba632 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft.rc @@ -0,0 +1,227 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\cdvddraft.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "cdvddraft DLL\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "cdvddraft\0" + VALUE "LegalCopyright", "Copyright (C) 2003\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "cdvddraft.DLL\0" + VALUE "ProductName", "cdvddraft Dynamic Link Library\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 236, 118 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Configure C/DVD Plugin" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,45,97,50,14 + LTEXT "Interface:",IDC_STATIC,8,36,48,8 + PUSHBUTTON "Cancel",IDCANCEL,144,97,50,14 + LTEXT "Read Mode:",IDC_STATIC,134,36,48,8 + COMBOBOX IDC_DRIVE,8,17,218,95,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Buffering Mode:",IDC_STATIC,8,65,65,8 + LTEXT "Drive:",IDC_STATIC,8,7,23,8 + COMBOBOX IDC_INTERFACE,8,46,99,47,CBS_DROPDOWNLIST | WS_DISABLED | + WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_READMODE,128,46,98,58,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + GROUPBOX "",IDC_STATIC,1,1,231,114 + COMBOBOX IDC_PREFETCH,8,75,99,47,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP +END + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 186, 125 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,71,104,50,14 + LTEXT "Coded by Xeven",IDC_STATIC,69,9,61,8 + CONTROL 7010,IDC_STATIC,"Static",SS_BITMAP,67,31,57,50 + LTEXT "http://batard.psxfanatics.com",IDC_STATIC,48,18,97,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 231 + TOPMARGIN, 7 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 118 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog Info +// + +IDD_CONFIG DLGINIT +BEGIN + IDC_INTERFACE, 0x403, 5, 0 +0x5341, 0x4950, "\000" + IDC_INTERFACE, 0x403, 6, 0 +0x4f49, 0x5443, 0x004c, + IDC_READMODE, 0x403, 11, 0 +0x5541, 0x4f54, 0x4544, 0x4554, 0x5443, "\000" + IDC_READMODE, 0x403, 7, 0 +0x4552, 0x4441, 0x4443, "\000" + IDC_READMODE, 0x403, 7, 0 +0x4353, 0x4953, 0x3031, "\000" + IDC_PREFETCH, 0x403, 12, 0 +0x5953, 0x434e, 0x5248, 0x4e4f, 0x554f, 0x0053, + IDC_PREFETCH, 0x403, 13, 0 +0x5341, 0x4e59, 0x4843, 0x4f52, 0x4f4e, 0x5355, "\000" + 0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\cdvddraft.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.sln b/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.sln new file mode 100644 index 0000000..5eaa33f --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdvddraft", "cdvddraft_2003.vcproj", "{1FAB7EBD-BE78-4375-B134-F5295148C5EA}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1FAB7EBD-BE78-4375-B134-F5295148C5EA}.Debug.ActiveCfg = Debug|Win32 + {1FAB7EBD-BE78-4375-B134-F5295148C5EA}.Debug.Build.0 = Debug|Win32 + {1FAB7EBD-BE78-4375-B134-F5295148C5EA}.Release.ActiveCfg = Release|Win32 + {1FAB7EBD-BE78-4375-B134-F5295148C5EA}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.vcproj b/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.vcproj new file mode 100644 index 0000000..5cc6908 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvddraft_2003.vcproj @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDdraft/Src/cdvdmisc.cpp b/plugins/cdvd/CDVDdraft/Src/cdvdmisc.cpp new file mode 100644 index 0000000..8b848e8 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvdmisc.cpp @@ -0,0 +1,93 @@ +// cdvdmisc.cpp: implementation of the cdvdmisc class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "cdvddraft.h" +#include "cdvdmisc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +extern int g_status [CDVD_NUM_BUFFERS]; // status of read to buffer-n +extern HANDLE g_handle [CDVD_NUM_BUFFERS]; // handle used to read to buffer-n +extern int g_sectstart[CDVD_NUM_BUFFERS]; // start of sector read to buffer-n +extern BOOL g_filled [CDVD_NUM_BUFFERS]; // check if buffer-n was filled +extern CDVD_BUFFER_MODE g_current_buffmode; +extern CDVD_INTERFACE_TYPE g_current_intftype; +extern int g_current_drivenum; +extern CDVD_READ_MODE g_current_readmode; + +int init_buffersandflags() +{ + for(int i=0; i +int load_registrysettings() +{ + CRegKey rKey; + + if(rKey.Create(HKEY_CURRENT_USER, PLUGIN_REG_PATH) == ERROR_SUCCESS) + { + DWORD val; + + g_current_readmode = CDVD_READ_UNKNOWN; + if(rKey.QueryValue(val, _T("DriveNum")) == ERROR_SUCCESS) + g_current_drivenum = val; + if(rKey.QueryValue(val, _T("BuffMode")) == ERROR_SUCCESS) + g_current_buffmode = (CDVD_BUFFER_MODE) val; + TRACE("---- buffmode: %ld -----\n", g_current_buffmode); + if(rKey.QueryValue(val, _T("Interface")) == ERROR_SUCCESS) + g_current_intftype = (CDVD_INTERFACE_TYPE) val; + if(rKey.QueryValue(val, _T("ReadMode")) == ERROR_SUCCESS) + { + if(val == 0) g_current_readmode = CDVD_READ_UNKNOWN; + else + g_current_readmode = (CDVD_READ_MODE) (val - 1); + } + rKey.Close(); + } + else return CDVD_ERROR_FAIL; + + return CDVD_ERROR_SUCCESS; +} \ No newline at end of file diff --git a/plugins/cdvd/CDVDdraft/Src/cdvdmisc.h b/plugins/cdvd/CDVDdraft/Src/cdvdmisc.h new file mode 100644 index 0000000..7a3b78b --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/cdvdmisc.h @@ -0,0 +1,17 @@ +// cdvdmisc.h: interface for the cdvdmisc class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CDVDMISC_H__A0D50EB2_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CDVDMISC_H__A0D50EB2_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +int init_buffersandflags(); +int shut_buffersandflags(); +int load_registrysettings(); +int flush_all(); + +#endif // !defined(AFX_CDVDMISC_H__A0D50EB2_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/constants.h b/plugins/cdvd/CDVDdraft/Src/constants.h new file mode 100644 index 0000000..23a9814 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/constants.h @@ -0,0 +1,109 @@ +// constants.h: interface for the constants class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CONSTANTS_H__A0D50EAF_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_CONSTANTS_H__A0D50EAF_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// win32 o/s types +typedef enum WIN32OSTYPE +{ + WIN32S, + WIN95, + WINNTOLD, + WINNTNEW +}; + +// available read modes supported (only mmc & scsi10 are enabled atm) +typedef enum CDVD_READ_MODE +{ + CDVD_READ_MMC = 0, + CDVD_READ_SCSI10 = 1, + CDVD_READ_D8 = 2, // disabled + CDVD_READ_D410 = 3, // disabled + CDVD_READ_D412 = 4, // disabled + CDVD_READ_UNKNOWN = 5, + CDVD_READ_RESERVE = 6, +}; + +// available buffer modes supported (only sync & async are enabled atm) +typedef enum CDVD_BUFFER_MODE +{ + CDVD_BUFFER_SYNC = 0, + CDVD_BUFFER_ASYNC = 1, + CDVD_BUFFER_SINGLE = 2, // unused + CDVD_BUFFER_UNKNOWN = 3, // unused + CDVD_BUFFER_RESERVE = 4 +}; + +// available interfaces (only aspi & ioctl are enabled atm) +typedef enum CDVD_INTERFACE_TYPE +{ + CDVD_INTF_ASPI = 0, + CDVD_INTF_IOCTL = 1, + CDVD_INTF_IOCTL_RAW = 2, // unused + CDVD_INTF_UNKNOWN = 3, // unused + CDVD_INTF_RESERVE = 4 +}; + +// return codes +const int CDVD_ERROR_SUCCESS = 0; +const int CDVD_ERROR_FAIL = -1; +const int CDVD_ERROR_UNINITIALIZED = -2; +const int CDVD_ERROR_PENDING = 1; + +// srb codes +const int CDVD_SRB_ERROR = -1; +const int CDVD_SRB_COMPLETED = 0; +const int CDVD_SRB_PENDING = 1; + +// max number of c/dvd drives to be supported +const int CDVD_MAX_SUPPORTED_DRIVES = 26; + +// max number of sectors returned per read +const int CDVD_NUM_SECTORS_PER_BUFF = 26; + +// num buffers selectable (used by c/dvd reads) +const int CDVD_NUM_BUFFERS = 2; + +// supported sector sizes +const int CDVD_SECTOR_SIZE_CD = 2352; +const int CDVD_SECTOR_SIZE_DVD = 2048; + +// retry for srb +const int CDVD_MAX_RETRY = 2; + +// mmc datamodes (indicates return fields) +const int CDVD_MMC_DATAMODE_RAW = 0xF8; +const int CDVD_MMC_DATAMODE_USER = 0x10; + +// c/dvd drive types +const int CDVD_DRIVETYPE_UNKNOWN = -1; // everything is fucked, dunno what type of drive it is +const int CDVD_DRIVETYPE_CD = 1; // it's a cd ONLY drive +const int CDVD_DRIVETYPE_DVD = 2; // it's a dvd ONLY drive +const int CDVD_DRIVETYPE_CDVD = 3; // it's a c/dvd drive (read's both cdrom & dvd's) + +// c/dvd media types +const int CDVD_MEDIATYPE_UNKNOWN = -1; // everything is fucked, unknown dumbfuck media +const int CDVD_MEDIATYPE_CD = 1; // its a cd, yay (yes i know there's various types of cd's) +const int CDVD_MEDIATYPE_DVD = 2; // it's a dvd, (okay various types of dvd and all that shit, but who cares) + +// prelim, unused +const int CDVD_CDTYPE_UNKNOWN = -1; +const int CDVD_CDTYPE_CDDA = 0; +const int CDVD_CDTYPE_DATA = 1; +const int CDVD_CDTYPE_CDXA = 2; + +// prelim, unused +const int CDVD_DVDTYPE_UNKNOWN = -1; +const int CDVD_DVDTYPE_DVDROM = 0; +const int CDVD_DVDTYPE_DVDMINRW = 1; +const int CDVD_DVDTYPE_DVDPLSRW = 2; +const int CDVD_DVDTYPE_DVDRAM = 3; + + +#endif // !defined(AFX_CONSTANTS_H__A0D50EAF_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/ioctl.cpp b/plugins/cdvd/CDVDdraft/Src/ioctl.cpp new file mode 100644 index 0000000..f0cf3b1 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/ioctl.cpp @@ -0,0 +1,208 @@ +// Ioctl.cpp: implementation of the ioctl methods +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "cdvd.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +/***********************************************************/ +/* IOCTL Init/Shutdown related methods */ +/***********************************************************/ +int CCdvd::Ioctl_Init() +{ + int retval = CDVD_ERROR_FAIL; + + if(m_bIoctlInitialized) + return CDVD_ERROR_SUCCESS; + + + + return retval; +} + +// shuts down ioctl +int CCdvd::Ioctl_Shutdown() +{ + int retval = CDVD_ERROR_SUCCESS; + + + GetNumSectors = Dummy_T1; + GetToc = Dummy_T1; + Stop = Dummy_T1; + Play = Dummy_T3; + TestReady = Dummy_T1; + SetSpeed = Dummy_T2; + SetSectorSize = Dummy_T2; + ReadSector = Dummy_T4; + UpdateInterfaceObject(); + + ShutdownBuffers(); + return retval; +} + +// open a drive for reading +int CCdvd::Ioctl_OpenDrive(int drv_num) +{ + int retval = CDVD_ERROR_SUCCESS; + CloseDrive(); + m_nCurrentDrive = drv_num; + + return retval; +} + +// dummy for now +int CCdvd::Ioctl_CloseDrive() +{ + int retval = CDVD_ERROR_SUCCESS; + m_nCurrentDrive = -1; + + return retval; +} + +// get srb status +int CCdvd::Ioctl_GetSrbStatus(int srb_num) +{ + int retval = CDVD_SRB_ERROR; + switch(m_nCurrentReadMode) + { + case CDVD_READ_MMC: + case CDVD_READ_SCSI10: + case CDVD_READ_D8: + case CDVD_READ_D410: + case CDVD_READ_D412: + default: break; + } + + if(retval == SS_COMP) retval = CDVD_SRB_COMPLETED; + else if(retval == SS_PENDING) retval = CDVD_SRB_PENDING; + else retval = CDVD_SRB_ERROR; + + return retval; +} + +// set read mode +int CCdvd::Ioctl_SetReadMode(CDVD_READ_MODE read_mode) +{ + int retval = CDVD_ERROR_SUCCESS; + + switch(read_mode) + { + case CDVD_READ_MMC: + case CDVD_READ_SCSI10: + case CDVD_READ_D8: + case CDVD_READ_D410: + case CDVD_READ_D412: + default: retval = CDVD_ERROR_FAIL; break; + } + + UpdateInterfaceObject(); + + return retval; +} + +// search for scsi adapters with c/dvd drives. +int CCdvd::Ioctl_ScsiBusScan() +{ + int retval = CDVD_ERROR_SUCCESS; + + HANDLE handle; + char adapter_name[16]; + UI08 buffer[2048]; + int adapter_num = 0; + + memset(m_drvDetails, 0, CDVD_MAX_SUPPORTED_DRIVES * sizeof(ADAPTERINFO)); + + m_nDrives = 0; + for(;;) + { + wsprintf(adapter_name,"\\\\.\\SCSI%d:", adapter_num); + + ++adapter_num; + + if((handle = CreateFile(adapter_name, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL)) == INVALID_HANDLE_VALUE) + { + break; // no more scsi adapters + } + + UI32 nreturned; + if(DeviceIoControl(handle, + IOCTL_SCSI_GET_INQUIRY_DATA, + NULL, + 0, + buffer, + sizeof(buffer), + &nreturned, + FALSE) == 0) + { + continue; // failed + } + + Ioctl_AddAdapter(adapter_num, buffer); + } + + return retval; +} + +// add an adapter to the adapter list +int CCdvd::Ioctl_AddAdapter(int adptr_num, UI08 *buffer) +{ + int retval = CDVD_ERROR_SUCCESS; + + SCSI_ADAPTER_BUS_INFO *adapter_info = (SCSI_ADAPTER_BUS_INFO *) buffer; + char string[40]; + + memset(string, 0, sizeof(string)); + + for (int i = 0; i < adapter_info->NumberOfBuses; i++) + { + SCSI_INQUIRY_DATA *inquiry_data = + (PSCSI_INQUIRY_DATA) (buffer + adapter_info->BusData[i].InquiryDataOffset); + + //while + if(adapter_info->BusData[i].InquiryDataOffset) + { + if(inquiry_data->InquiryData[0] == 0x05) // c/dvd drive + { + m_drvDetails[m_nDrives].ha = adptr_num; + m_drvDetails[m_nDrives].id = inquiry_data->TargetId; + m_drvDetails[m_nDrives].lun = inquiry_data->Lun; + m_drvDetails[m_nDrives].hostname[0] = '\0'; + + memcpy(m_drvDetails[m_nDrives].name, + &inquiry_data->InquiryData[8] + 9, 27); + + m_drvDetails[m_nDrives].name[27] = '\0'; + ++m_nDrives; + } + + if(inquiry_data->NextInquiryDataOffset == 0) + { + break; + } + + inquiry_data = (SCSI_INQUIRY_DATA *) (buffer + inquiry_data->NextInquiryDataOffset); + } + } + + return retval; +} + +/***********************************************************/ +/* IOCTL Execute SRB */ +/***********************************************************/ + +/***********************************************************/ +/* ASPI C/DVD Methods */ +/***********************************************************/ diff --git a/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries b/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries new file mode 100644 index 0000000..964ba3f --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries @@ -0,0 +1,2 @@ +/cdvddraft.rc2/1.1.1.1/Wed Aug 27 00:52:39 2003// +D diff --git a/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries.Extra b/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries.Extra new file mode 100644 index 0000000..c2ebd7b --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/res/CVS/Entries.Extra @@ -0,0 +1 @@ +/cdvddraft.rc2/// diff --git a/plugins/cdvd/CDVDdraft/Src/res/CVS/Repository b/plugins/cdvd/CDVDdraft/Src/res/CVS/Repository new file mode 100644 index 0000000..7dfbb18 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/res/CVS/Repository @@ -0,0 +1 @@ +plugins/cdvd/CDVDdraft/Src/res diff --git a/plugins/cdvd/CDVDdraft/Src/res/CVS/Root b/plugins/cdvd/CDVDdraft/Src/res/CVS/Root new file mode 100644 index 0000000..288eecb --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/res/CVS/Root @@ -0,0 +1 @@ +:ext:aumatt@cvs.sourceforge.net:/cvsroot/pcsx2 diff --git a/plugins/cdvd/CDVDdraft/Src/res/cdvddraft.rc2 b/plugins/cdvd/CDVDdraft/Src/res/cdvddraft.rc2 new file mode 100644 index 0000000..fe54583 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/res/cdvddraft.rc2 @@ -0,0 +1,13 @@ +// +// CDVDDRAFT.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDdraft/Src/resource.h b/plugins/cdvd/CDVDdraft/Src/resource.h new file mode 100644 index 0000000..d97fa4e --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by cdvddraft.rc +// +#define IDD_CONFIG 7000 +#define IDC_COMBO1 7001 +#define IDC_DRIVE 7001 +#define IDC_COMBO2 7002 +#define IDC_INTERFACE 7002 +#define IDC_COMBO3 7003 +#define IDC_READMODE 7003 +#define IDC_PREFETCH 7004 +#define IDD_ABOUT 7007 +#define IDB_BITMAP1 7010 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 7011 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 7000 +#define _APS_NEXT_SYMED_VALUE 7000 +#endif +#endif diff --git a/plugins/cdvd/CDVDdraft/Src/typedefs.h b/plugins/cdvd/CDVDdraft/Src/typedefs.h new file mode 100644 index 0000000..4027655 --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/typedefs.h @@ -0,0 +1,125 @@ +// typedefs.h: interface for the typedefs class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_TYPEDEFS_H__A0D50EB0_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) +#define AFX_TYPEDEFS_H__A0D50EB0_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#if !defined(UI32) +typedef unsigned long UI32; +#endif + +#if !defined(SI32) +typedef long SI32; +#endif + +#if !defined(UI16) +typedef unsigned short UI16; +#endif + +#if !defined(SI16) +typedef short SI16; +#endif + +#if !defined(UI08) +typedef unsigned char UI08; +#endif + +#if !defined(SI08) +typedef char SI08; +#endif + +#if !defined(MAX_PATH) +const int MAX_PATH = 256; +#endif + +#if !defined(EXTERN) +#define EXTERN extern +#endif + +class CCdvd; + +typedef int (CCdvd::*CDVD_INTF_FUNC_T1)(); +typedef int (CCdvd::*CDVD_INTF_FUNC_T2)(int a); +typedef int (CCdvd::*CDVD_INTF_FUNC_T3)(int a, int b); +typedef int (CCdvd::*CDVD_INTF_FUNC_T4)(int a, HANDLE *b); +typedef DWORD (*CDROMSendASPI32Command)(LPSRB); +typedef DWORD (*CDROMGetASPI32SupportInfo)(void); + +// adapater info +typedef struct tagADAPTERINFO +{ + UI08 ha; + UI08 id; + UI08 lun; + char hostname[MAX_PATH]; + char name[MAX_PATH]; + +} ADAPTERINFO, *LPADAPTERINFO; + +// SPTI command buffer +typedef struct tagSPTD_WITH_SENSE_BUFF +{ + SCSI_PASS_THROUGH_DIRECT sptd; + UI32 filler; + UI08 sensebuff[32]; + +} SPTD_WITH_SENSE_BUFF, *PSPTD_WITH_SENSE_BUFF; + +// scsi mode/block selection header +typedef struct tagMODESELHEADER +{ + UI08 reserved1; + UI08 medium; + UI08 reserved2; + UI08 block_desc_length; + UI08 density; + UI08 number_of_blocks_hi; + UI08 number_of_blocks_med; + UI08 number_of_blocks_lo; + UI08 reserved3; + UI08 block_length_hi; + UI08 block_length_med; + UI08 block_length_lo; + +} MODESELHEADER, *PMODESELHEADER; + +// toc track descriptor definition +typedef struct tagTOCTRACKDESCRIPTOR +{ + UI08 reserved1; + UI08 adr_control; + UI08 track_num; // based 1 + UI08 reserved2; + UI08 lba_byte3; + UI08 lba_byte2; + UI08 lba_byte1; + UI08 lba_byte0; + +} TOCTRACK_DESCRIPTOR, *LPTOCTRACKDESCRIPTOR; + +// toc data definition +typedef struct tagTOCDATA +{ + UI08 datalen_byte1; + UI08 datalen_byte0; + UI08 first_track_num; //based 1 + UI08 last_track_num; //based 1 + +} TOCDATA, *LPTOCDATA; + +// information recovered per track (start offset & track_type only) +typedef struct tagDECODEDTRACKINFO +{ + UI32 track_offset[256]; + UI08 track_type[256]; + UI32 total_tracks; + +} DECODEDTRACKINFO, *LPDECODEDTRACKINFO; + + +#endif // !defined(AFX_TYPEDEFS_H__A0D50EB0_BD80_11D7_8E2C_0050DA15DE89__INCLUDED_) diff --git a/plugins/cdvd/CDVDdraft/Src/winaspi/scsidefs.h b/plugins/cdvd/CDVDdraft/Src/winaspi/scsidefs.h new file mode 100644 index 0000000..4f4555a --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/winaspi/scsidefs.h @@ -0,0 +1,279 @@ +#pragma pack(1) + +//*************************************************************************** +// +// Name: SCSIDEFS.H +// +// Description: SCSI definitions ('C' Language) +// +//*************************************************************************** + +//*************************************************************************** +// %%% TARGET STATUS VALUES %%% +//*************************************************************************** +#define STATUS_GOOD 0x00 // Status Good +#define STATUS_CHKCOND 0x02 // Check Condition +#define STATUS_CONDMET 0x04 // Condition Met +#define STATUS_BUSY 0x08 // Busy +#define STATUS_INTERM 0x10 // Intermediate +#define STATUS_INTCDMET 0x14 // Intermediate-condition met +#define STATUS_RESCONF 0x18 // Reservation conflict +#define STATUS_COMTERM 0x22 // Command Terminated +#define STATUS_QFULL 0x28 // Queue full + +//*************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//*************************************************************************** +#define MAXLUN 7 // Maximum Logical Unit Id +#define MAXTARG 7 // Maximum Target Id +#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs +#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Commands for all Device Types %%% +//*************************************************************************** +#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_COPY 0x18 // Copy (O) +#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) +#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) +#define SCSI_LOG_SELECT 0x4C // Log Select (O) +#define SCSI_LOG_SENSE 0x4D // Log Sense (O) +#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) +#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) +#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) +#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) +#define SCSI_READ_BUFF 0x3C // Read Buffer (O) +#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) +#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) +#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Direct Access Devices %%% +//*************************************************************************** +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) +#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) +#define SCSI_PREFETCH 0x34 // Prefetch (O) +#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) +#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) +#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) +#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) +#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) +#define SCSI_READ_LONG 0x3E // Read Long (O) +#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) +#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) +#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) +#define SCSI_REZERO 0x01 // Rezero Unit (O) +#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) +#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) +#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) +#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) +#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) +#define SCSI_SET_LIMIT 0x33 // Set Limits (O) +#define SCSI_START_STP 0x1B // Start/Stop Unit (O) +#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) +#define SCSI_VERIFY 0x2F // Verify (O) +#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) +#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) +#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) +#define SCSI_WRITE_LONG 0x3F // Write Long (O) +#define SCSI_WRITE_SAME 0x41 // Write Same (O) + +//*************************************************************************** +// %%% Commands Unique to Sequential Access Devices %%% +//*************************************************************************** +#define SCSI_ERASE 0x19 // Erase (MANDATORY) +#define SCSI_LOAD_UN 0x1B // Load/Unload (O) +#define SCSI_LOCATE 0x2B // Locate (O) +#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) +#define SCSI_READ_POS 0x34 // Read Position (O) +#define SCSI_READ_REV 0x0F // Read Reverse (O) +#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) +#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) +#define SCSI_REWIND 0x01 // Rewind (MANDATORY) +#define SCSI_SPACE 0x11 // Space (MANDATORY) +#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) +#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Printer Devices %%% +//*************************************************************************** +#define SCSI_PRINT 0x0A // Print (MANDATORY) +#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) +#define SCSI_STOP_PNT 0x1B // Stop Print (O) +#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Processor Devices %%% +//*************************************************************************** +#define SCSI_RECEIVE 0x08 // Receive (O) +#define SCSI_SEND 0x0A // Send (O) + +//*************************************************************************** +// %%% Commands Unique to Write-Once Devices %%% +//*************************************************************************** +#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) +#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) +#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) +#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) +#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) +#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) +#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) +#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) +#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) +#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) +#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) +#define SCSI_WRITE12 0xAA // Write 12-Byte (O) +#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) +#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) + +//*************************************************************************** +// %%% Commands Unique to CD-ROM Devices %%% +//*************************************************************************** +#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) +#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) +#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) +#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) +#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) +#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) +#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) +#define SCSI_READHEADER 0x44 // Read Header (O) +#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) +#define SCSI_READ_TOC 0x43 // Read TOC (O) + +//*************************************************************************** +// %%% Commands Unique to Scanner Devices %%% +//*************************************************************************** +#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) +#define SCSI_GETWINDOW 0x25 // Get Window (O) +#define SCSI_OBJECTPOS 0x31 // Object Postion (O) +#define SCSI_SCAN 0x1B // Scan (O) +#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Optical Memory Devices %%% +//*************************************************************************** +#define SCSI_UpdateBlk 0x3D // Update Block (O) + +//*************************************************************************** +// %%% Commands Unique to Medium Changer Devices %%% +//*************************************************************************** +#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) +#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) +#define SCSI_POSTOELEM 0x2B // Position to Element (O) +#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) +#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) + +//*************************************************************************** +// %%% Commands Unique to Communication Devices %%% +//*************************************************************************** +#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) +#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) +#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) +#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) +#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) +#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% END OF SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Request Sense Data Format %%% +//*************************************************************************** +typedef struct { + + BYTE ErrorCode; // Error Code (70H or 71H) + BYTE SegmentNum; // Number of current segment descriptor + BYTE SenseKey; // Sense Key(See bit definitions too) + BYTE InfoByte0; // Information MSB + BYTE InfoByte1; // Information MID + BYTE InfoByte2; // Information MID + BYTE InfoByte3; // Information LSB + BYTE AddSenLen; // Additional Sense Length + BYTE ComSpecInf0; // Command Specific Information MSB + BYTE ComSpecInf1; // Command Specific Information MID + BYTE ComSpecInf2; // Command Specific Information MID + BYTE ComSpecInf3; // Command Specific Information LSB + BYTE AddSenseCode; // Additional Sense Code + BYTE AddSenQual; // Additional Sense Code Qualifier + BYTE FieldRepUCode; // Field Replaceable Unit Code + BYTE SenKeySpec15; // Sense Key Specific 15th byte + BYTE SenKeySpec16; // Sense Key Specific 16th byte + BYTE SenKeySpec17; // Sense Key Specific 17th byte + BYTE AddSenseBytes; // Additional Sense Bytes + +} SENSE_DATA_FMT; + +//*************************************************************************** +// %%% REQUEST SENSE ERROR CODE %%% +//*************************************************************************** +#define SERROR_CURRENT 0x70 // Current Errors +#define SERROR_DEFERED 0x71 // Deferred Errors + +//*************************************************************************** +// %%% REQUEST SENSE BIT DEFINITIONS %%% +//*************************************************************************** +#define SENSE_VALID 0x80 // Byte 0 Bit 7 +#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 +#define SENSE_EOM 0x40 // Byte 2 Bit 6 +#define SENSE_ILI 0x20 // Byte 2 Bit 5 + +//*************************************************************************** +// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% +//*************************************************************************** +#define KEY_NOSENSE 0x00 // No Sense +#define KEY_RECERROR 0x01 // Recovered Error +#define KEY_NOTREADY 0x02 // Not Ready +#define KEY_MEDIUMERR 0x03 // Medium Error +#define KEY_HARDERROR 0x04 // Hardware Error +#define KEY_ILLGLREQ 0x05 // Illegal Request +#define KEY_UNITATT 0x06 // Unit Attention +#define KEY_DATAPROT 0x07 // Data Protect +#define KEY_BLANKCHK 0x08 // Blank Check +#define KEY_VENDSPEC 0x09 // Vendor Specific +#define KEY_COPYABORT 0x0A // Copy Abort +#define KEY_EQUAL 0x0C // Equal (Search) +#define KEY_VOLOVRFLW 0x0D // Volume Overflow +#define KEY_MISCOMP 0x0E // Miscompare (Search) +#define KEY_RESERVED 0x0F // Reserved + +//*************************************************************************** +// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% +//*************************************************************************** +#define DTYPE_DASD 0x00 // Disk Device +#define DTYPE_SEQD 0x01 // Tape Device +#define DTYPE_PRNT 0x02 // Printer +#define DTYPE_PROC 0x03 // Processor +#define DTYPE_WORM 0x04 // Write-once read-multiple +#define DTYPE_CROM 0x05 // CD-ROM device +#define DTYPE_CDROM 0x05 // CD-ROM device +#define DTYPE_SCAN 0x06 // Scanner device +#define DTYPE_OPTI 0x07 // Optical memory device +#define DTYPE_JUKE 0x08 // Medium Changer device +#define DTYPE_COMM 0x09 // Communications device +#define DTYPE_RESL 0x0A // Reserved (low) +#define DTYPE_RESH 0x1E // Reserved (high) +#define DTYPE_UNKNOWN 0x1F // Unknown or no device type + +//*************************************************************************** +// %%% ANSI APPROVED VERSION DEFINITIONS %%% +//*************************************************************************** +#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand +#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) +#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 +#define ANSI_RESLO 0x3 // Reserved (low) +#define ANSI_RESHI 0x7 // Reserved (high) + +#pragma pack() diff --git a/plugins/cdvd/CDVDdraft/Src/winaspi/wnaspi32.h b/plugins/cdvd/CDVDdraft/Src/winaspi/wnaspi32.h new file mode 100644 index 0000000..99cd6fa --- /dev/null +++ b/plugins/cdvd/CDVDdraft/Src/winaspi/wnaspi32.h @@ -0,0 +1,325 @@ +/****************************************************************************** +** +** Module Name: wnaspi32.h +** +** Description: Header file for ASPI for Win32. This header includes +** macro and type declarations, and can be included without +** modification when using Borland C++ or Microsoft Visual +** C++ with 32-bit compilation. If you are using a different +** compiler then you MUST ensure that structures are packed +** onto byte alignments, and that C++ name mangling is turned +** off. +** +** Notes: This file created using 4 spaces per tab. +** +******************************************************************************/ + +#ifndef __WNASPI32_H__ +#define __WNASPI32_H__ + +/* +** Make sure structures are packed and undecorated. +*/ + +#ifdef __BORLANDC__ +#pragma option -a1 +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack(1) +#endif //__MSC_VER + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//***************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//***************************************************************************** + +#define SENSE_LEN 14 // Default sense buffer length +#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI +#define SRB_POSTING 0x01 // Enable ASPI posting +#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count reporting +#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host +#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI target +#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI event notification + +#define RESIDUAL_COUNT_SUPPORTED 0x02 // Extended buffer flag +#define MAX_SRB_TIMEOUT 108000lu // 30 hour maximum timeout in s +#define DEFAULT_SRB_TIMEOUT 108000lu // Max timeout by default + + +//***************************************************************************** +// %%% ASPI Command Definitions %%% +//***************************************************************************** + +#define SC_HA_INQUIRY 0x00 // Host adapter inquiry +#define SC_GET_DEV_TYPE 0x01 // Get device type +#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command +#define SC_ABORT_SRB 0x03 // Abort an SRB +#define SC_RESET_DEV 0x04 // SCSI bus device reset +#define SC_SET_HA_PARMS 0x05 // Set HA parameters +#define SC_GET_DISK_INFO 0x06 // Get Disk information +#define SC_RESCAN_SCSI_BUS 0x07 // ReBuild SCSI device map +#define SC_GETSET_TIMEOUTS 0x08 // Get/Set target timeouts + +//***************************************************************************** +// %%% SRB Status %%% +//***************************************************************************** + +#define SS_PENDING 0x00 // SRB being processed +#define SS_COMP 0x01 // SRB completed without error +#define SS_ABORTED 0x02 // SRB aborted +#define SS_ABORT_FAIL 0x03 // Unable to abort SRB +#define SS_ERR 0x04 // SRB completed with error + +#define SS_INVALID_CMD 0x80 // Invalid ASPI command +#define SS_INVALID_HA 0x81 // Invalid host adapter number +#define SS_NO_DEVICE 0x82 // SCSI device not installed + +#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB +#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Windows +#define SS_BUFFER_ALIGN 0xE1 // Buffer not aligned (replaces OLD_MANAGER in Win32) +#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode +#define SS_NO_ASPI 0xE3 // No ASPI managers resident +#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init +#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute cmd +#define SS_BUFFER_TO_BIG 0xE6 // Buffer size to big to handle! +#define SS_MISMATCHED_COMPONENTS 0xE7 // The DLLs/EXEs of ASPI don't version check +#define SS_NO_ADAPTERS 0xE8 // No host adapters to manage +#define SS_INSUFFICIENT_RESOURCES 0xE9 // Couldn't allocate resources needed to init +#define SS_ASPI_IS_SHUTDOWN 0xEA // Call came to ASPI after PROCESS_DETACH +#define SS_BAD_INSTALL 0xEB // The DLL or other components are installed wrong + +//***************************************************************************** +// %%% Host Adapter Status %%% +//***************************************************************************** + +#define HASTAT_OK 0x00 // Host adapter did not detect an // error +#define HASTAT_SEL_TO 0x11 // Selection Timeout +#define HASTAT_DO_DU 0x12 // Data overrun data underrun +#define HASTAT_BUS_FREE 0x13 // Unexpected bus free +#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence // failure +#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was waiting to beprocessed. +#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. +#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the // adapter received a MESSAGE +#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. +#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. +#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing + +//***************************************************************************** +// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY (0) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_HA_INQUIRY + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE HA_Count; // 08/008 Number of host adapters present + BYTE HA_SCSI_ID; // 09/009 SCSI ID of host adapter + BYTE HA_ManagerId[16]; // 0A/010 String describing the manager + BYTE HA_Identifier[16]; // 1A/026 String describing the host adapter + BYTE HA_Unique[16]; // 2A/042 Host Adapter Unique parameters + WORD HA_Rsvd1; // 3A/058 Reserved, MUST = 0 +} +SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; + +//***************************************************************************** +// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DEV_TYPE + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_DeviceType; // 0A/010 Target's peripheral device type + BYTE SRB_Rsvd1; // 0B/011 Reserved, MUST = 0 +} +SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; + +//***************************************************************************** +// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_EXEC_SCSI_CMD + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + WORD SRB_Rsvd1; // 0A/010 Reserved for Alignment + DWORD SRB_BufLen; // 0C/012 Data Allocation Length + BYTE FAR *SRB_BufPointer; // 10/016 Data Buffer Pointer + BYTE SRB_SenseLen; // 14/020 Sense Allocation Length + BYTE SRB_CDBLen; // 15/021 CDB Length + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[20]; // 1C/028 Reserved, MUST = 0 + BYTE CDBByte[16]; // 30/048 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 50/064 Request Sense buffer +} +SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; + +//***************************************************************************** +// %%% SRB - ABORT AN SRB - SC_ABORT_SRB (3) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_ABORT_SRB + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + VOID FAR *SRB_ToAbort; // 08/008 Pointer to SRB to abort +} +SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; + +//***************************************************************************** +// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV (4) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESET_DEV + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_Rsvd1[12]; // 0A/010 Reserved for Alignment + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[36]; // 1C/028 Reserved, MUST = 0 +} +SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; + +//***************************************************************************** +// %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DISK_INFO + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_DriveFlags; // 0A/010 Driver flags + BYTE SRB_Int13HDriveInfo; // 0B/011 Host Adapter Status + BYTE SRB_Heads; // 0C/012 Preferred number of heads translation + BYTE SRB_Sectors; // 0D/013 Preferred number of sectors translation + BYTE SRB_Rsvd1[10]; // 0E/014 Reserved, MUST = 0 +} +SRB_GetDiskInfo, *PSRB_GetDiskInfo, FAR *LPSRB_GetDiskInfo; + +//***************************************************************************** +// %%% SRB - RESCAN SCSI BUS(ES) ON SCSIPORT %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESCAN_SCSI_BUS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 +} +SRB_RescanPort, *PSRB_RescanPort, FAR *LPSRB_RescanPort; + +//***************************************************************************** +// %%% SRB - GET/SET TARGET TIMEOUTS %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GETSET_TIMEOUTS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + DWORD SRB_Timeout; // 0A/010 Timeout in half seconds +} +SRB_GetSetTimeouts, *PSRB_GetSetTimeouts, FAR *LPSRB_GetSetTimeouts; + +//***************************************************************************** +// %%% ASPIBUFF - Structure For Controllng I/O Buffers %%% +//***************************************************************************** + +typedef struct tag_ASPI32BUFF // Offset +{ // HX/DEC + PBYTE AB_BufPointer; // 00/000 Pointer to the ASPI allocated buffer + DWORD AB_BufLen; // 04/004 Length in bytes of the buffer + DWORD AB_ZeroFill; // 08/008 Flag set to 1 if buffer should be zeroed + DWORD AB_Reserved; // 0C/012 Reserved +} +ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; + +//***************************************************************************** +// %%% PROTOTYPES - User Callable ASPI for Win32 Functions %%% +//***************************************************************************** + +typedef void *LPSRB; + +#if defined(__BORLANDC__) + +DWORD _import GetASPI32SupportInfo( void ); +DWORD _import SendASPI32Command( LPSRB ); +BOOL _import GetASPI32Buffer( PASPI32BUFF ); +BOOL _import FreeASPI32Buffer( PASPI32BUFF ); +BOOL _import TranslateASPI32Address( PDWORD, PDWORD ); + +#elif defined(_MSC_VER) + +__declspec(dllimport) DWORD GetASPI32SupportInfo( void ); +__declspec(dllimport) DWORD SendASPI32Command( LPSRB ); +__declspec(dllimport) BOOL GetASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL FreeASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#else + +extern DWORD GetASPI32SupportInfo( void ); +extern DWORD GetASPI32Command( LPSRB ); +extern BOOL GetASPI32Buffer( PASPI32BUFF ); +extern BOOL FreeASPI32Buffer( PASPI32BUFF ); +extern BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#endif + +/* +** Restore compiler default packing and close off the C declarations. +*/ + +#ifdef __BORLANDC__ +#pragma option -a. +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack() +#endif //_MSC_VER + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__WNASPI32_H__ diff --git a/plugins/cdvd/CDVDdraft/cdvddraft.dll b/plugins/cdvd/CDVDdraft/cdvddraft.dll new file mode 100644 index 0000000000000000000000000000000000000000..4dccba806178eb1708103369a298da7476467894 GIT binary patch literal 49152 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDiso/ReadMe.txt b/plugins/cdvd/CDVDiso/ReadMe.txt new file mode 100644 index 0000000..b1a9153 --- /dev/null +++ b/plugins/cdvd/CDVDiso/ReadMe.txt @@ -0,0 +1,78 @@ +CDVDiso v0.5 +------------ + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Linux requeriments: +------------------ + You need the GTK library, compiled with GTK v1.2.5, + the Zlib library (v1.1.3) and the bz2 library (v1.0.0). + +Usage: +----- + Place the file "libCDVDiso.so" (linux) or "CDVDiso.dll" (win32) at the Plugin + directory of the Emulator to use it. + + Linux only: Also place the cfgCDVDiso file at your $HOME directory or at the + Emulator directory. + +Configuration: +------------- + You can either write the iso you want to use in the config dialog, or everytime + you run the emu open it, if you're doing this don't write anything in the dialog. + +Creating an iso (linux only): +--------------- + To create an iso you can use the buttons 'Create Iso' or 'Create Compressed Iso', + the file will be the one in the Iso Edit, and the Cdrom Device is the cdrom that + will be used as source. + The compression method is specified by the Compression Method Combo. + + Note: This will fail if the file in the Iso Edit already exists (if it's + compressed the .Z or .bz suffix will be added). + +Compressed isos: +--------------- + You must create them by the Compress Iso button, this will create a .Z or .bz + file (the compressed image) and a .Z.table or .bz.index file (this is a table, + for speed reasons), both will be created in the same dir the selected iso + image, the original image will not be deleted and/or changed, and also you can + decompress the compressed iso with Decompress Iso button. + The compression method is specified by the Compression Method Combo. + + Note: you only can decompress the images with the Decompress button, not with + compress or bzip2. + +Compression Method: +------------------ + .Z - compress faster: this will compress faster, but not as good as the .bz. + .bz - compress better: will compress better, but slower. + +Changes: +------- + v0.5: + * Added block dumping code + * Added BZ2/Z2 format ;) + * Added optimaze asm code of zlib with vsnet2003 only. Compression / Uncompression should be faster now (shadow) + * Added Vsnet2005 beta1 project files + amd64 asm optimaze code for zlib (shadow) + + v0.4: + * Rewrote mostly ;) + * .bz is still unsupported + + v0.3: + * Better Iso detection, thx florin :) + * Updated to PS2Edefs v0.4.5 + + v0.2: + * Added support for isos using 2048 blocksize + * Nero images are supported + * Better extension filtering + + v0.1: + * First Release + * Tested with Pcsx2 + + Email: diff --git a/plugins/cdvd/CDVDiso/build.sh b/plugins/cdvd/CDVDiso/build.sh new file mode 100644 index 0000000..3f569fb --- /dev/null +++ b/plugins/cdvd/CDVDiso/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +curdir=`pwd` + +echo ---------------- +echo Building CDVDiso +echo ---------------- + +cd ${curdir}/src/Linux +make $@ + +# copy the files +if [ -s cfgCDVDiso ] && [ -s libCDVDiso.so ] +then +cp cfgCDVDiso libCDVDiso.so ${PCSX2PLUGINS} +fi diff --git a/plugins/cdvd/CDVDiso/src/CDVDiso.c b/plugins/cdvd/CDVDiso/src/CDVDiso.c new file mode 100644 index 0000000..57ea57c --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/CDVDiso.c @@ -0,0 +1,341 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "CDVDiso.h" +#include "Config.h" + +#ifndef MAX_PATH +#define MAX_PATH 255 +#endif + +char *methods[] = { + ".Z - compress faster", + ".BZ - compress better", + NULL +}; + +#ifdef _DEBUG +char *LibName = "Linuzappz Iso CDVD (Debug) "; +#else +char *LibName = "Linuzappz Iso CDVD "; +#endif + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 0; +const unsigned char build = 6; + +s32 msf_to_lba(u8 m, u8 s, u8 f) { + u32 lsn; + lsn = f; + lsn+=(s - 2) * 75; + lsn+= m * 75 * 60; + return lsn; +} + +void lba_to_msf(s32 lba, u8* m, u8* s, u8* f) { + lba += 150; + *m = lba / (60*75); + *s = (lba / 75) % 60; + *f = lba % 75; +} + +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ + + +char* CALLBACK PS2EgetLibName() { + return LibName; +} + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_CDVD; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version << 16) | (revision << 8) | build; +} + +#ifdef CDVD_LOG +void __Log(char *fmt, ...) { + va_list list; + + va_start(list, fmt); + vfprintf(cdvdLog, fmt, list); + va_end(list); +} +#endif + + +s32 CALLBACK CDVDinit() { +#ifdef CDVD_LOG + cdvdLog = fopen("logs/cdvdLog.txt", "w"); + if (cdvdLog == NULL) { + cdvdLog = fopen("cdvdLog.txt", "w"); + if (cdvdLog == NULL) { + SysMessage("Can't create cdvdLog.txt"); return -1; + } + } + setvbuf(cdvdLog, NULL, _IONBF, 0); + CDVD_LOG("CDVDinit\n"); +#endif + memset(cdIso, 0, sizeof(cdIso)); + return 0; +} + +void CALLBACK CDVDshutdown() { +#ifdef CDVD_LOG + fclose(cdvdLog); +#endif +} + +s32 CALLBACK CDVDopen(const char* pTitle) { + LoadConf(); + + if( pTitle != NULL ) strcpy(IsoFile, pTitle); + + if (*IsoFile == 0) { + char temp[256]; + + CfgOpenFile(); + + LoadConf(); + strcpy(temp, IsoFile); + *IsoFile = 0; + SaveConf(); + strcpy(IsoFile, temp); + } + + iso = isoOpen(IsoFile); + if (iso == NULL) { + SysMessage("Error loading %s\n", IsoFile); + return -1; + } + + if (iso->type == ISOTYPE_DVD) { + cdtype = CDVD_TYPE_PS2DVD; + } else + if (iso->type == ISOTYPE_AUDIO) { + cdtype = CDVD_TYPE_CDDA; + } else { + cdtype = CDVD_TYPE_PS2CD; + } + + if (BlockDump) { + char fname_only[MAX_PATH]; + char* p, *plast; + +#ifdef _WIN32 + char fname[MAX_PATH],ext[MAX_PATH]; + _splitpath(IsoFile,NULL,NULL,fname,ext); + _makepath(fname_only,NULL,NULL,fname,NULL); +#else + plast = p = strchr(IsoFile, '/'); + while(p != NULL) { + plast = p; + p = strchr(p+1, '/'); + } + + if( plast != NULL ) strcpy(fname_only, plast+1); + else strcpy(fname_only, IsoFile); + + plast = p = strchr(fname_only, '.'); + while(p != NULL) { + plast = p; + p = strchr(p+1, '.'); + } + + if( plast != NULL ) *plast = 0; + +#endif + strcat(fname_only, ".dump"); + fdump = isoCreate(fname_only, ISOFLAGS_BLOCKDUMP); + if (fdump) { + isoSetFormat(fdump, iso->blockofs, iso->blocksize, iso->blocks); + } + } else { + fdump = NULL; + } + + return 0; +} + +void CALLBACK CDVDclose() { + isoClose(iso); + if (fdump != NULL) { + isoClose(fdump); + } +} + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + // fake it + u8 min, sec, frm; + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = itob(1); + subq->trackIndex= itob(1); + + lba_to_msf(lsn, &min, &sec, &frm); + subq->trackM = itob(min); + subq->trackS = itob(sec); + subq->trackF = itob(frm); + + subq->pad = 0; + + lba_to_msf(lsn + (2*75), &min, &sec, &frm); + subq->discM = itob(min); + subq->discS = itob(sec); + subq->discF = itob(frm); + return 0; +} + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + Buffer->strack = 1; + Buffer->etrack = 1; + + return 0; +} + +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer) { + if (Track == 0) { + Buffer->lsn = iso->blocks; + } else { + Buffer->type = CDVD_MODE1_TRACK; + Buffer->lsn = 0; + } + + return 0; +} + +s32 CALLBACK CDVDgetTOC(void* toc) { + u8 type = CDVDgetDiskType(); + u8* tocBuff = (u8*)toc; + + if( type == CDVD_TYPE_DVDV || + type == CDVD_TYPE_PS2DVD) + { + // get dvd structure format + // scsi command 0x43 + memset(tocBuff, 0, 2048); + // fake it + tocBuff[ 0] = 0x04; + tocBuff[ 1] = 0x02; + tocBuff[ 2] = 0xF2; + tocBuff[ 3] = 0x00; + tocBuff[ 4] = 0x86; + tocBuff[ 5] = 0x72; + + tocBuff[16] = 0x00; + tocBuff[17] = 0x03; + tocBuff[18] = 0x00; + tocBuff[19] = 0x00; + } + else if(type == CDVD_TYPE_CDDA || + type == CDVD_TYPE_PS2CDDA || + type == CDVD_TYPE_PS2CD || + type == CDVD_TYPE_PSCDDA || + type == CDVD_TYPE_PSCD) + { + // cd toc + // (could be replaced by 1 command that reads the full toc) + u8 min, sec, frm; + s32 i, err; + cdvdTN diskInfo; + cdvdTD trackInfo; + memset(tocBuff, 0, 1024); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + tocBuff[0] = 0x41; + tocBuff[1] = 0x00; + + //Number of FirstTrack + tocBuff[2] = 0xA0; + tocBuff[7] = itob(diskInfo.strack); + + //Number of LastTrack + tocBuff[12] = 0xA1; + tocBuff[17] = itob(diskInfo.etrack); + + //DiskLength + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[22] = 0xA2; + tocBuff[27] = itob(min); + tocBuff[28] = itob(sec); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) + { + err = CDVDgetTD(i, &trackInfo); + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[i*10+30] = trackInfo.type; + tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number + tocBuff[i*10+37] = itob(min); + tocBuff[i*10+38] = itob(sec); + tocBuff[i*10+39] = itob(frm); + } + } + else + return -1; + + return 0; +} + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + int _lsn = lsn; + if (_lsn < 0) { +// lsn = 2097152 + (-_lsn); + lsn = iso->blocks - (-_lsn); + } +// printf ("CDRreadTrack %d\n", lsn); + + isoReadBlock(iso, cdbuffer, lsn); + if (fdump != NULL) { + isoWriteBlock(fdump, cdbuffer, lsn); + } + + pbuffer = cdbuffer; + switch (mode) { + case CDVD_MODE_2352: break; + case CDVD_MODE_2340: pbuffer+= 12; break; + case CDVD_MODE_2328: pbuffer+= 24; break; + case CDVD_MODE_2048: pbuffer+= 24; break; + } + + return 0; +} + +u8* CALLBACK CDVDgetBuffer() { + return pbuffer; +} + +s32 CALLBACK CDVDgetDiskType() { + return cdtype; +} + +s32 CALLBACK CDVDgetTrayStatus() { + return CDVD_TRAY_CLOSE; +} + +s32 CALLBACK CDVDctrlTrayOpen() { + return 0; +} +s32 CALLBACK CDVDctrlTrayClose() { + return 0; +} + + +s32 CALLBACK CDVDtest() { + if (*IsoFile == 0) + return 0; + + iso = isoOpen(IsoFile); + if (iso == NULL) return -1; + isoClose(iso); + + return 0; +} + diff --git a/plugins/cdvd/CDVDiso/src/CDVDiso.h b/plugins/cdvd/CDVDiso/src/CDVDiso.h new file mode 100644 index 0000000..5a303e8 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/CDVDiso.h @@ -0,0 +1,80 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifdef __MSCW32__ +#pragma warning(disable:4018) +#endif + +#define CDVDdefs +#include "PS2Edefs.h" +#include "libiso.h" + +//#define CDVD_LOG __Log +FILE *cdvdLog; + +void __Log(char *fmt, ...); + +#define VERBOSE 1 + +char IsoFile[256]; +#define DEV_DEF "" +char CdDev[256]; +#define CDDEV_DEF "/dev/cdrom" +int BlockDump; +isoFile *fdump; + +isoFile *iso; + +typedef struct { + int slsn; + int elsn; +#ifdef __WIN32__ + HANDLE handle; +#else + FILE *handle; +#endif +} _cdIso; +_cdIso cdIso[8]; + +#define CD_FRAMESIZE_RAW 2352 +#define DATA_SIZE (CD_FRAMESIZE_RAW-12) + +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ + +#define MSF2SECT(m,s,f) (((m)*60+(s)-2)*75+(f)) + +unsigned char cdbuffer[CD_FRAMESIZE_RAW * 10]; +unsigned char *pbuffer; +int cdblocksize; +int cdblockofs; +int cdoffset; +int cdtype; +int cdblocks; + +int Zmode; // 1 Z - 2 bz2 +int fmode; // 0 - file / 1 - Zfile +char *Ztable; + +extern char *methods[]; + +void UpdateZmode(); +void CfgOpenFile(); +void SysMessage(char *fmt, ...); + diff --git a/plugins/cdvd/CDVDiso/src/Linux/CDVDiso.glade b/plugins/cdvd/CDVDiso/src/Linux/CDVDiso.glade new file mode 100644 index 0000000..4123673 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/CDVDiso.glade @@ -0,0 +1,368 @@ + + + + + cdriso + cdriso + + + + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + CDVD Config Dialog + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkHBox + hbox1 + False + 10 + + 0 + True + True + + + + GtkEntry + GtkEntry_Iso + True + True + True + 0 + + + 0 + True + True + + + + + GtkButton + button5 + True + + clicked + OnFileSel + Tue, 19 Feb 2002 05:35:24 GMT + + + GTK_RELIEF_NORMAL + + 0 + False + False + + + + + + GtkHBox + hbox2 + False + 10 + + 0 + False + False + + + + GtkProgressBar + GtkProgressBar_Progress + 0 + 0 + 100 + GTK_PROGRESS_CONTINUOUS + GTK_PROGRESS_LEFT_TO_RIGHT + False + False + %P %% + 0.5 + 0.5 + + 0 + True + False + + + + + GtkButton + button6 + 61 + True + + clicked + OnStop + Tue, 19 Feb 2002 05:34:11 GMT + + + GTK_RELIEF_NORMAL + + 0 + False + False + GTK_PACK_END + + + + + + GtkHBox + hbox4 + False + 5 + + 0 + True + True + + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Method + False + True + False + True + False + + + 0 + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Compress + True + True + + clicked + OnCompress + Tue, 19 Feb 2002 05:40:44 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Decompress + True + True + + clicked + OnDecompress + Tue, 19 Feb 2002 06:56:17 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHBox + hbox3 + False + 5 + + 0 + False + False + + + + GtkLabel + label1 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + GtkEntry_CdDev + True + True + True + 0 + + + 0 + True + True + + + + + + GtkHButtonBox + hbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + GtkButton_Create + True + True + + clicked + OnCreate + Tue, 19 Feb 2002 21:06:29 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_CreateZ + True + True + + clicked + OnCreateZ + Tue, 19 Feb 2002 21:06:19 GMT + + + GTK_RELIEF_NORMAL + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnOk + Tue, 19 Feb 2002 05:42:17 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnCancel + Tue, 19 Feb 2002 05:42:24 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/cdvd/CDVDiso/src/Linux/Config.c b/plugins/cdvd/CDVDiso/src/Linux/Config.c new file mode 100644 index 0000000..c5eea54 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/Config.c @@ -0,0 +1,59 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "CDVDiso.h" + +void LoadConf() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/CDVDiso.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + strcpy(IsoFile, DEV_DEF); + strcpy(CdDev, CDDEV_DEF); + return; + } + fscanf(f, "IsoFile = %[^\n]\n", IsoFile); + fscanf(f, "CdDev = %[^\n]\n", CdDev); + if (!strncmp(IsoFile, "CdDev =", 9)) *IsoFile = 0; // quick fix + if (*CdDev == 0) strcpy(CdDev, CDDEV_DEF); + fclose(f); +} + +void SaveConf() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/CDVDiso.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fprintf(f, "IsoFile = %s\n", IsoFile); + fprintf(f, "CdDev = %s\n", CdDev); + fclose(f); +} + diff --git a/plugins/cdvd/CDVDiso/src/Linux/Config.h b/plugins/cdvd/CDVDiso/src/Linux/Config.h new file mode 100644 index 0000000..d1df0d3 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/Config.h @@ -0,0 +1,20 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void SaveConf(); +void LoadConf(); diff --git a/plugins/cdvd/CDVDiso/src/Linux/Linux.c b/plugins/cdvd/CDVDiso/src/Linux/Linux.c new file mode 100644 index 0000000..70947b5 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/Linux.c @@ -0,0 +1,76 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "Config.h" +#include "CDVDiso.h" + +void ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgCDVDiso"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + strcpy(cfg, "./cfg/cfgCDVDiso"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + sprintf(cfg, "%s/cfgCDVDiso", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + system(cfg); return; + } + + printf("cfgCDVDiso file not found!\n"); +} + +void CDVDconfigure() { + ExecCfg("configure"); +} + +void CDVDabout() { + ExecCfg("about"); +} + +void CfgOpenFile() { + ExecCfg("open"); +} + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[256]; + char cmd[256]; + + va_start(list, fmt); + vsprintf(tmp, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", tmp); + ExecCfg(cmd); +} diff --git a/plugins/cdvd/CDVDiso/src/Linux/Makefile b/plugins/cdvd/CDVDiso/src/Linux/Makefile new file mode 100644 index 0000000..62128c1 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/Makefile @@ -0,0 +1,34 @@ + +CC = gcc + +PLUGIN = libCDVDiso.so +CFG = cfgCDVDiso +MKISO = mkiso +CFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -I.. -I. -D__LINUX__ +OBJS = ../CDVDiso.o Config.o Linux.o ../libiso.o +CFGOBJS = conf.o interface.o support.o ${OBJS} +LIBS = -lz -lbz2 -lstdc++ +CFGLIBS = $(shell pkg-config --libs gtk+-2.0) ${LIBS} +CFLAGS += $(shell pkg-config --cflags gtk+-2.0) +DEPS:= $(OBJS:.o=.d) $(CFGOBJS:.o=.d) + +all: plugin cfg +install: all + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} + rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} ${CFGOBJS} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/cdvd/CDVDiso/src/Linux/callbacks.c b/plugins/cdvd/CDVDiso/src/Linux/callbacks.c new file mode 100644 index 0000000..3fe79a9 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/callbacks.c @@ -0,0 +1,98 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnFileSel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnStop (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCreate (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCompress (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfig_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConfig_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnOk (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnDecompress (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCreate (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnCreateZ (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/cdvd/CDVDiso/src/Linux/callbacks.h b/plugins/cdvd/CDVDiso/src/Linux/callbacks.h new file mode 100644 index 0000000..0d24ea4 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/callbacks.h @@ -0,0 +1,46 @@ +#include + + +void +OnFileSel (GtkButton *button, + gpointer user_data); + +void +OnStop (GtkButton *button, + gpointer user_data); + +void +OnCreate (GtkButton *button, + gpointer user_data); + +void +OnCompress (GtkButton *button, + gpointer user_data); + +void +OnConfig_Ok (GtkButton *button, + gpointer user_data); + +void +OnConfig_Cancel (GtkButton *button, + gpointer user_data); + +void +OnOk (GtkButton *button, + gpointer user_data); + +void +OnCancel (GtkButton *button, + gpointer user_data); + +void +OnDecompress (GtkButton *button, + gpointer user_data); + +void +OnCreate (GtkButton *button, + gpointer user_data); + +void +OnCreateZ (GtkButton *button, + gpointer user_data); diff --git a/plugins/cdvd/CDVDiso/src/Linux/conf.c b/plugins/cdvd/CDVDiso/src/Linux/conf.c new file mode 100644 index 0000000..9f2c132 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/conf.c @@ -0,0 +1,865 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "CDVDiso.h" +#include "Config.h" + +unsigned char Zbuf[CD_FRAMESIZE_RAW * 10 * 2]; + +extern char *LibName; + +extern const unsigned char revision; +extern const unsigned char build; + +GtkWidget *FileSel; + +void OnFile_Ok() { + gchar *File; + + gtk_widget_hide(FileSel); + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + strcpy(IsoFile, File); + gtk_main_quit(); +} + +void OnFile_Cancel() { + gtk_widget_hide(FileSel); + gtk_main_quit(); +} + +void _CDRopen() { + GtkWidget *Ok, *Cancel; + + FileSel = gtk_file_selection_new("Select Iso File"); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect(GTK_OBJECT(Ok), "clicked", + GTK_SIGNAL_FUNC(OnFile_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect(GTK_OBJECT(Cancel), "clicked", + GTK_SIGNAL_FUNC(OnFile_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); + + gtk_main(); + + SaveConf(); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +static void SysMessageLoc(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + int w; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + w = strlen(msg) * 6 + 20; + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_usize(MsgDlg, w, 70); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "cdriso Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 0); + + Box = gtk_vbox_new(0, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *ConfDlg; +GtkWidget *Edit, *CdEdit; +GtkWidget *FileSel; +GtkWidget *Progress; +GtkWidget *BtnCompress; +GtkWidget *BtnDecompress; +GtkWidget *BtnCreate; +GtkWidget *BtnCreateZ; +GtkWidget *Method; + +GList *methodlist; +extern char *methods[]; + +int stop; + +void OnOk(GtkMenuItem * menuitem, gpointer userdata) { + char *tmp; + + stop=1; + tmp = gtk_entry_get_text(GTK_ENTRY(Edit)); + strcpy(IsoFile, tmp); + tmp = gtk_entry_get_text(GTK_ENTRY(CdEdit)); + strcpy(CdDev, tmp); + SaveConf(); + gtk_widget_destroy(ConfDlg); + gtk_main_quit(); +} + +void OnCancel(GtkMenuItem * menuitem, gpointer userdata) { + stop=1; + gtk_widget_destroy(ConfDlg); + gtk_main_quit(); +} + +void OnFileSel_Ok() { + gchar *File; + + File = gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel)); + gtk_entry_set_text(GTK_ENTRY(Edit), File); + gtk_widget_destroy(FileSel); +} + +void OnFileSel_Cancel() { + gtk_widget_destroy(FileSel); +} + +void OnFileSel() { + GtkWidget *Ok,*Cancel; + + FileSel = gtk_file_selection_new("Select Psx Iso File"); + gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), IsoFile); + + Ok = GTK_FILE_SELECTION(FileSel)->ok_button; + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnFileSel_Ok), NULL); + gtk_widget_show(Ok); + + Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button; + gtk_signal_connect (GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnFileSel_Cancel), NULL); + gtk_widget_show(Cancel); + + gtk_widget_show(FileSel); + gdk_window_raise(FileSel->window); +} + +void OnStop() { + stop=1; +} + +void UpdZmode() { + char *tmp; + + tmp = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(Method)->entry)); + if (!strcmp(tmp, methods[0])) Zmode = 1; + else Zmode = 2; +} + +char buffer[2352 * 10]; + +void OnCompress() { + struct stat buf; + u32 lsn; + u8 cdbuff[10*2352]; + char Zfile[256]; + char *tmp; + int ret; + isoFile *src; + isoFile *dst; + + tmp = gtk_entry_get_text(GTK_ENTRY(Edit)); + strcpy(IsoFile, tmp); + UpdZmode(); + + if (Zmode == 1) sprintf(Zfile, "%s.Z2", IsoFile); + if (Zmode == 2) sprintf(Zfile, "%s.BZ2", IsoFile); + + if (stat(Zfile, &buf) != -1) { + char str[256]; + return; +/* sprintf(str, "'%s' already exists, overwrite?", Zfile); + if (MessageBox(hDlg, str, "Question", MB_YESNO) != IDYES) { + return; + }*/ + } + + src = isoOpen(IsoFile); + if (src == NULL) return; + dst = isoCreate(Zfile, Zmode == 1 ? ISOFLAGS_Z2 : ISOFLAGS_BZ2); + if (dst == NULL) return; + + gtk_widget_set_sensitive(BtnCompress, FALSE); + gtk_widget_set_sensitive(BtnDecompress, FALSE); + gtk_widget_set_sensitive(BtnCreate, FALSE); + gtk_widget_set_sensitive(BtnCreateZ, FALSE); + stop=0; + + for (lsn = 0; lsnblocks; lsn++) { + printf("block %d ", lsn); + putchar(13); + fflush(stdout); + ret = isoReadBlock(src, cdbuff, lsn); + if (ret == -1) break; + ret = isoWriteBlock(dst, cdbuff, lsn); + if (ret == -1) break; + + gtk_progress_bar_update(GTK_PROGRESS_BAR(Progress), (lsn * 100) / src->blocks); + while (gtk_events_pending()) gtk_main_iteration(); + if (stop) break; + } + isoClose(src); + isoClose(dst); + + if (!stop) gtk_entry_set_text(GTK_ENTRY(Edit), IsoFile); + + gtk_widget_set_sensitive(BtnCompress, TRUE); + gtk_widget_set_sensitive(BtnDecompress, TRUE); + gtk_widget_set_sensitive(BtnCreate, TRUE); + gtk_widget_set_sensitive(BtnCreateZ, TRUE); + + if (!stop) { + if (ret == -1) { + SysMessageLoc("Error compressing iso image"); + } else { + SysMessageLoc("Iso image compressed OK"); + } + } +} + +void OnDecompress() { +#if 0 + struct stat buf; + FILE *f; + unsigned long c=0, p=0, s; + char table[256]; + char *tmp; + int blocks; + + tmp = gtk_entry_get_text(GTK_ENTRY(Edit)); + strcpy(IsoFile, tmp); + + if (strstr(IsoFile, ".Z") != NULL) Zmode = 1; + else Zmode = 2; + + strcpy(table, IsoFile); + if (Zmode == 1) strcat(table, ".table"); + else strcat(table, ".index"); + + if (stat(table, &buf) == -1) { + return; + } + if (Zmode == 1) c = s = buf.st_size / 6; + else c = s = (buf.st_size / 4) - 1; + f = fopen(table, "rb"); + Ztable = (char*)malloc(buf.st_size); + fread(Ztable, 1, buf.st_size, f); + fclose(f); + + cdHandle[0] = fopen(IsoFile, "rb"); + if (cdHandle[0] == NULL) { + return; + } + + if (Zmode == 1) IsoFile[strlen(IsoFile) - 2] = 0; + else IsoFile[strlen(IsoFile) - 3] = 0; + + f = fopen(IsoFile, "wb"); + if (f == NULL) { + return; + } + + gtk_widget_set_sensitive(BtnCompress, FALSE); + gtk_widget_set_sensitive(BtnDecompress, FALSE); + gtk_widget_set_sensitive(BtnCreate, FALSE); + gtk_widget_set_sensitive(BtnCreateZ, FALSE); + stop=0; + + if (Zmode == 1) { + blocks = 1; + } else { + blocks = 10; + } + + while (c--) { + unsigned long size, pos, ssize; + float per; + + if (Zmode == 1) { + pos = *(unsigned long*)&Ztable[p * 6]; + fseek(cdHandle[0], pos, SEEK_SET); + + ssize = *(unsigned short*)&Ztable[p * 6 + 4]; + fread(Zbuf, 1, ssize, cdHandle[0]); + } else { + pos = *(unsigned long*)&Ztable[p * 4]; + fseek(cdHandle[0], pos, SEEK_SET); + + ssize = *(unsigned long*)&Ztable[p * 4 + 4] - pos; + fread(Zbuf, 1, ssize, cdHandle[0]); + } + + size = CD_FRAMESIZE_RAW * blocks; + if (Zmode == 1) uncompress(cdbuffer, &size, Zbuf, ssize); + else BZ2_bzBuffToBuffDecompress(cdbuffer, (unsigned int*)&size, Zbuf, ssize, 0, 0); + + fwrite(cdbuffer, 1, size, f); + + p++; + + per = ((float)p / s); + gtk_progress_bar_update(GTK_PROGRESS_BAR(Progress), per); + while (gtk_events_pending()) gtk_main_iteration(); + if (stop) break; + } + if (!stop) gtk_entry_set_text(GTK_ENTRY(Edit), IsoFile); + + fclose(f); + fclose(cdHandle[0]); cdHandle[0] = NULL; + free(Ztable); Ztable = NULL; + + gtk_widget_set_sensitive(BtnCompress, TRUE); + gtk_widget_set_sensitive(BtnDecompress, TRUE); + gtk_widget_set_sensitive(BtnCreate, TRUE); + gtk_widget_set_sensitive(BtnCreateZ, TRUE); + + if (!stop) SysMessageLoc("Iso Image Decompressed OK"); +#endif +} + +#define CD_LEADOUT (0xaa) +unsigned char param[4]; +int cddev = -1; + +union { + struct cdrom_msf msf; + unsigned char buf[CD_FRAMESIZE_RAW]; +} cr; + +void incSector() { + param[2]++; + if (param[2] == 75) { + param[2] = 0; + param[1]++; + } + if (param[1] == 60) { + param[1] = 0; + param[0]++; + } +} + +long CDR_open(void) { + if (cddev != -1) + return 0; + cddev = open(CdDev, O_RDONLY); + if (cddev == -1) { + printf("CDR: Could not open %s\n", CdDev); + return -1; + } + + return 0; +} + +long CDR_close(void) { + if (cddev == -1) return 0; + close(cddev); + cddev = -1; + + return 0; +} + +// return Starting and Ending Track +// buffer: +// byte 0 - start track +// byte 1 - end track +long CDR_getTN(unsigned char *buffer) { + struct cdrom_tochdr toc; + + if (ioctl(cddev, CDROMREADTOCHDR, &toc) == -1) return -1; + + buffer[0] = toc.cdth_trk0; // start track + buffer[1] = toc.cdth_trk1; // end track + + return 0; +} + +// return Track Time +// buffer: +// byte 0 - frame +// byte 1 - second +// byte 2 - minute +long CDR_getTD(unsigned char track, unsigned char *buffer) { + struct cdrom_tocentry entry; + + if (track == 0) track = 0xaa; // total time + entry.cdte_track = track; + entry.cdte_format = CDROM_MSF; + + if (ioctl(cddev, CDROMREADTOCENTRY, &entry) == -1) return -1; + + buffer[0] = entry.cdte_addr.msf.minute; /* minute */ + buffer[1] = entry.cdte_addr.msf.second; /* second */ + buffer[2] = entry.cdte_addr.msf.frame; /* frame */ + + return 0; +} + +// read track +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame +char *CDR_readTrack(unsigned char *time) { + cr.msf.cdmsf_min0 = time[0]; + cr.msf.cdmsf_sec0 = time[1]; + cr.msf.cdmsf_frame0 = time[2]; + + if (ioctl(cddev, CDROMREADRAW, &cr) == -1) return NULL; + return cr.buf; +} + + +void OnCreate() { + FILE *f; + struct stat buf; + struct tm *Tm; + time_t Ttime; + unsigned long ftrack, ltrack; + unsigned long p=0,s; + unsigned char *buffer; + unsigned char bufferz[2352]; + unsigned char start[4], end[4]; + char *tmp; +#ifdef VERBOSE + unsigned long count = 0; + int i=0; +#endif + + memset(bufferz, 0, sizeof(bufferz)); + ftrack = 1; + ltrack = CD_LEADOUT; + + tmp = gtk_entry_get_text(GTK_ENTRY(Edit)); + strcpy(IsoFile, tmp); + + if (stat(IsoFile, &buf) == 0) { + printf("File %s Already exists\n", IsoFile); + return; + } + + if (CDR_open() == -1) { + return; + } + + if (CDR_getTD(ftrack, start) == -1) { + printf("Error getting TD\n"); + + CDR_close(); + return; + } + if (CDR_getTD(ltrack, end) == -1) { + printf("Error getting TD\n"); + + CDR_close(); + return; + } + + f = fopen(IsoFile, "wb"); + if (f == NULL) { + CDR_close(); + printf("Error opening %s", IsoFile); + return; + } + + printf("Making Iso: from %2.2d:%2.2d:%2.2d to %2.2d:%2.2d:%2.2d\n", + start[0], start[1], start[2], end[0], end[1], end[2]); + + memcpy(param, start, 3); + + time(&Ttime); + + stop = 0; + s = MSF2SECT(end[0], end[1], end[2]); + gtk_widget_set_sensitive(BtnCompress, FALSE); + gtk_widget_set_sensitive(BtnDecompress, FALSE); + gtk_widget_set_sensitive(BtnCreate, FALSE); + gtk_widget_set_sensitive(BtnCreateZ, FALSE); + + for (;;) { /* loop until end */ + float per; + + if ((param[0] == end[0]) & (param[1] == end[1]) & (param[2] == end[2])) + break; + buffer = CDR_readTrack(param); + if (buffer == NULL) { + int i; + + for (i=0; i<10; i++) { + buffer = CDR_readTrack(param); + if (buffer != NULL) break; + } + if (buffer == NULL) { + printf("Error Reading %2d:%2d:%2d\n", param[0], param[1], param[2]); + buffer = bufferz; + buffer[12] = param[0]; + buffer[13] = param[1]; + buffer[14] = param[2]; + buffer[15] = 0x2; + } + } + fwrite(buffer, 1, 2352, f); +#ifdef VERBOSE + count+= CD_FRAMESIZE_RAW; + + printf("reading %2d:%2d:%2d ", param[0], param[1], param[2]); + if ((time(NULL) - Ttime) != 0) { + i = (count / 1024) / (time(NULL) - Ttime); + printf("( %5dKbytes/s, %dX)", i, i / 150); + } + putchar(13); + fflush(stdout); +#endif + + incSector(); + + p++; + per = ((float)p / s); + gtk_progress_bar_update(GTK_PROGRESS_BAR(Progress), per); + while (gtk_events_pending()) gtk_main_iteration(); + if (stop) break; + } + + Ttime = time(NULL) - Ttime; + Tm = gmtime(&Ttime); + printf("\nTotal Time used: %d:%d:%d\n", Tm->tm_hour, Tm->tm_min, + Tm->tm_sec); + + CDR_close(); + fclose(f); + + gtk_widget_set_sensitive(BtnCompress, TRUE); + gtk_widget_set_sensitive(BtnDecompress, TRUE); + gtk_widget_set_sensitive(BtnCreate, TRUE); + gtk_widget_set_sensitive(BtnCreateZ, TRUE); + + if (!stop) SysMessageLoc("Iso Image Created OK"); +} + +void OnCreateZ() { + FILE *f; + FILE *t; + struct stat buf; + struct tm *Tm; + time_t Ttime; + unsigned long ftrack, ltrack; + unsigned long p=0,s,c=0; + unsigned char *buffer; + unsigned char bufferz[2352]; + unsigned char start[4], end[4]; + char table[256]; + char *tmp; + int b, blocks; +#ifdef VERBOSE + unsigned long count = 0; + int i=0; +#endif + + memset(bufferz, 0, sizeof(bufferz)); + ftrack = 1; + ltrack = CD_LEADOUT; + + tmp = gtk_entry_get_text(GTK_ENTRY(Edit)); + strcpy(IsoFile, tmp); + + UpdZmode(); + + if (Zmode == 1) { + blocks = 1; + if (strstr(IsoFile, ".Z") == NULL) strcat(IsoFile, ".Z"); + } else { + blocks = 10; + if (strstr(IsoFile, ".bz") == NULL) strcat(IsoFile, ".bz"); + } + if (stat(IsoFile, &buf) == 0) { + printf("File %s Already exists\n", IsoFile); + return; + } + + strcpy(table, IsoFile); + if (Zmode == 1) strcat(table, ".table"); + else strcat(table, ".index"); + + t = fopen(table, "wb"); + if (t == NULL) { + return; + } + + if (CDR_open() == -1) { + return; + } + + if (CDR_getTD(ftrack, start) == -1) { + printf("Error getting TD\n"); + + CDR_close(); + return; + } + if (CDR_getTD(ltrack, end) == -1) { + printf("Error getting TD\n"); + + CDR_close(); + return; + } + + f = fopen(IsoFile, "wb"); + if (f == NULL) { + CDR_close(); + printf("Error opening %s", IsoFile); + return; + } + + printf("Making Iso: from %2.2d:%2.2d:%2.2d to %2.2d:%2.2d:%2.2d\n", + start[0], start[1], start[2], end[0], end[1], end[2]); + + memcpy(param, start, 3); + + time(&Ttime); + + stop = 0; + s = MSF2SECT(end[0], end[1], end[2]) / blocks; + gtk_widget_set_sensitive(BtnCompress, FALSE); + gtk_widget_set_sensitive(BtnDecompress, FALSE); + gtk_widget_set_sensitive(BtnCreate, FALSE); + gtk_widget_set_sensitive(BtnCreateZ, FALSE); + + for (;;) { /* loop until end */ + unsigned long size; + unsigned char Zbuf[CD_FRAMESIZE_RAW * 10 * 2]; + float per; + + for (b=0; btm_hour, Tm->tm_min, + Tm->tm_sec); + + CDR_close(); + fclose(f); + fclose(t); + + gtk_widget_set_sensitive(BtnCompress, TRUE); + gtk_widget_set_sensitive(BtnDecompress, TRUE); + gtk_widget_set_sensitive(BtnCreate, TRUE); + gtk_widget_set_sensitive(BtnCreateZ, TRUE); + + if (!stop) SysMessageLoc("Compressed Iso Image Created OK"); +} + +long CDRconfigure(void) { + int i; + + LoadConf(); + + ConfDlg = create_Config(); + + Edit = lookup_widget(ConfDlg, "GtkEntry_Iso"); + gtk_entry_set_text(GTK_ENTRY(Edit), IsoFile); + CdEdit = lookup_widget(ConfDlg, "GtkEntry_CdDev"); + gtk_entry_set_text(GTK_ENTRY(CdEdit), CdDev); + + Progress = lookup_widget(ConfDlg, "GtkProgressBar_Progress"); + + BtnCompress = lookup_widget(ConfDlg, "GtkButton_Compress"); + BtnDecompress = lookup_widget(ConfDlg, "GtkButton_Decompress"); + BtnCreate = lookup_widget(ConfDlg, "GtkButton_Create"); + BtnCreateZ = lookup_widget(ConfDlg, "GtkButton_CreateZ"); + + methodlist = NULL; + for (i=0; i<2; i++) + methodlist = g_list_append(methodlist, methods[i]); + Method = lookup_widget(ConfDlg, "GtkCombo_Method"); + gtk_combo_set_popdown_strings(GTK_COMBO(Method), methodlist); + if (strstr(IsoFile, ".Z") != NULL) + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(Method)->entry), methods[0]); + else gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(Method)->entry), methods[1]); + + gtk_widget_show_all(ConfDlg); + gtk_main(); + + return 0; +} + +GtkWidget *AboutDlg; + +void OnAboutOk(GtkMenuItem * menuitem, gpointer userdata) { + gtk_widget_hide(AboutDlg); + gtk_main_quit(); +} + +void CDRabout(void) { + GtkWidget *Label; + GtkWidget *Ok; + GtkWidget *Box, *BBox; + char AboutText[255]; + + sprintf(AboutText, "%s %d.%d\n", LibName, revision, build); + + AboutDlg = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_usize(AboutDlg, 260, 80); + gtk_window_set_title(GTK_WINDOW(AboutDlg), "CDVD About Dialog"); + gtk_window_set_position(GTK_WINDOW(AboutDlg), GTK_WIN_POS_CENTER); + gtk_container_set_border_width(GTK_CONTAINER(AboutDlg), 10); + + Box = gtk_vbox_new(0, 0); + gtk_container_add(GTK_CONTAINER(AboutDlg), Box); + gtk_widget_show(Box); + + Label = gtk_label_new(AboutText); + gtk_box_pack_start(GTK_BOX(Box), Label, FALSE, FALSE, 0); + gtk_widget_show(Label); + + BBox = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), BBox, FALSE, FALSE, 0); + gtk_widget_show(BBox); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect(GTK_OBJECT(Ok), "clicked", + GTK_SIGNAL_FUNC(OnAboutOk), NULL); + gtk_container_add(GTK_CONTAINER(BBox), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(AboutDlg); + gtk_main(); +} + +int main(int argc, char *argv[]) { + if (argc < 2) return 0; + + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "open")) { + _CDRopen(); + } else if (!strcmp(argv[1], "configure")) { + CDRconfigure(); + } else if (!strcmp(argv[1], "message")) { + if (argc > 2) SysMessageLoc(argv[2]); + } else { + CDRabout(); + } + + return 0; +} + + diff --git a/plugins/cdvd/CDVDiso/src/Linux/interface.c b/plugins/cdvd/CDVDiso/src/Linux/interface.c new file mode 100644 index 0000000..bec825d --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/interface.c @@ -0,0 +1,253 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *hbox1; + GtkWidget *GtkEntry_Iso; + GtkWidget *button5; + GtkWidget *hbox2; + GtkWidget *GtkProgressBar_Progress; + GtkWidget *button6; + GtkWidget *hbox4; + GtkWidget *label2; + GtkWidget *GtkCombo_Method; + GtkWidget *combo_entry1; + GtkWidget *hbuttonbox2; + GtkWidget *GtkButton_Compress; + GtkWidget *GtkButton_Decompress; + GtkWidget *hbox3; + GtkWidget *label1; + GtkWidget *GtkEntry_CdDev; + GtkWidget *hbuttonbox3; + GtkWidget *GtkButton_Create; + GtkWidget *GtkButton_CreateZ; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "CDVD Config Dialog"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + hbox1 = gtk_hbox_new (FALSE, 10); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0); + + GtkEntry_Iso = gtk_entry_new (); + gtk_widget_ref (GtkEntry_Iso); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkEntry_Iso", GtkEntry_Iso, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_Iso); + gtk_box_pack_start (GTK_BOX (hbox1), GtkEntry_Iso, TRUE, TRUE, 0); + + button5 = gtk_button_new_with_label ("Select Iso"); + gtk_widget_ref (button5); + gtk_object_set_data_full (GTK_OBJECT (Config), "button5", button5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button5); + gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0); + + hbox2 = gtk_hbox_new (FALSE, 10); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, FALSE, 0); + + GtkProgressBar_Progress = gtk_progress_bar_new (); + gtk_widget_ref (GtkProgressBar_Progress); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkProgressBar_Progress", GtkProgressBar_Progress, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkProgressBar_Progress); + gtk_box_pack_start (GTK_BOX (hbox2), GtkProgressBar_Progress, TRUE, FALSE, 0); + + button6 = gtk_button_new_with_label ("Stop"); + gtk_widget_ref (button6); + gtk_object_set_data_full (GTK_OBJECT (Config), "button6", button6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button6); + gtk_box_pack_end (GTK_BOX (hbox2), button6, FALSE, FALSE, 0); + gtk_widget_set_usize (button6, 61, -2); + + hbox4 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox4); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox4", hbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox4); + gtk_box_pack_start (GTK_BOX (vbox1), hbox4, TRUE, TRUE, 0); + + label2 = gtk_label_new ("Compression Method:"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (Config), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (hbox4), label2, FALSE, FALSE, 0); + + GtkCombo_Method = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Method); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Method", GtkCombo_Method, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Method); + gtk_box_pack_start (GTK_BOX (hbox4), GtkCombo_Method, TRUE, FALSE, 0); + + combo_entry1 = GTK_COMBO (GtkCombo_Method)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox2, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox2), 0); + + GtkButton_Compress = gtk_button_new_with_label ("Compress Iso"); + gtk_widget_ref (GtkButton_Compress); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkButton_Compress", GtkButton_Compress, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Compress); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), GtkButton_Compress); + GTK_WIDGET_SET_FLAGS (GtkButton_Compress, GTK_CAN_DEFAULT); + + GtkButton_Decompress = gtk_button_new_with_label ("Decompress Iso"); + gtk_widget_ref (GtkButton_Decompress); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkButton_Decompress", GtkButton_Decompress, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Decompress); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), GtkButton_Decompress); + GTK_WIDGET_SET_FLAGS (GtkButton_Decompress, GTK_CAN_DEFAULT); + + hbox3 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox3); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox3", hbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox3); + gtk_box_pack_start (GTK_BOX (vbox1), hbox3, FALSE, FALSE, 0); + + label1 = gtk_label_new ("Cdrom Device: "); + gtk_widget_ref (label1); + gtk_object_set_data_full (GTK_OBJECT (Config), "label1", label1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label1); + gtk_box_pack_start (GTK_BOX (hbox3), label1, FALSE, FALSE, 0); + + GtkEntry_CdDev = gtk_entry_new (); + gtk_widget_ref (GtkEntry_CdDev); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkEntry_CdDev", GtkEntry_CdDev, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkEntry_CdDev); + gtk_box_pack_start (GTK_BOX (hbox3), GtkEntry_CdDev, TRUE, TRUE, 0); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox3", hbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox3, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox3), 0); + + GtkButton_Create = gtk_button_new_with_label ("Create Iso"); + gtk_widget_ref (GtkButton_Create); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkButton_Create", GtkButton_Create, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Create); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_Create); + GTK_WIDGET_SET_FLAGS (GtkButton_Create, GTK_CAN_DEFAULT); + + GtkButton_CreateZ = gtk_button_new_with_label ("Create Compressed Iso"); + gtk_widget_ref (GtkButton_CreateZ); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkButton_CreateZ", GtkButton_CreateZ, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_CreateZ); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), GtkButton_CreateZ); + GTK_WIDGET_SET_FLAGS (GtkButton_CreateZ, GTK_CAN_DEFAULT); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox1), 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button5), "clicked", + GTK_SIGNAL_FUNC (OnFileSel), + NULL); + gtk_signal_connect (GTK_OBJECT (button6), "clicked", + GTK_SIGNAL_FUNC (OnStop), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Compress), "clicked", + GTK_SIGNAL_FUNC (OnCompress), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Decompress), "clicked", + GTK_SIGNAL_FUNC (OnDecompress), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Create), "clicked", + GTK_SIGNAL_FUNC (OnCreate), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_CreateZ), "clicked", + GTK_SIGNAL_FUNC (OnCreateZ), + NULL); + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnOk), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnCancel), + NULL); + + return Config; +} + diff --git a/plugins/cdvd/CDVDiso/src/Linux/interface.h b/plugins/cdvd/CDVDiso/src/Linux/interface.h new file mode 100644 index 0000000..3f7353b --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/interface.h @@ -0,0 +1,5 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); diff --git a/plugins/cdvd/CDVDiso/src/Linux/support.c b/plugins/cdvd/CDVDiso/src/Linux/support.c new file mode 100644 index 0000000..a917d4f --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/cdvd/CDVDiso/src/Linux/support.h b/plugins/cdvd/CDVDiso/src/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/cdvd/CDVDiso/src/PS2Edefs.h b/plugins/cdvd/CDVDiso/src/PS2Edefs.h new file mode 100644 index 0000000..ef33df3 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/PS2Edefs.h @@ -0,0 +1,812 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDiso/src/PS2Etypes.h b/plugins/cdvd/CDVDiso/src/PS2Etypes.h new file mode 100644 index 0000000..3a63c58 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.sln b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.sln new file mode 100644 index 0000000..b1a6c9e --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "CDVDiso 2005 x64.vcproj", "{BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release|x64.ActiveCfg = Release|x64 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.vcproj b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.vcproj new file mode 100644 index 0000000..57c4f93 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso 2005 x64.vcproj @@ -0,0 +1,561 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.def b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.def new file mode 100644 index 0000000..cb35900 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.def @@ -0,0 +1,29 @@ +; CDVDiso.def : Declares the module parameters for the DLL. + +LIBRARY "CDVDiso" +DESCRIPTION 'CDVDiso Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + CDVDinit @5 + CDVDshutdown @6 + CDVDopen @7 + CDVDclose @8 + CDVDreadTrack @9 + CDVDgetBuffer @10 + CDVDreadSubQ @11 + CDVDgetTN @12 + CDVDgetTD @13 + CDVDgetTOC @14 + CDVDgetDiskType @15 + CDVDgetTrayStatus @16 + CDVDctrlTrayOpen @17 + CDVDctrlTrayClose @18 + + CDVDconfigure @19 + CDVDtest @20 + CDVDabout @21 + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsp b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsp new file mode 100644 index 0000000..3fcc620 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="CDVDiso" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=CDVDiso - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "CDVDiso.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "CDVDiso.mak" CFG="CDVDiso - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "CDVDiso - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "__MSCW32__" /D "_MBCS" /D "_USRDLL" /D "CDVDiso_EXPORTS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "__MSCW32__" /D "_MBCS" /D "_USRDLL" /D "CDVDiso_EXPORTS" /D "__WIN32__" /D "_LARGEFILE_SOURCE" /D _FILE_OFFSET_BITS=64 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x408 /d "NDEBUG" +# ADD RSC /l 0x408 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib libbz2.lib zlib.lib /nologo /dll /machine:I386 /nodefaultlib:"msvcrt.lib" +# SUBTRACT LINK32 /nodefaultlib +# Begin Target + +# Name "CDVDiso - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\CDVDiso.c +# End Source File +# Begin Source File + +SOURCE=.\CDVDiso.def +# End Source File +# Begin Source File + +SOURCE=.\Config.c +# End Source File +# Begin Source File + +SOURCE=..\libiso.c +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\CDVDiso.h +# End Source File +# Begin Source File + +SOURCE=.\Config.h +# End Source File +# Begin Source File + +SOURCE=..\libiso.h +# End Source File +# Begin Source File + +SOURCE=..\PS2Edefs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\CDVDiso.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsw b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsw new file mode 100644 index 0000000..df2f338 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.dsw @@ -0,0 +1,30 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "CDVDiso"=".\CDVDiso.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.rc b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.rc new file mode 100644 index 0000000..f43e876 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.rc @@ -0,0 +1,134 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 212, 161 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDconfigure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,105,140,50,14 + EDITTEXT IDC_ISOFILE,10,10,145,14,ES_AUTOHSCROLL + PUSHBUTTON "Cancel",IDCANCEL,160,140,50,14 + PUSHBUTTON "Select Iso",IDC_SELECTISO,160,10,45,14 + PUSHBUTTON "Compress Iso",IDC_COMPRESSISO,33,75,65,14 + PUSHBUTTON "Decompress Iso",IDC_DECOMPRESSISO,113,75,65,14 + COMBOBOX IDC_METHOD,120,55,85,50,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER | + 0x1,10,35,145,14 + LTEXT "Compression Method:",IDC_STATIC,29,57,69,8 + PUSHBUTTON "Stop",IDC_STOP,160,35,45,14 + GROUPBOX "",IDC_STATIC,5,0,205,95 + GROUPBOX "Options",IDC_STATIC,5,100,205,30 + CONTROL "Enable Block Dump => ""ISO name.dump""",IDC_BLOCKDUMP, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,115,148,10 +END + +IDD_ABOUT DIALOG 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "CDVDabout" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "CDVDiso Driver",IDC_NAME,70,10,50,8 + GROUPBOX "",IDC_STATIC,5,35,170,40 + LTEXT "Thanks to:\n mooby - coding hints and .bz support\n Brenden Conte - linux conf bugfix", + IDC_STATIC,10,45,160,25 + LTEXT "Author: linuzappz ",IDC_STATIC, + 20,20,141,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 154 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.sln b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.sln new file mode 100644 index 0000000..0e80670 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "CDVDiso.vcproj", "{BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release.ActiveCfg = Release|Win32 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.vcproj b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.vcproj new file mode 100644 index 0000000..1157f3a --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso.vcproj @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.sln b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.sln new file mode 100644 index 0000000..6ff0d45 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "CDVDiso_2003.vcproj", "{BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release.ActiveCfg = Release|Win32 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.vcproj b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.vcproj new file mode 100644 index 0000000..ac5e3a7 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2003.vcproj @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.sln b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.sln new file mode 100644 index 0000000..b8f64bb --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDiso", "CDVDiso_2005.vcproj", "{BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Debug|Win32.ActiveCfg = Debug|Win32 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Debug|Win32.Build.0 = Debug|Win32 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release|Win32.ActiveCfg = Release|Win32 + {BB27CC2C-28D1-4438-A0DF-3E120D01EDEC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.vcproj b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.vcproj new file mode 100644 index 0000000..09994ac --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/CDVDiso_2005.vcproj @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDiso/src/Win32/Config.c b/plugins/cdvd/CDVDiso/src/Win32/Config.c new file mode 100644 index 0000000..ecf4d4c --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/Config.c @@ -0,0 +1,45 @@ +#include +#include + +#include "CDVDiso.h" + +#define GetKeyV(name, var, s, t) \ + size = s; type = t; \ + RegQueryValueEx(myKey, name, 0, &type, (LPBYTE) var, &size); + +#define GetKeyVdw(name, var) \ + GetKeyV(name, var, 4, REG_DWORD); + +#define SetKeyV(name, var, s, t) \ + RegSetValueEx(myKey, name, 0, t, (LPBYTE) var, s); + +#define SetKeyVdw(name, var) \ + SetKeyV(name, var, 4, REG_DWORD); + +void SaveConf() { + HKEY myKey; + DWORD myDisp; + + RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\CDVD\\CDVDiso", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &myDisp); + + SetKeyV("IsoFile", IsoFile, sizeof(IsoFile), REG_BINARY); + SetKeyVdw("BlockDump", &BlockDump); + + RegCloseKey(myKey); +} + +void LoadConf() { + HKEY myKey; + DWORD type, size; + + memset(IsoFile, 0, sizeof(IsoFile)); + + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\CDVD\\CDVDiso", 0, KEY_ALL_ACCESS, &myKey)!=ERROR_SUCCESS) { + SaveConf(); return; + } + + GetKeyV("IsoFile", IsoFile, sizeof(IsoFile), REG_BINARY); + GetKeyVdw("BlockDump", &BlockDump); + + RegCloseKey(myKey); +} diff --git a/plugins/cdvd/CDVDiso/src/Win32/Config.h b/plugins/cdvd/CDVDiso/src/Win32/Config.h new file mode 100644 index 0000000..0ce9be1 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/Config.h @@ -0,0 +1,3 @@ +void SaveConf(); +void LoadConf(); + diff --git a/plugins/cdvd/CDVDiso/src/Win32/Makefile b/plugins/cdvd/CDVDiso/src/Win32/Makefile new file mode 100644 index 0000000..483698a --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/Makefile @@ -0,0 +1,57 @@ +# +# Makefile for MINGW32 +# + + +all: cdvdiso + +PLUGIN = CDVDiso.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 #-lintl +RESOBJ = cdvdiso.o + +OBJS = ../CDVDiso.o ../libiso.o +OBJS+= Config.o Win32.o ${RESOBJ} +OBJS+= ../zlib/adler32.o ../zlib/compress.o ../zlib/crc32.o ../zlib/gzio.o ../zlib/uncompr.o ../zlib/deflate.o ../zlib/trees.o \ + ../zlib/zutil.o ../zlib/inflate.o ../zlib/infback.o ../zlib/inftrees.o ../zlib/inffast.o +OBJS+= ../bzip2/blocksort.o ../bzip2/bzlib.o \ + ../bzip2/compress.o ../bzip2/crctable.o \ + ../bzip2/decompress.o ../bzip2/huffman.o \ + ../bzip2/randtable.o + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I/usr/local/include -I../zlib -I../bzip2 ${FLAGS} + +cdvdiso: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean cdvdiso + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: CDVDiso.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + + \ No newline at end of file diff --git a/plugins/cdvd/CDVDiso/src/Win32/Win32.c b/plugins/cdvd/CDVDiso/src/Win32/Win32.c new file mode 100644 index 0000000..7c9c88c --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/Win32.c @@ -0,0 +1,311 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "Config.h" +#include "CDVDiso.h" +#include "resource.h" + +HINSTANCE hInst; +#define MAXFILENAME 256 + +u8 Zbuf[2352 * 10 * 2]; +HWND hDlg; +HWND hProgress; +HWND hIsoFile; +HWND hMethod; +HWND hBlockDump; +int stop; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "CDVDiso Msg", 0); +} + +int _GetFile(char *out) { + OPENFILENAME ofn; + char szFileName[MAXFILENAME]; + char szFileTitle[MAXFILENAME]; + + memset(&szFileName, 0, sizeof(szFileName)); + memset(&szFileTitle, 0, sizeof(szFileTitle)); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GetActiveWindow(); + ofn.lpstrFilter = "Supported Formats\0*.bin;*.iso;*.img;*.nrg;*.mdf;*.Z;*.Z2;*.BZ2;*.dump\0Cd Iso Format (*.bin;*.iso;*.img;*.nrg;*.mdf)\0*.bin;*.iso;*.img;*.nrg;*.mdf\0Compressed Z Iso Format (*.Z;*.Z2)\0*.Z;*.Z2\0Compressed BZ Iso Format (*.BZ2)\0*.BZ2\0Block Dumps (*.dump)\0*.dump\0All Files\0*.*\0"; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFileName; + ofn.nMaxFile = MAXFILENAME; + ofn.lpstrInitialDir = NULL; + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = MAXFILENAME; + ofn.lpstrTitle = NULL; + ofn.lpstrDefExt = NULL; + ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + + if (GetOpenFileName ((LPOPENFILENAME)&ofn)) { + strcpy(out, szFileName); + return 1; + } + + return 0; +} + +void CfgOpenFile() { + if (_GetFile(IsoFile) == 1) + SaveConf(); +} + +void UpdZmode() { + if (ComboBox_GetCurSel(hMethod) == 0) { + Zmode = 1; + } else { + Zmode = 2; + } +} + + +void SysUpdate() { + MSG msg; + + while (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +void OnCompress() { + u32 lsn; + u8 cdbuff[10*2352]; + char Zfile[256]; + int ret; + isoFile *src; + isoFile *dst; + + Edit_GetText(hIsoFile, IsoFile, 256); + UpdZmode(); + + if (Zmode == 1) { + sprintf(Zfile, "%s.Z2", IsoFile); + } else { + sprintf(Zfile, "%s.BZ2", IsoFile); + } + + src = isoOpen(IsoFile); + if (src == NULL) return; + if (Zmode == 1) { + dst = isoCreate(Zfile, ISOFLAGS_Z2); + } else { + dst = isoCreate(Zfile, ISOFLAGS_BZ2); + } + if (dst == NULL) return; + + isoSetFormat(dst, src->blockofs, src->blocksize, src->blocks); + Button_Enable(GetDlgItem(hDlg, IDC_COMPRESSISO), FALSE); + Button_Enable(GetDlgItem(hDlg, IDC_DECOMPRESSISO), FALSE); + stop=0; + + for (lsn = 0; lsnblocks; lsn++) { + printf("block %d ", lsn); + putchar(13); + fflush(stdout); + ret = isoReadBlock(src, cdbuff, lsn); + if (ret == -1) break; + ret = isoWriteBlock(dst, cdbuff, lsn); + if (ret == -1) break; + + SendMessage(hProgress, PBM_SETPOS, (lsn * 100) / src->blocks, 0); + SysUpdate(); + if (stop) break; + } + isoClose(src); + isoClose(dst); + + if (!stop) Edit_SetText(hIsoFile, Zfile); + + Button_Enable(GetDlgItem(hDlg, IDC_COMPRESSISO), TRUE); + Button_Enable(GetDlgItem(hDlg, IDC_DECOMPRESSISO), TRUE); + + if (!stop) { + if (ret == -1) { + SysMessage("Error compressing iso image"); + } else { + SysMessage("Iso image compressed OK"); + } + } +} + +void OnDecompress() { + char file[256]; + u8 cdbuff[10*2352]; + u32 lsn; + isoFile *src; + isoFile *dst; + int ret; + + Edit_GetText(hIsoFile, IsoFile, 256); + + src = isoOpen(IsoFile); + if (src == NULL) return; + + strcpy(file, IsoFile); + if (src->flags & ISOFLAGS_Z) { + file[strlen(file) - 2] = 0; + } else + if (src->flags & ISOFLAGS_Z2) { + file[strlen(file) - 3] = 0; + } else + if (src->flags & ISOFLAGS_BZ2) { + file[strlen(file) - 3] = 0; + } else { + SysMessage("%s is not a compressed image", IsoFile); + return; + } + + dst = isoCreate(file, 0); + if (dst == NULL) return; + + isoSetFormat(dst, src->blockofs, src->blocksize, src->blocks); + Button_Enable(GetDlgItem(hDlg, IDC_COMPRESSISO), FALSE); + Button_Enable(GetDlgItem(hDlg, IDC_DECOMPRESSISO), FALSE); + stop=0; + + for (lsn = 0; lsnblocks; lsn++) { + printf("block %d ", lsn); + putchar(13); + fflush(stdout); + ret = isoReadBlock(src, cdbuff, lsn); + if (ret == -1) break; + ret = isoWriteBlock(dst, cdbuff, lsn); + if (ret == -1) break; + + SendMessage(hProgress, PBM_SETPOS, (lsn * 100) / src->blocks, 0); + SysUpdate(); + if (stop) break; + } + if (!stop) Edit_SetText(hIsoFile, file); + + isoClose(src); + isoClose(dst); + + Button_Enable(GetDlgItem(hDlg, IDC_COMPRESSISO), TRUE); + Button_Enable(GetDlgItem(hDlg, IDC_DECOMPRESSISO), TRUE); + + if (!stop) { + if (ret == -1) { + SysMessage("Error decompressing iso image"); + } else { + SysMessage("Iso image decompressed OK"); + } + } +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + int i; + + switch(uMsg) { + case WM_INITDIALOG: + hDlg = hW; + LoadConf(); + + hProgress = GetDlgItem(hW, IDC_PROGRESS); + hIsoFile = GetDlgItem(hW, IDC_ISOFILE); + hMethod = GetDlgItem(hW, IDC_METHOD); + hBlockDump = GetDlgItem(hW, IDC_BLOCKDUMP); + + for (i=0; methods[i] != NULL; i++) { + ComboBox_AddString(hMethod, methods[i]); + } + + Edit_SetText(hIsoFile, IsoFile); + ComboBox_SetCurSel(hMethod, 0); +/* if (strstr(IsoFile, ".Z") != NULL) + ComboBox_SetCurSel(hMethod, 1); + else ComboBox_SetCurSel(hMethod, 0);*/ + Button_SetCheck(hBlockDump, BlockDump); + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_SELECTISO: + if (_GetFile(IsoFile) == 1) + Edit_SetText(hIsoFile, IsoFile); + return TRUE; + + case IDC_COMPRESSISO: + OnCompress(); + return TRUE; + + case IDC_DECOMPRESSISO: + OnDecompress(); + return TRUE; + + case IDC_STOP: + stop = 1; + return TRUE; + + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + Edit_GetText(hIsoFile, IsoFile, 256); + BlockDump = Button_GetCheck(hBlockDump); + + SaveConf(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK CDVDconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK CDVDabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/cdvd/CDVDiso/src/Win32/afxresmw.h b/plugins/cdvd/CDVDiso/src/Win32/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/cdvd/CDVDiso/src/Win32/plugin.def b/plugins/cdvd/CDVDiso/src/Win32/plugin.def new file mode 100644 index 0000000..4d19ae2 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/plugin.def @@ -0,0 +1,21 @@ +EXPORTS + PS2EgetLibType = PS2EgetLibType@0 @2 + PS2EgetLibName = PS2EgetLibName@0 @3 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4 + CDVDinit = CDVDinit@0 @5 + CDVDshutdown = CDVDshutdown@0 @6 + CDVDopen = CDVDopen@0 @7 + CDVDclose = CDVDclose@0 @8 + CDVDreadTrack = CDVDreadTrack@8 @9 + CDVDgetBuffer = CDVDgetBuffer@0 @10 + CDVDreadSubQ = CDVDreadSubQ@8 @11 + CDVDgetTN = CDVDgetTN@4 @12 + CDVDgetTD = CDVDgetTD@8 @13 + CDVDgetTOC = CDVDgetTOC@4 @14 + CDVDgetDiskType = CDVDgetDiskType@0 @15 + CDVDgetTrayStatus = CDVDgetTrayStatus@0 @16 + CDVDctrlTrayOpen = CDVDctrlTrayOpen@0 @17 + CDVDctrlTrayClose = CDVDctrlTrayClose@0 @18 + CDVDconfigure = CDVDconfigure@0 @19 + CDVDtest = CDVDtest@0 @20 + CDVDabout = CDVDabout@0 @21 diff --git a/plugins/cdvd/CDVDiso/src/Win32/resource.h b/plugins/cdvd/CDVDiso/src/Win32/resource.h new file mode 100644 index 0000000..fe23588 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/Win32/resource.h @@ -0,0 +1,28 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by CDVDiso.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_ISOFILE 1000 +#define IDC_SELECTISO 1001 +#define IDC_COMPRESSISO 1002 +#define IDC_DECOMPRESSISO 1003 +#define IDC_METHOD 1004 +#define IDC_PROGRESS 1005 +#define IDC_STOP 1006 +#define IDC_BLOCKDUMP 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + diff --git a/plugins/cdvd/CDVDiso/src/bzip2/LICENSE b/plugins/cdvd/CDVDiso/src/bzip2/LICENSE new file mode 100644 index 0000000..4458e35 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/LICENSE @@ -0,0 +1,43 @@ + +-------------------------------------------------------------------------- + +This program, "bzip2", the associated library "libbzip2", and all +documentation, are copyright (C) 1996-2006 Julian R Seward. All +rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, Cambridge, UK. +jseward@bzip.org +bzip2/libbzip2 version 1.0.4 of 20 December 2006 + +-------------------------------------------------------------------------- diff --git a/plugins/cdvd/CDVDiso/src/bzip2/README b/plugins/cdvd/CDVDiso/src/bzip2/README new file mode 100644 index 0000000..b18c096 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/README @@ -0,0 +1,205 @@ + +This is the README for bzip2/libzip2. +This version is fully compatible with the previous public releases. + +------------------------------------------------------------------ +This file is part of bzip2/libbzip2, a program and library for +lossless, block-sorting data compression. + +bzip2/libbzip2 version 1.0.4 of 20 December 2006 +Copyright (C) 1996-2006 Julian Seward + +Please read the WARNING, DISCLAIMER and PATENTS sections in this file. + +This program is released under the terms of the license contained +in the file LICENSE. +------------------------------------------------------------------ + +Complete documentation is available in Postscript form (manual.ps), +PDF (manual.pdf) or html (manual.html). A plain-text version of the +manual page is available as bzip2.txt. + + +HOW TO BUILD -- UNIX + +Type 'make'. This builds the library libbz2.a and then the programs +bzip2 and bzip2recover. Six self-tests are run. If the self-tests +complete ok, carry on to installation: + +To install in /usr/local/bin, /usr/local/lib, /usr/local/man and +/usr/local/include, type + + make install + +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + + make install PREFIX=/xxx/yyy + +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + + make -n install or + make -n install PREFIX=/xxx/yyy respectively. + +The -n instructs make to show the commands it would execute, but not +actually execute them. + + +HOW TO BUILD -- UNIX, shared library libbz2.so. + +Do 'make -f Makefile-libbz2_so'. This Makefile seems to work for +Linux-ELF (RedHat 7.2 on an x86 box), with gcc. I make no claims +that it works for any other platform, though I suspect it probably +will work for most platforms employing both ELF and gcc. + +bzip2-shared, a client of the shared library, is also built, but not +self-tested. So I suggest you also build using the normal Makefile, +since that conducts a self-test. A second reason to prefer the +version statically linked to the library is that, on x86 platforms, +building shared objects makes a valuable register (%ebx) unavailable +to gcc, resulting in a slowdown of 10%-20%, at least for bzip2. + +Important note for people upgrading .so's from 0.9.0/0.9.5 to version +1.0.X. All the functions in the library have been renamed, from (eg) +bzCompress to BZ2_bzCompress, to avoid namespace pollution. +Unfortunately this means that the libbz2.so created by +Makefile-libbz2_so will not work with any program which used an older +version of the library. I do encourage library clients to make the +effort to upgrade to use version 1.0, since it is both faster and more +robust than previous versions. + + +HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc. + +It's difficult for me to support compilation on all these platforms. +My approach is to collect binaries for these platforms, and put them +on the master web site (http://www.bzip.org). Look there. However +(FWIW), bzip2-1.0.X is very standard ANSI C and should compile +unmodified with MS Visual C. If you have difficulties building, you +might want to read README.COMPILATION.PROBLEMS. + +At least using MS Visual C++ 6, you can build from the unmodified +sources by issuing, in a command shell: + + nmake -f makefile.msc + +(you may need to first run the MSVC-provided script VCVARS32.BAT + so as to set up paths to the MSVC tools correctly). + + +VALIDATION + +Correct operation, in the sense that a compressed file can always be +decompressed to reproduce the original, is obviously of paramount +importance. To validate bzip2, I used a modified version of Mark +Nelson's churn program. Churn is an automated test driver which +recursively traverses a directory structure, using bzip2 to compress +and then decompress each file it encounters, and checking that the +decompressed data is the same as the original. + + + +Please read and be aware of the following: + +WARNING: + + This program and library (attempts to) compress data by + performing several non-trivial transformations on it. + Unless you are 100% familiar with *all* the algorithms + contained herein, and with the consequences of modifying them, + you should NOT meddle with the compression or decompression + machinery. Incorrect changes can and very likely *will* + lead to disastrous loss of data. + + +DISCLAIMER: + + I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE + USE OF THIS PROGRAM/LIBRARY, HOWSOEVER CAUSED. + + Every compression of a file implies an assumption that the + compressed file can be decompressed to reproduce the original. + Great efforts in design, coding and testing have been made to + ensure that this program works correctly. However, the complexity + of the algorithms, and, in particular, the presence of various + special cases in the code which occur with very low but non-zero + probability make it impossible to rule out the possibility of bugs + remaining in the program. DO NOT COMPRESS ANY DATA WITH THIS + PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER + SMALL, THAT THE DATA WILL NOT BE RECOVERABLE. + + That is not to say this program is inherently unreliable. + Indeed, I very much hope the opposite is true. bzip2/libbzip2 + has been carefully constructed and extensively tested. + + +PATENTS: + + To the best of my knowledge, bzip2/libbzip2 does not use any + patented algorithms. However, I do not have the resources + to carry out a patent search. Therefore I cannot give any + guarantee of the above statement. + + + +WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ? + + * Approx 10% faster compression, 30% faster decompression + * -t (test mode) is a lot quicker + * Can decompress concatenated compressed files + * Programming interface, so programs can directly read/write .bz2 files + * Less restrictive (BSD-style) licensing + * Flag handling more compatible with GNU gzip + * Much more documentation, i.e., a proper user manual + * Hopefully, improved portability (at least of the library) + +WHAT'S NEW IN 0.9.5 ? + + * Compression speed is much less sensitive to the input + data than in previous versions. Specifically, the very + slow performance caused by repetitive data is fixed. + * Many small improvements in file and flag handling. + * A Y2K statement. + +WHAT'S NEW IN 1.0.0 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.2 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.3 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.4 ? + + See the CHANGES file. + + +I hope you find bzip2 useful. Feel free to contact me at + jseward@bzip.org +if you have any suggestions or queries. Many people mailed me with +comments, suggestions and patches after the releases of bzip-0.15, +bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1, +1.0.2 and 1.0.3, and the changes in bzip2 are largely a result of this +feedback. I thank you for your comments. + +bzip2's "home" is http://www.bzip.org/ + +Julian Seward +jseward@bzip.org +Cambridge, UK. + +18 July 1996 (version 0.15) +25 August 1996 (version 0.21) + 7 August 1997 (bzip2, version 0.1) +29 August 1997 (bzip2, version 0.1pl2) +23 August 1998 (bzip2, version 0.9.0) + 8 June 1999 (bzip2, version 0.9.5) + 4 Sept 1999 (bzip2, version 0.9.5d) + 5 May 2000 (bzip2, version 1.0pre8) +30 December 2001 (bzip2, version 1.0.2pre1) +15 February 2005 (bzip2, version 1.0.3) +20 December 2006 (bzip2, version 1.0.4) diff --git a/plugins/cdvd/CDVDiso/src/bzip2/blocksort.c b/plugins/cdvd/CDVDiso/src/bzip2/blocksort.c new file mode 100644 index 0000000..8535c93 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/blocksort.c @@ -0,0 +1,1094 @@ + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlib_private.h" + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + if (verb >= 4) + VPrintf1 ( " depth %6d has ", H ); + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + if (verb >= 4) + VPrintf1 ( "%6d unresolved strings\n", nNotDone ); + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + if (verb >= 4) + VPrintf0 ( " reconstructing block ...\n" ); + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +__inline__ +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32 verb, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + if (verb >= 4) + VPrintf4 ( " qsort [0x%x, 0x%x] " + "done %d this %d\n", + ss, j, numQSorted, hi - lo + 1 ); + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( (copyStart[ss]-1 == copyEnd[ss]) + || + /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1. + Necessity for this case is demonstrated by compressing + a sequence of approximately 48.5 million of character + 251; 1.0.0/1.0.1 will then die here. */ + (copyStart[ss] == 0 && copyEnd[ss] == nblock-1), + 1007 ) + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } + + if (verb >= 4) + VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", + nblock, numQSorted, nblock - numQSorted ); +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 verb = s->verbosity; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); + if (verb >= 3) + VPrintf3 ( " %d work, %d block, ratio %5.2f\n", + budgetInit - budget, + nblock, + (float)(budgetInit - budget) / + (float)(nblock==0 ? 1 : nblock) ); + if (budget < 0) { + if (verb >= 2) + VPrintf0 ( " too repetitive; using fallback" + " sorting algorithm\n" ); + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/bzlib.c b/plugins/cdvd/CDVDiso/src/bzip2/bzlib.c new file mode 100644 index 0000000..79c34a5 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/bzlib.c @@ -0,0 +1,1571 @@ + +/*-------------------------------------------------------------*/ +/*--- Library top-level functions. ---*/ +/*--- bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + +/* CHANGES + 0.9.0 -- original version. + 0.9.0a/b -- no changes in this file. + 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). + fixed bzWrite/bzRead to ignore zero-length requests. + fixed bzread to correctly handle read requests after EOF. + wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. +*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Compression stuff ---*/ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +#ifndef BZ_NO_STDIO +void BZ2_bz__AssertH__fail ( int errcode ) +{ + fprintf(stderr, + "\n\nbzip2/libbzip2: internal error number %d.\n" + "This is a bug in bzip2/libbzip2, %s.\n" + "Please report it to me at: jseward@bzip.org. If this happened\n" + "when you were using some program which uses libbzip2 as a\n" + "component, you should also report this bug to the author(s)\n" + "of that program. Please make an effort to report this bug;\n" + "timely and accurate bug reports eventually lead to higher\n" + "quality software. Thanks. Julian Seward, 15 February 2005.\n\n", + errcode, + BZ2_bzlibVersion() + ); + + if (errcode == 1007) { + fprintf(stderr, + "\n*** A special note about internal error number 1007 ***\n" + "\n" + "Experience suggests that a common cause of i.e. 1007\n" + "is unreliable memory or other hardware. The 1007 assertion\n" + "just happens to cross-check the results of huge numbers of\n" + "memory reads/writes, and so acts (unintendedly) as a stress\n" + "test of your memory system.\n" + "\n" + "I suggest the following: try compressing the file again,\n" + "possibly monitoring progress in detail with the -vv flag.\n" + "\n" + "* If the error cannot be reproduced, and/or happens at different\n" + " points in compression, you may have a flaky memory system.\n" + " Try a memory-test program. I have used Memtest86\n" + " (www.memtest86.com). At the time of writing it is free (GPLd).\n" + " Memtest86 tests memory much more thorougly than your BIOSs\n" + " power-on test, and may find failures that the BIOS doesn't.\n" + "\n" + "* If the error can be repeatably reproduced, this is a bug in\n" + " bzip2, and I would very much like to hear about it. Please\n" + " let me know, and, ideally, save a copy of the file causing the\n" + " problem -- without which I will be unable to investigate it.\n" + "\n" + ); + } + + exit(3); +} +#endif + + +/*---------------------------------------------------*/ +static +int bz_config_ok ( void ) +{ + if (sizeof(int) != 4) return 0; + if (sizeof(short) != 2) return 0; + if (sizeof(char) != 1) return 0; + return 1; +} + + +/*---------------------------------------------------*/ +static +void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) +{ + void* v = malloc ( items * size ); + return v; +} + +static +void default_bzfree ( void* opaque, void* addr ) +{ + if (addr != NULL) free ( addr ); +} + + +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ + Int32 i; + s->nblock = 0; + s->numZ = 0; + s->state_out_pos = 0; + BZ_INITIALISE_CRC ( s->blockCRC ); + for (i = 0; i < 256; i++) s->inUse[i] = False; + s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ + s->state_in_ch = 256; + s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ + if (s->state_in_ch < 256 && s->state_in_len > 0) + return False; else + return True; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) + ( bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 n; + EState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL || + blockSize100k < 1 || blockSize100k > 9 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(EState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + + s->arr1 = NULL; + s->arr2 = NULL; + s->ftab = NULL; + + n = 100000 * blockSize100k; + s->arr1 = BZALLOC( n * sizeof(UInt32) ); + s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); + s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); + + if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + if (s != NULL) BZFREE(s); + return BZ_MEM_ERROR; + } + + s->blockNo = 0; + s->state = BZ_S_INPUT; + s->mode = BZ_M_RUNNING; + s->combinedCRC = 0; + s->blockSize100k = blockSize100k; + s->nblockMAX = 100000 * blockSize100k - 19; + s->verbosity = verbosity; + s->workFactor = workFactor; + + s->block = (UChar*)s->arr2; + s->mtfv = (UInt16*)s->arr1; + s->zbits = NULL; + s->ptr = (UInt32*)s->arr1; + + strm->state = s; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + init_RL ( s ); + prepare_new_block ( s ); + return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ + Int32 i; + UChar ch = (UChar)(s->state_in_ch); + for (i = 0; i < s->state_in_len; i++) { + BZ_UPDATE_CRC( s->blockCRC, ch ); + } + s->inUse[s->state_in_ch] = True; + switch (s->state_in_len) { + case 1: + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 2: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 3: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + default: + s->inUse[s->state_in_len-4] = True; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = ((UChar)(s->state_in_len-4)); + s->nblock++; + break; + } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ + if (s->state_in_ch < 256) add_pair_to_block ( s ); + init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ +{ \ + UInt32 zchh = (UInt32)(zchh0); \ + /*-- fast track the common case --*/ \ + if (zchh != zs->state_in_ch && \ + zs->state_in_len == 1) { \ + UChar ch = (UChar)(zs->state_in_ch); \ + BZ_UPDATE_CRC( zs->blockCRC, ch ); \ + zs->inUse[zs->state_in_ch] = True; \ + zs->block[zs->nblock] = (UChar)ch; \ + zs->nblock++; \ + zs->state_in_ch = zchh; \ + } \ + else \ + /*-- general, uncommon cases --*/ \ + if (zchh != zs->state_in_ch || \ + zs->state_in_len == 255) { \ + if (zs->state_in_ch < 256) \ + add_pair_to_block ( zs ); \ + zs->state_in_ch = zchh; \ + zs->state_in_len = 1; \ + } else { \ + zs->state_in_len++; \ + } \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ + Bool progress_in = False; + + if (s->mode == BZ_M_RUNNING) { + + /*-- fast track the common case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + + } else { + + /*-- general, uncommon case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + /*-- flush/finish end? --*/ + if (s->avail_in_expect == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + s->avail_in_expect--; + } + } + return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ + Bool progress_out = False; + + while (True) { + + /*-- no output space? --*/ + if (s->strm->avail_out == 0) break; + + /*-- block done? --*/ + if (s->state_out_pos >= s->numZ) break; + + progress_out = True; + *(s->strm->next_out) = s->zbits[s->state_out_pos]; + s->state_out_pos++; + s->strm->avail_out--; + s->strm->next_out++; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ + Bool progress_in = False; + Bool progress_out = False; + EState* s = strm->state; + + while (True) { + + if (s->state == BZ_S_OUTPUT) { + progress_out |= copy_output_until_stop ( s ); + if (s->state_out_pos < s->numZ) break; + if (s->mode == BZ_M_FINISHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + prepare_new_block ( s ); + s->state = BZ_S_INPUT; + if (s->mode == BZ_M_FLUSHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + } + + if (s->state == BZ_S_INPUT) { + progress_in |= copy_input_until_stop ( s ); + if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { + flush_RL ( s ); + BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); + s->state = BZ_S_OUTPUT; + } + else + if (s->nblock >= s->nblockMAX) { + BZ2_compressBlock ( s, False ); + s->state = BZ_S_OUTPUT; + } + else + if (s->strm->avail_in == 0) { + break; + } + } + + } + + return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ + Bool progress; + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + preswitch: + switch (s->mode) { + + case BZ_M_IDLE: + return BZ_SEQUENCE_ERROR; + + case BZ_M_RUNNING: + if (action == BZ_RUN) { + progress = handle_compress ( strm ); + return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; + } + else + if (action == BZ_FLUSH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FLUSHING; + goto preswitch; + } + else + if (action == BZ_FINISH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FINISHING; + goto preswitch; + } + else + return BZ_PARAM_ERROR; + + case BZ_M_FLUSHING: + if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FLUSH_OK; + s->mode = BZ_M_RUNNING; + return BZ_RUN_OK; + + case BZ_M_FINISHING: + if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (!progress) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FINISH_OK; + s->mode = BZ_M_IDLE; + return BZ_STREAM_END; + } + return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) +{ + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + BZFREE(strm->state); + + strm->state = NULL; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/*--- Decompression stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) + ( bz_stream* strm, + int verbosity, + int small ) +{ + DState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL) return BZ_PARAM_ERROR; + if (small != 0 && small != 1) return BZ_PARAM_ERROR; + if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; + + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(DState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + strm->state = s; + s->state = BZ_X_MAGIC_1; + s->bsLive = 0; + s->bsBuff = 0; + s->calculatedCombinedCRC = 0; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + s->smallDecompress = (Bool)small; + s->ll4 = NULL; + s->ll16 = NULL; + s->tt = NULL; + s->currBlockNo = 0; + s->verbosity = verbosity; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + /* restore */ + UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; + UChar c_state_out_ch = s->state_out_ch; + Int32 c_state_out_len = s->state_out_len; + Int32 c_nblock_used = s->nblock_used; + Int32 c_k0 = s->k0; + UInt32* c_tt = s->tt; + UInt32 c_tPos = s->tPos; + char* cs_next_out = s->strm->next_out; + unsigned int cs_avail_out = s->strm->avail_out; + /* end restore */ + + UInt32 avail_out_INIT = cs_avail_out; + Int32 s_save_nblockPP = s->save_nblock+1; + unsigned int total_out_lo32_old; + + while (True) { + + /* try to finish existing run */ + if (c_state_out_len > 0) { + while (True) { + if (cs_avail_out == 0) goto return_notr; + if (c_state_out_len == 1) break; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + c_state_out_len--; + cs_next_out++; + cs_avail_out--; + } + s_state_out_len_eq_one: + { + if (cs_avail_out == 0) { + c_state_out_len = 1; goto return_notr; + }; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + cs_next_out++; + cs_avail_out--; + } + } + /* Only caused by corrupt data stream? */ + if (c_nblock_used > s_save_nblockPP) + return True; + + /* can a new run be started? */ + if (c_nblock_used == s_save_nblockPP) { + c_state_out_len = 0; goto return_notr; + }; + c_state_out_ch = c_k0; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (k1 != c_k0) { + c_k0 = k1; goto s_state_out_len_eq_one; + }; + if (c_nblock_used == s_save_nblockPP) + goto s_state_out_len_eq_one; + + c_state_out_len = 2; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + c_state_out_len = 3; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + BZ_GET_FAST_C(k1); c_nblock_used++; + c_state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST_C(c_k0); c_nblock_used++; + } + + return_notr: + total_out_lo32_old = s->strm->total_out_lo32; + s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); + if (s->strm->total_out_lo32 < total_out_lo32_old) + s->strm->total_out_hi32++; + + /* save */ + s->calculatedBlockCRC = c_calculatedBlockCRC; + s->state_out_ch = c_state_out_ch; + s->state_out_len = c_state_out_len; + s->nblock_used = c_nblock_used; + s->k0 = c_k0; + s->tt = c_tt; + s->tPos = c_tPos; + s->strm->next_out = cs_next_out; + s->strm->avail_out = cs_avail_out; + /* end save */ + } + return False; +} + + + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ + Int32 nb, na, mid; + nb = 0; + na = 256; + do { + mid = (nb + na) >> 1; + if (indx >= cftab[mid]) nb = mid; else na = mid; + } + while (na - nb != 1); + return nb; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ + Bool corrupt; + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + while (True) { + if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; + if (s->state == BZ_X_OUTPUT) { + if (s->smallDecompress) + corrupt = unRLE_obuf_to_output_SMALL ( s ); else + corrupt = unRLE_obuf_to_output_FAST ( s ); + if (corrupt) return BZ_DATA_ERROR; + if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { + BZ_FINALISE_CRC ( s->calculatedBlockCRC ); + if (s->verbosity >= 3) + VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, + s->calculatedBlockCRC ); + if (s->verbosity >= 2) VPrintf0 ( "]" ); + if (s->calculatedBlockCRC != s->storedBlockCRC) + return BZ_DATA_ERROR; + s->calculatedCombinedCRC + = (s->calculatedCombinedCRC << 1) | + (s->calculatedCombinedCRC >> 31); + s->calculatedCombinedCRC ^= s->calculatedBlockCRC; + s->state = BZ_X_BLKHDR_1; + } else { + return BZ_OK; + } + } + if (s->state >= BZ_X_MAGIC_1) { + Int32 r = BZ2_decompress ( s ); + if (r == BZ_STREAM_END) { + if (s->verbosity >= 3) + VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", + s->storedCombinedCRC, s->calculatedCombinedCRC ); + if (s->calculatedCombinedCRC != s->storedCombinedCRC) + return BZ_DATA_ERROR; + return r; + } + if (s->state != BZ_X_OUTPUT) return r; + } + } + + AssertH ( 0, 6001 ); + + return 0; /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) +{ + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->tt != NULL) BZFREE(s->tt); + if (s->ll16 != NULL) BZFREE(s->ll16); + if (s->ll4 != NULL) BZFREE(s->ll4); + + BZFREE(strm->state); + strm->state = NULL; + + return BZ_OK; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ +/*--- File I/O stuff ---*/ +/*---------------------------------------------------*/ + +#define BZ_SETERR(eee) \ +{ \ + if (bzerror != NULL) *bzerror = eee; \ + if (bzf != NULL) bzf->lastErr = eee; \ +} + +typedef + struct { + FILE* handle; + Char buf[BZ_MAX_UNUSED]; + Int32 bufN; + Bool writing; + bz_stream strm; + Int32 lastErr; + Bool initialisedOk; + } + bzFile; + + +/*---------------------------------------------*/ +static Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzWriteOpen) + ( int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 ret; + bzFile* bzf = NULL; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (blockSize100k < 1 || blockSize100k > 9) || + (workFactor < 0 || workFactor > 250) || + (verbosity < 0 || verbosity > 4)) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + bzf->initialisedOk = False; + bzf->bufN = 0; + bzf->handle = f; + bzf->writing = True; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + if (workFactor == 0) workFactor = 30; + ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = 0; + bzf->initialisedOk = True; + return bzf; +} + + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWrite) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return; }; + + bzf->strm.avail_in = len; + bzf->strm.next_in = buf; + + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); + if (ret != BZ_RUN_OK) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (bzf->strm.avail_in == 0) + { BZ_SETERR(BZ_OK); return; }; + } +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWriteClose) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ) +{ + BZ2_bzWriteClose64 ( bzerror, b, abandon, + nbytes_in, NULL, nbytes_out, NULL ); +} + + +void BZ_API(BZ2_bzWriteClose64) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; + if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; + if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; + if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; + + if ((!abandon) && bzf->lastErr == BZ_OK) { + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); + if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (ret == BZ_STREAM_END) break; + } + } + + if ( !abandon && !ferror ( bzf->handle ) ) { + fflush ( bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (nbytes_in_lo32 != NULL) + *nbytes_in_lo32 = bzf->strm.total_in_lo32; + if (nbytes_in_hi32 != NULL) + *nbytes_in_hi32 = bzf->strm.total_in_hi32; + if (nbytes_out_lo32 != NULL) + *nbytes_out_lo32 = bzf->strm.total_out_lo32; + if (nbytes_out_hi32 != NULL) + *nbytes_out_hi32 = bzf->strm.total_out_hi32; + + BZ_SETERR(BZ_OK); + BZ2_bzCompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzReadOpen) + ( int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused ) +{ + bzFile* bzf = NULL; + int ret; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (small != 0 && small != 1) || + (verbosity < 0 || verbosity > 4) || + (unused == NULL && nUnused != 0) || + (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + + bzf->initialisedOk = False; + bzf->handle = f; + bzf->bufN = 0; + bzf->writing = False; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + while (nUnused > 0) { + bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; + unused = ((void*)( 1 + ((UChar*)(unused)) )); + nUnused--; + } + + ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + + bzf->initialisedOk = True; + return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) +{ + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + + if (bzf->initialisedOk) + (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzRead) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return 0; }; + + bzf->strm.avail_out = len; + bzf->strm.next_out = buf; + + while (True) { + + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + + if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { + n = fread ( bzf->buf, sizeof(UChar), + BZ_MAX_UNUSED, bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + bzf->bufN = n; + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + } + + ret = BZ2_bzDecompress ( &(bzf->strm) ); + + if (ret != BZ_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return 0; }; + + if (ret == BZ_OK && myfeof(bzf->handle) && + bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) + { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; + + if (ret == BZ_STREAM_END) + { BZ_SETERR(BZ_STREAM_END); + return len - bzf->strm.avail_out; }; + if (bzf->strm.avail_out == 0) + { BZ_SETERR(BZ_OK); return len; }; + + } + + return 0; /*not reached*/ +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadGetUnused) + ( int* bzerror, + BZFILE* b, + void** unused, + int* nUnused ) +{ + bzFile* bzf = (bzFile*)b; + if (bzf == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (bzf->lastErr != BZ_STREAM_END) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (unused == NULL || nUnused == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + + BZ_SETERR(BZ_OK); + *nUnused = bzf->strm.avail_in; + *unused = bzf->strm.next_in; +} +#endif + + +/*---------------------------------------------------*/ +/*--- Misc convenience stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffCompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + blockSize100k < 1 || blockSize100k > 9 || + verbosity < 0 || verbosity > 4 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzCompressInit ( &strm, blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzCompress ( &strm, BZ_FINISH ); + if (ret == BZ_FINISH_OK) goto output_overflow; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzCompressEnd ( &strm ); + return BZ_OK; + + output_overflow: + BZ2_bzCompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + + errhandler: + BZ2_bzCompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffDecompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + (small != 0 && small != 1) || + verbosity < 0 || verbosity > 4) + return BZ_PARAM_ERROR; + + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzDecompress ( &strm ); + if (ret == BZ_OK) goto output_overflow_or_eof; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzDecompressEnd ( &strm ); + return BZ_OK; + + output_overflow_or_eof: + if (strm.avail_out > 0) { + BZ2_bzDecompressEnd ( &strm ); + return BZ_UNEXPECTED_EOF; + } else { + BZ2_bzDecompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + }; + + errhandler: + BZ2_bzDecompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +/*-- + Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +/*-- + return version like "0.9.5d, 4-Sept-1999". +--*/ +const char * BZ_API(BZ2_bzlibVersion)(void) +{ + return BZ_VERSION; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif +static +BZFILE * bzopen_or_bzdopen + ( const char *path, /* no use when bzdopen */ + int fd, /* no use when bzdopen */ + const char *mode, + int open_mode) /* bzopen: 0, bzdopen:1 */ +{ + int bzerr; + char unused[BZ_MAX_UNUSED]; + int blockSize100k = 9; + int writing = 0; + char mode2[10] = ""; + FILE *fp = NULL; + BZFILE *bzfp = NULL; + int verbosity = 0; + int workFactor = 30; + int smallMode = 0; + int nUnused = 0; + + if (mode == NULL) return NULL; + while (*mode) { + switch (*mode) { + case 'r': + writing = 0; break; + case 'w': + writing = 1; break; + case 's': + smallMode = 1; break; + default: + if (isdigit((int)(*mode))) { + blockSize100k = *mode-BZ_HDR_0; + } + } + mode++; + } + strcat(mode2, writing ? "w" : "r" ); + strcat(mode2,"b"); /* binary mode */ + + if (open_mode==0) { + if (path==NULL || strcmp(path,"")==0) { + fp = (writing ? stdout : stdin); + SET_BINARY_MODE(fp); + } else { + fp = fopen(path,mode2); + } + } else { +#ifdef BZ_STRICT_ANSI + fp = NULL; +#else + fp = fdopen(fd,mode2); +#endif + } + if (fp == NULL) return NULL; + + if (writing) { + /* Guard against total chaos and anarchy -- JRS */ + if (blockSize100k < 1) blockSize100k = 1; + if (blockSize100k > 9) blockSize100k = 9; + bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, + verbosity,workFactor); + } else { + bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, + unused,nUnused); + } + if (bzfp == NULL) { + if (fp != stdin && fp != stdout) fclose(fp); + return NULL; + } + return bzfp; +} + + +/*---------------------------------------------------*/ +/*-- + open file for read or write. + ex) bzopen("file","w9") + case path="" or NULL => use stdin or stdout. +--*/ +BZFILE * BZ_API(BZ2_bzopen) + ( const char *path, + const char *mode ) +{ + return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); +} + + +/*---------------------------------------------------*/ +BZFILE * BZ_API(BZ2_bzdopen) + ( int fd, + const char *mode ) +{ + return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) +{ + int bzerr, nread; + if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; + nread = BZ2_bzRead(&bzerr,b,buf,len); + if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { + return nread; + } else { + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) +{ + int bzerr; + + BZ2_bzWrite(&bzerr,b,buf,len); + if(bzerr == BZ_OK){ + return len; + }else{ + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzflush) (BZFILE *b) +{ + /* do nothing now... */ + return 0; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzclose) (BZFILE* b) +{ + int bzerr; + FILE *fp; + + if (b==NULL) {return;} + fp = ((bzFile *)b)->handle; + if(((bzFile*)b)->writing){ + BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); + if(bzerr != BZ_OK){ + BZ2_bzWriteClose(NULL,b,1,NULL,NULL); + } + }else{ + BZ2_bzReadClose(&bzerr,b); + } + if(fp!=stdin && fp!=stdout){ + fclose(fp); + } +} + + +/*---------------------------------------------------*/ +/*-- + return last error code +--*/ +static const char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"CONFIG_ERROR" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + + +const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) +{ + int err = ((bzFile *)b)->lastErr; + + if(err>0) err = 0; + *errnum = err; + return bzerrorstrings[err*-1]; +} +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/bzlib.h b/plugins/cdvd/CDVDiso/src/bzip2/bzlib.h new file mode 100644 index 0000000..fdb0dbe --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/bzlib.h @@ -0,0 +1,282 @@ + +/*-------------------------------------------------------------*/ +/*--- Public header file for the library. ---*/ +/*--- bzlib.h ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#ifndef _BZLIB_H +#define _BZLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BZ_RUN 0 +#define BZ_FLUSH 1 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FLUSH_OK 2 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 +#define BZ_SEQUENCE_ERROR (-1) +#define BZ_PARAM_ERROR (-2) +#define BZ_MEM_ERROR (-3) +#define BZ_DATA_ERROR (-4) +#define BZ_DATA_ERROR_MAGIC (-5) +#define BZ_IO_ERROR (-6) +#define BZ_UNEXPECTED_EOF (-7) +#define BZ_OUTBUFF_FULL (-8) +#define BZ_CONFIG_ERROR (-9) + +typedef + struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; + } + bz_stream; + + +#ifndef BZ_IMPORT +#define BZ_EXPORT +#endif + +#ifndef BZ_NO_STDIO +/* Need a definitition for FILE */ +#include +#endif + +#ifdef _WIN32 +# include +# ifdef small + /* windows.h define small to char */ +# undef small +# endif +# ifdef BZ_EXPORT +# define BZ_API(func) WINAPI func +# define BZ_EXTERN extern +# else + /* import windows dll dynamically */ +# define BZ_API(func) (WINAPI * func) +# define BZ_EXTERN +# endif +#else +# define BZ_API(func) func +# define BZ_EXTERN extern +#endif + + +/*-- Core (low-level) library functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompress) ( + bz_stream* strm, + int action + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( + bz_stream *strm, + int verbosity, + int small + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( + bz_stream *strm + ); + + + +/*-- High(er) level library functions --*/ + +#ifndef BZ_NO_STDIO +#define BZ_MAX_UNUSED 5000 + +typedef void BZFILE; + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( + int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( + int* bzerror, + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( + int* bzerror, + BZFILE* b, + void** unused, + int* nUnused + ); + +BZ_EXTERN int BZ_API(BZ2_bzRead) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( + int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN void BZ_API(BZ2_bzWrite) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 + ); +#endif + + +/*-- Utility functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity + ); + + +/*-- + Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ + +BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( + void + ); + +#ifndef BZ_NO_STDIO +BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( + const char *path, + const char *mode + ); + +BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( + int fd, + const char *mode + ); + +BZ_EXTERN int BZ_API(BZ2_bzread) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzwrite) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzflush) ( + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzclose) ( + BZFILE* b + ); + +BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( + BZFILE *b, + int *errnum + ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/bzlib_private.h b/plugins/cdvd/CDVDiso/src/bzip2/bzlib_private.h new file mode 100644 index 0000000..d0a0554 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/bzlib_private.h @@ -0,0 +1,503 @@ + +/*-------------------------------------------------------------*/ +/*--- Private header file for the library. ---*/ +/*--- bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#ifndef _BZLIB_PRIVATE_H +#define _BZLIB_PRIVATE_H + +#include + +#ifndef BZ_NO_STDIO +#include +#include +#include +#endif + +#include "bzlib.h" + + + +/*-- General stuff. --*/ + +#define BZ_VERSION "1.0.4, 20-Dec-2006" + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#ifndef __GNUC__ +#define __inline__ /* */ +#endif + +#ifndef BZ_NO_STDIO + +extern void BZ2_bz__AssertH__fail ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); } + +#if BZ_DEBUG +#define AssertD(cond,msg) \ + { if (!(cond)) { \ + fprintf ( stderr, \ + "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\ + exit(1); \ + }} +#else +#define AssertD(cond,msg) /* */ +#endif + +#define VPrintf0(zf) \ + fprintf(stderr,zf) +#define VPrintf1(zf,za1) \ + fprintf(stderr,zf,za1) +#define VPrintf2(zf,za1,za2) \ + fprintf(stderr,zf,za1,za2) +#define VPrintf3(zf,za1,za2,za3) \ + fprintf(stderr,zf,za1,za2,za3) +#define VPrintf4(zf,za1,za2,za3,za4) \ + fprintf(stderr,zf,za1,za2,za3,za4) +#define VPrintf5(zf,za1,za2,za3,za4,za5) \ + fprintf(stderr,zf,za1,za2,za3,za4,za5) + +#else + +extern void bz_internal_error ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) bz_internal_error ( errcode ); } +#define AssertD(cond,msg) do { } while (0) +#define VPrintf0(zf) do { } while (0) +#define VPrintf1(zf,za1) do { } while (0) +#define VPrintf2(zf,za1,za2) do { } while (0) +#define VPrintf3(zf,za1,za2,za3) do { } while (0) +#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0) +#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0) + +#endif + + +#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1) +#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp)) + + +/*-- Header bytes. --*/ + +#define BZ_HDR_B 0x42 /* 'B' */ +#define BZ_HDR_Z 0x5a /* 'Z' */ +#define BZ_HDR_h 0x68 /* 'h' */ +#define BZ_HDR_0 0x30 /* '0' */ + +/*-- Constants for the back end. --*/ + +#define BZ_MAX_ALPHA_SIZE 258 +#define BZ_MAX_CODE_LEN 23 + +#define BZ_RUNA 0 +#define BZ_RUNB 1 + +#define BZ_N_GROUPS 6 +#define BZ_G_SIZE 50 +#define BZ_N_ITERS 4 + +#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) + + + +/*-- Stuff for randomising repetitive blocks. --*/ + +extern Int32 BZ2_rNums[512]; + +#define BZ_RAND_DECLS \ + Int32 rNToGo; \ + Int32 rTPos \ + +#define BZ_RAND_INIT_MASK \ + s->rNToGo = 0; \ + s->rTPos = 0 \ + +#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) + +#define BZ_RAND_UPD_MASK \ + if (s->rNToGo == 0) { \ + s->rNToGo = BZ2_rNums[s->rTPos]; \ + s->rTPos++; \ + if (s->rTPos == 512) s->rTPos = 0; \ + } \ + s->rNToGo--; + + + +/*-- Stuff for doing CRCs. --*/ + +extern UInt32 BZ2_crc32Table[256]; + +#define BZ_INITIALISE_CRC(crcVar) \ +{ \ + crcVar = 0xffffffffL; \ +} + +#define BZ_FINALISE_CRC(crcVar) \ +{ \ + crcVar = ~(crcVar); \ +} + +#define BZ_UPDATE_CRC(crcVar,cha) \ +{ \ + crcVar = (crcVar << 8) ^ \ + BZ2_crc32Table[(crcVar >> 24) ^ \ + ((UChar)cha)]; \ +} + + + +/*-- States and modes for compression. --*/ + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + + + + +/*-- Structure holding all the compression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* mode this stream is in, and whether inputting */ + /* or outputting data */ + Int32 mode; + Int32 state; + + /* remembers avail_in when flush/finish requested */ + UInt32 avail_in_expect; + + /* for doing the block sorting */ + UInt32* arr1; + UInt32* arr2; + UInt32* ftab; + Int32 origPtr; + + /* aliases for arr1 and arr2 */ + UInt32* ptr; + UChar* block; + UInt16* mtfv; + UChar* zbits; + + /* for deciding when to use the fallback sorting algorithm */ + Int32 workFactor; + + /* run-length-encoding of the input */ + UInt32 state_in_ch; + Int32 state_in_len; + BZ_RAND_DECLS; + + /* input and output limits and current posns */ + Int32 nblock; + Int32 nblockMAX; + Int32 numZ; + Int32 state_out_pos; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + UChar unseqToSeq[256]; + + /* the buffer for bit stream creation */ + UInt32 bsBuff; + Int32 bsLive; + + /* block and combined CRCs */ + UInt32 blockCRC; + UInt32 combinedCRC; + + /* misc administratium */ + Int32 verbosity; + Int32 blockNo; + Int32 blockSize100k; + + /* stuff for coding the MTF values */ + Int32 nMTF; + Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + /* second dimension: only 3 needed; 4 makes index calculations faster */ + UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; + + } + EState; + + + +/*-- externs for compression. --*/ + +extern void +BZ2_blockSort ( EState* ); + +extern void +BZ2_compressBlock ( EState*, Bool ); + +extern void +BZ2_bsInitWrite ( EState* ); + +extern void +BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); + +extern void +BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); + + + +/*-- states for decompression. --*/ + +#define BZ_X_IDLE 1 +#define BZ_X_OUTPUT 2 + +#define BZ_X_MAGIC_1 10 +#define BZ_X_MAGIC_2 11 +#define BZ_X_MAGIC_3 12 +#define BZ_X_MAGIC_4 13 +#define BZ_X_BLKHDR_1 14 +#define BZ_X_BLKHDR_2 15 +#define BZ_X_BLKHDR_3 16 +#define BZ_X_BLKHDR_4 17 +#define BZ_X_BLKHDR_5 18 +#define BZ_X_BLKHDR_6 19 +#define BZ_X_BCRC_1 20 +#define BZ_X_BCRC_2 21 +#define BZ_X_BCRC_3 22 +#define BZ_X_BCRC_4 23 +#define BZ_X_RANDBIT 24 +#define BZ_X_ORIGPTR_1 25 +#define BZ_X_ORIGPTR_2 26 +#define BZ_X_ORIGPTR_3 27 +#define BZ_X_MAPPING_1 28 +#define BZ_X_MAPPING_2 29 +#define BZ_X_SELECTOR_1 30 +#define BZ_X_SELECTOR_2 31 +#define BZ_X_SELECTOR_3 32 +#define BZ_X_CODING_1 33 +#define BZ_X_CODING_2 34 +#define BZ_X_CODING_3 35 +#define BZ_X_MTF_1 36 +#define BZ_X_MTF_2 37 +#define BZ_X_MTF_3 38 +#define BZ_X_MTF_4 39 +#define BZ_X_MTF_5 40 +#define BZ_X_MTF_6 41 +#define BZ_X_ENDHDR_2 42 +#define BZ_X_ENDHDR_3 43 +#define BZ_X_ENDHDR_4 44 +#define BZ_X_ENDHDR_5 45 +#define BZ_X_ENDHDR_6 46 +#define BZ_X_CCRC_1 47 +#define BZ_X_CCRC_2 48 +#define BZ_X_CCRC_3 49 +#define BZ_X_CCRC_4 50 + + + +/*-- Constants for the fast MTF decoder. --*/ + +#define MTFA_SIZE 4096 +#define MTFL_SIZE 16 + + + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* state indicator for this stream */ + Int32 state; + + /* for doing the final run-length decoding */ + UChar state_out_ch; + Int32 state_out_len; + Bool blockRandomised; + BZ_RAND_DECLS; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 blockSize100k; + Bool smallDecompress; + Int32 currBlockNo; + Int32 verbosity; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + UInt32 tPos; + Int32 k0; + Int32 unzftab[256]; + Int32 nblock_used; + Int32 cftab[257]; + Int32 cftabCopy[257]; + + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 *tt; + + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 *ll16; + UChar *ll4; + + /* stored and calculated CRCs */ + UInt32 storedBlockCRC; + UInt32 storedCombinedCRC; + UInt32 calculatedBlockCRC; + UInt32 calculatedCombinedCRC; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + Bool inUse16[16]; + UChar seqToUnseq[256]; + + /* for decoding the MTF values */ + UChar mtfa [MTFA_SIZE]; + Int32 mtfbase[256 / MTFL_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + + Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 minLens[BZ_N_GROUPS]; + + /* save area for scalars in the main decompress code */ + Int32 save_i; + Int32 save_j; + Int32 save_t; + Int32 save_alphaSize; + Int32 save_nGroups; + Int32 save_nSelectors; + Int32 save_EOB; + Int32 save_groupNo; + Int32 save_groupPos; + Int32 save_nextSym; + Int32 save_nblockMAX; + Int32 save_nblock; + Int32 save_es; + Int32 save_N; + Int32 save_curr; + Int32 save_zt; + Int32 save_zn; + Int32 save_zvec; + Int32 save_zj; + Int32 save_gSel; + Int32 save_gMinlen; + Int32* save_gLimit; + Int32* save_gBase; + Int32* save_gPerm; + + } + DState; + + + +/*-- Macros for decompression. --*/ + +#define BZ_GET_FAST(cccc) \ + s->tPos = s->tt[s->tPos]; \ + cccc = (UChar)(s->tPos & 0xff); \ + s->tPos >>= 8; + +#define BZ_GET_FAST_C(cccc) \ + c_tPos = c_tt[c_tPos]; \ + cccc = (UChar)(c_tPos & 0xff); \ + c_tPos >>= 8; + +#define SET_LL4(i,n) \ + { if (((i) & 0x1) == 0) \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ + } + +#define GET_LL4(i) \ + ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) + +#define SET_LL(i,n) \ + { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ + SET_LL4(i, n >> 16); \ + } + +#define GET_LL(i) \ + (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) + +#define BZ_GET_SMALL(cccc) \ + cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ + s->tPos = GET_LL(s->tPos); + + +/*-- externs for decompression. --*/ + +extern Int32 +BZ2_indexIntoF ( Int32, Int32* ); + +extern Int32 +BZ2_decompress ( DState* ); + +extern void +BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#endif + + +/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ + +#ifdef BZ_NO_STDIO +#ifndef NULL +#define NULL 0 +#endif +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/compress.c b/plugins/cdvd/CDVDiso/src/bzip2/compress.c new file mode 100644 index 0000000..d98d5c0 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/compress.c @@ -0,0 +1,672 @@ + +/*-------------------------------------------------------------*/ +/*--- Compression machinery (not incl block sorting) ---*/ +/*--- compress.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +/* CHANGES + 0.9.0 -- original version. + 0.9.0a/b -- no changes in this file. + 0.9.0c -- changed setting of nGroups in sendMTFValues() + so as to do a bit better on small files +*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +void BZ2_bsInitWrite ( EState* s ) +{ + s->bsLive = 0; + s->bsBuff = 0; +} + + +/*---------------------------------------------------*/ +static +void bsFinishWrite ( EState* s ) +{ + while (s->bsLive > 0) { + s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } +} + + +/*---------------------------------------------------*/ +#define bsNEEDW(nz) \ +{ \ + while (s->bsLive >= 8) { \ + s->zbits[s->numZ] \ + = (UChar)(s->bsBuff >> 24); \ + s->numZ++; \ + s->bsBuff <<= 8; \ + s->bsLive -= 8; \ + } \ +} + + +/*---------------------------------------------------*/ +static +__inline__ +void bsW ( EState* s, Int32 n, UInt32 v ) +{ + bsNEEDW ( n ); + s->bsBuff |= (v << (32 - s->bsLive - n)); + s->bsLive += n; +} + + +/*---------------------------------------------------*/ +static +void bsPutUInt32 ( EState* s, UInt32 u ) +{ + bsW ( s, 8, (u >> 24) & 0xffL ); + bsW ( s, 8, (u >> 16) & 0xffL ); + bsW ( s, 8, (u >> 8) & 0xffL ); + bsW ( s, 8, u & 0xffL ); +} + + +/*---------------------------------------------------*/ +static +void bsPutUChar ( EState* s, UChar c ) +{ + bsW( s, 8, (UInt32)c ); +} + + +/*---------------------------------------------------*/ +/*--- The back end proper ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +static +void makeMaps_e ( EState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->unseqToSeq[i] = s->nInUse; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +static +void generateMTFValues ( EState* s ) +{ + UChar yy[256]; + Int32 i, j; + Int32 zPend; + Int32 wr; + Int32 EOB; + + /* + After sorting (eg, here), + s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, + and + ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] + holds the original block data. + + The first thing to do is generate the MTF values, + and put them in + ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. + Because there are strictly fewer or equal MTF values + than block values, ptr values in this area are overwritten + with MTF values only when they are no longer needed. + + The final compressed bitstream is generated into the + area starting at + (UChar*) (&((UChar*)s->arr2)[s->nblock]) + + These storage aliases are set up in bzCompressInit(), + except for the last one, which is arranged in + compressBlock(). + */ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt16* mtfv = s->mtfv; + + makeMaps_e ( s ); + EOB = s->nInUse+1; + + for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; + + wr = 0; + zPend = 0; + for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; + + for (i = 0; i < s->nblock; i++) { + UChar ll_i; + AssertD ( wr <= i, "generateMTFValues(1)" ); + j = ptr[i]-1; if (j < 0) j += s->nblock; + ll_i = s->unseqToSeq[block[j]]; + AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); + + if (yy[0] == ll_i) { + zPend++; + } else { + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + { + register UChar rtmp; + register UChar* ryy_j; + register UChar rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while ( rll_i != rtmp ) { + register UChar rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + }; + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; + } + + } + } + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + + mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; + + s->nMTF = wr; +} + + +/*---------------------------------------------------*/ +#define BZ_LESSER_ICOST 0 +#define BZ_GREATER_ICOST 15 + +static +void sendMTFValues ( EState* s ) +{ + Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; + Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; + Int32 nGroups, nBytes; + + /*-- + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + is a global since the decoder also needs it. + + Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + are also globals only used in this proc. + Made global to keep stack frame size small. + --*/ + + + UInt16 cost[BZ_N_GROUPS]; + Int32 fave[BZ_N_GROUPS]; + + UInt16* mtfv = s->mtfv; + + if (s->verbosity >= 3) + VPrintf3( " %d in block, %d after MTF & 1-2 coding, " + "%d+2 syms in use\n", + s->nblock, s->nMTF, s->nInUse ); + + alphaSize = s->nInUse+2; + for (t = 0; t < BZ_N_GROUPS; t++) + for (v = 0; v < alphaSize; v++) + s->len[t][v] = BZ_GREATER_ICOST; + + /*--- Decide how many coding tables to use ---*/ + AssertH ( s->nMTF > 0, 3001 ); + if (s->nMTF < 200) nGroups = 2; else + if (s->nMTF < 600) nGroups = 3; else + if (s->nMTF < 1200) nGroups = 4; else + if (s->nMTF < 2400) nGroups = 5; else + nGroups = 6; + + /*--- Generate an initial set of coding tables ---*/ + { + Int32 nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = s->nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs-1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize-1) { + ge++; + aFreq += s->mtfFreq[ge]; + } + + if (ge > gs + && nPart != nGroups && nPart != 1 + && ((nGroups-nPart) % 2 == 1)) { + aFreq -= s->mtfFreq[ge]; + ge--; + } + + if (s->verbosity >= 3) + VPrintf5( " initial group %d, [%d .. %d], " + "has %d syms (%4.1f%%)\n", + nPart, gs, ge, aFreq, + (100.0 * (float)aFreq) / (float)(s->nMTF) ); + + for (v = 0; v < alphaSize; v++) + if (v >= gs && v <= ge) + s->len[nPart-1][v] = BZ_LESSER_ICOST; else + s->len[nPart-1][v] = BZ_GREATER_ICOST; + + nPart--; + gs = ge+1; + remF -= aFreq; + } + } + + /*--- + Iterate up to BZ_N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZ_N_ITERS; iter++) { + + for (t = 0; t < nGroups; t++) fave[t] = 0; + + for (t = 0; t < nGroups; t++) + for (v = 0; v < alphaSize; v++) + s->rfreq[t][v] = 0; + + /*--- + Set up an auxiliary length table which is used to fast-track + the common case (nGroups == 6). + ---*/ + if (nGroups == 6) { + for (v = 0; v < alphaSize; v++) { + s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; + s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; + s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (True) { + + /*--- Set group start & end marks. --*/ + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (t = 0; t < nGroups; t++) cost[t] = 0; + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + register UInt32 cost01, cost23, cost45; + register UInt16 icv; + cost01 = cost23 = cost45 = 0; + +# define BZ_ITER(nn) \ + icv = mtfv[gs+(nn)]; \ + cost01 += s->len_pack[icv][0]; \ + cost23 += s->len_pack[icv][1]; \ + cost45 += s->len_pack[icv][2]; \ + + BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); + BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); + BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); + BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); + BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); + BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); + BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); + BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); + BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); + BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); + +# undef BZ_ITER + + cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; + cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; + cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + UInt16 icv = mtfv[i]; + for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; bt = -1; + for (t = 0; t < nGroups; t++) + if (cost[t] < bc) { bc = cost[t]; bt = t; }; + totc += bc; + fave[bt]++; + s->selector[nSelectors] = bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + +# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ + + BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); + BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); + BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); + BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); + BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); + BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); + BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); + BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); + BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); + BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); + +# undef BZ_ITUR + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) + s->rfreq[bt][ mtfv[i] ]++; + } + + gs = ge+1; + } + if (s->verbosity >= 3) { + VPrintf2 ( " pass %d: size is %d, grp uses are ", + iter+1, totc/8 ); + for (t = 0; t < nGroups; t++) + VPrintf1 ( "%d ", fave[t] ); + VPrintf0 ( "\n" ); + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See + comment in huffman.c for details. */ + for (t = 0; t < nGroups; t++) + BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), + alphaSize, 17 /*20*/ ); + } + + + AssertH( nGroups < 8, 3002 ); + AssertH( nSelectors < 32768 && + nSelectors <= (2 + (900000 / BZ_G_SIZE)), + 3003 ); + + + /*--- Compute MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) pos[i] = i; + for (i = 0; i < nSelectors; i++) { + ll_i = s->selector[i]; + j = 0; + tmp = pos[j]; + while ( ll_i != tmp ) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + }; + pos[0] = tmp; + s->selectorMtf[i] = j; + } + }; + + /*--- Assign actual codes for the tables. --*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + AssertH ( !(maxLen > 17 /*20*/ ), 3004 ); + AssertH ( !(minLen < 1), 3005 ); + BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), + minLen, maxLen, alphaSize ); + } + + /*--- Transmit the mapping table. ---*/ + { + Bool inUse16[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = False; + for (j = 0; j < 16; j++) + if (s->inUse[i * 16 + j]) inUse16[i] = True; + } + + nBytes = s->numZ; + for (i = 0; i < 16; i++) + if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); + + for (i = 0; i < 16; i++) + if (inUse16[i]) + for (j = 0; j < 16; j++) { + if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); + } + + if (s->verbosity >= 3) + VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes ); + } + + /*--- Now the selectors. ---*/ + nBytes = s->numZ; + bsW ( s, 3, nGroups ); + bsW ( s, 15, nSelectors ); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); + bsW(s,1,0); + } + if (s->verbosity >= 3) + VPrintf1( "selectors %d, ", s->numZ-nBytes ); + + /*--- Now the coding tables. ---*/ + nBytes = s->numZ; + + for (t = 0; t < nGroups; t++) { + Int32 curr = s->len[t][0]; + bsW ( s, 5, curr ); + for (i = 0; i < alphaSize; i++) { + while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; + while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; + bsW ( s, 1, 0 ); + } + } + + if (s->verbosity >= 3) + VPrintf1 ( "code lengths %d, ", s->numZ-nBytes ); + + /*--- And finally, the block data proper ---*/ + nBytes = s->numZ; + selCtr = 0; + gs = 0; + while (True) { + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + AssertH ( s->selector[selCtr] < nGroups, 3006 ); + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + UInt16 mtfv_i; + UChar* s_len_sel_selCtr + = &(s->len[s->selector[selCtr]][0]); + Int32* s_code_sel_selCtr + = &(s->code[s->selector[selCtr]][0]); + +# define BZ_ITAH(nn) \ + mtfv_i = mtfv[gs+(nn)]; \ + bsW ( s, \ + s_len_sel_selCtr[mtfv_i], \ + s_code_sel_selCtr[mtfv_i] ) + + BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); + BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); + BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); + BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); + BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); + BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); + BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); + BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); + BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); + BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); + +# undef BZ_ITAH + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + bsW ( s, + s->len [s->selector[selCtr]] [mtfv[i]], + s->code [s->selector[selCtr]] [mtfv[i]] ); + } + } + + + gs = ge+1; + selCtr++; + } + AssertH( selCtr == nSelectors, 3007 ); + + if (s->verbosity >= 3) + VPrintf1( "codes %d\n", s->numZ-nBytes ); +} + + +/*---------------------------------------------------*/ +void BZ2_compressBlock ( EState* s, Bool is_last_block ) +{ + if (s->nblock > 0) { + + BZ_FINALISE_CRC ( s->blockCRC ); + s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); + s->combinedCRC ^= s->blockCRC; + if (s->blockNo > 1) s->numZ = 0; + + if (s->verbosity >= 2) + VPrintf4( " block %d: crc = 0x%08x, " + "combined CRC = 0x%08x, size = %d\n", + s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); + + BZ2_blockSort ( s ); + } + + s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); + + /*-- If this is the first block, create the stream header. --*/ + if (s->blockNo == 1) { + BZ2_bsInitWrite ( s ); + bsPutUChar ( s, BZ_HDR_B ); + bsPutUChar ( s, BZ_HDR_Z ); + bsPutUChar ( s, BZ_HDR_h ); + bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) ); + } + + if (s->nblock > 0) { + + bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 ); + bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); + bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); + + /*-- Now the block's CRC, so it is in a known place. --*/ + bsPutUInt32 ( s, s->blockCRC ); + + /*-- + Now a single bit indicating (non-)randomisation. + As of version 0.9.5, we use a better sorting algorithm + which makes randomisation unnecessary. So always set + the randomised bit to 'no'. Of course, the decoder + still needs to be able to handle randomised blocks + so as to maintain backwards compatibility with + older versions of bzip2. + --*/ + bsW(s,1,0); + + bsW ( s, 24, s->origPtr ); + generateMTFValues ( s ); + sendMTFValues ( s ); + } + + + /*-- If this is the last block, add the stream trailer. --*/ + if (is_last_block) { + + bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 ); + bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); + bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); + bsPutUInt32 ( s, s->combinedCRC ); + if (s->verbosity >= 2) + VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/crctable.c b/plugins/cdvd/CDVDiso/src/bzip2/crctable.c new file mode 100644 index 0000000..bc7e2ae --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/crctable.c @@ -0,0 +1,104 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for doing CRCs ---*/ +/*--- crctable.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlib_private.h" + +/*-- + I think this is an implementation of the AUTODIN-II, + Ethernet & FDDI 32-bit CRC standard. Vaguely derived + from code by Rob Warnock, in Section 51 of the + comp.compression FAQ. +--*/ + +UInt32 BZ2_crc32Table[256] = { + + /*-- Ugly, innit? --*/ + + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, + 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, + 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, + 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, + 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, + 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, + 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, + 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, + 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, + 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, + 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, + 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, + 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, + 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, + 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, + 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, + 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, + 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, + 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, + 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, + 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, + 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, + 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, + 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, + 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, + 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, + 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, + 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, + 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, + 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, + 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, + 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, + 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + + +/*-------------------------------------------------------------*/ +/*--- end crctable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/decompress.c b/plugins/cdvd/CDVDiso/src/bzip2/decompress.c new file mode 100644 index 0000000..124cc8d --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/decompress.c @@ -0,0 +1,626 @@ + +/*-------------------------------------------------------------*/ +/*--- Decompression machinery ---*/ +/*--- decompress.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +static +void makeMaps_d ( DState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->seqToUnseq[s->nInUse] = i; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + while (True) { \ + if (s->bsLive >= nnn) { \ + UInt32 v; \ + v = (s->bsBuff >> \ + (s->bsLive-nnn)) & ((1 << nnn)-1); \ + s->bsLive -= nnn; \ + vvv = v; \ + break; \ + } \ + if (s->strm->avail_in == 0) RETURN(BZ_OK); \ + s->bsBuff \ + = (s->bsBuff << 8) | \ + ((UInt32) \ + (*((UChar*)(s->strm->next_in)))); \ + s->bsLive += 8; \ + s->strm->next_in++; \ + s->strm->avail_in--; \ + s->strm->total_in_lo32++; \ + if (s->strm->total_in_lo32 == 0) \ + s->strm->total_in_hi32++; \ + } + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (groupPos == 0) { \ + groupNo++; \ + if (groupNo >= nSelectors) \ + RETURN(BZ_DATA_ERROR); \ + groupPos = BZ_G_SIZE; \ + gSel = s->selector[groupNo]; \ + gMinlen = s->minLens[gSel]; \ + gLimit = &(s->limit[gSel][0]); \ + gPerm = &(s->perm[gSel][0]); \ + gBase = &(s->base[gSel][0]); \ + } \ + groupPos--; \ + zn = gMinlen; \ + GET_BITS(label1, zvec, zn); \ + while (1) { \ + if (zn > 20 /* the longest code */) \ + RETURN(BZ_DATA_ERROR); \ + if (zvec <= gLimit[zn]) break; \ + zn++; \ + GET_BIT(label2, zj); \ + zvec = (zvec << 1) | zj; \ + }; \ + if (zvec - gBase[zn] < 0 \ + || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ + RETURN(BZ_DATA_ERROR); \ + lval = gPerm[zvec - gBase[zn]]; \ +} + + +/*---------------------------------------------------*/ +Int32 BZ2_decompress ( DState* s ) +{ + UChar uc; + Int32 retVal; + Int32 minLen, maxLen; + bz_stream* strm = s->strm; + + /* stuff that needs to be saved/restored */ + Int32 i; + Int32 j; + Int32 t; + Int32 alphaSize; + Int32 nGroups; + Int32 nSelectors; + Int32 EOB; + Int32 groupNo; + Int32 groupPos; + Int32 nextSym; + Int32 nblockMAX; + Int32 nblock; + Int32 es; + Int32 N; + Int32 curr; + Int32 zt; + Int32 zn; + Int32 zvec; + Int32 zj; + Int32 gSel; + Int32 gMinlen; + Int32* gLimit; + Int32* gBase; + Int32* gPerm; + + if (s->state == BZ_X_MAGIC_1) { + /*initialise the save area*/ + s->save_i = 0; + s->save_j = 0; + s->save_t = 0; + s->save_alphaSize = 0; + s->save_nGroups = 0; + s->save_nSelectors = 0; + s->save_EOB = 0; + s->save_groupNo = 0; + s->save_groupPos = 0; + s->save_nextSym = 0; + s->save_nblockMAX = 0; + s->save_nblock = 0; + s->save_es = 0; + s->save_N = 0; + s->save_curr = 0; + s->save_zt = 0; + s->save_zn = 0; + s->save_zvec = 0; + s->save_zj = 0; + s->save_gSel = 0; + s->save_gMinlen = 0; + s->save_gLimit = NULL; + s->save_gBase = NULL; + s->save_gPerm = NULL; + } + + /*restore from the save area*/ + i = s->save_i; + j = s->save_j; + t = s->save_t; + alphaSize = s->save_alphaSize; + nGroups = s->save_nGroups; + nSelectors = s->save_nSelectors; + EOB = s->save_EOB; + groupNo = s->save_groupNo; + groupPos = s->save_groupPos; + nextSym = s->save_nextSym; + nblockMAX = s->save_nblockMAX; + nblock = s->save_nblock; + es = s->save_es; + N = s->save_N; + curr = s->save_curr; + zt = s->save_zt; + zn = s->save_zn; + zvec = s->save_zvec; + zj = s->save_zj; + gSel = s->save_gSel; + gMinlen = s->save_gMinlen; + gLimit = s->save_gLimit; + gBase = s->save_gBase; + gPerm = s->save_gPerm; + + retVal = BZ_OK; + + switch (s->state) { + + GET_UCHAR(BZ_X_MAGIC_1, uc); + if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_2, uc); + if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_3, uc) + if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) + if (s->blockSize100k < (BZ_HDR_0 + 1) || + s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC); + s->blockSize100k -= BZ_HDR_0; + + if (s->smallDecompress) { + s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); + s->ll4 = BZALLOC( + ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) + ); + if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); + } else { + s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); + if (s->tt == NULL) RETURN(BZ_MEM_ERROR); + } + + GET_UCHAR(BZ_X_BLKHDR_1, uc); + + if (uc == 0x17) goto endhdr_2; + if (uc != 0x31) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_2, uc); + if (uc != 0x41) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_3, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_4, uc); + if (uc != 0x26) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_5, uc); + if (uc != 0x53) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_6, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + + s->currBlockNo++; + if (s->verbosity >= 2) + VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); + + s->storedBlockCRC = 0; + GET_UCHAR(BZ_X_BCRC_1, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_2, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_3, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_4, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + + GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); + + s->origPtr = 0; + GET_UCHAR(BZ_X_ORIGPTR_1, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_2, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_3, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + + if (s->origPtr < 0) + RETURN(BZ_DATA_ERROR); + if (s->origPtr > 10 + 100000*s->blockSize100k) + RETURN(BZ_DATA_ERROR); + + /*--- Receive the mapping table ---*/ + for (i = 0; i < 16; i++) { + GET_BIT(BZ_X_MAPPING_1, uc); + if (uc == 1) + s->inUse16[i] = True; else + s->inUse16[i] = False; + } + + for (i = 0; i < 256; i++) s->inUse[i] = False; + + for (i = 0; i < 16; i++) + if (s->inUse16[i]) + for (j = 0; j < 16; j++) { + GET_BIT(BZ_X_MAPPING_2, uc); + if (uc == 1) s->inUse[i * 16 + j] = True; + } + makeMaps_d ( s ); + if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); + alphaSize = s->nInUse+2; + + /*--- Now the selectors ---*/ + GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); + if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); + if (nSelectors < 1) RETURN(BZ_DATA_ERROR); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (True) { + GET_BIT(BZ_X_SELECTOR_3, uc); + if (uc == 0) break; + j++; + if (j >= nGroups) RETURN(BZ_DATA_ERROR); + } + s->selectorMtf[i] = j; + } + + /*--- Undo the MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], tmp, v; + for (v = 0; v < nGroups; v++) pos[v] = v; + + for (i = 0; i < nSelectors; i++) { + v = s->selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { pos[v] = pos[v-1]; v--; } + pos[0] = tmp; + s->selector[i] = tmp; + } + } + + /*--- Now the coding tables ---*/ + for (t = 0; t < nGroups; t++) { + GET_BITS(BZ_X_CODING_1, curr, 5); + for (i = 0; i < alphaSize; i++) { + while (True) { + if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); + GET_BIT(BZ_X_CODING_2, uc); + if (uc == 0) break; + GET_BIT(BZ_X_CODING_3, uc); + if (uc == 0) curr++; else curr--; + } + s->len[t][i] = curr; + } + } + + /*--- Create the Huffman decoding tables ---*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + BZ2_hbCreateDecodeTables ( + &(s->limit[t][0]), + &(s->base[t][0]), + &(s->perm[t][0]), + &(s->len[t][0]), + minLen, maxLen, alphaSize + ); + s->minLens[t] = minLen; + } + + /*--- Now the MTF values ---*/ + + EOB = s->nInUse+1; + nblockMAX = 100000 * s->blockSize100k; + groupNo = -1; + groupPos = 0; + + for (i = 0; i <= 255; i++) s->unzftab[i] = 0; + + /*-- MTF init --*/ + { + Int32 ii, jj, kk; + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + /*-- end MTF init --*/ + + nblock = 0; + GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); + + while (True) { + + if (nextSym == EOB) break; + + if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + + es = -1; + N = 1; + do { + if (nextSym == BZ_RUNA) es = es + (0+1) * N; else + if (nextSym == BZ_RUNB) es = es + (1+1) * N; + N = N * 2; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); + + es++; + uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; + s->unzftab[uc] += es; + + if (s->smallDecompress) + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->ll16[nblock] = (UInt16)uc; + nblock++; + es--; + } + else + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->tt[nblock] = (UInt32)uc; + nblock++; + es--; + }; + + continue; + + } else { + + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + + /*-- uc = MTF ( nextSym-1 ) --*/ + { + Int32 ii, jj, kk, pp, lno, off; + UInt32 nn; + nn = (UInt32)(nextSym - 1); + + if (nn < MTFL_SIZE) { + /* avoid general-case expense */ + pp = s->mtfbase[0]; + uc = s->mtfa[pp+nn]; + while (nn > 3) { + Int32 z = pp+nn; + s->mtfa[(z) ] = s->mtfa[(z)-1]; + s->mtfa[(z)-1] = s->mtfa[(z)-2]; + s->mtfa[(z)-2] = s->mtfa[(z)-3]; + s->mtfa[(z)-3] = s->mtfa[(z)-4]; + nn -= 4; + } + while (nn > 0) { + s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; + }; + s->mtfa[pp] = uc; + } else { + /* general case */ + lno = nn / MTFL_SIZE; + off = nn % MTFL_SIZE; + pp = s->mtfbase[lno] + off; + uc = s->mtfa[pp]; + while (pp > s->mtfbase[lno]) { + s->mtfa[pp] = s->mtfa[pp-1]; pp--; + }; + s->mtfbase[lno]++; + while (lno > 0) { + s->mtfbase[lno]--; + s->mtfa[s->mtfbase[lno]] + = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; + lno--; + } + s->mtfbase[0]--; + s->mtfa[s->mtfbase[0]] = uc; + if (s->mtfbase[0] == 0) { + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + } + } + /*-- end uc = MTF ( nextSym-1 ) --*/ + + s->unzftab[s->seqToUnseq[uc]]++; + if (s->smallDecompress) + s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else + s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); + nblock++; + + GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); + continue; + } + } + + /* Now we know what nblock is, we can do a better sanity + check on s->origPtr. + */ + if (s->origPtr < 0 || s->origPtr >= nblock) + RETURN(BZ_DATA_ERROR); + + /*-- Set up cftab to facilitate generation of T^(-1) --*/ + s->cftab[0] = 0; + for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; + for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + for (i = 0; i <= 256; i++) { + if (s->cftab[i] < 0 || s->cftab[i] > nblock) { + /* s->cftab[i] can legitimately be == nblock */ + RETURN(BZ_DATA_ERROR); + } + } + + s->state_out_len = 0; + s->state_out_ch = 0; + BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); + s->state = BZ_X_OUTPUT; + if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); + + if (s->smallDecompress) { + + /*-- Make a copy of cftab, used in generation of T --*/ + for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; + + /*-- compute the T vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->ll16[i]); + SET_LL(i, s->cftabCopy[uc]); + s->cftabCopy[uc]++; + } + + /*-- Compute T^(-1) by pointer reversal on T --*/ + i = s->origPtr; + j = GET_LL(i); + do { + Int32 tmp = GET_LL(j); + SET_LL(j, i); + i = j; + j = tmp; + } + while (i != s->origPtr); + + s->tPos = s->origPtr; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_SMALL(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } else { + + /*-- compute the T^(-1) vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->tt[i] & 0xff); + s->tt[s->cftab[uc]] |= (i << 8); + s->cftab[uc]++; + } + + s->tPos = s->tt[s->origPtr] >> 8; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_FAST(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_FAST(s->k0); s->nblock_used++; + } + + } + + RETURN(BZ_OK); + + + + endhdr_2: + + GET_UCHAR(BZ_X_ENDHDR_2, uc); + if (uc != 0x72) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_3, uc); + if (uc != 0x45) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_4, uc); + if (uc != 0x38) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_5, uc); + if (uc != 0x50) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_6, uc); + if (uc != 0x90) RETURN(BZ_DATA_ERROR); + + s->storedCombinedCRC = 0; + GET_UCHAR(BZ_X_CCRC_1, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_2, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_3, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_4, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + + s->state = BZ_X_IDLE; + RETURN(BZ_STREAM_END); + + default: AssertH ( False, 4001 ); + } + + AssertH ( False, 4002 ); + + save_state_and_return: + + s->save_i = i; + s->save_j = j; + s->save_t = t; + s->save_alphaSize = alphaSize; + s->save_nGroups = nGroups; + s->save_nSelectors = nSelectors; + s->save_EOB = EOB; + s->save_groupNo = groupNo; + s->save_groupPos = groupPos; + s->save_nextSym = nextSym; + s->save_nblockMAX = nblockMAX; + s->save_nblock = nblock; + s->save_es = es; + s->save_N = N; + s->save_curr = curr; + s->save_zt = zt; + s->save_zn = zn; + s->save_zvec = zvec; + s->save_zj = zj; + s->save_gSel = gSel; + s->save_gMinlen = gMinlen; + s->save_gLimit = gLimit; + s->save_gBase = gBase; + s->save_gPerm = gPerm; + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/huffman.c b/plugins/cdvd/CDVDiso/src/bzip2/huffman.c new file mode 100644 index 0000000..be4dc02 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/huffman.c @@ -0,0 +1,205 @@ + +/*-------------------------------------------------------------*/ +/*--- Huffman coding low-level stuff ---*/ +/*--- huffman.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlib_private.h" + +/*---------------------------------------------------*/ +#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) +#define DEPTHOF(zz1) ((zz1) & 0x000000ff) +#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) + +#define ADDWEIGHTS(zw1,zw2) \ + (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ + (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) + +#define UPHEAP(z) \ +{ \ + Int32 zz, tmp; \ + zz = z; tmp = heap[zz]; \ + while (weight[tmp] < weight[heap[zz >> 1]]) { \ + heap[zz] = heap[zz >> 1]; \ + zz >>= 1; \ + } \ + heap[zz] = tmp; \ +} + +#define DOWNHEAP(z) \ +{ \ + Int32 zz, yy, tmp; \ + zz = z; tmp = heap[zz]; \ + while (True) { \ + yy = zz << 1; \ + if (yy > nHeap) break; \ + if (yy < nHeap && \ + weight[heap[yy+1]] < weight[heap[yy]]) \ + yy++; \ + if (weight[tmp] < weight[heap[yy]]) break; \ + heap[zz] = heap[yy]; \ + zz = yy; \ + } \ + heap[zz] = tmp; \ +} + + +/*---------------------------------------------------*/ +void BZ2_hbMakeCodeLengths ( UChar *len, + Int32 *freq, + Int32 alphaSize, + Int32 maxLen ) +{ + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + Int32 nNodes, nHeap, n1, n2, i, j, k; + Bool tooLong; + + Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; + Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; + Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; + + for (i = 0; i < alphaSize; i++) + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + + while (True) { + + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + UPHEAP(nHeap); + } + + AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); + + while (nHeap > 1) { + n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + nNodes++; + parent[n1] = parent[n2] = nNodes; + weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + UPHEAP(nHeap); + } + + AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); + + tooLong = False; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { k = parent[k]; j++; } + len[i-1] = j; + if (j > maxLen) tooLong = True; + } + + if (! tooLong) break; + + /* 17 Oct 04: keep-going condition for the following loop used + to be 'i < alphaSize', which missed the last element, + theoretically leading to the possibility of the compressor + looping. However, this count-scaling step is only needed if + one of the generated Huffman code words is longer than + maxLen, which up to and including version 1.0.2 was 20 bits, + which is extremely unlikely. In version 1.0.3 maxLen was + changed to 17 bits, which has minimal effect on compression + ratio, but does mean this scaling step is used from time to + time, enough to verify that it works. + + This means that bzip2-1.0.3 and later will only produce + Huffman codes with a maximum length of 17 bits. However, in + order to preserve backwards compatibility with bitstreams + produced by versions pre-1.0.3, the decompressor must still + handle lengths of up to 20. */ + + for (i = 1; i <= alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbAssignCodes ( Int32 *code, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) + if (length[i] == n) { code[i] = vec; vec++; }; + vec <<= 1; + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbCreateDecodeTables ( Int32 *limit, + Int32 *base, + Int32 *perm, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) + for (j = 0; j < alphaSize; j++) + if (length[j] == i) { perm[pp] = j; pp++; }; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; + for (i = 0; i < alphaSize; i++) base[length[i]+1]++; + + for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (base[i+1] - base[i]); + limit[i] = vec-1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) + base[i] = ((limit[i-1] + 1) << 1) - base[i]; +} + + +/*-------------------------------------------------------------*/ +/*--- end huffman.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/bzip2/randtable.c b/plugins/cdvd/CDVDiso/src/bzip2/randtable.c new file mode 100644 index 0000000..d186335 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/bzip2/randtable.c @@ -0,0 +1,84 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.4 of 20 December 2006 + Copyright (C) 1996-2006 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlib_private.h" + + +/*---------------------------------------------*/ +Int32 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDiso/src/libiso.c b/plugins/cdvd/CDVDiso/src/libiso.c new file mode 100644 index 0000000..f94e4f4 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/libiso.c @@ -0,0 +1,908 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __WIN32__ +#include +#endif + +#include "PS2Etypes.h" +#include "CDVDiso.h" +#include "libiso.h" + +/* some structs from libcdvd by Hiryu & Sjeep (C) 2002 */ + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + + +#ifdef __WIN32__ +void *_openfile(const char *filename, int flags) { + HANDLE handle; + +// printf("_openfile %s, %d\n", filename, flags & O_RDONLY); + if (flags & O_WRONLY) { + int _flags = CREATE_NEW; + if (flags & O_CREAT) _flags = CREATE_ALWAYS; + handle = CreateFile(filename, GENERIC_WRITE, 0, NULL, _flags, 0, NULL); + } else { + handle = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + } + + return handle == INVALID_HANDLE_VALUE ? NULL : handle; +} + +u64 _tellfile(void *handle) { + u64 ofs; + DWORD *_ofs = (DWORD*)&ofs; + _ofs[1] = 0; + _ofs[0] = SetFilePointer(handle, 0, &_ofs[1], FILE_CURRENT); + return ofs; +} + +int _seekfile(void *handle, u64 offset, int whence) { + u64 ofs = (u64)offset; + DWORD *_ofs = (DWORD*)&ofs; +// printf("_seekfile %p, %d_%d\n", handle, _ofs[1], _ofs[0]); + if (whence == SEEK_SET) { + SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_BEGIN); + } else { + SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_END); + } + return 0; +} + +int _readfile(void *handle, void *dst, int size) { + DWORD ret; + +// printf("_readfile %p %d\n", handle, size); + ReadFile(handle, dst, size, &ret, NULL); +// printf("_readfile ret %d; %d\n", ret, GetLastError()); + return ret; +} + +int _writefile(void *handle, void *src, int size) { + DWORD ret; + +// printf("_writefile %p, %d\n", handle, size); +// _seekfile(handle, _tellfile(handle)); + WriteFile(handle, src, size, &ret, NULL); +// printf("_writefile ret %d\n", ret); + return ret; +} + +void _closefile(void *handle) { + CloseHandle(handle); +} + +#else + +void *_openfile(const char *filename, int flags) { + printf("_openfile %s %x\n", filename, flags); + if (flags & O_WRONLY) + return fopen(filename, "wb"); + else return fopen(filename, "rb"); +} + +u64 _tellfile(void *handle) { + return ftell(handle); +} + +int _seekfile(void *handle, u64 offset, int whence) { + return fseek(handle, offset, whence); +} + +int _readfile(void *handle, void *dst, int size) { + return fread(dst, 1, size, handle); +} + +int _writefile(void *handle, void *src, int size) { + return fwrite(src, 1, size, handle); +} + +void _closefile(void *handle) { + fclose(handle); +} + +#endif + +int detect(isoFile *iso) { + char buf[2448]; + struct cdVolDesc *volDesc; + + if (isoReadBlock(iso, buf, 16) == -1) return -1; + volDesc = (struct cdVolDesc *)(buf + 24); + if (strncmp(volDesc->volID, "CD001", 5)) return 0; + + if (volDesc->rootToc.tocSize == 2048) { + iso->type = ISOTYPE_CD; + } else { + iso->type = ISOTYPE_DVD; + } + + return 1; +} + +int _isoReadZtable(isoFile *iso) { + void *handle; + char table[256]; + int size; + + sprintf(table, "%s.table", iso->filename); + handle = _openfile(table, O_RDONLY); + if (handle == NULL) { + printf("Error loading %s\n", table); + return -1; + } + + _seekfile(handle, 0, SEEK_END); + size = _tellfile(handle); + iso->Ztable = (char*)malloc(size); + if (iso->Ztable == NULL) { + return -1; + } + + _seekfile(handle, 0, SEEK_SET); + _readfile(handle, iso->Ztable, size); + _closefile(handle); + + iso->blocks = size / 6; + + return 0; +} + +int _isoReadZ2table(isoFile *iso) { + void *handle; + char table[256]; + u32 *Ztable; + int ofs; + int size; + int i; + + sprintf(table, "%s.table", iso->filename); + handle = _openfile(table, O_RDONLY); + if (handle == NULL) { + printf("Error loading %s\n", table); + return -1; + } + + _seekfile(handle, 0, SEEK_END); + size = _tellfile(handle); + Ztable = (u32*)malloc(size); + if (Ztable == NULL) { + return -1; + } + + _seekfile(handle, 0, SEEK_SET); + _readfile(handle, Ztable, size); + _closefile(handle); + + iso->Ztable = (char*)malloc(iso->blocks*8); + if (iso->Ztable == NULL) { + return -1; + } + + ofs=16; + for (i=0; iblocks; i++) { + *(u32*)&iso->Ztable[i*8+0] = ofs; + *(u32*)&iso->Ztable[i*8+4] = Ztable[i]; + ofs+= Ztable[i]; + } + free(Ztable); + + return 0; +} + +int _isoReadBZ2table(isoFile *iso) { + void *handle; + char table[256]; + u32 *Ztable; + int ofs; + int size; + int i; + + sprintf(table, "%s.table", iso->filename); + handle = _openfile(table, O_RDONLY); + if (handle == NULL) { + printf("Error loading %s\n", table); + return -1; + } + + _seekfile(handle, 0, SEEK_END); + size = _tellfile(handle); + Ztable = (u32*)malloc(size); + if (Ztable == NULL) { + return -1; + } + + _seekfile(handle, 0, SEEK_SET); + _readfile(handle, Ztable, size); + _closefile(handle); + + iso->Ztable = (char*)malloc(iso->blocks*8); + if (iso->Ztable == NULL) { + return -1; + } + + ofs=16; + for (i=0; iblocks/16; i++) { + *(u32*)&iso->Ztable[i*8+0] = ofs; + *(u32*)&iso->Ztable[i*8+4] = Ztable[i]; + ofs+= Ztable[i]; + } + if (iso->blocks & 0xf) { + *(u32*)&iso->Ztable[i*8+0] = ofs; + *(u32*)&iso->Ztable[i*8+4] = Ztable[i]; + ofs+= Ztable[i]; + } + free(Ztable); + + return 0; +} + +int _isoReadDtable(isoFile *iso) { + int ret; + int i; + + _seekfile(iso->handle, 0, SEEK_END); + iso->dtablesize = (_tellfile(iso->handle) - 16) / (iso->blocksize+4); + iso->dtable = (u32*)malloc(iso->dtablesize*4); + + for (i=0; idtablesize; i++) { + _seekfile(iso->handle, 16+(iso->blocksize+4)*i, SEEK_SET); + ret = _readfile(iso->handle, &iso->dtable[i], 4); + if (ret < 4) { + return -1; + } + } + + return 0; +} + +int isoDetect(isoFile *iso) { // based on florin's CDVDbin detection code :) + char buf[32]; + int len; + + iso->type = ISOTYPE_ILLEGAL; + + len = strlen(iso->filename); + if (len >= 2) { + if (!strncmp(iso->filename+(len-2), ".Z", 2)) { + iso->flags = ISOFLAGS_Z; + iso->blocksize = 2352; + _isoReadZtable(iso); + return detect(iso) == 1 ? 0 : -1; + } + } + + _seekfile(iso->handle, 0, SEEK_SET); + _readfile(iso->handle, buf, 4); + if (strncmp(buf, "BDV2", 4) == 0) { + iso->flags = ISOFLAGS_BLOCKDUMP; + _readfile(iso->handle, &iso->blocksize, 4); + _readfile(iso->handle, &iso->blocks, 4); + _readfile(iso->handle, &iso->blockofs, 4); + _isoReadDtable(iso); + return detect(iso) == 1 ? 0 : -1; + } else + if (strncmp(buf, "Z V2", 4) == 0) { + iso->flags = ISOFLAGS_Z2; + _readfile(iso->handle, &iso->blocksize, 4); + _readfile(iso->handle, &iso->blocks, 4); + _readfile(iso->handle, &iso->blockofs, 4); + _isoReadZ2table(iso); + return detect(iso) == 1 ? 0 : -1; + } else + if (strncmp(buf, "BZV2", 4) == 0) { + iso->flags = ISOFLAGS_BZ2; + _readfile(iso->handle, &iso->blocksize, 4); + _readfile(iso->handle, &iso->blocks, 4); + _readfile(iso->handle, &iso->blockofs, 4); + iso->buflsn = -1; + iso->buffer = malloc(iso->blocksize*16); + if (iso->buffer == NULL) return -1; + _isoReadBZ2table(iso); + return detect(iso) == 1 ? 0 : -1; + } else { + iso->blocks = 16; + } + + // ISO 2048 + iso->blocksize = 2048; iso->offset = 0; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // RAW 2336 + iso->blocksize = 2336; iso->offset = 0; iso->blockofs = 16; + if (detect(iso) == 1) return 0; + + // RAW 2352 + iso->blocksize = 2352; iso->offset = 0; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // RAWQ 2448 + iso->blocksize = 2448; iso->offset = 0; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // NERO ISO 2048 + iso->blocksize = 2048; iso->offset = 150*2048; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // NERO RAW 2352 + iso->blocksize = 2352; iso->offset = 150*2048; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // NERO RAWQ 2448 + iso->blocksize = 2448; iso->offset = 150*2048; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // ISO 2048 + iso->blocksize = 2048; iso->offset = -8; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // RAW 2352 + iso->blocksize = 2352; iso->offset = -8; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // RAWQ 2448 + iso->blocksize = 2448; iso->offset = -8; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + iso->offset = 0; + iso->blocksize = 2352; + iso->type = ISOTYPE_AUDIO; + return 0; + + return -1; +} + +isoFile *isoOpen(const char *filename) { + isoFile *iso; + int i; + + iso = (isoFile*)malloc(sizeof(isoFile)); + if (iso == NULL) return NULL; + + memset(iso, 0, sizeof(isoFile)); + strcpy(iso->filename, filename); + + iso->handle = _openfile(iso->filename, O_RDONLY); + if (iso->handle == NULL) { + printf("Error loading %s\n", iso->filename); + return NULL; + } + + if (isoDetect(iso) == -1) return NULL; + + printf("detected blocksize = %d\n", iso->blocksize); + + if (strlen(iso->filename) > 3 && + strncmp(iso->filename + (strlen(iso->filename) - 3), "I00", 3) == 0) { + _closefile(iso->handle); + iso->flags|= ISOFLAGS_MULTI; + iso->blocks = 0; + for (i=0; i<8; i++) { + iso->filename[strlen(iso->filename) - 1] = '0' + i; + iso->multih[i].handle = _openfile(iso->filename, O_RDONLY); + if (iso->multih[i].handle == NULL) { + break; + } + iso->multih[i].slsn = iso->blocks; + _seekfile(iso->multih[i].handle, 0, SEEK_END); + iso->blocks+= (u32)((_tellfile(iso->multih[i].handle) - iso->offset) / + (iso->blocksize)); + iso->multih[i].elsn = iso->blocks-1; + } + + if (i == 0) { + return NULL; + } + } + + if (iso->flags == 0) { + _seekfile(iso->handle, 0, SEEK_END); + iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / + (iso->blocksize)); + } + + + printf("isoOpen: %s ok\n", iso->filename); + printf("offset = %d\n", iso->offset); + printf("blockofs = %d\n", iso->blockofs); + printf("blocksize = %d\n", iso->blocksize); + printf("blocks = %d\n", iso->blocks); + printf("type = %d\n", iso->type); + + return iso; +} + +isoFile *isoCreate(const char *filename, int flags) { + isoFile *iso; + char Zfile[256]; + + iso = (isoFile*)malloc(sizeof(isoFile)); + if (iso == NULL) return NULL; + + memset(iso, 0, sizeof(isoFile)); + strcpy(iso->filename, filename); + iso->flags = flags; + iso->offset = 0; + iso->blockofs = 24; + iso->blocksize = CD_FRAMESIZE_RAW; + iso->blocksize = 2048; + + if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BZ2)) { + sprintf(Zfile, "%s.table", iso->filename); + iso->htable = _openfile(Zfile, O_WRONLY); + if (iso->htable == NULL) { + return NULL; + } + } + + iso->handle = _openfile(iso->filename, O_WRONLY | O_CREAT); + if (iso->handle == NULL) { + printf("Error loading %s\n", iso->filename); + return NULL; + } + printf("isoCreate: %s ok\n", iso->filename); + printf("offset = %d\n", iso->offset); + + return iso; +} + +int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks) { + iso->blocksize = blocksize; + iso->blocks = blocks; + iso->blockofs = blockofs; + printf("blockofs = %d\n", iso->blockofs); + printf("blocksize = %d\n", iso->blocksize); + printf("blocks = %d\n", iso->blocks); + if (iso->flags & ISOFLAGS_Z2) { + if (_writefile(iso->handle, "Z V2", 4) < 4) return -1; + if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; + if (_writefile(iso->handle, &blocks, 4) < 4) return -1; + if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; + } + if (iso->flags & ISOFLAGS_BZ2) { + if (_writefile(iso->handle, "BZV2", 4) < 4) return -1; + if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; + if (_writefile(iso->handle, &blocks, 4) < 4) return -1; + if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; + iso->buflsn = -1; + iso->buffer = malloc(iso->blocksize*16); + if (iso->buffer == NULL) return -1; + } + if (iso->flags & ISOFLAGS_BLOCKDUMP) { + if (_writefile(iso->handle, "BDV2", 4) < 4) return -1; + if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; + if (_writefile(iso->handle, &blocks, 4) < 4) return -1; + if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; + } + + return 0; +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + u8 m, s, f; + + lsn += 150; + m = lsn / 4500; // minuten + lsn = lsn - m * 4500; // minuten rest + s = lsn / 75; // sekunden + f = lsn - (s * 75); // sekunden rest + Time[0] = itob(m); Time[1] = itob(s); Time[2] = itob(f); +} + +int _isoReadBlock(isoFile *iso, char *dst, int lsn) { + u64 ofs = (u64)lsn * iso->blocksize + iso->offset; + int ret; + +// printf("_isoReadBlock %d, blocksize=%d, blockofs=%d\n", lsn, iso->blocksize, iso->blockofs); + memset(dst, 0, iso->blockofs); + _seekfile(iso->handle, ofs, SEEK_SET); + ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize); + if (ret < iso->blocksize) { + printf("read error %d\n", ret); + return -1; + } + + return 0; +} + +int _isoReadBlockZ(isoFile *iso, char *dst, int lsn) { + u32 pos, p; + uLongf size; + u8 Zbuf[CD_FRAMESIZE_RAW*2]; + int ret; + +// printf("_isoReadBlockZ %d, %d\n", lsn, iso->blocksize); + pos = *(unsigned long*)&iso->Ztable[lsn * 6]; + p = *(unsigned short*)&iso->Ztable[lsn * 6 + 4]; +// printf("%d, %d\n", pos, p); + _seekfile(iso->handle, pos, SEEK_SET); + ret = _readfile(iso->handle, Zbuf, p); + if (ret < p) { + printf("error reading block!!\n"); + return -1; + } + + size = CD_FRAMESIZE_RAW; + uncompress(dst, &size, Zbuf, p); + + return 0; +} + +int _isoReadBlockZ2(isoFile *iso, char *dst, int lsn) { + u32 pos, p; + uLongf size; + u8 Zbuf[16*1024]; + int ret; + +// printf("_isoReadBlockZ2 %d, %d\n", lsn, iso->blocksize); + pos = *(u32*)&iso->Ztable[lsn*8]; + p = *(u32*)&iso->Ztable[lsn*8+4]; +// printf("%d, %d\n", pos, p); + _seekfile(iso->handle, pos, SEEK_SET); + ret = _readfile(iso->handle, Zbuf, p); + if (ret < p) { + printf("error reading block!!\n"); + return -1; + } + + size = iso->blocksize; + uncompress(dst + iso->blockofs, &size, Zbuf, p); + + return 0; +} + +int _isoReadBlockBZ2(isoFile *iso, char *dst, int lsn) { + u32 pos, p; + u32 size; + u8 Zbuf[64*1024]; + int ret; + + if ((lsn/16) == iso->buflsn) { + memset(dst, 0, iso->blockofs); + memcpy(dst + iso->blockofs, iso->buffer+(iso->blocksize*(lsn&0xf)), iso->blocksize); + return 0; + } + + iso->buflsn = lsn/16; +// printf("_isoReadBlockBZ2 %d, %d\n", lsn, iso->blocksize); + pos = *(u32*)&iso->Ztable[(lsn/16)*8]; + p = *(u32*)&iso->Ztable[(lsn/16)*8+4]; +// printf("%d, %d\n", pos, p); + _seekfile(iso->handle, pos, SEEK_SET); + ret = _readfile(iso->handle, Zbuf, p); + if (ret < p) { + printf("error reading block!!\n"); + return -1; + } + + size = iso->blocksize*64; + ret = BZ2_bzBuffToBuffDecompress(iso->buffer, &size, Zbuf, p, 0, 0); + if (ret != BZ_OK) { + printf("_isoReadBlockBZ2 %d, %d\n", lsn, iso->blocksize); + printf("%d, %d\n", pos, p); + printf("error on BZ2: %d\n", ret); + } + + memset(dst, 0, iso->blockofs); + memcpy(dst + iso->blockofs, iso->buffer+(iso->blocksize*(lsn&0xf)), iso->blocksize); + + return 0; +} + +int _isoReadBlockD(isoFile *iso, char *dst, int lsn) { + int ret; + int i; + +// printf("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", lsn, iso->blocksize, iso->blockofs); + memset(dst, 0, iso->blockofs); + for (i=0; idtablesize;i++) { + if (iso->dtable[i] != lsn) continue; + + _seekfile(iso->handle, 16+i*(iso->blocksize+4)+4, SEEK_SET); + ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize); + if (ret < iso->blocksize) return -1; + + return 0; + } + printf("block %d not found in dump\n", lsn); + + return -1; +} + +int _isoReadBlockM(isoFile *iso, char *dst, int lsn) { + u64 ofs; + int ret; + int i; + + for (i=0; i<8; i++) { + if (lsn >= iso->multih[i].slsn && + lsn <= iso->multih[i].elsn) { + break; + } + } + if (i==8) return -1; + + ofs = (u64)(lsn-iso->multih[i].slsn) * iso->blocksize + iso->offset; +// printf("_isoReadBlock %d, blocksize=%d, blockofs=%d\n", lsn, iso->blocksize, iso->blockofs); + memset(dst, 0, iso->blockofs); + _seekfile(iso->multih[i].handle, ofs, SEEK_SET); + ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize); + if (ret < iso->blocksize) { + printf("read error %d\n", ret); + return -1; + } + + return 0; +} + +int isoReadBlock(isoFile *iso, char *dst, int lsn) { + int ret; + + if (lsn > iso->blocks) { + printf("isoReadBlock: %d > %d\n", lsn, iso->blocks); + return -1; + } + if (iso->flags & ISOFLAGS_Z) { + ret = _isoReadBlockZ(iso, dst, lsn); + } else + if (iso->flags & ISOFLAGS_Z2) { + ret = _isoReadBlockZ2(iso, dst, lsn); + } else + if (iso->flags & ISOFLAGS_BLOCKDUMP) { + ret = _isoReadBlockD(iso, dst, lsn); + } else + if (iso->flags & ISOFLAGS_MULTI) { + ret = _isoReadBlockM(iso, dst, lsn); + } else + if (iso->flags & ISOFLAGS_BZ2) { + ret = _isoReadBlockBZ2(iso, dst, lsn); + } else + ret = _isoReadBlock(iso, dst, lsn); + if (ret == -1) return ret; + + if (iso->type == ISOTYPE_CD) { + LSNtoMSF(dst+12, lsn); + dst[15] = 2; + } + + return 0; +} + + +int _isoWriteBlock(isoFile *iso, u8 *src, int lsn) { + u64 ofs = (u64)lsn * iso->blocksize + iso->offset; + int ret; + +// printf("_isoWriteBlock %d (ofs=%d)\n", iso->blocksize, ofs); + _seekfile(iso->handle, ofs, SEEK_SET); + ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlock %d\n", ret); + if (ret < iso->blocksize) return -1; + + return 0; +} + +int _isoWriteBlockZ(isoFile *iso, u8 *src, int lsn) { + u32 pos; + uLongf size; + u8 Zbuf[CD_FRAMESIZE_RAW]; + int ret; + +// printf("_isoWriteBlockZ %d\n", iso->blocksize); + size = 2352; + compress(Zbuf, &size, src, 2352); +// printf("_isoWriteBlockZ %d\n", size); + + pos = (u32)_tellfile(iso->handle); + ret = _writefile(iso->htable, (u8*)&pos, 4); + if (ret < 4) return -1; + ret = _writefile(iso->htable, (u8*)&size, 2); + if (ret < 2) return -1; + + ret = _writefile(iso->handle, Zbuf, size); +// printf("_isoWriteBlockZ %d\n", ret); + if (ret < size) { + printf("error writing block!!\n"); + return -1; + } + + return 0; +} + +int _isoWriteBlockZ2(isoFile *iso, u8 *src, int lsn) { + uLongf size; + u8 Zbuf[1024*16]; + int ret; + +// printf("_isoWriteBlockZ %d\n", iso->blocksize); + size = 1024*16; + compress(Zbuf, &size, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlockZ %d\n", size); + + ret = _writefile(iso->htable, (u8*)&size, 4); + if (ret < 4) return -1; + ret = _writefile(iso->handle, Zbuf, size); +// printf("_isoWriteBlockZ %d\n", ret); + if (ret < size) { + printf("error writing block!!\n"); + return -1; + } + + return 0; +} + +int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn) { + int ret; + +// printf("_isoWriteBlock %d (ofs=%d)\n", iso->blocksize, ofs); + ret = _writefile(iso->handle, &lsn, 4); + if (ret < 4) return -1; + ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlock %d\n", ret); + if (ret < iso->blocksize) return -1; + + return 0; +} + +int _isoWriteBlockBZ2(isoFile *iso, u8 *src, int lsn) { + u32 size; + u8 Zbuf[64*1024]; + int blocks; + int ret; + + memcpy(iso->buffer+(iso->blocksize*(lsn&0xf)), src + iso->blockofs, iso->blocksize); + + if (lsn == (iso->blocks-1)) { + blocks = (lsn & 0xf)+1; + } else { + blocks = 16; + if ((lsn & 0xf) != 0xf) return 0; + } + +// printf("_isoWriteBlockBZ2 %d\n", iso->blocksize); + size = 64*1024; + ret = BZ2_bzBuffToBuffCompress(Zbuf, (u32*)&size, iso->buffer, iso->blocksize*blocks, 9, 0, 30); + if (ret != BZ_OK) { + printf("error on BZ2: %d\n", ret); + } +// printf("_isoWriteBlockBZ2 %d\n", size); + + ret = _writefile(iso->htable, (u8*)&size, 4); + if (ret < 4) return -1; + ret = _writefile(iso->handle, Zbuf, size); +// printf("_isoWriteBlockZ %d\n", ret); + if (ret < size) { + printf("error writing block!!\n"); + return -1; + } + + return 0; +} + +int isoWriteBlock(isoFile *iso, char *src, int lsn) { + int ret; + + if (iso->flags & ISOFLAGS_Z) { + ret = _isoWriteBlockZ(iso, src, lsn); + } else + if (iso->flags & ISOFLAGS_Z2) { + ret = _isoWriteBlockZ2(iso, src, lsn); + } else + if (iso->flags & ISOFLAGS_BLOCKDUMP) { + ret = _isoWriteBlockD(iso, src, lsn); + } else + if (iso->flags & ISOFLAGS_BZ2) { + ret = _isoWriteBlockBZ2(iso, src, lsn); + } else + ret = _isoWriteBlock(iso, src, lsn); + if (ret == -1) return ret; + + return 0; +} + +void isoClose(isoFile *iso) { + if (iso->handle) { + _closefile(iso->handle); + } + if (iso->htable) { + _closefile(iso->htable); + } + if (iso->buffer) { + free(iso->buffer); + } + free(iso); +} + diff --git a/plugins/cdvd/CDVDiso/src/libiso.h b/plugins/cdvd/CDVDiso/src/libiso.h new file mode 100644 index 0000000..458d560 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/libiso.h @@ -0,0 +1,65 @@ +#ifndef __LIBISO_H__ +#define __LIBISO_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4018) +#endif + +#define ISOTYPE_ILLEGAL 0 +#define ISOTYPE_CD 1 +#define ISOTYPE_DVD 2 +#define ISOTYPE_AUDIO 3 + +#define ISOFLAGS_Z 0x0001 +#define ISOFLAGS_Z2 0x0002 +#define ISOFLAGS_BLOCKDUMP 0x0004 +#define ISOFLAGS_MULTI 0x0008 +#define ISOFLAGS_BZ2 0x0010 + +#define CD_FRAMESIZE_RAW 2352 +#define DATA_SIZE (CD_FRAMESIZE_RAW-12) + +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ + +typedef struct { + u32 slsn; + u32 elsn; + void *handle; +} _multih; + +typedef struct { + char filename[256]; + u32 type; + u32 flags; + u32 offset; + u32 blockofs; + u32 blocksize; + u32 blocks; + void *handle; + void *htable; + char *Ztable; + u32 *dtable; + int dtablesize; + _multih multih[8]; + int buflsn; + char *buffer; +} isoFile; + + +isoFile *isoOpen(const char *filename); +isoFile *isoCreate(const char *filename, int mode); +int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks); +int isoDetect(isoFile *iso); +int isoReadBlock(isoFile *iso, char *dst, int lsn); +int isoWriteBlock(isoFile *iso, char *src, int lsn); +void isoClose(isoFile *iso); + +void *_openfile(const char *filename, int flags); +u64 _tellfile(void *handle); +int _seekfile(void *handle, u64 offset, int whence); +int _readfile(void *handle, void *dst, int size); +int _writefile(void *handle, void *src, int size); +void _closefile(void *handle); + +#endif /* __LIBISO_H__ */ diff --git a/plugins/cdvd/CDVDiso/src/mkiso/Makefile b/plugins/cdvd/CDVDiso/src/mkiso/Makefile new file mode 100644 index 0000000..052c8b5 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/mkiso/Makefile @@ -0,0 +1,26 @@ + +CC = gcc + +MKISO = mkiso +CFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -I.. -I. -D__LINUX__ -I../zlib +OBJS = mkiso.o ../libiso.o +LIBS = +OBJS+= ../zlib/adler32.o ../zlib/compress.o ../zlib/crc32.o ../zlib/gzio.o ../zlib/uncompr.o ../zlib/deflate.o ../zlib/trees.o \ + ../zlib/zutil.o ../zlib/inflate.o ../zlib/infback.o ../zlib/inftrees.o ../zlib/inffast.o + +DEPS:= $(OBJS:.o=.d) + +all: mkiso + +mkiso: ${OBJS} + rm -f ${MKISO} + ${CC} ${CFLAGS} ${OBJS} -o ${MKISO} ${LIBS} + strip ${MKISO} + +clean: + rm -f ${OBJS} ${DEPS} ${MKISO} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/cdvd/CDVDiso/src/mkiso/Makefile.mingw b/plugins/cdvd/CDVDiso/src/mkiso/Makefile.mingw new file mode 100644 index 0000000..c854399 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/mkiso/Makefile.mingw @@ -0,0 +1,31 @@ + +CC = gcc + +MKISO = mkiso.exe +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing +CFLAGS = -Wall ${OPTIMIZE} -I.. -I. -D__WIN32__ -I../zlib -I../bzip2 +OBJS = mkiso.o ../libiso.o +LIBS = +OBJS+= ../zlib/adler32.o ../zlib/compress.o ../zlib/crc32.o ../zlib/gzio.o ../zlib/uncompr.o ../zlib/deflate.o ../zlib/trees.o \ + ../zlib/zutil.o ../zlib/inflate.o ../zlib/infback.o ../zlib/inftrees.o ../zlib/inffast.o +OBJS+= ../bzip2/blocksort.o ../bzip2/huffman.o \ + ../bzip2/crctable.o ../bzip2/randtable.o \ + ../bzip2/compress.o ../bzip2/decompress.o \ + ../bzip2/bzlib.o + +DEPS:= $(OBJS:.o=.d) + +all: mkiso + +mkiso: ${OBJS} + rm -f ${MKISO} + ${CC} ${CFLAGS} ${OBJS} -o ${MKISO} ${LIBS} + strip ${MKISO} + +clean: + rm -f ${OBJS} ${DEPS} ${MKISO} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/cdvd/CDVDiso/src/mkiso/mkiso.c b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.c new file mode 100644 index 0000000..70e6da7 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.c @@ -0,0 +1,153 @@ +/* CDVDiso + * Copyright (C) 2002-2004 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "CDVDiso.h" + + +void Compress(char *filename, int mode) { + struct stat buf; + u32 lsn; + u8 cdbuff[1024*16]; + char Zfile[256]; + int ret=0; + isoFile *src; + isoFile *dst; + + if (mode == 1) { + sprintf(Zfile, "%s.Z2", filename); + } else { + sprintf(Zfile, "%s.BZ2", filename); + } + + if (stat(Zfile, &buf) != -1) { + printf("'%s' already exists\n", Zfile); + return; +/* sprintf(str, "'%s' already exists, overwrite?", Zfile); + if (MessageBox(hDlg, str, "Question", MB_YESNO) != IDYES) { + return; + }*/ + } + + printf("src %s; dst %s\n", filename, Zfile); + src = isoOpen(filename); + if (src == NULL) return; + + if (mode == 1) { + dst = isoCreate(Zfile, ISOFLAGS_Z2); + } else { + dst = isoCreate(Zfile, ISOFLAGS_BZ2); + } + isoSetFormat(dst, src->blockofs, src->blocksize, src->blocks); + if (dst == NULL) return; + + for (lsn = 0; lsnblocks; lsn++) { + printf("block %d ", lsn); + putchar(13); + fflush(stdout); + ret = isoReadBlock(src, cdbuff, lsn); + if (ret == -1) break; + ret = isoWriteBlock(dst, cdbuff, lsn); + if (ret == -1) break; + } + isoClose(src); + isoClose(dst); + + if (ret == -1) { + printf("Error compressing iso image\n"); + } else { + printf("Iso image compressed OK\n"); + } +} + +void Decompress(char *filename) { + struct stat buf; + char file[256]; + u8 cdbuff[10*2352]; + u32 lsn; + isoFile *src; + isoFile *dst; + int ret=0; + + src = isoOpen(filename); + if (src == NULL) return; + + strcpy(file, filename); + if (src->flags & ISOFLAGS_Z) { + file[strlen(file) - 2] = 0; + } else + if (src->flags & ISOFLAGS_Z2) { + file[strlen(file) - 3] = 0; + } else + if (src->flags & ISOFLAGS_BZ2) { + file[strlen(file) - 3] = 0; + } else { + printf("%s is not a compressed image\n", filename); + return; + } + if (stat(file, &buf) != -1) { + char str[256]; + sprintf(str, "'%s' already exists", file); + isoClose(src); + return; + } + + dst = isoCreate(file, 0); + if (dst == NULL) return; + isoSetFormat(dst, src->blockofs, src->blocksize, src->blocks); + + for (lsn = 0; lsnblocks; lsn++) { + printf("block %d ", lsn); + putchar(13); + fflush(stdout); + ret = isoReadBlock(src, cdbuff, lsn); + if (ret == -1) break; + ret = isoWriteBlock(dst, cdbuff, lsn); + if (ret == -1) break; + } + + isoClose(src); + isoClose(dst); + + if (ret == -1) { + printf("Error decompressing iso image\n"); + } else { + printf("Iso image decompressed OK\n"); + } +} + + +int main(int argc, char *argv[]) { + if (argc < 3) return 0; + + if (argv[1][0] == 'c') { + Compress(argv[2], 1); + } else + if (argv[1][0] == 'C') { + Compress(argv[2], 2); + } else + if (argv[1][0] == 'd') { + Decompress(argv[2]); + } + + return 0; +} diff --git a/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsp b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsp new file mode 100644 index 0000000..85e4136 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsp @@ -0,0 +1,206 @@ +# Microsoft Developer Studio Project File - Name="mkiso" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mkiso - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mkiso.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mkiso.mak" CFG="mkiso - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mkiso - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mkiso - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mkiso - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /D "__MSCW32__" /YX /FD /c +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "mkiso - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "./" /I "../" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__WIN32__" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x2c0a /d "_DEBUG" +# ADD RSC /l 0x2c0a /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib zlib.lib libbz2.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mkiso - Win32 Release" +# Name "mkiso - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\libiso.c +# End Source File +# Begin Source File + +SOURCE=.\mkiso.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\zlib\adler32.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\compress.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\crc32.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\crc32.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\deflate.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\deflate.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\gvmat32c.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\gzio.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\infback.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\inffas8664.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\inffast.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\inffast.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\inffixed.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\inflate.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\inflate.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\inftrees.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\inftrees.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\trees.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\trees.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\uncompr.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\zconf.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\zlib.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\zutil.c +# End Source File +# Begin Source File + +SOURCE=..\zlib\zutil.h +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsw b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsw new file mode 100644 index 0000000..81430b0 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/mkiso/mkiso.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "mkiso"=.\mkiso.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/cdvd/CDVDiso/src/zlib/ChangeLog b/plugins/cdvd/CDVDiso/src/zlib/ChangeLog new file mode 100644 index 0000000..1ac9463 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/ChangeLog @@ -0,0 +1,855 @@ + + ChangeLog file for zlib + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Added zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases. +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] + +Changes in 1.2.2 (3 October 2004) +- Update zlib.h comments on gzip in-memory processing +- Set adler to 1 in inflateReset() to support Java test suite [Walles] +- Add contrib/dotzlib [Ravn] +- Update win32/DLL_FAQ.txt [Truta] +- Update contrib/minizip [Vollant] +- Move contrib/visual-basic.txt to old/ [Truta] +- Fix assembler builds in projects/visualc6/ [Truta] + +Changes in 1.2.1.2 (9 September 2004) +- Update INDEX file +- Fix trees.c to update strm->data_type (no one ever noticed!) +- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] +- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) +- Add limited multitasking protection to DYNAMIC_CRC_TABLE +- Add NO_vsnprintf for VMS in zutil.h [Mozilla] +- Don't declare strerror() under VMS [Mozilla] +- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize +- Update contrib/ada [Anisimkov] +- Update contrib/minizip [Vollant] +- Fix configure to not hardcode directories for Darwin [Peterson] +- Fix gzio.c to not return error on empty files [Brown] +- Fix indentation; update version in contrib/delphi/ZLib.pas and + contrib/pascal/zlibpas.pas [Truta] +- Update mkasm.bat in contrib/masmx86 [Truta] +- Update contrib/untgz [Truta] +- Add projects/README.projects [Truta] +- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] +- Remove an unnecessary assignment to curr in inftrees.c [Truta] +- Add OS/2 to exe builds in configure [Poltorak] +- Remove err dummy parameter in zlib.h [Kientzle] + +Changes in 1.2.1.1 (9 January 2004) +- Update email address in README +- Several FAQ updates +- Fix a big fat bug in inftrees.c that prevented decoding valid + dynamic blocks with only literals and no distance codes -- + Thanks to "Hot Emu" for the bug report and sample file +- Add a note to puff.c on no distance codes case. + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occurring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Lvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/plugins/cdvd/CDVDiso/src/zlib/README b/plugins/cdvd/CDVDiso/src/zlib/README new file mode 100644 index 0000000..80f71ae --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/README @@ -0,0 +1,125 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.3 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install". For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.3 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2004 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/plugins/cdvd/CDVDiso/src/zlib/adler32.c b/plugins/cdvd/CDVDiso/src/zlib/adler32.c new file mode 100644 index 0000000..f201d67 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/compress.c b/plugins/cdvd/CDVDiso/src/zlib/compress.c new file mode 100644 index 0000000..d37e84f --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/crc32.c b/plugins/cdvd/CDVDiso/src/zlib/crc32.c new file mode 100644 index 0000000..32814c2 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/crc32.h b/plugins/cdvd/CDVDiso/src/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/cdvd/CDVDiso/src/zlib/deflate.c b/plugins/cdvd/CDVDiso/src/zlib/deflate.c new file mode 100644 index 0000000..529f716 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/deflate.c @@ -0,0 +1,1736 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + /* %%% avoid this when Z_RLE */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +#if 0 +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif diff --git a/plugins/cdvd/CDVDiso/src/zlib/deflate.h b/plugins/cdvd/CDVDiso/src/zlib/deflate.h new file mode 100644 index 0000000..222c53e --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/gvmat32.obj b/plugins/cdvd/CDVDiso/src/zlib/gvmat32.obj new file mode 100644 index 0000000000000000000000000000000000000000..b215511b0b4c7a0e25957aaea71516367e689507 GIT binary patch literal 10137 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 WW3{ysJC^V-X2vvN#VBA!9Ps}|LQHM| literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDiso/src/zlib/gvmat32c.c b/plugins/cdvd/CDVDiso/src/zlib/gvmat32c.c new file mode 100644 index 0000000..7ad2b27 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/gvmat32c.c @@ -0,0 +1,62 @@ +/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 + * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. + * File written by Gilles Vollant, by modifiying the longest_match + * from Jean-loup Gailly in deflate.c + * it prepare all parameters and call the assembly longest_match_gvasm + * longest_match execute standard C code is wmask != 0x7fff + * (assembly code is faster with a fixed wmask) + * + * Read comment at beginning of gvmat32.asm for more information + */ + +#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) +#include "deflate.h" + +/* if your C compiler don't add underline before function name, + define ADD_UNDERLINE_ASMFUNC */ +#ifdef ADD_UNDERLINE_ASMFUNC +#define longest_match_7fff _longest_match_7fff +#define longest_match_686 _longest_match_686 +#define cpudetect32 _cpudetect32 +#endif + + +unsigned long cpudetect32(); + +uInt longest_match_c( + deflate_state *s, + IPos cur_match); /* current match */ + + +uInt longest_match_7fff( + deflate_state *s, + IPos cur_match); /* current match */ + +uInt longest_match_686( + deflate_state *s, + IPos cur_match); /* current match */ + + +static uInt iIsPPro=2; + +void match_init () +{ + iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; +} + +uInt longest_match( + deflate_state *s, + IPos cur_match) /* current match */ +{ + if (iIsPPro!=0) + return longest_match_686(s,cur_match); + + if (s->w_mask != 0x7fff) + return longest_match_686(s,cur_match); + + /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */ + return longest_match_7fff(s,cur_match); +} + + +#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/gvmat64.obj b/plugins/cdvd/CDVDiso/src/zlib/gvmat64.obj new file mode 100644 index 0000000000000000000000000000000000000000..ce31fc14bbbc97429b22f70e48bfa575b4e809ce GIT binary patch literal 4215 zcmb8yeQ*@z9l-J5B{8IXjd#3*R9S{Al>(V0gcuU2NjTtAFAP$uj9g1Ed%0W6Ki$dZ z^Lu{#?C$eCxA#1It(%Kv>EfY{{!$TL2DY+vWKG(R75xPw2lL7*)Meq1%38ze@J0EH zi}kXwx2!eN(z(L-z3j0khlt!&C^E}EkST+D@iyA^7H8|tA}FC<`J1X2=)TQ&JkXu? z^#{5`zLSCOnD3O|JQD0~^_>k;IB)*uKF%=@>{tIA>djpb5Y&BjTjAl;1({=q-}k!v zIkDI5dXl`~+_pneciiu3KJM>c>^mAXuMe2}?jpOOCpJ==%|A4KaiVF%hlOTC&9q{d z$n?ww2n&&-EOdFvoK!v+?KZ;uDX|^BgLg z@2`8!v$>rMbbTV?63?A2!~+%6osLRPd6j18DlK$W^5s<;Ggzr}+v&-UY8Plh_J*Gk z+b!GFmdRw==GXbWo=r;$>3J_*DF{4&{ws=XO+5!^lyKeadR{D5dd7^XWUmdFMU{c+ zMYWxi0;a#RBrx4yThcj7#a$jK(^*QUC~)|c-sbM@ z9CG-SmvX^WS75_i66h(aZJKg;b^-TVKf9r>?~b8rY_lW!@g&aooBjUouB~*V&hI!37YEBAv)hz zs)bYW>Y8eObu_(Fk5ibcCpyy6cr+Dh)x)V&B;FERt1nNqM)bC1BCa)`nI`xjmN+tqVq5{IOVQT`byCQCUfwLaJeFs;fdPR>i~V>Z&q| za*or+u+wqzy0)J?GkW3Oi*D621$BEz?B}ANli#XtVsGkut+spEH`@8}B8JNG&$tY` zP{W^~2RGmd+=!!b6Mh3X;{@D>-@>2bG~ABmxC5(kC)VK4uomyd+4vA%i+ivUA4Weu zf&qLK7vN*~ef$+J!F?FQUt<`bzzFiqHg3TK*n!Vt3J>8bd=A&)OSm3iM*1kPAbpcw zq)&1Ld+=3M58W}OFY+edhi~D7_%_m3c^7G`yoYM~`6E7sC-52kGd_n*GvFLJ%F&_CA856J&C*nAqgjeDeyb8;Zx<(c1Sc{xv)Z;gC9&(Nm z#H;aooQyZ(G+c_DYb?VV7{zM*F_ggUypHSecX%uQ z9&g7t@D6+%4SWabgYh2H2jc{8#*?@OKg2unBfJ|w!F%uwZo{*<9nawoJdgC%xPZG+ z3Pc{nA@~rwaSxW_BRCZI;%NLOj>AWBJTexB5BKA@k+Co;@M*jT4`MAogWtgya1OqR z0c329W_%eJA!B6Rh`kuX*YI6DX3H2EYE62a+)Qx|CH#MuebXP#liB`vfMBct=Xc=H(*cRT0%eb)ce}Wh^&b`G;y88et;KGcW=EP_OQfDX zx6H94O>Q7k51m_XvLj7mM8m9HhaG9MfoQmu+hRwW>>?Ur<#yYVCQlHJv~o||ktVMa zjk0n_?TEe+jkakg_WCTN18Mejk9v|>`0R( zMC!f6Eg?IiZ$wvGxehy`Z$wvFxh-}?--yOrx!rc8NfG5@YotH_>~bmbs>wuc1q^Dj zxYUqwG?y>R%hxYY#5>BOt@rO)FX~OVQ1X94smY|!m3`Mz*BRLIe?2jCs1^2qw)|gC zszrq^_1me;Q7`{jlj=pGYnJ19wxEuw%_X{8AlOu=)TA|#@%hTFO&zh?tO9F1XWJP* zIJPP5VRlt#ATyKbDMw~5CG{4QtFw@jdXLFvLX^~-N-nd467L~-8TH0CmI}E#x09LZ z$aIsbcVxDc2@YnmvkEJ2-gWj;N3Hk#*}XVOq*nf1rjLwz2gqgKB*ThjXM*;GqSp0X zoj*}Wt;D&EdOuTZ>Odx_W-VqBwW + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[46]; /* allow for up to 128-bit integers */ + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + start++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + if (len == s->stream.avail_out && + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) + return -1; + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Returns 1 if reading and doing so transparently, otherwise zero. +*/ +int ZEXPORT gzdirect (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return 0; + return s->transparent; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + if (do_flush (file, Z_FINISH) != Z_OK) + return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +#ifdef STDC +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +/* =========================================================================== + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/infback.c b/plugins/cdvd/CDVDiso/src/zlib/infback.c new file mode 100644 index 0000000..1e03e1b --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/inffas32.obj b/plugins/cdvd/CDVDiso/src/zlib/inffas32.obj new file mode 100644 index 0000000000000000000000000000000000000000..52e8ccd3998d5c2ae795295fd12b1bc031539983 GIT binary patch literal 14899 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 b=dK`}j9N#BpK%!#vd7gWu}oN;F + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->write; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/plugins/cdvd/CDVDiso/src/zlib/inffast.c b/plugins/cdvd/CDVDiso/src/zlib/inffast.c new file mode 100644 index 0000000..fa31cad --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/inffast.h b/plugins/cdvd/CDVDiso/src/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/cdvd/CDVDiso/src/zlib/inffasx64.obj b/plugins/cdvd/CDVDiso/src/zlib/inffasx64.obj new file mode 100644 index 0000000000000000000000000000000000000000..be18d9da5fc30aee47203f57e615da1d25f0c1bf GIT binary patch literal 5881 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDiso/src/zlib/inffixed.h b/plugins/cdvd/CDVDiso/src/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/cdvd/CDVDiso/src/zlib/inflate.c b/plugins/cdvd/CDVDiso/src/zlib/inflate.c new file mode 100644 index 0000000..33ea902 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/inflate.h b/plugins/cdvd/CDVDiso/src/zlib/inflate.h new file mode 100644 index 0000000..fbbc871 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/cdvd/CDVDiso/src/zlib/inftrees.c b/plugins/cdvd/CDVDiso/src/zlib/inftrees.c new file mode 100644 index 0000000..38ded81 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/inftrees.h b/plugins/cdvd/CDVDiso/src/zlib/inftrees.h new file mode 100644 index 0000000..dc0fd56 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/cdvd/CDVDiso/src/zlib/trees.c b/plugins/cdvd/CDVDiso/src/zlib/trees.c new file mode 100644 index 0000000..7a04802 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/trees.c @@ -0,0 +1,1219 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2005 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to BINARY or TEXT, using a crude approximation: + * set it to Z_TEXT if all symbols are either printable characters (33 to 255) + * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local void set_data_type(s) + deflate_state *s; +{ + int n; + + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/trees.h b/plugins/cdvd/CDVDiso/src/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/cdvd/CDVDiso/src/zlib/uncompr.c b/plugins/cdvd/CDVDiso/src/zlib/uncompr.c new file mode 100644 index 0000000..ad6db0a --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/plugins/cdvd/CDVDiso/src/zlib/zconf.h b/plugins/cdvd/CDVDiso/src/zlib/zconf.h new file mode 100644 index 0000000..e3b0c96 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/zlib.h b/plugins/cdvd/CDVDiso/src/zlib/zlib.h new file mode 100644 index 0000000..62d0e46 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/zutil.c b/plugins/cdvd/CDVDiso/src/zlib/zutil.c new file mode 100644 index 0000000..0f4bd78 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/plugins/cdvd/CDVDiso/src/zlib/zutil.h b/plugins/cdvd/CDVDiso/src/zlib/zutil.h new file mode 100644 index 0000000..0ba6e02 --- /dev/null +++ b/plugins/cdvd/CDVDiso/src/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/cdvd/CDVDisoEFP/ChangeLog.txt b/plugins/cdvd/CDVDisoEFP/ChangeLog.txt new file mode 100644 index 0000000..525e384 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/ChangeLog.txt @@ -0,0 +1,58 @@ +CDVDisoEFP v0.6 Changes: +-------------------- + + v0.6: + * Completely re-wrote screens (efp) + * Used device access sources from CDVDlinuz to get data from DVDs. (efp) + * Added ability to read devices from Windows XP (efp) + Note: only ISO and CDDA seem to be readable from CDs at this time. + If your trying to get another format, use Linux. + DVD5 is readable. Don't have a DVD9 game to test. (I think - efp) + * Separated image file access by OS. (Linux, Windows) (efp) + * Separated Multi-file/Compression/Image-Typing to their own source files. (efp) + * Added a few entries to the Image Typing database, based on Linux CD-ROM sources (efp) + * Added Table Rebuild (for those who lost .table files.) (efp) + * Put in a separate source program to compare two ISOs for data accuracy. (efp) + * Renamed executables and config files (so not to conflict with CDVDiso) (efp) + * Internalized the .INI File code (to allow use in other OS-es besides Windows) (efp) + * Added temporarily a .toc file saving track info (for PS1 and Music CDs) (efp) + * Added a new compression format. (BZip2 Size) (efp) + * Added .glade files at linuzappz's request (efp) + * Upgraded to 0.6.0 beta PS2Edef.h definitions (efp) + + * Data buffer start position re-set for CDs. (shadow caught the problem while testing) + * Supported images grouped in "Browse" button (shadow's suggestion) + * Initial Image reminder added to Windows CDVDOpen() (shadow's suggestion) + * used 64 bit fstat (fstat64) for correct sizes on >2GB files in Linux (efp) + * Adjusted CD types to allow for PS2 CDs (shadow pointed out an example iso) + * Added changing CDs/DVDs while emulation stopped (shadow's suggestion) + Built in an "open tray" delay when switching media. (efp) + * Added ".img" to Image Filter (although .cue/.sub files aren't tapped.) (efp) + * Added ".nrg" to Image Filter (shadow's suggestion) + * In Windows, when newly selected from the PCSX2 configure screen, CDVDinit() + (as well as InitConf()) are not called. Fixed (EFP) + + v0.5: + * Added block dumping code + * Added BZ2/Z2 format ;) + * Added optimaze asm code of zlib with vsnet2003 only. Compression / Uncompression should be faster now (shadow) + * Added Vsnet2005 beta1 project files + amd64 asm optimaze code for zlib (shadow) + + v0.4: + * Rewrote mostly ;) + * .bz is still unsupported + + v0.3: + * Better Iso detection, thx florin :) + * Updated to PS2Edefs v0.4.5 + + v0.2: + * Added support for isos using 2048 blocksize + * Nero images are supported + * Better extension filtering + + v0.1: + * First Release + * Tested with Pcsx2 + + Email: diff --git a/plugins/cdvd/CDVDisoEFP/build.sh b/plugins/cdvd/CDVDisoEFP/build.sh new file mode 100644 index 0000000..c7fd593 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +curdir=`pwd` + +echo ------------------- +echo Building CDVDisoEFP +echo ------------------- + +cd ${curdir}/src/Linux +make $@ + +if [ -s cfgCDVDisoEFP ] && [ -s libCDVDisoEFP.so ] +then +# copy the files +cp cfgCDVDisoEFP libCDVDisoEFP.so ${PCSX2PLUGINS} +fi diff --git a/plugins/cdvd/CDVDisoEFP/license.txt b/plugins/cdvd/CDVDisoEFP/license.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/license.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/cdvd/CDVDisoEFP/readme.txt b/plugins/cdvd/CDVDisoEFP/readme.txt new file mode 100644 index 0000000..fca4b91 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/readme.txt @@ -0,0 +1,55 @@ +CDVDiso v0.6 +------------ + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Linux requirements: +------------------ + You need the GTK library, compiled with GTK v2.6.1 (at least). + +Usage: +----- + For those using Windows, place the file "CDVDisoEFP.dll" in the Plugin + directory of the Emulator to use it. + + For Linux users, place the file "libCDVDisoEFP.so" in the plugin + directory of the Emulator. Also, place the file "cfgCDVDisoEFP" in the "cfg" + directory of the Emulator to use it. + +Configuration: +------------- + You must select the iso you want to use in the Configuration dialog. You + will come back to this dialog should the Emulator want another disc. + +Creating an iso (linux, Windows XP only): +--------------- + To create an iso you can use the button 'Make Image'. The file + will be the one in the Iso Edit, and the Source Device is the CDRom or + DVD drive that will have the disc you want to make an image of. + The compression method is specified by the Compression Method Combo. + + Note: This will fail if the file already exists (if it's compressed + a .z or .bz2 suffix will be added). + +Compressed isos: +--------------- + You can create them using the Convert button. This will create a .Z or .bz + file (the compressed image) and a .z.table or .bz2.table file (this is a + table, for speed reasons.) Both will be created in the same dir as the + selected image. The original image will not be deleted and/or changed. Also, + you can decompress a compressed image by selecting "None" in the + Compression Method Combo. + + Note: you only can decompress the images with this program; not with + compress or bzip2. + +Compression Method: +------------------ + .z speed - fast compression, small blocks, table in memory. + .bz2 speed - average compression, 32k - 40k blocks, table in memory. + .bz2 size - best compression, 60k - 62k blocks, table on file. + + + Email: diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/CD.c b/plugins/cdvd/CDVDisoEFP/src/Linux/CD.c new file mode 100644 index 0000000..ab5796c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/CD.c @@ -0,0 +1,367 @@ +/* CD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // strerror() +#include // open() +#include // ioctl() +#include // open() +#include // lseek(), open() +#include // close(), lseek(), (sleep()) + +#include // CD/DVD based ioctl() and defines. + +#include "../convert.h" +#include "logfile.h" +#include "device.h" +#include "CD.h" + + +// Constants +u8 *playstationcdname = "PLAYSTATION\0"; +u8 *ps1name = "CD-XA001\0"; + +// CD-ROM temp storage structures (see linux/cdrom.h for details) +struct cdrom_tochdr cdheader; +struct cdrom_tocentry cdtrack; +struct cdrom_subchnl subchannel; +u8 cdtempbuffer[2352]; + +int cdmode; // mode of last CDVDreadTrack call (important for CDs) + + +// Internal Functions + +void InitCDSectorInfo() { + cdmode = -1; +} // END InitSectorInfo(); + + +// Function Calls from CDVD.c + +void InitCDInfo() { + InitCDSectorInfo(); +} // END InitDiscType() + +s32 CDreadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDreadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + s32result = 0; + + if(buffer == NULL) return(-1); + + // The CD way of figuring out where to read. + LBAtoMSF(lsn, buffer); + + switch(mode) { + case CDVD_MODE_2048: + case CDVD_MODE_2328: + case CDVD_MODE_2340: + case CDVD_MODE_2352: + errno = 4; // Interrupted system call... (simulated the first time) + while(errno == 4) { + errno = 0; + s32result = ioctl(devicehandle, CDROMREADRAW, buffer); + } // ENDWHILE- Continually being interrupted by the system... + break; + case CDVD_MODE_2368: // Unimplemented... as yet. + default: +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Unknown Mode %i", mode); +#endif /* VERBOSE_WARNINGS */ + return(-1); // Illegal Read Mode? Abort + break; + } // ENDSWITCH- Which read mode should we choose? + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading CD: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitCDSectorInfo(); + return(-1); + } // ENDIF- Trouble getting a track count? + + cdmode = mode; // Save mode for buffer positioning later. + return(0); // Call accomplished +} // END CDreadTrack() + +s32 CDgetBufferOffset() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetBufferOffset()"); +#endif /* VERBOSE_FUNCTION */ + + switch(cdmode) { + case CDVD_MODE_2048: + return(0+24); + case CDVD_MODE_2328: + return(0+24); + case CDVD_MODE_2340: + return(0+12); + case CDVD_MODE_2352: + return(0+0); + case CDVD_MODE_2368: // Unimplemented... as yet. + default: +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Unknown Mode %i", cdmode); +#endif /* VERBOSE_WARNINGS */ + return(0); // Not to worry. for now. + } // ENDSWITCH- where should we put the buffer pointer? +} // END CDgetBuffer() + +// I, personally, don't see the big deal with SubQ +// However, sooner or later I'll incorporate it into the Cache Buffer system +// (backward compatibility, and all that) +s32 CDreadSubQ(u32 lsn, cdvdSubQ *subq) { + int tempmode; + s32 s32result; + + s32result = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDreadSubQ()"); +#endif /* VERBOSE_FUNCTION */ + + tempmode = cdmode; + if(tempmode == -1) tempmode = CDVD_MODE_2352; + CDreadTrack(lsn, tempmode, cdtempbuffer); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error prepping CD SubQ: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(s32result); + } // ENDIF- Trouble? + + subchannel.cdsc_format = CDROM_MSF; + s32result = ioctl(devicehandle, CDROMSUBCHNL, &subchannel); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading CD SubQ: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(s32result); + } // ENDIF- Trouble? + + if(subq != NULL) { + subq->mode = subchannel.cdsc_adr; + subq->ctrl = subchannel.cdsc_ctrl; + subq->trackNum = subchannel.cdsc_trk; + subq->trackIndex = subchannel.cdsc_ind; + subq->trackM = subchannel.cdsc_reladdr.msf.minute; + subq->trackS = subchannel.cdsc_reladdr.msf.second; + subq->trackF = subchannel.cdsc_reladdr.msf.frame; + subq->discM = subchannel.cdsc_absaddr.msf.minute; + subq->discS = subchannel.cdsc_absaddr.msf.second; + subq->discF = subchannel.cdsc_absaddr.msf.frame; + } // ENDIF- Did the caller want all this data? + + return(0); +} // END CDVDreadSubQ() + +s32 CDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetTN()"); +#endif /* VERBOSE_FUNCTION */ + + if(cdvdtn != NULL) { + cdvdtn->strack = cdheader.cdth_trk0; + cdvdtn->etrack = cdheader.cdth_trk1; + } // ENDIF- programmer actually WANTS this info? + + return(0); // Call accomplished +} // END CDVDgetTN() + +s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd) { + u8 j; + u16 k; + char temptime[3]; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetTD()"); +#endif /* VERBOSE_FUNCTION */ + + j = newtrack; + if(j == CDROM_LEADOUT) j = 0; + + if(j == 0) { + k = 27; + } else { + k = j * 10 + 37; + } // ENDIF- Where to start hunting for this number? + + if(cdvdtd != NULL) { + cdvdtd->type = tocbuffer[j*10 + 30]; + + temptime[0] = BCDTOHEX(tocbuffer[k]); + temptime[1] = BCDTOHEX(tocbuffer[k + 1]); + temptime[2] = BCDTOHEX(tocbuffer[k + 2]); + cdvdtd->lsn = MSFtoLBA(temptime); + } // ENDIF- Does the caller REALLY want this data? + + return(0); // Call accomplished +} // END CDVDgetTD() + +s32 CALLBACK CDgetDiskType(s32 ioctldisktype) { + s32 offset; + s32 s32result; + int i; + u8 j; + int tempdisctype; + + offset = 0; + errno = 0; + i = 0; + j = 0; + tempdisctype = CDVD_TYPE_UNKNOWN; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetDiskType()"); +#endif /* VERBOSE_FUNCTION */ + + s32result = CDreadTrack(16, CDVD_MODE_2352, cdtempbuffer); + if((s32result != 0) || (errno != 0)) { + return(-1); + } // ENDIF- Cannot read the CD's ISO9660 volume sector? Abort + disctype = CDVD_TYPE_DETCTCD; + + switch(ioctldisktype) { + case CDS_AUDIO: +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected CDDA Audio disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_CDDA; + tocbuffer[0] = 0x01; + break; + + case CDS_DATA_1: + case CDS_MIXED: +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tocbuffer[0] = 0x41; + + CDreadTrack(16, CDVD_MODE_2048, cdtempbuffer); + offset = CDgetBufferOffset(); + i = 0; + while((*(playstationcdname + i) != 0) && + (*(playstationcdname + i) == cdtempbuffer[offset + 8 + i])) i++; + if(*(playstationcdname + i) == 0) { + i = 0; + while((*(ps1name + i) != 0) && + (*(ps1name + i) == cdtempbuffer[offset + 1024 + i])) i++; + if(*(ps1name + i) == 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PSCD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation 2 CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2CD; + } // ENDIF- Did we find the CD ident? (For Playstation 1 CDs) + } else { + tempdisctype = CDVD_TYPE_UNKNOWN; + } // ENDIF- Did we find the Playstation name? + break; + + default: + return(-1); + } // ENDSWITCH- What has ioctl disc type come up with? + + // Collect TN data + cdheader.cdth_trk0 = 0; + cdheader.cdth_trk1 = 0; + + s32result = ioctl(devicehandle, CDROMREADTOCHDR, &cdheader); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TN: (%i) %i:%s", + s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + cdheader.cdth_trk0 = 1; + cdheader.cdth_trk1 = 1; + } // ENDIF- Failed to read in track count? Assume 1 track. +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Track Number Range: %i-%i", + cdheader.cdth_trk0, cdheader.cdth_trk1); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[2] = 0xA0; + tocbuffer[7] = HEXTOBCD(cdheader.cdth_trk0); + tocbuffer[12] = 0xA1; + tocbuffer[17] = HEXTOBCD(cdheader.cdth_trk1); + + // Collect disc TD data + cdtrack.cdte_track = CDROM_LEADOUT; + cdtrack.cdte_format = CDROM_LBA; + s32result = ioctl(devicehandle, CDROMREADTOCENTRY, &cdtrack); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TD for disc: (%i) %i:%s", + s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Trouble getting a track count? + + LBAtoMSF(cdtrack.cdte_addr.lba, &tocbuffer[27]); +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Total Time: %i:%i", + tocbuffer[27], tocbuffer[28]); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[27] = HEXTOBCD(tocbuffer[27]); + tocbuffer[28] = HEXTOBCD(tocbuffer[28]); + tocbuffer[29] = HEXTOBCD(tocbuffer[29]); + + // Collect track TD data + for(j = cdheader.cdth_trk0; j <= cdheader.cdth_trk1; j++) { + cdtrack.cdte_track = j; // j-1? + cdtrack.cdte_format = CDROM_LBA; + s32result = ioctl(devicehandle, CDROMREADTOCENTRY, &cdtrack); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TD for track %i: (%i) %i:%s", + j, s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + // No more here... + + } else { + LBAtoMSF(cdtrack.cdte_addr.lba, &tocbuffer[j*10 + 37]); +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Track %i: Data Mode %i Disc Start Time:%i:%i.%i\n", + j, + cdtrack.cdte_datamode, + tocbuffer[j*10+37], + tocbuffer[j*10+38], + tocbuffer[j*10+39]); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[j*10 + 30] = cdtrack.cdte_datamode; + tocbuffer[j*10 + 32] = HEXTOBCD(j); + tocbuffer[j*10 + 37] = HEXTOBCD(tocbuffer[j*10 + 37]); + tocbuffer[j*10 + 38] = HEXTOBCD(tocbuffer[j*10 + 38]); + tocbuffer[j*10 + 39] = HEXTOBCD(tocbuffer[j*10 + 39]); + } // ENDIF- Trouble getting a track count? + } // NEXT j- Reading each track's info in turn + + errno = 0; + disctype = tempdisctype; // Trigger the fact we have the info (finally) + return(disctype); +} // END CDVDgetDiskType() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/CD.h b/plugins/cdvd/CDVDisoEFP/src/Linux/CD.h new file mode 100644 index 0000000..2546cba --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/CD.h @@ -0,0 +1,46 @@ +/* CD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __CD_H__ +#define __CD_H__ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "../PS2Edefs.h" + + +// Exported Functions + +extern void InitCDInfo(); +extern s32 CDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 CDgetBufferOffset(); +extern s32 CDreadSubQ(u32 lsn, cdvdSubQ *subq); +extern s32 CDgetTN(cdvdTN *cdvdtn); +extern s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 CDgetDiskType(s32 ioctldisktype); + + +#endif /* __CD_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.c b/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.c new file mode 100644 index 0000000..e5ad373 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.c @@ -0,0 +1,450 @@ +/* CDVDiso.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ +#define CDVDdefs +#include "PS2Edefs.h" + +#include "conf.h" +#include "actualfile.h" +#include "isofile.h" +#include "logfile.h" +#include "convert.h" +#include "version.h" +#include "CDVDiso.h" + + +struct IsoFile *isofile; +char isobuffer[2448]; +char isocdcheck[2448]; +int isomode; +int deviceopencount; // 0 = Closed, 1+ = Open + + +char* CALLBACK PS2EgetLibName() { + return(libname); +} // END PS2EgetLibName() + + +u32 CALLBACK PS2EgetLibType() { + return(PS2E_LT_CDVD); +} // END PS2getLibType() + + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return((version << 16) | (revision << 8) | build); +} + + +s32 CALLBACK CDVDinit() { + int i; + + InitLog(); + if(OpenLog() != 0) return(-1); // Couldn't open Log File? Abort. + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDinit()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + InitConf(); + + isofile = NULL; + isomode = -1; + for(i = 0; i < 2048; i++) isocdcheck[i] = 0; + deviceopencount = 0; + + return(0); +} // END CDVDinit() + + +void CALLBACK CDVDshutdown() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDshutdown()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + isofile = IsoFileClose(isofile); + CloseLog(); +} // END CDVDshutdown() + + +s32 CALLBACK CDVDopen(const char* pTitleFilename) { + int retval; + int i; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDopen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + LoadConf(); + + if( pTitleFilename != NULL ) strcpy(conf.isoname, pTitleFilename); + + if((conf.isoname[0] == 0) || + ((conf.startconfigure != 0) && (deviceopencount == 0)) || + ((conf.restartconfigure != 0) && (deviceopencount > 0))) { + ExecCfg("configure"); + LoadConf(); + } // ENDIF- Haven't initialized the configure program yet? Do so now. + + isofile = IsoFileOpenForRead(conf.isoname); + if(isofile == NULL) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Failed to open ISO file!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + // return(-1); // Taken out for "NULL" device simulation + for(i = 0; i < 2048; i++) isocdcheck[i] = 0; + return(0); + } // ENDIF- Trouble opening file? Abort. + + retval = IsoFileSeek(isofile, 16); + if(retval != 0) return(-1); + retval = IsoFileRead(isofile, isobuffer); + if(retval != 0) return(-1); + + if(deviceopencount > 0) { + i = 0; + while((i < 2048) && (isocdcheck[i] == isobuffer[i])) i++; + if(i == 2048) deviceopencount = 0; // Same CD/DVD? No delay. + } // ENDIF- Is this a restart? Check for disc change. + + for(i = 0; i < 2048; i++) isocdcheck[i] = isobuffer[i]; + + return(0); +} // END CDVDopen() + + +void CALLBACK CDVDclose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDclose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + isofile = IsoFileClose(isofile); + deviceopencount = 50; +} // END CDVDclose() + + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + char temptime[3]; + int i; + int pos; + u32 tracklsn; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDreadSubQ()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) return(-1); + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + return(-1); // DVDs don't have SubQ data + } // ENDIF- Trying to get a SubQ from a DVD? + + // fake it + i = BCDTOHEX(isofile->toc[7]); + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + tracklsn = MSFtoLBA(temptime); + while((i < BCDTOHEX(isofile->toc[17])) && (tracklsn < lsn)) { + i++; + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + tracklsn = MSFtoLBA(temptime); + } // ENDIF- Loop through tracks searching for lsn track + i--; + + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = HEXTOBCD(i); + subq->trackIndex = HEXTOBCD(i); + + LBAtoMSF(lsn - tracklsn, temptime); + subq->trackM = HEXTOBCD(temptime[0]); + subq->trackS = HEXTOBCD(temptime[1]); + subq->trackF = HEXTOBCD(temptime[2]); + + subq->pad = 0; + + // lba_to_msf(lsn + (2*75), &min, &sec, &frm); + LBAtoMSF(lsn, temptime); + subq->discM = HEXTOBCD(temptime[0]); + subq->discS = HEXTOBCD(temptime[1]); + subq->discF = HEXTOBCD(temptime[2]); + + return(0); +} // END CDVDreadSubQ() + + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + if(isofile == NULL) return(-1); + if(deviceopencount > 0) return(-1); + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + Buffer->strack = 1; + Buffer->etrack = 1; + } else { + Buffer->strack = BCDTOHEX(isofile->toc[7]); + Buffer->etrack = BCDTOHEX(isofile->toc[17]); + } // ENDIF- Retrieve track info from a DVD? (or a CD?) + + return(0); +} // END CDVDgetTN() + + +s32 CALLBACK CDVDgetTD(u8 track, cdvdTD *Buffer) { + u8 actualtrack; + int pos; + char temptime[3]; + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) return(-1); + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + actualtrack = track; + if(actualtrack == 0xaa) actualtrack = 0; + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + if (actualtrack <= 1) { + Buffer->type = 0; + Buffer->lsn = isofile->filesectorsize; + } else { + Buffer->type = CDVD_MODE1_TRACK; + Buffer->lsn = 0; + } // ENDIF- Whole disc? (or single track?) + } else { + if (actualtrack == 0) { + Buffer->type = 0; + temptime[0] = BCDTOHEX(isofile->toc[27]); + temptime[1] = BCDTOHEX(isofile->toc[28]); + temptime[2] = BCDTOHEX(isofile->toc[29]); + Buffer->lsn = MSFtoLBA(temptime); + } else { + pos = actualtrack * 10; + pos += 30; + Buffer->type = isofile->toc[pos]; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + Buffer->lsn = MSFtoLBA(temptime); + } // ENDIF- Whole disc? (or single track?) + } // ENDIF- Retrieve track info from a DVD? (or a CD?) + + return(0); +} // END CDVDgetTD() + + +s32 CALLBACK CDVDgetTOC(void* toc) { + int i; + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) return(-1); + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTOC()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + for(i = 0; i < 2048; i++) *(((char *) toc) + i) = isofile->toc[i]; + return(0); +} // END CDVDgetTOC() + + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + int retval; + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + return(-1); + } // ENDIF- Simulate a temporarily open device? + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDreadTrack(%u)", lsn); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + retval = IsoFileSeek(isofile, (off64_t) lsn); + if(retval != 0) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Trouble finding the sector!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(-1); + } // ENDIF- Trouble finding the sector? + + retval = IsoFileRead(isofile, isobuffer); + if(retval != 0) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Trouble reading the sector!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(-1); + } // ENDIF- Trouble finding the sector? + + isomode = mode; + return(0); +} // END CDVDreadTrack() + + +u8* CALLBACK CDVDgetBuffer() { + int offset; + + if(isofile == NULL) return(NULL); + if(deviceopencount > 0) return(NULL); + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetBuffer()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + offset = 0; + switch(isomode) { + case CDVD_MODE_2352: + offset = 0; + break; + case CDVD_MODE_2340: + offset = 12; + break; + case CDVD_MODE_2328: + case CDVD_MODE_2048: + offset = 24; + break; + } // ENDSWITCH isomode- offset to where data it wants is. + + if(offset > isofile->blockoffset) offset = isofile->blockoffset; + + return(isobuffer + offset); +} // END CDVDgetBuffer() + + +s32 CALLBACK CDVDgetDiskType() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(CDVD_TYPE_NODISC); + if(deviceopencount > 0) { + deviceopencount--; + return(CDVD_TYPE_DETCT); + } // ENDIF- Simulate a temporarily open device? + + return(isofile->cdvdtype); +} // END CDVDgetDiskType() + + +s32 CALLBACK CDVDgetTrayStatus() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTrayStatus()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(CDVD_TRAY_OPEN); + if(deviceopencount > 30) { + deviceopencount--; + return(CDVD_TRAY_OPEN); + } // ENDIF- Simulate a temporarily open device? + + return(CDVD_TRAY_CLOSE); +} // END CDVDgetTrayStatus() + + +s32 CALLBACK CDVDctrlTrayOpen() { + int i; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDctrlTrayOpen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + // Close() + isofile = IsoFileClose(isofile); + deviceopencount = 50; + + // and re-Open() + if((conf.isoname[0] == 0) || + ((conf.restartconfigure != 0) && (deviceopencount > 0))) { + ExecCfg("configure"); + LoadConf(); + } // ENDIF- Haven't initialized the configure program yet? Do so now. + + isofile = IsoFileOpenForRead(conf.isoname); + if(isofile == NULL) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Failed to open ISO file!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + } // ENDIF- Trouble opening file? Abort. + + if(deviceopencount > 0) { + i = 0; + while((i < 2048) && (isocdcheck[i] == isobuffer[i])) i++; + if(i == 2048) deviceopencount = 0; // Same CD/DVD? No delay. + } // ENDIF- Is this a restart? Check for disc change. + + for(i = 0; i < 2048; i++) isocdcheck[i] = isobuffer[i]; + + return(0); +} // END CDVDctrlTrayOpen() + + +s32 CALLBACK CDVDctrlTrayClose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDctrlTrayClose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(0); +} // END CDVDctrlTrayClose() + + +void CALLBACK CDVDconfigure() { + ExecCfg("configure"); +} // END CDVDconfigure() + + +s32 CALLBACK CDVDtest() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDtest()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + InitConf(); // Odd... hasn't CDVDinit been called yet? + LoadConf(); + + if(conf.isoname[0] == 0) return(0); // No name chosen yet. Catch on Open() + if(IsIsoFile(conf.isoname) == 0) return(0); // Valid name. Go. + return(-1); // Invalid name - reconfigure first. + // Note really need this? Why not just return(0)... +} // END CDVDtest() + + +void CALLBACK CDVDabout() { + ExecCfg("about"); +} // END CDVDabout() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.h b/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.h new file mode 100644 index 0000000..8cd9301 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/CDVDiso.h @@ -0,0 +1,29 @@ +/* CDVDiso.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CDVDISO_H +#define CDVDISO_H + + +// #define VERBOSE_FUNCTION_INTERFACE + + +#endif /* CDVDISO_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.c b/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.c new file mode 100644 index 0000000..8bf18ae --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.c @@ -0,0 +1,582 @@ +/* DVD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // strerror(), memset(), memcpy() +#include // open() +#include // ioctl() +#include // open() +#include // lseek(), open() +#include // close(), lseek(), (sleep()) + +#include // CD/DVD based ioctl() and defines. + +#include "logfile.h" +#include "device.h" +#include "DVD.h" + + +// Constants +u8 *playstationname = "PLAYSTATION\0"; + +// DVD storage structures (see linux/cdrom.h for details) +dvd_struct dvdphysical; +dvd_struct dvdcopyright[DVD_LAYERS]; +dvd_struct dvdbca; +dvd_struct dvdmanufact[DVD_LAYERS]; + +u32 dvdlastlsn; +u8 dvdtempbuffer[2064]; + + +// Internal Functions + +void InitDVDSectorInfo() { + dvdlastlsn = 0xffffffff; +} // END InitSectorInfo(); + +void HexDump(u8 *strptr, u8 count) { + int i; + u8 ch[2]; + char hexline[81]; + int hexlinepos; + + ch[1] = 0; + + if(count == 0) count = 16; + if((count < 1) || (count > 16)) return; + + hexlinepos = 0; + hexlinepos += sprintf(&hexline[hexlinepos], "CDVD driver: "); + + for(i = 0; i < count; i++) { + hexlinepos += sprintf(&hexline[hexlinepos], "%.2x ", (*(strptr + i)) * 1); + } // NEXT i- printing each new Hex number + + for(i = 0; i < count; i++) { + if((*(strptr + i) < 32) || (*(strptr + i) > 127)) { + hexlinepos += sprintf(&hexline[hexlinepos], "."); + } else { + ch[0] = *(strptr + i); + hexlinepos += sprintf(&hexline[hexlinepos], "%s", ch); + } // ENDIF- Is this an unprintable character? + } // NEXT i- printing each new character + PrintLog(hexline); +} // ENDIF HexDump() + + +//// DVD Structure Functions + +s32 DVDreadPhysical() { + s32 s32result; + u8 i; + + errno = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadPhysical()\n"); +#endif /* VERBOSE_FUNCTION */ + + memset(&dvdphysical, 0, sizeof(dvd_struct)); + dvdphysical.type = DVD_STRUCT_PHYSICAL; + + i = DVD_LAYERS; + while(i > 0) { + i--; + dvdphysical.physical.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdphysical); + } // ENDWHILE- reading in all physical layers... + + if((s32result == -1) || (errno != 0)) { + dvdphysical.type = 0xFF; +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Physical structure: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with reading Layer 0 of the physical data? Abort + + i = 3; + while((i > 0) && (dvdphysical.physical.layer[i].end_sector == 0)) i--; + dvdphysical.physical.layer_num = i; + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Physical Characteristics"); + PrintLog("CDVD driver: Number of Layers: %i", + (s32) dvdphysical.physical.layer_num + 1); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + PrintLog("CDVD driver: Layer Number %i", i); + switch(dvdphysical.physical.layer[i].book_type) { + case 0: + PrintLog("CDVD driver: Book Type: DVD-ROM"); + break; + case 1: + PrintLog("CDVD driver: Book Type: DVD-RAM"); + break; + case 2: + PrintLog("CDVD driver: Book Type: DVD-R"); + break; + case 3: + PrintLog("CDVD driver: Book Type: DVD-RW"); + break; + case 9: + PrintLog("CDVD driver: Book Type: DVD+RW"); + break; + default: + PrintLog("CDVD driver: Book Type: Unknown (%i)", + dvdphysical.physical.layer[i].book_type); + break; + } // ENDSWITCH- Displaying the Book Type + PrintLog("CDVD driver: Book Version %i", + dvdphysical.physical.layer[i].book_version); + switch(dvdphysical.physical.layer[i].min_rate) { + case 0: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-ROM"); + break; + case 1: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-RAM"); + break; + case 2: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-R"); + break; + case 3: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-RW"); + break; + case 9: + PrintLog("CDVD driver: Use Minimum Rate for: DVD+RW"); + break; + default: + PrintLog("CDVD driver: Use Minimum Rate for: Unknown (%i)", + dvdphysical.physical.layer[i].min_rate); + break; + } // ENDSWITCH- Displaying the Minimum (Spin?) Rate + switch(dvdphysical.physical.layer[i].disc_size) { + case 0: + PrintLog("CDVD driver: Physical Disk Size: 120mm"); + break; + case 1: + PrintLog("CDVD driver: Physical Disk Size: 80mm"); + break; + default: + PrintLog("CDVD driver: Physical Disk Size: Unknown (%i)", + dvdphysical.physical.layer[i].disc_size); + break; + } // ENDSWITCH- What's the Disk Size? + switch(dvdphysical.physical.layer[i].layer_type) { + case 1: + PrintLog("CDVD driver: Layer Type: Read-Only"); + break; + case 2: + PrintLog("CDVD driver: Layer Type: Recordable"); + break; + case 4: + PrintLog("CDVD driver: Layer Type: Rewritable"); + break; + default: + PrintLog("CDVD driver: Layer Type: Unknown (%i)", + dvdphysical.physical.layer[i].layer_type); + break; + } // ENDSWITCH- Displaying the Layer Type + switch(dvdphysical.physical.layer[i].track_path) { + case 0: + PrintLog("CDVD driver: Track Path: PTP"); + break; + case 1: + PrintLog("CDVD driver: Track Path: OTP"); + break; + default: + PrintLog("CDVD driver: Track Path: Unknown (%i)", + dvdphysical.physical.layer[i].track_path); + break; + } // ENDSWITCH- What's Track Path Layout? + // PrintLog("CDVD driver: Disc Size %i Layer Type %i Track Path %i Nlayers %i", + // dvdphysical.physical.layer[i].nlayers); + switch(dvdphysical.physical.layer[i].track_density) { + case 0: + PrintLog("CDVD driver: Track Density: .74 m/track"); + break; + case 1: + PrintLog("CDVD driver: Track Density: .8 m/track"); + break; + case 2: + PrintLog("CDVD driver: Track Density: .615 m/track"); + break; + default: + PrintLog("CDVD driver: Track Density: Unknown (%i)", + dvdphysical.physical.layer[i].track_density); + break; + } // ENDSWITCH- Displaying the Track Density + switch(dvdphysical.physical.layer[i].linear_density) { + case 0: + PrintLog("CDVD driver: Linear Density: .267 m/bit"); + break; + case 1: + PrintLog("CDVD driver: Linear Density: .293 m/bit"); + break; + case 2: + PrintLog("CDVD driver: Linear Density: .409 to .435 m/bit"); + break; + case 4: + PrintLog("CDVD driver: Linear Density: .280 to .291 m/bit"); + break; + case 8: + PrintLog("CDVD driver: Linear Density: .353 m/bit"); + break; + default: + PrintLog("CDVD driver: Linear Density: Unknown (%i)", + dvdphysical.physical.layer[i].linear_density); + break; + } // ENDSWITCH- Displaying the Linear Density + if(dvdphysical.physical.layer[i].start_sector == 0x30000) { + PrintLog("CDVD driver: Starting Sector: %lu (DVD-ROM, DVD-R, DVD-RW)", + dvdphysical.physical.layer[i].start_sector); + } else if(dvdphysical.physical.layer[i].start_sector == 0x31000) { + PrintLog("CDVD driver: Starting Sector: %lu (DVD-RAM, DVD+RW)", + dvdphysical.physical.layer[i].start_sector); + } else { + PrintLog("CDVD driver: Starting Sector: %lu", + dvdphysical.physical.layer[i].start_sector); + } // ENDLONGIF- What does the starting sector tell us? + PrintLog("CDVD driver: End of Layer 0: %lu", + dvdphysical.physical.layer[i].end_sector_l0); + PrintLog("CDVD driver: Ending Sector: %lu", + dvdphysical.physical.layer[i].end_sector); + if(dvdphysical.physical.layer[i].bca != 0) + PrintLog("CDVD driver: BCA data present"); + } // NEXT i- Work our way through each layer... +#endif /* VERBOSE_DISC_INFO */ + + return(0); // Success. Physical data stored for perusal. +} // END DVDreadPhysical() + +s32 DVDreadCopyright() { + s32 s32result; + u8 i; + int successflag; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadCopyright()"); +#endif /* VERBOSE_FUNCTION */ + + successflag = 0; + + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + memset(&dvdcopyright[i], 0, sizeof(dvd_struct)); + dvdcopyright[i].type = DVD_STRUCT_COPYRIGHT; + dvdcopyright[i].copyright.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdcopyright[i]); + if(s32result == 0) { + successflag = 1; + } else { + dvdcopyright[i].type = 0xFF; + } // ENDIF- + } // NEXT i- Getting copyright data for every known layer + + if(successflag == 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Copyright info: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Copyright Information\n"); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + if(dvdcopyright[i].type != 0xFF) { + PrintLog("CDVD driver: Layer Number %i CPST %i RMI %i", + dvdcopyright[i].copyright.layer_num, + dvdcopyright[i].copyright.cpst, + dvdcopyright[i].copyright.rmi); + } // ENDIF- Were we successful reading this one? + } // NEXT i- Printing out all copyright info found... +#endif /* VERBOSE_DISC_INFO */ + + errno = 0; + return(0); // Success. Copyright data stored for perusal. +} // END DVDreadCopyright() + +s32 DVDreadBCA() { + s32 s32result; + int i; + + i = 0; + errno = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadBCA()"); +#endif /* VERBOSE_FUNCTION */ + + memset(&dvdbca, 0, sizeof(dvd_struct)); + dvdbca.type = DVD_STRUCT_BCA; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdbca); + if((s32result == -1) || (errno != 0)) { + dvdbca.type = 0xFF; +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting BCA: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: BCA Length %i Value:", + dvdbca.bca.len); + for(i = 0; i < 188-15; i += 16) { + HexDump(dvdbca.bca.value+i, 16); + } // NEXT i- dumping whole key data +#endif /* VERBOSE_DISC_INFO */ + + return(0); // Success. BCA data stored for perusal. +} // END DVDreadBCA() + +s32 DVDreadManufact() { + s32 s32result; + u8 i; + int successflag; + int j; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadManufact()"); +#endif /* VERBOSE_FUNCTION */ + + j = 0; + successflag = 0; + + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + memset(&dvdmanufact[i], 0, sizeof(dvd_struct)); + dvdmanufact[i].type = DVD_STRUCT_MANUFACT; + dvdmanufact[i].manufact.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdmanufact[i]); + if((s32result != 0) || (errno != 0)) { + dvdmanufact[i].type = 0xFF; + } else { + successflag = 1; + } // ENDIF- Did we fail to read in some manufacturer data? + } // NEXT i- Collecting manufacturer data from all layers + + if(successflag == 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Manufact: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Manufact Data"); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + if(dvdmanufact[i].type != 0xFF) { + PrintLog("CDVD driver: Layer %i Length %i Value:", + dvdmanufact[i].manufact.layer_num, + dvdmanufact[i].manufact.len); + for(j = 0; j < 128-15; j += 16) { + HexDump(dvdmanufact[i].manufact.value+j, 16); + } // NEXT j- dumping whole key data + } // ENDIF- Do we have data at this layer? + } // NEXT i- Running through all the layers +#endif /* VERBOSE_DISC_INFO */ + + errno = 0; + return(0); // Success. Manufacturer's data stored for perusal. +} // END DVDreadManufact() + + +// External Functions + +// Function Calls from CDVD.c + +void InitDVDInfo() { + int j; + + dvdphysical.type = 0xFF; // Using for empty=0xff, full!=0xff test + dvdbca.type = 0xFF; + for(j = 0; j < DVD_LAYERS; j++) { + dvdcopyright[j].type = 0xFF; + dvdmanufact[j].type = 0xFF; + } // NEXT j- Zeroing each layer of data + InitDVDSectorInfo(); +} // END InitDiscType() + +s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + off64_t offsettarget; + off64_t offsetresult; + + errno = 0; + s32result = 0; + offsetresult = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + if(lsn != dvdlastlsn + 1) { + offsettarget = lsn; + offsettarget *= 2048; + errno = 4; + while(errno == 4) { + errno = 0; + offsetresult = lseek64(devicehandle, offsettarget, SEEK_SET); + } // ENDWHILE- waiting for the system interruptions to cease. + if((offsetresult < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error on seek: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitDVDSectorInfo(); + return(-1); + } // ENDIF- trouble with seek? Reset pointer and abort + } // ENDIF- Do we have to seek a new position to read? + + errno = 4; + while(errno == 4) { + errno = 0; + s32result = read(devicehandle, buffer, 2048); + } // ENDWHILE- waiting for the system interruptions to cease. + if((s32result != 2048) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: DVD Short Block, Size: %i", s32result); + PrintLog("CDVD driver: Error: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitDVDSectorInfo(); + return(-1); + } // ENDIF- Trouble reading the data? Reset pointer and abort + + dvdlastlsn = lsn; + return(0); // Call accomplished +} // END DVDreadTrack() + +s32 DVDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION */ + + // Going to treat this as one large track for now. + if(cdvdtn != NULL) { + cdvdtn->strack = 1; + cdvdtn->etrack = 1; + } // ENDIF- programmer actually WANTS this info? + + return(0); // Call accomplished +} // END DVDgetTN() + +s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION */ + + if((newtrack >= 2) && (newtrack != CDROM_LEADOUT)) return(-1); + + if(cdvdtd != NULL) { + cdvdtd->lsn = dvdphysical.physical.layer[0].end_sector + - dvdphysical.physical.layer[0].start_sector + + 1; + cdvdtd->type = CDVD_MODE_2048; + } // ENDIF- Does the caller REALLY want this data? + + return(0); // Call accomplished +} // END DVDgetTD() + +s32 DVDgetDiskType(s32 ioctldisktype) { + s32 s32result; + int i; + s32 tempdisctype; + + errno = 0; + s32result = 0; + i = 0; + tempdisctype = CDVD_TYPE_UNKNOWN; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION */ + + if((ioctldisktype != CDS_DATA_1) && (ioctldisktype != CDS_MIXED)) { + return(-1); + } // ENDIF- Not a data disc we know of? Abort then + + s32result = DVDreadPhysical(); + if((s32result != 0) || (errno != 0)) { + return(-1); + } // ENDIF- Error reading the DVD physical structure? Not a DVD after all. + + if(dvdphysical.physical.layer[0].end_sector >= (2048*1024)) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: DVD Found (Dual-Sided)"); +#endif /* VERBOSE_DISC_TYPE */ + disctype = CDVD_TYPE_DETCTDVDD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: DVD Found (Single-Sided)"); +#endif /* VERBOSE_DISC_TYPE */ + disctype = CDVD_TYPE_DETCTDVDS; + } // ENDIF- Definitely a DVD. Size Test? + + // Read in the rest of the structures... + DVDreadCopyright(); + DVDreadBCA(); + DVDreadManufact(); + + // Test for "Playstation" header + s32result = DVDreadTrack(16, CDVD_MODE_2048, dvdtempbuffer); + if(s32result != 0) { + return(-1); + } else { + i = 0; + while((*(playstationname + i) != 0) && + (*(playstationname + i) == dvdtempbuffer[8 + i])) { + i++; + } // ENDWHILE- Checking each letter of PLAYSTATION name for a match + if(*(playstationname + i) == 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation 2 DVD"); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2DVD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Guessing it's a Video DVD"); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_DVDV; + } // ENDIF- Did we find the Playstation name? + } // ENDIF- Error reading disc volume information? Invalidate Disc + + if(dvdphysical.physical.layer[0].end_sector >= (2048*1024)) { + tocbuffer[0] = 0x24; // Dual-Sided DVD + tocbuffer[4] = 0x41; + tocbuffer[5] = 0x95; + } else { + tocbuffer[0] = 0x04; // Single-Sided DVD + tocbuffer[4] = 0x86; + tocbuffer[5] = 0x72; + } // ENDIF- Are there too many sectors for a single-sided disc? + + tocbuffer[1] = 0x02; + tocbuffer[2] = 0xF2; + tocbuffer[3] = 0x00; + + tocbuffer[16] = 0x00; + tocbuffer[17] = 0x03; + tocbuffer[18] = 0x00; + tocbuffer[19] = 0x00; + + disctype = tempdisctype; // Triggers the fact the other info is available + return(disctype); +} // END DVDgetDiskType() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.h b/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.h new file mode 100644 index 0000000..7dbc1c7 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/DVD.h @@ -0,0 +1,45 @@ +/* DVD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DVD_H__ +#define __DVD_H__ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +// Exported Functions + +extern void HexDump(u8 *strptr, u8 count); +extern void InitDVDInfo(); +extern s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DVDgetTN(cdvdTN *cdvdtn); +extern s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 DVDgetDiskType(s32 ioctldisktype); + + +#endif /* __DVD_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/Makefile b/plugins/cdvd/CDVDisoEFP/src/Linux/Makefile new file mode 100644 index 0000000..1fee325 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/Makefile @@ -0,0 +1,91 @@ + +PLUGIN = libCDVDisoEFP.so +PLUGINOBJS = CDVDiso.o +PLUGINHEADERS = CDVDiso.h +PLUGINFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -D_LARGEFILE64_SOURCE \ + -I.. -I. -I./Linux +PLUGINLIBS = -lz -lbz2 + +CFG = cfgCDVDisoEFP +CFGOBJS = interface.o aboutbox.o mainbox.o selectionbox.o \ + devicebox.o conversionbox.o progressbox.o messagebox.o \ + tablerebuild.o device.o CD.o DVD.o +CFGHEADERS = interface.h aboutbox.h mainbox.h selectionbox.h \ + devicebox.h conversionbox.h progressbox.h messagebox.h \ + tablerebuild.h device.h CD.h DVD.h +CFGFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -D_LARGEFILE64_SOURCE \ + -I.. -I. -I./Linux +CFGLIBS = -lz -lbz2 + +COMP = compCDVDisoEFP +COMPOBJS = comparisonbox.o progressbox.o messagebox.o \ + comparisondummy.o +COMPHEADERS = progressbox.h messagebox.h + +SHAREDOBJS = ../version.o actualfile.o ../isofile.o conf.o logfile.o \ + ../imagetype.o ../multifile.o ../isocompress.o ../convert.o \ + ../gzipv1.o ../blockv2.o ../gzipv2.o ../ecma119.o \ + ../bzip2v3.o ../bzip2v2.o \ + ../toc.o ../ini.o +SHAREDHEADERS = ../version.h actualfile.h ../isofile.h conf.h logfile.h \ + ../imagetype.h ../multifile.h ../isocompress.h ../convert.h \ + ../gzipv1.h ../blockv2.h ../gzipv2.h ../bzip2v2.h ../ecma119.h \ + ../toc.h ../ini.h ../bzip2v3.h + + +CC = gcc + +GTKFLAGS = $(shell pkg-config --cflags gtk+-2.0) + +//GTKFLAGS += -DG_DISABLE_DEPRECATED \ +// -DGDK_DISABLE_DEPRECATED \ +// -DGDK_PIXBUF_DISABLE_DEPRECATED \ +// -DGTK_DISABLE_DEPRECATED + +GTKLIBS = $(shell pkg-config --libs gtk+-2.0) +# Do we need to remove "-rdynamic" as well? Or is that just the main program? + + +all: plugin cfg +install: all + +release: plugin cfg + cp $(PLUGIN) ../.. + cp $(CFG) ../.. + +plugin: $(PLUGINOBJS) $(SHAREDOBJS) + rm -f $(PLUGIN) + $(CC) -shared -Wl,-soname,$(PLUGIN) $(PLUGINFLAGS) $(PLUGINLIBS) \ + $(PLUGINOBJS) $(SHAREDOBJS) -o $(PLUGIN) + strip --strip-unneeded --strip-debug $(PLUGIN) + +cfg: $(CFGOBJS) $(SHAREDOBJS) + rm -f $(CFG) + $(CC) $(CFGFLAGS) $(GTKFLAGS) $(CFGLIBS) $(GTKLIBS) \ + $(CFGOBJS) $(SHAREDOBJS) -o $(CFG) + strip $(CFG) + +compare: $(COMPOBJS) $(SHAREDOBJS) + rm -f $(COMP) + $(CC) $(CFGFLAGS) $(GTKFLAGS) $(CFGLIBS) $(GTKLIBS) \ + $(COMPOBJS) $(SHAREDOBJS) -o $(COMP) + strip $(COMP) + +$(PLUGINOBJS) $(SHAREDOBJS): %.o: %.c + $(CC) $(PLUGINFLAGS) -c $< -o $@ + +$(CFGOBJS) ../comparisonbox.o ../comparisondummy.o: %.o: %.c + $(CC) $(CFGFLAGS) $(GTKFLAGS) -c $< -o $@ + +.PHONY : clean allclean +clean: + -rm -f $(PLUGINOBJS) $(PLUGIN) $(CFGOBJS) $(CFG) \ + $(COMP) $(COMPOBJS) $(SHAREDOBJS) + -rm -f *~ temp.txt ../*~ ../temp.txt ../../*~ + +allclean: + -rm -f $(PLUGINOBJS) $(PLUGIN) $(CFGOBJS) $(CFG) \ + $(COMP) $(COMPOBJS) $(SHAREDOBJS) + -rm -f *~ temp.txt ../*~ ../temp.txt ../../*~ + -rm -f ../../$(PLUGIN) ../../$(CFG) + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.c new file mode 100644 index 0000000..80b73f5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.c @@ -0,0 +1,106 @@ +/* aboutbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() + +#include // gtk_button_new_with_label() +#include // gtk_container_add() +#include // gtk_hbutton_box_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "version.h" +#include "aboutbox.h" + + +struct AboutBoxData aboutbox; + + +gint AboutBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + if(aboutbox.window != NULL) { + gtk_widget_destroy(aboutbox.window); + aboutbox.window = NULL; + } // ENDIF- Do we have an About Box still? + + gtk_main_quit(); + return(TRUE); +} // END AboutBoxCancelEvent() + + +void AboutBoxDisplay() { + GtkWidget *item; + GtkWidget *container; + GtkWidget *vbox1; + char templine[256]; + + aboutbox.window = NULL; + aboutbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(aboutbox.window), 5); + gtk_window_set_title(GTK_WINDOW(aboutbox.window), "About CDVDisoEFP"); + gtk_window_set_position(GTK_WINDOW(aboutbox.window), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(aboutbox.window), TRUE); + gtk_window_set_resizable(GTK_WINDOW(aboutbox.window), FALSE); + + g_signal_connect(G_OBJECT(aboutbox.window), "delete_event", + G_CALLBACK(AboutBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(aboutbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + sprintf(templine, "%s v%i.%i", libname, revision, build); + item = gtk_label_new(templine); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + item = gtk_label_new("Current Author: efp"); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + item = gtk_label_new("Original code by: linuzappz & shadow"); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + container = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), container, TRUE, TRUE, 0); + gtk_widget_show(container); + + item = gtk_button_new_with_label("Ok"); + gtk_container_add(GTK_CONTAINER(container), item); + GTK_WIDGET_SET_FLAGS(item, GTK_CAN_DEFAULT); + gtk_widget_show(item); + + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(AboutBoxCancelEvent), NULL); + item = NULL; + container = NULL; + vbox1 = NULL; + + gtk_widget_show(aboutbox.window); + gtk_main(); +} // END AboutDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.glade new file mode 100644 index 0000000..cb099be --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.glade @@ -0,0 +1,118 @@ + + + + + + + + True + About CDVDiso + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + True + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + CDVDiso ISO Driver v0.6 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Author: linuzappz <linuzappz@hotmail.com> + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Modified by: shadow, efp + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.h new file mode 100644 index 0000000..bf1df52 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/aboutbox.h @@ -0,0 +1,39 @@ +/* aboutbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef ABOUTBOX_H +#define ABOUTBOX_H + + +#include + + +struct AboutBoxData { + GtkWidget *window; // GtkWindow - About Box +}; + +extern struct AboutBoxData aboutbox; + + +extern void AboutBoxDisplay(); + + +#endif /* ABOUTBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.c b/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.c new file mode 100644 index 0000000..64eaa69 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.c @@ -0,0 +1,222 @@ +/* actualfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // errno +#include // open() +#include // rename() +#include // strerror() +#include // stat64(), open(), fstat() +#include // stat64(), open(), fstat(), lseek64() +#include // stat64(), fstat(), lseek64(), read(), close(), write() +// unlink() + +#include "logfile.h" +#include "actualfile.h" + + +int IsActualFile(const char *filename) { + int retval; + struct stat64 filestat; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: IsActualFile(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = stat64(filename, &filestat); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error retrieving stats on %s", filename); + PrintLog("CDVDiso file: %i:%s\n", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); // Name doesn't exist. + } // ENDIF- Trouble getting stat on a file? + + if(S_ISREG(filestat.st_mode) == 0) return(-2); // Not a regular file. + return(0); // Yep, that's a file. +} // END IsActualFile() + + +void ActualFileDelete(const char *filename) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileDelete(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + unlink(filename); +} // END ActualFileDelete() + + +void ActualFileRename(const char *origname, const char *newname) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileRename(%s->%s)", origname, newname); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + rename(origname, newname); + return; +} // END ActualFileRename() + + +ACTUALHANDLE ActualFileOpenForRead(const char *filename) { + int newhandle; + + if(filename == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForRead(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + newhandle = open(filename, O_RDONLY | O_LARGEFILE); + if((newhandle < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s\n", filename); + PrintLog("CDVDiso file: (%i) %i:%s\n", newhandle, errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForRead() + + +off64_t ActualFileSize(ACTUALHANDLE handle) { + int retval; + struct stat64 filestat; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSize()\n"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = fstat64(handle, &filestat); + if((retval < 0) || (errno != 0)) return(-1); // Name doesn't exist. + return(filestat.st_size); +} // END ActualFileSize() + + +int ActualFileSeek(ACTUALHANDLE handle, off64_t position) { + off64_t moved; + + if(handle < 0) return(-1); + if(position < 0) return(-1); // Maybe... position = 0? + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSeek(%lli)", position); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + moved = lseek64(handle, position, SEEK_SET); + if(errno != 0) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error on seek (%lli)", position); + PrintLog("CDVDiso file: %i:%s\n", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(0); +} // END ActualFileSeek() + + +int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + + if(handle == ACTUALHANDLENULL) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileRead(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = read(handle, buffer, bytes); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error reading from file!"); + PrintLog("CDVDiso file: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + // return(-1); + } // ENDIF- Error? Abort + + return(retval); // Send back how many bytes read +} // END ActualFileRead() + + +void ActualFileClose(ACTUALHANDLE handle) { + if(handle < 0) return; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileClose()"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + close(handle); + return; +} // END ActualFileClose() + + +ACTUALHANDLE ActualFileOpenForWrite(const char *filename) { + int newhandle; + + if(filename == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForWrite(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + newhandle = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0644); + if((newhandle < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s", filename); + PrintLog("CDVDiso file: (%i) %i:%s", newhandle, errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForWrite() + + +int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + + if(handle < 0) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileWrite(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = write(handle, buffer, bytes); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error writing to file!"); + PrintLog("CDVDiso file: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + // return(-1); + } // ENDIF- Error? Abort + + return(retval); // Send back how many bytes written +} // END ActualFileWrite() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.h b/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.h new file mode 100644 index 0000000..a678b63 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/actualfile.h @@ -0,0 +1,50 @@ +/* actualfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef ACTUALFILE_H +#define ACTUALFILE_H + + +#include // off64_t + + +#define ACTUALHANDLE int +#define ACTUALHANDLENULL -1 + +// #define VERBOSE_FUNCTION_ACTUALFILE +// #define VERBOSE_WARNING_ACTUALFILE + + +extern int IsActualFile(const char *filename); +extern void ActualFileDelete(const char *filename); +extern void ActualFileRename(const char *origname, const char *newname); + +extern ACTUALHANDLE ActualFileOpenForRead(const char *filename); +extern off64_t ActualFileSize(ACTUALHANDLE handle); +extern int ActualFileSeek(ACTUALHANDLE handle, off64_t position); +extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer); +extern void ActualFileClose(ACTUALHANDLE handle); + +extern ACTUALHANDLE ActualFileOpenForWrite(const char *filename); +extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer); + + +#endif /* ACTUALFILE_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.c new file mode 100644 index 0000000..3eb216b --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.c @@ -0,0 +1,415 @@ +/* comparisonbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcpy() + +#include // gtk_button_new_with_label() +#include // gtk_container_add() +#include // gtk_entry_new() +#include // gtk_file_selection_set_filename() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_hseparator_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_vbox_new() +#include +#include // gtk_window_new() + +#include "logfile.h" +#include "conf.h" +#include "isofile.h" +#include "isocompress.h" // compressdesc[] +#include "multifile.h" // multinames[] +#include "tablerebuild.h" // IsoTableRebuild() +#include "progressbox.h" +#include "messagebox.h" + + +struct MainBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *file1; // GtkEntry + GtkWidget *desc1; // GtkLabel + GtkWidget *file2; // GtkEntry + GtkWidget *desc2; // GtkLabel + GtkWidget *okbutton; // GtkButton + // Leaving the Cancel button unblocked... for emergency shutdown + + int stop; // Variable signal to stop long processes +}; + + +struct MainBoxData mainbox; + + +void MainBoxDestroy() { + if(mainbox.window != NULL) { + gtk_widget_destroy(mainbox.window); + mainbox.window = NULL; + mainbox.file1 = NULL; + mainbox.desc1 = NULL; + mainbox.file2 = NULL; + mainbox.desc2 = NULL; + mainbox.okbutton = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MainBoxDestroy() + + +void MainBoxUnfocus() { + gtk_widget_set_sensitive(mainbox.file1, FALSE); + gtk_widget_set_sensitive(mainbox.file2, FALSE); + gtk_widget_set_sensitive(mainbox.okbutton, FALSE); + gtk_window_iconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxUnfocus() + + +gint MainBoxFile1Event(GtkWidget *widget, GdkEvent event, gpointer data) { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + returnval = IsIsoFile(gtk_entry_get_text(GTK_ENTRY(mainbox.file1))); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(mainbox.desc1), "File Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + gtk_label_set_text(GTK_LABEL(mainbox.desc1), "File Type: Not a file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -3) { + gtk_label_set_text(GTK_LABEL(mainbox.desc1), "File Type: Not a valid image file"); + return(TRUE); + } // ENDIF- Not an Image file? + + if(returnval == -4) { + gtk_label_set_text(GTK_LABEL(mainbox.desc1), "File Type: Missing Table File (will rebuild)"); + return(TRUE); + } // ENDIF- Missing Compression seek table? + + tempfile = IsoFileOpenForRead(gtk_entry_get_text(GTK_ENTRY(mainbox.file1))); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + gtk_label_set_text(GTK_LABEL(mainbox.desc1), templine); + tempfile = IsoFileClose(tempfile); + return(TRUE); +} // END MainBoxFileEvent() + + +gint MainBoxFile2Event(GtkWidget *widget, GdkEvent event, gpointer data) { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + returnval = IsIsoFile(gtk_entry_get_text(GTK_ENTRY(mainbox.file2))); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(mainbox.desc2), "File Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + gtk_label_set_text(GTK_LABEL(mainbox.desc2), "File Type: Not a file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -3) { + gtk_label_set_text(GTK_LABEL(mainbox.desc2), "File Type: Not a valid image file"); + return(TRUE); + } // ENDIF- Not an Image file? + + if(returnval == -4) { + gtk_label_set_text(GTK_LABEL(mainbox.desc2), "File Type: Missing Table File (will rebuild)"); + return(TRUE); + } // ENDIF- Missing Compression seek table? + + tempfile = IsoFileOpenForRead(gtk_entry_get_text(GTK_ENTRY(mainbox.file2))); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + gtk_label_set_text(GTK_LABEL(mainbox.desc2), templine); + tempfile = IsoFileClose(tempfile); + return(TRUE); +} // END MainBoxFileEvent() + + +void MainBoxRefocus() { + GdkEvent event; + + MainBoxFile1Event(NULL, event, NULL); + MainBoxFile2Event(NULL, event, NULL); + + gtk_widget_set_sensitive(mainbox.file1, TRUE); + gtk_widget_set_sensitive(mainbox.file2, TRUE); + gtk_widget_set_sensitive(mainbox.okbutton, TRUE); + gtk_window_set_focus(GTK_WINDOW(mainbox.window), mainbox.file1); + gtk_window_deiconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxRefocus() + + +gint MainBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + mainbox.stop = 1; // Halt all long processess... + + MessageBoxDestroy(); + ProgressBoxDestroy(); + MainBoxDestroy(); + + gtk_main_quit(); + return(TRUE); +} // END MainBoxCancelEvent() + + +gint MainBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + const char *tempisoname1; + const char *tempisoname2; + struct IsoFile *tempiso1; + struct IsoFile *tempiso2; + int stop; + off64_t endsector; + off64_t sector; + int retval; + char tempblock1[2448]; + char tempblock2[2448]; + int i; + + MainBoxUnfocus(); + + tempisoname1 = gtk_entry_get_text(GTK_ENTRY(mainbox.file1)); + tempisoname2 = gtk_entry_get_text(GTK_ENTRY(mainbox.file2)); + tempiso1 = NULL; + tempiso2 = NULL; + + tempiso1 = IsoFileOpenForRead(tempisoname1); + if(tempiso1 == NULL) { + MainBoxRefocus(); + MessageBoxShow("First file is not a Valid Image File.", 0); + tempisoname1 = NULL; + tempisoname2 = NULL; + return(TRUE); + } // ENDIF- Not an ISO file? Message and Stop here. + + tempiso2 = IsoFileOpenForRead(tempisoname2); + if(tempiso2 == NULL) { + MainBoxRefocus(); + MessageBoxShow("Second file is not a Valid Image File.", 0); + tempiso1 = IsoFileClose(tempiso1); + tempisoname1 = NULL; + tempisoname2 = NULL; + return(TRUE); + } // ENDIF- Not an ISO file? Message and Stop here. + + if(tempiso1->blocksize != tempiso2->blocksize) { + MainBoxRefocus(); + MessageBoxShow("Block sizes in Image files do not match.", 0); + tempiso1 = IsoFileClose(tempiso1); + tempiso2 = IsoFileClose(tempiso2); + tempisoname1 = NULL; + tempisoname2 = NULL; + return(TRUE); + } // ENDIF- Not an ISO file? Message and Stop here. + + if(tempiso1->multi == 1) { + i = 0; + while((i < 10) && + (IsoFileSeek(tempiso1, tempiso1->multisectorend[i] + 1) == 0)) i++; + endsector = tempiso1->multisectorend[tempiso1->multiend]; + } else { + endsector = tempiso1->filesectorsize; + } // ENDIF- Get ending sector from multifile? (Or single file?) + IsoFileSeek(tempiso1, 0); + + if(tempiso2->multi == 1) { + i = 0; + while((i < 10) && + (IsoFileSeek(tempiso2, tempiso2->multisectorend[i] + 1) == 0)) i++; + sector = tempiso2->multisectorend[tempiso2->multiend]; + } else { + sector = tempiso2->filesectorsize; + } // ENDIF- Get ending sector from multifile? (Or single file?) + IsoFileSeek(tempiso2, 0); + if(sector != endsector) { + MainBoxRefocus(); + MessageBoxShow("Number of blocks in Image files do not match.", 0); + tempiso1 = IsoFileClose(tempiso1); + tempiso2 = IsoFileClose(tempiso2); + tempisoname1 = NULL; + tempisoname2 = NULL; + return(TRUE); + } // ENDIF- Number of blocks don't match? Say so. + + sprintf(tempblock1, "%s == %s ?", tempisoname1, tempisoname2); + ProgressBoxStart(tempblock1, endsector); + + stop = 0; + mainbox.stop = 0; + progressbox.stop = 0; + while((stop == 0) && (tempiso1->sectorpos < endsector)) { + retval = IsoFileRead(tempiso1, tempblock1); + if(retval < 0) { + MainBoxRefocus(); + MessageBoxShow("Trouble reading first file.", 0); + stop = 1; + } else { + retval = IsoFileRead(tempiso2, tempblock2); + if(retval < 0) { + MainBoxRefocus(); + MessageBoxShow("Trouble reading second file.", 0); + stop = 1; + } else { + i = 0; + while((i < tempiso1->blocksize) && (tempblock1[i] == tempblock2[i])) i++; + if(i < tempiso1->blocksize) { + MainBoxRefocus(); + MessageBoxShow("Trouble reading second file.", 0); + stop = 1; + } // ENDIF- Sectors don't match? Say so. + } // ENDIF- Trouble reading second file? + } // ENDIF- Trouble reading first file? + + ProgressBoxTick(tempiso1->sectorpos); + while(gtk_events_pending()) gtk_main_iteration(); + + if(mainbox.stop != 0) stop = 2; + if(progressbox.stop != 0) stop = 2; + } // ENDWHILE- Comparing two files... sector by sector + + if(stop == 0) { + MainBoxRefocus(); + MessageBoxShow("Images Match.", 0); + } // ENDIF- Everything checked out? Say so. + tempiso1 = IsoFileClose(tempiso1); + tempiso2 = IsoFileClose(tempiso2); + tempisoname1 = NULL; + tempisoname2 = NULL; + return(TRUE); +} // END MainBoxOKEvent() + + +void MainBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + + mainbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(mainbox.window), 5); + gtk_window_set_title(GTK_WINDOW(mainbox.window), "CDVDisoEFP Comparsion"); + gtk_window_set_position(GTK_WINDOW(mainbox.window), GTK_WIN_POS_CENTER); + // gtk_window_set_resizable(GTK_WINDOW(mainbox.window), FALSE); + + g_signal_connect(G_OBJECT(mainbox.window), "delete_event", + G_CALLBACK(MainBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(mainbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("First Iso File:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + mainbox.file1 = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.file1, TRUE, TRUE, 0); + gtk_widget_show(mainbox.file1); + g_signal_connect(G_OBJECT(mainbox.file1), "changed", + G_CALLBACK(MainBoxFile1Event), NULL); + hbox1 = NULL; + + mainbox.desc1 = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.desc1, FALSE, FALSE, 0); + gtk_widget_show(mainbox.desc1); + + item = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + item = NULL; + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Second Iso File:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + mainbox.file2 = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.file2, TRUE, TRUE, 0); + gtk_widget_show(mainbox.file2); + g_signal_connect(G_OBJECT(mainbox.file2), "changed", + G_CALLBACK(MainBoxFile2Event), NULL); + hbox1 = NULL; + + mainbox.desc2 = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.desc2, FALSE, FALSE, 0); + gtk_widget_show(mainbox.desc2); + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + mainbox.okbutton = gtk_button_new_with_label("Compare"); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.okbutton, TRUE, TRUE, 0); + gtk_widget_show(mainbox.okbutton); + g_signal_connect(G_OBJECT(mainbox.okbutton), "clicked", + G_CALLBACK(MainBoxOKEvent), NULL); + + item = gtk_button_new_with_label("Exit"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(MainBoxCancelEvent), NULL); + item = NULL; + hbox1 = NULL; + vbox1 = NULL; + + // We held off setting the name until now... so description would show. + gtk_entry_set_text(GTK_ENTRY(mainbox.file1), conf.isoname); + gtk_entry_set_text(GTK_ENTRY(mainbox.file2), conf.isoname); +} // END MainBoxDisplay() + + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + OpenLog(); + InitConf(); + LoadConf(); + MainBoxDisplay(); + ProgressBoxDisplay(); + MessageBoxDisplay(); + + gtk_widget_show_all(mainbox.window); + gtk_main(); + CloseLog(); + return(0); +} // END main() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.glade new file mode 100644 index 0000000..8ca32e1 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisonbox.glade @@ -0,0 +1,227 @@ + + + + + + + + 5 + True + CDVDiso Comparison + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + False + 0 + + + + True + First Iso File: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 5 + True + True + + + + + 0 + True + True + + + + + + True + File Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Second Iso File: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 5 + True + True + + + + + 0 + True + True + + + + + + True + File Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Compare + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Exit + True + GTK_RELIEF_NORMAL + True + + + + + 5 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/comparisondummy.c b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisondummy.c new file mode 100644 index 0000000..ebedf17 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/comparisondummy.c @@ -0,0 +1,24 @@ +/* comparisondummy.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +void ConversionBoxRefocus() { return; } + +void DeviceBoxRefocus() { return; } diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/conf.c b/plugins/cdvd/CDVDisoEFP/src/Linux/conf.c new file mode 100644 index 0000000..cd75fe4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/conf.c @@ -0,0 +1,204 @@ +/* conf.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // getenv() +#include // strerror() +#include // mkdir(), stat() +#include // mkdir(), stat() +#include // stat() + +// #define CDVDdefs +// #include "../PS2Edefs.h" +#include "logfile.h" +#include "../ini.h" +#include "conf.h" + + +const char *cfgname[] = { \ + "./cfg/cfgCDVDisoEFP", \ + "../cfg/cfgCDVDisoEFP", \ + "./cfgCDVDisoEFP", \ + "../cfgCDVDisoEFP", \ + "./plugins/cfgCDVDisoEFP", \ + "../plugins/cfgCDVDisoEFP", \ + NULL }; + +const char *confnames[] = { "IsoFile", "CdDev", NULL }; +const u8 defaultdevice[] = DEFAULT_DEVICE; +const char defaulthome[] = "../inis"; +const char defaultdirectory[] = ".PS2E"; +const char defaultfile[] = "CDVDisoEFP.ini"; + +char confdirname[256]; +char conffilename[256]; + +CDVDconf conf; + + +void ExecCfg(char *arg) { + int nameptr; + struct stat filestat; + char templine[256]; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVDiso interface: ExecCfg(%s)", arg); +#endif /* VERBOSE FUNCTION_CONF */ + errno = 0; + nameptr = 0; + while((cfgname[nameptr] != NULL) && + (stat(cfgname[nameptr], &filestat) == -1)) nameptr++; + errno = 0; + + if(cfgname[nameptr] == NULL) { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVDiso interface: Couldn't find configuration program!"); +#endif /* VERBOSE_FUNCTION_CONF */ + return; + } // ENDIF- Did not find the executable? + + sprintf(templine, "%s %s", cfgname[nameptr], arg); + system(templine); +} // END ExecCfg() + + +void InitConf() { + int i; + int pos; + char *envptr; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: InitConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + conf.isoname[0] = 0; // Empty the iso name + + i = 0; + while((i < 255) && defaultdevice[i] != 0) { + conf.devicename[i] = defaultdevice[i]; + i++; + } // ENDWHILE- copying the default CD/DVD name in + conf.devicename[i] = 0; // 0-terminate the device name + + // Locating directory and file positions + pos = 0; + envptr = getenv("HOME"); + if(envptr == NULL) { + // = + i = 0; + while((pos < 253) && (defaulthome[i] != 0)) { + confdirname[pos] = defaulthome[i]; + conffilename[pos] = defaulthome[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + } else { + // = / + i = 0; + while((pos < 253) && (*(envptr + i) != 0)) { + confdirname[pos] = *(envptr + i); + conffilename[pos] = *(envptr + i); + pos++; + i++; + } // ENDWHILE- copying home directory info in + + if(confdirname[pos-1] != '/') { + confdirname[pos] = '/'; + conffilename[pos] = '/'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultdirectory[i] != 0)) { + confdirname[pos] = defaultdirectory[i]; + conffilename[pos] = defaultdirectory[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + } // ENDIF- No Home directory? + + confdirname[pos] = 0; // Directory reference finished + + // += / + if(conffilename[pos-1] != '/') { + conffilename[pos] = '/'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultfile[i] != 0)) { + conffilename[pos] = defaultfile[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + conffilename[pos] = 0; // File reference finished + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: Directory: %s\n", confdirname); + PrintLog("CDVD config: File: %s\n", conffilename); +#endif /* VERBOSE_FUNCTION_CONF */ +} // END InitConf() + + +void LoadConf() { + int retval; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: LoadConf()\n"); +#endif /* VERBOSE_FUNCTION_CONF */ + + retval = INILoadString(conffilename, "Settings", "IsoFile", conf.isoname); + if(retval < 0) { + sprintf(conf.isoname, "[Put an Image Name here]"); + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadString(conffilename, "Settings", "Device", conf.devicename); + if(retval < 0) { + sprintf(conf.devicename, "/dev/dvd"); + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadUInt(conffilename, "Settings", "OpenOnStart", &conf.startconfigure); + if(retval < 0) { + conf.startconfigure = 0; // False + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadUInt(conffilename, "Settings", "OpenOnRestart", &conf.restartconfigure); + if(retval < 0) { + conf.restartconfigure = 1; // True + } // ENDIF- Couldn't find keyword? Fill in a default +} // END LoadConf() + + +void SaveConf() { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: SaveConf()\n"); +#endif /* VERBOSE_FUNCTION_CONF */ + + mkdir(confdirname, 0755); + + INISaveString(conffilename, "Settings", "IsoFile", conf.isoname); + INISaveString(conffilename, "Settings", "Device", conf.devicename); + INISaveUInt(conffilename, "Settings", "OpenOnStart", conf.startconfigure); + INISaveUInt(conffilename, "Settings", "OpenOnRestart", conf.restartconfigure); +} // END SaveConf() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/conf.h b/plugins/cdvd/CDVDisoEFP/src/Linux/conf.h new file mode 100644 index 0000000..42bb401 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/conf.h @@ -0,0 +1,54 @@ +/* conf.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef CONF_H +#define CONF_H + + +#define CDVDdefs +#include "../PS2Edefs.h" + + +#define VERBOSE_FUNCTION_CONF + + +// Configuration Data + +typedef struct { + u8 isoname[256]; + u8 devicename[256]; + unsigned int startconfigure; + unsigned int restartconfigure; +} CDVDconf; +extern CDVDconf conf; + +#define DEFAULT_DEVICE "K:\\" + + +// Configuration Functions + +extern void InitConf(); +extern void LoadConf(); +extern void SaveConf(); + +extern void ExecCfg(char *arg); + + +#endif /* CONF_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.c new file mode 100644 index 0000000..7bd5501 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.c @@ -0,0 +1,388 @@ +/* conversionbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcpy() +#include // off64_t + +#include // gtk_button_new_with_label() +#include // gtk_combo_box_new() +#include // gtk_check_button_new() +#include // gtk_container_add() +#include // gtk_entry_new() +#include // gtk_file_selection_set_filename() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_hseparator_new() +#include // gtk_label_new() +#include // gtk_main_iteration() +#include // gtk_toggle_button_get_active() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "isofile.h" +#include "isocompress.h" // compressdesc[] +#include "imagetype.h" // imagedata[] +#include "multifile.h" // multinames[] +#include "toc.h" +#include "progressbox.h" +#include "messagebox.h" +#include "selectionbox.h" +#include "mainbox.h" +#include "conversionbox.h" + + +struct ConversionBoxData conversionbox; + + +void ConversionBoxDestroy() { + if(conversionbox.window != NULL) { + gtk_widget_destroy(conversionbox.window); + conversionbox.window = NULL; + conversionbox.file = NULL; + conversionbox.selectbutton = NULL; + conversionbox.filedesc = NULL; + conversionbox.compress = NULL; + conversionbox.multi = NULL; + conversionbox.okbutton = NULL; + conversionbox.cancelbutton = NULL; + } // ENDIF- Do we have a Main Window still? +} // END ConversionBoxDestroy() + + +void ConversionBoxUnfocus() { + gtk_widget_set_sensitive(conversionbox.file, FALSE); + gtk_widget_set_sensitive(conversionbox.selectbutton, FALSE); + gtk_widget_set_sensitive(conversionbox.compress, FALSE); + gtk_widget_set_sensitive(conversionbox.multi, FALSE); + gtk_widget_set_sensitive(conversionbox.okbutton, FALSE); + gtk_widget_set_sensitive(conversionbox.cancelbutton, FALSE); + // gtk_window_iconify(GTK_WINDOW(conversionbox.window)); + gtk_widget_hide(conversionbox.window); +} // END ConversionBoxUnfocus() + + +gint ConversionBoxFileEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + returnval = IsIsoFile(gtk_entry_get_text(GTK_ENTRY(conversionbox.file))); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(conversionbox.filedesc), "File Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + gtk_label_set_text(GTK_LABEL(conversionbox.filedesc), + "File Type: Not a file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -3) { + gtk_label_set_text(GTK_LABEL(conversionbox.filedesc), + "File Type: Not a valid image file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -4) { + gtk_label_set_text(GTK_LABEL(conversionbox.filedesc), + "File Type: Missing Table File (will rebuild)"); + return(TRUE); + } // ENDIF- Not a regular file? + + tempfile = IsoFileOpenForRead(gtk_entry_get_text(GTK_ENTRY(conversionbox.file))); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + gtk_label_set_text(GTK_LABEL(conversionbox.filedesc), templine); + tempfile = IsoFileClose(tempfile); + return(TRUE); +} // END ConversionBoxFileEvent() + + +void ConversionBoxRefocus() { + GdkEvent event; + + ConversionBoxFileEvent(NULL, event, NULL); + + gtk_widget_set_sensitive(conversionbox.file, TRUE); + gtk_widget_set_sensitive(conversionbox.selectbutton, TRUE); + gtk_widget_set_sensitive(conversionbox.compress, TRUE); + gtk_widget_set_sensitive(conversionbox.multi, TRUE); + gtk_widget_set_sensitive(conversionbox.okbutton, TRUE); + gtk_widget_set_sensitive(conversionbox.cancelbutton, TRUE); + gtk_window_set_focus(GTK_WINDOW(conversionbox.window), conversionbox.file); + gtk_widget_show_all(conversionbox.window); + gtk_window_deiconify(GTK_WINDOW(conversionbox.window)); +} // END ConversionBoxRefocus() + + +gint ConversionBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + gtk_widget_hide(conversionbox.window); + MainBoxRefocus(); + return(TRUE); +} // END ConversionBoxCancelEvent() + + +gint ConversionBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + char templine[256]; + char tempblock[2352]; + const char *filename; + int compressmethod; + int multi; + struct IsoFile *fromfile; + struct IsoFile *tofile; + int i; + off64_t endsector; + int stop; + int retval; + + ConversionBoxUnfocus(); + + filename = gtk_entry_get_text(GTK_ENTRY(conversionbox.file)); + if(IsIsoFile(filename) < 0) { + filename = NULL; + MessageBoxShow("Not a valid file", 3); + return(TRUE); + } // ENDIF- Not an Iso File? Stop early. + + compressmethod = gtk_combo_box_get_active(GTK_COMBO_BOX(conversionbox.compress)); + if(compressmethod > 0) compressmethod += 2; + multi = 0; + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(conversionbox.multi)) == TRUE) + multi = 1; + + fromfile = NULL; + fromfile = IsoFileOpenForRead(filename); + if(fromfile == NULL) { + filename = NULL; + MessageBoxShow("Cannot opening the source file", 3); + return(TRUE); + } // ENDIF- Not an Iso File? Stop early. + + if((compressmethod == fromfile->compress) && + (multi == fromfile->multi)) { + fromfile = IsoFileClose(fromfile); + filename = NULL; + MessageBoxShow("Compress/Multifile methods match - no need to convert", 3); + return(TRUE); + } // ENDIF- Not an Iso File? Stop early. + + tofile = IsoFileOpenForWrite(filename, + GetImageTypeConvertTo(fromfile->imagetype), + multi, + compressmethod); + if(tofile == NULL) { + fromfile = IsoFileClose(fromfile); + filename = NULL; + MessageBoxShow("Cannot create the new file", 3); + return(TRUE); + } // ENDIF- Not an Iso File? Stop early. + + if(fromfile->multi == 1) { + i = 0; + while((i < 10) && + (IsoFileSeek(fromfile, fromfile->multisectorend[i] + 1) == 0)) i++; + endsector = fromfile->multisectorend[fromfile->multiend]; + } else { + endsector = fromfile->filesectorsize; + } // ENDIF- Get ending sector from multifile? (Or single file?) + IsoFileSeek(fromfile, 0); + + // Open Progress Bar + sprintf(templine, "%s: %s%s -> %s%s", + filename, + multinames[fromfile->multi], + compressdesc[fromfile->compress], + multinames[tofile->multi], + compressdesc[tofile->compress]); + ProgressBoxStart(templine, endsector); + + tofile->cdvdtype = fromfile->cdvdtype; + for(i = 0; i < 2048; i++) tofile->toc[i] = fromfile->toc[i]; + + stop = 0; + mainbox.stop = 0; + progressbox.stop = 0; + while((stop == 0) && (tofile->sectorpos < endsector)) { + retval = IsoFileRead(fromfile, tempblock); + if(retval < 0) { + MessageBoxShow("Trouble reading source file", 3); + stop = 1; + } else { + retval = IsoFileWrite(tofile, tempblock); + if(retval < 0) { + MessageBoxShow("Trouble writing new file", 3); + stop = 1; + } // ENDIF- Trouble writing out the next block? + } // ENDIF- Trouble reading in the next block? + + ProgressBoxTick(tofile->sectorpos); + while(gtk_events_pending()) gtk_main_iteration(); + + if(mainbox.stop != 0) stop = 2; + if(progressbox.stop != 0) stop = 2; + } // ENDWHILE- Not stopped for some reason... + + ProgressBoxStop(); + + if(stop == 0) { + if(tofile->multi == 1) tofile->name[tofile->multipos] = '0'; // First file + strcpy(templine, tofile->name); + + // fromfile = IsoFileCloseAndDelete(fromfile); + fromfile = IsoFileClose(fromfile); + + IsoSaveTOC(tofile); + tofile = IsoFileClose(tofile); + gtk_entry_set_text(GTK_ENTRY(mainbox.file), templine); + + } else { + fromfile = IsoFileClose(fromfile); + tofile = IsoFileCloseAndDelete(tofile); + } // ENDIF- Did we succeed in the transfer? + + if(stop != 1) ConversionBoxRefocus(); + if(stop == 0) ConversionBoxCancelEvent(widget, event, data); + return(TRUE); +} // END ConversionBoxOKEvent() + + +gint ConversionBoxBrowseEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + ConversionBoxUnfocus(); + + // Transfer file name to file selection + gtk_file_selection_set_filename(GTK_FILE_SELECTION(selectionbox.window), + gtk_entry_get_text(GTK_ENTRY(conversionbox.file))); + selectionbox.wherefrom = 3; // From the Conversion Window + SelectionBoxRefocus(); + return(TRUE); +} // END ConversionBoxBrowseEvent() + + +void ConversionBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + int nameptr; + + conversionbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(conversionbox.window), 5); + gtk_window_set_title(GTK_WINDOW(conversionbox.window), "CDVDisoEFP File Conversion"); + gtk_window_set_position(GTK_WINDOW(conversionbox.window), GTK_WIN_POS_CENTER); + + g_signal_connect(G_OBJECT(conversionbox.window), "delete_event", + G_CALLBACK(ConversionBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(conversionbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Iso File:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + conversionbox.file = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.file, TRUE, TRUE, 0); + gtk_widget_show(conversionbox.file); + g_signal_connect(G_OBJECT(conversionbox.file), "changed", + G_CALLBACK(ConversionBoxFileEvent), NULL); + + conversionbox.selectbutton = gtk_button_new_with_label("Browse"); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.selectbutton, FALSE, FALSE, 0); + gtk_widget_show(conversionbox.selectbutton); + g_signal_connect(G_OBJECT(conversionbox.selectbutton), "clicked", + G_CALLBACK(ConversionBoxBrowseEvent), NULL); + hbox1 = NULL; + + conversionbox.filedesc = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), conversionbox.filedesc, FALSE, FALSE, 0); + gtk_widget_show(conversionbox.filedesc); + // ConversionBoxFileEvent(NULL, 0, NULL); // Work out compromise later... + + item = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + item = NULL; + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Change Compression To:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + conversionbox.compress = gtk_combo_box_new_text(); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.compress, FALSE, FALSE, 0); + nameptr = 0; + while(compressnames[nameptr] != NULL) { + gtk_combo_box_append_text(GTK_COMBO_BOX(conversionbox.compress), + compressnames[nameptr]); + nameptr++; + } // ENDWHILE- loading compression types into combo box + gtk_combo_box_set_active(GTK_COMBO_BOX(conversionbox.compress), 0); // Temp Line + gtk_widget_show(conversionbox.compress); + hbox1 = NULL; + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Multiple Files (all under 2 GB):"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + conversionbox.multi = gtk_check_button_new(); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.multi, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(conversionbox.multi), FALSE); + gtk_widget_show(conversionbox.multi); + hbox1 = NULL; + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + conversionbox.okbutton = gtk_button_new_with_label("Change File"); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.okbutton, TRUE, TRUE, 0); + gtk_widget_show(conversionbox.okbutton); + g_signal_connect(G_OBJECT(conversionbox.okbutton), "clicked", + G_CALLBACK(ConversionBoxOKEvent), NULL); + + conversionbox.cancelbutton = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), conversionbox.cancelbutton, TRUE, TRUE, 0); + gtk_widget_show(conversionbox.cancelbutton); + g_signal_connect(G_OBJECT(conversionbox.cancelbutton), "clicked", + G_CALLBACK(ConversionBoxCancelEvent), NULL); + hbox1 = NULL; + vbox1 = NULL; +} // END ConversionBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.glade new file mode 100644 index 0000000..d51c5d3 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.glade @@ -0,0 +1,272 @@ + + + + + + + + 5 + True + CDVDiso File Conversion + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + False + 0 + + + + True + Iso File: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + + True + True + Browse + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + File Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Change Compression To: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + None +GZip (for speed) +BZip2 (for speed) +BZip2 (for size) + + + + 5 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Multiple Files (all under 2 GB): + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Change File + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.h new file mode 100644 index 0000000..d583837 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/conversionbox.h @@ -0,0 +1,47 @@ +/* conversionbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CONVERSIONBOX_H +#define CONVERSIONBOX_H + + +#include + + +struct ConversionBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *file; // GtkEntry + GtkWidget *selectbutton; // GtkButton + GtkWidget *filedesc; // GtkLabel + GtkWidget *compress; // GtkComboBox + GtkWidget *multi; // GtkCheckButton + GtkWidget *okbutton; // GtkButton + GtkWidget *cancelbutton; // GtkButton +}; + +extern struct ConversionBoxData conversionbox; + +extern void ConversionBoxDestroy(); +extern void ConversionBoxRefocus(); +extern void ConversionBoxDisplay(); + + +#endif /* CONVERSIONBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/device.c b/plugins/cdvd/CDVDisoEFP/src/Linux/device.c new file mode 100644 index 0000000..51efeea --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/device.c @@ -0,0 +1,418 @@ +/* device.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // open() +#include // NULL +#include // getenv() +#include // strerror() +#include // ioctl() +#include // open() +#include // open() +#include // time_t, time(), struct timeval +#include // close(), select() + +#include // CD/DVD based ioctl() and defines. + +#include "logfile.h" +#include "conf.h" +#include "CD.h" +#include "DVD.h" +#include "device.h" + + +// Globals + +int devicehandle; // File Handle for the device/drive +s32 devicecapability; // Capability Flags +time_t lasttime; // Time marker (in case something gets called too often) +s32 traystatus; // Is the CD/DVD tray open? + +s32 disctype; // Type of disc in drive (Video DVD, PSX CD, etc.) +u8 tocbuffer[2048]; + + +void DeviceInit() { + devicehandle = -1; + devicecapability = 0; + lasttime = time(NULL); + + InitDisc(); +} // END DeviceInit() + + +// Called by DeviceOpen(), DeviceGetDiskType() +void InitDisc() { + int i; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: InitDisc()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if((disctype == CDVD_TYPE_PS2DVD) || + (disctype == CDVD_TYPE_DVDV)) { + InitDVDInfo(); + } // ENDIF- Clean out DVD Disc Info? + + if((disctype == CDVD_TYPE_PS2CD) || + (disctype == CDVD_TYPE_PS2CDDA) || + (disctype == CDVD_TYPE_PSCD) || + (disctype == CDVD_TYPE_PSCDDA) || + (disctype == CDVD_TYPE_CDDA)) { + InitCDInfo(); + } // ENDIF- Clean out DVD Disc Info? + + disctype = CDVD_TYPE_NODISC; + for(i = 0; i > sizeof(tocbuffer); i++) tocbuffer[i] = 0x00; +} // END InitDisc() + + +s32 DiscInserted() { + if(devicehandle == -1) return(-1); + if(traystatus == CDVD_TRAY_OPEN) return(-1); + if(disctype == CDVD_TYPE_ILLEGAL) return(-1); + // if(disctype == CDVD_TYPE_UNKNOWN) return(-1); // Hmm. Let this one through? + if(disctype == CDVD_TYPE_DETCTDVDD) return(-1); + if(disctype == CDVD_TYPE_DETCTDVDS) return(-1); + if(disctype == CDVD_TYPE_DETCTCD) return(-1); + if(disctype == CDVD_TYPE_DETCT) return(-1); + if(disctype == CDVD_TYPE_NODISC) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DiscInserted()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + return(0); +} // END DiscInserted() + + +// Called by DeviceTrayStatus() and CDVDopen() +s32 DeviceOpen() { + // s32 s32result; + + errno = 0; + + if(devicehandle != -1) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVD device: Device already open!"); +#endif /* VERBOSE_WARNING_DEVICE */ + return(0); + } // ENDIF- Is the CD/DVD already in use? That's fine. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + // InitConf(); + // LoadConf(); // Should be done once before making this call + + devicehandle = open(conf.devicename, O_RDONLY | O_NONBLOCK); + if(devicehandle == -1) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Error opening device: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Failed to open device? Abort + + // Note: Hmm. Need a minimum capability in case this fails? + devicecapability = ioctl(devicehandle, CDROM_GET_CAPABILITY); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Error getting device capabilities: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + close(devicehandle); + devicehandle = -1; + devicecapability = 0; + return(-1); + } // ENDIF- Can't read drive capabilities? Close and Abort. + +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD device: Device Type(s)"); + if(devicecapability < CDC_CD_R) PrintLog("CDVD device: CD"); + if(devicecapability & CDC_CD_R) PrintLog("CDVD device: CD-R"); + if(devicecapability & CDC_CD_RW) PrintLog("CDVD device: CD-RW"); + if(devicecapability & CDC_DVD) PrintLog("CDVD device: DVD"); + if(devicecapability & CDC_DVD_R) PrintLog("CDVD device: DVD-R"); + if(devicecapability & CDC_DVD_RAM) PrintLog("CDVD device: DVD-RAM"); +#endif /* VERBOSE_DISC_TYPE */ +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD device: Device Capabilities:"); + if(devicecapability & CDC_CLOSE_TRAY) PrintLog("CDVD device: Can close a tray"); + if(devicecapability & CDC_OPEN_TRAY) PrintLog("CDVD device: Can open a tray"); + // if(devicecapability & CDC_LOCK) PrintLog("CDVD device: Can lock the drive door"); + if(devicecapability & CDC_SELECT_SPEED) PrintLog("CDVD device: Can change spin speed"); + // if(devicecapability & CDC_SELECT_DISC) PrintLog("CDVD device: Can change disks (multi-disk tray)"); + // if(devicecapability & CDC_MULTI_SESSION) PrintLog("CDVD device: Can read multi-session disks"); + // if(devicecapability & CDC_MCN) PrintLog("CDVD device: Can read Medium Catalog Numbers (maybe)"); + if(devicecapability & CDC_MEDIA_CHANGED) PrintLog("CDVD device: Can tell if the disc was changed"); + if(devicecapability & CDC_PLAY_AUDIO) PrintLog("CDVD device: Can play audio disks"); + // if(devicecapability & CDC_RESET) PrintLog("CDVD device: Can reset the device"); + //if(devicecapability & CDC_IOCTLS) PrintLog("CDVD device: Odd IOCTLs. Not sure of compatability"); + if(devicecapability & CDC_DRIVE_STATUS) PrintLog("CDVD device: Can monitor the drive tray"); + +#endif /* VERBOSE_DISC_INFO */ + + ////// Should be called after an open (instead of inside of one) + // InitDisc(); + // traystatus = CDVD_TRAY_OPEN; // Start with Tray Open + // DeviceTrayStatus(); // Now find out for sure. + + return(0); // Device opened and ready for use. +} // END DeviceOpen() + + +// Called by DeviceTrayStatus(), CDVDclose(), and CDVDshutdown() +void DeviceClose() { + // s32 s32result; + int zerospeed; + + zerospeed = 0; + + if(devicehandle == -1) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: Device already closed"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + return; + } // ENDIF- Device already closed? Ok. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + InitDisc(); + close(devicehandle); + devicehandle = -1; + devicecapability = 0; + return; +} // END CDVDclose() + + +s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceReadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(DiscInserted() == -1) return(-1); + + // Get that data + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + s32result = DVDreadTrack(lsn, mode, buffer); + } else { + s32result = CDreadTrack(lsn, mode, buffer); + } //ENDIF- Read a DVD sector or a CD sector? + + return(s32result); +} // END DeviceReadTrack() + + +s32 DeviceBufferOffset() { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceBufferOffset()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(0); + } else { + return(CDgetBufferOffset()); + } // ENDIF- Is this a DVD? +} // END DeviceBufferOffset() + + +s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTD(track, cdvdtd)); + } else { + return(CDgetTD(track, cdvdtd)); + } // ENDIF- Is this a DVD? +} // END DeviceGetTD() + + +// Called by DeviceTrayStatus() +s32 DeviceGetDiskType() { + s32 s32result; + s32 ioctldisktype; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if(traystatus == CDVD_TRAY_OPEN) { + return(disctype); + } // ENDIF- Is the device tray open? No disc to check yet. + + if(disctype != CDVD_TYPE_NODISC) { + return(disctype); + } // ENDIF- Already checked? Drive still closed? Disc hasn't changed. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceGetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + disctype = CDVD_TYPE_DETCT; + + ioctldisktype = ioctl(devicehandle, CDROM_DISC_STATUS); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble reading Disc Type!"); + PrintLog("CDVD device: Error: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + disctype = CDVD_TYPE_UNKNOWN; + return(disctype); + } // ENDIF- Trouble probing for a disc? + + s32result = DVDgetDiskType(ioctldisktype); + if(s32result != -1) { + return(disctype); + } // ENDIF- Did we find a disc type? + + s32result = CDgetDiskType(ioctldisktype); + if(s32result != -1) { + return(disctype); + } // ENDIF- Did we find a disc type? + + disctype = CDVD_TYPE_UNKNOWN; // Not a CD? Not a DVD? Is is peanut butter? + return(disctype); +} // END CDVDgetDiskType() + + +// Called by PollLoop() and CDVDgetTrayStatus() +s32 DeviceTrayStatus() { + s32 s32result; + + errno = 0; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayStatus()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_DRIVE_STATUS) != 0) { + s32result = ioctl(devicehandle, CDROM_DRIVE_STATUS); + if(s32result < 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble reading Drive Status!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + s32result = CDS_TRAY_OPEN; + } // ENDIF- Failure to get status? Assume it's open. + errno = 0; + + } else { + s32result = ioctl(devicehandle, CDROM_DISC_STATUS); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble detecting Disc Status presense!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + s32result = CDS_TRAY_OPEN; + errno = 0; + } // ENDIF- Trouble? + if(s32result == CDS_NO_DISC) { + s32result = CDS_TRAY_OPEN; + } // ENDIF- Is there no disc in the device? Guess the tray is open + } // ENDIF- Can we poll the tray directly? (Or look at disc status instead?) + + if(s32result == CDS_TRAY_OPEN) { + traystatus = CDVD_TRAY_OPEN; + if(disctype != CDVD_TYPE_NODISC) { + DeviceClose(); // Kind of severe way of flushing all buffers. + DeviceOpen(); + InitDisc(); + } // ENDIF- Tray just opened... clear disc info + } else { + traystatus = CDVD_TRAY_CLOSE; + if(disctype == CDVD_TYPE_NODISC) { + DeviceGetDiskType(); + } // ENDIF- Tray just closed? Get disc information + } // ENDIF- Do we detect an open tray? + return(traystatus); +} // END CDVD_getTrayStatus() + + +s32 DeviceTrayOpen() { + s32 s32result; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_OPEN_TRAY) == 0) { + return(-1); + } // ENDIF- Don't have open capability? Error out. + + // Tray already open? Exit. + if(traystatus == CDVD_TRAY_OPEN) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + s32result = ioctl(devicehandle, CDROMEJECT); +#ifdef VERBOSE_WARNINGS + if((s32result != 0) || (errno != 0)) { + PrintLog("CDVD device: Could not open the tray!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); + } // ENDIF- Trouble? +#endif /* VERBOSE_WARNINGS */ + return(s32result); +} // END DeviceTrayOpen() + + +s32 DeviceTrayClose() { + s32 s32result; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_CLOSE_TRAY) == 0) { + return(-1); + } // ENDIF- Don't have close capability? Error out. + + // Tray already closed? Exit. + if(traystatus == CDVD_TRAY_CLOSE) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + s32result = ioctl(devicehandle, CDROMCLOSETRAY); +#ifdef VERBOSE_WARNINGS + if((s32result != 0) || (errno != 0)) { + PrintLog("CDVD device: Could not close the tray!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); + } // ENDIF- Trouble? +#endif /* VERBOSE_WARNINGS */ + return(s32result); +} // END DeviceTrayClose() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/device.h b/plugins/cdvd/CDVDisoEFP/src/Linux/device.h new file mode 100644 index 0000000..0d0d8ff --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/device.h @@ -0,0 +1,69 @@ +/* device.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + + +#include // time_t + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ +#define CDVDdefs +#include "../PS2Edefs.h" + + +// #define VERBOSE_FUNCTION_DEVICE +// #define VERBOSE_WARNINGS +#define VERBOSE_DISC_TYPE +#define VERBOSE_DISC_INFO + + +// Device Data + +extern int devicehandle; +extern s32 devicecapability; // Need to export? + +extern time_t lasttime; +extern s32 traystatus; +extern s32 disctype; +extern u8 tocbuffer[]; + + +// Device Functions + +extern void DeviceInit(); +extern void InitDisc(); +extern s32 DiscInserted(); +extern s32 DeviceOpen(); +extern void DeviceClose(); +extern s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DeviceBufferOffset(); +extern s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd); +extern s32 DeviceGetDiskType(); +extern s32 DeviceTrayStatus(); +extern s32 DeviceTrayOpen(); +extern s32 DeviceTrayClose(); + + +#endif /* __DEVICE_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.c new file mode 100644 index 0000000..ff0f566 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.c @@ -0,0 +1,443 @@ +/* devicebox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcpy() +#include // stat() +#include // stat() +#include // stat() + +#include // gtk_button_new_with_label() +#include // gtk_combo_box_new() +#include // gtk_check_button_new() +#include // gtk_container_add() +#include // gtk_entry_new() +#include // gtk_file_selection_set_filename() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_hseparator_new() +#include // gtk_label_new() +#include // gtk_main_iteration() +#include // gtk_toggle_button_get_active() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ +#define CDVDdefs +#include "PS2Edefs.h" + +#include "conf.h" +#include "device.h" +#include "isofile.h" +#include "isocompress.h" // compressdesc[] +// #include "imagetype.h" // imagedata[].name +#include "multifile.h" // multinames[] +#include "toc.h" +#include "progressbox.h" +#include "messagebox.h" +#include "selectionbox.h" +#include "mainbox.h" +#include "devicebox.h" + + +struct DeviceBoxData devicebox; + + +void DeviceBoxDestroy() { + if(devicebox.window != NULL) { + gtk_widget_destroy(devicebox.window); + devicebox.window = NULL; + devicebox.device = NULL; + devicebox.devicedesc = NULL; + devicebox.file = NULL; + devicebox.selectbutton = NULL; + devicebox.filedesc = NULL; + devicebox.compress = NULL; + devicebox.multi = NULL; + devicebox.okbutton = NULL; + devicebox.cancelbutton = NULL; + } // ENDIF- Do we have a Main Window still? +} // END DeviceBoxDestroy() + + +void DeviceBoxUnfocus() { + gtk_widget_set_sensitive(devicebox.device, FALSE); + gtk_widget_set_sensitive(devicebox.file, FALSE); + gtk_widget_set_sensitive(devicebox.selectbutton, FALSE); + gtk_widget_set_sensitive(devicebox.compress, FALSE); + gtk_widget_set_sensitive(devicebox.multi, FALSE); + gtk_widget_set_sensitive(devicebox.okbutton, FALSE); + gtk_widget_set_sensitive(devicebox.cancelbutton, FALSE); + gtk_widget_hide(devicebox.window); + // gtk_window_iconify(GTK_WINDOW(devicebox.window)); +} // END DeviceBoxUnfocus() + + +gint DeviceBoxDeviceEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + struct stat filestat; + int returnval; + + returnval = stat(gtk_entry_get_text(GTK_ENTRY(devicebox.device)), &filestat); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(devicebox.devicedesc), "Device Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(S_ISDIR(filestat.st_mode) != 0) { + gtk_label_set_text(GTK_LABEL(devicebox.devicedesc), "Device Type: Not a device"); + return(TRUE); + } // ENDIF- Not a regular file? + + gtk_label_set_text(GTK_LABEL(devicebox.devicedesc), "Device Type: Device Likely"); + return(TRUE); +} // END DeviceBoxDeviceEvent() + + +gint DeviceBoxFileEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + returnval = IsIsoFile(gtk_entry_get_text(GTK_ENTRY(devicebox.file))); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(devicebox.filedesc), "File Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + gtk_label_set_text(GTK_LABEL(devicebox.filedesc), "File Type: Not a file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -3) { + gtk_label_set_text(GTK_LABEL(devicebox.filedesc), "File Type: Not a valid image file"); + return(TRUE); + } // ENDIF- Not an image file? + + if(returnval == -4) { + gtk_label_set_text(GTK_LABEL(devicebox.filedesc), "File Type: Missing Table File (will rebuild)"); + return(TRUE); + } // ENDIF- Not a regular file? + + tempfile = IsoFileOpenForRead(gtk_entry_get_text(GTK_ENTRY(devicebox.file))); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + gtk_label_set_text(GTK_LABEL(devicebox.filedesc), templine); + tempfile = IsoFileClose(tempfile); + return(TRUE); +} // END DeviceBoxFileEvent() + + +void DeviceBoxRefocus() { + GdkEvent event; + + DeviceBoxDeviceEvent(NULL, event, NULL); + DeviceBoxFileEvent(NULL, event, NULL); + + gtk_widget_set_sensitive(devicebox.device, TRUE); + gtk_widget_set_sensitive(devicebox.file, TRUE); + gtk_widget_set_sensitive(devicebox.selectbutton, TRUE); + gtk_widget_set_sensitive(devicebox.compress, TRUE); + gtk_widget_set_sensitive(devicebox.multi, TRUE); + gtk_widget_set_sensitive(devicebox.okbutton, TRUE); + gtk_widget_set_sensitive(devicebox.cancelbutton, TRUE); + gtk_window_set_focus(GTK_WINDOW(devicebox.window), devicebox.file); + gtk_widget_show_all(devicebox.window); + gtk_window_deiconify(GTK_WINDOW(devicebox.window)); +} // END DeviceBoxRefocus() + + +gint DeviceBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + gtk_widget_hide(devicebox.window); + MainBoxRefocus(); + return(TRUE); +} // END DeviceBoxCancelEvent() + + +gint DeviceBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + char templine[256]; + u8 tempbuffer[2352]; + struct IsoFile *tofile; + const char *tempdevice; + s32 retval; + cdvdTD cdvdtd; + int stop; + int compressmethod; + int multi; + int imagetype; + int i; + + DeviceBoxUnfocus(); + + tempdevice = gtk_entry_get_text(GTK_ENTRY(devicebox.device)); + strcpy(conf.devicename, tempdevice); // Temporarily put in new device name + tempdevice = NULL; + retval = DeviceOpen(); + if(retval != 0) { + DeviceClose(); + MessageBoxShow("Could not open the device", 2); + return(TRUE); + } // ENDIF- Trouble opening device? Abort here. + + DeviceTrayStatus(); + retval = DiscInserted(); + if(retval != 0) { + DeviceClose(); + MessageBoxShow("No disc in the device\r\nPlease put a disc in and try again.", 2); + return(TRUE); + } // ENDIF- Trouble opening device? Abort here. + + retval = DeviceGetTD(0, &cdvdtd); // Fish for Ending Sector + if(retval < 0) { + DeviceClose(); + MessageBoxShow("Could not retrieve disc sector size", 2); + return(TRUE); + } // ENDIF- Trouble getting disc sector count? + + compressmethod = gtk_combo_box_get_active(GTK_COMBO_BOX(devicebox.compress)); + if(compressmethod > 0) compressmethod += 2; + multi = 0; + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(devicebox.multi)) == TRUE) + multi = 1; + + imagetype = 0; + if((disctype != CDVD_TYPE_PS2DVD) && + (disctype != CDVD_TYPE_DVDV)) imagetype = 8; + + tofile = IsoFileOpenForWrite(gtk_entry_get_text(GTK_ENTRY(devicebox.file)), + imagetype, + multi, + compressmethod); + if(tofile == NULL) { + DeviceClose(); + MessageBoxShow("Could not create the new ISO file", 2); + return(TRUE); + } // ENDIF- Trouble opening the ISO file? + + // Open Progress Bar + sprintf(templine, "%s -> %s", + gtk_entry_get_text(GTK_ENTRY(devicebox.device)), tofile->name); + ProgressBoxStart(templine, (off64_t) cdvdtd.lsn); + + tofile->cdvdtype = disctype; + for(i = 0; i < 2048; i++) tofile->toc[i] = tocbuffer[i]; + + stop = 0; + mainbox.stop = 0; + progressbox.stop = 0; + while((stop == 0) && (tofile->sectorpos < cdvdtd.lsn)) { + if(imagetype == 0) { + retval = DeviceReadTrack((u32) tofile->sectorpos, + CDVD_MODE_2048, + tempbuffer); + } else { + retval = DeviceReadTrack((u32) tofile->sectorpos, + CDVD_MODE_2352, + tempbuffer); + } // ENDIF- Are we reading a DVD sector? (Or a CD sector?) + if(retval < 0) { + for(i = 0; i < 2352; i++) { + tempbuffer[i] = 0; + } // NEXT i- Zeroing the buffer + } // ENDIF- Trouble reading next block? + retval = IsoFileWrite(tofile, tempbuffer); + if(retval < 0) { + MessageBoxShow("Trouble writing new file", 3); + stop = 1; + } // ENDIF- Trouble writing out the next block? + + ProgressBoxTick(tofile->sectorpos); + while(gtk_events_pending()) gtk_main_iteration(); + + if(mainbox.stop != 0) stop = 2; + if(progressbox.stop != 0) stop = 2; + } // ENDWHILE- No reason found to stop... + + ProgressBoxStop(); + + if(stop == 0) { + if(tofile->multi == 1) tofile->name[tofile->multipos] = '0'; // First file + strcpy(templine, tofile->name); + } // ENDIF- Did we succeed with the transfer? + + DeviceClose(); + if(stop == 0) { + IsoSaveTOC(tofile); + tofile = IsoFileClose(tofile); + gtk_entry_set_text(GTK_ENTRY(mainbox.file), templine); + } else { + tofile = IsoFileCloseAndDelete(tofile); + } // ENDIF- (Failed to complete writing file? Get rid of the garbage files.) + + if(stop != 1) DeviceBoxRefocus(); + if(stop == 0) DeviceBoxCancelEvent(widget, event, data); + return(TRUE); +} // END DeviceBoxOKEvent() + + +gint DeviceBoxBrowseEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + DeviceBoxUnfocus(); + + // Transfer file name to file selection + gtk_file_selection_set_filename(GTK_FILE_SELECTION(selectionbox.window), + gtk_entry_get_text(GTK_ENTRY(devicebox.file))); + selectionbox.wherefrom = 2; // From the Device Window + SelectionBoxRefocus(); + return(TRUE); +} // END DeviceBoxBrowseEvent() + + +void DeviceBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + int nameptr; + + devicebox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(devicebox.window), 5); + gtk_window_set_title(GTK_WINDOW(devicebox.window), "CDVDisoEFP ISO Creation"); + gtk_window_set_position(GTK_WINDOW(devicebox.window), GTK_WIN_POS_CENTER); + + g_signal_connect(G_OBJECT(devicebox.window), "delete_event", + G_CALLBACK(DeviceBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(devicebox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Source CD/DVD Device:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + devicebox.device = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.device, TRUE, TRUE, 0); + gtk_widget_show(devicebox.device); + g_signal_connect(G_OBJECT(devicebox.device), "changed", + G_CALLBACK(DeviceBoxDeviceEvent), NULL); + hbox1 = NULL; + + devicebox.devicedesc = gtk_label_new("Device Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), devicebox.devicedesc, FALSE, FALSE, 0); + gtk_widget_show(devicebox.devicedesc); + + item = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + item = NULL; + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Iso File:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + devicebox.file = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.file, TRUE, TRUE, 0); + gtk_widget_show(devicebox.file); + g_signal_connect(G_OBJECT(devicebox.file), "changed", + G_CALLBACK(DeviceBoxFileEvent), NULL); + + devicebox.selectbutton = gtk_button_new_with_label("Browse"); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.selectbutton, FALSE, FALSE, 0); + gtk_widget_show(devicebox.selectbutton); + g_signal_connect(G_OBJECT(devicebox.selectbutton), "clicked", + G_CALLBACK(DeviceBoxBrowseEvent), NULL); + hbox1 = NULL; + + devicebox.filedesc = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), devicebox.filedesc, FALSE, FALSE, 0); + gtk_widget_show(devicebox.filedesc); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("New File Compression:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + devicebox.compress = gtk_combo_box_new_text(); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.compress, FALSE, FALSE, 0); + nameptr = 0; + while(compressnames[nameptr] != NULL) { + gtk_combo_box_append_text(GTK_COMBO_BOX(devicebox.compress), + compressnames[nameptr]); + nameptr++; + } // ENDWHILE- loading compression types into combo box + gtk_combo_box_set_active(GTK_COMBO_BOX(devicebox.compress), 0); // Temp Line + gtk_widget_show(devicebox.compress); + hbox1 = NULL; + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Multiple Files (all under 2 GB):"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + devicebox.multi = gtk_check_button_new(); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.multi, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(devicebox.multi), FALSE); + gtk_widget_show(devicebox.multi); + hbox1 = NULL; + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + devicebox.okbutton = gtk_button_new_with_label("Make File"); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.okbutton, TRUE, TRUE, 0); + gtk_widget_show(devicebox.okbutton); + g_signal_connect(G_OBJECT(devicebox.okbutton), "clicked", + G_CALLBACK(DeviceBoxOKEvent), NULL); + + devicebox.cancelbutton = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), devicebox.cancelbutton, TRUE, TRUE, 0); + gtk_widget_show(devicebox.cancelbutton); + g_signal_connect(G_OBJECT(devicebox.cancelbutton), "clicked", + G_CALLBACK(DeviceBoxCancelEvent), NULL); + hbox1 = NULL; + vbox1 = NULL; + + // Device text not set until now to get the correct description. + gtk_entry_set_text(GTK_ENTRY(devicebox.device), conf.devicename); + + DeviceInit(); // Initialize device access +} // END DeviceBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.glade new file mode 100644 index 0000000..168c5e5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.glade @@ -0,0 +1,345 @@ + + + + + + + 5 + True + CDVDiso ISO Creation + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + False + 0 + + + + True + Source CD/DVD Device: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + /dev/dvd + True + * + False + + + 5 + True + True + + + + + 0 + True + True + + + + + + True + Device Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Iso File: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 5 + True + True + + + + + + True + True + Browse + True + GTK_RELIEF_NORMAL + True + + + 5 + False + False + + + + + 0 + True + True + + + + + + True + File Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + New File Compression: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + None +GZip (for speed) +BZip2 (for speed) +BZip2 (for size) + + + + 5 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Multiple Files (all under 2GB): + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Make File + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.h new file mode 100644 index 0000000..ecf748a --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/devicebox.h @@ -0,0 +1,50 @@ +/* devicebox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef DEVICEBOX_H +#define DEVICEBOX_H + + +#include + + +struct DeviceBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *device; // GtkEntry + GtkWidget *devicedesc; // GtkLabel + GtkWidget *file; // GtkEntry + GtkWidget *selectbutton; // GtkButton + GtkWidget *filedesc; // GtkLabel + GtkWidget *compress; // GtkComboBox + GtkWidget *multi; // GtkCheckButton + GtkWidget *okbutton; // GtkButton + GtkWidget *cancelbutton; // GtkButton +}; + +extern struct DeviceBoxData devicebox; + +extern void DeviceBoxDestroy(); +// extern void DeviceBoxUnfocus(); +extern void DeviceBoxRefocus(); +extern void DeviceBoxDisplay(); + + +#endif /* DEVICEBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/interface.c b/plugins/cdvd/CDVDisoEFP/src/Linux/interface.c new file mode 100644 index 0000000..af63d8f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/interface.c @@ -0,0 +1,67 @@ +/* interface.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcmp() + +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_widget_show_all() + +#include "logfile.h" +#include "conf.h" +#include "aboutbox.h" +#include "mainbox.h" +#include "devicebox.h" +#include "selectionbox.h" +#include "progressbox.h" +#include "messagebox.h" +#include "conversionbox.h" +#include "interface.h" + + +int main(int argc, char *argv[]) { + if(argc != 2) return(1); + + gtk_init(NULL, NULL); + + if(!strcmp(argv[1], "about")) { + AboutBoxDisplay(); + return(0); + } else if (!strcmp(argv[1], "configure")) { + OpenLog(); + InitConf(); + LoadConf(); + MainBoxDisplay(); + DeviceBoxDisplay(); + ConversionBoxDisplay(); + ProgressBoxDisplay(); + MessageBoxDisplay(); + SelectionBoxDisplay(); + + gtk_widget_show_all(mainbox.window); + gtk_main(); + CloseLog(); + return(0); + } // ENDLONGIF- Which display would you like to see? + + return(1); // No Displays chosen? Abort! +} // END main() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/interface.h b/plugins/cdvd/CDVDisoEFP/src/Linux/interface.h new file mode 100644 index 0000000..a23946f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/interface.h @@ -0,0 +1,29 @@ +/* interface.h + * Copyright (C) 2002-2004 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef INTERFACE_H +#define INTERFACE_H + + +// Place holder... for now + + +#endif /* INTERFACE_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.c b/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.c new file mode 100644 index 0000000..27c6fe8 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.c @@ -0,0 +1,90 @@ +/* logfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // open +#include // vsprintf() +#include // va_start(), va_end(), vsprintf() +#include // mkdir(), open() +#include // mkdir(), open() +#include // close(), write(), unlink() + +#include "logfile.h" + + +int logfile; +char logfiletemp[2048]; + + +void InitLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + mkdir("./logs", 0755); + + unlink("./logs/CDVDlog.txt"); +#endif /* VERBOSE LOGFILE */ +} // END InitLog(); + + +int OpenLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + logfile = -1; + logfile = open("./logs/CDVDlog.txt", O_WRONLY | O_CREAT | O_APPEND, 0755); + if(logfile == -1) return(-1); +#endif /* VERBOSE LOGFILE */ + + return(0); +} // END OpenLog(); + + +void CloseLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + if(logfile != -1) { + close(logfile); + logfile = -1; + } // ENDIF- Is the log file actually open? Close it. +#endif /* VERBOSE LOGFILE */ +} // END CloseLog() + + +void PrintLog(const char *fmt, ...) { + // Token comment line +#ifdef VERBOSE_LOGFILE + va_list list; + int len; + + if(logfile == -1) return; // Log file not open. + + va_start(list, fmt); + vsprintf(logfiletemp, fmt, list); + va_end(list); + + len = 0; + while((len < 2048) && (logfiletemp[len] != 0)) len++; + if((len > 0) && (logfiletemp[len-1] == '\n')) len--; + if((len > 0) && (logfiletemp[len-1] == '\r')) len--; + logfiletemp[len] = 0; // Slice off the last "\r\n"... + + write(logfile, logfiletemp, len); + write(logfile, "\r\n", 2); // ... and write out your own. +#endif /* VERBOSE LOGFILE */ +} // END PrintLog() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.h b/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.h new file mode 100644 index 0000000..8cee990 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/logfile.h @@ -0,0 +1,35 @@ +/* logfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef LOGFILE_H +#define LOGFILE_H + + +#define VERBOSE_LOGFILE + + +extern void InitLog(); +extern int OpenLog(); +extern void CloseLog(); +extern void PrintLog(const char *format, ...); + + +#endif /* LOGFILE_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.c new file mode 100644 index 0000000..d9989d5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.c @@ -0,0 +1,324 @@ +/* mainbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcpy() + +#include // gtk_button_new_with_label() +#include // gtk_check_button_new_with_label() +#include // gtk_container_add() +#include // gtk_entry_new() +#include // gtk_file_selection_set_filename() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_toggle_button_set_active(), (_get_) +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "conf.h" +#include "isofile.h" +#include "isocompress.h" // compressdesc[] +// #include "imagetype.h" // imagedata[].name +#include "multifile.h" // multinames[] +#include "tablerebuild.h" // IsoTableRebuild() +#include "devicebox.h" +#include "conversionbox.h" +#include "progressbox.h" +#include "messagebox.h" +#include "selectionbox.h" +#include "mainbox.h" + + +struct MainBoxData mainbox; + + +void MainBoxDestroy() { + if(mainbox.window != NULL) { + gtk_widget_destroy(mainbox.window); + mainbox.window = NULL; + mainbox.file = NULL; + mainbox.selectbutton = NULL; + mainbox.desc = NULL; + mainbox.startcheck = NULL; + mainbox.restartcheck = NULL; + mainbox.okbutton = NULL; + mainbox.devbutton = NULL; + mainbox.convbutton = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MainBoxDestroy() + + +void MainBoxUnfocus() { + gtk_widget_set_sensitive(mainbox.file, FALSE); + gtk_widget_set_sensitive(mainbox.selectbutton, FALSE); + gtk_widget_set_sensitive(mainbox.startcheck, FALSE); + gtk_widget_set_sensitive(mainbox.restartcheck, FALSE); + gtk_widget_set_sensitive(mainbox.okbutton, FALSE); + gtk_widget_set_sensitive(mainbox.devbutton, FALSE); + gtk_widget_set_sensitive(mainbox.convbutton, FALSE); + gtk_window_iconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxUnfocus() + + +gint MainBoxFileEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + returnval = IsIsoFile(gtk_entry_get_text(GTK_ENTRY(mainbox.file))); + if(returnval == -1) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "File Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "File Type: Not a file"); + return(TRUE); + } // ENDIF- Not a regular file? + + if(returnval == -3) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "File Type: Not a valid image file"); + return(TRUE); + } // ENDIF- Not an Image file? + + if(returnval == -4) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "File Type: Missing Table File (will rebuild)"); + return(TRUE); + } // ENDIF- Missing Compression seek table? + + tempfile = IsoFileOpenForRead(gtk_entry_get_text(GTK_ENTRY(mainbox.file))); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + gtk_label_set_text(GTK_LABEL(mainbox.desc), templine); + tempfile = IsoFileClose(tempfile); + return(TRUE); +} // END MainBoxFileEvent() + + +void MainBoxRefocus() { + GdkEvent event; + + MainBoxFileEvent(NULL, event, NULL); + + gtk_widget_set_sensitive(mainbox.file, TRUE); + gtk_widget_set_sensitive(mainbox.selectbutton, TRUE); + gtk_widget_set_sensitive(mainbox.startcheck, TRUE); + gtk_widget_set_sensitive(mainbox.restartcheck, TRUE); + gtk_widget_set_sensitive(mainbox.okbutton, TRUE); + gtk_widget_set_sensitive(mainbox.devbutton, TRUE); + gtk_widget_set_sensitive(mainbox.convbutton, TRUE); + gtk_window_set_focus(GTK_WINDOW(mainbox.window), mainbox.file); + gtk_window_deiconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxRefocus() + + +gint MainBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + mainbox.stop = 1; // Halt all long processess... + + MessageBoxDestroy(); + SelectionBoxDestroy(); + ProgressBoxDestroy(); + ConversionBoxDestroy(); + DeviceBoxDestroy(); + MainBoxDestroy(); + + gtk_main_quit(); + return(TRUE); +} // END MainBoxCancelEvent() + + +gint MainBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + const char *tempisoname; + + MainBoxUnfocus(); + + tempisoname = gtk_entry_get_text(GTK_ENTRY(mainbox.file)); + if(*(tempisoname) != 0) { + if(IsIsoFile(tempisoname) == -4) { + IsoTableRebuild(tempisoname); + MainBoxRefocus(); + return(TRUE); + } // ENDIF- Do we need to rebuild an image file's index before using it? + + if(IsIsoFile(tempisoname) < 0) { + tempisoname = NULL; + MainBoxRefocus(); + MessageBoxShow("Not a Valid Image File.", 1); + return(TRUE); + } // ENDIF- Not an ISO file? Message and Stop here. + } // ENDIF- Is there an ISO file to check out? + + strcpy(conf.isoname, tempisoname); + tempisoname = NULL; + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mainbox.startcheck)) == FALSE) { + conf.startconfigure = 0; // FALSE + } else { + conf.startconfigure = 1; // TRUE + } // ENDIF- Was this check button turned off? + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mainbox.restartcheck)) == FALSE) { + conf.restartconfigure = 0; // FALSE + } else { + conf.restartconfigure = 1; // TRUE + } // ENDIF- Was this check button turned off? + + SaveConf(); + + MainBoxCancelEvent(widget, event, data); + return(TRUE); +} // END MainBoxOKEvent() + + +gint MainBoxBrowseEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + MainBoxUnfocus(); + + gtk_file_selection_set_filename(GTK_FILE_SELECTION(selectionbox.window), + gtk_entry_get_text(GTK_ENTRY(mainbox.file))); + selectionbox.wherefrom = 1; // From the Main Window + SelectionBoxRefocus(); + return(TRUE); +} // END MainBoxBrowseEvent() + + +gint MainBoxDeviceEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + MainBoxUnfocus(); + + gtk_entry_set_text(GTK_ENTRY(devicebox.file), + gtk_entry_get_text(GTK_ENTRY(mainbox.file))); + gtk_window_set_focus(GTK_WINDOW(devicebox.window), devicebox.file); + gtk_widget_show_all(devicebox.window); + return(TRUE); +} // END MainBoxBrowseEvent() + + +gint MainBoxConversionEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + MainBoxUnfocus(); + + gtk_entry_set_text(GTK_ENTRY(conversionbox.file), + gtk_entry_get_text(GTK_ENTRY(mainbox.file))); + gtk_window_set_focus(GTK_WINDOW(conversionbox.window), conversionbox.file); + gtk_widget_show_all(conversionbox.window); + return(TRUE); +} // END MainBoxBrowseEvent() + + +void MainBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + + mainbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(mainbox.window), 5); + gtk_window_set_title(GTK_WINDOW(mainbox.window), "CDVDisoEFP Configuration"); + gtk_window_set_position(GTK_WINDOW(mainbox.window), GTK_WIN_POS_CENTER); + + g_signal_connect(G_OBJECT(mainbox.window), "delete_event", + G_CALLBACK(MainBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(mainbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("Iso File:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + mainbox.file = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.file, TRUE, TRUE, 0); + gtk_widget_show(mainbox.file); + g_signal_connect(G_OBJECT(mainbox.file), "changed", + G_CALLBACK(MainBoxFileEvent), NULL); + + mainbox.selectbutton = gtk_button_new_with_label("Browse"); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.selectbutton, FALSE, FALSE, 0); + gtk_widget_show(mainbox.selectbutton); + g_signal_connect(G_OBJECT(mainbox.selectbutton), "clicked", + G_CALLBACK(MainBoxBrowseEvent), NULL); + hbox1 = NULL; + + mainbox.desc = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.desc, FALSE, FALSE, 0); + gtk_widget_show(mainbox.desc); + + // hbox1 = gtk_hbox_new(FALSE, 10); + // gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + // gtk_widget_show(hbox1); + + mainbox.startcheck = gtk_check_button_new_with_label("Show Configure screen when starting emulation"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.startcheck, FALSE, FALSE, 0); + gtk_widget_show(mainbox.startcheck); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainbox.startcheck), FALSE); + if(conf.startconfigure != 0) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainbox.startcheck), TRUE); + } // ENDIF- Is this box supposed to be checked? + + mainbox.restartcheck = gtk_check_button_new_with_label("Show Configure screen when restarting emulation"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.restartcheck, FALSE, FALSE, 0); + gtk_widget_show(mainbox.restartcheck); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainbox.restartcheck), FALSE); + if(conf.restartconfigure != 0) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainbox.restartcheck), TRUE); + } // ENDIF- Is this box supposed to be checked? + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + mainbox.okbutton = gtk_button_new_with_label("Ok"); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.okbutton, TRUE, TRUE, 0); + gtk_widget_show(mainbox.okbutton); + g_signal_connect(G_OBJECT(mainbox.okbutton), "clicked", + G_CALLBACK(MainBoxOKEvent), NULL); + + mainbox.devbutton = gtk_button_new_with_label("Get from Disc"); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.devbutton, TRUE, TRUE, 0); + gtk_widget_show(mainbox.devbutton); + g_signal_connect(G_OBJECT(mainbox.devbutton), "clicked", + G_CALLBACK(MainBoxDeviceEvent), NULL); + + mainbox.convbutton = gtk_button_new_with_label("Convert"); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.convbutton, TRUE, TRUE, 0); + gtk_widget_show(mainbox.convbutton); + g_signal_connect(G_OBJECT(mainbox.convbutton), "clicked", + G_CALLBACK(MainBoxConversionEvent), NULL); + + item = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(MainBoxCancelEvent), NULL); + item = NULL; + hbox1 = NULL; + vbox1 = NULL; + + // We held off setting the name until now... so description would show. + gtk_entry_set_text(GTK_ENTRY(mainbox.file), conf.isoname); +} // END MainBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.glade new file mode 100644 index 0000000..a232918 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.glade @@ -0,0 +1,219 @@ + + + + + + + 5 + True + CDVDiso Configuration + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + False + 0 + + + + True + Iso File: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 5 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 5 + True + True + + + + + + True + True + Browse + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + File Type: --- + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + Show Configure screen when starting emulation + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Show Configure screen when restarting emulation + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Get from Disc + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Convert + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.h new file mode 100644 index 0000000..52f8403 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/mainbox.h @@ -0,0 +1,50 @@ +/* mainbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef MAINBOX_H +#define MAINBOX_H + + +#include + + +struct MainBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *file; // GtkEntry + GtkWidget *selectbutton; // GtkButton + GtkWidget *desc; // GtkLabel + GtkWidget *startcheck; // GtkCheckBox + GtkWidget *restartcheck; // GtkCheckBox + GtkWidget *devbutton; // GtkButton + GtkWidget *convbutton; // GtkButton + GtkWidget *okbutton; // GtkButton + // Leaving the Cancel button unblocked... for emergency shutdown + + int stop; // Variable signal to stop long processes +}; + +extern struct MainBoxData mainbox; + +extern void MainBoxRefocus(); +extern void MainBoxDisplay(); + + +#endif /* MAINBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.c new file mode 100644 index 0000000..845aba3 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.c @@ -0,0 +1,113 @@ +/* messagebox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL + +#include // gtk_button_new_with_label() +#include // gtk_hbutton_box_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "mainbox.h" +#include "devicebox.h" +#include "conversionbox.h" +#include "messagebox.h" + + +struct MessageBoxData messagebox; + + +void MessageBoxDestroy() { + if(messagebox.window != NULL) { + gtk_widget_destroy(messagebox.window); + messagebox.window = NULL; + messagebox.desc = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MessageBoxDestroy() + + +void MessageBoxShow(char *message, int wherefrom) { + gtk_label_set_text(GTK_LABEL(messagebox.desc), message); + messagebox.wherefrom = wherefrom; + + gtk_widget_show_all(messagebox.window); + gtk_window_deiconify(GTK_WINDOW(messagebox.window)); +} // END MessageBox() + + +gint MessageBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + gtk_widget_hide(messagebox.window); + + switch(messagebox.wherefrom) { + case 1: + MainBoxRefocus(); + break; + case 2: + DeviceBoxRefocus(); + break; + case 3: + ConversionBoxRefocus(); + break; + } // ENDSWITCH- Whose window do I get to re-focus when this is done? + + return(TRUE); +} // END MessageBoxCancelEvent() + + +void MessageBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + + messagebox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(messagebox.window), 5); + gtk_window_set_title(GTK_WINDOW(messagebox.window), "CDVDisoEFP"); + gtk_window_set_position(GTK_WINDOW(messagebox.window), GTK_WIN_POS_CENTER); + gtk_window_set_resizable(GTK_WINDOW(messagebox.window), FALSE); + + g_signal_connect(G_OBJECT(messagebox.window), "delete_event", + G_CALLBACK(MessageBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(messagebox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + messagebox.desc = gtk_label_new("Hi There!\r\nHow are you doing?"); + gtk_box_pack_start(GTK_BOX(vbox1), messagebox.desc, FALSE, FALSE, 0); + gtk_widget_show(messagebox.desc); + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS(item, GTK_CAN_DEFAULT); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(MessageBoxCancelEvent), NULL); + item = NULL; + hbox1 = NULL; + vbox1 = NULL; +} // END MessageBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.glade new file mode 100644 index 0000000..4529f9a --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.glade @@ -0,0 +1,76 @@ + + + + + + + + True + CDVDiso + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + Hello there +How are you doing? + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + button1 + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.h new file mode 100644 index 0000000..94ccb3c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/messagebox.h @@ -0,0 +1,43 @@ +/* messagebox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef MESSAGEBOX_H +#define MESSAGEBOX_H + + +#include + + +struct MessageBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *desc; // GtkLabel + + int wherefrom; // Whom do I refocus when the message is read? +}; + +extern struct MessageBoxData messagebox; + +extern void MessageBoxDestroy(); +extern void MessageBoxShow(char *message, int wherefrom); +extern void MessageBoxDisplay(); + + +#endif /* MESSAGEBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.c new file mode 100644 index 0000000..10fd173 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.c @@ -0,0 +1,144 @@ +/* progressbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // off64_t + +#include // gtk_button_new_with_label() +#include // gtk_container_add() +#include // gtk_file_selection_set_filename() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_label_new() +#include // gtk_main_iteration(), gtk_events_pending() +#include // gtk_progress_bar_new() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "progressbox.h" + + +struct ProgressBoxData progressbox; +char progressboxline[256]; + + +void ProgressBoxDestroy() { + if(progressbox.window != NULL) { + gtk_widget_destroy(progressbox.window); + progressbox.window = NULL; + progressbox.desc = NULL; + } // ENDIF- Do we have a Main Window still? +} // END ProgressBoxDestroy() + + +void ProgressBoxStart(char *description, off64_t maximum) { + gtk_label_set_text(GTK_LABEL(progressbox.desc), description); + + progressbox.max = maximum; + progressbox.gmax = maximum; + progressbox.lastpct = 100; + progressbox.stop = 0; + + ProgressBoxTick(0); + gtk_widget_show_all(progressbox.window); + gtk_window_deiconify(GTK_WINDOW(progressbox.window)); +} // END ProgressBoxStart() + + +void ProgressBoxTick(off64_t current) { + gdouble gcur; + off64_t thispct; + + gcur = current; + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbox.bar), + gcur / progressbox.gmax); + + sprintf(progressboxline, "%llu of %llu", current, progressbox.max); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progressbox.bar), progressboxline); + + if(progressbox.max >= 100) { + thispct = current / ( progressbox.max / 100 ); + if(thispct != progressbox.lastpct) { + sprintf(progressboxline, "%llu%% CDVDisoEFP Progress", thispct); + gtk_window_set_title(GTK_WINDOW(progressbox.window), progressboxline); + progressbox.lastpct = thispct; + } // ENDIF- Change in percentage? (Avoiding title flicker) + } // ENDIF- Our maximum # over 100? (Avoiding divide-by-zero error) + + while(gtk_events_pending()) gtk_main_iteration(); // Give time for window to redraw. +} // END ProgressBoxTick() + + +void ProgressBoxStop() { + gtk_widget_hide(progressbox.window); + gtk_window_set_title(GTK_WINDOW(progressbox.window), "CDVDisoEFP Progress"); +} // END ProgressBoxStop() + + +gint ProgressBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + progressbox.stop = 1; + + return(TRUE); +} // END ProgressBoxCancelEvent() + + +void ProgressBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + + progressbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(progressbox.window), 5); + gtk_window_set_title(GTK_WINDOW(progressbox.window), "CDVDisoEFP Progress"); + gtk_window_set_position(GTK_WINDOW(progressbox.window), GTK_WIN_POS_CENTER); + gtk_window_set_resizable(GTK_WINDOW(progressbox.window), FALSE); + + g_signal_connect(G_OBJECT(progressbox.window), "delete_event", + G_CALLBACK(ProgressBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(progressbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + progressbox.desc = gtk_label_new("Twiddling Thumbs"); + gtk_box_pack_start(GTK_BOX(vbox1), progressbox.desc, FALSE, FALSE, 0); + gtk_widget_show(progressbox.desc); + + progressbox.bar = gtk_progress_bar_new(); + gtk_box_pack_start(GTK_BOX(vbox1), progressbox.bar, FALSE, FALSE, 0); + gtk_widget_show(progressbox.bar); + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS(item, GTK_CAN_DEFAULT); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(ProgressBoxCancelEvent), NULL); + item = NULL; + hbox1 = NULL; + vbox1 = NULL; +} // END ProgressBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.glade new file mode 100644 index 0000000..0222925 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.glade @@ -0,0 +1,95 @@ + + + + + + + + True + CDVDiso Progress + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + /dev/dvd -> /usr/src/iso/GameImage.iso + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + Progress Bar: 12758 of 131509 + True + * + False + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 0 + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.h new file mode 100644 index 0000000..3b2eff5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/progressbox.h @@ -0,0 +1,55 @@ +/* progressbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef PROGRESSBOX_H +#define PROGRESSBOX_H + + +#include // off64_t + +#include // GtkWidget + + +extern const char *compressnames[]; + +struct ProgressBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *desc; // GtkLabel - What are we showing progress on? + GtkWidget *bar; // GtkProgressBar + + off64_t max; + gdouble gmax; + off64_t lastpct; + + int stop; // Someone pressed the Stop button +}; + +extern struct ProgressBoxData progressbox; + + +extern void ProgressBoxStart(char *description, off64_t maximum); +extern void ProgressBoxTick(off64_t current); +extern void ProgressBoxStop(); +extern void ProgressBoxDestroy(); +extern void ProgressBoxDisplay(); + + +#endif /* MAINBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.c b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.c new file mode 100644 index 0000000..a33a559 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.c @@ -0,0 +1,102 @@ +/* selectionbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL + +#include // g_signal_connect() +#include // gtk_entry_set_text() +#include // gtk_file_selection_new() + +#include "devicebox.h" +#include "conversionbox.h" +#include "selectionbox.h" +#include "mainbox.h" + + +struct SelectionBoxData selectionbox; + + +void SelectionBoxDestroy() { + if(selectionbox.window != NULL) { + gtk_widget_destroy(selectionbox.window); + selectionbox.window = NULL; + } // ENDIF- Do we have a Main Window still? +} // END SelectionBoxDestroy() + + +void SelectionBoxRefresh() { +} // END SelectionBoxRefresh() + + +void SelectionBoxUnfocus() { + gtk_widget_hide(selectionbox.window); +} // END SelectionBoxUnfocus() + + +void SelectionBoxRefocus() { + gtk_widget_show(selectionbox.window); +} // END SelectionBoxRefocus() + + +gint SelectionBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + SelectionBoxUnfocus(); + switch(selectionbox.wherefrom) { + case 1: + gtk_entry_set_text(GTK_ENTRY(mainbox.file), + gtk_file_selection_get_filename(GTK_FILE_SELECTION(selectionbox.window))); + MainBoxRefocus(); + break; + case 2: + gtk_entry_set_text(GTK_ENTRY(devicebox.file), + gtk_file_selection_get_filename(GTK_FILE_SELECTION(selectionbox.window))); + DeviceBoxRefocus(); + break; + case 3: + gtk_entry_set_text(GTK_ENTRY(conversionbox.file), + gtk_file_selection_get_filename(GTK_FILE_SELECTION(selectionbox.window))); + ConversionBoxRefocus(); + break; + } // ENDSWITCH wherefrom- What Box called us? + return(TRUE); +} // END SelectionBoxCancelEvent() + + +gint SelectionBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + // Validate listed file(?) + + // Transfer file name to calling window? + + SelectionBoxCancelEvent(widget, event, data); + return(TRUE); +} // END SelectionBoxOKEvent() + + +void SelectionBoxDisplay() { + selectionbox.window = gtk_file_selection_new("Select an ISO file"); + g_signal_connect(G_OBJECT(selectionbox.window), "delete_event", + G_CALLBACK(SelectionBoxCancelEvent), NULL); + g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(selectionbox.window)->ok_button), + "clicked", G_CALLBACK(SelectionBoxOKEvent), NULL); + g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(selectionbox.window)->cancel_button), + "clicked", G_CALLBACK(SelectionBoxCancelEvent), NULL); + + selectionbox.wherefrom = 0; // Called by no one... yet. +} // END SelectionBoxDisplay() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.glade b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.glade new file mode 100644 index 0000000..a57b9e4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.glade @@ -0,0 +1,44 @@ + + + + + + + + 10 + True + Select an ISO File + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.h b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.h new file mode 100644 index 0000000..d79febb --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/selectionbox.h @@ -0,0 +1,46 @@ +/* selectionbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef SELECTIONBOX_H +#define SELECTIONBOX_H + + +#include + + +struct SelectionBoxData { + GtkWidget *window; // GtkWindow + + int wherefrom; // Which box called you? + // 1 = MainBox + // 2 = DeviceBox + // 3 = ConversionBox +}; + +extern struct SelectionBoxData selectionbox; + + +extern void SelectionBoxDestroy(); +extern void SelectionBoxRefocus(); +extern void SelectionBoxDisplay(); + + +#endif /* SELECTIONBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.c b/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.c new file mode 100644 index 0000000..3d913ec --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.c @@ -0,0 +1,190 @@ +/* tablerebuild.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // malloc() + +// #include // gtk_main_iteration() + +#include "mainbox.h" +#include "progressbox.h" +#include "isofile.h" +#include "multifile.h" +#include "isocompress.h" // CompressClose() +#include "gzipv1.h" +#include "gzipv2.h" +#include "bzip2v2.h" +#include "bzip2v3.h" +#include "actualfile.h" // ACTUALHANDLENULL + + +void IsoTableRebuild(const char *filename) { + struct IsoFile *datafile; + struct IsoFile *tablefile; + int retval; + char tempblock[65536]; + int stop; + + struct TableData table; + + datafile = IsoFileOpenForRead(filename); + + // Note: This is the start of the "Multifile" process. It's commented + // out so at least we can rebuild 1 part of a multifile at a time. + // IsoNameStripExt(datafile); + // IsoNameStripMulti(datafile); + + // Prep tablefile to hold ONLY a table (no data) + tablefile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); + if(tablefile == NULL) { + datafile = IsoFileClose(datafile); + return; + } // ENDIF- Failed to allocate? Abort. + + tablefile->sectorpos = 0; + tablefile->openforread = 0; + tablefile->filebytepos = 0; + tablefile->filebytesize = 0; + tablefile->filesectorpos = 0; + tablefile->filesectorsize = 0; + tablefile->handle = ACTUALHANDLENULL; + + tablefile->namepos = 0; + while((tablefile->namepos < 255) && + (*(filename + tablefile->namepos) != 0)) { + tablefile->name[tablefile->namepos] = *(filename + tablefile->namepos); + tablefile->namepos++; + } // ENDWHILE- Copying file name into tablefile + tablefile->name[tablefile->namepos] = 0; // And 0-terminate. + + tablefile->imageheader = datafile->imageheader; + tablefile->blocksize = datafile->blocksize; + tablefile->blockoffset = datafile->blockoffset; + tablefile->cdvdtype = 0; // Not important right now. + + tablefile->compress = datafile->compress; + tablefile->compresspos = datafile->compresspos; + tablefile->numsectors = datafile->numsectors; + tablefile->tabledata = NULL; + + switch(tablefile->compress) { + case 1: + retval = GZipV1OpenTableForWrite(tablefile); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2OpenTableForWrite(tablefile); + break; + case 4: + retval = BZip2V2OpenTableForWrite(tablefile); + break; + case 5: + retval = BZip2V3OpenTableForWrite(tablefile); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Which table are we writing out? + if(retval < 0) { + datafile = IsoFileClose(datafile); + return; + } // ENDIF- Failed to open table file? Abort + + sprintf(tempblock, "Rebuilding table for %s", datafile->name); + ProgressBoxStart(tempblock, datafile->filebytesize); + + stop = 0; + mainbox.stop = 0; + progressbox.stop = 0; + while((stop == 0) && (datafile->filebytepos < datafile->filebytesize)) { + switch(datafile->compress) { + case 1: + retval = GZipV1Read(datafile, 0, tempblock); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2Read(datafile, 0, tempblock); + break; + case 4: + retval = BZip2V2Read(datafile, 0, tempblock); + break; + case 5: + retval = BZip2V3Read(datafile, 0, tempblock); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Scanning for the next complete compressed block + + if(retval <= 0) { +#ifdef FUNCTION_WARNING_TABLEREBUILD + PrintLog("CDVDiso rebuild: failed to decompress - data corrupt"); +#endif /* FUNCTION_WARNING_TABLEREBUILD */ + stop = 1; + } else { + table.offset = datafile->filebytepos - retval; + table.size = retval; + switch(tablefile->compress) { + case 1: + retval = GZipV1WriteTable(tablefile, table); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2WriteTable(tablefile, table); + break; + case 4: + retval = BZip2V2WriteTable(tablefile, table); + break; + case 5: + retval = BZip2V3WriteTable(tablefile, table); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Writing out the relavent table facts + if(retval < 0) stop = 1; + } // ENDIF- Do we have a valid record to write an entry for? + + ProgressBoxTick(datafile->filebytepos); + // while(gtk_events_pending()) gtk_main_iteration(); + + if(mainbox.stop != 0) stop = 2; + if(progressbox.stop != 0) stop = 2; + } // ENDWHILE- Read in the data file and writing a table, 1 block at a time + + ProgressBoxStop(); + + CompressClose(tablefile); // Guarentee the table is flushed and closed. + if(stop != 0) { + ActualFileDelete(tablefile->tablename); + } // ENDIF- Aborted or trouble? Delete the table file + tablefile = IsoFileClose(tablefile); + datafile = IsoFileClose(datafile); + + return; +} // END IsoTableRebuild() diff --git a/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.h b/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.h new file mode 100644 index 0000000..731911d --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Linux/tablerebuild.h @@ -0,0 +1,32 @@ +/* tablerebuild.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef TABLEREBUILD_H +#define TABLEREBUILD_H + + +// #define FUNCTION_WARNING_TABLEREBUILD + + +extern void IsoTableRebuild(const char *filename); + + +#endif /* TABLEREBUILD_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/PS2Edefs.h b/plugins/cdvd/CDVDisoEFP/src/PS2Edefs.h new file mode 100644 index 0000000..620a7c8 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/PS2Edefs.h @@ -0,0 +1,812 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(off64_t *mem); +void CALLBACK GSreadFIFO2(off64_t *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(off64_t *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(off64_t *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/PS2Etypes.h b/plugins/cdvd/CDVDisoEFP/src/PS2Etypes.h new file mode 100644 index 0000000..04ad559 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/PS2Etypes.h @@ -0,0 +1,75 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/CD.c b/plugins/cdvd/CDVDisoEFP/src/Win32/CD.c new file mode 100644 index 0000000..469a2dc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/CD.c @@ -0,0 +1,774 @@ +/* CD.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + +#include // IOCTL_CDROM... + + + +#include // off64_t + + + +#define CDVDdefs + +#include "PS2Edefs.h" + + + +#include "logfile.h" + +#include "../convert.h" // MSFtoLBA(), HEXTOBCD() + +#include "actualfile.h" + +#include "device.h" // tocbuffer[], FinishCommand() + +#include "CD.h" + + + + + +int actualcdmode; // -1=ReadFile, 0=YellowMode2, 1=XAForm2, 2=CDDA + +DWORD cdblocksize; // 2048 to 2352 + +int cdoffset; // 0, 8, 16, or 24 + +int cdmode; + + + + + +void InitCDInfo() { + + actualcdmode = -1; + + cdblocksize = 2048; + + cdmode = -1; + +} // END InitCDInfo() + + + + + +s32 CDreadTrackPass(u32 lsn, int mode, u8 *buffer) { + + RAW_READ_INFO rawinfo; + + BOOL boolresult; + + DWORD byteswritten; + + DWORD errcode; + + LARGE_INTEGER targetpos; + + int i; + + + + if((actualcdmode < -1) || (actualcdmode > 2)) return(-1); + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVD CD: CDreadTrack(%llu, %i)", lsn, actualcdmode); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + if(actualcdmode >= 0) { + + rawinfo.DiskOffset.QuadPart = lsn * 2048; // Yes, 2048. + + rawinfo.SectorCount = 1; + + rawinfo.TrackMode = actualcdmode; + + boolresult = DeviceIoControl(devicehandle, + + IOCTL_CDROM_RAW_READ, + + &rawinfo, + + sizeof(RAW_READ_INFO), + + buffer, + + 2352, + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso CD: Couldn't read a sector raw!"); + + PrintError("CDVDiso CD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Couldn't read a raw sector? Maybe not a CD. + + + + } else { + + targetpos.QuadPart = lsn * 2048; + + waitevent.Offset = targetpos.LowPart; + + waitevent.OffsetHigh = targetpos.HighPart; + + + + boolresult = ReadFile(devicehandle, + + buffer + 24, + + 2048, + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso CD: Couldn't read a cooked sector!"); + + PrintError("CDVDiso CD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Trouble with seek? Report it. + + + + for(i = 0; i < 24; i++) *(buffer + i) = 0; + + for(i = 24 + 2048; i < 2352; i++) *(buffer + i) = 0; + + } // ENDIF- Could we read a raw sector? Read another one! + + + + if(boolresult == FALSE) { + + boolresult = GetOverlappedResult(devicehandle, + + &waitevent, + + &byteswritten, + + FALSE); + + } // ENDIF- Did the initial call not complete? Get byteswritten for + + // the completed call. + + + + if(byteswritten < 2048) { + +#ifdef VERBOSE_WARNING_DEVICE + + errcode = GetLastError(); + + PrintLog("CDVDiso CD: Short block! only got %u out of %u bytes", + + byteswritten, cdblocksize); + + PrintError("CDVDiso CD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Couldn't read a raw sector? Maybe not a CD. + + + + cdmode = mode; + + cdblocksize = byteswritten; + + return(0); + +} // END CDreadTrackPass() + + + + + +s32 CDreadTrack(u32 lsn, int mode, u8 *buffer) { + + int retval; + + int lastmode; + + int i; + + + + retval = CDreadTrackPass(lsn, mode, buffer); + + if(retval >= 0) return(retval); + + + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso CD: Same mode doesn't work. Scanning..."); + +#endif /* VERBOSE_WARNING_DEVICE */ + + + + lastmode = actualcdmode; + + actualcdmode = 2; + + while(actualcdmode >= -1) { + + retval = CDreadTrackPass(lsn, mode, buffer); + + if(retval >= 0) return(retval); + + actualcdmode--; + + } // ENDWHILE- Searching each mode for a way to read the sector + + actualcdmode = lastmode; // None worked? Go back to first mode. + + + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso CD: No modes work. Failing sector!"); + +#endif /* VERBOSE_WARNING_DEVICE */ + + + + for(i = 0; i < 2352; i++) *(buffer + i) = 0; + + return(-1); + +} // END CDreadTrack() + + + + + +s32 CDgetBufferOffset() { + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVD CD: CDgetBufferOffset()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + // Send a whole CDDA record in? + + if((actualcdmode == CDDA) && (cdmode == CDVD_MODE_2352)) return(0); + + + + // Otherwise, send the start of the data block in... + + return(cdoffset); + +} // END CDgetBufferOffset() + + + + + +s32 CDreadSubQ() { + + return(-1); + +} // END CDreadSubQ() + + + + + +s32 CDgetTN(cdvdTN *cdvdtn) { + + cdvdtn->strack = BCDTOHEX(tocbuffer[7]); + + cdvdtn->etrack = BCDTOHEX(tocbuffer[17]); + + return(0); + +} // END CDgetTN() + + + + + +s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd) { + + u8 actualtrack; + + int pos; + + char temptime[3]; + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso CD: CDgetTD()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + actualtrack = newtrack; + + if(actualtrack == 0xaa) actualtrack = 0; + + + + if(actualtrack == 0) { + + cdvdtd->type = 0; + + temptime[0] = BCDTOHEX(tocbuffer[27]); + + temptime[1] = BCDTOHEX(tocbuffer[28]); + + temptime[2] = BCDTOHEX(tocbuffer[29]); + + cdvdtd->lsn = MSFtoLBA(temptime); + + } else { + + pos = actualtrack * 10; + + pos += 30; + + cdvdtd->type = tocbuffer[pos]; + + temptime[0] = BCDTOHEX(tocbuffer[pos + 7]); + + temptime[1] = BCDTOHEX(tocbuffer[pos + 8]); + + temptime[2] = BCDTOHEX(tocbuffer[pos + 9]); + + cdvdtd->lsn = MSFtoLBA(temptime); + + } // ENDIF- Whole disc? (or single track?) + + + + return(0); + +} // END CDgetTD() + + + + + +s32 CDgetDiskType() { + + CDROM_TOC cdinfo; + + BOOL boolresult; + + int retval; + + DWORD byteswritten; + + DWORD errcode; + + u8 iso9660name[] = "CD001\0"; + + u8 playstationname[] = "PLAYSTATION\0"; + + u8 ps1name[] = "CD-XA001\0"; + + u8 tempbuffer[2448]; + + int tempdisctype; + + int i; + + int pos; + + unsigned long volumesize; + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso CD: CDgetDiskType()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + tempdisctype = CDVD_TYPE_UNKNOWN; + + + + actualcdmode = 2; + + retval = CDreadTrack(16, CDVD_MODE_2048, tempbuffer); + + if(retval < 0) { + + disctype = tempdisctype; + + return(-1); + + } // ENDIF- Couldn't read the directory sector? Abort. + + + + disctype = CDVD_TYPE_DETCTCD; + + tempdisctype = CDVD_TYPE_CDDA; + + + + cdoffset = 0; + + i = 0; + + while((cdoffset <= 24) && (iso9660name[i] != 0)) { + + i = 0; + + while((iso9660name[i] != 0) && + + (iso9660name[i] == tempbuffer[cdoffset + 1 + i])) i++; + + if(iso9660name[i] != 0) cdoffset += 8; + + } // ENDWHILE- Trying to find a working offset for a ISO9660 record. + + + + if(iso9660name[i] != 0) { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("Detected a CDDA (Music CD)."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_CDDA; + + tocbuffer[0] = 0x01; + + + + } else { + + tocbuffer[0] = 0x41; + + i = 0; + + while((playstationname[i] != 0) && + + (playstationname[i] == tempbuffer[cdoffset + 8 + i])) i++; + + if(playstationname[i] != 0) { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("Detected a non-Playstation CD."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_UNKNOWN; + + + + } else { + + i = 0; + + while((ps1name[i] != 0) && + + (ps1name[i] == tempbuffer[cdoffset + 1024 + i])) i++; + + if(ps1name[i] != 0) { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("Detected a Playstation 2 CD."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_PS2CD; + + } else { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("Detected a Playstation CD."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_PSCD; + + } // ENDIF- Is this not a PlayStation Disc? + + } // ENDIF- Is this not a PlayStation Disc? + + } // ENDIF- Is this not an ISO9660 CD? (a CDDA, in other words?) + + + + // Build the Fake TOC + + tocbuffer[2] = 0xA0; + + tocbuffer[7] = HEXTOBCD(1); // Starting Track + + tocbuffer[12] = 0xA1; + + tocbuffer[17] = HEXTOBCD(1); // Ending Track + + + + volumesize = tempbuffer[84]; // Volume size (big endian) + + volumesize *= 256; + + volumesize += tempbuffer[85]; + + volumesize *= 256; + + volumesize += tempbuffer[86]; + + volumesize *= 256; + + volumesize += tempbuffer[87]; + +#ifdef VERBOSE_DISC_INFO + + if(tempdisctype != CDVD_TYPE_CDDA) { + + PrintLog("CDVDiso CD: ISO9660 size %llu", volumesize); + + } // ENDIF- Data CD? Print size in blocks. + +#endif /* VERBOSE_DISC_INFO */ + + + + LBAtoMSF(volumesize, &tocbuffer[27]); + + tocbuffer[27] = HEXTOBCD(tocbuffer[27]); + + tocbuffer[28] = HEXTOBCD(tocbuffer[28]); + + tocbuffer[29] = HEXTOBCD(tocbuffer[29]); + + + + tocbuffer[40] = 0x02; // Data Mode + + tocbuffer[42] = 0x01; // Track # + + LBAtoMSF(0, &tocbuffer[47]); + + tocbuffer[47] = HEXTOBCD(tocbuffer[47]); + + tocbuffer[48] = HEXTOBCD(tocbuffer[48]); + + tocbuffer[49] = HEXTOBCD(tocbuffer[49]); + + + + // Can we get the REAL TOC? + + boolresult = DeviceIoControl(devicehandle, + + IOCTL_CDROM_READ_TOC, + + NULL, + + 0, + + &cdinfo, + + sizeof(CDROM_TOC), + + &byteswritten, + + NULL); + + + + if(boolresult == FALSE) { + +#ifdef VERBOSE_WARNING_DEVICE + + errcode = GetLastError(); + + PrintLog("CDVDiso CD: Can't get TOC!"); + + PrintError("CDVDiso CD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + disctype = tempdisctype; + + return(disctype); + + } // ENDIF- Can't read the TOC? Accept the fake TOC then. + + + + // Fill in the pieces of the REAL TOC. + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVDiso CD: TOC First Track: %u Last Track: %u", + + cdinfo.FirstTrack, cdinfo.LastTrack); + +#endif /* VERBOSE_DISC_INFO */ + + tocbuffer[7] = HEXTOBCD(cdinfo.FirstTrack); + + tocbuffer[17] = HEXTOBCD(cdinfo.LastTrack); + + + + // for(i = cdinfo.FirstTrack; i <= cdinfo.LastTrack; i++) { + + for(i = 0; i <= cdinfo.LastTrack - cdinfo.FirstTrack; i++) { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVDiso CD: TOC Track %u Disc Size: %u:%u.%u Data Mode %u", + + cdinfo.TrackData[i].TrackNumber, + + cdinfo.TrackData[i].Address[1] * 1, + + cdinfo.TrackData[i].Address[2] * 1, + + cdinfo.TrackData[i].Address[3] * 1, + + cdinfo.TrackData[i].Control * 1); + +#endif /* VERBOSE_DISC_INFO */ + + pos = i * 10 + 40; + + tocbuffer[pos] = cdinfo.TrackData[i].Control; + + tocbuffer[pos + 2] = HEXTOBCD(i + 1); + + tocbuffer[pos + 7] = HEXTOBCD(cdinfo.TrackData[i].Address[1]); + + tocbuffer[pos + 8] = HEXTOBCD(cdinfo.TrackData[i].Address[2]); + + tocbuffer[pos + 9] = HEXTOBCD(cdinfo.TrackData[i].Address[3]); + + } // NEXT i- Transferring Track data to the PS2 TOC + + + + + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVDiso CD: TOC Disc Size: %u:%u.%u", + + cdinfo.TrackData[i].Address[1] * 1, + + cdinfo.TrackData[i].Address[2] * 1, + + cdinfo.TrackData[i].Address[3] * 1); + +#endif /* VERBOSE_DISC_INFO */ + + tocbuffer[27] = HEXTOBCD(cdinfo.TrackData[i].Address[1]); + + tocbuffer[28] = HEXTOBCD(cdinfo.TrackData[i].Address[2]); + + tocbuffer[29] = HEXTOBCD(cdinfo.TrackData[i].Address[3]); + + + + disctype = tempdisctype; + + return(disctype); + +} // END CDgetDiskType() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/CD.h b/plugins/cdvd/CDVDisoEFP/src/Win32/CD.h new file mode 100644 index 0000000..6bff6d8 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/CD.h @@ -0,0 +1,44 @@ +/* CD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CD_H +#define CD_H + + +#include // DWORD + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern DWORD cdblocksize; + + +extern void InitCDInfo(); +extern s32 CDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 CDgetBufferOffset(); +extern s32 CDreadSubQ(); +extern s32 CDgetTN(cdvdTN *cdvdtn); +extern s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 CDgetDiskType(); + + +#endif /* CD_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.c b/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.c new file mode 100644 index 0000000..27cf979 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.c @@ -0,0 +1,570 @@ +/* CDVDiso.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // BOOL, CALLBACK, APIENTRY +#include // NULL + +#define CDVDdefs +#include "../PS2Edefs.h" + +#include "conf.h" +#include "actualfile.h" +#include "../isofile.h" +#include "logfile.h" +#include "../convert.h" +#include "../version.h" +#include "screens.h" +#include "mainbox.h" // Initialize mainboxwindow +#include "progressbox.h" // Initialize progressboxwindow +#include "conversionbox.h" // Initialize conversionboxwindow +#include "devicebox.h" // Initialize deviceboxwindow +#include "CDVDiso.h" + + +struct IsoFile *isofile; +char isobuffer[2448]; +char isocdcheck[2048]; +int isomode; +int deviceopencount; + +HINSTANCE progmodule; + + +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD param, + LPVOID reserved) { + + + switch(param) { + case DLL_PROCESS_ATTACH: + progmodule = hModule; + // mainboxwindow = NULL; + // progressboxwindow = NULL; + // conversionboxwindow = NULL; + // deviceboxwindow = NULL; + return(TRUE); + break; + case DLL_PROCESS_DETACH: + // CDVDshutdown(); + return(TRUE); + break; + case DLL_THREAD_ATTACH: + return(TRUE); + break; + case DLL_THREAD_DETACH: + return(TRUE); + break; + } // ENDSWITCH param- What does the OS want with us? + + return(FALSE); // Wasn't on list? Wasn't handled. +} // END DllMain() + + +char* CALLBACK PS2EgetLibName() { + return(libname); +} // END PS2EgetLibName() + + +u32 CALLBACK PS2EgetLibType() { + return(PS2E_LT_CDVD); +} // END PS2getLibType() + + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return((version << 16) | (revision << 8) | build); +} // END PS2EgetLibVersion2() + + +s32 CALLBACK CDVDinit() { + int i; + + InitLog(); + if(OpenLog() != 0) return(-1); // Couldn't open Log File? Abort. + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDinit()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + InitConf(); + + isofile = NULL; + isomode = -1; + deviceopencount = 0; + for(i = 0; i < 2048; i++) isocdcheck[i] = 0; + + mainboxwindow = NULL; + progressboxwindow = NULL; + conversionboxwindow = NULL; + deviceboxwindow = NULL; + + return(0); +} // END CDVDinit() + + +void CALLBACK CDVDshutdown() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDshutdown()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + isofile = IsoFileClose(isofile); + + // Close Windows as well? (Just in case) + + CloseLog(); +} // END CDVDshutdown() + + +s32 CALLBACK CDVDopen(const char* pTitleFilename) { + HWND lastwindow; + int i; + int retval; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDopen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + lastwindow = GetActiveWindow(); + LoadConf(); + + if( pTitleFilename != NULL ) strcpy(conf.isoname, pTitleFilename); + + if((conf.isoname[0] == 0) || (conf.isoname[0] == '[') || + ((conf.startconfigure == 1) && (deviceopencount == 0)) || + ((conf.restartconfigure == 1) && (deviceopencount > 0))) { + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0200), + lastwindow, + (DLGPROC)MainBoxCallback); + SetActiveWindow(lastwindow); + LoadConf(); + // Blank out the name in config file afterwards? Seems excessive. + } // ENDIF- Haven't initialized the configure program yet? Do so now. + lastwindow = NULL; + + isofile = IsoFileOpenForRead(conf.isoname); + if(isofile == NULL) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Failed to open ISO file!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + // return(-1); // Removed to simulate disc not in drive. + for(i = 0; i < 2048; i++) isocdcheck[i] = 0; + return(0); + } // ENDIF- Trouble opening file? Abort. + + retval = IsoFileSeek(isofile, 16); + if(retval != 0) return(-1); + retval = IsoFileRead(isofile, isobuffer); + if(retval != 0) return(-1); + + if(deviceopencount > 0) { + i = 0; + while((i < 2048) && (isocdcheck[i] == isobuffer[i])) i++; + if(i == 2048) deviceopencount = 0; // Same CD/DVD? No delay. + } // ENDIF- Is this a restart? Check for disc change. + + for(i = 0; i < 2048; i++) isocdcheck[i] = isobuffer[i]; + + return(0); +} // END CDVDopen() + + +void CALLBACK CDVDclose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDclose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + isofile = IsoFileClose(isofile); + deviceopencount = 50; +} // END CDVDclose() + + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + char temptime[3]; + int i; + int pos; + u32 tracklsn; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDreadSubQ()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(-1); + } // ENDIF- Still simulating device tray open? + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + return(-1); // DVDs don't have SubQ data + } // ENDIF- Trying to get a SubQ from a DVD? + + // fake it + i = BCDTOHEX(isofile->toc[7]); + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + tracklsn = MSFtoLBA(temptime); + while((i < BCDTOHEX(isofile->toc[17])) && (tracklsn < lsn)) { + i++; + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + tracklsn = MSFtoLBA(temptime); + } // ENDIF- Loop through tracks searching for lsn track + i--; + + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = HEXTOBCD(i); + subq->trackIndex = HEXTOBCD(i); + + LBAtoMSF(lsn - tracklsn, temptime); + subq->trackM = HEXTOBCD(temptime[0]); + subq->trackS = HEXTOBCD(temptime[1]); + subq->trackF = HEXTOBCD(temptime[2]); + + subq->pad = 0; + + // lba_to_msf(lsn + (2*75), &min, &sec, &frm); + LBAtoMSF(lsn, temptime); + subq->discM = HEXTOBCD(temptime[0]); + subq->discS = HEXTOBCD(temptime[1]); + subq->discF = HEXTOBCD(temptime[2]); + + return(0); +} // END CDVDreadSubQ() + + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(-1); + } // ENDIF- Still simulating device tray open? + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + Buffer->strack = 1; + Buffer->etrack = 1; + } else { + Buffer->strack = BCDTOHEX(isofile->toc[7]); + Buffer->etrack = BCDTOHEX(isofile->toc[17]); + } // ENDIF- Retrieve track info from a DVD? (or a CD?) + + return(0); +} // END CDVDgetTN() + + +s32 CALLBACK CDVDgetTD(u8 track, cdvdTD *Buffer) { + u8 actualtrack; + int pos; + char temptime[3]; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(-1); + } // ENDIF- Still simulating device tray open? + + actualtrack = track; + if(actualtrack == 0xaa) actualtrack = 0; + + if((isofile->cdvdtype == CDVD_TYPE_PS2DVD) || + (isofile->cdvdtype == CDVD_TYPE_DVDV)) { + if (actualtrack <= 1) { + Buffer->type = 0; + Buffer->lsn = isofile->filesectorsize; + } else { + Buffer->type = CDVD_MODE1_TRACK; + Buffer->lsn = 0; + } // ENDIF- Whole disc? (or single track?) + } else { + if (actualtrack == 0) { + Buffer->type = 0; + temptime[0] = BCDTOHEX(isofile->toc[27]); + temptime[1] = BCDTOHEX(isofile->toc[28]); + temptime[2] = BCDTOHEX(isofile->toc[29]); + Buffer->lsn = MSFtoLBA(temptime); + } else { + pos = actualtrack * 10; + pos += 30; + Buffer->type = isofile->toc[pos]; + temptime[0] = BCDTOHEX(isofile->toc[pos + 7]); + temptime[1] = BCDTOHEX(isofile->toc[pos + 8]); + temptime[2] = BCDTOHEX(isofile->toc[pos + 9]); + Buffer->lsn = MSFtoLBA(temptime); + } // ENDIF- Whole disc? (or single track?) + } // ENDIF- Retrieve track info from a DVD? (or a CD?) + + return(0); +} // END CDVDgetTD() + + +s32 CALLBACK CDVDgetTOC(void* toc) { + int i; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetTOC()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(-1); + } // ENDIF- Still simulating device tray open? + + for(i = 0; i < 2048; i++) *(((char *) toc) + i) = isofile->toc[i]; + return(0); +} // END CDVDgetTOC() + + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + int retval; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDreadTrack(%u)", lsn); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(-1); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(-1); + } // ENDIF- Still simulating device tray open? + + retval = IsoFileSeek(isofile, (off64_t) lsn); + if(retval != 0) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Trouble finding the sector!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(-1); + } // ENDIF- Trouble finding the sector? + + retval = IsoFileRead(isofile, isobuffer); + if(retval != 0) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Trouble reading the sector!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(-1); + } // ENDIF- Trouble finding the sector? + + isomode = mode; + return(0); +} // END CDVDreadTrack() + + +u8* CALLBACK CDVDgetBuffer() { + int offset; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDgetBuffer()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(NULL); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(NULL); + } // ENDIF- Still simulating device tray open? + + offset = 0; + switch(isomode) { + case CDVD_MODE_2352: + offset = 0; + break; + case CDVD_MODE_2340: + offset = 12; + break; + case CDVD_MODE_2328: + case CDVD_MODE_2048: + offset = 24; + break; + } // ENDSWITCH isomode- offset to where data it wants is. + + if(offset > isofile->blockoffset) offset = isofile->blockoffset; + + return(isobuffer + offset); +} // END CDVDgetBuffer() + + +s32 CALLBACK CDVDgetDiskType() { +#ifdef VERBOSE_FUNCTION_INTERFACE + // PrintLog("CDVDiso interface: CDVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(CDVD_TYPE_NODISC); + if(deviceopencount > 0) { + deviceopencount--; + if(deviceopencount > 0) return(CDVD_TYPE_DETCT); + } // ENDIF- Still simulating device tray open? + + return(isofile->cdvdtype); +} // END CDVDgetDiskType() + + +s32 CALLBACK CDVDgetTrayStatus() { +#ifdef VERBOSE_FUNCTION_INTERFACE + // PrintLog("CDVDiso interface: CDVDgetTrayStatus()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(isofile == NULL) return(CDVD_TRAY_OPEN); + if(deviceopencount > 30) { + deviceopencount--; + return(CDVD_TRAY_OPEN); + } // ENDIF- Still simulating device tray open? + + return(CDVD_TRAY_CLOSE); +} // END CDVDgetTrayStatus() + + +s32 CALLBACK CDVDctrlTrayOpen() { + HWND lastwindow; + int i; + int retval; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDctrlTrayOpen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + // CDVDclose(); + isofile = IsoFileClose(isofile); + deviceopencount = 50; + + // CDVDopen(); + lastwindow = GetActiveWindow(); + LoadConf(); + if((conf.isoname[0] == 0) || (conf.isoname[0] == '[') || + ((conf.restartconfigure == 1) && (deviceopencount > 0))) { + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0200), + lastwindow, + (DLGPROC)MainBoxCallback); + SetActiveWindow(lastwindow); + LoadConf(); + // Blank out the name in config file afterwards? Seems excessive. + } // ENDIF- Haven't initialized the configure program yet? Do so now. + lastwindow = NULL; + deviceopencount = 0; // Temp line! + // NOTE: What happened to repetitive polling when disc not in drive? + + isofile = IsoFileOpenForRead(conf.isoname); + if(isofile == NULL) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: Failed to open ISO file!"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + // return(-1); // Removed to simulate disc not in drive. + for(i = 0; i < 2048; i++) isocdcheck[i] = 0; + return(0); + } // ENDIF- Trouble opening file? Abort. + + retval = IsoFileSeek(isofile, 16); + if(retval != 0) return(-1); + retval = IsoFileRead(isofile, isobuffer); + if(retval != 0) return(-1); + + if(deviceopencount > 0) { + i = 0; + while((i < 2048) && (isocdcheck[i] == isobuffer[i])) i++; + if(i == 2048) deviceopencount = 0; // Same CD/DVD? No delay. + } // ENDIF- Is this a restart? Check for disc change. + + for(i = 0; i < 2048; i++) isocdcheck[i] = isobuffer[i]; + + return(0); +} // END CDVDctrlTrayOpen() + + +s32 CALLBACK CDVDctrlTrayClose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDctrlTrayClose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + return(0); +} // END CDVDctrlTrayClose() + + +s32 CALLBACK CDVDtest() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDiso interface: CDVDtest()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + // InitConf(); // Shouldn't need this. Doesn't CDVDInit() get called first? + LoadConf(); + + if(conf.isoname[0] == 0) return(0); // No name chosen yet. Catch on Open() + if(IsIsoFile(conf.isoname) == 0) return(0); // Valid name. Go. + return(-1); // Invalid name - reconfigure first. + // Note really need this? Why not just return(0)... +} // END CDVDtest() + + +void CALLBACK CDVDconfigure() { + HWND lastwindow; + + lastwindow = GetActiveWindow(); + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0200), + lastwindow, + (DLGPROC)MainBoxCallback); + SetActiveWindow(lastwindow); + lastwindow = NULL; + return; +} // END CDVDconfigure() + + +BOOL CALLBACK AboutCallback(HWND window, UINT msg, WPARAM param, LPARAM param2) { + switch(msg) { + case WM_COMMAND: + switch(LOWORD(param)) { + case IDC_0104: // "Ok" Button + EndDialog(window, FALSE); + return(TRUE); + break; + } // ENDSWITCH param- Which Windows Message Command? + + case WM_CLOSE: + EndDialog(window, FALSE); + return(TRUE); + break; + } // ENDSWITCH msg- what message has been sent to this window? + + return(FALSE); // Not a recognisable message. Pass it back to the OS. +} // END AboutCallback() + +void CALLBACK CDVDabout() { + HWND lastwindow; + + lastwindow = GetActiveWindow(); + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0100), + lastwindow, + (DLGPROC)AboutCallback); + SetActiveWindow(lastwindow); + return; +} // END CDVDabout() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.h b/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.h new file mode 100644 index 0000000..61aab42 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/CDVDiso.h @@ -0,0 +1,36 @@ +/* CDVDiso.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CDVDISO_H +#define CDVDISO_H + + +#include // HINSTANCE + + +// #define VERBOSE_FUNCTION_INTERFACE + + +extern HINSTANCE progmodule; +extern char isobuffer[]; + + +#endif /* CDVDISO_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.c b/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.c new file mode 100644 index 0000000..18f5c65 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.c @@ -0,0 +1,796 @@ +/* DVD.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + +#include // IOCTL_DVD... + + + +#include // off64_t + + + +#define CDVDdefs + +#include "PS2Edefs.h" + + + +#include "logfile.h" + +#include "device.h" // FinishCommand() + + + + + +struct { + + DVD_DESCRIPTOR_HEADER h; + + DVD_LAYER_DESCRIPTOR d; + +} layer; + +// DVD_LAYER_DESCRIPTOR layer; + +// DVD_COPYRIGHT_DESCRIPTOR copyright; + +// DVD_DISK_KEY_DESCRIPTOR disckey; + +// DVD_BCA_DESCRIPTOR bca; + +// DVD_MANUFACTURER_DESCRIPTOR manufact; + + + + + +void InitDVDInfo() { + + layer.d.EndDataSector = 0; + +} // END InitDVDInfo() + + + + + +s32 DVDGetStructures() { + + DVD_SESSION_ID sessionid; + + DVD_READ_STRUCTURE request; + + DWORD byteswritten; + + BOOL boolresult; + + DWORD errcode; + + s32 retval; + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso DVD: DVDgetStructures()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + boolresult = DeviceIoControl(devicehandle, + + IOCTL_DVD_START_SESSION, + + NULL, + + 0, + + &sessionid, + + sizeof(DVD_SESSION_ID), + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso DVD: Couldn't start session!"); + + PrintError("CDVDiso DVD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Couldn't start a user session on the DVD drive? Fail. + + + + request.BlockByteOffset.QuadPart = 0; + + request.Format = DvdPhysicalDescriptor; + + request.SessionId = sessionid; + + request.LayerNumber = 0; + + retval = 0; + + boolresult = DeviceIoControl(devicehandle, + + IOCTL_DVD_READ_STRUCTURE, + + &request, + + sizeof(DVD_READ_STRUCTURE), + + &layer, + + sizeof(layer), + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso DVD: Couldn't get layer data!"); + + PrintError("CDVDiso DVD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + retval = -1; + + } // ENDIF- Couldn't get layer data? (Including DVD size) Abort. + + + +#ifdef VERBOSE_DISC_INFO + + switch(layer.d.BookType) { + + case 0: + + PrintLog("CDVDiso DVD: Book Type: DVD-ROM"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Book Type: DVD-RAM"); + + break; + + case 2: + + PrintLog("CDVDiso DVD: Book Type: DVD-R"); + + break; + + case 3: + + PrintLog("CDVDiso DVD: Book Type: DVD-RW"); + + break; + + case 9: + + PrintLog("CDVDiso DVD: Book Type: DVD+RW"); + + break; + + default: + + PrintLog("CDVDiso DVD: Book Type: Unknown (%i)", layer.d.BookType); + + break; + + } // ENDSWITCH- Displaying the Book Type + + PrintLog("CDVDiso DVD: Book Version %i", layer.d.BookVersion); + + switch(layer.d.MinimumRate) { + + case 0: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: DVD-ROM"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: DVD-RAM"); + + break; + + case 2: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: DVD-R"); + + break; + + case 3: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: DVD-RW"); + + break; + + case 9: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: DVD+RW"); + + break; + + default: + + PrintLog("CDVDiso DVD: Use Minimum Rate for: Unknown (%i)", layer.d.MinimumRate); + + break; + + } // ENDSWITCH- Displaying the Minimum (Spin?) Rate + + switch(layer.d.DiskSize) { + + case 0: + + PrintLog("CDVDiso DVD: Physical Disk Size: 120mm"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Physical Disk Size: 80mm"); + + break; + + default: + + PrintLog("CDVDiso DVD: Physical Disk Size: Unknown (%i)", layer.d.DiskSize); + + break; + + } // ENDSWITCH- What's the Disk Size? + + switch(layer.d.LayerType) { + + case 1: + + PrintLog("CDVDiso DVD: Layer Type: Read-Only"); + + break; + + case 2: + + PrintLog("CDVDiso DVD: Layer Type: Recordable"); + + break; + + case 4: + + PrintLog("CDVDiso DVD: Layer Type: Rewritable"); + + break; + + default: + + PrintLog("CDVDiso DVD: Layer Type: Unknown (%i)", layer.d.LayerType); + + break; + + } // ENDSWITCH- Displaying the Layer Type + + switch(layer.d.TrackPath) { + + case 0: + + PrintLog("CDVDiso DVD: Track Path: PTP"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Track Path: OTP"); + + break; + + default: + + PrintLog("CDVDiso DVD: Track Path: Unknown (%i)", layer.d.TrackPath); + + break; + + } // ENDSWITCH- What's Track Path Layout? + + PrintLog("CDVDiso DVD: Number of Layers: %i", layer.d.NumberOfLayers + 1); + + switch(layer.d.TrackDensity) { + + case 0: + + PrintLog("CDVDiso DVD: Track Density: .74 m/track"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Track Density: .8 m/track"); + + break; + + case 2: + + PrintLog("CDVDiso DVD: Track Density: .615 m/track"); + + break; + + default: + + PrintLog("CDVDiso DVD: Track Density: Unknown (%i)", layer.d.TrackDensity); + + break; + + } // ENDSWITCH- Displaying the Layer Type + + switch(layer.d.LinearDensity) { + + case 0: + + PrintLog("CDVDiso DVD: Linear Density: .267 m/bit"); + + break; + + case 1: + + PrintLog("CDVDiso DVD: Linear Density: .293 m/bit"); + + break; + + case 2: + + PrintLog("CDVDiso DVD: Linear Density: .409 to .435 m/bit"); + + break; + + case 4: + + PrintLog("CDVDiso DVD: Linear Density: .280 to .291 m/bit"); + + break; + + case 8: + + PrintLog("CDVDiso DVD: Linear Density: .353 m/bit"); + + break; + + default: + + PrintLog("CDVDiso DVD: Linear Density: Unknown (%i)", layer.d.LinearDensity); + + break; + + } // ENDSWITCH- Displaying the Book Type + + if(layer.d.StartingDataSector == 0x30000) { + + PrintLog("CDVDiso DVD: Starting Sector: %lu (DVD-ROM, DVD-R, DVD-RW)", + + layer.d.StartingDataSector); + + } else if(layer.d.StartingDataSector == 0x31000) { + + PrintLog("CDVDiso DVD: Starting Sector: %lu (DVD-RAM, DVD+RW)", + + layer.d.StartingDataSector); + + } else { + + PrintLog("CDVDiso DVD: Starting Sector: %lu", layer.d.StartingDataSector); + + } // ENDLONGIF- What does the starting sector tell us? + + PrintLog("CDVDiso DVD: End of Layer 0: %lu", layer.d.EndLayerZeroSector); + + PrintLog("CDVDiso DVD: Ending Sector: %lu", layer.d.EndDataSector); + + if(layer.d.BCAFlag != 0) PrintLog("CDVDiso DVD: BCA data present"); + +#endif /* VERBOSE_DISC_INFO */ + + + + boolresult = DeviceIoControl(devicehandle, + + IOCTL_DVD_END_SESSION, + + &sessionid, + + sizeof(DVD_SESSION_ID), + + NULL, + + 0, + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso DVD: Couldn't end the session!"); + + PrintError("CDVDiso DVD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + } // ENDIF- Couldn't end the user session? Report it. + + + + return(retval); + +} // END DVDGetStructures() + + + + + +s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer) { + + LARGE_INTEGER targetpos; + + DWORD byteswritten; + + BOOL boolresult; + + DWORD errcode; + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso DVD: DVDreadTrack(%lu)", lsn); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + targetpos.QuadPart = lsn * 2048; + + waitevent.Offset = targetpos.LowPart; + + waitevent.OffsetHigh = targetpos.HighPart; + + + + boolresult = ReadFile(devicehandle, + + buffer, + + 2048, + + &byteswritten, + + &waitevent); + + errcode = FinishCommand(boolresult); + + + + if(errcode != 0) { + +#ifdef VERBOSE_WARNING_DEVICE + + PrintLog("CDVDiso DVD: Couldn't read sector!"); + + PrintError("CDVDiso DVD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Trouble with the command? Report it. + + + + if(boolresult == FALSE) { + + boolresult = GetOverlappedResult(devicehandle, + + &waitevent, + + &byteswritten, + + FALSE); + + } // ENDIF- Did the initial call not complete? Get byteswritten for + + // the completed call. + + + + if(byteswritten < 2048) { + +#ifdef VERBOSE_WARNING_DEVICE + + errcode = GetLastError(); + + PrintLog("CDVDiso CD: Short block! only got %u out of %u bytes", + + byteswritten, 2048); + + PrintError("CDVDiso CD", errcode); + +#endif /* VERBOSE_WARNING_DEVICE */ + + return(-1); + + } // ENDIF- Didn't get enough bytes? Report and Abort! + + + + return(0); + +} // END DVDreadTrack() + + + + + +s32 DVDgetTN(cdvdTN *cdvdtn) { + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso DVD: DVDgetTN()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + if(cdvdtn != NULL) { + + cdvdtn->strack = 1; + + cdvdtn->etrack = 1; + + } // ENDIF- Does the user really want this data? + + return(0); + +} // END DVDgetTN() + + + + + +s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd) { + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso DVD: DVDgetTD()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + if((newtrack >= 2) && (newtrack != 0xAA)) return(-1); // Wrong track + + + + if(cdvdtd != NULL) { + + cdvdtd->type = 0; + + cdvdtd->lsn = layer.d.EndDataSector - layer.d.StartingDataSector + 1; + + } // ENDIF- Does the user really want this data? + + return(0); + +} // END DVDgetTD() + + + + + +s32 DVDgetDiskType() { + + char playstationname[] = "PLAYSTATION\0"; + + int retval; + + s32 tempdisctype; + + char tempbuffer[2048]; + + int i; + + + +#ifdef VERBOSE_FUNCTION_DEVICE + + PrintLog("CDVDiso DVD: DVDgetDiskType()"); + +#endif /* VERBOSE_FUNCTION_DEVICE */ + + + + retval = DVDGetStructures(); + + if(retval < 0) return(-1); // Can't get DVD structures? Not a DVD then. + + if(layer.d.EndDataSector == 0) return(-1); // Missing info? Abort. + + + + retval = DVDreadTrack(16, CDVD_MODE_2048, tempbuffer); + + if(retval < 0) { + + return(-1); + + } // ENDIF- Couldn't read the ISO9660 volume track? Fail. + + + + tempdisctype = CDVD_TYPE_UNKNOWN; + + if(layer.d.NumberOfLayers == 0) { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVDiso DVD: Found Single-Sided DVD."); + +#endif /* VERBOSE_DISC_INFO */ + + disctype = CDVD_TYPE_DETCTDVDS; + + } else { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVDiso DVD: Found Dual-Sided DVD."); + +#endif /* VERBOSE_DISC_INFO */ + + disctype = CDVD_TYPE_DETCTDVDD; + + } // ENDIF- Are we looking at a single layer DVD? (NumberOfLayers + 1) + + + + i = 0; + + while((playstationname[i] != 0) && + + (playstationname[i] == tempbuffer[8 + i])) i++; + + if(playstationname[i] == 0) { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("CDVDiso DVD: Found Playstation 2 DVD."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_PS2DVD; + + } else { + +#ifdef VERBOSE_DISC_TYPE + + PrintLog("CDVDiso DVD: Guessing it's a Video DVD."); + +#endif /* VERBOSE_DISC_TYPE */ + + tempdisctype = CDVD_TYPE_DVDV; + + } // ENDIF- Is this a playstation disc? + + + + for(i = 0; i < 2048; i++) tocbuffer[i] = 0; + + + + if(layer.d.NumberOfLayers == 0) { + + tocbuffer[0] = 0x04; + + tocbuffer[4] = 0x86; + + tocbuffer[5] = 0x72; + + } else { + + tocbuffer[0] = 0x24; + + tocbuffer[4] = 0x41; + + tocbuffer[5] = 0x95; + + } // ENDIF- Are we looking at a single layer DVD? (NumberOfLayers + 1) + + + + tocbuffer[1] = 0x02; + + tocbuffer[2] = 0xF2; + + tocbuffer[3] = 0x00; + + + + tocbuffer[16] = 0x00; + + tocbuffer[17] = 0x03; + + tocbuffer[18] = 0x00; + + tocbuffer[19] = 0x00; + + + + disctype = tempdisctype; + + return(disctype); + +} // END DVDgetDiskType() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.h b/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.h new file mode 100644 index 0000000..3876101 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/DVD.h @@ -0,0 +1,37 @@ +/* DVD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef DVD_H +#define DVD_H + + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern void InitDVDInfo(); +extern s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DVDgetTN(cdvdTN *cdvdtn); +extern s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 DVDgetDiskType(); + + +#endif /* DVD_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32 b/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32 new file mode 100644 index 0000000..d499a79 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32 @@ -0,0 +1,59 @@ +all: plugin + +PLUGIN = CDVDisoEFP.dll +CC = mingw32-gcc.exe + +PLUGINOBJS = CDVDiso.o mainbox.o tablerebuild.o progressbox.o conversionbox.o \ + devicebox.o device.o DVD.o CD.o +PLUGINHEADERS = CDVDiso.h mainbox.h tablerebuild.h progressbox.h conversionbox.h \ + devicebox.h device.h DVD.h CD.h +PLUGINFLAGS = -Wall -O2 -D_WIN32 -D_LARGEFILE64_SOURCE -I.. -I. -I./Win32 -mwindows +PLUGINLIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -lkernel32 \ + -luser32 --subsystem,windows +# Note: Don't think we need all the above libs... will pare down later. + +SHAREDOBJS = ..\\version.o conf.o ..\\isofile.o actualfile.o logfile.o \ + ..\\imagetype.o ..\\multifile.o ..\\isocompress.o ..\\convert.o \ + ..\\gzipv1.o ..\\blockv2.o ..\\gzipv2.o ..\\bzip2v2.o ..\\ecma119.o \ + ..\\toc.o ..\\ini.o ..\\bzip2v3.o \ + ..\\zlib\\adler32.o ..\\zlib\\compress.o ..\\zlib\\crc32.o \ + ..\\zlib\\gzio.o ..\\zlib\\uncompr.o ..\\zlib\\deflate.o \ + ..\\zlib\\trees.o ..\\zlib\\zutil.o ..\\zlib\\inflate.o \ + ..\\zlib\\infback.o ..\\zlib\\inftrees.o ..\\zlib\\inffast.o \ + ..\\bzip2\\blocksort.o ..\\bzip2\\bzlib.o ..\\bzip2\\compress.o \ + ..\\bzip2\\crctable.o ..\\bzip2\\decompress.o ..\\bzip2\\huffman.o \ + ..\\bzip2\\randtable.o +SHAREDHEADERS = ..\\version.h conf.h ..\\isofile.h actualfile.h logfile.h \ + ..\\imagetype.h ..\\multifile.h ..\\isocompress.h ..\\convert.h \ + ..\\gzipv1.h ..\\blockv2.o ..\\gzipv2.h ..\\bzip2v2.h ..\\ecma119.h \ + ..\\toc.h ..\\ini.h ..\\bzip2v3.o + + + +WINDRES = windres.exe + + + +release: plugin + copy $(PLUGIN) ..\\.. + +plugin: $(PLUGINOBJS) $(SHAREDOBJS) screens.res + -del $(PLUGIN) + dllwrap --def plugin.def -o $(PLUGIN) $(PLUGINOBJS) screens.res $(SHAREDOBJS) $(PLUGINLIBS) + strip --strip-unneeded --strip-debug $(PLUGIN) + +$(PLUGINOBJS) $(SHAREDOBJS): %.o: %.c + $(CC) $(PLUGINFLAGS) -c $< -o $@ + +screens.res: screens.rc + $(WINDRES) -i screens.rc -J rc -o screens.res -O coff + +.PHONY : clean allclean +clean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + +allclean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + -del temp.txt err.txt ..\\temp.txt ..\\err.txt + -del ..\\..\\$(PLUGIN) + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32.bak b/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32.bak new file mode 100644 index 0000000..6e9077f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/Makefile.MinGW32.bak @@ -0,0 +1,57 @@ + +PLUGIN = CDVDisoEFP.dll +PLUGINOBJS = CDVDiso.o mainbox.o tablerebuild.o progressbox.o conversionbox.o \ + devicebox.o device.o DVD.o CD.o +PLUGINHEADERS = CDVDiso.h mainbox.h tablerebuild.h progressbox.h conversionbox.h \ + devicebox.h device.h DVD.h CD.h +PLUGINFLAGS = -Wall -O2 -D_LARGEFILE64_SOURCE -I.. -I. -I./Win32 -mwindows +PLUGINLIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -lkernel32 \ + -luser32 --subsystem,windows +# Note: Don't think we need all the above libs... will pare down later. + +SHAREDOBJS = ..\\version.o conf.o ..\\isofile.o actualfile.o logfile.o \ + ..\\imagetype.o ..\\multifile.o ..\\isocompress.o ..\\convert.o \ + ..\\gzipv1.o ..\\blockv2.o ..\\gzipv2.o ..\\bzip2v2.o ..\\ecma119.o \ + ..\\toc.o ..\\ini.o ..\\bzip2v3.o \ + ..\\zlib\\adler32.o ..\\zlib\\compress.o ..\\zlib\\crc32.o \ + ..\\zlib\\gzio.o ..\\zlib\\uncompr.o ..\\zlib\\deflate.o \ + ..\\zlib\\trees.o ..\\zlib\\zutil.o ..\\zlib\\inflate.o \ + ..\\zlib\\infback.o ..\\zlib\\inftrees.o ..\\zlib\\inffast.o \ + ..\\bzip2\\blocksort.o ..\\bzip2\\bzlib.o ..\\bzip2\\compress.o \ + ..\\bzip2\\crctable.o ..\\bzip2\\decompress.o ..\\bzip2\\huffman.o \ + ..\\bzip2\\randtable.o +SHAREDHEADERS = ..\\version.h conf.h ..\\isofile.h actualfile.h logfile.h \ + ..\\imagetype.h ..\\multifile.h ..\\isocompress.h ..\\convert.h \ + ..\\gzipv1.h ..\\blockv2.o ..\\gzipv2.h ..\\bzip2v2.h ..\\ecma119.h \ + ..\\toc.h ..\\ini.h ..\\bzip2v3.o + + +CC = mingw32-gcc.exe +WINDRES = windres.exe + + +all: plugin + +release: plugin + copy $(PLUGIN) ..\\.. + +plugin: $(PLUGINOBJS) $(SHAREDOBJS) screens.res + -del $(PLUGIN) + dllwrap --def plugin.def -o $(PLUGIN) $(PLUGINOBJS) screens.res $(SHAREDOBJS) $(PLUGINLIBS) + strip --strip-unneeded --strip-debug $(PLUGIN) + +$(PLUGINOBJS) $(SHAREDOBJS): %.o: %.c + $(CC) $(PLUGINFLAGS) -c $< -o $@ + +screens.res: screens.rc + $(WINDRES) -i screens.rc -J rc -o screens.res -O coff + +.PHONY : clean allclean +clean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + +allclean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + -del temp.txt err.txt ..\\temp.txt ..\\err.txt + -del ..\\..\\$(PLUGIN) + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.c b/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.c new file mode 100644 index 0000000..864bf91 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.c @@ -0,0 +1,506 @@ +/* actualfile.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + + + +#include // NULL + + + +#include "logfile.h" + +#include "actualfile.h" + + + + + +int IsActualFile(const char *filename) { + + DWORD retval; + + + + if(filename == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: IsActualFile(%s)", filename); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + retval = GetFileAttributes(filename); + + if(retval == INVALID_FILE_ATTRIBUTES) return(-1); // Name doesn't exist. + + if((retval & FILE_ATTRIBUTE_DIRECTORY) != 0) return(-2); + + + + return(0); // Yep, that's a file. + +} // END IsActualFile() + + + + + +void ActualFileDelete(const char *filename) { + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileDelete(%s)", filename); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + DeleteFile(filename); + +} // END ActualFileDelete() + + + + + +void ActualFileRename(const char *origname, const char *newname) { + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileDelete(%s->%s)", origname, newname); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + MoveFile(origname, newname); + + return; + +} // END ActualFileRename() + + + + + +ACTUALHANDLE ActualFileOpenForRead(const char *filename) { + + HANDLE newhandle; + + + + if(filename == NULL) return(NULL); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileOpenForRead(%s)", filename); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + newhandle = CreateFile(filename, + + GENERIC_READ, + + FILE_SHARE_READ, + + NULL, + + OPEN_EXISTING, + + FILE_FLAG_RANDOM_ACCESS, + + NULL); + + if(newhandle == INVALID_HANDLE_VALUE) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + + PrintLog("CDVDiso file: Error opening file %s", filename); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + return(NULL); + + } // ENDIF- Error? Abort + + + + return(newhandle); + +} // END ActualFileOpenForRead() + + + + + +off64_t ActualFileSize(ACTUALHANDLE handle) { + + int retval; + + BY_HANDLE_FILE_INFORMATION info; + + off64_t retsize; + + + + if(handle == NULL) return(-1); + + if(handle == INVALID_HANDLE_VALUE) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileSize()"); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + retval = GetFileInformationByHandle(handle, &info); + + if(retval == 0) return(-1); // Handle doesn't exist... + + + + retsize = info.nFileSizeHigh; + + retsize *= 0x10000; + + retsize *= 0x10000; + + retsize += info.nFileSizeLow; + + return(retsize); + +} // END ActualFileSize() + + + + + +int ActualFileSeek(ACTUALHANDLE handle, off64_t position) { + + // int retval; + + LARGE_INTEGER realpos; + + DWORD errcode; + + + + if(handle == NULL) return(-1); + + if(handle == INVALID_HANDLE_VALUE) return(-1); + + if(position < 0) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileSeek(%llu)", position); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + realpos.QuadPart = position; + +////// WinXP code for seek + +// retval = SetFilePointerEx(handle, + +// realpos, + +// NULL, + +// FILE_BEGIN); + +// if(retval == 0) { + + + +////// Win98 code for seek + + realpos.LowPart = SetFilePointer(handle, + + realpos.LowPart, + + &realpos.HighPart, + + FILE_BEGIN); + + errcode = GetLastError(); + + if((realpos.LowPart == 0xFFFFFFFF) && (errcode != NO_ERROR)) { + + + +#ifdef VERBOSE_WARNING_ACTUALFILE + + PrintLog("CDVDiso file: Error on seek (%llu)", position); + + PrintError("CDVDiso file", errcode); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + return(-1); + + } // ENDIF- Error? Abort + + + + return(0); + +} // END ActualFileSeek() + + + + + +int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer) { + + int retval; + + DWORD bytesread; + +#ifdef VERBOSE_WARNING_ACTUALFILE + + DWORD errcode; + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + + + if(handle == NULL) return(-1); + + if(handle == INVALID_HANDLE_VALUE) return(-1); + + if(bytes < 1) return(-1); + + if(buffer == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileRead(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + retval = ReadFile(handle, buffer, bytes, &bytesread, NULL); + + if(retval == 0) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + + errcode = GetLastError(); + + PrintLog("CDVDiso file: Error reading from file"); + + PrintError("CDVDiso file", errcode); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + return(-1); + + } // ENDIF- Error? Abort + + if(bytesread < bytes) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + + PrintLog("CDVDiso file: Short Block! Only read %i out of %i bytes", bytesread, bytes); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + } // ENDIF- Error? Abort + + + + return(bytesread); // Send back how many bytes read + +} // END ActualFileRead() + + + + + +void ActualFileClose(ACTUALHANDLE handle) { + + if(handle == NULL) return; + + if(handle == INVALID_HANDLE_VALUE) return; + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileClose()"); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + CloseHandle(handle); + + return; + +} // END ActualFileClose() + + + + + +ACTUALHANDLE ActualFileOpenForWrite(const char *filename) { + + HANDLE newhandle; + + + + if(filename == NULL) return(NULL); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileOpenForWrite(%s)", filename); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + newhandle = CreateFile(filename, + + GENERIC_WRITE, + + 0, + + NULL, + + CREATE_ALWAYS, + + FILE_FLAG_SEQUENTIAL_SCAN, + + NULL); + + if(newhandle == INVALID_HANDLE_VALUE) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + + PrintLog("CDVDiso file: Error opening file %s", filename); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + return(NULL); + + } // ENDIF- Error? Abort + + + + return(newhandle); + +} // END ActualFileOpenForWrite() + + + + + +int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer) { + + int retval; + + DWORD byteswritten; + + + + if(handle == NULL) return(-1); + + if(handle == INVALID_HANDLE_VALUE) return(-1); + + if(bytes < 1) return(-1); + + if(buffer == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + + PrintLog("CDVDiso file: ActualFileWrite(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + + + retval = WriteFile(handle, buffer, bytes, &byteswritten, NULL); + + if(retval == 0) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + + PrintLog("CDVDiso file: Error writing to file!"); + +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + // return(-1); + + } // ENDIF- Error? Abort + + + + return(byteswritten); // Send back how many bytes written + +} // END ActualFileWrite() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.h b/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.h new file mode 100644 index 0000000..f1cc9c4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/actualfile.h @@ -0,0 +1,104 @@ +/* actualfile.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef ACTUALFILE_H + +#define ACTUALFILE_H + + + + + +#include + + + +#include // off64_t +#include "PS2Etypes.h" + + + + +#define ACTUALHANDLE HANDLE + +#define ACTUALHANDLENULL NULL + + + +// #define VERBOSE_FUNCTION_ACTUALFILE + +// #define VERBOSE_WARNING_ACTUALFILE + + + + + +extern int IsActualFile(const char *filename); + +extern void ActualFileDelete(const char *filename); + +extern void ActualFileRename(const char *origname, const char *newname); + + + +extern ACTUALHANDLE ActualFileOpenForRead(const char *filename); + +extern off64_t ActualFileSize(ACTUALHANDLE handle); + +extern int ActualFileSeek(ACTUALHANDLE handle, off64_t position); + +extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer); + +extern void ActualFileClose(ACTUALHANDLE handle); + + + +extern ACTUALHANDLE ActualFileOpenForWrite(const char *filename); + +extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer); + + + + + +#endif /* ACTUALFILE_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/conf.c b/plugins/cdvd/CDVDisoEFP/src/Win32/conf.c new file mode 100644 index 0000000..467a317 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/conf.c @@ -0,0 +1,195 @@ +/* conf.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // getenv() +#include // strerror() +#include // mkdir(), stat() +#include // mkdir(), stat(), fork() +#include // stat(), fork(), execlp() + +#include // CreateProcess() + +// #define CDVDdefs +// #include "../PS2Edefs.h" +#include "../PS2Etypes.h" // u8 +#include "logfile.h" +#include "../ini.h" +#include "conf.h" + + +const char *confnames[] = { "IsoFile", "Device", "OpenOnStart", "OpenOnRestart", NULL }; +const u8 defaultdevice[] = DEFAULT_DEVICE; +const char defaulthome[] = "inis"; +const char defaultdirectory[] = "HideMe.PS2E"; +const char defaultfile[] = "CDVDisoEFP.ini"; + +char confdirname[256]; +char conffilename[256]; + +CDVDconf conf; + + +void InitConf() { + DWORD retval; + int i; + int pos; + char *envptr; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: InitConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + conf.isoname[0] = 0; // Empty the iso name + + i = 0; + while((i < 255) && defaultdevice[i] != 0) { + conf.devicename[i] = defaultdevice[i]; + i++; + } // ENDWHILE- copying the default CD/DVD name in + conf.devicename[i] = 0; // 0-terminate the device name + + // Locating directory and file positions + pos = 0; + envptr = NULL; + // envptr = getenv("HOME"); + if(envptr == NULL) { + // = + retval = GetCurrentDirectory(253, confdirname); + if(retval > 0) { + pos = retval; + } else { + pos = 2; + confdirname[0] = '.'; + confdirname[1] = '\\'; + } // ENDIF- Did we retrieve a directory reference? + + i = 0; + while(i < pos) { + conffilename[i] = confdirname[i]; + i++; + } // ENDWHILE- Copying dir info (so far) into file info + + if(confdirname[pos-1] != '\\') { + confdirname[pos] = '\\'; + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaulthome[i] != 0)) { + confdirname[pos] = defaulthome[i]; + conffilename[pos] = defaulthome[i]; + pos++; + i++; + } // ENDWHILE- putting an offset where to store ini data + + } else { + // = / + i = 0; + while((pos < 253) && (*(envptr + i) != 0)) { + confdirname[pos] = *(envptr + i); + conffilename[pos] = *(envptr + i); + pos++; + i++; + } // ENDWHILE- copying home directory info in + + if(confdirname[pos-1] != '\\') { + confdirname[pos] = '\\'; + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultdirectory[i] != 0)) { + confdirname[pos] = defaultdirectory[i]; + conffilename[pos] = defaultdirectory[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + } // ENDIF- No Home directory? + + confdirname[pos] = 0; // Directory reference finished + + // += / + if(conffilename[pos-1] != '\\') { + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultfile[i] != 0)) { + conffilename[pos] = defaultfile[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + conffilename[pos] = 0; // File reference finished + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: Directory: %s", confdirname); + PrintLog("CDVD config: File: %s", conffilename); +#endif /* VERBOSE_FUNCTION_CONF */ +} // END InitConf() + + +void LoadConf() { + int retval; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: LoadConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + retval = INILoadString(conffilename, "Settings", "IsoFile", conf.isoname); + if(retval < 0) { + sprintf(conf.isoname, "[Put an Image File here]"); + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadString(conffilename, "Settings", "Device", conf.devicename); + if(retval < 0) { + sprintf(conf.devicename, "D:"); + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadUInt(conffilename, "Settings", "OpenOnStart", &conf.startconfigure); + if(retval < 0) { + conf.startconfigure = 0; // FALSE + } // ENDIF- Couldn't find keyword? Fill in a default + + retval = INILoadUInt(conffilename, "Settings", "OpenOnRestart", &conf.restartconfigure); + if(retval < 0) { + conf.restartconfigure = 1; // TRUE + } // ENDIF- Couldn't find keyword? Fill in a default +} // END LoadConf() + + +void SaveConf() { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: SaveConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + mkdir(confdirname); + + INISaveString(conffilename, "Settings", "IsoFile", conf.isoname); + INISaveString(conffilename, "Settings", "Device", conf.devicename); + INISaveUInt(conffilename, "Settings", "OpenOnStart", conf.startconfigure); + INISaveUInt(conffilename, "Settings", "OpenOnRestart", conf.restartconfigure); +} // END SaveConf() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/conf.h b/plugins/cdvd/CDVDisoEFP/src/Win32/conf.h new file mode 100644 index 0000000..42bb401 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/conf.h @@ -0,0 +1,54 @@ +/* conf.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef CONF_H +#define CONF_H + + +#define CDVDdefs +#include "../PS2Edefs.h" + + +#define VERBOSE_FUNCTION_CONF + + +// Configuration Data + +typedef struct { + u8 isoname[256]; + u8 devicename[256]; + unsigned int startconfigure; + unsigned int restartconfigure; +} CDVDconf; +extern CDVDconf conf; + +#define DEFAULT_DEVICE "K:\\" + + +// Configuration Functions + +extern void InitConf(); +extern void LoadConf(); +extern void SaveConf(); + +extern void ExecCfg(char *arg); + + +#endif /* CONF_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.c b/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.c new file mode 100644 index 0000000..03ee140 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.c @@ -0,0 +1,750 @@ +/* conversionbox.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + +#include // ComboBox_AddString(), CheckDlgButton() + +#include // NULL + +// #include + + + +#include // sprintf() + +#include // strcpy() + +#include // off64_t + + + +#include "isofile.h" + +#include "isocompress.h" // compressdesc[] + +#include "imagetype.h" // imagedata[] + +#include "multifile.h" // multinames[] + +#include "toc.h" + +#include "progressbox.h" + +#include "mainbox.h" + +#include "screens.h" // DLG_..., IDC_... + +#include "conversionbox.h" + + + + + +HWND conversionboxwindow; + + + + + +void ConversionBoxDestroy() { + + if(conversionboxwindow != NULL) { + + EndDialog(conversionboxwindow, FALSE); + + conversionboxwindow = NULL; + + } // ENDIF- Do we have a Main Window still? + +} // END ConversionBoxDestroy() + + + + + +void ConversionBoxUnfocus() { + + // gtk_widget_set_sensitive(conversionbox.file, FALSE); + + // gtk_widget_set_sensitive(conversionbox.selectbutton, FALSE); + + // gtk_widget_set_sensitive(conversionbox.compress, FALSE); + + // gtk_widget_set_sensitive(conversionbox.multi, FALSE); + + // gtk_widget_set_sensitive(conversionbox.okbutton, FALSE); + + // gtk_widget_set_sensitive(conversionbox.cancelbutton, FALSE); + + ShowWindow(conversionboxwindow, SW_HIDE); + +} // END ConversionBoxUnfocus() + + + + + +void ConversionBoxFileEvent() { + + int returnval; + + char templine[256]; + + struct IsoFile *tempfile; + + + + GetDlgItemText(conversionboxwindow, IDC_0402, templine, 256); + + returnval = IsIsoFile(templine); + + if(returnval == -1) { + + SetDlgItemText(conversionboxwindow, IDC_0404, "File Type: ---"); + + return; + + } // ENDIF- Not a name of any sort? + + + + if(returnval == -2) { + + SetDlgItemText(conversionboxwindow, IDC_0404, "File Type: Not a file"); + + return; + + } // ENDIF- Not a regular file? + + + + if(returnval == -3) { + + SetDlgItemText(conversionboxwindow, IDC_0404, "File Type: Not a valid image file"); + + return; + + } // ENDIF- Not a regular file? + + + + if(returnval == -4) { + + SetDlgItemText(conversionboxwindow, IDC_0404, "File Type: Missing Table File (will rebuild)"); + + return; + + } // ENDIF- Not a regular file? + + + + tempfile = IsoFileOpenForRead(templine); + + sprintf(templine, "File Type: %s%s%s", + + multinames[tempfile->multi], + + tempfile->imagename, + + compressdesc[tempfile->compress]); + + SetDlgItemText(conversionboxwindow, IDC_0404, templine); + + tempfile = IsoFileClose(tempfile); + + return; + +} // END ConversionBoxFileEvent() + + + + + +void ConversionBoxRefocus() { + + ConversionBoxFileEvent(); + + + + // gtk_widget_set_sensitive(conversionbox.file, TRUE); + + // gtk_widget_set_sensitive(conversionbox.selectbutton, TRUE); + + // gtk_widget_set_sensitive(conversionbox.compress, TRUE); + + // gtk_widget_set_sensitive(conversionbox.multi, TRUE); + + // gtk_widget_set_sensitive(conversionbox.okbutton, TRUE); + + // gtk_widget_set_sensitive(conversionbox.cancelbutton, TRUE); + + // gtk_window_set_focus(GTK_WINDOW(conversionbox.window), conversionbox.file); + + ShowWindow(conversionboxwindow, SW_SHOW); + + SetActiveWindow(conversionboxwindow); + +} // END ConversionBoxRefocus() + + + + + +void ConversionBoxCancelEvent() { + + // ShowWindow(conversionboxwindow, SW_HIDE); + + ConversionBoxDestroy(); + + MainBoxRefocus(); + + return; + +} // END ConversionBoxCancelEvent() + + + + + +void ConversionBoxOKEvent() { + + char templine[256]; + + char tempblock[2352]; + + char filename[256]; + + HWND tempitem; + + int compressmethod; + + int multi; + + struct IsoFile *fromfile; + + struct IsoFile *tofile; + + int i; + + off64_t endsector; + + int stop; + + int retval; + + + + ConversionBoxUnfocus(); + + + + GetDlgItemText(conversionboxwindow, IDC_0402, filename, 256); + + if(IsIsoFile(filename) < 0) { + + ConversionBoxRefocus(); + + MessageBox(conversionboxwindow, + + "Not a Valid Image File.", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Not an Iso File? Stop early. + + + + tempitem = GetDlgItem(conversionboxwindow, IDC_0406); + + compressmethod = ComboBox_GetCurSel(tempitem); + + tempitem = NULL; + + if(compressmethod > 0) compressmethod += 2; + + + + multi = 0; + + if(IsDlgButtonChecked(conversionboxwindow, IDC_0408)) multi = 1; + + + + fromfile = NULL; + + fromfile = IsoFileOpenForRead(filename); + + if(fromfile == NULL) { + + ConversionBoxRefocus(); + + MessageBox(conversionboxwindow, + + "Cannot opening the source file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Not an Iso File? Stop early. + + + + if((compressmethod == fromfile->compress) && + + (multi == fromfile->multi)) { + + fromfile = IsoFileClose(fromfile); + + ConversionBoxRefocus(); + + MessageBox(conversionboxwindow, + + "Compress/Multifile methods match - no need to convert", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Not an Iso File? Stop early. + + + + tofile = IsoFileOpenForWrite(filename, + + GetImageTypeConvertTo(fromfile->imagetype), + + multi, + + compressmethod); + + if(tofile == NULL) { + + fromfile = IsoFileClose(fromfile); + + ConversionBoxRefocus(); + + MessageBox(conversionboxwindow, + + "Cannot create the new file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Not an Iso File? Stop early. + + + + if(fromfile->multi == 1) { + + i = 0; + + while((i < 10) && + + (IsoFileSeek(fromfile, fromfile->multisectorend[i] + 1) == 0)) i++; + + endsector = fromfile->multisectorend[fromfile->multiend]; + + } else { + + endsector = fromfile->filesectorsize; + + } // ENDIF- Get ending sector from multifile? (Or single file?) + + IsoFileSeek(fromfile, 0); + + + + // Open Progress Bar + + sprintf(templine, "%s: %s%s -> %s%s", + + filename, + + multinames[fromfile->multi], + + compressdesc[fromfile->compress], + + multinames[tofile->multi], + + compressdesc[tofile->compress]); + + ProgressBoxStart(templine, endsector); + + + + tofile->cdvdtype = fromfile->cdvdtype; + + for(i = 0; i < 2048; i++) tofile->toc[i] = fromfile->toc[i]; + + + + stop = 0; + + mainboxstop = 0; + + progressboxstop = 0; + + while((stop == 0) && (tofile->sectorpos < endsector)) { + + retval = IsoFileRead(fromfile, tempblock); + + if(retval < 0) { + + MessageBox(conversionboxwindow, + + "Trouble reading source file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + stop = 1; + + } else { + + retval = IsoFileWrite(tofile, tempblock); + + if(retval < 0) { + + MessageBox(conversionboxwindow, + + "Trouble writing new file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + stop = 1; + + } // ENDIF- Trouble writing out the next block? + + } // ENDIF- Trouble reading in the next block? + + + + ProgressBoxTick(tofile->sectorpos); + + + + if(mainboxstop != 0) stop = 2; + + if(progressboxstop != 0) stop = 2; + + } // ENDWHILE- Not stopped for some reason... + + + + ProgressBoxStop(); + + + + if(stop == 0) { + + if(tofile->multi == 1) tofile->name[tofile->multipos] = '0'; // First file + + strcpy(templine, tofile->name); + + + + // fromfile = IsoFileCloseAndDelete(fromfile); + + fromfile = IsoFileClose(fromfile); + + + + IsoSaveTOC(tofile); + + tofile = IsoFileClose(tofile); + + SetDlgItemText(mainboxwindow, IDC_0202, templine); + + + + } else { + + fromfile = IsoFileClose(fromfile); + + tofile = IsoFileCloseAndDelete(tofile); + + } // ENDIF- Did we succeed in the transfer? + + + + ConversionBoxRefocus(); + + if(stop == 0) ConversionBoxCancelEvent(); + + return; + +} // END ConversionBoxOKEvent() + + + + + +void ConversionBoxBrowseEvent() { + + OPENFILENAME filebox; + + char newfilename[256]; + + BOOL returnbool; + + + + filebox.lStructSize = sizeof(filebox); + + filebox.hwndOwner = conversionboxwindow; + + filebox.hInstance = NULL; + + filebox.lpstrFilter = fileselection; + + filebox.lpstrCustomFilter = NULL; + + filebox.nFilterIndex = 0; + + filebox.lpstrFile = newfilename; + + filebox.nMaxFile = 256; + + filebox.lpstrFileTitle = NULL; + + filebox.nMaxFileTitle = 0; + + filebox.lpstrInitialDir = NULL; + + filebox.lpstrTitle = NULL; + + filebox.Flags = OFN_FILEMUSTEXIST + + | OFN_NOCHANGEDIR + + | OFN_HIDEREADONLY; + + filebox.nFileOffset = 0; + + filebox.nFileExtension = 0; + + filebox.lpstrDefExt = NULL; + + filebox.lCustData = 0; + + filebox.lpfnHook = NULL; + + filebox.lpTemplateName = NULL; + + + + GetDlgItemText(conversionboxwindow, IDC_0402, newfilename, 256); + + returnbool = GetOpenFileName(&filebox); + + if(returnbool != FALSE) { + + SetDlgItemText(conversionboxwindow, IDC_0402, newfilename); + + } // ENDIF- User actually selected a name? Save it. + + + + return; + +} // END ConversionBoxBrowseEvent() + + + + + +void ConversionBoxDisplay() { + + char templine[256]; + + HWND itemptr; + + int itemcount; + + + + // Adjust window position? + + + + // Pull the name from the Main Window... for a starting place. + + GetDlgItemText(mainboxwindow, IDC_0202, templine, 256); + + SetDlgItemText(conversionboxwindow, IDC_0402, templine); + + + + // ConversionBoxFileEvent(); // Needed? + + + + itemptr = GetDlgItem(conversionboxwindow, IDC_0406); // Compression Combo + + itemcount = 0; + + while(compressnames[itemcount] != NULL) { + + ComboBox_AddString(itemptr, compressnames[itemcount]); + + itemcount++; + + } // ENDWHILE- loading compression types into combo box + + ComboBox_SetCurSel(itemptr, 0); // First Selection? + + itemptr = NULL; + + + + CheckDlgButton(conversionboxwindow, IDC_0408, FALSE); // Start unchecked + + + + return; + +} // END ConversionBoxDisplay() + + + + + +BOOL CALLBACK ConversionBoxCallback(HWND window, + + UINT msg, + + WPARAM param, + + LPARAM param2) { + + switch(msg) { + + case WM_INITDIALOG: + + conversionboxwindow = window; + + ConversionBoxDisplay(); // Final touches to this window + + return(FALSE); // Let Windows display this window + + break; + + + + case WM_CLOSE: // The "X" in the upper right corner was hit. + + ConversionBoxCancelEvent(); + + return(TRUE); + + break; + + + + case WM_COMMAND: + + switch(LOWORD(param)) { + + case IDC_0402: // Filename Edit Box + + ConversionBoxFileEvent(); // Describe the File's current type... + + return(FALSE); // Let Windows edit the text. + + break; + + + + case IDC_0403: // "Browse" Button + + ConversionBoxBrowseEvent(); + + return(TRUE); + + break; + + + + case IDC_0409: // "Change File" Button + + ConversionBoxOKEvent(); + + return(TRUE); + + break; + + + + case IDC_0410: // "Cancel" Button + + ConversionBoxCancelEvent(); + + return(TRUE); + + break; + + } // ENDSWITCH param- Which object got the message? + + } // ENDSWITCH msg- what message has been sent to this window? + + + + return(FALSE); + +} // END ConversionBoxEventLoop() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.h b/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.h new file mode 100644 index 0000000..91a7ffe --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/conversionbox.h @@ -0,0 +1,40 @@ +/* conversionbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CONVERSIONBOX_H +#define CONVERSIONBOX_H + + +#include // HWND + + +extern HWND conversionboxwindow; + +extern void ConversionBoxDestroy(); +extern void ConversionBoxRefocus(); +extern void ConversionBoxDisplay(); +extern BOOL CALLBACK ConversionBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2); + + +#endif /* CONVERSIONBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/device.c b/plugins/cdvd/CDVDisoEFP/src/Win32/device.c new file mode 100644 index 0000000..2b45636 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/device.c @@ -0,0 +1,586 @@ +/* device.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include // IOCTL_CDROM..., IOCTL_STORAGE... +#include // IOCTL_DISK... +#include // sprintf() +#include // time_t + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" +#include "conf.h" +#include "CD.h" +#include "DVD.h" +#include "device.h" + + +HANDLE devicehandle; +OVERLAPPED waitevent; + +time_t lasttime; +s32 traystatus; +int traystatusmethod; +s32 disctype; +char tocbuffer[2048]; + + +void DeviceInit() { + devicehandle = NULL; + waitevent.hEvent = NULL; + waitevent.Internal = 0; + waitevent.InternalHigh = 0; + waitevent.Offset = 0; + waitevent.OffsetHigh = 0; + lasttime = 0; + + InitDisc(); +} // END DeviceInit() + + +void InitDisc() { + int i; + + InitCDInfo(); + InitDVDInfo(); + traystatus = CDVD_TRAY_OPEN; + traystatusmethod = 0; // Poll all until one works + disctype = CDVD_TYPE_NODISC; + for(i = 0; i < 2048; i++) tocbuffer[i] = 0; +} // END InitDisc() + + +s32 DiscInserted() { + if(traystatus != CDVD_TRAY_CLOSE) return(-1); + + if(disctype == CDVD_TYPE_ILLEGAL) return(-1); + // if(disctype == CDVD_TYPE_UNKNOWN) return(-1); // Hmm. Let this one through? + if(disctype == CDVD_TYPE_DETCTDVDD) return(-1); + if(disctype == CDVD_TYPE_DETCTDVDS) return(-1); + if(disctype == CDVD_TYPE_DETCTCD) return(-1); + if(disctype == CDVD_TYPE_DETCT) return(-1); + if(disctype == CDVD_TYPE_NODISC) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DiscInserted()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + return(0); +} // END DiscInserted() + + +// Returns errcode (or 0 if successful) +DWORD FinishCommand(BOOL boolresult) { + DWORD errcode; + DWORD waitcode; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: FinishCommand()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(boolresult == TRUE) { + ResetEvent(waitevent.hEvent); + return(0); + } // ENDIF- Device is ready? Say so. + + errcode = GetLastError(); + if(errcode == ERROR_IO_PENDING) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: Waiting for completion."); +#endif /* VERBOSE_FUNCTION_DEVICE */ + waitcode = WaitForSingleObject(waitevent.hEvent, 10 * 1000); // 10 sec wait + if((waitcode == WAIT_FAILED) || (waitcode == WAIT_ABANDONED)) { + errcode = GetLastError(); + } else if(waitcode == WAIT_TIMEOUT) { + errcode = 21; + CancelIo(devicehandle); // Speculative Line + } else { + ResetEvent(waitevent.hEvent); + return(0); // Success! + } // ENDIF- Trouble waiting? (Or doesn't finish in 5 seconds?) + } // ENDIF- Should we wait for the call to finish? + + ResetEvent(waitevent.hEvent); + return(errcode); +} // END DeviceCommand() + + +s32 DeviceOpen() { + char tempname[256]; + UINT drivetype; + DWORD errcode; + + if(conf.devicename[0] == 0) return(-1); + + if(devicehandle != NULL) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + // InitConf(); + // LoadConf(); // Should be done at least once before this call + + // Root Directory reference + if(conf.devicename[1] == 0) { + sprintf(tempname, "%s:\\", conf.devicename); + } else if((conf.devicename[1] == ':') && (conf.devicename[2] == 0)) { + sprintf(tempname, "%s\\", conf.devicename); + } else { + sprintf(tempname, "%s", conf.devicename); + } // ENDIF- Not a single drive letter? (or a letter/colon?) Copy the name in. + + drivetype = GetDriveType(tempname); + if(drivetype != DRIVE_CDROM) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Not a CD-ROM!"); + PrintLog("CDVDiso device: (Came back: %u)", drivetype); + errcode = GetLastError(); + if(errcode > 0) PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Not a CD-ROM? Say so! + // Hmm. Do we want to include DRIVE_REMOVABLE... just in case? + + // Device Reference + if(conf.devicename[1] == 0) { + sprintf(tempname, "\\\\.\\%s:", conf.devicename); + } else if((conf.devicename[1] == ':') && (conf.devicename[2] == 0)) { + sprintf(tempname, "\\\\.\\%s", conf.devicename); + } else { + sprintf(tempname, "%s", conf.devicename); + } // ENDIF- Not a single drive letter? (or a letter/colon?) Copy the name in. + + devicehandle = CreateFile(tempname, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + + if(devicehandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Couldn't open device read-only! Read-Write perhaps?"); + errcode = GetLastError(); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + devicehandle = CreateFile(tempname, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + } // ENDIF- Couldn't open for read? Try read/write (for those drives that insist) + + if(devicehandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Couldn't open device!"); + errcode = GetLastError(); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + devicehandle = NULL; + return(-1); + } // ENDIF- Couldn't open that way either? Abort. + + waitevent.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if(waitevent.hEvent == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Couldn't open event handler!"); + errcode = GetLastError(); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + waitevent.hEvent = NULL; + CloseHandle(devicehandle); + devicehandle = NULL; + } // ENDIF- Couldn't create an "Wait for I/O" handle? Abort. + + // More here... DeviceIoControl? for Drive Capabilities + // DEVICE_CAPABILITIES? + + ////// Should be done just after the first DeviceOpen(); + // InitDisc(); // ? + // DeviceTrayStatus(); + + return(0); +} // END DeviceOpen() + + +void DeviceClose() { + if(devicehandle == NULL) return; + + if(devicehandle == INVALID_HANDLE_VALUE) { + devicehandle = NULL; + return; + } // ENDIF- Bad value? Just clear the value. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(waitevent.hEvent != NULL) { + if(waitevent.hEvent != INVALID_HANDLE_VALUE) { + CancelIo(devicehandle); + CloseHandle(waitevent.hEvent); + } // ENDIF- Is this handle actually open? + waitevent.hEvent = NULL; + waitevent.Offset = 0; + waitevent.OffsetHigh = 0; + } // ENDIF- Reset the event handle? + + CloseHandle(devicehandle); + devicehandle = NULL; + return; +} // END DeviceClose() + + +s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDreadTrack(lsn, mode, buffer)); + } else { + return(CDreadTrack(lsn, mode, buffer)); + } // ENDIF- Is this a DVD? +} // END DeviceReadTrack() + + +s32 DeviceBufferOffset() { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(0); + } else { + return(CDgetBufferOffset()); + } // ENDIF- Is this a DVD? + + return(-1); +} // END DeviceBufferOffset() + + +s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTD(track, cdvdtd)); + } else { + return(CDgetTD(track, cdvdtd)); + } // ENDIF- Is this a DVD? + + return(-1); +} // END DeviceGetTD() + + +s32 DeviceGetDiskType() { + s32 s32result; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_OPEN) return(disctype); + + if(disctype != CDVD_TYPE_NODISC) return(disctype); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceGetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + disctype = CDVD_TYPE_DETCT; + + s32result = DVDgetDiskType(); + if(s32result != -1) return(disctype); + + s32result = CDgetDiskType(); + if(s32result != -1) return(disctype); + + disctype = CDVD_TYPE_UNKNOWN; + return(disctype); +} // END DeviceGetDiskType() + + +BOOL DeviceTrayStatusStorage() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + // Note: Unlike other calls, CHECK_VERIFY is not waited on. At this point, + // this is the only way to detect if a disc is ready for action. + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = GetLastError(); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Trouble detecting drive status (STORAGE)!"); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusStorage() + + +BOOL DeviceTrayStatusCDRom() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + // Note: Unlike other calls, CHECK_VERIFY is not waited on. At this point, + // this is the only way to detect if a disc is ready for action. + + boolresult = DeviceIoControl(devicehandle, + IOCTL_CDROM_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = GetLastError(); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Trouble detecting drive status (CDROM)!"); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusCDRom() + + +BOOL DeviceTrayStatusDisk() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + // Note: Unlike other calls, CHECK_VERIFY is not waited on. At this point, + // this is the only way to detect if a disc is ready for action. + + boolresult = DeviceIoControl(devicehandle, + IOCTL_DISK_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = GetLastError(); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Trouble detecting drive status (DISK)!"); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusDisk() + + +s32 DeviceTrayStatus() { + BOOL boolresult; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceTrayStatus()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + switch(traystatusmethod) { + case 1: + boolresult = DeviceTrayStatusStorage(); + break; + case 2: + boolresult = DeviceTrayStatusCDRom(); + break; + case 3: + boolresult = DeviceTrayStatusDisk(); + break; + default: + boolresult = FALSE; + break; + } // ENDSWITCH traystatusmethod- One method already working? Try it again. + + if(boolresult == FALSE) { + traystatusmethod = 0; + boolresult = DeviceTrayStatusStorage(); + if(boolresult == TRUE) { + traystatusmethod = 1; + } else { + boolresult = DeviceTrayStatusCDRom(); + if(boolresult == TRUE) { + traystatusmethod = 2; + } else { + boolresult = DeviceTrayStatusDisk(); + if(boolresult == TRUE) traystatusmethod = 3; + } // ENDIF- Did we succeed with CDRom? + } // ENDIF- Did we succeed with Storage? + } // Single call to already working test just failed? Test them all. + + if(boolresult == FALSE) { + if(traystatus == CDVD_TRAY_CLOSE) { + traystatus = CDVD_TRAY_OPEN; + DeviceClose(); + DeviceOpen(); + InitDisc(); + } // ENDIF- Just opened? clear disc info + return(traystatus); + } // ENDIF- Still failed? Assume no disc in drive then. + + if(traystatus == CDVD_TRAY_OPEN) { + traystatus = CDVD_TRAY_CLOSE; + DeviceGetDiskType(); + return(traystatus); + } // ENDIF- Just closed? Get disc information + + return(traystatus); +} // END DeviceTrayStatus() + + +s32 DeviceTrayOpen() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_OPEN) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceOpenTray()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_EJECT_MEDIA, + NULL, + 0, + NULL, + 0, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Couldn't signal media to eject! (STORAGE)"); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_DISK_EJECT_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- Storage Call failed? Try Disk call. + +// if(boolresult == FALSE) { +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDiso device: Couldn't signal media to eject! (DISK)"); +// PrintError("CDVDiso device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Disk Call failed as well? Give it up. + + return(0); +} // END DeviceTrayOpen() + + +s32 DeviceTrayClose() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_CLOSE) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDiso device: DeviceCloseTray()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_LOAD_MEDIA, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDiso device: Couldn't signal media to load! (STORAGE)"); + PrintError("CDVDiso device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_CDROM_LOAD_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- Storage call failed. CDRom call? + +// if(boolresult == FALSE) { +// errcode = GetLastError(); +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDiso device: Couldn't signal media to load! (CDROM)"); +// PrintError("CDVDiso device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_DISK_LOAD_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- CDRom call failed. Disk call? + +// if(boolresult == FALSE) { +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDiso device: Couldn't signal media to load! (DISK)"); +// PrintError("CDVDiso device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Media not available? + + return(0); +} // END DeviceTrayClose() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/device.h b/plugins/cdvd/CDVDisoEFP/src/Win32/device.h new file mode 100644 index 0000000..608f13d --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/device.h @@ -0,0 +1,64 @@ +/* device.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + + +#include // BOOL, DWORD + +#include // time_t + +#define CDVDdefs +#include "../PS2Edefs.h" + + +// #define VERBOSE_FUNCTION_DEVICE +// #define VERBOSE_WARNING_DEVICE +#define VERBOSE_DISC_TYPE +#define VERBOSE_DISC_INFO + + +extern HANDLE devicehandle; +extern OVERLAPPED waitevent; + +extern time_t lasttime; +extern s32 traystatus; +extern s32 disctype; +extern char tocbuffer[]; + + +extern void DeviceInit(); +extern void InitDisc(); +extern s32 DiscInserted(); +extern DWORD FinishCommand(BOOL boolresult); + +extern s32 DeviceOpen(); +extern void DeviceClose(); +extern s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DeviceBufferOffset(); +extern s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd); +extern s32 DeviceGetDiskType(); +extern s32 DeviceTrayStatus(); +extern s32 DeviceTrayOpen(); +extern s32 DeviceTrayClose(); + + +#endif /* __DEVICE_H__ */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.c b/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.c new file mode 100644 index 0000000..c5c25fc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.c @@ -0,0 +1,818 @@ +/* devicebox.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + +#include // ComboBox_AddString() + +#include // NULL + + + +#include // sprintf() + +#include // strcpy() + +#include // stat() + +#include // stat() + +#include // stat() + + + +#define CDVDdefs + +#include "PS2Edefs.h" + + + +#include "conf.h" + +#include "device.h" + +#include "isofile.h" + +#include "isocompress.h" // compressdesc[] + +// #include "imagetype.h" // imagedata[].name + +#include "multifile.h" // multinames[] + +#include "toc.h" + +#include "progressbox.h" + +#include "mainbox.h" + +#include "screens.h" + +#include "devicebox.h" + + + + + +HWND deviceboxwindow; + + + + + +void DeviceBoxDestroy() { + + if(deviceboxwindow != NULL) { + + EndDialog(deviceboxwindow, FALSE); + + deviceboxwindow = NULL; + + } // ENDIF- Do we have a Main Window still? + +} // END DeviceBoxDestroy() + + + + + +void DeviceBoxUnfocus() { + + // gtk_widget_set_sensitive(devicebox.device, FALSE); + + // gtk_widget_set_sensitive(devicebox.file, FALSE); + + // gtk_widget_set_sensitive(devicebox.selectbutton, FALSE); + + // gtk_widget_set_sensitive(devicebox.compress, FALSE); + + // gtk_widget_set_sensitive(devicebox.multi, FALSE); + + // gtk_widget_set_sensitive(devicebox.okbutton, FALSE); + + // gtk_widget_set_sensitive(devicebox.cancelbutton, FALSE); + + ShowWindow(deviceboxwindow, SW_HIDE); + +} // END DeviceBoxUnfocus() + + + + + +void DeviceBoxDeviceEvent() { + + char tempdevice[256]; + + struct stat filestat; + + int returnval; + + + + GetDlgItemText(deviceboxwindow, IDC_0302, tempdevice, 256); + + returnval = stat(tempdevice, &filestat); + + if(returnval == -1) { + + SetDlgItemText(deviceboxwindow, IDC_0303, "Device Type: ---"); + + return; + + } // ENDIF- Not a name of any sort? + + + + if(S_ISDIR(filestat.st_mode) != 0) { + + SetDlgItemText(deviceboxwindow, IDC_0303, "Device Type: Not a device"); + + return; + + } // ENDIF- Not a regular file? + + + + SetDlgItemText(deviceboxwindow, IDC_0303, "Device Type: Device Likely"); + + return; + +} // END DeviceBoxDeviceEvent() + + + + + +void DeviceBoxFileEvent() { + + int returnval; + + char templine[256]; + + struct IsoFile *tempfile; + + + + GetDlgItemText(deviceboxwindow, IDC_0305, templine, 256); + + returnval = IsIsoFile(templine); + + if(returnval == -1) { + + SetDlgItemText(deviceboxwindow, IDC_0307, "File Type: ---"); + + return; + + } // ENDIF- Not a name of any sort? + + + + if(returnval == -2) { + + SetDlgItemText(deviceboxwindow, IDC_0307, "File Type: Not a file"); + + return; + + } // ENDIF- Not a regular file? + + + + if(returnval == -3) { + + SetDlgItemText(deviceboxwindow, IDC_0307, "File Type: Not a valid image file"); + + return; + + } // ENDIF- Not an image file? + + + + if(returnval == -4) { + + SetDlgItemText(deviceboxwindow, IDC_0307, "File Type: Missing Table File (will rebuild)"); + + return; + + } // ENDIF- Not a regular file? + + + + tempfile = IsoFileOpenForRead(templine); + + sprintf(templine, "File Type: %s%s%s", + + multinames[tempfile->multi], + + tempfile->imagename, + + compressdesc[tempfile->compress]); + + SetDlgItemText(deviceboxwindow, IDC_0307, templine); + + tempfile = IsoFileClose(tempfile); + + return; + +} // END DeviceBoxFileEvent() + + + + + +void DeviceBoxRefocus() { + + DeviceBoxDeviceEvent(); + + DeviceBoxFileEvent(); + + + + // gtk_widget_set_sensitive(devicebox.device, TRUE); + + // gtk_widget_set_sensitive(devicebox.file, TRUE); + + // gtk_widget_set_sensitive(devicebox.selectbutton, TRUE); + + // gtk_widget_set_sensitive(devicebox.compress, TRUE); + + // gtk_widget_set_sensitive(devicebox.multi, TRUE); + + // gtk_widget_set_sensitive(devicebox.okbutton, TRUE); + + // gtk_widget_set_sensitive(devicebox.cancelbutton, TRUE); + + // gtk_window_set_focus(GTK_WINDOW(devicebox.window), devicebox.file); + + ShowWindow(deviceboxwindow, SW_SHOW); + + SetActiveWindow(deviceboxwindow); + +} // END DeviceBoxRefocus() + + + + + +void DeviceBoxCancelEvent() { + + // ShowWindow(deviceboxwindow, SW_HIDE); + + DeviceBoxDestroy(); + + MainBoxRefocus(); + + return; + +} // END DeviceBoxCancelEvent() + + + + + +void DeviceBoxOKEvent() { + + char templine[256]; + + u8 tempbuffer[2352]; + + struct IsoFile *tofile; + + s32 retval; + + cdvdTD cdvdtd; + + int stop; + + HWND tempitem; + + int compressmethod; + + int multi; + + int imagetype; + + int i; + + + + DeviceBoxUnfocus(); + + + + GetDlgItemText(deviceboxwindow, IDC_0302, conf.devicename, 256); + + retval = DeviceOpen(); + + if(retval != 0) { + + DeviceClose(); + + DeviceBoxRefocus(); + + MessageBox(deviceboxwindow, + + "Could not open the device", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Trouble opening device? Abort here. + + + + DeviceTrayStatus(); + + retval = DiscInserted(); + + if(retval != 0) { + + DeviceClose(); + + DeviceBoxRefocus(); + + MessageBox(deviceboxwindow, + + "No disc in the device\r\nPlease put a disc in and try again.", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Trouble opening device? Abort here. + + + + retval = DeviceGetTD(0, &cdvdtd); // Fish for Ending Sector + + if(retval < 0) { + + DeviceClose(); + + DeviceBoxRefocus(); + + MessageBox(deviceboxwindow, + + "Could not retrieve disc sector size", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Trouble getting disc sector count? + + + + tempitem = GetDlgItem(deviceboxwindow, IDC_0309); + + compressmethod = ComboBox_GetCurSel(tempitem); + + tempitem = NULL; + + if(compressmethod > 0) compressmethod += 2; + + + + multi = 0; + + if(IsDlgButtonChecked(deviceboxwindow, IDC_0311)) multi = 1; + + + + imagetype = 0; + + if((disctype != CDVD_TYPE_PS2DVD) && + + (disctype != CDVD_TYPE_DVDV)) imagetype = 8; + + + + GetDlgItemText(deviceboxwindow, IDC_0305, templine, 256); + + tofile = IsoFileOpenForWrite(templine, + + imagetype, + + multi, + + compressmethod); + + if(tofile == NULL) { + + DeviceClose(); + + DeviceBoxRefocus(); + + MessageBox(deviceboxwindow, + + "Could not create the new ISO file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + return; + + } // ENDIF- Trouble opening the ISO file? + + + + // Open Progress Bar + + sprintf(templine, "%s -> %s", conf.devicename, tofile->name); + + ProgressBoxStart(templine, (off64_t) cdvdtd.lsn); + + + + tofile->cdvdtype = disctype; + + for(i = 0; i < 2048; i++) tofile->toc[i] = tocbuffer[i]; + + + + stop = 0; + + mainboxstop = 0; + + progressboxstop = 0; + + while((stop == 0) && (tofile->sectorpos < cdvdtd.lsn)) { + + if(imagetype == 0) { + + retval = DeviceReadTrack((u32) tofile->sectorpos, + + CDVD_MODE_2048, + + tempbuffer); + + } else { + + retval = DeviceReadTrack((u32) tofile->sectorpos, + + CDVD_MODE_2352, + + tempbuffer); + + } // ENDIF- Are we reading a DVD sector? (Or a CD sector?) + + if(retval < 0) { + + for(i = 0; i < 2352; i++) { + + tempbuffer[i] = 0; + + } // NEXT i- Zeroing the buffer + + } // ENDIF- Trouble reading next block? + + retval = IsoFileWrite(tofile, tempbuffer); + + if(retval < 0) { + + MessageBox(deviceboxwindow, + + "Trouble writing new file", + + "CDVDisoEFP Message", + + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + + stop = 1; + + } // ENDIF- Trouble writing out the next block? + + + + ProgressBoxTick(tofile->sectorpos); + + + + if(mainboxstop != 0) stop = 2; + + if(progressboxstop != 0) stop = 2; + + } // ENDWHILE- No reason found to stop... + + + + ProgressBoxStop(); + + + + if(stop == 0) { + + if(tofile->multi == 1) tofile->name[tofile->multipos] = '0'; // First file + + strcpy(templine, tofile->name); + + } // ENDIF- Did we succeed with the transfer? + + + + DeviceClose(); + + if(stop == 0) { + + IsoSaveTOC(tofile); + + tofile = IsoFileClose(tofile); + + SetDlgItemText(mainboxwindow, IDC_0202, templine); + + } else { + + tofile = IsoFileCloseAndDelete(tofile); + + } // ENDIF- (Failed to complete writing file? Get rid of the garbage files.) + + + + DeviceBoxRefocus(); + + if(stop == 0) DeviceBoxCancelEvent(); + + return; + +} // END DeviceBoxOKEvent() + + + + + +void DeviceBoxBrowseEvent() { + + OPENFILENAME filebox; + + char newfilename[256]; + + BOOL returnbool; + + + + filebox.lStructSize = sizeof(filebox); + + filebox.hwndOwner = deviceboxwindow; + + filebox.hInstance = NULL; + + filebox.lpstrFilter = fileselection; + + filebox.lpstrCustomFilter = NULL; + + filebox.nFilterIndex = 0; + + filebox.lpstrFile = newfilename; + + filebox.nMaxFile = 256; + + filebox.lpstrFileTitle = NULL; + + filebox.nMaxFileTitle = 0; + + filebox.lpstrInitialDir = NULL; + + filebox.lpstrTitle = NULL; + + filebox.Flags = OFN_PATHMUSTEXIST + + | OFN_NOCHANGEDIR + + | OFN_HIDEREADONLY; + + filebox.nFileOffset = 0; + + filebox.nFileExtension = 0; + + filebox.lpstrDefExt = NULL; + + filebox.lCustData = 0; + + filebox.lpfnHook = NULL; + + filebox.lpTemplateName = NULL; + + + + GetDlgItemText(deviceboxwindow, IDC_0305, newfilename, 256); + + returnbool = GetOpenFileName(&filebox); + + if(returnbool != FALSE) { + + SetDlgItemText(deviceboxwindow, IDC_0305, newfilename); + + } // ENDIF- User actually selected a name? Save it. + + + + return; + +} // END DeviceBoxBrowseEvent() + + + + + +void DeviceBoxDisplay() { + + char templine[256]; + + HWND itemptr; + + int itemcount; + + + + // Adjust Window Position? + + + + SetDlgItemText(deviceboxwindow, IDC_0302, conf.devicename); + + + + // DeviceBoxDeviceEvent(); // Needed? + + + + GetDlgItemText(mainboxwindow, IDC_0202, templine, 256); + + SetDlgItemText(deviceboxwindow, IDC_0305, templine); + + + + // DeviceBoxFileEvent(); // Needed? + + + + itemptr = GetDlgItem(deviceboxwindow, IDC_0309); // Compression Combo + + itemcount = 0; + + while(compressnames[itemcount] != NULL) { + + ComboBox_AddString(itemptr, compressnames[itemcount]); + + itemcount++; + + } // ENDWHILE- loading compression types into combo box + + ComboBox_SetCurSel(itemptr, 0); // First Selection? + + itemptr = NULL; + + + + CheckDlgButton(deviceboxwindow, IDC_0311, FALSE); // Start unchecked + + + + DeviceInit(); // Initialize device access + +} // END DeviceBoxDisplay() + + + + + +BOOL CALLBACK DeviceBoxCallback(HWND window, + + UINT msg, + + WPARAM param, + + LPARAM param2) { + + switch(msg) { + + case WM_INITDIALOG: + + deviceboxwindow = window; + + DeviceBoxDisplay(); // Final touches to this window + + return(FALSE); // Let Windows display this window + + break; + + + + case WM_CLOSE: // The "X" in the upper right corner was hit. + + DeviceBoxCancelEvent(); + + return(TRUE); + + break; + + + + case WM_COMMAND: + + switch(LOWORD(param)) { + + case IDC_0302: // Device Edit Box + + DeviceBoxDeviceEvent(); + + return(FALSE); + + break; + + + + case IDC_0305: // Filename Edit Box + + DeviceBoxFileEvent(); + + return(FALSE); + + break; + + + + case IDC_0306: // "Browse" Button + + DeviceBoxBrowseEvent(); + + return(TRUE); + + break; + + + + case IDC_0312: // "Make File" Button + + DeviceBoxOKEvent(); + + return(TRUE); + + break; + + + + case IDC_0313: // "Cancel" Button + + DeviceBoxCancelEvent(); + + return(TRUE); + + break; + + } // ENDSWITCH param- Which object got the message? + + } // ENDSWITCH msg- What message has been sent to this window? + + + + return(FALSE); + +} // END DeviceBoxCallback() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.h b/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.h new file mode 100644 index 0000000..bf699f5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/devicebox.h @@ -0,0 +1,41 @@ +/* devicebox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef DEVICEBOX_H +#define DEVICEBOX_H + + +#include // HWND + + +extern HWND deviceboxwindow; + +extern void DeviceBoxDestroy(); +// extern void DeviceBoxUnfocus(); +extern void DeviceBoxRefocus(); +extern void DeviceBoxDisplay(); +extern BOOL CALLBACK DeviceBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2); + + +#endif /* DEVICEBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.c b/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.c new file mode 100644 index 0000000..28f82eb --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.c @@ -0,0 +1,119 @@ +/* logfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include + +// #include // open() +// #include // mkdir() +#include // NULL +#include // vsprintf() +#include // va_start(), va_end(), vsprintf() +// #include // open() +// #include // open() + +#include "logfile.h" + + +HANDLE logfile; +char logfiletemp[2048]; + + +void InitLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + CreateDirectory("logs", NULL); + + DeleteFile("logs\\CDVDlog.txt"); + logfile = NULL; +#endif /* VERBOSE LOGFILE */ +} // END InitLog(); + + +int OpenLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + logfile = CreateFile("logs\\CDVDlog.txt", + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(logfile == INVALID_HANDLE_VALUE) { + logfile = NULL; + return(-1); + } // ENDIF- Failed to open? Say so. +#endif /* VERBOSE LOGFILE */ + + return(0); +} // END OpenLog(); + + +void CloseLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + if(logfile != NULL) { + CloseHandle(logfile); + logfile = NULL; + } // ENDIF- Is the log file actually open? Close it. +#endif /* VERBOSE LOGFILE */ +} // END CloseLog() + + +void PrintLog(const char *fmt, ...) { + DWORD byteswritten; + + // Token comment line +#ifdef VERBOSE_LOGFILE + va_list list; + int len; + + if(logfile == NULL) return; // Log file not open... yet. + + va_start(list, fmt); + vsprintf(logfiletemp, fmt, list); + va_end(list); + + len = 0; + while((len < 2048) && (logfiletemp[len] != 0)) len++; + if((len > 0) && (logfiletemp[len-1] == '\n')) len--; + if((len > 0) && (logfiletemp[len-1] == '\r')) len--; + logfiletemp[len] = 0; // Slice off the last "\r\n"... + + WriteFile(logfile, logfiletemp, len, &byteswritten, NULL); + WriteFile(logfile, "\r\n", 2, &byteswritten, NULL); +#endif /* VERBOSE LOGFILE */ +} // END PrintLog() + +void PrintError(const char *header, DWORD errcode) { +#ifdef VERBOSE_LOGFILE + TCHAR errmsg[256]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 80, + NULL, + errcode, + 0, + errmsg, + 256, + NULL); + PrintLog("%s: (%u) %s", header, errcode, errmsg); +#endif /* VERBOSE_WARNING_DEVICE */ +} // END PrintError() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.h b/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.h new file mode 100644 index 0000000..ff6e3b0 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/logfile.h @@ -0,0 +1,39 @@ +/* logfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef LOGFILE_H +#define LOGFILE_H + + +#include // Just for DWORD + + +#define VERBOSE_LOGFILE + + +extern void InitLog(); +extern int OpenLog(); +extern void CloseLog(); +extern void PrintLog(const char *format, ...); +extern void PrintError(const char *header, DWORD errcode); + + +#endif /* LOGFILE_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.c b/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.c new file mode 100644 index 0000000..fe54884 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.c @@ -0,0 +1,309 @@ +/* mainbox.c + * Copyright (C) 2002-2005 CDVDiso Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include // Button_ +#include // NULL + +#include // sprintf() +#include // strcpy() + +#include "conf.h" +#include "isofile.h" +#include "isocompress.h" // compressdesc[] +// #include "imagetype.h" // imagedata[].name +#include "multifile.h" // multinames[] +#include "tablerebuild.h" // IsoTableRebuild() +#include "devicebox.h" +#include "conversionbox.h" +#include "progressbox.h" +#include "screens.h" // DLG_, IDC_ +#include "CDVDiso.h" // progmodule +#include "mainbox.h" + + +const char fileselection[] = "\Disc Image Files (*.bin,*.img,*.iso,*.nrg)\0*.bin;*.img;*.iso;*.nrg\0\All Files (*.*)\0*.*\0\\0\0"; + + +HWND mainboxwindow; +int mainboxstop; + + +void MainBoxDestroy() { + if(progressboxwindow != NULL) { + ProgressBoxDestroy(); + } // ENDIF- Do we have a Progress Window still? + + if(mainboxwindow != NULL) { + EndDialog(mainboxwindow, FALSE); + mainboxwindow = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MainBoxDestroy() + + +void MainBoxUnfocus() { + // EnableWindow(?) + // gtk_widget_set_sensitive(mainbox.file, FALSE); + // gtk_widget_set_sensitive(mainbox.selectbutton, FALSE); + // gtk_widget_set_sensitive(mainbox.okbutton, FALSE); + // gtk_widget_set_sensitive(mainbox.devbutton, FALSE); + // gtk_widget_set_sensitive(mainbox.convbutton, FALSE); + ShowWindow(mainboxwindow, SW_HIDE); +} // END MainBoxUnfocus() + + +void MainBoxFileEvent() { + int returnval; + char templine[256]; + struct IsoFile *tempfile; + + GetDlgItemText(mainboxwindow, IDC_0202, templine, 256); + returnval = IsIsoFile(templine); + if(returnval == -1) { + SetDlgItemText(mainboxwindow, IDC_0204, "File Type: ---"); + return; + } // ENDIF- Not a name of any sort? + + if(returnval == -2) { + SetDlgItemText(mainboxwindow, IDC_0204, "File Type: Not a file"); + return; + } // ENDIF- Not a regular file? + + if(returnval == -3) { + SetDlgItemText(mainboxwindow, IDC_0204, "File Type: Not a valid image file"); + return; + } // ENDIF- Not an Image file? + + if(returnval == -4) { + SetDlgItemText(mainboxwindow, IDC_0204, "File Type: Missing Table File (will rebuild)"); + return; + } // ENDIF- Missing Compression seek table? + + tempfile = IsoFileOpenForRead(templine); + sprintf(templine, "File Type: %s%s%s", + multinames[tempfile->multi], + tempfile->imagename, + compressdesc[tempfile->compress]); + SetDlgItemText(mainboxwindow, IDC_0204, templine); + tempfile = IsoFileClose(tempfile); + return; +} // END MainBoxFileEvent() + + +void MainBoxRefocus() { + MainBoxFileEvent(); + + // gtk_widget_set_sensitive(mainbox.file, TRUE); + // gtk_widget_set_sensitive(mainbox.selectbutton, TRUE); + // gtk_widget_set_sensitive(mainbox.okbutton, TRUE); + // gtk_widget_set_sensitive(mainbox.devbutton, TRUE); + // gtk_widget_set_sensitive(mainbox.convbutton, TRUE); + // gtk_window_set_focus(GTK_WINDOW(mainbox.window), mainbox.file); + // ShowWindow(mainboxwindow, SW_RESTORE); // and/or, SW_SHOW? SW_SHOWNORMAL? + ShowWindow(mainboxwindow, SW_SHOW); + SetActiveWindow(mainboxwindow); +} // END MainBoxRefocus() + + +void MainBoxCancelEvent() { + mainboxstop = 1; // Halt all long processess... + + MainBoxDestroy(); + return; +} // END MainBoxCancelEvent() + + +void MainBoxOKEvent() { + char tempisoname[256]; + + MainBoxUnfocus(); + + GetDlgItemText(mainboxwindow, IDC_0202, tempisoname, 256); + if(*(tempisoname) != 0) { + if(IsIsoFile(tempisoname) == -4) { + IsoTableRebuild(tempisoname); + MainBoxRefocus(); + return; + } // ENDIF- Do we need to rebuild an image file's index before using it? + + if(IsIsoFile(tempisoname) < 0) { + MainBoxRefocus(); + MessageBox(mainboxwindow, + "Not a Valid Image File.", + "CDVDisoEFP Message", + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + return; + } // ENDIF- Not an ISO file? Message and Stop here. + } // ENDIF- Do we have a name to check out? + + strcpy(conf.isoname, tempisoname); + if(Button_GetCheck(GetDlgItem(mainboxwindow, IDC_0209)) == BST_UNCHECKED) { + conf.startconfigure = 0; // FALSE + } else { + conf.startconfigure = 1; // TRUE + } // ENDIF- Was this checkbox unchecked? + if(Button_GetCheck(GetDlgItem(mainboxwindow, IDC_0210)) == BST_UNCHECKED) { + conf.restartconfigure = 0; // FALSE + } else { + conf.restartconfigure = 1; // TRUE + } // ENDIF- Was this checkbox unchecked? + SaveConf(); + + MainBoxCancelEvent(); + return; +} // END MainBoxOKEvent() + + +void MainBoxBrowseEvent() { + OPENFILENAME filebox; + char newfilename[256]; + BOOL returnbool; + + filebox.lStructSize = sizeof(filebox); + filebox.hwndOwner = mainboxwindow; + filebox.hInstance = NULL; + filebox.lpstrFilter = fileselection; + filebox.lpstrCustomFilter = NULL; + filebox.nFilterIndex = 0; + filebox.lpstrFile = newfilename; + filebox.nMaxFile = 256; + filebox.lpstrFileTitle = NULL; + filebox.nMaxFileTitle = 0; + filebox.lpstrInitialDir = NULL; + filebox.lpstrTitle = NULL; + filebox.Flags = OFN_FILEMUSTEXIST + | OFN_NOCHANGEDIR + | OFN_HIDEREADONLY; + filebox.nFileOffset = 0; + filebox.nFileExtension = 0; + filebox.lpstrDefExt = NULL; + filebox.lCustData = 0; + filebox.lpfnHook = NULL; + filebox.lpTemplateName = NULL; + + GetDlgItemText(mainboxwindow, IDC_0202, newfilename, 256); + returnbool = GetOpenFileName(&filebox); + if(returnbool != FALSE) { + SetDlgItemText(mainboxwindow, IDC_0202, newfilename); + } // ENDIF- User actually selected a name? Save it. + + return; +} // END MainBoxBrowseEvent() + + +void MainBoxDeviceEvent() { + MainBoxUnfocus(); + + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0300), + mainboxwindow, + (DLGPROC)DeviceBoxCallback); + return; +} // END MainBoxBrowseEvent() + + +void MainBoxConversionEvent() { + MainBoxUnfocus(); + + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0400), + mainboxwindow, + (DLGPROC)ConversionBoxCallback); + return; +} // END MainBoxBrowseEvent() + + +void MainBoxDisplay() { + LoadConf(); + + // Adjust window position? + + // We held off setting the name until now... so description would show. + SetDlgItemText(mainboxwindow, IDC_0202, conf.isoname); + if(conf.startconfigure == 0) { + Button_SetCheck(GetDlgItem(mainboxwindow, IDC_0209), BST_UNCHECKED); + } else { + Button_SetCheck(GetDlgItem(mainboxwindow, IDC_0209), BST_CHECKED); + } // ENDIF- Do we need to uncheck this box? + if(conf.restartconfigure == 0) { + Button_SetCheck(GetDlgItem(mainboxwindow, IDC_0210), BST_UNCHECKED); + } else { + Button_SetCheck(GetDlgItem(mainboxwindow, IDC_0210), BST_CHECKED); + } // ENDIF- Do we need to uncheck this box? + + // First Time - Show the window + ShowWindow(mainboxwindow, SW_SHOWNORMAL); +} // END MainBoxDisplay() + + +BOOL CALLBACK MainBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2) { + switch(msg) { + case WM_INITDIALOG: + mainboxwindow = window; + MainBoxDisplay(); // In this case, final touches to this window. + ProgressBoxDisplay(); // Create the Progress Box at this time. + return(FALSE); // And let Windows display this window. + break; + + case WM_CLOSE: // The "X" in the upper right corner was hit. + MainBoxCancelEvent(); + return(TRUE); + break; + + case WM_COMMAND: + // Do we wish to capture 'ENTER/RETURN' and/or 'ESC' here? + + switch(LOWORD(param)) { + case IDC_0202: // Filename Edit Box + MainBoxFileEvent(); // Describe the File's type... + return(FALSE); // Let Windows handle the actual 'edit' processing... + break; + + case IDC_0203: // "Browse" Button + MainBoxBrowseEvent(); + return(TRUE); + break; + + case IDC_0205: // "Ok" Button + MainBoxOKEvent(); + return(TRUE); + break; + + case IDC_0206: // "Get from Disc" Button + MainBoxDeviceEvent(); + return(TRUE); + break; + + case IDC_0207: // "Convert" Button + MainBoxConversionEvent(); + return(TRUE); + break; + + case IDC_0208: // "Cancel" Button + MainBoxCancelEvent(); + return(TRUE); + break; + } // ENDSWITCH param- Which object got the message? + } // ENDSWITCH msg- what message has been sent to this window? + + return(FALSE); // Not a recognized message? Tell Windows to handle it. +} // END MainBoxEventLoop() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.h b/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.h new file mode 100644 index 0000000..639c9c9 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/mainbox.h @@ -0,0 +1,43 @@ +/* mainbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef MAINBOX_H +#define MAINBOX_H + + +#include // HWND + + +extern const char fileselection[]; + +extern HWND mainboxwindow; +extern int mainboxstop; + + +extern void MainBoxRefocus(); +extern void MainBoxDisplay(); +extern BOOL CALLBACK MainBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2); + + +#endif /* MAINBOX_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/make.bat b/plugins/cdvd/CDVDisoEFP/src/Win32/make.bat new file mode 100644 index 0000000..fc4b70f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/make.bat @@ -0,0 +1 @@ +mingw32-make -f Makefile.MinGW32 %1 diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/makeming.bat b/plugins/cdvd/CDVDisoEFP/src/Win32/makeming.bat new file mode 100644 index 0000000..5e98853 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/makeming.bat @@ -0,0 +1 @@ +make -f Makefile.MinGW32 %1 diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/plugin.def b/plugins/cdvd/CDVDisoEFP/src/Win32/plugin.def new file mode 100644 index 0000000..d7b55ea --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/plugin.def @@ -0,0 +1,21 @@ +EXPORTS + PS2EgetLibType = PS2EgetLibType@0 @2 + PS2EgetLibName = PS2EgetLibName@0 @3 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4 + CDVDinit = CDVDinit@0 @5 + CDVDshutdown = CDVDshutdown@0 @6 + CDVDopen = CDVDopen@4 @7 + CDVDclose = CDVDclose@0 @8 + CDVDreadTrack = CDVDreadTrack@8 @9 + CDVDgetBuffer = CDVDgetBuffer@0 @10 + CDVDreadSubQ = CDVDreadSubQ@8 @11 + CDVDgetTN = CDVDgetTN@4 @12 + CDVDgetTD = CDVDgetTD@8 @13 + CDVDgetTOC = CDVDgetTOC@4 @14 + CDVDgetDiskType = CDVDgetDiskType@0 @15 + CDVDgetTrayStatus = CDVDgetTrayStatus@0 @16 + CDVDctrlTrayOpen = CDVDctrlTrayOpen@0 @17 + CDVDctrlTrayClose = CDVDctrlTrayClose@0 @18 + CDVDconfigure = CDVDconfigure@0 @19 + CDVDtest = CDVDtest@0 @20 + CDVDabout = CDVDabout@0 @21 diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.c b/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.c new file mode 100644 index 0000000..0666c6e --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.c @@ -0,0 +1,340 @@ +/* progressbox.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include + +#include // Enable_Button() + +#include // NULL + +#include // PBM_... + + + +#include // sprintf() + +#include // strcat() + +#include // off64_t + + + +#include "CDVDiso.h" // progmodule + +#include "screens.h" + +#include "mainbox.h" + +#include "progressbox.h" + + + + + +HWND progressboxwindow; + +HWND progressboxbar; + +int progressboxstop; + + + +off64_t progressboxmax; + +off64_t progressboxlastpct; + +char progressboxline[256]; + +char progressboxmaxchar[16]; + + + + + +void ProgressBoxDestroy() { + + if(progressboxwindow != NULL) { + + DestroyWindow(progressboxwindow); + + progressboxwindow = NULL; + + progressboxbar = NULL; + + } // ENDIF- Do we have a Progress Window still? + + return; + +} // END ProgressBoxDestroy() + + + + + +void ProgressBoxStart(char *description, off64_t maximum) { + + SetDlgItemText(progressboxwindow, IDC_0501, description); + + + + progressboxmax = maximum; + + sprintf(progressboxmaxchar, "%llu", maximum); + + progressboxlastpct = 100; + + progressboxstop = 0; + + + + ProgressBoxTick(0); + + ShowWindow(progressboxwindow, SW_SHOW); + + SetForegroundWindow(progressboxwindow); + + return; + +} // END ProgressBoxStart() + + + + + +void ProgressBoxTick(off64_t current) { + + off64_t thispct; + + MSG msg; + + BOOL returnbool; + + + + sprintf(progressboxline, "%llu of ", current); + + strcat(progressboxline, progressboxmaxchar); + + SetDlgItemText(progressboxwindow, IDC_0503, progressboxline); + + + + if(progressboxmax >= 30000 ) { + + SendMessage(progressboxbar, PBM_SETPOS, current / (progressboxmax / 30000), 0); + + } else { + + SendMessage(progressboxbar, PBM_SETPOS, (current * 30000) / progressboxmax, 0); + + } // ENDIF- Our maximum # over 30000? (Avoiding divide-by-zero error) + + + + if(progressboxmax >= 100) { + + thispct = current / ( progressboxmax / 100 ); + + if(thispct != progressboxlastpct) { + + sprintf(progressboxline, "%llu%% CDVDisoEFP Progress", thispct); + + SetWindowText(progressboxwindow, progressboxline); + + progressboxlastpct = thispct; + + } // ENDIF- Change in percentage? (Avoiding title flicker) + + } // ENDIF- Our maximum # over 100? (Avoiding divide-by-zero error) + + + + returnbool = PeekMessage(&msg, progressboxwindow, 0, 0, PM_REMOVE); + + while(returnbool != FALSE) { + + TranslateMessage(&msg); + + DispatchMessage(&msg); + + returnbool = PeekMessage(&msg, progressboxwindow, 0, 0, PM_REMOVE); + + } // ENDWHILE- Updating the progress window display as needed + + return; + +} // END ProgressBoxTick() + + + + + +void ProgressBoxStop() { + + ShowWindow(progressboxwindow, SW_HIDE); + + SetWindowText(progressboxwindow, "CDVDisoEFP Progress"); + + return; + +} // END ProgressBoxStop() + + + + + +void ProgressBoxCancelEvent() { + + progressboxstop = 1; + + + + return; + +} // END ProgressBoxCancelEvent() + + + + + +BOOL CALLBACK ProgressBoxCallback(HWND window, + + UINT msg, + + WPARAM param, + + LPARAM param2) { + + switch(msg) { + + case WM_INITDIALOG: + + return(TRUE); + + break; + + + + case WM_CLOSE: // The "X" in the upper right corner is hit. + + ProgressBoxCancelEvent(); + + return(TRUE); + + break; + + + + case WM_COMMAND: + + switch(LOWORD(param)) { + + case IDC_0504: + + ProgressBoxCancelEvent(); + + return(TRUE); + + break; + + } // ENDSWITCH param- Which item got the message? + + + + // Hmm. Custom control? (for WM_GETFONT and WM_SETFONT msgs?) + + } // ENDSWITCH msg- what message has been sent to this window? + + + + return(FALSE); // Not a recognized message? Tell Windows to handle it. + +} // ENDIF ProgressBoxCallback() + + + + + +void ProgressBoxDisplay() { + + // ? progressload + + LPARAM range; + + + + InitCommonControls(); + + // progressload. + + // progressload. = ICC_PROGRESS_CLASS + + // InitCommonControlsEx(&progressload); + + + + progressboxwindow = CreateDialog(progmodule, + + MAKEINTRESOURCE(DLG_0500), + + mainboxwindow, + + (DLGPROC) ProgressBoxCallback); + + + + progressboxbar = GetDlgItem(progressboxwindow, IDC_0502); + + range = MAKELPARAM(0, 30000); // Widen the range for granularity + + SendMessage(progressboxbar, PBM_SETRANGE, 0, range); + + + + ShowWindow(progressboxwindow, SW_SHOWNORMAL); + + ShowWindow(progressboxwindow, SW_HIDE); + + return; + +} // END ProgressBoxDisplay() + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.h b/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.h new file mode 100644 index 0000000..c8a2925 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/progressbox.h @@ -0,0 +1,89 @@ +/* progressbox.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef PROGRESSBOX_H + +#define PROGRESSBOX_H + + + + + +#include + + + +#include // off64_t +#include "PS2Etypes.h" + + + + + +extern const char *compressnames[]; + + + +extern HWND progressboxwindow; + +extern int progressboxstop; + + + + + +extern void ProgressBoxStart(char *description, off64_t maximum); + +extern void ProgressBoxTick(off64_t current); + +extern void ProgressBoxStop(); + +extern void ProgressBoxDestroy(); + +extern void ProgressBoxDisplay(); + + + + + +#endif /* MAINBOX_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/screens.h b/plugins/cdvd/CDVDisoEFP/src/Win32/screens.h new file mode 100644 index 0000000..8824d9c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/screens.h @@ -0,0 +1,37 @@ +/* Weditres generated include file. Do NOT edit */ +#include +#define DLG_0100 100 +#define IDC_0104 104 +#define DLG_0200 200 +#define IDC_0202 202 +#define IDC_0203 203 +#define IDC_0204 204 +#define IDC_0205 205 +#define IDC_0206 206 +#define IDC_0207 207 +#define IDC_0208 208 +#define IDC_0209 209 +#define IDC_0210 210 +#define DLG_0300 300 +#define IDC_0302 302 +#define IDC_0303 303 +#define IDC_0305 305 +#define IDC_0306 306 +#define IDC_0307 307 +#define IDC_0309 309 +#define IDC_0311 311 +#define IDC_0312 312 +#define IDC_0313 313 +#define DLG_0400 400 +#define IDC_0402 402 +#define IDC_0403 403 +#define IDC_0404 404 +#define IDC_0406 406 +#define IDC_0408 408 +#define IDC_0409 409 +#define IDC_0410 410 +#define DLG_0500 500 +#define IDC_0501 501 +#define IDC_0502 502 +#define IDC_0503 503 +#define IDC_0504 504 diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/screens.rc b/plugins/cdvd/CDVDisoEFP/src/Win32/screens.rc new file mode 100644 index 0000000..fe5b248 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/screens.rc @@ -0,0 +1,82 @@ +/* Wedit generated resource file */ +#ifdef __LCC__ +#include +#endif +#include "screens.h" + + +DLG_0100 DIALOG 2, 2, 140, 59 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About CDVDisoEFP" +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "EFP Iso CDVD Driver v0.6", 101, 11, 6, 118, 12 + CTEXT "Current Author: efp", 102, 12, 16, 118, 12 + CTEXT "Original code by: linuzappz && shadow", 103, 12, 26, 118, 12 + PUSHBUTTON "Ok", IDC_0104, 50, 37, 40, 14 +END + +DLG_0200 DIALOG 4, 2, 241, 73 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDisoEFP Configuration" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Iso File:", 201, 14, 8, 27, 12 + EDITTEXT IDC_0202, 43, 7, 149, 12, ES_AUTOHSCROLL + PUSHBUTTON "Browse", IDC_0203, 197, 6, 34, 12 + CTEXT "File Type: ---", IDC_0204, 10, 21, 220, 12 + PUSHBUTTON "Ok", IDC_0205, 15, 53, 48, 14 + PUSHBUTTON "Get from Disc", IDC_0206, 69, 53, 48, 14 + PUSHBUTTON "Convert", IDC_0207, 123, 53, 48, 14 + PUSHBUTTON "Cancel", IDC_0208, 177, 53, 48, 14 + AUTOCHECKBOX "Show Configure screen when starting emulation", IDC_0209, 13, 32, 179, 10 + AUTOCHECKBOX "Show Configure screen when restarting emulation", IDC_0210, 13, 41, 180, 10 +END + +DLG_0300 DIALOG 3, 1, 255, 124 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDisoEFP ISO Creation" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Source CD/DVD Device:", 301, 10, 8, 80, 12 + EDITTEXT IDC_0302, 92, 7, 153, 12, ES_AUTOHSCROLL + CTEXT "Device Type: ---", IDC_0303, 10, 22, 234, 12 + LTEXT "Iso File:", 304, 11, 39, 26, 12 + EDITTEXT IDC_0305, 37, 38, 172, 12, ES_AUTOHSCROLL + PUSHBUTTON "Browse", IDC_0306, 214, 37, 31, 14 + CTEXT "File Type: ---", IDC_0307, 9, 52, 236, 12 + LTEXT "New File Compression:", 308, 10, 71, 72, 12 + COMBOBOX IDC_0309, 83, 69, 100, 48, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Multiple Files (all under 2 GB):", 310, 10, 83, 94, 12 + AUTOCHECKBOX "", IDC_0311, 107, 83, 40, 10 + PUSHBUTTON "Make File", IDC_0312, 9, 104, 40, 14 + PUSHBUTTON "Cancel", IDC_0313, 205, 104, 40, 14 +END + +DLG_0400 DIALOG 4, 2, 234, 89 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDisoEFP File Conversion" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Iso File:", 401, 11, 7, 25, 12 + EDITTEXT IDC_0402, 37, 7, 146, 12, ES_AUTOHSCROLL + PUSHBUTTON "Browse", IDC_0403, 189, 6, 35, 12 + CTEXT "File Type: ---", IDC_0404, 10, 21, 214, 12 + LTEXT "Change Compression To:", 405, 9, 38, 81, 12 + COMBOBOX IDC_0406, 91, 36, 100, 50, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Multiple Files (all under 2 GB):", 407, 10, 51, 94, 12 + AUTOCHECKBOX "", IDC_0408, 105, 51, 40, 10 + PUSHBUTTON "Change File", IDC_0409, 10, 69, 40, 14 + PUSHBUTTON "Cancel", IDC_0410, 184, 68, 40, 14 +END + +DLG_0500 DIALOG 3, 0, 273, 66 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDisoEFP Progress" +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "Twiddling my Thumbs", IDC_0501, 9, 7, 255, 12 + CONTROL "", IDC_0502, "msctls_progress32", 0x1 | WS_CLIPSIBLINGS, 8, 19, 257, 11 + CTEXT "10 of 10", 503, 10, 32, 254, 12 + PUSHBUTTON "Cancel", IDC_0504, 118, 45, 40, 14 +END diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.c b/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.c new file mode 100644 index 0000000..090767b --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.c @@ -0,0 +1,187 @@ +/* tablerebuild.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // malloc() + +#include "mainbox.h" +#include "progressbox.h" +#include "isofile.h" +#include "multifile.h" +#include "isocompress.h" // CompressClose() +#include "gzipv1.h" +#include "gzipv2.h" +#include "bzip2v2.h" +#include "bzip2v3.h" +#include "actualfile.h" // ACTUALHANDLENULL + + +void IsoTableRebuild(const char *filename) { + struct IsoFile *datafile; + struct IsoFile *tablefile; + int retval; + char tempblock[65536]; + int stop; + + struct TableData table; + + datafile = IsoFileOpenForRead(filename); + + // Note: This is the start of the "Multifile" process. It's commented + // out so at least we can rebuild 1 part of a multifile at a time. + // IsoNameStripExt(datafile); + // IsoNameStripMulti(datafile); + + // Prep tablefile to hold ONLY a table (no data) + tablefile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); + if(tablefile == NULL) { + datafile = IsoFileClose(datafile); + return; + } // ENDIF- Failed to allocate? Abort. + + tablefile->sectorpos = 0; + tablefile->openforread = 0; + tablefile->filebytepos = 0; + tablefile->filebytesize = 0; + tablefile->filesectorpos = 0; + tablefile->filesectorsize = 0; + tablefile->handle = ACTUALHANDLENULL; + + tablefile->namepos = 0; + while((tablefile->namepos < 255) && + (*(filename + tablefile->namepos) != 0)) { + tablefile->name[tablefile->namepos] = *(filename + tablefile->namepos); + tablefile->namepos++; + } // ENDWHILE- Copying file name into tablefile + tablefile->name[tablefile->namepos] = 0; // And 0-terminate. + + tablefile->imageheader = datafile->imageheader; + tablefile->blocksize = datafile->blocksize; + tablefile->blockoffset = datafile->blockoffset; + tablefile->cdvdtype = 0; // Not important right now. + + tablefile->compress = datafile->compress; + tablefile->compresspos = datafile->compresspos; + tablefile->numsectors = datafile->numsectors; + tablefile->tabledata = NULL; + + switch(tablefile->compress) { + case 1: + retval = GZipV1OpenTableForWrite(tablefile); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2OpenTableForWrite(tablefile); + break; + case 4: + retval = BZip2V2OpenTableForWrite(tablefile); + break; + case 5: + retval = BZip2V3OpenTableForWrite(tablefile); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Which table are we writing out? + if(retval < 0) { + datafile = IsoFileClose(datafile); + return; + } // ENDIF- Failed to open table file? Abort + + sprintf(tempblock, "Rebuilding table for %s", datafile->name); + ProgressBoxStart(tempblock, datafile->filebytesize); + + stop = 0; + mainboxstop = 0; + progressboxstop = 0; + while((stop == 0) && (datafile->filebytepos < datafile->filebytesize)) { + switch(datafile->compress) { + case 1: + retval = GZipV1Read(datafile, 0, tempblock); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2Read(datafile, 0, tempblock); + break; + case 4: + retval = BZip2V2Read(datafile, 0, tempblock); + break; + case 5: + retval = BZip2V3Read(datafile, 0, tempblock); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Scanning for the next complete compressed block + + if(retval <= 0) { +#ifdef FUNCTION_WARNING_TABLEREBUILD + PrintLog("CDVDiso rebuild: failed to decompress - data corrupt"); +#endif /* FUNCTION_WARNING_TABLEREBUILD */ + stop = 1; + } else { + table.offset = datafile->filebytepos - retval; + table.size = retval; + switch(tablefile->compress) { + case 1: + retval = GZipV1WriteTable(tablefile, table); + break; + case 2: + retval = -1; + break; + case 3: + retval = GZipV2WriteTable(tablefile, table); + break; + case 4: + retval = BZip2V2WriteTable(tablefile, table); + break; + case 5: + retval = BZip2V3WriteTable(tablefile, table); + break; + default: + retval = -1; + break; + } // ENDSWITCH compress- Writing out the relavent table facts + if(retval < 0) stop = 1; + } // ENDIF- Do we have a valid record to write an entry for? + + ProgressBoxTick(datafile->filebytepos); + + if(mainboxstop != 0) stop = 2; + if(progressboxstop != 0) stop = 2; + } // ENDWHILE- Read in the data file and writing a table, 1 block at a time + + ProgressBoxStop(); + + CompressClose(tablefile); // Guarentee the table is flushed and closed. + if(stop != 0) { + ActualFileDelete(tablefile->tablename); + } // ENDIF- Aborted or trouble? Delete the table file + tablefile = IsoFileClose(tablefile); + datafile = IsoFileClose(datafile); + + return; +} // END IsoTableRebuild() diff --git a/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.h b/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.h new file mode 100644 index 0000000..731911d --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/Win32/tablerebuild.h @@ -0,0 +1,32 @@ +/* tablerebuild.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef TABLEREBUILD_H +#define TABLEREBUILD_H + + +// #define FUNCTION_WARNING_TABLEREBUILD + + +extern void IsoTableRebuild(const char *filename); + + +#endif /* TABLEREBUILD_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/blockv2.c b/plugins/cdvd/CDVDisoEFP/src/blockv2.c new file mode 100644 index 0000000..9d7453f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/blockv2.c @@ -0,0 +1,612 @@ +/* blockv2.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // malloc() + +#include // off64_t + + + +#include "zlib/zlib.h" + + + +#include "convert.h" + +#include "logfile.h" + +#include "isofile.h" // IsoFile + +#include "isocompress.h" // TableData, TableMap + +#include "actualfile.h" + +#include "blockv2.h" + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct BlockV2Header { + + char id[4]; + + unsigned int blocksize; + + unsigned int numblocks; + + unsigned int blockoffset; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +int BlockV2OpenTableForRead(struct IsoFile *isofile) { + + int i; + + int j; + + off64_t offset; + + int tableoffset; + + int retval; + + union TableMap tablemap; + + + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: OpenTableForRead()"); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + // We pre-read the WHOLE offset table. + + isofile->tabledata = (char *) malloc(isofile->filesectorsize * sizeof(struct TableData)); + + if(isofile->tabledata == NULL) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Couldn't allocate internal table!"); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + return(-1); + + } // ENDIF- Could not get enough memory to hold table data + + + + offset = sizeof(struct BlockV2Header); + + tableoffset = 0; + + for(i = 0; i < isofile->filesectorsize; i++) { + + retval = BlockV2Seek(isofile, offset); + + if(retval != 0) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Failed to find sector %i!", i); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + return(-1); + + } // ENDIF- Trouble finding a lsn id? Fail. + + + + retval = ActualFileRead(isofile->handle, + + sizeof(int), + + (char *) &j); + + if(retval != sizeof(int)) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Failed to read in sector %i!", i); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + return(-1); + + } // ENDIF- Trouble reading in a lsn id? Table damaged... fail. + + + + tablemap.table.offset = ConvertEndianUInt(j); // Actually, a lsn. + + for(j = 0; j < sizeof(struct TableData); j++) + + *(isofile->tabledata + tableoffset + j) = tablemap.ch[j]; + + offset += isofile->blocksize + 4; + + tableoffset += sizeof(struct TableData); + + } // NEXT i- reading in the sizes, and making offset as I go. + + + + isofile->tablehandle = ACTUALHANDLENULL; + + + + return(0); + +} // END BlockV2OpenTableForRead() + + + + + +int BlockV2SeekTable(struct IsoFile *isofile, off64_t sector) { + + int i; + + int tableoffset; + + union TableMap tablemap; + + off64_t filesectorstart; + + + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: SeekTable(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + if((isofile->filesectorpos >= 0) && + + (isofile->filesectorpos < isofile->filesectorsize)) { + + tableoffset = isofile->filesectorpos * sizeof(struct TableData); + + for(i = 0; i < sizeof(struct TableData); i++) + + tablemap.ch[i] = *(isofile->tabledata + tableoffset + i); + + if(sector == tablemap.table.offset) { + + return(0); + + } // ENDIF- Are we already pointing at the right sector? + + + + } else { + + isofile->filesectorpos = 0; + + tablemap.table.offset = -1; + + } // ENDIF- Is the file sector pointer within table limits? + + + + filesectorstart = isofile->filesectorpos; + + isofile->filesectorpos++; + + if(isofile->filesectorpos >= isofile->filesectorsize) + + isofile->filesectorpos = 0; + + while((isofile->filesectorpos != filesectorstart) && + + (tablemap.table.offset != sector)) { + + tableoffset = isofile->filesectorpos * sizeof(struct TableData); + + for(i = 0; i < sizeof(struct TableData); i++) + + tablemap.ch[i] = *(isofile->tabledata + tableoffset + i); + + + + if(tablemap.table.offset != sector) { + + isofile->filesectorpos++; + + if(isofile->filesectorpos >= isofile->filesectorsize) + + isofile->filesectorpos = 0; + + } // ENDIF- Still didn't find it? move to next sector. + + } // ENDWHILE- Scanning through whole sector list (starting at current pos) + + + + if(isofile->filesectorpos == filesectorstart) { + + return(-1); + + } // ENDIF- Did we loop through the whole file... and not find this sector? + + + + return(0); + +} // END BlockV2SeekTable() + + + + + +int BlockV2ReadTable(struct IsoFile *isofile, struct TableData *table) { + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: ReadTable()"); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + table->offset = sizeof(int) + isofile->blocksize; + + table->offset *= isofile->filesectorpos; + + table->offset += sizeof(struct BlockV2Header) + 4; + + table->size = isofile->blocksize; + + isofile->filesectorpos++; + + return(0); + +} // END BlockV2ReadTable() + + + + + +int BlockV2OpenTableForWrite(struct IsoFile *isofile) { + + return(-1); + +} // END BlockV2OpenTableForWrite() + + + + + +int BlockV2WriteTable(struct IsoFile *isofile, struct TableData table) { + + return(-1); + +} // END BlockV2WriteTable() + + + + + +int BlockV2OpenForRead(struct IsoFile *isofile) { + + int retval; + + struct BlockV2Header header; + + + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filebytepos = 0; + + + + isofile->imageheader = 0; + + isofile->numsectors = 1; // Sectors per block + + + + retval = ActualFileRead(isofile->handle, + + sizeof(struct BlockV2Header), + + (char *) &header); + + if(retval != sizeof(struct BlockV2Header)) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Couldn't read header!"); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF Could not read the first sector? Fail. + + isofile->filebytepos += retval; + + + + if((header.id[0] != 'B') || + + (header.id[1] != 'D') || + + (header.id[2] != 'V') || + + (header.id[3] != '2')) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Not a block dump v2 header!"); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF- ID for this compression type doesn't match? + + + + isofile->blocksize = ConvertEndianUInt(header.blocksize); + + // isofile->filesectorsize = ConvertEndianUInt(header.numblocks); + + isofile->blockoffset = ConvertEndianUInt(header.blockoffset); + + isofile->filesectorsize = isofile->filebytesize; + + isofile->filesectorsize -= 16; + + isofile->filesectorsize /= (isofile->blocksize + sizeof(int)); + + isofile->filesectorpos = 0; + + return(0); + +} // END BlockV2OpenForRead() + + + + + +int BlockV2Seek(struct IsoFile *isofile, off64_t position) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Seek(%lli)", position); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + retval = ActualFileSeek(isofile->handle, position); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Couldn't find the start of the block!"); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + return(-1); + + } // ENDIF- Couldn't find the data entry? Fail. + + isofile->filebytepos = position; + + return(0); + + + + return(-1); // Fail. (Due to lack of ambition?) + +} // END BlockV2Seek() + + + + + +int BlockV2Read(struct IsoFile *isofile, int bytes, char *buffer) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Read(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + retval = ActualFileRead(isofile->handle, isofile->blocksize, buffer); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != isofile->blocksize) { + +#ifdef VERBOSE_WARNING_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BLOCKV2 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + return(isofile->blocksize); + +} // END BlockV2Read() + + + + + +int BlockV2OpenForWrite(struct IsoFile *isofile) { + + return(-1); + +} // END BlockV2OpenForWrite() + + + + + +int BlockV2Write(struct IsoFile *isofile, char *buffer) { + + return(-1); + +} // END BlockV2Write() + + + + + +void BlockV2Close(struct IsoFile *isofile) { + +#ifdef VERBOSE_FUNCTION_BLOCKV2 + + PrintLog("CDVDiso BlockV2: Close()"); + +#endif /* VERBOSE_FUNCTION_BLOCKV2 */ + + + + if(isofile->handle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Is there a data file open? Close it. + + + + if(isofile->tabledata != NULL) { + + free(isofile->tabledata); + + isofile->tabledata = NULL; + + } // ENDIF- Do we have a read-in table to clear out? + + + + return; + +} // END BlockV2Close() + diff --git a/plugins/cdvd/CDVDisoEFP/src/blockv2.h b/plugins/cdvd/CDVDisoEFP/src/blockv2.h new file mode 100644 index 0000000..500e99c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/blockv2.h @@ -0,0 +1,104 @@ +/* blockv2.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef BLOCKV2_H + +#define BLOCKV2_H + + + + + +#include + + + +#include "isofile.h" + +#include "isocompress.h" + + + + + +// #define VERBOSE_FUNCTION_BLOCKV2 + +// #define VERBOSE_WARNING_BLOCKV2 + + + + + +extern int BlockV2OpenTableForRead(struct IsoFile *isofile); + +extern int BlockV2SeekTable(struct IsoFile *isofile, off64_t sector); + +extern int BlockV2ReadTable(struct IsoFile *isofile, struct TableData *table); + + + +extern int BlockV2OpenTableForWrite(struct IsoFile *isofile); + +extern int BlockV2WriteTable(struct IsoFile *isofile, struct TableData table); + + + +extern int BlockV2OpenForRead(struct IsoFile *isofile); + +extern int BlockV2Seek(struct IsoFile *isofile, off64_t sector); + +extern int BlockV2Read(struct IsoFile *isofile, int bytes, char *buffer); + +extern void BlockV2Close(struct IsoFile *isofile); + + + +extern int BlockV2OpenForWrite(struct IsoFile *isofile); + +extern int BlockV2Write(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* BLOCKV2_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/LICENSE b/plugins/cdvd/CDVDisoEFP/src/bzip2/LICENSE new file mode 100644 index 0000000..b5e5348 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/LICENSE @@ -0,0 +1,40 @@ + +This program, "bzip2", the associated library "libbzip2", and all +documentation, are copyright (C) 1996-2005 Julian R Seward. All +rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, Cambridge, UK. +jseward@acm.org +bzip2/libbzip2 version 1.0.3 of 15 February 2005 + diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/README b/plugins/cdvd/CDVDisoEFP/src/bzip2/README new file mode 100644 index 0000000..f49d9e9 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/README @@ -0,0 +1,185 @@ + +This is the README for bzip2, a block-sorting file compressor, version +1.0.3. This version is fully compatible with the previous public +releases, versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and 1.0.2. + +bzip2-1.0.3 is distributed under a BSD-style license. For details, +see the file LICENSE. + +Complete documentation is available in Postscript form (manual.ps), +PDF (manual.pdf) or html (manual.html). A plain-text version of the +manual page is available as bzip2.txt. A statement about Y2K issues +is now included in the file Y2K_INFO. + + +HOW TO BUILD -- UNIX + +Type `make'. This builds the library libbz2.a and then the +programs bzip2 and bzip2recover. Six self-tests are run. +If the self-tests complete ok, carry on to installation: + +To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type + make install +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + make install PREFIX=/xxx/yyy +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + make -n install or + make -n install PREFIX=/xxx/yyy respectively. +The -n instructs make to show the commands it would execute, but +not actually execute them. + + +HOW TO BUILD -- UNIX, shared library libbz2.so. + +Do 'make -f Makefile-libbz2_so'. This Makefile seems to work for +Linux-ELF (RedHat 7.2 on an x86 box), with gcc. I make no claims +that it works for any other platform, though I suspect it probably +will work for most platforms employing both ELF and gcc. + +bzip2-shared, a client of the shared library, is also built, but not +self-tested. So I suggest you also build using the normal Makefile, +since that conducts a self-test. A second reason to prefer the +version statically linked to the library is that, on x86 platforms, +building shared objects makes a valuable register (%ebx) unavailable +to gcc, resulting in a slowdown of 10%-20%, at least for bzip2. + +Important note for people upgrading .so's from 0.9.0/0.9.5 to version +1.0.X. All the functions in the library have been renamed, from (eg) +bzCompress to BZ2_bzCompress, to avoid namespace pollution. +Unfortunately this means that the libbz2.so created by +Makefile-libbz2_so will not work with any program which used an older +version of the library. Sorry. I do encourage library clients to +make the effort to upgrade to use version 1.0, since it is both faster +and more robust than previous versions. + + +HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc. + +It's difficult for me to support compilation on all these platforms. +My approach is to collect binaries for these platforms, and put them +on the master web page (http://sources.redhat.com/bzip2). Look there. +However (FWIW), bzip2-1.0.X is very standard ANSI C and should compile +unmodified with MS Visual C. If you have difficulties building, you +might want to read README.COMPILATION.PROBLEMS. + +At least using MS Visual C++ 6, you can build from the unmodified +sources by issuing, in a command shell: + nmake -f makefile.msc +(you may need to first run the MSVC-provided script VCVARS32.BAT + so as to set up paths to the MSVC tools correctly). + + +VALIDATION + +Correct operation, in the sense that a compressed file can always be +decompressed to reproduce the original, is obviously of paramount +importance. To validate bzip2, I used a modified version of Mark +Nelson's churn program. Churn is an automated test driver which +recursively traverses a directory structure, using bzip2 to compress +and then decompress each file it encounters, and checking that the +decompressed data is the same as the original. + + + +Please read and be aware of the following: + +WARNING: + + This program (attempts to) compress data by performing several + non-trivial transformations on it. Unless you are 100% familiar + with *all* the algorithms contained herein, and with the + consequences of modifying them, you should NOT meddle with the + compression or decompression machinery. Incorrect changes can and + very likely *will* lead to disastrous loss of data. + + +DISCLAIMER: + + I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE + USE OF THIS PROGRAM, HOWSOEVER CAUSED. + + Every compression of a file implies an assumption that the + compressed file can be decompressed to reproduce the original. + Great efforts in design, coding and testing have been made to + ensure that this program works correctly. However, the complexity + of the algorithms, and, in particular, the presence of various + special cases in the code which occur with very low but non-zero + probability make it impossible to rule out the possibility of bugs + remaining in the program. DO NOT COMPRESS ANY DATA WITH THIS + PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER + SMALL, THAT THE DATA WILL NOT BE RECOVERABLE. + + That is not to say this program is inherently unreliable. Indeed, + I very much hope the opposite is true. bzip2 has been carefully + constructed and extensively tested. + + +PATENTS: + + To the best of my knowledge, bzip2 does not use any patented + algorithms. However, I do not have the resources to carry out + a patent search. Therefore I cannot give any guarantee of the + above statement. + +End of legalities. + + +WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ? + + * Approx 10% faster compression, 30% faster decompression + * -t (test mode) is a lot quicker + * Can decompress concatenated compressed files + * Programming interface, so programs can directly read/write .bz2 files + * Less restrictive (BSD-style) licensing + * Flag handling more compatible with GNU gzip + * Much more documentation, i.e., a proper user manual + * Hopefully, improved portability (at least of the library) + +WHAT'S NEW IN 0.9.5 ? + + * Compression speed is much less sensitive to the input + data than in previous versions. Specifically, the very + slow performance caused by repetitive data is fixed. + * Many small improvements in file and flag handling. + * A Y2K statement. + +WHAT'S NEW IN 1.0.0 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.2 ? + + See the CHANGES file. + +WHAT'S NEW IN 1.0.3 ? + + See the CHANGES file. + + +I hope you find bzip2 useful. Feel free to contact me at + jseward@bzip.org +if you have any suggestions or queries. Many people mailed me with +comments, suggestions and patches after the releases of bzip-0.15, +bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1 and +1.0.2, and the changes in bzip2 are largely a result of this feedback. +I thank you for your comments. + +At least for the time being, bzip2's "home" is (or can be reached via) +http://www.bzip.org + +Julian Seward +jseward@bzip.org + +Cambridge, UK. + +18 July 1996 (version 0.15) +25 August 1996 (version 0.21) + 7 August 1997 (bzip2, version 0.1) +29 August 1997 (bzip2, version 0.1pl2) +23 August 1998 (bzip2, version 0.9.0) + 8 June 1999 (bzip2, version 0.9.5) + 4 Sept 1999 (bzip2, version 0.9.5d) + 5 May 2000 (bzip2, version 1.0pre8) +30 December 2001 (bzip2, version 1.0.2pre1) +15 February 2005 (bzip2, version 1.0.3) diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/blocksort.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/blocksort.c new file mode 100644 index 0000000..02554cc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/blocksort.c @@ -0,0 +1,1141 @@ + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. + + To get some idea how the block sorting algorithms in this file + work, read my paper + On the Performance of BWT Sorting Algorithms + in Proceedings of the IEEE Data Compression Conference 2000, + Snowbird, Utah, USA, 27-30 March 2000. The main sort in this + file implements the algorithm called cache in the paper. +--*/ + + +#include "bzlib_private.h" + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + if (verb >= 4) + VPrintf1 ( " depth %6d has ", H ); + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + if (verb >= 4) + VPrintf1 ( "%6d unresolved strings\n", nNotDone ); + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + if (verb >= 4) + VPrintf0 ( " reconstructing block ...\n" ); + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +__inline__ +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32 verb, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + if (verb >= 4) + VPrintf4 ( " qsort [0x%x, 0x%x] " + "done %d this %d\n", + ss, j, numQSorted, hi - lo + 1 ); + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( (copyStart[ss]-1 == copyEnd[ss]) + || + /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1. + Necessity for this case is demonstrated by compressing + a sequence of approximately 48.5 million of character + 251; 1.0.0/1.0.1 will then die here. */ + (copyStart[ss] == 0 && copyEnd[ss] == nblock-1), + 1007 ) + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } + + if (verb >= 4) + VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", + nblock, numQSorted, nblock - numQSorted ); +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 verb = s->verbosity; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); + if (verb >= 3) + VPrintf3 ( " %d work, %d block, ratio %5.2f\n", + budgetInit - budget, + nblock, + (float)(budgetInit - budget) / + (float)(nblock==0 ? 1 : nblock) ); + if (budget < 0) { + if (verb >= 2) + VPrintf0 ( " too repetitive; using fallback" + " sorting algorithm\n" ); + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.c new file mode 100644 index 0000000..5704dc4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.c @@ -0,0 +1,1616 @@ + +/*-------------------------------------------------------------*/ +/*--- Library top-level functions. ---*/ +/*--- bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * made zero-length BZ_FLUSH work correctly in bzCompress(). + * fixed bzWrite/bzRead to ignore zero-length requests. + * fixed bzread to correctly handle read requests after EOF. + * wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. +--*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Compression stuff ---*/ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +#ifndef BZ_NO_STDIO +void BZ2_bz__AssertH__fail ( int errcode ) +{ + fprintf(stderr, + "\n\nbzip2/libbzip2: internal error number %d.\n" + "This is a bug in bzip2/libbzip2, %s.\n" + "Please report it to me at: jseward@bzip.org. If this happened\n" + "when you were using some program which uses libbzip2 as a\n" + "component, you should also report this bug to the author(s)\n" + "of that program. Please make an effort to report this bug;\n" + "timely and accurate bug reports eventually lead to higher\n" + "quality software. Thanks. Julian Seward, 15 February 2005.\n\n", + errcode, + BZ2_bzlibVersion() + ); + + if (errcode == 1007) { + fprintf(stderr, + "\n*** A special note about internal error number 1007 ***\n" + "\n" + "Experience suggests that a common cause of i.e. 1007\n" + "is unreliable memory or other hardware. The 1007 assertion\n" + "just happens to cross-check the results of huge numbers of\n" + "memory reads/writes, and so acts (unintendedly) as a stress\n" + "test of your memory system.\n" + "\n" + "I suggest the following: try compressing the file again,\n" + "possibly monitoring progress in detail with the -vv flag.\n" + "\n" + "* If the error cannot be reproduced, and/or happens at different\n" + " points in compression, you may have a flaky memory system.\n" + " Try a memory-test program. I have used Memtest86\n" + " (www.memtest86.com). At the time of writing it is free (GPLd).\n" + " Memtest86 tests memory much more thorougly than your BIOSs\n" + " power-on test, and may find failures that the BIOS doesn't.\n" + "\n" + "* If the error can be repeatably reproduced, this is a bug in\n" + " bzip2, and I would very much like to hear about it. Please\n" + " let me know, and, ideally, save a copy of the file causing the\n" + " problem -- without which I will be unable to investigate it.\n" + "\n" + ); + } + + exit(3); +} +#endif + + +/*---------------------------------------------------*/ +static +int bz_config_ok ( void ) +{ + if (sizeof(int) != 4) return 0; + if (sizeof(short) != 2) return 0; + if (sizeof(char) != 1) return 0; + return 1; +} + + +/*---------------------------------------------------*/ +static +void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) +{ + void* v = malloc ( items * size ); + return v; +} + +static +void default_bzfree ( void* opaque, void* addr ) +{ + if (addr != NULL) free ( addr ); +} + + +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ + Int32 i; + s->nblock = 0; + s->numZ = 0; + s->state_out_pos = 0; + BZ_INITIALISE_CRC ( s->blockCRC ); + for (i = 0; i < 256; i++) s->inUse[i] = False; + s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ + s->state_in_ch = 256; + s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ + if (s->state_in_ch < 256 && s->state_in_len > 0) + return False; else + return True; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) + ( bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 n; + EState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL || + blockSize100k < 1 || blockSize100k > 9 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(EState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + + s->arr1 = NULL; + s->arr2 = NULL; + s->ftab = NULL; + + n = 100000 * blockSize100k; + s->arr1 = BZALLOC( n * sizeof(UInt32) ); + s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); + s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); + + if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + if (s != NULL) BZFREE(s); + return BZ_MEM_ERROR; + } + + s->blockNo = 0; + s->state = BZ_S_INPUT; + s->mode = BZ_M_RUNNING; + s->combinedCRC = 0; + s->blockSize100k = blockSize100k; + s->nblockMAX = 100000 * blockSize100k - 19; + s->verbosity = verbosity; + s->workFactor = workFactor; + + s->block = (UChar*)s->arr2; + s->mtfv = (UInt16*)s->arr1; + s->zbits = NULL; + s->ptr = (UInt32*)s->arr1; + + strm->state = s; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + init_RL ( s ); + prepare_new_block ( s ); + return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ + Int32 i; + UChar ch = (UChar)(s->state_in_ch); + for (i = 0; i < s->state_in_len; i++) { + BZ_UPDATE_CRC( s->blockCRC, ch ); + } + s->inUse[s->state_in_ch] = True; + switch (s->state_in_len) { + case 1: + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 2: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 3: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + default: + s->inUse[s->state_in_len-4] = True; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = ((UChar)(s->state_in_len-4)); + s->nblock++; + break; + } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ + if (s->state_in_ch < 256) add_pair_to_block ( s ); + init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ +{ \ + UInt32 zchh = (UInt32)(zchh0); \ + /*-- fast track the common case --*/ \ + if (zchh != zs->state_in_ch && \ + zs->state_in_len == 1) { \ + UChar ch = (UChar)(zs->state_in_ch); \ + BZ_UPDATE_CRC( zs->blockCRC, ch ); \ + zs->inUse[zs->state_in_ch] = True; \ + zs->block[zs->nblock] = (UChar)ch; \ + zs->nblock++; \ + zs->state_in_ch = zchh; \ + } \ + else \ + /*-- general, uncommon cases --*/ \ + if (zchh != zs->state_in_ch || \ + zs->state_in_len == 255) { \ + if (zs->state_in_ch < 256) \ + add_pair_to_block ( zs ); \ + zs->state_in_ch = zchh; \ + zs->state_in_len = 1; \ + } else { \ + zs->state_in_len++; \ + } \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ + Bool progress_in = False; + + if (s->mode == BZ_M_RUNNING) { + + /*-- fast track the common case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + + } else { + + /*-- general, uncommon case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + /*-- flush/finish end? --*/ + if (s->avail_in_expect == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + s->avail_in_expect--; + } + } + return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ + Bool progress_out = False; + + while (True) { + + /*-- no output space? --*/ + if (s->strm->avail_out == 0) break; + + /*-- block done? --*/ + if (s->state_out_pos >= s->numZ) break; + + progress_out = True; + *(s->strm->next_out) = s->zbits[s->state_out_pos]; + s->state_out_pos++; + s->strm->avail_out--; + s->strm->next_out++; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ + Bool progress_in = False; + Bool progress_out = False; + EState* s = strm->state; + + while (True) { + + if (s->state == BZ_S_OUTPUT) { + progress_out |= copy_output_until_stop ( s ); + if (s->state_out_pos < s->numZ) break; + if (s->mode == BZ_M_FINISHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + prepare_new_block ( s ); + s->state = BZ_S_INPUT; + if (s->mode == BZ_M_FLUSHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + } + + if (s->state == BZ_S_INPUT) { + progress_in |= copy_input_until_stop ( s ); + if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { + flush_RL ( s ); + BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); + s->state = BZ_S_OUTPUT; + } + else + if (s->nblock >= s->nblockMAX) { + BZ2_compressBlock ( s, False ); + s->state = BZ_S_OUTPUT; + } + else + if (s->strm->avail_in == 0) { + break; + } + } + + } + + return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ + Bool progress; + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + preswitch: + switch (s->mode) { + + case BZ_M_IDLE: + return BZ_SEQUENCE_ERROR; + + case BZ_M_RUNNING: + if (action == BZ_RUN) { + progress = handle_compress ( strm ); + return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; + } + else + if (action == BZ_FLUSH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FLUSHING; + goto preswitch; + } + else + if (action == BZ_FINISH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FINISHING; + goto preswitch; + } + else + return BZ_PARAM_ERROR; + + case BZ_M_FLUSHING: + if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FLUSH_OK; + s->mode = BZ_M_RUNNING; + return BZ_RUN_OK; + + case BZ_M_FINISHING: + if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (!progress) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FINISH_OK; + s->mode = BZ_M_IDLE; + return BZ_STREAM_END; + } + return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) +{ + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + BZFREE(strm->state); + + strm->state = NULL; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/*--- Decompression stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) + ( bz_stream* strm, + int verbosity, + int small ) +{ + DState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL) return BZ_PARAM_ERROR; + if (small != 0 && small != 1) return BZ_PARAM_ERROR; + if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; + + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(DState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + strm->state = s; + s->state = BZ_X_MAGIC_1; + s->bsLive = 0; + s->bsBuff = 0; + s->calculatedCombinedCRC = 0; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + s->smallDecompress = (Bool)small; + s->ll4 = NULL; + s->ll16 = NULL; + s->tt = NULL; + s->currBlockNo = 0; + s->verbosity = verbosity; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + /* restore */ + UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; + UChar c_state_out_ch = s->state_out_ch; + Int32 c_state_out_len = s->state_out_len; + Int32 c_nblock_used = s->nblock_used; + Int32 c_k0 = s->k0; + UInt32* c_tt = s->tt; + UInt32 c_tPos = s->tPos; + char* cs_next_out = s->strm->next_out; + unsigned int cs_avail_out = s->strm->avail_out; + /* end restore */ + + UInt32 avail_out_INIT = cs_avail_out; + Int32 s_save_nblockPP = s->save_nblock+1; + unsigned int total_out_lo32_old; + + while (True) { + + /* try to finish existing run */ + if (c_state_out_len > 0) { + while (True) { + if (cs_avail_out == 0) goto return_notr; + if (c_state_out_len == 1) break; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + c_state_out_len--; + cs_next_out++; + cs_avail_out--; + } + s_state_out_len_eq_one: + { + if (cs_avail_out == 0) { + c_state_out_len = 1; goto return_notr; + }; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + cs_next_out++; + cs_avail_out--; + } + } + /* Only caused by corrupt data stream? */ + if (c_nblock_used > s_save_nblockPP) + return True; + + /* can a new run be started? */ + if (c_nblock_used == s_save_nblockPP) { + c_state_out_len = 0; goto return_notr; + }; + c_state_out_ch = c_k0; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (k1 != c_k0) { + c_k0 = k1; goto s_state_out_len_eq_one; + }; + if (c_nblock_used == s_save_nblockPP) + goto s_state_out_len_eq_one; + + c_state_out_len = 2; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + c_state_out_len = 3; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + BZ_GET_FAST_C(k1); c_nblock_used++; + c_state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST_C(c_k0); c_nblock_used++; + } + + return_notr: + total_out_lo32_old = s->strm->total_out_lo32; + s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); + if (s->strm->total_out_lo32 < total_out_lo32_old) + s->strm->total_out_hi32++; + + /* save */ + s->calculatedBlockCRC = c_calculatedBlockCRC; + s->state_out_ch = c_state_out_ch; + s->state_out_len = c_state_out_len; + s->nblock_used = c_nblock_used; + s->k0 = c_k0; + s->tt = c_tt; + s->tPos = c_tPos; + s->strm->next_out = cs_next_out; + s->strm->avail_out = cs_avail_out; + /* end save */ + } + return False; +} + + + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ + Int32 nb, na, mid; + nb = 0; + na = 256; + do { + mid = (nb + na) >> 1; + if (indx >= cftab[mid]) nb = mid; else na = mid; + } + while (na - nb != 1); + return nb; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ + Bool corrupt; + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + while (True) { + if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; + if (s->state == BZ_X_OUTPUT) { + if (s->smallDecompress) + corrupt = unRLE_obuf_to_output_SMALL ( s ); else + corrupt = unRLE_obuf_to_output_FAST ( s ); + if (corrupt) return BZ_DATA_ERROR; + if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { + BZ_FINALISE_CRC ( s->calculatedBlockCRC ); + if (s->verbosity >= 3) + VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, + s->calculatedBlockCRC ); + if (s->verbosity >= 2) VPrintf0 ( "]" ); + if (s->calculatedBlockCRC != s->storedBlockCRC) + return BZ_DATA_ERROR; + s->calculatedCombinedCRC + = (s->calculatedCombinedCRC << 1) | + (s->calculatedCombinedCRC >> 31); + s->calculatedCombinedCRC ^= s->calculatedBlockCRC; + s->state = BZ_X_BLKHDR_1; + } else { + return BZ_OK; + } + } + if (s->state >= BZ_X_MAGIC_1) { + Int32 r = BZ2_decompress ( s ); + if (r == BZ_STREAM_END) { + if (s->verbosity >= 3) + VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", + s->storedCombinedCRC, s->calculatedCombinedCRC ); + if (s->calculatedCombinedCRC != s->storedCombinedCRC) + return BZ_DATA_ERROR; + return r; + } + if (s->state != BZ_X_OUTPUT) return r; + } + } + + AssertH ( 0, 6001 ); + + return 0; /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) +{ + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->tt != NULL) BZFREE(s->tt); + if (s->ll16 != NULL) BZFREE(s->ll16); + if (s->ll4 != NULL) BZFREE(s->ll4); + + BZFREE(strm->state); + strm->state = NULL; + + return BZ_OK; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ +/*--- File I/O stuff ---*/ +/*---------------------------------------------------*/ + +#define BZ_SETERR(eee) \ +{ \ + if (bzerror != NULL) *bzerror = eee; \ + if (bzf != NULL) bzf->lastErr = eee; \ +} + +typedef + struct { + FILE* handle; + Char buf[BZ_MAX_UNUSED]; + Int32 bufN; + Bool writing; + bz_stream strm; + Int32 lastErr; + Bool initialisedOk; + } + bzFile; + + +/*---------------------------------------------*/ +static Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzWriteOpen) + ( int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 ret; + bzFile* bzf = NULL; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (blockSize100k < 1 || blockSize100k > 9) || + (workFactor < 0 || workFactor > 250) || + (verbosity < 0 || verbosity > 4)) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + bzf->initialisedOk = False; + bzf->bufN = 0; + bzf->handle = f; + bzf->writing = True; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + if (workFactor == 0) workFactor = 30; + ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = 0; + bzf->initialisedOk = True; + return bzf; +} + + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWrite) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return; }; + + bzf->strm.avail_in = len; + bzf->strm.next_in = buf; + + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); + if (ret != BZ_RUN_OK) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (bzf->strm.avail_in == 0) + { BZ_SETERR(BZ_OK); return; }; + } +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWriteClose) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ) +{ + BZ2_bzWriteClose64 ( bzerror, b, abandon, + nbytes_in, NULL, nbytes_out, NULL ); +} + + +void BZ_API(BZ2_bzWriteClose64) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; + if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; + if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; + if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; + + if ((!abandon) && bzf->lastErr == BZ_OK) { + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); + if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (ret == BZ_STREAM_END) break; + } + } + + if ( !abandon && !ferror ( bzf->handle ) ) { + fflush ( bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (nbytes_in_lo32 != NULL) + *nbytes_in_lo32 = bzf->strm.total_in_lo32; + if (nbytes_in_hi32 != NULL) + *nbytes_in_hi32 = bzf->strm.total_in_hi32; + if (nbytes_out_lo32 != NULL) + *nbytes_out_lo32 = bzf->strm.total_out_lo32; + if (nbytes_out_hi32 != NULL) + *nbytes_out_hi32 = bzf->strm.total_out_hi32; + + BZ_SETERR(BZ_OK); + BZ2_bzCompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzReadOpen) + ( int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused ) +{ + bzFile* bzf = NULL; + int ret; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (small != 0 && small != 1) || + (verbosity < 0 || verbosity > 4) || + (unused == NULL && nUnused != 0) || + (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + + bzf->initialisedOk = False; + bzf->handle = f; + bzf->bufN = 0; + bzf->writing = False; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + while (nUnused > 0) { + bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; + unused = ((void*)( 1 + ((UChar*)(unused)) )); + nUnused--; + } + + ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + + bzf->initialisedOk = True; + return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) +{ + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + + if (bzf->initialisedOk) + (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzRead) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return 0; }; + + bzf->strm.avail_out = len; + bzf->strm.next_out = buf; + + while (True) { + + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + + if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { + n = fread ( bzf->buf, sizeof(UChar), + BZ_MAX_UNUSED, bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + bzf->bufN = n; + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + } + + ret = BZ2_bzDecompress ( &(bzf->strm) ); + + if (ret != BZ_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return 0; }; + + if (ret == BZ_OK && myfeof(bzf->handle) && + bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) + { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; + + if (ret == BZ_STREAM_END) + { BZ_SETERR(BZ_STREAM_END); + return len - bzf->strm.avail_out; }; + if (bzf->strm.avail_out == 0) + { BZ_SETERR(BZ_OK); return len; }; + + } + + return 0; /*not reached*/ +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadGetUnused) + ( int* bzerror, + BZFILE* b, + void** unused, + int* nUnused ) +{ + bzFile* bzf = (bzFile*)b; + if (bzf == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (bzf->lastErr != BZ_STREAM_END) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (unused == NULL || nUnused == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + + BZ_SETERR(BZ_OK); + *nUnused = bzf->strm.avail_in; + *unused = bzf->strm.next_in; +} +#endif + + +/*---------------------------------------------------*/ +/*--- Misc convenience stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffCompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + blockSize100k < 1 || blockSize100k > 9 || + verbosity < 0 || verbosity > 4 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzCompressInit ( &strm, blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzCompress ( &strm, BZ_FINISH ); + if (ret == BZ_FINISH_OK) goto output_overflow; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzCompressEnd ( &strm ); + return BZ_OK; + + output_overflow: + BZ2_bzCompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + + errhandler: + BZ2_bzCompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffDecompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + (small != 0 && small != 1) || + verbosity < 0 || verbosity > 4) + return BZ_PARAM_ERROR; + + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzDecompress ( &strm ); + if (ret == BZ_OK) goto output_overflow_or_eof; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzDecompressEnd ( &strm ); + return BZ_OK; + + output_overflow_or_eof: + if (strm.avail_out > 0) { + BZ2_bzDecompressEnd ( &strm ); + return BZ_UNEXPECTED_EOF; + } else { + BZ2_bzDecompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + }; + + errhandler: + BZ2_bzDecompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +/*-- + Code contributed by Yoshioka Tsuneo + (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +/*-- + return version like "0.9.0c". +--*/ +const char * BZ_API(BZ2_bzlibVersion)(void) +{ + return BZ_VERSION; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif +static +BZFILE * bzopen_or_bzdopen + ( const char *path, /* no use when bzdopen */ + int fd, /* no use when bzdopen */ + const char *mode, + int open_mode) /* bzopen: 0, bzdopen:1 */ +{ + int bzerr; + char unused[BZ_MAX_UNUSED]; + int blockSize100k = 9; + int writing = 0; + char mode2[10] = ""; + FILE *fp = NULL; + BZFILE *bzfp = NULL; + int verbosity = 0; + int workFactor = 30; + int smallMode = 0; + int nUnused = 0; + + if (mode == NULL) return NULL; + while (*mode) { + switch (*mode) { + case 'r': + writing = 0; break; + case 'w': + writing = 1; break; + case 's': + smallMode = 1; break; + default: + if (isdigit((int)(*mode))) { + blockSize100k = *mode-BZ_HDR_0; + } + } + mode++; + } + strcat(mode2, writing ? "w" : "r" ); + strcat(mode2,"b"); /* binary mode */ + + if (open_mode==0) { + if (path==NULL || strcmp(path,"")==0) { + fp = (writing ? stdout : stdin); + SET_BINARY_MODE(fp); + } else { + fp = fopen(path,mode2); + } + } else { +#ifdef BZ_STRICT_ANSI + fp = NULL; +#else + fp = fdopen(fd,mode2); +#endif + } + if (fp == NULL) return NULL; + + if (writing) { + /* Guard against total chaos and anarchy -- JRS */ + if (blockSize100k < 1) blockSize100k = 1; + if (blockSize100k > 9) blockSize100k = 9; + bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, + verbosity,workFactor); + } else { + bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, + unused,nUnused); + } + if (bzfp == NULL) { + if (fp != stdin && fp != stdout) fclose(fp); + return NULL; + } + return bzfp; +} + + +/*---------------------------------------------------*/ +/*-- + open file for read or write. + ex) bzopen("file","w9") + case path="" or NULL => use stdin or stdout. +--*/ +BZFILE * BZ_API(BZ2_bzopen) + ( const char *path, + const char *mode ) +{ + return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); +} + + +/*---------------------------------------------------*/ +BZFILE * BZ_API(BZ2_bzdopen) + ( int fd, + const char *mode ) +{ + return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) +{ + int bzerr, nread; + if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; + nread = BZ2_bzRead(&bzerr,b,buf,len); + if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { + return nread; + } else { + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) +{ + int bzerr; + + BZ2_bzWrite(&bzerr,b,buf,len); + if(bzerr == BZ_OK){ + return len; + }else{ + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzflush) (BZFILE *b) +{ + /* do nothing now... */ + return 0; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzclose) (BZFILE* b) +{ + int bzerr; + FILE *fp = ((bzFile *)b)->handle; + + if (b==NULL) {return;} + if(((bzFile*)b)->writing){ + BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); + if(bzerr != BZ_OK){ + BZ2_bzWriteClose(NULL,b,1,NULL,NULL); + } + }else{ + BZ2_bzReadClose(&bzerr,b); + } + if(fp!=stdin && fp!=stdout){ + fclose(fp); + } +} + + +/*---------------------------------------------------*/ +/*-- + return last error code +--*/ +static char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"CONFIG_ERROR" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + + +const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) +{ + int err = ((bzFile *)b)->lastErr; + + if(err>0) err = 0; + *errnum = err; + return bzerrorstrings[err*-1]; +} +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.h b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.h new file mode 100644 index 0000000..d3cc8cf --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib.h @@ -0,0 +1,323 @@ + +/*-------------------------------------------------------------*/ +/*--- Public header file for the library. ---*/ +/*--- bzlib.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_H +#define _BZLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BZ_RUN 0 +#define BZ_FLUSH 1 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FLUSH_OK 2 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 +#define BZ_SEQUENCE_ERROR (-1) +#define BZ_PARAM_ERROR (-2) +#define BZ_MEM_ERROR (-3) +#define BZ_DATA_ERROR (-4) +#define BZ_DATA_ERROR_MAGIC (-5) +#define BZ_IO_ERROR (-6) +#define BZ_UNEXPECTED_EOF (-7) +#define BZ_OUTBUFF_FULL (-8) +#define BZ_CONFIG_ERROR (-9) + +typedef + struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; + } + bz_stream; + + +#ifndef BZ_IMPORT +#define BZ_EXPORT +#endif + +#ifndef BZ_NO_STDIO +/* Need a definitition for FILE */ +#include +#endif + +#ifdef _WIN32 +# include +# ifdef small + /* windows.h define small to char */ +# undef small +# endif +# ifdef BZ_EXPORT +# define BZ_API(func) WINAPI func +# define BZ_EXTERN extern +# else + /* import windows dll dynamically */ +# define BZ_API(func) (WINAPI * func) +# define BZ_EXTERN +# endif +#else +# define BZ_API(func) func +# define BZ_EXTERN extern +#endif + + +/*-- Core (low-level) library functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompress) ( + bz_stream* strm, + int action + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( + bz_stream *strm, + int verbosity, + int small + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( + bz_stream *strm + ); + + + +/*-- High(er) level library functions --*/ + +#ifndef BZ_NO_STDIO +#define BZ_MAX_UNUSED 5000 + +typedef void BZFILE; + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( + int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( + int* bzerror, + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( + int* bzerror, + BZFILE* b, + void** unused, + int* nUnused + ); + +BZ_EXTERN int BZ_API(BZ2_bzRead) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( + int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN void BZ_API(BZ2_bzWrite) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 + ); +#endif + + +/*-- Utility functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity + ); + + +/*-- + Code contributed by Yoshioka Tsuneo + (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ + +BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( + void + ); + +#ifndef BZ_NO_STDIO +BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( + const char *path, + const char *mode + ); + +BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( + int fd, + const char *mode + ); + +BZ_EXTERN int BZ_API(BZ2_bzread) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzwrite) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzflush) ( + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzclose) ( + BZFILE* b + ); + +BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( + BZFILE *b, + int *errnum + ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib_private.h b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib_private.h new file mode 100644 index 0000000..0bc1bfe --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/bzlib_private.h @@ -0,0 +1,537 @@ + +/*-------------------------------------------------------------*/ +/*--- Private header file for the library. ---*/ +/*--- bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_PRIVATE_H +#define _BZLIB_PRIVATE_H + +#include + +#ifndef BZ_NO_STDIO +#include +#include +#include +#endif + +#include "bzlib.h" + + + +/*-- General stuff. --*/ + +#define BZ_VERSION "1.0.3, 15-Feb-2005" + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#ifndef __GNUC__ +#define __inline__ /* */ +#endif + +#ifndef BZ_NO_STDIO +extern void BZ2_bz__AssertH__fail ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); } +#if BZ_DEBUG +#define AssertD(cond,msg) \ + { if (!(cond)) { \ + fprintf ( stderr, \ + "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\ + exit(1); \ + }} +#else +#define AssertD(cond,msg) /* */ +#endif +#define VPrintf0(zf) \ + fprintf(stderr,zf) +#define VPrintf1(zf,za1) \ + fprintf(stderr,zf,za1) +#define VPrintf2(zf,za1,za2) \ + fprintf(stderr,zf,za1,za2) +#define VPrintf3(zf,za1,za2,za3) \ + fprintf(stderr,zf,za1,za2,za3) +#define VPrintf4(zf,za1,za2,za3,za4) \ + fprintf(stderr,zf,za1,za2,za3,za4) +#define VPrintf5(zf,za1,za2,za3,za4,za5) \ + fprintf(stderr,zf,za1,za2,za3,za4,za5) +#else +extern void bz_internal_error ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) bz_internal_error ( errcode ); } +#define AssertD(cond,msg) /* */ +#define VPrintf0(zf) /* */ +#define VPrintf1(zf,za1) /* */ +#define VPrintf2(zf,za1,za2) /* */ +#define VPrintf3(zf,za1,za2,za3) /* */ +#define VPrintf4(zf,za1,za2,za3,za4) /* */ +#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */ +#endif + + +#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1) +#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp)) + + +/*-- Header bytes. --*/ + +#define BZ_HDR_B 0x42 /* 'B' */ +#define BZ_HDR_Z 0x5a /* 'Z' */ +#define BZ_HDR_h 0x68 /* 'h' */ +#define BZ_HDR_0 0x30 /* '0' */ + +/*-- Constants for the back end. --*/ + +#define BZ_MAX_ALPHA_SIZE 258 +#define BZ_MAX_CODE_LEN 23 + +#define BZ_RUNA 0 +#define BZ_RUNB 1 + +#define BZ_N_GROUPS 6 +#define BZ_G_SIZE 50 +#define BZ_N_ITERS 4 + +#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) + + + +/*-- Stuff for randomising repetitive blocks. --*/ + +extern Int32 BZ2_rNums[512]; + +#define BZ_RAND_DECLS \ + Int32 rNToGo; \ + Int32 rTPos \ + +#define BZ_RAND_INIT_MASK \ + s->rNToGo = 0; \ + s->rTPos = 0 \ + +#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) + +#define BZ_RAND_UPD_MASK \ + if (s->rNToGo == 0) { \ + s->rNToGo = BZ2_rNums[s->rTPos]; \ + s->rTPos++; \ + if (s->rTPos == 512) s->rTPos = 0; \ + } \ + s->rNToGo--; + + + +/*-- Stuff for doing CRCs. --*/ + +extern UInt32 BZ2_crc32Table[256]; + +#define BZ_INITIALISE_CRC(crcVar) \ +{ \ + crcVar = 0xffffffffL; \ +} + +#define BZ_FINALISE_CRC(crcVar) \ +{ \ + crcVar = ~(crcVar); \ +} + +#define BZ_UPDATE_CRC(crcVar,cha) \ +{ \ + crcVar = (crcVar << 8) ^ \ + BZ2_crc32Table[(crcVar >> 24) ^ \ + ((UChar)cha)]; \ +} + + + +/*-- States and modes for compression. --*/ + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + + + + +/*-- Structure holding all the compression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* mode this stream is in, and whether inputting */ + /* or outputting data */ + Int32 mode; + Int32 state; + + /* remembers avail_in when flush/finish requested */ + UInt32 avail_in_expect; + + /* for doing the block sorting */ + UInt32* arr1; + UInt32* arr2; + UInt32* ftab; + Int32 origPtr; + + /* aliases for arr1 and arr2 */ + UInt32* ptr; + UChar* block; + UInt16* mtfv; + UChar* zbits; + + /* for deciding when to use the fallback sorting algorithm */ + Int32 workFactor; + + /* run-length-encoding of the input */ + UInt32 state_in_ch; + Int32 state_in_len; + BZ_RAND_DECLS; + + /* input and output limits and current posns */ + Int32 nblock; + Int32 nblockMAX; + Int32 numZ; + Int32 state_out_pos; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + UChar unseqToSeq[256]; + + /* the buffer for bit stream creation */ + UInt32 bsBuff; + Int32 bsLive; + + /* block and combined CRCs */ + UInt32 blockCRC; + UInt32 combinedCRC; + + /* misc administratium */ + Int32 verbosity; + Int32 blockNo; + Int32 blockSize100k; + + /* stuff for coding the MTF values */ + Int32 nMTF; + Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + /* second dimension: only 3 needed; 4 makes index calculations faster */ + UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; + + } + EState; + + + +/*-- externs for compression. --*/ + +extern void +BZ2_blockSort ( EState* ); + +extern void +BZ2_compressBlock ( EState*, Bool ); + +extern void +BZ2_bsInitWrite ( EState* ); + +extern void +BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); + +extern void +BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); + + + +/*-- states for decompression. --*/ + +#define BZ_X_IDLE 1 +#define BZ_X_OUTPUT 2 + +#define BZ_X_MAGIC_1 10 +#define BZ_X_MAGIC_2 11 +#define BZ_X_MAGIC_3 12 +#define BZ_X_MAGIC_4 13 +#define BZ_X_BLKHDR_1 14 +#define BZ_X_BLKHDR_2 15 +#define BZ_X_BLKHDR_3 16 +#define BZ_X_BLKHDR_4 17 +#define BZ_X_BLKHDR_5 18 +#define BZ_X_BLKHDR_6 19 +#define BZ_X_BCRC_1 20 +#define BZ_X_BCRC_2 21 +#define BZ_X_BCRC_3 22 +#define BZ_X_BCRC_4 23 +#define BZ_X_RANDBIT 24 +#define BZ_X_ORIGPTR_1 25 +#define BZ_X_ORIGPTR_2 26 +#define BZ_X_ORIGPTR_3 27 +#define BZ_X_MAPPING_1 28 +#define BZ_X_MAPPING_2 29 +#define BZ_X_SELECTOR_1 30 +#define BZ_X_SELECTOR_2 31 +#define BZ_X_SELECTOR_3 32 +#define BZ_X_CODING_1 33 +#define BZ_X_CODING_2 34 +#define BZ_X_CODING_3 35 +#define BZ_X_MTF_1 36 +#define BZ_X_MTF_2 37 +#define BZ_X_MTF_3 38 +#define BZ_X_MTF_4 39 +#define BZ_X_MTF_5 40 +#define BZ_X_MTF_6 41 +#define BZ_X_ENDHDR_2 42 +#define BZ_X_ENDHDR_3 43 +#define BZ_X_ENDHDR_4 44 +#define BZ_X_ENDHDR_5 45 +#define BZ_X_ENDHDR_6 46 +#define BZ_X_CCRC_1 47 +#define BZ_X_CCRC_2 48 +#define BZ_X_CCRC_3 49 +#define BZ_X_CCRC_4 50 + + + +/*-- Constants for the fast MTF decoder. --*/ + +#define MTFA_SIZE 4096 +#define MTFL_SIZE 16 + + + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* state indicator for this stream */ + Int32 state; + + /* for doing the final run-length decoding */ + UChar state_out_ch; + Int32 state_out_len; + Bool blockRandomised; + BZ_RAND_DECLS; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 blockSize100k; + Bool smallDecompress; + Int32 currBlockNo; + Int32 verbosity; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + UInt32 tPos; + Int32 k0; + Int32 unzftab[256]; + Int32 nblock_used; + Int32 cftab[257]; + Int32 cftabCopy[257]; + + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 *tt; + + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 *ll16; + UChar *ll4; + + /* stored and calculated CRCs */ + UInt32 storedBlockCRC; + UInt32 storedCombinedCRC; + UInt32 calculatedBlockCRC; + UInt32 calculatedCombinedCRC; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + Bool inUse16[16]; + UChar seqToUnseq[256]; + + /* for decoding the MTF values */ + UChar mtfa [MTFA_SIZE]; + Int32 mtfbase[256 / MTFL_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + + Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 minLens[BZ_N_GROUPS]; + + /* save area for scalars in the main decompress code */ + Int32 save_i; + Int32 save_j; + Int32 save_t; + Int32 save_alphaSize; + Int32 save_nGroups; + Int32 save_nSelectors; + Int32 save_EOB; + Int32 save_groupNo; + Int32 save_groupPos; + Int32 save_nextSym; + Int32 save_nblockMAX; + Int32 save_nblock; + Int32 save_es; + Int32 save_N; + Int32 save_curr; + Int32 save_zt; + Int32 save_zn; + Int32 save_zvec; + Int32 save_zj; + Int32 save_gSel; + Int32 save_gMinlen; + Int32* save_gLimit; + Int32* save_gBase; + Int32* save_gPerm; + + } + DState; + + + +/*-- Macros for decompression. --*/ + +#define BZ_GET_FAST(cccc) \ + s->tPos = s->tt[s->tPos]; \ + cccc = (UChar)(s->tPos & 0xff); \ + s->tPos >>= 8; + +#define BZ_GET_FAST_C(cccc) \ + c_tPos = c_tt[c_tPos]; \ + cccc = (UChar)(c_tPos & 0xff); \ + c_tPos >>= 8; + +#define SET_LL4(i,n) \ + { if (((i) & 0x1) == 0) \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ + } + +#define GET_LL4(i) \ + ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) + +#define SET_LL(i,n) \ + { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ + SET_LL4(i, n >> 16); \ + } + +#define GET_LL(i) \ + (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) + +#define BZ_GET_SMALL(cccc) \ + cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ + s->tPos = GET_LL(s->tPos); + + +/*-- externs for decompression. --*/ + +extern Int32 +BZ2_indexIntoF ( Int32, Int32* ); + +extern Int32 +BZ2_decompress ( DState* ); + +extern void +BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#endif + + +/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ + +#ifdef BZ_NO_STDIO +#ifndef NULL +#define NULL 0 +#endif +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/compress.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/compress.c new file mode 100644 index 0000000..f6ff751 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/compress.c @@ -0,0 +1,716 @@ + +/*-------------------------------------------------------------*/ +/*--- Compression machinery (not incl block sorting) ---*/ +/*--- compress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * changed setting of nGroups in sendMTFValues() so as to + do a bit better on small files +--*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +void BZ2_bsInitWrite ( EState* s ) +{ + s->bsLive = 0; + s->bsBuff = 0; +} + + +/*---------------------------------------------------*/ +static +void bsFinishWrite ( EState* s ) +{ + while (s->bsLive > 0) { + s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } +} + + +/*---------------------------------------------------*/ +#define bsNEEDW(nz) \ +{ \ + while (s->bsLive >= 8) { \ + s->zbits[s->numZ] \ + = (UChar)(s->bsBuff >> 24); \ + s->numZ++; \ + s->bsBuff <<= 8; \ + s->bsLive -= 8; \ + } \ +} + + +/*---------------------------------------------------*/ +static +__inline__ +void bsW ( EState* s, Int32 n, UInt32 v ) +{ + bsNEEDW ( n ); + s->bsBuff |= (v << (32 - s->bsLive - n)); + s->bsLive += n; +} + + +/*---------------------------------------------------*/ +static +void bsPutUInt32 ( EState* s, UInt32 u ) +{ + bsW ( s, 8, (u >> 24) & 0xffL ); + bsW ( s, 8, (u >> 16) & 0xffL ); + bsW ( s, 8, (u >> 8) & 0xffL ); + bsW ( s, 8, u & 0xffL ); +} + + +/*---------------------------------------------------*/ +static +void bsPutUChar ( EState* s, UChar c ) +{ + bsW( s, 8, (UInt32)c ); +} + + +/*---------------------------------------------------*/ +/*--- The back end proper ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +static +void makeMaps_e ( EState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->unseqToSeq[i] = s->nInUse; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +static +void generateMTFValues ( EState* s ) +{ + UChar yy[256]; + Int32 i, j; + Int32 zPend; + Int32 wr; + Int32 EOB; + + /* + After sorting (eg, here), + s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, + and + ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] + holds the original block data. + + The first thing to do is generate the MTF values, + and put them in + ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. + Because there are strictly fewer or equal MTF values + than block values, ptr values in this area are overwritten + with MTF values only when they are no longer needed. + + The final compressed bitstream is generated into the + area starting at + (UChar*) (&((UChar*)s->arr2)[s->nblock]) + + These storage aliases are set up in bzCompressInit(), + except for the last one, which is arranged in + compressBlock(). + */ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt16* mtfv = s->mtfv; + + makeMaps_e ( s ); + EOB = s->nInUse+1; + + for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; + + wr = 0; + zPend = 0; + for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; + + for (i = 0; i < s->nblock; i++) { + UChar ll_i; + AssertD ( wr <= i, "generateMTFValues(1)" ); + j = ptr[i]-1; if (j < 0) j += s->nblock; + ll_i = s->unseqToSeq[block[j]]; + AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); + + if (yy[0] == ll_i) { + zPend++; + } else { + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + { + register UChar rtmp; + register UChar* ryy_j; + register UChar rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while ( rll_i != rtmp ) { + register UChar rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + }; + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; + } + + } + } + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + + mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; + + s->nMTF = wr; +} + + +/*---------------------------------------------------*/ +#define BZ_LESSER_ICOST 0 +#define BZ_GREATER_ICOST 15 + +static +void sendMTFValues ( EState* s ) +{ + Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; + Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; + Int32 nGroups, nBytes; + + /*-- + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + is a global since the decoder also needs it. + + Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + are also globals only used in this proc. + Made global to keep stack frame size small. + --*/ + + + UInt16 cost[BZ_N_GROUPS]; + Int32 fave[BZ_N_GROUPS]; + + UInt16* mtfv = s->mtfv; + + if (s->verbosity >= 3) + VPrintf3( " %d in block, %d after MTF & 1-2 coding, " + "%d+2 syms in use\n", + s->nblock, s->nMTF, s->nInUse ); + + alphaSize = s->nInUse+2; + for (t = 0; t < BZ_N_GROUPS; t++) + for (v = 0; v < alphaSize; v++) + s->len[t][v] = BZ_GREATER_ICOST; + + /*--- Decide how many coding tables to use ---*/ + AssertH ( s->nMTF > 0, 3001 ); + if (s->nMTF < 200) nGroups = 2; else + if (s->nMTF < 600) nGroups = 3; else + if (s->nMTF < 1200) nGroups = 4; else + if (s->nMTF < 2400) nGroups = 5; else + nGroups = 6; + + /*--- Generate an initial set of coding tables ---*/ + { + Int32 nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = s->nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs-1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize-1) { + ge++; + aFreq += s->mtfFreq[ge]; + } + + if (ge > gs + && nPart != nGroups && nPart != 1 + && ((nGroups-nPart) % 2 == 1)) { + aFreq -= s->mtfFreq[ge]; + ge--; + } + + if (s->verbosity >= 3) + VPrintf5( " initial group %d, [%d .. %d], " + "has %d syms (%4.1f%%)\n", + nPart, gs, ge, aFreq, + (100.0 * (float)aFreq) / (float)(s->nMTF) ); + + for (v = 0; v < alphaSize; v++) + if (v >= gs && v <= ge) + s->len[nPart-1][v] = BZ_LESSER_ICOST; else + s->len[nPart-1][v] = BZ_GREATER_ICOST; + + nPart--; + gs = ge+1; + remF -= aFreq; + } + } + + /*--- + Iterate up to BZ_N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZ_N_ITERS; iter++) { + + for (t = 0; t < nGroups; t++) fave[t] = 0; + + for (t = 0; t < nGroups; t++) + for (v = 0; v < alphaSize; v++) + s->rfreq[t][v] = 0; + + /*--- + Set up an auxiliary length table which is used to fast-track + the common case (nGroups == 6). + ---*/ + if (nGroups == 6) { + for (v = 0; v < alphaSize; v++) { + s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; + s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; + s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (True) { + + /*--- Set group start & end marks. --*/ + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (t = 0; t < nGroups; t++) cost[t] = 0; + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + register UInt32 cost01, cost23, cost45; + register UInt16 icv; + cost01 = cost23 = cost45 = 0; + +# define BZ_ITER(nn) \ + icv = mtfv[gs+(nn)]; \ + cost01 += s->len_pack[icv][0]; \ + cost23 += s->len_pack[icv][1]; \ + cost45 += s->len_pack[icv][2]; \ + + BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); + BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); + BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); + BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); + BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); + BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); + BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); + BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); + BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); + BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); + +# undef BZ_ITER + + cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; + cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; + cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + UInt16 icv = mtfv[i]; + for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; bt = -1; + for (t = 0; t < nGroups; t++) + if (cost[t] < bc) { bc = cost[t]; bt = t; }; + totc += bc; + fave[bt]++; + s->selector[nSelectors] = bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + +# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ + + BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); + BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); + BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); + BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); + BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); + BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); + BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); + BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); + BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); + BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); + +# undef BZ_ITUR + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) + s->rfreq[bt][ mtfv[i] ]++; + } + + gs = ge+1; + } + if (s->verbosity >= 3) { + VPrintf2 ( " pass %d: size is %d, grp uses are ", + iter+1, totc/8 ); + for (t = 0; t < nGroups; t++) + VPrintf1 ( "%d ", fave[t] ); + VPrintf0 ( "\n" ); + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See + comment in huffman.c for details. */ + for (t = 0; t < nGroups; t++) + BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), + alphaSize, 17 /*20*/ ); + } + + + AssertH( nGroups < 8, 3002 ); + AssertH( nSelectors < 32768 && + nSelectors <= (2 + (900000 / BZ_G_SIZE)), + 3003 ); + + + /*--- Compute MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) pos[i] = i; + for (i = 0; i < nSelectors; i++) { + ll_i = s->selector[i]; + j = 0; + tmp = pos[j]; + while ( ll_i != tmp ) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + }; + pos[0] = tmp; + s->selectorMtf[i] = j; + } + }; + + /*--- Assign actual codes for the tables. --*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + AssertH ( !(maxLen > 17 /*20*/ ), 3004 ); + AssertH ( !(minLen < 1), 3005 ); + BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), + minLen, maxLen, alphaSize ); + } + + /*--- Transmit the mapping table. ---*/ + { + Bool inUse16[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = False; + for (j = 0; j < 16; j++) + if (s->inUse[i * 16 + j]) inUse16[i] = True; + } + + nBytes = s->numZ; + for (i = 0; i < 16; i++) + if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); + + for (i = 0; i < 16; i++) + if (inUse16[i]) + for (j = 0; j < 16; j++) { + if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); + } + + if (s->verbosity >= 3) + VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes ); + } + + /*--- Now the selectors. ---*/ + nBytes = s->numZ; + bsW ( s, 3, nGroups ); + bsW ( s, 15, nSelectors ); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); + bsW(s,1,0); + } + if (s->verbosity >= 3) + VPrintf1( "selectors %d, ", s->numZ-nBytes ); + + /*--- Now the coding tables. ---*/ + nBytes = s->numZ; + + for (t = 0; t < nGroups; t++) { + Int32 curr = s->len[t][0]; + bsW ( s, 5, curr ); + for (i = 0; i < alphaSize; i++) { + while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; + while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; + bsW ( s, 1, 0 ); + } + } + + if (s->verbosity >= 3) + VPrintf1 ( "code lengths %d, ", s->numZ-nBytes ); + + /*--- And finally, the block data proper ---*/ + nBytes = s->numZ; + selCtr = 0; + gs = 0; + while (True) { + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + AssertH ( s->selector[selCtr] < nGroups, 3006 ); + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + UInt16 mtfv_i; + UChar* s_len_sel_selCtr + = &(s->len[s->selector[selCtr]][0]); + Int32* s_code_sel_selCtr + = &(s->code[s->selector[selCtr]][0]); + +# define BZ_ITAH(nn) \ + mtfv_i = mtfv[gs+(nn)]; \ + bsW ( s, \ + s_len_sel_selCtr[mtfv_i], \ + s_code_sel_selCtr[mtfv_i] ) + + BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); + BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); + BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); + BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); + BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); + BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); + BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); + BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); + BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); + BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); + +# undef BZ_ITAH + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + bsW ( s, + s->len [s->selector[selCtr]] [mtfv[i]], + s->code [s->selector[selCtr]] [mtfv[i]] ); + } + } + + + gs = ge+1; + selCtr++; + } + AssertH( selCtr == nSelectors, 3007 ); + + if (s->verbosity >= 3) + VPrintf1( "codes %d\n", s->numZ-nBytes ); +} + + +/*---------------------------------------------------*/ +void BZ2_compressBlock ( EState* s, Bool is_last_block ) +{ + if (s->nblock > 0) { + + BZ_FINALISE_CRC ( s->blockCRC ); + s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); + s->combinedCRC ^= s->blockCRC; + if (s->blockNo > 1) s->numZ = 0; + + if (s->verbosity >= 2) + VPrintf4( " block %d: crc = 0x%08x, " + "combined CRC = 0x%08x, size = %d\n", + s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); + + BZ2_blockSort ( s ); + } + + s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); + + /*-- If this is the first block, create the stream header. --*/ + if (s->blockNo == 1) { + BZ2_bsInitWrite ( s ); + bsPutUChar ( s, BZ_HDR_B ); + bsPutUChar ( s, BZ_HDR_Z ); + bsPutUChar ( s, BZ_HDR_h ); + bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) ); + } + + if (s->nblock > 0) { + + bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 ); + bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); + bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); + + /*-- Now the block's CRC, so it is in a known place. --*/ + bsPutUInt32 ( s, s->blockCRC ); + + /*-- + Now a single bit indicating (non-)randomisation. + As of version 0.9.5, we use a better sorting algorithm + which makes randomisation unnecessary. So always set + the randomised bit to 'no'. Of course, the decoder + still needs to be able to handle randomised blocks + so as to maintain backwards compatibility with + older versions of bzip2. + --*/ + bsW(s,1,0); + + bsW ( s, 24, s->origPtr ); + generateMTFValues ( s ); + sendMTFValues ( s ); + } + + + /*-- If this is the last block, add the stream trailer. --*/ + if (is_last_block) { + + bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 ); + bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); + bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); + bsPutUInt32 ( s, s->combinedCRC ); + if (s->verbosity >= 2) + VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/crctable.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/crctable.c new file mode 100644 index 0000000..26e4242 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/crctable.c @@ -0,0 +1,144 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for doing CRCs ---*/ +/*--- crctable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + +/*-- + I think this is an implementation of the AUTODIN-II, + Ethernet & FDDI 32-bit CRC standard. Vaguely derived + from code by Rob Warnock, in Section 51 of the + comp.compression FAQ. +--*/ + +UInt32 BZ2_crc32Table[256] = { + + /*-- Ugly, innit? --*/ + + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, + 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, + 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, + 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, + 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, + 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, + 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, + 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, + 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, + 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, + 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, + 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, + 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, + 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, + 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, + 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, + 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, + 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, + 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, + 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, + 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, + 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, + 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, + 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, + 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, + 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, + 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, + 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, + 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, + 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, + 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, + 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, + 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + + +/*-------------------------------------------------------------*/ +/*--- end crctable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/decompress.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/decompress.c new file mode 100644 index 0000000..ce02afa --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/decompress.c @@ -0,0 +1,666 @@ + +/*-------------------------------------------------------------*/ +/*--- Decompression machinery ---*/ +/*--- decompress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +static +void makeMaps_d ( DState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->seqToUnseq[s->nInUse] = i; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + while (True) { \ + if (s->bsLive >= nnn) { \ + UInt32 v; \ + v = (s->bsBuff >> \ + (s->bsLive-nnn)) & ((1 << nnn)-1); \ + s->bsLive -= nnn; \ + vvv = v; \ + break; \ + } \ + if (s->strm->avail_in == 0) RETURN(BZ_OK); \ + s->bsBuff \ + = (s->bsBuff << 8) | \ + ((UInt32) \ + (*((UChar*)(s->strm->next_in)))); \ + s->bsLive += 8; \ + s->strm->next_in++; \ + s->strm->avail_in--; \ + s->strm->total_in_lo32++; \ + if (s->strm->total_in_lo32 == 0) \ + s->strm->total_in_hi32++; \ + } + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (groupPos == 0) { \ + groupNo++; \ + if (groupNo >= nSelectors) \ + RETURN(BZ_DATA_ERROR); \ + groupPos = BZ_G_SIZE; \ + gSel = s->selector[groupNo]; \ + gMinlen = s->minLens[gSel]; \ + gLimit = &(s->limit[gSel][0]); \ + gPerm = &(s->perm[gSel][0]); \ + gBase = &(s->base[gSel][0]); \ + } \ + groupPos--; \ + zn = gMinlen; \ + GET_BITS(label1, zvec, zn); \ + while (1) { \ + if (zn > 20 /* the longest code */) \ + RETURN(BZ_DATA_ERROR); \ + if (zvec <= gLimit[zn]) break; \ + zn++; \ + GET_BIT(label2, zj); \ + zvec = (zvec << 1) | zj; \ + }; \ + if (zvec - gBase[zn] < 0 \ + || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ + RETURN(BZ_DATA_ERROR); \ + lval = gPerm[zvec - gBase[zn]]; \ +} + + +/*---------------------------------------------------*/ +Int32 BZ2_decompress ( DState* s ) +{ + UChar uc; + Int32 retVal; + Int32 minLen, maxLen; + bz_stream* strm = s->strm; + + /* stuff that needs to be saved/restored */ + Int32 i; + Int32 j; + Int32 t; + Int32 alphaSize; + Int32 nGroups; + Int32 nSelectors; + Int32 EOB; + Int32 groupNo; + Int32 groupPos; + Int32 nextSym; + Int32 nblockMAX; + Int32 nblock; + Int32 es; + Int32 N; + Int32 curr; + Int32 zt; + Int32 zn; + Int32 zvec; + Int32 zj; + Int32 gSel; + Int32 gMinlen; + Int32* gLimit; + Int32* gBase; + Int32* gPerm; + + if (s->state == BZ_X_MAGIC_1) { + /*initialise the save area*/ + s->save_i = 0; + s->save_j = 0; + s->save_t = 0; + s->save_alphaSize = 0; + s->save_nGroups = 0; + s->save_nSelectors = 0; + s->save_EOB = 0; + s->save_groupNo = 0; + s->save_groupPos = 0; + s->save_nextSym = 0; + s->save_nblockMAX = 0; + s->save_nblock = 0; + s->save_es = 0; + s->save_N = 0; + s->save_curr = 0; + s->save_zt = 0; + s->save_zn = 0; + s->save_zvec = 0; + s->save_zj = 0; + s->save_gSel = 0; + s->save_gMinlen = 0; + s->save_gLimit = NULL; + s->save_gBase = NULL; + s->save_gPerm = NULL; + } + + /*restore from the save area*/ + i = s->save_i; + j = s->save_j; + t = s->save_t; + alphaSize = s->save_alphaSize; + nGroups = s->save_nGroups; + nSelectors = s->save_nSelectors; + EOB = s->save_EOB; + groupNo = s->save_groupNo; + groupPos = s->save_groupPos; + nextSym = s->save_nextSym; + nblockMAX = s->save_nblockMAX; + nblock = s->save_nblock; + es = s->save_es; + N = s->save_N; + curr = s->save_curr; + zt = s->save_zt; + zn = s->save_zn; + zvec = s->save_zvec; + zj = s->save_zj; + gSel = s->save_gSel; + gMinlen = s->save_gMinlen; + gLimit = s->save_gLimit; + gBase = s->save_gBase; + gPerm = s->save_gPerm; + + retVal = BZ_OK; + + switch (s->state) { + + GET_UCHAR(BZ_X_MAGIC_1, uc); + if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_2, uc); + if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_3, uc) + if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) + if (s->blockSize100k < (BZ_HDR_0 + 1) || + s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC); + s->blockSize100k -= BZ_HDR_0; + + if (s->smallDecompress) { + s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); + s->ll4 = BZALLOC( + ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) + ); + if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); + } else { + s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); + if (s->tt == NULL) RETURN(BZ_MEM_ERROR); + } + + GET_UCHAR(BZ_X_BLKHDR_1, uc); + + if (uc == 0x17) goto endhdr_2; + if (uc != 0x31) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_2, uc); + if (uc != 0x41) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_3, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_4, uc); + if (uc != 0x26) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_5, uc); + if (uc != 0x53) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_6, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + + s->currBlockNo++; + if (s->verbosity >= 2) + VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); + + s->storedBlockCRC = 0; + GET_UCHAR(BZ_X_BCRC_1, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_2, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_3, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_4, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + + GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); + + s->origPtr = 0; + GET_UCHAR(BZ_X_ORIGPTR_1, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_2, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_3, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + + if (s->origPtr < 0) + RETURN(BZ_DATA_ERROR); + if (s->origPtr > 10 + 100000*s->blockSize100k) + RETURN(BZ_DATA_ERROR); + + /*--- Receive the mapping table ---*/ + for (i = 0; i < 16; i++) { + GET_BIT(BZ_X_MAPPING_1, uc); + if (uc == 1) + s->inUse16[i] = True; else + s->inUse16[i] = False; + } + + for (i = 0; i < 256; i++) s->inUse[i] = False; + + for (i = 0; i < 16; i++) + if (s->inUse16[i]) + for (j = 0; j < 16; j++) { + GET_BIT(BZ_X_MAPPING_2, uc); + if (uc == 1) s->inUse[i * 16 + j] = True; + } + makeMaps_d ( s ); + if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); + alphaSize = s->nInUse+2; + + /*--- Now the selectors ---*/ + GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); + if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); + if (nSelectors < 1) RETURN(BZ_DATA_ERROR); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (True) { + GET_BIT(BZ_X_SELECTOR_3, uc); + if (uc == 0) break; + j++; + if (j >= nGroups) RETURN(BZ_DATA_ERROR); + } + s->selectorMtf[i] = j; + } + + /*--- Undo the MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], tmp, v; + for (v = 0; v < nGroups; v++) pos[v] = v; + + for (i = 0; i < nSelectors; i++) { + v = s->selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { pos[v] = pos[v-1]; v--; } + pos[0] = tmp; + s->selector[i] = tmp; + } + } + + /*--- Now the coding tables ---*/ + for (t = 0; t < nGroups; t++) { + GET_BITS(BZ_X_CODING_1, curr, 5); + for (i = 0; i < alphaSize; i++) { + while (True) { + if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); + GET_BIT(BZ_X_CODING_2, uc); + if (uc == 0) break; + GET_BIT(BZ_X_CODING_3, uc); + if (uc == 0) curr++; else curr--; + } + s->len[t][i] = curr; + } + } + + /*--- Create the Huffman decoding tables ---*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + BZ2_hbCreateDecodeTables ( + &(s->limit[t][0]), + &(s->base[t][0]), + &(s->perm[t][0]), + &(s->len[t][0]), + minLen, maxLen, alphaSize + ); + s->minLens[t] = minLen; + } + + /*--- Now the MTF values ---*/ + + EOB = s->nInUse+1; + nblockMAX = 100000 * s->blockSize100k; + groupNo = -1; + groupPos = 0; + + for (i = 0; i <= 255; i++) s->unzftab[i] = 0; + + /*-- MTF init --*/ + { + Int32 ii, jj, kk; + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + /*-- end MTF init --*/ + + nblock = 0; + GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); + + while (True) { + + if (nextSym == EOB) break; + + if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + + es = -1; + N = 1; + do { + if (nextSym == BZ_RUNA) es = es + (0+1) * N; else + if (nextSym == BZ_RUNB) es = es + (1+1) * N; + N = N * 2; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); + + es++; + uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; + s->unzftab[uc] += es; + + if (s->smallDecompress) + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->ll16[nblock] = (UInt16)uc; + nblock++; + es--; + } + else + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->tt[nblock] = (UInt32)uc; + nblock++; + es--; + }; + + continue; + + } else { + + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + + /*-- uc = MTF ( nextSym-1 ) --*/ + { + Int32 ii, jj, kk, pp, lno, off; + UInt32 nn; + nn = (UInt32)(nextSym - 1); + + if (nn < MTFL_SIZE) { + /* avoid general-case expense */ + pp = s->mtfbase[0]; + uc = s->mtfa[pp+nn]; + while (nn > 3) { + Int32 z = pp+nn; + s->mtfa[(z) ] = s->mtfa[(z)-1]; + s->mtfa[(z)-1] = s->mtfa[(z)-2]; + s->mtfa[(z)-2] = s->mtfa[(z)-3]; + s->mtfa[(z)-3] = s->mtfa[(z)-4]; + nn -= 4; + } + while (nn > 0) { + s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; + }; + s->mtfa[pp] = uc; + } else { + /* general case */ + lno = nn / MTFL_SIZE; + off = nn % MTFL_SIZE; + pp = s->mtfbase[lno] + off; + uc = s->mtfa[pp]; + while (pp > s->mtfbase[lno]) { + s->mtfa[pp] = s->mtfa[pp-1]; pp--; + }; + s->mtfbase[lno]++; + while (lno > 0) { + s->mtfbase[lno]--; + s->mtfa[s->mtfbase[lno]] + = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; + lno--; + } + s->mtfbase[0]--; + s->mtfa[s->mtfbase[0]] = uc; + if (s->mtfbase[0] == 0) { + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + } + } + /*-- end uc = MTF ( nextSym-1 ) --*/ + + s->unzftab[s->seqToUnseq[uc]]++; + if (s->smallDecompress) + s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else + s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); + nblock++; + + GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); + continue; + } + } + + /* Now we know what nblock is, we can do a better sanity + check on s->origPtr. + */ + if (s->origPtr < 0 || s->origPtr >= nblock) + RETURN(BZ_DATA_ERROR); + + /*-- Set up cftab to facilitate generation of T^(-1) --*/ + s->cftab[0] = 0; + for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; + for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + for (i = 0; i <= 256; i++) { + if (s->cftab[i] < 0 || s->cftab[i] > nblock) { + /* s->cftab[i] can legitimately be == nblock */ + RETURN(BZ_DATA_ERROR); + } + } + + s->state_out_len = 0; + s->state_out_ch = 0; + BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); + s->state = BZ_X_OUTPUT; + if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); + + if (s->smallDecompress) { + + /*-- Make a copy of cftab, used in generation of T --*/ + for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; + + /*-- compute the T vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->ll16[i]); + SET_LL(i, s->cftabCopy[uc]); + s->cftabCopy[uc]++; + } + + /*-- Compute T^(-1) by pointer reversal on T --*/ + i = s->origPtr; + j = GET_LL(i); + do { + Int32 tmp = GET_LL(j); + SET_LL(j, i); + i = j; + j = tmp; + } + while (i != s->origPtr); + + s->tPos = s->origPtr; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_SMALL(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } else { + + /*-- compute the T^(-1) vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->tt[i] & 0xff); + s->tt[s->cftab[uc]] |= (i << 8); + s->cftab[uc]++; + } + + s->tPos = s->tt[s->origPtr] >> 8; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_FAST(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_FAST(s->k0); s->nblock_used++; + } + + } + + RETURN(BZ_OK); + + + + endhdr_2: + + GET_UCHAR(BZ_X_ENDHDR_2, uc); + if (uc != 0x72) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_3, uc); + if (uc != 0x45) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_4, uc); + if (uc != 0x38) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_5, uc); + if (uc != 0x50) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_6, uc); + if (uc != 0x90) RETURN(BZ_DATA_ERROR); + + s->storedCombinedCRC = 0; + GET_UCHAR(BZ_X_CCRC_1, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_2, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_3, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_4, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + + s->state = BZ_X_IDLE; + RETURN(BZ_STREAM_END); + + default: AssertH ( False, 4001 ); + } + + AssertH ( False, 4002 ); + + save_state_and_return: + + s->save_i = i; + s->save_j = j; + s->save_t = t; + s->save_alphaSize = alphaSize; + s->save_nGroups = nGroups; + s->save_nSelectors = nSelectors; + s->save_EOB = EOB; + s->save_groupNo = groupNo; + s->save_groupPos = groupPos; + s->save_nextSym = nextSym; + s->save_nblockMAX = nblockMAX; + s->save_nblock = nblock; + s->save_es = es; + s->save_N = N; + s->save_curr = curr; + s->save_zt = zt; + s->save_zn = zn; + s->save_zvec = zvec; + s->save_zj = zj; + s->save_gSel = gSel; + s->save_gMinlen = gMinlen; + s->save_gLimit = gLimit; + s->save_gBase = gBase; + s->save_gPerm = gPerm; + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/huffman.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/huffman.c new file mode 100644 index 0000000..a15a259 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/huffman.c @@ -0,0 +1,245 @@ + +/*-------------------------------------------------------------*/ +/*--- Huffman coding low-level stuff ---*/ +/*--- huffman.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + +/*---------------------------------------------------*/ +#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) +#define DEPTHOF(zz1) ((zz1) & 0x000000ff) +#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) + +#define ADDWEIGHTS(zw1,zw2) \ + (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ + (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) + +#define UPHEAP(z) \ +{ \ + Int32 zz, tmp; \ + zz = z; tmp = heap[zz]; \ + while (weight[tmp] < weight[heap[zz >> 1]]) { \ + heap[zz] = heap[zz >> 1]; \ + zz >>= 1; \ + } \ + heap[zz] = tmp; \ +} + +#define DOWNHEAP(z) \ +{ \ + Int32 zz, yy, tmp; \ + zz = z; tmp = heap[zz]; \ + while (True) { \ + yy = zz << 1; \ + if (yy > nHeap) break; \ + if (yy < nHeap && \ + weight[heap[yy+1]] < weight[heap[yy]]) \ + yy++; \ + if (weight[tmp] < weight[heap[yy]]) break; \ + heap[zz] = heap[yy]; \ + zz = yy; \ + } \ + heap[zz] = tmp; \ +} + + +/*---------------------------------------------------*/ +void BZ2_hbMakeCodeLengths ( UChar *len, + Int32 *freq, + Int32 alphaSize, + Int32 maxLen ) +{ + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + Int32 nNodes, nHeap, n1, n2, i, j, k; + Bool tooLong; + + Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; + Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; + Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; + + for (i = 0; i < alphaSize; i++) + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + + while (True) { + + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + UPHEAP(nHeap); + } + + AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); + + while (nHeap > 1) { + n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + nNodes++; + parent[n1] = parent[n2] = nNodes; + weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + UPHEAP(nHeap); + } + + AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); + + tooLong = False; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { k = parent[k]; j++; } + len[i-1] = j; + if (j > maxLen) tooLong = True; + } + + if (! tooLong) break; + + /* 17 Oct 04: keep-going condition for the following loop used + to be 'i < alphaSize', which missed the last element, + theoretically leading to the possibility of the compressor + looping. However, this count-scaling step is only needed if + one of the generated Huffman code words is longer than + maxLen, which up to and including version 1.0.2 was 20 bits, + which is extremely unlikely. In version 1.0.3 maxLen was + changed to 17 bits, which has minimal effect on compression + ratio, but does mean this scaling step is used from time to + time, enough to verify that it works. + + This means that bzip2-1.0.3 and later will only produce + Huffman codes with a maximum length of 17 bits. However, in + order to preserve backwards compatibility with bitstreams + produced by versions pre-1.0.3, the decompressor must still + handle lengths of up to 20. */ + + for (i = 1; i <= alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbAssignCodes ( Int32 *code, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) + if (length[i] == n) { code[i] = vec; vec++; }; + vec <<= 1; + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbCreateDecodeTables ( Int32 *limit, + Int32 *base, + Int32 *perm, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) + for (j = 0; j < alphaSize; j++) + if (length[j] == i) { perm[pp] = j; pp++; }; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; + for (i = 0; i < alphaSize; i++) base[length[i]+1]++; + + for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (base[i+1] - base[i]); + limit[i] = vec-1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) + base[i] = ((limit[i-1] + 1) << 1) - base[i]; +} + + +/*-------------------------------------------------------------*/ +/*--- end huffman.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2/randtable.c b/plugins/cdvd/CDVDisoEFP/src/bzip2/randtable.c new file mode 100644 index 0000000..27b28d1 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2/randtable.c @@ -0,0 +1,124 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2005 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@bzip.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------*/ +Int32 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2v2.c b/plugins/cdvd/CDVDisoEFP/src/bzip2v2.c new file mode 100644 index 0000000..e93811a --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2v2.c @@ -0,0 +1,1052 @@ +/* bzip2v2.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // malloc() + +#include // off64_t + + + +#include "bzip2/bzlib.h" + + + +#include "convert.h" + +#include "logfile.h" + +#include "isofile.h" // IsoFile + +#include "isocompress.h" // TableData, TableMap + +#include "actualfile.h" + +// #include "convert.h" + +#include "bzip2v2.h" + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct BZip2V2Header { + + char id[4]; + + unsigned int blocksize; + + unsigned int numblocks; + + unsigned int blockoffset; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct BZip2V2Table { + + unsigned int size; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +int BZip2V2OpenTableForRead(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + off64_t numentries; + + off64_t offset; + + off64_t actual; + + int tableoffset; + + struct BZip2V2Table table; + + int retval; + + union TableMap tablemap; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: OpenTableForRead()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForRead(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + numentries = isofile->filesectorsize / 16; + + if((isofile->filesectorsize % 16) != 0) numentries++; + + offset = numentries * sizeof(struct BZip2V2Table); + + actual = ActualFileSize(isofile->tablehandle); + + if(offset != actual) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Table not the correct size! (Should be %lli, is %lli)", + + offset, actual); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Not the correct-sized table for the data file? Fail. + + + + // We pre-read the WHOLE offset table. + + isofile->tabledata = (char *) malloc(numentries * sizeof(struct TableData)); + + if(isofile->tabledata == NULL) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't allocate internal table!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Could not get enough memory to hold table data + + + + offset = sizeof(struct BZip2V2Header); + + tableoffset = 0; + + for(i = 0; i < numentries; i++) { + + retval = ActualFileRead(isofile->tablehandle, + + sizeof(struct BZip2V2Table), + + (char *) &table); + + if(retval != sizeof(struct BZip2V2Table)) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Failed to read in entry %i!", i); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Trouble reading in a size? Table damaged... fail. + + + + tablemap.table.offset = offset; + + tablemap.table.size = ConvertEndianUInt(table.size); + + for(j = 0; j < sizeof(struct TableData); j++) + + *(isofile->tabledata + tableoffset + j) = tablemap.ch[j]; + + offset += tablemap.table.size; + + tableoffset += sizeof(struct TableData); + + } // NEXT i- reading in the sizes, and making offset as I go. + + + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + return(0); + +} // END BZip2V2OpenTableForRead() + + + + + +int BZip2V2SeekTable(struct IsoFile *isofile, off64_t sector) { + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: SeekTable(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + isofile->filesectorpos = sector; + + isofile->compsector = isofile->filesectorsize + isofile->numsectors; + + return(0); + +} // END BZip2V2SeekTable() + + + + + +int BZip2V2ReadTable(struct IsoFile *isofile, struct TableData *table) { + + off64_t target; + + union TableMap tablemap; + + off64_t i; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: ReadTable()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + target = (isofile->filesectorpos / isofile->numsectors) + + * sizeof(struct TableData); + + for(i = 0; i < sizeof(struct TableData); i++) + + tablemap.ch[i] = *(isofile->tabledata + target + i); + + + + table->offset = tablemap.table.offset; + + table->size = tablemap.table.size; + + return(0); + +} // END BZip2V2ReadTable() + + + + + +int BZip2V2OpenTableForWrite(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: OpenTableForWrite()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForWrite(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + // isofile->filesectorsize = 0; + + return(0); + +} // END BZip2V2OpenTableForWrite() + + + + + +int BZip2V2WriteTable(struct IsoFile *isofile, struct TableData table) { + + int retval; + + struct BZip2V2Table bv2table; + + unsigned int tempint; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: WriteTable(%lli, %i)", table.offset, table.size); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + tempint = table.size; + + bv2table.size = ConvertEndianUInt(tempint); + + retval = ActualFileWrite(isofile->tablehandle, + + sizeof(struct BZip2V2Table), + + (char *) &bv2table); + + if(retval != sizeof(struct BZip2V2Table)) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't write table entry!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + return(0); + +} // END BZip2V2WriteTable() + + + + + +int BZip2V2OpenForRead(struct IsoFile *isofile) { + + int retval; + + struct BZip2V2Header header; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + + + isofile->imageheader = 0; + + isofile->numsectors = 16; // Sectors per block + + + + retval = ActualFileRead(isofile->handle, + + sizeof(struct BZip2V2Header), + + (char *) &header); + + if(retval != sizeof(struct BZip2V2Header)) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't read header!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF Could not read the first sector? Fail. + + isofile->filebytepos += retval; + + + + if((header.id[0] != 'B') || + + (header.id[1] != 'Z') || + + (header.id[2] != 'V') || + + (header.id[3] != '2')) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Not a bzip2 v2 compression header!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF- ID for this compression type doesn't match? + + + + isofile->blocksize = ConvertEndianUInt(header.blocksize); + + isofile->filesectorsize = ConvertEndianUInt(header.numblocks); + + isofile->blockoffset = ConvertEndianUInt(header.blockoffset); + + isofile->filesectorpos = 0; + + isofile->compsector = header.numblocks + isofile->numsectors; + + return(0); + +} // END BZip2V2OpenForRead() + + + + + +int BZip2V2Seek(struct IsoFile *isofile, off64_t position) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Seek(%lli)", position); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + retval = ActualFileSeek(isofile->handle, position); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Couldn't find the start of the compressed block!"); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-1); + + } // ENDIF- Couldn't find the data entry? Fail. + + isofile->filebytepos = position; + + return(0); + + + + return(-1); // Fail. (Due to lack of ambition?) + +} // END BZip2V2Seek() + + + + + +int BZip2V2Read(struct IsoFile *isofile, int bytes, char *buffer) { + + int retval; + + unsigned int blocklen; + + bz_stream strm; + + unsigned int tempin; + + char tempblock[65536]; + + unsigned int tempout; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Read(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + if(bytes > 0) { + + retval = ActualFileRead(isofile->handle, bytes, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != bytes) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + blocklen = 65536; + + retval = BZ2_bzBuffToBuffDecompress(buffer, &blocklen, tempblock, bytes, 0, 0); + + if(retval != BZ_OK) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Cannot decode block! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-1); + + } // ENDIF- Trouble decoding the sector? Abort. + + + + return(0); + + } // ENDIF- Do we know how many compressed bytes to get for this record? + + + + // Hmm. Don't know the compressed size? Well, we'll just have to find it. + + + + tempin = 0; + + tempout = 0; + + retval = BZ_OK; + + while((tempin < 65536) && (tempout < isofile->blocksize * isofile->numsectors)) { + + strm.bzalloc = NULL; + + strm.bzfree = NULL; + + strm.opaque = NULL; + + retval = BZ2_bzDecompressInit ( &strm, 0, 0 ); + + if (retval != BZ_OK) return(-1); + + + + strm.next_out = buffer; + + + + strm.avail_in = tempin; + + strm.avail_out = 65536; + + + + retval = BZ_OK; + + while((tempin < 65536) && (retval == BZ_OK)) { + + retval = ActualFileRead(isofile->handle, 1, &tempblock[tempin]); + + if(retval != 1) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Cannot read a byte! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + BZ2_bzDecompressEnd(&strm); + + return(-1); + + } // ENDIF- Trouble reading a piece of compressed sector? Abort. + + tempin++; + + strm.avail_in++; + + + + strm.next_in = &tempblock[tempin - strm.avail_in]; + + retval = BZ2_bzDecompress(&strm); + + } // ENDWHILE- trying to uncompress an increasingly filled buffer + + tempout = 65536 - strm.avail_out; + + BZ2_bzDecompressEnd(&strm); + + + + } // ENDWHILE- trying to uncompress a whole buffer + + if(retval != BZ_STREAM_END) { + +#ifdef VERBOSE_WARNING_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Failed to decode block! (Returned %i", retval); + +#endif /* VERBOSE_WARNING_BZIP2V2 */ + + return(-1); + + } // ENDIF- Not a clean cutoff of a buffer? Say so. + + + + if(tempin == 65536) return(-1); + + isofile->filebytepos += tempin; + + return(tempin); // Send out # of compressed bytes (to record in table) + +} // END BZip2V2Read() + + + + + +int BZip2V2OpenForWrite(struct IsoFile *isofile) { + + char garbage[sizeof(struct BZip2V2Header)]; + + int i; + + + + if(isofile == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: OpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + isofile->handle = ActualFileOpenForWrite(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + for(i = 0; i < sizeof(struct BZip2V2Header); i++) garbage[i] = 0; + + ActualFileWrite(isofile->handle, sizeof(struct BZip2V2Header), garbage); + + + + isofile->filebytesize = 0; + + isofile->filebytepos = sizeof(struct BZip2V2Header); + + isofile->numsectors = 16; + + isofile->filesectorsize = 0; + + isofile->filesectorpos = 0; + + isofile->compsector = 0; + + return(0); + +} // END BZip2V2OpenForWrite() + + + + + +int BZip2V2Write(struct IsoFile *isofile, char *buffer) { + + int retval; + + unsigned int blocklen; + + char tempblock[65536]; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Write()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + blocklen = 65536; + + retval = BZ2_bzBuffToBuffCompress(tempblock, + + &blocklen, + + buffer, + + isofile->blocksize * isofile->numsectors, + + 9, 0, 250); + + if(retval != BZ_OK) { + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Cannot encode block! Returned: (%i)", retval); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + return(-1); + + } // ENDIF- Trouble compressing a block? Abort. + + + + retval = ActualFileWrite(isofile->handle, blocklen, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval < blocklen) { + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Cannot write bytes! Returned: (%i out of %llu)", + + retval, blocklen); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + return(-1); + + } // ENDIF- Trouble writing out the compressed block? Abort. + + + + return(blocklen); // Not in list? Fail. + +} // END BZip2V2Write() + + + + + +void BZip2V2Close(struct IsoFile *isofile) { + + struct BZip2V2Header header; + + struct TableData table; + + int compptr; + + int i; + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V2 + + PrintLog("CDVDiso BZip2V2: Close()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V2 */ + + + + if((isofile->tablehandle != ACTUALHANDLENULL) && + + (isofile->handle != ACTUALHANDLENULL)) { + + if(isofile->openforread == 0) { + + if(isofile->compsector != isofile->filesectorpos) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = compptr; i < 65536; i++) isofile->compblock[i] = 0; + + retval = BZip2V2Write(isofile, isofile->compblock); + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + BZip2V2WriteTable(isofile, table); + + isofile->compsector = isofile->filesectorpos; + + } // ENDIF - still have buffers to write? + + } // ENDIF- Opened for write? Don't forget to flush the file buffer! + + } // ENDIF- Are both the data file and table files open? + + + + if(isofile->tablehandle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + } // ENDIF- Is there a table file open? Close it. + + + + if(isofile->handle != ACTUALHANDLENULL) { + + if(isofile->openforread == 0) { + + if(isofile->compsector != isofile->filesectorpos) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = compptr; i < 65536; i++) isofile->compblock[i] = 0; + + BZip2V2Write(isofile, isofile->compblock); + + } // ENDIF - still have buffers to write? + + header.id[0] = 'B'; + + header.id[1] = 'Z'; + + header.id[2] = 'V'; + + header.id[3] = '2'; + + header.blocksize = ConvertEndianUInt(isofile->blocksize); + + header.numblocks = ConvertEndianUInt(isofile->filesectorsize); + + header.blockoffset = ConvertEndianUInt(isofile->blockoffset); + + ActualFileSeek(isofile->handle, 0); + + ActualFileWrite(isofile->handle, + + sizeof(struct BZip2V2Header), + + (char *) &header); + + } // ENDIF- Opened for write? Don't forget to update the header block! + + + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Is there a data file open? Close it. + + + + if(isofile->tabledata != NULL) { + + free(isofile->tabledata); + + isofile->tabledata = NULL; + + } // ENDIF- Do we have a read-in table to clear out? + + + + return; + +} // END BZip2V2Close() + diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2v2.h b/plugins/cdvd/CDVDisoEFP/src/bzip2v2.h new file mode 100644 index 0000000..8ecd464 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2v2.h @@ -0,0 +1,104 @@ +/* bzip2v2.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef BZIP2V2_H + +#define BZIP2V2_H + + + + + +#include + + + +#include "isofile.h" + +#include "isocompress.h" + + + + + +// #define VERBOSE_FUNCTION_BZIP2V2 + +// #define VERBOSE_WARNING_BZIP2V2 + + + + + +extern int BZip2V2OpenTableForRead(struct IsoFile *isofile); + +extern int BZip2V2SeekTable(struct IsoFile *isofile, off64_t sector); + +extern int BZip2V2ReadTable(struct IsoFile *isofile, struct TableData *table); + + + +extern int BZip2V2OpenTableForWrite(struct IsoFile *isofile); + +extern int BZip2V2WriteTable(struct IsoFile *isofile, struct TableData table); + + + +extern int BZip2V2OpenForRead(struct IsoFile *isofile); + +extern int BZip2V2Seek(struct IsoFile *isofile, off64_t sector); + +extern int BZip2V2Read(struct IsoFile *isofile, int bytes, char *buffer); + +extern void BZip2V2Close(struct IsoFile *isofile); + + + +extern int BZip2V2OpenForWrite(struct IsoFile *isofile); + +extern int BZip2V2Write(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* BZIP2V2_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2v3.c b/plugins/cdvd/CDVDisoEFP/src/bzip2v3.c new file mode 100644 index 0000000..2c1b253 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2v3.c @@ -0,0 +1,968 @@ +/* bzip2v3.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // malloc() + +#include // off64_t + + + +#include "bzip2/bzlib.h" + + + +#include "convert.h" + +#include "logfile.h" + +#include "isofile.h" // IsoFile + +#include "isocompress.h" // TableData, TableMap + +#include "actualfile.h" + +#include "convert.h" + +#include "bzip2v3.h" + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct BZip2V3Header { + + char id[4]; + + unsigned short blocksize; + + off64_t numblocks; + + unsigned short blockoffset; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct BZip2V3Table { + + off64_t offset; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +int BZip2V3OpenTableForRead(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + off64_t numentries; + + off64_t offset; + + off64_t actual; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: OpenTableForRead()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForRead(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + numentries = isofile->filesectorsize / isofile->numsectors; + + if((isofile->filesectorsize % isofile->numsectors) != 0) numentries++; + + offset = numentries * sizeof(struct BZip2V3Table); + + actual = ActualFileSize(isofile->tablehandle); + + if(offset != actual) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Table not the correct size! (Should be %lli, is %lli)", + + offset, actual); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Not the correct-sized table for the data file? Fail. + + + + return(0); + +} // END BZip2V3OpenTableForRead() + + + + + +int BZip2V3SeekTable(struct IsoFile *isofile, off64_t sector) { + + off64_t target; + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: SeekTable(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + target = sector / isofile->numsectors; + + target *= sizeof(struct BZip2V3Table); + + retval = ActualFileSeek(isofile->tablehandle, target); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't find sector!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Trouble finding the place? Fail. + + + + isofile->filesectorpos = sector; + + isofile->compsector = isofile->filesectorsize + isofile->numsectors; + + return(0); + +} // END BZip2V3SeekTable() + + + + + +int BZip2V3ReadTable(struct IsoFile *isofile, struct TableData *table) { + + int retval; + + struct BZip2V3Table temptable; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: ReadTable()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + retval = ActualFileRead(isofile->tablehandle, + + sizeof(struct BZip2V3Table), + + (char *) &temptable); + + if(retval != sizeof(struct BZip2V3Table)) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't read table entry!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + table->offset = ConvertEndianOffset(temptable.offset); + + table->size = 0; + + return(0); + +} // END BZip2V3ReadTable() + + + + + +int BZip2V3OpenTableForWrite(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: OpenTableForWrite()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForWrite(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + // isofile->filesectorsize = 0; + + return(0); + +} // END BZip2V3OpenTableForWrite() + + + + + +int BZip2V3WriteTable(struct IsoFile *isofile, struct TableData table) { + + int retval; + + struct BZip2V3Table bv3table; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: WriteTable(%lli, %i)", table.offset, table.size); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + bv3table.offset = ConvertEndianOffset(table.offset); + + retval = ActualFileWrite(isofile->tablehandle, + + sizeof(struct BZip2V3Table), + + (char *) &bv3table); + + if(retval != sizeof(struct BZip2V3Table)) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't write table entry!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + return(0); + +} // END BZip2V3WriteTable() + + + + + +int BZip2V3OpenForRead(struct IsoFile *isofile) { + + int retval; + + struct BZip2V3Header header; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + + + isofile->imageheader = 0; + + + + retval = ActualFileRead(isofile->handle, + + sizeof(struct BZip2V3Header), + + (char *) &header); + + if(retval != sizeof(struct BZip2V3Header)) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't read header!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF Could not read the first sector? Fail. + + isofile->filebytepos += retval; + + + + if((header.id[0] != 'B') || + + (header.id[1] != 'Z') || + + (header.id[2] != 'V') || + + (header.id[3] != '3')) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Not a bzip2 v3 compression header!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF- ID for this compression type doesn't match? + + + + isofile->blocksize = ConvertEndianUShort(header.blocksize); + + isofile->filesectorsize = ConvertEndianOffset(header.numblocks); + + isofile->blockoffset = ConvertEndianUShort(header.blockoffset); + + isofile->numsectors = (65536 / isofile->blocksize) - 1; + + isofile->filesectorpos = 0; + + isofile->compsector = header.numblocks + isofile->numsectors; + + return(0); + +} // END BZip2V3OpenForRead() + + + + + +int BZip2V3Seek(struct IsoFile *isofile, off64_t position) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Seek(%lli)", position); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + retval = ActualFileSeek(isofile->handle, position); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Couldn't find the start of the compressed block!"); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-1); + + } // ENDIF- Couldn't find the data entry? Fail. + + isofile->filebytepos = position; + + return(0); + + + + return(-1); // Fail. (Due to lack of ambition?) + +} // END BZip2V3Seek() + + + + + +int BZip2V3Read(struct IsoFile *isofile, int bytes, char *buffer) { + + int retval; + + unsigned short tempsize; + + char tempblock[65536]; + + unsigned int blocklen; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Read()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + retval = ActualFileRead(isofile->handle, + + sizeof(unsigned short), + + (char *) &tempsize); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != sizeof(unsigned short)) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + tempsize = ConvertEndianUShort(tempsize); + + + + retval = ActualFileRead(isofile->handle, tempsize, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != tempsize) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + blocklen = 65536; + + retval = BZ2_bzBuffToBuffDecompress(buffer, &blocklen, tempblock, tempsize, 0, 0); + + if(retval != BZ_OK) { + +#ifdef VERBOSE_WARNING_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot decode block! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble decoding the sector? Abort. + + + + return(tempsize + sizeof(unsigned short)); + +} // END BZip2V3Read() + + + + + +int BZip2V3OpenForWrite(struct IsoFile *isofile) { + + char garbage[sizeof(struct BZip2V3Header)]; + + int i; + + + + if(isofile == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: OpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + isofile->handle = ActualFileOpenForWrite(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + for(i = 0; i < sizeof(struct BZip2V3Header); i++) garbage[i] = 0; + + ActualFileWrite(isofile->handle, sizeof(struct BZip2V3Header), garbage); + + + + isofile->filebytesize = 0; + + isofile->filebytepos = sizeof(struct BZip2V3Header); + + isofile->numsectors = (65536 / isofile->blocksize) - 1; + + isofile->filesectorsize = 0; + + isofile->filesectorpos = 0; + + isofile->compsector = 0; + + return(0); + +} // END BZip2V3OpenForWrite() + + + + + +int BZip2V3Write(struct IsoFile *isofile, char *buffer) { + + int retval; + + unsigned int blocklen; + + char tempblock[65536]; + + unsigned short tempsize; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Write()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + blocklen = 65536; + + retval = BZ2_bzBuffToBuffCompress(tempblock, + + &blocklen, + + buffer, + + isofile->blocksize * isofile->numsectors, + + 9, 0, 250); + + if(retval != BZ_OK) { + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot encode block! Returned: (%i)", retval); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble compressing a block? Abort. + + + + tempsize = blocklen; + + tempsize = ConvertEndianUShort(tempsize); + + retval = ActualFileWrite(isofile->handle, + + sizeof(unsigned short), + + (char *) &tempsize); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval < sizeof(unsigned short)) { + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot write bytes! Returned: (%i out of %llu)", + + retval, sizeof(unsigned short)); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble writing out the compressed block? Abort. + + + + + + retval = ActualFileWrite(isofile->handle, blocklen, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval < blocklen) { + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Cannot write bytes! Returned: (%i out of %llu)", + + retval, blocklen); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + return(-1); + + } // ENDIF- Trouble writing out the compressed block? Abort. + + + + return(blocklen + sizeof(unsigned short)); // Not in list? Fail. + +} // END BZip2V3Write() + + + + + +void BZip2V3Close(struct IsoFile *isofile) { + + struct BZip2V3Header header; + + struct TableData table; + + int compptr; + + int i; + + int retval; + + unsigned short tempsize; + + + +#ifdef VERBOSE_FUNCTION_BZIP2V3 + + PrintLog("CDVDiso BZip2V3: Close()"); + +#endif /* VERBOSE_FUNCTION_BZIP2V3 */ + + + + if((isofile->tablehandle != ACTUALHANDLENULL) && + + (isofile->handle != ACTUALHANDLENULL)) { + + if(isofile->openforread == 0) { + + if(isofile->compsector != isofile->filesectorpos) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = compptr; i < 65536; i++) isofile->compblock[i] = 0; + + retval = BZip2V3Write(isofile, isofile->compblock); + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + BZip2V3WriteTable(isofile, table); + + isofile->compsector = isofile->filesectorpos; + + } // ENDIF - still have buffers to write? + + } // ENDIF- Opened for write? Don't forget to flush the file buffer! + + } // ENDIF- Both data file and table file are open? + + + + if(isofile->tablehandle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + } // ENDIF- Is there a table file open? Close it. + + + + if(isofile->handle != ACTUALHANDLENULL) { + + if(isofile->openforread == 0) { + + if(isofile->compsector != isofile->filesectorpos) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = compptr; i < 65536; i++) isofile->compblock[i] = 0; + + BZip2V3Write(isofile, isofile->compblock); + + } // ENDIF - still have buffers to write? + + header.id[0] = 'B'; + + header.id[1] = 'Z'; + + header.id[2] = 'V'; + + header.id[3] = '3'; + + tempsize = isofile->blocksize; + + header.blocksize = ConvertEndianUShort(tempsize); + + header.numblocks = ConvertEndianOffset(isofile->filesectorsize); + + tempsize = isofile->blockoffset; + + header.blockoffset = ConvertEndianUShort(tempsize); + + ActualFileSeek(isofile->handle, 0); + + ActualFileWrite(isofile->handle, + + sizeof(struct BZip2V3Header), + + (char *) &header); + + } // ENDIF- Opened for write? Don't forget to update the header block! + + + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Is there a data file open? Close it. + + + + if(isofile->tabledata != NULL) { + + free(isofile->tabledata); + + isofile->tabledata = NULL; + + } // ENDIF- Do we have a read-in table to clear out? + + + + return; + +} // END BZip2V3Close() + diff --git a/plugins/cdvd/CDVDisoEFP/src/bzip2v3.h b/plugins/cdvd/CDVDisoEFP/src/bzip2v3.h new file mode 100644 index 0000000..ab54e7c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/bzip2v3.h @@ -0,0 +1,104 @@ +/* bzip2v3.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef BZIP2V3_H + +#define BZIP2V3_H + + + + + +#include + + + +#include "isofile.h" + +#include "isocompress.h" + + + + + +// #define VERBOSE_FUNCTION_BZIP2V3 + +// #define VERBOSE_WARNING_BZIP2V3 + + + + + +extern int BZip2V3OpenTableForRead(struct IsoFile *isofile); + +extern int BZip2V3SeekTable(struct IsoFile *isofile, off64_t sector); + +extern int BZip2V3ReadTable(struct IsoFile *isofile, struct TableData *table); + + + +extern int BZip2V3OpenTableForWrite(struct IsoFile *isofile); + +extern int BZip2V3WriteTable(struct IsoFile *isofile, struct TableData table); + + + +extern int BZip2V3OpenForRead(struct IsoFile *isofile); + +extern int BZip2V3Seek(struct IsoFile *isofile, off64_t sector); + +extern int BZip2V3Read(struct IsoFile *isofile, int bytes, char *buffer); + +extern void BZip2V3Close(struct IsoFile *isofile); + + + +extern int BZip2V3OpenForWrite(struct IsoFile *isofile); + +extern int BZip2V3Write(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* BZIP2V3_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/convert.c b/plugins/cdvd/CDVDisoEFP/src/convert.c new file mode 100644 index 0000000..5edbe9e --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/convert.c @@ -0,0 +1,118 @@ +/* convert.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include + +#include "convert.h" + + +off64_t ConvertEndianOffset(off64_t number) { +#ifndef CONVERTLITTLEENDIAN + union { + off64_t n; + char c[sizeof(off64_t)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(off64_t); i++) + newnumber.c[i] = oldnumber.c[sizeof(off64_t) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianOffset() + + +unsigned int ConvertEndianUInt(unsigned int number) { +#ifndef CONVERTLITTLEENDIAN + union { + unsigned int n; + char c[sizeof(unsigned int)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(unsigned int); i++) + newnumber.c[i] = oldnumber.c[sizeof(unsigned int) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianUInt() + + +unsigned short ConvertEndianUShort(unsigned short number) { +#ifndef CONVERTLITTLEENDIAN + union { + unsigned short n; + char c[sizeof(unsigned short)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(unsigned short); i++) + newnumber.c[i] = oldnumber.c[sizeof(unsigned short) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianUShort() + + +// Note: deposits M/S/F data in buffer[0]/[1]/[2] respectively. +void LBAtoMSF(unsigned long lsn, char *buffer) { + unsigned long templsn; + + if(lsn >= 0xFFFFFFFF - 150) { + *(buffer + 2) = 75-1; + *(buffer + 1) = 60-1; + *(buffer) = 100-1; + } // ENDIF- Out of range? + + templsn = lsn; + templsn += 150; // 2 second offset (75 Frames * 2 Seconds) + *(buffer + 2) = templsn % 75; // Remainder in frames + templsn -= *(buffer + 2); + templsn /= 75; + *(buffer + 1) = templsn % 60; // Remainder in seconds + templsn -= *(buffer + 1); + templsn /= 60; + *(buffer) = templsn; // Leftover quotient in minutes +} // END LBAtoMSF() + + +unsigned long MSFtoLBA(char *buffer) { + unsigned long templsn; + + if(buffer == NULL) return(0xFFFFFFFF); + + templsn = *(buffer); // Minutes + templsn *= 60; + templsn += *(buffer + 1); // Seconds + templsn *= 75; + templsn += *(buffer + 2); // Frames + if(templsn < 150) return(0xFFFFFFFF); + templsn -= 150; // Offset + + return(templsn); +} // END MSFtoLBA() diff --git a/plugins/cdvd/CDVDisoEFP/src/convert.h b/plugins/cdvd/CDVDisoEFP/src/convert.h new file mode 100644 index 0000000..3933382 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/convert.h @@ -0,0 +1,50 @@ +/* convert.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CONVERT_H +#define CONVERT_H + + +#include // off64_t +#include "PS2Etypes.h" +#ifdef __linux__ +#include "endian.h" +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define CONVERTLITTLEENDIAN +#endif /* __BYTE_ORDER */ +#endif /* __linux__ */ + +#ifdef _WIN32 +#define CONVERTLITTLEENDIAN +#endif /* _WIN32 */ + +#define HEXTOBCD(i) (((i)/10*16) + ((i)%10)) +#define BCDTOHEX(i) (((i)/16*10) + ((i)%16)) + + +extern off64_t ConvertEndianOffset(off64_t number); +extern unsigned int ConvertEndianUInt(unsigned int number); +extern unsigned short ConvertEndianUShort(unsigned short number); + +extern void LBAtoMSF(unsigned long lsn, char *buffer); +extern unsigned long MSFtoLBA(char *buffer); + +#endif /* CONVERT_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/ecma119.c b/plugins/cdvd/CDVDisoEFP/src/ecma119.c new file mode 100644 index 0000000..24f2e4e --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/ecma119.c @@ -0,0 +1,59 @@ +/* ecma119.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include + +// #ifndef __LINUX__ +// #ifdef __linux__ +// #define __LINUX__ +// #endif /* __linux__ */ +// #endif /* No __LINUX__ */ + +// #define CDVDdefs +// #include "PS2Edefs.h" + +#include "ecma119.h" + + +const char ECMA119VolumeIDstdid[] = "CD001\0"; + + +int ValidateECMA119PrimaryVolume(struct ECMA119PrimaryVolume *volume) { + int i; + + if(volume == NULL) return(-1); + + // Volume ID + if(volume->id.voltype != 1) return(-1); // Incorrect volume type + if(volume->id.version != 1) return(-1); // Not a Standard Version? + i = 0; + while((ECMA119VolumeIDstdid[i] != 0) && + (ECMA119VolumeIDstdid[i] == volume->id.stdid[i])) i++; + if(ECMA119VolumeIDstdid[i] != 0) return(-1); // "CD001" did not match? + + // Looks like numblocksle might give us maximum sector count... + // Looks like blocksizele can be compared to blocksize stored in isofile... + + return(0); +} // END ValidateECMA119PrimaryVolume() + + +// Not sure the Partition Volume will be much help... diff --git a/plugins/cdvd/CDVDisoEFP/src/ecma119.h b/plugins/cdvd/CDVDisoEFP/src/ecma119.h new file mode 100644 index 0000000..494e659 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/ecma119.h @@ -0,0 +1,468 @@ +/* ecma119.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef ECMA119_H + +#define ECMA119_H + + + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + + + +// ECMA119 was sent to ISO to be fast-tracked into ISO 9660 + +// ECMA119 can be found at http://www.ecma.ch, somewhere. + + + +// Throughout these definitions, number pairs in both big-endian and + +// little-endian varieties are stored next to each other. To separate + +// the pairs a 'le' suffix has been attached to little-endian numbers, and + +// a 'be' suffix to big-endian ones. + + + +// All 'unused' entries should be set to (or tested for) 0x00. + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct ECMA119ASCIITime { + + char year[4]; + + char month[2]; + + char day[2]; + + char hour[2]; + + char min[2]; + + char sec[2]; + + char hundredthsec[2]; + + char offsetgmt; // 15 min intervals, from -48 to +52 + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct ECMA119DateTime { + + unsigned char year; // 1900+year, that is. + + unsigned char month; + + unsigned char day; + + unsigned char hour; + + unsigned char minute; + + unsigned char sec; + + signed char offsetgmt; // In 15 min intervals, from -48 to +52 + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct ECMA119DirectoryRecord { + + unsigned char reclen; // Length of this record + + unsigned char attlen; // Extended Attribute Record Length + + + + unsigned long externlocle; // Location of Extent + + unsigned long externlocbe; + + + + struct ECMA119DateTime recorded; // Recording Date and Time + + + + unsigned char flags; // File Flags + + unsigned char interleave; // Interleave Gap Size + + + + unsigned short seqnole; // Volume Sequence No. + + unsigned short seqnobe; + + + + unsigned short idlen; + + char id[223]; + + // Note: sometimes a OS uses the end of this record for it's own use. + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct ECMA119RootDirectoryRecord { + + unsigned char reclen; // Length of this record + + unsigned char attlen; // Extended Attribute Record Length + + + + unsigned long externlocle; // Location of Extent + + unsigned long externlocbe; + + + + struct ECMA119DateTime recorded; // Recording Date and Time + + + + unsigned char flags; // File Flags + + unsigned char interleave; // Interleave Gap Size + + + + unsigned short seqnole; // Volume Sequence No. + + unsigned short seqnobe; + + + + unsigned short idlen; + + char id[1]; // Probably for the '.' (But I'm just guessing :) + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct ECMA119VolumeID { + + unsigned char voltype; + + // 0 = Boot Record + + // 1 = Primary Volume Descriptor (PrimaryVolume below) + + // 2 = Supplementary Volume Descriptor + + // 3 = Partition Descriptor (PartitionVolume below) + + // 4 - 254 Reserved + + // 255 = End-of-Descriptor-Set + + + + char stdid[5]; // Standard Identifier. Always "CD001" + + + + unsigned char version; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct ECMA119PrimaryVolume { + + struct ECMA119VolumeID id; + + // id.voltype should be 1 (for this type of volume) + + // id.version should be 1 (standard) + + + + char unused1; + + + + char systemid[32]; + + char volumeid[32]; + + + + char unused2[8]; + + + + unsigned long numblocksle; // Total logical blocks. (on Media? or just + + unsigned long numblocksbe; // in volume?) + + + + char unused3[32]; + + + + unsigned short volumesetsizele; // Volume Set size of the volume. (?) + + unsigned short volumesetsizebe; + + + + unsigned short ordinalle; // Count of which descriptor this is in the Volume + + unsigned short ordinalbe; // set. + + + + unsigned short blocksizele; // Size of a Logical Block + + unsigned short blocksizebe; + + + + unsigned long pathtablesizele; // Path Table Size + + unsigned long pathtablesizebe; + + + + unsigned long typelpathtablelocation; // (le) Location of a Type L Path Table + + + + unsigned long typelopttablelocation; // (le) Location of an Optional Type L + + + + unsigned long typempathtablelocation; // (be) Location of a Type M Path Table + + + + unsigned long typemopttablelocation; // (be) Location of an Optional Type M + + + + struct ECMA119RootDirectoryRecord root; + + + + char volumesetid[128]; // Volume Set ID + + + + char publisher[128]; // Publisher + + + + char datapreparer[128]; // Data Preparer + + + + char application[128]; // Application ID + + + + char copyrightfile[37]; // Copyright File Identifier + + + + char abstractfile[37]; // Abstract File Identifier + + + + char bibliograchicfile[37]; // Bibliographic File Identifier + + + + struct ECMA119ASCIITime volcreatedate; // Date Created + + struct ECMA119ASCIITime volmodifydate; // Last Date Modified + + struct ECMA119ASCIITime volexpiredate; // Date data expires + + struct ECMA119ASCIITime voleffectivedata; // Date data becomes accurate (effective) + + + + unsigned char filestructversion; // File Structure Version + + // Should be 1 = Standard + + + + char unused4; + + + + char applicationuse[512]; // For use by an application + + + + char unused5[653]; // Rounds this out to 2048 bytes... + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +// struct ECMA119PartitionVolume { + +// struct ECMA119VolumeID id; + +// #ifdef _WIN32 + +// }; + +// #else + +// } __attribute__ ((packed)); + +// #endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +extern int ValidateECMA119PrimaryVolume(struct ECMA119PrimaryVolume *volume); + +// extern int ValidateECMA119PartitionVolume(struct ECMA119PartitionVolume volume); + + + + + +#endif /* ECMA119_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/gzipv1.c b/plugins/cdvd/CDVDisoEFP/src/gzipv1.c new file mode 100644 index 0000000..bdd73de --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/gzipv1.c @@ -0,0 +1,844 @@ +/* gzipv1.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + + + +#include "zlib/zlib.h" + + + +#include "convert.h" + +#include "logfile.h" + +#include "isofile.h" + +#include "isocompress.h" // TableData + +#include "actualfile.h" + +#include "gzipv1.h" + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct GZipV1Table { + + unsigned int offset; // Data file position + + unsigned short size; // of Compressed data + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +int GZipV1OpenTableForRead(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: OpenTableForRead()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForRead(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + isofile->filesectorsize = ActualFileSize(isofile->tablehandle) + + / sizeof(struct GZipV1Table); + + + + return(0); + +} // END GZipV1OpenTableForRead() + + + + + +int GZipV1SeekTable(struct IsoFile *isofile, off64_t sector) { + + off64_t target; + + int retval; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: SeekTable(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + target = sector * sizeof(struct GZipV1Table); + + retval = ActualFileSeek(isofile->tablehandle, target); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't find sector!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-2); + + } // ENDIF- Trouble finding the place? Fail. + + + + isofile->filesectorpos = sector; + + return(0); + +} // END GZipV1SeekTable() + + + + + +int GZipV1ReadTable(struct IsoFile *isofile, struct TableData *table) { + + int retval; + + struct GZipV1Table temptable; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: ReadTable()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + retval = ActualFileRead(isofile->tablehandle, + + sizeof(struct GZipV1Table), + + (char *) &temptable); + + if(retval != sizeof(struct GZipV1Table)) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't read table entry!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + table->offset = ConvertEndianUInt(temptable.offset); + + table->size = ConvertEndianUShort(temptable.size); + + isofile->filesectorpos++; + + return(0); + +} // END GZipV1ReadTable() + + + + + +int GZipV1OpenTableForWrite(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: OpenTableForWrite()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForWrite(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + isofile->filesectorsize = 0; + + return(0); + +} // END GZipV1OpenTableForWrite() + + + + + +int GZipV1WriteTable(struct IsoFile *isofile, struct TableData table) { + + int retval; + + struct GZipV1Table temptable; + + unsigned int tempint; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: WriteTable(%lli, %i)", table.offset, table.size); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + tempint = table.offset; + + temptable.offset = ConvertEndianUInt(tempint); + + temptable.size = ConvertEndianUShort(table.size); + + retval = ActualFileWrite(isofile->tablehandle, + + sizeof(struct GZipV1Table), + + (char *) &temptable); + + if(retval != sizeof(struct GZipV1Table)) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't write table entry!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + return(0); + +} // END GZipV1WriteTable() + + + + + +int GZipV1OpenForRead(struct IsoFile *isofile) { + + int retval; + + char tempblock[2448]; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + + + isofile->imageheader = 0; + + isofile->blocksize = 2352; + + isofile->blockoffset = 0; // Don't panic. "imagetype.c" will test later. + + isofile->numsectors = 1; // Sectors per block + + + + retval = GZipV1Read(isofile, 2448, tempblock); + + if(retval != 0) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't decode the first block. Not compressed?"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF Could not read the first sector? Fail. + + + + ActualFileSeek(isofile->handle, 0); // Restart at top of file + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + return(0); + +} // END GZipV1OpenForRead() + + + + + +int GZipV1Seek(struct IsoFile *isofile, off64_t position) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Seek(%lli)", position); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + retval = ActualFileSeek(isofile->handle, position); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Couldn't find the start of the compressed block!"); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Couldn't find the data entry? Fail. + + isofile->filebytepos = position; + + return(0); + + + + return(-1); // Fail. (Due to lack of ambition?) + +} // END GZipV1Seek() + + + + + +int GZipV1Read(struct IsoFile *isofile, int bytes, char *buffer) { + + int retval; + + unsigned long blocklen; + + z_stream strm; + + unsigned long tempin; + + char tempblock[2800]; + + unsigned long tempout; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Read(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + if(bytes > 0) { + + retval = ActualFileRead(isofile->handle, bytes, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != bytes) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + blocklen = isofile->blocksize; + + retval = uncompress(buffer, &blocklen, tempblock, bytes); + + if(retval != Z_OK) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Cannot decode block! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble decoding the sector? Abort. + + + + return(0); + + } // ENDIF- Do we know how many compressed bytes to get for this record? + + + + // Hmm. Don't know the compressed size? Well, we'll just have to find it. + + + + tempin = 0; + + tempout = 0; + + retval = Z_OK; + + while((tempin < 2800) && (tempout < 2352)) { + + + + strm.zalloc = (alloc_func)0; + + strm.zfree = (free_func)0; + + + + strm.next_in = tempblock; + + strm.next_out = buffer; + + + + strm.avail_in = tempin; + + strm.avail_out = 2800; + + + + retval = inflateInit(&strm); + + if (retval != Z_OK) return(-1); + + + + while((tempin < 2800) && (retval == Z_OK)) { + + retval = ActualFileRead(isofile->handle, 1, &tempblock[tempin]); + + if(retval != 1) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Cannot read a byte! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + tempin++; + + strm.avail_in++; + + + + strm.next_in = &tempblock[tempin - strm.avail_in]; + + retval = inflate(&strm, Z_NO_FLUSH); + + } // ENDWHILE- trying to uncompress an increasingly filled buffer + + tempout = strm.total_out; + + inflateEnd(&strm); + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: tempin=%lu tempout=%lu retval=%i", + + tempin, tempout, retval); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + } // ENDWHILE- trying to uncompress a whole buffer + + if(retval != Z_STREAM_END) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Failed to decode block! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + if(tempin == 2800) { + +#ifdef VERBOSE_WARNING_GZIPV1 + + PrintLog("CDVDiso GZipV1: Overfilled input buffer for only %llu bytes!", tempout); + +#endif /* VERBOSE_WARNING_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + isofile->filebytepos += tempin; + + return(tempin); // Send out # of compressed bytes (to record in table) + +} // END GZipV1Read() + + + + + +int GZipV1OpenForWrite(struct IsoFile *isofile) { + + if(isofile == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: OpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + isofile->handle = ActualFileOpenForWrite(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = 0; + + isofile->filebytepos = 0; + + return(0); + +} // END GZipV1OpenForWrite() + + + + + +int GZipV1Write(struct IsoFile *isofile, char *buffer) { + + int retval; + + unsigned long blocklen; + + char tempblock[2800]; + + + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Write()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + blocklen = 2800; + + retval = compress2(tempblock, &blocklen, + + buffer, 2352, + + Z_BEST_COMPRESSION); + + if(retval != Z_OK) { + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Cannot encode block! Returned: (%i)", retval); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble compressing a block? Abort. + + + + retval = ActualFileWrite(isofile->handle, blocklen, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval < blocklen) { + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Cannot write bytes! Returned: (%i out of %llu)", + + retval, blocklen); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + return(-1); + + } // ENDIF- Trouble writing out the compressed block? Abort. + + isofile->filesectorpos++; + + + + return(blocklen); + +} // END GZipV1Write() + + + + + +void GZipV1Close(struct IsoFile *isofile) { + +#ifdef VERBOSE_FUNCTION_GZIPV1 + + PrintLog("CDVDiso GZipV1: Close()"); + +#endif /* VERBOSE_FUNCTION_GZIPV1 */ + + + + // Flush Write data... if any was held in the compression block area. + + // In this case, though... nothing's held there. + + + + if(isofile->tablehandle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + } // ENDIF- Is there a table file open? Close it. + + + + if(isofile->handle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Is there a data file open? Close it. + + + + return; + +} // END GZipV1Close() + diff --git a/plugins/cdvd/CDVDisoEFP/src/gzipv1.h b/plugins/cdvd/CDVDisoEFP/src/gzipv1.h new file mode 100644 index 0000000..c47981f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/gzipv1.h @@ -0,0 +1,104 @@ +/* gzipv1.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef GZIPV1_H + +#define GZIPV1_H + + + + + +#include + + + +#include "isofile.h" + +#include "isocompress.h" + + + + + +// #define VERBOSE_FUNCTION_GZIPV1 + +// #define VERBOSE_WARNING_GZIPV1 + + + + + +extern int GZipV1OpenTableForRead(struct IsoFile *isofile); + +extern int GZipV1SeekTable(struct IsoFile *isofile, off64_t sector); + +extern int GZipV1ReadTable(struct IsoFile *isofile, struct TableData *table); + + + +extern int GZipV1OpenTableForWrite(struct IsoFile *isofile); + +extern int GZipV1WriteTable(struct IsoFile *isofile, struct TableData table); + + + +extern int GZipV1OpenForRead(struct IsoFile *isofile); + +extern int GZipV1Seek(struct IsoFile *isofile, off64_t sector); + +extern int GZipV1Read(struct IsoFile *isofile, int bytes, char *buffer); + +extern void GZipV1Close(struct IsoFile *isofile); + + + +extern int GZipV1OpenForWrite(struct IsoFile *isofile); + +extern int GZipV1Write(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* GZIPV1_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/gzipv2.c b/plugins/cdvd/CDVDisoEFP/src/gzipv2.c new file mode 100644 index 0000000..3a82174 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/gzipv2.c @@ -0,0 +1,980 @@ +/* gzipv2.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // malloc() + +#include // off64_t + + + +#include "zlib/zlib.h" + + + +#include "convert.h" + +#include "logfile.h" + +#include "isofile.h" // IsoFile + +#include "isocompress.h" // TableData, TableMap + +#include "actualfile.h" + +#include "gzipv2.h" + + + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct GZipV2Header { + + char id[4]; + + unsigned int blocksize; + + unsigned int numblocks; + + unsigned int blockoffset; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +struct GZipV2Table { + + unsigned int size; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +#ifdef _WIN32 + +#pragma pack() + +#endif /* _WIN32 */ + + + + + +int GZipV2OpenTableForRead(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + off64_t offset; + + off64_t actual; + + int tableoffset; + + struct GZipV2Table table; + + int retval; + + union TableMap tablemap; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: OpenTableForRead()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForRead(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + offset = isofile->filesectorsize * sizeof(struct GZipV2Table); + + actual = ActualFileSize(isofile->tablehandle); + + if(offset != actual) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Table not the correct size! (Should be %lli, is %lli)", + + offset, actual); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Not the correct-sized table for the data file? Fail. + + + + // We pre-read the WHOLE offset table. + + isofile->tabledata = (char *) malloc(isofile->filesectorsize * sizeof(struct TableData)); + + if(isofile->tabledata == NULL) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't allocate internal table!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Could not get enough memory to hold table data + + + + offset = sizeof(struct GZipV2Header); + + tableoffset = 0; + + for(i = 0; i < isofile->filesectorsize; i++) { + + retval = ActualFileRead(isofile->tablehandle, + + sizeof(struct GZipV2Table), + + (char *) &table); + + if(retval != sizeof(struct GZipV2Table)) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Failed to read in sector %i!", i); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Trouble reading in a size? Table damaged... fail. + + + + tablemap.table.offset = offset; + + tablemap.table.size = ConvertEndianUInt(table.size); + + for(j = 0; j < sizeof(struct TableData); j++) + + *(isofile->tabledata + tableoffset + j) = tablemap.ch[j]; + + offset += table.size; + + tableoffset += sizeof(struct TableData); + + } // NEXT i- reading in the sizes, and making offset as I go. + + + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + return(0); + +} // END GZipV2OpenTableForRead() + + + + + +int GZipV2SeekTable(struct IsoFile *isofile, off64_t sector) { + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: SeekTable(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + isofile->filesectorpos = sector; + + return(0); + +} // END GZipV2SeekTable() + + + + + +int GZipV2ReadTable(struct IsoFile *isofile, struct TableData *table) { + + off64_t target; + + union TableMap tablemap; + + off64_t i; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: ReadTable()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + target = isofile->filesectorpos * sizeof(struct TableData); + + for(i = 0; i < sizeof(struct TableData); i++) + + tablemap.ch[i] = *(isofile->tabledata + target + i); + + + + table->offset = tablemap.table.offset; + + table->size = tablemap.table.size; + + isofile->filesectorpos++; + + return(0); + +} // END GZipV2ReadTable() + + + + + +int GZipV2OpenTableForWrite(struct IsoFile *isofile) { + + int i; + + int j; + + char tableext[] = ".table\0"; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: OpenTableForWrite()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + i = 0; + + while((i < 256) && (isofile->name[i] != 0)) { + + isofile->tablename[i] = isofile->name[i]; + + i++; + + } // ENDWHILE- Copying the data name to the table name + + j = 0; + + while((i < 256) && (tableext[j] != 0)) { + + isofile->tablename[i] = tableext[j]; + + i++; + + j++; + + } // ENDWHILE- Adding the ".table" extension. + + isofile->tablename[i] = 0; // And 0-terminate. + + + + isofile->tablehandle = ActualFileOpenForWrite(isofile->tablename); + + if(isofile->tablehandle == ACTUALHANDLENULL) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't open table!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Couldn't open table file? Fail. + + + + isofile->filesectorsize = 0; + + return(0); + +} // END GZipV2OpenTableForWrite() + + + + + +int GZipV2WriteTable(struct IsoFile *isofile, struct TableData table) { + + int retval; + + struct GZipV2Table gv2table; + + unsigned int tempint; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: WriteTable(%lli, %i)", table.offset, table.size); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + tempint = table.size; + + gv2table.size = ConvertEndianUInt(tempint); + + retval = ActualFileWrite(isofile->tablehandle, + + sizeof(struct GZipV2Table), + + (char *) &gv2table); + + if(retval != sizeof(unsigned int)) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't write table entry!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-2); + + } // ENDIF- Trouble reading table entry? Fail. + + + + return(0); + +} // END GZipV2WriteTable() + + + + + +int GZipV2OpenForRead(struct IsoFile *isofile) { + + int retval; + + struct GZipV2Header header; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + + + isofile->imageheader = 0; + + isofile->numsectors = 1; // Sectors per block + + + + retval = ActualFileRead(isofile->handle, + + sizeof(struct GZipV2Header), + + (char *) &header); + + if(retval != sizeof(struct GZipV2Header)) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't read header!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF Could not read the first sector? Fail. + + isofile->filebytepos += retval; + + + + if((header.id[0] != 'Z') || + + (header.id[1] != ' ') || + + (header.id[2] != 'V') || + + (header.id[3] != '2')) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Not a gzip v2 compression header!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + return(-1); + + } // ENDIF- ID for this compression type doesn't match? + + + + isofile->blocksize = ConvertEndianUInt(header.blocksize); + + isofile->filesectorsize = ConvertEndianUInt(header.numblocks); + + isofile->blockoffset = ConvertEndianUInt(header.blockoffset); + + isofile->filesectorpos = 0; + + return(0); + +} // END GZipV2OpenForRead() + + + + + +int GZipV2Seek(struct IsoFile *isofile, off64_t position) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Seek(%lli)", position); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + retval = ActualFileSeek(isofile->handle, position); + + if(retval < 0) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Couldn't find the start of the compressed block!"); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-1); + + } // ENDIF- Couldn't find the data entry? Fail. + + isofile->filebytepos = position; + + return(0); + + + + return(-1); // Fail. (Due to lack of ambition?) + +} // END GZipV2Seek() + + + + + +int GZipV2Read(struct IsoFile *isofile, int bytes, char *buffer) { + + int retval; + + unsigned long blocklen; + + z_stream strm; + + unsigned long tempin; + + char tempblock[2800]; + + unsigned long tempout; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Read(%i)", bytes); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + if(bytes > 0) { + + retval = ActualFileRead(isofile->handle, bytes, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval != bytes) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Cannot read bytes! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + + + blocklen = isofile->blocksize; + + retval = uncompress(buffer, &blocklen, tempblock, bytes); + + if(retval != Z_OK) { + +#ifdef VERBOSE_WARNING_GZIPV2 + + PrintLog("CDVDiso GZipV2: Cannot decode block! Returned: (%i)", retval); + +#endif /* VERBOSE_WARNING_GZIPV2 */ + + return(-1); + + } // ENDIF- Trouble decoding the sector? Abort. + + + + return(0); + + } // ENDIF- Do we know how many compressed bytes to get for this record? + + + + // Hmm. Don't know the compressed size? Well, we'll just have to find it. + + + + tempin = 0; + + tempout = 0; + + retval = Z_OK; + + while((tempin < 2800) && (tempout < isofile->blocksize * isofile->numsectors)) { + + + + strm.zalloc = (alloc_func)0; + + strm.zfree = (free_func)0; + + + + strm.next_in = tempblock; + + strm.next_out = buffer; + + + + strm.avail_in = tempin; + + strm.avail_out = 2800; + + + + retval = inflateInit(&strm); + + if (retval != Z_OK) return(-1); + + + + while((tempin < 2800) && (retval == Z_OK)) { + + retval = ActualFileRead(isofile->handle, 1, &tempblock[tempin]); + + if(retval != 1) { + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Cannot read a byte! Returned: (%i)", retval); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + return(-1); + + } // ENDIF- Trouble reading compressed sector? Abort. + + tempin++; + + strm.avail_in++; + + + + strm.next_in = &tempblock[tempin - strm.avail_in]; + + retval = inflate(&strm, Z_NO_FLUSH); + + } // ENDWHILE- trying to uncompress an increasingly filled buffer + + tempout = 2800 - strm.avail_out; + + inflateEnd(&strm); + + + + } // ENDWHILE- trying to uncompress a whole buffer + + if(retval != Z_STREAM_END) return(-1); + + + + if(tempin == 2800) return(-1); + + isofile->filebytepos += tempin; + + return(tempin); // Send out # of compressed bytes (to record in table) + +} // END GZipV2Read() + + + + + +int GZipV2OpenForWrite(struct IsoFile *isofile) { + + char garbage[sizeof(struct GZipV2Header)]; + + int i; + + + + if(isofile == NULL) return(-1); + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: OpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + isofile->handle = ActualFileOpenForWrite(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + return(-1); + + } // ENDIF- Couldn't open data file? Fail. + + for(i = 0; i < sizeof(struct GZipV2Header); i++) garbage[i] = 0; + + ActualFileWrite(isofile->handle, sizeof(struct GZipV2Header), garbage); + + + + isofile->filebytesize = 0; + + isofile->filebytepos = sizeof(struct GZipV2Header); + + isofile->filesectorpos = 0; + + isofile->filesectorsize = 0; + + return(0); + +} // END GZipV2OpenForWrite() + + + + + +int GZipV2Write(struct IsoFile *isofile, char *buffer) { + + int retval; + + unsigned long blocklen; + + char tempblock[2800]; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Write()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + blocklen = 2800; + + retval = compress2(tempblock, &blocklen, + + buffer, isofile->blocksize, + + Z_BEST_COMPRESSION); + + if(retval != Z_OK) { + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Cannot encode block! Returned: (%i)", retval); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + return(-1); + + } // ENDIF- Trouble compressing a block? Abort. + + + + retval = ActualFileWrite(isofile->handle, blocklen, tempblock); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval < blocklen) { + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Cannot write bytes! Returned: (%i out of %llu)", + + retval, blocklen); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + return(-1); + + } // ENDIF- Trouble writing out the compressed block? Abort. + + isofile->filesectorpos++; + + + + return(blocklen); // Not in list? Fail. + +} // END GZipV2Write() + + + + + +void GZipV2Close(struct IsoFile *isofile) { + + struct GZipV2Header header; + + unsigned int tempint; + + + +#ifdef VERBOSE_FUNCTION_GZIPV2 + + PrintLog("CDVDiso GZipV2: Close()"); + +#endif /* VERBOSE_FUNCTION_GZIPV2 */ + + + + if(isofile->tablehandle != ACTUALHANDLENULL) { + + ActualFileClose(isofile->tablehandle); + + isofile->tablehandle = ACTUALHANDLENULL; + + } // ENDIF- Is there a table file open? Close it. + + + + if(isofile->handle != ACTUALHANDLENULL) { + + if(isofile->openforread == 0) { + + header.id[0] = 'Z'; + + header.id[1] = ' '; + + header.id[2] = 'V'; + + header.id[3] = '2'; + + tempint = isofile->blocksize; + + header.blocksize = ConvertEndianUInt(tempint); + + tempint = isofile->filesectorsize; + + header.numblocks = ConvertEndianUInt(tempint); + + tempint = isofile->blockoffset; + + header.blockoffset = ConvertEndianUInt(tempint); + + ActualFileSeek(isofile->handle, 0); + + ActualFileWrite(isofile->handle, + + sizeof(struct GZipV2Header), + + (char *) &header); + + } // ENDIF- Opened for write? Don't forget to update the header block! + + + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Is there a data file open? Close it. + + + + if(isofile->tabledata != NULL) { + + free(isofile->tabledata); + + isofile->tabledata = NULL; + + } // ENDIF- Do we have a read-in table to clear out? + + + + return; + +} // END GZipV2Close() + diff --git a/plugins/cdvd/CDVDisoEFP/src/gzipv2.h b/plugins/cdvd/CDVDisoEFP/src/gzipv2.h new file mode 100644 index 0000000..b91219c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/gzipv2.h @@ -0,0 +1,104 @@ +/* gzipv2.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef GZIPV2_H + +#define GZIPV2_H + + + + + +#include + + + +#include "isofile.h" + +#include "isocompress.h" + + + + + +// #define VERBOSE_FUNCTION_GZIPV2 + +// #define VERBOSE_WARNING_GZIPV2 + + + + + +extern int GZipV2OpenTableForRead(struct IsoFile *isofile); + +extern int GZipV2SeekTable(struct IsoFile *isofile, off64_t sector); + +extern int GZipV2ReadTable(struct IsoFile *isofile, struct TableData *table); + + + +extern int GZipV2OpenTableForWrite(struct IsoFile *isofile); + +extern int GZipV2WriteTable(struct IsoFile *isofile, struct TableData table); + + + +extern int GZipV2OpenForRead(struct IsoFile *isofile); + +extern int GZipV2Seek(struct IsoFile *isofile, off64_t sector); + +extern int GZipV2Read(struct IsoFile *isofile, int bytes, char *buffer); + +extern void GZipV2Close(struct IsoFile *isofile); + + + +extern int GZipV2OpenForWrite(struct IsoFile *isofile); + +extern int GZipV2Write(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* GZIPV2_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/imagetype.c b/plugins/cdvd/CDVDisoEFP/src/imagetype.c new file mode 100644 index 0000000..8b6785f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/imagetype.c @@ -0,0 +1,306 @@ +/* imagetype.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // off64_t + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + +#include "isofile.h" + +#include "actualfile.h" + +#include "imagetype.h" + + + + + +// Based (mostly) off of florin's CDVDbin detection code, twice removed + +// with some additions from the header. + +struct ImageTypes imagedata[] = { + + { "ISO 2048", 2048, 0, 0, 0 }, + + { "YellowBook 2064", 2064, 0, 16, 1 }, + + { "RAW 2064", 2064, 0, 0, 2 }, + + { "GreenBook 2072", 2072, 0, 24, 3 }, + + { "RAW 2072", 2072, 0, 0, 4 }, + + { "RAW 2324", 2324, 0, 0, 5 }, + + { "RAW 2328", 2328, 0, 0, 6 }, + + { "RAW 2336", 2336, 0, 0, 7 }, + + { "GreenBook 2352", 2352, 0, 24, 8 }, + + { "YellowBook 2352", 2352, 0, 16, 9 }, + + { "RedBook 2352", 2352, 0, 0, 10 }, + + { "RAWQ 2448", 2448, 0, 0, 11 }, + + + + { "NERO ISO 2048", 2048, 150*2048, 0, 0 }, + + { "NERO GreenBook 2352", 2352, 150*2352, 24, 8 }, + + { "NERO YellowBook 2352", 2352, 150*2352, 16, 9 }, + + { "NERO RedBook 2352", 2352, 150*2352, 0, 10 }, + + { "NERO RAWQ 2448", 2448, 150*2448, 0, 11 }, + + + + { "Alt ISO 2048", 2048, 8, 0, 0 }, + + { "Alt RAW 2336", 2336, 8, 0, 7 }, + + { "Alt GreenBook 2352", 2352, 8, 24, 8 }, + + { "Alt YellowBook 2352", 2352, 8, 16, 9 }, + + { "Alt RedBook 2352", 2352, 8, 0, 10 }, + + { "Alt RAWQ 2448", 2448, 8, 0, 11 }, + + { NULL, 0, 0, 0, 0 } + +}; + + + + + +#define REDBOOK2352 10 + + + + + +void GetImageType(struct IsoFile *isofile, int imagetype) { + + int temptype; + + int i; + + + + temptype = imagetype; + + if((temptype < 0) || (temptype > 22)) temptype = REDBOOK2352; + + + + i = 0; + + while((i < 40) && (*(imagedata[temptype].name + i) != 0)) { + + isofile->imagename[i] = *(imagedata[temptype].name + i); + + i++; + + } // ENDWHILE- filling in the image name + + isofile->imagename[i] = 0; // And 0-terminate. + + + + isofile->blocksize = imagedata[temptype].blocksize; + + isofile->imageheader = imagedata[temptype].fileoffset; + + isofile->blockoffset = imagedata[temptype].dataoffset; + +} // END GetImageType() + + + + + +int GetImageTypeConvertTo(int imagetype) { + + return(imagedata[imagetype].conversiontype); + +} // END GetImageTypeConvertTo() + + + + + +int DetectImageType(struct IsoFile *isofile) { + + char comparestr[] = "CD001"; + + int newtype; + + off64_t targetpos; + + char teststr[2448]; + + int dataoffset; + + int i; + + int retval; + + + + newtype = 0; + + if(isofile->compress > 0) { + + IsoFileSeek(isofile, 16); + + IsoFileRead(isofile, teststr); + + + + while(imagedata[newtype].name != NULL) { + + if((isofile->blocksize == imagedata[newtype].blocksize) && + + (isofile->imageheader == imagedata[newtype].fileoffset)) { + + dataoffset = imagedata[newtype].dataoffset + 1; + + i = 0; + + while((i < 5) && (teststr[dataoffset + i] == comparestr[i])) i++; + + if(i == 5) { + + GetImageType(isofile, newtype); + + return(newtype); + + } // ENDIF- Did we find a match? + + } // ENDIF- Do these pieces match the compression storage pieces? + + newtype++; + + } // ENDWHILE- looking for the image type that fits the stats + + + + } else { + + while(imagedata[newtype].name != NULL) { + + targetpos = (16 * imagedata[newtype].blocksize) + + + imagedata[newtype].fileoffset + + + imagedata[newtype].dataoffset + + + 1; // Moves to start of string + + retval = ActualFileSeek(isofile->handle, targetpos); + + if(retval == 0) { + + retval = ActualFileRead(isofile->handle, 5, teststr); + + if(retval == 5) { + + i = 0; + + while((i < 5) && (teststr[i] == comparestr[i])) i++; + + if(i == 5) { + + ActualFileSeek(isofile->handle, isofile->imageheader); + + GetImageType(isofile, newtype); + + return(newtype); + + } // ENDIF- Did we find a match? + + } // ENDIF- Could we read in the test string? Cool! Test it. + + } // ENDIF- Could actually get to this point? + + newtype++; + + } // ENDWHILE- looking for the directory header string "CD001" + + ActualFileSeek(isofile->handle, isofile->imageheader); + + } // ENDIF- Do we match type to compression stats? (Or search against raw data?) + + + + GetImageType(isofile, REDBOOK2352); + + return(REDBOOK2352); // Couldn't find it? Guess it's RAW 2352, then. (Audio CD?) + +} // END ImageDetect() + diff --git a/plugins/cdvd/CDVDisoEFP/src/imagetype.h b/plugins/cdvd/CDVDisoEFP/src/imagetype.h new file mode 100644 index 0000000..20448cc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/imagetype.h @@ -0,0 +1,112 @@ +/* imagetype.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef IMAGETYPE_H + +#define IMAGETYPE_H + + + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + +#include "isofile.h" + + + + + +struct ImageTypes { + + char *name; + + off64_t blocksize; + + off64_t fileoffset; + + int dataoffset; + + int conversiontype; // For conversionbox to write a new file as. + +}; + + + +// Note: Worked around since a failure occurred with MSVCRT.DLL. It couldn't + +// printf a char string inside an array of structures. Don't know why. + +// extern struct ImageTypes imagedata[]; + + + + + +extern void GetImageType(struct IsoFile *isofile, int imagetype); + +extern int GetImageTypeConvertTo(int imagetype); + +extern int DetectImageType(struct IsoFile *isofile); + + + + + +#endif /* IMAGETYPE_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/ini.c b/plugins/cdvd/CDVDisoEFP/src/ini.c new file mode 100644 index 0000000..a00dac8 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/ini.c @@ -0,0 +1,689 @@ +/* ini.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() + +#include "logfile.h" +#include "actualfile.h" +#include "ini.h" + + +const char INIext[] = ".ini"; +const char INInewext[] = ".new"; + + +// Returns: position where new extensions should be added. +int INIRemoveExt(char *argname, char *tempname) { + int i; + int j; + int k; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: RemoveExt(%s)", argname); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i <= INIMAXLEN) && (*(argname + i) != 0)) { + *(tempname + i) = *(argname + i); + i++; + } // ENDWHILE- Copying the argument name into a temporary area; + *(tempname + i) = 0; // And 0-terminate + k = i; + k--; + + j = 0; + while((j <= INIMAXLEN) && (INIext[j] != 0)) j++; + j--; + + while((j >= 0) && (*(tempname + k) == INIext[j])) { + k--; + j--; + } // ENDWHILE- Comparing the ending characters to the INI ext. + if(j < 0) { + k++; + i = k; + *(tempname + i) = 0; // 0-terminate, cutting off ".ini" + } // ENDIF- Do we have a match? Then remove the end chars. + + return(i); +} // END INIRemoveExt() + + +void INIAddInExt(char *tempname, int temppos) { + int i; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: AddInExt(%s, %i)", tempname, temppos); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i + temppos < INIMAXLEN) && (INIext[i] != 0)) { + *(tempname + temppos + i) = INIext[i]; + i++; + } // ENDWHILE- Attaching extenstion to filename + *(tempname + temppos + i) = 0; // And 0-terminate +} // END INIAddInExt() + + +void INIAddOutExt(char *tempname, int temppos) { + int i; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: AddOutExt(%s, %i)", tempname, temppos); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i + temppos < INIMAXLEN) && (INInewext[i] != 0)) { + *(tempname + temppos + i) = INInewext[i]; + i++; + } // ENDWHILE- Attaching extenstion to filename + *(tempname + temppos + i) = 0; // And 0-terminate +} // END INIAddInExt() + + +// Returns number of bytes read to get line (0 means end-of-file) +int INIReadLine(ACTUALHANDLE infile, char *buffer) { + int charcount; + int i; + char tempin[2]; + int retflag; + int retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: ReadLine()"); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + i = 0; + tempin[1] = 0; + retflag = 0; + + while((i < INIMAXLEN) && (retflag < 2)) { + retval = ActualFileRead(infile, 1, tempin); + charcount++; + if(retval != 1) { + retflag = 2; + charcount--; + + } else if(tempin[0] == '\n') { + retflag = 2; + + } else if(tempin[0] >= ' ') { + *(buffer + i) = tempin[0]; + i++; + } // ENDLONGIF- How do we react to the next character? + } // ENDWHILE- Loading up on characters until an End-of-Line appears + *(buffer + i) = 0; // And 0-terminate + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Line: %s", buffer); +#endif /* VERBOSE_FUNCTION_INI */ + + return(charcount); +} // END INIReadLine() +// Note: Do we need to back-skip a char if something other \n follows \r? + + +// Returns: number of bytes to get to start of section (or -1) +int INIFindSection(ACTUALHANDLE infile, char *section) { + int charcount; + int i; + int retflag; + int retval; + char scanbuffer[INIMAXLEN+1]; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: FindSection(%s)", section); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + retflag = 0; + + while(retflag == 0) { + retval = INIReadLine(infile, scanbuffer); + if(retval == 0) return(-1); // EOF? Stop here. + + if(scanbuffer[0] == '[') { + i = 0; + while((i < INIMAXLEN) && + (*(section + i) != 0) && + (*(section + i) == scanbuffer[i + 1])) i++; + if((i < INIMAXLEN - 2) && (*(section + i) == 0)) { + if((scanbuffer[i + 1] == ']') && (scanbuffer[i + 2] == 0)) { + retflag = 1; + } // ENDIF- End marks look good? Return successful. + } // ENDIF- Do we have a section match? + } // ENDIF- Does this look like a section header? + + if(retflag == 0) charcount += retval; + } // ENDWHILE- Scanning lines for the correct [Section] header. + + return(charcount); +} // END INIFindSection() + + +// Returns: number of bytes to get to start of keyword (or -1) +int INIFindKeyword(ACTUALHANDLE infile, char *keyword, char *buffer) { + int charcount; + int i; + int j; + int retflag; + int retval; + char scanbuffer[INIMAXLEN+1]; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: FindKeyword(%s)", keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + retflag = 0; + + while(retflag == 0) { + retval = INIReadLine(infile, scanbuffer); + if(retval == 0) return(-1); // EOF? Stop here. + if(scanbuffer[0] == '[') return(-1); // New section? Stop here. + + i = 0; + while((i < INIMAXLEN) && + (*(keyword + i) != 0) && + (*(keyword + i) == scanbuffer[i])) i++; + if((i < INIMAXLEN - 2) && (*(keyword + i) == 0)) { + if(scanbuffer[i] == '=') { + retflag = 1; + if(buffer != NULL) { + i++; + j = 0; + while((i < INIMAXLEN) && (scanbuffer[i] != 0)) { + *(buffer + j) = scanbuffer[i]; + i++; + j++; + } // ENDWHILE- Copying the value out to the outbound buffer. + *(buffer + j) = 0; // And 0-terminate. + } // ENDIF- Return the value as well? + } // ENDIF- End marks look good? Return successful. + } // ENDIF- Do we have a section match? + + if(retflag == 0) charcount += retval; + } // ENDWHILE- Scanning lines for the correct [Section] header. + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Value: %s", buffer); +#endif /* VERBOSE_FUNCTION_INI */ + + return(charcount); +} // END INIFindKeyWord() + + +// Returns: number of bytes left to write... (from charcount back) +int INICopy(ACTUALHANDLE infile, ACTUALHANDLE outfile, int charcount) { + char buffer[4096]; + int i; + int chunk; + int retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Copy(%i)", charcount); +#endif /* VERBOSE_FUNCTION_INI */ + + i = charcount; + chunk = 4096; + if(i < chunk) chunk = i; + while(chunk > 0) { + retval = ActualFileRead(infile, chunk, buffer); + if(retval <= 0) return(i); // Trouble? Stop here. + if(retval < chunk) chunk = retval; // Short block? Note it. + + retval = ActualFileWrite(outfile, chunk, buffer); + if(retval <= 0) return(i); // Trouble? Stop here. + i -= retval; + if(retval < chunk) return(i); // Short block written? Stop here. + + chunk = 4096; + if(i < chunk) chunk = i; + } // ENDWHILE- Copying a section of file across, one chunk at a time. + + return(0); +} // END INICopyToPos() + + +int INISaveString(char *file, char *section, char *keyword, char *value) { + char inname[INIMAXLEN+1]; + char outname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + ACTUALHANDLE outfile; + int i; + int retval; + char templine[INIMAXLEN+1]; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + if(keyword == NULL) return(-1); + if(value == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: SaveString(%s, %s, %s, %s)", + file, section, keyword, value); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + for(i = 0; i <= filepos; i++) outname[i] = inname[i]; + INIAddInExt(inname, filepos); + INIAddOutExt(outname, filepos); + + filepos = 0; + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new file"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(inname); + if(outfile == ACTUALHANDLENULL) return(-1); // Just a bad name? Abort. + + sprintf(templine, "[%s]\r\n", section); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + if(retval < i) { + ActualFileDelete(inname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + return(0); + } // ENDIF- No input file? Create a brand new .ini file then. + + retval = INIFindSection(infile, section); + if(retval < 0) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new section"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); // Move ini to beginning of file... + INICopy(infile, outfile, 0x0FFFFFFF); // Copy the whole file out... + + sprintf(templine, "\r\n[%s]\r\n", section); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + if(retval < i) { + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); + } // ENDIF- Couldn't find the section? Make a new one! + + filepos = retval; + ActualFileSeek(infile, filepos); + filepos += INIReadLine(infile, templine); // Get section line's byte count + + retval = INIFindKeyword(infile, keyword, NULL); + if(retval < 0) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + ActualFileSeek(infile, filepos); + retval = INIReadLine(infile, templine); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0) && (templine[i] != '=')) i++; + while((retval > 0) && (templine[i] == '=')) { + filepos += retval; + retval = INIReadLine(infile, templine); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0) && (templine[i] != '=')) i++; + } // ENDWHILE- skimming to the bottom of the section + + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + } else { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: replacing keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + filepos += retval; // Position just before old version of keyword + + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + INIReadLine(infile, templine); // Read past old keyword/value... + + // Replace with new value + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + } // ENDIF- Need to add a new keyword? + + INICopy(infile, outfile, 0xFFFFFFF); // Write out rest of file + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); +} // END INISaveString() + + +int INILoadString(char *file, char *section, char *keyword, char *buffer) { + char inname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + int retval; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + if(keyword == NULL) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: LoadString(%s, %s, %s)", + file, section, keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + INIAddInExt(inname, filepos); + + filepos = 0; + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) return(-1); + + retval = INIFindSection(infile, section); + if(retval < 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Didn't find it? Abort. + + retval = INIFindKeyword(infile, keyword, buffer); + if(retval < 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Didn't find it? Abort. + + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(0); +} // END INILoadString() + + +int INIRemove(char *file, char *section, char *keyword) { + char inname[INIMAXLEN+1]; + char outname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + ACTUALHANDLE outfile; + char templine[INIMAXLEN+1]; + int i; + int retval; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Remove(%s, %s, %s)", + file, section, keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + for(i = 0; i <= filepos; i++) outname[i] = inname[i]; + INIAddInExt(inname, filepos); + INIAddOutExt(outname, filepos); + + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) return(-1); + + retval = INIFindSection(infile, section); + if(retval == -1) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't even find the section? Abort + + filepos = retval; + if(keyword == NULL) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: removing section"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to the section? Abort. + + templine[0] = 0; + retval = 1; + while((retval > 0) && (templine[0] != '[')) { + retval = INIReadLine(infile, templine); + } // ENDWHILE- Read to the start of the next section... or EOF. + + if(templine[0] == '[') { + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + } // ENDIF- Are there other sections after this one? Save them then. + + } else { + filepos = retval; + ActualFileSeek(infile, filepos); + filepos += INIReadLine(infile, templine); // Get section line's byte count + + retval = INIFindKeyword(infile, keyword, NULL); + if(retval == -1) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't find the keyword? Abort + filepos += retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: removing keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + INIReadLine(infile, templine); // Read (and discard) the keyword line + } // ENDIF- Wipe out the whole section? Or just a keyword? + + INICopy(infile, outfile, 0xFFFFFFF); // Write out rest of file + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); +} // END INIRemove() + + +int INISaveUInt(char *file, char *section, char *keyword, unsigned int value) { + char numvalue[INIMAXLEN+1]; + + sprintf(numvalue, "%u", value); + return(INISaveString(file, section, keyword, numvalue)); +} // END INISaveUInt() + + +int INILoadUInt(char *file, char *section, char *keyword, unsigned int *buffer) { + char numvalue[INIMAXLEN+1]; + int retval; + unsigned int value; + // unsigned int sign; // Not needed in unsigned numbers + int pos; + + if(buffer == NULL) return(-1); + *(buffer) = 0; + + retval = INILoadString(file, section, keyword, numvalue); + if(retval < 0) return(retval); + + value = 0; + // sign = 1; // Start positive + pos = 0; + + // Note: skip leading spaces? (Shouldn't have to, I hope) + + // if(numvalue[pos] == '-') { + // pos++; + // sign = -1; + // } // ENDIF- Negative sign check + + while((pos < INIMAXLEN) && (numvalue[pos] != 0)) { + if(value > (0xFFFFFFFF / 10)) return(-1); // Overflow? + + if((numvalue[pos] >= '0') && (numvalue[pos] <= '9')) { + value *= 10; + value += numvalue[pos] - '0'; + pos++; + } else { + numvalue[pos] = 0; + } // ENDIF- Add a digit in? Or stop searching for digits? + } // ENDWHILE- Adding digits of info to our ever-increasing value + + // value *= sign + *(buffer) = value; + return(0); +} // END INILoadUInt() diff --git a/plugins/cdvd/CDVDisoEFP/src/ini.h b/plugins/cdvd/CDVDisoEFP/src/ini.h new file mode 100644 index 0000000..fbd2349 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/ini.h @@ -0,0 +1,64 @@ +/* ini.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef INI_H +#define INI_H + + +// #ifndef __LINUX__ +// #ifdef __linux__ +// #define __LINUX__ +// #endif /* __linux__ */ +// #endif /* No __LINUX__ */ + +// #define CDVDdefs +// #include "PS2Edefs.h" + + +// File format: +// [section] +// keyword=value + +// file - Name of the INI file +// section - Section within the file +// keyword - Identifier for a value +// value - value to store with a keyword in a section in the file +// buffer - place to retrieve the value of a keyword + +// return values: 0 = success, -1 = failure + + +// #define VERBOSE_FUNCTION_INI + +#define INIMAXLEN 255 + + +extern int INISaveString(char *file, char *section, char *keyword, char *value); +extern int INILoadString(char *file, char *section, char *keyword, char *buffer); + +extern int INISaveUInt(char *file, char *section, char *keyword, unsigned int value); +extern int INILoadUInt(char *file, char *section, char *keyword, unsigned int *buffer); + +// NULL in the keyword below removes the whole section. +extern int INIRemove(char *file, char *section, char *keyword); + + +#endif /* INI_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/isocompress.c b/plugins/cdvd/CDVDisoEFP/src/isocompress.c new file mode 100644 index 0000000..5385342 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/isocompress.c @@ -0,0 +1,914 @@ +/* isocompress.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + +#include "logfile.h" + +#include "isofile.h" + +#include "actualfile.h" + +#include "gzipv1.h" + +#include "blockv2.h" + +#include "gzipv2.h" + +#include "bzip2v2.h" + +#include "bzip2v3.h" + +#include "isocompress.h" + + + + + +const char *compressnames[] = { + + "No Compression", + + ".Z (zlib) for speed", + + ".BZ2 (bzip2) for speed", + + ".bz2 (bzip2) for size", + + NULL }; // Compress types 0, 3, 4, and 5 + + + +const char *compressdesc[] = { + + "", + + " zlib orig", + + " block.dump", + + " zlib speed", + + " bzip2 speed", + + " bzip2 size", + + NULL }; + + + +const char *compressid[] = { + + "BVD2", + + "Z V2", + + "BZV2", + + "BZV3", + + NULL }; // Starts at compress type 2 + + + +struct CompressExt compressext[] = { + + { ".z", 1 }, + + { ".Z", 1 }, + + { ".bz2", 5 }, + + { ".BZ2", 3 }, + + { ".bZ2", 3 }, + + { ".Bz2", 3 }, + + { ".bz", 3 }, + + { ".BZ", 3 }, + + { ".bZ", 3 }, + + { ".Bz", 3 }, + + { ".dump", 2 }, + + { NULL, 0 } + +}; + + + + + +int IsoNameStripCompress(struct IsoFile *isofile) { + + int tempext; + + int tempnamepos; + + int tempextpos; + + int retmethod; + + + + retmethod = 0; + + tempext = 0; + + while(compressext[tempext].name != NULL) { + + tempextpos = 0; + + while(*(compressext[tempext].name + tempextpos) != 0) tempextpos++; + + + + tempnamepos = isofile->namepos; + + while((tempnamepos > 0) && (tempextpos > 0) && + + (isofile->name[tempnamepos - 1] == *(compressext[tempext].name + tempextpos - 1))) { + + tempnamepos--; + + tempextpos--; + + } // ENDWHILE- Comparing one extension to the end of the file name + + if(tempextpos == 0) { + + isofile->namepos = tempnamepos; // Move name pointer in front of ext. + + return(compressext[tempext].method); // Found a match... say which one. + + } else { + + tempext++; // Next ext in the list to test... + + } // ENDIF- Did we find a match? + + } // ENDWHILE- looking through extension list + + + + return(0); // No compress extension found. + +} // END IsoNameStripCompress() + + + + + +int CompressOpenForRead(struct IsoFile *isofile) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: OpenForRead()"); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + retval = GZipV1OpenForRead(isofile); + + if(retval >= 0) retval = GZipV1OpenTableForRead(isofile); + + break; + + case 2: + + retval = BlockV2OpenForRead(isofile); + + if(retval >= 0) retval = BlockV2OpenTableForRead(isofile); + + break; + + case 3: + + retval = GZipV2OpenForRead(isofile); + + if(retval >= 0) retval = GZipV2OpenTableForRead(isofile); + + break; + + case 4: + + retval = BZip2V2OpenForRead(isofile); + + if(retval >= 0) retval = BZip2V2OpenTableForRead(isofile); + + break; + + case 5: + + retval = BZip2V3OpenForRead(isofile); + + if(retval >= 0) retval = BZip2V3OpenTableForRead(isofile); + + break; + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + return(retval); + +} // END CompressOpenForRead() + + + + + +int CompressSeek(struct IsoFile *isofile, off64_t sector) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: Seek(%lli)", sector); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + retval = GZipV1SeekTable(isofile, sector); + + break; + + case 2: + + retval = BlockV2SeekTable(isofile, sector); + + break; + + case 3: + + retval = GZipV2SeekTable(isofile, sector); + + break; + + case 4: + + retval = BZip2V2SeekTable(isofile, sector); + + break; + + case 5: + + retval = BZip2V3SeekTable(isofile, sector); + + break; + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + return(retval); + +} // END CompressSeek() + + + + + +int CompressRead(struct IsoFile *isofile, char *buffer) { + + struct TableData table; + + int retval; + + int compptr; + + int i; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: Read()"); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + retval = GZipV1ReadTable(isofile, &table); + + if(retval >= 0) { + + if(table.offset != isofile->filebytepos) { + + retval = GZipV1Seek(isofile, table.offset); + + } // ENDIF- The data file not in position? + + } // ENDIF- Did we get a table entry? + + if(retval >= 0) { + + retval = GZipV1Read(isofile, table.size, buffer); + + } // ENDIF- Are we still on track? + + break; + + + + case 2: + + retval = BlockV2ReadTable(isofile, &table); + + if(retval >= 0) { + + if(table.offset != isofile->filebytepos) { + + retval = BlockV2Seek(isofile, table.offset); + + } // ENDIF- The data file not in position? + + } // ENDIF- Did we get a table entry? + + if(retval >= 0) { + + retval = BlockV2Read(isofile, table.size, buffer); + + } // ENDIF- Are we still on track? + + break; + + + + + + case 3: + + retval = GZipV2ReadTable(isofile, &table); + + if(retval >= 0) { + + if(table.offset != isofile->filebytepos) { + + retval = GZipV2Seek(isofile, table.offset); + + } // ENDIF- The data file not in position? + + } // ENDIF- Did we get a table entry? + + if(retval >= 0) { + + retval = GZipV2Read(isofile, table.size, buffer); + + } // ENDIF- Are we still on track? + + break; + + + + case 4: + + retval = 0; + + if((isofile->filesectorpos < isofile->compsector) || + + (isofile->filesectorpos > isofile->compsector + isofile->numsectors - 1)) { + + + + retval = BZip2V2ReadTable(isofile, &table); + + if(retval >= 0) { + + if(table.offset != isofile->filebytepos) { + + retval = BZip2V2Seek(isofile, table.offset); + + } // ENDIF- The data file not in position? + + } // ENDIF- Did we get a table entry? + + if(retval >= 0) { + + retval = BZip2V2Read(isofile, table.size, isofile->compblock); + + isofile->compsector = isofile->filesectorpos / isofile->numsectors; + + isofile->compsector *= isofile->numsectors; + + } // ENDIF- Are we still on track? + + } // ENDIF- Did we have to read in another block? + + + + if(retval >= 0) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + if((compptr < 0) || (compptr > (65535 - isofile->blocksize))) { + + retval = -1; + + } else { + + for(i = 0; i < isofile->blocksize; i++) + + *(buffer + i) = isofile->compblock[compptr + i]; + + isofile->filesectorpos++; + + } // ENDIF- Not a good buffer pointer? Say so. + + } // ENDIF- Do we have a valid buffer to draw from? + + break; + + + + case 5: + + retval = 0; + + if((isofile->filesectorpos < isofile->compsector) || + + (isofile->filesectorpos > isofile->compsector + isofile->numsectors - 1)) { + + + + if(isofile->filesectorpos != isofile->compsector + isofile->numsectors) { + + retval = BZip2V3ReadTable(isofile, &table); + + if(retval >= 0) { + + if(table.offset != isofile->filebytepos) { + + retval = BZip2V3Seek(isofile, table.offset); + + } // ENDIF- The data file not in position? + + } // ENDIF- Did we get a table entry? + + } // ENDIF- Not the next block in the batch? Seek then. + + + + if(retval >= 0) { + + retval = BZip2V3Read(isofile, 0, isofile->compblock); + + isofile->compsector = isofile->filesectorpos / isofile->numsectors; + + isofile->compsector *= isofile->numsectors; + + } // ENDIF- Are we still on track? + + } // ENDIF- Did we have to read in another block? + + + + if(retval >= 0) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + if((compptr < 0) || (compptr > (65535 - isofile->blocksize))) { + + retval = -1; + + } else { + + for(i = 0; i < isofile->blocksize; i++) + + *(buffer + i) = isofile->compblock[compptr + i]; + + isofile->filesectorpos++; + + } // ENDIF- Not a good buffer pointer? Say so. + + } // ENDIF- Do we have a valid buffer to draw from? + + break; + + + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + if(retval >= 0) retval = isofile->blocksize; + + return(retval); + +} // END CompressRead() + + + + + +void CompressClose(struct IsoFile *isofile) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: Close()"); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + GZipV1Close(isofile); + + break; + + case 2: + + BlockV2Close(isofile); + + break; + + case 3: + + GZipV2Close(isofile); + + break; + + case 4: + + BZip2V2Close(isofile); + + break; + + case 5: + + BZip2V3Close(isofile); + + break; + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + return; + +} // END CompressClose() + + + + + +int CompressOpenForWrite(struct IsoFile *isofile) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: OpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + retval = GZipV1OpenForWrite(isofile); + + if(retval >= 0) retval = GZipV1OpenTableForWrite(isofile); + + break; + + case 2: + + retval = -1; + + break; + + case 3: + + retval = GZipV2OpenForWrite(isofile); + + if(retval >= 0) retval = GZipV2OpenTableForWrite(isofile); + + break; + + case 4: + + retval = BZip2V2OpenForWrite(isofile); + + if(retval >= 0) retval = BZip2V2OpenTableForWrite(isofile); + + break; + + case 5: + + retval = BZip2V3OpenForWrite(isofile); + + if(retval >= 0) retval = BZip2V3OpenTableForWrite(isofile); + + break; + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + return(retval); + +} // END CompressOpenForWrite() + + + + + +int CompressWrite(struct IsoFile *isofile, char *buffer) { + + struct TableData table; + + int compptr; + + int retval; + + int i; + + + +#ifdef VERBOSE_FUNCTION_ISOCOMPRESS + + PrintLog("CDVDiso compress: Write()"); + +#endif /* VERBOSE_FUNCTION_ISOCOMPRESS */ + + + + switch(isofile->compress) { + + case 1: + + retval = GZipV1Write(isofile, buffer); + + if(retval > 0) { + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + retval = GZipV1WriteTable(isofile, table); + + } // ENDIF- Wrote the data out? Update the table as well. + + break; + + + + case 2: + + retval = -1; + + break; + + + + case 3: + + retval = GZipV2Write(isofile, buffer); + + if(retval > 0) { + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + retval = GZipV2WriteTable(isofile, table); + + } // ENDIF- Wrote the data out? Update the table as well. + + break; + + + + case 4: + + retval = 0; + + if((isofile->filesectorpos < isofile->compsector) || + + (isofile->filesectorpos > isofile->compsector + isofile->numsectors - 1)) { + + retval = BZip2V2Write(isofile, isofile->compblock); + + isofile->compsector += isofile->numsectors; + + if(retval > 0) { + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + retval = BZip2V2WriteTable(isofile, table); + + } // ENDIF- Wrote the data out? Update the table as well. + + } // ENDIF- Do we have a full buffer to write out? + + + + if(retval >= 0) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = 0; i < isofile->blocksize; i++) + + isofile->compblock[compptr + i] = *(buffer + i); + + } // ENDIF- Do we have a valid buffer to draw from? + + isofile->filesectorpos++; + + break; + + + + case 5: + + retval = 0; + + if((isofile->filesectorpos < isofile->compsector) || + + (isofile->filesectorpos > isofile->compsector + isofile->numsectors - 1)) { + + retval = BZip2V3Write(isofile, isofile->compblock); + + isofile->compsector += isofile->numsectors; + + if(retval > 0) { + + table.offset = isofile->filebytepos - retval; + + table.size = retval; + + retval = BZip2V3WriteTable(isofile, table); + + } // ENDIF- Wrote the data out? Update the table as well. + + } // ENDIF- Do we have a full buffer to write out? + + + + if(retval >= 0) { + + compptr = isofile->filesectorpos - isofile->compsector; + + compptr *= isofile->blocksize; + + for(i = 0; i < isofile->blocksize; i++) + + isofile->compblock[compptr + i] = *(buffer + i); + + } // ENDIF- Do we have a valid buffer to draw from? + + isofile->filesectorpos++; + + break; + + + + default: + + retval = -1; + + break; + + } // ENDSWITCH compress- which method do we try to get header info from? + + + + if(retval >= 0) retval = isofile->blocksize; + + return(retval); + +} // END CompressWrite() + diff --git a/plugins/cdvd/CDVDisoEFP/src/isocompress.h b/plugins/cdvd/CDVDisoEFP/src/isocompress.h new file mode 100644 index 0000000..f566d0f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/isocompress.h @@ -0,0 +1,158 @@ +/* isocompress.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef ISOCOMPRESS_H + +#define ISOCOMPRESS_H + + + + + +#include + + + +#include "isofile.h" + +#include "actualfile.h" + + + + + +// #define VERBOSE_FUNCTION_ISOCOMPRESS + +// #define VERBOSE_WARNING_ISOCOMPRESS + + + + + +struct CompressExt { + + const char *name; + + int method; + +}; + + + +#ifdef _WIN32 + +#pragma pack(1) + +#endif /* _WIN32 */ + + + +struct TableData { + + off64_t offset; + + unsigned short size; + +#ifdef _WIN32 + +}; + +#else + +} __attribute__ ((packed)); + +#endif /* _WIN32 */ + + + +union TableMap { + + struct TableData table; + + char ch[sizeof(struct TableData)]; + +}; + + + + + +extern const char *compressnames[]; + +extern const char *compressdesc[]; + + + +extern struct CompressExt compressext[]; + + + + + +extern int IsoNameStripCompress(struct IsoFile *isofile); + + + +// 0 = success, -1 = Failure w/data, -2 = Failure w/table + +extern int CompressOpenForRead(struct IsoFile *isofile); + + + +extern int CompressSeek(struct IsoFile *isofile, off64_t sector); + +extern int CompressRead(struct IsoFile *isofile, char *buffer); + +extern void CompressClose(struct IsoFile *isofile); + + + +extern int CompressOpenForWrite(struct IsoFile *isofile); + +extern int CompressWrite(struct IsoFile *isofile, char *buffer); + + + + + +#endif /* ISOCOMPRESS_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/isofile.c b/plugins/cdvd/CDVDisoEFP/src/isofile.c new file mode 100644 index 0000000..a655b59 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/isofile.c @@ -0,0 +1,1292 @@ +/* isofile.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // malloc() + +#include // off64_t + + + +#ifndef __LINUX__ + +#ifdef __linux__ + +#define __LINUX__ + +#endif /* __linux__ */ + +#endif /* No __LINUX__ */ + +#define CDVDdefs + +#include "PS2Edefs.h" + + + +#include "logfile.h" + +#include "multifile.h" + +#include "isocompress.h" + +#include "actualfile.h" + +#include "imagetype.h" + +#include "toc.h" + +#include "ecma119.h" + +#include "isofile.h" + + + + + +const char *isofileext[] = { + + ".iso", + + ".bin", + + ".img", + + NULL + +}; + + + +const char *cdname = "CD-XA001\0"; + +const char *playstationid = "PLAYSTATION\0"; + +// const char ps1/2name? + + + +// Internal functions + + + +void IsoNameStripExt(struct IsoFile *isofile) { + + int tempext; + + int tempnamepos; + + int tempextpos; + + + + tempext = 0; + + while(isofileext[tempext] != NULL) { + + tempextpos = 0; + + while(*(isofileext[tempext] + tempextpos) != 0) tempextpos++; + + + + tempnamepos = isofile->namepos; + + while((tempnamepos > 0) && (tempextpos > 0) && + + (isofile->name[tempnamepos - 1] == *(isofileext[tempext] + tempextpos - 1))) { + + tempnamepos--; + + tempextpos--; + + } // ENDWHILE- Comparing one extension to the end of the file name + + if(tempextpos == 0) { + + isofile->namepos = tempnamepos; // Move name pointer in front of ext. + + tempext = 0; // ... and test the list all over again. + + } else { + + tempext++; // Next ext in the list to test... + + } // ENDIF- Did we find a match? + + } // ENDWHILE- looking through extension list + +} // END IsoNameStripExt() + + + + + +// External functions + + + +struct IsoFile *IsoFileOpenForRead(const char *filename) { + + struct IsoFile *newfile; + + int retval; + + int i; + + char tempblock[2448]; + + struct tocTN toctn; + + struct tocTD toctd; + +// union { + +// struct ECMA119PrimaryVolume vol; + +// char ch[sizeof(struct ECMA119PrimaryVolume)]; + +// } *volcheck; + + union { + + struct ECMA119PrimaryVolume *vol; + + char *ch; + + } volcheck; + + + + newfile = NULL; + + + + if(filename == NULL) return(NULL); + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileOpenForRead(%s)", filename); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + newfile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); + + if(newfile == NULL) return(NULL); + + + + newfile->sectorpos = 0; + + newfile->openforread = 1; // Read-only ISO + + newfile->filebytepos = 0; + + newfile->filesectorpos = 0; + + newfile->blocksize = 0; // Flags as non-detected yet (Compress vs. Image) + + newfile->tabledata = NULL; + + + + newfile->namepos = 0; + + while((newfile->namepos < 255) && + + (*(filename + newfile->namepos) != 0)) { + + newfile->name[newfile->namepos] = *(filename + newfile->namepos); + + newfile->namepos++; + + } // ENDWHILE- copying the file name in... + + newfile->name[newfile->namepos] = 0; // And 0-terminate. + + + + IsoNameStripExt(newfile); // Ex: -I00.Z[.bin] + + + + // File Compression name detection + + newfile->compress = IsoNameStripCompress(newfile); // Ex: -I00.bin[.Z] + + newfile->compresspos = newfile->namepos; + + + + // Test File name compression + + retval = -1; + + if(newfile->compress > 0) { + + retval = CompressOpenForRead(newfile); + + if(retval == -1) CompressClose(newfile); + + } // ENDIF- Have a compression type hint? Test it out + + + + if(retval == -1) { + + newfile->compress = 5; + + while((newfile->compress > 0) && (retval == -1)) { + + retval = CompressOpenForRead(newfile); + + if(retval == -1) { + + CompressClose(newfile); + + newfile->compress--; + + } // ENDIF- Failed to open? Close it... and try the next one. + + } // ENDWHILE- Trying to find a compression scheme that will work... + + + + if(newfile->compress == 0) { + + newfile->handle = ActualFileOpenForRead(newfile->name); + + if(newfile->handle == ACTUALHANDLENULL) { + + free(newfile); + + newfile = NULL; + + return(NULL); + + } // ENDIF- Failed to open? Abort. + + newfile->filebytesize = ActualFileSize(newfile->handle); + + } // ENDIF- No compression? Open it uncompressed. + + } // ENDIF- Temp- failed to open? Abort... + + + + // Compressed data file with no table? Return prematurely... + + // Condition detection: compress > 0, tablehandle == ACTUALHANDLENULL + + if(retval == -2) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Data file with no table!"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(newfile); + + } // ENDIF- + + + + newfile->imagetype = DetectImageType(newfile); + + + + if(newfile->compress == 0) { + + newfile->filesectorsize = newfile->filebytesize / newfile->blocksize; + + } // ENDIF- Now that blocksize is known, raw file sectors can be figured out + + + + IsoNameStripExt(newfile); // Ex: -I00[.bin].Z + + + + IsoNameStripMulti(newfile); // Ex: [-I00].bin.Z + + + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Filename: %s", filename); + + if(newfile->multi > 0) PrintLog("CDVD isofile: Multiple <2GB files."); + + PrintLog("CDVD isofile: Compression Method: %s", + + compressdesc[newfile->compress]); + + PrintLog("CDVD isofile: Image Type: %s", + + newfile->imagename); + + PrintLog("CDVD isofile: Block Size: %lli", newfile->blocksize); + + PrintLog("CDVD isofile: Total Sectors (of first file): %lli", + + newfile->filesectorsize); + +#endif /* VERBOSE_DISC_INFO */ + + + + // Load a TOC from a .toc file (is there is one) + + retval = IsoLoadTOC(newfile); + + if(retval == 0) return(newfile); + + + + // Get the volume sector for disc type test + + retval = IsoFileSeek(newfile, 16); + + if(retval < 0) { + + newfile = IsoFileClose(newfile); + + return(NULL); + + } // ENDIF- Could not find the directory sector? Abort. + + retval = IsoFileRead(newfile, tempblock); + + if(retval < 0) { + + newfile = IsoFileClose(newfile); + + return(NULL); + + } // ENDIF- Could not read the directory sector? Abort. + + + + volcheck.ch = tempblock; + + volcheck.ch += newfile->blockoffset; + + if(ValidateECMA119PrimaryVolume(volcheck.vol) != 0) { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Not an ISO9660 disc! Music CD perhaps?"); + +#endif /* VERBOSE_DISC_INFO */ + + newfile->cdvdtype = CDVD_TYPE_CDDA; + + + + } else { + + // Is this a playstation image? + + i = 0; + + while((*(playstationid + i) != 0) && + + (*(playstationid + i) == tempblock[newfile->blockoffset + 8 + i])) i++; + + if(*(playstationid + i) != 0) { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Not a Playstation Disc!"); + +#endif /* VERBOSE_DISC_INFO */ + + newfile->cdvdtype = CDVD_TYPE_DVDV; + + } else { + + newfile->cdvdtype = CDVD_TYPE_PS2DVD; + + } // ENDIF- Is this not a Playstation 1 image? + + // Sidenote: if the emulator is just playing Playstation 2 images, we could + + // just invalidate the image file right here. + + } // ENDIF- Not an ISO9660 disc? Assume Music CD. + + + + if(newfile->cdvdtype == CDVD_TYPE_PS2DVD) { + + // Is this a Playstation CD image? + + i = 0; + + while((*(cdname + i) != 0) && + + (*(cdname + i) == tempblock[newfile->blockoffset + 1024 + i])) i++; + + if(*(cdname + i) == 0) { + + newfile->cdvdtype = CDVD_TYPE_PSCD; + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Image is a Playstation 1 CD."); + +#endif /* VERBOSE_DISC_INFO */ + + } else { + + if(newfile->blocksize != 2048) { + + newfile->cdvdtype = CDVD_TYPE_PS2CD; + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Image is a Playstation 2 CD."); + +#endif /* VERBOSE_DISC_INFO */ + + } else { + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD isofile: Image is a DVD."); + +#endif /* VERBOSE_DISC_INFO */ + + } // ENDIF- Is the blocksize not 2048? CD image then. + + } // ENDIF- Is this a PS1 CD image? + + } // ENDIF- Is this a Playstation image? + + volcheck.ch = NULL; + + + + if((newfile->cdvdtype == CDVD_TYPE_DVDV) && + + (newfile->blocksize == 2352)) newfile->cdvdtype = CDVD_TYPE_CDDA; + + + + // Slap together a TOC based on the above guesswork. + + IsoInitTOC(newfile); + + if((newfile->cdvdtype != CDVD_TYPE_PS2DVD) && + + (newfile->cdvdtype != CDVD_TYPE_DVDV)) { + + toctn.strack = 1; + + toctn.etrack = 1; + + IsoAddTNToTOC(newfile, toctn); + + + + toctd.type = 0; + + toctd.lsn = newfile->filesectorsize; + + IsoAddTDToTOC(newfile, 0xAA, toctd); + + + + toctd.type = 0; // ? + + if(newfile->cdvdtype == CDVD_TYPE_CDDA) { + + toctd.type = CDVD_AUDIO_TRACK; // Music track assumed + + } else { + + toctd.type = CDVD_MODE1_TRACK; // Data track assumed + + } // ENDIF- Is this track a music or data track? + + toctd.lsn = 0; + + IsoAddTDToTOC(newfile, 1, toctd); + + } // ENDIF- Is this a CD? Single track for all sectors + + + + return(newfile); + +} // END IsoFileOpenForRead() + + + + + +int IsIsoFile(const char *filename) { + + int retval; + + struct IsoFile *tempfile; + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsIsoFile()"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + retval = IsActualFile(filename); + + if(retval < 0) return(retval); // Not a regular file? Report it. + + + + tempfile = NULL; + + tempfile = IsoFileOpenForRead(filename); + + if(tempfile == NULL) return(-3); // Not an image file? Report it. + + + + retval = 0; + + if((tempfile->compress > 0) && + + (tempfile->tablehandle == ACTUALHANDLENULL) && + + (tempfile->tabledata == NULL)) retval = -4; + + + + tempfile = IsoFileClose(tempfile); + + return(retval); + +} // END IsIsoFile() + + + + + +int IsoFileSeek(struct IsoFile *file, off64_t sector) { + + int retval; + + + + if(file == NULL) return(-1); + + if(sector < 0) return(-1); + + + + if(sector == file->sectorpos) return(0); + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileSeek(%llu)", sector); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + if(file->multi > 0) { + + retval = MultiFileSeek(file, sector); + + } else if(file->compress > 0) { + + retval = CompressSeek(file, sector); + + } else { + + retval = ActualFileSeek(file->handle, + + (sector * file->blocksize) + file->imageheader); + + if(retval == 0) { + + file->filesectorpos = sector; + + file->filebytepos = (sector * file->blocksize) + file->imageheader; + + } // ENDIF- Succeeded? Adjust internal pointers + + } // ENDLONGIF- Seek right file? Or compressed block? Or Raw block? + + + + if(retval < 0) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Trouble finding the sector!"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(-1); + + } // ENDIF- Trouble reading the block? Say so! + + + + file->sectorpos = sector; + + return(0); + +} // END IsoFileSeek() + + + + + +int IsoFileRead(struct IsoFile *file, char *block) { + + int retval; + + + + if(file == NULL) return(-1); + + if(block == NULL) return(-1); + + if(file->openforread == 0) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileRead(%i)", file->blocksize); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + if(file->multi > 0) { + + retval = MultiFileRead(file, block); + + } else if(file->compress > 0) { + + retval = CompressRead(file, block); + + } else { + + if(file->sectorpos >= file->filesectorsize) return(-1); + + retval = ActualFileRead(file->handle, + + file->blocksize, + + block); + + if(retval > 0) file->filebytepos += retval; + + if(retval == file->blocksize) file->filesectorpos++; + + } // ENDLONGIF- Read right file? Or compressed block? Or Raw block? + + + + if(retval < 0) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Trouble reading the sector!"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(-1); + + } // ENDIF- Trouble reading the block? Say so! + + + + if(retval < file->blocksize) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Short block! Got %i out of %i bytes", + + retval, file->blocksize); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(-1); + + } // ENDIF- Didn't get enough bytes? Say so! + + + + file->sectorpos++; + + return(0); + +} // END IsoFileRead() + + + + + +struct IsoFile *IsoFileClose(struct IsoFile *file) { + + if(file == NULL) return(NULL); + + + + if(file->handle != ACTUALHANDLENULL) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileClose()"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + if(file->compress > 0) { + + CompressClose(file); + + } else { + + ActualFileClose(file->handle); + + file->handle = ACTUALHANDLENULL; + + } // ENDIF- Compressed File? Close (and flush) compression too. + + } // ENDIF- Open Handle? Close the file + + + + free(file); + + return(NULL); + +} // END IsoFileClose() + + + + + +struct IsoFile *IsoFileOpenForWrite(const char *filename, + + int imagetype, + + int multi, + + int compress) { + + struct IsoFile *newfile; + + + + newfile = NULL; + + + + if(filename == NULL) return(NULL); + + if((imagetype < 0) || (imagetype > 11)) return(NULL); + + if((compress < 0) || (compress > 5)) return(NULL); + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileOpenForWrite()"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + newfile = (struct IsoFile *) malloc(sizeof(struct IsoFile)); + + if(newfile == NULL) return(NULL); + + + + newfile->sectorpos = 0; + + newfile->openforread = 0; // Write-only file + + newfile->filebytesize = 0; + + newfile->filebytepos = 0; + + newfile->filesectorsize = 0; + + newfile->filesectorpos = 0; + + + + // if(toc != NULL) { + + // for(i = 0; i < 2048; i++) newfile->toc[i] = *(toc + i); + + // } else { + + // for(i = 0; i < 2048; i++) newfile->toc[i] = 0; + + // } // ENDIF- Do we have a PS2 Table of Contents to save out as well? + + + + newfile->namepos = 0; + + while((newfile->namepos < 255) && + + (*(filename + newfile->namepos) != 0)) { + + newfile->name[newfile->namepos] = *(filename + newfile->namepos); + + newfile->namepos++; + + } // ENDWHILE- copying the file name in... + + newfile->name[newfile->namepos] = 0; // And 0-terminate. + + + + IsoNameStripExt(newfile); + + IsoNameStripCompress(newfile); + + IsoNameStripExt(newfile); + + IsoNameStripMulti(newfile); + + newfile->name[newfile->namepos] = 0; // And 0-terminate. + + + + newfile->imagetype = imagetype; + + GetImageType(newfile, imagetype); + + newfile->cdvdtype = CDVD_TYPE_PS2DVD; // Does it matter here? Nope. + + + + newfile->multi = multi; + + if(newfile->multi > 0) { + + newfile->name[newfile->namepos + 0] = '-'; + + newfile->name[newfile->namepos + 1] = 'I'; + + newfile->name[newfile->namepos + 2] = '0'; + + newfile->name[newfile->namepos + 3] = '0'; + + newfile->name[newfile->namepos + 4] = 0; + + newfile->multipos = newfile->namepos + 3; + + newfile->namepos += 4; + + newfile->multistart = 0; + + newfile->multiend = 0; + + newfile->multinow = 0; + + newfile->multioffset = 0; + + newfile->multisectorend[0] = 0; + + } // ENDIF- Are we creating a multi-file? + + + + newfile->compress = compress; + + switch(newfile->compress) { + + case 1: + + case 3: + + newfile->name[newfile->namepos + 0] = '.'; + + newfile->name[newfile->namepos + 1] = 'Z'; + + newfile->name[newfile->namepos + 2] = 0; + + newfile->namepos += 2; + + break; + + + + case 2: + + newfile->name[newfile->namepos + 0] = '.'; + + newfile->name[newfile->namepos + 1] = 'd'; + + newfile->name[newfile->namepos + 2] = 'u'; + + newfile->name[newfile->namepos + 3] = 'm'; + + newfile->name[newfile->namepos + 4] = 'p'; + + newfile->name[newfile->namepos + 5] = 0; + + newfile->namepos += 5; + + break; + + + + case 4: + + newfile->name[newfile->namepos + 0] = '.'; + + newfile->name[newfile->namepos + 1] = 'B'; + + newfile->name[newfile->namepos + 2] = 'Z'; + + newfile->name[newfile->namepos + 3] = '2'; + + newfile->name[newfile->namepos + 4] = 0; + + newfile->namepos += 4; + + break; + + + + case 5: + + newfile->name[newfile->namepos + 0] = '.'; + + newfile->name[newfile->namepos + 1] = 'b'; + + newfile->name[newfile->namepos + 2] = 'z'; + + newfile->name[newfile->namepos + 3] = '2'; + + newfile->name[newfile->namepos + 4] = 0; + + newfile->namepos += 4; + + break; + + + + case 0: + + default: + + break; + + } // ENDSWITCH compress- which compression extension should we add on? + + + + newfile->name[newfile->namepos + 0] = '.'; + + newfile->name[newfile->namepos + 4] = 0; + + if(newfile->blocksize == 2048) { + + newfile->name[newfile->namepos + 1] = 'i'; + + newfile->name[newfile->namepos + 2] = 's'; + + newfile->name[newfile->namepos + 3] = 'o'; + + } else { + + newfile->name[newfile->namepos + 1] = 'b'; + + newfile->name[newfile->namepos + 2] = 'i'; + + newfile->name[newfile->namepos + 3] = 'n'; + + } // ENDIF- Is this a true ISO (or just a raw BIN file?) + + newfile->namepos += 4; + + + + if(IsActualFile(newfile->name) == 0) { + + free(newfile); + + newfile = NULL; + + return(NULL); + + } // ENDIF- Does the destination file already exist? + + + + if(newfile->compress > 0) { + + CompressOpenForWrite(newfile); + + if((newfile->handle != ACTUALHANDLENULL) && + + (newfile->tablehandle == ACTUALHANDLENULL)) { + + ActualFileClose(newfile->handle); + + newfile->handle = ACTUALHANDLENULL; + + } // ENDIF Data file created, but table file stopped? Close and remove data + + } else { + + newfile->handle = ActualFileOpenForWrite(newfile->name); + + } // ENDIF- Writing out a compressed file? + + + + if(newfile->handle == ACTUALHANDLENULL) { + + free(newfile); + + newfile = NULL; + + return(NULL); + + } // ENDIF- Couldn't create file? Abort + + + + return(newfile); + +} // END IsoFileOpenForWrite() + + + + + +int IsoFileWrite(struct IsoFile *file, char *block) { + + int byteswritten; + + + + if(file == NULL) return(-1); + + if(block == NULL) return(-1); + + if(file->openforread == 1) return(-1); + + + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileWrite()"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + byteswritten = 0; + + if(file->multi > 0) { + + byteswritten = MultiFileWrite(file, block); + + } else if(file->compress > 0) { + + byteswritten = CompressWrite(file, block); + + } else { + + byteswritten = ActualFileWrite(file->handle, + + file->blocksize, + + block); + + if(byteswritten > 0) file->filebytepos += byteswritten; + + if(byteswritten == file->blocksize) file->filesectorpos++; + + } // ENDLONGIF- Write to different file? Compressed block? or Raw? + + if(byteswritten < 0) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Trouble writing the sector!"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(-1); + + } // ENDIF- Trouble reading the block? Say so! + + if(file->filebytepos > file->filebytesize) + + file->filebytesize = file->filebytepos; + + + + if(byteswritten < file->blocksize) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: Short block! Wrote %i out of %i bytes", + + byteswritten, file->blocksize); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + return(-1); + + } // ENDIF- Didn't write enough bytes? Say so! + + if(file->filesectorpos > file->filesectorsize) + + file->filesectorsize = file->filesectorpos; + + + + file->sectorpos++; + + return(0); + +} // END IsoFileWrite() + + + + + +struct IsoFile *IsoFileCloseAndDelete(struct IsoFile *file) { + + int i; + + + + if(file == NULL) return(NULL); + + + + if(file->handle != ACTUALHANDLENULL) { + +#ifdef VERBOSE_FUNCTION_ISOFILE + + PrintLog("CDVD isofile: IsoFileCloseAndDelete()"); + +#endif /* VERBOSE_FUNCTION_ISOFILE */ + + + + if(file->compress > 0) { + + CompressClose(file); + + } else { + + ActualFileClose(file->handle); + + file->handle = ACTUALHANDLENULL; + + } // ENDIF- Compressed File? Close (and flush) compression too. + + } // ENDIF- Open Handle? Close the file + + + + if(file->multi == 1) { + + for(i = file->multistart; i <= file->multiend; i++) { + + file->name[file->multipos] = '0' + i; + + ActualFileDelete(file->name); + + if(file->compress > 0) { + + file->tablename[file->multipos] = '0' + i; + + ActualFileDelete(file->tablename); + + } // ENDIF- Get the table file too? + + } // NEXT i- iterate through each multi-file name, removing it. + + } else { + + ActualFileDelete(file->name); + + if(file->compress > 0) { + + ActualFileDelete(file->tablename); + + } // ENDIF- Get the table file too? + + } // ENDIF- Do we have to remove multiple files? + + + + free(file); + + return(NULL); + +} // END IsoFileCloseAndDelete() + diff --git a/plugins/cdvd/CDVDisoEFP/src/isofile.h b/plugins/cdvd/CDVDisoEFP/src/isofile.h new file mode 100644 index 0000000..93dff0e --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/isofile.h @@ -0,0 +1,246 @@ +/* isofile.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef ISOFILE_H + +#define ISOFILE_H + + + + + +#include // off64_t + + + +#include "actualfile.h" + + + + + +// #define VERBOSE_FUNCTION_ISOFILE + +#define VERBOSE_DISC_INFO + + + + + +struct IsoFile { + + // *** Primary Data area + + char name[256]; + + int namepos; // Used for detection of components within name + + ACTUALHANDLE handle; + + off64_t sectorpos; // Overall. + + // blocks (char [2352]) provided by users + + + + // *** Derived Stats from Primary Data + + int openforread; // 1 = Yes, 0 = No + + off64_t filebytesize; + + off64_t filebytepos; + + off64_t filesectorsize; + + off64_t filesectorpos; + + int cdvdtype; // for GetDiskType call + + char toc[2048]; // for GetTOC call + + + + // From imagetype.h + + int imagetype; + + char imagename[40]; + + off64_t imageheader; // Header bytes in every file... + + off64_t blocksize; // sized to add quickly to other off64_t counters + + int blockoffset; // Where to place data in block + + + + // from isocompress.h + + int compress; // Compression Method used (0 = none, 1...) + + int compresspos; // Start pos of ".Z", ".BZ", etc... + + char tablename[256]; + + ACTUALHANDLE tablehandle; + + char compblock[65536]; // Temporary storage of uncompressed sectors. + + off64_t compsector; // First sector of the compblock[] + + off64_t numsectors; // Number of sectors in a compression block + + char *tabledata; // Table holding area + + + + // From multifile.h + + int multi; // 0 = Single File, 1 = Multiple Files + + int multipos; // Position of Multi # ('0'-'9') + + off64_t multisectorend[10]; // Ending sector of each file... + + off64_t multioffset; // To help with seek calls. Sector offset. + + int multistart; // Starting file number (0-1) + + int multiend; // Ending file number (?-9) + + int multinow; // Current open file number + + + + // *** (Specific) Compression Data area + +}; + + + + + +// Read-only section + +// IsoFiles opened for read are treated as random-access files + + + +extern int IsIsoFile(const char *filename); + +// Returns an image type (positive or zero) or an error (negative) + + + +extern struct IsoFile *IsoFileOpenForRead(const char *filename); + +// Will seek blocksize and compression method on it's own. + + + +extern int IsoFileSeek(struct IsoFile *file, off64_t sector); + +// Sector, not byte. + + + +extern int IsoFileRead(struct IsoFile *file, char *block); + +// Buffers should be at least of "blocksize" size. 2352 bytes, please. + + + + + +// Write-only section + +// IsoFiles opened for write are treated as sequential files (still written + +// out a block at a time, though, to be read in later as random-access) + +// No plans are made to make writes random-access at this time. + + + +extern struct IsoFile *IsoFileOpenForWrite(const char *filename, + + int imagetype, + + int multi, + + int compress); + + + +extern int IsoFileWrite(struct IsoFile *file, char *block); + +// Uncompressed buffers, please. + +// Will compress with this call (if it's necessary.) + + + + + +// Calls used for all Isofiles + + + +extern struct IsoFile *IsoFileClose(struct IsoFile *file); + +// Use return variable to NULL the file pointer. + +// Ex: lastfile = IsoFileClose(lastfile); + + + +extern struct IsoFile *IsoFileCloseAndDelete(struct IsoFile *file); + +// For failure to finish writing out a file(set). + + + + + +#endif /* ISOFILE_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/multifile.c b/plugins/cdvd/CDVDisoEFP/src/multifile.c new file mode 100644 index 0000000..9c26174 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/multifile.c @@ -0,0 +1,578 @@ +/* multifile.c + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#include // NULL + +#include // off64_t + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + +#include "logfile.h" + +#include "isofile.h" + +#include "isocompress.h" + +#include "actualfile.h" + +#include "multifile.h" + + + + + +#define FILESIZELIMIT 2000000000 + + + + + +char *multinames[] = { + + "", + + "Multiple ", + + NULL }; + + + + + +void IsoNameStripMulti(struct IsoFile *isofile) { + + isofile->multi = 0; + + if(isofile->namepos < 2) return; // Not enough digits + + if(isofile->name[isofile->namepos - 1] < '0') return; // Ex: -I0[0] + + if(isofile->name[isofile->namepos - 1] > '1') return; // Ex: -I0[1] + + if(isofile->name[isofile->namepos - 2] != '0') return; // Ex: -I[0]0 + + + + isofile->multi = 1; + + isofile->multipos = isofile->namepos - 1; + + isofile->namepos -= 2; + + isofile->multistart = isofile->name[isofile->multipos] - '0'; + + isofile->multiend = isofile->multistart; + + isofile->multinow = isofile->multistart; + + isofile->multisectorend[0] = 0; // Sometimes the file name starts with '1' + + isofile->multisectorend[isofile->multistart] = isofile->filesectorsize; + + isofile->multioffset = 0; + + + + if(isofile->namepos < 1) return; + + if(isofile->name[isofile->namepos - 1] != 'I') return; // Ex: -[I]00 + + isofile->namepos--; + + + + if(isofile->namepos < 2) return; // Filename doesn't start with '-' + + if(isofile->name[isofile->namepos - 1] != '-') return; // Ex: [-]I00 + + isofile->namepos--; + + + + return; + +} // END IsoNameStripMulti() + + + + + +int MultiFileSeek(struct IsoFile *isofile, off64_t sector) { + + int multinext; + + int retval; + + off64_t tempfilesector; + + + +#ifdef VERBOSE_FUNCTION_MULTIFILE + + PrintLog("CDVD multifile: MultiFileSeek(%llu)", sector); + +#endif /* VERBOSE_FUNCTION_MULTIFILE */ + + + + multinext = isofile->multinow; + + + + // Do we need to back up a file or so? + + while((multinext > isofile->multistart) && + + (sector < isofile->multisectorend[multinext - 1])) multinext--; + + + + // Do we need to go forward a file or two (that we know about?) + + while((multinext < isofile->multiend) && + + (sector >= isofile->multisectorend[multinext])) multinext++; + + + + // Do we need to go forward a file or two (that we *don't* know about?) + + while((multinext < 9) && + + (sector >= isofile->multisectorend[multinext])) { + + if(isofile->compress > 0) { + + CompressClose(isofile); + + } else { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Close a compressed file? (or an uncompressed one?) + + + + multinext++; + + + + isofile->name[isofile->multipos] = '0' + multinext; + + if(isofile->compress > 0) { + + retval = CompressOpenForRead(isofile); + + + + } else { + + isofile->handle = ActualFileOpenForRead(isofile->name); + + retval = 0; + + if(isofile->handle == ACTUALHANDLENULL) { + + retval = -1; + + + + } else { + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filesectorsize = isofile->filebytesize / isofile->blocksize; + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + } // ENDIF- Failed to open the file raw? + + } // ENDIF- Compressed or non-compressed? What a question. + + + + if(retval < 0) { + + if(isofile->compress > 0) { + + CompressClose(isofile); + + } else { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Close a compressed file? (or an uncompressed one?) + + + + multinext--; + + + + isofile->name[isofile->multipos] = '0' + multinext; + + if(isofile->compress > 0) { + + CompressOpenForRead(isofile); + + } else { + + isofile->handle = ActualFileOpenForRead(isofile->name); + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filesectorsize = isofile->filebytesize / isofile->blocksize; + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + } // ENDIF- Compressed or non-compressed? What a question. + + + + isofile->multinow = multinext; + + if(isofile->multinow == 0) { + + isofile->multioffset = 0; + + } else { + + isofile->multioffset = isofile->multisectorend[isofile->multinow - 1]; + + } // ENDIF- At the start of the list? Offset 0. + + return(-1); + + } // ENDIF- Failed to open next in series? Revert and abort. + + + + isofile->multinow = multinext; + + isofile->multiend = multinext; + + isofile->multioffset = isofile->multisectorend[multinext - 1]; + + isofile->multisectorend[multinext] = isofile->multisectorend[multinext - 1] + + + isofile->filesectorsize; + +#ifdef VERBOSE_DISC_INFO + + PrintLog("CDVD multifile: File %i opened, %llu sectors found (%llu sectors total)", + + multinext, + + isofile->filesectorsize, + + isofile->multisectorend[multinext]); + +#endif /* VERBOSE_DISC_INFO */ + + } // ENDWHILE- searching through new files for a high enough end-mark + + + + if(multinext != isofile->multinow) { + +#ifdef VERBOSE_WARNING_MULTIFILE + + PrintLog("CDVD multifile: Changing to File %i", multinext); + +#endif /* VERBOSE_WARNING_MULTIFILE */ + + if(isofile->compress > 0) { + + CompressClose(isofile); + + } else { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Close a compressed file? (or an uncompressed one?) + + + + isofile->name[isofile->multipos] = '0' + multinext; + + if(isofile->compress > 0) { + + CompressOpenForRead(isofile); + + } else { + + isofile->handle = ActualFileOpenForRead(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) return(-1); // Couldn't re-open? + + isofile->filebytesize = ActualFileSize(isofile->handle); + + isofile->filesectorsize = isofile->filebytesize / isofile->blocksize; + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + } // ENDIF- Compressed or non-compressed? What a question. + + + + isofile->multinow = multinext; + + if(multinext == 0) { + + isofile->multioffset = 0; + + } else { + + isofile->multioffset = isofile->multisectorend[multinext - 1]; + + } // ENDIF- At the start of the list? Offset 0. + + } // ENDIF- Not looking at the same file? Change to the new one. + + + + tempfilesector = sector - isofile->multioffset; + + if(isofile->compress > 0) { + + return(CompressSeek(isofile, tempfilesector)); + + } else { + + retval = ActualFileSeek(isofile->handle, + + (tempfilesector * isofile->blocksize) + + + isofile->imageheader); + + if(retval == 0) { + + isofile->filesectorpos = sector; + + isofile->filebytepos = (sector * isofile->blocksize) + + + isofile->imageheader; + + } // ENDIF- Sucessful? Adjust internals + + return(retval); + + } // ENDIF- Seek a position in a compressed file? + +} // END MultiFileSeek() + + + + + +int MultiFileRead(struct IsoFile *isofile, char *block) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_MULTIFILE + + PrintLog("CDVD multifile: MultiFileRead()"); + +#endif /* VERBOSE_FUNCTION_MULTIFILE */ + + + + if(isofile->filesectorpos >= isofile->filesectorsize) + + MultiFileSeek(isofile, isofile->sectorpos); + + + + if(isofile->compress > 0) { + + return(CompressRead(isofile, block)); + + } else { + + retval = ActualFileRead(isofile->handle, isofile->blocksize, block); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval == isofile->blocksize) isofile->filesectorpos++; + + return(retval); + + } // ENDIF- Read a compressed sector? + +} // END MultiFileRead() + + + + + +int MultiFileWrite(struct IsoFile *isofile, char *block) { + + int retval; + + + +#ifdef VERBOSE_FUNCTION_MULTIFILE + + PrintLog("CDVD multifile: MultiFileWrite()"); + +#endif /* VERBOSE_FUNCTION_MULTIFILE */ + + + + if(isofile->filebytesize + isofile->blocksize > FILESIZELIMIT) { + + if(isofile->compress > 0) { + + CompressClose(isofile); + + } else { + + ActualFileClose(isofile->handle); + + isofile->handle = ACTUALHANDLENULL; + + } // ENDIF- Close a compressed file? (or an uncompressed one?) + + if(isofile->multinow == 9) return(-1); // Over 10 files? Overflow! + + + + isofile->multioffset += isofile->filesectorsize; + + isofile->multinow++; + + isofile->multiend++; + +#ifdef VERBOSE_WARNING_MULTIFILE + + PrintLog("CDVD multifile: Changing to File %i", isofile->multinow); + +#endif /* VERBOSE_WARNING_MULTIFILE */ + + + + isofile->name[isofile->multipos] = '0' + isofile->multinow; + + if(isofile->compress > 0) { + + retval = CompressOpenForWrite(isofile); + + } else { + + isofile->handle = ActualFileOpenForWrite(isofile->name); + + if(isofile->handle == ACTUALHANDLENULL) { + + retval = -1; + + } else { + + retval = 0; + + isofile->filebytesize = 0; + + isofile->filesectorsize = 0; + + isofile->filebytepos = 0; + + isofile->filesectorpos = 0; + + } // ENDIF- Trouble opening next file? + + } // ENDIF- Opening the next compressed file? (Or uncompressed?) + + if(retval < 0) return(-1); // Couldn't open another file? Abort. + + } // ENDIF- Hit the size limit? Move on to next file... + + + + if(isofile->compress > 0) { + + return(CompressWrite(isofile, block)); + + } else { + + retval = ActualFileWrite(isofile->handle, isofile->blocksize, block); + + if(retval > 0) isofile->filebytepos += retval; + + if(retval == isofile->blocksize) isofile->filesectorpos++; + + return(retval); + + } // ENDIF- Write a compressed sector? + +} // END MultiFileWrite() + diff --git a/plugins/cdvd/CDVDisoEFP/src/multifile.h b/plugins/cdvd/CDVDisoEFP/src/multifile.h new file mode 100644 index 0000000..66b8177 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/multifile.h @@ -0,0 +1,106 @@ +/* multifile.h + + * Copyright (C) 2002-2005 PCSX2 Team + + * + + * This program is free software; you can redistribute it and/or modify + + * it under the terms of the GNU General Public License as published by + + * the Free Software Foundation; either version 2 of the License, or + + * (at your option) any later version. + + * + + * This program is distributed in the hope that it will be useful, + + * but WITHOUT ANY WARRANTY; without even the implied warranty of + + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + * GNU General Public License for more details. + + * + + * You should have received a copy of the GNU General Public License + + * along with this program; if not, write to the Free Software + + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * + + * PCSX2 members can be contacted through their website at www.pcsx2.net. + + */ + + + + + +#ifndef MULTIFILE_H + +#define MULTIFILE_H + + + + + +// #ifndef __LINUX__ + +// #ifdef __linux__ + +// #define __LINUX__ + +// #endif /* __linux__ */ + +// #endif /* No __LINUX__ */ + + + +// #define CDVDdefs + +// #include "PS2Edefs.h" + + + +#include "isofile.h" + + + + + +// #define VERBOSE_FUNCTION_MULTIFILE + +// #define VERBOSE_WARNING_MULTIFILE + + + + + +extern char *multinames[]; + + + + + +extern void IsoNameStripMulti(struct IsoFile *isofile); + + + +extern int MultiFileSeek(struct IsoFile *isofile, off64_t sector); + +extern int MultiFileRead(struct IsoFile *isofile, char *block); + + + +extern int MultiFileWrite(struct IsoFile *isofile, char *block); + + + + + +#endif /* MULTIFILE_H */ + diff --git a/plugins/cdvd/CDVDisoEFP/src/toc.c b/plugins/cdvd/CDVDisoEFP/src/toc.c new file mode 100644 index 0000000..7a87b87 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/toc.c @@ -0,0 +1,358 @@ +/* toc.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // off64_t + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" +#include "convert.h" +#include "isofile.h" +#include "actualfile.h" + +#include "toc.h" + + +// PCSX2's .toc file format: +// 1 unsigned char - CDVD_TYPE_???? +// 1 tocTN +// As many tocTDs as it takes. + + +extern void IsoInitTOC(struct IsoFile *isofile) { + int i; + off64_t sectorsize; + + if(isofile == NULL) return; + +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: IsoInitTOC()"); +#endif /* VERBOSE_FUNCTION_TOC */ + + if(isofile->multi > 0) { + sectorsize = isofile->multisectorend[isofile->multiend]; + } else { + sectorsize = isofile->filesectorsize; + } // ENDIF- Establish largest sector from multifile? (or single file?) + + for(i = 0; i < 2048; i++) isofile->toc[i] = 0; + switch(isofile->cdvdtype) { + case CDVD_TYPE_DVDV: + case CDVD_TYPE_PS2DVD: + if((isofile->filesectorsize > (2048*1024)) || + (isofile->multi > 0)) { + isofile->toc[0] = 0x24; // Dual-Sided DVD (?) + isofile->toc[4] = 0x41; + isofile->toc[5] = 0x95; + } else { + isofile->toc[0] = 0x04; // Single-Sided DVD (?) + isofile->toc[4] = 0x86; + isofile->toc[5] = 0x72; + } // ENDIF- Too many sectors for a single-layered disc? + + isofile->toc[1] = 0x02; + isofile->toc[2] = 0xF2; + isofile->toc[3] = 0x00; + + isofile->toc[16] = 0x00; + isofile->toc[17] = 0x03; + isofile->toc[18] = 0x00; + isofile->toc[19] = 0x00; + return; // DVD's don't have tracks. Might track multisession later... + break; + + case CDVD_TYPE_PS2CD: + case CDVD_TYPE_PSCD: + isofile->toc[0] = 0x41; + break; + case CDVD_TYPE_CDDA: + isofile->toc[0] = 0x01; + break; + default: + break; + } // ENDSWITCH isofile->cdvdtype - Which TOC for which type? + + // CD Details here... (tracks and stuff) + isofile->toc[2] = 0xA0; + isofile->toc[7] = 0x01; // Starting Track No. + isofile->toc[12] = 0xA1; + isofile->toc[17] = 0x01; // Ending Track No. + + isofile->toc[22] = 0xA2; + LBAtoMSF(sectorsize, &isofile->toc[27]); + isofile->toc[27] = HEXTOBCD(isofile->toc[27]); + isofile->toc[28] = HEXTOBCD(isofile->toc[28]); + isofile->toc[29] = HEXTOBCD(isofile->toc[29]); + + isofile->toc[40] = 0x02; // YellowBook? Data Mode? + isofile->toc[42] = 0x01; // Track No. + LBAtoMSF(0, &isofile->toc[47]); + isofile->toc[47] = HEXTOBCD(isofile->toc[47]); + isofile->toc[48] = HEXTOBCD(isofile->toc[48]); + isofile->toc[49] = HEXTOBCD(isofile->toc[49]); +} // END IsoInitTOC() + + +extern void IsoAddTNToTOC(struct IsoFile *isofile, struct tocTN toctn) { + if(isofile == NULL) return; + +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: IsoAddTNToTOC()"); +#endif /* VERBOSE_FUNCTION_TOC */ + + isofile->toc[7] = HEXTOBCD(toctn.strack); + isofile->toc[17] = HEXTOBCD(toctn.etrack); + return; +} // END IsoAddTNToTOC() + + +extern void IsoAddTDToTOC(struct IsoFile *isofile, + unsigned char track, + struct tocTD toctd) { + int temptrack; + int position; + +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: IsoAddTNToTOC(%u)", track); +#endif /* VERBOSE_FUNCTION_TOC */ + + if(isofile == NULL) return; + + temptrack = track; + if(temptrack == 0xAA) temptrack = 0; + if(temptrack > 99) return; // Only up to 99 tracks allowed. + + if(temptrack == 0) { + LBAtoMSF(toctd.lsn, &isofile->toc[27]); + isofile->toc[27] = HEXTOBCD(isofile->toc[27]); + isofile->toc[28] = HEXTOBCD(isofile->toc[28]); + isofile->toc[29] = HEXTOBCD(isofile->toc[29]); + + } else { + position = temptrack * 10; + position += 30; + isofile->toc[position] = toctd.type; + isofile->toc[position + 2] = HEXTOBCD(temptrack); + LBAtoMSF(toctd.lsn, &isofile->toc[position + 7]); + isofile->toc[position + 7] = HEXTOBCD(isofile->toc[position + 7]); + isofile->toc[position + 8] = HEXTOBCD(isofile->toc[position + 8]); + isofile->toc[position + 9] = HEXTOBCD(isofile->toc[position + 9]); + } // ENDIF- Is this a lead-out? (or an actual track?) +} // END IsoAddTDToTOC() + + +extern int IsoLoadTOC(struct IsoFile *isofile) { + char tocext[] = ".toc\0"; + char tocheader[5]; + ACTUALHANDLE tochandle; + char tocname[256]; + int i; + int j; + int retval; + unsigned char cdvdtype; + struct tocTN toctn; + struct tocTD toctd; + + if(isofile == NULL) return(-1); + + i = 0; + while((i < 256) && (isofile->name[i] != 0)) { + tocname[i] = isofile->name[i]; + i++; + } // ENDWHILE- Copying the data name to the toc name + j = 0; + while((i < 256) && (tocext[j] != 0)) { + tocname[i] = tocext[j]; + i++; + j++; + } // ENDWHILE- Append ".toc" to end of name + tocname[i] = 0; // And 0-terminate + + tochandle = ActualFileOpenForRead(tocname); + if(tochandle == ACTUALHANDLENULL) return(-1); + + retval = ActualFileRead(tochandle, 4, tocheader); + if(retval < 4) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Trouble reading the 'toc' file? + + if((tocheader[0] != 'T') || + (tocheader[1] != 'O') || + (tocheader[2] != 'C') || + (tocheader[3] != '1')) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Not a 'toc' file after all? + +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: IsoLoadTOC(%s)", tocname); +#endif /* VERBOSE_FUNCTION_TOC */ + + retval = ActualFileRead(tochandle, 1, (char *) &cdvdtype); + if(retval < 1) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Trouble reading the 'toc' file? + + isofile->cdvdtype = cdvdtype; + IsoInitTOC(isofile); + + if((cdvdtype != CDVD_TYPE_PS2DVD) && (cdvdtype != CDVD_TYPE_DVDV)) { + retval = ActualFileRead(tochandle, sizeof(struct tocTN), (char *) &toctn); + if(retval < sizeof(struct tocTN)) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Trouble reading the 'toc' file? + + if((toctn.strack > 99) || (toctn.etrack > 99)) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Track numbers out of range? +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: Start Track %u End Track %u", + toctn.strack, toctn.etrack); +#endif /* VERBOSE_FUNCTION_TOC */ + IsoAddTNToTOC(isofile, toctn); + + retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) &toctd); + if(retval < sizeof(struct tocTD)) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Trouble reading the 'toc' file? + + if(toctd.type != 0) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Track numbers out of range? +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: Total Sectors: %lu", toctd.lsn); +#endif /* VERBOSE_FUNCTION_TOC */ + IsoAddTDToTOC(isofile, 0xAA, toctd); + + for(i = toctn.strack; i <= toctn.etrack; i++) { + + retval = ActualFileRead(tochandle, sizeof(struct tocTD), (char *) &toctd); + if(retval < sizeof(struct tocTD)) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Trouble reading the 'toc' file? +#ifdef VERBOSE_FUNCTION_TOC + PrintLog("CDVDiso TOC: Track %u Type %u Sector Start: %lu", + i, toctd.type, toctd.lsn); +#endif /* VERBOSE_FUNCTION_TOC */ + IsoAddTDToTOC(isofile, i, toctd); + } // NEXT i- read in each track + } // ENDIF- Not a DVD? (Then read in CD track data) + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + + return(0); +} // END IsoLoadTOC() + + +extern int IsoSaveTOC(struct IsoFile *isofile) { + char tocext[] = ".toc\0"; + char tocheader[] = "TOC1\0"; + ACTUALHANDLE tochandle; + char tocname[256]; + int i; + int j; + int retval; + unsigned char cdvdtype; + struct tocTN toctn; + struct tocTD toctd; + char temptime[3]; + + if(isofile == NULL) return(-1); + + i = 0; + while((i < 256) && (isofile->name[i] != 0)) { + tocname[i] = isofile->name[i]; + i++; + } // ENDWHILE- Copying the data name to the toc name + j = 0; + while((i < 256) && (tocext[j] != 0)) { + tocname[i] = tocext[j]; + i++; + j++; + } // ENDWHILE- Append ".toc" to end of name + tocname[i] = 0; // And 0-terminate + + ActualFileDelete(tocname); + tochandle = ActualFileOpenForWrite(tocname); + if(tochandle == ACTUALHANDLENULL) return(-1); + + retval = ActualFileWrite(tochandle, 4, tocheader); + if(retval < 4) { + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + ActualFileDelete(tocname); + return(-1); + } // ENDIF- Trouble writing to the 'toc' file? + + cdvdtype = isofile->cdvdtype; + ActualFileWrite(tochandle, 1, (char *) &cdvdtype); + + if((cdvdtype != CDVD_TYPE_PS2DVD) && (cdvdtype != CDVD_TYPE_DVDV)) { + toctn.strack = BCDTOHEX(isofile->toc[7]); + toctn.etrack = BCDTOHEX(isofile->toc[17]); + ActualFileWrite(tochandle, sizeof(struct tocTN), (char *) &toctn); + + // Leadout Data + toctd.type = 0; + temptime[0] = BCDTOHEX(isofile->toc[27]); + temptime[1] = BCDTOHEX(isofile->toc[28]); + temptime[2] = BCDTOHEX(isofile->toc[29]); + toctd.lsn = MSFtoLBA(temptime); + ActualFileWrite(tochandle, sizeof(struct tocTD), (char *) &toctd); + + for(i = toctn.strack; i <= toctn.etrack; i++) { + j = i * 10 + 30; + toctd.type = isofile->toc[j]; + temptime[0] = BCDTOHEX(isofile->toc[j + 7]); + temptime[1] = BCDTOHEX(isofile->toc[j + 8]); + temptime[2] = BCDTOHEX(isofile->toc[j + 9]); + toctd.lsn = MSFtoLBA(temptime); + ActualFileWrite(tochandle, sizeof(struct tocTD), (char *) &toctd); + } // NEXT i- write out each track + } // ENDIF- Not a DVD? (Then output CD track data) + ActualFileClose(tochandle); + tochandle = ACTUALHANDLENULL; + + return(0); +} // END IsoSaveTOC() diff --git a/plugins/cdvd/CDVDisoEFP/src/toc.h b/plugins/cdvd/CDVDisoEFP/src/toc.h new file mode 100644 index 0000000..26dc7e4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/toc.h @@ -0,0 +1,84 @@ +/* toc.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef TOC_H +#define TOC_H + + +// #ifndef __LINUX__ +// #ifdef __linux__ +// #define __LINUX__ +// #endif /* __linux__ */ +// #endif /* No __LINUX__ */ + +// #define CDVDdefs +// #include "PS2Edefs.h" + +#include "isofile.h" + + +// #define VERBOSE_FUNCTION_TOC + + +#ifdef _WIN32 +#pragma pack(1) +#endif /* _WIN32 */ + +struct tocTD { + unsigned long lsn; + unsigned char type; +#ifdef _WIN32 +}; +#else +} __attribute__ ((packed)); +#endif /* _WIN32 */ + +struct tocTN { + unsigned char strack; + unsigned char etrack; +#ifdef _WIN32 +}; +#else +} __attribute__ ((packed)); +#endif /* _WIN32 */ + +#ifdef _WIN32 +#pragma pack() +#endif /* _WIN32 */ + + +// PCSX2's .toc file format: +// 1 unsigned char - CDVD_TYPE_???? +// 1 tocTN +// As many tocTDs as it takes. + + +extern void IsoInitTOC(struct IsoFile *isofile); +extern void IsoAddTNToTOC(struct IsoFile *isofile, struct tocTN toctn); +extern void IsoAddTDToTOC(struct IsoFile *isofile, + unsigned char track, + struct tocTD toctd); + +extern int IsoLoadTOC(struct IsoFile *isofile); +extern int IsoSaveTOC(struct IsoFile *isofile); + + +#endif /* TOC_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/version.c b/plugins/cdvd/CDVDisoEFP/src/version.c new file mode 100644 index 0000000..f8d053f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/version.c @@ -0,0 +1,36 @@ +/* version.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +char *libname = "EFP Iso CDVD Driver"; + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 0; +const unsigned char build = 6; diff --git a/plugins/cdvd/CDVDisoEFP/src/version.h b/plugins/cdvd/CDVDisoEFP/src/version.h new file mode 100644 index 0000000..774ce3b --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/version.h @@ -0,0 +1,43 @@ +/* version.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef VERSION_H +#define VERSION_H + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern char *libname; + +extern const unsigned char version; +extern const unsigned char revision; +extern const unsigned char build; + + +#endif /* VERSION_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/ChangeLog b/plugins/cdvd/CDVDisoEFP/src/zlib/ChangeLog new file mode 100644 index 0000000..9e5e28e --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/ChangeLog @@ -0,0 +1,722 @@ + + ChangeLog file for zlib + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Lvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id: ChangeLog,v 1.1 2005/07/12 22:08:51 petersoneugene Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/README b/plugins/cdvd/CDVDisoEFP/src/zlib/README new file mode 100644 index 0000000..266edd4 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/README @@ -0,0 +1,126 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.1 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). These documents are also available in other +formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file example.c which also tests that the library +is working correctly. Another example is given in the file minigzip.c. The +compression library itself is composed of all source files except example.c and +minigzip.c. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile. In short "make test; make install" should work for most +machines. For Unix: "./configure; make test; make install" For MSDOS, use one +of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or +descrip.mms. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, +please check this site to verify that you have the latest version of zlib; +otherwise get the latest version and check whether the problem still exists or +not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking +for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.2.1 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess is in the +CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries is +availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + +- When building a shared, i.e. dynamic library on Mac OS X, the library must be + installed before testing (do "make install" before "make test"), since the + library location is specified in the library. + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. Please +read the FAQ for more information on the distribution of modified source +versions. diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/adler32.c b/plugins/cdvd/CDVDisoEFP/src/zlib/adler32.c new file mode 100644 index 0000000..bc0842f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/compress.c b/plugins/cdvd/CDVDisoEFP/src/zlib/compress.c new file mode 100644 index 0000000..e7ea2c5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.c b/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.c new file mode 100644 index 0000000..aa8b984 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.h b/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.c b/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.c new file mode 100644 index 0000000..efe7b63 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.h b/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.h new file mode 100644 index 0000000..26775e9 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/gzio.c b/plugins/cdvd/CDVDisoEFP/src/zlib/gzio.c new file mode 100644 index 0000000..4cfd64f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/infback.c b/plugins/cdvd/CDVDisoEFP/src/zlib/infback.c new file mode 100644 index 0000000..5cf5d22 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.c b/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.c new file mode 100644 index 0000000..63aa440 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.h b/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inffixed.h b/plugins/cdvd/CDVDisoEFP/src/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.c b/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.c new file mode 100644 index 0000000..71fe3cc --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.h b/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.h new file mode 100644 index 0000000..b696512 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.c b/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.c new file mode 100644 index 0000000..55fd27b --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.h b/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.h new file mode 100644 index 0000000..1dbfe53 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/trees.c b/plugins/cdvd/CDVDisoEFP/src/zlib/trees.c new file mode 100644 index 0000000..d0bce9f --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/trees.h b/plugins/cdvd/CDVDisoEFP/src/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/uncompr.c b/plugins/cdvd/CDVDisoEFP/src/zlib/uncompr.c new file mode 100644 index 0000000..82ebef7 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/zconf.h b/plugins/cdvd/CDVDisoEFP/src/zlib/zconf.h new file mode 100644 index 0000000..f4cfc21 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(_WIN32)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h b/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h new file mode 100644 index 0000000..d54ac94 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h.bak b/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h.bak new file mode 100644 index 0000000..530c64c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/zlib.h.bak @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.c b/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.c new file mode 100644 index 0000000..db137f8 --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.h b/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.h new file mode 100644 index 0000000..e300f7c --- /dev/null +++ b/plugins/cdvd/CDVDisoEFP/src/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/cdvd/CDVDlinuz/ChangeLog.txt b/plugins/cdvd/CDVDlinuz/ChangeLog.txt new file mode 100644 index 0000000..dd0b7eb --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/ChangeLog.txt @@ -0,0 +1,43 @@ +Changes: +------- + CDVDlinuz v0.4 (efp): + * Moved all "threaded" code to CDVDEFP (actual directory) (efp) + * Copied mid-level (not low-level) device drivers from CDVDisoEFP (efp) + * In Windows, when newly selected from the PCSX2 configure screen, CDVDinit() + (as well as InitConf()) are not called. Fixed. (efp) + + CDVDEFP v0.3 (efp): + * Protection against "Interrupted system call" errors enhanced (threading) + * Simplified ReadLoop completion detection code (threading) + * Separated buffer.c from device.c for cross-CDVD portability. + + CDVDEFP v0.2 (efp): + * Separated out device command calls (for easier maintainability) + * Added a read cache (currently sized at 512kb) + * Added threading code (pthreads, because it's portable) + * With threading comes tray polling (currently at 1/sec) + * With threading comes a read-ahead function (currently set to 64kb) + + CDVDEFP v0.1 (efp): + * Updated to 0.6.0 (beta) specs + * Removed Glade influence in Configure/About interfaces + * Added O_NONBLOCK so disc is not required to be in drive when Pcsx2 starts + discs can now be switched out at will. + * Separated CD and DVD access calls for better maintainability + * Removed 2GB byte limitation to DVD sector calls + * Collected all info on disc when disc is first inserted + * Expanded disc type detection to meet 0.6.0 specs. + CD/DVD detection. PS1/PS2/CDDA/other detection. + * Multilevel Debug info added (currently controlled by #defines) + + CDVDlinuz v0.3 (linuzappz): + * Updated to 0.4.3 specs + + CDVDlinuz v0.2 (linuzappz): + * Updated to 0.2.9 specs + + CDVDlinuz v0.1 (linuzappz): + * First Release + * Tested with Pcsx2 + + Email: diff --git a/plugins/cdvd/CDVDlinuz/License.txt b/plugins/cdvd/CDVDlinuz/License.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/CD.c b/plugins/cdvd/CDVDlinuz/Src/Linux/CD.c new file mode 100644 index 0000000..ab5796c --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/CD.c @@ -0,0 +1,367 @@ +/* CD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // strerror() +#include // open() +#include // ioctl() +#include // open() +#include // lseek(), open() +#include // close(), lseek(), (sleep()) + +#include // CD/DVD based ioctl() and defines. + +#include "../convert.h" +#include "logfile.h" +#include "device.h" +#include "CD.h" + + +// Constants +u8 *playstationcdname = "PLAYSTATION\0"; +u8 *ps1name = "CD-XA001\0"; + +// CD-ROM temp storage structures (see linux/cdrom.h for details) +struct cdrom_tochdr cdheader; +struct cdrom_tocentry cdtrack; +struct cdrom_subchnl subchannel; +u8 cdtempbuffer[2352]; + +int cdmode; // mode of last CDVDreadTrack call (important for CDs) + + +// Internal Functions + +void InitCDSectorInfo() { + cdmode = -1; +} // END InitSectorInfo(); + + +// Function Calls from CDVD.c + +void InitCDInfo() { + InitCDSectorInfo(); +} // END InitDiscType() + +s32 CDreadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDreadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + s32result = 0; + + if(buffer == NULL) return(-1); + + // The CD way of figuring out where to read. + LBAtoMSF(lsn, buffer); + + switch(mode) { + case CDVD_MODE_2048: + case CDVD_MODE_2328: + case CDVD_MODE_2340: + case CDVD_MODE_2352: + errno = 4; // Interrupted system call... (simulated the first time) + while(errno == 4) { + errno = 0; + s32result = ioctl(devicehandle, CDROMREADRAW, buffer); + } // ENDWHILE- Continually being interrupted by the system... + break; + case CDVD_MODE_2368: // Unimplemented... as yet. + default: +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Unknown Mode %i", mode); +#endif /* VERBOSE_WARNINGS */ + return(-1); // Illegal Read Mode? Abort + break; + } // ENDSWITCH- Which read mode should we choose? + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading CD: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitCDSectorInfo(); + return(-1); + } // ENDIF- Trouble getting a track count? + + cdmode = mode; // Save mode for buffer positioning later. + return(0); // Call accomplished +} // END CDreadTrack() + +s32 CDgetBufferOffset() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetBufferOffset()"); +#endif /* VERBOSE_FUNCTION */ + + switch(cdmode) { + case CDVD_MODE_2048: + return(0+24); + case CDVD_MODE_2328: + return(0+24); + case CDVD_MODE_2340: + return(0+12); + case CDVD_MODE_2352: + return(0+0); + case CDVD_MODE_2368: // Unimplemented... as yet. + default: +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Unknown Mode %i", cdmode); +#endif /* VERBOSE_WARNINGS */ + return(0); // Not to worry. for now. + } // ENDSWITCH- where should we put the buffer pointer? +} // END CDgetBuffer() + +// I, personally, don't see the big deal with SubQ +// However, sooner or later I'll incorporate it into the Cache Buffer system +// (backward compatibility, and all that) +s32 CDreadSubQ(u32 lsn, cdvdSubQ *subq) { + int tempmode; + s32 s32result; + + s32result = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDreadSubQ()"); +#endif /* VERBOSE_FUNCTION */ + + tempmode = cdmode; + if(tempmode == -1) tempmode = CDVD_MODE_2352; + CDreadTrack(lsn, tempmode, cdtempbuffer); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error prepping CD SubQ: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(s32result); + } // ENDIF- Trouble? + + subchannel.cdsc_format = CDROM_MSF; + s32result = ioctl(devicehandle, CDROMSUBCHNL, &subchannel); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading CD SubQ: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(s32result); + } // ENDIF- Trouble? + + if(subq != NULL) { + subq->mode = subchannel.cdsc_adr; + subq->ctrl = subchannel.cdsc_ctrl; + subq->trackNum = subchannel.cdsc_trk; + subq->trackIndex = subchannel.cdsc_ind; + subq->trackM = subchannel.cdsc_reladdr.msf.minute; + subq->trackS = subchannel.cdsc_reladdr.msf.second; + subq->trackF = subchannel.cdsc_reladdr.msf.frame; + subq->discM = subchannel.cdsc_absaddr.msf.minute; + subq->discS = subchannel.cdsc_absaddr.msf.second; + subq->discF = subchannel.cdsc_absaddr.msf.frame; + } // ENDIF- Did the caller want all this data? + + return(0); +} // END CDVDreadSubQ() + +s32 CDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetTN()"); +#endif /* VERBOSE_FUNCTION */ + + if(cdvdtn != NULL) { + cdvdtn->strack = cdheader.cdth_trk0; + cdvdtn->etrack = cdheader.cdth_trk1; + } // ENDIF- programmer actually WANTS this info? + + return(0); // Call accomplished +} // END CDVDgetTN() + +s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd) { + u8 j; + u16 k; + char temptime[3]; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetTD()"); +#endif /* VERBOSE_FUNCTION */ + + j = newtrack; + if(j == CDROM_LEADOUT) j = 0; + + if(j == 0) { + k = 27; + } else { + k = j * 10 + 37; + } // ENDIF- Where to start hunting for this number? + + if(cdvdtd != NULL) { + cdvdtd->type = tocbuffer[j*10 + 30]; + + temptime[0] = BCDTOHEX(tocbuffer[k]); + temptime[1] = BCDTOHEX(tocbuffer[k + 1]); + temptime[2] = BCDTOHEX(tocbuffer[k + 2]); + cdvdtd->lsn = MSFtoLBA(temptime); + } // ENDIF- Does the caller REALLY want this data? + + return(0); // Call accomplished +} // END CDVDgetTD() + +s32 CALLBACK CDgetDiskType(s32 ioctldisktype) { + s32 offset; + s32 s32result; + int i; + u8 j; + int tempdisctype; + + offset = 0; + errno = 0; + i = 0; + j = 0; + tempdisctype = CDVD_TYPE_UNKNOWN; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDgetDiskType()"); +#endif /* VERBOSE_FUNCTION */ + + s32result = CDreadTrack(16, CDVD_MODE_2352, cdtempbuffer); + if((s32result != 0) || (errno != 0)) { + return(-1); + } // ENDIF- Cannot read the CD's ISO9660 volume sector? Abort + disctype = CDVD_TYPE_DETCTCD; + + switch(ioctldisktype) { + case CDS_AUDIO: +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected CDDA Audio disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_CDDA; + tocbuffer[0] = 0x01; + break; + + case CDS_DATA_1: + case CDS_MIXED: +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tocbuffer[0] = 0x41; + + CDreadTrack(16, CDVD_MODE_2048, cdtempbuffer); + offset = CDgetBufferOffset(); + i = 0; + while((*(playstationcdname + i) != 0) && + (*(playstationcdname + i) == cdtempbuffer[offset + 8 + i])) i++; + if(*(playstationcdname + i) == 0) { + i = 0; + while((*(ps1name + i) != 0) && + (*(ps1name + i) == cdtempbuffer[offset + 1024 + i])) i++; + if(*(ps1name + i) == 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PSCD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation 2 CD disc."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2CD; + } // ENDIF- Did we find the CD ident? (For Playstation 1 CDs) + } else { + tempdisctype = CDVD_TYPE_UNKNOWN; + } // ENDIF- Did we find the Playstation name? + break; + + default: + return(-1); + } // ENDSWITCH- What has ioctl disc type come up with? + + // Collect TN data + cdheader.cdth_trk0 = 0; + cdheader.cdth_trk1 = 0; + + s32result = ioctl(devicehandle, CDROMREADTOCHDR, &cdheader); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TN: (%i) %i:%s", + s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + cdheader.cdth_trk0 = 1; + cdheader.cdth_trk1 = 1; + } // ENDIF- Failed to read in track count? Assume 1 track. +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Track Number Range: %i-%i", + cdheader.cdth_trk0, cdheader.cdth_trk1); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[2] = 0xA0; + tocbuffer[7] = HEXTOBCD(cdheader.cdth_trk0); + tocbuffer[12] = 0xA1; + tocbuffer[17] = HEXTOBCD(cdheader.cdth_trk1); + + // Collect disc TD data + cdtrack.cdte_track = CDROM_LEADOUT; + cdtrack.cdte_format = CDROM_LBA; + s32result = ioctl(devicehandle, CDROMREADTOCENTRY, &cdtrack); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TD for disc: (%i) %i:%s", + s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Trouble getting a track count? + + LBAtoMSF(cdtrack.cdte_addr.lba, &tocbuffer[27]); +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Total Time: %i:%i", + tocbuffer[27], tocbuffer[28]); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[27] = HEXTOBCD(tocbuffer[27]); + tocbuffer[28] = HEXTOBCD(tocbuffer[28]); + tocbuffer[29] = HEXTOBCD(tocbuffer[29]); + + // Collect track TD data + for(j = cdheader.cdth_trk0; j <= cdheader.cdth_trk1; j++) { + cdtrack.cdte_track = j; // j-1? + cdtrack.cdte_format = CDROM_LBA; + s32result = ioctl(devicehandle, CDROMREADTOCENTRY, &cdtrack); + if((s32result == -1) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error reading TD for track %i: (%i) %i:%s", + j, s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + // No more here... + + } else { + LBAtoMSF(cdtrack.cdte_addr.lba, &tocbuffer[j*10 + 37]); +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Track %i: Data Mode %i Disc Start Time:%i:%i.%i\n", + j, + cdtrack.cdte_datamode, + tocbuffer[j*10+37], + tocbuffer[j*10+38], + tocbuffer[j*10+39]); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[j*10 + 30] = cdtrack.cdte_datamode; + tocbuffer[j*10 + 32] = HEXTOBCD(j); + tocbuffer[j*10 + 37] = HEXTOBCD(tocbuffer[j*10 + 37]); + tocbuffer[j*10 + 38] = HEXTOBCD(tocbuffer[j*10 + 38]); + tocbuffer[j*10 + 39] = HEXTOBCD(tocbuffer[j*10 + 39]); + } // ENDIF- Trouble getting a track count? + } // NEXT j- Reading each track's info in turn + + errno = 0; + disctype = tempdisctype; // Trigger the fact we have the info (finally) + return(disctype); +} // END CDVDgetDiskType() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/CD.h b/plugins/cdvd/CDVDlinuz/Src/Linux/CD.h new file mode 100644 index 0000000..2546cba --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/CD.h @@ -0,0 +1,46 @@ +/* CD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __CD_H__ +#define __CD_H__ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "../PS2Edefs.h" + + +// Exported Functions + +extern void InitCDInfo(); +extern s32 CDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 CDgetBufferOffset(); +extern s32 CDreadSubQ(u32 lsn, cdvdSubQ *subq); +extern s32 CDgetTN(cdvdTN *cdvdtn); +extern s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 CDgetDiskType(s32 ioctldisktype); + + +#endif /* __CD_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.c b/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.c new file mode 100644 index 0000000..7ff0daa --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.c @@ -0,0 +1,368 @@ +/* CDVDlinuz.c + * Copyright (C) 2002-2005 CDVDlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include // errno +#include // open() +#include // NULL +#include // printf() +#include // getenv(), system() +#include // strerror(), sprintf() +#include // ioctl() +#include // stat() +#include // stat() +#include // time_t, time(), struct timeval +#include // stat() + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" +// #include "PS2Etypes.h" + +#include "CDVDlinuz.h" + +#include "buffer.h" +#include "conf.h" +#include "logfile.h" +#include "CD.h" // InitCDInfo() +#include "DVD.h" // InitDVDInfo() +#include "device.h" + +#include "../version.h" + + +// Globals + +time_t lasttime; + + +// Interface Functions + +u32 CALLBACK PS2EgetLibType() { + return(PS2E_LT_CDVD); // Library Type CDVD +} // END PS2EgetLibType() + + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return((version<<16)|(revision<<8)|build); +} // END PS2EgetLibVersion2() + + +char* CALLBACK PS2EgetLibName() { + return(libname); +} // END PS2EgetLibName() + + +s32 CALLBACK CDVDinit() { + errno = 0; + + InitLog(); + if(OpenLog() != 0) return(-1); + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDinit()"); +#endif /* VERBOSE_FUNCTION */ + + InitConf(); + + devicehandle = -1; + devicecapability = 0; + lasttime = time(NULL); + + // Initialize DVD.c and CD.c as well + InitDisc(); + InitDVDInfo(); + InitCDInfo(); + + return(0); +} // END CDVDinit() + + +void CALLBACK CDVDshutdown() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDshutdown()"); +#endif /* VERBOSE_FUNCTION */ + + DeviceClose(); + CloseLog(); +} // END CDVDshutdown() + + +s32 CALLBACK CDVDopen(const char* pTitleFilename) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDopen()"); +#endif /* VERBOSE_FUNCTION */ + + InitBuffer(); + + LoadConf(); + + errno = 0; + s32result = DeviceOpen(); + if(s32result != 0) return(s32result); + if(errno != 0) return(-1); + + return(0); +} // END CDVDopen(); + + +void CALLBACK CDVDclose() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDclose()"); +#endif /* VERBOSE_FUNCTION */ + + DeviceClose(); +} // END CDVDclose() + + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDreadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + s32result = 0; + errno = 0; + + if(DiscInserted() == -1) return(-1); + + if(userbuffer < BUFFERMAX) { + if((bufferlist[userbuffer].lsn == lsn) && + (bufferlist[userbuffer].mode == mode)) { + return(0); + } // ENDIF- And it's the right one? + } // ENDIF- Are we already pointing at the buffer? + + userbuffer = FindListBuffer(lsn); + if(userbuffer < BUFFERMAX) { + if((bufferlist[userbuffer].lsn == lsn) && + (bufferlist[userbuffer].mode == mode)) { + return(0); + } // ENDIF- And it was the right one? + } // ENDIF- Was a buffer found in the cache? + + replacebuffer++; + if(replacebuffer >= BUFFERMAX) replacebuffer = 0; + userbuffer = replacebuffer; + + if(bufferlist[replacebuffer].upsort != 0xffff) { + RemoveListBuffer(replacebuffer); + } // ENDIF- Reference already in place? Remove it. + + s32result = DeviceReadTrack(lsn, mode, bufferlist[replacebuffer].buffer); + bufferlist[replacebuffer].lsn = lsn; + bufferlist[replacebuffer].mode = mode; + bufferlist[replacebuffer].offset = DeviceBufferOffset(); + + if((s32result != 0) || (errno != 0)) { + bufferlist[replacebuffer].mode = -1; // Error! flag buffer as such. + } else { + if((disctype != CDVD_TYPE_PS2DVD) && (disctype != CDVD_TYPE_DVDV)) { + if(mode == CDVD_MODE_2352) { + CDreadSubQ(lsn, &bufferlist[replacebuffer].subq); + errno = 0; + } // ENDIF- Read subq as well? + } // ENDIF- Read a DVD buffer or a CD buffer? + } // ENDIF-Read ok? Fill out rest of buffer info. + AddListBuffer(replacebuffer); + return(s32result); +} // END CDVDreadTrack() + + +u8* CALLBACK CDVDgetBuffer() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDgetBuffer()"); +#endif /* VERBOSE_FUNCTION */ + + if(DiscInserted() == -1) return(NULL); + + if(userbuffer == 0xffff) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD interface: Not pointing to a buffer!"); +#endif /* VERBOSE_WARNINGS */ + return(NULL); // No buffer reference? + } // ENDIF- user buffer not pointing at anything? Abort + + if(bufferlist[userbuffer].mode < 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD interface: Error in buffer!"); +#endif /* VERBOSE_WARNINGS */ + return(NULL); // Bad Sector? + } // ENDIF- Trouble reading physical sector? Tell them. + + return(bufferlist[userbuffer].buffer + bufferlist[userbuffer].offset); +} // END CDVDgetBuffer() + + +// Note: without the lsn, I could pull the SubQ data directly from +// the stored buffer (in buffer.h). Oh, well. +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ *subq) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDreadSubQ(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + if(DiscInserted() == -1) return(-1); + + // DVDs don't have SubQ data + if(disctype == CDVD_TYPE_PS2DVD) return(-1); + if(disctype == CDVD_TYPE_DVDV) return(-1); + + return(CDreadSubQ(lsn, subq)); +} // END CDVDreadSubQ() + + +s32 CALLBACK CDVDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION */ + + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTN(cdvdtn)); + } else { + return(CDgetTN(cdvdtn)); + } // ENDIF- Are we looking at a DVD? +} // END CDVDgetTN() + + +s32 CALLBACK CDVDgetTD(u8 newtrack, cdvdTD *cdvdtd) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION */ + + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTD(newtrack, cdvdtd)); + } else { + return(CDgetTD(newtrack, cdvdtd)); + } // ENDIF- Are we looking at a DVD? +} // END CDVDgetTD() + + +s32 CALLBACK CDVDgetTOC(void *toc) { + // A structure to fill in, or at least some documentation on what + // the PS2 expects from this call would be more helpful than a + // "void *". + + union { + void *voidptr; + u8 *u8ptr; + } tocptr; + s32 i; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDgetTOC()"); +#endif /* VERBOSE_FUNCTION */ + + if(toc == NULL) return(-1); + if(DiscInserted() == -1) return(-1); + + tocptr.voidptr = toc; + for(i = 0; i < 1024; i++) *(tocptr.u8ptr + i) = tocbuffer[i]; + tocptr.voidptr = NULL; + + return(0); +} // END CDVDgetTOC() + + +s32 CALLBACK CDVDgetDiskType() { +#ifdef VERBOSE_FUNCTION + // Called way too often in boot part of bios to be left in. + // PrintLog("CDVD interface: CDVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION */ + + if(lasttime != time(NULL)) { + lasttime = time(NULL); + DeviceTrayStatus(); + } // ENDIF- Has enough time passed between calls? + + return(disctype); +} // END CDVDgetDiskType() + + +s32 CALLBACK CDVDgetTrayStatus() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDgetTrayStatus()"); +#endif /* VERBOSE_FUNCTION */ + + if(lasttime != time(NULL)) { + lasttime = time(NULL); + DeviceTrayStatus(); + } // ENDIF- Has enough time passed between calls? + + return(traystatus); +} // END CDVDgetTrayStatus() + + +s32 CALLBACK CDVDctrlTrayOpen() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDctrlTrayOpen()"); +#endif /* VERBOSE_FUNCTION */ + + return(DeviceTrayOpen()); +} // END CDVDctrlTrayOpen() + + +s32 CALLBACK CDVDctrlTrayClose() { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD interface: CDVDctrlTrayClose()"); +#endif /* VERBOSE_FUNCTION */ + + return(DeviceTrayClose()); +} // END CDVDctrlTrayClose() + + +void CALLBACK CDVDconfigure() { + ExecCfg("configure"); +} // END CDVDconfigure() + + +void CALLBACK CDVDabout() { + ExecCfg("about"); +} // END CDVDabout() + + +s32 CALLBACK CDVDtest() { + s32 s32result; + + errno = 0; + + if(devicehandle != -1) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD interface: Device already open"); +#endif /* VERBOSE_WARNINGS */ + return(0); + } // ENDIF- Is the CD/DVD already in use? That's fine. + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDVDtest()"); +#endif /* VERBOSE_FUNCTION */ + + s32result = DeviceOpen(); + DeviceClose(); + return(s32result); +} // END CDVDtest() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.h b/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.h new file mode 100644 index 0000000..69a4add --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/CDVDlinuz.h @@ -0,0 +1,31 @@ +/* CDVDlinuz.h + * Copyright (C) 2002-2005 CDVDlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __CDVDLINUZ_H__ +#define __CDVDLINUZ_H__ + + +// #define VERBOSE_WARNINGS +// #define VERBOSE_FUNCTION +#define VERBOSE_DISC_INFO +#define VERBOSE_DISC_TYPE + +#define READ_AHEAD_BUFFERS 32 + + +#endif /* __CDVDLINUZ_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.c b/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.c new file mode 100644 index 0000000..d76fd2d --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.c @@ -0,0 +1,584 @@ +/* DVD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // strerror(), memset(), memcpy() +#include // open() +#include // ioctl() +#include // open() +#include // lseek(), open() +#include // close(), lseek(), (sleep()) + +#include // CD/DVD based ioctl() and defines. + +#include "logfile.h" +#include "device.h" +#include "DVD.h" + +#include "../PS2Etypes.h" // u8, u32 + + +// Constants +u8 *playstationname = "PLAYSTATION\0"; + +// DVD storage structures (see linux/cdrom.h for details) +dvd_struct dvdphysical; +dvd_struct dvdcopyright[DVD_LAYERS]; +dvd_struct dvdbca; +dvd_struct dvdmanufact[DVD_LAYERS]; + +u32 dvdlastlsn; +u8 dvdtempbuffer[2064]; + + +// Internal Functions + +void InitDVDSectorInfo() { + dvdlastlsn = 0xffffffff; +} // END InitSectorInfo(); + +void HexDump(u8 *strptr, u8 count) { + int i; + u8 ch[2]; + char hexline[81]; + int hexlinepos; + + ch[1] = 0; + + if(count == 0) count = 16; + if((count < 1) || (count > 16)) return; + + hexlinepos = 0; + hexlinepos += sprintf(&hexline[hexlinepos], "CDVD driver: "); + + for(i = 0; i < count; i++) { + hexlinepos += sprintf(&hexline[hexlinepos], "%.2x ", (*(strptr + i)) * 1); + } // NEXT i- printing each new Hex number + + for(i = 0; i < count; i++) { + if((*(strptr + i) < 32) || (*(strptr + i) > 127)) { + hexlinepos += sprintf(&hexline[hexlinepos], "."); + } else { + ch[0] = *(strptr + i); + hexlinepos += sprintf(&hexline[hexlinepos], "%s", ch); + } // ENDIF- Is this an unprintable character? + } // NEXT i- printing each new character + PrintLog(hexline); +} // ENDIF HexDump() + + +//// DVD Structure Functions + +s32 DVDreadPhysical() { + s32 s32result; + u8 i; + + errno = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadPhysical()\n"); +#endif /* VERBOSE_FUNCTION */ + + memset(&dvdphysical, 0, sizeof(dvd_struct)); + dvdphysical.type = DVD_STRUCT_PHYSICAL; + + i = DVD_LAYERS; + while(i > 0) { + i--; + dvdphysical.physical.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdphysical); + } // ENDWHILE- reading in all physical layers... + + if((s32result == -1) || (errno != 0)) { + dvdphysical.type = 0xFF; +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Physical structure: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with reading Layer 0 of the physical data? Abort + + i = 3; + while((i > 0) && (dvdphysical.physical.layer[i].end_sector == 0)) i--; + dvdphysical.physical.layer_num = i; + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Physical Characteristics"); + PrintLog("CDVD driver: Number of Layers: %i", + (s32) dvdphysical.physical.layer_num + 1); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + PrintLog("CDVD driver: Layer Number %i", i); + switch(dvdphysical.physical.layer[i].book_type) { + case 0: + PrintLog("CDVD driver: Book Type: DVD-ROM"); + break; + case 1: + PrintLog("CDVD driver: Book Type: DVD-RAM"); + break; + case 2: + PrintLog("CDVD driver: Book Type: DVD-R"); + break; + case 3: + PrintLog("CDVD driver: Book Type: DVD-RW"); + break; + case 9: + PrintLog("CDVD driver: Book Type: DVD+RW"); + break; + default: + PrintLog("CDVD driver: Book Type: Unknown (%i)", + dvdphysical.physical.layer[i].book_type); + break; + } // ENDSWITCH- Displaying the Book Type + PrintLog("CDVD driver: Book Version %i", + dvdphysical.physical.layer[i].book_version); + switch(dvdphysical.physical.layer[i].min_rate) { + case 0: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-ROM"); + break; + case 1: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-RAM"); + break; + case 2: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-R"); + break; + case 3: + PrintLog("CDVD driver: Use Minimum Rate for: DVD-RW"); + break; + case 9: + PrintLog("CDVD driver: Use Minimum Rate for: DVD+RW"); + break; + default: + PrintLog("CDVD driver: Use Minimum Rate for: Unknown (%i)", + dvdphysical.physical.layer[i].min_rate); + break; + } // ENDSWITCH- Displaying the Minimum (Spin?) Rate + switch(dvdphysical.physical.layer[i].disc_size) { + case 0: + PrintLog("CDVD driver: Physical Disk Size: 120mm"); + break; + case 1: + PrintLog("CDVD driver: Physical Disk Size: 80mm"); + break; + default: + PrintLog("CDVD driver: Physical Disk Size: Unknown (%i)", + dvdphysical.physical.layer[i].disc_size); + break; + } // ENDSWITCH- What's the Disk Size? + switch(dvdphysical.physical.layer[i].layer_type) { + case 1: + PrintLog("CDVD driver: Layer Type: Read-Only"); + break; + case 2: + PrintLog("CDVD driver: Layer Type: Recordable"); + break; + case 4: + PrintLog("CDVD driver: Layer Type: Rewritable"); + break; + default: + PrintLog("CDVD driver: Layer Type: Unknown (%i)", + dvdphysical.physical.layer[i].layer_type); + break; + } // ENDSWITCH- Displaying the Layer Type + switch(dvdphysical.physical.layer[i].track_path) { + case 0: + PrintLog("CDVD driver: Track Path: PTP"); + break; + case 1: + PrintLog("CDVD driver: Track Path: OTP"); + break; + default: + PrintLog("CDVD driver: Track Path: Unknown (%i)", + dvdphysical.physical.layer[i].track_path); + break; + } // ENDSWITCH- What's Track Path Layout? + // PrintLog("CDVD driver: Disc Size %i Layer Type %i Track Path %i Nlayers %i", + // dvdphysical.physical.layer[i].nlayers); + switch(dvdphysical.physical.layer[i].track_density) { + case 0: + PrintLog("CDVD driver: Track Density: .74 m/track"); + break; + case 1: + PrintLog("CDVD driver: Track Density: .8 m/track"); + break; + case 2: + PrintLog("CDVD driver: Track Density: .615 m/track"); + break; + default: + PrintLog("CDVD driver: Track Density: Unknown (%i)", + dvdphysical.physical.layer[i].track_density); + break; + } // ENDSWITCH- Displaying the Track Density + switch(dvdphysical.physical.layer[i].linear_density) { + case 0: + PrintLog("CDVD driver: Linear Density: .267 m/bit"); + break; + case 1: + PrintLog("CDVD driver: Linear Density: .293 m/bit"); + break; + case 2: + PrintLog("CDVD driver: Linear Density: .409 to .435 m/bit"); + break; + case 4: + PrintLog("CDVD driver: Linear Density: .280 to .291 m/bit"); + break; + case 8: + PrintLog("CDVD driver: Linear Density: .353 m/bit"); + break; + default: + PrintLog("CDVD driver: Linear Density: Unknown (%i)", + dvdphysical.physical.layer[i].linear_density); + break; + } // ENDSWITCH- Displaying the Linear Density + if(dvdphysical.physical.layer[i].start_sector == 0x30000) { + PrintLog("CDVD driver: Starting Sector: %lu (DVD-ROM, DVD-R, DVD-RW)", + dvdphysical.physical.layer[i].start_sector); + } else if(dvdphysical.physical.layer[i].start_sector == 0x31000) { + PrintLog("CDVD driver: Starting Sector: %lu (DVD-RAM, DVD+RW)", + dvdphysical.physical.layer[i].start_sector); + } else { + PrintLog("CDVD driver: Starting Sector: %lu", + dvdphysical.physical.layer[i].start_sector); + } // ENDLONGIF- What does the starting sector tell us? + PrintLog("CDVD driver: End of Layer 0: %lu", + dvdphysical.physical.layer[i].end_sector_l0); + PrintLog("CDVD driver: Ending Sector: %lu", + dvdphysical.physical.layer[i].end_sector); + if(dvdphysical.physical.layer[i].bca != 0) + PrintLog("CDVD driver: BCA data present"); + } // NEXT i- Work our way through each layer... +#endif /* VERBOSE_DISC_INFO */ + + return(0); // Success. Physical data stored for perusal. +} // END DVDreadPhysical() + +s32 DVDreadCopyright() { + s32 s32result; + u8 i; + int successflag; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadCopyright()"); +#endif /* VERBOSE_FUNCTION */ + + successflag = 0; + + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + memset(&dvdcopyright[i], 0, sizeof(dvd_struct)); + dvdcopyright[i].type = DVD_STRUCT_COPYRIGHT; + dvdcopyright[i].copyright.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdcopyright[i]); + if(s32result == 0) { + successflag = 1; + } else { + dvdcopyright[i].type = 0xFF; + } // ENDIF- + } // NEXT i- Getting copyright data for every known layer + + if(successflag == 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Copyright info: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Copyright Information\n"); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + if(dvdcopyright[i].type != 0xFF) { + PrintLog("CDVD driver: Layer Number %i CPST %i RMI %i", + dvdcopyright[i].copyright.layer_num, + dvdcopyright[i].copyright.cpst, + dvdcopyright[i].copyright.rmi); + } // ENDIF- Were we successful reading this one? + } // NEXT i- Printing out all copyright info found... +#endif /* VERBOSE_DISC_INFO */ + + errno = 0; + return(0); // Success. Copyright data stored for perusal. +} // END DVDreadCopyright() + +s32 DVDreadBCA() { + s32 s32result; + int i; + + i = 0; + errno = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadBCA()"); +#endif /* VERBOSE_FUNCTION */ + + memset(&dvdbca, 0, sizeof(dvd_struct)); + dvdbca.type = DVD_STRUCT_BCA; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdbca); + if((s32result == -1) || (errno != 0)) { + dvdbca.type = 0xFF; +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting BCA: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: BCA Length %i Value:", + dvdbca.bca.len); + for(i = 0; i < 188-15; i += 16) { + HexDump(dvdbca.bca.value+i, 16); + } // NEXT i- dumping whole key data +#endif /* VERBOSE_DISC_INFO */ + + return(0); // Success. BCA data stored for perusal. +} // END DVDreadBCA() + +s32 DVDreadManufact() { + s32 s32result; + u8 i; + int successflag; + int j; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadManufact()"); +#endif /* VERBOSE_FUNCTION */ + + j = 0; + successflag = 0; + + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + memset(&dvdmanufact[i], 0, sizeof(dvd_struct)); + dvdmanufact[i].type = DVD_STRUCT_MANUFACT; + dvdmanufact[i].manufact.layer_num = i; + errno = 0; + s32result = ioctl(devicehandle, DVD_READ_STRUCT, &dvdmanufact[i]); + if((s32result != 0) || (errno != 0)) { + dvdmanufact[i].type = 0xFF; + } else { + successflag = 1; + } // ENDIF- Did we fail to read in some manufacturer data? + } // NEXT i- Collecting manufacturer data from all layers + + if(successflag == 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error getting Manufact: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Problem with read of physical data? + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD driver: Manufact Data"); + for(i = 0; i <= dvdphysical.physical.layer_num; i++) { + if(dvdmanufact[i].type != 0xFF) { + PrintLog("CDVD driver: Layer %i Length %i Value:", + dvdmanufact[i].manufact.layer_num, + dvdmanufact[i].manufact.len); + for(j = 0; j < 128-15; j += 16) { + HexDump(dvdmanufact[i].manufact.value+j, 16); + } // NEXT j- dumping whole key data + } // ENDIF- Do we have data at this layer? + } // NEXT i- Running through all the layers +#endif /* VERBOSE_DISC_INFO */ + + errno = 0; + return(0); // Success. Manufacturer's data stored for perusal. +} // END DVDreadManufact() + + +// External Functions + +// Function Calls from CDVD.c + +void InitDVDInfo() { + int j; + + dvdphysical.type = 0xFF; // Using for empty=0xff, full!=0xff test + dvdbca.type = 0xFF; + for(j = 0; j < DVD_LAYERS; j++) { + dvdcopyright[j].type = 0xFF; + dvdmanufact[j].type = 0xFF; + } // NEXT j- Zeroing each layer of data + InitDVDSectorInfo(); +} // END InitDiscType() + +s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + off64_t offsettarget; + off64_t offsetresult; + + errno = 0; + s32result = 0; + offsetresult = 0; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDreadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION */ + + if(lsn != dvdlastlsn + 1) { + offsettarget = lsn; + offsettarget *= 2048; + errno = 4; + while(errno == 4) { + errno = 0; + offsetresult = lseek64(devicehandle, offsettarget, SEEK_SET); + } // ENDWHILE- waiting for the system interruptions to cease. + if((offsetresult < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: Error on seek: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitDVDSectorInfo(); + return(-1); + } // ENDIF- trouble with seek? Reset pointer and abort + } // ENDIF- Do we have to seek a new position to read? + + errno = 4; + while(errno == 4) { + errno = 0; + s32result = read(devicehandle, buffer, 2048); + } // ENDWHILE- waiting for the system interruptions to cease. + if((s32result != 2048) || (errno != 0)) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD driver: DVD Short Block, Size: %i", s32result); + PrintLog("CDVD driver: Error: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + InitDVDSectorInfo(); + return(-1); + } // ENDIF- Trouble reading the data? Reset pointer and abort + + dvdlastlsn = lsn; + return(0); // Call accomplished +} // END DVDreadTrack() + +s32 DVDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION */ + + // Going to treat this as one large track for now. + if(cdvdtn != NULL) { + cdvdtn->strack = 1; + cdvdtn->etrack = 1; + } // ENDIF- programmer actually WANTS this info? + + return(0); // Call accomplished +} // END DVDgetTN() + +s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd) { +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION */ + + if((newtrack >= 2) && (newtrack != CDROM_LEADOUT)) return(-1); + + if(cdvdtd != NULL) { + cdvdtd->lsn = dvdphysical.physical.layer[0].end_sector + - dvdphysical.physical.layer[0].start_sector + + 1; + cdvdtd->type = CDVD_MODE_2048; + } // ENDIF- Does the caller REALLY want this data? + + return(0); // Call accomplished +} // END DVDgetTD() + +s32 DVDgetDiskType(s32 ioctldisktype) { + s32 s32result; + int i; + s32 tempdisctype; + + errno = 0; + s32result = 0; + i = 0; + tempdisctype = CDVD_TYPE_UNKNOWN; + +#ifdef VERBOSE_FUNCTION + PrintLog("CDVD driver: DVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION */ + + if((ioctldisktype != CDS_DATA_1) && (ioctldisktype != CDS_MIXED)) { + return(-1); + } // ENDIF- Not a data disc we know of? Abort then + + s32result = DVDreadPhysical(); + if((s32result != 0) || (errno != 0)) { + return(-1); + } // ENDIF- Error reading the DVD physical structure? Not a DVD after all. + + if(dvdphysical.physical.layer[0].end_sector >= (2048*1024)) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: DVD Found (Dual-Sided)"); +#endif /* VERBOSE_DISC_TYPE */ + disctype = CDVD_TYPE_DETCTDVDD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: DVD Found (Single-Sided)"); +#endif /* VERBOSE_DISC_TYPE */ + disctype = CDVD_TYPE_DETCTDVDS; + } // ENDIF- Definitely a DVD. Size Test? + + // Read in the rest of the structures... + DVDreadCopyright(); + DVDreadBCA(); + DVDreadManufact(); + + // Test for "Playstation" header + s32result = DVDreadTrack(16, CDVD_MODE_2048, dvdtempbuffer); + if(s32result != 0) { + return(-1); + } else { + i = 0; + while((*(playstationname + i) != 0) && + (*(playstationname + i) == dvdtempbuffer[8 + i])) { + i++; + } // ENDWHILE- Checking each letter of PLAYSTATION name for a match + if(*(playstationname + i) == 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Detected Playstation 2 DVD"); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2DVD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD driver: Guessing it's a Video DVD"); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_DVDV; + } // ENDIF- Did we find the Playstation name? + } // ENDIF- Error reading disc volume information? Invalidate Disc + + if(dvdphysical.physical.layer[0].end_sector >= (2048*1024)) { + tocbuffer[0] = 0x24; // Dual-Sided DVD + tocbuffer[4] = 0x41; + tocbuffer[5] = 0x95; + } else { + tocbuffer[0] = 0x04; // Single-Sided DVD + tocbuffer[4] = 0x86; + tocbuffer[5] = 0x72; + } // ENDIF- Are there too many sectors for a single-sided disc? + + tocbuffer[1] = 0x02; + tocbuffer[2] = 0xF2; + tocbuffer[3] = 0x00; + + tocbuffer[16] = 0x00; + tocbuffer[17] = 0x03; + tocbuffer[18] = 0x00; + tocbuffer[19] = 0x00; + + disctype = tempdisctype; // Triggers the fact the other info is available + return(disctype); +} // END DVDgetDiskType() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.h b/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.h new file mode 100644 index 0000000..7dbc1c7 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/DVD.h @@ -0,0 +1,45 @@ +/* DVD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DVD_H__ +#define __DVD_H__ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +// Exported Functions + +extern void HexDump(u8 *strptr, u8 count); +extern void InitDVDInfo(); +extern s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DVDgetTN(cdvdTN *cdvdtn); +extern s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 DVDgetDiskType(s32 ioctldisktype); + + +#endif /* __DVD_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/Makefile b/plugins/cdvd/CDVDlinuz/Src/Linux/Makefile new file mode 100644 index 0000000..be45567 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/Makefile @@ -0,0 +1,71 @@ + +PLUGIN = libCDVDlinuz.so +PLUGINOBJS = CDVDlinuz.o ../buffer.o +PLUGINHEADERS = CDVDlinuz.h ../buffer.h +PLUGINFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -D_LARGEFILE64_SOURCE \ + -I.. -I. -I./Linux +PLUGINLIBS = + +CFG = cfgCDVDlinuz +CFGOBJS = aboutbox.o mainbox.o interface.o +CFGHEADERS = aboutbox.h mainbox.h interface.h +CFGFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -D_LARGEFILE64_SOURCE \ + -I.. -I. -I./Linux +CFGLIBS = + +SHAREDOBJS = actualfile.o conf.o logfile.o \ + device.o CD.o DVD.o \ + ../convert.o ../ini.o ../version.o +SHAREDHEADERS = actualfile.h conf.h logfile.h \ + device.h CD.h DVD.h \ + ../convert.h ../ini.h ../version.h + + +CC = gcc + +GTKFLAGS = $(shell pkg-config --cflags gtk+-2.0) + +//GTKFLAGS += -DG_DISABLE_DEPRECATED \ +// -DGDK_DISABLE_DEPRECATED \ +// -DGDK_PIXBUF_DISABLE_DEPRECATED \ +// -DGTK_DISABLE_DEPRECATED + +GTKLIBS = $(shell pkg-config --libs gtk+-2.0) +# Do we need to remove "-rdynamic" as well? Or is that just the main program? + + +all: plugin cfg +install: all + +release: plugin cfg + cp $(PLUGIN) ../.. + cp $(CFG) ../.. + +plugin: $(PLUGINOBJS) $(SHAREDOBJS) +# rm -f $(PLUGIN) + $(CC) -shared -Wl,-soname,$(PLUGIN) $(PLUGINFLAGS) $(PLUGINLIBS) \ + $(PLUGINOBJS) $(SHAREDOBJS) -o $(PLUGIN) + strip --strip-unneeded --strip-debug $(PLUGIN) + +cfg: $(CFGOBJS) $(SHAREDOBJS) +# rm -f $(CFG) + $(CC) $(CFGFLAGS) $(GTKFLAGS) $(CFGLIBS) $(GTKLIBS) \ + $(CFGOBJS) $(SHAREDOBJS) -o $(CFG) + strip $(CFG) + +$(PLUGINOBJS) $(SHAREDOBJS): %.o: %.c + $(CC) $(PLUGINFLAGS) -c $< -o $@ + +$(CFGOBJS): %.o: %.c + $(CC) $(CFGFLAGS) $(GTKFLAGS) -c $< -o $@ + +.PHONY : clean allclean +clean: + -rm -f $(PLUGINOBJS) $(PLUGIN) $(CFGOBJS) $(CFG) $(SHAREDOBJS) + -rm -f *~ temp.txt ../*~ ../temp.txt ../../*~ + +allclean: + -rm -f $(PLUGINOBJS) $(PLUGIN) $(CFGOBJS) $(CFG) $(SHAREDOBJS) + -rm -f *~ temp.txt ../*~ ../temp.txt ../../*~ + -rm -f ../../$(PLUGIN) ../../$(CFG) + diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.c b/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.c new file mode 100644 index 0000000..9408d0b --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.c @@ -0,0 +1,106 @@ +/* aboutbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() + +#include // gtk_button_new_with_label() +#include // gtk_container_add() +#include // gtk_hbutton_box_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "version.h" +#include "aboutbox.h" + + +struct AboutBoxData aboutbox; + + +gint AboutBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + if(aboutbox.window != NULL) { + gtk_widget_destroy(aboutbox.window); + aboutbox.window = NULL; + } // ENDIF- Do we have an About Box still? + + gtk_main_quit(); + return(TRUE); +} // END AboutBoxCancelEvent() + + +void AboutBoxDisplay() { + GtkWidget *item; + GtkWidget *container; + GtkWidget *vbox1; + char templine[256]; + + aboutbox.window = NULL; + aboutbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(aboutbox.window), 5); + gtk_window_set_title(GTK_WINDOW(aboutbox.window), "About CDVDlinuz"); + gtk_window_set_position(GTK_WINDOW(aboutbox.window), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(aboutbox.window), TRUE); + gtk_window_set_resizable(GTK_WINDOW(aboutbox.window), FALSE); + + g_signal_connect(G_OBJECT(aboutbox.window), "delete_event", + G_CALLBACK(AboutBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(aboutbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + sprintf(templine, "%s v%i.%i", libname, revision, build); + item = gtk_label_new(templine); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + item = gtk_label_new("Current Author: efp"); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + item = gtk_label_new("Original code by: linuzappz & shadow"); + gtk_box_pack_start(GTK_BOX(vbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + container = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), container, TRUE, TRUE, 0); + gtk_widget_show(container); + + item = gtk_button_new_with_label("Ok"); + gtk_container_add(GTK_CONTAINER(container), item); + GTK_WIDGET_SET_FLAGS(item, GTK_CAN_DEFAULT); + gtk_widget_show(item); + + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(AboutBoxCancelEvent), NULL); + item = NULL; + container = NULL; + vbox1 = NULL; + + gtk_widget_show(aboutbox.window); + gtk_main(); +} // END AboutDisplay() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.h b/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.h new file mode 100644 index 0000000..bf1df52 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/aboutbox.h @@ -0,0 +1,39 @@ +/* aboutbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef ABOUTBOX_H +#define ABOUTBOX_H + + +#include + + +struct AboutBoxData { + GtkWidget *window; // GtkWindow - About Box +}; + +extern struct AboutBoxData aboutbox; + + +extern void AboutBoxDisplay(); + + +#endif /* ABOUTBOX_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.c b/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.c new file mode 100644 index 0000000..64eaa69 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.c @@ -0,0 +1,222 @@ +/* actualfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // errno +#include // open() +#include // rename() +#include // strerror() +#include // stat64(), open(), fstat() +#include // stat64(), open(), fstat(), lseek64() +#include // stat64(), fstat(), lseek64(), read(), close(), write() +// unlink() + +#include "logfile.h" +#include "actualfile.h" + + +int IsActualFile(const char *filename) { + int retval; + struct stat64 filestat; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: IsActualFile(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = stat64(filename, &filestat); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error retrieving stats on %s", filename); + PrintLog("CDVDiso file: %i:%s\n", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); // Name doesn't exist. + } // ENDIF- Trouble getting stat on a file? + + if(S_ISREG(filestat.st_mode) == 0) return(-2); // Not a regular file. + return(0); // Yep, that's a file. +} // END IsActualFile() + + +void ActualFileDelete(const char *filename) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileDelete(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + unlink(filename); +} // END ActualFileDelete() + + +void ActualFileRename(const char *origname, const char *newname) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileRename(%s->%s)", origname, newname); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + rename(origname, newname); + return; +} // END ActualFileRename() + + +ACTUALHANDLE ActualFileOpenForRead(const char *filename) { + int newhandle; + + if(filename == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForRead(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + newhandle = open(filename, O_RDONLY | O_LARGEFILE); + if((newhandle < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s\n", filename); + PrintLog("CDVDiso file: (%i) %i:%s\n", newhandle, errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForRead() + + +off64_t ActualFileSize(ACTUALHANDLE handle) { + int retval; + struct stat64 filestat; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSize()\n"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = fstat64(handle, &filestat); + if((retval < 0) || (errno != 0)) return(-1); // Name doesn't exist. + return(filestat.st_size); +} // END ActualFileSize() + + +int ActualFileSeek(ACTUALHANDLE handle, off64_t position) { + off64_t moved; + + if(handle < 0) return(-1); + if(position < 0) return(-1); // Maybe... position = 0? + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSeek(%lli)", position); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + moved = lseek64(handle, position, SEEK_SET); + if(errno != 0) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error on seek (%lli)", position); + PrintLog("CDVDiso file: %i:%s\n", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(0); +} // END ActualFileSeek() + + +int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + + if(handle == ACTUALHANDLENULL) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileRead(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = read(handle, buffer, bytes); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error reading from file!"); + PrintLog("CDVDiso file: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + // return(-1); + } // ENDIF- Error? Abort + + return(retval); // Send back how many bytes read +} // END ActualFileRead() + + +void ActualFileClose(ACTUALHANDLE handle) { + if(handle < 0) return; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileClose()"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + close(handle); + return; +} // END ActualFileClose() + + +ACTUALHANDLE ActualFileOpenForWrite(const char *filename) { + int newhandle; + + if(filename == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForWrite(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + newhandle = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0644); + if((newhandle < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s", filename); + PrintLog("CDVDiso file: (%i) %i:%s", newhandle, errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForWrite() + + +int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + + if(handle < 0) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileWrite(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + errno = 0; + retval = write(handle, buffer, bytes); + if((retval < 0) || (errno != 0)) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error writing to file!"); + PrintLog("CDVDiso file: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + // return(-1); + } // ENDIF- Error? Abort + + return(retval); // Send back how many bytes written +} // END ActualFileWrite() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.h b/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.h new file mode 100644 index 0000000..a678b63 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/actualfile.h @@ -0,0 +1,50 @@ +/* actualfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef ACTUALFILE_H +#define ACTUALFILE_H + + +#include // off64_t + + +#define ACTUALHANDLE int +#define ACTUALHANDLENULL -1 + +// #define VERBOSE_FUNCTION_ACTUALFILE +// #define VERBOSE_WARNING_ACTUALFILE + + +extern int IsActualFile(const char *filename); +extern void ActualFileDelete(const char *filename); +extern void ActualFileRename(const char *origname, const char *newname); + +extern ACTUALHANDLE ActualFileOpenForRead(const char *filename); +extern off64_t ActualFileSize(ACTUALHANDLE handle); +extern int ActualFileSeek(ACTUALHANDLE handle, off64_t position); +extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer); +extern void ActualFileClose(ACTUALHANDLE handle); + +extern ACTUALHANDLE ActualFileOpenForWrite(const char *filename); +extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer); + + +#endif /* ACTUALFILE_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/conf.c b/plugins/cdvd/CDVDlinuz/Src/Linux/conf.c new file mode 100644 index 0000000..330af46 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/conf.c @@ -0,0 +1,184 @@ +/* conf.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // getenv() +#include // strerror() +#include // mkdir(), stat() +#include // mkdir(), stat() +#include // stat() + +// #define CDVDdefs +// #include "../PS2Edefs.h" +#include "logfile.h" +#include "../ini.h" +#include "conf.h" + + +const char *cfgname[] = { \ + "./cfg/cfgCDVDlinuz", \ + "../cfg/cfgCDVDlinuz", \ + "./plugins/cfgCDVDlinuz", \ + "../plugins/cfgCDVDlinuz", \ + "./cfgCDVDlinuz", \ + "../cfgCDVDlinuz", \ + NULL }; + +const char *confnames[] = { "Device", NULL }; +const u8 defaultdevice[] = DEFAULT_DEVICE; +const char defaulthome[] = "../inis"; +const char defaultdirectory[] = ".PS2E"; +const char defaultfile[] = "CDVDlinuz.ini"; + +char confdirname[256]; +char conffilename[256]; + +CDVDconf conf; + + +void ExecCfg(char *arg) { + int nameptr; + struct stat filestat; + char templine[256]; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVDiso interface: ExecCfg(%s)", arg); +#endif /* VERBOSE FUNCTION_CONF */ + errno = 0; + nameptr = 0; + while((cfgname[nameptr] != NULL) && + (stat(cfgname[nameptr], &filestat) == -1)) nameptr++; + errno = 0; + + if(cfgname[nameptr] == NULL) { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVDiso interface: Couldn't find configuration program!"); +#endif /* VERBOSE_FUNCTION_CONF */ + return; + } // ENDIF- Did not find the executable? + + sprintf(templine, "%s %s", cfgname[nameptr], arg); + system(templine); +} // END ExecCfg() + + +void InitConf() { + int i; + int pos; + char *envptr; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: InitConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + i = 0; + while((i < 255) && defaultdevice[i] != 0) { + conf.devicename[i] = defaultdevice[i]; + i++; + } // ENDWHILE- copying the default CD/DVD name in + conf.devicename[i] = 0; // 0-terminate the device name + + // Locating directory and file positions + pos = 0; + envptr = getenv("HOME"); + if(envptr == NULL) { + // = + i = 0; + while((pos < 253) && (defaulthome[i] != 0)) { + confdirname[pos] = defaulthome[i]; + conffilename[pos] = defaulthome[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + } else { + // = / + i = 0; + while((pos < 253) && (*(envptr + i) != 0)) { + confdirname[pos] = *(envptr + i); + conffilename[pos] = *(envptr + i); + pos++; + i++; + } // ENDWHILE- copying home directory info in + + if(confdirname[pos-1] != '/') { + confdirname[pos] = '/'; + conffilename[pos] = '/'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultdirectory[i] != 0)) { + confdirname[pos] = defaultdirectory[i]; + conffilename[pos] = defaultdirectory[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + } // ENDIF- No Home directory? + + confdirname[pos] = 0; // Directory reference finished + + // += / + if(conffilename[pos-1] != '/') { + conffilename[pos] = '/'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultfile[i] != 0)) { + conffilename[pos] = defaultfile[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + conffilename[pos] = 0; // File reference finished + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: Directory: %s\n", confdirname); + PrintLog("CDVD config: File: %s\n", conffilename); +#endif /* VERBOSE_FUNCTION_CONF */ +} // END InitConf() + + +void LoadConf() { + int retval; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: LoadConf()\n"); +#endif /* VERBOSE_FUNCTION_CONF */ + + retval = INILoadString(conffilename, "Settings", "Device", conf.devicename); + if(retval < 0) { + sprintf(conf.devicename, "/dev/dvd"); + } // ENDIF- Couldn't find keyword? Fill in a default +} // END LoadConf() + + +void SaveConf() { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: SaveConf()\n"); +#endif /* VERBOSE_FUNCTION_CONF */ + + mkdir(confdirname, 0755); + + INISaveString(conffilename, "Settings", "Device", conf.devicename); +} // END SaveConf() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/conf.h b/plugins/cdvd/CDVDlinuz/Src/Linux/conf.h new file mode 100644 index 0000000..b66dfd0 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/conf.h @@ -0,0 +1,57 @@ +/* conf.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef CONF_H +#define CONF_H + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "../PS2Edefs.h" + + +#define VERBOSE_FUNCTION_CONF + + +// Configuration Data + +typedef struct { + u8 devicename[256]; +} CDVDconf; +extern CDVDconf conf; + +#define DEFAULT_DEVICE "/dev/cdrom" + + +// Configuration Functions + +extern void InitConf(); +extern void LoadConf(); +extern void SaveConf(); + +extern void ExecCfg(char *arg); + + +#endif /* CONF_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/device.c b/plugins/cdvd/CDVDlinuz/Src/Linux/device.c new file mode 100644 index 0000000..b45f883 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/device.c @@ -0,0 +1,420 @@ +/* device.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // open() +#include // NULL +#include // getenv() +#include // strerror() +#include // ioctl() +#include // open() +#include // open() +#include // time_t, time(), struct timeval +#include // close(), select() + +#include // CD/DVD based ioctl() and defines. + +// missing on some files for some reason......... +#ifndef CDC_IOCTLS +#define CDC_IOCTLS 0x400 +#endif + +#include "logfile.h" +#include "conf.h" +#include "CD.h" +#include "DVD.h" +#include "device.h" + +#include "../PS2Etypes.h" // u32, u8, s32 + + +// Globals + +int devicehandle; // File Handle for the device/drive +s32 devicecapability; // Capability Flags +time_t lasttime; // Time marker (in case something gets called too often) +s32 traystatus; // Is the CD/DVD tray open? + +s32 disctype; // Type of disc in drive (Video DVD, PSX CD, etc.) +u8 tocbuffer[2048]; + + +void DeviceInit() { + devicehandle = -1; + devicecapability = 0; + lasttime = time(NULL); + + InitDisc(); +} // END DeviceInit() + + +// Called by DeviceOpen(), DeviceGetDiskType() +void InitDisc() { + int i; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: InitDisc()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if((disctype == CDVD_TYPE_PS2DVD) || + (disctype == CDVD_TYPE_DVDV)) { + InitDVDInfo(); + } // ENDIF- Clean out DVD Disc Info? + + if((disctype == CDVD_TYPE_PS2CD) || + (disctype == CDVD_TYPE_PS2CDDA) || + (disctype == CDVD_TYPE_PSCD) || + (disctype == CDVD_TYPE_PSCDDA) || + (disctype == CDVD_TYPE_CDDA)) { + InitCDInfo(); + } // ENDIF- Clean out DVD Disc Info? + + disctype = CDVD_TYPE_NODISC; + for(i = 0; i > sizeof(tocbuffer); i++) tocbuffer[i] = 0x00; +} // END InitDisc() + + +s32 DiscInserted() { + if(devicehandle == -1) return(-1); + if(traystatus == CDVD_TRAY_OPEN) return(-1); + if(disctype == CDVD_TYPE_ILLEGAL) return(-1); + // if(disctype == CDVD_TYPE_UNKNOWN) return(-1); // Hmm. Let this one through? + if(disctype == CDVD_TYPE_DETCTDVDD) return(-1); + if(disctype == CDVD_TYPE_DETCTDVDS) return(-1); + if(disctype == CDVD_TYPE_DETCTCD) return(-1); + if(disctype == CDVD_TYPE_DETCT) return(-1); + if(disctype == CDVD_TYPE_NODISC) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DiscInserted()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + return(0); +} // END DiscInserted() + + +// Called by DeviceTrayStatus() and CDVDopen() +s32 DeviceOpen() { + // s32 s32result; + + errno = 0; + + if(devicehandle != -1) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVD device: Device already open!"); +#endif /* VERBOSE_WARNING_DEVICE */ + return(0); + } // ENDIF- Is the CD/DVD already in use? That's fine. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + // InitConf(); + // LoadConf(); // Should be done once before making this call + + devicehandle = open(conf.devicename, O_RDONLY | O_NONBLOCK); + if(devicehandle == -1) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Error opening device: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + return(-1); + } // ENDIF- Failed to open device? Abort + + // Note: Hmm. Need a minimum capability in case this fails? + devicecapability = ioctl(devicehandle, CDROM_GET_CAPABILITY); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Error getting device capabilities: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + close(devicehandle); + devicehandle = -1; + devicecapability = 0; + return(-1); + } // ENDIF- Can't read drive capabilities? Close and Abort. + +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVD device: Device Type(s)"); + if(devicecapability < CDC_CD_R) PrintLog("CDVD device: CD"); + if(devicecapability & CDC_CD_R) PrintLog("CDVD device: CD-R"); + if(devicecapability & CDC_CD_RW) PrintLog("CDVD device: CD-RW"); + if(devicecapability & CDC_DVD) PrintLog("CDVD device: DVD"); + if(devicecapability & CDC_DVD_R) PrintLog("CDVD device: DVD-R"); + if(devicecapability & CDC_DVD_RAM) PrintLog("CDVD device: DVD-RAM"); +#endif /* VERBOSE_DISC_TYPE */ +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVD device: Device Capabilities:"); + if(devicecapability & CDC_CLOSE_TRAY) PrintLog("CDVD device: Can close a tray"); + if(devicecapability & CDC_OPEN_TRAY) PrintLog("CDVD device: Can open a tray"); + // if(devicecapability & CDC_LOCK) PrintLog("CDVD device: Can lock the drive door"); + if(devicecapability & CDC_SELECT_SPEED) PrintLog("CDVD device: Can change spin speed"); + // if(devicecapability & CDC_SELECT_DISC) PrintLog("CDVD device: Can change disks (multi-disk tray)"); + // if(devicecapability & CDC_MULTI_SESSION) PrintLog("CDVD device: Can read multi-session disks"); + // if(devicecapability & CDC_MCN) PrintLog("CDVD device: Can read Medium Catalog Numbers (maybe)"); + if(devicecapability & CDC_MEDIA_CHANGED) PrintLog("CDVD device: Can tell if the disc was changed"); + if(devicecapability & CDC_PLAY_AUDIO) PrintLog("CDVD device: Can play audio disks"); + // if(devicecapability & CDC_RESET) PrintLog("CDVD device: Can reset the device"); + if(devicecapability & CDC_IOCTLS) PrintLog("CDVD device: Odd IOCTLs. Not sure of compatability"); + if(devicecapability & CDC_DRIVE_STATUS) PrintLog("CDVD device: Can monitor the drive tray"); +#endif /* VERBOSE_DISC_INFO */ + + ////// Should be called after an open (instead of inside of one) + // InitDisc(); + // traystatus = CDVD_TRAY_OPEN; // Start with Tray Open + // DeviceTrayStatus(); // Now find out for sure. + + return(0); // Device opened and ready for use. +} // END DeviceOpen() + + +// Called by DeviceTrayStatus(), CDVDclose(), and CDVDshutdown() +void DeviceClose() { + if(devicehandle == -1) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: Device already closed"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + return; + } // ENDIF- Device already closed? Ok. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + InitDisc(); + close(devicehandle); + devicehandle = -1; + devicecapability = 0; + return; +} // END CDVDclose() + + +s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer) { + s32 s32result; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceReadTrack(%i)", lsn); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(DiscInserted() == -1) return(-1); + + // Get that data + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + s32result = DVDreadTrack(lsn, mode, buffer); + } else { + s32result = CDreadTrack(lsn, mode, buffer); + } //ENDIF- Read a DVD sector or a CD sector? + + return(s32result); +} // END DeviceReadTrack() + + +s32 DeviceBufferOffset() { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceBufferOffset()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(0); + } else { + return(CDgetBufferOffset()); + } // ENDIF- Is this a DVD? +} // END DeviceBufferOffset() + + +s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTD(track, cdvdtd)); + } else { + return(CDgetTD(track, cdvdtd)); + } // ENDIF- Is this a DVD? +} // END DeviceGetTD() + + +// Called by DeviceTrayStatus() +s32 DeviceGetDiskType() { + s32 s32result; + s32 ioctldisktype; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if(traystatus == CDVD_TRAY_OPEN) { + return(disctype); + } // ENDIF- Is the device tray open? No disc to check yet. + + if(disctype != CDVD_TYPE_NODISC) { + return(disctype); + } // ENDIF- Already checked? Drive still closed? Disc hasn't changed. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceGetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + disctype = CDVD_TYPE_DETCT; + + ioctldisktype = ioctl(devicehandle, CDROM_DISC_STATUS); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble reading Disc Type!"); + PrintLog("CDVD device: Error: %i:%s", errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + disctype = CDVD_TYPE_UNKNOWN; + return(disctype); + } // ENDIF- Trouble probing for a disc? + + s32result = DVDgetDiskType(ioctldisktype); + if(s32result != -1) { + return(disctype); + } // ENDIF- Did we find a disc type? + + s32result = CDgetDiskType(ioctldisktype); + if(s32result != -1) { + return(disctype); + } // ENDIF- Did we find a disc type? + + disctype = CDVD_TYPE_UNKNOWN; // Not a CD? Not a DVD? Is is peanut butter? + return(disctype); +} // END CDVDgetDiskType() + + +// Called by PollLoop() and CDVDgetTrayStatus() +s32 DeviceTrayStatus() { + s32 s32result; + + errno = 0; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayStatus()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_DRIVE_STATUS) != 0) { + s32result = ioctl(devicehandle, CDROM_DRIVE_STATUS); + if(s32result < 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble reading Drive Status!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + s32result = CDS_TRAY_OPEN; + } // ENDIF- Failure to get status? Assume it's open. + errno = 0; + + } else { + s32result = ioctl(devicehandle, CDROM_DISC_STATUS); + if(errno != 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVD device: Trouble detecting Disc Status presense!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); +#endif /* VERBOSE_WARNINGS */ + s32result = CDS_TRAY_OPEN; + errno = 0; + } // ENDIF- Trouble? + if(s32result == CDS_NO_DISC) { + s32result = CDS_TRAY_OPEN; + } // ENDIF- Is there no disc in the device? Guess the tray is open + } // ENDIF- Can we poll the tray directly? (Or look at disc status instead?) + + if(s32result == CDS_TRAY_OPEN) { + traystatus = CDVD_TRAY_OPEN; + if(disctype != CDVD_TYPE_NODISC) { + DeviceClose(); // Kind of severe way of flushing all buffers. + DeviceOpen(); + InitDisc(); + } // ENDIF- Tray just opened... clear disc info + } else { + traystatus = CDVD_TRAY_CLOSE; + if(disctype == CDVD_TYPE_NODISC) { + DeviceGetDiskType(); + } // ENDIF- Tray just closed? Get disc information + } // ENDIF- Do we detect an open tray? + return(traystatus); +} // END CDVD_getTrayStatus() + + +s32 DeviceTrayOpen() { + s32 s32result; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_OPEN_TRAY) == 0) { + return(-1); + } // ENDIF- Don't have open capability? Error out. + + // Tray already open? Exit. + if(traystatus == CDVD_TRAY_OPEN) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + s32result = ioctl(devicehandle, CDROMEJECT); +#ifdef VERBOSE_WARNINGS + if((s32result != 0) || (errno != 0)) { + PrintLog("CDVD device: Could not open the tray!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); + } // ENDIF- Trouble? +#endif /* VERBOSE_WARNINGS */ + return(s32result); +} // END DeviceTrayOpen() + + +s32 DeviceTrayClose() { + s32 s32result; + + errno = 0; + + if(devicehandle == -1) { + return(-1); + } // ENDIF- Someone forget to open the device? + + if((devicecapability & CDC_CLOSE_TRAY) == 0) { + return(-1); + } // ENDIF- Don't have close capability? Error out. + + // Tray already closed? Exit. + if(traystatus == CDVD_TRAY_CLOSE) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD device: DeviceTrayClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + s32result = ioctl(devicehandle, CDROMCLOSETRAY); +#ifdef VERBOSE_WARNINGS + if((s32result != 0) || (errno != 0)) { + PrintLog("CDVD device: Could not close the tray!"); + PrintLog("CDVD device: Error: (%i) %i:%s", s32result, errno, strerror(errno)); + } // ENDIF- Trouble? +#endif /* VERBOSE_WARNINGS */ + return(s32result); +} // END DeviceTrayClose() + diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/device.h b/plugins/cdvd/CDVDlinuz/Src/Linux/device.h new file mode 100644 index 0000000..0d0d8ff --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/device.h @@ -0,0 +1,69 @@ +/* device.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + + +#include // time_t + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ +#define CDVDdefs +#include "../PS2Edefs.h" + + +// #define VERBOSE_FUNCTION_DEVICE +// #define VERBOSE_WARNINGS +#define VERBOSE_DISC_TYPE +#define VERBOSE_DISC_INFO + + +// Device Data + +extern int devicehandle; +extern s32 devicecapability; // Need to export? + +extern time_t lasttime; +extern s32 traystatus; +extern s32 disctype; +extern u8 tocbuffer[]; + + +// Device Functions + +extern void DeviceInit(); +extern void InitDisc(); +extern s32 DiscInserted(); +extern s32 DeviceOpen(); +extern void DeviceClose(); +extern s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DeviceBufferOffset(); +extern s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd); +extern s32 DeviceGetDiskType(); +extern s32 DeviceTrayStatus(); +extern s32 DeviceTrayOpen(); +extern s32 DeviceTrayClose(); + + +#endif /* __DEVICE_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/interface.c b/plugins/cdvd/CDVDlinuz/Src/Linux/interface.c new file mode 100644 index 0000000..5a354d9 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/interface.c @@ -0,0 +1,57 @@ +/* interface.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcmp() + +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_widget_show_all() + +#include "logfile.h" +#include "conf.h" +#include "aboutbox.h" +#include "mainbox.h" + + +int main(int argc, char *argv[]) { + if(argc != 2) return(1); + + gtk_init(NULL, NULL); + + if(!strcmp(argv[1], "about")) { + AboutBoxDisplay(); + return(0); + + } else if (!strcmp(argv[1], "configure")) { + OpenLog(); + InitConf(); + LoadConf(); + MainBoxDisplay(); + + gtk_widget_show_all(mainbox.window); + gtk_main(); + CloseLog(); + return(0); + } // ENDLONGIF- Which display would you like to see? + + return(1); // No Displays chosen? Abort! +} // END main() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.c b/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.c new file mode 100644 index 0000000..27c6fe8 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.c @@ -0,0 +1,90 @@ +/* logfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // open +#include // vsprintf() +#include // va_start(), va_end(), vsprintf() +#include // mkdir(), open() +#include // mkdir(), open() +#include // close(), write(), unlink() + +#include "logfile.h" + + +int logfile; +char logfiletemp[2048]; + + +void InitLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + mkdir("./logs", 0755); + + unlink("./logs/CDVDlog.txt"); +#endif /* VERBOSE LOGFILE */ +} // END InitLog(); + + +int OpenLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + logfile = -1; + logfile = open("./logs/CDVDlog.txt", O_WRONLY | O_CREAT | O_APPEND, 0755); + if(logfile == -1) return(-1); +#endif /* VERBOSE LOGFILE */ + + return(0); +} // END OpenLog(); + + +void CloseLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + if(logfile != -1) { + close(logfile); + logfile = -1; + } // ENDIF- Is the log file actually open? Close it. +#endif /* VERBOSE LOGFILE */ +} // END CloseLog() + + +void PrintLog(const char *fmt, ...) { + // Token comment line +#ifdef VERBOSE_LOGFILE + va_list list; + int len; + + if(logfile == -1) return; // Log file not open. + + va_start(list, fmt); + vsprintf(logfiletemp, fmt, list); + va_end(list); + + len = 0; + while((len < 2048) && (logfiletemp[len] != 0)) len++; + if((len > 0) && (logfiletemp[len-1] == '\n')) len--; + if((len > 0) && (logfiletemp[len-1] == '\r')) len--; + logfiletemp[len] = 0; // Slice off the last "\r\n"... + + write(logfile, logfiletemp, len); + write(logfile, "\r\n", 2); // ... and write out your own. +#endif /* VERBOSE LOGFILE */ +} // END PrintLog() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.h b/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.h new file mode 100644 index 0000000..8cee990 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/logfile.h @@ -0,0 +1,35 @@ +/* logfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef LOGFILE_H +#define LOGFILE_H + + +#define VERBOSE_LOGFILE + + +extern void InitLog(); +extern int OpenLog(); +extern void CloseLog(); +extern void PrintLog(const char *format, ...); + + +#endif /* LOGFILE_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.c b/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.c new file mode 100644 index 0000000..c6423e2 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.c @@ -0,0 +1,187 @@ +/* mainbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() +#include // strcpy() +#include // stat() +#include // stat() +#include // stat() + +#include // gtk_button_new_with_label() +#include // gtk_container_add() +#include // gtk_entry_new() +#include // gtk_hbutton_box_new() +#include // gtk_hbox_new() +#include // gtk_label_new() +#include // gtk_init(), gtk_main(), gtk_main_quit() +#include // gtk_vbox_new() +#include // gtk_window_new() + +#include "conf.h" +// #include "logfile.h" +#include "device.h" // DeviceOpen(), DeviceClose() +#include "mainbox.h" + + +struct MainBoxData mainbox; + + +void MainBoxDestroy() { + if(mainbox.window != NULL) { + gtk_widget_destroy(mainbox.window); + mainbox.window = NULL; + mainbox.device = NULL; + mainbox.desc = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MainBoxDestroy() + + +void MainBoxUnfocus() { + gtk_widget_set_sensitive(mainbox.device, FALSE); + gtk_window_iconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxUnfocus() + + +gint MainBoxDeviceEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + struct stat filestat; + int retval; + + retval = stat(gtk_entry_get_text(GTK_ENTRY(mainbox.device)), &filestat); + if(retval == -1) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "Device Type: ---"); + return(TRUE); + } // ENDIF- Not a name of any sort? + + if(S_ISDIR(filestat.st_mode) != 0) { + gtk_label_set_text(GTK_LABEL(mainbox.desc), "Device Type: Not a device"); + return(TRUE); + } // ENDIF- Not a regular file? + + gtk_label_set_text(GTK_LABEL(mainbox.desc), "Device Type: Device Likely"); + return(TRUE); +} // END MainBoxFileEvent() + + +void MainBoxRefocus() { + GdkEvent event; + + MainBoxDeviceEvent(NULL, event, NULL); + + gtk_widget_set_sensitive(mainbox.device, TRUE); + gtk_window_set_focus(GTK_WINDOW(mainbox.window), mainbox.device); + gtk_window_deiconify(GTK_WINDOW(mainbox.window)); +} // END MainBoxRefocus() + + +gint MainBoxCancelEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + MainBoxDestroy(); + + gtk_main_quit(); + return(TRUE); +} // END MainBoxCancelEvent() + + +gint MainBoxOKEvent(GtkWidget *widget, GdkEvent event, gpointer data) { + const char *tempdevice; + int retval; + + MainBoxUnfocus(); + + tempdevice = gtk_entry_get_text(GTK_ENTRY(mainbox.device)); + strcpy(conf.devicename, tempdevice); // Temporarily put in new device name + tempdevice = NULL; + if(*(conf.devicename) != 0) { + retval = DeviceOpen(); // Test by opening the device. + DeviceClose(); // Failed or not, close it. + if(retval != 0) { + MainBoxRefocus(); + return(TRUE); + } // ENDIF- Not an ISO file? Message and Stop here. + } // ENDIF- Is there an ISO file to check out? + + SaveConf(); + + MainBoxCancelEvent(widget, event, data); + return(TRUE); +} // END MainBoxOKEvent() + + +void MainBoxDisplay() { + GtkWidget *item; + GtkWidget *hbox1; + GtkWidget *vbox1; + + mainbox.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width(GTK_CONTAINER(mainbox.window), 5); + gtk_window_set_title(GTK_WINDOW(mainbox.window), "CDVDlinuz Configuration"); + gtk_window_set_position(GTK_WINDOW(mainbox.window), GTK_WIN_POS_CENTER); + + g_signal_connect(G_OBJECT(mainbox.window), "delete_event", + G_CALLBACK(MainBoxCancelEvent), NULL); + + vbox1 = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(mainbox.window), vbox1); + gtk_container_set_border_width(GTK_CONTAINER(vbox1), 5); + gtk_widget_show(vbox1); + + hbox1 = gtk_hbox_new(FALSE, 10); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_label_new("CD/DVD Device:"); + gtk_box_pack_start(GTK_BOX(hbox1), item, FALSE, FALSE, 0); + gtk_widget_show(item); + item = NULL; + + mainbox.device = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox1), mainbox.device, TRUE, TRUE, 0); + gtk_widget_show(mainbox.device); + g_signal_connect(G_OBJECT(mainbox.device), "changed", + G_CALLBACK(MainBoxDeviceEvent), NULL); + hbox1 = NULL; + + mainbox.desc = gtk_label_new("File Type: ---"); + gtk_box_pack_start(GTK_BOX(vbox1), mainbox.desc, FALSE, FALSE, 0); + gtk_widget_show(mainbox.desc); + + hbox1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0); + gtk_widget_show(hbox1); + + item = gtk_button_new_with_label("Ok"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(MainBoxOKEvent), NULL); + + item = gtk_button_new_with_label("Cancel"); + gtk_box_pack_start(GTK_BOX(hbox1), item, TRUE, TRUE, 0); + gtk_widget_show(item); + g_signal_connect(G_OBJECT(item), "clicked", + G_CALLBACK(MainBoxCancelEvent), NULL); + item = NULL; + hbox1 = NULL; + vbox1 = NULL; + + // We held off setting the name until now... so description would show. + gtk_entry_set_text(GTK_ENTRY(mainbox.device), conf.devicename); +} // END MainBoxDisplay() diff --git a/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.h b/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.h new file mode 100644 index 0000000..c862063 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Linux/mainbox.h @@ -0,0 +1,41 @@ +/* mainbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef MAINBOX_H +#define MAINBOX_H + + +#include + + +struct MainBoxData { + GtkWidget *window; // GtkWindow + GtkWidget *device; // GtkEntry + GtkWidget *desc; // GtkLabel +}; + +extern struct MainBoxData mainbox; + +// extern void MainBoxRefocus(); +extern void MainBoxDisplay(); + + +#endif /* MAINBOX_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/PS2Edefs.h b/plugins/cdvd/CDVDlinuz/Src/PS2Edefs.h new file mode 100644 index 0000000..ef33df3 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/PS2Edefs.h @@ -0,0 +1,812 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/PS2Etypes.h b/plugins/cdvd/CDVDlinuz/Src/PS2Etypes.h new file mode 100644 index 0000000..1d60570 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/CD.c b/plugins/cdvd/CDVDlinuz/Src/Win32/CD.c new file mode 100644 index 0000000..24c6499 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/CD.c @@ -0,0 +1,387 @@ +/* CD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include // IOCTL_CDROM... + +#include // off64_t + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" +#include "../convert.h" // MSFtoLBA(), HEXTOBCD() +#include "actualfile.h" +#include "device.h" // tocbuffer[], FinishCommand() +#include "CD.h" + + +int actualcdmode; // -1=ReadFile, 0=YellowMode2, 1=XAForm2, 2=CDDA +DWORD cdblocksize; // 2048 to 2352 +int cdoffset; // 0, 8, 16, or 24 +int cdmode; + + +void InitCDInfo() { + actualcdmode = -1; + cdblocksize = 2048; + cdmode = -1; +} // END InitCDInfo() + + +s32 CDreadTrackPass(u32 lsn, int mode, u8 *buffer) { + RAW_READ_INFO rawinfo; + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + LARGE_INTEGER targetpos; + int i; + + if((actualcdmode < -1) || (actualcdmode > 2)) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz CD: CDreadTrack(%llu, %i)", lsn, actualcdmode); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(actualcdmode >= 0) { + rawinfo.DiskOffset.QuadPart = lsn * 2048; // Yes, 2048. + rawinfo.SectorCount = 1; + rawinfo.TrackMode = actualcdmode; + boolresult = DeviceIoControl(devicehandle, + IOCTL_CDROM_RAW_READ, + &rawinfo, + sizeof(RAW_READ_INFO), + buffer, + 2352, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz CD: Couldn't read a sector raw!"); + PrintError("CDVDlinuz CD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Couldn't read a raw sector? Maybe not a CD. + + } else { + targetpos.QuadPart = lsn * 2048; + waitevent.Offset = targetpos.LowPart; + waitevent.OffsetHigh = targetpos.HighPart; + + boolresult = ReadFile(devicehandle, + buffer + 24, + 2048, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz CD: Couldn't read a cooked sector!"); + PrintError("CDVDlinuz CD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Trouble with seek? Report it. + + for(i = 0; i < 24; i++) *(buffer + i) = 0; + for(i = 24 + 2048; i < 2352; i++) *(buffer + i) = 0; + } // ENDIF- Could we read a raw sector? Read another one! + + if(boolresult == FALSE) { + boolresult = GetOverlappedResult(devicehandle, + &waitevent, + &byteswritten, + FALSE); + } // ENDIF- Did the initial call not complete? Get byteswritten for + // the completed call. + + if(byteswritten < 2048) { +#ifdef VERBOSE_WARNING_DEVICE + errcode = GetLastError(); + PrintLog("CDVDlinuz CD: Short block! only got %u out of %u bytes", + byteswritten, cdblocksize); + PrintError("CDVDlinuz CD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Couldn't read a raw sector? Maybe not a CD. + + cdmode = mode; + cdblocksize = byteswritten; + return(0); +} // END CDreadTrackPass() + + +s32 CDreadTrack(u32 lsn, int mode, u8 *buffer) { + int retval; + int lastmode; + int i; + + retval = CDreadTrackPass(lsn, mode, buffer); + if(retval >= 0) return(retval); + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz CD: Same mode doesn't work. Scanning..."); +#endif /* VERBOSE_WARNING_DEVICE */ + + lastmode = actualcdmode; + actualcdmode = 2; + while(actualcdmode >= -1) { + retval = CDreadTrackPass(lsn, mode, buffer); + if(retval >= 0) return(retval); + actualcdmode--; + } // ENDWHILE- Searching each mode for a way to read the sector + actualcdmode = lastmode; // None worked? Go back to first mode. + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz CD: No modes work. Failing sector!"); +#endif /* VERBOSE_WARNING_DEVICE */ + + for(i = 0; i < 2352; i++) *(buffer + i) = 0; + return(-1); +} // END CDreadTrack() + + +s32 CDgetBufferOffset() { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVD CD: CDgetBufferOffset()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + // Send a whole CDDA record in? + if((actualcdmode == CDDA) && (cdmode == CDVD_MODE_2352)) return(0); + + // Otherwise, send the start of the data block in... + return(cdoffset); +} // END CDgetBufferOffset() + + +s32 CDreadSubQ() { + return(-1); +} // END CDreadSubQ() + + +s32 CDgetTN(cdvdTN *cdvdtn) { + cdvdtn->strack = BCDTOHEX(tocbuffer[7]); + cdvdtn->etrack = BCDTOHEX(tocbuffer[17]); + return(0); +} // END CDgetTN() + + +s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd) { + u8 actualtrack; + int pos; + char temptime[3]; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz CD: CDgetTD()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + actualtrack = newtrack; + if(actualtrack == 0xaa) actualtrack = 0; + + if(actualtrack == 0) { + cdvdtd->type = 0; + temptime[0] = BCDTOHEX(tocbuffer[27]); + temptime[1] = BCDTOHEX(tocbuffer[28]); + temptime[2] = BCDTOHEX(tocbuffer[29]); + cdvdtd->lsn = MSFtoLBA(temptime); + } else { + pos = actualtrack * 10; + pos += 30; + cdvdtd->type = tocbuffer[pos]; + temptime[0] = BCDTOHEX(tocbuffer[pos + 7]); + temptime[1] = BCDTOHEX(tocbuffer[pos + 8]); + temptime[2] = BCDTOHEX(tocbuffer[pos + 9]); + cdvdtd->lsn = MSFtoLBA(temptime); + } // ENDIF- Whole disc? (or single track?) + + return(0); +} // END CDgetTD() + + +s32 CDgetDiskType() { + CDROM_TOC cdinfo; + BOOL boolresult; + int retval; + DWORD byteswritten; + DWORD errcode; + u8 iso9660name[] = "CD001\0"; + u8 playstationname[] = "PLAYSTATION\0"; + u8 ps1name[] = "CD-XA001\0"; + u8 tempbuffer[2448]; + int tempdisctype; + int i; + int pos; + unsigned long volumesize; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz CD: CDgetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + tempdisctype = CDVD_TYPE_UNKNOWN; + + actualcdmode = 2; + retval = CDreadTrack(16, CDVD_MODE_2048, tempbuffer); + if(retval < 0) { + disctype = tempdisctype; + return(-1); + } // ENDIF- Couldn't read the directory sector? Abort. + + disctype = CDVD_TYPE_DETCTCD; + tempdisctype = CDVD_TYPE_CDDA; + + cdoffset = 0; + i = 0; + while((cdoffset <= 24) && (iso9660name[i] != 0)) { + i = 0; + while((iso9660name[i] != 0) && + (iso9660name[i] == tempbuffer[cdoffset + 1 + i])) i++; + if(iso9660name[i] != 0) cdoffset += 8; + } // ENDWHILE- Trying to find a working offset for a ISO9660 record. + + if(iso9660name[i] != 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("Detected a CDDA (Music CD)."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_CDDA; + tocbuffer[0] = 0x01; + + } else { + tocbuffer[0] = 0x41; + i = 0; + while((playstationname[i] != 0) && + (playstationname[i] == tempbuffer[cdoffset + 8 + i])) i++; + if(playstationname[i] != 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("Detected a non-Playstation CD."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_UNKNOWN; + + } else { + i = 0; + while((ps1name[i] != 0) && + (ps1name[i] == tempbuffer[cdoffset + 1024 + i])) i++; + if(ps1name[i] != 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("Detected a Playstation 2 CD."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2CD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("Detected a Playstation CD."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PSCD; + } // ENDIF- Is this not a PlayStation Disc? + } // ENDIF- Is this not a PlayStation Disc? + } // ENDIF- Is this not an ISO9660 CD? (a CDDA, in other words?) + + // Build the Fake TOC + tocbuffer[2] = 0xA0; + tocbuffer[7] = HEXTOBCD(1); // Starting Track + tocbuffer[12] = 0xA1; + tocbuffer[17] = HEXTOBCD(1); // Ending Track + + volumesize = tempbuffer[84]; // Volume size (big endian) + volumesize *= 256; + volumesize += tempbuffer[85]; + volumesize *= 256; + volumesize += tempbuffer[86]; + volumesize *= 256; + volumesize += tempbuffer[87]; +#ifdef VERBOSE_DISC_INFO + if(tempdisctype != CDVD_TYPE_CDDA) { + PrintLog("CDVDlinuz CD: ISO9660 size %llu", volumesize); + } // ENDIF- Data CD? Print size in blocks. +#endif /* VERBOSE_DISC_INFO */ + + LBAtoMSF(volumesize, &tocbuffer[27]); + tocbuffer[27] = HEXTOBCD(tocbuffer[27]); + tocbuffer[28] = HEXTOBCD(tocbuffer[28]); + tocbuffer[29] = HEXTOBCD(tocbuffer[29]); + + tocbuffer[40] = 0x02; // Data Mode + tocbuffer[42] = 0x01; // Track # + LBAtoMSF(0, &tocbuffer[47]); + tocbuffer[47] = HEXTOBCD(tocbuffer[47]); + tocbuffer[48] = HEXTOBCD(tocbuffer[48]); + tocbuffer[49] = HEXTOBCD(tocbuffer[49]); + + // Can we get the REAL TOC? + boolresult = DeviceIoControl(devicehandle, + IOCTL_CDROM_READ_TOC, + NULL, + 0, + &cdinfo, + sizeof(CDROM_TOC), + &byteswritten, + NULL); + + if(boolresult == FALSE) { +#ifdef VERBOSE_WARNING_DEVICE + errcode = GetLastError(); + PrintLog("CDVDlinuz CD: Can't get TOC!"); + PrintError("CDVDlinuz CD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + disctype = tempdisctype; + return(disctype); + } // ENDIF- Can't read the TOC? Accept the fake TOC then. + + // Fill in the pieces of the REAL TOC. +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVDlinuz CD: TOC First Track: %u Last Track: %u", + cdinfo.FirstTrack, cdinfo.LastTrack); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[7] = HEXTOBCD(cdinfo.FirstTrack); + tocbuffer[17] = HEXTOBCD(cdinfo.LastTrack); + + // for(i = cdinfo.FirstTrack; i <= cdinfo.LastTrack; i++) { + for(i = 0; i <= cdinfo.LastTrack - cdinfo.FirstTrack; i++) { +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVDlinuz CD: TOC Track %u Disc Size: %u:%u.%u Data Mode %u", + cdinfo.TrackData[i].TrackNumber, + cdinfo.TrackData[i].Address[1] * 1, + cdinfo.TrackData[i].Address[2] * 1, + cdinfo.TrackData[i].Address[3] * 1, + cdinfo.TrackData[i].Control * 1); +#endif /* VERBOSE_DISC_INFO */ + pos = i * 10 + 40; + tocbuffer[pos] = cdinfo.TrackData[i].Control; + tocbuffer[pos + 2] = HEXTOBCD(i + 1); + tocbuffer[pos + 7] = HEXTOBCD(cdinfo.TrackData[i].Address[1]); + tocbuffer[pos + 8] = HEXTOBCD(cdinfo.TrackData[i].Address[2]); + tocbuffer[pos + 9] = HEXTOBCD(cdinfo.TrackData[i].Address[3]); + } // NEXT i- Transferring Track data to the PS2 TOC + + +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVDlinuz CD: TOC Disc Size: %u:%u.%u", + cdinfo.TrackData[i].Address[1] * 1, + cdinfo.TrackData[i].Address[2] * 1, + cdinfo.TrackData[i].Address[3] * 1); +#endif /* VERBOSE_DISC_INFO */ + tocbuffer[27] = HEXTOBCD(cdinfo.TrackData[i].Address[1]); + tocbuffer[28] = HEXTOBCD(cdinfo.TrackData[i].Address[2]); + tocbuffer[29] = HEXTOBCD(cdinfo.TrackData[i].Address[3]); + + disctype = tempdisctype; + return(disctype); +} // END CDgetDiskType() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/CD.h b/plugins/cdvd/CDVDlinuz/Src/Win32/CD.h new file mode 100644 index 0000000..6bff6d8 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/CD.h @@ -0,0 +1,44 @@ +/* CD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CD_H +#define CD_H + + +#include // DWORD + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern DWORD cdblocksize; + + +extern void InitCDInfo(); +extern s32 CDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 CDgetBufferOffset(); +extern s32 CDreadSubQ(); +extern s32 CDgetTN(cdvdTN *cdvdtn); +extern s32 CDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 CDgetDiskType(); + + +#endif /* CD_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.c b/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.c new file mode 100644 index 0000000..a4ebc64 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.c @@ -0,0 +1,434 @@ +/* CDVDlinuz.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // BOOL, CALLBACK, APIENTRY +#include // NULL + +#include // time(), time_t + +#define CDVDdefs +#include "../PS2Edefs.h" + +#include "device.h" +#include "CD.h" +#include "DVD.h" +#include "../buffer.h" +#include "../convert.h" +#include "conf.h" +#include "logfile.h" +#include "../version.h" +#include "screens.h" +#include "mainbox.h" // Initialize mainboxwindow +#include "CDVDlinuz.h" + + +HINSTANCE progmodule; + + +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD param, + LPVOID reserved) { + + + switch(param) { + case DLL_PROCESS_ATTACH: + progmodule = hModule; + // mainboxwindow = NULL; + return(TRUE); + break; + case DLL_PROCESS_DETACH: + // CDVDshutdown(); + return(TRUE); + break; + case DLL_THREAD_ATTACH: + return(TRUE); + break; + case DLL_THREAD_DETACH: + return(TRUE); + break; + } // ENDSWITCH param- What does the OS want with us? + + return(FALSE); // Wasn't on list? Wasn't handled. +} // END DllMain() + + +char* CALLBACK PS2EgetLibName() { + return(libname); +} // END PS2EgetLibName() + + +u32 CALLBACK PS2EgetLibType() { + return(PS2E_LT_CDVD); +} // END PS2getLibType() + + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return((version << 16) | (revision << 8) | build); +} // END PS2EgetLibVersion2() + + +s32 CALLBACK CDVDinit() { + InitLog(); + if(OpenLog() != 0) return(-1); // Couldn't open Log File? Abort. + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDinit()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + InitConf(); + + DeviceInit(); + InitCDInfo(); + InitDVDInfo(); + + mainboxwindow = NULL; + + return(0); +} // END CDVDinit() + + +void CALLBACK CDVDshutdown() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDshutdown()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + DeviceClose(); + + // Close Windows as well? (Just in case) + + CloseLog(); +} // END CDVDshutdown() + + +s32 CALLBACK CDVDopen() { + int retval; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDopen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + InitBuffer(); + + LoadConf(); + + retval = DeviceOpen(); + if(retval == 0) { + DeviceTrayStatus(); + } // ENDIF- Did we open the device? Poll for media. + return(retval); +} // END CDVDopen() + + +void CALLBACK CDVDclose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDclose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + DeviceClose(); +} // END CDVDclose() + + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + char temptime[3]; + int i; + int pos; + u32 tracklsn; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDreadSubQ()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(DiscInserted() != 0) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(-1); // DVDs don't have SubQ data + } // ENDIF- Trying to get a SubQ from a DVD? + + // fake it + i = BCDTOHEX(tocbuffer[7]); + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(tocbuffer[pos + 7]); + temptime[1] = BCDTOHEX(tocbuffer[pos + 8]); + temptime[2] = BCDTOHEX(tocbuffer[pos + 9]); + tracklsn = MSFtoLBA(temptime); + while((i < BCDTOHEX(tocbuffer[17])) && (tracklsn < lsn)) { + i++; + pos = i * 10; + pos += 30; + temptime[0] = BCDTOHEX(tocbuffer[pos + 7]); + temptime[1] = BCDTOHEX(tocbuffer[pos + 8]); + temptime[2] = BCDTOHEX(tocbuffer[pos + 9]); + tracklsn = MSFtoLBA(temptime); + } // ENDIF- Loop through tracks searching for lsn track + i--; + + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = HEXTOBCD(i); + subq->trackIndex = HEXTOBCD(i); + + LBAtoMSF(lsn - tracklsn, temptime); + subq->trackM = HEXTOBCD(temptime[0]); + subq->trackS = HEXTOBCD(temptime[1]); + subq->trackF = HEXTOBCD(temptime[2]); + + subq->pad = 0; + + // lba_to_msf(lsn + (2*75), &min, &sec, &frm); + LBAtoMSF(lsn, temptime); + subq->discM = HEXTOBCD(temptime[0]); + subq->discS = HEXTOBCD(temptime[1]); + subq->discF = HEXTOBCD(temptime[2]); + return(0); +} // END CDVDreadSubQ() + + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetTN()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(DiscInserted() != 0) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + Buffer->strack = 1; + Buffer->etrack = 1; + } else { + Buffer->strack = BCDTOHEX(tocbuffer[7]); + Buffer->etrack = BCDTOHEX(tocbuffer[17]); + } // ENDIF- Retrieve track info from a DVD? (or a CD?) + + return(0); +} // END CDVDgetTN() + + +s32 CALLBACK CDVDgetTD(u8 track, cdvdTD *buffer) { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetTD()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + return(DeviceGetTD(track, buffer)); +} // END CDVDgetTD() + + +s32 CALLBACK CDVDgetTOC(void* toc) { + int i; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetTOC()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(DiscInserted() != 0) return(-1); + + for(i = 0; i < 2048; i++) *(((char *) toc) + i) = tocbuffer[i]; + return(0); +} // END CDVDgetTOC() + + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + int retval; + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDreadTrack(%u)", lsn); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(DiscInserted() == -1) return(-1); + + if(userbuffer < BUFFERMAX) { + if((bufferlist[userbuffer].lsn == lsn) && + (bufferlist[userbuffer].mode == mode)) { + return(0); + } // ENDIF- And it's the right one? + } // ENDIF- Are we already pointing at the buffer? + + userbuffer = FindListBuffer(lsn); + if(userbuffer < BUFFERMAX) { + if((bufferlist[userbuffer].lsn == lsn) && + (bufferlist[userbuffer].mode == mode)) { + return(0); + } // ENDIF- And it was the right one? + } // ENDIF- Was a buffer found in the cache? + + replacebuffer++; + if(replacebuffer >= BUFFERMAX) replacebuffer = 0; + userbuffer = replacebuffer; + + if(bufferlist[replacebuffer].upsort != 0xffff) { + RemoveListBuffer(replacebuffer); + } // ENDIF- Reference already in place? Remove it. + + retval = DeviceReadTrack(lsn, mode, bufferlist[replacebuffer].buffer); + bufferlist[replacebuffer].lsn = lsn; + bufferlist[replacebuffer].mode = mode; + bufferlist[replacebuffer].offset = DeviceBufferOffset(); + + if(retval != 0) { + bufferlist[replacebuffer].mode = -1; // Error! flag buffer as such. + } else { + if((disctype != CDVD_TYPE_PS2DVD) && (disctype != CDVD_TYPE_DVDV)) { + if(mode == CDVD_MODE_2352) { + CDreadSubQ(lsn, &bufferlist[replacebuffer].subq); + } // ENDIF- Read subq as well? + } // ENDIF- Read a DVD buffer or a CD buffer? + } // ENDIF-Read ok? Fill out rest of buffer info. + AddListBuffer(replacebuffer); + return(retval); +} // END CDVDreadTrack() + + +u8* CALLBACK CDVDgetBuffer() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetBuffer()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(DiscInserted() == -1) return(NULL); + + if(userbuffer == 0xffff) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVDlinuz interface: Not pointing to a buffer!"); +#endif /* VERBOSE_WARNINGS */ + return(NULL); // No buffer reference? + } // ENDIF- user buffer not pointing at anything? Abort + + if(bufferlist[userbuffer].mode < 0) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVDlinuz interface: Error retrieving sector (ReadTrack call)"); +#endif /* VERBOSE_WARNINGS */ + return(NULL); // Bad Sector? + } // ENDIF- Trouble reading physical sector? Tell them. + + return(bufferlist[userbuffer].buffer + bufferlist[userbuffer].offset); +} // END CDVDgetBuffer() + + +s32 CALLBACK CDVDgetDiskType() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(lasttime != time(NULL)) { + lasttime = time(NULL); + DeviceTrayStatus(); + } // ENDIF- Has enough time passed between calls? + + return(disctype); +} // END CDVDgetDiskType() + + +s32 CALLBACK CDVDgetTrayStatus() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDgetTrayStatus()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + if(lasttime != time(NULL)) { + lasttime = time(NULL); + DeviceTrayStatus(); + } // ENDIF- Has enough time passed between calls? + + return(traystatus); +} // END CDVDgetTrayStatus() + + +s32 CALLBACK CDVDctrlTrayOpen() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDctrlTrayOpen()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + return(DeviceTrayOpen()); +} // END CDVDctrlTrayOpen() + + +s32 CALLBACK CDVDctrlTrayClose() { +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDctrlTrayClose()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + return(DeviceTrayClose()); +} // END CDVDctrlTrayClose() + + +s32 CALLBACK CDVDtest() { + int retval; + + errno = 0; + + if(devicehandle != NULL) { +#ifdef VERBOSE_WARNINGS + PrintLog("CDVDlinuz interface: Device already open"); +#endif /* VERBOSE_WARNINGS */ + return(0); + } // ENDIF- Is the CD/DVD already in use? That's fine. + +#ifdef VERBOSE_FUNCTION_INTERFACE + PrintLog("CDVDlinuz interface: CDVDtest()"); +#endif /* VERBOSE_FUNCTION_INTERFACE */ + + retval = DeviceOpen(); + DeviceClose(); + return(retval); +} // END CDVDtest() + + +void CALLBACK CDVDconfigure() { + HWND lastwindow; + + lastwindow = GetActiveWindow(); + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0200), + lastwindow, + (DLGPROC)MainBoxCallback); + SetActiveWindow(lastwindow); + lastwindow = NULL; + return; +} // END CDVDconfigure() + + +BOOL CALLBACK AboutCallback(HWND window, UINT msg, WPARAM param, LPARAM param2) { + switch(msg) { + case WM_COMMAND: + switch(LOWORD(param)) { + case IDC_0104: // "Ok" Button + EndDialog(window, FALSE); + return(TRUE); + break; + } // ENDSWITCH param- Which Windows Message Command? + + case WM_CLOSE: + EndDialog(window, FALSE); + return(TRUE); + break; + } // ENDSWITCH msg- what message has been sent to this window? + + return(FALSE); // Not a recognisable message. Pass it back to the OS. +} // END AboutCallback() + +void CALLBACK CDVDabout() { + HWND lastwindow; + + lastwindow = GetActiveWindow(); + DialogBox(progmodule, + MAKEINTRESOURCE(DLG_0100), + lastwindow, + (DLGPROC)AboutCallback); + SetActiveWindow(lastwindow); + return; +} // END CDVDabout() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.h b/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.h new file mode 100644 index 0000000..e93973f --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/CDVDlinuz.h @@ -0,0 +1,40 @@ +/* CDVDlinuz.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CDVDLINUZ_H +#define CDVDLINUZ_H + + +#include // HINSTANCE + + +// #define VERBOSE_WARNINGS +// #define VERBOSE_FUNCTION_INTERFACE +#define VERBOSE_DISC_INFO +#define VERBOSE_DISC_TYPE + +#define READ_AHEAD_BUFFERS 32 + + +extern HINSTANCE progmodule; + + +#endif /* CDVDLINUZ_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.c b/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.c new file mode 100644 index 0000000..92854d6 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.c @@ -0,0 +1,398 @@ +/* DVD.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include // IOCTL_DVD... + +#include // off64_t + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" +#include "device.h" // FinishCommand() + + +struct { + DVD_DESCRIPTOR_HEADER h; + DVD_LAYER_DESCRIPTOR d; +} layer; +// DVD_LAYER_DESCRIPTOR layer; +// DVD_COPYRIGHT_DESCRIPTOR copyright; +// DVD_DISK_KEY_DESCRIPTOR disckey; +// DVD_BCA_DESCRIPTOR bca; +// DVD_MANUFACTURER_DESCRIPTOR manufact; + + +void InitDVDInfo() { + layer.d.EndDataSector = 0; +} // END InitDVDInfo() + + +s32 DVDGetStructures() { + DVD_SESSION_ID sessionid; + DVD_READ_STRUCTURE request; + DWORD byteswritten; + BOOL boolresult; + DWORD errcode; + s32 retval; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz DVD: DVDgetStructures()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_DVD_START_SESSION, + NULL, + 0, + &sessionid, + sizeof(DVD_SESSION_ID), + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz DVD: Couldn't start session!"); + PrintError("CDVDlinuz DVD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Couldn't start a user session on the DVD drive? Fail. + + request.BlockByteOffset.QuadPart = 0; + request.Format = DvdPhysicalDescriptor; + request.SessionId = sessionid; + request.LayerNumber = 0; + retval = 0; + boolresult = DeviceIoControl(devicehandle, + IOCTL_DVD_READ_STRUCTURE, + &request, + sizeof(DVD_READ_STRUCTURE), + &layer, + sizeof(layer), + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz DVD: Couldn't get layer data!"); + PrintError("CDVDlinuz DVD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + retval = -1; + } // ENDIF- Couldn't get layer data? (Including DVD size) Abort. + +#ifdef VERBOSE_DISC_INFO + switch(layer.d.BookType) { + case 0: + PrintLog("CDVDlinuz DVD: Book Type: DVD-ROM"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Book Type: DVD-RAM"); + break; + case 2: + PrintLog("CDVDlinuz DVD: Book Type: DVD-R"); + break; + case 3: + PrintLog("CDVDlinuz DVD: Book Type: DVD-RW"); + break; + case 9: + PrintLog("CDVDlinuz DVD: Book Type: DVD+RW"); + break; + default: + PrintLog("CDVDlinuz DVD: Book Type: Unknown (%i)", layer.d.BookType); + break; + } // ENDSWITCH- Displaying the Book Type + PrintLog("CDVDlinuz DVD: Book Version %i", layer.d.BookVersion); + switch(layer.d.MinimumRate) { + case 0: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: DVD-ROM"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: DVD-RAM"); + break; + case 2: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: DVD-R"); + break; + case 3: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: DVD-RW"); + break; + case 9: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: DVD+RW"); + break; + default: + PrintLog("CDVDlinuz DVD: Use Minimum Rate for: Unknown (%i)", layer.d.MinimumRate); + break; + } // ENDSWITCH- Displaying the Minimum (Spin?) Rate + switch(layer.d.DiskSize) { + case 0: + PrintLog("CDVDlinuz DVD: Physical Disk Size: 120mm"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Physical Disk Size: 80mm"); + break; + default: + PrintLog("CDVDlinuz DVD: Physical Disk Size: Unknown (%i)", layer.d.DiskSize); + break; + } // ENDSWITCH- What's the Disk Size? + switch(layer.d.LayerType) { + case 1: + PrintLog("CDVDlinuz DVD: Layer Type: Read-Only"); + break; + case 2: + PrintLog("CDVDlinuz DVD: Layer Type: Recordable"); + break; + case 4: + PrintLog("CDVDlinuz DVD: Layer Type: Rewritable"); + break; + default: + PrintLog("CDVDlinuz DVD: Layer Type: Unknown (%i)", layer.d.LayerType); + break; + } // ENDSWITCH- Displaying the Layer Type + switch(layer.d.TrackPath) { + case 0: + PrintLog("CDVDlinuz DVD: Track Path: PTP"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Track Path: OTP"); + break; + default: + PrintLog("CDVDlinuz DVD: Track Path: Unknown (%i)", layer.d.TrackPath); + break; + } // ENDSWITCH- What's Track Path Layout? + PrintLog("CDVDlinuz DVD: Number of Layers: %i", layer.d.NumberOfLayers + 1); + switch(layer.d.TrackDensity) { + case 0: + PrintLog("CDVDlinuz DVD: Track Density: .74 m/track"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Track Density: .8 m/track"); + break; + case 2: + PrintLog("CDVDlinuz DVD: Track Density: .615 m/track"); + break; + default: + PrintLog("CDVDlinuz DVD: Track Density: Unknown (%i)", layer.d.TrackDensity); + break; + } // ENDSWITCH- Displaying the Layer Type + switch(layer.d.LinearDensity) { + case 0: + PrintLog("CDVDlinuz DVD: Linear Density: .267 m/bit"); + break; + case 1: + PrintLog("CDVDlinuz DVD: Linear Density: .293 m/bit"); + break; + case 2: + PrintLog("CDVDlinuz DVD: Linear Density: .409 to .435 m/bit"); + break; + case 4: + PrintLog("CDVDlinuz DVD: Linear Density: .280 to .291 m/bit"); + break; + case 8: + PrintLog("CDVDlinuz DVD: Linear Density: .353 m/bit"); + break; + default: + PrintLog("CDVDlinuz DVD: Linear Density: Unknown (%i)", layer.d.LinearDensity); + break; + } // ENDSWITCH- Displaying the Book Type + if(layer.d.StartingDataSector == 0x30000) { + PrintLog("CDVDlinuz DVD: Starting Sector: %lu (DVD-ROM, DVD-R, DVD-RW)", + layer.d.StartingDataSector); + } else if(layer.d.StartingDataSector == 0x31000) { + PrintLog("CDVDlinuz DVD: Starting Sector: %lu (DVD-RAM, DVD+RW)", + layer.d.StartingDataSector); + } else { + PrintLog("CDVDlinuz DVD: Starting Sector: %lu", layer.d.StartingDataSector); + } // ENDLONGIF- What does the starting sector tell us? + PrintLog("CDVDlinuz DVD: End of Layer 0: %lu", layer.d.EndLayerZeroSector); + PrintLog("CDVDlinuz DVD: Ending Sector: %lu", layer.d.EndDataSector); + if(layer.d.BCAFlag != 0) PrintLog("CDVDlinuz DVD: BCA data present"); +#endif /* VERBOSE_DISC_INFO */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_DVD_END_SESSION, + &sessionid, + sizeof(DVD_SESSION_ID), + NULL, + 0, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz DVD: Couldn't end the session!"); + PrintError("CDVDlinuz DVD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + } // ENDIF- Couldn't end the user session? Report it. + + return(retval); +} // END DVDGetStructures() + + +s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer) { + LARGE_INTEGER targetpos; + DWORD byteswritten; + BOOL boolresult; + DWORD errcode; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz DVD: DVDreadTrack(%lu)", lsn); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + targetpos.QuadPart = lsn * 2048; + waitevent.Offset = targetpos.LowPart; + waitevent.OffsetHigh = targetpos.HighPart; + + boolresult = ReadFile(devicehandle, + buffer, + 2048, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz DVD: Couldn't read sector!"); + PrintError("CDVDlinuz DVD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Trouble with the command? Report it. + + if(boolresult == FALSE) { + boolresult = GetOverlappedResult(devicehandle, + &waitevent, + &byteswritten, + FALSE); + } // ENDIF- Did the initial call not complete? Get byteswritten for + // the completed call. + + if(byteswritten < 2048) { +#ifdef VERBOSE_WARNING_DEVICE + errcode = GetLastError(); + PrintLog("CDVDlinuz CD: Short block! only got %u out of %u bytes", + byteswritten, 2048); + PrintError("CDVDlinuz CD", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Didn't get enough bytes? Report and Abort! + + return(0); +} // END DVDreadTrack() + + +s32 DVDgetTN(cdvdTN *cdvdtn) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz DVD: DVDgetTN()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(cdvdtn != NULL) { + cdvdtn->strack = 1; + cdvdtn->etrack = 1; + } // ENDIF- Does the user really want this data? + return(0); +} // END DVDgetTN() + + +s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz DVD: DVDgetTD()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if((newtrack >= 2) && (newtrack != 0xAA)) return(-1); // Wrong track + + if(cdvdtd != NULL) { + cdvdtd->type = 0; + cdvdtd->lsn = layer.d.EndDataSector - layer.d.StartingDataSector + 1; + } // ENDIF- Does the user really want this data? + return(0); +} // END DVDgetTD() + + +s32 DVDgetDiskType() { + char playstationname[] = "PLAYSTATION\0"; + int retval; + s32 tempdisctype; + char tempbuffer[2048]; + int i; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz DVD: DVDgetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + retval = DVDGetStructures(); + if(retval < 0) return(-1); // Can't get DVD structures? Not a DVD then. + if(layer.d.EndDataSector == 0) return(-1); // Missing info? Abort. + + retval = DVDreadTrack(16, CDVD_MODE_2048, tempbuffer); + if(retval < 0) { + return(-1); + } // ENDIF- Couldn't read the ISO9660 volume track? Fail. + + tempdisctype = CDVD_TYPE_UNKNOWN; + if(layer.d.NumberOfLayers == 0) { +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVDlinuz DVD: Found Single-Sided DVD."); +#endif /* VERBOSE_DISC_INFO */ + disctype = CDVD_TYPE_DETCTDVDS; + } else { +#ifdef VERBOSE_DISC_INFO + PrintLog("CDVDlinuz DVD: Found Dual-Sided DVD."); +#endif /* VERBOSE_DISC_INFO */ + disctype = CDVD_TYPE_DETCTDVDD; + } // ENDIF- Are we looking at a single layer DVD? (NumberOfLayers + 1) + + i = 0; + while((playstationname[i] != 0) && + (playstationname[i] == tempbuffer[8 + i])) i++; + if(playstationname[i] == 0) { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVDlinuz DVD: Found Playstation 2 DVD."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_PS2DVD; + } else { +#ifdef VERBOSE_DISC_TYPE + PrintLog("CDVDlinuz DVD: Guessing it's a Video DVD."); +#endif /* VERBOSE_DISC_TYPE */ + tempdisctype = CDVD_TYPE_DVDV; + } // ENDIF- Is this a playstation disc? + + for(i = 0; i < 2048; i++) tocbuffer[i] = 0; + + if(layer.d.NumberOfLayers == 0) { + tocbuffer[0] = 0x04; + tocbuffer[4] = 0x86; + tocbuffer[5] = 0x72; + } else { + tocbuffer[0] = 0x24; + tocbuffer[4] = 0x41; + tocbuffer[5] = 0x95; + } // ENDIF- Are we looking at a single layer DVD? (NumberOfLayers + 1) + + tocbuffer[1] = 0x02; + tocbuffer[2] = 0xF2; + tocbuffer[3] = 0x00; + + tocbuffer[16] = 0x00; + tocbuffer[17] = 0x03; + tocbuffer[18] = 0x00; + tocbuffer[19] = 0x00; + + disctype = tempdisctype; + return(disctype); +} // END DVDgetDiskType() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.h b/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.h new file mode 100644 index 0000000..3876101 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/DVD.h @@ -0,0 +1,37 @@ +/* DVD.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef DVD_H +#define DVD_H + + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern void InitDVDInfo(); +extern s32 DVDreadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DVDgetTN(cdvdTN *cdvdtn); +extern s32 DVDgetTD(u8 newtrack, cdvdTD *cdvdtd); +extern s32 DVDgetDiskType(); + + +#endif /* DVD_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/Makefile.MinGW32 b/plugins/cdvd/CDVDlinuz/Src/Win32/Makefile.MinGW32 new file mode 100644 index 0000000..f3cf50c --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/Makefile.MinGW32 @@ -0,0 +1,43 @@ + +PLUGIN = CDVDlinuz.dll +PLUGINOBJS = CDVDlinuz.o mainbox.o +PLUGINHEADERS = CDVDlinuz.h mainbox.h +PLUGINFLAGS = -Wall -O2 -D_LARGEFILE64_SOURCE -I.. -I. -I.\\Win32 +PLUGINLIBS = + +# In this case, SHARED marks files that don't need Windows Display components +SHAREDOBJS = device.o CD.o DVD.o logfile.o actualfile.o conf.o \ + ..\\ini.o ..\\buffer.o ..\\version.o ..\\convert.o +SHAREDHEADERS = device.h CD.h DVD.h logfile.h actualfile.h conf.h \ + ..\\ini.h ..\\buffer.h ..\\version.h ..\\convert.h + + +CC = mingw32-gcc.exe +WINDRES = windres.exe + + +all: plugin + +release: plugin + copy $(PLUGIN) ..\\.. + +plugin: $(PLUGINOBJS) $(SHAREDOBJS) screens.res + -del $(PLUGIN) + dllwrap --def plugin.def -o $(PLUGIN) $(PLUGINOBJS) screens.res $(SHAREDOBJS) $(PLUGINLIBS) + strip --strip-unneeded --strip-debug $(PLUGIN) + +$(PLUGINOBJS) $(SHAREDOBJS): %.o: %.c + $(CC) $(PLUGINFLAGS) -c $< -o $@ + +screens.res: screens.rc + $(WINDRES) -i screens.rc -J rc -o screens.res -O coff + +.PHONY : clean allclean +clean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + +allclean: + -del $(PLUGINOBJS) $(PLUGIN) $(SHAREDOBJS) screens.res + -del temp.txt err.txt ..\\temp.txt ..\\err.txt + -del ..\\..\\$(PLUGIN) + diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.c b/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.c new file mode 100644 index 0000000..b2a5f23 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.c @@ -0,0 +1,253 @@ +/* actualfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include + +#include // NULL + +#include "logfile.h" +#include "actualfile.h" + + +int IsActualFile(const char *filename) { + DWORD retval; + + if(filename == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: IsActualFile(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + retval = GetFileAttributes(filename); + if(retval == INVALID_FILE_ATTRIBUTES) return(-1); // Name doesn't exist. + if((retval & FILE_ATTRIBUTE_DIRECTORY) != 0) return(-2); + + return(0); // Yep, that's a file. +} // END IsActualFile() + + +void ActualFileDelete(const char *filename) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileDelete(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + DeleteFile(filename); +} // END ActualFileDelete() + + +void ActualFileRename(const char *origname, const char *newname) { +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileDelete(%s->%s)", origname, newname); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + MoveFile(origname, newname); + return; +} // END ActualFileRename() + + +ACTUALHANDLE ActualFileOpenForRead(const char *filename) { + HANDLE newhandle; + + if(filename == NULL) return(NULL); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForRead(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + newhandle = CreateFile(filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_RANDOM_ACCESS, + NULL); + if(newhandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s", filename); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(NULL); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForRead() + + +off64_t ActualFileSize(ACTUALHANDLE handle) { + int retval; + BY_HANDLE_FILE_INFORMATION info; + off64_t retsize; + + if(handle == NULL) return(-1); + if(handle == INVALID_HANDLE_VALUE) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSize()"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + retval = GetFileInformationByHandle(handle, &info); + if(retval == 0) return(-1); // Handle doesn't exist... + + retsize = info.nFileSizeHigh; + retsize *= 0x10000; + retsize *= 0x10000; + retsize += info.nFileSizeLow; + return(retsize); +} // END ActualFileSize() + + +int ActualFileSeek(ACTUALHANDLE handle, off64_t position) { + // int retval; + LARGE_INTEGER realpos; + DWORD errcode; + + if(handle == NULL) return(-1); + if(handle == INVALID_HANDLE_VALUE) return(-1); + if(position < 0) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileSeek(%llu)", position); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + realpos.QuadPart = position; +////// WinXP code for seek +// retval = SetFilePointerEx(handle, +// realpos, +// NULL, +// FILE_BEGIN); +// if(retval == 0) { + +////// Win98 code for seek + realpos.LowPart = SetFilePointer(handle, + realpos.LowPart, + &realpos.HighPart, + FILE_BEGIN); + errcode = GetLastError(); + if((realpos.LowPart == 0xFFFFFFFF) && (errcode != NO_ERROR)) { + +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error on seek (%llu)", position); + PrintError("CDVDiso file", errcode); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + + return(0); +} // END ActualFileSeek() + + +int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + DWORD bytesread; +#ifdef VERBOSE_WARNING_ACTUALFILE + DWORD errcode; +#endif /* VERBOSE_WARNING_ACTUALFILE */ + + if(handle == NULL) return(-1); + if(handle == INVALID_HANDLE_VALUE) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileRead(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + retval = ReadFile(handle, buffer, bytes, &bytesread, NULL); + if(retval == 0) { +#ifdef VERBOSE_WARNING_ACTUALFILE + errcode = GetLastError(); + PrintLog("CDVDiso file: Error reading from file"); + PrintError("CDVDiso file", errcode); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(-1); + } // ENDIF- Error? Abort + if(bytesread < bytes) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Short Block! Only read %i out of %i bytes", bytesread, bytes); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + } // ENDIF- Error? Abort + + return(bytesread); // Send back how many bytes read +} // END ActualFileRead() + + +void ActualFileClose(ACTUALHANDLE handle) { + if(handle == NULL) return; + if(handle == INVALID_HANDLE_VALUE) return; + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileClose()"); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + CloseHandle(handle); + return; +} // END ActualFileClose() + + +ACTUALHANDLE ActualFileOpenForWrite(const char *filename) { + HANDLE newhandle; + + if(filename == NULL) return(NULL); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileOpenForWrite(%s)", filename); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + newhandle = CreateFile(filename, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(newhandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error opening file %s", filename); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + return(NULL); + } // ENDIF- Error? Abort + + return(newhandle); +} // END ActualFileOpenForWrite() + + +int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer) { + int retval; + DWORD byteswritten; + + if(handle == NULL) return(-1); + if(handle == INVALID_HANDLE_VALUE) return(-1); + if(bytes < 1) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_ACTUALFILE + PrintLog("CDVDiso file: ActualFileWrite(%i)", bytes); +#endif /* VERBOSE_FUNCTION_ACTUALFILE */ + + retval = WriteFile(handle, buffer, bytes, &byteswritten, NULL); + if(retval == 0) { +#ifdef VERBOSE_WARNING_ACTUALFILE + PrintLog("CDVDiso file: Error writing to file!"); +#endif /* VERBOSE_WARNING_ACTUALFILE */ + // return(-1); + } // ENDIF- Error? Abort + + return(byteswritten); // Send back how many bytes written +} // END ActualFileWrite() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.h b/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.h new file mode 100644 index 0000000..6c215f3 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/actualfile.h @@ -0,0 +1,52 @@ +/* actualfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef ACTUALFILE_H +#define ACTUALFILE_H + + +#include + +#include // off64_t + + +#define ACTUALHANDLE HANDLE +#define ACTUALHANDLENULL NULL + +// #define VERBOSE_FUNCTION_ACTUALFILE +// #define VERBOSE_WARNING_ACTUALFILE + + +extern int IsActualFile(const char *filename); +extern void ActualFileDelete(const char *filename); +extern void ActualFileRename(const char *origname, const char *newname); + +extern ACTUALHANDLE ActualFileOpenForRead(const char *filename); +extern off64_t ActualFileSize(ACTUALHANDLE handle); +extern int ActualFileSeek(ACTUALHANDLE handle, off64_t position); +extern int ActualFileRead(ACTUALHANDLE handle, int bytes, char *buffer); +extern void ActualFileClose(ACTUALHANDLE handle); + +extern ACTUALHANDLE ActualFileOpenForWrite(const char *filename); +extern int ActualFileWrite(ACTUALHANDLE handle, int bytes, char *buffer); + + +#endif /* ACTUALFILE_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/conf.c b/plugins/cdvd/CDVDlinuz/Src/Win32/conf.c new file mode 100644 index 0000000..1fe4467 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/conf.c @@ -0,0 +1,175 @@ +/* conf.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#include // errno +#include // NULL +#include // sprintf() +#include // getenv() +#include // strerror() +#include // mkdir(), stat() +#include // mkdir(), stat(), fork() +#include // stat(), fork(), execlp() + +#include // CreateProcess() + +// #define CDVDdefs +// #include "../PS2Edefs.h" +#include "../PS2Etypes.h" // u8 +#include "logfile.h" +#include "../ini.h" +#include "conf.h" + + +const char *confnames[] = { "Device", NULL }; +const u8 defaultdevice[] = DEFAULT_DEVICE; +const char defaulthome[] = "inis"; +const char defaultdirectory[] = "HideMe.PS2E"; +const char defaultfile[] = "CDVDlinuz.ini"; + +char confdirname[256]; +char conffilename[256]; + +CDVDconf conf; + + +void InitConf() { + DWORD retval; + int i; + int pos; + char *envptr; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: InitConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + i = 0; + while((i < 255) && defaultdevice[i] != 0) { + conf.devicename[i] = defaultdevice[i]; + i++; + } // ENDWHILE- copying the default CD/DVD name in + conf.devicename[i] = 0; // 0-terminate the device name + + // Locating directory and file positions + pos = 0; + envptr = NULL; + // envptr = getenv("HOME"); + if(envptr == NULL) { + // = + retval = GetCurrentDirectory(253, confdirname); + if(retval > 0) { + pos = retval; + } else { + pos = 2; + confdirname[0] = '.'; + confdirname[1] = '\\'; + } // ENDIF- Did we retrieve a directory reference? + + i = 0; + while(i < pos) { + conffilename[i] = confdirname[i]; + i++; + } // ENDWHILE- Copying dir info (so far) into file info + + if(confdirname[pos-1] != '\\') { + confdirname[pos] = '\\'; + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaulthome[i] != 0)) { + confdirname[pos] = defaulthome[i]; + conffilename[pos] = defaulthome[i]; + pos++; + i++; + } // ENDWHILE- putting an offset where to store ini data + + } else { + // = / + i = 0; + while((pos < 253) && (*(envptr + i) != 0)) { + confdirname[pos] = *(envptr + i); + conffilename[pos] = *(envptr + i); + pos++; + i++; + } // ENDWHILE- copying home directory info in + + if(confdirname[pos-1] != '\\') { + confdirname[pos] = '\\'; + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultdirectory[i] != 0)) { + confdirname[pos] = defaultdirectory[i]; + conffilename[pos] = defaultdirectory[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + } // ENDIF- No Home directory? + + confdirname[pos] = 0; // Directory reference finished + + // += / + if(conffilename[pos-1] != '\\') { + conffilename[pos] = '\\'; + pos++; + } // ENDIF- No directory separator here? Add one. + + i = 0; + while((pos < 253) && (defaultfile[i] != 0)) { + conffilename[pos] = defaultfile[i]; + pos++; + i++; + } // NEXT- putting a default place to store configuration data + + conffilename[pos] = 0; // File reference finished + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: Directory: %s", confdirname); + PrintLog("CDVD config: File: %s", conffilename); +#endif /* VERBOSE_FUNCTION_CONF */ +} // END InitConf() + + +void LoadConf() { + int retval; + +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: LoadConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + retval = INILoadString(conffilename, "Settings", "Device", conf.devicename); + if(retval < 0) { + sprintf(conf.devicename, "D:"); + } // ENDIF- Couldn't find keyword? Fill in a default +} // END LoadConf() + + +void SaveConf() { +#ifdef VERBOSE_FUNCTION_CONF + PrintLog("CDVD config: SaveConf()"); +#endif /* VERBOSE_FUNCTION_CONF */ + + mkdir(confdirname); + + INISaveString(conffilename, "Settings", "Device", conf.devicename); +} // END SaveConf() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/conf.h b/plugins/cdvd/CDVDlinuz/Src/Win32/conf.h new file mode 100644 index 0000000..406ed03 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/conf.h @@ -0,0 +1,49 @@ +/* conf.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef CONF_H +#define CONF_H + + +#define CDVDdefs +#include "../PS2Edefs.h" + + +#define VERBOSE_FUNCTION_CONF + + +// Configuration Data + +typedef struct { + u8 devicename[256]; +} CDVDconf; +extern CDVDconf conf; + +#define DEFAULT_DEVICE "K:\\" + + +// Configuration Functions + +extern void InitConf(); +extern void LoadConf(); +extern void SaveConf(); + + +#endif /* CONF_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/device.c b/plugins/cdvd/CDVDlinuz/Src/Win32/device.c new file mode 100644 index 0000000..527c142 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/device.c @@ -0,0 +1,583 @@ +/* device.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include // IOCTL_CDROM..., IOCTL_STORAGE... +#include // IOCTL_DISK... +#include // sprintf() +#include // time_t + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" +#include "conf.h" +#include "CD.h" +#include "DVD.h" +#include "device.h" + + +HANDLE devicehandle; +OVERLAPPED waitevent; + +time_t lasttime; +s32 traystatus; +int traystatusmethod; +s32 disctype; +char tocbuffer[2048]; + + +void DeviceInit() { + devicehandle = NULL; + waitevent.hEvent = NULL; + waitevent.Internal = 0; + waitevent.InternalHigh = 0; + waitevent.Offset = 0; + waitevent.OffsetHigh = 0; + lasttime = 0; + + InitDisc(); +} // END DeviceInit() + + +void InitDisc() { + int i; + + InitCDInfo(); + InitDVDInfo(); + traystatus = CDVD_TRAY_OPEN; + traystatusmethod = 0; // Poll all until one works + disctype = CDVD_TYPE_NODISC; + for(i = 0; i < 2048; i++) tocbuffer[i] = 0; +} // END InitDisc() + + +s32 DiscInserted() { + if(traystatus != CDVD_TRAY_CLOSE) return(-1); + + if(disctype == CDVD_TYPE_ILLEGAL) return(-1); + // if(disctype == CDVD_TYPE_UNKNOWN) return(-1); // Hmm. Let this one through? + if(disctype == CDVD_TYPE_DETCTDVDD) return(-1); + if(disctype == CDVD_TYPE_DETCTDVDS) return(-1); + if(disctype == CDVD_TYPE_DETCTCD) return(-1); + if(disctype == CDVD_TYPE_DETCT) return(-1); + if(disctype == CDVD_TYPE_NODISC) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DiscInserted()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + return(0); +} // END DiscInserted() + + +// Returns errcode (or 0 if successful) +DWORD FinishCommand(BOOL boolresult) { + DWORD errcode; + DWORD waitcode; + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: FinishCommand()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(boolresult == TRUE) { + ResetEvent(waitevent.hEvent); + return(0); + } // ENDIF- Device is ready? Say so. + + errcode = GetLastError(); + if(errcode == ERROR_IO_PENDING) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: Waiting for completion."); +#endif /* VERBOSE_FUNCTION_DEVICE */ + waitcode = WaitForSingleObject(waitevent.hEvent, 10 * 1000); // 10 sec wait + if((waitcode == WAIT_FAILED) || (waitcode == WAIT_ABANDONED)) { + errcode = GetLastError(); + } else if(waitcode == WAIT_TIMEOUT) { + errcode = 21; + CancelIo(devicehandle); // Speculative Line + } else { + ResetEvent(waitevent.hEvent); + return(0); // Success! + } // ENDIF- Trouble waiting? (Or doesn't finish in 5 seconds?) + } // ENDIF- Should we wait for the call to finish? + + ResetEvent(waitevent.hEvent); + return(errcode); +} // END DeviceCommand() + + +s32 DeviceOpen() { + char tempname[256]; + UINT drivetype; + DWORD errcode; + + if(conf.devicename[0] == 0) return(-1); + + if(devicehandle != NULL) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceOpen()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + // InitConf(); + // LoadConf(); // Should be done at least once before this call + + // Root Directory reference + if(conf.devicename[1] == 0) { + sprintf(tempname, "%s:\\", conf.devicename); + } else if((conf.devicename[1] == ':') && (conf.devicename[2] == 0)) { + sprintf(tempname, "%s\\", conf.devicename); + } else { + sprintf(tempname, "%s", conf.devicename); + } // ENDIF- Not a single drive letter? (or a letter/colon?) Copy the name in. + + drivetype = GetDriveType(tempname); + if(drivetype != DRIVE_CDROM) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Not a CD-ROM!"); + PrintLog("CDVDlinuz device: (Came back: %u)", drivetype); + errcode = GetLastError(); + if(errcode > 0) PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Not a CD-ROM? Say so! + // Hmm. Do we want to include DRIVE_REMOVABLE... just in case? + + // Device Reference + if(conf.devicename[1] == 0) { + sprintf(tempname, "\\\\.\\%s:", conf.devicename); + } else if((conf.devicename[1] == ':') && (conf.devicename[2] == 0)) { + sprintf(tempname, "\\\\.\\%s", conf.devicename); + } else { + sprintf(tempname, "%s", conf.devicename); + } // ENDIF- Not a single drive letter? (or a letter/colon?) Copy the name in. + + devicehandle = CreateFile(tempname, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + + if(devicehandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Couldn't open device read-only! Read-Write perhaps?"); + errcode = GetLastError(); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + devicehandle = CreateFile(tempname, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + } // ENDIF- Couldn't open for read? Try read/write (for those drives that insist) + + if(devicehandle == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Couldn't open device!"); + errcode = GetLastError(); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + devicehandle = NULL; + return(-1); + } // ENDIF- Couldn't open that way either? Abort. + + waitevent.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if(waitevent.hEvent == INVALID_HANDLE_VALUE) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Couldn't open event handler!"); + errcode = GetLastError(); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + waitevent.hEvent = NULL; + CloseHandle(devicehandle); + devicehandle = NULL; + } // ENDIF- Couldn't create an "Wait for I/O" handle? Abort. + + // More here... DeviceIoControl? for Drive Capabilities + // DEVICE_CAPABILITIES? + + ////// Should be done just after the first DeviceOpen(); + // InitDisc(); // ? + // DeviceTrayStatus(); + + return(0); +} // END DeviceOpen() + + +void DeviceClose() { + if(devicehandle == NULL) return; + + if(devicehandle == INVALID_HANDLE_VALUE) { + devicehandle = NULL; + return; + } // ENDIF- Bad value? Just clear the value. + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceClose()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + if(waitevent.hEvent != NULL) { + if(waitevent.hEvent != INVALID_HANDLE_VALUE) { + CancelIo(devicehandle); + CloseHandle(waitevent.hEvent); + } // ENDIF- Is this handle actually open? + waitevent.hEvent = NULL; + waitevent.Offset = 0; + waitevent.OffsetHigh = 0; + } // ENDIF- Reset the event handle? + + CloseHandle(devicehandle); + devicehandle = NULL; + return; +} // END DeviceClose() + + +s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDreadTrack(lsn, mode, buffer)); + } else { + return(CDreadTrack(lsn, mode, buffer)); + } // ENDIF- Is this a DVD? +} // END DeviceReadTrack() + + +s32 DeviceBufferOffset() { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(0); + } else { + return(CDgetBufferOffset()); + } // ENDIF- Is this a DVD? + + return(-1); +} // END DeviceBufferOffset() + + +s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd) { + if(DiscInserted() == -1) return(-1); + + if((disctype == CDVD_TYPE_PS2DVD) || (disctype == CDVD_TYPE_DVDV)) { + return(DVDgetTD(track, cdvdtd)); + } else { + return(CDgetTD(track, cdvdtd)); + } // ENDIF- Is this a DVD? + + return(-1); +} // END DeviceGetTD() + + +s32 DeviceGetDiskType() { + s32 s32result; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_OPEN) return(disctype); + + if(disctype != CDVD_TYPE_NODISC) return(disctype); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceGetDiskType()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + disctype = CDVD_TYPE_DETCT; + + s32result = DVDgetDiskType(); + if(s32result != -1) return(disctype); + + s32result = CDgetDiskType(); + if(s32result != -1) return(disctype); + + disctype = CDVD_TYPE_UNKNOWN; + return(disctype); +} // END DeviceGetDiskType() + + +BOOL DeviceTrayStatusStorage() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = FinishCommand(boolresult); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Trouble detecting drive status (STORAGE)!"); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusStorage() + + +BOOL DeviceTrayStatusCDRom() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + boolresult = DeviceIoControl(devicehandle, + IOCTL_CDROM_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = FinishCommand(boolresult); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Trouble detecting drive status (CDROM)!"); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusCDRom() + + +BOOL DeviceTrayStatusDisk() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + boolresult = DeviceIoControl(devicehandle, + IOCTL_DISK_CHECK_VERIFY, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = FinishCommand(boolresult); + + if(errcode == 0) return(TRUE); + if(errcode == 21) return(FALSE); // Device not ready? (Valid error) + +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Trouble detecting drive status (DISK)!"); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + return(FALSE); +} // END DeviceTrayStatusDisk() + + +s32 DeviceTrayStatus() { + BOOL boolresult; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceTrayStatus()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + switch(traystatusmethod) { + case 1: + boolresult = DeviceTrayStatusStorage(); + break; + case 2: + boolresult = DeviceTrayStatusCDRom(); + break; + case 3: + boolresult = DeviceTrayStatusDisk(); + break; + default: + boolresult = FALSE; + break; + } // ENDSWITCH traystatusmethod- One method already working? Try it again. + + if(boolresult == FALSE) { + traystatusmethod = 0; + boolresult = DeviceTrayStatusStorage(); + if(boolresult == TRUE) { + traystatusmethod = 1; + } else { + boolresult = DeviceTrayStatusCDRom(); + if(boolresult == TRUE) { + traystatusmethod = 2; + } else { + boolresult = DeviceTrayStatusDisk(); + if(boolresult == TRUE) traystatusmethod = 3; + } // ENDIF- Did we succeed with CDRom? + } // ENDIF- Did we succeed with Storage? + } // Single call to already working test just failed? Test them all. + + if(boolresult == FALSE) { + if(traystatus == CDVD_TRAY_CLOSE) { +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: Tray just opened!"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + traystatus = CDVD_TRAY_OPEN; + DeviceClose(); + DeviceOpen(); + InitDisc(); + } // ENDIF- Just opened? clear disc info + return(traystatus); + } // ENDIF- Still failed? Assume no disc in drive then. + + if(traystatus == CDVD_TRAY_OPEN) { + traystatus = CDVD_TRAY_CLOSE; +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: Tray just closed!"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + DeviceGetDiskType(); + return(traystatus); + } // ENDIF- Just closed? Get disc information + + return(traystatus); +} // END DeviceTrayStatus() + + +s32 DeviceTrayOpen() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_OPEN) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceOpenTray()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_EJECT_MEDIA, + NULL, + 0, + NULL, + 0, + &byteswritten, + &waitevent); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Couldn't signal media to eject! (STORAGE)"); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ + +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_DISK_EJECT_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- Storage Call failed? Try Disk call. + +// if(boolresult == FALSE) { +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDlinuz device: Couldn't signal media to eject! (DISK)"); +// PrintError("CDVDlinuz device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Disk Call failed as well? Give it up. + + return(0); +} // END DeviceTrayOpen() + + +s32 DeviceTrayClose() { + BOOL boolresult; + DWORD byteswritten; + DWORD errcode; + + if(devicehandle == NULL) return(-1); + if(devicehandle == INVALID_HANDLE_VALUE) return(-1); + + if(traystatus == CDVD_TRAY_CLOSE) return(0); + +#ifdef VERBOSE_FUNCTION_DEVICE + PrintLog("CDVDlinuz device: DeviceCloseTray()"); +#endif /* VERBOSE_FUNCTION_DEVICE */ + + boolresult = DeviceIoControl(devicehandle, + IOCTL_STORAGE_LOAD_MEDIA, + NULL, + 0, + NULL, + 0, + &byteswritten, + NULL); + errcode = FinishCommand(boolresult); + + if(errcode != 0) { +#ifdef VERBOSE_WARNING_DEVICE + PrintLog("CDVDlinuz device: Couldn't signal media to load! (STORAGE)"); + PrintError("CDVDlinuz device", errcode); +#endif /* VERBOSE_WARNING_DEVICE */ +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_CDROM_LOAD_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- Storage call failed. CDRom call? + +// if(boolresult == FALSE) { +// errcode = GetLastError(); +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDlinuz device: Couldn't signal media to load! (CDROM)"); +// PrintError("CDVDlinuz device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ +// boolresult = DeviceIoControl(devicehandle, +// IOCTL_DISK_LOAD_MEDIA, +// NULL, +// 0, +// NULL, +// 0, +// &byteswritten, +// NULL); +// } // ENDIF- CDRom call failed. Disk call? + +// if(boolresult == FALSE) { +// #ifdef VERBOSE_WARNING_DEVICE +// PrintLog("CDVDlinuz device: Couldn't signal media to load! (DISK)"); +// PrintError("CDVDlinuz device", errcode); +// #endif /* VERBOSE_WARNING_DEVICE */ + return(-1); + } // ENDIF- Media not available? + + return(0); +} // END DeviceTrayClose() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/device.h b/plugins/cdvd/CDVDlinuz/Src/Win32/device.h new file mode 100644 index 0000000..608f13d --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/device.h @@ -0,0 +1,64 @@ +/* device.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + + +#include // BOOL, DWORD + +#include // time_t + +#define CDVDdefs +#include "../PS2Edefs.h" + + +// #define VERBOSE_FUNCTION_DEVICE +// #define VERBOSE_WARNING_DEVICE +#define VERBOSE_DISC_TYPE +#define VERBOSE_DISC_INFO + + +extern HANDLE devicehandle; +extern OVERLAPPED waitevent; + +extern time_t lasttime; +extern s32 traystatus; +extern s32 disctype; +extern char tocbuffer[]; + + +extern void DeviceInit(); +extern void InitDisc(); +extern s32 DiscInserted(); +extern DWORD FinishCommand(BOOL boolresult); + +extern s32 DeviceOpen(); +extern void DeviceClose(); +extern s32 DeviceReadTrack(u32 lsn, int mode, u8 *buffer); +extern s32 DeviceBufferOffset(); +extern s32 DeviceGetTD(u8 track, cdvdTD *cdvdtd); +extern s32 DeviceGetDiskType(); +extern s32 DeviceTrayStatus(); +extern s32 DeviceTrayOpen(); +extern s32 DeviceTrayClose(); + + +#endif /* __DEVICE_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.c b/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.c new file mode 100644 index 0000000..28f82eb --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.c @@ -0,0 +1,119 @@ +/* logfile.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include + +// #include // open() +// #include // mkdir() +#include // NULL +#include // vsprintf() +#include // va_start(), va_end(), vsprintf() +// #include // open() +// #include // open() + +#include "logfile.h" + + +HANDLE logfile; +char logfiletemp[2048]; + + +void InitLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + CreateDirectory("logs", NULL); + + DeleteFile("logs\\CDVDlog.txt"); + logfile = NULL; +#endif /* VERBOSE LOGFILE */ +} // END InitLog(); + + +int OpenLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + logfile = CreateFile("logs\\CDVDlog.txt", + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if(logfile == INVALID_HANDLE_VALUE) { + logfile = NULL; + return(-1); + } // ENDIF- Failed to open? Say so. +#endif /* VERBOSE LOGFILE */ + + return(0); +} // END OpenLog(); + + +void CloseLog() { + // Token comment line +#ifdef VERBOSE_LOGFILE + if(logfile != NULL) { + CloseHandle(logfile); + logfile = NULL; + } // ENDIF- Is the log file actually open? Close it. +#endif /* VERBOSE LOGFILE */ +} // END CloseLog() + + +void PrintLog(const char *fmt, ...) { + DWORD byteswritten; + + // Token comment line +#ifdef VERBOSE_LOGFILE + va_list list; + int len; + + if(logfile == NULL) return; // Log file not open... yet. + + va_start(list, fmt); + vsprintf(logfiletemp, fmt, list); + va_end(list); + + len = 0; + while((len < 2048) && (logfiletemp[len] != 0)) len++; + if((len > 0) && (logfiletemp[len-1] == '\n')) len--; + if((len > 0) && (logfiletemp[len-1] == '\r')) len--; + logfiletemp[len] = 0; // Slice off the last "\r\n"... + + WriteFile(logfile, logfiletemp, len, &byteswritten, NULL); + WriteFile(logfile, "\r\n", 2, &byteswritten, NULL); +#endif /* VERBOSE LOGFILE */ +} // END PrintLog() + +void PrintError(const char *header, DWORD errcode) { +#ifdef VERBOSE_LOGFILE + TCHAR errmsg[256]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 80, + NULL, + errcode, + 0, + errmsg, + 256, + NULL); + PrintLog("%s: (%u) %s", header, errcode, errmsg); +#endif /* VERBOSE_WARNING_DEVICE */ +} // END PrintError() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.h b/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.h new file mode 100644 index 0000000..ff6e3b0 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/logfile.h @@ -0,0 +1,39 @@ +/* logfile.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef LOGFILE_H +#define LOGFILE_H + + +#include // Just for DWORD + + +#define VERBOSE_LOGFILE + + +extern void InitLog(); +extern int OpenLog(); +extern void CloseLog(); +extern void PrintLog(const char *format, ...); +extern void PrintError(const char *header, DWORD errcode); + + +#endif /* LOGFILE_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.c b/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.c new file mode 100644 index 0000000..0c7c9f8 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.c @@ -0,0 +1,173 @@ +/* mainbox.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +// #include // Button_ +#include // NULL + +#include // sprintf() +#include // strcpy() +#include // stat() +#include // stat() +#include // stat() + +#include "conf.h" +#include "device.h" +// #include "imagetype.h" // imagedata[].name +#include "screens.h" // DLG_, IDC_ +#include "CDVDlinuz.h" // progmodule +#include "mainbox.h" + + +HWND mainboxwindow; + + +void MainBoxDestroy() { + if(mainboxwindow != NULL) { + EndDialog(mainboxwindow, FALSE); + mainboxwindow = NULL; + } // ENDIF- Do we have a Main Window still? +} // END MainBoxDestroy() + + +void MainBoxUnfocus() { + // EnableWindow(?) + // gtk_widget_set_sensitive(mainbox.device, FALSE); + ShowWindow(mainboxwindow, SW_HIDE); +} // END MainBoxUnfocus() + + +void MainBoxDeviceEvent() { + char tempdevice[256]; + struct stat filestat; + int returnval; + + GetDlgItemText(mainboxwindow, IDC_0202, tempdevice, 256); + returnval = stat(tempdevice, &filestat); + if(returnval == -1) { + SetDlgItemText(mainboxwindow, IDC_0203, "Device Type: ---"); + return; + } // ENDIF- Not a name of any sort? + + if(S_ISDIR(filestat.st_mode) != 0) { + SetDlgItemText(mainboxwindow, IDC_0203, "Device Type: Not a device"); + return; + } // ENDIF- Not a regular file? + + SetDlgItemText(mainboxwindow, IDC_0203, "Device Type: Device Likely"); + return; +} // END MainBoxFileEvent() + + +void MainBoxRefocus() { + MainBoxDeviceEvent(); + + // gtk_widget_set_sensitive(mainbox.device, TRUE); + // gtk_window_set_focus(GTK_WINDOW(mainbox.window), mainbox.device); + // ShowWindow(mainboxwindow, SW_RESTORE); // and/or, SW_SHOW? SW_SHOWNORMAL? + ShowWindow(mainboxwindow, SW_SHOW); + SetActiveWindow(mainboxwindow); +} // END MainBoxRefocus() + + +void MainBoxCancelEvent() { + MainBoxDestroy(); + return; +} // END MainBoxCancelEvent() + + +void MainBoxOKEvent() { + int retval; + + MainBoxUnfocus(); + + GetDlgItemText(mainboxwindow, IDC_0202, conf.devicename, 256); + retval = DeviceOpen(); + DeviceClose(); + if(retval != 0) { + MainBoxRefocus(); + MessageBox(mainboxwindow, + "Could not open the device", + "CDVDlinuz Message", + MB_OK | MB_ICONWARNING | MB_SETFOREGROUND); + return; + } // ENDIF- Trouble opening device? Abort here. + + SaveConf(); + + MainBoxCancelEvent(); + return; +} // END MainBoxOKEvent() + + +void MainBoxDisplay() { + InitConf(); // Man, am I boiling mad! CDVDinit() should have been called first! + LoadConf(); + + // Adjust window position? + + // We held off setting the name until now... so description would show. + SetDlgItemText(mainboxwindow, IDC_0202, conf.devicename); + + // First Time - Show the window + ShowWindow(mainboxwindow, SW_SHOWNORMAL); +} // END MainBoxDisplay() + + +BOOL CALLBACK MainBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2) { + switch(msg) { + case WM_INITDIALOG: + mainboxwindow = window; + MainBoxDisplay(); // In this case, final touches to this window. + return(FALSE); // And let Windows display this window. + break; + + case WM_CLOSE: // The "X" in the upper right corner was hit. + MainBoxCancelEvent(); + return(TRUE); + break; + + case WM_COMMAND: + // Do we wish to capture 'ENTER/RETURN' and/or 'ESC' here? + + switch(LOWORD(param)) { + case IDC_0202: // Devicename Edit Box + MainBoxDeviceEvent(); // Describe the File's type... + return(FALSE); // Let Windows handle the actual 'edit' processing... + break; + + case IDC_0204: // "Ok" Button + MainBoxOKEvent(); + return(TRUE); + break; + + case IDC_0205: // "Cancel" Button + MainBoxCancelEvent(); + return(TRUE); + break; + } // ENDSWITCH param- Which object got the message? + } // ENDSWITCH msg- what message has been sent to this window? + + return(FALSE); // Not a recognized message? Tell Windows to handle it. +} // END MainBoxEventLoop() diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.h b/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.h new file mode 100644 index 0000000..850ab6c --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/mainbox.h @@ -0,0 +1,42 @@ +/* mainbox.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef MAINBOX_H +#define MAINBOX_H + + +#include // HWND + + +extern const char fileselection[]; + +extern HWND mainboxwindow; + + +extern void MainBoxRefocus(); +extern void MainBoxDisplay(); +extern BOOL CALLBACK MainBoxCallback(HWND window, + UINT msg, + WPARAM param, + LPARAM param2); + + +#endif /* MAINBOX_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/make.bat b/plugins/cdvd/CDVDlinuz/Src/Win32/make.bat new file mode 100644 index 0000000..fc4b70f --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/make.bat @@ -0,0 +1 @@ +mingw32-make -f Makefile.MinGW32 %1 diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/plugin.def b/plugins/cdvd/CDVDlinuz/Src/Win32/plugin.def new file mode 100644 index 0000000..ecd0afb --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/plugin.def @@ -0,0 +1,21 @@ +EXPORTS + PS2EgetLibType = PS2EgetLibType@0 @2 + PS2EgetLibName = PS2EgetLibName@0 @3 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4 + CDVDinit = CDVDinit@0 @5 + CDVDshutdown = CDVDshutdown@0 @6 + CDVDopen = CDVDopen@0 @7 + CDVDclose = CDVDclose@0 @8 + CDVDreadTrack = CDVDreadTrack@8 @9 + CDVDgetBuffer = CDVDgetBuffer@0 @10 + CDVDreadSubQ = CDVDreadSubQ@8 @11 + CDVDgetTN = CDVDgetTN@4 @12 + CDVDgetTD = CDVDgetTD@8 @13 + CDVDgetTOC = CDVDgetTOC@4 @14 + CDVDgetDiskType = CDVDgetDiskType@0 @15 + CDVDgetTrayStatus = CDVDgetTrayStatus@0 @16 + CDVDctrlTrayOpen = CDVDctrlTrayOpen@0 @17 + CDVDctrlTrayClose = CDVDctrlTrayClose@0 @18 + CDVDconfigure = CDVDconfigure@0 @19 + CDVDtest = CDVDtest@0 @20 + CDVDabout = CDVDabout@0 @21 diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/screens.h b/plugins/cdvd/CDVDlinuz/Src/Win32/screens.h new file mode 100644 index 0000000..7f14743 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/screens.h @@ -0,0 +1,9 @@ +/* Weditres generated include file. Do NOT edit */ +#include +#define DLG_0100 100 +#define IDC_0104 104 +#define DLG_0200 200 +#define IDC_0202 202 +#define IDC_0203 203 +#define IDC_0204 204 +#define IDC_0205 205 diff --git a/plugins/cdvd/CDVDlinuz/Src/Win32/screens.rc b/plugins/cdvd/CDVDlinuz/Src/Win32/screens.rc new file mode 100644 index 0000000..8978447 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/Win32/screens.rc @@ -0,0 +1,29 @@ +/* Wedit generated resource file */ +#ifdef __LCC__ +#include +#endif +#include "screens.h" + + +DLG_0100 DIALOG 2, 2, 140, 59 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About CDVDlinuz" +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "EFP polling CDVD Driver v0.4", 101, 11, 6, 118, 12 + CTEXT "Current Author: efp", 102, 12, 16, 118, 12 + CTEXT "Original code by: linuzappz && shadow", 103, 12, 26, 118, 12 + PUSHBUTTON "Ok", IDC_0104, 50, 37, 40, 14 +END + +DLG_0200 DIALOG 4, 2, 241, 50 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "CDVDlinuz Configuration" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "CD/DVD device:", 201, 14, 8, 59, 12 + EDITTEXT IDC_0202, 71, 7, 164, 12, ES_AUTOHSCROLL + CTEXT "Device Type: ---", IDC_0203, 10, 21, 220, 12 + PUSHBUTTON "Ok", IDC_0204, 15, 31, 48, 14 + PUSHBUTTON "Cancel", IDC_0205, 177, 31, 48, 14 +END diff --git a/plugins/cdvd/CDVDlinuz/Src/buffer.c b/plugins/cdvd/CDVDlinuz/Src/buffer.c new file mode 100644 index 0000000..60e63e4 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/buffer.c @@ -0,0 +1,525 @@ +/* buffer.c + * Copyright (C) 2002-2005 CDVDlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include // errno +#include // NULL +#include // printf() +#include // strerror() + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + +#include "logfile.h" + +#include "buffer.h" + + +// Globals + +struct BufferSortEmpty { + u16 sortptr; +}; + +struct BufferSort { + u16 upptr; + u16 uppos; + + u32 mask; + u32 divisor; + + struct { + u8 isdata; + u16 ptr; + } lower[256]; + u16 ptrcount; + u16 firstptr; +}; + +struct BufferSortEmpty buffersortempty[BUFFERMAX]; +u16 buffersortemptystart; +u16 buffersortemptyend; + +struct BufferSort buffersort[BUFFERMAX]; +u8 buffersortstartisdata; +u16 buffersortstart; + +struct BufferList bufferlist[BUFFERMAX]; +u16 userbuffer; +u16 replacebuffer; + + +void InitBuffer() { + u16 i; + u16 j; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: InitBuffer()"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + buffersortemptystart = 0; + buffersortemptyend = 0; + for(i = 0; i < BUFFERMAX; i++) { + buffersortempty[i].sortptr = i; + } // NEXT i- Saying all buffersort[] entries are open. + + buffersortstart = 0xffff; + buffersortstartisdata = 2; + for(i = 0; i < BUFFERMAX; i++) { + for(j = 0; j < 256; j++) buffersort[i].lower[j].isdata = 2; + // buffersort[i].ptrcount = 0; + } // NEXT i- Saying all buffersort[] entries are open. + + for(i = 0; i < BUFFERMAX; i++) { + bufferlist[i].upsort = 0xffff; + } // NEXT i- Clearing out the buffer pointers + userbuffer = 0xffff; + replacebuffer = BUFFERMAX - 1; +} // END InitBuffer(); + + +u16 AllocSortBuffer() { + u16 newbuffer; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: AllocSortBuffer()"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + newbuffer = buffersortempty[buffersortemptyend].sortptr; + buffersortempty[buffersortemptyend].sortptr = BUFFERMAX; + buffersortemptyend++; + if(buffersortemptyend > BUFFERMAX - 1) buffersortemptyend = 0; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Sort Buffer %u", newbuffer); +#endif /* VERBOSE_FUNCTION_BUFFER */ + +#ifdef VERBOSE_WARNINGS_BUFFER + if(buffersortemptyend == buffersortemptystart) { + PrintLog("Completely out of Sort Buffers to allocate now!"); + } // ENDIF- Out of Sort Buffers? Say so! +#endif /* VERBOSE_WARNINGS_BUFFER */ + + return(newbuffer); +} // END AllocSortBuffer() + + +void ReleaseSortBuffer(u16 oldbuffer) { +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: ReleaseSortBuffer(%u)", oldbuffer); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + buffersortempty[buffersortemptystart].sortptr = oldbuffer; + buffersortemptystart++; + if(buffersortemptystart > BUFFERMAX - 1) buffersortemptystart = 0; +} // END ReleaseSortBuffer() + + +// Returns either index in buffersort... or closest insertion point. +// Make lsn == buffersort[int].lsn test for exact match +u16 FindListBuffer(u32 lsn) { + u16 current; + u8 isdata; + u32 index; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: FindListBuffer(%u)", lsn); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + if(buffersortstart == 0xffff) return(0xffff); // Buffer empty? Exit + + if(buffersortstartisdata == 1) { + if(bufferlist[buffersortstart].lsn != lsn) return(0xffff); + return(buffersortstart); + } // ENDIF- Only one Record in Buffer? + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Searching..."); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + current = buffersortstart; + isdata = 0; + while(isdata == 0) { + index = lsn; + index &= buffersort[current].mask; + index /= buffersort[current].divisor; + isdata = buffersort[current].lower[index].isdata; + current = buffersort[current].lower[index].ptr; + } // ENDWHILE- still haven't found data + + if(isdata == 2) return(0xffff); // Pointing at empty entry? + if(bufferlist[current].lsn != lsn) return(0xffff); // LSNs don't match? + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Found."); +#endif /* VERBOSE_FUNCTION_BUFFER */ + return(current); +} // END FindListBuffer() + + +// Removes buffer from the buffersort list +// bufnum = The bufferlist pointer +void RemoveListBuffer(u16 bufnum) { + u16 current; + u16 currentpos; + + u16 upperlink; + u16 upperindex; + + u16 lowerlink; + u8 lowerisdata; + + u32 index; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: RemoveListBuffer(%u)", bufnum); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + if(bufferlist[bufnum].upsort == 0xffff) return; // No link to break. + + current = bufferlist[bufnum].upsort; + currentpos = bufferlist[bufnum].uppos; + bufferlist[bufnum].upsort = 0xffff; + + if(current == 0xfffe) { + buffersortstart = 0xffff; + buffersortstartisdata = 2; +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Buffer emptied"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + return; + } // ENDIF- Last link broken... empty buffer now. + + lowerlink = 0xffff; + lowerisdata = 2; + + // Remove Lower Pointer + buffersort[current].lower[currentpos].isdata = 2; + if(currentpos == buffersort[current].firstptr) { + index = currentpos + 1; + while((index < 256) && (buffersort[current].lower[index].isdata == 2)) index++; + buffersort[current].firstptr = index; + } // ENDIF- Do we need to move firstptr to an active entry? + buffersort[current].ptrcount--; +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Pointer count for sort buffer %u: %u", + current, buffersort[current].ptrcount); +#endif /* VERBOSE_FUNCTION_BUFFER */ + if(buffersort[current].ptrcount > 1) return; // Still 2+ branches left + + // Find Lower Link + index = buffersort[current].firstptr; + lowerlink = buffersort[current].lower[index].ptr; + lowerisdata = buffersort[current].lower[index].isdata; + buffersort[current].lower[index].isdata = 2; + + // Find and Break Upper Link + upperlink = buffersort[current].upptr; + upperindex = buffersort[current].uppos; + + if(upperlink == 0xffff) { + buffersortstart = lowerlink; + buffersortstartisdata = lowerisdata; + } else { + buffersort[upperlink].lower[upperindex].ptr = lowerlink; + buffersort[upperlink].lower[upperindex].isdata = lowerisdata; + } // ENDIF- Did we hit the top of the web? + + // Break Lower Link + if(lowerisdata == 1) { + if(upperlink == 0xffff) { + bufferlist[lowerlink].upsort = 0xfffe; +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Buffer down to 1 record now"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + } else { + bufferlist[lowerlink].upsort = upperlink; + bufferlist[lowerlink].uppos = upperindex; + } // ENDIF- Is this the last active buffersort? + } else { + buffersort[lowerlink].upptr = upperlink; + buffersort[lowerlink].uppos = upperindex; + } // ENDIF- Was this a BufferList link? + + // Cleanup in aisle 5.... + ReleaseSortBuffer(current); + return; +} // END RemoveListBuffer() + + +// Adds buffer to the buffersort list +// bufnum = The bufferlist pointer +void AddListBuffer(u16 bufnum) { + u32 newmask; + u32 newdivisor; + + u16 newbuffer; + u32 newvalue; + + u16 current; + u32 currentvalue; + u8 currentisdata; + + u16 prevbuffer; + u32 prevvalue; + + u16 comparebuffer; + u8 compareisdata; + u32 comparevalue; + +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: AddListBuffer(%u)", bufnum); +#endif /* VERBOSE_FUNCTION_BUFFER */ + + // Already in list? Oh, re-sorting? Got it covered. + if(bufferlist[bufnum].upsort != 0xffff) RemoveListBuffer(bufnum); + + if(buffersortstartisdata == 2) { + buffersortstart = bufnum; + buffersortstartisdata = 1; + bufferlist[bufnum].upsort = 0xfffe; +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Buffer up to 1 record now"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + return; + } // ENDIF- Empty list? Set for just 1 entry. + + if(buffersortstartisdata == 1) { + newmask = 0xff000000; + newdivisor = 0x01000000; + newvalue = (bufferlist[bufnum].lsn & newmask) / newdivisor; + currentvalue = (bufferlist[buffersortstart].lsn & newmask) / newdivisor; + while((newdivisor != 0x00000001) && (newvalue == currentvalue)) { + newmask /= 0x0100; + newdivisor /= 0x0100; + newvalue = (bufferlist[bufnum].lsn & newmask) / newdivisor; + currentvalue = (bufferlist[buffersortstart].lsn & newmask) / newdivisor; + } // ENDWHILE- trying to find a difference between the LSNs + + if(newvalue == currentvalue) { + bufferlist[buffersortstart].upsort = 0xffff; + bufferlist[bufnum].upsort = 0xfffe; + buffersortstart = bufnum; + return; + + } else { + newbuffer = AllocSortBuffer(); + buffersort[newbuffer].upptr = 0xffff; + buffersort[newbuffer].mask = newmask; + buffersort[newbuffer].divisor = newdivisor; + buffersort[newbuffer].lower[currentvalue].isdata = 1; + buffersort[newbuffer].lower[currentvalue].ptr = buffersortstart; + buffersort[newbuffer].lower[newvalue].isdata = 1; + buffersort[newbuffer].lower[newvalue].ptr = bufnum; + buffersort[newbuffer].ptrcount = 2; + buffersort[newbuffer].firstptr = currentvalue; + if(newvalue < buffersort[newbuffer].firstptr) + buffersort[newbuffer].firstptr = newvalue; + + bufferlist[buffersortstart].upsort = newbuffer; + bufferlist[buffersortstart].uppos = currentvalue; + buffersortstart = newbuffer; + buffersortstartisdata = 0; + + bufferlist[bufnum].upsort = newbuffer; + bufferlist[bufnum].uppos = newvalue; +#ifdef VERBOSE_FUNCTION_BUFFER + PrintLog("CDVD buffer: Buffer up to 2 records now"); +#endif /* VERBOSE_FUNCTION_BUFFER */ + return; + } // ENDIF- Same LSN? Shift pointer in response. Else, add a Sort Record. + } // ENDIF- Only 1 record? Check if we need a Sort Record. + + newmask = 0xff000000; + newdivisor = 0x01000000; + prevbuffer = 0xffff; + prevvalue = 0; + current = buffersortstart; + currentisdata = 0; + while(currentisdata == 0) { + newvalue = (bufferlist[bufnum].lsn & newmask) / newdivisor; + + if(buffersort[current].mask != newmask) { + comparebuffer = current; + compareisdata = 0; + while(compareisdata == 0) { + comparevalue = buffersort[comparebuffer].firstptr; + compareisdata = buffersort[comparebuffer].lower[comparevalue].isdata; + comparebuffer = buffersort[comparebuffer].lower[comparevalue].ptr; + } // ENDWHILE- looking for an another buffer to compare to... + + comparevalue = (bufferlist[comparebuffer].lsn & newmask) / newdivisor; + if(newvalue != comparevalue) { + // Add buffersort here (comparevalue/newvalue) + newbuffer = AllocSortBuffer(); + buffersort[newbuffer].upptr = buffersort[current].upptr; + buffersort[newbuffer].uppos = buffersort[current].uppos; + buffersort[newbuffer].mask = newmask; + buffersort[newbuffer].divisor = newdivisor; + buffersort[newbuffer].lower[comparevalue].isdata = 0; + buffersort[newbuffer].lower[comparevalue].ptr = current; + buffersort[newbuffer].lower[newvalue].isdata = 1; + buffersort[newbuffer].lower[newvalue].ptr = bufnum; + buffersort[newbuffer].ptrcount = 2; + buffersort[newbuffer].firstptr = comparevalue; + if(newvalue < buffersort[newbuffer].firstptr) + buffersort[newbuffer].firstptr = newvalue; + + if(buffersort[newbuffer].upptr == 0xffff) { + buffersortstart = newbuffer; + } else { + buffersort[prevbuffer].lower[prevvalue].isdata = 0; + buffersort[prevbuffer].lower[prevvalue].ptr = newbuffer; + if(prevvalue < buffersort[prevbuffer].firstptr) + buffersort[prevbuffer].firstptr = prevvalue; + } // ENDIF- Do we need to adjust to buffersortstart connection? + buffersort[current].upptr = newbuffer; + buffersort[current].uppos = comparevalue; + bufferlist[bufnum].upsort = newbuffer; + bufferlist[bufnum].uppos = newvalue; + return; + } // ENDIF- Don't match? Add a buffersort here to say that! + + compareisdata = 0; + newmask /= 0x0100; + newdivisor /= 0x0100; + + } else { + currentisdata = buffersort[current].lower[newvalue].isdata; + prevbuffer = current; + prevvalue = newvalue; + if(currentisdata == 0) { + current = buffersort[current].lower[newvalue].ptr; + newmask /= 0x0100; + newdivisor /= 0x0100; + if(newdivisor == 0) { +#ifdef VERBOSE_WARNINGS_BUFFER + PrintLog("CDVD buffer: Mask/Divisor at 0! Index corruption! (detected in search)"); +#endif /* VERBOSE_WARNINGS_BUFFER */ + return; + } // ENDIF- The Mask went too far! Abort! (Sanity Check) + } // ENDIF- Do we have to go through another level of sort data? + } // ENDIF- We don't have a comparison on this byte? + } // ENDWHILE- looking for his level... + + if(buffersort[current].lower[newvalue].isdata == 2) { + buffersort[current].lower[newvalue].isdata = 1; + buffersort[current].lower[newvalue].ptr = bufnum; + buffersort[current].ptrcount++; + if(newvalue < buffersort[current].firstptr) + buffersort[current].firstptr = newvalue; + bufferlist[bufnum].upsort = current; + bufferlist[bufnum].uppos = newvalue; + return; + } // ENDIF- an empty slot? Fill it in. + + comparebuffer = buffersort[current].lower[newvalue].ptr; + if(bufferlist[bufnum].lsn == bufferlist[comparebuffer].lsn) { + buffersort[current].lower[newvalue].ptr = bufnum; + bufferlist[bufnum].upsort = current; + bufferlist[bufnum].uppos = newvalue; + bufferlist[comparebuffer].upsort = 0xffff; + return; + } // ENDIF- Same LSN? Replace! + + // Calc new position based on new separation markers... + newmask /= 0x0100; + newdivisor /= 0x0100; + if(newdivisor == 0) { +#ifdef VERBOSE_WARNINGS_BUFFER + PrintLog("CDVD buffer: Mask/Divisor at 0! Index corruption! (bottom add initial)"); +#endif /* VERBOSE_WARNINGS_BUFFER */ + return; + } // ENDIF- The Mask went too far! Abort! (Sanity Check) + newvalue = (bufferlist[bufnum].lsn & newmask) / newdivisor; + comparevalue = (bufferlist[comparebuffer].lsn & newmask) / newdivisor; + while((newmask != 0x000000ff) && (comparevalue == newvalue)) { + newmask /= 0x0100; + newdivisor /= 0x0100; + if(newdivisor == 0) { +#ifdef VERBOSE_WARNINGS_BUFFER + PrintLog("CDVD buffer: Mask/Divisor at 0! Index corruption! (bottom add loop)"); +#endif /* VERBOSE_WARNINGS_BUFFER */ + return; + } // ENDIF- The Mask went too far! Abort! (Sanity Check) + newvalue = (bufferlist[bufnum].lsn & newmask) / newdivisor; + comparevalue = (bufferlist[comparebuffer].lsn & newmask) / newdivisor; + } // ENDWHILE- continuing to scan for difference between the two numbers + + newbuffer = AllocSortBuffer(); + buffersort[newbuffer].upptr = prevbuffer; + buffersort[newbuffer].uppos = prevvalue; + buffersort[newbuffer].mask = newmask; + buffersort[newbuffer].divisor = newdivisor; + buffersort[newbuffer].lower[comparevalue].isdata = 1; + buffersort[newbuffer].lower[comparevalue].ptr = comparebuffer; + buffersort[newbuffer].lower[newvalue].isdata = 1; + buffersort[newbuffer].lower[newvalue].ptr = bufnum; + buffersort[newbuffer].ptrcount = 2; + buffersort[newbuffer].firstptr = comparevalue; + if(newvalue < buffersort[newbuffer].firstptr) + buffersort[newbuffer].firstptr = newvalue; + + buffersort[prevbuffer].lower[prevvalue].isdata = 0; + buffersort[prevbuffer].lower[prevvalue].ptr = newbuffer; + bufferlist[comparebuffer].upsort = newbuffer; + bufferlist[comparebuffer].uppos = comparevalue; + bufferlist[bufnum].upsort = newbuffer; + bufferlist[bufnum].uppos = newvalue; +} // END AddListBuffer() + +#ifdef VERBOSE_WARNINGS_BUFFER +void PrintSortBuffers() { + u16 h; + u16 i; + u16 j; + + printf("CDVD buffer: Sort Buffer Dump\n"); + printf("CDVD buffer: Top Pointer: isdata %u ptr %u\n", + buffersortstartisdata, buffersortstart); + for(i = 0; i < BUFFERMAX; i++) { + + h = 0; + while((h < BUFFERMAX) && (buffersortempty[h].sortptr != i)) h++; + + if(h == BUFFERMAX) { + printf("CDVD buffer: Sort Buffer:%u Mask:%x Divisor:%x\n", + i, buffersort[i].mask, buffersort[i].divisor); + printf("CDVD buffer: Up Ptr:%u Up Pos:%u First Down Ptr:%u Ptr Count: %u\n", + buffersort[i].upptr, + buffersort[i].uppos, + buffersort[i].firstptr, + buffersort[i].ptrcount); + printf("CDVD buffer: "); + for(j = 0; j < 256; j++) { + if(buffersort[i].lower[j].isdata == 1) printf(" D"); + if(buffersort[i].lower[j].isdata == 0) printf(" L"); + if(buffersort[i].lower[j].isdata < 2) { + printf("%u:%u", j, buffersort[i].lower[j].ptr); + } // ENDIF- We have active data? Print it. + } // NEXT j- Scanning lower 256 pointers for active ones... + printf("\n"); + } // ENDIF- Not found in inactive list? Must be active! Print it. + } // NEXT i- looking at all the Allocated Buffers... +} // END PrintSortBuffers() +#endif /* VERBOSE_WARNINGS_BUFFER */ diff --git a/plugins/cdvd/CDVDlinuz/Src/buffer.h b/plugins/cdvd/CDVDlinuz/Src/buffer.h new file mode 100644 index 0000000..fefe605 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/buffer.h @@ -0,0 +1,67 @@ +/* buffer.h + * Copyright (C) 2002-2005 CDVDlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BUFFER_H__ +#define __BUFFER_H__ + + +#define CDVDdefs +#include "PS2Edefs.h" + + +// #define VERBOSE_FUNCTION_BUFFER +// #define VERBOSE_WARNINGS_BUFFER + +// Remember, each buffer set is about 5k (packed. might be 4x that in-memory) +// Minimum: 16 Maximum: 32760 +#define BUFFERMAX 256 + + +// Buffer Structures + +struct BufferList { + u16 upsort; // Don't alter this variable + u16 uppos; // Don't alter this variable + + u32 lsn; + int mode; // -1 means error + u8 buffer[2368]; + u8 offset; + cdvdSubQ subq; +}; + + +// Exported Variables + +extern struct BufferList bufferlist[]; +extern u16 userbuffer; +extern u16 replacebuffer; + + +// Exported Functions + +extern void InitBuffer(); +extern u16 FindListBuffer(u32 lsn); +extern void RemoveListBuffer(u16 oldbuffer); +extern void AddListBuffer(u16 newbuffer); +#ifdef VERBOSE_WARNINGS_BUFFER +extern void PrintSortBuffers(); +#endif /* VERBOSE_WARNINGS_BUFFER */ + + +#endif /* __BUFFER_H__ */ diff --git a/plugins/cdvd/CDVDlinuz/Src/convert.c b/plugins/cdvd/CDVDlinuz/Src/convert.c new file mode 100644 index 0000000..9e6a62a --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/convert.c @@ -0,0 +1,118 @@ +/* convert.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include +#include + +#include "convert.h" + + +off64_t ConvertEndianOffset(off64_t number) { +#ifndef CONVERTLITTLEENDIAN + union { + off64_t n; + char c[sizeof(off64_t)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(off64_t); i++) + newnumber.c[i] = oldnumber.c[sizeof(off64_t) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianOffset() + + +unsigned int ConvertEndianUInt(unsigned int number) { +#ifndef CONVERTLITTLEENDIAN + union { + unsigned int n; + char c[sizeof(unsigned int)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(unsigned int); i++) + newnumber.c[i] = oldnumber.c[sizeof(unsigned int) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianUInt() + + +unsigned short ConvertEndianUShort(unsigned short number) { +#ifndef CONVERTLITTLEENDIAN + union { + unsigned short n; + char c[sizeof(unsigned short)]; + } oldnumber, newnumber; + int i; + + oldnumber.n = number; + for(i = 0; i < sizeof(unsigned short); i++) + newnumber.c[i] = oldnumber.c[sizeof(unsigned short) - 1 - i]; + return(newnumber.n); +#else + return(number); +#endif /* CONVERTLITTLEENDIAN */ +} // END ConvertEndianUShort() + + +// Note: deposits M/S/F data in buffer[0]/[1]/[2] respectively. +void LBAtoMSF(unsigned long lsn, char *buffer) { + unsigned long templsn; + + if(lsn >= 0xFFFFFFFF - 150) { + *(buffer + 2) = 75-1; + *(buffer + 1) = 60-1; + *(buffer) = 100-1; + } // ENDIF- Out of range? + + templsn = lsn; + templsn += 150; // 2 second offset (75 Frames * 2 Seconds) + *(buffer + 2) = templsn % 75; // Remainder in frames + templsn -= *(buffer + 2); + templsn /= 75; + *(buffer + 1) = templsn % 60; // Remainder in seconds + templsn -= *(buffer + 1); + templsn /= 60; + *(buffer) = templsn; // Leftover quotient in minutes +} // END LBAtoMSF() + + +unsigned long MSFtoLBA(char *buffer) { + unsigned long templsn; + + if(buffer == NULL) return(0xFFFFFFFF); + + templsn = *(buffer); // Minutes + templsn *= 60; + templsn += *(buffer + 1); // Seconds + templsn *= 75; + templsn += *(buffer + 2); // Frames + if(templsn < 150) return(0xFFFFFFFF); + templsn -= 150; // Offset + + return(templsn); +} // END MSFtoLBA() diff --git a/plugins/cdvd/CDVDlinuz/Src/convert.h b/plugins/cdvd/CDVDlinuz/Src/convert.h new file mode 100644 index 0000000..0806f7b --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/convert.h @@ -0,0 +1,50 @@ +/* convert.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef CONVERT_H +#define CONVERT_H + + +#include // off64_t + +#ifdef __linux__ +#include "endian.h" +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define CONVERTLITTLEENDIAN +#endif /* __BYTE_ORDER */ +#endif /* __linux__ */ + +#ifdef __WIN32__ +#define CONVERTLITTLEENDIAN +#endif /* __WIN32__ */ + +#define HEXTOBCD(i) (((i)/10*16) + ((i)%10)) +#define BCDTOHEX(i) (((i)/16*10) + ((i)%16)) + + +extern off64_t ConvertEndianOffset(off64_t number); +extern unsigned int ConvertEndianUInt(unsigned int number); +extern unsigned short ConvertEndianUShort(unsigned short number); + +extern void LBAtoMSF(unsigned long lsn, char *buffer); +extern unsigned long MSFtoLBA(char *buffer); + +#endif /* CONVERT_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/ini.c b/plugins/cdvd/CDVDlinuz/Src/ini.c new file mode 100644 index 0000000..a00dac8 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/ini.c @@ -0,0 +1,689 @@ +/* ini.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#include // NULL +#include // sprintf() + +#include "logfile.h" +#include "actualfile.h" +#include "ini.h" + + +const char INIext[] = ".ini"; +const char INInewext[] = ".new"; + + +// Returns: position where new extensions should be added. +int INIRemoveExt(char *argname, char *tempname) { + int i; + int j; + int k; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: RemoveExt(%s)", argname); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i <= INIMAXLEN) && (*(argname + i) != 0)) { + *(tempname + i) = *(argname + i); + i++; + } // ENDWHILE- Copying the argument name into a temporary area; + *(tempname + i) = 0; // And 0-terminate + k = i; + k--; + + j = 0; + while((j <= INIMAXLEN) && (INIext[j] != 0)) j++; + j--; + + while((j >= 0) && (*(tempname + k) == INIext[j])) { + k--; + j--; + } // ENDWHILE- Comparing the ending characters to the INI ext. + if(j < 0) { + k++; + i = k; + *(tempname + i) = 0; // 0-terminate, cutting off ".ini" + } // ENDIF- Do we have a match? Then remove the end chars. + + return(i); +} // END INIRemoveExt() + + +void INIAddInExt(char *tempname, int temppos) { + int i; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: AddInExt(%s, %i)", tempname, temppos); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i + temppos < INIMAXLEN) && (INIext[i] != 0)) { + *(tempname + temppos + i) = INIext[i]; + i++; + } // ENDWHILE- Attaching extenstion to filename + *(tempname + temppos + i) = 0; // And 0-terminate +} // END INIAddInExt() + + +void INIAddOutExt(char *tempname, int temppos) { + int i; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: AddOutExt(%s, %i)", tempname, temppos); +#endif /* VERBOSE_FUNCTION_INI */ + + i = 0; + while((i + temppos < INIMAXLEN) && (INInewext[i] != 0)) { + *(tempname + temppos + i) = INInewext[i]; + i++; + } // ENDWHILE- Attaching extenstion to filename + *(tempname + temppos + i) = 0; // And 0-terminate +} // END INIAddInExt() + + +// Returns number of bytes read to get line (0 means end-of-file) +int INIReadLine(ACTUALHANDLE infile, char *buffer) { + int charcount; + int i; + char tempin[2]; + int retflag; + int retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: ReadLine()"); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + i = 0; + tempin[1] = 0; + retflag = 0; + + while((i < INIMAXLEN) && (retflag < 2)) { + retval = ActualFileRead(infile, 1, tempin); + charcount++; + if(retval != 1) { + retflag = 2; + charcount--; + + } else if(tempin[0] == '\n') { + retflag = 2; + + } else if(tempin[0] >= ' ') { + *(buffer + i) = tempin[0]; + i++; + } // ENDLONGIF- How do we react to the next character? + } // ENDWHILE- Loading up on characters until an End-of-Line appears + *(buffer + i) = 0; // And 0-terminate + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Line: %s", buffer); +#endif /* VERBOSE_FUNCTION_INI */ + + return(charcount); +} // END INIReadLine() +// Note: Do we need to back-skip a char if something other \n follows \r? + + +// Returns: number of bytes to get to start of section (or -1) +int INIFindSection(ACTUALHANDLE infile, char *section) { + int charcount; + int i; + int retflag; + int retval; + char scanbuffer[INIMAXLEN+1]; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: FindSection(%s)", section); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + retflag = 0; + + while(retflag == 0) { + retval = INIReadLine(infile, scanbuffer); + if(retval == 0) return(-1); // EOF? Stop here. + + if(scanbuffer[0] == '[') { + i = 0; + while((i < INIMAXLEN) && + (*(section + i) != 0) && + (*(section + i) == scanbuffer[i + 1])) i++; + if((i < INIMAXLEN - 2) && (*(section + i) == 0)) { + if((scanbuffer[i + 1] == ']') && (scanbuffer[i + 2] == 0)) { + retflag = 1; + } // ENDIF- End marks look good? Return successful. + } // ENDIF- Do we have a section match? + } // ENDIF- Does this look like a section header? + + if(retflag == 0) charcount += retval; + } // ENDWHILE- Scanning lines for the correct [Section] header. + + return(charcount); +} // END INIFindSection() + + +// Returns: number of bytes to get to start of keyword (or -1) +int INIFindKeyword(ACTUALHANDLE infile, char *keyword, char *buffer) { + int charcount; + int i; + int j; + int retflag; + int retval; + char scanbuffer[INIMAXLEN+1]; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: FindKeyword(%s)", keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + charcount = 0; + retflag = 0; + + while(retflag == 0) { + retval = INIReadLine(infile, scanbuffer); + if(retval == 0) return(-1); // EOF? Stop here. + if(scanbuffer[0] == '[') return(-1); // New section? Stop here. + + i = 0; + while((i < INIMAXLEN) && + (*(keyword + i) != 0) && + (*(keyword + i) == scanbuffer[i])) i++; + if((i < INIMAXLEN - 2) && (*(keyword + i) == 0)) { + if(scanbuffer[i] == '=') { + retflag = 1; + if(buffer != NULL) { + i++; + j = 0; + while((i < INIMAXLEN) && (scanbuffer[i] != 0)) { + *(buffer + j) = scanbuffer[i]; + i++; + j++; + } // ENDWHILE- Copying the value out to the outbound buffer. + *(buffer + j) = 0; // And 0-terminate. + } // ENDIF- Return the value as well? + } // ENDIF- End marks look good? Return successful. + } // ENDIF- Do we have a section match? + + if(retflag == 0) charcount += retval; + } // ENDWHILE- Scanning lines for the correct [Section] header. + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Value: %s", buffer); +#endif /* VERBOSE_FUNCTION_INI */ + + return(charcount); +} // END INIFindKeyWord() + + +// Returns: number of bytes left to write... (from charcount back) +int INICopy(ACTUALHANDLE infile, ACTUALHANDLE outfile, int charcount) { + char buffer[4096]; + int i; + int chunk; + int retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Copy(%i)", charcount); +#endif /* VERBOSE_FUNCTION_INI */ + + i = charcount; + chunk = 4096; + if(i < chunk) chunk = i; + while(chunk > 0) { + retval = ActualFileRead(infile, chunk, buffer); + if(retval <= 0) return(i); // Trouble? Stop here. + if(retval < chunk) chunk = retval; // Short block? Note it. + + retval = ActualFileWrite(outfile, chunk, buffer); + if(retval <= 0) return(i); // Trouble? Stop here. + i -= retval; + if(retval < chunk) return(i); // Short block written? Stop here. + + chunk = 4096; + if(i < chunk) chunk = i; + } // ENDWHILE- Copying a section of file across, one chunk at a time. + + return(0); +} // END INICopyToPos() + + +int INISaveString(char *file, char *section, char *keyword, char *value) { + char inname[INIMAXLEN+1]; + char outname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + ACTUALHANDLE outfile; + int i; + int retval; + char templine[INIMAXLEN+1]; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + if(keyword == NULL) return(-1); + if(value == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: SaveString(%s, %s, %s, %s)", + file, section, keyword, value); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + for(i = 0; i <= filepos; i++) outname[i] = inname[i]; + INIAddInExt(inname, filepos); + INIAddOutExt(outname, filepos); + + filepos = 0; + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new file"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(inname); + if(outfile == ACTUALHANDLENULL) return(-1); // Just a bad name? Abort. + + sprintf(templine, "[%s]\r\n", section); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + if(retval < i) { + ActualFileDelete(inname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + return(0); + } // ENDIF- No input file? Create a brand new .ini file then. + + retval = INIFindSection(infile, section); + if(retval < 0) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new section"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); // Move ini to beginning of file... + INICopy(infile, outfile, 0x0FFFFFFF); // Copy the whole file out... + + sprintf(templine, "\r\n[%s]\r\n", section); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + if(retval < i) { + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); + } // ENDIF- Couldn't find the section? Make a new one! + + filepos = retval; + ActualFileSeek(infile, filepos); + filepos += INIReadLine(infile, templine); // Get section line's byte count + + retval = INIFindKeyword(infile, keyword, NULL); + if(retval < 0) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: creating new keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + ActualFileSeek(infile, filepos); + retval = INIReadLine(infile, templine); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0) && (templine[i] != '=')) i++; + while((retval > 0) && (templine[i] == '=')) { + filepos += retval; + retval = INIReadLine(infile, templine); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0) && (templine[i] != '=')) i++; + } // ENDWHILE- skimming to the bottom of the section + + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + + } else { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: replacing keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + filepos += retval; // Position just before old version of keyword + + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + INIReadLine(infile, templine); // Read past old keyword/value... + + // Replace with new value + sprintf(templine, "%s=%s\r\n", keyword, value); + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + } // ENDIF- Need to add a new keyword? + + INICopy(infile, outfile, 0xFFFFFFF); // Write out rest of file + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); +} // END INISaveString() + + +int INILoadString(char *file, char *section, char *keyword, char *buffer) { + char inname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + int retval; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + if(keyword == NULL) return(-1); + if(buffer == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: LoadString(%s, %s, %s)", + file, section, keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + INIAddInExt(inname, filepos); + + filepos = 0; + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) return(-1); + + retval = INIFindSection(infile, section); + if(retval < 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Didn't find it? Abort. + + retval = INIFindKeyword(infile, keyword, buffer); + if(retval < 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Didn't find it? Abort. + + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(0); +} // END INILoadString() + + +int INIRemove(char *file, char *section, char *keyword) { + char inname[INIMAXLEN+1]; + char outname[INIMAXLEN+1]; + int filepos; + ACTUALHANDLE infile; + ACTUALHANDLE outfile; + char templine[INIMAXLEN+1]; + int i; + int retval; + + if(file == NULL) return(-1); + if(section == NULL) return(-1); + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: Remove(%s, %s, %s)", + file, section, keyword); +#endif /* VERBOSE_FUNCTION_INI */ + + filepos = INIRemoveExt(file, inname); + for(i = 0; i <= filepos; i++) outname[i] = inname[i]; + INIAddInExt(inname, filepos); + INIAddOutExt(outname, filepos); + + infile = ActualFileOpenForRead(inname); + if(infile == ACTUALHANDLENULL) return(-1); + + retval = INIFindSection(infile, section); + if(retval == -1) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't even find the section? Abort + + filepos = retval; + if(keyword == NULL) { +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: removing section"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to the section? Abort. + + templine[0] = 0; + retval = 1; + while((retval > 0) && (templine[0] != '[')) { + retval = INIReadLine(infile, templine); + } // ENDWHILE- Read to the start of the next section... or EOF. + + if(templine[0] == '[') { + i = 0; + while((i < INIMAXLEN) && (templine[i] != 0)) i++; + retval = ActualFileWrite(outfile, i, templine); + if(retval < i) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing it out? Abort. + } // ENDIF- Are there other sections after this one? Save them then. + + } else { + filepos = retval; + ActualFileSeek(infile, filepos); + filepos += INIReadLine(infile, templine); // Get section line's byte count + + retval = INIFindKeyword(infile, keyword, NULL); + if(retval == -1) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't find the keyword? Abort + filepos += retval; + +#ifdef VERBOSE_FUNCTION_INI + PrintLog("CDVDiso ini: removing keyword"); +#endif /* VERBOSE_FUNCTION_INI */ + outfile = ActualFileOpenForWrite(outname); + if(outfile == ACTUALHANDLENULL) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + return(-1); + } // ENDIF- Couldn't open a temp file? Abort + + ActualFileSeek(infile, 0); + retval = INICopy(infile, outfile, filepos); + if(retval > 0) { + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(outname); + return(-1); + } // ENDIF- Trouble writing everything up to keyword? Abort. + + INIReadLine(infile, templine); // Read (and discard) the keyword line + } // ENDIF- Wipe out the whole section? Or just a keyword? + + INICopy(infile, outfile, 0xFFFFFFF); // Write out rest of file + ActualFileClose(infile); + infile = ACTUALHANDLENULL; + ActualFileClose(outfile); + outfile = ACTUALHANDLENULL; + ActualFileDelete(inname); + ActualFileRename(outname, inname); + return(0); +} // END INIRemove() + + +int INISaveUInt(char *file, char *section, char *keyword, unsigned int value) { + char numvalue[INIMAXLEN+1]; + + sprintf(numvalue, "%u", value); + return(INISaveString(file, section, keyword, numvalue)); +} // END INISaveUInt() + + +int INILoadUInt(char *file, char *section, char *keyword, unsigned int *buffer) { + char numvalue[INIMAXLEN+1]; + int retval; + unsigned int value; + // unsigned int sign; // Not needed in unsigned numbers + int pos; + + if(buffer == NULL) return(-1); + *(buffer) = 0; + + retval = INILoadString(file, section, keyword, numvalue); + if(retval < 0) return(retval); + + value = 0; + // sign = 1; // Start positive + pos = 0; + + // Note: skip leading spaces? (Shouldn't have to, I hope) + + // if(numvalue[pos] == '-') { + // pos++; + // sign = -1; + // } // ENDIF- Negative sign check + + while((pos < INIMAXLEN) && (numvalue[pos] != 0)) { + if(value > (0xFFFFFFFF / 10)) return(-1); // Overflow? + + if((numvalue[pos] >= '0') && (numvalue[pos] <= '9')) { + value *= 10; + value += numvalue[pos] - '0'; + pos++; + } else { + numvalue[pos] = 0; + } // ENDIF- Add a digit in? Or stop searching for digits? + } // ENDWHILE- Adding digits of info to our ever-increasing value + + // value *= sign + *(buffer) = value; + return(0); +} // END INILoadUInt() diff --git a/plugins/cdvd/CDVDlinuz/Src/ini.h b/plugins/cdvd/CDVDlinuz/Src/ini.h new file mode 100644 index 0000000..fbd2349 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/ini.h @@ -0,0 +1,64 @@ +/* ini.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef INI_H +#define INI_H + + +// #ifndef __LINUX__ +// #ifdef __linux__ +// #define __LINUX__ +// #endif /* __linux__ */ +// #endif /* No __LINUX__ */ + +// #define CDVDdefs +// #include "PS2Edefs.h" + + +// File format: +// [section] +// keyword=value + +// file - Name of the INI file +// section - Section within the file +// keyword - Identifier for a value +// value - value to store with a keyword in a section in the file +// buffer - place to retrieve the value of a keyword + +// return values: 0 = success, -1 = failure + + +// #define VERBOSE_FUNCTION_INI + +#define INIMAXLEN 255 + + +extern int INISaveString(char *file, char *section, char *keyword, char *value); +extern int INILoadString(char *file, char *section, char *keyword, char *buffer); + +extern int INISaveUInt(char *file, char *section, char *keyword, unsigned int value); +extern int INILoadUInt(char *file, char *section, char *keyword, unsigned int *buffer); + +// NULL in the keyword below removes the whole section. +extern int INIRemove(char *file, char *section, char *keyword); + + +#endif /* INI_H */ diff --git a/plugins/cdvd/CDVDlinuz/Src/version.c b/plugins/cdvd/CDVDlinuz/Src/version.c new file mode 100644 index 0000000..c2b9b2d --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/version.c @@ -0,0 +1,36 @@ +/* version.c + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +char *libname = "EFP polling CDVD Driver"; + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 0; +const unsigned char build = 4; diff --git a/plugins/cdvd/CDVDlinuz/Src/version.h b/plugins/cdvd/CDVDlinuz/Src/version.h new file mode 100644 index 0000000..774ce3b --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/Src/version.h @@ -0,0 +1,43 @@ +/* version.h + * Copyright (C) 2002-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * PCSX2 members can be contacted through their website at www.pcsx2.net. + */ + + +#ifndef VERSION_H +#define VERSION_H + + +#ifndef __LINUX__ +#ifdef __linux__ +#define __LINUX__ +#endif /* __linux__ */ +#endif /* No __LINUX__ */ + +#define CDVDdefs +#include "PS2Edefs.h" + + +extern char *libname; + +extern const unsigned char version; +extern const unsigned char revision; +extern const unsigned char build; + + +#endif /* VERSION_H */ diff --git a/plugins/cdvd/CDVDlinuz/build.sh b/plugins/cdvd/CDVDlinuz/build.sh new file mode 100644 index 0000000..523ab08 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +curdir=`pwd` + +echo ------------------ +echo Building CDVDlinuz +echo ------------------ + +cd ${curdir}/Src/Linux +make $@ + +if [ -s cfgCDVDlinuz ] && [ -s libCDVDlinuz.so ] +then +# copy the files +cp cfgCDVDlinuz libCDVDlinuz.so ${PCSX2PLUGINS} +fi diff --git a/plugins/cdvd/CDVDlinuz/readme.txt b/plugins/cdvd/CDVDlinuz/readme.txt new file mode 100644 index 0000000..93fa7a7 --- /dev/null +++ b/plugins/cdvd/CDVDlinuz/readme.txt @@ -0,0 +1,37 @@ +CDVDlinuz v0.4 +-------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + + Modified by efp to work with DVDs as well + +To install in Windows: +----- + Place the file "CDVDlinuz.dll" in the "plugins" directory. + +To install in Linux: +----- + Place the file "libCDVDlinuz.so" in the "plugins/" directory. + Place the file "cfgCDVDlinuz" in the "cfg/" directory. + +To activate in PCSX2: +----- + Start up PCSX2. + Select "Configuration", then "Plugins and Bios". + In the "Cdvdrom" pull-down menu, you should see: + "EFP polling CDVD Driver v.04" + Select it. + Then press the "Configure" button under it. + In the "CDVDlinuz Configuration" screen, type in where your CD or DVD +device can be found. + (In Linux, devices look like "/dev/") + (In Windows, devices look like "D:". There are other types of references to +devices, but they haven't been tested.) + Press to "OK" button to save your selection. + Finally, put a CD or DVD in the selected drive, and run PCSX2. + + Keep in mind the above instructions only cover the "CD/DVD" portion of +PCSX2. All configuration options must be attended to before PCSX2 could run +correctly. diff --git a/plugins/cdvd/CDVDnull/CDVDnull.dll b/plugins/cdvd/CDVDnull/CDVDnull.dll new file mode 100644 index 0000000000000000000000000000000000000000..d728311c75c2281d2efdc45dd0c4c52d89c29661 GIT binary patch literal 49152 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 literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDnull/ReadMe.txt b/plugins/cdvd/CDVDnull/ReadMe.txt new file mode 100644 index 0000000..24a6674 --- /dev/null +++ b/plugins/cdvd/CDVDnull/ReadMe.txt @@ -0,0 +1,39 @@ +CDVDnull v0.6 +--------------- + + This is an extension to use with playstation2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Using: +----- + Place the file "CDVDnull.dll" at the Plugins directory + of the Emulator to use it. + +Changes: +------- + v0.6: + * added vsnet2003 project files. + * added support for functions in new plugin version + + v0.5: + * added vsnet2005beta1 project files. 64bit plugin should be okay now (Not tested!) + + v0.4: + * updated to 0.4.3 specifications + + v0.3: + * updated to 0.4.0 specifications + + v0.2: + * add the 0.2.9 specifications + * CDVDopen refixed + + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + + diff --git a/plugins/cdvd/CDVDnull/Src/CDVD.c b/plugins/cdvd/CDVDnull/Src/CDVD.c new file mode 100644 index 0000000..5f338b6 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVD.c @@ -0,0 +1,146 @@ +#include + +#include "CDVD.h" + + +char *LibName = "CDVDnull Driver"; + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 0; +const unsigned char build = 6; + + +char* CALLBACK PS2EgetLibName() { + return LibName; +} + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_CDVD; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version << 16) | (revision << 8) | build; +} + +#ifdef _WIN32 +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + + MessageBox(0, tmp, "CDVDnull Msg", 0); +} +#else + +void SysMessage(char *fmt, ...) { + /*GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main();*/ +} + +#endif + +s32 CALLBACK CDVDinit() { + return 0; +} + +s32 CALLBACK CDVDopen(const char* pTitle) { + return 0; +} + +void CALLBACK CDVDclose() { +} + +void CALLBACK CDVDshutdown() { +} + +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode) { + return -1; +} + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer() { + return NULL; +} + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) { + return -1; +} + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer) { + return -1; +} + +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer) { + return -1; +} + +s32 CALLBACK CDVDgetTOC(void* toc) { + return -1; +} + +s32 CALLBACK CDVDgetDiskType() { + return CDVD_TYPE_NODISC; +} + +s32 CALLBACK CDVDgetTrayStatus() { + return CDVD_TRAY_CLOSE; +} + +s32 CALLBACK CDVDctrlTrayOpen() { + return 0; +} + +s32 CALLBACK CDVDctrlTrayClose() { + return 0; +} + +void CALLBACK CDVDconfigure() { + SysMessage("Nothing to Configure"); +} + +void CALLBACK CDVDabout() { + SysMessage("%s %d.%d", LibName, revision, build); +} + +s32 CALLBACK CDVDtest() { + return 0; +} diff --git a/plugins/cdvd/CDVDnull/Src/CDVD.h b/plugins/cdvd/CDVDnull/Src/CDVD.h new file mode 100644 index 0000000..9424491 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVD.h @@ -0,0 +1,11 @@ +#ifndef __CDVD_H__ +#define __CDVD_H__ + +#ifdef _WIN32 +#include +#endif + +#define CDVDdefs +#include "PS2Edefs.h" + +#endif /* __CDVD_H__ */ diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.def b/plugins/cdvd/CDVDnull/Src/CDVDnull.def new file mode 100644 index 0000000..18fb480 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull.def @@ -0,0 +1,29 @@ +; CDVDnull.def : Declares the module parameters for the DLL. + +LIBRARY "CDVDnull" +DESCRIPTION 'CDVD Null Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + CDVDinit @5 + CDVDshutdown @6 + CDVDopen @7 + CDVDclose @8 + CDVDreadTrack @9 + CDVDgetBuffer @10 + CDVDreadSubQ @11 + CDVDgetTN @12 + CDVDgetTD @13 + CDVDgetTOC @14 + CDVDgetDiskType @15 + CDVDgetTrayStatus @16 + CDVDctrlTrayOpen @17 + CDVDctrlTrayClose @18 + + CDVDconfigure @19 + CDVDtest @20 + CDVDabout @21 + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.dsp b/plugins/cdvd/CDVDnull/Src/CDVDnull.dsp new file mode 100644 index 0000000..5e02435 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="CDVDnull" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=CDVDNULL - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "CDVDnull.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "CDVDnull.mak" CFG="CDVDNULL - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "CDVDnull - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "__MSCW32__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDNULL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "__MSCW32__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDNULL_EXPORTS" /D "__WIN32__" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# Begin Target + +# Name "CDVDnull - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\CDVD.c +# End Source File +# Begin Source File + +SOURCE=.\CDVDnull.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\CDVD.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Etypes.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.dsw b/plugins/cdvd/CDVDnull/Src/CDVDnull.dsw new file mode 100644 index 0000000..ca22d5b --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "CDVDnull"=".\CDVDnull.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.opt b/plugins/cdvd/CDVDnull/Src/CDVDnull.opt new file mode 100644 index 0000000000000000000000000000000000000000..13a3499ad319ec9623dbe40f3db4ac98e2582e95 GIT binary patch literal 53760 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

+ +

+

Build Log

+

+--------------------Configuration: CDVDnull - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\marcelo\LOCALS~1\Temp\RSP89.tmp" with contents +[ +/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CDVDNULL_EXPORTS" /D "__WIN32__" /Fo"Release/" /Fd"Release/" /FD /c +"C:\pcsx2\plugins\cdvd\CDVDnull\Src\CDVD.c" +] +Creating command line "xicl6.exe @C:\DOCUME~1\marcelo\LOCALS~1\Temp\RSP89.tmp" +Creating temporary file "C:\DOCUME~1\marcelo\LOCALS~1\Temp\RSP8A.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"Release/CDVDnull.pdb" /machine:I386 /def:".\CDVDnull.def" /out:"Release/CDVDnull.dll" /implib:"Release/CDVDnull.lib" +.\Release\CDVD.obj +] +Creating command line "xilink6.exe @C:\DOCUME~1\marcelo\LOCALS~1\Temp\RSP8A.tmp" +

Output Window

+Compiling... +CDVD.c +Linking... +xilink6: executing 'C:\PROGRA~1\MICROS~2\VC98\Bin\link.exe' + Creating library Release/CDVDnull.lib and object Release/CDVDnull.exp + + + +

Results

+CDVDnull.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.sln b/plugins/cdvd/CDVDnull/Src/CDVDnull.sln new file mode 100644 index 0000000..4336fc7 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDnull", "CDVDnull.vcproj", "{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release.ActiveCfg = Release|Win32 + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull.vcproj b/plugins/cdvd/CDVDnull/Src/CDVDnull.vcproj new file mode 100644 index 0000000..632c7b4 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull.vcproj @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.sln b/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.sln new file mode 100644 index 0000000..c0b7d90 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDnull", "CDVDnull_2003.vcproj", "{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release.ActiveCfg = Release|Win32 + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.vcproj b/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.vcproj new file mode 100644 index 0000000..863e390 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_2003.vcproj @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.sln b/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.sln new file mode 100644 index 0000000..2814883 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDnull", "CDVDnull_2005_x64.vcproj", "{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release|x64.ActiveCfg = amd64|x64 + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release|x64.Build.0 = amd64|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.vcproj b/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.vcproj new file mode 100644 index 0000000..db25f76 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_2005_x64.vcproj @@ -0,0 +1,607 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.sln b/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.sln new file mode 100644 index 0000000..349a3a1 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CDVDnull", "CDVDnull_vsnet2005beta1.vcproj", "{F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release|Win32.ActiveCfg = Release|Win32 + {F38D9DF0-F68D-49D9-B3A0-932E74FB74A0}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.vcproj b/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.vcproj new file mode 100644 index 0000000..19d70bd --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/CDVDnull_vsnet2005beta1.vcproj @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDnull/Src/Makefile b/plugins/cdvd/CDVDnull/Src/Makefile new file mode 100644 index 0000000..8331e1c --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/Makefile @@ -0,0 +1,50 @@ +# +# Makefile for MINGW32 +# + + +all: cdvdnull +install: all + +PLUGIN = libCDVDnull.so + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing +FLAGS = -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = +LIBS = +RESOBJ = cdvdnull.o + +OBJS = CDVD.o + + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I/usr/local/include ${FLAGS} -fPIC + +cdvdnull: ${OBJS} +# dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean cdvdnull + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: CDVDnull.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} diff --git a/plugins/cdvd/CDVDnull/Src/PS2Edefs.h b/plugins/cdvd/CDVDnull/Src/PS2Edefs.h new file mode 100644 index 0000000..3e97070 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/PS2Edefs.h @@ -0,0 +1,827 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// call to give a hint to the PAD plugin to query for the keyboard state. A +// good plugin will query the OS for keyboard state ONLY in this function. +// This function is necessary when multithreading because otherwise +// the PAD plugin can get into deadlocks with the thread that really owns +// the window (and input). Note that PADupdate can be called from a different +// thread than the other functions, so mutex or other multithreading primitives +// have to be added to maintain data integrity. +void CALLBACK PADupdate(int pad); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits) +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); +typedef void (CALLBACK* _PADupdate)(int pad); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgetLastTag GSgetLastTag; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; +_PADupdate PAD1update; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; +_PADupdate PAD2update; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDnull/Src/PS2Etypes.h b/plugins/cdvd/CDVDnull/Src/PS2Etypes.h new file mode 100644 index 0000000..1ad73e2 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/PS2Etypes.h @@ -0,0 +1,76 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif // _MSC_VER + +#if defined(__x86_64__) +typedef u64 uptr; +typedef s64 sptr; +#else +typedef u32 uptr; +typedef s32 sptr; +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDnull/Src/plugin.def b/plugins/cdvd/CDVDnull/Src/plugin.def new file mode 100644 index 0000000..4d19ae2 --- /dev/null +++ b/plugins/cdvd/CDVDnull/Src/plugin.def @@ -0,0 +1,21 @@ +EXPORTS + PS2EgetLibType = PS2EgetLibType@0 @2 + PS2EgetLibName = PS2EgetLibName@0 @3 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4 + CDVDinit = CDVDinit@0 @5 + CDVDshutdown = CDVDshutdown@0 @6 + CDVDopen = CDVDopen@0 @7 + CDVDclose = CDVDclose@0 @8 + CDVDreadTrack = CDVDreadTrack@8 @9 + CDVDgetBuffer = CDVDgetBuffer@0 @10 + CDVDreadSubQ = CDVDreadSubQ@8 @11 + CDVDgetTN = CDVDgetTN@4 @12 + CDVDgetTD = CDVDgetTD@8 @13 + CDVDgetTOC = CDVDgetTOC@4 @14 + CDVDgetDiskType = CDVDgetDiskType@0 @15 + CDVDgetTrayStatus = CDVDgetTrayStatus@0 @16 + CDVDctrlTrayOpen = CDVDctrlTrayOpen@0 @17 + CDVDctrlTrayClose = CDVDctrlTrayClose@0 @18 + CDVDconfigure = CDVDconfigure@0 @19 + CDVDtest = CDVDtest@0 @20 + CDVDabout = CDVDabout@0 @21 diff --git a/plugins/cdvd/CDVDnull/build.sh b/plugins/cdvd/CDVDnull/build.sh new file mode 100644 index 0000000..cc8792b --- /dev/null +++ b/plugins/cdvd/CDVDnull/build.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +curdir=`pwd` + +echo ----------------- +echo Building CDVDnull +echo ----------------- +cd ${curdir}/Src +make $@ + +# copy the files +cp libCDVDnull.so ${PCSX2PLUGINS} diff --git a/plugins/cdvd/CDVDpeops/CDVDiso.c b/plugins/cdvd/CDVDpeops/CDVDiso.c new file mode 100644 index 0000000..d15d1ff --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CDVDiso.c @@ -0,0 +1,822 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + * Fixed CdRead by linuzappz + */ + +#include +#ifdef __LINUX__ +#define strnicmp strncasecmp +#endif + +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +struct dir_toc_data{ + unsigned int start_LBA; + unsigned int num_sectors; + unsigned int num_entries; + unsigned int current_entry; + unsigned int current_sector; + unsigned int current_sector_offset; + unsigned int inc_dirs; + unsigned char extension_list[128+1]; +}; + +//static u8 cdVolDescriptor[2048]; +static struct dir_toc_data getDirTocData; +static struct cdVolDesc CDVolDesc; + +void _splitpath2(const char *constpath, char *dir, char *fname){ + // 255 char max path-length is an ISO9660 restriction + // we must change this for Joliet or relaxed iso restriction support + static char pathcopy[1024+1]; + + char* slash; + + strncpy(pathcopy, constpath, 1024); + + slash = strrchr (pathcopy, '/'); + + // if the path doesn't contain a '/' then look for a '\' + if (!slash) + slash = strrchr (pathcopy, (int)'\\'); + + // if a slash was found + if (slash != NULL) + { + // null terminate the path + slash[0] = 0; + // and copy the path into 'dir' + strncpy(dir, pathcopy, 1024); + dir[255]=0; + + // copy the filename into 'fname' + strncpy(fname, slash+1, 128); + fname[128]=0; + } + else + { + dir[0] = 0; + + strncpy(fname, pathcopy, 128); + fname[128]=0; + } + +} + +// Used in findfile +int tolower(int c); +int strcasecmp(const char *s1, const char *s2){ + while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) + { + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +// Copy a TOC Entry from the CD native format to our tidier format +void TocEntryCopy(struct TocEntry* tocEntry, struct dirTocEntry* internalTocEntry){ + int i; + int filenamelen; + + tocEntry->fileSize = internalTocEntry->fileSize; + tocEntry->fileLBA = internalTocEntry->fileLBA; + tocEntry->fileProperties = internalTocEntry->fileProperties; + memcpy(tocEntry->date, internalTocEntry->dateStamp, 7); + + if (CDVolDesc.filesystemType == 2){ + // This is a Joliet Filesystem, so use Unicode to ISO string copy + + filenamelen = internalTocEntry->filenameLength/2; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + for (i=0; i < filenamelen; i++) + tocEntry->filename[i] = internalTocEntry->filename[(i<<1)+1]; + + tocEntry->filename[filenamelen] = 0; + } + else{ + filenamelen = internalTocEntry->filenameLength; + + if (!(tocEntry->fileProperties & 0x02)){ + // strip the ;1 from the filename +// filenamelen -= 2;//(Florin) nah, do not strip ;1 + } + + // use normal string copy + strncpy(tocEntry->filename,internalTocEntry->filename,128); + tocEntry->filename[filenamelen] = 0; + } +} + +// Check if a TOC Entry matches our extension list +int TocEntryCompare(char* filename, char* extensions){ + static char ext_list[129]; + + char* token; + + char* ext_point; + + strncpy(ext_list,extensions,128); + ext_list[128]=0; + + token = strtok( ext_list, " ," ); + while( token != NULL ) + { + // if 'token' matches extension of 'filename' + // then return a match + ext_point = strrchr(filename,'.'); + + if (strnicmp(ext_point, token, strlen(token)) == 0) + return (TRUE); + + /* Get next token: */ + token = strtok( NULL, " ," ); + } + + // If not match found then return FALSE + return (FALSE); + +} + +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_MSF_OFFSET 150 /* MSF numbering offset of first frame */ + +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + int rmode; + + switch (mode->datapattern) { + case CdSecS2048: + rmode = CDVD_MODE_2048; break; + case CdSecS2328: + rmode = CDVD_MODE_2328; break; + case CdSecS2340: + rmode = CDVD_MODE_2340; break; + default: + return 0; + } + + for (i=0; idatapattern){ + case CdSecS2048: + memcpy((void*)((uptr)buf+2048*i), buff, 2048);break;//only data + case CdSecS2328: + memcpy((void*)((uptr)buf+2328*i), buff, 2328);break;//without sync & head & sub + case CdSecS2340: + memcpy((void*)((uptr)buf+2340*i), buff, 2340);break;//without sync + } + } + return 1; +} + +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode){ + u32 i; + u8* buff; + + for (i=lsn; i<(lsn+sectors); i++){ + if (CDVDreadTrack(i, CDVD_MODE_2048)==-1) + return 0; + buff = CDVDgetBuffer(); + if (buff==NULL) return 0; + +// switch (mode->datapattern){ +// case CdSecS2064: + ((u32*)buf)[0] = i + 0x30000; + memcpy((u8*)buf+12, buff, 2048); + (u8*)buf+= 2064; break; +// default: +// return 0; +// } + } + + return 1; +} + +/************************************************************** +* The functions below are not exported for normal file-system * +* operations, but are used by the file-system operations, and * +* may also be exported for use via RPC * +**************************************************************/ + +int CDVD_GetVolumeDescriptor(void){ + // Read until we find the last valid Volume Descriptor + int volDescSector; + + static struct cdVolDesc localVolDesc; + +#ifdef DEBUG + printf("CDVD_GetVolumeDescriptor called\n"); +#endif + + for (volDescSector = 16; volDescSector<20; volDescSector++) + { + CdRead(volDescSector,1,&localVolDesc,&cdReadMode); +// CdSync(0x00); + + // If this is still a volume Descriptor + if (strncmp(localVolDesc.volID, "CD001", 5) == 0) + { + if ((localVolDesc.filesystemType == 1) || + (localVolDesc.filesystemType == 2)) + { + memcpy(&CDVolDesc, &localVolDesc, sizeof(struct cdVolDesc)); + } + } + else + break; + } + +#ifdef DEBUG + if (CDVolDesc.filesystemType == 1) + printf("CD FileSystem is ISO9660\n"); + else if (CDVolDesc.filesystemType == 2) + printf("CD FileSystem is Joliet\n"); + else printf("Could not detect CD FileSystem type\n"); +#endif +// CdStop(); + + return TRUE; +} + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry){ + static char filename[128+1]; + static char pathname[1024+1]; + static char toc[2048]; + char* dirname; + + + static struct TocEntry localTocEntry; // used for internal checking only + + int found_dir; + + int num_dir_sectors; + int current_sector; + + int dir_lba; + + struct dirTocEntry* tocEntryPointer; + +#ifdef DEBUG + printf("CDVD_findfile called\n"); +#endif + + //make sure we have good cdReadMode + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; + + _splitpath2(fname, pathname, filename); + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + + while( dirname != NULL ) + { + found_dir = FALSE; +/* + while(tocEntryPointer->length > 0) + { + // while there are still more directory entries then search through + // for the one we want + + if (tocEntryPointer->fileProperties & 0x02) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcasecmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } +*/ + while(1) + { + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) + { + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE) + { + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else + { + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + + if (tocEntryPointer->fileProperties & 0x02) + { + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0) + { + // if the name matches then we've found the directory + found_dir = TRUE; + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + { + return -1; + } + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE) + { + return -1; + } +// CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; //round up fix + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; //round up fix + dir_lba = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + while (num_dir_sectors > 0) + { + while(tocEntryPointer->length != 0) + { + // Copy the CD format TOC Entry to our format + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if ((strnicmp(localTocEntry.filename, filename, strlen(filename)) == 0) || + ((filename[strlen(filename)-2] == ';') && + (localTocEntry.filename[strlen(localTocEntry.filename)-2] == ';') && + (strnicmp(localTocEntry.filename, filename, strlen(filename)-2) == 0))) + { + // if the filename matches then copy the toc Entry + tocEntry->fileLBA = localTocEntry.fileLBA; + tocEntry->fileProperties = localTocEntry.fileProperties; + tocEntry->fileSize = localTocEntry.fileSize; + + strcpy(tocEntry->filename, localTocEntry.filename); + memcpy(tocEntry->date, localTocEntry.date, 7); + +#ifdef DEBUG + printf("CDVD_findfile: found file\n"); +#endif + + return TRUE; + } + + (char*)tocEntryPointer += tocEntryPointer->length; + } + + num_dir_sectors--; + + if (num_dir_sectors > 0) + { + dir_lba++; + + if (CdRead(dir_lba,1,toc,&cdReadMode) != TRUE){ + return -1; + } +// CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + } + + return FALSE; +} + +// This is the RPC-ready function which takes the request to start the tocEntry retrieval +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs){ +// int dir_depth = 1; + static char toc[2048]; + char* dirname; + int found_dir; + int num_dir_sectors; + unsigned int toc_entry_num; + struct dirTocEntry* tocEntryPointer; + static struct TocEntry localTocEntry; + int current_sector; + + // store the extension list statically for the retrieve function + strncpy(getDirTocData.extension_list, extensions, 128); + getDirTocData.extension_list[128]=0; + + getDirTocData.inc_dirs = inc_dirs; + + // Find the TOC for a specific directory + if (CDVD_GetVolumeDescriptor() != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Could not get CD Volume Descriptor\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Getting Directory Listing for: \"%s\"\n", pathname); +#endif + + // Read the TOC of the root directory + if (CdRead(CDVolDesc.rootToc.tocLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + // point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + + num_dir_sectors = (tocEntryPointer->fileSize+2047) >> 11; + current_sector = tocEntryPointer->fileLBA; + + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + // use strtok to get the next dir name + + // if there isnt one, then assume we want the LBA + // for the current one, and exit the while loop + + // if there is another dir name then increment dir_depth + // and look through dir table entries until we find the right name + // if we dont find the right name + // before finding an entry at a higher level (lower num), then return nothing + + localTocEntry.fileLBA = CDVolDesc.rootToc.tocLBA; + + // while (there are more dir names in the path) + dirname = strtok( pathname, "\\/" ); + while( dirname != NULL ){ + found_dir = FALSE; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)) { + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + + current_sector++; + if (CdRead(current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + } + else{ + // Couldnt find the directory, and got to end of directory + return -1; + } + } + + if (tocEntryPointer->fileProperties & 0x02){ + TocEntryCopy(&localTocEntry, tocEntryPointer); + + // If this TOC Entry is a directory, + // then see if it has the right name + if (strcmp(dirname,localTocEntry.filename) == 0){ + // if the name matches then we've found the directory + found_dir = TRUE; +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Found directory %s in subdir at sector %d\n",dirname,current_sector); + RPC_LOG("[RPC: ] LBA of found subdirectory = %d\n",localTocEntry.fileLBA); +#endif + break; + } + } + + // point to the next entry + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // If we havent found the directory name we wanted then fail + if (found_dir != TRUE) + return -1; + + // Get next directory name + dirname = strtok( NULL, "\\/" ); + + // Read the TOC of the found subdirectory + if (CdRead(localTocEntry.fileLBA,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + num_dir_sectors = (localTocEntry.fileSize+2047) >> 11; + current_sector = localTocEntry.fileLBA; + + // and point the tocEntryPointer at the first real toc entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + } + + // We know how much data we need to read in from the DirTocHeader + // but we need to read in at least 1 sector before we can get this value + + // Now we need to COUNT the number of entries (dont do anything with info at this point) + // so set the tocEntryPointer to point to the first actual file entry + + // This is a bit of a waste of reads since we're not actually copying the data out yet, + // but we dont know how big this TOC might be, so we cant allocate a specific size + + (char*)tocEntryPointer = toc; + + // Need to STORE the start LBA and number of Sectors, for use by the retrieve func. + getDirTocData.start_LBA = localTocEntry.fileLBA; + getDirTocData.num_sectors = (tocEntryPointer->fileSize+2047) >> 11; + getDirTocData.num_entries = 0; + getDirTocData.current_entry = 0; + getDirTocData.current_sector = getDirTocData.start_LBA; + getDirTocData.current_sector_offset = 0; + + num_dir_sectors = getDirTocData.num_sectors; + + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + toc_entry_num=0; + + while(1){ + if ((tocEntryPointer->length == 0) || (((char*)tocEntryPointer-toc)>=2048)){ + // decrease the number of dirs remaining + num_dir_sectors--; + + if (num_dir_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC: ] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + (char*)tocEntryPointer = toc; + +// continue; + } + else{ + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + return (toc_entry_num); + } + } + + // We've found a file/dir in this directory + // now check if it matches our extension list (if there is one) + TocEntryCopy(&localTocEntry, tocEntryPointer); + + if (localTocEntry.fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs){ + toc_entry_num++; + } + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(localTocEntry.filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + } + else{ + toc_entry_num++; + } + } + + (char*)tocEntryPointer += tocEntryPointer->length; + + } + + + // THIS SHOULD BE UNREACHABLE - + // since we are trying to count ALL matching entries, rather than upto a limit + + + // STORE total number of TOC entries + getDirTocData.num_entries = toc_entry_num; + getDirTocData.current_sector = getDirTocData.start_LBA; + + + // we've reached the toc entry limit, so return how many we've done + return (toc_entry_num); + +} + +// This function can be called repeatedly after CDVD_GetDir_RPC_request to get the actual entries +// buffer (tocEntry) must be 18KB in size, and this will be filled with a maximum of 128 entries in one go +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries){ + static char toc[2048]; + int toc_entry_num; + + struct dirTocEntry* tocEntryPointer; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + if (getDirTocData.current_entry == 0){ + // if this is the first read then make sure we point to the first real entry + (char*)tocEntryPointer = toc; + (char*)tocEntryPointer += tocEntryPointer->length; + (char*)tocEntryPointer += tocEntryPointer->length; + + getDirTocData.current_sector_offset = (char*)tocEntryPointer - toc; + } + else{ + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + + if (req_entries > 128) + req_entries = 128; + + for (toc_entry_num=0; toc_entry_num < req_entries;){ + if ((tocEntryPointer->length == 0) || (getDirTocData.current_sector_offset >= 2048)){ + // decrease the number of dirs remaining + getDirTocData.num_sectors--; + + if (getDirTocData.num_sectors > 0){ + // If we've run out of entries, but arent on the last sector + // then load another sector + getDirTocData.current_sector++; + + if (CdRead(getDirTocData.current_sector,1,toc,&cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[RPC:cdvd] Couldn't Read from CD !\n"); +#endif + return -1; + } + //CdSync(0x00); + + getDirTocData.current_sector_offset = 0; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + +// continue; + } + else{ + return (toc_entry_num); + } + } + + // This must be incremented even if the filename doesnt match extension list + getDirTocData.current_entry++; + + // We've found a file in this directory + // now check if it matches our extension list (if there is one) + + // Copy the entry regardless, as it makes the comparison easier + // if it doesn't match then it will just be overwritten + TocEntryCopy(&tocEntry[toc_entry_num], tocEntryPointer); + + if (tocEntry[toc_entry_num].fileProperties & 0x02){ + // If this is a subdir, then check if we want to include subdirs + if (getDirTocData.inc_dirs) { + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else{ + if (strlen(getDirTocData.extension_list) > 0){ + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE){ + // increment the number of matching entries counter + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + + } + else{ + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + } +/* + if (strlen(getDirTocData.extension_list) > 0) + { + if (TocEntryCompare(tocEntry[toc_entry_num].filename, getDirTocData.extension_list) == TRUE) + { + + // increment this here, rather than in the main for loop + // since this should count the number of matching entries + toc_entry_num++; + } + + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } + else + { + toc_entry_num++; + getDirTocData.current_sector_offset += tocEntryPointer->length; + (char*)tocEntryPointer = toc + getDirTocData.current_sector_offset; + } +*/ + } + return (toc_entry_num); +} diff --git a/plugins/cdvd/CDVDpeops/CDVDiso.h b/plugins/cdvd/CDVDpeops/CDVDiso.h new file mode 100644 index 0000000..72b0552 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CDVDiso.h @@ -0,0 +1,131 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISO_H__ +#define __CDVDISO_H__ + +#include "CDVDlib.h" + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +int CDVD_GetDir_RPC_request(char* pathname, char* extensions, unsigned int inc_dirs); +int CDVD_GetDir_RPC_get_entries(struct TocEntry tocEntry[], int req_entries); + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTableEntry +{ + u8 dirNameLength; + u8 reserved; + u32 dirTOCLBA; + u16 dirDepth; + u8 dirName[32]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct dirTocEntry +{ + short length; + unsigned int fileLBA; + unsigned int fileLBA_bigend; + unsigned int fileSize; + unsigned int fileSize_bigend; + unsigned char dateStamp[6]; + unsigned char reserved1; + unsigned char fileProperties; + unsigned char reserved2[6]; + unsigned char filenameLength; + unsigned char filename[128]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif // This is the internal format on the CD +// TocEntry structure contains only the important stuff needed for export + +#if defined(__WIN32__) +#pragma pack() +#endif + +#endif//__CDVDISO_H__ diff --git a/plugins/cdvd/CDVDpeops/CDVDisodrv.c b/plugins/cdvd/CDVDpeops/CDVDisodrv.c new file mode 100644 index 0000000..180f89c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CDVDisodrv.c @@ -0,0 +1,264 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#include + +#include "CDVDlib.h" +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +CdRMode cdReadMode; + +struct fdtable{ +//int fd; + int fileSize; + int LBA; + int filePos; +}; + +static struct fdtable fd_table[16]; +static int fd_used[16]; +static int files_open=0; +static int inited=FALSE; + +/************************************************************* +* The functions below are the normal file-system operations, * +* used to provide a standard filesystem interface * +*************************************************************/ + +////////////////////////////////////////////////////////////////////// +// CDVDFS_init +// called by 80000592 sceCdInit() +////////////////////////////////////////////////////////////////////// +void CDVDFS_init(){ + + if (inited) return;//might change in the future as a param; forceInit/Reset + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:init] CDVD Filesystem v1.00\n"); + RPC_LOG("[CDVDisodrv ] \tby A.Lee (aka Hiryu) & Nicholas Van Veen (aka Sjeep)\n"); + RPC_LOG("[CDVDisodrv ] Initializing '%s' file driver.\n", "cdfs"); +#endif + + //CdInit(0); already called by plugin loading system ;) + + cdReadMode.trycount = 0; + cdReadMode.spindlctrl = CdSpinStm; + cdReadMode.datapattern = CdSecS2048; //isofs driver only needs + //2KB sectors + + memset(fd_table, 0, sizeof(fd_table)); + memset(fd_used, 0, 16*sizeof(int)); + + inited = TRUE; + + return; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_open +// called by 80000001 fileio_open for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_open(char *name, int mode){ + register int j; + static struct TocEntry tocEntry; + + // check if the file exists + if (CDVD_findfile(name, &tocEntry) != TRUE) + return -1; + + if(mode != 1) return -2; //SCE_RDONLY + + // set up a new file descriptor + for(j=0; j < 16; j++) if(fd_used[j] == 0) break; + if(j >= 16) return -3; + + fd_used[j] = 1; + files_open++; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:open] internal fd=%d\n", j); +#endif + + fd_table[j].fileSize = tocEntry.fileSize; + fd_table[j].LBA = tocEntry.fileLBA; + fd_table[j].filePos = 0; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv ] tocEntry.fileSize = %d\n",tocEntry.fileSize); +#endif + + return j; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_lseek +// called by 80000001 fileio_lseek for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_lseek(int fd, int offset, int whence){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:lseek] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + switch(whence){ + case SEEK_SET: + fd_table[fd].filePos = offset; + break; + + case SEEK_CUR: + fd_table[fd].filePos += offset; + break; + + case SEEK_END: + fd_table[fd].filePos = fd_table[fd].fileSize + offset; + break; + + default: + return -1; + } + + if (fd_table[fd].filePos < 0) + fd_table[fd].filePos = 0; + + if (fd_table[fd].filePos > fd_table[fd].fileSize) + fd_table[fd].filePos = fd_table[fd].fileSize; + + return fd_table[fd].filePos; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_read +// called by 80000001 fileio_read for devices: "cdrom:", "cdrom0:", "cdfs:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_read( int fd, char *buffer, int size ){ +// int start_sector; + int off_sector; +// int num_sectors; + + //static char local_buffer[2024*2048]; //4MB + static char lb[2048]; //2KB + //Start, Aligned, End + int ssector, asector, esector; + int ssize=0, asize, esize; + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + + // A few sanity checks + if (fd_table[fd].filePos > fd_table[fd].fileSize){ + // We cant start reading from past the beginning of the file + return 0; // File exists but we couldnt read anything from it + } + + if ((fd_table[fd].filePos + size) > fd_table[fd].fileSize) + size = fd_table[fd].fileSize - fd_table[fd].filePos; + + // Now work out where we want to start reading from + asector = ssector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + if (off_sector){ + ssize = min(2048 - off_sector, size); + size -= ssize; + asector++; + } + asize = size & 0xFFFFF800; + esize = size & 0x000007FF; + esector=asector + (asize >> 11); + size += ssize; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n", ssector, esector-(esize==0)); +#endif + + if (ssize){ if (CdRead(ssector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer, lb + off_sector, ssize); + } + if (asize) if (CdRead(asector, asize >> 11, buffer+ssize, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + if (esize){ if (CdRead(esector, 1, lb, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + memcpy(buffer+ssize+asize, lb, esize); + } +/*********************** + // Now work out where we want to start reading from + start_sector = fd_table[fd].LBA + (fd_table[fd].filePos >> 11); + off_sector = (fd_table[fd].filePos & 0x7FF); + num_sectors = ((off_sector + size) >> 11) + 1; + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:read] read sectors 0x%08X to 0x%08X\n",start_sector,start_sector+num_sectors); +#endif + + // Read the data (we only ever get 16KB max request at once) + if (CdRead(start_sector, num_sectors, local_buffer, &cdReadMode) != TRUE){ +#ifdef RPC_LOG + //RPC_LOG("sector = %d, start sector = %d\n",sector,start_sector); + RPC_LOG("[CDVDisodrv: ] Couldn't Read from file for some reason\n"); +#endif + return 0; + } + //CdSync(0); hm, a wait function maybe... + + memcpy(buffer,local_buffer+off_sector,size); +**************************/ + fd_table[fd].filePos += size; + + return (size); +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_write +// called by 80000001 fileio_write for devices: "cdrom:", "cdrom0:" +// hehe, this ain't a CD writing option :D +////////////////////////////////////////////////////////////////////// +int CDVDFS_write( int fd, char * buffer, int size ){ + if(size == 0) return 0; + else return -1; +} + +////////////////////////////////////////////////////////////////////// +// CDVDFS_close +// called by 80000001 fileio_close for devices: "cdrom:", "cdrom0:" +////////////////////////////////////////////////////////////////////// +int CDVDFS_close( int fd){ + + if ((fd >= 16) || (fd_used[fd]==0)){ +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] ERROR: File does not appear to be open!\n"); +#endif + return -1; + } + +#ifdef RPC_LOG + RPC_LOG("[CDVDisodrv:close] internal fd %d\n", fd); +#endif + + fd_used[fd] = 0; + files_open--; + + return 0; +} + diff --git a/plugins/cdvd/CDVDpeops/CDVDisodrv.h b/plugins/cdvd/CDVDpeops/CDVDisodrv.h new file mode 100644 index 0000000..dcf8545 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CDVDisodrv.h @@ -0,0 +1,22 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Modified by Florin for PCSX2 emu + */ + +#ifndef __CDVDISODRV_H__ +#define __CDVDISODRV_H__ + +//#include "Common.h" +#include "CDVDlib.h" + +extern CdRMode cdReadMode; + +/* Filing-system exported functions */ +void CDVDFS_init(); +int CDVDFS_open(char *name, int mode); +int CDVDFS_lseek(int fd, int offset, int whence); +int CDVDFS_read( int fd, char * buffer, int size ); +int CDVDFS_write( int fd, char * buffer, int size ); +int CDVDFS_close( int fd); + +#endif//__CDVDISODRV_H__ diff --git a/plugins/cdvd/CDVDpeops/CDVDlib.h b/plugins/cdvd/CDVDpeops/CDVDlib.h new file mode 100644 index 0000000..f2c2f87 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CDVDlib.h @@ -0,0 +1,189 @@ +/* + * Original code from libcdvd by Hiryu & Sjeep (C) 2002 + * Linux kernel headers + * Modified by Florin for PCSX2 emu + */ + +#ifndef _CDVDLIB_H +#define _CDVDLIB_H + +#define __WIN32__ +#define __MSCW32__ +#define CDVDdefs +#include "PS2Etypes.h" +#include "PS2Edefs.h" + +// Macros for READ Data pattan +#define CdSecS2048 0 // sector size 2048 +#define CdSecS2328 1 // sector size 2328 +#define CdSecS2340 2 // sector size 2340 + +//#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /*2340*/ +//#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /*2336*/ +//#define CD_HEAD_SIZE 4 /* header (address) bytes per raw data frame */ +//#define CD_SUBHEAD_SIZE 8 /* subheader bytes per raw XA data frame */ +//#define CD_XA_HEAD (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */ + +/* + * A CD-ROM physical sector size is 2048, 2052, 2056, 2324, 2332, 2336, + * 2340, or 2352 bytes long. + * Sector types of the standard CD-ROM data formats: + * + * format sector type user data size (bytes) + * ----------------------------------------------------------------------------- + * 1 (Red Book) CD-DA 2352 (CD_FRAMESIZE_RAW) + * 2 (Yellow Book) Mode1 Form1 2048 (CD_FRAMESIZE) + * 3 (Yellow Book) Mode1 Form2 2336 (CD_FRAMESIZE_RAW0) + * 4 (Green Book) Mode2 Form1 2048 (CD_FRAMESIZE) + * 5 (Green Book) Mode2 Form2 2328 (2324+4 spare bytes) + * + * + * The layout of the standard CD-ROM data formats: + * ----------------------------------------------------------------------------- + * - audio (red): | audio_sample_bytes | + * | 2352 | + * + * - data (yellow, mode1): | sync - head - data - EDC - zero - ECC | + * | 12 - 4 - 2048 - 4 - 8 - 276 | + * + * - data (yellow, mode2): | sync - head - data | + * | 12 - 4 - 2336 | + * + * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC | + * | 12 - 4 - 8 - 2048 - 4 - 276 | + * + * - XA data (green, mode2 form2): | sync - head - sub - data - Spare | + * | 12 - 4 - 8 - 2324 - 4 | + * + */ + +// Macros for Spindle control +#define CdSpinMax 0 +#define CdSpinNom 1 // Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. +#define CdSpinStm 0 // Recommended stream rotation speed. + +// Macros for TrayReq +#define CdTrayOpen 0 +#define CdTrayClose 1 +#define CdTrayCheck 2 + +/* + * Macros for sceCdGetDiskType() //comments translated from japanese;) + */ +#define SCECdIllgalMedia 0xff + /* ILIMEDIA (Illegal Media) + A non-PS / non-PS2 Disc. */ +#define SCECdDVDV 0xfe + /* DVDV (DVD Video) + A non-PS / non-PS2 Disc, but a DVD Video Disc */ +#define SCECdCDDA 0xfd + /* CDDA (CD DA) + A non-PS / non-PS2 Disc that include a DA track */ +#define SCECdPS2DVD 0x14 + /* PS2DVD PS2 consumer DVD. */ +#define SCECdPS2CDDA 0x13 + /* PS2CDDA PS2 consumer CD that includes a DA track */ +#define SCECdPS2CD 0x12 + /* PS2CD PS2 consumer CD that does not include a DA track */ +#define SCECdPSCDDA 0x11 + /* PSCDDA PS CD that includes a DA track */ +#define SCECdPSCD 0x10 + /* PSCD PS CD that does not include a DA track */ +#define SCECdDETCT 0x01 + /* DETCT (Detecting) Disc distinction action */ +#define SCECdNODISC 0x00 + /* NODISC (No disc) No disc entered */ + +/* + * Media mode + */ +#define SCECdCD 1 +#define SCECdDVD 2 + +typedef struct { + u8 stat; // 0: normal. Any other: error + u8 second; // second (BCD value) + u8 minute; // minute (BCD value) + u8 hour; // hour (BCD value) + u8 week; // week (BCD value) + u8 day; // day (BCD value) + u8 month; // month (BCD value) + u8 year; // year (BCD value) +} CdCLOCK; + +typedef struct { + u32 lsn; // Logical sector number of file + u32 size; // File size (in bytes) + char name[16]; // Filename + u8 date[8]; // 1th: Seconds + // 2th: Minutes + // 3th: Hours + // 4th: Date + // 5th: Month + // 6th 7th: Year (4 digits) +} CdlFILE; + +typedef struct { + u8 minute; // Minutes + u8 second; // Seconds + u8 sector; // Sector + u8 track; // Track number +} CdlLOCCD; + +typedef struct { + u8 trycount; // Read try count (No. of error retries + 1) (0 - 255) + u8 spindlctrl; // SCECdSpinStm: Recommended stream rotation speed. + // SCECdSpinNom: Starts reading data at maximum rotational velocity and if a read error occurs, the rotational velocity is reduced. + u8 datapattern; // SCECdSecS2048: Data size 2048 bytes + // SCECdSecS2328: 2328 bytes + // SCECdSecS2340: 2340 bytes + u8 pad; // Padding data produced by alignment. +} CdRMode; + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct TocEntry +{ + u32 fileLBA; + u32 fileSize; + u8 fileProperties; + u8 padding1[3]; + u8 filename[128+1]; + u8 date[7]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +#if defined(__WIN32__) +#pragma pack() +#endif + +int CDVD_findfile(char* fname, struct TocEntry* tocEntry); +/* +int CdBreak(void); +int CdCallback( void (*func)() ); +int CdDiskReady(int mode); +int CdGetDiskType(void); +int CdGetError(void); +u32 CdGetReadPos(void); +int CdGetToc(u8 *toc); +int CdInit(int init_mode); +CdlLOCCD *CdIntToPos(int i, CdlLOCCD *p); +int CdPause(void); +int CdPosToInt(CdlLOCCD *p);*/ +int CdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +int DvdRead(u32 lsn, u32 sectors, void *buf, CdRMode *mode); +/*int CdReadClock(CdCLOCK *rtc); +int CdSearchFile (CdlFILE *fp, const char *name); +int CdSeek(u32 lsn); +int CdStandby(void); +int CdStatus(void); +int CdStop(void); +int CdSync(int mode); +int CdTrayReq(int mode, u32 *traycnt); +*/ +#endif // _CDVDLIB_H diff --git a/plugins/cdvd/CDVDpeops/CLEAN.BAT b/plugins/cdvd/CDVDpeops/CLEAN.BAT new file mode 100644 index 0000000..cbeb91c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CLEAN.BAT @@ -0,0 +1,3 @@ +del *.o +del *.c~ +del *.h~ \ No newline at end of file diff --git a/plugins/cdvd/CDVDpeops/Cdr.c b/plugins/cdvd/CDVDpeops/Cdr.c new file mode 100644 index 0000000..1665333 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Cdr.c @@ -0,0 +1,856 @@ +/*************************************************************************** + cdr.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/25 - Pete +// - added an hack in CDVDgetTD for big dvds +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops cdvd release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#include +#include "resource.h" +#define _IN_CDR +#include "externals.h" +#define CDVDdefs +#include "PS2Etypes.h" +#include "PS2Edefs.h" +#include "libiso.h" + +#ifdef DBGOUT +#define SMALLDEBUG 1 +#include +#endif + +///////////////////////////////////////////////////////// +// PCSX2 CDVD interface: + +EXPORT_GCC char * CALLBACK PS2EgetLibName(); +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType(); +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type); +EXPORT_GCC long CALLBACK CDVDinit(); +EXPORT_GCC void CALLBACK CDVDshutdown(); +EXPORT_GCC long CALLBACK CDVDopen(const char* pTitle); +EXPORT_GCC void CALLBACK CDVDclose(); +EXPORT_GCC long CALLBACK CDVDtest(); +EXPORT_GCC long CALLBACK CDVDreadTrack(unsigned long lsn, int mode); +EXPORT_GCC unsigned char * CALLBACK CDVDgetBuffer(); +EXPORT_GCC long CALLBACK CDVDgetTN(cdvdTN *Buffer); +EXPORT_GCC long CALLBACK CDVDgetTD(unsigned char track, cdvdTD *Buffer); +EXPORT_GCC long CALLBACK CDVDgetDiskType(); +EXPORT_GCC long CALLBACK CDVDgetTrayStatus(); + +///////////////////////////////////////////////////////// + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 1; +const unsigned char build = 2; +char *libraryName = "P.E.Op.S. CDVD Driver (CDDA mod)"; + +///////////////////////////////////////////////////////// + +BOOL bIsOpen=FALSE; // flag: open called once +BOOL bCDDAPlay=FALSE; // flag: audio is playing +int iCDROK=0; // !=0: cd is ok +int iCDType=CDVD_TYPE_UNKNOWN; // CD/DVD +int iCheckTrayStatus=0; // if 0 : report tray as closed, else try a real check +void *fdump; + +///////////////////////////////////////////////////////// +// usual info funcs + +EXPORT_GCC char * CALLBACK PS2EgetLibName() +{ + return libraryName; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType() +{ + return PS2E_LT_CDVD; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type) +{ + return version<<16|revision<<8|build; +} +/* +EXPORT_GCC unsigned long CALLBACK PS2EgetCpuPlatform(void) +{ + return PS2E_X86; +// return PS2E_X86_64; +}*/ + +s32 msf_to_lba(u8 m, u8 s, u8 f) { + u32 lsn; + lsn = f; + lsn+=(s - 2) * 75; + lsn+= m * 75 * 60; + return lsn; +} + +void lba_to_msf(s32 lba, u8* m, u8* s, u8* f) { + lba += 150; + *m = (u8)(lba / (60*75)); + *s = (u8)((lba / 75) % 60); + *f = (u8)(lba % 75); +} + +///////////////////////////////////////////////////////// +// init: called once at library load + +EXPORT_GCC long CALLBACK CDVDinit() +{ + szSUBF[0]=0; // just init the filename buffers + szPPF[0] =0; + return 0; +} + +///////////////////////////////////////////////////////// +// shutdown: called once at final exit + +EXPORT_GCC void CALLBACK CDVDshutdown() +{ +} + +///////////////////////////////////////////////////////// +// open: called, when games starts/cd has been changed + +int CheckDiskType(int baseType); + +EXPORT_GCC long CALLBACK CDVDopen(const char* pTitle) +{ + int i,audioTracks,dataTracks; + cdvdTD T; + if(bIsOpen) // double-open check (if the main emu coder doesn't know what he is doing ;) + { + if(iCDROK<=0) return -1; + else return 0; + } + + bIsOpen=TRUE; // ok, open func called once + + ReadConfig(); // read user config + + BuildPPFCache(); // build ppf cache + + BuildSUBCache(); // build sub cache + + CreateREADBufs(); // setup generic read buffers + + CreateGenEvent(); // create read event + + iCDROK=OpenGenCD(iCD_AD,iCD_TA,iCD_LU); // generic open, setup read func + + if(iCDROK<=0) {iCDROK=0;return -1;} + + ReadTOC(); // read the toc + + SetGenCDSpeed(0); // try to change the reading speed (if wanted) + + iCDType=CDVD_TYPE_UNKNOWN; // let's look after the disc type + // (funny stuff taken from Xobro's/Florin's bin plugin) + if(CDVDreadTrack(16,CDVD_MODE_2048)==0) + { + struct cdVolDesc *volDesc; + volDesc=(struct cdVolDesc *)CDVDgetBuffer(); + if(volDesc) + { + +//todo: CDVD_TYPE_CDDA + + if(volDesc->rootToc.tocSize==2048) + iCDType = CDVD_TYPE_DETCTCD; + else iCDType = CDVD_TYPE_DETCTDVDS; + } + } + + fprintf(stderr," * CDVD Disk Open: %d tracks (%d to %d):\n",sTOC.cLastTrack-sTOC.cFirstTrack+1,sTOC.cFirstTrack,sTOC.cLastTrack); + + audioTracks=dataTracks=0; + for(i=sTOC.cFirstTrack;i<=sTOC.cLastTrack;i++) + { + CDVDgetTD(i,&T); + if(T.type==CDVD_AUDIO_TRACK) { + audioTracks++; + fprintf(stderr," * * Track %d: Audio (%d sectors)\n",i,T.lsn); + } + else { + dataTracks++; + fprintf(stderr," * * Track %d: Data (Mode %d) (%d sectors)\n",i,((T.type==CDVD_MODE1_TRACK)?1:2),T.lsn); + } + } + if((dataTracks==0)&&(audioTracks>0)) + iCDType=CDVD_TYPE_CDDA; + else if(dataTracks>0) + iCDType=CheckDiskType(iCDType); + + if((iCDType==CDVD_TYPE_ILLEGAL)&&(audioTracks>0)) + iCDType=CDVD_TYPE_CDDA; + else if((iCDType==CDVD_TYPE_PS2CD)&&(audioTracks>0)) + iCDType=CDVD_TYPE_PS2CDDA; + else if((iCDType==CDVD_TYPE_PSCD)&&(audioTracks>0)) + iCDType=CDVD_TYPE_PSCDDA; + + switch(iCDType) { + case CDVD_TYPE_ILLEGAL: // Illegal Disc + fprintf(stderr," * Disk Type: Illegal Disk.\n");break; + case CDVD_TYPE_DVDV: // DVD Video + fprintf(stderr," * Disk Type: DVD Video.\n");break; + case CDVD_TYPE_CDDA: // Audio CD + fprintf(stderr," * Disk Type: CDDA.\n");break; + case CDVD_TYPE_PS2DVD: // PS2 DVD + fprintf(stderr," * Disk Type: PS2 DVD.\n");break; + case CDVD_TYPE_PS2CDDA: // PS2 CD (with audio) + fprintf(stderr," * Disk Type: PS2 CD+Audio.\n");break; + case CDVD_TYPE_PS2CD: // PS2 CD + fprintf(stderr," * Disk Type: PS2 CD.\n");break; + case CDVD_TYPE_PSCDDA: // PS CD (with audio) + fprintf(stderr," * Disk Type: PS1 CD+Audio.\n");break; + case CDVD_TYPE_PSCD: // PS CD + fprintf(stderr," * Disk Type: PS1 CD.\n");break; + case CDVD_TYPE_UNKNOWN: // Unknown + fprintf(stderr," * Disk Type: Unknown.\n");break; + case CDVD_TYPE_NODISC: // No Disc + fprintf(stderr," * Disk Type: No Disc.\n");break; + } + +/* if (iBlockDump)*/ { +// fdump = isoCreate("block.dump", ISOFLAGS_BLOCKDUMP); + fdump = NULL; + if (fdump) { + cdvdTD buf; + CDVDgetTD(0, &buf); + isoSetFormat(fdump, 0, 2352, buf.lsn); + } + } /*else { + fdump = NULL; + }*/ + + + return 0; // ok, done +} + +///////////////////////////////////////////////////////// +// close: called when emulation stops + +EXPORT_GCC void CALLBACK CDVDclose() +{ + if(!bIsOpen) return; // no open? no close... + + if (fdump != NULL) { + isoClose(fdump); + } + bIsOpen=FALSE; // no more open + + LockGenCDAccess(); // make sure that no more reading is happening + + if(iCDROK) // cd was ok? + { + if(bCDDAPlay) {DoCDDAPlay(0);bCDDAPlay=FALSE;} // -> cdda playing? stop it + SetGenCDSpeed(1); // -> repair speed + CloseGenCD(); // -> cd not used anymore + } + + UnlockGenCDAccess(); + + FreeREADBufs(); // free read bufs + FreeGenEvent(); // free event + FreePPFCache(); // free ppf cache + FreeSUBCache(); // free sub cache +} + +///////////////////////////////////////////////////////// +// test: ah, well, always fine + +EXPORT_GCC long CALLBACK CDVDtest() +{ + return 0; +} + +///////////////////////////////////////////////////////// +// readSubQ: read subq from disc (only cds have subq data) +EXPORT_GCC long CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) +{ + u8 min, sec, frm; + + if(!bIsOpen) CDVDopen("DVD"); // usual checks + if(!iCDROK) return -1; + + // fake it + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = itob(1); + subq->trackIndex= itob(1); + + lba_to_msf(lsn, &min, &sec, &frm); + subq->trackM = itob(min); + subq->trackS = itob(sec); + subq->trackF = itob(frm); + + subq->pad = 0; + + lba_to_msf(lsn + (2*75), &min, &sec, &frm); + subq->discM = itob(min); + subq->discS = itob(sec); + subq->discF = itob(frm); + return 0; +} + +///////////////////////////////////////////////////////// +// gettoc: ps2 style TOC +EXPORT_GCC long CALLBACK CDVDgetTOC(void* toc) +{ + u32 type; + u8* tocBuff = (u8*)toc; + + if(!bIsOpen) CDVDopen("DVD"); // not open? funny emu... + + if(!iCDROK) return -1; // cd not ok? + + type = CDVDgetDiskType(); + + if( type == CDVD_TYPE_DVDV || + type == CDVD_TYPE_PS2DVD) + { + // get dvd structure format + // scsi command 0x43 + memset(tocBuff, 0, 2048); + // fake it + tocBuff[ 0] = 0x04; + tocBuff[ 1] = 0x02; + tocBuff[ 2] = 0xF2; + tocBuff[ 3] = 0x00; + tocBuff[ 4] = 0x86; + tocBuff[ 5] = 0x72; + + tocBuff[16] = 0x00; + tocBuff[17] = 0x03; + tocBuff[18] = 0x00; + tocBuff[19] = 0x00; + } + else if(type == CDVD_TYPE_CDDA || + type == CDVD_TYPE_PS2CDDA || + type == CDVD_TYPE_PS2CD || + type == CDVD_TYPE_PSCDDA || + type == CDVD_TYPE_PSCD) + { + // cd toc + // (could be replaced by 1 command that reads the full toc) + u8 min, sec, frm,i; + s32 err; + cdvdTN diskInfo; + cdvdTD trackInfo; + memset(tocBuff, 0, 1024); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + tocBuff[0] = 0x41; + tocBuff[1] = 0x00; + + //Number of FirstTrack + tocBuff[2] = 0xA0; + tocBuff[7] = itob(diskInfo.strack); + + //Number of LastTrack + tocBuff[12] = 0xA1; + tocBuff[17] = itob(diskInfo.etrack); + + //DiskLength + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[22] = 0xA2; + tocBuff[27] = itob(min); + tocBuff[28] = itob(sec); + tocBuff[29] = itob(frm); + + fprintf(stderr,"Track 0: %d mins %d secs %d frames\n",min,sec,frm); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) + { + err = CDVDgetTD(i, &trackInfo); + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[i*10+30] = trackInfo.type; + tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number + tocBuff[i*10+37] = itob(min); + tocBuff[i*10+38] = itob(sec); + tocBuff[i*10+39] = itob(frm); + fprintf(stderr,"Track %d: %d mins %d secs %d frames\n",i,min,sec,frm); + } + } + else + return -1; + + return 0; +} + +///////////////////////////////////////////////////////// +// gettn: first/last track num + +EXPORT_GCC long CALLBACK CDVDgetTN(cdvdTN *Buffer) +{ + if(!bIsOpen) CDVDopen("DVD"); // not open? funny emu... + + if(!iCDROK) // cd not ok? + { + Buffer->strack=1; + Buffer->etrack=1; + return -1; + } + + ReadTOC(); // read the TOC + + Buffer->strack=sTOC.cFirstTrack; // get the infos + Buffer->etrack=sTOC.cLastTrack; + + return 0; +} + +///////////////////////////////////////////////////////// +// gettd: track addr + +EXPORT_GCC long CALLBACK CDVDgetTD(unsigned char track, cdvdTD *Buffer) +{ + unsigned long lu,i; + unsigned char buffer[2352]; + unsigned char *buf; + u8 t1; + + if(!bIsOpen) CDVDopen("DVD"); // not open? funny emu... + + if(!iCDROK) return -1; // cd not ok? bye + + ReadTOC(); // read toc + +/* +// PSEmu style: + if(track==0) // 0 = last track + { + lu=reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr); + addr2time(lu,buffer); + } + else // others: track n + { + lu=reOrder(sTOC.tracks[track-1].lAddr); + addr2time(lu,buffer); + } + + Buffer->minute = buffer[1]; + Buffer->second = buffer[2]; + Buffer->frame = buffer[3]; + Buffer->type = iCDType; +#ifdef DBGOUT + auxprintf("Read Toc %d: %u\n",track,lu); +#endif +*/ + + lu=0; + if(track==0) + lu=reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr); + else + lu=reOrder(sTOC.tracks[track].lAddr); + //addr2time(lu,buffer); + + Buffer->lsn=lu; + + if(track==0) + Buffer->type = iCDType; + else + { + lu=0; + for(i=sTOC.cFirstTrack;itype=t1; + } + + return 0; +} + +///////////////////////////////////////////////////////// +// readtrack: start reading at given address + +EXPORT_GCC long CALLBACK CDVDreadTrack(unsigned long lsn, int mode) +{ + if(!bIsOpen) CDVDopen("DVD"); // usual checks + if(!iCDROK) return -1; + if(bCDDAPlay) bCDDAPlay=FALSE; + +#ifdef DBGOUT + auxprintf("Read Track %u: %d\n",lsn,mode); +#endif + + lLastAccessedAddr=lsn; // store read track values (for getbuffer) + iLastAccessedMode=mode; + + if(!pReadTrackFunc(lLastAccessedAddr)) // start reading + return -1; + + return 0; +} + +///////////////////////////////////////////////////////// +// getbuffer: will be called after readtrack, to get ptr +// to data + +// small helper buffer to get bigger block sizes +unsigned char cDataAndSub[2368]; + +EXPORT_GCC unsigned char * CALLBACK CDVDgetBuffer() +{ + unsigned char * pbuffer; + + if(!bIsOpen) CDVDopen("DVD"); + + if(pGetPtrFunc) pGetPtrFunc(); // get ptr on thread modes + + pbuffer=pCurrReadBuf; // init buffer pointer + if (fdump != NULL) { + isoWriteBlock(fdump, pbuffer, lLastAccessedAddr); + } + + if(iLastAccessedMode!=iUsedMode) + { + switch(iLastAccessedMode) // what does the emu want? + {//------------------------------------------------// + case CDVD_MODE_2048: + { + if(iUsedBlockSize==2352) pbuffer+=24; + }break; + //------------------------------------------------// + case CDVD_MODE_2352: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+24,pbuffer,2048); + pbuffer=cDataAndSub; + } + }break; + //------------------------------------------------// + case CDVD_MODE_2340: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+12,pbuffer,2048); + pbuffer=cDataAndSub; + } + else pbuffer+=12; + }break; + //------------------------------------------------// + case CDVD_MODE_2328: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+0,pbuffer,2048); + pbuffer=cDataAndSub; + } + else pbuffer+=24; + }break; + //------------------------------------------------// + case CDVD_MODE_2368: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+24,pbuffer,2048); + pbuffer=cDataAndSub; + +/* +// NO SUBCHANNEL SUPPORT RIGHT NOW!!! + { + if(subHead) // some sub file? + CheckSUBCache(lLastAccessedAddr); // -> get cached subs + else + if(iUseSubReading!=1 && pCurrSubBuf) // no direct cd sub read? + FakeSubData(lLastAccessedAddr); // -> fake the data + memcpy(cDataAndSub,pCurrReadBuf,2352); + if(pCurrSubBuf) + memcpy(cDataAndSub+2352,pCurrSubBuf+12,16); + pbuffer=cDataAndSub; + } +*/ + + } + }break; + //------------------------------------------------// + } + } + +#ifdef DBGOUT + auxprintf("get buf %d\n",iLastAccessedMode); + +/* +{ + int k; + for(k=0;k<2352;k++) + auxprintf("%02x ",*(pbuffer+k)); + auxprintf("\n\n"); +} +*/ +#endif + + return pbuffer; +} + +///////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK CDVDgetDiskType() +{ + return iCDType; +} + +///////////////////////////////////////////////////////// +// CDVDgetTrayStatus + +EXPORT_GCC long CALLBACK CDVDgetTrayStatus() +{ + static time_t to=0; + static long lLastTrayState=CDVD_TRAY_CLOSE; + + if(to==time(NULL)) return lLastTrayState; // we only check once per second + to = time(NULL); + + lLastTrayState=CDVD_TRAY_CLOSE; // init state with "closed" + + if(iCheckTrayStatus) // user really want a tray check + { + int iStatus; + + LockGenCDAccess(); // make sure that no more reading is happening + iStatus=GetSCSIStatus(iCD_AD,iCD_TA,iCD_LU); // get device status + UnlockGenCDAccess(); + + if(iStatus==SS_ERR) + lLastTrayState=CDVD_TRAY_OPEN; + } + +#ifdef DBGOUT +auxprintf("check %d -> %d\n",to,lLastTrayState); +#endif + + + return lLastTrayState; +} + +EXPORT_GCC s32 CALLBACK CDVDctrlTrayOpen() { + return 0; +} + +EXPORT_GCC s32 CALLBACK CDVDctrlTrayClose() { + return 0; +} + + + +///////////////////////////////////////////////////////// +// configure: shows config window + +EXPORT_GCC void CALLBACK CDVDconfigure() +{ + if(iCDROK) // mmm... someone has already called Open? bad + {MessageBeep((UINT)-1);return;} + + CreateGenEvent(); // we need an event handle + + DialogBox(hInst,MAKEINTRESOURCE(IDD_CONFIG), // call dialog + GetActiveWindow(),(DLGPROC)CDRDlgProc); + + FreeGenEvent(); // free event handle +} + +///////////////////////////////////////////////////////// +// about: shows about window + +EXPORT_GCC void CALLBACK CDVDabout() +{ + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(),(DLGPROC)AboutDlgProc); +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + +/* +// CURRENTLY UNUSED OLD STUFF FROM PSX CD PLUGIN: + +///////////////////////////////////////////////////////// +// audioplay: PLAYSECTOR is NOT BCD coded !!! + +EXPORT_GCC long CALLBACK CDRplay(unsigned char * sector) +{ + if(!bIsOpen) CDVDopen(); + if(!iCDROK) return PSE_ERR_FATAL; + + if(!DoCDDAPlay(time2addr(sector))) // start playing + return PSE_CDR_ERR_NOREAD; + + bCDDAPlay=TRUE; // raise flag: we are playing + + return PSE_CDR_ERR_SUCCESS; +} + +///////////////////////////////////////////////////////// +// audiostop: stops cdda playing + +EXPORT_GCC long CALLBACK CDRstop(void) +{ + if(!bCDDAPlay) return PSE_ERR_FATAL; + + DoCDDAPlay(0); // stop cdda + + bCDDAPlay=FALSE; // reset flag: no more playing + + return PSE_CDR_ERR_SUCCESS; +} + +///////////////////////////////////////////////////////// +// getdriveletter + +EXPORT_GCC char CALLBACK CDRgetDriveLetter(void) +{ + if(!iCDROK) return 0; // not open? no way to get the letter + + if(iInterfaceMode==2 || iInterfaceMode==3) // w2k/xp: easy + { + return MapIOCTLDriveLetter(iCD_AD,iCD_TA,iCD_LU); + } + else // but with aspi??? + { // -> no idea yet (maybe registry read...pfff) + } + + return 0; +} + +///////////////////////////////////////////////////////// +// getstatus: pcsx func... poorly supported here +// problem is: func will be called often, which +// would block all of my cdr reading if I would use +// lotsa scsi commands + +struct CdrStat +{ + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; // current playing time +}; + +struct CdrStat ostat; + +// reads cdr status +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: +// 0x00 - unknown +// 0x02 - error +// 0x08 - seek error +// 0x10 - shell open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + + +EXPORT_GCC long CALLBACK CDRgetStatus(struct CdrStat *stat) +{ + int iStatus; + static time_t to; + + if(!bCDDAPlay) // if not playing update stat only once in a second + { + if(to get pos + stat->Type = 0x02; // -> audio + if(pB) + { + stat->Status|=0x80; // --> playing flag + stat->Time[0]=pB[18]; // --> and curr play time + stat->Time[1]=pB[19]; + stat->Time[2]=pB[20]; + } + } + else // cdda not playing? + { + stat->Type = 0x01; // -> data + } + + LockGenCDAccess(); // make sure that no more reading is happening + iStatus=GetSCSIStatus(iCD_AD,iCD_TA,iCD_LU); // get device status + UnlockGenCDAccess(); + + if(iStatus==SS_ERR) + { // no cdrom? + stat->Type = 0xff; + stat->Status|= 0x10; + } + + memcpy(&ostat, stat, sizeof(struct CdrStat)); + + return 0; +} + +///////////////////////////////////////////////////////// +*/ diff --git a/plugins/cdvd/CDVDpeops/Cdr.c.bak b/plugins/cdvd/CDVDpeops/Cdr.c.bak new file mode 100644 index 0000000..7a6100e --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Cdr.c.bak @@ -0,0 +1,848 @@ +/*************************************************************************** + cdr.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/25 - Pete +// - added an hack in CDVDgetTD for big dvds +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops cdvd release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#include +#include "resource.h" +#define _IN_CDR +#include "externals.h" +#include "libiso.h" + +#ifdef DBGOUT +#define SMALLDEBUG 1 +#include +#endif + +///////////////////////////////////////////////////////// +// PCSX2 CDVD interface: + +EXPORT_GCC char * CALLBACK PS2EgetLibName(); +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType(); +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type); +EXPORT_GCC long CALLBACK CDVDinit(); +EXPORT_GCC void CALLBACK CDVDshutdown(); +EXPORT_GCC long CALLBACK CDVDopen(); +EXPORT_GCC void CALLBACK CDVDclose(); +EXPORT_GCC long CALLBACK CDVDtest(); +EXPORT_GCC long CALLBACK CDVDreadTrack(unsigned long lsn, int mode); +EXPORT_GCC unsigned char * CALLBACK CDVDgetBuffer(); +EXPORT_GCC long CALLBACK CDVDgetTN(cdvdTN *Buffer); +EXPORT_GCC long CALLBACK CDVDgetTD(unsigned char track, cdvdTD *Buffer); +EXPORT_GCC long CALLBACK CDVDgetDiskType(); +EXPORT_GCC long CALLBACK CDVDgetTrayStatus(); + +///////////////////////////////////////////////////////// + +const unsigned char version = PS2E_CDVD_VERSION; +const unsigned char revision = 1; +const unsigned char build = 2; +char *libraryName = "P.E.Op.S. CDVD Driver (CDDA mod)"; + +///////////////////////////////////////////////////////// + +BOOL bIsOpen=FALSE; // flag: open called once +BOOL bCDDAPlay=FALSE; // flag: audio is playing +int iCDROK=0; // !=0: cd is ok +int iCDType=CDVD_TYPE_UNKNOWN; // CD/DVD +int iCheckTrayStatus=0; // if 0 : report tray as closed, else try a real check +void *fdump; + +///////////////////////////////////////////////////////// +// usual info funcs + +EXPORT_GCC char * CALLBACK PS2EgetLibName() +{ + return libraryName; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType() +{ + return PS2E_LT_CDVD; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type) +{ + return version<<16|revision<<8|build; +} +/* +EXPORT_GCC unsigned long CALLBACK PS2EgetCpuPlatform(void) +{ + return PS2E_X86; +// return PS2E_X86_64; +}*/ + +s32 msf_to_lba(u8 m, u8 s, u8 f) { + u32 lsn; + lsn = f; + lsn+=(s - 2) * 75; + lsn+= m * 75 * 60; + return lsn; +} + +void lba_to_msf(s32 lba, u8* m, u8* s, u8* f) { + lba += 150; + *m = lba / (60*75); + *s = (lba / 75) % 60; + *f = lba % 75; +} + +///////////////////////////////////////////////////////// +// init: called once at library load + +EXPORT_GCC long CALLBACK CDVDinit() +{ + szSUBF[0]=0; // just init the filename buffers + szPPF[0] =0; + return 0; +} + +///////////////////////////////////////////////////////// +// shutdown: called once at final exit + +EXPORT_GCC void CALLBACK CDVDshutdown() +{ +} + +///////////////////////////////////////////////////////// +// open: called, when games starts/cd has been changed + +int CheckDiskType(int baseType); + +EXPORT_GCC long CALLBACK CDVDopen() +{ + int i,audioTracks,dataTracks; + cdvdTD T; + if(bIsOpen) // double-open check (if the main emu coder doesn't know what he is doing ;) + { + if(iCDROK<=0) return -1; + else return 0; + } + + bIsOpen=TRUE; // ok, open func called once + + ReadConfig(); // read user config + + BuildPPFCache(); // build ppf cache + + BuildSUBCache(); // build sub cache + + CreateREADBufs(); // setup generic read buffers + + CreateGenEvent(); // create read event + + iCDROK=OpenGenCD(iCD_AD,iCD_TA,iCD_LU); // generic open, setup read func + + if(iCDROK<=0) {iCDROK=0;return -1;} + + ReadTOC(); // read the toc + + SetGenCDSpeed(0); // try to change the reading speed (if wanted) + + iCDType=CDVD_TYPE_UNKNOWN; // let's look after the disc type + // (funny stuff taken from Xobro's/Florin's bin plugin) + if(CDVDreadTrack(16,CDVD_MODE_2048)==0) + { + struct cdVolDesc *volDesc; + volDesc=(struct cdVolDesc *)CDVDgetBuffer(); + if(volDesc) + { + +//todo: CDVD_TYPE_CDDA + + if(volDesc->rootToc.tocSize==2048) + iCDType = CDVD_TYPE_DETCTCD; + else iCDType = CDVD_TYPE_DETCTDVDS; + } + } + + fprintf(stderr," * CDVD Disk Open: %d tracks (%d to %d):\n",sTOC.cLastTrack-sTOC.cFirstTrack+1,sTOC.cFirstTrack,sTOC.cLastTrack); + + audioTracks=dataTracks=0; + for(i=sTOC.cFirstTrack;i<=sTOC.cLastTrack;i++) + { + CDVDgetTD(i,&T); + if(T.type==CDVD_AUDIO_TRACK) { + audioTracks++; + fprintf(stderr," * * Track %d: Audio (%d sectors)\n",i,T.lsn); + } + else { + dataTracks++; + fprintf(stderr," * * Track %d: Data (Mode %d) (%d sectors)\n",i,((T.type==CDVD_MODE1_TRACK)?1:2),T.lsn); + } + } + if((dataTracks==0)&&(audioTracks>0)) + iCDType=CDVD_TYPE_CDDA; + else if(dataTracks>0) + iCDType=CheckDiskType(iCDType); + + if((iCDType==CDVD_TYPE_ILLEGAL)&&(audioTracks>0)) + iCDType=CDVD_TYPE_CDDA; + else if((iCDType==CDVD_TYPE_PS2CD)&&(audioTracks>0)) + iCDType=CDVD_TYPE_PS2CDDA; + else if((iCDType==CDVD_TYPE_PSCD)&&(audioTracks>0)) + iCDType=CDVD_TYPE_PSCDDA; + + switch(iCDType) { + case CDVD_TYPE_ILLEGAL: // Illegal Disc + fprintf(stderr," * Disk Type: Illegal Disk.\n");break; + case CDVD_TYPE_DVDV: // DVD Video + fprintf(stderr," * Disk Type: DVD Video.\n");break; + case CDVD_TYPE_CDDA: // Audio CD + fprintf(stderr," * Disk Type: CDDA.\n");break; + case CDVD_TYPE_PS2DVD: // PS2 DVD + fprintf(stderr," * Disk Type: PS2 DVD.\n");break; + case CDVD_TYPE_PS2CDDA: // PS2 CD (with audio) + fprintf(stderr," * Disk Type: PS2 CD+Audio.\n");break; + case CDVD_TYPE_PS2CD: // PS2 CD + fprintf(stderr," * Disk Type: PS2 CD.\n");break; + case CDVD_TYPE_PSCDDA: // PS CD (with audio) + fprintf(stderr," * Disk Type: PS1 CD+Audio.\n");break; + case CDVD_TYPE_PSCD: // PS CD + fprintf(stderr," * Disk Type: PS1 CD.\n");break; + case CDVD_TYPE_UNKNOWN: // Unknown + fprintf(stderr," * Disk Type: Unknown.\n");break; + case CDVD_TYPE_NODISC: // No Disc + fprintf(stderr," * Disk Type: No Disc.\n");break; + } + +/* if (iBlockDump)*/ { +// fdump = isoCreate("block.dump", ISOFLAGS_BLOCKDUMP); + fdump = NULL; + if (fdump) { + cdvdTD buf; + CDVDgetTD(0, &buf); + isoSetFormat(fdump, 0, 2352, buf.lsn); + } + } /*else { + fdump = NULL; + }*/ + + + return 0; // ok, done +} + +///////////////////////////////////////////////////////// +// close: called when emulation stops + +EXPORT_GCC void CALLBACK CDVDclose() +{ + if(!bIsOpen) return; // no open? no close... + + if (fdump != NULL) { + isoClose(fdump); + } + bIsOpen=FALSE; // no more open + + LockGenCDAccess(); // make sure that no more reading is happening + + if(iCDROK) // cd was ok? + { + if(bCDDAPlay) {DoCDDAPlay(0);bCDDAPlay=FALSE;} // -> cdda playing? stop it + SetGenCDSpeed(1); // -> repair speed + CloseGenCD(); // -> cd not used anymore + } + + UnlockGenCDAccess(); + + FreeREADBufs(); // free read bufs + FreeGenEvent(); // free event + FreePPFCache(); // free ppf cache + FreeSUBCache(); // free sub cache +} + +///////////////////////////////////////////////////////// +// test: ah, well, always fine + +EXPORT_GCC long CALLBACK CDVDtest() +{ + return 0; +} + +///////////////////////////////////////////////////////// +// readSubQ: read subq from disc (only cds have subq data) +EXPORT_GCC long CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq) +{ + if(!bIsOpen) CDVDopen(); // usual checks + if(!iCDROK) return -1; + + // fake it + u8 min, sec, frm; + subq->ctrl = 4; + subq->mode = 1; + subq->trackNum = itob(1); + subq->trackIndex= itob(1); + + lba_to_msf(lsn, &min, &sec, &frm); + subq->trackM = itob(min); + subq->trackS = itob(sec); + subq->trackF = itob(frm); + + subq->pad = 0; + + lba_to_msf(lsn + (2*75), &min, &sec, &frm); + subq->discM = itob(min); + subq->discS = itob(sec); + subq->discF = itob(frm); + return 0; +} + +///////////////////////////////////////////////////////// +// gettoc: ps2 style TOC +EXPORT_GCC long CALLBACK CDVDgetTOC(void* toc) +{ + u32 type; + u8* tocBuff = (u8*)toc; + + if(!bIsOpen) CDVDopen(); // not open? funny emu... + + if(!iCDROK) return -1; // cd not ok? + + type = CDVDgetDiskType(); + + if( type == CDVD_TYPE_DVDV || + type == CDVD_TYPE_PS2DVD) + { + // get dvd structure format + // scsi command 0x43 + memset(tocBuff, 0, 2048); + // fake it + tocBuff[ 0] = 0x04; + tocBuff[ 1] = 0x02; + tocBuff[ 2] = 0xF2; + tocBuff[ 3] = 0x00; + tocBuff[ 4] = 0x86; + tocBuff[ 5] = 0x72; + + tocBuff[16] = 0x00; + tocBuff[17] = 0x03; + tocBuff[18] = 0x00; + tocBuff[19] = 0x00; + } + else if(type == CDVD_TYPE_CDDA || + type == CDVD_TYPE_PS2CDDA || + type == CDVD_TYPE_PS2CD || + type == CDVD_TYPE_PSCDDA || + type == CDVD_TYPE_PSCD) + { + // cd toc + // (could be replaced by 1 command that reads the full toc) + u8 min, sec, frm,i; + s32 err; + cdvdTN diskInfo; + cdvdTD trackInfo; + memset(tocBuff, 0, 1024); + if (CDVDgetTN(&diskInfo) == -1) { diskInfo.etrack = 0;diskInfo.strack = 1; } + if (CDVDgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0; + + tocBuff[0] = 0x41; + tocBuff[1] = 0x00; + + //Number of FirstTrack + tocBuff[2] = 0xA0; + tocBuff[7] = itob(diskInfo.strack); + + //Number of LastTrack + tocBuff[12] = 0xA1; + tocBuff[17] = itob(diskInfo.etrack); + + //DiskLength + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[22] = 0xA2; + tocBuff[27] = itob(min); + tocBuff[28] = itob(sec); + tocBuff[29] = itob(frm); + + for (i=diskInfo.strack; i<=diskInfo.etrack; i++) + { + err = CDVDgetTD(i, &trackInfo); + lba_to_msf(trackInfo.lsn, &min, &sec, &frm); + tocBuff[i*10+30] = trackInfo.type; + tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number + tocBuff[i*10+37] = itob(min); + tocBuff[i*10+38] = itob(sec); + tocBuff[i*10+39] = itob(frm); + } + } + else + return -1; + + return 0; +} + +EXPORT_GCC long CALLBACK CDVDctrlTrayOpen() +{ + return 0; +} + +EXPORT_GCC long CALLBACK CDVDctrlTrayClose() +{ + return 0; +} + + +///////////////////////////////////////////////////////// +// gettn: first/last track num + +EXPORT_GCC long CALLBACK CDVDgetTN(cdvdTN *Buffer) +{ + if(!bIsOpen) CDVDopen(); // not open? funny emu... + + if(!iCDROK) // cd not ok? + { + Buffer->strack=1; + Buffer->etrack=1; + return -1; + } + + ReadTOC(); // read the TOC + + Buffer->strack=sTOC.cFirstTrack; // get the infos + Buffer->etrack=sTOC.cLastTrack; + + return 0; +} + +///////////////////////////////////////////////////////// +// gettd: track addr + +EXPORT_GCC long CALLBACK CDVDgetTD(unsigned char track, cdvdTD *Buffer) +{ + unsigned long lu,i; + unsigned char buffer[2352]; + unsigned char *buf; + u8 t1; + + if(!bIsOpen) CDVDopen(); // not open? funny emu... + + if(!iCDROK) return -1; // cd not ok? bye + + ReadTOC(); // read toc + +/* +// PSEmu style: + if(track==0) // 0 = last track + { + lu=reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr); + addr2time(lu,buffer); + } + else // others: track n + { + lu=reOrder(sTOC.tracks[track-1].lAddr); + addr2time(lu,buffer); + } + + Buffer->minute = buffer[1]; + Buffer->second = buffer[2]; + Buffer->frame = buffer[3]; + Buffer->type = iCDType; +#ifdef DBGOUT + auxprintf("Read Toc %d: %u\n",track,lu); +#endif +*/ + + lu=0; + if(track==0) + lu=reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr); + else + lu=reOrder(sTOC.tracks[track].lAddr); + //addr2time(lu,buffer); + + Buffer->lsn=lu; + + if(track==0) + Buffer->type = iCDType; + else + { + lu=0; + for(i=sTOC.cFirstTrack;itype=t1; + } + + return 0; +} + +///////////////////////////////////////////////////////// +// readtrack: start reading at given address + +EXPORT_GCC long CALLBACK CDVDreadTrack(unsigned long lsn, int mode) +{ + if(!bIsOpen) CDVDopen(); // usual checks + if(!iCDROK) return -1; + if(bCDDAPlay) bCDDAPlay=FALSE; + +#ifdef DBGOUT + auxprintf("Read Track %u: %d\n",lsn,mode); +#endif + + lLastAccessedAddr=lsn; // store read track values (for getbuffer) + iLastAccessedMode=mode; + + if(!pReadTrackFunc(lLastAccessedAddr)) // start reading + return -1; + + return 0; +} + +///////////////////////////////////////////////////////// +// getbuffer: will be called after readtrack, to get ptr +// to data + +// small helper buffer to get bigger block sizes +unsigned char cDataAndSub[2368]; + +EXPORT_GCC unsigned char * CALLBACK CDVDgetBuffer() +{ + unsigned char * pbuffer; + + if(!bIsOpen) CDVDopen(); + + if(pGetPtrFunc) pGetPtrFunc(); // get ptr on thread modes + + pbuffer=pCurrReadBuf; // init buffer pointer + + if(iLastAccessedMode!=iUsedMode) + { + switch(iLastAccessedMode) // what does the emu want? + {//------------------------------------------------// + case CDVD_MODE_2048: + { + if(iUsedBlockSize==2352) pbuffer+=24; + }break; + //------------------------------------------------// + case CDVD_MODE_2352: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+24,pbuffer,2048); + pbuffer=cDataAndSub; + } + }break; + //------------------------------------------------// + case CDVD_MODE_2340: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+12,pbuffer,2048); + pbuffer=cDataAndSub; + } + else pbuffer+=12; + }break; + //------------------------------------------------// + case CDVD_MODE_2328: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+0,pbuffer,2048); + pbuffer=cDataAndSub; + } + else pbuffer+=24; + }break; + //------------------------------------------------// + case CDVD_MODE_2368: + { + if(iUsedBlockSize==2048) + { + memset(cDataAndSub,0,2368); + memcpy(cDataAndSub+24,pbuffer,2048); + pbuffer=cDataAndSub; + +/* +// NO SUBCHANNEL SUPPORT RIGHT NOW!!! + { + if(subHead) // some sub file? + CheckSUBCache(lLastAccessedAddr); // -> get cached subs + else + if(iUseSubReading!=1 && pCurrSubBuf) // no direct cd sub read? + FakeSubData(lLastAccessedAddr); // -> fake the data + memcpy(cDataAndSub,pCurrReadBuf,2352); + if(pCurrSubBuf) + memcpy(cDataAndSub+2352,pCurrSubBuf+12,16); + pbuffer=cDataAndSub; + } +*/ + + } + }break; + //------------------------------------------------// + } + } + +#ifdef DBGOUT + auxprintf("get buf %d\n",iLastAccessedMode); + +/* +{ + int k; + for(k=0;k<2352;k++) + auxprintf("%02x ",*(pbuffer+k)); + auxprintf("\n\n"); +} +*/ +#endif + + return pbuffer; +} + +///////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK CDVDgetDiskType() +{ + return iCDType; +} + +///////////////////////////////////////////////////////// +// CDVDgetTrayStatus + +EXPORT_GCC long CALLBACK CDVDgetTrayStatus() +{ + static time_t to=0; + static long lLastTrayState=CDVD_TRAY_CLOSE; + + if(to==time(NULL)) return lLastTrayState; // we only check once per second + to = time(NULL); + + lLastTrayState=CDVD_TRAY_CLOSE; // init state with "closed" + + if(iCheckTrayStatus) // user really want a tray check + { + int iStatus; + + LockGenCDAccess(); // make sure that no more reading is happening + iStatus=GetSCSIStatus(iCD_AD,iCD_TA,iCD_LU); // get device status + UnlockGenCDAccess(); + + if(iStatus==SS_ERR) + lLastTrayState=CDVD_TRAY_OPEN; + } + +#ifdef DBGOUT +auxprintf("check %d -> %d\n",to,lLastTrayState); +#endif + + + return lLastTrayState; +} + + +///////////////////////////////////////////////////////// +// configure: shows config window + +EXPORT_GCC void CALLBACK CDVDconfigure() +{ + if(iCDROK) // mmm... someone has already called Open? bad + {MessageBeep((UINT)-1);return;} + + CreateGenEvent(); // we need an event handle + + DialogBox(hInst,MAKEINTRESOURCE(IDD_CONFIG), // call dialog + GetActiveWindow(),(DLGPROC)CDRDlgProc); + + FreeGenEvent(); // free event handle +} + +///////////////////////////////////////////////////////// +// about: shows about window + +EXPORT_GCC void CALLBACK CDVDabout() +{ + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(),(DLGPROC)AboutDlgProc); +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + +/* +// CURRENTLY UNUSED OLD STUFF FROM PSX CD PLUGIN: + +///////////////////////////////////////////////////////// +// audioplay: PLAYSECTOR is NOT BCD coded !!! + +EXPORT_GCC long CALLBACK CDRplay(unsigned char * sector) +{ + if(!bIsOpen) CDVDopen(); + if(!iCDROK) return PSE_ERR_FATAL; + + if(!DoCDDAPlay(time2addr(sector))) // start playing + return PSE_CDR_ERR_NOREAD; + + bCDDAPlay=TRUE; // raise flag: we are playing + + return PSE_CDR_ERR_SUCCESS; +} + +///////////////////////////////////////////////////////// +// audiostop: stops cdda playing + +EXPORT_GCC long CALLBACK CDRstop(void) +{ + if(!bCDDAPlay) return PSE_ERR_FATAL; + + DoCDDAPlay(0); // stop cdda + + bCDDAPlay=FALSE; // reset flag: no more playing + + return PSE_CDR_ERR_SUCCESS; +} + +///////////////////////////////////////////////////////// +// getdriveletter + +EXPORT_GCC char CALLBACK CDRgetDriveLetter(void) +{ + if(!iCDROK) return 0; // not open? no way to get the letter + + if(iInterfaceMode==2 || iInterfaceMode==3) // w2k/xp: easy + { + return MapIOCTLDriveLetter(iCD_AD,iCD_TA,iCD_LU); + } + else // but with aspi??? + { // -> no idea yet (maybe registry read...pfff) + } + + return 0; +} + +///////////////////////////////////////////////////////// +// getstatus: pcsx func... poorly supported here +// problem is: func will be called often, which +// would block all of my cdr reading if I would use +// lotsa scsi commands + +struct CdrStat +{ + unsigned long Type; + unsigned long Status; + unsigned char Time[3]; // current playing time +}; + +struct CdrStat ostat; + +// reads cdr status +// type: +// 0x00 - unknown +// 0x01 - data +// 0x02 - audio +// 0xff - no cdrom +// status: +// 0x00 - unknown +// 0x02 - error +// 0x08 - seek error +// 0x10 - shell open +// 0x20 - reading +// 0x40 - seeking +// 0x80 - playing +// time: +// byte 0 - minute +// byte 1 - second +// byte 2 - frame + + +EXPORT_GCC long CALLBACK CDRgetStatus(struct CdrStat *stat) +{ + int iStatus; + static time_t to; + + if(!bCDDAPlay) // if not playing update stat only once in a second + { + if(to get pos + stat->Type = 0x02; // -> audio + if(pB) + { + stat->Status|=0x80; // --> playing flag + stat->Time[0]=pB[18]; // --> and curr play time + stat->Time[1]=pB[19]; + stat->Time[2]=pB[20]; + } + } + else // cdda not playing? + { + stat->Type = 0x01; // -> data + } + + LockGenCDAccess(); // make sure that no more reading is happening + iStatus=GetSCSIStatus(iCD_AD,iCD_TA,iCD_LU); // get device status + UnlockGenCDAccess(); + + if(iStatus==SS_ERR) + { // no cdrom? + stat->Type = 0xff; + stat->Status|= 0x10; + } + + memcpy(&ostat, stat, sizeof(struct CdrStat)); + + return 0; +} + +///////////////////////////////////////////////////////// +*/ diff --git a/plugins/cdvd/CDVDpeops/Cfg.c b/plugins/cdvd/CDVDpeops/Cfg.c new file mode 100644 index 0000000..c7ac3bc --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Cfg.c @@ -0,0 +1,527 @@ +/*************************************************************************** + cfg.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +//////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "resource.h" +#define _IN_CFG +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// read config from registry + +void ReadConfig(void) +{ + HKEY myKey;DWORD temp,type,size; + + // init values + + iCD_AD=-1; + iCD_TA=-1; + iCD_LU=-1; + iRType=0; + iUseSpeedLimit=0; + iSpeedLimit=2; + iNoWait=0; + iMaxRetry=5; + iShowReadErr=0; + iUsePPF=0; + iUseSubReading=0; + iUseDataCache=0; + iCheckTrayStatus=0; + memset(szPPF,0,260); + memset(szSUBF,0,260); + + // read values + + if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\PS2Eplugin\\CDVD\\CDVDPeops",0,KEY_ALL_ACCESS,&myKey)==ERROR_SUCCESS) + { + size = 4; + if(RegQueryValueEx(myKey,"Adapter",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iCD_AD=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"Target",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iCD_TA=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"LUN",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iCD_LU=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseCaching",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseCaching=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseDataCache",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseDataCache=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseSpeedLimit",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseSpeedLimit=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"SpeedLimit",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iSpeedLimit=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"NoWait",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iNoWait=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"CheckTrayStatus",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iCheckTrayStatus=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"MaxRetry",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iMaxRetry=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"ShowReadErr",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iShowReadErr=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UsePPF",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUsePPF=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseSubReading",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseSubReading=(int)temp; + size=259; + RegQueryValueEx(myKey,"PPFFile",0,&type,(LPBYTE)szPPF,&size); + size=259; + RegQueryValueEx(myKey,"SCFile",0,&type,(LPBYTE)szSUBF,&size); + + RegCloseKey(myKey); + } + + // disabled for now + iUsePPF=0; +} + +//////////////////////////////////////////////////////////////////////// +// write user config + +void WriteConfig(void) +{ + HKEY myKey;DWORD myDisp,temp; + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\PS2Eplugin\\CDVD\\CDVDPeops",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&myKey,&myDisp); + temp=iInterfaceMode; + RegSetValueEx(myKey,"InterfaceMode",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iCD_AD; + RegSetValueEx(myKey,"Adapter",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iCD_TA; + RegSetValueEx(myKey,"Target",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iCD_LU; + RegSetValueEx(myKey,"LUN",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseCaching; + RegSetValueEx(myKey,"UseCaching",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseDataCache; + RegSetValueEx(myKey,"UseDataCache",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseSpeedLimit; + RegSetValueEx(myKey,"UseSpeedLimit",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iSpeedLimit; + RegSetValueEx(myKey,"SpeedLimit",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iNoWait; + RegSetValueEx(myKey,"NoWait",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iCheckTrayStatus ; + RegSetValueEx(myKey,"CheckTrayStatus",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iMaxRetry; + RegSetValueEx(myKey,"MaxRetry",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iShowReadErr; + RegSetValueEx(myKey,"ShowReadErr",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUsePPF; + RegSetValueEx(myKey,"UsePPF",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseSubReading; + RegSetValueEx(myKey,"UseSubReading",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + + RegSetValueEx(myKey,"PPFFile",0,REG_BINARY,(LPBYTE)szPPF,259); + RegSetValueEx(myKey,"SCFile",0,REG_BINARY,(LPBYTE)szSUBF,259); + + RegCloseKey(myKey); +} + +//////////////////////////////////////////////////////////////////////// +// choose ppf/sbi/m3s file name + +void OnChooseFile(HWND hW,int iFType) +{ + OPENFILENAME ofn;char szB[260];BOOL b; + + ofn.lStructSize=sizeof(OPENFILENAME); + ofn.hwndOwner=hW; + ofn.hInstance=NULL; + if(iFType==0) ofn.lpstrFilter="PPF Files\0*.PPF\0\0\0"; + else if(iFType==1) ofn.lpstrFilter="SBI Files\0*.SBI\0M3S Files\0*.M3S\0\0\0"; + else if(iFType==2) ofn.lpstrFilter="SUB Files\0*.SUB\0\0\0"; + else if(iFType==3) ofn.lpstrFilter="SBI Files\0*.SBI\0\0\0"; + else ofn.lpstrFilter="M3S Files\0*.M3S\0\0\0"; + + ofn.lpstrCustomFilter=NULL; + ofn.nMaxCustFilter=0; + ofn.nFilterIndex=0; + if(iFType==0) GetDlgItemText(hW,IDC_PPFFILE,szB,259); + else if(iFType==1) GetDlgItemText(hW,IDC_SUBFILE,szB,259); + else if(iFType==2) GetDlgItemText(hW,IDC_SUBFILEEDIT,szB,259); + else if(iFType==3) GetDlgItemText(hW,IDC_OUTFILEEDIT,szB,259); + else GetDlgItemText(hW,IDC_OUTFILEEDIT,szB,259); + + ofn.lpstrFile=szB; + ofn.nMaxFile=259; + ofn.lpstrFileTitle=NULL; + ofn.nMaxFileTitle=0; + ofn.lpstrInitialDir=NULL; + ofn.lpstrTitle=NULL; + if(iFType<3) + ofn.Flags=OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_HIDEREADONLY; + else + ofn.Flags=OFN_CREATEPROMPT|OFN_NOCHANGEDIR|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT; + ofn.nFileOffset=0; + ofn.nFileExtension=0; + ofn.lpstrDefExt=0; + ofn.lCustData=0; + ofn.lpfnHook=NULL; + ofn.lpTemplateName=NULL; + + if(iFType<3) + b=GetOpenFileName(&ofn); + else b=GetSaveFileName(&ofn); + + if(b) + { + if(iFType==0) SetDlgItemText(hW,IDC_PPFFILE,szB); + else if(iFType==1) SetDlgItemText(hW,IDC_SUBFILE,szB); + else if(iFType==2) SetDlgItemText(hW,IDC_SUBFILEEDIT,szB); + else if(iFType==3) SetDlgItemText(hW,IDC_OUTFILEEDIT,szB); + else SetDlgItemText(hW,IDC_OUTFILEEDIT,szB); + } +} + +//////////////////////////////////////////////////////////////////////// +// file drive combo + +void EnumDrives(HWND hW) +{ + HWND hWC;char szB[256];int i=0,k=0,iNum; + char * p, * pBuf, * pN; + + hWC=GetDlgItem(hW,IDC_DRIVE); + ComboBox_ResetContent(hWC); + ComboBox_AddString(hWC,"NONE"); // add always existing 'none' + + wsprintf(szB,"[%d:%d:%d",iCD_AD,iCD_TA,iCD_LU); // make current user info text + + pN=pBuf=(char *)malloc(32768); + memset(pBuf,0,32768); + iNum=GetGenCDDrives(pBuf); // get the system cd drives list + + for(i=0;i add drive name + p=strchr(pN,']'); + if(p) + { + *p=0; + if(strcmp(szB,pN)==0) k=i+1; // -> is it the current user drive? sel it + *p=']'; + } + pN+=strlen(pN)+1; // next drive in buffer + } + + free(pBuf); + + ComboBox_SetCurSel(hWC,k); // do the drive sel +} + +//////////////////////////////////////////////////////////////////////// +// get curr selected drive + +void GetCDRInfos(HWND hW,int * iA, int * iT,int * iL) +{ + HWND hWC=GetDlgItem(hW,IDC_DRIVE); + char szB[256];int i;char * p; + + i=ComboBox_GetCurSel(hWC); + if(i<=0) // none selected + { + *iA=-1;*iT=-1;*iL=-1; + MessageBox(hW,"Please select a cdrom drive!","Config error",MB_OK|MB_ICONINFORMATION); + return; + } + + ComboBox_GetLBText(hWC,i,szB); // get cd text + p=szB+1; + *iA=atoi(p); // get AD,TA,LU + p=strchr(szB,':')+1; + *iT=atoi(p); + p=strchr(p,':')+1; + *iL=atoi(p); +} + +//////////////////////////////////////////////////////////////////////// +// interface mode has changed + +void OnIMode(HWND hW) +{ + HWND hWC=GetDlgItem(hW,IDC_IMODE); + int iM = ComboBox_GetCurSel(hWC); + + GetCDRInfos(hW,&iCD_AD,&iCD_TA,&iCD_LU); // get sel drive + CloseGenInterface(); // close current interface + iInterfaceMode=iM; // set new interface mode + OpenGenInterface(); // open new interface + ComboBox_SetCurSel(hWC,iInterfaceMode); // sel interface again (maybe it was not supported on open) + EnumDrives(hW); // enum drives again +} + +//////////////////////////////////////////////////////////////////////// +// cache mode has changed + +void OnCache(HWND hW) +{ + HWND hWC=GetDlgItem(hW,IDC_CACHE); + if(ComboBox_GetCurSel(hWC)<=0) + ShowWindow(GetDlgItem(hW,IDC_DATACACHE),SW_HIDE); + else ShowWindow(GetDlgItem(hW,IDC_DATACACHE),SW_SHOW); +} + +//////////////////////////////////////////////////////////////////////// +// show/hide files depending on subc mode + +void ShowSubFileStuff(HWND hW) +{ + HWND hWC=GetDlgItem(hW,IDC_SUBCHAN0); + int iShow,iSel=ComboBox_GetCurSel(hWC); + + if(iSel==2) iShow=SW_SHOW; + else iShow=SW_HIDE; + + ShowWindow(GetDlgItem(hW,IDC_SFSTATIC),iShow); + ShowWindow(GetDlgItem(hW,IDC_SUBFILE),iShow); + ShowWindow(GetDlgItem(hW,IDC_CHOOSESUBF),iShow); + + if(iSel==1) + { + ComboBox_SetCurSel(GetDlgItem(hW,IDC_CACHE),0); + ShowWindow(GetDlgItem(hW,IDC_DATACACHE),SW_HIDE); + } +} + +//////////////////////////////////////////////////////////////////////// +// init dialog + +BOOL OnInitCDRDialog(HWND hW) +{ + HWND hWC;int i=0; + + ReadConfig(); // read config + + hWC=GetDlgItem(hW,IDC_IMODE); // interface + ComboBox_AddString(hWC,"NONE"); + ComboBox_AddString(hWC,"W9X/ME - ASPI scsi commands"); + ComboBox_AddString(hWC,"W2K/XP - IOCTL scsi commands"); + +// not supported with my dvd drive - DISABLED! +// ComboBox_AddString(hWC,"W2K/XP - IOCTL raw reading"); + + ComboBox_SetCurSel(hWC,iInterfaceMode); + + EnumDrives(hW); // enum drives + + hWC=GetDlgItem(hW,IDC_CACHE); // caching + ComboBox_AddString(hWC,"None - reads one sector"); + ComboBox_AddString(hWC,"Read ahead - fast, reads more sectors at once"); + ComboBox_AddString(hWC,"Async read - faster, additional asynchronous reads"); + ComboBox_AddString(hWC,"Thread read - fast with IOCTL, always async reads"); + ComboBox_AddString(hWC,"Smooth read - for drives with ps2 cd/dvd reading troubles"); + ComboBox_SetCurSel(hWC,iUseCaching); + + if(iUseDataCache) + CheckDlgButton(hW,IDC_DATACACHE,TRUE); + if(!iUseCaching) + ShowWindow(GetDlgItem(hW,IDC_DATACACHE),SW_HIDE); + + if(iUseSpeedLimit) // speed limit + CheckDlgButton(hW,IDC_SPEEDLIMIT,TRUE); + + if(iNoWait) // wait for drive + CheckDlgButton(hW,IDC_NOWAIT,TRUE); + + if(iCheckTrayStatus) // tray status + CheckDlgButton(hW,IDC_TRAYSTATE,TRUE); + + SetDlgItemInt(hW,IDC_RETRY,iMaxRetry,FALSE); // retry on error + if(iMaxRetry) CheckDlgButton(hW,IDC_TRYAGAIN,TRUE); + if(iShowReadErr) CheckDlgButton(hW,IDC_SHOWREADERR,TRUE); + + hWC=GetDlgItem(hW,IDC_SUBCHAN0); // subchannel mode + ComboBox_AddString(hWC,"Don't read subchannels"); + ComboBox_AddString(hWC,"Read subchannels (slow, few drives support it, best chances with BE mode)"); + ComboBox_AddString(hWC,"Use subchannel SBI/M3S info file (recommended)"); + ComboBox_SetCurSel(hWC,iUseSubReading); + + ShowSubFileStuff(hW); // show/hide subc controls + + hWC=GetDlgItem(hW,IDC_SPEED); // speed limit + ComboBox_AddString(hWC,"2 X"); + ComboBox_AddString(hWC,"4 X"); + ComboBox_AddString(hWC,"8 X"); + ComboBox_AddString(hWC,"16 X"); + + i=0; + if(iSpeedLimit==4) i=1; + if(iSpeedLimit==8) i=2; + if(iSpeedLimit==16) i=3; + + ComboBox_SetCurSel(hWC,i); + + if(iUsePPF) CheckDlgButton(hW,IDC_USEPPF,TRUE); // ppf + SetDlgItemText(hW,IDC_PPFFILE,szPPF); + SetDlgItemText(hW,IDC_SUBFILE,szSUBF); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void OnCDROK(HWND hW) +{ + int iA,iT,iL,iR; + HWND hWC=GetDlgItem(hW,IDC_RTYPE); + + GetCDRInfos(hW,&iA,&iT,&iL); + if(iA==-1) return; + + hWC=GetDlgItem(hW,IDC_CACHE); + iUseCaching=ComboBox_GetCurSel(hWC); + if(iUseCaching<0) iUseCaching=0; + if(iUseCaching>4) iUseCaching=4; + + iCD_AD=iA;iCD_TA=iT;iCD_LU=iL; + + if(IsDlgButtonChecked(hW,IDC_SPEEDLIMIT)) + iUseSpeedLimit=1; + else iUseSpeedLimit=0; + + iUseSubReading=0; + hWC=GetDlgItem(hW,IDC_SUBCHAN0); + iUseSubReading=ComboBox_GetCurSel(hWC); + if(iUseSubReading<0) iUseSubReading=0; + if(iUseSubReading>2) iUseSubReading=2; + if(iUseSubReading==1) iUseCaching=0; + + if(IsDlgButtonChecked(hW,IDC_DATACACHE)) + iUseDataCache=1; + else iUseDataCache=0; + if(iUseCaching==0) iUseDataCache=0; + + if(IsDlgButtonChecked(hW,IDC_NOWAIT)) + iNoWait=1; + else iNoWait=0; + + if(IsDlgButtonChecked(hW,IDC_TRAYSTATE)) + iCheckTrayStatus=1; + else iCheckTrayStatus=0; + + iMaxRetry=GetDlgItemInt(hW,IDC_RETRY,NULL,FALSE); + if(iMaxRetry<1) iMaxRetry=1; + if(iMaxRetry>10) iMaxRetry=10; + if(!IsDlgButtonChecked(hW,IDC_TRYAGAIN)) iMaxRetry=0; + + if(IsDlgButtonChecked(hW,IDC_SHOWREADERR)) + iShowReadErr=1; + else iShowReadErr=0; + + hWC=GetDlgItem(hW,IDC_SPEED); + iR=ComboBox_GetCurSel(hWC); + + iSpeedLimit=2; + if(iR==1) iSpeedLimit=4; + if(iR==2) iSpeedLimit=8; + if(iR==3) iSpeedLimit=16; + + if(IsDlgButtonChecked(hW,IDC_USEPPF)) + iUsePPF=1; + else iUsePPF=0; + + GetDlgItemText(hW,IDC_PPFFILE,szPPF,259); + GetDlgItemText(hW,IDC_SUBFILE,szSUBF,259); + + WriteConfig(); // write registry + + EndDialog(hW,TRUE); +} + +//////////////////////////////////////////////////////////////////////// + +void OnCDRCancel(HWND hW) +{ + EndDialog(hW,FALSE); +} + +//////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK CDRDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + return OnInitCDRDialog(hW); + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_SUBCHAN0: if(HIWORD(wParam)==CBN_SELCHANGE) + {ShowSubFileStuff(hW);return TRUE;} + case IDC_IMODE: if(HIWORD(wParam)==CBN_SELCHANGE) + {OnIMode(hW);return TRUE;} + break; + case IDC_CACHE: if(HIWORD(wParam)==CBN_SELCHANGE) + {OnCache(hW);return TRUE;} + break; + case IDCANCEL: OnCDRCancel(hW); return TRUE; + case IDOK: OnCDROK(hW); return TRUE; + case IDC_CHOOSEFILE: OnChooseFile(hW,0);return TRUE; + case IDC_CHOOSESUBF: OnChooseFile(hW,1);return TRUE; + } + } + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDCANCEL: EndDialog(hW,FALSE);return TRUE; + case IDOK: EndDialog(hW,FALSE);return TRUE; + } + } + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/cdvd/CDVDpeops/CheckDiskType.c b/plugins/cdvd/CDVDpeops/CheckDiskType.c new file mode 100644 index 0000000..4719c39 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/CheckDiskType.c @@ -0,0 +1,41 @@ + +#include +#include "CDVDlib.h" +#include "CDVDiso.h" +#include "CDVDisodrv.h" + +int CheckDiskType(int baseType){ + int f; + char buffer[256];//if a file is longer...it should be shorter :D + char *pos; + static struct TocEntry tocEntry; + + CDVDFS_init(); + + // check if the file exists + if (CDVD_findfile("SYSTEM.CNF;1", &tocEntry) != TRUE){ + if (CDVD_findfile("VIDEO_TS/VIDEO_TS.IFO;1", &tocEntry) != TRUE) + if (CDVD_findfile("PSX.EXE;1", &tocEntry) != TRUE) + return CDVD_TYPE_ILLEGAL; + else + return CDVD_TYPE_PSCD; + else + return CDVD_TYPE_DVDV; + } + + f=CDVDFS_open("SYSTEM.CNF;1", 1); + CDVDFS_read(f, buffer, 256); + CDVDFS_close(f); + + buffer[tocEntry.fileSize]='\0'; + + pos=strstr(buffer, "BOOT2"); + if (pos==NULL){ + pos=strstr(buffer, "BOOT"); + if (pos==NULL) { + return CDVD_TYPE_ILLEGAL; + } + return CDVD_TYPE_PSCD; + } + return (baseType==CDVD_TYPE_DETCTCD)?CDVD_TYPE_PS2CD:CDVD_TYPE_PS2DVD; +} diff --git a/plugins/cdvd/CDVDpeops/Ioctrl.c b/plugins/cdvd/CDVDpeops/Ioctrl.c new file mode 100644 index 0000000..62a38d2 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Ioctrl.c @@ -0,0 +1,383 @@ +/*************************************************************************** + ioctrl.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_IOCTL +#include "externals.h" + +///////////////////////////////////////////////////////// + +HANDLE hIOCTL=NULL; // global drive file handle +DWORD dwIOCTLAttr=0; // open attribute +OVERLAPPED ovcIOCTL; // global overlapped struct +SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptIOCTL; // global read bufs +RAW_READ_INFO rawIOCTL; + +///////////////////////////////////////////////////////// +// open drive + +void OpenIOCTLHandle(int iA,int iT,int iL) +{ + char cLetter; + + if(hIOCTL) return; + + cLetter=MapIOCTLDriveLetter(iA,iT,iL); // get drive + + if(!cLetter) return; + + hIOCTL=OpenIOCTLFile(cLetter, // open drive + (iUseCaching==2)?TRUE:FALSE); // (caching:2 -> overlapped) +} + +///////////////////////////////////////////////////////// +// close drive + +void CloseIOCTLHandle(void) +{ + if(hIOCTL) CloseHandle(hIOCTL); + hIOCTL=NULL; +} + +///////////////////////////////////////////////////////// +// get drive letter by a,t,l + +char MapIOCTLDriveLetter(int iA,int iT,int iL) +{ + char cLetter[4];int iDA,iDT,iDL;HANDLE hF; + + strcpy(cLetter,"C:\\"); + + for(cLetter[0]='C';cLetter[0]<='Z';cLetter[0]++) + { + if(GetDriveType(cLetter)==DRIVE_CDROM) + { + hF=OpenIOCTLFile(cLetter[0],FALSE); + GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); + CloseHandle(hF); + if(iA==iDA && iT==iDT && iL==iDL) + return cLetter[0]; + } + } + return 0; +} + +///////////////////////////////////////////////////////// +// get cd drive list, using ioctl, not aspi + +int GetIOCTLCDDrives(char * pDList) +{ + char cLetter[4];int iDA,iDT,iDL;HANDLE hF; + int iCnt=0;char * p=pDList; + + strcpy(cLetter,"C:\\"); + + for(cLetter[0]='C';cLetter[0]<='Z';cLetter[0]++) + { + if(GetDriveType(cLetter)==DRIVE_CDROM) + { + hF=OpenIOCTLFile(cLetter[0],FALSE); + GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); + CloseHandle(hF); + if(iDA!=-1 && iDT!=-1 && iDL!=-1) + { + wsprintf(p,"[%d:%d:%d] Drive %c:", + iDA,iDT,iDL,cLetter[0]); + p+=strlen(p)+1; + iCnt++; + } + } + } + + return iCnt; +} + +///////////////////////////////////////////////////////// +// open drive in sync/async mode + +HANDLE OpenIOCTLFile(char cLetter,BOOL bAsync) +{ + HANDLE hF;char szFName[16]; + OSVERSIONINFO ov;DWORD dwFlags; + + if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED; + else dwIOCTLAttr=0; + + memset(&ov,0,sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); + GetVersionEx(&ov); + + if((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && + (ov.dwMajorVersion>4)) + dwFlags = GENERIC_READ|GENERIC_WRITE; // add gen write on W2k/XP + else dwFlags = GENERIC_READ; + + wsprintf(szFName, "\\\\.\\%c:",cLetter); + + hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // open drive + NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); + + if(hF==INVALID_HANDLE_VALUE) // mmm... no success? + { + dwFlags^=GENERIC_WRITE; // -> try write toggle + hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again + NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); + if(hF==INVALID_HANDLE_VALUE) return NULL; + } + + return hF; +} + +///////////////////////////////////////////////////////// +// get a,t,l + +void GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL) +{ + char szBuf[1024];PSCSI_ADDRESS pSA;DWORD dwRet; + + *iDA=*iDT=*iDL=-1; + if(hF==NULL) return; + + memset(szBuf,0,1024); + + pSA=(PSCSI_ADDRESS)szBuf; + pSA->Length=sizeof(SCSI_ADDRESS); + + if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL, + 0,pSA,sizeof(SCSI_ADDRESS), + &dwRet,NULL)) + return; + + *iDA = pSA->PortNumber; + *iDT = pSA->TargetId; + *iDL = pSA->Lun; +} + +///////////////////////////////////////////////////////// +// we fake the aspi call in ioctl scsi mode + +DWORD IOCTLSendASPI32Command(LPSRB pSRB) +{ + LPSRB_ExecSCSICmd pSC;DWORD dwRet;BOOL bStat; + + if(!pSRB) return SS_ERR; + + if(hIOCTL==NULL || + pSRB->SRB_Cmd!=SC_EXEC_SCSI_CMD) // we only fake exec aspi scsi commands + { + pSRB->SRB_Status=SS_ERR; + return SS_ERR; + } + + pSC=(LPSRB_ExecSCSICmd)pSRB; + + memset(&sptIOCTL,0,sizeof(sptIOCTL)); + + sptIOCTL.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); + sptIOCTL.spt.CdbLength = pSC->SRB_CDBLen; + sptIOCTL.spt.DataTransferLength = pSC->SRB_BufLen; + sptIOCTL.spt.TimeOutValue = 60; + sptIOCTL.spt.DataBuffer = pSC->SRB_BufPointer; + sptIOCTL.spt.SenseInfoLength = 14; + sptIOCTL.spt.TargetId = pSC->SRB_Target; + sptIOCTL.spt.Lun = pSC->SRB_Lun; + sptIOCTL.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); + if(pSC->SRB_Flags&SRB_DIR_IN) sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_IN; + else if(pSC->SRB_Flags&SRB_DIR_OUT) sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_OUT; + else sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; + memcpy(sptIOCTL.spt.Cdb,pSC->CDBByte,pSC->SRB_CDBLen); + + if(dwIOCTLAttr==FILE_FLAG_OVERLAPPED) // async? + { + ovcIOCTL.Internal=0; + ovcIOCTL.InternalHigh=0; + ovcIOCTL.Offset=0; + ovcIOCTL.OffsetHigh=0; + ovcIOCTL.hEvent=hEvent; + bStat = DeviceIoControl(hIOCTL, + IOCTL_SCSI_PASS_THROUGH_DIRECT, + &sptIOCTL, + sizeof(sptIOCTL), + &sptIOCTL, + sizeof(sptIOCTL), + &dwRet, + &ovcIOCTL); + } + else // sync? + { + bStat = DeviceIoControl(hIOCTL, + IOCTL_SCSI_PASS_THROUGH_DIRECT, + &sptIOCTL, + sizeof(sptIOCTL), + &sptIOCTL, + sizeof(sptIOCTL), + &dwRet, + NULL); + } + + if(!bStat) // some err? + { + DWORD dwErrCode; + dwErrCode=GetLastError(); + if(dwErrCode==ERROR_IO_PENDING) // -> pending? + { + pSC->SRB_Status=SS_COMP; // --> ok + return SS_PENDING; + } + pSC->SRB_Status=SS_ERR; // -> else error + return SS_ERR; + } + + pSC->SRB_Status=SS_COMP; + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// special raw mode... works on TEAC532S, for example + +DWORD ReadIOCTL_Raw(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwRet;BOOL bStat; + + if(hIOCTL==NULL) return SS_ERR; + + rawIOCTL.DiskOffset.QuadPart = f->dwFrame*2048; // 2048 is needed here + rawIOCTL.SectorCount = f->dwFrameCnt; + rawIOCTL.TrackMode = XAForm2;//CDDA;//YellowMode2;//XAForm2; + + if(dwIOCTLAttr==FILE_FLAG_OVERLAPPED) // async? + { + ovcIOCTL.Internal=0; + ovcIOCTL.InternalHigh=0; + ovcIOCTL.Offset=0; + ovcIOCTL.OffsetHigh=0; + ovcIOCTL.hEvent=hEvent; + ResetEvent(hEvent); + bStat = DeviceIoControl(hIOCTL, + IOCTL_CDROM_RAW_READ, + &rawIOCTL,sizeof(RAW_READ_INFO), + &(f->BufData[0]),f->dwBufLen,//2048, + &dwRet, &ovcIOCTL); + } + else // sync? + { + bStat = DeviceIoControl(hIOCTL, + IOCTL_CDROM_RAW_READ, + &rawIOCTL,sizeof(RAW_READ_INFO), + &(f->BufData[0]),f->dwBufLen,//2048, + &dwRet,NULL); + } + + if(!bStat) + { + DWORD dwErrCode; + dwErrCode=GetLastError(); + +#ifdef DBGOUT +auxprintf("errorcode %d\n", dwErrCode); +#endif + + if(dwErrCode==ERROR_IO_PENDING) + { + // we do a wait here, not later... no real async mode anyway + // bDoWaiting=TRUE; + + WaitGenEvent(0xFFFFFFFF); + } + else + { + sx.SRB_Status=SS_ERR; + return SS_ERR; + } + } + + sx.SRB_Status=SS_COMP; + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// special raw + special sub... dunno if this really +// works on any drive (teac is working, but giving unprecise +// subdata) + +DWORD ReadIOCTL_Raw_Sub(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwRet;BOOL bStat; + SUB_Q_CHANNEL_DATA qd;unsigned char * p; + CDROM_SUB_Q_DATA_FORMAT qf; + + if(hIOCTL==NULL) return SS_ERR; + + rawIOCTL.DiskOffset.QuadPart = f->dwFrame*2048; + rawIOCTL.SectorCount = f->dwFrameCnt; + rawIOCTL.TrackMode = XAForm2; + + bStat = DeviceIoControl(hIOCTL, + IOCTL_CDROM_RAW_READ, + &rawIOCTL,sizeof(RAW_READ_INFO), + &(f->BufData[0]),f->dwBufLen, + &dwRet,NULL); + + if(!bStat) {sx.SRB_Status=SS_ERR;return SS_ERR;} + + qf.Format=IOCTL_CDROM_CURRENT_POSITION; + qf.Track=1; + bStat = DeviceIoControl(hIOCTL, + IOCTL_CDROM_READ_Q_CHANNEL, + &qf,sizeof(CDROM_SUB_Q_DATA_FORMAT), + &qd,sizeof(SUB_Q_CHANNEL_DATA), + &dwRet,NULL); + + p=(unsigned char*)&qd; + + SubCData[12]=(p[5]<<4)|(p[5]>>4); + SubCData[13]=p[6]; + SubCData[14]=p[7]; + SubCData[15]=p[13]; + SubCData[16]=p[14]; + SubCData[17]=p[15]; + SubCData[18]=0; + SubCData[19]=p[9]; + SubCData[20]=p[10]; + SubCData[21]=p[11]; + + SubCData[15]=itob(SubCData[15]); + SubCData[16]=itob(SubCData[16]); + SubCData[17]=itob(SubCData[17]); + + SubCData[19]=itob(SubCData[19]); + SubCData[20]=itob(SubCData[20]); + SubCData[21]=itob(SubCData[21]); + + if(!bStat) {sx.SRB_Status=SS_ERR;return SS_ERR;} + + sx.SRB_Status=SS_COMP; + return SS_COMP; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/Makefile.win b/plugins/cdvd/CDVDpeops/Makefile.win new file mode 100644 index 0000000..c860068 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Makefile.win @@ -0,0 +1,72 @@ +# Project: cdvdPeops +# Makefile created by Dev-C++ 4.9.9.0 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = cdvdPeops_private.res +OBJ = Release/cdr.o Release/cdvdPeops.o Release/cfg.o Release/generic.o Release/ioctrl.o Release/ppf.o Release/read.o Release/scsi.o Release/StdAfx.o Release/sub.o Release/toc.o Release/cdda.o Release/i386.o $(RES) +LINKOBJ = Release/cdr.o Release/cdvdPeops.o Release/cfg.o Release/generic.o Release/ioctrl.o Release/ppf.o Release/read.o Release/scsi.o Release/StdAfx.o Release/sub.o Release/toc.o Release/cdda.o Release/i386.o $(RES) +LIBS = -L"D:/vs/Dev-Cpp/lib" -lkernel32 -luser32 -ladvapi32 -lcomdlg32 --add-stdcall-alias +INCS = -I"D:/vs/Dev-Cpp/include" -I"d:/vs/vc98/MFC/include" +CXXINCS = -I"D:/vs/Dev-Cpp/include/c++" -I"D:/vs/Dev-Cpp/include/c++/mingw32" -I"D:/vs/Dev-Cpp/include/c++/backward" -I"D:/vs/Dev-Cpp/include" -I"d:/vs/vc98/MFC/include" +BIN = ../../../emus/pcsx2_0.6/plugins/cdvdPeops.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC -fexpensive-optimizations -O3 +CFLAGS = $(INCS) -D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC -fexpensive-optimizations -O3 + +.PHONY: all all-before all-after clean clean-custom + +all: all-before ../../../emus/pcsx2_0.6/plugins/cdvdPeops.dll all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=../../../emus/pcsx2_0.6/plugins/libcdvdPeops.def +STATICLIB=../../../emus/pcsx2_0.6/plugins/libcdvdPeops.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +Release/cdr.o: cdr.c + $(CC) -c cdr.c -o Release/cdr.o $(CFLAGS) + +Release/cdvdPeops.o: cdvdPeops.c + $(CC) -c cdvdPeops.c -o Release/cdvdPeops.o $(CFLAGS) + +Release/cfg.o: cfg.c + $(CC) -c cfg.c -o Release/cfg.o $(CFLAGS) + +Release/generic.o: generic.c + $(CC) -c generic.c -o Release/generic.o $(CFLAGS) + +Release/ioctrl.o: ioctrl.c + $(CC) -c ioctrl.c -o Release/ioctrl.o $(CFLAGS) + +Release/ppf.o: ppf.c + $(CC) -c ppf.c -o Release/ppf.o $(CFLAGS) + +Release/read.o: read.c + $(CC) -c read.c -o Release/read.o $(CFLAGS) + +Release/scsi.o: scsi.c + $(CC) -c scsi.c -o Release/scsi.o $(CFLAGS) + +Release/StdAfx.o: StdAfx.c + $(CC) -c StdAfx.c -o Release/StdAfx.o $(CFLAGS) + +Release/sub.o: sub.c + $(CC) -c sub.c -o Release/sub.o $(CFLAGS) + +Release/toc.o: toc.c + $(CC) -c toc.c -o Release/toc.o $(CFLAGS) + +Release/cdda.o: cdda.c + $(CC) -c cdda.c -o Release/cdda.o $(CFLAGS) + +Release/i386.o: i386.asm + nasmw.exe -f win32 -D__WIN32__ -D__i386__ i386.asm -o release\i386.o + +cdvdPeops_private.res: cdvdPeops_private.rc ../../../src/cdvdPeops/src/cdvdPeops.rc + $(WINDRES) -i cdvdPeops_private.rc -I rc -o cdvdPeops_private.res -O coff diff --git a/plugins/cdvd/CDVDpeops/PS2Edefs.h b/plugins/cdvd/CDVDpeops/PS2Edefs.h new file mode 100644 index 0000000..48093ae --- /dev/null +++ b/plugins/cdvd/CDVDpeops/PS2Edefs.h @@ -0,0 +1,789 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetCSR(u64 *csr); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetCSR)(u64 * csr); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetCSR GSsetCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/cdvd/CDVDpeops/PS2Etypes.h b/plugins/cdvd/CDVDpeops/PS2Etypes.h new file mode 100644 index 0000000..3a63c58 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/cdvd/CDVDpeops/ReadMe.txt b/plugins/cdvd/CDVDpeops/ReadMe.txt new file mode 100644 index 0000000..3eff73e --- /dev/null +++ b/plugins/cdvd/CDVDpeops/ReadMe.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : cdrPeops +======================================================================== + + +AppWizard has created this cdrPeops DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your cdrPeops application. + +cdrPeops.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +cdrPeops.cpp + This is the main DLL source file. + +cdrPeops.h + This file contains your DLL exports. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named cdrPeops.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/Scsi.c b/plugins/cdvd/CDVDpeops/Scsi.c new file mode 100644 index 0000000..7f1f9e5 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/Scsi.c @@ -0,0 +1,1134 @@ +/*************************************************************************** + scsi.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_SCSI +#include "externals.h" + +///////////////////////////////////////////////////////// + +SRB_ExecSCSICmd sx; // used with all (non-waiting) read funcs +BOOL bDoWaiting=FALSE; // flag for async reads + +///////////////////////////////////////////////////////// +// returns device type + +int GetSCSIDevice(int iA,int iT,int iL) +{ + SRB_GDEVBlock s;DWORD dwStatus; + + memset(&s,0,sizeof(SRB_GDEVBlock)); + s.SRB_Cmd = SC_GET_DEV_TYPE; + s.SRB_HaID = iA; + s.SRB_Target = iT; + s.SRB_Lun = iL; + + ResetEvent(hEvent); + + dwStatus=pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) + {WaitGenEvent(30000);dwStatus=s.SRB_Status;} + + if(dwStatus==SS_COMP) return s.SRB_DeviceType; + + return -1; +} + +///////////////////////////////////////////////////////// + +int GetSCSIStatus(int iA,int iT,int iL) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + char ret[0x324]; + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x324; + s.SRB_BufPointer = (BYTE FAR *)ret; + s.SRB_SenseLen = 0x0E; + s.SRB_CDBLen = 0x0A; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x00; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) WaitGenEvent(30000); + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// +// fills toc infos + +DWORD GetSCSITOC(LPTOC toc) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x324; + s.SRB_BufPointer = (BYTE FAR *)toc; + s.SRB_SenseLen = 0x0E; + s.SRB_CDBLen = 0x0A; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x43; + s.CDBByte[1] = 0x00; // 0x02 for MSF + s.CDBByte[7] = 0x03; + s.CDBByte[8] = 0x24; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) WaitGenEvent(30000); + + if(s.SRB_Status!=SS_COMP) return SS_ERR; + + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// enum all cd drives into 32k buffer, return num of drives + +int GetSCSICDDrives(char * pDList) +{ + int iCnt=0,iA,iT,iL;char * p=pDList; + SRB_HAInquiry si;SRB_GDEVBlock sd; + SRB_ExecSCSICmd s;int iNumA;char szBuf[100]; + DWORD dw,dwStatus; + + if(!pGetASPI32SupportInfo) return 0; + + dw=pGetASPI32SupportInfo(); + + if(HIBYTE(LOWORD(dw))!=SS_COMP) return 0; + iNumA=(int)LOBYTE(LOWORD(dw)); + + for(iA=0;iA> 24) & 0xFF); + s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF); + s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF); + s.CDBByte[5] = (unsigned char)((start & 0xFF)); + s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF); + s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF); + s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF); + s.CDBByte[9] = (unsigned char)(len & 0xFF); + } + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) WaitGenEvent(10000); + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// +// do (unprecise) sub channel read on audio play + +unsigned char * GetSCSIAudioSub(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + unsigned char cB[20]; + + memset(cB,0,20); + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = 20;//44; + s.SRB_BufPointer = cB; + s.SRB_CDBLen = 10; + + s.CDBByte[0] = 0x42; + s.CDBByte[1] = (iCD_LU<<5)|2; // lun & msf + s.CDBByte[2] = 0x40; // subq + s.CDBByte[3] = 0x01; // curr pos info + s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) + s.CDBByte[7] = 0; // alloc len + s.CDBByte[8] = 20;//44; + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) return NULL; + + SubAData[12]=(cB[5]<<4)|(cB[5]>>4); + SubAData[13]=cB[6]; + SubAData[14]=cB[7]; + SubAData[15]=itob(cB[13]); + SubAData[16]=itob(cB[14]); + SubAData[17]=itob(cB[15]); + SubAData[18]=0; + SubAData[19]=itob(cB[9]); + SubAData[20]=itob(cB[10]); + SubAData[21]=itob(cB[11]); + + return SubAData; +} + +///////////////////////////////////////////////////////// +// test, if drive is ready (doesn't work on all drives) + +BOOL TestSCSIUnitReady(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + memset(&s,0,sizeof(s)); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0; + s.SRB_BufPointer = 0; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x00; + s.CDBByte[1] = iCD_LU << 5; + + ResetEvent(hEvent); + dwStatus = pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) + WaitGenEvent(1000); + + if(s.SRB_Status!=SS_COMP) + return FALSE; + + if(s.SRB_TargStat==STATUS_GOOD) return TRUE; // will always be GOOD with ioctl, so no problem here + + return FALSE; +} + +///////////////////////////////////////////////////////// +// change the read speed (not supported on all drives) + +DWORD SetSCSISpeed(DWORD dwSpeed) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_DIR_OUT | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 12; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0xBB; + s.CDBByte[2] = (BYTE)(dwSpeed >> 8); + s.CDBByte[3] = (BYTE)dwSpeed; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) return SS_ERR; + + return SS_COMP; +} + +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// all the different SCSI read commands can be found here +// 'bWait' is a flag, if the command should wait until +// completed, or if the func can return as soon as possible +// (async reading). Attention: 'bWait' is not really used +// in the Sub-channel commands yet (sub is done always +// blocking, and just 'one sector' reads are done, caching=0) +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// BE: used by most ATAPI drives +///////////////////////////////////////////////////////// + +DWORD ReadSCSI_BE(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xBE; + //s.CDBByte[1] = 0x04; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + sx.CDBByte[9] = (iRType==MODE_BE_1)?0x10:0xF8;//F0!!!!!!!!!!! + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + + if(dwStatus==SS_PENDING) + { + if(bWait) WaitGenEvent(WAITFOREVER); + else + { + bDoWaiting=TRUE; + return SS_COMP; + } + } + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + return SS_COMP; +} + +///////////////////////////////////////////////////////// + +DWORD ReadSCSI_BE_Sub(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen + 16; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xBE; + //s.CDBByte[1] = 0x04; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + sx.CDBByte[9] = (iRType==MODE_BE_1)?0x10:0xF8;//F0!!!!!!!!!!! + sx.CDBByte[10] = 0x2; + + ResetEvent(hEvent ); + dwStatus=pSendASPI32Command((LPSRB)&sx); + + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITSUB); + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + memcpy(&SubCData[12],&f->BufData[2352],16); + + SubCData[15]=itob(SubCData[15]); + SubCData[16]=itob(SubCData[16]); + SubCData[17]=itob(SubCData[17]); + + SubCData[19]=itob(SubCData[19]); + SubCData[20]=itob(SubCData[20]); + SubCData[21]=itob(SubCData[21]); + + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// different sub reading for lite-on ltd163d... +// 16 bytes subc data is encoded in 96 bytes... + +DWORD ReadSCSI_BE_Sub_1(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen + 96; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xBE; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + sx.CDBByte[9] = 0xF8; + sx.CDBByte[10] = 0x1; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITSUB); + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + DecodeSub_BE_2_1(&f->BufData[2352]); + + memcpy(&SubCData[12],&f->BufData[2352],16); + + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// 28: used by most SCSI drives +///////////////////////////////////////////////////////// + +DWORD InitSCSI_28_2(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + int i; + BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x09, 0x30, 0x23, 6, 0, 0, 0, 0, 0, 0x80 }; + BYTE init2[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 1, 6, 32, 7, 0, 0, 0, 0 }; + + for(i=0;i<2;i++) + { + memset( &s, 0, sizeof( s ) ); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x14; + s.SRB_BufPointer = (i==0)?init1:init2; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x15; + s.CDBByte[1] = 0x10; + s.CDBByte[4] = 0x14; + + ResetEvent(hEvent); + + dwStatus=pSendASPI32Command((LPSRB)&s); + if (dwStatus == SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) + return SS_ERR; + } + + pDeInitFunc = DeInitSCSI_28; + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// + +DWORD InitSCSI_28_1(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x09, 0x30 }; + + memset(&s,0,sizeof(s)); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x0C; + s.SRB_BufPointer = init1; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x15; + s.CDBByte[4] = 0x0C; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) + return SS_ERR; + + pDeInitFunc = DeInitSCSI_28; + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// + +DWORD InitSCSI_28_2048(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + BYTE init1[] = { 0, 0, 0, 0x08, 0, 0, 0, 0, 0, 0, 0x08, 0x0 }; + + pDeInitFunc = DeInitSCSI_28; + + memset(&s,0,sizeof(s)); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x0C; + s.SRB_BufPointer = init1; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x15; + s.CDBByte[4] = 0x0C; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) + return SS_ERR; + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// + +DWORD DeInitSCSI_28(void) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + BYTE init1[] = { 0, 0, 0, 8, 83, 0, 0, 0, 0, 0, 8, 0 }; + + memset(&s,0,sizeof(s)); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = iCD_AD; + s.SRB_Target = iCD_TA; + s.SRB_Lun = iCD_LU; + s.SRB_Flags = SRB_EVENT_NOTIFY | SRB_ENABLE_RESIDUAL_COUNT; + s.SRB_BufLen = 0x0C; + s.SRB_BufPointer = init1; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x15; + s.CDBByte[4] = 0x0C; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(s.SRB_Status!=SS_COMP) + return SS_ERR; + + return s.SRB_Status; +} + +///////////////////////////////////////////////////////// + +DWORD ReadSCSI_28(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + if(!pDeInitFunc) + { + if(iRType==MODE_28_2) + { + if(InitSCSI_28_2()!=SS_COMP) return SS_ERR; + } + else + { + if(InitSCSI_28_1()!=SS_COMP) return SS_ERR; + } + } + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 10; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0x28; // read10 command + sx.CDBByte[1] = iCD_LU << 5; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + { + if(bWait) WaitGenEvent(WAITFOREVER); + else + { + bDoWaiting=TRUE; + return SS_COMP; + } + } + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + return SS_COMP; +} + +///////////////////////////////////////////////////////// +// DVD MODE + +DWORD ReadSCSI_28_2048(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + if(!pDeInitFunc) + { + InitSCSI_28_2048(); + + //if(InitSCSI_28_2048()!=SS_COMP) return SS_ERR; + } + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 10; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0x28; // read10 command + sx.CDBByte[1] = iCD_LU << 5; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + sx.CDBByte[9] = 0xF8; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + { + if(bWait) WaitGenEvent(WAITFOREVER); + else + { + bDoWaiting=TRUE; + return SS_COMP; + } + } + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + return SS_COMP; +} + +DWORD ReadSCSI_28_2048_Ex(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + if(!pDeInitFunc) + { + InitSCSI_28_2048(); + + //if(InitSCSI_28_2048()!=SS_COMP) return SS_ERR; + } + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 10; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0x28; // read10 command + sx.CDBByte[1] = iCD_LU << 5; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + // NO F8 + //sx.CDBByte[9] = 0xF8; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + { + if(bWait) WaitGenEvent(WAITFOREVER); + else + { + bDoWaiting=TRUE; + return SS_COMP; + } + } + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + return SS_COMP; +} + + +///////////////////////////////////////////////////////// +// stupid subc reading on Teac 532S + +char tbuf[2368]; + +DWORD ReadSCSI_28_Sub(BOOL bWait,FRAMEBUF * f) +{ + DWORD dwStatus; + + if(!pDeInitFunc) + { + if(iRType==MODE_28_2) + { + if(InitSCSI_28_2()!=SS_COMP) return SS_ERR; + } + else + { + if(InitSCSI_28_1()!=SS_COMP) return SS_ERR; + } + } + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = f->dwBufLen; + sx.SRB_BufPointer = &(f->BufData[0]); + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 10; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0x28; // read10 + sx.CDBByte[1] = iCD_LU << 5; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[8] = (unsigned char)(f->dwFrameCnt & 0xFF); + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = 2368; + sx.SRB_BufPointer = tbuf; + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xD8; + sx.CDBByte[2] = (unsigned char)((f->dwFrame >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((f->dwFrame >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((f->dwFrame >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(f->dwFrame & 0xFF); + sx.CDBByte[9] = (unsigned char)(f->dwFrameCnt & 0xFF); + sx.CDBByte[10] = 1; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(sx.SRB_Status!=SS_COMP) + return SS_ERR; + + memcpy(&SubCData[12],&tbuf[2352],16); + + return SS_COMP; +} + + +///////////////////////////////////////////////////////// +// various simple scsi sub data read funcs... used for +// ripping and subread checking... first 2352 bytes can +// be trash after read, only the bytes after are important +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// + +int ReadSub_BE_2(unsigned long addr,unsigned char * pBuf,int iNum) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = 2368*iNum; + sx.SRB_BufPointer = pBuf; + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xBE; + sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(addr & 0xFF); + sx.CDBByte[8] = iNum; + sx.CDBByte[9] = 0xF8; + sx.CDBByte[10] = 0x2; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command( (LPSRB)&sx ); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITSUB); + + if(sx.SRB_Status!=SS_COMP) + return 0; + + return 1; +} + +///////////////////////////////////////////////////////// + +int ReadSub_BE_2_1(unsigned long addr,unsigned char * pBuf,int iNum) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = 2448*iNum; // special! 96 bytes instead of 16 + sx.SRB_BufPointer = pBuf; + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xBE; + sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(addr & 0xFF); + sx.CDBByte[8] = iNum; + sx.CDBByte[9] = 0xF8; + sx.CDBByte[10] = 0x1; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITSUB); + + if(sx.SRB_Status!=SS_COMP) + return 0; + + return 1; +} + +///////////////////////////////////////////////////////// + +int ReadSub_D8(unsigned long addr,unsigned char * pBuf,int iNum) +{ + DWORD dwStatus; + + memset(&sx,0,sizeof(sx)); + sx.SRB_Cmd = SC_EXEC_SCSI_CMD; + sx.SRB_HaId = iCD_AD; + sx.SRB_Target = iCD_TA; + sx.SRB_Lun = iCD_LU; + sx.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + sx.SRB_BufLen = 2368*iNum; + sx.SRB_BufPointer = pBuf; + sx.SRB_SenseLen = SENSE_LEN; + sx.SRB_CDBLen = 12; + sx.SRB_PostProc = (LPVOID)hEvent; + sx.CDBByte[0] = 0xD8; + sx.CDBByte[2] = (unsigned char)((addr >> 24) & 0xFF); + sx.CDBByte[3] = (unsigned char)((addr >> 16) & 0xFF); + sx.CDBByte[4] = (unsigned char)((addr >> 8) & 0xFF); + sx.CDBByte[5] = (unsigned char)(addr & 0xFF); + sx.CDBByte[9] = iNum; + sx.CDBByte[10] = 1; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&sx); + if(dwStatus==SS_PENDING) + WaitGenEvent(WAITFOREVER); + + if(sx.SRB_Status!=SS_COMP) + return 0; + + return 1; +} + +///////////////////////////////////////////////////////// +// liteon subdata decoding + +void DecodeSub_BE_2_1(unsigned char * pBuf) +{ + int i,j; + unsigned char * pS=pBuf; + unsigned char c; + + for(i=0;i<12;i++) + { + c=0; + for(j=7;j>=0;j--,pS++) + { + if(*pS & 0x40) c|=(1<dwFrame = 16; // we check on addr 16 (should be available on all ps2 cds/dvds) + f->dwFrameCnt = 1; + f->dwBufLen = iBlock[i]; + + pDeInitFunc = NULL; + iRType=iModes[i]; // set global read mode + GetGenReadFunc(iRType); // get read func pointer + + for(j=0;j<3;j++) // try it 3 times + { + memset(f->BufData,0xAA,f->dwBufLen); // fill buf with AA + dwStatus=pReadFunc(TRUE,f); // do the read + +#ifdef DBGOUT +auxprintf("status %d\n",dwStatus); +#endif + + if(dwStatus!=SS_COMP) continue; // error? try again + + p=&(f->BufData[0]); + +#ifdef DBGOUT +auxprintf("check mode %d\n",i); +#endif + + for(k=0,iCnt=0;k<(int)f->dwBufLen;k+=4,p+=4) // now check the returned data + { +#ifdef DBGOUT +// auxprintf("%08x ",*((DWORD *)p)); +#endif + + if(*((DWORD *)p)==0xAAAAAAAA) // -> still AA? bad + iCnt++; + else iCnt=0; + + if(iCnt>=8) {dwStatus=SS_ERR;break;} // -> if we have found many AA's, the reading was bad + } + + if(dwStatus==SS_COMP) // reading was a success, no AA's? + { + iRType = iModes[i]; // -> set found mode + iUsedBlockSize = iBlock[i]; + if(iUsedBlockSize==2352) + iUsedMode=CDVD_MODE_2352; + else iUsedMode=CDVD_MODE_2048; + +#ifdef DBGOUT +auxprintf("mode found %d\n",i); +#endif + + return dwStatus; // -> bye + } + } + if(pDeInitFunc) pDeInitFunc(); // deinit, try next mode + } + + return dwStatus; +} + +///////////////////////////////////////////////////////// +// dummy read dunc + +DWORD ReadSCSI_Dummy(BOOL bWait,FRAMEBUF * f) +{ + return SS_ERR; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/StdAfx.c b/plugins/cdvd/CDVDpeops/StdAfx.c new file mode 100644 index 0000000..cf47398 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/StdAfx.c @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// cdvdPeops.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/plugins/cdvd/CDVDpeops/StdAfx.h b/plugins/cdvd/CDVDpeops/StdAfx.h new file mode 100644 index 0000000..d0b6fbb --- /dev/null +++ b/plugins/cdvd/CDVDpeops/StdAfx.h @@ -0,0 +1,82 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A412EBA3_CBB9_11D6_A315_008048C61B72__INCLUDED_) +#define AFX_STDAFX_H__A412EBA3_CBB9_11D6_A315_008048C61B72__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifdef _GCC +#define EXPORT_GCC __declspec (dllexport) +#else +#define EXPORT_GCC +#endif + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// special setup for MinGW/Dev-C++ ################### // +// (I don't want to change PS2Edefs.h/PS2Etypes.h) + +#undef __WIN32__ + +typedef char s8; +typedef short s16; +typedef long s32; +#ifdef _GCC +typedef long long s64; +#else +typedef __int64 s64; +#endif + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +#ifdef _GCC +typedef unsigned long long u64; +#else +typedef unsigned __int64 u64; +#endif + +#include "PS2Edefs.h" + +#define __WIN32__ + +// ################################################### // + + +#include "wnaspi32.h" +#include "scsidefs.h" + +#include "defines.h" +#include "cdda.h" +#include "cdr.h" +#include "cfg.h" +#include "generic.h" +#include "ioctrl.h" +#include "ppf.h" +#include "read.h" +#include "scsi.h" +#include "sub.h" +#include "toc.h" + +//#define DBGOUT + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A412EBA3_CBB9_11D6_A315_008048C61B72__INCLUDED_) diff --git a/plugins/cdvd/CDVDpeops/build.sh b/plugins/cdvd/CDVDpeops/build.sh new file mode 100644 index 0000000..5ce4a49 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +curdir=`pwd` + +echo ------------------ +echo Building CDVDpeops +echo ------------------ + +cd ${curdir}/src/Linux +make $@ + +# copy the files +if [ -s cfgCDVDpeops ] && [ -s libCDVDpeops.so ] +then +cp cfgCDVDpeops libCDVDpeops.so ${PCSX2PLUGINS} +fi diff --git a/plugins/cdvd/CDVDpeops/cdda.c b/plugins/cdvd/CDVDpeops/cdda.c new file mode 100644 index 0000000..dc0180b --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdda.c @@ -0,0 +1,80 @@ +/*************************************************************************** + cdda.c - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_CDDA +#include "externals.h" + +///////////////////////////////////////////////////////// +// starts/stops audio playing (addr==0 -> stop) +// note: no cdda support in PS2 plugins yet + +BOOL DoCDDAPlay(unsigned long addr) +{ + DWORD dw; + + LockGenCDAccess(); + + if(addr) dw=PlaySCSIAudio(addr,lMaxAddr-addr); // start playing (til end of cd) +// mmm... this stop doesn't work right +// else dw=PlayFunc(0,1); + else // funny stop... but seems to work + { + unsigned char cdb[3000]; + FRAMEBUF * f=(FRAMEBUF *)cdb; + + f->dwFrame = 16; // -> use an existing address (16 will ever exist on ps2 cds/dvds) + f->dwFrameCnt = 1; + f->dwBufLen = 2352; + + dw=pReadFunc(1,f); // -> do a simply sync read... seems to stop all audio playing + } + + UnlockGenCDAccess(); + + if(dw!=SS_COMP) return FALSE; + return TRUE; +} + +///////////////////////////////////////////////////////// +// get curr playing pos + +unsigned char * GetCDDAPlayPosition(void) +{ + unsigned char * pos; + + LockGenCDAccess(); + + pos=GetSCSIAudioSub(); // get the pos (scsi command) + + UnlockGenCDAccess(); + + return pos; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/cdda.h b/plugins/cdvd/CDVDpeops/cdda.h new file mode 100644 index 0000000..b51a8d9 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdda.h @@ -0,0 +1,28 @@ +/*************************************************************************** + cdda.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +BOOL DoCDDAPlay(unsigned long addr); +unsigned char * GetCDDAPlayPosition(void); diff --git a/plugins/cdvd/CDVDpeops/cdr.h b/plugins/cdvd/CDVDpeops/cdr.h new file mode 100644 index 0000000..97492cf --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdr.h @@ -0,0 +1,27 @@ +/*************************************************************************** + cdr.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +// nothing yet diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.aps b/plugins/cdvd/CDVDpeops/cdvdPeops.aps new file mode 100644 index 0000000000000000000000000000000000000000..c4534d72cef0753e16fb000548ffe371dd72fab2 GIT binary patch literal 38376 zcmd6Q3zTG6S?)iR7fA?2f*2EoPJ}#!OsY;*cUJ{8IaPJ4yO`>#N>%mrbcoiPOeSGW zG85+!5(G_9Tub3{y>Qj5B8t4iOCItjJg5nnuiSg}O;?Zh9lY^y_-V(Xy&&IpX&lyF5=4c3Sm%h#Ido{>;e$sH?cKNI zIfMv%ozAR19CUjtRIOC$1mlvnhU-%}By^&2n5?((u}&xP$M&oR@2JG0RA2N>XlWa8V!l_!J#~CMl z?)Lhe!fKVyFmCPD;c${U=Y$?_oO^4-ju30~!^UNtZcKM`HmY@cf^nLT)6K~=oeHr| zKVn=_lI_)WP+{sKof$Y**>Q<})Hrt1Y3j-hu4e_*gsIDPcJAoX*q|pGHs%DeRMU8SxVDxKIu@>@S5>JV5(d-pu%G*{EzzRJC!1@T^NwagOT^WJ zuXAY6H8-QfOJCo14n24O0rP1)ZQC`O?aIcJ-f%GM4Z7&6=m*=R7EJA4a8dO_6cT)4 zoY>ZGjVH6T-&+~X`dN2Mm7CF*fTqI{kVKG5fQ)-9tL%$&hawHI)^Iu2$WX4nKm`f&F9{ORXbF1ISNV zWVP4HP)(zL+Rg;5H2QR@1t+~LvRP+ykglOqa(tC~pDxp2x3@bpfmV_}r55V;k(AzG z#rUcAF%6k|UK#gBqiihhTw$Euj>U%KUN)G{R)^y&=mOO$P~gv3A5A%4NZrsITHG}7 z#*In)lghb}Rzh!F?j|x7z42xpIN%F0m%4`9w~6oKt546e?t`H;VUuB-v7yDJS?e76 zq}ldn(>AgmxQS_gUILcxir{j~H|jMGNWl z+UaySo?+ZUF0*CK(3=s|#=vB-DqRs_gLUqQ@RrcCBWThdbD;vO(UlQ4+{KLrP@R4{ zg2oxQNkEJAGZC~i9i#?ZqM2Zrl+!V%pDMJ6wx!+Ovt9?|&S*57_NJJd5fZA6Uhc78 zr=P85lS#T_(JK9hM_04{h$n)8kMjrMoTWe*Vj_D7GrAEK)Ss0>6XoNHLF&j;t ze%Hgp*0W3kRUbtVi}ZVvEuNw<6>MrF8{8fUwDF2_xJv&Yv*SlHN1r1TaKaNe*M9c|`0Y0)1kIKvdVmiD9(Rx53K ztH;*H>$7feJTd9PlJ4y>*2h|a3jo+VidbT>D*bU0s~IezcNVd_!D{rbBDQF-I=#Dy zEg5W)-c!Vu4Yow@En*FWEz|poSkqt)dVdi^t|jwL`alV2OD3f|N;xj6PBV+T!WbM?UAq`pjdPv;)H{!m9Mh1KMfzmqKI``eJB_C$`cw>J z=hN<`Het*3X^)Sy5fy?m3B|Z<8)xg*eaIPpVe49owTvMX` z`nn*p8Nf7R3Tm-J_lPqOl{4>LrF+G>I~=cJrPxK(62Vf19uQ!N0__bZSn#;Y!YY@( zonz7`xb?|=kYGRXV2B|%uE-Ni^bbWScBhy#dSG$92`0jaL&j)~S!+D)Wj2C3eJ3X% z;FceX6AV1xb<^a`&I#zRc5lRU!v!u824 z2dnfb5010ky-p{4ceb9WF4w@seTqjXYZ%pB4K+~6kM>wU9j{~_tI}x->zM(xQBCME z-no-aF|SH(HmWsxtVhs{GP87Oz_4+;2U@({kUDC>jPXNxK}lJl2zzT-NxHJ}$$eZz zOm_!F8|oPn57rmh=lRCeM6v#eM%;AJL@PN{1KiQLikfI3KdJ%OHkxSEXE6YChT83( z>rywFP1?Mx;y|$3qo-+LZD`hDT}1oz0N`xrz7o1906D8USfd>pUnof51ZF}gV)@vSI!!BaA*Oxi3TkX=KhdSA0 zXWDLK!99fejf8Cs#k2mnXNSAtieZXy)TbN7l5?$tD-g8T+FbAg2c{CdgXRt70 zi81Z6%IN&5nGB9`U^yqMat(OeC-3sQ+V@q3b;?I|B|U>xliFOTSsC1D>%y*oi}pfkzkVphw5kZV>nq-RMDC ziRzRs)6aRdH-MEH6K{KcJkADfGcGn8bht?2efYE|vpAC1q$Bew6Rc0AoSP{fbu?aE zo5;8}?0TTf29BFOrHerlL*R5cFuv2z zd(_9%mJ<#iQ=Oi#XxwhFR-4H($%L~=FHnR$y;vDwi7kVi;VscGl=1rM`k=k)*851; zGX0|GVT8-ZgB1M`0k6wk3`&D;^%Q6S4;W3l%`@MQavFKCnglo%u8s+!Fn+=b4rH%uK`*9p>LxdfXNjh6HR?2gVrLtv0Ik`<{bE z5t=KidLjd1wUN*tc+|FLnV_qff?wqzvw*`eq$97>A37YfM?Oqosn_e;&=={|WfU_) zm@F*OYdpmcX}L)h$zP_|dfdmNDGhpE83mmm%Xzbgt~Q$V`Z5wPEl|svnbPfLOm8JX zs#^30&soV}dC&`7le0Fx(Q{x_F5`6QO`c#tJ{-ZA1$X9fn?4f3JnH3x9)`7#MtC;tnus&{n1|9a z=JLFrTNV0~2-Ef4s?wbi%!A%=&^H4@E1{1^I9k`x+%w@!w`%l>h#g;oMm4 zLfvY+LVxCY)~02RlidW?;?H>09*Lv9o25VkgYp0NFv4!*OisZG{gsE=dZe%#eb!;4 z+2r!R8|`HX<}4%_^8X>E7}F7tL0Bhma3gaCnqUU_$B>+@ji#FjwZFcG%MHdNf~(V}c3eD0VXq|u?Tg=8N2F;~fk zXdt&EPCbWcb_%%kC?$EFJGmQ484gOg^B?hUy-?n%okDIe@I?+e+Iq3IZV6m0iw z^ow+VNa9R&GuNJ*OY}g9_XcQmXf@Lr=SLb}bD6#wl5DATa2y58hnZ6iwL#wssrI%C zH)S_I=7QDkU2EeXQ(finnm%fSR? ztxlXvdo!S$U=rCDvQS$XV$nm4DKEh+a$?B99Ko^3#V#IxTDZCyGR%0lJ_xLs38s@r zIo@QpI-UB97u}?TvxErbvB6sIk`B%kBADlYZuprTJ0JucE<_Y8NLRzo(ZNAOL_)W1 z;ijswaU~rbI7Ec7S#*}@aS_381Y~0(W#3t*Ga?QL(p$rj46B&yDxC&B-qA43VRmQ@ zcjF3Qh0gNM#+nD$DxK|J#d5%A2(gUtIoy+CP$+C3fDwj|;+|X}po%S8qlE%$ZLdkC zPUmdrqbMAY_Hj#P$X88pJXWQri1SA8idNd@Wf&Z5^i=0)4@%%zr}La64n}(up4i~L zNay=Vr)i5vTE2>C&wPvNfyIU!huM8BssOW0FsYz`CyyF%q*$Mvl+eD{TCp zU`{&iK8(>iUFK0!@^ae6*dnD0v&WnaEK$n?Vx4m*@Qf}~+oNpO6%(Ljqd^@H@q)R< z^J^wplQNIV788MCCDiq| zy2`;l95CYAQpco$YA~$SXkUn$8`2Eb=^6*MWeLnJhew+VT^|BGC`=fs(hVUpnQrzC zl+b|)!ug|ks?kA@OkgqFnenMMf~(Vw9>F3g8>27qon;)I{hUW8DUXwOC|sgL9>KhV z3B84@Dmw`#zzQ9Wv5i$W9|5bdWqN)Lt>9`uLk)UC4B?9O>eS&)`h^(pU~yt{ z3H#_TmZ2`EFp=I`hTGi2K6+aWOXNI4al&z?`@)#OvHM)ZHu_6t44ZRUMSnShO?zaM z=!-lu!831J<7q9*v*i|S9pr)3w&hGcZCJ7)9=MN=Io6jR;(j)w;O>h(ko-q#-PJ9 z_=;IMW@xX!UqW$fu?&s&4`Q6p`pjh$MA4vEmEk^sCjDVdkV8#-Uj;#=^y-+=8$_HI zy(Z=uhL5OCuZ<}#7*FcZ>td3PNuC0jvd!rAG0BBwu2&mcmu`<~C|xrMa~+{yz9A;y z^7F9I3l!Ot;TkEuF{ZSpgRZMV^vySw;IL=mik+kao%78lj6BEanr|t=S24OsCpUpC z(jUbnSiNKy<3n1ax5lI>m}Pp~T!s&)L2vggn2^_Tgl3Y_q<46vHI$1ZD94ok*gN-N zK`_?QtlFY?dVu*FY}30uXyzH8h7P^kgUBi#L}2id6CY=6%BmT?XCBE66H?1vdha}z z8x5F;W0&`No<*<_w1)N!3*GmJI2OS(JtpA1k&5({RSzbG(x zYs7c@3}cc0vcO;?o;SB-ST%pfb6}V-#>g&AKx~d1mkZs-s$b?@v(4g^NMUN7X1u|7=NoNSYi(GN{)N0pX|~){apzO zbDiQW(%)+i%nI(t!ElVrM=f*cmEj!YA2d%$!)b2K%W#D8kD6cua#q?5M;M>eI0umS zxp+78TEsENKWR<}8`yT%8|J2k3?~`?tQjg4+9jJ_0cT*;YQ?9!Jtj<&{UOw2KnqYDpnT;|Svc9TW z=oc`Mb93+~Q5o!5U(+Pc3`{Okx{?@}vF_FcJ`Izyllz9gd|}M`ddx#WzM5gh`WH>G z2VMw|?_!u1XkuKVZrkS{Z#?b8t4iMf$q*;1*;_AI_N`(j1qzpn}^~dRUWe1-JXXQ480mJE~sV z34N!8s;BsNjlQcX)+*;4T)R%+(*z#X`5F>80UV9s0LdhMk-o2K6Ff_4ukzw0O#Bl4 zK-2KzgCBOV(GjgT`&L7`rsa!pL)Ej zsYGhZJc)Vaih2RqF3s-h`+rv2%tiYD??U5(!WJAa*X1;1WgXYL*`_s-Uc)H&P#kde z*ICn{)D`bc@D+3Mh~K(0vPXW`dL9>VW4v78+rH8! z>f-zn{~SDj*3a=h5C215k&E(lY-a+#O2>ynzh{S_d6k!9RDAj)%1wWi0(;goa5njk?(*;gbpBoN#JEBfV*gmr%@^c2DI~Dei~II=+meos!pQ-`dI*0 z;7VKyyouzgoh{2yiZFB~BBN5yRAuhAT)86;&(bwrCYh@3- zNeMBan8O;34CdMsX9v<8AwM#sTfWw`i9AHsb?ZSX-dMg&Flw$tJ8jd2PF>{}=ia15Us^Zvi_&S5D zPYh#4x>d%pbe^es_C~scqKVaUR5<3Yq3L3<{@8$w2W(-jLXHn#%)=NdW$KVB2^DfI zGgip)0T|OGLO^y*VIgwFWET5vvRzjx;F?Fm|!180I z0^$x^Ffr1^s!O_^am_3(-%;GtW<#9v5`zPVeX=1rGnSsSg90sIYrkl#r?5T z0gjKA3WUP3QYph9E5)#x3HVq^A;n`Q1+ou+tfT>btfbuav66CD$4bhzxtxnp?00?wwUOKwmoOy*{PgCao6Zcr#f$qfpH7H&{zEVx0TfRY;&3XN}2 zD2Rt5TN8ZoLam}Y=90d-L7{xixj~^AB{wK?wCo0j0>c{=3Mk&7P+)w6LP7Bj3I!Ez zP$(?EK~aGG4T=KfZcxNPeuE+g@_Q1pxOKx!bb})IH0K6|!pm<^%p>GCC~`vi4T>Bt zy+IM7`UXV~%{d(|!+9AfhsSE? zCN2Fe*EA~emuni8V7aDI36^Ubm0(Si7Q68_RpruxV|uPfJfAD^h((ToL1pAVb4{Z% zpSEn;rNP?5ff$}|?s>4ercoJ~YZ^tM6S1g5XTd-`eTJGwvAdW0aUIO~QJO~Di`O(# zu3FPbIR~0XvAcV(4gn(9t0ZFaG;=p9x!|#5QJzChqY%)VMhYov8YvJP>Ri)EIb)S? zon7S>HH{42x+{Sd)-(#RNYg053Ytbm6i2CMoWY&G01Y&a3{ucE^3Gb*$hh+8kE`ZN z(@438nnnr;G>wcq@3&z1bnlj-f@CdV%Ei@knWm8mg;%&ryvWT1JX9)YSGML{#y#%I zs?ant!IWznc}$v_xs{9N#W%?!47qVd&iBb;w5VwmG3+su(lqh}xe1WV%dw^rFtcvT zFMsBf8*3UB;Yib{gn)A7Aq#h|OT2S&8dPml^SEWoGq5zaC~2XlQ88-9v1K;_xEklj z0|g~X_{EIpA+01CV@4B1lq6$FD@n$fQj&}zoQ`uESxGX6w34L3$~2i2V&AXj+DooI ziMK$LNqJ(EqZ%?;lS!dopf#Bk5Na|Rz+5T7 z%xT3DSwty7-2B5LN&#T^t|Foo0Io5zh!OzP+G53|0MLp_A%M%-UKB~Sd=73cQcMbb za_Y1sl4|(um(!?WsVSe*ytlGqQV?#Wm=s{KVv+)5#UurlDkdqMSIfMZM%xy}Bn7!M zW&=t6xI7dTla#kuF-bu#M6H;lU@kTmGjru5ib)DDQ%q8@R!qvBw^B^XNzrqySjZ^I zdVbCksT~E)XP#n`im_ZVNfBgR4Hc6V8Yw0zBvMRLh=dp^CIzq*f2^1kFtC3qDkjZg zNV};AEnHH7=4P)iR-l*^dsa99Do{*{;ZQM2p~g}p&n&cJl48g#&ahFR!mZuef#K9W!l1kWcIR3 z@kll%t}_c) zlN2ml2o5JyOj3*z#UzCm6_XSw>s*y}JY7|&lS9y|EO>fUM$yVHte8|1ilb=7q?|Ti zF-cLp>IF{?UdKpv7p*@cjYlaasgOz(lN9RXDJmvu8XJ0WFDX<^(u7cL}0dWIa#F*H-rl=*GqnP`Ufnri2qB6y#0!b?-6+o?+Q~+J4 z;dy}-lL`dgH?7IXRfDZ**Nc5O$6FyCP{hlnR&Z{sqO&Z%o9dNKaD%@{DN#(COHvX? zYJSRlaj9ZbF|eGbf>V<_)G_1=R-~9z45z4=q&OvtNeZ>CIaf@|p*f04IiBYgk>fU` zQcNnPgo;UuQmUAwa9e+fCAY~!z9?u>o)YRHso`9wmX{WIpdKnFmB#385Tcl*ICB+~ z6bB~jq7Fh8dKZdQu9&0LYF)7F9D<(x0V<+M<2oq>QF)1R?RZNO_TPh|++%m6_XLH*Bq<~5A?8ww>#1Q- z?p7T4ByDP8*-&}>?vEK*B|*i;c!^3v2}7$Sl)#}%LJ7ecz9ln|2P>gyl>`Nwc9P2+ z1l5{jp+-S481O>hiyQ=_fP+HcL3P^_^Z_W#V_v?DhG7H)fDNNWB|&AgR3%{!o~tA% zT<%8jxsH@DR1#t=xL6@72{~h~NO~n(h8LX#o1CNA>hR- z2_aZiNeJ+Am4twTs~Dv!31y^MB_ZHoDZ%y%z9k>4Bm_Jm>F4uMNeBowAgz)R;2c1S zN-Q@sa(x-24^`9DX1g_ z0nAlN2w3w}5&{xu2FomNyrLxP&@g&vveY;lh1SDI*b5s(_sCEi5QO50#uTp2@KqVmvW4=m4K%1|U5YVq~g6Wxk$3;22L*y;EWF23XyoczW(zoXrSzo0zB_Y8l0 zc|tuJ(g2@(_}<0u{Pn@(@BdeRZfO4VOKSdoJN^o{`8uAC$EWb?^KjUP@Q%I2HWG_X?gH^Utd!eP_YvHfn=&1ODv;{|Ftn!9NEtyd8EU z{!;P*x&BnD$CuZUk#T(sn>nv=?FCg#R4xL4?HVT%uEz-(5fs!QK18AJ0Qv z75Sdn-#M_l#L4Bu>EN{QL5ca?mBlrpCm^mq_}2=XOYKIK377h{$mtP;TXb8%UprnP zTn5L#8eL?6F2}xQ^E-c*J}{+s0A+T)owmm|xyIA^m8)@pp z#|W+oezsAIyYPPj|GCZFgzyfbFYrI2N6{L13;55y=dk?7_-5lZ$Bw;-9q{F`CkS?TDRw@vl)e#Q+iaN2^a|ABcY)nX>xi54$u03}#O`_^x3>kv zynuAJ(CSUkzgo(A4_x=+x4qKeO`1&Dr=bKm?0Y0^uA^JPJ%VywKzRGnYB`1l#K|pS zA7Wgf3y}YV*7YddZ^WlV5+9>iNeG-8PS4d+LR^xE=|U+DUml;PopcWVRQ$aqc|Hw) zu>Rvn*L{+%j@0w{66bS~50j>&NC)RWjAsEZTszzvxQsYIoMMxDlLME=1=QU>dhXnG zx-z;3e@^>UdRWrZmNMLn-p}R4BLc^87{8kytILP$fDw-M>0sT0d>qA3u8RZs$#cLS zX=kS0atI6HT!Vk6w2mW}hTEi`z8Tch9vSI)v|(TT-Q}9yuEl3=p*&V_J6^!7#xsJc zl(OWJ z?lAsw>bRv|1^1ir^N~_$+vRTlc^dvg{j*T!-;%Ihn;)UCb`cWKc1NT&a}AogG*7qq z--Q3y)1&FzD%}{R1Uqiq?Fj$T^q_?8`nR-88~2@b!Z!RpW8kh2qdWw=6n|R$qwxFv z(s1vTaDNbmi&@0>c^n@1f7dc@Kz;CBW_+E*%LRO$h#EX&+j$c9tymMd*0TVg zX4Sx>0=F&m<^8=9{+?+473+yx1b=yc3;ep}uSuWXYl6)4`B;p(Ps`KaL#*7B4xz?5 zCobhW%nu;UAG2Xj(9^Dx9CNz4|MNHz_74-`_U)!z&%%iFB*b^>@m#KMCNt%;Bbc9f z#1H2uu2T~l5zkd;$cOvrGx9T)K5$g}+W))xiKE(Tj*_I{8@I=+=njlX+!lGx4O=7g zxUHQ)C!i0WEIH#63D*n@w&gI}d>KEd2Yz_OF{7NBwak3Pqk?O#+V9zcU!L8$h5A{g z%+CdZAGhW`AMI@c?RO1r#mo?8ersF!<E1pXql|t>l~EPrtccN= zY}xPIN0-y-0WX2l&<^y@MEJb+Vn1gGeq7%Eqw9Gc3+Lf-IzNb~g&N}?b{)o+ zgEBi^hR?j(;5p+4q?l_Z{^D?IK{&kPK7#VQ1naGfF|P2x9r%0|eEZ$V4jU?m$2%cz zpM+f-jZQ{9e@~a^?N31ajoaGkNXvPu?5B2&;&r)O! zo4!Aa`crXN`N+MB+tH}B9UZnU>9C~a5OTZEmNfUz9WurrK})+4sXItN3pd^!9Tpe2 zBfVHsY*Np^a=K5!sy)Mg)3paP!ySc&+8%^;BYwKkDr`rW!{1Alzj^I_FVb*xo<37# zFToGqH+2v*TN+ldi}QAd6|C}mg7w9fIp$06iP+Ad_e)R5=SuEo=BO*JTZW&Qd*y2d z-_P7;em?m`d#^uw^}dC3oiyILr=5au*xs{sTA0D}x7Xxjk7pu^r@(!c zHn4-@G@Ce?>wY^AzjM8Ljx9*?Vci8|(60xayYPwY#&cM|^ZA$QaEkh!d*J8sh|I@T z)DnCiIIjpeMV&v^+IuD{)Q7V}63zK{`C|Ln?YD8B=h(+ig#QdGzsm=e%!fm_GzTly)spZ^Ok))k!q literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.c b/plugins/cdvd/CDVDpeops/cdvdPeops.c new file mode 100644 index 0000000..a1e5c04 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.c @@ -0,0 +1,89 @@ +/*************************************************************************** + cdvdPeops.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +// cdrPeops.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" +#include "cdvdPeops.h" +#define _IN_PEOPS +#include "externals.h" + +///////////////////////////////////////////////////////// + +HINSTANCE hInst=0; + +///////////////////////////////////////////////////////// +// get selected interface mode from registry: needed, +// if user has w2k and aspi available, so the plugin +// can know, what he wants to use + +int iGetUserInterfaceMode(void) +{ + HKEY myKey;DWORD temp;DWORD type;DWORD size; + int iRet=0; + + if(RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\PS2Eplugin\\CDVD\\CDVDPeops",0,KEY_ALL_ACCESS,&myKey)==ERROR_SUCCESS) + { + size = 4; + if(RegQueryValueEx(myKey,"InterfaceMode",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iRet=(int)temp; + RegCloseKey(myKey); + } + return iRet; +} + +///////////////////////////////////////////////////////// +// dll entry point + +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved) +{ + hInst=(HINSTANCE)hModule; + + switch (ul_reason_for_call) + {//--------------------------------------------------// + case DLL_PROCESS_ATTACH: + iInterfaceMode=iGetUserInterfaceMode(); // get interface on startup + OpenGenInterface(); // open interface (can be changed in the config window) + break; + //--------------------------------------------------// + case DLL_PROCESS_DETACH: + CloseGenInterface(); // close interface + break; + //--------------------------------------------------// + case DLL_THREAD_ATTACH: + break; + //--------------------------------------------------// + case DLL_THREAD_DETACH: + break; + //--------------------------------------------------// + } + return TRUE; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.def b/plugins/cdvd/CDVDpeops/cdvdPeops.def new file mode 100644 index 0000000..90bdc5c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.def @@ -0,0 +1,30 @@ +; cdvdPeops.def : Declares the module parameters for the DLL. + +LIBRARY "cdvdPeops" + +EXPORTS + ; Explicit exports can go here + + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + CDVDinit @5 + CDVDshutdown @6 + CDVDopen @7 + CDVDclose @8 + CDVDconfigure @9 + CDVDabout @10 + CDVDtest @11 + CDVDgetTN @12 + CDVDgetTD @13 + CDVDreadTrack @14 + CDVDgetBuffer @15 + CDVDgetDiskType @16 + CDVDgetTrayStatus @17 + CDVDreadSubQ @18 + CDVDgetTOC @19 + CDVDctrlTrayOpen @20 + CDVDctrlTrayClose @21 +; PS2EgetCpuPlatform @18 + + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.def.bak b/plugins/cdvd/CDVDpeops/cdvdPeops.def.bak new file mode 100644 index 0000000..55d1203 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.def.bak @@ -0,0 +1,30 @@ +; cdvdPeops.def : Declares the module parameters for the DLL. + +LIBRARY "cdvdPeops" + +EXPORTS + ; Explicit exports can go here + + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + CDVDinit @5 + CDVDshutdown @6 + CDVDopen @7 + CDVDclose @8 + CDVDconfigure @9 + CDVDabout @10 + CDVDtest @11 + CDVDgetTN @12 + CDVDgetTD @13 + CDVDreadTrack @14 + CDVDgetBuffer @15 + CDVDgetDiskType @16 + CDVDgetTrayStatus @17 + PS2EgetCpuPlatform @18 + CDVDreadSubQ @19 + CDVDgetTOC @20 + CDVDctrlTrayOpen @21 + CDVDctrlTrayClose @22 + + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.dev b/plugins/cdvd/CDVDpeops/cdvdPeops.dev new file mode 100644 index 0000000..968ed2b --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.dev @@ -0,0 +1,418 @@ +[Project] +FileName=cdvdPeops.dev +Name=cdvdPeops +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC_@@_ +CppCompiler=-D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC_@@_ +Includes=d:\vs\vc98\MFC\include +Linker=-lkernel32 -luser32 -ladvapi32 -lcomdlg32 --add-stdcall-alias_@@_ +Libs= +UnitCount=37 +Folders="Documentation files","Header Files","Resource Files","Source Files" +ObjFiles= +PrivateResource=cdvdPeops_private.rc +ResourceIncludes= +MakeIncludes= +Icon= +ExeOutput=..\..\..\emus\pcsx2_0.6\plugins +ObjectOutput=Release +OverrideOutput=1 +OverrideOutputName=cdvdPeops.dll +HostApplication= +CommandLine= +UseCustomMakefile=0 +CustomMakefile=OwnMakefile.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000001001000000000 + +[Unit1] +FileName=cdr.c +CompileCpp=0 +Folder="Source Files" +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=cdvdPeops.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=cdvdPeops.def +Folder="Source Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=cfg.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=generic.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=ioctrl.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=ppf.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=read.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=scsi.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=StdAfx.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=sub.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=toc.c +Folder="Source Files" +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=cdda.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=cdr.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=cdvdPeops.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=cfg.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=defines.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=externals.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=generic.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=ioctrl.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=ppf.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=read.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=resource.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=scsi.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=scsidefs.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=StdAfx.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=sub.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=toc.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=wnaspi32.h +Folder="Header Files" +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=cdvdPeops.rc +Folder="Resource Files" +Compile=1 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=changelog.txt +Folder="Documentation files" +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=filemap.txt +Folder="Documentation files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=license.txt +Folder="Documentation files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=cdda.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c cdda.c -o cdda.o $(CFLAGS) + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=cdvdPeops.exe +ProductName=cdvdPeops +ProductVersion=0.1 +AutoIncBuildNr=0 + +[Unit35] +FileName=i386.asm +Folder=Source Files +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=1 +BuildCmd=nasmw.exe -f win32 -D__WIN32__ -D__i386__ i386.asm -o release\i386.o + +[Unit36] +FileName=PS2Edefs.h +CompileCpp=1 +Folder=Header Files +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=PS2Etypes.h +CompileCpp=1 +Folder=Header Files +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.dsp b/plugins/cdvd/CDVDpeops/cdvdPeops.dsp new file mode 100644 index 0000000..1d4555c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.dsp @@ -0,0 +1,251 @@ +# Microsoft Developer Studio Project File - Name="cdvdPeops" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=cdvdPeops - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cdvdPeops.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cdvdPeops.mak" CFG="cdvdPeops - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cdvdPeops - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "cdvdPeops - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cdvdPeops - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /G5 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib advapi32.lib comdlg32.lib /nologo /subsystem:windows /dll /machine:I386 +# SUBTRACT LINK32 /pdb:none +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=copy release\*.dll d:\emus\pcsx2_07\plugins +# End Special Build Tool + +!ELSEIF "$(CFG)" == "cdvdPeops - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "cdvdPeops - Win32 Release" +# Name "cdvdPeops - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\cdda.c +# End Source File +# Begin Source File + +SOURCE=.\cdr.c +# End Source File +# Begin Source File + +SOURCE=.\cdvdPeops.c +# End Source File +# Begin Source File + +SOURCE=.\cdvdPeops.def +# End Source File +# Begin Source File + +SOURCE=.\cfg.c +# End Source File +# Begin Source File + +SOURCE=.\generic.c +# End Source File +# Begin Source File + +SOURCE=.\ioctrl.c +# End Source File +# Begin Source File + +SOURCE=.\ppf.c +# End Source File +# Begin Source File + +SOURCE=.\read.c +# End Source File +# Begin Source File + +SOURCE=.\scsi.c +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.c +# End Source File +# Begin Source File + +SOURCE=.\sub.c +# End Source File +# Begin Source File + +SOURCE=.\toc.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\cdda.h +# End Source File +# Begin Source File + +SOURCE=.\cdr.h +# End Source File +# Begin Source File + +SOURCE=.\cdvdPeops.h +# End Source File +# Begin Source File + +SOURCE=.\cfg.h +# End Source File +# Begin Source File + +SOURCE=.\defines.h +# End Source File +# Begin Source File + +SOURCE=.\externals.h +# End Source File +# Begin Source File + +SOURCE=.\generic.h +# End Source File +# Begin Source File + +SOURCE=.\ioctrl.h +# End Source File +# Begin Source File + +SOURCE=.\ppf.h +# End Source File +# Begin Source File + +SOURCE=".\PSEmu Plugin Defs.h" +# End Source File +# Begin Source File + +SOURCE=.\read.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\scsi.h +# End Source File +# Begin Source File + +SOURCE=.\scsidefs.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\sub.h +# End Source File +# Begin Source File + +SOURCE=.\toc.h +# End Source File +# Begin Source File + +SOURCE=.\wnaspi32.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\cdvdPeops.rc +# End Source File +# End Group +# Begin Group "Documentation files" + +# PROP Default_Filter "txt" +# Begin Source File + +SOURCE=.\changelog.txt +# End Source File +# Begin Source File + +SOURCE=.\filemap.txt +# End Source File +# Begin Source File + +SOURCE=.\license.txt +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.dsw b/plugins/cdvd/CDVDpeops/cdvdPeops.dsw new file mode 100644 index 0000000..55e3602 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cdvdPeops"=.\cdvdPeops.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.h b/plugins/cdvd/CDVDpeops/cdvdPeops.h new file mode 100644 index 0000000..87d277e --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.h @@ -0,0 +1,25 @@ +/*************************************************************************** + cdvdPeops.h - description + ------------------- + begin : Wed Nov 12 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.layout b/plugins/cdvd/CDVDpeops/cdvdPeops.layout new file mode 100644 index 0000000..ebcf4cf --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.layout @@ -0,0 +1,238 @@ +[Editor_26] +CursorCol=1 +CursorRow=19 +TopLine=12 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Order=0,35,11,4,10 +Focused=35 +[Editor_0] +Open=1 +Top=0 +CursorCol=39 +CursorRow=60 +TopLine=36 +LeftChar=1 +[Editor_1] +Open=0 +Top=0 +CursorCol=1 +CursorRow=23 +TopLine=1 +LeftChar=1 +[Editor_2] +Open=0 +Top=0 +CursorCol=2 +CursorRow=26 +TopLine=1 +LeftChar=1 +[Editor_3] +Open=0 +Top=0 +CursorCol=1 +CursorRow=438 +TopLine=428 +LeftChar=1 +[Editor_4] +Open=1 +Top=0 +CursorCol=19 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_5] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_6] +Open=0 +Top=0 +CursorCol=20 +CursorRow=20 +TopLine=1 +LeftChar=1 +[Editor_7] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_8] +Open=0 +Top=0 +CursorCol=19 +CursorRow=95 +TopLine=94 +LeftChar=1 +[Editor_9] +Open=0 +Top=0 +CursorCol=1 +CursorRow=8 +TopLine=1 +LeftChar=1 +[Editor_10] +Open=1 +Top=0 +CursorCol=17 +CursorRow=167 +TopLine=156 +LeftChar=1 +[Editor_11] +Open=1 +Top=0 +CursorCol=7 +CursorRow=99 +TopLine=70 +LeftChar=1 +[Editor_12] +Open=0 +Top=0 +[Editor_13] +Open=0 +Top=0 +CursorCol=27 +CursorRow=19 +TopLine=2 +LeftChar=1 +[Editor_14] +Open=0 +Top=0 +[Editor_15] +Open=0 +Top=0 +[Editor_16] +Open=0 +Top=0 +CursorCol=9 +CursorRow=112 +TopLine=95 +LeftChar=1 +[Editor_17] +Open=0 +Top=0 +CursorCol=1 +CursorRow=42 +TopLine=31 +LeftChar=1 +[Editor_18] +Open=0 +Top=0 +CursorCol=15 +CursorRow=15 +TopLine=16 +LeftChar=1 +[Editor_19] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_20] +Open=0 +Top=0 +[Editor_21] +Open=0 +Top=0 +[Editor_22] +Open=0 +Top=0 +[Editor_23] +Open=0 +Top=0 +CursorCol=18 +CursorRow=32 +TopLine=20 +LeftChar=1 +[Editor_24] +Open=0 +Top=0 +CursorCol=16 +CursorRow=258 +TopLine=544 +LeftChar=1 +[Editor_25] +Open=0 +Top=0 +CursorCol=1 +CursorRow=19 +TopLine=47 +LeftChar=1 +[Editor_27] +Open=0 +Top=0 +CursorCol=16 +CursorRow=22 +TopLine=1 +LeftChar=1 +[Editor_28] +Open=0 +Top=0 +CursorCol=83 +CursorRow=281 +TopLine=187 +LeftChar=1 +[Editor_29] +Open=0 +Top=0 +CursorCol=17 +CursorRow=210 +TopLine=1 +LeftChar=1 +[Editor_30] +Open=0 +Top=0 +CursorCol=47 +CursorRow=5 +TopLine=1 +LeftChar=1 +[Editor_31] +Open=0 +Top=0 +CursorCol=34 +CursorRow=19 +TopLine=1 +LeftChar=1 +[Editor_32] +Open=0 +Top=0 +CursorCol=13 +CursorRow=269 +TopLine=257 +LeftChar=1 +[Editor_33] +Open=0 +Top=0 +CursorCol=29 +CursorRow=20 +TopLine=1 +LeftChar=1 +[Editor_34] +Open=0 +Top=0 +CursorCol=1 +CursorRow=26 +TopLine=1 +LeftChar=1 +[Editor_35] +CursorCol=15 +CursorRow=282 +TopLine=39 +LeftChar=1 +Open=1 +Top=1 +[Editor_36] +Open=0 +Top=0 +CursorCol=1 +CursorRow=29 +TopLine=1 +LeftChar=1 diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.opt b/plugins/cdvd/CDVDpeops/cdvdPeops.opt new file mode 100644 index 0000000000000000000000000000000000000000..ed0495e33340205fae97c306affb7116c4f4e310 GIT binary patch literal 50688 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 B(#`+? literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.plg b/plugins/cdvd/CDVDpeops/cdvdPeops.plg new file mode 100644 index 0000000..c020cb4 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.plg @@ -0,0 +1,96 @@ + + +
+

Build Log

+

+--------------------Configuration: cdvdPeops - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x407 /fo"Release/cdvdPeops.res" /d "NDEBUG" "D:\src\cdvdPeops\src\cdvdPeops.rc"" +Creating temporary file "E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSP9E.tmp" with contents +[ +/nologo /G5 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR"Release/" /Fp"Release/cdvdPeops.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"D:\src\cdvdPeops\src\cdda.c" +"D:\src\cdvdPeops\src\cdr.c" +"D:\src\cdvdPeops\src\cdvdPeops.c" +"D:\src\cdvdPeops\src\cfg.c" +"D:\src\cdvdPeops\src\generic.c" +"D:\src\cdvdPeops\src\ioctrl.c" +"D:\src\cdvdPeops\src\ppf.c" +"D:\src\cdvdPeops\src\read.c" +"D:\src\cdvdPeops\src\scsi.c" +"D:\src\cdvdPeops\src\StdAfx.c" +"D:\src\cdvdPeops\src\sub.c" +"D:\src\cdvdPeops\src\toc.c" +] +Creating command line "cl.exe @E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSP9E.tmp" +Creating temporary file "E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSP9F.tmp" with contents +[ +kernel32.lib user32.lib advapi32.lib comdlg32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"Release/cdvdPeops.pdb" /machine:I386 /def:".\cdvdPeops.def" /out:"Release/cdvdPeops.dll" /implib:"Release/cdvdPeops.lib" +.\Release\cdda.obj +.\Release\cdr.obj +.\Release\cdvdPeops.obj +.\Release\cfg.obj +.\Release\generic.obj +.\Release\ioctrl.obj +.\Release\ppf.obj +.\Release\read.obj +.\Release\scsi.obj +.\Release\StdAfx.obj +.\Release\sub.obj +.\Release\toc.obj +.\Release\cdvdPeops.res +] +Creating command line "link.exe @E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSP9F.tmp" +

Output Window

+Compiling resources... +Compiling... +cdda.c +cdr.c +cdvdPeops.c +cfg.c +generic.c +ioctrl.c +ppf.c +read.c +scsi.c +StdAfx.c +sub.c +toc.c +Linking... + Creating library Release/cdvdPeops.lib and object Release/cdvdPeops.exp +Creating temporary file "E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSPA3.tmp" with contents +[ +/nologo /o"Release/cdvdPeops.bsc" +.\Release\cdda.sbr +.\Release\cdr.sbr +.\Release\cdvdPeops.sbr +.\Release\cfg.sbr +.\Release\generic.sbr +.\Release\ioctrl.sbr +.\Release\ppf.sbr +.\Release\read.sbr +.\Release\scsi.sbr +.\Release\StdAfx.sbr +.\Release\sub.sbr +.\Release\toc.sbr] +Creating command line "bscmake.exe @E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSPA3.tmp" +Creating browse info file... +

Output Window

+Creating temporary file "E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSPA4.bat" with contents +[ +@echo off +copy release\*.dll d:\emus\pcsx2_07\plugins +] +Creating command line "E:\DOCUME~1\Pete1\LOCALS~1\Temp\RSPA4.bat" + +release\cdvdPeops.dll + 1 file(s) copied. + + + +

Results

+cdvdPeops.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.rc b/plugins/cdvd/CDVDpeops/cdvdPeops.rc new file mode 100644 index 0000000..83e137a --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.rc @@ -0,0 +1,235 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,2,0 + PRODUCTVERSION 1,0,2,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040704b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Pete Bernert and the P.E.Op.S. team\0" + VALUE "FileDescription", "cdvdPeops\0" + VALUE "FileVersion", "1, 0, 2, 0\0" + VALUE "InternalName", "cdvdPeops\0" + VALUE "LegalCopyright", "Copyright 2003-2004\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "cdvdPeops.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "cdvdPeops\0" + VALUE "ProductVersion", "1, 0, 2, 0\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x407, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 287, 239 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Configure the P.E.Op.S. ASPI/IOCTL PS2 CDVD Driver..." +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_IMODE,63,6,199,52,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_DRIVE,63,22,199,52,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_CACHE,63,39,199,65,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "Use additional 4 MByte data cache",IDC_DATACACHE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,63,55,156,11 + CONTROL "Try to limit speed (not supported by all drives)", + IDC_SPEEDLIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13, + 76,156,11 + COMBOBOX IDC_SPEED,204,75,33,93,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "Don't wait until drive is ready (needed by a few drives)", + IDC_NOWAIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,89, + 198,11 + CONTROL "Check tray state (not tested, you can leave that off)", + IDC_TRAYSTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13, + 102,186,11 + CONTROL "Try again on reading error. Retry count (1-10):", + IDC_TRYAGAIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13, + 129,156,11 + EDITTEXT IDC_RETRY,204,128,33,13,ES_AUTOHSCROLL + CONTROL "Show message box on reading error",IDC_SHOWREADERR, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,142,156,11 + CONTROL "Use PPF patch file:",IDC_USEPPF,"Button", + BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,168,74,11 + EDITTEXT IDC_PPFFILE,89,168,167,12,ES_AUTOHSCROLL | WS_DISABLED + PUSHBUTTON "...",IDC_CHOOSEFILE,259,168,13,12,WS_DISABLED + COMBOBOX IDC_SUBCHAN0,13,197,261,52,CBS_DROPDOWNLIST | + WS_DISABLED | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_SUBFILE,63,197,193,12,ES_AUTOHSCROLL | WS_DISABLED + PUSHBUTTON "...",IDC_CHOOSESUBF,259,197,13,12,WS_DISABLED + DEFPUSHBUTTON "OK",IDOK,63,221,50,14 + PUSHBUTTON "Cancel",IDCANCEL,175,221,50,14 + RTEXT "Drive:",IDC_STATIC,37,24,21,11 + RTEXT "Caching mode:",IDC_STATIC,9,41,49,11 + GROUPBOX "Error handling",IDC_STATIC,6,119,275,38 + GROUPBOX "PPF patches",IDC_STATIC,6,158,275,28 + GROUPBOX "Misc",IDC_STATIC,6,66,275,52 + RTEXT "Interface:",IDC_STATIC,15,8,43,11 + GROUPBOX "Subchannel reading",IDC_STATIC,6,187,275,29 + RTEXT "File:",IDC_SFSTATIC,26,198,30,11,SS_CENTERIMAGE +END + +IDD_ABOUT DIALOGEX 0, 0, 238, 210 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About the P.E.Op.S. ASPI/IOCTL PS2 CDVD Driver..." +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,98,188,44,14 + RTEXT "Version :",IDC_STATIC,5,5,74,9 + RTEXT "Release date :",IDC_STATIC,5,16,74,9 + RTEXT "Coded by :",IDC_STATIC,5,27,74,9 + RTEXT "Pete's EMail :",IDC_STATIC,5,40,74,9 + RTEXT "Pete's homepage :",IDC_STATIC,5,51,74,9 + LTEXT "1.2",IDC_STATIC,82,5,154,9 + LTEXT "25.12.2004",IDC_STATIC,81,16,154,9 + LTEXT "Pete Bernert and the P.E.Op.S. team",IDC_STATIC,81,27, + 154,9 + LTEXT "BlackDove@addcom.de",IDC_STATIC,81,39,154,9 + LTEXT "http://www.pbernert.com",IDC_STATIC,81,51,154,9 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,9,100,218,81, + WS_EX_DLGMODALFRAME + RTEXT "Thanks to :",IDC_STATIC,16,109,38,9 + LTEXT "the PCSX2 team - special thanx to shadow for kicking my ass", + IDC_STATIC,57,109,161,18 + LTEXT "My girlfriend Heike... because everything I do wouldn't be the same without her", + IDC_STATIC,57,130,161,19 + RTEXT "P.E.Op.S. homepage :",IDC_STATIC,5,80,74,9 + LTEXT "https://sourceforge.net/projects/peops/",IDC_STATIC,81, + 80,154,9 + RTEXT "linuzappz :",IDC_STATIC,10,63,69,10 + LTEXT "http://www.pcsx.net",IDC_STATIC,81,63,142,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 280 + TOPMARGIN, 7 + BOTTOMMARGIN, 232 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 231 + TOPMARGIN, 7 + BOTTOMMARGIN, 203 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.sln b/plugins/cdvd/CDVDpeops/cdvdPeops.sln new file mode 100644 index 0000000..3793c5c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdvdPeops", "cdvdPeops.vcproj", "{74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Debug.ActiveCfg = Debug|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Debug.Build.0 = Debug|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Release.ActiveCfg = Release|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops.suo b/plugins/cdvd/CDVDpeops/cdvdPeops.suo new file mode 100644 index 0000000000000000000000000000000000000000..53722080b1d8783710cbde153a322d1317f82ff7 GIT binary patch literal 13312 zcmeI2TWnlM8OO(Kn>fy;O-W-2p)AhLgxF1d2}u)D?6s4oiF0$B1j!Pz*T>E#>s@QT zP7|6)d8v>96(nAGs8n%zqd<8<;-w&7C`c%P1WyRj2jDS0a0$?M`Tggd**$yp#?B^b znpyq#%+Ac2Z_YRW`Mz)F>~C(a`}4PcwDE0Ik`9_?^ImSH`B135iM(LbaVqq{i3OvMmIM2El(mbZ7!N4 zNS`J*Vy@KcqO5L%i8P6O;-tn=)}Ts(xT|!=Oqh9d$s98Yu37T}-yUOf<@0{Cs^43X zzn)sHnR?~RhH8B&9YK<2AZaG~zGB9#^vjGUPHyoOMZV-}4c04PHv0!b*IJ)~=0tYD z{nqoiyw<<$fNX%)zwChYEgiZxZvE@`0Oc;?P4GhjbB06q&2f@i_!z#td` zF)$29z#(uLJO_?|=fP2M42*)~-~>1cPJz>444eTP$JyX|p6lm>JjD-W`dRNQtN-xZ zrsu!%lZD@Z_4RcxGu%5$e~-yaEIo-=kHs=q=d%;Z=xJ{*oypoI*D^ejolv*!=SPo4 z$Kn^fS^IO%aAG2vo{5f3C9>&^8azIlo=haY=s9mPdMKTlwYRS<`qdsw&(5V&Udr!# z&ACKsD*fVop?S-5XGS%1h zR9uomHXvQtM_?C;&PHF zon~x>ak<~d-2d^F@=q2hg|^4gwk*wJQHbN8xTl1|7fs^oUz_}9)#YDBZ;FYm;jP-I zXR!Vh6V)qUv6^B9C9U@?GBaphd@pza z7a4oZL6&tTTcDQ37U`KlzGN%;z1IHLv&&v7RpO`5TIW5~s@jU1P-R&vzrUp^F-b4i}xJ)^(Qrg`caYyTwK_rt*rB^TDel`GjwCDj#wc2GJQ z5cC8#?jkcNpIB{;SL`Gxd};~uKgqprbq~R=VIs#tm@xt+ySWZiHe$h8XQ0a~*#?MT{sPUEtjb8@+^Cr`=+48^=xGx~Xj&u}m>HmpiuocDEO1`*M5i zK_4z&y%zX~J|dAGJp7PlsiK}C7$t*HSar|dpWk*eabI~j{s%b@isiq1Ud zaT@mdGq8edanJk9p2fEygFN*iSR%W!_W0Nz-@LVY^vhen`P0a2Pu{js;osJ8{oM~Y zZ$A9vzr1~Y`{Zmtc8r$4+?af4<>nJ#&wc6k&7XgF#M(}|Beyj<$$YOTNrB1M7J>bUU+oi((rrIbvmtcRx&tJ~5 zYLY6KuU~?E+1VQbY5tRE$$#^?|K)S<^sX@>ht(4 zt%hK29G|CMwwFKuR1EZO97QhIX1>E!QBMzks(58QUBOiJ;6v4;QWwxk_Egbm{8@Ep z8wsRpW_3PUSXawib2`KE_rB7Czc(IdB(pX)D?}0FFl;P1*NM~aN=g0;l<98y6pvc* z-(SlI@)F`pkf2^_*@64TgY!4#kCvVm=aG0S9u;Q#ZgR*5(aQ}hu2m#;*wtKv(2Y1C zjJx+7?)}FY@r!J*&fpXkFJ=L;zjqw}_A(Bd$5}_A!p-ZB*{#8bhNxs1NHn-T?g;>2_;v z-R^owbQ^7*_{vto5Jw!N#&t~=C14Zrn4}?;^A?h4&MM z@da!X*ScD^H51V1az*R7gY)l>h<4oVI;SP=xaaG*^u?vWA-G&gr<6J674%)7f*a*| zq}x-??GdZnqIF!V+la}(TexR&)7{r?jMb|nm`j0gzr-=YRm=Xy`5_&GFMi-%5=XkV zX-_gCcGw=cx?uBJjce}D8ZMSe63t9D(0++aW6hgqSJZh2dc*hr;!2Vf62VDgte30@7=`R=4Xg>pg^^$tJK`~>|9I%J1H3u#4 z6aMPZTTZr7)~!fq> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops_2005.sln b/plugins/cdvd/CDVDpeops/cdvdPeops_2005.sln new file mode 100644 index 0000000..8f88a95 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops_2005.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cdvdPeops", "cdvdPeops_2005.vcproj", "{74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Debug|Win32.ActiveCfg = Debug|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Debug|Win32.Build.0 = Debug|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Release|Win32.ActiveCfg = Release|Win32 + {74689B0D-A4E7-4D0E-A2D8-8A30EA455BC6}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops_2005.vcproj b/plugins/cdvd/CDVDpeops/cdvdPeops_2005.vcproj new file mode 100644 index 0000000..a06cc37 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops_2005.vcproj @@ -0,0 +1,647 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops_private.h b/plugins/cdvd/CDVDpeops/cdvdPeops_private.h new file mode 100644 index 0000000..18a8395 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops_private.h @@ -0,0 +1,23 @@ +// THIS FILE WILL BE OVERWRITTEN BY DEV-C++! +// DO NOT EDIT! + +#ifndef CDVDPEOPS_PRIVATE_H +#define CDVDPEOPS_PRIVATE_H + +// VERSION DEFINITIONS +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "0.1" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "cdvdPeops.exe" +#define PRODUCT_NAME "cdvdPeops" +#define PRODUCT_VERSION "0.1" + +#endif //CDVDPEOPS_PRIVATE_H diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops_private.rc b/plugins/cdvd/CDVDpeops/cdvdPeops_private.rc new file mode 100644 index 0000000..ae59fb0 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cdvdPeops_private.rc @@ -0,0 +1,4 @@ +// THIS FILE WILL BE OVERWRITTEN BY DEV-C++! +// DO NOT EDIT! + +#include "cdvdPeops.rc" diff --git a/plugins/cdvd/CDVDpeops/cdvdPeops_private.res b/plugins/cdvd/CDVDpeops/cdvdPeops_private.res new file mode 100644 index 0000000000000000000000000000000000000000..73dde28c621dce1432cf712a4a113338b41a6e36 GIT binary patch literal 4584 zcmcIo%WqUw82`<50C`laL}I|l#VAFEK4>F>kd!_k7AYMlG+<)PbUH0#+v#LxN`X}& zA#ueYV2Ht$xRQk{A4y%HE?5|rCb~9J!M8*c@%Q`AJ#+6J23Q!+mmvaAI6DZ{35=GUvYHbA2UWVY##lcrDhy-O9}pCM?VN za!Jii)_*2-%j!YQql76GF^vUOP@s%8oU}TN4(#JIN_jgl#wS2O>nw)R$!8RUIEsTD z&2n@H>p=`*oKL`~LYk*Yr^0>u0S{q>>jFMG@~m1*^F{KP-Zy6jsShjh1$yy&%bhzH zG{6$gZLqoTn$ERzt{>kg=29Weow$UxxZN^9DQo;mYTy`ANa7qO`73g~Xfrv?afd~6)zYFucPaD6`S!oer%$LR-C}+#CNj+-;hb& zZoC&Mn=}y+Ly2{Jl24gEnx8;c)iZ1@DVZn(ST{t^qa>F zch|@*XPl~R%L=kbq%ZX~BktQcbB6LPu$G-ltYEeZkGO!4QmCm-{8&Y2B= zZouPhnBz&2hD29h6lp?Z)9lNqE1Z+(2ROpM@Jmm5!zHZ>eK)rA=^}#N&W#vU&Y8bn zXKOQBaf>!Q7tTfaE*id{8t{!#U-PExIdZJ>C#2HT1jkRaeh}KaFEf0B+^^sO?ea?l zAAe@DJoWoYwM;%WI}Nh7yrmGA$7r1(t@p4FzsBTYM7Ft>)D`kthu=82RF4&Q=0hCU zup-rqKV$w(J=t6zuHiH8{i`Y6Yex6)2D+)x&VBfXG3#OG1@Rr_sqw}6!3W`d+U5r- zWr6kBAB%h5rheUO+PS;FPV^K(ywA+hI+JzHF_atam9*#j z)E1+?#8~Y8D&S7xnIsxV!C{K_y~BM^hWqZel>9>_T0g+`z2W*1(yS7lD<1zNjNdQS z@eh-`&Rc~xmn4zRBbpzR=2IcfF`mZ>lUTSFEfmFk42jE-PCMB*GEzNFerq$*>;8mi z$z~xuD6g%z&Q08~y5BrrasL0zWn`7QUq18r6TN8V-TrV$Z zr@sXB&k_29%NNb|_S|Q$Vwd8UqKS)INeZT=>=Ekd?U;_b885oMLh5xodl+qrbvv+& zE4$Fc_YT%w%9d1l+exPsMhcCHUbLc<$IV$W zDW~U{V&gH!qt)E^H4dA9j*+UOevud(i+rn%xVOaYbTo`tGv+7m7SznXySVRNa?|P7 z8HjG8gS<5!w>zfSY(TmE{V7i*?#`wivXAne<5RVfN$NoNkSW#`)-#4(Z?hy-Ki{u_hQ{E zqYN<2l|mU1r*1E^?3L&%@;Fh5{7so%w$)1A)O2=Sw9~!45{J&VJL}novv>E+{=p|u zK9_CkbJfu6s)nROX$zsIb(T9Qhdiv4-l==ho9yM;ui8j~BV}tRfeZH(E9-rgC)S}ohPJerY?|r<#joG)( zA@+xHh?!{A7Jiz!^^g0iOtBw5eU1z={H4RTufDYbogR6NJkRGfjEz`mq&Y(*-d-8?dINPZ{OBIB(*p_eG4c?7iftb+lp(x3|XEZ z4SC7RLg4MJo~+kQM~ck)x&xjyep#b&iaR8^zFd`CCqqU~FIuC#yk}9&0IDb Ux|?3Dx0dUz_`f$gb1g>kU*jg);Q#;t literal 0 HcmV?d00001 diff --git a/plugins/cdvd/CDVDpeops/cfg.h b/plugins/cdvd/CDVDpeops/cfg.h new file mode 100644 index 0000000..dfa285b --- /dev/null +++ b/plugins/cdvd/CDVDpeops/cfg.h @@ -0,0 +1,47 @@ +/*************************************************************************** + cfg.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void ReadConfig(void); +void WriteConfig(void); +void OnChooseFile(HWND hW,int iFType); +void EnumDrives(HWND hW); +void GetCDRInfos(HWND hW,int * iA, int * iT,int * iL); +void OnIMode(HWND hW); +void OnCache(HWND hW); +void ShowSubFileStuff(HWND hW); +BOOL OnInitCDRDialog(HWND hW); +void OnCDRAuto(HWND hW); +void ShowProgress(HWND hW,long lact,long lmin,long lmax); +void WriteDiffSub(FILE * xfile,int i,unsigned char * lpX,int iM,BOOL b3Min); +BOOL OnCreateSubFileEx(HWND hW,HWND hWX,BOOL b3Min); +BOOL OnCreateSubEx(HWND hW,HWND hWX,int iM,BOOL b3Min); +void StartSubReading(HWND hW,HWND hWX); +BOOL CALLBACK SubDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +void OnCreateSub(HWND hW); +void OnCDROK(HWND hW); +void OnCDRCancel(HWND hW); +BOOL CALLBACK CDRDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); diff --git a/plugins/cdvd/CDVDpeops/changelog.txt b/plugins/cdvd/CDVDpeops/changelog.txt new file mode 100644 index 0000000..83c8f0a --- /dev/null +++ b/plugins/cdvd/CDVDpeops/changelog.txt @@ -0,0 +1,19 @@ +######################################################################### + +Version 1.2 +----------- +- Pete: added an hack in CDVDgetTD for big dvds +- Pete: fixed a track size calculation bug + + +Version 1.1 +----------- +- Pete: added dvd support for Plextor PX-708A + +Version 1.0 +----------- +- First release + Pete Bernert: ported the P.E.Op.S. PSX cdr plugin to PS2 needs + +######################################################################### + diff --git a/plugins/cdvd/CDVDpeops/defines.h b/plugins/cdvd/CDVDpeops/defines.h new file mode 100644 index 0000000..5ead0e7 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/defines.h @@ -0,0 +1,212 @@ +/*************************************************************************** + defines.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +// general buffer for reading several frames + +#pragma pack(1) + +typedef struct _FRAMEBUF +{ + DWORD dwFrame; + DWORD dwFrameCnt; + DWORD dwBufLen; + unsigned char BufData[1024*1024]; +} FRAMEBUF; + +#pragma pack() + +// raw ioctl structs: + +typedef enum _TRACK_MODE_TYPE +{ + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct _RAW_READ_INFO +{ + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +// sub cache: + +typedef struct +{ + long addr; + void * pNext; + unsigned char subq[10]; +} SUB_DATA; + +typedef struct +{ + long addr; + void * pNext; +} SUB_CACHE; + +// ppf cache: + +typedef struct +{ + long addr; + void * pNext; + long pos; + long anz; + // memdata +} PPF_DATA; + +typedef struct +{ + long addr; + void * pNext; +} PPF_CACHE; + +///////////////////////////////////////////////////////// + +#define MODE_BE_1 1 +#define MODE_BE_2 2 +#define MODE_28_1 3 +#define MODE_28_2 4 +#define MODE_28_2048 5 +#define MODE_28_2048_Ex 6 + +#define itob(i) ((i)/10*16 + (i)%10) +#define btoi(b) ((b)/16*10 + (b)%16) +#define itod(i) ((((i)/10)<<4) + ((i)%10)) +#define dtoi(b) ((((b)>>4)&0xf)*10 + (((b)&0xf)%10)) + +///////////////////////////////////////////////////////// + +void addr2time(unsigned long addr, unsigned char *time); +void addr2timeB(unsigned long addr, unsigned char *time); +unsigned long time2addr(unsigned char *time); +unsigned long time2addrB(unsigned char *time); +#ifdef _GCC +#define reOrder i386_reOrder +#endif +unsigned long reOrder(unsigned long value); + +///////////////////////////////////////////////////////// +// debug helper + +#ifndef _IN_CDR +#ifdef DBGOUT +void auxprintf (LPCTSTR pFormat, ...); +#endif +#endif + +///////////////////////////////////////////////////////// + +typedef DWORD (*READFUNC)(BOOL bWait,FRAMEBUF * f); +typedef DWORD (*DEINITFUNC)(void); +typedef BOOL (*READTRACKFUNC)(unsigned long addr); +typedef void (*GETPTRFUNC)(void); + +///////////////////////////////////////////////////////// + +#define WAITFOREVER 0xFFFFFFFF +#define WAITSUB 10000 +#define FRAMEBUFEXTRA 12 +#define CDSECTOR 2352 +#define MAXCACHEBLOCK 26 +#define MAXCDBUFFER (((MAXCACHEBLOCK+1)*(CDSECTOR+16))+240) + +///////////////////////////////////////////////////////// + +/* some structs from libcdvd by Hiryu & Sjeep (C) 2002 */ + +#pragma pack(1) + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +}; //+22 + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +}; + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +}; + +#pragma pack() + + diff --git a/plugins/cdvd/CDVDpeops/defines.h.bak b/plugins/cdvd/CDVDpeops/defines.h.bak new file mode 100644 index 0000000..7926e94 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/defines.h.bak @@ -0,0 +1,213 @@ +/*************************************************************************** + defines.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +// general buffer for reading several frames + +#pragma pack(1) + +typedef struct _FRAMEBUF +{ + DWORD dwFrame; + DWORD dwFrameCnt; + DWORD dwBufLen; + unsigned char BufData[1024*1024]; +} FRAMEBUF; + +#pragma pack() + +// raw ioctl structs: + +typedef enum _TRACK_MODE_TYPE +{ + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct _RAW_READ_INFO +{ + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +// sub cache: + +typedef struct +{ + long addr; + void * pNext; + unsigned char subq[10]; +} SUB_DATA; + +typedef struct +{ + long addr; + void * pNext; +} SUB_CACHE; + +// ppf cache: + +typedef struct +{ + long addr; + void * pNext; + long pos; + long anz; + // memdata +} PPF_DATA; + +typedef struct +{ + long addr; + void * pNext; +} PPF_CACHE; + +///////////////////////////////////////////////////////// + +#define MODE_BE_1 1 +#define MODE_BE_2 2 +#define MODE_28_1 3 +#define MODE_28_2 4 +#define MODE_28_2048 5 +#define MODE_28_2048_Ex 6 + +u8 __inline itob(u32 i); + +#define btoi(b) ((b)/16*10 + (b)%16) +#define itod(i) ((((i)/10)<<4) + ((i)%10)) +#define dtoi(b) ((((b)>>4)&0xf)*10 + (((b)&0xf)%10)) + +///////////////////////////////////////////////////////// + +void addr2time(unsigned long addr, unsigned char *time); +void addr2timeB(unsigned long addr, unsigned char *time); +unsigned long time2addr(unsigned char *time); +unsigned long time2addrB(unsigned char *time); +#ifdef _GCC +#define reOrder i386_reOrder +#endif +unsigned long reOrder(unsigned long value); + +///////////////////////////////////////////////////////// +// debug helper + +#ifndef _IN_CDR +#ifdef DBGOUT +void auxprintf (LPCTSTR pFormat, ...); +#endif +#endif + +///////////////////////////////////////////////////////// + +typedef DWORD (*READFUNC)(BOOL bWait,FRAMEBUF * f); +typedef DWORD (*DEINITFUNC)(void); +typedef BOOL (*READTRACKFUNC)(unsigned long addr); +typedef void (*GETPTRFUNC)(void); + +///////////////////////////////////////////////////////// + +#define WAITFOREVER 0xFFFFFFFF +#define WAITSUB 10000 +#define FRAMEBUFEXTRA 12 +#define CDSECTOR 2352 +#define MAXCACHEBLOCK 26 +#define MAXCDBUFFER (((MAXCACHEBLOCK+1)*(CDSECTOR+16))+240) + +///////////////////////////////////////////////////////// + +/* some structs from libcdvd by Hiryu & Sjeep (C) 2002 */ + +#pragma pack(1) + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +}; //+22 + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +}; + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +}; + +#pragma pack() + + diff --git a/plugins/cdvd/CDVDpeops/externals.h b/plugins/cdvd/CDVDpeops/externals.h new file mode 100644 index 0000000..95d8d3c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/externals.h @@ -0,0 +1,177 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#ifndef _IN_CDDA + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_CDR + +extern BOOL bIsOpen; +extern BOOL bCDDAPlay; +extern int iCDROK; +extern char *libraryName; +extern int iCheckTrayStatus; +extern void *fdump; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_PEOPS + +extern HINSTANCE hInst; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_CFG + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_GENERIC + +extern int iCD_AD; +extern int iCD_TA; +extern int iCD_LU; +extern int iRType; +extern int iUseSpeedLimit; +extern int iSpeedLimit; +extern int iNoWait; +extern int iMaxRetry; +extern int iShowReadErr; +extern HANDLE hEvent; +extern HINSTANCE hASPI; +extern READFUNC pReadFunc; +extern DEINITFUNC pDeInitFunc; +extern int iInterfaceMode; +extern int iWantedBlockSize; +extern int iUsedBlockSize; +extern int iUsedMode; +extern int iBlockDump; + +extern DWORD (*pGetASPI32SupportInfo)(void); +extern DWORD (*pSendASPI32Command)(LPSRB); + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_IOCTL + +extern HANDLE hIOCTL; +extern DWORD dwIOCTLAttr; +extern OVERLAPPED ovcIOCTL; +extern SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptIOCTL; +extern RAW_READ_INFO rawIOCTL; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_PPF + +extern int iUsePPF; +extern char szPPF[]; +extern PPF_CACHE * ppfCache; +extern PPF_DATA * ppfHead; +extern int iPPFNum; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_READ + +extern READTRACKFUNC pReadTrackFunc; +extern GETPTRFUNC pGetPtrFunc; + +extern int iUseCaching; +extern int iUseDataCache; +extern int iTryAsync; +extern int iBufSel; + +extern unsigned char * pMainBuffer; +extern unsigned char * pCurrReadBuf; +extern unsigned char * pFirstReadBuf; +extern unsigned char * pAsyncBuffer; + +extern unsigned long lMaxAddr; +extern unsigned long lLastAddr; +extern unsigned long lLastAsyncAddr; + +extern unsigned char * ptrBuffer[]; +extern unsigned char * pAsyncFirstReadBuf[]; +extern unsigned long lLastAccessedAddr; +extern int iLastAccessedMode; + +extern HANDLE hReadThread; +extern BOOL bThreadEnded; +extern HANDLE hThreadEvent[]; +extern HANDLE hThreadMutex[]; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_SCSI + +extern SRB_ExecSCSICmd sx; +extern BOOL bDoWaiting; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_SUB + +extern unsigned char * pCurrSubBuf; +extern int iUseSubReading; +extern char szSUBF[]; +extern SUB_CACHE * subCache; +extern SUB_DATA * subHead; +extern int iSUBNum; +extern unsigned char SubCData[]; +extern unsigned char SubAData[]; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_TOC + +extern TOC sTOC; + +#endif + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/externals.h.bak b/plugins/cdvd/CDVDpeops/externals.h.bak new file mode 100644 index 0000000..c0ffb37 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/externals.h.bak @@ -0,0 +1,175 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#ifndef _IN_CDDA + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_CDR + +extern BOOL bIsOpen; +extern BOOL bCDDAPlay; +extern int iCDROK; +extern char *libraryName; +extern int iCheckTrayStatus; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_PEOPS + +extern HINSTANCE hInst; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_CFG + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_GENERIC + +extern int iCD_AD; +extern int iCD_TA; +extern int iCD_LU; +extern int iRType; +extern int iUseSpeedLimit; +extern int iSpeedLimit; +extern int iNoWait; +extern int iMaxRetry; +extern int iShowReadErr; +extern HANDLE hEvent; +extern HINSTANCE hASPI; +extern READFUNC pReadFunc; +extern DEINITFUNC pDeInitFunc; +extern int iInterfaceMode; +extern int iWantedBlockSize; +extern int iUsedBlockSize; +extern int iUsedMode; + +extern DWORD (*pGetASPI32SupportInfo)(void); +extern DWORD (*pSendASPI32Command)(LPSRB); + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_IOCTL + +extern HANDLE hIOCTL; +extern DWORD dwIOCTLAttr; +extern OVERLAPPED ovcIOCTL; +extern SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptIOCTL; +extern RAW_READ_INFO rawIOCTL; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_PPF + +extern int iUsePPF; +extern char szPPF[]; +extern PPF_CACHE * ppfCache; +extern PPF_DATA * ppfHead; +extern int iPPFNum; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_READ + +extern READTRACKFUNC pReadTrackFunc; +extern GETPTRFUNC pGetPtrFunc; + +extern int iUseCaching; +extern int iUseDataCache; +extern int iTryAsync; +extern int iBufSel; + +extern unsigned char * pMainBuffer; +extern unsigned char * pCurrReadBuf; +extern unsigned char * pFirstReadBuf; +extern unsigned char * pAsyncBuffer; + +extern unsigned long lMaxAddr; +extern unsigned long lLastAddr; +extern unsigned long lLastAsyncAddr; + +extern unsigned char * ptrBuffer[]; +extern unsigned char * pAsyncFirstReadBuf[]; +extern unsigned long lLastAccessedAddr; +extern int iLastAccessedMode; + +extern HANDLE hReadThread; +extern BOOL bThreadEnded; +extern HANDLE hThreadEvent[]; +extern HANDLE hThreadMutex[]; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_SCSI + +extern SRB_ExecSCSICmd sx; +extern BOOL bDoWaiting; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_SUB + +extern unsigned char * pCurrSubBuf; +extern int iUseSubReading; +extern char szSUBF[]; +extern SUB_CACHE * subCache; +extern SUB_DATA * subHead; +extern int iSUBNum; +extern unsigned char SubCData[]; +extern unsigned char SubAData[]; + +#endif + +///////////////////////////////////////////////////////// + +#ifndef _IN_TOC + +extern TOC sTOC; + +#endif + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/filemap.txt b/plugins/cdvd/CDVDpeops/filemap.txt new file mode 100644 index 0000000..e111546 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/filemap.txt @@ -0,0 +1,52 @@ +######################################################################### + +- cdr.c / cdr.h + main plugin interface funcs + +- cdda.c / cdda.h + audio playing funcs + +- cfg.c / cfg.h + configuration dialogs/file reading funcs + +- cdvdPeops.* + Windows dll related files (including msvc/devc++ project files) + +- generic.c / generic.h + generic stuff + +- ioctrl.c / ioctrl.h + w2k/xp ioctl functions + +- ppf.c / ppf.h + ppf caching funcs + +- read.c / read.h + the different read caching modes + +- scsi.c / scsi.h + all the used scsi commands + +- stdafx.h + main include file + +- sub.c / sub.h + sub data caching + +- toc.c / toc.h + toc related funcs + +- externals.h + generic defines/external vars + +- defines.h + typedef structs/defines/inline funcs + +- resource.h + Windows resource header + +- i386.asm + NASM funcs + +######################################################################### + diff --git a/plugins/cdvd/CDVDpeops/generic.c b/plugins/cdvd/CDVDpeops/generic.c new file mode 100644 index 0000000..8193679 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/generic.c @@ -0,0 +1,378 @@ +/*************************************************************************** + generic.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/25 - Pete +// - repaired time2addr/addr2time +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_GENERIC +#include "externals.h" + +///////////////////////////////////////////////////////// + +int iCD_AD=-1; // drive address +int iCD_TA=-1; +int iCD_LU=-1; +int iRType=0; // read mode +int iUseSpeedLimit=0; // speed limit use +int iSpeedLimit=2; // speed 2x +int iNoWait=0; // wait +int iMaxRetry=5; // retry on error +int iShowReadErr=0; // show msg on error +HANDLE hEvent=NULL; // global event +HINSTANCE hASPI=NULL; // aspi lib +READFUNC pReadFunc=NULL; // read func +DEINITFUNC pDeInitFunc=NULL; // deinit func +int iInterfaceMode=1; // interface (aspi/ioctrlscsi/ioctrlraw) +int iWantedBlockSize=2352; +int iUsedBlockSize=2352; +int iUsedMode=CDVD_MODE_2352; +int iBlockDump=0; + +DWORD (*pGetASPI32SupportInfo)(void); // ptrs to aspi funcs +DWORD (*pSendASPI32Command)(LPSRB); + +///////////////////////////////////////////////////////// + +void addr2time(unsigned long addr, unsigned char *time) +{ + addr+=150; + time[3] = (unsigned char)(addr%75); + addr/=75; + time[2]=(unsigned char)(addr%60); + addr/=60; + time[1]=(unsigned char)(addr%100); + time[0]=(unsigned char)(addr/100); +} + +void addr2timeB(unsigned long addr, unsigned char *time) +{ + time[3] = itob((unsigned char)(addr%75)); + addr/=75; + time[2]=itob((unsigned char)(addr%60)); + addr/=60; + time[1]=itob((unsigned char)(addr%100)); + time[0]=itob((unsigned char)(addr/100)); +} + +unsigned long time2addr(unsigned char *time) +{ + unsigned long addr; + + addr = time[0]*100; + addr += time[1]; + addr *= 60; + + addr = (addr + time[2])*75; + addr += time[3]; + addr -= 150; + return addr; +} + +unsigned long time2addrB(unsigned char *time) +{ + unsigned long addr; + + addr = (btoi(time[0]))*100; + addr += btoi(time[1]); + addr *= 60; + addr = (addr + btoi(time[2]))*75; + addr += btoi(time[3]); + addr -= 150; + return addr; +} + +#ifndef _GCC +unsigned long reOrder(unsigned long value) +{ +#pragma warning (disable: 4035) + __asm + { + mov eax,value + bswap eax + } +} +#endif + +///////////////////////////////////////////////////////// + +void CreateGenEvent(void) +{ + hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); +} + +///////////////////////////////////////////////////////// + +void FreeGenEvent(void) +{ + if(hEvent) CloseHandle(hEvent); + hEvent=0; +} + +///////////////////////////////////////////////////////// + +DWORD WaitGenEvent(DWORD dwMS) +{ + if(hASPI) // aspi event + return WaitForSingleObject(hEvent,dwMS); + else + { // ioctl overlapped (always waiting til finished, dwMS not used) + DWORD dwR=0; + GetOverlappedResult(hIOCTL,&ovcIOCTL,&dwR,TRUE); + return 0; + } +} + +///////////////////////////////////////////////////////// + +void LockGenCDAccess(void) +{ + if(hReadThread) // thread mode? + WaitForSingleObject(hThreadMutex[0],INFINITE); // -> wait until all reading is done + else // async prefetch? + if(bDoWaiting) // -> async operation has to finish first + {WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;} +} + +///////////////////////////////////////////////////////// + +void UnlockGenCDAccess(void) +{ + if(hReadThread) // thread mode? + ReleaseMutex(hThreadMutex[0]); // -> we are finished with our special command, now reading can go on +} + +///////////////////////////////////////////////////////// + +void WaitUntilDriveIsReady(void) +{ + if(iNoWait==0) + { + while(TestSCSIUnitReady()==0) Sleep(500); + } +} + +///////////////////////////////////////////////////////// + +void SetGenCDSpeed(int iReset) +{ + if(iUseSpeedLimit) + { + if(bDoWaiting) // still a command running? wait + {WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;} + + if(iReset) SetSCSISpeed(0xFFFF); + else + if(SetSCSISpeed(176*iSpeedLimit)<=0) + { + MessageBox(GetActiveWindow(), + "Failure: cannot change the drive speed!", + "cdvdPeops... speed limitation", + MB_OK|MB_ICONEXCLAMATION); + iUseSpeedLimit=0; + } + } +} + +///////////////////////////////////////////////////////// +// checks, which direct subchannel reading type is supported + +void GetBESubReadFunc(void) +{ + unsigned char * pB=(unsigned char *)malloc(4096); + + pReadFunc = ReadSCSI_BE_Sub; // pre-init read func + + WaitUntilDriveIsReady(); // wait before first read + + ReadSub_BE_2(0,pB,1); // first (unchecked) read + if(!ReadSub_BE_2(0,pB,1)) // read again, and check this time + { // -> read failed? + if(ReadSub_BE_2_1(0,pB,1)) // -> try different sub reading + { // --> success? mmm... let us check the data + DecodeSub_BE_2_1(pB+2352); // --> decode sub + if(*(pB+2352)==0x41) // --> check the first decoded byte + pReadFunc = ReadSCSI_BE_Sub_1; // ---> wow, byte is ok + } + } + free(pB); +} + +///////////////////////////////////////////////////////// + +int GetGenReadFunc(int iRM) +{ + switch(iRM) // scsi read mode + { + // ------------------------------------------------ // + case MODE_BE_1: + case MODE_BE_2: + { + if(iUseSubReading==1) + GetBESubReadFunc(); + else pReadFunc = ReadSCSI_BE; + } break; + // ------------------------------------------------ // + case MODE_28_1: + case MODE_28_2: + { + if(iUseSubReading==1) + pReadFunc = ReadSCSI_28_Sub; + else pReadFunc = ReadSCSI_28; + } break; + // ------------------------------------------------ // + case MODE_28_2048: + { + pReadFunc = ReadSCSI_28_2048; + } break; + // ------------------------------------------------ // + case MODE_28_2048_Ex: + { + pReadFunc = ReadSCSI_28_2048_Ex; + } break; + // ------------------------------------------------ // + default: + { + pReadFunc = ReadSCSI_Dummy; + } return -3; + // ------------------------------------------------ // + } + return 1; +} + +///////////////////////////////////////////////////////// + +int OpenGenCD(int iA,int iT,int iL) +{ + pDeInitFunc = NULL; // init de-init func + pReadFunc = ReadSCSI_Dummy; // init (dummy) read func + + if(iA==-1) return -1; // not configured properly + + // -------------------------------------------------- // + + if(iInterfaceMode>1) // ioctrl interfaces? + { + OpenIOCTLHandle(iA,iT,iL); // open w2k/xp ioctrl device + if(hIOCTL==NULL) return -2; // no cdrom available + + if(iInterfaceMode==3) // special ioctl RAW mode? + { // -> get special reading funcs (non-scsi!) + if(iUseSubReading==1) + pReadFunc = ReadIOCTL_Raw_Sub; + else pReadFunc = ReadIOCTL_Raw; + + WaitUntilDriveIsReady(); + return 1; + } + } + else // aspi interface? + { + int iDevice=GetSCSIDevice(iA,iT,iL); // get device type + if(iDevice!=DTYPE_CDROM) return -2; // no cdrom? bye + } + + if(CheckSCSIReadMode()==SS_COMP) + WaitUntilDriveIsReady(); + else + { + CloseIOCTLHandle(); + return -3; + } + + return 1; +} + +///////////////////////////////////////////////////////// + +void CloseGenCD(void) +{ + iCDROK=0; // no more cd available + if(pDeInitFunc) pDeInitFunc(); // deinit, if needed + pDeInitFunc = NULL; + pReadFunc = ReadSCSI_Dummy; + CloseIOCTLHandle(); // close ioctl drive file (if used) +} + +///////////////////////////////////////////////////////// + +void OpenGenInterface(void) +{ + hASPI=NULL; + + if(iInterfaceMode==0) return; // no interface? no fun + else + if(iInterfaceMode==1) // aspi + { + hASPI=LoadLibrary("WNASPI32.DLL"); + if(hASPI) + { + pGetASPI32SupportInfo = + (DWORD(*)(void)) GetProcAddress(hASPI,"GetASPI32SupportInfo"); + pSendASPI32Command = + (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command"); + + if(!pGetASPI32SupportInfo || !pSendASPI32Command) + { + iInterfaceMode=0; + return; + } + } + } + else // ioctl + { + if(iInterfaceMode<2 || iInterfaceMode>3) iInterfaceMode=2; + pGetASPI32SupportInfo = NULL; + pSendASPI32Command = IOCTLSendASPI32Command; + } +} + +///////////////////////////////////////////////////////// + +void CloseGenInterface(void) +{ + pGetASPI32SupportInfo=NULL; // clear funcs + pSendASPI32Command=NULL; + + if(hASPI) // free aspi + { + FreeLibrary(hASPI); + hASPI=NULL; + } + else CloseIOCTLHandle(); // or close ioctl file +} + +///////////////////////////////////////////////////////// + +int GetGenCDDrives(char * pDList) +{ + if(hASPI) return GetSCSICDDrives(pDList); // aspi? use it + return GetIOCTLCDDrives(pDList); // or use ioctl +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/generic.c.bak b/plugins/cdvd/CDVDpeops/generic.c.bak new file mode 100644 index 0000000..30cf7eb --- /dev/null +++ b/plugins/cdvd/CDVDpeops/generic.c.bak @@ -0,0 +1,377 @@ +/*************************************************************************** + generic.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/25 - Pete +// - repaired time2addr/addr2time +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_GENERIC +#include "externals.h" + +///////////////////////////////////////////////////////// + +int iCD_AD=-1; // drive address +int iCD_TA=-1; +int iCD_LU=-1; +int iRType=0; // read mode +int iUseSpeedLimit=0; // speed limit use +int iSpeedLimit=2; // speed 2x +int iNoWait=0; // wait +int iMaxRetry=5; // retry on error +int iShowReadErr=0; // show msg on error +HANDLE hEvent=NULL; // global event +HINSTANCE hASPI=NULL; // aspi lib +READFUNC pReadFunc=NULL; // read func +DEINITFUNC pDeInitFunc=NULL; // deinit func +int iInterfaceMode=1; // interface (aspi/ioctrlscsi/ioctrlraw) +int iWantedBlockSize=2352; +int iUsedBlockSize=2352; +int iUsedMode=CDVD_MODE_2352; + +DWORD (*pGetASPI32SupportInfo)(void); // ptrs to aspi funcs +DWORD (*pSendASPI32Command)(LPSRB); + +///////////////////////////////////////////////////////// + +void addr2time(unsigned long addr, unsigned char *time) +{ + addr+=150; + time[3] = (unsigned char)(addr%75); + addr/=75; + time[2]=(unsigned char)(addr%60); + addr/=60; + time[1]=(unsigned char)(addr%100); + time[0]=(unsigned char)(addr/100); +} + +void addr2timeB(unsigned long addr, unsigned char *time) +{ + time[3] = itob((unsigned char)(addr%75)); + addr/=75; + time[2]=itob((unsigned char)(addr%60)); + addr/=60; + time[1]=itob((unsigned char)(addr%100)); + time[0]=itob((unsigned char)(addr/100)); +} + +unsigned long time2addr(unsigned char *time) +{ + unsigned long addr; + + addr = time[0]*100; + addr += time[1]; + addr *= 60; + + addr = (addr + time[2])*75; + addr += time[3]; + addr -= 150; + return addr; +} + +unsigned long time2addrB(unsigned char *time) +{ + unsigned long addr; + + addr = (btoi(time[0]))*100; + addr += btoi(time[1]); + addr *= 60; + addr = (addr + btoi(time[2]))*75; + addr += btoi(time[3]); + addr -= 150; + return addr; +} + +#ifndef _GCC +unsigned long reOrder(unsigned long value) +{ +#pragma warning (disable: 4035) + __asm + { + mov eax,value + bswap eax + } +} +#endif + +///////////////////////////////////////////////////////// + +void CreateGenEvent(void) +{ + hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); +} + +///////////////////////////////////////////////////////// + +void FreeGenEvent(void) +{ + if(hEvent) CloseHandle(hEvent); + hEvent=0; +} + +///////////////////////////////////////////////////////// + +DWORD WaitGenEvent(DWORD dwMS) +{ + if(hASPI) // aspi event + return WaitForSingleObject(hEvent,dwMS); + else + { // ioctl overlapped (always waiting til finished, dwMS not used) + DWORD dwR=0; + GetOverlappedResult(hIOCTL,&ovcIOCTL,&dwR,TRUE); + return 0; + } +} + +///////////////////////////////////////////////////////// + +void LockGenCDAccess(void) +{ + if(hReadThread) // thread mode? + WaitForSingleObject(hThreadMutex[0],INFINITE); // -> wait until all reading is done + else // async prefetch? + if(bDoWaiting) // -> async operation has to finish first + {WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;} +} + +///////////////////////////////////////////////////////// + +void UnlockGenCDAccess(void) +{ + if(hReadThread) // thread mode? + ReleaseMutex(hThreadMutex[0]); // -> we are finished with our special command, now reading can go on +} + +///////////////////////////////////////////////////////// + +void WaitUntilDriveIsReady(void) +{ + if(iNoWait==0) + { + while(TestSCSIUnitReady()==0) Sleep(500); + } +} + +///////////////////////////////////////////////////////// + +void SetGenCDSpeed(int iReset) +{ + if(iUseSpeedLimit) + { + if(bDoWaiting) // still a command running? wait + {WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE;} + + if(iReset) SetSCSISpeed(0xFFFF); + else + if(SetSCSISpeed(176*iSpeedLimit)<=0) + { + MessageBox(GetActiveWindow(), + "Failure: cannot change the drive speed!", + "cdvdPeops... speed limitation", + MB_OK|MB_ICONEXCLAMATION); + iUseSpeedLimit=0; + } + } +} + +///////////////////////////////////////////////////////// +// checks, which direct subchannel reading type is supported + +void GetBESubReadFunc(void) +{ + unsigned char * pB=(unsigned char *)malloc(4096); + + pReadFunc = ReadSCSI_BE_Sub; // pre-init read func + + WaitUntilDriveIsReady(); // wait before first read + + ReadSub_BE_2(0,pB,1); // first (unchecked) read + if(!ReadSub_BE_2(0,pB,1)) // read again, and check this time + { // -> read failed? + if(ReadSub_BE_2_1(0,pB,1)) // -> try different sub reading + { // --> success? mmm... let us check the data + DecodeSub_BE_2_1(pB+2352); // --> decode sub + if(*(pB+2352)==0x41) // --> check the first decoded byte + pReadFunc = ReadSCSI_BE_Sub_1; // ---> wow, byte is ok + } + } + free(pB); +} + +///////////////////////////////////////////////////////// + +int GetGenReadFunc(int iRM) +{ + switch(iRM) // scsi read mode + { + // ------------------------------------------------ // + case MODE_BE_1: + case MODE_BE_2: + { + if(iUseSubReading==1) + GetBESubReadFunc(); + else pReadFunc = ReadSCSI_BE; + } break; + // ------------------------------------------------ // + case MODE_28_1: + case MODE_28_2: + { + if(iUseSubReading==1) + pReadFunc = ReadSCSI_28_Sub; + else pReadFunc = ReadSCSI_28; + } break; + // ------------------------------------------------ // + case MODE_28_2048: + { + pReadFunc = ReadSCSI_28_2048; + } break; + // ------------------------------------------------ // + case MODE_28_2048_Ex: + { + pReadFunc = ReadSCSI_28_2048_Ex; + } break; + // ------------------------------------------------ // + default: + { + pReadFunc = ReadSCSI_Dummy; + } return -3; + // ------------------------------------------------ // + } + return 1; +} + +///////////////////////////////////////////////////////// + +int OpenGenCD(int iA,int iT,int iL) +{ + pDeInitFunc = NULL; // init de-init func + pReadFunc = ReadSCSI_Dummy; // init (dummy) read func + + if(iA==-1) return -1; // not configured properly + + // -------------------------------------------------- // + + if(iInterfaceMode>1) // ioctrl interfaces? + { + OpenIOCTLHandle(iA,iT,iL); // open w2k/xp ioctrl device + if(hIOCTL==NULL) return -2; // no cdrom available + + if(iInterfaceMode==3) // special ioctl RAW mode? + { // -> get special reading funcs (non-scsi!) + if(iUseSubReading==1) + pReadFunc = ReadIOCTL_Raw_Sub; + else pReadFunc = ReadIOCTL_Raw; + + WaitUntilDriveIsReady(); + return 1; + } + } + else // aspi interface? + { + int iDevice=GetSCSIDevice(iA,iT,iL); // get device type + if(iDevice!=DTYPE_CDROM) return -2; // no cdrom? bye + } + + if(CheckSCSIReadMode()==SS_COMP) + WaitUntilDriveIsReady(); + else + { + CloseIOCTLHandle(); + return -3; + } + + return 1; +} + +///////////////////////////////////////////////////////// + +void CloseGenCD(void) +{ + iCDROK=0; // no more cd available + if(pDeInitFunc) pDeInitFunc(); // deinit, if needed + pDeInitFunc = NULL; + pReadFunc = ReadSCSI_Dummy; + CloseIOCTLHandle(); // close ioctl drive file (if used) +} + +///////////////////////////////////////////////////////// + +void OpenGenInterface(void) +{ + hASPI=NULL; + + if(iInterfaceMode==0) return; // no interface? no fun + else + if(iInterfaceMode==1) // aspi + { + hASPI=LoadLibrary("WNASPI32.DLL"); + if(hASPI) + { + pGetASPI32SupportInfo = + (DWORD(*)(void)) GetProcAddress(hASPI,"GetASPI32SupportInfo"); + pSendASPI32Command = + (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command"); + + if(!pGetASPI32SupportInfo || !pSendASPI32Command) + { + iInterfaceMode=0; + return; + } + } + } + else // ioctl + { + if(iInterfaceMode<2 || iInterfaceMode>3) iInterfaceMode=2; + pGetASPI32SupportInfo = NULL; + pSendASPI32Command = IOCTLSendASPI32Command; + } +} + +///////////////////////////////////////////////////////// + +void CloseGenInterface(void) +{ + pGetASPI32SupportInfo=NULL; // clear funcs + pSendASPI32Command=NULL; + + if(hASPI) // free aspi + { + FreeLibrary(hASPI); + hASPI=NULL; + } + else CloseIOCTLHandle(); // or close ioctl file +} + +///////////////////////////////////////////////////////// + +int GetGenCDDrives(char * pDList) +{ + if(hASPI) return GetSCSICDDrives(pDList); // aspi? use it + return GetIOCTLCDDrives(pDList); // or use ioctl +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/generic.h b/plugins/cdvd/CDVDpeops/generic.h new file mode 100644 index 0000000..0313e50 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/generic.h @@ -0,0 +1,41 @@ +/*************************************************************************** + generic.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void CreateGenEvent(void); +void FreeGenEvent(void); +DWORD WaitGenEvent(DWORD dwMS); +void LockGenCDAccess(void); +void UnlockGenCDAccess(void); +void WaitUntilDriveIsReady(void); +void SetGenCDSpeed(int iReset); +void GetBESubReadFunc(void); +int GetGenReadFunc(int iRM); +int OpenGenCD(int iA,int iT,int iL); +void CloseGenCD(void); +void OpenGenInterface(void); +void CloseGenInterface(void); +int GetGenCDDrives(char * pDList); + diff --git a/plugins/cdvd/CDVDpeops/i386.asm b/plugins/cdvd/CDVDpeops/i386.asm new file mode 100644 index 0000000..e6f11ac --- /dev/null +++ b/plugins/cdvd/CDVDpeops/i386.asm @@ -0,0 +1,32 @@ +; i386.asm - description +; ------------------- +; begin : Sun Nov 08 2001 +; copyright : (C) 2001 by Pete Bernert +; email : BlackDove@addcom.de + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +bits 32 + +section .text + +%include "macros.inc" + +;----------------------------------------------------------------- +NEWSYM i386_reOrder + push ebp + mov ebp, esp + + mov eax, [ebp+8] + bswap eax + + mov esp, ebp + pop ebp + ret + + diff --git a/plugins/cdvd/CDVDpeops/ioctrl.h b/plugins/cdvd/CDVDpeops/ioctrl.h new file mode 100644 index 0000000..f105c96 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/ioctrl.h @@ -0,0 +1,35 @@ +/*************************************************************************** + ioctrl.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void OpenIOCTLHandle(int iA,int iT,int iL); +void CloseIOCTLHandle(void); +char MapIOCTLDriveLetter(int iA,int iT,int iL); +int GetIOCTLCDDrives(char * pDList); +HANDLE OpenIOCTLFile(char cLetter,BOOL bAsync); +void GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL); +DWORD IOCTLSendASPI32Command(LPSRB pSrb); +DWORD ReadIOCTL_Raw(BOOL bWait,FRAMEBUF * f); +DWORD ReadIOCTL_Raw_Sub(BOOL bWait,FRAMEBUF * f); diff --git a/plugins/cdvd/CDVDpeops/libiso.c b/plugins/cdvd/CDVDpeops/libiso.c new file mode 100644 index 0000000..ba681e2 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/libiso.c @@ -0,0 +1,733 @@ +#include +#include +#include +#include +#include +#include +//#include + +#define __MSCW32__ +#define __WIN32__ +#ifdef __WIN32__ +#include +#endif + +#include "PS2Etypes.h" +//#include "CDVDiso.h" +#include "libiso.h" + +/* some structs from libcdvd by Hiryu & Sjeep (C) 2002 */ + +#if defined(__WIN32__) +#pragma pack(1) +#endif + +struct rootDirTocHeader +{ + u16 length; //+00 + u32 tocLBA; //+02 + u32 tocLBA_bigend; //+06 + u32 tocSize; //+0A + u32 tocSize_bigend; //+0E + u8 dateStamp[8]; //+12 + u8 reserved[6]; //+1A + u8 reserved2; //+20 + u8 reserved3; //+21 +#if defined(__WIN32__) +}; //+22 +#else +} __attribute__((packed)); +#endif + +struct asciiDate +{ + char year[4]; + char month[2]; + char day[2]; + char hours[2]; + char minutes[2]; + char seconds[2]; + char hundreths[2]; + char terminator[1]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + +struct cdVolDesc +{ + u8 filesystemType; // 0x01 = ISO9660, 0x02 = Joliet, 0xFF = NULL + u8 volID[5]; // "CD001" + u8 reserved2; + u8 reserved3; + u8 sysIdName[32]; + u8 volName[32]; // The ISO9660 Volume Name + u8 reserved5[8]; + u32 volSize; // Volume Size + u32 volSizeBig; // Volume Size Big-Endian + u8 reserved6[32]; + u32 unknown1; + u32 unknown1_bigend; + u16 volDescSize; //+80 + u16 volDescSize_bigend; //+82 + u32 unknown3; //+84 + u32 unknown3_bigend; //+88 + u32 priDirTableLBA; // LBA of Primary Dir Table //+8C + u32 reserved7; //+90 + u32 secDirTableLBA; // LBA of Secondary Dir Table //+94 + u32 reserved8; //+98 + struct rootDirTocHeader rootToc; + u8 volSetName[128]; + u8 publisherName[128]; + u8 preparerName[128]; + u8 applicationName[128]; + u8 copyrightFileName[37]; + u8 abstractFileName[37]; + u8 bibliographyFileName[37]; + struct asciiDate creationDate; + struct asciiDate modificationDate; + struct asciiDate effectiveDate; + struct asciiDate expirationDate; + u8 reserved10; + u8 reserved11[1166]; +#if defined(__WIN32__) +}; +#else +} __attribute__((packed)); +#endif + + +#ifdef __WIN32__ +void *_openfile(const char *filename, int flags) { + HANDLE handle; + +// printf("_openfile %s, %d\n", filename, flags & O_RDONLY); + if (flags & O_WRONLY) { + int _flags = CREATE_NEW; + if (flags & O_CREAT) _flags = CREATE_ALWAYS; + handle = CreateFile(filename, GENERIC_WRITE, 0, NULL, _flags, 0, NULL); + } else { + handle = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + } + + return handle == INVALID_HANDLE_VALUE ? NULL : handle; +} + +u64 _tellfile(void *handle) { + u64 ofs; + DWORD *_ofs = (DWORD*)&ofs; + _ofs[1] = 0; + _ofs[0] = SetFilePointer(handle, 0, &_ofs[1], FILE_CURRENT); + return ofs; +} + +int _seekfile(void *handle, u64 offset, int whence) { + u64 ofs = (u64)offset; + DWORD *_ofs = (DWORD*)&ofs; +// printf("_seekfile %p, %d_%d\n", handle, _ofs[1], _ofs[0]); + if (whence == SEEK_SET) { + SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_BEGIN); + } else { + SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_END); + } + return 0; +} + +int _readfile(void *handle, void *dst, int size) { + DWORD ret; + +// printf("_readfile %p %d\n", handle, size); + ReadFile(handle, dst, size, &ret, NULL); +// printf("_readfile ret %d; %d\n", ret, GetLastError()); + return ret; +} + +int _writefile(void *handle, void *src, int size) { + DWORD ret; + +// printf("_writefile %p, %d\n", handle, size); +// _seekfile(handle, _tellfile(handle)); + WriteFile(handle, src, size, &ret, NULL); +// printf("_writefile ret %d\n", ret); + return ret; +} + +void _closefile(void *handle) { + CloseHandle(handle); +} + +#else + +void *_openfile(const char *filename, int flags) { + printf("_openfile %s %x\n", filename, flags); + if (flags & O_WRONLY) + return fopen(filename, "wb"); + else return fopen(filename, "rb"); +} + +u64 _tellfile(void *handle) { + return ftell(handle); +} + +int _seekfile(void *handle, u64 offset, int whence) { + return fseek(handle, offset, whence); +} + +int _readfile(void *handle, void *dst, int size) { + return fread(dst, 1, size, handle); +} + +int _writefile(void *handle, void *src, int size) { + return fwrite(src, 1, size, handle); +} + +void _closefile(void *handle) { + fclose(handle); +} + +#endif + +int detect(isoFile *iso) { + char buf[2448]; + struct cdVolDesc *volDesc; + + if (isoReadBlock(iso, buf, 16) == -1) return -1; + volDesc = (struct cdVolDesc *)(buf + 24); + if (strncmp(volDesc->volID, "CD001", 5)) return 0; + + if (volDesc->rootToc.tocSize == 2048) { + iso->type = ISOTYPE_CD; + } else { + iso->type = ISOTYPE_DVD; + } + + return 1; +} + +int _isoReadZtable(isoFile *iso) { + void *handle; + char table[256]; + int size; + + sprintf(table, "%s.table", iso->filename); + handle = _openfile(table, O_RDONLY); + if (handle == NULL) { + printf("Error loading %s\n", table); + return -1; + } + + _seekfile(handle, 0, SEEK_END); + size = (int)_tellfile(handle); + iso->Ztable = (char*)malloc(size); + if (iso->Ztable == NULL) { + return -1; + } + + _seekfile(handle, 0, SEEK_SET); + _readfile(handle, iso->Ztable, size); + _closefile(handle); + + iso->blocks = size / 6; + + return 0; +} + +int _isoReadZ2table(isoFile *iso) { + void *handle; + char table[256]; + u32 *Ztable; + int ofs; + int size; + int i; + + sprintf(table, "%s.table", iso->filename); + handle = _openfile(table, O_RDONLY); + if (handle == NULL) { + printf("Error loading %s\n", table); + return -1; + } + + _seekfile(handle, 0, SEEK_END); + size = (int)_tellfile(handle); + Ztable = (u32*)malloc(size); + if (Ztable == NULL) { + return -1; + } + + _seekfile(handle, 0, SEEK_SET); + _readfile(handle, Ztable, size); + _closefile(handle); + + iso->Ztable = (char*)malloc(iso->blocks*8); + if (iso->Ztable == NULL) { + return -1; + } + + ofs=16; + for (i=0; iblocks; i++) { + *(u32*)&iso->Ztable[i*8+0] = ofs; + *(u32*)&iso->Ztable[i*8+4] = Ztable[i]; + ofs+= Ztable[i]; + } + free(Ztable); + + return 0; +} + +int _isoReadDtable(isoFile *iso) { + int ret; + int i; + + _seekfile(iso->handle, 0, SEEK_END); + iso->dtablesize = (int)(_tellfile(iso->handle) - 16) / (iso->blocksize+4); + iso->dtable = (u32*)malloc(iso->dtablesize*4); + + for (i=0; idtablesize; i++) { + _seekfile(iso->handle, 16+(iso->blocksize+4)*i, SEEK_SET); + ret = _readfile(iso->handle, &iso->dtable[i], 4); + if (ret < 4) { + return -1; + } + } + + return 0; +} + +int isoDetect(isoFile *iso) { // based on florin's CDVDbin detection code :) + char buf[32]; + int len; + + iso->type = ISOTYPE_ILLEGAL; + + len = strlen(iso->filename); + if (len >= 2) { + if (!strncmp(iso->filename+(len-2), ".Z", 2)) { + iso->flags = ISOFLAGS_Z; + iso->blocksize = 2352; + _isoReadZtable(iso); + return detect(iso) == 1 ? 0 : -1; + } + } + + _seekfile(iso->handle, 0, SEEK_SET); + _readfile(iso->handle, buf, 4); + if (strncmp(buf, "BDV2", 4) == 0) { + iso->flags = ISOFLAGS_BLOCKDUMP; + _readfile(iso->handle, &iso->blocksize, 4); + _readfile(iso->handle, &iso->blocks, 4); + _readfile(iso->handle, &iso->blockofs, 4); + _isoReadDtable(iso); + return detect(iso) == 1 ? 0 : -1; + } else + if (strncmp(buf, "Z V2", 4) == 0) { + iso->flags = ISOFLAGS_Z2; + _readfile(iso->handle, &iso->blocksize, 4); + _readfile(iso->handle, &iso->blocks, 4); + _readfile(iso->handle, &iso->blockofs, 4); + _isoReadZ2table(iso); + return detect(iso) == 1 ? 0 : -1; + } else { + iso->blocks = 16; + } + + // ISO 2048 + iso->blocksize = 2048; iso->offset = 0; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // RAW 2336 + iso->blocksize = 2336; iso->offset = 0; iso->blockofs = 16; + if (detect(iso) == 1) return 0; + + // RAW 2352 + iso->blocksize = 2352; iso->offset = 0; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // RAWQ 2448 + iso->blocksize = 2448; iso->offset = 0; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // NERO ISO 2048 + iso->blocksize = 2048; iso->offset = 150*2048; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // NERO RAW 2352 + iso->blocksize = 2352; iso->offset = 150*2048; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // NERO RAWQ 2448 + iso->blocksize = 2448; iso->offset = 150*2048; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // ISO 2048 + iso->blocksize = 2048; iso->offset = -8; iso->blockofs = 24; + if (detect(iso) == 1) return 0; + + // RAW 2352 + iso->blocksize = 2352; iso->offset = -8; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + // RAWQ 2448 + iso->blocksize = 2448; iso->offset = -8; iso->blockofs = 0; + if (detect(iso) == 1) return 0; + + iso->offset = 0; + iso->blocksize = 2352; + iso->type = ISOTYPE_AUDIO; + return 0; + + return -1; +} + +isoFile *isoOpen(const char *filename) { + isoFile *iso; + + iso = (isoFile*)malloc(sizeof(isoFile)); + if (iso == NULL) return NULL; + + memset(iso, 0, sizeof(isoFile)); + strcpy(iso->filename, filename); + + iso->handle = _openfile(iso->filename, O_RDONLY); + if (iso->handle == NULL) { + printf("Error loading %s\n", iso->filename); + return NULL; + } + + if (isoDetect(iso) == -1) return NULL; + + if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BLOCKDUMP)) { + } else { + _seekfile(iso->handle, 0, SEEK_END); + iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / + (iso->blocksize)); + } +/* + if (strlen(IsoFile) > 3 && + !strncmp(IsoFile + (strlen(IsoFile) - 3), "I00", 3)) { + int i; + int llsn=0; + + for (i=0; i<8; i++) { + IsoFile[strlen(IsoFile) - 1] = '0' + i; + if (stat(IsoFile, &buf) == -1) break; + cdIndexs[i].slsn = llsn; + llsn+= buf.st_size / cdblocksize; + cdIndexs[i].elsn = llsn-1; + cdHandle[i] = fopen(IsoFile, "rb"); + if (cdHandle[i] == NULL) break; + } + + if (i == 0) { + SysMessage("Error loading %s\n", IsoFile); + return -1; + } + fmode = 3; + } else*//* { + iso->handle = _openfile(iso->filename, O_RDONLY); + if (iso->handle == NULL) { + printf("Error loading %s\n", iso->filename); + return NULL; + } + }*/ + + printf("isoOpen: %s ok\n", iso->filename); + printf("offset = %d\n", iso->offset); + printf("blockofs = %d\n", iso->blockofs); + printf("blocksize = %d\n", iso->blocksize); + printf("blocks = %d\n", iso->blocks); + printf("type = %d\n", iso->type); + + return iso; +} + +isoFile *isoCreate(const char *filename, int flags) { + isoFile *iso; + char Zfile[256]; + + iso = (isoFile*)malloc(sizeof(isoFile)); + if (iso == NULL) return NULL; + + memset(iso, 0, sizeof(isoFile)); + strcpy(iso->filename, filename); + iso->flags = flags; + iso->offset = 0; + iso->blockofs = 24; + iso->blocksize = CD_FRAMESIZE_RAW; + iso->blocksize = 2048; + + if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2)) { + sprintf(Zfile, "%s.table", iso->filename); + iso->htable = _openfile(Zfile, O_WRONLY); + if (iso->htable == NULL) { + return NULL; + } + } + + iso->handle = _openfile(iso->filename, O_WRONLY); + if (iso->handle == NULL) { + printf("Error loading %s\n", iso->filename); + return NULL; + } + printf("isoCreate: %s ok\n", iso->filename); + printf("offset = %d\n", iso->offset); + + return iso; +} + +int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks) { + iso->blocksize = blocksize; + iso->blocks = blocks; + iso->blockofs = blockofs; + printf("blockofs = %d\n", iso->blockofs); + printf("blocksize = %d\n", iso->blocksize); + printf("blocks = %d\n", iso->blocks); + if (iso->flags & ISOFLAGS_Z2) { + if (_writefile(iso->handle, "Z V2", 4) < 4) return -1; + if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; + if (_writefile(iso->handle, &blocks, 4) < 4) return -1; + if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; + } + if (iso->flags & ISOFLAGS_BLOCKDUMP) { + if (_writefile(iso->handle, "BDV2", 4) < 4) return -1; + if (_writefile(iso->handle, &blocksize, 4) < 4) return -1; + if (_writefile(iso->handle, &blocks, 4) < 4) return -1; + if (_writefile(iso->handle, &blockofs, 4) < 4) return -1; + } + + return 0; +} + +s32 MSFtoLSN(u8 *Time) { + u32 lsn; + + lsn = Time[2]; + lsn+=(Time[1] - 2) * 75; + lsn+= Time[0] * 75 * 60; + return lsn; +} + +void LSNtoMSF(u8 *Time, s32 lsn) { + u8 m, s, f; + + lsn += 150; + m = lsn / 4500; // minuten + lsn = lsn - m * 4500; // minuten rest + s = lsn / 75; // sekunden + f = lsn - (s * 75); // sekunden rest + Time[0] = itob(m); Time[1] = itob(s); Time[2] = itob(f); +} + +int _isoReadBlock(isoFile *iso, char *dst, int lsn) { + u64 ofs = (u64)lsn * iso->blocksize + iso->offset; + int ret; + +// printf("_isoReadBlock %d, blocksize=%d, blockofs=%d\n", lsn, iso->blocksize, iso->blockofs); + memset(dst, 0, iso->blockofs); + _seekfile(iso->handle, ofs, SEEK_SET); + ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize); + if (ret < iso->blocksize) { + printf("read error %d\n", ret); + return -1; + } + + return 0; +} +/* +int _isoReadBlockZ(isoFile *iso, char *dst, int lsn) { + u32 pos, p; + uLongf size; + u8 Zbuf[CD_FRAMESIZE_RAW*2]; + int ret; + +// printf("_isoReadBlockZ %d, %d\n", lsn, iso->blocksize); + pos = *(unsigned long*)&iso->Ztable[lsn * 6]; + p = *(unsigned short*)&iso->Ztable[lsn * 6 + 4]; +// printf("%d, %d\n", pos, p); + _seekfile(iso->handle, pos, SEEK_SET); + ret = _readfile(iso->handle, Zbuf, p); + if (ret < p) { + printf("error reading block!!\n"); + return -1; + } + + size = CD_FRAMESIZE_RAW; + uncompress(dst, &size, Zbuf, p); + + return 0; +} + +int _isoReadBlockZ2(isoFile *iso, char *dst, int lsn) { + u32 pos, p; + uLongf size; + u8 Zbuf[16*1024]; + int ret; + +// printf("_isoReadBlockZ2 %d, %d\n", lsn, iso->blocksize); + pos = *(u32*)&iso->Ztable[lsn*8]; + p = *(u32*)&iso->Ztable[lsn*8+4]; +// printf("%d, %d\n", pos, p); + _seekfile(iso->handle, pos, SEEK_SET); + ret = _readfile(iso->handle, Zbuf, p); + if (ret < p) { + printf("error reading block!!\n"); + return -1; + } + + size = iso->blocksize; + uncompress(dst + iso->blockofs, &size, Zbuf, p); + + return 0; +} +*/ +int _isoReadBlockD(isoFile *iso, char *dst, int lsn) { + int ret; + int i; + +// printf("_isoReadBlockD %d, blocksize=%d, blockofs=%d\n", lsn, iso->blocksize, iso->blockofs); + memset(dst, 0, iso->blockofs); + for (i=0; idtablesize;i++) { + if (iso->dtable[i] != lsn) continue; + + _seekfile(iso->handle, 16+i*(iso->blocksize+4)+4, SEEK_SET); + ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize); + if (ret < iso->blocksize) return -1; + + return 0; + } + printf("block %d not found in dump\n", lsn); + + return -1; +} + +int isoReadBlock(isoFile *iso, char *dst, int lsn) { + int ret; + + if (lsn > iso->blocks) { + printf("isoReadBlock: %d > %d\n", lsn, iso->blocks); + return -1; + } +/* if (iso->flags & ISOFLAGS_Z) { + ret = _isoReadBlockZ(iso, dst, lsn); + } else + if (iso->flags & ISOFLAGS_Z2) { + ret = _isoReadBlockZ2(iso, dst, lsn); + } else +*/ if (iso->flags & ISOFLAGS_BLOCKDUMP) { + ret = _isoReadBlockD(iso, dst, lsn); + } else + ret = _isoReadBlock(iso, dst, lsn); + if (ret == -1) return ret; + + if (iso->type == ISOTYPE_CD) { + LSNtoMSF(dst+12, lsn); + dst[15] = 2; + } + + return 0; +} + + +int _isoWriteBlock(isoFile *iso, u8 *src, int lsn) { + u64 ofs = (u64)lsn * iso->blocksize + iso->offset; + int ret; + +// printf("_isoWriteBlock %d (ofs=%d)\n", iso->blocksize, ofs); + _seekfile(iso->handle, ofs, SEEK_SET); + ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlock %d\n", ret); + if (ret < iso->blocksize) return -1; + + return 0; +} +/* +int _isoWriteBlockZ(isoFile *iso, u8 *src, int lsn) { + u32 pos; + uLongf size; + u8 Zbuf[CD_FRAMESIZE_RAW]; + int ret; + +// printf("_isoWriteBlockZ %d\n", iso->blocksize); + size = 2352; + compress(Zbuf, &size, src, 2352); +// printf("_isoWriteBlockZ %d\n", size); + + pos = (u32)_tellfile(iso->handle); + ret = _writefile(iso->htable, (u8*)&pos, 4); + if (ret < 4) return -1; + ret = _writefile(iso->htable, (u8*)&size, 2); + if (ret < 2) return -1; + + ret = _writefile(iso->handle, Zbuf, size); +// printf("_isoWriteBlockZ %d\n", ret); + if (ret < size) { + printf("error writing block!!\n"); + return -1; + } + + return 0; +} + +int _isoWriteBlockZ2(isoFile *iso, u8 *src, int lsn) { + uLongf size; + u8 Zbuf[1024*16]; + int ret; + +// printf("_isoWriteBlockZ %d\n", iso->blocksize); + size = 1024*16; + compress(Zbuf, &size, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlockZ %d\n", size); + + ret = _writefile(iso->htable, (u8*)&size, 4); + if (ret < 4) return -1; + ret = _writefile(iso->handle, Zbuf, size); +// printf("_isoWriteBlockZ %d\n", ret); + if (ret < size) { + printf("error writing block!!\n"); + return -1; + } + + return 0; +} +*/ +int _isoWriteBlockD(isoFile *iso, u8 *src, int lsn) { + int ret; + +// printf("_isoWriteBlock %d (ofs=%d)\n", iso->blocksize, ofs); + ret = _writefile(iso->handle, &lsn, 4); + if (ret < 4) return -1; + ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize); +// printf("_isoWriteBlock %d\n", ret); + if (ret < iso->blocksize) return -1; + + return 0; +} + +int isoWriteBlock(isoFile *iso, char *src, int lsn) { + int ret; + +/* if (iso->flags & ISOFLAGS_Z) { + ret = _isoWriteBlockZ(iso, src, lsn); + } else + if (iso->flags & ISOFLAGS_Z2) { + ret = _isoWriteBlockZ2(iso, src, lsn); + } else +*/ if (iso->flags & ISOFLAGS_BLOCKDUMP) { + ret = _isoWriteBlockD(iso, src, lsn); + } else + ret = _isoWriteBlock(iso, src, lsn); + if (ret == -1) return ret; + + return 0; +} + +void isoClose(isoFile *iso) { + if (iso->handle) { + _closefile(iso->handle); + } + if (iso->htable) { + _closefile(iso->htable); + } + free(iso); +} + diff --git a/plugins/cdvd/CDVDpeops/libiso.h b/plugins/cdvd/CDVDpeops/libiso.h new file mode 100644 index 0000000..461f792 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/libiso.h @@ -0,0 +1,59 @@ +#ifndef __LIBISO_H__ +#define __LIBISO_H__ + +#ifdef __MSCW32__ +#pragma warning(disable:4018) +#endif + +#define CDVDdefs +#include "PS2Etypes.h" +#include "PS2Edefs.h" + +#define ISOTYPE_ILLEGAL 0 +#define ISOTYPE_CD 1 +#define ISOTYPE_DVD 2 +#define ISOTYPE_AUDIO 3 + +#define ISOFLAGS_Z 0x1 +#define ISOFLAGS_Z2 0x2 +#define ISOFLAGS_BLOCKDUMP 0x4 + +#define CD_FRAMESIZE_RAW 2352 +#define DATA_SIZE (CD_FRAMESIZE_RAW-12) + +#define itob(i) ((i)/10*16 + (i)%10) /* u_char to BCD */ +#define btoi(b) ((b)/16*10 + (b)%16) /* BCD to u_char */ + +typedef struct { + char filename[256]; + u32 type; + u32 flags; + u32 offset; + u32 blockofs; + u32 blocksize; + u32 blocks; + void *handle; + void *htable; + char *Ztable; + u32 *dtable; + int dtablesize; + char buffer[CD_FRAMESIZE_RAW * 10]; +} isoFile; + + +isoFile *isoOpen(const char *filename); +isoFile *isoCreate(const char *filename, int mode); +int isoSetFormat(isoFile *iso, int blockofs, int blocksize, int blocks); +int isoDetect(isoFile *iso); +int isoReadBlock(isoFile *iso, char *dst, int lsn); +int isoWriteBlock(isoFile *iso, char *src, int lsn); +void isoClose(isoFile *iso); + +void *_openfile(const char *filename, int flags); +u64 _tellfile(void *handle); +int _seekfile(void *handle, u64 offset, int whence); +int _readfile(void *handle, void *dst, int size); +int _writefile(void *handle, void *src, int size); +void _closefile(void *handle); + +#endif /* __LIBISO_H__ */ diff --git a/plugins/cdvd/CDVDpeops/license.txt b/plugins/cdvd/CDVDpeops/license.txt new file mode 100644 index 0000000..e51338c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/license.txt @@ -0,0 +1,282 @@ +######################################################################### + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/cdvd/CDVDpeops/macros.inc b/plugins/cdvd/CDVDpeops/macros.inc new file mode 100644 index 0000000..4782928 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/macros.inc @@ -0,0 +1,40 @@ +; macros.inc - description +; ------------------- +; begin : Sun Nov 08 2001 +; based on ZSNES macros.mac +; email : linuzappz@pcsx.net + +; This program is free software; you can redistribute it and/or modify * +; it under the terms of the GNU General Public License as published by * +; the Free Software Foundation; either version 2 of the License, or * +; (at your option) any later version. See also the license.txt file for * +; additional informations. * + + +%ifdef __WIN32__ + +%imacro EXTSYM 1-* +%rep %0 + extern _%1 + %define %1 _%1 +%rotate 1 +%endrep +%endmacro + +%imacro NEWSYM 1 + global _%1 + _%1: + %1: +%endmacro + +%else + +%define EXTSYM extern + +%imacro NEWSYM 1 + global %1 + %1: +%endmacro + +%endif + diff --git a/plugins/cdvd/CDVDpeops/mingw/afxres.h b/plugins/cdvd/CDVDpeops/mingw/afxres.h new file mode 100644 index 0000000..060e13b --- /dev/null +++ b/plugins/cdvd/CDVDpeops/mingw/afxres.h @@ -0,0 +1,2 @@ +#include +#define IDC_STATIC -1 diff --git a/plugins/cdvd/CDVDpeops/ppf.c b/plugins/cdvd/CDVDpeops/ppf.c new file mode 100644 index 0000000..c9f755d --- /dev/null +++ b/plugins/cdvd/CDVDpeops/ppf.c @@ -0,0 +1,353 @@ +/*************************************************************************** + ppf.c - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/02/14 - Pete +// - fixed a bug reading PPF3 patches reported by Zydio +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_PPF +#include "externals.h" + +///////////////////////////////////////////////////////// + +int iUsePPF=0; +char szPPF[260]; +PPF_CACHE * ppfCache=NULL; +PPF_DATA * ppfHead=NULL; +int iPPFNum=0; + +///////////////////////////////////////////////////////// +// works like sub cache... using a linked data list, and address array + +void FillPPFCache(void) +{ + PPF_DATA * p;PPF_CACHE * pc; + long lastaddr; + + p=ppfHead; + lastaddr=-1; + iPPFNum=0; + + while(p) + { + if(p->addr!=lastaddr) iPPFNum++; + lastaddr=p->addr; + p=(PPF_DATA *)p->pNext; + } + + if(!iPPFNum) return; + + pc=ppfCache=(PPF_CACHE *)malloc(iPPFNum*sizeof(PPF_CACHE)); + + iPPFNum--; + p=ppfHead; + lastaddr=-1; + + while(p) + { + if(p->addr!=lastaddr) + { + pc->addr=p->addr; + pc->pNext=(void *)p; + pc++; + } + lastaddr=p->addr; + p=(PPF_DATA *)p->pNext; + } +} + +///////////////////////////////////////////////////////// + +void FreePPFCache(void) +{ + PPF_DATA * p=ppfHead; + void * pn; + + while(p) + { + pn=p->pNext; + free(p); + p=(PPF_DATA *)pn; + } + ppfHead=NULL; + + if(ppfCache) free(ppfCache); + ppfCache=NULL; +} + +///////////////////////////////////////////////////////// + +void CheckPPFCache(long addr,unsigned char * pB) +{ + PPF_CACHE * pcstart, * pcend, * pcpos; + + pcstart=ppfCache; + if(addraddr) return; + pcend=ppfCache+iPPFNum; + if(addr>pcend->addr) return; + + while(1) + { + if(addr==pcend->addr) {pcpos=pcend;break;} + + pcpos=pcstart+(pcend-pcstart)/2; + if(pcpos==pcstart) break; + if(addraddr) + { + pcend=pcpos; + continue; + } + if(addr>pcpos->addr) + { + pcstart=pcpos; + continue; + } + break; + } + + if(addr==pcpos->addr) + { + PPF_DATA * p=(PPF_DATA *)pcpos->pNext; + while(p && p->addr==addr) + { + memcpy(pB+p->pos,p+1,p->anz); + p=(PPF_DATA *)p->pNext; + } + } +} + +///////////////////////////////////////////////////////// + +void AddToPPF(long ladr,long pos,long anz,char * ppfmem) +{ + if(!ppfHead) + { + ppfHead=(PPF_DATA *)malloc(sizeof(PPF_DATA)+anz); + ppfHead->addr=ladr; + ppfHead->pNext=NULL; + ppfHead->pos=pos; + ppfHead->anz=anz; + memcpy(ppfHead+1,ppfmem,anz); + iPPFNum=1; + } + else + { + PPF_DATA * p=ppfHead; + PPF_DATA * plast=NULL; + PPF_DATA * padd; + while(p) + { + if(ladraddr) break; + if(ladr==p->addr) + { + while(p && ladr==p->addr && pos>p->pos) + { + plast=p; + p=(PPF_DATA *)p->pNext; + } + break; + } + plast=p; + p=(PPF_DATA *)p->pNext; + } + padd=(PPF_DATA *)malloc(sizeof(PPF_DATA)+anz); + padd->addr=ladr; + padd->pNext=(void *)p; + padd->pos=pos; + padd->anz=anz; + memcpy(padd+1,ppfmem,anz); + iPPFNum++; + if(plast==NULL) + ppfHead=padd; + else plast->pNext=(void *)padd; + } +} + +///////////////////////////////////////////////////////// +// build ppf cache, if wanted + +void BuildPPFCache(void) +{ + FILE * ppffile; + char buffer[5]; + char method,undo=0,blockcheck=0; + int dizlen, dizyn, dizlensave=0; + char ppfmem[512]; + int count,seekpos, pos; + //unsigned char anz; + unsigned int anz; // new! avoids stupid overflows + long ladr,off,anx; + + ppfHead=NULL; + + if(iUsePPF==0) return; // no ppf cache wanted? + if(szPPF[0]==0) return; // no ppf file given? + + ppffile=fopen(szPPF, "rb"); + if(ppffile==0) + { + MessageBox(NULL,"No PPF file found!",libraryName,MB_OK); + return; + } + + memset(buffer,0,5); + fread(buffer, 3, 1, ppffile); + + if(strcmp(buffer,"PPF")) + { + MessageBox(NULL,"No PPF file format!",libraryName,MB_OK); + fclose(ppffile); + return; + } + + fseek(ppffile, 5, SEEK_SET); + fread(&method, 1, 1,ppffile); + + switch(method) + { + case 0: // ppf1 + fseek(ppffile, 0, SEEK_END); + count=ftell(ppffile); + count-=56; + seekpos=56; + break; + + case 1: // ppf2 + fseek(ppffile, -8,SEEK_END); + + memset(buffer,0,5); + fread(buffer, 4, 1,ppffile); + if(strcmp(".DIZ", buffer)) + { + dizyn=0; + } + else + { + fread(&dizlen, 4, 1, ppffile); + dizyn=1; + dizlensave=dizlen; + } + + fseek(ppffile, 56, SEEK_SET); + fread(&dizlen, 4, 1,ppffile); + fseek(ppffile, 0, SEEK_END); + count=ftell(ppffile); + if(dizyn==0) + { + count-=1084; + seekpos=1084; + } + else + { + count-=1084; + count-=38; + count-=dizlensave; + seekpos=1084; + } + break; + + case 2: // ppf3 + fseek(ppffile, 57, SEEK_SET); + fread(&blockcheck, 1, 1,ppffile); + fseek(ppffile, 58, SEEK_SET); + fread(&undo, 1, 1,ppffile); + + fseek(ppffile, -6,SEEK_END); + memset(buffer,0,5); + fread(buffer, 4, 1,ppffile); + dizlen=0; + if(!strcmp(".DIZ", buffer)) + { + fseek(ppffile, -2,SEEK_END); + fread(&dizlen, 2, 1, ppffile); + dizlen+=36; + } + + fseek(ppffile, 0, SEEK_END); + count=ftell(ppffile); + count-=dizlen; + + if(blockcheck) + { + seekpos=1084; + count-=1084; + } + else + { + seekpos=60; + count-=60; + } + + break; + + default: + fclose(ppffile); + MessageBox(NULL,"Unknown PPF format!",libraryName,MB_OK); + return; + } + + do // now do the data reading + { + fseek(ppffile, seekpos, SEEK_SET); + fread(&pos, 4, 1, ppffile); + + if(method==2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here) + + anz=0; // new! init anz (since it's no unsigned char anymore) + fread(&anz, 1, 1, ppffile); + fread(ppfmem, anz, 1, ppffile); + + ladr=pos/2352; + off=pos%2352; + + if(off+anz>2352) + { + anx=off+anz-2352; + anz-=(unsigned char)anx; + AddToPPF(ladr+1,0,anx,ppfmem+anz); + } + + AddToPPF(ladr,off,anz,ppfmem); // add to link list + + if(method==2) // adjust ppf3 size + { + if(undo) anz+=anz; + anz+=4; + } + + seekpos=seekpos+5+anz; + count=count-5-anz; + } + while(count!=0); // loop til end + + fclose(ppffile); + + FillPPFCache(); // build address array +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/ppf.h b/plugins/cdvd/CDVDpeops/ppf.h new file mode 100644 index 0000000..af20e48 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/ppf.h @@ -0,0 +1,32 @@ +/*************************************************************************** + ppf.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void FillPPFCache(void); +void FreePPFCache(void); +void CheckPPFCache(long addr,unsigned char * pB); +void AddToPPF(long ladr,long pos,long anz,char * ppfmem); +void BuildPPFCache(void); + diff --git a/plugins/cdvd/CDVDpeops/read.c b/plugins/cdvd/CDVDpeops/read.c new file mode 100644 index 0000000..e0de204 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/read.c @@ -0,0 +1,910 @@ +/*************************************************************************** + read.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_READ +#include "externals.h" + +///////////////////////////////////////////////////////// + +READTRACKFUNC pReadTrackFunc=NULL; +GETPTRFUNC pGetPtrFunc=NULL; + +int iUseCaching=0; +int iTryAsync=0; +int iBufSel=0; + +unsigned char * pMainBuffer=0; +unsigned char * pCurrReadBuf=0; +unsigned char * pFirstReadBuf=0; +unsigned char * pAsyncBuffer=0; + +unsigned long lMaxAddr=0; +unsigned long lLastAddr = 0xFFFFFFFF; +unsigned long lLastAsyncAddr = 0xFFFFFFFF; +unsigned long lNeededAddr = 0xFFFFFFFF; +unsigned long lLastAccessedAddr = 0xFFFFFFFF; +int iLastAccessedMode=0; + +unsigned char * ptrBuffer[2]; +unsigned char * pAsyncFirstReadBuf[2]; + + +#define MAXQSIZE 16 +#define MAXQFETCH 8 + +unsigned long lAddrQ[MAXQSIZE]; +int iQPos=0; +int iQIdle=0; +int iQLockPos=-1; + +///////////////////////////////////////////////////////// +// thread helper vars + +HANDLE hReadThread = NULL; +BOOL bThreadEnded = FALSE; +HANDLE hThreadEvent[3]; +HANDLE hThreadMutex[2]; + +///////////////////////////////////////////////////////// +// internal MAXDATACACHE*64KB (4MB) data cache + +#define MAXDATACACHE 64 +unsigned long lDataCacheAddr[MAXDATACACHE]; +unsigned char * pDataCacheBuf[MAXDATACACHE]; +BOOL bDataCacheHit=FALSE; +int iUseDataCache=0; + +///////////////////////////////////////////////////////// +// main init func + +void CreateREADBufs(void) +{ + switch(iUseCaching) + { + case 4: iUseDataCache = 2; // use a special data cache on threadex reading + pReadTrackFunc = DoReadThreadEx; + pGetPtrFunc = GetREADThreadExPtr; break; + case 3: pReadTrackFunc = DoReadThread; + pGetPtrFunc = GetREADThreadPtr; break; + case 2: pReadTrackFunc = DoReadAsync; + pGetPtrFunc = NULL; break; + default: pReadTrackFunc = DoRead; + pGetPtrFunc = NULL; break; + } + + hThreadEvent[0]=NULL; // clear events/mutex + hThreadEvent[1]=NULL; + hThreadEvent[2]=NULL; + hThreadMutex[0]=NULL; + hThreadMutex[1]=NULL; + + AllocDataCache(); // build data cache, if wanted + + lLastAddr = 0xFFFFFFFF; + lLastAsyncAddr = 0xFFFFFFFF; + iBufSel = 0; + + if(iUseCaching) // some caching? need bigger buffer + pMainBuffer=(unsigned char *)malloc(MAXCDBUFFER); + else pMainBuffer=(unsigned char *)malloc(CDSECTOR+208+96); + + pCurrReadBuf=pFirstReadBuf=pMainBuffer+FRAMEBUFEXTRA; + + if(iUseCaching>=2) // async/thread mode + { + pAsyncBuffer=(unsigned char *)malloc(MAXCDBUFFER); + ptrBuffer[0]=pMainBuffer; + ptrBuffer[1]=pAsyncBuffer; + pAsyncFirstReadBuf[0]=pFirstReadBuf; + pAsyncFirstReadBuf[1]=pAsyncBuffer+FRAMEBUFEXTRA; + + if(iUseCaching>=3) // thread mode + { + DWORD dw; + bThreadEnded = FALSE; + + for(dw=0;dw<3;dw++) // -> create events + { + hThreadEvent[dw]=CreateEvent(NULL,TRUE,FALSE,NULL); + ResetEvent(hThreadEvent[dw]); + } + for(dw=0;dw<2;dw++) // -> create mutex + { + hThreadMutex[dw]=CreateMutex(NULL,FALSE,NULL); + } + if(iUseCaching==3) // -> create thread + hReadThread=CreateThread(NULL,0,READThread,0,0,&dw); + else + { + for(dw=0;dw signal: end thread + while(!bThreadEnded) {Sleep(5L);} // -> wait til ended + WaitForSingleObject(hThreadMutex[1],INFINITE); + ReleaseMutex(hThreadMutex[1]); + hReadThread=NULL; // -> clear handle + } + + if(hThreadEvent[0]) CloseHandle(hThreadEvent[0]); // kill events/mutex + if(hThreadEvent[1]) CloseHandle(hThreadEvent[1]); + if(hThreadEvent[2]) CloseHandle(hThreadEvent[2]); + if(hThreadMutex[0]) CloseHandle(hThreadMutex[0]); + if(hThreadMutex[1]) CloseHandle(hThreadMutex[1]); + + if(pMainBuffer) free(pMainBuffer); // free main data buf + pMainBuffer=NULL; + if(pAsyncBuffer) free(pAsyncBuffer); // free async data buf + pAsyncBuffer=NULL; + + FreeDataCache(); +} + +///////////////////////////////////////////////////////// +// retry on readng error (blocking) + +BOOL bReadRetry(FRAMEBUF * f) +{ + int iRetry=0; + + while (iRetry tell it to user + { + char szB[64]; + wsprintf(szB,"Read error on address %08lx!",f->dwFrame); + MessageBox(NULL,szB,libraryName,MB_OK); + } + return FALSE; // -> tell emu: bad + } + + return TRUE; +} + +//////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +// sync modes (caching 0 and 1) +// just reads one or more blocks, and always waits until +// reading is done +///////////////////////////////////////////////////////// + +BOOL DoRead(unsigned long addr) +{ + FRAMEBUF * f; + + //////////////////////////////////////////////////////// + + if(iUseCaching && // cache block available? + lLastAddr!=0xFFFFFFFF && + addr>=lLastAddr && // and addr in block? + addr<=(lLastAddr+MAXCACHEBLOCK)) + { + pCurrReadBuf=pFirstReadBuf+ // -> calc data ptr + ((addr-lLastAddr)*iUsedBlockSize); + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); // -> apply ppf + return TRUE; // -> done + } + + //////////////////////////////////////////////////////// + + if(iUseDataCache && CheckDataCache(addr)) // cache used and data is in cache? set read ptr, if yes + return TRUE; // -> also fine + + //////////////////////////////////////////////////////// + + f=(FRAMEBUF *)pMainBuffer; // setup read for one sector + + f->dwFrameCnt = 1; + f->dwBufLen = iUsedBlockSize; + f->dwFrame = addr; + + pCurrReadBuf=pFirstReadBuf; + + //////////////////////////////////////////////////////// + + if(iUseCaching) // cache block? + { + if((addr+MAXCACHEBLOCK)dwFrameCnt = MAXCACHEBLOCK+1; // -> set bigger read + f->dwBufLen = (MAXCACHEBLOCK+1)*iUsedBlockSize; + lLastAddr = addr; // -> store addr of block + } + else + { + lLastAddr=0xFFFFFFFF; // no caching, no block addr + } + } + + //////////////////////////////////////////////////////// + + if(pReadFunc(TRUE,f)!=SS_COMP) // do a waiting read + { + if(!bReadRetry(f)) return FALSE; // and retry on error + } + + if(iUseDataCache && lLastAddr!=0xFFFFFFFF) // data cache used? and whole 64 k read block? + AddToDataCache(addr,pFirstReadBuf); // -> add the complete data to cache + + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); // apply ppf + + return TRUE; +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +// async mode (caching 2) +// this mode works fine with ASPI... +// the first read will be done sync, though, only the +// additional pre-fetching will be done async... +// well, with mdecs most reads will be prefetched, so +// speed is good... with IOCTL this mode is more like +// a 'double sync' reading, since IOCTL seems always +// to be blocking (see also notes for caching mode 3) +///////////////////////////////////////////////////////// + +BOOL DoReadAsync(unsigned long addr) +{ + FRAMEBUF * f; + + //////////////////////////////////////////////////////// + // 1. check if data is in already filled buffer + + if(lLastAddr!=0xFFFFFFFF && + addr>=lLastAddr && + addr<=(lLastAddr+MAXCACHEBLOCK)) + { + pCurrReadBuf=pAsyncFirstReadBuf[iBufSel]+ + ((addr-lLastAddr)*iUsedBlockSize); + + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); + + iTryAsync=0; + return TRUE; + } + + //////////////////////////////////////////////////////// + // check data cache + + if(iUseDataCache && CheckDataCache(addr)) // cache used and data is in cache? set read ptr, if yes + return TRUE; // -> also fine + + //////////////////////////////////////////////////////// + // 2. not in main buffer? wait for async to be finished + + if(bDoWaiting) + { + WaitGenEvent(0xFFFFFFFF);bDoWaiting=FALSE; + if(sx.SRB_Status!=SS_COMP) lLastAsyncAddr=0xFFFFFFFF; + } + + //////////////////////////////////////////////////////// + // 3. check in asyncbuffer. if yes, swap buffers and do next async read + + if(lLastAsyncAddr!=0xFFFFFFFF && + addr>=lLastAsyncAddr && + addr<=(lLastAsyncAddr+MAXCACHEBLOCK)) + { + int iAsyncSel=iBufSel; // store old buf num + if(iBufSel==0) iBufSel=1; else iBufSel=0; // toggle to new num + + lLastAddr=lLastAsyncAddr; // set adr of block + pCurrReadBuf=pAsyncFirstReadBuf[iBufSel]+ // set data ptr + ((addr-lLastAddr)*iUsedBlockSize); + + if(iUseDataCache) // data cache used? + AddToDataCache(lLastAddr,pAsyncFirstReadBuf[iBufSel]); // -> add the complete 64k data to cache + + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); // apply ppf + + iTryAsync=0; // data was async, reset count + addr=lLastAddr+MAXCACHEBLOCK+1; // calc adr of next prefetch + if(!((addr+MAXCACHEBLOCK)dwFrameCnt = MAXCACHEBLOCK+1; + f->dwBufLen = (MAXCACHEBLOCK+1)*iUsedBlockSize; + f->dwFrame = addr; + + lLastAsyncAddr=addr; // store prefetch addr + + if(pReadFunc(FALSE,f)!=SS_COMP) // start the async read + lLastAsyncAddr=0xFFFFFFFF; // -> if no success, no async prefetch buf available + + return TRUE; + } + + //////////////////////////////////////////////////////// + // here we do a sync read + + iBufSel=0; // read in buf 0 + + f=(FRAMEBUF *)ptrBuffer[0]; + f->dwFrame = addr; + + pCurrReadBuf=pFirstReadBuf; + + //////////////////////////////////////////////////////// + // if it's possible, we do a bigger read + + if((addr+MAXCACHEBLOCK)dwFrameCnt = MAXCACHEBLOCK+1; + f->dwBufLen = (MAXCACHEBLOCK+1)*iUsedBlockSize; + lLastAddr = addr; + } + else + { + f->dwFrameCnt = 1; + f->dwBufLen = iUsedBlockSize; + lLastAddr = 0xFFFFFFFF; + } + + //////////////////////////////////////////////////////// + // start read, wait til finished + + if(pReadFunc(TRUE,f)!=SS_COMP) + { + if(!bReadRetry(f)) return FALSE; + } + + if(iUseDataCache && lLastAddr!=0xFFFFFFFF) // data cache used? and complete 64k block? + AddToDataCache(addr,pAsyncFirstReadBuf[0]); // -> add the complete data to cache + + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); + + //////////////////////////////////////////////////////// + // start additional async prefetch read, if it's ok + + iTryAsync++; + if(iTryAsync>1) {iTryAsync=2;return TRUE;} // prefetches seems to be useless right now, so turn them off until next real read + + addr+=MAXCACHEBLOCK+1; // prefetch addr + if(!((addr+MAXCACHEBLOCK)dwFrameCnt = MAXCACHEBLOCK+1; + f->dwBufLen = (MAXCACHEBLOCK+1)*iUsedBlockSize; + f->dwFrame = addr; + + lLastAsyncAddr= addr; + + if(pReadFunc(FALSE,f)!=SS_COMP) // start the async prefetch + lLastAsyncAddr=0xFFFFFFFF; + + return TRUE; +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +// thread mode (caching 3) +// this mode helps with slower drives using the IOCTL +// interface (since that one seems to do always blocking +// reads, even when they are done overlapped). +// With ASPI, the thread mode performance will be more or less +// the same as with async caching mode 2... +// thread reading would be much more powerful, if the main +// emu would do: +// ... +// CDRreadTrack() +// ... do some other stuff here ... +// CDRgetBuffer() +// ... +// but lazy main emu coders seem to prefer: +// ... +// CDRreadTrack() +// CDRgetBuffer() +// ... +// so there is no time between the calls to do a good +// asynchronous read... sad, sad... +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// reading thread... sleeps until a new read is signaled + +DWORD WINAPI READThread(LPVOID lpParameter) +{ + FRAMEBUF * f; + + while(WaitForMultipleObjects(2,hThreadEvent,FALSE, // wait until event to start (or event to end) get raised + INFINITE)==WAIT_OBJECT_0) + { + WaitForSingleObject(hThreadMutex[0],INFINITE); // read mutex: nobody else is allowed to read now + WaitForSingleObject(hThreadMutex[1],INFINITE); // variable access mutex: nobody else can change the vars now + ResetEvent(hThreadEvent[0]); // ok, kick event has been handled + SetEvent(hThreadEvent[2]); // set flag: we have started the read + + lLastAsyncAddr = lNeededAddr; // setup read and vars + f=(FRAMEBUF *)ptrBuffer[!iBufSel]; // !iSel = async buffer + f->dwFrame = lNeededAddr; + f->dwFrameCnt = min((lMaxAddr-lNeededAddr+1),(MAXCACHEBLOCK+1)); + f->dwBufLen = f->dwFrameCnt*iUsedBlockSize; + + ReleaseMutex(hThreadMutex[1]); // ok, vars have been changed, now that vars are again available for all + + if(pReadFunc(TRUE,f)!=SS_COMP) // do a blocking (sync) read + { + bReadRetry(f); // mmm... if reading fails a number of times, we don't have a chance to return 'bad' to emu with tread reading... life is hard :) + } + + ReleaseMutex(hThreadMutex[0]); // ok, read has done + } + + bThreadEnded=1; + return 0; +} + +///////////////////////////////////////////////////////// +// emu says: we need data at given addr soon... +// so, if we don't have it in any buffer, we kick a read +// ... called on CDRreadTrack() + +BOOL DoReadThread(unsigned long addr) +{ + if(!hReadThread) return FALSE; // no thread, no fun + + bDataCacheHit=FALSE; // init data cache hit flag (even if no cache is used...) + + if(lLastAddr!=0xFFFFFFFF && // data is in curr data buffer? + addr>=lLastAddr && + addr<=(lLastAddr+MAXCACHEBLOCK)) + return TRUE; // -> fine + + if(iUseDataCache && CheckDataCache(addr)) // data cache used and data is in cache? set read ptr, if yes + {bDataCacheHit=TRUE;return TRUE;} // -> and raise 'hit' flag, so we don't need to do anything in 'getbuffer' + + WaitForSingleObject(hThreadMutex[1],INFINITE); // wait to access 'buffer 1 vars' + + if(lLastAsyncAddr!=0xFFFFFFFF && // data is (or will be soon if reading is going on in thread now) in async buffer? + addr>=lLastAsyncAddr && + addr<=(lLastAsyncAddr+MAXCACHEBLOCK)) + { + ReleaseMutex(hThreadMutex[1]); // -> fine + return TRUE; + } + // data is not in buf0 and not in buf1: + lNeededAddr=addr; // set needed adr (mutex is active, so it's safe to change that) + ResetEvent(hThreadEvent[2]); // reset "read has started" flag + SetEvent(hThreadEvent[0]); // set "start read" flag... the read will start reading soon after + ReleaseMutex(hThreadMutex[1]); // done with var access + return TRUE; +} + +///////////////////////////////////////////////////////// +// emu says: gimme ptr to needed data... this will +// automatically do an async data prefetch read as well +// ... called on CDRgetBuffer() + +void GetREADThreadPtr(void) +{ + unsigned long addr=lLastAccessedAddr; + + if(bDataCacheHit) return; // if we had a data cache hit, the readbuf ptr is already fine, nothing else to do + + if(lLastAddr!=0xFFFFFFFF && // data is in buffer 0? + addr>=lLastAddr && + addr<=(lLastAddr+MAXCACHEBLOCK)) + { + pCurrReadBuf=pAsyncFirstReadBuf[iBufSel]+ // -> ok, return curr data buffer ptr + ((addr-lLastAddr)*iUsedBlockSize); + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); + return; + } + + WaitForSingleObject(hThreadEvent[2],INFINITE); // wait until reading has started (it will take a small time after the read start kick, so we have to go sure that it has _really_ started) + WaitForSingleObject(hThreadMutex[0],INFINITE); // wait until reading has finished + + lLastAddr=lLastAsyncAddr; // move data to from async data to curr data buffer (by toggling iSel) + iBufSel=!iBufSel; + lLastAsyncAddr=0xFFFFFFFF; // nothing in async data buffer now + + lNeededAddr=addr+MAXCACHEBLOCK+1; // prefetch read addr + ResetEvent(hThreadEvent[2]); // reset "read has started" flag + SetEvent(hThreadEvent[0]); // signal for start next read + ReleaseMutex(hThreadMutex[0]); // ok, now reading in buffer 1 can start + + if(iUseDataCache) // data cache used? can be less then 64 kb with thread reading, but that doesn't matter here... will be either 64 k or (max-addr) sectors + AddToDataCache(lLastAddr, + pAsyncFirstReadBuf[iBufSel]); // -> add the complete data to cache + + pCurrReadBuf=pAsyncFirstReadBuf[iBufSel]+ // -> return the curr data buffer ptr + ((addr-lLastAddr)*iUsedBlockSize); + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +// special thread mode (caching 4) +// this mode helps with certain drives +// basically it does the following: +// It has a queue for n prefetch reads. If the main emu is +// asking for an addr, the mode will check, if +// this addr is a) getting read right now, b) already +// in our 4 MB cache, c) already in the q. +// If no condition matches, it will add it in q... +// the same is done with the next n/2 addr blocks, so +// the q will keep the drive busy... also, if everything +// is cached (and the q is empty), we will add additional +// addresses to read, also to keep the drive busy, and to +// do the needed reading as soon as possible :) + +///////////////////////////////////////////////////////// +// reading thread... + +DWORD WINAPI READThreadEx(LPVOID lpParameter) +{ + FRAMEBUF * f; + + while(WaitForMultipleObjects(2,hThreadEvent,FALSE, // wait until event to start (or event to end) get raised + INFINITE)==WAIT_OBJECT_0) + { + while(1) + { + //------------------------------------------------// + WaitForSingleObject(hThreadMutex[1],INFINITE); // variable access mutex: nobody else can change the vars now + ResetEvent(hThreadEvent[0]); // ok, kick event has been handled + + if(lAddrQ[iQPos]==0xFFFFFFFF) // nothing to do? strange :) + {ReleaseMutex(hThreadMutex[1]);break;} + + f=(FRAMEBUF *)ptrBuffer[0]; + lNeededAddr = lAddrQ[iQPos]; // store it in 'Neededaddr' for checks outside the thread + f->dwFrame = lNeededAddr; + f->dwFrameCnt = min((lMaxAddr-f->dwFrame+1),(MAXCACHEBLOCK+1)); + f->dwBufLen = f->dwFrameCnt*iUsedBlockSize; + + lAddrQ[iQPos++]=0xFFFFFFFF; // set this slot as 'done' + if(iQPos>=MAXQSIZE) iQPos=0; // amnd inc the head pos + + ReleaseMutex(hThreadMutex[1]); // ok, vars have been changed, now that vars are again available for all + //------------------------------------------------// + WaitForSingleObject(hThreadMutex[0],INFINITE); // read mutex: nobody else is allowed to read now + if(!iCDROK) + { + ReleaseMutex(hThreadMutex[0]); + break; + } + + if(bCDDAPlay) // some cdda security... + { // it should just prevent prefetch reads happening in cdda mode, if this one breaks a 'needed' read, we are lost... + lNeededAddr=0xFFFFFFFF; // so maybe we should remove this check? mmm, we will see + ReleaseMutex(hThreadMutex[0]); + break; + } + + if(pReadFunc(TRUE,f)!=SS_COMP) // do a blocking (sync) read + { // mmm... if reading fails a number of times, we don't have a chance to return 'bad' to emu with thread reading... life is hard :) + bReadRetry(f); // but at least our 'wait for data in cache' getptr will not wait forever (just returning wrong data, ehehe) + } + + ReleaseMutex(hThreadMutex[0]); // ok, read has done + //------------------------------------------------// + WaitForSingleObject(hThreadMutex[1],INFINITE); // variable access mutex: nobody else can change the vars now + lNeededAddr=0xFFFFFFFF; // no read is now active + AddToDataCache(f->dwFrame,pFirstReadBuf); // add the complete data to cache + ReleaseMutex(hThreadMutex[1]); // ok, vars have been changed, now that vars are again available for all + //------------------------------------------------// + if(WaitForSingleObject(hThreadEvent[0],0)!=WAIT_OBJECT_0) + Sleep(1); // if nobody has started a new kick, let's sleep awhile to give Windows more room to breath + } + } + + bThreadEnded=1; + return 0; +} + +///////////////////////////////////////////////////////// +// emu says: we need data at given addr soon... +// so, if we don't have it in any buffer, we kick a read +// ... called on CDRreadTrack() + +//#define THREADEX_STRAIGHT + +BOOL DoReadThreadEx(unsigned long addr) +{ + int i,k,j=0; + + if(!hReadThread) return FALSE; // no thread, no fun + + WaitForSingleObject(hThreadMutex[1],INFINITE); // wait for data access + +//-----------------------------------------------------// +// straight reading try... should have been faster, but +// in 'real life' this approach keeps the cdrom drive +// spinning too much, giving other pc resources no room +// to breath... by increasing the thread 'Sleep' value +// the performance can get better, but then the annoying +// breaks we wanted to fight will show up again... +// so this type is disabled as long as nobody enables the +// define again :) + +#ifdef THREADEX_STRAIGHT + + if(addr>=lNeededAddr && + addr<=(lNeededAddr+MAXCACHEBLOCK)) + { + ReleaseMutex(hThreadMutex[1]); + return TRUE; + } + + for(k=0;k=lDataCacheAddr[i] && // -> addr found? + addr<=(lDataCacheAddr[i]+MAXCACHEBLOCK)) + { + if(k==0) iQLockPos=i; // -> if it's the current main addr, lock it, so no prefetch read overwrites its content + break; + } + } + if(i!=MAXDATACACHE) // found in data cache? + {addr=addr+MAXCACHEBLOCK+1;continue;} // -> do nothing with this addr, we have its content + else break; // here is the first unknown addr + } + + if(addr>=lMaxAddr) // check, if addr too big + { + ReleaseMutex(hThreadMutex[1]); + if(k==0) return FALSE; // -> if it's the main addr, there is an error + return TRUE; // -> otherwise we can't simply cache that addr + } + + for(i=0;i=lAddrQ[i] && // -> addr will be read soon? + addr<=(lAddrQ[i]+MAXCACHEBLOCK)) + { + addr=lAddrQ[i]; // --> take this aligned addr for new header + break; + } + } + + for(i=0;i=lMaxAddr) break; + } + + for(;i=lNeededAddr && // addr is getting read right now? + addr<=(lNeededAddr+MAXCACHEBLOCK)) // -> ok, we do nothing with it + {addr=addr+MAXCACHEBLOCK+1;continue;} + + for(i=0;i=lDataCacheAddr[i] && // -> addr found? + addr<=(lDataCacheAddr[i]+MAXCACHEBLOCK)) + { + if(k==0) iQLockPos=i; // -> if it's the current main addr, lock it, so no other prefetch read overwrites its content + break; + } + } + if(i!=MAXDATACACHE) // found in data cache? + {addr=addr+MAXCACHEBLOCK+1;continue;} // -> do nothing with this addr, we have its content + + for(i=0;i=lAddrQ[i] && // -> addr will be read soon? + addr<=(lAddrQ[i]+MAXCACHEBLOCK)) + { + if(k==0 && i!=iQPos) // curr needed addr is not on top of the q? + { + addr=lAddrQ[i]; // -> get the addr (our main addr is in it, but that one is more aligned to prev reads) + for(i=0;i clear whole q (we will fill the slots in that loop again) + i=MAXQSIZE; // -> sign for storing the addr in q + } + break; + } + } + if(i!=MAXQSIZE) // found in q? + {addr=addr+MAXCACHEBLOCK+1;continue;} // -> do nothing with this addr, we will have its content soon + + // not in q or data cache? + if(k==0) lAddrQ[iQPos]=addr; // -> if it's the main addr, store it on top of list + else // -> if it's a prefetch addr, try to store it elsewhere at the end of the q + { + j=iQPos; + for(i=0;i=MAXQSIZE) j=0; + } + } + + SetEvent(hThreadEvent[0]); // kick a read, if neccessary + addr=addr+MAXCACHEBLOCK+1; // next prefetch addr + if(addr>=lMaxAddr) break; // security, for detecting if we are at the end of cd + } + + //----------------------------------------------------// ok, and here's something to keep the drive busy... + + if(lAddrQ[iQPos]==0xFFFFFFFF && addr10) // more then x times? + { + iQIdle=0; + lAddrQ[iQPos]=addr; // we add the farest prefetch addr + SetEvent(hThreadEvent[0]); // and do an additional kick + } + } + else iQIdle=0; // not idling? ok + + //----------------------------------------------------// + +#endif + + ReleaseMutex(hThreadMutex[1]); + + return TRUE; +} + +///////////////////////////////////////////////////////// +// emu says: gimme ptr to needed data... this will +// automatically do an async data prefetch read as well +// ... called on CDRgetBuffer() + +void GetREADThreadExPtr(void) +{ + unsigned long addr=lLastAccessedAddr; + + while(1) + { + if(bThreadEnded) return; // main emu is already closing (thread is down)? bye + WaitForSingleObject(hThreadMutex[1],INFINITE); // wait for data access + if(CheckDataCache(addr)) // data now in cache? + { + ReleaseMutex(hThreadMutex[1]); // -> ok, done + return; + } + ReleaseMutex(hThreadMutex[1]); // else try again (no sleep here, we are blocking everything anyway) + } + +} + +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////// +// simple data cache + +void AllocDataCache(void) +{ + bDataCacheHit=FALSE; // init thread cache hit flag + if(!iUseCaching) iUseDataCache=0; // security: no additinal data cache, if no caching active + if(iUseDataCache) + { + int i; + for(i=0;i=MAXDATACACHE) iPos=0;} // -> don't use that pos, use next one + lDataCacheAddr[iPos]=addr; + memcpy(pDataCacheBuf[iPos],pB, + MAXCDBUFFER-FRAMEBUFEXTRA); + iPos++; if(iPos>=MAXDATACACHE) iPos=0; +} + +///////////////////////////////////////////////////////// +// easy data cache check: loop MAXDATACACHE blocks, set ptr if addr found + +BOOL CheckDataCache(unsigned long addr) +{ + int i; + + for(i=0;i=lDataCacheAddr[i] && + addr<=(lDataCacheAddr[i]+MAXCACHEBLOCK)) + { + pCurrReadBuf=pDataCacheBuf[i]+ + ((addr-lDataCacheAddr[i])*iUsedBlockSize); + if(ppfHead) CheckPPFCache(addr,pCurrReadBuf); + return TRUE; + } + } + return FALSE; +} + +///////////////////////////////////////////////////////// + diff --git a/plugins/cdvd/CDVDpeops/read.h b/plugins/cdvd/CDVDpeops/read.h new file mode 100644 index 0000000..8d475e3 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/read.h @@ -0,0 +1,41 @@ +/*************************************************************************** + read.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void CreateREADBufs(void); +void FreeREADBufs(void); +BOOL bReadRetry(FRAMEBUF * f); +BOOL DoReadAsync(unsigned long addr); +BOOL DoRead(unsigned long addr); +DWORD WINAPI READThread(LPVOID lpParameter); +BOOL DoReadThread(unsigned long addr); +void GetREADThreadPtr(void); +DWORD WINAPI READThreadEx(LPVOID lpParameter); +BOOL DoReadThreadEx(unsigned long addr); +void GetREADThreadExPtr(void); +void AllocDataCache(void); +void FreeDataCache(void); +void AddToDataCache(unsigned long addr,unsigned char * pB); +BOOL CheckDataCache(unsigned long addr); diff --git a/plugins/cdvd/CDVDpeops/readme_1_2.txt b/plugins/cdvd/CDVDpeops/readme_1_2.txt new file mode 100644 index 0000000..1a31d5b --- /dev/null +++ b/plugins/cdvd/CDVDpeops/readme_1_2.txt @@ -0,0 +1,198 @@ +P.E.Op.S. PS2 CDVD emulation plugin +--------------------------------------------------------------------------- + +The P.E.Op.S. PS2 CDVD plugin is based on the P.E.Op.S. PSX +CDR plugin which is based on Pete's CDR ASPI/IOCTL plugin +for Windows. + +--------------------------------------------------------------------------- +Introduction - 19.11.2003 +---------------------------------------------------------------------------- + +PS2 emulation is growing. + +Oh, don't get me wrong, it will still need a lot of time until +you can really play your favourite PS2 games on the PC (ehe... +and I remember how I got flamed away nearly two years ago by +die-hard know-it-alls when I predicted that it will need at +least 'a couple of years' for 'playable' PS2 emulation). + +But yeah, it is growing. Lotsa nice guys are spending their +free time coding on PCSX2, for example. One of them is Shadow... +and he never gets tired to ask me for some PS2 plugins, ehe. + +Well, what to say? Last week I had some free time as well, +Shadow asked for a CDVD plugin, and so I got to work. I took +the P.E.Op.S. cdr sources, added the PCSX2 interface, changed +some lines of code, asked a few stupid questions (hi to +linuzappz), tested it with a few PS2 dvds and cds, and it was +done. + +Of course it's not 100% complete. There are a few (but not +important) things missing, more cd/dvd modes have to get +investigated and added, etc. But basically I hope it will +work just fine with the current PCSX2 version. So go on, +and give it a try :) + +---------------------------------------------------------------------------- + +Requirements: + +* A cdrom/dvd drive (yeah, you need a dvd drive to play dvds... + no emails please telling me that your cd drive doesn't work + correctly with dvds). +* The ASPI layer with W9x/ME +* Nothing special with W2K/WXP +* Some PS2 cds/dvds. + +---------------------------------------------------------------------------- + +Installation: + +just copy the file cdvdPeops.dll into your PCSX2 \plugins +directory, that's all. + +---------------------------------------------------------------------------- + +Configuration (similar to the P.E.Op.S. psx cdr plugin): + +You HAVE TO configure the plugin before you use +it the first time. There are only a few options +available: + +0) Interface +----------------- + +If you are using W9x/ME, you have to use the ASPI Interface. +If you are using NT/W2K/XP, you have the free choice: +ASPI (if it's installed), or IOCTL scsi commands. + +1) Drive +-------------- + +Well, that's self-explaining. Just select the drive +you want to use. "NONE" is NO drive... you have to +select a real one. + +2.) Caching +------------------------------------- + +To get more speed, there are five caching modes: +None, Read ahead, Async, Thread and Smooth. + +- 'None' is the slowest mode, but it should work on +most drives. +- 'Read ahead' will read more sectors at once, speeding up +mdecs. There is a small chance that a few drives cannot +do it, so set it to 'None', if you are having troubles. +- The 'Async mode' will do read ahead and some additional +'intelligent' asynchronous reads... that mode is recommended +with the ASPI interface, it can squeeze some more speed +out of your drive :) +- The 'Thread mode' will speed up the IOCTL interfaces, +since that ones can't do real async reading. So, when +you are using W2K/XP, and you have no ASPI installed, +try this mode for best speed. +- Some drives will have speed problems reading ps2 +cds/dvds, this caching mode will try to solve such issues. + + +Also available: an additional data cache option, which +will store up to 4 MBytes of already read sectors. This +can speed up certain games, which are re-reading the +same range of sectors again and again. + + +3.) Speed limitation +------------------------------- + +Some drives will work better (less noisy and smoother) +if you limit the drive speed. Not all drives are supporting +the "set speed" command I am using, though. +If your drive doesn't support it, a message will be displayed +on startup. There are some tools in the net which will +offer the same function, prolly for a wider range of drives, +so you can also try one of them, if the plugin speed limit fails. + + +4.) Don't wait til drive is ready +----------------------------------------------- + +By default my plugin is asking the cd/dvd drive on startup, +if its state is ready (that means: a cd is inserted and the +drive can start reading). +A few drives will not answer that question (bah, bah, bah), +and the screen will stay black... forever :) +If you are encoutering that problem, you can turn on the +"Don't wait..." option, but be warned: it can cause problems +(blue screens, for example) if the plugin starts reading and +there is a problem with the drive... + + +5.) Check drive tray state +----------------------------------------------- +PCSX2 may ask the plugin if the tray is open or closed. If +this option is turned off, the plugion always will respond +"closed". If this option is enabled, the plugin will try +to ask the drive for the tray state. Since I couldn't test +this option yet, I suggest to leave it off (and honestly, +are you able to run a multi-dvd game which needs disc +changing right now in PCSX2?) :) + + +6.) Try again on reading error +----------------------------------------------- +It might happen that your drive can't read a certain sector at +the first time, if your cd/dvd is scratched. Therefore I've added +that option, by activating it you can tell the plugin to try it +up to 10 times again before reporting the read error to the +main emu. +If you want, you can also activate some error message box, +if a sector is not readable (just to inform you something is +going wrong). + + +7.) Use PPF patches (not available yet) +--------------------------------------- + +- TODO :) + + +8.) Subchannel reading (not available yet) +------------------------------------------ + +- MAYBE TODO :) + +---------------------------------------------------------------------------- + +Conclusion: + +You never ever can escape your Shadow ;) + +For version infos read the "version.txt" file. + +And, peops, have fun! + +Pete Bernert + +---------------------------------------------------------------------------- + +P.E.Op.S. page on sourceforge: https://sourceforge.net/projects/peops/ + +P.E.Op.S. developer: + +Pete Bernert http://www.pbernert.com +Lewpy http://lewpy.psxemu.com/ +lu_zero http://brsk.virtualave.net/lu_zero/ +linuzappz http://www.pcsx.net +Darko Matesic http://mrdario.tripod.com +syo http://www.geocities.co.jp/SiliconValley-Bay/2072/ + +---------------------------------------------------------------------------- + +Disclaimer/Licence: + +This plugin is under GPL... check out the license.txt file in the /src +directory for details. + +---------------------------------------------------------------------------- diff --git a/plugins/cdvd/CDVDpeops/resource.h b/plugins/cdvd/CDVDpeops/resource.h new file mode 100644 index 0000000..3e2e235 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/resource.h @@ -0,0 +1,56 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by cdvdPeops.rc +// +#define IDD_CONFIG 101 +#define IDD_ABOUT 102 +#define IDD_SUB 104 +#define IDC_DRIVE 1000 +#define IDC_RTYPE 1001 +#define IDC_AUTO 1002 +#define IDC_CACHE 1003 +#define IDC_SPEEDLIMIT 1004 +#define IDC_SPEED 1005 +#define IDC_NOWAIT 1006 +#define IDC_RETRY 1007 +#define IDC_SHOWREADERR 1008 +#define IDC_TRYAGAIN 1009 +#define IDC_USEPPF 1010 +#define IDC_PPFFILE 1011 +#define IDC_CHOOSEFILE 1012 +#define IDC_IMODE 1013 +#define IDC_RAWTXT 1014 +#define IDC_TRAYSTATE 1014 +#define IDC_SUBCHAN0 1015 +#define IDC_SUBCHAN1 1016 +#define IDC_DATACACHE 1016 +#define IDC_SUBCHAN2 1017 +#define IDC_SUBFILE 1018 +#define IDC_CHOOSESUBF 1019 +#define IDC_CREATESUB 1020 +#define IDC_CHOOSEOUTF 1020 +#define IDC_SUBTYPE 1021 +#define IDC_SUBSTATIC 1023 +#define IDC_WAITSTATIC 1024 +#define IDC_SUBFRAME 1026 +#define IDC_SUBOUTSTATIC 1027 +#define IDC_SUBFILEEDIT 1028 +#define IDC_SUBOUTSTATIC2 1029 +#define IDC_OUTFILEEDIT 1030 +#define IDC_SUBMODE1 1031 +#define IDC_SUBMODE2 1032 +#define IDC_SUBOUTSTATIC3 1033 +#define IDC_SUBFILL 1034 +#define IDC_SUBOUTSTATIC4 1035 +#define IDC_SFSTATIC 1035 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 107 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1036 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/cdvd/CDVDpeops/scsi.h b/plugins/cdvd/CDVDpeops/scsi.h new file mode 100644 index 0000000..5a56031 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/scsi.h @@ -0,0 +1,55 @@ +/*************************************************************************** + scsi.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/28 - linuzappz +// - added GetSCSIStatus +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +int GetSCSIDevice(int iA,int iT,int iL); +int GetSCSIStatus(int iA,int iT,int iL); +DWORD GetSCSITOC(LPTOC toc); +int GetSCSICDDrives(char * pDList); +DWORD PlaySCSIAudio(unsigned long start,unsigned long len); +unsigned char * GetSCSIAudioSub(void); +BOOL TestSCSIUnitReady(void); +DWORD SetSCSISpeed(DWORD dwSpeed); +DWORD ReadSCSI_BE(BOOL bWait,FRAMEBUF * f); +DWORD ReadSCSI_BE_Sub(BOOL bWait,FRAMEBUF * f); +DWORD ReadSCSI_BE_Sub_1(BOOL bWait,FRAMEBUF * f); +DWORD InitSCSI_28_1(void); +DWORD InitSCSI_28_2(void); +DWORD DeInitSCSI_28(void); +DWORD ReadSCSI_28(BOOL bWait,FRAMEBUF * f); +DWORD ReadSCSI_28_Sub(BOOL bWait,FRAMEBUF * f); +DWORD InitSCSI_28_2048(void); +DWORD ReadSCSI_28_2048(BOOL bWait,FRAMEBUF * f); +DWORD ReadSCSI_28_2048_Ex(BOOL bWait,FRAMEBUF * f); +int ReadSub_BE_2(unsigned long addr,unsigned char * pBuf,int iNum); +int ReadSub_BE_2_1(unsigned long addr,unsigned char * pBuf,int iNum); +int ReadSub_D8(unsigned long addr,unsigned char * pBuf,int iNum); +void DecodeSub_BE_2_1(unsigned char * pBuf); +DWORD CheckSCSIReadMode(void); +DWORD ReadSCSI_Dummy(BOOL bWait,FRAMEBUF * f); + diff --git a/plugins/cdvd/CDVDpeops/scsidefs.h b/plugins/cdvd/CDVDpeops/scsidefs.h new file mode 100644 index 0000000..180b21c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/scsidefs.h @@ -0,0 +1,579 @@ +//*************************************************************************** +// +// Name: SCSIDEFS.H +// +// Description: SCSI definitions ('C' Language) +// +//*************************************************************************** + +//*************************************************************************** +// %%% TARGET STATUS VALUES %%% +//*************************************************************************** +#define STATUS_GOOD 0x00 // Status Good +#define STATUS_CHKCOND 0x02 // Check Condition +#define STATUS_CONDMET 0x04 // Condition Met +#define STATUS_BUSY 0x08 // Busy +#define STATUS_INTERM 0x10 // Intermediate +#define STATUS_INTCDMET 0x14 // Intermediate-condition met +#define STATUS_RESCONF 0x18 // Reservation conflict +#define STATUS_COMTERM 0x22 // Command Terminated +#define STATUS_QFULL 0x28 // Queue full + +//*************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//*************************************************************************** +#define MAXLUN 7 // Maximum Logical Unit Id +#define MAXTARG 7 // Maximum Target Id +#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs +#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Commands for all Device Types %%% +//*************************************************************************** +#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_COPY 0x18 // Copy (O) +#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) +#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) +#define SCSI_LOG_SELECT 0x4C // Log Select (O) +#define SCSI_LOG_SENSE 0x4D // Log Sense (O) +#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) +#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) +#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) +#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) +#define SCSI_READ_BUFF 0x3C // Read Buffer (O) +#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) +#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) +#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Direct Access Devices %%% +//*************************************************************************** +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) +#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) +#define SCSI_PREFETCH 0x34 // Prefetch (O) +#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) +#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) +#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) +#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) +#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) +#define SCSI_READ_LONG 0x3E // Read Long (O) +#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) +#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) +#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) +#define SCSI_REZERO 0x01 // Rezero Unit (O) +#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) +#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) +#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) +#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) +#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) +#define SCSI_SET_LIMIT 0x33 // Set Limits (O) +#define SCSI_START_STP 0x1B // Start/Stop Unit (O) +#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) +#define SCSI_VERIFY 0x2F // Verify (O) +#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) +#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) +#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) +#define SCSI_WRITE_LONG 0x3F // Write Long (O) +#define SCSI_WRITE_SAME 0x41 // Write Same (O) + +//*************************************************************************** +// %%% Commands Unique to Sequential Access Devices %%% +//*************************************************************************** +#define SCSI_ERASE 0x19 // Erase (MANDATORY) +#define SCSI_LOAD_UN 0x1B // Load/Unload (O) +#define SCSI_LOCATE 0x2B // Locate (O) +#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) +#define SCSI_READ_POS 0x34 // Read Position (O) +#define SCSI_READ_REV 0x0F // Read Reverse (O) +#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) +#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) +#define SCSI_REWIND 0x01 // Rewind (MANDATORY) +#define SCSI_SPACE 0x11 // Space (MANDATORY) +#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) +#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Printer Devices %%% +//*************************************************************************** +#define SCSI_PRINT 0x0A // Print (MANDATORY) +#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) +#define SCSI_STOP_PNT 0x1B // Stop Print (O) +#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Processor Devices %%% +//*************************************************************************** +#define SCSI_RECEIVE 0x08 // Receive (O) +#define SCSI_SEND 0x0A // Send (O) + +//*************************************************************************** +// %%% Commands Unique to Write-Once Devices %%% +//*************************************************************************** +#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) +#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) +#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) +#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) +#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) +#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) +#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) +#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) +#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) +#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) +#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) +#define SCSI_WRITE12 0xAA // Write 12-Byte (O) +#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) +#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) + +//*************************************************************************** +// %%% Commands Unique to CD-ROM Devices %%% +//*************************************************************************** +#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) +#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) +#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) +#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) +#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) +#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) +#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) +#define SCSI_READHEADER 0x44 // Read Header (O) +#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) +#define SCSI_READ_TOC 0x43 // Read TOC (O) + +//*************************************************************************** +// %%% Commands Unique to Scanner Devices %%% +//*************************************************************************** +#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) +#define SCSI_GETWINDOW 0x25 // Get Window (O) +#define SCSI_OBJECTPOS 0x31 // Object Postion (O) +#define SCSI_SCAN 0x1B // Scan (O) +#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Optical Memory Devices %%% +//*************************************************************************** +#define SCSI_UpdateBlk 0x3D // Update Block (O) + +//*************************************************************************** +// %%% Commands Unique to Medium Changer Devices %%% +//*************************************************************************** +#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) +#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) +#define SCSI_POSTOELEM 0x2B // Position to Element (O) +#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) +#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) + +//*************************************************************************** +// %%% Commands Unique to Communication Devices %%% +//*************************************************************************** +#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) +#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) +#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) +#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) +#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) +#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% END OF SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Request Sense Data Format %%% +//*************************************************************************** +typedef struct { + + BYTE ErrorCode; // Error Code (70H or 71H) + BYTE SegmentNum; // Number of current segment descriptor + BYTE SenseKey; // Sense Key(See bit definitions too) + BYTE InfoByte0; // Information MSB + BYTE InfoByte1; // Information MID + BYTE InfoByte2; // Information MID + BYTE InfoByte3; // Information LSB + BYTE AddSenLen; // Additional Sense Length + BYTE ComSpecInf0; // Command Specific Information MSB + BYTE ComSpecInf1; // Command Specific Information MID + BYTE ComSpecInf2; // Command Specific Information MID + BYTE ComSpecInf3; // Command Specific Information LSB + BYTE AddSenseCode; // Additional Sense Code + BYTE AddSenQual; // Additional Sense Code Qualifier + BYTE FieldRepUCode; // Field Replaceable Unit Code + BYTE SenKeySpec15; // Sense Key Specific 15th byte + BYTE SenKeySpec16; // Sense Key Specific 16th byte + BYTE SenKeySpec17; // Sense Key Specific 17th byte + BYTE AddSenseBytes; // Additional Sense Bytes + +} SENSE_DATA_FMT; + +//*************************************************************************** +// %%% REQUEST SENSE ERROR CODE %%% +//*************************************************************************** +#define SERROR_CURRENT 0x70 // Current Errors +#define SERROR_DEFERED 0x71 // Deferred Errors + +//*************************************************************************** +// %%% REQUEST SENSE BIT DEFINITIONS %%% +//*************************************************************************** +#define SENSE_VALID 0x80 // Byte 0 Bit 7 +#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 +#define SENSE_EOM 0x40 // Byte 2 Bit 6 +#define SENSE_ILI 0x20 // Byte 2 Bit 5 + +//*************************************************************************** +// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% +//*************************************************************************** +#define KEY_NOSENSE 0x00 // No Sense +#define KEY_RECERROR 0x01 // Recovered Error +#define KEY_NOTREADY 0x02 // Not Ready +#define KEY_MEDIUMERR 0x03 // Medium Error +#define KEY_HARDERROR 0x04 // Hardware Error +#define KEY_ILLGLREQ 0x05 // Illegal Request +#define KEY_UNITATT 0x06 // Unit Attention +#define KEY_DATAPROT 0x07 // Data Protect +#define KEY_BLANKCHK 0x08 // Blank Check +#define KEY_VENDSPEC 0x09 // Vendor Specific +#define KEY_COPYABORT 0x0A // Copy Abort +#define KEY_EQUAL 0x0C // Equal (Search) +#define KEY_VOLOVRFLW 0x0D // Volume Overflow +#define KEY_MISCOMP 0x0E // Miscompare (Search) +#define KEY_RESERVED 0x0F // Reserved + +//*************************************************************************** +// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% +//*************************************************************************** +#define DTYPE_DASD 0x00 // Disk Device +#define DTYPE_SEQD 0x01 // Tape Device +#define DTYPE_PRNT 0x02 // Printer +#define DTYPE_PROC 0x03 // Processor +#define DTYPE_WORM 0x04 // Write-once read-multiple +#define DTYPE_CROM 0x05 // CD-ROM device +#define DTYPE_CDROM 0x05 // CD-ROM device +#define DTYPE_SCAN 0x06 // Scanner device +#define DTYPE_OPTI 0x07 // Optical memory device +#define DTYPE_JUKE 0x08 // Medium Changer device +#define DTYPE_COMM 0x09 // Communications device +#define DTYPE_RESL 0x0A // Reserved (low) +#define DTYPE_RESH 0x1E // Reserved (high) +#define DTYPE_UNKNOWN 0x1F // Unknown or no device type + +//*************************************************************************** +// %%% ANSI APPROVED VERSION DEFINITIONS %%% +//*************************************************************************** +#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand +#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) +#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 +#define ANSI_RESLO 0x3 // Reserved (low) +#define ANSI_RESHI 0x7 // Reserved (high) + + +//////////////////////////////////////////////////////////////// + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + + +typedef struct { + SCSI_PASS_THROUGH spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; + UCHAR ucDataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; + + +typedef struct { + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; +} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; + + + +typedef struct { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +} SCSI_BUS_DATA, *PSCSI_BUS_DATA; + + +typedef struct { + UCHAR NumberOfBusses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + + +typedef struct { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + + +typedef struct { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + + +/* + * method codes + */ +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +/* + * file access values + */ +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS (0x0001) +#define FILE_WRITE_ACCESS (0x0002) + + +#define IOCTL_SCSI_BASE 0x00000004 + +/* + * constants for DataIn member of SCSI_PASS_THROUGH* structures + */ +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +/* + * Standard IOCTL define + */ +#define CTL_CODE( DevType, Function, Method, Access ) ( \ + ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) + +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) + +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE + +#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define FILE_DEVICE_CD_ROM 0x00000002 +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + +// +// CD ROM Sub-Q Channel Data Format +// + +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval : 1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + + +// IOCTL_DISK_SET_CACHE allows the caller to get or set the state of the disk +// read/write caches. +// +// If the structure is provided as the input buffer for the ioctl the read & +// write caches will be enabled or disabled depending on the parameters +// provided. +// +// If the structure is provided as an output buffer for the ioctl the state +// of the read & write caches will be returned. If both input and outut buffers +// are provided the output buffer will contain the cache state BEFORE any +// changes are made + + +typedef enum { + EqualPriority, + KeepPrefetchedData, + KeepReadData +} DISK_CACHE_RETENTION_PRIORITY; + +#define FILE_DEVICE_DISK 0x00000007 +#define IOCTL_DISK_BASE FILE_DEVICE_DISK +#define IOCTL_DISK_GET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0035, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_SET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0036, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +typedef struct _DISK_CACHE_INFORMATION { + + // + // on return indicates that the device is capable of saving any parameters + // in non-volatile storage. On send indicates that the device should + // save the state in non-volatile storage. + // + + BOOLEAN ParametersSavable; + + // + // Indicates whether the write and read caches are enabled. + // + + BOOLEAN ReadCacheEnabled; + BOOLEAN WriteCacheEnabled; + + // + // Controls the likelyhood of data remaining in the cache depending on how + // it got there. Data cached from a READ or WRITE operation may be given + // higher, lower or equal priority to data entered into the cache for other + // means (like prefetch) + // + + DISK_CACHE_RETENTION_PRIORITY ReadRetentionPriority; + DISK_CACHE_RETENTION_PRIORITY WriteRetentionPriority; + + // + // Requests for a larger number of blocks than this may have prefetching + // disabled. If this value is set to 0 prefetch will be disabled. + // + + USHORT DisablePrefetchTransferLength; + + // + // If TRUE then ScalarPrefetch (below) will be valid. If FALSE then + // the minimum and maximum values should be treated as a block count + // (BlockPrefetch) + // + + BOOLEAN PrefetchScalar; + + // + // Contains the minimum and maximum amount of data which will be + // will be prefetched into the cache on a disk operation. This value + // may either be a scalar multiplier of the transfer length of the request, + // or an abolute number of disk blocks. PrefetchScalar (above) indicates + // which interpretation is used. + // + + union { + struct { + USHORT Minimum; + USHORT Maximum; + + // + // The maximum number of blocks which will be prefetched - useful + // with the scalar limits to set definite upper limits. + // + + USHORT MaximumBlocks; + } ScalarPrefetch; + + struct { + USHORT Minimum; + USHORT Maximum; + } BlockPrefetch; + }; + +} DISK_CACHE_INFORMATION, *PDISK_CACHE_INFORMATION; + diff --git a/plugins/cdvd/CDVDpeops/sub.c b/plugins/cdvd/CDVDpeops/sub.c new file mode 100644 index 0000000..073ecf7 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/sub.c @@ -0,0 +1,321 @@ +/*************************************************************************** + sub.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_SUB +#include "externals.h" + +/* TODO (#1#): SUB CHANNEL STUFF */ + +///////////////////////////////////////////////////////// + +unsigned char * pCurrSubBuf=NULL; // ptr to emu sub data (or NULL) +int iUseSubReading=0; // subdata support (by file or directly) +char szSUBF[260]; // sub file name +SUB_CACHE * subCache=NULL; // cache memory +SUB_DATA * subHead=NULL; +int iSUBNum=0; // number of subdata cached +unsigned char SubCData[96]; // global data subc buffer +unsigned char SubAData[96]; // global audio subc buffer + +///////////////////////////////////////////////////////// + +void BuildSUBCache(void) +{ + FILE * subfile; + unsigned char buffer[16], * p; + SUB_DATA * plast=NULL,* px; + + if(iUseSubReading) // some subreading wanted? + { + if(iUseSubReading==1) iUseCaching=0; // -> direct read? no caching done, only 1 sector reads + memset(SubCData,0,96); // -> init subc + pCurrSubBuf=SubCData; // -> set global ptr + } + else // no plugin subreading? + { + pCurrSubBuf=NULL; // -> return NULL as subc buffer to emu + } + + memset(SubAData,0,96); // init audio subc buffer + + if(iUseSubReading!=2) return; // no subfile wanted? + if(szSUBF[0]==0) return; // no filename given? + + subfile=fopen(szSUBF, "rb"); // open subfile + if(subfile==0) + { + MessageBox(NULL,"No SBI/M3S file found!",libraryName,MB_OK); + return; + } + + memset(buffer,0,5); // read header + fread(buffer, 4, 1, subfile); + + iSUBNum=0;subHead=NULL; + + if(strcmp((char *)buffer,"SBI")==0) // ah, SBI file + { + while(fread(buffer, 4, 1, subfile)==1) // -> read record header + { + iSUBNum++; // -> one more sub cache block + px=(SUB_DATA *)malloc(sizeof(SUB_DATA)); // -> get cache buff +//!!!!!!!!!!!!!!!!!!!!!!!!!!!! // -> and fill it... + +/* TODO (#1#): addr2time subchannel */ + + + px->addr=time2addrB(buffer); + + px->pNext=NULL; + + px->subq[0]=0x41; + px->subq[1]=0x01; + px->subq[2]=0x01; + p=&px->subq[3]; + addr2timeB(px->addr,p); + px->subq[6]=0x00; + p=&px->subq[7]; + addr2timeB(px->addr+150,p); + + if(buffer[3]==1) + { + fread(px->subq,10, 1, subfile); + } + else if(buffer[3]==2) + { + fread(&px->subq[3],3, 1, subfile); + } + else if(buffer[3]==3) + { + fread(&px->subq[7],3, 1, subfile); + } + + if(plast==NULL) // add new cache block to linked list + { + plast=subHead=px; + } + else + { + plast->pNext=px;plast=px; + } + } + } + else // M3S file? + { // -> read data, and store all + unsigned char min,sec,frame,xmin,xsec,xframe; // -> subs which are different from + BOOL b1,b2,goon=TRUE;int iNum=0; // -> the expected calculated values + + xmin=2; + xsec=58; + xframe=0; + min=3; + sec=0; + frame=0; + + fread(buffer+4, 12, 1, subfile); + do + { + if(itod(min) != buffer[7]|| + itod(sec) != buffer[8]|| + itod(frame) != buffer[9]) + b1=TRUE; else b1=FALSE; + + if(itod(xmin) != buffer[3]|| + itod(xsec) != buffer[4]|| + itod(xframe) != buffer[5]) + b2=TRUE; else b2=FALSE; + + if(buffer[1]!=1) b1=b2=TRUE; + if(buffer[2]!=1) b1=b2=TRUE; + + if(b1 || b2) + { + iSUBNum++; + px=(SUB_DATA *)malloc(sizeof(SUB_DATA)); + px->pNext=NULL; + memcpy(px->subq,buffer,10); + buffer[7]=itod(min); + buffer[8]=itod(sec); + buffer[9]=itod(frame); +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + px->addr=time2addrB(&buffer[7]); + + if(plast==NULL) + {plast=subHead=px;} + else {plast->pNext=px;plast=px;} + } + + xframe=xframe+1; + if(xframe>74) + { + xsec+=1; + xframe-=75; + if(xsec>59) + { + xmin+=1; + xsec-=60; + if(xmin>99) + { + goon=FALSE; + } + } + } + + frame=frame+1; + if(frame>74) + { + sec+=1; + frame-=75; + if(sec>59) + { + min+=1; + sec-=60; + if(min>99) + { + goon=FALSE; + } + } + } + iNum++; + if(iNum>(60*75)) goon=FALSE; + } + while(goon && (fread(buffer, 16, 1, subfile)==1)); + + if(iNum!=(60*75)) goon=FALSE; + else + if(iSUBNum==(60*75)) goon=FALSE; + + if(!goon) + { + MessageBox(NULL,"Bad SBI/M3S file!",libraryName,MB_OK); + fclose(subfile); + FreeSUBCache(); + return; + } + } + + subCache=NULL; + if(iSUBNum) // something in cache? + { // -> create an array with the used addresses, for fast searching access + SUB_CACHE * psc;int i; + subCache=(SUB_CACHE *)malloc(iSUBNum*sizeof(SUB_CACHE)); + psc=subCache;px=subHead; + for(i=0;ipNext) + { + psc->addr = px->addr; + psc->pNext = (void *)px; + } + iSUBNum--; + } + + fclose(subfile); +} + +///////////////////////////////////////////////////////// +// func for calculating 'right' subdata + +void FakeSubData(unsigned long adr) +{ + SubCData[12]=0x41; + SubCData[13]=0x01; + SubCData[14]=0x01; + + /* TODO (#1#): addr2time fake sub data + */ + + +//!!!!!!!!!!!!!!!!!!!!!!!???? + addr2timeB(adr, &SubCData[15]); +// SubCData[18]=0x00; + addr2timeB(adr+150,&SubCData[19]); +} + +///////////////////////////////////////////////////////// +// check, if for a given addr we have special subdata in cache + +void CheckSUBCache(long addr) +{ + SUB_CACHE * pcstart, * pcend, * pcpos; + + pcstart=subCache; // ptrs to address arrays (start/end) + pcend =subCache+iSUBNum; + + if(addr>=pcstart->addr && // easy check, if given addr is between start/end + addr<=pcend->addr) + { + while(1) // now search for sub + { + if(addr==pcend->addr) {pcpos=pcend;break;} // got it! break + + pcpos=pcstart+(pcend-pcstart)/2; // get the 'middle' address + if(pcpos==pcstart) break; // no more checks can be done + if(addraddr) // look further... + { + pcend=pcpos; + continue; + } + if(addr>pcpos->addr) + { + pcstart=pcpos; + continue; + } + break; + } + + if(addr==pcpos->addr) // found some cached data? + { + SUB_DATA * p=(SUB_DATA *)pcpos->pNext; // -> ptr to data + memcpy(&SubCData[12],p->subq,10); // -> get the data + return; // -> done + } + } + + FakeSubData(addr); // no subcdata avail, so fake right one +} + +///////////////////////////////////////////////////////// +// free all sub cache bufs + +void FreeSUBCache(void) +{ + SUB_DATA * p=subHead; + void * pn; + while(p) + { + pn=p->pNext; + free(p); + p=(SUB_DATA *)pn; + } + subHead=NULL; + + if(subCache) free(subCache); + subCache=NULL; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/sub.h b/plugins/cdvd/CDVDpeops/sub.h new file mode 100644 index 0000000..50aa7d6 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/sub.h @@ -0,0 +1,30 @@ +/*************************************************************************** + sub.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void BuildSUBCache(void); +void FakeSubData(unsigned long adr); +void CheckSUBCache(long addr); +void FreeSUBCache(void); diff --git a/plugins/cdvd/CDVDpeops/toc.c b/plugins/cdvd/CDVDpeops/toc.c new file mode 100644 index 0000000..a7e23f9 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/toc.c @@ -0,0 +1,105 @@ +/*************************************************************************** + toc.c - description + ------------------- + begin : Sun Nov 16 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/11/16 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////// + +#include "stdafx.h" +#define _IN_TOC +#include "externals.h" + +///////////////////////////////////////////////////////// + +TOC sTOC; + +///////////////////////////////////////////////////////// +// read toc + + +void ReadTOC(void) +{ + unsigned char xbuffer[4];DWORD dwStatus; + + LockGenCDAccess(); + + memset(&(sTOC),0,sizeof(sTOC)); // init toc infos + + dwStatus=GetSCSITOC((LPTOC)&sTOC); // get toc by scsi... may change that for ioctrl in xp/2k? + + UnlockGenCDAccess(); + + if(dwStatus!=SS_COMP) return; + +#ifdef DBGOUT + auxprintf("TOC Last %d, max %08x,%08x\n",sTOC.cLastTrack,sTOC.tracks[sTOC.cLastTrack].lAddr,reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr)); +#endif + // re-order it to psemu pro standards + addr2time(reOrder(sTOC.tracks[sTOC.cLastTrack].lAddr),xbuffer); + +#ifdef DBGOUT + auxprintf("TOC %d, %d, %d, %d\n", + xbuffer[0],xbuffer[1],xbuffer[2],xbuffer[3] ); +#endif + + xbuffer[0]=itob(xbuffer[0]); + xbuffer[1]=itob(xbuffer[1]); + xbuffer[2]=itob(xbuffer[2]); + xbuffer[3]=itob(xbuffer[3]); + lMaxAddr=time2addrB(xbuffer); // get max data adr +} + +///////////////////////////////////////////////////////// +// get the highest address of first (=data) track + +unsigned long GetLastTrack1Addr(void) +{ + unsigned char xbuffer[4];DWORD dwStatus; + unsigned long lmax; + TOC xTOC; + + LockGenCDAccess(); + + memset(&(xTOC),0,sizeof(xTOC)); + + dwStatus=GetSCSITOC((LPTOC)&xTOC); + + UnlockGenCDAccess(); + + if(dwStatus!=SS_COMP) return 0; + + addr2time(reOrder(xTOC.tracks[1].lAddr),xbuffer); + + xbuffer[0]=itob(xbuffer[0]); + xbuffer[1]=itob(xbuffer[1]); + xbuffer[2]=itob(xbuffer[2]); + xbuffer[3]=itob(xbuffer[3]); + + lmax=time2addrB(xbuffer); + if(lmax<150) return 0; + + return lmax-150; +} + +///////////////////////////////////////////////////////// diff --git a/plugins/cdvd/CDVDpeops/toc.h b/plugins/cdvd/CDVDpeops/toc.h new file mode 100644 index 0000000..03d31c3 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/toc.h @@ -0,0 +1,28 @@ +/*************************************************************************** + toc.h - description + ------------------- + begin : Wed Sep 18 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/09/19 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void ReadTOC(void); +unsigned long GetLastTrack1Addr(void); diff --git a/plugins/cdvd/CDVDpeops/version_1_2.txt b/plugins/cdvd/CDVDpeops/version_1_2.txt new file mode 100644 index 0000000..560e71c --- /dev/null +++ b/plugins/cdvd/CDVDpeops/version_1_2.txt @@ -0,0 +1,61 @@ +-------------------------------------------------------------------------- +25. December, 2004 Version 1.2 + +- The plugin is tested with PCSX2 0.7! + +- I've repaired a stupid bug concerning calculating the track sizes. + +- I've added an hack for big DVDs (fake minute info in the CDVDgetTD + function). + + +-------------------------------------------------------------------------- +29. March, 2004 Version 1.1 + +- Ah, to make it short: I've got some times this weekend, tried the + PCSX2 0.6 version, noticed that my relatively new Plextor PX-708A + drive didn't work with the P.E.Op.S. dvd plugin, and therefore + added a new good working reading mode. + + So, if you had just some error message like 'unable to open dvd + plugin' with PCSX2 and the P.E.Op.S. dvd plugin in the past, chances + are high that this version will now give better results on your + system. At least I was able to see the first intro screens of some + games without problems :) + + +-------------------------------------------------------------------------- + +19. November, 2003 Version 1.0 + +- What to say? Blame Shadow of the PCSX2 team... he wanted + a PS2 CDVD plugin from me, and he didn't give up asking until + I made one, sigh ;) + + Ok, I have done this plugin using my old P.E.Op.S. PSX cdr + plugin sources, so you will notice some similaries, of course. + + This plugin is able to play PS2 CDs and PS2 DVDs in your + PC's CD/DVD drives, and since all the old P.E.Op.S. cdr read + caching modes are available, the speed should be fine as well. + + For the plugin settings, check out the included readme file + (but if you are familar with the P.E.Op.S. cdr config, you + will not have much troubles... the new plugin's config is even + easier to use, since you don't have to specify a read method). + + I cannot say much about compatibility (since I did the plugin + in a few hours last weekend, and I only have a Liteon DVD drive + for tests available right now), but I think it's free of major + bugs, so feel free to try it. + + Some stuff is not available right now: PPF support and subchannel + reading, for example (but both are not very important at the + moment, imho). + + The sources of the plugin (license: GPL) can be found on the + P.E.Op.S. site on sourceforge, I've added a MS VisualStudio 6 + project file, as well as a Bloodshed Dev-C++ one (you will + also need NASM for this one). + + Ok, have fun :) diff --git a/plugins/cdvd/CDVDpeops/wnaspi32.h b/plugins/cdvd/CDVDpeops/wnaspi32.h new file mode 100644 index 0000000..fabc0f3 --- /dev/null +++ b/plugins/cdvd/CDVDpeops/wnaspi32.h @@ -0,0 +1,354 @@ +/****************************************************************************** +** +** Module Name: wnaspi32.h +** +** Description: Header file for ASPI for Win32. This header includes +** macro and type declarations, and can be included without +** modification when using Borland C++ or Microsoft Visual +** C++ with 32-bit compilation. If you are using a different +** compiler then you MUST ensure that structures are packed +** onto byte alignments, and that C++ name mangling is turned +** off. +** +** Notes: This file created using 4 spaces per tab. +** +******************************************************************************/ + +#ifndef __WNASPI32_H__ +#define __WNASPI32_H__ + +/* +** Make sure structures are packed and undecorated. +*/ + +#ifdef __BORLANDC__ +#pragma option -a1 +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack(1) +#endif //__MSC_VER + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//***************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//***************************************************************************** + +#define SENSE_LEN 14 // Default sense buffer length +#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI +#define SRB_POSTING 0x01 // Enable ASPI posting +#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count reporting +#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host +#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI target +#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI event notification + +#define RESIDUAL_COUNT_SUPPORTED 0x02 // Extended buffer flag +#define MAX_SRB_TIMEOUT 108000lu // 30 hour maximum timeout in s +#define DEFAULT_SRB_TIMEOUT 108000lu // Max timeout by default + + +//***************************************************************************** +// %%% ASPI Command Definitions %%% +//***************************************************************************** + +#define SC_HA_INQUIRY 0x00 // Host adapter inquiry +#define SC_GET_DEV_TYPE 0x01 // Get device type +#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command +#define SC_ABORT_SRB 0x03 // Abort an SRB +#define SC_RESET_DEV 0x04 // SCSI bus device reset +#define SC_SET_HA_PARMS 0x05 // Set HA parameters +#define SC_GET_DISK_INFO 0x06 // Get Disk information +#define SC_RESCAN_SCSI_BUS 0x07 // ReBuild SCSI device map +#define SC_GETSET_TIMEOUTS 0x08 // Get/Set target timeouts + +//***************************************************************************** +// %%% SRB Status %%% +//***************************************************************************** + +#define SS_PENDING 0x00 // SRB being processed +#define SS_COMP 0x01 // SRB completed without error +#define SS_ABORTED 0x02 // SRB aborted +#define SS_ABORT_FAIL 0x03 // Unable to abort SRB +#define SS_ERR 0x04 // SRB completed with error + +#define SS_INVALID_CMD 0x80 // Invalid ASPI command +#define SS_INVALID_HA 0x81 // Invalid host adapter number +#define SS_NO_DEVICE 0x82 // SCSI device not installed + +#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB +#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Windows +#define SS_BUFFER_ALIGN 0xE1 // Buffer not aligned (replaces OLD_MANAGER in Win32) +#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode +#define SS_NO_ASPI 0xE3 // No ASPI managers resident +#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init +#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute cmd +#define SS_BUFFER_TO_BIG 0xE6 // Buffer size to big to handle! +#define SS_MISMATCHED_COMPONENTS 0xE7 // The DLLs/EXEs of ASPI don't version check +#define SS_NO_ADAPTERS 0xE8 // No host adapters to manage +#define SS_INSUFFICIENT_RESOURCES 0xE9 // Couldn't allocate resources needed to init +#define SS_ASPI_IS_SHUTDOWN 0xEA // Call came to ASPI after PROCESS_DETACH +#define SS_BAD_INSTALL 0xEB // The DLL or other components are installed wrong + +//***************************************************************************** +// %%% Host Adapter Status %%% +//***************************************************************************** + +#define HASTAT_OK 0x00 // Host adapter did not detect an // error +#define HASTAT_SEL_TO 0x11 // Selection Timeout +#define HASTAT_DO_DU 0x12 // Data overrun data underrun +#define HASTAT_BUS_FREE 0x13 // Unexpected bus free +#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence // failure +#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was waiting to beprocessed. +#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. +#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the // adapter received a MESSAGE +#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. +#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. +#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing + +//***************************************************************************** +// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY (0) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_HA_INQUIRY + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE HA_Count; // 08/008 Number of host adapters present + BYTE HA_SCSI_ID; // 09/009 SCSI ID of host adapter + BYTE HA_ManagerId[16]; // 0A/010 String describing the manager + BYTE HA_Identifier[16]; // 1A/026 String describing the host adapter + BYTE HA_Unique[16]; // 2A/042 Host Adapter Unique parameters + WORD HA_Rsvd1; // 3A/058 Reserved, MUST = 0 +} +SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; + +//***************************************************************************** +// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) %%% +//***************************************************************************** + +typedef struct +{ + BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE */ + BYTE SRB_Status; /* 01/001 ASPI command status byte */ + BYTE SRB_HaID; /* 02/002 ASPI host adapter number */ + BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ + DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ + BYTE SRB_Target; /* 08/008 Target's SCSI ID */ + BYTE SRB_Lun; /* 09/009 Target's LUN number */ + BYTE SRB_DeviceType; /* 0a/010 Target's peripheral device type */ + BYTE SRB_Rsvd1; /* 0b/011 Reserved, must = 0 */ + BYTE pad[68]; +} SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; + +//***************************************************************************** +// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_EXEC_SCSI_CMD + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + WORD SRB_Rsvd1; // 0A/010 Reserved for Alignment + DWORD SRB_BufLen; // 0C/012 Data Allocation Length + BYTE FAR *SRB_BufPointer; // 10/016 Data Buffer Pointer + BYTE SRB_SenseLen; // 14/020 Sense Allocation Length + BYTE SRB_CDBLen; // 15/021 CDB Length + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[20]; // 1C/028 Reserved, MUST = 0 + BYTE CDBByte[16]; // 30/048 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 50/064 Request Sense buffer +} +SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; + +//***************************************************************************** +// %%% SRB - ABORT AN SRB - SC_ABORT_SRB (3) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_ABORT_SRB + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + VOID FAR *SRB_ToAbort; // 08/008 Pointer to SRB to abort +} +SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; + +//***************************************************************************** +// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV (4) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESET_DEV + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_Rsvd1[12]; // 0A/010 Reserved for Alignment + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[36]; // 1C/028 Reserved, MUST = 0 +} +SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; + +//***************************************************************************** +// %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DISK_INFO + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_DriveFlags; // 0A/010 Driver flags + BYTE SRB_Int13HDriveInfo; // 0B/011 Host Adapter Status + BYTE SRB_Heads; // 0C/012 Preferred number of heads translation + BYTE SRB_Sectors; // 0D/013 Preferred number of sectors translation + BYTE SRB_Rsvd1[10]; // 0E/014 Reserved, MUST = 0 +} +SRB_GetDiskInfo, *PSRB_GetDiskInfo, FAR *LPSRB_GetDiskInfo; + +//***************************************************************************** +// %%% SRB - RESCAN SCSI BUS(ES) ON SCSIPORT %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESCAN_SCSI_BUS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 +} +SRB_RescanPort, *PSRB_RescanPort, FAR *LPSRB_RescanPort; + +//***************************************************************************** +// %%% SRB - GET/SET TARGET TIMEOUTS %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GETSET_TIMEOUTS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + DWORD SRB_Timeout; // 0A/010 Timeout in half seconds +} +SRB_GetSetTimeouts, *PSRB_GetSetTimeouts, FAR *LPSRB_GetSetTimeouts; + +//***************************************************************************** +// %%% ASPIBUFF - Structure For Controllng I/O Buffers %%% +//***************************************************************************** + +typedef struct tag_ASPI32BUFF // Offset +{ // HX/DEC + PBYTE AB_BufPointer; // 00/000 Pointer to the ASPI allocated buffer + DWORD AB_BufLen; // 04/004 Length in bytes of the buffer + DWORD AB_ZeroFill; // 08/008 Flag set to 1 if buffer should be zeroed + DWORD AB_Reserved; // 0C/012 Reserved +} +ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; + +//***************************************************************************** +// %%% TOC structures %%% +//***************************************************************************** + +typedef struct +{ + unsigned char reserved1; + unsigned char cAdrCtrl; + unsigned char cTrackNum; + unsigned char reserved2; + unsigned long lAddr; +} TOC_TRACK; + +typedef struct +{ + unsigned short usTocDataLen; + unsigned char cFirstTrack; + unsigned char cLastTrack; + TOC_TRACK tracks[100]; +} TOC, *PTOC, FAR *LPTOC; + +//***************************************************************************** +// %%% PROTOTYPES - User Callable ASPI for Win32 Functions %%% +//***************************************************************************** + +typedef struct +{ + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaId; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; +} SRB, *PSRB, FAR *LPSRB; + + +#if defined(__BORLANDC__) + +DWORD _import GetASPI32SupportInfo( void ); +DWORD _import SendASPI32Command( LPSRB ); +BOOL _import GetASPI32Buffer( PASPI32BUFF ); +BOOL _import FreeASPI32Buffer( PASPI32BUFF ); +BOOL _import TranslateASPI32Address( PDWORD, PDWORD ); + +#elif defined(_MSC_VER) + +__declspec(dllimport) DWORD GetASPI32SupportInfo( void ); +__declspec(dllimport) DWORD SendASPI32Command( LPSRB ); +__declspec(dllimport) BOOL GetASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL FreeASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#else + +extern DWORD GetASPI32SupportInfo( void ); +extern DWORD GetASPI32Command( LPSRB ); +extern BOOL GetASPI32Buffer( PASPI32BUFF ); +extern BOOL FreeASPI32Buffer( PASPI32BUFF ); +extern BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#endif + +/* +** Restore compiler default packing and close off the C declarations. +*/ + +#ifdef __BORLANDC__ +#pragma option -a. +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack() +#endif //_MSC_VER + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__WNASPI32_H__ diff --git a/plugins/cdvd/build.sh b/plugins/cdvd/build.sh new file mode 100644 index 0000000..d601339 --- /dev/null +++ b/plugins/cdvd/build.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +echo ------------------------ +echo Building CDVD plugins... +echo ------------------------ + +curdir=`pwd` + +cd ${curdir}/CDVDiso +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/CDVDisoEFP +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/CDVDlinuz +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/CDVDnull +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi diff --git a/plugins/dev9/DEV9linuz/DEV9.c b/plugins/dev9/DEV9linuz/DEV9.c new file mode 100644 index 0000000..19f0e0a --- /dev/null +++ b/plugins/dev9/DEV9linuz/DEV9.c @@ -0,0 +1,1267 @@ +#include +#include +#include +#include + +#include "DEV9.h" +#include "socks.h" +#include "Config.h" + +#ifdef __WIN32__ +#pragma warning(disable:4244) + +HINSTANCE hInst=NULL; +#endif + +//#define HDD_48BIT + +const u8 eeprom[] = { + 0x00, // MAC ADDR: 00:0A:E6:71:55:34 +/* 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, + 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10,*/ + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +char ata_cmds[256][256]; +void (*ata_cmdf[256])(int irq); + +#define INIT_ATA_CMD(num, name, func) \ + strcpy(ata_cmds[num], name); \ + ata_cmdf[num] = func; + +void ata_unknown(int irq); +void ata_nop(int irq); +void ata_recalibrate(int irq); +void ata_readsec(int irq); +void ata_readdma(int irq); +void ata_readdma_ext(int irq); +void ata_writedma(int irq); +void ata_writedma_ext(int irq); +void ata_specify(int irq); +void ata_flushcache(int irq); +void ata_identify(int irq); +void ata_pidentify(int irq); +void ata_setidle(int irq); +void ata_setfeatures(int irq); +void ata_smart(int irq); +void ata_specify(int irq); + +int Log = 1; + +const unsigned char version = PS2E_DEV9_VERSION; +const unsigned char revision = 0; +const unsigned char build = 2; // increase that with each version + +static char *libraryName = "DEV9linuz Driver"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_DEV9; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + +// if (!Log) return; + + va_start(list, fmt); + vfprintf(dev9Log, fmt, list); + va_end(list); +} + +#ifdef __WIN32__ +void _set_sparse(void *handle) { + DWORD bytes=0; + printf("%d\n", DeviceIoControl(handle, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytes, NULL)); + printf("%d\n", GetLastError()); +} + +static void *_openfile(const char *filename, int flags) { + void *ret; +// printf("_openfile %s: %d;%d\n", filename, flags & O_RDONLY, flags & O_RDWR); + if (flags & O_RDWR) { + ret = CreateFile(filename, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (ret == INVALID_HANDLE_VALUE) { + ret = CreateFile(filename, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL); + if (ret == INVALID_HANDLE_VALUE) return NULL; + } + } else + if (flags & O_WRONLY) { + ret = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + if (ret == INVALID_HANDLE_VALUE) return NULL; + } else { + ret = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (ret == INVALID_HANDLE_VALUE) return NULL; + } + _set_sparse(ret); + return ret; +} + +static u64 _tellfile(void *handle) { + u64 ofs; + u32 *_ofs = (u32*)&ofs; + _ofs[1] = 0; + _ofs[0] = SetFilePointer(handle, 0, &_ofs[1], FILE_CURRENT); + DEV9_LOG("_tellfile %p, %x_%x\n", handle, _ofs[1], _ofs[0]); + return ofs; +} + +static int _seekfile(void *handle, u64 offset) { + u64 ofs = (u64)offset; + u32 *_ofs = (u32*)&ofs; + DEV9_LOG("_seekfile %p, %x_%x\n", handle, _ofs[1], _ofs[0]); + SetFilePointer(handle, _ofs[0], &_ofs[1], FILE_BEGIN); + return 0; +} +/* +static void dump(u8 *ptr, int size) { + int i; + DEV9_LOG("dump: "); + for (i=0; ir_status&= ~ATA_STAT_BUSY; + ata_cmdf[dev9.atacmd](1); + } + dev9Ru16(SPD_R_INTR_STAT)|= dev9.irqcause; +#ifdef DEV9_LOG + DEV9_LOG("_DEV9irqHandler %x, %x\n", dev9Ru16(SPD_R_INTR_STAT), dev9Ru16(SPD_R_INTR_MASK)); +#endif + if (dev9Ru16(SPD_R_INTR_STAT) & dev9Ru16(SPD_R_INTR_MASK)) return 1; + return 0; +} + +DEV9handler CALLBACK DEV9irqHandler(void) { + return (DEV9handler)_DEV9irqHandler; +} + +void _DEV9irq(int cause, int cycles) { +#ifdef DEV9_LOG + DEV9_LOG("_DEV9irq %x, %x\n", cause, dev9Ru16(SPD_R_INTR_MASK)); +#endif + + dev9.irqcause|= cause; + DEV9irq(cycles); +} + + +u8 CALLBACK DEV9read8(u32 addr) { + u8 hard; + + switch (addr) { + case SPD_R_PIO_DATA: + hard = dev9.eeprom[dev9.eeprompos++]; + break; + + case DEV9_R_REV: + hard = 0x30; // expansion bay + break; + + case ATA_R_CONTROL: + case ATA_R_STATUS: + case ATA_R_NSECTOR: + return DEV9read16(addr); + + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u8)FLASHread32(addr, 1); + } + + hard = dev9Ru8(addr); +#ifdef DEV9_LOG + DEV9_LOG("*Unknown 8bit read at address %lx value %x\n", addr, hard); +#endif + return hard; + } + +#ifdef DEV9_LOG + DEV9_LOG("*Known 8bit read at address %lx value %x\n", addr, hard); +#endif + return hard; +} + +u16 CALLBACK DEV9read16(u32 addr) { + u16 hard; + + switch (addr) { +#ifdef DEV9_LOG + case SMAP_R_EMAC3_MODE0_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_MODE0_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_MODE0_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_MODE0_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_MODE1_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_MODE1_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_MODE1_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_MODE1_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_RxMODE_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_RxMODE_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_RxMODE_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_RxMODE_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_INTR_STAT_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_INTR_STAT_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_INTR_STAT_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_INTR_STAT_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_INTR_ENABLE_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_INTR_ENABLE_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_INTR_ENABLE_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_INTR_ENABLE_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_TxMODE0_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_TxMODE0_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_H 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_TxMODE1_L: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_L 16bit read %x\n", hard); + return hard; + + case SMAP_R_EMAC3_TxMODE1_H: + hard = dev9Ru16(addr); + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_H 16bit read %x\n", hard); + return hard; +#endif + +/* case SPD_R_INTR_STAT: + return 0xff; +*/ + case DEV9_R_REV: + hard = 0x0030; // expansion bay + break; + + case SPD_R_REV_1: + hard = 0x0011; +#ifdef DEV9_LOG + DEV9_LOG("STD_R_REV_1 16bit read %x\n", hard); +#endif + return hard; + + case SPD_R_REV_3: + // bit 0: smap + // bit 1: hdd + // bit 5: flash + hard = 0; + if (config.hddEnable) { + hard|= 0x2; + } + if (config.ethEnable) { + hard|= 0x1; + } + hard|= 0x20;//flash + break; + + case SPD_R_0e: + hard = 0x0002; + break; + + case ATA_R_CONTROL: + hard = 0x0040; // we're always ready :D +#ifdef DEV9_LOG + DEV9_LOG("ATA_R_CONTROL 16bit read %x\n", hard); +#endif + return hard; + + case ATA_R_DATA: + hard = dev9.atabuf[dev9.atacount++]; dev9.atasize--; + if (dev9.atasize <= 0) { + ata_hwport->r_status&= ~ATA_STAT_DRQ; + } +#ifdef DEV9_LOG + DEV9_LOG("ATA_R_DATA 16bit read %x\n", hard); +#endif + return hard; + + case ATA_R_STATUS: + if (dev9Ru16(ATA_R_SELECT) & 0x10) { + hard = 0x0001; + } else { + hard = ata_hwport->r_status | 0x0040; // we're always ready :D + } +#ifdef DEV9_LOG + DEV9_LOG("ATA_R_STATUS 16bit read %x\n", hard); +#endif + return hard; + + case ATA_R_NSECTOR: + if ((dev9Ru16(ATA_R_SELECT) >> 4) != 0) { + hard = 0x0000; + } else { + hard = 0x0001; + } +#ifdef DEV9_LOG + DEV9_LOG("ATA_R_NSECTOR 16bit read %x\n", hard); +#endif + return hard; + + default: + if (addr >= SMAP_BD_TX_BASE && addr < (SMAP_BD_TX_BASE + SMAP_BD_SIZE)) { + switch (addr & 0x7) { + case 0: // ctrl_stat + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("TX_CTRL_STAT[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); +#endif + return hard; + case 2: // unknown + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("TX_UNKNOWN[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); +#endif + return hard; + case 4: // length + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("TX_LENGTH[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); +#endif + return hard; + case 6: // pointer + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("TX_POINTER[%d]: read %x\n", (addr - SMAP_BD_TX_BASE) / 8, hard); +#endif + return hard; + } + } + if (addr >= SMAP_BD_RX_BASE && addr < (SMAP_BD_RX_BASE + SMAP_BD_SIZE)) { + switch (addr & 0x7) { + case 0: // ctrl_stat + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("RX_CTRL_STAT[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); +#endif + return hard; + case 2: // unknown + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("RX_UNKNOWN[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); +#endif + return hard; + case 4: // length + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("RX_LENGTH[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); +#endif + return hard; + case 6: // pointer + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("RX_POINTER[%d]: read %x\n", (addr - SMAP_BD_RX_BASE) / 8, hard); +#endif + return hard; + } + } + + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u16)FLASHread32(addr, 2); + } + + hard = dev9Ru16(addr); +#ifdef DEV9_LOG + DEV9_LOG("*Unknown 16bit read at address %lx value %x\n", addr, hard); +#endif + return hard; + } + +#ifdef DEV9_LOG + DEV9_LOG("*Known 16bit read at address %lx value %x\n", addr, hard); +#endif + return hard; +} + +u32 CALLBACK DEV9read32(u32 addr) { + u32 hard; + + switch (addr) { + case SMAP_R_RXFIFO_DATA: + hard = *(u32*)&dev9.buffer[dev9Ru32(SMAP_R_RXFIFO_RD_PTR)]; + dev9Ru32(SMAP_R_RXFIFO_RD_PTR)+= 4; +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_RXFIFO_DATA 32bit read %x\n", hard); +#endif + return hard; + + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + return (u32)FLASHread32(addr, 4); + } + + hard = dev9Ru32(addr); +#ifdef DEV9_LOG + DEV9_LOG("*Unkwnown 32bit read at address %lx\n", addr); +#endif + return hard; + } + +#ifdef DEV9_LOG + DEV9_LOG("*Known 32bit read at address %lx: %lx\n", addr, hard); +#endif + return hard; +} + +void CALLBACK DEV9write8(u32 addr, u8 value) { + switch (addr) { + case 0x10000020: + dev9Ru16(SPD_R_INTR_STAT) = 0xff; + break; + + case ATA_R_STATUS: + DEV9write16(addr, value); + return; + + case SMAP_R_RXFIFO_FRAME_DEC: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_RXFIFO_FRAME_DEC 8bit write %x\n", value); +#endif +// dev9Ru8(addr) = 0; // blah :P + dev9Ru8(addr) = value; + return; + + case SPD_R_PIO_DIR: +#ifdef DEV9_LOG + DEV9_LOG("SPD_R_PIO_DIR 8bit write %x\n", value); +#endif + if (value == 0xe1) dev9.eeprompos = 0; + if (value == 0xe0) dev9.eeprompos = 0; + return; + + case SPD_R_PIO_DATA: +#ifdef DEV9_LOG + DEV9_LOG("SPD_R_PIO_DATA 8bit write %x\n", value); +#endif + dev9Ru8(addr) = value; + return; + + case SMAP_R_TXFIFO_CTRL: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_TXFIFO_CTRL 8bit write %x\n", value); +#endif + value&= ~SMAP_TXFIFO_RESET; + return; + + case SMAP_R_RXFIFO_CTRL: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_RXFIFO_CTRL 8bit write %x\n", value); +#endif + value&= ~SMAP_RXFIFO_RESET; + return; + +#ifdef DEV9_LOG + case ATA_R_DATA: + DEV9_LOG("ATA_R_DATA 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_ERROR: + DEV9_LOG("ATA_R_ERROR 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_NSECTOR: + DEV9_LOG("ATA_R_NSECTOR 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_SECTOR: + DEV9_LOG("ATA_R_SECTOR 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_LCYL: + DEV9_LOG("ATA_R_LCYC 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_HCYL: + DEV9_LOG("ATA_R_HCYC 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_SELECT: + DEV9_LOG("ATA_R_SELECT 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; + + case ATA_R_CONTROL: + DEV9_LOG("ATA_R_CONTROL 8bit write %x\n", value); + dev9Ru8(addr) = value; + return; +#endif + + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 1); + return; + } + + dev9Ru8(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Unknown 8bit write at address %lx value %x\n", addr, value); +#endif + return; + } + dev9Ru8(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Known 8bit write at address %lx value %x\n", addr, value); +#endif +} + +u32 _ata_getlba() { + u32 lba; + + if (ata_hwport->r_select & 0x40) { + lba = (ata_hwport->r_sector & 0xff); + lba|= (ata_hwport->r_lcyl & 0xff) << 8; + lba|= (ata_hwport->r_hcyl & 0xff) << 16; +#ifdef HDD_48BIT + lba|= ((ata_hwport->r_sector >> 8) & 0xff) << 24; +#else + lba|= (ata_hwport->r_select & 0x0f) << 24; +#endif + } else { +#ifdef DEV9_LOG + DEV9_LOG("fixme: lba not set\n"); +#endif + return -1; + } + + return lba; +} + +int _ata_seek() { + u32 lba; + + lba = _ata_getlba(); +#ifdef DEV9_LOG + DEV9_LOG("_ata_seek: lba=%x\n", lba); +#endif + if (lba == -1) return -1; + if (_seekfile(hdd, (u64)lba*512) != 0) { +#ifdef DEV9_LOG + DEV9_LOG("fseek error: %s\n", strerror(errno)); +#endif + return -1; + } + + return 0; +} + + +void ata_unknown(int irq) { +#ifdef DEV9_LOG + DEV9_LOG("ata_unknown\n"); +#endif + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + dev9Ru16(ATA_R_STATUS)|= ATA_STAT_ERR; + dev9Ru16(ATA_R_ERROR) = 0x01; +} + +void ata_nop(int irq) { + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); +} + +void ata_recalibrate(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_readsec(int irq) { + if (irq) { + if (_seekfile(hdd, dev9.atasector*512) != 0) { +#ifdef DEV9_LOG + DEV9_LOG("fseek error: %s\n", strerror(errno)); +#endif + dev9Ru16(ATA_R_STATUS)|= ATA_STAT_ERR; + dev9Ru16(ATA_R_ERROR) = 0x01; + return; + } + dev9.atasize = 512; + dev9.atacount = 0; +#ifdef DEV9_LOG + DEV9_LOG("read 512 bytes from %x\n", ftell(hdd) / 512); +#endif + if (_readfile(hdd, dev9.atabuf, 512) == 0) { + memset(dev9.atabuf, 0, 512); +// printf("fread error: %s\n", strerror(errno)); return; + } + + ata_hwport->r_status|= ATA_STAT_DRQ; + dev9.atasector++; + dev9.atansector--; + if (dev9.atansector > 0) { + _DEV9irq(0x1, 0x1000); + } + + return; + } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + dev9.atansector = ata_hwport->r_nsector == 0 ? 256 : ata_hwport->r_nsector; + dev9.atasector = _ata_getlba(); + if (dev9.atasector == -1) { + dev9Ru16(ATA_R_STATUS)|= ATA_STAT_ERR; + dev9Ru16(ATA_R_ERROR) = 0x01; + return; + } + + _DEV9irq(0x1, 0x1000); +} + +void ata_specify(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_flushcache(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_readdma(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_readdma_ext(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_writedma(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_writedma_ext(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_pidentify(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_identify(int irq) { + struct hd_driveid *id = (struct hd_driveid *)dev9.atabuf; + + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + memset(id, 0, sizeof(struct hd_driveid)); + id->lba_capacity = config.HddSize * 1024*2; + id->cyls = (id->lba_capacity/16)/63; + id->heads = 16; + id->sectors = 63; + +#ifdef HDD_48BIT + id->command_set_2|= 1<<10; // 48bit + id->lba_capacity_2 = (u64)config.HddSize * 1024*2; +#endif +#ifdef DEV9_LOG + DEV9_LOG("id->lba_capacity=%x\n", id->lba_capacity); + DEV9_LOG("id->lba_capacity2=%x\n", id->lba_capacity_2); +#endif + + id->capability = 0x3; // DMA | LBA + + id->model[1] = 'D'; + id->model[0] = 'E'; + id->model[3] = 'V'; + id->model[2] = '9'; + id->model[5] = ' '; + id->model[4] = 'H'; + id->model[7] = 'D'; + id->model[6] = 'D'; + dev9.atasize = 256; dev9.atacount = 0; + ata_hwport->r_status|= ATA_STAT_DRQ | ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_setidle(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_setfeatures(int irq) { + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); + + ata_hwport->r_status|= ATA_STAT_BUSY; + _DEV9irq(0x1, 0x1000); +} + +void ata_smart(int irq) { +#ifdef DEV9_LOG + DEV9_LOG("ata_smart: irq=%x r_error=%x\n", irq, ata_hwport->r_error); +#endif + if (irq) { ata_hwport->r_status&= ~ATA_STAT_BUSY; return; } + + switch (ata_hwport->r_error) { // no IO + case SMART_ENABLE: + _DEV9irq(0x1, 0x1000); + break; + + default: +#ifdef DEV9_LOG + DEV9_LOG("ata_smart: unknown cmd %x\n", ata_hwport->r_error); +#endif + } + + ata_hwport->r_error = 0; + ata_hwport->r_status&= ~(ATA_STAT_DRQ | ATA_STAT_ERR); +} + +void ata_cmd(u8 value) { +#ifdef DEV9_LOG + DEV9_LOG("ata_cmd: %s (%2.2x)\n", ata_cmds[value], value); +#endif + + dev9.atacmd = value; + ata_cmdf[dev9.atacmd](0); +} + +void CALLBACK DEV9write16(u32 addr, u16 value) { + switch (addr) { + case ATA_R_STATUS: +#ifdef DEV9_LOG + DEV9_LOG("ATA_R_STATUS 16bit write %x\n", value); +#endif + ata_cmd(value); + return; + + case SMAP_R_INTR_CLR: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_INTR_CLR 16bit write %x\n", value); +#endif + dev9Ru16(SPD_R_INTR_STAT)&= ~value; + return; + + case SMAP_R_TXFIFO_WR_PTR: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_TXFIFO_WR_PTR 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_MODE0_L: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_MODE0_L 16bit write %x\n", value); +#endif + dev9Ru16(addr) = (value & (~SMAP_E3_SOFT_RESET)) | SMAP_E3_TXMAC_IDLE | SMAP_E3_RXMAC_IDLE; + dev9Ru16(SMAP_R_EMAC3_STA_CTRL_H)|= SMAP_E3_PHY_OP_COMP; + return; + case SMAP_R_EMAC3_MODE0_H: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_MODE0_H 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_TxMODE0_L: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_L 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value & ~SMAP_E3_TX_GNP_0; + return; + case SMAP_R_EMAC3_TxMODE0_H: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_TxMODE0_H 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_TxMODE1_L: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_L 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_TxMODE1_H: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_TxMODE1_H 16bit write %x\n", value); +#endif + dev9Ru16(addr) = value; + return; + case SMAP_R_EMAC3_STA_CTRL_H: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_EMAC3_STA_CTRL_H 16bit write %x\n", value); +#endif + value|= SMAP_E3_PHY_OP_COMP; + if (value & (SMAP_E3_PHY_READ)) { + int reg = value & (SMAP_E3_PHY_REG_ADDR_MSK); + u16 val = dev9.phyregs[reg]; + switch (reg) { + case SMAP_DsPHYTER_BMSR: + val|= SMAP_PHY_BMSR_LINK | SMAP_PHY_BMSR_ANCP; + break; + case SMAP_DsPHYTER_PHYSTS: + val|= SMAP_PHY_STS_LINK | SMAP_PHY_STS_ANCP; + break; + } +#ifdef DEV9_LOG + DEV9_LOG("phy_read %d: %x\n", reg, val); +#endif + dev9Ru16(SMAP_R_EMAC3_STA_CTRL_L) = val; + } else + if (value & (SMAP_E3_PHY_WRITE)) { + int reg = value & (SMAP_E3_PHY_REG_ADDR_MSK); + u16 val = dev9Ru16(SMAP_R_EMAC3_STA_CTRL_L); + switch (reg) { + case SMAP_DsPHYTER_BMCR: + val&= ~SMAP_PHY_BMCR_RST; + val|= 0x1; + break; + } +#ifdef DEV9_LOG + DEV9_LOG("phy_write %d: %x\n", reg, val); +#endif + dev9.phyregs[reg] = val; + } + break; + default: + if (addr >= SMAP_BD_TX_BASE && addr < (SMAP_BD_TX_BASE + SMAP_BD_SIZE)) { + switch (addr & 0x7) { + case 0: // ctrl_stat +#ifdef DEV9_LOG + DEV9_LOG("TX_CTRL_STAT[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); +#endif + if (value & SMAP_BD_TX_READY) { + u32 base = (SMAP_REGBASE + dev9Ru16(addr + 6)) & 0xffff; + +#ifdef DEV9_LOG + DEV9_LOG("sockSendData: base %x, size %d\n", base, dev9Ru16(addr + 4)); +#endif + sockSendData(&dev9.dev9R[base], dev9Ru16(addr + 4)); + _DEV9irq(SMAP_INTR_TXEND, 0x1000); + value&= ~SMAP_BD_TX_READY; + } + dev9Ru16(addr) = value; + return; + case 2: // unknown +#ifdef DEV9_LOG + DEV9_LOG("TX_UNKNOWN[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + case 4: // length +#ifdef DEV9_LOG + DEV9_LOG("TX_LENGTH[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + case 6: // pointer +#ifdef DEV9_LOG + DEV9_LOG("TX_POINTER[%d]: write %x\n", (addr - SMAP_BD_TX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + } + } + if (addr >= SMAP_BD_RX_BASE && addr < (SMAP_BD_RX_BASE + SMAP_BD_SIZE)) { + switch (addr & 0x7) { + case 0: // ctrl_stat +#ifdef DEV9_LOG + DEV9_LOG("RX_CTRL_STAT[%d]: write %x\n", (addr - SMAP_BD_RX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + case 2: // unknown +#ifdef DEV9_LOG + DEV9_LOG("RX_UNKNOWN[%d]: write %x\n", (addr - SMAP_BD_RX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + case 4: // length +#ifdef DEV9_LOG + DEV9_LOG("RX_LENGTH[%d]: write %x\n", (addr - SMAP_BD_RX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + case 6: // pointer +#ifdef DEV9_LOG + DEV9_LOG("RX_POINTER[%d]: write %x\n", (addr - SMAP_BD_RX_BASE) / 8, value); +#endif + dev9Ru16(addr) = value; + return; + } + } + + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 2); + return; + } + + dev9Ru16(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Unknown 16bit write at address %lx value %x\n", addr, value); +#endif + return; + } + dev9Ru16(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Known 16bit write at address %lx value %x\n", addr, value); +#endif +} + +void CALLBACK DEV9write32(u32 addr, u32 value) { + switch (addr) { + case SMAP_R_TXFIFO_DATA: +#ifdef DEV9_LOG + DEV9_LOG("SMAP_R_TXFIFO_DATA 32bit write %x (ptr %x)\n", value, SMAP_TX_BASE + dev9Ru32(SMAP_R_TXFIFO_WR_PTR)); +#endif + dev9Ru32(SMAP_TX_BASE + dev9Ru32(SMAP_R_TXFIFO_WR_PTR)) = value; + dev9Ru32(SMAP_R_TXFIFO_WR_PTR)+= 4; + return; + default: + if ((addr >= FLASH_REGBASE) && (addr < (FLASH_REGBASE + FLASH_REGSIZE))) { + FLASHwrite32(addr, (u32)value, 4); + return; + } + + dev9Ru32(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Unknown 32bit write at address %lx write %x\n", addr, value); +#endif + return; + } + dev9Ru32(addr) = value; +#ifdef DEV9_LOG + DEV9_LOG("*Known 32bit write at address %lx value %lx\n", addr, value); +#endif +} + +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size) { +#ifdef DEV9_LOG + DEV9_LOG("*DEV9readDMA8Mem: size %x\n", size); +#endif + + if (_ata_seek() == -1) return; +#ifdef DEV9_LOG + DEV9_LOG("read %x bytes from %x\n", size, _tellfile(hdd) / 512); +#endif + + if (_readfile(hdd, pMem, size) == 0) { +#ifdef DEV9_LOG + DEV9_LOG("fread error: %s\n", strerror(errno)); +#endif + memset(pMem, 0, size); + return; + } +} + +void CALLBACK DEV9writeDMA8Mem(u32* pMem, int size) { +#ifdef DEV9_LOG + DEV9_LOG("*DEV9writeDMA8Mem: size %x\n", size); +#endif + + if (_ata_seek() == -1) return; +#ifdef DEV9_LOG + DEV9_LOG("write %x bytes from %x\n", size, _tellfile(hdd) / 512); +#endif + + if (_writefile(hdd, pMem, size) == 0) { +#ifdef DEV9_LOG + DEV9_LOG("fwrite error: %s\n", strerror(errno)); +#endif + return; + } +} + +void CALLBACK DEV9irqCallback(void (*callback)(int cycles)) { + DEV9irq = callback; +} + + +// extended funcs + +s32 CALLBACK DEV9test() { + return 0; +} + +void DEV9thread() { + smap_bd_t *pbd; + int bytes; + int rxbi = 0; + + if (config.ethEnable == 0) return; + +// if (sockOpen("d9n0") == -1) { + if (sockOpen(config.Eth) == -1) { + SysMessage("Can't open Device '%s'\n", config.Eth); + return; + } + ThreadRun = 1; + while (ThreadRun) { +#ifdef DEV9_LOG + DEV9_LOG("sockRecvData\n"); +#endif + bytes = sockRecvData(dev9.buffer, sizeof(dev9.buffer)); +#ifdef DEV9_LOG + DEV9_LOG("sockRecvData: %d\n", bytes); +#endif + if (bytes <= 0) continue; + + pbd = (smap_bd_t *)&dev9.dev9R[SMAP_BD_RX_BASE & 0xffff]; + pbd = &pbd[rxbi]; + if (!(pbd->ctrl_stat & SMAP_BD_RX_EMPTY)) { +#ifdef DEV9_LOG + DEV9_LOG("Discarding %d bytes (RX%d not ready)\n", bytes, rxbi); +#endif + printf("Discarding %d bytes (RX%d not ready)\n", bytes, rxbi); + continue; + } +#ifdef DEV9_LOG + DEV9_LOG("DEV9received %d bytes, rxbi %d\n", bytes, rxbi); +#endif + + rxbi++; + if (rxbi == (SMAP_BD_SIZE/8)) rxbi = 0; + + pbd->ctrl_stat&= ~SMAP_BD_RX_EMPTY; + pbd->length = bytes; +// dev9Ru8(SMAP_R_RXFIFO_FRAME_DEC) = 1; // guessing ;) + _DEV9irq(SMAP_INTR_RXEND, 0); + } +} + diff --git a/plugins/dev9/DEV9linuz/DEV9.h b/plugins/dev9/DEV9linuz/DEV9.h new file mode 100644 index 0000000..f48be90 --- /dev/null +++ b/plugins/dev9/DEV9linuz/DEV9.h @@ -0,0 +1,1144 @@ +#ifndef __DEV9_H__ +#define __DEV9_H__ + +#include + +#define DEV9defs +#define WINVER 0x0500 +#define _WIN32_WINNT 0x0500 + +#include "PS2Edefs.h" + +#ifdef __WIN32__ + + +#define usleep(x) Sleep(x / 1000) +#include +#include +#include + +#else + +#include + +#define __inline inline + +#endif + +#define DEV9_LOG __Log + +#define ETH_DEF "eth0" +#define HDD_DEF "DEV9hdd.raw" + +typedef struct { + char Eth[256]; + char Hdd[256]; + int HddSize; + + int hddEnable; + int ethEnable; +} Config; + +Config config; + +typedef struct { + s8 dev9R[0x10000]; + int eeprompos; + u8 eeprom[65]; + u8 buffer[2048]; + u16 atabuf[1024]; + u32 atacount; + u32 atasize; + u16 phyregs[32]; + int irqcause; + u8 atacmd; + u32 atasector; + u32 atansector; +} dev9Struct; + +dev9Struct dev9; + +#define dev9Rs8(mem) dev9.dev9R[(mem) & 0xffff] +#define dev9Rs16(mem) (*(s16*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Rs32(mem) (*(s32*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru8(mem) (*(u8*) &dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru16(mem) (*(u16*)&dev9.dev9R[(mem) & 0xffff]) +#define dev9Ru32(mem) (*(u32*)&dev9.dev9R[(mem) & 0xffff]) + +void *hdd; +int ThreadRun; + +s32 _DEV9open(); +void _DEV9close(); +DEV9callback DEV9irq; +void DEV9thread(); + +FILE *dev9Log; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#define DEV9_R_REV 0x1f80146e + + +/* + * SPEED (ASIC on SMAP) register definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2smap iop driver, modified by linuzappz * + */ + +#define SPD_REGBASE 0x10000000 + +#define SPD_R_REV (SPD_REGBASE + 0x00) +#define SPD_R_REV_1 (SPD_REGBASE + 0x02) +#define SPD_R_REV_3 (SPD_REGBASE + 0x04) +#define SPD_R_0e (SPD_REGBASE + 0x0e) + +#define SPD_R_DMA_CTRL (SPD_REGBASE + 0x24) +#define SPD_R_INTR_STAT (SPD_REGBASE + 0x28) +#define SPD_R_INTR_MASK (SPD_REGBASE + 0x2a) +#define SPD_R_PIO_DIR (SPD_REGBASE + 0x2c) +#define SPD_R_PIO_DATA (SPD_REGBASE + 0x2e) +#define SPD_PP_DOUT (1<<4) /* Data output, read port */ +#define SPD_PP_DIN (1<<5) /* Data input, write port */ +#define SPD_PP_SCLK (1<<6) /* Clock, write port */ +#define SPD_PP_CSEL (1<<7) /* Chip select, write port */ +/* Operation codes */ +#define SPD_PP_OP_READ 2 +#define SPD_PP_OP_WRITE 1 +#define SPD_PP_OP_EWEN 0 +#define SPD_PP_OP_EWDS 0 + +#define SPD_R_XFR_CTRL (SPD_REGBASE + 0x32) +#define SPD_R_IF_CTRL (SPD_REGBASE + 0x64) +#define SPD_IF_ATA_RESET 0x80 +#define SPD_IF_DMA_ENABLE 0x04 +#define SPD_R_PIO_MODE (SPD_REGBASE + 0x70) +#define SPD_R_MWDMA_MODE (SPD_REGBASE + 0x72) +#define SPD_R_UDMA_MODE (SPD_REGBASE + 0x74) + + +/* + * SMAP (PS2 Network Adapter) register definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2smap iop driver, modified by linuzappz * + */ + + +/* SMAP interrupt status bits (selected from the SPEED device). */ +#define SMAP_INTR_EMAC3 (1<<6) +#define SMAP_INTR_RXEND (1<<5) +#define SMAP_INTR_TXEND (1<<4) +#define SMAP_INTR_RXDNV (1<<3) /* descriptor not valid */ +#define SMAP_INTR_TXDNV (1<<2) /* descriptor not valid */ +#define SMAP_INTR_CLR_ALL (SMAP_INTR_RXEND|SMAP_INTR_TXEND|SMAP_INTR_RXDNV) +#define SMAP_INTR_ENA_ALL (SMAP_INTR_EMAC3|SMAP_INTR_CLR_ALL) +#define SMAP_INTR_BITMSK 0x7C + +/* SMAP Register Definitions. */ + +#define SMAP_REGBASE (SPD_REGBASE + 0x100) + +#define SMAP_R_BD_MODE (SMAP_REGBASE + 0x02) +#define SMAP_BD_SWAP (1<<0) + +#define SMAP_R_INTR_CLR (SMAP_REGBASE + 0x28) + +/* SMAP FIFO Registers. */ + +#define SMAP_R_TXFIFO_CTRL (SMAP_REGBASE + 0xf00) +#define SMAP_TXFIFO_RESET (1<<0) +#define SMAP_TXFIFO_DMAEN (1<<1) +#define SMAP_R_TXFIFO_WR_PTR (SMAP_REGBASE + 0xf04) +#define SMAP_R_TXFIFO_SIZE (SMAP_REGBASE + 0xf08) +#define SMAP_R_TXFIFO_FRAME_CNT (SMAP_REGBASE + 0xf0C) +#define SMAP_R_TXFIFO_FRAME_INC (SMAP_REGBASE + 0xf10) +#define SMAP_R_TXFIFO_DATA (SMAP_REGBASE + 0x1000) + +#define SMAP_R_RXFIFO_CTRL (SMAP_REGBASE + 0xf30) +#define SMAP_RXFIFO_RESET (1<<0) +#define SMAP_RXFIFO_DMAEN (1<<1) +#define SMAP_R_RXFIFO_RD_PTR (SMAP_REGBASE + 0xf34) +#define SMAP_R_RXFIFO_SIZE (SMAP_REGBASE + 0xf38) +#define SMAP_R_RXFIFO_FRAME_CNT (SMAP_REGBASE + 0xf3C) +#define SMAP_R_RXFIFO_FRAME_DEC (SMAP_REGBASE + 0xf40) +#define SMAP_R_RXFIFO_DATA (SMAP_REGBASE + 0x1100) + +#define SMAP_R_FIFO_ADDR (SMAP_REGBASE + 0x1200) +#define SMAP_FIFO_CMD_READ (1<<1) +#define SMAP_FIFO_DATA_SWAP (1<<0) +#define SMAP_R_FIFO_DATA (SMAP_REGBASE + 0x1208) + +/* EMAC3 Registers. */ + +#define SMAP_EMAC3_REGBASE (SMAP_REGBASE + 0x1f00) + +#define SMAP_R_EMAC3_MODE0_L (SMAP_EMAC3_REGBASE + 0x00) +#define SMAP_E3_RXMAC_IDLE (1<<15) +#define SMAP_E3_TXMAC_IDLE (1<<14) +#define SMAP_E3_SOFT_RESET (1<<13) +#define SMAP_E3_TXMAC_ENABLE (1<<12) +#define SMAP_E3_RXMAC_ENABLE (1<<11) +#define SMAP_E3_WAKEUP_ENABLE (1<<10) +#define SMAP_R_EMAC3_MODE0_H (SMAP_EMAC3_REGBASE + 0x02) + +#define SMAP_R_EMAC3_MODE1 (SMAP_EMAC3_REGBASE + 0x04) +#define SMAP_R_EMAC3_MODE1_L (SMAP_EMAC3_REGBASE + 0x04) +#define SMAP_R_EMAC3_MODE1_H (SMAP_EMAC3_REGBASE + 0x06) +#define SMAP_E3_FDX_ENABLE (1<<31) +#define SMAP_E3_INLPBK_ENABLE (1<<30) /* internal loop back */ +#define SMAP_E3_VLAN_ENABLE (1<<29) +#define SMAP_E3_FLOWCTRL_ENABLE (1<<28) /* integrated flow ctrl(pause frame) */ +#define SMAP_E3_ALLOW_PF (1<<27) /* allow pause frame */ +#define SMAP_E3_ALLOW_EXTMNGIF (1<<25) /* allow external management IF */ +#define SMAP_E3_IGNORE_SQE (1<<24) +#define SMAP_E3_MEDIA_FREQ_BITSFT (22) +#define SMAP_E3_MEDIA_10M (0<<22) +#define SMAP_E3_MEDIA_100M (1<<22) +#define SMAP_E3_MEDIA_1000M (2<<22) +#define SMAP_E3_MEDIA_MSK (3<<22) +#define SMAP_E3_RXFIFO_SIZE_BITSFT (20) +#define SMAP_E3_RXFIFO_512 (0<<20) +#define SMAP_E3_RXFIFO_1K (1<<20) +#define SMAP_E3_RXFIFO_2K (2<<20) +#define SMAP_E3_RXFIFO_4K (3<<20) +#define SMAP_E3_TXFIFO_SIZE_BITSFT (18) +#define SMAP_E3_TXFIFO_512 (0<<18) +#define SMAP_E3_TXFIFO_1K (1<<18) +#define SMAP_E3_TXFIFO_2K (2<<18) +#define SMAP_E3_TXREQ0_BITSFT (15) +#define SMAP_E3_TXREQ0_SINGLE (0<<15) +#define SMAP_E3_TXREQ0_MULTI (1<<15) +#define SMAP_E3_TXREQ0_DEPEND (2<<15) +#define SMAP_E3_TXREQ1_BITSFT (13) +#define SMAP_E3_TXREQ1_SINGLE (0<<13) +#define SMAP_E3_TXREQ1_MULTI (1<<13) +#define SMAP_E3_TXREQ1_DEPEND (2<<13) +#define SMAP_E3_JUMBO_ENABLE (1<<12) + +#define SMAP_R_EMAC3_TxMODE0_L (SMAP_EMAC3_REGBASE + 0x08) +#define SMAP_E3_TX_GNP_0 (1<<15) /* get new packet */ +#define SMAP_E3_TX_GNP_1 (1<<14) /* get new packet */ +#define SMAP_E3_TX_GNP_DEPEND (1<<13) /* get new packet */ +#define SMAP_E3_TX_FIRST_CHANNEL (1<<12) +#define SMAP_R_EMAC3_TxMODE0_H (SMAP_EMAC3_REGBASE + 0x0A) + +#define SMAP_R_EMAC3_TxMODE1_L (SMAP_EMAC3_REGBASE + 0x0C) +#define SMAP_R_EMAC3_TxMODE1_H (SMAP_EMAC3_REGBASE + 0x0E) +#define SMAP_E3_TX_LOW_REQ_MSK (0x1F) /* low priority request */ +#define SMAP_E3_TX_LOW_REQ_BITSFT (27) /* low priority request */ +#define SMAP_E3_TX_URG_REQ_MSK (0xFF) /* urgent priority request */ +#define SMAP_E3_TX_URG_REQ_BITSFT (16) /* urgent priority request */ + +#define SMAP_R_EMAC3_RxMODE (SMAP_EMAC3_REGBASE + 0x10) +#define SMAP_R_EMAC3_RxMODE_L (SMAP_EMAC3_REGBASE + 0x10) +#define SMAP_R_EMAC3_RxMODE_H (SMAP_EMAC3_REGBASE + 0x12) +#define SMAP_E3_RX_STRIP_PAD (1<<31) +#define SMAP_E3_RX_STRIP_FCS (1<<30) +#define SMAP_E3_RX_RX_RUNT_FRAME (1<<29) +#define SMAP_E3_RX_RX_FCS_ERR (1<<28) +#define SMAP_E3_RX_RX_TOO_LONG_ERR (1<<27) +#define SMAP_E3_RX_RX_IN_RANGE_ERR (1<<26) +#define SMAP_E3_RX_PROP_PF (1<<25) /* propagate pause frame */ +#define SMAP_E3_RX_PROMISC (1<<24) +#define SMAP_E3_RX_PROMISC_MCAST (1<<23) +#define SMAP_E3_RX_INDIVID_ADDR (1<<22) +#define SMAP_E3_RX_INDIVID_HASH (1<<21) +#define SMAP_E3_RX_BCAST (1<<20) +#define SMAP_E3_RX_MCAST (1<<19) + +#define SMAP_R_EMAC3_INTR_STAT (SMAP_EMAC3_REGBASE + 0x14) +#define SMAP_R_EMAC3_INTR_STAT_L (SMAP_EMAC3_REGBASE + 0x14) +#define SMAP_R_EMAC3_INTR_STAT_H (SMAP_EMAC3_REGBASE + 0x16) +#define SMAP_R_EMAC3_INTR_ENABLE (SMAP_EMAC3_REGBASE + 0x18) +#define SMAP_R_EMAC3_INTR_ENABLE_L (SMAP_EMAC3_REGBASE + 0x18) +#define SMAP_R_EMAC3_INTR_ENABLE_H (SMAP_EMAC3_REGBASE + 0x1C) +#define SMAP_E3_INTR_OVERRUN (1<<25) /* this bit does NOT WORKED */ +#define SMAP_E3_INTR_PF (1<<24) +#define SMAP_E3_INTR_BAD_FRAME (1<<23) +#define SMAP_E3_INTR_RUNT_FRAME (1<<22) +#define SMAP_E3_INTR_SHORT_EVENT (1<<21) +#define SMAP_E3_INTR_ALIGN_ERR (1<<20) +#define SMAP_E3_INTR_BAD_FCS (1<<19) +#define SMAP_E3_INTR_TOO_LONG (1<<18) +#define SMAP_E3_INTR_OUT_RANGE_ERR (1<<17) +#define SMAP_E3_INTR_IN_RANGE_ERR (1<<16) +#define SMAP_E3_INTR_DEAD_DEPEND (1<<9) +#define SMAP_E3_INTR_DEAD_0 (1<<8) +#define SMAP_E3_INTR_SQE_ERR_0 (1<<7) +#define SMAP_E3_INTR_TX_ERR_0 (1<<6) +#define SMAP_E3_INTR_DEAD_1 (1<<5) +#define SMAP_E3_INTR_SQE_ERR_1 (1<<4) +#define SMAP_E3_INTR_TX_ERR_1 (1<<3) +#define SMAP_E3_INTR_MMAOP_SUCCESS (1<<1) +#define SMAP_E3_INTR_MMAOP_FAIL (1<<0) +#define SMAP_E3_INTR_ALL \ + (SMAP_E3_INTR_OVERRUN|SMAP_E3_INTR_PF|SMAP_E3_INTR_BAD_FRAME| \ + SMAP_E3_INTR_RUNT_FRAME|SMAP_E3_INTR_SHORT_EVENT| \ + SMAP_E3_INTR_ALIGN_ERR|SMAP_E3_INTR_BAD_FCS| \ + SMAP_E3_INTR_TOO_LONG|SMAP_E3_INTR_OUT_RANGE_ERR| \ + SMAP_E3_INTR_IN_RANGE_ERR| \ + SMAP_E3_INTR_DEAD_DEPEND|SMAP_E3_INTR_DEAD_0| \ + SMAP_E3_INTR_SQE_ERR_0|SMAP_E3_INTR_TX_ERR_0| \ + SMAP_E3_INTR_DEAD_1|SMAP_E3_INTR_SQE_ERR_1| \ + SMAP_E3_INTR_TX_ERR_1| \ + SMAP_E3_INTR_MMAOP_SUCCESS|SMAP_E3_INTR_MMAOP_FAIL) +#define SMAP_E3_DEAD_ALL \ + (SMAP_E3_INTR_DEAD_DEPEND|SMAP_E3_INTR_DEAD_0| \ + SMAP_E3_INTR_DEAD_1) + +#define SMAP_R_EMAC3_ADDR_HI (SMAP_EMAC3_REGBASE + 0x1C) +#define SMAP_R_EMAC3_ADDR_LO (SMAP_EMAC3_REGBASE + 0x20) + +#define SMAP_R_EMAC3_VLAN_TPID (SMAP_EMAC3_REGBASE + 0x24) +#define SMAP_E3_VLAN_ID_MSK 0xFFFF + +#define SMAP_R_EMAC3_VLAN_TCI (SMAP_EMAC3_REGBASE + 0x28) +#define SMAP_E3_VLAN_TCITAG_MSK 0xFFFF + +#define SMAP_R_EMAC3_PAUSE_TIMER (SMAP_EMAC3_REGBASE + 0x2C) +#define SMAP_E3_PTIMER_MSK 0xFFFF + +#define SMAP_R_EMAC3_INDIVID_HASH1 (SMAP_EMAC3_REGBASE + 0x30) +#define SMAP_R_EMAC3_INDIVID_HASH2 (SMAP_EMAC3_REGBASE + 0x34) +#define SMAP_R_EMAC3_INDIVID_HASH3 (SMAP_EMAC3_REGBASE + 0x38) +#define SMAP_R_EMAC3_INDIVID_HASH4 (SMAP_EMAC3_REGBASE + 0x3C) +#define SMAP_R_EMAC3_GROUP_HASH1 (SMAP_EMAC3_REGBASE + 0x40) +#define SMAP_R_EMAC3_GROUP_HASH2 (SMAP_EMAC3_REGBASE + 0x44) +#define SMAP_R_EMAC3_GROUP_HASH3 (SMAP_EMAC3_REGBASE + 0x48) +#define SMAP_R_EMAC3_GROUP_HASH4 (SMAP_EMAC3_REGBASE + 0x4C) +#define SMAP_E3_HASH_MSK 0xFFFF + +#define SMAP_R_EMAC3_LAST_SA_HI (SMAP_EMAC3_REGBASE + 0x50) +#define SMAP_R_EMAC3_LAST_SA_LO (SMAP_EMAC3_REGBASE + 0x54) + +#define SMAP_R_EMAC3_INTER_FRAME_GAP (SMAP_EMAC3_REGBASE + 0x58) +#define SMAP_E3_IFGAP_MSK 0x3F + +#define SMAP_R_EMAC3_STA_CTRL_L (SMAP_EMAC3_REGBASE + 0x5C) +#define SMAP_R_EMAC3_STA_CTRL_H (SMAP_EMAC3_REGBASE + 0x5E) +#define SMAP_E3_PHY_DATA_MSK (0xFFFF) +#define SMAP_E3_PHY_DATA_BITSFT (16) +#define SMAP_E3_PHY_OP_COMP (1<<15) /* operation complete */ +#define SMAP_E3_PHY_ERR_READ (1<<14) +#define SMAP_E3_PHY_STA_CMD_BITSFT (12) +#define SMAP_E3_PHY_READ (1<<12) +#define SMAP_E3_PHY_WRITE (2<<12) +#define SMAP_E3_PHY_OPBCLCK_BITSFT (10) +#define SMAP_E3_PHY_50M (0<<10) +#define SMAP_E3_PHY_66M (1<<10) +#define SMAP_E3_PHY_83M (2<<10) +#define SMAP_E3_PHY_100M (3<<10) +#define SMAP_E3_PHY_ADDR_MSK (0x1F) +#define SMAP_E3_PHY_ADDR_BITSFT (5) +#define SMAP_E3_PHY_REG_ADDR_MSK (0x1F) + +#define SMAP_R_EMAC3_TX_THRESHOLD (SMAP_EMAC3_REGBASE + 0x60) +#define SMAP_E3_TX_THRESHLD_MSK (0x1F) +#define SMAP_E3_TX_THRESHLD_BITSFT (27) + +#define SMAP_R_EMAC3_RX_WATERMARK (SMAP_EMAC3_REGBASE + 0x64) +#define SMAP_E3_RX_LO_WATER_MSK (0x1FF) +#define SMAP_E3_RX_LO_WATER_BITSFT (23) +#define SMAP_E3_RX_HI_WATER_MSK (0x1FF) +#define SMAP_E3_RX_HI_WATER_BITSFT (7) + +#define SMAP_R_EMAC3_TX_OCTETS (SMAP_EMAC3_REGBASE + 0x68) +#define SMAP_R_EMAC3_RX_OCTETS (SMAP_EMAC3_REGBASE + 0x6C) + +/* Buffer descriptors. */ + +typedef struct _smap_bd { + u16 ctrl_stat; + u16 reserved; /* must be zero */ + u16 length; /* number of bytes in pkt */ + u16 pointer; +} smap_bd_t; + +#define SMAP_BD_REGBASE (SMAP_REGBASE + 0x2f00) +#define SMAP_BD_TX_BASE (SMAP_BD_REGBASE + 0x0000) +#define SMAP_TX_BASE (SMAP_REGBASE + 0x1000) +#define SMAP_TX_BUFSIZE 4096 +#define SMAP_BD_RX_BASE (SMAP_BD_REGBASE + 0x0200) +#define SMAP_BD_SIZE 512 +#define SMAP_BD_MAX_ENTRY 64 + +/* TX Control */ +#define SMAP_BD_TX_READY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_TX_GENFCS (1<<9) /* generate FCS */ +#define SMAP_BD_TX_GENPAD (1<<8) /* generate padding */ +#define SMAP_BD_TX_INSSA (1<<7) /* insert source address */ +#define SMAP_BD_TX_RPLSA (1<<6) /* replace source address */ +#define SMAP_BD_TX_INSVLAN (1<<5) /* insert VLAN Tag */ +#define SMAP_BD_TX_RPLVLAN (1<<4) /* replace VLAN Tag */ + +/* TX Status */ +#define SMAP_BD_TX_READY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_TX_BADFCS (1<<9) /* bad FCS */ +#define SMAP_BD_TX_BADPKT (1<<8) /* bad previous pkt in dependent mode */ +#define SMAP_BD_TX_LOSSCR (1<<7) /* loss of carrior sense */ +#define SMAP_BD_TX_EDEFER (1<<6) /* excessive deferal */ +#define SMAP_BD_TX_ECOLL (1<<5) /* excessive collision */ +#define SMAP_BD_TX_LCOLL (1<<4) /* late collision */ +#define SMAP_BD_TX_MCOLL (1<<3) /* multiple collision */ +#define SMAP_BD_TX_SCOLL (1<<2) /* single collision */ +#define SMAP_BD_TX_UNDERRUN (1<<1) /* underrun */ +#define SMAP_BD_TX_SQE (1<<0) /* SQE */ + +#define SMAP_BD_TX_ERROR (SMAP_BD_TX_LOSSCR|SMAP_BD_TX_EDEFER|SMAP_BD_TX_ECOLL| \ + SMAP_BD_TX_LCOLL|SMAP_BD_TX_UNDERRUN) + +/* RX Control */ +#define SMAP_BD_RX_EMPTY (1<<15) /* set:driver, clear:HW */ + +/* RX Status */ +#define SMAP_BD_RX_EMPTY (1<<15) /* set:driver, clear:HW */ +#define SMAP_BD_RX_OVERRUN (1<<9) /* overrun */ +#define SMAP_BD_RX_PFRM (1<<8) /* pause frame */ +#define SMAP_BD_RX_BADFRM (1<<7) /* bad frame */ +#define SMAP_BD_RX_RUNTFRM (1<<6) /* runt frame */ +#define SMAP_BD_RX_SHORTEVNT (1<<5) /* short event */ +#define SMAP_BD_RX_ALIGNERR (1<<4) /* alignment error */ +#define SMAP_BD_RX_BADFCS (1<<3) /* bad FCS */ +#define SMAP_BD_RX_FRMTOOLONG (1<<2) /* frame too long */ +#define SMAP_BD_RX_OUTRANGE (1<<1) /* out of range error */ +#define SMAP_BD_RX_INRANGE (1<<0) /* in range error */ + +#define SMAP_BD_RX_ERROR (SMAP_BD_RX_OVERRUN|SMAP_BD_RX_RUNTFRM|SMAP_BD_RX_SHORTEVNT| \ + SMAP_BD_RX_ALIGNERR|SMAP_BD_RX_BADFCS|SMAP_BD_RX_FRMTOOLONG| \ + SMAP_BD_RX_OUTRANGE|SMAP_BD_RX_INRANGE) + +/* PHY registers (National Semiconductor DP83846A). */ + +#define SMAP_NS_OUI 0x080017 +#define SMAP_DsPHYTER_ADDRESS 0x1 + +#define SMAP_DsPHYTER_BMCR 0x00 +#define SMAP_PHY_BMCR_RST (1<<15) /* ReSeT */ +#define SMAP_PHY_BMCR_LPBK (1<<14) /* LooPBacK */ +#define SMAP_PHY_BMCR_100M (1<<13) /* speed select, 1:100M, 0:10M */ +#define SMAP_PHY_BMCR_10M (0<<13) /* speed select, 1:100M, 0:10M */ +#define SMAP_PHY_BMCR_ANEN (1<<12) /* Auto-Negotiation ENable */ +#define SMAP_PHY_BMCR_PWDN (1<<11) /* PoWer DowN */ +#define SMAP_PHY_BMCR_ISOL (1<<10) /* ISOLate */ +#define SMAP_PHY_BMCR_RSAN (1<<9) /* ReStart Auto-Negotiation */ +#define SMAP_PHY_BMCR_DUPM (1<<8) /* DUPlex Mode, 1:FDX, 0:HDX */ +#define SMAP_PHY_BMCR_COLT (1<<7) /* COLlision Test */ + +#define SMAP_DsPHYTER_BMSR 0x01 +#define SMAP_PHY_BMSR_ANCP (1<<5) /* Auto-Negotiation ComPlete */ +#define SMAP_PHY_BMSR_LINK (1<<2) /* LINK status */ + +#define SMAP_DsPHYTER_PHYIDR1 0x02 +#define SMAP_PHY_IDR1_VAL (((SMAP_NS_OUI<<2)>>8)&0xffff) + +#define SMAP_DsPHYTER_PHYIDR2 0x03 +#define SMAP_PHY_IDR2_VMDL 0x2 /* Vendor MoDeL number */ +#define SMAP_PHY_IDR2_VAL \ + (((SMAP_NS_OUI<<10)&0xFC00)|((SMAP_PHY_IDR2_VMDL<<4)&0x3F0)) +#define SMAP_PHY_IDR2_MSK 0xFFF0 +#define SMAP_PHY_IDR2_REV_MSK 0x000F + +#define SMAP_DsPHYTER_ANAR 0x04 +#define SMAP_DsPHYTER_ANLPAR 0x05 +#define SMAP_DsPHYTER_ANLPARNP 0x05 +#define SMAP_DsPHYTER_ANER 0x06 +#define SMAP_DsPHYTER_ANNPTR 0x07 + +/* Extended registers. */ +#define SMAP_DsPHYTER_PHYSTS 0x10 +#define SMAP_PHY_STS_REL (1<<13) /* Receive Error Latch */ +#define SMAP_PHY_STS_POST (1<<12) /* POlarity STatus */ +#define SMAP_PHY_STS_FCSL (1<<11) /* False Carrier Sense Latch */ +#define SMAP_PHY_STS_SD (1<<10) /* 100BT unconditional Signal Detect */ +#define SMAP_PHY_STS_DSL (1<<9) /* 100BT DeScrambler Lock */ +#define SMAP_PHY_STS_PRCV (1<<8) /* Page ReCeiVed */ +#define SMAP_PHY_STS_RFLT (1<<6) /* Remote FauLT */ +#define SMAP_PHY_STS_JBDT (1<<5) /* JaBber DetecT */ +#define SMAP_PHY_STS_ANCP (1<<4) /* Auto-Negotiation ComPlete */ +#define SMAP_PHY_STS_LPBK (1<<3) /* LooPBacK status */ +#define SMAP_PHY_STS_DUPS (1<<2) /* DUPlex Status,1:FDX,0:HDX */ +#define SMAP_PHY_STS_FDX (1<<2) /* Full Duplex */ +#define SMAP_PHY_STS_HDX (0<<2) /* Half Duplex */ +#define SMAP_PHY_STS_SPDS (1<<1) /* SPeeD Status */ +#define SMAP_PHY_STS_10M (1<<1) /* 10Mbps */ +#define SMAP_PHY_STS_100M (0<<1) /* 100Mbps */ +#define SMAP_PHY_STS_LINK (1<<0) /* LINK status */ +#define SMAP_DsPHYTER_FCSCR 0x14 +#define SMAP_DsPHYTER_RECR 0x15 +#define SMAP_DsPHYTER_PCSR 0x16 +#define SMAP_DsPHYTER_PHYCTRL 0x19 +#define SMAP_DsPHYTER_10BTSCR 0x1A +#define SMAP_DsPHYTER_CDCTRL 0x1B + + +/* + * ATA hardware types and definitions. + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2drv iop driver, modified by linuzappz * + */ + + +#define ATA_DEV9_HDD_BASE (SPD_REGBASE + 0x40) +/* AIF on T10Ks - Not supported yet. */ +#define ATA_AIF_HDD_BASE (SPD_REGBASE + 0x4000000 + 0x60) + +/* A port contains all of the ATA controller registers. */ +typedef struct _ata_hwport { + u16 r_data; /* 00 */ + u16 r_error; /* 02 */ +#define r_feature r_error + u16 r_nsector; /* 04 */ + u16 r_sector; /* 06 */ + u16 r_lcyl; /* 08 */ + u16 r_hcyl; /* 0a */ + u16 r_select; /* 0c */ + u16 r_status; /* 0e */ +#define r_command r_status + u16 pad[6]; + u16 r_control; /* 1c */ +} ata_hwport_t; + +ata_hwport_t *ata_hwport; + +#define ATA_R_DATA (ATA_DEV9_HDD_BASE + 0x00) +#define ATA_R_ERROR (ATA_DEV9_HDD_BASE + 0x02) +#define ATA_R_NSECTOR (ATA_DEV9_HDD_BASE + 0x04) +#define ATA_R_SECTOR (ATA_DEV9_HDD_BASE + 0x06) +#define ATA_R_LCYL (ATA_DEV9_HDD_BASE + 0x08) +#define ATA_R_HCYL (ATA_DEV9_HDD_BASE + 0x0a) +#define ATA_R_SELECT (ATA_DEV9_HDD_BASE + 0x0c) +#define ATA_R_STATUS (ATA_DEV9_HDD_BASE + 0x0e) +#define ATA_R_CONTROL (ATA_DEV9_HDD_BASE + 0x1c) + +/* r_error bits. */ +#define ATA_ERR_MARK 0x01 +#define ATA_ERR_TRACK0 0x02 +#define ATA_ERR_ABORT 0x04 +#define ATA_ERR_MCR 0x08 +#define ATA_ERR_ID 0x10 +#define ATA_ERR_MC 0x20 +#define ATA_ERR_ECC 0x40 +#define ATA_ERR_ICRC 0x80 + +/* r_status bits. */ +#define ATA_STAT_ERR 0x01 +#define ATA_STAT_INDEX 0x02 +#define ATA_STAT_ECC 0x04 +#define ATA_STAT_DRQ 0x08 +#define ATA_STAT_SEEK 0x10 +#define ATA_STAT_WRERR 0x20 +#define ATA_STAT_READY 0x40 +#define ATA_STAT_BUSY 0x80 + + + + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +#define WIN_RESTORE WIN_RECAL +/* + * 0x10->0x1F Reserved + */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* + * 0x28 + */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ +#define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ +#define WIN_INIT 0x60 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define WIN_STANDBY2 0x96 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ERASE_SECTORS 0xC0 +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ +#define WIN_POSTBOOT 0xDC +#define WIN_PREBOOT 0xDD +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ + /* SET_FEATURES 0x22 or 0xDD */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* WIN_SMART sub-commands */ + +#define SMART_READ_VALUES 0xD0 +#define SMART_READ_THRESHOLDS 0xD1 +#define SMART_AUTOSAVE 0xD2 +#define SMART_SAVE 0xD3 +#define SMART_IMMEDIATE_OFFLINE 0xD4 +#define SMART_READ_LOG_SECTOR 0xD5 +#define SMART_WRITE_LOG_SECTOR 0xD6 +#define SMART_WRITE_THRESHOLDS 0xD7 +#define SMART_ENABLE 0xD8 +#define SMART_DISABLE 0xD9 +#define SMART_STATUS 0xDA +#define SMART_AUTO_OFFLINE 0xDB + +/* Password used in TF4 & TF5 executing SMART commands */ + +#define SMART_LCYL_PASS 0x4F +#define SMART_HCYL_PASS 0xC2 + +/* WIN_SETFEATURES sub-commands */ +#define SETFEATURES_EN_8BIT 0x01 /* Enable 8-Bit Transfers */ +#define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */ +#define SETFEATURES_XFER 0x03 /* Set transfer mode */ +# define XFER_UDMA_7 0x47 /* 0100|0111 */ +# define XFER_UDMA_6 0x46 /* 0100|0110 */ +# define XFER_UDMA_5 0x45 /* 0100|0101 */ +# define XFER_UDMA_4 0x44 /* 0100|0100 */ +# define XFER_UDMA_3 0x43 /* 0100|0011 */ +# define XFER_UDMA_2 0x42 /* 0100|0010 */ +# define XFER_UDMA_1 0x41 /* 0100|0001 */ +# define XFER_UDMA_0 0x40 /* 0100|0000 */ +# define XFER_MW_DMA_2 0x22 /* 0010|0010 */ +# define XFER_MW_DMA_1 0x21 /* 0010|0001 */ +# define XFER_MW_DMA_0 0x20 /* 0010|0000 */ +# define XFER_SW_DMA_2 0x12 /* 0001|0010 */ +# define XFER_SW_DMA_1 0x11 /* 0001|0001 */ +# define XFER_SW_DMA_0 0x10 /* 0001|0000 */ +# define XFER_PIO_4 0x0C /* 0000|1100 */ +# define XFER_PIO_3 0x0B /* 0000|1011 */ +# define XFER_PIO_2 0x0A /* 0000|1010 */ +# define XFER_PIO_1 0x09 /* 0000|1001 */ +# define XFER_PIO_0 0x08 /* 0000|1000 */ +# define XFER_PIO_SLOW 0x00 /* 0000|0000 */ +#define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */ +#define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */ +#define SETFEATURES_EN_SAME_R 0x22 /* for a region ATA-1 */ +#define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */ +#define SETFEATURES_DIS_RETRY 0x33 /* Disable Retry */ +#define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */ +#define SETFEATURES_RW_LONG 0x44 /* Set Lenght of VS bytes */ +#define SETFEATURES_SET_CACHE 0x54 /* Set Cache segments to SC Reg. Val */ +#define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */ +#define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */ +#define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */ +#define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */ +#define SETFEATURES_DIS_ECC 0x77 /* Disable ECC byte count */ +#define SETFEATURES_DIS_8BIT 0x81 /* Disable 8-Bit Transfers */ +#define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */ +#define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */ +#define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */ +#define SETFEATURES_EN_ECC 0x88 /* Enable ECC byte count */ +#define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */ +#define SETFEATURES_EN_RETRY 0x99 /* Enable Retry */ +#define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */ +#define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */ +#define SETFEATURES_EN_REST 0xAC /* ATA-1 */ +#define SETFEATURES_4B_RW_LONG 0xBB /* Set Lenght of 4 bytes */ +#define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */ +#define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */ +#define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt ATAPI */ +#define SETFEATURES_EN_SAME_M 0xDD /* for a entire device ATA-1 */ +#define SETFEATURES_DIS_SI 0xDE /* Disable SERVICE interrupt ATAPI */ + +/* WIN_SECURITY sub-commands */ + +#define SECURITY_SET_PASSWORD 0xBA +#define SECURITY_UNLOCK 0xBB +#define SECURITY_ERASE_PREPARE 0xBC +#define SECURITY_ERASE_UNIT 0xBD +#define SECURITY_FREEZE_LOCK 0xBE +#define SECURITY_DISABLE_PASSWORD 0xBF + +struct hd_geometry { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; +}; + +/* BIG GEOMETRY */ +struct hd_big_geometry { + unsigned char heads; + unsigned char sectors; + unsigned int cylinders; + unsigned long start; +}; + +/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */ +#define HDIO_GETGEO 0x0301 /* get device geometry */ +#define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */ +#define HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */ +#define HDIO_GET_QDMA 0x0305 /* get use-qdma flag */ + +#define HDIO_SET_XFER 0x0306 /* set transfer rate via proc */ + +#define HDIO_OBSOLETE_IDENTITY 0x0307 /* OBSOLETE, DO NOT USE: returns 142 bytes */ +#define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */ +#define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */ +#define HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */ +#define HDIO_GET_DMA 0x030b /* get use-dma flag */ +#define HDIO_GET_NICE 0x030c /* get nice flags */ +#define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */ +#define HDIO_GET_WCACHE 0x030e /* get write cache mode on|off */ +#define HDIO_GET_ACOUSTIC 0x030f /* get acoustic value */ +#define HDIO_GET_ADDRESS 0x0310 /* */ + +#define HDIO_GET_BUSSTATE 0x031a /* get the bus state of the hwif */ +#define HDIO_TRISTATE_HWIF 0x031b /* execute a channel tristate */ +#define HDIO_DRIVE_RESET 0x031c /* execute a device reset */ +#define HDIO_DRIVE_TASKFILE 0x031d /* execute raw taskfile */ +#define HDIO_DRIVE_TASK 0x031e /* execute task and special drive command */ +#define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */ + +#define HDIO_DRIVE_CMD_AEB HDIO_DRIVE_TASK + +/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */ +#define HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */ +#define HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */ +#define HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */ +#define HDIO_SET_32BIT 0x0324 /* change io_32bit flags */ +#define HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */ +#define HDIO_SET_DMA 0x0326 /* change use-dma flag */ +#define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ +#define HDIO_SCAN_HWIF 0x0328 /* register and (re)scan interface */ +#define HDIO_SET_NICE 0x0329 /* set nice flags */ +#define HDIO_UNREGISTER_HWIF 0x032a /* unregister interface */ +#define HDIO_SET_WCACHE 0x032b /* change write cache enable-disable */ +#define HDIO_SET_ACOUSTIC 0x032c /* change acoustic behavior */ +#define HDIO_SET_BUSSTATE 0x032d /* set the bus state of the hwif */ +#define HDIO_SET_QDMA 0x032e /* change use-qdma flag */ +#define HDIO_SET_ADDRESS 0x032f /* change lba addressing modes */ + +/* bus states */ +enum { + BUSSTATE_OFF = 0, + BUSSTATE_ON, + BUSSTATE_TRISTATE +}; + +/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */ +#define HDIO_GETGEO_BIG 0x0330 /* */ +#define HDIO_GETGEO_BIG_RAW 0x0331 /* */ + +#define HDIO_SET_IDE_SCSI 0x0338 +#define HDIO_SET_SCSI_IDE 0x0339 + +#define __NEW_HD_DRIVE_ID +/* structure returned by HDIO_GET_IDENTITY, + * as per ANSI NCITS ATA6 rev.1b spec + */ +struct hd_driveid { + unsigned short config; /* lots of obsolete bit flags */ + unsigned short cyls; /* Obsolete, "physical" cyls */ + unsigned short reserved2; /* reserved (word 2) */ + unsigned short heads; /* Obsolete, "physical" heads */ + unsigned short track_bytes; /* unformatted bytes per track */ + unsigned short sector_bytes; /* unformatted bytes per sector */ + unsigned short sectors; /* Obsolete, "physical" sectors per track */ + unsigned short vendor0; /* vendor unique */ + unsigned short vendor1; /* vendor unique */ + unsigned short vendor2; /* Retired vendor unique */ + unsigned char serial_no[20]; /* 0 = not_specified */ + unsigned short buf_type; /* Retired */ + unsigned short buf_size; /* Retired, 512 byte increments + * 0 = not_specified + */ + unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */ + unsigned char fw_rev[8]; /* 0 = not_specified */ + unsigned char model[40]; /* 0 = not_specified */ + unsigned char max_multsect; /* 0=not_implemented */ + unsigned char vendor3; /* vendor unique */ + unsigned short dword_io; /* 0=not_implemented; 1=implemented */ + unsigned char vendor4; /* vendor unique */ + unsigned char capability; /* (upper byte of word 49) + * 3: IORDYsup + * 2: IORDYsw + * 1: LBA + * 0: DMA + */ + unsigned short reserved50; /* reserved (word 50) */ + unsigned char vendor5; /* Obsolete, vendor unique */ + unsigned char tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ + unsigned char vendor6; /* Obsolete, vendor unique */ + unsigned char tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ + unsigned short field_valid; /* (word 53) + * 2: ultra_ok word 88 + * 1: eide_ok words 64-70 + * 0: cur_ok words 54-58 + */ + unsigned short cur_cyls; /* Obsolete, logical cylinders */ + unsigned short cur_heads; /* Obsolete, l heads */ + unsigned short cur_sectors; /* Obsolete, l sectors per track */ + unsigned short cur_capacity0; /* Obsolete, l total sectors on drive */ + unsigned short cur_capacity1; /* Obsolete, (2 words, misaligned int) */ + unsigned char multsect; /* current multiple sector count */ + unsigned char multsect_valid; /* when (bit0==1) multsect is ok */ + unsigned int lba_capacity; /* Obsolete, total number of sectors */ + unsigned short dma_1word; /* Obsolete, single-word dma info */ + unsigned short dma_mword; /* multiple-word dma info */ + unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */ + unsigned short eide_dma_min; /* min mword dma cycle time (ns) */ + unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */ + unsigned short eide_pio; /* min cycle time (ns), no IORDY */ + unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */ + unsigned short words69_70[2]; /* reserved words 69-70 + * future command overlap and queuing + */ + /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */ + unsigned short words71_74[4]; /* reserved words 71-74 + * for IDENTIFY PACKET DEVICE command + */ + unsigned short queue_depth; /* (word 75) + * 15:5 reserved + * 4:0 Maximum queue depth -1 + */ + unsigned short words76_79[4]; /* reserved words 76-79 */ + unsigned short major_rev_num; /* (word 80) */ + unsigned short minor_rev_num; /* (word 81) */ + unsigned short command_set_1; /* (word 82) supported + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + unsigned short command_set_2; /* (word 83) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + unsigned short cfsse; /* (word 84) + * cmd set-feature supported extensions + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging + * 4: Streaming Feature Set + * 3: Media Card Pass Through + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + unsigned short cfs_enable_1; /* (word 85) + * command set-feature enabled + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + unsigned short cfs_enable_2; /* (word 86) + * command set-feature enabled + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + unsigned short csf_default; /* (word 87) + * command set-feature default + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging enabled + * 4: Valid CONFIGURE STREAM executed + * 3: Media Card Pass Through enabled + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + unsigned short dma_ultra; /* (word 88) */ + unsigned short trseuc; /* time required for security erase */ + unsigned short trsEuc; /* time required for enhanced erase */ + unsigned short CurAPMvalues; /* current APM values */ + unsigned short mprc; /* master password revision code */ + unsigned short hw_config; /* hardware config (word 93) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: + * 12: + * 11: + * 10: + * 9: + * 8: + * 7: + * 6: + * 5: + * 4: + * 3: + * 2: + * 1: + * 0: Shall be ONE + */ + unsigned short acoustic; /* (word 94) + * 15:8 Vendor's recommended value + * 7:0 current value + */ + unsigned short msrqs; /* min stream request size */ + unsigned short sxfert; /* stream transfer time */ + unsigned short sal; /* stream access latency */ + unsigned int spg; /* stream performance granularity */ + u64 lba_capacity_2; /* 48-bit total number of sectors */ + unsigned short words104_125[22];/* reserved words 104-125 */ + unsigned short last_lun; /* (word 126) */ + unsigned short word127; /* (word 127) Feature Set + * Removable Media Notification + * 15:2 reserved + * 1:0 00 = not supported + * 01 = supported + * 10 = reserved + * 11 = reserved + */ + unsigned short dlf; /* (word 128) + * device lock function + * 15:9 reserved + * 8 security level 1:max 0:high + * 7:6 reserved + * 5 enhanced erase + * 4 expire + * 3 frozen + * 2 locked + * 1 en/disabled + * 0 capability + */ + unsigned short csfo; /* (word 129) + * current set features options + * 15:4 reserved + * 3: auto reassign + * 2: reverting + * 1: read-look-ahead + * 0: write cache + */ + unsigned short words130_155[26];/* reserved vendor words 130-155 */ + unsigned short word156; /* reserved vendor word 156 */ + unsigned short words157_159[3];/* reserved vendor words 157-159 */ + unsigned short cfa_power; /* (word 160) CFA Power Mode + * 15 word 160 supported + * 14 reserved + * 13 + * 12 + * 11:0 + */ + unsigned short words161_175[15];/* Reserved for CFA */ + unsigned short words176_205[30];/* Current Media Serial Number */ + unsigned short words206_254[49];/* reserved words 206-254 */ + unsigned short integrity_word; /* (word 255) + * 15:8 Checksum + * 7:0 Signature + */ +}; + +/* + * NAND Flash via Dev9 driver definitions + * + * Copyright (c) 2003 Marcus R. Brown + * + * * code included from the ps2sdk iop driver * + */ + +#define FLASH_ID_64MBIT 0xe6 +#define FLASH_ID_128MBIT 0x73 +#define FLASH_ID_256MBIT 0x75 +#define FLASH_ID_512MBIT 0x76 +#define FLASH_ID_1024MBIT 0x79 + +/* SmartMedia commands. */ +#define SM_CMD_READ1 0x00 +#define SM_CMD_READ2 0x01 +#define SM_CMD_READ3 0x50 +#define SM_CMD_RESET 0xff +#define SM_CMD_WRITEDATA 0x80 +#define SM_CMD_PROGRAMPAGE 0x10 +#define SM_CMD_ERASEBLOCK 0x60 +#define SM_CMD_ERASECONFIRM 0xd0 +#define SM_CMD_GETSTATUS 0x70 +#define SM_CMD_READID 0x90 + +typedef struct { + u32 id; + u32 mbits; + u32 page_bytes; /* bytes/page */ + u32 block_pages; /* pages/block */ + u32 blocks; +} flash_info_t; + +/* +static flash_info_t devices[] = { + { FLASH_ID_64MBIT, 64, 528, 16, 1024 }, + { FLASH_ID_128MBIT, 128, 528, 32, 1024 }, + { FLASH_ID_256MBIT, 256, 528, 32, 2048 }, + { FLASH_ID_512MBIT, 512, 528, 32, 4096 }, + { FLASH_ID_1024MBIT, 1024, 528, 32, 8192 } +}; +#define NUM_DEVICES (sizeof(devices)/sizeof(flash_info_t)) +*/ + +// definitions added by Florin + +#define FLASH_REGBASE 0x10004800 + +#define FLASH_R_DATA (FLASH_REGBASE + 0x00) +#define FLASH_R_CMD (FLASH_REGBASE + 0x04) +#define FLASH_R_ADDR (FLASH_REGBASE + 0x08) +#define FLASH_R_CTRL (FLASH_REGBASE + 0x0C) +#define FLASH_PP_READY (1<<0) // r/w /BUSY +#define FLASH_PP_WRITE (1<<7) // -/w WRITE data +#define FLASH_PP_CSEL (1<<8) // -/w CS +#define FLASH_PP_READ (1<<11) // -/w READ data +#define FLASH_PP_NOECC (1<<12) // -/w ECC disabled +//#define FLASH_R_10 (FLASH_REGBASE + 0x10) +#define FLASH_R_ID (FLASH_REGBASE + 0x14) + +#define FLASH_REGSIZE 0x20 + +void CALLBACK FLASHinit(); +u32 CALLBACK FLASHread32(u32 addr, int size); +void CALLBACK FLASHwrite32(u32 addr, u32 value, int size); + +#endif diff --git a/plugins/dev9/DEV9linuz/Linux/Config.c b/plugins/dev9/DEV9linuz/Linux/Config.c new file mode 100644 index 0000000..5a7accd --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/Config.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +#include "DEV9.h" + +void LoadConf() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/DEV9linuz.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + strcpy(config.Eth, ETH_DEF); + strcpy(config.Hdd, HDD_DEF); + config.HddSize = 1024; + return; + } + fscanf(f, "Eth = %[^\n]\n", config.Eth); + fscanf(f, "Hdd = %[^\n]\n", config.Hdd); + fscanf(f, "HddSize = %d\n", &config.HddSize); + if (*config.Eth == 0) strcpy(config.Eth, ETH_DEF); + if (*config.Hdd == 0) strcpy(config.Hdd, HDD_DEF); + if (config.HddSize == 0) config.HddSize = 1024; + fclose(f); +} + +void SaveConf() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/DEV9linuz.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fprintf(f, "Eth = %s\n", config.Eth); + fprintf(f, "Hdd = %s\n", config.Hdd); + fprintf(f, "HddSize = %d\n", config.HddSize); + fclose(f); +} + diff --git a/plugins/dev9/DEV9linuz/Linux/Config.h b/plugins/dev9/DEV9linuz/Linux/Config.h new file mode 100644 index 0000000..6293929 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/Config.h @@ -0,0 +1,2 @@ +void SaveConf(); +void LoadConf(); diff --git a/plugins/dev9/DEV9linuz/Linux/Linux.c b/plugins/dev9/DEV9linuz/Linux/Linux.c new file mode 100644 index 0000000..9b1eeb3 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/Linux.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "DEV9.h" +#include "socks.h" + +int ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgDEV9linuz"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + strcpy(cfg, "./cfg/cfgDEV9linuz"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + sprintf(cfg, "%s/cfgDEV9linuz", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + printf("cfgDEV9linuz file not found!\n"); + return -1; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", msg); + ExecCfg(cmd); +} + +void DEV9configure() { + ExecCfg("configure"); +} + +void DEV9about() { + ExecCfg("about"); +} + +void *_DEV9thread(void *arg) { + DEV9thread(); + return NULL; +} + +pthread_t thread; + +s32 _DEV9open() { + pthread_create(&thread, NULL, _DEV9thread, NULL); + + return 0; +} + +void _DEV9close() { + ThreadRun = 0; + pthread_join(thread, NULL); +} + diff --git a/plugins/dev9/DEV9linuz/Linux/Makefile b/plugins/dev9/DEV9linuz/Linux/Makefile new file mode 100644 index 0000000..b13d853 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/Makefile @@ -0,0 +1,37 @@ + +PLUGIN = libDEV9linuz.so +CFG = cfgDEV9linuz +CFLAGS+= -fPIC -Wall -I. -I.. -O3 -fomit-frame-pointer +OBJS = ../DEV9.o +OBJS+= Linux.o Config.o socks.o +CFGOBJS = conf.o interface.o support.o Config.o +DEV9NETOBJS = dev9net.o +DEPS:= $(OBJS:.o=.d) +LIBS = -lpthread +CFLAGS+= $(shell gtk-config --cflags) -D__LINUX__ +CFGLIBS = $(shell gtk-config --libs) + +CC = gcc + +all: plugin cfg dev9net + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} + rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +dev9net: + ${CC} -O2 -Wall -fno-strict-aliasing -D__KERNEL__ -DMODULE=1 -I/usr/src/linux/include -c -o dev9net.o dev9net.c + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/dev9/DEV9linuz/Linux/callbacks.c b/plugins/dev9/DEV9linuz/Linux/callbacks.c new file mode 100644 index 0000000..fa070a7 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/dev9/DEV9linuz/Linux/callbacks.h b/plugins/dev9/DEV9linuz/Linux/callbacks.h new file mode 100644 index 0000000..22cf74a --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/dev9/DEV9linuz/Linux/conf.c b/plugins/dev9/DEV9linuz/Linux/conf.c new file mode 100644 index 0000000..cc27074 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/conf.c @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "callbacks.h" +#include "DEV9.h" +#include "Config.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void cfgSysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "DEV9 Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CFGabout() { + About = create_About(); + gtk_widget_show_all(About); + gtk_main(); +} + +GtkWidget *Conf; +GtkWidget *ComboEth; +GtkWidget *ComboHdd; +GList *ethdevs; +GList *hdddevs; + +void OnConf_Ok(GtkButton *button, gpointer user_data) { + gchar *str; + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboEth)->entry)); + strcpy(config.Eth, str); + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboHdd)->entry)); + strcpy(config.Hdd, str); + + SaveConf(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void GetEthDevs() { +/* struct ifconf ifc; + int sock; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return; +*/ + ethdevs = g_list_append(ethdevs, "disabled"); + ethdevs = g_list_append(ethdevs, "lo"); + ethdevs = g_list_append(ethdevs, "eth0"); +} + +void GetHddDevs() { +/* struct ifconf ifc; + int sock; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) return; +*/ + hdddevs = g_list_append(hdddevs, HDD_DEF); +} + +void CFGconfigure() { + Conf = create_Config(); + + LoadConf(); + + ComboEth = lookup_widget(Conf, "GtkCombo_Eth"); + ethdevs = NULL; + GetEthDevs(); + if (ethdevs) { + gtk_combo_set_popdown_strings(GTK_COMBO(ComboEth), ethdevs); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboEth)->entry), config.Eth); + } + + ComboHdd = lookup_widget(Conf, "GtkCombo_Hdd"); + hdddevs = NULL; + GetHddDevs(); + if (hdddevs) { + gtk_combo_set_popdown_strings(GTK_COMBO(ComboHdd), hdddevs); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboHdd)->entry), config.Hdd); + } + + gtk_widget_show_all(Conf); + gtk_main(); +} + +long CFGmessage(char *msg) { + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(argv[2]); + } + + return 0; +} diff --git a/plugins/dev9/DEV9linuz/Linux/dev9linuz.glade b/plugins/dev9/DEV9linuz/Linux/dev9linuz.glade new file mode 100644 index 0000000..715af05 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/dev9linuz.glade @@ -0,0 +1,300 @@ + + + + + DEV9linuz + dev9linuz + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + DEV9config + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox1 + 5 + True + 5 + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Eth + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + + GtkFrame + frame3 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox2 + 5 + True + 5 + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Hdd + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + DEV9about + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/dev9/DEV9linuz/Linux/dev9net.c b/plugins/dev9/DEV9linuz/Linux/dev9net.c new file mode 100644 index 0000000..401ecaa --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/dev9net.c @@ -0,0 +1,194 @@ +/* dummy.c: a d9n net driver + + The purpose of this driver is to provide a device to point a + route through, but not to actually transmit packets. + + Why? If you have a machine whose only connection is an occasional + PPP/SLIP/PLIP link, you can only connect to your own hostname + when the link is up. Otherwise you have to use localhost. + This isn't very consistent. + + One solution is to set up a d9n link using PPP/SLIP/PLIP, + but this seems (to me) too much overhead for too little gain. + This driver provides a small alternative. Thus you can do + + [when not running slip] + ifconfig d9n slip.addr.ess.here up + [to go to slip] + ifconfig d9n down + dip whatever + + This was written by looking at Donald Becker's skeleton driver + and the loopback driver. I then threw away anything that didn't + apply! Thanks to Alan Cox for the key clue on what to do with + misguided packets. + + Nick Holloway, 27th May 1994 + [I tweaked this explanation a little but that's all] + Alan Cox, 30th May 1994 +*/ + +/* To have statistics (just packets sent) define this */ + +#include +#include +#include +#include +#include +#include +#include + + +static char *edev; +static struct net_device *ndev; + +MODULE_PARM(edev, "s"); +MODULE_PARM_DESC(edev, + "name of the device from which to send packets"); + +static struct net_device dev_d9n; + + +static int d9n_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *d9n_get_stats(struct net_device *dev); +static int d9n_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int d9n_rx_hook(struct sk_buff *skb); +static int (*old_rx_hook)(struct sk_buff *skb); + + +/* fake multicast ability */ +static void set_multicast_list(struct net_device *dev) { +} + +#ifdef CONFIG_NET_FASTROUTE +static int d9n_accept_fastpath(struct net_device *dev, struct dst_entry *dst) { + return -1; +} +#endif + +static int __init d9n_init(struct net_device *dev) { + + /* Initialize the device structure. */ + + dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct net_device_stats)); + + dev->get_stats = d9n_get_stats; + dev->hard_start_xmit = d9n_xmit; + dev->set_multicast_list = set_multicast_list; + dev->do_ioctl = d9n_ioctl; +#ifdef CONFIG_NET_FASTROUTE + dev->accept_fastpath = d9n_accept_fastpath; +#endif + + /* Fill in device structure with ethernet-generic values. */ + ether_setup(dev); + dev->tx_queue_len = 0; + dev->flags = 0; + + return 0; +} + +static int d9n_xmit(struct sk_buff *skb, struct net_device *dev) { + struct net_device_stats *stats = dev->priv; + + printk("d9n_xmit %d\n", skb->len); + +// dev_queue_xmit(skb); + stats->tx_packets++; + stats->tx_bytes+=skb->len; + + dev_kfree_skb(skb); + return 0; +} + +static struct net_device_stats *d9n_get_stats(struct net_device *dev) { + return dev->priv; +} + +static int d9n_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + printk("d9n_ioctl\n"); + + if (!netif_running(dev)) + return -EINVAL; + +/* switch (cmd) { + case + }*/ + return 0; +} + +static int d9n_rx_hook(struct sk_buff *skb) { + struct sk_buff *skb2; + struct iphdr *iph; + unsigned char *ptr; + __u32 saddr; + int proto; + + printk("d9n_rx_hook: %d\n", skb->len); + ptr = skb->mac.ethernet->h_dest; + printk("h_dest: %02X:%02X:%02X:%02X:%02X:%02X.\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + ptr = skb->mac.ethernet->h_source; + printk("h_source: %02X:%02X:%02X:%02X:%02X:%02X.\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + + proto = ntohs(skb->mac.ethernet->h_proto); + if (proto != ETH_P_IP) { + return NET_RX_SUCCESS; + } + + printk("ETH_P_IP\n"); + iph = (struct iphdr*)skb->data; + printk("saddr=%08x, daddr=%08x\n", iph->saddr, iph->daddr); + + skb2 = skb_clone(skb, GFP_ATOMIC); + skb2->dev = &dev_d9n; + netif_rx(skb2); + + return NET_RX_SUCCESS; +} + +static int __init d9n_init_module(void) { + int err; + + printk("d9n_init_module\n"); + if (edev == NULL) { + printk(KERN_ERR "dev9net: please specify network device (dev='device'), aborting.\n"); + return -1; + } + ndev = dev_get_by_name(edev); + if (ndev == NULL) { + printk(KERN_ERR "dev9net: network device %s does not exists, aborting.\n", edev); + return -1; + } + + old_rx_hook = ndev->rx_hook; + ndev->rx_hook = d9n_rx_hook; + + dev_d9n.init = d9n_init; + SET_MODULE_OWNER(&dev_d9n); + + /* Find a name for this unit */ + err=dev_alloc_name(&dev_d9n,"d9n"); + if(err<0) + return err; + err = register_netdev(&dev_d9n); + printk("register_netdev: %d\n", err); + if (err<0) + return err; + return 0; +} + +static void __exit d9n_cleanup_module(void) { + unregister_netdev(&dev_d9n); + kfree(dev_d9n.priv); + + memset(&dev_d9n, 0, sizeof(dev_d9n)); + dev_d9n.init = d9n_init; + ndev->rx_hook = old_rx_hook; +} + +module_init(d9n_init_module); +module_exit(d9n_cleanup_module); +MODULE_LICENSE("GPL"); diff --git a/plugins/dev9/DEV9linuz/Linux/interface.c b/plugins/dev9/DEV9linuz/Linux/interface.c new file mode 100644 index 0000000..a73c086 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/interface.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *hbox1; + GtkWidget *label4; + GtkWidget *GtkCombo_Eth; + GtkWidget *combo_entry1; + GtkWidget *frame3; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_Hdd; + GtkWidget *entry1; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "DEV9config"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Ethernet"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + hbox1 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (frame2), hbox1); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label4 = gtk_label_new ("Device:"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (Config), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox1), label4, FALSE, FALSE, 0); + + GtkCombo_Eth = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Eth); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Eth", GtkCombo_Eth, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Eth); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_Eth, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Eth, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_Eth)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + frame3 = gtk_frame_new ("Hdd"); + gtk_widget_ref (frame3); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame3", frame3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (frame3), hbox2); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label5 = gtk_label_new ("Device:"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_Hdd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Hdd); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Hdd", GtkCombo_Hdd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Hdd); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_Hdd, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Hdd, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_Hdd)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "DEV9about"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("DEV9linuz Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Author: linuzappz "); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/dev9/DEV9linuz/Linux/interface.h b/plugins/dev9/DEV9linuz/Linux/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/dev9/DEV9linuz/Linux/socks.c b/plugins/dev9/DEV9linuz/Linux/socks.c new file mode 100644 index 0000000..3dfbbce --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/socks.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socks.h" + +static int sock; +static int index; + +long sockOpen(char *Device) { + struct ifreq ifr; + int opts; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + printf("socket error\n"); return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, Device, sizeof(ifr.ifr_name)); + + if (ioctl(sock, SIOGIFINDEX, &ifr) == -1) { + printf("SIOGIFINDEX error\n"); return -1; + } + + index = ifr.ifr_ifindex; + close(sock); + + sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sock == -1) return -1; +/* opts = fcntl(sock, F_GETFL); + if (opts < 0) return -1; + opts|= O_NONBLOCK; + fcntl(sock, F_SETFL, opts); +*/ + return 0; +} + +void sockClose() { + close(sock); +} + +long sockSendData(void *pData, int Size) { + struct sockaddr_ll addr; + + memset(&addr, 0, sizeof(addr)); + addr.sll_family = AF_PACKET; + addr.sll_ifindex = index; + addr.sll_protocol = htons(ETH_P_ALL); + + return sendto(sock, pData, Size, 0, (struct sockaddr*)&addr, sizeof(addr)); +} + +long sockRecvData(void *pData, int Size) { + struct sockaddr_ll addr; + socklen_t len = sizeof(addr); + int ret; + +_start: + memset(&addr, 0, sizeof(addr)); + addr.sll_family = AF_PACKET; + addr.sll_ifindex = index; + addr.sll_protocol = htons(ETH_P_ALL); + + ret = recvfrom(sock, pData, Size, 0, (struct sockaddr*)&addr, &len); + return ret; +} + diff --git a/plugins/dev9/DEV9linuz/Linux/socks.h b/plugins/dev9/DEV9linuz/Linux/socks.h new file mode 100644 index 0000000..dd90062 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/socks.h @@ -0,0 +1,22 @@ +#ifndef __SOCKS_H__ +#define __SOCKS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +long sockOpen(char *Device); +void sockClose(); +long sockSendData(void *pData, int Size); +long sockRecvData(void *pData, int Size); + +#endif /* __SOCKS_H__*/ diff --git a/plugins/dev9/DEV9linuz/Linux/support.c b/plugins/dev9/DEV9linuz/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/dev9/DEV9linuz/Linux/support.h b/plugins/dev9/DEV9linuz/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/dev9/DEV9linuz/PS2Edefs.h b/plugins/dev9/DEV9linuz/PS2Edefs.h new file mode 100644 index 0000000..a52d86a --- /dev/null +++ b/plugins/dev9/DEV9linuz/PS2Edefs.h @@ -0,0 +1,684 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.5 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0005 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/dev9/DEV9linuz/PS2Etypes.h b/plugins/dev9/DEV9linuz/PS2Etypes.h new file mode 100644 index 0000000..443ad45 --- /dev/null +++ b/plugins/dev9/DEV9linuz/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/dev9/DEV9linuz/Win32/Config.c b/plugins/dev9/DEV9linuz/Win32/Config.c new file mode 100644 index 0000000..5068caf --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Config.c @@ -0,0 +1,52 @@ +#include + +#include "DEV9.h" + +#define GetKeyV(name, var, s, t) \ + size = s; type = t; \ + RegQueryValueEx(myKey, name, 0, &type, (LPBYTE) var, &size); + +#define GetKeyVdw(name, var) \ + GetKeyV(name, var, 4, REG_DWORD); + +#define SetKeyV(name, var, s, t) \ + RegSetValueEx(myKey, name, 0, t, (LPBYTE) var, s); + +#define SetKeyVdw(name, var) \ + SetKeyV(name, var, 4, REG_DWORD); + +void SaveConf() { + HKEY myKey; + DWORD myDisp; + + RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\DEV9\\DEV9linuz", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &myDisp); + SetKeyV("Eth", config.Eth, strlen(config.Eth), REG_SZ); + SetKeyV("Hdd", config.Hdd, strlen(config.Hdd), REG_SZ); + SetKeyVdw("HddSize", &config.HddSize); + SetKeyVdw("ethEnable", &config.ethEnable); + SetKeyVdw("hddEnable", &config.hddEnable); + + RegCloseKey(myKey); +} + +void LoadConf() { + HKEY myKey; + DWORD type, size; + + memset(&config, 0, sizeof(config)); + strcpy(config.Hdd, HDD_DEF); + config.HddSize=8*1024; + strcpy(config.Eth, ETH_DEF); + + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\PS2Eplugin\\DEV9\\DEV9linuz", 0, KEY_ALL_ACCESS, &myKey)!=ERROR_SUCCESS) { + SaveConf(); return; + } + GetKeyV("Eth", config.Eth, sizeof(config.Eth), REG_SZ); + GetKeyV("Hdd", config.Hdd, sizeof(config.Hdd), REG_SZ); + GetKeyVdw("HddSize", &config.HddSize); + GetKeyVdw("ethEnable", &config.ethEnable); + GetKeyVdw("hddEnable", &config.hddEnable); + + RegCloseKey(myKey); +} + diff --git a/plugins/dev9/DEV9linuz/Win32/Config.h b/plugins/dev9/DEV9linuz/Win32/Config.h new file mode 100644 index 0000000..6293929 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Config.h @@ -0,0 +1,2 @@ +void SaveConf(); +void LoadConf(); diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.def b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.def new file mode 100644 index 0000000..40fd157 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.def @@ -0,0 +1,29 @@ +; DEV9linuz.def : Declares the module parameters for the DLL. + +LIBRARY "DEV9linuz" +DESCRIPTION 'DEV9linuz Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + DEV9init @5 + DEV9shutdown @6 + DEV9open @7 + DEV9close @8 + DEV9read8 @9 + DEV9read16 @10 + DEV9read32 @11 + DEV9write8 @12 + DEV9write16 @13 + DEV9write32 @14 + DEV9readDMA8Mem @15 + DEV9writeDMA8Mem @16 + + DEV9configure @17 + DEV9test @18 + DEV9about @19 + DEV9irqCallback @20 + DEV9irqHandler @21 + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsp b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsp new file mode 100644 index 0000000..51ae7cc --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsp @@ -0,0 +1,107 @@ +# Microsoft Developer Studio Project File - Name="DEV9linuz" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=DEV9linuz - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "DEV9linuz.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DEV9linuz.mak" CFG="DEV9linuz - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DEV9linuz - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=snCl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEV9linuz_EXPORTS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEV9linuz_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=2 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x408 /d "NDEBUG" +# ADD RSC /l 0x408 /d "NDEBUG" +BSC32=snBsc.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=snLink.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib packet.lib /nologo /dll /machine:I386 /nodefaultlib:"msvcrt.lib" +# SUBTRACT LINK32 /nodefaultlib +# Begin Target + +# Name "DEV9linuz - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Config.c +# End Source File +# Begin Source File + +SOURCE=..\DEV9.c +# End Source File +# Begin Source File + +SOURCE=.\DEV9linuz.def +# End Source File +# Begin Source File + +SOURCE=..\flash.c +# End Source File +# Begin Source File + +SOURCE=.\socks.c +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\DEV9.h +# End Source File +# Begin Source File + +SOURCE=..\PS2Edefs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\Dev9linuz.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsw b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsw new file mode 100644 index 0000000..74c94b3 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "DEV9linuz"=".\DEV9linuz.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.ncb b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.ncb new file mode 100644 index 0000000000000000000000000000000000000000..b7fb8464478814601470f1626b4abd26cbd6e7e5 GIT binary patch literal 150528 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 literal 0 HcmV?d00001 diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.opt b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.opt new file mode 100644 index 0000000000000000000000000000000000000000..5d2d83220c88c95ab9bfcbb36863f7a8b8211ede GIT binary patch literal 48640 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 + +
+

Build Log

+

+--------------------Configuration: DEV9linuz - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\Florin\LOCALS~1\Temp\RSP5C7.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEV9linuz_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=2 /Fo"Release/" /Fd"Release/" /FD /c +"D:\Temporar\Npcsx2\plugins\dev9\DEV9linuz\flash.c" +] +Creating command line "snCl.exe @C:\DOCUME~1\Florin\LOCALS~1\Temp\RSP5C7.tmp" +Creating temporary file "C:\DOCUME~1\Florin\LOCALS~1\Temp\RSP5C8.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib packet.lib /nologo /dll /incremental:no /pdb:"Release/DEV9linuz.pdb" /machine:I386 /nodefaultlib:"msvcrt.lib" /def:".\DEV9linuz.def" /out:"Release/DEV9linuz.dll" /implib:"Release/DEV9linuz.lib" +.\Release\Config.obj +.\Release\DEV9.obj +.\Release\socks.obj +.\Release\Win32.obj +.\Release\Dev9linuz.res +.\Release\flash.obj +] +Creating command line "snLink.exe @C:\DOCUME~1\Florin\LOCALS~1\Temp\RSP5C8.tmp" +

Output Window

+Compiling... +snCL -- Detected win32 build...passing to cl.exe +flash.c + +NOTE: WINVER has been defined as 0x0500 or greater which enables +Windows NT 5.0 and Windows 98 features. When these headers were released, +Windows NT 5.0 beta 1 and Windows 98 beta 2.1 were the current versions. + +For this release when WINVER is defined as 0x0500 or greater, you can only +build beta or test applications. To build a retail application, +set WINVER to 0x0400 or visit http://www.microsoft.com/msdn/sdk +to see if retail Windows NT 5.0 or Windows 98 headers are available. + +See the SDK release notes for more information. + +Linking... +snCL -- Detected win32 build...passing to link.exe +snMonitor already running. + Creating library Release/DEV9linuz.lib and object Release/DEV9linuz.exp + + + +

Results

+DEV9linuz.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.rc b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.rc new file mode 100644 index 0000000..10ca317 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.rc @@ -0,0 +1,135 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifdef __MINGW32__ +#include "afxresmw.h" +#else +#include "afxres.h" +#endif + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Castilian) (unknown sub-lang: 0xB) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, 0xB +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 227, 170 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "HDD Configure" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,115,150,50,14 + PUSHBUTTON "Cancel",IDCANCEL,170,150,50,14 + COMBOBOX IDC_BAYTYPE,90,10,130,47,CBS_DROPDOWNLIST | CBS_SORT | + WS_DISABLED + LTEXT "DEV9 Type",IDC_STATIC,15,10,60,11,SS_CENTERIMAGE + LTEXT "Ethernet Device",IDC_STATIC,15,60,60,10,SS_CENTERIMAGE + COMBOBOX IDC_ETHDEV,85,60,130,45,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + GROUPBOX "Ethernet",IDC_STATIC,5,30,215,50 + CONTROL "Enabled",IDC_ETHENABLED,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,15,45,42,10 + LTEXT "HDD File",IDC_STATIC,15,115,60,10,SS_CENTERIMAGE + GROUPBOX "Hard Disk Drive",IDC_STATIC,5,85,215,50 + CONTROL "Enabled",IDC_HDDENABLED,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,15,100,42,10 + EDITTEXT IDC_HDDFILE,85,115,130,12,ES_AUTOHSCROLL +END + +IDD_ABOUT DIALOGEX 0, 0, 177, 86 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "DEV9 About" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,65,50,14 + LTEXT "DEV9 Driver",IDC_NAME,59,7,42,8 + LTEXT "Author: linuzappz ",IDC_STATIC, + 17,31,141,10 + LTEXT "Shadow ",IDC_STATIC,43,47,112,13 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 220 + TOPMARGIN, 7 + BOTTOMMARGIN, 163 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 79 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Castilian) (unknown sub-lang: 0xB) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln new file mode 100644 index 0000000..d599424 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9linuz", "DEV9linuz.vcproj", "{BBE4E5FB-530A-4D18-A633-35AF0577B7F3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release.ActiveCfg = Release|Win32 + {BBE4E5FB-530A-4D18-A633-35AF0577B7F3}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln.old b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln.old new file mode 100644 index 0000000..fb1fdd4 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.sln.old @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DEV9linuz", "DEV9linuz.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.suo b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.suo new file mode 100644 index 0000000000000000000000000000000000000000..118b652efa4330b079aec32e75480800834c47c8 GIT binary patch literal 13312 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.7.10.old b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.7.10.old new file mode 100644 index 0000000..9bcce3f --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.7.10.old @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.FLORIN.Florin.user b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.FLORIN.Florin.user new file mode 100644 index 0000000..5c3399f --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/DEV9linuz.vcproj.FLORIN.Florin.user @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/plugins/dev9/DEV9linuz/Win32/Devioctl.h b/plugins/dev9/DEV9linuz/Win32/Devioctl.h new file mode 100644 index 0000000..af8784b --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Devioctl.h @@ -0,0 +1,90 @@ +/*++ BUILD Version: 0004 // Increment this if a change has global effects + Copyright (c) 1992-1993 Microsoft Corporation + Module Name: + devioctl.h + Revision History: + -- */ +// begin_winioctl +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ +// begin_ntddk begin_nthal begin_ntifs +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// +#define DEVICE_TYPE ULONG +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) +// +// Define the method codes for how buffers are passed for I/O and FS controls +// +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 +// +// Define the access check value for any access +// +// +// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in +// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these +// constants *MUST* always be in sync. +// +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe +#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe +// end_ntddk end_nthal end_ntifs +#endif // _DEVIOCTL_ +// end_winioctl diff --git a/plugins/dev9/DEV9linuz/Win32/Makefile b/plugins/dev9/DEV9linuz/Win32/Makefile new file mode 100644 index 0000000..accfa99 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Makefile @@ -0,0 +1,52 @@ +# +# Makefile for MINGW32 +# + + +all: dev9linuz + +PLUGIN = DEV9linuz.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +ASMFLAGS = -D__WIN32__ -i.. -i.# -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 -lPacket +RESOBJ = dev9linuz.o + +OBJS = ../DEV9.o +OBJS+= socks.o Config.o Win32.o ${RESOBJ} + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I/usr/local/include ${FLAGS} +ASMFLAGS = -f elf ${FLAGS} -i./ -i../ + +dev9linuz: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} +# ${STRIP} ${PLUGIN} + +.PHONY: clean dev9linuz + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: DEV9linuz.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/dev9/DEV9linuz/Win32/Ntddndis.h b/plugins/dev9/DEV9linuz/Win32/Ntddndis.h new file mode 100644 index 0000000..0b62980 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Ntddndis.h @@ -0,0 +1,1400 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + Copyright (c) 1990-1993 Microsoft Corporation + Module Name: + ntddndis.h + Abstract: + This is the include file that defines all constants and types for + accessing the Network driver interface device. + Author: + Steve Wood (stevewo) 27-May-1990 + Revision History: + Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0. + Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures + Kyle Brandon (kyleb) 09/24/96 added general co ndis oids. + -- */ +#ifndef _NTDDNDIS_ +#define _NTDDNDIS_ +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// +#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN" +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// +#define _NDIS_CONTROL_CODE(request,method) \ + CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS) +#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED ) +#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED ) +#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED ) +#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED ) +#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED ) +#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT ) +// +// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for +// this device. +// +// +// This is the type of an NDIS OID value. +// +typedef ULONG NDIS_OID, *PNDIS_OID; +// +// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed +// together (no padding is required since statistics all have +// four or eight bytes of data). +// +typedef struct _NDIS_STATISTICS_VALUE { + NDIS_OID Oid; + ULONG DataLength; + UCHAR Data[1]; // variable length + +} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE; + +// +// Structure used by TRANSLATE_NAME IOCTL +// +typedef struct _NET_PNP_ID { + ULONG ClassId; + ULONG Token; +} NET_PNP_ID, *PNET_PNP_ID; + +typedef struct _NET_PNP_TRANSLATE_LIST { + ULONG BytesNeeded; + NET_PNP_ID IdArray[ANYSIZE_ARRAY]; +} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST; + +// +// Structure used to define a self-contained variable data structure +// +typedef struct _NDIS_VAR_DATA_DESC { + USHORT Length; // # of octects of data + + USHORT MaximumLength; // # of octects available + + LONG Offset; // Offset of data relative to the descriptor + +} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC; + +// +// Object Identifiers used by NdisRequest Query/Set Information +// +// +// General Objects +// +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +// +// These are connection-oriented general OIDs. +// These replace the above OIDs for connection-oriented media. +// +#define OID_GEN_CO_SUPPORTED_LIST 0x00010101 +#define OID_GEN_CO_HARDWARE_STATUS 0x00010102 +#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_CO_MEDIA_IN_USE 0x00010104 +#define OID_GEN_CO_LINK_SPEED 0x00010105 +#define OID_GEN_CO_VENDOR_ID 0x00010106 +#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 +#define OID_GEN_CO_DRIVER_VERSION 0x00010108 +#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 +#define OID_GEN_CO_MAC_OPTIONS 0x0001010A +#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B +#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C +#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D +#define OID_GEN_CO_GET_TIME_CAPS 0x00010201 +#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202 +// +// These are connection-oriented statistics OIDs. +// +#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101 +#define OID_GEN_CO_RCV_PDUS_OK 0x00020102 +#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 +#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 +#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 +#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201 +#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 +#define OID_GEN_CO_BYTES_XMIT 0x00020203 +#define OID_GEN_CO_BYTES_RCV 0x00020204 +#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 +#define OID_GEN_CO_NETCARD_LOAD 0x00020206 +// +// These are objects for Connection-oriented media call-managers and are not +// valid for ndis drivers. Under construction. +// +#define OID_CO_ADD_PVC 0xFF000001 +#define OID_CO_DELETE_PVC 0xFF000002 +#define OID_CO_GET_CALL_INFORMATION 0xFF000003 +#define OID_CO_ADD_ADDRESS 0xFF000004 +#define OID_CO_DELETE_ADDRESS 0xFF000005 +#define OID_CO_GET_ADDRESSES 0xFF000006 +#define OID_CO_ADDRESS_CHANGE 0xFF000007 +#define OID_CO_SIGNALING_ENABLED 0xFF000008 +#define OID_CO_SIGNALING_DISABLED 0xFF000009 +// +// 802.3 Objects (Ethernet) +// +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +// +// +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 +// +// 802.5 Objects (Token-Ring) +// +#define OID_802_5_PERMANENT_ADDRESS 0x02010101 +#define OID_802_5_CURRENT_ADDRESS 0x02010102 +#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103 +#define OID_802_5_CURRENT_GROUP 0x02010104 +#define OID_802_5_LAST_OPEN_STATUS 0x02010105 +#define OID_802_5_CURRENT_RING_STATUS 0x02010106 +#define OID_802_5_CURRENT_RING_STATE 0x02010107 +#define OID_802_5_LINE_ERRORS 0x02020101 +#define OID_802_5_LOST_FRAMES 0x02020102 +#define OID_802_5_BURST_ERRORS 0x02020201 +#define OID_802_5_AC_ERRORS 0x02020202 +#define OID_802_5_ABORT_DELIMETERS 0x02020203 +#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204 +#define OID_802_5_FREQUENCY_ERRORS 0x02020205 +#define OID_802_5_TOKEN_ERRORS 0x02020206 +#define OID_802_5_INTERNAL_ERRORS 0x02020207 +// +// FDDI Objects +// +#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101 +#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102 +#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103 +#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104 +#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105 +#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106 +#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107 +#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108 +#define OID_FDDI_ATTACHMENT_TYPE 0x03020101 +#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102 +#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103 +#define OID_FDDI_FRAME_ERRORS 0x03020104 +#define OID_FDDI_FRAMES_LOST 0x03020105 +#define OID_FDDI_RING_MGT_STATE 0x03020106 +#define OID_FDDI_LCT_FAILURES 0x03020107 +#define OID_FDDI_LEM_REJECTS 0x03020108 +#define OID_FDDI_LCONNECTION_STATE 0x03020109 +#define OID_FDDI_SMT_STATION_ID 0x03030201 +#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202 +#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203 +#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204 +#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205 +#define OID_FDDI_SMT_USER_DATA 0x03030206 +#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207 +#define OID_FDDI_SMT_MAC_CT 0x03030208 +#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209 +#define OID_FDDI_SMT_MASTER_CT 0x0303020A +#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B +#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C +#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D +#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E +#define OID_FDDI_SMT_T_NOTIFY 0x0303020F +#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210 +#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211 +#define OID_FDDI_SMT_PORT_INDEXES 0x03030212 +#define OID_FDDI_SMT_MAC_INDEXES 0x03030213 +#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214 +#define OID_FDDI_SMT_ECM_STATE 0x03030215 +#define OID_FDDI_SMT_CF_STATE 0x03030216 +#define OID_FDDI_SMT_HOLD_STATE 0x03030217 +#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218 +#define OID_FDDI_SMT_STATION_STATUS 0x03030219 +#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A +#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B +#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C +#define OID_FDDI_SMT_SET_COUNT 0x0303021D +#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E +#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F +#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220 +#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221 +#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222 +#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223 +#define OID_FDDI_MAC_CURRENT_PATH 0x03030224 +#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225 +#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226 +#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227 +#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228 +#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229 +#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A +#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B +#define OID_FDDI_MAC_INDEX 0x0303022C +#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D +#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E +#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F +#define OID_FDDI_MAC_T_REQ 0x03030230 +#define OID_FDDI_MAC_T_NEG 0x03030231 +#define OID_FDDI_MAC_T_MAX 0x03030232 +#define OID_FDDI_MAC_TVX_VALUE 0x03030233 +#define OID_FDDI_MAC_T_PRI0 0x03030234 +#define OID_FDDI_MAC_T_PRI1 0x03030235 +#define OID_FDDI_MAC_T_PRI2 0x03030236 +#define OID_FDDI_MAC_T_PRI3 0x03030237 +#define OID_FDDI_MAC_T_PRI4 0x03030238 +#define OID_FDDI_MAC_T_PRI5 0x03030239 +#define OID_FDDI_MAC_T_PRI6 0x0303023A +#define OID_FDDI_MAC_FRAME_CT 0x0303023B +#define OID_FDDI_MAC_COPIED_CT 0x0303023C +#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D +#define OID_FDDI_MAC_TOKEN_CT 0x0303023E +#define OID_FDDI_MAC_ERROR_CT 0x0303023F +#define OID_FDDI_MAC_LOST_CT 0x03030240 +#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241 +#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242 +#define OID_FDDI_MAC_LATE_CT 0x03030243 +#define OID_FDDI_MAC_RING_OP_CT 0x03030244 +#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245 +#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246 +#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247 +#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248 +#define OID_FDDI_MAC_RMT_STATE 0x03030249 +#define OID_FDDI_MAC_DA_FLAG 0x0303024A +#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B +#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C +#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D +#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E +#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F +#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250 +#define OID_FDDI_PATH_INDEX 0x03030251 +#define OID_FDDI_PATH_RING_LATENCY 0x03030252 +#define OID_FDDI_PATH_TRACE_STATUS 0x03030253 +#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254 +#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255 +#define OID_FDDI_PATH_CONFIGURATION 0x03030256 +#define OID_FDDI_PATH_T_R_MODE 0x03030257 +#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258 +#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259 +#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A +#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B +#define OID_FDDI_PORT_MY_TYPE 0x0303025C +#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D +#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E +#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F +#define OID_FDDI_PORT_CURRENT_PATH 0x03030260 +#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261 +#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262 +#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263 +#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264 +#define OID_FDDI_PORT_PMD_CLASS 0x03030265 +#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266 +#define OID_FDDI_PORT_INDEX 0x03030267 +#define OID_FDDI_PORT_MAINT_LS 0x03030268 +#define OID_FDDI_PORT_BS_FLAG 0x03030269 +#define OID_FDDI_PORT_PC_LS 0x0303026A +#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B +#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C +#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D +#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E +#define OID_FDDI_PORT_LEM_CT 0x0303026F +#define OID_FDDI_PORT_LER_CUTOFF 0x03030270 +#define OID_FDDI_PORT_LER_ALARM 0x03030271 +#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272 +#define OID_FDDI_PORT_PCM_STATE 0x03030273 +#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274 +#define OID_FDDI_PORT_LER_FLAG 0x03030275 +#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276 +#define OID_FDDI_SMT_STATION_ACTION 0x03030277 +#define OID_FDDI_PORT_ACTION 0x03030278 +#define OID_FDDI_IF_DESCR 0x03030279 +#define OID_FDDI_IF_TYPE 0x0303027A +#define OID_FDDI_IF_MTU 0x0303027B +#define OID_FDDI_IF_SPEED 0x0303027C +#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D +#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E +#define OID_FDDI_IF_OPER_STATUS 0x0303027F +#define OID_FDDI_IF_LAST_CHANGE 0x03030280 +#define OID_FDDI_IF_IN_OCTETS 0x03030281 +#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282 +#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283 +#define OID_FDDI_IF_IN_DISCARDS 0x03030284 +#define OID_FDDI_IF_IN_ERRORS 0x03030285 +#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286 +#define OID_FDDI_IF_OUT_OCTETS 0x03030287 +#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288 +#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289 +#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A +#define OID_FDDI_IF_OUT_ERRORS 0x0303028B +#define OID_FDDI_IF_OUT_QLEN 0x0303028C +#define OID_FDDI_IF_SPECIFIC 0x0303028D +// +// WAN objects +// +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 +#define OID_WAN_LINE_COUNT 0x0401010A +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E +// +// LocalTalk objects +// +#define OID_LTALK_CURRENT_NODE_ID 0x05010102 +#define OID_LTALK_IN_BROADCASTS 0x05020101 +#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102 +#define OID_LTALK_OUT_NO_HANDLERS 0x05020201 +#define OID_LTALK_COLLISIONS 0x05020202 +#define OID_LTALK_DEFERS 0x05020203 +#define OID_LTALK_NO_DATA_ERRORS 0x05020204 +#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205 +#define OID_LTALK_FCS_ERRORS 0x05020206 +// +// Arcnet objects +// +#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101 +#define OID_ARCNET_CURRENT_ADDRESS 0x06010102 +#define OID_ARCNET_RECONFIGURATIONS 0x06020201 +// +// TAPI objects +// +#define OID_TAPI_ACCEPT 0x07030101 +#define OID_TAPI_ANSWER 0x07030102 +#define OID_TAPI_CLOSE 0x07030103 +#define OID_TAPI_CLOSE_CALL 0x07030104 +#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105 +#define OID_TAPI_CONFIG_DIALOG 0x07030106 +#define OID_TAPI_DEV_SPECIFIC 0x07030107 +#define OID_TAPI_DIAL 0x07030108 +#define OID_TAPI_DROP 0x07030109 +#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A +#define OID_TAPI_GET_ADDRESS_ID 0x0703010B +#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C +#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D +#define OID_TAPI_GET_CALL_INFO 0x0703010E +#define OID_TAPI_GET_CALL_STATUS 0x0703010F +#define OID_TAPI_GET_DEV_CAPS 0x07030110 +#define OID_TAPI_GET_DEV_CONFIG 0x07030111 +#define OID_TAPI_GET_EXTENSION_ID 0x07030112 +#define OID_TAPI_GET_ID 0x07030113 +#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114 +#define OID_TAPI_MAKE_CALL 0x07030115 +#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116 +#define OID_TAPI_OPEN 0x07030117 +#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118 +#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119 +#define OID_TAPI_SECURE_CALL 0x0703011A +#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B +#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C +#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D +#define OID_TAPI_SET_CALL_PARAMS 0x0703011E +#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F +#define OID_TAPI_SET_DEV_CONFIG 0x07030120 +#define OID_TAPI_SET_MEDIA_MODE 0x07030121 +#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122 +// +// ATM Connection Oriented Ndis +// +#define OID_ATM_SUPPORTED_VC_RATES 0x08010101 +#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102 +#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103 +#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104 +#define OID_ATM_MAX_ACTIVE_VCS 0x08010105 +#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106 +#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107 +#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108 +#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109 +#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A +#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B +#define OID_ATM_SIGNALING_VPIVCI 0x08010201 +#define OID_ATM_ASSIGNED_VPI 0x08010202 +#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203 +#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204 +#define OID_ATM_ILMI_VPIVCI 0x08010205 +#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206 +#define OID_ATM_GET_NEAREST_FLOW 0x08010207 +#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208 +// +// ATM specific statistics OIDs. +// +#define OID_ATM_RCV_CELLS_OK 0x08020101 +#define OID_ATM_XMIT_CELLS_OK 0x08020102 +#define OID_ATM_RCV_CELLS_DROPPED 0x08020103 +#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201 +#define OID_ATM_CELLS_HEC_ERROR 0x08020202 +#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203 +// +// PCCA (Wireless) object +// +// +// All WirelessWAN devices must support the following OIDs +// +#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101 +#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102 +#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103 +#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104 +#define OID_WW_GEN_INDICATION_REQUEST 0x09010105 +#define OID_WW_GEN_DEVICE_INFO 0x09010106 +#define OID_WW_GEN_OPERATION_MODE 0x09010107 +#define OID_WW_GEN_LOCK_STATUS 0x09010108 +#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109 +#define OID_WW_GEN_NETWORK_ID 0x0901010A +#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B +#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C +#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D +#define OID_WW_GEN_BASESTATION_ID 0x0901010E +#define OID_WW_GEN_CHANNEL_ID 0x0901010F +#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110 +#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111 +#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112 +#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113 +#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114 +#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115 +#define OID_WW_GEN_LATENCY 0x09010116 +#define OID_WW_GEN_BATTERY_LEVEL 0x09010117 +#define OID_WW_GEN_EXTERNAL_POWER 0x09010118 +// +// Network Dependent OIDs - Mobitex: +// +#define OID_WW_MBX_SUBADDR 0x09050101 +// OID 0x09050102 is reserved and may not be used +#define OID_WW_MBX_FLEXLIST 0x09050103 +#define OID_WW_MBX_GROUPLIST 0x09050104 +#define OID_WW_MBX_TRAFFIC_AREA 0x09050105 +#define OID_WW_MBX_LIVE_DIE 0x09050106 +#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107 +// +// Network Dependent OIDs - Pinpoint: +// +#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101 +#define OID_WW_PIN_LAST_LOCATION 0x09090102 +#define OID_WW_PIN_LOC_FIX 0x09090103 +// +// Network Dependent - CDPD: +// +#define OID_WW_CDPD_SPNI 0x090D0101 +#define OID_WW_CDPD_WASI 0x090D0102 +#define OID_WW_CDPD_AREA_COLOR 0x090D0103 +#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104 +#define OID_WW_CDPD_EID 0x090D0105 +#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106 +#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107 +#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108 +#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109 +#define OID_WW_CDPD_NEI 0x090D010A +#define OID_WW_CDPD_NEI_STATE 0x090D010B +#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C +#define OID_WW_CDPD_SLEEP_MODE 0x090D010D +#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E +#define OID_WW_CDPD_TEI 0x090D010F +#define OID_WW_CDPD_RSSI 0x090D0110 +// +// Network Dependent - Ardis: +// +#define OID_WW_ARD_SNDCP 0x09110101 +#define OID_WW_ARD_TMLY_MSG 0x09110102 +#define OID_WW_ARD_DATAGRAM 0x09110103 +// +// Network Dependent - DataTac: +// +#define OID_WW_TAC_COMPRESSION 0x09150101 +#define OID_WW_TAC_SET_CONFIG 0x09150102 +#define OID_WW_TAC_GET_STATUS 0x09150103 +#define OID_WW_TAC_USER_HEADER 0x09150104 +// +// Network Dependent - Metricom: +// +#define OID_WW_MET_FUNCTION 0x09190101 +// +// IRDA objects +// +#define OID_IRDA_RECEIVING 0x0A010100 +#define OID_IRDA_TURNAROUND_TIME 0x0A010101 +#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102 +#define OID_IRDA_LINK_SPEED 0x0A010103 +#define OID_IRDA_MEDIA_BUSY 0x0A010104 +#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200 +#define OID_IRDA_RATE_SNIFF 0x0A010201 +#define OID_IRDA_UNICAST_LIST 0x0A010202 +#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203 +#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204 +#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205 +// +// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/ +// OID_GEN_MEDIA_IN_USE). +// +typedef enum _NDIS_MEDIUM { + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, // defined for convenience, not a real medium + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumMax // Not a real medium, defined as an upper-bound +} NDIS_MEDIUM, *PNDIS_MEDIUM; + +// +// Hardware status codes (OID_GEN_HARDWARE_STATUS). +// +typedef enum _NDIS_HARDWARE_STATUS { + NdisHardwareStatusReady, + NdisHardwareStatusInitializing, + NdisHardwareStatusReset, + NdisHardwareStatusClosing, + NdisHardwareStatusNotReady +} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS; + +// +// this is the type passed in the OID_GEN_GET_TIME_CAPS request +// +typedef struct _GEN_GET_TIME_CAPS { + ULONG Flags; // Bits defined below + + ULONG ClockPrecision; +} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS; + +#define READABLE_LOCAL_CLOCK 0x000000001 +#define CLOCK_NETWORK_DERIVED 0x000000002 +#define CLOCK_PRECISION 0x000000004 +#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008 +#define TIMED_SEND_CAPABLE 0x000000010 +#define TIME_STAMP_CAPABLE 0x000000020 +// +// +// this is the type passed in the OID_GEN_GET_NETCARD_TIME request +// +typedef struct _GEN_GET_NETCARD_TIME { + ULONG ReadTime; +} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME; + +// +// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE). +// +typedef enum _NDIS_FDDI_ATTACHMENT_TYPE { + NdisFddiTypeIsolated = 1, + NdisFddiTypeLocalA, + NdisFddiTypeLocalB, + NdisFddiTypeLocalAB, + NdisFddiTypeLocalS, + NdisFddiTypeWrapA, + NdisFddiTypeWrapB, + NdisFddiTypeWrapAB, + NdisFddiTypeWrapS, + NdisFddiTypeCWrapA, + NdisFddiTypeCWrapB, + NdisFddiTypeCWrapS, + NdisFddiTypeThrough +} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE; + +// +// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE). +// +typedef enum _NDIS_FDDI_RING_MGT_STATE { + NdisFddiRingIsolated = 1, + NdisFddiRingNonOperational, + NdisFddiRingOperational, + NdisFddiRingDetect, + NdisFddiRingNonOperationalDup, + NdisFddiRingOperationalDup, + NdisFddiRingDirected, + NdisFddiRingTrace +} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE; + +// +// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE). +// +typedef enum _NDIS_FDDI_LCONNECTION_STATE { + NdisFddiStateOff = 1, + NdisFddiStateBreak, + NdisFddiStateTrace, + NdisFddiStateConnect, + NdisFddiStateNext, + NdisFddiStateSignal, + NdisFddiStateJoin, + NdisFddiStateVerify, + NdisFddiStateActive, + NdisFddiStateMaintenance +} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE; + +// +// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE). +// +typedef enum _NDIS_WAN_MEDIUM_SUBTYPE { + NdisWanMediumHub, + NdisWanMediumX_25, + NdisWanMediumIsdn, + NdisWanMediumSerial, + NdisWanMediumFrameRelay, + NdisWanMediumAtm, + NdisWanMediumSonet, + NdisWanMediumSW56K +} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE; + +// +// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT). +// +typedef enum _NDIS_WAN_HEADER_FORMAT { + NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID + NdisWanHeaderEthernet // emulation of ethernet header +} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT; + +// +// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE). +// +typedef enum _NDIS_WAN_QUALITY { + NdisWanRaw, + NdisWanErrorControl, + NdisWanReliable +} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY; + +// +// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE). +// +typedef enum _NDIS_802_5_RING_STATE { + NdisRingStateOpened = 1, + NdisRingStateClosed, + NdisRingStateOpening, + NdisRingStateClosing, + NdisRingStateOpenFailure, + NdisRingStateRingFailure +} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE; + +// +// Defines the state of the LAN media +// +typedef enum _NDIS_MEDIA_STATE { + NdisMediaStateConnected, + NdisMediaStateDisconnected +} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE; + +// +// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority +// +typedef ULONG Priority_802_3; // 0-7 priority levels +// +// The following structure is used to query OID_GEN_CO_LINK_SPEED and +// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current +// link speed of the adapter. The second will return the minimum link speed +// the adapter is capable of. +// + +typedef struct _NDIS_CO_LINK_SPEED { + ULONG Outbound; + ULONG Inbound; +} NDIS_CO_LINK_SPEED, + +*PNDIS_CO_LINK_SPEED; +// +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). +// +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_SMT 0x0040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 +// +// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS). +// +#define NDIS_RING_SIGNAL_LOSS 0x00008000 +#define NDIS_RING_HARD_ERROR 0x00004000 +#define NDIS_RING_SOFT_ERROR 0x00002000 +#define NDIS_RING_TRANSMIT_BEACON 0x00001000 +#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800 +#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400 +#define NDIS_RING_REMOVE_RECEIVED 0x00000200 +#define NDIS_RING_COUNTER_OVERFLOW 0x00000100 +#define NDIS_RING_SINGLE_STATION 0x00000080 +#define NDIS_RING_RING_RECOVERY 0x00000040 +// +// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS). +// +#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001 +#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002 +#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004 +// +// Ndis MAC option bits (OID_GEN_MAC_OPTIONS). +// +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 +// +// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS. +// +#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001 +#ifdef IRDA +// +// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo +// This is the per-packet info specified on a per-packet basis +// +typedef struct _NDIS_IRDA_PACKET_INFO { + UINT ExtraBOFs; + UINT MinTurnAroundTime; +} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO; + +#endif +#ifdef WIRELESS_WAN +// +// Wireless WAN structure definitions +// +// +// currently defined Wireless network subtypes +// +typedef enum _NDIS_WW_NETWORK_TYPE { + NdisWWGeneric, + NdisWWMobitex, + NdisWWPinpoint, + NdisWWCDPD, + NdisWWArdis, + NdisWWDataTAC, + NdisWWMetricom, + NdisWWGSM, + NdisWWCDMA, + NdisWWTDMA, + NdisWWAMPS, + NdisWWInmarsat, + NdisWWpACT +} NDIS_WW_NETWORK_TYPE; + +// +// currently defined header formats +// +typedef enum _NDIS_WW_HEADER_FORMAT { + NdisWWDIXEthernetFrames, + NdisWWMPAKFrames, + NdisWWRDLAPFrames, + NdisWWMDC4800Frames +} NDIS_WW_HEADER_FORMAT; + +// +// currently defined encryption types +// +typedef enum _NDIS_WW_ENCRYPTION_TYPE { + NdisWWUnknownEncryption = -1, + NdisWWNoEncryption, + NdisWWDefaultEncryption +} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE; + +// +// OID_WW_GEN_INDICATION_REQUEST +// +typedef struct _NDIS_WW_INDICATION_REQUEST { + NDIS_OID Oid; // IN + + UINT uIndicationFlag; // IN + + UINT uApplicationToken; // IN OUT + + HANDLE hIndicationHandle; // IN OUT + + INT iPollingInterval; // IN OUT + + NDIS_VAR_DATA_DESC InitialValue; // IN OUT + + NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication + + NDIS_VAR_DATA_DESC TriggerValue; // IN + +} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST; + +#define OID_INDICATION_REQUEST_ENABLE 0x0000 +#define OID_INDICATION_REQUEST_CANCEL 0x0001 +// +// OID_WW_GEN_DEVICE_INFO +// +typedef struct _WW_DEVICE_INFO { + NDIS_VAR_DATA_DESC Manufacturer; + NDIS_VAR_DATA_DESC ModelNum; + NDIS_VAR_DATA_DESC SWVersionNum; + NDIS_VAR_DATA_DESC SerialNum; +} WW_DEVICE_INFO, *PWW_DEVICE_INFO; + +// +// OID_WW_GEN_OPERATION_MODE +// +typedef INT WW_OPERATION_MODE; // 0 = Normal mode + // 1 = Power saving mode + // -1 = mode unknown +// +// OID_WW_GEN_LOCK_STATUS +// + +typedef INT WW_LOCK_STATUS; // 0 = unlocked + // 1 = locked + // -1 = unknown lock status +// +// OID_WW_GEN_DISABLE_TRANSMITTER +// + +typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled + // 1 = transmitter disabled + // -1 = unknown value +// +// OID_WW_GEN_NETWORK_ID +// + +typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID; +// +// OID_WW_GEN_PERMANENT_ADDRESS +// +typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS; +// +// OID_WW_GEN_CURRENT_ADDRESS +// +typedef struct _WW_CURRENT_ADDRESS { + NDIS_WW_HEADER_FORMAT Format; + NDIS_VAR_DATA_DESC Address; +} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS; + +// +// OID_WW_GEN_SUSPEND_DRIVER +// +typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational + // 1 = driver suspended +// +// OID_WW_GEN_BASESTATION_ID +// + +typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID; +// +// OID_WW_GEN_CHANNEL_ID +// +typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID; +// +// OID_WW_GEN_ENCRYPTION_STATE +// +typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled + // 1 = if encryption is enabled +// +// OID_WW_GEN_CHANNEL_QUALITY +// + +typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact, + // 1-100 = Quality of Channel (100 is highest quality). + // -1 = channel quality is unknown +// +// OID_WW_GEN_REGISTRATION_STATUS +// + +typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied + // 1 = Registration pending + // 2 = Registered + // -1 = unknown registration status +// +// OID_WW_GEN_RADIO_LINK_SPEED +// + +typedef UINT WW_RADIO_LINK_SPEED; // Bits per second. +// +// OID_WW_GEN_LATENCY +// + +typedef UINT WW_LATENCY; // milliseconds +// +// OID_WW_GEN_BATTERY_LEVEL +// + +typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage + // (100=fully charged) + // -1 = unknown battery level. +// +// OID_WW_GEN_EXTERNAL_POWER +// + +typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected + // 1 = external power connected + // -1 = unknown +// +// OID_WW_MET_FUNCTION +// + +typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION; +// +// OID_WW_TAC_COMPRESSION +// +typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression + // is being used. +// +// OID_WW_TAC_SET_CONFIG +// + +typedef struct _WW_TAC_SETCONFIG { + NDIS_VAR_DATA_DESC RCV_MODE; + NDIS_VAR_DATA_DESC TX_CONTROL; + NDIS_VAR_DATA_DESC RX_CONTROL; + NDIS_VAR_DATA_DESC FLOW_CONTROL; + NDIS_VAR_DATA_DESC RESET_CNF; + NDIS_VAR_DATA_DESC READ_CNF; +} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG; + +// +// OID_WW_TAC_GET_STATUS +// +typedef struct _WW_TAC_GETSTATUS { + BOOLEAN Action; // Set = Execute command. + + NDIS_VAR_DATA_DESC Command; + NDIS_VAR_DATA_DESC Option; + NDIS_VAR_DATA_DESC Response; // The response to the requested command + // - max. length of string is 256 octets. + +} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS; + +// +// OID_WW_TAC_USER_HEADER +// +typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets. +// +// OID_WW_ARD_SNDCP +// + +typedef struct _WW_ARD_SNDCP { + NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported. + + INT BlockSize; // The block size used for SNDCP + + INT Window; // The window size used in SNDCP + +} WW_ARD_SNDCP, *PWW_ARD_SNDCP; + +// +// OID_WW_ARD_TMLY_MSG +// +typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel. +// +// OID_WW_ARD_DATAGRAM +// + +typedef struct _WW_ARD_DATAGRAM { + BOOLEAN LoadLevel; // Byte that contains the load level info. + + INT SessionTime; // Datagram session time remaining. + + NDIS_VAR_DATA_DESC HostAddr; // Host address. + + NDIS_VAR_DATA_DESC THostAddr; // Test host address. + +} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM; + +// +// OID_WW_CDPD_SPNI +// +typedef struct _WW_CDPD_SPNI { + UINT SPNI[10]; //10 16-bit service provider network IDs + + INT OperatingMode; // 0 = ignore SPNI, + // 1 = require SPNI from list, + // 2 = prefer SPNI from list. + // 3 = exclude SPNI from list. + +} WW_CDPD_SPNI, *PWW_CDPD_SPNI; + +// +// OID_WW_CDPD_WASI +// +typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID { + UINT WASI[10]; //10 16-bit wide area service IDs + + INT OperatingMode; // 0 = ignore WASI, + // 1 = Require WASI from list, + // 2 = prefer WASI from list + // 3 = exclude WASI from list. + +} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID; + +// +// OID_WW_CDPD_AREA_COLOR +// +typedef INT WW_CDPD_AREA_COLOR; +// +// OID_WW_CDPD_TX_POWER_LEVEL +// +typedef UINT WW_CDPD_TX_POWER_LEVEL; +// +// OID_WW_CDPD_EID +// +typedef NDIS_VAR_DATA_DESC WW_CDPD_EID; +// +// OID_WW_CDPD_HEADER_COMPRESSION +// +typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression, + // 1 = always compress headers, + // 2 = compress headers if MD-IS does + // -1 = unknown +// +// OID_WW_CDPD_DATA_COMPRESSION +// + +typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression, + // 1 = data compression enabled + // -1 = unknown +// +// OID_WW_CDPD_CHANNEL_SELECT +// + +typedef struct _WW_CDPD_CHANNEL_SELECT { + UINT ChannelID; // channel number + + UINT fixedDuration; // duration in seconds + +} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT; + +// +// OID_WW_CDPD_CHANNEL_STATE +// +typedef enum _WW_CDPD_CHANNEL_STATE { + CDPDChannelNotAvail, + CDPDChannelScanning, + CDPDChannelInitAcquired, + CDPDChannelAcquired, + CDPDChannelSleeping, + CDPDChannelWaking, + CDPDChannelCSDialing, + CDPDChannelCSRedial, + CDPDChannelCSAnswering, + CDPDChannelCSConnected, + CDPDChannelCSSuspended +} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE; + +// +// OID_WW_CDPD_NEI +// +typedef enum _WW_CDPD_NEI_FORMAT { + CDPDNeiIPv4, + CDPDNeiCLNP, + CDPDNeiIPv6 +} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT; +typedef enum _WW_CDPD_NEI_TYPE { + CDPDNeiIndividual, + CDPDNeiMulticast, + CDPDNeiBroadcast +} WW_CDPD_NEI_TYPE; +typedef struct _WW_CDPD_NEI { + UINT uNeiIndex; + WW_CDPD_NEI_FORMAT NeiFormat; + WW_CDPD_NEI_TYPE NeiType; + WORD NeiGmid; // group member identifier, only + // meaningful if NeiType == + // CDPDNeiMulticast + + NDIS_VAR_DATA_DESC NeiAddress; +} WW_CDPD_NEI; + +// +// OID_WW_CDPD_NEI_STATE +// +typedef enum _WW_CDPD_NEI_STATE { + CDPDUnknown, + CDPDRegistered, + CDPDDeregistered +} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE; +typedef enum _WW_CDPD_NEI_SUB_STATE { + CDPDPending, // Registration pending + CDPDNoReason, // Registration denied - no reason given + CDPDMDISNotCapable, // Registration denied - MD-IS not capable of + // handling M-ES at this time + CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to + // use this subnetwork + CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient + // authentication credentials + CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported + // authentication credentials + CDPDUsageExceeded, // Registration denied - NEI has exceeded usage + // limitations + CDPDDeniedThisNetwork // Registration denied on this network, service + // may be obtained on alternate Service Provider + // network +} WW_CDPD_NEI_SUB_STATE; +typedef struct _WW_CDPD_NEI_REG_STATE { + UINT uNeiIndex; + WW_CDPD_NEI_STATE NeiState; + WW_CDPD_NEI_SUB_STATE NeiSubState; +} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE; + +// +// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER +// +typedef struct _WW_CDPD_SERVICE_PROVIDER_ID { + UINT SPI[10]; //10 16-bit service provider IDs + + INT OperatingMode; // 0 = ignore SPI, + // 1 = require SPI from list, + // 2 = prefer SPI from list. + // 3 = exclude SPI from list. + +} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID; + +// +// OID_WW_CDPD_SLEEP_MODE +// +typedef INT WW_CDPD_SLEEP_MODE; +// +// OID_WW_CDPD_TEI +// +typedef ULONG WW_CDPD_TEI; +// +// OID_WW_CDPD_CIRCUIT_SWITCHED +// +typedef struct _WW_CDPD_CIRCUIT_SWITCHED { + INT service_preference; // -1 = unknown, + // 0 = always use packet switched CDPD, + // 1 = always use CS CDPD via AMPS, + // 2 = always use CS CDPD via PSTN, + // 3 = use circuit switched via AMPS only + // when packet switched is not available. + // 4 = use packet switched only when circuit + // switched via AMPS is not available. + // 5 = device manuf. defined service + // preference. + // 6 = device manuf. defined service + // preference. + + INT service_status; // -1 = unknown, + // 0 = packet switched CDPD, + // 1 = circuit switched CDPD via AMPS, + // 2 = circuit switched CDPD via PSTN. + + INT connect_rate; // CS connection bit rate (bits per second). + // 0 = no active connection, + // -1 = unknown + // Dial code last used to dial. + + NDIS_VAR_DATA_DESC dial_code[20]; + + UINT sid; // Current AMPS system ID + + INT a_b_side_selection; // -1 = unknown, + // 0 = no AMPS service + // 1 = AMPS "A" side channels selected + // 2 = AMPS "B" side channels selected + + INT AMPS_channel; // -1= unknown + // 0 = no AMPS service. + // 1-1023 = AMPS channel number in use + + UINT action; // 0 = no action + // 1 = suspend (hangup) + // 2 = dial + + // Default dial code for CS CDPD service + // encoded as specified in the CS CDPD + // implementor guidelines. + NDIS_VAR_DATA_DESC default_dial[20]; + + // Number for the CS CDPD network to call + // back the mobile, encoded as specified in + // the CS CDPD implementor guidelines. + NDIS_VAR_DATA_DESC call_back[20]; + + UINT sid_list[10]; // List of 10 16-bit preferred AMPS + // system IDs for CS CDPD. + + UINT inactivity_timer; // Wait time after last data before dropping + // call. + // 0-65535 = inactivity time limit (seconds). + + UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines. + +} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED; +typedef UINT WW_CDPD_RSSI; +// +// OID_WW_PIN_LOC_AUTHORIZE +// +typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized + // 1 = authorized + // -1 = unknown +// +// OID_WW_PIN_LAST_LOCATION +// OID_WW_PIN_LOC_FIX +// + +typedef struct _WW_PIN_LOCATION { + INT Latitude; // Latitude in hundredths of a second + + INT Longitude; // Longitude in hundredths of a second + + INT Altitude; // Altitude in feet + + INT FixTime; // Time of the location fix, since midnight, local time (of the + // current day), in tenths of a second + + INT NetTime; // Current local network time of the current day, since midnight, + // in tenths of a second + + INT LocQuality; // 0-100 = location quality + + INT LatReg; // Latitude registration offset, in hundredths of a second + + INT LongReg; // Longitude registration offset, in hundredths of a second + + INT GMTOffset; // Offset in minutes of the local time zone from GMT + +} WW_PIN_LOCATION, *PWW_PIN_LOCATION; + +// +// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox +// +typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag +// +// OID_WW_MBX_SUBADDR +// + +typedef struct _WW_MBX_PMAN { + BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN + + UINT MAN; + UCHAR PASSWORD[8]; // Password should be null for Logout and indications. + // Maximum length of password is 8 chars. + +} WW_MBX_PMAN, *PWW_MBX_PMAN; + +// +// OID_WW_MBX_FLEXLIST +// +typedef struct _WW_MBX_FLEXLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[7]; // List of MANs. + +} WW_MBX_FLEXLIST; + +// +// OID_WW_MBX_GROUPLIST +// +typedef struct _WW_MBX_GROUPLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[15]; // List of MANs. + +} WW_MBX_GROUPLIST; + +// +// OID_WW_MBX_TRAFFIC_AREA +// +typedef enum _WW_MBX_TRAFFIC_AREA { + unknown_traffic_area, // The driver has no information about the current traffic area. + in_traffic_area, // Mobile unit has entered a subscribed traffic area. + in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized. + unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized. +} WW_MBX_TRAFFIC_AREA; + +// +// OID_WW_MBX_LIVE_DIE +// +typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received + // 1 = LIVE last received + // -1 = unknown +// +// OID_WW_MBX_TEMP_DEFAULTLIST +// + +typedef struct _WW_MBX_CHANNEL_PAIR { + UINT Mobile_Tx; + UINT Mobile_Rx; +} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR; +typedef struct _WW_MBX_TEMPDEFAULTLIST { + UINT Length; + WW_MBX_CHANNEL_PAIR ChannelPair[1]; +} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST; + +#endif // WIRELESS_WAN +#endif // _NTDDNDIS_ diff --git a/plugins/dev9/DEV9linuz/Win32/Packet.lib b/plugins/dev9/DEV9linuz/Win32/Packet.lib new file mode 100644 index 0000000000000000000000000000000000000000..253d81f07f12821a08e74e5271c5d2c00170f722 GIT binary patch literal 8180 zcmcgxOLG%P5N_Fk!C)}*`z7Zs`l=7e>2}adb(%Evp34E?T26V zex6c)^K(l}bD5=u`Rl5F&ikBS%y_R`y#VkfKwkr(e-Gf|3xLt*Tt@B#Fd5wEGBygp zWPHn$*Z4$9zUMOX67eVlZ@7#-MLf!Y&1Lc}0F%KSm$7$fN0~rAS8m`FWd=Ez3_tM% z%M7CoJ>xQscqUV?xJ)nNH_A|&%M`Ym$#9a(47P#EjC%H;Z@kCA+-+z2!iul)IPB2JP@O2XJ%o>wCF7rPY<<3Y0e8g4ybWR=M@)8>`i> zHXB$?wQiR}Y`nx*mSaRyy+E$Es(V%|46j*vsk^q-SgDk4$7-p~Q4Abguo@Nqrb4M+ zN4CSDXyDkDTCKTVb}UoPx{YJj8&$`Irh0C_-Lj1JQawlJt!)bj&s42u;*eXlX4^6j zoND3dg5`Yu+pT}wsyh0lAdpySYu6h)O+(MHy}m`%y-{rx zo41+W_?)Ovl?3OaMXy!tJ`VXeCca76TN7~>Tca;Zl^&lM;a7twpy?1 zQ;bb!Xy3%~>usi6YgDX?S~oQuK3gq{Y&8o2jXr=qjNdOV0zAh&aeoA0e-LB&7{Jyz zz-yHE82ewM{>=cuQ`Fn|d^-t{L)<(3em((k17μK?xBP@WB;ej4D_6u=@r)A)TK z-;-#2inzyEz8~c}a$?GaUN{fupdU`b1dPBG48bs*gtIUUC!h!V;3AxcGcW*2NWlzT zfJqpGaTtX`n1%#&byU9FUoYm^X^Kw4Xc!V^P;E>is1LX_*YV}bT>v!!=R{p-I1r^o zLi1dSgnxr`ah0BFxz>=>jL|(1I%VSH70Hw*@))}PO(jlhfi<`$yoJKon_n+U6hak< z04yrF@k&4f0SF=HK&OT20to}b4b2BPJW9sVU5;iW)$yo>x*ye}Z$u_S%@wtx#36$g zV-_LKsg;PxV}|H1+?Ccs_a=%yEH3H}ObaP)Obwbdt0u!1LAtRTl%-xv-@cR6nwieD zv7ipG;hD*pW_>851{I4jNop6q-#e4Mi^(NZ9V)b~pD|DzzHVU>`bVU7OE% z=dG>YY@!>In@?8$O#o&E%u4`?vx!sq7V*OzhiL+{N%*hZH6f5;*&p{Q9^nQ52g{X; z^zdj+45a|16bV&)s3=0zXE^ zO0pXGl=Qe`ebUuQ7Hqa@WD{*eKpuNSOSjLb||S ziJx5cP0UYz^*_8P^AlF@kh?W|-Y=aEj>L;}}l4KGRX21Lvn zz2qTu@-^lvkBHNKl1)20NtTaTzH(8<@B{aY}{%@mI21<9tK@+1lI z(s+F7MKd2>li?Ot%$|Q6(g{< +#include "devioctl.h" +#ifdef HAVE_DAG_API +#include +#endif /* HAVE_DAG_API */ + +// Working modes +#define PACKET_MODE_CAPT 0x0 ///< Capture mode +#define PACKET_MODE_STAT 0x1 ///< Statistical mode +#define PACKET_MODE_MON 0x2 ///< Monitoring mode +#define PACKET_MODE_DUMP 0x10 ///< Dump mode +#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode + +// ioctls +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size. +#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program. +#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats. +#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout. +#define pBIOCSMODE 7412 ///< IOCTL code: set working mode. +#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app. +#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call. +#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value. +#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value. +#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only. +#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only. +#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode. +#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer. +#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets. +#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets. +#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function. +#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function. + +#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only. + + +/// Alignment macro. Defines the alignment size. +#define Packet_ALIGNMENT sizeof(int) +/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) + + +#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent +#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent + +/*! + \brief Network type structure. + + This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. +*/ +typedef struct NetType +{ + UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) + ULONGLONG LinkSpeed; ///< The speed of the network in bits per second +}NetType; + + +//some definitions stolen from libpcap + +#ifndef BPF_MAJOR_VERSION + +/*! + \brief A BPF pseudo-assembly program. + + The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. +*/ +struct bpf_program +{ + UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. + struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. +}; + +/*! + \brief A single BPF pseudo-instruction. + + bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. +*/ +struct bpf_insn +{ + USHORT code; ///< Instruction type and addressing mode. + UCHAR jt; ///< Jump if true + UCHAR jf; ///< Jump if false + int k; ///< Generic field used for various purposes. +}; + +/*! + \brief Structure that contains a couple of statistics values on the current capture. + + It is used by packet.dll to return statistics about a capture session. +*/ +struct bpf_stat +{ + UINT bs_recv; ///< Number of packets that the driver received from the network adapter + ///< from the beginning of the current capture. This value includes the packets + ///< lost by the driver. + UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. + ///< Basically, a packet is lost when the the buffer of the driver is full. + ///< In this situation the packet cannot be stored and the driver rejects it. + UINT ps_ifdrop; ///< drops by interface. XXX not yet supported + UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and + ///< thus reach the application. +}; + +/*! + \brief Packet header. + + This structure defines the header associated with every packet delivered to the application. +*/ +struct bpf_hdr +{ + struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. + ///< It is stored in a TimeVal structure. + UINT bh_caplen; ///< Length of captured portion. The captured portion can be different + ///< from the original packet, because it is possible (with a proper filter) + ///< to instruct the driver to capture only a portion of the packets. + UINT bh_datalen; ///< Original length of packet + USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, + ///< a padding could be added between the end of this structure and the packet + ///< data for performance reasons. This filed can be used to retrieve the actual data + ///< of the packet. +}; + +/*! + \brief Dump packet header. + + This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). + It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a + packet in a dump file. This makes straightforward sending WinPcap dump files to the network. +*/ +struct dump_bpf_hdr{ + struct timeval ts; ///< Time stamp of the packet + UINT caplen; ///< Length of captured portion. The captured portion can smaller than the + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + + +#endif + +#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices +#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links +#define NMAX_PACKET 65535 + +/* + * Desired design of maximum size and alignment. + * These are implementation specific. + */ +#define _SS_MAXSIZE 128 // Maximum size. +#define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment. + +/* + * Definitions used for sockaddr_storage structure paddings design. + */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \ + + _SS_ALIGNSIZE)) + +struct sockaddr_storage { + short ss_family; // Address family. + char __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, this is to make + // implementation specific pad up to + // alignment field that follows explicit + // in the data structure. + __int64 __ss_align; // Field to force desired structure. + char __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad to achieve desired size; + // _SS_MAXSIZE value minus size of + // ss_family, __ss_pad1, and + // __ss_align fields is 112. +}; + +/*! + \brief Addresses of a network adapter. + + This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with + an adapter. +*/ +typedef struct npf_if_addr { + struct sockaddr_storage IPAddress; ///< IP address. + struct sockaddr_storage SubnetMask; ///< Netmask for that address. + struct sockaddr_storage Broadcast; ///< Broadcast address. +}npf_if_addr; + + +#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API. +#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API. +#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. +#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API. + + +typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API +typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API + +#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter +#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter +#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card +#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file +#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones. + +/*! + \brief Contains comprehensive information about a network adapter. + + This structure is filled with all the accessory information that the user can need about an adapter installed + on his system. +*/ +typedef struct _ADAPTER_INFO +{ + struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list. + CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter. + CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter + UINT MacAddressLen; ///< Length of the link layer address. + UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address. + NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter. + INT NNetworkAddresses; ///< Number of network layer addresses of this adapter. + npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter. + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. +} +ADAPTER_INFO, *PADAPTER_INFO; + +/*! + \brief Describes an opened network adapter. + + This structure is the most important for the functioning of packet.dll, but the great part of its fields + should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters +*/ +typedef struct _ADAPTER { + HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. + CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. + int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated + ///< on the wire. + HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. + ///< It can be passed to standard Win32 functions (like WaitForSingleObject + ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some + ///< data. It is particularly useful in GUI applications that need to wait + ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() + ///< function can be used to define the minimum amount of data in the kernel buffer + ///< that will cause the event to be signalled. + + UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and + ///< ReadEvent will be signaled, also if no packets were captured + CHAR Name[ADAPTER_NAME_LENGTH]; + PWAN_ADAPTER pWanAdapter; + UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API. +#ifdef HAVE_DAG_API + dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter + PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card + struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure + unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry + DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps). +#endif // HAVE_DAG_API +} ADAPTER, *LPADAPTER; + +/*! + \brief Structure that contains a group of packets coming from the driver. + + This structure defines the header associated with every packet delivered to the application. +*/ +typedef struct _PACKET { + HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. + OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. + PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for + ///< details about the organization of the data in this buffer + UINT Length; ///< Length of the buffer + DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data + ///< received by the last call to PacketReceivePacket() + BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. +} PACKET, *LPPACKET; + +/*! + \brief Structure containing an OID request. + + It is used by the PacketRequest() function to send an OID to the interface card driver. + It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, + the list of the multicast groups defined on it, and so on. +*/ +struct _PACKET_OID_DATA { + ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + ULONG Length; ///< Length of the data field + UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + + +#if _DBG +#define ODS(_x) OutputDebugString(TEXT(_x)) +#define ODSEx(_x, _y) +#else +#ifdef _DEBUG_TO_FILE +/*! + \brief Macro to print a debug string. The behavior differs depending on the debug level +*/ +#define ODS(_x) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, "%s", _x); \ + fclose(f); \ +} +/*! + \brief Macro to print debug data with the printf convention. The behavior differs depending on + the debug level +*/ +#define ODSEx(_x, _y) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, _x, _y); \ + fclose(f); \ +} + + + +LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName); +#else +#define ODS(_x) +#define ODSEx(_x, _y) +#endif +#endif + +/* We load dinamically the dag library in order link it only when it's present on the system */ +#ifdef HAVE_DAG_API +typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll +typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll +typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll +typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll +#endif // HAVE_DAG_API + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @} + */ + +// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent +// opening of firewire adapters +#define FIREWIRE_SUBSTR L"1394" + +void PacketPopulateAdaptersInfoList(); +PWCHAR SChar2WChar(PCHAR string); +PCHAR WChar2SChar(PWCHAR string); +BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen); +PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName); +BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName); +BOOLEAN IsFireWire(TCHAR *AdapterDesc); + + +//--------------------------------------------------------------------------- +// EXPORTED FUNCTIONS +//--------------------------------------------------------------------------- + +PCHAR PacketGetVersion(); +PCHAR PacketGetDriverVersion(); +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); +INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen); +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); +LPADAPTER PacketOpenAdapter(PCHAR AdapterName); +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); +INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); +LPPACKET PacketAllocatePacket(void); +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); +VOID PacketFreePacket(LPPACKET lpPacket); +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); +BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); +BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries); +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); +BOOL PacketStopDriver(); +VOID PacketCloseAdapter(LPADAPTER lpAdapter); + +#ifdef __cplusplus +} +#endif + +#endif //__PACKET32 diff --git a/plugins/dev9/DEV9linuz/Win32/Win32.c b/plugins/dev9/DEV9linuz/Win32/Win32.c new file mode 100644 index 0000000..0df0870 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/Win32.c @@ -0,0 +1,132 @@ +#include +#include +#include + +#include "Config.h" +#include "resource.h" +#include "DEV9.h" +#include "socks.h" + +HINSTANCE hInst; +HANDLE handleDEV9Thread = NULL; +DWORD dwThreadId, dwThrdParam; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "Dev9linuz Msg", 0); +} + +void OnInitDialog(HWND hW) { + char *dev; + int i; + + LoadConf(); + + ComboBox_AddString(GetDlgItem(hW, IDC_BAYTYPE), "Expansion"); + ComboBox_AddString(GetDlgItem(hW, IDC_BAYTYPE), "PC Card"); + for (i=0; i +#include + +#define IDC_STATIC (-1) diff --git a/plugins/dev9/DEV9linuz/Win32/libpacket.a b/plugins/dev9/DEV9linuz/Win32/libpacket.a new file mode 100644 index 0000000000000000000000000000000000000000..b70fed022f676e746676cb82fb9f2c4623196a53 GIT binary patch literal 23732 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 literal 0 HcmV?d00001 diff --git a/plugins/dev9/DEV9linuz/Win32/plugin.def b/plugins/dev9/DEV9linuz/Win32/plugin.def new file mode 100644 index 0000000..cf90ede --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/plugin.def @@ -0,0 +1,24 @@ +EXPORTS + DEV9ThreadProc @4 + DEV9about = DEV9about@0 @5 + DEV9close = DEV9close@0 @6 + DEV9configure = DEV9configure@0 @7 + DEV9init = DEV9init@0 @8 + DEV9irq @9 DATA + DEV9irqCallback = DEV9irqCallback@4 @10 + DEV9irqHandler = DEV9irqHandler@0 @11 + DEV9open = DEV9open@4 @12 + DEV9read16 = DEV9read16@4 @13 + DEV9read32 = DEV9read32@4 @14 + DEV9read8 = DEV9read8@4 @15 + DEV9readDMA8Mem = DEV9readDMA8Mem@8 @16 + DEV9shutdown = DEV9shutdown@0 @17 + DEV9test = DEV9test@0 @18 + DEV9thread @19 + DEV9write16 = DEV9write16@8 @20 + DEV9write32 = DEV9write32@8 @21 + DEV9write8 = DEV9write8@8 @22 + DEV9writeDMA8Mem = DEV9writeDMA8Mem@8 @23 + PS2EgetLibName = PS2EgetLibName@0 @28 + PS2EgetLibType = PS2EgetLibType@0 @29 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @30 diff --git a/plugins/dev9/DEV9linuz/Win32/resource.h b/plugins/dev9/DEV9linuz/Win32/resource.h new file mode 100644 index 0000000..fc9591a --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by DEV9linuz.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_COMBO1 1007 +#define IDC_ETHDEV 1007 +#define IDC_BAYTYPE 1008 +#define IDC_ETHENABLED 1009 +#define IDC_HDDFILE 1010 +#define IDC_HDDENABLED 1011 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/dev9/DEV9linuz/Win32/socks.c b/plugins/dev9/DEV9linuz/Win32/socks.c new file mode 100644 index 0000000..1c8a0c9 --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/socks.c @@ -0,0 +1,191 @@ +#include +#include + +#include "packet32.h" +#include "ntddndis.h" + +#include "socks.h" +#include "DEV9.h" + +#define BUFFER_SIZE (2048) + +LPADAPTER lpAdapter; +LPPACKET lpSendPacket; +LPPACKET lpRecvPacket; +u8 buffer[BUFFER_SIZE]; +u8 *buf; +int lbytes; +int tbytes; +typedef struct { + char name[256]; + char desc[256]; +} _Adapter; + +_Adapter AdapterList[16]; + +long sockOpen(char *Device) { + lpAdapter = PacketOpenAdapter(Device); + if (lpAdapter == NULL) return -1; + +#ifdef DEV9_LOG + DEV9_LOG("PacketOpenAdapter %s: %p\n", Device, lpAdapter); +#endif + + if(PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE){ + SysMessage("Warning: unable to set promiscuous mode!"); + } + + if(PacketSetBuff(lpAdapter,512000)==FALSE){ + SysMessage("Unable to set the kernel buffer!"); + return -1; + } + + if(PacketSetReadTimeout(lpAdapter,100)==FALSE){ + SysMessage("Warning: unable to set the read tiemout!"); + } + + if((lpRecvPacket = PacketAllocatePacket())==NULL){ + SysMessage("Error: failed to allocate the LPPACKET structure."); + return (-1); + } + if((lpSendPacket = PacketAllocatePacket())==NULL){ + SysMessage("Error: failed to allocate the LPPACKET structure."); + return (-1); + } + + lbytes=0; + tbytes=0; + + return 0; +} + +void sockClose() { + PacketCloseAdapter(lpAdapter); +} + +long sockSendData(void *pData, int Size) { + u8 *data = (u8*)pData; +// printf("_sendPacket %d (time=%d)\n", Size, timeGetTime()); + while (Size > 0) { + PacketInitPacket(lpSendPacket, data, Size > 1024 ? 1024 : Size); + if(PacketSendPacket(lpAdapter,lpSendPacket,FALSE)==FALSE){ + printf("Error: PacketSendPacket failed\n"); + return (-1); + } + data+= 1024; Size-= 1024; + PacketFreePacket(lpSendPacket); + } + + return 0; +} + +int _filterPacket(u8 *_buf) { +/* DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[5], _buf[4], _buf[3], _buf[2], _buf[1], _buf[0]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[11], _buf[10], _buf[9], _buf[8], _buf[7], _buf[6]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[17], _buf[16], _buf[15], _buf[14], _buf[13], _buf[12]); + DEV9_LOG("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", _buf[23], _buf[22], _buf[21], _buf[20], _buf[19], _buf[18]); +*/ + if (_buf[0] == 0xff && _buf[1] == 0xff && _buf[2] == 0xff && + _buf[3] == 0xff && _buf[4] == 0xff && _buf[5] == 0xff) { + return 1; + } else + if (_buf[0] == 0x00 && _buf[1] == 0x00 && _buf[2] == 0x00 && + _buf[3] == 0x00 && _buf[4] == 0x00 && _buf[5] == 0x00) { + return 1; + } else + if (*((u16*)&_buf[12]) == 0x0806) { + printf("ARP\n"); + return 1; + } + + return 0; +} + +int _recvPacket(void *pData) { + struct bpf_hdr *hdr; + u8 *data; + int ret=0; + int size; + + while (lbytes > 0) { + hdr = (struct bpf_hdr *)buf; +// DEV9_LOG("hdr %d,%d,%d\n", hdr->bh_hdrlen, hdr->bh_caplen, hdr->bh_datalen); +// DEV9_LOG("lbytes %d\n", lbytes); + data = buf+hdr->bh_hdrlen; + size = Packet_WORDALIGN(hdr->bh_hdrlen+hdr->bh_datalen); + buf+= size; lbytes-= size; + if (_filterPacket(data)) { + struct bpf_stat stat; + + ret = hdr->bh_datalen; + memcpy(pData, data, ret); + if(PacketGetStats(lpAdapter,&stat)==FALSE){ + printf("Warning: unable to get stats from the kernel!\n"); + } +// printf("_recvPacket %d (tbytes=%d, packets=%d, lost=%d, time=%d)\n", ret, tbytes, stat.bs_recv,stat.bs_drop, timeGetTime()); +// printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", data[5], data[4], data[3], data[2], data[1], data[0]); + break; + } + } + + return ret; +} + +long sockRecvData(void *pData, int Size) { + int ret; + + ret = _recvPacket(pData); + if (ret > 0) return ret; + + PacketInitPacket(lpRecvPacket, buffer, BUFFER_SIZE); + if(PacketReceivePacket(lpAdapter,lpRecvPacket,TRUE)==FALSE){ + printf("Error: PacketReceivePacket failed"); + return (-1); + } + lbytes = lpRecvPacket->ulBytesReceived; + tbytes+= lbytes; +// DEV9_LOG("PacketReceivePacket %d:\n", lbytes); + if (lbytes == 0) return 0; + memcpy(buffer, lpRecvPacket->Buffer, lbytes); + buf = buffer; + PacketFreePacket(lpRecvPacket); + + return _recvPacket(pData); +} + +long sockGetDevicesNum() { + char AdapterName[8192]; // string that contains a list of the network adapters + ULONG AdapterLength; + char *temp,*temp1; + int i; + + AdapterLength = sizeof(AdapterName); + if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){ + printf("Unable to retrieve the list of the adapters!\n"); + return -1; + } + temp=AdapterName; + temp1=AdapterName; + + i=0; + while (temp[0] != 0) { + strcpy(AdapterList[i++].name, temp); + temp+= strlen(temp)+1; + } + i=0; temp++; + while (temp[0] != 0) { + strcpy(AdapterList[i++].desc, temp); + temp+= strlen(temp)+1; + } + + return i; +} + +char *sockGetDevice(int index) { + return AdapterList[index].name; +} + +char *sockGetDeviceDesc(int index) { + return AdapterList[index].desc; +} + diff --git a/plugins/dev9/DEV9linuz/Win32/socks.h b/plugins/dev9/DEV9linuz/Win32/socks.h new file mode 100644 index 0000000..22cf9ab --- /dev/null +++ b/plugins/dev9/DEV9linuz/Win32/socks.h @@ -0,0 +1,12 @@ +#ifndef __SOCKS_H__ +#define __SOCKS_H__ + +long sockOpen(char *Device); +void sockClose(); +long sockSendData(void *pData, int Size); +long sockRecvData(void *pData, int Size); +long sockGetDevicesNum(); +char *sockGetDevice(int index); +char *sockGetDeviceDesc(int index); + +#endif /* __SOCKS_H__*/ diff --git a/plugins/dev9/DEV9linuz/flash.c b/plugins/dev9/DEV9linuz/flash.c new file mode 100644 index 0000000..a9300e2 --- /dev/null +++ b/plugins/dev9/DEV9linuz/flash.c @@ -0,0 +1,283 @@ +// The code has been designed for 64Mb flash and uses as file support the second memory card + +#include +#include "DEV9.h" + +#define PAGE_SIZE_BITS 9 +#define PAGE_SIZE (1<>2), page+PAGE_SIZE+0*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 1*(PAGE_SIZE>>2), page+PAGE_SIZE+1*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 2*(PAGE_SIZE>>2), page+PAGE_SIZE+2*3);//(ECC_SIZE>>2)); + xfromman_call20_calculateXors(page + 3*(PAGE_SIZE>>2), page+PAGE_SIZE+3*3);//(ECC_SIZE>>2)); +} + +static char* getCmdName(u32 cmd){ + switch(cmd) { + case SM_CMD_READ1: return "READ1"; + case SM_CMD_READ2: return "READ2"; + case SM_CMD_READ3: return "READ3"; + case SM_CMD_RESET: return "RESET"; + case SM_CMD_WRITEDATA: return "WRITEDATA"; + case SM_CMD_PROGRAMPAGE: return "PROGRAMPAGE"; + case SM_CMD_ERASEBLOCK: return "ERASEBLOCK"; + case SM_CMD_ERASECONFIRM: return "ERASECONFIRM"; + case SM_CMD_GETSTATUS: return "GETSTATUS"; + case SM_CMD_READID: return "READID"; + default: return "unknown"; + } +} + +void CALLBACK FLASHinit(){ + FILE *fd; + + id= FLASH_ID_64MBIT; + counter= 0; + addrbyte= 0; + + address = 0; + memset(data, 0xFF, PAGE_SIZE); + calculateECC(data); + ctrl = FLASH_PP_READY; + + if (fd=fopen("memcards\\Mcd002.ps2", "rb")){ + fread(file, 1, CARD_SIZE_ECC, fd); + fclose(fd); + }else + memset(file, 0xFF, CARD_SIZE_ECC); +} + +u32 CALLBACK FLASHread32(u32 addr, int size) { + u32 value, refill= 0; + + switch(addr) { + case FLASH_R_DATA: + memcpy(&value, &data[counter], size); + counter += size; +#ifdef DEV9_LOG + DEV9_LOG("*FLASH DATA %dbit read 0x%08lX %s\n", size*8, value, (ctrl & FLASH_PP_READ) ? "READ_ENABLE" : "READ_DISABLE"); +#endif + if (cmd == SM_CMD_READ3){ + if (counter >= PAGE_SIZE_ECC){ + counter= PAGE_SIZE; + refill= 1; + } + }else{ + if ( (ctrl & FLASH_PP_NOECC) && (counter >= PAGE_SIZE)){ + counter %= PAGE_SIZE; + refill= 1; + }else + if (!(ctrl & FLASH_PP_NOECC) && (counter >= PAGE_SIZE_ECC)){ + counter %= PAGE_SIZE_ECC; + refill= 1; + } + } + + if (refill){ + ctrl &= ~FLASH_PP_READY; + address += PAGE_SIZE; + address %= CARD_SIZE; + memcpy(data, file+(address>>PAGE_SIZE_BITS)*PAGE_SIZE_ECC, PAGE_SIZE); + calculateECC(data); // calculate ECC; should be in the file already + ctrl |= FLASH_PP_READY; + } + + return value; + + case FLASH_R_CMD: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CMD %dbit read %s DENIED\n", size*8, getCmdName(cmd)); +#endif + return cmd; + + case FLASH_R_ADDR: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH ADDR %dbit read DENIED\n", size*8); +#endif + return 0; + + case FLASH_R_CTRL: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CTRL %dbit read 0x%08lX\n", size*8, ctrl); +#endif + return ctrl; + + case FLASH_R_ID: + if (cmd == SM_CMD_READID){ +#ifdef DEV9_LOG + DEV9_LOG("*FLASH ID %dbit read 0x%08lX\n", size*8, id); +#endif + return id;//0x98=Toshiba/0xEC=Samsung maker code should be returned first + }else + if (cmd == SM_CMD_GETSTATUS){ + value= 0x80 | ((ctrl & 1) << 6); // 0:0=pass, 6:ready/busy, 7:1=not protected +#ifdef DEV9_LOG + DEV9_LOG("*FLASH STATUS %dbit read 0x%08lX\n", size*8, value); +#endif + return value; + }//else fall off + + default: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH Unkwnown %dbit read at address %lx\n", size*8, addr); +#endif + return 0; + } +} + +void CALLBACK FLASHwrite32(u32 addr, u32 value, int size) { + + switch(addr & 0x1FFFFFFF) { + case FLASH_R_DATA: + +#ifdef DEV9_LOG + DEV9_LOG("*FLASH DATA %dbit write 0x%08lX %s\n", size*8, value, (ctrl & FLASH_PP_WRITE) ? "WRITE_ENABLE" : "WRITE_DISABLE"); +#endif + memcpy(&data[counter], &value, size); + counter += size; + counter %= PAGE_SIZE_ECC;//should not get past the last byte, but at the end + break; + + case FLASH_R_CMD: + if (!(ctrl & FLASH_PP_READY)){ + if ((value != SM_CMD_GETSTATUS) && (value != SM_CMD_RESET)){ +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CMD %dbit write %s ILLEGAL in busy mode - IGNORED\n", size*8, getCmdName(value)); +#endif + break; + } + } + if (cmd == SM_CMD_WRITEDATA){ + if ((value != SM_CMD_PROGRAMPAGE) && (value != SM_CMD_RESET)){ +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CMD %dbit write %s ILLEGAL after WRITEDATA cmd - IGNORED\n", size*8, getCmdName(value)); +#endif + ctrl &= ~FLASH_PP_READY;//go busy, reset is needed + break; + } + } +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CMD %dbit write %s\n", size*8, getCmdName(value)); +#endif + switch (value){ // A8 bit is encoded in READ cmd;) + case SM_CMD_READ1: counter= 0; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_READ2: counter= PAGE_SIZE/2; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_READ3: counter= PAGE_SIZE; if (cmd != SM_CMD_GETSTATUS) address= counter; addrbyte= 0; break; + case SM_CMD_RESET: FLASHinit(); break; + case SM_CMD_WRITEDATA: counter= 0; address= counter; addrbyte= 0; break; + case SM_CMD_ERASEBLOCK: counter= 0; memset(data, 0xFF, PAGE_SIZE); address= counter; addrbyte= 1; break; + case SM_CMD_PROGRAMPAGE: //fall + case SM_CMD_ERASECONFIRM: + ctrl &= ~FLASH_PP_READY; + calculateECC(data); + memcpy(file+(address/PAGE_SIZE)*PAGE_SIZE_ECC, data, PAGE_SIZE_ECC); + /*write2file*/ + ctrl |= FLASH_PP_READY; break; + case SM_CMD_GETSTATUS: break; + case SM_CMD_READID: counter= 0; address= counter; addrbyte= 0; break; + default: + ctrl &= ~FLASH_PP_READY; + return;//ignore any other command; go busy, reset is needed + } + cmd= value; + break; + + case FLASH_R_ADDR: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH ADDR %dbit write 0x%08lX\n", size*8, value); +#endif + address |= (value & 0xFF) << (addrbyte == 0 ? 0 : (1 + 8 * addrbyte)); + addrbyte++; +#ifdef DEV9_LOG + DEV9_LOG("*FLASH ADDR = 0x%08lX (addrbyte=%d)\n", address, addrbyte); +#endif + if (!(value & 0x100)){ // address is complete + if ((cmd == SM_CMD_READ1) || (cmd == SM_CMD_READ2) || (cmd == SM_CMD_READ3)) { + ctrl &= ~FLASH_PP_READY; + memcpy(data, file+(address>>PAGE_SIZE_BITS)*PAGE_SIZE_ECC, PAGE_SIZE); + calculateECC(data); // calculate ECC; should be in the file already + ctrl |= FLASH_PP_READY; + } + addrbyte= 0; // address reset +#ifdef DEV9_LOG + { + u32 bytes, pages, blocks; + + blocks = address / BLOCK_SIZE; + pages = address-(blocks*BLOCK_SIZE); + bytes = pages % PAGE_SIZE; + pages = pages / PAGE_SIZE; + DEV9_LOG("*FLASH ADDR = 0x%08lX (%d:%d:%d) (addrbyte=%d) FINAL\n", address, blocks, pages, bytes, addrbyte); + } +#endif + } + break; + + case FLASH_R_CTRL: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH CTRL %dbit write 0x%08lX\n", size*8, value); +#endif + ctrl = (ctrl & FLASH_PP_READY) | (value & ~FLASH_PP_READY); + break; + + case FLASH_R_ID: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH ID %dbit write 0x%08lX DENIED :P\n", size*8, value); +#endif + break; + + default: +#ifdef DEV9_LOG + DEV9_LOG("*FLASH Unkwnown %dbit write at address 0x%08lX= 0x%08lX IGNORED\n", size*8, addr, value); +#endif + break; + } +} + +static unsigned char xor_table[256]={ + 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4, 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00, + 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77, 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3, + 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66, 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2, + 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5, 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11, + 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55, 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1, + 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96, 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22, + 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87, 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33, + 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44, 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0, + 0xF0, 0x77, 0x66, 0xE1, 0x55, 0xD2, 0xC3, 0x44, 0x44, 0xC3, 0xD2, 0x55, 0xE1, 0x66, 0x77, 0xF0, + 0x33, 0xB4, 0xA5, 0x22, 0x96, 0x11, 0x00, 0x87, 0x87, 0x00, 0x11, 0x96, 0x22, 0xA5, 0xB4, 0x33, + 0x22, 0xA5, 0xB4, 0x33, 0x87, 0x00, 0x11, 0x96, 0x96, 0x11, 0x00, 0x87, 0x33, 0xB4, 0xA5, 0x22, + 0xE1, 0x66, 0x77, 0xF0, 0x44, 0xC3, 0xD2, 0x55, 0x55, 0xD2, 0xC3, 0x44, 0xF0, 0x77, 0x66, 0xE1, + 0x11, 0x96, 0x87, 0x00, 0xB4, 0x33, 0x22, 0xA5, 0xA5, 0x22, 0x33, 0xB4, 0x00, 0x87, 0x96, 0x11, + 0xD2, 0x55, 0x44, 0xC3, 0x77, 0xF0, 0xE1, 0x66, 0x66, 0xE1, 0xF0, 0x77, 0xC3, 0x44, 0x55, 0xD2, + 0xC3, 0x44, 0x55, 0xD2, 0x66, 0xE1, 0xF0, 0x77, 0x77, 0xF0, 0xE1, 0x66, 0xD2, 0x55, 0x44, 0xC3, + 0x00, 0x87, 0x96, 0x11, 0xA5, 0x22, 0x33, 0xB4, 0xB4, 0x33, 0x22, 0xA5, 0x11, 0x96, 0x87, 0x00}; + +static void xfromman_call20_calculateXors(unsigned char buffer[128], unsigned char xor[4]){ + register unsigned char a=0, b=0, c=0, i; + + for (i=0; i<128; i++){ + a ^= xor_table[buffer[i]]; + if (xor_table[buffer[i]] & 0x80){ + b ^= ~i; + c ^= i; + } + } + + xor[0]=(~a) & 0x77; + xor[1]=(~b) & 0x7F; + xor[2]=(~c) & 0x7F; +} diff --git a/plugins/dev9/build.sh b/plugins/dev9/build.sh new file mode 100644 index 0000000..50d1c00 --- /dev/null +++ b/plugins/dev9/build.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +echo ------------------------ +echo Building DEV9 plugins... +echo ------------------------ +curdir=`pwd` + +cd ${curdir}/dev9null +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi \ No newline at end of file diff --git a/plugins/dev9/dev9null/DEV9null.dll b/plugins/dev9/dev9null/DEV9null.dll new file mode 100644 index 0000000000000000000000000000000000000000..e1f4677514bbc3edfd0ac251e4f44c6626b3d475 GIT binary patch literal 40960 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 + shadow + + + diff --git a/plugins/dev9/dev9null/build.sh b/plugins/dev9/dev9null/build.sh new file mode 100644 index 0000000..496e733 --- /dev/null +++ b/plugins/dev9/dev9null/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +echo Building dev9null... +curdir=`pwd` + +cd ${curdir}/src +make $@ + +cp libDEV9null.so ${PCSX2PLUGINS} diff --git a/plugins/dev9/dev9null/src/DEV9.h b/plugins/dev9/dev9null/src/DEV9.h new file mode 100644 index 0000000..73ce78e --- /dev/null +++ b/plugins/dev9/dev9null/src/DEV9.h @@ -0,0 +1,17 @@ +#ifndef __DEV9_H__ +#define __DEV9_H__ + +#include + +#define DEV9defs + +#include "PS2Edefs.h" + + +FILE *dev9Log; +void __Log(char *fmt, ...); +void (*DEV9irq)(); +void SysMessage(char *fmt, ...); + + +#endif diff --git a/plugins/dev9/dev9null/src/DEV9null.dsp b/plugins/dev9/dev9null/src/DEV9null.dsp new file mode 100644 index 0000000..9b3427e --- /dev/null +++ b/plugins/dev9/dev9null/src/DEV9null.dsp @@ -0,0 +1,89 @@ +# Microsoft Developer Studio Project File - Name="DEV9null" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=DEV9null - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "DEV9null.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DEV9null.mak" CFG="DEV9null - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DEV9null - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cwcl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEV9null_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEV9null_EXPORTS" /D "__WIN32__" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=cwlink.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# Begin Target + +# Name "DEV9null - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\DEV9null.c +# End Source File +# Begin Source File + +SOURCE=.\DEV9null.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Etypes.h +# End Source File +# Begin Source File + +SOURCE=.\DEV9.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/plugins/dev9/dev9null/src/DEV9null.dsw b/plugins/dev9/dev9null/src/DEV9null.dsw new file mode 100644 index 0000000..b6dd358 --- /dev/null +++ b/plugins/dev9/dev9null/src/DEV9null.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "DEV9null"=".\DEV9null.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/dev9/dev9null/src/Dev9null.ncb b/plugins/dev9/dev9null/src/Dev9null.ncb new file mode 100644 index 0000000000000000000000000000000000000000..aa1b30d04728455b9d51c8513d7d2213694d3a67 GIT binary patch literal 68608 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 biW(?tps0bO28tReYM`irq6Yp&HSqrcop6^t literal 0 HcmV?d00001 diff --git a/plugins/dev9/dev9null/src/Dev9null.sln b/plugins/dev9/dev9null/src/Dev9null.sln new file mode 100644 index 0000000..61bcaa6 --- /dev/null +++ b/plugins/dev9/dev9null/src/Dev9null.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dev9null", "Dev9null.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/dev9/dev9null/src/Dev9null.suo b/plugins/dev9/dev9null/src/Dev9null.suo new file mode 100644 index 0000000000000000000000000000000000000000..e572d0962bdb077861347bcbaa6e408368d165dc GIT binary patch literal 9216 zcmeHMTWpj?6h7NhXt@+9H$}via;ezXUZ5B1CA3>gV++`pmYBY5cmI}!?f!MU;_+a3{U`*t}7$OhGM||*t3asBZ^UvP8+x>T2)FwTf^Z)bD zoH=La%sFSy%zkrY{g3Z_y!EzZ!1Gcn58@TFJf+@)GEu=gkrEX6{U9EX>q-$6mtYZT z;6BE>%vr-Syt&>hfaSmn;2Pjc;40v1AlDj8pIB#pFTvu~z<}8J#l$P!62Utv=drr( zVY8GaY=O2i7hJ9_xpl?&m8TR$U(lEU#~{&`Q_>6R<0y5@Io;s$xmij)8$i1j$W?IJ zO=!b}A@R$!oR&Tb;T@CXcv={fsh`$lIiEWre?401Gj8QGX41b1y^zEe2+J6r=VVYx zKZDT(P|6Qp$fw*Ykh+!6xcz~{n*K}VnwU7iZ_dZGrTRbDxDrTxn|8`J75Er%8}MFVfQ?Qa>6f5z z4fIx5z4BezK=+$(^;{1R_uhdz3xZ#|xJwid+*j86tTUm2l&RhGKS<1nc_ku~69Zj#y*fLw0mhb+1VKTG?e!PT3JF z5>t(9MnaLGeReuYzU=T&e;=7uc7;PzW41pU^bUj~6RcX%V@0f}Kg{y%I{NZ_fc>8Z zcF6%5l_|u58JU3hM-YcbC5RYsM%q(K5wwT#8%28*F=EsauKW8CLjs_fL_bFJY4IYy zMZm|aB1;T)8s}3 z2kv8P&KyltMljwO=5P{U`C>15F#b`8jA+%8foQ)1qrhLxY!Wd3tEo`MLYB4v| zKtA~~M!J>H9P6;dGE+YHKSus3wNkdS1BW#0Yqz6+?k8^Lla@%J?g*o>0BZa+2986X z7dFV)Y<$(r5o85JC^aGCH%K$aFboc@c#}^I@1!rh{;!XL_8P`4$1$4Z zNX)m$|7ApaoF-mCO=?v#?T;(Pcrggw&p^BRvJlvx%0IXZxV1mhe&*o_L|I*`|0m_2 zhfbLjslcm=vpkLcQ#K(B$*d~oe!2X=A67aEsmy~%99`JLD3~2;F@NSw%!%B}XTCV( zu%o}nATtWB)B2O1Vlrb3YY>B9F&2>F z)Zx1s*ox9Vw6>^HJ4*Wzw(3CF0LpgMcA~un-_0=pHn}7hl^bxQH`{wXw*3G?us$4J zM7h}Xz=z;D49@k~QZM3n0kRrU*C+=uuCC0CA=T!O!RDsn1I!t6?L-ZZ|1*zsYyb4U z3(lg=CEuLIeDI7IFdNiEKKE0ui(C2ILCc(rz&OX8%gj;x**IoAq2eDU>)C7i%qRR` z$)#*UW_z~pCs6sl6aS7P#+|~R$h|U`k7wgy>b4gle-AppY#6k_GCN_3`(Y!r+iqYZ zO6{m^QFhym))v)HEAIjxRQ7&Ju}JZmnz?+YL@F1J&jb->)4eg^_)eSBRU787u@0JH zT0-w{#LuU6*M`Pem599?tvg_x4rYx%&PswrNEt z2}~Pf1ox7DSZY|=>7eox=0r0H9%cs-c~0eLA{|&<_}&7Bu6pDOXW>QkPb2pzWXB*U zDV4Vc=`?0+dUqpjxjOeRzVVmC7pAJ%l^!}D~}BRaP`jW{?~S0`Ml)qO?OqU^7F=B z-+owK-Sg>Bw=eA(o7|`3P385i;d>R;N8gCQdiTbc?{+K8Gz*LJDX?EBDB`;%1 z@u$~J!RZ^HKA${H{+PRh^yw$_csJwQ1`g?~mueUK-iv&6p357))N{B#J8=*m_`t8c z+ya!#Z;8_HPHC0gRi#q-18=T;sr;Fs`YTcTJ5joqDBX8Tt0eA}YSF(3V~GHHP76Ex zkKX%ck5bQL7*w6G{Q#m4Psvu|{*t4v0rDO>n8r){y17{hp${!o_djuiej$)fD5Ssk zAJac`1v(VJ{12uf^K})jM6p2sx$5{&W-gTf_J-#a-kTJAdLM=4u!?2V>I`lnmKTvPu?|}BS>K}@V~U-g_wgo zZO^8n8kgd~xuq#2ersJO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.sln b/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.sln new file mode 100644 index 0000000..4b73f6e --- /dev/null +++ b/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dev9null", "Dev9null_vsnet2005beta1.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + amd64|Win32 = amd64|Win32 + amd64|Win64 (AMD64) = amd64|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win32.ActiveCfg = amd64|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win32.Build.0 = amd64|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win64 (AMD64).ActiveCfg = amd64|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win64 (AMD64).Build.0 = amd64|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win32.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win32.Build.0 = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.vcproj b/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.vcproj new file mode 100644 index 0000000..08517ad --- /dev/null +++ b/plugins/dev9/dev9null/src/Dev9null_vsnet2005beta1.vcproj @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/dev9/dev9null/src/Makefile b/plugins/dev9/dev9null/src/Makefile new file mode 100644 index 0000000..1b129e4 --- /dev/null +++ b/plugins/dev9/dev9null/src/Makefile @@ -0,0 +1,23 @@ + +CC = gcc + +PLUGIN = libDEV9null.so +CFLAGS+= -fPIC -Wall -O2 -fomit-frame-pointer -D__LINUX__ +OBJS = dev9null.o +DEPS:= $(OBJS:.o=.d) + +all: plugin +install: all + +plugin: ${OBJS} + rm -f ${PLUGIN} + gcc -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +clean: + rm -f ${OBJS} ${DEPS} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/dev9/dev9null/src/Makefile.mingw b/plugins/dev9/dev9null/src/Makefile.mingw new file mode 100644 index 0000000..20bc9ef --- /dev/null +++ b/plugins/dev9/dev9null/src/Makefile.mingw @@ -0,0 +1,51 @@ +# +# Makefile for MINGW32 +# + + +all: dev9null + +PLUGIN = DEV9null.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwinmm -lgdi32 -lcomdlg32 #-lintl -lwsock32 +RESOBJ = dev9nullrc.o + +OBJS = dev9null.o + + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I/usr/local/include ${FLAGS} + +dev9null: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean dev9null + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: DEV9null.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + + \ No newline at end of file diff --git a/plugins/dev9/dev9null/src/PS2Edefs.h b/plugins/dev9/dev9null/src/PS2Edefs.h new file mode 100644 index 0000000..a52d86a --- /dev/null +++ b/plugins/dev9/dev9null/src/PS2Edefs.h @@ -0,0 +1,684 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.5 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0005 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/dev9/dev9null/src/PS2Etypes.h b/plugins/dev9/dev9null/src/PS2Etypes.h new file mode 100644 index 0000000..443ad45 --- /dev/null +++ b/plugins/dev9/dev9null/src/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/dev9/dev9null/src/dev9null.c b/plugins/dev9/dev9null/src/dev9null.c new file mode 100644 index 0000000..56a8562 --- /dev/null +++ b/plugins/dev9/dev9null/src/dev9null.c @@ -0,0 +1,152 @@ + + +#ifdef __WIN32__ + +#include +#include +#include + +#endif + +#include +#include +#include +#include +#include "PS2Etypes.h" +#include "DEV9.h" + +#ifdef __WIN32__ + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "DEV9null Msg", 0); +} + +#else + +#include + +void SysMessage(char *fmt, ...) { +} + +#endif + +const unsigned char version = PS2E_DEV9_VERSION; +const unsigned char revision = 0; +const unsigned char build = 3; // increase that with each version + +static char *libraryName = "DEV9null Driver"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_DEV9; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + +// if (!Log) return; + + va_start(list, fmt); + vfprintf(dev9Log, fmt, list); + va_end(list); +} + +s32 CALLBACK DEV9init() { + + return 0; +} + +void CALLBACK DEV9shutdown() { +} + +s32 CALLBACK DEV9open(void *pDsp) { + +#ifdef _WIN32 +#else + Display* dsp = *(Display**)pDsp; +#endif + return 0; +} + +void CALLBACK DEV9close() { + +} + + +u8 CALLBACK DEV9read8(u32 addr) { + return 0; +} + +u16 CALLBACK DEV9read16(u32 addr) { + return 0; +} + +u32 CALLBACK DEV9read32(u32 addr) { + return 0; +} + +void CALLBACK DEV9write8(u32 addr, u8 value) { +} + +void CALLBACK DEV9write16(u32 addr, u16 value) { + +} + +void CALLBACK DEV9write32(u32 addr, u32 value) { + +} + +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size) { + +} + +void CALLBACK DEV9writeDMA8Mem(u32* pMem, int size) { + +} + + +void CALLBACK DEV9irqCallback(DEV9callback callback) { + +} + +DEV9handler CALLBACK DEV9irqHandler(void) { + return NULL; +} + + +// extended funcs + +s32 CALLBACK DEV9test() { + return 0; +} + +void CALLBACK DEV9configure() +{ + SysMessage("Nothing to Configure"); +} +void CALLBACK DEV9about(){} + +#ifdef __WIN32__ + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + +#endif diff --git a/plugins/dev9/dev9null/src/dev9null.def b/plugins/dev9/dev9null/src/dev9null.def new file mode 100644 index 0000000..e3f3b7e --- /dev/null +++ b/plugins/dev9/dev9null/src/dev9null.def @@ -0,0 +1,27 @@ +; DEV9null.def : Declares the module parameters for the DLL. + +LIBRARY "DEV9null" +DESCRIPTION 'DEV9null Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + DEV9init @5 + DEV9shutdown @6 + DEV9open @7 + DEV9close @8 + DEV9read8 @9 + DEV9read16 @10 + DEV9read32 @11 + DEV9write8 @12 + DEV9write16 @13 + DEV9write32 @14 + DEV9readDMA8Mem @15 + DEV9writeDMA8Mem @16 + DEV9configure @17 + DEV9test @18 + DEV9about @19 + DEV9irqCallback @20 + DEV9irqHandler @21 diff --git a/plugins/dev9/dev9null/src/plugin.def b/plugins/dev9/dev9null/src/plugin.def new file mode 100644 index 0000000..4fd95f3 --- /dev/null +++ b/plugins/dev9/dev9null/src/plugin.def @@ -0,0 +1,22 @@ +EXPORTS + DEV9about = DEV9about@0 @1 + DEV9close = DEV9close@0 @2 + DEV9configure = DEV9configure@0 @3 + DEV9init = DEV9init@0 @4 + DEV9irq @5 DATA + DEV9irqCallback = DEV9irqCallback@4 @6 + DEV9irqHandler = DEV9irqHandler@0 @7 + DEV9open = DEV9open@4 @8 + DEV9read16 = DEV9read16@4 @9 + DEV9read32 = DEV9read32@4 @10 + DEV9read8 = DEV9read8@4 @11 + DEV9readDMA8Mem = DEV9readDMA8Mem@8 @12 + DEV9shutdown = DEV9shutdown@0 @13 + DEV9test = DEV9test@0 @14 + DEV9write16 = DEV9write16@8 @15 + DEV9write32 = DEV9write32@8 @16 + DEV9write8 = DEV9write8@8 @17 + DEV9writeDMA8Mem = DEV9writeDMA8Mem@8 @18 + PS2EgetLibName = PS2EgetLibName@0 @19 + PS2EgetLibType = PS2EgetLibType@0 @20 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @21 diff --git a/plugins/fw/FWlinuz/FW.c b/plugins/fw/FWlinuz/FW.c new file mode 100644 index 0000000..3ec311c --- /dev/null +++ b/plugins/fw/FWlinuz/FW.c @@ -0,0 +1,285 @@ +/* FW + * Copyright (C) 2004 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "FW.h" + +const unsigned char version = PS2E_FW_VERSION; +const unsigned char revision = 0; +const unsigned char build = 1; // increase that with each version + +static char *libraryName = "FWlinuz Driver"; + +s8 *fwregs; +u8 phyregs[8]; +u8 portregs[3][8]; +u8 vidregs[8]; +u8 vderegs[8]; + +#define fwRs32(mem) (*(s32*)&fwregs[(mem) & 0xffff]) +#define fwRu32(mem) (*(u32*)&fwregs[(mem) & 0xffff]) + + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_FW; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.Log) return; + + va_start(list, fmt); + vfprintf(fwLog, fmt, list); + va_end(list); +} + +s32 CALLBACK FWinit() { + LoadConfig(); +#ifdef FW_LOG + fwLog = fopen("logs/fwLog.txt", "w"); + setvbuf(fwLog, NULL, _IONBF, 0); + FW_LOG("FWlinuz plugin version %d,%d\n",revision,build); + FW_LOG("FW init\n"); +#endif + + fwregs = (s8*)malloc(0x10000); + if (fwregs == NULL) { + SysMessage("Error allocating Memory\n"); return -1; + } + memset(phyregs, 0, sizeof(phyregs)); + memset(portregs, 0, sizeof(portregs)); + memset(vidregs, 0, sizeof(vidregs)); + memset(vderegs, 0, sizeof(vderegs)); + fwRu32(0x8400) = 0xffc00001; + phyregs[0] = 0xc1; + portregs[0][0] = 0xe5; + vidregs[0] = 0x01; + + return 0; +} + +void CALLBACK FWshutdown() { + free(fwregs); + +#ifdef FW_LOG + fclose(fwLog); +#endif +} + +s32 CALLBACK FWopen(void *pDsp) { +#ifdef FW_LOG + FW_LOG("FW open\n"); +#endif + + return 0; +} + +void CALLBACK FWclose() { +} + +u32 CALLBACK FWread32(u32 addr) { + u32 ret=0; + + switch (addr) { + case 0x1f808410: + ret = 0x8; + break; + + default: + ret = fwRu32(addr); + break; + } +#ifdef FW_LOG + FW_LOG("FW read mem 0x%x: 0x%x\n", addr, ret); +#endif + + return ret; +} + +void _irq0(int num) { + fwRu32(0x8420)|= 1<> 24) & 0xf; + int port; + u8 value=0; + + PHYACC = (PHYACC & ~0xf00) | (reg << 8); + PHYACC&= ~0x80000000; + + if (reg > 7) { + reg-= 8; + switch (phyregs[7] & 0x7) { + case 0: + port = phyregs[7] >> 16; + if (port < 3) { + value = portregs[port][reg]; + } else { + value = 0; + } + printf("port[%d] read 0x%x: 0x%2.2x\n", port, reg, value); +#ifdef FW_LOG + FW_LOG("port[%d] read 0x%x: 0x%2.2x\n", port, reg, value); +#endif + break; + case 1: + value = vidregs[reg]; + printf("vid read 0x%x: 0x%2.2x\n", reg, value); +#ifdef FW_LOG + FW_LOG("vid read 0x%x: 0x%2.2x\n", reg, value); +#endif + break; + case 3: + value = 0x02; + printf("vid read 0x%x: 0x%2.2x\n", reg, value); +#ifdef FW_LOG + FW_LOG("vid read 0x%x: 0x%2.2x\n", reg, value); +#endif + break; + case 7: + printf("vde read 0x%x: 0x%2.2x\n", reg, vderegs[reg]); +#ifdef FW_LOG + FW_LOG("vde read 0x%x: 0x%2.2x\n", reg, vderegs[reg]); +#endif + value = vderegs[reg]; + break; + } + } else { + printf("phy read 0x%x: 0x%2.2x\n", reg, phyregs[reg]); +#ifdef FW_LOG + FW_LOG("phy read 0x%x: 0x%2.2x\n", reg, phyregs[reg]); +#endif + value = phyregs[reg]; + } + + PHYACC = (PHYACC & ~0xff) | value; + _irq0(30); +} + +void phy_write() { + int reg = (PHYACC >> 24) & 0xf; + int port; + u8 value = (PHYACC >> 16) & 0xff; + + if (reg > 7) { + reg-= 8; + switch (phyregs[7] & 0x7) { + case 0: + port = phyregs[7] >> 4; + printf("port[%d] write 0x%x: 0x%2.2x\n", port, reg, value); +#ifdef FW_LOG + FW_LOG("port[%d] write 0x%x: 0x%2.2x\n", port, reg, value); +#endif + if (port < 3) { + switch (reg) { + case 0x0: portregs[port][reg] = (portregs[port][reg] & 0x7f) | (value & ~0x7f); break; + case 0x1: portregs[port][reg] = (portregs[port][reg] & 0x07) | (value & ~0x07); break; + } + } + break; + + case 1: + printf("vid write 0x%x: 0x%2.2x\n", reg, value); +#ifdef FW_LOG + FW_LOG("vid write 0x%x: 0x%2.2x\n", reg, value); +#endif + break; + + case 7: + printf("vde write 0x%x: 0x%2.2x\n", reg, value); +#ifdef FW_LOG + FW_LOG("vde write 0x%x: 0x%2.2x\n", reg, value); +#endif + switch (reg) { + case 0x0: vderegs[reg] = value; break; + } + break; + } + } else { + printf("phy write 0x%x: 0x%2.2x\n", reg, value); +#ifdef FW_LOG + FW_LOG("phy write 0x%x: 0x%2.2x\n", reg, value); +#endif + switch (reg) { + case 0x0: break; + case 0x2: break; + case 0x3: break; + case 0x4: phyregs[reg] = (phyregs[reg] & 0x1c) | (value & ~0x1c); break; + case 0x6: break; + default: phyregs[reg] = value; + } + } + + PHYACC&= ~0x40000000; +} + +void CALLBACK FWwrite32(u32 addr, u32 value) { + switch (addr) { + case 0x1f808400: + fwRu32(addr) = (fwRu32(addr) & 0x003f0001) | (value & ~0x003f0001); + break; + + case 0x1f808414: + fwRu32(addr) = (fwRu32(addr) & 0xfff) | (value & ~0xfff); + if (value & 0x80000000) phy_read(); + if (value & 0x40000000) phy_write(); + break; + + case 0x1f808420: + case 0x1f808428: + case 0x1f808430: + fwRu32(addr) = (fwRu32(addr) & ~value); + break; + + default: + fwRu32(addr) = value; + break; + } +#ifdef FW_LOG + FW_LOG("FW write mem 0x%x: 0x%x\n", addr, value); +#endif +} + +void CALLBACK FWirqCallback(void (*callback)()) { + FWirq = callback; +} + +s32 CALLBACK FWfreeze(int mode, freezeData *data) { + return 0; +} + +s32 CALLBACK FWtest() { + return 0; +} + diff --git a/plugins/fw/FWlinuz/FW.h b/plugins/fw/FWlinuz/FW.h new file mode 100644 index 0000000..d071998 --- /dev/null +++ b/plugins/fw/FWlinuz/FW.h @@ -0,0 +1,62 @@ +/* FireWire + * Copyright (C) 2004 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __FIREWIRE_H__ +#define __FIREWIRE_H__ + +#include + +#define FIREWIREdefs +#include "PS2Edefs.h" + +#ifdef __WIN32__ + +#include +#include + +#else + +#include + +#define __inline inline + +#endif + +#define FW_LOG __Log + +typedef struct { + int Log; +} Config; + +Config conf; + +#define PHYACC fwRu32(0x8414) + + +void (*FWirq)(); + +void SaveConfig(); +void LoadConfig(); + +FILE *fwLog; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#endif diff --git a/plugins/fw/FWlinuz/License.txt b/plugins/fw/FWlinuz/License.txt new file mode 100644 index 0000000..7d1f860 --- /dev/null +++ b/plugins/fw/FWlinuz/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/fw/FWlinuz/Linux/Config.c b/plugins/fw/FWlinuz/Linux/Config.c new file mode 100644 index 0000000..7f3b9e5 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/Config.c @@ -0,0 +1,51 @@ +/* FireWire + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "FireWire.h" + +void LoadConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/FireWire.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + return; + } + fclose(f); +} + +void SaveConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/FireWire.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fclose(f); +} + diff --git a/plugins/fw/FWlinuz/Linux/Config.h b/plugins/fw/FWlinuz/Linux/Config.h new file mode 100644 index 0000000..9eb3647 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/Config.h @@ -0,0 +1,20 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void SaveConf(); +void LoadConf(); diff --git a/plugins/fw/FWlinuz/Linux/Linux.c b/plugins/fw/FWlinuz/Linux/Linux.c new file mode 100644 index 0000000..b12ef28 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/Linux.c @@ -0,0 +1,75 @@ +/* FireWire + * Copyright (C) 2002-2004 FireWire Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "FireWire.h" + +int ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgFireWire"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + strcpy(cfg, "./cfg/cfgFireWire"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + sprintf(cfg, "%s/cfgFireWire", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + printf("cfgFireWire file not found!\n"); + return -1; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", msg); + ExecCfg(cmd); +} + +void FireWireconfigure() { + ExecCfg("configure"); +} + +void FireWireabout() { + ExecCfg("about"); +} + diff --git a/plugins/fw/FWlinuz/Linux/Makefile b/plugins/fw/FWlinuz/Linux/Makefile new file mode 100644 index 0000000..d40d8c6 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/Makefile @@ -0,0 +1,34 @@ + +PLUGIN = libFireWire.so +CFG = cfgFireWire +CFLAGS+= -fPIC -Wall -I. -I.. -O3 -fomit-frame-pointer -fno-strict-aliasing +OBJS = ../FireWire.o +OBJS+= Linux.o Config.o +CFGOBJS = conf.o interface.o support.o Config.o +DEPS:= $(OBJS:.o=.d) +CFGDEPS:= $(CFGOBJS:.o=.d) +LIBS = -lpthread +CFLAGS+= $(shell gtk-config --cflags) -D__LINUX__ +CFGLIBS = $(shell gtk-config --libs) + +CC = gcc + +all: plugin cfg + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} + rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +clean: + rm -f ${OBJS} ${DEPS} ${CFGOBJS} ${CFGDEPS} ${PLUGIN} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/fw/FWlinuz/Linux/callbacks.c b/plugins/fw/FWlinuz/Linux/callbacks.c new file mode 100644 index 0000000..fa070a7 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/fw/FWlinuz/Linux/callbacks.h b/plugins/fw/FWlinuz/Linux/callbacks.h new file mode 100644 index 0000000..22cf74a --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/fw/FWlinuz/Linux/conf.c b/plugins/fw/FWlinuz/Linux/conf.c new file mode 100644 index 0000000..6f42a8d --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/conf.c @@ -0,0 +1,136 @@ +/* FireWire + * Copyright (C) 2002-2004 FireWire Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "callbacks.h" +#include "FireWire.h" +#include "Config.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void cfgSysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "FireWire Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CFGabout() { + About = create_About(); + gtk_widget_show_all(About); + gtk_main(); +} + +GtkWidget *Conf; + +void OnConf_Ok(GtkButton *button, gpointer user_data) { + gchar *str; + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CFGconfigure() { + Conf = create_Config(); + + LoadConfig(); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +long CFGmessage(char *msg) { + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(argv[2]); + } + + return 0; +} diff --git a/plugins/fw/FWlinuz/Linux/firewire.glade b/plugins/fw/FWlinuz/Linux/firewire.glade new file mode 100644 index 0000000..6644e52 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/firewire.glade @@ -0,0 +1,300 @@ + + + + + FireWire + dev9linuz + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + DEV9config + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox1 + 5 + True + 5 + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Eth + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + + GtkFrame + frame3 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox2 + 5 + True + 5 + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Hdd + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + DEV9about + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/fw/FWlinuz/Linux/interface.c b/plugins/fw/FWlinuz/Linux/interface.c new file mode 100644 index 0000000..a73c086 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/interface.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *hbox1; + GtkWidget *label4; + GtkWidget *GtkCombo_Eth; + GtkWidget *combo_entry1; + GtkWidget *frame3; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_Hdd; + GtkWidget *entry1; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "DEV9config"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Ethernet"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + hbox1 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (frame2), hbox1); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label4 = gtk_label_new ("Device:"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (Config), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox1), label4, FALSE, FALSE, 0); + + GtkCombo_Eth = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Eth); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Eth", GtkCombo_Eth, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Eth); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_Eth, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Eth, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_Eth)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + frame3 = gtk_frame_new ("Hdd"); + gtk_widget_ref (frame3); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame3", frame3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (frame3), hbox2); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label5 = gtk_label_new ("Device:"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_Hdd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Hdd); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Hdd", GtkCombo_Hdd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Hdd); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_Hdd, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Hdd, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_Hdd)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "DEV9about"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("DEV9linuz Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Author: linuzappz "); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/fw/FWlinuz/Linux/interface.h b/plugins/fw/FWlinuz/Linux/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/fw/FWlinuz/Linux/support.c b/plugins/fw/FWlinuz/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/fw/FWlinuz/Linux/support.h b/plugins/fw/FWlinuz/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/fw/FWlinuz/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/fw/FWlinuz/PS2Edefs.h b/plugins/fw/FWlinuz/PS2Edefs.h new file mode 100644 index 0000000..b20cbbc --- /dev/null +++ b/plugins/fw/FWlinuz/PS2Edefs.h @@ -0,0 +1,724 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.0 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetCSR(u64 *csr); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetCSR)(u64 * csr); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetCSR GSsetCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/fw/FWlinuz/PS2Etypes.h b/plugins/fw/FWlinuz/PS2Etypes.h new file mode 100644 index 0000000..3a63c58 --- /dev/null +++ b/plugins/fw/FWlinuz/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/fw/FWlinuz/ReadMe.txt b/plugins/fw/FWlinuz/ReadMe.txt new file mode 100644 index 0000000..aede3fd --- /dev/null +++ b/plugins/fw/FWlinuz/ReadMe.txt @@ -0,0 +1,25 @@ +FWlinuz v0.1 +------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Usage: +----- + Place the file "FWlinuz.so" (linux) or "FWlinuz.dll" (win32) + at the Plugin directory of the Emulator to use it. + +Changes: +------- + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + shadow + linuzappz + + + diff --git a/plugins/fw/FWlinuz/Win32/Config.c b/plugins/fw/FWlinuz/Win32/Config.c new file mode 100644 index 0000000..1109f31 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/Config.c @@ -0,0 +1,45 @@ +#include + +#include "FW.h" + +extern HINSTANCE hInst; + +void SaveConfig() { + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\fwlinuz.ini"); + sprintf(szValue,"%u",Conf1->Log); + WritePrivateProfileString("Interface", "Logging",szValue,szIniFile); +} + +void LoadConfig() { + FILE *fp; + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\fwlinuz.ini"); + fp=fopen("inis\\fwlinuz.ini","rt");//check if firewirenull.ini really exists + if (!fp) { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.Log = 0;//default value + SaveConfig();//save and return + return ; + } + fclose(fp); + GetPrivateProfileString("Interface", "Logging", NULL, szValue, 20, szIniFile); + Conf1->Log = strtoul(szValue, NULL, 10); +} + diff --git a/plugins/fw/FWlinuz/Win32/FWlinuz.def b/plugins/fw/FWlinuz/Win32/FWlinuz.def new file mode 100644 index 0000000..dc1fd03 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/FWlinuz.def @@ -0,0 +1,19 @@ +; FireWire.def : Declares the module parameters for the DLL. + +LIBRARY "FireWirePlugin" + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + FWinit @5 + FWshutdown @6 + FWopen @7 + FWclose @8 + FWread32 @11 + FWwrite32 @14 + FWirqCallback @15 + FWconfigure @17 + FWtest @18 + FWabout @19 diff --git a/plugins/fw/FWlinuz/Win32/FWlinuz.rc b/plugins/fw/FWlinuz/Win32/FWlinuz.rc new file mode 100644 index 0000000..a084b79 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/FWlinuz.rc @@ -0,0 +1,123 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifdef __MINGW32__ +#include "afxresmw.h" +#else +#include "afxres.h" +#endif + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 212, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Firewireconfigure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,48,100,50,14 + PUSHBUTTON "Cancel",IDCANCEL,113,100,50,14 + CONTROL "Enable Logging (for develop use only)",IDC_LOGGING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,187,13 +END + +IDD_ABOUT DIALOGEX 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "FireWire About" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "FireWire Driver",IDC_NAME,70,10,48,8 + GROUPBOX "",IDC_STATIC,5,35,170,40 + LTEXT "Author: Shadow and linuzappz",IDC_STATIC,29,19,141,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/fw/FWlinuz/Win32/FWlinuz.sln b/plugins/fw/FWlinuz/Win32/FWlinuz.sln new file mode 100644 index 0000000..95dd0df --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/FWlinuz.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FireWireNull", "FireWireNull.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/fw/FWlinuz/Win32/FireWireNull.ncb b/plugins/fw/FWlinuz/Win32/FireWireNull.ncb new file mode 100644 index 0000000000000000000000000000000000000000..b2d6aa5d8f1e90aac5d7572ded439a758ae5e45d GIT binary patch literal 60416 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 DAK((* literal 0 HcmV?d00001 diff --git a/plugins/fw/FWlinuz/Win32/FireWireNull.sln b/plugins/fw/FWlinuz/Win32/FireWireNull.sln new file mode 100644 index 0000000..c9d4c3a --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/FireWireNull.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FWlinuz", "FireWireNull.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/fw/FWlinuz/Win32/FireWireNull.suo b/plugins/fw/FWlinuz/Win32/FireWireNull.suo new file mode 100644 index 0000000000000000000000000000000000000000..f7f71bf1a745dfd650775ff75d17e4bc6df4846d GIT binary patch literal 8192 zcmeHLOKenC82+cF(()+fRS^|O%1flRv;|u55j)e?#!icEX<2l^bmq1U+?lB}w-f{t zcP1tpjWIECVSMb2ub8+pXj~Xs7>rRC#u!)_m$>kO3XI=(?zuD5={)X~VkGH*^WXEh z|2_YI&iP;Gd~;#-r8hs?cv*7bQK^(0sT#Q>tKWk$i7vc6_fkBDmvBWD~5<{7gQ`lkmP%l+! zo3AYK+mW{~9jbrfOAqNjr$PY^f@55cNiVohpw=ZP?GG;B^-|$k3))pc?uN_X1nx`0 zummM3$E8mqC@ndJw*i@){$z;(w}Ag@(9mYw@~6+FeGz(PM1~|Fe!UV?io1nf=u|5+ zqvf%w=e~D>KW&zF>6U-Czjkbyd*b*3_HjPWH`+h_K(-IydOP3OWYyQBUJtwzxB=J% zB;DO8?*ZNm+yuN2=mp*nV&V8qGDE)PiQzyW2dnj&k*V=`FcJ0+Mq-ofTH0g8j6~36eJ*(Bc9qq`|MvrZ zc#p}Hm@+Ms@I^7${TMvr4Bp)`ihlM@%QI+?s(LH*eyl8B`G|Yr=@!YV`{0rj95Y{SgS zm+{0cf6_Yf=VtZSk&W@=S)i@Qc2u9lS_UPGJ?h3>Otqt9h;`I0M*Spk0`v4D1~U3i zgW5!E2z}EMR`d5Fg7hOR7)E~!JbtsZLhDB`!akH7$3mGz8B*5p;(sm!_0_~ICzJ$^ zBu-o8|00nsXRgP{)j#f33~N7xy_r_4THFgj|CIeR3b@rj(thf}3s9KENyXL{4`Qor1j`nVWX9BBE?ax?> zlNlS(D+_i-UqDK}Gt%tW>u=BA-Tc>rH*>v(0{Y%uxS77(v2JC%N>um=D;^u9uJU6K z(%n>Qdqw)Hk7HLGg6}S(zHhkTyY8|NU zf!k^XT{9><(A$acd(m!%`nStjIit3nfrl!`vLD80;%P!C4j~xWhom#8yH69CHZpS&Q_CNRui!qNz`s7w^MJ&e^R{62$Oq8l z2Dq=a{X;*VyRsti{MOe#t9WDmRTbTSS-17u4;mVJKKc3b+3n-eHf1lh=QofSS&GYcT+4Ij;+(LW`_1DdV{|*ecU&kL7yqBA8z1e=j{+`Lx zc|%|+FA#(MbA@c*Of9dL-+18%sFvT;wLf%ixm;DXO8FBd|EiR~(o}z^YyYHc*V47? zy0%x6SN z8^J#ry*PY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/fw/FWlinuz/Win32/Makefile b/plugins/fw/FWlinuz/Win32/Makefile new file mode 100644 index 0000000..b6e9f8e --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/Makefile @@ -0,0 +1,52 @@ +# +# Makefile for MINGW32 +# + + +all: fwlinuz + +PLUGIN = FWlinuz.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +ASMFLAGS = -D__WIN32__ -i.. -i.# -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +RESOBJ = FWlinuz.o + +OBJS = ../FW.o +OBJS+= Config.o Win32.o ${RESOBJ} + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I/usr/local/include ${FLAGS} +ASMFLAGS = -f elf ${FLAGS} -i./ -i../ + +fwlinuz: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} +# ${STRIP} ${PLUGIN} + +.PHONY: clean fwlinuz + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: FWlinuz.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/fw/FWlinuz/Win32/Win32.c b/plugins/fw/FWlinuz/Win32/Win32.c new file mode 100644 index 0000000..e734c45 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/Win32.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "resource.h" +#include "FW.h" + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "FW Plugin Msg", 0); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + if (conf.Log) CheckDlgButton(hW, IDC_LOGGING, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOGGING)) + conf.Log = 1; + else conf.Log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK FWconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK FWabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/fw/FWlinuz/Win32/afxresmw.h b/plugins/fw/FWlinuz/Win32/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/fw/FWlinuz/Win32/plugin.def b/plugins/fw/FWlinuz/Win32/plugin.def new file mode 100644 index 0000000..1ac66e0 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/plugin.def @@ -0,0 +1,15 @@ +EXPORTS + FWabout = FWabout@0 @3 + FWclose = FWclose@0 @4 + FWconfigure = FWconfigure@0 @5 + FWfreeze = FWfreeze@8 @6 + FWinit = FWinit@0 @7 + FWirqCallback = FWirqCallback@4 @9 + FWopen = FWopen@4 @10 + FWread32 = FWread32@4 @11 + FWshutdown = FWshutdown@0 @12 + FWtest = FWtest@0 @13 + FWwrite32 = FWwrite32@8 @14 + PS2EgetLibName = PS2EgetLibName@0 @16 + PS2EgetLibType = PS2EgetLibType@0 @17 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @18 diff --git a/plugins/fw/FWlinuz/Win32/resource.h b/plugins/fw/FWlinuz/Win32/resource.h new file mode 100644 index 0000000..f8ab276 --- /dev/null +++ b/plugins/fw/FWlinuz/Win32/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by FireWireNull.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_CHECK1 1007 +#define IDC_LOGGING 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/fw/FWnull/FW.c b/plugins/fw/FWnull/FW.c new file mode 100644 index 0000000..37aeda8 --- /dev/null +++ b/plugins/fw/FWnull/FW.c @@ -0,0 +1,147 @@ +/* FWnull + * Copyright (C) 2004-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "FW.h" + +const unsigned char version = PS2E_FW_VERSION; +const unsigned char revision = 0; +const unsigned char build = 4; // increase that with each version + +static char *libraryName = "FWnull Driver"; + +s8 *fwregs; + +#define fwRs32(mem) (*(s32*)&fwregs[(mem) & 0xffff]) +#define fwRu32(mem) (*(u32*)&fwregs[(mem) & 0xffff]) + + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_FW; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.Log || fwLog == NULL) return; + + va_start(list, fmt); + vfprintf(fwLog, fmt, list); + va_end(list); +} + +s32 CALLBACK FWinit() { + LoadConfig(); +#ifdef FW_LOG + fwLog = fopen("logs/fwLog.txt", "w"); + if (fwLog) setvbuf(fwLog, NULL, _IONBF, 0); + FW_LOG("FWnull plugin version %d,%d\n",revision,build); + FW_LOG("FW init\n"); +#endif + + fwregs = (s8*)malloc(0x10000); + if (fwregs == NULL) { + SysMessage("Error allocating Memory\n"); return -1; + } + + return 0; +} + +void CALLBACK FWshutdown() { + free(fwregs); + +#ifdef FW_LOG + if (fwLog) fclose(fwLog); +#endif +} + +s32 CALLBACK FWopen(void *pDsp) { +#ifdef FW_LOG + FW_LOG("FW open\n"); +#endif + +#ifdef _WIN32 +#else + Display* dsp = *(Display**)pDsp; +#endif + + return 0; +} + +void CALLBACK FWclose() { +} + + + + +u32 CALLBACK FWread32(u32 addr) { + u32 ret=0; + + switch (addr) { + case 0x1f808410: + ret = 0x8; + break; + + default: + ret = fwRu32(addr); + } +#ifdef FW_LOG + FW_LOG("FW read mem 0x%x: 0x%x\n", addr, ret); +#endif + + return ret; +} + + + +void CALLBACK FWwrite32(u32 addr, u32 value) { + switch (addr) { + default: + fwRu32(addr) = value; + break; + } +#ifdef FW_LOG + FW_LOG("FW write mem 0x%x: 0x%x\n", addr, value); +#endif +} + +void CALLBACK FWirqCallback(void (*callback)()) { + FWirq = callback; +} + + +s32 CALLBACK FWfreeze(int mode, freezeData *data) { + return 0; +} + + +s32 CALLBACK FWtest() { + return 0; +} + diff --git a/plugins/fw/FWnull/FW.h b/plugins/fw/FWnull/FW.h new file mode 100644 index 0000000..6e8aeee --- /dev/null +++ b/plugins/fw/FWnull/FW.h @@ -0,0 +1,59 @@ +/* FWnull + * Copyright (C) 2004-2005 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __FW_H__ +#define __FW_H__ + +#include + +#define FWdefs +#include "PS2Edefs.h" + +#ifdef __WIN32__ + +#include +#include + +#else + +#include +#include + +#define __inline inline + +#endif + +#define FW_LOG __Log + +typedef struct { + int Log; +} Config; + +Config conf; +void (*FWirq)(); + +void SaveConfig(); +void LoadConfig(); + +FILE *fwLog; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#endif diff --git a/plugins/fw/FWnull/License.txt b/plugins/fw/FWnull/License.txt new file mode 100644 index 0000000..7d1f860 --- /dev/null +++ b/plugins/fw/FWnull/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/fw/FWnull/Linux/Config.c b/plugins/fw/FWnull/Linux/Config.c new file mode 100644 index 0000000..3eda6eb --- /dev/null +++ b/plugins/fw/FWnull/Linux/Config.c @@ -0,0 +1,51 @@ +/* FireWire + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "FW.h" + +void LoadConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/FWnull.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + return; + } + fclose(f); +} + +void SaveConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/FWnull.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fclose(f); +} + diff --git a/plugins/fw/FWnull/Linux/Config.h b/plugins/fw/FWnull/Linux/Config.h new file mode 100644 index 0000000..9eb3647 --- /dev/null +++ b/plugins/fw/FWnull/Linux/Config.h @@ -0,0 +1,20 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void SaveConf(); +void LoadConf(); diff --git a/plugins/fw/FWnull/Linux/Linux.c b/plugins/fw/FWnull/Linux/Linux.c new file mode 100644 index 0000000..9a70105 --- /dev/null +++ b/plugins/fw/FWnull/Linux/Linux.c @@ -0,0 +1,75 @@ +/* FireWire + * Copyright (C) 2002-2004 FireWire Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "FW.h" + +int ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgFWnull"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + strcpy(cfg, "./cfg/cfgFWnull"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + sprintf(cfg, "%s/cfgFWnull", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + printf("cfgFWnull file not found!\n"); + return -1; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", msg); + ExecCfg(cmd); +} + +void FWconfigure() { + ExecCfg("configure"); +} + +void FWabout() { + ExecCfg("about"); +} + diff --git a/plugins/fw/FWnull/Linux/Makefile b/plugins/fw/FWnull/Linux/Makefile new file mode 100644 index 0000000..28665db --- /dev/null +++ b/plugins/fw/FWnull/Linux/Makefile @@ -0,0 +1,35 @@ + +PLUGIN = libFWnull.so +CFG = cfgFWnull +CFLAGS+= -fPIC -Wall -I. -I.. -O3 -fomit-frame-pointer -fno-strict-aliasing +OBJS = ../FW.o +OBJS+= Linux.o Config.o +CFGOBJS = conf.o interface.o support.o Config.o +DEPS:= $(OBJS:.o=.d) +CFGDEPS:= $(CFGOBJS:.o=.d) +LIBS = -lpthread +CFLAGS+= $(shell pkg-config --cflags gtk+-2.0) -D__LINUX__ +CFGLIBS = $(shell pkg-config --libs gtk+-2.0) + +CC = gcc + +all: plugin cfg +install: all + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} + rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +clean: + rm -f ${OBJS} ${DEPS} ${CFGOBJS} ${CFGDEPS} ${PLUGIN} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/fw/FWnull/Linux/callbacks.c b/plugins/fw/FWnull/Linux/callbacks.c new file mode 100644 index 0000000..fa070a7 --- /dev/null +++ b/plugins/fw/FWnull/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/fw/FWnull/Linux/callbacks.h b/plugins/fw/FWnull/Linux/callbacks.h new file mode 100644 index 0000000..22cf74a --- /dev/null +++ b/plugins/fw/FWnull/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/fw/FWnull/Linux/conf.c b/plugins/fw/FWnull/Linux/conf.c new file mode 100644 index 0000000..2d3aa71 --- /dev/null +++ b/plugins/fw/FWnull/Linux/conf.c @@ -0,0 +1,136 @@ +/* FireWire + * Copyright (C) 2002-2004 FireWire Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "callbacks.h" +#include "FW.h" +#include "Config.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void cfgSysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "FireWire Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CFGabout() { + About = create_About(); + gtk_widget_show_all(About); + gtk_main(); +} + +GtkWidget *Conf; + +void OnConf_Ok(GtkButton *button, gpointer user_data) { + gchar *str; + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CFGconfigure() { + Conf = create_Config(); + + LoadConfig(); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +long CFGmessage(char *msg) { + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(argv[2]); + } + + return 0; +} diff --git a/plugins/fw/FWnull/Linux/firewire.glade b/plugins/fw/FWnull/Linux/firewire.glade new file mode 100644 index 0000000..6644e52 --- /dev/null +++ b/plugins/fw/FWnull/Linux/firewire.glade @@ -0,0 +1,300 @@ + + + + + FireWire + dev9linuz + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + DEV9config + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox1 + 5 + True + 5 + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Eth + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + + GtkFrame + frame3 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox2 + 5 + True + 5 + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Hdd + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + DEV9about + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/fw/FWnull/Linux/interface.c b/plugins/fw/FWnull/Linux/interface.c new file mode 100644 index 0000000..a73c086 --- /dev/null +++ b/plugins/fw/FWnull/Linux/interface.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *hbox1; + GtkWidget *label4; + GtkWidget *GtkCombo_Eth; + GtkWidget *combo_entry1; + GtkWidget *frame3; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_Hdd; + GtkWidget *entry1; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "DEV9config"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Ethernet"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + hbox1 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (frame2), hbox1); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label4 = gtk_label_new ("Device:"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (Config), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox1), label4, FALSE, FALSE, 0); + + GtkCombo_Eth = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Eth); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Eth", GtkCombo_Eth, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Eth); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_Eth, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Eth, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_Eth)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + frame3 = gtk_frame_new ("Hdd"); + gtk_widget_ref (frame3); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame3", frame3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (frame3), hbox2); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label5 = gtk_label_new ("Device:"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_Hdd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Hdd); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Hdd", GtkCombo_Hdd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Hdd); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_Hdd, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Hdd, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_Hdd)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "DEV9about"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("DEV9linuz Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Author: linuzappz "); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/fw/FWnull/Linux/interface.h b/plugins/fw/FWnull/Linux/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/fw/FWnull/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/fw/FWnull/Linux/support.c b/plugins/fw/FWnull/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/fw/FWnull/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/fw/FWnull/Linux/support.h b/plugins/fw/FWnull/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/fw/FWnull/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/fw/FWnull/PS2Edefs.h b/plugins/fw/FWnull/PS2Edefs.h new file mode 100644 index 0000000..b20cbbc --- /dev/null +++ b/plugins/fw/FWnull/PS2Edefs.h @@ -0,0 +1,724 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.0 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetCSR(u64 *csr); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetCSR)(u64 * csr); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetCSR GSsetCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/fw/FWnull/PS2Etypes.h b/plugins/fw/FWnull/PS2Etypes.h new file mode 100644 index 0000000..443ad45 --- /dev/null +++ b/plugins/fw/FWnull/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/fw/FWnull/ReadMe.txt b/plugins/fw/FWnull/ReadMe.txt new file mode 100644 index 0000000..f2ae2f5 --- /dev/null +++ b/plugins/fw/FWnull/ReadMe.txt @@ -0,0 +1,34 @@ +FireWire v0.3 +------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Usage: +----- + Place the file "FireWirePlugin.so" (linux) or "FireWirePlugin.dll" (win32) + at the Plugin directory of the Emulator to use it. + +Changes: +------- + v0.4: +*Added vsnet2005 beta1 support. 64bit dll should work okay (not tested yet!) + + v0.3: + *up to specs 0.5.5 + *added logging option and ini saving + + v0.2: + *new specs + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + shadow + linuzappz + + + diff --git a/plugins/fw/FWnull/Win32/Config.c b/plugins/fw/FWnull/Win32/Config.c new file mode 100644 index 0000000..d1b1459 --- /dev/null +++ b/plugins/fw/FWnull/Win32/Config.c @@ -0,0 +1,51 @@ +#include + +#include "FW.h" + +extern HINSTANCE hInst; +void SaveConfig() +{ + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\fwnull.ini"); + sprintf(szValue,"%u",Conf1->Log); + WritePrivateProfileString("Interface", "Logging",szValue,szIniFile); + +} + +void LoadConfig() { + FILE *fp; + + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\fwnull.ini"); + fp=fopen("inis\\fwnull.ini","rt");//check if firewirenull.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.Log = 0;//default value + SaveConfig();//save and return + return ; + } + fclose(fp); + GetPrivateProfileString("Interface", "Logging", NULL, szValue, 20, szIniFile); + Conf1->Log = strtoul(szValue, NULL, 10); + return ; + +} + diff --git a/plugins/fw/FWnull/Win32/FireWireNull.def b/plugins/fw/FWnull/Win32/FireWireNull.def new file mode 100644 index 0000000..dc1fd03 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull.def @@ -0,0 +1,19 @@ +; FireWire.def : Declares the module parameters for the DLL. + +LIBRARY "FireWirePlugin" + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + FWinit @5 + FWshutdown @6 + FWopen @7 + FWclose @8 + FWread32 @11 + FWwrite32 @14 + FWirqCallback @15 + FWconfigure @17 + FWtest @18 + FWabout @19 diff --git a/plugins/fw/FWnull/Win32/FireWireNull.dsp b/plugins/fw/FWnull/Win32/FireWireNull.dsp new file mode 100644 index 0000000..6361780 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="FireWireNull" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=FireWireNull - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "FireWireNull.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "FireWireNull.mak" CFG="FireWireNull - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "FireWireNull - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "FireWireNull - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "FireWireNull - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "__WIN32__" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "FireWireNull - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__WIN32__" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "FireWireNull - Win32 Release" +# Name "FireWireNull - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Config.c +# End Source File +# Begin Source File + +SOURCE=..\FireWire.c +# End Source File +# Begin Source File + +SOURCE=.\FireWireNull.def +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\FireWire.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=..\PS2Etypes.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\FireWireNull.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/fw/FWnull/Win32/FireWireNull.dsw b/plugins/fw/FWnull/Win32/FireWireNull.dsw new file mode 100644 index 0000000..e7ef5c3 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "FireWireNull"=.\FireWireNull.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/fw/FWnull/Win32/FireWireNull.ncb b/plugins/fw/FWnull/Win32/FireWireNull.ncb new file mode 100644 index 0000000000000000000000000000000000000000..93bbc90f1c588e65622aade8830ef7c1e9c20523 GIT binary patch literal 52224 zcmeI534C8wweR;nom)E5finLo1=>*Bq%#4rX_BU)8A_ARg)~k6X+qPaWGIvwWgZ1V zxC~NIK(rvB3<6>i1e6O88I?igdS$pGT)h_r5qZDwKIi=ZXQwHm?|t68>VL1C{MT7$ zojt5Q@3Yq4l`Rb&?VasSU8&-!#Rndks;rrxnmr{yf9T-dN@|Q;Ut_F(rt5l>d%1(c zpWOeP1acDiJD0#OiT}1waxN!abD09&7rj zqVIgtt2VCxqgAhawh23{h4?_pOST=O%qTN2@Y{)1X0!^g`hJQ!l?%`xU*JieXGLUV*U#G?&0=bH1)V2?J! zbeogSD_*!G%|w%DKJsWgn+axra|1M8#)UiDOg2-@2G74;Oum_89u$w3P0V1&x2xGr zFjTbuifQ=n?)piYITl(=MBCHsBREa|@ovbsmjNz_Xo2%@Z?lJBuZR|gv5(nR@L%$; zuda|b-i#B_7GEb?jrdpV0*AIizu@_zU7+8KBYOOt`_X##wtjieb&oFI?G*haU61Pi zC0(O+&CvDv==bdCJ)R#B@#(dk`yVKQOQ#gr<=3|}UIcU*30epK3UhDBL^VgvYV?ZVh zs}Lre_r=#gLkl$Lo@n0jXnoxLwN~%;&G7X#Qw0wxEDLP}aqefP3EWy_hSp!JlLh8u z`IqGzWM&K8d_BXrlbI=)q%cN`Ha8#thMEHf1HEvEX{JBLlzFt_8Z*r>!6`!xGQ{8a zbgdN5967$?xpH#eTr3`BQmHHFauWFeDS@X)ss0mz6l?!lCo)UTMpgcpHdM6brqS%5 zpbZzTN$XZGjLh;0HS0~AX&#)V$!l}1x!zo|Qn#=6iA3$($`%8pb6R#$~8EM^Np(JIov}NWqsXnji8FH>V4RdH#(sUlhE? zyQ!k4kZ+_pP4FJH;)wzF1QzhDmW!Wd;X3nqB9(dIZoK4H{vNQdu^(OT{q=1cI| zSXN`rNrKJLS{f&Ze7l$v1r45mwXzd-*ySr(H_GI%DXqhl} zH>V1Il}Nv%3qdmZ>?X>uv0z% zQf9iHZeLW{&GPMI4zvf_vqmRr<4u7ru+_UIY5SR}cB=j3*d*-$GsRA^%T=+m{!KFZ zHs9Xl@#UFmcAA~*#rZ%p!A`KRczl!1es({*#!K&1bC5mA-t5J1nwe-P+HVa@hCAIH zU=Oh0P-V=}Q)x1v5RqIc9-f zU=Q-*cd%J$SK4i!tPV9R>uZ|B=-p8V#TT3c&BR-2RM zD>6&$5<74AB(2z#*)qGvlV7P>Xct-}TW*(mVN{vbcC}sP$>j)BWvgtF$5(5rZM9wE<)Eg)JRpu(e6JFh4ZLSvl99nU8Wyp7=xkj+Xi_1~wQhTY*e6w+Bt25`?bFGFo z3AwB>U$$SineRA`ufbemFR_{LIF8n6&bDV;_Z^2e!qJ+{h4w<5`Htgg&E_0?j&ogzib{AoadE;%gkef#hzR)H$M`r_xS$B z{8(_aS1+$JPYYi6_^vU}3AT9k=&R;_!SP=EcddC*u*{Ro7V~|0Jld`LvUr4fTrv>ZgnZvN^?^WX z%hGN$%YtRWBZ^;^cDtzy>VlV*jx6mCb5w9taE{WOrG3XN36=zfs{2{mcg>1mMR1a2 znx)-omIh0M61A~e+FfQ37 zf5N;j80qzcPnzEdhI;kmDf5P)+6&`p^IJi)M|;NnPB6oxJ!{?)eCYKb&zrXe4|!p{ zpzrt}m{w(4w%q^Bd`@tNNBg-sOz>@w_M(|9m;mj#uhfM3`;xxp7n)ZYM`UO(ySei3 zJlZR6?mgOj_ZM!CzSZM<)y?Ja_h`R#bN(kh+H0~=m~Q%b{{5SoB{;;R{mL97sPSn3 zZVnZE6DDHb^00NMjbd&`svp7Pq4|1i7QU99!` zfVcJSe6$_njgfw|}Sc z7kFj&zs+zv+`j4Yy>CX?5%wdm|Mcv1B?`)**z2}XFdes-Xs#jAq@?GV9pUfCUDhY9Mua=(*3QLvZzB*LhD z9%?T)mz%r2IylT8EvQ4z%n@C_4Ywx*hkG8KpNpPo^m;2j|f^x6?O|r)bUh>8flWn`;CCM}^mxJv4f?5#lHt*fp_CEz*RDNXRGROW}u%Aae*uE|p<@r}=e_ME1Dk{P_A7+OHLxShLcRz1G64ZO|&b5Pr zLBYYET#D?#U|>+{#buuTP_Vl<-YvHMf_}k0s^{7GmDv74|6rS!zoqt%f_GJhvV8OH zp9K$lGAOg32<}sP$?`3*9}9+f{*~K4L7!l6mFFzq;r360jb7RoYP>%<_^Fr%w0A{o z4;9u1Hh9TPTcr);4)fwyWl?H<#iLc*zCqt$p%=y?dr)vtaJlMqHZDil3BiQmdun5| zw8i$o;J~26qt)2FATKz}qt)8+!T8`rFKtWg#9(4@hnGi7?Y_ajL7|tw%k2Ka{z0=> zCYRg&g8hPLJejVrlY_~@iC(xX?E%37!5A-$RrUeF2cE1}+v^3-dNMfD-Y}bz7QyRY*=V%i5$x@yEp6`* z96&j!T~Hm?k0yJs;0vCt*4gU>zxDF6*?w1WhL?^O`%S?QJieptw*D_3*COF9R?-=`i!M$EycG#~Ap7i9` zX>Sxv^y1fLZxY<+^;_Nc8-jISTsGMo1Yhyua;$wqaHPj~oP9`ejVHg&_Hn^gLFAaETYc6YPV6TCW_OXn!O)(~I9p_J@L6k9M+sRFLQ8(JA&Z!POq$srF&PP%n(r z>?49Zy)ym<`>%rYyfXepdyQZpFV3gis|2rmd3lDtT5y?{M`zl96FlU#FK5|b2sV3s zXWOR*o4oj)V}B`l*DJf{+E)cX_TqP*eM*qh*fA^T^X<mW5y6OHq!*Vf?ViD&!CWuTud;gtdjwm& zGIX^a77Po{^!&TVjtj;GYrHc4Rl94jYf$dR?^-)N7#{r5OUD*FDi{?^_1?YCjt)i# zW4(O4-tHXi9PHzT`!%~;uv<{;#rf-YWH2(g*{l0E*u8?ig716b-e|`LV}sv%vcJjh z66_MRd-D5+9TSWRtYpBq8oqUoGdJ5MW{G)2A8N9+Z`xW@YtGPzm@MsEc7^n=@ACMz z+6L2LPWEWG*m~(WU+K|qwQJ2qKLbEJ8~A;_=;O*O_%@iATHJHk)QM$fMn3H<%6P zZ3!hSm+#qD(`xSbX!qLdjKHJaXSbLw<|L1HzrE4iXqJ1l@7o*94Q7l-d%$irTg_~b z_5*v1xy8Jv@*;ASm)q>O%(u)TUfFoiHtO5mdar)`(6;E?-Byq9A={>JcSm}4^HaZY=$fOC9`hZgXYfC!>qT9I#DBPGvvk3;MZf3i>eBURJ-+cWJvr)R@aQNlfZt^e2(d&=#N0lz{_&sEZ zERiYn_#*5$ZgIReh!)2wjtl(p^Vo(U_Jd!(1t;g;}<_RMfq??B=`5D`#4N^;Em-7 z9?KEDME!8ggG^%?GOl7A#kh%a65}GqL5zDC=P<5e9K*PUamruIPngLISrX@Ng}Y}| zMkzC-m3Sco__^;N$@FC9_2s%Mbj{H9w(0`)fqIs#Kf@!Qw0`05%{BzThp4}c<3wC~ zmYet)`55P0oJTy%SKQ(NCb!}DN@Vl?d%CRa7KT#fWA7A_E`7Mf*dk=cTk5ZLK_$JHm z$A*RPUZmd=$?6f6|2^;ve)0T5et#&wWArRTkNk@Lc~AU=&-?LvywfwxF$&`?`59mM z&$|bze$7@m=PE6KP#KQnQm-@+pXTWLUBZ9-j^p--4P3KSkZ z@5(>IzDn&Wv^d^Rstm_|#A%D~<1`YtnF^1~J=6Qd!=v?(&sXGcyWS%naoR}N8LllFGf-~gtLJ@8=NJCuJ$6&*hFz&ny;E0#t`X6NP7XRa=-i-VgWe80H2wk)Z;8)KeLm7bPo7; zMc(<>UmA8pT^pR`8(@YBkVTd@P?mi|%xMY(nOvdYJ9KT)b(XGHU3crsxts)Y68PIC zFn*8hH!r@*P}iqXq`Jze?dYd(!F|m~&@ydDf74H} z%JXl4KEI4Gn?2e<&22`S!#vs`GhFZ$k2Y93gFBmpMC001*9cvIP?%hu!Y|gfETaAG zlFGfAlfXZo1nyUocFxpI>TZAYzf@O}H0oCTWAU!@z;&a~^G&Iowo-`f8alhU-iF0^@YkGPDu;a$l6y^><;6 zGPDYN$iLWjKqGY5w!Njeyrb)VT{2fN!*uP4R;p*Ux*BvnDfak^=au6{&$*lg{+=ap zn2S6k^qk8{ASZ!;HVJ6DE(;jr?B}$kC#Md)R~L+6Zt(xYtzUEeJPjqxFBBO1;96pm z8}I&a|1Z$0sdIKN*9IvAlC+r@MwgV)yM7z%SG3->Zm6L8L8GrLPFPTt&?)V!nx%9I9?=F~LJ8R;#eyK3eUcPzj6 zhI#$YIDE-#18;nBR8hf#GY-H0_BBWRX6vo@j@{?<5f`6bGU4nIBgc=t`0VG~st$NK zuj$c?um8m*GY93})qLH&6|eo|=g_2 zu$DpPw741;XMQh*@|oPJe~GL2vJ|~F_#27WTcda-NI5hoft&>X0VFU)%_+9)*s$|W zq33r7zSr`df%Q7p=U9)U%|!1PJzw;C(c?vL7d>6{a?!&@?-o5<^lH(gMQ;{8S@dGj zgGKLk5AmSaiXJO^tLUksmx>o+x^u=z*g5iJm8Vo#=6*w~3x6 zdYR~9qIZd&Wug2>j}pB}^d!-XL=O_ZNAw)gYebI`y+!mC(Mv=R5xqn74ACn@j}W~< z^aRlhL=OqCzZy*>2w(91&)54}6|?Ec#Cx#*>#hlbu6dS>XAp+|<^7A~uMp>367p*^iO&CiaHd z7h)608WL;dtckldaQ(8z&6+m4G1!Y?AI2Vy52-!CE(|*`?7pz`I!AHDjtjdj?6k1U z!VU|&E9|VWtHO>7yD99Xu#3VD3cDxloSa>g{K9StJ0}0Tu!43wy7wlZHYr&2MyA|wI*gKN%etgU3yB=e+XB2n#%i#MRs{!ap@I4MY3ciuE zwPWjQ3Z~p4cwyz&^=JRWwy=VWkKD_qC2R3c0{&3L8 zQ%C%%{mSWsZoBBBPu>~6x%s;X?0M0F@ATPy)1L;vG3r;VUOa2{=?#jibLf4^YiSAf zap?y?OWzq|yU~GqN?n4!n|P>S;Nyf-2Elg{Kj{U(Q8?unTw3O?4uKyioOTNQIq^`w z!4DTbwlf_f3i?*i*NRS^1D_(Cya(^Abxi6#_$bk-i{J&qV|&`ZqEI)W4^>#`yMfn; zhqedY3MWs&uM`jU4}8ApvAu0SQ7CWFS&OAz0G}it@&^2edY3j6{7vDME%4KX^PL8~ zkKU#3f)COi?F0D1@&`RM@HN8G=>uORoc0&|Kg1u~4iD5CG3_YyKZ{Oz1iwl+bp)K< zplP4MeqkJf*5^uX)HPn`#6j~Ut*@WaJVUj_c} z!l{SgR|}^N03W0O^poHN^)7u6_@Bf>8wI{lIPE<60SXJv>(LV*R z6wcm5;23Q%-T)tqslYSq3kZ}4n@L}S)-|-rA+q@SndbH3h#KSia{CrG)GX8=7 zy!aU>fDacB?J0PFwHy!W7o2w(OMwqk8tLo7^Tbb|1wKGrw8J6Z*Xf^vuNDt|Ecng} z3mr4?-9@MG245hYz6Jb?;(12D;Iz5)k>LI1KYbMV@p{6T1$-J9)K3H6grJ#Q( z9{O$Y-Gwu@0{=)jx^3Wl>0QQU;J+80aS`|!(dom%hbdgfPv9d(M-L8sym0zP@Kg0J zI=JAgL}$DS{!`Hz2Y~mJKa45Ce<3>KSa77v7z2Da(HV1szbgFZD4vD#lkpw&!NM7D zg1;r65A+M(NB{XA25uz>#IrwCL;f$rhpApVj7W{qT?i-r$eu@KQ73e$bKVw?(kHy2-6MU?~Wh@20x9I3Q zgRc;saV~gY;fy!H&kzseaqwRXXZ#HQ2jPrEz|R&={}0}xcNsr{4_9g!KZExXow)*d zfAKTs2Y*>O<8|==6wa6%JPGm@XKV&OP<}EV1m8>i%pt&E6po%Y_)76JUIQPc z|BSo9H;IQaF8E>MVSWMrZ=y412G19rF(>$*qB9==|3oZ^DUOK zI`q$rhjB6ZKH_1V4?auuc;EB^qA-4gj@||1PVf`N&)fn0An`Nb0{@lh?70L!Ksa+R z@YjW-{|{aze&$=??~2YG0lZXn_q|s50L7Cz3G}I=GlmCGiJ$ob_(0*zNx0r2sn$NPp15`{51^k(re&jf!-JdB0GuM^Jv2zO(fBO$7Kd(V0JhUm!YjEAU3qnU{c{Bsx0C;QNWr+yeZoqB9o(KSwz8K=6_J z&%6|TviQ+w2H!_G`p)2c2xs00zKh;vUIc!eaOO7P=L*Nh1AK}2na_YtAR^Q`F1nZUm;oHYpW zH-xhW0^UzJ^Cj>=Aux9Z-$Qif|KOvEXB3AMMaNDB`clzZI{+UhocS8~7V)rF0set- z=2_so=s)v#@Y&)=UmQFo9J>$j2I28u1j9sO4FLKK(V2ULkCLCvH^EO4&YTha8sV%p zfbTDU=78X8o!xvNe4*&^K07<0bu)~2TA=TBd~v|;vY`BmSrzJ8rv*w~R? z+uhRIHKna#t!dbCT#DPEBR*_7t-rlP&RF??(`wYM~y zn)*%Y=)PAE^_KIdqor*f-W;0l=xA#PYdUsu=XC9znm18Dd6V{UI<_Odu5;ByYbT}l zPvsxiBzNQ_vmw0!*6xs1KRaffFZmr)T;JNdRta{|OHIsci0&s%B)*f({AC^K`bPPN zkGfLzjg1|mwzRc$86vc(W?JdGbXP^o+NJ4^&X)GJkgaR;#M6KX2YYzqBIJgvo}`OA*&Xz5BvQP@=9+MPBX=}j$!XY%#9 zePg;UOhVqqlFp5ybfr7H^wZGV-pTt-9qIJ(Y17iymDr~GhaTI~rZb@`_R=!)1D$+55%0+-q6P#@e_PkfkmO#o7yM zUQzKvqrF@!tE*hJVXmvFtt+cB`N!oKxD4ceQBetmu$(}sS+rytl&}OqDK1&+c;;kY zDk)uhuy_jcGn6GY^F)}ICCp!@`x()FSxw#2(#199)m8YMpFb;nPhtD?C>BJ)e-K56 znD`H7hCUG?|H1U|f#Q{+I}s@N;;1YvU9o6!X-$px3lzGzw4$`Arc@gRx=<>sOG@je zO`qxCDnZGo)8-^^^JmP_hJwlGv!ds;KlJc5jMKC`SXzk*n6?MfG)yjY{F5FiyDy<4{i zSJ#P&LXGIio`Q&=auy{B>a+}XRzwY7t}LpF-YqGrEvj?3^B0$vu2i+CRwan=nxdtp z8N7UDsZj~)Om{6Vs*IX18gPmm&2C9$(VR-%)9&VN1f%`xY*9m22T%Rl_UiT8FYZ*oeKndAhQ?9}if?$J^);&PazRu@My?`m%#i7o}m zx~a8Z%|0(@+Ib`piCbuhmDOY(D-SX_a&^6qi?r*RG9q=+mO!1jGufAnayDTR7PZln zB+Ag+vYMzfLt2qcX1iiiFe@r1b;)i!BV@dQe~#&%<8m;HW?7BPlR4XE$($&nnWVYa z+og!&($Lk>TH8^-x!9#veOXvEGM&-v8R?n%2RF>Fn~ih}qU5?f3FRZ9rMongP=DxN z&4?-Ti=yX(bn$bgBg9l#QsF4TJx&TCD?gaxfZ}=IId=mTm6hiDw#L?UhpXDI z+L3}xQC<)|MQSmpf{u$~X7J^PNtE4$7vzyE({&0aOiNTvGlCAoq9D2Gs==8-Nh+&} zW0y&J=#heUh|B(Lm9LY_co7-Hg8kZyjP};UDDm@#4Ox1<6k*twT-1KZ$rD#DAcv$4X z94koNB~>#YB<4{qP{E9v%w$4ch}leZx6V`YHteGC)U|lTNLiuzc=yIGwUe`5w#Dgp zBcw1sdebk%otcj8ZWx|r$jW)&7Ps|@GA`>mRDoSDp$232&w!c?!R5VKow=-nTegsSchI|#--E^lj0ANOetm7n&o=F=X|-@!xL zo8BYb*wWdsqwsjPqu_YfYiP;Ui%fYaC@fU--CGp&B<=ccs%WMn(HI}oo$lC7Jl0eOEIB9oOu* z;ZN9h#T`sMs>^f;;Sh`%yBo_j#@FoA^PHK65=7JqBZyG?8U{H=rJ96B(x7g2wQNYcnXX<-WO`XmMzGl=#3a&@NiZ|W z%pe_VCc07k>!!MDTr&%W!dwJ-Gg|FT1eXmYy(u%D)J!OBV|gPHO(d8plVLX!l^NG< z)h)^l;xj9#NHm;`$8+##sOb7V;#||c_6Toeqk^L8I^=jP6y*ed`Q2i2Fqa(BWHZGD z6HSq`IjO9g7NcVX8AOL2UtB4pSsG0MzB$%d zi18o=DJDurnE%OP1aF3uE1pHoL(fq!j}jG<5)iJ5WC|A9lr3~|S#Z->*Xk)=VSOaL zu)-n6Oj(NGNab~QuRX>U`ed!o7ShCWeImoda_Z_r6wjm}!c(T7_;cMkwl;@)sjaow6k*3@9sJb;$@O*^bwi;AhxWyI8Bl#I-A|8FN@L z>(LX$1HJ4jQl=_~US*1i+PTDPR6PFl`XZHRVih+qF49S1$16QN2nWyfDGi$&^cl;I zYQvm#a#Q=58I#UX!A}hDr@IEwmC7A1@JEaK*|AJroqW_JuT!$ua$-kU_K_Z#PUe3R zOJ@8N@^#K}!^bQ?y;JWWNVMjoZ+IQ)&i3w(hO|DGl$Vs$6<1fyFR3Uq1^Rpt-yW$0<#S3-3Zhro3cdw5pW#v_6rmkpFOWa*p`C2&3Jgiw!SsK6C ztAN8~y8rsDH$I!*@ur9#w4`;NK2bK9dDYbwZgih&US^h*SJkGvD?8VjWjeE@s4{iz zqI!MAG!@}pYk1dOu8(SFL3ve8ZBbRRR<+~SG4`{hwY9RorOhl*;`HUGxw5^nTT{l8 zWz~yIQjNzh)|XNZAd>@!P!Qjd!(gR1$A-x`l)2g5 z6^Ftx%Ec&_qZo?9I0h^jKYSL4!4QWqqEyXhpUb2uD@|j=MhFgz!Y#Pwhu{mjrG!vgwzF??@!go)HVk%18I5xz^aX=Ib z>KL%0fQeB6oA9!69h=x;p!I7#!vKVX4B5mE$A*|}LX8m|3e6Z9pwNz@BpV*a&zo3QbM^NCDNqBD1r@kpOykDhFfd^io=iz0|hqw<Z#-S98!`KbSX3Qvcvw3jr zwnzrC!vF&Vf}V~|ZgCty`L{R>R@fw&4YD~j49CXxI1H>fa4dEx&7+XZ=Cf={9=k`C z=a)+sYY9L|VA8=EI{u-#3HHyaE;83y4t*pE6eq(TmV-s!+YkN8jA@3Iv<0OpoFiyj0hQre^ zq{lFhO$Tupkzn+MV?$~-oyR~F$L8x_53^FeF=|bYMh-(I5t(9NLOeCz7}2r0BE~y7Hm>i@v7rz~ zmwlD*9Jst#a^{fgq+aTuv`=p_a|7=b4phP*h8 zXD|ke9fpIS<~WD~L+9QcM&}r5a=0`GPqD**j|0@%{2b#O4DHz*s;A??*@r~rP!kTh z9fxM%Fc9XD z6AsU0v(=GNKJW|!q@IqA6#g2AF%hmr?F5G}aL51#sW>)~=dhI*B{L3x>CJIa1{*(M z#Fum&G|k2XNyh;Vy}9zJ9qH{Ehos`JlAK>t{o^15+|9ao#IWyKXKpCyKLximfpu;5OsHtpQ^yWtUJmbw-5rT~ z!p0dK0L$hc9G=WZATKJ;94_){4&!bN+BtM3c5@Z4Kgcf*O1WC^&(JR$^x-(5CUzLS z$8LF)Puyd;%0U?zJ!3$Jp&f?dJ* z$Af#RgE3$3_wQN)mrg0L%b#CaOzpY#!V}g${nRH5ulxA+rwUHJE$>oENI}*1ovLonn%F2$rBQ4#VbX!BZ96ghS2U9;~EiYVV z(_-FV8Z|UC#YoN`Rh^0#uf0;wMcBlQLPQg^d5DnCPL%_-65)s*K;ZuP)vH zr>?oWr(jWN4%D@`u9U8QbdA>~Rx?4@e!BM8MFE|tYm%-!UG#($I`wca9C{~uQF=<^ z#>j%+h%kr`g_ikdr`80yzofB#@IpP69az{9Q}ne*>GE BYC`}3 literal 0 HcmV?d00001 diff --git a/plugins/fw/FWnull/Win32/FireWireNull.rc b/plugins/fw/FWnull/Win32/FireWireNull.rc new file mode 100644 index 0000000..a084b79 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull.rc @@ -0,0 +1,123 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifdef __MINGW32__ +#include "afxresmw.h" +#else +#include "afxres.h" +#endif + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 212, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Firewireconfigure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,48,100,50,14 + PUSHBUTTON "Cancel",IDCANCEL,113,100,50,14 + CONTROL "Enable Logging (for develop use only)",IDC_LOGGING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,187,13 +END + +IDD_ABOUT DIALOGEX 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "FireWire About" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "FireWire Driver",IDC_NAME,70,10,48,8 + GROUPBOX "",IDC_STATIC,5,35,170,40 + LTEXT "Author: Shadow and linuzappz",IDC_STATIC,29,19,141,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/fw/FWnull/Win32/FireWireNull.sln b/plugins/fw/FWnull/Win32/FireWireNull.sln new file mode 100644 index 0000000..95dd0df --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FireWireNull", "FireWireNull.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/fw/FWnull/Win32/FireWireNull.suo b/plugins/fw/FWnull/Win32/FireWireNull.suo new file mode 100644 index 0000000000000000000000000000000000000000..c194506856e6ee0d4e9ca8d32b2ace824efe05e5 GIT binary patch literal 7168 zcmeHMOK)366h3Yeng>ZAlmG#WY5EdstuzTulL!!rlMpFxN|Gj(h>#rn#&vV;YwYW$ z6;xu!4wXfJ01|5u8&<54y67qh2_dnf3&au@JPNc8-#7P;eeJ~W7EzRAojb2HbLMeg zGyZyG-wz*u-g8@u;8kgo`*rARdy4YF9iz{mW-^)jKq=Javom; zbJF#h3IiUNUA}#wp}ue)706XHZ6@gn)3PY@5|W_16Dh^r#wm=comqG1<4|w?z6AcY zuHS2~wNCR)v>jj_ZGdj`+JH{fcLDc!+V^|%y3bRndm8u*um|`o@Hyb~K+?S6rZ2i_ zFVe%nBfz6>9qD%9;qJh6@BVkbZJC?+=*HA7b8-4-Y<*4e%Q(G6{XpNcCum%bM-2bC zm9*2AsZ_2x7`DS4w*5kA#y=mqXe3mzGZ+t>R?I&UjoVh51bai)O58O3OU8( z_qKvk`?!@zSxF;ltH#cycrt3OXY%CDZ!CmnI9S)X8BeWP;dInL7f;4mwR_4)8tJgf z{8peYHv;T`1~@JwvMebvB`Y!5q9pWw85VIJ-$_|QIg2(Er6tumApOWU4%4u7^Z=%; z;CltOh}Q2ictnt^41U-C&<0RaEBA2X#!p?sAh@ikHOCa^CD>ydyf30u$@X#x@_zy; zZCADY8Rr}T5{miL>Kd5C8qUH}J8hSp$8qqdFQJXBmOuSu5J)KIPyffAPhl70m;vRW z92~8~|Izno|I?`a>bcQ>ybpBb*zxKy>}6OIIHO6d#Z)J{3|~jtqSwy=SFuh%d?3AV z7Stw6^Qg;8RIT4H0Xd7PU;*|0(udywHqs2zh|-4-|MfXgUQMiWRn0)p zM3+VWD>HKDS!^?k<&P(o#NN;2Y_e)s%Uc1+pO3Kuy+F0{Pueei_y9`tzluGjO)6n{ zo$iPgYLEY@uch=q1Sw5`E8}3t(ne8Y6t+E_!1^isydPD&e#VOn?r_w18$8q4bxMC; zQ*>l(K(1`)6>R}2`OVK}1pLWYgF9^5MBB@9iSK*sVg4qVV3C&8i7XpQx-zd zG!v&9SC%gfS)lz(p+s+#p&{tK2Yh zFT-M<1YI8}hfzC*_R}a2K=aPXHGD0|R~9nwNS0UT&!H`YS(Wodeb7JN2^hyw29Z<* z>K<(dp&WmG7Yjl&Y~Xeffc*15Qj7dQ33|p01ll>qTzZX;o~>flG1St3=@y5+_zV5d z@ve6L-5BJ1*Z$4I#$AF0&{vky@nW9d^1(XzAH)D5caQ*V{d$qy&8q0bD|Ni>(JOD2 zO~*QswpHER9;9rJ%4^{JAV&bx0!j)5u)?s?5)g!j6# z#c{;P22N`gr{=7j(p)(5C~B$!+R2{|9Qo$6-rlJ%e!P9{*h*qhiALA09`kNn@9g!> z5AJMy^~r>fwY*8wLoi0ArZPPXIpxhj zd%d2g_Hy)ty#3Jg(i=L`Mt@fx`2Iq^v?o0wpr8pMW_h9{$3~Fe#>pukA5!e2_=@)q$XI{_kv((%J(2odC(|OtR{AU2Z z#lUIsU8qodyn5-h=i@})P;F(Elh8k&kmDQ4r&WFpI2>B#w_NUbH`gI|RIW+>K+0ZC z@@J0fuUzi$T<&fzchAjr$flb+f&NpNOA<&wVY-^*_>Qf!bk?y5sxizu0t?JrrjfgU zbKb{+e20w|jOECrei@9TPhKuBY`71p>|O`xcTWBOIS<=M9poLHUNO&U`@yOIlsgUE cQx(=8Ls8#93tQ?dY2Hlh8= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.sln b/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.sln new file mode 100644 index 0000000..8348796 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FireWireNull", "FireWireNull_vsnet2005beta1.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + amd64|Win32 = amd64|Win32 + amd64|Win64 (AMD64) = amd64|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win32.ActiveCfg = amd64|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win32.Build.0 = amd64|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win64 (AMD64).ActiveCfg = amd64|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.amd64|Win64 (AMD64).Build.0 = amd64|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win32.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win32.Build.0 = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {F7181922-7377-4F67-9F50-10997B4613D8}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.vcproj b/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.vcproj new file mode 100644 index 0000000..e1bf380 --- /dev/null +++ b/plugins/fw/FWnull/Win32/FireWireNull_vsnet2005beta1.vcproj @@ -0,0 +1,431 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/fw/FWnull/Win32/Makefile b/plugins/fw/FWnull/Win32/Makefile new file mode 100644 index 0000000..82afda1 --- /dev/null +++ b/plugins/fw/FWnull/Win32/Makefile @@ -0,0 +1,29 @@ + +RC = windres +STRIP = strip + +PLUGIN = FWnull.dll +CFLAGS = -Wall -O2 -fomit-frame-pointer -I.. -D__WIN32__ -D__MINGW32__ +LIBS = -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +RESOBJ = FireWireNull.o +OBJS = ../FW.o Config.o Win32.o ${RESOBJ} + +DEPS:= $(OBJS:.o=.d) + +all: plugin + +plugin: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clear plugin + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} + +${RESOBJ}: FireWireNull.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/fw/FWnull/Win32/PS2Edefs.h b/plugins/fw/FWnull/Win32/PS2Edefs.h new file mode 100644 index 0000000..eafdf7e --- /dev/null +++ b/plugins/fw/FWnull/Win32/PS2Edefs.h @@ -0,0 +1,651 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.4.9 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0004 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0002 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0002 +#define PS2E_USB_VERSION 0x0001 +#define PS2E_FIREWIRE_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 + +typedef struct { + int size; + s8 *data; +} freezeData; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +void CALLBACK USBirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/fw/FWnull/Win32/Win32.c b/plugins/fw/FWnull/Win32/Win32.c new file mode 100644 index 0000000..205bb8f --- /dev/null +++ b/plugins/fw/FWnull/Win32/Win32.c @@ -0,0 +1,81 @@ +#include +#include +#include + + +#include "resource.h" +#include "FW.h" + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "FW Plugin Msg", 0); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + if (conf.Log) CheckDlgButton(hW, IDC_LOGGING, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOGGING)) + conf.Log = 1; + else conf.Log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK FWconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK FWabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/fw/FWnull/Win32/afxresmw.h b/plugins/fw/FWnull/Win32/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/fw/FWnull/Win32/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/fw/FWnull/Win32/plugin.def b/plugins/fw/FWnull/Win32/plugin.def new file mode 100644 index 0000000..1ac66e0 --- /dev/null +++ b/plugins/fw/FWnull/Win32/plugin.def @@ -0,0 +1,15 @@ +EXPORTS + FWabout = FWabout@0 @3 + FWclose = FWclose@0 @4 + FWconfigure = FWconfigure@0 @5 + FWfreeze = FWfreeze@8 @6 + FWinit = FWinit@0 @7 + FWirqCallback = FWirqCallback@4 @9 + FWopen = FWopen@4 @10 + FWread32 = FWread32@4 @11 + FWshutdown = FWshutdown@0 @12 + FWtest = FWtest@0 @13 + FWwrite32 = FWwrite32@8 @14 + PS2EgetLibName = PS2EgetLibName@0 @16 + PS2EgetLibType = PS2EgetLibType@0 @17 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @18 diff --git a/plugins/fw/FWnull/Win32/resource.h b/plugins/fw/FWnull/Win32/resource.h new file mode 100644 index 0000000..f8ab276 --- /dev/null +++ b/plugins/fw/FWnull/Win32/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by FireWireNull.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_CHECK1 1007 +#define IDC_LOGGING 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/fw/FWnull/build.sh b/plugins/fw/FWnull/build.sh new file mode 100644 index 0000000..a7ad4f2 --- /dev/null +++ b/plugins/fw/FWnull/build.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +echo --------------- +echo Building FWnull +echo --------------- + +curdir=`pwd` + +cd ${curdir}/Linux +make $@ + +if [ -s cfgFWnull ] && [ -s libFWnull.so ] +then +cp cfgFWnull libFWnull.so ${PCSX2PLUGINS} +fi diff --git a/plugins/fw/build.sh b/plugins/fw/build.sh new file mode 100644 index 0000000..f97fa19 --- /dev/null +++ b/plugins/fw/build.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo ---------------------------- +echo Building FireWire plugins... +echo ---------------------------- + +curdir=`pwd` + +cd ${curdir}/FWnull +sh build.sh $@ + +#cd ${curdir}/FWlinuz +#sh build.sh $@ diff --git a/plugins/gs/GSsoft/License.txt b/plugins/gs/GSsoft/License.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/gs/GSsoft/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/gs/GSsoft/ReadMe.txt b/plugins/gs/GSsoft/ReadMe.txt new file mode 100644 index 0000000..5b9f33f --- /dev/null +++ b/plugins/gs/GSsoft/ReadMe.txt @@ -0,0 +1,109 @@ +GSsoft v1.0 +----------- + + This is an extension to use with play station2 emulators + such as PCSX2. + The plugin is free open source code. + +Using: +----- + Place the file "GSsoft.dll" (Windows) or "GSsoft.so" (Linux) + at the Plugins directory of the Emulator to use it. + +Configuration: +------------- + Display Resolution: + Select the Resolution mode you want to use. + + Fullscreen: + Sets fullscreen mode (else windowed). + + Display FPS Count: + This will show on the start the frame per second count, + also you can change settings from here. + + Frameskip: + You can use this to improve a little speed (will skip some + frames). + +Quick Keys: +---------- + Delete - Show/Hide FPS Count. + End - Change selected setting in FPS Count. + PageUp/ + PageDn - Move up/down in the FPS Count. + +Changes: +------- + v1.0 + * Fixed GIFprocessReg with RGBAQ/STQ handling + + v0.9 + * Lots of fixes, implemented most psm's, thx to gabest + for helping me with some stuff + * Rewrote triangle algorithm, based on the 3DFC algo, + http://www.geocities.com/SiliconValley/Bay/1704 + * Both CRTs now are blended when both enabled + + v0.8 + * Up to 0.5.5 specs + * Several fixes + * Up to SDL 1.2.7 + * added sdl_gfxprimitives 1.5 inside source. No need to load external dll + * savings are now done in ini. + * cleanup some stuff + + v0.6 + * Added savestates support + * Partially fixed the local memory structure, big thanks to asadr/tyranid + * Fixed some bugs + * This version is a bit untested, so you may expect some crashes ;P + v0.5: + * Added Color.c/Texts.c + * Most _Z primitives are implemented + * Fixed lots of bugs + * Implemented Alpha Blending + * Implemented colorclamping + * New PS2Edefs v0.4.0 + + v0.41: + * Corrected VSync interlace bit + * Added FINISH handling + * Added From VRam transfers + + v0.4: + * Added Linux-SDL dir, thanks to Muad + * Added bugfix for ps2mame (thanks to asad) + * STQ stuff starts to work (thanks to Absolute0) + * Added GSgifTransfer2 support + * Also some internal changes + + v0.31: + * Fixed interlace modes + + v0.3: + * Added Draw.c/h for blits. + * Added ShowFullVRam option on FPS Count. + * Added some zBuffer support. + * Last vertex rgba is now ok. + * Added more stuff on GSwrite/read32/64 + + v0.2: + * 16bit mode should be fine always now + * Cursor will be disabled in windowed mode too + * Improved lots of stuff, psms now works (8bit textures) + * Added non-stretched blits + * Linux support under XWindows (GSsoftx) + + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + + linuzappz + [TyRaNiD] + shadow + + diff --git a/plugins/gs/GSsoft/Src/Cache.c b/plugins/gs/GSsoft/Src/Cache.c new file mode 100644 index 0000000..08353cf --- /dev/null +++ b/plugins/gs/GSsoft/Src/Cache.c @@ -0,0 +1,201 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "Draw.h" +#include "Mem.h" +#include "Page.h" +#include "Texts.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +typedef struct { + u32 *_data; + u32 *data; + tex0Info tex0; +} Cache; + +Cache *Texts; +Cache *Texture; +int TextureCount; + +int CacheInit() { + Texts = (Cache*)malloc(conf.cachesize * sizeof(Cache)); + memset(Texts, 0, conf.cachesize * sizeof(Cache)); + TextureCount = 0; + + return 0; +} + +void _CacheLoadTexture32(Cache *tex) { + s32 otick; + s32 tick; + u32 *mem; + u32 *ptr; + int u, v; + +#ifdef __GNUC__ + __asm__ __volatile__ ( + "rdtsc\n" + : "=a"(otick) : + ); +#else + __asm { + rdtsc + mov otick, eax + } +#endif + + ptr = tex->data; + for (v=0; vtex0.th; v++) { + for (u=0; utex0.tw; u+=8) { + mem = &vRamUL[getPixelAddress32(u, v, tex->tex0.tbp0, tex->tex0.tbw)]; +#ifdef __GNUC__ + __asm__ __volatile__ ( + "movsd %1, %%xmm0\n" + "movhps %2, %%xmm0\n" + "movaps %%xmm0, %0\n" + : "=m"(&ptr[0]) : "m"(&mem[0]), "m"(&mem[4]) + ); +#else + ptr[0] = mem[0]; ptr[1] = mem[1]; + ptr[2] = mem[4]; ptr[3] = mem[5]; + ptr[4] = mem[8]; ptr[5] = mem[9]; + ptr[6] = mem[12]; ptr[7] = mem[13]; +#endif + ptr+= 8; + } + + for (; utex0.tw; u++) { + *ptr++ = readPixel32(u, v, tex->tex0.tbp0, tex->tex0.tbw); + } + } + +#ifdef __GNUC__ + __asm__ __volatile__ ( + "rdtsc\n" + : "=a"(tick) : + ); +#else + __asm { + rdtsc + mov tick, eax + } +#endif + + printf("%d\n", tick - otick); +} + +void _CacheLoadTexture(Cache *tex) { + u32 *ptr; + int u, v; + + ptr = tex->data; + for (v=0; vtex0.th; v++) { + for (u=0; utex0.tw; u++) { + *ptr++ = GetTexturePixel32(u, v); + } + } +} + +void CacheLoadTexture(int i) { + Texts[i].tex0 = *tex0; + Texts[i]._data = malloc(Texts[i].tex0.th*Texts[i].tex0.tw*4+16); + Texts[i].data = _align16(Texts[i]._data); +/* if (Texts[i].tex0.psm == 0) { + _CacheLoadTexture32(&Texts[i]); + return; + }*/ + _CacheLoadTexture(&Texts[i]); +} + +void CacheFreeTexture(int i) { + free(Texts[i]._data); Texts[i]._data = NULL; +} + +int CacheSetTexture() { + int i; + +#ifdef GS_LOG + GS_LOG("CacheSetTexture\n"); +#endif + if (tex0->tbp0 == gs._gsfb[0].fbp || + tex0->tbp0 == gs._gsfb[1].fbp) { + return -1; + } + + for (i=0; i= conf.cachesize) TextureCount = 0; + CacheFreeTexture(i); + } + +#ifdef GS_LOG + GS_LOG("CacheSetTexture: %dx%d: %d\n", tex0->tw, tex0->th, i); +#endif + printf("CacheSetTexture: %x, %dx%d: %d\n", tex0->tbp0, tex0->tw, tex0->th, i); + CacheLoadTexture(i); + Texture = &Texts[i]; + return 0; +} + +u32 CacheGetTexturePixel32(int u, int v) { + wrapUV(&u, &v); + if (u < 0 || u >= Texture->tex0.tw) return 0; + if (v < 0 || v >= Texture->tex0.th) return 0; +#ifdef GS_LOG +// GS_LOG("CacheGetTexturePixel32 %dx%d\n", u, v); +#endif + return Texture->data[v*Texture->tex0.tw+u]; +} + +void CacheClear(u32 bp, int size) { + int i; + + for (i=0; i + +#include "GS.h" +#include "Soft.h" +#include "Texts.h" +#include "Color.h" +#include "Mem.h" + +/* blend 2 colours together and return the result */ +u32 blender(const u8 *A, const u8 *B, const int C, const u8 *D) { + int i; + u32 res = 0; + int temp; + + for (i = 0; i < 3; i++) { + temp = ((((int) A[i] - (int) B[i]) * C) >> 7) + (int)D[i]; + if (gs.colclamp) { + if (temp < 0x00) temp = 0x00; else + if (temp > 0xFF) temp = 0xFF; + } else { + temp&= 0xFF; + } + + res |= temp << (i << 3); + } + + return res; +} + +int scissorTest(int x, int y) { + if (x < scissor->x0 || x > scissor->x1) return -1; + if (y < scissor->y0 || y > scissor->y1) return -1; + + return 0; +} + +int dateTest32(int x, int y) { + if (test->date) { // Destination Alpha Test + u32 pixel = readPixel32(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 31) == 0) return -1; + } else { + if ((pixel >> 31) == 1) return -1; + } + } + + return 0; +} + +int dateTest16(int x, int y) { + if (test->date) { // Destination Alpha Test + u16 pixel = readPixel16(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 15) == 0) return -1; + } else { + if ((pixel >> 15) == 1) return -1; + } + } + + return 0; +} + +int dateTest16S(int x, int y) { + if (test->date) { // Destination Alpha Test + u16 pixel = readPixel16S(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 15) == 0) return -1; + } else { + if ((pixel >> 15) == 1) return -1; + } + } + + return 0; +} + +int dateTest32Z(int x, int y) { + if (test->date) { // Destination Alpha Test + u32 pixel = readPixel32Z(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 31) == 0) return -1; + } else { + if ((pixel >> 31) == 1) return -1; + } + } + + return 0; +} + +int dateTest16Z(int x, int y) { + if (test->date) { // Destination Alpha Test + u16 pixel = readPixel16Z(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 15) == 0) return -1; + } else { + if ((pixel >> 15) == 1) return -1; + } + } + + return 0; +} + +int dateTest16SZ(int x, int y) { + if (test->date) { // Destination Alpha Test + u16 pixel = readPixel16SZ(x, y, gsfb->fbp, gsfb->fbw); + if (test->datm) { + if ((pixel >> 15) == 0) return -1; + } else { + if ((pixel >> 15) == 1) return -1; + } + } + + return 0; +} + +int depthTest(int x, int y, u32 z) { +//GS_LOG("depthTest %dx%d %x\n", x, y, z); + switch (test->ztst) { + case ZTST_NEVER: + return -1; + + case ZTST_ALWAYS: + break; + + case ZTST_GEQUAL: + if (z < readPixelZ(x, y)) return -1; + break; + + case ZTST_GREATER: + if (z <= readPixelZ(x, y)) return -1; + break; + } + + return 0; +} + +int _alphaTest(u32 p) { + switch (test->atst) { + case ATST_NEVER: + return -1; + case ATST_ALWAYS: + break; + case ATST_LESS: + if ((p >> 24) < test->aref) break; + else return -1; + case ATST_LEQUAL: + if ((p >> 24) <= test->aref) break; + else return -1; + case ATST_EQUAL: + if ((p >> 24) == test->aref) break; + else return -1; + case ATST_GEQUAL: + if ((p >> 24) >= test->aref) break; + else return -1; + case ATST_GREATER: + if ((p >> 24) > test->aref) break; + else return -1; + case ATST_NOTEQUAL: + if ((p >> 24) != test->aref) break; + else return -1; + } + + return 0; +} + +int alphaTest(u32 p) { + if (test->ate == 0) return 0; + + if (_alphaTest(p) == -1) { + switch (test->afail) { + case AFAIL_KEEP: + return -1; + case AFAIL_FB_ONLY: + return 1; + case AFAIL_ZB_ONLY: + return 2; + case AFAIL_RGB_ONLY: + return 3; + } + } + + return 0; +} + +u32 fog(u32 p) { +/* if (prim->fge) { // Fogging + u8 r, g, b, a; + + r = ((F * (p >> 16)) >> 8) + + (((0xff - F) * fogcolr) >> 8); + p = (r << 16) | (g << 8) | b + }*/ + + return p; +} + +u32 (*procPixelABE) (int, int, u32); + +u32 _procPixelABE(u32 Cs, u32 Cd) { + u32 A, B, C, D, c; + + switch (alpha->a) { + case 0x00: A = Cs & 0xffffff; break; + case 0x01: A = Cd & 0xffffff; break; + default: A = 0; break; + } + + switch (alpha->b) { + case 0x00: B = Cs & 0xffffff; break; + case 0x01: B = Cd & 0xffffff; break; + default: B = 0; break; + } + + switch (alpha->c) { + case 0x00: C = Cs >> 24; break; + case 0x01: C = Cd >> 24; break; + case 0x02: C = alpha->fix; break; + default: C = 0; break; + } + + switch (alpha->d) { + case 0x00: D = Cs & 0xffffff; break; + case 0x01: D = Cd & 0xffffff; break; + default: D = 0; break; + } + c = blender((u8 *) &A, (u8 *) &B, C, (u8 *) &D); + c|= fba->fba << 31; +// printf("_procPixelABE (%d): %dx%d: %x, %x, %x, %x: %x (%d)\n", gs.pabe, x, y, A, B, C, D, c, alpha->c); + + return c; +} + +u32 _procPixelABE32(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel32(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE24(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel24(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE16(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel16to32(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE16S(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel16Sto32(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE32Z(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel32Z(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE24Z(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel24Z(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE16Z(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel16Zto32(x, y, gsfb->fbp, gsfb->fbw)); +} + +u32 _procPixelABE16SZ(int x, int y, u32 p) { + if (gs.pabe) { + if ((p >> 31) == 0) { // MSB = 0*/ + return p; + } + } + + return _procPixelABE(p, readPixel16SZto32(x, y, gsfb->fbp, gsfb->fbw)); +} + + +void _drawPixelAA1(int x, int y, u32 p) { +} + +////////////////////////////////// +// drawPixel + +void _drawPixel32(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest32(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (gsfb->fbm) { + p = (p & (~gsfb->fbm)) | (readPixel32(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } + + if (ret == 0 || ret == 1) { + writePixel32(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + writePixel24(x, y, p, gsfb->fbp, gsfb->fbw); + } +} + +void _drawPixel24(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (gsfb->fbm) { + p = (p & (~gsfb->fbm)) | (readPixel24(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } + writePixel24(x, y, p, gsfb->fbp, gsfb->fbw); +} + +void _drawPixel16(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest16(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (ret == 0 || ret == 1) { + if (gsfb->fbm) { + p = (RGBA32to16(p) & (~gsfb->fbm)) | (readPixel16(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } else { + p = RGBA32to16(p); + } + writePixel16(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + if (gsfb->fbm) { + u32 fbm = gsfb->fbm | 0x8000; + p = (RGBA32to16(p) & (~fbm)) | (readPixel16(x, y, gsfb->fbp, gsfb->fbw) & fbm); + } else { + p = (RGBA32to16(p) & ~0x8000) | (readPixel16(x, y, gsfb->fbp, gsfb->fbw) & 0x8000); + } + writePixel16(x, y, RGBA32to16(p), gsfb->fbp, gsfb->fbw); + } +} + +void _drawPixel16S(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest16S(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (ret == 0 || ret == 1) { + if (gsfb->fbm) { + p = (RGBA32to16(p) & (~gsfb->fbm)) | (readPixel16S(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } else { + p = RGBA32to16(p); + } + writePixel16S(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + if (gsfb->fbm) { + u32 fbm = gsfb->fbm | 0x8000; + p = (RGBA32to16(p) & (~fbm)) | (readPixel16S(x, y, gsfb->fbp, gsfb->fbw) & fbm); + } else { + p = (RGBA32to16(p) & ~0x8000) | (readPixel16S(x, y, gsfb->fbp, gsfb->fbw) & 0x8000); + } + writePixel16S(x, y, RGBA32to16(p), gsfb->fbp, gsfb->fbw); + } +} + +void _drawPixel32Z(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest32Z(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (gsfb->fbm) { + p = (p & (~gsfb->fbm)) | (readPixel32Z(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } + + if (ret == 0 || ret == 1) { + writePixel32Z(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + writePixel24Z(x, y, p, gsfb->fbp, gsfb->fbw); + } +} + +void _drawPixel24Z(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (gsfb->fbm) { + p = (p & (~gsfb->fbm)) | (readPixel24Z(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } + writePixel24Z(x, y, p, gsfb->fbp, gsfb->fbw); +} + +void _drawPixel16Z(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest16Z(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (ret == 0 || ret == 1) { + if (gsfb->fbm) { + p = (RGBA32to16(p) & (~gsfb->fbm)) | (readPixel16Z(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } else { + p = RGBA32to16(p); + } + writePixel16(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + if (gsfb->fbm) { + u32 fbm = gsfb->fbm | 0x8000; + p = (RGBA32to16(p) & (~fbm)) | (readPixel16Z(x, y, gsfb->fbp, gsfb->fbw) & fbm); + } else { + p = (RGBA32to16(p) & ~0x8000) | (readPixel16Z(x, y, gsfb->fbp, gsfb->fbw) & 0x8000); + } + writePixel16Z(x, y, RGBA32to16(p), gsfb->fbp, gsfb->fbw); + } +} + +void _drawPixel16SZ(int x, int y, u32 p) { + int ret; + + if (scissorTest(x, y)) return; + if (dateTest16SZ(x, y)) return; + ret = alphaTest(p); + if (ret == -1) return; + + if (prim->abe) { // alpha blending + p = procPixelABE(x, y, p); + } + + if (ret == 0 || ret == 1) { + if (gsfb->fbm) { + p = (RGBA32to16(p) & (~gsfb->fbm)) | (readPixel16SZ(x, y, gsfb->fbp, gsfb->fbw) & gsfb->fbm); + } else { + p = RGBA32to16(p); + } + writePixel16SZ(x, y, p, gsfb->fbp, gsfb->fbw); + } else + if (ret == 3) { + if (gsfb->fbm) { + u32 fbm = gsfb->fbm | 0x8000; + p = (RGBA32to16(p) & (~fbm)) | (readPixel16SZ(x, y, gsfb->fbp, gsfb->fbw) & fbm); + } else { + p = (RGBA32to16(p) & ~0x8000) | (readPixel16SZ(x, y, gsfb->fbp, gsfb->fbw) & 0x8000); + } + writePixel16SZ(x, y, RGBA32to16(p), gsfb->fbp, gsfb->fbw); + } +} + +////////////////////////////////// +// drawPixelF + + +void SETprocPixelABE() { + procPixelABE = 0; +#if 0 + if (alpha->a == 0) { + if (alpha->b == 0) { + } else + if (alpha->b == 1) { + } else { + if (alpha->c == 0) { + if (alpha->d == 0) { + } else + if (alpha->d == 1) { + switch (gsfb->psm) { + case 0x0: + if (gs.pabe) { + if (gs.colclamp) { + procPixelABE = _procPixelABE32_A0B2C0D1_PABE_CC; + } else { + procPixelABE = _procPixelABE32_A0B2C0D1_PABE; + } + } else { + if (gs.colclamp) { + procPixelABE = _procPixelABE32_A0B2C0D1_CC; + } else { + procPixelABE = _procPixelABE32_A0B2C0D1; + } + } + break; + case 0x2: procPixelABE = _procPixelABE16_A0B2C0D1; break; + } + } + } else + if (alpha->c == 1) { + } else + if (alpha->c == 2) { + } + } + } else + if (alpha->a == 1) { + if (alpha->b == 0) { + } else + if (alpha->b == 1) { + } else { + if (alpha->c == 0) { + if (alpha->d == 0) { + } else + if (alpha->d == 1) { + } + } else + if (alpha->c == 1) { + } else + if (alpha->c == 2) { + if (alpha->d == 0) { +/* switch (gsfb->psm) { + case 0x0: + if (gs.pabe) { + if (gs.colclamp) { + procPixelABE = _procPixelABE32_A1B2C2D0_PABE_CC; + } else { + procPixelABE = _procPixelABE32_A1B2C2D0_PABE; + } + } else { + if (gs.colclamp) { + procPixelABE = _procPixelABE32_A1B2C2D0_CC; + } else { + procPixelABE = _procPixelABE32_A1B2C2D0; + } + } + break; + }*/ + } else + if (alpha->d == 1) { + } + } + } + } else { + } +#endif + if (procPixelABE == 0) { +// printf("ABE default: %d,%d,%d,%d\n", alpha->a, alpha->b, alpha->c, alpha->d); + switch (gsfb->psm) { + case 0x0: procPixelABE = _procPixelABE32; break; + case 0x1: procPixelABE = _procPixelABE24; break; + case 0x2: procPixelABE = _procPixelABE16; break; + case 0xa: procPixelABE = _procPixelABE16S; break; + case 0x30:procPixelABE = _procPixelABE32Z; break; + case 0x31:procPixelABE = _procPixelABE24Z; break; + case 0x32:procPixelABE = _procPixelABE16Z; break; + case 0x3a:procPixelABE = _procPixelABE16SZ; break; + default: + if (gsfb->psm) printf("SETprocPixelABE psm == %d!!\n", gsfb->psm); + drawPixel = _drawPixel32; + break; + } + } +} + +void SETdrawPixel() { + drawPixel = 0; + if (drawPixel == 0) { + switch (gsfb->psm) { + case 0x1: drawPixel = _drawPixel24; break; + case 0x2: drawPixel = _drawPixel16; break; + case 0xa: drawPixel = _drawPixel16S; break; + case 0x30:drawPixel = _drawPixel32Z; break; + case 0x31:drawPixel = _drawPixel24Z; break; + case 0x32:drawPixel = _drawPixel16Z; break; + case 0x3a:drawPixel = _drawPixel16SZ; break; + default: // PSMT32 + if (gsfb->psm) printf("SETdrawPixel psm == %d!!\n", gsfb->psm); + drawPixel = _drawPixel32; + break; + } + } + + if (prim->abe) { // alpha blending + SETprocPixelABE(); + } +} + +void SETdrawPixelF() { +/* drawPixelF = 0; + if (drawPixelF == 0) { + switch (gsfb->psm) { + case 0x1: drawPixelF = _drawPixel24F; break; + case 0x2: drawPixelF = _drawPixel16F; break; + case 0xa: drawPixelF = _drawPixel16SF; break; + default: // PSMT32 + if (gsfb->psm) printf("SETdrawPixel psm == %d!!\n", gsfb->psm); + drawPixelF = _drawPixel32F; + break; + } + } + + if (prim->abe) { // alpha blending + SETprocPixelABE(); + }*/ +} + +////////////////////////////////// +// drawPixelZ + + +// zmsk = 0 +void _drawPixel32_Z(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel32Z(x, y, z, zbuf->zbp, gsfb->fbw); + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 2: // write z only + writePixel32Z(x, y, z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 1 +void _drawPixel32_Zmsk(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 0 +void _drawPixel24_Z(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel24Z(x, y, z, zbuf->zbp, gsfb->fbw); + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 2: // write z only + writePixel24Z(x, y, z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 1 +void _drawPixel24_Zmsk(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 0 +void _drawPixel16_Z(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel16Z(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 2: // write z only + writePixel16Z(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 1 +void _drawPixel16_Zmsk(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 0 +void _drawPixel16S_Z(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel16SZ(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 2: // write z only + writePixel16SZ(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + +// zmsk = 1 +void _drawPixel16S_Zmsk(int x, int y, u32 p, u32 z) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixel(x, y, p); + break; + + case 1: // write p only + drawPixel(x, y, p); + break; + + case 3: // write rgb only + drawPixel(x, y, p); + break; + } +} + + +////////////////////////////////// +// drawPixelZF + + +// zmsk = 0 +void _drawPixel32_ZF(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel32Z(x, y, z, zbuf->zbp, gsfb->fbw); + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 2: // write z only + writePixel32Z(x, y, z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 1 +void _drawPixel32_ZFmsk(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 0 +void _drawPixel24_ZF(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel24Z(x, y, z, zbuf->zbp, gsfb->fbw); + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 2: // write z only + writePixel24Z(x, y, z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 1 +void _drawPixel24_ZFmsk(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 0 +void _drawPixel16_ZF(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel16Z(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 2: // write z only + writePixel16Z(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 1 +void _drawPixel16_ZFmsk(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 0 +void _drawPixel16S_FZ(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + writePixel16SZ(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 2: // write z only + writePixel16SZ(x, y, (u16)z, zbuf->zbp, gsfb->fbw); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + +// zmsk = 1 +void _drawPixel16S_FZmsk(int x, int y, u32 p, u32 z, u32 f) { + int ret; + + if (scissorTest(x, y)) return; + if (depthTest(x, y, z)) return; + + ret = alphaTest(p); + switch (ret) { + case 0: // write p and z + drawPixelF(x, y, p, f); + break; + + case 1: // write p only + drawPixelF(x, y, p, f); + break; + + case 3: // write rgb only + drawPixelF(x, y, p, f); + break; + } +} + + +u32 _readPixel32Z(int x, int y) { + return readPixel32Z(x, y, zbuf->zbp, gsfb->fbw); +} + +u32 _readPixel24Z(int x, int y) { + return readPixel24Z(x, y, zbuf->zbp, gsfb->fbw); +} + +u32 _readPixel16Z(int x, int y) { + return readPixel16Z(x, y, zbuf->zbp, gsfb->fbw); +} + +u32 _readPixel16SZ(int x, int y) { + return readPixel16SZ(x, y, zbuf->zbp, gsfb->fbw); +} + +void SETdrawPixelZ() { + SETdrawPixel(); + switch (zbuf->psm) { + case 0x1: // PSMZ24 + if (zbuf->zmsk == 0) { + drawPixelZ = _drawPixel24_Z; + } else { + drawPixelZ = _drawPixel24_Zmsk; + } + readPixelZ = _readPixel24Z; break; + case 0x2: // PSMZ16 + if (zbuf->zmsk == 0) { + drawPixelZ = _drawPixel16_Z; + } else { + drawPixelZ = _drawPixel16_Zmsk; + } + readPixelZ = _readPixel16Z; break; + case 0xa: // PSMZ16S + if (zbuf->zmsk == 0) { + drawPixelZ = _drawPixel16S_Z; + } else { + drawPixelZ = _drawPixel16S_Zmsk; + } + readPixelZ = _readPixel16SZ; break; + default: + if (zbuf->psm) printf("unknown PSMZ psm %x\n", zbuf->psm); + if (zbuf->zmsk == 0) { + drawPixelZ = _drawPixel32_Z; + } else { + drawPixelZ = _drawPixel32_Zmsk; + } + readPixelZ = _readPixel32Z; break; + } +} + +void SETdrawPixelZF() { + SETdrawPixelF(); + switch (zbuf->psm) { + case 0x1: // PSMZ24 + if (zbuf->zmsk == 0) { + drawPixelZF = _drawPixel24_ZF; + } else { + drawPixelZF = _drawPixel24_ZFmsk; + } + readPixelZ = _readPixel24Z; break; + case 0x2: // PSMZ16 + if (zbuf->zmsk == 0) { + drawPixelZF = _drawPixel16_ZF; + } else { + drawPixelZF = _drawPixel16_ZFmsk; + } + readPixelZ = _readPixel16Z; break; + case 0xa: // PSMZ16S + if (zbuf->zmsk == 0) { + drawPixelZF = _drawPixel16S_FZ; + } else { + drawPixelZF = _drawPixel16S_FZmsk; + } + readPixelZ = _readPixel16SZ; break; + default: + if (zbuf->psm) printf("unknown PSMZ psm %x\n", zbuf->psm); + if (zbuf->zmsk == 0) { + drawPixelZF = _drawPixel32_ZF; + } else { + drawPixelZF = _drawPixel32_ZFmsk; + } + readPixelZ = _readPixel32Z; break; + } +} + +int af, rf, gf, bf; /* Colour of vertex */ + +void colSetCol(u32 crgba) { + af = (crgba >> 24) & 0xFF; + rf = (crgba >> 16) & 0xFF; + gf = (crgba >> 8) & 0xFF; + bf = (crgba ) & 0xFF; +} + +u32 colModulate(u32 texcol) { + u32 at, rt, gt, bt; /* Colour of texture */ + + rt = (texcol >> 16) & 0xFF; + gt = (texcol >> 8) & 0xFF; + bt = texcol & 0xFF; /* Extract colours from texture */ + + rt = (rt * rf) >> 7; + gt = (gt * gf) >> 7; + bt = (bt * bf) >> 7; + if(rt > 0xFF) rt = 0xFF; + if(gt > 0xFF) gt = 0xFF; + if(bt > 0xFF) bt = 0xFF; + + if (tex0->tcc) { // RGBA + at = (texcol >> 24) & 0xFF; + at = (at * af) >> 7; /* Multiply by colour value */ + if(at > 0xFF) at = 0xFF; + } else { // RGB + at = af; + } + + return (at << 24) | (rt << 16) | (gt << 8) | bt; +} + +u32 colHighlight(u32 texcol) { + u32 at, rt, gt, bt; /* Colour of texture */ + + rt = (texcol >> 16) & 0xFF; + gt = (texcol >> 8) & 0xFF; + bt = texcol & 0xFF; /* Extract colours from texture */ + + rt = ((rt * rf) >> 7) + af; + gt = ((gt * gf) >> 7) + af; + bt = ((bt * bf) >> 7) + af; + if(rt > 0xFF) rt = 0xFF; + if(gt > 0xFF) gt = 0xFF; + if(bt > 0xFF) bt = 0xFF; + + if (tex0->tcc) { // RGBA + at = (texcol >> 24) & 0xFF; + at = (at * af) >> 7; /* Multiply by colour value */ + if(at > 0xFF) at = 0xFF; + } else { // RGB + at = af; + } + + return (at << 24) | (rt << 16) | (gt << 8) | bt; +} + +u32 colHighlight2(u32 texcol) { + u32 at, rt, gt, bt; /* Colour of texture */ + + rt = (texcol >> 16) & 0xFF; + gt = (texcol >> 8) & 0xFF; + bt = texcol & 0xFF; /* Extract colours from texture */ + + rt = ((rt * rf) >> 7) + af; + gt = ((gt * gf) >> 7) + af; + bt = ((bt * bf) >> 7) + af; + if(rt > 0xFF) rt = 0xFF; + if(gt > 0xFF) gt = 0xFF; + if(bt > 0xFF) bt = 0xFF; + + if (tex0->tcc) { // RGBA + at = (texcol >> 24) & 0xFF; + } else { // RGB + at = af; + } + + return (at << 24) | (rt << 16) | (gt << 8) | bt; +} + diff --git a/plugins/gs/GSsoft/Src/Color.h b/plugins/gs/GSsoft/Src/Color.h new file mode 100644 index 0000000..74b2db2 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Color.h @@ -0,0 +1,40 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __COLOR_H__ +#define __COLOR_H__ + +void (*drawPixel) (int, int, u32); +void SETdrawPixel(); + +void (*drawPixelF) (int, int, u32, u32); +void SETdrawPixelF(); + +void (*drawPixelZ) (int, int, u32, u32); +u32 (*readPixelZ) (int, int); +void SETdrawPixelZ(); + +void (*drawPixelZF) (int, int, u32, u32, u32); +void SETdrawPixelZF(); + +void colSetCol(u32 crgba); +u32 colModulate(u32 texcol); +u32 colHighlight(u32 texcol); +u32 colHighlight2(u32 texcol); + +#endif /* __COLOR_H__ */ diff --git a/plugins/gs/GSsoft/Src/Draw.c b/plugins/gs/GSsoft/Src/Draw.c new file mode 100644 index 0000000..e023c4a --- /dev/null +++ b/plugins/gs/GSsoft/Src/Draw.c @@ -0,0 +1,530 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Draw.h" +#include "Mem.h" +#include "Page.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +void (*_ScrBlit)(u8 *, int, int, int, Rect *, u32, u32, u32); +void (*_ScrBlitMerge)(u8 *, int, int, int); + + +//////////////////// +// 15bit + +void _ScrBlit32to15(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u32 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x0000f8) << 7) | /* 0x7c00 */ + ((c & 0x00f800) >> 6) | /* 0x03e0 */ + ((c & 0xf80000) >> 19); /* 0x001f */ + } + } +} + +void _ScrBlit16to15(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x001f) << 10) | /* 0x7c00 */ + ((c & 0x03e0) ) | /* 0x03e0 */ + ((c & 0x7c00) >> 10); /* 0x001f */ + } + } +} + +void _ScrBlit16Sto15(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x001f) << 10) | /* 0x7c00 */ + ((c & 0x03e0) ) | /* 0x03e0 */ + ((c & 0x7c00) >> 10); /* 0x001f */ + } + } +} + +void ScrBlit15(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 psm, u32 bp, u32 bw) { + switch (psm) { + case 0x2: _ScrBlit16to15(scr, dw, dh, sp, gsScr, bp, bw); break; + case 0xA: _ScrBlit16Sto15(scr, dw, dh, sp, gsScr, bp, bw); break; + default: _ScrBlit32to15(scr, dw, dh, sp, gsScr, bp, bw); break; + } +} + +//////////////////// +// 16bit + +void _ScrBlit32to16(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u32 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x0000f8) << 8) | /* 0xf800 */ + ((c & 0x00fc00) >> 5) | /* 0x07e0 */ + ((c & 0xf80000) >> 19); /* 0x001f */ + } + } +} + +void _ScrBlit16to16(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x001f) << 11) | /* 0xf800 */ + ((c & 0x03e0) << 1) | /* 0x07e0 */ + ((c & 0x7c00) >> 10); /* 0x001f */ + } + } +} + +void _ScrBlit16Sto16(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u16 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + *pscr++= ((c & 0x001f) << 11) | /* 0xf800 */ + ((c & 0x03e0) << 1) | /* 0x07e0 */ + ((c & 0x7c00) >> 10); /* 0x001f */ + } + } +} + +void ScrBlit16(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 psm, u32 bp, u32 bw) { + switch (psm) { + case 0x2: _ScrBlit16to16(scr, dw, dh, sp, gsScr, bp, bw); break; + case 0xA: _ScrBlit16Sto16(scr, dw, dh, sp, gsScr, bp, bw); break; + default: _ScrBlit32to16(scr, dw, dh, sp, gsScr, bp, bw); break; + } +} + +//////////////////// +// 32bit + +void _ScrBlit32to32(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u8 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u32 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + pscr[0] = (c >> 16) & 0xff; + pscr[1] = (c >> 8) & 0xff; + pscr[2] = c & 0xff; + pscr+=4; + } + } +} + +void _ScrBlit16to32(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u8 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + pscr[0] = (c >> 7) & 0xf8; + pscr[1] = (c >> 2) & 0xf8; + pscr[2] = (c << 3) & 0xf8; + pscr+=4; + } + } +} + +void _ScrBlit16Sto32(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 bp, u32 bw) { + u8 *pscr; + int x, y; + int xpos, xinc; + int ypos, yinc; + u16 c; + + xinc = (gsScr->w << 16) / dw; + yinc = (gsScr->h << 16) / dh; + + for (y=0, ypos=gsScr->y<<16; yx<<16; x>16, ypos>>16, bp, bw); + pscr[0] = (c >> 7) & 0xf8; + pscr[1] = (c >> 2) & 0xf8; + pscr[2] = (c << 3) & 0xf8; + pscr+=4; + } + } +} + +void ScrBlit32(u8 *scr, int dw, int dh, int sp, Rect *gsScr, u32 psm, u32 bp, u32 bw) { + switch (psm) { + case 0x2: _ScrBlit16to32(scr, dw, dh, sp, gsScr, bp, bw); break; + case 0xA: _ScrBlit16Sto32(scr, dw, dh, sp, gsScr, bp, bw); break; + default: _ScrBlit32to32(scr, dw, dh, sp, gsScr, bp, bw); break; + } +} + + +void ScrBlitMerge15(u8 *scr, int dw, int dh, int sp) { + u32 (*_readPixel1)(int x, int y, u32 bp, u32 bw); + u32 (*_readPixel2)(int x, int y, u32 bp, u32 bw); + u16 *pscr; + int x, y; + int xpos1, xinc1; + int ypos1, yinc1; + int xpos2, xinc2; + int ypos2, yinc2; + u32 alpha; + u32 c1, c2; + u32 r1,g1,b1; + u32 r2,g2,b2; + + switch (gs.DISPFB[0].psm) { + case 0x2: _readPixel1 = readPixel16to32; break; + case 0xA: _readPixel1 = readPixel16Sto32; break; + default: _readPixel1 = readPixel32; break; + } + switch (gs.DISPFB[1].psm) { + case 0x2: _readPixel2 = readPixel16to32; break; + case 0xA: _readPixel2 = readPixel16Sto32; break; + default: _readPixel2 = readPixel32; break; + } + + xinc1 = (gs.DISPLAY[0].w << 16) / dw; + yinc1 = (gs.DISPLAY[0].h << 16) / dh; + + ypos1 = gs.DISPLAY[0].y<<16; + + xinc2 = (gs.DISPLAY[1].w << 16) / dw; + yinc2 = (gs.DISPLAY[1].h << 16) / dh; + + ypos2 = gs.DISPLAY[1].y<<16; + +// if (gs.PMODE.alp) alpha = gs.PMODE.alp; + alpha = 0x80; + + for (y=0; y>16, ypos1>>16, gs.DISPFB[0].fbp, gs.DISPFB[0].fbw); + r1 = (c1 >> 16) & 0xff; + g1 = (c1 >> 8) & 0xff; + b1 = (c1 ) & 0xff; + c2 = _readPixel2(xpos2>>16, ypos2>>16, gs.DISPFB[1].fbp, gs.DISPFB[1].fbw); + r2 = (c2 >> 16) & 0xff; + g2 = (c2 >> 8) & 0xff; + b2 = (c2 ) & 0xff; + + r1 = ((r1 * alpha) + (r2 * (0xff - alpha))) / alpha; + g1 = ((g1 * alpha) + (g2 * (0xff - alpha))) / alpha; + b1 = ((b1 * alpha) + (b2 * (0xff - alpha))) / alpha; + if (r1 > 0xff) r1 = 0xff; + if (g1 > 0xff) g1 = 0xff; + if (b1 > 0xff) b1 = 0xff; + + *pscr++= ((b1 >> 3) << 10) | /* 0x7c00 */ + ((g1 >> 3) << 5) | /* 0x03e0 */ + ((r1 >> 3) ); /* 0x001f */ + xpos1+= xinc1; + xpos2+= xinc2; + } + ypos1+= yinc1; + ypos2+= yinc2; + } +} + +void ScrBlitMerge16(u8 *scr, int dw, int dh, int sp) { + u32 (*_readPixel1)(int x, int y, u32 bp, u32 bw); + u32 (*_readPixel2)(int x, int y, u32 bp, u32 bw); + u16 *pscr; + int x, y; + int xpos1, xinc1; + int ypos1, yinc1; + int xpos2, xinc2; + int ypos2, yinc2; + u32 alpha; + u32 c1, c2; + u32 r1,g1,b1; + u32 r2,g2,b2; + + switch (gs.DISPFB[0].psm) { + case 0x2: _readPixel1 = readPixel16to32; break; + case 0xA: _readPixel1 = readPixel16Sto32; break; + default: _readPixel1 = readPixel32; break; + } + switch (gs.DISPFB[1].psm) { + case 0x2: _readPixel2 = readPixel16to32; break; + case 0xA: _readPixel2 = readPixel16Sto32; break; + default: _readPixel2 = readPixel32; break; + } + + xinc1 = (gs.DISPLAY[0].w << 16) / dw; + yinc1 = (gs.DISPLAY[0].h << 16) / dh; + + ypos1 = gs.DISPLAY[0].y<<16; + + xinc2 = (gs.DISPLAY[1].w << 16) / dw; + yinc2 = (gs.DISPLAY[1].h << 16) / dh; + + ypos2 = gs.DISPLAY[1].y<<16; + +// if (gs.PMODE.alp) alpha = gs.PMODE.alp; + alpha = 0x80; + + for (y=0; y>16, ypos1>>16, gs.DISPFB[0].fbp, gs.DISPFB[0].fbw); + r1 = (c1 >> 16) & 0xff; + g1 = (c1 >> 8) & 0xff; + b1 = (c1 ) & 0xff; + c2 = _readPixel2(xpos2>>16, ypos2>>16, gs.DISPFB[1].fbp, gs.DISPFB[1].fbw); + r2 = (c2 >> 16) & 0xff; + g2 = (c2 >> 8) & 0xff; + b2 = (c2 ) & 0xff; + + r1 = ((r1 * alpha) + (r2 * (0xff - alpha))) / alpha; + g1 = ((g1 * alpha) + (g2 * (0xff - alpha))) / alpha; + b1 = ((b1 * alpha) + (b2 * (0xff - alpha))) / alpha; + if (r1 > 0xff) r1 = 0xff; + if (g1 > 0xff) g1 = 0xff; + if (b1 > 0xff) b1 = 0xff; + + *pscr++= ((b1 >> 3) << 11) | /* 0xf800 */ + ((g1 >> 2) << 5) | /* 0x07e0 */ + ((r1 >> 3) ); /* 0x001f */ + xpos1+= xinc1; + xpos2+= xinc2; + } + ypos1+= yinc1; + ypos2+= yinc2; + } +} + +void ScrBlitMerge32(u8 *scr, int dw, int dh, int sp) { + u32 (*_readPixel1)(int x, int y, u32 bp, u32 bw); + u32 (*_readPixel2)(int x, int y, u32 bp, u32 bw); + u8 *pscr; + int x, y; + int xpos1, xinc1; + int ypos1, yinc1; + int xpos2, xinc2; + int ypos2, yinc2; + u32 alpha; + u32 c1, c2; + u32 r1,g1,b1; + u32 r2,g2,b2; + + switch (gs.DISPFB[0].psm) { + case 0x2: _readPixel1 = readPixel16to32; break; + case 0xA: _readPixel1 = readPixel16Sto32; break; + default: _readPixel1 = readPixel32; break; + } + switch (gs.DISPFB[1].psm) { + case 0x2: _readPixel2 = readPixel16to32; break; + case 0xA: _readPixel2 = readPixel16Sto32; break; + default: _readPixel2 = readPixel32; break; + } + + xinc1 = (gs.DISPLAY[0].w << 16) / dw; + yinc1 = (gs.DISPLAY[0].h << 16) / dh; + + ypos1 = gs.DISPLAY[0].y<<16; + + xinc2 = (gs.DISPLAY[1].w << 16) / dw; + yinc2 = (gs.DISPLAY[1].h << 16) / dh; + + ypos2 = gs.DISPLAY[1].y<<16; + +// if (gs.PMODE.alp) alpha = gs.PMODE.alp; + alpha = 0x80; + + for (y=0; y>16, ypos1>>16, gs.DISPFB[0].fbp, gs.DISPFB[0].fbw); + r1 = (c1 >> 16) & 0xff; + g1 = (c1 >> 8) & 0xff; + b1 = (c1 ) & 0xff; + c2 = _readPixel2(xpos2>>16, ypos2>>16, gs.DISPFB[1].fbp, gs.DISPFB[1].fbw); + r2 = (c2 >> 16) & 0xff; + g2 = (c2 >> 8) & 0xff; + b2 = (c2 ) & 0xff; + + r1 = ((r1 * alpha) + (r2 * (0xff - alpha))) / alpha; + g1 = ((g1 * alpha) + (g2 * (0xff - alpha))) / alpha; + b1 = ((b1 * alpha) + (b2 * (0xff - alpha))) / alpha; + if (r1 > 0xff) r1 = 0xff; + if (g1 > 0xff) g1 = 0xff; + if (b1 > 0xff) b1 = 0xff; + + pscr[0] = r1; + pscr[1] = g1; + pscr[2] = b1; + pscr+=4; + xpos1+= xinc1; + xpos2+= xinc2; + } + ypos1+= yinc1; + ypos2+= yinc2; + } +} + + +void ScrBlit(SDL_Surface *dst, int y) { + Rect gsScr; + + if (showfullvram) { + if (gs.PMODE.en[0]) { + gsScr.x = 0; + gsScr.y = 0; + gsScr.w = gs.DISPFB[0].fbw; + gsScr.h = gs.DISPFB[0].fbh; + + _ScrBlit((u8*)dst->pixels + y * dst->pitch, dst->w, dst->h-y, dst->pitch, &gsScr, gs.DISPFB[0].psm, 0, gs.DISPFB[0].fbw); + } else + if (gs.PMODE.en[1]) { + gsScr.x = 0; + gsScr.y = 0; + gsScr.w = gs.DISPFB[1].fbw; + gsScr.h = gs.DISPFB[1].fbh; + + _ScrBlit((u8*)dst->pixels + y * dst->pitch, dst->w, dst->h-y, dst->pitch, &gsScr, gs.DISPFB[1].psm, 0, gs.DISPFB[1].fbw); + } + return; + } + + if (gs.PMODE.en[0] && gs.PMODE.en[1]) { + _ScrBlitMerge((u8*)dst->pixels + y * dst->pitch, dst->w, dst->h-y, dst->pitch); + return; + } + + if (gs.PMODE.en[0]) { + gsScr.x = gs.DISPLAY[0].x; + gsScr.y = gs.DISPLAY[0].y; + gsScr.w = gs.DISPLAY[0].w; + gsScr.h = gs.DISPLAY[0].h; + _ScrBlit((u8*)dst->pixels + y * dst->pitch, dst->w, dst->h-y, dst->pitch, &gsScr, gs.DISPFB[0].psm, gs.DISPFB[0].fbp, gs.DISPFB[0].fbw); + } + + if (gs.PMODE.en[1]) { + gsScr.x = gs.DISPLAY[1].x; + gsScr.y = gs.DISPLAY[1].y; + gsScr.w = gs.DISPLAY[1].w; + gsScr.h = gs.DISPLAY[1].h; + _ScrBlit((u8*)dst->pixels + y * dst->pitch, dst->w, dst->h-y, dst->pitch, &gsScr, gs.DISPFB[1].psm, gs.DISPFB[1].fbp, gs.DISPFB[1].fbw); + } +} + + +void SETScrBlit(int bpp) { + switch (bpp) { + case 15: + _ScrBlit = ScrBlit15; + _ScrBlitMerge = ScrBlitMerge15; + break; + case 16: + _ScrBlit = ScrBlit16; + _ScrBlitMerge = ScrBlitMerge16; + break; + case 32: + _ScrBlit = ScrBlit32; + _ScrBlitMerge = ScrBlitMerge32; + break; + } +} diff --git a/plugins/gs/GSsoft/Src/Draw.h b/plugins/gs/GSsoft/Src/Draw.h new file mode 100644 index 0000000..9c54f30 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Draw.h @@ -0,0 +1,36 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DRAW_H__ +#define __DRAW_H__ + +#include "GS.h" + +void SETScrBlit(int bpp); +void ScrBlit(SDL_Surface *dst, int y); + +#endif /* __DRAW_H__ */ + + + + + + + + + diff --git a/plugins/gs/GSsoft/Src/GS.c b/plugins/gs/GSsoft/Src/GS.c new file mode 100644 index 0000000..766add4 --- /dev/null +++ b/plugins/gs/GSsoft/Src/GS.c @@ -0,0 +1,825 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Rec.h" +#include "Page.h" +#include "Transfer.h" +#include "Cache.h" +#include "Regs.h" +#if defined(__i386__) || defined(__x86_64__) +#include "ix86.h" +#endif + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +char *codeclist[] = { "MPEG1", /*"DIVX", "MPEG2",*/ NULL }; +char *filterslist[] = { "Disabled", "Scale2x", NULL }; + + +const unsigned char version = PS2E_GS_VERSION; +const unsigned char revision = 1; // revision and build gives plugin version +const unsigned char build = 0; + +static char *libraryName = "GSsoft Plugin"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_GS; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +#ifdef __WIN32__ + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "GSsoftdx Msg", 0); +} + +#endif + +#ifdef GS_LOG +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.log || gsLog == NULL) return; + + va_start(list, fmt); + vfprintf(gsLog, fmt, list); + va_end(list); +} +#endif + +void gsSetCtxt(int ctxt) { + if (gs.ctxt == ctxt) return; + gs.ctxt = ctxt; + +#ifdef GS_LOG + GS_LOG("gsSetCtxt %d\n", ctxt); +#endif + offset = &gs._offset[ctxt]; + test = &gs._test[ctxt]; + scissor = &gs._scissor[ctxt]; + tex0 = &gs._tex0[ctxt]; + tex1 = &gs._tex1[ctxt]; + tex2 = &gs._tex2[ctxt]; + clamp = &gs._clamp[ctxt]; + miptbp0 = &gs._miptbp0[ctxt]; + miptbp1 = &gs._miptbp1[ctxt]; + gsfb = &gs._gsfb[ctxt]; + alpha = &gs._alpha[ctxt]; + zbuf = &gs._zbuf[ctxt]; + fba = &gs._fba[ctxt]; +/* fBuf = vRam + gsfb->fbp * 4; + fBufUS = (u16*)fBuf; + fBufUL = (u32*)fBuf; + zBuf = vRam + zbuf->zbp * 4; + zBufUS = (u16*)zBuf; + zBufUL = (u32*)zBuf; + tBuf = vRam + (tex0->tbp0 & ~0x1f) * 256; + tBufUS = (u16*)tBuf; + tBufUL = (u32*)tBuf; + cBuf = vRam + (tex0->cbp & ~0x1f) * 256; + cBufUS = (u16*)cBuf; + cBufUL = (u32*)cBuf;*/ +} + +void GSreset() { + dBuf = vRam; + dBufUL = vRamUL; + + memset(&gs, 0, sizeof(gs)); + + gs.DISPLAY[0].w = 640; + gs.DISPLAY[0].h = 480; + gs.DISPLAY[1].w = 640; + gs.DISPLAY[1].h = 480; + + gs.DISPFB[0].fbw = 640; + gs.DISPFB[0].fbh = (1024*1024) / gs.DISPFB[0].fbw; + gs.DISPFB[1].fbw = 640; + gs.DISPFB[1].fbh = (1024*1024) / gs.DISPFB[1].fbw; + + gs._gsfb[0].fbw = 640; + gs._gsfb[0].fbh = (1024*1024) / gs._gsfb[0].fbw; + gs._gsfb[1].fbw = 640; + gs._gsfb[1].fbh = (1024*1024) / gs._gsfb[1].fbw; + + gs._scissor[0].x1 = 639; + gs._scissor[0].y1 = 479; + gs._scissor[1].x1 = 639; + gs._scissor[1].y1 = 479; + gs.ctxt = -1; + + gsSetCtxt(0); + + gs.prac = 1; + prim = &gs._prim[0]; + gs.primC = 0; + + gs._tex0[0].tbw = 64; + gs._tex0[1].tbw = 64; + + gs.CSRr = 0x55190000; +} + +void *_align16(void *ptr) { + return (void*)(((uptr)ptr+0x10) & ~0xf); +} + +s32 CALLBACK GSinit() { +#ifdef GS_LOG + gsLog = fopen("logs/gsLog.txt", "w"); + if (gsLog) setvbuf(gsLog, NULL, _IONBF, 0); + GS_LOG("GSinit\n"); +#endif + + _vRam = (u8*)malloc(4*1024*1024); vRam = _align16(_vRam); + if (vRam == NULL) return -1; + + vRamUS = (u16*)vRam; + vRamUL = (u32*)vRam; + + GSreset(); + norender = 0; +#ifdef GS_LOG + GS_LOG("GSinit ok\n"); +#endif + + return 0; +} + +void CALLBACK GSshutdown() { + free(_vRam); +#ifdef GS_LOG + fclose(gsLog); +#endif +} + +s32 CALLBACK GSopen(void *pDsp, char *Title) { + s32 dsp; + +#ifdef GS_LOG + GS_LOG("GSopen\n"); +#endif + + LoadConfig(); + + strcpy(GStitle, Title); + + dsp = DXopen(); + if (dsp == 0) return -1; + *(s32*)pDsp = dsp; + + if (conf.record) recOpen(); + if (conf.cache) if (CacheInit() == -1) return -1; + + DXsetGSmode(640, gs.SYNCV.vfp & 1 ? gs.SYNCV.vdp : gs.SYNCV.vdp/2); + +#ifdef GS_LOG + GS_LOG("GSopen ok\n"); +#endif + + return 0; +} + +void CALLBACK GSclose() { + DXclose(); + + if (conf.record) recClose(); + if (conf.cache) CacheShutdown(); + +#ifdef __WIN32__ + DestroyWindow(GShwnd); +#endif +} + +void CALLBACK GSirqCallback(void (*callback)()) { + GSirq = callback; +} + +void CALLBACK GSmakeSnapshot(char *path) { + FILE *bmpfile; + char filename[256]; + unsigned char header[0x36]; + long size; + unsigned char line[1024*3]; + int w,h; + short i,j; + unsigned char empty[2]={0,0}; + u32 color; + u32 snapshotnr = 0; + +// w = dispfb->fbw; +// h = dispfb->fbh - 20; + size = w*h*3 + 0x38; + + // fill in proper values for BMP + + // hardcoded BMP header + memset(header,0,0x36); + header[0]='B'; + header[1]='M'; + header[2]=size&0xff; + header[3]=(size>>8)&0xff; + header[4]=(size>>16)&0xff; + header[5]=(size>>24)&0xff; + header[0x0a]=0x36; + header[0x0e]=0x28; + header[0x12]=w%256; + header[0x13]=w/256; + header[0x16]=h%256; + header[0x17]=h/256; + header[0x1a]=0x01; + header[0x1c]=0x18; + header[0x26]=0x12; + header[0x27]=0x0B; + header[0x2A]=0x12; + header[0x2B]=0x0B; + + // increment snapshot value & try to get filename + for (;;) { + snapshotnr++; + + sprintf(filename,"%ssnap%03ld.bmp", path, snapshotnr); + + bmpfile=fopen(filename,"rb"); + if (bmpfile == NULL) break; + fclose(bmpfile); + } + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) + return; + + fwrite(header,0x36,1,bmpfile); + for(i=h-1;i>=0;i--) { + for(j=0;jfbw); + line[j*3+2]=(color )&0xff; + line[j*3+1]=(color>> 8)&0xff; + line[j*3+0]=(color>>16)&0xff; + } + fwrite(line,w*3,1,bmpfile); + } + fwrite(empty,0x2,1,bmpfile); + fclose(bmpfile); +} + +void CALLBACK GSvsync() { +#ifdef GS_LOG + GS_LOG("\nGSvsync\n\n"); +#endif + gs.interlace = 1 - gs.interlace; + + DXupdate(); + + ppf = 0; + bpf = 0; +} + +#define _FBmoveImage(spsm, dpsm) { \ + int x, y; \ + u32 pixel; \ + if (s->x < d->x) { \ + for(y=0; y=0; x--) { \ + pixel = readPixel##spsm(s->x + x, s->y + y, gs.srcbuf.bp, gs.srcbuf.bw); \ + writePixel##dpsm(d->x + x, d->y + y, pixel, gs.dstbuf.bp, gs.dstbuf.bw); \ + } \ + } \ + } else { \ + for(y=0; yx + x, s->y + y, gs.srcbuf.bp, gs.srcbuf.bw); \ + writePixel##dpsm(d->x + x, d->y + y, pixel, gs.dstbuf.bp, gs.dstbuf.bw); \ + } \ + } \ + } \ +} + +#define __FBmoveImage(bpp) \ +void FBmoveImage##bpp##to32(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 32); } \ +void FBmoveImage##bpp##to24(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 24); } \ +void FBmoveImage##bpp##to16(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 16); } \ +void FBmoveImage##bpp##to16S(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 16S); } \ +void FBmoveImage##bpp##to8(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 8); } \ +void FBmoveImage##bpp##to4(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 4); } \ +void FBmoveImage##bpp##to8H(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 8H); } \ +void FBmoveImage##bpp##to4HL(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 4HL); } \ +void FBmoveImage##bpp##to4HH(Point *s, Point *d, int w, int h) { _FBmoveImage(bpp, 4HH); } + +__FBmoveImage(32); +__FBmoveImage(24); +__FBmoveImage(16); +__FBmoveImage(16S); +__FBmoveImage(8); +__FBmoveImage(4); +__FBmoveImage(8H); +__FBmoveImage(4HL); +__FBmoveImage(4HH); + +#define _FBmoveImageTO(bpp) \ + switch (gs.srcbuf.psm) { \ + case 0x0: FBmoveImage32to##bpp(&s, &d, w, h); return; \ + case 0x1: FBmoveImage24to##bpp(&s, &d, w, h); return; \ + case 0x2: FBmoveImage16to##bpp(&s, &d, w, h); return; \ + case 0xA: FBmoveImage16to##bpp(&s, &d, w, h); return; \ + case 0x13: FBmoveImage8to##bpp(&s, &d, w, h); return; \ + case 0x14: FBmoveImage4to##bpp(&s, &d, w, h); return; \ + case 0x1B: FBmoveImage8Hto##bpp(&s, &d, w, h); return; \ + case 0x24: FBmoveImage4HLto##bpp(&s, &d, w, h); return; \ + case 0x2C: FBmoveImage4HHto##bpp(&s, &d, w, h); return; \ + } + +void FBmoveImage() { + Point s, d; + int sw, sh, dw, dh; + int w, h; + + s.x = gs.trxpos.sx; + s.y = gs.trxpos.sy; + d.x = gs.trxpos.dx; + d.y = gs.trxpos.dy; + sw = dw = gs.imageW; + sh = dh = gs.imageH; + + if (d.x >= gs.dstbuf.bw || d.y >= gs.dstbuf.bh) return; + if (s.x >= gs.srcbuf.bw || s.y >= gs.srcbuf.bh) return; + + if ((d.x + dw) < 0 || (d.y + dh) < 0) return; + if ((s.x + sw) < 0 || (s.y + sh) < 0) return; + + if (d.x < 0) { dw-= -d.x; d.x = 0; } + if (d.y < 0) { dh-= -d.y; d.y = 0; } + + if (s.x < 0) { sw-= -s.x; s.x = 0; } + if (s.y < 0) { sh-= -s.y; s.y = 0; } + + if ((d.x + dw) > gs.dstbuf.bw) dw = gs.dstbuf.bw; + if ((d.y + dh) > gs.dstbuf.bh) dh = gs.dstbuf.bh; + + if ((s.x + sw) > gs.srcbuf.bw) sw = gs.srcbuf.bw; + if ((s.y + sh) > gs.srcbuf.bh) sh = gs.srcbuf.bh; + + w = min(dw, sw); + h = min(dh, sh); + + switch (gs.dstbuf.psm) { + case 0x0: _FBmoveImageTO(32); break; + case 0x1: _FBmoveImageTO(24); break; + case 0x2: _FBmoveImageTO(16); break; + case 0xA: _FBmoveImageTO(16S); break; + case 0x13: _FBmoveImageTO(8); break; + case 0x14: _FBmoveImageTO(4); break; + case 0x1B: _FBmoveImageTO(8H); break; + case 0x24: _FBmoveImageTO(4HL); break; + case 0x2C: _FBmoveImageTO(4HH); break; + } + + printf("invalid FBmoveImage psm configuraton: %x to %x\n", gs.dstbuf.psm, gs.srcbuf.psm); +} + +u32 primP[2]; + +void GIFtag(pathInfo *path, u32 *data) { + path->tag.nloop = data[0] & 0x7fff; + path->tag.eop = (data[0] >> 15) & 0x1; + path->tag.pre = (data[1] >> 14) & 0x1; + path->tag.prim = (data[1] >> 15) & 0x7ff; + path->tag.flg = (data[1] >> 26) & 0x3; + path->tag.nreg = data[1] >> 28; + if (path->tag.nreg == 0) path->tag.nreg = 16; + +#ifdef GS_LOG + GS_LOG("GIFtag: %8.8lx_%8.8lx_%8.8lx_%8.8lx: EOP=%d, NLOOP=%x, FLG=%x, NREG=%d, PRE=%d\n", + data[3], data[2], data[1], data[0], + path->tag.eop, path->tag.nloop, path->tag.flg, path->tag.nreg, path->tag.pre); +#endif + + switch (path->tag.flg) { + case 0x0: + gs.regs = *(u64 *)(data+2); + gs.regn = 0; + path->mode = 1; + if (path->tag.pre) { + primP[0] = path->tag.prim; + primP[1] = 0; + + GSwrite(primP, 0); + } + break; + + case 0x1: + gs.regs = *(u64 *)(data+2); + gs.regn = 0; + path->mode = 2; + break; + + case 0x3: + case 0x2: +// if (gs.dstbuf.bw == 0) printf("gs.dstbuf == 0!!!\n"); + if (gs.imageTransfer == 0x2) { +/*#ifdef GS_LOG + GS_LOG("moveImage %dx%d %dx%d %dx%d (dir=%d)\n", + gs.trxpos.sx, gs.trxpos.sy, gs.trxpos.dx, gs.trxpos.dy, gs.imageW, gs.imageH, gs.trxpos.dir); +#endif + FBmoveImage();*/ + break; + } + path->mode = 3; +#ifdef GS_LOG + GS_LOG("imageTransfer size %lx, %dx%d %dx%d (psm=%x, bp=%x)\n", + path->tag.nloop, gs.trxpos.dx, gs.trxpos.dy, gs.imageW, gs.imageH, gs.dstbuf.psm, gs.dstbuf.bp); +#endif + break; + } +} + + +void GIFprocessReg(u32 *data, int reg) { + u32 out[2]; +// GS_LOG("GIFprocessReg %d %8.8x_%8.8x_%8.8x_%8.8x\n", reg, data[3], data[2], data[1], data[0]); + + switch (reg) { + case 0x0: // prim + out[0] = data[0]; + GSwrite(out, 0x0); + break; + + case 0x1: // rgbaq + out[0] = (data[0] & 0xff) | + ((data[1] & 0xff) << 8) | + ((data[2] & 0xff) << 16) | + ((data[3] & 0xff) << 24); + out[1] = gs.q; + GSwrite(out, 0x1); + break; + + case 0x2: // st + GSwrite(data, 0x2); + out[0] = gs.rgba; + out[1] = data[2]; + GSwrite(out, 0x1); + break; + + case 0x3: // uv + out[0] = (data[0] & 0x7fff) | + ((data[1] & 0x7fff) << 16); + GSwrite(out, 0x3); + break; + + case 0x4: // xyzf2 + out[0] = (data[0] & 0xffff) | + ((data[1] & 0xffff) << 16); + out[1] = ((data[2] >> 4) & 0xffffff) | + ((data[3] & 0xff0) << 20); + if ((data[3] >> 15) & 0x1) + GSwrite(out, 0xc); + else GSwrite(out, 0x4); + break; + + case 0x5: //xyz2 + out[0] = (data[0] & 0xffff) | + ((data[1] & 0xffff) << 16); + out[1] = data[2]; + if ((data[3] >> 15) & 0x1) + GSwrite(out, 0xd); + else GSwrite(out, 0x5); + break; + + case 0xe: // ad + GSwrite(data, data[2] & 0xff); + break; + + case 0xf: // nop + break; + + default: +#ifdef GS_LOG + GS_LOG("UNHANDLED GIFprocessReg %d %8.8x_%8.8x_%8.8x_%8.8x\n", reg, data[3], data[2], data[1], data[0]); +// GS_LOG("UNHANDLED %x!!!\n",reg); +#endif +// printf("UNHANDLED GIFprocessReg %d %8.8x_%8.8x_%8.8x_%8.8x\n", reg, data[3], data[2], data[1], data[0]); + GSwrite(data, reg); + break; + } +} + +void _GSgifPacket(pathInfo *path, u32 *pMem) { // 128bit + int reg = (int)((gs.regs >> (gs.regn*4)) & 0xf); + + GIFprocessReg(pMem, reg); + gs.regn++; + if (path->tag.nreg == gs.regn) { + gs.regn = 0; + path->tag.nloop--; + } +} + +void _GSgifRegList(pathInfo *path, u32 *pMem) { // 64bit + int reg; + + reg = (int)((gs.regs >> (gs.regn*4)) & 0xf); + GSwrite(pMem, reg); + gs.regn++; + if (path->tag.nreg == gs.regn) { + gs.regn = 0; + path->tag.nloop--; + } +} + +void _GSgifTransfer(pathInfo *path, u32 *pMem, u32 size) { + + while (size > 0) { + switch (path->mode) { + case 0: /* GIF TAG */ +/* if (path->tag.eop == 1) { + path->tag.eop = 0; + return; + }*/ + GIFtag(path, pMem); pMem+= 4; size--; + break; + + case 1: /* GIF PACKET */ + while (size > 0 && path->tag.nloop > 0) { + _GSgifPacket(path, pMem); + pMem+= 4; size--; + } + if (path->tag.nloop == 0 && + path->mode == 1) path->mode = 0; + break; + + case 2: /* GIF REGLIST */ + size*= 2; + while (size > 0 && path->tag.nloop > 0) { + _GSgifRegList(path, pMem); + pMem+= 2; size--; + } + if (size & 0x1) pMem+= 2; + size/= 2; + if (path->tag.nloop == 0 && + path->mode == 2) path->mode = 0; + break; + + case 3: /* GIF IMAGE */ + if (size < path->tag.nloop) { + FBtransferImage(pMem, size); + path->tag.nloop-= size; + return; + } else { + FBtransferImage(pMem, path->tag.nloop); + pMem+= path->tag.nloop*4; size-= path->tag.nloop; + path->tag.nloop = 0; path->mode = 0; + } + break; + + case 4: /* GIF IMAGE (FROM VRAM) */ +// if (size < path->tag.nloop) { + FBtransferImageSrc(pMem, size); + pMem+= size*4; path->tag.nloop-= size; + size = 0; path->mode = 0; +/* } else { + FBtransferImageSrc(pMem, path->tag.nloop); + pMem+= path->tag.nloop*4; size-= path->tag.nloop; + path->tag.nloop = 0; path->mode = 0; + }*/ + break; + } + } +} + +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) { +#if defined(__i386__) || defined(__x86_64__) + u64 tick; + + tick = GetCPUTick(); +#endif + +#ifdef GS_LOG + GS_LOG("GSgifTransfer2 size = %lx (mode %d, gs.path2.tag.nloop = %d)\n", size, gs.path2.mode, gs.path2.tag.nloop); +#endif + + _GSgifTransfer(&gs.path2, pMem, size); + +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif +} + +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) { +#if defined(__i386__) || defined(__x86_64__) + u64 tick; + + tick = GetCPUTick(); +#endif + +#ifdef GS_LOG + GS_LOG("GSgifTransfer3 size = %lx (mode %d, gs.path3.tag.nloop = %d)\n", size, gs.path3.mode, gs.path3.tag.nloop); +#endif + + _GSgifTransfer(&gs.path3, pMem, size); + +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif +} + +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) { + u32 *data; + pathInfo *path = &gs.path1; +#if defined(__i386__) || defined(__x86_64__) + u64 tick; + + tick = GetCPUTick(); +#endif + + +#ifdef GS_LOG + GS_LOG("GSgifTransfer1 0x%x (mode %d)\n", addr, path->mode); +#endif + + path->tag.eop = 0; + path->mode = 0; + for (;;) { + data = ((u8*)pMem)+(addr&0x3fff); + switch (path->mode) { + case 0: /* GIF TAG */ + if (path->tag.eop == 1) { /*if (addr > 0x4000) printf("meh %x\n", addr);*/ path->mode = 0; return; } + GIFtag(&gs.path1, data); addr+= 4*4; + if (path->tag.nloop == 0) { /*if (addr > 0x4000) printf("meh %x\n", addr);*/ path->mode = 0; return; } + break; + + case 1: /* GIF PACKET */ + _GSgifPacket(&gs.path1, data); + addr+= 4*4; + if (path->tag.nloop == 0 && + path->mode == 1) path->mode = 0; + break; + + case 2: /* GIF REGLIST */ + _GSgifRegList(&gs.path1, data); + addr+= 2*4; + if (path->tag.nloop == 0 && + path->mode == 2) { + if (addr & 2) addr+= 2*4; + path->mode = 0; + } + break; + + case 3: /* GIF IMAGE */ + FBtransferImage(pMem, 1); + addr+= 4*4; path->tag.nloop-= 1; + if (path->tag.nloop == 0) path->mode = 0; + break; + } + } +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif +} + +void CALLBACK GSreadFIFO(u64 *pMem) { +#if defined(__i386__) || defined(__x86_64__) + u64 tick; + + tick = GetCPUTick(); +#endif + +#ifdef GS_LOG + GS_LOG("GSreadFIFO\n"); +#endif + + FBtransferImageSrc(pMem, 1); + +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif +} + +#if 0 +void CALLBACK GSgifTransfer64(u32 *pMem) { +#ifdef GS_LOG + GS_LOG("GSgifTransfer64 (mode %d)\n", gs.gifMode); +#endif + GS_LOG("GSgifTransfer64 %8.8x+%8.8x\n", pMem[1], pMem[0]); + + switch (gs.gifMode) { + case 0: /* GIF TAG */ + printf("GIFTAG over Transfer64!!\n"); +// GIFtag(pMem); pMem+= 4; size--; + break; + + case 1: /* GIF PACKET */ + if (gs.buffsize == 1) { + gs.buffsize = 0; + memcpy(&gs.buff[1], pMem, 2*4); + _GSgifPacket((u32*)gs.buff); + } else { + gs.buffsize = 1; + memcpy(&gs.buff[0], pMem, 2*4); + } + break; + + case 2: /* GIF REGLIST */ + _GSgifRegList(pMem); + break; + + case 3: /* GIF IMAGE */ +/* if (size < gs.gtag.nloop) { + FBtransferImage(pMem, size); + gs.gtag.nloop-= size; + return; + } else { + FBtransferImage(pMem, gs.gtag.nloop); + pMem+= gs.gtag.nloop*4; size-= gs.gtag.nloop; + gs.gtag.nloop = 0; gs.gifMode = 0; + } +*/ break; + + case 4: /* GIF IMAGE (FROM VRAM) */ +// if (size < gs.gtag.nloop) { +/* FBtransferImageSrc(pMem, size); + pMem+= size*4; gs.gtag.nloop-= size; + size = 0; gs.gifMode = 0;*/ +/* } else { + FBtransferImageSrc(pMem, gs.gtag.nloop); + pMem+= gs.gtag.nloop*4; size-= gs.gtag.nloop; + gs.gtag.nloop = 0; gs.gifMode = 0; + }*/ + break; + } +} +#endif + +typedef struct { + u8 id[32]; + u8 vRam[4*1024*1024]; + GSinternal gs; +} GSfreezeData; + +s32 CALLBACK GSfreeze(int mode, freezeData *data) { + GSfreezeData *gsd; + + if (mode == FREEZE_LOAD) { + gsd = (GSfreezeData*)data->data; + if (data->size != sizeof(GSfreezeData)) { + SysMessage("GSsoft: freeze data size incorrect, %d != %d\n", data->size, sizeof(GSfreezeData)); + return 0; +// return -1; + } + if (strcmp(gsd->id, libraryName)) { + SysMessage("GSsoft: freeze data incorrect plugin\n"); + return -1; + } + memcpy(vRam, gsd->vRam, 4*1024*1024); + memcpy(&gs, &gsd->gs, sizeof(GSinternal)); + } else + if (mode == FREEZE_SAVE) { + data->size = sizeof(GSfreezeData); + gsd = (GSfreezeData*)data->data; + strcpy(gsd->id, libraryName); + memcpy(gsd->vRam, vRam, 4*1024*1024); + memcpy(&gsd->gs, &gs, sizeof(GSinternal)); + } + if (mode == FREEZE_SIZE) { + data->size = sizeof(GSfreezeData); + } + + return 0; +} + diff --git a/plugins/gs/GSsoft/Src/GS.h b/plugins/gs/GSsoft/Src/GS.h new file mode 100644 index 0000000..38fd0a3 --- /dev/null +++ b/plugins/gs/GSsoft/Src/GS.h @@ -0,0 +1,575 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +#include +#include + +#define GSdefs +#include "PS2Edefs.h" + +#ifdef __WIN32__ + +#include +#include + +HWND GShwnd; + +#else + +#include +#include +#include +#include + +#define __inline inline + +typedef int BOOL; + +//#define TRUE 1 +//#define FALSE 0 + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +#endif + +///////////////////// + +#ifndef _RELEASE +#define GS_LOG __Log +#endif + +char GStitle[256]; + +typedef struct { + int x, y, w, h; +} Rect; + +typedef struct { + int x, y; +} Point; + +typedef struct { + int x0, y0; + int x1, y1; +} Rect2; + +typedef struct { + int x, y, c; +} PointC; + +typedef struct { + int width; + int height; + int bpp; +} DXmode; + +typedef struct { + DXmode fmode; + DXmode wmode; + int fullscreen; + int fps; + int frameskip; + int record; + int cache; + int cachesize; + int codec; + int filter; +#ifdef GS_LOG + u32 log; +#endif + int dumptexts; +} GSconf; + +typedef struct { + int x, y, f; + u32 z; + int u, v; + u32 s, t, q; + u32 rgba; +} Vertex; + +DXmode modes[64]; +DXmode *cmode; +GSconf conf; +int norender; +int wireframe; +int showfullvram; +int fpspos; +int fpspress; +int ppf; +int bpf; +u64 gsticks; + +u8 *vRam; // Video Ram +u16 *vRamUS; +u32 *vRamUL; +u8 *_vRam; + +u8 *fBuf; // Frame Buffer +u16 *fBufUS; +u32 *fBufUL; + +u8 *dBuf; // Display Buffer +u16 *dBufUS; +u32 *dBufUL; + +u8 *zBuf; // Z Buffer +u16 *zBufUS; +u32 *zBufUL; + +u8 *iBuf; // Image Buffer +u16 *iBufUS; +u32 *iBufUL; + +u8 *tBuf; // Texture Buffer +u16 *tBufUS; +u32 *tBufUL; + +u8 *cBuf; // Clut Buffer +u16 *cBufUS; +u32 *cBufUL; + +extern char *codeclist[]; +extern char *filterslist[]; + +typedef struct { + int n; + int x, y; +} Block; + +typedef struct { + int nloop; + int eop; + int flg; + int nreg; + int prim; + int pre; +} tagInfo; + +typedef union { + s64 SD; + u64 UD; + s32 SL[2]; + u32 UL[2]; + s16 SS[4]; + u16 US[4]; + s8 SC[8]; + u8 UC[8]; +} reg64; + +/* privileged regs structs */ + + +typedef struct { + u32 fbp; + int fbw; + int fbh; + int psm; + int dbx; + int dby; +} dispfbInfo; + +typedef struct { + int inter; + int ffmd; + int dpms; +} smode2Info; + +typedef struct { + int rc; + int lc; + int t1248; + int slck; + int cmod; + int ex; + int prst; + int sint; + int xpck; + int pck2; + int spml; + int gcont; + int phs; + int pvs; + int pehs; + int pevs; + int clksel; + int nvck; + int slck2; + int vcksel; + int vhp; +} smode1Info; + +typedef struct { + int hfp; + int fbp; + int hseq; + int hsvs; + int hs; +} synch1Info; + +typedef struct { + int hb; + int hf; +} synch2Info; + +typedef struct { + int vfp; + int vfpe; + int vbp; + int vbpe; + int vdp; + int vs; +} syncvInfo; + +typedef struct { + int en[2]; + int crtmd; + int mmod; + int amod; + int slbg; + u32 alp; +} pmodeInfo; + +typedef struct { + u32 exbp; + u32 exbw; + int fbin; + int wffmd; + int emoda; + int emodc; + int wdx; + int wdy; +} extbufInfo; + +typedef struct { + u32 sigid; + u32 lblid; +} siglblidInfo; + +/* general purpose regs structs */ + +typedef struct { + int fbp; + int fbw; + int fbh; + int psm; + int fbm; +} frameInfo; + +frameInfo *gsfb; +Point *offset; +Rect2 *scissor; + +typedef struct { + int prim; + int iip; + int tme; + int fge; + int abe; + int aa1; + int fst; + int ctxt; + int fix; +} primInfo; + +primInfo *prim; + +typedef struct { + int ate; + int atst; + u32 aref; + int afail; + int date; + int datm; + int zte; + int ztst; +} pixTest; + +pixTest *test; + +#define ZTST_NEVER 0 +#define ZTST_ALWAYS 1 +#define ZTST_GEQUAL 2 +#define ZTST_GREATER 3 + +#define ATST_NEVER 0 +#define ATST_ALWAYS 1 +#define ATST_LESS 2 +#define ATST_LEQUAL 3 +#define ATST_EQUAL 4 +#define ATST_GEQUAL 5 +#define ATST_GREATER 6 +#define ATST_NOTEQUAL 7 + +#define AFAIL_KEEP 0 +#define AFAIL_FB_ONLY 1 +#define AFAIL_ZB_ONLY 2 +#define AFAIL_RGB_ONLY 3 + + +typedef struct { + int bp; + int bw; + int bh; + int psm; +} bufInfo; + +typedef struct { + int tbp0; + int tbw; + int psm; + int tw, th; + int tcc; + int tfx; + int cbp; + int cpsm; + int csm; +} tex0Info; + +tex0Info *tex0; + +#define TEX_MODULATE 0 +#define TEX_DECAL 1 +#define TEX_HIGHLIGHT 2 +#define TEX_HIGHLIGHT2 3 + +typedef struct { + int lcm; + int mxl; + int mmag; + int mmin; + int mtba; + int l; + int k; +} tex1Info; + +tex1Info *tex1; + +typedef struct { + int psm; + int cbp; + int cpsm; + int csm; + int csa; + int cld; +} tex2Info; + +tex2Info *tex2; + +typedef struct { + int u, v; +} uvInfo; + +typedef struct { + int s, t; +} stInfo; + +typedef struct { + int wms; + int wmt; + int minu; + int maxu; + int minv; + int maxv; +} clampInfo; + +clampInfo *clamp; + +typedef struct { + int cbw; + int cou; + int cov; +} clutInfo; + +typedef struct { + int tbp[3]; + int tbw[3]; +} miptbpInfo; + +miptbpInfo *miptbp0; +miptbpInfo *miptbp1; + +typedef struct { + int ta[2]; + int aem; +} texaInfo; + +typedef struct { + int sx; + int sy; + int dx; + int dy; + int dir; +} trxposInfo; + +typedef struct { + int a, b, c, d; + int fix; +} alphaInfo; + +alphaInfo *alpha; + +typedef struct { + int zbp; + int psm; + int zmsk; +} zbufInfo; + +zbufInfo *zbuf; + +typedef struct { + int fba; +} fbaInfo; + +fbaInfo *fba; + +typedef struct { + int mode; + tagInfo tag; +} pathInfo; + +typedef struct { + Vertex gsvertex[3]; + u32 rgba; + u32 q; + int primC; + int psm; + int prac; + int dthe; + int colclamp; + int fogf; + int fogcol; + int smask; + int pabe; + u64 regs; + int regn; + u64 buff[2]; + int buffsize; + int ctxt; + + pmodeInfo PMODE; + smode1Info SMODE1; + smode2Info SMODE2; + u64 SRFSH; + synch1Info SYNCH1; + synch2Info SYNCH2; + syncvInfo SYNCV; + dispfbInfo DISPFB[2]; + Rect DISPLAY[2]; + extbufInfo EXTBUF; + Rect EXTDATA; + u32 EXTWRITE; + u32 BGCOLOR; + u32 CSRr; + u32 CSRw; + u32 IMR; + u32 BUSDIR; + siglblidInfo SIGLBLID; + + frameInfo _gsfb[2]; + Point _offset[2]; + Rect2 _scissor[2]; + primInfo _prim[2]; + pixTest _test[2]; + bufInfo srcbuf; + bufInfo dstbuf; + tex0Info _tex0[2]; + tex1Info _tex1[2]; + tex2Info _tex2[2]; + uvInfo uv; + stInfo st; + clampInfo _clamp[2]; + clutInfo clut; + miptbpInfo _miptbp0[2]; + miptbpInfo _miptbp1[2]; + texaInfo texa; + trxposInfo trxpos; + alphaInfo _alpha[2]; + zbufInfo _zbuf[2]; + fbaInfo _fba[2]; + + int imageTransfer; + int imageX, imageY, imageW, imageH; + + pathInfo path1; + pathInfo path2; + pathInfo path3; + + int interlace; +} GSinternal; + +GSinternal gs; + + +FILE *gsLog; + +#ifdef GS_LOG +#define RDWR_LOG /*if (conf.log & 0x00000001)*/ __Log +#define TRAN_LOG /*if (conf.log & 0x00000002)*/ __Log +#define PREG_LOG /*if (conf.log & 0x00000004)*/ __Log +#define GREG_LOG /*if (conf.log & 0x00000008)*/ __Log +#define PRIM_LOG /*if (conf.log & 0x00000010)*/ __Log +#define DRAW_LOG /*if (conf.log & 0x00000020)*/ __Log +#define WARN_LOG /*if (conf.log & 0x00000040)*/ __Log +#endif + +void __Log(char *fmt, ...); + +void LoadConfig(); +void SaveConfig(); + +s32 DXopen(); +void DXclose(); +int DXsetGSmode(int w, int h); +void DXupdate(); +int DXgetModes(); +int DXgetDrvs(); +void DXclearScr(); + +void GSreset(); + +void (*GSirq)(); + +void *_align16(void *ptr); +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void SysMessage(char *fmt, ...); + +#define RGBA32to16(c) \ + (u16)((((c) & 0x000000f8) >> 3) | \ + (((c) & 0x0000f800) >> 6) | \ + (((c) & 0x00f80000) >> 9) | \ + (((c) & 0x80000000) >> 16)) \ + +#define RGBA16to32(c) \ + (((c) & 0x001f) << 3) | \ + (((c) & 0x03e0) << 6) | \ + (((c) & 0x7c00) << 9) | \ + (((c) & 0x8000) << 16) \ + +void gsSetCtxt(int ctxt); +void FBmoveImage(); +u32 TextureSizeGS(int width, int height, int psm); + +#endif diff --git a/plugins/gs/GSsoft/Src/Linux-SDL/Conf.c b/plugins/gs/GSsoft/Src/Linux-SDL/Conf.c new file mode 100644 index 0000000..33a89c6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux-SDL/Conf.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include + +#include "../../nsx2.h" +#include "../gs.h" +#include "../../iniapi/iniapi.h" + + +void SaveConfig() { + FILE *f; + char cfg[255]; + + sprintf (cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0x755); + sprintf (cfg, "%s/.PS2E/GSsoftx.cfg", getenv("HOME")); + f = fopen(cfg,"w"); + if (f == NULL) return; + fwrite(&conf, 1, sizeof(conf), f); + fclose(f); +} + +void LoadConfig() { + FILE *f; + char cfg[255]; + int result; + + memset(&conf, 0, sizeof(conf)); + + /* Read config File */ + result = getini(nSX2ConfigFile,"Video","Width",cfg); + if ( result == 0 ) conf.mode.width = 320; + else conf.mode.width = atoi ( cfg ); + + result = getini(nSX2ConfigFile,"Video","Height",cfg); + if ( result == 0 ) conf.mode.height = 240; + else conf.mode.height = atoi ( cfg ); + + result = getini(nSX2ConfigFile,"Video","Bpp",cfg); + if ( result == 0 ) conf.mode.bpp = 16; + else conf.mode.bpp = atoi ( cfg ); + + result = getini(nSX2ConfigFile,"Video","Stretch",cfg); + if ( result == 0 ) conf.stretch = 1; + else conf.stretch = atoi ( cfg ); + /* + conf.mode.width = 640; + conf.mode.height = 480; + conf.mode.bpp = 16; + conf.fullscreen = 0; + conf.stretch = 0; + */ + + conf.fullscreen = 0; + + sprintf (cfg, "%s/.PS2E/GSsoftx.cfg", getenv("HOME")); + f = fopen(cfg,"r"); + if (f == NULL) return; + fread(&conf, 1, sizeof(conf), f); + fclose(f); +} + diff --git a/plugins/gs/GSsoft/Src/Linux-SDL/X11.c b/plugins/gs/GSsoft/Src/Linux-SDL/X11.c new file mode 100644 index 0000000..6d163a8 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux-SDL/X11.c @@ -0,0 +1,279 @@ +#include + +#include "../gs.h" +#include "../Draw.h" + + +SDL_Surface *display; +SDL_Surface *visual; +SDL_Surface* gc; + +int screen; +int depth; + +char *buffd; +SDL_Surface *buffer; + + +SDL_Surface * TextGC; +char *textd; + +SDL_Surface *text; + +static int ShowFullVRam=0; + +void (*ScrBlit) (char *, char *, Rect *, int); + +int DXinit = 0; + +int DXswitchScrMode() { + DXclose(); + conf.fullscreen = 1 - conf.fullscreen; + return DXopen(); +} + +void DXclearScr() { + if (conf.fullscreen) { + + } else { + memset(buffd, 0, conf.mode.width * conf.mode.height * 4); + + SDL_BlitSurface ( GShwnd , NULL , buffer, NULL ); + + } +} + +void DXupdScrBlit() { + //printf("DXupdScrBlit : %d s:%d\n",depth,conf.stretch); + switch (depth) { + case 15: + if (conf.stretch) ScrBlit = ScrBlit15S; + else ScrBlit = ScrBlit15; + break; + case 16: + if (conf.stretch) ScrBlit = ScrBlit16S; + else ScrBlit = ScrBlit16; + break; + case 24: + if (conf.stretch) ScrBlit = ScrBlit24S; + else ScrBlit = ScrBlit24; + break; + case 32: + if (conf.stretch) ScrBlit = ScrBlit32S; + else ScrBlit = ScrBlit32; + break; + } +} + +int DXopen() { + + + u32 rmask, gmask, bmask, amask; + + if (DXinit == 1) return 0; + + + + + //printf("DXopen : %d \n",conf.fullscreen); + + if (conf.fullscreen) { + + return -1; + + } else { + + + buffd = malloc(conf.mode.width * conf.mode.height * 4); + if (buffd == NULL) return -1; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; +#else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; +#endif + + depth = conf.mode.bpp; + + buffer = SDL_GetVideoSurface(); + + if ( buffer == NULL ) printf("DXopenError : Create buffer\n"); + //else printf("DXopenOK : Create buffer\n"); + + + } + + DXinit = 1; + + DXupdScrBlit(); + DXclearScr(); + + return 0; +} + +void DXclose() { + DXinit = 0; + + if (conf.fullscreen) { + + } else { + SDL_FreeSurface ( buffer ); + } +} + +#include +int fpspos; +int fpspress; + +void DXupdate() { + Rect gsScr; + static time_t to; + static int fpscount, fpsc, fc; + int lPitch; + char *sbuff; + + fc++; + + if (conf.fps || conf.frameskip) { + if (time(NULL) > to) { + time(&to); + fpsc = fpscount; + fpscount = 0; + } + fpscount++; + } + + if (conf.frameskip) { + if ((fpscount % 3) == 0) { + norender = 1; + } else if (norender) { + norender = 0; + return; + } + } + + if (conf.fullscreen) { + conf.fps = 0; + // sbuff = dgaDev->data; + // lPitch = dgaDev->mode.imageWidth * (dgaDev->mode.bitsPerPixel / 8); + + sbuff = buffer->pixels; + lPitch = buffer->pitch; + + } else { + //sbuff = buffd; + //lPitch = buffer->bytes_per_line; + sbuff = (char * )buffer->pixels; + lPitch = buffer->pitch ; + + } + + if (ShowFullVRam) { + gsScr.x = 0; + gsScr.y = 0; + gsScr.w = gsdspfb->fbw; + gsScr.h = gsdspfb->fbh; + + ScrBlit(sbuff, vRam, &gsScr, lPitch); + + } else { + gsScr.x = gsmode->x + gsdspfb->dbx; + gsScr.y = gsmode->y + gsdspfb->dby; + gsScr.w = gsmode->w; + gsScr.h = gsmode->h; + + + //SDL_LockSurface( buffer ); + ScrBlit(sbuff, dBuf, &gsScr, lPitch); + //SDL_UnlockSurface ( buffer ); + + + } + + if (conf.fps && conf.fullscreen == 0) { + char title[256]; + char tmp[256]; + + if (fpspos < 0) fpspos = 0; +#ifndef GS_LOG + if (fpspos > 4) fpspos = 4; +#else + if (fpspos > 5) fpspos = 5; +#endif + switch (fpspos) { + case 0: // FrameSkip + sprintf(tmp, "Frameskip %s", conf.frameskip == 1 ? "On" : "Off"); + norender = 0; + break; + case 1: // FullScreen + sprintf(tmp, "Fullscreen %s", conf.fullscreen == 1 ? "On" : "Off"); + break; + case 2: // Stretch + sprintf(tmp, "Stretch %s", conf.stretch == 1 ? "On" : "Off"); + break; + case 3: // Misc stuff + sprintf(tmp, "GSmode: %dx%d - FC: %d", gsmode->w, gsmode->h, fc); + break; + case 4: // ShowFullVRam + sprintf(tmp, "ShowFullVRam %s", ShowFullVRam == 1 ? "On" : "Off"); + break; +#ifdef GS_LOG + case 5: // Log + sprintf(tmp, "Log %s - FC: %d", Log == 1 ? "On" : "Off", fc); + break; +#endif + } + if (fpspress) { + switch (fpspos) { + case 0: + conf.frameskip = 1 - conf.frameskip; + break; + case 1: + DXswitchScrMode(); + fpspress = 0; + return; + case 2: + conf.stretch = 1 - conf.stretch; + DXupdScrBlit(); + DXclearScr(); + fpspress = 0; + return; + case 4: + DXclearScr(); + ShowFullVRam = 1 - ShowFullVRam; + break; +#ifdef GS_LOG + case 5: + Log = 1 - Log; + break; +#endif + } + fpspress = 0; + } + + sprintf (title," FPS %d -- %s", fpsc, tmp); + + + +// XPutImage(display, GShwnd, gc, text, 0, 0, 0, 0, conf.mode.width, 15); +// XDrawString(display, GShwnd, TextGC, 0, 12, title, strlen(title)); + } + + if (conf.fullscreen == 0) { + //int i = conf.fps ? 15 : 0; + + SDL_Flip(buffer ); + + + } + +} + + + diff --git a/plugins/gs/GSsoft/Src/Linux/Conf.c b/plugins/gs/GSsoft/Src/Linux/Conf.c new file mode 100644 index 0000000..f6e6fcc --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/Conf.c @@ -0,0 +1,88 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include "GS.h" + +void SaveConfig() { + FILE *f; + char cfg[255]; + + sprintf (cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf (cfg, "%s/.PS2E/GSsoftx.cfg", getenv("HOME")); + f = fopen(cfg,"w"); + if (f == NULL) return; + fprintf(f, "fmode.width = %d\n", conf.fmode.width); + fprintf(f, "fmode.height = %d\n", conf.fmode.height); + fprintf(f, "wmode.width = %d\n", conf.wmode.width); + fprintf(f, "wmode.height = %d\n", conf.wmode.height); + fprintf(f, "fullscreen = %d\n", conf.fullscreen); + fprintf(f, "fps = %d\n", conf.fps); + fprintf(f, "frameskip = %d\n", conf.frameskip); + fprintf(f, "record = %d\n", conf.record); + fprintf(f, "cache = %d\n", conf.cache); + fprintf(f, "cachesize = %d\n", conf.cachesize); + fprintf(f, "codec = %d\n", conf.codec); +#ifdef GS_LOG + fprintf(f, "log = %d\n", conf.log); +#endif + fclose(f); +} + +void LoadConfig() { + FILE *f; + char cfg[255]; + + memset(&conf, 0, sizeof(conf)); + conf.fmode.width = 320; + conf.fmode.height = 240; + conf.wmode.width = 320; + conf.wmode.height = 240; + conf.fullscreen = 1; + conf.cachesize = 128; + conf.codec = 0; + + sprintf (cfg, "%s/.PS2E/GSsoftx.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) return; + fscanf(f, "fmode.width = %d\n", &conf.fmode.width); + fscanf(f, "fmode.height = %d\n", &conf.fmode.height); + fscanf(f, "wmode.width = %d\n", &conf.wmode.width); + fscanf(f, "wmode.height = %d\n", &conf.wmode.height); + fscanf(f, "fullscreen = %d\n", &conf.fullscreen); + fscanf(f, "fps = %d\n", &conf.fps); + fscanf(f, "frameskip = %d\n", &conf.frameskip); + fscanf(f, "record = %d\n", &conf.record); + fscanf(f, "cache = %d\n", &conf.cache); + fscanf(f, "cachesize = %d\n", &conf.cachesize); + fscanf(f, "codec = %d\n", &conf.codec); +#ifdef GS_LOG + fscanf(f, "log = %d\n", &conf.log); +#endif + fclose(f); + + if (conf.fullscreen) cmode = &conf.fmode; + else cmode = &conf.wmode; +} + diff --git a/plugins/gs/GSsoft/Src/Linux/Linux.c b/plugins/gs/GSsoft/Src/Linux/Linux.c new file mode 100644 index 0000000..7cc4725 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/Linux.c @@ -0,0 +1,320 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "GS.h" +#include "interface.h" +#include "support.h" +#include "Linux.h" +#include "Rec.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + + +void CALLBACK GSkeyEvent(keyEvent *ev) { + switch (ev->event) { + case KEYPRESS: + switch (ev->key) { + case XK_Page_Up: + if (conf.fps) fpspos++; break; + case XK_Page_Down: + if (conf.fps) fpspos--; break; + case XK_End: + if (conf.fps) fpspress = 1; break; + case XK_Delete: + conf.fps = 1 - conf.fps; + break; + } + break; + } +} + +GtkWidget *Conf; +GtkWidget *Logging; +GtkWidget *ComboFRes; +GtkWidget *ComboWRes; +GtkWidget *ComboCacheSize; +GtkWidget *ComboCodec; +GtkWidget *ComboFilters; +GList *fresl; +GList *wresl; +GList *cachesizel; +GList *codecl; +GList *filtersl; + +void OnConf_Ok() { + GtkWidget *Btn; + char *str; + int i; + + Btn = lookup_widget(Conf, "GtkCheckButton_Fullscreen"); + conf.fullscreen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboFRes)->entry)); + sscanf(str, "%dx%d", &conf.fmode.width, &conf.fmode.height); + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboWRes)->entry)); + sscanf(str, "%dx%d", &conf.wmode.width, &conf.wmode.height); + + Btn = lookup_widget(Conf, "GtkCheckButton_Fps"); + conf.fps = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(Conf, "GtkCheckButton_Frameskip"); + conf.frameskip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(Conf, "GtkCheckButton_Record"); + conf.record = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + Btn = lookup_widget(Conf, "GtkCheckButton_Cache"); + conf.cache = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboCacheSize)->entry)); + sscanf(str, "%d", &conf.cachesize); + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboCodec)->entry)); + for (i=0; ; i++) { + if (codeclist[i] == NULL) break; + if (strcmp(str, codeclist[i]) == 0) { conf.codec = i; break; } + } + + str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(ComboFilters)->entry)); + for (i=0; ; i++) { + if (filterslist[i] == NULL) break; + if (strcmp(str, filterslist[i]) == 0) { conf.filter = i; break; } + } + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel() { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Logging() { +#ifdef GS_LOG + GtkWidget *Btn; + + Logging = create_Logging(); + + Btn = lookup_widget(Logging, "GtkCheckButton_Log"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.log); + + gtk_widget_show_all(Logging); + gtk_main(); +#endif +} + +void OnLogging_Ok() { +#ifdef GS_LOG + GtkWidget *Btn; + + Btn = lookup_widget(Logging, "GtkCheckButton_Log"); + conf.log = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn)); + + SaveConfig(); + + gtk_widget_destroy(Logging); + gtk_main_quit(); +#endif +} + +void OnLogging_Cancel() { + gtk_widget_destroy(Logging); + gtk_main_quit(); +} + +char mname[64][32]; + +void CALLBACK GSconfigure() { + GtkWidget *Btn; + char name[32]; + int nmodes, i; + + LoadConfig(); + + Conf = create_Config(); + + fresl = NULL; + ComboFRes = lookup_widget(Conf, "GtkCombo_FRes"); + nmodes = DXgetModes(); + for (i=0; ientry), name); + + wresl = NULL; + ComboWRes = lookup_widget(Conf, "GtkCombo_WRes"); + wresl = g_list_append(wresl, "320x240"); + wresl = g_list_append(wresl, "512x384"); + wresl = g_list_append(wresl, "640x480"); + wresl = g_list_append(wresl, "800x600"); + gtk_combo_set_popdown_strings(GTK_COMBO(ComboWRes), wresl); + sprintf(name, "%dx%d", conf.wmode.width, conf.wmode.height); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboWRes)->entry), name); + + Btn = lookup_widget(Conf, "GtkCheckButton_Fullscreen"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.fullscreen); + + Btn = lookup_widget(Conf, "GtkCheckButton_Fps"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.fps); + + Btn = lookup_widget(Conf, "GtkCheckButton_Frameskip"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.frameskip); + + Btn = lookup_widget(Conf, "GtkCheckButton_Record"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.record); + + Btn = lookup_widget(Conf, "GtkCheckButton_Cache"); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), conf.cache); + + cachesizel = NULL; + ComboCacheSize = lookup_widget(Conf, "GtkCombo_CacheSize"); + cachesizel = g_list_append(cachesizel, "64"); + cachesizel = g_list_append(cachesizel, "128"); + cachesizel = g_list_append(cachesizel, "256"); + gtk_combo_set_popdown_strings(GTK_COMBO(ComboCacheSize), cachesizel); + sprintf(name, "%d", conf.cachesize); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboCacheSize)->entry), name); + + codecl = NULL; + ComboCodec = lookup_widget(Conf, "GtkCombo_Codec"); + for (i=0; ; i++) { + if (codeclist[i] == NULL) break; + codecl = g_list_append(codecl, codeclist[i]); + } + gtk_combo_set_popdown_strings(GTK_COMBO(ComboCodec), codecl); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboCodec)->entry), codeclist[conf.codec]); + + if (recExist() == -1) { + Btn = lookup_widget(Conf, "GtkFrame_Rec"); + gtk_widget_set_sensitive(Btn, FALSE); + } + + filtersl = NULL; + ComboFilters = lookup_widget(Conf, "GtkCombo_Filters"); + for (i=0; ; i++) { + if (filterslist[i] == NULL) break; + filtersl = g_list_append(filtersl, filterslist[i]); + } + gtk_combo_set_popdown_strings(GTK_COMBO(ComboFilters), filtersl); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(ComboFilters)->entry), filterslist[conf.filter]); + +#ifndef GS_LOG + Btn = lookup_widget(Conf, "GtkButton_Logging"); + gtk_widget_set_sensitive(Btn, FALSE); +#endif + + gtk_widget_show_all(Conf); + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok() { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CALLBACK GSabout() { + + About = create_About(); + + gtk_widget_show_all(About); + gtk_main(); +} + +s32 CALLBACK GStest() { + return 0; +} + +void *SysLoadLibrary(char *lib) { + return dlopen(lib, RTLD_NOW | RTLD_GLOBAL); +} + +void *SysLoadSym(void *lib, char *sym) { + void *ret = dlsym(lib, sym); + if (ret == NULL) printf("null: %s\n", sym); + return dlsym(lib, sym); +} + +char *SysLibError() { + return dlerror(); +} + +void SysCloseLibrary(void *lib) { + dlclose(lib); +} + diff --git a/plugins/gs/GSsoft/Src/Linux/Linux.h b/plugins/gs/GSsoft/Src/Linux/Linux.h new file mode 100644 index 0000000..bbac864 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/Linux.h @@ -0,0 +1,24 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + + + +#endif diff --git a/plugins/gs/GSsoft/Src/Linux/Makefile b/plugins/gs/GSsoft/Src/Linux/Makefile new file mode 100644 index 0000000..8e9fb53 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/Makefile @@ -0,0 +1,46 @@ + + +CPU = $(shell gcc -dumpmachine) + +OPTIMIZE = -O2 -fomit-frame-pointer -ffast-math -fno-exceptions -m128bit-long-double +#OPTIMIZE = -g -O0 + + +PLUGIN = libGSsoft.so +CFLAGS+= -fPIC -Wall ${OPTIMIZE} -I. -I.. -I../x86 +OBJS = ../GS.o ../Prim.o ../Soft.o ../Draw.o \ + ../Texts.o ../Color.o ../Mem.o ../Rec.o \ + ../Page.o ../Transfer.o ../Cache.o \ + ../SDL.o ../scale2x.o ../Regs.o ../SDL_gfxPrimitives.o +OBJS+= Conf.o interface.o support.o Linux.o +OBJS+= ../x86/ix86_cpudetect.o + +DEPS:= $(OBJS:.o=.d) +LIBS = $(shell gtk-config --libs) $(shell sdl-config --libs) -ldl +CFLAGS+= $(shell gtk-config --cflags) $(shell sdl-config --cflags) -D__LINUX__ + + + +CC = gcc +NASM = nasm + +all: plugin + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} +# strip --strip-unneeded --strip-debug ${PLUGIN} + +test: ../test.o ../i386.o + ${CC} ${CFLAGS} ../test.o ../i386.o -o test ${LIBS} + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +../i386.o: ../i386.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +-include ${DEPS} diff --git a/plugins/gs/GSsoft/Src/Linux/callbacks.c b/plugins/gs/GSsoft/Src/Linux/callbacks.c new file mode 100644 index 0000000..ab877b0 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/callbacks.c @@ -0,0 +1,58 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Logging (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/gs/GSsoft/Src/Linux/callbacks.h b/plugins/gs/GSsoft/Src/Linux/callbacks.h new file mode 100644 index 0000000..ef017bc --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/callbacks.h @@ -0,0 +1,26 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Logging (GtkButton *button, + gpointer user_data); + +void +OnLogging_Ok (GtkButton *button, + gpointer user_data); + +void +OnLogging_Cancel (GtkButton *button, + gpointer user_data); diff --git a/plugins/gs/GSsoft/Src/Linux/gssoft.glade b/plugins/gs/GSsoft/Src/Linux/gssoft.glade new file mode 100644 index 0000000..1fba276 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/gssoft.glade @@ -0,0 +1,791 @@ + + + + + GSsoft + gssoft + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + GSconfig + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + False + False + + + GtkVBox + vbox4 + False + 0 + + + GtkHBox + hbox5 + False + 0 + + 0 + True + True + + + + GtkVBox + vbox1 + 5 + False + 5 + + 0 + True + True + + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox8 + False + 0 + + + GtkHBox + hbox1 + 5 + False + 5 + + 0 + True + True + + + + GtkLabel + label1 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_FRes + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + False + True + 0 + + + + + + + GtkHBox + hbox6 + 5 + False + 5 + + 0 + True + True + + + + GtkLabel + label6 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_WRes + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + False + True + 0 + + + + + + + + + GtkFrame + frame1 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkTable + table1 + 5 + 3 + 2 + False + 5 + 5 + + + GtkCheckButton + GtkCheckButton_Fps + True + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + GtkCheckButton_Frameskip + True + + False + True + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + GtkCheckButton_Fullscreen + True + + False + True + + 1 + 2 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + GtkCheckButton_Stretch + True + + False + True + + 1 + 2 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label7 + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkCombo + GtkCombo_Filters + 120 + False + True + False + True + False + + + 1 + 2 + 2 + 3 + 0 + 0 + False + False + False + False + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry4 + True + True + True + 0 + + + + + + + + + GtkVBox + vbox6 + 5 + False + 0 + + 0 + True + True + + + + GtkFrame + frame4 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox5 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_Cache + True + + False + True + + 0 + False + False + + + + + GtkHBox + hbox2 + False + 5 + + 0 + True + True + + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_CacheSize + 80 + False + True + False + True + False + + + 0 + True + False + + + + GtkEntry + GtkCombo:entry + combo-entry2 + True + True + True + 0 + + + + + + + + + GtkFrame + GtkFrame_Rec + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox7 + 5 + False + 0 + + + GtkCheckButton + GtkCheckButton_Record + True + + False + True + + 0 + False + False + + + + + GtkCombo + GtkCombo_Codec + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry3 + True + True + True + 0 + + + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_END + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + GtkButton_Logging + True + True + + clicked + OnConf_Logging + Sat, 22 Nov 2003 04:35:59 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + GSabout + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label4 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + Logging + 5 + Logging + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox3 + False + 0 + + + GtkCheckButton + GtkCheckButton_Log + True + + False + True + + 0 + False + False + + + + + Placeholder + + + + GtkHButtonBox + hbuttonbox3 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button5 + True + True + + clicked + OnLogging_Ok + Sat, 22 Nov 2003 04:39:03 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button6 + True + True + + clicked + OnLogging_Cancel + Sat, 22 Nov 2003 04:40:17 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/gs/GSsoft/Src/Linux/interface.c b/plugins/gs/GSsoft/Src/Linux/interface.c new file mode 100644 index 0000000..c1e260b --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/interface.c @@ -0,0 +1,517 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox4; + GtkWidget *hbox5; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *vbox8; + GtkWidget *hbox1; + GtkWidget *label1; + GtkWidget *GtkCombo_FRes; + GtkWidget *combo_entry1; + GtkWidget *hbox6; + GtkWidget *label6; + GtkWidget *GtkCombo_WRes; + GtkWidget *entry1; + GtkWidget *frame1; + GtkWidget *table1; + GtkWidget *GtkCheckButton_Fps; + GtkWidget *GtkCheckButton_Frameskip; + GtkWidget *GtkCheckButton_Fullscreen; + GtkWidget *GtkCheckButton_Stretch; + GtkWidget *label7; + GtkWidget *GtkCombo_Filters; + GtkWidget *combo_entry4; + GtkWidget *vbox6; + GtkWidget *frame4; + GtkWidget *vbox5; + GtkWidget *GtkCheckButton_Cache; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_CacheSize; + GtkWidget *combo_entry2; + GtkWidget *GtkFrame_Rec; + GtkWidget *vbox7; + GtkWidget *GtkCheckButton_Record; + GtkWidget *GtkCombo_Codec; + GtkWidget *combo_entry3; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + GtkWidget *GtkButton_Logging; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "GSconfig"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + gtk_window_set_policy (GTK_WINDOW (Config), FALSE, FALSE, FALSE); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox4); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox4", vbox4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox4); + gtk_container_add (GTK_CONTAINER (Config), vbox4); + + hbox5 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox5); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox5", hbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox5); + gtk_box_pack_start (GTK_BOX (vbox4), hbox5, TRUE, TRUE, 0); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_box_pack_start (GTK_BOX (hbox5), vbox1, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Display Setup"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox8); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox8", vbox8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (frame2), vbox8); + + hbox1 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox8), hbox1, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label1 = gtk_label_new ("Fullscreen Resolution"); + gtk_widget_ref (label1); + gtk_object_set_data_full (GTK_OBJECT (Config), "label1", label1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label1); + gtk_box_pack_start (GTK_BOX (hbox1), label1, FALSE, FALSE, 0); + + GtkCombo_FRes = gtk_combo_new (); + gtk_widget_ref (GtkCombo_FRes); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_FRes", GtkCombo_FRes, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_FRes); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_FRes, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_FRes, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_FRes)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + gtk_entry_set_editable (GTK_ENTRY (combo_entry1), FALSE); + + hbox6 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox6); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox6", hbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox8), hbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox6), 5); + + label6 = gtk_label_new ("Windowed Resolution"); + gtk_widget_ref (label6); + gtk_object_set_data_full (GTK_OBJECT (Config), "label6", label6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label6); + gtk_box_pack_start (GTK_BOX (hbox6), label6, FALSE, FALSE, 0); + + GtkCombo_WRes = gtk_combo_new (); + gtk_widget_ref (GtkCombo_WRes); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_WRes", GtkCombo_WRes, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_WRes); + gtk_box_pack_start (GTK_BOX (hbox6), GtkCombo_WRes, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_WRes, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_WRes)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + gtk_entry_set_editable (GTK_ENTRY (entry1), FALSE); + + frame1 = gtk_frame_new ("Options"); + gtk_widget_ref (frame1); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame1", frame1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox1), frame1, TRUE, TRUE, 0); + + table1 = gtk_table_new (3, 2, FALSE); + gtk_widget_ref (table1); + gtk_object_set_data_full (GTK_OBJECT (Config), "table1", table1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (table1); + gtk_container_add (GTK_CONTAINER (frame1), table1); + gtk_container_set_border_width (GTK_CONTAINER (table1), 5); + gtk_table_set_row_spacings (GTK_TABLE (table1), 5); + gtk_table_set_col_spacings (GTK_TABLE (table1), 5); + + GtkCheckButton_Fps = gtk_check_button_new_with_label ("Display Fps Count"); + gtk_widget_ref (GtkCheckButton_Fps); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Fps", GtkCheckButton_Fps, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Fps); + gtk_table_attach (GTK_TABLE (table1), GtkCheckButton_Fps, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + GtkCheckButton_Frameskip = gtk_check_button_new_with_label ("Enable Frameskip"); + gtk_widget_ref (GtkCheckButton_Frameskip); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Frameskip", GtkCheckButton_Frameskip, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Frameskip); + gtk_table_attach (GTK_TABLE (table1), GtkCheckButton_Frameskip, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + GtkCheckButton_Fullscreen = gtk_check_button_new_with_label ("Enable Fullscreen"); + gtk_widget_ref (GtkCheckButton_Fullscreen); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Fullscreen", GtkCheckButton_Fullscreen, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Fullscreen); + gtk_table_attach (GTK_TABLE (table1), GtkCheckButton_Fullscreen, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + GtkCheckButton_Stretch = gtk_check_button_new_with_label ("Disable Stretching"); + gtk_widget_ref (GtkCheckButton_Stretch); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Stretch", GtkCheckButton_Stretch, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Stretch); + gtk_table_attach (GTK_TABLE (table1), GtkCheckButton_Stretch, 1, 2, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label7 = gtk_label_new ("Screen Filtering"); + gtk_widget_ref (label7); + gtk_object_set_data_full (GTK_OBJECT (Config), "label7", label7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label7); + gtk_table_attach (GTK_TABLE (table1), label7, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5); + + GtkCombo_Filters = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Filters); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Filters", GtkCombo_Filters, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Filters); + gtk_table_attach (GTK_TABLE (table1), GtkCombo_Filters, 1, 2, 2, 3, + (GtkAttachOptions) (0), + (GtkAttachOptions) (0), 0, 0); + gtk_widget_set_usize (GtkCombo_Filters, 120, -2); + + combo_entry4 = GTK_COMBO (GtkCombo_Filters)->entry; + gtk_widget_ref (combo_entry4); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry4", combo_entry4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry4); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox6); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox6", vbox6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox6); + gtk_box_pack_start (GTK_BOX (hbox5), vbox6, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox6), 5); + + frame4 = gtk_frame_new ("Texture Caching"); + gtk_widget_ref (frame4); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame4", frame4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (vbox6), frame4, TRUE, TRUE, 0); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox5); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox5", vbox5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox5); + gtk_container_add (GTK_CONTAINER (frame4), vbox5); + gtk_container_set_border_width (GTK_CONTAINER (vbox5), 5); + + GtkCheckButton_Cache = gtk_check_button_new_with_label ("Enable Texture Caching"); + gtk_widget_ref (GtkCheckButton_Cache); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Cache", GtkCheckButton_Cache, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Cache); + gtk_box_pack_start (GTK_BOX (vbox5), GtkCheckButton_Cache, FALSE, FALSE, 0); + + hbox2 = gtk_hbox_new (FALSE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_box_pack_start (GTK_BOX (vbox5), hbox2, TRUE, TRUE, 0); + + label5 = gtk_label_new ("Cache Size"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_CacheSize = gtk_combo_new (); + gtk_widget_ref (GtkCombo_CacheSize); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_CacheSize", GtkCombo_CacheSize, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_CacheSize); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_CacheSize, TRUE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_CacheSize, 80, -2); + + combo_entry2 = GTK_COMBO (GtkCombo_CacheSize)->entry; + gtk_widget_ref (combo_entry2); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry2", combo_entry2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry2); + + GtkFrame_Rec = gtk_frame_new ("Recording"); + gtk_widget_ref (GtkFrame_Rec); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkFrame_Rec", GtkFrame_Rec, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkFrame_Rec); + gtk_box_pack_start (GTK_BOX (vbox6), GtkFrame_Rec, TRUE, TRUE, 0); + + vbox7 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox7); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox7", vbox7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox7); + gtk_container_add (GTK_CONTAINER (GtkFrame_Rec), vbox7); + gtk_container_set_border_width (GTK_CONTAINER (vbox7), 5); + + GtkCheckButton_Record = gtk_check_button_new_with_label ("Enable Recording"); + gtk_widget_ref (GtkCheckButton_Record); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Record", GtkCheckButton_Record, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Record); + gtk_box_pack_start (GTK_BOX (vbox7), GtkCheckButton_Record, FALSE, FALSE, 0); + + GtkCombo_Codec = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Codec); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Codec", GtkCombo_Codec, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Codec); + gtk_box_pack_start (GTK_BOX (vbox7), GtkCombo_Codec, FALSE, FALSE, 0); + + combo_entry3 = GTK_COMBO (GtkCombo_Codec)->entry; + gtk_widget_ref (combo_entry3); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry3", combo_entry3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry3); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox4), hbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + GtkButton_Logging = gtk_button_new_with_label ("Logging..."); + gtk_widget_ref (GtkButton_Logging); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkButton_Logging", GtkButton_Logging, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkButton_Logging); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), GtkButton_Logging); + GTK_WIDGET_SET_FLAGS (GtkButton_Logging, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + gtk_signal_connect (GTK_OBJECT (GtkButton_Logging), "clicked", + GTK_SIGNAL_FUNC (OnConf_Logging), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *label4; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "GSabout"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("GSsoftx Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Authors: linuzappz \n [TyRaNiD]"); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + label4 = gtk_label_new ("Thanks to:\n\t\tshadow - conding support and help.\n\t\tPete Bernert - for the triangles code.\n\t\tAbsolute0 - help fixing bugs :)"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (About), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (vbox2), label4, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label4), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + +GtkWidget* +create_Logging (void) +{ + GtkWidget *Logging; + GtkWidget *vbox3; + GtkWidget *GtkCheckButton_Log; + GtkWidget *hbuttonbox3; + GtkWidget *button5; + GtkWidget *button6; + + Logging = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Logging), "Logging", Logging); + gtk_container_set_border_width (GTK_CONTAINER (Logging), 5); + gtk_window_set_title (GTK_WINDOW (Logging), "Logging"); + gtk_window_set_position (GTK_WINDOW (Logging), GTK_WIN_POS_CENTER); + + vbox3 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "vbox3", vbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox3); + gtk_container_add (GTK_CONTAINER (Logging), vbox3); + + GtkCheckButton_Log = gtk_check_button_new_with_label ("Log"); + gtk_widget_ref (GtkCheckButton_Log); + gtk_object_set_data_full (GTK_OBJECT (Logging), "GtkCheckButton_Log", GtkCheckButton_Log, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Log); + gtk_box_pack_start (GTK_BOX (vbox3), GtkCheckButton_Log, FALSE, FALSE, 0); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox3); + gtk_object_set_data_full (GTK_OBJECT (Logging), "hbuttonbox3", hbuttonbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox3); + gtk_box_pack_start (GTK_BOX (vbox3), hbuttonbox3, TRUE, TRUE, 0); + + button5 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button5); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button5", button5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button5); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), button5); + GTK_WIDGET_SET_FLAGS (button5, GTK_CAN_DEFAULT); + + button6 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button6); + gtk_object_set_data_full (GTK_OBJECT (Logging), "button6", button6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button6); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), button6); + GTK_WIDGET_SET_FLAGS (button6, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button5), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button6), "clicked", + GTK_SIGNAL_FUNC (OnLogging_Cancel), + NULL); + + return Logging; +} + diff --git a/plugins/gs/GSsoft/Src/Linux/interface.h b/plugins/gs/GSsoft/Src/Linux/interface.h new file mode 100644 index 0000000..3c4209a --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/interface.h @@ -0,0 +1,7 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); +GtkWidget* create_Logging (void); diff --git a/plugins/gs/GSsoft/Src/Linux/support.c b/plugins/gs/GSsoft/Src/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/gs/GSsoft/Src/Linux/support.h b/plugins/gs/GSsoft/Src/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/gs/GSsoft/Src/Mem.c b/plugins/gs/GSsoft/Src/Mem.c new file mode 100644 index 0000000..7e44a04 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Mem.c @@ -0,0 +1,174 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Page.h" + + +void writePixel32(int x, int y, u32 pixel, u32 bp, u32 bw) { + vRamUL[getPixelAddress32(x, y, bp, bw)] = pixel; +} + +void writePixel24(int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)]; + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +void writePixel16(int x, int y, u16 pixel, u32 bp, u32 bw) { + vRamUS[getPixelAddress16(x, y, bp, bw)] = pixel; +} + +void writePixel16S(int x, int y, u16 pixel, u32 bp, u32 bw) { + vRamUS[getPixelAddress16S(x, y, bp, bw)] = pixel; +} + +void writePixel8(int x, int y, u8 pixel, u32 bp, u32 bw) { + vRam[getPixelAddress8(x, y, bp, bw)] = pixel; +} + +void writePixel8H(int x, int y, u8 pixel, u32 bp, u32 bw) { + ((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3] = pixel; +} + +void writePixel4(int x, int y, u8 pixel, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = vRam[addr/2]; + if (addr & 0x1) + vRam[addr/2] = (pix & 0x0f) | (pixel << 4); + else vRam[addr/2] = (pix & 0xf0) | (pixel); +} + +void writePixel4HL(int x, int y, u8 pixel, u32 bp, u32 bw) { + u8 *p = &((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3]; + *p = (*p & 0xf0) | pixel; +} + +void writePixel4HH(int x, int y, u8 pixel, u32 bp, u32 bw) { + u8 *p = &((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3]; + *p = (*p & 0x0f) | pixel; +} + + +void writePixel32Z(int x, int y, u32 pixel, u32 bp, u32 bw) { + vRamUL[getPixelAddress32Z(x, y, bp, bw)] = pixel; +} + +void writePixel24Z(int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)&vRamUL[getPixelAddress32Z(x, y, bp, bw)]; + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +void writePixel16Z(int x, int y, u16 pixel, u32 bp, u32 bw) { + vRamUS[getPixelAddress16Z(x, y, bp, bw)] = pixel; +} + +void writePixel16SZ(int x, int y, u16 pixel, u32 bp, u32 bw) { + vRamUS[getPixelAddress16SZ(x, y, bp, bw)] = pixel; +} + + +/////////////// + +u32 readPixel32(int x, int y, u32 bp, u32 bw) { + return vRamUL[getPixelAddress32(x, y, bp, bw)]; +} + +u32 readPixel24(int x, int y, u32 bp, u32 bw) { + return vRamUL[getPixelAddress32(x, y, bp, bw)] & 0xffffff; +} + +u16 readPixel16(int x, int y, u32 bp, u32 bw) { + return vRamUS[getPixelAddress16(x, y, bp, bw)]; +} + +u16 readPixel16S(int x, int y, u32 bp, u32 bw) { + return vRamUS[getPixelAddress16S(x, y, bp, bw)]; +} + +u8 readPixel8(int x, int y, u32 bp, u32 bw) { + return vRam[getPixelAddress8(x, y, bp, bw)]; +} + +u8 readPixel8H(int x, int y, u32 bp, u32 bw) { + return ((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3]; +} + +u8 readPixel4(int x, int y, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = vRam[addr/2]; + if (addr & 0x1) + return pix >> 4; + else return pix & 0xf; +} + +u8 readPixel4HL(int x, int y, u32 bp, u32 bw) { + u8 *p = &((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3]; + return *p & 0x0f; +} + +u8 readPixel4HH(int x, int y, u32 bp, u32 bw) { + u8 *p = &((u8*)&vRamUL[getPixelAddress32(x, y, bp, bw)])[3]; + return *p >> 4; +} + +/////////////// + +u32 readPixel32Z(int x, int y, u32 bp, u32 bw) { + return vRamUL[getPixelAddress32Z(x, y, bp, bw)]; +} + +u32 readPixel24Z(int x, int y, u32 bp, u32 bw) { + return vRamUL[getPixelAddress32Z(x, y, bp, bw)] & 0xffffff; +} + +u16 readPixel16Z(int x, int y, u32 bp, u32 bw) { + return vRamUS[getPixelAddress16Z(x, y, bp, bw)]; +} + +u16 readPixel16SZ(int x, int y, u32 bp, u32 bw) { + return vRamUS[getPixelAddress16SZ(x, y, bp, bw)]; +} + +/////////////// + +u32 readPixel16to32(int x, int y, u32 bp, u32 bw) { + return RGBA16to32(vRamUS[getPixelAddress16(x, y, bp, bw)]); +} + +u32 readPixel16Sto32(int x, int y, u32 bp, u32 bw) { + return RGBA16to32(vRamUS[getPixelAddress16S(x, y, bp, bw)]); +} + +/////////////// + +u32 readPixel16Zto32(int x, int y, u32 bp, u32 bw) { + return RGBA16to32(vRamUS[getPixelAddress16Z(x, y, bp, bw)]); +} + +u32 readPixel16SZto32(int x, int y, u32 bp, u32 bw) { + return RGBA16to32(vRamUS[getPixelAddress16SZ(x, y, bp, bw)]); +} + diff --git a/plugins/gs/GSsoft/Src/Mem.h b/plugins/gs/GSsoft/Src/Mem.h new file mode 100644 index 0000000..389cb05 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Mem.h @@ -0,0 +1,59 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MEM_H__ +#define __MEM_H__ + + +void writePixel32(int x, int y, u32 pixel, u32 bp, u32 bw); +void writePixel24(int x, int y, u32 pixel, u32 bp, u32 bw); +void writePixel16(int x, int y, u16 pixel, u32 bp, u32 bw); +void writePixel16S(int x, int y, u16 pixel, u32 bp, u32 bw); +void writePixel8(int x, int y, u8 pixel, u32 bp, u32 bw); +void writePixel8H(int x, int y, u8 pixel, u32 bp, u32 bw); +void writePixel4(int x, int y, u8 pixel, u32 bp, u32 bw); +void writePixel4HL(int x, int y, u8 pixel, u32 bp, u32 bw); +void writePixel4HH(int x, int y, u8 pixel, u32 bp, u32 bw); + +u32 readPixel32(int x, int y, u32 bp, u32 bw); +u32 readPixel24(int x, int y, u32 bp, u32 bw); +u16 readPixel16(int x, int y, u32 bp, u32 bw); +u16 readPixel16S(int x, int y, u32 bp, u32 bw); +u8 readPixel8(int x, int y, u32 bp, u32 bw); +u8 readPixel8H(int x, int y, u32 bp, u32 bw); +u8 readPixel4(int x, int y, u32 bp, u32 bw); +u8 readPixel4HL(int x, int y, u32 bp, u32 bw); +u8 readPixel4HH(int x, int y, u32 bp, u32 bw); + +void writePixel32Z(int x, int y, u32 pixel, u32 bp, u32 bw); +void writePixel24Z(int x, int y, u32 pixel, u32 bp, u32 bw); +void writePixel16Z(int x, int y, u16 pixel, u32 bp, u32 bw); +void writePixel16SZ(int x, int y, u16 pixel, u32 bp, u32 bw); + +u32 readPixel32Z(int x, int y, u32 bp, u32 bw); +u32 readPixel24Z(int x, int y, u32 bp, u32 bw); +u16 readPixel16Z(int x, int y, u32 bp, u32 bw); +u16 readPixel16SZ(int x, int y, u32 bp, u32 bw); + +u32 readPixel16to32(int x, int y, u32 bp, u32 bw); +u32 readPixel16Sto32(int x, int y, u32 bp, u32 bw); + +u32 readPixel16Zto32(int x, int y, u32 bp, u32 bw); +u32 readPixel16SZto32(int x, int y, u32 bp, u32 bw); + +#endif /* __MEM_H__ */ diff --git a/plugins/gs/GSsoft/Src/PS2Edefs.h b/plugins/gs/GSsoft/Src/PS2Edefs.h new file mode 100644 index 0000000..6481d35 --- /dev/null +++ b/plugins/gs/GSsoft/Src/PS2Edefs.h @@ -0,0 +1,696 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.7 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite8(u32 mem, u8 value); +void CALLBACK GSwrite16(u32 mem, u16 value); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u8 CALLBACK GSread8(u32 mem); +u16 CALLBACK GSread16(u32 mem); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _GSwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u8 (CALLBACK* _GSread8)(u32 mem); +typedef u16 (CALLBACK* _GSread16)(u32 mem); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite8 GSwrite8; +_GSwrite16 GSwrite16; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread8 GSread8; +_GSread16 GSread16; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/gs/GSsoft/Src/PS2Etypes.h b/plugins/gs/GSsoft/Src/PS2Etypes.h new file mode 100644 index 0000000..3a63c58 --- /dev/null +++ b/plugins/gs/GSsoft/Src/PS2Etypes.h @@ -0,0 +1,43 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__MSCW32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#elif defined(__LINUX__) || defined(__MINGW32__) + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/gs/GSsoft/Src/Page.c b/plugins/gs/GSsoft/Src/Page.c new file mode 100644 index 0000000..192b74a --- /dev/null +++ b/plugins/gs/GSsoft/Src/Page.c @@ -0,0 +1,354 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" + +int blockTable32[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +int blockTable32Z[4][8] = { + { 24, 25, 28, 29, 8, 9, 12, 13}, + { 26, 27, 30, 31, 10, 11, 14, 15}, + { 16, 17, 20, 21, 0, 1, 4, 5}, + { 18, 19, 22, 23, 2, 3, 6, 7} +}; + +int blockTable16[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +int blockTable16S[8][4] = { + { 0, 2, 16, 18 }, + { 1, 3, 17, 19 }, + { 8, 10, 24, 26 }, + { 9, 11, 25, 27 }, + { 4, 6, 20, 22 }, + { 5, 7, 21, 23 }, + { 12, 14, 28, 30 }, + { 13, 15, 29, 31 } +}; + +int blockTable16Z[8][4] = { + { 24, 26, 16, 18 }, + { 25, 27, 17, 19 }, + { 28, 30, 20, 22 }, + { 29, 31, 21, 23 }, + { 8, 10, 0, 2 }, + { 9, 11, 1, 3 }, + { 12, 14, 4, 6 }, + { 13, 15, 5, 7 } +}; + +int blockTable16SZ[8][4] = { + { 24, 26, 8, 10 }, + { 25, 27, 9, 11 }, + { 16, 18, 0, 2 }, + { 17, 19, 1, 3 }, + { 28, 30, 12, 14 }, + { 29, 31, 13, 15 }, + { 20, 22, 4, 6 }, + { 21, 23, 5, 7 } +}; + +int blockTable8[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +int blockTable4[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +int columnTable32[8][8] = { + { 0, 1, 4, 5, 8, 9, 12, 13 }, + { 2, 3, 6, 7, 10, 11, 14, 15 }, + { 16, 17, 20, 21, 24, 25, 28, 29 }, + { 18, 19, 22, 23, 26, 27, 30, 31 }, + { 32, 33, 36, 37, 40, 41, 44, 45 }, + { 34, 35, 38, 39, 42, 43, 46, 47 }, + { 48, 49, 52, 53, 56, 57, 60, 61 }, + { 50, 51, 54, 55, 58, 59, 62, 63 }, +}; + +int columnTable16[8][16] = { + { 0, 2, 8, 10, 16, 18, 24, 26, + 1, 3, 9, 11, 17, 19, 25, 27 }, + { 4, 6, 12, 14, 20, 22, 28, 30, + 5, 7, 13, 15, 21, 23, 29, 31 }, + { 32, 34, 40, 42, 48, 50, 56, 58, + 33, 35, 41, 43, 49, 51, 57, 59 }, + { 36, 38, 44, 46, 52, 54, 60, 62, + 37, 39, 45, 47, 53, 55, 61, 63 }, + { 64, 66, 72, 74, 80, 82, 88, 90, + 65, 67, 73, 75, 81, 83, 89, 91 }, + { 68, 70, 76, 78, 84, 86, 92, 94, + 69, 71, 77, 79, 85, 87, 93, 95 }, + { 96, 98, 104, 106, 112, 114, 120, 122, + 97, 99, 105, 107, 113, 115, 121, 123 }, + { 100, 102, 108, 110, 116, 118, 124, 126, + 101, 103, 109, 111, 117, 119, 125, 127 }, +}; + +int columnTable8[16][16] = { + { 0, 4, 16, 20, 32, 36, 48, 52, // column 0 + 2, 6, 18, 22, 34, 38, 50, 54 }, + { 8, 12, 24, 28, 40, 44, 56, 60, + 10, 14, 26, 30, 42, 46, 58, 62 }, + { 33, 37, 49, 53, 1, 5, 17, 21, + 35, 39, 51, 55, 3, 7, 19, 23 }, + { 41, 45, 57, 61, 9, 13, 25, 29, + 43, 47, 59, 63, 11, 15, 27, 31 }, + { 96, 100, 112, 116, 64, 68, 80, 84, // column 1 + 98, 102, 114, 118, 66, 70, 82, 86 }, + { 104, 108, 120, 124, 72, 76, 88, 92, + 106, 110, 122, 126, 74, 78, 90, 94 }, + { 65, 69, 81, 85, 97, 101, 113, 117, + 67, 71, 83, 87, 99, 103, 115, 119 }, + { 73, 77, 89, 93, 105, 109, 121, 125, + 75, 79, 91, 95, 107, 111, 123, 127 }, + { 128, 132, 144, 148, 160, 164, 176, 180, // column 2 + 130, 134, 146, 150, 162, 166, 178, 182 }, + { 136, 140, 152, 156, 168, 172, 184, 188, + 138, 142, 154, 158, 170, 174, 186, 190 }, + { 161, 165, 177, 181, 129, 133, 145, 149, + 163, 167, 179, 183, 131, 135, 147, 151 }, + { 169, 173, 185, 189, 137, 141, 153, 157, + 171, 175, 187, 191, 139, 143, 155, 159 }, + { 224, 228, 240, 244, 192, 196, 208, 212, // column 3 + 226, 230, 242, 246, 194, 198, 210, 214 }, + { 232, 236, 248, 252, 200, 204, 216, 220, + 234, 238, 250, 254, 202, 206, 218, 222 }, + { 193, 197, 209, 213, 225, 229, 241, 245, + 195, 199, 211, 215, 227, 231, 243, 247 }, + { 201, 205, 217, 221, 233, 237, 249, 253, + 203, 207, 219, 223, 235, 239, 251, 255 }, +}; + +int columnTable4[16][32] = { + { 0, 8, 32, 40, 64, 72, 96, 104, // column 0 + 2, 10, 34, 42, 66, 74, 98, 106, + 4, 12, 36, 44, 68, 76, 100, 108, + 6, 14, 38, 46, 70, 78, 102, 110 }, + { 16, 24, 48, 56, 80, 88, 112, 120, + 18, 26, 50, 58, 82, 90, 114, 122, + 20, 28, 52, 60, 84, 92, 116, 124, + 22, 30, 54, 62, 86, 94, 118, 126 }, + { 65, 73, 97, 105, 1, 9, 33, 41, + 67, 75, 99, 107, 3, 11, 35, 43, + 69, 77, 101, 109, 5, 13, 37, 45, + 71, 79, 103, 111, 7, 15, 39, 47 }, + { 81, 89, 113, 121, 17, 25, 49, 57, + 83, 91, 115, 123, 19, 27, 51, 59, + 85, 93, 117, 125, 21, 29, 53, 61, + 87, 95, 119, 127, 23, 31, 55, 63 }, + { 192, 200, 224, 232, 128, 136, 160, 168, // column 1 + 194, 202, 226, 234, 130, 138, 162, 170, + 196, 204, 228, 236, 132, 140, 164, 172, + 198, 206, 230, 238, 134, 142, 166, 174 }, + { 208, 216, 240, 248, 144, 152, 176, 184, + 210, 218, 242, 250, 146, 154, 178, 186, + 212, 220, 244, 252, 148, 156, 180, 188, + 214, 222, 246, 254, 150, 158, 182, 190 }, + { 129, 137, 161, 169, 193, 201, 225, 233, + 131, 139, 163, 171, 195, 203, 227, 235, + 133, 141, 165, 173, 197, 205, 229, 237, + 135, 143, 167, 175, 199, 207, 231, 239 }, + { 145, 153, 177, 185, 209, 217, 241, 249, + 147, 155, 179, 187, 211, 219, 243, 251, + 149, 157, 181, 189, 213, 221, 245, 253, + 151, 159, 183, 191, 215, 223, 247, 255 }, + { 256, 264, 288, 296, 320, 328, 352, 360, // column 2 + 258, 266, 290, 298, 322, 330, 354, 362, + 260, 268, 292, 300, 324, 332, 356, 364, + 262, 270, 294, 302, 326, 334, 358, 366 }, + { 272, 280, 304, 312, 336, 344, 368, 376, + 274, 282, 306, 314, 338, 346, 370, 378, + 276, 284, 308, 316, 340, 348, 372, 380, + 278, 286, 310, 318, 342, 350, 374, 382 }, + { 321, 329, 353, 361, 257, 265, 289, 297, + 323, 331, 355, 363, 259, 267, 291, 299, + 325, 333, 357, 365, 261, 269, 293, 301, + 327, 335, 359, 367, 263, 271, 295, 303 }, + { 337, 345, 369, 377, 273, 281, 305, 313, + 339, 347, 371, 379, 275, 283, 307, 315, + 341, 349, 373, 381, 277, 285, 309, 317, + 343, 351, 375, 383, 279, 287, 311, 319 }, + { 448, 456, 480, 488, 384, 392, 416, 424, // column 3 + 450, 458, 482, 490, 386, 394, 418, 426, + 452, 460, 484, 492, 388, 396, 420, 428, + 454, 462, 486, 494, 390, 398, 422, 430 }, + { 464, 472, 496, 504, 400, 408, 432, 440, + 466, 474, 498, 506, 402, 410, 434, 442, + 468, 476, 500, 508, 404, 412, 436, 444, + 470, 478, 502, 510, 406, 414, 438, 446 }, + { 385, 393, 417, 425, 449, 457, 481, 489, + 387, 395, 419, 427, 451, 459, 483, 491, + 389, 397, 421, 429, 453, 461, 485, 493, + 391, 399, 423, 431, 455, 463, 487, 495 }, + { 401, 409, 433, 441, 465, 473, 497, 505, + 403, 411, 435, 443, 467, 475, 499, 507, + 405, 413, 437, 445, 469, 477, 501, 509, + 407, 415, 439, 447, 471, 479, 503, 511 }, +}; + +u32 getPixelAddress32(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress32: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable32[(y / 8) & 3][(x / 8) & 7]; + basepage = (bp >> 5) + ((y / 32) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 64 + columnTable32[y % 8][x % 8]; + if (word >= 0x100000) { +// GS_LOG("getPixelAddress32: %d, %d, %x, %x -> %x\n", x, y, bp, bw, word); + return 0; + } + return word; +} + +u32 getPixelAddress16(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress16: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable16[(y / 8) & 7][(x / 16) & 3]; + basepage = (bp >> 5) + ((y / 64) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 128 + columnTable16[y % 8][x % 16]; +/* GS_LOG("block: %x\n", block); + GS_LOG("basepage: %x\n", basepage); + GS_LOG("word: %x\n", word);*/ + if (word >= 0x200000) return 0; + return word; +} + +u32 getPixelAddress16S(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress16: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable16S[(y / 8) & 7][(x / 16) & 3]; + basepage = (bp >> 5) + ((y / 64) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 128 + columnTable16[y % 8][x % 16]; +/* GS_LOG("block: %x\n", block); + GS_LOG("basepage: %x\n", basepage); + GS_LOG("word: %x\n", word);*/ + if (word >= 0x200000) return 0; + return word; +} + +u32 getPixelAddress8(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress8: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable8[(y / 16) & 3][(x / 16) & 7]; + basepage = (bp >> 5) + ((y / 64) * ((bw+127)/128)) + x/128; + word = ((basepage * 32) + block) * 256 + columnTable8[y % 16][x % 16]; +// GS_LOG("block: %x\n", block); +// GS_LOG("basepage: %x\n", basepage); +// GS_LOG("word: %x\n", word); + if (word >= 0x400000) return 0; + return word; +} + +u32 getPixelAddress4(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + + block = (bp & 0x1f) + blockTable4[(y / 16) & 7][(x / 32) & 3]; + basepage = (bp >> 5) + ((y / 128) * ((bw+127)/128)) + x/128; + word = ((basepage * 32) + block) * 512 + columnTable4[y % 16][x % 32]; + if (word >= 0x800000) return 0; + return word; +} + +u32 getPixelAddress32Z(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress32: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable32Z[(y / 8) & 3][(x / 8) & 7]; + basepage = (bp >> 5) + ((y / 32) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 64 + (y % 8) * 8 + x % 8; + if (word >= 0x100000) return 0; + return word; +} + +u32 getPixelAddress16Z(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress16: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable16Z[(y / 8) & 7][(x / 16) & 3]; + basepage = (bp >> 5) + ((y / 64) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 128 + (y % 8) * 16 + x % 16; +/* GS_LOG("block: %x\n", block); + GS_LOG("basepage: %x\n", basepage); + GS_LOG("word: %x\n", word);*/ + if (word >= 0x200000) return 0; + return word; +} + +u32 getPixelAddress16SZ(int x, int y, u32 bp, u32 bw) { + u32 block; + u32 basepage; + u32 word; + +// GS_LOG("getPixelAddress16: %d, %d, %x, %x\n", x, y, bp, bw); + block = (bp & 0x1f) + blockTable16SZ[(y / 8) & 7][(x / 16) & 3]; + basepage = (bp >> 5) + ((y / 64) * (bw/64)) + x/64; + word = ((basepage * 32) + block) * 128 + (y % 8) * 16 + x % 16; +/* GS_LOG("block: %x\n", block); + GS_LOG("basepage: %x\n", basepage); + GS_LOG("word: %x\n", word);*/ + if (word >= 0x200000) return 0; + return word; +} + diff --git a/plugins/gs/GSsoft/Src/Page.h b/plugins/gs/GSsoft/Src/Page.h new file mode 100644 index 0000000..3179ed6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Page.h @@ -0,0 +1,33 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PAGE_H__ +#define __PAGE_H__ + +u32 getPixelAddress32(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress16(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress16S(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress8(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress4(int x, int y, u32 bp, u32 bw); + +u32 getPixelAddress32Z(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress16Z(int x, int y, u32 bp, u32 bw); +u32 getPixelAddress16SZ(int x, int y, u32 bp, u32 bw); + + +#endif /* __PAGE_H__ */ diff --git a/plugins/gs/GSsoft/Src/Prim.c b/plugins/gs/GSsoft/Src/Prim.c new file mode 100644 index 0000000..4579084 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Prim.c @@ -0,0 +1,390 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "GS.h" +#include "Soft.h" +#include "Mem.h" + + +__inline void stepGSvertex() { + int i; + + gs.primC--; + + for (i=0; itme) { + if (prim->fst) { + gs.gsvertex[i].u = gs.gsvertex[i+1].u; + gs.gsvertex[i].v = gs.gsvertex[i+1].v; + } else { + gs.gsvertex[i].s = gs.gsvertex[i+1].s; + gs.gsvertex[i].t = gs.gsvertex[i+1].t; + gs.gsvertex[i].q = gs.gsvertex[i+1].q; + } + } + + if (prim->iip) { + gs.gsvertex[i].rgba = gs.gsvertex[i+1].rgba; + } + } +} + +__inline void stepGSfanvertex() { + gs.primC--; + + gs.gsvertex[1].x = gs.gsvertex[2].x; + gs.gsvertex[1].y = gs.gsvertex[2].y; + gs.gsvertex[1].z = gs.gsvertex[2].z; + gs.gsvertex[1].f = gs.gsvertex[2].f; + + if (prim->tme) { + if (prim->fst) { + gs.gsvertex[1].u = gs.gsvertex[2].u; + gs.gsvertex[1].v = gs.gsvertex[2].v; + } else { + gs.gsvertex[1].s = gs.gsvertex[2].s; + gs.gsvertex[1].t = gs.gsvertex[2].t; + gs.gsvertex[1].q = gs.gsvertex[2].q; + } + } + + if (prim->iip) { + gs.gsvertex[1].rgba = gs.gsvertex[2].rgba; + } +} + +__inline void STQtoUV(Vertex *v, float q) { +#ifdef GS_LOG + GS_LOG("STQtoUV %f, %f, %f (tw=%d, th=%d)\n", + *(float*)&v->s, *(float*)&v->t, q, tex0->tw, tex0->th); +#endif + if (v->s == 0xffffffff) { printf("v->s == nan\n"); } + if (v->t == 0xffffffff) { printf("v->t == nan\n"); } + if (q == 0xffffffff) { printf("v->q == nan\n"); } + if (q == 0) { + v->u = (int)((float)(tex0->tw-1) * (*(float*)&v->s)); + v->v = (int)((float)(tex0->th-1) * (*(float*)&v->t)); + } else { + v->u = (int)((float)(tex0->tw-1) * (*(float*)&v->s / q)); + v->v = (int)((float)(tex0->th-1) * (*(float*)&v->t / q)); + } + if (v->u > tex0->tw) { +#ifdef GS_LOG + GS_LOG("*warning*: U > TW\n"); +#endif + } + if (v->v > tex0->th) { +#ifdef GS_LOG + GS_LOG("*warning*: V > TH\n"); +#endif + } +} + +void _primPoint(Vertex *vertex) { + Vertex v; + + memcpy(&v, vertex, sizeof(Vertex)); + +#ifdef GS_LOG + GS_LOG("primPoint %dx%d %lx\n", + v.x, v.y, gs.rgba); +#endif + + v.x -= offset->x; v.y -= offset->y; + + if (v.x < scissor->x0) return; + if (v.y < scissor->y0) return; + if (v.x > scissor->x1) return; + if (v.y > scissor->y1) return; + + if (v.x < 0) return; + if (v.x >= gsfb->fbw) return; + if (v.y < 0) return; + if (v.y >= gsfb->fbh) return; + + writePixel32(v.x, v.y, gs.rgba, gsfb->fbp, gsfb->fbw); +} + +void primPoint(Vertex *vertex) { + if (vertex && norender == 0) _primPoint(vertex); + + memset(gs.gsvertex, 0, sizeof(Vertex)); + gs.primC = 0; +} + +void _primLine(Vertex *vertex) { + Vertex v[2]; + + memcpy(v, vertex, sizeof(Vertex) * 2); + + v[0].x -= offset->x; v[0].y -= offset->y; + v[1].x -= offset->x; v[1].y -= offset->y; + +#ifdef GS_LOG + GS_LOG("primLine %dx%d %lx, %dx%d %lx\n", + v[0].x, v[0].y, v[0].rgba, + v[1].x, v[1].y, v[1].rgba); +#endif + if (prim->iip == 0) { + if (test->zte) + drawLineF_Z(v); + else drawLineF(v); + } else { + if (test->zte) + drawLineG_Z(v); + else drawLineG(v); + } +} + +void primLine(Vertex *vertex) { + if (vertex && norender == 0) _primLine(vertex); + + memset(gs.gsvertex, 0, sizeof(Vertex)*2); + gs.primC = 0; +} + +void primLineStrip(Vertex *vertex) { + if (vertex && norender == 0) _primLine(vertex); + + stepGSvertex(); +} + +void _primTriangle(Vertex *vertex) { + Vertex v[3]; + + memcpy(v, vertex, sizeof(Vertex) * 3); + + v[0].x -= offset->x; v[0].y -= offset->y; + v[1].x -= offset->x; v[1].y -= offset->y; + v[2].x -= offset->x; v[2].y -= offset->y; + +#ifdef GS_LOG + GS_LOG("primTriangle%s%s %dx%dx%x %lx - %dx%dx%x %lx - %dx%dx%x %lx (offset %dx%d)\n", + prim->iip == 0 ? "F" : "G", + prim->tme == 0 ? "" : "T", + v[0].x, v[0].y, v[0].z, v[0].rgba, + v[1].x, v[1].y, v[1].z, v[1].rgba, + v[2].x, v[2].y, v[2].z, v[2].rgba, + offset->x, offset->y); +#endif + + if (wireframe) { + drawLineF(&v[0]); + drawLineF(&v[1]); + memcpy(&v[1], &v[2], sizeof(Vertex)); + drawLineF(&v[0]); + return; + } + + if (prim->tme) { + if (tex0->tw == 0 || tex0->th == 0) return; + + if (prim->fst == 0) { +#ifdef GS_LOG + GS_LOG("stq: %fx%fx%f - %fx%fx%f - %fx%fx%f (tex0.tw=%d, tex0.th=%d)\n", + *(float*)&v[0].s, *(float*)&v[0].t, *(float*)&v[0].q, + *(float*)&v[1].s, *(float*)&v[1].t, *(float*)&v[1].q, + *(float*)&v[2].s, *(float*)&v[2].t, *(float*)&v[2].q, + tex0->tw, tex0->th); +#endif + + if (prim->iip) { + STQtoUV(&v[0], *(float*)&v[0].q); + STQtoUV(&v[1], *(float*)&v[1].q); + STQtoUV(&v[2], *(float*)&v[2].q); + } else { + STQtoUV(&v[0], *(float*)&gs.q); + STQtoUV(&v[1], *(float*)&gs.q); + STQtoUV(&v[2], *(float*)&gs.q); + } + } +#ifdef GS_LOG + GS_LOG("uv: %dx%d - %dx%d - %dx%d (tex0.tw=%d, tex0.th=%d)\n", + v[0].u, v[0].v, + v[1].u, v[1].v, v[2].u, v[2].v, + tex0->tw, tex0->th); +#endif + +#ifdef GS_LOG + GS_LOG("uv: %dx%d - %dx%d - %dx%d (tex0.tw=%d, tex0.th=%d)\n", + v[0].u, v[0].v, + v[1].u, v[1].v, v[2].u, v[2].v, + tex0->tw, tex0->th); +#endif + + if (prim->iip) { + if (test->zte) { + switch (tex0->tfx) { + case TEX_DECAL: drawTriangleGTDecal_Z(v); break; + case TEX_MODULATE: drawTriangleGTModulate_Z(v); break; + case TEX_HIGHLIGHT: drawTriangleGTHighlight_Z(v); break; + case TEX_HIGHLIGHT2: drawTriangleGTHighlight2_Z(v); break; + } + } else { + switch (tex0->tfx) { + case TEX_DECAL: drawTriangleGTDecal(v); break; + case TEX_MODULATE: drawTriangleGTModulate(v); break; + case TEX_HIGHLIGHT: drawTriangleGTHighlight(v); break; + case TEX_HIGHLIGHT2: drawTriangleGTHighlight2(v); break; + } + } + } else { + if(test->zte) { + switch (tex0->tfx) { + case TEX_DECAL: drawTriangleFTDecal_Z(v); break; + case TEX_MODULATE: drawTriangleFTModulate_Z(v); break; + case TEX_HIGHLIGHT: drawTriangleFTHighlight_Z(v); break; + case TEX_HIGHLIGHT2: drawTriangleFTHighlight2_Z(v); break; + } + } else { + switch (tex0->tfx) { + case TEX_DECAL: drawTriangleFTDecal(v); break; + case TEX_MODULATE: drawTriangleFTModulate(v); break; + case TEX_HIGHLIGHT: drawTriangleFTHighlight(v); break; + case TEX_HIGHLIGHT2: drawTriangleFTHighlight2(v); break; + } + } + } + } else { + if (prim->iip) { + if(test->zte) + drawTriangleG_Z(v); + else + drawTriangleG(v); + } else { + if(test->zte) + drawTriangleF_Z(v); + else + drawTriangleF(v); + } + } +} + +void primTriangle(Vertex *vertex) { + if (vertex && norender == 0) _primTriangle(vertex); + + memset(gs.gsvertex, 0, sizeof(Vertex)*3); + gs.primC = 0; +// if (conf.log) { DXupdate(); Sleep(250); } +} + +void primTriangleStrip(Vertex *vertex) { + if (vertex && norender == 0) _primTriangle(vertex); + + stepGSvertex(); +// if (conf.log) { DXupdate(); Sleep(250); } +} + +void primTriangleFan(Vertex *vertex) { + if (vertex && norender == 0) _primTriangle(vertex); + + stepGSfanvertex(); +// if (conf.log) { DXupdate(); Sleep(250); } +} + +void _primSprite(Vertex *vertex) { + Vertex v[2]; + + memcpy(v, vertex, sizeof(Vertex) * 2); + +#ifdef GS_LOG + GS_LOG("primSprite%s %dx%d %lx - %dx%d %lx (offset %dx%d) (tex %dx%d %dx%d)\n", + prim->tme == 0 ? "" : "T", + v[0].x, v[0].y, v[0].rgba, + v[1].x, v[1].y, v[1].rgba, + offset->x, offset->y, + v[0].u, v[0].v, + v[1].u, v[1].v); +#endif + + v[0].x -= offset->x; v[0].y -= offset->y; + v[1].x -= offset->x; v[1].y -= offset->y; + + if (v[0].x > v[1].x) { + int x; + x = v[0].x; v[0].x = v[1].x; v[1].x = x; + if (prim->tme) { + float f; + x = v[0].u; v[0].u = v[1].u; v[1].u = x; + f = v[0].s; v[0].s = v[1].s; v[1].s = f; + } + } + if (v[0].y > v[1].y) { + int y; + y = v[0].y; v[0].y = v[1].y; v[1].y = y; + if (prim->tme) { + float f; + y = v[0].v; v[0].v = v[1].v; v[1].v = y; + f = v[0].t; v[0].t = v[1].t; v[1].t = f; + } + } + + if (prim->tme) { + if (tex0->tw == 0 || tex0->th == 0) return; + + if (prim->fst == 0) { + STQtoUV(&v[0], *(float*)&gs.q); + STQtoUV(&v[1], *(float*)&gs.q); + } + + if(test->zte) { // If z buffer enabled + switch (tex0->tfx) { + case TEX_DECAL: drawSpriteTDecal_Z(v); break; + case TEX_MODULATE: drawSpriteTModulate_Z(v); break; + case TEX_HIGHLIGHT: drawSpriteTHighlight_Z(v); break; + case TEX_HIGHLIGHT2: drawSpriteTHighlight2_Z(v); break; + } + } else { + switch (tex0->tfx) { + case TEX_DECAL: drawSpriteTDecal(v); break; + case TEX_MODULATE: drawSpriteTModulate(v); break; + case TEX_HIGHLIGHT: drawSpriteTHighlight(v); break; + case TEX_HIGHLIGHT2: drawSpriteTHighlight2(v); break; + } + } + } else { + if(test->zte) // If z buffer enabled + drawSprite_Z(v); + else + drawSprite(v); + } +} + +void primSprite(Vertex *vertex) { + if (vertex && norender == 0) _primSprite(vertex); + + memset(gs.gsvertex, 0, sizeof(Vertex)*2); + gs.primC = 0; +// if (conf.log) { DXupdate(); Sleep(250); } +} + +void primNull(Vertex *v) { +} + +void (*primTable[8])(Vertex *v) = { + primPoint, primLine, primLineStrip, + primTriangle, primTriangleStrip, primTriangleFan, + primSprite, primNull +}; diff --git a/plugins/gs/GSsoft/Src/Rec.c b/plugins/gs/GSsoft/Src/Rec.c new file mode 100644 index 0000000..918023f --- /dev/null +++ b/plugins/gs/GSsoft/Src/Rec.c @@ -0,0 +1,285 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "GS.h" +#include "Draw.h" +#include "Rec.h" + +AVFormatContext *output = NULL; +AVStream *stream; +AVFrame *picture; +AVFrame *yuv420p; +u8 *picture_buf; +int picture_size; +u8 *outbuf; +int outbuf_size; + +#define av_register_all _av_register_all +#define av_new_stream _av_new_stream +#define av_set_parameters _av_set_parameters +#define av_write_header _av_write_header +#define av_write_frame _av_write_frame +#define av_write_trailer _av_write_trailer +#define avpicture_fill _avpicture_fill +#define avpicture_get_size _avpicture_get_size +#define img_convert _img_convert +#define avcodec_alloc_frame _avcodec_alloc_frame +#define avcodec_open _avcodec_open +#define avcodec_find_encoder _avcodec_find_encoder +#define avcodec_encode_video _avcodec_encode_video +#define avcodec_close _avcodec_close +#define av_mallocz _av_mallocz +#define av_free _av_free +#define __av_freep ___av_freep +#define url_fopen _url_fopen +#define url_fclose _url_fclose +#define first_oformat _first_oformat + +void *avcodeclib; +void *avformatlib; + +#ifdef __WIN32__ +#define AVCODECLIB "avcodec.dll" +#define AVFORMATLIB "avformat.dll" +#else +#define AVCODECLIB "libavcodec.so" +#define AVFORMATLIB "libavformat.so" +#endif + +void (*av_register_all)(void); +AVStream *(*av_new_stream)(AVFormatContext *s, int id); +int (*av_set_parameters)(AVFormatContext *s, AVFormatParameters *ap); +int (*av_write_header)(AVFormatContext *s); +int (*av_write_frame)(AVFormatContext *s, int stream_index, const uint8_t *buf, + int size); +int (*av_write_trailer)(AVFormatContext *s); +int (*avpicture_fill)(AVPicture *picture, uint8_t *ptr, + int pix_fmt, int width, int height); +int (*avpicture_get_size)(int pix_fmt, int width, int height); +int (*img_convert)(AVPicture *dst, int dst_pix_fmt, + AVPicture *src, int pix_fmt, + int width, int height); +AVFrame *(*avcodec_alloc_frame)(void); +int (*avcodec_open)(AVCodecContext *avctx, AVCodec *codec); + +AVCodec *(*avcodec_find_encoder)(enum CodecID id); +int (*avcodec_encode_video)(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict); +int (*avcodec_close)(AVCodecContext *avctx); +void *(*av_mallocz)(unsigned int size); +void (*av_free)(void *ptr); +void (*__av_freep)(void **ptr); +int (*url_fopen)(URLContext **h, const char *filename, int flags); +int (*url_fclose)(URLContext *h); +AVOutputFormat **first_oformat; + +int recLoad() { + avcodeclib = SysLoadLibrary(AVCODECLIB); + if (avcodeclib == NULL) { + printf("Couldn't load %s: %s\n", AVCODECLIB, SysLibError()); + return -1; + } + avformatlib = SysLoadLibrary(AVFORMATLIB); + if (avformatlib == NULL) { + printf("Couldn't load %s: %s\n", AVFORMATLIB, SysLibError()); + return -1; + } + av_register_all = SysLoadSym(avformatlib, "av_register_all"); + av_new_stream = SysLoadSym(avformatlib, "av_new_stream"); + av_set_parameters = SysLoadSym(avformatlib, "av_set_parameters"); + av_write_header = SysLoadSym(avformatlib, "av_write_header"); + av_write_frame = SysLoadSym(avformatlib, "av_write_frame"); + av_write_trailer = SysLoadSym(avformatlib, "av_write_trailer"); + avpicture_fill = SysLoadSym(avcodeclib, "avpicture_fill"); + avpicture_get_size = SysLoadSym(avcodeclib, "avpicture_get_size"); + img_convert = SysLoadSym(avcodeclib, "img_convert"); + avcodec_alloc_frame = SysLoadSym(avcodeclib, "avcodec_alloc_frame"); + avcodec_open = SysLoadSym(avcodeclib, "avcodec_open"); + avcodec_find_encoder = SysLoadSym(avcodeclib, "avcodec_find_encoder"); + avcodec_encode_video = SysLoadSym(avcodeclib, "avcodec_encode_video"); + avcodec_close = SysLoadSym(avcodeclib, "avcodec_close"); + av_mallocz = SysLoadSym(avcodeclib, "av_mallocz"); + av_free = SysLoadSym(avcodeclib, "av_free"); + __av_freep = SysLoadSym(avcodeclib, "__av_freep"); + url_fopen = SysLoadSym(avformatlib, "url_fopen"); + url_fclose = SysLoadSym(avformatlib, "url_fclose"); + first_oformat = SysLoadSym(avformatlib, "first_oformat"); + + return 0; +} + +void recUnload() { + SysLoadLibrary(avcodeclib); + SysLoadLibrary(avformatlib); +} + +void recOpen() { + AVOutputFormat *fmt; + AVCodecContext *codec_ctx; + AVCodec *codec; + char filename[256]; + int video_codec; + + if (output != NULL) recClose(); + + if (recLoad() == -1) { + conf.record = 0; return; + } + + av_register_all(); + + switch (conf.codec) { + case 1: // divx + video_codec = CODEC_ID_MPEG4; + sprintf(filename, "gssoft.avi"); + break; + case 2: // mpeg2 + video_codec = CODEC_ID_MPEG2VIDEO; + sprintf(filename, "gssoft.mpg"); + break; + default: // mpeg1 + video_codec = CODEC_ID_MPEG1VIDEO; + sprintf(filename, "gssoft.mpg"); + break; + } + + fmt = *first_oformat; + while (fmt != NULL) { + if (fmt->video_codec == video_codec) break; + fmt = fmt->next; + } + if (fmt == NULL) { + SysMessage("codec not found"); + conf.record = 0; return; + } + + output = av_mallocz(sizeof(AVFormatContext)); + if (output == NULL) { + SysMessage("Out of Memory"); + conf.record = 0; return; + } + + output->oformat = fmt; + snprintf(output->filename, sizeof(output->filename), "%s", filename); + + stream = av_new_stream(output, 0); + if (stream == NULL) { + SysMessage("Out of Memory"); + conf.record = 0; return; + } + codec_ctx = &stream->codec; + codec_ctx->codec_id = video_codec; + codec_ctx->codec_type = CODEC_TYPE_VIDEO; + codec_ctx->bit_rate = 400000; + codec_ctx->width = cmode->width; + codec_ctx->height = cmode->height; + codec_ctx->frame_rate = gs.SMODE1.cmod & 1 ? 50 : 60; + codec_ctx->frame_rate_base = 1; + if (conf.codec == 0) { + codec_ctx->gop_size = 10; + codec_ctx->max_b_frames = 1; + } + + if (av_set_parameters(output, NULL) < 0) { + SysMessage("set parameters failed"); + conf.record = 0; return; + } + + codec = avcodec_find_encoder(codec_ctx->codec_id); + if (codec == NULL) { + SysMessage("codec not found"); + conf.record = 0; return; + } + if (avcodec_open(codec_ctx, codec) < 0) { + SysMessage("Unable to open codec"); + conf.record = 0; return; + } + + if (url_fopen(&output->pb, filename, URL_WRONLY) < 0) { + SysMessage("Unable to open %s for writing", filename); + conf.record = 0; return; + } + + av_write_header(output); + + picture = avcodec_alloc_frame(); + yuv420p = avcodec_alloc_frame(); + + outbuf_size = 100000; + outbuf = malloc(outbuf_size); + if (outbuf == NULL) { + SysMessage("Out of Memory"); + conf.record = 0; return; + } + + picture_size = avpicture_get_size(PIX_FMT_YUV420P, codec_ctx->width, codec_ctx->height); + picture_buf = malloc(picture_size); + if (picture_buf == NULL) { + SysMessage("Out of Memory"); + conf.record = 0; return; + } + + avpicture_fill((AVPicture*)yuv420p, picture_buf, PIX_FMT_YUV420P, codec_ctx->width, codec_ctx->height); +} + +void recFrame(char *sbuff, int lPitch, int bpp) { + int size; + int pix_fmt; + + picture->data[0] = sbuff; + picture->linesize[0] = lPitch; + switch (bpp) { + case 15: pix_fmt = PIX_FMT_RGB555; break; + case 16: pix_fmt = PIX_FMT_RGB565; break; + case 24: pix_fmt = PIX_FMT_RGB24; break; + case 32: pix_fmt = PIX_FMT_RGBA32; break; + default: return; + } + img_convert((AVPicture*)yuv420p, PIX_FMT_YUV420P, (AVPicture*)picture, pix_fmt, stream->codec.width, stream->codec.height); + size = avcodec_encode_video(&stream->codec, outbuf, outbuf_size, yuv420p); + if (size == -1) { + printf("error encoding frame\n"); return; + } + + av_write_frame(output, stream->index, outbuf, size); +} + +int recExist() { + if (recLoad() == -1) return -1; + recUnload(); + return 0; +} + +void recClose() { + avcodec_close(&stream->codec); + free(outbuf); + free(picture_buf); + free(picture); + free(yuv420p); + + av_write_trailer(output); + url_fclose(&output->pb); + av_freep(&output->streams[0]); + av_free(output); output = NULL; + + recUnload(); +} + diff --git a/plugins/gs/GSsoft/Src/Rec.h b/plugins/gs/GSsoft/Src/Rec.h new file mode 100644 index 0000000..eeff7a8 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Rec.h @@ -0,0 +1,27 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __REC_H__ +#define __REC_H__ + +void recOpen(); +void recFrame(char *sbuff, int lPitch, int bpp); +int recExist(); +void recClose(); + +#endif /* __REC_H__ */ diff --git a/plugins/gs/GSsoft/Src/Regs.c b/plugins/gs/GSsoft/Src/Regs.c new file mode 100644 index 0000000..9c12378 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Regs.c @@ -0,0 +1,1159 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Rec.h" +#include "Page.h" +#include "Transfer.h" +#include "Cache.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) + +#endif + +int primTableC[8] = {1, 2, 2, 3, 3, 3, 2, 0}; +void (*primTable[8])(Vertex *v); + +int pmode=0; + +void CSRwrite(u32 value) { + gs.CSRw = value; + if (value & 0x1) gs.CSRr&= ~0x1; + if (value & 0x2) gs.CSRr&= ~0x2; + if (value & 0x200) { // reset + GSreset(); + } +} + +void IMRwrite(u32 value) { + gs.IMR = value; +} + +void writePMODE(u32 *data) { +#ifdef PREG_LOG + PREG_LOG("GSwrite PMODE value %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + + gs.PMODE.en[0] = (data[0] ) & 0x1; + gs.PMODE.en[1] = (data[0] >> 1) & 0x1; + gs.PMODE.crtmd = (data[0] >> 2) & 0x7; + gs.PMODE.mmod = (data[0] >> 5) & 0x1; + gs.PMODE.amod = (data[0] >> 6) & 0x1; + gs.PMODE.slbg = (data[0] >> 7) & 0x1; + gs.PMODE.alp = (data[0] >> 8) & 0xff; +} + +void writeSMODE1(u32 *data) { + int cmod; + +#ifdef PREG_LOG + PREG_LOG("GSwrite SMODE1 value %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + cmod = (data[0] >> 13) & 0x3; + if (gs.SMODE1.cmod != cmod) { + gs.SMODE1.cmod = cmod; + if (conf.record) recOpen(); + } + + gs.SMODE1.rc = (data[0] ) & 0x7; + gs.SMODE1.lc = (data[0] >> 3) & 0x1f; + gs.SMODE1.t1248 = (data[0] >> 10) & 0x3; + gs.SMODE1.slck = (data[0] >> 12) & 0x1; +// gs.SMODE1.cmod = (data[0] >> 13) & 0x3; + gs.SMODE1.ex = (data[0] >> 15) & 0x1; + gs.SMODE1.prst = (data[0] >> 16) & 0x1; + gs.SMODE1.sint = (data[0] >> 17) & 0x1; + gs.SMODE1.xpck = (data[0] >> 18) & 0x1; + gs.SMODE1.pck2 = (data[0] >> 19) & 0x1; + gs.SMODE1.spml = (data[0] >> 21) & 0xf; + gs.SMODE1.gcont = (data[0] >> 25) & 0x1; + gs.SMODE1.phs = (data[0] >> 26) & 0x1; + gs.SMODE1.pvs = (data[0] >> 27) & 0x1; + gs.SMODE1.pehs = (data[0] >> 28) & 0x1; + gs.SMODE1.pevs = (data[0] >> 29) & 0x1; + gs.SMODE1.clksel= (data[0] >> 30) & 0x3; + gs.SMODE1.nvck = (data[1] ) & 0x1; + gs.SMODE1.slck2 = (data[1] >> 1) & 0x1; + gs.SMODE1.vcksel= (data[1] >> 2) & 0x3; + gs.SMODE1.vhp = (data[1] >> 4);// & 0x7; + + DXsetGSmode(640, gs.SYNCV.vfp & 1 ? gs.SYNCV.vdp : gs.SYNCV.vdp/2); +} + +void writeSMODE2(u32 *data) { +#ifdef PREG_LOG + PREG_LOG("GSwrite SMODE2 value %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + gs.SMODE2.inter = (data[0] ) & 0x1; + gs.SMODE2.ffmd = (data[0] >> 1) & 0x1; + gs.SMODE2.dpms = (data[0] >> 2) & 0x3; +} + +void writeSYNCH1(u32 *data) { +#ifdef PREG_LOG + PREG_LOG("GSwrite SYNCH1 value %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + gs.SYNCH1.hfp = (data[0] ) & 0x7ff; + gs.SYNCH1.fbp = (data[0] >> 11) & 0x7ff; + gs.SYNCH1.hseq = (data[0] >> 22) & 0x3ff; + gs.SYNCH1.hsvs = (data[1] ) & 0x7ff; + gs.SYNCH1.hs = (data[1] >> 11);// & 0x3ff; +} + +void writeSYNCH2(u32 *data) { +#ifdef PREG_LOG + PREG_LOG("GSwrite SYNCH2 value %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + gs.SYNCH2.hf = (data[0] ) & 0x7ff; + gs.SYNCH2.hb = (data[0] >> 11);//\ & 0x7ff; +} + +void writeSYNCHV(u32 *data) { + gs.SYNCV.vfp = (data[0] ) & 0x3ff; + gs.SYNCV.vfpe = (data[0] >> 10) & 0x3ff; + gs.SYNCV.vbp = (data[0] >> 20) & 0xfff; + gs.SYNCV.vbpe = (data[1] ) & 0x3ff; + gs.SYNCV.vdp = (data[1] >> 10) & 0x7ff; + gs.SYNCV.vs = (data[1] >> 21);//\ & 0x7ff; + +#ifdef PREG_LOG + PREG_LOG("GSwrite SYNCV value %8.8lx_%8.8lx: vfp=0x%x vfpe=0x%x vbp=0x%x vbpe=0x%x vdp=0x%x vs=0x%x\n", data[1], data[0], + gs.SYNCV.vfp, gs.SYNCV.vfpe, gs.SYNCV.vbp, gs.SYNCV.vbpe, gs.SYNCV.vdp, gs.SYNCV.vs); +#endif +} + +void writeDISPFB(u32 *data, int i) { +#ifdef PREG_LOG + PREG_LOG("GSwrite DISPFB%d value %8.8lx_%8.8lx\n", i+1, data[1], data[0]); +#endif + gs.DISPFB[i].fbp =((data[0] ) & 0x1ff) * 32; + gs.DISPFB[i].fbw =((data[0] >> 9) & 0x3f) * 64; + gs.DISPFB[i].psm = (data[0] >> 15) & 0x1f; + gs.DISPFB[i].dbx = (data[1] ) & 0x7ff; + gs.DISPFB[i].dby = (data[1] >> 11) & 0x7ff; + if (gs.DISPFB[i].fbw > 0) { + gs.DISPFB[i].fbh = ((4/TextureSizeGS(1, 1, gs.DISPFB[i].psm))*1024*1024) / gs.DISPFB[i].fbw; + } else { + gs.DISPFB[i].fbh = 1024*1024; + } +#ifdef PREG_LOG + PREG_LOG("dispfb%d fbp=0x%x fbw=%d fbh=%d psm=0x%x db %d,%d\n", i+1, + gs.DISPFB[i].fbp, gs.DISPFB[i].fbw, gs.DISPFB[i].fbh, + gs.DISPFB[i].psm, gs.DISPFB[i].dbx, gs.DISPFB[i].dby); +#endif +} + +void writeDISPLAY(u32 *data, int i) { + int magh, magv; + + magh = ((data[0] >> 23) & 0xf) + 1; + magv = ((data[0] >> 27) & 0x3) + 1; +// gs.DISPLAY[i].x = ((data[0] ) & 0xfff) / magh; +// gs.DISPLAY[i].y = ((data[0] >> 12) & 0x7ff) / magv; + gs.DISPLAY[i].w = (((data[1] ) & 0xfff) / magh) + 1; + gs.DISPLAY[i].h = (((data[1] >> 12) & 0x7ff) / magv) + 1; + +// if(((gs.SMODE2.inter == 0) || (gs.SMODE2.ffmd == 1)) && (gs.DISPLAY[1].h > 256)) + if (gs.SMODE2.inter && gs.SMODE2.ffmd) + gs.DISPLAY[i].h >>= 1; + +#ifdef PREG_LOG + PREG_LOG("GSwrite DISPLAY%d value %8.8lx_%8.8lx: mode = %dx%d %dx%d, magh=%d, magv=%d\n", + i+1, data[1], data[0], + gs.DISPLAY[i].x, gs.DISPLAY[i].y, gs.DISPLAY[i].w, + gs.DISPLAY[i].h, magh, magv); +#endif +} + +void BUSDIRwrite(u32 value) { + gs.BUSDIR = value; +} + +void CALLBACK GSwrite8(u32 mem, u8 value) { +} + +void CALLBACK GSwrite16(u32 mem, u16 value) { +} + +void CALLBACK GSwrite32(u32 mem, u32 value) { + u32 data[2]; + + data[0] = value; data[1] = 0; + switch (mem) { + case 0x12000000: // PMODE + writePMODE(data); + break; + + case 0x12000070: // DISPFB1 + writeDISPFB(data, 0); + break; + + case 0x12000090: // DISPFB2 + writeDISPFB(data, 1); + break; + + case 0x12001000: // CSR +#ifdef PREG_LOG + PREG_LOG("GSwrite32 CSR (%x) value %8.8lx\n", mem, value); +#endif + CSRwrite(value); + break; + + case 0x12001010: // IMR +#ifdef PREG_LOG + PREG_LOG("GSwrite32 IMR (%x) value %8.8lx\n", mem, value); +#endif + IMRwrite(value); + break; + + case 0x12001040: // BUSDIR + BUSDIRwrite(value); + break; + + case 0x12001080: // SIGLBLID +#ifdef PREG_LOG + PREG_LOG("GSwrite32 SIGLBLID (%x) value %8.8lx\n", mem, value); +#endif + gs.SIGLBLID.sigid = value; + break; + + default: +#ifdef PREG_LOG + PREG_LOG("GSwrite32 unknown mem %x value %8.8lx\n", mem, value); +#endif + break; + } +} + +void CALLBACK GSwrite64(u32 mem, u64 value) { + u32 data[2]; + + *(u64*)data = value; + switch (mem) { + case 0x12000000: // PMODE + writePMODE(data); + break; + + case 0x12000010: // SMODE1 + writeSMODE1(data); + break; + + case 0x12000020: // SMODE2 + writeSMODE2(data); + break; + + case 0x12000030: // SRFSH +#ifdef PREG_LOG + PREG_LOG("GSwrite64 SRFSH (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + + case 0x12000040: // SYNCH1 + writeSYNCH1(data); + break; + + case 0x12000050: // SYNCH2 + writeSYNCH2(data); + break; + + case 0x12000060: // SYNCV + writeSYNCHV(data); + break; + + case 0x12000070: // DISPFB1 + writeDISPFB(data, 0); + break; + + case 0x12000080: // DISPLAY1 + writeDISPLAY(data, 0); + break; + + case 0x12000090: // DISPFB2 + writeDISPFB(data, 1); + break; + + case 0x120000A0: // DISPLAY2 + writeDISPLAY(data, 1); + break; + + case 0x120000B0: // EXTBUF +#ifdef PREG_LOG + PREG_LOG("GSwrite64 EXTBUF (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + + case 0x120000C0: // EXTDATA +#ifdef PREG_LOG + PREG_LOG("GSwrite64 EXTDATA (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + + case 0x120000D0: // EXTWRITE +#ifdef PREG_LOG + PREG_LOG("GSwrite64 EXTWRITE (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + + case 0x120000E0: // BGCOLOR +#ifdef PREG_LOG + PREG_LOG("GSwrite64 BGCOLOR (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + + case 0x12001000: // CSR +#ifdef PREG_LOG + PREG_LOG("GSwrite64 CSR (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + CSRwrite(*data); + break; + + case 0x12001010: // IMR +#ifdef PREG_LOG + PREG_LOG("GSwrite64 IMR (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + IMRwrite(*data); + break; + + case 0x12001040: // BUSDIR + BUSDIRwrite(*data); + break; + + case 0x12001080: // SIGLBLID +#ifdef PREG_LOG + PREG_LOG("GSwrite64 SIGLBLID (%x) value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + gs.SIGLBLID.sigid = data[0]; + gs.SIGLBLID.lblid = data[1]; + break; + + default: +#ifdef PREG_LOG + PREG_LOG("GSwrite64 unknown mem %x value %8.8lx_%8.8lx\n", mem, *(data+1), *data); +#endif + break; + } +} + +u8 CALLBACK GSread8(u32 mem) { + u8 ret; + + ret = GSread32(mem & ~3) >> ((mem & 3) * 8); +/* switch (mem) { + case 0x12001000: // CSR + ret = gs.interlace << 13; + ret|= gs.CSRr; + return ret; + + case 0x12001080: // SIGLBLID + ret = gs.SIGLBLID.sigid; + break; + + default: + ret = 0; + break; + }*/ + +#ifdef PREG_LOG + PREG_LOG("GSread8 mem %x ret %8.8lx\n", mem, ret); +#endif + return ret; +} + +u16 CALLBACK GSread16(u32 mem) { + u16 ret; + + ret = GSread32(mem & ~3) >> ((mem & 3) * 8); +/* switch (mem) { + case 0x12001000: // CSR + ret = gs.interlace << 13; + ret|= gs.CSRr; + return ret; + + case 0x12001080: // SIGLBLID + ret = gs.SIGLBLID.sigid; + break; + + default: + ret = 0; + break; + }*/ + +#ifdef PREG_LOG + PREG_LOG("GSread16 mem %x ret %8.8lx\n", mem, ret); +#endif + return ret; +} + +u32 CALLBACK GSread32(u32 mem) { + u32 ret; + + switch (mem) { + case 0x12001000: // CSR +// gs.interlace = 1 - gs.interlace; + ret = gs.interlace << 13; + ret|= gs.CSRr; + return ret; + + case 0x12001080: // SIGLBLID + ret = gs.SIGLBLID.sigid; + break; + + default: + ret = 0; + break; + } + +#ifdef PREG_LOG + PREG_LOG("GSread32 mem %x ret %8.8lx\n", mem, ret); +#endif + return ret; +} + +u64 CALLBACK GSread64(u32 mem) { + u64 ret; + + switch (mem) { + case 0x12000400: // ??? +// gs.interlace = 1 - gs.interlace; + ret = gs.interlace << 13; + break; + + case 0x12001000: // CSR +// gs.interlace = 1 - gs.interlace; + ret = gs.interlace << 13; + ret|= gs.CSRr; + return ret; + + case 0x12001080: // SIGLBLID + ret = (u64)gs.SIGLBLID.sigid | + ((u64)gs.SIGLBLID.lblid << 32); + break; + + default: + ret = 0; + break; + } +#ifdef PREG_LOG + PREG_LOG("GSread64 mem %x ret %8.8lx_%8.8lx\n", mem, (u32)(ret>>32), (u32)ret); +#endif + return ret; +} + + +void primWrite(u32 *data) { + if (data[1] || data[0] & ~0x3ff) { +#ifdef WARN_LOG + WARN_LOG("warning: unknown bits in prim %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + } + + prim->prim = (data[0] ) & 0x7; + if (gs.prac == 0) return; +// prim->prim = (data[0] ) & 0x7; + prim->iip = (data[0] >> 3) & 0x1; + prim->tme = (data[0] >> 4) & 0x1; + prim->fge = (data[0] >> 5) & 0x1; + prim->abe = (data[0] >> 6) & 0x1; + prim->aa1 = (data[0] >> 7) & 0x1; + prim->fst = (data[0] >> 8) & 0x1; + prim->ctxt = (data[0] >> 9) & 0x1; + prim->fix = (data[0] >> 10) & 0x1; + gsSetCtxt(prim->ctxt); + gs.primC = 0; + +#ifdef GREG_LOG + GREG_LOG("prim %8.8lx_%8.8lx prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x\n", + data[1], data[0], prim->prim, prim->iip, prim->tme, prim->fge, prim->abe, prim->aa1, prim->fst, prim->ctxt, prim->fix); +#endif +} + +void tex0Write(int i, u32 *data) { + gs._tex0[i].tbp0 = (data[0] & 0x3fff); + gs._tex0[i].tbw = ((data[0] >> 14) & 0x3f) * 64; + gs._tex0[i].psm = (data[0] >> 20) & 0x3f; + gs._tex0[i].tw = (data[0] >> 26) & 0xf; + if (gs._tex0[i].tw > 10) gs._tex0[i].tw = 10; + gs._tex0[i].tw = (int)pow(2, (double)gs._tex0[i].tw); + gs._tex0[i].th = ((data[0] >> 30) & 0x3) | ((data[1] & 0x3) << 2); + if (gs._tex0[i].th > 10) gs._tex0[i].th = 10; + gs._tex0[i].th = (int)pow(2, (double)gs._tex0[i].th); + gs._tex0[i].tcc = (data[1] >> 2) & 0x1; + gs._tex0[i].tfx = (data[1] >> 3) & 0x3; + gs._tex0[i].cbp = ((data[1] >> 5) & 0x3fff); + gs._tex0[i].cpsm = (data[1] >> 19) & 0xf; + gs._tex0[i].csm = (data[1] >> 23) & 0x1; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("tex0_%d %8.8lx_%8.8lx tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d\n", + i+1, data[1], data[0], + gs._tex0[i].tbp0, gs._tex0[i].tbw, gs._tex0[i].psm, gs._tex0[i].tw, + gs._tex0[i].th, gs._tex0[i].tcc, gs._tex0[i].tfx, gs._tex0[i].cbp, + gs._tex0[i].cpsm, gs._tex0[i].csm); +#endif + +/* if (conf.log) { + SetTexture(); + DumpTexture(); + }*/ + if (gs._tex0[i].tbw == 0) gs._tex0[i].tbw = 64; +} + +void frameWrite(int i, u32 *data) { + gs._gsfb[i].fbp = ((data[0] ) & 0x1ff) * 32; + gs._gsfb[i].fbw = ((data[0] >> 16) & 0x3f) * 64; + gs._gsfb[i].psm = (data[0] >> 24) & 0x3f; + gs._gsfb[i].fbm = data[1]; + if (gs._gsfb[i].fbw > 0) gs._gsfb[i].fbh = (1024*1024) / gs._gsfb[i].fbw; + else gs._gsfb[i].fbh = 1024*1024; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("frame_%d %8.8lx_%8.8lx: fbp=0x%x fbw=%d psm=0x%x fbm=0x%x\n", + i+1, data[1], data[0], + gs._gsfb[i].fbp, gs._gsfb[i].fbw, gs._gsfb[i].psm, gs._gsfb[i].fbm); +#endif +} + +void testWrite(int i, u32 *data) { + gs._test[i].ate = (data[0] ) & 0x1; + gs._test[i].atst = (data[0] >> 1) & 0x7; + gs._test[i].aref = (data[0] >> 4) & 0xff; + gs._test[i].afail = (data[0] >> 12) & 0x3; + gs._test[i].date = (data[0] >> 14) & 0x1; + gs._test[i].datm = (data[0] >> 15) & 0x1; + gs._test[i].zte = (data[0] >> 16) & 0x1; + gs._test[i].ztst = (data[0] >> 17) & 0x3; + +#ifdef GREG_LOG + GREG_LOG("test_%d %8.8lx_%8.8lx: ate=%x atst=%x aref=%x afail=%x date=%x datm%x zte=%x ztst=%x\n", + i+1, data[1], data[0], + gs._test[0].ate, gs._test[0].atst, gs._test[0].aref, + gs._test[0].afail, gs._test[0].date, gs._test[0].datm, + gs._test[0].zte, gs._test[0].ztst); +#endif +} + +void clampWrite(int i, u32 *data) { + gs._clamp[i].wms = (data[0] ) & 0x2; + gs._clamp[i].wmt = (data[0] >> 2) & 0x2; + gs._clamp[i].minu = (data[0] >> 4) & 0x3ff; + gs._clamp[i].maxu = (data[0] >> 14) & 0x3ff; + gs._clamp[i].minv =((data[0] >> 24) & 0xff) | ((data[1] & 0x3) << 8); + gs._clamp[i].maxv = (data[1] >> 2) & 0x3ff; + +#ifdef GREG_LOG + GREG_LOG("clamp_%d %8.8lx_%8.8lx: wms=%x wmt=%x minu=%x maxu=%x minv=%x maxv=%x\n", i, data[1], data[0], + gs._clamp[i].wms, gs._clamp[i].wmt, + gs._clamp[i].minu, gs._clamp[i].maxu, + gs._clamp[i].minv, gs._clamp[i].maxv); +#endif +} + +/* + * GSwrite: 128bit wide + */ +void GSwrite(u32 *data, int reg) { + int i; + + switch (reg) { + case 0x00: // prim + primWrite(data); + break; + + case 0x01: // rgbaq + gs.gsvertex[gs.primC].rgba = data[0]; + gs.gsvertex[gs.primC].q = data[1]; + gs.rgba = data[0]; + gs.q = data[1]; + +#ifdef GREG_LOG + GREG_LOG("rgbaq %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x02: // st + gs.gsvertex[gs.primC].s = data[0]; + gs.gsvertex[gs.primC].t = data[1]; + + +#ifdef GREG_LOG + GREG_LOG("st %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x03: // uv + gs.gsvertex[gs.primC].u = (data[0] >> 4) & 0x7ff; + gs.gsvertex[gs.primC].v = (data[0] >> (16+4)) & 0x7ff; + +#ifdef GREG_LOG + GREG_LOG("uv %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x04: // xyzf2 + gs.gsvertex[gs.primC].x = (data[0] >> 4) & 0xfff; + gs.gsvertex[gs.primC].y = (data[0] >> (16+4)) & 0xfff; + gs.gsvertex[gs.primC].z = data[1] & 0xffffff; + gs.gsvertex[gs.primC].f = data[1] >> 24; + gs.primC++; + +#ifdef GREG_LOG + GREG_LOG("xyzf2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + + if (gs.primC >= primTableC[prim->prim]) { +#ifdef GREG_LOG + GREG_LOG("prim %x\n", prim->prim); +#endif + primTable[prim->prim](gs.gsvertex); + ppf++; + } + break; + + case 0x05: // xyz2 + gs.gsvertex[gs.primC].x = (data[0] >> 4) & 0xfff; + gs.gsvertex[gs.primC].y = (data[0] >> (16+4)) & 0xfff; + gs.gsvertex[gs.primC].z = data[1]; + gs.primC++; + +#ifdef GREG_LOG + GREG_LOG("xyz2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + + if (gs.primC >= primTableC[prim->prim]) { +#ifdef GREG_LOG + GREG_LOG("prim %x\n", prim->prim); +#endif + primTable[prim->prim](gs.gsvertex); + ppf++; + } + break; + + case 0x06: // tex0_1 + tex0Write(0, data); + break; + + case 0x07: // tex0_2 + tex0Write(1, data); + break; + + case 0x08: // clamp_1 + clampWrite(0, data); + break; + + case 0x09: // clamp_2 + clampWrite(1, data); + break; + + case 0x0a: // fog + gs.fogf = data[1] >> 24; + +#ifdef GREG_LOG + GREG_LOG("fogH %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x0c: // xyzf3 + gs.gsvertex[gs.primC].x = (data[0] >> 4) & 0xfff; + gs.gsvertex[gs.primC].y = (data[0] >> (16+4)) & 0xfff; + gs.gsvertex[gs.primC].z = data[1] & 0xffffff; + gs.gsvertex[gs.primC].f = data[1] >> 24; + gs.primC++; + +#ifdef GREG_LOG + GREG_LOG("xyzf3 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + if (gs.primC >= primTableC[prim->prim]) { + primTable[prim->prim](NULL); + } + break; + + case 0x0d: // xyz3 + gs.gsvertex[gs.primC].x = (data[0] >> 4) & 0xfff; + gs.gsvertex[gs.primC].y = (data[0] >> (16+4)) & 0xfff; + gs.gsvertex[gs.primC].z = data[1]; + gs.primC++; + +#ifdef GREG_LOG + GREG_LOG("xyz3 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + if (gs.primC >= primTableC[prim->prim]) { + primTable[prim->prim](NULL); + } + break; + + case 0x14: // tex1_1 + gs._tex1[0].lcm = (data[0] ) & 0x1; + gs._tex1[0].mxl = (data[0] >> 2) & 0x7; + gs._tex1[0].mmag = (data[0] >> 5) & 0x1; + gs._tex1[0].mmin = (data[0] >> 6) & 0x7; + gs._tex1[0].mtba = (data[0] >> 9) & 0x1; + gs._tex1[0].l = (data[0] >> 19) & 0x3; + gs._tex1[0].k = (data[1] >> 4) & 0xff; + +#ifdef GREG_LOG + GREG_LOG("tex1_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x15: // tex1_2 + gs._tex1[1].lcm = (data[0] ) & 0x1; + gs._tex1[1].mxl = (data[0] >> 2) & 0x7; + gs._tex1[1].mmag = (data[0] >> 5) & 0x1; + gs._tex1[1].mmin = (data[0] >> 6) & 0x7; + gs._tex1[1].mtba = (data[0] >> 9) & 0x1; + gs._tex1[1].l = (data[0] >> 19) & 0x3; + gs._tex1[1].k = (data[1] >> 4) & 0xff; + +#ifdef GREG_LOG + GREG_LOG("tex1_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x16: // tex2_1 + gs._tex2[0].psm = (data[0] >> 20) & 0x3f; + gs._tex2[0].cbp = (data[1] >> 5) & 0x3fff; + gs._tex2[0].cpsm = (data[1] >> 19) & 0xf; + gs._tex2[0].csm = (data[1] >> 23) & 0x1; + gs._tex2[0].csa = (data[1] >> 24) & 0x1f; + gs._tex2[0].cld = (data[1] >> 29) & 0x7; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("tex2_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x17: // tex2_2 + gs._tex2[1].psm = (data[0] >> 20) & 0x3f; + gs._tex2[1].cbp = (data[1] >> 5) & 0x3fff; + gs._tex2[1].cpsm = (data[1] >> 19) & 0xf; + gs._tex2[1].csm = (data[1] >> 23) & 0x1; + gs._tex2[1].csa = (data[1] >> 24) & 0x1f; + gs._tex2[1].cld = (data[1] >> 29) & 0x7; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("tex2_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x18: // xyoffset_1 + gs._offset[0].x = (data[0] >> 4) & 0xfff; + gs._offset[0].y = (data[1] >> 4) & 0xfff; + +#ifdef GREG_LOG + GREG_LOG("xyoffset_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x19: // xyoffset_2 + gs._offset[1].x = (data[0] >> 4) & 0xfff; + gs._offset[1].y = (data[1] >> 4) & 0xfff; + +#ifdef GREG_LOG + GREG_LOG("xyoffset_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x1a: // prmodecont + gs.prac = data[0] & 0x1; + prim = &gs._prim[gs.prac]; + +#ifdef GREG_LOG + GREG_LOG("prmodecont %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x1b: // prmode + if (gs.prac == 1) break; + prim->iip = (data[0] >> 3) & 0x1; + prim->tme = (data[0] >> 4) & 0x1; + prim->fge = (data[0] >> 5) & 0x1; + prim->abe = (data[0] >> 6) & 0x1; + prim->aa1 = (data[0] >> 7) & 0x1; + prim->fst = (data[0] >> 8) & 0x1; + prim->ctxt = (data[0] >> 9) & 0x1; + prim->fix = (data[0] >> 10) & 0x1; + gsSetCtxt(prim->ctxt); + gs.primC = 0; + +#ifdef GREG_LOG + GREG_LOG("prmode %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x1c: // texclut + gs.clut.cbw = ((data[0] ) & 0x3f) * 64; + gs.clut.cou = ((data[0] >> 6) & 0x3f) * 16; + gs.clut.cov = (data[0] >> 12) & 0x3ff; + +#ifdef GREG_LOG + GREG_LOG("texclut %8.8lx_%8.8lx: cbw=%x, cou=%d, cov=%d\n", + data[1], data[0], gs.clut.cbw, gs.clut.cou, gs.clut.cov); +#endif + break; + + case 0x22: // scanmsk + gs.smask = data[0] & 0x3; + +#ifdef GREG_LOG + GREG_LOG("scanmsk %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x34: // miptbp1_1 + gs._miptbp0[0].tbp[0] = (data[0] ) & 0x3fff; + gs._miptbp0[0].tbw[0] = (data[0] >> 14) & 0x3f; + gs._miptbp0[0].tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + gs._miptbp0[0].tbw[1] = (data[1] >> 2) & 0x3f; + gs._miptbp0[0].tbp[2] = (data[1] >> 8) & 0x3fff; + gs._miptbp0[0].tbw[2] = (data[1] >> 22) & 0x3f; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("miptbp1_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x35: // miptbp1_2 + gs._miptbp0[1].tbp[0] = (data[0] ) & 0x3fff; + gs._miptbp0[1].tbw[0] = (data[0] >> 14) & 0x3f; + gs._miptbp0[1].tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + gs._miptbp0[1].tbw[1] = (data[1] >> 2) & 0x3f; + gs._miptbp0[1].tbp[2] = (data[1] >> 8) & 0x3fff; + gs._miptbp0[1].tbw[2] = (data[1] >> 22) & 0x3f; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("miptbp1_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x36: // miptbp2_1 + gs._miptbp1[0].tbp[0] = (data[0] ) & 0x3fff; + gs._miptbp1[0].tbw[0] = (data[0] >> 14) & 0x3f; + gs._miptbp1[0].tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + gs._miptbp1[0].tbw[1] = (data[1] >> 2) & 0x3f; + gs._miptbp1[0].tbp[2] = (data[1] >> 8) & 0x3fff; + gs._miptbp1[0].tbw[2] = (data[1] >> 22) & 0x3f; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("miptbp2_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x37: // miptbp2_2 + gs._miptbp1[1].tbp[0] = (data[0] ) & 0x3fff; + gs._miptbp1[1].tbw[0] = (data[0] >> 14) & 0x3f; + gs._miptbp1[1].tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + gs._miptbp1[1].tbw[1] = (data[1] >> 2) & 0x3f; + gs._miptbp1[1].tbp[2] = (data[1] >> 8) & 0x3fff; + gs._miptbp1[1].tbw[2] = (data[1] >> 22) & 0x3f; + gsSetCtxt(prim->ctxt); + +#ifdef GREG_LOG + GREG_LOG("miptbp2_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x3b: // texa + gs.texa.ta[0] = data[0] & 0xff; + gs.texa.aem = (data[0] >> 15) & 0x1; + gs.texa.ta[1] = data[1] & 0xff; + +#ifdef GREG_LOG + GREG_LOG("texa %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x3d: // fogcol + gs.fogcol = data[0] & 0xffffff; + +#ifdef GREG_LOG + GREG_LOG("fogcol %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x3f: // texflush +#ifdef GREG_LOG + GREG_LOG("texflush %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x40: // scissor_1 + gs._scissor[0].x0 = (data[0] ) & 0x7ff; + gs._scissor[0].x1 = (data[0] >> 16) & 0x7ff; + gs._scissor[0].y0 = (data[1] ) & 0x7ff; + gs._scissor[0].y1 = (data[1] >> 16) & 0x7ff; +#ifdef GREG_LOG + GREG_LOG("scissor_1 %8.8lx_%8.8lx: %dx%d - %dx%d\n", + data[1], data[0], + gs._scissor[0].x0, gs._scissor[0].y0, gs._scissor[0].x1, gs._scissor[0].y1); +#endif + break; + + case 0x41: // scissor_2 + gs._scissor[1].x0 = (data[0] ) & 0x7ff; + gs._scissor[1].x1 = (data[0] >> 16) & 0x7ff; + gs._scissor[1].y0 = (data[1] ) & 0x7ff; + gs._scissor[1].y1 = (data[1] >> 16) & 0x7ff; +#ifdef GREG_LOG + GREG_LOG("scissor_2 %8.8lx_%8.8lx: %dx%d - %dx%d\n", + data[1], data[0], + gs._scissor[1].x0, gs._scissor[1].y0, gs._scissor[1].x1, gs._scissor[1].y1); +#endif + break; + + case 0x42: // alpha_1 + gs._alpha[0].a = (data[0] ) & 0x3; + gs._alpha[0].b = (data[0] >> 2) & 0x3; + gs._alpha[0].c = (data[0] >> 4) & 0x3; + gs._alpha[0].d = (data[0] >> 6) & 0x3; + gs._alpha[0].fix = (data[1] ) & 0xff; + +#ifdef GREG_LOG + GREG_LOG("alpha_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x43: // alpha_2 + gs._alpha[1].a = (data[0] ) & 0x3; + gs._alpha[1].b = (data[0] >> 2) & 0x3; + gs._alpha[1].c = (data[0] >> 4) & 0x3; + gs._alpha[1].d = (data[0] >> 6) & 0x3; + gs._alpha[1].fix = (data[1] ) & 0xff; + +#ifdef GREG_LOG + GREG_LOG("alpha_2 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x44: // dimx +#ifdef GREG_LOG + GREG_LOG("dimx %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x45: // dthe + gs.dthe = data[0] & 0x1; + +#ifdef GREG_LOG + GREG_LOG("dthe %8.8lx_%8.8lx: dthe = %x\n", data[1], data[0], gs.dthe); +#endif + break; + + case 0x46: // colclamp + gs.colclamp = data[0] & 0x1; + +#ifdef GREG_LOG + GREG_LOG("colclamp %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x47: // test_1 + testWrite(0, data); + break; + + case 0x48: // test_2 + testWrite(1, data); + break; + + case 0x49: // pabe + gs.pabe = *data & 0x1; + +#ifdef GREG_LOG + GREG_LOG("pabe %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x4a: // fba_1 + gs._fba[0].fba = *data & 0x1; + +#ifdef GREG_LOG + GREG_LOG("fba_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x4b: // fba_2 + gs._fba[1].fba = *data & 0x1; + +#ifdef GREG_LOG + GREG_LOG("fba_1 %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x4c: // frame_1 + frameWrite(0, data); + break; + + case 0x4d: // frame_2 + frameWrite(1, data); + break; + + case 0x4e: // zbuf_1 + gs._zbuf[0].zbp = (data[0] & 0x1ff) * 32; + gs._zbuf[0].psm = (data[0] >> 24) & 0xf; + gs._zbuf[0].zmsk = data[1] & 0x1; + +#ifdef GREG_LOG + GREG_LOG("zbuf_1 %8.8lx_%8.8lx: zbp=%x psm=%x zmsk=%x\n", + data[1], data[0], + gs._zbuf[0].zbp, gs._zbuf[0].psm, gs._zbuf[0].zmsk); +#endif + break; + + case 0x4f: // zbuf_2 + gs._zbuf[1].zbp = (data[0] & 0x1ff) * 32; + gs._zbuf[1].psm = (data[0] >> 24) & 0xf; + gs._zbuf[1].zmsk = data[1] & 0x1; + +#ifdef GREG_LOG + GREG_LOG("zbuf_2 %8.8lx_%8.8lx: zbp=%x psm=%x zmsk=%x\n", + data[1], data[0], + gs._zbuf[1].zbp, gs._zbuf[1].psm, gs._zbuf[1].zmsk); +#endif + break; + + case 0x50: // bitbltbuf + gs.srcbuf.bp = ((data[0] ) & 0x3fff);// * 64; + gs.srcbuf.bw = ((data[0] >> 16) & 0x3f) * 64; + gs.srcbuf.psm = (data[0] >> 24) & 0x3f; + if (gs.srcbuf.bw > 0) gs.srcbuf.bh = (1024*1024) / gs.srcbuf.bw; + else gs.srcbuf.bh = 1024*1024; + gs.dstbuf.bp = ((data[1] ) & 0x3fff);// * 64; + gs.dstbuf.bw = ((data[1] >> 14) & 0x1ff) * 16; + gs.dstbuf.psm = (data[1] >> 24) & 0x3f; + if (gs.dstbuf.bw > 0) gs.dstbuf.bh = (1024*1024) / gs.dstbuf.bw; + else gs.dstbuf.bh = 1024*1024; + +#ifdef GREG_LOG + GREG_LOG("bitbltbuf %8.8lx_%8.8lx: sbp = %x, sbw = %d, spsm = %x, sbh = %d; dbp = %x, dbw = %d, dpsm = %x, dbh = %d\n", data[1], data[0], + gs.srcbuf.bp, gs.srcbuf.bw, gs.srcbuf.psm, gs.srcbuf.bh, + gs.dstbuf.bp, gs.dstbuf.bw, gs.dstbuf.psm, gs.dstbuf.bh); +#endif + + if (gs.dstbuf.bw == 0) gs.dstbuf.bw = 64; + break; + + case 0x51: // trxpos + gs.trxpos.sx = (data[0] ) & 0x7ff; + gs.trxpos.sy = (data[0] >> 16) & 0x7ff; + gs.trxpos.dx = (data[1] ) & 0x7ff; + gs.trxpos.dy = (data[1] >> 16) & 0x7ff; + gs.trxpos.dir = (data[1] >> 27) & 0x3; +#ifdef GREG_LOG + GREG_LOG("trxpos %8.8lx_%8.8lx: %dx%d %dx%d : dir=%d\n", data[1], data[0], + gs.trxpos.sx, gs.trxpos.sy, gs.trxpos.dx, gs.trxpos.dy, gs.trxpos.dir); +#endif + break; + + case 0x52: // trxreg + gs.imageW = data[0]; + gs.imageH = data[1]; + +#ifdef GREG_LOG + GREG_LOG("trxreg %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + break; + + case 0x53: // trxdir + gs.imageTransfer = data[0] & 0x3; + +#ifdef GREG_LOG + GREG_LOG("trxdir %8.8lx_%8.8lx: gs.imageTransfer = %x\n", data[1], data[0], gs.imageTransfer); +#endif + if (gs.imageTransfer == 0x2) { +#ifdef GREG_LOG + GREG_LOG("moveImage %dx%d %dx%d %dx%d (dir=%d)\n", + gs.trxpos.sx, gs.trxpos.sy, gs.trxpos.dx, gs.trxpos.dy, gs.imageW, gs.imageH, gs.trxpos.dir); +#endif + FBmoveImage(); + break; + } + if (gs.imageTransfer == 1) { +#ifdef GREG_LOG +// GREG_LOG("gs.imageTransferSrc size %lx, %dx%d %dx%d (psm=%x, bp=%x)\n", +// gs.gtag.nloop, gs.trxpos.sx, gs.trxpos.sy, gs.imageW, gs.imageH, gs.srcbuf.psm, gs.srcbuf.bp); +#endif + gs.imageX = gs.trxpos.sx; + gs.imageY = gs.trxpos.sy; + } else { + gs.imageX = gs.trxpos.dx; + gs.imageY = gs.trxpos.dy; + } + + break; + + case 0x60: // signal +#ifdef GREG_LOG + GREG_LOG("signal %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + for (i=0; i<32; i++) { + if (data[1] & (1< +#include +#include + +#include +#include +#include +//#include + +#include "GS.h" +#include "Draw.h" +#include "Rec.h" +#include "scale2x.h" +#if defined(__i386__) || defined(__x86_64__) +#include "ix86.h" +#endif + +SDL_Surface *surf1x; +SDL_Surface *surf2x; +SDL_Surface *surf; +SDL_SysWMinfo info; +//FPSmanager fps; +char gsmsg[256]; +u32 gsmsgscount; +u32 gsmsgcount; + +void DXclearScr() { + SDL_FillRect(surf, NULL, 0); +} + +s32 DXopen() { +#ifdef __LINUX__ + int screen; + int w, h; +#endif + + if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; + + surf = SDL_SetVideoMode(cmode->width, cmode->height, 0, conf.fullscreen ? SDL_FULLSCREEN | SDL_HWSURFACE : SDL_HWSURFACE); + if (surf == NULL) return -1; + + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info) == 0) return -1; + +#ifdef __LINUX__ + info.info.x11.lock_func(); + screen = DefaultScreen(info.info.x11.display); + w = DisplayWidth(info.info.x11.display, screen); + h = DisplayHeight(info.info.x11.display, screen); + XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, + cmode->width < w ? (w - cmode->width) / 2 : 0, + cmode->height < h ? (h - cmode->height) / 2 : 0); + info.info.x11.unlock_func(); +#endif + + SDL_WM_SetCaption(GStitle, NULL); + + SETScrBlit(surf->format->BitsPerPixel); + DXclearScr(); + + surf1x = surf2x = NULL; + +// SDL_initFramerate(&fps); +// SDL_setFramerate(&fps, 60); + +#ifdef __WIN32__ + return (s32)info.window; +#else + return (s32)info.info.x11.display; +#endif +} + +void DXclose() { + SDL_Quit(); +} + +void DXcreateSurface1x(int w, int h) { + if (surf1x != NULL) { + if ((w == surf1x->w && + h == surf1x->h)) + return; + + SDL_FreeSurface(surf1x); surf1x = NULL; + } + +/* if (surf->flags & SDL_HWSURFACE) { + surf1x = SDL_CreateRGBSurface(SDL_HWSURFACE, w, h, + 0, 0, 0, 0, 0); + if (surf1x == NULL) printf("Error allocating video memory surface, trying with normal memory\n"); + }*/ + if (surf1x == NULL) { + surf1x = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, + surf->format->BitsPerPixel, surf->format->Rmask, + surf->format->Gmask, surf->format->Bmask, + surf->format->Amask); + if (surf1x == NULL) { + SysMessage("Error allocating surface\n"); + exit(1); + } + } +} + +void DXcreateSurface2x(int w, int h) { + if (surf2x != NULL) { + if ((w == surf2x->w && + h == surf2x->h)) + return; + + SDL_FreeSurface(surf2x); surf2x = NULL; + } + +/* if (surf->flags & SDL_HWSURFACE) { + surf2x = SDL_CreateRGBSurface(SDL_HWSURFACE, w*2, h*2, + 0, 0, 0, 0, 0); + if (surf2x == NULL) printf("Error allocating video memory surface, trying with normal memory\n"); + }*/ + if (surf2x == NULL) { + surf2x = SDL_CreateRGBSurface(SDL_SWSURFACE, w*2, h*2, + surf->format->BitsPerPixel, surf->format->Rmask, + surf->format->Gmask, surf->format->Bmask, + surf->format->Amask); + if (surf2x == NULL) conf.filter = 0; + } +} + +void DXblit(int y) { + if (conf.filter) { + SDL_Rect dst; + + if (surf1x == NULL) return; + + SDL_LockSurface(surf1x); + ScrBlit(surf1x, 0); + SDL_UnlockSurface(surf1x); + + scale2x(surf1x, surf2x); + + dst.x = 0; dst.y = y; + dst.w = surf->w; dst.h = surf->h - dst.y; + SDL_SoftStretch(surf2x, NULL, surf, &dst); + } else { + SDL_LockSurface(surf); + ScrBlit(surf, y); + SDL_UnlockSurface(surf); +/* SDL_LockSurface(surf1x); + + ScrBlit(surf1x); + + dst.x = 0; dst.y = y; + dst.w = surf->w; dst.h = surf->h - dst.y; +// SDL_BlitSurface(surf1x, NULL, surf, NULL); + SDL_LockSurface(surf); + SDL_SoftStretch(surf1x, NULL, surf, &dst); + SDL_UnlockSurface(surf); + + SDL_UnlockSurface(surf1x);*/ + } +} + +int DXsetGSmode(int w, int h) { + if (w <= 0 || h <= 0) return 0; + + DXcreateSurface1x(w, h); + if (conf.filter) DXcreateSurface2x(w, h); + return 0; +} + +void DXupdate() { + SDL_Rect rect; + static int to; + static int fpsc, fc; + static u64 cto; + int ticks; + u64 cticks; + int i; +#if defined(__i386__) || defined(__x86_64__) + u64 tick; + + tick = GetCPUTick(); +#endif + + fc++; + + if (conf.fps || conf.frameskip) { + ticks = SDL_GetTicks(); + fpsc = ticks - to; + to = ticks; + } +#if defined(__i386__) || defined(__x86_64__) + cticks = GetCPUTick() - cto; + cto = GetCPUTick(); +#endif + +/* if (conf.frameskip) { + if ((fpscount % 3) == 0) { + norender = 1; + } else if (norender) { + norender = 0; + } + }*/ + +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif + rect.x = 0; rect.y = 0; + rect.w = cmode->width; + rect.h = 15; + if (conf.fps || norender) { + char title[256]; + char tmp[256]; + + if (fpspos < 0) fpspos = 0; +#ifndef GS_LOG + if (fpspos > 5) fpspos = 5; +#else + if (fpspos > 6) fpspos = 6; +#endif + switch (fpspos) { + case 0: // NoRender + sprintf(tmp, "NoRender %s", norender == 1 ? "On" : "Off"); + break; + case 1: // WireFrame + sprintf(tmp, "WireFrame %s", wireframe == 1 ? "On" : "Off"); + break; + case 2: // ShowFullVRam + sprintf(tmp, "ShowFullVRam %s", showfullvram == 1 ? "On" : "Off"); + break; + case 3: // FrameSkip + sprintf(tmp, "Frameskip %s", conf.frameskip == 1 ? "On" : "Off"); + break; + case 4: // GSmode + if (gs.PMODE.en[0] && gs.PMODE.en[1]) { + sprintf(tmp, "GSmode %dx%d CRT1 %dx%d CRT2 %dx%d", surf1x->w, surf1x->h, gs.DISPLAY[0].w,gs.DISPLAY[0].h, gs.DISPLAY[1].w, gs.DISPLAY[1].h); + } else + if (gs.PMODE.en[0]) { + sprintf(tmp, "GSmode %dx%d CRT1 %dx%d", surf1x->w, surf1x->h, gs.DISPLAY[0].w,gs.DISPLAY[0].h); + } else { + sprintf(tmp, "GSmode %dx%d CRT2 %dx%d", surf1x->w, surf1x->h, gs.DISPLAY[1].w, gs.DISPLAY[1].h); + } + break; + case 5: // DumpTexts + sprintf(tmp, "DumpTexts %s", conf.dumptexts == 1 ? "On" : "Off"); + break; +#ifdef GS_LOG + case 6: // Log + sprintf(tmp, "Log %s", conf.log == 1 ? "On" : "Off"); + break; +#endif + } + if (fpspress) { + switch (fpspos) { + case 0: + norender = 1 - norender; + break; + case 1: + wireframe = 1 - wireframe; + break; + case 2: + showfullvram = 1 - showfullvram; + break; + case 3: + conf.frameskip = 1 - conf.frameskip; + norender = 0; + break; + case 4: + break; + case 5: + conf.dumptexts = 1 - conf.dumptexts; + break; +#ifdef GS_LOG + case 6: + conf.log = 1 - conf.log; + break; +#endif + } + fpspress = 0; + } + + if (cmode->width <= 320) { + sprintf(title, "FPS %.2f; %s; FC %d", 1000.0 / fpsc, tmp, fc); + + SDL_FillRect(surf, &rect, 0); + stringRGBA(surf, 4, rect.y+4, title, 0, 0xff, 0, 0xff); + rect.y+= 15; + + sprintf(title, "PPF %d; BPF %d; CPU %d%% - TICKS %lld", ppf, bpf, (u32)((gsticks*100)/cticks), cticks); + + SDL_FillRect(surf, &rect, 0); + stringRGBA(surf, 4, rect.y+4, title, 0, 0xff, 0, 0xff); + rect.y+= 15; + } else { + sprintf(title, "FPS %.2f; %s; FC %d; PPF %d; BPF %d; CPU %d%% - TICKS %lld", 1000.0 / fpsc, tmp, fc, ppf, bpf, (u32)((gsticks*100)/cticks), cticks); + + SDL_FillRect(surf, &rect, 0); + stringRGBA(surf, 4, rect.y+4, title, 0, 0xff, 0, 0xff); + rect.y+= 15; + } + } + gsticks = 0; + +#if defined(__i386__) || defined(__x86_64__) + tick = GetCPUTick(); +#endif + if (gsmsg[0]) { + char str[256]; + char *s = gsmsg; + int len = strlen(gsmsg); + + while (len>0) { + for (i=0; i<255; i++) { + if (len <= 0) break; + if (*s == '\n' || *s == '\0') { s++; break; } + str[i] = *s++; + } + if (i == 0) break; + str[i] = 0; + + SDL_FillRect(surf, &rect, 0); + stringRGBA(surf, 4, rect.y+4, str, 0, 0xff, 0, 0xff); + rect.y+= 15; + } + + if ((SDL_GetTicks() - gsmsgscount) >= gsmsgcount) gsmsg[0] = 0; + } + + if (norender == 0) { + DXblit(rect.y); + } + + if (conf.record) { + SDL_LockSurface(surf); + recFrame(surf->pixels, surf->pitch, surf->format->BitsPerPixel); + SDL_UnlockSurface(surf); + } + SDL_UpdateRect(surf, 0, 0, 0, 0); +#ifdef __WIN32__ + SDL_PumpEvents(); +#endif +#if defined(__i386__) || defined(__x86_64__) + gsticks+= GetCPUTick() - tick; +#endif +} + +int DXgetModes() { + SDL_Rect **rects; + int i; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; + + memset(modes, 0, sizeof(modes)); + rects = SDL_ListModes(NULL, SDL_FULLSCREEN); + if (rects == NULL) return -1; + + for (i=0; i<64; i++) { + if (rects[i] == NULL) break; + modes[i].width = rects[i]->w; + modes[i].height = rects[i]->h; + } + + SDL_Quit(); + + return i; +} + +void CALLBACK GSprintf(int timeout, char *fmt, ...) { + va_list list; + + va_start(list,fmt); + vsprintf(gsmsg,fmt,list); + va_end(list); + gsmsgscount = SDL_GetTicks(); + gsmsgcount = timeout*1000; +} + +void CALLBACK GSgetDriverInfo(GSdriverInfo *info) { + strcpy(info->name, "sdl"); + info->common = surf; +} diff --git a/plugins/gs/GSsoft/Src/SDL_gfxPrimitives.c b/plugins/gs/GSsoft/Src/SDL_gfxPrimitives.c new file mode 100644 index 0000000..8a0d3fa --- /dev/null +++ b/plugins/gs/GSsoft/Src/SDL_gfxPrimitives.c @@ -0,0 +1,2561 @@ +/* + + SDL_gfxPrimitives - Graphics primitives for SDL surfaces + + Note: Does not lock or update surfaces. Implement in calling routine. + +*/ + +#include +#include +#include +#include + +#include + +#include "SDL_gfxPrimitives.h" +#include "SDL_gfxPrimitives_font.h" + +/* -===================- */ + +/* Define this flag to use surface blits for alpha blended drawing. */ +/* This is usually slower that direct surface calculations. */ + +#undef SURFACE_ALPHA_PIXEL + +/* ----- Defines for pixel clipping tests */ + +#define clip_xmin(surface) surface->clip_rect.x +#define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1 +#define clip_ymin(surface) surface->clip_rect.y +#define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1 + +/* ----- Pixel - fast, no blending, no locking, clipping */ + +int fastPixelColorNolock (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) +{ + int bpp; + Uint8 *p; + + /* Honor clipping setup at pixel level */ + if ( (x >= clip_xmin(dst)) && + (x <= clip_xmax(dst)) && + (y >= clip_ymin(dst)) && + (y <= clip_ymax(dst)) ) { + + /* Get destination format */ + bpp = dst->format->BytesPerPixel; + p = (Uint8 *)dst->pixels + y * dst->pitch + x * bpp; + switch(bpp) { + case 1: + *p = color; + break; + case 2: + *(Uint16 *)p = color; + break; + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (color >> 16) & 0xff; + p[1] = (color >> 8) & 0xff; + p[2] = color & 0xff; + } else { + p[0] = color & 0xff; + p[1] = (color >> 8) & 0xff; + p[2] = (color >> 16) & 0xff; + } + break; + case 4: + *(Uint32 *)p = color; + break; + } /* switch */ + + + } + + return(0); +} + +/* ----- Pixel - fast, no blending, no locking, no clipping */ + +/* (faster but dangerous, make sure we stay in surface bounds) */ + +int fastPixelColorNolockNoclip (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) +{ + int bpp; + Uint8 *p; + + /* Get destination format */ + bpp = dst->format->BytesPerPixel; + p = (Uint8 *)dst->pixels + y * dst->pitch + x * bpp; + switch(bpp) { + case 1: + *p = color; + break; + case 2: + *(Uint16 *)p = color; + break; + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (color >> 16) & 0xff; + p[1] = (color >> 8) & 0xff; + p[2] = color & 0xff; + } else { + p[0] = color & 0xff; + p[1] = (color >> 8) & 0xff; + p[2] = (color >> 16) & 0xff; + } + break; + case 4: + *(Uint32 *)p = color; + break; + } /* switch */ + + return(0); +} + +/* ----- Pixel - fast, no blending, locking, clipping */ + +int fastPixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) +{ + int result; + + /* Lock the surface */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return(-1); + } + } + + result=fastPixelColorNolock (dst,x,y,color); + + /* Unlock surface */ + if ( SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface (dst); + } + + return(result); +} + +/* ----- Pixel - fast, no blending, locking, RGB input */ + +int fastPixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + Uint32 color; + + /* Setup color */ + color=SDL_MapRGBA(dst->format, r, g, b, a); + + /* Draw */ + return(fastPixelColor(dst, x, y, color)); + +} + +/* ----- Pixel - fast, no blending, no locking RGB input */ + +int fastPixelRGBANolock (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + Uint32 color; + + /* Setup color */ + color=SDL_MapRGBA(dst->format, r, g, b, a); + + /* Draw */ + return(fastPixelColorNolock(dst, x, y, color)); +} + +#ifdef SURFACE_ALPHA_PIXEL + +/* ----- Pixel - using single pixel blit with blending enabled if a<255 */ + +static SDL_Surface *gfxPrimitivesSinglePixel=NULL; + +int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) +{ + SDL_Rect srect; + SDL_Rect drect; + int result; + + /* Setup source rectangle for pixel */ + srect.x=0; + srect.y=0; + srect.w=1; + srect.h=1; + + /* Setup destination rectangle for pixel */ + drect.x=x; + drect.y=y; + drect.w=1; + drect.h=1; + + /* Create single pixel in 32bit RGBA format */ + if (gfxPrimitivesSinglePixel==NULL) { + gfxPrimitivesSinglePixel=SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 1, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + } + + /* Draw color into pixel*/ + SDL_FillRect (gfxPrimitivesSinglePixel, &srect, color); + + /* Draw pixel onto destination surface */ + result=SDL_BlitSurface (gfxPrimitivesSinglePixel, &srect, dst, &drect); + + return(result); +} + +#else + +/* PutPixel routine with alpha blending, input color in destination format */ + +int _putPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) +{ + Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask; + Uint32 R,G,B,A = 0; + + if (x>=clip_xmin(surface) && x<=clip_xmax(surface) && y>=clip_ymin(surface) && y<=clip_ymax(surface)) { + + switch (surface->format->BytesPerPixel) { + case 1: { /* Assuming 8-bpp */ + if( alpha == 255 ){ + *((Uint8 *)surface->pixels + y*surface->pitch + x) = color; + } else { + Uint8 *pixel = (Uint8 *)surface->pixels + y*surface->pitch + x; + + Uint8 dR = surface->format->palette->colors[*pixel].r; + Uint8 dG = surface->format->palette->colors[*pixel].g; + Uint8 dB = surface->format->palette->colors[*pixel].b; + Uint8 sR = surface->format->palette->colors[color].r; + Uint8 sG = surface->format->palette->colors[color].g; + Uint8 sB = surface->format->palette->colors[color].b; + + dR = dR + ((sR-dR)*alpha >> 8); + dG = dG + ((sG-dG)*alpha >> 8); + dB = dB + ((sB-dB)*alpha >> 8); + + *pixel = SDL_MapRGB(surface->format, dR, dG, dB); + } + } + break; + + case 2: { /* Probably 15-bpp or 16-bpp */ + if ( alpha == 255 ) { + *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color; + } else { + Uint16 *pixel = (Uint16 *)surface->pixels + y*surface->pitch/2 + x; + Uint32 dc = *pixel; + + R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask; + G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask; + B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask; + if( Amask ) + A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask; + + *pixel= R | G | B | A; + } + } + break; + + case 3: { /* Slow 24-bpp mode, usually not used */ + Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; + Uint8 rshift8=surface->format->Rshift/8; + Uint8 gshift8=surface->format->Gshift/8; + Uint8 bshift8=surface->format->Bshift/8; + Uint8 ashift8=surface->format->Ashift/8; + + + if ( alpha == 255 ) { + *(pix+rshift8) = color>>surface->format->Rshift; + *(pix+gshift8) = color>>surface->format->Gshift; + *(pix+bshift8) = color>>surface->format->Bshift; + *(pix+ashift8) = color>>surface->format->Ashift; + } else { + Uint8 dR, dG, dB, dA=0; + Uint8 sR, sG, sB, sA=0; + + pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; + + dR = *((pix)+rshift8); + dG = *((pix)+gshift8); + dB = *((pix)+bshift8); + dA = *((pix)+ashift8); + + sR = (color>>surface->format->Rshift)&0xff; + sG = (color>>surface->format->Gshift)&0xff; + sB = (color>>surface->format->Bshift)&0xff; + sA = (color>>surface->format->Ashift)&0xff; + + dR = dR + ((sR-dR)*alpha >> 8); + dG = dG + ((sG-dG)*alpha >> 8); + dB = dB + ((sB-dB)*alpha >> 8); + dA = dA + ((sA-dA)*alpha >> 8); + + *((pix)+rshift8) = dR; + *((pix)+gshift8) = dG; + *((pix)+bshift8) = dB; + *((pix)+ashift8) = dA; + } + } + break; + + case 4: { /* Probably 32-bpp */ + if ( alpha == 255 ) { + *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color; + } else { + Uint32 *pixel = (Uint32 *)surface->pixels + y*surface->pitch/4 + x; + Uint32 dc = *pixel; + + R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask; + G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask; + B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask; + if ( Amask ) + A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask; + + *pixel = R | G | B | A; + } + } + break; + } + } + + return(0); +} + +/* ----- Pixel - pixel draw with blending enabled if a<255 */ + +int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color) +{ + Uint8 alpha; + Uint32 mcolor; + int result=0; + + /* Lock the surface */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return(-1); + } + } + + /* Setup color */ + alpha=color &0x000000ff; + mcolor=SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); + + /* Draw */ + result = _putPixelAlpha(dst,x,y,mcolor,alpha); + + /* Unlock the surface */ + if (SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + + return(result); +} + + +/* Filled rectangle with alpha blending, color in destination format */ + +int _filledRectAlpha (SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha) +{ + Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask; + Uint32 R,G,B,A=0; + Sint16 x,y; + + switch (surface->format->BytesPerPixel) { + case 1: { /* Assuming 8-bpp */ + Uint8 *row, *pixel; + Uint8 dR, dG, dB; + + Uint8 sR = surface->format->palette->colors[color].r; + Uint8 sG = surface->format->palette->colors[color].g; + Uint8 sB = surface->format->palette->colors[color].b; + + for(y = y1; y<=y2; y++){ + row = (Uint8 *)surface->pixels + y*surface->pitch; + for(x = x1; x <= x2; x++){ + pixel = row + x; + + dR = surface->format->palette->colors[*pixel].r; + dG = surface->format->palette->colors[*pixel].g; + dB = surface->format->palette->colors[*pixel].b; + + dR = dR + ((sR-dR)*alpha >> 8); + dG = dG + ((sG-dG)*alpha >> 8); + dB = dB + ((sB-dB)*alpha >> 8); + + *pixel = SDL_MapRGB(surface->format, dR, dG, dB); + } + } + } + break; + + case 2: { /* Probably 15-bpp or 16-bpp */ + Uint16 *row, *pixel; + Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask); + + for(y = y1; y<=y2; y++){ + row = (Uint16 *)surface->pixels + y*surface->pitch/2; + for(x = x1; x <= x2; x++){ + pixel = row + x; + + R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask; + G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask; + B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask; + if( Amask ) + A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask; + + *pixel= R | G | B | A; + } + } + } + break; + + case 3: { /* Slow 24-bpp mode, usually not used */ + Uint8 *row,*pix; + Uint8 dR, dG, dB, dA; + Uint8 rshift8=surface->format->Rshift/8; + Uint8 gshift8=surface->format->Gshift/8; + Uint8 bshift8=surface->format->Bshift/8; + Uint8 ashift8=surface->format->Ashift/8; + + Uint8 sR = (color>>surface->format->Rshift)&0xff; + Uint8 sG = (color>>surface->format->Gshift)&0xff; + Uint8 sB = (color>>surface->format->Bshift)&0xff; + Uint8 sA = (color>>surface->format->Ashift)&0xff; + + for(y = y1; y<=y2; y++){ + row = (Uint8 *)surface->pixels + y * surface->pitch; + for(x = x1; x <= x2; x++){ + pix = row + x*3; + + dR = *((pix)+rshift8); + dG = *((pix)+gshift8); + dB = *((pix)+bshift8); + dA = *((pix)+ashift8); + + dR = dR + ((sR-dR)*alpha >> 8); + dG = dG + ((sG-dG)*alpha >> 8); + dB = dB + ((sB-dB)*alpha >> 8); + dA = dA + ((sA-dA)*alpha >> 8); + + *((pix)+rshift8) = dR; + *((pix)+gshift8) = dG; + *((pix)+bshift8) = dB; + *((pix)+ashift8) = dA; + } + } + + } + break; + + case 4: { /* Probably 32-bpp */ + Uint32 *row, *pixel; + Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask); + + for(y = y1; y<=y2; y++){ + row = (Uint32 *)surface->pixels + y*surface->pitch/4; + for(x = x1; x <= x2; x++){ + pixel = row + x; + + R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask; + G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask; + B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask; + if( Amask ) + A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask; + + *pixel= R | G | B | A; + } + } + } + break; + } + + return(0); +} + +/* Draw rectangle with alpha enabled from RGBA color. */ + +int filledRectAlpha (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) +{ + Uint8 alpha; + Uint32 mcolor; + int result=0; + + /* Lock the surface */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return(-1); + } + } + + /* Setup color */ + alpha = color & 0x000000ff; + mcolor=SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); + + /* Draw */ + result = _filledRectAlpha(dst,x1,y1,x2,y2,mcolor,alpha); + + /* Unlock the surface */ + if (SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + + return(result); +} + +/* Draw horizontal line with alpha enabled from RGBA color */ + +int HLineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) +{ + return (filledRectAlpha(dst, x1, y, x2, y, color)); +} + + +/* Draw vertical line with alpha enabled from RGBA color */ + +int VLineAlpha(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) +{ + return (filledRectAlpha(dst, x, y1, x, y2, color)); +} + +#endif + + +/* Pixel - using alpha weight on color for AA-drawing */ + +int pixelColorWeight (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) +{ + Uint32 a; + + /* Get alpha */ + a=(color & (Uint32)0x000000ff); + + /* Modify Alpha by weight */ + a = ((a*weight) >> 8); + + return(pixelColor (dst,x,y, (color & (Uint32)0xffffff00) | (Uint32)a )); +} + +int pixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + Uint32 color; + + /* Check Alpha */ + if (a==255) { + /* No alpha blending required */ + /* Setup color */ + color=SDL_MapRGBA(dst->format, r, g, b, a); + /* Draw */ + return(fastPixelColor (dst, x, y, color)); + } else { + /* Alpha blending required */ + /* Draw */ + return(pixelColor (dst, x, y, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a )); + } +} + +/* ----- Horizontal line */ + +#ifdef SURFACE_ALPHA_PIXEL + static SDL_Surface *gfxPrimitivesHline=NULL; +#endif + +int hlineColor (SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) +{ + Sint16 left,right,top,bottom; + Uint8 *pixel,*pixellast; + int dx; + int pixx, pixy; + Sint16 w; + Sint16 xtmp; + int result=-1; + Uint8 *colorptr; +#ifdef SURFACE_ALPHA_PIXEL + Uint32 a; + SDL_Rect srect; + SDL_Rect drect; +#endif + + /* Get clipping boundary */ + left = dst->clip_rect.x; + right = dst->clip_rect.x+dst->clip_rect.w-1; + top = dst->clip_rect.y; + bottom = dst->clip_rect.y+dst->clip_rect.h-1; + + /* Swap x1, x2 if required */ + if (x1>x2) { + xtmp=x1; x1=x2; x2=xtmp; + } + + /* Visible */ + if ((x1>right) || (x2bottom)) { + return(0); + } + + /* Clip x */ + if (x1right) { + x2=right; + } + + /* Calculate width */ + w=x2-x1; + + /* Sanity check on width */ + if (w<0) { + return(0); + } + + /* Alpha check */ + if ((color & 255)==255) { + + /* No alpha-blending required */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + /* More variable setup */ + dx=w; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y; + + /* Draw */ + switch(dst->format->BytesPerPixel) { + case 1: + memset (pixel, color, dx); + break; + case 2: + pixellast = pixel + dx + dx; + for (; pixel<=pixellast; pixel += pixx) { + *(Uint16*)pixel = color; + } + break; + case 3: + pixellast = pixel + dx + dx + dx; + for (; pixel<=pixellast; pixel += pixx) { + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + } + break; + default: /* case 4*/ + dx = dx + dx; + pixellast = pixel + dx + dx; + for (; pixel<=pixellast; pixel += pixx) { + *(Uint32*)pixel = color; + } + break; + } + + /* Unlock surface */ + SDL_UnlockSurface(dst); + + /* Set result code */ + result=0; + + } else { + + /* Alpha blending blit */ + +#ifdef SURFACE_ALPHA_PIXEL + + /* Adjust width for Rect setup */ + w++; + + /* Setup source rectangle for pixel */ + srect.x=0; + srect.y=0; + srect.w=w; + srect.h=1; + + /* Setup rectangle for destination line */ + drect.x=x1; + drect.y=y; + drect.w=w; + drect.h=1; + + /* Maybe deallocate existing surface if size is too small */ + if ((gfxPrimitivesHline!=NULL) && (gfxPrimitivesHline->wclip_rect.x; + right = dst->clip_rect.x+dst->clip_rect.w-1; + top = dst->clip_rect.y; + bottom = dst->clip_rect.y+dst->clip_rect.h-1; + + /* Swap y1, y2 if required */ + if (y1>y2) { + ytmp=y1; y1=y2; y2=ytmp; + } + + /* Visible */ + if ((y2bottom) || (xright)) { + return(0); + } + + /* Clip y */ + if (y1bottom) { + y2=bottom; + } + + /* Calculate height */ + h=y2-y1; + + /* Sanity check on height */ + if (h<0) { + return(0); + } + + /* Alpha check */ + if ((color & 255)==255) { + + /* No alpha-blending required */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + /* More variable setup */ + dy=h; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8*)dst->pixels) + pixx * (int)x + pixy * (int)y1; + pixellast = pixel + pixy*dy; + + /* Draw */ + switch(dst->format->BytesPerPixel) { + case 1: + for (; pixel<=pixellast; pixel += pixy) { + *(Uint8*)pixel = color; + } + break; + case 2: + for (; pixel<=pixellast; pixel += pixy) { + *(Uint16*)pixel = color; + } + break; + case 3: + for (; pixel<=pixellast; pixel += pixy) { + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + } + break; + default: /* case 4*/ + for (; pixel<=pixellast; pixel += pixy) { + *(Uint32*)pixel = color; + } + break; + } + + /* Unlock surface */ + SDL_UnlockSurface(dst); + + /* Set result code */ + result=0; + + } else { + + /* Alpha blending blit */ + +#ifdef SURFACE_ALPHA_PIXEL + + /* Adjust height for Rect setup */ + h++; + + /* Setup source rectangle for pixel */ + srect.x=0; + srect.y=0; + srect.w=1; + srect.h=h; + + /* Setup rectangle for line */ + drect.x=x; + drect.y=y1; + drect.w=1; + drect.h=h; + + /* Maybe deallocate existing surface if size is too small */ + if ( (gfxPrimitivesVline!=NULL) && (gfxPrimitivesVline->hx2) { + xtmp=x1; x1=x2; x2=xtmp; + } + + /* Swap y1, y2 if required */ + if (y1>y2) { + ytmp=y1; y1=y2; y2=ytmp; + } + + /* Calculate width&height */ + w=x2-x1; + h=y2-y1; + + /* Sanity check */ + if ((w<0) || (h<0)) { + return(0); + } + + /* Test for special cases of straight lines or single point */ + if (x1==x2) { + if (y1==y2) { + return(pixelColor(dst, x1, y1, color)); + } else { + return(vlineColor(dst, x1, y1, y2, color)); + } + } else { + if (y1==y2) { + return(hlineColor(dst, x1, x2, y1, color)); + } + } + + /* Draw rectangle */ + result=0; + result |= vlineColor(dst, x1, y1, y2, color); + result |= vlineColor(dst, x2, y1, y2, color); + result |= hlineColor(dst, x1, x2, y1, color); + result |= hlineColor(dst, x1, x2, y2, color); + + return(result); + +} + +int rectangleRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(rectangleColor(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* --------- Clipping routines for box/line */ + +/* Clipping based heavily on code from */ +/* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */ + +#define CLIP_LEFT_EDGE 0x1 +#define CLIP_RIGHT_EDGE 0x2 +#define CLIP_BOTTOM_EDGE 0x4 +#define CLIP_TOP_EDGE 0x8 +#define CLIP_INSIDE(a) (!a) +#define CLIP_REJECT(a,b) (a&b) +#define CLIP_ACCEPT(a,b) (!(a|b)) + +static int clipEncode (Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) +{ + int code = 0; + if (x < left) { + code |= CLIP_LEFT_EDGE; + } else if (x > right) { + code |= CLIP_RIGHT_EDGE; + } + if (y < top) { + code |= CLIP_TOP_EDGE; + } else if (y > bottom) { + code |= CLIP_BOTTOM_EDGE; + } + return code; +} + +static int clipLine(SDL_Surface *dst, Sint16 *x1, Sint16 *y1, Sint16 *x2, Sint16 *y2) +{ + Sint16 left,right,top,bottom; + int code1, code2; + int draw = 0; + Sint16 swaptmp; + float m; + + /* Get clipping boundary */ + left = dst->clip_rect.x; + right = dst->clip_rect.x+dst->clip_rect.w-1; + top = dst->clip_rect.y; + bottom = dst->clip_rect.y+dst->clip_rect.h-1; + + while (1) { + code1 = clipEncode (*x1, *y1, left, top, right, bottom); + code2 = clipEncode (*x2, *y2, left, top, right, bottom); + if (CLIP_ACCEPT(code1, code2)) { + draw = 1; + break; + } else if (CLIP_REJECT(code1, code2)) + break; + else { + if(CLIP_INSIDE (code1)) { + swaptmp = *x2; *x2 = *x1; *x1 = swaptmp; + swaptmp = *y2; *y2 = *y1; *y1 = swaptmp; + swaptmp = code2; code2 = code1; code1 = swaptmp; + } + if (*x2 != *x1) { + m = (*y2 - *y1) / (float)(*x2 - *x1); + } else { + m = 1.0f; + } + if (code1 & CLIP_LEFT_EDGE) { + *y1 += (Sint16)((left - *x1) * m); + *x1 = left; + } else if (code1 & CLIP_RIGHT_EDGE) { + *y1 += (Sint16)((right - *x1) * m); + *x1 = right; + } else if (code1 & CLIP_BOTTOM_EDGE) { + if (*x2 != *x1) { + *x1 += (Sint16)((bottom - *y1) / m); + } + *y1 = bottom; + } else if (code1 & CLIP_TOP_EDGE) { + if (*x2 != *x1) { + *x1 += (Sint16)((top - *y1) / m); + } + *y1 = top; + } + } + } + + return draw; +} + +/* ----- Filled rectangle (Box) */ + +#ifdef SURFACE_ALPHA_PIXEL + static SDL_Surface *gfxPrimitivesBox=NULL; +#endif + +int boxColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) +{ + Uint8 *pixel, *pixellast; + int x, dx; + int dy; + int pixx, pixy; + Sint16 w,h,tmp; + int result; + Uint8 *colorptr; +#ifdef SURFACE_ALPHA_PIXEL + Uint32 a; + SDL_Rect srect; + SDL_Rect drect; +#endif + + /* Clip diagonal and test if we have to draw */ + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Test for special cases of straight lines or single point */ + if (x1==x2) { + if (y1y2) { + return(vlineColor(dst, x1, y2, y1, color)); + } else { + return(pixelColor(dst, x1, y1, color)); + } + } + if (y1==y2) { + if (x1x2) { + return(hlineColor(dst, x2, x1, y1, color)); + } + } + + /* Order coordinates */ + if (x1>x2) { + tmp=x1; + x1=x2; + x2=tmp; + } + if (y1>y2) { + tmp=y1; + y1=y2; + y2=tmp; + } + + /* Calculate width&height */ + w=x2-x1; + h=y2-y1; + + /* Alpha check */ + if ((color & 255)==255) { + + /* No alpha-blending required */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + /* More variable setup */ + dx=w; + dy=h; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y1; + pixellast = pixel + pixx*dx + pixy*dy; + + /* Draw */ + switch(dst->format->BytesPerPixel) { + case 1: + for (; pixel<=pixellast; pixel += pixy) { + memset(pixel,(Uint8)color,dx); + } + break; + case 2: + pixy -= (pixx*dx); + for (; pixel<=pixellast; pixel += pixy) { + for (x=0; x> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + pixel += pixx; + } + } + break; + default: /* case 4*/ + pixy -= (pixx*dx); + for (; pixel<=pixellast; pixel += pixy) { + for (x=0; xwhy2) { + return(vlineColor(dst, x1, y2, y1, color)); + } else { + return(pixelColor(dst, x1, y1, color)); + } + } + if (y1==y2) { + if (x1x2) { + return(hlineColor(dst, x2, x1, y1, color)); + } + } + + /* Variable setup */ + dx = x2 - x1; + dy = y2 - y1; + sx = (dx >= 0) ? 1 : -1; + sy = (dy >= 0) ? 1 : -1; + + /* Check for alpha blending */ + if ((color & 255)==255) { + + /* No alpha blending - use fast pixel routines */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + /* More variable setup */ + dx = sx * dx + 1; + dy = sy * dy + 1; + pixx = dst->format->BytesPerPixel; + pixy = dst->pitch; + pixel = ((Uint8*)dst->pixels) + pixx * (int)x1 + pixy * (int)y1; + pixx *= sx; + pixy *= sy; + if (dx < dy) { + swaptmp = dx; dx = dy; dy = swaptmp; + swaptmp = pixx; pixx = pixy; pixy = swaptmp; + } + + /* Draw */ + x=0; + y=0; + switch(dst->format->BytesPerPixel) { + case 1: + for(; x < dx; x++, pixel += pixx) { + *pixel = color; + y += dy; + if (y >= dx) { + y -= dx; pixel += pixy; + } + } + break; + case 2: + for (; x < dx; x++, pixel += pixx) { + *(Uint16*)pixel = color; + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + case 3: + for(; x < dx; x++, pixel += pixx) { + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + pixel[0] = (color >> 16) & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = color & 0xff; + } else { + pixel[0] = color & 0xff; + pixel[1] = (color >> 8) & 0xff; + pixel[2] = (color >> 16) & 0xff; + } + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + default: /* case 4 */ + for(; x < dx; x++, pixel += pixx) { + *(Uint32*)pixel = color; + y += dy; + if (y >= dx) { + y -= dx; + pixel += pixy; + } + } + break; + } + + /* Unlock surface */ + SDL_UnlockSurface(dst); + + } else { + + /* Alpha blending required - use single-pixel blits */ + + ax = ABS(dx) << 1; + ay = ABS(dy) << 1; + x = x1; + y = y1; + if (ax > ay) { + int d = ay - (ax >> 1); + while (x != x2) { + pixelColor(dst, x, y, color); + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } else { + int d = ax - (ay >> 1); + while (y != y2) { + pixelColor(dst, x, y, color); + if (d > 0 || ((d == 0) && (sy == 1))) { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } + pixelColor(dst, x, y, color); + + } + + return(0); +} + +int lineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(lineColor(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* AA Line */ + +#define AAlevels 256 +#define AAbits 8 + +/* + +This implementation of the Wu antialiasing code is based on Mike Abrash's +DDJ article which was reprinted as Chapter 42 of his Graphics Programming +Black Book, but has been optimized to work with SDL and utilizes 32-bit +fixed-point arithmetic. (A. Schiffler). + +*/ + +int aalineColorInt (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint) +{ + Sint32 xx0,yy0,xx1,yy1; + int result; + Uint32 intshift, erracc, erradj; + Uint32 erracctmp, wgt, wgtcompmask; + int dx, dy, tmp, xdir, y0p1, x0pxdir; + + /* Clip line and test if we have to draw */ + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Keep on working with 32bit numbers */ + xx0=x1; + yy0=y1; + xx1=x2; + yy1=y2; + + /* Reorder points if required */ + if (yy0 > yy1) { + tmp = yy0; yy0 = yy1; yy1 = tmp; + tmp = xx0; xx0 = xx1; xx1 = tmp; + } + + /* Calculate distance */ + dx = xx1 - xx0; + dy = yy1 - yy0; + + /* Adjust for negative dx and set xdir */ + if (dx >= 0) { + xdir=1; + } else { + xdir=-1; + dx=(-dx); + } + + /* Check for special cases */ + if (dx==0) { + /* Vertical line */ + return (vlineColor(dst,x1,y1,y2,color)); + } else if (dy==0) { + /* Horizontal line */ + return (hlineColor(dst,x1,x2,y1,color)); + } else if (dx==dy) { + /* Diagonal line */ + return (lineColor(dst,x1,y1,x2,y2,color)); + } + + /* Line is not horizontal, vertical or diagonal */ + result=0; + /* Zero accumulator */ + erracc = 0; + /* # of bits by which to shift erracc to get intensity level */ + intshift = 32 - AAbits; + /* Mask used to flip all bits in an intensity weighting */ + wgtcompmask = AAlevels - 1; + + /* Draw the initial pixel in the foreground color */ + result |= pixelColor (dst, x1, y1, color); + + /* x-major or y-major? */ + if (dy > dx) { + + /* y-major. Calculate 16-bit fixed point fractional part of a pixel that + X advances every time Y advances 1 pixel, truncating the result so that + we won't overrun the endpoint along the X axis */ + /* Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; */ + erradj = ((dx << 16) / dy)<<16; + + /* draw all pixels other than the first and last */ + x0pxdir=xx0+xdir; + while (--dy) { + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) { + /* rollover in error accumulator, x coord advances */ + xx0=x0pxdir; + x0pxdir += xdir; + } + yy0++; /* y-major so always advance Y */ + + /* the AAbits most significant bits of erracc give us the intensity + weighting for this pixel, and the complement of the weighting for + the paired pixel. */ + wgt = (erracc >> intshift) & 255; + result |= pixelColorWeight (dst, xx0, yy0, color, 255-wgt); + result |= pixelColorWeight (dst, x0pxdir, yy0, color, wgt); + } + + } else { + + /* x-major line. Calculate 16-bit fixed-point fractional part of a pixel + that Y advances each time X advances 1 pixel, truncating the result so + that we won't overrun the endpoint along the X axis. */ + /* Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; */ + erradj = ((dy << 16) / dx)<<16; + + /* draw all pixels other than the first and last */ + y0p1=yy0+1; + while (--dx) { + + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) { + /* Accumulator turned over, advance y */ + yy0=y0p1; + y0p1++; + } + xx0 += xdir; /* x-major so always advance X */ + /* the AAbits most significant bits of erracc give us the intensity + weighting for this pixel, and the complement of the weighting for + the paired pixel. */ + wgt = (erracc >> intshift) & 255; + result |= pixelColorWeight (dst, xx0, yy0, color, 255-wgt); + result |= pixelColorWeight (dst, xx0, y0p1, color, wgt); + } + } + + /* Do we have to draw the endpoint */ + if (draw_endpoint) { + /* Draw final pixel, always exactly intersected by the line and doesn't + need to be weighted. */ + result |= pixelColor (dst, x2, y2, color); + } + + return(result); +} + +int aalineColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) +{ + return(aalineColorInt(dst,x1,y1,x2,y1,color,1)); +} + +int aalineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + return(aalineColorInt(dst, x1, y1, x2, y2, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a, 1)); +} + + +/* ----- Circle */ + +/* Note: Based on algorithm from sge library, modified by A. Schiffler */ +/* with multiple pixel-draw removal and other minor speedup changes. */ + +int circleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color) +{ + int result; + Sint16 x1,y1,x2,y2; + Sint16 cx = 0; + Sint16 cy = r; + Sint16 ocx = (Sint16)0xffff; + Sint16 ocy = (Sint16)0xffff; + Sint16 df = 1 - r; + Sint16 d_e = 3; + Sint16 d_se = -2 * r + 5; + Sint16 xpcx, xmcx, xpcy, xmcy; + Sint16 ypcy, ymcy, ypcx, ymcx; + Uint8 *colorptr; + + /* Sanity check radius */ + if (r<0) { + return(-1); + } + + /* Special case for r=0 - draw a point */ + if (r==0) { + return(pixelColor (dst, x, y, color)); + } + + /* Test if bounding box of circle is visible */ + x1=x-r; + y1=y-r; + x2=x+r; + y2=y+r; + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Draw circle */ + result=0; + /* Alpha Check */ + if ((color & 255) ==255) { + + /* No Alpha - direct memory writes */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + /* Draw */ + do { + if ((ocy!=cy) || (ocx!=cx)) { + xpcx=x+cx; + xmcx=x-cx; + if (cy>0) { + ypcy=y+cy; + ymcy=y-cy; + result |= fastPixelColorNolock(dst,xmcx,ypcy,color); + result |= fastPixelColorNolock(dst,xpcx,ypcy,color); + result |= fastPixelColorNolock(dst,xmcx,ymcy,color); + result |= fastPixelColorNolock(dst,xpcx,ymcy,color); + } else { + result |= fastPixelColorNolock(dst,xmcx,y,color); + result |= fastPixelColorNolock(dst,xpcx,y,color); + } + ocy=cy; + xpcy=x+cy; + xmcy=x-cy; + if (cx>0) { + ypcx=y+cx; + ymcx=y-cx; + result |= fastPixelColorNolock(dst,xmcy,ypcx,color); + result |= fastPixelColorNolock(dst,xpcy,ypcx,color); + result |= fastPixelColorNolock(dst,xmcy,ymcx,color); + result |= fastPixelColorNolock(dst,xpcy,ymcx,color); + } else { + result |= fastPixelColorNolock(dst,xmcy,y,color); + result |= fastPixelColorNolock(dst,xpcy,y,color); + } + ocx=cx; + } + /* Update */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while(cx <= cy); + + /* Unlock surface */ + SDL_UnlockSurface(dst); + + } else { + + /* Using Alpha - blended pixel blits */ + + do { + /* Draw */ + if ((ocy!=cy) || (ocx!=cx)) { + xpcx=x+cx; + xmcx=x-cx; + if (cy>0) { + ypcy=y+cy; + ymcy=y-cy; + result |= pixelColor(dst,xmcx,ypcy,color); + result |= pixelColor(dst,xpcx,ypcy,color); + result |= pixelColor(dst,xmcx,ymcy,color); + result |= pixelColor(dst,xpcx,ymcy,color); + } else { + result |= pixelColor(dst,xmcx,y,color); + result |= pixelColor(dst,xpcx,y,color); + } + ocy=cy; + xpcy=x+cy; + xmcy=x-cy; + if (cx>0) { + ypcx=y+cx; + ymcx=y-cx; + result |= pixelColor(dst,xmcy,ypcx,color); + result |= pixelColor(dst,xpcy,ypcx,color); + result |= pixelColor(dst,xmcy,ymcx,color); + result |= pixelColor(dst,xpcy,ymcx,color); + } else { + result |= pixelColor(dst,xmcy,y,color); + result |= pixelColor(dst,xpcy,y,color); + } + ocx=cx; + } + /* Update */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while(cx <= cy); + + } /* Alpha check */ + + return(result); +} + +int circleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(circleColor(dst, x, y, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* ----- AA Circle */ + +/* Low-speed antialiased circle implementation by drawing aalines. */ +/* Works best for larger radii. */ + +int aacircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color) +{ + return (aaellipseColor(dst, x, y, r, r, color)); +} + +int aacircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(aaellipseColor(dst, x, y, rad, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* ----- Filled Circle */ + +/* Note: Based on algorithm from sge library with multiple-hline draw removal */ +/* and other speedup changes. */ + +int filledCircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color) +{ + int result; + Sint16 x1,y1,x2,y2; + Sint16 cx = 0; + Sint16 cy = r; + Sint16 ocx = (Sint16)0xffff; + Sint16 ocy = (Sint16)0xffff; + Sint16 df = 1 - r; + Sint16 d_e = 3; + Sint16 d_se = -2 * r + 5; + Sint16 xpcx, xmcx, xpcy, xmcy; + Sint16 ypcy, ymcy, ypcx, ymcx; + + /* Sanity check radius */ + if (r<0) { + return(-1); + } + + /* Special case for r=0 - draw a point */ + if (r==0) { + return(pixelColor (dst, x, y, color)); + } + + /* Test bounding box */ + x1=x-r; + y1=y-r; + x2=x+r; + y2=y+r; + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Draw */ + result=0; + do { + xpcx=x+cx; + xmcx=x-cx; + xpcy=x+cy; + xmcy=x-cy; + if (ocy!=cy) { + if (cy>0) { + ypcy=y+cy; + ymcy=y-cy; + result |= hlineColor(dst,xmcx,xpcx,ypcy,color); + result |= hlineColor(dst,xmcx,xpcx,ymcy,color); + } else { + result |= hlineColor(dst,xmcx,xpcx,y,color); + } + ocy=cy; + } + if (ocx!=cx) { + if (cx!=cy) { + if (cx>0) { + ypcx=y+cx; + ymcx=y-cx; + result |= hlineColor(dst,xmcy,xpcy,ymcx,color); + result |= hlineColor(dst,xmcy,xpcy,ypcx,color); + } else { + result |= hlineColor(dst,xmcy,xpcy,y,color); + } + } + ocx=cx; + } + /* Update */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while(cx <= cy); + + return(result); +} + +int filledCircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(filledCircleColor(dst, x, y, rad, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + + +/* ----- Ellipse */ + +/* Note: Based on algorithm from sge library with multiple-hline draw removal */ +/* and other speedup changes. */ + +int ellipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) +{ + int result; + Sint16 x1, y1, x2, y2; + int ix, iy; + int h, i, j, k; + int oh, oi, oj, ok; + int xmh, xph, ypk, ymk; + int xmi, xpi, ymj, ypj; + int xmj, xpj, ymi, ypi; + int xmk, xpk, ymh, yph; + Uint8 *colorptr; + + /* Sanity check radii */ + if ((rx<0) || (ry<0)) { + return(-1); + } + + /* Special case for rx=0 - draw a vline */ + if (rx==0) { + return(vlineColor (dst, x, y-ry, y+ry, color)); + } + /* Special case for ry=0 - draw a hline */ + if (ry==0) { + return(hlineColor (dst, x-rx, x+rx, y, color)); + } + + /* Test bounding box */ + x1=x-rx; + y1=y-ry; + x2=x+rx; + y2=y+ry; + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Init vars */ + oh = oi = oj = ok = 0xFFFF; + + /* Draw */ + result=0; + /* Check alpha */ + if ((color & 255)==255) { + + /* No Alpha - direct memory writes */ + + /* Setup color */ + colorptr=(Uint8 *)&color; + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + color=SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); + } else { + color=SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); + } + + /* Lock surface */ + SDL_LockSurface(dst); + + if (rx > ry) { + ix = 0; + iy = rx * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if (((ok!=k) && (oj!=k)) || ((oj!=j) && (ok!=j)) || (k!=j)) { + xph=x+h; + xmh=x-h; + if (k>0) { + ypk=y+k; + ymk=y-k; + result |= fastPixelColorNolock (dst,xmh,ypk, color); + result |= fastPixelColorNolock (dst,xph,ypk, color); + result |= fastPixelColorNolock (dst,xmh,ymk, color); + result |= fastPixelColorNolock (dst,xph,ymk, color); + } else { + result |= fastPixelColorNolock (dst,xmh,y, color); + result |= fastPixelColorNolock (dst,xph,y, color); + } + ok=k; + xpi=x+i; + xmi=x-i; + if (j>0) { + ypj=y+j; + ymj=y-j; + result |= fastPixelColorNolock (dst,xmi,ypj, color); + result |= fastPixelColorNolock (dst,xpi,ypj, color); + result |= fastPixelColorNolock (dst,xmi,ymj, color); + result |= fastPixelColorNolock (dst,xpi,ymj, color); + } else { + result |= fastPixelColorNolock (dst,xmi,y, color); + result |= fastPixelColorNolock (dst,xpi,y, color); + } + oj=j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + + } while (i > h); + } else { + ix = 0; + iy = ry * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if (((oi!=i) && (oh!=i)) || ((oh!=h) && (oi!=h) && (i!=h))) { + xmj=x-j; + xpj=x+j; + if (i>0) { + ypi=y+i; + ymi=y-i; + result |= fastPixelColorNolock (dst,xmj,ypi,color); + result |= fastPixelColorNolock (dst,xpj,ypi,color); + result |= fastPixelColorNolock (dst,xmj,ymi,color); + result |= fastPixelColorNolock (dst,xpj,ymi,color); + } else { + result |= fastPixelColorNolock (dst,xmj,y,color); + result |= fastPixelColorNolock (dst,xpj,y,color); + } + oi=i; + xmk=x-k; + xpk=x+k; + if (h>0) { + yph=y+h; + ymh=y-h; + result |= fastPixelColorNolock (dst,xmk,yph,color); + result |= fastPixelColorNolock (dst,xpk,yph,color); + result |= fastPixelColorNolock (dst,xmk,ymh,color); + result |= fastPixelColorNolock (dst,xpk,ymh,color); + } else { + result |= fastPixelColorNolock (dst,xmk,y,color); + result |= fastPixelColorNolock (dst,xpk,y,color); + } + oh=h; + } + + ix = ix + iy / ry; + iy = iy - ix / ry; + + } while(i > h); + } + + /* Unlock surface */ + SDL_UnlockSurface(dst); + + } else { + + if (rx > ry) { + ix = 0; + iy = rx * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if (((ok!=k) && (oj!=k)) || ((oj!=j) && (ok!=j)) || (k!=j)) { + xph=x+h; + xmh=x-h; + if (k>0) { + ypk=y+k; + ymk=y-k; + result |= pixelColor (dst,xmh,ypk, color); + result |= pixelColor (dst,xph,ypk, color); + result |= pixelColor (dst,xmh,ymk, color); + result |= pixelColor (dst,xph,ymk, color); + } else { + result |= pixelColor (dst,xmh,y, color); + result |= pixelColor (dst,xph,y, color); + } + ok=k; + xpi=x+i; + xmi=x-i; + if (j>0) { + ypj=y+j; + ymj=y-j; + result |= pixelColor (dst,xmi,ypj, color); + result |= pixelColor (dst,xpi,ypj, color); + result |= pixelColor (dst,xmi,ymj, color); + result |= pixelColor (dst,xpi,ymj, color); + } else { + result |= pixelColor (dst,xmi,y, color); + result |= pixelColor (dst,xpi,y, color); + } + oj=j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + + } while (i > h); + } else { + ix = 0; + iy = ry * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if (((oi!=i) && (oh!=i)) || ((oh!=h) && (oi!=h) && (i!=h))) { + xmj=x-j; + xpj=x+j; + if (i>0) { + ypi=y+i; + ymi=y-i; + result |= pixelColor (dst,xmj,ypi,color); + result |= pixelColor (dst,xpj,ypi,color); + result |= pixelColor (dst,xmj,ymi,color); + result |= pixelColor (dst,xpj,ymi,color); + } else { + result |= pixelColor (dst,xmj,y,color); + result |= pixelColor (dst,xpj,y,color); + } + oi=i; + xmk=x-k; + xpk=x+k; + if (h>0) { + yph=y+h; + ymh=y-h; + result |= pixelColor (dst,xmk,yph,color); + result |= pixelColor (dst,xpk,yph,color); + result |= pixelColor (dst,xmk,ymh,color); + result |= pixelColor (dst,xpk,ymh,color); + } else { + result |= pixelColor (dst,xmk,y,color); + result |= pixelColor (dst,xpk,y,color); + } + oh=h; + } + + ix = ix + iy / ry; + iy = iy - ix / ry; + + } while(i > h); + } + + } /* Alpha check */ + + return(result); +} + +int ellipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(ellipseColor(dst, x, y, rx, ry, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* ----- AA Ellipse */ + +/* Low-speed antialiased ellipse implementation by drawing aalines. */ +/* Works best for larger radii. */ + +int aaellipseColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) +{ + int result; + Sint16 x1, y1, x2, y2; + double angle; + double deltaAngle; + double drx, dry, dr; + int posX, posY, oldPosX, oldPosY; + int i, r; + + /* Sanity check radii */ + if ((rx<0) || (ry<0)) { + return(-1); + } + + /* Special case for rx=0 - draw a vline */ + if (rx==0) { + return(vlineColor (dst, x, y-ry, y+ry, color)); + } + /* Special case for ry=0 - draw a hline */ + if (ry==0) { + return(hlineColor (dst, x-rx, x+rx, y, color)); + } + + /* Test bounding box */ + x1=x-rx; + y1=y-ry; + x2=x+rx; + y2=y+ry; + if (!(clipLine(dst,&x1,&y1,&x2,&y2))) { + return(0); + } + + /* Draw */ + r=(rx+ry)>>1; + dr=(double)r; + drx=(double)rx; + dry=(double)ry; + deltaAngle=(2*M_PI)/dr; + angle=deltaAngle; + oldPosX=x+rx; + oldPosY=y; + + result=0; + for(i=0; i ry) { + ix = 0; + iy = rx * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if ((ok!=k) && (oj!=k)) { + xph=x+h; + xmh=x-h; + if (k>0) { + result |= hlineColor (dst,xmh,xph,y+k,color); + result |= hlineColor (dst,xmh,xph,y-k,color); + } else { + result |= hlineColor (dst,xmh,xph,y,color); + } + ok=k; + } + if ((oj!=j) && (ok!=j) && (k!=j)) { + xmi=x-i; + xpi=x+i; + if (j>0) { + result |= hlineColor (dst,xmi,xpi,y+j,color); + result |= hlineColor (dst,xmi,xpi,y-j,color); + } else { + result |= hlineColor (dst,xmi,xpi,y ,color); + } + oj=j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + + } while (i > h); + } else { + ix = 0; + iy = ry * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if ((oi!=i) && (oh!=i)) { + xmj=x-j; + xpj=x+j; + if (i>0) { + result |= hlineColor (dst,xmj,xpj,y+i,color); + result |= hlineColor (dst,xmj,xpj,y-i,color); + } else { + result |= hlineColor (dst,xmj,xpj,y,color); + } + oi=i; + } + if ((oh!=h) && (oi!=h) && (i!=h)) { + xmk=x-k; + xpk=x+k; + if (h>0) { + result |= hlineColor (dst,xmk,xpk,y+h,color); + result |= hlineColor (dst,xmk,xpk,y-h,color); + } else { + result |= hlineColor (dst,xmk,xpk,y ,color); + } + oh=h; + } + + ix = ix + iy / ry; + iy = iy - ix / ry; + + } while(i > h); + } + + return(result); +} + + +int filledEllipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(filledEllipseColor(dst, x, y, rx, ry, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +/* ---- Polygon */ + +int polygonColor (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint32 color) +{ + int result; + int i; + Sint16 *x1, *y1, *x2, *y2; + + /* Sanity check */ + if (n<3) { + return(-1); + } + + /* Pointer setup */ + x1=x2=vx; + y1=y2=vy; + x2++; + y2++; + + /* Draw */ + result=0; + for (i=1; i maxy) { + maxy = vy[i]; + } + } + + /* Draw, scanning y */ + result=0; + for (y=miny; (y <= maxy); y++) { + ints = 0; + for (i=0; (i < n); i++) { + if (!i) { + ind1 = n-1; + ind2 = 0; + } else { + ind1 = i-1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) { + x1 = vx[ind1]; + x2 = vx[ind2]; + } else if (y1 > y2) { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } else { + continue; + } + if ((y >= y1) && (y < y2)) { + gfxPrimitivesPolyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1; + } else if ((y == maxy) && (y > y1) && (y <= y2)) { + gfxPrimitivesPolyInts[ints++] = (y-y1) * (x2-x1) / (y2-y1) + x1; + } + } + qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt); + + for (i=0; (ipixels; + memset (curpos, 0, 8*8*4); + + /* Drawing loop */ + for (iy=0; iy<8; iy++) { + bitpos=bits; + for (ix=0; ix<8; ix++) { + if ((*charpos & *bitpos)==*bitpos) { + memcpy(curpos,&color,4); + } + bitpos++; + curpos += 4;; + } + charpos++; + } + } + + /* Draw bitmap onto destination surface */ + result=SDL_BlitSurface (gfxPrimitivesFont[(unsigned char)c], &srect, dst, &drect); + + return(result); +} + +int characterRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + /* Draw */ + return(characterColor(dst, x, y, c, ((Uint32)r << 24) | ((Uint32)g << 16) | ((Uint32)b << 8) | (Uint32)a)); +} + +int stringColor (SDL_Surface *dst, Sint16 x, Sint16 y, char *c, Uint32 color) +{ + int result; + int i,length; + char *curchar; + int curx; + + length=strlen(c); + curchar=c; + curx=x; + result=0; + for (i=0; i +#ifndef M_PI + #define M_PI 3.141592654 +#endif + +#include + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* ----- Versioning */ + +#define SDL_GFXPRIMITIVES_MAJOR 1 +#define SDL_GFXPRIMITIVES_MINOR 5 + +/* ----- W32 DLL interface */ + +#ifdef WIN32 + #define DLLINTERFACE DECLSPEC +#else + #define DLLINTERFACE +#endif + +/* ----- Prototypes */ + +/* Note: all ___Color routines expect the color to be in format 0xRRGGBBAA */ + +/* Pixel */ + +DLLINTERFACE int pixelColor (SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color); +DLLINTERFACE int pixelRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Horizontal line */ + +DLLINTERFACE int hlineColor (SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color); +DLLINTERFACE int hlineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Vertical line */ + +DLLINTERFACE int vlineColor (SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color); +DLLINTERFACE int vlineRGBA (SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Rectangle */ + +DLLINTERFACE int rectangleColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); +DLLINTERFACE int rectangleRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Filled rectangle (Box) */ + +DLLINTERFACE int boxColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); +DLLINTERFACE int boxRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Line */ + +DLLINTERFACE int lineColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); +DLLINTERFACE int lineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* AA Line */ +DLLINTERFACE int aalineColor (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); +DLLINTERFACE int aalineRGBA (SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Circle */ + +DLLINTERFACE int circleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); +DLLINTERFACE int circleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* AA Circle */ + +DLLINTERFACE int aacircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); +DLLINTERFACE int aacircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Filled Circle */ + +DLLINTERFACE int filledCircleColor(SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); +DLLINTERFACE int filledCircleRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Ellipse */ + +DLLINTERFACE int ellipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); +DLLINTERFACE int ellipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* AA Ellipse */ + +DLLINTERFACE int aaellipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); +DLLINTERFACE int aaellipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Filled Ellipse */ + +DLLINTERFACE int filledEllipseColor (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); +DLLINTERFACE int filledEllipseRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Polygon */ + +DLLINTERFACE int polygonColor (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint32 color); +DLLINTERFACE int polygonRGBA (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Filled Polygon */ + +DLLINTERFACE int filledPolygonColor (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, int color); +DLLINTERFACE int filledPolygonRGBA (SDL_Surface *dst, Sint16 *vx, Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* 8x8 Characters/Strings */ + +DLLINTERFACE int characterColor (SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint32 color); +DLLINTERFACE int characterRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a); +DLLINTERFACE int stringColor (SDL_Surface *dst, Sint16 x, Sint16 y, char *c, Uint32 color); +DLLINTERFACE int stringRGBA (SDL_Surface *dst, Sint16 x, Sint16 y, char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +}; +#endif + +#endif /* _SDL_gfxPrimitives_h */ diff --git a/plugins/gs/GSsoft/Src/SDL_gfxPrimitives_font.h b/plugins/gs/GSsoft/Src/SDL_gfxPrimitives_font.h new file mode 100644 index 0000000..861f724 --- /dev/null +++ b/plugins/gs/GSsoft/Src/SDL_gfxPrimitives_font.h @@ -0,0 +1,2567 @@ +/* ---- 8x8 font definition ---- */ + +#define GFX_FONTDATAMAX (8*256) + +static unsigned char gfxPrimitivesFontdata[GFX_FONTDATAMAX] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + + /* 2 0x02 '^B' */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + + /* 3 0x03 '^C' */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 6 0x06 '^F' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x0f, /* 00001111 */ + 0x07, /* 00000111 */ + 0x0f, /* 00001111 */ + 0x7d, /* 01111101 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + + /* 12 0x0c '^L' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + + /* 13 0x0d '^M' */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + + /* 14 0x0e '^N' */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + + /* 15 0x0f '^O' */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + + /* 16 0x10 '^P' */ + 0x80, /* 10000000 */ + 0xe0, /* 11100000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xe0, /* 11100000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x02, /* 00000010 */ + 0x0e, /* 00001110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x0e, /* 00001110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + + /* 19 0x13 '^S' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x3e, /* 00111110 */ + 0x61, /* 01100001 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x86, /* 10000110 */ + 0x7c, /* 01111100 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + + /* 24 0x18 '^X' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x24, /* 00100100 */ + 0x66, /* 01100110 */ + 0xff, /* 11111111 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x60, /* 01100000 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 60 0x3c '<' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xc0, /* 11000000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xce, /* 11001110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xce, /* 11001110 */ + 0x7c, /* 01111100 */ + 0x0e, /* 00001110 */ + + /* 82 0x52 'R' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x8c, /* 10001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0xc0, /* 11000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + + /* 96 0x60 '`' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0xf8, /* 11111000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + + /* 104 0x68 'h' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + + /* 107 0x6b 'k' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x4c, /* 01001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + + /* 129 0x81 '' */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x0c, /* 00001100 */ + 0x38, /* 00111000 */ + + /* 136 0x88 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '' */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xf8, /* 11111000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '' */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '' */ + 0x78, /* 01111000 */ + 0x84, /* 10000100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 153 0x99 '' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 156 0x9c '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 158 0x9e '' */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfa, /* 11111010 */ + 0xc6, /* 11000110 */ + 0xcf, /* 11001111 */ + 0xc6, /* 11000110 */ + 0xc7, /* 11000111 */ + + /* 159 0x9f '' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '' */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x63, /* 01100011 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7e, /* 01111110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x0f, /* 00001111 */ + + /* 172 0xac '' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7a, /* 01111010 */ + 0x36, /* 00110110 */ + 0x6a, /* 01101010 */ + 0xdf, /* 11011111 */ + 0x06, /* 00000110 */ + + /* 173 0xad '' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '' */ + 0x00, /* 00000000 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '' */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '' */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + + /* 177 0xb1 '' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '' */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + + /* 179 0xb3 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb '' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd '' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde '' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf '' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xc8, /* 11001000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '' */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0xc0, /* 11000000 */ + + /* 231 0xe7 '' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '' */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + + /* 233 0xe9 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 236 0xec '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + + /* 238 0xee '' */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 239 0xef '' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '' */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + + /* 246 0xf6 '' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '' */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + + /* 252 0xfc '' */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '' */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/plugins/gs/GSsoft/Src/Soft.c b/plugins/gs/GSsoft/Src/Soft.c new file mode 100644 index 0000000..e53862a --- /dev/null +++ b/plugins/gs/GSsoft/Src/Soft.c @@ -0,0 +1,1504 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "GS.h" +#include "Soft.h" +#include "Texts.h" +#include "Color.h" +#include "Mem.h" + +#undef ABS +#define ABS(a) (((a)<0) ? -(a) : (a)) + +__inline int shl10idiv(int x, int y) { + s64 bi = x; + bi <<= 10; + return (int)(bi / y); +} + +__inline s64 shl10idiv64(s64 x, s64 y) { + s64 bi = x; + bi <<= 10; + return (s64)(bi / y); +} + +// + +void drawLineF(Vertex * v) { + int dx = v[1].x - v[0].x; + int dy = v[1].y - v[0].y; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + int x = v[0].x; + int y = v[0].y; + +#ifdef GS_LOG + GS_LOG("drawLineF %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, gs.rgba); +#endif + + SETdrawPixel(); + + if (ax > ay) { + int d = ay - (ax >> 1); + while (x != v[1].x) { + drawPixel(x, y, gs.rgba); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; + d += ay; + } + } else { + int d = ax - (ay >> 1); + while (y != v[1].y) { + drawPixel(x, y, gs.rgba); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; + d -= ay; + } + y += sy; + d += ax; + } + } +} + +void drawLineF_F(Vertex * v) { + int dx = v[1].x - v[0].x; + int dy = v[1].y - v[0].y; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + int x = v[0].x; + int y = v[0].y; + u32 f0, f1; + int df; + +#ifdef GS_LOG + GS_LOG("drawLineF_F %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, gs.rgba); +#endif + + SETdrawPixelF(); + + f0 = v[0].f << 16; + f1 = v[1].f << 16; + + if (ax > ay) { + int d = ay - (ax >> 1); + df = (f1 - f0) / dx; + while (x != v[1].x) { + drawPixelF(x, y, gs.rgba, f0 >> 16); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; d -= ax; + } + x += sx; d += ay; + f0+= df; + } + } else { + int d = ax - (ay >> 1); + df = (f1 - f0) / dy; + while (y != v[1].y) { + drawPixelF(x, y, gs.rgba, f0 >> 16); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; d -= ay; + } + y += sy; d += ax; + f0+= df; + } + } +} + +void drawLineF_Z(Vertex * v) { + int dx = v[1].x - v[0].x; + int dy = v[1].y - v[0].y; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + int x = v[0].x; + int y = v[0].y; + +#ifdef GS_LOG + GS_LOG("drawLineF_Z %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, gs.rgba); +#endif + + SETdrawPixelZ(); + + if (ax > ay) { + int d = ay - (ax >> 1); + while (x != v[1].x) { + drawPixelZ(x, y, gs.rgba, v[1].z); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; d -= ax; + } + x += sx; d += ay; + } + } else { + int d = ax - (ay >> 1); + while (y != v[1].y) { + drawPixelZ(x, y, gs.rgba, v[1].z); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; d -= ay; + } + y += sy; d += ax; + } + } +} + +void drawLineG(Vertex * v) { + int dx = v[1].x - v[0].x; + int dy = v[1].y - v[0].y; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + int x = v[0].x; + int y = v[0].y; + u32 r0, g0, b0, a0; + u32 r1, g1, b1, a1; + int dr, dg, db, da; + +#ifdef GS_LOG + GS_LOG("drawLineG %dx%d %x - %dx%d %x\n", + v[0].x, v[0].y, v[0].rgba, v[1].x, v[1].y, v[1].rgba); +#endif + + SETdrawPixel(); + + r0 = (v[0].rgba & 0x00ff0000); + g0 = (v[0].rgba & 0x0000ff00) << 8; + b0 = (v[0].rgba & 0x000000ff) << 16; + a0 = (v[0].rgba & 0xff000000) >> 8; + r1 = (v[1].rgba & 0x00ff0000); + g1 = (v[1].rgba & 0x0000ff00) << 8; + b1 = (v[1].rgba & 0x000000ff) << 16; + a1 = (v[1].rgba & 0xff000000) >> 8; + + if (ax > ay) { + int d = ay - (ax >> 1); + + if (dx == 0) return; + dr = ((int)r1 - (int)r0) / dx; + dg = ((int)g1 - (int)g0) / dx; + db = ((int)b1 - (int)b0) / dx; + da = ((int)a1 - (int)a0) / dx; + + while (x != v[1].x) { + drawPixel(x, y, ( r0 & 0xff0000) | + ((g0 & 0xff0000) >> 8) | + ((b0 & 0xff0000) >> 16) | + ((a0 & 0xff0000) << 8)); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; d += ay; + r0+= dr; g0+= dg; b0+= db; a0+= da; + } + } else { + int d = ax - (ay >> 1); + + if (dy == 0) return; + dr = ((int)r1 - (int)r0) / dy; + dg = ((int)g1 - (int)g0) / dy; + db = ((int)b1 - (int)b0) / dy; + da = ((int)a1 - (int)a0) / dy; + + while (y != v[1].y) { + drawPixel(x, y, ( r0 & 0xff0000) | + ((g0 & 0xff0000) >> 8) | + ((b0 & 0xff0000) >> 16) | + ((a0 & 0xff0000) << 8)); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; + d -= ay; + } + y += sy; d += ax; + r0+= dr; g0+= dg; b0+= db; a0+= da; + } + } +} + +void drawLineG_Z(Vertex * v) { + int dx = v[1].x - v[0].x; + int dy = v[1].y - v[0].y; + int ax = ABS(dx) << 1; + int ay = ABS(dy) << 1; + int sx = (dx >= 0) ? 1 : -1; + int sy = (dy >= 0) ? 1 : -1; + int x = v[0].x; + int y = v[0].y; + u32 r0, g0, b0, a0; + u32 r1, g1, b1, a1; + int dr, dg, db, da; + +#ifdef GS_LOG + GS_LOG("drawLineG_Z %dx%d %x - %dx%d %x\n", + v[0].x, v[0].y, v[0].rgba, v[1].x, v[1].y, v[1].rgba); +#endif + + SETdrawPixelZ(); + + r0 = (v[0].rgba & 0x00ff0000); + g0 = (v[0].rgba & 0x0000ff00) << 8; + b0 = (v[0].rgba & 0x000000ff) << 16; + a0 = (v[0].rgba & 0xff000000) >> 8; + r1 = (v[1].rgba & 0x00ff0000); + g1 = (v[1].rgba & 0x0000ff00) << 8; + b1 = (v[1].rgba & 0x000000ff) << 16; + a1 = (v[1].rgba & 0xff000000) >> 8; + + if (ax > ay) { + int d = ay - (ax >> 1); + + if (dx == 0) return; + dr = ((int)r1 - (int)r0) / dx; + dg = ((int)g1 - (int)g0) / dx; + db = ((int)b1 - (int)b0) / dx; + da = ((int)a1 - (int)a0) / dx; + + while (x != v[1].x) { + drawPixelZ(x, y, ( r0 & 0xff0000) | + ((g0 & 0xff0000) >> 8) | + ((b0 & 0xff0000) >> 16) | + ((a0 & 0xff0000) << 8), v[1].z); + + if (d > 0 || (d == 0 && sx == 1)) { + y += sy; + d -= ax; + } + x += sx; d += ay; + r0+= dr; g0+= dg; b0+= db; + } + } else { + int d = ax - (ay >> 1); + + if (dy == 0) return; + dr = ((int)r1 - (int)r0) / dy; + dg = ((int)g1 - (int)g0) / dy; + db = ((int)b1 - (int)b0) / dy; + da = ((int)a1 - (int)a0) / dy; + + while (y != v[1].y) { + drawPixelZ(x, y, ( r0 & 0xff0000) | + ((g0 & 0xff0000) >> 8) | + ((b0 & 0xff0000) >> 16) | + ((a0 & 0xff0000) << 8), v[1].z); + + if (d > 0 || (d == 0 && sy == 1)) { + x += sx; + d -= ay; + } + y += sy; d += ax; + r0+= dr; g0+= dg; b0+= db; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void drawSprite(Vertex * v) { + int x, y; + +#ifdef GS_LOG + GS_LOG("drawSprite %dx%d - %dx%d %lx\n", + v[0].x, v[0].y, v[1].x, v[1].y, gs.rgba); +#endif + + SETdrawPixel(); + for (y = v[0].y; y < v[1].y; y++) + for (x = v[0].x; x < v[1].x; x++) + drawPixel(x, y, gs.rgba); +} + +void drawSprite_F(Vertex * v) { + int x, y; + +#ifdef GS_LOG + GS_LOG("drawSprite_F %dx%d - %dx%d %lx\n", + v[0].x, v[0].y, v[1].x, v[1].y, gs.rgba); +#endif + + SETdrawPixelF(); + for (y = v[0].y; y < v[1].y; y++) + for (x = v[0].x; x < v[1].x; x++) + drawPixelF(x, y, gs.rgba, v[1].f); +} + +void drawSprite_Z(Vertex * v) { + int x, y; + +#ifdef GS_LOG + GS_LOG("drawSprite_Z %dx%d %lx - %dx%d %lx\n", + v[0].x, v[0].y, v[0].rgba, v[1].x, v[1].y, v[1].rgba); +#endif + + SETdrawPixelZ(); + + for (y = v[0].y; y < v[1].y; y++) { + for (x = v[0].x; x < v[1].x; x++) { + drawPixelZ(x, y, gs.rgba, v[1].z); + } + } +} + +void drawSprite_ZF(Vertex * v) { + int x, y; + +#ifdef GS_LOG + GS_LOG("drawSprite_ZF %dx%d %lx - %dx%d %lx\n", + v[0].x, v[0].y, v[0].rgba, v[1].x, v[1].y, v[1].rgba); +#endif + + SETdrawPixelZF(); + + for (y = v[0].y; y < v[1].y; y++) { + for (x = v[0].x; x < v[1].x; x++) { + drawPixelZF(x, y, gs.rgba, v[1].z, v[1].f); + } + } +} + +//////////////////////////////////////////////////////////////////////// +// TEXTURED SPRITE +//////////////////////////////////////////////////////////////////////// + + +#define _drawSpriteT(ftx) \ + SetTexture(); \ + SETdrawPixel(); \ + \ + if (vx[1].x == vx[0].x) uinc = 0; \ + else uinc = ((vx[1].u - vx[0].u) << 16) / (vx[1].x - vx[0].x); \ + if (vx[1].y == vx[0].y) vinc = 0; \ + else vinc = ((vx[1].v - vx[0].v) << 16) / (vx[1].y - vx[0].y); \ + \ + for (y = vx[0].y, vpos = vx[0].v << 16; y < vx[1].y; y++, vpos+= vinc) { \ + v = vpos >> 16; \ + for (x = vx[0].x, upos = vx[0].u << 16; x < vx[1].x; x++, upos+= uinc) { \ + u = upos >> 16; \ + drawPixel(x, y, ftx); \ + } \ + } + +void drawSpriteTDecal(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTDecal %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + _drawSpriteT( + GetTexturePixel32(u, v) + ); +} + +void drawSpriteTModulate(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTModulate %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT( + colModulate(GetTexturePixel32(u, v)) + ); +} + +void drawSpriteTHighlight(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTHighlight %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT( + colHighlight(GetTexturePixel32(u, v)) + ); +} + +void drawSpriteTHighlight2(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTHighlight2 %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT( + colHighlight2(GetTexturePixel32(u, v)) + ); +} + +//////////////////////////////////////////////////////////////////////// +// TEXTURED SPRITE WITH Z-MAPPING +//////////////////////////////////////////////////////////////////////// + +#define _drawSpriteT_Z(ftx) \ + SetTexture(); \ + SETdrawPixelZ(); \ + \ + if (vx[1].x == vx[0].x) uinc = 0; \ + else uinc = ((vx[1].u - vx[0].u) << 16) / (vx[1].x - vx[0].x); \ + if (vx[1].y == vx[0].y) vinc = 0; \ + else vinc = ((vx[1].v - vx[0].v) << 16) / (vx[1].y - vx[0].y); \ + \ + for (y = vx[0].y, vpos = vx[0].v << 16; y < vx[1].y; y++, vpos+= vinc) { \ + v = vpos >> 16; \ + for (x = vx[0].x, upos = vx[0].u << 16; x < vx[1].x; x++, upos+= uinc) { \ + u = upos >> 16; \ + drawPixelZ(x, y, ftx, vx[1].z); \ + } \ + } + +void drawSpriteTDecal_Z(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTDecal_Z %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + _drawSpriteT_Z( + GetTexturePixel32(u, v) + ); +} + +void drawSpriteTModulate_Z(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTModulate_Z %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, tbp0=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->tbp0, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT_Z( + colModulate(GetTexturePixel32(u, v)) + ); +} + +void drawSpriteTHighlight_Z(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTHighlight_Z %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT_Z( + colHighlight(GetTexturePixel32(u, v)) + ); +} + +void drawSpriteTHighlight2_Z(Vertex * vx) { + int x, y; + int u, v; + int upos, uinc; + int vpos, vinc; + +#ifdef GS_LOG + GS_LOG("drawSpriteTHighlight2_Z %dx%d - %dx%d %lx; tex: %dx%d - %dx%d (psm=%x, cbp=%x, csm=%x, cpsm=%x)\n", + vx[0].x, vx[0].y, vx[1].x, vx[1].y, gs.rgba, + vx[0].u, vx[0].v, vx[1].u, vx[1].v, + tex0->psm, tex0->cbp, tex0->csm, tex0->cpsm); +#endif + + colSetCol(gs.rgba); + _drawSpriteT_Z( + colHighlight2(GetTexturePixel32(u, v)) + ); +} + + + +typedef struct { + s32 X, U, V; + s32 R, G, B, A; + s64 Z; +} tagPolyEdge; + +tagPolyEdge ForwardEdges[1024*8]; +tagPolyEdge BackwardEdges[1024*8]; + +#define drawTriangle(scanFunc, drawFunc) { \ + int i; \ + int nYMin, nYMax; \ + int nPosMin, nPosMax; \ + int nPos1, nPos2; \ + int nY; \ + \ + nYMin = v[0].y; \ + nYMax = v[0].y; \ + nPosMin = 0; \ + nPosMax = 0; \ + \ + for (i=1; i<3; i++) { \ + if (v[i].y > nYMax) { \ + nYMax = v[i].y; \ + nPosMax = i; \ + } \ + \ + if (v[i].y < nYMin) { \ + nYMin = v[i].y; \ + nPosMin = i; \ + } \ + } \ + \ + if (nYMax == nYMin) \ + return; \ + \ + nPos1 = nPosMin; \ + nPos2 = nPos1; \ + while (nPos1 != nPosMax) { \ + nPos2 ++; \ + if (nPos2 == 3) \ + nPos2 = 0; \ + \ + scanFunc(ForwardEdges, &v[nPos1], &v[nPos2]); \ + nPos1 = nPos2; \ + } \ + \ + nPos1 = nPosMin; \ + nPos2 = nPos1; \ + while (nPos1 != nPosMax) { \ + nPos2 --; \ + if (nPos2 == -1) \ + nPos2 = 2; \ + \ + scanFunc(BackwardEdges, &v[nPos1], &v[nPos2]); \ + nPos1 = nPos2; \ + } \ + \ + if (nYMin < 0) nYMin = 0; \ + for (nY = nYMin; nY < nYMax; nY++) { \ + if (BackwardEdges[nY].X < ForwardEdges[nY].X) { \ + drawFunc(nY, &BackwardEdges[nY], &ForwardEdges[nY]); \ + } else { \ + drawFunc(nY, &ForwardEdges[nY], &BackwardEdges[nY]); \ + } \ + } \ +} + + +void scanEdgeF(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + int nX, nY; + int nXInc; + + if (v1->y == v2->y) + return; + + nX = v1->x << 16; + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + } +} + +void drawHLineF(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { + int nX; + + if (stEdgeEnd->X <= stEdgeIni->X) { + return; + } + + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { + drawPixel(nX, nY, gs.rgba); + } +} + +void drawTriangleF(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleF %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); +#endif + + SETdrawPixel(); + + drawTriangle(scanEdgeF, drawHLineF); +} + +void scanEdgeFZ(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + s32 nX, nY; + s32 nXInc; + s64 nZ; + s64 nZInc; + + if (v1->y == v2->y) + return; + + nX = v1->x << 16; + nZ = (u64)v1->z << 16; + + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nZInc = ((s64)((s64)v2->z - v1->z) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nZ += nZInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].Z = nZ; nZ += nZInc; + } +} + +void drawHLineFZ(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { + s32 nX; + s64 nZ; + s64 nZInc; + + if (stEdgeEnd->X <= stEdgeIni->X) { + return; + } + + nZ = stEdgeIni->Z; + nZInc = (s64)((s64)stEdgeEnd->Z - stEdgeIni->Z) / (stEdgeEnd->X - stEdgeIni->X); + + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { + drawPixelZ(nX, nY, gs.rgba, (u32)(nZ >> 16)); + nZ += nZInc; + } +} + +void drawTriangleF_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleF_Z %dx%dx%lx - %dx%dx%lx - %dx%dx%lx rgba=%x\n", + v[0].x, v[0].y, v[0].z, v[1].x, v[1].y, v[1].z, v[2].x, v[2].y, v[2].z, gs.rgba); +#endif + + SETdrawPixelZ(); + + drawTriangle(scanEdgeFZ, drawHLineFZ); +} + + +void scanEdgeG(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + s32 nX, nY, nR, nG, nB, nA; + s32 nXInc, nRInc, nGInc, nBInc, nAInc; + s32 r1, g1, b1, a1; + s32 r2, g2, b2, a2; + + if (v1->y == v2->y) + return; + + b1 = (v1->rgba & 0x000000FF); + g1 = (v1->rgba & 0x0000FF00) >> 8; + r1 = (v1->rgba & 0x00FF0000) >> 16; + a1 = (v1->rgba & 0xFF000000) >> 24; + b2 = (v2->rgba & 0x000000FF); + g2 = (v2->rgba & 0x0000FF00) >> 8; + r2 = (v2->rgba & 0x00FF0000) >> 16; + a2 = (v2->rgba & 0xFF000000) >> 24; + + nX = v1->x << 16; + nR = r1 << 16; + nG = g1 << 16; + nB = b1 << 16; + nA = a1 << 16; + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nRInc = (( r2 - r1) << 16) / (v2->y - v1->y); + nGInc = (( g2 - g1) << 16) / (v2->y - v1->y); + nBInc = (( b2 - b1) << 16) / (v2->y - v1->y); + nAInc = (( a2 - a1) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nR += nRInc; + nG += nGInc; + nB += nBInc; + nA += nAInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].R = nR; nR += nRInc; + pastEdge[nY].G = nG; nG += nGInc; + pastEdge[nY].B = nB; nB += nBInc; + pastEdge[nY].A = nA; nA += nAInc; + } +} + +void drawHLineG(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { + s32 nX, nR, nG, nB, nA; + s32 nRInc, nGInc, nBInc, nAInc; + + if (stEdgeEnd->X <= stEdgeIni->X) { + return; + } + + nR = stEdgeIni->R; + nG = stEdgeIni->G; + nB = stEdgeIni->B; + nA = stEdgeIni->A; + nRInc = (stEdgeEnd->R - stEdgeIni->R) / (stEdgeEnd->X - stEdgeIni->X); + nGInc = (stEdgeEnd->G - stEdgeIni->G) / (stEdgeEnd->X - stEdgeIni->X); + nBInc = (stEdgeEnd->B - stEdgeIni->B) / (stEdgeEnd->X - stEdgeIni->X); + nAInc = (stEdgeEnd->A - stEdgeIni->A) / (stEdgeEnd->X - stEdgeIni->X); + + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { + drawPixel(nX, nY, ( nR & 0xff0000) | + ((nG & 0xff0000) >> 8) | + ((nB & 0xff0000) >> 16) | + ((nA & 0xff0000) << 8)); + nR += nRInc; nG += nGInc; nB += nBInc; nA += nAInc; + } +} + +void drawTriangleG(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleG %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, v[0].rgba); +#endif + + SETdrawPixel(); + + drawTriangle(scanEdgeG, drawHLineG); +} + + +void scanEdgeGZ(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + s32 nX, nY, nR, nG, nB, nA; + s32 nXInc, nRInc, nGInc, nBInc, nAInc; + s32 r1, g1, b1, a1; + s32 r2, g2, b2, a2; + s64 nZ; + s64 nZInc; + + if (v1->y == v2->y) + return; + + b1 = (v1->rgba & 0x000000FF); + g1 = (v1->rgba & 0x0000FF00) >> 8; + r1 = (v1->rgba & 0x00FF0000) >> 16; + a1 = (v1->rgba & 0xFF000000) >> 24; + b2 = (v2->rgba & 0x000000FF); + g2 = (v2->rgba & 0x0000FF00) >> 8; + r2 = (v2->rgba & 0x00FF0000) >> 16; + a2 = (v2->rgba & 0xFF000000) >> 24; + + nX = v1->x << 16; + nZ = (u64)v1->z << 16; + nR = r1 << 16; + nG = g1 << 16; + nB = b1 << 16; + nA = a1 << 16; + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nZInc = ((s64)((s64)v2->z - v1->z) << 16) / (v2->y - v1->y); + nRInc = (( r2 - r1) << 16) / (v2->y - v1->y); + nGInc = (( g2 - g1) << 16) / (v2->y - v1->y); + nBInc = (( b2 - b1) << 16) / (v2->y - v1->y); + nAInc = (( a2 - a1) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nZ += nZInc; + nR += nRInc; + nG += nGInc; + nB += nBInc; + nA += nAInc; + } + for (;nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].Z = nZ; nZ += nZInc; + pastEdge[nY].R = nR; nR += nRInc; + pastEdge[nY].G = nG; nG += nGInc; + pastEdge[nY].B = nB; nB += nBInc; + pastEdge[nY].A = nA; nA += nAInc; + } +} + +void drawHLineGZ(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { + s32 nX, nR, nG, nB, nA; + s32 nRInc, nGInc, nBInc, nAInc; + s64 nZ; + s64 nZInc; + + if (stEdgeEnd->X <= stEdgeIni->X) { + return; + } + + nZ = stEdgeIni->Z; + nR = stEdgeIni->R; + nG = stEdgeIni->G; + nB = stEdgeIni->B; + nA = stEdgeIni->A; + nZInc = (s64)((s64)stEdgeEnd->Z - stEdgeIni->Z) / (stEdgeEnd->X - stEdgeIni->X); + nRInc = (stEdgeEnd->R - stEdgeIni->R) / (stEdgeEnd->X - stEdgeIni->X); + nGInc = (stEdgeEnd->G - stEdgeIni->G) / (stEdgeEnd->X - stEdgeIni->X); + nBInc = (stEdgeEnd->B - stEdgeIni->B) / (stEdgeEnd->X - stEdgeIni->X); + nAInc = (stEdgeEnd->A - stEdgeIni->A) / (stEdgeEnd->X - stEdgeIni->X); + + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { + drawPixelZ(nX, nY, ( nR & 0xff0000) | + ((nG & 0xff0000) >> 8) | + ((nB & 0xff0000) >> 16) | + ((nA & 0xff0000) << 8), (u32)(nZ >> 16)); + nZ += nZInc; + nR += nRInc; nG += nGInc; nB += nBInc; nA += nAInc; + } +} + +void drawTriangleG_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleG_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, v[0].rgba); +#endif + + SETdrawPixelZ(); + + drawTriangle(scanEdgeGZ, drawHLineGZ); +} + + +void scanEdgeFT(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + int nX, nY, nU, nV; + int nXInc, nUInc, nVInc; + + if (v1->y == v2->y) + return; + + nX = v1->x << 16; + nU = v1->u << 16; + nV = v1->v << 16; + + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nUInc = ((v2->u - v1->u) << 16) / (v2->y - v1->y); + nVInc = ((v2->v - v1->v) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nU += nUInc; + nV += nVInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].U = nU; nU += nUInc; + pastEdge[nY].V = nV; nV += nVInc; + } +} + + +#define _drawHLineFT(name, ftx) \ +void drawHLineFT##name(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { \ + int nX, nU, nV; \ + int nUInc, nVInc; \ + \ + if (stEdgeEnd->X <= stEdgeIni->X) { \ + return; \ + } \ + \ + nX = stEdgeIni->X; \ + nU = stEdgeIni->U; \ + nV = stEdgeIni->V; \ + nUInc = (stEdgeEnd->U - stEdgeIni->U) / (stEdgeEnd->X - stEdgeIni->X); \ + nVInc = (stEdgeEnd->V - stEdgeIni->V) / (stEdgeEnd->X - stEdgeIni->X); \ + \ + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { \ + drawPixel(nX, nY, ftx); \ + nU += nUInc; nV += nVInc; \ + } \ +} + +_drawHLineFT(Decal, + GetTexturePixel32(nU >> 16, nV >> 16) +); +_drawHLineFT(Modulate, + colModulate(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineFT(Highlight, + colHighlight(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineFT(Highlight2, + colHighlight2(GetTexturePixel32(nU >> 16, nV >> 16)) +); + +void drawTriangleFTDecal(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTDecal %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + + drawTriangle(scanEdgeFT, drawHLineFTDecal); +} + +void drawTriangleFTModulate(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTModulate %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFT, drawHLineFTModulate); +} + +void drawTriangleFTHighlight(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTHighlight %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFT, drawHLineFTHighlight); +} + +void drawTriangleFTHighlight2(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTHighlight2 %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFT, drawHLineFTHighlight2); +} + +void scanEdgeFTZ(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + int nX, nY, nU, nV; + int nXInc, nUInc, nVInc; + s64 nZ; + s64 nZInc; + + if (v1->y == v2->y) + return; + + nX = v1->x << 16; + nZ = (u64)v1->z << 16; + nU = v1->u << 16; + nV = v1->v << 16; + + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nZInc = ((s64)((s64)v2->z - v1->z) << 16) / (v2->y - v1->y); + nUInc = ((v2->u - v1->u) << 16) / (v2->y - v1->y); + nVInc = ((v2->v - v1->v) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nZ += nZInc; + nU += nUInc; + nV += nVInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].Z = nZ; nZ += nZInc; + pastEdge[nY].U = nU; nU += nUInc; + pastEdge[nY].V = nV; nV += nVInc; + } +} + + +#define _drawHLineFTZ(name, ftx) \ +void drawHLineFTZ##name(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { \ + int nX, nU, nV; \ + int nUInc, nVInc; \ + s64 nZ; \ + s64 nZInc; \ + \ + if (stEdgeEnd->X <= stEdgeIni->X) { \ + return; \ + } \ + \ + nX = stEdgeIni->X; \ + nZ = stEdgeIni->Z; \ + nU = stEdgeIni->U; \ + nV = stEdgeIni->V; \ + nZInc = (s64)((s64)stEdgeEnd->Z - stEdgeIni->Z) / (stEdgeEnd->X - stEdgeIni->X); \ + nUInc = (stEdgeEnd->U - stEdgeIni->U) / (stEdgeEnd->X - stEdgeIni->X); \ + nVInc = (stEdgeEnd->V - stEdgeIni->V) / (stEdgeEnd->X - stEdgeIni->X); \ + \ + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { \ + drawPixelZ(nX, nY, ftx, (u32)(nZ >> 16)); \ + nZ += nZInc; \ + nU += nUInc; nV += nVInc; \ + } \ +} + +_drawHLineFTZ(Decal, + GetTexturePixel32(nU >> 16, nV >> 16) +); +_drawHLineFTZ(Modulate, + colModulate(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineFTZ(Highlight, + colHighlight(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineFTZ(Highlight2, + colHighlight2(GetTexturePixel32(nU >> 16, nV >> 16)) +); + +void drawTriangleFTDecal_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTDecal_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + + drawTriangle(scanEdgeFTZ, drawHLineFTZDecal); +} + +void drawTriangleFTModulate_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTModulate_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFTZ, drawHLineFTZModulate); +} + +void drawTriangleFTHighlight_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTHighlight_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFTZ, drawHLineFTZHighlight); +} + +void drawTriangleFTHighlight2_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleFTHighlight2_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + colSetCol(gs.rgba); + + drawTriangle(scanEdgeFTZ, drawHLineFTZHighlight2); +} + +/**************************/ +/* Gouraud Shaded/Textued */ + +void scanEdgeGT(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + s32 nX, nU, nV, nY, nR, nG, nB, nA; + s32 nXInc, nUInc, nVInc, nRInc, nGInc, nBInc, nAInc; + s32 r1, g1, b1, a1; + s32 r2, g2, b2, a2; + + if (v1->y == v2->y) + return; + + b1 = (v1->rgba & 0x000000FF); + g1 = (v1->rgba & 0x0000FF00) >> 8; + r1 = (v1->rgba & 0x00FF0000) >> 16; + a1 = (v1->rgba & 0xFF000000) >> 24; + b2 = (v2->rgba & 0x000000FF); + g2 = (v2->rgba & 0x0000FF00) >> 8; + r2 = (v2->rgba & 0x00FF0000) >> 16; + a2 = (v2->rgba & 0xFF000000) >> 24; + + nX = v1->x << 16; + nR = r1 << 16; + nG = g1 << 16; + nB = b1 << 16; + nA = a1 << 16; + nU = v1->u << 16; + nV = v1->v << 16; + + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nRInc = (( r2 - r1) << 16) / (v2->y - v1->y); + nGInc = (( g2 - g1) << 16) / (v2->y - v1->y); + nBInc = (( b2 - b1) << 16) / (v2->y - v1->y); + nAInc = (( a2 - a1) << 16) / (v2->y - v1->y); + nUInc = ((v2->u - v1->u) << 16) / (v2->y - v1->y); + nVInc = ((v2->v - v1->v) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nU += nUInc; + nV += nVInc; + nR += nRInc; + nG += nGInc; + nB += nBInc; + nA += nAInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].U = nU; nU += nUInc; + pastEdge[nY].V = nV; nV += nVInc; + pastEdge[nY].R = nR; nR += nRInc; + pastEdge[nY].G = nG; nG += nGInc; + pastEdge[nY].B = nB; nB += nBInc; + pastEdge[nY].A = nA; nA += nAInc; + } +} + +#define _drawHLineGT(name, ftx) \ +void drawHLineGT##name(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { \ + s32 nX, nU, nV, nR, nG, nB, nA; \ + s32 nUInc, nVInc, nRInc, nGInc, nBInc, nAInc; \ + \ + if (stEdgeEnd->X <= stEdgeIni->X) { \ + return; \ + } \ + \ + nR = stEdgeIni->R; \ + nG = stEdgeIni->G; \ + nB = stEdgeIni->B; \ + nA = stEdgeIni->A; \ + nU = stEdgeIni->U; \ + nV = stEdgeIni->V; \ + nRInc = (stEdgeEnd->R - stEdgeIni->R) / (stEdgeEnd->X - stEdgeIni->X); \ + nGInc = (stEdgeEnd->G - stEdgeIni->G) / (stEdgeEnd->X - stEdgeIni->X); \ + nBInc = (stEdgeEnd->B - stEdgeIni->B) / (stEdgeEnd->X - stEdgeIni->X); \ + nAInc = (stEdgeEnd->A - stEdgeIni->A) / (stEdgeEnd->X - stEdgeIni->X); \ + nUInc = (stEdgeEnd->U - stEdgeIni->U) / (stEdgeEnd->X - stEdgeIni->X); \ + nVInc = (stEdgeEnd->V - stEdgeIni->V) / (stEdgeEnd->X - stEdgeIni->X); \ + \ + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { \ + colSetCol(( nR & 0xff0000) | \ + ((nG & 0xff0000) >> 8) | \ + ((nB & 0xff0000) >> 16) | \ + ((nA & 0xff0000) << 8)); \ + drawPixel(nX, nY, ftx); \ + nU += nUInc; nV += nVInc; \ + nR += nRInc; nG += nGInc; nB += nBInc; nA += nAInc; \ + } \ +} + +_drawHLineGT(Modulate, + colModulate(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineGT(Highlight, + colHighlight(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineGT(Highlight2, + colHighlight2(GetTexturePixel32(nU >> 16, nV >> 16)) +); + + +void drawTriangleGTDecal(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTDecal %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + drawTriangleFTDecal(v); +} + +void drawTriangleGTModulate(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTModulate %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + + drawTriangle(scanEdgeGT, drawHLineGTModulate); +} + +void drawTriangleGTHighlight(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTHighlight %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + + drawTriangle(scanEdgeGT, drawHLineGTHighlight); +} + +void drawTriangleGTHighlight2(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTHighlight2 %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixel(); + + drawTriangle(scanEdgeGT, drawHLineGTHighlight2); +} + +void scanEdgeGTZ(tagPolyEdge* pastEdge, Vertex *v1, Vertex *v2) { + s32 nX, nU, nV, nY, nR, nG, nB, nA; + s32 nXInc, nUInc, nVInc, nRInc, nGInc, nBInc, nAInc; + s64 nZ; + s64 nZInc; + s32 r1, g1, b1, a1; + s32 r2, g2, b2, a2; + + if (v1->y == v2->y) + return; + + b1 = (v1->rgba & 0x000000FF); + g1 = (v1->rgba & 0x0000FF00) >> 8; + r1 = (v1->rgba & 0x00FF0000) >> 16; + a1 = (v1->rgba & 0xFF000000) >> 24; + b2 = (v2->rgba & 0x000000FF); + g2 = (v2->rgba & 0x0000FF00) >> 8; + r2 = (v2->rgba & 0x00FF0000) >> 16; + a2 = (v2->rgba & 0xFF000000) >> 24; + + nX = v1->x << 16; + nZ = (u64)v1->z << 16; + nR = r1 << 16; + nG = g1 << 16; + nB = b1 << 16; + nA = a1 << 16; + nU = v1->u << 16; + nV = v1->v << 16; + + nXInc = ((v2->x - v1->x) << 16) / (v2->y - v1->y); + nZInc = ((s64)((s64)v2->z - v1->z) << 16) / (v2->y - v1->y); + nRInc = (( r2 - r1) << 16) / (v2->y - v1->y); + nGInc = (( g2 - g1) << 16) / (v2->y - v1->y); + nBInc = (( b2 - b1) << 16) / (v2->y - v1->y); + nAInc = (( a2 - a1) << 16) / (v2->y - v1->y); + nUInc = ((v2->u - v1->u) << 16) / (v2->y - v1->y); + nVInc = ((v2->v - v1->v) << 16) / (v2->y - v1->y); + + for (nY = v1->y; nY < 0; nY++) { + nX += nXInc; + nZ += nZInc; + nU += nUInc; + nV += nVInc; + nR += nRInc; + nG += nGInc; + nB += nBInc; + nA += nAInc; + } + for (; nY < v2->y; nY++) { + pastEdge[nY].X = nX >> 16; nX += nXInc; + pastEdge[nY].Z = nZ; nZ += nZInc; + pastEdge[nY].U = nU; nU += nUInc; + pastEdge[nY].V = nV; nV += nVInc; + pastEdge[nY].R = nR; nR += nRInc; + pastEdge[nY].G = nG; nG += nGInc; + pastEdge[nY].B = nB; nB += nBInc; + pastEdge[nY].A = nA; nA += nAInc; + } +} + +#define _drawHLineGTZ(name, ftx) \ +void drawHLineGTZ##name(int nY, tagPolyEdge *stEdgeIni, tagPolyEdge *stEdgeEnd) { \ + s32 nX, nU, nV, nR, nG, nB, nA; \ + s32 nUInc, nVInc, nRInc, nGInc, nBInc, nAInc; \ + s64 nZ; \ + s64 nZInc; \ + \ + if (stEdgeEnd->X <= stEdgeIni->X) { \ + return; \ + } \ + \ + nZ = stEdgeIni->Z; \ + nR = stEdgeIni->R; \ + nG = stEdgeIni->G; \ + nB = stEdgeIni->B; \ + nA = stEdgeIni->A; \ + nU = stEdgeIni->U; \ + nV = stEdgeIni->V; \ + nZInc = (s64)((s64)stEdgeEnd->Z - stEdgeIni->Z) / (stEdgeEnd->X - stEdgeIni->X); \ + nRInc = (stEdgeEnd->R - stEdgeIni->R) / (stEdgeEnd->X - stEdgeIni->X); \ + nGInc = (stEdgeEnd->G - stEdgeIni->G) / (stEdgeEnd->X - stEdgeIni->X); \ + nBInc = (stEdgeEnd->B - stEdgeIni->B) / (stEdgeEnd->X - stEdgeIni->X); \ + nAInc = (stEdgeEnd->A - stEdgeIni->A) / (stEdgeEnd->X - stEdgeIni->X); \ + nUInc = (stEdgeEnd->U - stEdgeIni->U) / (stEdgeEnd->X - stEdgeIni->X); \ + nVInc = (stEdgeEnd->V - stEdgeIni->V) / (stEdgeEnd->X - stEdgeIni->X); \ + \ + for (nX = stEdgeIni->X; nX <= stEdgeEnd->X; nX++) { \ + colSetCol(( nR & 0xff0000) | \ + ((nG & 0xff0000) >> 8) | \ + ((nB & 0xff0000) >> 16) | \ + ((nA & 0xff0000) << 8)); \ + drawPixelZ(nX, nY, ftx, (u32)(nZ >> 16)); \ + nZ += nZInc; \ + nU += nUInc; nV += nVInc; \ + nR += nRInc; nG += nGInc; nB += nBInc; nA += nAInc; \ + } \ +} + +_drawHLineGTZ(Modulate, + colModulate(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineGTZ(Highlight, + colHighlight(GetTexturePixel32(nU >> 16, nV >> 16)) +); +_drawHLineGTZ(Highlight2, + colHighlight2(GetTexturePixel32(nU >> 16, nV >> 16)) +); + +void drawTriangleGTDecal_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTDecal_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + drawTriangleFTDecal_Z(v); +} + +void drawTriangleGTModulate_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTModulate_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + + drawTriangle(scanEdgeGTZ, drawHLineGTZModulate); +} + +void drawTriangleGTHighlight_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTHighlight_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + + drawTriangle(scanEdgeGTZ, drawHLineGTZHighlight); +} + +void drawTriangleGTHighlight2_Z(Vertex * v) { +#ifdef GS_LOG + GS_LOG("drawTriangleGTHighlight2_Z %dx%d - %dx%d - %dx%d rgba=%x\n", + v[0].x, v[0].y, v[1].x, v[1].y, v[2].x, v[2].y, gs.rgba); + GS_LOG("uv: %xx%x - %xx%x - %xx%x\n", + v[0].u, v[0].v, v[1].u, v[1].v, v[2].u, v[2].v); +#endif + + SetTexture(); + SETdrawPixelZ(); + + drawTriangle(scanEdgeGTZ, drawHLineGTZHighlight2); +} + + +/* + 3DFC + http://www.geocities.com/SiliconValley/Bay/1704 + +*/ + diff --git a/plugins/gs/GSsoft/Src/Soft.h b/plugins/gs/GSsoft/Src/Soft.h new file mode 100644 index 0000000..5fb5695 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Soft.h @@ -0,0 +1,107 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SOFT_H__ +#define __SOFT_H__ + +void drawLineF(Vertex *v); +void drawLineF_Z(Vertex *v); +void drawLineF_F(Vertex *v); +void drawLineF_ZF(Vertex *v); + +void drawLineG(Vertex *v); +void drawLineG_Z(Vertex *v); +void drawLineG_F(Vertex *v); +void drawLineG_ZF(Vertex *v); + +void drawTriangleF(Vertex *v); +void drawTriangleF_Z(Vertex *v); +void drawTriangleF_F(Vertex *v); +void drawTriangleF_ZF(Vertex *v); + +void drawTriangleG(Vertex *v); +void drawTriangleG_Z(Vertex *v); +void drawTriangleG_F(Vertex *v); +void drawTriangleG_ZF(Vertex *v); + +void drawTriangleFTDecal(Vertex *v); +void drawTriangleFTDecal_Z(Vertex * v); +void drawTriangleFTDecal_F(Vertex * v); +void drawTriangleFTDecal_ZF(Vertex * v); + +void drawTriangleFTModulate(Vertex *v); +void drawTriangleFTModulate_Z(Vertex * v); +void drawTriangleFTModulate_F(Vertex * v); +void drawTriangleFTModulate_ZF(Vertex * v); + +void drawTriangleFTHighlight(Vertex *v); +void drawTriangleFTHighlight_Z(Vertex * v); +void drawTriangleFTHighlight_F(Vertex * v); +void drawTriangleFTHighlight_ZF(Vertex * v); + +void drawTriangleFTHighlight2(Vertex *v); +void drawTriangleFTHighlight2_Z(Vertex * v); +void drawTriangleFTHighlight2_F(Vertex * v); +void drawTriangleFTHighlight2_ZF(Vertex * v); + +void drawTriangleGTDecal(Vertex *v); +void drawTriangleGTDecal_Z(Vertex * v); +void drawTriangleGTDecal_F(Vertex * v); +void drawTriangleGTDecal_ZF(Vertex * v); + +void drawTriangleGTModulate(Vertex *v); +void drawTriangleGTModulate_Z(Vertex * v); +void drawTriangleGTModulate_F(Vertex * v); +void drawTriangleGTModulate_ZF(Vertex * v); + +void drawTriangleGTHighlight(Vertex *v); +void drawTriangleGTHighlight_Z(Vertex * v); +void drawTriangleGTHighlight_F(Vertex * v); +void drawTriangleGTHighlight_ZF(Vertex * v); + +void drawTriangleGTHighlight2(Vertex *v); +void drawTriangleGTHighlight2_Z(Vertex * v); +void drawTriangleGTHighlight2_F(Vertex * v); +void drawTriangleGTHighlight2_ZF(Vertex * v); + +void drawSprite(Vertex *v); +void drawSprite_Z(Vertex *v); +void drawSprite_F(Vertex *v); +void drawSprite_ZF(Vertex *v); + +void drawSpriteTDecal(Vertex *v); +void drawSpriteTDecal_Z(Vertex * v); +void drawSpriteTDecal_F(Vertex * v); +void drawSpriteTDecal_ZF(Vertex * v); + +void drawSpriteTModulate(Vertex *v); +void drawSpriteTModulate_Z(Vertex * v); +void drawSpriteTModulate_F(Vertex * v); +void drawSpriteTModulate_ZF(Vertex * v); + +void drawSpriteTHighlight(Vertex *v); +void drawSpriteTHighlight_Z(Vertex * v); +void drawSpriteTHighlight_F(Vertex * v); +void drawSpriteTHighlight_ZF(Vertex * v); + +void drawSpriteTHighlight2(Vertex *v); +void drawSpriteTHighlight2_Z(Vertex * v); +void drawSpriteTHighlight2_F(Vertex * v); +void drawSpriteTHighlight2_ZF(Vertex * v); + +#endif /* __SOFT_H__ */ diff --git a/plugins/gs/GSsoft/Src/System.h b/plugins/gs/GSsoft/Src/System.h new file mode 100644 index 0000000..b855f3e --- /dev/null +++ b/plugins/gs/GSsoft/Src/System.h @@ -0,0 +1,29 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +void SysMessage(char *fmt, ...); // Message used to print msg to users +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library + +#endif /* __SYSTEM_H__ */ diff --git a/plugins/gs/GSsoft/Src/Texts.c b/plugins/gs/GSsoft/Src/Texts.c new file mode 100644 index 0000000..b87496e --- /dev/null +++ b/plugins/gs/GSsoft/Src/Texts.c @@ -0,0 +1,544 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "GS.h" +#include "Texts.h" +#include "Mem.h" +#include "Cache.h" + +u32 clud[256]; + +void copy_clut32_8(u32 *clud) { + int x, y; + int cy; + int i; + + for (y=0, cy=0; y < 8; y++) { +// GS_LOG("clut1[%d];\n", cy); + for(x=0, i=0; x < 8; x++, i++) { + clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64); +// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]); + } + for(x=16; x < 24; x++, i++) { + clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64); +// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]); + } + cy++; + +// GS_LOG("clut2[%d];\n", cy); + for(x=8, i=0; x < 16; x++, i++) { + clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64); +// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]); + } + for(x=24; x < 32; x++, i++) { + clud[y*32 + x] = readPixel32(i, cy, tex0->cbp, 64); +// GS_LOG("clut[%d] = %x\n", x, clud[y*32 + x]); + } + cy++; + } +} + +void copy_clut32_4(u32 *clud) { + int x, y; + + for (y = 0; y < 2; y++) { + for(x = 0; x < 8; x++) { + clud[y*8 + x] = readPixel32(x, y, tex0->cbp, 64); +// GS_LOG("clut[%d] = %x\n", x, clud[y*8 + x]); + } + } +} + +u32 _readPixel16(int x, int y, u32 bp, u32 bw) { + u32 c = readPixel16(x, y, bp, bw); + u32 p; + + p = ((c & 0x7c00) << 9) | + ((c & 0x03e0) << 6) | + ((c & 0x001f) << 3); + if (gs.texa.aem) { + if (c & 0x8000) { + p|= gs.texa.ta[1] << 24; + } else { + if (p) p|= gs.texa.ta[0] << 24; + } + } else { + p|= gs.texa.ta[(c & 0x8000) >> 15] << 24; + } + + return p; +} + +u32 _readPixel16S(int x, int y, u32 bp, u32 bw) { + u32 c = readPixel16S(x, y, bp, bw); + u32 p; + + p = ((c & 0x7c00) << 9) | + ((c & 0x03e0) << 6) | + ((c & 0x001f) << 3); + if (gs.texa.aem) { + if (c & 0x8000) { + p|= gs.texa.ta[1] << 24; + } else { + if (p) p|= gs.texa.ta[0] << 24; + } + } else { + p|= gs.texa.ta[(c & 0x8000) >> 15] << 24; + } + + return p; +} + +u32 _readPixel24(int x, int y, u32 bp, u32 bw) { + u32 c = readPixel24(x, y, bp, bw); + + if (gs.texa.aem) { + if (c) c|= gs.texa.ta[0] << 24; + } else { + c|= gs.texa.ta[0] << 24; + } + + return c; +} + +void copy_clut16S_8_1(u32 *clup) { + int x, y; + int cy; + int i; + + for (y=0, cy=0; y < 8; y++) { + for(x=0, i=0; x < 8; x++, i++) { + clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64); + } + for(x=16; x < 24; x++, i++) { + clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64); + } + cy++; + + for(x=8, i=0; x < 16; x++, i++) { + clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64); + } + for(x=24; x < 32; x++, i++) { + clud[y*32 + x] = _readPixel16S(i, cy, tex0->cbp, 64); + } + cy++; + } +} + +void copy_clut16S_8_2(u32 *clup) { + int i; + + for (i=0; i < 256; i++) { + clud[i] = _readPixel16S(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw); + } +} + +void copy_clut16_8_1(u32 *clup) { + int x, y; + int cy; + int i; + + for (y=0, cy=0; y < 8; y++) { + for(x=0, i=0; x < 8; x++, i++) { + clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64); + } + for(x=16; x < 24; x++, i++) { + clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64); + } + cy++; + + for(x=8, i=0; x < 16; x++, i++) { + clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64); + } + for(x=24; x < 32; x++, i++) { + clud[y*32 + x] = _readPixel16(i, cy, tex0->cbp, 64); + } + cy++; + } +} + +void copy_clut16_8_2(u32 *clup) { + int i; + + for (i=0; i < 256; i++) { + clud[i] = _readPixel16(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw); + } +} + +void copy_clut16_4_1(u32 *clud) { + int x, y; + + for (y = 0; y < 2; y++) { + for(x = 0; x < 8; x++) { + clud[y*8 + x] = _readPixel16(x, y, tex0->cbp, 64); + } + } +} + +void copy_clut16_4_2(u32 *clup) { + int i; + + for (i=0; i < 16; i++) { + clud[i] = _readPixel16(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw); + } +} + +void copy_clut16S_4_1(u32 *clud) { + int x, y; + + for (y = 0; y < 2; y++) { + for(x = 0; x < 8; x++) { + clud[y*8 + x] = _readPixel16S(x, y, tex0->cbp, 64); + } + } +} + +void copy_clut16S_4_2(u32 *clup) { + int i; + + for (i=0; i < 16; i++) { + clud[i] = _readPixel16S(gs.clut.cou + i, gs.clut.cov, tex0->cbp, gs.clut.cbw); + } +} + +void wrapUV(int *u, int *v) { + switch (clamp->wms) { + case 0: // REPEAT + *u = *u % tex0->tw; + break; + + case 1: // CLAMP + if (*u < 0) *u = 0; + if (*u >= tex0->tw) *u = tex0->tw - 1; + break; + + case 2: // REGION_CLAMP + if (*u < clamp->minu) *u = clamp->minu; + if (*u > clamp->maxu) *u = clamp->maxu; + break; + + case 3: // REGION_REPEAT + printf("REGION_REPEAT\n"); + *u = (*u & clamp->minu) | clamp->maxu; + break; + } + + switch (clamp->wmt) { + case 0: // REPEAT + *v = *v % tex0->th; + break; + + case 1: // CLAMP + if (*v < 0) *v = 0; + if (*v >= tex0->th) *v = tex0->th - 1; + break; + + case 2: // REGION_CLAMP + if (*v < clamp->minv) *v = clamp->minv; + if (*v > clamp->maxv) *v = clamp->maxv; + break; + + case 3: // REGION_REPEAT + printf("REGION_REPEAT\n"); + *v = (*v & clamp->minv) | clamp->maxv; + break; + } +} + + + + +u32 _GetTexturePixel32_T32B(int u, int v) { + wrapUV(&u, &v); + return readPixel32(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_T24B(int u, int v) { + wrapUV(&u, &v); + return _readPixel24(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_T16B(int u, int v) { + wrapUV(&u, &v); + return _readPixel16(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_T16SB(int u, int v) { + wrapUV(&u, &v); + return _readPixel16S(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_T8B(int u, int v) { + wrapUV(&u, &v); + return clud[readPixel8(u, v, tex0->tbp0, tex0->tbw)]; +} + +u32 _GetTexturePixel32_T4B(int u, int v) { + wrapUV(&u, &v); + return clud[readPixel4(u, v, tex0->tbp0, tex0->tbw)]; +} + +u32 _GetTexturePixel32_T8HB(int u, int v) { + wrapUV(&u, &v); + return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw)]; +} + +u32 _GetTexturePixel32_T4HLB(int u, int v) { + wrapUV(&u, &v); + return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw) & 0xf]; +} + +u32 _GetTexturePixel32_T4HHB(int u, int v) { + wrapUV(&u, &v); + return clud[readPixel8H(u, v, tex0->tbp0, tex0->tbw) >> 4]; +} + +u32 _GetTexturePixel32_Z32B(int u, int v) { + wrapUV(&u, &v); + return readPixel32Z(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_Z24B(int u, int v) { + wrapUV(&u, &v); + return readPixel24Z(u, v, tex0->tbp0, tex0->tbw); +} + +/*u32 _GetTexturePixel32_Z16B(int u, int v) { + wrapUV(&u, &v); + return readPixel24Z(u, v, tex0->tbp0, tex0->tbw); +} + +u32 _GetTexturePixel32_Z16SB(int u, int v) { + wrapUV(&u, &v); + return readPixel24Z(u, v, tex0->tbp0, tex0->tbw); +}*/ + +void _SetGetTexturePixelB() { + switch (tex0->psm) { + case 0x00: // PSMCT32 + GetTexturePixel32 = _GetTexturePixel32_T32B; break; + case 0x01: // PSMCT24 + GetTexturePixel32 = _GetTexturePixel32_T24B; break; + case 0x02: // PSMCT16 + GetTexturePixel32 = _GetTexturePixel32_T16B; break; + case 0x0A: // PSMCT16S + GetTexturePixel32 = _GetTexturePixel32_T16SB;break; + case 0x13: // PSMT8 + GetTexturePixel32 = _GetTexturePixel32_T8B; break; + case 0x14: // PSMT4 + GetTexturePixel32 = _GetTexturePixel32_T4B; break; + case 0x1B: // PSMT8H + GetTexturePixel32 = _GetTexturePixel32_T8HB; break; + case 0x24: // PSMT4HL + GetTexturePixel32 = _GetTexturePixel32_T4HLB; break; + case 0x2C: // PSMT4HH + GetTexturePixel32 = _GetTexturePixel32_T4HHB; break; + case 0x30: // PSMZ32 + GetTexturePixel32 = _GetTexturePixel32_Z32B; break; +/* case 0x31: // PSMZ24 + GetTexturePixel32 = _GetTexturePixel32_Z24B; break; + case 0x32: // PSMZ16 + GetTexturePixel32 = _GetTexturePixel32_Z16B; break; + case 0x3A: // PSMZ16S + GetTexturePixel32 = _GetTexturePixel32_Z16SB; break;*/ + default: + printf("unhandled psm : %x\n", tex0->psm); + GetTexturePixel32 = _GetTexturePixel32_T32B; break; + } +} + +void SetTexture() { + int clutf=0; + + switch (tex0->psm) { + case 0x13: // PSMT8 + case 0x1B: // PSMT8H + clutf = 8; break; + case 0x14: // PSMT4 + case 0x24: // PSMT4HL + case 0x2C: // PSMT4HH + clutf = 4; break; + } + + if (clutf == 8) { + if (tex0->cpsm == 0) { + copy_clut32_8(clud); + } + if (tex0->cpsm == 0x2) { + if (tex0->csm == 0) { + copy_clut16_8_1(clud); + } else { + copy_clut16_8_2(clud); + } + } + if (tex0->cpsm == 0xa) { + if (tex0->csm == 0) { + copy_clut16S_8_1(clud); + } else { + copy_clut16S_8_2(clud); + } + } + } + + if (clutf == 4) { + if (tex0->cpsm == 0) { + copy_clut32_4(clud); + } + if (tex0->cpsm == 0x2) { + if (tex0->csm == 0) { + copy_clut16_4_1(clud); + } else { + copy_clut16_4_2(clud); + } + } + if (tex0->cpsm == 0xa) { + if (tex0->csm == 0) { + copy_clut16S_4_1(clud); + } else { + copy_clut16S_4_2(clud); + } + } + } + +/* if (tex0->tbp0 & 0x1f)*/ { + _SetGetTexturePixelB(); + } /*else + switch (tex0->psm) { + case 0x00: // PSMCT32 + GetTexturePixel32 = _GetTexturePixel32_T32; break; + case 0x01: // PSMCT24 + GetTexturePixel32 = _GetTexturePixel32_T24; break; + case 0x02: // PSMCT16 + case 0x0A: // PSMCT16S + GetTexturePixel32 = _GetTexturePixel32_T16; break; + case 0x13: // PSMT8 + GetTexturePixel32 = _GetTexturePixel32_T8; break; + case 0x14: // PSMT4 + GetTexturePixel32 = _GetTexturePixel32_T4; break; + case 0x1B: // PSMT8H + GetTexturePixel32 = _GetTexturePixel32_T8H; break; + case 0x24: // PSMT4HL + GetTexturePixel32 = _GetTexturePixel32_T4HL;break; + case 0x2C: // PSMT4HH + GetTexturePixel32 = _GetTexturePixel32_T4HH;break; + default: + printf("unhandled psm : %x\n", tex0->psm); + GetTexturePixel32 = _GetTexturePixel32_T32; break; + }*/ + + if (conf.cache) { + if (CacheSetTexture() == 0) { + GetTexturePixel32 = CacheGetTexturePixel32; + } + } +// if (tex0->tbp0 == 0x75680) + if (conf.dumptexts) DumpTexture(); +} + +u32 TextureSizeGS(int width, int height, int psm) { + switch (psm) { + case 0x00: // PSMCT32 + case 0x01: // PSMCT24 + case 0x1B: // PSMT8H + case 0x24: // PSMT4HL + case 0x2C: // PSMT4HH + return (width*height*4); + case 0x02: // PSMCT16 + case 0x0A: // PSMCT16S + return (width*height*2); + case 0x13: // PSMT8 + return (width*height ); + case 0x14: // PSMT4 + return (width*height/2); + default: + printf("unsupported PSM %d\n", psm); + return 0; + } +} + +void DumpTexture() { + FILE *bmpfile; + char filename[256]; + unsigned char header[0x36]; + long size; + unsigned char line[1024*3]; + int w,h; + short i,j; + unsigned char empty[2]={0,0}; + u32 color; + u32 snapshotnr = 0; + + w = tex0->tw; + h = tex0->th-20; + size = w*h*3 + 0x38; + printf("DumpTexture %d, %d\n", w, h); + + // fill in proper values for BMP + + // hardcoded BMP header + memset(header,0,0x36); + header[0]='B'; + header[1]='M'; + header[2]=size&0xff; + header[3]=(size>>8)&0xff; + header[4]=(size>>16)&0xff; + header[5]=(size>>24)&0xff; + header[0x0a]=0x36; + header[0x0e]=0x28; + header[0x12]=w%256; + header[0x13]=w/256; + header[0x16]=h%256; + header[0x17]=h/256; + header[0x1a]=0x01; + header[0x1c]=0x18; + header[0x26]=0x12; + header[0x27]=0x0B; + header[0x2A]=0x12; + header[0x2B]=0x0B; + + // increment snapshot value & try to get filename + for (;;) { + snapshotnr++; + + sprintf(filename,"tex%03ld_%x.bmp", snapshotnr, tex0->tbp0); + + bmpfile=fopen(filename,"rb"); + if (bmpfile == NULL) break; + fclose(bmpfile); + } + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) + return; + + fwrite(header,0x36,1,bmpfile); + for(i=h-1;i>=0;i--) { + for(j=0;j> 8)&0xff; + line[j*3+0]=(color>>16)&0xff; + } + fwrite(line,w*3,1,bmpfile); + } + fwrite(empty,0x2,1,bmpfile); + fclose(bmpfile); +} + diff --git a/plugins/gs/GSsoft/Src/Texts.h b/plugins/gs/GSsoft/Src/Texts.h new file mode 100644 index 0000000..3610821 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Texts.h @@ -0,0 +1,28 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TEXTS_H__ +#define __TEXTS_H__ + +void SetTexture(); +void DumpTexture(); +u32 TextureSizeGS(int width, int height, int psm); +u32 (*GetTexturePixel32)(int, int); +void wrapUV(int *u, int *v); + +#endif /* __TEXTS_H__ */ diff --git a/plugins/gs/GSsoft/Src/Transfer.c b/plugins/gs/GSsoft/Src/Transfer.c new file mode 100644 index 0000000..167c9d8 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Transfer.c @@ -0,0 +1,1328 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Rec.h" +#include "Page.h" +#include "Cache.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) + +#endif + +//#define _OPTIMIZE + + +/////////////////////////////// +// TransferPixel from/to vRam +// + +__inline void TransferPixel(u32 pixel) { + writePixel32(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixelB(u32 pixel) { + writePixel32(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel32Z(u32 pixel) { + writePixel32Z(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel24(u8 *pixel) { + u32 pix = pixel[0] | (pixel[1] << 8) | (pixel[2] << 16); + writePixel24(gs.imageX, gs.imageY, pix, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel24B(u8 *pixel) { + u32 pix = pixel[0] | (pixel[1] << 8) | (pixel[2] << 16); + writePixel24(gs.imageX, gs.imageY, pix, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel24Z(u8 *pixel) { + u32 pix = pixel[0] | (pixel[1] << 8) | (pixel[2] << 16); + writePixel24Z(gs.imageX, gs.imageY, pix, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16(u16 pixel) { + writePixel16(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16B(u16 pixel) { + writePixel16(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16Z(u16 pixel) { + writePixel16Z(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16S(u16 pixel) { + writePixel16S(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16SB(u16 pixel) { + writePixel16S(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel16SZ(u16 pixel) { + writePixel16SZ(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel8(u8 pixel) { + writePixel8(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel8B(u8 pixel) { + writePixel8(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel8H(u8 pixel) { + writePixel8H(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel8HB(u8 pixel) { + writePixel8H(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4(u8 pixel) { + writePixel4(gs.imageX, gs.imageY, pixel & 0xf, gs.dstbuf.bp, gs.dstbuf.bw); + writePixel4(gs.imageX+1, gs.imageY, pixel >> 4, gs.dstbuf.bp, gs.dstbuf.bw); + + gs.imageX+= 2; + if (gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4B(u8 pixel) { + writePixel4(gs.imageX, gs.imageY, pixel & 0xf, gs.dstbuf.bp, gs.dstbuf.bw); + writePixel4(gs.imageX+1, gs.imageY, pixel >> 4, gs.dstbuf.bp, gs.dstbuf.bw); + + gs.imageX+= 2; + if (gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4HL(u8 pixel) { + writePixel4HL(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4HLB(u8 pixel) { + writePixel4HL(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4HH(u8 pixel) { + writePixel4HH(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixel4HHB(u8 pixel) { + writePixel4HH(gs.imageX, gs.imageY, pixel, gs.dstbuf.bp, gs.dstbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +__inline void TransferPixelSrc(u32 *pixel) { + *pixel = readPixel32(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrcB(u32 *pixel) { + *pixel = readPixel32(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc32Z(u32 *pixel) { + *pixel = readPixel32Z(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc24(u8 *pixel) { + u32 pix = readPixel24(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + pixel[0] = ((u8*)pix)[0]; pixel[1] = ((u8*)pix)[1]; pixel[2] = ((u8*)pix)[2]; + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc24B(u8 *pixel) { + u32 pix = readPixel24(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + pixel[0] = ((u8*)pix)[0]; pixel[1] = ((u8*)pix)[1]; pixel[2] = ((u8*)pix)[2]; + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc24Z(u8 *pixel) { + u32 pix = readPixel24Z(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + pixel[0] = ((u8*)pix)[0]; pixel[1] = ((u8*)pix)[1]; pixel[2] = ((u8*)pix)[2]; + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16(u16 *pixel) { + *pixel = readPixel16(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16B(u16 *pixel) { + *pixel = readPixel16(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16Z(u16 *pixel) { + *pixel = readPixel16Z(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16S(u16 *pixel) { + *pixel = readPixel16S(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16SB(u16 *pixel) { + *pixel = readPixel16S(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc16SZ(u16 *pixel) { + *pixel = readPixel16SZ(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc8(u8 *pixel) { + *pixel = readPixel8(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc8B(u8 *pixel) { + *pixel = readPixel8(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc8H(u8 *pixel) { + *pixel = readPixel8H(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc8HB(u8 *pixel) { + *pixel = readPixel8H(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4(u8 *pixel) { + *pixel = readPixel4(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + gs.imageX+= 2; + if (gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4B(u8 *pixel) { + *pixel = readPixel4(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + gs.imageX+= 2; + if (gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4HL(u8 *pixel) { + *pixel = readPixel4HL(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4HLB(u8 *pixel) { + *pixel = readPixel4HL(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4HH(u8 *pixel) { + *pixel = readPixel4HH(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +__inline void TransferPixelSrc4HHB(u8 *pixel) { + *pixel = readPixel4HH(gs.imageX, gs.imageY, gs.srcbuf.bp, gs.srcbuf.bw); + + if (++gs.imageX == (gs.imageW + gs.trxpos.sx)) { + gs.imageX = gs.trxpos.sx; gs.imageY++; + } +} + +/////////////////////////////// +// FrameBuffer writes/reads +// + +void FBwrite(u32 *data) { + TransferPixel(data[0]); + TransferPixel(data[1]); + TransferPixel(data[2]); + TransferPixel(data[3]); +} + +void FBwriteB(u32 *data) { + TransferPixelB(data[0]); + TransferPixelB(data[1]); + TransferPixelB(data[2]); + TransferPixelB(data[3]); +} + +void FBwrite32Z(u32 *data) { + TransferPixel32Z(data[0]); + TransferPixel32Z(data[1]); + TransferPixel32Z(data[2]); + TransferPixel32Z(data[3]); +} + +void FBwrite_8x8(u32 *data) { + u32 *fb = (u32*)&vRamUL[getPixelAddress32(gs.imageX, gs.imageY, gs.dstbuf.bp, gs.dstbuf.bw)]; + u32 *data2 = data+gs.imageW; + +#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__) + __asm__( + "movq 0(%1), %%xmm0\n" + "movq 8(%1), %%xmm1\n" + "movq 16(%1), %%xmm2\n" + "movq 24(%1), %%xmm3\n" + + "movhps 0(%2), %%xmm0\n" + "movhps 8(%2), %%xmm1\n" + "movhps 16(%2), %%xmm2\n" + "movhps 24(%2), %%xmm3\n" + + "movaps %%xmm0, 0(%0)\n" + "movaps %%xmm1, 16(%0)\n" + "movaps %%xmm2, 32(%0)\n" + "movaps %%xmm3, 48(%0)\n" + + :: "r"(fb), "r"(data), "r"(data2) + ); +#else + fb[0] = data[0]; fb[1] = data[1]; + fb[4] = data[2]; fb[5] = data[3]; + fb[8] = data[4]; fb[9] = data[5]; + fb[12] = data[6]; fb[13] = data[7]; + + fb[2] = data2[0]; fb[3] = data2[1]; + fb[6] = data2[2]; fb[7] = data2[3]; + fb[10] = data2[4]; fb[11] = data2[5]; + fb[14] = data2[6]; fb[15] = data2[7]; +#endif + + gs.imageX+= 8; + if (gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY+= 2; + } +} + +void FBwrite_8(u32 *data) { + u32 *fb = (u32*)&vRamUL[getPixelAddress32(gs.imageX, gs.imageY, gs.dstbuf.bp, gs.dstbuf.bw)]; + + fb[0] = data[0]; fb[1] = data[1]; + fb[4] = data[2]; fb[5] = data[3]; + fb[8] = data[4]; fb[9] = data[5]; + fb[12] = data[6]; fb[13] = data[7]; + + gs.imageX+= 8; + if (gs.imageX == (gs.imageW + gs.trxpos.dx)) { + gs.imageX = gs.trxpos.dx; gs.imageY++; + } +} + +void FBwrite24_3(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixel24((u8*)(data8+i*3)); + } +} + +void FBwrite24_3B(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixel24B((u8*)(data8+i*3)); + } +} + +void FBwrite24Z_3(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixel24Z((u8*)(data8+i*3)); + } +} + +void FBwrite16(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16(data16[0]); + TransferPixel16(data16[1]); + TransferPixel16(data16[2]); + TransferPixel16(data16[3]); +} + +void FBwrite16B(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16B(data16[0]); + TransferPixel16B(data16[1]); + TransferPixel16B(data16[2]); + TransferPixel16B(data16[3]); +} + +void FBwrite16Z(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16Z(data16[0]); + TransferPixel16Z(data16[1]); + TransferPixel16Z(data16[2]); + TransferPixel16Z(data16[3]); +} + +void FBwrite16S(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16S(data16[0]); + TransferPixel16S(data16[1]); + TransferPixel16S(data16[2]); + TransferPixel16S(data16[3]); +} + +void FBwrite16SB(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16SB(data16[0]); + TransferPixel16SB(data16[1]); + TransferPixel16SB(data16[2]); + TransferPixel16SB(data16[3]); +} + +void FBwrite16SZ(u32 *data) { + const u16 *data16 = (u16*)data; + TransferPixel16SZ(data16[0]); + TransferPixel16SZ(data16[1]); + TransferPixel16SZ(data16[2]); + TransferPixel16SZ(data16[3]); +} + +void FBwrite8(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel8(data8[0]); + TransferPixel8(data8[1]); + TransferPixel8(data8[2]); + TransferPixel8(data8[3]); +} + +void FBwrite8B(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel8B(data8[0]); + TransferPixel8B(data8[1]); + TransferPixel8B(data8[2]); + TransferPixel8B(data8[3]); +} + +void FBwrite8H(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel8H(data8[0]); + TransferPixel8H(data8[1]); + TransferPixel8H(data8[2]); + TransferPixel8H(data8[3]); +} + +void FBwrite8HB(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel8HB(data8[0]); + TransferPixel8HB(data8[1]); + TransferPixel8HB(data8[2]); + TransferPixel8HB(data8[3]); +} + +void FBwrite4(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4(data8[0]); + TransferPixel4(data8[1]); + TransferPixel4(data8[2]); + TransferPixel4(data8[3]); +} + +void FBwrite4B(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4B(data8[0]); + TransferPixel4B(data8[1]); + TransferPixel4B(data8[2]); + TransferPixel4B(data8[3]); +} + +void FBwrite4HL(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4HL(data8[0] & 0xf); + TransferPixel4HL(data8[0] >> 4); + TransferPixel4HL(data8[1] & 0xf); + TransferPixel4HL(data8[1] >> 4); + TransferPixel4HL(data8[2] & 0xf); + TransferPixel4HL(data8[2] >> 4); + TransferPixel4HL(data8[3] & 0xf); + TransferPixel4HL(data8[3] >> 4); +} + +void FBwrite4HLB(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4HLB(data8[0] & 0xf); + TransferPixel4HLB(data8[0] >> 4); + TransferPixel4HLB(data8[1] & 0xf); + TransferPixel4HLB(data8[1] >> 4); + TransferPixel4HLB(data8[2] & 0xf); + TransferPixel4HLB(data8[2] >> 4); + TransferPixel4HLB(data8[3] & 0xf); + TransferPixel4HLB(data8[3] >> 4); +} + +void FBwrite4HH(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4HH(data8[0] << 4); + TransferPixel4HH(data8[0] & 0xf0); + TransferPixel4HH(data8[1] << 4); + TransferPixel4HH(data8[1] & 0xf0); + TransferPixel4HH(data8[2] << 4); + TransferPixel4HH(data8[2] & 0xf0); + TransferPixel4HH(data8[3] << 4); + TransferPixel4HH(data8[3] & 0xf0); +} + +void FBwrite4HHB(u32 *data) { + const u8 *data8 = (u8*)data; + TransferPixel4HHB(data8[0] << 4); + TransferPixel4HHB(data8[0] & 0xf0); + TransferPixel4HHB(data8[1] << 4); + TransferPixel4HHB(data8[1] & 0xf0); + TransferPixel4HHB(data8[2] << 4); + TransferPixel4HHB(data8[2] & 0xf0); + TransferPixel4HHB(data8[3] << 4); + TransferPixel4HHB(data8[3] & 0xf0); +} + +void FBread(u32 *data) { + TransferPixelSrc(&data[0]); + TransferPixelSrc(&data[1]); + TransferPixelSrc(&data[2]); + TransferPixelSrc(&data[3]); +} + +void FBreadB(u32 *data) { + TransferPixelSrcB(&data[0]); + TransferPixelSrcB(&data[1]); + TransferPixelSrcB(&data[2]); + TransferPixelSrcB(&data[3]); +} + +void FBread32Z(u32 *data) { + TransferPixelSrc32Z(&data[0]); + TransferPixelSrc32Z(&data[1]); + TransferPixelSrc32Z(&data[2]); + TransferPixelSrc32Z(&data[3]); +} + +void FBread24_3(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixelSrc24((u8*)(data8+i*3)); + } +} + +void FBread24_3B(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixelSrc24B((u8*)(data8+i*3)); + } +} + +void FBread24Z_3(u32 *data) { + u8 *data8 = (u8*)data; + int i; + + for (i=0; i<16; i++) { + TransferPixelSrc24Z((u8*)(data8+i*3)); + } +} + +void FBread16(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16(&data16[0]); + TransferPixelSrc16(&data16[1]); + TransferPixelSrc16(&data16[2]); + TransferPixelSrc16(&data16[3]); +} + +void FBread16B(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16B(&data16[0]); + TransferPixelSrc16B(&data16[1]); + TransferPixelSrc16B(&data16[2]); + TransferPixelSrc16B(&data16[3]); +} + +void FBread16Z(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16Z(&data16[0]); + TransferPixelSrc16Z(&data16[1]); + TransferPixelSrc16Z(&data16[2]); + TransferPixelSrc16Z(&data16[3]); +} + +void FBread16S(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16S(&data16[0]); + TransferPixelSrc16S(&data16[1]); + TransferPixelSrc16S(&data16[2]); + TransferPixelSrc16S(&data16[3]); +} + +void FBread16SB(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16SB(&data16[0]); + TransferPixelSrc16SB(&data16[1]); + TransferPixelSrc16SB(&data16[2]); + TransferPixelSrc16SB(&data16[3]); +} + +void FBread16SZ(u32 *data) { + u16 *data16 = (u16*)data; + TransferPixelSrc16SZ(&data16[0]); + TransferPixelSrc16SZ(&data16[1]); + TransferPixelSrc16SZ(&data16[2]); + TransferPixelSrc16SZ(&data16[3]); +} + +void FBread8(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc8(&data8[0]); + TransferPixelSrc8(&data8[1]); + TransferPixelSrc8(&data8[2]); + TransferPixelSrc8(&data8[3]); +} + +void FBread8B(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc8B(&data8[0]); + TransferPixelSrc8B(&data8[1]); + TransferPixelSrc8B(&data8[2]); + TransferPixelSrc8B(&data8[3]); +} + +void FBread8H(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc8H(&data8[0]); + TransferPixelSrc8H(&data8[1]); + TransferPixelSrc8H(&data8[2]); + TransferPixelSrc8H(&data8[3]); +} + +void FBread8HB(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc8HB(&data8[0]); + TransferPixelSrc8HB(&data8[1]); + TransferPixelSrc8HB(&data8[2]); + TransferPixelSrc8HB(&data8[3]); +} + +void FBread4(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4(&data8[0]); + TransferPixelSrc4(&data8[1]); + TransferPixelSrc4(&data8[2]); + TransferPixelSrc4(&data8[3]); +} + +void FBread4B(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4B(&data8[0]); + TransferPixelSrc4B(&data8[1]); + TransferPixelSrc4B(&data8[2]); + TransferPixelSrc4B(&data8[3]); +} + +void FBread4HL(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4HL(&data8[0]); + TransferPixelSrc4HL(&data8[1]); + TransferPixelSrc4HL(&data8[2]); + TransferPixelSrc4HL(&data8[3]); +} + +void FBread4HLB(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4HLB(&data8[0]); + TransferPixelSrc4HLB(&data8[1]); + TransferPixelSrc4HLB(&data8[2]); + TransferPixelSrc4HLB(&data8[3]); +} + +void FBread4HH(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4HH(&data8[0]); + TransferPixelSrc4HH(&data8[1]); + TransferPixelSrc4HH(&data8[2]); + TransferPixelSrc4HH(&data8[3]); +} + +void FBread4HHB(u32 *data) { + u8 *data8 = (u8*)data; + TransferPixelSrc4HHB(&data8[0]); + TransferPixelSrc4HHB(&data8[1]); + TransferPixelSrc4HHB(&data8[2]); + TransferPixelSrc4HHB(&data8[3]); +} + +void FBtransferImageB(u32 *pMem, int size) { +// printf("GS IMAGE transferB %d, gs.dstbuf.psm=%x; %dx%d %dx%d (bp=%x)\n", size, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageW, gs.imageH, gs.dstbuf.bp); + + switch (gs.dstbuf.psm) { + case 0x01: // PSMCT24 + while (size >= 3) { + FBwrite24_3B(pMem); pMem+= 12; size-=3; + } + break; + + case 0x02: // PSMCT16 + while (size > 0) { + FBwrite16B(pMem); pMem+= 2; + FBwrite16B(pMem); pMem+= 2; size--; + } + break; + + case 0x0A: // PSMCT16S + while (size > 0) { + FBwrite16SB(pMem); pMem+= 2; + FBwrite16SB(pMem); pMem+= 2; size--; + } + break; + + case 0x13: // PSMT8 + while (size > 0) { + FBwrite8B(pMem); pMem++; + FBwrite8B(pMem); pMem++; + FBwrite8B(pMem); pMem++; + FBwrite8B(pMem); pMem++; size--; + } + break; + + case 0x14: // PSMT4 + while (size > 0) { + FBwrite4B(pMem); pMem++; + FBwrite4B(pMem); pMem++; + FBwrite4B(pMem); pMem++; + FBwrite4B(pMem); pMem++; size--; + } + break; + + case 0x1B: // PSMT8H + while (size > 0) { + FBwrite8HB(pMem); pMem++; + FBwrite8HB(pMem); pMem++; + FBwrite8HB(pMem); pMem++; + FBwrite8HB(pMem); pMem++; size--; + } + break; + + case 0x24: // PSMT4HL + while (size > 0) { + FBwrite4HLB(pMem); pMem++; + FBwrite4HLB(pMem); pMem++; + FBwrite4HLB(pMem); pMem++; + FBwrite4HLB(pMem); pMem++; size--; + } + break; + + case 0x2C: // PSMT4HH + while (size > 0) { + FBwrite4HHB(pMem); pMem++; + FBwrite4HHB(pMem); pMem++; + FBwrite4HHB(pMem); pMem++; + FBwrite4HHB(pMem); pMem++; size--; + } + break; + + case 0x30: // PSMZ32 + while (size > 0) { + FBwrite32Z(pMem); pMem+= 4; size--; + } + break; + + case 0x31: // PSMZ24 + while (size >= 3) { + FBwrite24Z_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x32: // PSMZ16 + while (size > 0) { + FBwrite16Z(pMem); pMem+= 2; + FBwrite16Z(pMem); pMem+= 2; size--; + } + break; + + case 0x3A: // PSMZ16S + while (size > 0) { + FBwrite16SZ(pMem); pMem+= 2; + FBwrite16SZ(pMem); pMem+= 2; size--; + } + break; + + default: + case 0x00: // PSMCT32 + if (gs.dstbuf.psm != 0) printf("gs.dstbuf.psm == %x!!\n", gs.dstbuf.psm); + while (size > 0) { + FBwriteB(pMem); pMem+= 4; size--; + } + break; + } +} + +void _TransferImage8(u32 *pMem, int size) { +/* if ((gs.imageX & 0x1f) == 0 && (gs.imageY & 0xf) == 0 && + ((gs.imageW + gs.trxpos.dx) & 0x1f) == 0) { + while (size > 2) { + FBwrite8B_8(pMem); pMem+= 4; size--; + } +#ifdef __i386__ + _sfence(); + _emms(); +#endif + }*/ + while (size > 0) { + FBwrite8(pMem); pMem++; + FBwrite8(pMem); pMem++; + FBwrite8(pMem); pMem++; + FBwrite8(pMem); pMem++; size--; + } +} + +void _TransferImage32(u32 *pMem, int size) { + int s2size; + size*= 4; + + if ((gs.imageX & 0x7) != 0 || (gs.imageY & 0x7) != 0) { + while (size > 0) { + TransferPixel(*pMem++); size--; + } + return; + } + + if ((gs.imageW & 0x7) == 0) { + s2size = gs.imageW*2; + while (size >= s2size) { + int i; + + for (i=0; i 0) { + if (gs.imageX < (gs.imageW-8)) { + while (size >= 2) { + FBwrite_8(pMem); pMem+= 8; size-= 8; + } +#ifdef __i386__ +// _sfence(); +// _emms(); +#endif + } + while (size > 0) { + TransferPixel(*pMem++); size--; + } + } +} + +void FBtransferImage(u32 *pMem, int size) { +#ifdef GS_LOG + GS_LOG("GS IMAGE transfer %d, gs.dstbuf.psm=%x; %dx%d\n", size, gs.dstbuf.psm, gs.imageW, gs.imageH); +#endif + bpf+= size*16; + + if (conf.cache) { + CacheClear(gs.dstbuf.bp, size*4); + } + +#ifndef _OPTIMIZE + FBtransferImageB(pMem, size); + return; +#endif + if (gs.dstbuf.bp & 0x1f) { + FBtransferImageB(pMem, size); + return; + } + + switch (gs.dstbuf.psm) { + case 0x01: // PSMCT24 + while (size >= 3) { + FBwrite24_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x02: // PSMCT16 + while (size > 0) { + FBwrite16(pMem); pMem+= 2; + FBwrite16(pMem); pMem+= 2; size--; + } + break; + + case 0x0A: // PSMCT16S + while (size > 0) { + FBwrite16S(pMem); pMem+= 2; + FBwrite16S(pMem); pMem+= 2; size--; + } + break; + + case 0x13: // PSMT8 + _TransferImage8(pMem, size); + break; + + case 0x14: // PSMT4 + while (size > 0) { + FBwrite4(pMem); pMem++; + FBwrite4(pMem); pMem++; + FBwrite4(pMem); pMem++; + FBwrite4(pMem); pMem++; size--; + } + break; + + case 0x1B: // PSMT8H + while (size > 0) { + FBwrite8H(pMem); pMem++; + FBwrite8H(pMem); pMem++; + FBwrite8H(pMem); pMem++; + FBwrite8H(pMem); pMem++; size--; + } + break; + + case 0x24: // PSMT4HL + while (size > 0) { + FBwrite4HL(pMem); pMem++; + FBwrite4HL(pMem); pMem++; + FBwrite4HL(pMem); pMem++; + FBwrite4HL(pMem); pMem++; size--; + } + break; + + case 0x2C: // PSMT4HH + while (size > 0) { + FBwrite4HH(pMem); pMem++; + FBwrite4HH(pMem); pMem++; + FBwrite4HH(pMem); pMem++; + FBwrite4HH(pMem); pMem++; size--; + } + break; + + case 0x30: // PSMZ32 + while (size > 0) { + FBwrite32Z(pMem); pMem+= 4; size--; + } + break; + + case 0x31: // PSMZ24 + while (size >= 3) { + FBwrite24Z_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x32: // PSMZ16 + while (size > 0) { + FBwrite16Z(pMem); pMem+= 2; + FBwrite16Z(pMem); pMem+= 2; size--; + } + break; + + case 0x3A: // PSMZ16S + while (size > 0) { + FBwrite16SZ(pMem); pMem+= 2; + FBwrite16SZ(pMem); pMem+= 2; size--; + } + break; + + default: + case 0x00: // PSMCT32 + if (gs.dstbuf.psm != 0) printf("gs.dstbuf.psm == %x!!\n", gs.dstbuf.psm); + _TransferImage32(pMem, size); + break; + } +} + +void FBtransferImageSrcB(u32 *pMem, int size) { +#ifdef GS_LOG + GS_LOG("GS IMAGE SRC transfer %d, gs.srcbuf.psm=%x\n", size, gs.srcbuf.psm); +#endif + + switch (gs.srcbuf.psm) { + case 0x01: // PSMCT24 + while (size >= 3) { + FBread24_3B(pMem); pMem+= 12; size-=3; + } + break; + + case 0x02: // PSMCT16 + while (size > 0) { + FBread16B(pMem); pMem+= 2; + FBread16B(pMem); pMem+= 2; size--; + } + break; + + case 0x0A: // PSMCT16S + while (size > 0) { + FBread16SB(pMem); pMem+= 2; + FBread16SB(pMem); pMem+= 2; size--; + } + break; + + case 0x13: // PSMT8 + while (size > 0) { + FBread8B(pMem); pMem++; + FBread8B(pMem); pMem++; + FBread8B(pMem); pMem++; + FBread8B(pMem); pMem++; size--; + } + break; + + case 0x14: // PSMT4 + while (size > 0) { + FBread4B(pMem); pMem++; + FBread4B(pMem); pMem++; + FBread4B(pMem); pMem++; + FBread4B(pMem); pMem++; size--; + } + break; + + case 0x1B: // PSMT8H + while (size > 0) { + FBread8HB(pMem); pMem++; + FBread8HB(pMem); pMem++; + FBread8HB(pMem); pMem++; + FBread8HB(pMem); pMem++; size--; + } + break; + + case 0x24: // PSMT4HL + while (size > 0) { + FBread4HLB(pMem); pMem++; + FBread4HLB(pMem); pMem++; + FBread4HLB(pMem); pMem++; + FBread4HLB(pMem); pMem++; size--; + } + break; + + case 0x2C: // PSMT4HH + while (size > 0) { + FBread4HHB(pMem); pMem++; + FBread4HHB(pMem); pMem++; + FBread4HHB(pMem); pMem++; + FBread4HHB(pMem); pMem++; size--; + } + break; + + case 0x30: // PSMZ32 + while (size > 0) { + FBread32Z(pMem); pMem+= 4; size--; + } + break; + + case 0x31: // PSMZ24 + while (size >= 3) { + FBread24Z_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x32: // PSMZ16 + while (size > 0) { + FBread16Z(pMem); pMem+= 2; + FBread16Z(pMem); pMem+= 2; size--; + } + break; + + case 0x3A: // PSMZ16S + while (size > 0) { + FBread16SZ(pMem); pMem+= 2; + FBread16SZ(pMem); pMem+= 2; size--; + } + break; + + default: + case 0x00: // PSMCT32 + if (gs.srcbuf.psm != 0) printf("gs.srcbuf.psm == %d!!\n", gs.srcbuf.psm); + while (size > 0) { + FBreadB(pMem); pMem+= 4; size--; + } + break; + } +} + +void FBtransferImageSrc(u32 *pMem, int size) { +#ifdef GS_LOG + GS_LOG("GS IMAGE SRC transfer %d, gs.srcbuf.psm=%x\n", size, gs.srcbuf.psm); +#endif + + if (gs.srcbuf.bp & 0x1f) { + FBtransferImageSrcB(pMem, size); + return; + } + + switch (gs.srcbuf.psm) { + case 0x01: // PSMCT24 + while (size >= 3) { + FBread24_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x02: // PSMCT16 + while (size > 0) { + FBread16(pMem); pMem+= 2; + FBread16(pMem); pMem+= 2; size--; + } + break; + + case 0x0A: // PSMCT16S + while (size > 0) { + FBread16S(pMem); pMem+= 2; + FBread16S(pMem); pMem+= 2; size--; + } + break; + + case 0x13: // PSMT8 + while (size> 0) { + FBread8(pMem); pMem++; + FBread8(pMem); pMem++; + FBread8(pMem); pMem++; + FBread8(pMem); pMem++; size--; + } + break; + + case 0x14: // PSMT4 + while (size > 0) { + FBread4(pMem); pMem++; + FBread4(pMem); pMem++; + FBread4(pMem); pMem++; + FBread4(pMem); pMem++; size--; + } + break; + + case 0x1B: // PSMT8H + while (size > 0) { + FBread8H(pMem); pMem++; + FBread8H(pMem); pMem++; + FBread8H(pMem); pMem++; + FBread8H(pMem); pMem++; size--; + } + break; + + case 0x24: // PSMT4HL + while (size > 0) { + FBread4HL(pMem); pMem++; + FBread4HL(pMem); pMem++; + FBread4HL(pMem); pMem++; + FBread4HL(pMem); pMem++; size--; + } + break; + + case 0x2C: // PSMT4HH + while (size > 0) { + FBread4HH(pMem); pMem++; + FBread4HH(pMem); pMem++; + FBread4HH(pMem); pMem++; + FBread4HH(pMem); pMem++; size--; + } + break; + + case 0x30: // PSMZ32 + while (size > 0) { + FBread32Z(pMem); pMem+= 4; size--; + } + break; + + case 0x31: // PSMZ24 + while (size >= 3) { + FBread24Z_3(pMem); pMem+= 12; size-=3; + } + break; + + case 0x32: // PSMZ16 + while (size > 0) { + FBread16Z(pMem); pMem+= 2; + FBread16Z(pMem); pMem+= 2; size--; + } + break; + + case 0x3A: // PSMZ16S + while (size > 0) { + FBread16SZ(pMem); pMem+= 2; + FBread16SZ(pMem); pMem+= 2; size--; + } + break; + + default: + case 0x00: // PSMCT32 + if (gs.srcbuf.psm != 0) printf("gs.srcbuf.psm == %d!!\n", gs.srcbuf.psm); + while (size > 0) { + FBread(pMem); pMem+= 4; size--; + } + break; + } +} + diff --git a/plugins/gs/GSsoft/Src/Transfer.h b/plugins/gs/GSsoft/Src/Transfer.h new file mode 100644 index 0000000..122858e --- /dev/null +++ b/plugins/gs/GSsoft/Src/Transfer.h @@ -0,0 +1,27 @@ +/* GSsoft + * Copyright (C) 2002-2005 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TRANSFER_H__ +#define __TRANSFER_H__ + +void FBtransferImageB(u32 *pMem, int size); +void FBtransferImage(u32 *pMem, int size); +void FBtransferImageSrcB(u32 *pMem, int size); +void FBtransferImageSrc(u32 *pMem, int size); + +#endif /* __TRANSFER_H__ */ diff --git a/plugins/gs/GSsoft/Src/Win32/Conf.c b/plugins/gs/GSsoft/Src/Win32/Conf.c new file mode 100644 index 0000000..51a0530 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/Conf.c @@ -0,0 +1,110 @@ +#include + +#include "GS.h" +#include "Win32.h" + +extern HINSTANCE hInst; + + +void SaveConfig() { + + GSconf *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\gssoft.ini"); + + sprintf(szValue,"%u",Conf1->fmode.height); + WritePrivateProfileString("Settings", "FmodeHeight",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->fmode.width); + WritePrivateProfileString("Settings", "FmodeWidth",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->wmode.height); + WritePrivateProfileString("Settings", "WmodeHeight",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->wmode.width); + WritePrivateProfileString("Settings", "WmodeWidth",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->fullscreen); + WritePrivateProfileString("Settings", "Fullscreen",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->fps); + WritePrivateProfileString("Settings", "Fps",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->frameskip); + WritePrivateProfileString("Settings", "FrameSkip",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->record); + WritePrivateProfileString("Settings", "Record",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->cache); + WritePrivateProfileString("Settings", "Cache",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->cachesize); + WritePrivateProfileString("Settings", "Cachesize",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->codec); + WritePrivateProfileString("Settings", "Codec",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->filter); + WritePrivateProfileString("Settings", "Filter",szValue,szIniFile); + sprintf(szValue,"%u",Conf1->log); + WritePrivateProfileString("Settings", "Log",szValue,szIniFile); +} + +void LoadConfig() { + + FILE *fp; + GSconf *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\gssoft.ini"); + fp=fopen("inis\\gssoft.ini","rt"); + if (!fp) + { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.fmode.width = 640; + conf.fmode.height = 480; + conf.wmode.width = 640; + conf.wmode.height = 480; + conf.fullscreen = 0; + conf.cachesize = 128; + SaveConfig();//save and return + return ; + } + fclose(fp); + + + + GetPrivateProfileString("Settings", "FmodeHeight", NULL, szValue, 20, szIniFile); + Conf1->fmode.height = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "FmodeWidth", NULL, szValue, 20, szIniFile); + Conf1->fmode.width= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "WmodeHeight", NULL, szValue, 20, szIniFile); + Conf1->wmode.height= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "WmodeWidth", NULL, szValue, 20, szIniFile); + Conf1->wmode.width= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Fullscreen", NULL, szValue, 20, szIniFile); + Conf1->fullscreen= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Fps", NULL, szValue, 20, szIniFile); + Conf1->fps= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "FrameSkip", NULL, szValue, 20, szIniFile); + Conf1->frameskip= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Record", NULL, szValue, 20, szIniFile); + Conf1->record = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Cache", NULL, szValue, 20, szIniFile); + Conf1->cache= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Cachesize", NULL, szValue, 20, szIniFile); + Conf1->cachesize= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Codec", NULL, szValue, 20, szIniFile); + Conf1->codec= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Filter", NULL, szValue, 20, szIniFile); + Conf1->filter= strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Log", NULL, szValue, 20, szIniFile); + Conf1->log = strtoul(szValue, NULL, 10); + + + if (conf.fullscreen) cmode = &conf.fmode; + else cmode = &conf.wmode; +} + diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.def b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.def new file mode 100644 index 0000000..5b1024c --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.def @@ -0,0 +1,33 @@ +; GpuDx7.def : Declares the module parameters for the DLL. + +LIBRARY "GSsoftdx" +DESCRIPTION 'GSsoftdx dll' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + GSinit @5 + GSshutdown @6 + GSopen @7 + GSclose @8 + GSwrite32 @9 + GSwrite64 @10 + GSread32 @11 + GSread64 @12 + GSgifTransfer1 @13 + GSgifTransfer2 @14 + GSgifTransfer3 @15 + GSreadFIFO @16 + GSvsync @17 + GSmakeSnapshot @18 + GSkeyEvent @19 + GSfreeze @20 + GSconfigure @21 + GStest @22 + GSabout @23 + GSwrite8 @24 + GSread8 @25 + GSread16 @26 + GSwrite16 @27 diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsp b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsp new file mode 100644 index 0000000..84be459 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsp @@ -0,0 +1,202 @@ +# Microsoft Developer Studio Project File - Name="GSsoftdx" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=GSsoftdx - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "GSsoftdx.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "GSsoftdx.mak" CFG="GSsoftdx - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "GSsoftdx - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GSSOFTDX_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GSSOFTDX_EXPORTS" /D "__WIN32__" /D "__MSCW32__" /D "__i386__" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 ddraw.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib sdl_gfx.lib /nologo /dll /pdb:none /machine:I386 +# Begin Target + +# Name "GSsoftdx - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\Cache.c +# End Source File +# Begin Source File + +SOURCE=..\Color.c +# End Source File +# Begin Source File + +SOURCE=.\Conf.c +# End Source File +# Begin Source File + +SOURCE=..\Draw.c +# End Source File +# Begin Source File + +SOURCE=..\GS.c +# End Source File +# Begin Source File + +SOURCE=.\GSsoftdx.def +# End Source File +# Begin Source File + +SOURCE=..\Mem.c +# End Source File +# Begin Source File + +SOURCE=..\Page.c +# End Source File +# Begin Source File + +SOURCE=..\Prim.c +# End Source File +# Begin Source File + +SOURCE=..\Rec.c +# End Source File +# Begin Source File + +SOURCE=..\Regs.c +# End Source File +# Begin Source File + +SOURCE=..\scale2x.c +# End Source File +# Begin Source File + +SOURCE=..\SDL.c +# End Source File +# Begin Source File + +SOURCE=..\SDL_gfxPrimitives.c +# End Source File +# Begin Source File + +SOURCE=..\Soft.c +# End Source File +# Begin Source File + +SOURCE=..\Texts.c +# End Source File +# Begin Source File + +SOURCE=..\Transfer.c +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\Draw.h +# End Source File +# Begin Source File + +SOURCE=..\GS.h +# End Source File +# Begin Source File + +SOURCE=..\Mem.h +# End Source File +# Begin Source File + +SOURCE=.\plugin.h +# End Source File +# Begin Source File + +SOURCE=..\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=..\PS2Etypes.h +# End Source File +# Begin Source File + +SOURCE=..\Rec.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=..\Soft.h +# End Source File +# Begin Source File + +SOURCE=..\Texts.h +# End Source File +# Begin Source File + +SOURCE=.\Win32.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\GSsoftdx.rc +# End Source File +# Begin Source File + +SOURCE=.\Pcsx2.ico +# End Source File +# End Group +# Begin Group "Docs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\ReadMe.txt +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsw b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsw new file mode 100644 index 0000000..2eed447 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "GSsoftdx"=".\GSsoftdx.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.ncb b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.ncb new file mode 100644 index 0000000000000000000000000000000000000000..6a64f15d3f8182c5b6e7f1f4627474c367021b63 GIT binary patch literal 273408 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 z
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

?_d1^a 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�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\n\t[TyRaNiD]", + IDC_STATIC,27,20,141,17 + LTEXT "Thanks to:\n shadow - coding support and help.\n Pete Bernert - for the triangles code.\n Absolute0 - help fixing bugs :)\n asadr - lots of help from him :)\n Gabest - fixes, hints, etc, etc ^^\n\nBeta Testers:\n bositman, CKemu, belmont, parotak", + IDC_STATIC,10,45,160,50 +END + +IDD_LOGGING DIALOG DISCARDABLE 0, 0, 152, 55 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,40,35,50,14 + PUSHBUTTON "Cancel",IDCANCEL,95,35,50,14 + CONTROL "Log",IDC_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60, + 15,28,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 330 + TOPMARGIN, 7 + BOTTOMMARGIN, 144 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 175 + TOPMARGIN, 7 + BOTTOMMARGIN, 159 + END + + IDD_LOGGING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 145 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Castilian) (unknown sub-lang: 0xB) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.sln b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.sln new file mode 100644 index 0000000..e415096 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GSsoftdx", "GSsoftdx.vcproj", "{2D4E85B2-F47F-4D65-B091-701E5C031DAC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release.ActiveCfg = Release|Win32 + {2D4E85B2-F47F-4D65-B091-701E5C031DAC}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.suo b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.suo new file mode 100644 index 0000000000000000000000000000000000000000..e1cae98af9531c793dd2ab934ff93ce750ea49b8 GIT binary patch literal 8192 zcmeHMOKe+36un6rn)Khav=B-$O@EZyBzF37Q$CIDq>+-gBq8Y{LUQbv)a|n!Y^NW! zMeIN<5D0Y-5<3Kl4J*U~iA5Kv6%s;Xf#?FUY!`e=X=~1z_r`xaFHVYDDc8Dh=FQwU zcjnIh&G`DY^}l}nW%~^&ftRF7?q^%&v4Zvn)QJk#i8P|Z_xssw)@l?%bqO9J3Eab6 zm)U#RjFS7k9M}SE1+D_F0ImeC2Ce~ezllrm=u2Q&lK5rBB_ThD~rKMULj>;P^D?f~utl4iGE?m_uHa4*npx4nR}6W9gx+HL%13Faq( zfsVE}erz5NeQ>4!syQ}r6QZ0K+zK#C)DMg+YlFtwSj2Dzl8H z*$5<*@~77|Fo!ePi=>iprsh0$gFj;leWX+VjFU>+D)49gqvU5Gg&1Z)J*Wjck%g15 zhFY|`kFiI`pM~nL9+UCoEuf{xR#cycEW;AV9`#`@rrOa7#5(F0qrTQ@7h)iz?<}ZI zP>*2kvl3P7cZo-iAuAX~yB8k6Q+&|(F^q5kCC8ynq*2l)MBe+~=RkcmvC1hm13eS{ z{_xDmnrEr6DAj-NR06Ue!T!uDsn+%a(7y)e3XB5OK@@WWX}`7=uR8w=kSTpq6~}9H zsYm~5uhr~-2wEBkSLVT%hmGQmSy*M*i}h3YR{@=_pZVgbJsj;l1D+{Jo!Xzb6rC9x z(5npWioSr9eCB6!2>i9}JLSItyy-6&3wRGu3JYl~9qU29H;W1%QN?4kyxVxJ0j@lo z-PM@8>UgKe-|*34zoKj9J_GK^MYyA&bi*|rlzm9ny+}>_@O}VKH_D*wN4pz6o#IED z>PAl|$`D!u%8hk_<_PMS#2=msn8!KQKiXczR*+i!^;s+k%g6vL zfd~4}I|*$Am1s)awxZ#%-AF&joJ+6Kva>0ydRqBEa<<}d=_uAa>_5lb>H43+r$5{N z?>KziX~aav%4#-VnX}cpwGRHf@M%a7N?i>BsiA&o>waj88$s5m^w$r)_F`gQXbx+a z@mZJG*UbZ7&Q^BUvXw@;`_S9U2<&4J))KL; zoEcQ{$USIr0(7IlZ`|?27abk_U;TFD@~+8vw{k6OuC|+ZTRV=wpMCrGwQoNOsqn>9 zTH$Gup+@9GCyc7lyy_Bp9c!6yc*@JI_y~Yb)ip zsx`^qDCrTJuydx;<+M738L;K~MIqdO;s)3{(>slSyr;8fnZN&K9?aVhX5N&p=+ z)&}0ck}q=#r~ID-?K)*7g8SZt;u?mv8o=VLJD+D)o5i*|;&0*l%dN2*r^@YZb?~PW z9J1H{kF6Umawk{&H&?rxtKG9}DyF7|Nj_4?4k|w4vtxIUec90 i(Ee$68Y)v2xBBp^@1Kf$>U-0?S=Kkg!oGTx`TqxiM-_hn literal 0 HcmV?d00001 diff --git a/plugins/gs/GSsoft/Src/Win32/GSsoftdx.vcproj b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.vcproj new file mode 100644 index 0000000..a0ef1d6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/GSsoftdx.vcproj @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/GSsoft/Src/Win32/Makefile b/plugins/gs/GSsoft/Src/Win32/Makefile new file mode 100644 index 0000000..eaeff62 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/Makefile @@ -0,0 +1,58 @@ +# +# GSsoft Makefile for MINGW32 +# + + +all: gssoft + +PLUGIN = GSsoft.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +FLAGS = -D__WIN32__ -D__MINGW32__ $(shell sdl-config --cflags)# -DENABLE_NLS -DPACKAGE=\"pcsx2\" +ASMFLAGS = -D__WIN32__ -i.. -i.# -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 $(shell sdl-config --libs) #-lintl +RESOBJ = gssoft.o + +OBJS = ../GS.o ../Cache.o ../Color.o ../Draw.o ../Mem.o \ + ../Page.o ../Prim.o ../Rec.o ../Regs.o ../SDL.o \ + ../Soft.o ../Texts.o ../Transfer.o \ + ../scale2x.o ../SDL_gfxPrimitives.o +OBJS+= Conf.o Win32.o ${RESOBJ} + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I/usr/local/include -I../ffmpeg ${FLAGS} +ASMFLAGS = -f elf ${FLAGS} -i./ -i../ + +FLAGS+= -I../x86 +OBJS+= ../x86/ix86_cpudetect.o + +gssoft: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean gssoft + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: GSsoftdx.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/gs/GSsoft/Src/Win32/SDL.c b/plugins/gs/GSsoft/Src/Win32/SDL.c new file mode 100644 index 0000000..50affb5 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/SDL.c @@ -0,0 +1,225 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +//#include + +#include "GS.h" +#include "Draw.h" +#include "Win32.h" +#include "Rec.h" + +SDL_Surface *surf; +SDL_SysWMinfo info; + +void DXclearScr() { + SDL_FillRect(surf, NULL, 0); +} + +s32 DXopen() { +#ifdef __LINUX__ + int screen; + int w, h; +#endif + + if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; + + surf = SDL_SetVideoMode(cmode->width, cmode->height, 0, conf.fullscreen ? SDL_FULLSCREEN : 0); + if (surf == NULL) return -1; + + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info) == 0) return -1; + +#ifdef __LINUX__ + info.info.x11.lock_func(); + screen = DefaultScreen(info.info.x11.display); + w = DisplayWidth(info.info.x11.display, screen); + h = DisplayHeight(info.info.x11.display, screen); + XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, + cmode->width < w ? (w - cmode->width) / 2 : 0, + cmode->height < h ? (h - cmode->height) / 2 : 0); + info.info.x11.unlock_func(); +#endif + + SDL_WM_SetCaption(GStitle, NULL); + + SETScrBlit(surf->format->BitsPerPixel); + DXclearScr(); + +#ifdef __WIN32__ + return (s32)info.window; +#else + return (s32)info.info.x11.display; +#endif +} + +void DXclose() { + SDL_Quit(); +} + +#include + +void DXupdate() { + SDL_Rect rect; + static time_t to; + static int fpscount, fpsc, fc; + int lPitch; + char *sbuff; + + fc++; + + if (conf.fps || conf.frameskip) { + if (time(NULL) > to) { + time(&to); + fpsc = fpscount; + fpscount = 0; + } + fpscount++; + } + + if (conf.frameskip) { + if ((fpscount % 3) == 0) { + norender = 1; + } else if (norender) { + norender = 0; + } + } + + if (norender == 0) { + SDL_LockSurface(surf); + sbuff = surf->pixels; + lPitch = surf->pitch; + + ScrBlit(sbuff, lPitch); + if (conf.record) recFrame(sbuff, lPitch, surf->format->BitsPerPixel); + + SDL_UnlockSurface(surf); + } + + if (conf.fps) { + char title[256]; + char tmp[256]; + + if (fpspos < 0) fpspos = 0; +#ifndef GS_LOG + if (fpspos > 6) fpspos = 6; +#else + if (fpspos > 7) fpspos = 7; +#endif + switch (fpspos) { + case 0: // FrameSkip + sprintf(tmp, "Frameskip %s", conf.frameskip == 1 ? "On" : "Off"); + norender = 0; + break; + case 1: // Stretch + sprintf(tmp, "Stretch %s", conf.stretch == 1 ? "On" : "Off"); + break; + /*case 2: // Misc stuff + sprintf(tmp, "GSmode %dx%d", gsmode->w, gsmode->h); + break;*/ + case 3: // ShowFullVRam + sprintf(tmp, "ShowFullVRam %s", showfullvram == 1 ? "On" : "Off"); + break; + case 4: // NoAlphaBlending + sprintf(tmp, "NoAlphaBlending %s", noabe == 1 ? "On" : "Off"); + break; + case 5: // DisableRendering + sprintf(tmp, "DisableRendering %s", norender == 1 ? "On" : "Off"); + break; + case 6: // WireFrame + sprintf(tmp, "WireFrame %s", wireframe == 1 ? "On" : "Off"); + break; +#ifdef GS_LOG + case 7: // Log + sprintf(tmp, "Log %s", conf.log == 1 ? "On" : "Off"); + break; +#endif + } + if (fpspress) { + switch (fpspos) { + case 0: + conf.frameskip = 1 - conf.frameskip; + norender = 0; + break; + case 1: + conf.stretch = 1 - conf.stretch; + SETScrBlit(surf->format->BitsPerPixel); + DXclearScr(); + fpspress = 0; + return; + case 3: + DXclearScr(); + showfullvram = 1 - showfullvram; + break; + case 4: + noabe = 1 - noabe; + break; + case 5: + norender = 1 - norender; + break; + case 6: + wireframe = 1 - wireframe; + break; +#ifdef GS_LOG + case 7: + conf.log = 1 - conf.log; + break; +#endif + } + fpspress = 0; + } + + sprintf(title,"FPS %d -- %s - FC: %d", fpsc, tmp, fc); + + rect.x = 0; rect.y = 0; + rect.w = cmode->width; + rect.h = 15; + SDL_FillRect(surf, &rect, 0); +// stringRGBA(surf, 4, 4, title, 0, 0xff, 0, 0xff); + } + + SDL_UpdateRect(surf, 0, 0, 0, 0); + SDL_PumpEvents(); +} + +int DXgetModes() { + SDL_Rect **rects; + int i; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) return -1; + + memset(modes, 0, sizeof(modes)); + rects = SDL_ListModes(NULL, SDL_FULLSCREEN); + if (rects == NULL) return -1; + + for (i=0; i<64; i++) { + if (rects[i] == NULL) break; + modes[i].width = rects[i]->w; + modes[i].height = rects[i]->h; + } + + SDL_Quit(); + + return i; +} + diff --git a/plugins/gs/GSsoft/Src/Win32/Win32.c b/plugins/gs/GSsoft/Src/Win32/Win32.c new file mode 100644 index 0000000..ff72e71 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/Win32.c @@ -0,0 +1,274 @@ +#include +#include +#include + +#include "GS.h" +#include "Win32.h" +#include "Rec.h" + +HINSTANCE hInst=NULL; + +void CALLBACK GSkeyEvent(keyEvent *ev) { + switch (ev->event) { + case KEYPRESS: + switch (ev->key) { + case VK_PRIOR: + if (conf.fps) fpspos++; break; + case VK_NEXT: + if (conf.fps) fpspos--; break; + case VK_END: + if (conf.fps) fpspress = 1; break; + case VK_DELETE: + conf.fps = 1 - conf.fps; + break; + } + break; + } +} + +#include "Win32/resource.h" + +BOOL CALLBACK LoggingDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + if (conf.log) CheckDlgButton(hW, IDC_LOG, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOG)) + conf.log = 1; + else conf.log = 0; + + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +int CacheSizes[] = { 64, 128, 256, 0 }; + +DXmode wmodes[] = { + { 320, 240, 0 }, + { 512, 384, 0 }, + { 640, 480, 0 }, + { 800, 600, 0 }, + { 0, 0, 0 }, +}; + +void OnInitDialog(HWND hW) { + HWND hWC; + char str[256]; + int i, j; + int nmode; + + LoadConfig(); + if (recExist() == 0) { + EnableWindow (GetDlgItem(hW, IDC_RECORD), TRUE); + EnableWindow (GetDlgItem(hW, IDC_CODEC) , TRUE); + } else { + conf.record=0; + CheckDlgButton(hW,IDC_RECORD,BST_UNCHECKED); + EnableWindow (GetDlgItem(hW, IDC_RECORD), FALSE); + EnableWindow (GetDlgItem(hW, IDC_CODEC), FALSE); + } + for (i=0; ; i++) { + if (codeclist[i] == NULL) break; + ComboBox_AddString(GetDlgItem(hW, IDC_CODEC), codeclist[i]); + } + + ComboBox_SetCurSel(GetDlgItem(hW, IDC_CODEC), conf.codec); + nmode = DXgetModes(); + + hWC = GetDlgItem(hW, IDC_FRES); + for (i=0; i +#include + +#define IDC_STATIC (-1) diff --git a/plugins/gs/GSsoft/Src/Win32/plugin.def b/plugins/gs/GSsoft/Src/Win32/plugin.def new file mode 100644 index 0000000..49ad02b --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/plugin.def @@ -0,0 +1,31 @@ +EXPORTS + GSabout = GSabout@0 @90 + GSclose = GSclose@0 @91 + GSconfigure = GSconfigure@0 @92 + GSfreeze = GSfreeze@8 @93 + GSgetDriverInfo = GSgetDriverInfo@4 @94 + GSgifTransfer1 = GSgifTransfer1@8 @95 + GSgifTransfer2 = GSgifTransfer2@8 @96 + GSgifTransfer3 = GSgifTransfer3@8 @97 + GSinit = GSinit@0 @99 + GSirqCallback = GSirqCallback@4 @101 + GSkeyEvent = GSkeyEvent@4 @102 + GSmakeSnapshot = GSmakeSnapshot@4 @103 + GSopen = GSopen@8 @104 + GSprintf = GSprintf@0 @105 + GSread16 = GSread16@4 @106 + GSread32 = GSread32@4 @107 + GSread64 = GSread64@4 @108 + GSread8 = GSread8@4 @109 + GSreadFIFO = GSreadFIFO@4 @110 + GSreset @111 + GSshutdown = GSshutdown@0 @112 + GStest = GStest@0 @113 + GSvsync = GSvsync@0 @115 + GSwrite16 = GSwrite16@8 @117 + GSwrite32 = GSwrite32@8 @118 + GSwrite64 = GSwrite64@12 @119 + GSwrite8 = GSwrite8@8 @120 + PS2EgetLibName = PS2EgetLibName@0 @128 + PS2EgetLibType = PS2EgetLibType@0 @129 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @130 diff --git a/plugins/gs/GSsoft/Src/Win32/plugin.h b/plugins/gs/GSsoft/Src/Win32/plugin.h new file mode 100644 index 0000000..ab4f660 --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/plugin.h @@ -0,0 +1,18 @@ + + +typedef struct { + HINSTANCE havcodec; + void (__cdecl* avcodec_init)(void); + void (__cdecl* avcodec_register_all)(void); + AVCodec *(__cdecl* avcodec_find_encoder)(enum CodecID id); + AVCodecContext *(__cdecl* avcodec_alloc_context)(void); + AVFrame *(__cdecl* avcodec_alloc_frame)(void); + int (__cdecl* avcodec_open)(AVCodecContext *avctx, AVCodec *codec); + int (__cdecl* img_convert)(AVPicture *dst, int dst_pix_fmt, AVPicture *src, int pix_fmt, int width, int height); + int (__cdecl* avcodec_encode_video)(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVFrame *pict); + int (__cdecl* avcodec_close)(AVCodecContext *avctx); +} RECPLUGIN; + +extern RECPLUGIN recplugin; + + diff --git a/plugins/gs/GSsoft/Src/Win32/resource.h b/plugins/gs/GSsoft/Src/Win32/resource.h new file mode 100644 index 0000000..e11e2fe --- /dev/null +++ b/plugins/gs/GSsoft/Src/Win32/resource.h @@ -0,0 +1,42 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by GSsoftdx.rc +// +#define IDD_CONFIG 101 +#define IDD_ABOUT 102 +#define IDD_LOGGING 106 +#define IDC_CHECK1 1000 +#define IDC_FULLSCREEN 1000 +#define IDC_NAME 1000 +#define IDC_LOG 1000 +#define IDC_CHECK2 1001 +#define IDC_FPSCOUNT 1001 +#define IDC_CHECK5 1002 +#define IDC_FRAMESKIP 1002 +#define IDC_STRETCH 1003 +#define IDC_LOGGING 1004 +#define IDC_COMBO1 1005 +#define IDC_CACHE 1005 +#define IDC_CACHESIZE 1006 +#define IDC_CHECK3 1007 +#define IDC_RECORD 1007 +#define IDC_COMBO2 1008 +#define IDC_DSPRES 1008 +#define IDC_WRES 1008 +#define IDC_COMBO3 1009 +#define IDC_DDDRV 1009 +#define IDC_FRES 1009 +#define IDC_COMBO4 1012 +#define IDC_CODEC 1012 +#define IDC_FILTERS 1014 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 107 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1015 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/gs/GSsoft/Src/avcodec.h b/plugins/gs/GSsoft/Src/avcodec.h new file mode 100644 index 0000000..e04bff5 --- /dev/null +++ b/plugins/gs/GSsoft/Src/avcodec.h @@ -0,0 +1,1688 @@ +#ifndef AVCODEC_H +#define AVCODEC_H + +/** + * @file avcodec.h + * external api header. + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common.h" + +#define FFMPEG_VERSION_INT 0x000408 +#define FFMPEG_VERSION "0.4.8" +#define LIBAVCODEC_BUILD 4680 + +#define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT +#define LIBAVCODEC_VERSION FFMPEG_VERSION + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s +#define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" AV_STRINGIFY(LIBAVCODEC_BUILD) + +enum CodecID { + CODEC_ID_NONE, + CODEC_ID_MPEG1VIDEO, + CODEC_ID_MPEG2VIDEO, /* prefered ID for MPEG Video 1 or 2 decoding */ + CODEC_ID_MPEG2VIDEO_XVMC, + CODEC_ID_H263, + CODEC_ID_RV10, + CODEC_ID_MP2, + CODEC_ID_MP3, /* prefered ID for MPEG Audio layer 1, 2 or3 decoding */ + CODEC_ID_VORBIS, + CODEC_ID_AC3, + CODEC_ID_MJPEG, + CODEC_ID_MJPEGB, + CODEC_ID_LJPEG, + CODEC_ID_MPEG4, + CODEC_ID_RAWVIDEO, + CODEC_ID_MSMPEG4V1, + CODEC_ID_MSMPEG4V2, + CODEC_ID_MSMPEG4V3, + CODEC_ID_WMV1, + CODEC_ID_WMV2, + CODEC_ID_H263P, + CODEC_ID_H263I, + CODEC_ID_FLV1, + CODEC_ID_SVQ1, + CODEC_ID_SVQ3, + CODEC_ID_DVVIDEO, + CODEC_ID_DVAUDIO, + CODEC_ID_WMAV1, + CODEC_ID_WMAV2, + CODEC_ID_MACE3, + CODEC_ID_MACE6, + CODEC_ID_HUFFYUV, + CODEC_ID_CYUV, + CODEC_ID_H264, + CODEC_ID_INDEO3, + CODEC_ID_VP3, + CODEC_ID_AAC, + CODEC_ID_MPEG4AAC, + CODEC_ID_ASV1, + CODEC_ID_ASV2, + CODEC_ID_FFV1, + CODEC_ID_4XM, + CODEC_ID_VCR1, + CODEC_ID_CLJR, + CODEC_ID_MDEC, + CODEC_ID_ROQ, + CODEC_ID_INTERPLAY_VIDEO, + CODEC_ID_XAN_WC3, + CODEC_ID_XAN_WC4, + + /* various pcm "codecs" */ + CODEC_ID_PCM_S16LE, + CODEC_ID_PCM_S16BE, + CODEC_ID_PCM_U16LE, + CODEC_ID_PCM_U16BE, + CODEC_ID_PCM_S8, + CODEC_ID_PCM_U8, + CODEC_ID_PCM_MULAW, + CODEC_ID_PCM_ALAW, + + /* various adpcm codecs */ + CODEC_ID_ADPCM_IMA_QT, + CODEC_ID_ADPCM_IMA_WAV, + CODEC_ID_ADPCM_IMA_DK3, + CODEC_ID_ADPCM_IMA_DK4, + CODEC_ID_ADPCM_MS, + CODEC_ID_ADPCM_4XM, + + /* AMR */ + CODEC_ID_AMR_NB, + /* RealAudio codecs*/ + CODEC_ID_RA_144, + CODEC_ID_RA_288, + + /* various DPCM codecs */ + CODEC_ID_ROQ_DPCM, + CODEC_ID_INTERPLAY_DPCM, + CODEC_ID_XAN_DPCM, +}; + +/* CODEC_ID_MP3LAME is absolete */ +#define CODEC_ID_MP3LAME CODEC_ID_MP3 + +enum CodecType { + CODEC_TYPE_UNKNOWN = -1, + CODEC_TYPE_VIDEO, + CODEC_TYPE_AUDIO, +}; + +/** + * Pixel format. Notes: + * + * PIX_FMT_RGBA32 is handled in an endian-specific manner. A RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little endian CPU architectures and ARGB on + * big endian CPUs. + * + * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in PIX_FMT_RGBA32 described above (i.e., it is + * also endian-specific). + */ +enum PixelFormat { + PIX_FMT_YUV420P, ///< Planar YUV 4:2:0 (1 Cr & Cb sample per 2x2 Y samples) + PIX_FMT_YUV422, + PIX_FMT_RGB24, ///< Packed pixel, 3 bytes per pixel, RGBRGB... + PIX_FMT_BGR24, ///< Packed pixel, 3 bytes per pixel, BGRBGR... + PIX_FMT_YUV422P, ///< Planar YUV 4:2:2 (1 Cr & Cb sample per 2x1 Y samples) + PIX_FMT_YUV444P, ///< Planar YUV 4:4:4 (1 Cr & Cb sample per 1x1 Y samples) + PIX_FMT_RGBA32, ///< Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness + PIX_FMT_YUV410P, ///< Planar YUV 4:1:0 (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YUV411P, ///< Planar YUV 4:1:1 (1 Cr & Cb sample per 4x1 Y samples) + PIX_FMT_RGB565, ///< always stored in cpu endianness + PIX_FMT_RGB555, ///< always stored in cpu endianness, most significant bit to 1 + PIX_FMT_GRAY8, + PIX_FMT_MONOWHITE, ///< 0 is white + PIX_FMT_MONOBLACK, ///< 0 is black + PIX_FMT_PAL8, ///< 8 bit with RGBA palette + PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0 full scale (jpeg) + PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2 full scale (jpeg) + PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4 full scale (jpeg) + PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h) + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_NB, +}; + +/* currently unused, may be used if 24/32 bits samples ever supported */ +enum SampleFormat { + SAMPLE_FMT_S16 = 0, ///< signed 16 bits +}; + +/* in bytes */ +#define AVCODEC_MAX_AUDIO_FRAME_SIZE 131072 + +/** + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * this is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end
+ * Note, if the first 23 bits of the additional bytes are not 0 then damaged + * MPEG bitstreams could cause overread and segfault + */ +#define FF_INPUT_BUFFER_PADDING_SIZE 8 + +/* motion estimation type, EPZS by default */ +enum Motion_Est_ID { + ME_ZERO = 1, + ME_FULL, + ME_LOG, + ME_PHODS, + ME_EPZS, + ME_X1 +}; + +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // if this is 0 then quality_factor will be used instead + float quality_factor; +} RcOverride; + +/* only for ME compatiblity with old apps */ +extern int motion_estimation_method; + +/* ME algos sorted by quality */ +static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, + ME_X1, ME_EPZS, ME_FULL }; + + +#define FF_MAX_B_FRAMES 8 + +/* encoding support + these flags can be passed in AVCodecContext.flags before initing + Note: note not everything is supported yet +*/ + +#define CODEC_FLAG_QSCALE 0x0002 ///< use fixed qscale +#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed +#define CODEC_FLAG_QPEL 0x0010 ///< use qpel MC +#define CODEC_FLAG_GMC 0x0020 ///< use GMC +#define CODEC_FLAG_PART 0x0080 ///< use data partitioning +/* parent program gurantees that the input for b-frame containing streams is not written to + for at least s->max_b_frames+1 frames, if this is not set than the input will be copied */ +#define CODEC_FLAG_INPUT_PRESERVED 0x0100 +#define CODEC_FLAG_PASS1 0x0200 ///< use internal 2pass ratecontrol in first pass mode +#define CODEC_FLAG_PASS2 0x0400 ///< use internal 2pass ratecontrol in second pass mode +#define CODEC_FLAG_EXTERN_HUFF 0x1000 ///< use external huffman table (for mjpeg) +#define CODEC_FLAG_GRAY 0x2000 ///< only decode/encode grayscale +#define CODEC_FLAG_EMU_EDGE 0x4000///< dont draw edges +#define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding +#define CODEC_FLAG_TRUNCATED 0x00010000 /** input bitstream might be truncated at a random location instead + of only at frame boundaries */ +#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 ///< normalize adaptive quantization +#define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< use interlaced dct +#define CODEC_FLAG_LOW_DELAY 0x00080000 ///< force low delay +#define CODEC_FLAG_ALT_SCAN 0x00100000 ///< use alternate scan +#define CODEC_FLAG_TRELLIS_QUANT 0x00200000 ///< use trellis quantization +#define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< place global headers in extradata instead of every keyframe +#define CODEC_FLAG_BITEXACT 0x00800000 ///< use only bitexact stuff (except (i)dct) +/* Fx : Flag for h263+ extra options */ +#define CODEC_FLAG_H263P_AIC 0x01000000 ///< Advanced intra coding +#define CODEC_FLAG_H263P_UMV 0x02000000 ///< Unlimited motion vector +/* For advanced prediction mode, we reuse the 4MV flag */ +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Deblocking filter internal loop + * Slice structured + * Reference Picture Selection + * Independant Segment Decoding + * Alternative Inter * VLC + * Modified Quantization */ +/* /Fx */ +/* codec capabilities */ + +#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< decoder can use draw_horiz_band callback +/** + * Codec uses get_buffer() for allocating buffers. + * direct rendering method 1 + */ +#define CODEC_CAP_DR1 0x0002 +/* if 'parse_only' field is true, then avcodec_parse_frame() can be + used */ +#define CODEC_CAP_PARSE_ONLY 0x0004 +#define CODEC_CAP_TRUNCATED 0x0008 + +#define FF_COMMON_FRAME \ + /**\ + * pointer to the picture planes.\ + * this might be different from the first allocated byte\ + * - encoding: \ + * - decoding: \ + */\ + uint8_t *data[4];\ + int linesize[4];\ + /**\ + * pointer to the first allocated byte of the picture. can be used in get_buffer/release_buffer\ + * this isnt used by lavc unless the default get/release_buffer() is used\ + * - encoding: \ + * - decoding: \ + */\ + uint8_t *base[4];\ + /**\ + * 1 -> keyframe, 0-> not\ + * - encoding: set by lavc\ + * - decoding: set by lavc\ + */\ + int key_frame;\ +\ + /**\ + * picture type of the frame, see ?_TYPE below.\ + * - encoding: set by lavc for coded_picture (and set by user for input)\ + * - decoding: set by lavc\ + */\ + int pict_type;\ +\ + /**\ + * presentation timestamp in micro seconds (time when frame should be shown to user)\ + * if 0 then the frame_rate will be used as reference\ + * - encoding: MUST be set by user\ + * - decoding: set by lavc\ + */\ + int64_t pts;\ +\ + /**\ + * picture number in bitstream order.\ + * - encoding: set by\ + * - decoding: set by lavc\ + */\ + int coded_picture_number;\ + /**\ + * picture number in display order.\ + * - encoding: set by\ + * - decoding: set by lavc\ + */\ + int display_picture_number;\ +\ + /**\ + * quality (between 1 (good) and 31 (bad)) \ + * - encoding: set by lavc for coded_picture (and set by user for input)\ + * - decoding: set by lavc\ + */\ + float quality; \ +\ + /**\ + * buffer age (1->was last buffer and dint change, 2->..., ...).\ + * set to something large if the buffer has not been used yet \ + * - encoding: unused\ + * - decoding: MUST be set by get_buffer()\ + */\ + int age;\ +\ + /**\ + * is this picture used as reference\ + * - encoding: unused\ + * - decoding: set by lavc (before get_buffer() call))\ + */\ + int reference;\ +\ + /**\ + * QP table\ + * - encoding: unused\ + * - decoding: set by lavc\ + */\ + int8_t *qscale_table;\ + /**\ + * QP store stride\ + * - encoding: unused\ + * - decoding: set by lavc\ + */\ + int qstride;\ +\ + /**\ + * mbskip_table[mb]>=1 if MB didnt change\ + * stride= mb_width = (width+15)>>4\ + * - encoding: unused\ + * - decoding: set by lavc\ + */\ + uint8_t *mbskip_table;\ +\ + /**\ + * for some private data of the user\ + * - encoding: unused\ + * - decoding: set by user\ + */\ + void *opaque;\ +\ + /**\ + * error\ + * - encoding: set by lavc if flags&CODEC_FLAG_PSNR\ + * - decoding: unused\ + */\ + uint64_t error[4];\ +\ + /**\ + * type of the buffer (to keep track of who has to dealloc data[*])\ + * - encoding: set by the one who allocs it\ + * - decoding: set by the one who allocs it\ + * Note: user allocated (direct rendering) & internal buffers can not coexist currently\ + */\ + int type;\ + \ + /**\ + * when decoding, this signal how much the picture must be delayed.\ + * extra_delay = repeat_pict / (2*fps)\ + * - encoding: unused\ + * - decoding: set by lavc\ + */\ + int repeat_pict;\ + \ + /**\ + * \ + */\ + int qscale_type;\ + +#define FF_QSCALE_TYPE_MPEG1 0 +#define FF_QSCALE_TYPE_MPEG2 1 + +#define FF_BUFFER_TYPE_INTERNAL 1 +#define FF_BUFFER_TYPE_USER 2 ///< Direct rendering buffers (image is (de)allocated by user) +#define FF_BUFFER_TYPE_SHARED 4 ///< buffer from somewher else, dont dealloc image (data/base) +#define FF_BUFFER_TYPE_COPY 8 ///< just a (modified) copy of some other buffer, dont dealloc anything + + +#define FF_I_TYPE 1 // Intra +#define FF_P_TYPE 2 // Predicted +#define FF_B_TYPE 3 // Bi-dir predicted +#define FF_S_TYPE 4 // S(GMC)-VOP MPEG4 +#define FF_SI_TYPE 5 +#define FF_SP_TYPE 6 + +/** + * Audio Video Frame. + */ +typedef struct AVFrame { + FF_COMMON_FRAME +} AVFrame; + +#define DEFAULT_FRAME_RATE_BASE 1001000 + +/** + * main external api structure. + */ +typedef struct AVCodecContext { + /** + * the average bitrate. + * - encoding: set by user. unused for constant quantizer encoding + * - decoding: set by lavc. 0 or some bitrate if this info is available in the stream + */ + int bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: set by user. unused for constant quantizer encoding + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * CODEC_FLAG_*. + * - encoding: set by user. + * - decoding: set by user. + */ + int flags; + + /** + * some codecs needs additionnal format info. It is stored here + * - encoding: set by user. + * - decoding: set by lavc. (FIXME is this ok?) + */ + int sub_id; + + /** + * motion estimation algorithm used for video coding. + * - encoding: MUST be set by user. + * - decoding: unused + */ + int me_method; + + /** + * some codecs need / can use extra-data like huffman tables. + * mjpeg: huffman tables + * rv10: additional flags + * mpeg4: global headers (they can be in the bitstream or here) + * - encoding: set/allocated/freed by lavc. + * - decoding: set/allocated/freed by user. + */ + void *extradata; + int extradata_size; + + /* video only */ + /** + * frames per sec multiplied by frame_rate_base. + * for variable fps this is the precission, so if the timestamps + * can be specified in msec precssion then this is 1000*frame_rate_base + * - encoding: MUST be set by user + * - decoding: set by lavc. 0 or the frame_rate if available + */ + int frame_rate; + + /** + * width / height. + * - encoding: MUST be set by user. + * - decoding: set by user, some codecs might override / change it during playback + */ + int width, height; + +#define FF_ASPECT_SQUARE 1 +#define FF_ASPECT_4_3_625 2 +#define FF_ASPECT_4_3_525 3 +#define FF_ASPECT_16_9_625 4 +#define FF_ASPECT_16_9_525 5 +#define FF_ASPECT_EXTENDED 15 + + /** + * the number of pictures in a group of pitures, or 0 for intra_only. + * - encoding: set by user. + * - decoding: unused + */ + int gop_size; + + /** + * pixel format, see PIX_FMT_xxx. + * - encoding: FIXME: used by ffmpeg to decide whether an pix_fmt + * conversion is in order. This only works for + * codecs with one supported pix_fmt, we should + * do something for a generic case as well. + * - decoding: set by lavc. + */ + enum PixelFormat pix_fmt; + + /** + * Frame rate emulation. If not zero lower layer (i.e. format handler) + * has to read frames at native frame rate. + * - encoding: set by user. + * - decoding: unused. + */ + int rate_emu; + + /** + * if non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw an horizontal band. It improve cache usage. Not + * all codecs can do that. You must check the codec capabilities + * before + * - encoding: unused + * - decoding: set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + AVFrame *src, int offset[4], + int y, int type, int height); + + /* audio only */ + int sample_rate; ///< samples per sec + int channels; + int sample_fmt; ///< sample format, currenly unused + + /* the following data should not be initialized */ + int frame_size; ///< in samples, initialized when calling 'init' + int frame_number; ///< audio or video frame number + int real_pict_num; ///< returns the real picture number of previous encoded frame + + /** + * number of frames the decoded output will be delayed relative to + * the encoded input. + * - encoding: set by lavc. + * - decoding: unused + */ + int delay; + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer. + * - encoding: set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer. + * - encoding: set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference etween frames. + * - encoding: set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * maximum number of b frames between non b frames. + * note: the output will be delayed by max_b_frames+1 relative to the input + * - encoding: set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between ip and b frames. + * - encoding: set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** obsolete FIXME remove */ + int rc_strategy; + int b_frame_strategy; + + /** + * hurry up amount. + * - encoding: unused + * - decoding: set by user. 1-> skip b frames, 2-> skip idct/dequant too, 5-> skip everything except header + */ + int hurry_up; + + struct AVCodec *codec; + + void *priv_data; + + /* The following data is for RTP friendly coding */ + /* By now only H.263/H.263+/MPEG4 coder honours this */ + int rtp_mode; /* 1 for activate RTP friendly-mode */ + /* highers numbers represent more error-prone */ + /* enviroments, by now just "1" exist */ + + int rtp_payload_size; /* The size of the RTP payload, the coder will */ + /* do it's best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263 */ + /* This doesn't take account of any particular */ + /* headers inside the transmited RTP payload */ + + + /* The RTP callcack: This function is called */ + /* every time the encoder as a packet to send */ + /* Depends on the encoder if the data starts */ + /* with a Start Code (it should) H.263 does */ + void (*rtp_callback)(void *data, int size, int packet_number); + + /* statistics, used for 2-pass encoding */ + int mv_bits; + int header_bits; + int i_tex_bits; + int p_tex_bits; + int i_count; + int p_count; + int skip_count; + int misc_bits; + + /** + * number of bits used for the previously encoded frame. + * - encoding: set by lavc + * - decoding: unused + */ + int frame_bits; + + /** + * private data of the user, can be used to carry app specific stuff. + * - encoding: set by user + * - decoding: set by user + */ + void *opaque; + + char codec_name[32]; + enum CodecType codec_type; /* see CODEC_TYPE_xxx */ + enum CodecID codec_id; /* see CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * this is used to workaround some encoder bugs + * - encoding: set by user, if not then the default based on codec_id will be used + * - decoding: set by user, will be converted to upper case by lavc during init + */ + unsigned int codec_tag; + + /** + * workaround bugs in encoders which sometimes cannot be detected automatically. + * - encoding: unused + * - decoding: set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_OLD_MSMPEG4 2 +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AC_VLC 32 +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +//#define FF_BUG_FAKE_SCALABILITY 16 //autodetection should work 100% + + /** + * luma single coeff elimination threshold. + * - encoding: set by user + * - decoding: unused + */ + int luma_elim_threshold; + + /** + * chroma single coeff elimination threshold. + * - encoding: set by user + * - decoding: unused + */ + int chroma_elim_threshold; + + /** + * strictly follow the std (MPEG4, ...). + * - encoding: set by user + * - decoding: unused + */ + int strict_std_compliance; + + /** + * qscale offset between ip and b frames. + * if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) + * if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) + * - encoding: set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * error resilience higher values will detect more errors but may missdetect + * some more or less valid parts as errors. + * - encoding: unused + * - decoding: set by user + */ + int error_resilience; +#define FF_ER_CAREFULL 1 +#define FF_ER_COMPLIANT 2 +#define FF_ER_AGGRESSIVE 3 +#define FF_ER_VERY_AGGRESSIVE 4 + + /** + * called at the beginning of each frame to get a buffer for it. + * if pic.reference is set then the frame will be read later by lavc + * width and height should be rounded up to the next multiple of 16 + * - encoding: unused + * - decoding: set by lavc, user can override + */ + int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * called to release buffers which where allocated with get_buffer. + * a released buffer can be reused in get_buffer() + * pic.data[*] must be set to NULL + * - encoding: unused + * - decoding: set by lavc, user can override + */ + void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * is 1 if the decoded stream contains b frames, 0 otherwise. + * - encoding: unused + * - decoding: set by lavc + */ + int has_b_frames; + + int block_align; ///< used by some WAV based audio codecs + + int parse_only; /* - decoding only: if true, only parsing is done + (function avcodec_parse_frame()). The frame + data is returned. Only MPEG codecs support this now. */ + + /** + * 0-> h263 quant 1-> mpeg quant. + * - encoding: set by user. + * - decoding: unused + */ + int mpeg_quant; + + /** + * pass1 encoding statistics output buffer. + * - encoding: set by lavc + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer. + * concatenated stuff from stats_out of pass1 should be placed here + * - encoding: allocated/set/freed by user + * - decoding: unused + */ + char *stats_in; + + /** + * ratecontrol qmin qmax limiting method. + * 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax + * - encoding: set by user. + * - decoding: unused + */ + float rc_qsquish; + + float rc_qmod_amp; + int rc_qmod_freq; + + /** + * ratecontrol override, see RcOverride. + * - encoding: allocated/set/freed by user. + * - decoding: unused + */ + RcOverride *rc_override; + int rc_override_count; + + /** + * rate control equation. + * - encoding: set by user + * - decoding: unused + */ + char *rc_eq; + + /** + * maximum bitrate. + * - encoding: set by user. + * - decoding: unused + */ + int rc_max_rate; + + /** + * minimum bitrate. + * - encoding: set by user. + * - decoding: unused + */ + int rc_min_rate; + + /** + * decoder bitstream buffer size. + * - encoding: set by user. + * - decoding: unused + */ + int rc_buffer_size; + float rc_buffer_aggressivity; + + /** + * qscale factor between p and i frames. + * - encoding: set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between p and i frames. + * if > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset) + * if < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset) + * - encoding: set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * initial complexity for pass1 ratecontrol. + * - encoding: set by user. + * - decoding: unused + */ + float rc_initial_cplx; + + /** + * dct algorithm, see FF_DCT_* below. + * - encoding: set by user + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_MLIB 4 +#define FF_DCT_ALTIVEC 5 + + /** + * luminance masking (0-> disabled). + * - encoding: set by user + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled). + * - encoding: set by user + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled). + * - encoding: set by user + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled). + * - encoding: set by user + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled). + * - encoding: set by user + * - decoding: unused + */ + float dark_masking; + + + /* for binary compatibility */ + int unused; + + /** + * idct algorithm, see FF_IDCT_* below. + * - encoding: set by user + * - decoding: set by user + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_LIBMPEG2MMX 4 +#define FF_IDCT_PS2 5 +#define FF_IDCT_MLIB 6 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SH4 9 +#define FF_IDCT_SIMPLEARM 10 + + /** + * slice count. + * - encoding: set by lavc + * - decoding: set by user (or 0) + */ + int slice_count; + /** + * slice offsets in the frame in bytes. + * - encoding: set/allocated by lavc + * - decoding: set/allocated by user (or NULL) + */ + int *slice_offset; + + /** + * error concealment flags. + * - encoding: unused + * - decoding: set by user + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 + + /** + * dsp_mask could be add used to disable unwanted CPU features + * CPU features (i.e. MMX, SSE. ...) + * + * with FORCE flag you may instead enable given CPU features + * (Dangerous: usable in case of misdetection, improper usage however will + * result into program crash) + */ + unsigned dsp_mask; +#define FF_MM_FORCE 0x80000000 /* force usage of selected flags (OR) */ + /* lower 16 bits - CPU features */ +#ifdef HAVE_MMX +#define FF_MM_MMX 0x0001 /* standard MMX */ +#define FF_MM_3DNOW 0x0004 /* AMD 3DNOW */ +#define FF_MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */ +#define FF_MM_SSE 0x0008 /* SSE functions */ +#define FF_MM_SSE2 0x0010 /* PIV SSE2 functions */ +#endif /* HAVE_MMX */ + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: set by lavc + * - decoding: set by user + */ + int bits_per_sample; + + /** + * prediction method (needed for huffyuv). + * - encoding: set by user + * - decoding: unused + */ + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 + + /** + * aspect ratio (0 if unknown). + * - encoding: set by user. + * - decoding: set by lavc. + */ + float aspect_ratio; + + /** + * the picture in the bitstream. + * - encoding: set by lavc + * - decoding: set by lavc + */ + AVFrame *coded_frame; + + /** + * debug. + * - encoding: set by user. + * - decoding: set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_MV 32 +#define FF_DEBUG_VIS_MV 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_PTS 0x00000200 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 + + /** + * error. + * - encoding: set by lavc if flags&CODEC_FLAG_PSNR + * - decoding: unused + */ + uint64_t error[4]; + + /** + * minimum MB quantizer. + * - encoding: set by user. + * - decoding: unused + */ + int mb_qmin; + + /** + * maximum MB quantizer. + * - encoding: set by user. + * - decoding: unused + */ + int mb_qmax; + + /** + * motion estimation compare function. + * - encoding: set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation compare function. + * - encoding: set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock compare function (not supported yet). + * - encoding: set by user. + * - decoding: unused + */ + int mb_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape. + * - encoding: set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square). + * - encoding: set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * pre pass for motion estimation. + * - encoding: set by user. + * - decoding: unused + */ + int pre_me; + + /** + * motion estimation pre pass compare function. + * - encoding: set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME pre pass diamond size & shape. + * - encoding: set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality. + * - encoding: set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * callback to negotiate the pixelFormat. + * @param fmt is the list of formats which are supported by the codec, + * its terminated by -1 as 0 is a valid format, the formats are ordered by quality + * the first is allways the native one + * @return the choosen format + * - encoding: unused + * - decoding: set by user, if not set then the native format will always be choosen + */ + enum PixelFormat (*get_format)(struct AVCodecContext *s, enum PixelFormat * fmt); + + /** + * DTG active format information (additionnal aspect ratio + * information only used in DVB MPEG2 transport streams). 0 if + * not set. + * + * - encoding: unused. + * - decoding: set by decoder + */ + int dtg_active_format; +#define FF_DTG_AFD_SAME 8 +#define FF_DTG_AFD_4_3 9 +#define FF_DTG_AFD_16_9 10 +#define FF_DTG_AFD_14_9 11 +#define FF_DTG_AFD_4_3_SP_14_9 13 +#define FF_DTG_AFD_16_9_SP_14_9 14 +#define FF_DTG_AFD_SP_4_3 15 + + /** + * Maximum motion estimation search range in subpel units. + * if 0 then no limit + * + * - encoding: set by user. + * - decoding: unused. + */ + int me_range; + + /** + * frame_rate_base. + * for variable fps this is 1 + * - encoding: set by user. + * - decoding: set by lavc. + * @todo move this after frame_rate + */ + + int frame_rate_base; + /** + * intra quantizer bias. + * - encoding: set by user. + * - decoding: unused + */ + int intra_quant_bias; +#define FF_DEFAULT_QUANT_BIAS 999999 + + /** + * inter quantizer bias. + * - encoding: set by user. + * - decoding: unused + */ + int inter_quant_bias; + + /** + * color table ID. + * - encoding: unused. + * - decoding: which clrtable should be used for 8bit RGB images + * table have to be stored somewhere FIXME + */ + int color_table_id; + + /** + * internal_buffer count. + * Dont touch, used by lavc default_get_buffer() + */ + int internal_buffer_count; + + /** + * internal_buffers. + * Dont touch, used by lavc default_get_buffer() + */ + void *internal_buffer; + +#define FF_QUALITY_SCALE 256 + /** + * global quality for codecs which cannot change it per frame. + * this should be proportional to MPEG1/2/4 qscale. + * - encoding: set by user. + * - decoding: unused + */ + int global_quality; + +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 + /** + * coder type + * - encoding: set by user. + * - decoding: unused + */ + int coder_type; + + /** + * context model + * - encoding: set by user. + * - decoding: unused + */ + int context_model; + + /** + * slice flags + * - encoding: unused + * - decoding: set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * XVideo Motion Acceleration + * - encoding: forbidden + * - decoding: set by decoder + */ + int xvmc_acceleration; + + /** + * macroblock decision mode + * - encoding: set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distoration + + /** + * custom intra quantization matrix + * - encoding: set by user, can be NULL + * - decoding: set by lavc + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * - encoding: set by user, can be NULL + * - decoding: set by lavc + */ + uint16_t *inter_matrix; + + /** + * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * this is used to workaround some encoder bugs + * - encoding: unused + * - decoding: set by user, will be converted to upper case by lavc during init + */ + unsigned int stream_codec_tag; + + /** + * scene change detection threshold. + * 0 is default, larger means fewer detected scene changes + * - encoding: set by user. + * - decoding: unused + */ + int scenechange_threshold; +} AVCodecContext; + + +/** + * AVOption. + */ +typedef struct AVOption { + /** options' name */ + const char *name; /* if name is NULL, it indicates a link to next */ + /** short English text help or const struct AVOption* subpointer */ + const char *help; // const struct AVOption* sub; + /** offset to context structure where the parsed value should be stored */ + int offset; + /** options' type */ + int type; +#define FF_OPT_TYPE_BOOL 1 ///< boolean - true,1,on (or simply presence) +#define FF_OPT_TYPE_DOUBLE 2 ///< double +#define FF_OPT_TYPE_INT 3 ///< integer +#define FF_OPT_TYPE_STRING 4 ///< string (finished with \0) +#define FF_OPT_TYPE_MASK 0x1f ///< mask for types - upper bits are various flags +//#define FF_OPT_TYPE_EXPERT 0x20 // flag for expert option +#define FF_OPT_TYPE_FLAG (FF_OPT_TYPE_BOOL | 0x40) +#define FF_OPT_TYPE_RCOVERRIDE (FF_OPT_TYPE_STRING | 0x80) + /** min value (min == max -> no limits) */ + double min; + /** maximum value for double/int */ + double max; + /** default boo [0,1]l/double/int value */ + double defval; + /** + * default string value (with optional semicolon delimited extra option-list + * i.e. option1;option2;option3 + * defval might select other then first argument as default + */ + const char *defstr; +#define FF_OPT_MAX_DEPTH 10 +} AVOption; + +/** + * Parse option(s) and sets fields in passed structure + * @param strct structure where the parsed results will be written + * @param list list with AVOptions + * @param opts string with options for parsing + */ +int avoption_parse(void* strct, const AVOption* list, const char* opts); + + +/** + * AVCodec. + */ +typedef struct AVCodec { + const char *name; + enum CodecType type; + int id; + int priv_data_size; + int (*init)(AVCodecContext *); + int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data); + int (*close)(AVCodecContext *); + int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, + uint8_t *buf, int buf_size); + int capabilities; + const AVOption *options; + struct AVCodec *next; + void (*flush)(AVCodecContext *); +} AVCodec; + +/** + * four components are given, that's all. + * the last component is alpha + */ +typedef struct AVPicture { + uint8_t *data[4]; + int linesize[4]; ///< number of bytes per line +} AVPicture; + +/** + * AVPaletteControl + * This structure defines a method for communicating palette changes + * between and demuxer and a decoder. + */ +typedef struct AVPaletteControl { + + /* demuxer sets this to 1 to indicate the palette has changed; + * decoder resets to 0 */ + int palette_changed; + + /* 256 3-byte RGB palette entries; the components should be + * formatted in the buffer as "RGBRGB..." and should be scaled to + * 8 bits if they originally represented 6-bit VGA palette + * components */ + unsigned char palette[256 * 3]; + +} AVPaletteControl; + +extern AVCodec ac3_encoder; +extern AVCodec mp2_encoder; +extern AVCodec mp3lame_encoder; +extern AVCodec oggvorbis_encoder; +extern AVCodec mpeg1video_encoder; +extern AVCodec mpeg2video_encoder; +extern AVCodec h263_encoder; +extern AVCodec h263p_encoder; +extern AVCodec flv_encoder; +extern AVCodec rv10_encoder; +extern AVCodec mjpeg_encoder; +extern AVCodec ljpeg_encoder; +extern AVCodec mpeg4_encoder; +extern AVCodec msmpeg4v1_encoder; +extern AVCodec msmpeg4v2_encoder; +extern AVCodec msmpeg4v3_encoder; +extern AVCodec wmv1_encoder; +extern AVCodec wmv2_encoder; +extern AVCodec huffyuv_encoder; +extern AVCodec h264_encoder; +extern AVCodec asv1_encoder; +extern AVCodec asv2_encoder; +extern AVCodec vcr1_encoder; +extern AVCodec ffv1_encoder; +extern AVCodec mdec_encoder; + +extern AVCodec h263_decoder; +extern AVCodec mpeg4_decoder; +extern AVCodec msmpeg4v1_decoder; +extern AVCodec msmpeg4v2_decoder; +extern AVCodec msmpeg4v3_decoder; +extern AVCodec wmv1_decoder; +extern AVCodec wmv2_decoder; +extern AVCodec mpeg1video_decoder; +extern AVCodec mpeg2video_decoder; +extern AVCodec mpeg_xvmc_decoder; +extern AVCodec h263i_decoder; +extern AVCodec flv_decoder; +extern AVCodec rv10_decoder; +extern AVCodec svq1_decoder; +extern AVCodec svq3_decoder; +extern AVCodec dvvideo_decoder; +extern AVCodec dvaudio_decoder; +extern AVCodec wmav1_decoder; +extern AVCodec wmav2_decoder; +extern AVCodec mjpeg_decoder; +extern AVCodec mjpegb_decoder; +extern AVCodec mp2_decoder; +extern AVCodec mp3_decoder; +extern AVCodec mace3_decoder; +extern AVCodec mace6_decoder; +extern AVCodec huffyuv_decoder; +extern AVCodec oggvorbis_decoder; +extern AVCodec cyuv_decoder; +extern AVCodec h264_decoder; +extern AVCodec indeo3_decoder; +extern AVCodec vp3_decoder; +extern AVCodec amr_nb_decoder; +extern AVCodec amr_nb_encoder; +extern AVCodec aac_decoder; +extern AVCodec mpeg4aac_decoder; +extern AVCodec asv1_decoder; +extern AVCodec asv2_decoder; +extern AVCodec vcr1_decoder; +extern AVCodec cljr_decoder; +extern AVCodec ffv1_decoder; +extern AVCodec fourxm_decoder; +extern AVCodec mdec_decoder; +extern AVCodec roq_decoder; +extern AVCodec interplay_video_decoder; +extern AVCodec xan_wc3_decoder; +extern AVCodec ra_144_decoder; +extern AVCodec ra_288_decoder; +extern AVCodec roq_dpcm_decoder; +extern AVCodec interplay_dpcm_decoder; +extern AVCodec xan_dpcm_decoder; + +/* pcm codecs */ +#define PCM_CODEC(id, name) \ +extern AVCodec name ## _decoder; \ +extern AVCodec name ## _encoder + +PCM_CODEC(CODEC_ID_PCM_S16LE, pcm_s16le); +PCM_CODEC(CODEC_ID_PCM_S16BE, pcm_s16be); +PCM_CODEC(CODEC_ID_PCM_U16LE, pcm_u16le); +PCM_CODEC(CODEC_ID_PCM_U16BE, pcm_u16be); +PCM_CODEC(CODEC_ID_PCM_S8, pcm_s8); +PCM_CODEC(CODEC_ID_PCM_U8, pcm_u8); +PCM_CODEC(CODEC_ID_PCM_ALAW, pcm_alaw); +PCM_CODEC(CODEC_ID_PCM_MULAW, pcm_mulaw); + +/* adpcm codecs */ + +PCM_CODEC(CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt); +PCM_CODEC(CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav); +PCM_CODEC(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3); +PCM_CODEC(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4); +PCM_CODEC(CODEC_ID_ADPCM_MS, adpcm_ms); +PCM_CODEC(CODEC_ID_ADPCM_4XM, adpcm_4xm); + +#undef PCM_CODEC + +/* dummy raw video codec */ +extern AVCodec rawvideo_encoder; +extern AVCodec rawvideo_decoder; + +/* the following codecs use external GPL libs */ +extern AVCodec ac3_decoder; + +/* resample.c */ + +struct ReSampleContext; + +typedef struct ReSampleContext ReSampleContext; + +ReSampleContext *audio_resample_init(int output_channels, int input_channels, + int output_rate, int input_rate); +int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); +void audio_resample_close(ReSampleContext *s); + +/* YUV420 format is assumed ! */ + +struct ImgReSampleContext; + +typedef struct ImgReSampleContext ImgReSampleContext; + +ImgReSampleContext *img_resample_init(int output_width, int output_height, + int input_width, int input_height); + +ImgReSampleContext *img_resample_full_init(int owidth, int oheight, + int iwidth, int iheight, + int topBand, int bottomBand, + int leftBand, int rightBand); + +void img_resample(ImgReSampleContext *s, + AVPicture *output, AVPicture *input); + +void img_resample_close(ImgReSampleContext *s); + +int avpicture_fill(AVPicture *picture, uint8_t *ptr, + int pix_fmt, int width, int height); +int avpicture_layout(AVPicture* src, int pix_fmt, int width, int height, + unsigned char *dest, int dest_size); +int avpicture_get_size(int pix_fmt, int width, int height); +void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift); +const char *avcodec_get_pix_fmt_name(int pix_fmt); +enum PixelFormat avcodec_get_pix_fmt(const char* name); + +#define FF_LOSS_RESOLUTION 0x0001 /* loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /* loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /* loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /* loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /* loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /* loss of chroma (e.g. rgb to gray conversion) */ + +int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt, + int has_alpha); +int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt, + int has_alpha, int *loss_ptr); + +#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */ +#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */ +int img_get_alpha_info(AVPicture *src, int pix_fmt, int width, int height); + +/* convert among pixel formats */ +int img_convert(AVPicture *dst, int dst_pix_fmt, + AVPicture *src, int pix_fmt, + int width, int height); + +/* deinterlace a picture */ +int avpicture_deinterlace(AVPicture *dst, AVPicture *src, + int pix_fmt, int width, int height); + +/* external high level API */ + +extern AVCodec *first_avcodec; + +/* returns LIBAVCODEC_VERSION_INT constant */ +unsigned avcodec_version(void); +/* returns LIBAVCODEC_BUILD constant */ +unsigned avcodec_build(void); +void avcodec_init(void); + +void register_avcodec(AVCodec *format); +AVCodec *avcodec_find_encoder(enum CodecID id); +AVCodec *avcodec_find_encoder_by_name(const char *name); +AVCodec *avcodec_find_decoder(enum CodecID id); +AVCodec *avcodec_find_decoder_by_name(const char *name); +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +void avcodec_get_context_defaults(AVCodecContext *s); +AVCodecContext *avcodec_alloc_context(void); +AVFrame *avcodec_alloc_frame(void); + +int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); +void avcodec_default_free_buffers(AVCodecContext *s); + +/** + * opens / inits the AVCodecContext. + * not thread save! + */ +int avcodec_open(AVCodecContext *avctx, AVCodec *codec); + +int avcodec_decode_audio(AVCodecContext *avctx, int16_t *samples, + int *frame_size_ptr, + uint8_t *buf, int buf_size); +int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + uint8_t *buf, int buf_size); +int avcodec_parse_frame(AVCodecContext *avctx, uint8_t **pdata, + int *data_size_ptr, + uint8_t *buf, int buf_size); +int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const short *samples); +int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict); + +int avcodec_close(AVCodecContext *avctx); + +void avcodec_register_all(void); + +void avcodec_flush_buffers(AVCodecContext *avctx); + +/* misc usefull functions */ + +/** + * returns a single letter to describe the picture type + */ +char av_get_pict_type_char(int pict_type); + +/** + * reduce a fraction. + * this is usefull for framerate calculations + * @param max the maximum allowed for dst_nom & dst_den + * @return 1 if exact, 0 otherwise + */ +int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max); + +/** + * rescale a 64bit integer. + * a simple a*b/c isnt possible as it can overflow + */ +int64_t av_rescale(int64_t a, int b, int c); + + +/** + * Interface for 0.5.0 version + * + * do not even think about it's usage for this moment + */ + +typedef struct { + /// compressed size used from given memory buffer + int size; + /// I/P/B frame type + int frame_type; +} avc_enc_result_t; + +/** + * Commands + * order can't be changed - once it was defined + */ +typedef enum { + // general commands + AVC_OPEN_BY_NAME = 0xACA000, + AVC_OPEN_BY_CODEC_ID, + AVC_OPEN_BY_FOURCC, + AVC_CLOSE, + + AVC_FLUSH, + // pin - struct { uint8_t* src, uint_t src_size } + // pout - struct { AVPicture* img, consumed_bytes, + AVC_DECODE, + // pin - struct { AVPicture* img, uint8_t* dest, uint_t dest_size } + // pout - uint_t used_from_dest_size + AVC_ENCODE, + + // query/get video commands + AVC_GET_VERSION = 0xACB000, + AVC_GET_WIDTH, + AVC_GET_HEIGHT, + AVC_GET_DELAY, + AVC_GET_QUANT_TABLE, + // ... + + // query/get audio commands + AVC_GET_FRAME_SIZE = 0xABC000, + + // maybe define some simple structure which + // might be passed to the user - but they can't + // contain any codec specific parts and these + // calls are usualy necessary only few times + + // set video commands + AVC_SET_WIDTH = 0xACD000, + AVC_SET_HEIGHT, + + // set video encoding commands + AVC_SET_FRAME_RATE = 0xACD800, + AVC_SET_QUALITY, + AVC_SET_HURRY_UP, + + // set audio commands + AVC_SET_SAMPLE_RATE = 0xACE000, + AVC_SET_CHANNELS, + +} avc_cmd_t; + +/** + * \param handle allocated private structure by libavcodec + * for initialization pass NULL - will be returned pout + * user is supposed to know nothing about its structure + * \param cmd type of operation to be performed + * \param pint input parameter + * \param pout output parameter + * + * \returns command status - eventually for query command it might return + * integer resulting value + */ +int avcodec(void* handle, avc_cmd_t cmd, void* pin, void* pout); + +/* memory */ +void *av_malloc(unsigned int size); +void *av_mallocz(unsigned int size); +void *av_realloc(void *ptr, unsigned int size); +void av_free(void *ptr); +char *av_strdup(const char *s); +void __av_freep(void **ptr); +#define av_freep(p) __av_freep((void **)(p)) +void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size); +/* for static data only */ +/* call av_free_static to release all staticaly allocated tables */ +void av_free_static(void); +void *__av_mallocz_static(void** location, unsigned int size); +#define av_mallocz_static(p, s) __av_mallocz_static((void **)(p), s) + +#ifdef __cplusplus +} +#endif + +#endif /* AVCODEC_H */ diff --git a/plugins/gs/GSsoft/Src/common.h b/plugins/gs/GSsoft/Src/common.h new file mode 100644 index 0000000..1f815f5 --- /dev/null +++ b/plugins/gs/GSsoft/Src/common.h @@ -0,0 +1,1142 @@ +/** + * @file common.h + * common internal api header. + */ + +#ifndef COMMON_H +#define COMMON_H + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +# define CONFIG_WIN32 +#endif + +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER + +#define ALT_BITSTREAM_READER +//#define LIBMPEG2_BITSTREAM_READER +//#define A32_BITSTREAM_READER +#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO + +#ifdef HAVE_AV_CONFIG_H +/* only include the following when compiling package */ +# include "config.h" + +# include +# include +# include +# include +# ifndef __BEOS__ +# include +# else +# include "berrno.h" +# endif +# include + +# ifndef ENODATA +# define ENODATA 61 +# endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include +#ifndef offsetof +# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F)) +#endif + +#define AVOPTION_CODEC_BOOL(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_BOOL } +#define AVOPTION_CODEC_DOUBLE(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_DOUBLE, minv, maxv, defval } +#define AVOPTION_CODEC_FLAG(name, help, field, flag, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_FLAG, flag, 0, defval } +#define AVOPTION_CODEC_INT(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_INT, minv, maxv, defval } +#define AVOPTION_CODEC_STRING(name, help, field, str, val) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_STRING, .defval = val, .defstr = str } +#define AVOPTION_CODEC_RCOVERRIDE(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_RCOVERRIDE, .defval = 0, .defstr = NULL } +#define AVOPTION_SUB(ptr) { .name = NULL, .help = (const char*)ptr } +#define AVOPTION_END() AVOPTION_SUB(NULL) + +struct AVOption; +#ifdef HAVE_MMX +extern const struct AVOption avoptions_common[3 + 5]; +#else +extern const struct AVOption avoptions_common[3]; +#endif +extern const struct AVOption avoptions_workaround_bug[11]; + +#endif /* HAVE_AV_CONFIG_H */ + +/* Suppress restrict if it was not defined in config.h. */ +#ifndef restrict +# define restrict +#endif + +#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define always_inline __attribute__((always_inline)) inline +#else +# define always_inline inline +#endif + +#ifdef CONFIG_WIN32 + +/* windows */ + +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +typedef signed char int8_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + +# ifndef __MINGW32__ +# define int64_t_C(c) (c ## i64) +# define uint64_t_C(c) (c ## i64) + +# define inline __inline + +# else +# define int64_t_C(c) (c ## LL) +# define uint64_t_C(c) (c ## ULL) +# endif /* __MINGW32__ */ + +# ifdef _DEBUG +# define DEBUG +# endif + +# define snprintf _snprintf +# define vsnprintf _vsnprintf + +/* CONFIG_WIN32 end */ +#elif defined (CONFIG_OS2) +/* OS/2 EMX */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +#include + +#endif /* HAVE_AV_CONFIG_H */ + +/* CONFIG_OS2 end */ +#else + +/* unix */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +# ifdef USE_FASTMEMCPY +# include "fastmemcpy.h" +# endif +# endif /* HAVE_AV_CONFIG_H */ + +#endif /* !CONFIG_WIN32 && !CONFIG_OS2 */ + +#ifdef HAVE_AV_CONFIG_H + +# include "bswap.h" + +# if defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# define MANGLE(a) "_" #a +# else +# define MANGLE(a) #a +# endif + +/* debug stuff */ + +# ifndef DEBUG +# define NDEBUG +# endif +# include + +/* dprintf macros */ +# if defined(CONFIG_WIN32) && !defined(__MINGW32__) + +inline void dprintf(const char* fmt,...) {} + +# else + +# ifdef DEBUG +# define dprintf(fmt,args...) printf(fmt, ## args) +# else +# define dprintf(fmt,args...) +# endif + +# endif /* !CONFIG_WIN32 */ + +# define av_abort() do { fprintf(stderr, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0) + +//rounded divison & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +extern const uint32_t inverse[256]; + +#ifdef ARCH_X86 +# define FASTDIV(a,b) \ + ({\ + int ret,dmy;\ + asm volatile(\ + "mull %3"\ + :"=d"(ret),"=a"(dmy)\ + :"1"(a),"g"(inverse[b])\ + );\ + ret;\ + }) +#elif defined(CONFIG_FASTDIV) +# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*inverse[b])>>32)) +#else +# define FASTDIV(a,b) ((a)/(b)) +#endif + +#ifdef ARCH_X86 +// avoid +32 for shift optimization (gcc should do that ...) +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + asm ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + asm ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +#else +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +/* bit output */ + +struct PutBitContext; + +typedef void (*WriteDataFunc)(void *, uint8_t *, int); + +typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + uint8_t *buf, *buf_end; + int index; +#else + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; +#endif + int64_t data_out_size; /* in bytes */ +} PutBitContext; + +void init_put_bits(PutBitContext *s, + uint8_t *buffer, int buffer_size, + void *opaque, + void (*write_data)(void *, uint8_t *, int)); + +int64_t get_bit_count(PutBitContext *s); /* XXX: change function name */ +void align_put_bits(PutBitContext *s); +void flush_put_bits(PutBitContext *s); +void put_string(PutBitContext * pbc, char *s); + +/* bit input */ + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; +#ifdef ALT_BITSTREAM_READER + int index; +#elif defined LIBMPEG2_BITSTREAM_READER + uint8_t *buffer_ptr; + uint32_t cache; + int bit_count; +#elif defined A32_BITSTREAM_READER + uint32_t *buffer_ptr; + uint32_t cache0; + uint32_t cache1; + int bit_count; +#endif + int size_in_bits; +} GetBitContext; + +static inline int get_bits_count(GetBitContext *s); + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +#ifdef ARCH_SPARC64 +#define UNALIGNED_STORES_ARE_BAD +#endif + +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#ifdef ARCH_X86 +# define unaligned32(a) (*(uint32_t*)(a)) +#else +# ifdef __GNUC__ +static inline uint32_t unaligned32(const void *v) { + struct Unaligned { + uint32_t i; + } __attribute__((packed)); + + return ((const struct Unaligned *) v)->i; +} +# elif defined(__DECC) +static inline uint32_t unaligned32(const void *v) { + return *(const __unaligned uint32_t *) v; +} +# else +static inline uint32_t unaligned32(const void *v) { + return *(const uint32_t *) v; +} +# endif +#endif //!ARCH_X86 + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + +#ifdef STATS + st_out_bit_counts[st_current_index] += n; +#endif + // printf("put_bits=%d %x\n", n, value); + assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<> (n - bit_left); +#ifdef UNALIGNED_STORES_ARE_BAD + if (3 & (int) s->buf_ptr) { + s->buf_ptr[0] = bit_buf >> 24; + s->buf_ptr[1] = bit_buf >> 16; + s->buf_ptr[2] = bit_buf >> 8; + s->buf_ptr[3] = bit_buf ; + } else +#endif + *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); + //printf("bitbuf = %08x\n", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +# ifdef ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# else //ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + +/* Bitstream reader API docs: +name + abritary name which is used as prefix for the internal variables + +gb + getbitcontext + +OPEN_READER(name, gb) + loads gb into local variables + +CLOSE_READER(name, gb) + stores local vars in gb + +UPDATE_CACHE(name, gb) + refills the internal cache from the bitstream + after this call at least MIN_CACHE_BITS will be available, + +GET_CACHE(name, gb) + will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) + +SHOW_UBITS(name, gb, num) + will return the nest num bits + +SHOW_SBITS(name, gb, num) + will return the nest num bits and do sign extension + +SKIP_BITS(name, gb, num) + will skip over the next num bits + note, this is equinvalent to SKIP_CACHE; SKIP_COUNTER + +SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) + +SKIP_COUNTER(name, gb, num) + will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) + +LAST_SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing + +LAST_SKIP_BITS(name, gb, num) + is equinvalent to SKIP_LAST_CACHE; SKIP_COUNTER + +for examples see get_bits, show_bits, skip_bits, get_vlc +*/ + +static inline int unaligned32_be(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); +#else + return be2me_32( unaligned32(v)); //original +#endif +} + +#ifdef ALT_BITSTREAM_READER +# define MIN_CACHE_BITS 25 + +# define OPEN_READER(name, gb)\ + int name##_index= (gb)->index;\ + int name##_cache= 0;\ + +# define CLOSE_READER(name, gb)\ + (gb)->index= name##_index;\ + +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_be( ((uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +// FIXME name? +# define SKIP_COUNTER(name, gb, num)\ + name##_index += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) ; + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return s->index; +} +#elif defined LIBMPEG2_BITSTREAM_READER +//libmpeg2 like reader + +# define MIN_CACHE_BITS 17 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + int name##_cache= (gb)->cache;\ + uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache= name##_cache;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +#ifdef LIBMPEG2_BITSTREAM_READER_HACK + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ + ((uint16_t*)name##_buffer_ptr)++;\ + name##_bit_count-= 16;\ + }\ + +#else + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ + name##_buffer_ptr+=2;\ + name##_bit_count-= 16;\ + }\ + +#endif + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +# define SKIP_COUNTER(name, gb, num)\ + name##_bit_count += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; +} + +#elif defined A32_BITSTREAM_READER + +# define MIN_CACHE_BITS 32 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + uint32_t name##_cache0= (gb)->cache0;\ + uint32_t name##_cache1= (gb)->cache1;\ + uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache0= name##_cache0;\ + (gb)->cache1= name##_cache1;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count > 0){\ + const uint32_t next= be2me_32( *name##_buffer_ptr );\ + name##_cache0 |= NEG_USR32(next,name##_bit_count);\ + name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; +} + +#endif + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + * @author BERO + */ +static inline int get_xbits(GetBitContext *s, int n){ + register int tmp; + register int32_t cache; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + cache = GET_CACHE(re,s); + if ((int32_t)cache<0) { //MSB=1 + tmp = NEG_USR32(cache,n); + } else { + // tmp = (-1<index+=n for the ALT_READER :)) + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +} + +static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + + return result; +#else + return get_bits(s, 1); +#endif +} + +static inline unsigned int show_bits1(GetBitContext *s){ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s){ + skip_bits(s, 1); +} + +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int buffer_size); + +int check_marker(GetBitContext *s, const char *msg); +void align_get_bits(GetBitContext *s); +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size); +void free_vlc(VLC *vlc); + +/** + * + * if the vlc code is invalid and max_depth=1 than no bits will be removed + * if the vlc code is invalid and max_depth>1 than the number of bits removed + * is undefined + */ +#define GET_VLC(code, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + code = table[index][0];\ + n = table[index][1];\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + if(max_depth > 2 && n < 0){\ + LAST_SKIP_BITS(name, gb, nb_bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + }\ + }\ + SKIP_BITS(name, gb, n)\ +} + +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + level = table[index].level;\ + n = table[index].len;\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + level;\ + level = table[index].level;\ + n = table[index].len;\ + }\ + run= table[index].run;\ + SKIP_BITS(name, gb, n)\ +} + +// deprecated, dont use get_vlc for new code, use get_vlc2 instead or use GET_VLC directly +static inline int get_vlc(GetBitContext *s, VLC *vlc) +{ + int code; + VLC_TYPE (*table)[2]= vlc->table; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, vlc->bits, 3) + + CLOSE_READER(re, s) + return code; +} + +/** + * parses a vlc code, faster then get_vlc() + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be readed to completly + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, bits, max_depth) + + CLOSE_READER(re, s) + return code; +} + +//#define TRACE + +#ifdef TRACE + +static inline void print_bin(int bits, int n){ + int i; + + for(i=n-1; i>=0; i--){ + printf("%d", (bits>>i)&1); + } + for(i=n; i<24; i++) + printf(" "); +} + +static inline int get_bits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int r= get_bits(s, n); + + print_bin(r, n); + printf("%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line); + return r; +} +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int r= get_vlc2(s, table, bits, max_depth); + int len= get_bits_count(s) - pos; + int bits2= show>>(24-len); + + print_bin(bits2, len); + + printf("%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line); + return r; +} +static inline int get_xbits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int show= show_bits(s, n); + int r= get_xbits(s, n); + + print_bin(show, n); + printf("%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line); + return r; +} + +#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf printf + +#else //TRACE +#define tprintf(_arg...) {} +#endif + +/* define it to include statistics code (useful only for optimizing + codec efficiency */ +//#define STATS + +#ifdef STATS + +enum { + ST_UNKNOWN, + ST_DC, + ST_INTRA_AC, + ST_INTER_AC, + ST_INTRA_MB, + ST_INTER_MB, + ST_MV, + ST_NB, +}; + +extern int st_current_index; +extern unsigned int st_bit_counts[ST_NB]; +extern unsigned int st_out_bit_counts[ST_NB]; + +void print_stats(void); +#endif + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +static inline int av_log2(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline int av_log2_16bit(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + + +/* median of 3 */ +static inline int mid_pred(int a, int b, int c) +{ + int vmin, vmax; + vmax = vmin = a; + if (b < vmin) + vmin = b; + else + vmax = b; + + if (c < vmin) + vmin = c; + else if (c > vmax) + vmax = c; + + return a + b + c - vmin - vmax; +} + +static inline int clip(int a, int amin, int amax) +{ + if (a < amin) + return amin; + else if (a > amax) + return amax; + else + return a; +} + +/* math */ +extern const uint8_t ff_sqrt_tab[128]; + +int64_t ff_gcd(int64_t a, int64_t b); + +static inline int ff_sqrt(int a) +{ + int ret=0; + int s; + int ret_sq=0; + + if(a<128) return ff_sqrt_tab[a]; + + for(s=15; s>=0; s--){ + int b= ret_sq + (1<<(s*2)) + (ret<>31;\ + level= (level^mask)-mask; +#endif + + +#if __CPU__ >= 686 && !defined(RUNTIME_CPUDETECT) +#define COPY3_IF_LT(x,y,a,b,c,d)\ +asm volatile (\ + "cmpl %0, %3 \n\t"\ + "cmovl %3, %0 \n\t"\ + "cmovl %4, %1 \n\t"\ + "cmovl %5, %2 \n\t"\ + : "+r" (x), "+r" (a), "+r" (c)\ + : "r" (y), "r" (b), "r" (d)\ +); +#else +#define COPY3_IF_LT(x,y,a,b,c,d)\ +if((y)<(x)){\ + (x)=(y);\ + (a)=(b);\ + (c)=(d);\ +} +#endif + +#ifdef ARCH_X86 +static inline long long rdtsc() +{ + long long l; + asm volatile( "rdtsc\n\t" + : "=A" (l) + ); + return l; +} + +#define START_TIMER \ +static uint64_t tsum=0;\ +static int tcount=0;\ +static int tskip_count=0;\ +uint64_t tend;\ +uint64_t tstart= rdtsc();\ + +#define STOP_TIMER(id) \ +tend= rdtsc();\ +if(tcount<2 || tend - tstart < 4*tsum/tcount){\ + tsum+= tend - tstart;\ + tcount++;\ +}else\ + tskip_count++;\ +if(256*256*256*64%(tcount+tskip_count)==0){\ + fprintf(stderr, "%Ld dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\ +} +#endif + +#define CLAMP_TO_8BIT(d) ((d > 0xff) ? 0xff : (d < 0) ? 0 : d) + +/* avoid usage of various functions */ +#define malloc please_use_av_malloc +#define free please_use_av_free +#define realloc please_use_av_realloc + +#define CHECKED_ALLOCZ(p, size)\ +{\ + p= av_mallocz(size);\ + if(p==NULL && (size)!=0){\ + perror("malloc");\ + goto fail;\ + }\ +} + +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* COMMON_H */ diff --git a/plugins/gs/GSsoft/Src/ffmpeg/avformat.h b/plugins/gs/GSsoft/Src/ffmpeg/avformat.h new file mode 100644 index 0000000..6fb7cec --- /dev/null +++ b/plugins/gs/GSsoft/Src/ffmpeg/avformat.h @@ -0,0 +1,544 @@ +#ifndef AVFORMAT_H +#define AVFORMAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBAVFORMAT_BUILD 4608 + +#define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT +#define LIBAVFORMAT_VERSION FFMPEG_VERSION +#define LIBAVFORMAT_IDENT "FFmpeg" FFMPEG_VERSION "b" AV_STRINGIFY(LIBAVFORMAT_BUILD) + +#include + +#include "avcodec.h" + +#include "avio.h" + +/* packet functions */ + +#ifndef MAXINT64 +#define MAXINT64 int64_t_C(0x7fffffffffffffff) +#endif + +#ifndef MININT64 +#define MININT64 int64_t_C(0x8000000000000000) +#endif + +#define AV_NOPTS_VALUE MININT64 +#define AV_TIME_BASE 1000000 + +typedef struct AVPacket { + int64_t pts; /* presentation time stamp in stream units (set av_set_pts_info) */ + uint8_t *data; + int size; + int stream_index; + int flags; + int duration; + void (*destruct)(struct AVPacket *); + void *priv; +} AVPacket; +#define PKT_FLAG_KEY 0x0001 + +static inline void av_init_packet(AVPacket *pkt) +{ + pkt->pts = AV_NOPTS_VALUE; + pkt->flags = 0; + pkt->stream_index = 0; +} + +int av_new_packet(AVPacket *pkt, int size); + +/** + * Free a packet + * + * @param pkt packet to free + */ +static inline void av_free_packet(AVPacket *pkt) +{ + if (pkt && pkt->destruct) { + pkt->destruct(pkt); + } +} + +/*************************************************/ +/* fractional numbers for exact pts handling */ + +/* the exact value of the fractional number is: 'val + num / den'. num + is assumed to be such as 0 <= num < den */ +typedef struct AVFrac { + int64_t val, num, den; +} AVFrac; + +void av_frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den); +void av_frac_add(AVFrac *f, int64_t incr); +void av_frac_set(AVFrac *f, int64_t val); + +/*************************************************/ +/* input/output formats */ + +struct AVFormatContext; + +/* this structure contains the data a format has to probe a file */ +typedef struct AVProbeData { + const char *filename; + unsigned char *buf; + int buf_size; +} AVProbeData; + +#define AVPROBE_SCORE_MAX 100 + +typedef struct AVFormatParameters { + int frame_rate; + int frame_rate_base; + int sample_rate; + int channels; + int width; + int height; + enum PixelFormat pix_fmt; + struct AVImageFormat *image_format; + int channel; /* used to select dv channel */ + const char *device; /* video4linux, audio or DV device */ + const char *standard; /* tv standard, NTSC, PAL, SECAM */ +} AVFormatParameters; + +#define AVFMT_NOFILE 0x0001 /* no file should be opened */ +#define AVFMT_NEEDNUMBER 0x0002 /* needs '%d' in filename */ +#define AVFMT_NOHEADER 0x0004 /* signal that no header is present + (streams are added dynamically) */ +#define AVFMT_SHOW_IDS 0x0008 /* show format stream IDs numbers */ +#define AVFMT_RAWPICTURE 0x0020 /* format wants AVPicture structure for + raw picture data */ + +typedef struct AVOutputFormat { + const char *name; + const char *long_name; + const char *mime_type; + const char *extensions; /* comma separated extensions */ + /* size of private data so that it can be allocated in the wrapper */ + int priv_data_size; + /* output support */ + enum CodecID audio_codec; /* default audio codec */ + enum CodecID video_codec; /* default video codec */ + int (*write_header)(struct AVFormatContext *); + int (*write_packet)(struct AVFormatContext *, + int stream_index, + const uint8_t *buf, int size, int64_t pts); + int (*write_trailer)(struct AVFormatContext *); + /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER */ + int flags; + /* currently only used to set pixel format if not YUV420P */ + int (*set_parameters)(struct AVFormatContext *, AVFormatParameters *); + /* private fields */ + struct AVOutputFormat *next; +} AVOutputFormat; + +typedef struct AVInputFormat { + const char *name; + const char *long_name; + /* size of private data so that it can be allocated in the wrapper */ + int priv_data_size; + /* tell if a given file has a chance of being parsing by this format */ + int (*read_probe)(AVProbeData *); + /* read the format header and initialize the AVFormatContext + structure. Return 0 if OK. 'ap' if non NULL contains + additionnal paramters. Only used in raw format right + now. 'av_new_stream' should be called to create new streams. */ + int (*read_header)(struct AVFormatContext *, + AVFormatParameters *ap); + /* read one packet and put it in 'pkt'. pts and flags are also + set. 'av_new_stream' can be called only if the flag + AVFMT_NOHEADER is used. */ + int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); + /* close the stream. The AVFormatContext and AVStreams are not + freed by this function */ + int (*read_close)(struct AVFormatContext *); + /* seek at or before a given pts (given in microsecond). The pts + origin is defined by the stream */ + int (*read_seek)(struct AVFormatContext *, int64_t pts); + /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_NOHEADER */ + int flags; + /* if extensions are defined, then no probe is done. You should + usually not use extension format guessing because it is not + reliable enough */ + const char *extensions; + /* general purpose read only value that the format can use */ + int value; + /* private fields */ + struct AVInputFormat *next; +} AVInputFormat; + +typedef struct AVStream { + int index; /* stream index in AVFormatContext */ + int id; /* format specific stream id */ + AVCodecContext codec; /* codec context */ + int r_frame_rate; /* real frame rate of the stream */ + int r_frame_rate_base;/* real frame rate base of the stream */ + void *priv_data; + /* internal data used in av_find_stream_info() */ + int codec_info_state; + int codec_info_nb_repeat_frames; + int codec_info_nb_real_frames; + /* PTS generation when outputing stream */ + AVFrac pts; + /* ffmpeg.c private use */ + int stream_copy; /* if TRUE, just copy stream */ + /* quality, as it has been removed from AVCodecContext and put in AVVideoFrame + * MN:dunno if thats the right place, for it */ + float quality; + /* decoding: position of the first frame of the component, in + AV_TIME_BASE fractional seconds. */ + int64_t start_time; + /* decoding: duration of the stream, in AV_TIME_BASE fractional + seconds. */ + int64_t duration; +} AVStream; + +#define MAX_STREAMS 20 + +/* format I/O context */ +typedef struct AVFormatContext { + /* can only be iformat or oformat, not both at the same time */ + struct AVInputFormat *iformat; + struct AVOutputFormat *oformat; + void *priv_data; + ByteIOContext pb; + int nb_streams; + AVStream *streams[MAX_STREAMS]; + char filename[1024]; /* input or output filename */ + /* stream info */ + char title[512]; + char author[512]; + char copyright[512]; + char comment[512]; + char album[512]; + int year; /* ID3 year, 0 if none */ + int track; /* track number, 0 if none */ + char genre[32]; /* ID3 genre */ + + int flags; /* format specific flags */ + /* private data for pts handling (do not modify directly) */ + int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */ + int pts_num, pts_den; /* value to convert to seconds */ + /* This buffer is only needed when packets were already buffered but + not decoded, for example to get the codec parameters in mpeg + streams */ + struct AVPacketList *packet_buffer; + + /* decoding: position of the first frame of the component, in + AV_TIME_BASE fractional seconds. NEVER set this value directly: + it is deduced from the AVStream values. */ + int64_t start_time; + /* decoding: duration of the stream, in AV_TIME_BASE fractional + seconds. NEVER set this value directly: it is deduced from the + AVStream values. */ + int64_t duration; + /* decoding: total file size. 0 if unknown */ + int64_t file_size; + /* decoding: total stream bitrate in bit/s, 0 if not + available. Never set it directly if the file_size and the + duration are known as ffmpeg can compute it automatically. */ + int bit_rate; +} AVFormatContext; + +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; + +extern AVInputFormat *first_iformat; +extern AVOutputFormat *first_oformat; + +/* still image support */ +struct AVInputImageContext; +typedef struct AVInputImageContext AVInputImageContext; + +typedef struct AVImageInfo { + enum PixelFormat pix_fmt; /* requested pixel format */ + int width; /* requested width */ + int height; /* requested height */ + int interleaved; /* image is interleaved (e.g. interleaved GIF) */ + AVPicture pict; /* returned allocated image */ +} AVImageInfo; + +/* AVImageFormat.flags field constants */ +#define AVIMAGE_INTERLEAVED 0x0001 /* image format support interleaved output */ + +typedef struct AVImageFormat { + const char *name; + const char *extensions; + /* tell if a given file has a chance of being parsing by this format */ + int (*img_probe)(AVProbeData *); + /* read a whole image. 'alloc_cb' is called when the image size is + known so that the caller can allocate the image. If 'allo_cb' + returns non zero, then the parsing is aborted. Return '0' if + OK. */ + int (*img_read)(ByteIOContext *, + int (*alloc_cb)(void *, AVImageInfo *info), void *); + /* write the image */ + int supported_pixel_formats; /* mask of supported formats for output */ + int (*img_write)(ByteIOContext *, AVImageInfo *); + int flags; + struct AVImageFormat *next; +} AVImageFormat; + +void av_register_image_format(AVImageFormat *img_fmt); +AVImageFormat *av_probe_image_format(AVProbeData *pd); +AVImageFormat *guess_image_format(const char *filename); +int av_read_image(ByteIOContext *pb, const char *filename, + AVImageFormat *fmt, + int (*alloc_cb)(void *, AVImageInfo *info), void *opaque); +int av_write_image(ByteIOContext *pb, AVImageFormat *fmt, AVImageInfo *img); + +extern AVImageFormat *first_image_format; + +extern AVImageFormat pnm_image_format; +extern AVImageFormat pbm_image_format; +extern AVImageFormat pgm_image_format; +extern AVImageFormat ppm_image_format; +extern AVImageFormat pam_image_format; +extern AVImageFormat pgmyuv_image_format; +extern AVImageFormat yuv_image_format; +#ifdef CONFIG_ZLIB +extern AVImageFormat png_image_format; +#endif +extern AVImageFormat jpeg_image_format; +extern AVImageFormat gif_image_format; + +/* XXX: use automatic init with either ELF sections or C file parser */ +/* modules */ + +/* mpeg.c */ +extern AVInputFormat mpegps_demux; +int mpegps_init(void); + +/* mpegts.c */ +extern AVInputFormat mpegts_demux; +int mpegts_init(void); + +/* rm.c */ +int rm_init(void); + +/* crc.c */ +int crc_init(void); + +/* img.c */ +int img_init(void); + +/* asf.c */ +int asf_init(void); + +/* avienc.c */ +int avienc_init(void); + +/* avidec.c */ +int avidec_init(void); + +/* swf.c */ +int swf_init(void); + +/* mov.c */ +int mov_init(void); + +/* movenc.c */ +int movenc_init(void); + +/* flvenc.c */ +int flvenc_init(void); + +/* flvdec.c */ +int flvdec_init(void); + +/* jpeg.c */ +int jpeg_init(void); + +/* gif.c */ +int gif_init(void); + +/* au.c */ +int au_init(void); + +/* amr.c */ +int amr_init(void); + +/* wav.c */ +int wav_init(void); + +/* raw.c */ +int raw_init(void); + +/* mp3.c */ +int mp3_init(void); + +/* yuv4mpeg.c */ +int yuv4mpeg_init(void); + +/* ogg.c */ +int ogg_init(void); + +/* dv.c */ +int dv_init(void); + +/* ffm.c */ +int ffm_init(void); + +/* rtsp.c */ +extern AVInputFormat redir_demux; +int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f); + +/* 4xm.c */ +int fourxm_init(void); + +/* psxstr.c */ +int str_init(void); + +/* idroq.c */ +int roq_init(void); + +/* ipmovie.c */ +int ipmovie_init(void); + +/* nut.c */ +int nut_init(void); + +/* wc3movie.c */ +int wc3_init(void); + +#include "rtp.h" + +#include "rtsp.h" + +/* yuv4mpeg.c */ +extern AVOutputFormat yuv4mpegpipe_oformat; + +/* utils.c */ +void av_register_input_format(AVInputFormat *format); +void av_register_output_format(AVOutputFormat *format); +AVOutputFormat *guess_stream_format(const char *short_name, + const char *filename, const char *mime_type); +AVOutputFormat *guess_format(const char *short_name, + const char *filename, const char *mime_type); + +void av_hex_dump(uint8_t *buf, int size); + +void av_register_all(void); + +typedef struct FifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; +} FifoBuffer; + +int fifo_init(FifoBuffer *f, int size); +void fifo_free(FifoBuffer *f); +int fifo_size(FifoBuffer *f, uint8_t *rptr); +int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr); +void fifo_write(FifoBuffer *f, uint8_t *buf, int size, uint8_t **wptr_ptr); + +/* media file input */ +AVInputFormat *av_find_input_format(const char *short_name); +AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); +int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, + AVInputFormat *fmt, + int buf_size, + AVFormatParameters *ap); + +#define AVERROR_UNKNOWN (-1) /* unknown error */ +#define AVERROR_IO (-2) /* i/o error */ +#define AVERROR_NUMEXPECTED (-3) /* number syntax expected in filename */ +#define AVERROR_INVALIDDATA (-4) /* invalid data found */ +#define AVERROR_NOMEM (-5) /* not enough memory */ +#define AVERROR_NOFMT (-6) /* unknown format */ + +int av_find_stream_info(AVFormatContext *ic); +int av_read_packet(AVFormatContext *s, AVPacket *pkt); +void av_close_input_file(AVFormatContext *s); +AVStream *av_new_stream(AVFormatContext *s, int id); +void av_set_pts_info(AVFormatContext *s, int pts_wrap_bits, + int pts_num, int pts_den); + +/* media file output */ +int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap); +int av_write_header(AVFormatContext *s); +int av_write_frame(AVFormatContext *s, int stream_index, const uint8_t *buf, + int size); +int av_write_trailer(AVFormatContext *s); + +void dump_format(AVFormatContext *ic, + int index, + const char *url, + int is_output); +int parse_image_size(int *width_ptr, int *height_ptr, const char *str); +int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg); +int64_t parse_date(const char *datestr, int duration); + +int64_t av_gettime(void); + +/* ffm specific for ffserver */ +#define FFM_PACKET_SIZE 4096 +offset_t ffm_read_write_index(int fd); +void ffm_write_write_index(int fd, offset_t pos); +void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size); + +int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info); + +int get_frame_filename(char *buf, int buf_size, + const char *path, int number); +int filename_number_test(const char *filename); + +/* grab specific */ +int video_grab_init(void); +int audio_init(void); + +/* DV1394 */ +int dv1394_init(void); + +#ifdef HAVE_AV_CONFIG_H + +#include "os_support.h" + +int strstart(const char *str, const char *val, const char **ptr); +int stristart(const char *str, const char *val, const char **ptr); +void pstrcpy(char *buf, int buf_size, const char *str); +char *pstrcat(char *buf, int buf_size, const char *s); + +void __dynarray_add(unsigned long **tab_ptr, int *nb_ptr, unsigned long elem); + +#ifdef __GNUC__ +#define dynarray_add(tab, nb_ptr, elem)\ +do {\ + typeof(tab) _tab = (tab);\ + typeof(elem) _elem = (elem);\ + (void)sizeof(**_tab == _elem); /* check that types are compatible */\ + __dynarray_add((unsigned long **)_tab, nb_ptr, (unsigned long)_elem);\ +} while(0) +#else +#define dynarray_add(tab, nb_ptr, elem)\ +do {\ + __dynarray_add((unsigned long **)(tab), nb_ptr, (unsigned long)(elem));\ +} while(0) +#endif + +time_t mktimegm(struct tm *tm); +const char *small_strptime(const char *p, const char *fmt, + struct tm *dt); + +struct in_addr; +int resolve_host(struct in_addr *sin_addr, const char *hostname); + +void url_split(char *proto, int proto_size, + char *hostname, int hostname_size, + int *port_ptr, + char *path, int path_size, + const char *url); + +int match_ext(const char *filename, const char *extensions); + +#endif /* HAVE_AV_CONFIG_H */ + +#ifdef __cplusplus +} +#endif + +#endif /* AVFORMAT_H */ diff --git a/plugins/gs/GSsoft/Src/ffmpeg/avio.h b/plugins/gs/GSsoft/Src/ffmpeg/avio.h new file mode 100644 index 0000000..952e8b6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/ffmpeg/avio.h @@ -0,0 +1,169 @@ +#ifndef AVIO_H +#define AVIO_H + +/* output byte stream handling */ + +typedef int64_t offset_t; + +/* unbuffered I/O */ + +struct URLContext { + struct URLProtocol *prot; + int flags; + int is_streamed; /* true if streamed (no seek possible), default = false */ + int max_packet_size; /* if non zero, the stream is packetized with this max packet size */ + void *priv_data; + char filename[1]; /* specified filename */ +}; + +typedef struct URLContext URLContext; + +typedef struct URLPollEntry { + URLContext *handle; + int events; + int revents; +} URLPollEntry; + +#define URL_RDONLY 0 +#define URL_WRONLY 1 +#define URL_RDWR 2 + +typedef int URLInterruptCB(void); + +int url_open(URLContext **h, const char *filename, int flags); +int url_read(URLContext *h, unsigned char *buf, int size); +int url_write(URLContext *h, unsigned char *buf, int size); +offset_t url_seek(URLContext *h, offset_t pos, int whence); +int url_close(URLContext *h); +int url_exist(const char *filename); +offset_t url_filesize(URLContext *h); +int url_get_max_packet_size(URLContext *h); +void url_get_filename(URLContext *h, char *buf, int buf_size); + +/* the callback is called in blocking functions to test regulary if + asynchronous interruption is needed. -EINTR is returned in this + case by the interrupted function. 'NULL' means no interrupt + callback is given. */ +void url_set_interrupt_cb(URLInterruptCB *interrupt_cb); + +/* not implemented */ +int url_poll(URLPollEntry *poll_table, int n, int timeout); + +typedef struct URLProtocol { + const char *name; + int (*url_open)(URLContext *h, const char *filename, int flags); + int (*url_read)(URLContext *h, unsigned char *buf, int size); + int (*url_write)(URLContext *h, unsigned char *buf, int size); + offset_t (*url_seek)(URLContext *h, offset_t pos, int whence); + int (*url_close)(URLContext *h); + struct URLProtocol *next; +} URLProtocol; + +extern URLProtocol *first_protocol; +extern URLInterruptCB *url_interrupt_cb; + +int register_protocol(URLProtocol *protocol); + +typedef struct { + unsigned char *buffer; + int buffer_size; + unsigned char *buf_ptr, *buf_end; + void *opaque; + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); + void (*write_packet)(void *opaque, uint8_t *buf, int buf_size); + int (*seek)(void *opaque, offset_t offset, int whence); + offset_t pos; /* position in the file of the current buffer */ + int must_flush; /* true if the next seek should flush */ + int eof_reached; /* true if eof reached */ + int write_flag; /* true if open for writing */ + int is_streamed; + int max_packet_size; +} ByteIOContext; + +int init_put_byte(ByteIOContext *s, + unsigned char *buffer, + int buffer_size, + int write_flag, + void *opaque, + int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), + void (*write_packet)(void *opaque, uint8_t *buf, int buf_size), + int (*seek)(void *opaque, offset_t offset, int whence)); + +void put_byte(ByteIOContext *s, int b); +void put_buffer(ByteIOContext *s, const unsigned char *buf, int size); +void put_le64(ByteIOContext *s, uint64_t val); +void put_be64(ByteIOContext *s, uint64_t val); +void put_le32(ByteIOContext *s, unsigned int val); +void put_be32(ByteIOContext *s, unsigned int val); +void put_le16(ByteIOContext *s, unsigned int val); +void put_be16(ByteIOContext *s, unsigned int val); +void put_tag(ByteIOContext *s, const char *tag); + +void put_be64_double(ByteIOContext *s, double val); +void put_strz(ByteIOContext *s, const char *buf); + +offset_t url_fseek(ByteIOContext *s, offset_t offset, int whence); +void url_fskip(ByteIOContext *s, offset_t offset); +offset_t url_ftell(ByteIOContext *s); +int url_feof(ByteIOContext *s); + +#define URL_EOF (-1) +int url_fgetc(ByteIOContext *s); +#ifdef __GNUC__ +int url_fprintf(ByteIOContext *s, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +#else +int url_fprintf(ByteIOContext *s, const char *fmt, ...); +#endif +char *url_fgets(ByteIOContext *s, char *buf, int buf_size); + +void put_flush_packet(ByteIOContext *s); + +int get_buffer(ByteIOContext *s, unsigned char *buf, int size); +int get_byte(ByteIOContext *s); +unsigned int get_le32(ByteIOContext *s); +uint64_t get_le64(ByteIOContext *s); +unsigned int get_le16(ByteIOContext *s); + +double get_be64_double(ByteIOContext *s); +char *get_strz(ByteIOContext *s, char *buf, int maxlen); +unsigned int get_be16(ByteIOContext *s); +unsigned int get_be32(ByteIOContext *s); +uint64_t get_be64(ByteIOContext *s); + +static inline int url_is_streamed(ByteIOContext *s) +{ + return s->is_streamed; +} + +int url_fdopen(ByteIOContext *s, URLContext *h); +int url_setbufsize(ByteIOContext *s, int buf_size); +int url_fopen(ByteIOContext *s, const char *filename, int flags); +int url_fclose(ByteIOContext *s); +URLContext *url_fileno(ByteIOContext *s); +int url_fget_max_packet_size(ByteIOContext *s); + +int url_open_buf(ByteIOContext *s, uint8_t *buf, int buf_size, int flags); +int url_close_buf(ByteIOContext *s); + +int url_open_dyn_buf(ByteIOContext *s); +int url_open_dyn_packet_buf(ByteIOContext *s, int max_packet_size); +int url_close_dyn_buf(ByteIOContext *s, uint8_t **pbuffer); + +/* file.c */ +extern URLProtocol file_protocol; +extern URLProtocol pipe_protocol; + +/* udp.c */ +extern URLProtocol udp_protocol; +int udp_set_remote_url(URLContext *h, const char *uri); +int udp_get_local_port(URLContext *h); +int udp_get_file_handle(URLContext *h); + +/* tcp.c */ +extern URLProtocol tcp_protocol; + +/* http.c */ +extern URLProtocol http_protocol; + +#endif + diff --git a/plugins/gs/GSsoft/Src/ffmpeg/rtp.h b/plugins/gs/GSsoft/Src/ffmpeg/rtp.h new file mode 100644 index 0000000..d488be2 --- /dev/null +++ b/plugins/gs/GSsoft/Src/ffmpeg/rtp.h @@ -0,0 +1,40 @@ +/* + * RTP definitions + * Copyright (c) 2002 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef RTP_H +#define RTP_H + +#define RTP_MIN_PACKET_LENGTH 12 +#define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */ + +int rtp_init(void); +int rtp_get_codec_info(AVCodecContext *codec, int payload_type); +int rtp_get_payload_type(AVCodecContext *codec); +int rtp_parse_packet(AVFormatContext *s1, AVPacket *pkt, + const unsigned char *buf, int len); + +extern AVOutputFormat rtp_mux; +extern AVInputFormat rtp_demux; + +int rtp_get_local_port(URLContext *h); +int rtp_set_remote_url(URLContext *h, const char *uri); +void rtp_get_file_handles(URLContext *h, int *prtp_fd, int *prtcp_fd); + +extern URLProtocol rtp_protocol; + +#endif /* RTP_H */ diff --git a/plugins/gs/GSsoft/Src/ffmpeg/rtsp.h b/plugins/gs/GSsoft/Src/ffmpeg/rtsp.h new file mode 100644 index 0000000..a92483c --- /dev/null +++ b/plugins/gs/GSsoft/Src/ffmpeg/rtsp.h @@ -0,0 +1,90 @@ +/* + * RTSP definitions + * Copyright (c) 2002 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef RTSP_H +#define RTSP_H + +/* RTSP handling */ +enum RTSPStatusCode { +#define DEF(n, c, s) c = n, +#include "rtspcodes.h" +#undef DEF +}; + +enum RTSPProtocol { + RTSP_PROTOCOL_RTP_UDP = 0, + RTSP_PROTOCOL_RTP_TCP = 1, + RTSP_PROTOCOL_RTP_UDP_MULTICAST = 2, +}; + +#define RTSP_DEFAULT_PORT 554 +#define RTSP_MAX_TRANSPORTS 8 +#define RTSP_TCP_MAX_PACKET_SIZE 1472 + +typedef struct RTSPTransportField { + int interleaved_min, interleaved_max; /* interleave ids, if TCP transport */ + int port_min, port_max; /* RTP ports */ + int client_port_min, client_port_max; /* RTP ports */ + int server_port_min, server_port_max; /* RTP ports */ + int ttl; /* ttl value */ + uint32_t destination; /* destination IP address */ + enum RTSPProtocol protocol; +} RTSPTransportField; + +typedef struct RTSPHeader { + int content_length; + enum RTSPStatusCode status_code; /* response code from server */ + int nb_transports; + RTSPTransportField transports[RTSP_MAX_TRANSPORTS]; + int seq; /* sequence number */ + char session_id[512]; +} RTSPHeader; + +/* the callback can be used to extend the connection setup/teardown step */ +enum RTSPCallbackAction { + RTSP_ACTION_SERVER_SETUP, + RTSP_ACTION_SERVER_TEARDOWN, + RTSP_ACTION_CLIENT_SETUP, + RTSP_ACTION_CLIENT_TEARDOWN, +}; + +typedef struct RTSPActionServerSetup { + uint32_t ipaddr; + char transport_option[512]; +} RTSPActionServerSetup; + +typedef int FFRTSPCallback(enum RTSPCallbackAction action, + const char *session_id, + char *buf, int buf_size, + void *arg); + +void rtsp_set_callback(FFRTSPCallback *rtsp_cb); + +int rtsp_init(void); +void rtsp_parse_line(RTSPHeader *reply, const char *buf); + +extern int rtsp_default_protocols; +extern int rtsp_rtp_port_min; +extern int rtsp_rtp_port_max; +extern FFRTSPCallback *ff_rtsp_callback; +extern AVInputFormat rtsp_demux; + +int rtsp_pause(AVFormatContext *s); +int rtsp_resume(AVFormatContext *s); + +#endif /* RTSP_H */ diff --git a/plugins/gs/GSsoft/Src/ffmpeg/rtspcodes.h b/plugins/gs/GSsoft/Src/ffmpeg/rtspcodes.h new file mode 100644 index 0000000..dbd2e51 --- /dev/null +++ b/plugins/gs/GSsoft/Src/ffmpeg/rtspcodes.h @@ -0,0 +1,11 @@ +DEF(200, RTSP_STATUS_OK, "OK") +DEF(405, RTSP_STATUS_METHOD, "Method Not Allowed") +DEF(453, RTSP_STATUS_BANDWIDTH, "Not Enough Bandwidth") +DEF(454, RTSP_STATUS_SESSION, "Session Not Found") +DEF(455, RTSP_STATUS_STATE, "Method Not Valid in This State") +DEF(459, RTSP_STATUS_AGGREGATE, "Aggregate operation not allowed") +DEF(460, RTSP_STATUS_ONLY_AGGREGATE, "Only aggregate operation allowed") +DEF(461, RTSP_STATUS_TRANSPORT, "Unsupported transport") +DEF(500, RTSP_STATUS_INTERNAL, "Internal Server Error") +DEF(503, RTSP_STATUS_SERVICE, "Service Unavailable") +DEF(505, RTSP_STATUS_VERSION, "RTSP Version not supported") diff --git a/plugins/gs/GSsoft/Src/scale2x.c b/plugins/gs/GSsoft/Src/scale2x.c new file mode 100644 index 0000000..7b6203b --- /dev/null +++ b/plugins/gs/GSsoft/Src/scale2x.c @@ -0,0 +1,141 @@ +/* + This implements the AdvanceMAME Scale2x feature found on this page, + http://scale2x.sourceforge.net/ + + It is an incredibly simple and powerful image doubling routine that does + an astonishing job of doubling game graphic data while interpolating out + the jaggies. Congrats to the AdvanceMAME team, I'm very impressed and + surprised with this code! +*/ + + + +#include +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +#define READINT24(x) ((x)[0]<<16 | (x)[1]<<8 | (x)[2]) +#define WRITEINT24(x, i) {(x)[0]=i>>16; (x)[1]=(i>>8)&0xff; x[2]=i&0xff; } + +/* + this requires a destination surface already setup to be twice as + large as the source. oh, and formats must match too. this will just + blindly assume you didn't flounder. +*/ + +void scale2x(SDL_Surface *src, SDL_Surface *dst) +{ + int looph, loopw; + + Uint8* srcpix = (Uint8*)src->pixels; + Uint8* dstpix = (Uint8*)dst->pixels; + + const int srcpitch = src->pitch; + const int dstpitch = dst->pitch; + const int width = src->w; + const int height = src->h; + + SDL_LockSurface(src); + SDL_LockSurface(dst); + switch(src->format->BytesPerPixel) + { + case 1: { + Uint8 E0, E1, E2, E3, B, D, E, F, H; + for(looph = 0; looph < height; ++looph) + { + for(loopw = 0; loopw < width; ++ loopw) + { + B = *(Uint8*)(srcpix + (MAX(0,looph-1)*srcpitch) + (1*loopw)); + D = *(Uint8*)(srcpix + (looph*srcpitch) + (1*MAX(0,loopw-1))); + E = *(Uint8*)(srcpix + (looph*srcpitch) + (1*loopw)); + F = *(Uint8*)(srcpix + (looph*srcpitch) + (1*MIN(width-1,loopw+1))); + H = *(Uint8*)(srcpix + (MIN(height-1,looph+1)*srcpitch) + (1*loopw)); + + E0 = D == B && B != F && D != H ? D : E; + E1 = B == F && B != D && F != H ? F : E; + E2 = D == H && D != B && H != F ? D : E; + E3 = H == F && D != H && B != F ? F : E; + + *(Uint8*)(dstpix + looph*2*dstpitch + loopw*2*1) = E0; + *(Uint8*)(dstpix + looph*2*dstpitch + (loopw*2+1)*1) = E1; + *(Uint8*)(dstpix + (looph*2+1)*dstpitch + loopw*2*1) = E2; + *(Uint8*)(dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*1) = E3; + } + }break;} + case 2: { + Uint16 E0, E1, E2, E3, B, D, E, F, H; + for(looph = 0; looph < height; ++looph) + { + for(loopw = 0; loopw < width; ++ loopw) + { + B = *(Uint16*)(srcpix + (MAX(0,looph-1)*srcpitch) + (2*loopw)); + D = *(Uint16*)(srcpix + (looph*srcpitch) + (2*MAX(0,loopw-1))); + E = *(Uint16*)(srcpix + (looph*srcpitch) + (2*loopw)); + F = *(Uint16*)(srcpix + (looph*srcpitch) + (2*MIN(width-1,loopw+1))); + H = *(Uint16*)(srcpix + (MIN(height-1,looph+1)*srcpitch) + (2*loopw)); + + E0 = D == B && B != F && D != H ? D : E; + E1 = B == F && B != D && F != H ? F : E; + E2 = D == H && D != B && H != F ? D : E; + E3 = H == F && D != H && B != F ? F : E; + + *(Uint16*)(dstpix + looph*2*dstpitch + loopw*2*2) = E0; + *(Uint16*)(dstpix + looph*2*dstpitch + (loopw*2+1)*2) = E1; + *(Uint16*)(dstpix + (looph*2+1)*dstpitch + loopw*2*2) = E2; + *(Uint16*)(dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*2) = E3; + } + }break;} + case 3: { + int E0, E1, E2, E3, B, D, E, F, H; + for(looph = 0; looph < height; ++looph) + { + for(loopw = 0; loopw < width; ++ loopw) + { + B = READINT24(srcpix + (MAX(0,looph-1)*srcpitch) + (3*loopw)); + D = READINT24(srcpix + (looph*srcpitch) + (3*MAX(0,loopw-1))); + E = READINT24(srcpix + (looph*srcpitch) + (3*loopw)); + F = READINT24(srcpix + (looph*srcpitch) + (3*MIN(width-1,loopw+1))); + H = READINT24(srcpix + (MIN(height-1,looph+1)*srcpitch) + (3*loopw)); + + E0 = D == B && B != F && D != H ? D : E; + E1 = B == F && B != D && F != H ? F : E; + E2 = D == H && D != B && H != F ? D : E; + E3 = H == F && D != H && B != F ? F : E; + + WRITEINT24((dstpix + looph*2*dstpitch + loopw*2*3), E0); + WRITEINT24((dstpix + looph*2*dstpitch + (loopw*2+1)*3), E1); + WRITEINT24((dstpix + (looph*2+1)*dstpitch + loopw*2*3), E2); + WRITEINT24((dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*3), E3); + } + }break;} + default: { /*case 4:*/ + Uint32 E0, E1, E2, E3, B, D, E, F, H; + for(looph = 0; looph < height; ++looph) + { + for(loopw = 0; loopw < width; ++ loopw) + { + B = *(Uint32*)(srcpix + (MAX(0,looph-1)*srcpitch) + (4*loopw)); + D = *(Uint32*)(srcpix + (looph*srcpitch) + (4*MAX(0,loopw-1))); + E = *(Uint32*)(srcpix + (looph*srcpitch) + (4*loopw)); + F = *(Uint32*)(srcpix + (looph*srcpitch) + (4*MIN(width-1,loopw+1))); + H = *(Uint32*)(srcpix + (MIN(height-1,looph+1)*srcpitch) + (4*loopw)); + + E0 = D == B && B != F && D != H ? D : E; + E1 = B == F && B != D && F != H ? F : E; + E2 = D == H && D != B && H != F ? D : E; + E3 = H == F && D != H && B != F ? F : E; + + *(Uint32*)(dstpix + looph*2*dstpitch + loopw*2*4) = E0; + *(Uint32*)(dstpix + looph*2*dstpitch + (loopw*2+1)*4) = E1; + *(Uint32*)(dstpix + (looph*2+1)*dstpitch + loopw*2*4) = E2; + *(Uint32*)(dstpix + (looph*2+1)*dstpitch + (loopw*2+1)*4) = E3; + } + }break;} + } + SDL_UnlockSurface(src); + SDL_UnlockSurface(dst); +} + diff --git a/plugins/gs/GSsoft/Src/scale2x.h b/plugins/gs/GSsoft/Src/scale2x.h new file mode 100644 index 0000000..265a317 --- /dev/null +++ b/plugins/gs/GSsoft/Src/scale2x.h @@ -0,0 +1,17 @@ +/* + This implements the AdvanceMAME Scale2x feature found on this page, + http://scale2x.sourceforge.net/ + + It is an incredibly simple and powerful image doubling routine that does + an astonishing job of doubling game graphic data while interpolating out + the jaggies. Congrats to the AdvanceMAME team, I'm very impressed and + surprised with this code! +*/ + + +#ifndef __SCALE2X_H__ +#define __SCALE2X_H__ + +void scale2x(SDL_Surface *src, SDL_Surface *dst); + +#endif /* __SCALE2X_H__ */ diff --git a/plugins/gs/GSsoft/Src/x86/ix86.h b/plugins/gs/GSsoft/Src/x86/ix86.h new file mode 100644 index 0000000..500de53 --- /dev/null +++ b/plugins/gs/GSsoft/Src/x86/ix86.h @@ -0,0 +1,1020 @@ +/* + * ix86 definitions v0.6.0 + * Authors: linuzappz + * alexey silinov + * goldfinger + * shadow < shadow@pcsx2.net > + */ + +#ifndef __IX86_H__ +#define __IX86_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "PS2Etypes.h" // Basic types header + +#define SIB 4 +#define DISP32 5 + +// general types +typedef enum +{ + EAX = 0, + EBX = 3, + ECX = 1, + EDX = 2, + ESI = 6, + EDI = 7, + EBP = 5, + ESP = 4, + + RAX = 0, + RBX = 3, + RCX = 1, + RDX = 2, + RSI = 6, + RDI = 7, + RBP = 5, + RSP = 4, + R8 = 8, + R9 = 9, + R10 =10, + R11 =11, + R12 =12, + R13 =13, + R14 =14, + R15 =15 + +} x86IntRegType; + +typedef enum +{ + MM0 = 0, + MM1 = 1, + MM2 = 2, + MM3 = 3, + MM4 = 4, + MM5 = 5, + MM6 = 6, + MM7 = 7 +} x86MMXRegType; + +typedef enum +{ + XMM0 = 0, + XMM1 = 1, + XMM2 = 2, + XMM3 = 3, + XMM4 = 4, + XMM5 = 5, + XMM6 = 6, + XMM7 = 7, + XMM8 = 8, + XMM9 = 9, + XMM10=10, + XMM11=11, + XMM12=12, + XMM13=13, + XMM14=14, + XMM15=15 + +} x86SSERegType; + + +extern u32 hasFloatingPointUnit; +extern u32 hasVirtual8086ModeEnhancements; +extern u32 hasDebuggingExtensions; +extern u32 hasPageSizeExtensions; +extern u32 hasTimeStampCounter; +extern u32 hasModelSpecificRegisters; +extern u32 hasPhysicalAddressExtension; +extern u32 hasMachineCheckArchitecture; +extern u32 hasCOMPXCHG8BInstruction; +extern u32 hasAdvancedProgrammableInterruptController; +extern u32 hasSEPFastSystemCall; +extern u32 hasMemoryTypeRangeRegisters; +extern u32 hasPTEGlobalFlag; +extern u32 hasMachineCheckArchitecture; +extern u32 hasConditionalMoveAndCompareInstructions; +extern u32 hasFGPageAttributeTable; +extern u32 has36bitPageSizeExtension; +extern u32 hasProcessorSerialNumber; +extern u32 hasCFLUSHInstruction; +extern u32 hasDebugStore; +extern u32 hasACPIThermalMonitorAndClockControl; +extern u32 hasMultimediaExtensions; +extern u32 hasFastStreamingSIMDExtensionsSaveRestore; +extern u32 hasStreamingSIMDExtensions; +extern u32 hasStreamingSIMD2Extensions; +extern u32 hasSelfSnoop; +extern u32 hasHyperThreading; +extern u32 hasThermalMonitor; +extern u32 hasIntel64BitArchitecture; +//that is only for AMDs +extern u32 hasMultimediaExtensionsExt; +extern u32 hasAMD64BitArchitecture; +extern u32 has3DNOWInstructionExtensionsExt; +extern u32 has3DNOWInstructionExtensions; + +extern s8 x86ID[16]; // Vendor ID +extern u32 x86Family; // Processor Family +extern u32 x86Model; // Processor Model +extern u32 x86PType; // Processor Type +extern u32 x86StepID; // Stepping ID +extern u32 x86Flags; // Feature Flags +extern u32 x86EFlags; // Extended Feature Flags +extern s8 x86Type[20]; //cpu type in char format +extern s8 x86Fam[50]; // family in char format +extern u32 cpuspeed; // Cpu speed +extern int cputype; // cpu type + +extern s8 *x86Ptr; +extern u8 *j8Ptr[32]; +extern u32 *j32Ptr[32]; + + +#ifdef __x86_64__ +#define MEMADDR(addr, oplen) ((addr) - ((u64)x86Ptr + ((u64)oplen))) +#else +#define MEMADDR(addr, oplen) (addr) +#endif + + + +void write8( u8 val ); +void write16( u16 val ); +void write32( u32 val ); +void write64( u64 val ); + +void x86Init( void ); +void x86SetPtr( char *ptr ); +void x86Shutdown( void ); +u64 GetCPUTick( void ); + +void x86SetJ8( u8 *j8 ); +void x86SetJ32( u32 *j32 ); +void x86Align( int bytes ); + +// General Helper functions + +void Rex( u8 w, u8 r, u8 x, u8 b ); +void ModRM( u8 mod, u8 rm, u8 reg ); +void SibSB( u8 ss, u8 rm, u8 index ); +void SET8R( u8 cc, u8 to ); +u8* J8Rel( u8 cc, u8 to ); +u32* J32Rel( u8 cc, u32 to ); +void CMOV32RtoR( u8 cc, u8 to, u8 from ); +void CMOV32MtoR( u8 cc, u8 to, u32 from ); + +//****************** +// IX86 intructions +//****************** + +// +// * scale values: +// * 0 - *1 +// * 1 - *2 +// * 2 - *4 +// * 3 - *8 +// + +void STC( void ); +void CLC( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r64 to r64 +void MOV64RtoR( x86IntRegType to, x86IntRegType from ); +// mov r64 to m64 +void MOV64RtoM( u64 to, x86IntRegType from ); +// mov m64 to r64 +void MOV64MtoR( x86IntRegType to, u64 from ); +// mov imm32 to m64 +void MOV64ItoM( u32 to, u32 from ); + +// mov r32 to r32 +void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +void MOV32RtoM( u32 to, x86IntRegType from ); +// mov m32 to r32 +void MOV32MtoR( x86IntRegType to, u32 from ); +// mov [r32] to r32 +void MOV32RmtoR( x86IntRegType to, x86IntRegType from ); +// mov [r32][r32*scale] to r32 +void MOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale ); +// mov r32 to [r32] +void MOV32RtoRm( x86IntRegType to, x86IntRegType from ); +// mov r32 to [r32][r32*scale] +void MOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale ); +// mov imm32 to r32 +void MOV32ItoR( x86IntRegType to, u32 from ); +// mov imm32 to m32 +void MOV32ItoM( u32 to, u32 from ); + +// mov r16 to m16 +void MOV16RtoM( u32 to, x86IntRegType from ); +// mov m16 to r16 +void MOV16MtoR( x86IntRegType to, u32 from ); +// mov imm16 to m16 +void MOV16ItoM( u32 to, u16 from ); +/* mov r16 to [r32][r32*scale] */ +void MOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale); + +// mov r8 to m8 +void MOV8RtoM( u32 to, x86IntRegType from ); +// mov m8 to r8 +void MOV8MtoR( x86IntRegType to, u32 from ); +// mov imm8 to m8 +void MOV8ItoM( u32 to, u8 from ); + +// movsx r8 to r32 +void MOVSX32R8toR( x86IntRegType to, x86IntRegType from ); +// movsx m8 to r32 +void MOVSX32M8toR( x86IntRegType to, u32 from ); +// movsx r16 to r32 +void MOVSX32R16toR( x86IntRegType to, x86IntRegType from ); +// movsx m16 to r32 +void MOVSX32M16toR( x86IntRegType to, u32 from ); + +// movzx r8 to r32 +void MOVZX32R8toR( x86IntRegType to, x86IntRegType from ); +// movzx m8 to r32 +void MOVZX32M8toR( x86IntRegType to, u32 from ); +// movzx r16 to r32 +void MOVZX32R16toR( x86IntRegType to, x86IntRegType from ); +// movzx m16 to r32 +void MOVZX32M16toR( x86IntRegType to, u32 from ); + +// cmovbe r32 to r32 +void CMOVBE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovbe m32 to r32 +void CMOVBE32MtoR( x86IntRegType to, u32 from ); +// cmovb r32 to r32 +void CMOVB32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovb m32 to r32 +void CMOVB32MtoR( x86IntRegType to, u32 from ); +// cmovae r32 to r32 +void CMOVAE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovae m32 to r32 +void CMOVAE32MtoR( x86IntRegType to, u32 from ); +// cmova r32 to r32 +void CMOVA32RtoR( x86IntRegType to, x86IntRegType from ); +// cmova m32 to r32 +void CMOVA32MtoR( x86IntRegType to, u32 from ); + +// cmovo r32 to r32 +void CMOVO32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovo m32 to r32 +void CMOVO32MtoR( x86IntRegType to, u32 from ); +// cmovp r32 to r32 +void CMOVP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovp m32 to r32 +void CMOVP32MtoR( x86IntRegType to, u32 from ); +// cmovs r32 to r32 +void CMOVS32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovs m32 to r32 +void CMOVS32MtoR( x86IntRegType to, u32 from ); +// cmovno r32 to r32 +void CMOVNO32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovno m32 to r32 +void CMOVNO32MtoR( x86IntRegType to, u32 from ); +// cmovnp r32 to r32 +void CMOVNP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovnp m32 to r32 +void CMOVNP32MtoR( x86IntRegType to, u32 from ); +// cmovns r32 to r32 +void CMOVNS32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovns m32 to r32 +void CMOVNS32MtoR( x86IntRegType to, u32 from ); + +// cmovne r32 to r32 +void CMOVNE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovne m32 to r32 +void CMOVNE32MtoR( x86IntRegType to, u32 from ); +// cmove r32 to r32 +void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmove m32 to r32 +void CMOVE32MtoR( x86IntRegType to, u32 from ); +// cmovg r32 to r32 +void CMOVG32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovg m32 to r32 +void CMOVG32MtoR( x86IntRegType to, u32 from ); +// cmovge r32 to r32 +void CMOVGE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovge m32 to r32 +void CMOVGE32MtoR( x86IntRegType to, u32 from ); +// cmovl r32 to r32 +void CMOVL32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovl m32 to r32 +void CMOVL32MtoR( x86IntRegType to, u32 from ); +// cmovle r32 to r32 +void CMOVLE32RtoR( x86IntRegType to, x86IntRegType from ); +// cmovle m32 to r32 +void CMOVLE32MtoR( x86IntRegType to, u32 from ); + +//////////////////////////////////// +// arithmetic instructions // +//////////////////////////////////// + +// add imm32 to r64 +void ADD64ItoR( x86IntRegType to, u32 from ); +// add m64 to r64 +void ADD64MtoR( x86IntRegType to, u32 from ); + +// add imm32 to r32 +void ADD32ItoR( x86IntRegType to, u32 from ); +// add imm32 to m32 +void ADD32ItoM( u32 to, u32 from ); +// add r32 to r32 +void ADD32RtoR( x86IntRegType to, x86IntRegType from ); +// add r32 to m32 +void ADD32RtoM( u32 to, x86IntRegType from ); +// add m32 to r32 +void ADD32MtoR( x86IntRegType to, u32 from ); + +// add imm16 to r16 +void ADD16ItoR( x86IntRegType to, u16 from ); +// add imm16 to m16 +void ADD16ItoM( u32 to, u16 from ); +// add r16 to m16 +void ADD16RtoM( u32 to, x86IntRegType from ); +// add m16 to r16 +void ADD16MtoR( x86IntRegType to, u32 from ); + +// adc imm32 to r32 +void ADC32ItoR( x86IntRegType to, u32 from ); +// adc imm32 to m32 +void ADC32ItoM( u32 to, u32 from ); +// adc r32 to r32 +void ADC32RtoR( x86IntRegType to, x86IntRegType from ); +// adc m32 to r32 +void ADC32MtoR( x86IntRegType to, u32 from ); + +// inc r32 +void INC32R( x86IntRegType to ); +// inc m32 +void INC32M( u32 to ); +// inc r16 +void INC16R( x86IntRegType to ); +// inc m16 +void INC16M( u32 to ); + +// sub m64 to r64 +void SUB64MtoR( x86IntRegType to, u32 from ); + +// sub imm32 to r32 +void SUB32ItoR( x86IntRegType to, u32 from ); +// sub imm32 to m32 +void SUB32ItoM( u32 to, u32 from ) ; +// sub r32 to r32 +void SUB32RtoR( x86IntRegType to, x86IntRegType from ); +// sub m32 to r32 +void SUB32MtoR( x86IntRegType to, u32 from ); +// sub imm16 to r16 +void SUB16ItoR( x86IntRegType to, u16 from ); +// sub imm16 to m16 +void SUB16ItoM( u32 to, u16 from ) ; +// sub m16 to r16 +void SUB16MtoR( x86IntRegType to, u32 from ); + +// sbb r64 to r64 +void SBB64RtoR( x86IntRegType to, x86IntRegType from ); + +// sbb imm32 to r32 +void SBB32ItoR( x86IntRegType to, u32 from ); +// sbb imm32 to m32 +void SBB32ItoM( u32 to, u32 from ); +// sbb r32 to r32 +void SBB32RtoR( x86IntRegType to, x86IntRegType from ); +// sbb m32 to r32 +void SBB32MtoR( x86IntRegType to, u32 from ); + +// dec r32 +void DEC32R( x86IntRegType to ); +// dec m32 +void DEC32M( u32 to ); +// dec r16 +void DEC16R( x86IntRegType to ); +// dec m16 +void DEC16M( u32 to ); + +// mul eax by r32 to edx:eax +void MUL32R( x86IntRegType from ); +// mul eax by m32 to edx:eax +void MUL32M( u32 from ); + +// imul eax by r32 to edx:eax +void IMUL32R( x86IntRegType from ); +// imul eax by m32 to edx:eax +void IMUL32M( u32 from ); +// imul r32 by r32 to r32 +void IMUL32RtoR( x86IntRegType to, x86IntRegType from ); + +// div eax by r32 to edx:eax +void DIV32R( x86IntRegType from ); +// div eax by m32 to edx:eax +void DIV32M( u32 from ); + +// idiv eax by r32 to edx:eax +void IDIV32R( x86IntRegType from ); +// idiv eax by m32 to edx:eax +void IDIV32M( u32 from ); + +//////////////////////////////////// +// shifting instructions // +//////////////////////////////////// + +// shl imm8 to r64 +void SHL64ItoR( x86IntRegType to, u8 from ); +// shl cl to r64 +void SHL64CLtoR( x86IntRegType to ); +// shr imm8 to r64 +void SHR64ItoR( x86IntRegType to, u8 from ); +// shr cl to r64 +void SHR64CLtoR( x86IntRegType to ); +// sar imm8 to r64 +void SAR64ItoR( x86IntRegType to, u8 from ); +// sar cl to r64 +void SAR64CLtoR( x86IntRegType to ); + +// shl imm8 to r32 +void SHL32ItoR( x86IntRegType to, u8 from ); +/* shl imm8 to m32 */ +void SHL32ItoM( u32 to, u8 from ); +// shl cl to r32 +void SHL32CLtoR( x86IntRegType to ); + +// shr imm8 to r32 +void SHR32ItoR( x86IntRegType to, u8 from ); +/* shr imm8 to m32 */ +void SHR32ItoM( u32 to, u8 from ); +// shr cl to r32 +void SHR32CLtoR( x86IntRegType to ); + +// sar imm8 to r32 +void SAR32ItoR( x86IntRegType to, u8 from ); +// sar imm8 to m32 +void SAR32ItoM( u32 to, u8 from ); +// sar cl to r32 +void SAR32CLtoR( x86IntRegType to ); + +void RCR32ItoR( x86IntRegType to,u8 from ); +// shld imm8 to r32 +void SHLD32ItoR( u32 to, u32 from, u8 shift ); +// shrd imm8 to r32 +void SHRD32ItoR( u32 to, u32 from, u8 shift ); + +// sal imm8 to r32 +#define SAL32ItoR SHL32ItoR +// sal cl to r32 +#define SAL32CLtoR SHL32CLtoR + +// logical instructions + +// or imm32 to r64 +void OR64ItoR( x86IntRegType to, u32 from ); +// or m64 to r64 +void OR64MtoR( x86IntRegType to, u32 from ); + +// or imm32 to r32 +void OR32ItoR( x86IntRegType to, u32 from ); +// or imm32 to m32 +void OR32ItoM( u32 to, u32 from ); +// or r32 to r32 +void OR32RtoR( x86IntRegType to, x86IntRegType from ); +// or r32 to m32 +void OR32RtoM( u32 to, x86IntRegType from ); +// or m32 to r32 +void OR32MtoR( x86IntRegType to, u32 from ); +// or m16 to r16 +void OR16MtoR( x86IntRegType to, u32 from ); + +// xor imm32 to r64 +void XOR64ItoR( x86IntRegType to, u32 from ); +// xor r64 to r64 +void XOR64RtoR( x86IntRegType to, x86IntRegType from ); +// xor m64 to r64 +void XOR64MtoR( x86IntRegType to, u32 from ); + +// xor imm32 to r32 +void XOR32ItoR( x86IntRegType to, u32 from ); +// xor imm32 to m32 +void XOR32ItoM( u32 to, u32 from ); +// xor r32 to r32 +void XOR32RtoR( x86IntRegType to, x86IntRegType from ); +// xor r16 to r16 +void XOR16RtoR( x86IntRegType to, x86IntRegType from ); +// xor r32 to m32 +void XOR32RtoM( u32 to, x86IntRegType from ); +// xor m32 to r32 +void XOR32MtoR( x86IntRegType to, u32 from ); + +// and imm32 to r64 +void AND64ItoR( x86IntRegType to, u32 from ); +// and m64 to r64 +void AND64MtoR( x86IntRegType to, u32 from ); +// and r64 to m64 +void AND64RtoM( x86IntRegType to, u32 from ); + +// and imm32 to r32 +void AND32ItoR( x86IntRegType to, u32 from ); +// and imm32 to m32 +void AND32ItoM( u32 to, u32 from ); +// and r32 to r32 +void AND32RtoR( x86IntRegType to, x86IntRegType from ); +// and r32 to m32 +void AND32RtoM( u32 to, x86IntRegType from ); +// and m32 to r32 +void AND32MtoR( x86IntRegType to, u32 from ); +// and r16 to m16 +void AND16RtoM( u32 to, x86IntRegType from ); +// and m16 to r16 +void AND16MtoR( x86IntRegType to, u32 from ); + +// not r64 +void NOT64R( x86IntRegType from ); +// not r32 +void NOT32R( x86IntRegType from ); +// neg r64 +void NEG64R( x86IntRegType from ); +// neg r32 +void NEG32R( x86IntRegType from ); +// neg r16 +void NEG16R( x86IntRegType from ); + +//////////////////////////////////// +// jump instructions // +//////////////////////////////////// + +// jmp rel8 +u8* JMP8( u8 to ); + +// jmp rel32 +u32* JMP32( u32 to ); +// jmp r32 +void JMP32R( x86IntRegType to ); + +// jp rel8 +u8* JP8( u8 to ); +// jnp rel8 +u8* JNP8( u8 to ); +// je rel8 +u8* JE8( u8 to ); +// jz rel8 +u8* JZ8( u8 to ); +// jg rel8 +u8* JG8( u8 to ); +// jge rel8 +u8* JGE8( u8 to ); +// js rel8 +u8* JS8( u8 to ); +// jns rel8 +u8* JNS8( u8 to ); +// jl rel8 +u8* JL8( u8 to ); +// ja rel8 +u8* JA8( u8 to ); +// jae rel8 +u8* JAE8( u8 to ); +// jb rel8 +u8* JB8( u8 to ); +// jbe rel8 +u8* JBE8( u8 to ); +// jle rel8 +u8* JLE8( u8 to ); +// jne rel8 +u8* JNE8( u8 to ); +// jnz rel8 +u8* JNZ8( u8 to ); +// jng rel8 +u8* JNG8( u8 to ); +// jnge rel8 +u8* JNGE8( u8 to ); +// jnl rel8 +u8* JNL8( u8 to ); +// jnle rel8 +u8* JNLE8( u8 to ); +// jo rel8 +u8* JO8( u8 to ); +// jno rel8 +u8* JNO8( u8 to ); + +// je rel32 +u32* JE32( u32 to ); +// jz rel32 +u32* JZ32( u32 to ); +// jg rel32 +u32* JG32( u32 to ); +// jge rel32 +u32* JGE32( u32 to ); +// jl rel32 +u32* JL32( u32 to ); +// jle rel32 +u32* JLE32( u32 to ); +// jne rel32 +u32* JNE32( u32 to ); +// jnz rel32 +u32* JNZ32( u32 to ); +// jng rel32 +u32* JNG32( u32 to ); +// jnge rel32 +u32* JNGE32( u32 to ); +// jnl rel32 +u32* JNL32( u32 to ); +// jnle rel32 +u32* JNLE32( u32 to ); +// jo rel32 +u32* JO32( u32 to ); +// jno rel32 +u32* JNO32( u32 to ); + +// call func +void CALLFunc( u32 func); // based on CALL32 +// call rel32 +void CALL32( u32 to ); +// call r32 +void CALL32R( x86IntRegType to ); +// call m32 +void CALL32M( u32 to ); + +//////////////////////////////////// +// misc instructions // +//////////////////////////////////// + +// cmp imm32 to r64 +void CMP64ItoR( x86IntRegType to, u32 from ); +// cmp m64 to r64 +void CMP64MtoR( x86IntRegType to, u32 from ); + +// cmp imm32 to r32 +void CMP32ItoR( x86IntRegType to, u32 from ); +// cmp imm32 to m32 +void CMP32ItoM( u32 to, u32 from ); +// cmp r32 to r32 +void CMP32RtoR( x86IntRegType to, x86IntRegType from ); +// cmp m32 to r32 +void CMP32MtoR( x86IntRegType to, u32 from ); + +// cmp imm16 to r16 +void CMP16ItoR( x86IntRegType to, u16 from ); +// cmp imm16 to m16 +void CMP16ItoM( u32 to, u16 from ); +// cmp r16 to r16 +void CMP16RtoR( x86IntRegType to, x86IntRegType from ); +// cmp m16 to r16 +void CMP16MtoR( x86IntRegType to, u32 from ); + +// test imm32 to r32 +void TEST32ItoR( x86IntRegType to, u32 from ); +// test r32 to r32 +void TEST32RtoR( x86IntRegType to, x86IntRegType from ); + +// sets r8 +void SETS8R( x86IntRegType to ); +// setl r8 +void SETL8R( x86IntRegType to ); +// setb r8 +void SETB8R( x86IntRegType to ); +// setnz r8 +void SETNZ8R( x86IntRegType to ); + +// cbw +void CBW( void ); +// cwd +void CWD( void ); +// cdq +void CDQ( void ); + +// push r32 +void PUSH32R( x86IntRegType from ); +// push m32 +void PUSH32M( u32 from ); +// push imm32 +void PUSH32I( u32 from ); +// pop r32 +void POP32R( x86IntRegType from ); +// pushad +void PUSHA32( void ); +// popad +void POPA32( void ); +// pushfd +void PUSHFD( void ); +// popfd +void POPFD( void ); +// ret +void RET( void ); + +void BT32ItoR( x86IntRegType to, x86IntRegType from ); + +//****************** +// FPU instructions +//****************** + +// fild m32 to fpu reg stack +void FILD32( u32 from ); +// fistp m32 from fpu reg stack +void FISTP32( u32 from ); +// fld m32 to fpu reg stack +void FLD32( u32 from ); +// fst m32 from fpu reg stack +void FST32( u32 to ); +// fstp m32 from fpu reg stack +void FSTP32( u32 to ); + +// fldcw fpu control word from m16 +void FLDCW( u32 from ); +// fstcw fpu control word to m16 +void FNSTCW( u32 to ); + +// fadd ST(src) to fpu reg stack ST(0) +void FADD32Rto0( x86IntRegType src ); +// fadd ST(0) to fpu reg stack ST(src) +void FADD320toR( x86IntRegType src ); +// fsub ST(src) to fpu reg stack ST(0) +void FSUB32Rto0( x86IntRegType src ); +// fsub ST(0) to fpu reg stack ST(src) +void FSUB320toR( x86IntRegType src ); +// fsubp -> subtract ST(0) from ST(1), store in ST(1) and POP stack +void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +void FDIV320toR( x86IntRegType src ); + +// fadd m32 to fpu reg stack +void FADD32( u32 from ); +// fsub m32 to fpu reg stack +void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +void FDIV32( u32 from ); +// fcomi st, st( i) +void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +void FCOM32( u32 from ); +// fabs fpu reg stack +void FABS( void ); +// fsqrt fpu reg stack +void FSQRT( void ); +// fchs fpu reg stack +void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +void FCMOVNU32( x86IntRegType from ); +void FCOMP32( u32 from ); +void FNSTSWtoAX( void ); + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +void MOVQMtoR( x86MMXRegType to, u32 from ); +// movq r64 to m64 +void MOVQRtoM( u32 to, x86MMXRegType from ); + +// pand r64 to r64 +void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +void PANDMtoR( x86MMXRegType to, u32 from ); +// pandn r64 to r64 +void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +void PANDNMtoR( x86MMXRegType to, u32 from ); +// por r64 to r64 +void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +void PORMtoR( x86MMXRegType to, u32 from ); +// pxor r64 to r64 +void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +void PXORMtoR( x86MMXRegType to, u32 from ); + +// psllq r64 to r64 +void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +void PSLLQMtoR( x86MMXRegType to, u32 from ); +// psllq imm8 to r64 +void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +void PSRLQMtoR( x86MMXRegType to, u32 from ); +// psrlq imm8 to r64 +void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +void PADDUSBMtoR( x86MMXRegType to, u32 from ); +// paddusw r64 to r64 +void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +void PADDUSWMtoR( x86MMXRegType to, u32 from ); + +// paddb r64 to r64 +void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +void PADDBMtoR( x86MMXRegType to, u32 from ); +// paddw r64 to r64 +void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +void PADDWMtoR( x86MMXRegType to, u32 from ); +// paddd r64 to r64 +void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +void PADDDMtoR( x86MMXRegType to, u32 from ); +void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PADDSDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBSDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +void PSRLWItoR( x86MMXRegType to, u8 from ); +void PSRLDItoR( x86MMXRegType to, u8 from ); +void PSLLWItoR( x86MMXRegType to, u8 from ); +void PSLLDItoR( x86MMXRegType to, u8 from ); +void PSRAWItoR( x86MMXRegType to, u8 from ); +void PSRADItoR( x86MMXRegType to, u8 from ); +void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVQ64ItoR( x86MMXRegType reg, u64 i ); //Prototype.Todo add all consts to end of block.not after jr $+8 +void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +void MOVDMtoMMX( x86MMXRegType to, u32 from ); +void MOVDMMXtoM( u32 to, x86MMXRegType from ); +void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +void MOVD64MMXtoR( x86IntRegType to, x86MMXRegType from ); +// emms +void EMMS( void ); + +//********************* +// SSE instructions * +//********************* +void MOVAPSMtoR( x86SSERegType to, u32 from ); +void MOVAPSRtoM( u32 to, x86SSERegType from ); +void MOVAPSRtoR( x86SSERegType to, x86SSERegType from ); + +void MOVSSMtoR( x86SSERegType to, u32 from ); +void MOVSSRtoM( u32 to, x86SSERegType from ); +void MOVSSRtoR( x86SSERegType to, x86SSERegType from ); + +void MOVLPSMtoR( x86SSERegType to, u32 from ); +void MOVLPSRtoM( u32 to, x86SSERegType from ); +void MOVHPSMtoR( x86SSERegType to, u32 from ); +void MOVHPSRtoM( u32 to, x86SSERegType from ); +void MOVLHPSRtoR( x86SSERegType to, x86SSERegType from ); +void MOVHLPSRtoR( x86SSERegType to, x86SSERegType from ); +void MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void MOVAPSRtoRm( x86IntRegType to, x86IntRegType from ); +void MOVAPSRmtoR( x86IntRegType to, x86IntRegType from ); +void MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ); +void MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ); +void MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ); +void ORPSMtoR( x86SSERegType to, u32 from ); +void ORPSRtoR( x86SSERegType to, x86SSERegType from ); +void XORPSMtoR( x86SSERegType to, u32 from ); +void XORPSRtoR( x86SSERegType to, x86SSERegType from ); +void ANDPSMtoR( x86SSERegType to, u32 from ); +void ANDPSRtoR( x86SSERegType to, x86SSERegType from ); +void ANDNPSMtoR( x86SSERegType to, u32 from ); +void ANDNPSRtoR( x86SSERegType to, x86SSERegType from ); +void ADDPSMtoR( x86SSERegType to, u32 from ); +void ADDPSRtoR( x86SSERegType to, x86SSERegType from ); +void SUBPSMtoR( x86SSERegType to, u32 from ); +void SUBPSRtoR( x86SSERegType to, x86SSERegType from ); +void MULPSMtoR( x86SSERegType to, u32 from ); +void MULPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPEQPSMtoR( x86SSERegType to, u32 from ); +void CMPLTPSMtoR( x86SSERegType to, u32 from ); +void CMPLEPSMtoR( x86SSERegType to, u32 from ); + +void CVTPS2DQMtoR( x86SSERegType to, u32 from ); +void CVTPS2DQRtoR( x86SSERegType to, x86SSERegType from ); + +void CVTDQ2PSDQMtoR( x86SSERegType to, u32 from ); +void CMPUNORDPSMtoR( x86SSERegType to, u32 from ); +void CMPNEPSMtoR( x86SSERegType to, u32 from ); +void CMPNLTPSMtoR( x86SSERegType to, u32 from ); +void CMPNLEPSMtoR( x86SSERegType to, u32 from ); +void CMPORDPSMtoR( x86SSERegType to, u32 from ); +void CMPEQPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPLTPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPLEPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPUNORDPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPNEPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPNLTPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPNLEPSRtoR( x86SSERegType to, x86SSERegType from ); +void CMPORDPSRtoR( x86SSERegType to, x86SSERegType from ); +void CVTPI2PSMtoR( x86SSERegType to, u32 from ); +void CVTPS2PIMtoR( x86SSERegType to, u32 from ); +void CVTPI2PSRtoR( x86SSERegType to, x86SSERegType from ); +void CVTPS2PIRtoR( x86SSERegType to, x86SSERegType from ); +void MAXPSMtoR( x86SSERegType to, u32 from ); +void MAXPSRtoR( x86SSERegType to, x86SSERegType from ); +void PMAXSWRtoR( x86SSERegType to, x86SSERegType from ); +void PMINSWRtoR( x86SSERegType to, x86SSERegType from ); +void MINPSMtoR( x86SSERegType to, u32 from ); +void MINPSRtoR( x86SSERegType to, x86SSERegType from ); +void RSQRTPSMtoR( x86SSERegType to, u32 from ); +void RSQRTPSRtoR( x86SSERegType to, x86SSERegType from ); +void SQRTPSMtoR( x86SSERegType to, u32 from ); +void SQRTPSRtoR( x86SSERegType to, x86SSERegType from ); +void UNPCKLPSRtoR( x86SSERegType to, x86SSERegType from ); +void UNPCKHPSRtoR( x86SSERegType to, x86SSERegType from ); +void SHUFPSRtoR( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void SHUFPSMtoR( x86SSERegType to, u32 from, u8 imm8 ); +void CVTDQ2PSMtoR( x86SSERegType to, u32 from ); + +void DIVPSMtoR( x86SSERegType to, u32 from ); +void DIVPSRtoR( x86SSERegType to, x86SSERegType from ); + +void DIVSSMtoR( x86SSERegType to, u32 from ); +void DIVSSRtoR( x86SSERegType to, x86SSERegType from ); + +void MOVDMtoXMM( x86SSERegType to, u32 from ); +void MOVDXMMtoM( u32 to, x86SSERegType from ); +void MOVD32RtoXMM( x86SSERegType to, x86IntRegType from ); +void MOVD64XMMtoR( x86IntRegType to, x86SSERegType from ); + +void PSHUFDRtoR( x86SSERegType to, x86SSERegType from, u8 imm8 ); +void PSHUFDMtoR( x86SSERegType to, u32 from, u8 imm8 ); + +void STMXCSR( u32 from ); +void LDMXCSR( u32 from ); + +//********************* +// 3DNOW instructions * +//********************* +void FEMMS( void ); +void PFCMPEQMtoR( x86IntRegType to, u32 from ); +void PFCMPGTMtoR( x86IntRegType to, u32 from ); +void PFCMPGEMtoR( x86IntRegType to, u32 from ); +void PFADDMtoR( x86IntRegType to, u32 from ); +void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +void PFSUBMtoR( x86IntRegType to, u32 from ); +void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +void PFMULMtoR( x86IntRegType to, u32 from ); +void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPMtoR( x86IntRegType to, u32 from ); +void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +void PF2IDMtoR( x86IntRegType to, u32 from ); +void PF2IDRtoR( x86IntRegType to, x86IntRegType from ); +void PI2FDMtoR( x86IntRegType to, u32 from ); +void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +void PFMAXMtoR( x86IntRegType to, u32 from ); +void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +void PFMINMtoR( x86IntRegType to, u32 from ); +void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + +#ifdef __cplusplus +} +#endif + +#endif // __IX86_H__ diff --git a/plugins/gs/GSsoft/Src/x86/ix86_cpudetect.c b/plugins/gs/GSsoft/Src/x86/ix86_cpudetect.c new file mode 100644 index 0000000..b616ee6 --- /dev/null +++ b/plugins/gs/GSsoft/Src/x86/ix86_cpudetect.c @@ -0,0 +1,510 @@ + +#if defined (__WIN32__) + +#include + +#endif + +#include +#include +#include + +#include "ix86.h" + +#if defined (__VCNET2005__) + + void __cpuid(int* CPUInfo, int InfoType); + unsigned __int64 __rdtsc(); + + #pragma intrinsic(__cpuid) + #pragma intrinsic(__rdtsc) + +#endif + +u32 hasFloatingPointUnit; +u32 hasVirtual8086ModeEnhancements; +u32 hasDebuggingExtensions; +u32 hasPageSizeExtensions; +u32 hasTimeStampCounter; +u32 hasModelSpecificRegisters; +u32 hasPhysicalAddressExtension; +u32 hasMachineCheckArchitecture; +u32 hasCOMPXCHG8BInstruction; +u32 hasAdvancedProgrammableInterruptController; +u32 hasSEPFastSystemCall; +u32 hasMemoryTypeRangeRegisters; +u32 hasPTEGlobalFlag; +u32 hasMachineCheckArchitecture; +u32 hasConditionalMoveAndCompareInstructions; +u32 hasFGPageAttributeTable; +u32 has36bitPageSizeExtension; +u32 hasProcessorSerialNumber; +u32 hasCFLUSHInstruction; +u32 hasDebugStore; +u32 hasACPIThermalMonitorAndClockControl; +u32 hasMultimediaExtensions; +u32 hasFastStreamingSIMDExtensionsSaveRestore; +u32 hasStreamingSIMDExtensions; +u32 hasStreamingSIMD2Extensions; +u32 hasSelfSnoop; +u32 hasHyperThreading; +u32 hasThermalMonitor; +u32 hasIntel64BitArchitecture; +//that is only for AMDs +u32 hasMultimediaExtensionsExt; +u32 hasAMD64BitArchitecture; +u32 has3DNOWInstructionExtensionsExt; +u32 has3DNOWInstructionExtensions; + +s8 x86ID[16]; // Vendor ID +u32 x86Family; // Processor Family +u32 x86Model; // Processor Model +u32 x86PType; // Processor Type +u32 x86StepID; // Stepping ID +u32 x86Flags; // Feature Flags +u32 x86EFlags; // Extended Feature Flags +//AMD 64 STUFF +u32 x86_64_8BITBRANDID; +u32 x86_64_12BITBRANDID; +s8 x86Type[20]; //cpu type in char format +s8 x86Fam[50]; // family in char format +u32 cpuspeed; // speed of cpu +int cputype; // Cpu type + +static s32 iCpuId( u32 cmd, u32 *regs ) +{ + int flag; + +#if defined (__VCNET2005__) + + __cpuid( regs, cmd ); + + return 0; + +#elif defined (__MSCW32__) && !defined(__x86_64__) + __asm + { + push ebx; + push edi; + + pushfd; + pop eax; + mov edx, eax; + xor eax, 1 << 21; + push eax; + popfd; + pushfd; + pop eax; + xor eax, edx; + mov flag, eax; + } + if ( ! flag ) + { + return -1; + } + + __asm + { + mov eax, cmd; + cpuid; + mov edi, [regs] + mov [edi], eax; + mov [edi+4], ebx; + mov [edi+8], ecx; + mov [edi+12], edx; + + pop edi; + pop ebx; + } + + return 0; + + +#else + + __asm__ __volatile__ ( +#ifdef __x86_64__ + "sub $0x18, %%rsp\n" +#endif + "pushf\n" + "pop %%eax\n" + "mov %%eax, %%edx\n" + "xor $0x200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "xor %%edx, %%eax\n" + "mov %%eax, %0\n" +#ifdef __x86_64__ + "add $0x18, %%rsp\n" +#endif + : "=r"(flag) : + ); + + if ( ! flag ) + { + return -1; + } + + __asm__ __volatile__ ( + "mov %4, %%eax\n" + "cpuid\n" + "mov %%eax, %0\n" + "mov %%ebx, %1\n" + "mov %%ecx, %2\n" + "mov %%edx, %3\n" + : "=m" (regs[0]), "=m" (regs[1]), + "=m" (regs[2]), "=m" (regs[3]) + : "m"(cmd) + : "eax", "ebx", "ecx", "edx" + ); + + return 0; +#endif +} + +u64 GetCPUTick( void ) +{ +#if defined (__VCNET2005__) + + return __rdtsc(); + +#elif defined(__MSCW32__) && !defined(__x86_64__) + + __asm rdtsc; + +#else + + u32 _a, _d; + __asm__ __volatile__ ("rdtsc" : "=a"(_a), "=d"(_d)); + return (u64)_a | ((u64)_d << 32); + +#endif +} + +#if defined __LINUX__ + +#include +#include + +u32 timeGetTime( void ) +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#endif + +s64 CPUSpeedHz( unsigned int time ) +{ + s64 timeStart, + timeStop; + s64 startTick, + endTick; + s64 overhead; + + if( ! hasTimeStampCounter ) + { + return 0; //check if function is supported + } + + overhead = GetCPUTick() - GetCPUTick(); + + timeStart = timeGetTime( ); + while( timeGetTime( ) == timeStart ) + { + timeStart = timeGetTime( ); + } + while ( 1 ) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > 1 ) + { + startTick = GetCPUTick( ); + break; + } + } + + timeStart = timeStop; + while ( 1 ) + { + timeStop = timeGetTime( ); + if ( ( timeStop - timeStart ) > time ) + { + endTick = GetCPUTick( ); + break; + } + } + + return (s64)( ( endTick - startTick ) + ( overhead ) ); +} +u32 AMDspeed; +s8 AMDspeedString[10]; +//////////////////////////////////////////////////// +void x86Init( void ) +{ + u32 regs[ 4 ]; + u32 cmds; + + memset( x86ID, 0, sizeof( x86ID ) ); + x86Family = 0; + x86Model = 0; + x86PType = 0; + x86StepID = 0; + x86Flags = 0; + x86EFlags = 0; + + if ( iCpuId( 0, regs ) == -1 ) return; + + cmds = regs[ 0 ]; + ((u32*)x86ID)[ 0 ] = regs[ 1 ]; + ((u32*)x86ID)[ 1 ] = regs[ 3 ]; + ((u32*)x86ID)[ 2 ] = regs[ 2 ]; + if ( cmds >= 0x00000001 ) + { + if ( iCpuId( 0x00000001, regs ) != -1 ) + { + x86StepID = regs[ 0 ] & 0xf; + x86Model = (regs[ 0 ] >> 4) & 0xf; + x86Family = (regs[ 0 ] >> 8) & 0xf; + x86PType = (regs[ 0 ] >> 12) & 0x3; + x86_64_8BITBRANDID = regs[1] & 0xff; + x86Flags = regs[ 3 ]; + } + } + if ( iCpuId( 0x80000000, regs ) != -1 ) + { + cmds = regs[ 0 ]; + if ( cmds >= 0x80000001 ) + { + if ( iCpuId( 0x80000001, regs ) != -1 ) + { + x86_64_12BITBRANDID = regs[1] & 0xfff; + x86EFlags = regs[ 3 ]; + + } + } + } + switch(x86PType) + { + case 0: + strcpy( x86Type, "Standard OEM"); + break; + case 1: + strcpy( x86Type, "Overdrive"); + break; + case 2: + strcpy( x86Type, "Dual"); + break; + case 3: + strcpy( x86Type, "Reserved"); + break; + default: + strcpy( x86Type, "Unknown"); + break; + } + if ( x86ID[ 0 ] == 'G' ){ cputype=0;}//trick lines but if you know a way better ;p + if ( x86ID[ 0 ] == 'A' ){ cputype=1;} + + if ( cputype == 0 ) //intel cpu + { + if( ( x86Family >= 7 ) && ( x86Family < 15 ) ) + { + strcpy( x86Fam, "Intel P6 family (Not PIV and Higher then PPro" ); + } + else + { + switch( x86Family ) + { + // Start at 486 because if it's below 486 there is no cpuid instruction + case 4: + strcpy( x86Fam, "Intel 486" ); + break; + case 5: + switch( x86Model ) + { + case 4: + case 8: // 0.25 m + strcpy( x86Fam, "Intel Pentium (MMX)"); + break; + default: + strcpy( x86Fam, "Intel Pentium" ); + } + break; + case 6: + switch( x86Model ) + { + case 0: // Pentium pro (P6 A-Step) + case 1: // Pentium pro + strcpy( x86Fam, "Intel Pentium Pro" ); + break; + + case 2: // 66 MHz FSB + case 5: // Xeon/Celeron (0.25 m) + case 6: // Internal L2 cache + strcpy( x86Fam, "Intel Pentium II" ); + break; + + case 7: // Xeon external L2 cache + case 8: // Xeon/Celeron with 256 KB on-die L2 cache + case 10: // Xeon/Celeron with 1 or 2 MB on-die L2 cache + case 11: // Xeon/Celeron with Tualatin core, on-die cache + strcpy( x86Fam, "Intel Pentium III" ); + break; + + default: + strcpy( x86Fam, "Intel Pentium Pro (Unknown)" ); + } + break; + case 15: + switch( x86Model ) + { + case 0: // Willamette (A-Step) + case 1: // Willamette + strcpy( x86Fam, "Willamette Intel Pentium IV" ); + break; + case 2: // Northwood + strcpy( x86Fam, "Northwood Intel Pentium IV" ); + break; + + default: + strcpy( x86Fam, "Intel Pentium IV (Unknown)" ); + break; + } + break; + default: + strcpy( x86Fam, "Unknown Intel CPU" ); + } + } + } + else if ( cputype == 1 ) //AMD cpu + { + if( x86Family >= 7 ) + { + if((x86_64_12BITBRANDID !=0) || (x86_64_8BITBRANDID !=0)) + { + if(x86_64_8BITBRANDID == 0 ) + { + switch((x86_64_12BITBRANDID >>6)& 0x3f) + { + case 4: + strcpy(x86Fam,"AMD Athlon(tm) 64 Processor"); + AMDspeed = 22 + (x86_64_12BITBRANDID & 0x1f); + //AMDspeedString = strtol(AMDspeed, (char**)NULL,10); + sprintf(AMDspeedString," %d",AMDspeed); + strcat(AMDspeedString,"00+"); + strcat(x86Fam,AMDspeedString); + break; + case 12: + strcpy(x86Fam,"AMD Opteron(tm) Processor"); + break; + default: + strcpy(x86Fam,"Unknown AMD 64 proccesor"); + + } + } + else //8bit brand id is non zero + { + strcpy(x86Fam,"Unsupported yet AMD64 cpu"); + } + } + else + { + strcpy( x86Fam, "AMD K7+" ); + } + } + else + { + switch ( x86Family ) + { + case 4: + switch( x86Model ) + { + case 14: + case 15: // Write-back enhanced + strcpy( x86Fam, "AMD 5x86" ); + break; + + case 3: // DX2 + case 7: // Write-back enhanced DX2 + case 8: // DX4 + case 9: // Write-back enhanced DX4 + strcpy( x86Fam, "AMD 486" ); + break; + + default: + strcpy( x86Fam, "AMD Unknown" ); + + } + break; + + case 5: + switch( x86Model) + { + case 0: // SSA 5 (75, 90 and 100 Mhz) + case 1: // 5k86 (PR 120 and 133 MHz) + case 2: // 5k86 (PR 166 MHz) + case 3: // K5 5k86 (PR 200 MHz) + strcpy( x86Fam, "AMD K5" ); + break; + + case 6: + case 7: // (0.25 m) + case 8: // K6-2 + case 9: // K6-III + case 14: // K6-2+ / K6-III+ + strcpy( x86Fam, "AMD K6" ); + break; + + default: + strcpy( x86Fam, "AMD Unknown" ); + } + break; + case 6: + strcpy( x86Fam, "AMD K7" ); + break; + default: + strcpy( x86Fam, "Unknown AMD CPU" ); + } + } + } + //capabilities + hasFloatingPointUnit = ( x86Flags >> 0 ) & 1; + hasVirtual8086ModeEnhancements = ( x86Flags >> 1 ) & 1; + hasDebuggingExtensions = ( x86Flags >> 2 ) & 1; + hasPageSizeExtensions = ( x86Flags >> 3 ) & 1; + hasTimeStampCounter = ( x86Flags >> 4 ) & 1; + hasModelSpecificRegisters = ( x86Flags >> 5 ) & 1; + hasPhysicalAddressExtension = ( x86Flags >> 6 ) & 1; + hasMachineCheckArchitecture = ( x86Flags >> 7 ) & 1; + hasCOMPXCHG8BInstruction = ( x86Flags >> 8 ) & 1; + hasAdvancedProgrammableInterruptController = ( x86Flags >> 9 ) & 1; + hasSEPFastSystemCall = ( x86Flags >> 11 ) & 1; + hasMemoryTypeRangeRegisters = ( x86Flags >> 12 ) & 1; + hasPTEGlobalFlag = ( x86Flags >> 13 ) & 1; + hasMachineCheckArchitecture = ( x86Flags >> 14 ) & 1; + hasConditionalMoveAndCompareInstructions = ( x86Flags >> 15 ) & 1; + hasFGPageAttributeTable = ( x86Flags >> 16 ) & 1; + has36bitPageSizeExtension = ( x86Flags >> 17 ) & 1; + hasProcessorSerialNumber = ( x86Flags >> 18 ) & 1; + hasCFLUSHInstruction = ( x86Flags >> 19 ) & 1; + hasDebugStore = ( x86Flags >> 21 ) & 1; + hasACPIThermalMonitorAndClockControl = ( x86Flags >> 22 ) & 1; + hasMultimediaExtensions = ( x86Flags >> 23 ) & 1; //mmx + hasFastStreamingSIMDExtensionsSaveRestore = ( x86Flags >> 24 ) & 1; + hasStreamingSIMDExtensions = ( x86Flags >> 25 ) & 1; //sse + hasStreamingSIMD2Extensions = ( x86Flags >> 26 ) & 1; //sse2 + hasSelfSnoop = ( x86Flags >> 27 ) & 1; + hasHyperThreading = ( x86Flags >> 28 ) & 1; + hasThermalMonitor = ( x86Flags >> 29 ) & 1; + hasIntel64BitArchitecture = ( x86Flags >> 30 ) & 1; + //that is only for AMDs + hasMultimediaExtensionsExt = ( x86EFlags >> 22 ) & 1; //mmx2 + hasAMD64BitArchitecture = ( x86EFlags >> 29 ) & 1; //64bit cpu + has3DNOWInstructionExtensionsExt = ( x86EFlags >> 30 ) & 1; //3dnow+ + has3DNOWInstructionExtensions = ( x86EFlags >> 31 ) & 1; //3dnow + + cpuspeed = (u32 )(CPUSpeedHz( 1000 ) / 1000000); +} diff --git a/plugins/gs/build.sh b/plugins/gs/build.sh new file mode 100644 index 0000000..5fd8813 --- /dev/null +++ b/plugins/gs/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +echo ---------------------------------------- +echo Building Graphics Synthesizer plugins... +echo ---------------------------------------- + +curdir=`pwd` + +cd ${curdir}/zerogs +sh build.sh $@ diff --git a/plugins/gs/zerogs/build.sh b/plugins/gs/zerogs/build.sh new file mode 100644 index 0000000..6a81ab1 --- /dev/null +++ b/plugins/gs/zerogs/build.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +curdir=`pwd` + +echo ---------------------- +echo Building ZeroGS OpenGL +echo ---------------------- + +cd ${curdir}/opengl + +if [ $# -gt 0 ] && [ $1 = "all" ] +then + +aclocal +automake +autoconf +./configure --enable-sse2 --prefix=${PCSX2PLUGINS} +make clean +make install + +else +make $@ +fi + +if [ $? -ne 0 ] +then +exit 1 +fi + +#cp libZeroGSogl*.so* ${PCSX2PLUGINS}/ +cp Win32/ps2hw.dat ${PCSX2PLUGINS}/ \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/GS.h b/plugins/gs/zerogs/opengl/GS.h new file mode 100644 index 0000000..bbd3d4e --- /dev/null +++ b/plugins/gs/zerogs/opengl/GS.h @@ -0,0 +1,840 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GS_H__ +#define __GS_H__ + +#include +#include +#include + +// need C definitions +extern "C" { +#define GSdefs +#include "PS2Edefs.h" +} + +#ifdef _WIN32 + +#include +#include + +extern HWND GShwnd; + +#else // linux basic definitions + +#include +#include +#include +#include +#include +#include +#include +#include + +#define __inline inline + +#if !defined(_MSC_VER) && !defined(HAVE_ALIGNED_MALLOC) + +// declare linux equivalents +extern __forceinline void* pcsx2_aligned_malloc(size_t size, size_t align) +{ + assert( align < 0x10000 ); + char* p = (char*)malloc(size+align); + int off = 2+align - ((int)(uptr)(p+2) % align); + + p += off; + *(u16*)(p-2) = off; + + return p; +} + +extern __forceinline void pcsx2_aligned_free(void* pmem) +{ + if( pmem != NULL ) { + char* p = (char*)pmem; + free(p - (int)*(u16*)(p-2)); + } +} + +#define _aligned_malloc pcsx2_aligned_malloc +#define _aligned_free pcsx2_aligned_free + +#endif + +#include // ftime(), struct timeb + +inline unsigned long timeGetTime() +{ +#ifdef _WIN32 + _timeb t; + _ftime(&t); +#else + timeb t; + ftime(&t); +#endif + + return (unsigned long)(t.time*1000+t.millitm); +} + +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +struct RECT +{ + int left, top; + int right, bottom; +}; + +typedef struct { + Display *dpy; + int screen; + Window win; + GLXContext ctx; + XSetWindowAttributes attr; + Bool fs; + Bool doubleBuffered; + XF86VidModeModeInfo deskMode; + int x, y; + unsigned int width, height; + unsigned int depth; +} GLWindow; + +extern GLWindow GLWin; + +#endif // linux basic definitions + +#include +#include + +#include +#include +using namespace std; + +#include "zerogsmath.h" + +#if defined(_MSC_VER) +#define FASTCALL(fn) __fastcall fn +#else + +#ifdef __x86_64 +#define FASTCALL(fn) fn +#else +#define FASTCALL(fn) __attribute__((fastcall)) fn +#endif + +#endif + +struct Vector_16F +{ + u16 x, y, z, w; +}; + +///////////////////// +// define when releasing +#define ZEROGS_CACHEDCLEAR // much better performance +//#define RELEASE_TO_PUBLIC + +#if !defined(_RELEASE) +#define GS_LOG __Log +#else +#define GS_LOG 0&& +#endif + +#ifdef RELEASE_TO_PUBLIC +#define WARN_LOG 0&& +#define PRIM_LOG 0&& +#else +#define WARN_LOG printf +#define PRIM_LOG if (conf.log & 0x00000010) GS_LOG +#endif + +#ifndef GREG_LOG +#define GREG_LOG 0&& +#endif +#ifndef PRIM_LOG +#define PRIM_LOG 0&& +#endif +#ifndef WARN_LOG +#define WARN_LOG 0&& +#endif + +#define REG64(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + struct { \ + +#define REG128(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + struct { \ + +#define REG64_(prefix, name) REG64(prefix##name) +#define REG128_(prefix, name) REG128(prefix##name) + +#define REG_END }; }; +#define REG_END2 }; + +#define REG64_SET(name) \ +union name \ +{ \ + u64 i64; \ + u32 ai32[2]; \ + +#define REG128_SET(name)\ +union name \ +{ \ + u64 ai64[2]; \ + u32 ai32[4]; \ + +#define REG_SET_END }; + +REG64_(GSReg, BGCOLOR) + u32 R:8; + u32 G:8; + u32 B:8; + u32 _PAD1:8; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, BUSDIR) + u32 DIR:1; + u32 _PAD1:31; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, CSR) + u32 SIGNAL:1; + u32 FINISH:1; + u32 HSINT:1; + u32 VSINT:1; + u32 EDWINT:1; + u32 ZERO1:1; + u32 ZERO2:1; + u32 _PAD1:1; + u32 FLUSH:1; + u32 RESET:1; + u32 _PAD2:2; + u32 NFIELD:1; + u32 FIELD:1; + u32 FIFO:2; + u32 REV:8; + u32 ID:8; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, DISPFB) // (-1/2) + u32 FBP:9; + u32 FBW:6; + u32 PSM:5; + u32 _PAD:12; + u32 DBX:11; + u32 DBY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, DISPLAY) // (-1/2) + u32 DX:12; + u32 DY:11; + u32 MAGH:4; + u32 MAGV:2; + u32 _PAD:3; + u32 DW:12; + u32 DH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTBUF) + u32 EXBP:14; + u32 EXBW:6; + u32 FBIN:2; + u32 WFFMD:1; + u32 EMODA:2; + u32 EMODC:2; + u32 _PAD1:5; + u32 WDX:11; + u32 WDY:11; + u32 _PAD2:10; +REG_END + +REG64_(GSReg, EXTDATA) + u32 SX:12; + u32 SY:11; + u32 SMPH:4; + u32 SMPV:2; + u32 _PAD1:3; + u32 WW:12; + u32 WH:11; + u32 _PAD2:9; +REG_END + +REG64_(GSReg, EXTWRITE) + u32 WRITE; + u32 _PAD2:32; +REG_END + +REG64_(GSReg, IMR) + u32 _PAD1:8; + u32 SIGMSK:1; + u32 FINISHMSK:1; + u32 HSMSK:1; + u32 VSMSK:1; + u32 EDWMSK:1; + u32 _PAD2:19; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, PMODE) + u32 EN1:1; + u32 EN2:1; + u32 CRTMD:3; + u32 MMOD:1; + u32 AMOD:1; + u32 SLBG:1; + u32 ALP:8; + u32 _PAD:16; + u32 _PAD1:32; +REG_END + +REG64_(GSReg, SIGLBLID) + u32 SIGID:32; + u32 LBLID:32; +REG_END + +REG64_(GSReg, SMODE1) + u32 RC:3; + u32 LC:7; + u32 T1248:2; + u32 SLCK:1; + u32 CMOD:2; + u32 EX:1; + u32 PRST:1; + u32 SINT:1; + u32 XPCK:1; + u32 PCK2:2; + u32 SPML:4; + u32 GCONT:1; + u32 PHS:1; + u32 PVS:1; + u32 PEHS:1; + u32 PEVS:1; + u32 CLKSEL:2; + u32 NVCK:1; + u32 SLCK2:1; + u32 VCKSEL:2; + u32 VHP:1; + u32 _PAD1:27; +REG_END + +REG64_(GSReg, SMODE2) + u32 INT:1; + u32 FFMD:1; + u32 DPMS:2; + u32 _PAD2:28; + u32 _PAD3:32; +REG_END + +REG64_(GSReg, SIGBLID) + u32 SIGID; + u32 LBLID; +REG_END + +extern u8* g_pBasePS2Mem; +#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000)) +#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010)) +#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020)) +// SRFSH +#define SYNCH1 ((GSRegSYNCH1*)(g_pBasePS2Mem+0x0040)) +#define SYNCH2 ((GSRegSYNCH2*)(g_pBasePS2Mem+0x0050)) +#define SYNCV ((GSRegSYNCV*)(g_pBasePS2Mem+0x0060)) +#define DISPFB1 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0070)) +#define DISPLAY1 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x0080)) +#define DISPFB2 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0090)) +#define DISPLAY2 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x00a0)) +#define EXTBUF ((GSRegEXTBUF*)(g_pBasePS2Mem+0x00b0)) +#define EXTDATA ((GSRegEXTDATA*)(g_pBasePS2Mem+0x00c0)) +#define EXTWRITE ((GSRegEXTWRITE*)(g_pBasePS2Mem+0x00d0)) +#define BGCOLOR ((GSRegBGCOLOR*)(g_pBasePS2Mem+0x00e0)) +#define CSR ((GSRegCSR*)(g_pBasePS2Mem+0x1000)) +#define IMR ((GSRegIMR*)(g_pBasePS2Mem+0x1010)) +#define BUSDIR ((GSRegBUSDIR*)(g_pBasePS2Mem+0x1040)) +#define SIGLBLID ((GSRegSIGBLID*)(g_pBasePS2Mem+0x1080)) + +#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2)) + +// +// sps2tags.h +// +#ifdef _M_AMD64 +#define GET_GIF_REG(tag, reg) \ + (((tag).ai64[1] >> ((reg) << 2)) & 0xf) +#else +#define GET_GIF_REG(tag, reg) \ + (((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf) +#endif + +// +// GIFTag +REG128(GIFTag) + u32 NLOOP:15; + u32 EOP:1; + u32 _PAD1:16; + u32 _PAD2:14; + u32 PRE:1; + u32 PRIM:11; + u32 FLG:2; // enum GIF_FLG + u32 NREG:4; + u64 REGS:64; +REG_END + +typedef struct { + int x, y, w, h; +} Rect; + +typedef struct { + int x, y; +} Point; + +typedef struct { + int x0, y0; + int x1, y1; +} Rect2; + +typedef struct { + int x, y, c; +} PointC; + +#define GSOPTION_FULLSCREEN 0x2 +#define GSOPTION_TGASNAP 0x4 +#define GSOPTION_CAPTUREAVI 0x8 + +#define GSOPTION_WINDIMS 0x30 +#define GSOPTION_WIN640 0x00 +#define GSOPTION_WIN800 0x10 +#define GSOPTION_WIN1024 0x20 +#define GSOPTION_WIN1280 0x30 + +#define GSOPTION_WIREFRAME 0x100 +#define GSOPTION_LOADED 0x8000 + +typedef struct { + int interlace; + int aa; // antialiasing 0 - off, 1 - 2x, 2 - 4x + int bilinear; // set to enable bilinear support + u32 options; + u32 gamesettings; // default game settings + int width, height; + int winstyle; // window style before full screen + int mrtdepth; // write color in render target +#ifdef GS_LOG + u32 log; +#endif +} GSconf; + +struct VertexGPU +{ + s16 x, y, f, resv0; // note: xy is 12d3 + u32 rgba; + u32 z; + float s, t, q; +}; + +struct Vertex +{ + u16 x, y, f, resv0; // note: xy is 12d3 + u32 rgba; + u32 z; + float s, t, q; + u16 u, v; +}; + +extern int g_GameSettings; +extern GSconf conf; +extern int ppf; + +#define PSMCT32 0 +#define PSMCT24 1 +#define PSMCT16 2 +#define PSMCT16S 10 +#define PSMT8 19 +#define PSMT4 20 +#define PSMT8H 27 +#define PSMT4HL 36 +#define PSMT4HH 44 +#define PSMT32Z 48 +#define PSMT24Z 49 +#define PSMT16Z 50 +#define PSMT16SZ 58 + +#define PSMT_ISCLUT(psm) (((psm)&0x7)>2) +#define PSMT_IS16BIT(psm) (((psm)&7)==2||((psm)&7)==10) + +typedef struct { + int nloop; + int eop; + int nreg; +} tagInfo; + +typedef union { + s64 SD; + u64 UD; + s32 SL[2]; + u32 UL[2]; + s16 SS[4]; + u16 US[4]; + s8 SC[8]; + u8 UC[8]; +} reg64; + +/* general purpose regs structs */ +typedef struct { + int fbp; + int fbw; + int fbh; + int psm; + u32 fbm; +} frameInfo; + +typedef struct { + u16 prim; + + union { + struct { + u16 iip : 1; + u16 tme : 1; + u16 fge : 1; + u16 abe : 1; + u16 aa1 : 1; + u16 fst : 1; + u16 ctxt : 1; + u16 fix : 1; + u16 resv : 8; + }; + u16 _val; + }; +} primInfo; + +extern primInfo *prim; + +typedef union { + struct { + u32 ate : 1; + u32 atst : 3; + u32 aref : 8; + u32 afail : 2; + u32 date : 1; + u32 datm : 1; + u32 zte : 1; + u32 ztst : 2; + u32 resv : 13; + }; + u32 _val; +} pixTest; + +typedef struct { + int bp; + int bw; + int psm; +} bufInfo; + +typedef struct { + int tbp0; + int tbw; + int cbp; + u16 tw, th; + u8 psm; + u8 tcc; + u8 tfx; + u8 cpsm; + u8 csm; + u8 csa; + u8 cld; +} tex0Info; + +#define TEX_MODULATE 0 +#define TEX_DECAL 1 +#define TEX_HIGHLIGHT 2 +#define TEX_HIGHLIGHT2 3 + +typedef struct { + int lcm; + int mxl; + int mmag; + int mmin; + int mtba; + int l; + int k; +} tex1Info; + +typedef struct { + int wms; + int wmt; + int minu; + int maxu; + int minv; + int maxv; +} clampInfo; + +typedef struct { + int cbw; + int cou; + int cov; +} clutInfo; + +typedef struct { + int tbp[3]; + int tbw[3]; +} miptbpInfo; + +typedef struct { + u16 aem; + u8 ta[2]; + float fta[2]; +} texaInfo; + +typedef struct { + int sx; + int sy; + int dx; + int dy; + int dir; +} trxposInfo; + +typedef struct { + union { + struct { + u8 a : 2; + u8 b : 2; + u8 c : 2; + u8 d : 2; + }; + u8 abcd; + }; + + u8 fix : 8; +} alphaInfo; + +typedef struct { + u16 zbp; // u16 address / 64 + u8 psm; + u8 zmsk; +} zbufInfo; + +typedef struct { + int fba; +} fbaInfo; + +typedef struct { + int mode; + int regn; + u64 regs; + tagInfo tag; +} pathInfo; + +typedef struct { + Vertex gsvertex[3]; + u32 rgba; + float q; + Vertex vertexregs; + + int primC; // number of verts current storing + int primIndex; // current prim index + int nTriFanVert; + + int prac; + int dthe; + int colclamp; + int fogcol; + int smask; + int pabe; + u64 buff[2]; + int buffsize; + int cbp[2]; // internal cbp registers + + u32 CSRw; + + primInfo _prim[2]; + bufInfo srcbuf, srcbufnew; + bufInfo dstbuf, dstbufnew; + + clutInfo clut; + + texaInfo texa; + trxposInfo trxpos, trxposnew; + + int imageWtemp, imageHtemp; + + int imageTransfer; + int imageWnew, imageHnew, imageX, imageY, imageEndX, imageEndY; + + pathInfo path1; + pathInfo path2; + pathInfo path3; + +} GSinternal; + +extern GSinternal gs; + +extern FILE *gsLog; + +void __Log(char *fmt, ...); +void ERROR_LOG(char *fmt, ...); + +void LoadConfig(); +void SaveConfig(); + +extern void (*GSirq)(); + +void *SysLoadLibrary(char *lib); // Loads Library +void *SysLoadSym(void *lib, char *sym); // Loads Symbol from Library +char *SysLibError(); // Gets previous error loading sysbols +void SysCloseLibrary(void *lib); // Closes Library +void SysMessage(char *fmt, ...); + +extern "C" void * memcpy_amd(void *dest, const void *src, size_t n); +extern "C" u8 memcmp_mmx(const void *dest, const void *src, int n); + +template +class CInterfacePtr +{ +public: + inline CInterfacePtr() : ptr(NULL) {} + inline explicit CInterfacePtr(T* newptr) : ptr(newptr) { if ( ptr != NULL ) ptr->AddRef(); } + inline ~CInterfacePtr() { if( ptr != NULL ) ptr->Release(); } + + inline T* operator* () { assert( ptr != NULL); return *ptr; } + inline T* operator->() { return ptr; } + inline T* get() { return ptr; } + + inline void release() { + if( ptr != NULL ) { ptr->Release(); ptr = NULL; } + } + + inline operator T*() { return ptr; } + + inline bool operator==(T* rhs) { return ptr == rhs; } + inline bool operator!=(T* rhs) { return ptr != rhs; } + + inline CInterfacePtr& operator= (T* newptr) { + if( ptr != NULL ) ptr->Release(); + ptr = newptr; + + if( ptr != NULL ) ptr->AddRef(); + return *this; + } + +private: + T* ptr; +}; + +#define RGBA32to16(c) \ + (u16)((((c) & 0x000000f8) >> 3) | \ + (((c) & 0x0000f800) >> 6) | \ + (((c) & 0x00f80000) >> 9) | \ + (((c) & 0x80000000) >> 16)) \ + +#define RGBA16to32(c) \ + (((c) & 0x001f) << 3) | \ + (((c) & 0x03e0) << 6) | \ + (((c) & 0x7c00) << 9) | \ + (((c) & 0x8000) ? 0xff000000 : 0) \ + +// converts float16 [0,1] to BYTE [0,255] (assumes value is in range, otherwise will take lower 8bits) +// f is a u16 +__forceinline u16 Float16ToBYTE(u16 f) { + //assert( !(f & 0x8000) ); + if( f & 0x8000 ) return 0; + + u16 d = ((((f&0x3ff)|0x400)*255)>>(10-((f>>10)&0x1f)+15)); + return d > 255 ? 255 : d; +} + +__forceinline u16 Float16ToALPHA(u16 f) { + //assert( !(f & 0x8000) ); + if( f & 0x8000 ) return 0; + + // round up instead of down (crash and burn), too much and charlie breaks + u16 d = (((((f&0x3ff)|0x400))*255)>>(10-((f>>10)&0x1f)+15)); + d = (d)>>1; + return d > 255 ? 255 : d; +} + +#ifndef COLOR_ARGB +#define COLOR_ARGB(a,r,g,b) \ + ((u32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) +#endif + +// assumes that positive in [1,2] (then extracts fraction by just looking at the specified bits) +#define Float16ToBYTE_2(f) ((u8)(*(u16*)&f>>2)) +#define Float16To5BIT(f) (Float16ToBYTE(f)>>3) + +#define Float16Alpha(f) (((*(u16*)&f&0x7c00)>=0x3900)?0x8000:0) // alpha is >= 1 + +// converts an array of 4 u16s to a u32 color +// f is a pointer to a u16 +#define Float16ToARGB(f) COLOR_ARGB(Float16ToALPHA(f.w), Float16ToBYTE(f.x), Float16ToBYTE(f.y), Float16ToBYTE(f.z)); + +#define Float16ToARGB16(f) (Float16Alpha(f.w)|(Float16To5BIT(f.x)<<10)|(Float16To5BIT(f.y)<<5)|Float16To5BIT(f.z)) + +// used for Z values +#define Float16ToARGB_Z(f) COLOR_ARGB((u32)Float16ToBYTE_2(f.w), Float16ToBYTE_2(f.x), Float16ToBYTE_2(f.y), Float16ToBYTE_2(f.z)) +#define Float16ToARGB16_Z(f) ((Float16ToBYTE_2(f.y)<<8)|Float16ToBYTE_2(f.z)) + + +inline float Clamp(float fx, float fmin, float fmax) +{ + if( fx < fmin ) return fmin; + return fx > fmax ? fmax : fx; +} + +// IMPORTANT: For every Reigster there must be an End +void DVProfRegister(char* pname); // first checks if this profiler exists in g_listProfilers +void DVProfEnd(u32 dwUserData); +void DVProfWrite(char* pfilename, u32 frames = 0); +void DVProfClear(); // clears all the profilers + +#define DVPROFILE +#ifdef DVPROFILE + +class DVProfileFunc +{ +public: + u32 dwUserData; + DVProfileFunc(char* pname) { DVProfRegister(pname); dwUserData = 0; } + DVProfileFunc(char* pname, u32 dwUserData) : dwUserData(dwUserData) { DVProfRegister(pname); } + ~DVProfileFunc() { DVProfEnd(dwUserData); } +}; + +#else + +class DVProfileFunc +{ +public: + u32 dwUserData; + __forceinline DVProfileFunc(char* pname) {} + __forceinline DVProfileFunc(char* pname, u32 dwUserData) { } + ~DVProfileFunc() {} +}; + +#endif + +#endif diff --git a/plugins/gs/zerogs/opengl/GSmain.cpp b/plugins/gs/zerogs/opengl/GSmain.cpp new file mode 100644 index 0000000..ab36e2d --- /dev/null +++ b/plugins/gs/zerogs/opengl/GSmain.cpp @@ -0,0 +1,1370 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if defined(_WIN32) +#include +#include "Win32.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +using namespace std; + +#include "GS.h" +#include "Mem.h" +#include "Regs.h" + +#include "zerogs.h" +#include "targets.h" +#include "ZeroGSShaders/zerogsshaders.h" + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +GSinternal gs; +char GStitle[256]; +GSconf conf; +int ppf; +primInfo *prim; +FILE *gsLog; +int g_GSMultiThreaded = 0; +void (*GSirq)(); +u8* g_pBasePS2Mem = NULL; +int g_TransferredToGPU = 0; +string s_strIniPath="inis/zerogs.ini"; + +static BOOL g_bHidden = 0; +int g_GameSettings = 0; + +// statistics +u32 g_nGenVars = 0, g_nTexVars = 0, g_nAlphaVars = 0, g_nResolve = 0; + +#define VER 96 +const unsigned char version = PS2E_GS_VERSION; +unsigned char revision = 0; // revision and build gives plugin version +unsigned char build = VER; +unsigned char minor = 2; + +#ifdef _DEBUG +char *libraryName = "ZeroGS OpenGL (Debug) "; +#elif defined(RELEASE_TO_PUBLIC) +char *libraryName = "ZeroGS KOSMOS OpenGL "; +#else +char *libraryName = "ZeroGS OpenGL (Dev) "; +#endif + +static const char* s_aa[3] = { "AA none |", "AA 2x |", "AA 4x |" }; +static const char* pbilinear[] = { "off", "normal", "forced" }; + +extern GIFRegHandler g_GIFPackedRegHandlers[]; +extern GIFRegHandler g_GIFRegHandlers[]; +GIFRegHandler g_GIFTempRegHandlers[16] = {0}; +extern int g_nPixelShaderVer; +extern int g_nFrameRender; +extern int g_nFramesSkipped; + +#ifdef RELEASE_TO_PUBLIC +#define g_bWriteProfile 0 +#else +BOOL g_bWriteProfile = 0; +#endif + +int s_frameskipping = 0; +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_GS; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build | (minor << 24); +} + +static u64 luPerfFreq; + +#ifdef _WIN32 + +HWND GShwnd = NULL; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "GSsoftdx Msg", 0); +} +#else + +GLWindow GLWin; + +#endif + +#ifdef GS_LOG +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.log) return; + + va_start(list, fmt); + vfprintf(gsLog, fmt, list); + va_end(list); +} +#endif + +void ERROR_LOG(char *fmt, ...) { + va_list list; + + va_start(list, fmt); + fprintf(gsLog, "ZeroGS: "); + vfprintf(gsLog, fmt, list); + va_end(list); + + va_start(list, fmt); + printf("ZeroGS: "); + vprintf(fmt, list); + va_end(list); +} + +void CALLBACK GSsetBaseMem(void* pmem) { + g_pBasePS2Mem = (u8*)pmem; +} + +extern int VALIDATE_THRESH; + +void CALLBACK GSsetGameCRC(int crc, int options) +{ + VALIDATE_THRESH = 8; + g_GameSettings = conf.gamesettings|options; + conf.mrtdepth = 0;//!(conf.gamesettings&GAME_DISABLEMRTDEPTH); + + if( !conf.mrtdepth ) { + ERROR_LOG("Disabling MRT depth writing\n"); + } + + switch(crc) { + case 0x54A548B4: // crash n burn + // overbright + break; + + case 0x7D2FE035: // espgaluda (j) + VALIDATE_THRESH = 24; + //g_GameSettings |= GAME_BIGVALIDATE; + break; + } +} + +void CALLBACK GSsetFrameSkip(int frameskip) +{ + s_frameskipping |= frameskip; + if( frameskip && g_nFrameRender > 1 ) { + + for(int i = 0; i < 16; ++i) { + g_GIFPackedRegHandlers[i] = GIFPackedRegHandlerNOP; + } + + // still keep certain handlers + g_GIFPackedRegHandlers[6] = GIFRegHandlerTEX0_1; + g_GIFPackedRegHandlers[7] = GIFRegHandlerTEX0_2; + g_GIFPackedRegHandlers[14] = GIFPackedRegHandlerA_D; + + g_GIFRegHandlers[0] = GIFRegHandlerNOP; + g_GIFRegHandlers[1] = GIFRegHandlerNOP; + g_GIFRegHandlers[2] = GIFRegHandlerNOP; + g_GIFRegHandlers[3] = GIFRegHandlerNOP; + g_GIFRegHandlers[4] = GIFRegHandlerNOP; + g_GIFRegHandlers[5] = GIFRegHandlerNOP; + g_GIFRegHandlers[12] = GIFRegHandlerNOP; + g_GIFRegHandlers[13] = GIFRegHandlerNOP; + g_GIFRegHandlers[26] = GIFRegHandlerNOP; + g_GIFRegHandlers[27] = GIFRegHandlerNOP; + g_nFrameRender = 0; + } + else if( !frameskip && g_nFrameRender <= 0 ) { + g_nFrameRender = 1; + + if( g_GIFTempRegHandlers[0] == NULL ) return; // not init yet + + // restore + memcpy(g_GIFPackedRegHandlers, g_GIFTempRegHandlers, sizeof(g_GIFTempRegHandlers)); + + g_GIFRegHandlers[0] = GIFRegHandlerPRIM; + g_GIFRegHandlers[1] = GIFRegHandlerRGBAQ; + g_GIFRegHandlers[2] = GIFRegHandlerST; + g_GIFRegHandlers[3] = GIFRegHandlerUV; + g_GIFRegHandlers[4] = GIFRegHandlerXYZF2; + g_GIFRegHandlers[5] = GIFRegHandlerXYZ2; + g_GIFRegHandlers[12] = GIFRegHandlerXYZF3; + g_GIFRegHandlers[13] = GIFRegHandlerXYZ2; + g_GIFRegHandlers[26] = GIFRegHandlerPRMODECONT; + g_GIFRegHandlers[27] = GIFRegHandlerPRMODE; + } +} + +void CALLBACK GSreset() { + + memset(&gs, 0, sizeof(gs)); + + ZeroGS::GSStateReset(); + + gs.prac = 1; + prim = &gs._prim[0]; + gs.nTriFanVert = -1; + gs.imageTransfer = -1; + gs.q = 1; +} + +void CALLBACK GSgifSoftReset(int mask) +{ + if( mask & 1 ) memset(&gs.path1, 0, sizeof(gs.path1)); + if( mask & 2 ) memset(&gs.path2, 0, sizeof(gs.path2)); + if( mask & 4 ) memset(&gs.path3, 0, sizeof(gs.path3)); + gs.imageTransfer = -1; + gs.q = 1; + gs.nTriFanVert = -1; +} + +s32 CALLBACK GSinit() +{ + memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers)); + +#ifdef GS_LOG + gsLog = fopen("logs/gsLog.txt", "w"); + if (gsLog == NULL) { + gsLog = fopen("gsLog.txt", "w"); + if (gsLog == NULL) { + SysMessage("Can't create gsLog.txt"); return -1; + } + } + setvbuf(gsLog, NULL, _IONBF, 0); + GS_LOG("GSinit\n"); +#endif + +#ifdef __LINUX__ + char strcurdir[256]; + getcwd(strcurdir, 256); + s_strIniPath = strcurdir; + s_strIniPath += "/inis/zerogs.ini"; +#endif + + GSreset(); + +#ifdef GS_LOG + GS_LOG("GSinit ok\n"); +#endif + + return 0; +} + +void CALLBACK GSshutdown() +{ +#ifdef GS_LOG + fclose(gsLog); +#endif +} + +// keyboard functions +void OnKeyboardF5(int shift) +{ + char strtitle[256]; + if( shift ) { + if( g_nPixelShaderVer == SHADER_REDUCED ) { + conf.bilinear = 0; + sprintf(strtitle, "reduced shaders don't support bilinear filtering"); + } + else { + conf.bilinear = (conf.bilinear+1)%3; + sprintf(strtitle, "bilinear filtering - %s", pbilinear[conf.bilinear]); + } + } + else { + conf.interlace++; + if( conf.interlace > 2 ) conf.interlace = 0; + if( conf.interlace < 2 ) sprintf(strtitle, "interlace on - mode %d", conf.interlace); + else sprintf(strtitle, "interlace off"); + } + + ZeroGS::AddMessage(strtitle); + SaveConfig(); +} + +void OnKeyboardF6(int shift) +{ + char strtitle[256]; + if( shift ) { + conf.options ^= GSOPTION_WIREFRAME; + glPolygonMode(GL_FRONT_AND_BACK, (conf.options&GSOPTION_WIREFRAME)?GL_LINE:GL_FILL); + sprintf(strtitle, "wireframe rendering - %s", (conf.options&GSOPTION_WIREFRAME)?"on":"off"); + } + else { + conf.aa++; + if( conf.aa > 2 ) conf.aa = 0; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa]); + ZeroGS::SetAA(conf.aa); + } + + ZeroGS::AddMessage(strtitle); + SaveConfig(); +} + +void OnKeyboardF7(int shift) +{ + char strtitle[256]; + if( shift ) { + extern BOOL g_bDisplayFPS; + g_bDisplayFPS ^= 1; + } + else { + conf.options ^= GSOPTION_CAPTUREAVI; + if( conf.options & GSOPTION_CAPTUREAVI ) ZeroGS::StartCapture(); + else ZeroGS::StopCapture(); + + sprintf(strtitle, "capture avi (zerogs_dump.avi) - %s", (conf.options&GSOPTION_CAPTUREAVI) ? "on" : "off"); + ZeroGS::AddMessage(strtitle); + SaveConfig(); + } +} + +void OnKeyboardF9(int shift) +{ + char strtitle[256]; + g_GameSettings ^= GAME_FFXHACK; + sprintf(strtitle, "ffx hack - %s", (g_GameSettings&GAME_FFXHACK) ? "on" : "off"); + ZeroGS::AddMessage(strtitle); + //SaveConfig(); +} + +#ifdef _WIN32 + +#ifdef _DEBUG +HANDLE g_hCurrentThread = NULL; +#endif + +LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + static int nWindowWidth = 0, nWindowHeight = 0; + + switch( msg ) { + case WM_DESTROY: + PostQuitMessage( 0 ); + return 0; + + case WM_KEYDOWN: +// switch(wParam) { +// case VK_ESCAPE: +// SendMessage(hWnd, WM_DESTROY, 0L, 0L); +// break; +// } + break; + + case WM_ACTIVATE: + + if( wParam != WA_INACTIVE ) { + //printf("restoring device\n"); + ZeroGS::Restore(); + } + + break; + + case WM_SIZE: + nWindowWidth = lParam&0xffff; + nWindowHeight = lParam>>16; + ZeroGS::ChangeWindowSize(nWindowWidth, nWindowHeight); + + break; + + case WM_SIZING: + // if button is 0, then just released so can resize + if( GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON) ) { + ZeroGS::SetChangeDeviceSize(nWindowWidth, nWindowHeight); + } + break; + + case WM_SETCURSOR: + SetCursor(NULL); + break; + } + + return DefWindowProc( hWnd, msg, wParam, lParam ); +} + +extern HINSTANCE hInst; +void CALLBACK GSconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); + + if( g_nPixelShaderVer == SHADER_REDUCED ) + conf.bilinear = 0; +} + + +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) { + + g_GSMultiThreaded = multithread; + +#ifdef GS_LOG + GS_LOG("GSopen\n"); +#endif + +#ifdef _DEBUG + g_hCurrentThread = GetCurrentThread(); +#endif + + assert( GSirq != NULL ); + LoadConfig(); + + strcpy(GStitle, Title); + + RECT rc, rcdesktop; + rc.left = 0; rc.top = 0; + rc.right = conf.width; rc.bottom = conf.height; + + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, + GetModuleHandle(NULL), NULL, NULL, NULL, NULL, + "PS2EMU_ZEROGS", NULL }; + RegisterClassEx( &wc ); + + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + GShwnd = CreateWindow( "PS2EMU_ZEROGS", "ZeroGS", WS_OVERLAPPEDWINDOW, + (rcdesktop.right-(rc.right-rc.left))/2, (rcdesktop.bottom-(rc.bottom-rc.top))/2, + rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, wc.hInstance, NULL ); + + if(GShwnd == NULL) { + GS_LOG("Failed to create window. Exiting..."); + return -1; + } + + if( pDsp != NULL ) + *(HWND*)pDsp = GShwnd; + + ERROR_LOG("creating\n"); + //if (conf.record) recOpen(); + if( !ZeroGS::Create(conf.width, conf.height) ) + return -1; + + ERROR_LOG("initialization successful\n"); + + if( conf.bilinear == 2 ) { + ZeroGS::AddMessage("bilinear filtering - forced", 1000); + } + else if( conf.bilinear == 1 ) { + ZeroGS::AddMessage("bilinear filtering - normal", 1000); + } + if( conf.aa ) { + char strtitle[64]; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa], 1000); + ZeroGS::AddMessage(strtitle); + } + + ShowWindow( GShwnd, SW_SHOWDEFAULT ); + UpdateWindow( GShwnd ); + //SetForegroundWindow(GShwnd); + SetFocus(GShwnd); + + conf.winstyle = GetWindowLong( GShwnd, GWL_STYLE ); + conf.winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + +#ifdef GS_LOG + GS_LOG("GSopen ok\n"); +#endif + + LARGE_INTEGER temp; + QueryPerformanceFrequency(&temp); + luPerfFreq = temp.QuadPart; + + gs.path1.mode = 0; + gs.path2.mode = 0; + gs.path3.mode = 0; + + return 0; +} + +void ProcessMessages() +{ + MSG msg; + ZeroMemory( &msg, sizeof(msg) ); + while( 1 ) { + if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) + { + switch( msg.message ) { + case WM_KEYDOWN : + if( msg.wParam == VK_F5 ) { + OnKeyboardF5(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F6 ) { + OnKeyboardF6(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F7 ) { + OnKeyboardF7(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_F9 ) { + OnKeyboardF9(GetKeyState(VK_SHIFT)&0x8000); + } + else if( msg.wParam == VK_ESCAPE ) { + + if( conf.options & GSOPTION_FULLSCREEN ) { + // destroy that msg + conf.options &= ~GSOPTION_FULLSCREEN; + conf.winstyle = GetWindowLong( GShwnd, GWL_STYLE ); + conf.winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + ZeroGS::ChangeDeviceSize(conf.width, conf.height); + UpdateWindow(GShwnd); + continue; // so that msg doesn't get sent + } + else { + SendMessage(GShwnd, WM_DESTROY, 0, 0); + g_bHidden = 1; + return; + } + } + + break; + } + + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + else + break; + } + + if( (GetKeyState(VK_MENU)&0x8000) && (GetKeyState(VK_RETURN)&0x8000) ) { + conf.options ^= GSOPTION_FULLSCREEN; + + if( conf.options & GSOPTION_FULLSCREEN ) { + conf.winstyle = GetWindowLong( GShwnd, GWL_STYLE ); + conf.winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style + } + + ZeroGS::SetChangeDeviceSize( + (conf.options&GSOPTION_FULLSCREEN) ? 1280 : conf.width, + (conf.options&GSOPTION_FULLSCREEN) ? 960 : conf.height); + } + +// if( conf.fullscreen && (GetKeyState(VK_ESCAPE)&0x8000)) { +// conf.fullscreen &= ~GSOPTION_FULLSCREEN; +// ZeroGS::SetChangeDeviceSize(conf.width, conf.height); +// } + + //if( conf.interlace && g_nGenVars + g_nTexVars + g_nAlphaVars + g_nResolve == 0 ) + // CSR->FIELD = 0; // 0 should always be the repeating at 0 +} + +#else // linux + +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread) +{ +#ifdef GS_LOG + GS_LOG("GSopen\n"); +#endif + + assert( GSirq != NULL ); + LoadConfig(); + + strcpy(GStitle, Title); + + GLWin.dpy = XOpenDisplay(0); + GLWin.screen = DefaultScreen(GLWin.dpy); + + if( pDsp != NULL ) + *(Display**)pDsp = GLWin.dpy; + + ERROR_LOG("creating\n"); + //if (conf.record) recOpen(); + if( !ZeroGS::Create(conf.width, conf.height) ) + return -1; + + ERROR_LOG("initialization successful\n"); + + if( conf.bilinear == 2 ) { + ZeroGS::AddMessage("bilinear filtering - forced", 1000); + } + else if( conf.bilinear == 1 ) { + ZeroGS::AddMessage("bilinear filtering - normal", 1000); + } + if( conf.aa ) { + char strtitle[64]; + sprintf(strtitle, "anti-aliasing - %s", s_aa[conf.aa], 1000); + ZeroGS::AddMessage(strtitle); + } + +#ifdef GS_LOG + GS_LOG("GSopen ok\n"); +#endif + + gs.path1.mode = 0; + gs.path2.mode = 0; + gs.path3.mode = 0; + luPerfFreq = 1; + + return 0; +} + +void ProcessMessages() +{ + XEvent event; +// KeySym key; +// vector keyevents; + + // check resizing + while(XCheckTypedEvent(GLWin.dpy, ConfigureNotify, &event)) { + if ((event.xconfigure.width != GLWin.width) || (event.xconfigure.height != GLWin.height)) { + ZeroGS::ChangeWindowSize(event.xconfigure.width, event.xconfigure.height); + GLWin.width = event.xconfigure.width; + GLWin.height = event.xconfigure.height; + } + } + +// while (XPending(GLWin.dpy) > 0) { +// XNextEvent(GLWin.dpy, &event); +// keyevents.push_back(event); +// +// switch (event.type) { +// case ConfigureNotify: +// if ((event.xconfigure.width != GLWin.width) || +// (event.xconfigure.height != GLWin.height)) +// { +// ZeroGS::ChangeWindowSize(event.xconfigure.width, event.xconfigure.height); +// GLWin.width = event.xconfigure.width; +// GLWin.height = event.xconfigure.height; +// } +// break; +// default: +// break; +// } +// } +// +// // push back all the key events for the PAD plugins, etc +// for(vector::iterator it = keyevents.begin(); it != keyevents.end(); ++it) +// XPutBackEvent(GLWin.dpy, &(*it)); +} + +#endif // linux + +void CALLBACK GSclose() { + ZeroGS::Destroy(1); + +#ifdef _WIN32 + if( GShwnd != NULL ) { + DestroyWindow(GShwnd); + GShwnd = NULL; + } +#else + if( GLWin.dpy != NULL ) { + XCloseDisplay(GLWin.dpy); + GLWin.dpy = NULL; + } +#endif +} + +void CALLBACK GSirqCallback(void (*callback)()) { + GSirq = callback; +} + +void CALLBACK GSwriteCSR(u32 write) +{ + gs.CSRw = write; +} + +void CALLBACK GSchangeSaveState(int newstate, const char* filename) +{ + char str[255]; + sprintf(str, "save state %d", newstate); + ZeroGS::AddMessage(str); +} + +void CALLBACK GSmakeSnapshot(char *path) +{ + FILE *bmpfile; + char filename[256]; + u32 snapshotnr = 0; + + // increment snapshot value & try to get filename + for (;;) { + snapshotnr++; + + sprintf(filename,"%ssnap%03ld.%s", path, snapshotnr, (conf.options&GSOPTION_TGASNAP)?"bmp":"jpg"); + + bmpfile=fopen(filename,"rb"); + if (bmpfile == NULL) break; + fclose(bmpfile); + } + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) { + char strdir[255]; + +#ifdef _WIN32 + sprintf(strdir, "%s", path); + CreateDirectory(strdir, NULL); +#else + sprintf(strdir, "mkdir %s", path); + system(strdir); +#endif + + if((bmpfile=fopen(filename,"wb"))==NULL) return; + } + + fclose(bmpfile); + + // get the bits + ZeroGS::SaveSnapshot(filename); +} + +int UPDATE_FRAMES = 16; +int g_nFrame = 0; +int g_nRealFrame = 0; + +float fFPS = 0; + +void CALLBACK GSvsync(int interlace) +{ +#ifdef GS_LOG + GS_LOG("\nGSvsync\n\n"); +#endif + + static u32 dwTime = timeGetTime(); + static int nToNextUpdate = 1; + char strtitle[256]; + + GL_REPORT_ERRORD(); + + g_nRealFrame++; + + ZeroGS::RenderCRTC(!interlace); + +#ifndef _WIN32 + //XLockDisplay(GLWin.dpy); +#endif + + ProcessMessages(); + + if( --nToNextUpdate <= 0 ) { + + u32 d = timeGetTime(); + fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d-dwTime,1); + dwTime = d; + g_nFrame += UPDATE_FRAMES; + +#ifdef RELEASE_TO_PUBLIC + const char* g_pShaders[4] = { "full", "reduced", "accurate", "accurate-reduced" }; + + sprintf(strtitle, "ZeroGS KOSMOS 0.%d.%d %.1f fps | %s%s%s%s %s (%.1f)", build, minor, fFPS, + (conf.interlace < 2) ? "interlace | " : "", + conf.bilinear ? (conf.bilinear==2?"forced bilinear | ":"bilinear | ") : "", + conf.aa ? s_aa[conf.aa] : "", + (g_GameSettings&GAME_FFXHACK) ? "ffxhack | " : "", + g_pShaders[g_nPixelShaderVer], (ppf&0xfffff)/(float)UPDATE_FRAMES); +#else + sprintf(strtitle, "%d | %.1f fps (sk:%d%%) | g: %.1f, t: %.1f, a: %.1f, r: %.1f | p: %.1f | tex: %d %d (%d kbpf)", g_nFrame, fFPS, + 100*g_nFramesSkipped/g_nFrame, + g_nGenVars/(float)UPDATE_FRAMES, g_nTexVars/(float)UPDATE_FRAMES, g_nAlphaVars/(float)UPDATE_FRAMES, + g_nResolve/(float)UPDATE_FRAMES, (ppf&0xfffff)/(float)UPDATE_FRAMES, + ZeroGS::g_MemTargs.listTargets.size(), ZeroGS::g_MemTargs.listClearedTargets.size(), g_TransferredToGPU>>10); + //_snprintf(strtitle, 512, "%x %x", *(int*)(g_pbyGSMemory + 256 * 0x3e0c + 4), *(int*)(g_pbyGSMemory + 256 * 0x3e04 + 4)); + +#endif + +// if( g_nFrame > 100 && fFPS > 60.0f ) { +// printf("set profile\n"); +// g_bWriteProfile = 1; +// } + +#ifdef _WIN32 + if( !(conf.options&GSOPTION_FULLSCREEN) ) + SetWindowText(GShwnd, strtitle); +#else // linux + XTextProperty prop; + memset(&prop, 0, sizeof(prop)); + char* ptitle = strtitle; + if( XStringListToTextProperty(&ptitle, 1, &prop) ) + XSetWMName(GLWin.dpy, GLWin.win, &prop); + XFree(prop.value); +#endif + + if( fFPS < 16 ) UPDATE_FRAMES = 4; + else if( fFPS < 32 ) UPDATE_FRAMES = 8; + else UPDATE_FRAMES = 16; + + nToNextUpdate = UPDATE_FRAMES; + + g_TransferredToGPU = 0; + g_nGenVars = 0; + g_nTexVars = 0; + g_nAlphaVars = 0; + g_nResolve = 0; + ppf = 0; + g_nFramesSkipped = 0; + } + +#ifndef RELEASE_TO_PUBLIC + if( g_bWriteProfile ) { + //g_bWriteProfile = 0; + DVProfWrite("prof.txt", UPDATE_FRAMES); + DVProfClear(); + } +#endif + GL_REPORT_ERRORD(); + +#ifndef _WIN32 + //XUnlockDisplay(GLWin.dpy); +#endif +} + +void GIFtag(pathInfo *path, u32 *data) { + + path->tag.nloop = data[0] & 0x7fff; + path->tag.eop = (data[0] >> 15) & 0x1; + u32 tagpre = (data[1] >> 14) & 0x1; + u32 tagprim = (data[1] >> 15) & 0x7ff; + u32 tagflg = (data[1] >> 26) & 0x3; + path->tag.nreg = (data[1] >> 28)<<2; + if (path->tag.nreg == 0) path->tag.nreg = 64; + + gs.q = 1; + +#ifdef GS_LOG +// GS_LOG("GIFtag: %8.8lx_%8.8lx_%8.8lx_%8.8lx: EOP=%d, NLOOP=%x, FLG=%x, NREG=%d, PRE=%d\n", +// data[3], data[2], data[1], data[0], +// path->tag.eop, path->tag.nloop, tagflg, path->tag.nreg, tagpre); +#endif + + path->mode = tagflg+1; + + switch (tagflg) { + case 0x0: + path->regs = *(u64 *)(data+2); + path->regn = 0; + if (tagpre) + GIFRegHandlerPRIM((u32*)&tagprim); + + break; + + case 0x1: + path->regs = *(u64 *)(data+2); + path->regn = 0; + + break; + } +} + +void _GSgifPacket(pathInfo *path, u32 *pMem) { // 128bit + + int reg = (int)((path->regs >> path->regn) & 0xf); + g_GIFPackedRegHandlers[reg](pMem); + + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + path->tag.nloop--; + } +} + +void _GSgifRegList(pathInfo *path, u32 *pMem) { // 64bit + int reg; + + reg = (int)((path->regs >> path->regn) & 0xf); + + g_GIFRegHandlers[reg](pMem); + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + path->tag.nloop--; + } +} + +static pathInfo* s_pLastPath = &gs.path3; +void CALLBACK GSgetLastTag(u64* ptag) +{ + int mode = s_pLastPath->mode > 0 ? s_pLastPath->mode-1 : 0; + *(u32*)ptag = s_pLastPath->tag.nloop|(s_pLastPath->tag.eop<<15); + *((u32*)ptag+1) = (mode<<26)|(s_pLastPath->regn<<28); +} + +void _GSgifTransfer(pathInfo *path, u32 *pMem, u32 size) +{ +#ifdef _WIN32 + assert( g_hCurrentThread == GetCurrentThread() ); +#endif + + s_pLastPath = path; + + while(size > 0) + { + //LOG(_T("Transfer(%08x, %d) START\n"), pMem, size); + if(path->tag.nloop == 0) { + GIFtag(path, pMem); + pMem+= 4; + size--; + + if(path->tag.nloop == 0 ) { + //bAfter0Tag = 1; + if( path == &gs.path1 ) { + // ffx hack + if( g_GameSettings & GAME_FFXHACK ) { + if( path->tag.eop ) + return; + continue; + } + + return; + } + + if( !path->tag.eop ) { + //printf("contuing from eop\n"); + continue; + } + + break; + } +// else { +// if( bAfter0Tag ) { +// // hack!! if all 0s, then break +// if( pMem[-3] == 0 && pMem[-2] == 0 ) { +// path->tag.nloop = 0; +// return; +// } +// } +// } + } + + switch(path->mode) { + case 1: // PACKED + { +// if( path->tag.nreg == 9 && gs.regs == 0x412412412L && gs.primC == 0) { +// // draw 3 points +// } + + //__Log("%8.8x%8.8x %d\n", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4); + assert( path->tag.nloop > 0 ); + for(; size > 0; size--, pMem += 4) + { + int reg = (int)((path->regs >> path->regn) & 0xf); + g_GIFPackedRegHandlers[reg](pMem); + + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + if( path->tag.nloop-- <= 1 ) { + size--; + pMem += 4; + break; + } + } + } + break; + } + case 2: // REGLIST + { + //__Log("%8.8x%8.8x %d L\n", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4); + assert( path->tag.nloop > 0 ); + size *= 2; + for(; size > 0; pMem+= 2, size--) + { + int reg = (int)((path->regs >> path->regn) & 0xf); + g_GIFRegHandlers[reg](pMem); + path->regn += 4; + if (path->tag.nreg == path->regn) { + path->regn = 0; + if( path->tag.nloop-- <= 1 ) { + size--; + pMem += 2; + break; + } + } + } + + if( size & 1 ) pMem += 2; + size /= 2; + break; + } + case 3: // GIF_IMAGE (FROM_VFRAM) + { + if(gs.imageTransfer >= 0 && gs.imageTransfer <= 1) + { + int process = min((int)size, path->tag.nloop); + + if( process > 0 ) { + if( gs.imageTransfer ) ZeroGS::TransferLocalHost(pMem, process); + else ZeroGS::TransferHostLocal(pMem, process*4); + + path->tag.nloop -= process; + pMem += process*4; size -= process; + + assert( size == 0 || path->tag.nloop == 0 ); + } + break; + } + else { + // simulate + int process = min((int)size, path->tag.nloop); + path->tag.nloop -= process; + pMem += process*4; size -= process; + } + + break; + } + default: + GS_LOG("*** WARNING **** Unexpected GIFTag flag\n"); + assert(0); +// ZeroGS::TransferLocalHost(pMem, size); +// pMem+= size*4; path->tag.nloop-= size; +// size = 0; path->mode = 0; + path->tag.nloop = 0; + break; + } + + if( path == &gs.path1 && path->tag.eop ) + return; + } +} + +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size) +{ +#ifdef GS_LOG + //GS_LOG("GSgifTransfer2 size = %lx (mode %d, gs.path2.tag.nloop = %d)\n", size, gs.path2.mode, gs.path2.tag.nloop); +#endif + + // if(!g_GSMultiThreaded) +// CSR->FINISH = 0; + //DVProfileFunc _pf("Transf2"); + + //assert( ((u32)pMem & 0xf) == 0 ); + _GSgifTransfer(&gs.path2, pMem, size); +} + +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size) +{ +#ifdef GS_LOG + //GS_LOG("GSgifTransfer3 size = %lx (mode %d, gs.path3.tag.nloop = %d)\n", size, gs.path3.mode, gs.path3.tag.nloop); +#endif + +// if(!g_GSMultiThreaded) +// CSR->FINISH = 0; + //DVProfileFunc _pf("Transf3"); + + //assert( ((u32)pMem & 0xf) == 0 ); + _GSgifTransfer(&gs.path3, pMem, size); +} + +static int s_trcount = 0; +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr) +{ + pathInfo *path = &gs.path1; + +#ifdef GS_LOG + //GS_LOG("GSgifTransfer1 0x%x (mode %d)\n", addr, path->mode); +#endif + + addr &= 0x3fff; + +#ifdef _DEBUG + PRIM_LOG("count :%d\n", s_trcount); + s_trcount++; + +// for(int i = addr; i < 0x4000; i += 16 ) { +// u32* mem = (u32*)((u8*)pMem+i); +// PRIM_LOG("%x: %x %x %x %x\n", i, mem[0], mem[1], mem[2], mem[3]); +// } +#endif + + gs.path1.tag.nloop = 0; + gs.path1.tag.eop = 0; + _GSgifTransfer(&gs.path1, (u32*)((u8*)pMem+addr), (0x4000-addr)/16); + + if( !gs.path1.tag.eop && gs.path1.tag.nloop > 0 ) { + assert( (addr&0xf) == 0 ); //BUG + gs.path1.tag.nloop = 0; + ERROR_LOG("Transfer1 - 2\n"); + //_GSgifTransfer(&gs.path1, (u32*)((u8*)pMem+0x4000-addr), addr/16); + return; + } +} + +void CALLBACK GSreadFIFO(u64 *pMem) +{ +#ifdef GS_LOG + //GS_LOG("GSreadFIFO\n"); +#endif + + ZeroGS::TransferLocalHost((u32*)pMem, 1); +} + +void CALLBACK GSreadFIFO2(u64 *pMem, int qwc) +{ +#ifdef GS_LOG + //GS_LOG("GSreadFIFO2\n"); +#endif + + ZeroGS::TransferLocalHost((u32*)pMem, qwc); +} + +s32 CALLBACK GSfreeze(int mode, freezeData *data) { + if (mode == FREEZE_LOAD) { + if( !ZeroGS::Load(data->data) ) + ERROR_LOG("Bad load format!"); + g_nRealFrame += 100; + + } else if (mode == FREEZE_SAVE) { + ZeroGS::Save(data->data); + } + if (mode == FREEZE_SIZE) { + data->size = ZeroGS::Save(NULL); + } + + return 0; +} + +//////////////////// +// Small profiler // +//////////////////// +#include +#include +#include +using namespace std; + +#ifdef _WIN32 + +inline u64 GET_PROFILE_TIME() +{ + LARGE_INTEGER lu; + QueryPerformanceCounter(&lu); + return lu.QuadPart; +} +#else +#define GET_PROFILE_TIME() //GetCpuTick() +#endif + + +struct DVPROFSTRUCT; + +struct DVPROFSTRUCT +{ + struct DATA + { + DATA(u64 time, u32 user = 0) : dwTime(time), dwUserData(user) {} + DATA() : dwTime(0), dwUserData(0) {} + + u64 dwTime; + u32 dwUserData; + }; + + ~DVPROFSTRUCT() { + list::iterator it = listpChild.begin(); + while(it != listpChild.end() ) { + SAFE_DELETE(*it); + ++it; + } + } + + list listTimes; // before DVProfEnd is called, contains the global time it started + // after DVProfEnd is called, contains the time it lasted + // the list contains all the tracked times + char pname[256]; + + list listpChild; // other profilers called during this profiler period +}; + +struct DVPROFTRACK +{ + u32 dwUserData; + DVPROFSTRUCT::DATA* pdwTime; + DVPROFSTRUCT* pprof; +}; + +list g_listCurTracking; // the current profiling functions, the back element is the + // one that will first get popped off the list when DVProfEnd is called + // the pointer is an element in DVPROFSTRUCT::listTimes +list g_listProfilers; // the current profilers, note that these are the parents + // any profiler started during the time of another is held in + // DVPROFSTRUCT::listpChild +list g_listAllProfilers; // ignores the hierarchy, pointer to elements in g_listProfilers + +void DVProfRegister(char* pname) +{ + if( !g_bWriteProfile ) + return; + + list::iterator it = g_listAllProfilers.begin(); + +// while(it != g_listAllProfilers.end() ) { +// +// if( _tcscmp(pname, (*it)->pname) == 0 ) { +// (*it)->listTimes.push_back(timeGetTime()); +// DVPROFTRACK dvtrack; +// dvtrack.pdwTime = &(*it)->listTimes.back(); +// dvtrack.pprof = *it; +// g_listCurTracking.push_back(dvtrack); +// return; +// } +// +// ++it; +// } + + // else add in a new profiler to the appropriate parent profiler + DVPROFSTRUCT* pprof = NULL; + + if( g_listCurTracking.size() > 0 ) { + assert( g_listCurTracking.back().pprof != NULL ); + g_listCurTracking.back().pprof->listpChild.push_back(new DVPROFSTRUCT()); + pprof = g_listCurTracking.back().pprof->listpChild.back(); + } + else { + g_listProfilers.push_back(DVPROFSTRUCT()); + pprof = &g_listProfilers.back(); + } + + strncpy(pprof->pname, pname, 256); + + // setup the profiler for tracking + pprof->listTimes.push_back(DVPROFSTRUCT::DATA(GET_PROFILE_TIME())); + + DVPROFTRACK dvtrack; + dvtrack.pdwTime = &pprof->listTimes.back(); + dvtrack.pprof = pprof; + dvtrack.dwUserData = 0; + + g_listCurTracking.push_back(dvtrack); + + // add to all profiler list + g_listAllProfilers.push_back(pprof); +} + +void DVProfEnd(u32 dwUserData) +{ + if( !g_bWriteProfile ) + return; + B_RETURN( g_listCurTracking.size() > 0 ); + + DVPROFTRACK dvtrack = g_listCurTracking.back(); + + assert( dvtrack.pdwTime != NULL && dvtrack.pprof != NULL ); + + dvtrack.pdwTime->dwTime = 1000000 * (GET_PROFILE_TIME()- dvtrack.pdwTime->dwTime) / luPerfFreq; + dvtrack.pdwTime->dwUserData= dwUserData; + + g_listCurTracking.pop_back(); +} + +struct DVTIMEINFO +{ + DVTIMEINFO() : uInclusive(0), uExclusive(0) {} + u64 uInclusive, uExclusive; +}; + +map mapAggregateTimes; + +u64 DVProfWriteStruct(FILE* f, DVPROFSTRUCT* p, int ident) +{ + fprintf(f, "%*s%s - ", ident, "", p->pname); + + list::iterator ittime = p->listTimes.begin(); + + u32 utime = 0; + + while(ittime != p->listTimes.end() ) { + utime += (u32)ittime->dwTime; + + if( ittime->dwUserData ) + fprintf(f, "time: %d, user: 0x%8.8x", (u32)ittime->dwTime, ittime->dwUserData); + else + fprintf(f, "time: %d", (u32)ittime->dwTime); + ++ittime; + } + + mapAggregateTimes[p->pname].uInclusive += utime; + + fprintf(f, "\n"); + + list::iterator itprof = p->listpChild.begin(); + + u32 uex = utime; + while(itprof != p->listpChild.end() ) { + + uex -= DVProfWriteStruct(f, *itprof, ident+4); + ++itprof; + } + + mapAggregateTimes[p->pname].uExclusive += uex; + return utime; +} + +void DVProfWrite(char* pfilename, u32 frames) +{ + assert( pfilename != NULL ); + FILE* f = fopen(pfilename, "wb"); + + mapAggregateTimes.clear(); + list::iterator it = g_listProfilers.begin(); + + while(it != g_listProfilers.end() ) { + DVProfWriteStruct(f, &(*it), 0); + ++it; + } + + { + map::iterator it; + fprintf(f, "\n\n-------------------------------------------------------------------\n\n"); + + u64 uTotal[2] = {0}; + double fiTotalTime[2]; + + for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) { + uTotal[0] += it->second.uExclusive; + uTotal[1] += it->second.uInclusive; + } + + fprintf(f, "total times (%d): ex: %Lu ", frames, uTotal[0]/frames); + fprintf(f, "inc: %Lu\n", uTotal[1]/frames); + + fiTotalTime[0] = 1.0 / (double)uTotal[0]; + fiTotalTime[1] = 1.0 / (double)uTotal[1]; + + // output the combined times + for(it = mapAggregateTimes.begin(); it != mapAggregateTimes.end(); ++it) { + fprintf(f, "%s - ex: %f inc: %f\n", it->first.c_str(), (double)it->second.uExclusive * fiTotalTime[0], + (double)it->second.uInclusive * fiTotalTime[1]); + } + } + + + fclose(f); +} + +void DVProfClear() +{ + g_listCurTracking.clear(); + g_listProfilers.clear(); + g_listAllProfilers.clear(); +} diff --git a/plugins/gs/zerogs/opengl/Linux/Conf.cpp b/plugins/gs/zerogs/opengl/Linux/Conf.cpp new file mode 100644 index 0000000..a5381c8 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/Conf.cpp @@ -0,0 +1,104 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include "GS.h" + +extern string s_strIniPath; + +void SaveConfig() { + FILE *f; + char cfg[255]; + + strcpy(cfg, s_strIniPath.c_str()); + f = fopen(cfg,"w"); + if (f == NULL) { + printf("failed to open %s\n", s_strIniPath.c_str()); + return; + } + fprintf(f, "interlace = %x\n", conf.interlace); + fprintf(f, "aliasing = %x\n", conf.aa); + fprintf(f, "bilinear = %x\n", conf.bilinear); + fprintf(f, "options = %x\n", conf.options); + fprintf(f, "gamesettings = %x\n", conf.gamesettings); + fclose(f); +} + +void LoadConfig() { + FILE *f; + char cfg[255]; + + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.options = 0; + conf.bilinear = 1; + conf.width = 640; + conf.height = 480; + + strcpy(cfg, s_strIniPath.c_str()); + f = fopen(cfg, "r"); + if (f == NULL) { + printf("failed to open %s\n", s_strIniPath.c_str()); + SaveConfig();//save and return + return; + } + fscanf(f, "interlace = %x\n", &conf.interlace); + fscanf(f, "aliasing = %x\n", &conf.aa); + fscanf(f, "bilinear = %x\n", &conf.bilinear); + fscanf(f, "options = %x\n", &conf.options); + fprintf(f, "gamesettings = %x\n", &conf.gamesettings); + fclose(f); + + // filter bad files + if( conf.aa < 0 || conf.aa > 2 ) conf.aa = 0; + + switch(conf.options&GSOPTION_WINDIMS) { + case GSOPTION_WIN640: + conf.width = 640; + conf.height = 480; + break; + case GSOPTION_WIN800: + conf.width = 800; + conf.height = 600; + break; + case GSOPTION_WIN1024: + conf.width = 1024; + conf.height = 768; + break; + case GSOPTION_WIN1280: + conf.width = 1280; + conf.height = 960; + break; + } + + // turn off all hacks by defaultof + conf.options &= ~(GSOPTION_FULLSCREEN|GSOPTION_WIREFRAME|GSOPTION_CAPTUREAVI); + conf.options |= GSOPTION_LOADED; + + if( conf.width <= 0 || conf.height <= 0 ) { + conf.width = 640; + conf.height = 480; + } +} + diff --git a/plugins/gs/zerogs/opengl/Linux/Linux.cpp b/plugins/gs/zerogs/opengl/Linux/Linux.cpp new file mode 100644 index 0000000..b6e0285 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/Linux.cpp @@ -0,0 +1,305 @@ +/* ZeroGS + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "GS.h" + +extern "C" { +#include "interface.h" +#include "support.h" +#include "callbacks.h" +} + +#include "Linux.h" + +#include + +static int prevbilinearfilter; +static map mapConfOpts; + +extern void OnKeyboardF5(int); +extern void OnKeyboardF6(int); +extern void OnKeyboardF7(int); +extern void OnKeyboardF9(int); + +void CALLBACK GSkeyEvent(keyEvent *ev) +{ + static bool bShift = false; + static bool bAlt = false; + + switch(ev->event) { + case KEYPRESS: + switch(ev->key) { + case XK_F5: + OnKeyboardF5(bShift); + break; + case XK_F6: + OnKeyboardF6(bShift); + break; + case XK_F7: + OnKeyboardF7(bShift); + break; + case XK_F9: + OnKeyboardF9(bShift); + break; + case XK_Escape: + break; + case XK_Shift_L: + case XK_Shift_R: + bShift = true; + break; + case XK_Alt_L: + case XK_Alt_R: + bAlt = true; + break; + } + break; + case KEYRELEASE: + switch(ev->key) { + case XK_Shift_L: + case XK_Shift_R: + bShift = false; + break; + case XK_Alt_L: + case XK_Alt_R: + bAlt = false; + break; + } + } +} + +GtkWidget *Conf; +GtkWidget *Logging; +GList *fresl; +GList *wresl; +GList *cachesizel; +GList *codecl; +GList *filtersl; + +void OnConf_Ok(GtkButton *button, gpointer user_data) +{ + GtkWidget *Btn; + char *str; + int i; + + u32 newinterlace = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkInterlace"))); + + if( !conf.interlace ) conf.interlace = newinterlace; + else if( !newinterlace ) conf.interlace = 2; // off + + conf.bilinear = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkBilinear"))); + // restore + if( conf.bilinear && prevbilinearfilter ) + conf.bilinear = prevbilinearfilter; + + //conf.mrtdepth = 1;//IsDlgButtonChecked(hW, IDC_CONFIG_DEPTHWRITE); + + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioAANone"))) ) { + conf.aa = 0; + } + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioAA2X"))) ) { + conf.aa = 1; + } + else conf.aa = 2; + + conf.options = 0; + conf.options |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkAVI"))) ? GSOPTION_CAPTUREAVI : 0; + conf.options |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkWireframe"))) ? GSOPTION_WIREFRAME : 0; + conf.options |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkbutton6"))) ? GSOPTION_FULLSCREEN : 0; + conf.options |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkTGA"))) ? GSOPTION_TGASNAP : 0; + + conf.gamesettings = 0; + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + GtkWidget* widget = lookup_widget(Conf, it->first.c_str()); + if( widget != NULL && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) + conf.gamesettings |= it->second; + } + GSsetGameCRC(0, conf.gamesettings); + + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize640"))) ) + conf.options |= GSOPTION_WIN640; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize800"))) ) + conf.options |= GSOPTION_WIN800; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize1024"))) ) + conf.options |= GSOPTION_WIN1024; + else if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize1280"))) ) + conf.options |= GSOPTION_WIN1280; + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +#define PUT_CONF(id) mapConfOpts["Opt"#id] = 0x##id + +void CALLBACK GSconfigure() +{ + char name[32]; + int nmodes, i; + + if( !(conf.options & GSOPTION_LOADED) ) + LoadConfig(); + + Conf = create_Config(); + + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkInterlace")), conf.interlace); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkBilinear")), !!conf.bilinear); + //gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkbutton6")), conf.mrtdepth); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioAANone")), conf.aa==0); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioAA2X")), conf.aa==1); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioAA4X")), conf.aa==2); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkWireframe")), (conf.options&GSOPTION_WIREFRAME)?1:0); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkAVI")), (conf.options&GSOPTION_CAPTUREAVI)?1:0); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkbutton6")), (conf.options&GSOPTION_FULLSCREEN)?1:0); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "checkTGA")), (conf.options&GSOPTION_TGASNAP)?1:0); + + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize640")), ((conf.options&GSOPTION_WINDIMS)>>4)==0); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize800")), ((conf.options&GSOPTION_WINDIMS)>>4)==1); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize1024")), ((conf.options&GSOPTION_WINDIMS)>>4)==2); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(Conf, "radioSize1280")), ((conf.options&GSOPTION_WINDIMS)>>4)==3); + + prevbilinearfilter = conf.bilinear; + + mapConfOpts.clear(); + PUT_CONF(00000001); + PUT_CONF(00000002); + PUT_CONF(00000004); + PUT_CONF(00000008); + PUT_CONF(00000010); + PUT_CONF(00000020); + PUT_CONF(00000040); + PUT_CONF(00000080); + PUT_CONF(00000200); + PUT_CONF(00000400); + PUT_CONF(00000800); + PUT_CONF(00001000); + PUT_CONF(00002000); + PUT_CONF(00004000); + PUT_CONF(00008000); + PUT_CONF(00010000); + PUT_CONF(00020000); + PUT_CONF(00040000); + PUT_CONF(00080000); + PUT_CONF(00100000); + PUT_CONF(00200000); + + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + GtkWidget* widget = lookup_widget(Conf, it->first.c_str()); + if( widget != NULL ) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), (conf.gamesettings&it->second)?1:0); + } + + gtk_widget_show_all(Conf); + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CALLBACK GSabout() { + + About = create_About(); + + gtk_widget_show_all(About); + gtk_main(); +} + +s32 CALLBACK GStest() { + return 0; +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +void *SysLoadLibrary(char *lib) { + return dlopen(lib, RTLD_NOW | RTLD_GLOBAL); +} + +void *SysLoadSym(void *lib, char *sym) { + void *ret = dlsym(lib, sym); + if (ret == NULL) printf("null: %s\n", sym); + return dlsym(lib, sym); +} + +char *SysLibError() { + return dlerror(); +} + +void SysCloseLibrary(void *lib) { + dlclose(lib); +} diff --git a/plugins/gs/zerogs/opengl/Linux/Linux.h b/plugins/gs/zerogs/opengl/Linux/Linux.h new file mode 100644 index 0000000..bbac864 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/Linux.h @@ -0,0 +1,24 @@ +/* GSsoft + * Copyright (C) 2002-2004 GSsoft Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_H__ +#define __LINUX_H__ + + + +#endif diff --git a/plugins/gs/zerogs/opengl/Linux/Makefile.am b/plugins/gs/zerogs/opengl/Linux/Makefile.am new file mode 100644 index 0000000..43f3fcb --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libZeroGSLinux.a +libZeroGSLinux_a_CPPFLAGS = -fPIC +libZeroGSLinux_a_CXXFLAGS = -fPIC +libZeroGSLinux_a_CFLAGS = -fPIC +INCLUDES = $(shell pkg-config --cflags gtk+-2.0) -I../ +libZeroGSLinux_a_SOURCES = callbacks.c Conf.cpp interface.c Linux.cpp support.c diff --git a/plugins/gs/zerogs/opengl/Linux/buildgui.sh b/plugins/gs/zerogs/opengl/Linux/buildgui.sh new file mode 100644 index 0000000..9f0d1fc --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/buildgui.sh @@ -0,0 +1,9 @@ +# builds the GUI C classes +mkdir temp +cp zerogs.glade temp/ +cd temp +glade-2 --write-source zerogs.glade +rm src/main.c +cp src/*.h src/*.c ../ +cd .. +/bin/rm -rf temp diff --git a/plugins/gs/zerogs/opengl/Linux/callbacks.c b/plugins/gs/zerogs/opengl/Linux/callbacks.c new file mode 100644 index 0000000..e87ed8b --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/gs/zerogs/opengl/Linux/callbacks.h b/plugins/gs/zerogs/opengl/Linux/callbacks.h new file mode 100644 index 0000000..e606c24 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/gs/zerogs/opengl/Linux/interface.c b/plugins/gs/zerogs/opengl/Linux/interface.c new file mode 100644 index 0000000..ffcf08f --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/interface.c @@ -0,0 +1,291 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox4; + GtkWidget *checkInterlace; + GtkWidget *checkBilinear; + GtkWidget *frame4; + GtkWidget *alignment1; + GtkWidget *hbox6; + GtkWidget *radioAANone; + GSList *radioAANone_group = NULL; + GtkWidget *radioAA2X; + GtkWidget *radioAA4X; + GtkWidget *label9; + GtkWidget *checkWireframe; + GtkWidget *checkAVI; + GtkWidget *checkBMP; + GtkWidget *checkbutton6; + GtkWidget *frame5; + GtkWidget *alignment2; + GtkWidget *hbox7; + GtkWidget *radioSize640; + GSList *radioSize640_group = NULL; + GtkWidget *radioSize800; + GtkWidget *radioSize1024; + GtkWidget *radioSize1280; + GtkWidget *label10; + GtkWidget *label11; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), _("ZeroOGS Configuration")); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox4); + gtk_container_add (GTK_CONTAINER (Config), vbox4); + + checkInterlace = gtk_check_button_new_with_mnemonic (_("Interlace Enable (toggle with F5)\n there are 2 modes + interlace off")); + gtk_widget_show (checkInterlace); + gtk_box_pack_start (GTK_BOX (vbox4), checkInterlace, FALSE, FALSE, 0); + + checkBilinear = gtk_check_button_new_with_mnemonic (_("Bilinear Filtering (Shift+F5)\n Best quality is on, turn off for speed")); + gtk_widget_show (checkBilinear); + gtk_box_pack_start (GTK_BOX (vbox4), checkBilinear, FALSE, FALSE, 0); + + frame4 = gtk_frame_new (NULL); + gtk_widget_show (frame4); + gtk_box_pack_start (GTK_BOX (vbox4), frame4, TRUE, TRUE, 0); + + alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment1); + gtk_container_add (GTK_CONTAINER (frame4), alignment1); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 0, 0, 12, 0); + + hbox6 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox6); + gtk_container_add (GTK_CONTAINER (alignment1), hbox6); + + radioAANone = gtk_radio_button_new_with_mnemonic (NULL, _("None")); + gtk_widget_show (radioAANone); + gtk_box_pack_start (GTK_BOX (hbox6), radioAANone, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAANone), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAANone)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioAANone), TRUE); + + radioAA2X = gtk_radio_button_new_with_mnemonic (NULL, _("2X")); + gtk_widget_show (radioAA2X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA2X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA2X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA2X)); + + radioAA4X = gtk_radio_button_new_with_mnemonic (NULL, _("4X")); + gtk_widget_show (radioAA4X); + gtk_box_pack_start (GTK_BOX (hbox6), radioAA4X, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioAA4X), radioAANone_group); + radioAANone_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioAA4X)); + + label9 = gtk_label_new (_("Anti-aliasing for higher quality (F6)")); + gtk_widget_show (label9); + gtk_frame_set_label_widget (GTK_FRAME (frame4), label9); + gtk_label_set_use_markup (GTK_LABEL (label9), TRUE); + + checkWireframe = gtk_check_button_new_with_mnemonic (_("Wireframe rendering (Shift+F6)")); + gtk_widget_show (checkWireframe); + gtk_box_pack_start (GTK_BOX (vbox4), checkWireframe, FALSE, FALSE, 0); + + checkAVI = gtk_check_button_new_with_mnemonic (_("Capture Avi (zerogs.avi)(F7)")); + gtk_widget_show (checkAVI); + gtk_box_pack_start (GTK_BOX (vbox4), checkAVI, FALSE, FALSE, 0); + + checkBMP = gtk_check_button_new_with_mnemonic (_("Save Snapshots as BMPs (default is JPG)")); + gtk_widget_show (checkBMP); + gtk_box_pack_start (GTK_BOX (vbox4), checkBMP, FALSE, FALSE, 0); + + checkbutton6 = gtk_check_button_new_with_mnemonic (_("Fullscreen (Alt+Enter)\n to get out press Alt+Enter again (or ESC)")); + gtk_widget_show (checkbutton6); + gtk_box_pack_start (GTK_BOX (vbox4), checkbutton6, FALSE, FALSE, 0); + + frame5 = gtk_frame_new (NULL); + gtk_widget_show (frame5); + gtk_box_pack_start (GTK_BOX (vbox4), frame5, TRUE, TRUE, 0); + + alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment2); + gtk_container_add (GTK_CONTAINER (frame5), alignment2); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment2), 0, 0, 12, 0); + + hbox7 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox7); + gtk_container_add (GTK_CONTAINER (alignment2), hbox7); + + radioSize640 = gtk_radio_button_new_with_mnemonic (NULL, _("640x480")); + gtk_widget_show (radioSize640); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize640, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize640), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize640)); + + radioSize800 = gtk_radio_button_new_with_mnemonic (NULL, _("800x600")); + gtk_widget_show (radioSize800); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize800, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize800), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize800)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radioSize800), TRUE); + + radioSize1024 = gtk_radio_button_new_with_mnemonic (NULL, _("1024x768")); + gtk_widget_show (radioSize1024); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize1024, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize1024), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize1024)); + + radioSize1280 = gtk_radio_button_new_with_mnemonic (NULL, _("1280x960")); + gtk_widget_show (radioSize1280); + gtk_box_pack_start (GTK_BOX (hbox7), radioSize1280, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radioSize1280), radioSize640_group); + radioSize640_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radioSize1280)); + + label10 = gtk_label_new (_("Default Window Size (no speed impact)")); + gtk_widget_show (label10); + gtk_frame_set_label_widget (GTK_FRAME (frame5), label10); + gtk_label_set_use_markup (GTK_LABEL (label10), TRUE); + + label11 = gtk_label_new (_("Show Frames Per Second (Shift+F7)\n (value is the average over 4-16 PS2 frames)")); + gtk_widget_show (label11); + gtk_box_pack_start (GTK_BOX (vbox4), label11, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox4), hbuttonbox1, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_SPREAD); + gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 30); + + button1 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_mnemonic (_("Cancel")); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button1, "clicked", + G_CALLBACK (OnConf_Ok), + NULL); + g_signal_connect ((gpointer) button2, "clicked", + G_CALLBACK (OnConf_Cancel), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (Config, Config, "Config"); + GLADE_HOOKUP_OBJECT (Config, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT (Config, checkInterlace, "checkInterlace"); + GLADE_HOOKUP_OBJECT (Config, checkBilinear, "checkBilinear"); + GLADE_HOOKUP_OBJECT (Config, frame4, "frame4"); + GLADE_HOOKUP_OBJECT (Config, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (Config, hbox6, "hbox6"); + GLADE_HOOKUP_OBJECT (Config, radioAANone, "radioAANone"); + GLADE_HOOKUP_OBJECT (Config, radioAA2X, "radioAA2X"); + GLADE_HOOKUP_OBJECT (Config, radioAA4X, "radioAA4X"); + GLADE_HOOKUP_OBJECT (Config, label9, "label9"); + GLADE_HOOKUP_OBJECT (Config, checkWireframe, "checkWireframe"); + GLADE_HOOKUP_OBJECT (Config, checkAVI, "checkAVI"); + GLADE_HOOKUP_OBJECT (Config, checkBMP, "checkTGA"); + GLADE_HOOKUP_OBJECT (Config, checkbutton6, "checkbutton6"); + GLADE_HOOKUP_OBJECT (Config, frame5, "frame5"); + GLADE_HOOKUP_OBJECT (Config, alignment2, "alignment2"); + GLADE_HOOKUP_OBJECT (Config, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (Config, radioSize640, "radioSize640"); + GLADE_HOOKUP_OBJECT (Config, radioSize800, "radioSize800"); + GLADE_HOOKUP_OBJECT (Config, radioSize1024, "radioSize1024"); + GLADE_HOOKUP_OBJECT (Config, radioSize1280, "radioSize1280"); + GLADE_HOOKUP_OBJECT (Config, label10, "label10"); + GLADE_HOOKUP_OBJECT (Config, label11, "label11"); + GLADE_HOOKUP_OBJECT (Config, hbuttonbox1, "hbuttonbox1"); + GLADE_HOOKUP_OBJECT (Config, button1, "button1"); + GLADE_HOOKUP_OBJECT (Config, button2, "button2"); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *label4; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), _("ZeroGS KOSMOS About")); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new (_("OpenGL version")); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER); + + label3 = gtk_label_new (_("Author: zerofrog(@gmail.com)")); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + + label4 = gtk_label_new (_("Many thanks to the Pcsx2 testing team")); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (vbox2), label4, FALSE, FALSE, 0); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + gtk_box_set_spacing (GTK_BOX (hbuttonbox2), 30); + + button3 = gtk_button_new_with_mnemonic (_("Ok")); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) button3, "clicked", + G_CALLBACK (OnAbout_Ok), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (About, About, "About"); + GLADE_HOOKUP_OBJECT (About, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (About, label2, "label2"); + GLADE_HOOKUP_OBJECT (About, label3, "label3"); + GLADE_HOOKUP_OBJECT (About, label4, "label4"); + GLADE_HOOKUP_OBJECT (About, hbuttonbox2, "hbuttonbox2"); + GLADE_HOOKUP_OBJECT (About, button3, "button3"); + + return About; +} + diff --git a/plugins/gs/zerogs/opengl/Linux/interface.h b/plugins/gs/zerogs/opengl/Linux/interface.h new file mode 100644 index 0000000..69c303b --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/gs/zerogs/opengl/Linux/support.c b/plugins/gs/zerogs/opengl/Linux/support.c new file mode 100644 index 0000000..00aff29 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/plugins/gs/zerogs/opengl/Linux/support.h b/plugins/gs/zerogs/opengl/Linux/support.h new file mode 100644 index 0000000..78e22b1 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/support.h @@ -0,0 +1,69 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# define Q_(String) g_strip_context ((String), gettext (String)) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define Q_(String) g_strip_context ((String), (String)) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +//GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +//void glade_set_atk_action_description (AtkAction *action, +// const gchar *action_name, +// const gchar *description); + diff --git a/plugins/gs/zerogs/opengl/Linux/zerogs.glade b/plugins/gs/zerogs/opengl/Linux/zerogs.glade new file mode 100644 index 0000000..50ee76a --- /dev/null +++ b/plugins/gs/zerogs/opengl/Linux/zerogs.glade @@ -0,0 +1,598 @@ + + + + + + + 5 + True + ZeroOGS Configuration + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + True + Interlace Enable (toggle with F5) + there are 2 modes + interlace off + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Bilinear Filtering (Shift+F5) + Best quality is on, turn off for speed + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + 0 + + + + True + True + None + True + GTK_RELIEF_NORMAL + True + True + False + True + + + 0 + False + False + + + + + + True + True + 2X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + True + True + 4X + True + GTK_RELIEF_NORMAL + True + False + False + True + radioAANone + + + 0 + False + False + + + + + + + + + + True + <b>Anti-aliasing for higher quality (F6)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + True + Wireframe rendering (Shift+F6) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Capture Avi (zerogs.avi)(F7) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Save Snapshots as TGAs (default is JPG) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Fullscreen (Alt+Enter) + to get out press Alt+Enter again (or ESC) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + 0 + + + + True + True + 640x480 + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + 800x600 + True + GTK_RELIEF_NORMAL + True + True + False + True + radioSize640 + + + 0 + False + False + + + + + + True + True + 1024x768 + True + GTK_RELIEF_NORMAL + True + False + False + True + radioSize640 + + + 0 + False + False + + + + + + True + True + 1280x960 + True + GTK_RELIEF_NORMAL + True + False + False + True + radioSize640 + + + 0 + False + False + + + + + + + + + + True + <b>Default Window Size (no speed impact)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + Show Frames Per Second (Shift+F7) + (value is the average over 4-16 PS2 frames) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_SPREAD + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + + 5 + True + ZeroGS KOSMOS About + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + 5 + True + False + 5 + + + + True + OpenGL version + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Author: zerofrog(@gmail.com) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Many thanks to the Pcsx2 testing team + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + + + + True + True + True + Ok + True + GTK_RELIEF_NORMAL + True + + + + + + 0 + True + True + + + + + + + diff --git a/plugins/gs/zerogs/opengl/Makefile.am b/plugins/gs/zerogs/opengl/Makefile.am new file mode 100644 index 0000000..557b4a8 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Makefile.am @@ -0,0 +1,48 @@ +# Create a shared library libZeroGSogl +AUTOMAKE_OPTIONS = foreign +noinst_LIBRARIES = libZeroGSogl.a + +libZeroGSogl_a_CPPFLAGS = $(shell pkg-config --cflags gtk+-2.0) +libZeroGSogl_a_CXXFLAGS = $(shell pkg-config --cflags gtk+-2.0) + +if X86_64 +libZeroGSogl_a_CPPFLAGS += -fPIC +libZeroGSogl_a_CXXFLAGS += -fPIC +CCASFLAGS += -fPIC +endif + +# Create a shared object by faking an exe (thanks to ODE makefiles) +traplibdir=$(prefix) + + +if RELEASE_TO_PUBLIC +preext=r +endif + +EXEEXT=$(preext)@so_ext@ + +traplib_PROGRAMS=libZeroGSogl +libZeroGSogl_SOURCES= +libZeroGSogl_DEPENDENCIES = libZeroGSogl.a +libZeroGSogl_LDFLAGS= @SHARED_LDFLAGS@ +libZeroGSogl_LDFLAGS+=-Wl,-soname,@ZEROGS_SONAME@ +libZeroGSogl_LDADD=$(libZeroGSogl_a_OBJECTS) + +libZeroGSogl_a_SOURCES = \ +GSmain.cpp memcpy_amd.cpp Regs.cpp x86.cpp zpipe.cpp \ +Mem.cpp rasterfont.cpp targets.cpp zerogs.cpp glprocs.c + +if X86_64 +libZeroGSogl_a_SOURCES += x86-64.S +else +libZeroGSogl_a_SOURCES += x86-32.S +endif + +if SSE2 +CCASFLAGS+= -DZEROGS_SSE2 +endif + +libZeroGSogl_a_DEPENDENCIES = Linux/libZeroGSLinux.a +libZeroGSogl_LDADD += Linux/libZeroGSLinux.a + +SUBDIRS = Linux . diff --git a/plugins/gs/zerogs/opengl/Mem.cpp b/plugins/gs/zerogs/opengl/Mem.cpp new file mode 100644 index 0000000..752e2e4 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Mem.cpp @@ -0,0 +1,892 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "GS.h" +#include "Mem.h" +#include "zerogs.h" +#include "targets.h" +#include "x86.h" + +u32 g_blockTable32[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable32Z[4][8] = { + { 24, 25, 28, 29, 8, 9, 12, 13}, + { 26, 27, 30, 31, 10, 11, 14, 15}, + { 16, 17, 20, 21, 0, 1, 4, 5}, + { 18, 19, 22, 23, 2, 3, 6, 7} +}; + +u32 g_blockTable16[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_blockTable16S[8][4] = { + { 0, 2, 16, 18 }, + { 1, 3, 17, 19 }, + { 8, 10, 24, 26 }, + { 9, 11, 25, 27 }, + { 4, 6, 20, 22 }, + { 5, 7, 21, 23 }, + { 12, 14, 28, 30 }, + { 13, 15, 29, 31 } +}; + +u32 g_blockTable16Z[8][4] = { + { 24, 26, 16, 18 }, + { 25, 27, 17, 19 }, + { 28, 30, 20, 22 }, + { 29, 31, 21, 23 }, + { 8, 10, 0, 2 }, + { 9, 11, 1, 3 }, + { 12, 14, 4, 6 }, + { 13, 15, 5, 7 } +}; + +u32 g_blockTable16SZ[8][4] = { + { 24, 26, 8, 10 }, + { 25, 27, 9, 11 }, + { 16, 18, 0, 2 }, + { 17, 19, 1, 3 }, + { 28, 30, 12, 14 }, + { 29, 31, 13, 15 }, + { 20, 22, 4, 6 }, + { 21, 23, 5, 7 } +}; + +u32 g_blockTable8[4][8] = { + { 0, 1, 4, 5, 16, 17, 20, 21}, + { 2, 3, 6, 7, 18, 19, 22, 23}, + { 8, 9, 12, 13, 24, 25, 28, 29}, + { 10, 11, 14, 15, 26, 27, 30, 31} +}; + +u32 g_blockTable4[8][4] = { + { 0, 2, 8, 10 }, + { 1, 3, 9, 11 }, + { 4, 6, 12, 14 }, + { 5, 7, 13, 15 }, + { 16, 18, 24, 26 }, + { 17, 19, 25, 27 }, + { 20, 22, 28, 30 }, + { 21, 23, 29, 31 } +}; + +u32 g_columnTable32[8][8] = { + { 0, 1, 4, 5, 8, 9, 12, 13 }, + { 2, 3, 6, 7, 10, 11, 14, 15 }, + { 16, 17, 20, 21, 24, 25, 28, 29 }, + { 18, 19, 22, 23, 26, 27, 30, 31 }, + { 32, 33, 36, 37, 40, 41, 44, 45 }, + { 34, 35, 38, 39, 42, 43, 46, 47 }, + { 48, 49, 52, 53, 56, 57, 60, 61 }, + { 50, 51, 54, 55, 58, 59, 62, 63 }, +}; + +u32 g_columnTable16[8][16] = { + { 0, 2, 8, 10, 16, 18, 24, 26, + 1, 3, 9, 11, 17, 19, 25, 27 }, + { 4, 6, 12, 14, 20, 22, 28, 30, + 5, 7, 13, 15, 21, 23, 29, 31 }, + { 32, 34, 40, 42, 48, 50, 56, 58, + 33, 35, 41, 43, 49, 51, 57, 59 }, + { 36, 38, 44, 46, 52, 54, 60, 62, + 37, 39, 45, 47, 53, 55, 61, 63 }, + { 64, 66, 72, 74, 80, 82, 88, 90, + 65, 67, 73, 75, 81, 83, 89, 91 }, + { 68, 70, 76, 78, 84, 86, 92, 94, + 69, 71, 77, 79, 85, 87, 93, 95 }, + { 96, 98, 104, 106, 112, 114, 120, 122, + 97, 99, 105, 107, 113, 115, 121, 123 }, + { 100, 102, 108, 110, 116, 118, 124, 126, + 101, 103, 109, 111, 117, 119, 125, 127 }, +}; + +u32 g_columnTable8[16][16] = { + { 0, 4, 16, 20, 32, 36, 48, 52, // column 0 + 2, 6, 18, 22, 34, 38, 50, 54 }, + { 8, 12, 24, 28, 40, 44, 56, 60, + 10, 14, 26, 30, 42, 46, 58, 62 }, + { 33, 37, 49, 53, 1, 5, 17, 21, + 35, 39, 51, 55, 3, 7, 19, 23 }, + { 41, 45, 57, 61, 9, 13, 25, 29, + 43, 47, 59, 63, 11, 15, 27, 31 }, + { 96, 100, 112, 116, 64, 68, 80, 84, // column 1 + 98, 102, 114, 118, 66, 70, 82, 86 }, + { 104, 108, 120, 124, 72, 76, 88, 92, + 106, 110, 122, 126, 74, 78, 90, 94 }, + { 65, 69, 81, 85, 97, 101, 113, 117, + 67, 71, 83, 87, 99, 103, 115, 119 }, + { 73, 77, 89, 93, 105, 109, 121, 125, + 75, 79, 91, 95, 107, 111, 123, 127 }, + { 128, 132, 144, 148, 160, 164, 176, 180, // column 2 + 130, 134, 146, 150, 162, 166, 178, 182 }, + { 136, 140, 152, 156, 168, 172, 184, 188, + 138, 142, 154, 158, 170, 174, 186, 190 }, + { 161, 165, 177, 181, 129, 133, 145, 149, + 163, 167, 179, 183, 131, 135, 147, 151 }, + { 169, 173, 185, 189, 137, 141, 153, 157, + 171, 175, 187, 191, 139, 143, 155, 159 }, + { 224, 228, 240, 244, 192, 196, 208, 212, // column 3 + 226, 230, 242, 246, 194, 198, 210, 214 }, + { 232, 236, 248, 252, 200, 204, 216, 220, + 234, 238, 250, 254, 202, 206, 218, 222 }, + { 193, 197, 209, 213, 225, 229, 241, 245, + 195, 199, 211, 215, 227, 231, 243, 247 }, + { 201, 205, 217, 221, 233, 237, 249, 253, + 203, 207, 219, 223, 235, 239, 251, 255 }, +}; + +u32 g_columnTable4[16][32] = { + { 0, 8, 32, 40, 64, 72, 96, 104, // column 0 + 2, 10, 34, 42, 66, 74, 98, 106, + 4, 12, 36, 44, 68, 76, 100, 108, + 6, 14, 38, 46, 70, 78, 102, 110 }, + { 16, 24, 48, 56, 80, 88, 112, 120, + 18, 26, 50, 58, 82, 90, 114, 122, + 20, 28, 52, 60, 84, 92, 116, 124, + 22, 30, 54, 62, 86, 94, 118, 126 }, + { 65, 73, 97, 105, 1, 9, 33, 41, + 67, 75, 99, 107, 3, 11, 35, 43, + 69, 77, 101, 109, 5, 13, 37, 45, + 71, 79, 103, 111, 7, 15, 39, 47 }, + { 81, 89, 113, 121, 17, 25, 49, 57, + 83, 91, 115, 123, 19, 27, 51, 59, + 85, 93, 117, 125, 21, 29, 53, 61, + 87, 95, 119, 127, 23, 31, 55, 63 }, + { 192, 200, 224, 232, 128, 136, 160, 168, // column 1 + 194, 202, 226, 234, 130, 138, 162, 170, + 196, 204, 228, 236, 132, 140, 164, 172, + 198, 206, 230, 238, 134, 142, 166, 174 }, + { 208, 216, 240, 248, 144, 152, 176, 184, + 210, 218, 242, 250, 146, 154, 178, 186, + 212, 220, 244, 252, 148, 156, 180, 188, + 214, 222, 246, 254, 150, 158, 182, 190 }, + { 129, 137, 161, 169, 193, 201, 225, 233, + 131, 139, 163, 171, 195, 203, 227, 235, + 133, 141, 165, 173, 197, 205, 229, 237, + 135, 143, 167, 175, 199, 207, 231, 239 }, + { 145, 153, 177, 185, 209, 217, 241, 249, + 147, 155, 179, 187, 211, 219, 243, 251, + 149, 157, 181, 189, 213, 221, 245, 253, + 151, 159, 183, 191, 215, 223, 247, 255 }, + { 256, 264, 288, 296, 320, 328, 352, 360, // column 2 + 258, 266, 290, 298, 322, 330, 354, 362, + 260, 268, 292, 300, 324, 332, 356, 364, + 262, 270, 294, 302, 326, 334, 358, 366 }, + { 272, 280, 304, 312, 336, 344, 368, 376, + 274, 282, 306, 314, 338, 346, 370, 378, + 276, 284, 308, 316, 340, 348, 372, 380, + 278, 286, 310, 318, 342, 350, 374, 382 }, + { 321, 329, 353, 361, 257, 265, 289, 297, + 323, 331, 355, 363, 259, 267, 291, 299, + 325, 333, 357, 365, 261, 269, 293, 301, + 327, 335, 359, 367, 263, 271, 295, 303 }, + { 337, 345, 369, 377, 273, 281, 305, 313, + 339, 347, 371, 379, 275, 283, 307, 315, + 341, 349, 373, 381, 277, 285, 309, 317, + 343, 351, 375, 383, 279, 287, 311, 319 }, + { 448, 456, 480, 488, 384, 392, 416, 424, // column 3 + 450, 458, 482, 490, 386, 394, 418, 426, + 452, 460, 484, 492, 388, 396, 420, 428, + 454, 462, 486, 494, 390, 398, 422, 430 }, + { 464, 472, 496, 504, 400, 408, 432, 440, + 466, 474, 498, 506, 402, 410, 434, 442, + 468, 476, 500, 508, 404, 412, 436, 444, + 470, 478, 502, 510, 406, 414, 438, 446 }, + { 385, 393, 417, 425, 449, 457, 481, 489, + 387, 395, 419, 427, 451, 459, 483, 491, + 389, 397, 421, 429, 453, 461, 485, 493, + 391, 399, 423, 431, 455, 463, 487, 495 }, + { 401, 409, 433, 441, 465, 473, 497, 505, + 403, 411, 435, 443, 467, 475, 499, 507, + 405, 413, 437, 445, 469, 477, 501, 509, + 407, 415, 439, 447, 471, 479, 503, 511 }, +}; + +u32 g_pageTable32[32][64]; +u32 g_pageTable32Z[32][64]; +u32 g_pageTable16[64][64]; +u32 g_pageTable16S[64][64]; +u32 g_pageTable16Z[64][64]; +u32 g_pageTable16SZ[64][64]; +u32 g_pageTable8[64][128]; +u32 g_pageTable4[128][128]; + +BLOCK m_Blocks[0x40]; // do so blocks are indexable +static PCSX2_ALIGNED16(u32 tempblock[64]); + +#define DSTPSM gs.dstbuf.psm + +#define START_HOSTLOCAL() \ + assert( gs.imageTransfer == 0 ); \ + u8* pstart = g_pbyGSMemory + gs.dstbuf.bp*256; \ + \ + const u8* pendbuf = (const u8*)pbyMem + nQWordSize*4; \ + int i = gs.imageY, j = gs.imageX; \ + +extern BOOL g_bSaveTrans; + +#define END_HOSTLOCAL() \ +End: \ + if( i >= gs.imageEndY ) { \ + assert( gs.imageTransfer == -1 || i == gs.imageEndY ); \ + gs.imageTransfer = -1; \ + /*int start, end; \ + ZeroGS::GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); \ + ZeroGS::g_MemTargs.ClearRange(start, end);*/ \ + } \ + else { \ + /* update new params */ \ + gs.imageY = i; \ + gs.imageX = j; \ + } \ + +// transfers whole rows +#define TRANSMIT_HOSTLOCAL_Y_(psm, T, widthlimit, endY) { \ + assert( (nSize%widthlimit) == 0 && widthlimit <= 4 ); \ + if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { \ + /*GS_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM);*/ \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += 1, nSize -= 1, pbuf += 1) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ + } \ + } \ + } \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += widthlimit) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ + \ + if( widthlimit > 1 ) { \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, pbuf[1], gs.dstbuf.bw); \ + \ + if( widthlimit > 2 ) { \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, pbuf[2], gs.dstbuf.bw); \ + \ + if( widthlimit > 3 ) { \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, pbuf[3], gs.dstbuf.bw); \ + } \ + } \ + } \ + } \ + \ + if( j >= gs.imageEndX ) { assert(j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || nSize*sizeof(T)/4 == 0 ); goto End; } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j++, pbuf++) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, pbuf[0], gs.dstbuf.bw); \ + } \ + pbuf += pitch-fracX; \ + } \ +} \ + +// transfers whole rows +#define TRANSMIT_HOSTLOCAL_Y_24(psm, T, widthlimit, endY) { \ + if( widthlimit != 8 || ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) { \ + /*GS_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM);*/ \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += 1, nSize -= 1, pbuf += 3) { \ + writePixel##psm##_0(pstart, j%2048, i%2048, *(u32*)(pbuf), gs.dstbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert(gs.imageTransfer == -1 || j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || nSize == 0 ); goto End; } \ + } \ + } \ + else { \ + assert( /*(nSize%widthlimit) == 0 &&*/ widthlimit == 8 ); \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += 3*widthlimit) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, *(u32*)(pbuf+0), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *(u32*)(pbuf+3), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *(u32*)(pbuf+6), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *(u32*)(pbuf+9), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *(u32*)(pbuf+12), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *(u32*)(pbuf+15), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *(u32*)(pbuf+18), gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *(u32*)(pbuf+21), gs.dstbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert(gs.imageTransfer == -1 || j == gs.imageEndX); j = gs.trxpos.dx; } \ + else { \ + if( nSize < 0 ) { \ + /* extracted too much */ \ + assert( (nSize%3)==0 && nSize > -24 ); \ + j += nSize/3; \ + nSize = 0; \ + } \ + assert( gs.imageTransfer == -1 || nSize == 0 ); \ + goto End; \ + } \ + } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_24(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j++, pbuf += 3) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, *(u32*)pbuf, gs.dstbuf.bw); \ + } \ + pbuf += 3*(pitch-fracX); \ + } \ +} \ + +// meant for 4bit transfers +#define TRANSMIT_HOSTLOCAL_Y_4(psm, T, widthlimit, endY) { \ + for(; i < endY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit) { \ + /* write as many pixel at one time as possible */ \ + writePixel##psm##_0(pstart, j%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + if( widthlimit > 2 ) { \ + writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + \ + if( widthlimit > 4 ) { \ + writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + \ + if( widthlimit > 6 ) { \ + writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ + pbuf++; \ + } \ + } \ + } \ + } \ + \ + if( j >= gs.imageEndX ) { j = gs.trxpos.dx; } \ + else { assert( gs.imageTransfer == -1 || (nSize/32) == 0 ); goto End; } \ + } \ +} \ + +// transmit until endX, don't check size since it has already been prevalidated +#define TRANSMIT_HOSTLOCAL_X_4(psm, T, widthlimit, blockheight, startX) { \ + for(int tempi = 0; tempi < blockheight; ++tempi) { \ + for(j = startX; j < gs.imageEndX; j+=2, pbuf++) { \ + writePixel##psm##_0(pstart, j%2048, (i+tempi)%2048, pbuf[0]&0x0f, gs.dstbuf.bw); \ + writePixel##psm##_0(pstart, (j+1)%2048, (i+tempi)%2048, pbuf[0]>>4, gs.dstbuf.bw); \ + } \ + pbuf += (pitch-fracX)/2; \ + } \ +} \ + +// calculate pitch in source buffer +#define TRANSMIT_PITCH_(pitch, T) (pitch*sizeof(T)) +#define TRANSMIT_PITCH_24(pitch, T) (pitch*3) +#define TRANSMIT_PITCH_4(pitch, T) (pitch/2) + +// special swizzle macros +#define SwizzleBlock24(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch-24) { \ + for(int bx = 0; bx < 8; ++bx, pnewsrc += 3) { \ + pblock[bx] = *(u32*)pnewsrc; \ + } \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x00ffffff); \ +} \ + +#define SwizzleBlock24u SwizzleBlock24 + +#define SwizzleBlock8H(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<24; \ + pblock[1] = u<<16; \ + pblock[2] = u<<8; \ + pblock[3] = u; \ + u = *(u32*)(pnewsrc+4); \ + pblock[4] = u<<24; \ + pblock[5] = u<<16; \ + pblock[6] = u<<8; \ + pblock[7] = u; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xff000000); \ +} \ + +#define SwizzleBlock8Hu SwizzleBlock8H + +#define SwizzleBlock4HH(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<28; \ + pblock[1] = u<<24; \ + pblock[2] = u<<20; \ + pblock[3] = u<<16; \ + pblock[4] = u<<12; \ + pblock[5] = u<<8; \ + pblock[6] = u<<4; \ + pblock[7] = u; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xf0000000); \ +} \ + +#define SwizzleBlock4HHu SwizzleBlock4HH + +#define SwizzleBlock4HL(dst, src, pitch) { \ + u8* pnewsrc = src; \ + u32* pblock = tempblock; \ + \ + for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch) { \ + u32 u = *(u32*)pnewsrc; \ + pblock[0] = u<<24; \ + pblock[1] = u<<20; \ + pblock[2] = u<<16; \ + pblock[3] = u<<12; \ + pblock[4] = u<<8; \ + pblock[5] = u<<4; \ + pblock[6] = u; \ + pblock[7] = u>>4; \ + } \ + SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x0f000000); \ +} \ + +#define SwizzleBlock4HLu SwizzleBlock4HL + +// ------------------------ +// | Y | +// ------------------------ +// | block | | +// | aligned area | X | +// | | | +// ------------------------ +// | Y | +// ------------------------ +#define DEFINE_TRANSFERLOCAL(psm, T, widthlimit, blockbits, blockwidth, blockheight, TransSfx, SwizzleBlock) \ +void TransferHostLocal##psm(const void* pbyMem, u32 nQWordSize) \ +{ \ + START_HOSTLOCAL(); \ + \ + const T* pbuf = (const T*)pbyMem; \ + int endY, alignedY, alignedX; \ + int nSize = nQWordSize*4*2/TRANSMIT_PITCH##TransSfx(2, T); \ + int pitch, area, fracX; \ + bool bAligned, bCanAlign; \ + nSize = min(nSize, gs.imageWnew * gs.imageHnew); \ + \ + endY = ROUND_UPPOW2(i, blockheight); \ + alignedY = ROUND_DOWNPOW2(gs.imageEndY, blockheight); \ + alignedX = ROUND_DOWNPOW2(gs.imageEndX, blockwidth); \ + bCanAlign = MOD_POW2(gs.trxpos.dx, blockwidth) == 0 && (j == gs.trxpos.dx) && (alignedY > endY) && alignedX > gs.trxpos.dx; \ + \ + if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { \ + /* hack */ \ + if( abs((int)nSize - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx)) <= widthlimit ) { \ + /* don't transfer */ \ + /*printf("bad texture %s: %d %d %d\n", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/ \ + gs.imageTransfer = -1; \ + } \ + bCanAlign = false; \ + } \ + \ + /* first align on block boundary */ \ + if( MOD_POW2(i, blockheight) || !bCanAlign ) { \ + \ + if( !bCanAlign ) \ + endY = gs.imageEndY; /* transfer the whole image */ \ + else \ + assert( endY < gs.imageEndY); /* part of alignment condition */ \ + \ + if( ((gs.imageEndX-gs.trxpos.dx)%widthlimit) || ((gs.imageEndX-j)%widthlimit) ) { \ + /* transmit with a width of 1 */ \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, (1+(DSTPSM == 0x14)), endY); \ + } \ + else { \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, widthlimit, endY); \ + } \ + \ + if( nSize == 0 || i == gs.imageEndY ) \ + goto End; \ + } \ + \ + assert( MOD_POW2(i, blockheight) == 0 && j == gs.trxpos.dx); \ + \ + /* can align! */ \ + pitch = gs.imageEndX-gs.trxpos.dx; \ + area = pitch*blockheight; \ + fracX = gs.imageEndX-alignedX; \ + \ + /* on top of checking whether pbuf is alinged, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */ \ + bAligned = !((u32)(uptr)pbuf & 0xf) && (TRANSMIT_PITCH##TransSfx(pitch, T)&0xf) == 0; \ + \ + /* transfer aligning to blocks */ \ + for(; i < alignedY && nSize >= area; i += blockheight, nSize -= area) { \ + \ + if( bAligned || ((DSTPSM==PSMCT24) || (DSTPSM==PSMT8H) || (DSTPSM==PSMT4HH) || (DSTPSM==PSMT4HL)) ) { \ + for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH##TransSfx(blockwidth, T)/sizeof(T)) { \ + SwizzleBlock(pstart + getPixelAddress##psm##_0(tempj, i, gs.dstbuf.bw)*blockbits/8, \ + (u8*)pbuf, TRANSMIT_PITCH##TransSfx(pitch, T)); \ + } \ + } \ + else { \ + for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH##TransSfx(blockwidth, T)/sizeof(T)) { \ + SwizzleBlock##u(pstart + getPixelAddress##psm##_0(tempj, i, gs.dstbuf.bw)*blockbits/8, \ + (u8*)pbuf, TRANSMIT_PITCH##TransSfx(pitch, T)); \ + } \ + } \ + \ + /* transfer the rest */ \ + if( alignedX < gs.imageEndX ) { \ + TRANSMIT_HOSTLOCAL_X##TransSfx(psm, T, widthlimit, blockheight, alignedX); \ + pbuf -= TRANSMIT_PITCH##TransSfx((alignedX-gs.trxpos.dx), T)/sizeof(T); \ + } \ + else pbuf += (blockheight-1)*TRANSMIT_PITCH##TransSfx(pitch, T)/sizeof(T); \ + j = gs.trxpos.dx; \ + } \ + \ + if( TRANSMIT_PITCH##TransSfx(nSize, T)/4 > 0 ) { \ + TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, widthlimit, gs.imageEndY); \ + /* sometimes wrong sizes are sent (tekken tag) */ \ + assert( gs.imageTransfer == -1 || TRANSMIT_PITCH##TransSfx(nSize,T)/4 <= 2 ); \ + } \ + \ + END_HOSTLOCAL(); \ +} \ + +DEFINE_TRANSFERLOCAL(32, u32, 2, 32, 8, 8, _, SwizzleBlock32); +DEFINE_TRANSFERLOCAL(32Z, u32, 2, 32, 8, 8, _, SwizzleBlock32); +DEFINE_TRANSFERLOCAL(24, u8, 8, 32, 8, 8, _24, SwizzleBlock24); +DEFINE_TRANSFERLOCAL(24Z, u8, 8, 32, 8, 8, _24, SwizzleBlock24); +DEFINE_TRANSFERLOCAL(16, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16S, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16Z, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(16SZ, u16, 4, 16, 16, 8, _, SwizzleBlock16); +DEFINE_TRANSFERLOCAL(8, u8, 4, 8, 16, 16, _, SwizzleBlock8); +DEFINE_TRANSFERLOCAL(4, u8, 8, 4, 32, 16, _4, SwizzleBlock4); +DEFINE_TRANSFERLOCAL(8H, u8, 4, 32, 8, 8, _, SwizzleBlock8H); +DEFINE_TRANSFERLOCAL(4HL, u8, 8, 32, 8, 8, _4, SwizzleBlock4HL); +DEFINE_TRANSFERLOCAL(4HH, u8, 8, 32, 8, 8, _4, SwizzleBlock4HH); + +//#define T u8 +//#define widthlimit 8 +//#define blockbits 4 +//#define blockwidth 32 +//#define blockheight 16 +// +//void TransferHostLocal4(const void* pbyMem, u32 nQWordSize) +//{ +// START_HOSTLOCAL(); +// +// const T* pbuf = (const T*)pbyMem; +// u32 nSize = nQWordSize*16*2/TRANSMIT_PITCH_4(2, T); +// nSize = min(nSize, gs.imageWnew * gs.imageHnew); +// +// int endY = ROUND_UPPOW2(i, blockheight); +// int alignedY = ROUND_DOWNPOW2(gs.imageEndY, blockheight); +// int alignedX = ROUND_DOWNPOW2(gs.imageEndX, blockwidth); +// bool bCanAlign = MOD_POW2(gs.trxpos.dx, blockwidth) == 0 && (j == gs.trxpos.dx) && (alignedY > endY) && alignedX > gs.trxpos.dx; +// +// if( (gs.imageEndX-gs.trxpos.dx)%widthlimit ) { +// /* hack */ +// if( abs((int)nSize - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx)) <= widthlimit ) { +// /* don't transfer */ +// /*printf("bad texture %s: %d %d %d\n", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/ +// gs.imageTransfer = -1; +// } +// bCanAlign = false; +// } +// +// /* first align on block boundary */ +// if( MOD_POW2(i, blockheight) || !bCanAlign ) { +// +// if( !bCanAlign ) +// endY = gs.imageEndY; /* transfer the whole image */ +// else +// assert( endY < gs.imageEndY); /* part of alignment condition */ +// +// if( (DSTPSM == 0x13 || DSTPSM == 0x14) && ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) { +// /* transmit with a width of 1 */ +// TRANSMIT_HOSTLOCAL_Y_4(4, T, (1+(DSTPSM == 0x14)), endY); +// } +// else { +// TRANSMIT_HOSTLOCAL_Y_4(4, T, widthlimit, endY); +// } +// +// if( nSize == 0 || i == gs.imageEndY ) +// goto End; +// } +// +// assert( MOD_POW2(i, blockheight) == 0 && j == gs.trxpos.dx); +// +// /* can align! */ +// int pitch = gs.imageEndX-gs.trxpos.dx; +// u32 area = pitch*blockheight; +// int fracX = gs.imageEndX-alignedX; +// +// /* on top of checking whether pbuf is alinged, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */ +// bool bAligned = !((u32)pbuf & 0xf) && (TRANSMIT_PITCH_4(pitch, T)&0xf) == 0; +// +// /* transfer aligning to blocks */ +// for(; i < alignedY && nSize >= area; i += blockheight, nSize -= area) { +// +// if( bAligned || ((DSTPSM==PSMCT24) || (DSTPSM==PSMT8H) || (DSTPSM==PSMT4HH) || (DSTPSM==PSMT4HL)) ) { +// for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH_4(blockwidth, T)/sizeof(T)) { +// SwizzleBlock4(pstart + getPixelAddress4_0(tempj, i, gs.dstbuf.bw)*blockbits/8, +// (u8*)pbuf, TRANSMIT_PITCH_4(pitch, T)); +// } +// } +// else { +// for(int tempj = gs.trxpos.dx; tempj < alignedX; tempj += blockwidth, pbuf += TRANSMIT_PITCH_4(blockwidth, T)/sizeof(T)) { +// SwizzleBlock4u(pstart + getPixelAddress4_0(tempj, i, gs.dstbuf.bw)*blockbits/8, +// (u8*)pbuf, TRANSMIT_PITCH_4(pitch, T)); +// } +// } +// +// /* transfer the rest */ +// if( alignedX < gs.imageEndX ) { +// TRANSMIT_HOSTLOCAL_X_4(4, T, widthlimit, blockheight, alignedX); +// pbuf -= TRANSMIT_PITCH_4((alignedX-gs.trxpos.dx), T)/sizeof(T); +// } +// else pbuf += (blockheight-1)*TRANSMIT_PITCH_4(pitch, T)/sizeof(T); +// j = 0; +// } +// +// if( TRANSMIT_PITCH_4(nSize, T)/4 > 0 ) { +// TRANSMIT_HOSTLOCAL_Y_4(4, T, widthlimit, gs.imageEndY); +// /* sometimes wrong sizes are sent (tekken tag) */ +// assert( gs.imageTransfer == -1 || TRANSMIT_PITCH_4(nSize,T)/4 <= 2 ); +// } +// +// END_HOSTLOCAL(); +//} + +void TransferLocalHost32(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost24(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost16(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost16S(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost8(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost4(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost8H(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost4HL(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost4HH(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost32Z(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize) +{ +} + +void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize) +{ +} + +#define FILL_BLOCK(bw, bh, ox, oy, mult, psm, psmcol) { \ + b.vTexDims = Vector(BLOCK_TEXWIDTH/(float)(bw), BLOCK_TEXHEIGHT/(float)bh, 0, 0); \ + b.vTexBlock = Vector((float)bw/BLOCK_TEXWIDTH, (float)bh/BLOCK_TEXHEIGHT, ((float)ox+0.2f)/BLOCK_TEXWIDTH, ((float)oy+0.05f)/BLOCK_TEXHEIGHT); \ + b.width = bw; \ + b.height = bh; \ + b.colwidth = bh / 4; \ + b.colheight = bw / 8; \ + b.bpp = 32/mult; \ + \ + b.pageTable = &g_pageTable##psm[0][0]; \ + b.blockTable = &g_blockTable##psm[0][0]; \ + b.columnTable = &g_columnTable##psmcol[0][0]; \ + assert( sizeof(g_pageTable##psm) == bw*bh*sizeof(g_pageTable##psm[0][0]) ); \ + psrcf = (float*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; \ + psrcw = (u16*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH; \ + for(i = 0; i < bh; ++i) { \ + for(j = 0; j < bw; ++j) { \ + /* fill the table */ \ + u32 u = g_blockTable##psm[(i / b.colheight)][(j / b.colwidth)] * 64 * mult + g_columnTable##psmcol[i%b.colheight][j%b.colwidth]; \ + b.pageTable[i*bw+j] = u; \ + if( floatfmt ) { \ + psrcf[i*BLOCK_TEXWIDTH+j] = (float)(u) / (float)(GPU_TEXWIDTH*mult); \ + } \ + else { \ + psrcw[i*BLOCK_TEXWIDTH+j] = u; \ + } \ + } \ + } \ + \ + if( floatfmt ) { \ + assert( floatfmt ); \ + psrcv = (Vector*)&vBilinearData[0] + ox + oy * BLOCK_TEXWIDTH; \ + for(i = 0; i < bh; ++i) { \ + for(j = 0; j < bw; ++j) { \ + Vector* pv = &psrcv[i*BLOCK_TEXWIDTH+j]; \ + pv->x = psrcf[i*BLOCK_TEXWIDTH+j]; \ + pv->y = psrcf[i*BLOCK_TEXWIDTH+((j+1)%bw)]; \ + pv->z = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+j]; \ + pv->w = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+((j+1)%bw)]; \ + } \ + } \ + } \ + b.getPixelAddress = getPixelAddress##psm; \ + b.getPixelAddress_0 = getPixelAddress##psm##_0; \ + b.writePixel = writePixel##psm; \ + b.writePixel_0 = writePixel##psm##_0; \ + b.readPixel = readPixel##psm; \ + b.readPixel_0 = readPixel##psm##_0; \ + b.TransferHostLocal = TransferHostLocal##psm; \ + b.TransferLocalHost = TransferLocalHost##psm; \ +} \ + +void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, int floatfmt) +{ + vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * (floatfmt ? 4 : 2)); + if( floatfmt ) + vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(Vector)); + + int i, j; + BLOCK b; + float* psrcf = NULL; + u16* psrcw = NULL; + Vector* psrcv = NULL; + + memset(m_Blocks, 0, sizeof(m_Blocks)); + + // 32 + FILL_BLOCK(64, 32, 0, 0, 1, 32, 32); + m_Blocks[PSMCT32] = b; + + // 24 (same as 32 except write/readPixel are different) + m_Blocks[PSMCT24] = b; + m_Blocks[PSMCT24].writePixel = writePixel24; + m_Blocks[PSMCT24].writePixel_0 = writePixel24_0; + m_Blocks[PSMCT24].readPixel = readPixel24; + m_Blocks[PSMCT24].readPixel_0 = readPixel24_0; + m_Blocks[PSMCT24].TransferHostLocal = TransferHostLocal24; + m_Blocks[PSMCT24].TransferLocalHost = TransferLocalHost24; + + // 8H (same as 32 except write/readPixel are different) + m_Blocks[PSMT8H] = b; + m_Blocks[PSMT8H].writePixel = writePixel8H; + m_Blocks[PSMT8H].writePixel_0 = writePixel8H_0; + m_Blocks[PSMT8H].readPixel = readPixel8H; + m_Blocks[PSMT8H].readPixel_0 = readPixel8H_0; + m_Blocks[PSMT8H].TransferHostLocal = TransferHostLocal8H; + m_Blocks[PSMT8H].TransferLocalHost = TransferLocalHost8H; + + m_Blocks[PSMT4HL] = b; + m_Blocks[PSMT4HL].writePixel = writePixel4HL; + m_Blocks[PSMT4HL].writePixel_0 = writePixel4HL_0; + m_Blocks[PSMT4HL].readPixel = readPixel4HL; + m_Blocks[PSMT4HL].readPixel_0 = readPixel4HL_0; + m_Blocks[PSMT4HL].TransferHostLocal = TransferHostLocal4HL; + m_Blocks[PSMT4HL].TransferLocalHost = TransferLocalHost4HL; + + m_Blocks[PSMT4HH] = b; + m_Blocks[PSMT4HH].writePixel = writePixel4HH; + m_Blocks[PSMT4HH].writePixel_0 = writePixel4HH_0; + m_Blocks[PSMT4HH].readPixel = readPixel4HH; + m_Blocks[PSMT4HH].readPixel_0 = readPixel4HH_0; + m_Blocks[PSMT4HH].TransferHostLocal = TransferHostLocal4HH; + m_Blocks[PSMT4HH].TransferLocalHost = TransferLocalHost4HH; + + // 32z + FILL_BLOCK(64, 32, 64, 0, 1, 32Z, 32); + m_Blocks[PSMT32Z] = b; + + // 24Z (same as 32Z except write/readPixel are different) + m_Blocks[PSMT24Z] = b; + m_Blocks[PSMT24Z].writePixel = writePixel24Z; + m_Blocks[PSMT24Z].writePixel_0 = writePixel24Z_0; + m_Blocks[PSMT24Z].readPixel = readPixel24Z; + m_Blocks[PSMT24Z].readPixel_0 = readPixel24Z_0; + m_Blocks[PSMT24Z].TransferHostLocal = TransferHostLocal24Z; + m_Blocks[PSMT24Z].TransferLocalHost = TransferLocalHost24Z; + + // 16 + FILL_BLOCK(64, 64, 0, 32, 2, 16, 16); + m_Blocks[PSMCT16] = b; + + // 16s + FILL_BLOCK(64, 64, 64, 32, 2, 16S, 16); + m_Blocks[PSMCT16S] = b; + + // 16z + FILL_BLOCK(64, 64, 0, 96, 2, 16Z, 16); + m_Blocks[PSMT16Z] = b; + + // 16sz + FILL_BLOCK(64, 64, 64, 96, 2, 16SZ, 16); + m_Blocks[PSMT16SZ] = b; + + // 8 + FILL_BLOCK(128, 64, 0, 160, 4, 8, 8); + m_Blocks[PSMT8] = b; + + // 4 + FILL_BLOCK(128, 128, 0, 224, 8, 4, 4); + m_Blocks[PSMT4] = b; +} diff --git a/plugins/gs/zerogs/opengl/Mem.h b/plugins/gs/zerogs/opengl/Mem.h new file mode 100644 index 0000000..bef2373 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Mem.h @@ -0,0 +1,487 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#include +#include + +// works only when base is a power of 2 +#define ROUND_UPPOW2(val, base) (((val)+(base-1))&~(base-1)) +#define ROUND_DOWNPOW2(val, base) ((val)&~(base-1)) +#define MOD_POW2(val, base) ((val)&(base-1)) + +// d3d texture dims +#define BLOCK_TEXWIDTH 128 +#define BLOCK_TEXHEIGHT 512 + +// rest not visible externally +struct BLOCK +{ + BLOCK() { memset(this, 0, sizeof(BLOCK)); } + + // shader constants for this block + Vector vTexBlock; + Vector vTexDims; + int width, height; // dims of one page in pixels + int bpp; + int colwidth, colheight; + u32* pageTable; // offset inside each page + u32* blockTable; + u32* columnTable; + + u32 (*getPixelAddress)(int x, int y, u32 bp, u32 bw); + u32 (*getPixelAddress_0)(int x, int y, u32 bw); + void (*writePixel)(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw); + void (*writePixel_0)(void* pmem, int x, int y, u32 pixel, u32 bw); + u32 (*readPixel)(const void* pmem, int x, int y, u32 bp, u32 bw); + u32 (*readPixel_0)(const void* pmem, int x, int y, u32 bw); + void (*TransferHostLocal)(const void* pbyMem, u32 nQWordSize); + void (*TransferLocalHost)(void* pbyMem, u32 nQWordSize); + + // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT + static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt); +}; + +extern BLOCK m_Blocks[]; + +extern u32 g_blockTable32[4][8]; +extern u32 g_blockTable32Z[4][8]; +extern u32 g_blockTable16[8][4]; +extern u32 g_blockTable16S[8][4]; +extern u32 g_blockTable16Z[8][4]; +extern u32 g_blockTable16SZ[8][4]; +extern u32 g_blockTable8[4][8]; +extern u32 g_blockTable4[8][4]; + +extern u32 g_columnTable32[8][8]; +extern u32 g_columnTable16[8][16]; +extern u32 g_columnTable8[16][16]; +extern u32 g_columnTable4[16][32]; + +extern u32 g_pageTable32[32][64]; +extern u32 g_pageTable32Z[32][64]; +extern u32 g_pageTable16[64][64]; +extern u32 g_pageTable16S[64][64]; +extern u32 g_pageTable16Z[64][64]; +extern u32 g_pageTable16SZ[64][64]; +extern u32 g_pageTable8[64][128]; +extern u32 g_pageTable4[128][128]; + +__forceinline u32 getPixelAddress32(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +__forceinline u32 getPixelAddress32_0(int x, int y, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = basepage * 2048 + g_pageTable32[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +#define getPixelAddress24 getPixelAddress32 +#define getPixelAddress24_0 getPixelAddress32_0 +#define getPixelAddress8H getPixelAddress32 +#define getPixelAddress8H_0 getPixelAddress32_0 +#define getPixelAddress4HL getPixelAddress32 +#define getPixelAddress4HL_0 getPixelAddress32_0 +#define getPixelAddress4HH getPixelAddress32 +#define getPixelAddress4HH_0 getPixelAddress32_0 + +__forceinline u32 getPixelAddress16(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16S(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16S[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16S_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16S[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress8(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * ((bw+127)>>7)) + (x>>7); + u32 word = bp * 256 + basepage * 8192 + g_pageTable8[y&63][x&127]; + //assert (word < 0x400000); + //word = min(word, 0x3fffff); + return word; +} + +__forceinline u32 getPixelAddress8_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * ((bw+127)>>7)) + (x>>7); + u32 word = basepage * 8192 + g_pageTable8[y&63][x&127]; + //assert (word < 0x400000); + //word = min(word, 0x3fffff); + return word; +} + +__forceinline u32 getPixelAddress4(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>7) * ((bw+127)>>7)) + (x>>7); + u32 word = bp * 512 + basepage * 16384 + g_pageTable4[y&127][x&127]; + //assert (word < 0x800000); + //word = min(word, 0x7fffff); + return word; +} + +__forceinline u32 getPixelAddress4_0(int x, int y, u32 bw) { + u32 basepage = ((y>>7) * ((bw+127)>>7)) + (x>>7); + u32 word = basepage * 16384 + g_pageTable4[y&127][x&127]; + //assert (word < 0x800000); + //word = min(word, 0x7fffff); + return word; +} + +__forceinline u32 getPixelAddress32Z(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = bp * 64 + basepage * 2048 + g_pageTable32Z[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +__forceinline u32 getPixelAddress32Z_0(int x, int y, u32 bw) { + u32 basepage = ((y>>5) * (bw>>6)) + (x>>6); + u32 word = basepage * 2048 + g_pageTable32Z[y&31][x&63]; + //assert (word < 0x100000); + //word = min(word, 0xfffff); + return word; +} + +#define getPixelAddress24Z getPixelAddress32Z +#define getPixelAddress24Z_0 getPixelAddress32Z_0 + +__forceinline u32 getPixelAddress16Z(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16Z[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16Z_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16Z[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16SZ(int x, int y, u32 bp, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = bp * 128 + basepage * 4096 + g_pageTable16SZ[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline u32 getPixelAddress16SZ_0(int x, int y, u32 bw) { + u32 basepage = ((y>>6) * (bw>>6)) + (x>>6); + u32 word = basepage * 4096 + g_pageTable16SZ[y&63][x&63]; + //assert (word < 0x200000); + //word = min(word, 0x1fffff); + return word; +} + +__forceinline void writePixel32(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u32*)pmem)[getPixelAddress32(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel24(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)&((u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +__forceinline void writePixel16(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel16S(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16S(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel8(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u8*)pmem)[getPixelAddress8(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel8H(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u8*)pmem)[4*getPixelAddress32(x, y, bp, bw)+3] = pixel; +} + +__forceinline void writePixel4(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((u8*)pmem)[addr/2]; + if (addr & 0x1) ((u8*)pmem)[addr/2] = (pix & 0x0f) | (pixel << 4); + else ((u8*)pmem)[addr/2] = (pix & 0xf0) | (pixel); +} + +__forceinline void writePixel4HL(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HL(x, y, bp, bw)+3; + *p = (*p & 0xf0) | pixel; +} + +__forceinline void writePixel4HH(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HH(x, y, bp, bw)+3; + *p = (*p & 0x0f) | (pixel<<4); +} + +__forceinline void writePixel32Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel24Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + u8 *buf = (u8*)pmem + 4*getPixelAddress32Z(x, y, bp, bw); + u8 *pix = (u8*)&pixel; + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +} + +__forceinline void writePixel16Z(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)] = pixel; +} + +__forceinline void writePixel16SZ(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw) { + ((u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)] = pixel; +} + + +/////////////// + +__forceinline u32 readPixel32(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)]; +} + +__forceinline u32 readPixel24(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32(x, y, bp, bw)] & 0xffffff; +} + +__forceinline u32 readPixel16(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16(x, y, bp, bw)]; +} + +__forceinline u32 readPixel16S(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16S(x, y, bp, bw)]; +} + +__forceinline u32 readPixel8(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u8*)pmem)[getPixelAddress8(x, y, bp, bw)]; +} + +__forceinline u32 readPixel8H(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u8*)pmem)[4*getPixelAddress32(x, y, bp, bw) + 3]; +} + +__forceinline u32 readPixel4(const void* pmem, int x, int y, u32 bp, u32 bw) { + u32 addr = getPixelAddress4(x, y, bp, bw); + u8 pix = ((const u8*)pmem)[addr/2]; + if (addr & 0x1) + return pix >> 4; + else return pix & 0xf; +} + +__forceinline u32 readPixel4HL(const void* pmem, int x, int y, u32 bp, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HL(x, y, bp, bw)+3; + return *p & 0x0f; +} + +__forceinline u32 readPixel4HH(const void* pmem, int x, int y, u32 bp, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HH(x, y, bp, bw) + 3; + return *p >> 4; +} + +/////////////// + +__forceinline u32 readPixel32Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)]; +} + +__forceinline u32 readPixel24Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z(x, y, bp, bw)] & 0xffffff; +} + +__forceinline u32 readPixel16Z(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16Z(x, y, bp, bw)]; +} + +__forceinline u32 readPixel16SZ(const void* pmem, int x, int y, u32 bp, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16SZ(x, y, bp, bw)]; +} + +/////////////////////////////// +// Functions that take 0 bps // +/////////////////////////////// + +__forceinline void writePixel32_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u32*)pmem)[getPixelAddress32_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel24_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *buf = (u8*)&((u32*)pmem)[getPixelAddress32_0(x, y, bw)]; + u8 *pix = (u8*)&pixel; +#if defined(_MSC_VER) && defined(__x86_64__) + memcpy(buf, pix, 3); +#else + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +#endif +} + +__forceinline void writePixel16_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel16S_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16S_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel8_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u8*)pmem)[getPixelAddress8_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel8H_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u8*)pmem)[4*getPixelAddress32_0(x, y, bw)+3] = pixel; +} + +__forceinline void writePixel4_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u32 addr = getPixelAddress4_0(x, y, bw); + u8 pix = ((u8*)pmem)[addr/2]; + if (addr & 0x1) ((u8*)pmem)[addr/2] = (pix & 0x0f) | (pixel << 4); + else ((u8*)pmem)[addr/2] = (pix & 0xf0) | (pixel); +} + +__forceinline void writePixel4HL_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HL_0(x, y, bw)+3; + *p = (*p & 0xf0) | pixel; +} + +__forceinline void writePixel4HH_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *p = (u8*)pmem + 4*getPixelAddress4HH_0(x, y, bw)+3; + *p = (*p & 0x0f) | (pixel<<4); +} + +__forceinline void writePixel32Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u32*)pmem)[getPixelAddress32Z_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel24Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + u8 *buf = (u8*)pmem + 4*getPixelAddress32Z_0(x, y, bw); + u8 *pix = (u8*)&pixel; +#if defined(_MSC_VER) && defined(__x86_64__) + memcpy(buf, pix, 3); +#else + buf[0] = pix[0]; buf[1] = pix[1]; buf[2] = pix[2]; +#endif +} + +__forceinline void writePixel16Z_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16Z_0(x, y, bw)] = pixel; +} + +__forceinline void writePixel16SZ_0(void* pmem, int x, int y, u32 pixel, u32 bw) { + ((u16*)pmem)[getPixelAddress16SZ_0(x, y, bw)] = pixel; +} + + +/////////////// + +__forceinline u32 readPixel32_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32_0(x, y, bw)]; +} + +__forceinline u32 readPixel24_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32_0(x, y, bw)] & 0xffffff; +} + +__forceinline u32 readPixel16_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16_0(x, y, bw)]; +} + +__forceinline u32 readPixel16S_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16S_0(x, y, bw)]; +} + +__forceinline u32 readPixel8_0(const void* pmem, int x, int y, u32 bw) { + return ((const u8*)pmem)[getPixelAddress8_0(x, y, bw)]; +} + +__forceinline u32 readPixel8H_0(const void* pmem, int x, int y, u32 bw) { + return ((const u8*)pmem)[4*getPixelAddress32_0(x, y, bw) + 3]; +} + +__forceinline u32 readPixel4_0(const void* pmem, int x, int y, u32 bw) { + u32 addr = getPixelAddress4_0(x, y, bw); + u8 pix = ((const u8*)pmem)[addr/2]; + if (addr & 0x1) + return pix >> 4; + else return pix & 0xf; +} + +__forceinline u32 readPixel4HL_0(const void* pmem, int x, int y, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HL_0(x, y, bw)+3; + return *p & 0x0f; +} + +__forceinline u32 readPixel4HH_0(const void* pmem, int x, int y, u32 bw) { + const u8 *p = (const u8*)pmem+4*getPixelAddress4HH_0(x, y, bw) + 3; + return *p >> 4; +} + +/////////////// + +__forceinline u32 readPixel32Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z_0(x, y, bw)]; +} + +__forceinline u32 readPixel24Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u32*)pmem)[getPixelAddress32Z_0(x, y, bw)] & 0xffffff; +} + +__forceinline u32 readPixel16Z_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16Z_0(x, y, bw)]; +} + +__forceinline u32 readPixel16SZ_0(const void* pmem, int x, int y, u32 bw) { + return ((const u16*)pmem)[getPixelAddress16SZ_0(x, y, bw)]; +} + +#endif /* __MEM_H__ */ diff --git a/plugins/gs/zerogs/opengl/PS2Edefs.h b/plugins/gs/zerogs/opengl/PS2Edefs.h new file mode 100644 index 0000000..da9166e --- /dev/null +++ b/plugins/gs/zerogs/opengl/PS2Edefs.h @@ -0,0 +1,815 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits) +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgetLastTag GSgetLastTag; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/gs/zerogs/opengl/PS2Etypes.h b/plugins/gs/zerogs/opengl/PS2Etypes.h new file mode 100644 index 0000000..1ad73e2 --- /dev/null +++ b/plugins/gs/zerogs/opengl/PS2Etypes.h @@ -0,0 +1,76 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif // _MSC_VER + +#if defined(__x86_64__) +typedef u64 uptr; +typedef s64 sptr; +#else +typedef u32 uptr; +typedef s32 sptr; +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/gs/zerogs/opengl/Regs.cpp b/plugins/gs/zerogs/opengl/Regs.cpp new file mode 100644 index 0000000..d67efa5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Regs.cpp @@ -0,0 +1,981 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerorog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "Regs.h" + +#include "zerogs.h" +#include "targets.h" + +const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff }; +const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 }; + +#ifdef __MSCW32__ +#pragma warning(disable:4244) +#endif + +GIFRegHandler g_GIFPackedRegHandlers[16] = { + GIFRegHandlerPRIM, GIFPackedRegHandlerRGBA, GIFPackedRegHandlerSTQ, GIFPackedRegHandlerUV, + GIFPackedRegHandlerXYZF2, GIFPackedRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2, + GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFPackedRegHandlerFOG, GIFPackedRegHandlerNull, + GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFPackedRegHandlerA_D, GIFPackedRegHandlerNOP }; + +GIFRegHandler g_GIFRegHandlers[] = { + GIFRegHandlerPRIM, GIFRegHandlerRGBAQ, GIFRegHandlerST, GIFRegHandlerUV, + GIFRegHandlerXYZF2, GIFRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2, + GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFRegHandlerFOG, GIFRegHandlerNull, + GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFRegHandlerNOP, GIFRegHandlerNOP, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerTEX1_1, GIFRegHandlerTEX1_2, GIFRegHandlerTEX2_1, GIFRegHandlerTEX2_2, + GIFRegHandlerXYOFFSET_1,GIFRegHandlerXYOFFSET_2,GIFRegHandlerPRMODECONT,GIFRegHandlerPRMODE, + GIFRegHandlerTEXCLUT, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerSCANMSK, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerMIPTBP1_1, GIFRegHandlerMIPTBP1_2, GIFRegHandlerMIPTBP2_1, GIFRegHandlerMIPTBP2_2, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerTEXA, + GIFRegHandlerNull, GIFRegHandlerFOGCOL, GIFRegHandlerNull, GIFRegHandlerTEXFLUSH, + GIFRegHandlerSCISSOR_1, GIFRegHandlerSCISSOR_2, GIFRegHandlerALPHA_1, GIFRegHandlerALPHA_2, + GIFRegHandlerDIMX, GIFRegHandlerDTHE, GIFRegHandlerCOLCLAMP, GIFRegHandlerTEST_1, + GIFRegHandlerTEST_2, GIFRegHandlerPABE, GIFRegHandlerFBA_1, GIFRegHandlerFBA_2, + GIFRegHandlerFRAME_1, GIFRegHandlerFRAME_2, GIFRegHandlerZBUF_1, GIFRegHandlerZBUF_2, + GIFRegHandlerBITBLTBUF, GIFRegHandlerTRXPOS, GIFRegHandlerTRXREG, GIFRegHandlerTRXDIR, + GIFRegHandlerHWREG, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, + GIFRegHandlerSIGNAL, GIFRegHandlerFINISH, GIFRegHandlerLABEL, GIFRegHandlerNull }; + +C_ASSERT(sizeof(g_GIFRegHandlers)/sizeof(g_GIFRegHandlers[0]) == 100 ); + +// values for keeping track of changes +u32 s_uTex1Data[2][2] = {0}, s_uClampData[2] = {0}; + +void FASTCALL(GIFPackedRegHandlerNull(u32* data)) +{ +#ifdef _DEBUG + printf("Unexpected packed reg handler %8.8lx_%8.8lx %x\n", data[0], data[1], data[2]); +#endif +} + +void FASTCALL(GIFPackedRegHandlerRGBA(u32* data)) +{ + gs.rgba = (data[0] & 0xff) | + ((data[1] & 0xff) << 8) | + ((data[2] & 0xff) << 16) | + ((data[3] & 0xff) << 24); + gs.vertexregs.rgba = gs.rgba; + gs.vertexregs.q = gs.q; +} + +void FASTCALL(GIFPackedRegHandlerSTQ(u32* data)) +{ + *(u32*)&gs.vertexregs.s = data[0]&0xffffff00; + *(u32*)&gs.vertexregs.t = data[1]&0xffffff00; + *(u32*)&gs.q = data[2]; +} + +void FASTCALL(GIFPackedRegHandlerUV(u32* data)) +{ + gs.vertexregs.u = data[0] & 0x3fff; + gs.vertexregs.v = data[1] & 0x3fff; +} + +#define KICK_VERTEX2() { \ + if( ++gs.primC >= (int)g_primmult[prim->prim]) { \ + (*ZeroGS::drawfn[prim->prim])(); \ + gs.primC -= g_primsub[prim->prim]; \ + } \ +} \ + +#define KICK_VERTEX3() { \ + if( ++gs.primC >= (int)g_primmult[prim->prim] ) { \ + gs.primC -= g_primsub[prim->prim]; \ + if( prim->prim == 5 ) { \ + /* tri fans need special processing */ \ + if( gs.nTriFanVert == gs.primIndex ) \ + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); \ + } \ + } \ +} \ + +void FASTCALL(GIFPackedRegHandlerXYZF2(u32* data)) +{ + gs.vertexregs.x = (data[0] >> 0) & 0xffff; + gs.vertexregs.y = (data[1] >> 0) & 0xffff; + gs.vertexregs.z = (data[2] >> 4) & 0xffffff; + gs.vertexregs.f = (data[3] >> 4) & 0xff; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + if( data[3] & 0x8000 ) { + KICK_VERTEX3(); + } + else { + KICK_VERTEX2(); + } +} + +void FASTCALL(GIFPackedRegHandlerXYZ2(u32* data)) +{ + gs.vertexregs.x = (data[0] >> 0) & 0xffff; + gs.vertexregs.y = (data[1] >> 0) & 0xffff; + gs.vertexregs.z = data[2]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + if( data[3] & 0x8000 ) { + KICK_VERTEX3(); + } + else { + KICK_VERTEX2(); + } +} + +void FASTCALL(GIFPackedRegHandlerFOG(u32* data)) +{ + gs.vertexregs.f = (data[3]&0xff0)>>4; +} + +void FASTCALL(GIFPackedRegHandlerA_D(u32* data)) +{ + if((data[2] & 0xff) < 100) + g_GIFRegHandlers[data[2] & 0xff](data); + else + GIFRegHandlerNull(data); +} + +void FASTCALL(GIFPackedRegHandlerNOP(u32* data)) +{ +} + +extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY; + +void tex0Write(int i, u32 *data) +{ + u32 psm = (data[0] >> 20) & 0x3f; + if( psm == 9 ) psm = 1; // hmm..., ffx intro menu + + if( m_Blocks[psm].bpp == 0 ) { + // kh and others + return; + } + + ZeroGS::vb[i].uNextTex0Data[0] = data[0]; + ZeroGS::vb[i].uNextTex0Data[1] = data[1]; + ZeroGS::vb[i].bNeedTexCheck = 1; + + // don't update unless necessary + if( PSMT_ISCLUT(psm) ) { + if( ZeroGS::CheckChangeInClut(data[1], psm) ) { + // loading clut, so flush whole texture + ZeroGS::vb[i].FlushTexData(); + } + // check if csa is the same!! (ffx bisaid island, grass) + else if( (data[1]&0x1f780000) != (ZeroGS::vb[i].uCurTex0Data[1]&0x1f780000) ) { + ZeroGS::Flush(i); // flush any previous entries + } + } +} + +void tex2Write(int i, u32 *data) +{ + tex0Info& tex0 = ZeroGS::vb[i].tex0; + + if( ZeroGS::vb[i].bNeedTexCheck ) + ZeroGS::vb[i].FlushTexData(); + + u32 psm = (data[0] >> 20) & 0x3f; + if( psm == 9 ) psm = 1; // hmm..., ffx intro menu + + u32* s_uTex0Data = ZeroGS::vb[i].uCurTex0Data; + + // don't update unless necessary + if( (s_uTex0Data[0]&0x03f00000) == (data[0]&0x03f00000) ) { // psm is the same + + if( PSMT_ISCLUT(psm) ) { + // have to write the CLUT again if changed + if( (s_uTex0Data[1]&0x1fffffe0) == (data[1]&0x1fffffe0) ) { + + if( data[1]&0xe0000000 ) { + tex0.cld = (data[1]>>29)&7; + ZeroGS::texClutWrite(i); + // invalidate to make sure target didn't change! + ZeroGS::vb[i].bVarsTexSync = FALSE; + } + + return; + } + + // CSAs have to be the same! +// if( (data[1]&0xe0000000) == 0 ) { +// +// if( (s_uTex0Data[1]&0x1f100000) != (data[1]&0x1f100000) ) +// ZeroGS::Flush(i); +// +// // clut isn't going to be loaded so can ignore, but at least update CSA and CPSM! +// ZeroGS::vb[i].uCurTex0Data[1] = (ZeroGS::vb[i].uCurTex0Data[1]&0xe087ffff)|(data[1]&0x1f780000); +// +// if( ZeroGS::vb[i].tex0.cpsm <= 1 ) ZeroGS::vb[i].tex0.csa = (data[1] >> 24) & 0xf; +// else ZeroGS::vb[i].tex0.csa = (data[1] >> 24) & 0x1f; +// +// ZeroGS::vb[i].tex0.cpsm = (data[1] >> 19) & 0xe; +// +// ZeroGS::vb[i].bVarsTexSync = FALSE; +// return; +// } + + // fall through + } + else { + //ZeroGS::vb[i].bVarsTexSync = FALSE; + return; + } + } + + ZeroGS::Flush(i); + ZeroGS::vb[i].bVarsTexSync = FALSE; + ZeroGS::vb[i].bTexConstsSync = FALSE; + + s_uTex0Data[0] = (s_uTex0Data[0]&~0x03f00000)|(psm<<20); + s_uTex0Data[1] = (s_uTex0Data[1]&0x1f)|(data[1]&~0x1f); + + tex0.psm = psm; + + if( PSMT_ISCLUT(tex0.psm) ) { + tex0.cbp = (data[1] >> 5) & 0x3fff; + tex0.cpsm = (data[1] >> 19) & 0xe; + tex0.csm = (data[1] >> 23) & 0x1; + + if( tex0.cpsm <= 1 ) tex0.csa = (data[1] >> 24) & 0xf; + else tex0.csa = (data[1] >> 24) & 0x1f; + + tex0.cld = (data[1] >> 29) & 0x7; + ZeroGS::texClutWrite(i); + } +} + +__forceinline void frameWrite(int i, u32 *data) +{ + frameInfo& gsfb = ZeroGS::vb[i].gsfb; + + if( (gsfb.fbp == ((data[0] ) & 0x1ff) * 32) && + (gsfb.fbw == ((data[0] >> 16) & 0x3f) * 64) && + gsfb.psm == ((data[0] >> 24) & 0x3f) && + (gsfb.fbm == data[1]) ) { + return; + } + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + gsfb.fbp = ((data[0] ) & 0x1ff) * 32; + gsfb.fbw = ((data[0] >> 16) & 0x3f) * 64; + gsfb.psm = (data[0] >> 24) & 0x3f; + gsfb.fbm = data[1]; + + if (gsfb.fbw > 0) { + + gsfb.fbh = (1024*1024-64*gsfb.fbp) / gsfb.fbw; + gsfb.fbh &= ~0x1f; + if( gsfb.psm & 2 ) + gsfb.fbh *= 2; + if( gsfb.fbh > 1024 ) gsfb.fbh = 1024; + } + else gsfb.fbh = 0; + + if( gsfb.psm == 1 ) gsfb.fbm |= 0xff000000; + else if( gsfb.psm & 2 ) { + + } + + ZeroGS::vb[i].bNeedFrameCheck = 1; +} + +__forceinline void testWrite(int i, u32 *data) +{ + pixTest* test = &ZeroGS::vb[i].test; + + if( (*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff) ) + return; + + ZeroGS::Flush(i); + *(u32*)test = data[0]; + +// test.ate = (data[0] ) & 0x1; +// test.atst = (data[0] >> 1) & 0x7; +// test.aref = (data[0] >> 4) & 0xff; +// test.afail = (data[0] >> 12) & 0x3; +// test.date = (data[0] >> 14) & 0x1; +// test.datm = (data[0] >> 15) & 0x1; +// test.zte = (data[0] >> 16) & 0x1; +// test.ztst = (data[0] >> 17) & 0x3; +} + +__forceinline void clampWrite(int i, u32 *data) +{ + clampInfo& clamp = ZeroGS::vb[i].clamp; + + if( s_uClampData[i] != data[0] || ((clamp.minv>>8)|(clamp.maxv<<2)) != (data[1]&0x0fff) ) { + +// if( ZeroGS::vb[i].bNeedTexCheck ) +// ZeroGS::vb[i].FlushTexData(); + + ZeroGS::Flush(i); + s_uClampData[i] = data[0]; + + clamp.wms = (data[0] ) & 0x3; + clamp.wmt = (data[0] >> 2) & 0x3; + clamp.minu = (data[0] >> 4) & 0x3ff; + clamp.maxu = (data[0] >> 14) & 0x3ff; + clamp.minv =((data[0] >> 24) & 0xff) | ((data[1] & 0x3) << 8); + clamp.maxv = (data[1] >> 2) & 0x3ff; + + ZeroGS::vb[i].bTexConstsSync = FALSE; + } +} + +void FASTCALL(GIFRegHandlerNull(u32* data)) +{ + // 0x7f happens on a lot of games + if( data[2] != 0x7f && (data[0] || data[1]) ) { +#ifdef _DEBUG + printf("Unexpected reg handler %x %x %x\n", data[0], data[1], data[2]); +#endif + } +} + +void FASTCALL(GIFRegHandlerPRIM(u32 *data)) +{ + if (data[0] & ~0x3ff) { +#ifdef WARN_LOG + //WARN_LOG("warning: unknown bits in prim %8.8lx_%8.8lx\n", data[1], data[0]); +#endif + } + + gs.nTriFanVert = gs.primIndex; + gs.primC = 0; + prim->prim = (data[0]) & 0x7; + gs._prim[0].prim = (data[0]) & 0x7; + gs._prim[1].prim = (data[0]) & 0x7; + gs._prim[1]._val = (data[0]>>3)&0xff; + + ZeroGS::Prim(); +} + +void FASTCALL(GIFRegHandlerRGBAQ(u32* data)) +{ + gs.rgba = data[0]; + gs.vertexregs.rgba = data[0]; + *(u32*)&gs.vertexregs.q = data[1]; +} + +void FASTCALL(GIFRegHandlerST(u32* data)) +{ + *(u32*)&gs.vertexregs.s = data[0]&0xffffff00; + *(u32*)&gs.vertexregs.t = data[1]&0xffffff00; + //*(u32*)&gs.q = data[2]; +} + +void FASTCALL(GIFRegHandlerUV(u32* data)) +{ + gs.vertexregs.u = (data[0]) & 0x3fff; + gs.vertexregs.v = (data[0] >> 16) & 0x3fff; +} + +void FASTCALL(GIFRegHandlerXYZF2(u32* data)) +{ + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1] & 0xffffff; + gs.vertexregs.f = data[1] >> 24; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX2(); +} + +void FASTCALL(GIFRegHandlerXYZ2(u32* data)) +{ + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX2(); +} + +void FASTCALL(GIFRegHandlerTEX0_1(u32* data)) +{ + tex0Write(0, data); +} + +void FASTCALL(GIFRegHandlerTEX0_2(u32* data)) +{ + tex0Write(1, data); +} + +void FASTCALL(GIFRegHandlerCLAMP_1(u32* data)) +{ + clampWrite(0, data); +} + +void FASTCALL(GIFRegHandlerCLAMP_2(u32* data)) +{ + clampWrite(1, data); +} + +void FASTCALL(GIFRegHandlerFOG(u32* data)) +{ + //gs.gsvertex[gs.primIndex].f = (data[1] >> 24); // shift to upper bits + gs.vertexregs.f = data[1]>>24; +} + +void FASTCALL(GIFRegHandlerXYZF3(u32* data)) +{ + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1] & 0xffffff; + gs.vertexregs.f = data[1] >> 24; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX3(); +} + +void FASTCALL(GIFRegHandlerXYZ3(u32* data)) +{ + gs.vertexregs.x = (data[0]) & 0xffff; + gs.vertexregs.y = (data[0] >> (16)) & 0xffff; + gs.vertexregs.z = data[1]; + gs.gsvertex[gs.primIndex] = gs.vertexregs; + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + + KICK_VERTEX3(); +} + +void FASTCALL(GIFRegHandlerNOP(u32* data)) +{ +} + +void FASTCALL(GIFRegHandlerTEX1_1(u32* data)) +{ + tex1Info& tex1 = ZeroGS::vb[0].tex1; + + if( conf.bilinear && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7)) ) { + ZeroGS::Flush(0); + ZeroGS::vb[0].bVarsTexSync = FALSE; + } + tex1.lcm = (data[0] ) & 0x1; + tex1.mxl = (data[0] >> 2) & 0x7; + tex1.mmag = (data[0] >> 5) & 0x1; + tex1.mmin = (data[0] >> 6) & 0x7; + tex1.mtba = (data[0] >> 9) & 0x1; + tex1.l = (data[0] >> 19) & 0x3; + tex1.k = (data[1] >> 4) & 0xff; +} + +void FASTCALL(GIFRegHandlerTEX1_2(u32* data)) +{ + tex1Info& tex1 = ZeroGS::vb[1].tex1; + + if( conf.bilinear && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7)) ) { + ZeroGS::Flush(1); + ZeroGS::vb[1].bVarsTexSync = FALSE; + } + + tex1.lcm = (data[0] ) & 0x1; + tex1.mxl = (data[0] >> 2) & 0x7; + tex1.mmag = (data[0] >> 5) & 0x1; + tex1.mmin = (data[0] >> 6) & 0x7; + tex1.mtba = (data[0] >> 9) & 0x1; + tex1.l = (data[0] >> 19) & 0x3; + tex1.k = (data[1] >> 4) & 0xff; +} + +void FASTCALL(GIFRegHandlerTEX2_1(u32* data)) +{ + tex2Write(0, data); +} + +void FASTCALL(GIFRegHandlerTEX2_2(u32* data)) +{ + tex2Write(1, data); +} + +void FASTCALL(GIFRegHandlerXYOFFSET_1(u32* data)) +{ + // eliminator low 4 bits for now + ZeroGS::vb[0].offset.x = (data[0]) & 0xffff; + ZeroGS::vb[0].offset.y = (data[1]) & 0xffff; + +// if( !conf.interlace ) { +// ZeroGS::vb[0].offset.x &= ~15; +// ZeroGS::vb[0].offset.y &= ~15; +// } +} + +void FASTCALL(GIFRegHandlerXYOFFSET_2(u32* data)) +{ + ZeroGS::vb[1].offset.x = (data[0]) & 0xffff; + ZeroGS::vb[1].offset.y = (data[1]) & 0xffff; + +// if( !conf.interlace ) { +// ZeroGS::vb[1].offset.x &= ~15; +// ZeroGS::vb[1].offset.y &= ~15; +// } +} + +void FASTCALL(GIFRegHandlerPRMODECONT(u32* data)) +{ + gs.prac = data[0] & 0x1; + prim = &gs._prim[gs.prac]; + + ZeroGS::Prim(); +} + +void FASTCALL(GIFRegHandlerPRMODE(u32* data)) +{ + gs._prim[0]._val = (data[0]>>3)&0xff; + + if (gs.prac == 0) + ZeroGS::Prim(); +} + +void FASTCALL(GIFRegHandlerTEXCLUT(u32* data)) +{ + if( ZeroGS::vb[0].bNeedTexCheck ) + ZeroGS::vb[0].FlushTexData(); + if( ZeroGS::vb[1].bNeedTexCheck ) + ZeroGS::vb[1].FlushTexData(); + gs.clut.cbw = ((data[0] ) & 0x3f) * 64; + gs.clut.cou = ((data[0] >> 6) & 0x3f) * 16; + gs.clut.cov = (data[0] >> 12) & 0x3ff; +} + +void FASTCALL(GIFRegHandlerSCANMSK(u32* data)) +{ +// ZeroGS::Flush(0); +// ZeroGS::Flush(1); +// ZeroGS::ResolveC(&ZeroGS::vb[0]); +// ZeroGS::ResolveZ(&ZeroGS::vb[0]); + + gs.smask = data[0] & 0x3; +} + +void FASTCALL(GIFRegHandlerMIPTBP1_1(u32* data)) +{ + miptbpInfo& miptbp0 = ZeroGS::vb[0].miptbp0; + miptbp0.tbp[0] = (data[0] ) & 0x3fff; + miptbp0.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp0.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp0.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp0.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void FASTCALL(GIFRegHandlerMIPTBP1_2(u32* data)) +{ + miptbpInfo& miptbp0 = ZeroGS::vb[1].miptbp0; + miptbp0.tbp[0] = (data[0] ) & 0x3fff; + miptbp0.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp0.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp0.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp0.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void FASTCALL(GIFRegHandlerMIPTBP2_1(u32* data)) +{ + miptbpInfo& miptbp1 = ZeroGS::vb[0].miptbp1; + miptbp1.tbp[0] = (data[0] ) & 0x3fff; + miptbp1.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp1.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp1.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp1.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void FASTCALL(GIFRegHandlerMIPTBP2_2(u32* data)) +{ + miptbpInfo& miptbp1 = ZeroGS::vb[1].miptbp1; + miptbp1.tbp[0] = (data[0] ) & 0x3fff; + miptbp1.tbw[0] = (data[0] >> 14) & 0x3f; + miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12); + miptbp1.tbw[1] = (data[1] >> 2) & 0x3f; + miptbp1.tbp[2] = (data[1] >> 8) & 0x3fff; + miptbp1.tbw[2] = (data[1] >> 22) & 0x3f; +} + +void FASTCALL(GIFRegHandlerTEXA(u32* data)) +{ + texaInfo newinfo; + newinfo.aem = (data[0] >> 15) & 0x1; + newinfo.ta[0] = data[0] & 0xff; + newinfo.ta[1] = data[1] & 0xff; + + if( *(u32*)&newinfo != *(u32*)&gs.texa ) { + ZeroGS::Flush(0); + ZeroGS::Flush(1); + *(u32*)&gs.texa = *(u32*)&newinfo; + gs.texa.fta[0] = newinfo.ta[0]/255.0f; + gs.texa.fta[1] = newinfo.ta[1]/255.0f; + + ZeroGS::vb[0].bTexConstsSync = FALSE; + ZeroGS::vb[1].bTexConstsSync = FALSE; + } +} + +void FASTCALL(GIFRegHandlerFOGCOL(u32* data)) +{ + ZeroGS::SetFogColor(data[0]&0xffffff); +} + +void FASTCALL(GIFRegHandlerTEXFLUSH(u32* data)) +{ + ZeroGS::SetTexFlush(); +} + +void FASTCALL(GIFRegHandlerSCISSOR_1(u32* data)) +{ + Rect2& scissor = ZeroGS::vb[0].scissor; + + Rect2 newscissor; + + newscissor.x0 = ((data[0] ) & 0x7ff) << 3; + newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3; + newscissor.y0 = ((data[1] ) & 0x7ff) << 3; + newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3; + + if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) { + + ZeroGS::Flush(0); + scissor = newscissor; + + ZeroGS::vb[0].bNeedFrameCheck = 1; + } +} + +void FASTCALL(GIFRegHandlerSCISSOR_2(u32* data)) +{ + Rect2& scissor = ZeroGS::vb[1].scissor; + + Rect2 newscissor; + + newscissor.x0 = ((data[0] ) & 0x7ff) << 3; + newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3; + newscissor.y0 = ((data[1] ) & 0x7ff) << 3; + newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3; + + if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || + newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) { + + ZeroGS::Flush(1); + scissor = newscissor; + + // flush everything + ZeroGS::vb[1].bNeedFrameCheck = 1; + } +} + +void FASTCALL(GIFRegHandlerALPHA_1(u32* data)) +{ + alphaInfo newalpha; + newalpha.abcd = *(u8*)data; + newalpha.fix = *(u8*)(data+1); + + if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[0].alpha ) { + ZeroGS::Flush(0); + + *(u16*)&ZeroGS::vb[0].alpha = *(u16*)&newalpha; + } +} + +void FASTCALL(GIFRegHandlerALPHA_2(u32* data)) +{ + alphaInfo newalpha; + newalpha.abcd = *(u8*)data; + newalpha.fix = *(u8*)(data+1); + + if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[1].alpha ) { + ZeroGS::Flush(1); + + *(u16*)&ZeroGS::vb[1].alpha = *(u16*)&newalpha; + } +} + +void FASTCALL(GIFRegHandlerDIMX(u32* data)) +{ +} + +void FASTCALL(GIFRegHandlerDTHE(u32* data)) +{ + gs.dthe = data[0] & 0x1; +} + +void FASTCALL(GIFRegHandlerCOLCLAMP(u32* data)) +{ + gs.colclamp = data[0] & 0x1; +} + +void FASTCALL(GIFRegHandlerTEST_1(u32* data)) +{ + testWrite(0, data); +} + +void FASTCALL(GIFRegHandlerTEST_2(u32* data)) +{ + testWrite(1, data); +} + +void FASTCALL(GIFRegHandlerPABE(u32* data)) +{ + //ZeroGS::SetAlphaChanged(0, GPUREG_PABE); + //ZeroGS::SetAlphaChanged(1, GPUREG_PABE); + int pabe = *data & 0x1; + if( gs.pabe != pabe ) { + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + gs.pabe = pabe; + } +} + +void FASTCALL(GIFRegHandlerFBA_1(u32* data)) +{ + int fba = *data & 0x1; + if( ZeroGS::vb[0].fba.fba != fba ) { + ZeroGS::Flush(0); + ZeroGS::Flush(1); + ZeroGS::vb[0].fba.fba = fba; + } +} + +void FASTCALL(GIFRegHandlerFBA_2(u32* data)) +{ + int fba = *data & 0x1; + if( ZeroGS::vb[0].fba.fba != fba ) { + ZeroGS::Flush(0); + ZeroGS::Flush(1); + ZeroGS::vb[1].fba.fba = fba; + } +} + +void FASTCALL(GIFRegHandlerFRAME_1(u32* data)) +{ + frameWrite(0, data); +} + +void FASTCALL(GIFRegHandlerFRAME_2(u32* data)) +{ + frameWrite(1, data); +} + +void FASTCALL(GIFRegHandlerZBUF_1(u32* data)) +{ + zbufInfo& zbuf = ZeroGS::vb[0].zbuf; + + if( zbuf.zbp == (data[0] & 0x1ff) * 32 && + zbuf.psm == (0x30|((data[0] >> 24) & 0xf)) && + zbuf.zmsk == (data[1] & 0x1) ) { + return; + } + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + zbuf.zbp = (data[0] & 0x1ff) * 32; + zbuf.psm = 0x30|((data[0] >> 24) & 0xf); + zbuf.zmsk = data[1] & 0x1; + + ZeroGS::vb[0].zprimmask = 0xffffffff; + if( zbuf.psm > 0x31 ) ZeroGS::vb[0].zprimmask = 0xffff; + + ZeroGS::vb[0].bNeedZCheck = 1; +} + +void FASTCALL(GIFRegHandlerZBUF_2(u32* data)) +{ + zbufInfo& zbuf = ZeroGS::vb[1].zbuf; + + if( zbuf.zbp == (data[0] & 0x1ff) * 32 && + zbuf.psm == (0x30|((data[0] >> 24) & 0xf)) && + zbuf.zmsk == (data[1] & 0x1) ) { + return; + } + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + zbuf.zbp = (data[0] & 0x1ff) * 32; + zbuf.psm = 0x30|((data[0] >> 24) & 0xf); + zbuf.zmsk = data[1] & 0x1; + + ZeroGS::vb[1].bNeedZCheck = 1; + + ZeroGS::vb[1].zprimmask = 0xffffffff; + if( zbuf.psm > 0x31 ) ZeroGS::vb[1].zprimmask = 0xffff; +} + +void FASTCALL(GIFRegHandlerBITBLTBUF(u32* data)) +{ + gs.srcbufnew.bp = ((data[0] ) & 0x3fff);// * 64; + gs.srcbufnew.bw = ((data[0] >> 16) & 0x3f) * 64; + gs.srcbufnew.psm = (data[0] >> 24) & 0x3f; + gs.dstbufnew.bp = ((data[1] ) & 0x3fff);// * 64; + gs.dstbufnew.bw = ((data[1] >> 16) & 0x3f) * 64; + gs.dstbufnew.psm = (data[1] >> 24) & 0x3f; + + if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64; +} + +void FASTCALL(GIFRegHandlerTRXPOS(u32* data)) +{ + gs.trxposnew.sx = (data[0] ) & 0x7ff; + gs.trxposnew.sy = (data[0] >> 16) & 0x7ff; + gs.trxposnew.dx = (data[1] ) & 0x7ff; + gs.trxposnew.dy = (data[1] >> 16) & 0x7ff; + gs.trxposnew.dir = (data[1] >> 27) & 0x3; +} + +void FASTCALL(GIFRegHandlerTRXREG(u32* data)) +{ + gs.imageWtemp = data[0]&0xfff; + gs.imageHtemp = data[1]&0xfff; +} + +void FASTCALL(GIFRegHandlerTRXDIR(u32* data)) +{ + // terminate any previous transfers + switch( gs.imageTransfer ) { + case 0: // host->loc + gs.imageTransfer = -1; + break; + case 1: // loc->host + ZeroGS::TerminateLocalHost(); + break; + } + + gs.srcbuf = gs.srcbufnew; + gs.dstbuf = gs.dstbufnew; + gs.trxpos = gs.trxposnew; + gs.imageTransfer = data[0] & 0x3; + gs.imageWnew = gs.imageWtemp; + gs.imageHnew = gs.imageHtemp; + + if( gs.imageWnew > 0 && gs.imageHnew > 0 ) { + switch(gs.imageTransfer) { + case 0: // host->loc + ZeroGS::InitTransferHostLocal(); + break; + + case 1: // loc->host + + ZeroGS::InitTransferLocalHost(); + break; + case 2: + + ZeroGS::TransferLocalLocal(); + break; + + case 3: + gs.imageTransfer = -1; + break; + + default: assert(0); + } + } + else { +#ifndef RELEASE_TO_PUBLIC + WARN_LOG("ZeroGS: dummy transfer\n"); +#endif + gs.imageTransfer = -1; + } +} + +static u32 oldhw[4]; +void FASTCALL(GIFRegHandlerHWREG(u32* data)) +{ + if( gs.imageTransfer == 0 ) { + ZeroGS::TransferHostLocal(data, 2); + } + else { +#ifndef RELEASE_TO_PUBLIC + ERROR_LOG("ZeroGS: HWREG!? %8.8x_%8.8x\n", data[0], data[1]); + //assert(0); +#endif + } +} + +extern int g_GSMultiThreaded; + +void FASTCALL(GIFRegHandlerSIGNAL(u32* data)) +{ + if(!g_GSMultiThreaded) { + SIGLBLID->SIGID = (SIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + +// if (gs.CSRw & 0x1) CSR->SIGNAL = 1; +// if (!IMR->SIGMSK && GSirq) +// GSirq(); + + if (gs.CSRw & 0x1) { + CSR->SIGNAL = 1; + //gs.CSRw &= ~1; + } + if (!IMR->SIGMSK && GSirq) + GSirq(); + } +} + +void FASTCALL(GIFRegHandlerFINISH(u32* data)) +{ + if(!g_GSMultiThreaded) { + + if (gs.CSRw & 0x2) + CSR->FINISH = 1; + if (!IMR->FINISHMSK && GSirq) + GSirq(); + +// if( gs.CSRw & 2 ) { +// //gs.CSRw &= ~2; +// //CSR->FINISH = 0; +// +// +// } +// CSR->FINISH = 1; +// +// if( !IMR->FINISHMSK && GSirq ) +// GSirq(); + } +} + +void FASTCALL(GIFRegHandlerLABEL(u32* data)) +{ + if(!g_GSMultiThreaded) { + SIGLBLID->LBLID = (SIGLBLID->LBLID&~data[1])|(data[0]&data[1]); + } +} diff --git a/plugins/gs/zerogs/opengl/Regs.h b/plugins/gs/zerogs/opengl/Regs.h new file mode 100644 index 0000000..fc5f250 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Regs.h @@ -0,0 +1,101 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GSREGS_H__ +#define __GSREGS_H__ + +#ifdef _MSC_VER +typedef void (__fastcall *GIFRegHandler)(u32* data); +#else + +#ifdef __x86_64__ +typedef void (*GIFRegHandler)(u32* data); +#else +typedef void (__attribute__((fastcall)) *GIFRegHandler)(u32* data); +#endif + +#endif + +void FASTCALL(GIFPackedRegHandlerNull(u32* data)); +void FASTCALL(GIFPackedRegHandlerRGBA(u32* data)); +void FASTCALL(GIFPackedRegHandlerSTQ(u32* data)); +void FASTCALL(GIFPackedRegHandlerUV(u32* data)); +void FASTCALL(GIFPackedRegHandlerXYZF2(u32* data)); +void FASTCALL(GIFPackedRegHandlerXYZ2(u32* data)); +void FASTCALL(GIFPackedRegHandlerFOG(u32* data)); +void FASTCALL(GIFPackedRegHandlerA_D(u32* data)); +void FASTCALL(GIFPackedRegHandlerNOP(u32* data)); + +void FASTCALL(GIFRegHandlerNull(u32* data)); +void FASTCALL(GIFRegHandlerPRIM(u32* data)); +void FASTCALL(GIFRegHandlerRGBAQ(u32* data)); +void FASTCALL(GIFRegHandlerST(u32* data)); +void FASTCALL(GIFRegHandlerUV(u32* data)); +void FASTCALL(GIFRegHandlerXYZF2(u32* data)); +void FASTCALL(GIFRegHandlerXYZ2(u32* data)); +void FASTCALL(GIFRegHandlerTEX0_1(u32* data)); +void FASTCALL(GIFRegHandlerTEX0_2(u32* data)); +void FASTCALL(GIFRegHandlerCLAMP_1(u32* data)); +void FASTCALL(GIFRegHandlerCLAMP_2(u32* data)); +void FASTCALL(GIFRegHandlerFOG(u32* data)); +void FASTCALL(GIFRegHandlerXYZF3(u32* data)); +void FASTCALL(GIFRegHandlerXYZ3(u32* data)); +void FASTCALL(GIFRegHandlerNOP(u32* data)); +void FASTCALL(GIFRegHandlerTEX1_1(u32* data)); +void FASTCALL(GIFRegHandlerTEX1_2(u32* data)); +void FASTCALL(GIFRegHandlerTEX2_1(u32* data)); +void FASTCALL(GIFRegHandlerTEX2_2(u32* data)); +void FASTCALL(GIFRegHandlerXYOFFSET_1(u32* data)); +void FASTCALL(GIFRegHandlerXYOFFSET_2(u32* data)); +void FASTCALL(GIFRegHandlerPRMODECONT(u32* data)); +void FASTCALL(GIFRegHandlerPRMODE(u32* data)); +void FASTCALL(GIFRegHandlerTEXCLUT(u32* data)); +void FASTCALL(GIFRegHandlerSCANMSK(u32* data)); +void FASTCALL(GIFRegHandlerMIPTBP1_1(u32* data)); +void FASTCALL(GIFRegHandlerMIPTBP1_2(u32* data)); +void FASTCALL(GIFRegHandlerMIPTBP2_1(u32* data)); +void FASTCALL(GIFRegHandlerMIPTBP2_2(u32* data)); +void FASTCALL(GIFRegHandlerTEXA(u32* data)); +void FASTCALL(GIFRegHandlerFOGCOL(u32* data)); +void FASTCALL(GIFRegHandlerTEXFLUSH(u32* data)); +void FASTCALL(GIFRegHandlerSCISSOR_1(u32* data)); +void FASTCALL(GIFRegHandlerSCISSOR_2(u32* data)); +void FASTCALL(GIFRegHandlerALPHA_1(u32* data)); +void FASTCALL(GIFRegHandlerALPHA_2(u32* data)); +void FASTCALL(GIFRegHandlerDIMX(u32* data)); +void FASTCALL(GIFRegHandlerDTHE(u32* data)); +void FASTCALL(GIFRegHandlerCOLCLAMP(u32* data)); +void FASTCALL(GIFRegHandlerTEST_1(u32* data)); +void FASTCALL(GIFRegHandlerTEST_2(u32* data)); +void FASTCALL(GIFRegHandlerPABE(u32* data)); +void FASTCALL(GIFRegHandlerFBA_1(u32* data)); +void FASTCALL(GIFRegHandlerFBA_2(u32* data)); +void FASTCALL(GIFRegHandlerFRAME_1(u32* data)); +void FASTCALL(GIFRegHandlerFRAME_2(u32* data)); +void FASTCALL(GIFRegHandlerZBUF_1(u32* data)); +void FASTCALL(GIFRegHandlerZBUF_2(u32* data)); +void FASTCALL(GIFRegHandlerBITBLTBUF(u32* data)); +void FASTCALL(GIFRegHandlerTRXPOS(u32* data)); +void FASTCALL(GIFRegHandlerTRXREG(u32* data)); +void FASTCALL(GIFRegHandlerTRXDIR(u32* data)); +void FASTCALL(GIFRegHandlerHWREG(u32* data)); +void FASTCALL(GIFRegHandlerSIGNAL(u32* data)); +void FASTCALL(GIFRegHandlerFINISH(u32* data)); +void FASTCALL(GIFRegHandlerLABEL(u32* data)); + +#endif diff --git a/plugins/gs/zerogs/opengl/Win32/Conf.cpp b/plugins/gs/zerogs/opengl/Win32/Conf.cpp new file mode 100644 index 0000000..1e84f6e --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/Conf.cpp @@ -0,0 +1,100 @@ +#include + +#include "GS.h" +#include "Win32.h" + +extern HINSTANCE hInst; + + +void SaveConfig() { + + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\zerogs.ini"); + + sprintf(szValue,"%u",conf.interlace); + WritePrivateProfileString("Settings", "Interlace",szValue,szIniFile); + sprintf(szValue,"%u",conf.aa); + WritePrivateProfileString("Settings", "Antialiasing",szValue,szIniFile); + sprintf(szValue,"%u",conf.bilinear); + WritePrivateProfileString("Settings", "Bilinear",szValue,szIniFile); + sprintf(szValue,"%u",conf.options); + WritePrivateProfileString("Settings", "Options",szValue,szIniFile); + sprintf(szValue,"%u",conf.gamesettings); + WritePrivateProfileString("Settings", "AdvancedOptions",szValue,szIniFile); +} + +void LoadConfig() { + + FILE *fp; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + memset(&conf, 0, sizeof(conf)); + conf.interlace = 0; // on, mode 1 + conf.mrtdepth = 1; + conf.options = 0; + conf.bilinear = 1; + conf.width = 640; + conf.height = 480; + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\zerogs.ini"); + fp=fopen("inis\\zerogs.ini","rt"); + if (!fp) + { + CreateDirectory("inis",NULL); + SaveConfig();//save and return + return ; + } + fclose(fp); + + GetPrivateProfileString("Settings", "Interlace", NULL, szValue, 20, szIniFile); + conf.interlace = (u8)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Antialiasing", NULL, szValue, 20, szIniFile); + conf.aa = (u8)strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Options", NULL, szValue, 20, szIniFile); + conf.options = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "AdvancedOptions", NULL, szValue, 20, szIniFile); + conf.gamesettings = strtoul(szValue, NULL, 10); + GetPrivateProfileString("Settings", "Bilinear", NULL, szValue, 20, szIniFile); + conf.bilinear = strtoul(szValue, NULL, 10); + + if( conf.aa < 0 || conf.aa > 2 ) conf.aa = 0; + + switch(conf.options&GSOPTION_WINDIMS) { + case GSOPTION_WIN640: + conf.width = 640; + conf.height = 480; + break; + case GSOPTION_WIN800: + conf.width = 800; + conf.height = 600; + break; + case GSOPTION_WIN1024: + conf.width = 1024; + conf.height = 768; + break; + case GSOPTION_WIN1280: + conf.width = 1280; + conf.height = 960; + break; + } + + // turn off all hacks by defaultof + conf.options &= ~(GSOPTION_FULLSCREEN|GSOPTION_WIREFRAME|GSOPTION_CAPTUREAVI); + conf.options |= GSOPTION_LOADED; + + if( conf.width <= 0 || conf.height <= 0 ) { + conf.width = 640; + conf.height = 480; + } +} diff --git a/plugins/gs/zerogs/opengl/Win32/Win32.cpp b/plugins/gs/zerogs/opengl/Win32/Win32.cpp new file mode 100644 index 0000000..f02f111 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/Win32.cpp @@ -0,0 +1,233 @@ +#include +#include +#include + +#include "resrc1.h" + +#include "GS.h" +#include "Win32.h" + +#include +using namespace std; + +extern int g_nPixelShaderVer; +static int prevbilinearfilter; +HINSTANCE hInst=NULL; + +void CALLBACK GSkeyEvent(keyEvent *ev) { +// switch (ev->event) { +// case KEYPRESS: +// switch (ev->key) { +// case VK_PRIOR: +// if (conf.fps) fpspos++; break; +// case VK_NEXT: +// if (conf.fps) fpspos--; break; +// case VK_END: +// if (conf.fps) fpspress = 1; break; +// case VK_DELETE: +// conf.fps = 1 - conf.fps; +// break; +// } +// break; +// } +} + +#include "Win32/resource.h" + +BOOL CALLBACK LoggingDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + if (conf.log) CheckDlgButton(hW, IDC_LOG, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, FALSE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOG)) + conf.log = 1; + else conf.log = 0; + + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +map mapConfOpts; +#define PUT_CONF(id) mapConfOpts[IDC_CONFOPT_##id] = 0x##id; + +void OnInitDialog(HWND hW) +{ + if( !(conf.options & GSOPTION_LOADED) ) + LoadConfig(); + + CheckDlgButton(hW, IDC_CONFIG_INTERLACE, conf.interlace); + CheckDlgButton(hW, IDC_CONFIG_BILINEAR, conf.bilinear); + CheckDlgButton(hW, IDC_CONFIG_DEPTHWRITE, conf.mrtdepth); + CheckRadioButton(hW,IDC_CONFIG_AANONE,IDC_CONFIG_AA4, IDC_CONFIG_AANONE+conf.aa); + CheckDlgButton(hW, IDC_CONFIG_WIREFRAME, (conf.options&GSOPTION_WIREFRAME)?1:0); + CheckDlgButton(hW, IDC_CONFIG_CAPTUREAVI, (conf.options&GSOPTION_CAPTUREAVI)?1:0); + //CheckDlgButton(hW, IDC_CONFIG_CACHEFBP, (conf.options&GSOPTION_ALPHACLAMP)?1:0); + CheckDlgButton(hW, IDC_CONFIG_FULLSCREEN, (conf.options&GSOPTION_FULLSCREEN)?1:0); + //CheckDlgButton(hW, IDC_CONFIG_FFX, (conf.options&GSOPTION_FFXHACK)?1:0); + CheckDlgButton(hW, IDC_CONFIG_BMPSS, (conf.options&GSOPTION_TGASNAP)?1:0); + CheckRadioButton(hW,IDC_CONF_WIN640, IDC_CONF_WIN1280, IDC_CONF_WIN640+((conf.options&GSOPTION_WINDIMS)>>4)); + + prevbilinearfilter = conf.bilinear; + + mapConfOpts.clear(); + PUT_CONF(00000001); + PUT_CONF(00000002); + PUT_CONF(00000004); + PUT_CONF(00000008); + PUT_CONF(00000010); + PUT_CONF(00000020); + PUT_CONF(00000040); + PUT_CONF(00000080); + PUT_CONF(00000200); + PUT_CONF(00000400); + PUT_CONF(00000800); + PUT_CONF(00001000); + PUT_CONF(00002000); + PUT_CONF(00004000); + PUT_CONF(00008000); + PUT_CONF(00010000); + PUT_CONF(00020000); + PUT_CONF(00040000); + PUT_CONF(00080000); + PUT_CONF(00100000); + PUT_CONF(00200000); + + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + CheckDlgButton(hW, it->first, (conf.gamesettings&it->second)?1:0); + } +} + +void OnOK(HWND hW) { + + u32 newinterlace = IsDlgButtonChecked(hW, IDC_CONFIG_INTERLACE); + + if( !conf.interlace ) conf.interlace = newinterlace; + else if( !newinterlace ) conf.interlace = 2; // off + + conf.bilinear = IsDlgButtonChecked(hW, IDC_CONFIG_BILINEAR); + // restore + if( conf.bilinear && prevbilinearfilter ) + conf.bilinear = prevbilinearfilter; + + //conf.mrtdepth = 1;//IsDlgButtonChecked(hW, IDC_CONFIG_DEPTHWRITE); + + if( SendDlgItemMessage(hW,IDC_CONFIG_AANONE,BM_GETCHECK,0,0) ) { + conf.aa = 0; + } + else if( SendDlgItemMessage(hW,IDC_CONFIG_AA2,BM_GETCHECK,0,0) ) { + conf.aa = 1; + } + else conf.aa = 2; + + conf.options = 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_CAPTUREAVI) ? GSOPTION_CAPTUREAVI : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_WIREFRAME) ? GSOPTION_WIREFRAME : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_FULLSCREEN) ? GSOPTION_FULLSCREEN : 0; + //conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_FFX) ? GSOPTION_FFXHACK : 0; + conf.options |= IsDlgButtonChecked(hW, IDC_CONFIG_BMPSS) ? GSOPTION_TGASNAP : 0; + + conf.gamesettings = 0; + for(map::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it) { + if( IsDlgButtonChecked(hW, it->first) ) + conf.gamesettings |= it->second; + } + GSsetGameCRC(0, conf.gamesettings); + + if( SendDlgItemMessage(hW,IDC_CONF_WIN640,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN640; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN800,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN800; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN1024,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN1024; + else if( SendDlgItemMessage(hW,IDC_CONF_WIN1280,BM_GETCHECK,0,0) ) conf.options |= GSOPTION_WIN1280; + + SaveConfig(); + EndDialog(hW, FALSE); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + OnInitDialog(hW); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + OnOK(hW); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + + //ZeroGS uses floating point render targets because A8R8G8B8 format is not sufficient for ps2 blending and this requires alpha blending on floating point render targets + //There might be a problem with pixel shader precision with older geforce models (textures will look blocky). + + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +s32 CALLBACK GStest() { + return 0; +} + +void CALLBACK GSabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + +static char *err = "Error Loading Symbol"; +static int errval; + +void *SysLoadLibrary(char *lib) { + return LoadLibrary(lib); +} + +void *SysLoadSym(void *lib, char *sym) { + void *tmp = GetProcAddress((HINSTANCE)lib, sym); + if (tmp == NULL) errval = 1; + else errval = 0; + return tmp; +} + +char *SysLibError() { + if (errval) { errval = 0; return err; } + return NULL; +} + +void SysCloseLibrary(void *lib) { + FreeLibrary((HINSTANCE)lib); +} diff --git a/plugins/gs/zerogs/opengl/Win32/Win32.h b/plugins/gs/zerogs/opengl/Win32/Win32.h new file mode 100644 index 0000000..45322b3 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/Win32.h @@ -0,0 +1,9 @@ +#ifndef __WIN32_H__ +#define __WIN32_H__ + +#include "resrc1.h" +#include "Win32/resource.h" + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); + +#endif /* __WIN32_H__ */ diff --git a/plugins/gs/zerogs/opengl/Win32/aviUtil.h b/plugins/gs/zerogs/opengl/Win32/aviUtil.h new file mode 100644 index 0000000..a6f7f46 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/aviUtil.h @@ -0,0 +1,484 @@ +#define AVIIF_KEYFRAME 0x00000010L // this frame is a key frame. + +#include +using namespace std; + +#include +#include +#include + +BOOL AVI_Init() +{ + /* first let's make sure we are running on 1.1 */ + WORD wVer = HIWORD(VideoForWindowsVersion()); + if (wVer < 0x010a){ + /* oops, we are too old, blow out of here */ + //MessageBeep(MB_ICONHAND); + MessageBox(NULL, "Cant't init AVI File - Video for Windows version is to old", "Error", MB_OK|MB_ICONSTOP); + return FALSE; + } + + AVIFileInit(); + + return TRUE; +} + +BOOL AVI_FileOpenWrite(PAVIFILE * pfile, const char *filename) +{ + HRESULT hr = AVIFileOpen(pfile, // returned file pointer + filename, // file name + OF_WRITE | OF_CREATE, // mode to open file with + NULL); // use handler determined + // from file extension.... + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +DWORD getFOURCC(const char* value) +{ + if(_stricmp(value, "DIB") == 0) + { + return mmioFOURCC(value[0],value[1],value[2],' '); + } + else if((_stricmp(value, "CVID") == 0) + || (_stricmp(value, "IV32") == 0) + || (_stricmp(value, "MSVC") == 0) + || (_stricmp(value, "IV50") == 0)) + { + return mmioFOURCC(value[0],value[1],value[2],value[3]); + } + else + { + return NULL; + } +} + +// Fill in the header for the video stream.... +// The video stream will run in rate ths of a second.... +BOOL AVI_CreateStream(PAVIFILE pfile, PAVISTREAM * ps, int rate, // sample/second + unsigned long buffersize, int rectwidth, int rectheight, + const char* _compressor) +{ + AVISTREAMINFO strhdr; + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeVIDEO;// stream type + strhdr.fccHandler = getFOURCC(_compressor); + //strhdr.fccHandler = 0; // no compression! + //strhdr.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //strhdr.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //strhdr.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //strhdr.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //strhdr.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //strhdr.dwFlags = AVISTREAMINFO_DISABLED; + //strhdr.dwCaps = + //strhdr.wPriority = + //strhdr.wLanguage = + strhdr.dwScale = 1; + strhdr.dwRate = rate; // rate fps + //strhdr.dwStart = + //strhdr.dwLength = + //strhdr.dwInitialFrames = + strhdr.dwSuggestedBufferSize = buffersize; + strhdr.dwQuality = -1; // use the default + //strhdr.dwSampleSize = + SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream + (int) rectwidth, + (int) rectheight); + //strhdr.dwEditCount = + //strhdr.dwFormatChangeCount = + //strcpy(strhdr.szName, "Full Frames (Uncompressed)"); + + // And create the stream; + HRESULT hr = AVIFileCreateStream(pfile, // file pointer + ps, // returned stream pointer + &strhdr); // stream header + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +string getFOURCCVAsString(DWORD value) +{ + string returnValue = ""; + if( value == 0 ) + return returnValue; + + DWORD ch0 = value & 0x000000FF; + returnValue.push_back((char) ch0); + DWORD ch1 = (value & 0x0000FF00)>>8; + returnValue.push_back((char) ch1); + DWORD ch2 = (value & 0x00FF0000)>>16; + returnValue.push_back((char) ch2); + DWORD ch3 = (value & 0xFF000000)>>24; + returnValue.push_back((char) ch3); + + return returnValue; +} + +string dumpAVICOMPRESSOPTIONS(AVICOMPRESSOPTIONS opts) +{ + char tmp[255]; + string returnValue = "Dump of AVICOMPRESSOPTIONS\n"; + + returnValue += "DWORD fccType = streamtype("; returnValue += getFOURCCVAsString(opts.fccType); returnValue += ")\n"; + returnValue += "DWORD fccHandler = "; returnValue += getFOURCCVAsString(opts.fccHandler); returnValue += "\n"; + + _snprintf(tmp, 255, "DWORD dwKeyFrameEvery = %d\n", opts.dwKeyFrameEvery); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwQuality = %d\n", opts.dwQuality); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwBytesPerSecond = %d\n", opts.dwBytesPerSecond); + returnValue += tmp; + + if((opts.dwFlags & AVICOMPRESSF_DATARATE) == AVICOMPRESSF_DATARATE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_DATARATE\n");} + else if((opts.dwFlags & AVICOMPRESSF_INTERLEAVE) == AVICOMPRESSF_INTERLEAVE){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_INTERLEAVE\n");} + else if((opts.dwFlags & AVICOMPRESSF_KEYFRAMES) == AVICOMPRESSF_KEYFRAMES){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_KEYFRAMES\n");} + else if((opts.dwFlags & AVICOMPRESSF_VALID) == AVICOMPRESSF_VALID){strcpy(tmp, "DWORD fccType = AVICOMPRESSF_VALID\n");} + else {_snprintf(tmp, 255, "DWORD dwFlags = Unknown(%d)\n", opts.dwFlags);} + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpFormat = %d\n", (int)opts.lpFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbFormat = %d\n", opts.cbFormat); + returnValue += tmp; + + _snprintf(tmp, 255, "LPVOID lpParms = %d\n", (int)opts.lpParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD cbParms = %d\n", opts.cbParms); + returnValue += tmp; + + _snprintf(tmp, 255, "DWORD dwInterleaveEvery = %d\n", opts.dwInterleaveEvery); + returnValue += tmp; + + return returnValue; +} + +BOOL AVI_SetOptions(PAVISTREAM * ps, PAVISTREAM * psCompressed, LPBITMAPINFOHEADER lpbi, + const char* _compressor) +{ + + AVICOMPRESSOPTIONS opts; + AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts}; + + memset(&opts, 0, sizeof(opts)); + opts.fccType = streamtypeVIDEO; + opts.fccHandler = getFOURCC(_compressor); + //opts.fccHandler = 0; + //opts.fccHandler = mmioFOURCC('D','I','B',' '); // Uncompressed + //opts.fccHandler = mmioFOURCC('C','V','I','D'); // Cinpak + //opts.fccHandler = mmioFOURCC('I','V','3','2'); // Intel video 3.2 + //opts.fccHandler = mmioFOURCC('M','S','V','C'); // Microsoft video 1 + //opts.fccHandler = mmioFOURCC('I','V','5','0'); // Intel video 5.0 + //opts.dwKeyFrameEvery = 5; + //opts.dwQuality + //opts.dwBytesPerSecond + //opts.dwFlags = AVICOMPRESSF_KEYFRAMES; + //opts.lpFormat + //opts.cbFormat + //opts.lpParms + //opts.cbParms + //opts.dwInterleaveEvery + + /* display the compression options dialog box if specified compressor is unknown */ + if(getFOURCC(_compressor) == NULL) + { + if (!AVISaveOptions(NULL, 0, 1, ps, (LPAVICOMPRESSOPTIONS FAR *) &aopts)) + { + return FALSE; + } + + //printf("%s", dumpAVICOMPRESSOPTIONS(opts)); + //MessageBox(NULL, dumpAVICOMPRESSOPTIONS(opts).c_str(), "AVICOMPRESSOPTIONS", MB_OK); + } + + HRESULT hr = AVIMakeCompressedStream(psCompressed, *ps, &opts, NULL); + if (hr != AVIERR_OK) { + return FALSE; + } + + hr = AVIStreamSetFormat(*psCompressed, 0, + lpbi, // stream format + lpbi->biSize // format size + + lpbi->biClrUsed * sizeof(RGBQUAD) + ); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_SetText(PAVIFILE pfile, PAVISTREAM psText, char *szText, int width, int height, int TextHeight) +{ + // Fill in the stream header for the text stream.... + AVISTREAMINFO strhdr; + DWORD dwTextFormat; + // The text stream is in 60ths of a second.... + + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeTEXT; + strhdr.fccHandler = mmioFOURCC('D', 'R', 'A', 'W'); + strhdr.dwScale = 1; + strhdr.dwRate = 60; + strhdr.dwSuggestedBufferSize = sizeof(szText); + SetRect(&strhdr.rcFrame, 0, (int) height, + (int) width, (int) height + TextHeight); // #define TEXT_HEIGHT 20 + + // ....and create the stream. + HRESULT hr = AVIFileCreateStream(pfile, &psText, &strhdr); + if (hr != AVIERR_OK) { + return FALSE; + } + + dwTextFormat = sizeof(dwTextFormat); + hr = AVIStreamSetFormat(psText, 0, &dwTextFormat, sizeof(dwTextFormat)); + if (hr != AVIERR_OK) { + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddFrame(PAVISTREAM psCompressed, int time, LPBITMAPINFOHEADER lpbi) +{ + int ImageSize = lpbi->biSizeImage; + if (ImageSize == 0) + { + if (lpbi->biBitCount == 24) + { + ImageSize = lpbi->biWidth * lpbi->biHeight * 3; + } + } + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + time, // time of this frame + 1, // number to write + (LPBYTE) lpbi + // pointer to data + lpbi->biSize + + lpbi->biClrUsed * sizeof(RGBQUAD), + ImageSize, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + char strMsg[255]; + _snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, "", MB_OK); + return FALSE; + } + + return TRUE; +} + +BOOL AVI_AddText(PAVISTREAM psText, int time, char *szText) +{ + int iLen = (int)strlen(szText); + + HRESULT hr = AVIStreamWrite(psText, + time, + 1, + szText, + iLen + 1, + AVIIF_KEYFRAME, + NULL, + NULL); + if (hr != AVIERR_OK) + return FALSE; + + return TRUE; +} + +BOOL AVI_CloseStream(PAVISTREAM ps, PAVISTREAM psCompressed, PAVISTREAM psText) +{ + if (ps) + AVIStreamClose(ps); + + if (psCompressed) + AVIStreamClose(psCompressed); + + if (psText) + AVIStreamClose(psText); + + + + return TRUE; +} + +BOOL AVI_CloseFile(PAVIFILE pfile) +{ + if (pfile) + AVIFileClose(pfile); + + return TRUE; +} + +BOOL AVI_Exit() +{ + AVIFileExit(); + + return TRUE; +} + + + + + + + + + + + + + + + + +/* Here are the additional functions we need! */ + + +static PAVIFILE pfile = NULL; +static PAVISTREAM ps = NULL; +static PAVISTREAM psCompressed = NULL; +static int count = 0; + + +// Initialization... +bool START_AVI(const char* file_name) +{ + if(! AVI_Init()) + { + //printf("Error - AVI_Init()\n"); + return false; + } + + if(! AVI_FileOpenWrite(&pfile, file_name)) + { + //printf("Error - AVI_FileOpenWrite()\n"); + return false; + } + + return true; +} + +bool ADD_FRAME_FROM_DIB_TO_AVI(const char* _compressor, int _frameRate, int width, int height, int bits, void* pdata) +{ + if(count == 0) + { + if(! AVI_CreateStream(pfile, &ps, _frameRate, + width*height/bits, + width, + height, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + return false; + } + + BITMAPINFOHEADER bi; + memset(&bi, 0, sizeof(bi)); + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = width; + bi.biHeight = height; + bi.biPlanes = 1; + bi.biBitCount = bits; + bi.biCompression = BI_RGB; + bi.biSizeImage = width * height * bits /8; + if(! AVI_SetOptions(&ps, &psCompressed, &bi, _compressor)) + { + return false; + } + } + + HRESULT hr = AVIStreamWrite(psCompressed, // stream pointer + count, // time of this frame + 1, // number to write + pdata, + width*height/8, // lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, + NULL); + if (hr != AVIERR_OK) + { + char strMsg[255]; + _snprintf(strMsg, 255, "Error: AVIStreamWrite, error %d",hr); + MessageBox(NULL, strMsg, "", MB_OK); + return FALSE; + } + + count++; + return true; +} + +//Now we can add frames +// ie. ADD_FRAME_FROM_DIB_TO_AVI(yourDIB, "CVID", 25); +bool ADD_FRAME_FROM_DIB_TO_AVI(HANDLE dib, const char* _compressor, int _frameRate) +{ + LPBITMAPINFOHEADER lpbi; + if(count == 0) + { + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_CreateStream(pfile, &ps, _frameRate, + (unsigned long) lpbi->biSizeImage, + (int) lpbi->biWidth, + (int) lpbi->biHeight, _compressor)) + { + //printf("Error - AVI_CreateStream()\n"); + GlobalUnlock(lpbi); + return false; + } + + if(! AVI_SetOptions(&ps, &psCompressed, lpbi, _compressor)) + { + //printf("Error - AVI_SetOptions()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + } + + lpbi = (LPBITMAPINFOHEADER)GlobalLock(dib); + if(! AVI_AddFrame(psCompressed, count * 1, lpbi)) + { + //printf("Error - AVI_AddFrame()\n"); + GlobalUnlock(lpbi); + return false; + } + + GlobalUnlock(lpbi); + count++; + return true; +} + +// The end... +bool STOP_AVI() +{ + if(! AVI_CloseStream(ps, psCompressed, NULL)) + { + //printf("Error - AVI_CloseStream()\n"); + return false; + } + + if(! AVI_CloseFile(pfile)) + { + //printf("Error - AVI_CloseFile()\n"); + return false; + } + + if(! AVI_Exit()) + { + //printf("Error - AVI_Exit()\n"); + return false; + } + + return true; +} + diff --git a/plugins/gs/zerogs/opengl/Win32/copytopcsx2.bat b/plugins/gs/zerogs/opengl/Win32/copytopcsx2.bat new file mode 100644 index 0000000..9c20d00 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/copytopcsx2.bat @@ -0,0 +1,4 @@ +copy .\Debug\ZeroGSogl.pdb ..\..\..\..\..\bin\plugins +copy .\Debug\ZeroGSogld.dll ..\..\..\..\..\bin\plugins +copy .\Release\ZeroGSogl.dll ..\..\..\..\..\bin\plugins +copy ".\Release (to Public)\ZeroGSoglr.dll" ..\..\..\..\..\bin\plugins \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/Win32/jconfig.h b/plugins/gs/zerogs/opengl/Win32/jconfig.h new file mode 100644 index 0000000..1f43a6e --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/jconfig.h @@ -0,0 +1,52 @@ +/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +//#define NEED_FAR_POINTERS /* for small or medium memory model */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +//#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ + +#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ + +//#define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ + +#define NEED_FHEAPMIN /* far heap management routines are broken */ + +#define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ +/* Note: the above define is known to improve the code with Microsoft C 6.00A. + * I do not know whether it is good for later compiler versions. + * Please report any info on this point to jpeg-info@uunet.uu.net. + */ + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define USE_SETMODE /* Microsoft has setmode() */ +#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/plugins/gs/zerogs/opengl/Win32/jmorecfg.h b/plugins/gs/zerogs/opengl/Win32/jmorecfg.h new file mode 100644 index 0000000..c856e22 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/jmorecfg.h @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/plugins/gs/zerogs/opengl/Win32/jpeglib.h b/plugins/gs/zerogs/opengl/Win32/jpeglib.h new file mode 100644 index 0000000..a893130 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/jpeglib.h @@ -0,0 +1,1099 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +#undef FAR +#define FAR + +typedef JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/plugins/gs/zerogs/opengl/Win32/libjpeg.lib b/plugins/gs/zerogs/opengl/Win32/libjpeg.lib new file mode 100644 index 0000000000000000000000000000000000000000..ae22f9c400f4473bd6e6e5038c4da14713f501f8 GIT binary patch literal 470518 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�*8S-ao#yR+JgG6&&XhH(aQ@%?wIb{vCe6Vovc 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 z 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%0A)B%-q?>`HWKQwJa@+6w$uH2Pp+2IS%z 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

&xTZsk`g?cH#9X1%)&4gz4ZRZ43cie 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%0Dlh&j3%6ozKC)1>jj? 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 literal 0 HcmV?d00001 diff --git a/plugins/gs/zerogs/opengl/Win32/ps2hw.dat b/plugins/gs/zerogs/opengl/Win32/ps2hw.dat new file mode 100644 index 0000000000000000000000000000000000000000..ad70207b37a824b305c8fb7967c70dd84f037e8a GIT binary patch literal 106682 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 literal 0 HcmV?d00001 diff --git a/plugins/gs/zerogs/opengl/Win32/resource.h b/plugins/gs/zerogs/opengl/Win32/resource.h new file mode 100644 index 0000000..053ec92 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/resource.h @@ -0,0 +1,45 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by GSsoftdx.rc +// +#define IDD_CONFIG 101 +#define IDD_ABOUT 102 +#define IDD_LOGGING 106 +#define IDB_ZEROGSLOGO 108 +#define IDR_REALPS2_FX 109 +#define IDR_SHADERS 110 +#define IDC_CHECK1 1000 +#define IDC_FULLSCREEN 1000 +#define IDC_NAME 1000 +#define IDC_LOG 1000 +#define IDC_CHECK2 1001 +#define IDC_FPSCOUNT 1001 +#define IDC_CHECK5 1002 +#define IDC_FRAMESKIP 1002 +#define IDC_STRETCH 1003 +#define IDC_LOGGING 1004 +#define IDC_COMBO1 1005 +#define IDC_CACHE 1005 +#define IDC_CACHESIZE 1006 +#define IDC_CHECK3 1007 +#define IDC_RECORD 1007 +#define IDC_COMBO2 1008 +#define IDC_DSPRES 1008 +#define IDC_WRES 1008 +#define IDC_COMBO3 1009 +#define IDC_DDDRV 1009 +#define IDC_FRES 1009 +#define IDC_COMBO4 1012 +#define IDC_CODEC 1012 +#define IDC_FILTERS 1014 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1015 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/gs/zerogs/opengl/Win32/resrc1.h b/plugins/gs/zerogs/opengl/Win32/resrc1.h new file mode 100644 index 0000000..e2f4b1f --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/resrc1.h @@ -0,0 +1,73 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by zerogs.rc +// +#define IDC_CONF_DEFAULT 3 +#define IDR_DATA1 112 +#define IDC_ABOUTTEXT 1015 +#define IDC_CONFIG_AA 1016 +#define IDC_CONFIG_INTERLACE 1017 +#define IDC_CONFIG_AA3 1018 +#define IDC_CONFIG_CAPTUREAVI 1018 +#define IDC_CONFIG_CAPTUREAVI2 1019 +#define IDC_CONFIG_FULLSCREEN 1019 +#define IDC_CONFIG_FULLSCREEN2 1020 +#define IDC_CONFIG_FFX 1020 +#define IDC_CONFIG_INTERLACE2 1021 +#define IDC_CONFIG_DEPTHWRITE 1021 +#define IDC_CONFIG_FFX2 1021 +#define IDC_CONFIG_BMPSS 1021 +#define IDC_CONFIG_AANONE 1022 +#define IDC_CONFIG_AA2 1023 +#define IDC_RADIO3 1024 +#define IDC_CONFIG_AA4 1024 +#define IDC_CONFIG_INTERLACE3 1025 +#define IDC_CONFIG_BILINEAR 1025 +#define IDC_CONF_WIN640 1026 +#define IDC_CONF_WIN800 1027 +#define IDC_CONF_WIN1024 1028 +#define IDC_RADIO5 1029 +#define IDC_CONF_WIN1280 1029 +#define IDC_CONFIG_CAPTUREAVI3 1030 +#define IDC_CONFIG_WIREFRAME 1030 +#define IDC_CONFIG_CAPTUREAVI4 1031 +#define IDC_CONFIG_CACHEFBP 1031 +#define IDC_CONFIG_SHOWFPS 1031 +#define IDC_CONFOPT_00100000 1031 +#define IDC_CONFOPT_00080000 1032 +#define IDC_CONFOPT_00002000 1033 +#define IDC_CONFOPT_00001000 1035 +#define IDC_CONFOPT_00000200 1037 +#define IDC_CONFOPT_00000080 1038 +#define IDC_CONFOPT_201 1039 +#define IDC_CONFOPT_00000040 1039 +#define IDC_CONFOPT_00000020 1040 +#define IDC_CONFOPT_00000001 1042 +#define IDC_CONFOPT_00000004 1044 +#define IDC_CONFOPT_IDS 1045 +#define IDC_CONFOPT_00200000 1046 +#define IDC_CONFOPT_00004000 1047 +#define IDC_BUTTON1 1048 +#define IDC_CONFOPT_COMPUTEOR 1048 +#define IDC_CONFOPT_4001 1049 +#define IDC_CONFOPT_00000010 1049 +#define IDC_CONFOPT_00008000 1050 +#define IDC_CONFOPT_00010000 1052 +#define IDC_CONFOPT_00020000 1054 +#define IDC_CONFOPT_00000002 1055 +#define IDC_CONFOPT_00000008 1058 +#define IDC_CONFOPT_00000400 1060 +#define IDC_CONFOPT_00000800 1061 +#define IDC_CONFOPT_NOALPHABLEND30 1062 +#define IDC_CONFOPT_00040000 1063 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1049 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/gs/zerogs/opengl/Win32/zerogs.bmp b/plugins/gs/zerogs/opengl/Win32/zerogs.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f4e576108388743a96f9ee434d0a2d050bbebbb7 GIT binary patch literal 921656 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 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0Rk5l F_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005.vcproj b/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005.vcproj new file mode 100644 index 0000000..ba587ab --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005.vcproj @@ -0,0 +1,579 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005_x64.vcproj b/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005_x64.vcproj new file mode 100644 index 0000000..93e85f7 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zerogsogl_2005_x64.vcproj @@ -0,0 +1,874 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/adler32.c b/plugins/gs/zerogs/opengl/Win32/zlib/adler32.c new file mode 100644 index 0000000..bc0842f --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/adler32.c @@ -0,0 +1,74 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? (int)len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + MOD(s1); + MOD(s2); + } + return (s2 << 16) | s1; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/compress.c b/plugins/gs/zerogs/opengl/Win32/zlib/compress.c new file mode 100644 index 0000000..e7ea2c5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/compress.c @@ -0,0 +1,79 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/crc32.c b/plugins/gs/zerogs/opengl/Win32/zlib/crc32.c new file mode 100644 index 0000000..aa8b984 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/crc32.c @@ -0,0 +1,311 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results about a factor + * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id: crc32.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ + +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, and + then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/crc32.h b/plugins/gs/zerogs/opengl/Win32/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/deflate.c b/plugins/gs/zerogs/opengl/Win32/zlib/deflate.c new file mode 100644 index 0000000..efe7b63 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/deflate.c @@ -0,0 +1,1502 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.1 Copyright 1995-2003 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifndef FASTEST +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif +#endif +local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds + * for every combination of windowBits and memLevel, as well as wrap. + * But even the conservative upper bound of about 14% expansion does not + * seem onerous for output buffer allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong destLen; + + /* conservative upper bound */ + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + + /* if can't get parameters, return conservative bound */ + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; + + /* if not default parameters, return conservative bound */ + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; + + /* default settings: return tight bound for that case */ + return compressBound(sourceLen); +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, 255); + s->status = BUSY_STATE; + strm->adler = crc32(0L, Z_NULL, 0); + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ +#endif /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 or strategy == Z_RLE only + */ +local uInt longest_match_fast(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ +#ifdef FASTEST + if ((s->strategy < Z_HUFFMAN_ONLY) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } +#else + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } +#endif + /* longest_match() or longest_match_fast() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy < Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } + /* longest_match() or longest_match_fast() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/deflate.h b/plugins/gs/zerogs/opengl/Win32/zlib/deflate.h new file mode 100644 index 0000000..26775e9 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/deflate.h @@ -0,0 +1,326 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/gzio.c b/plugins/gs/zerogs/opengl/Win32/zlib/gzio.c new file mode 100644 index 0000000..4cfd64f --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/gzio.c @@ -0,0 +1,1005 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2006/01/12 17:26:07 shadowpcsx2 Exp $ */ + +#include + +#include "zutil.h" + +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * start anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } + } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_GZCOMPRESS +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + buf[sizeof(buf) - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(buf, format, va); + va_end(va); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->out += s->stream.avail_out; + s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_GZCOMPRESS */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->in = s->out = offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if (offset >= s->out) { + offset -= s->out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return s->out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, (uLong)(s->in & 0xffffffff)); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char * ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/infback.c b/plugins/gs/zerogs/opengl/Win32/zlib/infback.c new file mode 100644 index 0000000..5cf5d22 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/infback.c @@ -0,0 +1,619 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_stream FAR *strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inffast.c b/plugins/gs/zerogs/opengl/Win32/zlib/inffast.c new file mode 100644 index 0000000..63aa440 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inffast.c @@ -0,0 +1,305 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - 68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inffast.h b/plugins/gs/zerogs/opengl/Win32/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inffixed.h b/plugins/gs/zerogs/opengl/Win32/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inflate.c b/plugins/gs/zerogs/opengl/Win32/zlib/inflate.c new file mode 100644 index 0000000..71fe3cc --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inflate.c @@ -0,0 +1,1270 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->wsize = 0; + state->whave = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + if (BITS(4) + 8 > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + } while (len && copy < have); + if (state->flags & 0x02000) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->mode != DICT) return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) return Z_DATA_ERROR; + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + *dest = *source; + *copy = *state; + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) + zmemcpy(window, state->window, 1U << state->wbits); + copy->window = window; + dest->state = (voidpf)copy; + return Z_OK; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inflate.h b/plugins/gs/zerogs/opengl/Win32/zlib/inflate.h new file mode 100644 index 0000000..b696512 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inflate.h @@ -0,0 +1,117 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ +#ifdef GUNZIP + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ +#endif + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ +#ifdef GUNZIP + LENGTH, /* i: waiting for 32-bit length (gzip) */ +#endif + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.c b/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.c new file mode 100644 index 0000000..55fd27b --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.c @@ -0,0 +1,321 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.1 Copyright 1995-2003 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 76, 66}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || (codes - count[0] != 1))) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.h b/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.h new file mode 100644 index 0000000..1dbfe53 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 code structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 1440 +#define MAXD 154 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/trees.c b/plugins/gs/zerogs/opengl/Win32/zlib/trees.c new file mode 100644 index 0000000..d0bce9f --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/trees.c @@ -0,0 +1,1215 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2003 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/trees.h b/plugins/gs/zerogs/opengl/Win32/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/uncompr.c b/plugins/gs/zerogs/opengl/Win32/zlib/uncompr.c new file mode 100644 index 0000000..82ebef7 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/zconf.h b/plugins/gs/zerogs/opengl/Win32/zlib/zconf.h new file mode 100644 index 0000000..b073c9e --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/zconf.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflatePrime z_deflatePrime +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +#define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/zlib.h b/plugins/gs/zerogs/opengl/Win32/zlib/zlib.h new file mode 100644 index 0000000..d54ac94 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/zlib.h @@ -0,0 +1,1200 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.1, November 17th, 2003 + + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.1" +#define ZLIB_VERNUM 0x1210 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by the in-memory functions is the zlib + format, which is a zlib wrapper documented in RFC 1950, wrapped around a + deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + This library does not provide any functions to write gzip files in memory. + However such functions could be easily written using zlib's deflate function, + the documentation in the gzip RFC, and the examples in gzio.c. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it get to the next deflate block boundary. When decoding the zlib + or gzip format, this will cause inflate() to return immediately after the + header and before the first block. When doing a raw inflate, inflate() will + go ahead and process the first block, and will return when it gets to the end + of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/zutil.c b/plugins/gs/zerogs/opengl/Win32/zlib/zutil.c new file mode 100644 index 0000000..db137f8 --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/zutil.c @@ -0,0 +1,319 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1 << 16; +#endif +#ifdef NO_GZIP + flags += 1 << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1 << 20; +#endif +#ifdef FASTEST + flags += 1 << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1 << 25; +# ifdef HAS_vsprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1 << 26; +# endif +# endif +#else + flags += 1 << 24; +# ifdef NO_snprintf + flags += 1 << 25; +# ifdef HAS_sprintf_void + flags += 1 << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1 << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* does not exist on WCE */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/plugins/gs/zerogs/opengl/Win32/zlib/zutil.h b/plugins/gs/zerogs/opengl/Win32/zlib/zutil.h new file mode 100644 index 0000000..e300f7c --- /dev/null +++ b/plugins/gs/zerogs/opengl/Win32/zlib/zutil.h @@ -0,0 +1,258 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2006/01/12 17:26:08 shadowpcsx2 Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/Makefile.am b/plugins/gs/zerogs/opengl/ZeroGSShaders/Makefile.am new file mode 100644 index 0000000..6d409c5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/Makefile.am @@ -0,0 +1,2 @@ +noinst_PROGRAMS = zgsbuild +zgsbuild_SOURCES = zpipe.cpp zerogsshaders.cpp diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/ZLib.lib b/plugins/gs/zerogs/opengl/ZeroGSShaders/ZLib.lib new file mode 100644 index 0000000000000000000000000000000000000000..7f4cf9ba6ed5cffb6d54b7d1cac4876a65cda678 GIT binary patch literal 101154 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%0A2!I2ly#qCEz6BGQhV03jx0a+yMAFU=!doz!>CU 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

sSdPO@+xFslc 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln b/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln new file mode 100644 index 0000000..45a5aa1 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZeroGSShaders", "ZeroGSShaders_2005.vcproj", "{811D47CC-E5F0-456A-918E-5908005E8FC0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release (to Public)|Win32 = Release (to Public)|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.ActiveCfg = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Debug|Win32.Build.0 = Debug|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.ActiveCfg = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release (to Public)|Win32.Build.0 = Release (to Public)|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.ActiveCfg = Release|Win32 + {811D47CC-E5F0-456A-918E-5908005E8FC0}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj b/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj new file mode 100644 index 0000000..0dfc9ad --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/ZeroGSShaders_2005.vcproj @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/copytozerogs.bat b/plugins/gs/zerogs/opengl/ZeroGSShaders/copytozerogs.bat new file mode 100644 index 0000000..32c9820 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/copytozerogs.bat @@ -0,0 +1 @@ +copy .\Release\ZeroGSShaders.exe ..\ \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.cpp b/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.cpp new file mode 100644 index 0000000..4659f74 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.cpp @@ -0,0 +1,337 @@ +#define _CRT_SECURE_NO_DEPRECATE + +// Builds all possible shader files from ps2hw.fx and stores them in +// a preprocessed database +#include +#include + +#include +#include "zpipe.h" + +#include +#include + +#define SAFE_RELEASE(x) { if( (x) != NULL ) { (x)->Release(); x = NULL; } } + +#include +#include + +using namespace std; + +#include "zerogsshaders.h" + +char* srcfilename = "ps2hw.fx"; +char* dstfilename = "ps2hw.dat"; + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +struct SHADERINFO +{ + int type; + vector buf; +}; + +map mapShaders; +CGcontext g_cgcontext; + +void LoadShader(int index, const char* pshader, CGprofile prof, vector& vargs, int context) +{ + vector realargs; + realargs.reserve(16); + realargs.resize(vargs.size()); + if( vargs.size() > 0 ) + memcpy(&realargs[0], &vargs[0], realargs.size() * sizeof(realargs[0])); + realargs.push_back(context ? "-Ictx1" : "-Ictx0"); + realargs.push_back(NULL); + + CGprogram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfilename, prof, pshader, &realargs[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", pshader, cgGetLastListing(g_cgcontext)); + return; + } + + if( mapShaders.find(index) != mapShaders.end() ) { + printf("error: two shaders share the same index %d\n", index); + exit(0); + } + + if( !cgIsProgramCompiled(prog) ) + cgCompileProgram(prog); + + const char* pstr = cgGetProgramString(prog, CG_COMPILED_PROGRAM); + + const char* pprog = strstr(pstr, "#program"); + if( pprog == NULL ) { + printf("program field not found!\n"); + return; + } + pprog += 9; + const char* progend = strchr(pprog, '\r'); + if( progend == NULL ) progend = strchr(pprog, '\n'); + + if( progend == NULL ) { + printf("prog end not found!\n"); + return; + } + + const char* defname = "main"; + + SHADERINFO info; + info.type = 0; + info.buf.resize(strlen(pstr)+1); + + // change the program name to main + memset(&info.buf[0], 0, info.buf.size()); + memcpy(&info.buf[0], pstr, pprog-pstr); + memcpy(&info.buf[pprog-pstr], defname, 4); + memcpy(&info.buf[pprog-pstr+4], progend, strlen(pstr)-(progend-pstr)); + + if( mapShaders.find(index) != mapShaders.end() ) + printf("same shader\n"); + assert( mapShaders.find(index) == mapShaders.end() ); + mapShaders[index] = info; + + cgDestroyProgram(prog); +} + +int main(int argc, char** argv) +{ + printf("usage: [src] [dst] [opts]\n"); + + if( argc >= 2 ) srcfilename = argv[1]; + if( argc >= 3 ) dstfilename = argv[2]; + + FILE* fsrc = fopen(srcfilename, "r"); + if( fsrc == NULL ) { + printf("cannot open %s\n", srcfilename); + return 0; + } + fclose(fsrc); + + g_cgcontext = cgCreateContext(); + if( !cgIsContext(g_cgcontext) ) { + printf("failed to create cg context\n"); + return -1; + } + + CGprofile cgvProf = CG_PROFILE_ARBVP1; + CGprofile cgfProf = CG_PROFILE_ARBFP1; + if( !cgGLIsProfileSupported(cgvProf) != CG_TRUE ) { + printf("arbvp1 not supported\n"); + return 0; + } + if( !cgGLIsProfileSupported(cgfProf) != CG_TRUE ) { + printf("arbfp1 not supported\n"); + return 0; + } + + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + vector vmacros; + + LoadShader(SH_BITBLTVS, "BitBltVS", cgvProf, vmacros, 0); + LoadShader(SH_BITBLTPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHPS, "BitBltDepthPS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTDEPTHMRTPS, "BitBltDepthMRTPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGPS, "CRTCTargPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCPS, "CRTCPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTC_NEARESTPS, "CRTCPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24PS, "CRTC24PS", cgfProf, vmacros, 0); + LoadShader(SH_ZEROPS, "ZeroPS", cgfProf, vmacros, 0); + LoadShader(SH_BASETEXTUREPS, "BaseTexturePS", cgfProf, vmacros, 0); + LoadShader(SH_BITBLTAAPS, "BitBltPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCTARGINTERPS, "CRTCTargInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTERPS, "CRTCInterPS", cgfProf, vmacros, 0); + LoadShader(SH_CRTCINTER_NEARESTPS, "CRTCInterPS_Nearest", cgfProf, vmacros, 0); + LoadShader(SH_CRTC24INTERPS, "CRTC24InterPS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT16TO32PS, "Convert16to32PS", cgfProf, vmacros, 0); + LoadShader(SH_CONVERT32TO16PS, "Convert32to16PS", cgfProf, vmacros, 0); + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + // load the texture shaders + char str[255], strdir[255]; + + strcpy(strdir, srcfilename); + int i = (int)strlen(strdir); + while(i > 0) { + if( strdir[i-1] == '/' || strdir[i-1] == '\\' ) + break; + --i; + } + + strdir[i] = 0; + + for(i = 0; i < ARRAYSIZE(vsshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0), pvsshaders[i], cgvProf, vmacros, 0); + LoadShader(vsshaders[i]|(writedepth?SH_WRITEDEPTH:0)|SH_CONTEXT1, pvsshaders[i], cgvProf, vmacros, 1); + if( writedepth ) vmacros.pop_back(); + } + } + + const int psshaders[2] = { SH_REGULARPS, SH_REGULARFOGPS }; + const char* ppsshaders[2] = { "RegularPS", "RegularFogPS" }; + + for(i = 0; i < ARRAYSIZE(psshaders); ++i) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + if( writedepth ) vmacros.push_back("-DWRITE_DEPTH"); + LoadShader(psshaders[i]|(writedepth?SH_WRITEDEPTH:0), ppsshaders[i], cgfProf, vmacros, 0); + if( writedepth ) vmacros.pop_back(); + } + } + + printf("creating shaders, note that ctx0/ps2hw_ctx.fx, and ctx1/ps2hw_ctx.fx are required\n"); + vmacros.resize(0); + + for(int texwrap = 0; texwrap < NUM_TEXWRAPS; ++texwrap ) { + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.push_back(g_pPsTexWrap[texwrap]); + + for(int context = 0; context < 2; ++context) { + + for(int texfilter = 0; texfilter < NUM_FILTERS; ++texfilter) { + for(int fog = 0; fog < 2; ++fog ) { + for(int writedepth = 0; writedepth < 2; ++writedepth ) { + + if( writedepth ) + vmacros.push_back("-DWRITE_DEPTH"); + + for(int testaem = 0; testaem < 2; ++testaem ) { + + if( testaem ) + vmacros.push_back("-DTEST_AEM"); + + for(int exactcolor = 0; exactcolor < 2; ++exactcolor ) { + + if( exactcolor ) + vmacros.push_back("-DEXACT_COLOR"); + + // 32 + sprintf(str, "Texture%s%d_32PS", fog?"Fog":"", texfilter); + + vmacros.push_back("-DACCURATE_DECOMPRESSION"); + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); + vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + if( texfilter == 0 ) { + // tex32 + sprintf(str, "Texture%s%d_tex32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // clut32 + sprintf(str, "Texture%s%d_clut32PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex32to16 + sprintf(str, "Texture%s%d_tex32to16PS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + + // tex16to8h + sprintf(str, "Texture%s%d_tex16to8hPS", fog?"Fog":"", texfilter); + +// vmacros.push_back("-DACCURATE_DECOMPRESSION"); +// LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_ACCURATE), str, cgfProf, vmacros, context); +// vmacros.pop_back(); + + LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, 0), str, cgfProf, vmacros, context); + } + + if( exactcolor ) + vmacros.pop_back(); + } + + if( testaem ) + vmacros.pop_back(); + } + + if( writedepth ) + vmacros.pop_back(); + } + } + } + } + + if( g_pPsTexWrap[texwrap] != NULL ) + vmacros.pop_back(); + } + + if( vmacros.size() != 0 ) + printf("error with macros!\n"); + + // create the database + + int num = (int)mapShaders.size(); + + // first compress + vector buffer; + buffer.reserve(10000000); // 10mb + buffer.resize(sizeof(SHADERHEADER)*num); + + i = 0; + for(map::iterator it = mapShaders.begin(); it != mapShaders.end(); ++it, ++i) { + SHADERHEADER h; + h.index = it->first | it->second.type; + h.offset = (int)buffer.size(); + h.size = (int)it->second.buf.size(); + + memcpy(&buffer[0] + i*sizeof(SHADERHEADER), &h, sizeof(SHADERHEADER)); + + size_t cur = buffer.size(); + buffer.resize(cur + it->second.buf.size()); + memcpy(&buffer[cur], &it->second.buf[0], it->second.buf.size()); + } + + int compressed_size; + int real_size = (int)buffer.size(); + vector dst; + dst.resize(buffer.size()); + def(&buffer[0], &dst[0], (int)buffer.size(), &compressed_size); + + // write to file + // fmt: num shaders, size of compressed, compressed data + FILE* fdst = fopen(dstfilename, "wb"); + if( fdst == NULL ) { + printf("failed to open %s\n", dstfilename); + return 0; + } + + fwrite(&num, 4, 1, fdst); + fwrite(&compressed_size, 4, 1, fdst); + fwrite(&real_size, 4, 1, fdst); + fwrite(&dst[0], compressed_size, 1, fdst); + + fclose(fdst); + + printf("wrote %s\n", dstfilename); + + cgDestroyContext(g_cgcontext); + + return 0; +} diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.h new file mode 100644 index 0000000..ae3f1d0 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zerogsshaders.h @@ -0,0 +1,89 @@ +#include +#include + +#define NUM_FILTERS 2 // texture filtering +#define NUM_TYPES 5 // types of texture read modes +#define NUM_TEXWRAPS 4 // texture wrapping + +#define SHADER_REDUCED 1 // equivalent to ps2.0 +#define SHADER_ACCURATE 2 // for older cards with less accurate math (ps2.x+) + +#define NUM_SHADERS (NUM_FILTERS*NUM_TYPES*NUM_TEXWRAPS*32) // # shaders for a given ps + +const static char* g_pShaders[] = { "full", "reduced", "accurate", "accurate-reduced" }; +const static char* g_pPsTexWrap[] = { "-DREPEAT", "-DCLAMP", "-DREGION_REPEAT", NULL }; +const static char* g_pTexTypes[] = { "32", "tex32", "clut32", "tex32to16", "tex16to8h" }; + +#define TEXWRAP_REPEAT 0 +#define TEXWRAP_CLAMP 1 +#define TEXWRAP_REGION_REPEAT 2 +#define TEXWRAP_REPEAT_CLAMP 3 + +inline int GET_SHADER_INDEX(int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int context, int ps) +{ + return type + texfilter*NUM_TYPES + NUM_FILTERS*NUM_TYPES*texwrap + NUM_TEXWRAPS*NUM_FILTERS*NUM_TYPES*(fog+2*writedepth+4*testaem+8*exactcolor+16*context+32*ps); +} + +extern CGcontext g_cgcontext; + +static CGprogram LoadShaderFromType(const char* srcdir, const char* srcfile, int type, int texfilter, int texwrap, int fog, int writedepth, int testaem, int exactcolor, int ps, int context) +{ + assert( texwrap < NUM_TEXWRAPS); + assert( type < NUM_TYPES ); + + char str[255], strctx[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + sprintf(strctx, "-I%s%s", srcdir, context?"ctx1":"ctx0"); + + vector macros; + macros.push_back(strctx); +#ifdef _DEBUG + macros.push_back("-bestprecision"); +#endif + if( g_pPsTexWrap[texwrap] != NULL ) macros.push_back(g_pPsTexWrap[texwrap]); + if( writedepth ) macros.push_back("-DWRITE_DEPTH"); + if( testaem ) macros.push_back("-DTEST_AEM"); + if( exactcolor ) macros.push_back("-DEXACT_COLOR"); + if( ps & SHADER_ACCURATE ) macros.push_back("-DACCURATE_DECOMPRESSION"); + macros.push_back(NULL); + + CGprogram prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, srcfile, CG_PROFILE_ARBFP1, str, ¯os[0]); + if( !cgIsProgram(prog) ) { + printf("Failed to load shader %s: \n%s\n", str, cgGetLastListing(g_cgcontext)); + return NULL; + } + + return prog; +} + +struct SHADERHEADER +{ + unsigned int index, offset, size; // if highest bit of index is set, pixel shader +}; + +#define SH_WRITEDEPTH 0x2000 // depth is written +#define SH_CONTEXT1 0x1000 // context1 is used + +#define SH_REGULARVS 0x8000 +#define SH_TEXTUREVS 0x8001 +#define SH_REGULARFOGVS 0x8002 +#define SH_TEXTUREFOGVS 0x8003 +#define SH_REGULARPS 0x8004 +#define SH_REGULARFOGPS 0x8005 +#define SH_BITBLTVS 0x8006 +#define SH_BITBLTPS 0x8007 +#define SH_BITBLTDEPTHPS 0x8009 +#define SH_CRTCTARGPS 0x800a +#define SH_CRTCPS 0x800b +#define SH_CRTC24PS 0x800c +#define SH_ZEROPS 0x800e +#define SH_BASETEXTUREPS 0x800f +#define SH_BITBLTAAPS 0x8010 +#define SH_CRTCTARGINTERPS 0x8012 +#define SH_CRTCINTERPS 0x8013 +#define SH_CRTC24INTERPS 0x8014 +#define SH_BITBLTDEPTHMRTPS 0x8016 +#define SH_CONVERT16TO32PS 0x8020 +#define SH_CONVERT32TO16PS 0x8021 +#define SH_CRTC_NEARESTPS 0x8022 +#define SH_CRTCINTER_NEARESTPS 0x8023 diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/crc32.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/crc32.h new file mode 100644 index 0000000..5de49bc --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/deflate.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/deflate.h new file mode 100644 index 0000000..0b5dd9b --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffast.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffast.h new file mode 100644 index 0000000..614fa78 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffixed.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffixed.h new file mode 100644 index 0000000..423d5c5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inflate.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inflate.h new file mode 100644 index 0000000..fbbc871 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inftrees.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inftrees.h new file mode 100644 index 0000000..dc0fd56 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/trees.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/trees.h new file mode 100644 index 0000000..1ca868b --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.h new file mode 100644 index 0000000..a5248c8 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.in.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.in.h new file mode 100644 index 0000000..48200f8 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zlib.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zlib.h new file mode 100644 index 0000000..62d0e46 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zutil.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zutil.h new file mode 100644 index 0000000..b691f27 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.2 2006/03/02 00:10:34 zerocool Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.cpp b/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.cpp new file mode 100644 index 0000000..e8c7b47 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.cpp @@ -0,0 +1,115 @@ +// zpipe.cpp : Defines the entry point for the console application. +// + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress) ; + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret;//, flush; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + have = bytes_to_compress - strm.avail_out ; + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + //unsigned have; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if( outbytes != NULL ) + *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.h b/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.h new file mode 100644 index 0000000..cb96229 --- /dev/null +++ b/plugins/gs/zerogs/opengl/ZeroGSShaders/zpipe.h @@ -0,0 +1,7 @@ +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif diff --git a/plugins/gs/zerogs/opengl/buildshaders.bat b/plugins/gs/zerogs/opengl/buildshaders.bat new file mode 100644 index 0000000..c769855 --- /dev/null +++ b/plugins/gs/zerogs/opengl/buildshaders.bat @@ -0,0 +1,3 @@ +ZeroGSShaders.exe ps2hw.fx ps2hw.dat +del Win32\ps2hw.dat Win32\Release\*.res Win32\Debug\*.res +move /y ps2hw.dat Win32\ps2hw.dat \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/common.h b/plugins/gs/zerogs/opengl/common.h new file mode 100644 index 0000000..1f815f5 --- /dev/null +++ b/plugins/gs/zerogs/opengl/common.h @@ -0,0 +1,1142 @@ +/** + * @file common.h + * common internal api header. + */ + +#ifndef COMMON_H +#define COMMON_H + +#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) +# define CONFIG_WIN32 +#endif + +//#define ALT_BITSTREAM_WRITER +//#define ALIGNED_BITSTREAM_WRITER + +#define ALT_BITSTREAM_READER +//#define LIBMPEG2_BITSTREAM_READER +//#define A32_BITSTREAM_READER +#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO + +#ifdef HAVE_AV_CONFIG_H +/* only include the following when compiling package */ +# include "config.h" + +# include +# include +# include +# include +# ifndef __BEOS__ +# include +# else +# include "berrno.h" +# endif +# include + +# ifndef ENODATA +# define ENODATA 61 +# endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include +#ifndef offsetof +# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F)) +#endif + +#define AVOPTION_CODEC_BOOL(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_BOOL } +#define AVOPTION_CODEC_DOUBLE(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_DOUBLE, minv, maxv, defval } +#define AVOPTION_CODEC_FLAG(name, help, field, flag, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_FLAG, flag, 0, defval } +#define AVOPTION_CODEC_INT(name, help, field, minv, maxv, defval) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_INT, minv, maxv, defval } +#define AVOPTION_CODEC_STRING(name, help, field, str, val) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_STRING, .defval = val, .defstr = str } +#define AVOPTION_CODEC_RCOVERRIDE(name, help, field) \ + { name, help, offsetof(AVCodecContext, field), FF_OPT_TYPE_RCOVERRIDE, .defval = 0, .defstr = NULL } +#define AVOPTION_SUB(ptr) { .name = NULL, .help = (const char*)ptr } +#define AVOPTION_END() AVOPTION_SUB(NULL) + +struct AVOption; +#ifdef HAVE_MMX +extern const struct AVOption avoptions_common[3 + 5]; +#else +extern const struct AVOption avoptions_common[3]; +#endif +extern const struct AVOption avoptions_workaround_bug[11]; + +#endif /* HAVE_AV_CONFIG_H */ + +/* Suppress restrict if it was not defined in config.h. */ +#ifndef restrict +# define restrict +#endif + +#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define always_inline __attribute__((always_inline)) inline +#else +# define always_inline inline +#endif + +#ifdef CONFIG_WIN32 + +/* windows */ + +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +typedef signed char int8_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + +# ifndef __MINGW32__ +# define int64_t_C(c) (c ## i64) +# define uint64_t_C(c) (c ## i64) + +# define inline __inline + +# else +# define int64_t_C(c) (c ## LL) +# define uint64_t_C(c) (c ## ULL) +# endif /* __MINGW32__ */ + +# ifdef _DEBUG +# define DEBUG +# endif + +# define snprintf _snprintf +# define vsnprintf _vsnprintf + +/* CONFIG_WIN32 end */ +#elif defined (CONFIG_OS2) +/* OS/2 EMX */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +#ifdef USE_FASTMEMCPY +#include "fastmemcpy.h" +#endif + +#include + +#endif /* HAVE_AV_CONFIG_H */ + +/* CONFIG_OS2 end */ +#else + +/* unix */ + +#include + +#ifndef int64_t_C +#define int64_t_C(c) (c ## LL) +#define uint64_t_C(c) (c ## ULL) +#endif + +#ifdef HAVE_AV_CONFIG_H + +# ifdef USE_FASTMEMCPY +# include "fastmemcpy.h" +# endif +# endif /* HAVE_AV_CONFIG_H */ + +#endif /* !CONFIG_WIN32 && !CONFIG_OS2 */ + +#ifdef HAVE_AV_CONFIG_H + +# include "bswap.h" + +# if defined(__MINGW32__) || defined(__CYGWIN__) || \ + defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# define MANGLE(a) "_" #a +# else +# define MANGLE(a) #a +# endif + +/* debug stuff */ + +# ifndef DEBUG +# define NDEBUG +# endif +# include + +/* dprintf macros */ +# if defined(CONFIG_WIN32) && !defined(__MINGW32__) + +inline void dprintf(const char* fmt,...) {} + +# else + +# ifdef DEBUG +# define dprintf(fmt,args...) printf(fmt, ## args) +# else +# define dprintf(fmt,args...) +# endif + +# endif /* !CONFIG_WIN32 */ + +# define av_abort() do { fprintf(stderr, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0) + +//rounded divison & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) +/* assume b>0 */ +#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) + +#define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +extern const uint32_t inverse[256]; + +#ifdef ARCH_X86 +# define FASTDIV(a,b) \ + ({\ + int ret,dmy;\ + asm volatile(\ + "mull %3"\ + :"=d"(ret),"=a"(dmy)\ + :"1"(a),"g"(inverse[b])\ + );\ + ret;\ + }) +#elif defined(CONFIG_FASTDIV) +# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*inverse[b])>>32)) +#else +# define FASTDIV(a,b) ((a)/(b)) +#endif + +#ifdef ARCH_X86 +// avoid +32 for shift optimization (gcc should do that ...) +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + asm ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + asm ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} +#else +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +/* bit output */ + +struct PutBitContext; + +typedef void (*WriteDataFunc)(void *, uint8_t *, int); + +typedef struct PutBitContext { +#ifdef ALT_BITSTREAM_WRITER + uint8_t *buf, *buf_end; + int index; +#else + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; +#endif + int64_t data_out_size; /* in bytes */ +} PutBitContext; + +void init_put_bits(PutBitContext *s, + uint8_t *buffer, int buffer_size, + void *opaque, + void (*write_data)(void *, uint8_t *, int)); + +int64_t get_bit_count(PutBitContext *s); /* XXX: change function name */ +void align_put_bits(PutBitContext *s); +void flush_put_bits(PutBitContext *s); +void put_string(PutBitContext * pbc, char *s); + +/* bit input */ + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; +#ifdef ALT_BITSTREAM_READER + int index; +#elif defined LIBMPEG2_BITSTREAM_READER + uint8_t *buffer_ptr; + uint32_t cache; + int bit_count; +#elif defined A32_BITSTREAM_READER + uint32_t *buffer_ptr; + uint32_t cache0; + uint32_t cache1; + int bit_count; +#endif + int size_in_bits; +} GetBitContext; + +static inline int get_bits_count(GetBitContext *s); + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +#ifdef ARCH_SPARC64 +#define UNALIGNED_STORES_ARE_BAD +#endif + +/* used to avoid missaligned exceptions on some archs (alpha, ...) */ +#ifdef ARCH_X86 +# define unaligned32(a) (*(uint32_t*)(a)) +#else +# ifdef __GNUC__ +static inline uint32_t unaligned32(const void *v) { + struct Unaligned { + uint32_t i; + } __attribute__((packed)); + + return ((const struct Unaligned *) v)->i; +} +# elif defined(__DECC) +static inline uint32_t unaligned32(const void *v) { + return *(const __unaligned uint32_t *) v; +} +# else +static inline uint32_t unaligned32(const void *v) { + return *(const uint32_t *) v; +} +# endif +#endif //!ARCH_X86 + +#ifndef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + +#ifdef STATS + st_out_bit_counts[st_current_index] += n; +#endif + // printf("put_bits=%d %x\n", n, value); + assert(n == 32 || value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + // printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf); + /* XXX: optimize */ + if (n < bit_left) { + bit_buf = (bit_buf<> (n - bit_left); +#ifdef UNALIGNED_STORES_ARE_BAD + if (3 & (int) s->buf_ptr) { + s->buf_ptr[0] = bit_buf >> 24; + s->buf_ptr[1] = bit_buf >> 16; + s->buf_ptr[2] = bit_buf >> 8; + s->buf_ptr[3] = bit_buf ; + } else +#endif + *(uint32_t *)s->buf_ptr = be2me_32(bit_buf); + //printf("bitbuf = %08x\n", bit_buf); + s->buf_ptr+=4; + bit_left+=32 - n; + bit_buf = value; + } + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} +#endif + + +#ifdef ALT_BITSTREAM_WRITER +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ +# ifdef ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl %0, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "shrdl %%cl, %1, %%eax \n\t" + "shrl %%cl, %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "andl $0xFFFFFFFC, %%ecx \n\t" + "bswapl %1 \n\t" + "orl %1, (%2, %%ecx) \n\t" + "bswapl %%eax \n\t" + "addl %3, %0 \n\t" + "movl %%eax, 4(%2, %%ecx) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n)) + : "%eax", "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5); + + value<<= 32-n; + + ptr[0] |= be2me_32(value>>(index&31)); + ptr[1] = be2me_32(value<<(32-(index&31))); +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# else //ALIGNED_BITSTREAM_WRITER +# ifdef ARCH_X86 + asm volatile( + "movl $7, %%ecx \n\t" + "andl %0, %%ecx \n\t" + "addl %3, %%ecx \n\t" + "negl %%ecx \n\t" + "shll %%cl, %1 \n\t" + "bswapl %1 \n\t" + "movl %0, %%ecx \n\t" + "shrl $3, %%ecx \n\t" + "orl %1, (%%ecx, %2) \n\t" + "addl %3, %0 \n\t" + "movl $0, 4(%%ecx, %2) \n\t" + : "=&r" (s->index), "=&r" (value) + : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) + : "%ecx" + ); +# else + int index= s->index; + uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); + + ptr[0] |= be2me_32(value<<(32-n-(index&7) )); + ptr[1] = 0; +//if(n>24) printf("%d %d\n", n, value); + index+= n; + s->index= index; +# endif +# endif //!ALIGNED_BITSTREAM_WRITER +} +#endif + + +static inline uint8_t* pbBufPtr(PutBitContext *s) +{ +#ifdef ALT_BITSTREAM_WRITER + return s->buf + (s->index>>3); +#else + return s->buf_ptr; +#endif +} + +/* Bitstream reader API docs: +name + abritary name which is used as prefix for the internal variables + +gb + getbitcontext + +OPEN_READER(name, gb) + loads gb into local variables + +CLOSE_READER(name, gb) + stores local vars in gb + +UPDATE_CACHE(name, gb) + refills the internal cache from the bitstream + after this call at least MIN_CACHE_BITS will be available, + +GET_CACHE(name, gb) + will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit) + +SHOW_UBITS(name, gb, num) + will return the nest num bits + +SHOW_SBITS(name, gb, num) + will return the nest num bits and do sign extension + +SKIP_BITS(name, gb, num) + will skip over the next num bits + note, this is equinvalent to SKIP_CACHE; SKIP_COUNTER + +SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER) + +SKIP_COUNTER(name, gb, num) + will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) + +LAST_SKIP_CACHE(name, gb, num) + will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing + +LAST_SKIP_BITS(name, gb, num) + is equinvalent to SKIP_LAST_CACHE; SKIP_COUNTER + +for examples see get_bits, show_bits, skip_bits, get_vlc +*/ + +static inline int unaligned32_be(const void *v) +{ +#ifdef CONFIG_ALIGN + const uint8_t *p=v; + return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]); +#else + return be2me_32( unaligned32(v)); //original +#endif +} + +#ifdef ALT_BITSTREAM_READER +# define MIN_CACHE_BITS 25 + +# define OPEN_READER(name, gb)\ + int name##_index= (gb)->index;\ + int name##_cache= 0;\ + +# define CLOSE_READER(name, gb)\ + (gb)->index= name##_index;\ + +# define UPDATE_CACHE(name, gb)\ + name##_cache= unaligned32_be( ((uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\ + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +// FIXME name? +# define SKIP_COUNTER(name, gb, num)\ + name##_index += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) ; + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return s->index; +} +#elif defined LIBMPEG2_BITSTREAM_READER +//libmpeg2 like reader + +# define MIN_CACHE_BITS 17 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + int name##_cache= (gb)->cache;\ + uint8_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache= name##_cache;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +#ifdef LIBMPEG2_BITSTREAM_READER_HACK + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= (int)be2me_16(*(uint16_t*)name##_buffer_ptr) << name##_bit_count;\ + ((uint16_t*)name##_buffer_ptr)++;\ + name##_bit_count-= 16;\ + }\ + +#else + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count >= 0){\ + name##_cache+= ((name##_buffer_ptr[0]<<8) + name##_buffer_ptr[1]) << name##_bit_count;\ + name##_buffer_ptr+=2;\ + name##_bit_count-= 16;\ + }\ + +#endif + +# define SKIP_CACHE(name, gb, num)\ + name##_cache <<= (num);\ + +# define SKIP_COUNTER(name, gb, num)\ + name##_bit_count += (num);\ + +# define SKIP_BITS(name, gb, num)\ + {\ + SKIP_CACHE(name, gb, num)\ + SKIP_COUNTER(name, gb, num)\ + }\ + +# define LAST_SKIP_BITS(name, gb, num) SKIP_BITS(name, gb, num) +# define LAST_SKIP_CACHE(name, gb, num) SKIP_CACHE(name, gb, num) + +# define SHOW_UBITS(name, gb, num)\ + NEG_USR32(name##_cache, num) + +# define SHOW_SBITS(name, gb, num)\ + NEG_SSR32(name##_cache, num) + +# define GET_CACHE(name, gb)\ + ((uint32_t)name##_cache) + +static inline int get_bits_count(GetBitContext *s){ + return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count; +} + +#elif defined A32_BITSTREAM_READER + +# define MIN_CACHE_BITS 32 + +# define OPEN_READER(name, gb)\ + int name##_bit_count=(gb)->bit_count;\ + uint32_t name##_cache0= (gb)->cache0;\ + uint32_t name##_cache1= (gb)->cache1;\ + uint32_t * name##_buffer_ptr=(gb)->buffer_ptr;\ + +# define CLOSE_READER(name, gb)\ + (gb)->bit_count= name##_bit_count;\ + (gb)->cache0= name##_cache0;\ + (gb)->cache1= name##_cache1;\ + (gb)->buffer_ptr= name##_buffer_ptr;\ + +# define UPDATE_CACHE(name, gb)\ + if(name##_bit_count > 0){\ + const uint32_t next= be2me_32( *name##_buffer_ptr );\ + name##_cache0 |= NEG_USR32(next,name##_bit_count);\ + name##_cache1 |= next<buffer_ptr - s->buffer)*8 - 32 + s->bit_count; +} + +#endif + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + * @author BERO + */ +static inline int get_xbits(GetBitContext *s, int n){ + register int tmp; + register int32_t cache; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + cache = GET_CACHE(re,s); + if ((int32_t)cache<0) { //MSB=1 + tmp = NEG_USR32(cache,n); + } else { + // tmp = (-1<index+=n for the ALT_READER :)) + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +} + +static inline unsigned int get_bits1(GetBitContext *s){ +#ifdef ALT_BITSTREAM_READER + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + + return result; +#else + return get_bits(s, 1); +#endif +} + +static inline unsigned int show_bits1(GetBitContext *s){ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s){ + skip_bits(s, 1); +} + +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int buffer_size); + +int check_marker(GetBitContext *s, const char *msg); +void align_get_bits(GetBitContext *s); +int init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size); +void free_vlc(VLC *vlc); + +/** + * + * if the vlc code is invalid and max_depth=1 than no bits will be removed + * if the vlc code is invalid and max_depth>1 than the number of bits removed + * is undefined + */ +#define GET_VLC(code, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + code = table[index][0];\ + n = table[index][1];\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + if(max_depth > 2 && n < 0){\ + LAST_SKIP_BITS(name, gb, nb_bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + code;\ + code = table[index][0];\ + n = table[index][1];\ + }\ + }\ + SKIP_BITS(name, gb, n)\ +} + +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth)\ +{\ + int n, index, nb_bits;\ +\ + index= SHOW_UBITS(name, gb, bits);\ + level = table[index].level;\ + n = table[index].len;\ +\ + if(max_depth > 1 && n < 0){\ + LAST_SKIP_BITS(name, gb, bits)\ + UPDATE_CACHE(name, gb)\ +\ + nb_bits = -n;\ +\ + index= SHOW_UBITS(name, gb, nb_bits) + level;\ + level = table[index].level;\ + n = table[index].len;\ + }\ + run= table[index].run;\ + SKIP_BITS(name, gb, n)\ +} + +// deprecated, dont use get_vlc for new code, use get_vlc2 instead or use GET_VLC directly +static inline int get_vlc(GetBitContext *s, VLC *vlc) +{ + int code; + VLC_TYPE (*table)[2]= vlc->table; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, vlc->bits, 3) + + CLOSE_READER(re, s) + return code; +} + +/** + * parses a vlc code, faster then get_vlc() + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be readed to completly + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + + GET_VLC(code, re, s, table, bits, max_depth) + + CLOSE_READER(re, s) + return code; +} + +//#define TRACE + +#ifdef TRACE + +static inline void print_bin(int bits, int n){ + int i; + + for(i=n-1; i>=0; i--){ + printf("%d", (bits>>i)&1); + } + for(i=n; i<24; i++) + printf(" "); +} + +static inline int get_bits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int r= get_bits(s, n); + + print_bin(r, n); + printf("%5d %2d %3d bit @%5d in %s %s:%d\n", r, n, r, get_bits_count(s)-n, file, func, line); + return r; +} +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int r= get_vlc2(s, table, bits, max_depth); + int len= get_bits_count(s) - pos; + int bits2= show>>(24-len); + + print_bin(bits2, len); + + printf("%5d %2d %3d vlc @%5d in %s %s:%d\n", bits2, len, r, pos, file, func, line); + return r; +} +static inline int get_xbits_trace(GetBitContext *s, int n, char *file, char *func, int line){ + int show= show_bits(s, n); + int r= get_xbits(s, n); + + print_bin(show, n); + printf("%5d %2d %3d xbt @%5d in %s %s:%d\n", show, n, r, get_bits_count(s)-n, file, func, line); + return r; +} + +#define get_bits(s, n) get_bits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf printf + +#else //TRACE +#define tprintf(_arg...) {} +#endif + +/* define it to include statistics code (useful only for optimizing + codec efficiency */ +//#define STATS + +#ifdef STATS + +enum { + ST_UNKNOWN, + ST_DC, + ST_INTRA_AC, + ST_INTER_AC, + ST_INTRA_MB, + ST_INTER_MB, + ST_MV, + ST_NB, +}; + +extern int st_current_index; +extern unsigned int st_bit_counts[ST_NB]; +extern unsigned int st_out_bit_counts[ST_NB]; + +void print_stats(void); +#endif + +/* misc math functions */ +extern const uint8_t ff_log2_tab[256]; + +static inline int av_log2(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xffff0000) { + v >>= 16; + n += 16; + } + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + +static inline int av_log2_16bit(unsigned int v) +{ + int n; + + n = 0; + if (v & 0xff00) { + v >>= 8; + n += 8; + } + n += ff_log2_tab[v]; + + return n; +} + + +/* median of 3 */ +static inline int mid_pred(int a, int b, int c) +{ + int vmin, vmax; + vmax = vmin = a; + if (b < vmin) + vmin = b; + else + vmax = b; + + if (c < vmin) + vmin = c; + else if (c > vmax) + vmax = c; + + return a + b + c - vmin - vmax; +} + +static inline int clip(int a, int amin, int amax) +{ + if (a < amin) + return amin; + else if (a > amax) + return amax; + else + return a; +} + +/* math */ +extern const uint8_t ff_sqrt_tab[128]; + +int64_t ff_gcd(int64_t a, int64_t b); + +static inline int ff_sqrt(int a) +{ + int ret=0; + int s; + int ret_sq=0; + + if(a<128) return ff_sqrt_tab[a]; + + for(s=15; s>=0; s--){ + int b= ret_sq + (1<<(s*2)) + (ret<>31;\ + level= (level^mask)-mask; +#endif + + +#if __CPU__ >= 686 && !defined(RUNTIME_CPUDETECT) +#define COPY3_IF_LT(x,y,a,b,c,d)\ +asm volatile (\ + "cmpl %0, %3 \n\t"\ + "cmovl %3, %0 \n\t"\ + "cmovl %4, %1 \n\t"\ + "cmovl %5, %2 \n\t"\ + : "+r" (x), "+r" (a), "+r" (c)\ + : "r" (y), "r" (b), "r" (d)\ +); +#else +#define COPY3_IF_LT(x,y,a,b,c,d)\ +if((y)<(x)){\ + (x)=(y);\ + (a)=(b);\ + (c)=(d);\ +} +#endif + +#ifdef ARCH_X86 +static inline long long rdtsc() +{ + long long l; + asm volatile( "rdtsc\n\t" + : "=A" (l) + ); + return l; +} + +#define START_TIMER \ +static uint64_t tsum=0;\ +static int tcount=0;\ +static int tskip_count=0;\ +uint64_t tend;\ +uint64_t tstart= rdtsc();\ + +#define STOP_TIMER(id) \ +tend= rdtsc();\ +if(tcount<2 || tend - tstart < 4*tsum/tcount){\ + tsum+= tend - tstart;\ + tcount++;\ +}else\ + tskip_count++;\ +if(256*256*256*64%(tcount+tskip_count)==0){\ + fprintf(stderr, "%Ld dezicycles in %s, %d runs, %d skips\n", tsum*10/tcount, id, tcount, tskip_count);\ +} +#endif + +#define CLAMP_TO_8BIT(d) ((d > 0xff) ? 0xff : (d < 0) ? 0 : d) + +/* avoid usage of various functions */ +#define malloc please_use_av_malloc +#define free please_use_av_free +#define realloc please_use_av_realloc + +#define CHECKED_ALLOCZ(p, size)\ +{\ + p= av_mallocz(size);\ + if(p==NULL && (size)!=0){\ + perror("malloc");\ + goto fail;\ + }\ +} + +#endif /* HAVE_AV_CONFIG_H */ + +#endif /* COMMON_H */ diff --git a/plugins/gs/zerogs/opengl/compile b/plugins/gs/zerogs/opengl/compile new file mode 100644 index 0000000..973c773 --- /dev/null +++ b/plugins/gs/zerogs/opengl/compile @@ -0,0 +1 @@ +link /usr/share/automake-1.9/compile \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/configure b/plugins/gs/zerogs/opengl/configure new file mode 100644 index 0000000..f1cfad7 --- /dev/null +++ b/plugins/gs/zerogs/opengl/configure @@ -0,0 +1,5631 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59 for ZeroGSogl 0.96.2. +# +# Report bugs to . +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='ZeroGSogl' +PACKAGE_TARNAME='zerogsogl' +PACKAGE_VERSION='0.96.2' +PACKAGE_STRING='ZeroGSogl 0.96.2' +PACKAGE_BUGREPORT='zerofrog@gmail.com' + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CPP RANLIB ac_ct_RANLIB CCAS CCASFLAGS ZEROGS_CURRENT ZEROGS_REVISION ZEROGS_AGE ZEROGS_RELEASE ZEROGS_SONAME RELEASE_TO_PUBLIC_TRUE RELEASE_TO_PUBLIC_FALSE SSE2_TRUE SSE2_FALSE X86_64_TRUE X86_64_FALSE GTK_CONFIG so_ext SHARED_LDFLAGS LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CCAS_set=${CCAS+set} +ac_env_CCAS_value=$CCAS +ac_cv_env_CCAS_set=${CCAS+set} +ac_cv_env_CCAS_value=$CCAS +ac_env_CCASFLAGS_set=${CCASFLAGS+set} +ac_env_CCASFLAGS_value=$CCASFLAGS +ac_cv_env_CCASFLAGS_set=${CCASFLAGS+set} +ac_cv_env_CCASFLAGS_value=$CCASFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures ZeroGSogl 0.96.2 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of ZeroGSogl 0.96.2:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-debug debug build + --enable-devbuild Special Build for developers that simplifies testing + and adds extra checks + --enable-sse2 Enable sse2 instructions + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + CCAS assembler compiler command (defaults to CC) + CCASFLAGS assembler compiler flags (defaults to CFLAGS) + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +ZeroGSogl configure 0.96.2 +generated by GNU Autoconf 2.59 + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by ZeroGSogl $as_me 0.96.2, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + +am__api_version="1.9" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # We used to keeping the `.' as first argument, in order to + # allow $(mkdir_p) to be used without argument. As in + # $(mkdir_p) $(somedir) + # where $(somedir) is conditionally defined. However this is wrong + # for two reasons: + # 1. if the package is installed by a user who cannot write `.' + # make install will fail, + # 2. the above comment should most certainly read + # $(mkdir_p) $(DESTDIR)$(somedir) + # so it does not work when $(somedir) is undefined and + # $(DESTDIR) is not. + # To support the latter case, we have to write + # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), + # so the `.' trick is pointless. + mkdir_p='mkdir -p --' +else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + for d in ./-p ./--version; + do + test -d $d && rmdir $d + done + # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. + if test -f "$ac_aux_dir/mkinstalldirs"; then + mkdir_p='$(mkinstalldirs)' + else + mkdir_p='$(install_sh) -d' + fi +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE=ZeroGSogl + VERSION=0.96.2 + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in gcc g++ cl KCC CC cxx cc++ xlC aCC c++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in gcc g++ cl KCC CC cxx cc++ xlC aCC c++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo done +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC gcc g++ cl KCC CC cxx cc++ xlC aCC c++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC gcc g++ cl KCC CC cxx cc++ xlC aCC c++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + +# By default we simply use the C compiler to build assembly code. + +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS + + + + +ZEROGS_CURRENT=0 +ZEROGS_REVISION=96 +ZEROGS_AGE=2 +ZEROGS_SONAME=libZeroGSogl.so.$ZEROGS_CURRENT.$ZEROGS_REVISION.$ZEROGS_AGE +ZEROGS_RELEASE=$ZEROGS_CURRENT.$ZEROGS_REVISION.$ZEROGS_AGE + + + + + + + +CFLAGS=" -I/opt/cg/include -L/opt/cg/lib " +CPPFLAGS=" -I/opt/cg/include -L/opt/cg/lib " +CXXFLAGS=" -I/opt/cg/include -L/opt/cg/lib " + +echo "$as_me:$LINENO: checking debug build" >&5 +echo $ECHO_N "checking debug build... $ECHO_C" >&6 +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + debug=$enableval +else + debug=no +fi; +if test "x$debug" == xyes +then + +cat >>confdefs.h <<\_ACEOF +#define _DEBUG 1 +_ACEOF + + CFLAGS+="-g " + CPPFLAGS+="-g " + CXXFLAGS+="-g " +else + +cat >>confdefs.h <<\_ACEOF +#define NDEBUG 1 +_ACEOF + + CFLAGS+="-O2 -fomit-frame-pointer " + CPPFLAGS+="-O2 -fomit-frame-pointer " + CXXFLAGS+="-O2 -fomit-frame-pointer " +fi +echo "$as_me:$LINENO: result: $debug" >&5 +echo "${ECHO_T}$debug" >&6 + + + + +for ac_func in _aligned_malloc _aligned_free +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + cat >>confdefs.h <<\_ACEOF +#define HAVE_ALIGNED_MALLOC 1 +_ACEOF + +fi +done + + +echo "$as_me:$LINENO: checking for development build..." >&5 +echo $ECHO_N "checking for development build...... $ECHO_C" >&6 +# Check whether --enable-devbuild or --disable-devbuild was given. +if test "${enable_devbuild+set}" = set; then + enableval="$enable_devbuild" + devbuild=$enableval +else + devbuild=no +fi; +if test "x$devbuild" == xno +then + +cat >>confdefs.h <<\_ACEOF +#define RELEASE_TO_PUBLIC 1 +_ACEOF + +fi +echo "$as_me:$LINENO: result: $devbuild" >&5 +echo "${ECHO_T}$devbuild" >&6 + + +if test x$devbuild = xno; then + RELEASE_TO_PUBLIC_TRUE= + RELEASE_TO_PUBLIC_FALSE='#' +else + RELEASE_TO_PUBLIC_TRUE='#' + RELEASE_TO_PUBLIC_FALSE= +fi + + +echo "$as_me:$LINENO: checking check for sse2..." >&5 +echo $ECHO_N "checking check for sse2...... $ECHO_C" >&6 +# Check whether --enable-sse2 or --disable-sse2 was given. +if test "${enable_sse2+set}" = set; then + enableval="$enable_sse2" + sse2=$enableval +else + sse2=no +fi; +if test "x$sse2" == xyes +then + +cat >>confdefs.h <<\_ACEOF +#define ZEROGS_SSE2 1 +_ACEOF + +fi +echo "$as_me:$LINENO: result: $sse2" >&5 +echo "${ECHO_T}$sse2" >&6 + + +if test x$sse2 = xyes; then + SSE2_TRUE= + SSE2_FALSE='#' +else + SSE2_TRUE='#' + SSE2_FALSE= +fi + + +echo "$as_me:$LINENO: checking for a x86-64 CPU" >&5 +echo $ECHO_N "checking for a x86-64 CPU... $ECHO_C" >&6 +if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int main() +{ +int a = 0; +int*pa = &a; +asm(".intel_syntax\n" + "mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + ".att_syntax\n" + : : "r"(pa) : "%rax"); +return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cpu64=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +cpu64=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +if test "x$cpu64" == xyes +then + +cat >>confdefs.h <<\_ACEOF +#define __x86_64__ 1 +_ACEOF + +fi +echo "$as_me:$LINENO: result: $cpu64" >&5 +echo "${ECHO_T}$cpu64" >&6 + + +if test x$cpu64 = xyes; then + X86_64_TRUE= + X86_64_FALSE='#' +else + X86_64_TRUE='#' + X86_64_FALSE= +fi + + +echo "$as_me:$LINENO: checking gtk2+" >&5 +echo $ECHO_N "checking gtk2+... $ECHO_C" >&6 +# Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_GTK_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$GTK_CONFIG"; then + ac_cv_prog_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_GTK_CONFIG="pkg-config" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +GTK_CONFIG=$ac_cv_prog_GTK_CONFIG +if test -n "$GTK_CONFIG"; then + echo "$as_me:$LINENO: result: $GTK_CONFIG" >&5 +echo "${ECHO_T}$GTK_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +LIBS+=$(pkg-config --libs gtk+-2.0) + + +so_ext=".so.$ZEROGS_RELEASE" +SHARED_LDFLAGS="-shared" + + + +echo "$as_me:$LINENO: checking OpenGL" >&5 +echo $ECHO_N "checking OpenGL... $ECHO_C" >&6 + + + +for ac_header in GL/gl.h GL/glu.h GL/glext.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_GL_GL_H + #include + #endif + #if HAVE_GL_GLU_H + #include + #endif + + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +echo "$as_me:$LINENO: checking for main in -lGL" >&5 +echo $ECHO_N "checking for main in -lGL... $ECHO_C" >&6 +if test "${ac_cv_lib_GL_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_GL_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_GL_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_GL_main" >&5 +echo "${ECHO_T}$ac_cv_lib_GL_main" >&6 +if test $ac_cv_lib_GL_main = yes; then + LIBS="$LIBS -lGL" +fi + +echo "$as_me:$LINENO: checking for main in -lGLU" >&5 +echo $ECHO_N "checking for main in -lGLU... $ECHO_C" >&6 +if test "${ac_cv_lib_GLU_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGLU $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_GLU_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_GLU_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_GLU_main" >&5 +echo "${ECHO_T}$ac_cv_lib_GLU_main" >&6 +if test $ac_cv_lib_GLU_main = yes; then + LIBS="$LIBS -lGLU" +fi + +echo "$as_me:$LINENO: checking Cg" >&5 +echo $ECHO_N "checking Cg... $ECHO_C" >&6 +#AC_CHECK_HEADERS([Cg/cg.h Cg/cgGL.h]) + +echo "$as_me:$LINENO: checking for main in -ljpeg" >&5 +echo $ECHO_N "checking for main in -ljpeg... $ECHO_C" >&6 +if test "${ac_cv_lib_jpeg_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_jpeg_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_jpeg_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_jpeg_main" >&5 +echo "${ECHO_T}$ac_cv_lib_jpeg_main" >&6 +if test $ac_cv_lib_jpeg_main = yes; then + LIBS="$LIBS -ljpeg" +fi + +echo "$as_me:$LINENO: checking for main in -lpthread" >&5 +echo $ECHO_N "checking for main in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_main" >&6 +if test $ac_cv_lib_pthread_main = yes; then + LIBS="$LIBS -lpthread" +fi + +echo "$as_me:$LINENO: checking for main in -lstdc++" >&5 +echo $ECHO_N "checking for main in -lstdc++... $ECHO_C" >&6 +if test "${ac_cv_lib_stdcpp_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lstdc++ $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_stdcpp_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_stdcpp_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_stdcpp_main" >&5 +echo "${ECHO_T}$ac_cv_lib_stdcpp_main" >&6 +if test $ac_cv_lib_stdcpp_main = yes; then + LIBS="$LIBS -lstdc++" +fi + +echo "$as_me:$LINENO: checking for main in -lz" >&5 +echo $ECHO_N "checking for main in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_z_main" >&5 +echo "${ECHO_T}$ac_cv_lib_z_main" >&6 +if test $ac_cv_lib_z_main = yes; then + LIBS="$LIBS -lz" +fi + +echo "$as_me:$LINENO: checking for main in -ldl" >&5 +echo $ECHO_N "checking for main in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_main" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_main" >&6 +if test $ac_cv_lib_dl_main = yes; then + LIBS="$LIBS -ldl" +fi + +echo "$as_me:$LINENO: checking for main in -lXxf86vm" >&5 +echo $ECHO_N "checking for main in -lXxf86vm... $ECHO_C" >&6 +if test "${ac_cv_lib_Xxf86vm_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXxf86vm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xxf86vm_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xxf86vm_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xxf86vm_main" >&5 +echo "${ECHO_T}$ac_cv_lib_Xxf86vm_main" >&6 +if test $ac_cv_lib_Xxf86vm_main = yes; then + LIBS="$LIBS -lXxf86vm" +fi + + +LIBS+=" -lCg -lCgGL" + + ac_config_files="$ac_config_files Makefile Linux/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${RELEASE_TO_PUBLIC_TRUE}" && test -z "${RELEASE_TO_PUBLIC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"RELEASE_TO_PUBLIC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"RELEASE_TO_PUBLIC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${SSE2_TRUE}" && test -z "${SSE2_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"SSE2\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"SSE2\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${X86_64_TRUE}" && test -z "${X86_64_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"X86_64\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"X86_64\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by ZeroGSogl $as_me 0.96.2, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +ZeroGSogl config.status 0.96.2 +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "Linux/Makefile" ) CONFIG_FILES="$CONFIG_FILES Linux/Makefile" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@mkdir_p@,$mkdir_p,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t +s,@AMTAR@,$AMTAR,;t t +s,@am__tar@,$am__tar,;t t +s,@am__untar@,$am__untar,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t +s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t +s,@CPP@,$CPP,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@CCAS@,$CCAS,;t t +s,@CCASFLAGS@,$CCASFLAGS,;t t +s,@ZEROGS_CURRENT@,$ZEROGS_CURRENT,;t t +s,@ZEROGS_REVISION@,$ZEROGS_REVISION,;t t +s,@ZEROGS_AGE@,$ZEROGS_AGE,;t t +s,@ZEROGS_RELEASE@,$ZEROGS_RELEASE,;t t +s,@ZEROGS_SONAME@,$ZEROGS_SONAME,;t t +s,@RELEASE_TO_PUBLIC_TRUE@,$RELEASE_TO_PUBLIC_TRUE,;t t +s,@RELEASE_TO_PUBLIC_FALSE@,$RELEASE_TO_PUBLIC_FALSE,;t t +s,@SSE2_TRUE@,$SSE2_TRUE,;t t +s,@SSE2_FALSE@,$SSE2_FALSE,;t t +s,@X86_64_TRUE@,$X86_64_TRUE,;t t +s,@X86_64_FALSE@,$X86_64_FALSE,;t t +s,@GTK_CONFIG@,$GTK_CONFIG,;t t +s,@so_ext@,$so_ext,;t t +s,@SHARED_LDFLAGS@,$SHARED_LDFLAGS,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +echo "Configuration:" +echo " Target system type: $target" +echo " x86-64 build? $cpu64" +echo " Debug build? $debug" +echo " Dev build? $devbuild" +echo " SSE2 enabled? $sse2" diff --git a/plugins/gs/zerogs/opengl/configure.ac b/plugins/gs/zerogs/opengl/configure.ac new file mode 100644 index 0000000..6fa9b6a --- /dev/null +++ b/plugins/gs/zerogs/opengl/configure.ac @@ -0,0 +1,148 @@ +AC_INIT(ZeroGSogl,0.96.2,zerofrog@gmail.com) + +AM_INIT_AUTOMAKE(ZeroGSogl,0.96.2) + +AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) + +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl necessary for compiling assembly +AM_PROG_AS + +ZEROGS_CURRENT=0 +ZEROGS_REVISION=96 +ZEROGS_AGE=2 +ZEROGS_SONAME=libZeroGSogl.so.[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] +ZEROGS_RELEASE=[$ZEROGS_CURRENT].[$ZEROGS_REVISION].[$ZEROGS_AGE] + +AC_SUBST(ZEROGS_CURRENT) +AC_SUBST(ZEROGS_REVISION) +AC_SUBST(ZEROGS_AGE) +AC_SUBST(ZEROGS_RELEASE) +AC_SUBST(ZEROGS_SONAME) + +CFLAGS=" -I/opt/cg/include -L/opt/cg/lib " +CPPFLAGS=" -I/opt/cg/include -L/opt/cg/lib " +CXXFLAGS=" -I/opt/cg/include -L/opt/cg/lib " + +dnl Check for debug build +AC_MSG_CHECKING(debug build) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), + debug=$enableval,debug=no) +if test "x$debug" == xyes +then + AC_DEFINE(_DEBUG,1,[_DEBUG]) + CFLAGS+="-g " + CPPFLAGS+="-g " + CXXFLAGS+="-g " +else + AC_DEFINE(NDEBUG,1,[NDEBUG]) + CFLAGS+="-O2 -fomit-frame-pointer " + CPPFLAGS+="-O2 -fomit-frame-pointer " + CXXFLAGS+="-O2 -fomit-frame-pointer " +fi +AC_MSG_RESULT($debug) + +AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) + +dnl Check for dev build +AC_MSG_CHECKING(for development build...) +AC_ARG_ENABLE(devbuild, AC_HELP_STRING([--enable-devbuild], [Special Build for developers that simplifies testing and adds extra checks]), + devbuild=$enableval,devbuild=no) +if test "x$devbuild" == xno +then + AC_DEFINE(RELEASE_TO_PUBLIC,1,[RELEASE_TO_PUBLIC]) +fi +AC_MSG_RESULT($devbuild) +AM_CONDITIONAL(RELEASE_TO_PUBLIC, test x$devbuild = xno) + +dnl Check for recompilation +AC_MSG_CHECKING(check for sse2...) +AC_ARG_ENABLE(sse2, AC_HELP_STRING([--enable-sse2], [Enable sse2 instructions]), + sse2=$enableval,sse2=no) +if test "x$sse2" == xyes +then + AC_DEFINE(ZEROGS_SSE2,1,[ZEROGS_SSE2]) +fi +AC_MSG_RESULT($sse2) +AM_CONDITIONAL(SSE2, test x$sse2 = xyes) + +dnl Check for 64bit CPU +AC_MSG_CHECKING(for a x86-64 CPU) +dnl if test "$build_os" == "target_os" +dnl then +AC_TRY_RUN([ +int main() +{ +int a = 0; +int*pa = &a; +asm(".intel_syntax\n" + "mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + ".att_syntax\n" + : : "r"(pa) : "%rax"); +return 0; +} +],cpu64=yes,cpu64=no,) +dnl else +dnl cpu64=no +dnl fi +if test "x$cpu64" == xyes +then +AC_DEFINE(__x86_64__,1,[__x86_64__]) +fi +AC_MSG_RESULT($cpu64) +AM_CONDITIONAL(X86_64, test x$cpu64 = xyes) + +dnl gtk +AC_MSG_CHECKING(gtk2+) +AC_CHECK_PROG(GTK_CONFIG, pkg-config, pkg-config) +LIBS+=$(pkg-config --libs gtk+-2.0) + +dnl bindir = pcsx2exe + +dnl assuming linux environment +so_ext=".so.$ZEROGS_RELEASE" +SHARED_LDFLAGS="-shared" +AC_SUBST(so_ext) +AC_SUBST(SHARED_LDFLAGS) + +AC_MSG_CHECKING(OpenGL) +AC_CHECK_HEADERS([GL/gl.h GL/glu.h GL/glext.h],,, + [[#if HAVE_GL_GL_H + #include + #endif + #if HAVE_GL_GLU_H + #include + #endif + ]]) +AC_CHECK_LIB(GL,main,[LIBS="$LIBS -lGL"]) +AC_CHECK_LIB(GLU,main,[LIBS="$LIBS -lGLU"]) +AC_MSG_CHECKING(Cg) +#AC_CHECK_HEADERS([Cg/cg.h Cg/cgGL.h]) + +AC_CHECK_LIB(jpeg,main,[LIBS="$LIBS -ljpeg"]) +AC_CHECK_LIB(pthread,main,[LIBS="$LIBS -lpthread"]) +AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"]) +AC_CHECK_LIB(z,main,[LIBS="$LIBS -lz"]) +AC_CHECK_LIB(dl,main,[LIBS="$LIBS -ldl"]) +AC_CHECK_LIB(Xxf86vm,main,[LIBS="$LIBS -lXxf86vm"]) + +dnl AC_CHECK_LIB(Cg,cgCreateContext,[LIBS="$LIBS -lCg"]) +dnl AC_CHECK_LIB(CgGL,cgGLEnableProfile,[LIBS="$LIBS -lCgGL"]) +LIBS+=" -lCg -lCgGL" + +AC_OUTPUT([ + Makefile + Linux/Makefile + ]) + +echo "Configuration:" +echo " Target system type: $target" +echo " x86-64 build? $cpu64" +echo " Debug build? $debug" +echo " Dev build? $devbuild" +echo " SSE2 enabled? $sse2" diff --git a/plugins/gs/zerogs/opengl/depcomp b/plugins/gs/zerogs/opengl/depcomp new file mode 100644 index 0000000..88b3a13 --- /dev/null +++ b/plugins/gs/zerogs/opengl/depcomp @@ -0,0 +1,529 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/gs/zerogs/opengl/glprocs.c b/plugins/gs/zerogs/opengl/glprocs.c new file mode 100644 index 0000000..da82208 --- /dev/null +++ b/plugins/gs/zerogs/opengl/glprocs.c @@ -0,0 +1,17864 @@ +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** Version: 1.1 +** +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#include +#include + +#ifdef _WIN32 + #include + #include //"gl.h" /* Include local "gl.h". Don't include vc32 . */ + #include "glprocs.h" +#else /* GLX */ + #include + #include + #include +#include "glprocs.h"// +// #define wglGetProcAddress glXGetProcAddress +inline void* wglGetProcAddress(const char* x) { + return (void*)glXGetProcAddress((const GLubyte*)x); +} + +#endif + +#define _ASSERT(a) assert(a) + +static void APIENTRY InitBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColor"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColor = extproc; + + glBlendColor(red, green, blue, alpha); +} + +static void APIENTRY InitBlendEquation (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquation"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquation = extproc; + + glBlendEquation(mode); +} + +static void APIENTRY InitDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElements = extproc; + + glDrawRangeElements(mode, start, end, count, type, indices); +} + +static void APIENTRY InitColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTable = extproc; + + glColorTable(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfv = extproc; + + glColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitColorTableParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameteriv = extproc; + + glColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTable = extproc; + + glCopyColorTable(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTable = extproc; + + glGetColorTable(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfv = extproc; + + glGetColorTableParameterfv(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameteriv = extproc; + + glGetColorTableParameteriv(target, pname, params); +} + +static void APIENTRY InitColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTable = extproc; + + glColorSubTable(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTable"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTable = extproc; + + glCopyColorSubTable(target, start, x, y, width); +} + +static void APIENTRY InitConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1D = extproc; + + glConvolutionFilter1D(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2D = extproc; + + glConvolutionFilter2D(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterf (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterf = extproc; + + glConvolutionParameterf(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfv = extproc; + + glConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteri (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteri = extproc; + + glConvolutionParameteri(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriv = extproc; + + glConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1D = extproc; + + glCopyConvolutionFilter1D(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2D = extproc; + + glCopyConvolutionFilter2D(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilter = extproc; + + glGetConvolutionFilter(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfv = extproc; + + glGetConvolutionParameterfv(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameteriv = extproc; + + glGetConvolutionParameteriv(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilter"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilter = extproc; + + glGetSeparableFilter(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2D = extproc; + + glSeparableFilter2D(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogram = extproc; + + glGetHistogram(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfv = extproc; + + glGetHistogramParameterfv(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameteriv = extproc; + + glGetHistogramParameteriv(target, pname, params); +} + +static void APIENTRY InitGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmax = extproc; + + glGetMinmax(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfv = extproc; + + glGetMinmaxParameterfv(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameteriv = extproc; + + glGetMinmaxParameteriv(target, pname, params); +} + +static void APIENTRY InitHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogram = extproc; + + glHistogram(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmax (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmax = extproc; + + glMinmax(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogram (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogram"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogram = extproc; + + glResetHistogram(target); +} + +static void APIENTRY InitResetMinmax (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmax"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmax = extproc; + + glResetMinmax(target); +} + +static void APIENTRY InitTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3D = extproc; + + glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3D = extproc; + + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3D = extproc; + + glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTexture = extproc; + + glActiveTexture(texture); +} + +static void APIENTRY InitClientActiveTexture (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTexture"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTexture = extproc; + + glClientActiveTexture(texture); +} + +static void APIENTRY InitMultiTexCoord1d (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1d = extproc; + + glMultiTexCoord1d(target, s); +} + +static void APIENTRY InitMultiTexCoord1dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dv = extproc; + + glMultiTexCoord1dv(target, v); +} + +static void APIENTRY InitMultiTexCoord1f (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1f = extproc; + + glMultiTexCoord1f(target, s); +} + +static void APIENTRY InitMultiTexCoord1fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fv = extproc; + + glMultiTexCoord1fv(target, v); +} + +static void APIENTRY InitMultiTexCoord1i (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1i = extproc; + + glMultiTexCoord1i(target, s); +} + +static void APIENTRY InitMultiTexCoord1iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iv = extproc; + + glMultiTexCoord1iv(target, v); +} + +static void APIENTRY InitMultiTexCoord1s (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1s = extproc; + + glMultiTexCoord1s(target, s); +} + +static void APIENTRY InitMultiTexCoord1sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sv = extproc; + + glMultiTexCoord1sv(target, v); +} + +static void APIENTRY InitMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2d = extproc; + + glMultiTexCoord2d(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dv = extproc; + + glMultiTexCoord2dv(target, v); +} + +static void APIENTRY InitMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2f = extproc; + + glMultiTexCoord2f(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fv = extproc; + + glMultiTexCoord2fv(target, v); +} + +static void APIENTRY InitMultiTexCoord2i (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2i = extproc; + + glMultiTexCoord2i(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iv = extproc; + + glMultiTexCoord2iv(target, v); +} + +static void APIENTRY InitMultiTexCoord2s (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2s = extproc; + + glMultiTexCoord2s(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sv = extproc; + + glMultiTexCoord2sv(target, v); +} + +static void APIENTRY InitMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3d = extproc; + + glMultiTexCoord3d(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dv = extproc; + + glMultiTexCoord3dv(target, v); +} + +static void APIENTRY InitMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3f = extproc; + + glMultiTexCoord3f(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fv = extproc; + + glMultiTexCoord3fv(target, v); +} + +static void APIENTRY InitMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3i = extproc; + + glMultiTexCoord3i(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iv = extproc; + + glMultiTexCoord3iv(target, v); +} + +static void APIENTRY InitMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3s = extproc; + + glMultiTexCoord3s(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sv = extproc; + + glMultiTexCoord3sv(target, v); +} + +static void APIENTRY InitMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4d = extproc; + + glMultiTexCoord4d(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dv (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dv = extproc; + + glMultiTexCoord4dv(target, v); +} + +static void APIENTRY InitMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4f = extproc; + + glMultiTexCoord4f(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fv (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fv = extproc; + + glMultiTexCoord4fv(target, v); +} + +static void APIENTRY InitMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4i = extproc; + + glMultiTexCoord4i(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4iv (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iv = extproc; + + glMultiTexCoord4iv(target, v); +} + +static void APIENTRY InitMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4s = extproc; + + glMultiTexCoord4s(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4sv (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sv = extproc; + + glMultiTexCoord4sv(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixf = extproc; + + glLoadTransposeMatrixf(m); +} + +static void APIENTRY InitLoadTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixd = extproc; + + glLoadTransposeMatrixd(m); +} + +static void APIENTRY InitMultTransposeMatrixf (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixf = extproc; + + glMultTransposeMatrixf(m); +} + +static void APIENTRY InitMultTransposeMatrixd (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixd = extproc; + + glMultTransposeMatrixd(m); +} + +static void APIENTRY InitSampleCoverage (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverage = extproc; + + glSampleCoverage(value, invert); +} + +static void APIENTRY InitCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3D = extproc; + + glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2D = extproc; + + glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1D = extproc; + + glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3D = extproc; + + glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2D = extproc; + + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1D"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1D = extproc; + + glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImage (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImage"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImage = extproc; + + glGetCompressedTexImage(target, level, img); +} + +static void APIENTRY InitBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparate"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparate = extproc; + + glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitFogCoordf (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordf = extproc; + + glFogCoordf(coord); +} + +static void APIENTRY InitFogCoordfv (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfv = extproc; + + glFogCoordfv(coord); +} + +static void APIENTRY InitFogCoordd (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordd"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordd = extproc; + + glFogCoordd(coord); +} + +static void APIENTRY InitFogCoorddv (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddv = extproc; + + glFogCoorddv(coord); +} + +static void APIENTRY InitFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointer = extproc; + + glFogCoordPointer(type, stride, pointer); +} + +static void APIENTRY InitMultiDrawArrays (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArrays"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArrays = extproc; + + glMultiDrawArrays(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElements"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElements = extproc; + + glMultiDrawElements(mode, count, type, indices, primcount); +} + +static void APIENTRY InitPointParameterf (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterf"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterf = extproc; + + glPointParameterf(pname, param); +} + +static void APIENTRY InitPointParameterfv (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfv = extproc; + + glPointParameterfv(pname, params); +} + +static void APIENTRY InitPointParameteri (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteri"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteri = extproc; + + glPointParameteri(pname, param); +} + +static void APIENTRY InitPointParameteriv (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriv = extproc; + + glPointParameteriv(pname, params); +} + +static void APIENTRY InitSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3b"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3b = extproc; + + glSecondaryColor3b(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bv (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bv = extproc; + + glSecondaryColor3bv(v); +} + +static void APIENTRY InitSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3d = extproc; + + glSecondaryColor3d(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dv = extproc; + + glSecondaryColor3dv(v); +} + +static void APIENTRY InitSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3f = extproc; + + glSecondaryColor3f(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fv = extproc; + + glSecondaryColor3fv(v); +} + +static void APIENTRY InitSecondaryColor3i (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3i = extproc; + + glSecondaryColor3i(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iv = extproc; + + glSecondaryColor3iv(v); +} + +static void APIENTRY InitSecondaryColor3s (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3s = extproc; + + glSecondaryColor3s(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sv = extproc; + + glSecondaryColor3sv(v); +} + +static void APIENTRY InitSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ub"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ub = extproc; + + glSecondaryColor3ub(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubv (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubv = extproc; + + glSecondaryColor3ubv(v); +} + +static void APIENTRY InitSecondaryColor3ui (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ui"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ui = extproc; + + glSecondaryColor3ui(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uiv (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiv = extproc; + + glSecondaryColor3uiv(v); +} + +static void APIENTRY InitSecondaryColor3us (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3us"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3us = extproc; + + glSecondaryColor3us(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usv (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usv = extproc; + + glSecondaryColor3usv(v); +} + +static void APIENTRY InitSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointer = extproc; + + glSecondaryColorPointer(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2d (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2d = extproc; + + glWindowPos2d(x, y); +} + +static void APIENTRY InitWindowPos2dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dv = extproc; + + glWindowPos2dv(v); +} + +static void APIENTRY InitWindowPos2f (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2f = extproc; + + glWindowPos2f(x, y); +} + +static void APIENTRY InitWindowPos2fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fv = extproc; + + glWindowPos2fv(v); +} + +static void APIENTRY InitWindowPos2i (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2i = extproc; + + glWindowPos2i(x, y); +} + +static void APIENTRY InitWindowPos2iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iv = extproc; + + glWindowPos2iv(v); +} + +static void APIENTRY InitWindowPos2s (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2s = extproc; + + glWindowPos2s(x, y); +} + +static void APIENTRY InitWindowPos2sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sv = extproc; + + glWindowPos2sv(v); +} + +static void APIENTRY InitWindowPos3d (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3d"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3d = extproc; + + glWindowPos3d(x, y, z); +} + +static void APIENTRY InitWindowPos3dv (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dv = extproc; + + glWindowPos3dv(v); +} + +static void APIENTRY InitWindowPos3f (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3f"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3f = extproc; + + glWindowPos3f(x, y, z); +} + +static void APIENTRY InitWindowPos3fv (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fv = extproc; + + glWindowPos3fv(v); +} + +static void APIENTRY InitWindowPos3i (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3i"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3i = extproc; + + glWindowPos3i(x, y, z); +} + +static void APIENTRY InitWindowPos3iv (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iv = extproc; + + glWindowPos3iv(v); +} + +static void APIENTRY InitWindowPos3s (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3s"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3s = extproc; + + glWindowPos3s(x, y, z); +} + +static void APIENTRY InitWindowPos3sv (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sv = extproc; + + glWindowPos3sv(v); +} + +static void APIENTRY InitGenQueries (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueries = extproc; + + glGenQueries(n, ids); +} + +static void APIENTRY InitDeleteQueries (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueries"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueries = extproc; + + glDeleteQueries(n, ids); +} + +static GLboolean APIENTRY InitIsQuery (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQuery = extproc; + + return glIsQuery(id); +} + +static void APIENTRY InitBeginQuery (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQuery = extproc; + + glBeginQuery(target, id); +} + +static void APIENTRY InitEndQuery (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQuery"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQuery = extproc; + + glEndQuery(target); +} + +static void APIENTRY InitGetQueryiv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryiv = extproc; + + glGetQueryiv(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectiv (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectiv = extproc; + + glGetQueryObjectiv(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuiv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuiv = extproc; + + glGetQueryObjectuiv(id, pname, params); +} + +static void APIENTRY InitBindBuffer (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBuffer = extproc; + + glBindBuffer(target, buffer); +} + +static void APIENTRY InitDeleteBuffers (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffers = extproc; + + glDeleteBuffers(n, buffers); +} + +static void APIENTRY InitGenBuffers (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffers"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffers = extproc; + + glGenBuffers(n, buffers); +} + +static GLboolean APIENTRY InitIsBuffer (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBuffer = extproc; + + return glIsBuffer(buffer); +} + +static void APIENTRY InitBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferData = extproc; + + glBufferData(target, size, data, usage); +} + +static void APIENTRY InitBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubData = extproc; + + glBufferSubData(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubData"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubData = extproc; + + glGetBufferSubData(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBuffer (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBuffer = extproc; + + return glMapBuffer(target, access); +} + +static GLboolean APIENTRY InitUnmapBuffer (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBuffer"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBuffer = extproc; + + return glUnmapBuffer(target); +} + +static void APIENTRY InitGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameteriv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameteriv = extproc; + + glGetBufferParameteriv(target, pname, params); +} + +static void APIENTRY InitGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointerv"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointerv = extproc; + + glGetBufferPointerv(target, pname, params); +} + +static void APIENTRY InitActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveTextureARB = extproc; + + glActiveTextureARB(texture); +} + +static void APIENTRY InitClientActiveTextureARB (GLenum texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveTextureARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveTextureARB = extproc; + + glClientActiveTextureARB(texture); +} + +static void APIENTRY InitMultiTexCoord1dARB (GLenum target, GLdouble s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dARB = extproc; + + glMultiTexCoord1dARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1dvARB = extproc; + + glMultiTexCoord1dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1fARB (GLenum target, GLfloat s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fARB = extproc; + + glMultiTexCoord1fARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1fvARB = extproc; + + glMultiTexCoord1fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1iARB (GLenum target, GLint s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1iARB = extproc; + + glMultiTexCoord1iARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1ivARB = extproc; + + glMultiTexCoord1ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord1sARB (GLenum target, GLshort s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1sARB = extproc; + + glMultiTexCoord1sARB(target, s); +} + +static void APIENTRY InitMultiTexCoord1svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1svARB = extproc; + + glMultiTexCoord1svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dARB = extproc; + + glMultiTexCoord2dARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2dvARB = extproc; + + glMultiTexCoord2dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fARB = extproc; + + glMultiTexCoord2fARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2fvARB = extproc; + + glMultiTexCoord2fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2iARB (GLenum target, GLint s, GLint t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2iARB = extproc; + + glMultiTexCoord2iARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2ivARB = extproc; + + glMultiTexCoord2ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2sARB = extproc; + + glMultiTexCoord2sARB(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2svARB = extproc; + + glMultiTexCoord2svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dARB = extproc; + + glMultiTexCoord3dARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3dvARB = extproc; + + glMultiTexCoord3dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fARB = extproc; + + glMultiTexCoord3fARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3fvARB = extproc; + + glMultiTexCoord3fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3iARB = extproc; + + glMultiTexCoord3iARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3ivARB = extproc; + + glMultiTexCoord3ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3sARB = extproc; + + glMultiTexCoord3sARB(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3svARB = extproc; + + glMultiTexCoord3svARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dARB = extproc; + + glMultiTexCoord4dARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4dvARB (GLenum target, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4dvARB = extproc; + + glMultiTexCoord4dvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fARB = extproc; + + glMultiTexCoord4fARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4fvARB (GLenum target, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4fvARB = extproc; + + glMultiTexCoord4fvARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4iARB = extproc; + + glMultiTexCoord4iARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4ivARB (GLenum target, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4ivARB = extproc; + + glMultiTexCoord4ivARB(target, v); +} + +static void APIENTRY InitMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4sARB = extproc; + + glMultiTexCoord4sARB(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4svARB (GLenum target, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4svARB = extproc; + + glMultiTexCoord4svARB(target, v); +} + +static void APIENTRY InitLoadTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixfARB = extproc; + + glLoadTransposeMatrixfARB(m); +} + +static void APIENTRY InitLoadTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadTransposeMatrixdARB = extproc; + + glLoadTransposeMatrixdARB(m); +} + +static void APIENTRY InitMultTransposeMatrixfARB (const GLfloat *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixfARB = extproc; + + glMultTransposeMatrixfARB(m); +} + +static void APIENTRY InitMultTransposeMatrixdARB (const GLdouble *m) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultTransposeMatrixdARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultTransposeMatrixdARB = extproc; + + glMultTransposeMatrixdARB(m); +} + +static void APIENTRY InitSampleCoverageARB (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleCoverageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleCoverageARB = extproc; + + glSampleCoverageARB(value, invert); +} + +static void APIENTRY InitCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage3DARB = extproc; + + glCompressedTexImage3DARB(target, level, internalformat, width, height, depth, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage2DARB = extproc; + + glCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexImage1DARB = extproc; + + glCompressedTexImage1DARB(target, level, internalformat, width, border, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage3DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage3DARB = extproc; + + glCompressedTexSubImage3DARB(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage2DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage2DARB = extproc; + + glCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void APIENTRY InitCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompressedTexSubImage1DARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompressedTexSubImage1DARB = extproc; + + glCompressedTexSubImage1DARB(target, level, xoffset, width, format, imageSize, data); +} + +static void APIENTRY InitGetCompressedTexImageARB (GLenum target, GLint level, GLvoid *img) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCompressedTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCompressedTexImageARB = extproc; + + glGetCompressedTexImageARB(target, level, img); +} + +static void APIENTRY InitPointParameterfARB (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfARB = extproc; + + glPointParameterfARB(pname, param); +} + +static void APIENTRY InitPointParameterfvARB (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvARB = extproc; + + glPointParameterfvARB(pname, params); +} + +static void APIENTRY InitWeightbvARB (GLint size, const GLbyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightbvARB = extproc; + + glWeightbvARB(size, weights); +} + +static void APIENTRY InitWeightsvARB (GLint size, const GLshort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightsvARB = extproc; + + glWeightsvARB(size, weights); +} + +static void APIENTRY InitWeightivARB (GLint size, const GLint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightivARB = extproc; + + glWeightivARB(size, weights); +} + +static void APIENTRY InitWeightfvARB (GLint size, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightfvARB = extproc; + + glWeightfvARB(size, weights); +} + +static void APIENTRY InitWeightdvARB (GLint size, const GLdouble *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightdvARB = extproc; + + glWeightdvARB(size, weights); +} + +static void APIENTRY InitWeightubvARB (GLint size, const GLubyte *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightubvARB = extproc; + + glWeightubvARB(size, weights); +} + +static void APIENTRY InitWeightusvARB (GLint size, const GLushort *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightusvARB = extproc; + + glWeightusvARB(size, weights); +} + +static void APIENTRY InitWeightuivARB (GLint size, const GLuint *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightuivARB = extproc; + + glWeightuivARB(size, weights); +} + +static void APIENTRY InitWeightPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWeightPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWeightPointerARB = extproc; + + glWeightPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitVertexBlendARB (GLint count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendARB = extproc; + + glVertexBlendARB(count); +} + +static void APIENTRY InitCurrentPaletteMatrixARB (GLint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCurrentPaletteMatrixARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCurrentPaletteMatrixARB = extproc; + + glCurrentPaletteMatrixARB(index); +} + +static void APIENTRY InitMatrixIndexubvARB (GLint size, const GLubyte *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexubvARB = extproc; + + glMatrixIndexubvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexusvARB (GLint size, const GLushort *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexusvARB = extproc; + + glMatrixIndexusvARB(size, indices); +} + +static void APIENTRY InitMatrixIndexuivARB (GLint size, const GLuint *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexuivARB = extproc; + + glMatrixIndexuivARB(size, indices); +} + +static void APIENTRY InitMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMatrixIndexPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMatrixIndexPointerARB = extproc; + + glMatrixIndexPointerARB(size, type, stride, pointer); +} + +static void APIENTRY InitWindowPos2dARB (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dARB = extproc; + + glWindowPos2dARB(x, y); +} + +static void APIENTRY InitWindowPos2dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvARB = extproc; + + glWindowPos2dvARB(v); +} + +static void APIENTRY InitWindowPos2fARB (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fARB = extproc; + + glWindowPos2fARB(x, y); +} + +static void APIENTRY InitWindowPos2fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvARB = extproc; + + glWindowPos2fvARB(v); +} + +static void APIENTRY InitWindowPos2iARB (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iARB = extproc; + + glWindowPos2iARB(x, y); +} + +static void APIENTRY InitWindowPos2ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivARB = extproc; + + glWindowPos2ivARB(v); +} + +static void APIENTRY InitWindowPos2sARB (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sARB = extproc; + + glWindowPos2sARB(x, y); +} + +static void APIENTRY InitWindowPos2svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svARB = extproc; + + glWindowPos2svARB(v); +} + +static void APIENTRY InitWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dARB = extproc; + + glWindowPos3dARB(x, y, z); +} + +static void APIENTRY InitWindowPos3dvARB (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvARB = extproc; + + glWindowPos3dvARB(v); +} + +static void APIENTRY InitWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fARB = extproc; + + glWindowPos3fARB(x, y, z); +} + +static void APIENTRY InitWindowPos3fvARB (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvARB = extproc; + + glWindowPos3fvARB(v); +} + +static void APIENTRY InitWindowPos3iARB (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iARB = extproc; + + glWindowPos3iARB(x, y, z); +} + +static void APIENTRY InitWindowPos3ivARB (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivARB = extproc; + + glWindowPos3ivARB(v); +} + +static void APIENTRY InitWindowPos3sARB (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sARB = extproc; + + glWindowPos3sARB(x, y, z); +} + +static void APIENTRY InitWindowPos3svARB (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svARB = extproc; + + glWindowPos3svARB(v); +} + +static void APIENTRY InitVertexAttrib1dARB (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dARB = extproc; + + glVertexAttrib1dARB(index, x); +} + +static void APIENTRY InitVertexAttrib1dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvARB = extproc; + + glVertexAttrib1dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1fARB (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fARB = extproc; + + glVertexAttrib1fARB(index, x); +} + +static void APIENTRY InitVertexAttrib1fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvARB = extproc; + + glVertexAttrib1fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib1sARB (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sARB = extproc; + + glVertexAttrib1sARB(index, x); +} + +static void APIENTRY InitVertexAttrib1svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svARB = extproc; + + glVertexAttrib1svARB(index, v); +} + +static void APIENTRY InitVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dARB = extproc; + + glVertexAttrib2dARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvARB = extproc; + + glVertexAttrib2dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fARB = extproc; + + glVertexAttrib2fARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvARB = extproc; + + glVertexAttrib2fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib2sARB (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sARB = extproc; + + glVertexAttrib2sARB(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svARB = extproc; + + glVertexAttrib2svARB(index, v); +} + +static void APIENTRY InitVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dARB = extproc; + + glVertexAttrib3dARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvARB = extproc; + + glVertexAttrib3dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fARB = extproc; + + glVertexAttrib3fARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvARB = extproc; + + glVertexAttrib3fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sARB = extproc; + + glVertexAttrib3sARB(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svARB = extproc; + + glVertexAttrib3svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NbvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NbvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NbvARB = extproc; + + glVertexAttrib4NbvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NivARB = extproc; + + glVertexAttrib4NivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NsvARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NsvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NsvARB = extproc; + + glVertexAttrib4NsvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubARB = extproc; + + glVertexAttrib4NubARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4NubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NubvARB = extproc; + + glVertexAttrib4NubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NuivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NuivARB = extproc; + + glVertexAttrib4NuivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4NusvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4NusvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4NusvARB = extproc; + + glVertexAttrib4NusvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4bvARB (GLuint index, const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4bvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4bvARB = extproc; + + glVertexAttrib4bvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dARB = extproc; + + glVertexAttrib4dARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvARB (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvARB = extproc; + + glVertexAttrib4dvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fARB = extproc; + + glVertexAttrib4fARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvARB (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvARB = extproc; + + glVertexAttrib4fvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ivARB (GLuint index, const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ivARB = extproc; + + glVertexAttrib4ivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sARB = extproc; + + glVertexAttrib4sARB(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svARB (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svARB = extproc; + + glVertexAttrib4svARB(index, v); +} + +static void APIENTRY InitVertexAttrib4ubvARB (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvARB = extproc; + + glVertexAttrib4ubvARB(index, v); +} + +static void APIENTRY InitVertexAttrib4uivARB (GLuint index, const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4uivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4uivARB = extproc; + + glVertexAttrib4uivARB(index, v); +} + +static void APIENTRY InitVertexAttrib4usvARB (GLuint index, const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4usvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4usvARB = extproc; + + glVertexAttrib4usvARB(index, v); +} + +static void APIENTRY InitVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerARB = extproc; + + glVertexAttribPointerARB(index, size, type, normalized, stride, pointer); +} + +static void APIENTRY InitEnableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVertexAttribArrayARB = extproc; + + glEnableVertexAttribArrayARB(index); +} + +static void APIENTRY InitDisableVertexAttribArrayARB (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVertexAttribArrayARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVertexAttribArrayARB = extproc; + + glDisableVertexAttribArrayARB(index); +} + +static void APIENTRY InitProgramStringARB (GLenum target, GLenum format, GLsizei len, const GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramStringARB = extproc; + + glProgramStringARB(target, format, len, string); +} + +static void APIENTRY InitBindProgramARB (GLenum target, GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramARB = extproc; + + glBindProgramARB(target, program); +} + +static void APIENTRY InitDeleteProgramsARB (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsARB = extproc; + + glDeleteProgramsARB(n, programs); +} + +static void APIENTRY InitGenProgramsARB (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsARB = extproc; + + glGenProgramsARB(n, programs); +} + +static void APIENTRY InitProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dARB = extproc; + + glProgramEnvParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4dvARB = extproc; + + glProgramEnvParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fARB = extproc; + + glProgramEnvParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramEnvParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramEnvParameter4fvARB = extproc; + + glProgramEnvParameter4fvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dARB = extproc; + + glProgramLocalParameter4dARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4dvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4dvARB = extproc; + + glProgramLocalParameter4dvARB(target, index, params); +} + +static void APIENTRY InitProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fARB = extproc; + + glProgramLocalParameter4fARB(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramLocalParameter4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramLocalParameter4fvARB = extproc; + + glProgramLocalParameter4fvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterdvARB = extproc; + + glGetProgramEnvParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramEnvParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramEnvParameterfvARB = extproc; + + glGetProgramEnvParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterdvARB = extproc; + + glGetProgramLocalParameterdvARB(target, index, params); +} + +static void APIENTRY InitGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramLocalParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramLocalParameterfvARB = extproc; + + glGetProgramLocalParameterfvARB(target, index, params); +} + +static void APIENTRY InitGetProgramivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivARB = extproc; + + glGetProgramivARB(target, pname, params); +} + +static void APIENTRY InitGetProgramStringARB (GLenum target, GLenum pname, GLvoid *string) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringARB = extproc; + + glGetProgramStringARB(target, pname, string); +} + +static void APIENTRY InitGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvARB = extproc; + + glGetVertexAttribdvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvARB = extproc; + + glGetVertexAttribfvARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivARB = extproc; + + glGetVertexAttribivARB(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervARB (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervARB = extproc; + + glGetVertexAttribPointervARB(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramARB (GLuint program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramARB = extproc; + + return glIsProgramARB(program); +} + +static void APIENTRY InitBindBufferARB (GLenum target, GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindBufferARB = extproc; + + glBindBufferARB(target, buffer); +} + +static void APIENTRY InitDeleteBuffersARB (GLsizei n, const GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteBuffersARB = extproc; + + glDeleteBuffersARB(n, buffers); +} + +static void APIENTRY InitGenBuffersARB (GLsizei n, GLuint *buffers) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenBuffersARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenBuffersARB = extproc; + + glGenBuffersARB(n, buffers); +} + +static GLboolean APIENTRY InitIsBufferARB (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsBufferARB = extproc; + + return glIsBufferARB(buffer); +} + +static void APIENTRY InitBufferDataARB (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferDataARB = extproc; + + glBufferDataARB(target, size, data, usage); +} + +static void APIENTRY InitBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBufferSubDataARB = extproc; + + glBufferSubDataARB(target, offset, size, data); +} + +static void APIENTRY InitGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferSubDataARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferSubDataARB = extproc; + + glGetBufferSubDataARB(target, offset, size, data); +} + +static GLvoid* APIENTRY InitMapBufferARB (GLenum target, GLenum access) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapBufferARB = extproc; + + return glMapBufferARB(target, access); +} + +static GLboolean APIENTRY InitUnmapBufferARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapBufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glUnmapBufferARB = extproc; + + return glUnmapBufferARB(target); +} + +static void APIENTRY InitGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferParameterivARB = extproc; + + glGetBufferParameterivARB(target, pname, params); +} + +static void APIENTRY InitGetBufferPointervARB (GLenum target, GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetBufferPointervARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetBufferPointervARB = extproc; + + glGetBufferPointervARB(target, pname, params); +} + +static void APIENTRY InitGenQueriesARB (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenQueriesARB = extproc; + + glGenQueriesARB(n, ids); +} + +static void APIENTRY InitDeleteQueriesARB (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteQueriesARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteQueriesARB = extproc; + + glDeleteQueriesARB(n, ids); +} + +static GLboolean APIENTRY InitIsQueryARB (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsQueryARB = extproc; + + return glIsQueryARB(id); +} + +static void APIENTRY InitBeginQueryARB (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginQueryARB = extproc; + + glBeginQueryARB(target, id); +} + +static void APIENTRY InitEndQueryARB (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndQueryARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndQueryARB = extproc; + + glEndQueryARB(target); +} + +static void APIENTRY InitGetQueryivARB (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryivARB = extproc; + + glGetQueryivARB(target, pname, params); +} + +static void APIENTRY InitGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectivARB = extproc; + + glGetQueryObjectivARB(id, pname, params); +} + +static void APIENTRY InitGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetQueryObjectuivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetQueryObjectuivARB = extproc; + + glGetQueryObjectuivARB(id, pname, params); +} + +static void APIENTRY InitDeleteObjectARB (GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteObjectARB = extproc; + + glDeleteObjectARB(obj); +} + +static GLhandleARB APIENTRY InitGetHandleARB (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHandleARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetHandleARB = extproc; + + return glGetHandleARB(pname); +} + +static void APIENTRY InitDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetachObjectARB = extproc; + + glDetachObjectARB(containerObj, attachedObj); +} + +static GLhandleARB APIENTRY InitCreateShaderObjectARB (GLenum shaderType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateShaderObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateShaderObjectARB = extproc; + + return glCreateShaderObjectARB(shaderType); +} + +static void APIENTRY InitShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderSourceARB = extproc; + + glShaderSourceARB(shaderObj, count, string, length); +} + +static void APIENTRY InitCompileShaderARB (GLhandleARB shaderObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCompileShaderARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCompileShaderARB = extproc; + + glCompileShaderARB(shaderObj); +} + +static GLhandleARB APIENTRY InitCreateProgramObjectARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCreateProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glCreateProgramObjectARB = extproc; + + return glCreateProgramObjectARB(); +} + +static void APIENTRY InitAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAttachObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAttachObjectARB = extproc; + + glAttachObjectARB(containerObj, obj); +} + +static void APIENTRY InitLinkProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLinkProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLinkProgramARB = extproc; + + glLinkProgramARB(programObj); +} + +static void APIENTRY InitUseProgramObjectARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUseProgramObjectARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUseProgramObjectARB = extproc; + + glUseProgramObjectARB(programObj); +} + +static void APIENTRY InitValidateProgramARB (GLhandleARB programObj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glValidateProgramARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glValidateProgramARB = extproc; + + glValidateProgramARB(programObj); +} + +static void APIENTRY InitUniform1fARB (GLint location, GLfloat v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fARB = extproc; + + glUniform1fARB(location, v0); +} + +static void APIENTRY InitUniform2fARB (GLint location, GLfloat v0, GLfloat v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fARB = extproc; + + glUniform2fARB(location, v0, v1); +} + +static void APIENTRY InitUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fARB = extproc; + + glUniform3fARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fARB = extproc; + + glUniform4fARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1iARB (GLint location, GLint v0) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1iARB = extproc; + + glUniform1iARB(location, v0); +} + +static void APIENTRY InitUniform2iARB (GLint location, GLint v0, GLint v1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2iARB = extproc; + + glUniform2iARB(location, v0, v1); +} + +static void APIENTRY InitUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3iARB = extproc; + + glUniform3iARB(location, v0, v1, v2); +} + +static void APIENTRY InitUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4iARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4iARB = extproc; + + glUniform4iARB(location, v0, v1, v2, v3); +} + +static void APIENTRY InitUniform1fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1fvARB = extproc; + + glUniform1fvARB(location, count, value); +} + +static void APIENTRY InitUniform2fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2fvARB = extproc; + + glUniform2fvARB(location, count, value); +} + +static void APIENTRY InitUniform3fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3fvARB = extproc; + + glUniform3fvARB(location, count, value); +} + +static void APIENTRY InitUniform4fvARB (GLint location, GLsizei count, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4fvARB = extproc; + + glUniform4fvARB(location, count, value); +} + +static void APIENTRY InitUniform1ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform1ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform1ivARB = extproc; + + glUniform1ivARB(location, count, value); +} + +static void APIENTRY InitUniform2ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform2ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform2ivARB = extproc; + + glUniform2ivARB(location, count, value); +} + +static void APIENTRY InitUniform3ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform3ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform3ivARB = extproc; + + glUniform3ivARB(location, count, value); +} + +static void APIENTRY InitUniform4ivARB (GLint location, GLsizei count, const GLint *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniform4ivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniform4ivARB = extproc; + + glUniform4ivARB(location, count, value); +} + +static void APIENTRY InitUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix2fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix2fvARB = extproc; + + glUniformMatrix2fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix3fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix3fvARB = extproc; + + glUniformMatrix3fvARB(location, count, transpose, value); +} + +static void APIENTRY InitUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUniformMatrix4fvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUniformMatrix4fvARB = extproc; + + glUniformMatrix4fvARB(location, count, transpose, value); +} + +static void APIENTRY InitGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterfvARB = extproc; + + glGetObjectParameterfvARB(obj, pname, params); +} + +static void APIENTRY InitGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectParameterivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectParameterivARB = extproc; + + glGetObjectParameterivARB(obj, pname, params); +} + +static void APIENTRY InitGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInfoLogARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInfoLogARB = extproc; + + glGetInfoLogARB(obj, maxLength, length, infoLog); +} + +static void APIENTRY InitGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttachedObjectsARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetAttachedObjectsARB = extproc; + + glGetAttachedObjectsARB(containerObj, maxCount, count, obj); +} + +static GLint APIENTRY InitGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetUniformLocationARB = extproc; + + return glGetUniformLocationARB(programObj, name); +} + +static void APIENTRY InitGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveUniformARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveUniformARB = extproc; + + glGetActiveUniformARB(programObj, index, maxLength, length, size, type, name); +} + +static void APIENTRY InitGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformfvARB = extproc; + + glGetUniformfvARB(programObj, location, params); +} + +static void APIENTRY InitGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetUniformivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetUniformivARB = extproc; + + glGetUniformivARB(programObj, location, params); +} + +static void APIENTRY InitGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetShaderSourceARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetShaderSourceARB = extproc; + + glGetShaderSourceARB(obj, maxLength, length, source); +} + +static void APIENTRY InitBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindAttribLocationARB = extproc; + + glBindAttribLocationARB(programObj, index, name); +} + +static void APIENTRY InitGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetActiveAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetActiveAttribARB = extproc; + + glGetActiveAttribARB(programObj, index, maxLength, length, size, type, name); +} + +static GLint APIENTRY InitGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetAttribLocationARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetAttribLocationARB = extproc; + + return glGetAttribLocationARB(programObj, name); +} + +static void APIENTRY InitBlendColorEXT (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendColorEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendColorEXT = extproc; + + glBlendColorEXT(red, green, blue, alpha); +} + +static void APIENTRY InitPolygonOffsetEXT (GLfloat factor, GLfloat bias) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPolygonOffsetEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPolygonOffsetEXT = extproc; + + glPolygonOffsetEXT(factor, bias); +} + +static void APIENTRY InitTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage3DEXT = extproc; + + glTexImage3DEXT(target, level, internalformat, width, height, depth, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage3DEXT = extproc; + + glTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} + +static void APIENTRY InitGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexFilterFuncSGIS = extproc; + + glGetTexFilterFuncSGIS(target, filter, weights); +} + +static void APIENTRY InitTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexFilterFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexFilterFuncSGIS = extproc; + + glTexFilterFuncSGIS(target, filter, n, weights); +} + +static void APIENTRY InitTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage1DEXT = extproc; + + glTexSubImage1DEXT(target, level, xoffset, width, format, type, pixels); +} + +static void APIENTRY InitTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage2DEXT = extproc; + + glTexSubImage2DEXT(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +static void APIENTRY InitCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage1DEXT = extproc; + + glCopyTexImage1DEXT(target, level, internalformat, x, y, width, border); +} + +static void APIENTRY InitCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexImage2DEXT = extproc; + + glCopyTexImage2DEXT(target, level, internalformat, x, y, width, height, border); +} + +static void APIENTRY InitCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage1DEXT = extproc; + + glCopyTexSubImage1DEXT(target, level, xoffset, x, y, width); +} + +static void APIENTRY InitCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage2DEXT = extproc; + + glCopyTexSubImage2DEXT(target, level, xoffset, yoffset, x, y, width, height); +} + +static void APIENTRY InitCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyTexSubImage3DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyTexSubImage3DEXT = extproc; + + glCopyTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, x, y, width, height); +} + +static void APIENTRY InitGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramEXT = extproc; + + glGetHistogramEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterfvEXT = extproc; + + glGetHistogramParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetHistogramParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetHistogramParameterivEXT = extproc; + + glGetHistogramParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxEXT = extproc; + + glGetMinmaxEXT(target, reset, format, type, values); +} + +static void APIENTRY InitGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterfvEXT = extproc; + + glGetMinmaxParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMinmaxParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMinmaxParameterivEXT = extproc; + + glGetMinmaxParameterivEXT(target, pname, params); +} + +static void APIENTRY InitHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHistogramEXT = extproc; + + glHistogramEXT(target, width, internalformat, sink); +} + +static void APIENTRY InitMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMinmaxEXT = extproc; + + glMinmaxEXT(target, internalformat, sink); +} + +static void APIENTRY InitResetHistogramEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetHistogramEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetHistogramEXT = extproc; + + glResetHistogramEXT(target); +} + +static void APIENTRY InitResetMinmaxEXT (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResetMinmaxEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResetMinmaxEXT = extproc; + + glResetMinmaxEXT(target); +} + +static void APIENTRY InitConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter1DEXT = extproc; + + glConvolutionFilter1DEXT(target, internalformat, width, format, type, image); +} + +static void APIENTRY InitConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionFilter2DEXT = extproc; + + glConvolutionFilter2DEXT(target, internalformat, width, height, format, type, image); +} + +static void APIENTRY InitConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfEXT = extproc; + + glConvolutionParameterfEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterfvEXT = extproc; + + glConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameteriEXT = extproc; + + glConvolutionParameteriEXT(target, pname, params); +} + +static void APIENTRY InitConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glConvolutionParameterivEXT = extproc; + + glConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter1DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter1DEXT = extproc; + + glCopyConvolutionFilter1DEXT(target, internalformat, x, y, width); +} + +static void APIENTRY InitCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyConvolutionFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyConvolutionFilter2DEXT = extproc; + + glCopyConvolutionFilter2DEXT(target, internalformat, x, y, width, height); +} + +static void APIENTRY InitGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionFilterEXT = extproc; + + glGetConvolutionFilterEXT(target, format, type, image); +} + +static void APIENTRY InitGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterfvEXT = extproc; + + glGetConvolutionParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetConvolutionParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetConvolutionParameterivEXT = extproc; + + glGetConvolutionParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSeparableFilterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSeparableFilterEXT = extproc; + + glGetSeparableFilterEXT(target, format, type, row, column, span); +} + +static void APIENTRY InitSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSeparableFilter2DEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSeparableFilter2DEXT = extproc; + + glSeparableFilter2DEXT(target, internalformat, width, height, format, type, row, column); +} + +static void APIENTRY InitColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableSGI = extproc; + + glColorTableSGI(target, internalformat, width, format, type, table); +} + +static void APIENTRY InitColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterfvSGI = extproc; + + glColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableParameterivSGI = extproc; + + glColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorTableSGI = extproc; + + glCopyColorTableSGI(target, internalformat, x, y, width); +} + +static void APIENTRY InitGetColorTableSGI (GLenum target, GLenum format, GLenum type, GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableSGI = extproc; + + glGetColorTableSGI(target, format, type, table); +} + +static void APIENTRY InitGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvSGI = extproc; + + glGetColorTableParameterfvSGI(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivSGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivSGI = extproc; + + glGetColorTableParameterivSGI(target, pname, params); +} + +static void APIENTRY InitPixelTexGenSGIX (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenSGIX = extproc; + + glPixelTexGenSGIX(mode); +} + +static void APIENTRY InitPixelTexGenParameteriSGIS (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameteriSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameteriSGIS = extproc; + + glPixelTexGenParameteriSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterivSGIS (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterivSGIS = extproc; + + glPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitPixelTexGenParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfSGIS = extproc; + + glPixelTexGenParameterfSGIS(pname, param); +} + +static void APIENTRY InitPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTexGenParameterfvSGIS = extproc; + + glPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterivSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterivSGIS = extproc; + + glGetPixelTexGenParameterivSGIS(pname, params); +} + +static void APIENTRY InitGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPixelTexGenParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPixelTexGenParameterfvSGIS = extproc; + + glGetPixelTexGenParameterfvSGIS(pname, params); +} + +static void APIENTRY InitTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexImage4DSGIS = extproc; + + glTexImage4DSGIS(target, level, internalformat, width, height, depth, size4d, border, format, type, pixels); +} + +static void APIENTRY InitTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexSubImage4DSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexSubImage4DSGIS = extproc; + + glTexSubImage4DSGIS(target, level, xoffset, yoffset, zoffset, woffset, width, height, depth, size4d, format, type, pixels); +} + +static GLboolean APIENTRY InitAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreTexturesResidentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreTexturesResidentEXT = extproc; + + return glAreTexturesResidentEXT(n, textures, residences); +} + +static void APIENTRY InitBindTextureEXT (GLenum target, GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindTextureEXT = extproc; + + glBindTextureEXT(target, texture); +} + +static void APIENTRY InitDeleteTexturesEXT (GLsizei n, const GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteTexturesEXT = extproc; + + glDeleteTexturesEXT(n, textures); +} + +static void APIENTRY InitGenTexturesEXT (GLsizei n, GLuint *textures) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenTexturesEXT = extproc; + + glGenTexturesEXT(n, textures); +} + +static GLboolean APIENTRY InitIsTextureEXT (GLuint texture) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsTextureEXT = extproc; + + return glIsTextureEXT(texture); +} + +static void APIENTRY InitPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrioritizeTexturesEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrioritizeTexturesEXT = extproc; + + glPrioritizeTexturesEXT(n, textures, priorities); +} + +static void APIENTRY InitDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDetailTexFuncSGIS = extproc; + + glDetailTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetDetailTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetDetailTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetDetailTexFuncSGIS = extproc; + + glGetDetailTexFuncSGIS(target, points); +} + +static void APIENTRY InitSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSharpenTexFuncSGIS = extproc; + + glSharpenTexFuncSGIS(target, n, points); +} + +static void APIENTRY InitGetSharpenTexFuncSGIS (GLenum target, GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetSharpenTexFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetSharpenTexFuncSGIS = extproc; + + glGetSharpenTexFuncSGIS(target, points); +} + +static void APIENTRY InitSampleMaskSGIS (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskSGIS = extproc; + + glSampleMaskSGIS(value, invert); +} + +static void APIENTRY InitSamplePatternSGIS (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternSGIS = extproc; + + glSamplePatternSGIS(pattern); +} + +static void APIENTRY InitArrayElementEXT (GLint i) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayElementEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayElementEXT = extproc; + + glArrayElementEXT(i); +} + +static void APIENTRY InitColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerEXT = extproc; + + glColorPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitDrawArraysEXT (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawArraysEXT = extproc; + + glDrawArraysEXT(mode, first, count); +} + +static void APIENTRY InitEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerEXT = extproc; + + glEdgeFlagPointerEXT(stride, count, pointer); +} + +static void APIENTRY InitGetPointervEXT (GLenum pname, GLvoid* *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetPointervEXT = extproc; + + glGetPointervEXT(pname, params); +} + +static void APIENTRY InitIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerEXT = extproc; + + glIndexPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerEXT = extproc; + + glNormalPointerEXT(type, stride, count, pointer); +} + +static void APIENTRY InitTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerEXT = extproc; + + glTexCoordPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerEXT = extproc; + + glVertexPointerEXT(size, type, stride, count, pointer); +} + +static void APIENTRY InitBlendEquationEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationEXT = extproc; + + glBlendEquationEXT(mode); +} + +static void APIENTRY InitSpriteParameterfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfSGIX = extproc; + + glSpriteParameterfSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterfvSGIX = extproc; + + glSpriteParameterfvSGIX(pname, params); +} + +static void APIENTRY InitSpriteParameteriSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameteriSGIX = extproc; + + glSpriteParameteriSGIX(pname, param); +} + +static void APIENTRY InitSpriteParameterivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSpriteParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSpriteParameterivSGIX = extproc; + + glSpriteParameterivSGIX(pname, params); +} + +static void APIENTRY InitPointParameterfEXT (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfEXT = extproc; + + glPointParameterfEXT(pname, param); +} + +static void APIENTRY InitPointParameterfvEXT (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvEXT = extproc; + + glPointParameterfvEXT(pname, params); +} + +static void APIENTRY InitPointParameterfSGIS (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfSGIS = extproc; + + glPointParameterfSGIS(pname, param); +} + +static void APIENTRY InitPointParameterfvSGIS (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterfvSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterfvSGIS = extproc; + + glPointParameterfvSGIS(pname, params); +} + +static GLint APIENTRY InitGetInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGetInstrumentsSGIX = extproc; + + return glGetInstrumentsSGIX(); +} + +static void APIENTRY InitInstrumentsBufferSGIX (GLsizei size, GLint *buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInstrumentsBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInstrumentsBufferSGIX = extproc; + + glInstrumentsBufferSGIX(size, buffer); +} + +static GLint APIENTRY InitPollInstrumentsSGIX (GLint *marker_p) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollInstrumentsSGIX = extproc; + + return glPollInstrumentsSGIX(marker_p); +} + +static void APIENTRY InitReadInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReadInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReadInstrumentsSGIX = extproc; + + glReadInstrumentsSGIX(marker); +} + +static void APIENTRY InitStartInstrumentsSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStartInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStartInstrumentsSGIX = extproc; + + glStartInstrumentsSGIX(); +} + +static void APIENTRY InitStopInstrumentsSGIX (GLint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStopInstrumentsSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStopInstrumentsSGIX = extproc; + + glStopInstrumentsSGIX(marker); +} + +static void APIENTRY InitFrameZoomSGIX (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFrameZoomSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFrameZoomSGIX = extproc; + + glFrameZoomSGIX(factor); +} + +static void APIENTRY InitTagSampleBufferSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTagSampleBufferSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTagSampleBufferSGIX = extproc; + + glTagSampleBufferSGIX(); +} + +static void APIENTRY InitDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3dSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3dSGIX = extproc; + + glDeformationMap3dSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformationMap3fSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformationMap3fSGIX = extproc; + + glDeformationMap3fSGIX(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, w1, w2, wstride, worder, points); +} + +static void APIENTRY InitDeformSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeformSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeformSGIX = extproc; + + glDeformSGIX(mask); +} + +static void APIENTRY InitLoadIdentityDeformationMapSGIX (GLbitfield mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadIdentityDeformationMapSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadIdentityDeformationMapSGIX = extproc; + + glLoadIdentityDeformationMapSGIX(mask); +} + +static void APIENTRY InitReferencePlaneSGIX (const GLdouble *equation) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReferencePlaneSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReferencePlaneSGIX = extproc; + + glReferencePlaneSGIX(equation); +} + +static void APIENTRY InitFlushRasterSGIX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushRasterSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushRasterSGIX = extproc; + + glFlushRasterSGIX(); +} + +static void APIENTRY InitFogFuncSGIS (GLsizei n, const GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogFuncSGIS = extproc; + + glFogFuncSGIS(n, points); +} + +static void APIENTRY InitGetFogFuncSGIS (GLfloat *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFogFuncSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFogFuncSGIS = extproc; + + glGetFogFuncSGIS(points); +} + +static void APIENTRY InitImageTransformParameteriHP (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameteriHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameteriHP = extproc; + + glImageTransformParameteriHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfHP = extproc; + + glImageTransformParameterfHP(target, pname, param); +} + +static void APIENTRY InitImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterivHP = extproc; + + glImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glImageTransformParameterfvHP = extproc; + + glImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterivHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterivHP = extproc; + + glGetImageTransformParameterivHP(target, pname, params); +} + +static void APIENTRY InitGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetImageTransformParameterfvHP"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetImageTransformParameterfvHP = extproc; + + glGetImageTransformParameterfvHP(target, pname, params); +} + +static void APIENTRY InitColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorSubTableEXT = extproc; + + glColorSubTableEXT(target, start, count, format, type, data); +} + +static void APIENTRY InitCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCopyColorSubTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCopyColorSubTableEXT = extproc; + + glCopyColorSubTableEXT(target, start, x, y, width); +} + +static void APIENTRY InitHintPGI (GLenum target, GLint mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glHintPGI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glHintPGI = extproc; + + glHintPGI(target, mode); +} + +static void APIENTRY InitColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorTableEXT = extproc; + + glColorTableEXT(target, internalFormat, width, format, type, table); +} + +static void APIENTRY InitGetColorTableEXT (GLenum target, GLenum format, GLenum type, GLvoid *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableEXT = extproc; + + glGetColorTableEXT(target, format, type, data); +} + +static void APIENTRY InitGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterivEXT = extproc; + + glGetColorTableParameterivEXT(target, pname, params); +} + +static void APIENTRY InitGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetColorTableParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetColorTableParameterfvEXT = extproc; + + glGetColorTableParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterfvSGIX = extproc; + + glGetListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetListParameterivSGIX = extproc; + + glGetListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitListParameterfSGIX (GLuint list, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfSGIX = extproc; + + glListParameterfSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterfvSGIX = extproc; + + glListParameterfvSGIX(list, pname, params); +} + +static void APIENTRY InitListParameteriSGIX (GLuint list, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameteriSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameteriSGIX = extproc; + + glListParameteriSGIX(list, pname, param); +} + +static void APIENTRY InitListParameterivSGIX (GLuint list, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glListParameterivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glListParameterivSGIX = extproc; + + glListParameterivSGIX(list, pname, params); +} + +static void APIENTRY InitIndexMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexMaterialEXT = extproc; + + glIndexMaterialEXT(face, mode); +} + +static void APIENTRY InitIndexFuncEXT (GLenum func, GLclampf ref) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexFuncEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexFuncEXT = extproc; + + glIndexFuncEXT(func, ref); +} + +static void APIENTRY InitLockArraysEXT (GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLockArraysEXT = extproc; + + glLockArraysEXT(first, count); +} + +static void APIENTRY InitUnlockArraysEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnlockArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnlockArraysEXT = extproc; + + glUnlockArraysEXT(); +} + +static void APIENTRY InitCullParameterdvEXT (GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterdvEXT = extproc; + + glCullParameterdvEXT(pname, params); +} + +static void APIENTRY InitCullParameterfvEXT (GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCullParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCullParameterfvEXT = extproc; + + glCullParameterfvEXT(pname, params); +} + +static void APIENTRY InitFragmentColorMaterialSGIX (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentColorMaterialSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentColorMaterialSGIX = extproc; + + glFragmentColorMaterialSGIX(face, mode); +} + +static void APIENTRY InitFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfSGIX = extproc; + + glFragmentLightfSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightfvSGIX = extproc; + + glFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightiSGIX (GLenum light, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightiSGIX = extproc; + + glFragmentLightiSGIX(light, pname, param); +} + +static void APIENTRY InitFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightivSGIX = extproc; + + glFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitFragmentLightModelfSGIX (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfSGIX = extproc; + + glFragmentLightModelfSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelfvSGIX = extproc; + + glFragmentLightModelfvSGIX(pname, params); +} + +static void APIENTRY InitFragmentLightModeliSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModeliSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModeliSGIX = extproc; + + glFragmentLightModeliSGIX(pname, param); +} + +static void APIENTRY InitFragmentLightModelivSGIX (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentLightModelivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentLightModelivSGIX = extproc; + + glFragmentLightModelivSGIX(pname, params); +} + +static void APIENTRY InitFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfSGIX = extproc; + + glFragmentMaterialfSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialfvSGIX = extproc; + + glFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialiSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialiSGIX = extproc; + + glFragmentMaterialiSGIX(face, pname, param); +} + +static void APIENTRY InitFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFragmentMaterialivSGIX = extproc; + + glFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightfvSGIX = extproc; + + glGetFragmentLightfvSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentLightivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentLightivSGIX = extproc; + + glGetFragmentLightivSGIX(light, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialfvSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialfvSGIX = extproc; + + glGetFragmentMaterialfvSGIX(face, pname, params); +} + +static void APIENTRY InitGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFragmentMaterialivSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFragmentMaterialivSGIX = extproc; + + glGetFragmentMaterialivSGIX(face, pname, params); +} + +static void APIENTRY InitLightEnviSGIX (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLightEnviSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLightEnviSGIX = extproc; + + glLightEnviSGIX(pname, param); +} + +static void APIENTRY InitDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementsEXT = extproc; + + glDrawRangeElementsEXT(mode, start, end, count, type, indices); +} + +static void APIENTRY InitApplyTextureEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glApplyTextureEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glApplyTextureEXT = extproc; + + glApplyTextureEXT(mode); +} + +static void APIENTRY InitTextureLightEXT (GLenum pname) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureLightEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureLightEXT = extproc; + + glTextureLightEXT(pname); +} + +static void APIENTRY InitTextureMaterialEXT (GLenum face, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureMaterialEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureMaterialEXT = extproc; + + glTextureMaterialEXT(face, mode); +} + +static void APIENTRY InitAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAsyncMarkerSGIX = extproc; + + glAsyncMarkerSGIX(marker); +} + +static GLint APIENTRY InitFinishAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glFinishAsyncSGIX = extproc; + + return glFinishAsyncSGIX(markerp); +} + +static GLint APIENTRY InitPollAsyncSGIX (GLuint *markerp) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPollAsyncSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glPollAsyncSGIX = extproc; + + return glPollAsyncSGIX(markerp); +} + +static GLuint APIENTRY InitGenAsyncMarkersSGIX (GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenAsyncMarkersSGIX = extproc; + + return glGenAsyncMarkersSGIX(range); +} + +static void APIENTRY InitDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteAsyncMarkersSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteAsyncMarkersSGIX = extproc; + + glDeleteAsyncMarkersSGIX(marker, range); +} + +static GLboolean APIENTRY InitIsAsyncMarkerSGIX (GLuint marker) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsAsyncMarkerSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsAsyncMarkerSGIX = extproc; + + return glIsAsyncMarkerSGIX(marker); +} + +static void APIENTRY InitVertexPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointervINTEL = extproc; + + glVertexPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitNormalPointervINTEL (GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointervINTEL = extproc; + + glNormalPointervINTEL(type, pointer); +} + +static void APIENTRY InitColorPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointervINTEL = extproc; + + glColorPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitTexCoordPointervINTEL (GLint size, GLenum type, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointervINTEL"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointervINTEL = extproc; + + glTexCoordPointervINTEL(size, type, pointer); +} + +static void APIENTRY InitPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameteriEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameteriEXT = extproc; + + glPixelTransformParameteriEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfEXT = extproc; + + glPixelTransformParameterfEXT(target, pname, param); +} + +static void APIENTRY InitPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterivEXT = extproc; + + glPixelTransformParameterivEXT(target, pname, params); +} + +static void APIENTRY InitPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelTransformParameterfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelTransformParameterfvEXT = extproc; + + glPixelTransformParameterfvEXT(target, pname, params); +} + +static void APIENTRY InitSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bEXT = extproc; + + glSecondaryColor3bEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3bvEXT = extproc; + + glSecondaryColor3bvEXT(v); +} + +static void APIENTRY InitSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dEXT = extproc; + + glSecondaryColor3dEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3dvEXT = extproc; + + glSecondaryColor3dvEXT(v); +} + +static void APIENTRY InitSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fEXT = extproc; + + glSecondaryColor3fEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3fvEXT = extproc; + + glSecondaryColor3fvEXT(v); +} + +static void APIENTRY InitSecondaryColor3iEXT (GLint red, GLint green, GLint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3iEXT = extproc; + + glSecondaryColor3iEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ivEXT = extproc; + + glSecondaryColor3ivEXT(v); +} + +static void APIENTRY InitSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3sEXT = extproc; + + glSecondaryColor3sEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3svEXT = extproc; + + glSecondaryColor3svEXT(v); +} + +static void APIENTRY InitSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubEXT = extproc; + + glSecondaryColor3ubEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3ubvEXT (const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3ubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3ubvEXT = extproc; + + glSecondaryColor3ubvEXT(v); +} + +static void APIENTRY InitSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uiEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uiEXT = extproc; + + glSecondaryColor3uiEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3uivEXT (const GLuint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3uivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3uivEXT = extproc; + + glSecondaryColor3uivEXT(v); +} + +static void APIENTRY InitSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usEXT = extproc; + + glSecondaryColor3usEXT(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3usvEXT (const GLushort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3usvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3usvEXT = extproc; + + glSecondaryColor3usvEXT(v); +} + +static void APIENTRY InitSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerEXT = extproc; + + glSecondaryColorPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitTextureNormalEXT (GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureNormalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureNormalEXT = extproc; + + glTextureNormalEXT(mode); +} + +static void APIENTRY InitMultiDrawArraysEXT (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawArraysEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawArraysEXT = extproc; + + glMultiDrawArraysEXT(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementsEXT = extproc; + + glMultiDrawElementsEXT(mode, count, type, indices, primcount); +} + +static void APIENTRY InitFogCoordfEXT (GLfloat coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfEXT = extproc; + + glFogCoordfEXT(coord); +} + +static void APIENTRY InitFogCoordfvEXT (const GLfloat *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordfvEXT = extproc; + + glFogCoordfvEXT(coord); +} + +static void APIENTRY InitFogCoorddEXT (GLdouble coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddEXT = extproc; + + glFogCoorddEXT(coord); +} + +static void APIENTRY InitFogCoorddvEXT (const GLdouble *coord) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoorddvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoorddvEXT = extproc; + + glFogCoorddvEXT(coord); +} + +static void APIENTRY InitFogCoordPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerEXT = extproc; + + glFogCoordPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bEXT = extproc; + + glTangent3bEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3bvEXT = extproc; + + glTangent3bvEXT(v); +} + +static void APIENTRY InitTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dEXT = extproc; + + glTangent3dEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3dvEXT = extproc; + + glTangent3dvEXT(v); +} + +static void APIENTRY InitTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fEXT = extproc; + + glTangent3fEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3fvEXT = extproc; + + glTangent3fvEXT(v); +} + +static void APIENTRY InitTangent3iEXT (GLint tx, GLint ty, GLint tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3iEXT = extproc; + + glTangent3iEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3ivEXT = extproc; + + glTangent3ivEXT(v); +} + +static void APIENTRY InitTangent3sEXT (GLshort tx, GLshort ty, GLshort tz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3sEXT = extproc; + + glTangent3sEXT(tx, ty, tz); +} + +static void APIENTRY InitTangent3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangent3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangent3svEXT = extproc; + + glTangent3svEXT(v); +} + +static void APIENTRY InitBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bEXT = extproc; + + glBinormal3bEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3bvEXT (const GLbyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3bvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3bvEXT = extproc; + + glBinormal3bvEXT(v); +} + +static void APIENTRY InitBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dEXT = extproc; + + glBinormal3dEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3dvEXT (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3dvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3dvEXT = extproc; + + glBinormal3dvEXT(v); +} + +static void APIENTRY InitBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fEXT = extproc; + + glBinormal3fEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3fvEXT (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3fvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3fvEXT = extproc; + + glBinormal3fvEXT(v); +} + +static void APIENTRY InitBinormal3iEXT (GLint bx, GLint by, GLint bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3iEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3iEXT = extproc; + + glBinormal3iEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3ivEXT (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3ivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3ivEXT = extproc; + + glBinormal3ivEXT(v); +} + +static void APIENTRY InitBinormal3sEXT (GLshort bx, GLshort by, GLshort bz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3sEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3sEXT = extproc; + + glBinormal3sEXT(bx, by, bz); +} + +static void APIENTRY InitBinormal3svEXT (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormal3svEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormal3svEXT = extproc; + + glBinormal3svEXT(v); +} + +static void APIENTRY InitTangentPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTangentPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTangentPointerEXT = extproc; + + glTangentPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitBinormalPointerEXT (GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBinormalPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBinormalPointerEXT = extproc; + + glBinormalPointerEXT(type, stride, pointer); +} + +static void APIENTRY InitFinishTextureSUNX (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishTextureSUNX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishTextureSUNX = extproc; + + glFinishTextureSUNX(); +} + +static void APIENTRY InitGlobalAlphaFactorbSUN (GLbyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorbSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorbSUN = extproc; + + glGlobalAlphaFactorbSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorsSUN (GLshort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorsSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorsSUN = extproc; + + glGlobalAlphaFactorsSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoriSUN (GLint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoriSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoriSUN = extproc; + + glGlobalAlphaFactoriSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorfSUN (GLfloat factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorfSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorfSUN = extproc; + + glGlobalAlphaFactorfSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactordSUN (GLdouble factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactordSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactordSUN = extproc; + + glGlobalAlphaFactordSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorubSUN (GLubyte factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorubSUN = extproc; + + glGlobalAlphaFactorubSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactorusSUN (GLushort factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactorusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactorusSUN = extproc; + + glGlobalAlphaFactorusSUN(factor); +} + +static void APIENTRY InitGlobalAlphaFactoruiSUN (GLuint factor) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGlobalAlphaFactoruiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGlobalAlphaFactoruiSUN = extproc; + + glGlobalAlphaFactoruiSUN(factor); +} + +static void APIENTRY InitReplacementCodeuiSUN (GLuint code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiSUN = extproc; + + glReplacementCodeuiSUN(code); +} + +static void APIENTRY InitReplacementCodeusSUN (GLushort code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusSUN = extproc; + + glReplacementCodeusSUN(code); +} + +static void APIENTRY InitReplacementCodeubSUN (GLubyte code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubSUN = extproc; + + glReplacementCodeubSUN(code); +} + +static void APIENTRY InitReplacementCodeuivSUN (const GLuint *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuivSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuivSUN = extproc; + + glReplacementCodeuivSUN(code); +} + +static void APIENTRY InitReplacementCodeusvSUN (const GLushort *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeusvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeusvSUN = extproc; + + glReplacementCodeusvSUN(code); +} + +static void APIENTRY InitReplacementCodeubvSUN (const GLubyte *code) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeubvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeubvSUN = extproc; + + glReplacementCodeubvSUN(code); +} + +static void APIENTRY InitReplacementCodePointerSUN (GLenum type, GLsizei stride, const GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodePointerSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodePointerSUN = extproc; + + glReplacementCodePointerSUN(type, stride, pointer); +} + +static void APIENTRY InitColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fSUN = extproc; + + glColor4ubVertex2fSUN(r, g, b, a, x, y); +} + +static void APIENTRY InitColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex2fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex2fvSUN = extproc; + + glColor4ubVertex2fvSUN(c, v); +} + +static void APIENTRY InitColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fSUN = extproc; + + glColor4ubVertex3fSUN(r, g, b, a, x, y, z); +} + +static void APIENTRY InitColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4ubVertex3fvSUN = extproc; + + glColor4ubVertex3fvSUN(c, v); +} + +static void APIENTRY InitColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fSUN = extproc; + + glColor3fVertex3fSUN(r, g, b, x, y, z); +} + +static void APIENTRY InitColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3fVertex3fvSUN = extproc; + + glColor3fVertex3fvSUN(c, v); +} + +static void APIENTRY InitNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fSUN = extproc; + + glNormal3fVertex3fSUN(nx, ny, nz, x, y, z); +} + +static void APIENTRY InitNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3fVertex3fvSUN = extproc; + + glNormal3fVertex3fvSUN(n, v); +} + +static void APIENTRY InitColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fSUN = extproc; + + glColor4fNormal3fVertex3fSUN(r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4fNormal3fVertex3fvSUN = extproc; + + glColor4fNormal3fVertex3fvSUN(c, n, v); +} + +static void APIENTRY InitTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fSUN = extproc; + + glTexCoord2fVertex3fSUN(s, t, x, y, z); +} + +static void APIENTRY InitTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fVertex3fvSUN = extproc; + + glTexCoord2fVertex3fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fSUN = extproc; + + glTexCoord4fVertex4fSUN(s, t, p, q, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fVertex4fvSUN = extproc; + + glTexCoord4fVertex4fvSUN(tc, v); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fSUN = extproc; + + glTexCoord2fColor4ubVertex3fSUN(s, t, r, g, b, a, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4ubVertex3fvSUN = extproc; + + glTexCoord2fColor4ubVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fSUN = extproc; + + glTexCoord2fColor3fVertex3fSUN(s, t, r, g, b, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor3fVertex3fvSUN = extproc; + + glTexCoord2fColor3fVertex3fvSUN(tc, c, v); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fSUN = extproc; + + glTexCoord2fNormal3fVertex3fSUN(s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fNormal3fVertex3fvSUN(tc, n, v); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fSUN(s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glTexCoord2fColor4fNormal3fVertex3fvSUN(tc, c, n, v); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fSUN(s, t, p, q, r, g, b, a, nx, ny, nz, x, y, z, w); +} + +static void APIENTRY InitTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4fColor4fNormal3fVertex4fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4fColor4fNormal3fVertex4fvSUN = extproc; + + glTexCoord4fColor4fNormal3fVertex4fvSUN(tc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fSUN = extproc; + + glReplacementCodeuiVertex3fSUN(rc, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiVertex3fvSUN = extproc; + + glReplacementCodeuiVertex3fvSUN(rc, v); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fSUN(rc, r, g, b, a, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4ubVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4ubVertex3fvSUN = extproc; + + glReplacementCodeuiColor4ubVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fSUN = extproc; + + glReplacementCodeuiColor3fVertex3fSUN(rc, r, g, b, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor3fVertex3fvSUN(rc, c, v); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fSUN(rc, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiNormal3fVertex3fvSUN(rc, n, v); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fSUN(rc, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiColor4fNormal3fVertex3fvSUN(rc, c, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fSUN(rc, s, t, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fVertex3fvSUN(rc, tc, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN(rc, s, t, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN(rc, tc, n, v); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN(rc, s, t, r, g, b, a, nx, ny, nz, x, y, z); +} + +static void APIENTRY InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = extproc; + + glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN(rc, tc, c, n, v); +} + +static void APIENTRY InitBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateEXT = extproc; + + glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendFuncSeparateINGR"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendFuncSeparateINGR = extproc; + + glBlendFuncSeparateINGR(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void APIENTRY InitVertexWeightfEXT (GLfloat weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfEXT = extproc; + + glVertexWeightfEXT(weight); +} + +static void APIENTRY InitVertexWeightfvEXT (const GLfloat *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightfvEXT = extproc; + + glVertexWeightfvEXT(weight); +} + +static void APIENTRY InitVertexWeightPointerEXT (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeightPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeightPointerEXT = extproc; + + glVertexWeightPointerEXT(size, type, stride, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeNV = extproc; + + glFlushVertexArrayRangeNV(); +} + +static void APIENTRY InitVertexArrayRangeNV (GLsizei length, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeNV = extproc; + + glVertexArrayRangeNV(length, pointer); +} + +static void APIENTRY InitCombinerParameterfvNV (GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfvNV = extproc; + + glCombinerParameterfvNV(pname, params); +} + +static void APIENTRY InitCombinerParameterfNV (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterfNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterfNV = extproc; + + glCombinerParameterfNV(pname, param); +} + +static void APIENTRY InitCombinerParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameterivNV = extproc; + + glCombinerParameterivNV(pname, params); +} + +static void APIENTRY InitCombinerParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerParameteriNV = extproc; + + glCombinerParameteriNV(pname, param); +} + +static void APIENTRY InitCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerInputNV = extproc; + + glCombinerInputNV(stage, portion, variable, input, mapping, componentUsage); +} + +static void APIENTRY InitCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerOutputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerOutputNV = extproc; + + glCombinerOutputNV(stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum); +} + +static void APIENTRY InitFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinalCombinerInputNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinalCombinerInputNV = extproc; + + glFinalCombinerInputNV(variable, input, mapping, componentUsage); +} + +static void APIENTRY InitGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterfvNV = extproc; + + glGetCombinerInputParameterfvNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerInputParameterivNV = extproc; + + glGetCombinerInputParameterivNV(stage, portion, variable, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterfvNV = extproc; + + glGetCombinerOutputParameterfvNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerOutputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerOutputParameterivNV = extproc; + + glGetCombinerOutputParameterivNV(stage, portion, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterfvNV = extproc; + + glGetFinalCombinerInputParameterfvNV(variable, pname, params); +} + +static void APIENTRY InitGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFinalCombinerInputParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFinalCombinerInputParameterivNV = extproc; + + glGetFinalCombinerInputParameterivNV(variable, pname, params); +} + +static void APIENTRY InitResizeBuffersMESA (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glResizeBuffersMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glResizeBuffersMESA = extproc; + + glResizeBuffersMESA(); +} + +static void APIENTRY InitWindowPos2dMESA (GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dMESA = extproc; + + glWindowPos2dMESA(x, y); +} + +static void APIENTRY InitWindowPos2dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2dvMESA = extproc; + + glWindowPos2dvMESA(v); +} + +static void APIENTRY InitWindowPos2fMESA (GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fMESA = extproc; + + glWindowPos2fMESA(x, y); +} + +static void APIENTRY InitWindowPos2fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2fvMESA = extproc; + + glWindowPos2fvMESA(v); +} + +static void APIENTRY InitWindowPos2iMESA (GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2iMESA = extproc; + + glWindowPos2iMESA(x, y); +} + +static void APIENTRY InitWindowPos2ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2ivMESA = extproc; + + glWindowPos2ivMESA(v); +} + +static void APIENTRY InitWindowPos2sMESA (GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2sMESA = extproc; + + glWindowPos2sMESA(x, y); +} + +static void APIENTRY InitWindowPos2svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos2svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos2svMESA = extproc; + + glWindowPos2svMESA(v); +} + +static void APIENTRY InitWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dMESA = extproc; + + glWindowPos3dMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3dvMESA = extproc; + + glWindowPos3dvMESA(v); +} + +static void APIENTRY InitWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fMESA = extproc; + + glWindowPos3fMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3fvMESA = extproc; + + glWindowPos3fvMESA(v); +} + +static void APIENTRY InitWindowPos3iMESA (GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3iMESA = extproc; + + glWindowPos3iMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3ivMESA = extproc; + + glWindowPos3ivMESA(v); +} + +static void APIENTRY InitWindowPos3sMESA (GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3sMESA = extproc; + + glWindowPos3sMESA(x, y, z); +} + +static void APIENTRY InitWindowPos3svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos3svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos3svMESA = extproc; + + glWindowPos3svMESA(v); +} + +static void APIENTRY InitWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dMESA = extproc; + + glWindowPos4dMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4dvMESA (const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4dvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4dvMESA = extproc; + + glWindowPos4dvMESA(v); +} + +static void APIENTRY InitWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fMESA = extproc; + + glWindowPos4fMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4fvMESA (const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4fvMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4fvMESA = extproc; + + glWindowPos4fvMESA(v); +} + +static void APIENTRY InitWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4iMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4iMESA = extproc; + + glWindowPos4iMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4ivMESA (const GLint *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4ivMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4ivMESA = extproc; + + glWindowPos4ivMESA(v); +} + +static void APIENTRY InitWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4sMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4sMESA = extproc; + + glWindowPos4sMESA(x, y, z, w); +} + +static void APIENTRY InitWindowPos4svMESA (const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWindowPos4svMESA"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWindowPos4svMESA = extproc; + + glWindowPos4svMESA(v); +} + +static void APIENTRY InitMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawArraysIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawArraysIBM = extproc; + + glMultiModeDrawArraysIBM(mode, first, count, primcount, modestride); +} + +static void APIENTRY InitMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiModeDrawElementsIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiModeDrawElementsIBM = extproc; + + glMultiModeDrawElementsIBM(mode, count, type, indices, primcount, modestride); +} + +static void APIENTRY InitColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorPointerListIBM = extproc; + + glColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColorPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColorPointerListIBM = extproc; + + glSecondaryColorPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitEdgeFlagPointerListIBM (GLint stride, const GLboolean* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEdgeFlagPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEdgeFlagPointerListIBM = extproc; + + glEdgeFlagPointerListIBM(stride, pointer, ptrstride); +} + +static void APIENTRY InitFogCoordPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordPointerListIBM = extproc; + + glFogCoordPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitIndexPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIndexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIndexPointerListIBM = extproc; + + glIndexPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitNormalPointerListIBM (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalPointerListIBM = extproc; + + glNormalPointerListIBM(type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoordPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoordPointerListIBM = extproc; + + glTexCoordPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitVertexPointerListIBM (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexPointerListIBM"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexPointerListIBM = extproc; + + glVertexPointerListIBM(size, type, stride, pointer, ptrstride); +} + +static void APIENTRY InitTbufferMask3DFX (GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTbufferMask3DFX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTbufferMask3DFX = extproc; + + glTbufferMask3DFX(mask); +} + +static void APIENTRY InitSampleMaskEXT (GLclampf value, GLboolean invert) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMaskEXT = extproc; + + glSampleMaskEXT(value, invert); +} + +static void APIENTRY InitSamplePatternEXT (GLenum pattern) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSamplePatternEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSamplePatternEXT = extproc; + + glSamplePatternEXT(pattern); +} + +static void APIENTRY InitTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTextureColorMaskSGIS"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTextureColorMaskSGIS = extproc; + + glTextureColorMaskSGIS(red, green, blue, alpha); +} + +static void APIENTRY InitIglooInterfaceSGIX (GLenum pname, const GLvoid *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIglooInterfaceSGIX"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glIglooInterfaceSGIX = extproc; + + glIglooInterfaceSGIX(pname, params); +} + +static void APIENTRY InitDeleteFencesNV (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesNV = extproc; + + glDeleteFencesNV(n, fences); +} + +static void APIENTRY InitGenFencesNV (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesNV = extproc; + + glGenFencesNV(n, fences); +} + +static GLboolean APIENTRY InitIsFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceNV = extproc; + + return glIsFenceNV(fence); +} + +static GLboolean APIENTRY InitTestFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceNV = extproc; + + return glTestFenceNV(fence); +} + +static void APIENTRY InitGetFenceivNV (GLuint fence, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetFenceivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetFenceivNV = extproc; + + glGetFenceivNV(fence, pname, params); +} + +static void APIENTRY InitFinishFenceNV (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceNV = extproc; + + glFinishFenceNV(fence); +} + +static void APIENTRY InitSetFenceNV (GLuint fence, GLenum condition) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceNV = extproc; + + glSetFenceNV(fence, condition); +} + +static void APIENTRY InitMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapControlPointsNV = extproc; + + glMapControlPointsNV(target, index, type, ustride, vstride, uorder, vorder, packed, points); +} + +static void APIENTRY InitMapParameterivNV (GLenum target, GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterivNV = extproc; + + glMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMapParameterfvNV = extproc; + + glMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapControlPointsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapControlPointsNV = extproc; + + glGetMapControlPointsNV(target, index, type, ustride, vstride, packed, points); +} + +static void APIENTRY InitGetMapParameterivNV (GLenum target, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterivNV = extproc; + + glGetMapParameterivNV(target, pname, params); +} + +static void APIENTRY InitGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapParameterfvNV = extproc; + + glGetMapParameterfvNV(target, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterivNV = extproc; + + glGetMapAttribParameterivNV(target, index, pname, params); +} + +static void APIENTRY InitGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetMapAttribParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetMapAttribParameterfvNV = extproc; + + glGetMapAttribParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitEvalMapsNV (GLenum target, GLenum mode) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEvalMapsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEvalMapsNV = extproc; + + glEvalMapsNV(target, mode); +} + +static void APIENTRY InitCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glCombinerStageParameterfvNV = extproc; + + glCombinerStageParameterfvNV(stage, pname, params); +} + +static void APIENTRY InitGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetCombinerStageParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetCombinerStageParameterfvNV = extproc; + + glGetCombinerStageParameterfvNV(stage, pname, params); +} + +static GLboolean APIENTRY InitAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAreProgramsResidentNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glAreProgramsResidentNV = extproc; + + return glAreProgramsResidentNV(n, programs, residences); +} + +static void APIENTRY InitBindProgramNV (GLenum target, GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindProgramNV = extproc; + + glBindProgramNV(target, id); +} + +static void APIENTRY InitDeleteProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteProgramsNV = extproc; + + glDeleteProgramsNV(n, programs); +} + +static void APIENTRY InitExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExecuteProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExecuteProgramNV = extproc; + + glExecuteProgramNV(target, id, params); +} + +static void APIENTRY InitGenProgramsNV (GLsizei n, GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenProgramsNV = extproc; + + glGenProgramsNV(n, programs); +} + +static void APIENTRY InitGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterdvNV = extproc; + + glGetProgramParameterdvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramParameterfvNV = extproc; + + glGetProgramParameterfvNV(target, index, pname, params); +} + +static void APIENTRY InitGetProgramivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramivNV = extproc; + + glGetProgramivNV(id, pname, params); +} + +static void APIENTRY InitGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramStringNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramStringNV = extproc; + + glGetProgramStringNV(id, pname, program); +} + +static void APIENTRY InitGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTrackMatrixivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTrackMatrixivNV = extproc; + + glGetTrackMatrixivNV(target, address, pname, params); +} + +static void APIENTRY InitGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribdvNV = extproc; + + glGetVertexAttribdvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribfvNV = extproc; + + glGetVertexAttribfvNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribivNV = extproc; + + glGetVertexAttribivNV(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribPointervNV (GLuint index, GLenum pname, GLvoid* *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribPointervNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribPointervNV = extproc; + + glGetVertexAttribPointervNV(index, pname, pointer); +} + +static GLboolean APIENTRY InitIsProgramNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsProgramNV = extproc; + + return glIsProgramNV(id); +} + +static void APIENTRY InitLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glLoadProgramNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glLoadProgramNV = extproc; + + glLoadProgramNV(target, id, len, program); +} + +static void APIENTRY InitProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dNV = extproc; + + glProgramParameter4dNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4dvNV = extproc; + + glProgramParameter4dvNV(target, index, v); +} + +static void APIENTRY InitProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fNV = extproc; + + glProgramParameter4fNV(target, index, x, y, z, w); +} + +static void APIENTRY InitProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameter4fvNV = extproc; + + glProgramParameter4fvNV(target, index, v); +} + +static void APIENTRY InitProgramParameters4dvNV (GLenum target, GLuint index, GLuint count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4dvNV = extproc; + + glProgramParameters4dvNV(target, index, count, v); +} + +static void APIENTRY InitProgramParameters4fvNV (GLenum target, GLuint index, GLuint count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramParameters4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramParameters4fvNV = extproc; + + glProgramParameters4fvNV(target, index, count, v); +} + +static void APIENTRY InitRequestResidentProgramsNV (GLsizei n, const GLuint *programs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glRequestResidentProgramsNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glRequestResidentProgramsNV = extproc; + + glRequestResidentProgramsNV(n, programs); +} + +static void APIENTRY InitTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTrackMatrixNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTrackMatrixNV = extproc; + + glTrackMatrixNV(target, address, matrix, transform); +} + +static void APIENTRY InitVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribPointerNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribPointerNV = extproc; + + glVertexAttribPointerNV(index, fsize, type, stride, pointer); +} + +static void APIENTRY InitVertexAttrib1dNV (GLuint index, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dNV = extproc; + + glVertexAttrib1dNV(index, x); +} + +static void APIENTRY InitVertexAttrib1dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1dvNV = extproc; + + glVertexAttrib1dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1fNV (GLuint index, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fNV = extproc; + + glVertexAttrib1fNV(index, x); +} + +static void APIENTRY InitVertexAttrib1fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1fvNV = extproc; + + glVertexAttrib1fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib1sNV (GLuint index, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1sNV = extproc; + + glVertexAttrib1sNV(index, x); +} + +static void APIENTRY InitVertexAttrib1svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1svNV = extproc; + + glVertexAttrib1svNV(index, v); +} + +static void APIENTRY InitVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dNV = extproc; + + glVertexAttrib2dNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2dvNV = extproc; + + glVertexAttrib2dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fNV = extproc; + + glVertexAttrib2fNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2fvNV = extproc; + + glVertexAttrib2fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2sNV (GLuint index, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2sNV = extproc; + + glVertexAttrib2sNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2svNV = extproc; + + glVertexAttrib2svNV(index, v); +} + +static void APIENTRY InitVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dNV = extproc; + + glVertexAttrib3dNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3dvNV = extproc; + + glVertexAttrib3dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fNV = extproc; + + glVertexAttrib3fNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3fvNV = extproc; + + glVertexAttrib3fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3sNV = extproc; + + glVertexAttrib3sNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3svNV = extproc; + + glVertexAttrib3svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dNV = extproc; + + glVertexAttrib4dNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4dvNV (GLuint index, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4dvNV = extproc; + + glVertexAttrib4dvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fNV = extproc; + + glVertexAttrib4fNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4fvNV (GLuint index, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4fvNV = extproc; + + glVertexAttrib4fvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4sNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4sNV = extproc; + + glVertexAttrib4sNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4svNV (GLuint index, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4svNV = extproc; + + glVertexAttrib4svNV(index, v); +} + +static void APIENTRY InitVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubNV = extproc; + + glVertexAttrib4ubNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4ubvNV (GLuint index, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4ubvNV = extproc; + + glVertexAttrib4ubvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1dvNV = extproc; + + glVertexAttribs1dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1fvNV = extproc; + + glVertexAttribs1fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1svNV = extproc; + + glVertexAttribs1svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2dvNV = extproc; + + glVertexAttribs2dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2fvNV = extproc; + + glVertexAttribs2fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2svNV = extproc; + + glVertexAttribs2svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3dvNV = extproc; + + glVertexAttribs3dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3fvNV = extproc; + + glVertexAttribs3fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3svNV = extproc; + + glVertexAttribs3svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4dvNV = extproc; + + glVertexAttribs4dvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4fvNV = extproc; + + glVertexAttribs4fvNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4svNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4svNV = extproc; + + glVertexAttribs4svNV(index, count, v); +} + +static void APIENTRY InitVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4ubvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4ubvNV = extproc; + + glVertexAttribs4ubvNV(index, count, v); +} + +static void APIENTRY InitTexBumpParameterivATI (GLenum pname, const GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterivATI = extproc; + + glTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitTexBumpParameterfvATI (GLenum pname, const GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexBumpParameterfvATI = extproc; + + glTexBumpParameterfvATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterivATI (GLenum pname, GLint *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterivATI = extproc; + + glGetTexBumpParameterivATI(pname, param); +} + +static void APIENTRY InitGetTexBumpParameterfvATI (GLenum pname, GLfloat *param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetTexBumpParameterfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetTexBumpParameterfvATI = extproc; + + glGetTexBumpParameterfvATI(pname, param); +} + +static GLuint APIENTRY InitGenFragmentShadersATI (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFragmentShadersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenFragmentShadersATI = extproc; + + return glGenFragmentShadersATI(range); +} + +static void APIENTRY InitBindFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindFragmentShaderATI = extproc; + + glBindFragmentShaderATI(id); +} + +static void APIENTRY InitDeleteFragmentShaderATI (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFragmentShaderATI = extproc; + + glDeleteFragmentShaderATI(id); +} + +static void APIENTRY InitBeginFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginFragmentShaderATI = extproc; + + glBeginFragmentShaderATI(); +} + +static void APIENTRY InitEndFragmentShaderATI (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndFragmentShaderATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndFragmentShaderATI = extproc; + + glEndFragmentShaderATI(); +} + +static void APIENTRY InitPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPassTexCoordATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPassTexCoordATI = extproc; + + glPassTexCoordATI(dst, coord, swizzle); +} + +static void APIENTRY InitSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSampleMapATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSampleMapATI = extproc; + + glSampleMapATI(dst, interp, swizzle); +} + +static void APIENTRY InitColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp1ATI = extproc; + + glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp2ATI = extproc; + + glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColorFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColorFragmentOp3ATI = extproc; + + glColorFragmentOp3ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp1ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp1ATI = extproc; + + glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod); +} + +static void APIENTRY InitAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp2ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp2ATI = extproc; + + glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod); +} + +static void APIENTRY InitAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAlphaFragmentOp3ATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAlphaFragmentOp3ATI = extproc; + + glAlphaFragmentOp3ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +} + +static void APIENTRY InitSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFragmentShaderConstantATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFragmentShaderConstantATI = extproc; + + glSetFragmentShaderConstantATI(dst, value); +} + +static void APIENTRY InitPNTrianglesiATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesiATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesiATI = extproc; + + glPNTrianglesiATI(pname, param); +} + +static void APIENTRY InitPNTrianglesfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPNTrianglesfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPNTrianglesfATI = extproc; + + glPNTrianglesfATI(pname, param); +} + +static GLuint APIENTRY InitNewObjectBufferATI (GLsizei size, const GLvoid *pointer, GLenum usage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNewObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glNewObjectBufferATI = extproc; + + return glNewObjectBufferATI(size, pointer, usage); +} + +static GLboolean APIENTRY InitIsObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsObjectBufferATI = extproc; + + return glIsObjectBufferATI(buffer); +} + +static void APIENTRY InitUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUpdateObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUpdateObjectBufferATI = extproc; + + glUpdateObjectBufferATI(buffer, offset, size, pointer, preserve); +} + +static void APIENTRY InitGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferfvATI = extproc; + + glGetObjectBufferfvATI(buffer, pname, params); +} + +static void APIENTRY InitGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetObjectBufferivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetObjectBufferivATI = extproc; + + glGetObjectBufferivATI(buffer, pname, params); +} + +static void APIENTRY InitFreeObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFreeObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFreeObjectBufferATI = extproc; + + glFreeObjectBufferATI(buffer); +} + +static void APIENTRY InitArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glArrayObjectATI = extproc; + + glArrayObjectATI(array, size, type, stride, buffer, offset); +} + +static void APIENTRY InitGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectfvATI = extproc; + + glGetArrayObjectfvATI(array, pname, params); +} + +static void APIENTRY InitGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetArrayObjectivATI = extproc; + + glGetArrayObjectivATI(array, pname, params); +} + +static void APIENTRY InitVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantArrayObjectATI = extproc; + + glVariantArrayObjectATI(id, type, stride, buffer, offset); +} + +static void APIENTRY InitGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectfvATI = extproc; + + glGetVariantArrayObjectfvATI(id, pname, params); +} + +static void APIENTRY InitGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantArrayObjectivATI = extproc; + + glGetVariantArrayObjectivATI(id, pname, params); +} + +static void APIENTRY InitBeginVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginVertexShaderEXT = extproc; + + glBeginVertexShaderEXT(); +} + +static void APIENTRY InitEndVertexShaderEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndVertexShaderEXT = extproc; + + glEndVertexShaderEXT(); +} + +static void APIENTRY InitBindVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexShaderEXT = extproc; + + glBindVertexShaderEXT(id); +} + +static GLuint APIENTRY InitGenVertexShadersEXT (GLuint range) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexShadersEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenVertexShadersEXT = extproc; + + return glGenVertexShadersEXT(range); +} + +static void APIENTRY InitDeleteVertexShaderEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexShaderEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexShaderEXT = extproc; + + glDeleteVertexShaderEXT(id); +} + +static void APIENTRY InitShaderOp1EXT (GLenum op, GLuint res, GLuint arg1) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp1EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp1EXT = extproc; + + glShaderOp1EXT(op, res, arg1); +} + +static void APIENTRY InitShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp2EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp2EXT = extproc; + + glShaderOp2EXT(op, res, arg1, arg2); +} + +static void APIENTRY InitShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glShaderOp3EXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glShaderOp3EXT = extproc; + + glShaderOp3EXT(op, res, arg1, arg2, arg3); +} + +static void APIENTRY InitSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSwizzleEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSwizzleEXT = extproc; + + glSwizzleEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glWriteMaskEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glWriteMaskEXT = extproc; + + glWriteMaskEXT(res, in, outX, outY, outZ, outW); +} + +static void APIENTRY InitInsertComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glInsertComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glInsertComponentEXT = extproc; + + glInsertComponentEXT(res, src, num); +} + +static void APIENTRY InitExtractComponentEXT (GLuint res, GLuint src, GLuint num) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glExtractComponentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glExtractComponentEXT = extproc; + + glExtractComponentEXT(res, src, num); +} + +static GLuint APIENTRY InitGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenSymbolsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glGenSymbolsEXT = extproc; + + return glGenSymbolsEXT(datatype, storagetype, range, components); +} + +static void APIENTRY InitSetInvariantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetInvariantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetInvariantEXT = extproc; + + glSetInvariantEXT(id, type, addr); +} + +static void APIENTRY InitSetLocalConstantEXT (GLuint id, GLenum type, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetLocalConstantEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetLocalConstantEXT = extproc; + + glSetLocalConstantEXT(id, type, addr); +} + +static void APIENTRY InitVariantbvEXT (GLuint id, const GLbyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantbvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantbvEXT = extproc; + + glVariantbvEXT(id, addr); +} + +static void APIENTRY InitVariantsvEXT (GLuint id, const GLshort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantsvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantsvEXT = extproc; + + glVariantsvEXT(id, addr); +} + +static void APIENTRY InitVariantivEXT (GLuint id, const GLint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantivEXT = extproc; + + glVariantivEXT(id, addr); +} + +static void APIENTRY InitVariantfvEXT (GLuint id, const GLfloat *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantfvEXT = extproc; + + glVariantfvEXT(id, addr); +} + +static void APIENTRY InitVariantdvEXT (GLuint id, const GLdouble *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantdvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantdvEXT = extproc; + + glVariantdvEXT(id, addr); +} + +static void APIENTRY InitVariantubvEXT (GLuint id, const GLubyte *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantubvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantubvEXT = extproc; + + glVariantubvEXT(id, addr); +} + +static void APIENTRY InitVariantusvEXT (GLuint id, const GLushort *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantusvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantusvEXT = extproc; + + glVariantusvEXT(id, addr); +} + +static void APIENTRY InitVariantuivEXT (GLuint id, const GLuint *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantuivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantuivEXT = extproc; + + glVariantuivEXT(id, addr); +} + +static void APIENTRY InitVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const GLvoid *addr) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVariantPointerEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVariantPointerEXT = extproc; + + glVariantPointerEXT(id, type, stride, addr); +} + +static void APIENTRY InitEnableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEnableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEnableVariantClientStateEXT = extproc; + + glEnableVariantClientStateEXT(id); +} + +static void APIENTRY InitDisableVariantClientStateEXT (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDisableVariantClientStateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDisableVariantClientStateEXT = extproc; + + glDisableVariantClientStateEXT(id); +} + +static GLuint APIENTRY InitBindLightParameterEXT (GLenum light, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindLightParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindLightParameterEXT = extproc; + + return glBindLightParameterEXT(light, value); +} + +static GLuint APIENTRY InitBindMaterialParameterEXT (GLenum face, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindMaterialParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindMaterialParameterEXT = extproc; + + return glBindMaterialParameterEXT(face, value); +} + +static GLuint APIENTRY InitBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTexGenParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTexGenParameterEXT = extproc; + + return glBindTexGenParameterEXT(unit, coord, value); +} + +static GLuint APIENTRY InitBindTextureUnitParameterEXT (GLenum unit, GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindTextureUnitParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindTextureUnitParameterEXT = extproc; + + return glBindTextureUnitParameterEXT(unit, value); +} + +static GLuint APIENTRY InitBindParameterEXT (GLenum value) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindParameterEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glBindParameterEXT = extproc; + + return glBindParameterEXT(value); +} + +static GLboolean APIENTRY InitIsVariantEnabledEXT (GLuint id, GLenum cap) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVariantEnabledEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVariantEnabledEXT = extproc; + + return glIsVariantEnabledEXT(id, cap); +} + +static void APIENTRY InitGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantBooleanvEXT = extproc; + + glGetVariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantIntegervEXT = extproc; + + glGetVariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantFloatvEXT = extproc; + + glGetVariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetVariantPointervEXT (GLuint id, GLenum value, GLvoid* *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVariantPointervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVariantPointervEXT = extproc; + + glGetVariantPointervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantBooleanvEXT = extproc; + + glGetInvariantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantIntegervEXT = extproc; + + glGetInvariantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetInvariantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetInvariantFloatvEXT = extproc; + + glGetInvariantFloatvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantBooleanvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantBooleanvEXT = extproc; + + glGetLocalConstantBooleanvEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantIntegervEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantIntegervEXT = extproc; + + glGetLocalConstantIntegervEXT(id, value, data); +} + +static void APIENTRY InitGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetLocalConstantFloatvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetLocalConstantFloatvEXT = extproc; + + glGetLocalConstantFloatvEXT(id, value, data); +} + +static void APIENTRY InitVertexStream1sATI (GLenum stream, GLshort x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1sATI = extproc; + + glVertexStream1sATI(stream, x); +} + +static void APIENTRY InitVertexStream1svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1svATI = extproc; + + glVertexStream1svATI(stream, coords); +} + +static void APIENTRY InitVertexStream1iATI (GLenum stream, GLint x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1iATI = extproc; + + glVertexStream1iATI(stream, x); +} + +static void APIENTRY InitVertexStream1ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1ivATI = extproc; + + glVertexStream1ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream1fATI (GLenum stream, GLfloat x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fATI = extproc; + + glVertexStream1fATI(stream, x); +} + +static void APIENTRY InitVertexStream1fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1fvATI = extproc; + + glVertexStream1fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream1dATI (GLenum stream, GLdouble x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dATI = extproc; + + glVertexStream1dATI(stream, x); +} + +static void APIENTRY InitVertexStream1dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream1dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream1dvATI = extproc; + + glVertexStream1dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2sATI (GLenum stream, GLshort x, GLshort y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2sATI = extproc; + + glVertexStream2sATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2svATI = extproc; + + glVertexStream2svATI(stream, coords); +} + +static void APIENTRY InitVertexStream2iATI (GLenum stream, GLint x, GLint y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2iATI = extproc; + + glVertexStream2iATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2ivATI = extproc; + + glVertexStream2ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fATI = extproc; + + glVertexStream2fATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2fvATI = extproc; + + glVertexStream2fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dATI = extproc; + + glVertexStream2dATI(stream, x, y); +} + +static void APIENTRY InitVertexStream2dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream2dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream2dvATI = extproc; + + glVertexStream2dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3sATI = extproc; + + glVertexStream3sATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3svATI = extproc; + + glVertexStream3svATI(stream, coords); +} + +static void APIENTRY InitVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3iATI = extproc; + + glVertexStream3iATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3ivATI = extproc; + + glVertexStream3ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fATI = extproc; + + glVertexStream3fATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3fvATI = extproc; + + glVertexStream3fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dATI = extproc; + + glVertexStream3dATI(stream, x, y, z); +} + +static void APIENTRY InitVertexStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream3dvATI = extproc; + + glVertexStream3dvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4sATI = extproc; + + glVertexStream4sATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4svATI = extproc; + + glVertexStream4svATI(stream, coords); +} + +static void APIENTRY InitVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4iATI = extproc; + + glVertexStream4iATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4ivATI = extproc; + + glVertexStream4ivATI(stream, coords); +} + +static void APIENTRY InitVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fATI = extproc; + + glVertexStream4fATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4fvATI = extproc; + + glVertexStream4fvATI(stream, coords); +} + +static void APIENTRY InitVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dATI = extproc; + + glVertexStream4dATI(stream, x, y, z, w); +} + +static void APIENTRY InitVertexStream4dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexStream4dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexStream4dvATI = extproc; + + glVertexStream4dvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bATI = extproc; + + glNormalStream3bATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3bvATI (GLenum stream, const GLbyte *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3bvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3bvATI = extproc; + + glNormalStream3bvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3sATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3sATI = extproc; + + glNormalStream3sATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3svATI (GLenum stream, const GLshort *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3svATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3svATI = extproc; + + glNormalStream3svATI(stream, coords); +} + +static void APIENTRY InitNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3iATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3iATI = extproc; + + glNormalStream3iATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3ivATI (GLenum stream, const GLint *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3ivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3ivATI = extproc; + + glNormalStream3ivATI(stream, coords); +} + +static void APIENTRY InitNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fATI = extproc; + + glNormalStream3fATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3fvATI (GLenum stream, const GLfloat *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3fvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3fvATI = extproc; + + glNormalStream3fvATI(stream, coords); +} + +static void APIENTRY InitNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dATI = extproc; + + glNormalStream3dATI(stream, nx, ny, nz); +} + +static void APIENTRY InitNormalStream3dvATI (GLenum stream, const GLdouble *coords) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormalStream3dvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormalStream3dvATI = extproc; + + glNormalStream3dvATI(stream, coords); +} + +static void APIENTRY InitClientActiveVertexStreamATI (GLenum stream) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glClientActiveVertexStreamATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glClientActiveVertexStreamATI = extproc; + + glClientActiveVertexStreamATI(stream); +} + +static void APIENTRY InitVertexBlendEnviATI (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnviATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnviATI = extproc; + + glVertexBlendEnviATI(pname, param); +} + +static void APIENTRY InitVertexBlendEnvfATI (GLenum pname, GLfloat param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexBlendEnvfATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexBlendEnvfATI = extproc; + + glVertexBlendEnvfATI(pname, param); +} + +static void APIENTRY InitElementPointerATI (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerATI = extproc; + + glElementPointerATI(type, pointer); +} + +static void APIENTRY InitDrawElementArrayATI (GLenum mode, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayATI = extproc; + + glDrawElementArrayATI(mode, count); +} + +static void APIENTRY InitDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayATI = extproc; + + glDrawRangeElementArrayATI(mode, start, end, count); +} + +static void APIENTRY InitDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawMeshArraysSUN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawMeshArraysSUN = extproc; + + glDrawMeshArraysSUN(mode, first, count, width); +} + +static void APIENTRY InitGenOcclusionQueriesNV (GLsizei n, GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenOcclusionQueriesNV = extproc; + + glGenOcclusionQueriesNV(n, ids); +} + +static void APIENTRY InitDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteOcclusionQueriesNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteOcclusionQueriesNV = extproc; + + glDeleteOcclusionQueriesNV(n, ids); +} + +static GLboolean APIENTRY InitIsOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsOcclusionQueryNV = extproc; + + return glIsOcclusionQueryNV(id); +} + +static void APIENTRY InitBeginOcclusionQueryNV (GLuint id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBeginOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBeginOcclusionQueryNV = extproc; + + glBeginOcclusionQueryNV(id); +} + +static void APIENTRY InitEndOcclusionQueryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glEndOcclusionQueryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glEndOcclusionQueryNV = extproc; + + glEndOcclusionQueryNV(); +} + +static void APIENTRY InitGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryivNV = extproc; + + glGetOcclusionQueryivNV(id, pname, params); +} + +static void APIENTRY InitGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetOcclusionQueryuivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetOcclusionQueryuivNV = extproc; + + glGetOcclusionQueryuivNV(id, pname, params); +} + +static void APIENTRY InitPointParameteriNV (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameteriNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameteriNV = extproc; + + glPointParameteriNV(pname, param); +} + +static void APIENTRY InitPointParameterivNV (GLenum pname, const GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPointParameterivNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPointParameterivNV = extproc; + + glPointParameterivNV(pname, params); +} + +static void APIENTRY InitActiveStencilFaceEXT (GLenum face) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glActiveStencilFaceEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glActiveStencilFaceEXT = extproc; + + glActiveStencilFaceEXT(face); +} + +static void APIENTRY InitElementPointerAPPLE (GLenum type, const GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glElementPointerAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glElementPointerAPPLE = extproc; + + glElementPointerAPPLE(type, pointer); +} + +static void APIENTRY InitDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawElementArrayAPPLE = extproc; + + glDrawElementArrayAPPLE(mode, first, count); +} + +static void APIENTRY InitDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawRangeElementArrayAPPLE = extproc; + + glDrawRangeElementArrayAPPLE(mode, start, end, first, count); +} + +static void APIENTRY InitMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawElementArrayAPPLE = extproc; + + glMultiDrawElementArrayAPPLE(mode, first, count, primcount); +} + +static void APIENTRY InitMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiDrawRangeElementArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiDrawRangeElementArrayAPPLE = extproc; + + glMultiDrawRangeElementArrayAPPLE(mode, start, end, first, count, primcount); +} + +static void APIENTRY InitGenFencesAPPLE (GLsizei n, GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenFencesAPPLE = extproc; + + glGenFencesAPPLE(n, fences); +} + +static void APIENTRY InitDeleteFencesAPPLE (GLsizei n, const GLuint *fences) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteFencesAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteFencesAPPLE = extproc; + + glDeleteFencesAPPLE(n, fences); +} + +static void APIENTRY InitSetFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSetFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSetFenceAPPLE = extproc; + + glSetFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitIsFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsFenceAPPLE = extproc; + + return glIsFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestFenceAPPLE = extproc; + + return glTestFenceAPPLE(fence); +} + +static void APIENTRY InitFinishFenceAPPLE (GLuint fence) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishFenceAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishFenceAPPLE = extproc; + + glFinishFenceAPPLE(fence); +} + +static GLboolean APIENTRY InitTestObjectAPPLE (GLenum object, GLuint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTestObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glTestObjectAPPLE = extproc; + + return glTestObjectAPPLE(object, name); +} + +static void APIENTRY InitFinishObjectAPPLE (GLenum object, GLint name) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFinishObjectAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFinishObjectAPPLE = extproc; + + glFinishObjectAPPLE(object, name); +} + +static void APIENTRY InitBindVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBindVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBindVertexArrayAPPLE = extproc; + + glBindVertexArrayAPPLE(array); +} + +static void APIENTRY InitDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDeleteVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDeleteVertexArraysAPPLE = extproc; + + glDeleteVertexArraysAPPLE(n, arrays); +} + +static void APIENTRY InitGenVertexArraysAPPLE (GLsizei n, const GLuint *arrays) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGenVertexArraysAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGenVertexArraysAPPLE = extproc; + + glGenVertexArraysAPPLE(n, arrays); +} + +static GLboolean APIENTRY InitIsVertexArrayAPPLE (GLuint array) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glIsVertexArrayAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glIsVertexArrayAPPLE = extproc; + + return glIsVertexArrayAPPLE(array); +} + +static void APIENTRY InitVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayRangeAPPLE = extproc; + + glVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitFlushVertexArrayRangeAPPLE (GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushVertexArrayRangeAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushVertexArrayRangeAPPLE = extproc; + + glFlushVertexArrayRangeAPPLE(length, pointer); +} + +static void APIENTRY InitVertexArrayParameteriAPPLE (GLenum pname, GLint param) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexArrayParameteriAPPLE"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexArrayParameteriAPPLE = extproc; + + glVertexArrayParameteriAPPLE(pname, param); +} + +static void APIENTRY InitDrawBuffersATI (GLsizei n, const GLenum *bufs) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDrawBuffersATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDrawBuffersATI = extproc; + + glDrawBuffersATI(n, bufs); +} + +static void APIENTRY InitProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fNV = extproc; + + glProgramNamedParameter4fNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dNV = extproc; + + glProgramNamedParameter4dNV(id, len, name, x, y, z, w); +} + +static void APIENTRY InitProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4fvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4fvNV = extproc; + + glProgramNamedParameter4fvNV(id, len, name, v); +} + +static void APIENTRY InitProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glProgramNamedParameter4dvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glProgramNamedParameter4dvNV = extproc; + + glProgramNamedParameter4dvNV(id, len, name, v); +} + +static void APIENTRY InitGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterfvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterfvNV = extproc; + + glGetProgramNamedParameterfvNV(id, len, name, params); +} + +static void APIENTRY InitGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetProgramNamedParameterdvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetProgramNamedParameterdvNV = extproc; + + glGetProgramNamedParameterdvNV(id, len, name, params); +} + +static void APIENTRY InitVertex2hNV (GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hNV = extproc; + + glVertex2hNV(x, y); +} + +static void APIENTRY InitVertex2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex2hvNV = extproc; + + glVertex2hvNV(v); +} + +static void APIENTRY InitVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hNV = extproc; + + glVertex3hNV(x, y, z); +} + +static void APIENTRY InitVertex3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex3hvNV = extproc; + + glVertex3hvNV(v); +} + +static void APIENTRY InitVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hNV = extproc; + + glVertex4hNV(x, y, z, w); +} + +static void APIENTRY InitVertex4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertex4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertex4hvNV = extproc; + + glVertex4hvNV(v); +} + +static void APIENTRY InitNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hNV = extproc; + + glNormal3hNV(nx, ny, nz); +} + +static void APIENTRY InitNormal3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glNormal3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glNormal3hvNV = extproc; + + glNormal3hvNV(v); +} + +static void APIENTRY InitColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hNV = extproc; + + glColor3hNV(red, green, blue); +} + +static void APIENTRY InitColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor3hvNV = extproc; + + glColor3hvNV(v); +} + +static void APIENTRY InitColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hNV = extproc; + + glColor4hNV(red, green, blue, alpha); +} + +static void APIENTRY InitColor4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glColor4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glColor4hvNV = extproc; + + glColor4hvNV(v); +} + +static void APIENTRY InitTexCoord1hNV (GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hNV = extproc; + + glTexCoord1hNV(s); +} + +static void APIENTRY InitTexCoord1hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord1hvNV = extproc; + + glTexCoord1hvNV(v); +} + +static void APIENTRY InitTexCoord2hNV (GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hNV = extproc; + + glTexCoord2hNV(s, t); +} + +static void APIENTRY InitTexCoord2hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord2hvNV = extproc; + + glTexCoord2hvNV(v); +} + +static void APIENTRY InitTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hNV = extproc; + + glTexCoord3hNV(s, t, r); +} + +static void APIENTRY InitTexCoord3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord3hvNV = extproc; + + glTexCoord3hvNV(v); +} + +static void APIENTRY InitTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hNV = extproc; + + glTexCoord4hNV(s, t, r, q); +} + +static void APIENTRY InitTexCoord4hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glTexCoord4hvNV = extproc; + + glTexCoord4hvNV(v); +} + +static void APIENTRY InitMultiTexCoord1hNV (GLenum target, GLhalfNV s) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hNV = extproc; + + glMultiTexCoord1hNV(target, s); +} + +static void APIENTRY InitMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord1hvNV = extproc; + + glMultiTexCoord1hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hNV = extproc; + + glMultiTexCoord2hNV(target, s, t); +} + +static void APIENTRY InitMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord2hvNV = extproc; + + glMultiTexCoord2hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hNV = extproc; + + glMultiTexCoord3hNV(target, s, t, r); +} + +static void APIENTRY InitMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord3hvNV = extproc; + + glMultiTexCoord3hvNV(target, v); +} + +static void APIENTRY InitMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hNV = extproc; + + glMultiTexCoord4hNV(target, s, t, r, q); +} + +static void APIENTRY InitMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMultiTexCoord4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glMultiTexCoord4hvNV = extproc; + + glMultiTexCoord4hvNV(target, v); +} + +static void APIENTRY InitFogCoordhNV (GLhalfNV fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhNV = extproc; + + glFogCoordhNV(fog); +} + +static void APIENTRY InitFogCoordhvNV (const GLhalfNV *fog) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFogCoordhvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFogCoordhvNV = extproc; + + glFogCoordhvNV(fog); +} + +static void APIENTRY InitSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hNV = extproc; + + glSecondaryColor3hNV(red, green, blue); +} + +static void APIENTRY InitSecondaryColor3hvNV (const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glSecondaryColor3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glSecondaryColor3hvNV = extproc; + + glSecondaryColor3hvNV(v); +} + +static void APIENTRY InitVertexWeighthNV (GLhalfNV weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthNV = extproc; + + glVertexWeighthNV(weight); +} + +static void APIENTRY InitVertexWeighthvNV (const GLhalfNV *weight) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexWeighthvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexWeighthvNV = extproc; + + glVertexWeighthvNV(weight); +} + +static void APIENTRY InitVertexAttrib1hNV (GLuint index, GLhalfNV x) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hNV = extproc; + + glVertexAttrib1hNV(index, x); +} + +static void APIENTRY InitVertexAttrib1hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib1hvNV = extproc; + + glVertexAttrib1hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hNV = extproc; + + glVertexAttrib2hNV(index, x, y); +} + +static void APIENTRY InitVertexAttrib2hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib2hvNV = extproc; + + glVertexAttrib2hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hNV = extproc; + + glVertexAttrib3hNV(index, x, y, z); +} + +static void APIENTRY InitVertexAttrib3hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib3hvNV = extproc; + + glVertexAttrib3hvNV(index, v); +} + +static void APIENTRY InitVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hNV = extproc; + + glVertexAttrib4hNV(index, x, y, z, w); +} + +static void APIENTRY InitVertexAttrib4hvNV (GLuint index, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttrib4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttrib4hvNV = extproc; + + glVertexAttrib4hvNV(index, v); +} + +static void APIENTRY InitVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs1hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs1hvNV = extproc; + + glVertexAttribs1hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs2hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs2hvNV = extproc; + + glVertexAttribs2hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs3hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs3hvNV = extproc; + + glVertexAttribs3hvNV(index, n, v); +} + +static void APIENTRY InitVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribs4hvNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribs4hvNV = extproc; + + glVertexAttribs4hvNV(index, n, v); +} + +static void APIENTRY InitPixelDataRangeNV (GLenum target, GLsizei length, GLvoid *pointer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPixelDataRangeNV = extproc; + + glPixelDataRangeNV(target, length, pointer); +} + +static void APIENTRY InitFlushPixelDataRangeNV (GLenum target) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glFlushPixelDataRangeNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glFlushPixelDataRangeNV = extproc; + + glFlushPixelDataRangeNV(target); +} + +static void APIENTRY InitPrimitiveRestartNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartNV = extproc; + + glPrimitiveRestartNV(); +} + +static void APIENTRY InitPrimitiveRestartIndexNV (GLuint index) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glPrimitiveRestartIndexNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glPrimitiveRestartIndexNV = extproc; + + glPrimitiveRestartIndexNV(index); +} + +static GLvoid* APIENTRY InitMapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glMapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + glMapObjectBufferATI = extproc; + + return glMapObjectBufferATI(buffer); +} + +static void APIENTRY InitUnmapObjectBufferATI (GLuint buffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glUnmapObjectBufferATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glUnmapObjectBufferATI = extproc; + + glUnmapObjectBufferATI(buffer); +} + +static void APIENTRY InitStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilOpSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilOpSeparateATI = extproc; + + glStencilOpSeparateATI(face, sfail, dpfail, dppass); +} + +static void APIENTRY InitStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glStencilFuncSeparateATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glStencilFuncSeparateATI = extproc; + + glStencilFuncSeparateATI(frontfunc, backfunc, ref, mask); +} + +static void APIENTRY InitVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glVertexAttribArrayObjectATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glVertexAttribArrayObjectATI = extproc; + + glVertexAttribArrayObjectATI(index, size, type, normalized, stride, buffer, offset); +} + +static void APIENTRY InitGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectfvATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectfvATI = extproc; + + glGetVertexAttribArrayObjectfvATI(index, pname, params); +} + +static void APIENTRY InitGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glGetVertexAttribArrayObjectivATI"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glGetVertexAttribArrayObjectivATI = extproc; + + glGetVertexAttribArrayObjectivATI(index, pname, params); +} + +static void APIENTRY InitDepthBoundsEXT (GLclampd zmin, GLclampd zmax) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glDepthBoundsEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glDepthBoundsEXT = extproc; + + glDepthBoundsEXT(zmin, zmax); +} + +static void APIENTRY InitBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glBlendEquationSeparateEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glBlendEquationSeparateEXT = extproc; + + glBlendEquationSeparateEXT(modeRGB, modeAlpha); +} + +static void APIENTRY InitAddSwapHintRectWIN (GLint x, GLint y, GLsizei width, GLsizei height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("glAddSwapHintRectWIN"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + glAddSwapHintRectWIN = extproc; + + glAddSwapHintRectWIN(x, y, width, height); +} + +#ifdef _WIN32 + +static HANDLE WINAPI InitCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateBufferRegionARB = extproc; + + return wglCreateBufferRegionARB(hDC, iLayerPlane, uType); +} + +static VOID WINAPI InitDeleteBufferRegionARB (HANDLE hRegion) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDeleteBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDeleteBufferRegionARB = extproc; + + wglDeleteBufferRegionARB(hRegion); +} + +static BOOL WINAPI InitSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSaveBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSaveBufferRegionARB = extproc; + + return wglSaveBufferRegionARB(hRegion, x, y, width, height); +} + +static BOOL WINAPI InitRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglRestoreBufferRegionARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglRestoreBufferRegionARB = extproc; + + return wglRestoreBufferRegionARB(hRegion, x, y, width, height, xSrc, ySrc); +} + +static const WINAPI InitGetExtensionsStringARB (HDC hdc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringARB = extproc; + + return wglGetExtensionsStringARB(hdc); +} + +static BOOL WINAPI InitGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivARB = extproc; + + return wglGetPixelFormatAttribivARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvARB = extproc; + + return wglGetPixelFormatAttribfvARB(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatARB = extproc; + + return wglChoosePixelFormatARB(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentARB = extproc; + + return wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCARB (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCARB = extproc; + + return wglGetCurrentReadDCARB(); +} + +static HPBUFFERARB WINAPI InitCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferARB = extproc; + + return wglCreatePbufferARB(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCARB = extproc; + + return wglGetPbufferDCARB(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCARB = extproc; + + return wglReleasePbufferDCARB(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferARB (HPBUFFERARB hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferARB = extproc; + + return wglDestroyPbufferARB(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferARB = extproc; + + return wglQueryPbufferARB(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindTexImageARB = extproc; + + return wglBindTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseTexImageARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseTexImageARB = extproc; + + return wglReleaseTexImageARB(hPbuffer, iBuffer); +} + +static BOOL WINAPI InitSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetPbufferAttribARB"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetPbufferAttribARB = extproc; + + return wglSetPbufferAttribARB(hPbuffer, piAttribList); +} + +static GLboolean WINAPI InitCreateDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateDisplayColorTableEXT = extproc; + + return wglCreateDisplayColorTableEXT(id); +} + +static GLboolean WINAPI InitLoadDisplayColorTableEXT (const GLushort *table, GLuint length) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglLoadDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglLoadDisplayColorTableEXT = extproc; + + return wglLoadDisplayColorTableEXT(table, length); +} + +static GLboolean WINAPI InitBindDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBindDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBindDisplayColorTableEXT = extproc; + + return wglBindDisplayColorTableEXT(id); +} + +static VOID WINAPI InitDestroyDisplayColorTableEXT (GLushort id) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyDisplayColorTableEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglDestroyDisplayColorTableEXT = extproc; + + wglDestroyDisplayColorTableEXT(id); +} + +static const WINAPI InitGetExtensionsStringEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetExtensionsStringEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetExtensionsStringEXT = extproc; + + return wglGetExtensionsStringEXT(); +} + +static BOOL WINAPI InitMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglMakeContextCurrentEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglMakeContextCurrentEXT = extproc; + + return wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); +} + +static HDC WINAPI InitGetCurrentReadDCEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetCurrentReadDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetCurrentReadDCEXT = extproc; + + return wglGetCurrentReadDCEXT(); +} + +static HPBUFFEREXT WINAPI InitCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreatePbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreatePbufferEXT = extproc; + + return wglCreatePbufferEXT(hDC, iPixelFormat, iWidth, iHeight, piAttribList); +} + +static HDC WINAPI InitGetPbufferDCEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPbufferDCEXT = extproc; + + return wglGetPbufferDCEXT(hPbuffer); +} + +static int WINAPI InitReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleasePbufferDCEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleasePbufferDCEXT = extproc; + + return wglReleasePbufferDCEXT(hPbuffer, hDC); +} + +static BOOL WINAPI InitDestroyPbufferEXT (HPBUFFEREXT hPbuffer) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyPbufferEXT = extproc; + + return wglDestroyPbufferEXT(hPbuffer); +} + +static BOOL WINAPI InitQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryPbufferEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryPbufferEXT = extproc; + + return wglQueryPbufferEXT(hPbuffer, iAttribute, piValue); +} + +static BOOL WINAPI InitGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribivEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribivEXT = extproc; + + return wglGetPixelFormatAttribivEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); +} + +static BOOL WINAPI InitGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetPixelFormatAttribfvEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetPixelFormatAttribfvEXT = extproc; + + return wglGetPixelFormatAttribfvEXT(hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, pfValues); +} + +static BOOL WINAPI InitChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglChoosePixelFormatEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglChoosePixelFormatEXT = extproc; + + return wglChoosePixelFormatEXT(hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); +} + +static BOOL WINAPI InitSwapIntervalEXT (int interval) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapIntervalEXT = extproc; + + return wglSwapIntervalEXT(interval); +} + +static int WINAPI InitGetSwapIntervalEXT (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSwapIntervalEXT"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSwapIntervalEXT = extproc; + + return wglGetSwapIntervalEXT(); +} + +static void* WINAPI InitAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAllocateMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAllocateMemoryNV = extproc; + + return wglAllocateMemoryNV(size, readfreq, writefreq, priority); +} + +static void WINAPI InitFreeMemoryNV (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglFreeMemoryNV"); + + if (extproc == NULL) { + _ASSERT(0); + return; + } + + wglFreeMemoryNV = extproc; + + wglFreeMemoryNV(); +} + +static BOOL WINAPI InitGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetSyncValuesOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetSyncValuesOML = extproc; + + return wglGetSyncValuesOML(hdc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetMscRateOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetMscRateOML = extproc; + + return wglGetMscRateOML(hdc, numerator, denominator); +} + +static INT64 WINAPI InitSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapBuffersMscOML = extproc; + + return wglSwapBuffersMscOML(hdc, target_msc, divisor, remainder); +} + +static INT64 WINAPI InitSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSwapLayerBuffersMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSwapLayerBuffersMscOML = extproc; + + return wglSwapLayerBuffersMscOML(hdc, fuPlanes, target_msc, divisor, remainder); +} + +static BOOL WINAPI InitWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForMscOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForMscOML = extproc; + + return wglWaitForMscOML(hdc, target_msc, divisor, remainder, ust, msc, sbc); +} + +static BOOL WINAPI InitWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglWaitForSbcOML"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglWaitForSbcOML = extproc; + + return wglWaitForSbcOML(hdc, target_sbc, ust, msc, sbc); +} + +static BOOL WINAPI InitGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetDigitalVideoParametersI3D = extproc; + + return wglGetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetDigitalVideoParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetDigitalVideoParametersI3D = extproc; + + return wglSetDigitalVideoParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableParametersI3D = extproc; + + return wglGetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableParametersI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableParametersI3D = extproc; + + return wglSetGammaTableParametersI3D(hDC, iAttribute, piValue); +} + +static BOOL WINAPI InitGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGammaTableI3D = extproc; + + return wglGetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglSetGammaTableI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglSetGammaTableI3D = extproc; + + return wglSetGammaTableI3D(hDC, iEntries, puRed, puGreen, puBlue); +} + +static BOOL WINAPI InitEnableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableGenlockI3D = extproc; + + return wglEnableGenlockI3D(hDC); +} + +static BOOL WINAPI InitDisableGenlockI3D (HDC hDC) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableGenlockI3D = extproc; + + return wglDisableGenlockI3D(hDC); +} + +static BOOL WINAPI InitIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledGenlockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledGenlockI3D = extproc; + + return wglIsEnabledGenlockI3D(hDC, pFlag); +} + +static BOOL WINAPI InitGenlockSourceI3D (HDC hDC, UINT uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceI3D = extproc; + + return wglGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGetGenlockSourceI3D (HDC hDC, UINT *uSource) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceI3D = extproc; + + return wglGetGenlockSourceI3D(hDC, uSource); +} + +static BOOL WINAPI InitGenlockSourceEdgeI3D (HDC hDC, UINT uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceEdgeI3D = extproc; + + return wglGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceEdgeI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceEdgeI3D = extproc; + + return wglGetGenlockSourceEdgeI3D(hDC, uEdge); +} + +static BOOL WINAPI InitGenlockSampleRateI3D (HDC hDC, UINT uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSampleRateI3D = extproc; + + return wglGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGetGenlockSampleRateI3D (HDC hDC, UINT *uRate) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSampleRateI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSampleRateI3D = extproc; + + return wglGetGenlockSampleRateI3D(hDC, uRate); +} + +static BOOL WINAPI InitGenlockSourceDelayI3D (HDC hDC, UINT uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGenlockSourceDelayI3D = extproc; + + return wglGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetGenlockSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetGenlockSourceDelayI3D = extproc; + + return wglGetGenlockSourceDelayI3D(hDC, uDelay); +} + +static BOOL WINAPI InitQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryGenlockMaxSourceDelayI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryGenlockMaxSourceDelayI3D = extproc; + + return wglQueryGenlockMaxSourceDelayI3D(hDC, uMaxLineDelay, uMaxPixelDelay); +} + +static LPVOID WINAPI InitCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglCreateImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglCreateImageBufferI3D = extproc; + + return wglCreateImageBufferI3D(hDC, dwSize, uFlags); +} + +static BOOL WINAPI InitDestroyImageBufferI3D (HDC hDC, LPVOID pAddress) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDestroyImageBufferI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDestroyImageBufferI3D = extproc; + + return wglDestroyImageBufferI3D(hDC, pAddress); +} + +static BOOL WINAPI InitAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglAssociateImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglAssociateImageBufferEventsI3D = extproc; + + return wglAssociateImageBufferEventsI3D(hDC, pEvent, pAddress, pSize, count); +} + +static BOOL WINAPI InitReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglReleaseImageBufferEventsI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglReleaseImageBufferEventsI3D = extproc; + + return wglReleaseImageBufferEventsI3D(hDC, pAddress, count); +} + +static BOOL WINAPI InitEnableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEnableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEnableFrameLockI3D = extproc; + + return wglEnableFrameLockI3D(); +} + +static BOOL WINAPI InitDisableFrameLockI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglDisableFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglDisableFrameLockI3D = extproc; + + return wglDisableFrameLockI3D(); +} + +static BOOL WINAPI InitIsEnabledFrameLockI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglIsEnabledFrameLockI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglIsEnabledFrameLockI3D = extproc; + + return wglIsEnabledFrameLockI3D(pFlag); +} + +static BOOL WINAPI InitQueryFrameLockMasterI3D (BOOL *pFlag) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameLockMasterI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameLockMasterI3D = extproc; + + return wglQueryFrameLockMasterI3D(pFlag); +} + +static BOOL WINAPI InitGetFrameUsageI3D (float *pUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglGetFrameUsageI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglGetFrameUsageI3D = extproc; + + return wglGetFrameUsageI3D(pUsage); +} + +static BOOL WINAPI InitBeginFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglBeginFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglBeginFrameTrackingI3D = extproc; + + return wglBeginFrameTrackingI3D(); +} + +static BOOL WINAPI InitEndFrameTrackingI3D (void) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglEndFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglEndFrameTrackingI3D = extproc; + + return wglEndFrameTrackingI3D(); +} + +static BOOL WINAPI InitQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage) +{ + void *extproc; + + extproc = (void *) wglGetProcAddress("wglQueryFrameTrackingI3D"); + + if (extproc == NULL) { + _ASSERT(0); + return 0; + } + + wglQueryFrameTrackingI3D = extproc; + + return wglQueryFrameTrackingI3D(pFrameCount, pMissedFrames, pLastMissedUsage); +} + +#endif /* _WIN32 */ + +_GLextensionProcs _extensionProcs = { + InitBlendColor, + InitBlendEquation, + InitDrawRangeElements, + InitColorTable, + InitColorTableParameterfv, + InitColorTableParameteriv, + InitCopyColorTable, + InitGetColorTable, + InitGetColorTableParameterfv, + InitGetColorTableParameteriv, + InitColorSubTable, + InitCopyColorSubTable, + InitConvolutionFilter1D, + InitConvolutionFilter2D, + InitConvolutionParameterf, + InitConvolutionParameterfv, + InitConvolutionParameteri, + InitConvolutionParameteriv, + InitCopyConvolutionFilter1D, + InitCopyConvolutionFilter2D, + InitGetConvolutionFilter, + InitGetConvolutionParameterfv, + InitGetConvolutionParameteriv, + InitGetSeparableFilter, + InitSeparableFilter2D, + InitGetHistogram, + InitGetHistogramParameterfv, + InitGetHistogramParameteriv, + InitGetMinmax, + InitGetMinmaxParameterfv, + InitGetMinmaxParameteriv, + InitHistogram, + InitMinmax, + InitResetHistogram, + InitResetMinmax, + InitTexImage3D, + InitTexSubImage3D, + InitCopyTexSubImage3D, + InitActiveTexture, + InitClientActiveTexture, + InitMultiTexCoord1d, + InitMultiTexCoord1dv, + InitMultiTexCoord1f, + InitMultiTexCoord1fv, + InitMultiTexCoord1i, + InitMultiTexCoord1iv, + InitMultiTexCoord1s, + InitMultiTexCoord1sv, + InitMultiTexCoord2d, + InitMultiTexCoord2dv, + InitMultiTexCoord2f, + InitMultiTexCoord2fv, + InitMultiTexCoord2i, + InitMultiTexCoord2iv, + InitMultiTexCoord2s, + InitMultiTexCoord2sv, + InitMultiTexCoord3d, + InitMultiTexCoord3dv, + InitMultiTexCoord3f, + InitMultiTexCoord3fv, + InitMultiTexCoord3i, + InitMultiTexCoord3iv, + InitMultiTexCoord3s, + InitMultiTexCoord3sv, + InitMultiTexCoord4d, + InitMultiTexCoord4dv, + InitMultiTexCoord4f, + InitMultiTexCoord4fv, + InitMultiTexCoord4i, + InitMultiTexCoord4iv, + InitMultiTexCoord4s, + InitMultiTexCoord4sv, + InitLoadTransposeMatrixf, + InitLoadTransposeMatrixd, + InitMultTransposeMatrixf, + InitMultTransposeMatrixd, + InitSampleCoverage, + InitCompressedTexImage3D, + InitCompressedTexImage2D, + InitCompressedTexImage1D, + InitCompressedTexSubImage3D, + InitCompressedTexSubImage2D, + InitCompressedTexSubImage1D, + InitGetCompressedTexImage, + InitBlendFuncSeparate, + InitFogCoordf, + InitFogCoordfv, + InitFogCoordd, + InitFogCoorddv, + InitFogCoordPointer, + InitMultiDrawArrays, + InitMultiDrawElements, + InitPointParameterf, + InitPointParameterfv, + InitPointParameteri, + InitPointParameteriv, + InitSecondaryColor3b, + InitSecondaryColor3bv, + InitSecondaryColor3d, + InitSecondaryColor3dv, + InitSecondaryColor3f, + InitSecondaryColor3fv, + InitSecondaryColor3i, + InitSecondaryColor3iv, + InitSecondaryColor3s, + InitSecondaryColor3sv, + InitSecondaryColor3ub, + InitSecondaryColor3ubv, + InitSecondaryColor3ui, + InitSecondaryColor3uiv, + InitSecondaryColor3us, + InitSecondaryColor3usv, + InitSecondaryColorPointer, + InitWindowPos2d, + InitWindowPos2dv, + InitWindowPos2f, + InitWindowPos2fv, + InitWindowPos2i, + InitWindowPos2iv, + InitWindowPos2s, + InitWindowPos2sv, + InitWindowPos3d, + InitWindowPos3dv, + InitWindowPos3f, + InitWindowPos3fv, + InitWindowPos3i, + InitWindowPos3iv, + InitWindowPos3s, + InitWindowPos3sv, + InitGenQueries, + InitDeleteQueries, + InitIsQuery, + InitBeginQuery, + InitEndQuery, + InitGetQueryiv, + InitGetQueryObjectiv, + InitGetQueryObjectuiv, + InitBindBuffer, + InitDeleteBuffers, + InitGenBuffers, + InitIsBuffer, + InitBufferData, + InitBufferSubData, + InitGetBufferSubData, + InitMapBuffer, + InitUnmapBuffer, + InitGetBufferParameteriv, + InitGetBufferPointerv, + InitActiveTextureARB, + InitClientActiveTextureARB, + InitMultiTexCoord1dARB, + InitMultiTexCoord1dvARB, + InitMultiTexCoord1fARB, + InitMultiTexCoord1fvARB, + InitMultiTexCoord1iARB, + InitMultiTexCoord1ivARB, + InitMultiTexCoord1sARB, + InitMultiTexCoord1svARB, + InitMultiTexCoord2dARB, + InitMultiTexCoord2dvARB, + InitMultiTexCoord2fARB, + InitMultiTexCoord2fvARB, + InitMultiTexCoord2iARB, + InitMultiTexCoord2ivARB, + InitMultiTexCoord2sARB, + InitMultiTexCoord2svARB, + InitMultiTexCoord3dARB, + InitMultiTexCoord3dvARB, + InitMultiTexCoord3fARB, + InitMultiTexCoord3fvARB, + InitMultiTexCoord3iARB, + InitMultiTexCoord3ivARB, + InitMultiTexCoord3sARB, + InitMultiTexCoord3svARB, + InitMultiTexCoord4dARB, + InitMultiTexCoord4dvARB, + InitMultiTexCoord4fARB, + InitMultiTexCoord4fvARB, + InitMultiTexCoord4iARB, + InitMultiTexCoord4ivARB, + InitMultiTexCoord4sARB, + InitMultiTexCoord4svARB, + InitLoadTransposeMatrixfARB, + InitLoadTransposeMatrixdARB, + InitMultTransposeMatrixfARB, + InitMultTransposeMatrixdARB, + InitSampleCoverageARB, + InitCompressedTexImage3DARB, + InitCompressedTexImage2DARB, + InitCompressedTexImage1DARB, + InitCompressedTexSubImage3DARB, + InitCompressedTexSubImage2DARB, + InitCompressedTexSubImage1DARB, + InitGetCompressedTexImageARB, + InitPointParameterfARB, + InitPointParameterfvARB, + InitWeightbvARB, + InitWeightsvARB, + InitWeightivARB, + InitWeightfvARB, + InitWeightdvARB, + InitWeightubvARB, + InitWeightusvARB, + InitWeightuivARB, + InitWeightPointerARB, + InitVertexBlendARB, + InitCurrentPaletteMatrixARB, + InitMatrixIndexubvARB, + InitMatrixIndexusvARB, + InitMatrixIndexuivARB, + InitMatrixIndexPointerARB, + InitWindowPos2dARB, + InitWindowPos2dvARB, + InitWindowPos2fARB, + InitWindowPos2fvARB, + InitWindowPos2iARB, + InitWindowPos2ivARB, + InitWindowPos2sARB, + InitWindowPos2svARB, + InitWindowPos3dARB, + InitWindowPos3dvARB, + InitWindowPos3fARB, + InitWindowPos3fvARB, + InitWindowPos3iARB, + InitWindowPos3ivARB, + InitWindowPos3sARB, + InitWindowPos3svARB, + InitVertexAttrib1dARB, + InitVertexAttrib1dvARB, + InitVertexAttrib1fARB, + InitVertexAttrib1fvARB, + InitVertexAttrib1sARB, + InitVertexAttrib1svARB, + InitVertexAttrib2dARB, + InitVertexAttrib2dvARB, + InitVertexAttrib2fARB, + InitVertexAttrib2fvARB, + InitVertexAttrib2sARB, + InitVertexAttrib2svARB, + InitVertexAttrib3dARB, + InitVertexAttrib3dvARB, + InitVertexAttrib3fARB, + InitVertexAttrib3fvARB, + InitVertexAttrib3sARB, + InitVertexAttrib3svARB, + InitVertexAttrib4NbvARB, + InitVertexAttrib4NivARB, + InitVertexAttrib4NsvARB, + InitVertexAttrib4NubARB, + InitVertexAttrib4NubvARB, + InitVertexAttrib4NuivARB, + InitVertexAttrib4NusvARB, + InitVertexAttrib4bvARB, + InitVertexAttrib4dARB, + InitVertexAttrib4dvARB, + InitVertexAttrib4fARB, + InitVertexAttrib4fvARB, + InitVertexAttrib4ivARB, + InitVertexAttrib4sARB, + InitVertexAttrib4svARB, + InitVertexAttrib4ubvARB, + InitVertexAttrib4uivARB, + InitVertexAttrib4usvARB, + InitVertexAttribPointerARB, + InitEnableVertexAttribArrayARB, + InitDisableVertexAttribArrayARB, + InitProgramStringARB, + InitBindProgramARB, + InitDeleteProgramsARB, + InitGenProgramsARB, + InitProgramEnvParameter4dARB, + InitProgramEnvParameter4dvARB, + InitProgramEnvParameter4fARB, + InitProgramEnvParameter4fvARB, + InitProgramLocalParameter4dARB, + InitProgramLocalParameter4dvARB, + InitProgramLocalParameter4fARB, + InitProgramLocalParameter4fvARB, + InitGetProgramEnvParameterdvARB, + InitGetProgramEnvParameterfvARB, + InitGetProgramLocalParameterdvARB, + InitGetProgramLocalParameterfvARB, + InitGetProgramivARB, + InitGetProgramStringARB, + InitGetVertexAttribdvARB, + InitGetVertexAttribfvARB, + InitGetVertexAttribivARB, + InitGetVertexAttribPointervARB, + InitIsProgramARB, + InitBindBufferARB, + InitDeleteBuffersARB, + InitGenBuffersARB, + InitIsBufferARB, + InitBufferDataARB, + InitBufferSubDataARB, + InitGetBufferSubDataARB, + InitMapBufferARB, + InitUnmapBufferARB, + InitGetBufferParameterivARB, + InitGetBufferPointervARB, + InitGenQueriesARB, + InitDeleteQueriesARB, + InitIsQueryARB, + InitBeginQueryARB, + InitEndQueryARB, + InitGetQueryivARB, + InitGetQueryObjectivARB, + InitGetQueryObjectuivARB, + InitDeleteObjectARB, + InitGetHandleARB, + InitDetachObjectARB, + InitCreateShaderObjectARB, + InitShaderSourceARB, + InitCompileShaderARB, + InitCreateProgramObjectARB, + InitAttachObjectARB, + InitLinkProgramARB, + InitUseProgramObjectARB, + InitValidateProgramARB, + InitUniform1fARB, + InitUniform2fARB, + InitUniform3fARB, + InitUniform4fARB, + InitUniform1iARB, + InitUniform2iARB, + InitUniform3iARB, + InitUniform4iARB, + InitUniform1fvARB, + InitUniform2fvARB, + InitUniform3fvARB, + InitUniform4fvARB, + InitUniform1ivARB, + InitUniform2ivARB, + InitUniform3ivARB, + InitUniform4ivARB, + InitUniformMatrix2fvARB, + InitUniformMatrix3fvARB, + InitUniformMatrix4fvARB, + InitGetObjectParameterfvARB, + InitGetObjectParameterivARB, + InitGetInfoLogARB, + InitGetAttachedObjectsARB, + InitGetUniformLocationARB, + InitGetActiveUniformARB, + InitGetUniformfvARB, + InitGetUniformivARB, + InitGetShaderSourceARB, + InitBindAttribLocationARB, + InitGetActiveAttribARB, + InitGetAttribLocationARB, + InitBlendColorEXT, + InitPolygonOffsetEXT, + InitTexImage3DEXT, + InitTexSubImage3DEXT, + InitGetTexFilterFuncSGIS, + InitTexFilterFuncSGIS, + InitTexSubImage1DEXT, + InitTexSubImage2DEXT, + InitCopyTexImage1DEXT, + InitCopyTexImage2DEXT, + InitCopyTexSubImage1DEXT, + InitCopyTexSubImage2DEXT, + InitCopyTexSubImage3DEXT, + InitGetHistogramEXT, + InitGetHistogramParameterfvEXT, + InitGetHistogramParameterivEXT, + InitGetMinmaxEXT, + InitGetMinmaxParameterfvEXT, + InitGetMinmaxParameterivEXT, + InitHistogramEXT, + InitMinmaxEXT, + InitResetHistogramEXT, + InitResetMinmaxEXT, + InitConvolutionFilter1DEXT, + InitConvolutionFilter2DEXT, + InitConvolutionParameterfEXT, + InitConvolutionParameterfvEXT, + InitConvolutionParameteriEXT, + InitConvolutionParameterivEXT, + InitCopyConvolutionFilter1DEXT, + InitCopyConvolutionFilter2DEXT, + InitGetConvolutionFilterEXT, + InitGetConvolutionParameterfvEXT, + InitGetConvolutionParameterivEXT, + InitGetSeparableFilterEXT, + InitSeparableFilter2DEXT, + InitColorTableSGI, + InitColorTableParameterfvSGI, + InitColorTableParameterivSGI, + InitCopyColorTableSGI, + InitGetColorTableSGI, + InitGetColorTableParameterfvSGI, + InitGetColorTableParameterivSGI, + InitPixelTexGenSGIX, + InitPixelTexGenParameteriSGIS, + InitPixelTexGenParameterivSGIS, + InitPixelTexGenParameterfSGIS, + InitPixelTexGenParameterfvSGIS, + InitGetPixelTexGenParameterivSGIS, + InitGetPixelTexGenParameterfvSGIS, + InitTexImage4DSGIS, + InitTexSubImage4DSGIS, + InitAreTexturesResidentEXT, + InitBindTextureEXT, + InitDeleteTexturesEXT, + InitGenTexturesEXT, + InitIsTextureEXT, + InitPrioritizeTexturesEXT, + InitDetailTexFuncSGIS, + InitGetDetailTexFuncSGIS, + InitSharpenTexFuncSGIS, + InitGetSharpenTexFuncSGIS, + InitSampleMaskSGIS, + InitSamplePatternSGIS, + InitArrayElementEXT, + InitColorPointerEXT, + InitDrawArraysEXT, + InitEdgeFlagPointerEXT, + InitGetPointervEXT, + InitIndexPointerEXT, + InitNormalPointerEXT, + InitTexCoordPointerEXT, + InitVertexPointerEXT, + InitBlendEquationEXT, + InitSpriteParameterfSGIX, + InitSpriteParameterfvSGIX, + InitSpriteParameteriSGIX, + InitSpriteParameterivSGIX, + InitPointParameterfEXT, + InitPointParameterfvEXT, + InitPointParameterfSGIS, + InitPointParameterfvSGIS, + InitGetInstrumentsSGIX, + InitInstrumentsBufferSGIX, + InitPollInstrumentsSGIX, + InitReadInstrumentsSGIX, + InitStartInstrumentsSGIX, + InitStopInstrumentsSGIX, + InitFrameZoomSGIX, + InitTagSampleBufferSGIX, + InitDeformationMap3dSGIX, + InitDeformationMap3fSGIX, + InitDeformSGIX, + InitLoadIdentityDeformationMapSGIX, + InitReferencePlaneSGIX, + InitFlushRasterSGIX, + InitFogFuncSGIS, + InitGetFogFuncSGIS, + InitImageTransformParameteriHP, + InitImageTransformParameterfHP, + InitImageTransformParameterivHP, + InitImageTransformParameterfvHP, + InitGetImageTransformParameterivHP, + InitGetImageTransformParameterfvHP, + InitColorSubTableEXT, + InitCopyColorSubTableEXT, + InitHintPGI, + InitColorTableEXT, + InitGetColorTableEXT, + InitGetColorTableParameterivEXT, + InitGetColorTableParameterfvEXT, + InitGetListParameterfvSGIX, + InitGetListParameterivSGIX, + InitListParameterfSGIX, + InitListParameterfvSGIX, + InitListParameteriSGIX, + InitListParameterivSGIX, + InitIndexMaterialEXT, + InitIndexFuncEXT, + InitLockArraysEXT, + InitUnlockArraysEXT, + InitCullParameterdvEXT, + InitCullParameterfvEXT, + InitFragmentColorMaterialSGIX, + InitFragmentLightfSGIX, + InitFragmentLightfvSGIX, + InitFragmentLightiSGIX, + InitFragmentLightivSGIX, + InitFragmentLightModelfSGIX, + InitFragmentLightModelfvSGIX, + InitFragmentLightModeliSGIX, + InitFragmentLightModelivSGIX, + InitFragmentMaterialfSGIX, + InitFragmentMaterialfvSGIX, + InitFragmentMaterialiSGIX, + InitFragmentMaterialivSGIX, + InitGetFragmentLightfvSGIX, + InitGetFragmentLightivSGIX, + InitGetFragmentMaterialfvSGIX, + InitGetFragmentMaterialivSGIX, + InitLightEnviSGIX, + InitDrawRangeElementsEXT, + InitApplyTextureEXT, + InitTextureLightEXT, + InitTextureMaterialEXT, + InitAsyncMarkerSGIX, + InitFinishAsyncSGIX, + InitPollAsyncSGIX, + InitGenAsyncMarkersSGIX, + InitDeleteAsyncMarkersSGIX, + InitIsAsyncMarkerSGIX, + InitVertexPointervINTEL, + InitNormalPointervINTEL, + InitColorPointervINTEL, + InitTexCoordPointervINTEL, + InitPixelTransformParameteriEXT, + InitPixelTransformParameterfEXT, + InitPixelTransformParameterivEXT, + InitPixelTransformParameterfvEXT, + InitSecondaryColor3bEXT, + InitSecondaryColor3bvEXT, + InitSecondaryColor3dEXT, + InitSecondaryColor3dvEXT, + InitSecondaryColor3fEXT, + InitSecondaryColor3fvEXT, + InitSecondaryColor3iEXT, + InitSecondaryColor3ivEXT, + InitSecondaryColor3sEXT, + InitSecondaryColor3svEXT, + InitSecondaryColor3ubEXT, + InitSecondaryColor3ubvEXT, + InitSecondaryColor3uiEXT, + InitSecondaryColor3uivEXT, + InitSecondaryColor3usEXT, + InitSecondaryColor3usvEXT, + InitSecondaryColorPointerEXT, + InitTextureNormalEXT, + InitMultiDrawArraysEXT, + InitMultiDrawElementsEXT, + InitFogCoordfEXT, + InitFogCoordfvEXT, + InitFogCoorddEXT, + InitFogCoorddvEXT, + InitFogCoordPointerEXT, + InitTangent3bEXT, + InitTangent3bvEXT, + InitTangent3dEXT, + InitTangent3dvEXT, + InitTangent3fEXT, + InitTangent3fvEXT, + InitTangent3iEXT, + InitTangent3ivEXT, + InitTangent3sEXT, + InitTangent3svEXT, + InitBinormal3bEXT, + InitBinormal3bvEXT, + InitBinormal3dEXT, + InitBinormal3dvEXT, + InitBinormal3fEXT, + InitBinormal3fvEXT, + InitBinormal3iEXT, + InitBinormal3ivEXT, + InitBinormal3sEXT, + InitBinormal3svEXT, + InitTangentPointerEXT, + InitBinormalPointerEXT, + InitFinishTextureSUNX, + InitGlobalAlphaFactorbSUN, + InitGlobalAlphaFactorsSUN, + InitGlobalAlphaFactoriSUN, + InitGlobalAlphaFactorfSUN, + InitGlobalAlphaFactordSUN, + InitGlobalAlphaFactorubSUN, + InitGlobalAlphaFactorusSUN, + InitGlobalAlphaFactoruiSUN, + InitReplacementCodeuiSUN, + InitReplacementCodeusSUN, + InitReplacementCodeubSUN, + InitReplacementCodeuivSUN, + InitReplacementCodeusvSUN, + InitReplacementCodeubvSUN, + InitReplacementCodePointerSUN, + InitColor4ubVertex2fSUN, + InitColor4ubVertex2fvSUN, + InitColor4ubVertex3fSUN, + InitColor4ubVertex3fvSUN, + InitColor3fVertex3fSUN, + InitColor3fVertex3fvSUN, + InitNormal3fVertex3fSUN, + InitNormal3fVertex3fvSUN, + InitColor4fNormal3fVertex3fSUN, + InitColor4fNormal3fVertex3fvSUN, + InitTexCoord2fVertex3fSUN, + InitTexCoord2fVertex3fvSUN, + InitTexCoord4fVertex4fSUN, + InitTexCoord4fVertex4fvSUN, + InitTexCoord2fColor4ubVertex3fSUN, + InitTexCoord2fColor4ubVertex3fvSUN, + InitTexCoord2fColor3fVertex3fSUN, + InitTexCoord2fColor3fVertex3fvSUN, + InitTexCoord2fNormal3fVertex3fSUN, + InitTexCoord2fNormal3fVertex3fvSUN, + InitTexCoord2fColor4fNormal3fVertex3fSUN, + InitTexCoord2fColor4fNormal3fVertex3fvSUN, + InitTexCoord4fColor4fNormal3fVertex4fSUN, + InitTexCoord4fColor4fNormal3fVertex4fvSUN, + InitReplacementCodeuiVertex3fSUN, + InitReplacementCodeuiVertex3fvSUN, + InitReplacementCodeuiColor4ubVertex3fSUN, + InitReplacementCodeuiColor4ubVertex3fvSUN, + InitReplacementCodeuiColor3fVertex3fSUN, + InitReplacementCodeuiColor3fVertex3fvSUN, + InitReplacementCodeuiNormal3fVertex3fSUN, + InitReplacementCodeuiNormal3fVertex3fvSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiColor4fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fVertex3fSUN, + InitReplacementCodeuiTexCoord2fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN, + InitReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN, + InitBlendFuncSeparateEXT, + InitBlendFuncSeparateINGR, + InitVertexWeightfEXT, + InitVertexWeightfvEXT, + InitVertexWeightPointerEXT, + InitFlushVertexArrayRangeNV, + InitVertexArrayRangeNV, + InitCombinerParameterfvNV, + InitCombinerParameterfNV, + InitCombinerParameterivNV, + InitCombinerParameteriNV, + InitCombinerInputNV, + InitCombinerOutputNV, + InitFinalCombinerInputNV, + InitGetCombinerInputParameterfvNV, + InitGetCombinerInputParameterivNV, + InitGetCombinerOutputParameterfvNV, + InitGetCombinerOutputParameterivNV, + InitGetFinalCombinerInputParameterfvNV, + InitGetFinalCombinerInputParameterivNV, + InitResizeBuffersMESA, + InitWindowPos2dMESA, + InitWindowPos2dvMESA, + InitWindowPos2fMESA, + InitWindowPos2fvMESA, + InitWindowPos2iMESA, + InitWindowPos2ivMESA, + InitWindowPos2sMESA, + InitWindowPos2svMESA, + InitWindowPos3dMESA, + InitWindowPos3dvMESA, + InitWindowPos3fMESA, + InitWindowPos3fvMESA, + InitWindowPos3iMESA, + InitWindowPos3ivMESA, + InitWindowPos3sMESA, + InitWindowPos3svMESA, + InitWindowPos4dMESA, + InitWindowPos4dvMESA, + InitWindowPos4fMESA, + InitWindowPos4fvMESA, + InitWindowPos4iMESA, + InitWindowPos4ivMESA, + InitWindowPos4sMESA, + InitWindowPos4svMESA, + InitMultiModeDrawArraysIBM, + InitMultiModeDrawElementsIBM, + InitColorPointerListIBM, + InitSecondaryColorPointerListIBM, + InitEdgeFlagPointerListIBM, + InitFogCoordPointerListIBM, + InitIndexPointerListIBM, + InitNormalPointerListIBM, + InitTexCoordPointerListIBM, + InitVertexPointerListIBM, + InitTbufferMask3DFX, + InitSampleMaskEXT, + InitSamplePatternEXT, + InitTextureColorMaskSGIS, + InitIglooInterfaceSGIX, + InitDeleteFencesNV, + InitGenFencesNV, + InitIsFenceNV, + InitTestFenceNV, + InitGetFenceivNV, + InitFinishFenceNV, + InitSetFenceNV, + InitMapControlPointsNV, + InitMapParameterivNV, + InitMapParameterfvNV, + InitGetMapControlPointsNV, + InitGetMapParameterivNV, + InitGetMapParameterfvNV, + InitGetMapAttribParameterivNV, + InitGetMapAttribParameterfvNV, + InitEvalMapsNV, + InitCombinerStageParameterfvNV, + InitGetCombinerStageParameterfvNV, + InitAreProgramsResidentNV, + InitBindProgramNV, + InitDeleteProgramsNV, + InitExecuteProgramNV, + InitGenProgramsNV, + InitGetProgramParameterdvNV, + InitGetProgramParameterfvNV, + InitGetProgramivNV, + InitGetProgramStringNV, + InitGetTrackMatrixivNV, + InitGetVertexAttribdvNV, + InitGetVertexAttribfvNV, + InitGetVertexAttribivNV, + InitGetVertexAttribPointervNV, + InitIsProgramNV, + InitLoadProgramNV, + InitProgramParameter4dNV, + InitProgramParameter4dvNV, + InitProgramParameter4fNV, + InitProgramParameter4fvNV, + InitProgramParameters4dvNV, + InitProgramParameters4fvNV, + InitRequestResidentProgramsNV, + InitTrackMatrixNV, + InitVertexAttribPointerNV, + InitVertexAttrib1dNV, + InitVertexAttrib1dvNV, + InitVertexAttrib1fNV, + InitVertexAttrib1fvNV, + InitVertexAttrib1sNV, + InitVertexAttrib1svNV, + InitVertexAttrib2dNV, + InitVertexAttrib2dvNV, + InitVertexAttrib2fNV, + InitVertexAttrib2fvNV, + InitVertexAttrib2sNV, + InitVertexAttrib2svNV, + InitVertexAttrib3dNV, + InitVertexAttrib3dvNV, + InitVertexAttrib3fNV, + InitVertexAttrib3fvNV, + InitVertexAttrib3sNV, + InitVertexAttrib3svNV, + InitVertexAttrib4dNV, + InitVertexAttrib4dvNV, + InitVertexAttrib4fNV, + InitVertexAttrib4fvNV, + InitVertexAttrib4sNV, + InitVertexAttrib4svNV, + InitVertexAttrib4ubNV, + InitVertexAttrib4ubvNV, + InitVertexAttribs1dvNV, + InitVertexAttribs1fvNV, + InitVertexAttribs1svNV, + InitVertexAttribs2dvNV, + InitVertexAttribs2fvNV, + InitVertexAttribs2svNV, + InitVertexAttribs3dvNV, + InitVertexAttribs3fvNV, + InitVertexAttribs3svNV, + InitVertexAttribs4dvNV, + InitVertexAttribs4fvNV, + InitVertexAttribs4svNV, + InitVertexAttribs4ubvNV, + InitTexBumpParameterivATI, + InitTexBumpParameterfvATI, + InitGetTexBumpParameterivATI, + InitGetTexBumpParameterfvATI, + InitGenFragmentShadersATI, + InitBindFragmentShaderATI, + InitDeleteFragmentShaderATI, + InitBeginFragmentShaderATI, + InitEndFragmentShaderATI, + InitPassTexCoordATI, + InitSampleMapATI, + InitColorFragmentOp1ATI, + InitColorFragmentOp2ATI, + InitColorFragmentOp3ATI, + InitAlphaFragmentOp1ATI, + InitAlphaFragmentOp2ATI, + InitAlphaFragmentOp3ATI, + InitSetFragmentShaderConstantATI, + InitPNTrianglesiATI, + InitPNTrianglesfATI, + InitNewObjectBufferATI, + InitIsObjectBufferATI, + InitUpdateObjectBufferATI, + InitGetObjectBufferfvATI, + InitGetObjectBufferivATI, + InitFreeObjectBufferATI, + InitArrayObjectATI, + InitGetArrayObjectfvATI, + InitGetArrayObjectivATI, + InitVariantArrayObjectATI, + InitGetVariantArrayObjectfvATI, + InitGetVariantArrayObjectivATI, + InitBeginVertexShaderEXT, + InitEndVertexShaderEXT, + InitBindVertexShaderEXT, + InitGenVertexShadersEXT, + InitDeleteVertexShaderEXT, + InitShaderOp1EXT, + InitShaderOp2EXT, + InitShaderOp3EXT, + InitSwizzleEXT, + InitWriteMaskEXT, + InitInsertComponentEXT, + InitExtractComponentEXT, + InitGenSymbolsEXT, + InitSetInvariantEXT, + InitSetLocalConstantEXT, + InitVariantbvEXT, + InitVariantsvEXT, + InitVariantivEXT, + InitVariantfvEXT, + InitVariantdvEXT, + InitVariantubvEXT, + InitVariantusvEXT, + InitVariantuivEXT, + InitVariantPointerEXT, + InitEnableVariantClientStateEXT, + InitDisableVariantClientStateEXT, + InitBindLightParameterEXT, + InitBindMaterialParameterEXT, + InitBindTexGenParameterEXT, + InitBindTextureUnitParameterEXT, + InitBindParameterEXT, + InitIsVariantEnabledEXT, + InitGetVariantBooleanvEXT, + InitGetVariantIntegervEXT, + InitGetVariantFloatvEXT, + InitGetVariantPointervEXT, + InitGetInvariantBooleanvEXT, + InitGetInvariantIntegervEXT, + InitGetInvariantFloatvEXT, + InitGetLocalConstantBooleanvEXT, + InitGetLocalConstantIntegervEXT, + InitGetLocalConstantFloatvEXT, + InitVertexStream1sATI, + InitVertexStream1svATI, + InitVertexStream1iATI, + InitVertexStream1ivATI, + InitVertexStream1fATI, + InitVertexStream1fvATI, + InitVertexStream1dATI, + InitVertexStream1dvATI, + InitVertexStream2sATI, + InitVertexStream2svATI, + InitVertexStream2iATI, + InitVertexStream2ivATI, + InitVertexStream2fATI, + InitVertexStream2fvATI, + InitVertexStream2dATI, + InitVertexStream2dvATI, + InitVertexStream3sATI, + InitVertexStream3svATI, + InitVertexStream3iATI, + InitVertexStream3ivATI, + InitVertexStream3fATI, + InitVertexStream3fvATI, + InitVertexStream3dATI, + InitVertexStream3dvATI, + InitVertexStream4sATI, + InitVertexStream4svATI, + InitVertexStream4iATI, + InitVertexStream4ivATI, + InitVertexStream4fATI, + InitVertexStream4fvATI, + InitVertexStream4dATI, + InitVertexStream4dvATI, + InitNormalStream3bATI, + InitNormalStream3bvATI, + InitNormalStream3sATI, + InitNormalStream3svATI, + InitNormalStream3iATI, + InitNormalStream3ivATI, + InitNormalStream3fATI, + InitNormalStream3fvATI, + InitNormalStream3dATI, + InitNormalStream3dvATI, + InitClientActiveVertexStreamATI, + InitVertexBlendEnviATI, + InitVertexBlendEnvfATI, + InitElementPointerATI, + InitDrawElementArrayATI, + InitDrawRangeElementArrayATI, + InitDrawMeshArraysSUN, + InitGenOcclusionQueriesNV, + InitDeleteOcclusionQueriesNV, + InitIsOcclusionQueryNV, + InitBeginOcclusionQueryNV, + InitEndOcclusionQueryNV, + InitGetOcclusionQueryivNV, + InitGetOcclusionQueryuivNV, + InitPointParameteriNV, + InitPointParameterivNV, + InitActiveStencilFaceEXT, + InitElementPointerAPPLE, + InitDrawElementArrayAPPLE, + InitDrawRangeElementArrayAPPLE, + InitMultiDrawElementArrayAPPLE, + InitMultiDrawRangeElementArrayAPPLE, + InitGenFencesAPPLE, + InitDeleteFencesAPPLE, + InitSetFenceAPPLE, + InitIsFenceAPPLE, + InitTestFenceAPPLE, + InitFinishFenceAPPLE, + InitTestObjectAPPLE, + InitFinishObjectAPPLE, + InitBindVertexArrayAPPLE, + InitDeleteVertexArraysAPPLE, + InitGenVertexArraysAPPLE, + InitIsVertexArrayAPPLE, + InitVertexArrayRangeAPPLE, + InitFlushVertexArrayRangeAPPLE, + InitVertexArrayParameteriAPPLE, + InitDrawBuffersATI, + InitProgramNamedParameter4fNV, + InitProgramNamedParameter4dNV, + InitProgramNamedParameter4fvNV, + InitProgramNamedParameter4dvNV, + InitGetProgramNamedParameterfvNV, + InitGetProgramNamedParameterdvNV, + InitVertex2hNV, + InitVertex2hvNV, + InitVertex3hNV, + InitVertex3hvNV, + InitVertex4hNV, + InitVertex4hvNV, + InitNormal3hNV, + InitNormal3hvNV, + InitColor3hNV, + InitColor3hvNV, + InitColor4hNV, + InitColor4hvNV, + InitTexCoord1hNV, + InitTexCoord1hvNV, + InitTexCoord2hNV, + InitTexCoord2hvNV, + InitTexCoord3hNV, + InitTexCoord3hvNV, + InitTexCoord4hNV, + InitTexCoord4hvNV, + InitMultiTexCoord1hNV, + InitMultiTexCoord1hvNV, + InitMultiTexCoord2hNV, + InitMultiTexCoord2hvNV, + InitMultiTexCoord3hNV, + InitMultiTexCoord3hvNV, + InitMultiTexCoord4hNV, + InitMultiTexCoord4hvNV, + InitFogCoordhNV, + InitFogCoordhvNV, + InitSecondaryColor3hNV, + InitSecondaryColor3hvNV, + InitVertexWeighthNV, + InitVertexWeighthvNV, + InitVertexAttrib1hNV, + InitVertexAttrib1hvNV, + InitVertexAttrib2hNV, + InitVertexAttrib2hvNV, + InitVertexAttrib3hNV, + InitVertexAttrib3hvNV, + InitVertexAttrib4hNV, + InitVertexAttrib4hvNV, + InitVertexAttribs1hvNV, + InitVertexAttribs2hvNV, + InitVertexAttribs3hvNV, + InitVertexAttribs4hvNV, + InitPixelDataRangeNV, + InitFlushPixelDataRangeNV, + InitPrimitiveRestartNV, + InitPrimitiveRestartIndexNV, + InitMapObjectBufferATI, + InitUnmapObjectBufferATI, + InitStencilOpSeparateATI, + InitStencilFuncSeparateATI, + InitVertexAttribArrayObjectATI, + InitGetVertexAttribArrayObjectfvATI, + InitGetVertexAttribArrayObjectivATI, + InitDepthBoundsEXT, + InitBlendEquationSeparateEXT, + InitAddSwapHintRectWIN, +#ifdef _WIN32 + InitCreateBufferRegionARB, + InitDeleteBufferRegionARB, + InitSaveBufferRegionARB, + InitRestoreBufferRegionARB, + InitGetExtensionsStringARB, + InitGetPixelFormatAttribivARB, + InitGetPixelFormatAttribfvARB, + InitChoosePixelFormatARB, + InitMakeContextCurrentARB, + InitGetCurrentReadDCARB, + InitCreatePbufferARB, + InitGetPbufferDCARB, + InitReleasePbufferDCARB, + InitDestroyPbufferARB, + InitQueryPbufferARB, + InitBindTexImageARB, + InitReleaseTexImageARB, + InitSetPbufferAttribARB, + InitCreateDisplayColorTableEXT, + InitLoadDisplayColorTableEXT, + InitBindDisplayColorTableEXT, + InitDestroyDisplayColorTableEXT, + InitGetExtensionsStringEXT, + InitMakeContextCurrentEXT, + InitGetCurrentReadDCEXT, + InitCreatePbufferEXT, + InitGetPbufferDCEXT, + InitReleasePbufferDCEXT, + InitDestroyPbufferEXT, + InitQueryPbufferEXT, + InitGetPixelFormatAttribivEXT, + InitGetPixelFormatAttribfvEXT, + InitChoosePixelFormatEXT, + InitSwapIntervalEXT, + InitGetSwapIntervalEXT, + InitAllocateMemoryNV, + InitFreeMemoryNV, + InitGetSyncValuesOML, + InitGetMscRateOML, + InitSwapBuffersMscOML, + InitSwapLayerBuffersMscOML, + InitWaitForMscOML, + InitWaitForSbcOML, + InitGetDigitalVideoParametersI3D, + InitSetDigitalVideoParametersI3D, + InitGetGammaTableParametersI3D, + InitSetGammaTableParametersI3D, + InitGetGammaTableI3D, + InitSetGammaTableI3D, + InitEnableGenlockI3D, + InitDisableGenlockI3D, + InitIsEnabledGenlockI3D, + InitGenlockSourceI3D, + InitGetGenlockSourceI3D, + InitGenlockSourceEdgeI3D, + InitGetGenlockSourceEdgeI3D, + InitGenlockSampleRateI3D, + InitGetGenlockSampleRateI3D, + InitGenlockSourceDelayI3D, + InitGetGenlockSourceDelayI3D, + InitQueryGenlockMaxSourceDelayI3D, + InitCreateImageBufferI3D, + InitDestroyImageBufferI3D, + InitAssociateImageBufferEventsI3D, + InitReleaseImageBufferEventsI3D, + InitEnableFrameLockI3D, + InitDisableFrameLockI3D, + InitIsEnabledFrameLockI3D, + InitQueryFrameLockMasterI3D, + InitGetFrameUsageI3D, + InitBeginFrameTrackingI3D, + InitEndFrameTrackingI3D, + InitQueryFrameTrackingI3D, +#endif /* _WIN32 */ +}; diff --git a/plugins/gs/zerogs/opengl/glprocs.h b/plugins/gs/zerogs/opengl/glprocs.h new file mode 100644 index 0000000..c40e5bd --- /dev/null +++ b/plugins/gs/zerogs/opengl/glprocs.h @@ -0,0 +1,2213 @@ +#ifndef _GLPROCS_H_ +#define _GLPROCS_H_ + +/* +** GLprocs utility for getting function addresses for OpenGL(R) 1.2, +** OpenGL 1.3, OpenGL 1.4, OpenGL 1.5 and OpenGL extension functions. +** +** Version: 1.1 +** +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +** +** Initial version of glprocs.{c,h} contributed by Intel(R) Corporation. +*/ + +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +#ifndef _WIN32 /* non-Windows environment */ + #ifndef APIENTRY + #define APIENTRY + #endif + #ifdef __GNUC__ + #define _inline __inline__ + #else + #define _inline + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure of all OpenGL {1.2, 1.3, 1.4, 1.5}, GL extension procs.*/ + +typedef struct { + void (APIENTRY *BlendColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *BlendEquation) (GLenum mode); + void (APIENTRY *DrawRangeElements) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ColorTable) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTable) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTable) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *ColorSubTable) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTable) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *ConvolutionFilter1D) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterf) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfv) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteri) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameteriv) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2D) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilter) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilter) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2D) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *GetHistogram) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmax) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfv) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *Histogram) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *Minmax) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogram) (GLenum target); + void (APIENTRY *ResetMinmax) (GLenum target); + void (APIENTRY *TexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *ActiveTexture) (GLenum texture); + void (APIENTRY *ClientActiveTexture) (GLenum texture); + void (APIENTRY *MultiTexCoord1d) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1f) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1i) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1s) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2d) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2f) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2i) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2s) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3d) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3f) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3i) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3s) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3sv) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4d) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dv) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4f) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fv) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4i) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4iv) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4s) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4sv) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixf) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixd) (const GLdouble *m); + void (APIENTRY *SampleCoverage) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImage) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *BlendFuncSeparate) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *FogCoordf) (GLfloat coord); + void (APIENTRY *FogCoordfv) (const GLfloat *coord); + void (APIENTRY *FogCoordd) (GLdouble coord); + void (APIENTRY *FogCoorddv) (const GLdouble *coord); + void (APIENTRY *FogCoordPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *MultiDrawArrays) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElements) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *PointParameterf) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfv) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameteri) (GLenum pname, GLint param); + void (APIENTRY *PointParameteriv) (GLenum pname, const GLint *params); + void (APIENTRY *SecondaryColor3b) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bv) (const GLbyte *v); + void (APIENTRY *SecondaryColor3d) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dv) (const GLdouble *v); + void (APIENTRY *SecondaryColor3f) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fv) (const GLfloat *v); + void (APIENTRY *SecondaryColor3i) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3iv) (const GLint *v); + void (APIENTRY *SecondaryColor3s) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3sv) (const GLshort *v); + void (APIENTRY *SecondaryColor3ub) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubv) (const GLubyte *v); + void (APIENTRY *SecondaryColor3ui) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uiv) (const GLuint *v); + void (APIENTRY *SecondaryColor3us) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usv) (const GLushort *v); + void (APIENTRY *SecondaryColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2d) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dv) (const GLdouble *v); + void (APIENTRY *WindowPos2f) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fv) (const GLfloat *v); + void (APIENTRY *WindowPos2i) (GLint x, GLint y); + void (APIENTRY *WindowPos2iv) (const GLint *v); + void (APIENTRY *WindowPos2s) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2sv) (const GLshort *v); + void (APIENTRY *WindowPos3d) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dv) (const GLdouble *v); + void (APIENTRY *WindowPos3f) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fv) (const GLfloat *v); + void (APIENTRY *WindowPos3i) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3iv) (const GLint *v); + void (APIENTRY *WindowPos3s) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3sv) (const GLshort *v); + void (APIENTRY *GenQueries) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueries) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQuery) (GLuint id); + void (APIENTRY *BeginQuery) (GLenum target, GLuint id); + void (APIENTRY *EndQuery) (GLenum target); + void (APIENTRY *GetQueryiv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectiv) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuiv) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *BindBuffer) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffers) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffers) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBuffer) (GLuint buffer); + void (APIENTRY *BufferData) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); + void (APIENTRY *GetBufferSubData) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); + GLvoid* (APIENTRY *MapBuffer) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBuffer) (GLenum target); + void (APIENTRY *GetBufferParameteriv) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointerv) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *ActiveTextureARB) (GLenum texture); + void (APIENTRY *ClientActiveTextureARB) (GLenum texture); + void (APIENTRY *MultiTexCoord1dARB) (GLenum target, GLdouble s); + void (APIENTRY *MultiTexCoord1dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord1fARB) (GLenum target, GLfloat s); + void (APIENTRY *MultiTexCoord1fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord1iARB) (GLenum target, GLint s); + void (APIENTRY *MultiTexCoord1ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord1sARB) (GLenum target, GLshort s); + void (APIENTRY *MultiTexCoord1svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord2dARB) (GLenum target, GLdouble s, GLdouble t); + void (APIENTRY *MultiTexCoord2dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t); + void (APIENTRY *MultiTexCoord2fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord2iARB) (GLenum target, GLint s, GLint t); + void (APIENTRY *MultiTexCoord2ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord2sARB) (GLenum target, GLshort s, GLshort t); + void (APIENTRY *MultiTexCoord2svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord3dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r); + void (APIENTRY *MultiTexCoord3dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord3fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY *MultiTexCoord3fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord3iARB) (GLenum target, GLint s, GLint t, GLint r); + void (APIENTRY *MultiTexCoord3ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord3sARB) (GLenum target, GLshort s, GLshort t, GLshort r); + void (APIENTRY *MultiTexCoord3svARB) (GLenum target, const GLshort *v); + void (APIENTRY *MultiTexCoord4dARB) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); + void (APIENTRY *MultiTexCoord4dvARB) (GLenum target, const GLdouble *v); + void (APIENTRY *MultiTexCoord4fARB) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY *MultiTexCoord4fvARB) (GLenum target, const GLfloat *v); + void (APIENTRY *MultiTexCoord4iARB) (GLenum target, GLint s, GLint t, GLint r, GLint q); + void (APIENTRY *MultiTexCoord4ivARB) (GLenum target, const GLint *v); + void (APIENTRY *MultiTexCoord4sARB) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); + void (APIENTRY *MultiTexCoord4svARB) (GLenum target, const GLshort *v); + void (APIENTRY *LoadTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *LoadTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *MultTransposeMatrixfARB) (const GLfloat *m); + void (APIENTRY *MultTransposeMatrixdARB) (const GLdouble *m); + void (APIENTRY *SampleCoverageARB) (GLclampf value, GLboolean invert); + void (APIENTRY *CompressedTexImage3DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage2DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexImage1DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage3DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage2DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *CompressedTexSubImage1DARB) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); + void (APIENTRY *GetCompressedTexImageARB) (GLenum target, GLint level, GLvoid *img); + void (APIENTRY *PointParameterfARB) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvARB) (GLenum pname, const GLfloat *params); + void (APIENTRY *WeightbvARB) (GLint size, const GLbyte *weights); + void (APIENTRY *WeightsvARB) (GLint size, const GLshort *weights); + void (APIENTRY *WeightivARB) (GLint size, const GLint *weights); + void (APIENTRY *WeightfvARB) (GLint size, const GLfloat *weights); + void (APIENTRY *WeightdvARB) (GLint size, const GLdouble *weights); + void (APIENTRY *WeightubvARB) (GLint size, const GLubyte *weights); + void (APIENTRY *WeightusvARB) (GLint size, const GLushort *weights); + void (APIENTRY *WeightuivARB) (GLint size, const GLuint *weights); + void (APIENTRY *WeightPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexBlendARB) (GLint count); + void (APIENTRY *CurrentPaletteMatrixARB) (GLint index); + void (APIENTRY *MatrixIndexubvARB) (GLint size, const GLubyte *indices); + void (APIENTRY *MatrixIndexusvARB) (GLint size, const GLushort *indices); + void (APIENTRY *MatrixIndexuivARB) (GLint size, const GLuint *indices); + void (APIENTRY *MatrixIndexPointerARB) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *WindowPos2dARB) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos2fARB) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos2iARB) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivARB) (const GLint *v); + void (APIENTRY *WindowPos2sARB) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svARB) (const GLshort *v); + void (APIENTRY *WindowPos3dARB) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvARB) (const GLdouble *v); + void (APIENTRY *WindowPos3fARB) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvARB) (const GLfloat *v); + void (APIENTRY *WindowPos3iARB) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivARB) (const GLint *v); + void (APIENTRY *WindowPos3sARB) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svARB) (const GLshort *v); + void (APIENTRY *VertexAttrib1dARB) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fARB) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sARB) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dARB) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fARB) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sARB) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sARB) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NbvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4NivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4NsvARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4NubARB) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4NubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4NuivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4NusvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttrib4bvARB) (GLuint index, const GLbyte *v); + void (APIENTRY *VertexAttrib4dARB) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvARB) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fARB) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvARB) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4ivARB) (GLuint index, const GLint *v); + void (APIENTRY *VertexAttrib4sARB) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svARB) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubvARB) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttrib4uivARB) (GLuint index, const GLuint *v); + void (APIENTRY *VertexAttrib4usvARB) (GLuint index, const GLushort *v); + void (APIENTRY *VertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *EnableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *DisableVertexAttribArrayARB) (GLuint index); + void (APIENTRY *ProgramStringARB) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); + void (APIENTRY *BindProgramARB) (GLenum target, GLuint program); + void (APIENTRY *DeleteProgramsARB) (GLsizei n, const GLuint *programs); + void (APIENTRY *GenProgramsARB) (GLsizei n, GLuint *programs); + void (APIENTRY *ProgramEnvParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramEnvParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramEnvParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramEnvParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *ProgramLocalParameter4dARB) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramLocalParameter4dvARB) (GLenum target, GLuint index, const GLdouble *params); + void (APIENTRY *ProgramLocalParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramLocalParameter4fvARB) (GLenum target, GLuint index, const GLfloat *params); + void (APIENTRY *GetProgramEnvParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramEnvParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramLocalParameterdvARB) (GLenum target, GLuint index, GLdouble *params); + void (APIENTRY *GetProgramLocalParameterfvARB) (GLenum target, GLuint index, GLfloat *params); + void (APIENTRY *GetProgramivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringARB) (GLenum target, GLenum pname, GLvoid *string); + void (APIENTRY *GetVertexAttribdvARB) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvARB) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivARB) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervARB) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramARB) (GLuint program); + void (APIENTRY *BindBufferARB) (GLenum target, GLuint buffer); + void (APIENTRY *DeleteBuffersARB) (GLsizei n, const GLuint *buffers); + void (APIENTRY *GenBuffersARB) (GLsizei n, GLuint *buffers); + GLboolean (APIENTRY *IsBufferARB) (GLuint buffer); + void (APIENTRY *BufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); + void (APIENTRY *BufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); + void (APIENTRY *GetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); + GLvoid* (APIENTRY *MapBufferARB) (GLenum target, GLenum access); + GLboolean (APIENTRY *UnmapBufferARB) (GLenum target); + void (APIENTRY *GetBufferParameterivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetBufferPointervARB) (GLenum target, GLenum pname, GLvoid* *params); + void (APIENTRY *GenQueriesARB) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteQueriesARB) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsQueryARB) (GLuint id); + void (APIENTRY *BeginQueryARB) (GLenum target, GLuint id); + void (APIENTRY *EndQueryARB) (GLenum target); + void (APIENTRY *GetQueryivARB) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectivARB) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *DeleteObjectARB) (GLhandleARB obj); + GLhandleARB (APIENTRY *GetHandleARB) (GLenum pname); + void (APIENTRY *DetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj); + GLhandleARB (APIENTRY *CreateShaderObjectARB) (GLenum shaderType); + void (APIENTRY *ShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); + void (APIENTRY *CompileShaderARB) (GLhandleARB shaderObj); + GLhandleARB (APIENTRY *CreateProgramObjectARB) (void); + void (APIENTRY *AttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj); + void (APIENTRY *LinkProgramARB) (GLhandleARB programObj); + void (APIENTRY *UseProgramObjectARB) (GLhandleARB programObj); + void (APIENTRY *ValidateProgramARB) (GLhandleARB programObj); + void (APIENTRY *Uniform1fARB) (GLint location, GLfloat v0); + void (APIENTRY *Uniform2fARB) (GLint location, GLfloat v0, GLfloat v1); + void (APIENTRY *Uniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + void (APIENTRY *Uniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void (APIENTRY *Uniform1iARB) (GLint location, GLint v0); + void (APIENTRY *Uniform2iARB) (GLint location, GLint v0, GLint v1); + void (APIENTRY *Uniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2); + void (APIENTRY *Uniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + void (APIENTRY *Uniform1fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform2fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform3fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform4fvARB) (GLint location, GLsizei count, const GLfloat *value); + void (APIENTRY *Uniform1ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform2ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform3ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *Uniform4ivARB) (GLint location, GLsizei count, const GLint *value); + void (APIENTRY *UniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *UniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void (APIENTRY *GetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint *params); + void (APIENTRY *GetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); + void (APIENTRY *GetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); + GLint (APIENTRY *GetUniformLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *GetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + void (APIENTRY *GetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat *params); + void (APIENTRY *GetUniformivARB) (GLhandleARB programObj, GLint location, GLint *params); + void (APIENTRY *GetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); + void (APIENTRY *BindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB *name); + void (APIENTRY *GetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); + GLint (APIENTRY *GetAttribLocationARB) (GLhandleARB programObj, const GLcharARB *name); + void (APIENTRY *BlendColorEXT) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (APIENTRY *PolygonOffsetEXT) (GLfloat factor, GLfloat bias); + void (APIENTRY *TexImage3DEXT) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *GetTexFilterFuncSGIS) (GLenum target, GLenum filter, GLfloat *weights); + void (APIENTRY *TexFilterFuncSGIS) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); + void (APIENTRY *TexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *CopyTexImage1DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + void (APIENTRY *CopyTexImage2DEXT) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void (APIENTRY *CopyTexSubImage1DEXT) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyTexSubImage2DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *CopyTexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetHistogramEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetHistogramParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetHistogramParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMinmaxEXT) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + void (APIENTRY *GetMinmaxParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMinmaxParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *HistogramEXT) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + void (APIENTRY *MinmaxEXT) (GLenum target, GLenum internalformat, GLboolean sink); + void (APIENTRY *ResetHistogramEXT) (GLenum target); + void (APIENTRY *ResetMinmaxEXT) (GLenum target); + void (APIENTRY *ConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); + void (APIENTRY *ConvolutionParameterfEXT) (GLenum target, GLenum pname, GLfloat params); + void (APIENTRY *ConvolutionParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ConvolutionParameteriEXT) (GLenum target, GLenum pname, GLint params); + void (APIENTRY *ConvolutionParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyConvolutionFilter1DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *CopyConvolutionFilter2DEXT) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); + void (APIENTRY *GetConvolutionFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *image); + void (APIENTRY *GetConvolutionParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetConvolutionParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetSeparableFilterEXT) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); + void (APIENTRY *SeparableFilter2DEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); + void (APIENTRY *ColorTableSGI) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *ColorTableParameterfvSGI) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *ColorTableParameterivSGI) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *CopyColorTableSGI) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); + void (APIENTRY *GetColorTableSGI) (GLenum target, GLenum format, GLenum type, GLvoid *table); + void (APIENTRY *GetColorTableParameterfvSGI) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetColorTableParameterivSGI) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *PixelTexGenSGIX) (GLenum mode); + void (APIENTRY *PixelTexGenParameteriSGIS) (GLenum pname, GLint param); + void (APIENTRY *PixelTexGenParameterivSGIS) (GLenum pname, const GLint *params); + void (APIENTRY *PixelTexGenParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PixelTexGenParameterfvSGIS) (GLenum pname, const GLfloat *params); + void (APIENTRY *GetPixelTexGenParameterivSGIS) (GLenum pname, GLint *params); + void (APIENTRY *GetPixelTexGenParameterfvSGIS) (GLenum pname, GLfloat *params); + void (APIENTRY *TexImage4DSGIS) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); + void (APIENTRY *TexSubImage4DSGIS) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); + GLboolean (APIENTRY *AreTexturesResidentEXT) (GLsizei n, const GLuint *textures, GLboolean *residences); + void (APIENTRY *BindTextureEXT) (GLenum target, GLuint texture); + void (APIENTRY *DeleteTexturesEXT) (GLsizei n, const GLuint *textures); + void (APIENTRY *GenTexturesEXT) (GLsizei n, GLuint *textures); + GLboolean (APIENTRY *IsTextureEXT) (GLuint texture); + void (APIENTRY *PrioritizeTexturesEXT) (GLsizei n, const GLuint *textures, const GLclampf *priorities); + void (APIENTRY *DetailTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetDetailTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SharpenTexFuncSGIS) (GLenum target, GLsizei n, const GLfloat *points); + void (APIENTRY *GetSharpenTexFuncSGIS) (GLenum target, GLfloat *points); + void (APIENTRY *SampleMaskSGIS) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternSGIS) (GLenum pattern); + void (APIENTRY *ArrayElementEXT) (GLint i); + void (APIENTRY *ColorPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *DrawArraysEXT) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *EdgeFlagPointerEXT) (GLsizei stride, GLsizei count, const GLboolean *pointer); + void (APIENTRY *GetPointervEXT) (GLenum pname, GLvoid* *params); + void (APIENTRY *IndexPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *NormalPointerEXT) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *TexCoordPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *VertexPointerEXT) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); + void (APIENTRY *BlendEquationEXT) (GLenum mode); + void (APIENTRY *SpriteParameterfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *SpriteParameterfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *SpriteParameteriSGIX) (GLenum pname, GLint param); + void (APIENTRY *SpriteParameterivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *PointParameterfEXT) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvEXT) (GLenum pname, const GLfloat *params); + void (APIENTRY *PointParameterfSGIS) (GLenum pname, GLfloat param); + void (APIENTRY *PointParameterfvSGIS) (GLenum pname, const GLfloat *params); + GLint (APIENTRY *GetInstrumentsSGIX) (void); + void (APIENTRY *InstrumentsBufferSGIX) (GLsizei size, GLint *buffer); + GLint (APIENTRY *PollInstrumentsSGIX) (GLint *marker_p); + void (APIENTRY *ReadInstrumentsSGIX) (GLint marker); + void (APIENTRY *StartInstrumentsSGIX) (void); + void (APIENTRY *StopInstrumentsSGIX) (GLint marker); + void (APIENTRY *FrameZoomSGIX) (GLint factor); + void (APIENTRY *TagSampleBufferSGIX) (void); + void (APIENTRY *DeformationMap3dSGIX) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); + void (APIENTRY *DeformationMap3fSGIX) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); + void (APIENTRY *DeformSGIX) (GLbitfield mask); + void (APIENTRY *LoadIdentityDeformationMapSGIX) (GLbitfield mask); + void (APIENTRY *ReferencePlaneSGIX) (const GLdouble *equation); + void (APIENTRY *FlushRasterSGIX) (void); + void (APIENTRY *FogFuncSGIS) (GLsizei n, const GLfloat *points); + void (APIENTRY *GetFogFuncSGIS) (GLfloat *points); + void (APIENTRY *ImageTransformParameteriHP) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *ImageTransformParameterfHP) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *ImageTransformParameterivHP) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *ImageTransformParameterfvHP) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetImageTransformParameterivHP) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetImageTransformParameterfvHP) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *ColorSubTableEXT) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); + void (APIENTRY *CopyColorSubTableEXT) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); + void (APIENTRY *HintPGI) (GLenum target, GLint mode); + void (APIENTRY *ColorTableEXT) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); + void (APIENTRY *GetColorTableEXT) (GLenum target, GLenum format, GLenum type, GLvoid *data); + void (APIENTRY *GetColorTableParameterivEXT) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetColorTableParameterfvEXT) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterfvSGIX) (GLuint list, GLenum pname, GLfloat *params); + void (APIENTRY *GetListParameterivSGIX) (GLuint list, GLenum pname, GLint *params); + void (APIENTRY *ListParameterfSGIX) (GLuint list, GLenum pname, GLfloat param); + void (APIENTRY *ListParameterfvSGIX) (GLuint list, GLenum pname, const GLfloat *params); + void (APIENTRY *ListParameteriSGIX) (GLuint list, GLenum pname, GLint param); + void (APIENTRY *ListParameterivSGIX) (GLuint list, GLenum pname, const GLint *params); + void (APIENTRY *IndexMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *IndexFuncEXT) (GLenum func, GLclampf ref); + void (APIENTRY *LockArraysEXT) (GLint first, GLsizei count); + void (APIENTRY *UnlockArraysEXT) (void); + void (APIENTRY *CullParameterdvEXT) (GLenum pname, GLdouble *params); + void (APIENTRY *CullParameterfvEXT) (GLenum pname, GLfloat *params); + void (APIENTRY *FragmentColorMaterialSGIX) (GLenum face, GLenum mode); + void (APIENTRY *FragmentLightfSGIX) (GLenum light, GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightfvSGIX) (GLenum light, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightiSGIX) (GLenum light, GLenum pname, GLint param); + void (APIENTRY *FragmentLightivSGIX) (GLenum light, GLenum pname, const GLint *params); + void (APIENTRY *FragmentLightModelfSGIX) (GLenum pname, GLfloat param); + void (APIENTRY *FragmentLightModelfvSGIX) (GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentLightModeliSGIX) (GLenum pname, GLint param); + void (APIENTRY *FragmentLightModelivSGIX) (GLenum pname, const GLint *params); + void (APIENTRY *FragmentMaterialfSGIX) (GLenum face, GLenum pname, GLfloat param); + void (APIENTRY *FragmentMaterialfvSGIX) (GLenum face, GLenum pname, const GLfloat *params); + void (APIENTRY *FragmentMaterialiSGIX) (GLenum face, GLenum pname, GLint param); + void (APIENTRY *FragmentMaterialivSGIX) (GLenum face, GLenum pname, const GLint *params); + void (APIENTRY *GetFragmentLightfvSGIX) (GLenum light, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentLightivSGIX) (GLenum light, GLenum pname, GLint *params); + void (APIENTRY *GetFragmentMaterialfvSGIX) (GLenum face, GLenum pname, GLfloat *params); + void (APIENTRY *GetFragmentMaterialivSGIX) (GLenum face, GLenum pname, GLint *params); + void (APIENTRY *LightEnviSGIX) (GLenum pname, GLint param); + void (APIENTRY *DrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); + void (APIENTRY *ApplyTextureEXT) (GLenum mode); + void (APIENTRY *TextureLightEXT) (GLenum pname); + void (APIENTRY *TextureMaterialEXT) (GLenum face, GLenum mode); + void (APIENTRY *AsyncMarkerSGIX) (GLuint marker); + GLint (APIENTRY *FinishAsyncSGIX) (GLuint *markerp); + GLint (APIENTRY *PollAsyncSGIX) (GLuint *markerp); + GLuint (APIENTRY *GenAsyncMarkersSGIX) (GLsizei range); + void (APIENTRY *DeleteAsyncMarkersSGIX) (GLuint marker, GLsizei range); + GLboolean (APIENTRY *IsAsyncMarkerSGIX) (GLuint marker); + void (APIENTRY *VertexPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *NormalPointervINTEL) (GLenum type, const GLvoid* *pointer); + void (APIENTRY *ColorPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *TexCoordPointervINTEL) (GLint size, GLenum type, const GLvoid* *pointer); + void (APIENTRY *PixelTransformParameteriEXT) (GLenum target, GLenum pname, GLint param); + void (APIENTRY *PixelTransformParameterfEXT) (GLenum target, GLenum pname, GLfloat param); + void (APIENTRY *PixelTransformParameterivEXT) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *PixelTransformParameterfvEXT) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *SecondaryColor3bEXT) (GLbyte red, GLbyte green, GLbyte blue); + void (APIENTRY *SecondaryColor3bvEXT) (const GLbyte *v); + void (APIENTRY *SecondaryColor3dEXT) (GLdouble red, GLdouble green, GLdouble blue); + void (APIENTRY *SecondaryColor3dvEXT) (const GLdouble *v); + void (APIENTRY *SecondaryColor3fEXT) (GLfloat red, GLfloat green, GLfloat blue); + void (APIENTRY *SecondaryColor3fvEXT) (const GLfloat *v); + void (APIENTRY *SecondaryColor3iEXT) (GLint red, GLint green, GLint blue); + void (APIENTRY *SecondaryColor3ivEXT) (const GLint *v); + void (APIENTRY *SecondaryColor3sEXT) (GLshort red, GLshort green, GLshort blue); + void (APIENTRY *SecondaryColor3svEXT) (const GLshort *v); + void (APIENTRY *SecondaryColor3ubEXT) (GLubyte red, GLubyte green, GLubyte blue); + void (APIENTRY *SecondaryColor3ubvEXT) (const GLubyte *v); + void (APIENTRY *SecondaryColor3uiEXT) (GLuint red, GLuint green, GLuint blue); + void (APIENTRY *SecondaryColor3uivEXT) (const GLuint *v); + void (APIENTRY *SecondaryColor3usEXT) (GLushort red, GLushort green, GLushort blue); + void (APIENTRY *SecondaryColor3usvEXT) (const GLushort *v); + void (APIENTRY *SecondaryColorPointerEXT) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *TextureNormalEXT) (GLenum mode); + void (APIENTRY *MultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + void (APIENTRY *FogCoordfEXT) (GLfloat coord); + void (APIENTRY *FogCoordfvEXT) (const GLfloat *coord); + void (APIENTRY *FogCoorddEXT) (GLdouble coord); + void (APIENTRY *FogCoorddvEXT) (const GLdouble *coord); + void (APIENTRY *FogCoordPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *Tangent3bEXT) (GLbyte tx, GLbyte ty, GLbyte tz); + void (APIENTRY *Tangent3bvEXT) (const GLbyte *v); + void (APIENTRY *Tangent3dEXT) (GLdouble tx, GLdouble ty, GLdouble tz); + void (APIENTRY *Tangent3dvEXT) (const GLdouble *v); + void (APIENTRY *Tangent3fEXT) (GLfloat tx, GLfloat ty, GLfloat tz); + void (APIENTRY *Tangent3fvEXT) (const GLfloat *v); + void (APIENTRY *Tangent3iEXT) (GLint tx, GLint ty, GLint tz); + void (APIENTRY *Tangent3ivEXT) (const GLint *v); + void (APIENTRY *Tangent3sEXT) (GLshort tx, GLshort ty, GLshort tz); + void (APIENTRY *Tangent3svEXT) (const GLshort *v); + void (APIENTRY *Binormal3bEXT) (GLbyte bx, GLbyte by, GLbyte bz); + void (APIENTRY *Binormal3bvEXT) (const GLbyte *v); + void (APIENTRY *Binormal3dEXT) (GLdouble bx, GLdouble by, GLdouble bz); + void (APIENTRY *Binormal3dvEXT) (const GLdouble *v); + void (APIENTRY *Binormal3fEXT) (GLfloat bx, GLfloat by, GLfloat bz); + void (APIENTRY *Binormal3fvEXT) (const GLfloat *v); + void (APIENTRY *Binormal3iEXT) (GLint bx, GLint by, GLint bz); + void (APIENTRY *Binormal3ivEXT) (const GLint *v); + void (APIENTRY *Binormal3sEXT) (GLshort bx, GLshort by, GLshort bz); + void (APIENTRY *Binormal3svEXT) (const GLshort *v); + void (APIENTRY *TangentPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *BinormalPointerEXT) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FinishTextureSUNX) (void); + void (APIENTRY *GlobalAlphaFactorbSUN) (GLbyte factor); + void (APIENTRY *GlobalAlphaFactorsSUN) (GLshort factor); + void (APIENTRY *GlobalAlphaFactoriSUN) (GLint factor); + void (APIENTRY *GlobalAlphaFactorfSUN) (GLfloat factor); + void (APIENTRY *GlobalAlphaFactordSUN) (GLdouble factor); + void (APIENTRY *GlobalAlphaFactorubSUN) (GLubyte factor); + void (APIENTRY *GlobalAlphaFactorusSUN) (GLushort factor); + void (APIENTRY *GlobalAlphaFactoruiSUN) (GLuint factor); + void (APIENTRY *ReplacementCodeuiSUN) (GLuint code); + void (APIENTRY *ReplacementCodeusSUN) (GLushort code); + void (APIENTRY *ReplacementCodeubSUN) (GLubyte code); + void (APIENTRY *ReplacementCodeuivSUN) (const GLuint *code); + void (APIENTRY *ReplacementCodeusvSUN) (const GLushort *code); + void (APIENTRY *ReplacementCodeubvSUN) (const GLubyte *code); + void (APIENTRY *ReplacementCodePointerSUN) (GLenum type, GLsizei stride, const GLvoid* *pointer); + void (APIENTRY *Color4ubVertex2fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); + void (APIENTRY *Color4ubVertex2fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color4ubVertex3fSUN) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4ubVertex3fvSUN) (const GLubyte *c, const GLfloat *v); + void (APIENTRY *Color3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color3fVertex3fvSUN) (const GLfloat *c, const GLfloat *v); + void (APIENTRY *Normal3fVertex3fSUN) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Normal3fVertex3fvSUN) (const GLfloat *n, const GLfloat *v); + void (APIENTRY *Color4fNormal3fVertex3fSUN) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *Color4fNormal3fVertex3fvSUN) (const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fVertex3fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord4fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fVertex4fvSUN) (const GLfloat *tc, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4ubVertex3fSUN) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4ubVertex3fvSUN) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *TexCoord2fColor3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *TexCoord2fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fSUN) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *TexCoord2fColor4fNormal3fVertex3fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fSUN) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *TexCoord4fColor4fNormal3fVertex4fvSUN) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiVertex3fSUN) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiVertex3fvSUN) (const GLuint *rc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fSUN) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4ubVertex3fvSUN) (const GLuint *rc, const GLubyte *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fSUN) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); + void (APIENTRY *BlendFuncSeparateEXT) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *BlendFuncSeparateINGR) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + void (APIENTRY *VertexWeightfEXT) (GLfloat weight); + void (APIENTRY *VertexWeightfvEXT) (const GLfloat *weight); + void (APIENTRY *VertexWeightPointerEXT) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeNV) (void); + void (APIENTRY *VertexArrayRangeNV) (GLsizei length, const GLvoid *pointer); + void (APIENTRY *CombinerParameterfvNV) (GLenum pname, const GLfloat *params); + void (APIENTRY *CombinerParameterfNV) (GLenum pname, GLfloat param); + void (APIENTRY *CombinerParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *CombinerParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *CombinerInputNV) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *CombinerOutputNV) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); + void (APIENTRY *FinalCombinerInputNV) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); + void (APIENTRY *GetCombinerInputParameterfvNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerInputParameterivNV) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *GetCombinerOutputParameterfvNV) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); + void (APIENTRY *GetCombinerOutputParameterivNV) (GLenum stage, GLenum portion, GLenum pname, GLint *params); + void (APIENTRY *GetFinalCombinerInputParameterfvNV) (GLenum variable, GLenum pname, GLfloat *params); + void (APIENTRY *GetFinalCombinerInputParameterivNV) (GLenum variable, GLenum pname, GLint *params); + void (APIENTRY *ResizeBuffersMESA) (void); + void (APIENTRY *WindowPos2dMESA) (GLdouble x, GLdouble y); + void (APIENTRY *WindowPos2dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos2fMESA) (GLfloat x, GLfloat y); + void (APIENTRY *WindowPos2fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos2iMESA) (GLint x, GLint y); + void (APIENTRY *WindowPos2ivMESA) (const GLint *v); + void (APIENTRY *WindowPos2sMESA) (GLshort x, GLshort y); + void (APIENTRY *WindowPos2svMESA) (const GLshort *v); + void (APIENTRY *WindowPos3dMESA) (GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *WindowPos3dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos3fMESA) (GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *WindowPos3fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos3iMESA) (GLint x, GLint y, GLint z); + void (APIENTRY *WindowPos3ivMESA) (const GLint *v); + void (APIENTRY *WindowPos3sMESA) (GLshort x, GLshort y, GLshort z); + void (APIENTRY *WindowPos3svMESA) (const GLshort *v); + void (APIENTRY *WindowPos4dMESA) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *WindowPos4dvMESA) (const GLdouble *v); + void (APIENTRY *WindowPos4fMESA) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *WindowPos4fvMESA) (const GLfloat *v); + void (APIENTRY *WindowPos4iMESA) (GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *WindowPos4ivMESA) (const GLint *v); + void (APIENTRY *WindowPos4sMESA) (GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *WindowPos4svMESA) (const GLshort *v); + void (APIENTRY *MultiModeDrawArraysIBM) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); + void (APIENTRY *MultiModeDrawElementsIBM) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); + void (APIENTRY *ColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *SecondaryColorPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *EdgeFlagPointerListIBM) (GLint stride, const GLboolean* *pointer, GLint ptrstride); + void (APIENTRY *FogCoordPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *IndexPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *NormalPointerListIBM) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TexCoordPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *VertexPointerListIBM) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); + void (APIENTRY *TbufferMask3DFX) (GLuint mask); + void (APIENTRY *SampleMaskEXT) (GLclampf value, GLboolean invert); + void (APIENTRY *SamplePatternEXT) (GLenum pattern); + void (APIENTRY *TextureColorMaskSGIS) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void (APIENTRY *IglooInterfaceSGIX) (GLenum pname, const GLvoid *params); + void (APIENTRY *DeleteFencesNV) (GLsizei n, const GLuint *fences); + void (APIENTRY *GenFencesNV) (GLsizei n, GLuint *fences); + GLboolean (APIENTRY *IsFenceNV) (GLuint fence); + GLboolean (APIENTRY *TestFenceNV) (GLuint fence); + void (APIENTRY *GetFenceivNV) (GLuint fence, GLenum pname, GLint *params); + void (APIENTRY *FinishFenceNV) (GLuint fence); + void (APIENTRY *SetFenceNV) (GLuint fence, GLenum condition); + void (APIENTRY *MapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); + void (APIENTRY *MapParameterivNV) (GLenum target, GLenum pname, const GLint *params); + void (APIENTRY *MapParameterfvNV) (GLenum target, GLenum pname, const GLfloat *params); + void (APIENTRY *GetMapControlPointsNV) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); + void (APIENTRY *GetMapParameterivNV) (GLenum target, GLenum pname, GLint *params); + void (APIENTRY *GetMapParameterfvNV) (GLenum target, GLenum pname, GLfloat *params); + void (APIENTRY *GetMapAttribParameterivNV) (GLenum target, GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetMapAttribParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *EvalMapsNV) (GLenum target, GLenum mode); + void (APIENTRY *CombinerStageParameterfvNV) (GLenum stage, GLenum pname, const GLfloat *params); + void (APIENTRY *GetCombinerStageParameterfvNV) (GLenum stage, GLenum pname, GLfloat *params); + GLboolean (APIENTRY *AreProgramsResidentNV) (GLsizei n, const GLuint *programs, GLboolean *residences); + void (APIENTRY *BindProgramNV) (GLenum target, GLuint id); + void (APIENTRY *DeleteProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *ExecuteProgramNV) (GLenum target, GLuint id, const GLfloat *params); + void (APIENTRY *GenProgramsNV) (GLsizei n, GLuint *programs); + void (APIENTRY *GetProgramParameterdvNV) (GLenum target, GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetProgramParameterfvNV) (GLenum target, GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetProgramivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetProgramStringNV) (GLuint id, GLenum pname, GLubyte *program); + void (APIENTRY *GetTrackMatrixivNV) (GLenum target, GLuint address, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribdvNV) (GLuint index, GLenum pname, GLdouble *params); + void (APIENTRY *GetVertexAttribfvNV) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribivNV) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *GetVertexAttribPointervNV) (GLuint index, GLenum pname, GLvoid* *pointer); + GLboolean (APIENTRY *IsProgramNV) (GLuint id); + void (APIENTRY *LoadProgramNV) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); + void (APIENTRY *ProgramParameter4dNV) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramParameter4dvNV) (GLenum target, GLuint index, const GLdouble *v); + void (APIENTRY *ProgramParameter4fNV) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramParameter4fvNV) (GLenum target, GLuint index, const GLfloat *v); + void (APIENTRY *ProgramParameters4dvNV) (GLenum target, GLuint index, GLuint count, const GLdouble *v); + void (APIENTRY *ProgramParameters4fvNV) (GLenum target, GLuint index, GLuint count, const GLfloat *v); + void (APIENTRY *RequestResidentProgramsNV) (GLsizei n, const GLuint *programs); + void (APIENTRY *TrackMatrixNV) (GLenum target, GLuint address, GLenum matrix, GLenum transform); + void (APIENTRY *VertexAttribPointerNV) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); + void (APIENTRY *VertexAttrib1dNV) (GLuint index, GLdouble x); + void (APIENTRY *VertexAttrib1dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib1fNV) (GLuint index, GLfloat x); + void (APIENTRY *VertexAttrib1fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib1sNV) (GLuint index, GLshort x); + void (APIENTRY *VertexAttrib1svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib2dNV) (GLuint index, GLdouble x, GLdouble y); + void (APIENTRY *VertexAttrib2dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib2fNV) (GLuint index, GLfloat x, GLfloat y); + void (APIENTRY *VertexAttrib2fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib2sNV) (GLuint index, GLshort x, GLshort y); + void (APIENTRY *VertexAttrib2svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib3dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexAttrib3dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib3fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexAttrib3fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib3sNV) (GLuint index, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexAttrib3svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4dNV) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexAttrib4dvNV) (GLuint index, const GLdouble *v); + void (APIENTRY *VertexAttrib4fNV) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexAttrib4fvNV) (GLuint index, const GLfloat *v); + void (APIENTRY *VertexAttrib4sNV) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexAttrib4svNV) (GLuint index, const GLshort *v); + void (APIENTRY *VertexAttrib4ubNV) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + void (APIENTRY *VertexAttrib4ubvNV) (GLuint index, const GLubyte *v); + void (APIENTRY *VertexAttribs1dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs1fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs1svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs2dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs2fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs2svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs3dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs3fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs3svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4dvNV) (GLuint index, GLsizei count, const GLdouble *v); + void (APIENTRY *VertexAttribs4fvNV) (GLuint index, GLsizei count, const GLfloat *v); + void (APIENTRY *VertexAttribs4svNV) (GLuint index, GLsizei count, const GLshort *v); + void (APIENTRY *VertexAttribs4ubvNV) (GLuint index, GLsizei count, const GLubyte *v); + void (APIENTRY *TexBumpParameterivATI) (GLenum pname, const GLint *param); + void (APIENTRY *TexBumpParameterfvATI) (GLenum pname, const GLfloat *param); + void (APIENTRY *GetTexBumpParameterivATI) (GLenum pname, GLint *param); + void (APIENTRY *GetTexBumpParameterfvATI) (GLenum pname, GLfloat *param); + GLuint (APIENTRY *GenFragmentShadersATI) (GLuint range); + void (APIENTRY *BindFragmentShaderATI) (GLuint id); + void (APIENTRY *DeleteFragmentShaderATI) (GLuint id); + void (APIENTRY *BeginFragmentShaderATI) (void); + void (APIENTRY *EndFragmentShaderATI) (void); + void (APIENTRY *PassTexCoordATI) (GLuint dst, GLuint coord, GLenum swizzle); + void (APIENTRY *SampleMapATI) (GLuint dst, GLuint interp, GLenum swizzle); + void (APIENTRY *ColorFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *ColorFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *ColorFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *AlphaFragmentOp1ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); + void (APIENTRY *AlphaFragmentOp2ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); + void (APIENTRY *AlphaFragmentOp3ATI) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); + void (APIENTRY *SetFragmentShaderConstantATI) (GLuint dst, const GLfloat *value); + void (APIENTRY *PNTrianglesiATI) (GLenum pname, GLint param); + void (APIENTRY *PNTrianglesfATI) (GLenum pname, GLfloat param); + GLuint (APIENTRY *NewObjectBufferATI) (GLsizei size, const GLvoid *pointer, GLenum usage); + GLboolean (APIENTRY *IsObjectBufferATI) (GLuint buffer); + void (APIENTRY *UpdateObjectBufferATI) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); + void (APIENTRY *GetObjectBufferfvATI) (GLuint buffer, GLenum pname, GLfloat *params); + void (APIENTRY *GetObjectBufferivATI) (GLuint buffer, GLenum pname, GLint *params); + void (APIENTRY *FreeObjectBufferATI) (GLuint buffer); + void (APIENTRY *ArrayObjectATI) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetArrayObjectfvATI) (GLenum array, GLenum pname, GLfloat *params); + void (APIENTRY *GetArrayObjectivATI) (GLenum array, GLenum pname, GLint *params); + void (APIENTRY *VariantArrayObjectATI) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVariantArrayObjectfvATI) (GLuint id, GLenum pname, GLfloat *params); + void (APIENTRY *GetVariantArrayObjectivATI) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *BeginVertexShaderEXT) (void); + void (APIENTRY *EndVertexShaderEXT) (void); + void (APIENTRY *BindVertexShaderEXT) (GLuint id); + GLuint (APIENTRY *GenVertexShadersEXT) (GLuint range); + void (APIENTRY *DeleteVertexShaderEXT) (GLuint id); + void (APIENTRY *ShaderOp1EXT) (GLenum op, GLuint res, GLuint arg1); + void (APIENTRY *ShaderOp2EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); + void (APIENTRY *ShaderOp3EXT) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); + void (APIENTRY *SwizzleEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *WriteMaskEXT) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); + void (APIENTRY *InsertComponentEXT) (GLuint res, GLuint src, GLuint num); + void (APIENTRY *ExtractComponentEXT) (GLuint res, GLuint src, GLuint num); + GLuint (APIENTRY *GenSymbolsEXT) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); + void (APIENTRY *SetInvariantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *SetLocalConstantEXT) (GLuint id, GLenum type, const GLvoid *addr); + void (APIENTRY *VariantbvEXT) (GLuint id, const GLbyte *addr); + void (APIENTRY *VariantsvEXT) (GLuint id, const GLshort *addr); + void (APIENTRY *VariantivEXT) (GLuint id, const GLint *addr); + void (APIENTRY *VariantfvEXT) (GLuint id, const GLfloat *addr); + void (APIENTRY *VariantdvEXT) (GLuint id, const GLdouble *addr); + void (APIENTRY *VariantubvEXT) (GLuint id, const GLubyte *addr); + void (APIENTRY *VariantusvEXT) (GLuint id, const GLushort *addr); + void (APIENTRY *VariantuivEXT) (GLuint id, const GLuint *addr); + void (APIENTRY *VariantPointerEXT) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); + void (APIENTRY *EnableVariantClientStateEXT) (GLuint id); + void (APIENTRY *DisableVariantClientStateEXT) (GLuint id); + GLuint (APIENTRY *BindLightParameterEXT) (GLenum light, GLenum value); + GLuint (APIENTRY *BindMaterialParameterEXT) (GLenum face, GLenum value); + GLuint (APIENTRY *BindTexGenParameterEXT) (GLenum unit, GLenum coord, GLenum value); + GLuint (APIENTRY *BindTextureUnitParameterEXT) (GLenum unit, GLenum value); + GLuint (APIENTRY *BindParameterEXT) (GLenum value); + GLboolean (APIENTRY *IsVariantEnabledEXT) (GLuint id, GLenum cap); + void (APIENTRY *GetVariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetVariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetVariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetVariantPointervEXT) (GLuint id, GLenum value, GLvoid* *data); + void (APIENTRY *GetInvariantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetInvariantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetInvariantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *GetLocalConstantBooleanvEXT) (GLuint id, GLenum value, GLboolean *data); + void (APIENTRY *GetLocalConstantIntegervEXT) (GLuint id, GLenum value, GLint *data); + void (APIENTRY *GetLocalConstantFloatvEXT) (GLuint id, GLenum value, GLfloat *data); + void (APIENTRY *VertexStream1sATI) (GLenum stream, GLshort x); + void (APIENTRY *VertexStream1svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream1iATI) (GLenum stream, GLint x); + void (APIENTRY *VertexStream1ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream1fATI) (GLenum stream, GLfloat x); + void (APIENTRY *VertexStream1fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream1dATI) (GLenum stream, GLdouble x); + void (APIENTRY *VertexStream1dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream2sATI) (GLenum stream, GLshort x, GLshort y); + void (APIENTRY *VertexStream2svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream2iATI) (GLenum stream, GLint x, GLint y); + void (APIENTRY *VertexStream2ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream2fATI) (GLenum stream, GLfloat x, GLfloat y); + void (APIENTRY *VertexStream2fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream2dATI) (GLenum stream, GLdouble x, GLdouble y); + void (APIENTRY *VertexStream2dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream3sATI) (GLenum stream, GLshort x, GLshort y, GLshort z); + void (APIENTRY *VertexStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream3iATI) (GLenum stream, GLint x, GLint y, GLint z); + void (APIENTRY *VertexStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream3fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); + void (APIENTRY *VertexStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream3dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); + void (APIENTRY *VertexStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *VertexStream4sATI) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); + void (APIENTRY *VertexStream4svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *VertexStream4iATI) (GLenum stream, GLint x, GLint y, GLint z, GLint w); + void (APIENTRY *VertexStream4ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *VertexStream4fATI) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *VertexStream4fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *VertexStream4dATI) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *VertexStream4dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *NormalStream3bATI) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); + void (APIENTRY *NormalStream3bvATI) (GLenum stream, const GLbyte *coords); + void (APIENTRY *NormalStream3sATI) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); + void (APIENTRY *NormalStream3svATI) (GLenum stream, const GLshort *coords); + void (APIENTRY *NormalStream3iATI) (GLenum stream, GLint nx, GLint ny, GLint nz); + void (APIENTRY *NormalStream3ivATI) (GLenum stream, const GLint *coords); + void (APIENTRY *NormalStream3fATI) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); + void (APIENTRY *NormalStream3fvATI) (GLenum stream, const GLfloat *coords); + void (APIENTRY *NormalStream3dATI) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); + void (APIENTRY *NormalStream3dvATI) (GLenum stream, const GLdouble *coords); + void (APIENTRY *ClientActiveVertexStreamATI) (GLenum stream); + void (APIENTRY *VertexBlendEnviATI) (GLenum pname, GLint param); + void (APIENTRY *VertexBlendEnvfATI) (GLenum pname, GLfloat param); + void (APIENTRY *ElementPointerATI) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayATI) (GLenum mode, GLsizei count); + void (APIENTRY *DrawRangeElementArrayATI) (GLenum mode, GLuint start, GLuint end, GLsizei count); + void (APIENTRY *DrawMeshArraysSUN) (GLenum mode, GLint first, GLsizei count, GLsizei width); + void (APIENTRY *GenOcclusionQueriesNV) (GLsizei n, GLuint *ids); + void (APIENTRY *DeleteOcclusionQueriesNV) (GLsizei n, const GLuint *ids); + GLboolean (APIENTRY *IsOcclusionQueryNV) (GLuint id); + void (APIENTRY *BeginOcclusionQueryNV) (GLuint id); + void (APIENTRY *EndOcclusionQueryNV) (void); + void (APIENTRY *GetOcclusionQueryivNV) (GLuint id, GLenum pname, GLint *params); + void (APIENTRY *GetOcclusionQueryuivNV) (GLuint id, GLenum pname, GLuint *params); + void (APIENTRY *PointParameteriNV) (GLenum pname, GLint param); + void (APIENTRY *PointParameterivNV) (GLenum pname, const GLint *params); + void (APIENTRY *ActiveStencilFaceEXT) (GLenum face); + void (APIENTRY *ElementPointerAPPLE) (GLenum type, const GLvoid *pointer); + void (APIENTRY *DrawElementArrayAPPLE) (GLenum mode, GLint first, GLsizei count); + void (APIENTRY *DrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); + void (APIENTRY *MultiDrawElementArrayAPPLE) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *MultiDrawRangeElementArrayAPPLE) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); + void (APIENTRY *GenFencesAPPLE) (GLsizei n, GLuint *fences); + void (APIENTRY *DeleteFencesAPPLE) (GLsizei n, const GLuint *fences); + void (APIENTRY *SetFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *IsFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestFenceAPPLE) (GLuint fence); + void (APIENTRY *FinishFenceAPPLE) (GLuint fence); + GLboolean (APIENTRY *TestObjectAPPLE) (GLenum object, GLuint name); + void (APIENTRY *FinishObjectAPPLE) (GLenum object, GLint name); + void (APIENTRY *BindVertexArrayAPPLE) (GLuint array); + void (APIENTRY *DeleteVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + void (APIENTRY *GenVertexArraysAPPLE) (GLsizei n, const GLuint *arrays); + GLboolean (APIENTRY *IsVertexArrayAPPLE) (GLuint array); + void (APIENTRY *VertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushVertexArrayRangeAPPLE) (GLsizei length, GLvoid *pointer); + void (APIENTRY *VertexArrayParameteriAPPLE) (GLenum pname, GLint param); + void (APIENTRY *DrawBuffersATI) (GLsizei n, const GLenum *bufs); + void (APIENTRY *ProgramNamedParameter4fNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (APIENTRY *ProgramNamedParameter4dNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + void (APIENTRY *ProgramNamedParameter4fvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); + void (APIENTRY *ProgramNamedParameter4dvNV) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); + void (APIENTRY *GetProgramNamedParameterfvNV) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); + void (APIENTRY *GetProgramNamedParameterdvNV) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); + void (APIENTRY *Vertex2hNV) (GLhalfNV x, GLhalfNV y); + void (APIENTRY *Vertex2hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex3hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *Vertex3hvNV) (const GLhalfNV *v); + void (APIENTRY *Vertex4hNV) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *Vertex4hvNV) (const GLhalfNV *v); + void (APIENTRY *Normal3hNV) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); + void (APIENTRY *Normal3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *Color3hvNV) (const GLhalfNV *v); + void (APIENTRY *Color4hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); + void (APIENTRY *Color4hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord1hNV) (GLhalfNV s); + void (APIENTRY *TexCoord1hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord2hNV) (GLhalfNV s, GLhalfNV t); + void (APIENTRY *TexCoord2hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord3hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *TexCoord3hvNV) (const GLhalfNV *v); + void (APIENTRY *TexCoord4hNV) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *TexCoord4hvNV) (const GLhalfNV *v); + void (APIENTRY *MultiTexCoord1hNV) (GLenum target, GLhalfNV s); + void (APIENTRY *MultiTexCoord1hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord2hNV) (GLenum target, GLhalfNV s, GLhalfNV t); + void (APIENTRY *MultiTexCoord2hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord3hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); + void (APIENTRY *MultiTexCoord3hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *MultiTexCoord4hNV) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); + void (APIENTRY *MultiTexCoord4hvNV) (GLenum target, const GLhalfNV *v); + void (APIENTRY *FogCoordhNV) (GLhalfNV fog); + void (APIENTRY *FogCoordhvNV) (const GLhalfNV *fog); + void (APIENTRY *SecondaryColor3hNV) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); + void (APIENTRY *SecondaryColor3hvNV) (const GLhalfNV *v); + void (APIENTRY *VertexWeighthNV) (GLhalfNV weight); + void (APIENTRY *VertexWeighthvNV) (const GLhalfNV *weight); + void (APIENTRY *VertexAttrib1hNV) (GLuint index, GLhalfNV x); + void (APIENTRY *VertexAttrib1hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib2hNV) (GLuint index, GLhalfNV x, GLhalfNV y); + void (APIENTRY *VertexAttrib2hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib3hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); + void (APIENTRY *VertexAttrib3hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttrib4hNV) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); + void (APIENTRY *VertexAttrib4hvNV) (GLuint index, const GLhalfNV *v); + void (APIENTRY *VertexAttribs1hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs2hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs3hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *VertexAttribs4hvNV) (GLuint index, GLsizei n, const GLhalfNV *v); + void (APIENTRY *PixelDataRangeNV) (GLenum target, GLsizei length, GLvoid *pointer); + void (APIENTRY *FlushPixelDataRangeNV) (GLenum target); + void (APIENTRY *PrimitiveRestartNV) (void); + void (APIENTRY *PrimitiveRestartIndexNV) (GLuint index); + GLvoid* (APIENTRY *MapObjectBufferATI) (GLuint buffer); + void (APIENTRY *UnmapObjectBufferATI) (GLuint buffer); + void (APIENTRY *StencilOpSeparateATI) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + void (APIENTRY *StencilFuncSeparateATI) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + void (APIENTRY *VertexAttribArrayObjectATI) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); + void (APIENTRY *GetVertexAttribArrayObjectfvATI) (GLuint index, GLenum pname, GLfloat *params); + void (APIENTRY *GetVertexAttribArrayObjectivATI) (GLuint index, GLenum pname, GLint *params); + void (APIENTRY *DepthBoundsEXT) (GLclampd zmin, GLclampd zmax); + void (APIENTRY *BlendEquationSeparateEXT) (GLenum modeRGB, GLenum modeAlpha); + void (APIENTRY *AddSwapHintRectWIN) (GLint x, GLint y, GLsizei width, GLsizei height); +#ifdef _WIN32 + HANDLE (WINAPI *CreateBufferRegionARB) (HDC hDC, int iLayerPlane, UINT uType); + VOID (WINAPI *DeleteBufferRegionARB) (HANDLE hRegion); + BOOL (WINAPI *SaveBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height); + BOOL (WINAPI *RestoreBufferRegionARB) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); + const int (WINAPI *GetExtensionsStringARB) (HDC hdc); + BOOL (WINAPI *GetPixelFormatAttribivARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvARB) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatARB) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *MakeContextCurrentARB) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCARB) (void); + HPBUFFERARB (WINAPI *CreatePbufferARB) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCARB) (HPBUFFERARB hPbuffer); + int (WINAPI *ReleasePbufferDCARB) (HPBUFFERARB hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferARB) (HPBUFFERARB hPbuffer); + BOOL (WINAPI *QueryPbufferARB) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *BindTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *ReleaseTexImageARB) (HPBUFFERARB hPbuffer, int iBuffer); + BOOL (WINAPI *SetPbufferAttribARB) (HPBUFFERARB hPbuffer, const int *piAttribList); + GLboolean (WINAPI *CreateDisplayColorTableEXT) (GLushort id); + GLboolean (WINAPI *LoadDisplayColorTableEXT) (const GLushort *table, GLuint length); + GLboolean (WINAPI *BindDisplayColorTableEXT) (GLushort id); + VOID (WINAPI *DestroyDisplayColorTableEXT) (GLushort id); + const int (WINAPI *GetExtensionsStringEXT) (void); + BOOL (WINAPI *MakeContextCurrentEXT) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); + HDC (WINAPI *GetCurrentReadDCEXT) (void); + HPBUFFEREXT (WINAPI *CreatePbufferEXT) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); + HDC (WINAPI *GetPbufferDCEXT) (HPBUFFEREXT hPbuffer); + int (WINAPI *ReleasePbufferDCEXT) (HPBUFFEREXT hPbuffer, HDC hDC); + BOOL (WINAPI *DestroyPbufferEXT) (HPBUFFEREXT hPbuffer); + BOOL (WINAPI *QueryPbufferEXT) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); + BOOL (WINAPI *GetPixelFormatAttribivEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); + BOOL (WINAPI *GetPixelFormatAttribfvEXT) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); + BOOL (WINAPI *ChoosePixelFormatEXT) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + BOOL (WINAPI *SwapIntervalEXT) (int interval); + int (WINAPI *GetSwapIntervalEXT) (void); + void* (WINAPI *AllocateMemoryNV) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); + void (WINAPI *FreeMemoryNV) (void); + BOOL (WINAPI *GetSyncValuesOML) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetMscRateOML) (HDC hdc, INT32 *numerator, INT32 *denominator); + INT64 (WINAPI *SwapBuffersMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); + INT64 (WINAPI *SwapLayerBuffersMscOML) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); + BOOL (WINAPI *WaitForMscOML) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *WaitForSbcOML) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); + BOOL (WINAPI *GetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetDigitalVideoParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableParametersI3D) (HDC hDC, int iAttribute, int *piValue); + BOOL (WINAPI *SetGammaTableParametersI3D) (HDC hDC, int iAttribute, const int *piValue); + BOOL (WINAPI *GetGammaTableI3D) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); + BOOL (WINAPI *SetGammaTableI3D) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); + BOOL (WINAPI *EnableGenlockI3D) (HDC hDC); + BOOL (WINAPI *DisableGenlockI3D) (HDC hDC); + BOOL (WINAPI *IsEnabledGenlockI3D) (HDC hDC, BOOL *pFlag); + BOOL (WINAPI *GenlockSourceI3D) (HDC hDC, UINT uSource); + BOOL (WINAPI *GetGenlockSourceI3D) (HDC hDC, UINT *uSource); + BOOL (WINAPI *GenlockSourceEdgeI3D) (HDC hDC, UINT uEdge); + BOOL (WINAPI *GetGenlockSourceEdgeI3D) (HDC hDC, UINT *uEdge); + BOOL (WINAPI *GenlockSampleRateI3D) (HDC hDC, UINT uRate); + BOOL (WINAPI *GetGenlockSampleRateI3D) (HDC hDC, UINT *uRate); + BOOL (WINAPI *GenlockSourceDelayI3D) (HDC hDC, UINT uDelay); + BOOL (WINAPI *GetGenlockSourceDelayI3D) (HDC hDC, UINT *uDelay); + BOOL (WINAPI *QueryGenlockMaxSourceDelayI3D) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); + LPVOID (WINAPI *CreateImageBufferI3D) (HDC hDC, DWORD dwSize, UINT uFlags); + BOOL (WINAPI *DestroyImageBufferI3D) (HDC hDC, LPVOID pAddress); + BOOL (WINAPI *AssociateImageBufferEventsI3D) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); + BOOL (WINAPI *ReleaseImageBufferEventsI3D) (HDC hDC, const LPVOID *pAddress, UINT count); + BOOL (WINAPI *EnableFrameLockI3D) (void); + BOOL (WINAPI *DisableFrameLockI3D) (void); + BOOL (WINAPI *IsEnabledFrameLockI3D) (BOOL *pFlag); + BOOL (WINAPI *QueryFrameLockMasterI3D) (BOOL *pFlag); + BOOL (WINAPI *GetFrameUsageI3D) (float *pUsage); + BOOL (WINAPI *BeginFrameTrackingI3D) (void); + BOOL (WINAPI *EndFrameTrackingI3D) (void); + BOOL (WINAPI *QueryFrameTrackingI3D) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif /* _WIN32 */ +} _GLextensionProcs; + +#define glBlendColor (_GET_TLS_PROCTABLE()->BlendColor) +#define glBlendEquation (_GET_TLS_PROCTABLE()->BlendEquation) +#define glDrawRangeElements (_GET_TLS_PROCTABLE()->DrawRangeElements) +#define glColorTable (_GET_TLS_PROCTABLE()->ColorTable) +#define glColorTableParameterfv (_GET_TLS_PROCTABLE()->ColorTableParameterfv) +#define glColorTableParameteriv (_GET_TLS_PROCTABLE()->ColorTableParameteriv) +#define glCopyColorTable (_GET_TLS_PROCTABLE()->CopyColorTable) +#define glGetColorTable (_GET_TLS_PROCTABLE()->GetColorTable) +#define glGetColorTableParameterfv (_GET_TLS_PROCTABLE()->GetColorTableParameterfv) +#define glGetColorTableParameteriv (_GET_TLS_PROCTABLE()->GetColorTableParameteriv) +#define glColorSubTable (_GET_TLS_PROCTABLE()->ColorSubTable) +#define glCopyColorSubTable (_GET_TLS_PROCTABLE()->CopyColorSubTable) +#define glConvolutionFilter1D (_GET_TLS_PROCTABLE()->ConvolutionFilter1D) +#define glConvolutionFilter2D (_GET_TLS_PROCTABLE()->ConvolutionFilter2D) +#define glConvolutionParameterf (_GET_TLS_PROCTABLE()->ConvolutionParameterf) +#define glConvolutionParameterfv (_GET_TLS_PROCTABLE()->ConvolutionParameterfv) +#define glConvolutionParameteri (_GET_TLS_PROCTABLE()->ConvolutionParameteri) +#define glConvolutionParameteriv (_GET_TLS_PROCTABLE()->ConvolutionParameteriv) +#define glCopyConvolutionFilter1D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1D) +#define glCopyConvolutionFilter2D (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2D) +#define glGetConvolutionFilter (_GET_TLS_PROCTABLE()->GetConvolutionFilter) +#define glGetConvolutionParameterfv (_GET_TLS_PROCTABLE()->GetConvolutionParameterfv) +#define glGetConvolutionParameteriv (_GET_TLS_PROCTABLE()->GetConvolutionParameteriv) +#define glGetSeparableFilter (_GET_TLS_PROCTABLE()->GetSeparableFilter) +#define glSeparableFilter2D (_GET_TLS_PROCTABLE()->SeparableFilter2D) +#define glGetHistogram (_GET_TLS_PROCTABLE()->GetHistogram) +#define glGetHistogramParameterfv (_GET_TLS_PROCTABLE()->GetHistogramParameterfv) +#define glGetHistogramParameteriv (_GET_TLS_PROCTABLE()->GetHistogramParameteriv) +#define glGetMinmax (_GET_TLS_PROCTABLE()->GetMinmax) +#define glGetMinmaxParameterfv (_GET_TLS_PROCTABLE()->GetMinmaxParameterfv) +#define glGetMinmaxParameteriv (_GET_TLS_PROCTABLE()->GetMinmaxParameteriv) +#define glHistogram (_GET_TLS_PROCTABLE()->Histogram) +#define glMinmax (_GET_TLS_PROCTABLE()->Minmax) +#define glResetHistogram (_GET_TLS_PROCTABLE()->ResetHistogram) +#define glResetMinmax (_GET_TLS_PROCTABLE()->ResetMinmax) +#define glTexImage3D (_GET_TLS_PROCTABLE()->TexImage3D) +#define glTexSubImage3D (_GET_TLS_PROCTABLE()->TexSubImage3D) +#define glCopyTexSubImage3D (_GET_TLS_PROCTABLE()->CopyTexSubImage3D) +#define glActiveTexture (_GET_TLS_PROCTABLE()->ActiveTexture) +#define glClientActiveTexture (_GET_TLS_PROCTABLE()->ClientActiveTexture) +#define glMultiTexCoord1d (_GET_TLS_PROCTABLE()->MultiTexCoord1d) +#define glMultiTexCoord1dv (_GET_TLS_PROCTABLE()->MultiTexCoord1dv) +#define glMultiTexCoord1f (_GET_TLS_PROCTABLE()->MultiTexCoord1f) +#define glMultiTexCoord1fv (_GET_TLS_PROCTABLE()->MultiTexCoord1fv) +#define glMultiTexCoord1i (_GET_TLS_PROCTABLE()->MultiTexCoord1i) +#define glMultiTexCoord1iv (_GET_TLS_PROCTABLE()->MultiTexCoord1iv) +#define glMultiTexCoord1s (_GET_TLS_PROCTABLE()->MultiTexCoord1s) +#define glMultiTexCoord1sv (_GET_TLS_PROCTABLE()->MultiTexCoord1sv) +#define glMultiTexCoord2d (_GET_TLS_PROCTABLE()->MultiTexCoord2d) +#define glMultiTexCoord2dv (_GET_TLS_PROCTABLE()->MultiTexCoord2dv) +#define glMultiTexCoord2f (_GET_TLS_PROCTABLE()->MultiTexCoord2f) +#define glMultiTexCoord2fv (_GET_TLS_PROCTABLE()->MultiTexCoord2fv) +#define glMultiTexCoord2i (_GET_TLS_PROCTABLE()->MultiTexCoord2i) +#define glMultiTexCoord2iv (_GET_TLS_PROCTABLE()->MultiTexCoord2iv) +#define glMultiTexCoord2s (_GET_TLS_PROCTABLE()->MultiTexCoord2s) +#define glMultiTexCoord2sv (_GET_TLS_PROCTABLE()->MultiTexCoord2sv) +#define glMultiTexCoord3d (_GET_TLS_PROCTABLE()->MultiTexCoord3d) +#define glMultiTexCoord3dv (_GET_TLS_PROCTABLE()->MultiTexCoord3dv) +#define glMultiTexCoord3f (_GET_TLS_PROCTABLE()->MultiTexCoord3f) +#define glMultiTexCoord3fv (_GET_TLS_PROCTABLE()->MultiTexCoord3fv) +#define glMultiTexCoord3i (_GET_TLS_PROCTABLE()->MultiTexCoord3i) +#define glMultiTexCoord3iv (_GET_TLS_PROCTABLE()->MultiTexCoord3iv) +#define glMultiTexCoord3s (_GET_TLS_PROCTABLE()->MultiTexCoord3s) +#define glMultiTexCoord3sv (_GET_TLS_PROCTABLE()->MultiTexCoord3sv) +#define glMultiTexCoord4d (_GET_TLS_PROCTABLE()->MultiTexCoord4d) +#define glMultiTexCoord4dv (_GET_TLS_PROCTABLE()->MultiTexCoord4dv) +#define glMultiTexCoord4f (_GET_TLS_PROCTABLE()->MultiTexCoord4f) +#define glMultiTexCoord4fv (_GET_TLS_PROCTABLE()->MultiTexCoord4fv) +#define glMultiTexCoord4i (_GET_TLS_PROCTABLE()->MultiTexCoord4i) +#define glMultiTexCoord4iv (_GET_TLS_PROCTABLE()->MultiTexCoord4iv) +#define glMultiTexCoord4s (_GET_TLS_PROCTABLE()->MultiTexCoord4s) +#define glMultiTexCoord4sv (_GET_TLS_PROCTABLE()->MultiTexCoord4sv) +#define glLoadTransposeMatrixf (_GET_TLS_PROCTABLE()->LoadTransposeMatrixf) +#define glLoadTransposeMatrixd (_GET_TLS_PROCTABLE()->LoadTransposeMatrixd) +#define glMultTransposeMatrixf (_GET_TLS_PROCTABLE()->MultTransposeMatrixf) +#define glMultTransposeMatrixd (_GET_TLS_PROCTABLE()->MultTransposeMatrixd) +#define glSampleCoverage (_GET_TLS_PROCTABLE()->SampleCoverage) +#define glCompressedTexImage3D (_GET_TLS_PROCTABLE()->CompressedTexImage3D) +#define glCompressedTexImage2D (_GET_TLS_PROCTABLE()->CompressedTexImage2D) +#define glCompressedTexImage1D (_GET_TLS_PROCTABLE()->CompressedTexImage1D) +#define glCompressedTexSubImage3D (_GET_TLS_PROCTABLE()->CompressedTexSubImage3D) +#define glCompressedTexSubImage2D (_GET_TLS_PROCTABLE()->CompressedTexSubImage2D) +#define glCompressedTexSubImage1D (_GET_TLS_PROCTABLE()->CompressedTexSubImage1D) +#define glGetCompressedTexImage (_GET_TLS_PROCTABLE()->GetCompressedTexImage) +#define glBlendFuncSeparate (_GET_TLS_PROCTABLE()->BlendFuncSeparate) +#define glFogCoordf (_GET_TLS_PROCTABLE()->FogCoordf) +#define glFogCoordfv (_GET_TLS_PROCTABLE()->FogCoordfv) +#define glFogCoordd (_GET_TLS_PROCTABLE()->FogCoordd) +#define glFogCoorddv (_GET_TLS_PROCTABLE()->FogCoorddv) +#define glFogCoordPointer (_GET_TLS_PROCTABLE()->FogCoordPointer) +#define glMultiDrawArrays (_GET_TLS_PROCTABLE()->MultiDrawArrays) +#define glMultiDrawElements (_GET_TLS_PROCTABLE()->MultiDrawElements) +#define glPointParameterf (_GET_TLS_PROCTABLE()->PointParameterf) +#define glPointParameterfv (_GET_TLS_PROCTABLE()->PointParameterfv) +#define glPointParameteri (_GET_TLS_PROCTABLE()->PointParameteri) +#define glPointParameteriv (_GET_TLS_PROCTABLE()->PointParameteriv) +#define glSecondaryColor3b (_GET_TLS_PROCTABLE()->SecondaryColor3b) +#define glSecondaryColor3bv (_GET_TLS_PROCTABLE()->SecondaryColor3bv) +#define glSecondaryColor3d (_GET_TLS_PROCTABLE()->SecondaryColor3d) +#define glSecondaryColor3dv (_GET_TLS_PROCTABLE()->SecondaryColor3dv) +#define glSecondaryColor3f (_GET_TLS_PROCTABLE()->SecondaryColor3f) +#define glSecondaryColor3fv (_GET_TLS_PROCTABLE()->SecondaryColor3fv) +#define glSecondaryColor3i (_GET_TLS_PROCTABLE()->SecondaryColor3i) +#define glSecondaryColor3iv (_GET_TLS_PROCTABLE()->SecondaryColor3iv) +#define glSecondaryColor3s (_GET_TLS_PROCTABLE()->SecondaryColor3s) +#define glSecondaryColor3sv (_GET_TLS_PROCTABLE()->SecondaryColor3sv) +#define glSecondaryColor3ub (_GET_TLS_PROCTABLE()->SecondaryColor3ub) +#define glSecondaryColor3ubv (_GET_TLS_PROCTABLE()->SecondaryColor3ubv) +#define glSecondaryColor3ui (_GET_TLS_PROCTABLE()->SecondaryColor3ui) +#define glSecondaryColor3uiv (_GET_TLS_PROCTABLE()->SecondaryColor3uiv) +#define glSecondaryColor3us (_GET_TLS_PROCTABLE()->SecondaryColor3us) +#define glSecondaryColor3usv (_GET_TLS_PROCTABLE()->SecondaryColor3usv) +#define glSecondaryColorPointer (_GET_TLS_PROCTABLE()->SecondaryColorPointer) +#define glWindowPos2d (_GET_TLS_PROCTABLE()->WindowPos2d) +#define glWindowPos2dv (_GET_TLS_PROCTABLE()->WindowPos2dv) +#define glWindowPos2f (_GET_TLS_PROCTABLE()->WindowPos2f) +#define glWindowPos2fv (_GET_TLS_PROCTABLE()->WindowPos2fv) +#define glWindowPos2i (_GET_TLS_PROCTABLE()->WindowPos2i) +#define glWindowPos2iv (_GET_TLS_PROCTABLE()->WindowPos2iv) +#define glWindowPos2s (_GET_TLS_PROCTABLE()->WindowPos2s) +#define glWindowPos2sv (_GET_TLS_PROCTABLE()->WindowPos2sv) +#define glWindowPos3d (_GET_TLS_PROCTABLE()->WindowPos3d) +#define glWindowPos3dv (_GET_TLS_PROCTABLE()->WindowPos3dv) +#define glWindowPos3f (_GET_TLS_PROCTABLE()->WindowPos3f) +#define glWindowPos3fv (_GET_TLS_PROCTABLE()->WindowPos3fv) +#define glWindowPos3i (_GET_TLS_PROCTABLE()->WindowPos3i) +#define glWindowPos3iv (_GET_TLS_PROCTABLE()->WindowPos3iv) +#define glWindowPos3s (_GET_TLS_PROCTABLE()->WindowPos3s) +#define glWindowPos3sv (_GET_TLS_PROCTABLE()->WindowPos3sv) +#define glGenQueries (_GET_TLS_PROCTABLE()->GenQueries) +#define glDeleteQueries (_GET_TLS_PROCTABLE()->DeleteQueries) +#define glIsQuery (_GET_TLS_PROCTABLE()->IsQuery) +#define glBeginQuery (_GET_TLS_PROCTABLE()->BeginQuery) +#define glEndQuery (_GET_TLS_PROCTABLE()->EndQuery) +#define glGetQueryiv (_GET_TLS_PROCTABLE()->GetQueryiv) +#define glGetQueryObjectiv (_GET_TLS_PROCTABLE()->GetQueryObjectiv) +#define glGetQueryObjectuiv (_GET_TLS_PROCTABLE()->GetQueryObjectuiv) +#define glBindBuffer (_GET_TLS_PROCTABLE()->BindBuffer) +#define glDeleteBuffers (_GET_TLS_PROCTABLE()->DeleteBuffers) +#define glGenBuffers (_GET_TLS_PROCTABLE()->GenBuffers) +#define glIsBuffer (_GET_TLS_PROCTABLE()->IsBuffer) +#define glBufferData (_GET_TLS_PROCTABLE()->BufferData) +#define glBufferSubData (_GET_TLS_PROCTABLE()->BufferSubData) +#define glGetBufferSubData (_GET_TLS_PROCTABLE()->GetBufferSubData) +#define glMapBuffer (_GET_TLS_PROCTABLE()->MapBuffer) +#define glUnmapBuffer (_GET_TLS_PROCTABLE()->UnmapBuffer) +#define glGetBufferParameteriv (_GET_TLS_PROCTABLE()->GetBufferParameteriv) +#define glGetBufferPointerv (_GET_TLS_PROCTABLE()->GetBufferPointerv) +#define glActiveTextureARB (_GET_TLS_PROCTABLE()->ActiveTextureARB) +#define glClientActiveTextureARB (_GET_TLS_PROCTABLE()->ClientActiveTextureARB) +#define glMultiTexCoord1dARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dARB) +#define glMultiTexCoord1dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1dvARB) +#define glMultiTexCoord1fARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fARB) +#define glMultiTexCoord1fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord1fvARB) +#define glMultiTexCoord1iARB (_GET_TLS_PROCTABLE()->MultiTexCoord1iARB) +#define glMultiTexCoord1ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord1ivARB) +#define glMultiTexCoord1sARB (_GET_TLS_PROCTABLE()->MultiTexCoord1sARB) +#define glMultiTexCoord1svARB (_GET_TLS_PROCTABLE()->MultiTexCoord1svARB) +#define glMultiTexCoord2dARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dARB) +#define glMultiTexCoord2dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2dvARB) +#define glMultiTexCoord2fARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fARB) +#define glMultiTexCoord2fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord2fvARB) +#define glMultiTexCoord2iARB (_GET_TLS_PROCTABLE()->MultiTexCoord2iARB) +#define glMultiTexCoord2ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord2ivARB) +#define glMultiTexCoord2sARB (_GET_TLS_PROCTABLE()->MultiTexCoord2sARB) +#define glMultiTexCoord2svARB (_GET_TLS_PROCTABLE()->MultiTexCoord2svARB) +#define glMultiTexCoord3dARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dARB) +#define glMultiTexCoord3dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3dvARB) +#define glMultiTexCoord3fARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fARB) +#define glMultiTexCoord3fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord3fvARB) +#define glMultiTexCoord3iARB (_GET_TLS_PROCTABLE()->MultiTexCoord3iARB) +#define glMultiTexCoord3ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord3ivARB) +#define glMultiTexCoord3sARB (_GET_TLS_PROCTABLE()->MultiTexCoord3sARB) +#define glMultiTexCoord3svARB (_GET_TLS_PROCTABLE()->MultiTexCoord3svARB) +#define glMultiTexCoord4dARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dARB) +#define glMultiTexCoord4dvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4dvARB) +#define glMultiTexCoord4fARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fARB) +#define glMultiTexCoord4fvARB (_GET_TLS_PROCTABLE()->MultiTexCoord4fvARB) +#define glMultiTexCoord4iARB (_GET_TLS_PROCTABLE()->MultiTexCoord4iARB) +#define glMultiTexCoord4ivARB (_GET_TLS_PROCTABLE()->MultiTexCoord4ivARB) +#define glMultiTexCoord4sARB (_GET_TLS_PROCTABLE()->MultiTexCoord4sARB) +#define glMultiTexCoord4svARB (_GET_TLS_PROCTABLE()->MultiTexCoord4svARB) +#define glLoadTransposeMatrixfARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixfARB) +#define glLoadTransposeMatrixdARB (_GET_TLS_PROCTABLE()->LoadTransposeMatrixdARB) +#define glMultTransposeMatrixfARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixfARB) +#define glMultTransposeMatrixdARB (_GET_TLS_PROCTABLE()->MultTransposeMatrixdARB) +#define glSampleCoverageARB (_GET_TLS_PROCTABLE()->SampleCoverageARB) +#define glCompressedTexImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexImage3DARB) +#define glCompressedTexImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexImage2DARB) +#define glCompressedTexImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexImage1DARB) +#define glCompressedTexSubImage3DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage3DARB) +#define glCompressedTexSubImage2DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage2DARB) +#define glCompressedTexSubImage1DARB (_GET_TLS_PROCTABLE()->CompressedTexSubImage1DARB) +#define glGetCompressedTexImageARB (_GET_TLS_PROCTABLE()->GetCompressedTexImageARB) +#define glPointParameterfARB (_GET_TLS_PROCTABLE()->PointParameterfARB) +#define glPointParameterfvARB (_GET_TLS_PROCTABLE()->PointParameterfvARB) +#define glWeightbvARB (_GET_TLS_PROCTABLE()->WeightbvARB) +#define glWeightsvARB (_GET_TLS_PROCTABLE()->WeightsvARB) +#define glWeightivARB (_GET_TLS_PROCTABLE()->WeightivARB) +#define glWeightfvARB (_GET_TLS_PROCTABLE()->WeightfvARB) +#define glWeightdvARB (_GET_TLS_PROCTABLE()->WeightdvARB) +#define glWeightubvARB (_GET_TLS_PROCTABLE()->WeightubvARB) +#define glWeightusvARB (_GET_TLS_PROCTABLE()->WeightusvARB) +#define glWeightuivARB (_GET_TLS_PROCTABLE()->WeightuivARB) +#define glWeightPointerARB (_GET_TLS_PROCTABLE()->WeightPointerARB) +#define glVertexBlendARB (_GET_TLS_PROCTABLE()->VertexBlendARB) +#define glCurrentPaletteMatrixARB (_GET_TLS_PROCTABLE()->CurrentPaletteMatrixARB) +#define glMatrixIndexubvARB (_GET_TLS_PROCTABLE()->MatrixIndexubvARB) +#define glMatrixIndexusvARB (_GET_TLS_PROCTABLE()->MatrixIndexusvARB) +#define glMatrixIndexuivARB (_GET_TLS_PROCTABLE()->MatrixIndexuivARB) +#define glMatrixIndexPointerARB (_GET_TLS_PROCTABLE()->MatrixIndexPointerARB) +#define glWindowPos2dARB (_GET_TLS_PROCTABLE()->WindowPos2dARB) +#define glWindowPos2dvARB (_GET_TLS_PROCTABLE()->WindowPos2dvARB) +#define glWindowPos2fARB (_GET_TLS_PROCTABLE()->WindowPos2fARB) +#define glWindowPos2fvARB (_GET_TLS_PROCTABLE()->WindowPos2fvARB) +#define glWindowPos2iARB (_GET_TLS_PROCTABLE()->WindowPos2iARB) +#define glWindowPos2ivARB (_GET_TLS_PROCTABLE()->WindowPos2ivARB) +#define glWindowPos2sARB (_GET_TLS_PROCTABLE()->WindowPos2sARB) +#define glWindowPos2svARB (_GET_TLS_PROCTABLE()->WindowPos2svARB) +#define glWindowPos3dARB (_GET_TLS_PROCTABLE()->WindowPos3dARB) +#define glWindowPos3dvARB (_GET_TLS_PROCTABLE()->WindowPos3dvARB) +#define glWindowPos3fARB (_GET_TLS_PROCTABLE()->WindowPos3fARB) +#define glWindowPos3fvARB (_GET_TLS_PROCTABLE()->WindowPos3fvARB) +#define glWindowPos3iARB (_GET_TLS_PROCTABLE()->WindowPos3iARB) +#define glWindowPos3ivARB (_GET_TLS_PROCTABLE()->WindowPos3ivARB) +#define glWindowPos3sARB (_GET_TLS_PROCTABLE()->WindowPos3sARB) +#define glWindowPos3svARB (_GET_TLS_PROCTABLE()->WindowPos3svARB) +#define glVertexAttrib1dARB (_GET_TLS_PROCTABLE()->VertexAttrib1dARB) +#define glVertexAttrib1dvARB (_GET_TLS_PROCTABLE()->VertexAttrib1dvARB) +#define glVertexAttrib1fARB (_GET_TLS_PROCTABLE()->VertexAttrib1fARB) +#define glVertexAttrib1fvARB (_GET_TLS_PROCTABLE()->VertexAttrib1fvARB) +#define glVertexAttrib1sARB (_GET_TLS_PROCTABLE()->VertexAttrib1sARB) +#define glVertexAttrib1svARB (_GET_TLS_PROCTABLE()->VertexAttrib1svARB) +#define glVertexAttrib2dARB (_GET_TLS_PROCTABLE()->VertexAttrib2dARB) +#define glVertexAttrib2dvARB (_GET_TLS_PROCTABLE()->VertexAttrib2dvARB) +#define glVertexAttrib2fARB (_GET_TLS_PROCTABLE()->VertexAttrib2fARB) +#define glVertexAttrib2fvARB (_GET_TLS_PROCTABLE()->VertexAttrib2fvARB) +#define glVertexAttrib2sARB (_GET_TLS_PROCTABLE()->VertexAttrib2sARB) +#define glVertexAttrib2svARB (_GET_TLS_PROCTABLE()->VertexAttrib2svARB) +#define glVertexAttrib3dARB (_GET_TLS_PROCTABLE()->VertexAttrib3dARB) +#define glVertexAttrib3dvARB (_GET_TLS_PROCTABLE()->VertexAttrib3dvARB) +#define glVertexAttrib3fARB (_GET_TLS_PROCTABLE()->VertexAttrib3fARB) +#define glVertexAttrib3fvARB (_GET_TLS_PROCTABLE()->VertexAttrib3fvARB) +#define glVertexAttrib3sARB (_GET_TLS_PROCTABLE()->VertexAttrib3sARB) +#define glVertexAttrib3svARB (_GET_TLS_PROCTABLE()->VertexAttrib3svARB) +#define glVertexAttrib4NbvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NbvARB) +#define glVertexAttrib4NivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NivARB) +#define glVertexAttrib4NsvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NsvARB) +#define glVertexAttrib4NubARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubARB) +#define glVertexAttrib4NubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NubvARB) +#define glVertexAttrib4NuivARB (_GET_TLS_PROCTABLE()->VertexAttrib4NuivARB) +#define glVertexAttrib4NusvARB (_GET_TLS_PROCTABLE()->VertexAttrib4NusvARB) +#define glVertexAttrib4bvARB (_GET_TLS_PROCTABLE()->VertexAttrib4bvARB) +#define glVertexAttrib4dARB (_GET_TLS_PROCTABLE()->VertexAttrib4dARB) +#define glVertexAttrib4dvARB (_GET_TLS_PROCTABLE()->VertexAttrib4dvARB) +#define glVertexAttrib4fARB (_GET_TLS_PROCTABLE()->VertexAttrib4fARB) +#define glVertexAttrib4fvARB (_GET_TLS_PROCTABLE()->VertexAttrib4fvARB) +#define glVertexAttrib4ivARB (_GET_TLS_PROCTABLE()->VertexAttrib4ivARB) +#define glVertexAttrib4sARB (_GET_TLS_PROCTABLE()->VertexAttrib4sARB) +#define glVertexAttrib4svARB (_GET_TLS_PROCTABLE()->VertexAttrib4svARB) +#define glVertexAttrib4ubvARB (_GET_TLS_PROCTABLE()->VertexAttrib4ubvARB) +#define glVertexAttrib4uivARB (_GET_TLS_PROCTABLE()->VertexAttrib4uivARB) +#define glVertexAttrib4usvARB (_GET_TLS_PROCTABLE()->VertexAttrib4usvARB) +#define glVertexAttribPointerARB (_GET_TLS_PROCTABLE()->VertexAttribPointerARB) +#define glEnableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->EnableVertexAttribArrayARB) +#define glDisableVertexAttribArrayARB (_GET_TLS_PROCTABLE()->DisableVertexAttribArrayARB) +#define glProgramStringARB (_GET_TLS_PROCTABLE()->ProgramStringARB) +#define glBindProgramARB (_GET_TLS_PROCTABLE()->BindProgramARB) +#define glDeleteProgramsARB (_GET_TLS_PROCTABLE()->DeleteProgramsARB) +#define glGenProgramsARB (_GET_TLS_PROCTABLE()->GenProgramsARB) +#define glProgramEnvParameter4dARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dARB) +#define glProgramEnvParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4dvARB) +#define glProgramEnvParameter4fARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fARB) +#define glProgramEnvParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramEnvParameter4fvARB) +#define glProgramLocalParameter4dARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dARB) +#define glProgramLocalParameter4dvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4dvARB) +#define glProgramLocalParameter4fARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fARB) +#define glProgramLocalParameter4fvARB (_GET_TLS_PROCTABLE()->ProgramLocalParameter4fvARB) +#define glGetProgramEnvParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterdvARB) +#define glGetProgramEnvParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramEnvParameterfvARB) +#define glGetProgramLocalParameterdvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterdvARB) +#define glGetProgramLocalParameterfvARB (_GET_TLS_PROCTABLE()->GetProgramLocalParameterfvARB) +#define glGetProgramivARB (_GET_TLS_PROCTABLE()->GetProgramivARB) +#define glGetProgramStringARB (_GET_TLS_PROCTABLE()->GetProgramStringARB) +#define glGetVertexAttribdvARB (_GET_TLS_PROCTABLE()->GetVertexAttribdvARB) +#define glGetVertexAttribfvARB (_GET_TLS_PROCTABLE()->GetVertexAttribfvARB) +#define glGetVertexAttribivARB (_GET_TLS_PROCTABLE()->GetVertexAttribivARB) +#define glGetVertexAttribPointervARB (_GET_TLS_PROCTABLE()->GetVertexAttribPointervARB) +#define glIsProgramARB (_GET_TLS_PROCTABLE()->IsProgramARB) +#define glBindBufferARB (_GET_TLS_PROCTABLE()->BindBufferARB) +#define glDeleteBuffersARB (_GET_TLS_PROCTABLE()->DeleteBuffersARB) +#define glGenBuffersARB (_GET_TLS_PROCTABLE()->GenBuffersARB) +#define glIsBufferARB (_GET_TLS_PROCTABLE()->IsBufferARB) +#define glBufferDataARB (_GET_TLS_PROCTABLE()->BufferDataARB) +#define glBufferSubDataARB (_GET_TLS_PROCTABLE()->BufferSubDataARB) +#define glGetBufferSubDataARB (_GET_TLS_PROCTABLE()->GetBufferSubDataARB) +#define glMapBufferARB (_GET_TLS_PROCTABLE()->MapBufferARB) +#define glUnmapBufferARB (_GET_TLS_PROCTABLE()->UnmapBufferARB) +#define glGetBufferParameterivARB (_GET_TLS_PROCTABLE()->GetBufferParameterivARB) +#define glGetBufferPointervARB (_GET_TLS_PROCTABLE()->GetBufferPointervARB) +#define glGenQueriesARB (_GET_TLS_PROCTABLE()->GenQueriesARB) +#define glDeleteQueriesARB (_GET_TLS_PROCTABLE()->DeleteQueriesARB) +#define glIsQueryARB (_GET_TLS_PROCTABLE()->IsQueryARB) +#define glBeginQueryARB (_GET_TLS_PROCTABLE()->BeginQueryARB) +#define glEndQueryARB (_GET_TLS_PROCTABLE()->EndQueryARB) +#define glGetQueryivARB (_GET_TLS_PROCTABLE()->GetQueryivARB) +#define glGetQueryObjectivARB (_GET_TLS_PROCTABLE()->GetQueryObjectivARB) +#define glGetQueryObjectuivARB (_GET_TLS_PROCTABLE()->GetQueryObjectuivARB) +#define glDeleteObjectARB (_GET_TLS_PROCTABLE()->DeleteObjectARB) +#define glGetHandleARB (_GET_TLS_PROCTABLE()->GetHandleARB) +#define glDetachObjectARB (_GET_TLS_PROCTABLE()->DetachObjectARB) +#define glCreateShaderObjectARB (_GET_TLS_PROCTABLE()->CreateShaderObjectARB) +#define glShaderSourceARB (_GET_TLS_PROCTABLE()->ShaderSourceARB) +#define glCompileShaderARB (_GET_TLS_PROCTABLE()->CompileShaderARB) +#define glCreateProgramObjectARB (_GET_TLS_PROCTABLE()->CreateProgramObjectARB) +#define glAttachObjectARB (_GET_TLS_PROCTABLE()->AttachObjectARB) +#define glLinkProgramARB (_GET_TLS_PROCTABLE()->LinkProgramARB) +#define glUseProgramObjectARB (_GET_TLS_PROCTABLE()->UseProgramObjectARB) +#define glValidateProgramARB (_GET_TLS_PROCTABLE()->ValidateProgramARB) +#define glUniform1fARB (_GET_TLS_PROCTABLE()->Uniform1fARB) +#define glUniform2fARB (_GET_TLS_PROCTABLE()->Uniform2fARB) +#define glUniform3fARB (_GET_TLS_PROCTABLE()->Uniform3fARB) +#define glUniform4fARB (_GET_TLS_PROCTABLE()->Uniform4fARB) +#define glUniform1iARB (_GET_TLS_PROCTABLE()->Uniform1iARB) +#define glUniform2iARB (_GET_TLS_PROCTABLE()->Uniform2iARB) +#define glUniform3iARB (_GET_TLS_PROCTABLE()->Uniform3iARB) +#define glUniform4iARB (_GET_TLS_PROCTABLE()->Uniform4iARB) +#define glUniform1fvARB (_GET_TLS_PROCTABLE()->Uniform1fvARB) +#define glUniform2fvARB (_GET_TLS_PROCTABLE()->Uniform2fvARB) +#define glUniform3fvARB (_GET_TLS_PROCTABLE()->Uniform3fvARB) +#define glUniform4fvARB (_GET_TLS_PROCTABLE()->Uniform4fvARB) +#define glUniform1ivARB (_GET_TLS_PROCTABLE()->Uniform1ivARB) +#define glUniform2ivARB (_GET_TLS_PROCTABLE()->Uniform2ivARB) +#define glUniform3ivARB (_GET_TLS_PROCTABLE()->Uniform3ivARB) +#define glUniform4ivARB (_GET_TLS_PROCTABLE()->Uniform4ivARB) +#define glUniformMatrix2fvARB (_GET_TLS_PROCTABLE()->UniformMatrix2fvARB) +#define glUniformMatrix3fvARB (_GET_TLS_PROCTABLE()->UniformMatrix3fvARB) +#define glUniformMatrix4fvARB (_GET_TLS_PROCTABLE()->UniformMatrix4fvARB) +#define glGetObjectParameterfvARB (_GET_TLS_PROCTABLE()->GetObjectParameterfvARB) +#define glGetObjectParameterivARB (_GET_TLS_PROCTABLE()->GetObjectParameterivARB) +#define glGetInfoLogARB (_GET_TLS_PROCTABLE()->GetInfoLogARB) +#define glGetAttachedObjectsARB (_GET_TLS_PROCTABLE()->GetAttachedObjectsARB) +#define glGetUniformLocationARB (_GET_TLS_PROCTABLE()->GetUniformLocationARB) +#define glGetActiveUniformARB (_GET_TLS_PROCTABLE()->GetActiveUniformARB) +#define glGetUniformfvARB (_GET_TLS_PROCTABLE()->GetUniformfvARB) +#define glGetUniformivARB (_GET_TLS_PROCTABLE()->GetUniformivARB) +#define glGetShaderSourceARB (_GET_TLS_PROCTABLE()->GetShaderSourceARB) +#define glBindAttribLocationARB (_GET_TLS_PROCTABLE()->BindAttribLocationARB) +#define glGetActiveAttribARB (_GET_TLS_PROCTABLE()->GetActiveAttribARB) +#define glGetAttribLocationARB (_GET_TLS_PROCTABLE()->GetAttribLocationARB) +#define glBlendColorEXT (_GET_TLS_PROCTABLE()->BlendColorEXT) +#define glPolygonOffsetEXT (_GET_TLS_PROCTABLE()->PolygonOffsetEXT) +#define glTexImage3DEXT (_GET_TLS_PROCTABLE()->TexImage3DEXT) +#define glTexSubImage3DEXT (_GET_TLS_PROCTABLE()->TexSubImage3DEXT) +#define glGetTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->GetTexFilterFuncSGIS) +#define glTexFilterFuncSGIS (_GET_TLS_PROCTABLE()->TexFilterFuncSGIS) +#define glTexSubImage1DEXT (_GET_TLS_PROCTABLE()->TexSubImage1DEXT) +#define glTexSubImage2DEXT (_GET_TLS_PROCTABLE()->TexSubImage2DEXT) +#define glCopyTexImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexImage1DEXT) +#define glCopyTexImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexImage2DEXT) +#define glCopyTexSubImage1DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage1DEXT) +#define glCopyTexSubImage2DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage2DEXT) +#define glCopyTexSubImage3DEXT (_GET_TLS_PROCTABLE()->CopyTexSubImage3DEXT) +#define glGetHistogramEXT (_GET_TLS_PROCTABLE()->GetHistogramEXT) +#define glGetHistogramParameterfvEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterfvEXT) +#define glGetHistogramParameterivEXT (_GET_TLS_PROCTABLE()->GetHistogramParameterivEXT) +#define glGetMinmaxEXT (_GET_TLS_PROCTABLE()->GetMinmaxEXT) +#define glGetMinmaxParameterfvEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterfvEXT) +#define glGetMinmaxParameterivEXT (_GET_TLS_PROCTABLE()->GetMinmaxParameterivEXT) +#define glHistogramEXT (_GET_TLS_PROCTABLE()->HistogramEXT) +#define glMinmaxEXT (_GET_TLS_PROCTABLE()->MinmaxEXT) +#define glResetHistogramEXT (_GET_TLS_PROCTABLE()->ResetHistogramEXT) +#define glResetMinmaxEXT (_GET_TLS_PROCTABLE()->ResetMinmaxEXT) +#define glConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter1DEXT) +#define glConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->ConvolutionFilter2DEXT) +#define glConvolutionParameterfEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfEXT) +#define glConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterfvEXT) +#define glConvolutionParameteriEXT (_GET_TLS_PROCTABLE()->ConvolutionParameteriEXT) +#define glConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->ConvolutionParameterivEXT) +#define glCopyConvolutionFilter1DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter1DEXT) +#define glCopyConvolutionFilter2DEXT (_GET_TLS_PROCTABLE()->CopyConvolutionFilter2DEXT) +#define glGetConvolutionFilterEXT (_GET_TLS_PROCTABLE()->GetConvolutionFilterEXT) +#define glGetConvolutionParameterfvEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterfvEXT) +#define glGetConvolutionParameterivEXT (_GET_TLS_PROCTABLE()->GetConvolutionParameterivEXT) +#define glGetSeparableFilterEXT (_GET_TLS_PROCTABLE()->GetSeparableFilterEXT) +#define glSeparableFilter2DEXT (_GET_TLS_PROCTABLE()->SeparableFilter2DEXT) +#define glColorTableSGI (_GET_TLS_PROCTABLE()->ColorTableSGI) +#define glColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->ColorTableParameterfvSGI) +#define glColorTableParameterivSGI (_GET_TLS_PROCTABLE()->ColorTableParameterivSGI) +#define glCopyColorTableSGI (_GET_TLS_PROCTABLE()->CopyColorTableSGI) +#define glGetColorTableSGI (_GET_TLS_PROCTABLE()->GetColorTableSGI) +#define glGetColorTableParameterfvSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterfvSGI) +#define glGetColorTableParameterivSGI (_GET_TLS_PROCTABLE()->GetColorTableParameterivSGI) +#define glPixelTexGenSGIX (_GET_TLS_PROCTABLE()->PixelTexGenSGIX) +#define glPixelTexGenParameteriSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameteriSGIS) +#define glPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterivSGIS) +#define glPixelTexGenParameterfSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfSGIS) +#define glPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->PixelTexGenParameterfvSGIS) +#define glGetPixelTexGenParameterivSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterivSGIS) +#define glGetPixelTexGenParameterfvSGIS (_GET_TLS_PROCTABLE()->GetPixelTexGenParameterfvSGIS) +#define glTexImage4DSGIS (_GET_TLS_PROCTABLE()->TexImage4DSGIS) +#define glTexSubImage4DSGIS (_GET_TLS_PROCTABLE()->TexSubImage4DSGIS) +#define glAreTexturesResidentEXT (_GET_TLS_PROCTABLE()->AreTexturesResidentEXT) +#define glBindTextureEXT (_GET_TLS_PROCTABLE()->BindTextureEXT) +#define glDeleteTexturesEXT (_GET_TLS_PROCTABLE()->DeleteTexturesEXT) +#define glGenTexturesEXT (_GET_TLS_PROCTABLE()->GenTexturesEXT) +#define glIsTextureEXT (_GET_TLS_PROCTABLE()->IsTextureEXT) +#define glPrioritizeTexturesEXT (_GET_TLS_PROCTABLE()->PrioritizeTexturesEXT) +#define glDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->DetailTexFuncSGIS) +#define glGetDetailTexFuncSGIS (_GET_TLS_PROCTABLE()->GetDetailTexFuncSGIS) +#define glSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->SharpenTexFuncSGIS) +#define glGetSharpenTexFuncSGIS (_GET_TLS_PROCTABLE()->GetSharpenTexFuncSGIS) +#define glSampleMaskSGIS (_GET_TLS_PROCTABLE()->SampleMaskSGIS) +#define glSamplePatternSGIS (_GET_TLS_PROCTABLE()->SamplePatternSGIS) +#define glArrayElementEXT (_GET_TLS_PROCTABLE()->ArrayElementEXT) +#define glColorPointerEXT (_GET_TLS_PROCTABLE()->ColorPointerEXT) +#define glDrawArraysEXT (_GET_TLS_PROCTABLE()->DrawArraysEXT) +#define glEdgeFlagPointerEXT (_GET_TLS_PROCTABLE()->EdgeFlagPointerEXT) +#define glGetPointervEXT (_GET_TLS_PROCTABLE()->GetPointervEXT) +#define glIndexPointerEXT (_GET_TLS_PROCTABLE()->IndexPointerEXT) +#define glNormalPointerEXT (_GET_TLS_PROCTABLE()->NormalPointerEXT) +#define glTexCoordPointerEXT (_GET_TLS_PROCTABLE()->TexCoordPointerEXT) +#define glVertexPointerEXT (_GET_TLS_PROCTABLE()->VertexPointerEXT) +#define glBlendEquationEXT (_GET_TLS_PROCTABLE()->BlendEquationEXT) +#define glSpriteParameterfSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfSGIX) +#define glSpriteParameterfvSGIX (_GET_TLS_PROCTABLE()->SpriteParameterfvSGIX) +#define glSpriteParameteriSGIX (_GET_TLS_PROCTABLE()->SpriteParameteriSGIX) +#define glSpriteParameterivSGIX (_GET_TLS_PROCTABLE()->SpriteParameterivSGIX) +#define glPointParameterfEXT (_GET_TLS_PROCTABLE()->PointParameterfEXT) +#define glPointParameterfvEXT (_GET_TLS_PROCTABLE()->PointParameterfvEXT) +#define glPointParameterfSGIS (_GET_TLS_PROCTABLE()->PointParameterfSGIS) +#define glPointParameterfvSGIS (_GET_TLS_PROCTABLE()->PointParameterfvSGIS) +#define glGetInstrumentsSGIX (_GET_TLS_PROCTABLE()->GetInstrumentsSGIX) +#define glInstrumentsBufferSGIX (_GET_TLS_PROCTABLE()->InstrumentsBufferSGIX) +#define glPollInstrumentsSGIX (_GET_TLS_PROCTABLE()->PollInstrumentsSGIX) +#define glReadInstrumentsSGIX (_GET_TLS_PROCTABLE()->ReadInstrumentsSGIX) +#define glStartInstrumentsSGIX (_GET_TLS_PROCTABLE()->StartInstrumentsSGIX) +#define glStopInstrumentsSGIX (_GET_TLS_PROCTABLE()->StopInstrumentsSGIX) +#define glFrameZoomSGIX (_GET_TLS_PROCTABLE()->FrameZoomSGIX) +#define glTagSampleBufferSGIX (_GET_TLS_PROCTABLE()->TagSampleBufferSGIX) +#define glDeformationMap3dSGIX (_GET_TLS_PROCTABLE()->DeformationMap3dSGIX) +#define glDeformationMap3fSGIX (_GET_TLS_PROCTABLE()->DeformationMap3fSGIX) +#define glDeformSGIX (_GET_TLS_PROCTABLE()->DeformSGIX) +#define glLoadIdentityDeformationMapSGIX (_GET_TLS_PROCTABLE()->LoadIdentityDeformationMapSGIX) +#define glReferencePlaneSGIX (_GET_TLS_PROCTABLE()->ReferencePlaneSGIX) +#define glFlushRasterSGIX (_GET_TLS_PROCTABLE()->FlushRasterSGIX) +#define glFogFuncSGIS (_GET_TLS_PROCTABLE()->FogFuncSGIS) +#define glGetFogFuncSGIS (_GET_TLS_PROCTABLE()->GetFogFuncSGIS) +#define glImageTransformParameteriHP (_GET_TLS_PROCTABLE()->ImageTransformParameteriHP) +#define glImageTransformParameterfHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfHP) +#define glImageTransformParameterivHP (_GET_TLS_PROCTABLE()->ImageTransformParameterivHP) +#define glImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->ImageTransformParameterfvHP) +#define glGetImageTransformParameterivHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterivHP) +#define glGetImageTransformParameterfvHP (_GET_TLS_PROCTABLE()->GetImageTransformParameterfvHP) +#define glColorSubTableEXT (_GET_TLS_PROCTABLE()->ColorSubTableEXT) +#define glCopyColorSubTableEXT (_GET_TLS_PROCTABLE()->CopyColorSubTableEXT) +#define glHintPGI (_GET_TLS_PROCTABLE()->HintPGI) +#define glColorTableEXT (_GET_TLS_PROCTABLE()->ColorTableEXT) +#define glGetColorTableEXT (_GET_TLS_PROCTABLE()->GetColorTableEXT) +#define glGetColorTableParameterivEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterivEXT) +#define glGetColorTableParameterfvEXT (_GET_TLS_PROCTABLE()->GetColorTableParameterfvEXT) +#define glGetListParameterfvSGIX (_GET_TLS_PROCTABLE()->GetListParameterfvSGIX) +#define glGetListParameterivSGIX (_GET_TLS_PROCTABLE()->GetListParameterivSGIX) +#define glListParameterfSGIX (_GET_TLS_PROCTABLE()->ListParameterfSGIX) +#define glListParameterfvSGIX (_GET_TLS_PROCTABLE()->ListParameterfvSGIX) +#define glListParameteriSGIX (_GET_TLS_PROCTABLE()->ListParameteriSGIX) +#define glListParameterivSGIX (_GET_TLS_PROCTABLE()->ListParameterivSGIX) +#define glIndexMaterialEXT (_GET_TLS_PROCTABLE()->IndexMaterialEXT) +#define glIndexFuncEXT (_GET_TLS_PROCTABLE()->IndexFuncEXT) +#define glLockArraysEXT (_GET_TLS_PROCTABLE()->LockArraysEXT) +#define glUnlockArraysEXT (_GET_TLS_PROCTABLE()->UnlockArraysEXT) +#define glCullParameterdvEXT (_GET_TLS_PROCTABLE()->CullParameterdvEXT) +#define glCullParameterfvEXT (_GET_TLS_PROCTABLE()->CullParameterfvEXT) +#define glFragmentColorMaterialSGIX (_GET_TLS_PROCTABLE()->FragmentColorMaterialSGIX) +#define glFragmentLightfSGIX (_GET_TLS_PROCTABLE()->FragmentLightfSGIX) +#define glFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightfvSGIX) +#define glFragmentLightiSGIX (_GET_TLS_PROCTABLE()->FragmentLightiSGIX) +#define glFragmentLightivSGIX (_GET_TLS_PROCTABLE()->FragmentLightivSGIX) +#define glFragmentLightModelfSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfSGIX) +#define glFragmentLightModelfvSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelfvSGIX) +#define glFragmentLightModeliSGIX (_GET_TLS_PROCTABLE()->FragmentLightModeliSGIX) +#define glFragmentLightModelivSGIX (_GET_TLS_PROCTABLE()->FragmentLightModelivSGIX) +#define glFragmentMaterialfSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfSGIX) +#define glFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialfvSGIX) +#define glFragmentMaterialiSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialiSGIX) +#define glFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->FragmentMaterialivSGIX) +#define glGetFragmentLightfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightfvSGIX) +#define glGetFragmentLightivSGIX (_GET_TLS_PROCTABLE()->GetFragmentLightivSGIX) +#define glGetFragmentMaterialfvSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialfvSGIX) +#define glGetFragmentMaterialivSGIX (_GET_TLS_PROCTABLE()->GetFragmentMaterialivSGIX) +#define glLightEnviSGIX (_GET_TLS_PROCTABLE()->LightEnviSGIX) +#define glDrawRangeElementsEXT (_GET_TLS_PROCTABLE()->DrawRangeElementsEXT) +#define glApplyTextureEXT (_GET_TLS_PROCTABLE()->ApplyTextureEXT) +#define glTextureLightEXT (_GET_TLS_PROCTABLE()->TextureLightEXT) +#define glTextureMaterialEXT (_GET_TLS_PROCTABLE()->TextureMaterialEXT) +#define glAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->AsyncMarkerSGIX) +#define glFinishAsyncSGIX (_GET_TLS_PROCTABLE()->FinishAsyncSGIX) +#define glPollAsyncSGIX (_GET_TLS_PROCTABLE()->PollAsyncSGIX) +#define glGenAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->GenAsyncMarkersSGIX) +#define glDeleteAsyncMarkersSGIX (_GET_TLS_PROCTABLE()->DeleteAsyncMarkersSGIX) +#define glIsAsyncMarkerSGIX (_GET_TLS_PROCTABLE()->IsAsyncMarkerSGIX) +#define glVertexPointervINTEL (_GET_TLS_PROCTABLE()->VertexPointervINTEL) +#define glNormalPointervINTEL (_GET_TLS_PROCTABLE()->NormalPointervINTEL) +#define glColorPointervINTEL (_GET_TLS_PROCTABLE()->ColorPointervINTEL) +#define glTexCoordPointervINTEL (_GET_TLS_PROCTABLE()->TexCoordPointervINTEL) +#define glPixelTransformParameteriEXT (_GET_TLS_PROCTABLE()->PixelTransformParameteriEXT) +#define glPixelTransformParameterfEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfEXT) +#define glPixelTransformParameterivEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterivEXT) +#define glPixelTransformParameterfvEXT (_GET_TLS_PROCTABLE()->PixelTransformParameterfvEXT) +#define glSecondaryColor3bEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bEXT) +#define glSecondaryColor3bvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3bvEXT) +#define glSecondaryColor3dEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dEXT) +#define glSecondaryColor3dvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3dvEXT) +#define glSecondaryColor3fEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fEXT) +#define glSecondaryColor3fvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3fvEXT) +#define glSecondaryColor3iEXT (_GET_TLS_PROCTABLE()->SecondaryColor3iEXT) +#define glSecondaryColor3ivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ivEXT) +#define glSecondaryColor3sEXT (_GET_TLS_PROCTABLE()->SecondaryColor3sEXT) +#define glSecondaryColor3svEXT (_GET_TLS_PROCTABLE()->SecondaryColor3svEXT) +#define glSecondaryColor3ubEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubEXT) +#define glSecondaryColor3ubvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3ubvEXT) +#define glSecondaryColor3uiEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uiEXT) +#define glSecondaryColor3uivEXT (_GET_TLS_PROCTABLE()->SecondaryColor3uivEXT) +#define glSecondaryColor3usEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usEXT) +#define glSecondaryColor3usvEXT (_GET_TLS_PROCTABLE()->SecondaryColor3usvEXT) +#define glSecondaryColorPointerEXT (_GET_TLS_PROCTABLE()->SecondaryColorPointerEXT) +#define glTextureNormalEXT (_GET_TLS_PROCTABLE()->TextureNormalEXT) +#define glMultiDrawArraysEXT (_GET_TLS_PROCTABLE()->MultiDrawArraysEXT) +#define glMultiDrawElementsEXT (_GET_TLS_PROCTABLE()->MultiDrawElementsEXT) +#define glFogCoordfEXT (_GET_TLS_PROCTABLE()->FogCoordfEXT) +#define glFogCoordfvEXT (_GET_TLS_PROCTABLE()->FogCoordfvEXT) +#define glFogCoorddEXT (_GET_TLS_PROCTABLE()->FogCoorddEXT) +#define glFogCoorddvEXT (_GET_TLS_PROCTABLE()->FogCoorddvEXT) +#define glFogCoordPointerEXT (_GET_TLS_PROCTABLE()->FogCoordPointerEXT) +#define glTangent3bEXT (_GET_TLS_PROCTABLE()->Tangent3bEXT) +#define glTangent3bvEXT (_GET_TLS_PROCTABLE()->Tangent3bvEXT) +#define glTangent3dEXT (_GET_TLS_PROCTABLE()->Tangent3dEXT) +#define glTangent3dvEXT (_GET_TLS_PROCTABLE()->Tangent3dvEXT) +#define glTangent3fEXT (_GET_TLS_PROCTABLE()->Tangent3fEXT) +#define glTangent3fvEXT (_GET_TLS_PROCTABLE()->Tangent3fvEXT) +#define glTangent3iEXT (_GET_TLS_PROCTABLE()->Tangent3iEXT) +#define glTangent3ivEXT (_GET_TLS_PROCTABLE()->Tangent3ivEXT) +#define glTangent3sEXT (_GET_TLS_PROCTABLE()->Tangent3sEXT) +#define glTangent3svEXT (_GET_TLS_PROCTABLE()->Tangent3svEXT) +#define glBinormal3bEXT (_GET_TLS_PROCTABLE()->Binormal3bEXT) +#define glBinormal3bvEXT (_GET_TLS_PROCTABLE()->Binormal3bvEXT) +#define glBinormal3dEXT (_GET_TLS_PROCTABLE()->Binormal3dEXT) +#define glBinormal3dvEXT (_GET_TLS_PROCTABLE()->Binormal3dvEXT) +#define glBinormal3fEXT (_GET_TLS_PROCTABLE()->Binormal3fEXT) +#define glBinormal3fvEXT (_GET_TLS_PROCTABLE()->Binormal3fvEXT) +#define glBinormal3iEXT (_GET_TLS_PROCTABLE()->Binormal3iEXT) +#define glBinormal3ivEXT (_GET_TLS_PROCTABLE()->Binormal3ivEXT) +#define glBinormal3sEXT (_GET_TLS_PROCTABLE()->Binormal3sEXT) +#define glBinormal3svEXT (_GET_TLS_PROCTABLE()->Binormal3svEXT) +#define glTangentPointerEXT (_GET_TLS_PROCTABLE()->TangentPointerEXT) +#define glBinormalPointerEXT (_GET_TLS_PROCTABLE()->BinormalPointerEXT) +#define glFinishTextureSUNX (_GET_TLS_PROCTABLE()->FinishTextureSUNX) +#define glGlobalAlphaFactorbSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorbSUN) +#define glGlobalAlphaFactorsSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorsSUN) +#define glGlobalAlphaFactoriSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoriSUN) +#define glGlobalAlphaFactorfSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorfSUN) +#define glGlobalAlphaFactordSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactordSUN) +#define glGlobalAlphaFactorubSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorubSUN) +#define glGlobalAlphaFactorusSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactorusSUN) +#define glGlobalAlphaFactoruiSUN (_GET_TLS_PROCTABLE()->GlobalAlphaFactoruiSUN) +#define glReplacementCodeuiSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiSUN) +#define glReplacementCodeusSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusSUN) +#define glReplacementCodeubSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubSUN) +#define glReplacementCodeuivSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuivSUN) +#define glReplacementCodeusvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeusvSUN) +#define glReplacementCodeubvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeubvSUN) +#define glReplacementCodePointerSUN (_GET_TLS_PROCTABLE()->ReplacementCodePointerSUN) +#define glColor4ubVertex2fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fSUN) +#define glColor4ubVertex2fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex2fvSUN) +#define glColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fSUN) +#define glColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4ubVertex3fvSUN) +#define glColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fSUN) +#define glColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color3fVertex3fvSUN) +#define glNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fSUN) +#define glNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Normal3fVertex3fvSUN) +#define glColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fSUN) +#define glColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->Color4fNormal3fVertex3fvSUN) +#define glTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fSUN) +#define glTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fVertex3fvSUN) +#define glTexCoord4fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fSUN) +#define glTexCoord4fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fVertex4fvSUN) +#define glTexCoord2fColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fSUN) +#define glTexCoord2fColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4ubVertex3fvSUN) +#define glTexCoord2fColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fSUN) +#define glTexCoord2fColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor3fVertex3fvSUN) +#define glTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fSUN) +#define glTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fNormal3fVertex3fvSUN) +#define glTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fSUN) +#define glTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->TexCoord2fColor4fNormal3fVertex3fvSUN) +#define glTexCoord4fColor4fNormal3fVertex4fSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fSUN) +#define glTexCoord4fColor4fNormal3fVertex4fvSUN (_GET_TLS_PROCTABLE()->TexCoord4fColor4fNormal3fVertex4fvSUN) +#define glReplacementCodeuiVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fSUN) +#define glReplacementCodeuiVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiVertex3fvSUN) +#define glReplacementCodeuiColor4ubVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fSUN) +#define glReplacementCodeuiColor4ubVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4ubVertex3fvSUN) +#define glReplacementCodeuiColor3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fSUN) +#define glReplacementCodeuiColor3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor3fVertex3fvSUN) +#define glReplacementCodeuiNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fSUN) +#define glReplacementCodeuiNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiNormal3fVertex3fvSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiColor4fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) +#define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (_GET_TLS_PROCTABLE()->ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) +#define glBlendFuncSeparateEXT (_GET_TLS_PROCTABLE()->BlendFuncSeparateEXT) +#define glBlendFuncSeparateINGR (_GET_TLS_PROCTABLE()->BlendFuncSeparateINGR) +#define glVertexWeightfEXT (_GET_TLS_PROCTABLE()->VertexWeightfEXT) +#define glVertexWeightfvEXT (_GET_TLS_PROCTABLE()->VertexWeightfvEXT) +#define glVertexWeightPointerEXT (_GET_TLS_PROCTABLE()->VertexWeightPointerEXT) +#define glFlushVertexArrayRangeNV (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeNV) +#define glVertexArrayRangeNV (_GET_TLS_PROCTABLE()->VertexArrayRangeNV) +#define glCombinerParameterfvNV (_GET_TLS_PROCTABLE()->CombinerParameterfvNV) +#define glCombinerParameterfNV (_GET_TLS_PROCTABLE()->CombinerParameterfNV) +#define glCombinerParameterivNV (_GET_TLS_PROCTABLE()->CombinerParameterivNV) +#define glCombinerParameteriNV (_GET_TLS_PROCTABLE()->CombinerParameteriNV) +#define glCombinerInputNV (_GET_TLS_PROCTABLE()->CombinerInputNV) +#define glCombinerOutputNV (_GET_TLS_PROCTABLE()->CombinerOutputNV) +#define glFinalCombinerInputNV (_GET_TLS_PROCTABLE()->FinalCombinerInputNV) +#define glGetCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterfvNV) +#define glGetCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerInputParameterivNV) +#define glGetCombinerOutputParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterfvNV) +#define glGetCombinerOutputParameterivNV (_GET_TLS_PROCTABLE()->GetCombinerOutputParameterivNV) +#define glGetFinalCombinerInputParameterfvNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterfvNV) +#define glGetFinalCombinerInputParameterivNV (_GET_TLS_PROCTABLE()->GetFinalCombinerInputParameterivNV) +#define glResizeBuffersMESA (_GET_TLS_PROCTABLE()->ResizeBuffersMESA) +#define glWindowPos2dMESA (_GET_TLS_PROCTABLE()->WindowPos2dMESA) +#define glWindowPos2dvMESA (_GET_TLS_PROCTABLE()->WindowPos2dvMESA) +#define glWindowPos2fMESA (_GET_TLS_PROCTABLE()->WindowPos2fMESA) +#define glWindowPos2fvMESA (_GET_TLS_PROCTABLE()->WindowPos2fvMESA) +#define glWindowPos2iMESA (_GET_TLS_PROCTABLE()->WindowPos2iMESA) +#define glWindowPos2ivMESA (_GET_TLS_PROCTABLE()->WindowPos2ivMESA) +#define glWindowPos2sMESA (_GET_TLS_PROCTABLE()->WindowPos2sMESA) +#define glWindowPos2svMESA (_GET_TLS_PROCTABLE()->WindowPos2svMESA) +#define glWindowPos3dMESA (_GET_TLS_PROCTABLE()->WindowPos3dMESA) +#define glWindowPos3dvMESA (_GET_TLS_PROCTABLE()->WindowPos3dvMESA) +#define glWindowPos3fMESA (_GET_TLS_PROCTABLE()->WindowPos3fMESA) +#define glWindowPos3fvMESA (_GET_TLS_PROCTABLE()->WindowPos3fvMESA) +#define glWindowPos3iMESA (_GET_TLS_PROCTABLE()->WindowPos3iMESA) +#define glWindowPos3ivMESA (_GET_TLS_PROCTABLE()->WindowPos3ivMESA) +#define glWindowPos3sMESA (_GET_TLS_PROCTABLE()->WindowPos3sMESA) +#define glWindowPos3svMESA (_GET_TLS_PROCTABLE()->WindowPos3svMESA) +#define glWindowPos4dMESA (_GET_TLS_PROCTABLE()->WindowPos4dMESA) +#define glWindowPos4dvMESA (_GET_TLS_PROCTABLE()->WindowPos4dvMESA) +#define glWindowPos4fMESA (_GET_TLS_PROCTABLE()->WindowPos4fMESA) +#define glWindowPos4fvMESA (_GET_TLS_PROCTABLE()->WindowPos4fvMESA) +#define glWindowPos4iMESA (_GET_TLS_PROCTABLE()->WindowPos4iMESA) +#define glWindowPos4ivMESA (_GET_TLS_PROCTABLE()->WindowPos4ivMESA) +#define glWindowPos4sMESA (_GET_TLS_PROCTABLE()->WindowPos4sMESA) +#define glWindowPos4svMESA (_GET_TLS_PROCTABLE()->WindowPos4svMESA) +#define glMultiModeDrawArraysIBM (_GET_TLS_PROCTABLE()->MultiModeDrawArraysIBM) +#define glMultiModeDrawElementsIBM (_GET_TLS_PROCTABLE()->MultiModeDrawElementsIBM) +#define glColorPointerListIBM (_GET_TLS_PROCTABLE()->ColorPointerListIBM) +#define glSecondaryColorPointerListIBM (_GET_TLS_PROCTABLE()->SecondaryColorPointerListIBM) +#define glEdgeFlagPointerListIBM (_GET_TLS_PROCTABLE()->EdgeFlagPointerListIBM) +#define glFogCoordPointerListIBM (_GET_TLS_PROCTABLE()->FogCoordPointerListIBM) +#define glIndexPointerListIBM (_GET_TLS_PROCTABLE()->IndexPointerListIBM) +#define glNormalPointerListIBM (_GET_TLS_PROCTABLE()->NormalPointerListIBM) +#define glTexCoordPointerListIBM (_GET_TLS_PROCTABLE()->TexCoordPointerListIBM) +#define glVertexPointerListIBM (_GET_TLS_PROCTABLE()->VertexPointerListIBM) +#define glTbufferMask3DFX (_GET_TLS_PROCTABLE()->TbufferMask3DFX) +#define glSampleMaskEXT (_GET_TLS_PROCTABLE()->SampleMaskEXT) +#define glSamplePatternEXT (_GET_TLS_PROCTABLE()->SamplePatternEXT) +#define glTextureColorMaskSGIS (_GET_TLS_PROCTABLE()->TextureColorMaskSGIS) +#define glIglooInterfaceSGIX (_GET_TLS_PROCTABLE()->IglooInterfaceSGIX) +#define glDeleteFencesNV (_GET_TLS_PROCTABLE()->DeleteFencesNV) +#define glGenFencesNV (_GET_TLS_PROCTABLE()->GenFencesNV) +#define glIsFenceNV (_GET_TLS_PROCTABLE()->IsFenceNV) +#define glTestFenceNV (_GET_TLS_PROCTABLE()->TestFenceNV) +#define glGetFenceivNV (_GET_TLS_PROCTABLE()->GetFenceivNV) +#define glFinishFenceNV (_GET_TLS_PROCTABLE()->FinishFenceNV) +#define glSetFenceNV (_GET_TLS_PROCTABLE()->SetFenceNV) +#define glMapControlPointsNV (_GET_TLS_PROCTABLE()->MapControlPointsNV) +#define glMapParameterivNV (_GET_TLS_PROCTABLE()->MapParameterivNV) +#define glMapParameterfvNV (_GET_TLS_PROCTABLE()->MapParameterfvNV) +#define glGetMapControlPointsNV (_GET_TLS_PROCTABLE()->GetMapControlPointsNV) +#define glGetMapParameterivNV (_GET_TLS_PROCTABLE()->GetMapParameterivNV) +#define glGetMapParameterfvNV (_GET_TLS_PROCTABLE()->GetMapParameterfvNV) +#define glGetMapAttribParameterivNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterivNV) +#define glGetMapAttribParameterfvNV (_GET_TLS_PROCTABLE()->GetMapAttribParameterfvNV) +#define glEvalMapsNV (_GET_TLS_PROCTABLE()->EvalMapsNV) +#define glCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->CombinerStageParameterfvNV) +#define glGetCombinerStageParameterfvNV (_GET_TLS_PROCTABLE()->GetCombinerStageParameterfvNV) +#define glAreProgramsResidentNV (_GET_TLS_PROCTABLE()->AreProgramsResidentNV) +#define glBindProgramNV (_GET_TLS_PROCTABLE()->BindProgramNV) +#define glDeleteProgramsNV (_GET_TLS_PROCTABLE()->DeleteProgramsNV) +#define glExecuteProgramNV (_GET_TLS_PROCTABLE()->ExecuteProgramNV) +#define glGenProgramsNV (_GET_TLS_PROCTABLE()->GenProgramsNV) +#define glGetProgramParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramParameterdvNV) +#define glGetProgramParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramParameterfvNV) +#define glGetProgramivNV (_GET_TLS_PROCTABLE()->GetProgramivNV) +#define glGetProgramStringNV (_GET_TLS_PROCTABLE()->GetProgramStringNV) +#define glGetTrackMatrixivNV (_GET_TLS_PROCTABLE()->GetTrackMatrixivNV) +#define glGetVertexAttribdvNV (_GET_TLS_PROCTABLE()->GetVertexAttribdvNV) +#define glGetVertexAttribfvNV (_GET_TLS_PROCTABLE()->GetVertexAttribfvNV) +#define glGetVertexAttribivNV (_GET_TLS_PROCTABLE()->GetVertexAttribivNV) +#define glGetVertexAttribPointervNV (_GET_TLS_PROCTABLE()->GetVertexAttribPointervNV) +#define glIsProgramNV (_GET_TLS_PROCTABLE()->IsProgramNV) +#define glLoadProgramNV (_GET_TLS_PROCTABLE()->LoadProgramNV) +#define glProgramParameter4dNV (_GET_TLS_PROCTABLE()->ProgramParameter4dNV) +#define glProgramParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramParameter4dvNV) +#define glProgramParameter4fNV (_GET_TLS_PROCTABLE()->ProgramParameter4fNV) +#define glProgramParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramParameter4fvNV) +#define glProgramParameters4dvNV (_GET_TLS_PROCTABLE()->ProgramParameters4dvNV) +#define glProgramParameters4fvNV (_GET_TLS_PROCTABLE()->ProgramParameters4fvNV) +#define glRequestResidentProgramsNV (_GET_TLS_PROCTABLE()->RequestResidentProgramsNV) +#define glTrackMatrixNV (_GET_TLS_PROCTABLE()->TrackMatrixNV) +#define glVertexAttribPointerNV (_GET_TLS_PROCTABLE()->VertexAttribPointerNV) +#define glVertexAttrib1dNV (_GET_TLS_PROCTABLE()->VertexAttrib1dNV) +#define glVertexAttrib1dvNV (_GET_TLS_PROCTABLE()->VertexAttrib1dvNV) +#define glVertexAttrib1fNV (_GET_TLS_PROCTABLE()->VertexAttrib1fNV) +#define glVertexAttrib1fvNV (_GET_TLS_PROCTABLE()->VertexAttrib1fvNV) +#define glVertexAttrib1sNV (_GET_TLS_PROCTABLE()->VertexAttrib1sNV) +#define glVertexAttrib1svNV (_GET_TLS_PROCTABLE()->VertexAttrib1svNV) +#define glVertexAttrib2dNV (_GET_TLS_PROCTABLE()->VertexAttrib2dNV) +#define glVertexAttrib2dvNV (_GET_TLS_PROCTABLE()->VertexAttrib2dvNV) +#define glVertexAttrib2fNV (_GET_TLS_PROCTABLE()->VertexAttrib2fNV) +#define glVertexAttrib2fvNV (_GET_TLS_PROCTABLE()->VertexAttrib2fvNV) +#define glVertexAttrib2sNV (_GET_TLS_PROCTABLE()->VertexAttrib2sNV) +#define glVertexAttrib2svNV (_GET_TLS_PROCTABLE()->VertexAttrib2svNV) +#define glVertexAttrib3dNV (_GET_TLS_PROCTABLE()->VertexAttrib3dNV) +#define glVertexAttrib3dvNV (_GET_TLS_PROCTABLE()->VertexAttrib3dvNV) +#define glVertexAttrib3fNV (_GET_TLS_PROCTABLE()->VertexAttrib3fNV) +#define glVertexAttrib3fvNV (_GET_TLS_PROCTABLE()->VertexAttrib3fvNV) +#define glVertexAttrib3sNV (_GET_TLS_PROCTABLE()->VertexAttrib3sNV) +#define glVertexAttrib3svNV (_GET_TLS_PROCTABLE()->VertexAttrib3svNV) +#define glVertexAttrib4dNV (_GET_TLS_PROCTABLE()->VertexAttrib4dNV) +#define glVertexAttrib4dvNV (_GET_TLS_PROCTABLE()->VertexAttrib4dvNV) +#define glVertexAttrib4fNV (_GET_TLS_PROCTABLE()->VertexAttrib4fNV) +#define glVertexAttrib4fvNV (_GET_TLS_PROCTABLE()->VertexAttrib4fvNV) +#define glVertexAttrib4sNV (_GET_TLS_PROCTABLE()->VertexAttrib4sNV) +#define glVertexAttrib4svNV (_GET_TLS_PROCTABLE()->VertexAttrib4svNV) +#define glVertexAttrib4ubNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubNV) +#define glVertexAttrib4ubvNV (_GET_TLS_PROCTABLE()->VertexAttrib4ubvNV) +#define glVertexAttribs1dvNV (_GET_TLS_PROCTABLE()->VertexAttribs1dvNV) +#define glVertexAttribs1fvNV (_GET_TLS_PROCTABLE()->VertexAttribs1fvNV) +#define glVertexAttribs1svNV (_GET_TLS_PROCTABLE()->VertexAttribs1svNV) +#define glVertexAttribs2dvNV (_GET_TLS_PROCTABLE()->VertexAttribs2dvNV) +#define glVertexAttribs2fvNV (_GET_TLS_PROCTABLE()->VertexAttribs2fvNV) +#define glVertexAttribs2svNV (_GET_TLS_PROCTABLE()->VertexAttribs2svNV) +#define glVertexAttribs3dvNV (_GET_TLS_PROCTABLE()->VertexAttribs3dvNV) +#define glVertexAttribs3fvNV (_GET_TLS_PROCTABLE()->VertexAttribs3fvNV) +#define glVertexAttribs3svNV (_GET_TLS_PROCTABLE()->VertexAttribs3svNV) +#define glVertexAttribs4dvNV (_GET_TLS_PROCTABLE()->VertexAttribs4dvNV) +#define glVertexAttribs4fvNV (_GET_TLS_PROCTABLE()->VertexAttribs4fvNV) +#define glVertexAttribs4svNV (_GET_TLS_PROCTABLE()->VertexAttribs4svNV) +#define glVertexAttribs4ubvNV (_GET_TLS_PROCTABLE()->VertexAttribs4ubvNV) +#define glTexBumpParameterivATI (_GET_TLS_PROCTABLE()->TexBumpParameterivATI) +#define glTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->TexBumpParameterfvATI) +#define glGetTexBumpParameterivATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterivATI) +#define glGetTexBumpParameterfvATI (_GET_TLS_PROCTABLE()->GetTexBumpParameterfvATI) +#define glGenFragmentShadersATI (_GET_TLS_PROCTABLE()->GenFragmentShadersATI) +#define glBindFragmentShaderATI (_GET_TLS_PROCTABLE()->BindFragmentShaderATI) +#define glDeleteFragmentShaderATI (_GET_TLS_PROCTABLE()->DeleteFragmentShaderATI) +#define glBeginFragmentShaderATI (_GET_TLS_PROCTABLE()->BeginFragmentShaderATI) +#define glEndFragmentShaderATI (_GET_TLS_PROCTABLE()->EndFragmentShaderATI) +#define glPassTexCoordATI (_GET_TLS_PROCTABLE()->PassTexCoordATI) +#define glSampleMapATI (_GET_TLS_PROCTABLE()->SampleMapATI) +#define glColorFragmentOp1ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp1ATI) +#define glColorFragmentOp2ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp2ATI) +#define glColorFragmentOp3ATI (_GET_TLS_PROCTABLE()->ColorFragmentOp3ATI) +#define glAlphaFragmentOp1ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp1ATI) +#define glAlphaFragmentOp2ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp2ATI) +#define glAlphaFragmentOp3ATI (_GET_TLS_PROCTABLE()->AlphaFragmentOp3ATI) +#define glSetFragmentShaderConstantATI (_GET_TLS_PROCTABLE()->SetFragmentShaderConstantATI) +#define glPNTrianglesiATI (_GET_TLS_PROCTABLE()->PNTrianglesiATI) +#define glPNTrianglesfATI (_GET_TLS_PROCTABLE()->PNTrianglesfATI) +#define glNewObjectBufferATI (_GET_TLS_PROCTABLE()->NewObjectBufferATI) +#define glIsObjectBufferATI (_GET_TLS_PROCTABLE()->IsObjectBufferATI) +#define glUpdateObjectBufferATI (_GET_TLS_PROCTABLE()->UpdateObjectBufferATI) +#define glGetObjectBufferfvATI (_GET_TLS_PROCTABLE()->GetObjectBufferfvATI) +#define glGetObjectBufferivATI (_GET_TLS_PROCTABLE()->GetObjectBufferivATI) +#define glFreeObjectBufferATI (_GET_TLS_PROCTABLE()->FreeObjectBufferATI) +#define glArrayObjectATI (_GET_TLS_PROCTABLE()->ArrayObjectATI) +#define glGetArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetArrayObjectfvATI) +#define glGetArrayObjectivATI (_GET_TLS_PROCTABLE()->GetArrayObjectivATI) +#define glVariantArrayObjectATI (_GET_TLS_PROCTABLE()->VariantArrayObjectATI) +#define glGetVariantArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectfvATI) +#define glGetVariantArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVariantArrayObjectivATI) +#define glBeginVertexShaderEXT (_GET_TLS_PROCTABLE()->BeginVertexShaderEXT) +#define glEndVertexShaderEXT (_GET_TLS_PROCTABLE()->EndVertexShaderEXT) +#define glBindVertexShaderEXT (_GET_TLS_PROCTABLE()->BindVertexShaderEXT) +#define glGenVertexShadersEXT (_GET_TLS_PROCTABLE()->GenVertexShadersEXT) +#define glDeleteVertexShaderEXT (_GET_TLS_PROCTABLE()->DeleteVertexShaderEXT) +#define glShaderOp1EXT (_GET_TLS_PROCTABLE()->ShaderOp1EXT) +#define glShaderOp2EXT (_GET_TLS_PROCTABLE()->ShaderOp2EXT) +#define glShaderOp3EXT (_GET_TLS_PROCTABLE()->ShaderOp3EXT) +#define glSwizzleEXT (_GET_TLS_PROCTABLE()->SwizzleEXT) +#define glWriteMaskEXT (_GET_TLS_PROCTABLE()->WriteMaskEXT) +#define glInsertComponentEXT (_GET_TLS_PROCTABLE()->InsertComponentEXT) +#define glExtractComponentEXT (_GET_TLS_PROCTABLE()->ExtractComponentEXT) +#define glGenSymbolsEXT (_GET_TLS_PROCTABLE()->GenSymbolsEXT) +#define glSetInvariantEXT (_GET_TLS_PROCTABLE()->SetInvariantEXT) +#define glSetLocalConstantEXT (_GET_TLS_PROCTABLE()->SetLocalConstantEXT) +#define glVariantbvEXT (_GET_TLS_PROCTABLE()->VariantbvEXT) +#define glVariantsvEXT (_GET_TLS_PROCTABLE()->VariantsvEXT) +#define glVariantivEXT (_GET_TLS_PROCTABLE()->VariantivEXT) +#define glVariantfvEXT (_GET_TLS_PROCTABLE()->VariantfvEXT) +#define glVariantdvEXT (_GET_TLS_PROCTABLE()->VariantdvEXT) +#define glVariantubvEXT (_GET_TLS_PROCTABLE()->VariantubvEXT) +#define glVariantusvEXT (_GET_TLS_PROCTABLE()->VariantusvEXT) +#define glVariantuivEXT (_GET_TLS_PROCTABLE()->VariantuivEXT) +#define glVariantPointerEXT (_GET_TLS_PROCTABLE()->VariantPointerEXT) +#define glEnableVariantClientStateEXT (_GET_TLS_PROCTABLE()->EnableVariantClientStateEXT) +#define glDisableVariantClientStateEXT (_GET_TLS_PROCTABLE()->DisableVariantClientStateEXT) +#define glBindLightParameterEXT (_GET_TLS_PROCTABLE()->BindLightParameterEXT) +#define glBindMaterialParameterEXT (_GET_TLS_PROCTABLE()->BindMaterialParameterEXT) +#define glBindTexGenParameterEXT (_GET_TLS_PROCTABLE()->BindTexGenParameterEXT) +#define glBindTextureUnitParameterEXT (_GET_TLS_PROCTABLE()->BindTextureUnitParameterEXT) +#define glBindParameterEXT (_GET_TLS_PROCTABLE()->BindParameterEXT) +#define glIsVariantEnabledEXT (_GET_TLS_PROCTABLE()->IsVariantEnabledEXT) +#define glGetVariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetVariantBooleanvEXT) +#define glGetVariantIntegervEXT (_GET_TLS_PROCTABLE()->GetVariantIntegervEXT) +#define glGetVariantFloatvEXT (_GET_TLS_PROCTABLE()->GetVariantFloatvEXT) +#define glGetVariantPointervEXT (_GET_TLS_PROCTABLE()->GetVariantPointervEXT) +#define glGetInvariantBooleanvEXT (_GET_TLS_PROCTABLE()->GetInvariantBooleanvEXT) +#define glGetInvariantIntegervEXT (_GET_TLS_PROCTABLE()->GetInvariantIntegervEXT) +#define glGetInvariantFloatvEXT (_GET_TLS_PROCTABLE()->GetInvariantFloatvEXT) +#define glGetLocalConstantBooleanvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantBooleanvEXT) +#define glGetLocalConstantIntegervEXT (_GET_TLS_PROCTABLE()->GetLocalConstantIntegervEXT) +#define glGetLocalConstantFloatvEXT (_GET_TLS_PROCTABLE()->GetLocalConstantFloatvEXT) +#define glVertexStream1sATI (_GET_TLS_PROCTABLE()->VertexStream1sATI) +#define glVertexStream1svATI (_GET_TLS_PROCTABLE()->VertexStream1svATI) +#define glVertexStream1iATI (_GET_TLS_PROCTABLE()->VertexStream1iATI) +#define glVertexStream1ivATI (_GET_TLS_PROCTABLE()->VertexStream1ivATI) +#define glVertexStream1fATI (_GET_TLS_PROCTABLE()->VertexStream1fATI) +#define glVertexStream1fvATI (_GET_TLS_PROCTABLE()->VertexStream1fvATI) +#define glVertexStream1dATI (_GET_TLS_PROCTABLE()->VertexStream1dATI) +#define glVertexStream1dvATI (_GET_TLS_PROCTABLE()->VertexStream1dvATI) +#define glVertexStream2sATI (_GET_TLS_PROCTABLE()->VertexStream2sATI) +#define glVertexStream2svATI (_GET_TLS_PROCTABLE()->VertexStream2svATI) +#define glVertexStream2iATI (_GET_TLS_PROCTABLE()->VertexStream2iATI) +#define glVertexStream2ivATI (_GET_TLS_PROCTABLE()->VertexStream2ivATI) +#define glVertexStream2fATI (_GET_TLS_PROCTABLE()->VertexStream2fATI) +#define glVertexStream2fvATI (_GET_TLS_PROCTABLE()->VertexStream2fvATI) +#define glVertexStream2dATI (_GET_TLS_PROCTABLE()->VertexStream2dATI) +#define glVertexStream2dvATI (_GET_TLS_PROCTABLE()->VertexStream2dvATI) +#define glVertexStream3sATI (_GET_TLS_PROCTABLE()->VertexStream3sATI) +#define glVertexStream3svATI (_GET_TLS_PROCTABLE()->VertexStream3svATI) +#define glVertexStream3iATI (_GET_TLS_PROCTABLE()->VertexStream3iATI) +#define glVertexStream3ivATI (_GET_TLS_PROCTABLE()->VertexStream3ivATI) +#define glVertexStream3fATI (_GET_TLS_PROCTABLE()->VertexStream3fATI) +#define glVertexStream3fvATI (_GET_TLS_PROCTABLE()->VertexStream3fvATI) +#define glVertexStream3dATI (_GET_TLS_PROCTABLE()->VertexStream3dATI) +#define glVertexStream3dvATI (_GET_TLS_PROCTABLE()->VertexStream3dvATI) +#define glVertexStream4sATI (_GET_TLS_PROCTABLE()->VertexStream4sATI) +#define glVertexStream4svATI (_GET_TLS_PROCTABLE()->VertexStream4svATI) +#define glVertexStream4iATI (_GET_TLS_PROCTABLE()->VertexStream4iATI) +#define glVertexStream4ivATI (_GET_TLS_PROCTABLE()->VertexStream4ivATI) +#define glVertexStream4fATI (_GET_TLS_PROCTABLE()->VertexStream4fATI) +#define glVertexStream4fvATI (_GET_TLS_PROCTABLE()->VertexStream4fvATI) +#define glVertexStream4dATI (_GET_TLS_PROCTABLE()->VertexStream4dATI) +#define glVertexStream4dvATI (_GET_TLS_PROCTABLE()->VertexStream4dvATI) +#define glNormalStream3bATI (_GET_TLS_PROCTABLE()->NormalStream3bATI) +#define glNormalStream3bvATI (_GET_TLS_PROCTABLE()->NormalStream3bvATI) +#define glNormalStream3sATI (_GET_TLS_PROCTABLE()->NormalStream3sATI) +#define glNormalStream3svATI (_GET_TLS_PROCTABLE()->NormalStream3svATI) +#define glNormalStream3iATI (_GET_TLS_PROCTABLE()->NormalStream3iATI) +#define glNormalStream3ivATI (_GET_TLS_PROCTABLE()->NormalStream3ivATI) +#define glNormalStream3fATI (_GET_TLS_PROCTABLE()->NormalStream3fATI) +#define glNormalStream3fvATI (_GET_TLS_PROCTABLE()->NormalStream3fvATI) +#define glNormalStream3dATI (_GET_TLS_PROCTABLE()->NormalStream3dATI) +#define glNormalStream3dvATI (_GET_TLS_PROCTABLE()->NormalStream3dvATI) +#define glClientActiveVertexStreamATI (_GET_TLS_PROCTABLE()->ClientActiveVertexStreamATI) +#define glVertexBlendEnviATI (_GET_TLS_PROCTABLE()->VertexBlendEnviATI) +#define glVertexBlendEnvfATI (_GET_TLS_PROCTABLE()->VertexBlendEnvfATI) +#define glElementPointerATI (_GET_TLS_PROCTABLE()->ElementPointerATI) +#define glDrawElementArrayATI (_GET_TLS_PROCTABLE()->DrawElementArrayATI) +#define glDrawRangeElementArrayATI (_GET_TLS_PROCTABLE()->DrawRangeElementArrayATI) +#define glDrawMeshArraysSUN (_GET_TLS_PROCTABLE()->DrawMeshArraysSUN) +#define glGenOcclusionQueriesNV (_GET_TLS_PROCTABLE()->GenOcclusionQueriesNV) +#define glDeleteOcclusionQueriesNV (_GET_TLS_PROCTABLE()->DeleteOcclusionQueriesNV) +#define glIsOcclusionQueryNV (_GET_TLS_PROCTABLE()->IsOcclusionQueryNV) +#define glBeginOcclusionQueryNV (_GET_TLS_PROCTABLE()->BeginOcclusionQueryNV) +#define glEndOcclusionQueryNV (_GET_TLS_PROCTABLE()->EndOcclusionQueryNV) +#define glGetOcclusionQueryivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryivNV) +#define glGetOcclusionQueryuivNV (_GET_TLS_PROCTABLE()->GetOcclusionQueryuivNV) +#define glPointParameteriNV (_GET_TLS_PROCTABLE()->PointParameteriNV) +#define glPointParameterivNV (_GET_TLS_PROCTABLE()->PointParameterivNV) +#define glActiveStencilFaceEXT (_GET_TLS_PROCTABLE()->ActiveStencilFaceEXT) +#define glElementPointerAPPLE (_GET_TLS_PROCTABLE()->ElementPointerAPPLE) +#define glDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawElementArrayAPPLE) +#define glDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->DrawRangeElementArrayAPPLE) +#define glMultiDrawElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawElementArrayAPPLE) +#define glMultiDrawRangeElementArrayAPPLE (_GET_TLS_PROCTABLE()->MultiDrawRangeElementArrayAPPLE) +#define glGenFencesAPPLE (_GET_TLS_PROCTABLE()->GenFencesAPPLE) +#define glDeleteFencesAPPLE (_GET_TLS_PROCTABLE()->DeleteFencesAPPLE) +#define glSetFenceAPPLE (_GET_TLS_PROCTABLE()->SetFenceAPPLE) +#define glIsFenceAPPLE (_GET_TLS_PROCTABLE()->IsFenceAPPLE) +#define glTestFenceAPPLE (_GET_TLS_PROCTABLE()->TestFenceAPPLE) +#define glFinishFenceAPPLE (_GET_TLS_PROCTABLE()->FinishFenceAPPLE) +#define glTestObjectAPPLE (_GET_TLS_PROCTABLE()->TestObjectAPPLE) +#define glFinishObjectAPPLE (_GET_TLS_PROCTABLE()->FinishObjectAPPLE) +#define glBindVertexArrayAPPLE (_GET_TLS_PROCTABLE()->BindVertexArrayAPPLE) +#define glDeleteVertexArraysAPPLE (_GET_TLS_PROCTABLE()->DeleteVertexArraysAPPLE) +#define glGenVertexArraysAPPLE (_GET_TLS_PROCTABLE()->GenVertexArraysAPPLE) +#define glIsVertexArrayAPPLE (_GET_TLS_PROCTABLE()->IsVertexArrayAPPLE) +#define glVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->VertexArrayRangeAPPLE) +#define glFlushVertexArrayRangeAPPLE (_GET_TLS_PROCTABLE()->FlushVertexArrayRangeAPPLE) +#define glVertexArrayParameteriAPPLE (_GET_TLS_PROCTABLE()->VertexArrayParameteriAPPLE) +#define glDrawBuffersATI (_GET_TLS_PROCTABLE()->DrawBuffersATI) +#define glProgramNamedParameter4fNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fNV) +#define glProgramNamedParameter4dNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dNV) +#define glProgramNamedParameter4fvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4fvNV) +#define glProgramNamedParameter4dvNV (_GET_TLS_PROCTABLE()->ProgramNamedParameter4dvNV) +#define glGetProgramNamedParameterfvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterfvNV) +#define glGetProgramNamedParameterdvNV (_GET_TLS_PROCTABLE()->GetProgramNamedParameterdvNV) +#define glVertex2hNV (_GET_TLS_PROCTABLE()->Vertex2hNV) +#define glVertex2hvNV (_GET_TLS_PROCTABLE()->Vertex2hvNV) +#define glVertex3hNV (_GET_TLS_PROCTABLE()->Vertex3hNV) +#define glVertex3hvNV (_GET_TLS_PROCTABLE()->Vertex3hvNV) +#define glVertex4hNV (_GET_TLS_PROCTABLE()->Vertex4hNV) +#define glVertex4hvNV (_GET_TLS_PROCTABLE()->Vertex4hvNV) +#define glNormal3hNV (_GET_TLS_PROCTABLE()->Normal3hNV) +#define glNormal3hvNV (_GET_TLS_PROCTABLE()->Normal3hvNV) +#define glColor3hNV (_GET_TLS_PROCTABLE()->Color3hNV) +#define glColor3hvNV (_GET_TLS_PROCTABLE()->Color3hvNV) +#define glColor4hNV (_GET_TLS_PROCTABLE()->Color4hNV) +#define glColor4hvNV (_GET_TLS_PROCTABLE()->Color4hvNV) +#define glTexCoord1hNV (_GET_TLS_PROCTABLE()->TexCoord1hNV) +#define glTexCoord1hvNV (_GET_TLS_PROCTABLE()->TexCoord1hvNV) +#define glTexCoord2hNV (_GET_TLS_PROCTABLE()->TexCoord2hNV) +#define glTexCoord2hvNV (_GET_TLS_PROCTABLE()->TexCoord2hvNV) +#define glTexCoord3hNV (_GET_TLS_PROCTABLE()->TexCoord3hNV) +#define glTexCoord3hvNV (_GET_TLS_PROCTABLE()->TexCoord3hvNV) +#define glTexCoord4hNV (_GET_TLS_PROCTABLE()->TexCoord4hNV) +#define glTexCoord4hvNV (_GET_TLS_PROCTABLE()->TexCoord4hvNV) +#define glMultiTexCoord1hNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hNV) +#define glMultiTexCoord1hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord1hvNV) +#define glMultiTexCoord2hNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hNV) +#define glMultiTexCoord2hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord2hvNV) +#define glMultiTexCoord3hNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hNV) +#define glMultiTexCoord3hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord3hvNV) +#define glMultiTexCoord4hNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hNV) +#define glMultiTexCoord4hvNV (_GET_TLS_PROCTABLE()->MultiTexCoord4hvNV) +#define glFogCoordhNV (_GET_TLS_PROCTABLE()->FogCoordhNV) +#define glFogCoordhvNV (_GET_TLS_PROCTABLE()->FogCoordhvNV) +#define glSecondaryColor3hNV (_GET_TLS_PROCTABLE()->SecondaryColor3hNV) +#define glSecondaryColor3hvNV (_GET_TLS_PROCTABLE()->SecondaryColor3hvNV) +#define glVertexWeighthNV (_GET_TLS_PROCTABLE()->VertexWeighthNV) +#define glVertexWeighthvNV (_GET_TLS_PROCTABLE()->VertexWeighthvNV) +#define glVertexAttrib1hNV (_GET_TLS_PROCTABLE()->VertexAttrib1hNV) +#define glVertexAttrib1hvNV (_GET_TLS_PROCTABLE()->VertexAttrib1hvNV) +#define glVertexAttrib2hNV (_GET_TLS_PROCTABLE()->VertexAttrib2hNV) +#define glVertexAttrib2hvNV (_GET_TLS_PROCTABLE()->VertexAttrib2hvNV) +#define glVertexAttrib3hNV (_GET_TLS_PROCTABLE()->VertexAttrib3hNV) +#define glVertexAttrib3hvNV (_GET_TLS_PROCTABLE()->VertexAttrib3hvNV) +#define glVertexAttrib4hNV (_GET_TLS_PROCTABLE()->VertexAttrib4hNV) +#define glVertexAttrib4hvNV (_GET_TLS_PROCTABLE()->VertexAttrib4hvNV) +#define glVertexAttribs1hvNV (_GET_TLS_PROCTABLE()->VertexAttribs1hvNV) +#define glVertexAttribs2hvNV (_GET_TLS_PROCTABLE()->VertexAttribs2hvNV) +#define glVertexAttribs3hvNV (_GET_TLS_PROCTABLE()->VertexAttribs3hvNV) +#define glVertexAttribs4hvNV (_GET_TLS_PROCTABLE()->VertexAttribs4hvNV) +#define glPixelDataRangeNV (_GET_TLS_PROCTABLE()->PixelDataRangeNV) +#define glFlushPixelDataRangeNV (_GET_TLS_PROCTABLE()->FlushPixelDataRangeNV) +#define glPrimitiveRestartNV (_GET_TLS_PROCTABLE()->PrimitiveRestartNV) +#define glPrimitiveRestartIndexNV (_GET_TLS_PROCTABLE()->PrimitiveRestartIndexNV) +#define glMapObjectBufferATI (_GET_TLS_PROCTABLE()->MapObjectBufferATI) +#define glUnmapObjectBufferATI (_GET_TLS_PROCTABLE()->UnmapObjectBufferATI) +#define glStencilOpSeparateATI (_GET_TLS_PROCTABLE()->StencilOpSeparateATI) +#define glStencilFuncSeparateATI (_GET_TLS_PROCTABLE()->StencilFuncSeparateATI) +#define glVertexAttribArrayObjectATI (_GET_TLS_PROCTABLE()->VertexAttribArrayObjectATI) +#define glGetVertexAttribArrayObjectfvATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectfvATI) +#define glGetVertexAttribArrayObjectivATI (_GET_TLS_PROCTABLE()->GetVertexAttribArrayObjectivATI) +#define glDepthBoundsEXT (_GET_TLS_PROCTABLE()->DepthBoundsEXT) +#define glBlendEquationSeparateEXT (_GET_TLS_PROCTABLE()->BlendEquationSeparateEXT) +#define glAddSwapHintRectWIN (_GET_TLS_PROCTABLE()->AddSwapHintRectWIN) +#ifdef _WIN32 +#define wglCreateBufferRegionARB (_GET_TLS_PROCTABLE()->CreateBufferRegionARB) +#define wglDeleteBufferRegionARB (_GET_TLS_PROCTABLE()->DeleteBufferRegionARB) +#define wglSaveBufferRegionARB (_GET_TLS_PROCTABLE()->SaveBufferRegionARB) +#define wglRestoreBufferRegionARB (_GET_TLS_PROCTABLE()->RestoreBufferRegionARB) +#define wglGetExtensionsStringARB (_GET_TLS_PROCTABLE()->GetExtensionsStringARB) +#define wglGetPixelFormatAttribivARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivARB) +#define wglGetPixelFormatAttribfvARB (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvARB) +#define wglChoosePixelFormatARB (_GET_TLS_PROCTABLE()->ChoosePixelFormatARB) +#define wglMakeContextCurrentARB (_GET_TLS_PROCTABLE()->MakeContextCurrentARB) +#define wglGetCurrentReadDCARB (_GET_TLS_PROCTABLE()->GetCurrentReadDCARB) +#define wglCreatePbufferARB (_GET_TLS_PROCTABLE()->CreatePbufferARB) +#define wglGetPbufferDCARB (_GET_TLS_PROCTABLE()->GetPbufferDCARB) +#define wglReleasePbufferDCARB (_GET_TLS_PROCTABLE()->ReleasePbufferDCARB) +#define wglDestroyPbufferARB (_GET_TLS_PROCTABLE()->DestroyPbufferARB) +#define wglQueryPbufferARB (_GET_TLS_PROCTABLE()->QueryPbufferARB) +#define wglBindTexImageARB (_GET_TLS_PROCTABLE()->BindTexImageARB) +#define wglReleaseTexImageARB (_GET_TLS_PROCTABLE()->ReleaseTexImageARB) +#define wglSetPbufferAttribARB (_GET_TLS_PROCTABLE()->SetPbufferAttribARB) +#define wglCreateDisplayColorTableEXT (_GET_TLS_PROCTABLE()->CreateDisplayColorTableEXT) +#define wglLoadDisplayColorTableEXT (_GET_TLS_PROCTABLE()->LoadDisplayColorTableEXT) +#define wglBindDisplayColorTableEXT (_GET_TLS_PROCTABLE()->BindDisplayColorTableEXT) +#define wglDestroyDisplayColorTableEXT (_GET_TLS_PROCTABLE()->DestroyDisplayColorTableEXT) +#define wglGetExtensionsStringEXT (_GET_TLS_PROCTABLE()->GetExtensionsStringEXT) +#define wglMakeContextCurrentEXT (_GET_TLS_PROCTABLE()->MakeContextCurrentEXT) +#define wglGetCurrentReadDCEXT (_GET_TLS_PROCTABLE()->GetCurrentReadDCEXT) +#define wglCreatePbufferEXT (_GET_TLS_PROCTABLE()->CreatePbufferEXT) +#define wglGetPbufferDCEXT (_GET_TLS_PROCTABLE()->GetPbufferDCEXT) +#define wglReleasePbufferDCEXT (_GET_TLS_PROCTABLE()->ReleasePbufferDCEXT) +#define wglDestroyPbufferEXT (_GET_TLS_PROCTABLE()->DestroyPbufferEXT) +#define wglQueryPbufferEXT (_GET_TLS_PROCTABLE()->QueryPbufferEXT) +#define wglGetPixelFormatAttribivEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribivEXT) +#define wglGetPixelFormatAttribfvEXT (_GET_TLS_PROCTABLE()->GetPixelFormatAttribfvEXT) +#define wglChoosePixelFormatEXT (_GET_TLS_PROCTABLE()->ChoosePixelFormatEXT) +#define wglSwapIntervalEXT (_GET_TLS_PROCTABLE()->SwapIntervalEXT) +#define wglGetSwapIntervalEXT (_GET_TLS_PROCTABLE()->GetSwapIntervalEXT) +#define wglAllocateMemoryNV (_GET_TLS_PROCTABLE()->AllocateMemoryNV) +#define wglFreeMemoryNV (_GET_TLS_PROCTABLE()->FreeMemoryNV) +#define wglGetSyncValuesOML (_GET_TLS_PROCTABLE()->GetSyncValuesOML) +#define wglGetMscRateOML (_GET_TLS_PROCTABLE()->GetMscRateOML) +#define wglSwapBuffersMscOML (_GET_TLS_PROCTABLE()->SwapBuffersMscOML) +#define wglSwapLayerBuffersMscOML (_GET_TLS_PROCTABLE()->SwapLayerBuffersMscOML) +#define wglWaitForMscOML (_GET_TLS_PROCTABLE()->WaitForMscOML) +#define wglWaitForSbcOML (_GET_TLS_PROCTABLE()->WaitForSbcOML) +#define wglGetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->GetDigitalVideoParametersI3D) +#define wglSetDigitalVideoParametersI3D (_GET_TLS_PROCTABLE()->SetDigitalVideoParametersI3D) +#define wglGetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->GetGammaTableParametersI3D) +#define wglSetGammaTableParametersI3D (_GET_TLS_PROCTABLE()->SetGammaTableParametersI3D) +#define wglGetGammaTableI3D (_GET_TLS_PROCTABLE()->GetGammaTableI3D) +#define wglSetGammaTableI3D (_GET_TLS_PROCTABLE()->SetGammaTableI3D) +#define wglEnableGenlockI3D (_GET_TLS_PROCTABLE()->EnableGenlockI3D) +#define wglDisableGenlockI3D (_GET_TLS_PROCTABLE()->DisableGenlockI3D) +#define wglIsEnabledGenlockI3D (_GET_TLS_PROCTABLE()->IsEnabledGenlockI3D) +#define wglGenlockSourceI3D (_GET_TLS_PROCTABLE()->GenlockSourceI3D) +#define wglGetGenlockSourceI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceI3D) +#define wglGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GenlockSourceEdgeI3D) +#define wglGetGenlockSourceEdgeI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceEdgeI3D) +#define wglGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GenlockSampleRateI3D) +#define wglGetGenlockSampleRateI3D (_GET_TLS_PROCTABLE()->GetGenlockSampleRateI3D) +#define wglGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GenlockSourceDelayI3D) +#define wglGetGenlockSourceDelayI3D (_GET_TLS_PROCTABLE()->GetGenlockSourceDelayI3D) +#define wglQueryGenlockMaxSourceDelayI3D (_GET_TLS_PROCTABLE()->QueryGenlockMaxSourceDelayI3D) +#define wglCreateImageBufferI3D (_GET_TLS_PROCTABLE()->CreateImageBufferI3D) +#define wglDestroyImageBufferI3D (_GET_TLS_PROCTABLE()->DestroyImageBufferI3D) +#define wglAssociateImageBufferEventsI3D (_GET_TLS_PROCTABLE()->AssociateImageBufferEventsI3D) +#define wglReleaseImageBufferEventsI3D (_GET_TLS_PROCTABLE()->ReleaseImageBufferEventsI3D) +#define wglEnableFrameLockI3D (_GET_TLS_PROCTABLE()->EnableFrameLockI3D) +#define wglDisableFrameLockI3D (_GET_TLS_PROCTABLE()->DisableFrameLockI3D) +#define wglIsEnabledFrameLockI3D (_GET_TLS_PROCTABLE()->IsEnabledFrameLockI3D) +#define wglQueryFrameLockMasterI3D (_GET_TLS_PROCTABLE()->QueryFrameLockMasterI3D) +#define wglGetFrameUsageI3D (_GET_TLS_PROCTABLE()->GetFrameUsageI3D) +#define wglBeginFrameTrackingI3D (_GET_TLS_PROCTABLE()->BeginFrameTrackingI3D) +#define wglEndFrameTrackingI3D (_GET_TLS_PROCTABLE()->EndFrameTrackingI3D) +#define wglQueryFrameTrackingI3D (_GET_TLS_PROCTABLE()->QueryFrameTrackingI3D) +#endif /* _WIN32 */ + +#ifndef _APP_PROCTABLE + +/* + * Applications can replace the following function with its own function + * for accessing thread local proc/context dependent proc table. + * The following default function works for most applications which + * are using the same device for all their contexts - even if + * the contexts are on different threads. + */ + +static _inline _GLextensionProcs *_GET_TLS_PROCTABLE(void) + +{ + extern _GLextensionProcs _extensionProcs; + + return (&_extensionProcs); +} + +#else + +/* + * Application should replace this compiled function with + * an inlined function for maximum performance. + */ + +extern _GLextensionProcs *_GET_TLS_PROCTABLE(void); + +#endif + +/* + * Provide an initialization function for the application + * to initialize its own proc tables in case the application + * needs to use multiple proc tables. + */ + +static _inline void _InitExtensionProcs(_GLextensionProcs *appProcs) +{ + extern _GLextensionProcs _extensionProcs; + + *appProcs = _extensionProcs; +} + +#ifdef __cplusplus +} +#endif + + +#endif /* _GLPROCS_H_ */ diff --git a/plugins/gs/zerogs/opengl/install-sh b/plugins/gs/zerogs/opengl/install-sh new file mode 100644 index 0000000..4d4a951 --- /dev/null +++ b/plugins/gs/zerogs/opengl/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/gs/zerogs/opengl/memcpy_amd.cpp b/plugins/gs/zerogs/opengl/memcpy_amd.cpp new file mode 100644 index 0000000..9d22f60 --- /dev/null +++ b/plugins/gs/zerogs/opengl/memcpy_amd.cpp @@ -0,0 +1,479 @@ +/****************************************************************************** + + Copyright (c) 2001 Advanced Micro Devices, Inc. + + LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY + EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, + NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY + PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY + DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, + BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR + INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION + OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY + NOT APPLY TO YOU. + + AMD does not assume any responsibility for any errors which may appear in the + Materials nor any responsibility to support or update the Materials. AMD retains + the right to make changes to its test specifications at any time, without notice. + + NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any + further information, software, technical information, know-how, or show-how + available to you. + + So that all may benefit from your experience, please report any problems + or suggestions about this software to 3dsdk.support@amd.com + + AMD Developer Technologies, M/S 585 + Advanced Micro Devices, Inc. + 5900 E. Ben White Blvd. + Austin, TX 78741 + 3dsdk.support@amd.com +******************************************************************************/ + +#include + +/***************************************************************************** +MEMCPY_AMD.CPP +******************************************************************************/ + +// Very optimized memcpy() routine for AMD Athlon and Duron family. +// This code uses any of FOUR different basic copy methods, depending +// on the transfer size. +// NOTE: Since this code uses MOVNTQ (also known as "Non-Temporal MOV" or +// "Streaming Store"), and also uses the software prefetch instructions, +// be sure you're running on Athlon/Duron or other recent CPU before calling! + +#define TINY_BLOCK_COPY 64 // upper limit for movsd type copy +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". + +#define IN_CACHE_COPY 2 * 1024 // upper limit for movq/movq copy w/SW prefetch +// Next is a copy that uses the MMX registers to copy 8 bytes at a time, +// also using the "unrolled loop" optimization. This code uses +// the software prefetch instruction to get the data into the cache. + +#define UNCACHED_COPY 4 * 1024 // upper limit for movq/movntq w/SW prefetch +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE" + +#define BLOCK_PREFETCH_COPY infinity // no limit for movq/movntq w/block prefetch +#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. + +//#include + +// Inline assembly syntax for use with Visual C++ +#ifdef _WIN32 +#include +#endif + +extern "C" { + +#include "PS2Etypes.h" + +#if defined(_MSC_VER) && !defined(__x86_64__) + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ + __asm { + mov ecx, [n] ; number of bytes to copy + mov edi, [dest] ; destination + mov esi, [src] ; source + mov ebx, ecx ; keep a copy of count + + cld + cmp ecx, TINY_BLOCK_COPY + jb $memcpy_ic_3 ; tiny? skip mmx copy + + cmp ecx, 32*1024 ; don't align between 32k-64k because + jbe $memcpy_do_align ; it appears to be slower + cmp ecx, 64*1024 + jbe $memcpy_align_done +$memcpy_do_align: + mov ecx, 8 ; a trick that's faster than rep movsb... + sub ecx, edi ; align destination to qword + and ecx, 111b ; get the low bits + sub ebx, ecx ; update copy count + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_align_done + jmp ecx ; jump to array of movsb's + +align 4 + movsb + movsb + movsb + movsb + movsb + movsb + movsb + movsb + +$memcpy_align_done: ; destination is dword aligned + mov ecx, ebx ; number of bytes left to copy + shr ecx, 6 ; get 64-byte block count + jz $memcpy_ic_2 ; finish the last few bytes + + cmp ecx, IN_CACHE_COPY/64 ; too big 4 cache? use uncached copy + jae $memcpy_uc_test + +// This is small block copy that uses the MMX registers to copy 8 bytes +// at a time. It uses the "unrolled loop" optimization, and also uses +// the software prefetch instruction to get the data into the cache. +align 16 +$memcpy_ic_1: ; 64-byte block copies, in-cache copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0, [esi+0] ; read 64 bits + movq mm1, [esi+8] + movq [edi+0], mm0 ; write 64 bits + movq [edi+8], mm1 ; note: the normal movq writes the + movq mm2, [esi+16] ; data to cache; a cache line will be + movq mm3, [esi+24] ; allocated as needed, to store the data + movq [edi+16], mm2 + movq [edi+24], mm3 + movq mm0, [esi+32] + movq mm1, [esi+40] + movq [edi+32], mm0 + movq [edi+40], mm1 + movq mm2, [esi+48] + movq mm3, [esi+56] + movq [edi+48], mm2 + movq [edi+56], mm3 + + add esi, 64 ; update source pointer + add edi, 64 ; update destination pointer + dec ecx ; count down + jnz $memcpy_ic_1 ; last 64-byte block? + +$memcpy_ic_2: + mov ecx, ebx ; has valid low 6 bits of the byte count +$memcpy_ic_3: + shr ecx, 2 ; dword count + and ecx, 1111b ; only look at the "remainder" bits + neg ecx ; set up to jump into the array + add ecx, offset $memcpy_last_few + jmp ecx ; jump to array of movsd's + +$memcpy_uc_test: + cmp ecx, UNCACHED_COPY/64 ; big enough? use block prefetch copy + jae $memcpy_bp_1 + +$memcpy_64_test: + or ecx, ecx ; tail end of block prefetch will jump here + jz $memcpy_ic_2 ; no more 64-byte blocks left + +// For larger blocks, which will spill beyond the cache, it's faster to +// use the Streaming Store instruction MOVNTQ. This write instruction +// bypasses the cache and writes straight to main memory. This code also +// uses the software prefetch instruction to pre-read the data. +align 16 +$memcpy_uc_1: ; 64-byte blocks, uncached copy + + prefetchnta [esi + (200*64/34+192)] ; start reading ahead + + movq mm0,[esi+0] ; read 64 bits + add edi,64 ; update destination pointer + movq mm1,[esi+8] + add esi,64 ; update source pointer + movq mm2,[esi-48] + movntq [edi-64], mm0 ; write 64 bits, bypassing the cache + movq mm0,[esi-40] ; note: movntq also prevents the CPU + movntq [edi-56], mm1 ; from READING the destination address + movq mm1,[esi-32] ; into the cache, only to be over-written + movntq [edi-48], mm2 ; so that also helps performance + movq mm2,[esi-24] + movntq [edi-40], mm0 + movq mm0,[esi-16] + movntq [edi-32], mm1 + movq mm1,[esi-8] + movntq [edi-24], mm2 + movntq [edi-16], mm0 + dec ecx + movntq [edi-8], mm1 + jnz $memcpy_uc_1 ; last 64-byte block? + + jmp $memcpy_ic_2 ; almost done + +// For the largest size blocks, a special technique called Block Prefetch +// can be used to accelerate the read operations. Block Prefetch reads +// one address per cache line, for a series of cache lines, in a short loop. +// This is faster than using software prefetch. The technique is great for +// getting maximum read bandwidth, especially in DDR memory systems. +$memcpy_bp_1: ; large blocks, block prefetch copy + + cmp ecx, CACHEBLOCK ; big enough to run another prefetch loop? + jl $memcpy_64_test ; no, back to regular uncached copy + + mov eax, CACHEBLOCK / 2 ; block prefetch loop, unrolled 2X + add esi, CACHEBLOCK * 64 ; move to the top of the block +align 16 +$memcpy_bp_2: + mov edx, [esi-64] ; grab one address per cache line + mov edx, [esi-128] ; grab one address per cache line + sub esi, 128 ; go reverse order to suppress HW prefetcher + dec eax ; count down the cache lines + jnz $memcpy_bp_2 ; keep grabbing more lines into cache + + mov eax, CACHEBLOCK ; now that it's in cache, do the copy +align 16 +$memcpy_bp_3: + movq mm0, [esi ] ; read 64 bits + movq mm1, [esi+ 8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + add esi, 64 ; update source pointer + movntq [edi ], mm0 ; write 64 bits, bypassing cache + movntq [edi+ 8], mm1 ; note: movntq also prevents the CPU + movntq [edi+16], mm2 ; from READING the destination address + movntq [edi+24], mm3 ; into the cache, only to be over-written, + movntq [edi+32], mm4 ; so that also helps performance + movntq [edi+40], mm5 + movntq [edi+48], mm6 + movntq [edi+56], mm7 + add edi, 64 ; update dest pointer + + dec eax ; count down + + jnz $memcpy_bp_3 ; keep copying + sub ecx, CACHEBLOCK ; update the 64-byte block count + jmp $memcpy_bp_1 ; keep processing chunks + +// The smallest copy uses the X86 "movsd" instruction, in an optimized +// form which is an "unrolled loop". Then it handles the last few bytes. +align 4 + movsd + movsd ; perform last 1-15 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + movsd + movsd ; perform last 1-7 dword copies + movsd + movsd + movsd + movsd + movsd + movsd + +$memcpy_last_few: ; dword aligned from before movsd's + mov ecx, ebx ; has valid low 2 bits of the byte count + and ecx, 11b ; the last few cows must come home + jz $memcpy_final ; no more, let's leave + rep movsb ; the last 1, 2, or 3 bytes + +$memcpy_final: + emms ; clean up the MMX state + sfence ; flush the write buffer + mov eax, [dest] ; ret value = destination pointer + + } +} + +// mmx memcpy implementation, size has to be a multiple of 8 +// returns 0 is equal, nonzero value if not equal +// ~10 times faster than standard memcmp +// (zerofrog) +u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +{ + assert( (cmpsize&7) == 0 ); + + __asm { +push esi + mov ecx, cmpsize + mov edx, src1 + mov esi, src2 + + cmp ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + movq mm2, [esi+16] + pmovmskb eax, mm0 + movq mm3, [esi+24] + + // check if eq + cmp eax, 0xff + je NextComp + mov eax, 1 + jmp End + +NextComp: + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je ContinueTest + mov eax, 1 + jmp End + + cmp ecx, 64 + jl Done8 + +Cmp8: + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + movq mm4, [esi+32] + movq mm5, [esi+40] + movq mm6, [esi+48] + movq mm7, [esi+56] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pcmpeqd mm4, [edx+32] + pand mm0, mm2 + pcmpeqd mm5, [edx+40] + pand mm0, mm3 + pcmpeqd mm6, [edx+48] + pand mm0, mm4 + pcmpeqd mm7, [edx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + je Continue + mov eax, 1 + jmp End + +Continue: + sub ecx, 64 + add esi, 64 + add edx, 64 +ContinueTest: + cmp ecx, 64 + jge Cmp8 + +Done8: + test ecx, 0x20 + jz Done4 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + movq mm3, [esi+24] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pcmpeqd mm3, [edx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub ecx, 32 + add esi, 32 + add edx, 32 + + // check if eq + cmp eax, 0xff + je Done4 + mov eax, 1 + jmp End + +Done4: + cmp ecx, 24 + jne Done2 + movq mm0, [esi] + movq mm1, [esi+8] + movq mm2, [esi+16] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pcmpeqd mm2, [edx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done2: + cmp ecx, 16 + jne Done1 + + movq mm0, [esi] + movq mm1, [esi+8] + pcmpeqd mm0, [edx] + pcmpeqd mm1, [edx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + // check if eq + cmp eax, 0xff + setne al + jmp End + +Done1: + cmp ecx, 8 + jne Done + + mov eax, [esi] + mov esi, [esi+4] + cmp eax, [edx] + je Next + mov eax, 1 + jmp End + +Next: + cmp esi, [edx+4] + setne al + jmp End + +Done: + xor eax, eax + +End: + pop esi + emms + } +} + +#else // _MSC_VER +// assume gcc or mingw or win x64 + +#include +#include + +void * memcpy_amd(void *dest, const void *src, size_t n) +{ +memcpy(dest, src, n); +return dest; +} + + +#endif + +} diff --git a/plugins/gs/zerogs/opengl/missing b/plugins/gs/zerogs/opengl/missing new file mode 100644 index 0000000..894e786 --- /dev/null +++ b/plugins/gs/zerogs/opengl/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/gs/zerogs/opengl/mkinstalldirs b/plugins/gs/zerogs/opengl/mkinstalldirs new file mode 100644 index 0000000..259dbfc --- /dev/null +++ b/plugins/gs/zerogs/opengl/mkinstalldirs @@ -0,0 +1,158 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2005-06-29.22 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/gs/zerogs/opengl/rasterfont.cpp b/plugins/gs/zerogs/opengl/rasterfont.cpp new file mode 100644 index 0000000..787ee47 --- /dev/null +++ b/plugins/gs/zerogs/opengl/rasterfont.cpp @@ -0,0 +1,147 @@ + +#ifdef _WIN32 +#include +#endif + +#include +#include + +#include "rasterfont.h" +// globals + +GLubyte rasters[][13] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, + {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, + {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, + {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, + {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, + {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, + {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, + {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, + {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, + {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, + {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, + {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, + {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, + {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, + {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, + {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, + {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, + {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, + {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, + {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, + {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, + {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, + {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, + {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, + {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, + {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, + {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, + {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, + {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, + {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, + {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, + {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, + {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} +}; + +RasterFont::RasterFont() +{ + // set GL modes + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // create the raster font + fontOffset = glGenLists (128); + for (int i = 32; i < 127; i++) { + glNewList(i+fontOffset, GL_COMPILE); + glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); + glEndList(); + } +} + +RasterFont::~RasterFont() +{ + glDeleteLists(fontOffset, 128); +} + +void RasterFont::printString(const char *s, double x, double y, double z) +{ + // go to the right spot + glRasterPos3d(x, y, z); + + glPushAttrib (GL_LIST_BIT); + glListBase(fontOffset); + glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); + glPopAttrib (); +} + +void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) +{ + int length = strlen(s); + int x = int(screen_width/2.0 - (length/2.0)*char_width); + + printString(s, x, y, z); +} + diff --git a/plugins/gs/zerogs/opengl/rasterfont.h b/plugins/gs/zerogs/opengl/rasterfont.h new file mode 100644 index 0000000..a0c7118 --- /dev/null +++ b/plugins/gs/zerogs/opengl/rasterfont.h @@ -0,0 +1,22 @@ +#ifndef RasterFont_Header +#define RasterFont_Header + +class RasterFont { +protected: + int fontOffset; + +public: + RasterFont(); + ~RasterFont(void); + static int debug; + + // some useful constants + enum {char_width = 10}; + enum {char_height = 15}; + + // and the happy helper functions + void printString(const char *s, double x, double y, double z=0.0); + void printCenteredString(const char *s, double y, int screen_width, double z=0.0); +}; + +#endif diff --git a/plugins/gs/zerogs/opengl/targets.cpp b/plugins/gs/zerogs/opengl/targets.cpp new file mode 100644 index 0000000..526f59b --- /dev/null +++ b/plugins/gs/zerogs/opengl/targets.cpp @@ -0,0 +1,3501 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "x86.h" +#include "zerogs.h" + +#include "targets.h" + +const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); + +extern int g_GameSettings; +using namespace ZeroGS; +extern int g_TransferredToGPU; +extern BOOL g_bIsLost; +extern BOOL g_bUpdateStencil; +extern u32 s_uFramebuffer; + +#ifdef RELEASE_TO_PUBLIC +#define INC_RESOLVE() +#else +#define INC_RESOLVE() ++g_nResolve +extern u32 g_nResolve; +extern BOOL g_bSaveTrans; +#endif + +namespace ZeroGS { + CRenderTargetMngr s_RTs, s_DepthRTs; + CBitwiseTextureMngr s_BitwiseTextures; + CMemoryTargetMngr g_MemTargs; + + extern u8 s_AAx, s_AAy; + extern Vector g_vdepth; + extern int icurctx; + + extern VERTEXSHADER pvsBitBlt; + extern FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; + extern FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; + extern GLuint vboRect; +} + +extern u32 s_ptexCurSet[2]; +extern u32 ptexBilinearBlocks; +extern u32 ptexConv32to16; +BOOL g_bSaveZUpdate = 0; + +//////////////////// +// Render Targets // +//////////////////// +ZeroGS::CRenderTarget::CRenderTarget() : ptex(0), ptexFeedback(0), psys(NULL) +{ + nUpdateTarg = 0; +} + +ZeroGS::CRenderTarget::~CRenderTarget() +{ + Destroy(); +} + +bool ZeroGS::CRenderTarget::Create(const frameInfo& frame) +{ + Resolve(); + Destroy(); + + lastused = timeGetTime(); + fbp = frame.fbp; + fbw = frame.fbw; + fbh = frame.fbh; + psm = (u8)frame.psm; + fbm = frame.fbm; + + vposxy.x = 2.0f * (1.0f / 8.0f) / (float)fbw; + vposxy.y = 2.0f * (1.0f / 8.0f) / (float)fbh; + vposxy.z = -1-0.5f/fbw; + vposxy.w = -1+0.5f/fbh; + status = 0; + + if( fbw > 0 && fbh > 0 ) { + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + + psys = _aligned_malloc( (fbh<= fbp ); + + dy = ((256/bpp)*(fbplocal-fbp)) / fbw; + + v.x = vposxy.x; + v.y = vposxy.y; + v.z = vposxy.z; + v.w = vposxy.w - dy*2.0f/(float)fbh; + cgGLSetParameter4fv(g_vparamPosXY[context], v); + } + else + cgGLSetParameter4fv(g_vparamPosXY[context], vposxy); + + // set render states + scissorrect.x = scissor.x0>>3; + scissorrect.y = (scissor.y0>>3) + dy; + scissorrect.w = (scissor.x1>>3)+1; + scissorrect.h = (scissor.y1>>3)+1+dy; + scissorrect.w = min(scissorrect.w, fbw) - scissorrect.x; + scissorrect.h = min(scissorrect.h, fbh) - scissorrect.y; + + scissorrect.x <<= s_AAx; + scissorrect.y <<= s_AAy; + scissorrect.w <<= s_AAx; + scissorrect.h <<= s_AAy; +} + +void ZeroGS::CRenderTarget::SetViewport() +{ + glViewport(0, 0, fbw< 10 || (g_GameSettings&GAME_NOTARGETRESOLVE) ) { + // don't resolve if depths aren't used + status = TS_Resolved; + return; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + GL_REPORT_ERRORD(); + //glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), GetRenderFormat()==RFT_float16?GL_FLOAT:GL_UNSIGNED_BYTE, psys); + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + GL_REPORT_ERRORD(); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveResolved ) { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, fbw< start ); // make sure it at least intersects + + if( ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate) ) { + + // flush if necessary + if( vb[0].prndr == this || vb[0].pdepth == this ) Flush(0); + if( vb[1].prndr == this || vb[1].pdepth == this ) Flush(1); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveResolved ) { + SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, fbw<>6); + + // in now way should data be overwritten!, instead resolve less + if( endrange < end ) { + // round down to nearest block and scanline + resolveheight = ((endrange-start)/(0x2000*(fbw>>6))) * blockheight; + if( resolveheight <= 32 ) { + status = TS_Resolved; + return; + } + } + else if( startrange > start ) { + // round up to nearest block and scanline + resolvefbp = startrange + scanlinewidth - 1; + resolvefbp -= resolvefbp % scanlinewidth; + + resolveheight = fbh-((resolvefbp-fbp)*blockheight/scanlinewidth); + if( resolveheight <= 64 ) { // this is a total hack, but kh doesn't resolve now + status = TS_Resolved; + return; + } + + resolvefbp >>= 8; + } + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex); + //glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), GetRenderFormat()==RFT_float16?GL_FLOAT:GL_UNSIGNED_BYTE, psys); + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys); + GL_REPORT_ERRORD(); + + u8* pbits = (u8*)psys; + u32 Pitch = (fbw<SetDepthStencilSurface(psurfDepth); + ResetRenderTarget(1); + SetRenderTarget(0); + assert( pdepth != NULL ); + ((CDepthTarget*)pdepth)->SetDepthStencilSurface(); + + Vector v = Vector(1,1,-0.5f/(float)(fbw<second == this ) { + ERROR_LOG("updating self"); + nUpdateTarg = 0; + } + } + else if( ittarg->second == this ) { + ERROR_LOG("updating self"); + nUpdateTarg = 0; + } + } + + SetViewport(); + + if( nUpdateTarg ) { + + cgGLSetTextureParameter(ppsBaseTexture.sFinal, ittarg->second->ptex); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + //assert( ittarg->second->fbw == fbw ); + int offset = (fbp-ittarg->second->fbp)*64/fbw; + if( psm & 2 ) // 16 bit + offset *= 2; + + v.x = (float)(fbw << s_AAx); + v.y = (float)(fbh << s_AAy); + v.z = 0.25f; + v.w = (float)(offset << s_AAy) + 0.25f; + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + v.x = v.y = v.z = v.w = 1; + cgGLSetParameter4fv(ppsBaseTexture.sOneColor, v); + + SETPIXELSHADER(ppsBaseTexture.prog); + nUpdateTarg = 0; + } + else { + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + + // write color and zero out stencil buf, always 0 context! + // force bilinear if using AA + SetTexVariablesInt(0, (s_AAx || s_AAy)?2:0, texframe, pmemtarg, &ppsBitBlt[s_AAx], 1); + cgGLSetTextureParameter(ppsBitBlt[s_AAx].sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsBitBlt[s_AAx].sMemory); + + v = Vector(1,1,0,0); + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + v.x = 1; + v.y = 2; + cgGLSetParameter4fv(ppsBitBlt[s_AAx].sOneColor, v); + + assert( ptex != 0 ); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if( ZeroGS::IsWriteDestAlphaTest() ) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 0, 0xff); + glStencilMask(0xff); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + } + + // render with an AA shader if possible (bilinearly interpolates data) + //cgGLLoadProgram(ppsBitBlt[s_AAx].prog); + SETPIXELSHADER(ppsBitBlt[s_AAx].prog); + } + + SETVERTEXSHADER(pvsBitBlt.prog); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // fill stencil buf only + if( ZeroGS::IsWriteDestAlphaTest() && !(g_GameSettings&GAME_NOSTENCIL)) { + glColorMask(0,0,0,0); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL, 1); + + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilFunc(GL_ALWAYS, 1, 0xff); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glColorMask(1,1,1,1); + } + + glEnable(GL_SCISSOR_TEST); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + if( conf.mrtdepth && pdepth != NULL && ZeroGS::IsWriteDepth() ) + pdepth->SetRenderTarget(1); + + status = TS_Resolved; + + // reset since settings changed + vb[0].bVarsTexSync = 0; + ZeroGS::ResetAlphaVariables(); +} + +void ZeroGS::CRenderTarget::ConvertTo32() +{ + u32 ptexConv; + + // create new target + glGenTextures(1, &ptexConv); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexConv); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), fbw<= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + vb[0].bVarsTexSync = 0; +} + +void ZeroGS::CRenderTarget::ConvertTo16() +{ + u32 ptexConv; + + // create new target + glGenTextures(1, &ptexConv); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexConv); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), fbw<Create(frame); +// s_DepthRTs.mapDummyTargs[(fbw<<16)|fbh] = pnewdepth; +// } +// else pnewdepth = (CDepthTarget*)itdepth->second; +// +// assert( pnewdepth != NULL ); +// pd3dDevice->SetDepthStencilSurface(pnewdepth->pdepth); + + SetViewport(); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // render with an AA shader if possible (bilinearly interpolates data) + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsConvert32to16.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + +#ifdef _DEBUG + //g_bSaveZUpdate = 1; + if( g_bSaveZUpdate ) { + SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, fbw<= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + vb[icurctx].bVarsSetTarg = 0; + } + vb[0].bVarsTexSync = 0; +} + +void ZeroGS::CRenderTarget::_CreateFeedback() +{ + if( ptexFeedback == 0 ) { + // create + glGenTextures(1, &ptexFeedback); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexFeedback); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GetRenderTargetFormat(), fbw<= 0 ) { + // reset since settings changed + vb[icurctx].bVarsTexSync = 0; + } + + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +} + +void ZeroGS::CRenderTarget::SetRenderTarget(int targ) +{ + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+targ, GL_TEXTURE_RECTANGLE_NV, ptex, 0 ); + //assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +} + +ZeroGS::CDepthTarget::CDepthTarget() : CRenderTarget(), pdepth(0), pstencil(0), icount(0) {} + +ZeroGS::CDepthTarget::~CDepthTarget() +{ + Destroy(); +} + +bool ZeroGS::CDepthTarget::Create(const frameInfo& frame) +{ + if( !CRenderTarget::Create(frame) ) + return false; + + if( psm == 0x31 ) fbm = 0xff000000; + else fbm = 0; + + assert( glGetError() == GL_NO_ERROR ); + + glGenRenderbuffersEXT( 1, &pdepth ); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, fbw< 0 if depth is used + +void ZeroGS::CDepthTarget::Resolve() +{ + if( g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && ZeroGS::IsWriteDepth() && !(g_GameSettings&GAME_NODEPTHRESOLVE) ) + CRenderTarget::Resolve(); + else { + // flush if necessary + if( vb[0].prndr == this || vb[0].pdepth == this ) Flush(0); + if( vb[1].prndr == this || vb[1].pdepth == this ) Flush(1); + + if( !(status & TS_Virtual) ) + status |= TS_Resolved; + } + + if( !(status&TS_Virtual) ) { + ZeroGS::SetWriteDepth(); + } +} + +void ZeroGS::CDepthTarget::Resolve(int startrange, int endrange) +{ + if( g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && ZeroGS::IsWriteDepth() ) CRenderTarget::Resolve(startrange, endrange); + else { + // flush if necessary + if( vb[0].prndr == this || vb[0].pdepth == this ) Flush(0); + if( vb[1].prndr == this || vb[1].pdepth == this ) Flush(1); + + if( !(status & TS_Virtual) ) + status |= TS_Resolved; + } + + if( !(status&TS_Virtual) ) { + ZeroGS::SetWriteDepth(); + } +} + +extern int g_nDepthUpdateCount; + +void ZeroGS::CDepthTarget::Update(int context, ZeroGS::CRenderTarget* prndr) +{ + assert( !(status & TS_Virtual) ); + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + tex0Info texframe; + texframe.tbp0 = fbp; + texframe.tbw = fbw; + texframe.tw = fbw; + texframe.th = fbh; + texframe.psm = psm; + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); + glDepthMask(1); + glDisable(GL_STENCIL_TEST); + glDepthFunc(GL_ALWAYS); + + // write color and zero out stencil buf, always 0 context! + SetTexVariablesInt(0, 0, texframe, pmemtarg, &ppsBitBltDepth, 1); + cgGLSetTextureParameter(ppsBitBltDepth.sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + Vector v = Vector(1,1,0.5f/(float)fbw,0.5f/(float)fbh); + cgGLSetParameter4fv(pvsBitBlt.sBitBltTex, v); + + v.z = v.w = 0; + v *= 1/32767.0f; + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + v.x = 1; + v.y = 2; + v.z = (psm&3)==2?1.0f:0.0f; + v.w = g_filog32; + cgGLSetParameter4fv(ppsBitBltDepth.sOneColor, v); + + Vector vdepth = ((255.0f/256.0f)*g_vdepth); + if( psm == PSMT24Z ) vdepth.w = 0; + else if( psm != PSMT32Z ) { vdepth.z = vdepth.w = 0; } + assert( ppsBitBltDepth.sBitBltZ != 0 ); + cgGLSetParameter4fv(ppsBitBltDepth.sBitBltZ, ((255.0f/256.0f)*vdepth)); + + assert( pdepth != 0 ); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, ptex, 0 ); + SetDepthStencilSurface(); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0 ); + GLenum buffer = GL_COLOR_ATTACHMENT0_EXT; + glDrawBuffers(1, &buffer); + int stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + + SetViewport(); + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsBitBltDepth.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + status = TS_Resolved; + + if( !ZeroGS::IsWriteDepth() ) { + ResetRenderTarget(1); + } + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_SCISSOR_TEST); + +#ifdef _DEBUG + if( g_bSaveZUpdate ) { + SaveTex(&texframe, 1); + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, fbw<second; + mapTargets.clear(); + for(MAPTARGETS::iterator it = mapDummyTargs.begin(); it != mapDummyTargs.end(); ++it) + delete it->second; + mapDummyTargs.clear(); +} + +void ZeroGS::CRenderTargetMngr::DestroyAllTargs(int start, int end, int fbw) +{ + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) { + if( it->second->start < end && start < it->second->end ) { + // if is depth, only resolve if fbw is the same + if( !it->second->IsDepth() ) { + // only resolve if the widths are the same or it->second has bit outside the range + // shadow of colossus swaps between fbw=256,fbh=256 and fbw=512,fbh=448. This kills the game if doing || it->second->end > end + + // kh hack, sometimes kh movies do this to clear the target, so have a static count that periodically checks end + static int count = 0; + + if( it->second->fbw == fbw || (it->second->fbw != fbw && (it->second->start < start || ((count++&0xf)?0:it->second->end > end) )) ) + it->second->Resolve(); + else { + if( vb[0].prndr == it->second || vb[0].pdepth == it->second ) Flush(0); + if( vb[1].prndr == it->second || vb[1].pdepth == it->second ) Flush(1); + + it->second->status |= CRenderTarget::TS_Resolved; + } + } + else { + if( it->second->fbw == fbw ) + it->second->Resolve(); + else { + if( vb[0].prndr == it->second || vb[0].pdepth == it->second ) Flush(0); + if( vb[1].prndr == it->second || vb[1].pdepth == it->second ) Flush(1); + + it->second->status |= CRenderTarget::TS_Resolved; + } + } + + for(int i = 0; i < 2; ++i) { + if( it->second == vb[i].prndr ) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; } + if( it->second == vb[i].pdepth ) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; } + } + + u32 dummykey = (it->second->fbw<<16)|it->second->fbh; + if( mapDummyTargs.find(dummykey) == mapDummyTargs.end() ) { + mapDummyTargs[dummykey] = it->second; + } + else + delete it->second; + mapTargets.erase(it++); + } + else ++it; + } +} + +void ZeroGS::CRenderTargetMngr::DestroyTarg(CRenderTarget* ptarg) +{ + for(int i = 0; i < 2; ++i) { + if( ptarg == vb[i].prndr ) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; } + if( ptarg == vb[i].pdepth ) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; } + } + + delete ptarg; +} + +void ZeroGS::CRenderTargetMngr::DestroyIntersecting(CRenderTarget* prndr) +{ + assert( prndr != NULL ); + + int start, end; + GetRectMemAddress(start, end, prndr->psm, 0, 0, prndr->fbw, prndr->fbh, prndr->fbp, prndr->fbw); + + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();) { + if( it->second != prndr && it->second->start < end && start < it->second->end ) { + it->second->Resolve(); + + for(int i = 0; i < 2; ++i) { + if( it->second == vb[i].prndr ) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; } + if( it->second == vb[i].pdepth ) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; } + } + + u32 dummykey = (it->second->fbw<<16)|it->second->fbh; + if( mapDummyTargs.find(dummykey) == mapDummyTargs.end() ) { + mapDummyTargs[dummykey] = it->second; + } + else + delete it->second; + + mapTargets.erase(it++); + } + else ++it; + } +} + +CRenderTarget* ZeroGS::CRenderTargetMngr::GetTarg(const frameInfo& frame, u32 opts, int maxposheight) +{ + if( frame.fbw <= 0 || frame.fbh <= 0 ) + return NULL; + + GL_REPORT_ERRORD(); + + u32 key = frame.fbp|(frame.fbw<<16); + MAPTARGETS::iterator it = mapTargets.find(key); + + // only enforce height if frame.fbh <= 0x1c0 + bool bfound = it != mapTargets.end(); + if( bfound ) { + if( opts&TO_StrictHeight ) { + bfound = it->second->fbh == frame.fbh; + } + else { + if( (frame.psm&2)==(it->second->psm&2) && !(g_GameSettings & GAME_FULL16BITRES) ) + bfound = (frame.fbh > 0x1c0 || it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight; + } + } + + if( !bfound ) { + // might be a virtual target + it = mapTargets.find(key|TARGET_VIRTUAL_KEY); + bfound = it != mapTargets.end() && ((opts&TO_StrictHeight) ? it->second->fbh == frame.fbh : it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight; + } + + if( bfound ) { + + // can be both 16bit and 32bit + if( (frame.psm&2) != (it->second->psm&2) ) { + // a lot of games do this actually... +#ifdef _DEBUG + WARN_LOG("Really bad formats! %d %d\n", frame.psm, it->second->psm); +#endif + if( g_GameSettings & GAME_VSSHACK ) { + if( it->second->psm & 2 ) { + it->second->status |= CRenderTarget::TS_NeedConvert32; + it->second->fbh /= 2; + } + else { + it->second->status |= CRenderTarget::TS_NeedConvert16; + it->second->fbh *= 2; + } + } + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + else { + // certain variables have to be reset every time + if( (it->second->psm&~1) != (frame.psm&~1) ) { +#ifndef RELEASE_TO_PUBLIC + WARN_LOG("bad formats 2: %d %d\n", frame.psm, it->second->psm); +#endif + it->second->psm = frame.psm; + + // recalc extents + GetRectMemAddress(it->second->start, it->second->end, frame.psm, 0, 0, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw); + } + } + + if( it->second->fbm != frame.fbm ) { + //WARN_LOG("bad fbm: 0x%8.8x 0x%8.8x, psm: %d\n", frame.fbm, it->second->fbm, frame.psm); + } + + it->second->fbm &= frame.fbm; + it->second->psm = frame.psm; // have to convert (ffx2) + + if( (it->first & TARGET_VIRTUAL_KEY) && !(opts&TO_Virtual) ) { + // switch + it->second->lastused = timeGetTime(); + return Promote(it->first&~TARGET_VIRTUAL_KEY); + } + + // check if there exists a more recent target that this target could update from + for(MAPTARGETS::iterator itnew = mapTargets.begin(); itnew != mapTargets.end(); ++itnew) { + if( itnew->second != it->second && itnew->second->start <= it->second->start && itnew->second->end >= it->second->end && + itnew->second->lastused > it->second->lastused && !(itnew->second->status & CRenderTarget::TS_NeedUpdate) ) { + + it->second->status |= CRenderTarget::TS_NeedUpdate; + it->second->nUpdateTarg = itnew->first; + break; + } + } + + it->second->lastused = timeGetTime(); + + return it->second; + } + + // NOTE: instead of resolving, if current render targ is completely outside of old, can transfer + // the data like that. + + // have to change, so recreate (find all intersecting targets and Resolve) + u32 besttarg = 0; + + if( !(opts & CRenderTargetMngr::TO_Virtual) ) { + + int start, end; + GetRectMemAddress(start, end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + + if( !(opts & CRenderTargetMngr::TO_StrictHeight) ) { + + // if there is only one intersecting target and it encompasses the current one, update the new render target with + // its data instead of resolving then updating (ffx2). Do not change the original target. + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) { +// if( g_GameSettings&GAME_FASTUPDATE ) { +// besttarg = it->first; +// //break; +// } +// else { + if( (g_GameSettings&GAME_FASTUPDATE) || (it->second->fbp != frame.fbp && it->second->fbw == frame.fbw) ) { + + if( besttarg != 0 ) { + besttarg = 0; + break; + } + + if( start >= it->second->start && end <= it->second->end ) { + besttarg = it->first; + } + } +// } + } + } + } + + if( besttarg == 0 ) { + // if none found, resolve all + DestroyAllTargs(start, end, frame.fbw); + } + } + + if( mapTargets.size() > 8 ) { + // release some resources + it = GetOldestTarg(mapTargets); + + // if more than 5s passed since target used, destroy + if( timeGetTime()-it->second->lastused > 5000 ) { + delete it->second; + mapTargets.erase(it); + } + } + + if( mapDummyTargs.size() > 8 ) { + it = GetOldestTarg(mapDummyTargs); + + delete it->second; + mapDummyTargs.erase(it); + } + + // first search for the target + CRenderTarget* ptarg = NULL; + + it = mapDummyTargs.find( (frame.fbw<<16)|frame.fbh ); + if( it != mapDummyTargs.end() ) { + ptarg = it->second; + mapDummyTargs.erase(it); + + // restore all setttings + ptarg->psm = frame.psm; + ptarg->fbm = frame.fbm; + ptarg->fbp = frame.fbp; + GetRectMemAddress(ptarg->start, ptarg->end, frame.psm, 0, 0, frame.fbw, frame.fbh, frame.fbp, frame.fbw); + + ptarg->status = CRenderTarget::TS_NeedUpdate; + } + else { + // create anew + ptarg = (opts&TO_DepthBuffer) ? new CDepthTarget() : new CRenderTarget(); + CRenderTargetMngr* pmngrs[2] = { &s_DepthRTs, this == &s_RTs ? &s_RTs : NULL }; + int cur = 0; + + while( !ptarg->Create(frame) ) { + + // destroy unused targets + if( mapDummyTargs.size() > 0 ) { + it = mapDummyTargs.begin(); + delete it->second; + mapDummyTargs.erase(it); + continue; + } + + if( g_MemTargs.listClearedTargets.size() > 0 ) { + g_MemTargs.DestroyCleared(); + continue; + } + else + if( g_MemTargs.listTargets.size() > 32 ) { + g_MemTargs.DestroyOldest(); + continue; + } + + if( pmngrs[cur] == NULL ) { + cur = !cur; + if( pmngrs[cur] == NULL ) { + WARN_LOG("Out of memory!\n"); + delete ptarg; + return NULL; + } + } + + if( pmngrs[cur]->mapTargets.size() == 0 ) + { + pmngrs[cur] = NULL; + cur = !cur; + continue; + } + + it = GetOldestTarg(pmngrs[cur]->mapTargets); + + DestroyTarg(it->second); + pmngrs[cur]->mapTargets.erase(it); + cur = !cur; + } + } + + if( (opts & CRenderTargetMngr::TO_Virtual) ) { + ptarg->status = CRenderTarget::TS_Virtual; + key |= TARGET_VIRTUAL_KEY; + + if( (it = mapTargets.find(key)) != mapTargets.end() ) { + + DestroyTarg(it->second); + it->second = ptarg; + ptarg->nUpdateTarg = besttarg; + return ptarg; + } + } + else + assert( mapTargets.find(key) == mapTargets.end()); + + ptarg->nUpdateTarg = besttarg; + mapTargets[key] = ptarg; + return ptarg; +} + +ZeroGS::CRenderTargetMngr::MAPTARGETS::iterator ZeroGS::CRenderTargetMngr::GetOldestTarg(MAPTARGETS& m) +{ + if( m.size() == 0 ) { + return m.end(); + } + + // release some resources + u32 curtime = timeGetTime(); + MAPTARGETS::iterator itmaxtarg = m.begin(); + for(MAPTARGETS::iterator it = ++m.begin(); it != m.end(); ++it) { + if( itmaxtarg->second->lastused-curtime < it->second->lastused-curtime ) itmaxtarg = it; + } + + return itmaxtarg; +} + +void ZeroGS::CRenderTargetMngr::GetTargs(int start, int end, list& listTargets) const +{ + for(MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) listTargets.push_back(it->second); + } +} + +void ZeroGS::CRenderTargetMngr::Resolve(int start, int end) +{ + for(MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it) { + if( it->second->start < end && start < it->second->end ) + it->second->Resolve(); + } +} + +void ZeroGS::CMemoryTargetMngr::Destroy() +{ + listTargets.clear(); + listClearedTargets.clear(); +} + +int memcmp_clut16(u16* pSavedBuffer, u16* pClutBuffer, int clutsize) +{ + assert( (clutsize&31) == 0 ); + + // left > 0 only when csa < 16 + int left = ((u32)(uptr)pClutBuffer & 2) ? 0 : (((u32)(uptr)pClutBuffer & 0x3ff)/2) + clutsize - 512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + for(int i = 0; i < 16; ++i) { + if( pSavedBuffer[i] != pClutBuffer[2*i] ) + return 1; + } + + clutsize -= 32; + pSavedBuffer += 16; + pClutBuffer += 32; + } + + if( left > 0 ) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + + while(left > 0) { + for(int i = 0; i < 16; ++i) { + if( pSavedBuffer[i] != pClutBuffer[2*i] ) + return 1; + } + + left -= 32; + pSavedBuffer += 16; + pClutBuffer += 32; + } + } + + return 0; +} + +bool ZeroGS::CMemoryTarget::ValidateClut(const tex0Info& tex0) +{ + assert( tex0.psm == psm && PSMT_ISCLUT(psm) && cpsm == tex0.cpsm ); + + int nClutOffset = 0; + int clutsize = 0; + + int entries = (tex0.psm&3)==3 ? 256 : 16; + if( tex0.cpsm <= 1 ) { // 32 bit + nClutOffset = 64 * tex0.csa; + clutsize = min(entries, 256-tex0.csa*16)*4; + } + else { + nClutOffset = 32 * (tex0.csa&15) + (tex0.csa>=16?2:0); + clutsize = min(entries, 512-tex0.csa*16)*2; + } + + assert( clutsize == clut.size() ); + + if( cpsm <= 1 ) { + if( memcmp_mmx(&clut[0], g_pbyGSClut+nClutOffset, clutsize) ) + return false; + } + else { + if( memcmp_clut16((u16*)&clut[0], (u16*)(g_pbyGSClut+nClutOffset), clutsize) ) + return false; + } + + return true; +} + +int VALIDATE_THRESH = 8; + +bool ZeroGS::CMemoryTarget::ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex) +{ + if( clearmaxy == 0 ) + return true; + + int checkstarty = max(starttex, clearminy); + int checkendy = min(endtex, clearmaxy); + if( checkstarty >= checkendy ) + return true; + + if( validatecount++ > VALIDATE_THRESH ) { + height = 0; + return false; + } + + // lock and compare + assert( ptex != NULL && ptex->memptr != NULL); + + int result = memcmp_mmx(ptex->memptr + (checkstarty-realy)*4*GPU_TEXWIDTH, g_pbyGSMemory+checkstarty*4*GPU_TEXWIDTH, (checkendy-checkstarty)*4*GPU_TEXWIDTH); + + if( result == 0 || !bDeleteBadTex ) { + if( result == 0 ) clearmaxy = 0; + return result == 0; + } + + // delete clearminy, clearmaxy range (not the checkstarty, checkendy range) + int newstarty = 0; + if( clearminy <= starty ) { + if( clearmaxy < starty + height) { + // preserve end + height = starty+height-clearmaxy; + starty = clearmaxy; + assert(height > 0); + } + else { + // destroy + height = 0; + } + } + else { + // beginning can be preserved + height = clearminy-starty; + } + + clearmaxy = 0; + assert( starty >= realy && starty+height<=realy+realheight ); + + return false; +} + +// used to build clut textures (note that this is for both 16 and 32 bit cluts) +#define BUILDCLUT() { \ + switch(tex0.psm) { \ + case PSMT8: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/2; ++j) { \ + pdst[0] = pclut[psrc[0]]; \ + pdst[1] = pclut[psrc[1]]; \ + pdst[2] = pclut[psrc[2]]; \ + pdst[3] = pclut[psrc[3]]; \ + pdst[4] = pclut[psrc[4]]; \ + pdst[5] = pclut[psrc[5]]; \ + pdst[6] = pclut[psrc[6]]; \ + pdst[7] = pclut[psrc[7]]; \ + pdst += 8; \ + psrc += 8; \ + } \ + } \ + break; \ + case PSMT4: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH; ++j) { \ + pdst[0] = pclut[psrc[0]&15]; \ + pdst[1] = pclut[psrc[0]>>4]; \ + pdst[2] = pclut[psrc[1]&15]; \ + pdst[3] = pclut[psrc[1]>>4]; \ + pdst[4] = pclut[psrc[2]&15]; \ + pdst[5] = pclut[psrc[2]>>4]; \ + pdst[6] = pclut[psrc[3]&15]; \ + pdst[7] = pclut[psrc[3]>>4]; \ + \ + pdst += 8; \ + psrc += 4; \ + } \ + } \ + break; \ + case PSMT8H: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]]; \ + pdst[1] = pclut[psrc[7]]; \ + pdst[2] = pclut[psrc[11]]; \ + pdst[3] = pclut[psrc[15]]; \ + pdst[4] = pclut[psrc[19]]; \ + pdst[5] = pclut[psrc[23]]; \ + pdst[6] = pclut[psrc[27]]; \ + pdst[7] = pclut[psrc[31]]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + case PSMT4HH: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]>>4]; \ + pdst[1] = pclut[psrc[7]>>4]; \ + pdst[2] = pclut[psrc[11]>>4]; \ + pdst[3] = pclut[psrc[15]>>4]; \ + pdst[4] = pclut[psrc[19]>>4]; \ + pdst[5] = pclut[psrc[23]>>4]; \ + pdst[6] = pclut[psrc[27]>>4]; \ + pdst[7] = pclut[psrc[31]>>4]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + case PSMT4HL: \ + for(int i = 0; i < targ->height; ++i) { \ + for(int j = 0; j < GPU_TEXWIDTH/8; ++j) { \ + pdst[0] = pclut[psrc[3]&15]; \ + pdst[1] = pclut[psrc[7]&15]; \ + pdst[2] = pclut[psrc[11]&15]; \ + pdst[3] = pclut[psrc[15]&15]; \ + pdst[4] = pclut[psrc[19]&15]; \ + pdst[5] = pclut[psrc[23]&15]; \ + pdst[6] = pclut[psrc[27]&15]; \ + pdst[7] = pclut[psrc[31]&15]; \ + pdst += 8; \ + psrc += 32; \ + } \ + } \ + break; \ + default: \ + assert(0); \ + } \ +} \ + +#define TARGET_THRESH 0x500 + +extern int g_MaxTexWidth, g_MaxTexHeight; + +//#define SORT_TARGETS +inline list::iterator ZeroGS::CMemoryTargetMngr::DestroyTargetIter(list::iterator& it) +{ + // find the target and destroy + list::iterator itprev = it; ++it; + listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); + + if( listClearedTargets.size() > 16 ) { + listClearedTargets.pop_front(); + } + + return it; +} + +#if defined(_MSC_VER) && defined(__x86_64__) +extern "C" void UnswizzleZ16Target(void* dst, void* src, int iters); +#endif + +ZeroGS::CMemoryTarget* ZeroGS::CMemoryTargetMngr::GetMemoryTarget(const tex0Info& tex0, int forcevalidate) +{ + int nbStart, nbEnd; + GetRectMemAddress(nbStart, nbEnd, tex0.psm, 0, 0, tex0.tw, tex0.th, tex0.tbp0, tex0.tbw); + assert( nbStart < nbEnd ); + nbEnd = min(nbEnd, 0x00400000); + + int nClutOffset = 0; + int clutsize = 0; + + if( PSMT_ISCLUT(tex0.psm) ) { + int entries = (tex0.psm&3)==3 ? 256 : 16; + if( tex0.cpsm <= 1 ) { // 32 bit + nClutOffset = 64 * tex0.csa; + clutsize = min(entries, 256-tex0.csa*16)*4; + } + else { + nClutOffset = 64 * (tex0.csa&15) + (tex0.csa>=16?2:0); + clutsize = min(entries, 512-tex0.csa*16)*2; + } + } + + DVProfileFunc _pf("GetMemoryTarget"); + + int start = nbStart / (4*GPU_TEXWIDTH); + int end = (nbEnd + GPU_TEXWIDTH*4 - 1) / (4*GPU_TEXWIDTH); + assert( start < end ); + + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + + if( it->starty <= start && it->starty+it->height >= end ) { + + assert( it->psm != 0xd ); + + // using clut, validate that same data + if( PSMT_ISCLUT(it->psm) != PSMT_ISCLUT(tex0.psm) ) { + if( it->validatecount++ > VALIDATE_THRESH ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + continue; + } + + if( PSMT_ISCLUT(tex0.psm) ) { + assert( it->clut.size() > 0 ); + + if( it->psm != tex0.psm || it->cpsm != tex0.cpsm || it->clut.size() != clutsize ) { + // wrong clut + if( it->validatecount++ > VALIDATE_THRESH ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + continue; + } + + if( tex0.cpsm <= 1 ) { + if( memcmp_mmx(&it->clut[0], g_pbyGSClut+nClutOffset, clutsize) ) { + ++it; + continue; + } + } + else { + if( memcmp_clut16((u16*)&it->clut[0], (u16*)(g_pbyGSClut+nClutOffset), clutsize) ) { + ++it; + continue; + } + } + } + else if( PSMT_IS16BIT(tex0.psm) != PSMT_IS16BIT(it->psm) ) { + + if( it->validatecount++ > VALIDATE_THRESH ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + + continue; + } + + if( forcevalidate ) {//&& listTargets.size() < TARGET_THRESH ) { + // do more validation checking. delete if not been used for a while + if( !it->ValidateTex(tex0, start, end, curstamp > it->usedstamp + 3) ) { + if( it->height <= 0 ) { + it = DestroyTargetIter(it); + if( listTargets.size() == 0 ) + break; + } + else + ++it; + continue; + } + } + + it->usedstamp = curstamp; + it->validatecount = 0; + + return &(*it); + } +#ifdef SORT_TARGETS + else if( it->starty >= end ) + break; +#endif + + ++it; + } + + // couldn't find so create + DVProfileFunc _pf1("GetMemoryTarget:Create"); + + CMemoryTarget* targ; + + u32 fmt = GL_UNSIGNED_BYTE; + if( (PSMT_ISCLUT(tex0.psm) && tex0.cpsm > 1) || tex0.psm == PSMCT16 || tex0.psm == PSMCT16S) { + fmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; + } + + int widthmult = 1; + if( g_MaxTexHeight < 4096 ) { + if( end-start > g_MaxTexHeight ) + widthmult = 2; + } + + int channels = 1; + if( PSMT_ISCLUT(tex0.psm) ) { + if( tex0.psm == PSMT8 ) channels = 4; + else if( tex0.psm == PSMT4 ) channels = 8; + } + else { + if( PSMT_IS16BIT(tex0.psm) ) { + // 16z needs to be a8r8g8b8 + channels = 2; + } + } + + if( listClearedTargets.size() > 0 ) { + + list::iterator itbest = listClearedTargets.begin(); + while(itbest != listClearedTargets.end()) { + + if( end-start <= itbest->realheight && itbest->fmt == fmt && itbest->widthmult == widthmult && itbest->channels == channels ) { + break; + } + ++itbest; + } + + if( itbest != listClearedTargets.end()) { + listTargets.splice(listTargets.end(), listClearedTargets, itbest); + targ = &listTargets.back(); + targ->validatecount = 0; + } + else { + // create a new + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + } + else { + listTargets.push_back(CMemoryTarget()); + targ = &listTargets.back(); + } + + // fill local clut + if( PSMT_ISCLUT(tex0.psm) ) { + assert( clutsize > 0 ); + targ->cpsm = tex0.cpsm; + targ->clut.reserve(256*4); // no matter what + targ->clut.resize(clutsize); + + if( tex0.cpsm <= 1 ) { // 32 bit + memcpy_amd(&targ->clut[0], g_pbyGSClut+nClutOffset, clutsize); + } + else { + u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset); + u16* pclut = (u16*)&targ->clut[0]; + int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset&0x3ff)/2)+clutsize-512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + pclut[0] = pClutBuffer[0]; + pclut++; + pClutBuffer+=2; + clutsize -= 2; + } + + if( left > 0) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + while(left > 0) { + pclut[0] = pClutBuffer[0]; + left -= 2; + pClutBuffer += 2; + pclut++; + } + } + } + } + + if( targ->ptex != NULL ) { + + assert( end-start <= targ->realheight && targ->fmt == fmt && targ->widthmult == widthmult ); + // good enough, so init + targ->realy = targ->starty = start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->height = end-start; + } + + if( targ->ptex == NULL ) { + + // not initialized yet + targ->fmt = fmt; + targ->realy = targ->starty = start; + targ->realheight = targ->height = end-start; + targ->usedstamp = curstamp; + targ->psm = tex0.psm; + targ->cpsm = tex0.cpsm; + targ->widthmult = widthmult; + targ->channels = channels; + + // alloc the mem + targ->ptex = new CMemoryTarget::TEXTURE(); + targ->ptex->ref = 1; + } + +#ifndef RELEASE_TO_PUBLIC + g_TransferredToGPU += GPU_TEXWIDTH * channels * 4 * targ->height; +#endif + + // fill with data + if( targ->ptex->memptr == NULL ) { + targ->ptex->memptr = (u8*)_aligned_malloc(4 * GPU_TEXWIDTH * targ->realheight, 16); + assert(targ->ptex->ref > 0 ); + } + + memcpy_amd(targ->ptex->memptr, g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy, 4 * GPU_TEXWIDTH * targ->height); + vector texdata; + u8* ptexdata = NULL; + + if( PSMT_ISCLUT(tex0.psm) ) { + + texdata.resize( (tex0.cpsm <= 1?4:2) *GPU_TEXWIDTH*channels*widthmult*(targ->realheight+widthmult-1)/widthmult); + ptexdata = &texdata[0]; + + u8* psrc = (u8*)(g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy); + + if( tex0.cpsm <= 1 ) { // 32bit + u32* pclut = (u32*)&targ->clut[0]; + u32* pdst = (u32*)ptexdata; + + BUILDCLUT(); + } + else { + u16* pclut = (u16*)&targ->clut[0]; + u16* pdst = (u16*)ptexdata; + + BUILDCLUT(); + } + } + else { + if( tex0.psm == PSMT16Z || tex0.psm == PSMT16SZ ) { + + texdata.resize(4*GPU_TEXWIDTH*channels*widthmult*(targ->realheight+widthmult-1)/widthmult); + ptexdata = &texdata[0]; + // needs to be 8 bit, use xmm for unpacking + u16* dst = (u16*)ptexdata; + u16* src = (u16*)(g_pbyGSMemory + 4 * GPU_TEXWIDTH * targ->realy); + + assert( ((u32)(uptr)dst)%16 == 0 ); + +#if defined(ZEROGS_SSE2) + int iters = targ->height*GPU_TEXWIDTH/16; + +#if defined(_MSC_VER) + +#if defined(__x86_64__) + UnswizzleZ16Target(dst, src, iters); +#else + __asm { + mov edx, iters + pxor xmm7, xmm7 + mov eax, dst + mov ecx, src + +Z16Loop: + // unpack 64 bytes at a time + movdqa xmm0, [ecx] + movdqa xmm2, [ecx+16] + movdqa xmm4, [ecx+32] + movdqa xmm6, [ecx+48] + + movdqa xmm1, xmm0 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + + punpcklwd xmm0, xmm7 + punpckhwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm3, xmm7 + + // start saving + movdqa [eax], xmm0 + movdqa [eax+16], xmm1 + + punpcklwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + + movdqa [eax+32], xmm2 + movdqa [eax+48], xmm3 + + movdqa xmm0, xmm6 + punpcklwd xmm6, xmm7 + + movdqa [eax+64], xmm4 + movdqa [eax+80], xmm5 + + punpckhwd xmm0, xmm7 + + movdqa [eax+96], xmm6 + movdqa [eax+112], xmm0 + + add ecx, 64 + add eax, 128 + sub edx, 1 + jne Z16Loop + } +#endif // __x86_64__ +#else // _MSC_VER + + __asm__(".intel_syntax\n" + "pxor %%xmm7, %%xmm7\n" + + "Z16Loop:\n" + // unpack 64 bytes at a time + "movdqa %%xmm0, [%0]\n" + "movdqa %%xmm2, [%0+16]\n" + "movdqa %%xmm4, [%0+32]\n" + "movdqa %%xmm6, [%0+48]\n" + + "movdqa %%xmm1, %%xmm0\n" + "movdqa %%xmm3, %%xmm2\n" + "movdqa %%xmm5, %%xmm4\n" + + "punpcklwd %%xmm0, %%xmm7\n" + "punpckhwd %%xmm1, %%xmm7\n" + "punpcklwd %%xmm2, %%xmm7\n" + "punpckhwd %%xmm3, %%xmm7\n" + + // start saving + "movdqa [%1], %%xmm0\n" + "movdqa [%1+16], %%xmm1\n" + + "punpcklwd %%xmm4, %%xmm7\n" + "punpckhwd %%xmm5, %%xmm7\n" + + "movdqa [%1+32], %%xmm2\n" + "movdqa [%1+48], %%xmm3\n" + + "movdqa %%xmm0, %%xmm6\n" + "punpcklwd %%xmm6, %%xmm7\n" + + "movdqa [%1+64], %%xmm4\n" + "movdqa [%1+80], %%xmm5\n" + + "punpckhwd %%xmm0, %%xmm7\n" + + "movdqa [%1+96], %%xmm6\n" + "movdqa [%1+112], %%xmm0\n" + + "add %0, 64\n" + "add %1, 128\n" + "sub %2, 1\n" + "jne Z16Loop\n" + ".att_syntax\n" : "=r"(src), "=r"(dst), "=r"(iters) : "0"(src), "1"(dst), "2"(iters)); + +#endif // _MSC_VER +#else // ZEROGS_SSE2 + for(int i = 0; i < targ->height; ++i) { + for(int j = 0; j < GPU_TEXWIDTH; ++j) { + dst[0] = src[0]; dst[1] = 0; + dst[2] = src[1]; dst[3] = 0; + dst += 4; + src += 2; + } + } +#endif // ZEROGS_SSE2 + } + else { + ptexdata = targ->ptex->memptr; + } + } + + // create the texture + GL_REPORT_ERRORD(); + assert(ptexdata != NULL); + if( targ->ptex->tex == 0 ) + glGenTextures(1, &targ->ptex->tex); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, targ->ptex->tex); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, fmt==GL_UNSIGNED_BYTE?4:GL_RGB5_A1, GPU_TEXWIDTH*channels*widthmult, + (targ->realheight+widthmult-1)/widthmult, 0, GL_RGBA, fmt, ptexdata); + + int realheight = targ->realheight; + while( glGetError() != GL_NO_ERROR ) { + + // release resources until can create + if( listClearedTargets.size() > 0 ) + listClearedTargets.pop_front(); + else { + if( listTargets.size() == 0 ) { + ERROR_LOG("Failed to create %dx%x texture\n", GPU_TEXWIDTH*channels*widthmult, (realheight+widthmult-1)/widthmult); + channels = 1; + return NULL; + } + DestroyOldest(); + } + + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, GPU_TEXWIDTH*channels*widthmult, (targ->realheight+widthmult-1)/widthmult, 0, GL_RGBA, fmt, ptexdata); + } + + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); + + assert( tex0.psm != 0xd ); + if( PSMT_ISCLUT(tex0.psm) ) + assert( targ->clut.size() > 0 ); + + return targ; +} + +void ZeroGS::CMemoryTargetMngr::ClearRange(int nbStartY, int nbEndY) +{ + int starty = nbStartY / (4*GPU_TEXWIDTH); + int endy = (nbEndY+4*GPU_TEXWIDTH-1) / (4*GPU_TEXWIDTH); + //int endy = (nbEndY+4096-1) / 4096; + + //if( listTargets.size() < TARGET_THRESH ) { + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + + if( it->starty < endy && (it->starty+it->height) > starty ) { + + // intersects, reduce valid texture mem (or totally delete texture) + // there are 4 cases + int miny = max(it->starty, starty); + int maxy = min(it->starty+it->height, endy); + assert(miny < maxy); + + if( it->clearmaxy == 0 ) { + it->clearminy = miny; + it->clearmaxy = maxy; + } + else { + if( it->clearminy > miny ) it->clearminy = miny; + if( it->clearmaxy < maxy ) it->clearmaxy = maxy; + } + } + + ++it; + } +// } +// else { +// for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { +// +// if( it->starty < endy && (it->starty+it->height) > starty ) { +// int newstarty = 0; +// if( starty <= it->starty ) { +// if( endy < it->starty + it->height) { +// // preserve end +// it->height = it->starty+it->height-endy; +// it->starty = endy; +// assert(it->height > 0); +// } +// else { +// // destroy +// it->height = 0; +// } +// } +// else { +// // beginning can be preserved +// it->height = starty-it->starty; +// } +// +// assert( it->starty >= it->realy && it->starty+it->height<=it->realy+it->realheight ); +// if( it->height <= 0 ) { +// list::iterator itprev = it; ++it; +// listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev); +// continue; +// } +// } +// +// ++it; +// } +// } +} + +void ZeroGS::CMemoryTargetMngr::DestroyCleared() +{ + for(list::iterator it = listClearedTargets.begin(); it != listClearedTargets.end(); ) { + if( it->usedstamp < curstamp - 2 ) { + it = listClearedTargets.erase(it); + continue; + } + + ++it; + } + + if( (curstamp % 3) == 0 ) { + // purge old targets every 3 frames + for(list::iterator it = listTargets.begin(); it != listTargets.end(); ) { + if( it->usedstamp < curstamp - 3 ) { + it = listTargets.erase(it); + continue; + } + + ++it; + } + } + + ++curstamp; +} + +void ZeroGS::CMemoryTargetMngr::DestroyOldest() +{ + if( listTargets.size() == 0 ) + return; + + list::iterator it, itbest; + it = itbest = listTargets.begin(); + + while(it != listTargets.end()) { + if( it->usedstamp < itbest->usedstamp ) + itbest = it; + ++it; + } + + listTargets.erase(itbest); +} + +////////////////////////////////////// +// Texture Mngr For Bitwise AND Ops // +////////////////////////////////////// +void ZeroGS::CBitwiseTextureMngr::Destroy() +{ + for(map::iterator it = mapTextures.begin(); it != mapTextures.end(); ++it) + glDeleteTextures(1, &it->second); + mapTextures.clear(); +} + +u32 ZeroGS::CBitwiseTextureMngr::GetTexInt(u32 bitvalue, u32 ptexDoNotDelete) +{ + if( mapTextures.size() > 32 ) { + // randomly delete 8 + for(map::iterator it = mapTextures.begin(); it != mapTextures.end();) { + if( !(rand()&3) && it->second != ptexDoNotDelete) { + glDeleteTextures(1, &it->second); + mapTextures.erase(it++); + } + else ++it; + } + } + + // create a new tex + u32 ptex; + glGenTextures(1, &ptex); + + vector data(GPU_TEXMASKWIDTH); + for(u32 i = 0; i < GPU_TEXMASKWIDTH; ++i) + data[i] = ((i&bitvalue)<<6)|0x1f; // add the 1/2 offset so that + + glBindTexture(GL_TEXTURE_2D, ptex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, GPU_TEXMASKWIDTH, 1, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, &data[0]); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + if( glGetError() != GL_NO_ERROR ) { + ERROR_LOG("Failed to create bitmask texture\n"); + return 0; + } + + mapTextures[bitvalue] = ptex; + return ptex; +} + +void ZeroGS::CRangeManager::Insert(int start, int end) +{ + int imin = 0, imax = (int)ranges.size(), imid; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + + switch( ranges.size() ) { + case 0: + ranges.push_back(RANGE(start, end)); + return; + + case 1: + if( end < ranges.front().start ) { + ranges.insert(ranges.begin(), RANGE(start, end)); + } + else if( start > ranges.front().end ) { + ranges.push_back(RANGE(start, end)); + } + else { + if( start < ranges.front().start ) ranges.front().start = start; + if( end > ranges.front().end ) ranges.front().end = end; + } + + return; + } + + // find where start is + while(imin < imax) { + imid = (imin+imax)>>1; + + assert( imid < (int)ranges.size() ); + + if( ranges[imid].end >= start && (imid == 0 || ranges[imid-1].end < start) ) { + imin = imid; + break; + } + else if( ranges[imid].start > start ) imax = imid; + else imin = imid+1; + } + + int startindex = imin; + + if( startindex >= (int)ranges.size() ) { + // non intersecting + assert( start > ranges.back().end ); + ranges.push_back(RANGE(start, end)); + return; + } + if( startindex == 0 && end < ranges.front().start ) { + ranges.insert(ranges.begin(), RANGE(start, end)); + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + return; + } + + imin = 0; imax = (int)ranges.size(); + + // find where end is + while(imin < imax) { + imid = (imin+imax)>>1; + + assert( imid < (int)ranges.size() ); + + if( ranges[imid].end <= end && (imid == ranges.size()-1 || ranges[imid+1].start > end ) ) { + imin = imid; + break; + } + else if( ranges[imid].start >= end ) imax = imid; + else imin = imid+1; + } + + int endindex = imin; + + if( startindex > endindex ) { + // create a new range + ranges.insert(ranges.begin()+startindex, RANGE(start, end)); + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + return; + } + + if( endindex >= (int)ranges.size()-1 ) { + // pop until startindex is reached + int lastend = ranges.back().end; + int numpop = (int)ranges.size() - startindex - 1; + while(numpop-- > 0 ) ranges.pop_back(); + + assert( start <= ranges.back().end ); + if( start < ranges.back().start ) ranges.back().start = start; + if( lastend > ranges.back().end ) ranges.back().end = lastend; + if( end > ranges.back().end ) ranges.back().end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + + return; + } + + if( endindex == 0 ) { + assert( end >= ranges.front().start ); + if( start < ranges.front().start ) ranges.front().start = start; + if( end > ranges.front().end ) ranges.front().end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif + } + + // somewhere in the middle + if( ranges[startindex].start < start ) start = ranges[startindex].start; + + if( startindex < endindex ) { + ranges.erase(ranges.begin() + startindex, ranges.begin() + endindex ); + } + + if( start < ranges[startindex].start ) ranges[startindex].start = start; + if( end > ranges[startindex].end ) ranges[startindex].end = end; + +#ifdef _DEBUG + // sanity check + for(int i = 0; i < (int)ranges.size()-1; ++i) assert( ranges[i].end < ranges[i+1].start ); +#endif +} + +namespace ZeroGS { + +CRangeManager s_RangeMngr; // manages overwritten memory +static int gs_imageEnd = 0; + +void ResolveInRange(int start, int end) +{ + list listTargs; + s_DepthRTs.GetTargs(start, end, listTargs); + s_RTs.GetTargs(start, end, listTargs); + + if( listTargs.size() > 0 ) { + Flush(0); + Flush(1); + + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) { + // only resolve if not completely covered + (*it)->Resolve(); + } + } +} + +////////////////// +// Transferring // +////////////////// +void FlushTransferRanges(const tex0Info* ptex) +{ + assert( s_RangeMngr.ranges.size() > 0 ); + bool bHasFlushed = false; + list listTransmissionUpdateTargs; + + int texstart = -1, texend = -1; + if( ptex != NULL ) { + GetRectMemAddress(texstart, texend, ptex->psm, 0, 0, ptex->tw, ptex->th, ptex->tbp0, ptex->tbw); + } + + for(vector::iterator itrange = s_RangeMngr.ranges.begin(); itrange != s_RangeMngr.ranges.end(); ++itrange ) { + + int start = itrange->start; + int end = itrange->end; + + listTransmissionUpdateTargs.clear(); + s_DepthRTs.GetTargs(start, end, listTransmissionUpdateTargs); + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs); + +// if( !bHasFlushed && listTransmissionUpdateTargs.size() > 0 ) { +// Flush(0); +// Flush(1); +// +//#ifdef _DEBUG +// // make sure targets are still the same +// list::iterator it; +// FORIT(it, listTransmissionUpdateTargs) { +// CRenderTargetMngr::MAPTARGETS::iterator itmap; +// for(itmap = s_RTs.mapTargets.begin(); itmap != s_RTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// if( itmap == s_RTs.mapTargets.end() ) { +// +// for(itmap = s_DepthRTs.mapTargets.begin(); itmap != s_DepthRTs.mapTargets.end(); ++itmap) { +// if( itmap->second == *it ) +// break; +// } +// +// assert( itmap != s_DepthRTs.mapTargets.end() ); +// } +// } +//#endif +// } + + for(list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) { + + CRenderTarget* ptarg = *it; + + if( (ptarg->status & CRenderTarget::TS_Virtual) ) + continue; + + if( !(ptarg->start < texend && ptarg->end > texstart) ) { + // chekc if target is currently being used + + if( !(g_GameSettings & GAME_NOQUICKRESOLVE) ) { + if( ptarg->fbp != vb[0].gsfb.fbp ) {//&& (vb[0].prndr == NULL || ptarg->fbp != vb[0].prndr->fbp) ) { + + if( ptarg->fbp != vb[1].gsfb.fbp ) { //&& (vb[1].prndr == NULL || ptarg->fbp != vb[1].prndr->fbp) ) { + // this render target currently isn't used and is not in the texture's way, so can safely ignore + // resolving it. Also the range has to be big enough compared to the target to really call it resolved + // (ffx changing screens, shadowhearts) + // start == ptarg->start, used for kh to transfer text + if( ptarg->IsDepth() || end-start > 0x50000 || ((g_GameSettings&GAME_QUICKRESOLVE1)&&start == ptarg->start) ) + ptarg->status |= CRenderTarget::TS_NeedUpdate|CRenderTarget::TS_Resolved; + + continue; + } + } + } + } + else { +// if( start <= texstart && end >= texend ) { +// // texture taken care of so can skip!? +// continue; +// } + } + + // the first range check was very rough; some games (dragonball z) have the zbuf in the same page as textures (but not overlapping) + // so detect that condition + if( ptarg->fbh % m_Blocks[ptarg->psm].height ) { + + // get start of left-most boundry page + int targstart, targend; + ZeroGS::GetRectMemAddress(targstart, targend, ptarg->psm, 0, 0, ptarg->fbw, ptarg->fbh & ~(m_Blocks[ptarg->psm].height-1), ptarg->fbp, ptarg->fbw); + + if( start >= targend ) { + + // don't bother + if( (ptarg->fbh % m_Blocks[ptarg->psm].height) <= 2 ) + continue; + + // calc how many bytes of the block that the page spans + } + } + + if( !(ptarg->status & CRenderTarget::TS_Virtual) ) { + + if( start < ptarg->end && end > ptarg->start ) { + + // suikoden5 is faster with check, but too big of a value and kh screens mess up + if( end - start > 0x8000 ) { + // intersects, do only one sided resolves + if( end-start > 4*ptarg->fbw ) { // at least it be greater than one scanline (spiro is faster) + if( start > ptarg->start ) { + ptarg->Resolve(ptarg->start, start); + } + else if( end < ptarg->end ) { + ptarg->Resolve(end, ptarg->end); + } + } + } + + ptarg->status |= CRenderTarget::TS_Resolved; + if( !ptarg->IsDepth() || (!(g_GameSettings & GAME_NODEPTHUPDATE) || end-start > 0x1000) ) + ptarg->status |= CRenderTarget::TS_NeedUpdate; + } + } + } + + ZeroGS::g_MemTargs.ClearRange(start, end); + } + + s_RangeMngr.Clear(); +} + +void InitTransferHostLocal() +{ + if( g_bIsLost ) + return; + +#ifndef RELEASE_TO_PUBLIC + if( gs.trxpos.dx+gs.imageWnew > gs.dstbuf.bw ) + WARN_LOG("Transfer error, width exceeds\n"); +#endif + + bool bHasFlushed = false; + + gs.imageX = gs.trxpos.dx; + gs.imageY = gs.trxpos.dy; + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + + assert( gs.imageEndX < 2048 && gs.imageEndY < 2048 ); + + // hack! viewful joe + if( gs.dstbuf.psm == 63 ) + gs.dstbuf.psm = 0; + + int start, end; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + if( end > 0x00400000 ) { + WARN_LOG("host local out of bounds!\n"); + //gs.imageTransfer = -1; + end = 0x00400000; + } + + gs_imageEnd = end; + + if( vb[0].nCount > 0 ) + Flush(0); + if( vb[1].nCount > 0 ) + Flush(1); + + //PRIM_LOG("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew); + +// if( !bHasFlushed && (vb[0].bNeedFrameCheck || vb[0].bNeedZCheck || vb[1].bNeedFrameCheck || vb[1].bNeedZCheck)) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// +// // for all ranges, flush the targets +// // check if new rect intersects with current rendering texture, if so, flush +// if( vb[0].nCount > 0 && vb[0].curprim.tme ) { +// int tstart, tend; +// GetRectMemAddress(tstart, tend, vb[0].tex0.psm, 0, 0, vb[0].tex0.tw, vb[0].tex0.th, vb[0].tex0.tbp0, vb[0].tex0.tbw); +// +// if( start < tend && end > tstart ) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// } +// +// if( !bHasFlushed && vb[1].nCount > 0 && vb[1].curprim.tme ) { +// int tstart, tend; +// GetRectMemAddress(tstart, tend, vb[1].tex0.psm, 0, 0, vb[1].tex0.tw, vb[1].tex0.th, vb[1].tex0.tbp0, vb[1].tex0.tbw); +// +// if( start < tend && end > tstart ) { +// Flush(0); +// Flush(1); +// bHasFlushed = 1; +// } +// } + + //ZeroGS::g_MemTargs.ClearRange(start, end); + //s_RangeMngr.Insert(start, end); +} + +void TransferHostLocal(const void* pbyMem, u32 nQWordSize) +{ + if( g_bIsLost ) + return; + + DVProfileFunc _pf("TransferHostLocal"); + + int start, end; + GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + assert( start < gs_imageEnd ); + + end = gs_imageEnd; + + // sometimes games can decompress to alpha channel of render target only, in this case + // do a resolve right away. wolverine x2 + if( gs.dstbuf.psm == PSMT8H || gs.dstbuf.psm == PSMT4HL || gs.dstbuf.psm == PSMT4HH ) { + list listTransmissionUpdateTargs; + s_RTs.GetTargs(start, end, listTransmissionUpdateTargs); + + for(list::iterator it = listTransmissionUpdateTargs.begin(); it != listTransmissionUpdateTargs.end(); ++it) { + + CRenderTarget* ptarg = *it; + + if( (ptarg->status & CRenderTarget::TS_Virtual) ) + continue; + + //ERROR_LOG("resolving to alpha channel\n"); + ptarg->Resolve(); + } + } + + s_RangeMngr.Insert(start, min(end, start+(int)nQWordSize*16)); + + m_Blocks[gs.dstbuf.psm].TransferHostLocal(pbyMem, nQWordSize); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveTrans ) { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + } +#endif +} + +// left/right, top/down +//void TransferHostLocal(const void* pbyMem, u32 nQWordSize) +//{ +// assert( gs.imageTransfer == 0 ); +// u8* pstart = g_pbyGSMemory + gs.dstbuf.bp*256; +// +// const u8* pendbuf = (const u8*)pbyMem + nQWordSize*4; +// int i = gs.imageY, j = gs.imageX; +// +//#define DSTPSM gs.dstbuf.psm +// +//#define TRANSFERHOSTLOCAL(psm, T, widthlimit) { \ +// const T* pbuf = (const T*)pbyMem; \ +// u32 nSize = nQWordSize*(4/sizeof(T)); \ +// assert( (nSize%widthlimit) == 0 && widthlimit <= 4 ); \ +// if( ((gs.imageEndX-gs.trxpos.dx)%widthlimit) ) ERROR_LOG("Bad Transmission! %d %d, psm: %d\n", gs.trxpos.dx, gs.imageEndX, DSTPSM); \ +// for(; i < gs.imageEndY; ++i) { \ +// for(; j < gs.imageEndX && nSize > 0; j += widthlimit, nSize -= widthlimit, pbuf += widthlimit) { \ +// /* write as many pixel at one time as possible */ \ +// writePixel##psm##_0(pstart, j%2048, i%2048, pbuf[0], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 1 ) { \ +// writePixel##psm##_0(pstart, (j+1)%2048, i%2048, pbuf[1], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 2 ) { \ +// writePixel##psm##_0(pstart, (j+2)%2048, i%2048, pbuf[2], gs.dstbuf.bw); \ +// \ +// if( widthlimit > 3 ) { \ +// writePixel##psm##_0(pstart, (j+3)%2048, i%2048, pbuf[3], gs.dstbuf.bw); \ +// } \ +// } \ +// } \ +// } \ +// \ +// if( j >= gs.imageEndX ) { assert(j == gs.imageEndX); j = gs.trxpos.dx; } \ +// else { assert( nSize == 0 ); goto End; } \ +// } \ +//} \ +// +//#define TRANSFERHOSTLOCAL_4(psm) { \ +// const u8* pbuf = (const u8*)pbyMem; \ +// u32 nSize = nQWordSize*8; \ +// for(; i < gs.imageEndY; ++i) { \ +// for(; j < gs.imageEndX && nSize > 0; j += 8, nSize -= 8) { \ +// /* write as many pixel at one time as possible */ \ +// writePixel##psm##_0(pstart, j%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+1)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+2)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+3)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+4)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+5)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// writePixel##psm##_0(pstart, (j+6)%2048, i%2048, *pbuf&0x0f, gs.dstbuf.bw); \ +// writePixel##psm##_0(pstart, (j+7)%2048, i%2048, *pbuf>>4, gs.dstbuf.bw); \ +// pbuf++; \ +// } \ +// \ +// if( j >= gs.imageEndX ) { /*assert(j == gs.imageEndX);*/ j = gs.trxpos.dx; } \ +// else { assert( nSize == 0 ); goto End; } \ +// } \ +//} \ +// +// switch (gs.dstbuf.psm) { +// case 0x0: TRANSFERHOSTLOCAL(32, u32, 2); break; +// case 0x1: TRANSFERHOSTLOCAL(24, u32, 4); break; +// case 0x2: TRANSFERHOSTLOCAL(16, u16, 4); break; +// case 0xA: TRANSFERHOSTLOCAL(16S, u16, 4); break; +// case 0x13: +// if( ((gs.imageEndX-gs.trxpos.dx)%4) ) { +// TRANSFERHOSTLOCAL(8, u8, 1); +// } +// else { +// TRANSFERHOSTLOCAL(8, u8, 4); +// } +// break; +// +// case 0x14: +//// if( (gs.imageEndX-gs.trxpos.dx)%8 ) { +//// // hack +//// if( abs((int)nQWordSize*8 - (gs.imageEndY-i)*(gs.imageEndX-gs.trxpos.dx)+(j-gs.trxpos.dx)) <= 8 ) { +//// // don't transfer +//// ERROR_LOG("bad texture 4: %d %d %d\n", gs.trxpos.dx, gs.imageEndX, nQWordSize); +//// gs.imageEndX = gs.trxpos.dx + (gs.imageEndX-gs.trxpos.dx)&~7; +//// //i = gs.imageEndY; +//// //goto End; +//// gs.imageTransfer = -1; +//// } +//// } +// TRANSFERHOSTLOCAL_4(4); +// break; +// case 0x1B: TRANSFERHOSTLOCAL(8H, u8, 4); break; +// case 0x24: TRANSFERHOSTLOCAL_4(4HL); break; +// case 0x2C: TRANSFERHOSTLOCAL_4(4HH); break; +// case 0x30: TRANSFERHOSTLOCAL(32Z, u32, 2); break; +// case 0x31: TRANSFERHOSTLOCAL(24Z, u32, 4); break; +// case 0x32: TRANSFERHOSTLOCAL(16Z, u16, 4); break; +// case 0x3A: TRANSFERHOSTLOCAL(16SZ, u16, 4); break; +// } +// +//End: +// if( i >= gs.imageEndY ) { +// assert( i == gs.imageEndY ); +// gs.imageTransfer = -1; +// +// if( g_bSaveTrans ) { +// tex0Info t; +// t.tbp0 = gs.dstbuf.bp; +// t.tw = gs.imageWnew; +// t.th = gs.imageHnew; +// t.tbw = gs.dstbuf.bw; +// t.psm = gs.dstbuf.psm; +// SaveTex(&t, 0); +// } +// } +// else { +// /* update new params */ +// gs.imageY = i; +// gs.imageX = j; +// } +//} + +void InitTransferLocalHost() +{ + assert( gs.trxpos.sx+gs.imageWnew <= 2048 && gs.trxpos.sy+gs.imageHnew <= 2048 ); + +#ifndef RELEASE_TO_PUBLIC + if( gs.trxpos.sx+gs.imageWnew > gs.srcbuf.bw ) + WARN_LOG("Transfer error, width exceeds\n"); +#endif + + gs.imageX = gs.trxpos.sx; + gs.imageY = gs.trxpos.sy; + gs.imageEndX = gs.imageX + gs.imageWnew; + gs.imageEndY = gs.imageY + gs.imageHnew; + + int start, end; + GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + ResolveInRange(start, end); +} + +// left/right, top/down +void TransferLocalHost(void* pbyMem, u32 nQWordSize) +{ + assert( gs.imageTransfer == 1 ); + + u8* pstart = g_pbyGSMemory + 256*gs.srcbuf.bp; + int i = gs.imageY, j = gs.imageX; + +#define TRANSFERLOCALHOST(psm, T) { \ + T* pbuf = (T*)pbyMem; \ + u32 nSize = nQWordSize*16/sizeof(T); \ + for(; i < gs.imageEndY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; ++j, --nSize) { \ + *pbuf++ = readPixel##psm##_0(pstart, j%2048, i%2048, gs.srcbuf.bw); \ + } \ + \ + if( j >= gs.imageEndX ) { assert( j == gs.imageEndX); j = gs.trxpos.sx; } \ + else { assert( nSize == 0 ); break; } \ + } \ +} \ + +#define TRANSFERLOCALHOST_24(psm) { \ + u8* pbuf = (u8*)pbyMem; \ + u32 nSize = nQWordSize*16/3; \ + for(; i < gs.imageEndY; ++i) { \ + for(; j < gs.imageEndX && nSize > 0; ++j, --nSize) { \ + u32 p = readPixel##psm##_0(pstart, j%2048, i%2048, gs.srcbuf.bw); \ + pbuf[0] = (u8)p; \ + pbuf[1] = (u8)(p>>8); \ + pbuf[2] = (u8)(p>>16); \ + pbuf += 3; \ + } \ + \ + if( j >= gs.imageEndX ) { assert( j == gs.imageEndX); j = gs.trxpos.sx; } \ + else { assert( nSize == 0 ); break; } \ + } \ +} \ + + switch (gs.srcbuf.psm) { + case 0x0: TRANSFERLOCALHOST(32, u32); break; + case 0x1: TRANSFERLOCALHOST_24(24); break; + case 0x2: TRANSFERLOCALHOST(16, u16); break; + case 0xA: TRANSFERLOCALHOST(16S, u16); break; + case 0x13: TRANSFERLOCALHOST(8, u8); break; + case 0x1B: TRANSFERLOCALHOST(8H, u8); break; + case 0x30: TRANSFERLOCALHOST(32Z, u32); break; + case 0x31: TRANSFERLOCALHOST_24(24Z); break; + case 0x32: TRANSFERLOCALHOST(16Z, u16); break; + case 0x3A: TRANSFERLOCALHOST(16SZ, u16); break; + default: assert(0); + } + + gs.imageY = i; + gs.imageX = j; + + if( gs.imageY >= gs.imageEndY ) { + assert( gs.imageY == gs.imageEndY ); + gs.imageTransfer = -1; + } +} + +// dir depends on trxpos.dir +void TransferLocalLocal() +{ + assert( gs.imageTransfer == 2 ); + assert( gs.trxpos.sx+gs.imageWnew < 2048 && gs.trxpos.sy+gs.imageHnew < 2048 ); + assert( gs.trxpos.dx+gs.imageWnew < 2048 && gs.trxpos.dy+gs.imageHnew < 2048 ); + assert( (gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7) ); + if( gs.trxpos.sx+gs.imageWnew > gs.srcbuf.bw ) + WARN_LOG("Transfer error, src width exceeds\n"); + if( gs.trxpos.dx+gs.imageWnew > gs.dstbuf.bw ) + WARN_LOG("Transfer error, dst width exceeds\n"); + + int srcstart, srcend, dststart, dstend; + + GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw); + GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw); + + // resolve the targs + ResolveInRange(srcstart, srcend); + + list listTargs; + s_RTs.GetTargs(dststart, dstend, listTargs); + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) { + if( !((*it)->status & CRenderTarget::TS_Virtual) ) { + (*it)->Resolve(); + (*it)->status |= CRenderTarget::TS_NeedUpdate; + } + } + + u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp*256; + u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp*256; + +#define TRANSFERLOCALLOCAL(srcpsm, dstpsm, widthlimit) { \ + assert( (gs.imageWnew&widthlimit)==0 && widthlimit <= 4); \ + for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < gs.trxpos.sy+gs.imageHnew; i++, i2++) { \ + for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < gs.trxpos.sx+gs.imageWnew; j+=widthlimit, j2+=widthlimit) { \ + \ + writePixel##dstpsm##_0(pDstBuf, j2%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, j%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 1 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+1)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+1)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 2 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+2)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+2)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + \ + if( widthlimit > 3 ) { \ + writePixel##dstpsm##_0(pDstBuf, (j2+3)%2048, i2%2048, \ + readPixel##srcpsm##_0(pSrcBuf, (j+3)%2048, i%2048, gs.srcbuf.bw), gs.dstbuf.bw); \ + } \ + } \ + } \ + } \ + } \ +} \ + +#define TRANSFERLOCALLOCAL_4(srcpsm, dstpsm) { \ + assert( (gs.imageWnew%8) == 0 ); \ + for(int i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < gs.trxpos.sy+gs.imageHnew; ++i, ++i2) { \ + for(int j = gs.trxpos.sx, j2 = gs.trxpos.dx; j < gs.trxpos.sx+gs.imageWnew; j+=8, j2+=8) { \ + /* NOTE: the 2 conseq 4bit values are in NOT in the same byte */ \ + u32 read = getPixelAddress##srcpsm##_0(j%2048, i%2048, gs.srcbuf.bw); \ + u32 write = getPixelAddress##dstpsm##_0(j2%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+1)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+1)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + \ + read = getPixelAddress##srcpsm##_0((j+2)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+2)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0xf0)|(pSrcBuf[read]&0x0f); \ + \ + read = getPixelAddress##srcpsm##_0((j+3)%2048, i%2048, gs.srcbuf.bw); \ + write = getPixelAddress##dstpsm##_0((j2+3)%2048, i2%2048, gs.dstbuf.bw); \ + pDstBuf[write] = (pDstBuf[write]&0x0f)|(pSrcBuf[read]&0xf0); \ + } \ + } \ +} \ + + switch (gs.srcbuf.psm) { + case PSMCT32: + if( gs.dstbuf.psm == PSMCT32 ) { + TRANSFERLOCALLOCAL(32, 32, 2); + } + else { + TRANSFERLOCALLOCAL(32, 32Z, 2); + } + break; + + case PSMCT24: + if( gs.dstbuf.psm == PSMCT24 ) { + TRANSFERLOCALLOCAL(24, 24, 4); + } + else { + TRANSFERLOCALLOCAL(24, 24Z, 4); + } + break; + + case PSMCT16: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16, 16SZ, 4); break; + } + break; + + case PSMCT16S: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16S, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16S, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16S, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16S, 16SZ, 4); break; + } + break; + + case PSMT8: + if( gs.dstbuf.psm == PSMT8 ) { + TRANSFERLOCALLOCAL(8, 8, 4); + } + else { + TRANSFERLOCALLOCAL(8, 8H, 4); + } + break; + + case PSMT4: + + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4, 4HH); break; + } + break; + + case PSMT8H: + if( gs.dstbuf.psm == PSMT8 ) { + TRANSFERLOCALLOCAL(8H, 8, 4); + } + else { + TRANSFERLOCALLOCAL(8H, 8H, 4); + } + break; + + case PSMT4HL: + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4HL, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4HL, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4HL, 4HH); break; + } + break; + case PSMT4HH: + switch(gs.dstbuf.psm ) { + case PSMT4: TRANSFERLOCALLOCAL_4(4HH, 4); break; + case PSMT4HL: TRANSFERLOCALLOCAL_4(4HH, 4HL); break; + case PSMT4HH: TRANSFERLOCALLOCAL_4(4HH, 4HH); break; + } + break; + + case PSMT32Z: + if( gs.dstbuf.psm == PSMCT32 ) { + TRANSFERLOCALLOCAL(32Z, 32, 2); + } + else { + TRANSFERLOCALLOCAL(32Z, 32Z, 2); + } + break; + + case PSMT24Z: + if( gs.dstbuf.psm == PSMCT24 ) { + TRANSFERLOCALLOCAL(24Z, 24, 4); + } + else { + TRANSFERLOCALLOCAL(24Z, 24Z, 4); + } + break; + + case PSMT16Z: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16Z, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16Z, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16Z, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16Z, 16SZ, 4); break; + } + break; + + case PSMT16SZ: + switch(gs.dstbuf.psm) { + case PSMCT16: TRANSFERLOCALLOCAL(16SZ, 16, 4); break; + case PSMCT16S: TRANSFERLOCALLOCAL(16SZ, 16S, 4); break; + case PSMT16Z: TRANSFERLOCALLOCAL(16SZ, 16Z, 4); break; + case PSMT16SZ: TRANSFERLOCALLOCAL(16SZ, 16SZ, 4); break; + } + break; + } + + g_MemTargs.ClearRange(dststart, dstend); + +#if !defined(RELEASE_TO_PUBLIC) && defined(_DEBUG) + if( g_bSaveTrans ) { + tex0Info t; + t.tbp0 = gs.dstbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.dstbuf.bw; + t.psm = gs.dstbuf.psm; + SaveTex(&t, 0); + + t.tbp0 = gs.srcbuf.bp; + t.tw = gs.imageWnew; + t.th = gs.imageHnew; + t.tbw = gs.srcbuf.bw; + t.psm = gs.srcbuf.psm; + SaveTex(&t, 0); + } +#endif +} + +void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw) +{ + if( (psm&0x30) == 0x30 || psm == 0xa ) { + + if( m_Blocks[psm].bpp == 0 ) { + ERROR_LOG("Bad psm 0x%x\n", psm); + start = 0; + end = 0x00400000; + return; + } + + const BLOCK& b = m_Blocks[psm]; + + bw = (bw + b.width -1)/b.width; + start = bp*256 + ((y/b.height) * bw + (x/b.width) )*0x2000; + end = bp*256 + (((y+h-1)/b.height) * bw + (x + w + b.width - 1)/b.width)*0x2000; + } + else { + // just take the addresses + switch(psm) { + case 0x00: + case 0x01: + case 0x1b: + case 0x24: + case 0x2c: + start = 4*getPixelAddress32(x, y, bp, bw); + end = 4*getPixelAddress32(x+w-1, y+h-1, bp, bw) + 4; + break; + case 0x02: + start = 2*getPixelAddress16(x, y, bp, bw); + end = 2*getPixelAddress16(x+w-1, y+h-1, bp, bw)+2; + break; + case 0x13: + start = getPixelAddress8(x, y, bp, bw); + end = getPixelAddress8(x+w-1, y+h-1, bp, bw)+1; + break; + case 0x14: + { + start = getPixelAddress4(x, y, bp, bw)/2; + int newx = ((x+w-1+31)&~31)-1; + int newy = ((y+h-1+15)&~15)-1; + end = (getPixelAddress4(max(newx,x), max(newy,y), bp, bw)+2)/2; + break; + } + } + } +} + +void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm) +{ + //assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + s_nResolved += 2; + + // align the rect to the nearest page + // note that fbp is always aligned on page boundaries + int start, end; + GetRectMemAddress(start, end, psm, 0, 0, fbw, fbh, fbp, fbw); + + PRIM_LOG("resolve: %x %x %x (%x-%x)\n", fbp, fbw, fbh, start, end); + + int i, j; + short smask1 = gs.smask&1; + short smask2 = gs.smask&2; + u32 mask, imask; + + if( psm&2 ) { // 16 bit + // mask is shifted + imask = RGBA32to16(fbm); + mask = (~imask)&0xffff; + } + else { + mask = ~fbm; + imask = fbm; + + if( (psm&0xf)>0 ) { + // preserve the alpha? + mask &= 0x00ffffff; + imask |= 0xff000000; + } + } + int Pitch; + +#define RESOLVE_32BIT(psm, T, Tsrc, blockbits, blockwidth, blockheight, convfn, frame, aax, aay) \ + { \ + Tsrc* src = (Tsrc*)psrc; \ + T* pPageOffset = (T*)g_pbyGSMemory + fbp*(256/sizeof(T)), *dst; \ + int srcpitch = Pitch * blockheight/sizeof(Tsrc); \ + int maxfbh = (0x00400000-fbp*256) / (sizeof(T) * fbw); \ + if( maxfbh > fbh ) maxfbh = fbh; \ + for(i = 0; i < (maxfbh&~(blockheight-1)); i += blockheight) { \ + /*if( smask2 && (i&1) == smask1 ) continue; */ \ + for(j = 0; j < fbw; j += blockwidth) { \ + /* have to write in the tiled format*/ \ + frame##SwizzleBlock##blockbits(pPageOffset + getPixelAddress##psm##_0(j, i, fbw), \ + src+(j< psm + switch(psm) { + case PSMCT32: + case PSMCT24: + if( s_AAy ) { + RESOLVE_32BIT(32, u32, u32, 32A4, 8, 8, (u32), Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else { + RESOLVE_32BIT(32, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + break; + case PSMCT16: + if( s_AAy ) { + RESOLVE_32BIT(16, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else { + RESOLVE_32BIT(16, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + case PSMCT16S: + if( s_AAy ) { + RESOLVE_32BIT(16S, u16, u32, 16A4, 16, 8, RGBA32to16, Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16S, u16, u32, 16A2, 16, 8, RGBA32to16, Frame, 1, 0); + } + else { + RESOLVE_32BIT(16S, u16, u32, 16, 16, 8, RGBA32to16, Frame, 0, 0); + } + + break; + case PSMT32Z: + case PSMT24Z: + if( s_AAy ) { + RESOLVE_32BIT(32Z, u32, u32, 32A4, 8, 8, (u32), Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32Z, u32, u32, 32A2, 8, 8, (u32), Frame, 1, 0); + } + else { + RESOLVE_32BIT(32Z, u32, u32, 32, 8, 8, (u32), Frame, 0, 0); + } + + break; + case PSMT16Z: + if( s_AAy ) { + RESOLVE_32BIT(16Z, u16, u32, 16A4, 16, 8, (u16), Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16Z, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else { + RESOLVE_32BIT(16Z, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + case PSMT16SZ: + if( s_AAy ) { + RESOLVE_32BIT(16SZ, u16, u32, 16A4, 16, 8, (u16), Frame, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16SZ, u16, u32, 16A2, 16, 8, (u16), Frame, 1, 0); + } + else { + RESOLVE_32BIT(16SZ, u16, u32, 16, 16, 8, (u16), Frame, 0, 0); + } + + break; + } + } + else { // float16 + + Pitch = fbw * 8; + + switch(psm) { + case PSMCT32: + case PSMCT24: + if( s_AAy ) { + RESOLVE_32BIT(32, u32, Vector_16F, 32A4, 8, 8, Float16ToARGB, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32, u32, Vector_16F, 32A2, 8, 8, Float16ToARGB, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(32, u32, Vector_16F, 32, 8, 8, Float16ToARGB, Frame16, 0, 0); + } + + break; + case PSMCT16: + if( s_AAy ) { + RESOLVE_32BIT(16, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + case PSMCT16S: + if( s_AAy ) { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A4, 16, 8, Float16ToARGB16, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16S, u16, Vector_16F, 16A2, 16, 8, Float16ToARGB16, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16S, u16, Vector_16F, 16, 16, 8, Float16ToARGB16, Frame16, 0, 0); + } + + break; + case PSMT32Z: + case PSMT24Z: + if( s_AAy ) { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA4, 8, 8, Float16ToARGB_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32ZA2, 8, 8, Float16ToARGB_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(32Z, u32, Vector_16F, 32Z, 8, 8, Float16ToARGB_Z, Frame16, 0, 0); + } + + break; + case PSMT16Z: + if( s_AAy ) { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16Z, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + case PSMT16SZ: + if( s_AAy ) { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA4, 16, 8, Float16ToARGB16_Z, Frame16, 1, 1); + } + else if( s_AAx ) { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16ZA2, 16, 8, Float16ToARGB16_Z, Frame16, 1, 0); + } + else { + RESOLVE_32BIT(16SZ, u16, Vector_16F, 16Z, 16, 8, Float16ToARGB16_Z, Frame16, 0, 0); + } + + break; + } + } + + g_MemTargs.ClearRange(start, end); + INC_RESOLVE(); +} + +//////////// +// Saving // +//////////// +void SaveTex(tex0Info* ptex, int usevid) +{ + vector data(ptex->tw*ptex->th); + vector srcdata; + + u32* dst = &data[0]; + u8* psrc = g_pbyGSMemory; + + CMemoryTarget* pmemtarg = NULL; + + if( usevid ) { + + pmemtarg = g_MemTargs.GetMemoryTarget(*ptex, 0); + assert( pmemtarg != NULL ); + + glBindTexture(GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex); + srcdata.resize(pmemtarg->realheight*GPU_TEXWIDTH*pmemtarg->widthmult*4*8); // max of 8 cannels + + glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pmemtarg->fmt, &srcdata[0]); + + u32 offset = pmemtarg->realy * 4 * GPU_TEXWIDTH; + if( ptex->psm == PSMT8 ) offset *= ptex->cpsm <= 1 ? 4 : 2; + else if( ptex->psm == PSMT4 ) offset *= ptex->cpsm <= 1 ? 8 : 4; + + psrc = &srcdata[0] - offset; + } + + for(int i = 0; i < ptex->th; ++i) { + for(int j = 0; j < ptex->tw; ++j) { + u32 u, addr; + switch(ptex->psm) { + case PSMCT32: + addr = getPixelAddress32(j, i, ptex->tbp0, ptex->tbw); + + if( addr*4 < 0x00400000 ) + u = readPixel32(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + + break; + case PSMCT24: + addr = getPixelAddress24(j, i, ptex->tbp0, ptex->tbw); + + if( addr*4 < 0x00400000 ) + u = readPixel24(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + + break; + case PSMCT16: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + + if( addr*2 < 0x00400000 ) { + u = readPixel16(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else u = 0; + + break; + case PSMCT16S: + addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw); + + if( addr*2 < 0x00400000 ) { + u = readPixel16S(psrc, j, i, ptex->tbp0, ptex->tbw); + u = RGBA16to32(u); + } + else u = 0; + break; + + case PSMT8: + addr = getPixelAddress8(j, i, ptex->tbp0, ptex->tbw); + + if( addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel8(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT4: + addr = getPixelAddress4(j, i, ptex->tbp0, ptex->tbw); + + if( addr < 2*0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT8H: + addr = getPixelAddress8H(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel8H(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + + break; + + case PSMT4HL: + addr = getPixelAddress4HL(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4HL(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT4HH: + addr = getPixelAddress4HH(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) { + if( usevid ) { + if( ptex->cpsm <= 1 ) u = *(u32*)(psrc+4*addr); + else u = RGBA16to32(*(u16*)(psrc+2*addr)); + } + else + u = readPixel4HH(psrc, j, i, ptex->tbp0, ptex->tbw); + } + else u = 0; + break; + + case PSMT32Z: + addr = getPixelAddress32Z(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) + u = readPixel32Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT24Z: + addr = getPixelAddress24Z(j, i, ptex->tbp0, ptex->tbw); + + if( 4*addr < 0x00400000 ) + u = readPixel24Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT16Z: + addr = getPixelAddress16Z(j, i, ptex->tbp0, ptex->tbw); + + if( 2*addr < 0x00400000 ) + u = readPixel16Z(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + case PSMT16SZ: + addr = getPixelAddress16SZ(j, i, ptex->tbp0, ptex->tbw); + + if( 2*addr < 0x00400000 ) + u = readPixel16SZ(psrc, j, i, ptex->tbp0, ptex->tbw); + else u = 0; + break; + + default: + assert(0); + } + + *dst++ = u; + } + } + + SaveTGA("tex.tga", ptex->tw, ptex->th, &data[0]); +} + +} diff --git a/plugins/gs/zerogs/opengl/targets.h b/plugins/gs/zerogs/opengl/targets.h new file mode 100644 index 0000000..6c7bfdf --- /dev/null +++ b/plugins/gs/zerogs/opengl/targets.h @@ -0,0 +1,160 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define TARGET_VIRTUAL_KEY 0x80000000 + +namespace ZeroGS { + + // manages render targets + class CRenderTargetMngr + { + public: + typedef map MAPTARGETS; + + enum TargetOptions + { + TO_DepthBuffer = 1, + TO_StrictHeight = 2, // height returned has to be the same as requested + TO_Virtual = 4 + }; + + ~CRenderTargetMngr() { Destroy(); } + + void Destroy(); + static MAPTARGETS::iterator GetOldestTarg(MAPTARGETS& m); + + CRenderTarget* GetTarg(const frameInfo& frame, u32 Options, int maxposheight); + inline CRenderTarget* GetTarg(int fbp, int fbw) { + MAPTARGETS::iterator it = mapTargets.find(fbp|(fbw<<16)); + return it != mapTargets.end() ? it->second : NULL; + } + + // gets all targets with a range + void GetTargs(int start, int end, list& listTargets) const; + + // resolves all targets within a range + __forceinline void Resolve(int start, int end); + __forceinline void ResolveAll() { + for(MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it ) + it->second->Resolve(); + } + + void DestroyAllTargs(int start, int end, int fbw); + void DestroyIntersecting(CRenderTarget* prndr); + + // promotes a target from virtual to real + inline CRenderTarget* Promote(u32 key) { + assert( !(key & TARGET_VIRTUAL_KEY) ); + + // promote to regular targ + CRenderTargetMngr::MAPTARGETS::iterator it = mapTargets.find(key|TARGET_VIRTUAL_KEY); + assert( it != mapTargets.end() ); + + CRenderTarget* ptarg = it->second; + mapTargets.erase(it); + + DestroyIntersecting(ptarg); + + it = mapTargets.find(key); + if( it != mapTargets.end() ) { + DestroyTarg(it->second); + it->second = ptarg; + } + else + mapTargets[key] = ptarg; + + if( g_GameSettings & GAME_RESOLVEPROMOTED ) + ptarg->status = CRenderTarget::TS_Resolved; + else + ptarg->status = CRenderTarget::TS_NeedUpdate; + return ptarg; + } + + static void DestroyTarg(CRenderTarget* ptarg); + + MAPTARGETS mapTargets, mapDummyTargs; + }; + + class CMemoryTargetMngr + { + public: + CMemoryTargetMngr() : curstamp(0) {} + CMemoryTarget* GetMemoryTarget(const tex0Info& tex0, int forcevalidate); // pcbp is pointer to start of clut + + void Destroy(); // destroy all targs + + void ClearRange(int starty, int endy); // set all targets to cleared + void DestroyCleared(); // flush all cleared targes + void DestroyOldest(); + + list listTargets, listClearedTargets; + u32 curstamp; + + private: + list::iterator DestroyTargetIter(list::iterator& it); + }; + + class CBitwiseTextureMngr + { + public: + ~CBitwiseTextureMngr() { Destroy(); } + + void Destroy(); + + // since GetTex can delete textures to free up mem, it is dangerous if using that texture, so specify at least one other tex to save + __forceinline u32 GetTex(u32 bitvalue, u32 ptexDoNotDelete) { + map::iterator it = mapTextures.find(bitvalue); + if( it != mapTextures.end() ) + return it->second; + return GetTexInt(bitvalue, ptexDoNotDelete); + } + + private: + u32 GetTexInt(u32 bitvalue, u32 ptexDoNotDelete); + + map mapTextures; + }; + + // manages + class CRangeManager + { + public: + CRangeManager() + { + ranges.reserve(16); + } + + // [start, end) + struct RANGE + { + RANGE() {} + inline RANGE(int start, int end) : start(start), end(end) {} + int start, end; + }; + + // works in semi logN + void Insert(int start, int end); + inline void Clear() { ranges.resize(0); } + + vector ranges; // organized in ascending order, non-intersecting + }; + + extern CRenderTargetMngr s_RTs, s_DepthRTs; + extern CBitwiseTextureMngr s_BitwiseTextures; + extern CMemoryTargetMngr g_MemTargs; +} diff --git a/plugins/gs/zerogs/opengl/x86-32.S b/plugins/gs/zerogs/opengl/x86-32.S new file mode 100644 index 0000000..4449f1a --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86-32.S @@ -0,0 +1,1002 @@ +# Copyright (C) 2005-2006 zerofrog(@gmail.com) +# +# This Program is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either ve%rsion 2, or (at your option) +# any later ve%rsion. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# +.intel_syntax + +## mmx memcpy implementation, size has to be a multiple of 8 +## returns 0 is equal, nonzero value if not equal +## ~10 times faster than standard memcmp +## (zerofrog) +#u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +.globl memcmp_mmx + .type memcmp_mmx, @function +memcmp_mmx: + push %esi + mov %ecx, dword ptr [%esp+16] + mov %edx, dword ptr [%esp+8] + mov %esi, dword ptr [%esp+12] + + cmp %ecx, 32 + jl Done4 + + // custom test first 8 to make sure things are ok + movq %mm0, [%esi] + movq %mm1, [%esi+8] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pand %mm0, %mm1 + movq %mm2, [%esi+16] + pmovmskb %eax, %mm0 + movq %mm3, [%esi+24] + + // check if eq + cmp %eax, 0xff + je NextComp + mov %eax, 1 + jmp End + +NextComp: + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm2, %mm3 + pmovmskb %eax, %mm2 + + sub %ecx, 32 + add %esi, 32 + add %edx, 32 + + // check if eq + cmp %eax, 0xff + je ContinueTest + mov %eax, 1 + jmp End + + cmp %ecx, 64 + jl Done8 + +Cmp8: + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + movq %mm3, [%esi+24] + movq %mm4, [%esi+32] + movq %mm5, [%esi+40] + movq %mm6, [%esi+48] + movq %mm7, [%esi+56] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm0, %mm1 + pcmpeqd %mm4, [%edx+32] + pand %mm0, %mm2 + pcmpeqd %mm5, [%edx+40] + pand %mm0, %mm3 + pcmpeqd %mm6, [%edx+48] + pand %mm0, %mm4 + pcmpeqd %mm7, [%edx+56] + pand %mm0, %mm5 + pand %mm0, %mm6 + pand %mm0, %mm7 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Continue + mov %eax, 1 + jmp End + +Continue: + sub %ecx, 64 + add %esi, 64 + add %edx, 64 +ContinueTest: + cmp %ecx, 64 + jge Cmp8 + +Done8: + test %ecx, 0x20 + jz Done4 + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + movq %mm3, [%esi+24] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pcmpeqd %mm3, [%edx+24] + pand %mm0, %mm1 + pand %mm0, %mm2 + pand %mm0, %mm3 + pmovmskb %eax, %mm0 + sub %ecx, 32 + add %esi, 32 + add %edx, 32 + + // check if eq + cmp %eax, 0xff + je Done4 + mov %eax, 1 + jmp End + +Done4: + cmp %ecx, 24 + jne Done2 + movq %mm0, [%esi] + movq %mm1, [%esi+8] + movq %mm2, [%esi+16] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pcmpeqd %mm2, [%edx+16] + pand %mm0, %mm1 + pand %mm0, %mm2 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + setne %al + jmp End + +Done2: + cmp %ecx, 16 + jne Done1 + + movq %mm0, [%esi] + movq %mm1, [%esi+8] + pcmpeqd %mm0, [%edx] + pcmpeqd %mm1, [%edx+8] + pand %mm0, %mm1 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + setne %al + jmp End + +Done1: + cmp %ecx, 8 + jne Done + + mov %eax, [%esi] + mov %esi, [%esi+4] + cmp %eax, [%edx] + je Next + mov %eax, 1 + jmp End + +Next: + cmp %esi, [%edx+4] + setne %al + jmp End + +Done: + xor %eax, %eax + +End: + pop %esi + emms + ret + + +#ifdef ZEROGS_SSE2 +// SSE2 extensions +#define punpck(op, sd0, sd2, s1, s3, d1, d3) \ + movdqa %xmm##d1, %xmm##sd0; \ + pshufd %xmm##d3, %xmm##sd2, 0xe4; \ + punpckl##op %xmm##sd0, %xmm##s1; \ + punpckh##op %xmm##d1, %xmm##s1; \ + punpckl##op %xmm##sd2, %xmm##s3; \ + punpckh##op %xmm##d3, %xmm##s3; \ + + +#define punpcknb \ + movdqa %xmm4, %xmm0; \ + pshufd %xmm5, %xmm1, 0xe4; \ + \ + psllq %xmm1, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm0, %xmm7; \ + pandn %xmm6, %xmm1; \ + por %xmm0, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm1, %xmm4; \ + \ + movdqa %xmm4, %xmm2; \ + pshufd %xmm5, %xmm3, 0xe4; \ + \ + psllq %xmm3, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm2, %xmm7; \ + pandn %xmm6, %xmm3; \ + por %xmm2, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm3, %xmm4; \ + \ + punpck(bw, 0, 2, 1, 3, 4, 6); \ + + +// +// swizzling +// + +// +// SwizzleBlock32 +// + +.globl SwizzleBlock32_sse2 + .type SwizzleBlock32_sse2, @function +SwizzleBlock32_sse2: + + push %esi + push %edi + + mov %edi, %ecx + mov %esi, %edx + mov %edx, [%esp+4+8] + mov %ecx, 4 + + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32_sse2_2 + + .align 16 +SwizzleBlock32_sse2_1: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32_sse2_2: + + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32_sse2_3: + movdqa %xmm0, [%esi] + movdqa %xmm4, [%esi+16] + movdqa %xmm1, [%esi+%edx] + movdqa %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movntps [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movntps [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movntps [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16 +// + +.globl SwizzleBlock16_sse2 + .type SwizzleBlock16_sse2, @function +SwizzleBlock16_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16_sse2_1: + movdqa %xmm0, [%edx] + movdqa %xmm1, [%edx+16] + movdqa %xmm2, [%edx+%ebx] + movdqa %xmm3, [%edx+%ebx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8 +// + +.globl SwizzleBlock8_sse2 + .type SwizzleBlock8_sse2, @function +SwizzleBlock8_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock8_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshufd %xmm1, [%edx], 0xb1 + pshufd %xmm3, [%edx+%ebx], 0xb1 + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 + + pshufd %xmm0, [%edx], 0xb1 + pshufd %xmm2, [%edx+%ebx], 0xb1 + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4 +// + +.globl SwizzleBlock4_sse2 + .type SwizzleBlock4_sse2, @function +SwizzleBlock4_sse2: + + push %ebx + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 + + movdqa %xmm0, [%edx] + movdqa %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqa %xmm1, [%edx] + movdqa %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4_sse2_1 + + pop %ebx + + ret 4 + +// +// swizzling with unaligned reads +// + +// +// SwizzleBlock32u +// + +.globl SwizzleBlock32u_sse2 + .type SwizzleBlock32u_sse2, @function +SwizzleBlock32u_sse2: + + push %esi + push %edi + + mov %edi, %ecx + mov %esi, %edx + mov %edx, [%esp+4+8] + mov %ecx, 4 + + mov %eax, [%esp+8+8] + cmp %eax, 0xffffffff + jne SwizzleBlock32u_sse2_2 + + .align 16 +SwizzleBlock32u_sse2_1: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movntps [%edi+16*0], %xmm0 + movntps [%edi+16*1], %xmm2 + movntps [%edi+16*2], %xmm4 + movntps [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_1 + + pop %edi + pop %esi + + ret 8 + +SwizzleBlock32u_sse2_2: + + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32u_sse2_3: + movdqu %xmm0, [%esi] + movdqu %xmm4, [%esi+16] + movdqu %xmm1, [%esi+%edx] + movdqu %xmm5, [%esi+%edx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%edi+16*0], %xmm0 + + pandn %xmm5, [%edi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%edi+16*1], %xmm2 + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + + pandn %xmm3, [%edi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm3 + movdqa [%edi+16*2], %xmm4 + + pandn %xmm5, [%edi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm5 + movdqa [%edi+16*3], %xmm6 + + lea %esi, [%esi+%edx*2] + add %edi, 64 + + dec %ecx + jnz SwizzleBlock32u_sse2_3 + + pop %edi + pop %esi + + ret 8 + +// +// SwizzleBlock16u +// + +.globl SwizzleBlock16u_sse2 + .type SwizzleBlock16u_sse2, @function +SwizzleBlock16u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 4 + + .align 16 +SwizzleBlock16u_sse2_1: + movdqu %xmm0, [%edx] + movdqu %xmm1, [%edx+16] + movdqu %xmm2, [%edx+%ebx] + movdqu %xmm3, [%edx+%ebx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm5 + + lea %edx, [%edx+%ebx*2] + add %ecx, 64 + + dec %eax + jnz SwizzleBlock16u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock8u +// + +.globl SwizzleBlock8u_sse2 + .type SwizzleBlock8u_sse2, @function +SwizzleBlock8u_sse2: + + push %ebx + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock8u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + pshufd %xmm1, %xmm1, 0xb1 + pshufd %xmm3, %xmm3, 0xb1 + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm4 + movntps [%ecx+16*2], %xmm1 + movntps [%ecx+16*3], %xmm5 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + pshufd %xmm0, %xmm0, 0xb1 + pshufd %xmm2, %xmm2, 0xb1 + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm4 + movntps [%ecx+16*6], %xmm1 + movntps [%ecx+16*7], %xmm5 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock8u_sse2_1 + + pop %ebx + + ret 4 + +// +// SwizzleBlock4u +// + +.globl SwizzleBlock4u_sse2 + .type SwizzleBlock4u_sse2, @function +SwizzleBlock4u_sse2: + + push %ebx + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + mov %ebx, [%esp+4+4] + mov %eax, 2 + + .align 16 +SwizzleBlock4u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*0], %xmm0 + movntps [%ecx+16*1], %xmm1 + movntps [%ecx+16*2], %xmm4 + movntps [%ecx+16*3], %xmm3 + + // col 1, 3 + + movdqu %xmm0, [%edx] + movdqu %xmm2, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + movdqu %xmm1, [%edx] + movdqu %xmm3, [%edx+%ebx] + lea %edx, [%edx+%ebx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknb + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movntps [%ecx+16*4], %xmm0 + movntps [%ecx+16*5], %xmm1 + movntps [%ecx+16*6], %xmm4 + movntps [%ecx+16*7], %xmm3 + + add %ecx, 128 + + dec %eax + jnz SwizzleBlock4u_sse2_1 + + pop %ebx + + ret 4 + + +s_clut16mask: + .align 16 + .long 0xffff1000 + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + +s_clut16mask2: + .align 16 + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + +.globl WriteCLUT_T16_I4_CSM1_sse2 + .type WriteCLUT_T16_I4_CSM1_sse2, @function +WriteCLUT_T16_I4_CSM1_sse2: + movdqa %xmm0, qword ptr [%edx] + movdqa %xmm1, qword ptr [%edx+16] + movdqa %xmm2, qword ptr [%edx+32] + movdqa %xmm3, qword ptr [%edx+48] + + // rearrange + pshuflw %xmm0, %xmm0, 0x88 + pshufhw %xmm0, %xmm0, 0x88 + pshuflw %xmm1, %xmm1, 0x88 + pshufhw %xmm1, %xmm1, 0x88 + pshuflw %xmm2, %xmm2, 0x88 + pshufhw %xmm2, %xmm2, 0x88 + pshuflw %xmm3, %xmm3, 0x88 + pshufhw %xmm3, %xmm3, 0x88 + + shufps %xmm0, %xmm1, 0x88 + shufps %xmm2, %xmm3, 0x88 + + pshufd %xmm0, %xmm0, 0xd8 + pshufd %xmm2, %xmm2, 0xd8 + + pxor %xmm6, %xmm6 + + test %ecx, 15 + jnz WriteUnaligned + + movdqa %xmm7, [s_clut16mask] // saves upper 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%ecx] + movdqa %xmm5, [%ecx+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + + movdqa [%ecx], %xmm0 + movdqa [%ecx+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%ecx+16] + pand %xmm5, [%ecx+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%ecx+16], %xmm2 + movdqa [%ecx+48], %xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + // %ecx is offset by 2 + sub %ecx, 2 + + movdqa %xmm7, [s_clut16mask2] // saves lower 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%ecx] + movdqa %xmm5, [%ecx+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + pslld %xmm0, 16 + pslld %xmm1, 16 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + pslld %xmm2, 16 + pslld %xmm3, 16 + + movdqa [%ecx], %xmm0 + movdqa [%ecx+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%ecx+16] + pand %xmm5, [%ecx+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%ecx+16], %xmm2 + movdqa [%ecx+48], %xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + + +.globl WriteCLUT_T32_I8_CSM1_sse2 + .type WriteCLUT_T32_I8_CSM1_sse2, @function +WriteCLUT_T32_I8_CSM1_sse2: + push %ebx + xor %ebx, %ebx +.L231: + xor %eax, %eax + .align 16 +.L232: + movdqa %xmm3, XMMWORD PTR [%eax+16+%ecx] + movdqa %xmm4, XMMWORD PTR [%eax+48+%ecx] + movdqa %xmm1, XMMWORD PTR [%eax+%ecx] + movdqa %xmm2, XMMWORD PTR [%eax+32+%ecx] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+32+%eax*2], %xmm1 + movdqa XMMWORD PTR [%edx+%eax*2], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+48+%eax*2], %xmm2 + movdqa XMMWORD PTR [%edx+16+%eax*2], %xmm0 + movdqa %xmm1, XMMWORD PTR [%eax+256+%ecx] + movdqa %xmm3, XMMWORD PTR [%eax+272+%ecx] + movdqa %xmm2, XMMWORD PTR [%eax+288+%ecx] + movdqa %xmm4, XMMWORD PTR [%eax+304+%ecx] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+96+%eax*2], %xmm1 + movdqa XMMWORD PTR [%edx+64+%eax*2], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+112+%eax*2], %xmm2 + movdqa XMMWORD PTR [%edx+80+%eax*2], %xmm0 + add %eax, 64 + cmp %eax, 256 + jne .L232 + add %edx, 512 + add %ecx, 512 + add %ebx, 512 + cmp %ebx, 1024 + jne .L231 + pop %ebx + ret + +.globl WriteCLUT_T32_I4_CSM1_sse2 + .type WriteCLUT_T32_I4_CSM1_sse2, @function +WriteCLUT_T32_I4_CSM1_sse2: + movdqa %xmm1, XMMWORD PTR [%ecx] + movdqa %xmm3, XMMWORD PTR [%ecx+16] + movdqa %xmm2, XMMWORD PTR [%ecx+32] + movdqa %xmm4, XMMWORD PTR [%ecx+48] + movdqa %xmm0, %xmm1 + punpckhqdq %xmm1, %xmm3 + punpcklqdq %xmm0, %xmm3 + movdqa XMMWORD PTR [%edx+32], %xmm1 + movdqa XMMWORD PTR [%edx], %xmm0 + movdqa %xmm0, %xmm2 + punpckhqdq %xmm2, %xmm4 + punpcklqdq %xmm0, %xmm4 + movdqa XMMWORD PTR [%edx+48], %xmm2 + movdqa XMMWORD PTR [%edx+16], %xmm0 + ret + +#endif diff --git a/plugins/gs/zerogs/opengl/x86-32.asm b/plugins/gs/zerogs/opengl/x86-32.asm new file mode 100644 index 0000000..1507d21 --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86-32.asm @@ -0,0 +1,652 @@ +; Copyright (C) 2003-2005 Gabest +; http://www.gabest.org +; +; This Program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. +; +; This Program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GNU Make; see the file COPYING. If not, write to +; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +; http://www.gnu.org/copyleft/gpl.html +; +; + .686 + .model flat + .mmx + .xmm + + .const + + __uvmin DD 0d01502f9r ; -1e+010 + __uvmax DD 0501502f9r ; +1e+010 + + .code + +; +; swizzling +; + +punpck macro op, sd0, sd2, s1, s3, d1, d3 + + movdqa @CatStr(xmm, %d1), @CatStr(xmm, %sd0) + pshufd @CatStr(xmm, %d3), @CatStr(xmm, %sd2), 0e4h + + @CatStr(punpckl, op) @CatStr(xmm, %sd0), @CatStr(xmm, %s1) + @CatStr(punpckh, op) @CatStr(xmm, %d1), @CatStr(xmm, %s1) + @CatStr(punpckl, op) @CatStr(xmm, %sd2), @CatStr(xmm, %s3) + @CatStr(punpckh, op) @CatStr(xmm, %d3), @CatStr(xmm, %s3) + + endm + +punpcknb macro + + movdqa xmm4, xmm0 + pshufd xmm5, xmm1, 0e4h + + psllq xmm1, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm0, xmm7 + pandn xmm6, xmm1 + por xmm0, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm1, xmm4 + + movdqa xmm4, xmm2 + pshufd xmm5, xmm3, 0e4h + + psllq xmm3, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm2, xmm7 + pandn xmm6, xmm3 + por xmm2, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm3, xmm4 + + punpck bw, 0, 2, 1, 3, 4, 6 + + endm + + +; +; swizzling +; + +; +; SwizzleBlock32 +; + +@SwizzleBlock32_sse2@16 proc public + + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32_sse2@WM + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqa xmm0, [esi] + movdqa xmm4, [esi+16] + movdqa xmm1, [esi+edx] + movdqa xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movntps [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movntps [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movntps [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32_sse2@16 endp + +; +; SwizzleBlock16 +; + +@SwizzleBlock16_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqa xmm0, [edx] + movdqa xmm1, [edx+16] + movdqa xmm2, [edx+ebx] + movdqa xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16_sse2@12 endp + +; +; SwizzleBlock8 +; + +@SwizzleBlock8_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + pshufd xmm1, [edx], 0b1h + pshufd xmm3, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [edx], 0b1h + pshufd xmm2, [edx+ebx], 0b1h + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8_sse2@12 endp + +; +; SwizzleBlock4 +; + +@SwizzleBlock4_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqa xmm0, [edx] + movdqa xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqa xmm1, [edx] + movdqa xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4_sse2@12 endp + +; +; swizzling with unaligned reads +; + +; +; SwizzleBlock32u +; + +@SwizzleBlock32u_sse2@16 proc public + + push esi + push edi + + mov edi, ecx + mov esi, edx + mov edx, [esp+4+8] + mov ecx, 4 + + mov eax, [esp+8+8] + cmp eax, 0ffffffffh + jne SwizzleBlock32u_sse2@WM + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movntps [edi+16*0], xmm0 + movntps [edi+16*1], xmm2 + movntps [edi+16*2], xmm4 + movntps [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +SwizzleBlock32u_sse2@WM: + + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqu xmm0, [esi] + movdqu xmm4, [esi+16] + movdqu xmm1, [esi+edx] + movdqu xmm5, [esi+edx+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [edi+16*0], xmm0 + + pandn xmm5, [edi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [edi+16*1], xmm2 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + + pandn xmm3, [edi+16*2] + pand xmm4, xmm7 + por xmm4, xmm3 + movdqa [edi+16*2], xmm4 + + pandn xmm5, [edi+16*3] + pand xmm6, xmm7 + por xmm6, xmm5 + movdqa [edi+16*3], xmm6 + + lea esi, [esi+edx*2] + add edi, 64 + + dec ecx + jnz @B + + pop edi + pop esi + + ret 8 + +@SwizzleBlock32u_sse2@16 endp + +; +; SwizzleBlock16u +; + +@SwizzleBlock16u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 4 + + align 16 +@@: + movdqu xmm0, [edx] + movdqu xmm1, [edx+16] + movdqu xmm2, [edx+ebx] + movdqu xmm3, [edx+ebx+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm5 + + lea edx, [edx+ebx*2] + add ecx, 64 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock16u_sse2@12 endp + +; +; SwizzleBlock8u +; + +@SwizzleBlock8u_sse2@12 proc public + + push ebx + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + pshufd xmm1, xmm1, 0b1h + pshufd xmm3, xmm3, 0b1h + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm4 + movntps [ecx+16*2], xmm1 + movntps [ecx+16*3], xmm5 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + pshufd xmm0, xmm0, 0b1h + pshufd xmm2, xmm2, 0b1h + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm4 + movntps [ecx+16*6], xmm1 + movntps [ecx+16*7], xmm5 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock8u_sse2@12 endp + +; +; SwizzleBlock4u +; + +@SwizzleBlock4u_sse2@12 proc public + + push ebx + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + mov ebx, [esp+4+4] + mov eax, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*0], xmm0 + movntps [ecx+16*1], xmm1 + movntps [ecx+16*2], xmm4 + movntps [ecx+16*3], xmm3 + + ; col 1, 3 + + movdqu xmm0, [edx] + movdqu xmm2, [edx+ebx] + lea edx, [edx+ebx*2] + + movdqu xmm1, [edx] + movdqu xmm3, [edx+ebx] + lea edx, [edx+ebx*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknb + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movntps [ecx+16*4], xmm0 + movntps [ecx+16*5], xmm1 + movntps [ecx+16*6], xmm4 + movntps [ecx+16*7], xmm3 + + add ecx, 128 + + dec eax + jnz @B + + pop ebx + + ret 4 + +@SwizzleBlock4u_sse2@12 endp + + end \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/x86-64.S b/plugins/gs/zerogs/opengl/x86-64.S new file mode 100644 index 0000000..d834073 --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86-64.S @@ -0,0 +1,903 @@ +## Copyright (C) 2005-2006 zerofrog(@gmail.com) +# +# This Program is free software you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation either ve%rsion 2, or (at your option) +# any later ve%rsion. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Make see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +# http://www.gnu.org/copyleft/gpl.html +# +# +.intel_syntax + +## mmx memcpy implementation, size has to be a multiple of 8 +## returns 0 is equal, nonzero value if not equal +## ~10 times faster than standard memcmp +## (zerofrog) +## u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +## %rdi - src1 +## %rsi - src2 +## edx - cmpsize +.globl memcmp_mmx + .type memcmp_mmx, @function +memcmp_mmx: + cmp %edx, 32 + jl Done4 + + ## custom test first 8 to make sure things are ok + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pand %mm0, %mm1 + movq %mm2, [%rsi+16] + pmovmskb %eax, %mm0 + movq %mm3, [%rsi+24] + + // check if eq + cmp %eax, 0xff + je NextComp + mov %eax, 1 + jmp End + +NextComp: + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm2, %mm3 + pmovmskb %eax, %mm2 + + sub %edx, 32 + add %rsi, 32 + add %rdi, 32 + + // check if eq + cmp %eax, 0xff + je ContinueTest + mov %eax, 1 + jmp End + + cmp %edx, 64 + jl Done8 + +Cmp8: + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + movq %mm3, [%rsi+24] + movq %mm4, [%rsi+32] + movq %mm5, [%rsi+40] + movq %mm6, [%rsi+48] + movq %mm7, [%rsi+56] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm0, %mm1 + pcmpeqd %mm4, [%rdi+32] + pand %mm0, %mm2 + pcmpeqd %mm5, [%rdi+40] + pand %mm0, %mm3 + pcmpeqd %mm6, [%rdi+48] + pand %mm0, %mm4 + pcmpeqd %mm7, [%rdi+56] + pand %mm0, %mm5 + pand %mm0, %mm6 + pand %mm0, %mm7 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Continue + mov %eax, 1 + jmp End + +Continue: + sub %edx, 64 + add %rsi, 64 + add %rdi, 64 +ContinueTest: + cmp %edx, 64 + jge Cmp8 + +Done8: + test %edx, 0x20 + jz Done4 + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + movq %mm3, [%rsi+24] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pcmpeqd %mm3, [%rdi+24] + pand %mm0, %mm1 + pand %mm0, %mm2 + pand %mm0, %mm3 + pmovmskb %eax, %mm0 + sub %edx, 32 + add %rsi, 32 + add %rdi, 32 + + // check if eq + cmp %eax, 0xff + je Done4 + mov %eax, 1 + jmp End + +Done4: + cmp %edx, 24 + jne Done2 + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + movq %mm2, [%rsi+16] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pcmpeqd %mm2, [%rdi+16] + pand %mm0, %mm1 + pand %mm0, %mm2 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Done + mov %eax, 1 + jmp End + +Done2: + cmp %edx, 16 + jne Done1 + + movq %mm0, [%rsi] + movq %mm1, [%rsi+8] + pcmpeqd %mm0, [%rdi] + pcmpeqd %mm1, [%rdi+8] + pand %mm0, %mm1 + pmovmskb %eax, %mm0 + + // check if eq + cmp %eax, 0xff + je Done + mov %eax, 1 + jmp End + +Done1: + cmp %edx, 8 + jne Done + + mov %eax, [%rsi] + mov %rsi, [%rsi+4] + cmp %eax, [%rdi] + je Next + mov %eax, 1 + jmp End + +Next: + cmp %rsi, [%rdi+4] + je Done + mov %eax, 1 + jmp End + +Done: + xor %eax, %eax + +End: + emms + ret + +#ifdef ZEROGS_SSE2 +// SSE2 extensions + +#define punpck(op, sd0, sd2, s1, s3, d1, d3) \ + movdqa %xmm##d1, %xmm##sd0; \ + pshufd %xmm##d3, %xmm##sd2, 0xe4; \ + punpckl##op %xmm##sd0, %xmm##s1; \ + punpckh##op %xmm##d1, %xmm##s1; \ + punpckl##op %xmm##sd2, %xmm##s3; \ + punpckh##op %xmm##d3, %xmm##s3; \ + +#define punpcknbl \ + movdqa %xmm4, %xmm0; \ + pshufd %xmm5, %xmm1, 0xe4; \ + \ + psllq %xmm1, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm0, %xmm7; \ + pandn %xmm6, %xmm1; \ + por %xmm0, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm1, %xmm4; \ + \ + movdqa %xmm4, %xmm2; \ + pshufd %xmm5, %xmm3, 0xe4; \ + \ + psllq %xmm3, 4; \ + psrlq %xmm4, 4; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm2, %xmm7; \ + pandn %xmm6, %xmm3; \ + por %xmm2, %xmm6; \ + \ + movdqa %xmm6, %xmm7; \ + pand %xmm4, %xmm7; \ + pandn %xmm6, %xmm5; \ + por %xmm4, %xmm6; \ + \ + movdqa %xmm3, %xmm4; \ + \ + punpck(bw, 0, 2, 1, 3, 4, 6); \ + +#define punpcknbh \ + movdqa %xmm12, %xmm8; \ + pshufd %xmm13, %xmm9, 0xe4; \ + \ + psllq %xmm9, 4; \ + psrlq %xmm12, 4; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm8, %xmm15; \ + pandn %xmm14, %xmm9; \ + por %xmm8, %xmm14; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm12, %xmm15; \ + pandn %xmm14, %xmm13; \ + por %xmm12, %xmm14; \ + \ + movdqa %xmm9, %xmm12; \ + \ + movdqa %xmm12, %xmm10; \ + pshufd %xmm13, %xmm11, 0xe4; \ + \ + psllq %xmm11, 4; \ + psrlq %xmm12, 4; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm10, %xmm15; \ + pandn %xmm14, %xmm11; \ + por %xmm10, %xmm14; \ + \ + movdqa %xmm14, %xmm15; \ + pand %xmm12, %xmm15; \ + pandn %xmm14, %xmm13; \ + por %xmm12, %xmm14; \ + \ + movdqa %xmm11, %xmm12; \ + \ + punpck(bw, 8, 10, 9, 11, 12, 14); \ + +// +// SwizzleBlock32_sse2 +// + +.globl SwizzleBlock32_sse2 + .type SwizzleBlock32_sse2, @function +SwizzleBlock32_sse2: + + mov %eax, 4 + + cmp %ecx, 0xffffffff + jne SwizzleBlock32_sse2_2 + + .align 16 +SwizzleBlock32_sse2_1: + movdqa %xmm0, [%rsi] + movdqa %xmm4, [%rsi+16] + movdqa %xmm1, [%rsi+%rdx] + movdqa %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm2 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32_sse2_1 + + ret + +SwizzleBlock32_sse2_2: + + movd %xmm7, %rcx + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32_sse2_3: + movdqa %xmm0, [%rsi] + movdqa %xmm4, [%rsi+16] + movdqa %xmm1, [%rsi+%rdx] + movdqa %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + movdqa %xmm9, %xmm7 + pshufd %xmm11, %xmm7, 0xe4 + + pandn %xmm3, [%rdi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%rdi+16*0], %xmm0 + + pandn %xmm5, [%rdi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%rdi+16*1], %xmm2 + + pandn %xmm9, [%rdi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm9 + movdqa [%rdi+16*2], %xmm4 + + pandn %xmm11, [%rdi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm11 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32_sse2_3 + + ret + +// +// SwizzleBlock16_sse2 +// + +.globl SwizzleBlock16_sse2 + .type SwizzleBlock16_sse2, @function +SwizzleBlock16_sse2: + + mov %eax, 4 + + .align 16 +SwizzleBlock16_sse2_1: + movdqa %xmm0, [%rsi] + movdqa %xmm1, [%rsi+16] + movdqa %xmm2, [%rsi+%rdx] + movdqa %xmm3, [%rsi+%rdx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm5 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock16_sse2_1 + + ret + +// +// SwizzleBlock8 +// + +.globl SwizzleBlock8_sse2 + .type SwizzleBlock8_sse2, @function +SwizzleBlock8_sse2: + + mov %ecx, 2 + + .align 16 +SwizzleBlock8_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshufd %xmm1, [%rsi], 0xb1 + pshufd %xmm3, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm4 + movdqa [%rdi+16*2], %xmm1 + movdqa [%rdi+16*3], %xmm5 + + // col 1, 3 + + pshufd %xmm0, [%rsi], 0xb1 + pshufd %xmm2, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm4 + movdqa [%rdi+16*6], %xmm1 + movdqa [%rdi+16*7], %xmm5 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock8_sse2_1 + + ret + +// +// SwizzleBlock4 +// + +.globl SwizzleBlock4_sse2 + .type SwizzleBlock4_sse2, @function +SwizzleBlock4_sse2: + + mov %ecx, 2 + + mov %eax, 0x0f0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock4_sse2_1: + // col 0, 2 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm3 + + // col 1, 3 + + movdqa %xmm0, [%rsi] + movdqa %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqa %xmm1, [%rsi] + movdqa %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm1 + movdqa [%rdi+16*6], %xmm4 + movdqa [%rdi+16*7], %xmm3 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock4_sse2_1 + + ret + +// +// swizzling with unaligned reads +// + +// +// SwizzleBlock32u_sse2 +// + +.globl SwizzleBlock32u_sse2 + .type SwizzleBlock32u_sse2, @function +SwizzleBlock32u_sse2: + + mov %eax, 4 + + cmp %ecx, 0xffffffff + jne SwizzleBlock32u_sse2_2 + + .align 16 +SwizzleBlock32u_sse2_1: + movdqu %xmm0, [%rsi] + movdqu %xmm4, [%rsi+16] + movdqu %xmm1, [%rsi+%rdx] + movdqu %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm2 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32u_sse2_1 + + ret + +SwizzleBlock32u_sse2_2: + + movd %xmm7, %rcx + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock32u_sse2_3: + movdqu %xmm0, [%rsi] + movdqu %xmm4, [%rsi+16] + movdqu %xmm1, [%rsi+%rdx] + movdqu %xmm5, [%rsi+%rdx+16] + + punpck(qdq, 0, 4, 1, 5, 2, 6) + + movdqa %xmm3, %xmm7 + pshufd %xmm5, %xmm7, 0xe4 + movdqa %xmm9, %xmm7 + pshufd %xmm11, %xmm7, 0xe4 + + pandn %xmm3, [%rdi+16*0] + pand %xmm0, %xmm7 + por %xmm0, %xmm3 + movdqa [%rdi+16*0], %xmm0 + + pandn %xmm5, [%rdi+16*1] + pand %xmm2, %xmm7 + por %xmm2, %xmm5 + movdqa [%rdi+16*1], %xmm2 + + pandn %xmm9, [%rdi+16*2] + pand %xmm4, %xmm7 + por %xmm4, %xmm9 + movdqa [%rdi+16*2], %xmm4 + + pandn %xmm11, [%rdi+16*3] + pand %xmm6, %xmm7 + por %xmm6, %xmm11 + movdqa [%rdi+16*3], %xmm6 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock32u_sse2_3 + + ret + +// +// SwizzleBlock16u_sse2 +// + +.globl SwizzleBlock16u_sse2 + .type SwizzleBlock16u_sse2, @function +SwizzleBlock16u_sse2: + mov %eax, 4 + + .align 16 +SwizzleBlock16u_sse2_1: + movdqu %xmm0, [%rsi] + movdqu %xmm1, [%rsi+16] + movdqu %xmm2, [%rsi+%rdx] + movdqu %xmm3, [%rsi+%rdx+16] + + punpck(wd, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm5 + + lea %rsi, [%rsi+%rdx*2] + add %rdi, 64 + + dec %eax + jnz SwizzleBlock16u_sse2_1 + + ret + +// +// SwizzleBlock8u +// + +.globl SwizzleBlock8u_sse2 + .type SwizzleBlock8u_sse2, @function +SwizzleBlock8u_sse2: + mov %ecx, 2 + + .align 16 +SwizzleBlock8u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshufd %xmm1, [%rsi], 0xb1 + pshufd %xmm3, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm4 + movdqa [%rdi+16*2], %xmm1 + movdqa [%rdi+16*3], %xmm5 + + // col 1, 3 + + pshufd %xmm0, [%rsi], 0xb1 + pshufd %xmm2, [%rsi+%rdx], 0xb1 + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(wd, 0, 2, 4, 6, 1, 3) + punpck(qdq, 0, 1, 2, 3, 4, 5) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm4 + movdqa [%rdi+16*6], %xmm1 + movdqa [%rdi+16*7], %xmm5 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock8u_sse2_1 + + ret + +// +// SwizzleBlock4u +// + +.globl SwizzleBlock4u_sse2 + .type SwizzleBlock4u_sse2, @function +SwizzleBlock4u_sse2: + + mov %ecx, 2 + + mov %eax, 0xf0f0f0f + movd %xmm7, %eax + pshufd %xmm7, %xmm7, 0 + + .align 16 +SwizzleBlock4u_sse2_1: + // col 0, 2 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm1, %xmm1, 0xb1 + pshuflw %xmm3, %xmm3, 0xb1 + pshufhw %xmm1, %xmm1, 0xb1 + pshufhw %xmm3, %xmm3, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*0], %xmm0 + movdqa [%rdi+16*1], %xmm1 + movdqa [%rdi+16*2], %xmm4 + movdqa [%rdi+16*3], %xmm3 + + // col 1, 3 + + movdqu %xmm0, [%rsi] + movdqu %xmm2, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + movdqu %xmm1, [%rsi] + movdqu %xmm3, [%rsi+%rdx] + lea %rsi, [%rsi+%rdx*2] + + pshuflw %xmm0, %xmm0, 0xb1 + pshuflw %xmm2, %xmm2, 0xb1 + pshufhw %xmm0, %xmm0, 0xb1 + pshufhw %xmm2, %xmm2, 0xb1 + + punpcknbl + punpck(bw, 0, 2, 4, 6, 1, 3) + punpck(bw, 0, 2, 1, 3, 4, 6) + punpck(qdq, 0, 4, 2, 6, 1, 3) + + movdqa [%rdi+16*4], %xmm0 + movdqa [%rdi+16*5], %xmm1 + movdqa [%rdi+16*6], %xmm4 + movdqa [%rdi+16*7], %xmm3 + + add %rdi, 128 + + dec %ecx + jnz SwizzleBlock4u_sse2_1 + + ret + + +s_clut16mask: + .align 16 + .long 0xffff1000 + .long 0xffff0000 + .long 0xffff0000 + .long 0xffff0000 + +s_clut16mask2: + .align 16 + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + .long 0x0000ffff + +.globl WriteCLUT_T16_I4_CSM1_sse2 + .type WriteCLUT_T16_I4_CSM1_sse2, @function +WriteCLUT_T16_I4_CSM1_sse2: + movdqa %xmm0, qword ptr [%rdi] + movdqa %xmm1, qword ptr [%rdi+16] + movdqa %xmm2, qword ptr [%rdi+32] + movdqa %xmm3, qword ptr [%rdi+48] + + // rearrange + pshuflw %xmm0, %xmm0, 0x88 + pshufhw %xmm0, %xmm0, 0x88 + pshuflw %xmm1, %xmm1, 0x88 + pshufhw %xmm1, %xmm1, 0x88 + pshuflw %xmm2, %xmm2, 0x88 + pshufhw %xmm2, %xmm2, 0x88 + pshuflw %xmm3, %xmm3, 0x88 + pshufhw %xmm3, %xmm3, 0x88 + + shufps %xmm0, %xmm1, 0x88 + shufps %xmm2, %xmm3, 0x88 + + pshufd %xmm0, %xmm0, 0xd8 + pshufd %xmm2, %xmm2, 0xd8 + + pxor %xmm6, %xmm6 + + test %rsi, 15 + jnz WriteUnaligned + + movdqa %xmm7, [%rip+s_clut16mask] // saves upper 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%rsi] + movdqa %xmm5, [%rsi+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + + movdqa [%rsi], %xmm0 + movdqa [%rsi+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%rsi+16] + pand %xmm5, [%rsi+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%rsi+16], %xmm2 + movdqa [%rsi+48], %xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + // %rsi is offset by 2 + sub %rsi, 2 + + movdqa %xmm7, [%rip+s_clut16mask2] // saves lower 16 bits + + // have to save interlaced with the old data + movdqa %xmm4, [%rsi] + movdqa %xmm5, [%rsi+32] + movhlps %xmm1, %xmm0 + movlhps %xmm0, %xmm2 // lower 8 colors + + pand %xmm4, %xmm7 + pand %xmm5, %xmm7 + + shufps %xmm1, %xmm2, 0xe4 // upper 8 colors + movdqa %xmm2, %xmm0 + movdqa %xmm3, %xmm1 + + punpcklwd %xmm0, %xmm6 + punpcklwd %xmm1, %xmm6 + pslld %xmm0, 16 + pslld %xmm1, 16 + por %xmm0, %xmm4 + por %xmm1, %xmm5 + + punpckhwd %xmm2, %xmm6 + punpckhwd %xmm3, %xmm6 + pslld %xmm2, 16 + pslld %xmm3, 16 + + movdqa [%rsi], %xmm0 + movdqa [%rsi+32], %xmm1 + + movdqa %xmm5, %xmm7 + pand %xmm7, [%rsi+16] + pand %xmm5, [%rsi+48] + + por %xmm2, %xmm7 + por %xmm3, %xmm5 + + movdqa [%rsi+16], %xmm2 + movdqa [%rsi+48], %xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + +#endif diff --git a/plugins/gs/zerogs/opengl/x86-64.asm b/plugins/gs/zerogs/opengl/x86-64.asm new file mode 100644 index 0000000..5f637b2 --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86-64.asm @@ -0,0 +1,1094 @@ +; Copyright (C) 2003-2005 Gabest/zerofrog +; http:;;www.gabest.org +; +; This Program is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 2, or (at your option) +; any later version. +; +; This Program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GNU Make; see the file COPYING. If not, write to +; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +; http:;;www.gnu.org/copyleft/gpl.html +; +; + + .const + + __uvmin DD 0d01502f9r ; -1e+010 + __uvmax DD 0501502f9r ; +1e+010 + +extern s_clut16mask:ptr + + .code + +; mmx memcpy implementation, size has to be a multiple of 8 +; returns 0 is equal, nonzero value if not equal +; ~10 times faster than standard memcmp +; (zerofrog) +; u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize) +; rcx - src1 +; rdx - src2 +; r8d - cmpsize +memcmp_mmx proc public + cmp r8d, 32 + jl Done4 + + ; custom test first 8 to make sure things are ok + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + movq mm2, [rdx+16] + pmovmskb eax, mm0 + movq mm3, [rdx+24] + + ; check if eq + cmp eax, 0ffh + je NextComp + mov eax, 1 + jmp Finish + +NextComp: + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm2, mm3 + pmovmskb eax, mm2 + + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ; check if eq + cmp eax, 0ffh + je ContinueTest + mov eax, 1 + jmp Finish + + cmp r8d, 64 + jl Done8 + +Cmp8: + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + movq mm4, [rdx+32] + movq mm5, [rdx+40] + movq mm6, [rdx+48] + movq mm7, [rdx+56] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pcmpeqd mm4, [rcx+32] + pand mm0, mm2 + pcmpeqd mm5, [rcx+40] + pand mm0, mm3 + pcmpeqd mm6, [rcx+48] + pand mm0, mm4 + pcmpeqd mm7, [rcx+56] + pand mm0, mm5 + pand mm0, mm6 + pand mm0, mm7 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Continue + mov eax, 1 + jmp Finish + +Continue: + sub r8d, 64 + add rdx, 64 + add rcx, 64 +ContinueTest: + cmp r8d, 64 + jge Cmp8 + +Done8: + test r8d, 020h + jz Done4 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + movq mm3, [rdx+24] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pcmpeqd mm3, [rcx+24] + pand mm0, mm1 + pand mm0, mm2 + pand mm0, mm3 + pmovmskb eax, mm0 + sub r8d, 32 + add rdx, 32 + add rcx, 32 + + ; check if eq + cmp eax, 0ffh + je Done4 + mov eax, 1 + jmp Finish + +Done4: + cmp r8d, 24 + jne Done2 + movq mm0, [rdx] + movq mm1, [rdx+8] + movq mm2, [rdx+16] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pcmpeqd mm2, [rcx+16] + pand mm0, mm1 + pand mm0, mm2 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Done + mov eax, 1 + jmp Finish + +Done2: + cmp r8d, 16 + jne Done1 + + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+8] + pand mm0, mm1 + pmovmskb eax, mm0 + + ; check if eq + cmp eax, 0ffh + je Done + mov eax, 1 + jmp Finish + +Done1: + cmp r8d, 8 + jne Done + + mov eax, [rdx] + mov rdx, [rdx+4] + cmp eax, [rcx] + je Next + mov eax, 1 + jmp Finish + +Next: + cmp rdx, [rcx+4] + je Done + mov eax, 1 + jmp Finish + +Done: + xor eax, eax + +Finish: + emms + ret + +memcmp_mmx endp + +; TestClutChangeMMX +; mov rdx, dst +; mov rcx, src +; mov r8d, entries +TestClutChangeMMX proc public + +Start: + movq mm0, [rdx] + movq mm1, [rdx+8] + pcmpeqd mm0, [rcx] + pcmpeqd mm1, [rcx+16] + + movq mm2, [rdx+16] + movq mm3, [rdx+24] + pcmpeqd mm2, [rcx+32] + pcmpeqd mm3, [rcx+48] + + pand mm0, mm1 + pand mm2, mm3 + movq mm4, [rdx+32] + movq mm5, [rdx+40] + pcmpeqd mm4, [rcx+8] + pcmpeqd mm5, [rcx+24] + + pand mm0, mm2 + pand mm4, mm5 + movq mm6, [rdx+48] + movq mm7, [rdx+56] + pcmpeqd mm6, [rcx+40] + pcmpeqd mm7, [rcx+56] + + pand mm0, mm4 + pand mm6, mm7 + pand mm0, mm6 + + pmovmskb eax, mm0 + cmp eax, 0ffh + je Continue + mov byte ptr [r9], 1 + jmp Return + +Continue: + cmp r8d, 16 + jle Return + + test r8d, 010h + jz AddRcx + sub rcx, 448 ; go back and down one column, +AddRcx: + add rcx, 256 ; go to the right block + + + jne Continue1 + add rcx, 256 ; skip whole block +Continue1: + add rdx, 64 + sub r8d, 16 + jmp Start + +Return: + emms + ret + +TestClutChangeMMX endp + +UnswizzleZ16Target proc public + pxor xmm7, xmm7 + +Z16Loop: + ;; unpack 64 bytes at a time + movdqa xmm0, [rdx] + movdqa xmm2, [rdx+16] + movdqa xmm4, [rdx+32] + movdqa xmm6, [rdx+48] + + movdqa xmm1, xmm0 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + + punpcklwd xmm0, xmm7 + punpckhwd xmm1, xmm7 + punpcklwd xmm2, xmm7 + punpckhwd xmm3, xmm7 + + ;; start saving + movdqa [rcx], xmm0 + movdqa [rcx+16], xmm1 + + punpcklwd xmm4, xmm7 + punpckhwd xmm5, xmm7 + + movdqa [rcx+32], xmm2 + movdqa [rcx+48], xmm3 + + movdqa xmm0, xmm6 + punpcklwd xmm6, xmm7 + + movdqa [rcx+64], xmm4 + movdqa [rcx+80], xmm5 + + punpckhwd xmm0, xmm7 + + movdqa [rcx+96], xmm6 + movdqa [rcx+112], xmm0 + + add rdx, 64 + add rcx, 128 + sub r9d, 1 + jne Z16Loop + + ret +UnswizzleZ16Target endp + +; +; swizzling +; + +punpck macro op, sd0, sd2, s1, s3, d1, d3 + + movdqa @CatStr(xmm, %d1), @CatStr(xmm, %sd0) + pshufd @CatStr(xmm, %d3), @CatStr(xmm, %sd2), 0e4h + + @CatStr(punpckl, op) @CatStr(xmm, %sd0), @CatStr(xmm, %s1) + @CatStr(punpckh, op) @CatStr(xmm, %d1), @CatStr(xmm, %s1) + @CatStr(punpckl, op) @CatStr(xmm, %sd2), @CatStr(xmm, %s3) + @CatStr(punpckh, op) @CatStr(xmm, %d3), @CatStr(xmm, %s3) + + endm + +punpcknbl macro + + movdqa xmm4, xmm0 + pshufd xmm5, xmm1, 0e4h + + psllq xmm1, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm0, xmm7 + pandn xmm6, xmm1 + por xmm0, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm1, xmm4 + + movdqa xmm4, xmm2 + pshufd xmm5, xmm3, 0e4h + + psllq xmm3, 4 + psrlq xmm4, 4 + + movdqa xmm6, xmm7 + pand xmm2, xmm7 + pandn xmm6, xmm3 + por xmm2, xmm6 + + movdqa xmm6, xmm7 + pand xmm4, xmm7 + pandn xmm6, xmm5 + por xmm4, xmm6 + + movdqa xmm3, xmm4 + + punpck bw, 0, 2, 1, 3, 4, 6 + + endm + +punpcknbh macro + + movdqa xmm12, xmm8 + pshufd xmm13, xmm9, 0e4h + + psllq xmm9, 4 + psrlq xmm12, 4 + + movdqa xmm14, xmm15 + pand xmm8, xmm15 + pandn xmm14, xmm9 + por xmm8, xmm14 + + movdqa xmm14, xmm15 + pand xmm12, xmm15 + pandn xmm14, xmm13 + por xmm12, xmm14 + + movdqa xmm9, xmm12 + + movdqa xmm12, xmm10 + pshufd xmm13, xmm11, 0e4h + + psllq xmm11, 4 + psrlq xmm12, 4 + + movdqa xmm14, xmm15 + pand xmm10, xmm15 + pandn xmm14, xmm11 + por xmm10, xmm14 + + movdqa xmm14, xmm15 + pand xmm12, xmm15 + pandn xmm14, xmm13 + por xmm12, xmm14 + + movdqa xmm11, xmm12 + + punpck bw, 8, 10, 9, 11, 12, 14 + + endm + +; +; SwizzleBlock32_sse2 +; + +SwizzleBlock32_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + cmp r9d, 0ffffffffh + jne SwizzleBlock32_sse2@WM + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm4, [rsi+16] + movdqa xmm1, [rsi+r8] + movdqa xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm2 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32_sse2@WM: + + movd xmm7, r9d + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm4, [rsi+16] + movdqa xmm1, [rsi+r8] + movdqa xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + movdqa xmm9, xmm7 + pshufd xmm11, xmm7, 0e4h + + pandn xmm3, [rdi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [rdi+16*0], xmm0 + + pandn xmm5, [rdi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [rdi+16*1], xmm2 + + pandn xmm9, [rdi+16*2] + pand xmm4, xmm7 + por xmm4, xmm9 + movdqa [rdi+16*2], xmm4 + + pandn xmm11, [rdi+16*3] + pand xmm6, xmm7 + por xmm6, xmm11 + movdqa [edi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32_sse2 endp + +; +; SwizzleBlock16_sse2 +; + +SwizzleBlock16_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + align 16 +@@: + movdqa xmm0, [rsi] + movdqa xmm1, [rsi+16] + movdqa xmm2, [rsi+r8] + movdqa xmm3, [rsi+r8+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm5 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock16_sse2 endp + +; +; SwizzleBlock8 +; + +SwizzleBlock8_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov ecx, 2 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshufd xmm1, [rsi], 0b1h + pshufd xmm3, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm4 + movdqa [rdi+16*2], xmm1 + movdqa [rdi+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [rsi], 0b1h + pshufd xmm2, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm4 + movdqa [rdi+16*6], xmm1 + movdqa [rdi+16*7], xmm5 + + add edi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock8_sse2 endp + +; +; SwizzleBlock4 +; + +SwizzleBlock4_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 2 + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + ; col 0, 2 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm3 + + ; col 1, 3 + + movdqa xmm0, [rsi] + movdqa xmm2, [rsi+r8] + lea esi, [rsi+r8*2] + + movdqa xmm1, [rsi] + movdqa xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm1 + movdqa [rdi+16*6], xmm4 + movdqa [rdi+16*7], xmm3 + + add rdi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock4_sse2 endp + +; +; swizzling with unaligned reads +; + +; +; SwizzleBlock32u_sse2 +; + +SwizzleBlock32u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + cmp r9d, 0ffffffffh + jne SwizzleBlock32u_sse2@WM + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm4, [rsi+16] + movdqu xmm1, [rsi+r8] + movdqu xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm2 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32u_sse2@WM: + + movd xmm7, r9d + pshufd xmm7, xmm7, 0 + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm4, [rsi+16] + movdqu xmm1, [rsi+r8] + movdqu xmm5, [rsi+r8+16] + + punpck qdq, 0, 4, 1, 5, 2, 6 + + movdqa xmm3, xmm7 + pshufd xmm5, xmm7, 0e4h + movdqa xmm9, xmm7 + pshufd xmm11, xmm7, 0e4h + + pandn xmm3, [rdi+16*0] + pand xmm0, xmm7 + por xmm0, xmm3 + movdqa [rdi+16*0], xmm0 + + pandn xmm5, [rdi+16*1] + pand xmm2, xmm7 + por xmm2, xmm5 + movdqa [rdi+16*1], xmm2 + + pandn xmm9, [rdi+16*2] + pand xmm4, xmm7 + por xmm4, xmm9 + movdqa [rdi+16*2], xmm4 + + pandn xmm11, [rdi+16*3] + pand xmm6, xmm7 + por xmm6, xmm11 + movdqa [edi+16*3], xmm6 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock32u_sse2 endp + +; +; SwizzleBlock16u_sse2 +; + +SwizzleBlock16u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 4 + + align 16 +@@: + movdqu xmm0, [rsi] + movdqu xmm1, [rsi+16] + movdqu xmm2, [rsi+r8] + movdqu xmm3, [rsi+r8+16] + + punpck wd, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm5 + + lea rsi, [rsi+r8*2] + add rdi, 64 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock16u_sse2 endp + +; +; SwizzleBlock8u +; + +SwizzleBlock8u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov ecx, 2 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshufd xmm1, [rsi], 0b1h + pshufd xmm3, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm4 + movdqa [rdi+16*2], xmm1 + movdqa [rdi+16*3], xmm5 + + ; col 1, 3 + + pshufd xmm0, [rsi], 0b1h + pshufd xmm2, [rsi+r8], 0b1h + lea rsi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + punpck bw, 0, 2, 1, 3, 4, 6 + punpck wd, 0, 2, 4, 6, 1, 3 + punpck qdq, 0, 1, 2, 3, 4, 5 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm4 + movdqa [rdi+16*6], xmm1 + movdqa [rdi+16*7], xmm5 + + add edi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock8u_sse2 endp + +; +; SwizzleBlock4u +; + +SwizzleBlock4u_sse2 proc public + + push rsi + push rdi + + mov rdi, rcx + mov rsi, rdx + mov rcx, 2 + + mov eax, 0f0f0f0fh + movd xmm7, eax + pshufd xmm7, xmm7, 0 + + align 16 +@@: + ; col 0, 2 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea rsi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm1, xmm1, 0b1h + pshuflw xmm3, xmm3, 0b1h + pshufhw xmm1, xmm1, 0b1h + pshufhw xmm3, xmm3, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*0], xmm0 + movdqa [rdi+16*1], xmm1 + movdqa [rdi+16*2], xmm4 + movdqa [rdi+16*3], xmm3 + + ; col 1, 3 + + movdqu xmm0, [rsi] + movdqu xmm2, [rsi+r8] + lea esi, [rsi+r8*2] + + movdqu xmm1, [rsi] + movdqu xmm3, [rsi+r8] + lea rsi, [rsi+r8*2] + + pshuflw xmm0, xmm0, 0b1h + pshuflw xmm2, xmm2, 0b1h + pshufhw xmm0, xmm0, 0b1h + pshufhw xmm2, xmm2, 0b1h + + punpcknbl + punpck bw, 0, 2, 4, 6, 1, 3 + punpck bw, 0, 2, 1, 3, 4, 6 + punpck qdq, 0, 4, 2, 6, 1, 3 + + movdqa [rdi+16*4], xmm0 + movdqa [rdi+16*5], xmm1 + movdqa [rdi+16*6], xmm4 + movdqa [rdi+16*7], xmm3 + + add rdi, 128 + + dec rcx + jnz @B + + pop rdi + pop rsi + + ret + +SwizzleBlock4u_sse2 endp + +WriteCLUT_T16_I4_CSM1_sse2 proc public + movdqa xmm0, XMMWORD PTR [rcx] + movdqa xmm1, XMMWORD PTR [rcx+16] + movdqa xmm2, XMMWORD PTR [rcx+32] + movdqa xmm3, XMMWORD PTR [rcx+48] + + ;; rearrange + pshuflw xmm0, xmm0, 088h + pshufhw xmm0, xmm0, 088h + pshuflw xmm1, xmm1, 088h + pshufhw xmm1, xmm1, 088h + pshuflw xmm2, xmm2, 088h + pshufhw xmm2, xmm2, 088h + pshuflw xmm3, xmm3, 088h + pshufhw xmm3, xmm3, 088h + + shufps xmm0, xmm1, 088h + shufps xmm2, xmm3, 088h + + pshufd xmm0, xmm0, 0d8h + pshufd xmm2, xmm2, 0d8h + + pxor xmm6, xmm6 + mov rax, s_clut16mask + + test rdx, 15 + jnz WriteUnaligned + + movdqa xmm7, XMMWORD PTR [rax] ;; saves upper 16 bits + + ;; have to save interlaced with the old data + movdqa xmm4, [rdx] + movdqa xmm5, [rdx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 ;; lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0e4h ;; upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + + movdqa [rdx], xmm0 + movdqa [rdx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [rdx+16] + pand xmm5, [rdx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [rdx+16], xmm2 + movdqa [rdx+48], xmm3 + jmp WriteCLUT_T16_I4_CSM1_End + +WriteUnaligned: + ;; rdx is offset by 2 + sub rdx, 2 + + movdqa xmm7, XMMWORD PTR [rax+16] ;; saves lower 16 bits + + ;; have to save interlaced with the old data + movdqa xmm4, [rdx] + movdqa xmm5, [rdx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 ;; lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0e4h ;; upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + pslld xmm0, 16 + pslld xmm1, 16 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + pslld xmm2, 16 + pslld xmm3, 16 + + movdqa [rdx], xmm0 + movdqa [rdx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [rdx+16] + pand xmm5, [rdx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [rdx+16], xmm2 + movdqa [rdx+48], xmm3 +WriteCLUT_T16_I4_CSM1_End: + ret + +WriteCLUT_T16_I4_CSM1_sse2 endp + +end \ No newline at end of file diff --git a/plugins/gs/zerogs/opengl/x86.cpp b/plugins/gs/zerogs/opengl/x86.cpp new file mode 100644 index 0000000..e3058d3 --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86.cpp @@ -0,0 +1,571 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 Gabest/zerofrog@gmail.com + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GS.h" +#include "Mem.h" +#include "x86.h" + +#if defined(ZEROGS_SSE2) && (defined(_WIN32)||defined(__x86_64__)) +#include +#include +#endif + +// swizzling + +void FASTCALL(SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask)) +{ + u32* d = &g_columnTable32[0][0]; + + if(WriteMask == 0xffffffff) + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = ((u32*)src)[i]; + } + else + { + for(int j = 0; j < 8; j++, d += 8, src += srcpitch) + for(int i = 0; i < 8; i++) + ((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask); + } +} + +void FASTCALL(SwizzleBlock16_c(u8* dst, u8* src, int srcpitch)) +{ + u32* d = &g_columnTable16[0][0]; + + for(int j = 0; j < 8; j++, d += 16, src += srcpitch) + for(int i = 0; i < 16; i++) + ((u16*)dst)[d[i]] = ((u16*)src)[i]; +} + +void FASTCALL(SwizzleBlock8_c(u8* dst, u8* src, int srcpitch)) +{ + u32* d = &g_columnTable8[0][0]; + + for(int j = 0; j < 16; j++, d += 16, src += srcpitch) + for(int i = 0; i < 16; i++) + dst[d[i]] = src[i]; +} + +void FASTCALL(SwizzleBlock4_c(u8* dst, u8* src, int srcpitch)) +{ + u32* d = &g_columnTable4[0][0]; + + for(int j = 0; j < 16; j++, d += 32, src += srcpitch) + { + for(int i = 0; i < 32; i++) + { + u32 addr = d[i]; + u8 c = (src[i>>1] >> ((i&1) << 2)) & 0x0f; + u32 shift = (addr&1) << 2; + dst[addr >> 1] = (dst[addr >> 1] & (0xf0 >> shift)) | (c << shift); + } + } +} + +#define _FrameSwizzleBlock(type, transfer, transfer16, incsrc) \ +/* FrameSwizzleBlock32 */ \ +void FASTCALL(FrameSwizzleBlock32##type##c(u32* dst, u32* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ + \ + if( WriteMask == 0xffffffff ) { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = (transfer); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + dst[d[j]] = ((transfer)&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ +} \ +\ +/* FrameSwizzleBlock16 */ \ +void FASTCALL(FrameSwizzleBlock16##type##c(u16* dst, u32* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + if( WriteMask == 0xffff ) { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + u32 temp = (transfer); \ + dst[d[j]] = RGBA32to16(temp); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + u32 temp = (transfer); \ + u32 dsrc = RGBA32to16(temp); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ +} \ +\ +/* Frame16SwizzleBlock32 */ \ +void FASTCALL(Frame16SwizzleBlock32##type##c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ +\ + if( WriteMask == 0xffffffff ) { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ +\ +/* Frame16SwizzleBlock32Z */ \ +void FASTCALL(Frame16SwizzleBlock32Z##type##c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable32[0][0]; \ + if( WriteMask == 0xffffffff ) { /* breaks KH text if not checked */ \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB_Z(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 8) { \ + for(int j = 0; j < 8; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB_Z(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ + \ + /* Frame16SwizzleBlock16 */ \ +void FASTCALL(Frame16SwizzleBlock16##type##c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + if( (WriteMask&0xfff8f8f8) == 0xfff8f8f8) { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB16(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + else { \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + u32 dsrc = Float16ToARGB16(dsrc16); \ + dst[d[j]] = (dsrc&WriteMask)|(dst[d[j]]&~WriteMask); \ + } \ + src += srcpitch << incsrc; \ + } \ + } \ + } \ + \ + /* Frame16SwizzleBlock16Z */ \ +void FASTCALL(Frame16SwizzleBlock16Z##type##c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)) \ +{ \ + u32* d = &g_columnTable16[0][0]; \ + \ + for(int i = 0; i < 8; ++i, d += 16) { \ + for(int j = 0; j < 16; ++j) { \ + Vector_16F dsrc16 = (transfer16); \ + dst[d[j]] = Float16ToARGB16_Z(dsrc16); \ + } \ + src += srcpitch << incsrc; \ + } \ +} \ + +_FrameSwizzleBlock(_, src[j], src[j], 0); +_FrameSwizzleBlock(A2_, (src[2*j]+src[2*j+1])>>1, src[2*j], 0); +_FrameSwizzleBlock(A4_, (src[2*j]+src[2*j+1]+src[2*j+srcpitch]+src[2*j+srcpitch+1])>>2, src[2*j], 1); + +#ifdef ZEROGS_SSE2 + +//void FASTCALL(WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut) +//{ +// __asm { +// mov eax, vm +// mov ecx, clut +// mov edx, 8 +// } +// +//Extract32x2: +// __asm { +// movdqa xmm0, qword ptr [eax] +// movdqa xmm1, qword ptr [eax+16] +// movdqa xmm2, qword ptr [eax+32] +// movdqa xmm3, qword ptr [eax+48] +// +// // rearrange +// pshuflw xmm0, xmm0, 0xd8 +// pshufhw xmm0, xmm0, 0xd8 +// pshuflw xmm1, xmm1, 0xd8 +// pshufhw xmm1, xmm1, 0xd8 +// pshuflw xmm2, xmm2, 0xd8 +// pshufhw xmm2, xmm2, 0xd8 +// pshuflw xmm3, xmm3, 0xd8 +// pshufhw xmm3, xmm3, 0xd8 +// +// movdqa xmm4, xmm0 +// movdqa xmm6, xmm2 +// +// shufps xmm0, xmm1, 0x88 +// shufps xmm2, xmm3, 0x88 +// +// shufps xmm4, xmm1, 0xdd +// shufps xmm6, xmm3, 0xdd +// +// pshufd xmm0, xmm0, 0xd8 +// pshufd xmm2, xmm2, 0xd8 +// pshufd xmm4, xmm4, 0xd8 +// pshufd xmm6, xmm6, 0xd8 +// +// // left column +// movhlps xmm1, xmm0 +// movlhps xmm0, xmm2 +// //movdqa xmm7, [ecx] +// +// movdqa [ecx], xmm0 +// shufps xmm1, xmm2, 0xe4 +// movdqa [ecx+16], xmm1 +// +// // right column +// movhlps xmm3, xmm4 +// movlhps xmm4, xmm6 +// movdqa [ecx+32], xmm4 +// shufps xmm3, xmm6, 0xe4 +// movdqa [ecx+48], xmm3 +// +// add eax, 16*4 +// add ecx, 16*8 +// sub edx, 1 +// cmp edx, 0 +// jne Extract32x2 +// } +//} + +#if (defined(_WIN32)||defined(__x86_64__)) + +extern "C" void FASTCALL(WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut)) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + for(int j = 0; j < 64; j += 32, src += 32, dst += 32) + { + for(int i = 0; i < 16; i += 4) + { + __m128i r0 = _mm_load_si128(&src[i+0]); + __m128i r1 = _mm_load_si128(&src[i+1]); + __m128i r2 = _mm_load_si128(&src[i+2]); + __m128i r3 = _mm_load_si128(&src[i+3]); + + _mm_store_si128(&dst[i*2+0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[i*2+2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[i*2+3], _mm_unpackhi_epi64(r2, r3)); + + __m128i r4 = _mm_load_si128(&src[i+0+16]); + __m128i r5 = _mm_load_si128(&src[i+1+16]); + __m128i r6 = _mm_load_si128(&src[i+2+16]); + __m128i r7 = _mm_load_si128(&src[i+3+16]); + + _mm_store_si128(&dst[i*2+4], _mm_unpacklo_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+5], _mm_unpacklo_epi64(r6, r7)); + _mm_store_si128(&dst[i*2+6], _mm_unpackhi_epi64(r4, r5)); + _mm_store_si128(&dst[i*2+7], _mm_unpackhi_epi64(r6, r7)); + } + } +} + +extern "C" void FASTCALL(WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut)) +{ + __m128i* src = (__m128i*)vm; + __m128i* dst = (__m128i*)clut; + + __m128i r0 = _mm_load_si128(&src[0]); + __m128i r1 = _mm_load_si128(&src[1]); + __m128i r2 = _mm_load_si128(&src[2]); + __m128i r3 = _mm_load_si128(&src[3]); + + _mm_store_si128(&dst[0], _mm_unpacklo_epi64(r0, r1)); + _mm_store_si128(&dst[1], _mm_unpacklo_epi64(r2, r3)); + _mm_store_si128(&dst[2], _mm_unpackhi_epi64(r0, r1)); + _mm_store_si128(&dst[3], _mm_unpackhi_epi64(r2, r3)); +} +#endif + +#if defined(_MSC_VER) + +extern "C" { +PCSX2_ALIGNED16(int s_clut16mask2[4]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff }; +PCSX2_ALIGNED16(int s_clut16mask[8]) = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000, + 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}; +} + +#if !defined(__x86_64__) + +extern "C" void FASTCALL(WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut)) +{ + __asm { + mov eax, vm + mov ecx, clut + movdqa xmm0, qword ptr [eax] + movdqa xmm1, qword ptr [eax+16] + movdqa xmm2, qword ptr [eax+32] + movdqa xmm3, qword ptr [eax+48] + + // rearrange + pshuflw xmm0, xmm0, 0x88 + pshufhw xmm0, xmm0, 0x88 + pshuflw xmm1, xmm1, 0x88 + pshufhw xmm1, xmm1, 0x88 + pshuflw xmm2, xmm2, 0x88 + pshufhw xmm2, xmm2, 0x88 + pshuflw xmm3, xmm3, 0x88 + pshufhw xmm3, xmm3, 0x88 + + shufps xmm0, xmm1, 0x88 + shufps xmm2, xmm3, 0x88 + + pshufd xmm0, xmm0, 0xd8 + pshufd xmm2, xmm2, 0xd8 + + pxor xmm6, xmm6 + + test ecx, 15 + jnz WriteUnaligned + + movdqa xmm7, s_clut16mask // saves upper 16 bits + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 + jmp End + +WriteUnaligned: + // ecx is offset by 2 + sub ecx, 2 + + movdqa xmm7, s_clut16mask2 // saves lower 16 bits + + // have to save interlaced with the old data + movdqa xmm4, [ecx] + movdqa xmm5, [ecx+32] + movhlps xmm1, xmm0 + movlhps xmm0, xmm2 // lower 8 colors + + pand xmm4, xmm7 + pand xmm5, xmm7 + + shufps xmm1, xmm2, 0xe4 // upper 8 colors + movdqa xmm2, xmm0 + movdqa xmm3, xmm1 + + punpcklwd xmm0, xmm6 + punpcklwd xmm1, xmm6 + pslld xmm0, 16 + pslld xmm1, 16 + por xmm0, xmm4 + por xmm1, xmm5 + + punpckhwd xmm2, xmm6 + punpckhwd xmm3, xmm6 + pslld xmm2, 16 + pslld xmm3, 16 + + movdqa [ecx], xmm0 + movdqa [ecx+32], xmm1 + + movdqa xmm5, xmm7 + pand xmm7, [ecx+16] + pand xmm5, [ecx+48] + + por xmm2, xmm7 + por xmm3, xmm5 + + movdqa [ecx+16], xmm2 + movdqa [ecx+48], xmm3 +End: + } +} +#endif // __x86_64__ +#endif // _MSC_VER + +#endif // ZEROGS_SSE2 + +void FASTCALL(WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut)) +{ + const static u32 map[] = + { + 0, 2, 8, 10, 16, 18, 24, 26, + 4, 6, 12, 14, 20, 22, 28, 30, + 1, 3, 9, 11, 17, 19, 25, 27, + 5, 7, 13, 15, 21, 23, 29, 31 + }; + + u16* vm = (u16*)_vm; + u16* clut = (u16*)_clut; + + int left = ((u32)(uptr)clut&2) ? 512 : 512-(((u32)(uptr)clut)&0x3ff)/2; + + for(int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32) + { + if(left == 32) { + assert( left == 32 ); + for(int i = 0; i < 16; i++) + clut[2*i] = vm[map[i]]; + + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + + for(int i = 16; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + else { + if( left == 0 ) { + clut = (u16*)((uptr)clut & ~0x3ff) + 1; + left = -1; + } + + for(int i = 0; i < 32; i++) + clut[2*i] = vm[map[i]]; + } + } +} + +void FASTCALL(WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut)) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + for(int j = 0; j < 2; j++, src += 32) { + for(int i = 0; i < 4; i++, dst+=16, src+=8) + { + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; + + dst[8] = src[32]; + dst[9] = src[32+2]; + dst[10] = src[32+4]; + dst[11] = src[32+6]; + dst[12] = src[32+1]; + dst[13] = src[32+3]; + dst[14] = src[32+5]; + dst[15] = src[32+7]; + } + } +} + +void FASTCALL(WriteCLUT_T16_I4_CSM1_c(u32* _vm, u32* _clut)) +{ + u16* dst = (u16*)_clut; + u16* src = (u16*)_vm; + + dst[0] = src[0]; dst[2] = src[2]; + dst[4] = src[8]; dst[6] = src[10]; + dst[8] = src[16]; dst[10] = src[18]; + dst[12] = src[24]; dst[14] = src[26]; + dst[16] = src[4]; dst[18] = src[6]; + dst[20] = src[12]; dst[22] = src[14]; + dst[24] = src[20]; dst[26] = src[22]; + dst[28] = src[28]; dst[30] = src[30]; +} + +void FASTCALL(WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut)) +{ + u64* src = (u64*)vm; + u64* dst = (u64*)clut; + + dst[0] = src[0]; + dst[1] = src[2]; + dst[2] = src[4]; + dst[3] = src[6]; + dst[4] = src[1]; + dst[5] = src[3]; + dst[6] = src[5]; + dst[7] = src[7]; +} diff --git a/plugins/gs/zerogs/opengl/x86.h b/plugins/gs/zerogs/opengl/x86.h new file mode 100644 index 0000000..a9eb717 --- /dev/null +++ b/plugins/gs/zerogs/opengl/x86.h @@ -0,0 +1,182 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 Gabest/zerofrog@gmail.com + * http://www.gabest.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#ifndef ZEROGS_X86 +#define ZEROGS_X86 + +#include "GS.h" + +extern "C" void FASTCALL(SwizzleBlock32_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff)); +extern "C" void FASTCALL(SwizzleBlock16_sse2(u8* dst, u8* src, int srcpitch)); +extern "C" void FASTCALL(SwizzleBlock8_sse2(u8* dst, u8* src, int srcpitch)); +extern "C" void FASTCALL(SwizzleBlock4_sse2(u8* dst, u8* src, int srcpitch)); +extern "C" void FASTCALL(SwizzleBlock32u_sse2(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff)); +extern "C" void FASTCALL(SwizzleBlock16u_sse2(u8* dst, u8* src, int srcpitch)); +extern "C" void FASTCALL(SwizzleBlock8u_sse2(u8* dst, u8* src, int srcpitch)); +extern "C" void FASTCALL(SwizzleBlock4u_sse2(u8* dst, u8* src, int srcpitch)); + +// frame swizzling + +// no AA +extern "C" void FASTCALL(FrameSwizzleBlock32_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(FrameSwizzleBlock16_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32Z_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16Z_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +// AA 2x +extern "C" void FASTCALL(FrameSwizzleBlock32A2_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(FrameSwizzleBlock16A2_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32A2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32ZA2_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16A2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16ZA2_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +// AA 4x +extern "C" void FASTCALL(FrameSwizzleBlock32A4_sse2(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(FrameSwizzleBlock16A4_sse2(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32A4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock32ZA4_sse2(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16A4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern "C" void FASTCALL(Frame16SwizzleBlock16ZA4_sse2(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +extern void FASTCALL(SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff)); +extern void FASTCALL(SwizzleBlock16_c(u8* dst, u8* src, int srcpitch)); +extern void FASTCALL(SwizzleBlock8_c(u8* dst, u8* src, int srcpitch)); +extern void FASTCALL(SwizzleBlock4_c(u8* dst, u8* src, int srcpitch)); + +// no AA +extern void FASTCALL(FrameSwizzleBlock32_c(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(FrameSwizzleBlock16_c(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32Z_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16Z_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +// AA 2x +extern void FASTCALL(FrameSwizzleBlock32A2_c(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(FrameSwizzleBlock16A2_c(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32A2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32ZA2_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16A2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16ZA2_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +// AA 4x +extern void FASTCALL(FrameSwizzleBlock32A4_c(u32* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(FrameSwizzleBlock16A4_c(u16* dst, u32* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32A4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock32ZA4_c(u32* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16A4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); +extern void FASTCALL(Frame16SwizzleBlock16ZA4_c(u16* dst, Vector_16F* src, int srcpitch, u32 WriteMask)); + +extern void FASTCALL(SwizzleColumn32_c(int y, u8* dst, u8* src, int srcpitch, u32 WriteMask = 0xffffffff)); +extern void FASTCALL(SwizzleColumn16_c(int y, u8* dst, u8* src, int srcpitch)); +extern void FASTCALL(SwizzleColumn8_c(int y, u8* dst, u8* src, int srcpitch)); +extern void FASTCALL(SwizzleColumn4_c(int y, u8* dst, u8* src, int srcpitch)); + +extern "C" void FASTCALL(WriteCLUT_T16_I8_CSM1_sse2(u32* vm, u32* clut)); +extern "C" void FASTCALL(WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut)); +extern "C" void FASTCALL(WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut)); +extern "C" void FASTCALL(WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut)); +extern void FASTCALL(WriteCLUT_T16_I8_CSM1_c(u32* vm, u32* clut)); +extern void FASTCALL(WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut)); + +extern void FASTCALL(WriteCLUT_T16_I4_CSM1_c(u32* vm, u32* clut)); +extern void FASTCALL(WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut)); + +#ifdef ZEROGS_SSE2 + +#define SwizzleBlock32 SwizzleBlock32_sse2 +#define SwizzleBlock16 SwizzleBlock16_sse2 +#define SwizzleBlock8 SwizzleBlock8_sse2 +#define SwizzleBlock4 SwizzleBlock4_sse2 +#define SwizzleBlock32u SwizzleBlock32u_sse2 +#define SwizzleBlock16u SwizzleBlock16u_sse2 +#define SwizzleBlock8u SwizzleBlock8u_sse2 +#define SwizzleBlock4u SwizzleBlock4u_sse2 + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_sse2 +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_sse2 +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_sse2 +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_sse2 + +#else + +#define SwizzleBlock32 SwizzleBlock32_c +#define SwizzleBlock16 SwizzleBlock16_c +#define SwizzleBlock8 SwizzleBlock8_c +#define SwizzleBlock4 SwizzleBlock4_c +#define SwizzleBlock32u SwizzleBlock32_c +#define SwizzleBlock16u SwizzleBlock16_c +#define SwizzleBlock8u SwizzleBlock8_c +#define SwizzleBlock4u SwizzleBlock4_c + +#define FrameSwizzleBlock32 FrameSwizzleBlock32_c +#define FrameSwizzleBlock16 FrameSwizzleBlock16_c +#define Frame16SwizzleBlock32 Frame16SwizzleBlock32_c +#define Frame16SwizzleBlock32Z Frame16SwizzleBlock32Z_c +#define Frame16SwizzleBlock16 Frame16SwizzleBlock16_c +#define Frame16SwizzleBlock16Z Frame16SwizzleBlock16Z_c + +#define FrameSwizzleBlock32A2 FrameSwizzleBlock32A2_c +#define FrameSwizzleBlock16A2 FrameSwizzleBlock16A2_c +#define Frame16SwizzleBlock32A2 Frame16SwizzleBlock32A2_c +#define Frame16SwizzleBlock32ZA2 Frame16SwizzleBlock32ZA2_c +#define Frame16SwizzleBlock16A2 Frame16SwizzleBlock16A2_c +#define Frame16SwizzleBlock16ZA2 Frame16SwizzleBlock16ZA2_c + +#define FrameSwizzleBlock32A4 FrameSwizzleBlock32A4_c +#define FrameSwizzleBlock16A4 FrameSwizzleBlock16A4_c +#define Frame16SwizzleBlock32A4 Frame16SwizzleBlock32A4_c +#define Frame16SwizzleBlock32ZA4 Frame16SwizzleBlock32ZA4_c +#define Frame16SwizzleBlock16A4 Frame16SwizzleBlock16A4_c +#define Frame16SwizzleBlock16ZA4 Frame16SwizzleBlock16ZA4_c + +#define WriteCLUT_T16_I8_CSM1 WriteCLUT_T16_I8_CSM1_c +#define WriteCLUT_T32_I8_CSM1 WriteCLUT_T32_I8_CSM1_c +#define WriteCLUT_T16_I4_CSM1 WriteCLUT_T16_I4_CSM1_c +#define WriteCLUT_T32_I4_CSM1 WriteCLUT_T32_I4_CSM1_c + +#endif + +#endif diff --git a/plugins/gs/zerogs/opengl/zerogs.cpp b/plugins/gs/zerogs/opengl/zerogs.cpp new file mode 100644 index 0000000..e46accb --- /dev/null +++ b/plugins/gs/zerogs/opengl/zerogs.cpp @@ -0,0 +1,5908 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if defined(_WIN32) +#include +#include + +#include "resource.h" +#endif + +#include + +#include +#include +#include +#include + +#include "GS.h" +#include "Mem.h" +#include "x86.h" +#include "zerogs.h" +#include "zpipe.h" + +#include "ZeroGSShaders/zerogsshaders.h" +#include "targets.h" +#include "rasterfont.h" // simple font + +#define VB_BUFFERSIZE 0x400 +#define VB_NUMBUFFERS 512 +#define SIZEOF_VB sizeof(ZeroGS::VB)//((u32)((u8*)&vb[0].buffers-(u8*)&vb[0])) + +#define MINMAX_SHIFT 3 +#define MAX_ACTIVECLUTS 16 + +#define ZEROGS_SAVEVER 0xaa000004 + +#define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80 +#define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush) +#define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush) +#define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush) +//#define STENCIL_PBE 16 +#define STENCIL_CLEAR (2|4|8|16) + +#define VBSAVELIMIT ((u32)((u8*)&vb[0].nNextFrameHeight-(u8*)&vb[0])) + +using namespace ZeroGS; + +extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve; +extern char *libraryName; +extern int g_nFrame, g_nRealFrame; +extern float fFPS; +extern unsigned char revision, build, minor; + +BOOL g_bDisplayMsg = 1; + +#ifdef _WIN32 +HDC hDC=NULL; // Private GDI Device Context +HGLRC hRC=NULL; // Permanent Rendering Context +#endif + +BOOL g_bCRTCBilinear = TRUE; +BOOL g_bSaveFlushedFrame = 0; +BOOL g_bIsLost = 0; +int g_nFrameRender = 10; +int g_nFramesSkipped = 0; + +#ifdef RELEASE_TO_PUBLIC + +#define INC_GENVARS() +#define INC_TEXVARS() +#define INC_ALPHAVARS() +#define INC_RESOLVE() + +#define g_bUpdateEffect 0 +#define g_bSaveTex 0 +#define g_bSaveTrans 0 +#define g_bSaveFrame 0 +#define g_bSaveFinalFrame 0 +#define g_bSaveResolved 0 + +#else + +#define INC_GENVARS() ++g_nGenVars +#define INC_TEXVARS() ++g_nTexVars +#define INC_ALPHAVARS() ++g_nAlphaVars +#define INC_RESOLVE() ++g_nResolve + +BOOL g_bSaveTrans = 0; +BOOL g_bUpdateEffect = 0; +BOOL g_bSaveTex = 0; // saves the curent texture +BOOL g_bSaveFrame = 0; // saves the current psurfTarget +BOOL g_bSaveFinalFrame = 0; // saves the input to the CRTC +BOOL g_bSaveResolved = 0; + +#ifdef _WIN32 +//#define EFFECT_NAME "f:\\ps2dev\\svn\\pcsx2\\ZeroGS\\opengl\\" +char* EFFECT_DIR = "C:\\programming\\ps2dev\\pcsx2\\zerogs\\opengl\\"; +char* EFFECT_NAME = "C:\\programming\\ps2dev\\pcsx2\\zerogs\\opengl\\ps2hw.fx"; +#else +char EFFECT_DIR[255] = "~/pcsx2/plugins/gs/zerogs/opengl/"; +char EFFECT_NAME[255] = "~/pcsx2/plugins/gs/zerogs/opengl/ps2hw.fx"; +#endif + +#endif + +BOOL g_bUpdateStencil = 1; // only needed for dest alpha test (unfortunately, it has to be on all the time) + +#define DRAW() glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount) + +#define GL_BLEND_RGB(src, dst) { \ + s_srcrgb = src; \ + s_dstrgb = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALPHA(src, dst) { \ + s_srcalpha = src; \ + s_dstalpha = dst; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \ + s_srcrgb = srcrgb; \ + s_dstrgb = dstrgb; \ + s_srcalpha = srcalpha; \ + s_dstalpha = dstalpha; \ + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \ +} + +#define GL_BLEND_SET() zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha) + +#define GL_ZTEST(enable) { \ + if( enable ) glEnable(GL_DEPTH_TEST); \ + else glDisable(GL_DEPTH_TEST); \ +} + +#define GL_ALPHATEST(enable) { \ + if( enable ) glEnable(GL_ALPHA_TEST); \ + else glDisable(GL_ALPHA_TEST); \ +} + +#define GL_BLENDEQ_RGB(eq) { \ + s_rgbeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define GL_BLENDEQ_ALPHA(eq) { \ + s_alphaeq = eq; \ + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \ +} + +#define GL_STENCILFUNC(func, ref, mask) { \ + s_stencilfunc = func; \ + s_stencilref = ref; \ + s_stencilmask = mask; \ + glStencilFunc(func, ref, mask); \ +} + +#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask) + +#define COLORMASK_RED 1 +#define COLORMASK_GREEN 2 +#define COLORMASK_BLUE 4 +#define COLORMASK_ALPHA 8 +#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA)) + +typedef void (APIENTRYP _PFNSWAPINTERVAL) (int); + +extern int s_frameskipping; + +static u32 g_SaveFrameNum = 0; +BOOL g_bMakeSnapshot = 0; +string strSnapshot; + +int GPU_TEXWIDTH = 512; +float g_fiGPU_TEXWIDTH = 1/512.0f; + +int g_MaxTexWidth = 4096, g_MaxTexHeight = 4096; +CGprogram g_vsprog = 0, g_psprog = 0; +// AVI Capture +static int s_aviinit = 0; +static int s_avicapturing = 0; + +inline u32 FtoDW(float f) { return (*((u32*)&f)); } + +float g_fBlockMult = 1; +static int s_nFullscreen = 0; +int g_nDepthUpdateCount = 0; +int g_nDepthBias = 0; + +// local alpha blending settings +static GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT +static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT +static u32 s_stencilfunc, s_stencilref, s_stencilmask; +static GLenum s_drawbuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; + +#ifdef _WIN32 +extern HINSTANCE hInst; + +void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; +void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#else +void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL; +void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL; +#endif + +GLenum g_internalFloatFmt = GL_ALPHA_FLOAT32_ATI; +GLenum g_internalRGBAFloatFmt = GL_RGBA_FLOAT32_ATI; +GLenum g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI; + +// Consts +static const GLenum primtype[8] = { GL_POINTS, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, 0xffffffff }; +static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT }; +static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; + +static const int PRIMMASK = 0x0e; // for now ignore 0x10 (AA) + +static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; + +// used for afail case +static const u32 g_dwReverseAlphaCmp[] = { GL_ALWAYS, GL_NEVER, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_EQUAL }; + +static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER }; + +PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL; +PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL; +PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL; +PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL; +PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; +PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL; + +///////////////////// +// graphics resources +static map mapGLExtensions; +RasterFont* font_p = NULL; +CGprofile cgvProf, cgfProf; +static CGprogram pvs[16] = {NULL}; +static FRAGMENTSHADER ppsRegular[4], ppsTexture[NUM_SHADERS]; +static FRAGMENTSHADER ppsCRTC[2], ppsCRTC24[2], ppsCRTCTarg[2]; +CGparameter g_vparamPosXY[2] = {0}, g_fparamFogColor = 0; + +int g_nPixelShaderVer = 0; // default + +static u8* s_lpShaderResources = NULL; +static map mapShaderResources; + +u32 s_uFramebuffer = 0; +u32 s_ptexCurSet[2] = {0}; + +#define s_bForceTexFlush 1 +static u32 s_ptexNextSet[2] = {0}; + +u32 ptexBlocks = 0, ptexConv16to32 = 0; // holds information on block tiling +u32 ptexBilinearBlocks = 0; +u32 ptexConv32to16 = 0; +static u32 s_ptexInterlace = 0; // holds interlace fields +static int s_nInterlaceTexWidth = 0; // width of texture +static vector s_vecTempTextures; // temporary textures, released at the end of every frame + +static BOOL s_bTexFlush = FALSE; +static u32 ptexLogo = 0; +static int nLogoWidth, nLogoHeight; +static BOOL s_bWriteDepth = FALSE; +static BOOL s_bDestAlphaTest = FALSE; +static int s_nLastResolveReset = 0; +static int s_nResolveCounts[30] = {0}; // resolve counts for last 30 frames +static int s_nCurResolveIndex = 0; +int s_nResolved = 0; // number of targets resolved this frame +int g_nDepthUsed = 0; // ffx2 pal movies +static int s_nWriteDepthCount = 0; +static int s_nWireframeCount = 0; +static int s_nWriteDestAlphaTest = 0; + +//////////////////// +// State parameters +static float fiRendWidth, fiRendHeight; + +static Vector vAlphaBlendColor; // used for GPU_COLOR + +static u8 bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80) +static u32 s_dwColorWrite = 0xf; // the color write mask of the current target + +BOOL g_bDisplayFPS = FALSE; + +union { + struct { + u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set + u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values + // otherwise alpha testing needs to be done separately. + u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1. + u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max + }; + u32 _bAlphaState; +} g_vars; + +//#define bNeedAlphaColor g_vars._bNeedAlphaColor +#define b2XAlphaTest g_vars._b2XAlphaTest +#define bDestAlphaColor g_vars._bDestAlphaColor +#define bAlphaClamping g_vars._bAlphaClamping + +int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY + +// stores the buffers for the last RenderCRTC +const float g_filog32 = 0.999f / (32.0f * logf(2.0f)); + +static alphaInfo s_alphaInfo; + +CGcontext g_cgcontext; +static int nBackbufferWidth, nBackbufferHeight; + +u8* g_pbyGSMemory = NULL; // 4Mb GS system mem +u8* g_pbyGSClut = NULL; + +namespace ZeroGS +{ + VB vb[2]; + float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + + GLuint vboRect = 0; + vector g_vboBuffers; // VBOs for all drawing commands + int g_nCurVBOIndex = 0; + + u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set + RenderFormatType g_RenderFormatType = RFT_float16; + int icurctx = -1; + + Vector g_vdepth = Vector(256.0f*65536.0f, 65536.0f, 256.0f, 65536.0f*65536.0f); + + VERTEXSHADER pvsBitBlt; + FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne; + FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16; + + extern CRangeManager s_RangeMngr; // manages overwritten memory + void FlushTransferRanges(const tex0Info* ptex); + + RenderFormatType GetRenderFormat() { return g_RenderFormatType; } + GLenum GetRenderTargetFormat() { return GetRenderFormat()==RFT_byte8?4:g_internalRGBAFloat16Fmt; } + + // returns the first and last addresses aligned to a page that cover + void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); + + bool LoadEffects(); + bool LoadExtraEffects(); + FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed); + + static int s_nNewWidth = -1, s_nNewHeight = -1; + void ChangeDeviceSize(int nNewWidth, int nNewHeight); + + void ProcessMessages(); + void RenderCustom(float fAlpha); // intro anim + + struct MESSAGE + { + MESSAGE() {} + MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } + char str[255]; + u32 dwTimeStamp; + }; + + static list listMsgs; + + /////////////////////// + // Method Prototypes // + /////////////////////// + + void AdjustTransToAspect(Vector& v, int dispwidth, int dispheight); + + void KickPoint(); + void KickLine(); + void KickTriangle(); + void KickTriangleFan(); + void KickSprite(); + void KickDummy(); + + inline void SetContextTarget(int context); + + // use to update the state + void SetTexVariables(int context, FRAGMENTSHADER* pfragment, int settexint); + void SetAlphaVariables(const alphaInfo& ainfo); + void ResetAlphaVariables(); + + __forceinline void SetAlphaTestInt(pixTest curtest); + + __forceinline void RenderAlphaTest(const VB& curvb, CGparameter sOneColor); + __forceinline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting); + __forceinline void ProcessStencil(const VB& curvb); + __forceinline void RenderFBA(const VB& curvb, CGparameter sOneColor); + __forceinline void ProcessFBA(const VB& curvb, CGparameter sOneColor); + + void ResolveInRange(int start, int end); + + void ExtWrite(); + + inline u32 CreateInterlaceTex(int width) { + if( width == s_nInterlaceTexWidth && s_ptexInterlace != 0 ) return s_ptexInterlace; + + SAFE_RELEASE_TEX(s_ptexInterlace); + s_nInterlaceTexWidth = width; + + vector data(width); + for(int i = 0; i < width; ++i) data[i] = (i&1) ? 0xffffffff : 0; + + glGenTextures(1, &s_ptexInterlace); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ptexInterlace); + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_REPORT_ERRORD(); + return s_ptexInterlace; + } + + void ResetRenderTarget(int index) { + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+index, GL_TEXTURE_RECTANGLE_NV, 0, 0 ); + } + + DrawFn drawfn[8] = { KickDummy, KickDummy, KickDummy, KickDummy, + KickDummy, KickDummy, KickDummy, KickDummy }; + +}; // end namespace + +/////////////////// +// Context State // +/////////////////// +ZeroGS::VB::VB() +{ + memset(this, 0, SIZEOF_VB); + tex0.tw = 1; + tex0.th = 1; +} + +ZeroGS::VB::~VB() +{ + Destroy(); +} + +void ZeroGS::VB::Destroy() +{ + _aligned_free(pBufferData); pBufferData = NULL; nNumVertices = 0; + + prndr = NULL; + pdepth = NULL; +} + +bool ZeroGS::VB::CheckPrim() +{ + if( (PRIMMASK & prim->_val) != (PRIMMASK & curprim._val) || primtype[prim->prim] != primtype[curprim.prim] ) + return nCount > 0; + + return false; +} + +// upper bound on max possible height +#define GET_MAXHEIGHT(fbp, fbw, psm) ((((0x00100000-64*(fbp))/(fbw))&~0x1f)<<((psm&2)?1:0)) + +#include +static int maxmin = 608; +//static set s_setFBP[2]; // previous frame/zbuf pointers for the last 2 frames +//static int s_nCurFBPSet = 0; +//static map s_mapFrameHeights[2]; +//static int s_nCurFrameMap = 0; + +// a lot of times, target is too big and overwrites the texture using, if tbp != 0, use it to bound +void ZeroGS::VB::CheckFrame(int tbp) +{ + static int bChanged; + + if( bNeedZCheck ) { + PRIM_LOG("zbuf_%d: zbp=0x%x psm=0x%x, zmsk=%d\n", ictx, zbuf.zbp, zbuf.psm, zbuf.zmsk); + //zbuf = *zb; + } + + bChanged = 0; + + if( bNeedFrameCheck ) { + + int maxpos = 0x00100000; + + // important to set before calling GetTarg + bNeedFrameCheck = 0; + bNeedZCheck = 0; + + // add constraints of other targets + if( gsfb.fbw > 0 ) { + maxpos = 0x00100000-64*gsfb.fbp; + + // make sure texture is far away from tbp + if( gsfb.fbp < tbp && gsfb.fbp + 0x2000 < tbp) { + maxpos = min(64*(tbp-gsfb.fbp), maxpos); + } + if( prndr != NULL ) { + // offroad uses 0x80 fbp which messes up targets + if( gsfb.fbp + 0x80 < frame.fbp ) { + // special case when double buffering (hamsterball) + maxpos = min(64*(frame.fbp-gsfb.fbp), maxpos); + } + } + if( zbuf.zbp < tbp && !zbuf.zmsk ) { + maxpos = min((tbp-zbuf.zbp)*((zbuf.psm&2)?128:64), maxpos); + } + + // old caching method + if( gsfb.fbp < zbuf.zbp && !zbuf.zmsk ) { // zmsk necessary for KH movie + int temp = 64*(zbuf.zbp-gsfb.fbp);//min( (0x00100000-64*zbuf.zbp) , 64*(zbuf.zbp-gsfb.fbp) ); + maxpos = min(temp, maxpos); + } + + maxpos /= gsfb.fbw; + if( gsfb.psm & 2 ) + maxpos *= 2; + + maxpos = min(gsfb.fbh, maxpos); + maxpos = min(maxmin, maxpos); + //? alteir aris crashes without it + if( maxpos > 256 ) + maxpos &= ~0x1f; + } + else { + prndr = NULL; + pdepth = NULL; + return; + } + + gsfb.psm &= 0xf; // shadow tower + + if( prndr != NULL ) { + + // render target + if( prndr->psm != gsfb.psm ) { + // behavior for dest alpha varies + ResetAlphaVariables(); + } + } + + int fbh = (scissor.y1>>MINMAX_SHIFT)+1; + if( fbh > 2 && (fbh&1) ) fbh -= 1; + + if( !(gsfb.psm&2) || !(g_GameSettings&GAME_FULL16BITRES) ) { + fbh = min(fbh, maxpos); + } + + frame = gsfb; + +// if( fbh > 256 && (fbh % m_Blocks[gsfb.psm].height) <= 2 ) { +// // dragon ball z +// fbh -= fbh%m_Blocks[gsfb.psm].height; +// } + if( !(frame.psm&2) || !(g_GameSettings&GAME_FULL16BITRES) ) + frame.fbh = fbh; + + if( !(frame.psm&2) ) {//|| !(g_GameSettings&GAME_FULL16BITRES) ) { + if( frame.fbh >= 512 ) { + // neopets hack + maxmin = min(maxmin, frame.fbh); + frame.fbh = maxmin; + } + } + + // ffxii hack to stop resolving + if( !(frame.psm&2) || !(g_GameSettings&GAME_FULL16BITRES) ) { + if( frame.fbp >= 0x3000 && fbh >= 0x1a0 ) { + int endfbp = frame.fbp + frame.fbw*fbh/((gsfb.psm&2)?128:64); + + // see if there is a previous render target in the way, reduce + for(CRenderTargetMngr::MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) { + if( itnew->second->fbp > frame.fbp && endfbp > itnew->second->fbp ) { + endfbp = itnew->second->fbp; + } + } + + frame.fbh = (endfbp-frame.fbp)*((gsfb.psm&2)?128:64)/frame.fbw; + } + } + + CRenderTarget* pprevrndr = prndr; + CDepthTarget* pprevdepth = pdepth; + + // reset so that Resolve doesn't call Flush + prndr = NULL; + pdepth = NULL; + + CRenderTarget* pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert( pnewtarg != NULL ); + + // pnewtarg->fbh >= 0x1c0 needed for ffx + if( pnewtarg->fbh >= 0x1c0 && pnewtarg->fbh > frame.fbh && zbuf.zbp < tbp && !zbuf.zmsk ) { + // check if zbuf is in the way of the texture (suikoden5) + int maxallowedfbh = (tbp-zbuf.zbp)*((zbuf.psm&2)?128:64) / gsfb.fbw; + if( gsfb.psm & 2 ) + maxallowedfbh *= 2; + + if( pnewtarg->fbh > maxallowedfbh+32 ) { // +32 needed for ffx2 + // destroy and recreate + s_RTs.DestroyAllTargs(0, 0x100, pnewtarg->fbw); + pnewtarg = s_RTs.GetTarg(frame, 0, maxmin); + assert( pnewtarg != NULL ); + } + } + + PRIM_LOG("frame_%d: fbp=0x%x fbw=%d fbh=%d(%d) psm=0x%x fbm=0x%x\n", ictx, gsfb.fbp, gsfb.fbw, gsfb.fbh, pnewtarg->fbh, gsfb.psm, gsfb.fbm); + + if( (pprevrndr != pnewtarg) || (prndr != NULL && (prndr->status & CRenderTarget::TS_NeedUpdate)) ) + bChanged = 1; + + prndr = pnewtarg; + + // update z + frameInfo tempfb; + tempfb.fbw = prndr->fbw; + tempfb.fbp = zbuf.zbp; + tempfb.psm = zbuf.psm; + tempfb.fbh = prndr->fbh; + if( zbuf.psm == 0x31 ) tempfb.fbm = 0xff000000; + else tempfb.fbm = 0; + + // check if there is a target that exactly aligns with zbuf (zbuf can be cleared this way, gunbird 2) + //u32 key = zbuf.zbp|(frame.fbw<<16); + //CRenderTargetMngr::MAPTARGETS::iterator it = s_RTs.mapTargets.find(key); +// if( it != s_RTs.mapTargets.end() ) { +//#ifdef _DEBUG +// printf("zbuf resolve\n"); +//#endif +// if( it->second->status & CRenderTarget::TS_Resolved ) +// it->second->Resolve(); +// } + + GL_REPORT_ERRORD(); + CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(tempfb, CRenderTargetMngr::TO_DepthBuffer | + CRenderTargetMngr::TO_StrictHeight|(zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), + GET_MAXHEIGHT(zbuf.zbp, gsfb.fbw, 0)); + assert( pnewdepth != NULL && prndr != NULL ); + assert( pnewdepth->fbh == prndr->fbh ); + + if( (pprevdepth != pnewdepth) || (pdepth != NULL && (pdepth->status & CRenderTarget::TS_NeedUpdate)) ) + bChanged |= 2; + + pdepth = pnewdepth; + + if( prndr->status & CRenderTarget::TS_NeedConvert32) { + if( pdepth->pdepth != 0 ) + pdepth->SetDepthStencilSurface(); + prndr->fbh *= 2; + prndr->ConvertTo32(); + prndr->status &= ~CRenderTarget::TS_NeedConvert32; + } + else if( prndr->status & CRenderTarget::TS_NeedConvert16 ) { + if( pdepth->pdepth != 0 ) + pdepth->SetDepthStencilSurface(); + prndr->fbh /= 2; + prndr->ConvertTo16(); + prndr->status &= ~CRenderTarget::TS_NeedConvert16; + } + } + else if( bNeedZCheck ) { + + bNeedZCheck = 0; + CDepthTarget* pprevdepth = pdepth; + pdepth = NULL; + + if( prndr != NULL && gsfb.fbw > 0 ) { + // just z changed + frameInfo f; + f.fbp = zbuf.zbp; + f.fbw = prndr->fbw; + f.fbh = prndr->fbh; + f.psm = zbuf.psm; + + if( zbuf.psm == 0x31 ) f.fbm = 0xff000000; + else f.fbm = 0; + CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer|CRenderTargetMngr::TO_StrictHeight| + (zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), GET_MAXHEIGHT(zbuf.zbp, gsfb.fbw, 0)); + + assert( pnewdepth != NULL && prndr != NULL ); + assert( pnewdepth->fbh == prndr->fbh ); + + if( (pprevdepth != pnewdepth) || (pdepth != NULL && (pdepth->status & CRenderTarget::TS_NeedUpdate)) ) + bChanged = 2; + + pdepth = pnewdepth; + } + } + + if( prndr != NULL ) + SetContextTarget(ictx); + + //if( prndr != NULL && ictx == icurctx) + //else bVarsSetTarg = 0; + +// if( prndr != NULL && bChanged ) { +// if( ictx == icurctx ) SetContextTarget(icurctx); +// else +// bVarsSetTarg = 0; +// } +} + +void ZeroGS::VB::FlushTexData() +{ + assert( bNeedTexCheck ); + + bNeedTexCheck = 0; + + u32 psm = (uNextTex0Data[0] >> 20) & 0x3f; + if( psm == 9 ) psm = 1; // hmm..., ffx intro menu + + // don't update unless necessary + if( uCurTex0Data[0] == uNextTex0Data[0] && (uCurTex0Data[1]&0x1f) == (uNextTex0Data[1]&0x1f) ) { + + if( PSMT_ISCLUT(psm) ) { + + // have to write the CLUT again if changed + if( (uCurTex0Data[1]&0x1fffffe0) == (uNextTex0Data[1]&0x1fffffe0) ) { + + if( uNextTex0Data[1]&0xe0000000 ) { + //ZeroGS::Flush(ictx); + ZeroGS::texClutWrite(ictx); + // invalidate to make sure target didn't change! + bVarsTexSync = FALSE; + } + + return; + } + + if( (uNextTex0Data[1]&0xe0000000) == 0 ) { + + if( (uCurTex0Data[1]&0x1ff10000) != (uNextTex0Data[1]&0x1ff10000) ) + ZeroGS::Flush(ictx); + + // clut isn't going to be loaded so can ignore, but at least update CSA and CPSM! + uCurTex0Data[1] = (uCurTex0Data[1]&0xe087ffff)|(uNextTex0Data[1]&0x1f780000); + + if( tex0.cpsm <= 1 ) tex0.csa = (uNextTex0Data[1] >> 24) & 0xf; + else tex0.csa = (uNextTex0Data[1] >> 24) & 0x1f; + + tex0.cpsm = (uNextTex0Data[1] >> 19) & 0xe; + ZeroGS::texClutWrite(ictx); + + bVarsTexSync = FALSE; + return; + } + + // fall through + } + else { + //bVarsTexSync = FALSE; + return; + } + } + + ZeroGS::Flush(ictx); + bVarsTexSync = FALSE; + bTexConstsSync = FALSE; + + uCurTex0Data[0] = uNextTex0Data[0]; + uCurTex0Data[1] = uNextTex0Data[1]; + + tex0.tbp0 = (uNextTex0Data[0] & 0x3fff); + tex0.tbw = ((uNextTex0Data[0] >> 14) & 0x3f) * 64; + tex0.psm = psm; + tex0.tw = (uNextTex0Data[0] >> 26) & 0xf; + if (tex0.tw > 10) tex0.tw = 10; + tex0.tw = 1<> 30) & 0x3) | ((uNextTex0Data[1] & 0x3) << 2); + if (tex0.th > 10) tex0.th = 10; + tex0.th = 1<> 2) & 0x1; + tex0.tfx = (uNextTex0Data[1] >> 3) & 0x3; + + ZeroGS::fiTexWidth[ictx] = (1/16.0f)/ tex0.tw; + ZeroGS::fiTexHeight[ictx] = (1/16.0f) / tex0.th; + + if (tex0.tbw == 0) tex0.tbw = 64; + + if( PSMT_ISCLUT(psm) ) { + tex0.cbp = ((uNextTex0Data[1] >> 5) & 0x3fff); + tex0.cpsm = (uNextTex0Data[1] >> 19) & 0xe; + tex0.csm = (uNextTex0Data[1] >> 23) & 0x1; + + if( tex0.cpsm <= 1 ) tex0.csa = (uNextTex0Data[1] >> 24) & 0xf; + else tex0.csa = (uNextTex0Data[1] >> 24) & 0x1f; + + tex0.cld = (uNextTex0Data[1] >> 29) & 0x7; + + ZeroGS::texClutWrite(ictx); + } +} + +// does one time only initializing/destruction +class ZeroGSInit +{ +public: + ZeroGSInit() { + // clear + g_pbyGSMemory = (u8*)_aligned_malloc(0x00410000, 1024); // leave some room for out of range accesses (saves on the checks) + memset(g_pbyGSMemory, 0, 0x00410000); + + g_pbyGSClut = (u8*)_aligned_malloc(256*8, 1024); // need 512 alignment! + memset(g_pbyGSClut, 0, 256*8); + +#ifndef _WIN32 + memset(&GLWin, 0, sizeof(GLWin)); +#endif + } + ~ZeroGSInit() { + _aligned_free(g_pbyGSMemory); g_pbyGSMemory = NULL; + _aligned_free(g_pbyGSClut); g_pbyGSClut = NULL; + } +}; + +static ZeroGSInit s_ZeroGSInit; + +#ifdef _WIN32 +void __stdcall glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#else +void APIENTRY glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4) +#endif +{ + glBlendFunc(e1, e2); +} + +#ifdef _WIN32 +void __stdcall glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#else +void APIENTRY glBlendEquationSeparateDummy(GLenum e1, GLenum e2) +#endif +{ + glBlendEquation(e1); +} + +void HandleCgError(CGcontext ctx, CGerror err, void* appdata) +{ + ERROR_LOG("Cg error: %s\n", cgGetErrorString(err)); + const char* listing = cgGetLastListing(g_cgcontext); + if( listing != NULL ) { + printf(" last listing: %s\n", listing); + } +// int loc; +// const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); +// if( pstr != NULL ) printf("error at: %s\n"); +// glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); +// printf("pos: %d\n", loc); +} + +void ZeroGS::HandleGLError() +{ + // check the error status of this framebuffer */ + GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort + if( error != 0 ) { + int w, h; + GLint fmt; + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w); + glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h); + + switch(error) + { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ERROR_LOG("Error! missing a required image/buffer attachment!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + ERROR_LOG("Error! has no images/buffers attached!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: + ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + ERROR_LOG("Error! colorbuffer attachments have different types!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); + break; + default: + ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT() for %s!\n"); + break; + } + } +} + +#define GL_LOADFN(name) { \ + if( (*(void**)&name = (void*)wglGetProcAddress(#name)) == NULL ) { \ + ERROR_LOG("Failed to find %s, exiting\n", #name); \ + } \ +} \ + +bool ZeroGS::IsGLExt( const char* szTargetExtension ) +{ + return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end(); +} + +bool ZeroGS::Create(int _width, int _height) +{ + GLenum err = GL_NO_ERROR; + bool bSuccess = true; + int i; + + Destroy(1); + GSStateReset(); + + cgSetErrorHandler(HandleCgError, NULL); + g_RenderFormatType = RFT_float16; + + nBackbufferWidth = _width; + nBackbufferHeight = _height; + fiRendWidth = 1.0f / nBackbufferWidth; + fiRendHeight = 1.0f / nBackbufferHeight; + +#ifdef _WIN32 + GLuint PixelFormat; // Holds The Results After Searching For A Match + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + if (conf.options & GSOPTION_FULLSCREEN) { + nBackbufferWidth = rcdesktop.right - rcdesktop.left; + nBackbufferHeight = rcdesktop.bottom - rcdesktop.top; + + DEVMODE dmScreenSettings; + memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); + dmScreenSettings.dmSize=sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = nBackbufferWidth; + dmScreenSettings.dmPelsHeight = nBackbufferHeight; + dmScreenSettings.dmBitsPerPel = 32; + dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) + { + if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) + conf.options &= ~GSOPTION_FULLSCREEN; + else + return false; + } + } + else { + // change to default resolution + ChangeDisplaySettings(NULL, 0); + } + + if( conf.options & GSOPTION_FULLSCREEN) { + dwExStyle=WS_EX_APPWINDOW; + dwStyle=WS_POPUP; + ShowCursor(FALSE); + } + else { + dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle=WS_OVERLAPPEDWINDOW; + } + + RECT rc; + rc.left = 0; rc.top = 0; + rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + SetWindowPos(GShwnd, NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION|SWP_NOZORDER); + + PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + 32, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // 8bit Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 24, // 24Bit Z-Buffer (Depth Buffer) + 8, // 8bit Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(GShwnd))) { + MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) { + MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!SetPixelFormat(hDC,PixelFormat,&pfd)) { + MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if (!(hRC=wglCreateContext(hDC))) { + MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(!wglMakeCurrent(hDC,hRC)) { + MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); + return false; + } + +#else + XVisualInfo *vi; + Colormap cmap; + int dpyWidth, dpyHeight; + int glxMajorVersion, glxMinorVersion; + int vidModeMajorVersion, vidModeMinorVersion; + Atom wmDelete; + Window winDummy; + unsigned int borderDummy; + + // attributes for a single buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None}; + + // attributes for a double buffered visual in RGBA format with at least + // 8 bits per color and a 24 bit depth buffer + int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_DEPTH_SIZE, 24, + None }; + + GLWin.fs = !!(conf.options & GSOPTION_FULLSCREEN); + + /* get an appropriate visual */ + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); + if (vi == NULL) { + vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); + GLWin.doubleBuffered = False; + ERROR_LOG("Only Singlebuffered Visual!\n"); + } + else { + GLWin.doubleBuffered = True; + ERROR_LOG("Got Doublebuffered Visual!\n"); + } + + glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); + ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); + /* create a GLX context */ + GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE); + /* create a color map */ + cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + vi->visual, AllocNone); + GLWin.attr.colormap = cmap; + GLWin.attr.border_pixel = 0; + + // get a connection + XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); + + if (GLWin.fs) { + + XF86VidModeModeInfo **modes = NULL; + int modeNum = 0; + int bestMode = 0; + + // set best mode to current + bestMode = 0; + ERROR_LOG("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion, vidModeMinorVersion); + XF86VidModeGetAllModeLines(GLWin.dpy, GLWin.screen, &modeNum, &modes); + + if( modeNum > 0 && modes != NULL ) { + /* save desktop-resolution before switching modes */ + GLWin.deskMode = *modes[0]; + /* look for mode with requested resolution */ + for (i = 0; i < modeNum; i++) { + if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height)) { + bestMode = i; + } + } + + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, modes[bestMode]); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + ERROR_LOG("Resolution %dx%d\n", dpyWidth, dpyHeight); + XFree(modes); + + /* create a fullscreen window */ + GLWin.attr.override_redirect = True; + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &GLWin.attr); + XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); + XMapRaised(GLWin.dpy, GLWin.win); + XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, GLWin.win, None, CurrentTime); + } + else { + ERROR_LOG("Failed to start fullscreen. If you received the \n" + "\"XFree86-VidModeExtension\" extension is missing, add\n" + "Load \"extmod\"\n" + "to your X configuration file (under the Module Section)\n"); + GLWin.fs = 0; + } + } + + + if( !GLWin.fs ) { + + //XRootWindow(dpy,screen) + //int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; + //int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; + + // create a window in window mode + GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + StructureNotifyMask; + GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), + 0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); + // only set window title and handle wm_delete_events if in windowed mode + wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); + XSetStandardProperties(GLWin.dpy, GLWin.win, "ZeroGS", + "ZeroGS", None, NULL, 0, NULL); + XMapRaised(GLWin.dpy, GLWin.win); + } + + // connect the glx-context to the window + glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); + XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, + &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); + ERROR_LOG("Depth %d\n", GLWin.depth); + if (glXIsDirect(GLWin.dpy, GLWin.ctx)) + ERROR_LOG("you have Direct Rendering!\n"); + else + ERROR_LOG("no Direct Rendering possible!\n"); + + // better for pad plugin key input (thc) + XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | KeyReleaseMask | + ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | + FocusChangeMask ); + +#endif + + // fill the opengl extension map + const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); + if( ptoken == NULL ) return false; + + int prevlog = conf.log; + conf.log = 1; + __Log("Supported OpenGL Extensions:\n%s\n", ptoken); // write to the log file + conf.log = prevlog; + + // insert all exts into mapGLExtensions + + const char* pend = NULL; + + while(ptoken != NULL ) { + pend = strchr(ptoken, ' '); + + if( pend != NULL ) { + mapGLExtensions[string(ptoken, pend-ptoken)]; + } + else { + mapGLExtensions[string(ptoken)]; + break; + } + + ptoken = pend; + while(*ptoken == ' ') ++ptoken; + } + + s_nFullscreen = (conf.options & GSOPTION_FULLSCREEN) ? 1 : 0; + conf.mrtdepth = 0; // for now + + if( !IsGLExt("GL_EXT_framebuffer_object") ) { + ERROR_LOG("*********\nZeroGS: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nZeroGS: *********\n"); + bSuccess = false; + } + if( !IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL ) { + ERROR_LOG("*********\nZeroGS: OGL WARNING: Need GL_EXT_blend_equation_separate\nZeroGS: *********\n"); + zgsBlendEquationSeparateEXT = glBlendEquationSeparateDummy; + } + else { + zgsBlendEquationSeparateEXT = glBlendEquationSeparateEXT; + } + + if( !IsGLExt("GL_EXT_blend_func_separate") || glBlendFuncSeparateEXT == NULL ) { + ERROR_LOG("*********\nZeroGS: OGL WARNING: Need GL_EXT_blend_func_separate\nZeroGS: *********\n"); + zgsBlendFuncSeparateEXT = glBlendFuncSeparateDummy; + } + else { + zgsBlendFuncSeparateEXT = glBlendFuncSeparateEXT; + } + + if( !IsGLExt("GL_EXT_secondary_color") ) { + ERROR_LOG("*********\nZeroGS: OGL WARNING: Need GL_EXT_secondary_color\nZeroGS: *********\n"); + bSuccess = false; + } + + if( !IsGLExt("GL_ARB_draw_buffers") && !IsGLExt("GL_ATI_draw_buffers") ) { + ERROR_LOG("*********\nZeroGS: OGL WARNING: multiple render targets not supported, some effects might look bad\nZeroGS: *********\n"); + conf.mrtdepth = 0; + } + + if( !bSuccess ) + return false; + + if( g_GameSettings & GAME_32BITTARGS ) { + g_RenderFormatType = RFT_byte8; + ERROR_LOG("Setting 32 bit render target\n"); + } + else { + if( !IsGLExt("GL_NV_float_buffer") && !IsGLExt("GL_ARB_color_buffer_float") && !IsGLExt("ATI_pixel_format_float") ) { + ERROR_LOG("******\nZeroGS: GS WARNING: Floating point render targets not supported, switching to 32bit\nZeroGS: *********\n"); + g_RenderFormatType = RFT_byte8; + } + } + g_RenderFormatType = RFT_byte8; + +#ifdef _WIN32 + if( IsGLExt("WGL_EXT_swap_control") || IsGLExt("EXT_swap_control") ) + wglSwapIntervalEXT(0); +#else + if( IsGLExt("GLX_SGI_swap_control") ) { + _PFNSWAPINTERVAL swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapInterval"); + if( !swapinterval ) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalSGI"); + if( !swapinterval ) + swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalEXT"); + + if( swapinterval ) + swapinterval(0); + else + ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); + } +#endif + + // check the max texture width and height + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth); + g_MaxTexHeight = g_MaxTexWidth; + GPU_TEXWIDTH = g_MaxTexWidth/8; + g_fiGPU_TEXWIDTH = 1.0f / GPU_TEXWIDTH; + +#ifdef RELEASE_TO_PUBLIC +#ifdef _WIN32 + HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA); + assert( hShaderSrc != NULL ); + HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc); + assert( hShaderGlob != NULL ); + s_lpShaderResources = (u8*)LockResource(hShaderGlob); +#else + FILE* fres = fopen("ps2hw.dat", "rb"); + if( fres == NULL ) { + fres = fopen("plugins/ps2hw.dat", "rb"); + if( fres == NULL ) { + ERROR_LOG("Cannot find ps2hw.dat in working directory. Exiting\n"); + return false; + } + } + fseek(fres, 0, SEEK_END); + size_t s = ftell(fres); + s_lpShaderResources = new u8[s+1]; + fseek(fres, 0, SEEK_SET); + fread(s_lpShaderResources, s, 1, fres); + s_lpShaderResources[s] = 0; +#endif + +#else + +#ifndef _WIN32 + // test if ps2hw.fx exists + char tempstr[255]; + char curwd[255]; + getcwd(curwd, ARRAY_SIZE(curwd)); + + strcpy(tempstr, "../plugins/gs/zerogs/opengl/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + FILE* f = fopen(EFFECT_NAME, "r"); + if( f == NULL ) { + + strcpy(tempstr, "../../plugins/gs/zerogs/opengl/"); + sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr); + f = fopen(EFFECT_NAME, "r"); + + if( f == NULL ) { + ERROR_LOG("Failed to find %s, try compiling a non-devbuild\n", EFFECT_NAME); + return false; + } + } + + fclose(f); + + sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr); + sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR); +#endif + +#endif // RELEASE_TO_PUBLIC + + // load the effect, find the best profiles (if any) + if( cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE ) { + ERROR_LOG("arbvp1 not supported\n"); + return false; + } + if( cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE ) { + ERROR_LOG("arbfp1 not supported\n"); + return false; + } + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + s_srcrgb = s_dstrgb = s_srcalpha = s_dstalpha = GL_ONE; + + GL_LOADFN(glIsRenderbufferEXT); + GL_LOADFN(glBindRenderbufferEXT); + GL_LOADFN(glDeleteRenderbuffersEXT); + GL_LOADFN(glGenRenderbuffersEXT); + GL_LOADFN(glRenderbufferStorageEXT); + GL_LOADFN(glGetRenderbufferParameterivEXT); + GL_LOADFN(glIsFramebufferEXT); + GL_LOADFN(glBindFramebufferEXT); + GL_LOADFN(glDeleteFramebuffersEXT); + GL_LOADFN(glGenFramebuffersEXT); + GL_LOADFN(glCheckFramebufferStatusEXT); + GL_LOADFN(glFramebufferTexture1DEXT); + GL_LOADFN(glFramebufferTexture2DEXT); + GL_LOADFN(glFramebufferTexture3DEXT); + GL_LOADFN(glFramebufferRenderbufferEXT); + GL_LOADFN(glGetFramebufferAttachmentParameterivEXT); + GL_LOADFN(glGenerateMipmapEXT); + + if( IsGLExt("GL_ARB_draw_buffers") ) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers"); + else if( IsGLExt("GL_ATI_draw_buffers") ) + glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffersATI"); + + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + glGenFramebuffersEXT( 1, &s_uFramebuffer); + if( s_uFramebuffer == 0 ) { + ERROR_LOG("failed to create the renderbuffer\n"); + } + + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + glDrawBuffers(1, s_drawbuffers); + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + font_p = new RasterFont(); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + // init draw fns + drawfn[0] = KickPoint; + drawfn[1] = KickLine; + drawfn[2] = KickLine; + drawfn[3] = KickTriangle; + drawfn[4] = KickTriangle; + drawfn[5] = KickTriangleFan; + drawfn[6] = KickSprite; + drawfn[7] = KickDummy; + + SetAA(conf.aa); + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + + //g_GameSettings |= 0;//GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE; + //s_bWriteDepth = TRUE; + + GL_BLEND_ALL(GL_ONE, GL_ONE, GL_ONE, GL_ONE); + + glViewport(0,0,nBackbufferWidth,nBackbufferHeight); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations + + glGenTextures(1, &ptexLogo); + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexLogo); + +#ifdef _WIN32 + HRSRC hBitmapSrc = FindResource(hInst, MAKEINTRESOURCE(IDB_ZEROGSLOGO), RT_BITMAP); + assert( hBitmapSrc != NULL ); + HGLOBAL hBitmapGlob = LoadResource(hInst, hBitmapSrc); + assert( hBitmapGlob != NULL ); + PBITMAPINFO pinfo = (PBITMAPINFO)LockResource(hBitmapGlob); + + glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, 0, pinfo->bmiHeader.biBitCount==32?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, (u8*)pinfo+pinfo->bmiHeader.biSize); + nLogoWidth = pinfo->bmiHeader.biWidth; + nLogoHeight = pinfo->bmiHeader.biHeight; + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +#else +#endif + + GL_REPORT_ERROR(); + + g_nCurVBOIndex = 0; + g_vboBuffers.resize(VB_NUMBUFFERS); + glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + for(i = 0; i < (int)g_vboBuffers.size(); ++i) { + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]); + glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW); + } + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + // create the blocks texture + g_fBlockMult = 1; + + vector vBlockData, vBilinearData; + BLOCK::FillBlocks(vBlockData, vBilinearData, 1); + + glGenTextures(1, &ptexBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBlocks); + + g_internalFloatFmt = GL_ALPHA_FLOAT32_ATI; + g_internalRGBAFloatFmt = GL_RGBA_FLOAT32_ATI; + g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI; + + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_FLOAT, &vBlockData[0]); + + if( glGetError() != GL_NO_ERROR ) { + // try different internal format + g_internalFloatFmt = GL_FLOAT_R32_NV; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, &vBlockData[0]); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + if( glGetError() != GL_NO_ERROR ) { + + // error, resort to 16bit + g_fBlockMult = 65535.0f*(float)g_fiGPU_TEXWIDTH; + + BLOCK::FillBlocks(vBlockData, vBilinearData, 0); + glTexImage2D(GL_TEXTURE_2D, 0, 2, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_R, GL_UNSIGNED_SHORT, &vBlockData[0]); + if( glGetError() != GL_NO_ERROR ) + return false; + } + else { + // fill in the bilinear blocks + glGenTextures(1, &ptexBilinearBlocks); + glBindTexture(GL_TEXTURE_2D, ptexBilinearBlocks); + glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]); + + if( glGetError() != GL_NO_ERROR ) { + g_internalRGBAFloatFmt = GL_FLOAT_RGBA32_NV; + g_internalRGBAFloat16Fmt = GL_FLOAT_RGBA16_NV; + glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]); + B_G(glGetError() == GL_NO_ERROR, return false); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + + float fpri = 1; + glPrioritizeTextures(1, &ptexBlocks, &fpri); + if( ptexBilinearBlocks != 0 ) + glPrioritizeTextures(1, &ptexBilinearBlocks, &fpri); + + GL_REPORT_ERROR(); + + // fill a simple rect + glGenBuffers(1, &vboRect); + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + + vector verts(4); + VertexGPU* pvert = &verts[0]; + pvert->x = -0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 0; pvert++; + pvert->x = 0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 0; pvert++; + pvert->x = -0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 1; pvert++; + pvert->x = 0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 1; pvert++; + glBufferDataARB(GL_ARRAY_BUFFER, 4*sizeof(VertexGPU), &verts[0], GL_STATIC_DRAW); + + // setup the default vertex declaration + glEnableClientState(GL_VERTEX_ARRAY); + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_SECONDARY_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + GL_REPORT_ERROR(); + + // some cards don't support this +// glClientActiveTexture(GL_TEXTURE0); +// glEnableClientState(GL_TEXTURE_COORD_ARRAY); +// glTexCoordPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); + + // create the conversion textures + glGenTextures(1, &ptexConv16to32); + glBindTexture(GL_TEXTURE_2D, ptexConv16to32); + + vector conv16to32data(256*256); + for(i = 0; i < 256*256; ++i) { + u32 tempcol = RGBA16to32(i); + // have to flip r and b + conv16to32data[i] = (tempcol&0xff00ff00)|((tempcol&0xff)<<16)|((tempcol&0xff0000)>>16); + } + glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv16to32data[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + vector conv32to16data(32*32*32); + + glGenTextures(1, &ptexConv32to16); + glBindTexture(GL_TEXTURE_3D, ptexConv32to16); + u32* dst = &conv32to16data[0]; + for(i = 0; i < 32; ++i) { + for(int j = 0; j < 32; ++j) { + for(int k = 0; k < 32; ++k) { + u32 col = (i<<10)|(j<<5)|k; + *dst++ = ((col&0xff)<<16)|(col&0xff00); + } + } + } + glTexImage3D(GL_TEXTURE_3D, 0, 4, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv32to16data[0]); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + g_cgcontext = cgCreateContext(); + + cgvProf = CG_PROFILE_ARBVP1; + cgfProf = CG_PROFILE_ARBFP1; + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); + cgGLSetOptimalOptions(cgvProf); + cgGLSetOptimalOptions(cgfProf); + + cgGLSetManageTextureParameters(g_cgcontext, CG_FALSE); + //cgSetAutoCompile(g_cgcontext, CG_COMPILE_IMMEDIATE); + + g_fparamFogColor = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[0] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + g_vparamPosXY[1] = cgCreateParameter(g_cgcontext, CG_FLOAT4); + + ERROR_LOG("Creating effects\n"); + B_G(LoadEffects(), return false); + + g_bDisplayMsg = 0; + + + // create a sample shader + clampInfo temp; + memset(&temp, 0, sizeof(temp)); + temp.wms = 3; temp.wmt = 3; + + g_nPixelShaderVer = SHADER_ACCURATE; + // test + bool bFailed; + FRAGMENTSHADER* pfrag = LoadShadeEffect(0, 1, 1, 1, 1, temp, 0, &bFailed); + if( bFailed || pfrag == NULL ) { + g_nPixelShaderVer = SHADER_ACCURATE|SHADER_REDUCED; + + pfrag = LoadShadeEffect(0, 0, 1, 1, 0, temp, 0, &bFailed); + if( pfrag != NULL ) + cgGLLoadProgram(pfrag->prog); + if( bFailed || pfrag == NULL || cgGetError() != CG_NO_ERROR ) { + g_nPixelShaderVer = SHADER_REDUCED; + ERROR_LOG("Basic shader test failed\n"); + } + } + + g_bDisplayMsg = 1; + if( g_nPixelShaderVer & SHADER_REDUCED ) + conf.bilinear = 0; + + ERROR_LOG("Creating extra effects\n"); + B_G(LoadExtraEffects(), return false); + + ERROR_LOG("using %s shaders\n", g_pShaders[g_nPixelShaderVer]); + + GL_REPORT_ERROR(); + if( err != GL_NO_ERROR ) bSuccess = false; + + glDisable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + glBlendColorEXT(0, 0, 0, 0.5f); + + glDisable(GL_CULL_FACE); + + // points + glPointSize(1.0f); + g_nDepthBias = 0; + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(0, 1); + + vb[0].Init(VB_BUFFERSIZE); + vb[1].Init(VB_BUFFERSIZE); + g_bSaveFlushedFrame = 1; + + g_vsprog = g_psprog = 0; + + return glGetError() == GL_NO_ERROR && bSuccess; +} + +void ZeroGS::Destroy(BOOL bD3D) +{ + if( s_aviinit ) { + StopCapture(); + +#ifdef _WIN32 + STOP_AVI(); +#else // linux + //TODO +#endif + ERROR_LOG("zerogs.avi stopped"); + s_aviinit = 0; + } + + g_MemTargs.Destroy(); + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + SAFE_RELEASE_TEX(s_ptexInterlace); + SAFE_RELEASE_TEX(ptexBlocks); + SAFE_RELEASE_TEX(ptexBilinearBlocks); + SAFE_RELEASE_TEX(ptexConv16to32); + SAFE_RELEASE_TEX(ptexConv32to16); + + vb[0].Destroy(); + vb[1].Destroy(); + + if( g_vboBuffers.size() > 0 ) { + glDeleteBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]); + g_vboBuffers.clear(); + } + g_nCurVBOIndex = 0; + + for(int i = 0; i < ARRAY_SIZE(pvs); ++i) { + SAFE_RELEASE_PROG(pvs[i]); + } + for(int i = 0; i < ARRAY_SIZE(ppsRegular); ++i) { + SAFE_RELEASE_PROG(ppsRegular[i].prog); + } + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + + SAFE_RELEASE_PROG(pvsBitBlt.prog); + SAFE_RELEASE_PROG(ppsBitBlt[0].prog); SAFE_RELEASE_PROG(ppsBitBlt[1].prog); + SAFE_RELEASE_PROG(ppsBitBltDepth.prog); + SAFE_RELEASE_PROG(ppsCRTCTarg[0].prog); SAFE_RELEASE_PROG(ppsCRTCTarg[1].prog); + SAFE_RELEASE_PROG(ppsCRTC[0].prog); SAFE_RELEASE_PROG(ppsCRTC[1].prog); + SAFE_RELEASE_PROG(ppsCRTC24[0].prog); SAFE_RELEASE_PROG(ppsCRTC24[1].prog); + SAFE_RELEASE_PROG(ppsOne.prog); + + SAFE_DELETE(font_p); + +#ifdef _WIN32 + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts? + { + MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + } + hRC=NULL; // Set RC To NULL + } + + if (hDC && !ReleaseDC(GShwnd,hDC)) // Are We Able To Release The DC + { + MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); + hDC=NULL; // Set DC To NULL + } +#else // linux + if (GLWin.ctx) + { + if (!glXMakeCurrent(GLWin.dpy, None, NULL)) + { + ERROR_LOG("Could not release drawing context.\n"); + } + glXDestroyContext(GLWin.dpy, GLWin.ctx); + GLWin.ctx = NULL; + } + /* switch back to original desktop resolution if we were in fs */ + if( GLWin.dpy != NULL ) { + if (GLWin.fs) { + XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode); + XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0); + } + } +#endif + + mapGLExtensions.clear(); +} + +void ZeroGS::GSStateReset() +{ + icurctx = -1; + + for(int i = 0; i < 2; ++i) { + vb[i].Destroy(); + memset(&vb[i], 0, SIZEOF_VB); + + vb[i].tex0.tw = 1; + vb[i].tex0.th = 1; + vb[i].scissor.x1 = 639; + vb[i].scissor.y1 = 479; + vb[i].tex0.tbw = 64; + vb[i].Init(VB_BUFFERSIZE); + } + + s_RangeMngr.Clear(); + g_MemTargs.Destroy(); + s_RTs.Destroy(); + s_DepthRTs.Destroy(); + s_BitwiseTextures.Destroy(); + + vb[0].ictx = 0; + vb[1].ictx = 1; +} + +void ZeroGS::AddMessage(const char* pstr, u32 ms) +{ + listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms)); +} + +void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color) +{ + cgGLDisableProfile(cgvProf); + cgGLDisableProfile(cgfProf); + + glColor3f(((color>>16)&0xff)/255.0f, ((color>>8)&0xff)/255.0f, (color&0xff)/255.0f); + + font_p->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0); + cgGLEnableProfile(cgvProf); + cgGLEnableProfile(cgfProf); +} + +void ZeroGS::ChangeWindowSize(int nNewWidth, int nNewHeight) +{ + nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; + nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; + + if( !(conf.options & GSOPTION_FULLSCREEN) ) { + conf.width = nNewWidth; + conf.height = nNewHeight; + //SaveConfig(); + } +} + +void ZeroGS::SetChangeDeviceSize(int nNewWidth, int nNewHeight) +{ + s_nNewWidth = nNewWidth; + s_nNewHeight = nNewHeight; + + if( !(conf.options & GSOPTION_FULLSCREEN) ) { + conf.width = nNewWidth; + conf.height = nNewHeight; + //SaveConfig(); + } +} + +void ZeroGS::Reset() +{ + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + vb[0].nCount = 0; + vb[1].nCount = 0; + + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + icurctx = -1; + g_vsprog = g_psprog = 0; + + GSStateReset(); + Destroy(0); + + drawfn[0] = KickDummy; + drawfn[1] = KickDummy; + drawfn[2] = KickDummy; + drawfn[3] = KickDummy; + drawfn[4] = KickDummy; + drawfn[5] = KickDummy; + drawfn[6] = KickDummy; + drawfn[7] = KickDummy; +} + +void ZeroGS::ChangeDeviceSize(int nNewWidth, int nNewHeight) +{ + int oldscreen = s_nFullscreen; + + int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; + if( !Create(nNewWidth&~7, nNewHeight&~7) ) { + ERROR_LOG("Failed to recreate, changing to old\n"); + if( !Create(oldwidth, oldheight) ) { + SysMessage("failed to create dev, exiting...\n"); + exit(0); + } + } + + for(int i = 0; i < 2; ++i) { + vb[i].bNeedFrameCheck = vb[i].bNeedZCheck = 1; + vb[i].CheckFrame(0); + } + + if( oldscreen && !(conf.options & GSOPTION_FULLSCREEN) ) { // if transitioning from full screen + RECT rc; + rc.left = 0; rc.top = 0; + rc.right = conf.width; rc.bottom = conf.height; + +#ifdef _WIN32 + AdjustWindowRect(&rc, conf.winstyle, FALSE); + + RECT rcdesktop; + GetWindowRect(GetDesktopWindow(), &rcdesktop); + + SetWindowLong( GShwnd, GWL_STYLE, conf.winstyle ); + SetWindowPos(GShwnd, HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2, + ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2, + rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); + UpdateWindow(GShwnd); +#else // linux +#endif + } + + assert( vb[0].pBufferData != NULL && vb[1].pBufferData != NULL ); +} + +void ZeroGS::SetAA(int mode) +{ + // need to flush all targets + s_RTs.ResolveAll(); + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + s_AAx = mode > 0; + s_AAy = mode > 1; + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + s_nLastResolveReset = 0; + + vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1; + vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1; + float f = mode > 0 ? 2.0f : 1.0f; + glPointSize(f); +} + +#define SET_UNIFORMPARAM(var, name) { \ + p = cgGetNamedParameter(pf->prog, name); \ + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) \ + pf->var = p; \ +} \ + +void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type) +{ + // uniform parameters + CGparameter p; + + p = cgGetNamedParameter(pf->prog, "g_fFogColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgConnectParameter(g_fparamFogColor, p); + } + + SET_UNIFORMPARAM(sOneColor, "g_fOneColor"); + SET_UNIFORMPARAM(sBitBltZ, "g_fBitBltZ"); + SET_UNIFORMPARAM(sInvTexDims, "g_fInvTexDims"); + SET_UNIFORMPARAM(fTexAlpha2, "fTexAlpha2"); + SET_UNIFORMPARAM(fTexOffset, "g_fTexOffset"); + SET_UNIFORMPARAM(fTexDims, "g_fTexDims"); + SET_UNIFORMPARAM(fTexBlock, "g_fTexBlock"); + SET_UNIFORMPARAM(fClampExts, "g_fClampExts"); + SET_UNIFORMPARAM(fTexWrapMode, "TexWrapMode"); + SET_UNIFORMPARAM(fRealTexDims, "g_fRealTexDims"); + SET_UNIFORMPARAM(fTestBlack, "g_fTestBlack"); + SET_UNIFORMPARAM(fPageOffset, "g_fPageOffset"); + SET_UNIFORMPARAM(fTexAlpha, "fTexAlpha"); + + // textures + p = cgGetNamedParameter(pf->prog, "g_sBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBlocks); + cgGLEnableTextureParameter(p); + } + + // cg parameter usage is wrong, so do it manually + if( type == 3 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv16to32"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv16to32); + cgGLEnableTextureParameter(p); + } + } + else if( type == 4 ) { + p = cgGetNamedParameter(pf->prog, "g_sConv32to16"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexConv32to16); + cgGLEnableTextureParameter(p); + } + } + else { + p = cgGetNamedParameter(pf->prog, "g_sBilinearBlocks"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetTextureParameter(p, ptexBilinearBlocks); + cgGLEnableTextureParameter(p); + } + } + + p = cgGetNamedParameter(pf->prog, "g_sMemory"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sMemory = p; + } + p = cgGetNamedParameter(pf->prog, "g_sSrcFinal"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sFinal = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDX"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDX = p; + } + p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDY"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sBitwiseANDY = p; + } + p = cgGetNamedParameter(pf->prog, "g_sCLUT"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sCLUT = p; + } + p = cgGetNamedParameter(pf->prog, "g_sInterlace"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + //cgGLEnableTextureParameter(p); + pf->sInterlace = p; + } + + // set global shader constants + p = cgGetNamedParameter(pf->prog, "g_fExactColor"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) { + cgGLSetParameter4fv(p, Vector(0.5f, (g_GameSettings&GAME_EXACTCOLOR)?0.9f/256.0f:0.5f/256.0f, 0,1/255.0f)); + } + + p = cgGetNamedParameter(pf->prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(pf->prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f)); + + p = cgGetNamedParameter(pf->prog, "g_fMult"); + if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1/1024.0f, 0.2f/1024.0f, 1/128.0f, 1/512.0f)); +} + +void SetupVertexProgramParameters(CGprogram prog, int context) +{ + CGparameter p; + + p = cgGetNamedParameter(prog, "g_fPosXY"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgConnectParameter(g_vparamPosXY[context], p); + + p = cgGetNamedParameter(prog, "g_fZ"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, g_vdepth); + + Vector vnorm = Vector(g_filog32, 0, 0,0); + p = cgGetNamedParameter(prog, "g_fZNorm"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, vnorm); + + p = cgGetNamedParameter(prog, "g_fBilinear"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f )); + + p = cgGetNamedParameter(prog, "g_fZBias"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f)); + + p = cgGetNamedParameter(prog, "g_fc0"); + if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) + cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f)); +} + +#ifdef RELEASE_TO_PUBLIC + +#define LOAD_VS(Index, prog) { \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + assert( (header) != NULL && (header)->index == (Index) ); \ + prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgvProf, NULL, NULL); \ + if( !cgIsProgram(prog) ) { \ + ERROR_LOG("Failed to load vs %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %d\n", Index); \ + SetupVertexProgramParameters(prog, !!(Index&SH_CONTEXT1)); \ +} \ + +#define LOAD_PS(Index, fragment) { \ + bLoadSuccess = true; \ + assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \ + header = mapShaderResources[Index]; \ + fragment.prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); \ + if( !cgIsProgram(fragment.prog) ) { \ + ERROR_LOG("Failed to load ps %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ERROR_LOG("failed to load program %d\n", Index); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, !!(Index&SH_CONTEXT1), 0); \ +} \ + +bool ZeroGS::LoadEffects() +{ + assert( s_lpShaderResources != NULL ); + + // process the header + u32 num = *(u32*)s_lpShaderResources; + int compressed_size = *(int*)(s_lpShaderResources+4); + int real_size = *(int*)(s_lpShaderResources+8); + int out; + + char* pbuffer = (char*)malloc(real_size); + inf((char*)s_lpShaderResources+12, &pbuffer[0], compressed_size, real_size, &out); + assert(out == real_size); + + s_lpShaderResources = (u8*)pbuffer; + SHADERHEADER* header = (SHADERHEADER*)s_lpShaderResources; + + mapShaderResources.clear(); + while(num-- > 0 ) { + mapShaderResources[header->index] = header; + ++header; + } + + // clear the textures + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + ppsTexture[i].prog = NULL; + } +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +// called +bool ZeroGS::LoadExtraEffects() +{ + SHADERHEADER* header; + bool bLoadSuccess = true; + + const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS }; + + for(int i = 0; i < 4; ++i) { + LOAD_VS(vsshaders[i], pvs[2*i]); + LOAD_VS(vsshaders[i]|SH_CONTEXT1, pvs[2*i+1]); + //if( conf.mrtdepth ) { + LOAD_VS(vsshaders[i]|SH_WRITEDEPTH, pvs[2*i+8]); + LOAD_VS(vsshaders[i]|SH_WRITEDEPTH|SH_CONTEXT1, pvs[2*i+8+1]); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + LOAD_VS(SH_BITBLTVS, pvsBitBlt.prog); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS(SH_REGULARPS, ppsRegular[0]); + LOAD_PS(SH_REGULARFOGPS, ppsRegular[1]); + + if( conf.mrtdepth ) { + LOAD_PS(SH_REGULARPS, ppsRegular[2]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS(SH_REGULARFOGPS, ppsRegular[3]); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS(SH_BITBLTPS, ppsBitBlt[0]); + LOAD_PS(SH_BITBLTAAPS, ppsBitBlt[1]); + if( !bLoadSuccess ) { + ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n"); + LOAD_PS(SH_BITBLTPS, ppsBitBlt[1]); + } + LOAD_PS(SH_BITBLTDEPTHPS, ppsBitBltDepth); + LOAD_PS(SH_CRTCTARGPS, ppsCRTCTarg[0]); + LOAD_PS(SH_CRTCTARGINTERPS, ppsCRTCTarg[1]); + + g_bCRTCBilinear = TRUE; + LOAD_PS(SH_CRTCPS, ppsCRTC[0]); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = FALSE; + LOAD_PS(SH_CRTC_NEARESTPS, ppsCRTC[0]); + LOAD_PS(SH_CRTCINTER_NEARESTPS, ppsCRTC[0]); + } + else { + LOAD_PS(SH_CRTCINTERPS, ppsCRTC[1]); + } + + if( !bLoadSuccess ) + ERROR_LOG("Failed to create CRTC shaders\n"); + + LOAD_PS(SH_CRTC24PS, ppsCRTC24[0]); + LOAD_PS(SH_CRTC24INTERPS, ppsCRTC24[1]); + LOAD_PS(SH_ZEROPS, ppsOne); + LOAD_PS(SH_BASETEXTUREPS, ppsBaseTexture); + LOAD_PS(SH_CONVERT16TO32PS, ppsConvert16to32); + LOAD_PS(SH_CONVERT32TO16PS, ppsConvert32to16); + + return true; +} + +FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + assert( texfilter < NUM_FILTERS ); + + if(g_nPixelShaderVer&SHADER_REDUCED) + texfilter = 0; + assert(!(g_nPixelShaderVer&SHADER_REDUCED) || !exactcolor); + + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + assert( index < ARRAY_SIZE(ppsTexture) ); + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pbFailed != NULL ) *pbFailed = false; + + if( pf->prog != NULL ) + return pf; + + if( (g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index+NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end() ) + index += NUM_SHADERS*SHADER_ACCURATE; + + assert( mapShaderResources.find(index) != mapShaderResources.end() ); + SHADERHEADER* header = mapShaderResources[index]; + if( header == NULL ) + ERROR_LOG("%d %d\n", index, g_nPixelShaderVer); + assert( header != NULL ); + + //printf("shader:\n%s\n", (char*)(s_lpShaderResources + (header)->offset)); + pf->prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); + if( pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR ) { + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + return pf; +// } + } + return pf; + } + + ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#else // not RELEASE_TO_PUBLIC + +#define LOAD_VS(name, prog, shaderver) { \ + prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(prog) ) { \ + ERROR_LOG("Failed to load vs %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(prog); \ + if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %s\n", name); \ + SetupVertexProgramParameters(prog, args[0]==context1); \ +} \ + +#ifdef _DEBUG +#define SET_PSFILENAME(frag, name) frag.filename = name +#else +#define SET_PSFILENAME(frag, name) +#endif + +#define LOAD_PS(name, fragment, shaderver) { \ + bLoadSuccess = true; \ + fragment.prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \ + if( !cgIsProgram(fragment.prog) ) { \ + ERROR_LOG("Failed to load ps %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \ + return false; \ + } \ + cgGLLoadProgram(fragment.prog); \ + if( cgGetError() != CG_NO_ERROR ) { \ + ERROR_LOG("failed to load program %s\n", name); \ + bLoadSuccess = false; \ + } \ + SetupFragmentProgramParameters(&fragment, args[0]==context1, 0); \ + SET_PSFILENAME(fragment, name); \ +} \ + +bool ZeroGS::LoadEffects() +{ + // clear the textures + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + +#ifndef _DEBUG + memset(ppsTexture, 0, sizeof(ppsTexture)); +#endif + + return true; +} + +bool ZeroGS::LoadExtraEffects() +{ + const char* args[] = { NULL , NULL, NULL, NULL }; + char context0[255], context1[255]; + sprintf(context0, "-I%sctx0", EFFECT_DIR); + sprintf(context1, "-I%sctx1", EFFECT_DIR); + char* write_depth = "-DWRITE_DEPTH"; + bool bLoadSuccess = true; + + const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" }; + + for(int i = 0; i < 4; ++i) { + args[0] = context0; + args[1] = NULL; + LOAD_VS(pvsshaders[i], pvs[2*i], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+1], cgvProf); + + //if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf); + args[0] = context1; + LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf); +// } +// else { +// pvs[2*i+8] = pvs[2*i+8+1] = NULL; +// } + } + + args[0] = context0; + args[1] = NULL; + LOAD_VS("BitBltVS", pvsBitBlt.prog, cgvProf); + pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos"); + pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex"); + pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans"); + + LOAD_PS("RegularPS", ppsRegular[0], cgfProf); + LOAD_PS("RegularFogPS", ppsRegular[1], cgfProf); + + if( conf.mrtdepth ) { + args[0] = context0; + args[1] = write_depth; + LOAD_PS("RegularPS", ppsRegular[2], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + LOAD_PS("RegularFogPS", ppsRegular[3], cgfProf); + if( !bLoadSuccess ) + conf.mrtdepth = 0; + } + + LOAD_PS("BitBltPS", ppsBitBlt[0], cgfProf); + LOAD_PS("BitBltAAPS", ppsBitBlt[1], cgfProf); + if( !bLoadSuccess ) { + ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n"); + LOAD_PS("BitBltPS", ppsBitBlt[1], cgfProf); + } + + LOAD_PS("BitBltDepthPS", ppsBitBltDepth, cgfProf); + LOAD_PS("CRTCTargPS", ppsCRTCTarg[0], cgfProf); LOAD_PS("CRTCTargInterPS", ppsCRTCTarg[1], cgfProf); + + g_bCRTCBilinear = TRUE; + LOAD_PS("CRTCPS", ppsCRTC[0], cgfProf); + if( !bLoadSuccess ) { + // switch to simpler + g_bCRTCBilinear = FALSE; + LOAD_PS("CRTCPS_Nearest", ppsCRTC[0], cgfProf); + LOAD_PS("CRTCInterPS_Nearest", ppsCRTC[0], cgfProf); + } + else { + LOAD_PS("CRTCInterPS", ppsCRTC[1], cgfProf); + } + + if( !bLoadSuccess ) + ERROR_LOG("Failed to create CRTC shaders\n"); + + LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf); LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf); + LOAD_PS("ZeroPS", ppsOne, cgfProf); + LOAD_PS("BaseTexturePS", ppsBaseTexture, cgfProf); + LOAD_PS("Convert16to32PS", ppsConvert16to32, cgfProf); + LOAD_PS("Convert32to16PS", ppsConvert32to16, cgfProf); + +// if( !conf.mrtdepth ) { +// ERROR_LOG("Disabling MRT depth writing\n"); +// s_bWriteDepth = FALSE; +// } + + return true; +} + +FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed) +{ + int texwrap; + + assert( texfilter < NUM_FILTERS ); + //assert( g_nPixelShaderVer == SHADER_30 ); + if( clamp.wms == clamp.wmt ) { + switch( clamp.wms ) { + case 0: texwrap = TEXWRAP_REPEAT; break; + case 1: texwrap = TEXWRAP_CLAMP; break; + case 2: texwrap = TEXWRAP_CLAMP; break; + default: + texwrap = TEXWRAP_REGION_REPEAT; break; + } + } + else if( clamp.wms==3||clamp.wmt==3) + texwrap = TEXWRAP_REGION_REPEAT; + else + texwrap = TEXWRAP_REPEAT_CLAMP; + + int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0); + + if( pbFailed != NULL ) *pbFailed = false; + + FRAGMENTSHADER* pf = ppsTexture+index; + + if( pf->prog != NULL ) + return pf; + + pf->prog = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context); + + if( pf->prog != NULL ) { +#ifdef _DEBUG + char str[255]; + sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]); + pf->filename = str; +#endif + SetupFragmentProgramParameters(pf, context, type); + cgGLLoadProgram(pf->prog); + if( cgGetError() != CG_NO_ERROR ) { + // try again +// cgGLLoadProgram(pf->prog); +// if( cgGetError() != CG_NO_ERROR ) { + ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + //assert(0); + // NULL makes things crash + return pf; +// } + } + return pf; + } + + ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt); + if( pbFailed != NULL ) *pbFailed = true; + + return NULL; +} + +#endif // RELEASE_TO_PUBLIC + +void ZeroGS::Prim() +{ + if( g_bIsLost ) + return; + + VB& curvb = vb[prim->ctxt]; + if( curvb.CheckPrim() ) + Flush(prim->ctxt); + curvb.curprim._val = prim->_val; + + // flush the other pipe if sharing the same buffer +// if( vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp && vb[!prim->ctxt].nCount > 0 ) +// { +// assert( vb[prim->ctxt].nCount == 0 ); +// Flush(!prim->ctxt); +// } + + curvb.curprim.prim = prim->prim; +} + +int GetTexFilter(const tex1Info& tex1) +{ + // always force + if( conf.bilinear == 2 ) + return 1; + + int texfilter = 0; + if( conf.bilinear && ptexBilinearBlocks != 0 ) { + if( tex1.mmin <= 1 ) + texfilter = tex1.mmin|tex1.mmag; + else + texfilter = tex1.mmag ? ((tex1.mmin+2)&5) : tex1.mmin; + + texfilter = texfilter == 1 || texfilter == 4 || texfilter == 5; + } + return texfilter; +} + +void ZeroGS::ReloadEffects() +{ +#ifndef RELEASE_TO_PUBLIC + for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) { + SAFE_RELEASE_PROG(ppsTexture[i].prog); + } + memset(ppsTexture, 0, sizeof(ppsTexture)); + LoadExtraEffects(); +#endif +} + +static int s_ClutResolve = 0; +void ZeroGS::Flush(int context) +{ + GL_REPORT_ERRORD(); + assert( context >= 0 && context <= 1 ); + +#ifndef RELEASE_TO_PUBLIC + if( g_bUpdateEffect ) { + ReloadEffects(); + g_bUpdateEffect = 0; + } +#endif + + VB& curvb = vb[context]; + const pixTest curtest = curvb.test; + if( curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || g_bIsLost ) { + curvb.nCount = 0; + return; + } + + if( s_RangeMngr.ranges.size() > 0 ) { + + // don't want infinite loop + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + FlushTransferRanges(curvb.curprim.tme ? &curvb.tex0 : NULL); + + curvb.nCount = prevcount; + //if( curvb.nCount == 0 ) + // return; + } + + if( curvb.bNeedTexCheck ) { + curvb.FlushTexData(); + + if( curvb.nCount == 0 ) + return; + } + + DVProfileFunc _pf("Flush"); + + GL_REPORT_ERRORD(); + if( curvb.bNeedFrameCheck || curvb.bNeedZCheck ) { + curvb.CheckFrame(curvb.curprim.tme ? curvb.tex0.tbp0 : 0); + } + + if( curvb.prndr == NULL || curvb.pdepth == NULL ) { + WARN_LOG("Current render target NULL (ctx: %d)", context); + curvb.nCount = 0; + return; + } + +#if defined(PRIM_LOG) && defined(_DEBUG) + static const char* patst[8] = { "NEVER", "ALWAYS", "LESS", "LEQUAL", "EQUAL", "GEQUAL", "GREATER", "NOTEQUAL"}; + static const char* pztst[4] = { "NEVER", "ALWAYS", "GEQUAL", "GREATER" }; + static const char* pafail[4] = { "KEEP", "FB_ONLY", "ZB_ONLY", "RGB_ONLY" }; + PRIM_LOG("**Drawing ctx %d, num %d, fbp: 0x%x, zbp: 0x%x, fpsm: %d, zpsm: %d, fbw: %d\n", context, vb[context].nCount, curvb.prndr->fbp, curvb.zbuf.zbp, curvb.prndr->psm, curvb.zbuf.psm, curvb.prndr->fbw); + PRIM_LOG("prim: prim=%x iip=%x tme=%x fge=%x abe=%x aa1=%x fst=%x ctxt=%x fix=%x\n", + curvb.curprim.prim, curvb.curprim.iip, curvb.curprim.tme, curvb.curprim.fge, curvb.curprim.abe, curvb.curprim.aa1, curvb.curprim.fst, curvb.curprim.ctxt, curvb.curprim.fix); + PRIM_LOG("test: ate:%d, atst: %s, aref: %d, afail: %s, date: %d, datm: %d, zte: %d, ztst: %s, fba: %d\n", + curvb.test.ate, patst[curvb.test.atst], curvb.test.aref, pafail[curvb.test.afail], curvb.test.date, curvb.test.datm, curvb.test.zte, pztst[curvb.test.ztst], curvb.fba.fba); + PRIM_LOG("alpha: A%d B%d C%d D%d FIX:%d pabe: %d; aem: %d, ta0: %d, ta1: %d\n", curvb.alpha.a, curvb.alpha.b, curvb.alpha.c, curvb.alpha.d, curvb.alpha.fix, gs.pabe, gs.texa.aem, gs.texa.ta[0], gs.texa.ta[1]); + PRIM_LOG("tex0: tbp0=0x%x, tbw=%d, psm=0x%x, tw=%d, th=%d, tcc=%d, tfx=%d, cbp=0x%x, cpsm=0x%x, csm=%d, csa=%d, cld=%d\n", + curvb.tex0.tbp0, curvb.tex0.tbw, curvb.tex0.psm, curvb.tex0.tw, + curvb.tex0.th, curvb.tex0.tcc, curvb.tex0.tfx, curvb.tex0.cbp, + curvb.tex0.cpsm, curvb.tex0.csm, curvb.tex0.csa, curvb.tex0.cld); + PRIM_LOG("frame: %d\n\n", g_SaveFrameNum); +#endif + + GL_REPORT_ERRORD(); + CRenderTarget* ptextarg = NULL; + + if( curtest.date || gs.pabe ) + SetDestAlphaTest(); + + // set the correct pixel shaders + if( curvb.curprim.tme ) { + + // if texture is part of a previous target, use that instead + int tbw = curvb.tex0.tbw; + int tbp0 = curvb.tex0.tbp0; + int tpsm = curvb.tex0.psm; + + if( curvb.bNeedTexCheck ) { + // not yet initied, but still need to get correct target! (xeno3 ingame) + tbp0 = (curvb.uNextTex0Data[0] & 0x3fff); + tbw = ((curvb.uNextTex0Data[0] >> 14) & 0x3f) * 64; + tpsm = (curvb.uNextTex0Data[0] >> 20) & 0x3f; + } + ptextarg = s_RTs.GetTarg(tbp0, tbw); + + if( (tpsm&0x30)==0x30 && ptextarg == NULL ) { + // try depth + ptextarg = s_DepthRTs.GetTarg(tbp0, tbw); + } + + if( ptextarg == NULL && (g_GameSettings&GAME_TEXTURETARGS) ) { + // check if any part of the texture intersects the current target + if( !PSMT_ISCLUT(tpsm) && curvb.tex0.tbp0 >= curvb.frame.fbp && (curvb.tex0.tbp0 << 8) < curvb.prndr->end) { + ptextarg = curvb.prndr; + } + } + + if( ptextarg != NULL && !(ptextarg->status&CRenderTarget::TS_NeedUpdate) ) { + if( PSMT_ISCLUT(tpsm) && tpsm != PSMT8H ) { // handle 8h cluts + // don't support clut targets, read from mem + if( s_ClutResolve <= 1 ) { // xenosaga requires 2 resolves + u32 prevcount = curvb.nCount; + curvb.nCount = 0; + ptextarg->Resolve(); + s_ClutResolve++; + curvb.nCount = prevcount; + } + ptextarg = NULL; + } + else { + if( ptextarg == curvb.prndr ) { + // need feedback + curvb.prndr->CreateFeedback(); + + if(s_bWriteDepth && curvb.pdepth != NULL) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } + } + } + else ptextarg = NULL; + } + +#ifdef _DEBUG + if( g_bSaveFlushedFrame & 0x80000000 ) { + char str[255]; + sprintf(str, "rndr.tga", g_SaveFrameNum); + SaveRenderTarget(str, curvb.prndr->fbw, curvb.prndr->fbh, 0); + } +#endif + + if( conf.options & GSOPTION_WIREFRAME ) { + // always render first few geometry as solid + if( s_nWireframeCount > 0 ) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + + if( !curvb.bVarsSetTarg ) + SetContextTarget(context); + else { + assert( curvb.pdepth != NULL ); + + if( curvb.pdepth->status & CRenderTarget::TS_Virtual) { + + if( !curvb.zbuf.zmsk ) { + CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp|(curvb.pdepth->fbw<<16)); + assert( ptemp == curvb.pdepth ); + } + else + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + + if( (curvb.pdepth->status & CRenderTarget::TS_NeedUpdate) || (curvb.prndr->status & CRenderTarget::TS_NeedUpdate) ) + SetContextTarget(context); + } + + icurctx = context; + + DVProfileFunc _pf5("Flush:after texvars"); + + glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]); + g_nCurVBOIndex = (g_nCurVBOIndex+1)%g_vboBuffers.size(); + glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW); +// void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); +// memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU)); +// glUnmapBuffer(GL_ARRAY_BUFFER); + SET_STREAM(); + + assert( !(curvb.prndr->status&CRenderTarget::TS_NeedUpdate) ); + curvb.prndr->status = 0; + + if( curvb.pdepth != NULL ) { + assert( !(curvb.pdepth->status&CRenderTarget::TS_NeedUpdate) ); + if( !curvb.zbuf.zmsk ) { + assert( !(curvb.pdepth->status & CRenderTarget::TS_Virtual) ); + curvb.pdepth->status = 0; + } + } + +#ifdef _DEBUG + //curvb.prndr->SetRenderTarget(0); + //curvb.pdepth->SetDepthStencilSurface(); + //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0 ); + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); +#endif + s_dwColorWrite = (curvb.prndr->psm&0xf) == 1 ? (COLORMASK_BLUE|COLORMASK_GREEN|COLORMASK_RED) : 0xf; + + if( ((curvb.frame.fbm)&0xff) == 0xff) s_dwColorWrite &= ~COLORMASK_RED; + if( ((curvb.frame.fbm>>8)&0xff) == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN; + if( ((curvb.frame.fbm>>16)&0xff) == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE; + if( ((curvb.frame.fbm>>24)&0xff) == 0xff) s_dwColorWrite &= ~COLORMASK_ALPHA; + + GL_COLORMASK(s_dwColorWrite); + + Rect& scissor = curvb.prndr->scissorrect; + glScissor(scissor.x, scissor.y, scissor.w, scissor.h); + + u32 dwUsingSpecialTesting = 0; + u32 dwFilterOpts = 0; + + FRAGMENTSHADER* pfragment = NULL; + + // need exact if equal or notequal + int exactcolor = 0; + if( !(g_nPixelShaderVer&SHADER_REDUCED) ) + // ffx2 breaks when ==7 + exactcolor = (curtest.ate && curtest.aref <= 128) && (curtest.atst==4);//||curtest.atst==7); + + int shadertype = 0; + + // set the correct pixel shaders + u32 ptexclut = 0; + if( curvb.curprim.tme ) { + + if( ptextarg != NULL ) { + + if( ptextarg->IsDepth() ) + SetWriteDepth(); + + Vector vpageoffset; + vpageoffset.w = 0; + + int psm = curvb.tex0.psm; + if( PSMT_ISCLUT(curvb.tex0.psm) ) psm = curvb.tex0.cpsm; + + shadertype = 1; + if( curvb.tex0.psm == PSMT8H && !(g_GameSettings&GAME_NOTARGETCLUT) ) { + // load the clut to memory + glGenTextures(1, &ptexclut); + glBindTexture(GL_TEXTURE_2D, ptexclut); + vector data((curvb.tex0.cpsm&2) ? 512 : 1024); + + if( ptexclut != 0 ) { + + // fill the buffer by decoding the clut + int nClutOffset = 0, clutsize; + int entries = (curvb.tex0.psm&3)==3 ? 256 : 16; + if( curvb.tex0.cpsm <= 1 ) { // 32 bit + nClutOffset = 64 * curvb.tex0.csa; + clutsize = min(entries, 256-curvb.tex0.csa*16)*4; + } + else { + nClutOffset = 64 * (curvb.tex0.csa&15) + (curvb.tex0.csa>=16?2:0); + clutsize = min(entries, 512-curvb.tex0.csa*16)*2; + } + + if( curvb.tex0.cpsm <= 1 ) { // 32 bit + memcpy_amd(&data[0], g_pbyGSClut+nClutOffset, clutsize); + } + else { + u16* pClutBuffer = (u16*)(g_pbyGSClut + nClutOffset); + u16* pclut = (u16*)&data[0]; + int left = ((u32)nClutOffset & 2) ? 0 : ((nClutOffset&0x3ff)/2)+clutsize-512; + if( left > 0 ) clutsize -= left; + + while(clutsize > 0) { + pclut[0] = pClutBuffer[0]; + pclut++; + pClutBuffer+=2; + clutsize -= 2; + } + + if( left > 0) { + pClutBuffer = (u16*)(g_pbyGSClut + 2); + while(left > 0) { + pclut[0] = pClutBuffer[0]; + left -= 2; + pClutBuffer += 2; + pclut++; + } + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 1, 0, GL_RGBA, (curvb.tex0.cpsm&2)?GL_UNSIGNED_SHORT_5_5_5_1:GL_UNSIGNED_BYTE, &data[0]); + s_vecTempTextures.push_back(ptexclut); + + if( g_bSaveTex ) + SaveTexture("clut.tga", GL_TEXTURE_2D, ptexclut, 256, 1); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + + if( !(g_nPixelShaderVer&SHADER_REDUCED) && (ptextarg->psm & 2) ) { + shadertype = 4; + } + else + shadertype = 2; + } + else { + if( PSMT_ISCLUT(curvb.tex0.psm) ) + WARN_LOG("Using render target with CLUTs %d!\n", curvb.tex0.psm); + else { + if( (curvb.tex0.psm&2) != (ptextarg->psm&2) && (!(g_nPixelShaderVer&SHADER_REDUCED) || !curvb.curprim.fge) ) { + if( curvb.tex0.psm & 2 ) { + // converting from 32->16 + shadertype = 3; + } + else { + // converting from 16->32 + WARN_LOG("ZeroGS: converting from 16 to 32bit RTs\n"); + //shadetype = 4; + } + } + } + } + + pfragment = LoadShadeEffect(shadertype, 0, curvb.curprim.fge, curvb.tex0.tcc && gs.texa.aem && (psm == PSMCT24 || psm == PSMCT16 || psm == PSMCT16S), + exactcolor, curvb.clamp, context, NULL); + + if( shadertype == 3 ) { + Vector v; + v.x = 16.0f / (float)curvb.tex0.tw; + v.y = 16.0f / (float)curvb.tex0.th; + v.z = 0.5f * v.x; + v.w = 0.5f * v.y; + cgGLSetParameter4fv(pfragment->fTexOffset, v); + + vpageoffset.x = -0.1f / 256.0f; + vpageoffset.y = -0.001f / 256.0f; + vpageoffset.z = -0.1f / ptextarg->fbh; + vpageoffset.w = ((ptextarg->psm&0x30)==0x30)?-1.0f:0.0f; + } + else if( shadertype == 4 ) { + Vector v; + v.x = 16.0f / (float)ptextarg->fbw; + v.y = 16.0f / (float)ptextarg->fbh; + v.z = -1; + v.w = 8.0f / (float)ptextarg->fbh; + cgGLSetParameter4fv(pfragment->fTexOffset, v); + + vpageoffset.x = 2; + vpageoffset.y = 1; + vpageoffset.z = 0; + vpageoffset.w = 0.0001f; + } + + u32 ptexset = ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex; + s_ptexCurSet[context] = ptexset; + + if( !curvb.tex1.mmag ) { + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + dwFilterOpts |= 1; + } + + if( !curvb.tex1.mmin ) { + if( curvb.tex1.mmag ) + glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexset); + glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + dwFilterOpts |= 2; + } + + Vector vTexDims; + vTexDims.x = curvb.tex0.tw; + vTexDims.y = curvb.tex0.th; + + // look at the offset of tbp0 from fbp + if( curvb.tex0.tbp0 <= ptextarg->fbp ) { + vTexDims.z = 0;//-0.5f/(float)ptextarg->fbw; + vTexDims.w = 0;//0.2f/(float)ptextarg->fbh; + } + else { + u32 tbp0 = curvb.tex0.tbp0 >> 5; // align to a page + int blockheight = (ptextarg->psm&2) ? 64 : 32; + int ycoord = ((curvb.tex0.tbp0-ptextarg->fbp)/(32*(ptextarg->fbw>>6))) * blockheight; + int xcoord = (((curvb.tex0.tbp0-ptextarg->fbp)%(32*(ptextarg->fbw>>6)))) * 2; + vTexDims.z = (float)xcoord; + vTexDims.w = (float)ycoord; + } + + if( shadertype == 4 ) { + vTexDims.z += 8.0f; + } + + cgGLSetParameter4fv(pfragment->fTexDims, vTexDims); + + // zoe2 + if( (ptextarg->psm&0x30) == 0x30 ) {//&& (psm&2) == (ptextarg->psm&2) ) { + // target of zbuf has +1 added to it, don't do 16bit + vpageoffset.w = -1; +// Vector valpha2; +// valpha2.x = 1; valpha2.y = 0; +// valpha2.z = -1; valpha2.w = 0; +// SETCONSTF(GPU_TEXALPHA20+context, &valpha2); + } + cgGLSetParameter4fv(pfragment->fPageOffset, vpageoffset); + + if( g_bSaveTex ) + SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, + ptextarg == curvb.prndr ? ptextarg->ptexFeedback : ptextarg->ptex, ptextarg->fbw<fbh<ValidateClut(curvb.tex0) ); +#endif + +//#ifdef ZEROGS_CACHEDCLEAR +// if( !curvb.pmemtarg->ValidateTex(curvb.tex0, true) ) { +// CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(curvb.tex0, 1); +// SetTexVariablesInt(context, GetTexFilter(curvb.tex1), curvb.tex0, pmemtarg, s_bForceTexFlush); +// vb[context].bVarsTexSync = TRUE; +// } +//#endif + + if( g_bSaveTex ) { + if( g_bSaveTex == 1 ) { + SaveTex(&curvb.tex0, 1); +// CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(curvb.tex0, 0); +// int texheight = (pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult; +// int texwidth = GPU_TEXWIDTH*pmemtarg->widthmult*pmemtarg->channels; +// SaveTexture("real.tga", GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex, texwidth, texheight); + } + else SaveTex(&curvb.tex0, 0); + } + + int psm = curvb.tex0.psm; + if( PSMT_ISCLUT(curvb.tex0.psm) ) psm = curvb.tex0.cpsm; + + pfragment = LoadShadeEffect(0, GetTexFilter(curvb.tex1), curvb.curprim.fge, + curvb.tex0.tcc && gs.texa.aem && (psm == PSMCT24 || psm == PSMCT16 || psm == PSMCT16S), + exactcolor, curvb.clamp, context, NULL); + } + + if( pfragment->prog != g_psprog ) { + // programs changed, so reset the texture variables + vb[context].bTexConstsSync = 0; + vb[context].bVarsTexSync = 0; + } + + SetTexVariables(context, pfragment, ptextarg == NULL); + } + else { + pfragment = &ppsRegular[curvb.curprim.fge+2*s_bWriteDepth]; + } + + assert(pfragment != 0 ); + if( curvb.curprim.tme ) { + // have to enable the texture parameters + if( curvb.ptexClamp[0] != 0 ) { + cgGLSetTextureParameter(pfragment->sBitwiseANDX, curvb.ptexClamp[0]); + cgGLEnableTextureParameter(pfragment->sBitwiseANDX); + } + if( curvb.ptexClamp[1] != 0 ) { + cgGLSetTextureParameter(pfragment->sBitwiseANDY, curvb.ptexClamp[1]); + cgGLEnableTextureParameter(pfragment->sBitwiseANDY); + } + if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0) { + cgGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context]); + cgGLEnableTextureParameter(pfragment->sMemory); + } + if( pfragment->sCLUT != NULL && ptexclut != 0 ) { + cgGLSetTextureParameter(pfragment->sCLUT, ptexclut); + cgGLEnableTextureParameter(pfragment->sCLUT); + } + } + + DVProfileFunc _pf4("Flush:before bind"); + GL_REPORT_ERRORD(); + + // set the shaders + SETVERTEXSHADER(pvs[2*((curvb.curprim._val>>1)&3)+8*s_bWriteDepth+context]); + + if( pfragment->prog != g_psprog ) { + cgGLBindProgram(pfragment->prog); + g_psprog = pfragment->prog; + } + + GL_REPORT_ERRORD(); + + DVProfileFunc _pf1("Flush:after bind"); + + BOOL bCanRenderStencil = g_bUpdateStencil && (curvb.prndr->psm&0xf) != 1 && !(curvb.frame.fbm&0x80000000); + if( g_GameSettings & GAME_NOSTENCIL ) + bCanRenderStencil = 0; + + if( s_bDestAlphaTest && bCanRenderStencil) { + glEnable(GL_STENCIL_TEST); + GL_STENCILFUNC(GL_ALWAYS, 0, 0); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + } + else glDisable(GL_STENCIL_TEST); + + glDepthMask(!curvb.zbuf.zmsk); + GL_ZTEST(curtest.zte); + if( curtest.zte ) { + if( curtest.ztst > 1 ) g_nDepthUsed = 2; + if( (curtest.ztst == 2) ^ (g_nDepthBias != 0) ) { + g_nDepthBias = curtest.ztst == 2; + //SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f)); + } + + glDepthFunc(g_dwZCmp[curtest.ztst]); + +// if( curtest.ztst == 3 ) { +// // gequal +// if( s_vznorm.y == 0 ) { +// s_vznorm.y = 0.00001f; +// SETCONSTF(GPU_ZNORM, s_vznorm); +// } +// } +// else { +// if( s_vznorm.y > 0 ) { +// s_vznorm.y = 0; +// SETCONSTF(GPU_ZNORM, s_vznorm); +// } +// } + } + + GL_ALPHATEST(curtest.ate&&USEALPHATESTING); + if( curtest.ate ) { + glAlphaFunc(g_dwAlphaCmp[curtest.atst], b2XAlphaTest ? min(1.0f,(float)curtest.aref * (1/ 127.5f)) : curtest.aref*(1/255.0f)); + } + + if( s_bWriteDepth ) { + if(!curvb.zbuf.zmsk) + curvb.pdepth->SetRenderTarget(1); + else + ResetRenderTarget(1); + } + + if( curvb.curprim.abe ) + SetAlphaVariables(curvb.alpha); + else + glDisable(GL_BLEND); + + // needs to be before RenderAlphaTest + if( curvb.fba.fba || s_bDestAlphaTest ) { + if( gs.pabe || (curvb.fba.fba || bCanRenderStencil) && !(curvb.frame.fbm&0x80000000) ) { + RenderFBA(curvb, pfragment->sOneColor); + } + } + + u32 oldabe = curvb.curprim.abe; + if( gs.pabe ) { + //WARN_LOG("PBE!\n"); + curvb.curprim.abe = 1; + glEnable(GL_BLEND); + } + + if( curvb.curprim.abe ) { + + if( //bCanRenderStencil && + (bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst>1) && (curtest.aref > 0x80))) ) { + // need special stencil processing for the alpha + RenderAlphaTest(curvb, pfragment->sOneColor); + dwUsingSpecialTesting = 1; + } + + // harvest fishing + Vector v = vAlphaBlendColor;// + Vector(0,0,0,(curvb.test.atst==4 && curvb.test.aref>=128)?-0.004f:0); + if( exactcolor ) { v.y *= 255; v.w *= 255; } + cgGLSetParameter4fv(pfragment->sOneColor, v); + } + else { + // not using blending so set to defaults + Vector v = exactcolor ? Vector(1, 510*255.0f/256.0f, 0, 0) : Vector(1,2*255.0f/256.0f,0,0); + cgGLSetParameter4fv(pfragment->sOneColor, v); + } + + if( s_bDestAlphaTest && bCanRenderStencil ) { + // if not 24bit and can write to high alpha bit + RenderStencil(curvb, dwUsingSpecialTesting); + } + else { + s_stencilref = STENCIL_SPECIAL; + s_stencilmask = STENCIL_SPECIAL; + + // setup the stencil to only accept the test pixels + if( dwUsingSpecialTesting ) { + glEnable(GL_STENCIL_TEST); + glStencilMask(STENCIL_PIXELWRITE); + GL_STENCILFUNC(GL_EQUAL, STENCIL_SPECIAL|STENCIL_PIXELWRITE, STENCIL_SPECIAL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + } + +#ifdef _DEBUG + if( bDestAlphaColor == 1 ) { + WARN_LOG("dest alpha blending! manipulate alpha here\n"); + } +#endif + + if( bCanRenderStencil && gs.pabe ) { + // only render the pixels with alpha values >= 0x80 + GL_STENCILFUNC(GL_EQUAL, s_stencilref|STENCIL_FBA, s_stencilmask|STENCIL_FBA); + } + +// curvb.prndr->SetViewport(); +// pd3dDevice->SetScissorRect(&curvb.prndr->scissorrect); +// glEnable(GL_SCISSOR_TEST); + + GL_REPORT_ERRORD(); + if( !curvb.test.ate || curvb.test.atst > 0 ) { + DRAW(); + } + GL_REPORT_ERRORD(); + + if( gs.pabe ) { + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + if( exactcolor ) v.y *= 255; + cgGLSetParameter4fv(pfragment->sOneColor, v); + + DRAW(); + + // reset + if( !s_stencilmask ) s_stencilfunc = GL_ALWAYS; + GL_STENCILFUNC_SET(); + } + + GL_REPORT_ERRORD(); + + // more work on alpha failure case + if( curtest.ate && curtest.atst != 1 && curtest.afail > 0 ) { + + // need to reverse the test and disable some targets + glAlphaFunc(g_dwReverseAlphaCmp[curtest.atst], b2XAlphaTest ? min(1.0f,(float)curtest.aref * (1/ 127.5f)) : curtest.aref*(1/255.0f)); + + if( curtest.afail & 1 ) { // front buffer update only + + if( curtest.afail == 3 ) // disable alpha + glColorMask(1,1,1,0); + + glDepthMask(0); + + if( s_bWriteDepth ) + ResetRenderTarget(1); + } + else { + // zbuffer update only + glColorMask(0,0,0,0); + } + + if( gs.pabe && bCanRenderStencil ) { + // only render the pixels with alpha values >= 0x80 + Vector v = vAlphaBlendColor; + if( exactcolor ) { v.y *= 255; v.w *= 255; } + cgGLSetParameter4fv(pfragment->sOneColor, v); + glEnable(GL_BLEND); + GL_STENCILFUNC(GL_EQUAL, s_stencilref|STENCIL_FBA, s_stencilmask|STENCIL_FBA); + } + +// IDirect3DQuery9* pOcclusionQuery; +// u32 numberOfPixelsDrawn; +// +// pd3dDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery); +// +// // Add an end marker to the command buffer queue. +// pOcclusionQuery->Issue(D3DISSUE_BEGIN); + + DRAW(); + GL_REPORT_ERRORD(); + +// pOcclusionQuery->Issue(D3DISSUE_END); + // Force the driver to execute the commands from the command buffer. + // Empty the command buffer and wait until the GPU is idle. +// while(S_FALSE == pOcclusionQuery->GetData( &numberOfPixelsDrawn, sizeof(u32), D3DGETDATA_FLUSH )); +// SAFE_RELEASE(pOcclusionQuery); + + if( gs.pabe ) { + // only render the pixels with alpha values < 0x80 + glDisable(GL_BLEND); + GL_STENCILFUNC_SET(); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + if( exactcolor ) v.y *= 255; + cgGLSetParameter4fv(pfragment->sOneColor, v); + + DRAW(); + + // reset + if( oldabe ) glEnable(GL_BLEND); + + if( !s_stencilmask ) s_stencilfunc = GL_ALWAYS; + GL_STENCILFUNC_SET(); + } + + // restore + + if( (curtest.afail & 1) && !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + assert( curvb.pdepth != NULL); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_COLORMASK(s_dwColorWrite); + + // not needed anymore since rest of ops concentrate on image processing + } + + GL_REPORT_ERRORD(); + + if( dwUsingSpecialTesting ) { + // render the real alpha + glDisable(GL_ALPHA_TEST); + glColorMask(0,0,0,1); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + + glDepthMask(0); + + glStencilFunc(GL_EQUAL, STENCIL_SPECIAL|STENCIL_PIXELWRITE, STENCIL_SPECIAL|STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + Vector v = Vector(0,exactcolor ? 510.0f : 2.0f,0,0); + cgGLSetParameter4fv(pfragment->sOneColor, v); + DRAW(); + + // don't need to restore + } + + GL_REPORT_ERRORD(); + + if( s_bDestAlphaTest ) { + if( (s_dwColorWrite&COLORMASK_ALPHA) ) { + if( curvb.fba.fba ) + ProcessFBA(curvb, pfragment->sOneColor); + else if( bCanRenderStencil ) + // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case) + ProcessStencil(curvb); + } + } + else if( (s_dwColorWrite&COLORMASK_ALPHA) && curvb.fba.fba ) + ProcessFBA(curvb, pfragment->sOneColor); + + if( bDestAlphaColor == 1 ) { + // need to reset the dest colors to their original counter parts + //WARN_LOG("Need to reset dest alpha color\n"); + } + +#ifdef _DEBUG + if( g_bSaveFlushedFrame & 0xf ) { +#ifdef _WIN32 + CreateDirectory("frames", NULL); +#else + mkdir("frames", 0755); +#endif + char str[255]; + sprintf(str, "frames/frame%.4d.tga", g_SaveFrameNum++); + if( (g_bSaveFlushedFrame & 2) ) { + //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + //glFlush(); + //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, curvb.prndr->fbw<fbh<fbw<fbh<SetRenderTarget(1); + } + } + + if( curvb.test.ate && USEALPHATESTING ) + glEnable(GL_ALPHA_TEST); + + GL_ZTEST(curtest.zte); + } + + if( dwFilterOpts ) { + // undo filter changes (binding didn't change) + if( dwFilterOpts & 1 ) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if( dwFilterOpts & 2 ) glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + +//#ifndef RELEASE_TO_PUBLIC + ppf += curvb.nCount+0x100000; +//#endif + + curvb.nCount = 0; + curvb.curprim.abe = oldabe; + //if( oldabe ) glEnable(GL_BLEND); + + if( conf.options & GSOPTION_WIREFRAME ) { + // always render first few geometry as solid + if( s_nWireframeCount > 0 ) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + --s_nWireframeCount; + } + } + + GL_REPORT_ERRORD(); +} + +void ZeroGS::ProcessMessages() +{ + if( listMsgs.size() > 0 ) { + int left = 25, top = 15; + list::iterator it = listMsgs.begin(); + + while( it != listMsgs.end() ) { + DrawText(it->str, left+1, top+1, 0xff000000); + DrawText(it->str, left, top, 0xffffff30); + top += 15; + + if( (int)(it->dwTimeStamp - timeGetTime()) < 0 ) + it = listMsgs.erase(it); + else ++it; + } + } +} + +void ZeroGS::RenderCustom(float fAlpha) +{ + GLenum err = GL_NO_ERROR; + + GL_REPORT_ERROR(); + + fAlpha = 1; + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(1,1,1,1); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_SCISSOR_TEST); + glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); + + // play custom animation + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + + // tex coords + Vector v = Vector(1/32767.0f, 1/32767.0f, 0, 0); + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + v.x = (float)nLogoWidth; + v.y = (float)nLogoHeight; + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + v.x = v.y = v.z = v.w = fAlpha; + cgGLSetParameter4fv(ppsBaseTexture.sOneColor, v); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + // inside vb[0]'s target area, so render that region only + cgGLSetTextureParameter(ppsBaseTexture.sFinal, ptexLogo); + cgGLEnableTextureParameter(ppsBaseTexture.sFinal); + + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + + SETVERTEXSHADER(pvsBitBlt.prog); + SETPIXELSHADER(ppsBaseTexture.prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // restore + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + ProcessMessages(); + +#ifdef _WIN32 + SwapBuffers(hDC); +#else + glXSwapBuffers(GLWin.dpy, GLWin.win); +#endif + + glEnable(GL_SCISSOR_TEST); + glEnable(GL_STENCIL_TEST); + + vb[0].bSyncVars = 0; + vb[1].bSyncVars = 0; + + GL_REPORT_ERROR(); + GLint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + assert( status == GL_FRAMEBUFFER_COMPLETE_EXT || status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT ); +} + +// adjusts trans to preserve aspect ratio +void ZeroGS::AdjustTransToAspect(Vector& v, int dispwidth, int dispheight) +{ + double temp; + float f; + if( dispwidth * nBackbufferHeight > dispheight * nBackbufferWidth) { + // limited by width + + // change in ratio + f = ((float)nBackbufferWidth / (float)dispwidth) / ((float)nBackbufferHeight / (float)dispheight); + v.y *= f; + v.w *= f; + + // scanlines mess up when not aligned right + v.y += (1-(float)modf(v.y*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight; + v.w += (1-(float)modf(v.w*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight; + } + else { + // limited by height + f = ((float)nBackbufferHeight / (float)dispheight) / ((float)nBackbufferWidth / (float)dispwidth); + f -= (float)modf(f*nBackbufferWidth, &temp)/(float)nBackbufferWidth; + v.x *= f; + v.z *= f; + } + +// v.y *= -1; +// v.w *= -1; + v *= 1/32767.0f; +} + +void ZeroGS::Restore() +{ + if( !g_bIsLost ) + return; + + //if( SUCCEEDED(pd3dDevice->Reset(&d3dpp)) ) { + g_bIsLost = 0; + // handle lost states + ZeroGS::ChangeDeviceSize(nBackbufferWidth, nBackbufferHeight); + //} +} + +void ZeroGS::RenderCRTC(int interlace) +{ + if( g_bIsLost ) return; + +//#ifdef RELEASE_TO_PUBLIC +// if(g_nRealFrame < 80 ) { +// RenderCustom( min(1.0f, 2.0f - (float)g_nRealFrame / 40.0f) ); +// +// if( g_nRealFrame == 79 ) +// SAFE_RELEASE_TEX(ptexLogo); +// return; +// } +//#endif + + if( conf.mrtdepth && pvs[8] == NULL ) { + conf.mrtdepth = 0; + s_bWriteDepth = FALSE; + ERROR_LOG("Disabling MRT depth writing\n"); + } + + Flush(0); + Flush(1); + GL_REPORT_ERRORD(); + + DVProfileFunc _pf("RenderCRTC"); + + // frame skipping + if( g_nFrameRender > 0 ) { + + if( g_nFrameRender < 8 ) { + g_nFrameRender++; + if( g_nFrameRender <= 3 ) { + g_nFramesSkipped++; + return; + } + } + } + else { + if( g_nFrameRender < -1 ) { + g_nFramesSkipped++; + return; + } + g_nFrameRender--; + } + + if( g_bSaveFrame ) { + if( vb[0].prndr != NULL ) { + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, vb[0].prndr->ptex, vb[0].prndr->fbw<fbh<ptex, vb[1].prndr->fbw<fbh< 0 ) + FlushTransferRanges(NULL); + + //g_GameSettings |= GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE; + //s_bWriteDepth = TRUE; + g_SaveFrameNum = 0; + //g_bSaveFlushedFrame = 1; +// static int counter = 0; +// counter++; + u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace<2); + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer + glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); + + // if interlace, only clear every other vsync + if(!bInterlace ) { + u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B); + glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + } + + SETVERTEXSHADER(pvsBitBlt.prog); + glBindBuffer(GL_ARRAY_BUFFER, vboRect); + SET_STREAM(); + GL_REPORT_ERRORD(); + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(1,1,1,1); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); + + GL_REPORT_ERRORD(); + + BOOL bUsingStencil = 0; + + if( bInterlace ) g_PrevBitwiseTexX = -1; // reset since will be using + + tex0Info dispinfo[2]; + + for(int i = 0; i < 2; ++i) { + + if( !(*(u32*)(PMODE) & (1<MAGH+1; + int magv = pd->MAGV+1; + + dispinfo[i].tbp0 = pfb->FBP << 5; + dispinfo[i].tbw = pfb->FBW << 6; + dispinfo[i].tw = (pd->DW + 1) / magh; + dispinfo[i].th = (pd->DH + 1) / magv; + dispinfo[i].psm = pfb->PSM; + + // hack!! + // 2 * dispinfo[i].tw / dispinfo[i].th <= 1, metal slug 4 + if( bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(g_GameSettings&GAME_INTERLACE2X) ) { + dispinfo[i].th >>= 1; + } + } + + //int dispwidth = max(dispinfo[0].tw, dispinfo[1].tw), dispheight = max(dispinfo[0].th, dispinfo[1].th); + + // hack!, CMOD != 3, gradius +// if( SMODE2->INT && SMODE2->FFMD && SMODE1->CMOD == 3 && dispwidth <= 320) +// dispwidth *= 2; + + // hack! makai + //if( !bInterlace && dispheight * 2 < dispwidth ) dispheight *= 2; + + // start from the last circuit + for(int i = !PMODE->SLBG; i >= 0; --i) { + + tex0Info& texframe = dispinfo[i]; + if( texframe.th <= 1 ) + continue; + + GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1; + GSRegDISPLAY* pd = i ? DISPLAY2 : DISPLAY1; + + Vector v, valpha; + u32 interlacetex = 0; + + if( bInterlace ) { + + texframe.th >>= 1; + + // interlace mode + interlacetex = CreateInterlaceTex(2*texframe.th); + + if( interlace == (conf.interlace&1) ) { + // pass if odd + valpha.z = 1.0f; + valpha.w = -0.4999f; + } + else { + // pass if even + valpha.z = -1.0f; + valpha.w = 0.5001f; + } + } + else { + + if( SMODE2->INT && SMODE2->FFMD ) { + texframe.th >>= 1; + } + + // always pass interlace test + valpha.z = 0; + valpha.w = 1; + } + + int bpp = 4; + if( texframe.psm == 0x12 ) bpp = 3; + else if( texframe.psm & 2 ) bpp = 2; + + // get the start and end addresses of the buffer + int start, end; + GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); + + if( i == 0 ) { + // setup right blending + glEnable(GL_BLEND); + zgsBlendEquationSeparateEXT(GL_FUNC_ADD, GL_FUNC_ADD); + + if( PMODE->MMOD ) { + glBlendColorEXT(PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), 0.5f); + s_srcrgb = GL_CONSTANT_COLOR_EXT; + s_dstrgb = GL_ONE_MINUS_CONSTANT_COLOR_EXT; + } + else { + s_srcrgb = GL_SRC_ALPHA; + s_dstrgb = GL_ONE_MINUS_SRC_ALPHA; + } + + s_srcalpha = PMODE->AMOD ? GL_ZERO : GL_ONE; + s_dstalpha = PMODE->AMOD? GL_ONE : GL_ZERO; + zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); + } + + if( bUsingStencil ) { + glStencilMask(1< listTargs; + + s_RTs.GetTargs(start, end, listTargs); + + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ) { + + CRenderTarget* ptarg = *it; + + if( ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256/bpp)*(texframe.tbp0-ptarg->fbp))%texframe.tbw == 0 ) { + + if( ptarg->fbp != texframe.tbp0 ) { + // look for a better target (metal slug 5) + list::iterator itbetter; + for(itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter ) { + if( (*itbetter)->fbp == texframe.tbp0 ) + break; + } + + if( itbetter != listTargs.end() ) { + it = listTargs.erase(it); + continue; + } + } + + if( g_bSaveFinalFrame ) + SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, ptarg->fbw<fbh<DBY; + int movy = 0; + + // determine the rectangle to render + if( ptarg->fbp < texframe.tbp0 ) { + dby += (256/bpp)*(texframe.tbp0-ptarg->fbp)/texframe.tbw; + } + else if( ptarg->fbp > texframe.tbp0 ) { + dby -= (256/bpp)*(ptarg->fbp-texframe.tbp0)/texframe.tbw; + + if( dby < 0 ) { + movy = -dby; + dby = 0; + } + } + + int dh = min(ptarg->fbh - dby, texframe.th-movy); + + if( dh >= 64 ) { + + if( ptarg->fbh - dby < texframe.th-movy && !bUsingStencil ) { + + if( !bUsingStencil ) { + glClear(GL_STENCIL_BUFFER_BIT); + } + bUsingStencil = 1; + glEnable(GL_STENCIL_TEST); + GL_STENCILFUNC(GL_NOTEQUAL, 3, 1<fbh; + + // tex coords + v = Vector((float)(texframe.tw << s_AAx), (float)(dh << s_AAy), (float)(pfb->DBX << s_AAx), (float)(dby< 0 ) + v.w -= movy/(float)texframe.th; + + if (bInterlace && interlace == (conf.interlace&1) ) { + // move down by 1 pixel + v.w += 1.0f / (float)dh; + } + + AdjustTransToAspect(v, 640, 480); + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + cgGLSetParameter4fv(pvsBitBlt.fBitBltTrans, Vector(fih * 0.5f, fih * -0.5f, fih * 0.5f, fih * 0.5f)); + + // use g_fInvTexDims to store inverse texture dims + if( ppsCRTCTarg[bInterlace].sInvTexDims ) { + v.x = fiw; + v.y = fih; + v.z = 0; + cgGLSetParameter4fv(ppsCRTCTarg[bInterlace].sInvTexDims, v); + } + + cgGLSetParameter4fv(ppsCRTCTarg[bInterlace].sOneColor, valpha); + + // inside vb[0]'s target area, so render that region only + cgGLSetTextureParameter(ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex); + cgGLEnableTextureParameter(ppsCRTCTarg[bInterlace].sFinal); + if( interlacetex != 0 ) { + cgGLSetTextureParameter(ppsCRTCTarg[bInterlace].sInterlace, interlacetex); + cgGLEnableTextureParameter(ppsCRTCTarg[bInterlace].sInterlace); + } + + SETPIXELSHADER(ppsCRTCTarg[bInterlace].prog); + GL_REPORT_ERRORD(); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + //SaveRenderTarget("temp.tga", nBackbufferWidth, nBackbufferHeight, 0); + + if( abs(dh - (int)texframe.th) <= 1 ) { + bSkip = 1; + break; + } + if( abs(dh - (int)ptarg->fbh) <= 1 ) { + it = listTargs.erase(it); + continue; + } + } + } + + ++it; + } + + if( !bSkip ) { + for(list::iterator it = listTargs.begin(); it != listTargs.end(); ++it) + (*it)->Resolve(); + + // context has to be 0 + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1); + SetTexVariablesInt(0, g_bCRTCBilinear?2:0, texframe, pmemtarg, &ppsCRTC[bInterlace], 1); + cgGLSetTextureParameter(ppsCRTC[bInterlace].sMemory, pmemtarg->ptex->tex); + cgGLEnableTextureParameter(ppsCRTC[bInterlace].sMemory); + + if( g_bSaveFinalFrame ) + SaveTex(&texframe, g_bSaveFinalFrame-1>0); + + // finally render from the memory (note that the stencil buffer will keep previous regions) + v = Vector(1,1,0,0); + + if (bInterlace && interlace == (conf.interlace)) { + // move down by 1 pixel + v.w += 1.0f / (float)texframe.th; + } + + cgGLSetParameter4fv(ppsCRTC[bInterlace].sOneColor, valpha); + + AdjustTransToAspect(v, 640, 480); + cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v); + + float fih = 1.0f / (float)texframe.th; + if( g_bCRTCBilinear ) + cgGLSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(texframe.tw,texframe.th,-0.5f,-0.5f)); + else + cgGLSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(1,1,-0.5f/(float)texframe.tw,-0.5f/(float)texframe.th)); + + cgGLSetParameter4fv(pvsBitBlt.fBitBltTrans, Vector(fih * 0.5f, fih * -0.5f, fih * 0.5f, fih * 0.5f)); + + // use g_fInvTexDims to store inverse texture dims + if( ppsCRTC[bInterlace].sInvTexDims ) { + v.x = 1.0f / (float)texframe.tw; + v.y = fih; + v.z = 0;//-0.5f * v.x; + v.w = -0.5f * fih; + cgGLSetParameter4fv(ppsCRTC[bInterlace].sInvTexDims, v); + } + + if( interlacetex != 0 ) { + cgGLSetTextureParameter(ppsCRTC[bInterlace].sInterlace, interlacetex); + cgGLEnableTextureParameter(ppsCRTC[bInterlace].sInterlace); + } + + SETPIXELSHADER(ppsCRTC[bInterlace].prog); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + GL_REPORT_ERRORD(); + if(1) {// || !bInterlace) { + glDisable(GL_BLEND); + ProcessMessages(); + + if( g_bMakeSnapshot ) { + char str[64]; + int left = 200, top = 15; + sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", revision, build, minor, fFPS, s_frameskipping?" - frameskipping":""); + + DrawText(str, left+1, top+1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); + } + + if( g_bDisplayFPS ) { + char str[64]; + int left = 10, top = 15; + sprintf(str, "%.1f fps", fFPS); + + DrawText(str, left+1, top+1, 0xff000000); + DrawText(str, left, top, 0xffc0ffff); + } + + if( glGetError() != GL_NO_ERROR ) { + printf("glerror before swap!\n"); + } + +#ifdef _WIN32 + static u32 lastswaptime = 0; + //if( timeGetTime() - lastswaptime > 14 ) { + SwapBuffers(hDC); + lastswaptime = timeGetTime(); + //} +#else + glXSwapBuffers(GLWin.dpy, GLWin.win); +#endif + +// if( glGetError() != GL_NO_ERROR) { +// // device is lost, need to recreate +// ERROR_LOG("device lost\n"); +// g_bIsLost = TRUE; +// Reset(); +// return; +// } + + if( conf.options & GSOPTION_WIREFRAME ) { + // clear all targets + s_nWireframeCount = 1; + } + + if( g_bMakeSnapshot ) { + + if( SaveRenderTarget(strSnapshot != ""?strSnapshot.c_str():"temp.jpg", nBackbufferWidth, -nBackbufferHeight, 0)) {//(conf.options&GSOPTION_TGASNAP)?0:1) ) { + char str[255]; + sprintf(str, "saved %s\n", strSnapshot.c_str()); + AddMessage(str, 500); + } + + g_bMakeSnapshot = 0; + } + + if( s_avicapturing ) { + CaptureFrame(); + } + + if( s_nNewWidth >= 0 && s_nNewHeight >= 0 && !g_bIsLost ) { + Reset(); + ChangeDeviceSize(s_nNewWidth, s_nNewHeight); + s_nNewWidth = s_nNewHeight = -1; + } + + // switch the fbp lists +// s_nCurFBPSet ^= 1; +// s_setFBP[s_nCurFBPSet].clear(); + //s_nCurFrameMap ^= 1; + //s_mapFrameHeights[s_nCurFrameMap].clear(); + } + + // switch back to rendering to textures + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); + + g_MemTargs.DestroyCleared(); + + if( s_vecTempTextures.size() > 0 ) + glDeleteTextures((GLsizei)s_vecTempTextures.size(), &s_vecTempTextures[0]); + s_vecTempTextures.clear(); + + if( EXTWRITE->WRITE&1 ) { + WARN_LOG("EXTWRITE\n"); + ExtWrite(); + EXTWRITE->WRITE = 0; + } + + if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_SCISSOR_TEST); + + if( icurctx >= 0 ) { + vb[icurctx].bVarsSetTarg = FALSE; + vb[icurctx].bVarsTexSync = FALSE; + vb[0].bVarsTexSync = FALSE; + } + + // statistics + if( s_nWriteDepthCount > 0 ) { + assert( conf.mrtdepth ); + if( --s_nWriteDepthCount <= 0 ) { + s_bWriteDepth = FALSE; + } + } + + if( s_nWriteDestAlphaTest > 0 ) { + if( --s_nWriteDestAlphaTest <= 0 ) { + s_bDestAlphaTest = FALSE; + } + } + + if( g_GameSettings & GAME_AUTORESET ) { + s_nResolveCounts[s_nCurResolveIndex] = s_nResolved; + s_nCurResolveIndex = (s_nCurResolveIndex+1)%ARRAY_SIZE(s_nResolveCounts); + + int total = 0; + for(int i = 0; i < ARRAY_SIZE(s_nResolveCounts); ++i) total += s_nResolveCounts[i]; + + if( total / ARRAY_SIZE(s_nResolveCounts) > 3 ) { + if( s_nLastResolveReset > (int)(fFPS * 8) ) { + // reset + ERROR_LOG("video mem reset\n"); + s_nLastResolveReset = 0; + memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts)); + + s_RTs.ResolveAll(); + s_RTs.Destroy(); + s_DepthRTs.ResolveAll(); + s_DepthRTs.Destroy(); + + vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1; + vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1; + } + } + + s_nLastResolveReset++; + } + + if( s_nResolved > 8 ) s_nResolved = 2; + else if( s_nResolved > 0 ) --s_nResolved; + + if( g_nDepthUsed > 0 ) --g_nDepthUsed; + + s_ClutResolve = 0; + g_nDepthUpdateCount = 0; + + maxmin = 608; +} + +////////////////////////// +// Internal Definitions // +////////////////////////// + +#define MOVZ(p, gsz) p.z = curvb.zprimmask==0xffff?min((u32)0xffff, gsz):gsz; +#define MOVFOG(p, gsf) p.f = ((s16)(gsf).f<<7)|0x7f; + +#define SET_VERTEX(p, Index) { \ + int index = Index; \ + p.x = (((int)gs.gsvertex[index].x - curvb.offset.x)>>1)&0xffff; \ + p.y = (((int)gs.gsvertex[index].y - curvb.offset.y)>>1)&0xffff; \ + /*x = ((int)gs.gsvertex[index].x - curvb.offset.x); \ + y = ((int)gs.gsvertex[index].y - curvb.offset.y); \ + p.x = (x&0x7fff) | (x < 0 ? 0x8000 : 0); \ + p.y = (y&0x7fff) | (y < 0 ? 0x8000 : 0);*/ \ + p.f = ((s16)gs.gsvertex[index].f<<7)|0x7f; \ + MOVZ(p, gs.gsvertex[index].z); \ + p.rgba = prim->iip ? gs.gsvertex[index].rgba : gs.rgba; \ + if( (g_GameSettings & GAME_TEXAHACK) && !(p.rgba&0xffffff) ) \ + p.rgba = 0; \ + if( prim->tme ) { \ + if( prim->fst ) { \ + p.s = (float)gs.gsvertex[index].u * fiTexWidth[prim->ctxt]; \ + p.t = (float)gs.gsvertex[index].v * fiTexHeight[prim->ctxt]; \ + p.q = 1; \ + } \ + else { \ + p.s = gs.gsvertex[index].s; \ + p.t = gs.gsvertex[index].t; \ + p.q = gs.gsvertex[index].q; \ + } \ + } \ +} \ + +#define OUTPUT_VERT(fn, vert, id) { \ + fn("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)\n", id==0?'*':' ', id, prim->prim, vert.x/8, vert.y/8, vert.z, vert.f/128, \ + vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10)); \ +} \ + +//#define OUTPUT_VERT(fn, vert, id) { \ +// fn("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d)\n", id==0?'*':' ', id, prim->prim, vert.x/8, vert.y/8, vert.z, vert.f/128); \ +//} \ + +void ZeroGS::KickPoint() +{ + assert( gs.primC >= 1 ); + + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(1); + + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(p[0], last); + curvb.nCount++; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); +#endif +} + +void ZeroGS::KickLine() +{ + assert( gs.primC >= 2 ); + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(2); + + int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(p[0], next); + SET_VERTEX(p[1], last); + + curvb.nCount += 2; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); +#endif +} + +void ZeroGS::KickTriangle() +{ + assert( gs.primC >= 3 ); + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(3); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(p[0], 0); + SET_VERTEX(p[1], 1); + SET_VERTEX(p[2], 2); + + curvb.nCount += 3; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); + OUTPUT_VERT(PRIM_LOG, p[2], 2); +#endif +} + +void ZeroGS::KickTriangleFan() +{ + assert( gs.primC >= 3 ); + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(3); + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + SET_VERTEX(p[0], 0); + SET_VERTEX(p[1], 1); + SET_VERTEX(p[2], 2); + + curvb.nCount += 3; + + // add 1 to skip the first vertex + if( gs.primIndex == gs.nTriFanVert ) + gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); + OUTPUT_VERT(PRIM_LOG, p[2], 2); +#endif +} + +void ZeroGS::KickSprite() +{ + assert( gs.primC >= 2 ); + VB& curvb = vb[prim->ctxt]; + if( curvb.bNeedTexCheck ) + curvb.FlushTexData(); + + if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp ) + { + assert( vb[prim->ctxt].nCount == 0 ); + Flush(!prim->ctxt); + } + + curvb.NotifyWrite(6); + + int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex); + int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex); + + // sprite is too small and AA shows lines (tek4) + if( s_AAx ) { + gs.gsvertex[last].x += 4; + if( s_AAy ) + gs.gsvertex[last].y += 4; + } + + // might be bad sprite (KH dialog text) + //if( gs.gsvertex[next].x == gs.gsvertex[last].x || gs.gsvertex[next].y == gs.gsvertex[last].y ) + // return; + + VertexGPU* p = curvb.pBufferData+curvb.nCount; + + SET_VERTEX(p[0], next); MOVZ(p[0], gs.gsvertex[last].z); MOVFOG(p[0], gs.gsvertex[last]); + SET_VERTEX(p[3], next); MOVZ(p[3], gs.gsvertex[last].z); MOVFOG(p[3], gs.gsvertex[last]); + + SET_VERTEX(p[1], last); MOVZ(p[1], gs.gsvertex[last].z); MOVFOG(p[1], gs.gsvertex[last]); + SET_VERTEX(p[4], last); MOVZ(p[4], gs.gsvertex[last].z); MOVFOG(p[4], gs.gsvertex[last]); + + SET_VERTEX(p[2], next); MOVZ(p[2], gs.gsvertex[last].z); MOVFOG(p[2], gs.gsvertex[last]); + p[2].s = p[1].s; + p[2].x = p[1].x; + + SET_VERTEX(p[5], last); MOVZ(p[5], gs.gsvertex[last].z); MOVFOG(p[5], gs.gsvertex[last]); + p[5].s = p[0].s; + p[5].x = p[0].x; + + curvb.nCount += 6; + +#ifdef PRIM_LOG + OUTPUT_VERT(PRIM_LOG, p[0], 0); + OUTPUT_VERT(PRIM_LOG, p[1], 1); +#endif +} + +void ZeroGS::KickDummy() +{ + //GREG_LOG("Kicking bad primitive: %.8x\n", *(u32*)prim); +} + +__forceinline void ZeroGS::RenderFBA(const VB& curvb, CGparameter sOneColor) +{ + // add fba to all pixels + GL_STENCILFUNC(GL_ALWAYS, STENCIL_FBA, 0xff); + glStencilMask(STENCIL_CLEAR); + glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,0); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL, 1); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + cgGLSetParameter4fv(sOneColor, v); + + DRAW(); + + if( !curvb.test.ate ) + glDisable(GL_ALPHA_TEST); + else { + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], b2XAlphaTest ? min(1.0f,curvb.test.aref*(1/127.5f)) : curvb.test.aref*(1/255.0f)); + } + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + assert( curvb.pdepth != NULL ); + if( s_bWriteDepth ) { + curvb.pdepth->SetRenderTarget(1); + } + } + GL_ZTEST(curvb.test.zte); +} + +__forceinline void ZeroGS::RenderAlphaTest(const VB& curvb, CGparameter sOneColor) +{ + if( !g_bUpdateStencil ) return; + + if( curvb.test.ate ) { + if( curvb.test.afail == 1 ) glDisable(GL_ALPHA_TEST); + } + + glDepthMask(0); + glColorMask(0,0,0,0); + + Vector v; + v.x = 1; v.y = 2; v.z = 0; v.w = 0; + cgGLSetParameter4fv(sOneColor, v); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + + // or a 1 to the stencil buffer wherever alpha passes + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + s_stencilfunc = GL_ALWAYS; + + glEnable(GL_STENCIL_TEST); + + if( !s_bDestAlphaTest ) { + // clear everything + s_stencilref = 0; + glStencilMask(STENCIL_CLEAR); + glDisable(GL_ALPHA_TEST); + GL_STENCILFUNC_SET(); + DRAW(); + + if( curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING ) + glEnable(GL_ALPHA_TEST); + } + + if( curvb.test.ate && curvb.test.atst>1 && curvb.test.aref > 0x80) { + v.x = 1; v.y = 1; v.z = 0; v.w = 0; + cgGLSetParameter4fv(sOneColor, v); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], curvb.test.aref*(1/255.0f)); + } + + s_stencilref = STENCIL_SPECIAL; + glStencilMask(STENCIL_SPECIAL); + GL_STENCILFUNC_SET(); + glDisable(GL_DEPTH_TEST); + + DRAW(); + + if( curvb.test.zte ) + glEnable(GL_DEPTH_TEST); + GL_ALPHATEST(0); + GL_COLORMASK(s_dwColorWrite); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + // set rt next level + if( s_bWriteDepth ) { + curvb.pdepth->SetRenderTarget(1); + } + } +} + +__forceinline void ZeroGS::RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting) +{ + //NOTE: This stencil hack for dest alpha testing ONLY works when + // the geometry in one DrawPrimitive call does not overlap + + // mark the stencil buffer for the new data's bits (mark 4 if alpha is >= 0xff) + // mark 4 if a pixel was written (so that the stencil buf can be changed with new values) + glStencilMask(STENCIL_PIXELWRITE); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + s_stencilmask = (curvb.test.date?STENCIL_ALPHABIT:0)|(dwUsingSpecialTesting?STENCIL_SPECIAL:0); + s_stencilfunc = s_stencilmask ? GL_EQUAL : GL_ALWAYS; + s_stencilref = curvb.test.date*curvb.test.datm|STENCIL_PIXELWRITE|(dwUsingSpecialTesting?STENCIL_SPECIAL:0); + GL_STENCILFUNC_SET(); +} + +__forceinline void ZeroGS::ProcessStencil(const VB& curvb) +{ + assert( !curvb.fba.fba ); + + // set new alpha bit + glStencilMask(STENCIL_ALPHABIT); + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE, STENCIL_PIXELWRITE|STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,0); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + + GL_ALPHATEST(0); + + SETPIXELSHADER(ppsOne.prog); + DRAW(); + + // process when alpha >= 0xff + GL_STENCILFUNC(GL_EQUAL, STENCIL_PIXELWRITE|STENCIL_FBA|STENCIL_ALPHABIT, STENCIL_PIXELWRITE|STENCIL_FBA); + DRAW(); + + // clear STENCIL_PIXELWRITE bit + glStencilMask(STENCIL_CLEAR); + GL_STENCILFUNC(GL_ALWAYS, 0, STENCIL_PIXELWRITE|STENCIL_FBA); + + DRAW(); + + // restore state + GL_COLORMASK(s_dwColorWrite); + + if( curvb.test.ate && USEALPHATESTING) + glEnable(GL_ALPHA_TEST); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + assert( curvb.pdepth != NULL ); + curvb.pdepth->SetRenderTarget(1); + } + } + + GL_ZTEST(curvb.test.zte); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +} + +__forceinline void ZeroGS::ProcessFBA(const VB& curvb, CGparameter sOneColor) +{ + if( (curvb.frame.fbm&0x80000000) ) return; + + // add fba to all pixels that were written and alpha was less than 0xff + glStencilMask(STENCIL_ALPHABIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + GL_STENCILFUNC(GL_EQUAL, STENCIL_FBA|STENCIL_PIXELWRITE|STENCIL_ALPHABIT, STENCIL_PIXELWRITE|STENCIL_FBA); + + glDisable(GL_DEPTH_TEST); + glDepthMask(0); + glColorMask(0,0,0,1); + + if( s_bWriteDepth ) { + ResetRenderTarget(1); + } + + // processes the pixels with ALPHA < 0x80*2 + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_LEQUAL, 1); + + // add 1 to dest + GL_BLEND_ALPHA(GL_ONE, GL_ONE); + GL_BLENDEQ_ALPHA(GL_FUNC_ADD); + + float f = 1; + cgGLSetParameter4fv(sOneColor, &f); + SETPIXELSHADER(ppsOne.prog); + + DRAW(); + + glDisable(GL_ALPHA_TEST); + + // reset bits + glStencilMask(STENCIL_CLEAR); + GL_STENCILFUNC(GL_GREATER, 0, STENCIL_PIXELWRITE|STENCIL_FBA); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + + DRAW(); + + if( curvb.test.atst && USEALPHATESTING) { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], b2XAlphaTest ? min(1.0f,curvb.test.aref*(1/127.5f)) : curvb.test.aref*(1/255.0f)); + } + + // restore (SetAlphaVariables) + GL_BLEND_ALPHA(GL_ONE, GL_ZERO); + if(vAlphaBlendColor.y<0) GL_BLENDEQ_ALPHA(GL_FUNC_REVERSE_SUBTRACT); + + // reset (not necessary) + GL_COLORMASK(s_dwColorWrite); + + if( !curvb.zbuf.zmsk ) { + glDepthMask(1); + + if( s_bWriteDepth ) { + curvb.pdepth->SetRenderTarget(1); + } + } + GL_ZTEST(curvb.test.zte); +} + +inline void ZeroGS::SetContextTarget(int context) +{ + VB& curvb = vb[context]; + GL_REPORT_ERRORD(); + + if( curvb.prndr == NULL ) + curvb.prndr = s_RTs.GetTarg(curvb.frame, 0, GET_MAXHEIGHT(curvb.gsfb.fbp, curvb.gsfb.fbw, curvb.gsfb.psm)); + + // make sure targets are valid + if( curvb.pdepth == NULL ) { + frameInfo f; + f.fbp = curvb.zbuf.zbp; + f.fbw = curvb.frame.fbw; + f.fbh = curvb.prndr->fbh; + f.psm = curvb.zbuf.psm; + f.fbm = 0; + curvb.pdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer|CRenderTargetMngr::TO_StrictHeight| + (curvb.zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), GET_MAXHEIGHT(curvb.zbuf.zbp, curvb.gsfb.fbw, 0)); + } + + assert( curvb.prndr != NULL && curvb.pdepth != NULL ); + assert( curvb.pdepth->fbh == curvb.prndr->fbh ); + + if( curvb.pdepth->status & CRenderTarget::TS_Virtual) { + + if( !curvb.zbuf.zmsk ) { + CRenderTarget* ptemp = s_DepthRTs.Promote(curvb.pdepth->fbp|(curvb.pdepth->fbw<<16)); + assert( ptemp == curvb.pdepth ); + } + else + curvb.pdepth->status &= ~CRenderTarget::TS_NeedUpdate; + } + + BOOL bSetTarg = 1; + if( curvb.pdepth->status & CRenderTarget::TS_NeedUpdate ) { + + assert( !(curvb.pdepth->status & CRenderTarget::TS_Virtual) ); + + // don't update if virtual + curvb.pdepth->Update(context, curvb.prndr); + bSetTarg = 0; + } + + GL_REPORT_ERRORD(); + if( curvb.prndr->status & CRenderTarget::TS_NeedUpdate ) { + +// if( s_bWriteDepth ) { +// if( bSetTarg ) { +// curvb.pdepth->SetRenderTarget(1); +// curvb.pdepth->SetDepthStencilSurface(); +// } +// } +// else if( bSetTarg ) +// curvb.pdepth->SetDepthStencilSurface(); + + curvb.prndr->Update(context, curvb.pdepth); + } + else { + + //if( (vb[0].prndr != vb[1].prndr && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg ) + curvb.prndr->SetRenderTarget(0); + //if( bSetTarg && ((vb[0].pdepth != vb[1].pdepth && vb[!context].bVarsSetTarg) || !vb[context].bVarsSetTarg) ) + curvb.pdepth->SetDepthStencilSurface(); + if( conf.mrtdepth && ZeroGS::IsWriteDepth() ) + curvb.pdepth->SetRenderTarget(1); + + if( s_ptexCurSet[0] == curvb.prndr->ptex ) { + s_ptexCurSet[0] = 0; + } + if( s_ptexCurSet[1] == curvb.prndr->ptex ) { + s_ptexCurSet[1] = 0; + } + + curvb.prndr->SetViewport(); + } + + curvb.prndr->SetTarget(curvb.frame.fbp, curvb.scissor, context); + + if( (curvb.zbuf.zbp-curvb.pdepth->fbp) != (curvb.frame.fbp - curvb.prndr->fbp) && curvb.test.zte ) { + WARN_LOG("frame and zbuf not aligned\n"); + } + + curvb.bVarsSetTarg = TRUE; + if( vb[!context].prndr != curvb.prndr ) + vb[!context].bVarsSetTarg = FALSE; + + assert( !(curvb.prndr->status&CRenderTarget::TS_NeedUpdate) ); + assert( curvb.pdepth == NULL || !(curvb.pdepth->status&CRenderTarget::TS_NeedUpdate) ); + GL_REPORT_ERRORD(); +} + +void ZeroGS::SetTexVariables(int context, FRAGMENTSHADER* pfragment, int settexint) +{ + if( !vb[context].curprim.tme ) { + return; + } + + DVProfileFunc _pf("SetTexVariables"); + + assert( !vb[context].bNeedTexCheck ); + + Vector v, v2; + tex0Info& tex0 = vb[context].tex0; + + float fw = (float)tex0.tw; + float fh = (float)tex0.th; + + if( !vb[context].bTexConstsSync ) { + // alpha and texture highlighting + Vector valpha, valpha2; + + // if clut, use the frame format + int psm = tex0.psm; + if( PSMT_ISCLUT(tex0.psm) ) psm = tex0.cpsm; + + int nNeedAlpha = (psm == 1 || psm == 2 || psm == 10); + + Vector vblack; + vblack.x = vblack.y = vblack.z = vblack.w = 10; + + switch(tex0.tfx) { + case 0: + valpha.z = 0; valpha.w = 0; + valpha2.x = 0; valpha2.y = 0; + valpha2.z = 2; valpha2.w = 1; + + break; + case 1: + valpha.z = 0; valpha.w = 1; + valpha2.x = 1; valpha2.y = 0; + valpha2.z = 0; valpha2.w = 0; + + break; + case 2: + valpha.z = 1; valpha.w = 1.0f; + valpha2.x = 0; valpha2.y = tex0.tcc ? 1.0f : 0.0f; + valpha2.z = 2; valpha2.w = 0; + + break; + + case 3: + valpha.z = 1; valpha.w = tex0.tcc ? 0.0f : 1.0f; + valpha2.x = 0; valpha2.y = tex0.tcc ? 1.0f : 0.0f; + valpha2.z = 2; valpha2.w = 0; + + break; + } + + if( tex0.tcc ) { + + if( tex0.tfx == 1 ) { + //mode.x = 10; + valpha.z = 0; valpha.w = 0; + valpha2.x = 1; valpha2.y = 1; + valpha2.z = 0; valpha2.w = 0; + } + + if( nNeedAlpha ) { + + if( tex0.tfx == 0 ) { + // make sure alpha is mult by two when the output is Cv = Ct*Cf + valpha.x = 2*gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha.y = 2*gs.texa.fta[psm != 1]; + valpha.y -= valpha.x; + } + else { + valpha.x = gs.texa.fta[0]; + // if 24bit, always choose ta[0] + valpha.y = gs.texa.fta[psm != 1]; + valpha.y -= valpha.x; + } + + // need black detection + if( gs.texa.aem && psm == PSMCT24 ) + vblack.w = 0; + } + else { + if( tex0.tfx == 0 ) { + valpha.x = 0; + valpha.y = 2; + } + else { + valpha.x = 0; + valpha.y = 1; + } + } + } + else { + + // reset alpha to color + valpha.x = valpha.y = 0; + valpha.w = 1; + } + + cgGLSetParameter4fv(pfragment->fTexAlpha, valpha); + cgGLSetParameter4fv(pfragment->fTexAlpha2, valpha2); + if( tex0.tcc && gs.texa.aem && (psm == PSMCT24 || psm == PSMCT16 || psm == PSMCT16S) ) + cgGLSetParameter4fv(pfragment->fTestBlack, vblack); + + // clamp relies on texture width + { + clampInfo* pclamp = &ZeroGS::vb[context].clamp; + Vector v, v2; + v.x = v.y = 0; + u32* ptex = ZeroGS::vb[context].ptexClamp; + ptex[0] = ptex[1] = 0; + + float fw = ZeroGS::vb[context].tex0.tw; + float fh = ZeroGS::vb[context].tex0.th; + + switch(pclamp->wms) { + case 0: + v2.x = -1e10; v2.z = 1e10; + break; + case 1: // pclamp + // suikoden5 movie text + v2.x = 0; v2.z = 1-0.5f/fw; + break; + case 2: // reg pclamp + v2.x = (pclamp->minu+0.5f)/fw; v2.z = (pclamp->maxu-0.5f)/fw; + break; + + case 3: // region rep x + v.x = 0.9999f; + v.z = fw / (float)GPU_TEXMASKWIDTH; + v2.x = (float)GPU_TEXMASKWIDTH / fw; + v2.z = pclamp->maxu / fw; + + if( pclamp->minu != g_PrevBitwiseTexX ) { + g_PrevBitwiseTexX = pclamp->minu; + ptex[0] = ZeroGS::s_BitwiseTextures.GetTex(pclamp->minu, 0); + } + break; + } + + switch(pclamp->wmt) { + case 0: + v2.y = -1e10; v2.w = 1e10; + break; + case 1: // pclamp + // suikoden5 movie text + v2.y = 0; v2.w = 1-0.5f/fh; + break; + case 2: // reg pclamp + v2.y = (pclamp->minv+0.5f)/fh; v2.w = (pclamp->maxv-0.5f)/fh; + break; + + case 3: // region rep y + v.y = 0.9999f; + v.w = fh / (float)GPU_TEXMASKWIDTH; + v2.y = (float)GPU_TEXMASKWIDTH / fh; + v2.w = pclamp->maxv / fh; + + if( pclamp->minv != g_PrevBitwiseTexY ) { + g_PrevBitwiseTexY = pclamp->minv; + ptex[1] = ZeroGS::s_BitwiseTextures.GetTex(pclamp->minv, ptex[0]); + } + break; + } + + if( pfragment->fTexWrapMode != 0 ) + cgGLSetParameter4fv(pfragment->fTexWrapMode, v); + if( pfragment->fClampExts != 0 ) + cgGLSetParameter4fv(pfragment->fClampExts, v2); + } + + vb[context].bTexConstsSync = TRUE; + } + + if(s_bTexFlush ) { + if( PSMT_ISCLUT(tex0.psm) ) + texClutWrite(context); + else + s_bTexFlush = FALSE; + } + + if( settexint ) { + CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(tex0, 1); + + if( vb[context].bVarsTexSync ) { + if( vb[context].pmemtarg != pmemtarg ) { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, pmemtarg, pfragment, s_bForceTexFlush); + vb[context].bVarsTexSync = TRUE; + } + } + else { + SetTexVariablesInt(context, GetTexFilter(vb[context].tex1), tex0, pmemtarg, pfragment, s_bForceTexFlush); + vb[context].bVarsTexSync = TRUE; + + INC_TEXVARS(); + } + } + else { + vb[context].bVarsTexSync = FALSE; + } +} + +void ZeroGS::SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, CMemoryTarget* pmemtarg, FRAGMENTSHADER* pfragment, int force) +{ + DVProfileFunc _pf("SetTexVariablesInt"); + + Vector v; + assert( pmemtarg != NULL && pfragment != NULL); + + float fw = (float)tex0.tw; + float fh = (float)tex0.th; + + bool bUseBilinear = bilinear > 1 || (bilinear && conf.bilinear); + if( bUseBilinear ) { + v.x = (float)fw; + v.y = (float)fh; + v.z = 1.0f / (float)fw; + v.w = 1.0f / (float)fh; + cgGLSetParameter4fv(pfragment->fRealTexDims, v); + } + + if( m_Blocks[tex0.psm].bpp == 0 ) { + ERROR_LOG("Undefined tex psm 0x%x!\n", tex0.psm); + return; + } + + const BLOCK& b = m_Blocks[tex0.psm]; + + float fbw = (float)tex0.tbw; + + Vector vTexDims; + vTexDims.x = b.vTexDims.x * fw; + vTexDims.y = b.vTexDims.y * fh; + vTexDims.z = (float)BLOCK_TEXWIDTH*(0.002f / 64.0f + 0.01f/128.0f); + vTexDims.w = (float)BLOCK_TEXHEIGHT*0.2f/512.0f; + + if( bUseBilinear ) { + vTexDims.x *= 1/128.0f; + vTexDims.y *= 1/512.0f; + vTexDims.z *= 1/128.0f; + vTexDims.w *= 1/512.0f; + } + + float g_fitexwidth = g_fiGPU_TEXWIDTH/(float)pmemtarg->widthmult; + float g_texwidth = GPU_TEXWIDTH*(float)pmemtarg->widthmult; + + float fpage = tex0.tbp0*(64.0f*g_fitexwidth) + 0.05f * g_fitexwidth; + float fpageint = floorf(fpage); + int starttbp = (int)fpage; + + // 2048 is number of words to span one page + float fblockstride = (2048.0f /(float)(g_texwidth*BLOCK_TEXWIDTH)) * b.vTexDims.x * fbw; + assert( fblockstride >= 1.0f ); + + v.x = (float)(2048 * g_fitexwidth); + v.y = fblockstride; + v.z = g_fBlockMult/(float)pmemtarg->widthmult; + v.w = fpage-fpageint; + + if( g_fBlockMult > 1 ) { + // make sure to divide by mult (since the G16R16 texture loses info) + v.z *= b.bpp * (1/32.0f); + } + + cgGLSetParameter4fv(pfragment->fTexDims, vTexDims); + cgGLSetParameter4fv(pfragment->fTexBlock, &b.vTexBlock.x); + cgGLSetParameter4fv(pfragment->fTexOffset, v); + + // get hardware texture dims + int texheight = (pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult; + int texwidth = GPU_TEXWIDTH*pmemtarg->widthmult*pmemtarg->channels; + + v.y = 1;//(float)1.0f / (float)((pmemtarg->realheight+pmemtarg->widthmult-1)/pmemtarg->widthmult); + v.x = (fpageint-(float)pmemtarg->realy/(float)pmemtarg->widthmult+0.5f);//*v.y; + +// v.x *= (float)texheight; +// v.y *= (float)texheight; + v.z = (float)texwidth; + if( !(g_nPixelShaderVer & SHADER_ACCURATE) || bUseBilinear ) + v.w = 0.25f; + else + v.w = 0.5f; + + cgGLSetParameter4fv(pfragment->fPageOffset, v); + + if( force ) s_ptexCurSet[context] = pmemtarg->ptex->tex; + else s_ptexNextSet[context] = pmemtarg->ptex->tex; + vb[context].pmemtarg = pmemtarg; + + vb[context].bVarsTexSync = FALSE; +} + +// assumes texture factor is unused +#define SET_ALPHA_COLOR_FACTOR(sign) { \ + switch(a.c) { \ + case 0: \ + vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \ + s_srcalpha = GL_ONE; \ + s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \ + break; \ + case 1: \ + /* if in 24 bit mode, dest alpha should be one */ \ + switch(vb[icurctx].prndr->psm&0xf) { \ + case 0: \ + bDestAlphaColor = (a.d!=2)&&((a.a==a.d)||(a.b==a.d)); \ + break; \ + case 1: \ + /* dest alpha should be one */ \ + bDestAlphaColor = 2; \ + break; \ + /* default: 16bit surface, so returned alpha is ok */ \ + } \ + break; \ + \ + case 2: \ + bNeedBlendFactorInAlpha = 1; /* should disable alpha channel writing */ \ + vAlphaBlendColor.y = 0; \ + vAlphaBlendColor.w = (sign) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f); \ + usec = 0; /* change so that alpha comes from source*/ \ + break; \ + } \ +} \ + +//if( a.fix <= 0x80 ) { \ +// dwTemp = (a.fix*2)>255?255:(a.fix*2); \ +// dwTemp = dwTemp|(dwTemp<<8)|(dwTemp<<16)|0x80000000; \ +// printf("bfactor: %8.8x\n", dwTemp); \ +// glBlendColorEXT(dwTemp); \ +// } \ +// else { \ + +void ZeroGS::ResetAlphaVariables() +{ +} + +void ZeroGS::SetAlphaVariables(const alphaInfo& a) +{ + bool alphaenable = true; + + // TODO: negative color when not clamping turns to positive??? + g_vars._bAlphaState = 0; // set all to zero + bNeedBlendFactorInAlpha = 0; + b2XAlphaTest = 1; + u32 dwTemp = 0xffffffff; + + // default + s_srcalpha = GL_ONE; + s_dstalpha = GL_ZERO; + s_alphaeq = GL_FUNC_ADD; + + s_alphaInfo = a; + + vAlphaBlendColor = Vector(1,2*255.0f/256.0f,0,0); + u32 usec = a.c; + + if( a.a == a.b ) { // just d remains + if( a.d == 0 ) { + alphaenable = false; + } + else { + s_dstrgb = a.d == 1 ? GL_ONE : GL_ZERO; + s_srcrgb = GL_ZERO; + s_rgbeq = GL_FUNC_ADD; + } + + goto EndSetAlpha; + } + else if( a.d == 2 ) { // zero + + if( a.a == 2 ) { + // zero all color + s_srcrgb = GL_ZERO; + s_dstrgb = GL_ZERO; + goto EndSetAlpha; + } + else if( a.b == 2 ) { + //b2XAlphaTest = 1; + + SET_ALPHA_COLOR_FACTOR(1); + + if( bDestAlphaColor == 2 ) { + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = a.a == 0 ? GL_ONE : GL_ZERO; + s_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE; + } + else { + bAlphaClamping = 2; + + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = a.a == 0 ? blendalpha[usec] : GL_ZERO; + s_dstrgb = a.a == 0 ? GL_ZERO : blendalpha[usec]; + } + + goto EndSetAlpha; + } + + // nothing is zero, so must do some real blending + //b2XAlphaTest = 1; + bAlphaClamping = 3; + + SET_ALPHA_COLOR_FACTOR(1); + + s_rgbeq = a.a == 0 ? GL_FUNC_SUBTRACT : GL_FUNC_REVERSE_SUBTRACT; + s_srcrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + s_dstrgb = bDestAlphaColor == 2 ? GL_ONE : blendalpha[usec]; + } + else if( a.a == 2 ) { // zero + + //b2XAlphaTest = 1; + bAlphaClamping = 1; // min testing + + SET_ALPHA_COLOR_FACTOR(1); + + if( a.b == a.d ) { + // can get away with 1-A + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendinvalpha[usec] : GL_ZERO; + s_dstrgb = (a.b == 0 || bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]; + } + else { + s_rgbeq = a.b==0 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_SUBTRACT; + s_srcrgb = (a.b == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + s_dstrgb = (a.b == 0 || bDestAlphaColor == 2 ) ? GL_ONE : blendalpha[usec]; + } + } + else if( a.b == 2 ) { + bAlphaClamping = 2; // max testing + + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) { + // can get away with 1+A, but need to set alpha to negative + s_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) { + assert(usec==1); + + // all ones + bNeedBlendFactorInAlpha = 1; + vAlphaBlendColor.y = 0; + vAlphaBlendColor.w = -1; + s_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_ZERO; + s_dstrgb = a.a == 0 ? GL_ZERO : GL_ONE_MINUS_SRC_ALPHA; + } + else { + s_srcrgb = a.a == 0 ? blendinvalpha[usec] : GL_ZERO; + s_dstrgb = a.a == 0 ? GL_ZERO : blendinvalpha[usec]; + } + } + else { + //b2XAlphaTest = 1; + s_rgbeq = GL_FUNC_ADD; + s_srcrgb = (a.a == 0 && bDestAlphaColor != 2) ? blendalpha[usec] : GL_ONE; + s_dstrgb = (a.a == 0 || bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]; + } + } + else { + // all 3 components are valid! + bAlphaClamping = 3; // all testing + SET_ALPHA_COLOR_FACTOR(a.a!=a.d); + + if( a.a == a.d ) { + // can get away with 1+A, but need to set alpha to negative + s_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) { + assert(usec==1); + + // all ones + bNeedBlendFactorInAlpha = 1; + vAlphaBlendColor.y = 0; + vAlphaBlendColor.w = -1; + s_srcrgb = a.a == 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + s_dstrgb = a.a == 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else { + s_srcrgb = a.a == 0 ? blendinvalpha[usec] : blendalpha[usec]; + s_dstrgb = a.a == 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + else { + assert(a.b == a.d); + s_rgbeq = GL_FUNC_ADD; + + if( bDestAlphaColor == 2 ) { + assert(usec==1); + + // all ones + bNeedBlendFactorInAlpha = 1; + vAlphaBlendColor.y = 0; + vAlphaBlendColor.w = 1; + s_srcrgb = a.a != 0 ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; + s_dstrgb = a.a != 0 ? GL_SRC_ALPHA : GL_ONE_MINUS_SRC_ALPHA; + } + else { + //b2XAlphaTest = 1; + s_srcrgb = a.a != 0 ? blendinvalpha[usec] : blendalpha[usec]; + s_dstrgb = a.a != 0 ? blendalpha[usec] : blendinvalpha[usec]; + } + } + } + +EndSetAlpha: + + GL_BLEND_SET(); + zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); + if( alphaenable ) glEnable(GL_BLEND); // always set + else glDisable(GL_BLEND); + + INC_ALPHAVARS(); +} + +void ZeroGS::SetWriteDepth() +{ + if( conf.mrtdepth ) { + s_bWriteDepth = TRUE; + s_nWriteDepthCount = 4; + } +} + +BOOL ZeroGS::IsWriteDepth() +{ + return s_bWriteDepth; +} + +BOOL ZeroGS::IsWriteDestAlphaTest() +{ + return s_bWriteDepth; +} + +void ZeroGS::SetDestAlphaTest() +{ + s_bDestAlphaTest = TRUE; + s_nWriteDestAlphaTest = 4; +} + +void ZeroGS::SetFogColor(u32 fog) +{ + if( 1||gs.fogcol != fog ) { + gs.fogcol = fog; + + ZeroGS::Flush(0); + ZeroGS::Flush(1); + + if( !g_bIsLost ) { + Vector v; + + // set it immediately + v.x = (gs.fogcol&0xff)/255.0f; + v.y = ((gs.fogcol>>8)&0xff)/255.0f; + v.z = ((gs.fogcol>>16)&0xff)/255.0f; + cgGLSetParameter4fv(g_fparamFogColor, v); + } + } +} + +void ZeroGS::ExtWrite() +{ + WARN_LOG("ExtWrite\n"); + + // use local DISPFB, EXTDATA, EXTBUF, and PMODE +// int bpp, start, end; +// tex0Info texframe; + +// bpp = 4; +// if( texframe.psm == 0x12 ) bpp = 3; +// else if( texframe.psm & 2 ) bpp = 2; +// +// // get the start and end addresses of the buffer +// GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw); +} + +//////////// +// Caches // +//////////// +#ifdef __x86_64__ +extern "C" void TestClutChangeMMX(void* src, void* dst, int entries, void* pret); +#endif + +bool ZeroGS::CheckChangeInClut(u32 highdword, u32 psm) +{ + int cld = (highdword >> 29) & 0x7; + int cbp = ((highdword >> 5) & 0x3fff); + + // processing the CLUT after tex0/2 are written + switch(cld) { + case 0: return false; + + // note sure about changing cbp[0,1] + case 4: return gs.cbp[0] != cbp; + case 5: return gs.cbp[1] != cbp; + + // default: load + } + + int cpsm = (highdword >> 19) & 0xe; + int csm = (highdword >> 23) & 0x1; + + if( cpsm > 1 || csm ) + // don't support 16bit for now + return true; + + int csa = (highdword >> 24) & 0x1f; + + int entries = (psm&3)==3 ? 256 : 16; + + u64* src = (u64*)(g_pbyGSMemory + cbp*256); + u64* dst = (u64*)(g_pbyGSClut+64*csa); + + bool bRet = false; + + // do a fast test with MMX +#ifdef _MSC_VER + +#ifdef __x86_64__ + TestClutChangeMMX(dst, src, entries, &bRet); +#else + int storeebx; + __asm { + mov storeebx, ebx + mov edx, dst + mov ecx, src + mov ebx, entries + +Start: + movq mm0, [edx] + movq mm1, [edx+8] + pcmpeqd mm0, [ecx] + pcmpeqd mm1, [ecx+16] + + movq mm2, [edx+16] + movq mm3, [edx+24] + pcmpeqd mm2, [ecx+32] + pcmpeqd mm3, [ecx+48] + + pand mm0, mm1 + pand mm2, mm3 + movq mm4, [edx+32] + movq mm5, [edx+40] + pcmpeqd mm4, [ecx+8] + pcmpeqd mm5, [ecx+24] + + pand mm0, mm2 + pand mm4, mm5 + movq mm6, [edx+48] + movq mm7, [edx+56] + pcmpeqd mm6, [ecx+40] + pcmpeqd mm7, [ecx+56] + + pand mm0, mm4 + pand mm6, mm7 + pand mm0, mm6 + + pmovmskb eax, mm0 + cmp eax, 0xff + je Continue + mov bRet, 1 + jmp Return + +Continue: + cmp ebx, 16 + jle Return + + test ebx, 0x10 + jz AddEcx + sub ecx, 448 // go back and down one column, +AddEcx: + add ecx, 256 // go to the right block + + + jne Continue1 + add ecx, 256 // skip whole block +Continue1: + add edx, 64 + sub ebx, 16 + jmp Start + +Return: + emms + mov ebx, storeebx + } +#endif // __x86_64__ + +#else // linux + +#ifdef __x86_64__ + __asm__( + ".intel_syntax\n" +"Start:\n" + "movq %%mm0, [%%rcx]\n" + "movq %%mm1, [%%rcx+8]\n" + "pcmpeqd %%mm0, [%%rdx]\n" + "pcmpeqd %%mm1, [%%rdx+16]\n" + "movq %%mm2, [%%rcx+16]\n" + "movq %%mm3, [%%rcx+24]\n" + "pcmpeqd %%mm2, [%%rdx+32]\n" + "pcmpeqd %%mm3, [%%rdx+48]\n" + "pand %%mm0, %%mm1\n" + "pand %%mm2, %%mm3\n" + "movq %%mm4, [%%rcx+32]\n" + "movq %%mm5, [%%rcx+40]\n" + "pcmpeqd %%mm4, [%%rdx+8]\n" + "pcmpeqd %%mm5, [%%rdx+24]\n" + "pand %%mm0, %%mm2\n" + "pand %%mm4, %%mm5\n" + "movq %%mm6, [%%rcx+48]\n" + "movq %%mm7, [%%rcx+56]\n" + "pcmpeqd %%mm6, [%%rdx+40]\n" + "pcmpeqd %%mm7, [%%rdx+56]\n" + "pand %%mm0, %%mm4\n" + "pand %%mm6, %%mm7\n" + "pand %%mm0, %%mm6\n" + "pmovmskb %%eax, %%mm0\n" + "cmp %%eax, 0xff\n" + "je Continue\n" + ".att_syntax\n" + "movb $1, %0\n" + ".intel_syntax\n" + "jmp Return\n" +"Continue:\n" + "cmp %%rbx, 16\n" + "jle Return\n" + "test %%rbx, 0x10\n" + "jz AddRcx\n" + "sub %%rdx, 448\n" // go back and down one column +"AddRcx:\n" + "add %%rdx, 256\n" // go to the right block + "cmp %%rbx, 0x90\n" + "jne Continue1\n" + "add %%rdx, 256\n" // skip whole block +"Continue1:\n" + "add %%rcx, 64\n" + "sub %%rbx, 16\n" + "jmp Start\n" +"Return:\n" + "emms\n" + ".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "b"(entries) : "rax", "memory"); +#else + // do a fast test with MMX + __asm__( + ".intel_syntax\n" +"Start:\n" + "movq %%mm0, [%%ecx]\n" + "movq %%mm1, [%%ecx+8]\n" + "pcmpeqd %%mm0, [%%edx]\n" + "pcmpeqd %%mm1, [%%edx+16]\n" + "movq %%mm2, [%%ecx+16]\n" + "movq %%mm3, [%%ecx+24]\n" + "pcmpeqd %%mm2, [%%edx+32]\n" + "pcmpeqd %%mm3, [%%edx+48]\n" + "pand %%mm0, %%mm1\n" + "pand %%mm2, %%mm3\n" + "movq %%mm4, [%%ecx+32]\n" + "movq %%mm5, [%%ecx+40]\n" + "pcmpeqd %%mm4, [%%edx+8]\n" + "pcmpeqd %%mm5, [%%edx+24]\n" + "pand %%mm0, %%mm2\n" + "pand %%mm4, %%mm5\n" + "movq %%mm6, [%%ecx+48]\n" + "movq %%mm7, [%%ecx+56]\n" + "pcmpeqd %%mm6, [%%edx+40]\n" + "pcmpeqd %%mm7, [%%edx+56]\n" + "pand %%mm0, %%mm4\n" + "pand %%mm6, %%mm7\n" + "pand %%mm0, %%mm6\n" + "pmovmskb %%eax, %%mm0\n" + "cmp %%eax, 0xff\n" + "je Continue\n" + ".att_syntax\n" + "movb $1, %0\n" + ".intel_syntax\n" + "jmp Return\n" +"Continue:\n" + "cmp %%ebx, 16\n" + "jle Return\n" + "test %%ebx, 0x10\n" + "jz AddEcx\n" + "sub %%edx, 448\n" // go back and down one column +"AddEcx:\n" + "add %%edx, 256\n" // go to the right block + "cmp %%ebx, 0x90\n" + "jne Continue1\n" + "add %%edx, 256\n" // skip whole block +"Continue1:\n" + "add %%ecx, 64\n" + "sub %%ebx, 16\n" + "jmp Start\n" +"Return:\n" + "emms\n" + ".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "b"(entries) : "eax", "memory"); +#endif // __x86_64__ + +#endif // _WIN32 + + return bRet; +} + +void ZeroGS::texClutWrite(int ctx) +{ + s_bTexFlush = 0; + if( g_bIsLost ) + return; + + tex0Info& tex0 = vb[ctx].tex0; + assert( PSMT_ISCLUT(tex0.psm) ); + + // processing the CLUT after tex0/2 are written + switch(tex0.cld) { + case 0: return; + case 2: gs.cbp[0] = tex0.cbp; break; + case 3: gs.cbp[1] = tex0.cbp; break; + // note sure about changing cbp[0,1] + case 4: + if( gs.cbp[0] == tex0.cbp ) + return; + gs.cbp[0] = tex0.cbp; + break; + case 5: + if( gs.cbp[1] == tex0.cbp ) + return; + gs.cbp[1] = tex0.cbp; + break; + } + + Flush(!ctx); + + int entries = (tex0.psm&3)==3 ? 256 : 16; + + if( tex0.csm ) { + // 16bit psm + // eggomania uses non16bit textures for csm2 + if( tex0.cpsm == PSMCT16 ) { + u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128; + u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)); + + for(int i = 0; i < entries; ++i) { + *dst = src[getPixelAddress16_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + // check for wrapping + if( ((u32)(uptr)dst & 0x3ff) == 0 ) + dst = (u16*)(g_pbyGSClut+2); + } + } + else if( tex0.cpsm == PSMCT16S ) { + + u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128; + u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)); + + for(int i = 0; i < entries; ++i) { + *dst = src[getPixelAddress16S_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + dst += 2; + // check for wrapping + if( ((u32)(uptr)dst & 0x3ff) == 0 ) + dst = (u16*)(g_pbyGSClut+2); + } + } + else if( tex0.cpsm == PSMCT32 || tex0.cpsm == PSMCT24 ) { + + u32* src = (u32*)g_pbyGSMemory + tex0.cbp*64; + u32 *dst = (u32*)(g_pbyGSClut+64*tex0.csa); + + for(int i = 0; i < entries; ++i) { + *dst++ = src[getPixelAddress32_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)]; + } + } + else { +#ifndef RELEASE_TO_PUBLIC + //printf("unknown cpsm: %x (%x)\n", tex0.cpsm, tex0.psm); +#endif + } + } + else { + if( tex0.cpsm <= 1 ) { + if( entries == 16 ) + WriteCLUT_T32_I4_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa)); + else + WriteCLUT_T32_I8_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa)); + } + else { + if( entries == 16 ) + WriteCLUT_T16_I4_CSM1((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0))); + else if(entries == 256) { + // sse2 for 256 is more complicated, so use regular + WriteCLUT_T16_I8_CSM1_c((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0))); + } + } + } +} + +void ZeroGS::SetTexFlush() +{ + s_bTexFlush = TRUE; + +// if( PSMT_ISCLUT(vb[0].tex0.psm) ) +// texClutWrite(0); +// if( PSMT_ISCLUT(vb[1].tex0.psm) ) +// texClutWrite(1); + + if( !s_bForceTexFlush ) { + if( s_ptexCurSet[0] != s_ptexNextSet[0] ) { + s_ptexCurSet[0] = s_ptexNextSet[0]; + } + if( s_ptexCurSet[1] != s_ptexNextSet[1] ) { + s_ptexCurSet[1] = s_ptexNextSet[1]; + } + } +} + +int ZeroGS::Save(char* pbydata) +{ + if( pbydata == NULL ) + return 40 + 0x00400000 + sizeof(gs) + 2*VBSAVELIMIT + 2*sizeof(frameInfo) + 4 + 256*4; + + s_RTs.ResolveAll(); + s_DepthRTs.ResolveAll(); + + strcpy(pbydata, libraryName); + *(u32*)(pbydata+16) = ZEROGS_SAVEVER; + pbydata += 32; + + *(int*)pbydata = icurctx; pbydata += 4; + *(int*)pbydata = VBSAVELIMIT; pbydata += 4; + + memcpy(pbydata, g_pbyGSMemory, 0x00400000); + pbydata += 0x00400000; + + memcpy(pbydata, g_pbyGSClut, 256*4); + pbydata += 256*4; + + memcpy(pbydata, &gs, sizeof(gs)); + pbydata += sizeof(gs); + + for(int i = 0; i < 2; ++i) { + memcpy(pbydata, &vb[i], VBSAVELIMIT); + pbydata += VBSAVELIMIT; + } + + return 0; +} + +extern u32 s_uTex1Data[2][2], s_uClampData[2]; +extern char *libraryName; +bool ZeroGS::Load(char* pbydata) +{ + memset(s_uTex1Data, 0, sizeof(s_uTex1Data)); + memset(s_uClampData, 0, sizeof(s_uClampData)); + + g_nCurVBOIndex = 0; + + // first 32 bytes are the id + if( strncmp(pbydata, libraryName, 6) == 0 && *(u32*)(pbydata+16) == ZEROGS_SAVEVER ) { + + g_MemTargs.Destroy(); + + GSStateReset(); + pbydata += 32; + + int context = *(int*)pbydata; pbydata += 4; + u32 savelimit = VBSAVELIMIT; + + savelimit = *(u32*)pbydata; pbydata += 4; + + memcpy(g_pbyGSMemory, pbydata, 0x00400000); + pbydata += 0x00400000; + + memcpy(g_pbyGSClut, pbydata, 256*4); + pbydata += 256*4; + + memcpy(&gs, pbydata, sizeof(gs)); + pbydata += sizeof(gs); + prim = &gs._prim[gs.prac]; + + vb[0].Destroy(); + memcpy(&vb[0], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[0].pBufferData = NULL; + + vb[1].Destroy(); + memcpy(&vb[1], pbydata, min(savelimit, VBSAVELIMIT)); + pbydata += savelimit; + vb[1].pBufferData = NULL; + + for(int i = 0; i < 2; ++i) { + vb[i].Init(VB_BUFFERSIZE); + vb[i].bNeedZCheck = vb[i].bNeedFrameCheck = 1; + + vb[i].bSyncVars = 0; vb[i].bNeedTexCheck = 1; + memset(vb[i].uCurTex0Data, 0, sizeof(vb[i].uCurTex0Data)); + } + + icurctx = -1; + + glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); // switch to the backbuffer + SetFogColor(gs.fogcol); + + GL_REPORT_ERRORD(); + return true; + } + + return false; +} + +void ZeroGS::SaveSnapshot(const char* filename) +{ + g_bMakeSnapshot = 1; + strSnapshot = filename; +} + +bool ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int jpeg) +{ + bool bflip = height < 0; + height = abs(height); + vector data(width*height); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if( glGetError() != GL_NO_ERROR ) + return false; + + if( bflip ) { + // swap scanlines + vector scanline(width); + for(int i = 0; i < height/2; ++i) { + memcpy(&scanline[0], &data[i*width], width*4); + memcpy(&data[i*width], &data[(height-i-1)*width], width*4); + memcpy(&data[(height-i-1)*width], &scanline[0], width*4); + } + } + + if( jpeg ) return SaveJPEG(filename, width, height, &data[0], 70); + + return SaveTGA(filename, width, height, &data[0]); +} + +bool ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height) +{ + vector data(width*height); + glBindTexture(textarget, tex); + glGetTexImage(textarget, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if( glGetError() != GL_NO_ERROR ) { + return false; + } + + return SaveTGA(filename, width, height, &data[0]);//SaveJPEG(filename, width, height, &data[0], 70); +} + +extern "C" { +#ifdef _WIN32 +#define XMD_H +#undef FAR +#define HAVE_BOOLEAN +#endif + +#include "jpeglib.h" +} + +bool ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality) +{ + u8* image_buffer = new u8[image_width * image_height * 3]; + u8* psrc = (u8*)pdata; + + // input data is rgba format, so convert to rgb + u8* p = image_buffer; + for(int i = 0; i < image_height; ++i) { + for(int j = 0; j < image_width; ++j) { + p[0] = psrc[0]; + p[1] = psrc[1]; + p[2] = psrc[2]; + p += 3; + psrc += 4; + } + } + + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + delete image_buffer; + /* And we're done! */ + return true; +} + +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif + +struct TGA_HEADER +{ + u8 identsize; // size of ID field that follows 18 u8 header (0 usually) + u8 colourmaptype; // type of colour map 0=none, 1=has palette + u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + s16 colourmapstart; // first colour map entry in palette + s16 colourmaplength; // number of colours in palette + u8 colourmapbits; // number of bits per palette entry 15,16,24,32 + + s16 xstart; // image x origin + s16 ystart; // image y origin + s16 width; // image width in pixels + s16 height; // image height in pixels + u8 bits; // image bits per pixel 8,16,24,32 + u8 descriptor; // image descriptor bits (vh flip bits) + + // pixel data follows header + +#if defined(_MSC_VER) +}; +#pragma pack(pop) +#else +} __attribute__((packed)); +#endif + +bool ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata) +{ + TGA_HEADER hdr; + FILE* f = fopen(filename, "wb"); + if( f == NULL ) + return false; + + assert( sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18 ); + + memset(&hdr, 0, sizeof(hdr)); + hdr.imagetype = 2; + hdr.bits = 32; + hdr.width = width; + hdr.height = height; + hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical + + fwrite(&hdr, sizeof(hdr), 1, f); + fwrite(pdata, width*height*4, 1, f); + fclose(f); + return true; +} + +// AVI capture stuff +void ZeroGS::StartCapture() +{ + if( !s_aviinit ) { + +#ifdef _WIN32 + START_AVI("zerogs.avi"); +#else // linux + //TODO +#endif + s_aviinit = 1; + } + else { + ERROR_LOG("Continuing from previous capture"); + } + + s_avicapturing = 1; +} + +void ZeroGS::StopCapture() +{ + s_avicapturing = 0; +} + +void ZeroGS::CaptureFrame() +{ + assert( s_avicapturing && s_aviinit ); + + //vector mem(nBackbufferWidth*nBackbufferHeight); + vector data(nBackbufferWidth*nBackbufferHeight); + glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + if( glGetError() != GL_NO_ERROR ) + return; + +// u8* pend = (u8*)&data[0] + (nBackbufferHeight-1)*nBackbufferWidth*4; +// for(int i = 0; i < conf.height; ++i) { +// memcpy_amd(&mem[nBackbufferWidth*4*i], pend - nBackbufferWidth*4*i, nBackbufferWidth * 4); +// } + + int fps = SMODE1->CMOD == 3 ? 50 : 60; + +#ifdef _WIN32 + bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, nBackbufferWidth, nBackbufferHeight, 32, &data[0]); + + if( !bSuccess ) { + s_avicapturing = 0; + STOP_AVI(); + ZeroGS::AddMessage("Failed to create avi"); + return; + } +#else // linux + //TODO +#endif +} + diff --git a/plugins/gs/zerogs/opengl/zerogs.h b/plugins/gs/zerogs/opengl/zerogs.h new file mode 100644 index 0000000..af95132 --- /dev/null +++ b/plugins/gs/zerogs/opengl/zerogs.h @@ -0,0 +1,544 @@ +/* ZeroGS KOSMOS + * Copyright (C) 2005-2006 zerofrog@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ZEROGS__H +#define __ZEROGS__H + +#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union + +#include +#include + +#ifndef _WIN32 +#include +inline void* wglGetProcAddress(const char* x) { + return (void*)glXGetProcAddress((const GLubyte*)x); +} +#endif + +#include "glprocs.h" + +#include +#include + +#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils +#define GL_DEPTH_STENCIL_EXT 0x84F9 +#define GL_UNSIGNED_INT_24_8_EXT 0x84FA +#define GL_DEPTH24_STENCIL8_EXT 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 +#endif + +#include + +#include +#include +#include +#include +#include +using namespace std; + +#ifndef SAFE_DELETE +#define SAFE_DELETE(x) if( (x) != NULL ) { delete (x); (x) = NULL; } +#endif +#ifndef SAFE_DELETE_ARRAY +#define SAFE_DELETE_ARRAY(x) if( (x) != NULL ) { delete[] (x); (x) = NULL; } +#endif +#ifndef SAFE_RELEASE +#define SAFE_RELEASE(x) if( (x) != NULL ) { (x)->Release(); (x) = NULL; } +#endif + +#define SAFE_RELEASE_PROG(x) { if( (x) != NULL ) { cgDestroyProgram(x); x = NULL; } } +#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } } + +#define FORIT(it, v) for(it = (v).begin(); it != (v).end(); ++(it)) + +// sends a message to output window if assert fails +#define BMSG(x, str) { if( !(x) ) { GS_LOG(str); GS_LOG(str); } } +#define BMSG_RETURN(x, str) { if( !(x) ) { GS_LOG(str); GS_LOG(str); return; } } +#define BMSG_RETURNX(x, str, rtype) { if( !(x) ) { GS_LOG(str); GS_LOG(str); return (##rtype); } } +#define B(x) { if( !(x) ) { GS_LOG(_#x"\n"); GS_LOG(#x"\n"); } } +#define B_RETURN(x) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); return; } } +#define B_RETURNX(x, rtype) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); return (##rtype); } } +#define B_G(x, action) { if( !(x) ) { ERROR_LOG("%s:%d: %s\n", __FILE__, (u32)__LINE__, #x); action; } } + +#define GL_REPORT_ERROR() { err = glGetError(); if( err != GL_NO_ERROR ) { ERROR_LOG("%s:%d: gl error 0x%x\n", __FILE__, (int)__LINE__, err); ZeroGS::HandleGLError(); } } + +#ifdef _DEBUG +#define GL_REPORT_ERRORD() { GLenum err = glGetError(); if( err != GL_NO_ERROR ) { ERROR_LOG("%s:%d: gl error 0x%x\n", __FILE__, (int)__LINE__, err); ZeroGS::HandleGLError(); } } +#else +#define GL_REPORT_ERRORD() +#endif + +// sets the data stream +#define SET_STREAM() { \ + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \ + glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \ + glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \ + glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \ +} + +#define SETVERTEXSHADER(prog) { \ + if( (prog) != g_vsprog ) { \ + cgGLBindProgram(prog); \ + g_vsprog = prog; \ + } \ +} \ + +#define SETPIXELSHADER(prog) { \ + if( (prog) != g_psprog ) { \ + cgGLBindProgram(prog); \ + g_psprog = prog; \ + } \ +} \ + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +// all textures have this width +//#define GPU_TEXWIDTH 512 +extern int GPU_TEXWIDTH; +extern float g_fiGPU_TEXWIDTH; +#define GPU_TEXMASKWIDTH 1024 // bitwise mask width for region repeat mode + +extern CGprogram g_vsprog, g_psprog; + +struct FRAGMENTSHADER +{ + FRAGMENTSHADER() : prog(0), sMemory(0), sFinal(0), sBitwiseANDX(0), sBitwiseANDY(0), sInterlace(0), sCLUT(0), sOneColor(0), sBitBltZ(0), + fTexAlpha2(0), fTexOffset(0), fTexDims(0), fTexBlock(0), fClampExts(0), fTexWrapMode(0), + fRealTexDims(0), fTestBlack(0), fPageOffset(0), fTexAlpha(0) {} + + CGprogram prog; + CGparameter sMemory, sFinal, sBitwiseANDX, sBitwiseANDY, sCLUT, sInterlace; + CGparameter sOneColor, sBitBltZ, sInvTexDims; + CGparameter fTexAlpha2, fTexOffset, fTexDims, fTexBlock, fClampExts, fTexWrapMode, fRealTexDims, fTestBlack, fPageOffset, fTexAlpha; + +#ifdef _DEBUG + string filename; +#endif +}; + +struct VERTEXSHADER +{ + VERTEXSHADER() : prog(0), sBitBltPos(0), sBitBltTex(0) {} + CGprogram prog; + CGparameter sBitBltPos, sBitBltTex, fBitBltTrans; // vertex shader constants +}; + +// don't change these values! +#define GAME_TEXTURETARGS 0x01 +#define GAME_AUTORESET 0x02 +#define GAME_INTERLACE2X 0x04 +#define GAME_TEXAHACK 0x08 // apply texa to non textured polys +#define GAME_NOTARGETRESOLVE 0x10 +#define GAME_EXACTCOLOR 0x20 +#define GAME_NOCOLORCLAMP 0x40 +#define GAME_FFXHACK 0x80 +#define GAME_NODEPTHUPDATE 0x0200 +#define GAME_QUICKRESOLVE1 0x0400 +#define GAME_NOQUICKRESOLVE 0x0800 +#define GAME_NOTARGETCLUT 0x1000 // full 16 bit resolution +#define GAME_NOSTENCIL 0x2000 +#define GAME_VSSHACK 0x4000 // vertical stripe syndrome +#define GAME_NODEPTHRESOLVE 0x8000 +#define GAME_FULL16BITRES 0x00010000 +#define GAME_RESOLVEPROMOTED 0x00020000 +#define GAME_FASTUPDATE 0x00040000 +#define GAME_NOALPHATEST 0x00080000 +#define GAME_DISABLEMRTDEPTH 0x00100000 +#define GAME_32BITTARGS 0x00200000 + +#define USEALPHATESTING (!(g_GameSettings&GAME_NOALPHATEST)) + +extern u8* g_pbyGSMemory; +extern u8* g_pbyGSClut; // the temporary clut buffer +extern CGparameter g_vparamPosXY[2], g_fparamFogColor; + +namespace ZeroGS { + + typedef void (*DrawFn)(); + + enum RenderFormatType + { + RFT_byte8 = 0, // A8R8G8B8 + RFT_float16 = 1, // A32R32B32G32 + }; + + // managers render-to-texture targets + class CRenderTarget + { + public: + CRenderTarget(); + virtual ~CRenderTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + // set the GPU_POSXY variable, scissor rect, and current render target + void SetTarget(int fbplocal, const Rect2& scissor, int context); + void SetViewport(); + + // copies/creates the feedback contents + inline void CreateFeedback() { + if( ptexFeedback == 0 || !(status&TS_FeedbackReady) ) + _CreateFeedback(); + } + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* pdepth); + virtual void ConvertTo32(); // converts a psm==2 target, to a psm==0 + virtual void ConvertTo16(); // converts a psm==0 target, to a psm==2 + + virtual bool IsDepth() { return false; } + void SetRenderTarget(int targ); + + void* psys; // system data used for comparison + u32 ptex; + + int fbp, fbw, fbh; // if fbp is negative, virtual target (not mapped to any real addr) + int start, end; // in bytes + u32 lastused; // time stamp since last used + Vector vposxy; + + u32 fbm; + u16 status; + u8 psm; + u8 resv0; + Rect scissorrect; + + //int startresolve, endresolve; + u32 nUpdateTarg; // use this target to update the texture if non 0 (one time only) + + // this is optionally used when feedback effects are used (render target is used as a texture when rendering to itself) + u32 ptexFeedback; + + enum TargetStatus { + TS_Resolved = 1, + TS_NeedUpdate = 2, + TS_Virtual = 4, // currently not mapped to memory + TS_FeedbackReady = 8, // feedback effect is ready and doesn't need to be updated + TS_NeedConvert32 = 16, + TS_NeedConvert16 = 32, + }; + + private: + void _CreateFeedback(); + }; + + // manages zbuffers + class CDepthTarget : public CRenderTarget + { + public: + CDepthTarget(); + virtual ~CDepthTarget(); + + virtual bool Create(const frameInfo& frame); + virtual void Destroy(); + + virtual void Resolve(); + virtual void Resolve(int startrange, int endrange); // resolves only in the allowed range + virtual void Update(int context, CRenderTarget* prndr); + + virtual bool IsDepth() { return true; } + + void SetDepthStencilSurface(); + + u32 pdepth; // 24 bit, will contain the stencil buffer if possible + u32 pstencil; // if not 0, contains the stencil buffer + int icount; // internal counter + }; + + // manages contiguous chunks of memory (width is always 1024) + class CMemoryTarget + { + public: + struct TEXTURE + { + inline TEXTURE() : tex(0), memptr(NULL), ref(0) {} + inline ~TEXTURE() { glDeleteTextures(1, &tex); _aligned_free(memptr); } + u32 tex; + int ref; + u8* memptr; // GPU memory used for comparison + }; + + inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), channels(0),cpsm(0), clearminy(0), clearmaxy(0), validatecount(0) {} + + inline CMemoryTarget(const CMemoryTarget& r) { + ptex = r.ptex; + if( ptex != NULL ) ptex->ref++; + starty = r.starty; + height = r.height; + realy = r.realy; + realheight = r.realheight; + usedstamp = r.usedstamp; + psm = r.psm; + cpsm = r.cpsm; + clut = r.clut; + clearminy = r.clearminy; + clearmaxy = r.clearmaxy; + widthmult = r.widthmult; + channels = r.channels; + validatecount = r.validatecount; + fmt = r.fmt; + } + + ~CMemoryTarget() { Destroy(); } + + inline void Destroy() { + if( ptex != NULL && ptex->ref > 0 ) { + if( --ptex->ref <= 0 ) + delete ptex; + } + + ptex = NULL; + } + + // returns true if clut data is synced + bool ValidateClut(const tex0Info& tex0); + // returns true if tex data is synced + bool ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex); + + int clearminy, clearmaxy; // when maxy > 0, need to check for clearing + + // realy is offset in pixels from start of valid region + // so texture in memory is [realy,starty+height] + // valid texture is [starty,starty+height] + // offset in mem [starty-realy, height] + int starty, height; // assert(starty >= realy) + int realy, realheight; // this is never touched once allocated + u32 usedstamp; + TEXTURE* ptex; // can be 16bit + u32 fmt; + + int widthmult; + int channels; + + int validatecount; // count how many times has been validated, if too many, destroy + + vector clut; // if nonzero, texture uses CLUT + u8 psm, cpsm; // texture and clut format. For psm, only 16bit/32bit differentiation matters + }; + + + struct VB + { + VB(); + ~VB(); + + void Destroy(); + + __forceinline bool CheckPrim(); + void CheckFrame(int tbp); + + // context specific state + Point offset; + Rect2 scissor; + tex0Info tex0; + tex1Info tex1; + miptbpInfo miptbp0; + miptbpInfo miptbp1; + alphaInfo alpha; + fbaInfo fba; + clampInfo clamp; + pixTest test; + u32 ptexClamp[2]; // textures for x and y dir region clamping + + public: + void FlushTexData(); + + // notify VB that nVerts need to be written to pbuf + inline void NotifyWrite(int nVerts) { + assert( pBufferData != NULL && nCount < nNumVertices && nVerts > 0 ); + + if( nCount + nVerts > nNumVertices ) { + // recreate except with a bigger count + VertexGPU* ptemp = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU)*nNumVertices*2, 256); + memcpy_amd(ptemp, pBufferData, sizeof(VertexGPU) * nCount); + nNumVertices *= 2; + assert( nCount + nVerts <= nNumVertices ); + _aligned_free(pBufferData); + pBufferData = ptemp; + } + } + + void Init(int nVerts) { + if( pBufferData == NULL && nVerts > 0 ) { + pBufferData = (VertexGPU*)_aligned_malloc(sizeof(VertexGPU)*nVerts, 256); + nNumVertices = nVerts; + } + + nCount = 0; + } + + u8 bNeedFrameCheck; + u8 bNeedZCheck; + u8 bNeedTexCheck; + u8 dummy0; + + union { + struct { + u8 bTexConstsSync; // only pixel shader constants that context owns + u8 bVarsTexSync; // texture info + u8 bVarsSetTarg; + u8 dummy1; + }; + u32 bSyncVars; + }; + + int ictx; + VertexGPU* pBufferData; // current allocated data + + int nNumVertices; // size of pBufferData in terms of VertexGPU objects + int nCount; + primInfo curprim; // the previous prim the current buffers are set to + + zbufInfo zbuf; + frameInfo gsfb; // the real info set by FRAME cmd + frameInfo frame; + int zprimmask; // zmask for incoming points + + u32 uCurTex0Data[2]; // current tex0 data + u32 uNextTex0Data[2]; // tex0 data that has to be applied if bNeedTexCheck is 1 + + //int nFrameHeights[8]; // frame heights for the past frame changes + int nNextFrameHeight; + + CMemoryTarget* pmemtarg; // the current mem target set + CRenderTarget* prndr; + CDepthTarget* pdepth; + }; + + // visible members + extern DrawFn drawfn[8]; + extern VB vb[2]; + extern float fiTexWidth[2], fiTexHeight[2]; // current tex width and height + + void AddMessage(const char* pstr, u32 ms = 5000); + void DrawText(const char* pstr, int left, int top, u32 color); + void ChangeWindowSize(int nNewWidth, int nNewHeight); + void SetChangeDeviceSize(int nNewWidth, int nNewHeight); + void ChangeDeviceSize(int nNewWidth, int nNewHeight); + void SetAA(int mode); + void SetCRC(int crc); + + void ReloadEffects(); + + // Methods // + bool IsGLExt( const char* szTargetExtension ); ///< returns true if the the opengl extension is supported + bool Create(int width, int height); + void Destroy(BOOL bD3D); + + void Restore(); // call to restore device + void Reset(); // call to destroy video resources + + void GSStateReset(); + void HandleGLError(); + + // called on a primitive switch + void Prim(); + + void SetTexFlush(); + // flush current vertices, call before setting new registers (the main render method) + void Flush(int context); + + void ExtWrite(); + + void SetWriteDepth(); + BOOL IsWriteDepth(); + + void SetDestAlphaTest(); + BOOL IsWriteDestAlphaTest(); + + void SetFogColor(u32 fog); + void SaveTex(tex0Info* ptex, int usevid); + + // called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf. + // Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks? + void InitTransferHostLocal(); + void TransferHostLocal(const void* pbyMem, u32 nQWordSize); + + void InitTransferLocalHost(); + void TransferLocalHost(void* pbyMem, u32 nQWordSize); + inline void TerminateLocalHost() {} + + void TransferLocalLocal(); + + // switches the render target to the real target, flushes the current render targets and renders the real image + void RenderCRTC(int interlace); + void ResetRenderTarget(int index); + + bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op + + // call to load CLUT data (depending on CLD) + void texClutWrite(int ctx); + RenderFormatType GetRenderFormat(); + GLenum GetRenderTargetFormat(); + + int Save(char* pbydata); + bool Load(char* pbydata); + + void SaveSnapshot(const char* filename); + bool SaveRenderTarget(const char* filename, int width, int height, int jpeg); + bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); + bool SaveJPEG(const char* filename, int width, int height, const void* pdata, int quality); + bool SaveTGA(const char* filename, int width, int height, void* pdata); + + // private methods + void FlushSysMem(const RECT* prc); + void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm); + + // returns the first and last addresses aligned to a page that cover + void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw); + + // inits the smallest rectangle in ptexMem that covers this region in ptexMem + // returns the offset that needs to be added to the locked rect to get the beginning of the buffer + //void GetMemRect(RECT& rc, int psm, int x, int y, int w, int h, int bp, int bw); + + // only sets a limited amount of state (for Update) + void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, ZeroGS::CMemoryTarget* pmemtarg, FRAGMENTSHADER* pfragment, int force); + + void ResetAlphaVariables(); + + void StartCapture(); + void StopCapture(); + void CaptureFrame(); +}; + +// GL prototypes +extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; +extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; +extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; +extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; +extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; +extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; +extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; +extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; +extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; +extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; +extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; +extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; +extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; +extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; +extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; +extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; +extern PFNGLDRAWBUFFERSPROC glDrawBuffers; + +#endif diff --git a/plugins/gs/zerogs/opengl/zerogsmath.h b/plugins/gs/zerogs/opengl/zerogsmath.h new file mode 100644 index 0000000..b654ea1 --- /dev/null +++ b/plugins/gs/zerogs/opengl/zerogsmath.h @@ -0,0 +1,900 @@ +#ifndef ZEROGS_MATH_H +#define ZEROGS_MATH_H + +#ifndef _WIN32 +#include +#endif + +#ifndef PI +#define PI ((dReal)3.141592654) +#endif + +#define rswap(x, y) *(int*)&(x) ^= *(int*)&(y) ^= *(int*)&(x) ^= *(int*)&(y); + +template inline T RAD_2_DEG(T radians) { return (radians * (T)57.29577951); } + +class Transform; +class TransformMatrix; + +typedef float dReal; +typedef dReal dMatrix3[3*4]; + +inline dReal* normalize3(dReal* pfout, const dReal* pf); +inline dReal* normalize4(dReal* pfout, const dReal* pf); +inline dReal* cross3(dReal* pfout, const dReal* pf1, const dReal* pf2); + +// multiplies 3x3 matrices +inline dReal* mult3(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* mult3(double* pfres, const double* pf1, const double* pf2); + +inline dReal* inv3(const dReal* pf, dReal* pfres, int stride); +inline dReal* inv4(const dReal* pf, dReal* pfres); + +// class used for 3 and 4 dim vectors and quaternions +// It is better to use this for a 3 dim vector because it is 16byte aligned and SIMD instructions can be used +class Vector +{ +public: + dReal x, y, z, w; + + Vector() : x(0), y(0), z(0), w(0) {} + Vector(dReal x, dReal y, dReal z) : x(x), y(y), z(z), w(0) {} + Vector(dReal x, dReal y, dReal z, dReal w) : x(x), y(y), z(z), w(w) {} + Vector(const Vector &vec) : x(vec.x), y(vec.y), z(vec.z), w(vec.w) {} + Vector(const dReal* pf) { assert(pf != NULL); x = pf[0]; y = pf[1]; z = pf[2]; w = 0; } + + dReal operator[](int i) const { return (&x)[i]; } + dReal& operator[](int i) { return (&x)[i]; } + + // casting operators + operator dReal* () { return &x; } + operator const dReal* () const { return (const dReal*)&x; } + + // SCALAR FUNCTIONS + inline dReal dot(const Vector &v) const { return x*v.x + y*v.y + z*v.z + w*v.w; } + inline void normalize() { normalize4(&x, &x); } + + inline void Set3(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; } + inline void Set4(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; w = pvals[3]; } + + // 3 dim cross product, w is not touched + /// this = this x v + inline void Cross(const Vector &v) { cross3(&x, &x, v); } + + /// this = u x v + inline void Cross(const Vector &u, const Vector &v) { cross3(&x, u, v); } + + inline Vector operator-() const { Vector v; v.x = -x; v.y = -y; v.z = -z; v.w = -w; return v; } + inline Vector operator+(const Vector &r) const { Vector v; v.x = x+r.x; v.y = y+r.y; v.z = z+r.z; v.w = w+r.w; return v; } + inline Vector operator-(const Vector &r) const { Vector v; v.x = x-r.x; v.y = y-r.y; v.z = z-r.z; v.w = w-r.w; return v; } + inline Vector operator*(const Vector &r) const { Vector v; v.x = r.x*x; v.y = r.y*y; v.z = r.z*z; v.w = r.w*w; return v; } + inline Vector operator*(dReal k) const { Vector v; v.x = k*x; v.y = k*y; v.z = k*z; v.w = k*w; return v; } + + inline Vector& operator += (const Vector& r) { x += r.x; y += r.y; z += r.z; w += r.w; return *this; } + inline Vector& operator -= (const Vector& r) { x -= r.x; y -= r.y; z -= r.z; w -= r.w; return *this; } + inline Vector& operator *= (const Vector& r) { x *= r.x; y *= r.y; z *= r.z; w *= r.w; return *this; } + + inline Vector& operator *= (const dReal k) { x *= k; y *= k; z *= k; w *= k; return *this; } + inline Vector& operator /= (const dReal _k) { dReal k=1/_k; x *= k; y *= k; z *= k; w *= k; return *this; } + + friend Vector operator* (float f, const Vector& v); + //friend ostream& operator<<(ostream& O, const Vector& v); + //friend istream& operator>>(istream& I, Vector& v); +}; + +inline Vector operator* (float f, const Vector& left) +{ + Vector v; + v.x = f * left.x; + v.y = f * left.y; + v.z = f * left.z; + return v; +} + +struct AABB +{ + Vector pos, extents; +}; + +struct OBB +{ + Vector right, up, dir, pos, extents; +}; + +struct TRIANGLE +{ + TRIANGLE() {} + TRIANGLE(const Vector& v1, const Vector& v2, const Vector& v3) : v1(v1), v2(v2), v3(v3) {} + ~TRIANGLE() {} + + Vector v1, v2, v3; //!< the vertices of the triangle + + const Vector& operator[](int i) const { return (&v1)[i]; } + Vector& operator[](int i) { return (&v1)[i]; } + + /// assumes CCW ordering of vertices + inline Vector ComputeNormal() { + Vector normal; + cross3(normal, v2-v1, v3-v1); + return normal; + } +}; + +// Routines made for 3D graphics that deal with 3 or 4 dim algebra structures +// Functions with postfix 3 are for 3x3 operations, etc + +// all fns return pfout on success or NULL on failure +// results and arguments can share pointers + + +// multiplies 4x4 matrices +inline dReal* mult4(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* mult4(double* pfres, const double* pf1, const double* pf2); + +// pf1^T * pf2 +inline dReal* multtrans3(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* multtrans3(double* pfres, const double* pf1, const double* pf2); +inline dReal* multtrans4(dReal* pfres, const dReal* pf1, const dReal* pf2); +inline double* multtrans4(double* pfres, const double* pf1, const double* pf2); + +inline dReal* transpose3(const dReal* pf, dReal* pfres); +inline double* transpose3(const double* pf, double* pfres); +inline dReal* transpose4(const dReal* pf, dReal* pfres); +inline double* transpose4(const double* pf, double* pfres); + +inline dReal dot2(const dReal* pf1, const dReal* pf2); +inline dReal dot3(const dReal* pf1, const dReal* pf2); +inline dReal dot4(const dReal* pf1, const dReal* pf2); + +inline dReal lengthsqr2(const dReal* pf); +inline dReal lengthsqr3(const dReal* pf); +inline dReal lengthsqr4(const dReal* pf); + +inline dReal* normalize2(dReal* pfout, const dReal* pf); +inline dReal* normalize3(dReal* pfout, const dReal* pf); +inline dReal* normalize4(dReal* pfout, const dReal* pf); + +//// +// More complex ops that deal with arbitrary matrices // +//// + +// extract eigen values and vectors from a 2x2 matrix and returns true if all values are real +// returned eigen vectors are normalized +inline bool eig2(const dReal* pfmat, dReal* peigs, dReal& fv1x, dReal& fv1y, dReal& fv2x, dReal& fv2y); + +// Simple routines for linear algebra algorithms // +int CubicRoots (double c0, double c1, double c2, double *r0, double *r1, double *r2); +bool QLAlgorithm3 (dReal* m_aafEntry, dReal* afDiag, dReal* afSubDiag); + +void EigenSymmetric3(dReal* fCovariance, dReal* eval, dReal* fAxes); + +void GetCovarBasisVectors(dReal fCovariance[3][3], Vector* vRight, Vector* vUp, Vector* vDir); + +// first root returned is always >= second, roots are defined if the quadratic doesn't have real solutions +void QuadraticSolver(dReal* pfQuadratic, dReal* pfRoots); + +int insideQuadrilateral(const Vector* p0,const Vector* p1, const Vector* p2,const Vector* p3); +int insideTriangle(const Vector* p0, const Vector* p1, const Vector* p2); + +// multiplies a matrix by a scalar +template inline void mult(T* pf, T fa, int r); + +// multiplies a r1xc1 by c1xc2 matrix into pfres, if badd is true adds the result to pfres +// does not handle cases where pfres is equal to pf1 or pf2, use multtox for those cases +template +inline T* mult(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd = false); + +// pf1 is transposed before mult +// rows of pf2 must equal rows of pf1 +// pfres will be c1xc2 matrix +template +inline T* multtrans(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd = false); + +// pf2 is transposed before mult +// the columns of both matrices must be the same and equal to c1 +// r2 is the number of rows in pf2 +// pfres must be an r1xr2 matrix +template +inline T* multtrans_to2(T* pf1, R* pf2, int r1, int c1, int r2, S* pfres, bool badd = false); + +// multiplies rxc matrix pf1 and cxc matrix pf2 and stores the result in pf1, +// the function needs a temporary buffer the size of c doubles, if pftemp == NULL, +// the function will allocate the necessary memory, otherwise pftemp should be big +// enough to store all the entries +template inline T* multto1(T* pf1, T* pf2, int r1, int c1, T* pftemp = NULL); + +// same as multto1 except stores the result in pf2, pf1 has to be an r2xr2 matrix +// pftemp must be of size r2 if not NULL +template inline T* multto2(T* pf1, S* pf2, int r2, int c2, S* pftemp = NULL); + +// add pf1 + pf2 and store in pf1 +template inline void sub(T* pf1, T* pf2, int r); +template inline T normsqr(T* pf1, int r); +template inline T lengthsqr(T* pf1, T* pf2, int length); +template inline T dot(T* pf1, T* pf2, int length); + +template inline T sum(T* pf, int length); + +// takes the inverse of the 3x3 matrix pf and stores it into pfres, returns true if matrix is invertible +template inline bool inv2(T* pf, T* pfres); + +/////////////////////// +// Function Definitions +/////////////////////// +bool eig2(const dReal* pfmat, dReal* peigs, dReal& fv1x, dReal& fv1y, dReal& fv2x, dReal& fv2y) +{ + // x^2 + bx + c + dReal a, b, c, d; + b = -(pfmat[0] + pfmat[3]); + c = pfmat[0] * pfmat[3] - pfmat[1] * pfmat[2]; + d = b * b - 4.0f * c + 1e-16f; + + if( d < 0 ) return false; + if( d < 1e-16f ) { + a = -0.5f * b; + peigs[0] = a; peigs[1] = a; + fv1x = pfmat[1]; fv1y = a - pfmat[0]; + c = 1 / sqrtf(fv1x*fv1x + fv1y*fv1y); + fv1x *= c; fv1y *= c; + fv2x = -fv1y; fv2y = fv1x; + return true; + } + + // two roots + d = sqrtf(d); + a = -0.5f * (b + d); + peigs[0] = a; + fv1x = pfmat[1]; fv1y = a-pfmat[0]; + c = 1 / sqrtf(fv1x*fv1x + fv1y*fv1y); + fv1x *= c; fv1y *= c; + + a += d; + peigs[1] = a; + fv2x = pfmat[1]; fv2y = a-pfmat[0]; + c = 1 / sqrtf(fv2x*fv2x + fv2y*fv2y); + fv2x *= c; fv2y *= c; + return true; +} + +//#ifndef TI_USING_IPP + +// Functions that are replacable by ipp library funcs +template inline T* _mult3(T* pfres, const T* pf1, const T* pf2) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL ); + + T* pfres2; + if( pfres == pf1 || pfres == pf2 ) pfres2 = (T*)alloca(9 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0*4+0] = pf1[0*4+0]*pf2[0*4+0]+pf1[0*4+1]*pf2[1*4+0]+pf1[0*4+2]*pf2[2*4+0]; + pfres2[0*4+1] = pf1[0*4+0]*pf2[0*4+1]+pf1[0*4+1]*pf2[1*4+1]+pf1[0*4+2]*pf2[2*4+1]; + pfres2[0*4+2] = pf1[0*4+0]*pf2[0*4+2]+pf1[0*4+1]*pf2[1*4+2]+pf1[0*4+2]*pf2[2*4+2]; + + pfres2[1*4+0] = pf1[1*4+0]*pf2[0*4+0]+pf1[1*4+1]*pf2[1*4+0]+pf1[1*4+2]*pf2[2*4+0]; + pfres2[1*4+1] = pf1[1*4+0]*pf2[0*4+1]+pf1[1*4+1]*pf2[1*4+1]+pf1[1*4+2]*pf2[2*4+1]; + pfres2[1*4+2] = pf1[1*4+0]*pf2[0*4+2]+pf1[1*4+1]*pf2[1*4+2]+pf1[1*4+2]*pf2[2*4+2]; + + pfres2[2*4+0] = pf1[2*4+0]*pf2[0*4+0]+pf1[2*4+1]*pf2[1*4+0]+pf1[2*4+2]*pf2[2*4+0]; + pfres2[2*4+1] = pf1[2*4+0]*pf2[0*4+1]+pf1[2*4+1]*pf2[1*4+1]+pf1[2*4+2]*pf2[2*4+1]; + pfres2[2*4+2] = pf1[2*4+0]*pf2[0*4+2]+pf1[2*4+1]*pf2[1*4+2]+pf1[2*4+2]*pf2[2*4+2]; + + if( pfres2 != pfres ) memcpy(pfres, pfres2, 9*sizeof(T)); + + return pfres; +} + +inline dReal* mult3(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _mult3(pfres, pf1, pf2); } +inline double* mult3(double* pfres, const double* pf1, const double* pf2) { return _mult3(pfres, pf1, pf2); } + +template +inline T* _mult4(T* pfres, const T* p1, const T* p2) +{ + assert( pfres != NULL && p1 != NULL && p2 != NULL ); + + T* pfres2; + if( pfres == p1 || pfres == p2 ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0*4+0] = p1[0*4+0]*p2[0*4+0] + p1[0*4+1]*p2[1*4+0] + p1[0*4+2]*p2[2*4+0] + p1[0*4+3]*p2[3*4+0]; + pfres2[0*4+1] = p1[0*4+0]*p2[0*4+1] + p1[0*4+1]*p2[1*4+1] + p1[0*4+2]*p2[2*4+1] + p1[0*4+3]*p2[3*4+1]; + pfres2[0*4+2] = p1[0*4+0]*p2[0*4+2] + p1[0*4+1]*p2[1*4+2] + p1[0*4+2]*p2[2*4+2] + p1[0*4+3]*p2[3*4+2]; + pfres2[0*4+3] = p1[0*4+0]*p2[0*4+3] + p1[0*4+1]*p2[1*4+3] + p1[0*4+2]*p2[2*4+3] + p1[0*4+3]*p2[3*4+3]; + + pfres2[1*4+0] = p1[1*4+0]*p2[0*4+0] + p1[1*4+1]*p2[1*4+0] + p1[1*4+2]*p2[2*4+0] + p1[1*4+3]*p2[3*4+0]; + pfres2[1*4+1] = p1[1*4+0]*p2[0*4+1] + p1[1*4+1]*p2[1*4+1] + p1[1*4+2]*p2[2*4+1] + p1[1*4+3]*p2[3*4+1]; + pfres2[1*4+2] = p1[1*4+0]*p2[0*4+2] + p1[1*4+1]*p2[1*4+2] + p1[1*4+2]*p2[2*4+2] + p1[1*4+3]*p2[3*4+2]; + pfres2[1*4+3] = p1[1*4+0]*p2[0*4+3] + p1[1*4+1]*p2[1*4+3] + p1[1*4+2]*p2[2*4+3] + p1[1*4+3]*p2[3*4+3]; + + pfres2[2*4+0] = p1[2*4+0]*p2[0*4+0] + p1[2*4+1]*p2[1*4+0] + p1[2*4+2]*p2[2*4+0] + p1[2*4+3]*p2[3*4+0]; + pfres2[2*4+1] = p1[2*4+0]*p2[0*4+1] + p1[2*4+1]*p2[1*4+1] + p1[2*4+2]*p2[2*4+1] + p1[2*4+3]*p2[3*4+1]; + pfres2[2*4+2] = p1[2*4+0]*p2[0*4+2] + p1[2*4+1]*p2[1*4+2] + p1[2*4+2]*p2[2*4+2] + p1[2*4+3]*p2[3*4+2]; + pfres2[2*4+3] = p1[2*4+0]*p2[0*4+3] + p1[2*4+1]*p2[1*4+3] + p1[2*4+2]*p2[2*4+3] + p1[2*4+3]*p2[3*4+3]; + + pfres2[3*4+0] = p1[3*4+0]*p2[0*4+0] + p1[3*4+1]*p2[1*4+0] + p1[3*4+2]*p2[2*4+0] + p1[3*4+3]*p2[3*4+0]; + pfres2[3*4+1] = p1[3*4+0]*p2[0*4+1] + p1[3*4+1]*p2[1*4+1] + p1[3*4+2]*p2[2*4+1] + p1[3*4+3]*p2[3*4+1]; + pfres2[3*4+2] = p1[3*4+0]*p2[0*4+2] + p1[3*4+1]*p2[1*4+2] + p1[3*4+2]*p2[2*4+2] + p1[3*4+3]*p2[3*4+2]; + pfres2[3*4+3] = p1[3*4+0]*p2[0*4+3] + p1[3*4+1]*p2[1*4+3] + p1[3*4+2]*p2[2*4+3] + p1[3*4+3]*p2[3*4+3]; + + if( pfres != pfres2 ) memcpy(pfres, pfres2, sizeof(T)*16); + return pfres; +} + +inline dReal* mult4(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _mult4(pfres, pf1, pf2); } +inline double* mult4(double* pfres, const double* pf1, const double* pf2) { return _mult4(pfres, pf1, pf2); } + +template +inline T* _multtrans3(T* pfres, const T* pf1, const T* pf2) +{ + T* pfres2; + if( pfres == pf1 ) pfres2 = (T*)alloca(9 * sizeof(T)); + else pfres2 = pfres; + + pfres2[0] = pf1[0]*pf2[0]+pf1[3]*pf2[3]+pf1[6]*pf2[6]; + pfres2[1] = pf1[0]*pf2[1]+pf1[3]*pf2[4]+pf1[6]*pf2[7]; + pfres2[2] = pf1[0]*pf2[2]+pf1[3]*pf2[5]+pf1[6]*pf2[8]; + + pfres2[3] = pf1[1]*pf2[0]+pf1[4]*pf2[3]+pf1[7]*pf2[6]; + pfres2[4] = pf1[1]*pf2[1]+pf1[4]*pf2[4]+pf1[7]*pf2[7]; + pfres2[5] = pf1[1]*pf2[2]+pf1[4]*pf2[5]+pf1[7]*pf2[8]; + + pfres2[6] = pf1[2]*pf2[0]+pf1[5]*pf2[3]+pf1[8]*pf2[6]; + pfres2[7] = pf1[2]*pf2[1]+pf1[5]*pf2[4]+pf1[8]*pf2[7]; + pfres2[8] = pf1[2]*pf2[2]+pf1[5]*pf2[5]+pf1[8]*pf2[8]; + + if( pfres2 != pfres ) memcpy(pfres, pfres2, 9*sizeof(T)); + + return pfres; +} + +template +inline T* _multtrans4(T* pfres, const T* pf1, const T* pf2) +{ + T* pfres2; + if( pfres == pf1 ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + for(int i = 0; i < 4; ++i) { + for(int j = 0; j < 4; ++j) { + pfres[4*i+j] = pf1[i] * pf2[j] + pf1[i+4] * pf2[j+4] + pf1[i+8] * pf2[j+8] + pf1[i+12] * pf2[j+12]; + } + } + + return pfres; +} + +inline dReal* multtrans3(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _multtrans3(pfres, pf1, pf2); } +inline double* multtrans3(double* pfres, const double* pf1, const double* pf2) { return _multtrans3(pfres, pf1, pf2); } +inline dReal* multtrans4(dReal* pfres, const dReal* pf1, const dReal* pf2) { return _multtrans4(pfres, pf1, pf2); } +inline double* multtrans4(double* pfres, const double* pf1, const double* pf2) { return _multtrans4(pfres, pf1, pf2); } + +// stride is in T +template inline T* _inv3(const T* pf, T* pfres, int stride) +{ + T* pfres2; + if( pfres == pf ) pfres2 = (T*)alloca(3 * stride * sizeof(T)); + else pfres2 = pfres; + + // inverse = C^t / det(pf) where C is the matrix of coefficients + + // calc C^t + pfres2[0*stride + 0] = pf[1*stride + 1] * pf[2*stride + 2] - pf[1*stride + 2] * pf[2*stride + 1]; + pfres2[0*stride + 1] = pf[0*stride + 2] * pf[2*stride + 1] - pf[0*stride + 1] * pf[2*stride + 2]; + pfres2[0*stride + 2] = pf[0*stride + 1] * pf[1*stride + 2] - pf[0*stride + 2] * pf[1*stride + 1]; + pfres2[1*stride + 0] = pf[1*stride + 2] * pf[2*stride + 0] - pf[1*stride + 0] * pf[2*stride + 2]; + pfres2[1*stride + 1] = pf[0*stride + 0] * pf[2*stride + 2] - pf[0*stride + 2] * pf[2*stride + 0]; + pfres2[1*stride + 2] = pf[0*stride + 2] * pf[1*stride + 0] - pf[0*stride + 0] * pf[1*stride + 2]; + pfres2[2*stride + 0] = pf[1*stride + 0] * pf[2*stride + 1] - pf[1*stride + 1] * pf[2*stride + 0]; + pfres2[2*stride + 1] = pf[0*stride + 1] * pf[2*stride + 0] - pf[0*stride + 0] * pf[2*stride + 1]; + pfres2[2*stride + 2] = pf[0*stride + 0] * pf[1*stride + 1] - pf[0*stride + 1] * pf[1*stride + 0]; + + T fdet = pf[0*stride + 2] * pfres2[2*stride + 0] + pf[1*stride + 2] * pfres2[2*stride + 1] + + pf[2*stride + 2] * pfres2[2*stride + 2]; + + if( fabs(fdet) < 1e-6 ) return NULL; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres != pf ) { + pfres[0*stride+0] *= fdet; pfres[0*stride+1] *= fdet; pfres[0*stride+2] *= fdet; + pfres[1*stride+0] *= fdet; pfres[1*stride+1] *= fdet; pfres[1*stride+2] *= fdet; + pfres[2*stride+0] *= fdet; pfres[2*stride+1] *= fdet; pfres[2*stride+2] *= fdet; + return pfres; + } + + pfres[0*stride+0] = pfres2[0*stride+0] * fdet; + pfres[0*stride+1] = pfres2[0*stride+1] * fdet; + pfres[0*stride+2] = pfres2[0*stride+2] * fdet; + pfres[1*stride+0] = pfres2[1*stride+0] * fdet; + pfres[1*stride+1] = pfres2[1*stride+1] * fdet; + pfres[1*stride+2] = pfres2[1*stride+2] * fdet; + pfres[2*stride+0] = pfres2[2*stride+0] * fdet; + pfres[2*stride+1] = pfres2[2*stride+1] * fdet; + pfres[2*stride+2] = pfres2[2*stride+2] * fdet; + return pfres; +} + +inline dReal* inv3(const dReal* pf, dReal* pfres, int stride) { return _inv3(pf, pfres, stride); } + +// inverse if 92 mults and 39 adds +template inline T* _inv4(const T* pf, T* pfres) +{ + T* pfres2; + if( pfres == pf ) pfres2 = (T*)alloca(16 * sizeof(T)); + else pfres2 = pfres; + + // inverse = C^t / det(pf) where C is the matrix of coefficients + + // calc C^t + + // determinants of all possibel 2x2 submatrices formed by last two rows + T fd0, fd1, fd2; + T f1, f2, f3; + fd0 = pf[2*4 + 0] * pf[3*4 + 1] - pf[2*4 + 1] * pf[3*4 + 0]; + fd1 = pf[2*4 + 1] * pf[3*4 + 2] - pf[2*4 + 2] * pf[3*4 + 1]; + fd2 = pf[2*4 + 2] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 2]; + + f1 = pf[2*4 + 1] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 1]; + f2 = pf[2*4 + 0] * pf[3*4 + 3] - pf[2*4 + 3] * pf[3*4 + 0]; + f3 = pf[2*4 + 0] * pf[3*4 + 2] - pf[2*4 + 2] * pf[3*4 + 0]; + + pfres2[0*4 + 0] = pf[1*4 + 1] * fd2 - pf[1*4 + 2] * f1 + pf[1*4 + 3] * fd1; + pfres2[0*4 + 1] = -(pf[0*4 + 1] * fd2 - pf[0*4 + 2] * f1 + pf[0*4 + 3] * fd1); + + pfres2[1*4 + 0] = -(pf[1*4 + 0] * fd2 - pf[1*4 + 2] * f2 + pf[1*4 + 3] * f3); + pfres2[1*4 + 1] = pf[0*4 + 0] * fd2 - pf[0*4 + 2] * f2 + pf[0*4 + 3] * f3; + + pfres2[2*4 + 0] = pf[1*4 + 0] * f1 - pf[1*4 + 1] * f2 + pf[1*4 + 3] * fd0; + pfres2[2*4 + 1] = -(pf[0*4 + 0] * f1 - pf[0*4 + 1] * f2 + pf[0*4 + 3] * fd0); + + pfres2[3*4 + 0] = -(pf[1*4 + 0] * fd1 - pf[1*4 + 1] * f3 + pf[1*4 + 2] * fd0); + pfres2[3*4 + 1] = pf[0*4 + 0] * fd1 - pf[0*4 + 1] * f3 + pf[0*4 + 2] * fd0; + + // determinants of first 2 rows of 4x4 matrix + fd0 = pf[0*4 + 0] * pf[1*4 + 1] - pf[0*4 + 1] * pf[1*4 + 0]; + fd1 = pf[0*4 + 1] * pf[1*4 + 2] - pf[0*4 + 2] * pf[1*4 + 1]; + fd2 = pf[0*4 + 2] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 2]; + + f1 = pf[0*4 + 1] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 1]; + f2 = pf[0*4 + 0] * pf[1*4 + 3] - pf[0*4 + 3] * pf[1*4 + 0]; + f3 = pf[0*4 + 0] * pf[1*4 + 2] - pf[0*4 + 2] * pf[1*4 + 0]; + + pfres2[0*4 + 2] = pf[3*4 + 1] * fd2 - pf[3*4 + 2] * f1 + pf[3*4 + 3] * fd1; + pfres2[0*4 + 3] = -(pf[2*4 + 1] * fd2 - pf[2*4 + 2] * f1 + pf[2*4 + 3] * fd1); + + pfres2[1*4 + 2] = -(pf[3*4 + 0] * fd2 - pf[3*4 + 2] * f2 + pf[3*4 + 3] * f3); + pfres2[1*4 + 3] = pf[2*4 + 0] * fd2 - pf[2*4 + 2] * f2 + pf[2*4 + 3] * f3; + + pfres2[2*4 + 2] = pf[3*4 + 0] * f1 - pf[3*4 + 1] * f2 + pf[3*4 + 3] * fd0; + pfres2[2*4 + 3] = -(pf[2*4 + 0] * f1 - pf[2*4 + 1] * f2 + pf[2*4 + 3] * fd0); + + pfres2[3*4 + 2] = -(pf[3*4 + 0] * fd1 - pf[3*4 + 1] * f3 + pf[3*4 + 2] * fd0); + pfres2[3*4 + 3] = pf[2*4 + 0] * fd1 - pf[2*4 + 1] * f3 + pf[2*4 + 2] * fd0; + + T fdet = pf[0*4 + 3] * pfres2[3*4 + 0] + pf[1*4 + 3] * pfres2[3*4 + 1] + + pf[2*4 + 3] * pfres2[3*4 + 2] + pf[3*4 + 3] * pfres2[3*4 + 3]; + + if( fabs(fdet) < 1e-6) return NULL; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres2 == pfres ) { + mult(pfres, fdet, 16); + return pfres; + } + + int i = 0; + while(i < 16) { + pfres[i] = pfres2[i] * fdet; + ++i; + } + + return pfres; +} + +inline dReal* inv4(const dReal* pf, dReal* pfres) { return _inv4(pf, pfres); } + +template inline T* _transpose3(const T* pf, T* pfres) +{ + assert( pf != NULL && pfres != NULL ); + + if( pf == pfres ) { + rswap(pfres[1], pfres[3]); + rswap(pfres[2], pfres[6]); + rswap(pfres[5], pfres[7]); + return pfres; + } + + pfres[0] = pf[0]; pfres[1] = pf[3]; pfres[2] = pf[6]; + pfres[3] = pf[1]; pfres[4] = pf[4]; pfres[5] = pf[7]; + pfres[6] = pf[2]; pfres[7] = pf[5]; pfres[8] = pf[8]; + + return pfres; +} + +inline dReal* transpose3(const dReal* pf, dReal* pfres) { return _transpose3(pf, pfres); } +inline double* transpose3(const double* pf, double* pfres) { return _transpose3(pf, pfres); } + +template inline T* _transpose4(const T* pf, T* pfres) +{ + assert( pf != NULL && pfres != NULL ); + + if( pf == pfres ) { + rswap(pfres[1], pfres[4]); + rswap(pfres[2], pfres[8]); + rswap(pfres[3], pfres[12]); + rswap(pfres[6], pfres[9]); + rswap(pfres[7], pfres[13]); + rswap(pfres[11], pfres[15]); + return pfres; + } + + pfres[0] = pf[0]; pfres[1] = pf[4]; pfres[2] = pf[8]; pfres[3] = pf[12]; + pfres[4] = pf[1]; pfres[5] = pf[5]; pfres[6] = pf[9]; pfres[7] = pf[13]; + pfres[8] = pf[2]; pfres[9] = pf[6]; pfres[10] = pf[10]; pfres[11] = pf[14]; + pfres[12] = pf[3]; pfres[13] = pf[7]; pfres[14] = pf[11]; pfres[15] = pf[15]; + return pfres; +} + +inline dReal* transpose4(const dReal* pf, dReal* pfres) { return _transpose4(pf, pfres); } +inline double* transpose4(const double* pf, double* pfres) { return _transpose4(pf, pfres); } + +inline dReal dot2(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1]; +} + +inline dReal dot3(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1] + pf1[2]*pf2[2]; +} + +inline dReal dot4(const dReal* pf1, const dReal* pf2) +{ + assert( pf1 != NULL && pf2 != NULL ); + return pf1[0]*pf2[0] + pf1[1]*pf2[1] + pf1[2]*pf2[2] + pf1[3] * pf2[3]; +} + +inline dReal lengthsqr2(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1]; +} + +inline dReal lengthsqr3(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1] + pf[2] * pf[2]; +} + +inline dReal lengthsqr4(const dReal* pf) +{ + assert( pf != NULL ); + return pf[0] * pf[0] + pf[1] * pf[1] + pf[2] * pf[2] + pf[3] * pf[3]; +} + +inline dReal* normalize2(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1]; + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + + return pfout; +} + +inline dReal* normalize3(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1] + pf[2]*pf[2]; + + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + pfout[2] = pf[2] * f; + + return pfout; +} + +inline dReal* normalize4(dReal* pfout, const dReal* pf) +{ + assert(pf != NULL); + + dReal f = pf[0]*pf[0] + pf[1]*pf[1] + pf[2]*pf[2] + pf[3]*pf[3]; + + f = 1.0f / sqrtf(f); + pfout[0] = pf[0] * f; + pfout[1] = pf[1] * f; + pfout[2] = pf[2] * f; + pfout[3] = pf[3] * f; + + return pfout; +} + +inline dReal* cross3(dReal* pfout, const dReal* pf1, const dReal* pf2) +{ + assert( pfout != NULL && pf1 != NULL && pf2 != NULL ); + + dReal temp[3]; + temp[0] = pf1[1] * pf2[2] - pf1[2] * pf2[1]; + temp[1] = pf1[2] * pf2[0] - pf1[0] * pf2[2]; + temp[2] = pf1[0] * pf2[1] - pf1[1] * pf2[0]; + + pfout[0] = temp[0]; pfout[1] = temp[1]; pfout[2] = temp[2]; + return pfout; +} + +template inline void mult(T* pf, T fa, int r) +{ + assert( pf != NULL ); + + while(r > 0) { + --r; + pf[r] *= fa; + } +} + +template +inline T* mult(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * r1 * c2); + + while(r1 > 0) { + --r1; + + j = 0; + while(j < c2) { + k = 0; + while(k < c1) { + pfres[j] += pf1[k] * pf2[k*c2 + j]; + ++k; + } + ++j; + } + + pf1 += c1; + pfres += c2; + } + + return pfres; +} + +template +inline T* multtrans(T* pf1, R* pf2, int r1, int c1, int c2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int i, j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * c1 * c2); + + i = 0; + while(i < c1) { + + j = 0; + while(j < c2) { + + k = 0; + while(k < r1) { + pfres[j] += pf1[k*c1] * pf2[k*c2 + j]; + ++k; + } + ++j; + } + + pfres += c2; + ++pf1; + + ++i; + } + + return pfres; +} + +template +inline T* multtrans_to2(T* pf1, R* pf2, int r1, int c1, int r2, S* pfres, bool badd) +{ + assert( pf1 != NULL && pf2 != NULL && pfres != NULL); + int j, k; + + if( !badd ) memset(pfres, 0, sizeof(S) * r1 * r2); + + while(r1 > 0) { + --r1; + + j = 0; + while(j < r2) { + k = 0; + while(k < c1) { + pfres[j] += pf1[k] * pf2[j*c1 + k]; + ++k; + } + ++j; + } + + pf1 += c1; + pfres += r2; + } + + return pfres; +} + +template inline T* multto1(T* pf1, T* pf2, int r, int c, T* pftemp) +{ + assert( pf1 != NULL && pf2 != NULL ); + + int j, k; + bool bdel = false; + + if( pftemp == NULL ) { + pftemp = new T[c]; + bdel = true; + } + + while(r > 0) { + --r; + + j = 0; + while(j < c) { + + pftemp[j] = 0.0; + + k = 0; + while(k < c) { + pftemp[j] += pf1[k] * pf2[k*c + j]; + ++k; + } + ++j; + } + + memcpy(pf1, pftemp, c * sizeof(T)); + pf1 += c; + } + + if( bdel ) delete[] pftemp; + + return pf1; +} + +template inline T* multto2(T* pf1, S* pf2, int r2, int c2, S* pftemp) +{ + assert( pf1 != NULL && pf2 != NULL ); + + int i, j, k; + bool bdel = false; + + if( pftemp == NULL ) { + pftemp = new S[r2]; + bdel = true; + } + + // do columns first + j = 0; + while(j < c2) { + i = 0; + while(i < r2) { + + pftemp[i] = 0.0; + + k = 0; + while(k < r2) { + pftemp[i] += pf1[i*r2 + k] * pf2[k*c2 + j]; + ++k; + } + ++i; + } + + i = 0; + while(i < r2) { + *(pf2+i*c2+j) = pftemp[i]; + ++i; + } + + ++j; + } + + if( bdel ) delete[] pftemp; + + return pf1; +} + +template inline void add(T* pf1, T* pf2, int r) +{ + assert( pf1 != NULL && pf2 != NULL); + + while(r > 0) { + --r; + pf1[r] += pf2[r]; + } +} + +template inline void sub(T* pf1, T* pf2, int r) +{ + assert( pf1 != NULL && pf2 != NULL); + + while(r > 0) { + --r; + pf1[r] -= pf2[r]; + } +} + +template inline T normsqr(T* pf1, int r) +{ + assert( pf1 != NULL ); + + T d = 0.0; + while(r > 0) { + --r; + d += pf1[r] * pf1[r]; + } + + return d; +} + +template inline T lengthsqr(T* pf1, T* pf2, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += sqr(pf1[length] - pf2[length]); + } + + return d; +} + +template inline T dot(T* pf1, T* pf2, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += pf1[length] * pf2[length]; + } + + return d; +} + +template inline T sum(T* pf, int length) +{ + T d = 0; + while(length > 0) { + --length; + d += pf[length]; + } + + return d; +} + +template inline bool inv2(T* pf, T* pfres) +{ + T fdet = pf[0] * pf[3] - pf[1] * pf[2]; + + if( fabs(fdet) < 1e-16 ) return false; + + fdet = 1 / fdet; + //if( pfdet != NULL ) *pfdet = fdet; + + if( pfres != pf ) { + pfres[0] = fdet * pf[3]; pfres[1] = -fdet * pf[1]; + pfres[2] = -fdet * pf[2]; pfres[3] = fdet * pf[0]; + return true; + } + + dReal ftemp = pf[0]; + pfres[0] = pf[3] * fdet; + pfres[1] *= -fdet; + pfres[2] *= -fdet; + pfres[3] = ftemp * pf[0]; + + return true; +} + +#endif diff --git a/plugins/gs/zerogs/opengl/zpipe.cpp b/plugins/gs/zerogs/opengl/zpipe.cpp new file mode 100644 index 0000000..fef5f68 --- /dev/null +++ b/plugins/gs/zerogs/opengl/zpipe.cpp @@ -0,0 +1,115 @@ +// zpipe.cpp : Defines the entry point for the console application. +// + +#include + +#include +#include +#include + +//#define ZLIB_WINAPI +#include "zlib.h" + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress) ; + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) +{ + z_stream strm; + + int ret;//, flush; + unsigned have; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ; + if (ret != Z_OK) + return ret; + + /* compress */ + strm.avail_in = bytes_to_compress ; + strm.avail_out = bytes_to_compress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + + ret = deflate(&strm, Z_FINISH) ; + have = bytes_to_compress - strm.avail_out ; + *bytes_after_compressed = have ; + + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes) +{ + z_stream strm; + + int ret; + //unsigned have; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress */ + strm.avail_in = bytes_to_decompress ; + strm.next_in = (Bytef *)src ; + strm.next_out = (Bytef *)dst ; + strm.avail_out = maximum_after_decompress ; + + ret = inflate(&strm, Z_NO_FLUSH) ; + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + assert(strm.avail_in == 0); /* all input will be used */ + + if( outbytes != NULL ) + *outbytes = strm.total_out; + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} diff --git a/plugins/gs/zerogs/opengl/zpipe.h b/plugins/gs/zerogs/opengl/zpipe.h new file mode 100644 index 0000000..cb96229 --- /dev/null +++ b/plugins/gs/zerogs/opengl/zpipe.h @@ -0,0 +1,7 @@ +#ifndef zpipe_h +#define zpipe_h + +int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed) ; +int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompress, int* outbytes); + +#endif diff --git a/plugins/pad/PADwin/ReadMe.txt b/plugins/pad/PADwin/ReadMe.txt new file mode 100644 index 0000000..43a9a5f --- /dev/null +++ b/plugins/pad/PADwin/ReadMe.txt @@ -0,0 +1,89 @@ +PADwin v1.0 +-------------------- + + This is an extension to use with play station2 emulators + such as PCSX2. + The plugin is free open source code. + +Usage: +----- + Place the file "PADwin.dll" (Windows) or "libPADwin.so" (Linux) + at the Plugins directory of the Emulator to use it. + Make sure you calibrated the joystick/gamepad with Control Panel's utility!!! + +Thanks +------ + My cousin Bogdan for giving me the gamepad;) (Florin) + Dr. Hell for his WinMM PAD Driver & joyinfo tool:) + Bositman for helping me fixing bugz;) + Raziel for PS2 controller info + +Changes: +------- + v1.0 + * Commented out the joystic code that was causing troubles in win32 + * Added Devc++ (4.9.9.2) project files to compile with mingw32 easy :) + * Moved some of the PADopen code to PADinit + + v0.9 + * Added vsnet2005 beta1 files. 64bit dll should now work (not tested!) + * Fixed bug in PADclose + + v0.8 + * Configure back to INI + * Some fixes + + v0.7 + * Rewritten by asadr. Analog mode with mouse + + v0.6 + * Analog mode. + * better compatibility + + v0.5: + * Merged with PADxwin + * Bugfixed PAD2 + * Rewrote PADpoll/PADstartPoll, now it has more pad commands + + v0.43: + * Added POV support + * I considered 0 for axis value as disabled. That was wrong. While it worked + with analog sticks, it didn't with "more precise" digital ones:P + * dwButtonNumber is not usable; with my gamepad it gives me the number of + the last button pressed. this is correct according to docs. I don't have + a driver for it so it is handeled by windows default driver. But some dudes, + at Gravis for example, did not understood the meaning of dwButtonNumber; + their driver returns the number of the buttons that are pressed in the same + time, hence the J0_1 assign bug. + * corrected back/fwrd for Z. + + v0.42: + * added joystick/gamepad support + 2 joys; 32 buttons/joy; 6 axis; no POV + + v0.41: + * add a pic in configuration window + + v0.4: + * fixed key repeating + * updated to v0.4.0 specs + + v0.31: + * fixed silly bug after exit + + v0.3: + * Changed old PADreadStatus for PADstartPoll/PADpoll + + v0.2: + * Config and About dialogs added + * Now pads works + + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + + linuzappz + florin diff --git a/plugins/pad/PADwin/Src/Conf.c b/plugins/pad/PADwin/Src/Conf.c new file mode 100644 index 0000000..6d54fec --- /dev/null +++ b/plugins/pad/PADwin/Src/Conf.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include "PAD.h" + + + +#include +#include +#include +#ifndef __WIN32__ +#include +#endif + +void SaveConfig() { + FILE *f; + char cfg[255]; + int i, j; +#ifdef __WIN32__ + CreateDirectory("inis",NULL); + sprintf(cfg,"inis/padwinkeyb.ini"); +#else + sprintf(cfg,"%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf (cfg,"%s/.PS2E/PADwin.cfg",getenv("HOME")); +#endif + f = fopen(cfg,"w"); + if (f == NULL) { + printf("PADwin: Error writing to '%s'\n", cfg); + return; + } + for (j=0; j<2; j++) { + for (i=0; i<16; i++) { + fprintf(f, "[%d][%d] = 0x%lx\n", j, i, conf.keys[j][i]); + } + } + fprintf(f, "logging = %d\n", conf.log); + fclose(f); +} + +void LoadConfig() { + FILE *f; + char str[256]; + char cfg[255]; + int i, j; + + memset(&conf, 0, sizeof(conf)); +#ifdef __WIN32__ + conf.keys[0][0] = '1'; // L2 + conf.keys[0][1] = '3'; // R2 + conf.keys[0][2] = 'Q'; // L1 + conf.keys[0][3] = 'E'; // R1 + conf.keys[0][4] = 'W'; // TRIANGLE + conf.keys[0][5] = 'D'; // CIRCLE + conf.keys[0][6] = 'X'; // CROSS + conf.keys[0][7] = 'A'; // SQUARE + conf.keys[0][8] = VK_DECIMAL; // SELECT + conf.keys[0][11] = VK_NUMPAD0; // START + conf.keys[0][12] = VK_NUMPAD8; // UP + conf.keys[0][13] = VK_NUMPAD6; // RIGHT + conf.keys[0][14] = VK_NUMPAD2; // DOWN + conf.keys[0][15] = VK_NUMPAD4; // LEFT +#else + conf.keys[0][0] = XK_1; // L2 + conf.keys[0][1] = XK_3; // R2 + conf.keys[0][2] = XK_q; // L1 + conf.keys[0][3] = XK_e; // R1 + conf.keys[0][4] = XK_w; // TRIANGLE + conf.keys[0][5] = XK_d; // CIRCLE + conf.keys[0][6] = XK_x; // CROSS + conf.keys[0][7] = XK_a; // SQUARE + conf.keys[0][8] = XK_KP_Delete; // SELECT + conf.keys[0][11] = XK_KP_Insert;// START + conf.keys[0][12] = XK_KP_Up; // UP + conf.keys[0][13] = XK_KP_Right; // RIGHT + conf.keys[0][14] = XK_KP_Down; // DOWN + conf.keys[0][15] = XK_KP_Left; // LEFT +#endif + conf.log = 0; +#ifdef __WIN32__ + sprintf(cfg,"inis/padwinkeyb.ini"); +#else + sprintf (cfg,"%s/.PS2E/PADwin.cfg", getenv("HOME")); +#endif + f = fopen(cfg,"r"); + if (f == NULL) return; + + for (j=0; j<2; j++) { + for (i=0; i<16; i++) { + sprintf(str, "[%d][%d] = 0x%%x\n", j, i); + fscanf(f, str, &conf.keys[j][i]); + } + } + fscanf(f, "logging = %d\n", &conf.log); + fclose(f); +} + + diff --git a/plugins/pad/PADwin/Src/Linux.c b/plugins/pad/PADwin/Src/Linux.c new file mode 100644 index 0000000..b49784f --- /dev/null +++ b/plugins/pad/PADwin/Src/Linux.c @@ -0,0 +1,210 @@ +#include +#include + +#include "PAD.h" +#include "interface.h" +#include "support.h" + +Display *GSdsp; +XEvent E; + + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +void _PADupdate() { + int key; + + XLockDisplay(GSdsp); + while (XPending(GSdsp) > 0) { + XNextEvent(GSdsp, &E); + switch (E.type) { + case KeyPress: + key = XLookupKeysym((XKeyEvent *)&E, 0); + _KeyPress(key); + break; + + case KeyRelease: + key = XLookupKeysym((XKeyEvent *)&E, 0); + _KeyRelease(key); + break; + + case FocusIn: + XAutoRepeatOff(GSdsp); + break; + + case FocusOut: + XAutoRepeatOn(GSdsp); + break; + } + } + XUnlockDisplay(GSdsp); +} + +s32 _PADopen(void *pDsp) { + GSdsp = *(Display**)pDsp; + XAutoRepeatOff(GSdsp); + + return 0; +} + +void _PADclose() { + XAutoRepeatOn(GSdsp); +} + + +GtkWidget *Conf; +GtkWidget *Btn; +//GtkWidget *Analog; +char name[32]; + +int padn; + +void UpdateConf() { + int i; + + for (i=0; i<24; i++) { + char *tmp; + + sprintf(name, "Key%d", i); + Btn = lookup_widget(Conf, name); + tmp = XKeysymToString(conf.keys[padn][i]); + if (tmp != NULL) + gtk_label_set_text(GTK_LABEL(GTK_BIN(Btn)->child), tmp); + else + gtk_label_set_text(GTK_LABEL(GTK_BIN(Btn)->child), "Unknown"); + gtk_object_set_user_data(GTK_OBJECT(Btn), &conf.keys[padn][i]); + } +} + +void OnConf_Key(GtkButton *Btn) { + GdkEvent *ev; + unsigned long *key = (unsigned long*)gtk_object_get_user_data(GTK_OBJECT(Btn)); + char *tmp; + + for (;;) { + ev = gdk_event_get(); + if (ev != NULL) { + if (ev->type == GDK_KEY_PRESS) { + *key = ev->key.keyval; + tmp = XKeysymToString(*key); + if (tmp != NULL) + gtk_label_set_text(GTK_LABEL(GTK_BIN(Btn)->child), tmp); + else + gtk_label_set_text(GTK_LABEL(GTK_BIN(Btn)->child), "Unknown"); + return; + } + } + } +} + +void OnConf_Pad1() { + padn = 0; + UpdateConf(); +} + +void OnConf_Pad2() { + padn = 1; + UpdateConf(); +} + +void OnConf_Ok() { +// conf.analog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Analog)); + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel() { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CALLBACK PADconfigure() { + LoadConfig(); + + Conf = create_Config(); + +// Analog = lookup_widget(Conf, "GtkCheckButton_Analog"); +// gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Analog), conf.analog); + + padn = 0; + UpdateConf(); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok() { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CALLBACK PADabout() { + + About = create_About(); + + gtk_widget_show_all(About); + gtk_main(); +} + +s32 CALLBACK PADtest() { + return 0; +} +/* +PADdriver PADx11 = { + "x11", + _PADopen, + _PADclose, + _PADupdate, +}; +*/ diff --git a/plugins/pad/PADwin/Src/Makefile b/plugins/pad/PADwin/Src/Makefile new file mode 100644 index 0000000..89423e8 --- /dev/null +++ b/plugins/pad/PADwin/Src/Makefile @@ -0,0 +1,25 @@ + +PLUGIN = libPADwin.so +CFLAGS = -fPIC -Wall -O2 -fomit-frame-pointer -D__LINUX__ +OBJS = PAD.o Conf.o Linux.o +OBJS += interface.o support.o +LIBS = $(shell pkg-config --libs gtk+-2.0) +CFLAGS += $(shell pkg-config --cflags gtk+-2.0) + +DEPS:= $(OBJS:.o=.d) + +all: plugin +install: all + +plugin: ${OBJS} + rm -f ${PLUGIN} + gcc -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +.PHONY: clear plugin + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} + +-include ${DEPS} + diff --git a/plugins/pad/PADwin/Src/Makefile.mingw b/plugins/pad/PADwin/Src/Makefile.mingw new file mode 100644 index 0000000..c125aa2 --- /dev/null +++ b/plugins/pad/PADwin/Src/Makefile.mingw @@ -0,0 +1,29 @@ + +RC = windres + +PLUGIN = PADwin.dll +CFLAGS = -Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32__ +LIBS = -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +RESOBJ = PADwnKeyb.o +OBJS = PAD.o Conf.o Win32.o ${RESOBJ} +STRIP = strip + +DEPS:= $(OBJS:.o=.d) + +all: plugin + +plugin: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clear plugin + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} + +${RESOBJ}: PADwnKeyb.rc + ${RC} -D__MINGW32__ -J rc -Imingw -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/pad/PADwin/Src/PAD.c b/plugins/pad/PADwin/Src/PAD.c new file mode 100644 index 0000000..1c9da16 --- /dev/null +++ b/plugins/pad/PADwin/Src/PAD.c @@ -0,0 +1,528 @@ +/* PADwin + * Copyright (C) 2002-2004 PADwin Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "PAD.h" + +char *libraryName = "PADwinKeyb Driver"; + +const unsigned char version = PS2E_PAD_VERSION; +const unsigned char revision = 1; +const unsigned char build = 0; // increase that with each version + + +u32 pads=0; +u8 stdpar[2][20] = { {0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; +u8 cmd40[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a}}; +u8 cmd41[2][8] = { {0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a}}; +u8 unk46[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}}; +u8 unk47[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}}; +u8 unk4c[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +u8 unk4d[2][8] = { {0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +u8 cmd4f[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a}}; +u8 stdcfg[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; // 2 & 3 = 0 +u8 stdmode[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +u8 stdmodel[2][8] = { {0xff, 0x5a, + 0x03, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}, + {0xff, 0x5a, + 0x03, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}}; + +u8 *buf; +int padID[2]; +int padMode[2]; +int curPad; +int curByte; +int curCmd; +int cmdLen; +int ds2mode = 0; // DS Mode at start +FILE *padLog = NULL; + +int POV(u32 direction, u32 angle){ + if ((direction==0) && (angle>= 0) && (angle< 4500)) return 1;//forward + if ((direction==2) && (angle>= 4500) && (angle<13500)) return 1;//right + if ((direction==1) && (angle>=13500) && (angle<22500)) return 1;//backward + if ((direction==3) && (angle>=22500) && (angle<31500)) return 1;//left + if ((direction==0) && (angle>=31500) && (angle<36000)) return 1;//forward + return 0; +} + +void _KeyPressNE(u32 key) { + int i; + + if (pads & 0x1) { + for (i=0; i<16; i++) { + if (key == conf.keys[0][i]) { + status[0]&=~(1<> 8; + stdpar[3] = status[curPad-1] & 0xff; + cmdLen = 4; + buf = stdpar; + return 0x41; + } + + if (curByte >= cmdLen) return 0; + return buf[curByte++]; +}*/ + +u8 _PADpoll(u8 value) { + u8 button_check = 0, button_check2 = 0; + + if (curByte == 0) { + curByte++; +#ifdef PAD_LOG + PAD_LOG("PADpoll: cmd: %x\n", value); +#endif + + curCmd = value; + switch (value) { + case 0x40: // DUALSHOCK2 ENABLER + cmdLen = 8; + buf = cmd40[curPad]; + return 0xf3; + + case 0x41: // QUERY_DS2_ANALOG_MODE + cmdLen = 8; + buf = cmd41[curPad]; + return 0xf3; + + case 0x42: // READ_DATA + if(lanalog.button) status[curPad] &= ~(1<<9); + else status[curPad] |= (1<<9); + if(ranalog.button) status[curPad] &= ~(1<<10); + else status[curPad] |= (1<<10); + + lanalog.button = 0; // reset them :p (l3) + ranalog.button = 0; // reset them :P (r3) + + stdpar[curPad][2] = status[curPad] >> 8; + stdpar[curPad][3] = status[curPad] & 0xff; + stdpar[curPad][4] = ranalog.x; + stdpar[curPad][5] = ranalog.y; + stdpar[curPad][6] = lanalog.x; + stdpar[curPad][7] = lanalog.y; + if (padMode[curPad] == 1) cmdLen = 20; + else cmdLen = 4; + button_check2 = stdpar[curPad][2] >> 4; + switch(stdpar[curPad][3]) + { + case 0xBF: // X + stdpar[curPad][14] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][16])); + break; + case 0xDF: // Circle + stdpar[curPad][13] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][17])); + break; + case 0xEF: // Triangle + stdpar[curPad][12] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][19])); + break; + case 0x7F: // Square + stdpar[curPad][15] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][18])); + break; + case 0xFB: // L1 + stdpar[curPad][16] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][26])); + break; + case 0xF7: // R1 + stdpar[curPad][17] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][28])); + break; + case 0xFE: // L2 + stdpar[curPad][18] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][27])); + break; + case 0xFD: // R2 + stdpar[curPad][19] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][29])); + break; + default: + stdpar[curPad][14] = 0x00; // Not pressed + stdpar[curPad][13] = 0x00; // Not pressed + stdpar[curPad][12] = 0x00; // Not pressed + stdpar[curPad][15] = 0x00; // Not pressed + stdpar[curPad][16] = 0x00; // Not pressed + stdpar[curPad][17] = 0x00; // Not pressed + stdpar[curPad][18] = 0x00; // Not pressed + stdpar[curPad][19] = 0x00; // Not pressed + break; + } + switch(button_check2) + { + case 0xE: // UP + stdpar[curPad][10] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][21])); + break; + case 0xB: // DOWN + stdpar[curPad][11] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][22])); + break; + case 0x7: // LEFT + stdpar[curPad][9] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][23])); + break; + case 0xD: // RIGHT + stdpar[curPad][8] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][24])); + break; + default: + stdpar[curPad][8] = 0x00; // Not pressed + stdpar[curPad][9] = 0x00; // Not pressed + stdpar[curPad][10] = 0x00; // Not pressed + stdpar[curPad][11] = 0x00; // Not pressed + break; + } + buf = stdpar[curPad]; + return padID[curPad]; + + case 0x43: // CONFIG_MODE + cmdLen = 8; + buf = stdcfg[curPad]; + if (stdcfg[curPad][3] == 0xff) return 0xf3; + else return padID[curPad]; + + case 0x44: // SET_MODE_AND_LOCK + cmdLen = 8; + buf = stdmode[curPad]; + return 0xf3; + + case 0x45: // QUERY_MODEL_AND_MODE + cmdLen = 8; + buf = stdmodel[curPad]; + buf[4] = padMode[curPad]; + return 0xf3; + + case 0x46: // ?? + cmdLen = 8; + buf = unk46[curPad]; + return 0xf3; + + case 0x47: // ?? + cmdLen = 8; + buf = unk47[curPad]; + return 0xf3; + + case 0x4c: // QUERY_MODE ?? + cmdLen = 8; + buf = unk4c[curPad]; + return 0xf3; + + case 0x4d: + cmdLen = 8; + buf = unk4d[curPad]; + return 0xf3; + + case 0x4f: // SET_DS2_NATIVE_MODE + cmdLen = 8; + padID[curPad] = 0x79; // setting ds2 mode + ds2mode = 1; // Set DS2 Mode + buf = cmd4f[curPad]; + return 0xf3; + + default: +#ifdef PAD_LOG + PAD_LOG("*PADpoll*: unknown cmd %x\n", value); +#endif + break; + } + } + + switch (curCmd) { + case 0x43: + if(curByte == 2) + { + switch(value){ + case 0: + buf[2] = 0; + buf[3] = 0; + break; + case 1: + buf[2] = 0xff; + buf[3] = 0xff; + break; + } + } + break; + + case 0x44: + if (curByte == 2) { + PADsetMode(curPad, value); + } + break; + + case 0x46: + if(curByte == 2) { + switch(value) { + case 0: // default + buf[5] = 0x2; + buf[6] = 0x0; + buf[7] = 0xA; + break; + case 1: // Param std conf change + buf[5] = 0x1; + buf[6] = 0x1; + buf[7] = 0x14; + break; + } + } + break; + + case 0x4c: + if (curByte == 2) { + switch (value) { + case 0: // mode 0 - digital mode + buf[5] = 0x4; + break; + + case 1: // mode 1 - analog mode + buf[5] = 0x7; + break; + } + } + break; + } + + if (curByte >= cmdLen) return 0; + return buf[curByte++]; +} + +u8 CALLBACK PADpoll(u8 value) { + u8 ret; +/* if (conf.analog) { + ret = PADpollAnalog(value); + } else { + ret = PADpollDigital(value); + }*/ + ret = _PADpoll(value); +#ifdef PAD_LOG + PAD_LOG("PADpoll: %x (%d: %x)\n", value, curByte, ret); +#endif + return ret; +} +/* +u32 CALLBACK PADgetType() { + if (conf.analog) return PAD_TYPE_ANALOG; + else return PAD_TYPE_DIGITAL; +}*/ + +keyEvent ev; + +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent() { + +#ifdef __LINUX__ + _PADupdate(); +#endif + + if (event.event != 0) { + memcpy(&ev, &event, sizeof(ev)); + event.event = 0; + return &ev; + } + + return NULL; +} + + diff --git a/plugins/pad/PADwin/Src/PAD.h b/plugins/pad/PADwin/Src/PAD.h new file mode 100644 index 0000000..f5b854e --- /dev/null +++ b/plugins/pad/PADwin/Src/PAD.h @@ -0,0 +1,107 @@ +/* PADwin + * Copyright (C) 2002-2004 PADwin Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PAD_H__ +#define __PAD_H__ + +#include + +#ifdef __WIN32__ +#include +#include + +#else + +#include +#include +#include + +#endif + +#define PADdefs +#include "PS2Edefs.h" +#include "resource.h" + +char *libraryName; + +typedef struct { + unsigned long keys[2][16]; + int log; +} PADconf; + +typedef struct { + u8 x,y; + u8 button; +} Analog; + +Analog lanalog, ranalog; +PADconf conf; + +extern FILE *padLog; +#define PAD_LOG __Log + + +/* from pad.h */ + +/* + * Button bits + */ +#define PAD_LEFT 0x8000 +#define PAD_DOWN 0x4000 +#define PAD_RIGHT 0x2000 +#define PAD_UP 0x1000 +#define PAD_START 0x0800 +#define PAD_R3 0x0400 +#define PAD_L3 0x0200 +#define PAD_SELECT 0x0100 +#define PAD_SQUARE 0x0080 +#define PAD_CROSS 0x0040 +#define PAD_CIRCLE 0x0020 +#define PAD_TRIANGLE 0x0010 +#define PAD_R1 0x0008 +#define PAD_L1 0x0004 +#define PAD_R2 0x0002 +#define PAD_L2 0x0001 + +/* end of pad.h */ + +keyEvent event; + +u16 status[2]; +int pressure; +extern u32 pads; + +int POV(u32 direction, u32 angle); +s32 _PADopen(void *pDsp); +void _PADclose(); +void _KeyPressNE(u32 key); +void _KeyPress(u32 key); +void _KeyReleaseNE(u32 key); +void _KeyRelease(u32 key); +void PADsetMode(int pad, int mode); +void _PADupdate(); + +void __Log(char *fmt, ...); +void LoadConfig(); +void SaveConfig(); + +void SysMessage(char *fmt, ...); + +#endif + + diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.def b/plugins/pad/PADwin/Src/PADwinKeyb.def new file mode 100644 index 0000000..7230a0f --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb.def @@ -0,0 +1,22 @@ +; PADdinput.def : Declares the module parameters for the DLL. + +LIBRARY "PADwinKeyb" +DESCRIPTION 'PAD Plugin Using Windows Keyboard' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + PADinit @5 + PADshutdown @6 + PADopen @7 + PADclose @8 + PADkeyEvent @9 + PADstartPoll @10 + PADpoll @11 + PADquery @12 + + PADconfigure @13 + PADtest @14 + PADabout @15 \ No newline at end of file diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.dsp b/plugins/pad/PADwin/Src/PADwinKeyb.dsp new file mode 100644 index 0000000..7d13f57 --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb.dsp @@ -0,0 +1,114 @@ +# Microsoft Developer Studio Project File - Name="PADwinKeyb" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=PADwinKeyb - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "PADwinKeyb.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "PADwinKeyb.mak" CFG="PADwinKeyb - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "PADwinKeyb - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PADDINPUT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PADDINPUT_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=5 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /dll /machine:I386 +# Begin Target + +# Name "PADwinKeyb - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Conf.c +# End Source File +# Begin Source File + +SOURCE=.\PAD.c +# End Source File +# Begin Source File + +SOURCE=.\PADwinKeyb.def +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\PAD.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=.\PS2Etypes.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\controller.bmp +# End Source File +# Begin Source File + +SOURCE=.\PADwnKeyb.rc +# End Source File +# Begin Source File + +SOURCE=.\ps2pad.bmp +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.dsw b/plugins/pad/PADwin/Src/PADwinKeyb.dsw new file mode 100644 index 0000000..6388bde --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "PADwinKeyb"=".\PADwinKeyb.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.sln b/plugins/pad/PADwin/Src/PADwinKeyb.sln new file mode 100644 index 0000000..5fff7a5 --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PADwinKeyb", "PADwinKeyb.vcproj", "{79D9E8A9-C764-4082-826C-B715341FB1E9}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release.ActiveCfg = Release|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.suo b/plugins/pad/PADwin/Src/PADwinKeyb.suo new file mode 100644 index 0000000000000000000000000000000000000000..fa80235f0d1243403ff3d6ef8ae7a13cf0549798 GIT binary patch literal 9216 zcmeHMNo*WN6#X8@#Li-8516fqorMrPj+d+u$jsPD6gvsFvm7kM*wc0h;t4TQ27iR?)|RjXrNzAT$X6kEm7og znZT@iPs^kx<@41gKGR;lY%FNMTt&VwX*@{#A<>khvK!JzQR5t8Q_kAto(`V_MUgc-vHOnN<32}fJ;MTbq;64)r=>L>OeN%@VyZe4g zMtM2P4}u;7HG&=nJp$?i`9Y6^G|&^E6`&?iGiW7= z1E?L;;ncByBg&gVn?YMZTS41EPlKKTZ3jIIdJeP$9+t^iODD0R6|fd5gF07fEl&orlDM}ArPNPSRq5}*JEbfQgyR}AuB{t za}M|QY6Bxj^l|k#KNtxa=9tzUj#y@#3=8_q;fSGYhxB2s$Bd7w&+D?D<^;^~m>Jch zcH8q0MWSKzWFpNzYu8|3FB_{57?Iep8H$Is{z!C;RkL^MQ9T|qSe{y{n%d_o{yK*? z0?5dGvsR)(%BK!}Ag}U?m&7Wj zT=_&@9ep?^G3bN3q81CMHIPrtq->_boar}QE6zKQx$?RGQS&i1QzqmWlPj^v804CeJ_H)U^C_S!ZO6hKjp7R` zR2mxse;i*AIb$rAaqcRSxPH9^vi-o0D#p-@5PU(C9`wsl;~TGP@h!+DG`*Ag@;wS+7Q~u9Yz^nanPw{ybZb*gYPhd>Mq~aj!+COD8*{v48 z6RQgOe;=%598wtvA98eI!mbN>;X23vZ0X+QFNXXR)s2jG%&P^v zCKix084WiS}&Mj_ssj9*q@uGQkUD-bUxRJTE4TUMXV`|mB`6OI*8i3n{5Z4dWXa^|uAT(~nlON?4=|t@Y zylp`M+=IGKlsW)oe$;NnwF%_Mb09Zj$h7(Wu(qSMC|_!I{Eu;@SNV^E_ps9#an1nJxns2bY!o9NQ}{>8_UQ9T=bpsJ2~+zb zuks%Q|Mw35?E}Ug#hS#ms*sQ8mu%NQHVOP$g->5_8|{*_awco}-UE=CK(|^E2998X zw>Ri#P@Y_fIlUo<9eA{&cV}>&RvyuTd%Hs|uyiim?eKsNxPqV-yxR;PXhVrhI_=daKPTVWx`hbtKnB*{4w`{rlAlrhRv{df)vw5;t zC-T-J7OiaGwy9luWk=f&iSt^&ci@MM*XQ-Uy7Jr?zPFa%P_f3ZOIBX}sHth^r@ve~ zyLx!MQ`u1c*Nw)lx~6?^Bwx94<koi;_n*pzUTPl0mM_3%3X{O za{FUPU4^2)be~pC0)Ml|pWZj6CobK7sS?gV)ws*i|9UjK)fxZun#gCE^Zzci+j~k^ zH`$Al{r_nu_n-6In6=x=+^zDhof>5q?9;Z=xTJYFjXYP)MxRVvv)`xpS-Iyx;;b#y zWv%?q!&RhO`6E^O(<#lB8>&<-e<3GwRmk)jD_Upq}i0e~I zc1$jEq*5`tTA1%qOy>UQaQ}Y{VC^FY^9+traavRPbwvDkvBxX^GKO)_pYpd_UTwMZ z%WJ(f_l%ZLV5s!5UuIA>J#l$QXBYnRWW?rc^2FwtIoCH&%tYT*hhvqVn|zTXHvu}r d*~;&rN;^*uhr2h*sV?|f3ZDvoc>jgcz`x?AjHdtq literal 0 HcmV?d00001 diff --git a/plugins/pad/PADwin/Src/PADwinKeyb.vcproj b/plugins/pad/PADwin/Src/PADwinKeyb.vcproj new file mode 100644 index 0000000..9e2d34c --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb.vcproj @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.sln b/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.sln new file mode 100644 index 0000000..4383d1f --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PADwinKeyb", "PADwinKeyb_vsnet2005beta1.vcproj", "{79D9E8A9-C764-4082-826C-B715341FB1E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + amd64|Win32 = amd64|Win32 + amd64|Win64 (AMD64) = amd64|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {79D9E8A9-C764-4082-826C-B715341FB1E9}.amd64|Win32.ActiveCfg = amd64|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.amd64|Win32.Build.0 = amd64|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.amd64|Win64 (AMD64).ActiveCfg = amd64|Win64 (AMD64) + {79D9E8A9-C764-4082-826C-B715341FB1E9}.amd64|Win64 (AMD64).Build.0 = amd64|Win64 (AMD64) + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win32.ActiveCfg = Release|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win32.Build.0 = Release|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.vcproj b/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.vcproj new file mode 100644 index 0000000..705b13b --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwinKeyb_vsnet2005beta1.vcproj @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/PADwin/Src/PADwnKeyb.rc b/plugins/pad/PADwin/Src/PADwnKeyb.rc new file mode 100644 index 0000000..706d8a3 --- /dev/null +++ b/plugins/pad/PADwin/Src/PADwnKeyb.rc @@ -0,0 +1,150 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Modern) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 3, 1, 443, 266 +STYLE WS_CAPTION | WS_SYSMENU +CAPTION "Pad Settings" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "OK",IDOK,320,244,56,18,NOT WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,384,244,56,17,NOT WS_TABSTOP + EDITTEXT IDC_ERIGHT,219,31,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Start",IDC_START,219,17,86,15,NOT WS_TABSTOP, + WS_EX_TRANSPARENT + EDITTEXT IDC_ER2,129,31,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Select",IDC_SELECT,129,17,86,15,NOT WS_TABSTOP, + WS_EX_TRANSPARENT + EDITTEXT IDC_ECIRCLE,340,214,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Cross",IDC2_CROSS,340,199,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ETRIANGLE,340,185,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Square",IDC_SQUARE,340,170,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESQUARE,340,155,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Circle",IDC_CIRCLE,340,140,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ECROSS,340,125,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Triangle",IDC_TRI,340,111,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ER3,340,96,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "R2",IDC_R2,340,81,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESELECT,340,67,86,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "R1",IDC_R1,340,52,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL2,5,214,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "Down",IDC_DOWN,5,199,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EUP,5,185,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "Right",IDC_RIGHT,5,170,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL1,5,155,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "Left",IDC_LEFT,5,140,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ELEFT,5,125,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "Up",IDC_UP,5,111,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL3,5,96,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "L2",IDC_L2,5,81,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESTART,5,67,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "L1",IDC_L1,5,52,86,15,NOT WS_TABSTOP + CONTROL 112,IDC_STATIC,"Static",SS_BITMAP | SS_SUNKEN,94,47,242, + 183,WS_EX_TRANSPARENT + CONTROL "Enable logging(for developer use only!)",IDC_LOG,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,245,141,13 + CONTROL "Tab1",IDC_TABC,"SysTabControl32",0x0,0,0,431,240 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_BITMAP1 BITMAP MOVEABLE PURE "ps2pad.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + BOTTOMMARGIN, 265 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Modern) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/pad/PADwin/Src/PS2Edefs.h b/plugins/pad/PADwin/Src/PS2Edefs.h new file mode 100644 index 0000000..709407d --- /dev/null +++ b/plugins/pad/PADwin/Src/PS2Edefs.h @@ -0,0 +1,812 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/pad/PADwin/Src/PS2Etypes.h b/plugins/pad/PADwin/Src/PS2Etypes.h new file mode 100644 index 0000000..194f655 --- /dev/null +++ b/plugins/pad/PADwin/Src/PS2Etypes.h @@ -0,0 +1,75 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_WIN32) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/pad/PADwin/Src/Win32.c b/plugins/pad/PADwin/Src/Win32.c new file mode 100644 index 0000000..6a4d34e --- /dev/null +++ b/plugins/pad/PADwin/Src/Win32.c @@ -0,0 +1,549 @@ +/* PADwin + * Copyright (C) 2002-2004 PADwin Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "PAD.h" +//#define JOY_TEST//not fully working joystic code +HWND GShwnd; +HINSTANCE hInst=NULL; + +WNDPROC GSwndProc; + +int timer; +#ifdef JOY_TEST +int axis[4][7];//4 joys X (6 axis + 1 POV) +#endif +extern char *libraryName; + +#define WM_MOUSEWHEEL 0x020A +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "PADwinKeyb Msg", 0); +} + +int lbutton = 0; +int rbutton = 0; +int keydown = 0; +LRESULT WINAPI PADwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { +#ifdef JOY_TEST + int i; u32 j; + JOYINFOEX ji={sizeof(JOYINFOEX), JOY_RETURNALL}; +#endif + switch (msg) { +#ifdef JOY_TEST + case WM_TIMER: + + for (i=0; i<4; i++) { + if (JOYERR_NOERROR == joyGetPosEx(i, &ji)) { + for (j=0; j<32; j++) { + if ((1<0xC000 && axis[i][j]){ + _KeyPressNE(0x100+0x10*i+j*2+1); + } else { + _KeyReleaseNE(0x100+0x10*i+j*2+1); + } + } + + if ((axis[i][6] && (ji.dwPOV>= 0) && (ji.dwPOV< 4500)) || + (axis[i][6] && (ji.dwPOV>=31500) && (ji.dwPOV<36000))) { + _KeyPressNE(0x10c+0x10*i); //forward + } else { + _KeyReleaseNE(0x10c+0x10*i); + } + if (axis[i][6] && (ji.dwPOV>= 4500) && (ji.dwPOV<13500)) { + _KeyPressNE((0x10e)+0x10*i); //right + } else { + _KeyReleaseNE((0x10e)+0x10*i); + } + if (axis[i][6] && (ji.dwPOV>=13500) && (ji.dwPOV<22500)) { + _KeyPressNE(0x10d+0x10*i); //backward + } else { + _KeyReleaseNE(0x10d+0x10*i); + } + if (axis[i][6] && (ji.dwPOV>=22500) && (ji.dwPOV<31500)) { + _KeyPressNE(0x10f+0x10*i); //left + } else { + _KeyReleaseNE(0x10f+0x10*i); + } + } + } + return TRUE; +#endif + case WM_KEYDOWN: + if (lParam & 0x40000000) + return TRUE; + _KeyPress(wParam); + keydown = 1; + return TRUE; + + case WM_KEYUP: + _KeyRelease(wParam); + keydown = 0; + pressure = 5; // reset it + return TRUE; + + case WM_MOUSEWHEEL: + if(keydown) + { + pressure += ((short)HIWORD(wParam)/120)*5; + if(pressure >= 100) pressure = 100; + if(pressure <= 0) pressure = 0; + } + return TRUE; + + case WM_LBUTTONDBLCLK: + lanalog.button = 1; + return TRUE; + + case WM_LBUTTONDOWN: + lbutton = 1; + return TRUE; + + case WM_LBUTTONUP: + lanalog.x = 0x80; + lanalog.y = 0x80; + lbutton = 0; + return TRUE; + + case WM_RBUTTONDBLCLK: + ranalog.button = 1; + return TRUE; + + case WM_RBUTTONDOWN: + rbutton = 1; + return TRUE; + + case WM_RBUTTONUP: + ranalog.x = 0x80; + ranalog.y = 0x80; + rbutton = 0; + return TRUE; + + case WM_MOUSEMOVE: + if(lbutton) + { + lanalog.x = LOWORD(lParam) & 254; + lanalog.y = HIWORD(lParam) & 254; + } + if(rbutton) + { + ranalog.x = LOWORD(lParam) & 254; + ranalog.y = HIWORD(lParam) & 254; + } + return TRUE; + + case WM_DESTROY: + case WM_QUIT: + KillTimer(hWnd, 0x80); + // fake escape :) + event.event = KEYPRESS; + event.key = VK_ESCAPE; +// exit(0); + return TRUE; + + default: + if (!timer){SetTimer(hWnd, 0x80, 50, NULL); timer=1;} + return GSwndProc(hWnd, msg, wParam, lParam); + } + + return FALSE; +} + +int padopen=0; + +s32 _PADopen(void *pDsp) { +#ifdef JOY_TEST + JOYCAPS jc; + int i, j; +#endif + memset(&event, 0, sizeof(event)); + + if (padopen == 1) return 0; + LoadConfig(); + + GShwnd = (HWND)*(long*)pDsp; + +#ifdef PAD_LOG + PAD_LOG("SubclassWindow\n"); +#endif + GSwndProc = SubclassWindow(GShwnd, PADwndProc); +#ifdef PAD_LOG + PAD_LOG("SubclassWindowk\n"); +#endif + + timer=0; +#ifdef JOY_TEST + axis[0][0]=axis[0][1]=axis[1][0]=axis[1][1]=1;//all joys have X & Y + for (i=JOYSTICKID1; i<=JOYSTICKID2; i++) + if (JOYERR_NOERROR == joyGetDevCaps(i, &jc, sizeof(jc))){ + for (j=0; j<5; j++) + if ((1<0xC000 && axis[i][j]){ + key=0x100+0x10*i+j*2+1; + break; + } + } + if (j!=6) break; + + if ((axis[i][6] && (ji.dwPOV>= 0) && (ji.dwPOV< 4500)) || + (axis[i][6] && (ji.dwPOV>=31500) && (ji.dwPOV<36000))){ + key=0x10c+0x10*i; break; }//forward + if (axis[i][6] && (ji.dwPOV>= 4500) && (ji.dwPOV<13500)){ + key=(0x10e)+0x10*i; break; }//right + if (axis[i][6] && (ji.dwPOV>=13500) && (ji.dwPOV<22500)){ + key=0x10d+0x10*i; break; }//backward + if (axis[i][6] && (ji.dwPOV>=22500) && (ji.dwPOV<31500)){ + key=0x10f+0x10*i; break; }//left + } + } +#endif + if ((key<256) && (key!=1/*mouse left*/) && (key!=2/*mouse right*/)){ + int i; + KillTimer(hW, 0x80); + for(i = IDC_L2; i <= IDC_LEFT; i+=2) + { + if(i == disabled) + { + HWND temp; + temp = GetDlgItem(hW, disabled-1); + hWC = GetDlgItem(hW, disabled); + switch(disabled) + { + case IDC_L2: + Button_SetText(temp, keyNames[conf.keys[padn][0] = key]); + break; + case IDC_R2: + Button_SetText(temp, keyNames[conf.keys[padn][1] = key]); + break; + case IDC_L1: + Button_SetText(temp, keyNames[conf.keys[padn][2] = key]); + break; + case IDC_R1: + Button_SetText(temp, keyNames[conf.keys[padn][3] = key]); + break; + case IDC_CIRCLE: + Button_SetText(temp, keyNames[conf.keys[padn][5] = key]); + break; + case IDC_TRI: + Button_SetText(temp, keyNames[conf.keys[padn][4] = key]); + break; + case IDC_SQUARE: + Button_SetText(temp, keyNames[conf.keys[padn][7] = key]); + break; + case IDC2_CROSS: + Button_SetText(temp, keyNames[conf.keys[padn][6] = key]); + break; + case IDC_START: + Button_SetText(temp, keyNames[conf.keys[padn][11] = key]); + break; + case IDC_SELECT: + Button_SetText(temp, keyNames[conf.keys[padn][8] = key]); + break; + case IDC_UP: + Button_SetText(temp, keyNames[conf.keys[padn][12] = key]); + break; + case IDC_DOWN: + Button_SetText(temp, keyNames[conf.keys[padn][14] = key]); + break; + case IDC_LEFT: + Button_SetText(temp, keyNames[conf.keys[padn][15] = key]); + break; + case IDC_RIGHT: + Button_SetText(temp, keyNames[conf.keys[padn][13] = key]); + break; + } + EnableWindow(hWC, TRUE); + disabled=0; + return TRUE; + } + } + return TRUE; + } + } + return TRUE; + + case WM_COMMAND: + for(i = IDC_L2; i <= IDC_LEFT; i+=2) + { + if(LOWORD(wParam) == i) + { + if (disabled)//change selection + EnableWindow(GetDlgItem(hW, disabled), TRUE); + + EnableWindow(GetDlgItem(hW, disabled=wParam), FALSE); + + SetTimer(hW, 0x80, 250, NULL); + + return TRUE; + } + } + + switch(LOWORD(wParam)) { + case IDCANCEL: + KillTimer(hW, 0x80); + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + KillTimer(hW, 0x80); + if (IsDlgButtonChecked(hW, IDC_LOG)) + conf.log = 1; + else conf.log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + case WM_NOTIFY: + switch (wParam) { + case IDC_TABC: + hWC = GetDlgItem(hW, IDC_TABC); + padn = TabCtrl_GetCurSel(hWC); + + for (i=0; i<16; i++) { + if( i != 9 && i!=10) + { + hWC = GetDlgItem(hW, IDC_EL3 + i*2); + strcpy(str, keyNames[conf.keys[padn][i]]); + + Button_SetText(hWC, str); + } + } + + return TRUE; + } + return FALSE; + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK PADconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_DIALOG1), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK PADabout() { + SysMessage("Made By Linuzappz - Redone by Asadr. 2004"); + /*DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc);*/ +} + +s32 CALLBACK PADtest() { + return 0; +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/pad/PADwin/Src/afxresmw.h b/plugins/pad/PADwin/Src/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/pad/PADwin/Src/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/pad/PADwin/Src/callbacks.c b/plugins/pad/PADwin/Src/callbacks.c new file mode 100644 index 0000000..e1998f8 --- /dev/null +++ b/plugins/pad/PADwin/Src/callbacks.c @@ -0,0 +1,58 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Pad1 (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Pad2 (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Key (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/pad/PADwin/Src/callbacks.h b/plugins/pad/PADwin/Src/callbacks.h new file mode 100644 index 0000000..941cb37 --- /dev/null +++ b/plugins/pad/PADwin/Src/callbacks.h @@ -0,0 +1,26 @@ +#include + + +void +OnConf_Pad1 (GtkButton *button, + gpointer user_data); + +void +OnConf_Pad2 (GtkButton *button, + gpointer user_data); + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnConf_Key (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/pad/PADwin/Src/controller.bmp b/plugins/pad/PADwin/Src/controller.bmp new file mode 100644 index 0000000000000000000000000000000000000000..943c8cbc28e30ae44918c14cb44a00b81f78f8d6 GIT binary patch literal 490056 zcmdqKXVhI)-R?clr}xAA?H%Ks=Nv_(DvINv z;{Pf9+gxcKrTzb#r~g(~Q_cVVfB$bOr2MyN-POzXN{iNA!;+U<-TUd&xaa#=#ZTT9-+Pl}QW1hd7Jx|uB=d0;{ncDpq z*z2hMdERGr%1R4rTD>gLwU(ZzvL)}|PGd6Vc&|UZY`2b*^^*_l^Hra}j;__1`H}i^ zwvlg3dajQn-*%l<%Y1T6t16#N^VH^vao*qB)c2fK%Qnw>mXeq0qwHStY_*fNUhA2bW-Irkc8!_6<}=Gy zN`0C7R%>+0>d(-)XOvmdH%tAV)V6vn&s<&gHJ(vss%@rnFH;|;Em!|vwT*J7nX5gc zY`L21q->A+4CN&HvOMG2|Fdkdnv!zbysZ4$ee!Dm8LHjg&)&DCZ(?J92; zZJVw7A7wM@jKV7$}UB|Wmqim|QiLSMLmCV&f zc@^?u+F13Cb&ciGx9Kyv57+v0Zm#FuLhqYBubw%dbrZYpzn4uke&c8U_p*`F#wwG0 z+4HPF-E(;B%oJN+;CzLb$>D5+ou26PRIiJ^Y2D#E%yxe zF~()}k8`f6?A3i+|CqZ`hohCr&R4GK`D#psy&ZFtv*eAv&#t`Q4zALdc`XNz#Zzak z^ViB618b)-82(ls8%vYDu(&IW$MY-&k6~-n;q5pjd!4&t?{i^naMpP1^|`v%`RjZ& z&IW&zx$qd~X5IK}jD@qoV)3-HS#8E%V{vl0&&6F>EN+q~XW?#3&f%;Zf8lJfw&upu z#@fnXSRCAiw^@e2mU{NmraG*eNrG3@l~>-XJsE55>Z`o9vREt5z&+z^Z43U2g~nx# zsmz6?k&?l1E8Co$9x`bDIW67Tx0iv zoyOi|urn9#T6^{fV|xy7x{4SYyyxfTzW({9*I)Bldc9T3Og#&2GxWOl*`e_;dlOw- zxtit7gTuA|X<9c%zQ8$~Z1pzrk9H;3tI1`xi;c-<)27B@+PtsvnR>9(#`Le#+VlR- z@qE4LhrxLd^m5dVt7D^$k#=}%&vGF(=Jmf9cIb$<-wpts^g|l!N%^PKOuqU_+YlFL$(bQYtfWM6I zm<)HRJAcL9wY>~iP5;7MOKMkNayIiZd#m1sxzjjo+P3E{tflUH7w*Db80~xw2G@Ge z;b1P@CBfCqD|^wjYES0sZ{B&Uzkh3Qn%A_i@ithyy0g~#D-MelUQVXL-KKws%nb$y zcdajUr*T+Ja@GceN9?69_2?iECRhDyIyc8UbGdd)eMazpY`qr$XV2FECBKiW>vzr5 zcKUnR<~h&S=i;iyVcs9-ulOzQqHWQu6Rd^FJ%bq+W9>QhGxGk<7GvT2+_hKJ@8@dz zeO0d4qs(i#XZd4sp6fz|$W=WRZJYSUz`>08si!B%6hGu6j92OD>j z!7$p(jh}Ef(;CL>zAt&2W0Kd|?qj(QW+s2zeUiC$UG4X=wa<9#Ty2^-H8454H@G{< z#a4K0%uUuZ)|s0uhLy?Op+NRQU@-Qx_+X)#e)5`>NKpvG7)Y1Lfc<44w~r zsjD50+dPKkt+x;KFU;+^tMXU_&kNofheHF;H5Tjdmp(Ku98LyXnYyQ{byZIdoL+pzzvv>~bYudLjcg)q_ulo+^HMqvBEH(x^e~rzxuD0Z`{{CSq32t~f zxtlrdl#{#CiYmjaUiUhG-B+;o(0=}X-^Zu-Fz_9uf8lBBT<7vo|C*K!ZR$LRwQ#pF zmuKhwGuDc)i(ar+*?EI?$}StNTXx&{1!bwyl8v8V7OQR13)VIs&lMBVzI%UW8pQG=G zYZ~|AFR!^-Fy8$Jv39I=$MvV7=5_9hmoPJQ?+%tHFUh0dbZ(ASK5ozc$W6y~3{PDP zXOpqXTz?LKt>L)jtzXk$3y&A-wJN7OJ={3$9L_Nd*LBuT)5GI7ING?Za@JvOuYvn= za5x#<=Z(SWjiDBvuj}0VZCbba4y`RYY`RyRb-&m3@7Vu!1}A%iv+!A(7B-vKCC@Ti zS7nmxURaFQbtb#+&9>0M!C2>S@HRMG`J3D&7Xw`Tk~>?o&3)hGZRBWP<8I@udk>*? z=`$X8>`l!(&c)w#A0! zfZ3asL+8ybhtJ=t9KP*V<a|`tZUF&vCPTppoW8yWOyNqwF zZM+SpSEhR1b#LRWGq~e&Xj^A)jH6Ajom#i@c%*INYmRaL!rWvuoOMmyYhb*JA%9&v zk6BASncJ7E?#+I&IOpA%lY_C1y-<`@xz+j8fw*PXe^-=W?$?yl~v-7=XAXM?rL zW7ymCH}!3wr~a)u+7|Xkjwj3f8-A+m+-K?Ybq&*$dv3a3IcU!2<(Nft%jvsrU(Q{& zOSy3QZso%Lb}#4dy-PWL>7sJX_H)ZYbGImaZoYomQTlXSI4FMd8s_&Jd);p^4IJ}p zK5zCvH0D35&gJ)Pr}dv(_S|f}a>(2n<+w%Llrwf+WUqC>K1<8_%XTd<-hHQX^3Ds& zk>dY;TW(^^NBho^AHsWz$FZ?q!0KSO>t(;TGMK)e zw^naVb*-CBRSuIGZ)rRZe!|im<9V_gwsKuE*7yobvn}&+Tkv$Obz42z3wJ~Frl!@k zaM%4}_Zw^uPHjDVv)ua+3(&i873PjShGcE#&R-ut<}G#edX2ZqX7?PNxt%7~821`H z-_|^~rh}8Uu7A-y5>!fAw1q>apiD$4bg5ML-H5CQmz~h-bR1&)^a$TN!K}Z zL*E*AQ}afi%oSU0-Y6LBzC-9?V==nc89ZQb>RE+-h+}cR(*}N(H6S4wTGrP&U!hu?iR35_n4*k&2+BVx0g72*xW74sk-CNrF2r(7jzWl(w%Il6fti1KqW6Dh{PAG3b z{rK{x6OSxc9ezMLPYgbOhk50|tv4&X%KzBz`D>P~q|?#s=3QirgI;gKb9fqh3_W*~ zv&P-zFC6U3$z$WM_}7n3?&f&UUCZWpAH#PZ?yJ7I|DYWFbl)Kv>-TZ4x{e+4IhpHR zZVcx7)>c^zYlFj$udZi@^<-}3%*Pq0oxf;c*T2fePxB#QGVNn6oUDekS?;|CV$Mh% zgN?Ui-K%S-vR6#4?Z#ldgk&xphOgA!W3WE+8`KuL@iz6ZF}HaP?lri#(3gpKusJsK zBbv8s9>a6cyRFSxn=uaQIlxom%(70bL&Q4-Ya5H18*=WN*N~c5f9o07z<1-OdsR;M z!elEm$CTWimcv_^?ChPDoDBw#`D@G-Z=AW(nPNqj;jHUj&z-x$WMgpZUi<~vi{}7$ z-D5xtH`aPNwJzm!DVOCKg_K*nVY&#^OWp{eOWN$p6jE`rV%xGBj`KUc3hB zQl5pMZ;pN+@QHWdY<>9{v&u{MSX^Fx@{%ZEF7j!$=Xz}eP~*1&m7*;4{M#d$=%epR!`llv2eKZR_$5tbIP7v2OD=o7kfFl z{IC3nV6d^(=G>CM!Cf?R@Ym**(Y^Y6@v=AybA!LGf$<&Od+@n7*Sybso@$|3F*zn+6sutd1rQ=4NiZwKi#4@zyA}mSZBHnlzVhYe+c&+r{Nls!F2Dce?UsIZ`+LfFZ@!^? z<~5g=n_qmg@%hvx3(EewcJYSKvwOi^bTr@nnMcd`hU)9;S<$F?x;yKdgXe5v-o;f% z99Z6U&gsV6@89~?^6NX^SN_23e*8n_XYaqY-1C-e%11A|uv~xg(dDK4?N*Lju(j#) z?blsf|F6=#dY?`6!d&An`O}}hkH=DHYH$|@kCO8>nGGXzY|GQfFpV4RwEI-1CR;n! zM&Cdu!{hLRdxm@2`?fb8H{SLhgfUh3ZOmmJGi&d z^zN|k{KZqC-Mxk6t@#WvIlYIfcSHBWVR1ECo4M=UXNJ!!2J7#>*SzUHO!y6AD{XM1 z#W*ybo7^?7_KdA%nCU6wU7O$Q`ZqOhGPci+#k$v)tN%~?zOYa_b+=7kP>#^N*|~c! zDQ`OI$nx>aFDl=A=MCkLcivGR`1+U1gWtKQJoMdfmIvy718S6))C zm+yf8ibt?VXkL6?UXOJZ=It7P!(#|v7hQ}#-b)_EF$?FEi}&BNy#0(5q^)0Be)8U% z%Y9$?bb0WbU$fVI@Y~-g4}9$l<@cZXaQW8Tt}_k(+7}&M&e&y<&HM400mFGe@r`qS z4egurY1x+br&DfPHh8(?h^yWQ50j&l?9D!B@MM3syKaSvjjuh6Z5+JKei%A_9_z=a zK)d=_XK~auJ~gm2H??iH>l#}#=hr4zD~rWju5%7Mdtq+Xz*c6CHrrq@+;#msU@xqV zb{k{tRa@%gU^TiJwx&)_&Q{N%`VP)j`eCrIeZyPmcw1T9JcsK2!d-MO$yl4d?j&!` zZ!rDaaX0vz`nR%Ib7`q}$(^y@R@tleIi%3Ju4!|u+R?eDWj&`3YkRFbt!~~gTGvu? z*L{cqZ+rIk{I&M*6U<~K}Z?&_25ZJM{!y7&xmx7WDh zsCy3SJ-7x=y=&aH@$wlgm;Tmg$sEP#@?C$~mK&LGiq^gD+|$a}-uznQ9PIns&wo-L z`NMCOepmkXi=UPU@BMoD!>2w{zVVhfly{%EqFgS&;rJcrm3_C|*zUEp{-5z%eLY2s zZ7`2PT;%;B2AKJ{{iKuel3#tqf#pLNpHsdgef`(FK4HB5`>%gtuldODepCMT(;piD ze|7tN%NO2or7@a0x5MYnvRE@>-}rxUuff?1Yb|yBeLC?rpEWfs%$>^J^^&{E)HQwF zdOeFNXTRruuWa``**ezPd2O;e>*UGabil&OY(hIoo(UQ8x|j{Z0GoI`PtUG2Dg6!Q1WNZ?bsI-(+r%tsby@!HvC*vsLp3 zW4-RoZE&9N=aQMICY2z^Ek>-WRB;)QdPv+L#bZ+pMvaU(J zJLa&jt8l#wXBpRPVA?V<-(%h{Iv3uO<0BAPrZRuuu76=Ib>+t0R)#IcV&khb*kgFn zxS7zL_`IH*2SGU!dN;Li=B|O!y20UKFZCMR8(eLy?fqSN+~&3T-oc#MzKYR0Wy!*F z)sY93554Rh)4KP4@iXP&AAPSp`sY8EfBfy?@{hm&tvvddKbMDp@`G~!m+vY+yzOn} zBbT0Eu9o&ZRX*>2vo^7N%@I@KE)4WF#6Fisd>L)LXT<#y8%*59nY-;+-gx{Grk{WI z{#(iecYjfQ|4DiD{=b%gJo5MQ*uxJQ_aFM+y{5JAdCRrp{Tb!u2QDi|FWg%G@C!88 zv4+K%z;7``x8`D_`^@c{VPE5G^(Nr4IO$AI-a3Ebsx#QfxCh}{x9a7NwW)8(owJj< z_a%>e?!wu=UFD9iV?QFbuj$>&TQo7=ZkN;tcWHOct1;?t+zlNpp4z&K(7DE5E2Dj# zxv76s8|VBRd}YpU%v`JY+zrk;d&OKhY%KO1-Zm}l+(rLRcn)aX@E2fgYGB{np?M5L z{)(*{Ys?+YuQeXSS?6z?XEVRoSnJGfYukdy$zJ8Aag)RFHOkIf_joDWd>UMZyIEJ+ z*sDC5o8z)>yfwY6F*d(O?i#nx2U=Jxg2AS9qs)EyeA!0-=fuM<-%7euJ}vPJcW6%Q zhwplOx&N!5FMs>lkIG~B-&g+mkH^YC|M}1I*aP<)6Cb$y3+4xWTz>286?<@oV#^ND zJr*lA0WHgC3=Bl$+Ps=HCq6IhH26$HpR)b}Z}-K!FSdAv&uH%KmmhwQyo|4wzyIc! z#(G}!pN~Bz-v7xy1Md6co#o!Qzscs}RxnABf?t9&hLO zJ`H0UQsWw52mE!WR*u%b#^0X9lp9~2yUEgg4eJ-jlk?NZ!`ALzFxNQW?g>kcubCTT zV_cM72R9yDJ^OT>>s{w@>R=xOe>15c{_47(y;(N~CyVQPjGnQsZIjjJC7^X{3V$Iy z2V<`3-_CdFHLsPOuQl$WvN!qbY;OGRSZoYdojiH0+_)QDPLH?p7EfZtUYmD|wyJYg zuiP~b!`xWcMqTV3>s|MBrES$`dY9bF&Ro;Fs;Ax^=IC43xb8Q^TpK=b^?Li*2JsY~ zYbn}|yRLUr^ETZZJWk&B`GC9V+~lllUUXsOZtyrbJVRqs=b8pq-MDL7*EO$s3*q&` zT1#kOW3ltL`43t5YiEgne77Ku%k=Kz1?8$E(7WeK@4ltn_oc_vyPtKv`-=0+YmYjl zoF=`yJoGLan&EN5-e-HSfXN(sS^_OB zO&_@Vyy^F5-f=hdaIQ73es9NI*S`IH8=6>}H`$wI>aaHI6U+?`!vNE|D`D?|#rV9H zy_DgvxEp@MQ0GeHilOQ8y2s#NueDW;n_3s<;x%}^c@4p0vDEf3gQ=7wrN2u~ToXJ^ z55mi0uJ!f&g~QHb^BctB)VRi4@r!!nE#>eT;A~~Em+=}*>nfk%Em}7cV|W(6@3S6w znbw~X7klZ!`-o}yyH~rv`>o#J{cZDiKaIb8O?l7x@^=+;cEXO^+8VY+@+{ong}a(d zlg72VHR)aV8UDjGeR6kSt$|=Y#H(L)kog*UpgNG(h*cEaN}=Qf?Yu(tZV@HXe$ zQukUO8aUbpegmBC*{ibeWtMtZxwMh{46b*by&msidpU@~W4|~3h2}kUnm2p|_kdTX zf8lU=5s@2XtM+aDonS8-IJK|*Ue~;|rS}`G4ZhBjrkvIBca|7x>{S~qPUcSd4Z+*W zUgPVKzx3G}itOt(F5Fdn^L$eSle@pmYqHmj$1|*_n1oqco3^XPGkoHe7nbkc@|NJI@cK-{0;V^Yfblt4_sNR_Vjsa zV-C#{?N)}nL*D`Z8gKjD%C2{Pel7h5a`6}5CU=9qrh9|Ac)69mrgPD{-q!Qh_$o$P zo{Y5|Z5u2``>O1$4IcL#?#lSQ=v|(VxL4NrvhNJ*5Ki1_zG+_8r+xY=#qUag;<^6* zQ;MTi8pQ9Oby9idA^Vh*74y5lyj@~(=RIe2{Y>l^CO_G?iL>fc(PrhA>k z#@FDmGq-Dp!rK52 zdq@05>vp_#uUC8x4cxqjU@!dbQqSGgx|thu#Z&Wq$%D0)uZ+9NU-K8>ZSdDPn;N(I zy6OAQklz5ud2aT5+@2U-#ow|yRO!Hwd<}{dX4GPkG%Z+@^-D?z4C?2 z%L>h>9ja^4y69KlV}1_UUOfi+y2f2NEWd$g;63s6YR@TqNb|B@4WIX_!w)R)5YPMd zYG1zA*Q>q%rDv5lpLCS1QD(gw>pWPi0l!)M$7}k2XTB$-XZS`gW8@(ey_1G z__x#gLmnoBSC*&0ko}db9ZzW+_BWlI*Vku&z3AbZ!^~iEv{wzSdTQLvt1h-{lDBOQ z9z2GxsdbzFO&y$h=w9jKWUPC_u3=O2W}X^%;5~#M&NlNQjL**1Uh~qIb8S8c=bUa{ zuj^iCaB{ch>GwAO0T#pE@Ezc=xIA^PEi|w3mU3#}0gIi>9>)+GSRC#B2G_dDS7)qo zSzLAIHqD!UZ!*{F$zti)s()dx>EGt{4mhj+;apo^cYSNxcjPtX+*ia(XPU3t=HaK^%4m<4xT_rl>-7 zDE4PqDld7St(UO<8T8y}cC@}}T`|`7BeWw6FrUq8m$h74vd&gbP^_crEgobH`0PER7ehvazc zcRnYJ>p1f!lE3K>M?E|Q)5gJ9V{f#l2hn@JliU@7F~D9W*TK$RI5oqVJjvaOy~~2V=t^TSOjbFyuC!K6PA)?Q=BE@EFW_9I(j-|H`2zK88iwqmy()Hm10?77AI=C8tS z_R8S(EN)lag@exB#$0Ey$2BmP&pOsA@3aAX@@!D|BZI%^@Vfi%R+v9KTYER0qBu9( zk4&+~yJ`*n6R$z97UhhZ&De(G~}{29=*by!|Y?>(GUZcO%iV{5dd zkwYglHv5P78ZteZ%NS>D>(4&-8t4y3!`_;lm5sX{XN|c{BR9_a7}L9*R?fQd7S>u{ z?%k8T9p^*-!rZETZ9N=J#hVDW29Hh4s_dFpIpw}?ybbN!^A;X67iVq3V%2-*_6*Ll zvpD!0{zHp<2yZu-Yg#z8Zt7x>=XKuNUJucqy4TkiH~+zT8+$pxUpqUf^B2NvXkKsn z3_d1xZlAm7D-CSA*I8_P=%l|Jp2WmnI{Mppzc(4oyc^sdGS_$uXN|St_on7GzV_Zi zmNReqw=q|26^E&N4uhSu#$9o#dJU9Q?`q5plG;3Ve8q35o`YY{SadC8GdB)LTb@P4 zo{HOvy*ntrfj!RmmX5`HeWCWfIb#0oa>RC9mBY5#($+fcv!(Xm)gI{VQ4Vui8_dta zYoK+Fx60wHuNO}CW}9=L&!pLUUDo+-uh&JxF3bIQ=Wc21kJ*Fw5Pc5dE9{||F=B){ z1A{q1-Y0xyj}cC7>%KzjTUcwn#c!w{Z_~VE&OO!Y#z*68FqZQA&Qxb;au)_t&OYTf zHm-xAQMc>jp8Y-g_R8F3uky*Z@EjPEI@rd0JDSyf34X7Vy^PIv=Wpu^ZEIt5eBb8x zG4=+7dym)3x_4!)%Ipb|b8h5~!O7h?p_j7INUiyu>k*D9A`qz0p)VRIg9qgl1J>KN3a{L9g zr{^$cF8bE>ZfIQNtm|BhF%yp`n2Y}q+;#RkbJ4_2=eDx@4z7Pat|9mvJofoD`~}*> zXAm2j{%vLBEzF&ooWZ`9t@9T&w)Yt-M}xK2$Nj`;7|!#${~@26&j#vxuDplM%b|Jg zS@pT2_sq_l(E2aDgC!fSV|$>pR~dUaELGZ>{m#YP1=0)flJ}IKmwVx{!okf}m8Tor z9co_ZuB~HJziDo<8qa}sZu6xZh(%-11@=|v^>)=~0CRTuAnfUYpUb{F?&+{$ zhe!H1nVT^V#@$}~y3Y03-p=z)-#7gR_E3*9K7@M@p@EIL;x2iXM}9-?i!s$>K<}F7 z^|-Q?`M$(3Se$QVaq8bGJ_D={)=ubOF|40&gK5cNbZyVz>CAOF2_f*ME+oEr~wAk31Tn)B{ zeywZ{{u-B~uj$|5XXs|c&}K%dcr|L%vRMxYxha%GQQ{g~MX3?(gd}lEpoD zDYtqumurp3$=a+NZ=+Altz#Hx$$ba&f5qj>U};y=y|hIdcnV_zt)6ekSh(9_%=r7ugbq{c znLFaH>s{v6(72JZZ0rr~t1?XL`I}{rBkMG9u-M|tgq zlNJsB!c}kMEp?*r>=&Cd`!x5V=`-n(AsejXbFtDkMh`dXPy&JgR|E07SdlZ&Z2cm z;WISN+xUw&koz}qjr-C5dBgqLkDX_mMN*mfAY_jYTUcC@fqkSVOqrNx6Hh(PjC`zlJ+92Pu77tozG@uvYCVIU9l_gRacbS3yUy93x6a+ucAIpI7#hAG%Cl?7lNMww$>u_9$Pn(etDM)++O)Us3vdr=`%lS$FojzV&#r#@?*MU)XF( z_i>&x7wEBY8JEVK9oN+J+Qd+_E<34>`^0bbLv8|o!hnhJ1dal-a zxf=fvJ_CM3aMR}J;BaLwea_+<3oL%pR_g=po0>OuZp)p!&fcN^4gVJ=iE>k?%!CP;kwP3T$@r$-8C+)PY&S==S9J~D-+dGkUUVAAPVX@)} zh$qKW;Aes7%#Fc2i#3z}wRkkzq8;|RzD?G8tZvWQ%HOGa*BOl7H73K+WT~}zziDJK zI5o2|8qRhp&-Q71@8rEbPp-QM;p>Mzroox}RQDL*Z?Y98W;ye!Q^m#PaJIP~MZ-oP zTr|c~&-S>d^|iJ-uDd4h*X|$p3*K6L=waup_fv+=o(G3vXk~Kv3c+1xY0R1Fq$8YVvj#tW`RC*>1Mym+isDK3tLR`^#U-+pm3nS)h3(^AyBC)1qQ9_uyw? zuF2vMG!MmIGwhGZ9$_!tZ>iRl?OR@T`2OXJ!(Z0K^ zRa+qMVUF0#^TB)D#{s`K6S`LG%&MP2eS*K8-bK46GlQ==m*y-Co{FK)-k!l;PL?K< z{k%5kuAN;0f8*Y)ea3rWo(?TOQ=e_cMUe{kNyUe~(xHBFpt$yl#9_Bvy`dg@_#t8#MJ*((hbab}B*v(X=I&ez~B zo=hEN2hF%B5-`qQ= zdcIZPI)8~BXuboC>@=^Howx2iJhL3N67D8{Kl$Mgh6Z+?u=ftn0CSo5TB^9N17~ku zPS|Ol#k{iSfiu$ByXJ!zpItt1;Y-S`XP>5Xa*nd~XvD;#hxeT+_Dc6!46fcQ{9V(w z;#kJ~8h<;^CVw+ef1u{U++G8xwoMJ1{DrHv&p6y`+K9{TH8EpI-ShD|L@XOIX=s1e z;LTNRFJoWyDSN^8w8{R`>@KcDp8?04!?pT^-%hl(M6+dfvINtkn+!M)R zr1Lbdbw-Q5@HUw%{w2G;P0wKc?fPV^Yh^ge_0H0!cfD?7lD(P7SmQ3dMH8!UsC|3( z4$C?JX1V@G`g%Q+DD|)9u6vu`E8cec*1QJlUCQ-t={-~i<27hpdb$?h3!`b9;x{CF z$um{Yx9VKyuXztEVXkT6(7Cz3xUI8D-@)_BU^H*=x6P^1=K7YtoL_SWN8L1T)4!>M z?QD3MEKO)_cnWYhbgbpZ<*J67q5Xf@vdrL@y|I72U{7=CU-M_%NVP_ z{i=1tTbLy#>^6Iga?RzhDAy{H!`WnR=1VmOcFYtTc};$n`O>PyS+Vc z>rObby#K&xBOzfR|-U1I!&%P-k;v8_em40Zh8xnlTM z@X0h{=w0|$^{#si7KfmAxLQ4j(6~K&$9}_D+h*O_3x9*T#$xnrt5<))`q1AVgTXu> z`Piq`S^4N0vG9|P7dMm@>0ee*+YT(ejFd6pJuT*0o zjK|_GZDMGjlDF{M8SJ{(#^5akb8BvX0}PH7I@dMvkh{rc)4=9Az+2~QuZ#OQvt)4c z)#@E@jlss+(7B<9nP0sKp zzd7fYy4Tr@$6yKlYh};z9jL$m=9>oWJ!mnv-H`*zG!@Y;5$4Ob#6YBaTU%g z?VP-gvNLw=0hd$v($~f-CffMv_o-#ZWc$C!-8*o;=Jizv$FAm>1!C7f$;c zI&yEDs(*v6-q(DFZS-3#nab$hY~Wpr<9U2?n#cuXIk2ixjB z-)RG#Q>J)@6Qp%tanRo7mY1AdzI4s2w2#=k%l%*ZoSjwn@K3&P=QTWd@7;E0U3^};+a!z|amL+P2O5enOHlh z2ag+HJs#J%n~W6`Q|CIH_4r_Pkory)p5=n`}(|C9t!8euUNWc zIeDk~rs?;ewVAEMSjhTf@p`7>(};ny`&&$d$DqNxr;`3%ygpow1aHNuJ{f1D-P!Dn zI?j07^l!Gq+bok;Cetof_WiIp=k^BLm+N9|wkLay%k)Lc z_L_(0^>rAbZ#C9+aA@A}e!0fAZ|1Irjk~FfgSU+HcKN%MD}QMp#z0ihLD#0PtzLt8 zoNbw#w;LXV&$&5c={MgYn420HUF*#CJ=J}VEx4;bUr#|D&cfW_t~74X-vN7VzD=Bk z$)SaP4@uX+#$DLkCu3_ec+B7C?PlzQpIaR5!QZ-`E&YaG?*@ab-i5oy-q5@%dt5_u zHuJ{W%3D|~t}>t2G_Tj)=XE_>nF~wdt;UmQn$BHcU&dz%p6n8RpFU9W3CyG69o&8i z=SAFLe0}H#-!6~*?$_nfzy8I}%K5wY66bv0KWIpF+sYY2})yd8KBx~6hheJ~vlgtZmh$s=Pe z8=98AB+lM*=kiMJ!Tvh!sq-f7qr={1*Btl4a>Wbx*JsPpa+2aXSZ~bv6s!T6t=|dW z=gp+yIU6X?s7RgpRLOUSk*04W59S#!gP++CPo2|f-Q+Lj#%g1+>dEAOd>u!>jp_K> z*RAY4-h0-@zG$x zQC@l0spc^lhr@F?Xu%vC^A`1!PS+f=`4nR39{L`1{;`K!yZ2wN^5y0e!`jQvJk{#7 zS$i@T?go3|EbKi`_qjpiEL|0OS3mcd!(A7Pr^(z`tT?6IaMdf7G+w#2oBz97dBuv8 z%k^r@l=?RLd&I6gc;BmH40)tCM}E=)dshx$a>hx8_DnE1V|x2?YFy{8v$k?q4A@6H z=1s4&n|(WxhtH)>3#)Voik_lAJWdt zdF)X;Bl6Kd>zuM5f4|)S#m|)Q-h6}k5yUzWXU6;*alf3oHd|V-a<^*Tj=|YRuH^m# zZg*%?V0aP z4R(s9$=I5U!^URvT6R6_?B$wdcIw~ghv8yqeGRMU*v4G?8>jsmIJ);%82e!15RFc-Jleay-}FFRcKdQ}gD%$iM!D&pCI|z35zNTR7W~c`IC1`yMkl zEI+t+`ZK2g!2SAbUF*VG*Syqs*O@Foxc8fbas4%YnQ^-*mNPZ+-CwwCa9!^?-2M4s zUwXgjTUgxRcV*=_Yny6Pvz83*#%`K|~(fmNpm+doMZtq$l*cImdR` z&f6E_u2%MZeftM*c}MkjVQ$}dtT=4GZ>M>``nk^z#$-%yf8AF!X5cf3yT|Oa`{249 zgSI_rrv;DuywkWlOWfr(_?g)wVd*B%H}1Yf++{xP&Z}NtelB14fp2`N{QZ|dD~~<+ zfWJQHL+W?g&jbE!`Ti|$wX=0NQ|+Xk=4)PVWAi}y4C7~myXNsq>k_9mh-pCoilLs| zcc|rLZ_Qcj0FPa-PIwOLGv11Q2mh%IeNj?wr3go_V!E8 zD_?ulYt6rAul8SmVG}TZ=RbSG&&qXY9(jl~?<&&8L++w~$6oJL?ut+S zbHG&B!Rh}#vmCo@3U|e0wC<;FpNv`P?}zs7>-f8TH^#p}?=E=Wn%WoadF7z3x3Kfj znN$0i&gfz83~v|4at=FZp~K%te*c^D(D&~xf4S=u<=(elSKg<+#EI)YL3)=tDPjSd z&%nA|F*miXu{IeCcl!iao9?Z1Xs{RNMl$9aM`;sJ)t?$SbBoE9&aIl4abhxBm-h^B zg_vXJ&hT>C5BNhDon7wHd2heD-OpJzr^0&Q8g7-$`y~o9F3C zxNcTk_{Hu)tZkaK|NT5po_b}o?%$WuyJM}3Rz7&)9F4;hUb7smbv?iN#qe)meJGwF@J;%%-u{`H70x8L?o zY1$2K{*5`f(+(W!Z8R@>m$B!7Cx`dyG5D#wtcqQaxk9v z`l^?nWAkdchZ(*@|9^1vb#E}f{%>F^zio&isRrtdCz$(Y#qr7J8WzFO|pkCacF#o!1>;5=*!8# ze@EUJEADOR%!PxrH*RJbUQXjO{VgSxsSe9Vb7%|NXt|W49Y; zO(S!yl3&;6<-Y#K;rIC!2k-0tgT}&TIQs4zt{dF<492Lve=X;3%*%!Do#3wNU2#|Z z?XNxkVEMkfrk`sYbGO&K#$9RN{vMR^9n6Oa-xu$9>_ar4Vfb_R^KWClYw-?Z^4McI zSsrdOH*;sNm}~QF9{(`OUFWRvS6m(FUU3uFwzO)2v;EKdLY;w7V;scW%3WPceAx;6 z?Kv3#y>H!Pn$Vf+aSnLD{XNmJkEeHg%{$h+zK6pkcRiL&b8gaRq-j0_x{Wx8{#hv7 zJX>%V_D<8gJ{RYD8b4+SY1F;9SYO|{XO|21U25whK5@lG=HC)GcK=sDS023QD|S95 z@nn4ehCv_FT8h^nb4WRB_Z@8ybJkthSv~T+dA*?l=i<%=gz-f-tS9w?)<@ap2mLihKWBTwgINw-e%!7JXM$r=Z&M{t#LEBYhFVw zcbv60*T>C|fW^t<%;SD)Z~Uh0{XL_-9QS~^!Ecz^|Nh>1^%cQtjfJ_Pjd|_Vy<_fX zd!OS;^!GhOIu=dax4}vC7#>gW!d+cA*1N`Can$GBoWEo4T3mz1qz?gm``5o)uWzwr z;X!0v?^wGUcXjQw_MCGY_nF?6|8TwL;QH5uyYMyV+nl`_-w=9NT6X2!4gLma&F8Hi zZ+Z}u*E?q;z89Tqyd|!|)0n$xTl@!K*Vf`1`kw`s63=^`=Gyx9-e>T6wP%$H?uPf< zU)S_*aCasCE?mRg?XUgrH}5gt8I#3a@@d?K$9R%F*Eaf|Y-gj%<2`uJ7Uk5%+m*}o z_we>Jj<-3bd*1Sf^5gg1BrW)^@{14NR=$7hTgzA8_?mM2%g(j4b1vL(H`}v;IINwt zUm0uP@OEvV1~E0)t5uyFZO+}s+rFOhWzO7A19#dt{o2N1_i#<$ny--jm9Gnb#cF&8 zer7c4-dk*FXU8)q_#vGy{5`D;;WNd26?xeI{KsSV-ojrz?gzg9CCxS7Dxddd@F^|Zem#jr$4$t>)cxrhKOJHfw*jf%2R;I#VXJ?K_AHzvw>xMbLak?=#d8+Hh z%zBO8JFcTWliF7tGKITphoQz=_^fi($|`?jq<4+CaZR#!%w1w3@F4oX75JSVL*`TU z?#j4Jj2W7jBrjr;yQzoUyjuVI&RzO4woGvkQ~ZRccZYLlFgG>tn7g)*&Puood&gwYbGMH#TcsSkl6kdbrun|XTbMgjvHerI ztGOk-2*$AfV_U_e?5KGr_POD_Gnj%7yk2wo?|tc+1?~IU*IZie)EqzOMY3Mv+T#z` z`DuIDeA+>C6xXUf#+jpoLEP8o)Y#+EIO}_Y<=mRJp?T4|%(tOwt(^WYI@dMvK<|dX zfcF4LGxsuVZS1Z5)mV=!!)Nfb;LzlIYp$3$2E6I_U-)8Mi+A4_J}n>RyXI&A(vsgdb!}sC>xZWk+|?YLak*o!#~lZ^)jpNG zu(?ZP?xJ_;@Bhx=WX3sIu71Y#V{Be+8h10kOnvBKbnoMFH~onI-i*g%*ul8#^KNKf zc-)V(H5JC=>Fo=(x7j3jJ^qY%v;JQ2wy*bPV$qDf(!*o!*7#oat<>ukKhtX%U*BSR zL-U5-g~9COFxI=qT`{++fke_mMXKEpJ+$3DEh)}1Jen*;8Ov<9jk(U=>hA_; z)9dX$1sh|YZfe}{7^HJEmY3_`E#BIK6&wct+m)hdSz|>%+InlBBpnP zyL`WYDlnJl7_t_QMiL`;fv;8%22-wWQO-K~IOX_hV>*4DJWjuY`ievL8~pB@&!Bc2 zD-QbDq4phfH$4c`#kvN*j=77UF~ME*Zmxfe93Qyand{vlU(JhH33ttBn4*z0#*A3s{xu(uyNp||`3~4S=4RXDA$*3>{F?c_ z(z+REHohJ&lLVI=gPYGgox6AttSgRO+P42$R<3vVH0IV=GF>;7yHoV8@1KL_b=^Ca zyW;CK-

K_irD^XAl=*qs5cyHOy}id+|MY#_Qc&=b|aTfj!Aik?(Mp&Y?V8oMl}B zYb#Dv?7|WHKU%K+95}m&{m{2ni~w4feRl9VD|f5r?dI3ewpH&o&6~Wf^K2c1=}X@s zwQe%GXRw#iy)YQ=dd^t%Hr_esU2p~v=f|JD*OGGGiAPAsUTkr3#A!Tm&sP<*@$K^P z557|#y!Y$oKj1NZ?zNZO9Nfh^pYx~%TkG>?ePcL#=4`R*|B8LeT<=a>L-Ft8aI!UX zI9to&+%Cb+T{hIYOg%?CmNF*CRW8%tjY%e_zV$lXY&scE(oR09cjfQWCtufm;*Py= z6ShwHyP=Kg&os&1DSB7jwf%#|RgVi^bE@8j%~QD>I@h?X@^roHS~xx4o*UI?kjBk9 zIQTo(yR=R9A0E$VusDa+Y>h?#nkOHyOdi9sa*BBk%L?%gegD-LojaYo;WMPaFfE6v z&fQ6$!FlWKt=tt)tt_@q^%;!0v2Hln+dpgL?kJ8-b9A|Xj?Jx2<*s|I{r#%X!2UU= zcUR8Wm2Y*uwt*4 zD^8brDdHf|x%0#^&J*T7wlBl#u?Mg8WjzbN)4$GFc$>@(4u{Tl#=8DZwl?m%zu+1d zO)Rb|QLjFO>bbw8>s@Crnj7zhm|J{V_FW(rm-P@gzxZTZC-FVSB>(24?=OG(>?g`! zKle%7kK)Jgxw(Al+N&&<;ngoX$b1++mzHesJYzWLS-|;>BlCSCo6qp?_I$^jb$u(g zRhBm14%iA)Nw7G_M%miBzFP0E$?`bYJ>ct^Q}u4+ax&Pw2jlMA6F!6KT(P(6U6m)f zJ6-P@r!}vZ`?li)_kW8k)4TW)sdH^^Z7O%syUAVGy#2l5bjCTD-VOdva+m!arp&7u zTYayG37c)t@8-I; zUhmqvHrT85_sPh5gFPE2;>hIh+FoYTLgw#I<*xItzh9eIYuuftcUKrKbraz`NEfE(VBD>`x6QG+-vEo9s~Oi@b1}|2o2-pG z>>cG!Iib!)mG&ox^=r>_@zfoa~;b=Ev8k#jh)0|1Gjw{_JO}aB8SK6TyzMpcBzMziK;wq)6*H2( z)AcU?!Z7vE+Vt+w-#xz9yINNPd!LBUz!=-J%rxlA{av*1Snu*&9`g%F-RB+qyB6OY ze00qlb8KQI+?=hwckrZPDeHYXlM?^I&ZLwtO1?n<=j?Ni$8Ow}PtJJ!3cL~9PePiP zeRzj!)<#}~>D_1(6Mc@Y_j%LnZ61Sr4as9?DOxl2FKl&>AsOtR1F^OA;WeO7S=+(6 z!|;=H-kD3p>wSZ~?6X zLyOy-+A7V{{dai^J#VwzSc_NCxar&t#&$Z^{RSVmB*yoQrY*0{`!!B?ene$=yhbpY zvD5T!<8FA(@HrTq?49QC(wBQg5c@EW-(7L=epCJ3JYU2834Dep?(f3f^cW~l_zV&6 z;QO4p?(MnZ+(ieA%ldmFhr#3cUHo0z$C@_%hiOdC{d>oH7k|NHdwreTQvL4t&xG$V zmAh~j_A1ez`l$Zc{>}KSzaQEr^zN%JYcamY-e;A?n~vglKd(44 z)4OBtqIcW=4b$e;();aycH^#?%HCz^GfdUH8Ux?@Ybm>Sb>^aZ+1H^TlRg8wbbRg^ zelOR+U-m!qy)J{ndXIRoSnCCAS#QDolyMjqt4y1ncd2n`XJfGL=h|0iwD(?b>RjdM z-}H2=pP;s3JXvF{u@}~gqvkWD{x!Yp3~stNxGO!%`Ziw2G_QDxuY#uEL%)B-&>g>M zUO98=4u#mbmmj#drHk~vh5g-6+Ht<^SH}5Ai}f9VpOZBh#010nJc}(^H{h;#O#7gX z`M3X~lx$oXe<%BstBuiITUjd>I-5s~4bIx@1TXU%2<9vTTT1R)Z*1Yx1owi=hJqXsT4Rx@^`|59Qng@~lsK55&^9Mfnl8#Y-N4}%!RKL+_iS%9Wo_@J!k)%{{MzG!#iu< zJM}JWD~NIE$J~6~H5Oksjw3U@EByz1@f!}=dEwwX?vZg0{rz~&exDrX*rs#Wb!C4o zJY@DT@Z9^ShJqUSJ z={KCIz2ExZU*j$@YsqKssj_Qc*T7f2__V<_{q@tztRqGP<3~*Ef4sJ1S+gv*j+r{X z2L2wb-xc=Z8TVx!_OiY>>rW(q*Y$7oIk##4gW5dSVNwgDf#K`^^246U>*N@ZXJB84 zt;&6m^RxKb#Ia}ONblk~OmJ5mFy`7C3uiBLYRO?Z@t@tF;jAMMHBWTR-TYZrmVf&8 z4@pl>`n%)tuwfc^%}-F@zuKQ+d_U8>(zDDj8E-3pX$$7c1D&NZ2~CZ5MH_CX|4YtU zv2%u{5t&~*XzR_ir_Sc(P|dp$Q?`8OCidNZ7x}=PkvUJgkk1}I2aLVays$MrUemf_ z7dqDx{0*L_22NdDwQ%&O)-|7D(B>Mq_Z#p5%!?2cIVXZ=zz0FIvfd1>&gaF>8{%QF zt9{^KV0*z6ufhJjtV?6eHfu}g>V4;2AUuoSU*HV*jNL`sn!fG4hswmzzqS4(Ga0V# zD)y3+i?DcCV`OqS7`%~d*c|6$ywBU5tGkTGrLJvbVjQm#{B)jX``YEKDcm((Z44K4 z$9XXLb6QV4{=J@7hl9uMxmetWyK6t8Yw|wq17UFv;`P`s&M}$inQzBv@3XO{tz)E# z*_U$cBV_+LXWZ`E@5J=3`3yt7YyN}S>psJ<&wO9~t&)$uhVkoU{lnU`$IlLO|ChZZ z$NNd-SbPRsM}hAk&XOM2-&MbJH}YVvvDdywuUc43{GZv6EZ0(ub#Ol8w4D1NvUs8K z4BvO!m~6vqU~jXmlQZ`Q59!-|&W!S_pZ#>u-;W)akJeg?WUA+Q3(s(ko7xxtO3RsM z)@z`3@ey{C*5eF!_N#r7K1=Ha{oN z#rF!Hko`JXT%2^yJsM7H-TOYU940a$iqoE0@+auA*l(<^;`A_P?K>``AZZ z>#Dzv8|vm{@$veddz;o3->A7bPks5yf-YXBJtp0MaPG4A88N~wpWN>k#+uF*Z`1c3 za~CF~fivZLH+%)W-qYn1d*9`@w*zJR>^vdm?BmNGlkC%*dG6awe*UpXRGn+Suj$?4 zdNt?n^mqnaYXNs7y=b=`jlVFs?cqz=6Kf`Ht}XlrpLdhaikOGo*Ee(Xcsu4&@40*D zC_e4*T^8v(BKkJDOP*zqX@J4(WA?JsPilMh%IAfveL8f>_U=F6BglWiS3vU)llJ4) zK4sQ+h5D2(I_-qAqrRJ)cPbq@<}Us&{sSB^k5@h~d-?X>1AFws-As#Y|6T3vdwJWV zm-)1o*pt`y<=uVu4C8Lbk@=coxI0XEz09%Uk-*Kx(tCSuwm~^$n=OpD=kK#ixk7s7 z^;$E_dJ6VYWG^%J)j5CJF5<8D2$u%lW7GBY`=;;a`aX~6fQK<7G_Nr?IV%R*zGc)c z!PPA1yqdGtd|&t(?5#OmRq}YUu0QU_>%vUe-4S~MccoqV`R!Z}>0kB^CZUCAX`KaY zsx3xC>x|L3ynfZWcnYu=&eptfcUm0p^tLC@?{%M{<7hI~G^h>pzotHE+t*xp z-r)1}&O1Kj+=acSeS^8Gr{93rK)EK(r}b-!bHB)z$9f9le1pO6>Ei45i8X66&nB)? z<~%m?{xct+1I}7(fW{HqaO^&ldN=3X$lY^*!|n@YEQ7U6%c9XT!P!|bCVd9$59ShE zX8o>#w-$4@mHuN5F*=vM(NEcVyK>0^dlu&SneYGTD_?4RgtJdL`$uy2@SDY9=A}+u zvOw2}z4{!peafVpVHxb}eFiIwWzJo6uJbeb>vb3$eaYJxXFAt-o1U&;&z`u+Sz;K> zGttjv>r(8!^|?R#>~lx_g~^_XgTuci`ToDT4#Q$2(6mz$Om)5MK7;cZ?>AD_zE2)! z$Noj~bl1?eP0OM`gQM`&%E4#jD=dbS!@i#5$=Bp|9c!A^@10{j_j{!;fv4O5{;#ae zIP~&>!5xc}!`?5h;w{wFJYs8u$32sc!|iO1H3^wOXfP0ecsK> z!D6_pScl|tHMsYH?%hSP{g3Al_y5PvSus~^z>6@}W*%{5L;hxL8T0*JO4h0^ zxy$+q${ELNISjV6N@3r#{#p7m{GH}A7;mMCZO<~X*XyBy#aUzUfVuEDQfOPN!(d~r z*sI)hpW0wH&xxnGWTSPoeqv*-3*M%@Z2!FqXD{6Giu23YbnfL3Z+n~Vm-7ql3(20n zoHzW@OJ7>vdfKt&62)b)ANv0C9Cpz?hylQ_Hob|y?UKcisqVf59zZ7NZED|StmRYq zyE$##R~*KJ<>%l`AB#)Y>*JR&FUYxSl<^esY;#`;K99_EhUvOj^@ycqEoQ;;(6**; zd%lLhn>;qgy0_pSM9h*2#AK2XWUlulHBxR$U86UBf!xgVVVM~_m5sZ}S@JB0{%t(Ybr($s(`Q^x-iF>yF5A3Y>gCY8 zrianLN@MQ&x?|S4g}ybd8~Qifq+yfA$=J$YW3Thq)>fd2lgFuhi9-wa!s2l}L;Aa} zcZVKC<1B1W?(%z2@;SH0Ue%c^H;;ibj1_}T7e4|0+w)gU&i!*PIpgGi`G3m)Gk!zU zyiMa){))l2e;IjjxaRWy+L>%(Y{%Ss9vj*=nGAzX^Sa(WQ*(1G^OW%#rp>FNgITLE z(7m1aVBT!#T-U!HcWDpaGQVd2ZZOxlYpl{-_{~oP-#JpMM9C^5$h4YbDoL9c} zwl~_kF5e?udqirVNcKu(kAr))j{*DVaCXIc@*EDIA7@^Qb-pKhuX$Zhn%0H8rh8$o zmp!J}89Zcf=RLq$7%5iz^_nv?<|>{<|F6U!FIJod`@8S4`Fdq9%?WbW1m&fgL*ty_ z?e%PUyL>LdUS2=%$v%=9v*7G)S~pp29s|4;YpceEyTN8ODD7h{`d?A6`WAlvXA&&# zcnmkEULWIXe~dFmqnoWicx-)H#@}!bU-^>L<=0-h(sY*Awxvey^Ce>qJe9*}U+1v1 zw%5B}M%yyRa^tgm4vb%M$iBv2_)B7M_1tIObg!|RShQgAh`q^M@?`KJ7guv%Gx(bx zL*|_Kec73(49;&${{jA9sy@zY!y6{Atd*{?cr#cVDS5lSaTVT1GWNpTV6O2uxEpP$ zdtLj6&tTlmGP*bC*j6k1Zo5@Iqb<*BYx!mByG-0o-?#a_rhC!6Bs6U>7Z$_Z%!o%%$z4{h5znv`u;WLE1y+C8v}xYt8Jh?|5H%AomE@e(1I*`j5YF zd-VSHV;?XreA~IFX%C%!Y~QbCx(91>VH<3pK|+^WlJ6kiy074EUUrVUzo33Ju*R9c zYkBwyXj7Og_HsY`T0D~Z@|0Ou$LGd=inBO$?hK0$;|xyrB0FaLx#fl1%(QdcVK8yI z3-mLieYpp(YkD^|u3{qKE37r%rl(-MRbS}a)V9W7V{h{qe2nw?zsl#`bt9coA1s{8 zP5Q;hrIpEEx3R{|jQv0b-SDKfE_Ztj`uRU-3 zvirLoi;cNxUpS239VS?ti9Ta5UW3Z8)?B2f}%~i?s*C{yK{SU-zmbv{&uR&S`rlYTuYg{_s2BBV7B`KJusE z+gT0lWBY?!ZKX2Jm+r#|G?Y6QQ-6h&D zho7785_~?ubJx3KW%>sb`gi0zpm8-ewQSYE#^u(Y{ZDqjbYo}gQt>s}O77*>W_*tJ z?CW`)*Ct~v502LI1eb%!8kZdAGr-E?p|LjWHpaQ?{oOcYZC4j3oxij-4i9*n+$A^m zCX4YR(vNVRTXnG7$KJ2axrwKYan`mxW6j*_RlD)n*=#!3Slrl~+_hYs9qZn@u6V@U z^c;+}U0-7@yv+n_JI;#9wT|wc!rjW+(7ky^Te8-2vDf*V`ZoMs*lWITW3TzX<~ub0 zI&-CK(Zpi0vlqSFaTwkPbB(j1Z->lH&msNY*rOM1o6H^Ocnqn1^|wvg6Q0A6xyjy| zCwDc@8SK1G9;0q_>MN%Qg` zzz4|rwYHCgbgvj|v0Z#F=vnM@AR~eHGPMr&LVKvXbjpDxW4)#|3;}P4x#84fw6Eg<=Aj&;?~nWHyh=W6h#lkn9`;J#WL3qW z8B069hVFGwA==YRU~DqhSdG8%@9`L5`mP&0Tb;kGb?NkLa+WsZv$SsXCujRS%ayZZ z?yjs}d7K>1oM#FC!rk5%HXbL3GtaejS#P;l^Ip75jd@!#Fe3wV`ueVw#Z z(74WBbZ_r9z};Z5m|_~Z_Z%vFdykiLB;&2eH=unhXW??sVz?W1W39?f_YRrMe4BX= z#5hn^@;E8V&Q{~EaaMJ5rQ|N38_cP3{^NnOH?!D;tB*Rk+#%og2bxR6%l+F=f2i|? z|E%-fAF(~cAHDA{zDM|1KVN?Q-glIbE53o)vK6~6(mgiUy`F39DA->(^{z2j9EHKg z{&?2edjH@vF}1{fu$K)#GhAi81B~5Vd+cP4Loyegj-R``Vki!ihrk&`uRii1^G7~; z<;Awo?zeBc-ZVRB6>(Pk`z|=sp7VU2S4r$K-Y@&=vTqsBX+E!U7tPz|*Szf7*7R-V zZEI^=KW!%u@@R3%`w%3fWgwR zXyC|A`v!xJ$>MU;!0zv&d427%>)iAn(sQ6M%Y9xMZ0vQux)tz^A*;rf4&RlPMeCBdSkb4j4-q5^g;F{8V z2>lChLkq)KIP6|88ke%TD_&HuVO%zrz!TOGJBLm0!dU8-tDjuS85~{%bur7@O#8y! z#$NmeXKgY!cniydzpiy#d)8C$T3xS!2Vy>hyn*GjHnMnJ_Uz*PVCK~R{F#rIhrV-< zop;F@WRL#k&&Bo#|K7LkoU(7f<9gpCTxYzWy30a~X&?rexU^jF1#3yXCZ7v@<}mNZ z*+Z-|CfWWE;=ivuX6>8Kh}W~37KXp(JrI}cS{MJ=y^&3|H~9kd6mB{DwDS4aU2d@# zzyHLC%Y9$`bh%Gn$e-@~sLt-WrF`|et99nYS>?4yAEGmrcd)%0cG3Q8_N;5T<|QUL zeO;ep3ym9kwlWyaYy5TgT3ng6bsq14y-&Ulc78f@(`#6o8rawif8j0M&2gE-(#Bom za*T0)`ZZZLmRDByeZkh`Zszb+DShAcAnbn0W6Q-<<1M~IrpDdmZF0EPV|_DBP5wrn zXBfd$XR>p)l{+mQy4Q4WaJTNo)3LYm*8E-f9cVMpcR~Z>1&7xl*5-Ng%(124kSuo1 z3yV|lX6{Tj_J-%%{08@W-TRgQYx8VyxM|(o%K_e|@0%>Ho^Nn9nVU@RxtsjWeH`*k zcwbM^V$8hWdkxOq^nZJgcR0T`^dD@lO`dP_d7Zff{=(i-YW{*VxbfEg-i+<-wXdH; zAzhn1hPlKwR0gXo?=-!J%wcY_4ZT=XXkGJpQ}?2UjqQrvl}E~c1n58ZK)-PL?&Zca zjx&w;)A!v{?*HOv%0u7&MtS(h-&6X&ahUjqpMBs~oi%)goi%*P0eh8W7S7Q*7NH^e z{vQ5ru8HG0;qA81^}}FvFsz2ZFxTeN z(7IwYYkQe5J9pWV^5&C|wtXCbs2I1ue*RPC!EfDd9<)90cfYAK+wUsG!128AIO{~k zChK_@%~j092Bw=~JaN3XCQiIG=4yV8e5ieWuB+H>Vh^(8gHJv-=?YItyL;F_lCVw+`4x83B4Xk?dR~%2@x9Qzp`=WV0S-*J)8uqhxH+M)8lQ-4Q(s7**;^&T{xVY*O~0!@l{@3To%i?o;Wf; z^HOUj=4??`Xie~Ijy%xTMtteoSLwXVca%ST>UQbJJMBz{Ki+vq`Kf$e&b>qz<4c^S zwZrV)z@9QN(aw0+Yp`xD`Obcm3!f)%OuXGoaRtQt9=gqz@@8k-_x>a1&n}0}-O}3k z6o+@#`aGVC=X1ZBXU3D(^J>2y&Xb3ouh2PIx1DpUVv1j1IEVegZ-3p+sC@L#f0RG+ zm-6@D{@Tu!xKBL(uJk$QTfSO9-ziHL%IEbneBe9223~`&QA^#Mdbjr-;3@o#KKP2S zOPg_a$lB@w8;_s7`8MODc)OeU!lvt zg{978Z=1&6oO82Wykv~WIyiex%T_HM-h()5-hydf+Jd!KcWpb4bEtKgJ5BS-_ibLU zbJo1w^dbHgcky=_)9c>kZ|3SV%?o$4tQ@vlY?*nzcn_mAU@ojp_BQXKvNn8%-ec(X zZsji;SFBF0%b4DOaDP{AVy$}&jkWGExZluoww=9(=MWx)u7{J&bD%7)8fzn0xoKWl z>-Cn?rg70t^U;MX5>sGYsQ8nv(A@OnG%{ku2cP`>dN{L)Ly zd(U5C^J(Yrv#VmY=4hX<4ecJRoA9;5{@T0--xpx$t{Z!-*WvTGve=22?6J7Kbf2ZB zu`k?jX?clahl#0R&++|cZmjX^>N@RHqyHz)OyhG34zst-vKbrMSwyT^<~+3T+en$C;I%)I1=5G<#0$ztv`@yYYB=PmH@_r|DeNyRLn! zz774`>dx9)hppnTY26WLpKSi_mRi*~2`gc6@H5#-TQXER{nU3;d(*>ljg1S2+kIjT zET>P`z{+GS*C#_;TVrju<(SOf+YN0T%x!(?G0@)_>^?=-GY_pBOg3K_zUrRFWGgox z!p{K><{EoPenT=hIGp~kc@XML9o)F<%=J09RO9$sCqZo4@Zvn?f7f)y`hJD?iy>w-^`Q2Xx&!E%XN0R*DL<2KiLa+ zo7Wp2FU+kmX3p8bJ!D~_J4 z{Y+jZ-}Z)6kJkR+rm`ocVV?HK*-VV|vxe~!@IkmgKa+7% zzQV4XtZUpj1$VuXPs1TT5+Q7|G=5+=V|VX*jvAEvRCWP^xhN4 zu!B70eS*7oM!VwPzW2@>+%wv_ z*|FDHoZO||%RXnvYbA4AUmHVT*GvvX^|6 zGTwo9*T9iW2Pbolwc@bpV7M$DYx))rN3s|OmD7K4-&fqVHs>zo0ejKE)pKBdaq`z$ zoLbjB2IFtAxaV%Kfx~}r4;UTnzHa8`GvGl~4J@xAS*zUE5gT(Ghm*UhbF1&0@x9Wz zrg^7mUGsIT#+{~hle?YQ5S$${7skf?8gp!xn&wT`W}f^_z1wneH|E*KF%GVO`}wtA z>-yZ<1aHy1RsV{ugL$^bVi=rrZ1|@bj}XzG(P>RmzVcmutGdOT>FymZcJZ3Ycq?tu>BeNztEf-`QLF;z_5As+kC%ru=l96(ep4QM@c#1H!w;GE#plK2{o!plTCB!vk2*wWw7cHj zalPm2nVZjG+zoGcIJcI5Z?G078*@7jhsHJEA+L-H{!>~8?Y~}+VCx0WadRW)N(;;)c%{fas zlGr(9Z>M`x4+nSCe{k-Om}?9U?!r~oQ|BgoowuoVHKuwE&RXMgoojOsBKMTc`8LZ< z>o(3-uUG9JbLO6JdJMLv0`87e#F@F*i_Q(Lo9q>9P4`yjCV%mHUE>;$;c$2lRrgvO z?cq1n9N$5DHrP9rzwlU$>GiMq4HoB++;t|W=a7sw-`6;t+=abL;#Tz+RIYKolq03a z_4tPL9NfpX`8H|8-fQsn!OXg))<^W7Q- z<7@ED#x${)eRY@3(D@8oZ&8lec9!vtJs8*%@&xJIqr_XzzGN;AoeOjMP65AWnXjwY zmR3hc^8E{EG>&i#Gc>BlRU;R>5OyI=8b4{5E(-+uWsi^F*M zCqJ+L$Tqg~1a{ zP6l^Au(4NTTiiqX41KP0$KGk{-MCMUeF(lLdwsoydl3DZ$Hv<59n1p`PuSVpH1BXN zvHQGs##`mD`wyvklfUK#gudCBfFnVe#1G zH6Fv=U@tu9GlKXA;<|Ry?-c$j>u*^@yr0fv+?Sl6 zXTD+*I5QKk7H(gD*naXXPPaL^U)}y*)1aK8jz)b@F%vNJ*E;7HKl!~EoK^4;@O$^y zYjdtKF}uWlF?UDo1N*V#7hL_KgUbgldWl`feVGG%;Ok$m`$_!%6CYA6@0-iVF1t{B ztQ{c_Wl1@F-YkoWKu7bLW*!6cYT{>$W0+PB_NLxV-p1UTa}=+^{e~fHpF9tuXX$^Y zoV-oG_H0e2X5Pl4UppObymjXK_1^Cq+RMJK!}YK+7H%7VJ3g<3$L2#AYh5dwuBD#( z)^zZQyJ~AXI2apkJ_naxLm$`B+R|$R^8t33FHcukj zlDV#ZUH4jB@-}>k^c+m@248DTFZF0!)ahQEZ!?|Sv~P_q!*3uNhhZ<}#$aP@=wNj3 zcrCHVl)+sw7rhH_#pBA`Q5}ujYhGh;jqUAxhV*yI(Y7l~(t62W*SOPt2fl~XZ~j8& zVwC#~%(;ceC5O3vuCnP~am_pi%VWMxo~rXUx$CTL%nkNNEQ9OdXZRdj=wI%gb64nB z_VU7e;QWc5G*8Uj8)yHphX;MGarMl)ZdROKOsp5LiN0U34s&VGx4k7_thEhqJmCnN z*ZR?WZZhUREL}=GFzb*X`Q5KA_Ui$yk^8CQZSTD574mzJDrfJt*w#jH*6~7KQ+gNn z;x(YRk6JjpT%dKp*XiEq=r3RU>hk?t-&%hDf!j>~{z&WY;5hqNzV*~&3u}l^*lC`v zS!2E1HfyhL?}6{rAk7-wP5wHAJ8cVR(Y(Q1i)-j~aL--FQGc>M23`Z+k#^sB9py@! zq|T+DeadTl_D9>4_GD{bZ*y?y-QXn`MtX3-($JT5{J}n!ba_J22PQ&BKYS?&~VIxU-BsOAg1JTgE(?=OC_D9?O5A zZIr6VD-BE87;Kz%zrneSz9qGD+?==R^ZHyGZNu0y_juE9a1O6t&n#~9YR+0)+or#t z)VF;OYpM5Ix0d_4HnBB5hH;+0uf>?b-lohL+3Z>dprK7dk**tu$DG2H@_iSJJh<3zv1!1+;JRl@OPkj#XR>KTz5KOLx&n) zy^J4VT9=&m(7xzo?uTBTtMA`p+yZgIUwp%rw#V6n_ug&HeeA&pY%QG4e~G>5-rs-n!={Pfapp;ib=bqMC%%{a z;Y0J;x1DtM62+R~FEaP??1HP^!PHSAB>UE>`ZcOE9*VY)U>%_#ItFxGis)y0Gsc$n!!}jfy{%>V( z^&Mi2)qB=99`{UJ2}T@T3CIRxs>5;UPV=VTO|O@F&be(P&bs#? zz8ZJo?6B`^KDHYGC&zCb^8? z0Gq4-pmOS9f)z{u*~HkI}y3Zg6%m=hm^;^l-5D|EKLudN)0;v%lw4Sc5flY?7iVaURu8 zHfK^KC2?w!qBu#iESi!?$%45r86 z+TQTD{of6Dhp!;kmiD#oE&l;*wZ8zyg411BM*gOzH@erkjn7-mmG%W+y|-qK+dl8s zZ;4n!eE-K^U4`Doxn!R6<+%*$UGSRqygZ*q zz03cb`9EV^qsD)O_lvy>-}&8#@6#S2??(H3yg$f$8-9g8eT5%Ba(~rc;9U&t(XF>D z@t+&gy35T3-4IUldV95#C^hc&H- z%~I7t;CI5_*1oPoi}$O1_$$sv`%XPP+1q`34&H~O|FGw8>)pj%`3tRg#ac4B{M{9c z!S)zR2a~&GvG_ZAyYm^u-0;>OgLoSjpS9<uJ@Iu|T;%$^(A zEA4CMs!s-s!_()bpUW1XA$m7{@0PdHxzxH??|!p(@|OJ`7jMO0^Eb>=l-@0!Tb!l7 z6?hVu*FS=K2JXf2-S>~4y{Pvv|CitX7rLY7KmG6j ztIjzb)ieAb|C`SIc0I#mdfWI}c)7lB2lq?jZ{U3m^f*|r#`-nZRPbFN)|m0%(Y(>SD{{?$ z0C&N#W~+H94}ok{8(MhrG&yTxt`ke^n`mfh;QT(h%D!5$SUK}LJPvmgqkXAolgs{` zG%kL_9FFHuW2~o^jmHqyI&SConm1!}*ZQ{m$8CW}nTm{N37LJIUO5ykNAwU48@3s^-jIFPR(PSAH+qTeS`GdsEx{Wa(UM zV6!>CgS9W2Ywo6&mtKP#{f5%NSQGwQ`$qSAe=WN9O3|z}Z{s&e^Rli?-h#Dm`bXTw z8fs#Cyo%wj*jqYRx#loA)#ure7hl8P@YZ^l?6v1g_HOyRxJ%E0Z86v54R_@wSnHCv zTjoN$mIe-Y9ZU0)zhIYgjMeVr{WbWGXVxyTewSw)u(!rKT;5^x-+%A})gAobRlm!+ zTGj6&^4^D4zxy-P@4oUJYIIS*i~DOH2T$o4^Y7<>7U<4&-hqyPS2_H9yjPNE+Q?Tn z?*B1zf73eIcd_%mVBWb)&fZykJ&U=Mx6NELmSZ<-S^K!i4V^1}n{|u5e?FZX-y-@o z?A3U~Tr$>8JPnJ*;P5v*WpvJ(*19)L)xROulG9jM+%>m39_zDi#4xze!;!V-v3-VS zuK0>?H*s)ye~++Oi}^5@k*rO$-&>sBb2mCS5sVdo$9U=D?7NA>)VyS{b*}s6JH&gy zeCyqKzK-&M!P4kldb!lXj^VN6#`l%}MV=bB>doXSMDs@PVr=GutzdBW*A|E4Gth&8 z29DpbiP&RP9WS|y_3jU!0qhlXS=Wm-tI=<$=6$yI7`&He&XUQ^-P!kE+rGYmT$S&j z|M%V=uf1OGsbN0cEx#eY0&5yn#|w^1_c9`9<{ssWa^9J>J1gc(i2fkH6NSLTsImyDW;B`#?;UL*1EMAi(J-AA5%N)H+FIGcj;bo zm5uC0OW!e`Z}RjctbfVk4QJ07FTa8FV5s)o5T$+h>;*gJL9otDeRA75*EsAnFSu&& zA==ktvNUxN?e~szZKz`qhrw6#nBGIRBkz}Ntwukh7)w2C&$qcNja!^udRLk^y4OB$ z{9Wl=@z%_Z&(O?`=C#h%-8rRi#a{L`4ukDAQ2&a(WUltsFh<{+xA)i9z8XA+W-mS7 z*1f86pwE!{2C>%l4A#E%9L!$xxIKr(-Y}SarN))cE#8W`t$R=Hu~Fw*?@n*m92RTI zRkY2W=#|^v&%5O=nHvt1v#oupZ_Qw9+x8vgGhi-Sm-EYOK%W2Ez#26EcYoGxeINHB zeDDPBXMm37nTY@4=YMthpKw3J|NIXhsn&t-#{W0S=Y9s>#jd+?s*ZtwhwnlUKmFdC z?nQ@Ja3}6amk!1~3p{@|-*e;M8GT%P3udj~5iaJ2wS%`|uee*9l{s@ZTrC!d!R0TA zxutK}|Bqnp{LKwB$;C}8Rz~C2oH=b?r+@q%zqS6g2jSn24vxOIh7NnV-rvb1z6@(8 zd()4Hz_Hk?NZ!tIdkn4#K7+y3y3xDht~r|eU+dq>6^nD9`r<9QTRdL%Wujp$Dq1i`nuM+@^|Ai z#A_gX(dU0BceMAr@g0h<$GSJ(LVSfSdlz@3cd3o>Tl{zI^YZ_{Un_>bfw$s+^ymZd zdmlag26bQm{MvU8zsH@w|BSkY-{3y7U*de)k1sx``yj(ydbjuEe>eKe<|-M>ws%^STtJ%(Ms&av@)@$`DBZKZX^TxebL zm+V#CY2T%FsdtOH(z^B?QpdY$9mv-Wb2Bz`m$y4udrI$$yS;yJI{FD_Z8m1 z``{gVi;^{ByzhbWy$koE{@@P1!Oq$P)`+oQfp@4|>-L*JJl87?8}=rGrR3+*wbHp& zpIdX`Zu<(D2P1F)Tx!VLW1!bCd7HlZ8toefGrG}hn0j=>U+Q44`!o8z_-pQd8)Nb|YZ7NpJTBh4 zAJ2gtF3pSIAd}#?4u-SQzwsBu-DqCK9+%fZu7a~< zAo=V1hUTt)h~e{c-wW&LZ?FbKH3#r%seQ@cZ=<%C=h=A2&3DmwZ#rucI8Q&9|99d4 zPW;aR>0J7=dULI{?$W&EaPig=o&uQ5w|k;-Q>Sb0lC7nArGc$mt$PP|<0}mQHhYV= zT4RoCZ*7iOpV~Jp?s|sKW$u&3#awWb%zg3pa}~k6m8&_;o5A5TIqB~zKR6!7p2g;E z-rAVV^xj-?7rz&8!aOx=H`;e`xY--#%6llDinr`*Z0(!7*B4`#7B2o4lgU@ImW&OT zJvMv$ym9u_SaasOvz#qHVlntjjXS-D=b~*Fcf(ajv3RkTIqP1r7Wq|UhW!2vari5} z3-7?pjnCk?_S(SC_`HeDU20zZzsKn{h_}|dVlKuVdrz%v8cO??$Gi5^%HP#Jz17$K z4PdG7E}PtSU%Hn%S1r0XdYArg*ENK@;;=OE-s3fYb!Ir4cdvWF%y8HY24At3d`+!c zSZi%d{%*DIUh~T1EpH)xou6Qi>|JLm$XByiy0&z#G%pzINXCY<E2F&sZjYC|wXYENroOE8Z+Q(j zgRSNJlEG@xxAGXMb6f8&%`2^2-mdo6TKDP=crbYS4fb{8FJKOO)(kEdi?8h4*NygF z-Yz`f)H%dwSa&tZi)hVje;1wunM{vC`)$qJz0U1%)t1R)h}U4vORdYAhNXX_dl|`C zaujZZNp&t2+_le;4fqQyPv9kw65Vb zpRHf*E3jXl!|)KKeWP*3;98g5pD{|Sf}byeY3VN(i?hYzV(exOzsYxqi@)JeQdjxkzUHtkjheyyZ zs*m?tYy8O9*}rmo7;BE&ZOEZrz}yAK)owz6w6AfF<6499`LEq{c=%S-AwgGdIc&X~ zd&}ltTf7GO4MX=n45pvQJ=qW4dQR<|6*E4LH)35HzhVE};lZ!ocy;ZT8xId$rrm$b z4Vu4SYi>Aj>~`a}e>3u%cKvRA!{I*6-*@x%)n-4r>ks#0o-OM#zV{~Q@2SYK`W5fF z>AD(UH-3YED}U?w-^%y*oWpl$caO;a72A#19qvNAo9*1STF-HE={sJl{GB&md$?0; zICgW6`Pr_i@im7#aF^Nb;J)>5`3&+E%vb7I`3O@BlfQpP-sZPnDi)fj_85{=T=T7k zSN@K3ht&^TXJj9~g%~@SOI9yNqyLPUOMZr->0fSqf~#V4^7*z{yP5MEGFXjl9jpy= zlM8#p-?N!Zwvx$aZ2IKu<6$blllfS z_sXm_lbgY2?L%KRZyy44*{;Z5u=GJTuC4yr3=VG@Cv$h>#a{4E%rp1Mi^JlsnL7E(-y>JaQuFn?;^@pL zH+jo`n45gDcW_l27wq-}Q>ao^Y2duvaLw|EESTaO$*c7lk{l8({%wBjA3nT~IY;*0eu8^Eeu6%uavZOA0sS=G{m=f>7Zln5YxFtK zsPQxBtIxG)$upw;xZ3Rh`04Y?{}p1lUi(-0hIxMLe$73FF&pwfVteX58slhBGUxU~ z^pDz8-$c&s2Z*aZ@y)|~93!T2%(Y%~e#Q5=7WY$eo{>DJ?p=D9KCiro(!4kBd#_FD*)Dqgy+Ac?mxWF{%Efu_u9h`pdlik{w0o;yZ@km)*)WPI_56nJNEgF$6l-ch5HY$ zs@->Z6>DF;z=)PyBIl~T!W{aqWSofnEBv;;=ek$$ducC^K65XhN5dLL^__bOeKzJ_ zI)88R`r6XFb6PtX`!~q3%{A=zZ#J97+i-WWw-{WE z&F}pU#^P|eOUAMld*6Q+{A6GGaJC}nkQZMO|N7~{(=Zp@Gj~1rW9GSb#p-h%8W}1k zS3f)^gUL~k&06!;{U6nQ`1@C2>gv~AI6EVG%kdA{!r$2kGk*YPim8mNU;M>4KUj_I z^&0cGn2X;ad&yk3{a)LnW8(BNre*R6&ZI~PWf|q12nYy3<-o^fgEEadcTlW#cR<<`5d(B*OS8cKvxp0`Q zd|fPUzKX%jk*nk@xX0G{&Sj44GA|C-Hi@1Yp)?& zxju}Y95#E&UvrkRnd`p&hig`y+0wT18qDA6HITz+@hyJACyi!pxEr0DadXnFZC@dO z&v(E3-NU=@zI*uTPk(y&;DZkiZ@>Na;rZvEUw^N3E;(CGK5}t4Y!-KMru&2EijRn9 zWpQ(aKx-($w|yEDGUZ;R3RcEe$g$y)K4%nf6ycg^NzZssn4yXJ2=YpokS zJa|lQimAwj!^kb|n|`ecV<(H7wc%_c7+XC3F|_Mh>zcQ%gQNEUp&ja;(1Ndn*t2mhL@I&$qa1pMg4;HNE7n_uIr@j+HZynVYS-YmFPt zn<)Jo4J_`GxzW1j?pxHYgSBDs%8|QRqjlu8I9xHDt?$X$a5Q~!S1iRGH89t#b)zp% zley5irF+fZFqo10xAbiy*$Y;Rx#&ydCPw#?o#bg4x{J)@;9 z+b8Gl^bo+^J6qdI-XrcQ4vwU|-{A?_R@31Ft-INakAaw(i|? zc&#tylC8{zyYBn@aM!GD{!;sHJO}C7;xGDPa`V@EH=5U8!_c$gFe94uZgONV*z9ko z&V6{ZE`EdbEx8H(8vfc(C?8_5xY=vnOOJs$c@2ph{+{+6egMCLT9*u#<_%9Vo_@o7 zPd-%K4Wq4f$>(?t7r5Uxdmo}8V1YTxtN6QjRtpMiSU?d|d%-T@=y zJ+$8t?pn(-Z*QTZxO|50C12NiXjyWYIW+M#kqoWAIE-=TIbMCNnGAk|V}1*!lCNU0 z`rs}3O4im~bZ&bLVXygWkD>bDTR56Xc1}M*eev3So$DrV!&>H+$AEsA8s;`{&EOuJ z(c!G)B|5=TF<~aAuU;a`W_|m0IVlRJRensitRVR!*xl7GUK8m$s zZt<77YUE)Uy7e16zdQzN(&;&@ap%d-J%bm2xnAECkHn<+-h;SnrZQ&+?^%pII2+wd&1>Cj_GaIWS~nhV-ou>UgE%V= zZ*^|!8D=%(aWR*y#qZ18MHFv2exw;3ovTRplEX(W%tb7QlArVq;^AtX9O7hZSgZA# zv(HOrW?l2Mcsg{fmfyVK3*XVZ-0Bl{xiKNAIl_Z?P`CP5j}L@Eye6-d7`o?K?PztF3>*TJbi_^*ZU{ zp^K$=;WdQ0WNkCJb#Hu!sdLq5Z3FbKxQo3t^7Wl3(3ajMe}}(I7K6LdyxMz{t}PFt zG^`j5-mSeg_BHmpaM>(o&YCwI-9&O1e0($BLUEXD$kq72Vy)H{cQF?~fsA#Zxzf5v ztZn|1we2}r&&GcUH^bI7CX>NL=i>vDw`t96dc0h_VJ~tT7jM@dTJdwRe)gH=4WZ zGl#kw{9V8P^{)@V``zyj|N5{0x;RVb@_$bKZS)=9fB*fZd0i)LuVMMS)VpXueeUAn zXW!cC-1rUh9EzRQ7bnpVFPqW!Cd5tgHEYacGnctj9!5CpZ=|0WXE7HJOVe`P-a~Y7 zm}`w2Zx`AaY)st){fCWqE&aNwb)dEd^A?Zw&EPKP$l&N!u1$X*gqRvVlRs~4B++vwV@77lN%bzgzcyJ{KO$M0|U*)(o{H}3$g zGZgR^Si>;+_NPDnX~VNQW}l7Pa`Nrta5wt)R1A|D`8U1x+H2Ce|MqYHw*Dp)*ZsqQoS+ogFq$KMr$!P@$Uj17Bx@6G-L*}Aka`erWo-lpe}J{dY1 znJTV!bd5teJh-iWx#n-QZ`dncTbyNXGB|#&@|>$?e;3{azXMy-!rP^L7k{aH&1Cb| zEOuQ3SUc()j`eS`7;ES^O&PovKOws9=>%4;xd!`0;N^V(BbbNE*M(!8m-F+R^l6J*kUSKyJ0l*X~k>m*$s0sZx)-c+Ec?C$FsfPsduN(z&C*C?e6(D zIZLi(oS596Z&%A+a!`B)TaV(HaDSHXMfEyO`{6?KMREBI4U{cJ`;I>)HnIpNXgSO=`>Xz1a&L3tzXH z&2ekqjSms_io5m@%wYD-V|fl?FV

w)V9r!SOfOnKr*wF+B$B-sSOvxzxJrt{gCV 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⋐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 F{{d_4lH33Q literal 0 HcmV?d00001 diff --git a/plugins/pad/PADwin/Src/interface.c b/plugins/pad/PADwin/Src/interface.c new file mode 100644 index 0000000..d011ef3 --- /dev/null +++ b/plugins/pad/PADwin/Src/interface.c @@ -0,0 +1,483 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *hbox1; + GSList *hbox1_group = NULL; + GtkWidget *radiobutton1; + GtkWidget *radiobutton2; + GtkWidget *fixed2; + GtkWidget *Key6; + GtkWidget *Key2; + GtkWidget *Key9; + GtkWidget *Key1; + GtkWidget *Key10; + GtkWidget *Key3; + GtkWidget *Key4; + GtkWidget *Key7; + GtkWidget *Key5; + GtkWidget *Key0; + GtkWidget *Key12; + GtkWidget *Key15; + GtkWidget *Key13; + GtkWidget *Key14; + GtkWidget *Key11; + GtkWidget *Key8; + GtkWidget *Key16; + GtkWidget *Key19; + GtkWidget *Key21; + GtkWidget *Key17; + GtkWidget *Key18; + GtkWidget *Key22; + GtkWidget *Key20; + GtkWidget *Key23; + GtkWidget *vbox3; + GtkWidget *GtkCheckButton_Analog; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "PADconfig"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0); + + radiobutton1 = gtk_radio_button_new_with_label (hbox1_group, "Pad1"); + hbox1_group = gtk_radio_button_group (GTK_RADIO_BUTTON (radiobutton1)); + gtk_widget_ref (radiobutton1); + gtk_object_set_data_full (GTK_OBJECT (Config), "radiobutton1", radiobutton1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (radiobutton1); + gtk_box_pack_start (GTK_BOX (hbox1), radiobutton1, TRUE, FALSE, 0); + + radiobutton2 = gtk_radio_button_new_with_label (hbox1_group, "Pad2"); + hbox1_group = gtk_radio_button_group (GTK_RADIO_BUTTON (radiobutton2)); + gtk_widget_ref (radiobutton2); + gtk_object_set_data_full (GTK_OBJECT (Config), "radiobutton2", radiobutton2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (radiobutton2); + gtk_box_pack_start (GTK_BOX (hbox1), radiobutton2, TRUE, FALSE, 0); + + fixed2 = gtk_fixed_new (); + gtk_widget_ref (fixed2); + gtk_object_set_data_full (GTK_OBJECT (Config), "fixed2", fixed2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (fixed2); + gtk_box_pack_start (GTK_BOX (vbox1), fixed2, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (fixed2), 5); + + Key6 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key6); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key6", Key6, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key6); + gtk_fixed_put (GTK_FIXED (fixed2), Key6, 48, 136); + gtk_widget_set_uposition (Key6, 48, 136); + gtk_widget_set_usize (Key6, 65, 22); + + Key2 = gtk_button_new_with_label ("button7"); + gtk_widget_ref (Key2); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key2", Key2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key2); + gtk_fixed_put (GTK_FIXED (fixed2), Key2, 48, 40); + gtk_widget_set_uposition (Key2, 48, 40); + gtk_widget_set_usize (Key2, 65, 22); + + Key9 = gtk_button_new_with_label ("button8"); + gtk_widget_ref (Key9); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key9", Key9, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key9); + gtk_fixed_put (GTK_FIXED (fixed2), Key9, 88, 8); + gtk_widget_set_uposition (Key9, 88, 8); + gtk_widget_set_usize (Key9, 65, 22); + + Key1 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key1); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key1", Key1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key1); + gtk_fixed_put (GTK_FIXED (fixed2), Key1, 168, 8); + gtk_widget_set_uposition (Key1, 168, 8); + gtk_widget_set_usize (Key1, 65, 22); + + Key10 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key10); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key10", Key10, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key10); + gtk_fixed_put (GTK_FIXED (fixed2), Key10, 248, 8); + gtk_widget_set_uposition (Key10, 248, 8); + gtk_widget_set_usize (Key10, 65, 22); + + Key3 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key3); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key3", Key3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key3); + gtk_fixed_put (GTK_FIXED (fixed2), Key3, 208, 40); + gtk_widget_set_uposition (Key3, 208, 40); + gtk_widget_set_usize (Key3, 65, 22); + + Key4 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key4); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key4", Key4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key4); + gtk_fixed_put (GTK_FIXED (fixed2), Key4, 48, 72); + gtk_widget_set_uposition (Key4, 48, 72); + gtk_widget_set_usize (Key4, 65, 22); + + Key7 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key7); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key7", Key7, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key7); + gtk_fixed_put (GTK_FIXED (fixed2), Key7, 8, 104); + gtk_widget_set_uposition (Key7, 8, 104); + gtk_widget_set_usize (Key7, 65, 22); + + Key5 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key5); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key5", Key5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key5); + gtk_fixed_put (GTK_FIXED (fixed2), Key5, 88, 104); + gtk_widget_set_uposition (Key5, 88, 104); + gtk_widget_set_usize (Key5, 65, 22); + + Key0 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key0); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key0", Key0, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key0); + gtk_fixed_put (GTK_FIXED (fixed2), Key0, 8, 8); + gtk_widget_set_uposition (Key0, 8, 8); + gtk_widget_set_usize (Key0, 65, 22); + + Key12 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key12); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key12", Key12, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key12); + gtk_fixed_put (GTK_FIXED (fixed2), Key12, 208, 72); + gtk_widget_set_uposition (Key12, 208, 72); + gtk_widget_set_usize (Key12, 65, 22); + + Key15 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key15); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key15", Key15, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key15); + gtk_fixed_put (GTK_FIXED (fixed2), Key15, 168, 104); + gtk_widget_set_uposition (Key15, 168, 104); + gtk_widget_set_usize (Key15, 65, 22); + + Key13 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key13); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key13", Key13, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key13); + gtk_fixed_put (GTK_FIXED (fixed2), Key13, 248, 104); + gtk_widget_set_uposition (Key13, 248, 104); + gtk_widget_set_usize (Key13, 65, 22); + + Key14 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key14); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key14", Key14, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key14); + gtk_fixed_put (GTK_FIXED (fixed2), Key14, 208, 136); + gtk_widget_set_uposition (Key14, 208, 136); + gtk_widget_set_usize (Key14, 65, 22); + + Key11 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key11); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key11", Key11, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key11); + gtk_fixed_put (GTK_FIXED (fixed2), Key11, 80, 168); + gtk_widget_set_uposition (Key11, 80, 168); + gtk_widget_set_usize (Key11, 65, 22); + + Key8 = gtk_button_new_with_label ("button5"); + gtk_widget_ref (Key8); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key8", Key8, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key8); + gtk_fixed_put (GTK_FIXED (fixed2), Key8, 176, 168); + gtk_widget_set_uposition (Key8, 176, 168); + gtk_widget_set_usize (Key8, 65, 22); + + Key16 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key16); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key16", Key16, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key16); + gtk_fixed_put (GTK_FIXED (fixed2), Key16, 360, 8); + gtk_widget_set_uposition (Key16, 360, 8); + gtk_widget_set_usize (Key16, 65, 22); + + Key19 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key19); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key19", Key19, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key19); + gtk_fixed_put (GTK_FIXED (fixed2), Key19, 320, 40); + gtk_widget_set_uposition (Key19, 320, 40); + gtk_widget_set_usize (Key19, 65, 22); + + Key21 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key21); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key21", Key21, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key21); + gtk_fixed_put (GTK_FIXED (fixed2), Key21, 400, 136); + gtk_widget_set_uposition (Key21, 400, 136); + gtk_widget_set_usize (Key21, 65, 22); + + Key17 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key17); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key17", Key17, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key17); + gtk_fixed_put (GTK_FIXED (fixed2), Key17, 400, 40); + gtk_widget_set_uposition (Key17, 400, 40); + gtk_widget_set_usize (Key17, 65, 22); + + Key18 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key18); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key18", Key18, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key18); + gtk_fixed_put (GTK_FIXED (fixed2), Key18, 360, 72); + gtk_widget_set_uposition (Key18, 360, 72); + gtk_widget_set_usize (Key18, 65, 22); + + Key22 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key22); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key22", Key22, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key22); + gtk_fixed_put (GTK_FIXED (fixed2), Key22, 360, 168); + gtk_widget_set_uposition (Key22, 360, 168); + gtk_widget_set_usize (Key22, 65, 22); + + Key20 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key20); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key20", Key20, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key20); + gtk_fixed_put (GTK_FIXED (fixed2), Key20, 360, 104); + gtk_widget_set_uposition (Key20, 360, 104); + gtk_widget_set_usize (Key20, 65, 22); + + Key23 = gtk_button_new_with_label ("button4"); + gtk_widget_ref (Key23); + gtk_object_set_data_full (GTK_OBJECT (Config), "Key23", Key23, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (Key23); + gtk_fixed_put (GTK_FIXED (fixed2), Key23, 320, 136); + gtk_widget_set_uposition (Key23, 320, 136); + gtk_widget_set_usize (Key23, 65, 22); + + vbox3 = gtk_vbox_new (FALSE, 0); + gtk_widget_ref (vbox3); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox3", vbox3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox3); + gtk_box_pack_start (GTK_BOX (vbox1), vbox3, TRUE, TRUE, 0); + + GtkCheckButton_Analog = gtk_check_button_new_with_label ("Analog Support"); + gtk_widget_ref (GtkCheckButton_Analog); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCheckButton_Analog", GtkCheckButton_Analog, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCheckButton_Analog); + gtk_box_pack_start (GTK_BOX (vbox3), GtkCheckButton_Analog, FALSE, FALSE, 0); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (radiobutton1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Pad1), + NULL); + gtk_signal_connect (GTK_OBJECT (radiobutton2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Pad2), + NULL); + gtk_signal_connect (GTK_OBJECT (Key6), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key9), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key10), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key3), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key4), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key7), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key5), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key0), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key12), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key15), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key13), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key14), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key11), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (Key8), "clicked", + GTK_SIGNAL_FUNC (OnConf_Key), + NULL); + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label1; + GtkWidget *label2; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "PADabout"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + gtk_window_set_modal (GTK_WINDOW (About), TRUE); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label1 = gtk_label_new ("PADwin Plugin"); + gtk_widget_ref (label1); + gtk_object_set_data_full (GTK_OBJECT (About), "label1", label1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label1); + gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0); + + label2 = gtk_label_new ("Authors:\nlinuzappz \nflorin sasu "); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/pad/PADwin/Src/interface.h b/plugins/pad/PADwin/Src/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/pad/PADwin/Src/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/pad/PADwin/Src/mingw/Makefile.win b/plugins/pad/PADwin/Src/mingw/Makefile.win new file mode 100644 index 0000000..8b5d68c --- /dev/null +++ b/plugins/pad/PADwin/Src/mingw/Makefile.win @@ -0,0 +1,43 @@ +# Project: PADwinKeyb +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//PADwinKeyb_private.res +OBJ = Obj//Win32.o Obj//Conf.o Obj//PAD.o $(RES) +LINKOBJ = Obj//Win32.o Obj//Conf.o Obj//PAD.o $(RES) +LIBS = -L"C:/Develop/Dev-Cpp/lib" --def ../plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +INCS = -I"C:/Develop/Dev-Cpp/include" -I"../" +CXXINCS = -I"C:/Develop/Dev-Cpp/include" -I"../" +BIN = PADwin.dll +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32__ +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before PADwin.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=libPADwin.def +STATICLIB=libPADwin.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +Obj//Win32.o: ../Win32.c + $(CC) -c ../Win32.c -o Obj//Win32.o $(CFLAGS) + +Obj//Conf.o: ../Conf.c + $(CC) -c ../Conf.c -o Obj//Conf.o $(CFLAGS) + +Obj//PAD.o: ../PAD.c + $(CC) -c ../PAD.c -o Obj//PAD.o $(CFLAGS) + +Obj//PADwinKeyb_private.res: PADwinKeyb_private.rc ../PADwnKeyb.rc + $(WINDRES) -i PADwinKeyb_private.rc --input-format=rc -o Obj//PADwinKeyb_private.res -O coff --include-dir ../ --include-dir ../mingw diff --git a/plugins/pad/PADwin/Src/mingw/PADwinKeyb.dev b/plugins/pad/PADwin/Src/mingw/PADwinKeyb.dev new file mode 100644 index 0000000..9aa2d71 --- /dev/null +++ b/plugins/pad/PADwin/Src/mingw/PADwinKeyb.dev @@ -0,0 +1,156 @@ +[Project] +FileName=PADwinKeyb.dev +Name=PADwinKeyb +UnitCount=11 +Type=3 +Ver=1 +ObjFiles= +Includes=../ +Libs= +PrivateResource=PADwinKeyb_private.rc +ResourceIncludes=../;..\mingw +MakeIncludes= +Compiler=-Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32___@@__@@_ +CppCompiler=_@@_ +Linker=--def ../plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32_@@_ _@@_ +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput=Obj/ +OverrideOutput=1 +OverrideOutputName=PADwin.dll +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=..\Win32.c +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\Conf.c +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\PAD.c +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\PAD.h +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\PADwnKeyb.rc +Folder=PADwinKeyb +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\PS2Edefs.h +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\PS2Etypes.h +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\resource.h +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit9] +FileName=..\ps2pad.bmp +Folder=PADwinKeyb +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\plugin.def +Folder=PADwinKeyb +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=afxres.h +CompileCpp=0 +Folder=PADwinKeyb +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/plugins/pad/PADwin/Src/mingw/PADwinKeyb.layout b/plugins/pad/PADwin/Src/mingw/PADwinKeyb.layout new file mode 100644 index 0000000..44f2cb5 --- /dev/null +++ b/plugins/pad/PADwin/Src/mingw/PADwinKeyb.layout @@ -0,0 +1,56 @@ +[Editor_10] +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editor_0] +CursorCol=1 +CursorRow=20 +TopLine=20 +LeftChar=1 +Open=0 +Top=0 +[Editor_2] +CursorCol=1 +CursorRow=1 +TopLine=136 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Order= +Focused=10 +[Editor_1] +Open=0 +Top=0 +[Editor_3] +Open=0 +Top=0 +[Editor_4] +Open=0 +Top=0 +CursorCol=1 +CursorRow=10 +TopLine=1 +LeftChar=1 +[Editor_5] +Open=0 +Top=0 +[Editor_6] +Open=0 +Top=0 +[Editor_7] +Open=0 +Top=0 +[Editor_8] +Open=0 +Top=0 +[Editor_9] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 diff --git a/plugins/pad/PADwin/Src/mingw/afxres.h b/plugins/pad/PADwin/Src/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/pad/PADwin/Src/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/pad/PADwin/Src/plugin.def b/plugins/pad/PADwin/Src/plugin.def new file mode 100644 index 0000000..c7c47c8 --- /dev/null +++ b/plugins/pad/PADwin/Src/plugin.def @@ -0,0 +1,17 @@ +EXPORTS + PADabout = PADabout@0 @6 + PADclose = PADclose@0 @7 + PADconfigure = PADconfigure@0 @8 + PADinit = PADinit@4 @9 + PADkeyEvent = PADkeyEvent@0 @10 + PADopen = PADopen@4 @11 + PADpoll = PADpoll@4 @12 + PADquery = PADquery@0 @13 + PADsetMode @14 + PADshutdown = PADshutdown@0 @15 + PADstartPoll = PADstartPoll@4 @16 + PADtest = PADtest@0 @17 + PADwndProc = PADwndProc@16 @18 + PS2EgetLibName = PS2EgetLibName@0 @20 + PS2EgetLibType = PS2EgetLibType@0 @21 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @22 diff --git a/plugins/pad/PADwin/Src/ps2pad.bmp b/plugins/pad/PADwin/Src/ps2pad.bmp new file mode 100644 index 0000000000000000000000000000000000000000..26d304da4e26ef55223072c46fb5941dd00ada3e GIT binary patch literal 320918 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 z zosC@-G||2EKwAstz^px z1i`4$!r`T$zv$(~GoG!B3x0e5isLJicGu;c@7eW-{U3dI=F2}E`SQ0D-+X@XuU{Vg z@~y!$+jDDn7YFZdjB3tuFxP%wRrzT&&A=c>V|gm1);A~9o|#aWloIAk!Li*!a+DFc zb$8JJaq;5Gv;92SapuUrt|X@~&Trb^ky4*zU7cWE9bqP7F0^8a)X((S$_q7S35oJ; zyG8VT3$vL|afiscq{`D;(HC7jD<#~SSQE44o^r8VoaAes6KI>^XP4w{ofc@587fA4 zpalcpD%yD#s;`)-PPNxla@3yzcCc>I<4{w0+EnF*k&5`cBTG+rWFKfw-clJtBe=py zQxnZsRAxVIy+qm8NLk!B4CT#?=PX$8JU;wzAG3-y|Nita#;UByb@?&W@(vcqZmdWg ztxoAE3{CMf#j;(XG6l6LYl>F1r&*ZIu{ENsZZ_qlCamkX%SoT(n8K7$y=KNg~{;OFNn5IM`+$lyE)y1 z1h7kc`d;1IabwT2$2SjtcxH1$5@q1|uMRgKSW|Iuu%@>t7=;mH>e&H$nJi-}_xyF} zmI8bL3aQ?@&syC)iZ;6?4@YX6mywwB?kR$jQk~aWYh!SXK65Z2hf~ z)-#>i_|9MLN;%!0c&a`1SX&yBwCDQs&aTWGt&8SIU|FIbYNoCz34)>tYKE^=rclfM z1Ft7wA>@HZysgH=01mjnB<$Jgv3o( z$oV5VueIPA7oAz#>eK#keE8Q}+o_ZTvW(MRN#jj1)xl;qYUJ=dgY=7?NGG4h z|7~fq0KE^AtmJ0>V(RSYr18qEXJ489%=Ed>&ro_^PVqUa_2()4QeNSgY8umw^=4aZ zO{a5`jfp%W`na_K4hGZ%vxTBKNX__~`m_L(NY_PR2W|`8irjTEOh_AN*+hEiQe{J# zER0lOhX-(=M%`_KuLc!#$pPAoN$g^ckQV00$fd-zrb>kfah;{^VBx zJ0w#J1d+@f5yW99K*Q(v)2oQLt%@=~(w~28Usq4Q4A&8A4H+H;@VLC<#n~k)>e-$P0NljHPm@!fzs1R zt0S6C!zxZ90f$J|(3pWnBubIko=^s`1JrYShPoC}P!45t_cXsI2;kx(6+Iq6=YZI)S5*?c3Z0ci7O2Tw$&H@`p z`3kZM``~IrcQ3>a$e`R?2+Tq02{)j@=U}4jsy~l{S8H8Glpt8=#L|hGky)g_XqL$m zpHDhUDl(ASbe8s)Cl`miQSwi>YGtKg z(H;S*F$ZmBbM=?CG@m9<1jfP5$y93=MhbWVYDjd0y9fj9;33b_UITI}s06?vvssA2 zgCGtxi=>f?fdWt>i^>a?Kw;6y+#+xpo+7A+tUom`3Ui-XsQA2@rb4ox1$9O=En8O` z*OC?-<7#H9tuSBVm!xtmS|F#f7z#X(&R%Zj@^sZQ(L>l};g+`S7!oTQY zqJ#h!!Z{8GxEQ9{8P9aIkax3GrTE=q(Q_kJQJ)@M{p*d5*Vj~>SzdTBpFb&xE? zT0wEcfVipJOlx&Hlf_e5y0%M{$U;W4Sb6R*$@iNt|6i(#&n;1YK}G&4x+`dt7^*L? zqb(27utCdOM^0D!WdvoVun3TWp+RF>(Go>NbYNmXHmQUoz{>a7VK~>^V2-pCr-tAf zGMh#AM`N4{@3;gUY@r@x9*X|zTJ&l{yq3-{Q|UUWtUO&=?v+JKFKa9$^#1Z9`Ip5* z<=Kl>=b|8GY@kG@nJJAsk%KdsF0+3XeH?X%Ixug*y_27E=ZI;CgbmRJGMpaxk2~cV!JZ=@=GJ^E*l0pQSU_qpZ=wn0_M4Q431fa;^ z15DxBoNzFq-q_CgVK}WNN4yFqv_%P6>_)X-4Ihf6d4)b42 zc=0`mfE0Rj#2!6)p5jJgW;lZcQ&YnQ#`-V_MYuEBM)V1RI8!@Efeb}-fFNeCuKE$Ci#UDUAG{GBu+JT*n1T3-WuGo@`mjcmsxg8XdQ zK|yU>qUUe-w%r-2X-{%$OLc6FHE)Ws;jThOT$Z1>#|i~48~T;V+NN2~^+9FdLO~3= z9~z2&s6a0%mKas zAa$LFlE|Z9=*}Un>r#Iqq=Qt^*XS>~s^n~!5HUQ_mrGwy8Ui6>Crc!kqX>x4WAqeglxAvuEBB&q0N2WoxxI&xqity_}<#I0BmhcIIZ1-D-)gIM8D@D6se;9(gc zMP7udbpHoIaw1K#!i^Zr8L2_K8KJ_vK@trMo(L4lc&vYtZt{Z-3xlX;Hp>n(OA9qg z4H3MfIK=e9@eO~ybL68FBS%(OetqZg=eG|oFAXmaw2eW*8KF06ro1 z6zd=O5Pl6m;g@CQOK5`Q7M{gJfdw)b2489tJEViz7DieFD=-vnAJR9-YR?X}go6NB zgjZTdcr>^v@?z~qFlxCt=M%+|QVG1(qG0AV_T#RP&l!NXJx}S+gAr_*^Gu}!(slD0Z-<;oadt)uKKwt#T z?yoE_q#rG9C9lZZ)3TF27khGF?GhqaWOFJjJ+Glc9TZ(xDM*<`VOv6w8D313H4x^p zKzLSj8l4}_HKv*^o=zV*Behq=#i~a02i&w`Pz!6Y=s7Z`4Hvy&qV@_&9~|j!rV?y1 zkN%k4V}6t{1hx6dPky~Z>jk*iN@%L0w`Gf;3>Gky_bpL3qb~ug~^2ncH~Ez zVKp!TJA~1J*#fH%0aLIkjG-iK;T?jQgqh&u;3S*@_+XSqnlnlw%m5V5kP&K>7iA8_ z&hcHi_W{frO;KSYm|uDFL|Dl zMM6AjUPh^2WUQDbIO};E%{N&%m0l{k^QZXP>tLu#nZ(c*M*}4*%~_%!wVRHm##D+; zkb}YoVL)f34+AYFKH^MgBD(*|hD^U&nJ$Q~rt^u&(nXB9=p|+>c8VT4RDL-xCN)k< z9i-MV(qGrrLHnn`izm!1Ua?xTg?Z<3dKDxIH#3{pIoP<)LyM6?m`)s;F1kVg>Zq%H*`al*mRaR>5LgoBVr zCcO$`!oNaA34MmwmnMFFZWQc*cbx0aKG&CbV`a&OzMR)r6@7 z2#IrRA%;%x5@C7St0U9GO8^dP>WQroSb=^g_-L~HNZ$ze(sD2sZW>V)=1*FLEy5>2o7e#RzeEU0dV24;wTGV0%Z`B zP~*Zd!~~xhAx33U7H=M1`_b9W=Qg(t)Wy@SPFO49=8WPP8{8b6M;hW2{?CB0Kq!R! zRt6IQgai}p#Bs|XB!5D-U1Wc&?zE!aWL8#WG@#pe;4*ntM8 z)|MXVNiPo-fuTfyBU~QB&~w(NmpIZ5$j2k>PSYuTsI+UPlz~7DgJ&7i9(K|qgJfkP z^*`FGmAUTyx!zrw-USgh;FR+0Us&lYx!Y(Esey-rKBj6f(bpn{=dUGegG4Nb%#k5n zp{SfQNZI0+74NRiz_}v=BL0+|QXxVGnwGbVs+sP~Zk7u10s5FT7$9&5T!Yvb*a&zT zX#2zszdXija^bP^rQZbeLE;pk07o+TLEsd^F@aSAUW5x)0ykmhm&94K;2|uXlP!6lIz1uS*h#pd>;1P!dKiYdFrDEhAgzD=m!|Xu@|P zK*In*$aw`dAQaNzEjWNJPq8N}$SgC^bn+{3BwRzHBs>dhh)50LA#Z(=lZwL?mxr%5 z`f}VtHrGa>vDk=%HrSY)E`EIS+{wiTi}ACvie$cLa&xu8Batd1%UcDe5oE*jf;B|+ z2lG%^h#opbYWPz~V#ZWth<-GVi*an5YD~pvK@EXDI&XT4NCX7fEm@isu&OY4V|fVr z8Zu!X?@d|08*+TsP3IGZf#XnK&|eu(vx|7( zj5l&ZR815d^S)$G)5VH7y+{#sfkcRlhY6MlgL-AQ2oWGA$Q+e0RG^5hgt^frV+n{u z2r@Omgp!3YPfc@uxpSv~suH+K82UM}gAdV=>T#qu<^I-&)#>gHQ5J1!_I0slwK1lR z2||moKH8jo)0PCAns8GZ$Cc5^CCms)LQIz}Hy=DBVo$hL5!r%%JDx~lu z4-H&d_1mU_p`_Dw!A{g_EtavDS+LE{ih5jIjkoKp{vk zFU$z+U|?DB)qqaGVshb0*dfS8mqgYjT24qP1AV<+5nDlYvr;2{E6PQ&EO3zC@egW@Q4HJsaB7?$aYS`WT(KuQg; zU6;+PGB5iFQqFtE0^s?8JGN=cip5s0Vf+AcP1=VW4h)pdOSY#$gd9Fka@$ zr07!bpgi}v)rGNNpV@S8v;pkEOM0p!Q)6#pI|rGtSc(aIgjj|=I{$aQUVPn?0{3`g;|O3h%X$M zD!cHjC^2h*KE5J>Cm`+7h_<3%q>K^emN&Ds7mFci2TgABI776bSYk_b{hzU3J1N+hl(77)xJh>K(@lP6?BI)) z1X&;NPP;r%3g7EVum?3z@gNAtfO=F@=YphIgh?Zw)F`vcNK*(!MXUv>s8qp#8np?Q z_*UT{unb%z6;b9;5;8^MoUz2rS9%ln0us8*3L|f#?SON-g3UEXM2-Z0h z&_S|yB>1RGv@cJzWAS5glqWcp#M-iM3nDGc;_dM-5E3qpv?3&25o22tZ7pmNLbI{9 zbW7$K3BM$F3Ge&8DI_c)OUxg^K4d7s`e%S0JmgjQO2|C}Q+No7OnwD+f)~7n^c36# za3Q#hX_Fmn4pMVGEDWbFMK>8fnv~=pUst-eETSODluTAi_=!egn@G$8Tm~TUK!YIs zw#-Eio(wnucLp9Yz(V39lf}Ejx&cspPy^6+)faI(H|vG?GW8ZbySzH-&W>JWHP#im z4wbp#ts5xyUR&a`rqpW%{SfjzXpgWa*K1{t=ei=F!9uU)sWu$5uP4)7YdB&_o~zQVbIBa9e_H0xn>K;KD%NUI^U(&%+>07}v$L@&iXm zCnY!yvLpm(d)g|Y_I&^Dou3XeCeQryW5?B#ht?JN-r82Xr6ziLvJ1dL!2;dD>*H-2 z5^Slmt%-qOSky(DQ}a@nU|WhC71EJlU7utN^*}hgB+{fh-lintZ)Wr4wfOfFU;oYI55lv66e{_x!?NAL=oQ z7pxqBL)>74jEF&!rw|)xigTWHfRtbh7F%J6X-%vRc1KyPb#8j!Mrxn9s^3CSgbYZ27CZj!i15?1&ay)8+DR)f*qg+_yWqnJ7fVG^DKW8en#gJB{vQ=xA`COA027f2#@4gUp>SYf&N z8!#XpQbq||2FxYQT{qlW%hQ-5cQhH4NkpbT;I)ah$JS?F*;{n=K+d&8S(nGtt{*9U zZGZM_hqEppO}?@}`R0+FYe#Y~9M608RN>{5xp&VMUR;y1r9PC~jFHMzJ3|$^v`}x! zJqC6oU`v*9FB!SKDF_1l5Hti#@gzxfF@1ssWVoqEcxwY9Ux@?v-9id-*(wNMYL@*5KY4l7I&j2Bvj zBWTJ)43@HJGe`%(!7+ai4gZtc{15jNqop8Can4g~Dia>Py7k^jEj?Ur^cCLdDY)E~ zeQtT?t1EI57CXN@_tL7u)7{x8d$JF=rEaP5hYBjpeOg8FMKVXdj1>s_Ci+Gc zjtd|M1Kyu-fHpT1T!}=55auCJfK~0)71VL1Gu;4@gcGCt;s#BeK z3UX1K;sh?>t)Q86Yhhq-RrK1H)UM)CRL<$WLd|=1xP5V`g>Z|;SrvzwgAQvdV}_Qd z?p|JgWJB|o&iqx?u`O9X_!kI^mXP!nV^OwIYG<#BfP$u12kZuN;`G^ThW`B6Z;Hi%%5DPITsW%B<5 zcX%j~4pKa128%h)R2Dfv0F;0=7(|#tdIwVK6q90;_YEK-~tFG zIZA*+nS(>*zq6mM1mfQV2gri9h=(RW2=KvT<{>^2_C$Hme^Z@IWf3|xS*W4-43e&I zPV|j+hWz1^W#2qr`_*6D9)G*`@t;!Z1#}$vh=>PJYuFoGeJbu*p-4~6I z9`}Ctxck8B(9IRD4T%nmW4Rq&z@WF$h6f!1H{=Wh{ zj_e#9%<_46OB3>qtqHa`I7k(1NpS!j7?S-0h#)D3c`|vO{g4TcL&P}Izdm5k%vITzZ~uJmNT-kbCKvVv>{;a5x^0kBSk>dyfp~~kg_R8fG%LcJs;Nq77Z97 zZtSGJ1ycYbLMLo9Wsz5sEV$FA1RF*9=wn;i8_rG+G-7dL3&>EzhT3zO0@wjMFyI%J z33fG!_5j4>?*LxFM?~Bt$Y8W1{kKg+{-@E+L+b2K2cj&iQ_Pu*%%O}_NeRcond*?=JzfclkRUR$a z$6F_de{*@)@2~D-`_9?TsG?_un_+cFXF0MtMwL7?LQb`Rho=pY4vOXKYF!!5xA5Co=;cW4Fhy zp0Hg#F{9l9n>zirbOdke2p?^a-`Se5t3Tx1->NJv|mHJa4Y0h{ug$ z6PXOHNCE^SM6sXD=fW1cA$eOs6LjRj4k9Tcm?FatkV3)^2~EHbG-87}o1bo!n<`tR zkIGBaCfD{)J^5dO9Up)6er1Toh2^=gugqPQ?a>x*)0SvQqI!#LOsy(QK~j%%@i5Mf~Ob*5B;txV5t6ja8+$$>vyFLWJdw_2oC# zm67FvzXMWDkc7qLxbf^a=D7}&3L&Ps- z1K*^830Z->#4<3^h0+8H7gVYH5KQ?##fu5|&)iT$aeT0Ga)=2X2_pe5Z0-T@L(gI5;&eV}LZD+q%t(oFbhA}twMC;)-L zjsOFIL*gCaFJ?}5uzoh~^AyJz#|0JPW=B?*4OYd}#5;f;5Ei^hzzqN)aKuLsn!`ip z=&*7&iGvW10Z_mWAOqk4H85?YIS=D}Ok+Itzz)*1sEb2~<=4kHygpR9w>o-TL&)1# z>c0Hlif#RVTPq^zc(9``cx!#|md4 z>#5BY?KRw&@JR?c3$Q@LO@Fwc)y$x}bSJDrefDzyYwhWOM zwhX+a#bJgZ2x%bL6vRip%tQxyst+BEX3ti7hP=IF167}%9eQ|h#RubkAB^{WbZFTJ z2l^gN^t?OP_15mrU+?RAFtO~Nz1Sbc2Ll9c zt}@s}pvl3NRbSpX{P^v2$5%IiW%x~L83%UIOSv%Aycp9X!s^=oRbSmb^3~O`Ki@d; z*~Og*wU*)#i4&k8EFF?i!tr_AetC6_W8OKiHb2Om*H*_n0vwzWe0-93035tfKm%zY zVP?2L7(j+#9HAl`g&&H+1dSD_2PBKn9OtxfZF$&4Z$WQ{7q5c0a4@-N7%8|p@Mj}# z2##Q_5F`dfzz&Ibu!g}7s%9j}U@o#q{6$fJoR=ZB%hozClS8b#XsVC-qK9WjF=h|6 zMBzT)z1;6FUv9X2sboh@_;>}{>ml@Q*j699r!Hc&(r?>3-^bsrzCNC|uGn+5G>S$r zE6M`NUZu>MbaK*v@Vo#Vzy#h6VIQH}f?68!9a&J8ZWRCrI1=Zt4_JT{P!CCo9^im$ zfErjg9K);P{55cwhI#ALXS;K0_2k0-4@~~IV8`SF_#qRV9WV<5u~KgrY#AU!WPC)K z3J{4hWe|?RdkO_0sDVZy{|C$7)ne`=E|hu^05<0PG|zRF zF{ABSyYk_yJO6m+=;wEiVvN8D*4D@V;pX^vcaL1&(p3><3v-b;PF=iR zd4%P%{LnvMKlJUb33zkhh>53la3 zi?Oduawhcy;D7|-zNH+7ILKEw#=pKc{`(6%no_;!lgevhJ=iS#K6qFszk(D40zp7k z5o4BR*5ebA=IqBCB7qBeA{bo!jQk+{;6=ekM^~5bUYd$mh+sM1T%0Drhe$sQAS1>M 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 Xzy>5RhaEOBNpnM-lYkXU;Gh0K3eU$E literal 0 HcmV?d00001 diff --git a/plugins/pad/PADwin/Src/resource.h b/plugins/pad/PADwin/Src/resource.h new file mode 100644 index 0000000..0ea747c --- /dev/null +++ b/plugins/pad/PADwin/Src/resource.h @@ -0,0 +1,70 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PadDialog.rc +// +#define IDD_DIALOG1 110 +#define IDB_BITMAP1 112 +#define IDC_EL3 1012 +#define IDC_L2 1013 +#define IDC_ER3 1014 +#define IDC_R2 1015 +#define IDC_ESTART 1016 +#define IDC_L1 1017 +#define IDC_ESELECT 1018 +#define IDC_R1 1019 +#define IDC_ECROSS 1020 +#define IDC_TRI 1021 +#define IDC_ESQUARE 1022 +#define IDC_CIRCLE 1023 +#define IDC_ECIRCLE 1024 +#define IDC2_CROSS 1025 +#define IDC_ETRIANGLE 1026 +#define IDC_SQUARE 1027 +#define IDC_ER2 1028 +#define IDC_SELECT 1029 +#define IDC_ER1 1030 +#define IDC_L3 1031 +#define IDC_EDOWN 1032 +#define IDC_R3 1033 +#define IDC_ERIGHT 1034 +#define IDC_START 1035 +#define IDC_ELEFT 1036 +#define IDC_UP 1037 +#define IDC_EUP 1038 +#define IDC_RIGHT 1039 +#define IDC_EL2 1040 +#define IDC_DOWN 1041 +#define IDC_EL1 1042 +#define IDC_LEFT 1043 +#define IDC_TABC 1044 +#define IDC_LAX 1045 +#define IDC_LAY 1046 +#define IDC_RAX 1047 +#define IDC_RAY 1048 +#define IDC_SCROSS 1049 +#define IDC_CHECK1 1050 +#define IDC_LOG 1050 +#define IDC_SCIRCLE 1051 +#define IDC_SSQUARE 1052 +#define IDC_STRIANGLE 1053 +#define IDC_SL3 1054 +#define IDC_SUP 1055 +#define IDC_SDOWN 1056 +#define IDC_SLEFT 1057 +#define IDC_SRIGHT 1058 +#define IDC_SR3 1059 +#define IDC_SL1 1060 +#define IDC_SL2 1061 +#define IDC_SR1 1062 +#define IDC_SR2 1063 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 114 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1051 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/pad/PADwin/Src/support.c b/plugins/pad/PADwin/Src/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/pad/PADwin/Src/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/pad/PADwin/Src/support.h b/plugins/pad/PADwin/Src/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/pad/PADwin/Src/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/pad/PADwin/build.sh b/plugins/pad/PADwin/build.sh new file mode 100644 index 0000000..bf9a915 --- /dev/null +++ b/plugins/pad/PADwin/build.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +echo --------------- +echo Building PADwin +echo --------------- + +curdir=`pwd` + +cd ${curdir}/Src +make $@ + +if [ -s libPADwin.so ] +then +cp libPADwin.so ${PCSX2PLUGINS} +fi diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX.cpp b/plugins/pad/SSSPSXPAD/PadSSSPSX.cpp new file mode 100644 index 0000000..9a26c3d --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX.cpp @@ -0,0 +1,1041 @@ +#define WINVER 0x0500 +#define _WIN32_WINNT WINVER +#define DIRECTINPUT_VERSION 0x0800 + +#include +#include +#include +#include + +#include "PadSSSPSX.h" + +static const char* LibraryName = "SSSPSX PAD Plugin Pressure Mod"; +static const unsigned char version = 0x0002; +static const unsigned char revision = 1; +static const unsigned char build = 6; + +HMODULE hInstance; +HWND hTargetWnd; + +static struct +{ + Config config; + int devcnt; + LPDIRECTINPUT8 pDInput; + LPDIRECTINPUTDEVICE8 pDKeyboard; + LPDIRECTINPUTDEVICE8 pDDevice[4]; + LPDIRECTINPUTEFFECT pDEffect[4][2]; /* for Small & Big Motor */ + DIJOYSTATE JoyState[4]; + u16 padStat[2]; + int padID[2]; + int padMode1[2]; + int padMode2[2]; + int padModeE[2]; + int padModeC[2]; + int padModeF[2]; + int padVib0[2]; + int padVib1[2]; + int padVibF[2][4]; + int padVibC[2]; + DWORD padPress[2][16]; + int curPad; + int curByte; + int curCmd; + int cmdLen; +} global; + +static BOOL CALLBACK EnumAxesCallback (LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) +{ + LPDIRECTINPUTDEVICE8 pDDevice = (LPDIRECTINPUTDEVICE8)pvRef; + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof (diprg); + diprg.diph.dwHeaderSize = sizeof (diprg.diph); + diprg.diph.dwObj = lpddoi->dwType; + diprg.diph.dwHow = DIPH_BYID; + diprg.lMin = -128; + diprg.lMax = 127; + pDDevice->SetProperty (DIPROP_RANGE, &diprg.diph); + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK EnumJoysticksCallback (const DIDEVICEINSTANCE* instance, VOID* pContext) +{ + const int devno = global.devcnt; + if (devno >= 4) + return DIENUM_STOP; + HRESULT result = global.pDInput->CreateDevice (instance->guidInstance, &global.pDDevice[devno], NULL); + if (FAILED (result)) + return DIENUM_CONTINUE; + global.devcnt++; + return DIENUM_CONTINUE; +} + +static bool ReleaseDirectInput (void) +{ + int index = 4; + while (index--) + { + if (global.pDEffect[index][0]) + { + global.pDEffect[index][0]->Unload(); + global.pDEffect[index][0]->Release(); + global.pDEffect[index][0] = NULL; + } + if (global.pDEffect[index][1]) + { + global.pDEffect[index][1]->Unload(); + global.pDEffect[index][1]->Release(); + global.pDEffect[index][1] = NULL; + } + if (global.pDDevice[index]) + { + global.pDDevice[index]->Unacquire(); + global.pDDevice[index]->Release(); + global.pDDevice[index] = NULL; + } + } + if (global.pDKeyboard) + { + global.pDKeyboard->Unacquire(); + global.pDKeyboard->Release(); + global.pDKeyboard = NULL; + } + if (global.pDInput) + { + global.pDInput->Release(); + global.pDInput = NULL; + } + global.devcnt = 0; + return FALSE; +} + +static bool InitDirectInput (void) +{ + if (global.pDInput) + return TRUE; + HRESULT result = DirectInput8Create (hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&global.pDInput, NULL); + if (FAILED (result)) + return ReleaseDirectInput(); + result = global.pDInput->CreateDevice (GUID_SysKeyboard, &global.pDKeyboard, NULL); + if (FAILED (result)) + return ReleaseDirectInput(); + result = global.pDInput->EnumDevices (DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY); + if (FAILED (result)) + return ReleaseDirectInput(); + result = global.pDKeyboard->SetDataFormat (&c_dfDIKeyboard); + if (FAILED (result)) + return ReleaseDirectInput(); + if (hTargetWnd) + { + global.pDKeyboard->Unacquire(); + result = global.pDKeyboard->SetCooperativeLevel (hTargetWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); + if (FAILED (result)) + return ReleaseDirectInput(); + } + int index = global.devcnt; + while (index--) + { + const LPDIRECTINPUTDEVICE8 pDDevice = global.pDDevice[index]; + result = pDDevice->SetDataFormat (&c_dfDIJoystick); + if (FAILED (result)) + return ReleaseDirectInput(); + if (hTargetWnd) + { + pDDevice->Unacquire(); + result = pDDevice->SetCooperativeLevel (hTargetWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); + if (FAILED (result)) + return ReleaseDirectInput(); + } + struct + { + DIPROPDWORD dipdw; + DWORD rgdwAxes[2]; + LONG rglDirection[2]; + DIPERIODIC per; + DICONSTANTFORCE cf; + DIEFFECT eff; + } local; + memset (&local, 0, sizeof (local)); + local.dipdw.diph.dwSize = sizeof (DIPROPDWORD); + local.dipdw.diph.dwHeaderSize = sizeof (DIPROPHEADER); + local.dipdw.diph.dwHow = DIPH_DEVICE; + local.dipdw.dwData = DIPROPAUTOCENTER_OFF; + pDDevice->SetProperty (DIPROP_AUTOCENTER, &local.dipdw.diph); + result = pDDevice->EnumObjects (EnumAxesCallback, pDDevice, DIDFT_AXIS); + if (FAILED (result)) + return ReleaseDirectInput(); + + local.rgdwAxes[0] = DIJOFS_X; + local.rgdwAxes[1] = DIJOFS_Y; + local.eff.dwSize = sizeof (DIEFFECT); + local.eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + local.eff.dwDuration = INFINITE; + local.eff.dwGain = DI_FFNOMINALMAX; + local.eff.dwTriggerButton = DIEB_NOTRIGGER; + local.eff.cAxes = 2; + local.eff.rgdwAxes = local.rgdwAxes; + local.eff.rglDirection = local.rglDirection; + + /* Small Motor */ + local.eff.cbTypeSpecificParams = sizeof (DIPERIODIC); + local.eff.lpvTypeSpecificParams = &local.per; + result = pDDevice->CreateEffect (GUID_Square , &local.eff, &global.pDEffect[index][0], NULL); + if (FAILED (result)) + global.pDEffect[index][0] = NULL; + + /* Big Motor */ + local.eff.cbTypeSpecificParams = sizeof (DICONSTANTFORCE); + local.eff.lpvTypeSpecificParams = &local.cf; + result = pDDevice->CreateEffect (GUID_ConstantForce , &local.eff, &global.pDEffect[index][1], NULL); + if (FAILED (result)) + global.pDEffect[index][1] = NULL; + } + return TRUE; +} + +static bool AcquireDevice (LPDIRECTINPUTDEVICE8 lpDirectInputDevice) +{ + if (FAILED (lpDirectInputDevice->Acquire())) + { + HRESULT result = lpDirectInputDevice->Acquire(); + if (result == DIERR_OTHERAPPHASPRIO) + return FALSE; + if (FAILED (result)) + return ReleaseDirectInput(); + } + return TRUE; +} + +/* Small Motor */ +static bool SetDeviceForceS (int pad, DWORD force) +{ + InitDirectInput(); + if (global.pDEffect[pad][0]) + { + if ( force == 0) { + if (FAILED (global.pDEffect[pad][0]->Stop())) { + AcquireDevice (global.pDDevice[pad]); + if (FAILED (global.pDEffect[pad][0]->Stop())) + return ReleaseDirectInput(); + } + return TRUE; + } + LONG rglDirection[2] = { 0, 0 }; + DIPERIODIC per; + rglDirection[0] = force; + rglDirection[1] = force; + per.dwMagnitude = force; + per.dwPeriod = (DWORD) (0.01 * DI_SECONDS); + per.lOffset = 0; + per.dwPhase = 0; + DIEFFECT eff; + eff.dwSize = sizeof (DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.cAxes = 2; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof (DIPERIODIC); + eff.lpvTypeSpecificParams = &per; + if (FAILED (global.pDEffect[pad][0]->SetParameters (&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START))) + return ReleaseDirectInput(); + if (FAILED (global.pDEffect[pad][0]->Start (1, 0))) + { + AcquireDevice (global.pDDevice[pad]); + if (FAILED (global.pDEffect[pad][0]->Start (1, 0))) + return ReleaseDirectInput(); + } + } + return TRUE; +} + +/* Big Motor */ +static bool SetDeviceForceB (int pad, DWORD force) +{ + InitDirectInput(); + if (global.pDEffect[pad][1]) + { + if ( force == 0) { + if (FAILED (global.pDEffect[pad][1]->Stop())) { + AcquireDevice (global.pDDevice[pad]); + if (FAILED (global.pDEffect[pad][1]->Stop())) + return ReleaseDirectInput(); + } + return TRUE; + } + LONG rglDirection[2] = { 0, 0 }; + DICONSTANTFORCE cf; + rglDirection[0] = force; + rglDirection[1] = force; + cf.lMagnitude = force; + DIEFFECT eff; + eff.dwSize = sizeof (DIEFFECT); + eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; + eff.cAxes = 2; + eff.rglDirection = rglDirection; + eff.lpEnvelope = 0; + eff.cbTypeSpecificParams = sizeof (DICONSTANTFORCE); + eff.lpvTypeSpecificParams = &cf; + if (FAILED (global.pDEffect[pad][1]->SetParameters (&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START))) + return ReleaseDirectInput(); + if (FAILED (global.pDEffect[pad][1]->Start (1, 0))) + { + AcquireDevice (global.pDDevice[pad]); + if (FAILED (global.pDEffect[pad][1]->Start (1, 0))) + return ReleaseDirectInput(); + } + } + return TRUE; +} + +static bool GetJoyState (const int devno) +{ + InitDirectInput(); + if (global.pDDevice[devno] == NULL) + return FALSE; + global.pDDevice[devno]->Poll(); + if (FAILED (global.pDDevice[devno]->GetDeviceState (sizeof (DIJOYSTATE), &global.JoyState[devno]))) + { + AcquireDevice (global.pDDevice[devno]); + return FALSE; + } + return TRUE; +} + +static bool GetKeyState (u8* keyboard) +{ + InitDirectInput(); + if (global.pDKeyboard == NULL) + return FALSE; + global.pDKeyboard->Poll(); + if (FAILED (global.pDKeyboard->GetDeviceState (256, keyboard))) + { + AcquireDevice (global.pDKeyboard); + return FALSE; + } + return TRUE; +} + +static void MakeConfigFileName (char* fname) +{ + GetModuleFileName (hInstance, fname, 256); + strcpy (fname + strlen (fname) - 3, "cfg"); +} + +static void SaveConfig (void) +{ + char fname[256]; + MakeConfigFileName (fname); + HANDLE hFile = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + DWORD number_of_bytes; + WriteFile (hFile, &global.config, sizeof (global.config), &number_of_bytes, NULL); + CloseHandle (hFile); + } +} + +static void LoadConfig (void) +{ + char fname[256]; + MakeConfigFileName (fname); + HANDLE hFile = CreateFile (fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + DWORD number_of_bytes; + ReadFile (hFile, &global.config, sizeof (global.config), &number_of_bytes, NULL); + CloseHandle (hFile); + } + global.padVibC[0] = global.padVibC[1] = -1; + for (int cnt = 21; cnt--; ) + { + const int key0 = global.config.keys[0][cnt]; + if (key0 >= 0x1000) + global.padVibC[0] = (key0 & 0xfff) / 0x100; + const int key1 = global.config.keys[1][cnt]; + if (key1 >= 0x1000) + global.padVibC[1] = (key1 & 0xfff) / 0x100; + } +} + +static void PADsetMode (const int pad, const int mode) +{ + static const u8 padID[] = { 0x41, 0x73, 0x41, 0x79 }; + global.padMode1[pad] = mode; + global.padVib0[pad] = 0; + global.padVib1[pad] = 0; + global.padVibF[pad][0] = 0; + global.padVibF[pad][1] = 0; + global.padID[pad] = padID[global.padMode2[pad] * 2 + mode]; +} + +static void KeyPress (const int pad, const int index, const bool press) +{ + if (index < 16) + { + if (press) + { + global.padStat[pad] &= ~(1 << index); + if (global.padPress[pad][index] == 0) + global.padPress[pad][index] = GetTickCount(); + } + else + { + global.padStat[pad] |= 1 << index; + global.padPress[pad][index] = 0; + } + } + else + { + static bool prev[2] = { FALSE, FALSE }; + if ((prev[pad] != press) && (global.padModeF[pad] == 0)) + { + prev[pad] = press; + if (press) PADsetMode (pad, !global.padMode1[pad]); + } + } +} + +static void UpdateState (const int pad) +{ + static int flag_keyboard; + static int flag_joypad[4]; + if (pad == 0) + { + flag_keyboard = 0; + flag_joypad[0] = 0; + flag_joypad[1] = 0; + flag_joypad[2] = 0; + flag_joypad[3] = 0; + } + static u8 keystate[256]; + for (int index = 17; index--; ) + { + const int key = global.config.keys[pad][index]; + if (key == 0) + continue; + else if (key < 0x100) + { + if (flag_keyboard == FALSE) + { + flag_keyboard = TRUE; + if (GetKeyState (keystate) == FALSE) + return; + } + KeyPress (pad, index, keystate[key] & 0x80); + } + else + { + const int joypad = ((key & 0xfff) / 100); + if (flag_joypad[joypad] == FALSE) + { + flag_joypad[joypad] = TRUE; + if (GetJoyState (joypad) == FALSE) + return; + } + if (key < 0x2000) + { + KeyPress (pad, index, global.JoyState[joypad].rgbButtons[key & 0xff]); + } + else if (key < 0x3000) + { + const int state = ((int*)&global.JoyState[joypad].lX)[(key & 0xff) /2]; + switch (key & 1) + { + case 0: KeyPress (pad, index, state < -64); break; + case 1: KeyPress (pad, index, state >= 64); break; + } + } + else + { + const u32 state = global.JoyState[joypad].rgdwPOV[(key & 0xff) /4]; + switch (key & 3) + { + case 0: KeyPress (pad, index, (state >= 0 && state <= 4500) || (state >= 31500 && state <= 36000)); break; + case 1: KeyPress (pad, index, state >= 4500 && state <= 13500); break; + case 2: KeyPress (pad, index, state >= 13500 && state <= 22500); break; + case 3: KeyPress (pad, index, state >= 22500 && state <= 31500); break; + } + } + } + } + + /* Small Motor */ + const int vib0 = global.padVibF[pad][0] ? 10000 : 0; + if ((global.padVibF[pad][2] != vib0) && (global.padVibC[pad] >= 0)) + { + global.padVibF[pad][2] = vib0; + SetDeviceForceS (global.padVibC[pad], vib0); + } + /* Big Motor */ + const int vib1 = global.padVibF[pad][1] ? 500 + 37*global.padVibF[pad][1] : 0; + if ((global.padVibF[pad][3] != vib1) && (global.padVibC[pad] >= 0)) + { + global.padVibF[pad][3] = vib1; + SetDeviceForceB (global.padVibC[pad], vib1); + } +} + +static void set_label (const HWND hWnd, const int pad, const int index) +{ + const int key = global.config.keys[pad][index]; + char buff[64]; + if (key < 0x100) + { + if (key == 0) + strcpy (buff, "NONE"); + else if (GetKeyNameText (key << 16, buff, sizeof (buff)) == 0) + wsprintf (buff, "Keyboard 0x%02X", key); + } + else if (key >= 0x1000 && key < 0x2000) + { + wsprintf (buff, "J%d_%d", (key & 0xfff) / 0x100, (key & 0xff) + 1); + } + else if (key >= 0x2000 && key < 0x3000) + { + static const char name[][4] = { "MIN", "MAX" }; + const int axis = (key & 0xff); + wsprintf (buff, "J%d_AXIS%d_%s", (key & 0xfff) / 0x100, axis / 2, name[axis % 2]); + if (index >= 17 && index <= 20) + buff[strlen (buff) -4] = '\0'; + } + else if (key >= 0x3000 && key < 0x4000) + { + static const char name[][7] = { "FOWARD", "RIGHT", "BACK", "LEFT" }; + const int pov = (key & 0xff); + wsprintf (buff, "J%d_POV%d_%s", (key & 0xfff) / 0x100, pov /4, name[pov % 4]); + } + Button_SetText (GetDlgItem (hWnd, IDC_ESELECT + index), buff); +} + +static BOOL CALLBACK ConfigureDlgProc (const HWND hWnd, const UINT msg, const WPARAM wParam, const LPARAM lParam) +{ + static BYTE keymaps[2][256]; + static DWORD countdown; + static int disabled; + static HWND hTabWnd; + static int pad; + int cnt1; + int cnt2; + int key; + switch (msg) + { + case WM_INITDIALOG: + hTargetWnd = hWnd; + pad = disabled = 0; + LoadConfig(); + for (cnt1 = 21; cnt1--; ) + set_label (hWnd, pad, cnt1); + hTabWnd = GetDlgItem (hWnd, IDC_TABC); + TCITEM tcI; + tcI.mask = TCIF_TEXT; + tcI.pszText = "PAD1"; + TabCtrl_InsertItem (hTabWnd, 0, &tcI); + tcI.mask = TCIF_TEXT; + tcI.pszText = "PAD2"; + TabCtrl_InsertItem (hTabWnd, 1, &tcI); + SetTimer (hWnd, 0x80, 50, NULL); + return TRUE; + case WM_DESTROY: + break; + case WM_NOTIFY: + if (wParam == IDC_TABC) + { + if (disabled) + EnableWindow (GetDlgItem (hWnd, disabled), TRUE); + disabled = 0; + pad = TabCtrl_GetCurSel (hTabWnd); + for (cnt1 = 21; cnt1--; ) + set_label (hWnd, pad, cnt1); + } + break; + case WM_COMMAND: + for (cnt1 = 21; cnt1--; ) + { + if (LOWORD (wParam) == IDC_BSELECT + cnt1) + { + if (disabled) + EnableWindow (GetDlgItem (hWnd, disabled), TRUE); + EnableWindow (GetDlgItem (hWnd, disabled = wParam), FALSE); + countdown = GetTickCount(); + GetKeyState (keymaps[0]); + return TRUE; + } + } + if (LOWORD (wParam) == IDOK) + EndDialog (hWnd, IDOK); + else if (LOWORD (wParam) == IDCANCEL) + EndDialog (hWnd, IDCANCEL); + break; + case WM_TIMER: + if (disabled) + { + const int index = disabled - IDC_BSELECT; + int analog = FALSE; + if ((GetTickCount() - countdown) / 1000 != 10) + { + char buff[64]; + wsprintf (buff, "Timeout: %d", 10 - (GetTickCount() - countdown) / 1000); + SetWindowText (GetDlgItem (hWnd, IDC_ESELECT + index), buff); + } + else + { + global.config.keys[pad][index] = 0; + set_label (hWnd, pad, index); + EnableWindow (GetDlgItem (hWnd, disabled), TRUE); + disabled = 0; + break; + } + if (GetKeyState (keymaps[1]) == FALSE) + break; + for (key = 0x100; key--; ) + { + if (~keymaps[0][key] & keymaps[1][key] & 0x80) + break; + } + for (cnt1 = global.devcnt; cnt1--;) + { + if (GetJoyState (cnt1) == FALSE) + break; + + for (cnt2 = 32; cnt2--; ) + { + if (global.JoyState[cnt1].rgbButtons[cnt2]) + key = 0x1000 + 0x100 * cnt1 + cnt2; + } + for (cnt2 = 8; cnt2--; ) + { + const int now = ((u32*)&global.JoyState[cnt1].lX)[cnt2]; + if (now < -64) + { + key = 0x2000 + 0x100 * cnt1 + cnt2 * 2 +0; + analog = TRUE; + } + else if (now >= 64) + { + key = 0x2000 + 0x100 * cnt1 + cnt2 * 2 +1; + analog = TRUE; + } + } + for (cnt2 = 4; cnt2--; ) + { + const u32 now = global.JoyState[cnt1].rgdwPOV[cnt2]; + if ((now >= 0 && now < 4500) || (now >= 31500 && now < 36000)) + key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +0; + if (now >= 4500 && now < 13500) + key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +1; + if (now >= 13500 && now < 22500) + key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +2; + if (now >= 22500 && now < 31500) + key = 0x3000 + 0x100 * cnt1 + cnt2 * 4 +3; + } + } + if (index >= 17 && index <= 20 && analog == 0) + key = 0; + else if (key > 0) + { + if (key != 1) + global.config.keys[pad][index] = key; + set_label (hWnd, pad, index); + EnableWindow (GetDlgItem (hWnd, disabled), TRUE); + disabled = 0; + } + } + } + return FALSE; +} + +u32 CALLBACK PS2EgetLibType (void) +{ + return 0x02; +} + +const char* CALLBACK PS2EgetLibName (void) +{ + return LibraryName; +} + +u32 CALLBACK PS2EgetLibVersion2 (u32 type) +{ + return (version << 16) | (revision << 8) | build; +} + +u32 CALLBACK PSEgetLibType (void) +{ + return 8; +} + +const char* CALLBACK PSEgetLibName (void) +{ + return LibraryName; +} + +u32 CALLBACK PSEgetLibVersion (void) +{ + return (version << 16) | (revision << 8) | build; +} + +s32 CALLBACK PADinit (u32 flags) +{ + return 0; +} + +void CALLBACK PADshutdown (void) +{ +} + +static int n_open = 0; +s32 CALLBACK PADopen (HWND hWnd) +{ + if (!IsWindow (hWnd) && !IsBadReadPtr ((u32*)hWnd, 4)) + hWnd = *(HWND*)hWnd; + if (!IsWindow (hWnd)) + hWnd = NULL; + else + { + while (GetWindowLong (hWnd, GWL_STYLE) & WS_CHILD) + hWnd = GetParent (hWnd); + } + hTargetWnd = hWnd; + if (n_open++ == FALSE) + { + memset (&global, 0, sizeof (global)); + global.padStat[0] = 0xffff; + global.padStat[1] = 0xffff; + LoadConfig(); + PADsetMode (0, 0); + PADsetMode (1, 0); + } + return 0; +} + +void CALLBACK PADclose (void) +{ + if (--n_open == 0) + ReleaseDirectInput(); +} + +u32 CALLBACK PADquery (void) +{ + return 3; +} + +u8 CALLBACK PADstartPoll (int pad) +{ + global.curPad = pad -1; + global.curByte = 0; + return 0xff; +} + +static const u8 cmd40[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a +}; +static const u8 cmd41[8] = +{ + 0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a, +}; +static const u8 cmd44[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const u8 cmd45[8] = +{ + 0xff, 0x5a, 0x03, 0x02, 0x01, 0x02, 0x01, 0x00, +}; +static const u8 cmd46[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0a, +}; +static const u8 cmd47[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, +}; +static const u8 cmd4c[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const u8 cmd4d[8] = +{ + 0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; +static const u8 cmd4f[8] = +{ + 0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, +}; + +static u8 get_analog (const int key) +{ + const int pad = ((key & 0xf00) / 0x100); + const int pos = ((key & 0x0ff) /2); + return (u8)(((int*)&global.JoyState[pad].lX)[pos] + 128); +} + +static u8 get_pressure (const DWORD now, const DWORD press) +{ + /*if (press == 0) + return 0; + return (u8)((now - press > 2550) ? 255 : (now - press) / 10);*/ + return 255; +} + +u8 CALLBACK PADpoll (const u8 value) +{ + const int pad = global.curPad; + const int cur = global.curByte; + static u8 buf[20]; + if (cur == 0) + { + global.curByte++; + global.curCmd = value; + switch (value) + { + case 0x40: + global.cmdLen = sizeof (cmd40); + memcpy (buf, cmd40, sizeof (cmd40)); + return 0xf3; + case 0x41: + global.cmdLen = sizeof (cmd41); + memcpy (buf, cmd41, sizeof (cmd41)); + return 0xf3; + case 0x42: + case 0x43: + if (value == 0x42) UpdateState (pad); + global.cmdLen = 2 + 2 * (global.padID[pad] & 0x0f); + buf[1] = global.padModeC[pad] ? 0x00 : 0x5a; + *(u16*)&buf[2] = global.padStat[pad]; + if (value == 0x43 && global.padModeE[pad]) + { + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + return 0xf3; + } + else + { + buf[ 4] = get_analog (global.config.keys[pad][19]); + buf[ 5] = get_analog (global.config.keys[pad][20]); + buf[ 6] = get_analog (global.config.keys[pad][17]); + buf[ 7] = get_analog (global.config.keys[pad][18]); + if (global.padID[pad] == 0x79) + { + const DWORD now = GetTickCount(); + buf[ 8] = get_pressure (now, global.padPress[pad][2]); + buf[ 9] = get_pressure (now, global.padPress[pad][0]); + buf[10] = get_pressure (now, global.padPress[pad][3]); + buf[11] = get_pressure (now, global.padPress[pad][1]); + buf[12] = get_pressure (now, global.padPress[pad][11]); + buf[13] = get_pressure (now, global.padPress[pad][10]); + buf[14] = get_pressure (now, global.padPress[pad][9]); + buf[15] = get_pressure (now, global.padPress[pad][8]); + buf[16] = get_pressure (now, global.padPress[pad][13]); + buf[17] = get_pressure (now, global.padPress[pad][12]); + buf[18] = get_pressure (now, global.padPress[pad][15]); + buf[19] = get_pressure (now, global.padPress[pad][14]); + } + return (u8)global.padID[pad]; + } + break; + case 0x44: + global.cmdLen = sizeof (cmd44); + memcpy (buf, cmd44, sizeof (cmd44)); + return 0xf3; + case 0x45: + global.cmdLen = sizeof (cmd45); + memcpy (buf, cmd45, sizeof (cmd45)); + buf[4] = (u8)global.padMode1[pad]; + return 0xf3; + case 0x46: + global.cmdLen = sizeof (cmd46); + memcpy (buf, cmd46, sizeof (cmd46)); + return 0xf3; + case 0x47: + global.cmdLen = sizeof (cmd47); + memcpy (buf, cmd47, sizeof (cmd47)); + return 0xf3; + case 0x4c: + global.cmdLen = sizeof (cmd4c); + memcpy (buf, cmd4c, sizeof (cmd4c)); + return 0xf3; + case 0x4d: + global.cmdLen = sizeof (cmd4d); + memcpy (buf, cmd4d, sizeof (cmd4d)); + return 0xf3; + case 0x4f: + global.padID[pad] = 0x79; + global.padMode2[pad] = 1; + global.cmdLen = sizeof (cmd4f); + memcpy (buf, cmd4f, sizeof (cmd4f)); + return 0xf3; + } + } + switch (global.curCmd) + { + case 0x42: + if (cur == global.padVib0[pad]) + global.padVibF[pad][0] = value; + if (cur == global.padVib1[pad]) + global.padVibF[pad][1] = value; + break; + case 0x43: + if (cur == 2) + { + global.padModeE[pad] = value; + global.padModeC[pad] = 0; + } + break; + case 0x44: + if (cur == 2) + PADsetMode (pad, value); + if (cur == 3) + global.padModeF[pad] = (value == 3); + break; + case 0x46: + if (cur == 2) + { + switch(value) + { + case 0: + buf[5] = 0x02; + buf[6] = 0x00; + buf[7] = 0x0A; + break; + case 1: + buf[5] = 0x01; + buf[6] = 0x01; + buf[7] = 0x14; + break; + } + } + break; + case 0x4c: + if (cur == 2) + { + static const u8 buf5[] = { 0x04, 0x07, 0x02, 0x05 }; + buf[5] = buf5[value & 3]; + } + break; + case 0x4d: + if (cur >= 2) + { + if (cur == global.padVib0[pad]) + buf[cur] = 0x00; + if (cur == global.padVib1[pad]) + buf[cur] = 0x01; + if (value == 0x00) + { + global.padVib0[pad] = cur; + if ((global.padID[pad] & 0x0f) < (cur - 1) / 2) + global.padID[pad] = (global.padID[pad] & 0xf0) + (cur - 1) / 2; + } + else if (value == 0x01) + { + global.padVib1[pad] = cur; + if ((global.padID[pad] & 0x0f) < (cur - 1) / 2) + global.padID[pad] = (global.padID[pad] & 0xf0) + (cur - 1) / 2; + } + } + break; + } + if (cur >= global.cmdLen) + return 0; + return buf[global.curByte++]; +} + +typedef struct +{ + unsigned char controllerType; + unsigned short buttonStatus; + unsigned char rightJoyX, rightJoyY, leftJoyX, leftJoyY; + unsigned char moveX, moveY; + unsigned char reserved[91]; +} PadDataS; + +long PADreadPort1 (PadDataS* pads) +{ + memset (pads, 0, sizeof (PadDataS)); + if ((global.padID[0] & 0xf0) == 0x40) + pads->controllerType = 4; + else + pads->controllerType = 7; + pads->buttonStatus = global.padStat[0]; + pads->leftJoyX = get_analog (global.config.keys[0][17]); + pads->leftJoyY = get_analog (global.config.keys[0][18]); + pads->rightJoyX = get_analog (global.config.keys[0][19]); + pads->rightJoyY = get_analog (global.config.keys[0][20]); + pads->moveX = 0; + pads->moveY = 0; + return 0; +} + +long PADreadPort2 (PadDataS* pads) +{ + memset (pads, 0, sizeof (PadDataS)); + if ((global.padID[1] & 0xf0) == 0x40) + pads->controllerType = 4; + else + pads->controllerType = 7; + pads->buttonStatus = global.padStat[1]; + pads->leftJoyX = get_analog (global.config.keys[1][17]); + pads->leftJoyY = get_analog (global.config.keys[1][18]); + pads->rightJoyX = get_analog (global.config.keys[1][19]); + pads->rightJoyY = get_analog (global.config.keys[1][20]); + pads->moveX = 0; + pads->moveY = 0; + return 0; +} + +keyEvent* CALLBACK PADkeyEvent (void) +{ + static keyEvent ev; + static u8 state[2][256]; + if (n_open) + { + memcpy (state[0], state[1], sizeof (state[0])); + GetKeyState (state[1]); + for (int cnt = 0; cnt < 256; cnt++) + { + if (~state[0][cnt] & state[1][cnt] & 0x80) + { + ev.event = (state[1][cnt] & 0x80) ? 1 : 2; + ev.key = MapVirtualKey (cnt, 1); + return &ev; + } + } + } + return NULL; +} + +void CALLBACK PADconfigure (void) +{ + if (n_open == 0) + { + memset (&global, 0, sizeof (global)); + if (DialogBox (hInstance, MAKEINTRESOURCE (IDD_DIALOG1), GetActiveWindow(), (DLGPROC)ConfigureDlgProc) == IDOK) + SaveConfig(); + ReleaseDirectInput(); + } +} + +void CALLBACK PADabout (void) +{ + MessageBox (0, "Copyright (C) 2004-2005 Nagisa", "SSSPSX PAD plugin", 0); +} + +s32 CALLBACK PADtest (void) +{ + return 0; +} +//#ifdef _WIN64 +BOOL APIENTRY DllMain(HMODULE hInst, DWORD dwReason, LPVOID lpReserved) +{ + hInstance = hInst; + return TRUE; +} +//#else +BOOL APIENTRY EntryPoint (HMODULE hInst, DWORD dwReason, LPVOID lpReserved) +{ + hInstance = hInst; + return TRUE; +} +//#endif diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX.def b/plugins/pad/SSSPSXPAD/PadSSSPSX.def new file mode 100644 index 0000000..a791c60 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX.def @@ -0,0 +1,22 @@ +LIBRARY "PadSSSPSX" + +EXPORTS + PSEgetLibType @1 + PSEgetLibName @2 + PSEgetLibVersion @3 + PS2EgetLibType @4 + PS2EgetLibName @5 + PS2EgetLibVersion2 @6 + PADinit @7 + PADshutdown @8 + PADopen @9 + PADclose @10 + PADkeyEvent @11 + PADstartPoll @12 + PADpoll @13 + PADreadPort1 @14 + PADreadPort2 @15 + PADquery @16 + PADconfigure @17 + PADtest @18 + PADabout @19 diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX.h b/plugins/pad/SSSPSXPAD/PadSSSPSX.h new file mode 100644 index 0000000..facd783 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX.h @@ -0,0 +1,45 @@ +/* PADwin + * Copyright (C) 2002-2004 PADwin Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PAD_H__ +#define __PAD_H__ + +#include "PadSSSPSXres.h" + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +typedef struct +{ + u32 key; + u32 event; +} keyEvent; + +typedef struct +{ + u32 keys[2][21]; +} Config; + +#endif diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX.rc b/plugins/pad/SSSPSXPAD/PadSSSPSX.rc new file mode 100644 index 0000000..6837be0 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX.rc @@ -0,0 +1,152 @@ +// Microsoft Visual C++ generated resource script. +// +#include "PadSSSPSXres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// { resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "PadSSSPSXres.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 0, 0, 442, 239 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "PAD Settings" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_TABC,"SysTabControl32",0x0,6,6,432,210 + PUSHBUTTON "L2",IDC_BL2,54,24,72,12,NOT WS_TABSTOP + EDITTEXT IDC_EL2,54,36,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "L1",IDC_BL1,54,48,72,12,NOT WS_TABSTOP + EDITTEXT IDC_EL1,54,60,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Up",IDC_BUP,54,78,72,12,NOT WS_TABSTOP + EDITTEXT IDC_EUP,54,90,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Left",IDC_BLEFT,12,102,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ELEFT,12,114,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Right",IDC_BRIGHT,96,102,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ERIGHT,96,114,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Down",IDC_BDOWN,54,126,72,12,NOT WS_TABSTOP + EDITTEXT IDC_EDOWN,54,138,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Select",IDC_BSELECT,144,36,72,12,NOT WS_TABSTOP, + WS_EX_TRANSPARENT + EDITTEXT IDC_ESELECT,144,48,72,12,ES_READONLY | NOT WS_TABSTOP, + WS_EX_TRANSPARENT + PUSHBUTTON "Start",IDC_BSTART,228,36,72,12,NOT WS_TABSTOP, + WS_EX_TRANSPARENT + EDITTEXT IDC_ESTART,228,48,72,12,ES_READONLY | NOT WS_TABSTOP, + WS_EX_TRANSPARENT + PUSHBUTTON "Analog",IDC_BMODE,186,66,72,12,NOT WS_TABSTOP, + WS_EX_TRANSPARENT + EDITTEXT IDC_EMODE,186,78,72,12,ES_READONLY | NOT WS_TABSTOP, + WS_EX_TRANSPARENT + PUSHBUTTON "R2",IDC_BR2,318,24,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ER2,318,36,72,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "R1",IDC_BR1,318,48,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ER1,318,60,72,12,ES_AUTOHSCROLL | ES_READONLY | NOT + WS_TABSTOP + PUSHBUTTON "Triangle",IDC_BTRIANGLE,318,78,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ETRIANGLE,318,90,72,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Square",IDC_BSQUARE,276,102,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ESQUARE,276,114,72,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Circle",IDC_BCIRCLE,360,102,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ECIRCLE,360,114,72,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "Cross",IDC_BCROSS,318,126,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ECROSS,318,138,72,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + PUSHBUTTON "L3",IDC_BL3,144,132,72,12,NOT WS_TABSTOP + EDITTEXT IDC_EL3,144,144,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "LX",IDC_BLAX,144,162,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ELAX,144,174,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "LY",IDC_BLAY,144,186,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ELAY,144,198,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "R3",IDC_BR3,228,132,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ER3,228,144,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "RX",IDC_BRAX,228,162,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ERAX,228,174,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "RY",IDC_BRAY,228,186,72,12,NOT WS_TABSTOP + EDITTEXT IDC_ERAY,228,198,72,12,ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "OK",IDOK,330,222,48,12,NOT WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,390,222,48,12,NOT WS_TABSTOP + CTEXT "",IDC_STATIC,318,174,108,30,0,WS_EX_STATICEDGE + LTEXT "DUALSHOCK2 INSIDE",IDC_STATIC,331,186,84,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + RIGHTMARGIN, 432 + BOTTOMMARGIN, 233 + END +END +#endif // APSTUDIO_INVOKED + +#endif // { resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX.vcproj b/plugins/pad/SSSPSXPAD/PadSSSPSX.vcproj new file mode 100644 index 0000000..ffdcde1 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.sln b/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.sln new file mode 100644 index 0000000..498a495 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PadSSSPSX_vc2005beta2", "PadSSSPSX_vc2005beta2.vcproj", "{79D9E8A9-C764-4082-826C-B715341FB1E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Debug|Win32.Build.0 = Debug|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Debug|x64.ActiveCfg = Debug|x64 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Debug|x64.Build.0 = Debug|x64 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win32.ActiveCfg = Release|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|Win32.Build.0 = Release|Win32 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|x64.ActiveCfg = Release|x64 + {79D9E8A9-C764-4082-826C-B715341FB1E9}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.vcproj b/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.vcproj new file mode 100644 index 0000000..6cbdcc8 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSX_vc2005beta2.vcproj @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/SSSPSXPAD/PadSSSPSXres.h b/plugins/pad/SSSPSXPAD/PadSSSPSXres.h new file mode 100644 index 0000000..bcfbc8f --- /dev/null +++ b/plugins/pad/SSSPSXPAD/PadSSSPSXres.h @@ -0,0 +1,59 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PadSSSPSX.rc +// +#define IDD_DIALOG1 100 +#define IDC_BSELECT 1000 +#define IDC_BL3 1001 +#define IDC_BR3 1002 +#define IDC_BSTART 1003 +#define IDC_BUP 1004 +#define IDC_BRIGHT 1005 +#define IDC_BDOWN 1006 +#define IDC_BLEFT 1007 +#define IDC_BL2 1008 +#define IDC_BR2 1009 +#define IDC_BL1 1010 +#define IDC_BR1 1011 +#define IDC_BTRIANGLE 1012 +#define IDC_BCIRCLE 1013 +#define IDC_BCROSS 1014 +#define IDC_BSQUARE 1015 +#define IDC_BMODE 1016 +#define IDC_BLAX 1017 +#define IDC_BLAY 1018 +#define IDC_BRAX 1019 +#define IDC_BRAY 1020 +#define IDC_ESELECT 1030 +#define IDC_EL3 1031 +#define IDC_ER3 1032 +#define IDC_ESTART 1033 +#define IDC_EUP 1034 +#define IDC_ERIGHT 1035 +#define IDC_EDOWN 1036 +#define IDC_ELEFT 1037 +#define IDC_EL2 1038 +#define IDC_ER2 1039 +#define IDC_EL1 1040 +#define IDC_ER1 1041 +#define IDC_ETRIANGLE 1042 +#define IDC_ECIRCLE 1043 +#define IDC_ECROSS 1044 +#define IDC_ESQUARE 1045 +#define IDC_EMODE 1046 +#define IDC_ELAX 1047 +#define IDC_ELAY 1048 +#define IDC_ERAX 1049 +#define IDC_ERAY 1050 +#define IDC_TABC 1060 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1061 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/pad/SSSPSXPAD/licence.txt b/plugins/pad/SSSPSXPAD/licence.txt new file mode 100644 index 0000000..b3143dc --- /dev/null +++ b/plugins/pad/SSSPSXPAD/licence.txt @@ -0,0 +1 @@ +see http://www.gnu.org/copyleft/gpl.html diff --git a/plugins/pad/SSSPSXPAD/readmewip.txt b/plugins/pad/SSSPSXPAD/readmewip.txt new file mode 100644 index 0000000..1444336 --- /dev/null +++ b/plugins/pad/SSSPSXPAD/readmewip.txt @@ -0,0 +1,48 @@ +SSSPSX Pad - An Open Source Pad plugin for PSX and PS2 emulators +Author: Nagisa +Homepage: http://www.asahi-net.or.jp/~bz7t-skmt/ + +Overview: +-Small executable program +-Source code under 1000 step,20kb binary +-Open Source,under the GPL Licence + + +Features: + +For PS1 emulators +- Force feedback support (PCSX only) + Delete the following PCSX sorce code. + File: sio.c Line: 138 +@--------------------- +@if (buf[parp] == 0x41) { +@@switch (value) { +@@@case 0x43: +@@@@buf[1] = 0x43; +@@@@break; +@@@case 0x45: +@@@@buf[1] = 0xf3; +@@@@break; +@@} +@} +@--------------------- + +For PCSX2 +-Force feedback support (maybe) +-PADKeyEvent API support +-Using DirectInput 9 (game controller and keyboard) + +Thanks to: +http://www.hm5.aitai.ne.jp/~takuya/index.html#ds2_analisys for the valuable info +PCSX2 team for the PadWinKeyb source code +bositman for some report + +Version History: +v1.0: -Initial Release +v1.1: -Changed to DirectInput 9 +v1.2: -PADKeyEvent API support added +v1.3: -DirectInput collision problem fixed +v1.4: -Added timeout on settings dialog.If the countdown ends, the key will be set to "NONE". + -Changed "ESC" key action on settings dialog.If you press the "ESC" key, the setting will keep the previous one. + -Fixed silly bug. (dont ask me about it). +v1.5: -Fixed 0x4D packet. diff --git a/plugins/pad/build.sh b/plugins/pad/build.sh new file mode 100644 index 0000000..f98c255 --- /dev/null +++ b/plugins/pad/build.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +echo ----------------------- +echo Building PAD plugins... +echo ----------------------- + +curdir=`pwd` + +cd ${curdir}/PADwin +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/zeropad +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi diff --git a/plugins/pad/zeropad/Makefile.am b/plugins/pad/zeropad/Makefile.am new file mode 100644 index 0000000..1c89d46 --- /dev/null +++ b/plugins/pad/zeropad/Makefile.am @@ -0,0 +1,29 @@ +# Create a shared library libZeroPAD +AUTOMAKE_OPTIONS = foreign +noinst_LIBRARIES = libZeroPAD.a + +libZeroPAD_a_CXXFLAGS = $(shell pkg-config --cflags gtk+-2.0) +libZeroPAD_a_CFLAGS = $(shell pkg-config --cflags gtk+-2.0) + +if X86_64 +libZeroPAD_a_CXXFLAGS += -fPIC +libZeroPAD_a_CFLAGS += -fPIC +endif + +# Create a shared object by faking an exe (thanks to ODE makefiles) +traplibdir=$(prefix) + +if DEBUGBUILD +preext=d +endif + +EXEEXT=$(preext)@so_ext@ + +traplib_PROGRAMS=libZeroPAD +libZeroPAD_SOURCES= +libZeroPAD_DEPENDENCIES = libZeroPAD.a +libZeroPAD_LDFLAGS= @SHARED_LDFLAGS@ +libZeroPAD_LDFLAGS+=-Wl,-soname,@ZEROPAD_SONAME@ +libZeroPAD_LDADD=$(libZeroPAD_a_OBJECTS) + +libZeroPAD_a_SOURCES = zeropad.cpp linux.cpp support.c interface.c \ No newline at end of file diff --git a/plugins/pad/zeropad/PS2Edefs.h b/plugins/pad/zeropad/PS2Edefs.h new file mode 100644 index 0000000..3e97070 --- /dev/null +++ b/plugins/pad/zeropad/PS2Edefs.h @@ -0,0 +1,827 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits) +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// call to give a hint to the PAD plugin to query for the keyboard state. A +// good plugin will query the OS for keyboard state ONLY in this function. +// This function is necessary when multithreading because otherwise +// the PAD plugin can get into deadlocks with the thread that really owns +// the window (and input). Note that PADupdate can be called from a different +// thread than the other functions, so mutex or other multithreading primitives +// have to be added to maintain data integrity. +void CALLBACK PADupdate(int pad); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgetLastTag)(u64* ptag); // returns the last tag processed (64 bits) +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); +typedef void (CALLBACK* _PADupdate)(int pad); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgetLastTag GSgetLastTag; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; +_PADupdate PAD1update; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; +_PADupdate PAD2update; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/pad/zeropad/PS2Etypes.h b/plugins/pad/zeropad/PS2Etypes.h new file mode 100644 index 0000000..dd1c67b --- /dev/null +++ b/plugins/pad/zeropad/PS2Etypes.h @@ -0,0 +1,75 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) && !defined(__LINUX__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_WIN32) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#if defined(__x86_64__) +typedef u64 uptr; +#else +typedef u32 uptr; +#endif + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/pad/zeropad/Windows/ZeroPAD.def b/plugins/pad/zeropad/Windows/ZeroPAD.def new file mode 100644 index 0000000..e853baa --- /dev/null +++ b/plugins/pad/zeropad/Windows/ZeroPAD.def @@ -0,0 +1,17 @@ +LIBRARY "ZeroPAD" + +EXPORTS + PS2EgetLibType @1 + PS2EgetLibName @2 + PS2EgetLibVersion2 @3 + PADinit @7 + PADshutdown @8 + PADopen @9 + PADclose @10 + PADkeyEvent @11 + PADstartPoll @12 + PADpoll @13 + PADquery @16 + PADconfigure @17 + PADtest @18 + PADabout @19 diff --git a/plugins/pad/zeropad/Windows/ZeroPAD.rc b/plugins/pad/zeropad/Windows/ZeroPAD.rc new file mode 100644 index 0000000..6514638 --- /dev/null +++ b/plugins/pad/zeropad/Windows/ZeroPAD.rc @@ -0,0 +1,136 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Sys. Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 3, 1, 443, 266 +STYLE DS_SETFONT | WS_CAPTION | WS_SYSMENU +CAPTION "Pad Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + PUSHBUTTON "OK",IDOK,320,244,56,18,NOT WS_TABSTOP + PUSHBUTTON "Cancel",IDCANCEL,384,244,56,17,NOT WS_TABSTOP + EDITTEXT IDC_ERIGHT,219,31,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Start",IDC_START,219,17,86,15,NOT WS_TABSTOP,WS_EX_TRANSPARENT + EDITTEXT IDC_ER2,129,31,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP,WS_EX_TRANSPARENT + PUSHBUTTON "Select",IDC_SELECT,129,17,86,15,NOT WS_TABSTOP,WS_EX_TRANSPARENT + EDITTEXT IDC_ECIRCLE,340,214,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Cross",IDC2_CROSS,340,199,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ETRIANGLE,340,185,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Square",IDC_SQUARE,340,170,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESQUARE,340,155,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Circle",IDC_CIRCLE,340,140,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ECROSS,340,125,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Triangle",IDC_TRI,340,111,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ER3,340,96,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "R2",IDC_R2,340,81,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESELECT,340,67,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "R1",IDC_R1,340,52,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL2,5,214,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Down",IDC_DOWN,5,199,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EUP,5,185,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Right",IDC_RIGHT,5,170,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL1,5,155,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Left",IDC_LEFT,5,140,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ELEFT,5,125,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "Up",IDC_UP,5,111,86,15,NOT WS_TABSTOP + EDITTEXT IDC_EL3,5,96,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "L2",IDC_L2,5,81,86,15,NOT WS_TABSTOP + EDITTEXT IDC_ESTART,5,67,86,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + PUSHBUTTON "L1",IDC_L1,5,52,86,15,NOT WS_TABSTOP + CONTROL 112,IDC_STATIC,"Static",SS_BITMAP | SS_SUNKEN,94,47,242,183,WS_EX_TRANSPARENT + CONTROL "Tab1",IDC_TABC,"SysTabControl32",0x0,0,0,431,240 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + BOTTOMMARGIN, 265 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral (Sys. Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Spanish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Spanish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/pad/zeropad/Windows/ZeroPAD.vcproj b/plugins/pad/zeropad/Windows/ZeroPAD.vcproj new file mode 100644 index 0000000..c67a988 --- /dev/null +++ b/plugins/pad/zeropad/Windows/ZeroPAD.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/zeropad/Windows/ZeroPAD_2005.vcproj b/plugins/pad/zeropad/Windows/ZeroPAD_2005.vcproj new file mode 100644 index 0000000..dac7e0e --- /dev/null +++ b/plugins/pad/zeropad/Windows/ZeroPAD_2005.vcproj @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/zeropad/Windows/ZeroPAD_2005_x64.vcproj b/plugins/pad/zeropad/Windows/ZeroPAD_2005_x64.vcproj new file mode 100644 index 0000000..1a2e54f --- /dev/null +++ b/plugins/pad/zeropad/Windows/ZeroPAD_2005_x64.vcproj @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/pad/zeropad/Windows/resource.h b/plugins/pad/zeropad/Windows/resource.h new file mode 100644 index 0000000..eec9db5 --- /dev/null +++ b/plugins/pad/zeropad/Windows/resource.h @@ -0,0 +1,70 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ZeroPAD.rc +// +#define IDD_DIALOG1 110 +#define IDB_BITMAP1 112 +#define IDC_EL3 1012 +#define IDC_L2 1013 +#define IDC_ER3 1014 +#define IDC_R2 1015 +#define IDC_ESTART 1016 +#define IDC_L1 1017 +#define IDC_ESELECT 1018 +#define IDC_R1 1019 +#define IDC_ECROSS 1020 +#define IDC_TRI 1021 +#define IDC_ESQUARE 1022 +#define IDC_CIRCLE 1023 +#define IDC_ECIRCLE 1024 +#define IDC2_CROSS 1025 +#define IDC_ETRIANGLE 1026 +#define IDC_SQUARE 1027 +#define IDC_ER2 1028 +#define IDC_SELECT 1029 +#define IDC_ER1 1030 +#define IDC_L3 1031 +#define IDC_EDOWN 1032 +#define IDC_R3 1033 +#define IDC_ERIGHT 1034 +#define IDC_START 1035 +#define IDC_ELEFT 1036 +#define IDC_UP 1037 +#define IDC_EUP 1038 +#define IDC_RIGHT 1039 +#define IDC_EL2 1040 +#define IDC_DOWN 1041 +#define IDC_EL1 1042 +#define IDC_LEFT 1043 +#define IDC_TABC 1044 +#define IDC_LAX 1045 +#define IDC_LAY 1046 +#define IDC_RAX 1047 +#define IDC_RAY 1048 +#define IDC_SCROSS 1049 +#define IDC_CHECK1 1050 +#define IDC_LOG 1050 +#define IDC_SCIRCLE 1051 +#define IDC_SSQUARE 1052 +#define IDC_STRIANGLE 1053 +#define IDC_SL3 1054 +#define IDC_SUP 1055 +#define IDC_SDOWN 1056 +#define IDC_SLEFT 1057 +#define IDC_SRIGHT 1058 +#define IDC_SR3 1059 +#define IDC_SL1 1060 +#define IDC_SL2 1061 +#define IDC_SR1 1062 +#define IDC_SR2 1063 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 114 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1051 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/pad/zeropad/Windows/win.cpp b/plugins/pad/zeropad/Windows/win.cpp new file mode 100644 index 0000000..17e4f37 --- /dev/null +++ b/plugins/pad/zeropad/Windows/win.cpp @@ -0,0 +1,315 @@ +/* ZeroPAD + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "resource.h" +#include "zeropad.h" + +#include +using namespace std; + +HINSTANCE hInst=NULL; + +void SaveConfig() +{ + char *szTemp; + char szIniFile[256], szValue[256], szProf[256]; + int i, j; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\zeropad.ini"); + + for (j=0; j<2; j++) { + for (i=0; i= 0x1000 && key < 0x2000) + { + sprintf (buff, "J%d_%d", (key & 0xfff) / 0x100, (key & 0xff) + 1); + } + else if (key >= 0x2000 && key < 0x3000) + { + static const char name[][4] = { "MIN", "MAX" }; + const int axis = (key & 0xff); + sprintf (buff, "J%d_AXIS%d_%s", (key & 0xfff) / 0x100, axis / 2, name[axis % 2]); + if (index >= 17 && index <= 20) + buff[strlen (buff) -4] = '\0'; + } + else if (key >= 0x3000 && key < 0x4000) + { + static const char name[][7] = { "FOWARD", "RIGHT", "BACK", "LEFT" }; + const int pov = (key & 0xff); + sprintf (buff, "J%d_POV%d_%s", (key & 0xfff) / 0x100, pov /4, name[pov % 4]); + } + + return buff; +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + HWND hWC; + TCITEM tcI; + int i,key, numkeys; + u8* pkeyboard; + static int disabled=0; + static int padn=0; + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + padn = 0; + if (conf.log) CheckDlgButton(hW, IDC_LOG, TRUE); + + for (i=0; i + + +void +OnConf_Key (GtkButton *button, + gpointer user_data); + +void +OnConf_Pad1 (GtkButton *button, + gpointer user_data); + +void +OnConf_Pad2 (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/pad/zeropad/compile b/plugins/pad/zeropad/compile new file mode 100644 index 0000000..973c773 --- /dev/null +++ b/plugins/pad/zeropad/compile @@ -0,0 +1 @@ +link /usr/share/automake-1.9/compile \ No newline at end of file diff --git a/plugins/pad/zeropad/configure.ac b/plugins/pad/zeropad/configure.ac new file mode 100644 index 0000000..7a452c4 --- /dev/null +++ b/plugins/pad/zeropad/configure.ac @@ -0,0 +1,102 @@ +AC_INIT(ZeroPAD,0.1,zerofrog@gmail.com) + +AM_INIT_AUTOMAKE(ZeroPAD,0.1) + +AC_PROG_CC([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CXX([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) +AC_PROG_CPP([gcc g++ cl KCC CC cxx cc++ xlC aCC c++]) + +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl necessary for compiling assembly +AM_PROG_AS + +ZEROPAD_CURRENT=0 +ZEROPAD_REVISION=1 +ZEROPAD_AGE=0 +ZEROPAD_SONAME=libZeroPAD.so.[$ZEROPAD_CURRENT].[$ZEROPAD_REVISION].[$ZEROPAD_AGE] +ZEROPAD_RELEASE=[$ZEROPAD_CURRENT].[$ZEROPAD_REVISION].[$ZEROPAD_AGE] + +AC_SUBST(ZEROPAD_CURRENT) +AC_SUBST(ZEROPAD_REVISION) +AC_SUBST(ZEROPAD_AGE) +AC_SUBST(ZEROPAD_RELEASE) +AC_SUBST(ZEROPAD_SONAME) + +CFLAGS= +CPPFLAGS= +CXXFLAGS= + +dnl Check for debug build +AC_MSG_CHECKING(debug build) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [debug build]), + debug=$enableval,debug=no) +if test "x$debug" == xyes +then + AC_DEFINE(_DEBUG,1,[_DEBUG]) + CFLAGS+="-g " + CPPFLAGS+="-g " + CXXFLAGS+="-g " +else + AC_DEFINE(NDEBUG,1,[NDEBUG]) + CFLAGS+="-O2 -fomit-frame-pointer " + CPPFLAGS+="-O2 -fomit-frame-pointer " + CXXFLAGS+="-O2 -fomit-frame-pointer " +fi +AM_CONDITIONAL(DEBUGBUILD, test x$debug = xyes) +AC_MSG_RESULT($debug) + +dnl Check for 64bit CPU +AC_MSG_CHECKING(for a x86-64 CPU) +dnl if test "$build_os" == "target_os" +dnl then +AC_TRY_RUN([ +int main() +{ +int a = 0; +int*pa = &a; +asm(".intel_syntax\n" + "mov %%rax, %0\n" + "mov %%eax, [%%rax]\n" + ".att_syntax\n" + : : "r"(pa) : "%rax"); +return 0; +} +],cpu64=yes,cpu64=no,) +dnl else +dnl cpu64=no +dnl fi +if test "x$cpu64" == xyes +then +AC_DEFINE(__x86_64__,1,[__x86_64__]) +fi +AC_MSG_RESULT($cpu64) +AM_CONDITIONAL(X86_64, test x$cpu64 = xyes) + +AC_CHECK_FUNCS([ _aligned_malloc _aligned_free ], AC_DEFINE(HAVE_ALIGNED_MALLOC)) + +dnl gtk +AC_MSG_CHECKING(gtk2+) +AC_CHECK_PROG(GTK_CONFIG, pkg-config, pkg-config) +LIBS+=$(pkg-config --libs gtk+-2.0) + +dnl bindir = pcsx2exe + +dnl assuming linux environment +so_ext=".so.$ZEROPAD_RELEASE" +SHARED_LDFLAGS="-shared" +AC_SUBST(so_ext) +AC_SUBST(SHARED_LDFLAGS) + +AC_CHECK_LIB(stdc++,main,[LIBS="$LIBS -lstdc++"]) +AC_CHECK_LIB(dl,main,[LIBS="$LIBS -ldl"]) + + +AC_OUTPUT([ + Makefile + ]) + +echo "Configuration:" +echo " Debug build? $debug" +echo " x86-64 build? $cpu64" \ No newline at end of file diff --git a/plugins/pad/zeropad/depcomp b/plugins/pad/zeropad/depcomp new file mode 100644 index 0000000..88b3a13 --- /dev/null +++ b/plugins/pad/zeropad/depcomp @@ -0,0 +1,529 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/pad/zeropad/install-sh b/plugins/pad/zeropad/install-sh new file mode 100644 index 0000000..4d4a951 --- /dev/null +++ b/plugins/pad/zeropad/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/pad/zeropad/interface.c b/plugins/pad/zeropad/interface.c new file mode 100644 index 0000000..0c832ab --- /dev/null +++ b/plugins/pad/zeropad/interface.c @@ -0,0 +1,570 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + const gchar *authors[] = { + "Author: zerofrog(@gmail.com)", + "Thanks to:", + " linuzappz ", + "florin sasu ", + "and SSSPSXPad, TwinPad authors", + NULL + }; + /* TRANSLATORS: Replace this string with your names, one name per line. */ + gchar *translators = _("translator-credits"); + + About = gtk_about_dialog_new (); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (About), VERSION); + gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (About), _("ZeroPAD")); + gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (About), authors); + gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG (About), translators); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (About, About, "About"); + + return About; +} + +GtkWidget* +create_Conf (void) +{ + GtkWidget *Conf; + GtkWidget *dialog_vbox1; + GtkWidget *vbox1; + GtkWidget *frame1; + GtkWidget *alignment1; + GtkWidget *hbox1; + GtkWidget *PAD1; + GSList *PAD1_group = NULL; + GtkWidget *PAD2; + GtkWidget *label2; + GtkWidget *fixed1; + GtkWidget *eL2; + GtkWidget *eL1; + GtkWidget *eSelect; + GtkWidget *eStart; + GtkWidget *eUp; + GtkWidget *eRight; + GtkWidget *eLeft; + GtkWidget *eDown; + GtkWidget *eR2; + GtkWidget *eR1; + GtkWidget *eAnalog; + GtkWidget *eSquare; + GtkWidget *eTriangle; + GtkWidget *eCircle; + GtkWidget *eCross; + GtkWidget *eR3; + GtkWidget *eL3; + GtkWidget *eRx; + GtkWidget *eLx; + GtkWidget *eRy; + GtkWidget *eLy; + GtkWidget *Select; + GtkWidget *L1; + GtkWidget *Left; + GtkWidget *Down; + GtkWidget *Analog; + GtkWidget *R2; + GtkWidget *Start; + GtkWidget *R1; + GtkWidget *Cross; + GtkWidget *Triangle; + GtkWidget *Circle; + GtkWidget *Right; + GtkWidget *Square; + GtkWidget *R3; + GtkWidget *Lx; + GtkWidget *Rx; + GtkWidget *Ly; + GtkWidget *Ry; + GtkWidget *label3; + GtkWidget *L3; + GtkWidget *Up; + GtkWidget *L2; + GtkWidget *dialog_action_area1; + GtkWidget *cancelbutton1; + GtkWidget *okbutton1; + + Conf = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (Conf), _("ZeroPAD Configuration Dialog")); + gtk_window_set_type_hint (GTK_WINDOW (Conf), GDK_WINDOW_TYPE_HINT_DIALOG); + + dialog_vbox1 = GTK_DIALOG (Conf)->vbox; + gtk_widget_show (dialog_vbox1); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1, TRUE, TRUE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (vbox1), frame1, FALSE, FALSE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_NONE); + + alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_show (alignment1); + gtk_container_add (GTK_CONTAINER (frame1), alignment1); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment1), 0, 0, 12, 0); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (alignment1), hbox1); + + PAD1 = gtk_radio_button_new_with_mnemonic (NULL, _("PAD1")); + gtk_widget_show (PAD1); + gtk_box_pack_start (GTK_BOX (hbox1), PAD1, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (PAD1), PAD1_group); + PAD1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (PAD1)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (PAD1), TRUE); + + PAD2 = gtk_radio_button_new_with_mnemonic (NULL, _("PAD2")); + gtk_widget_show (PAD2); + gtk_box_pack_start (GTK_BOX (hbox1), PAD2, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (PAD2), PAD1_group); + PAD1_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (PAD2)); + + label2 = gtk_label_new (_("Choose PAD to modify")); + gtk_widget_show (label2); + gtk_frame_set_label_widget (GTK_FRAME (frame1), label2); + gtk_label_set_use_markup (GTK_LABEL (label2), TRUE); + + fixed1 = gtk_fixed_new (); + gtk_widget_show (fixed1); + gtk_box_pack_start (GTK_BOX (vbox1), fixed1, TRUE, TRUE, 0); + + eL2 = gtk_entry_new (); + gtk_widget_show (eL2); + gtk_fixed_put (GTK_FIXED (fixed1), eL2, 64, 40); + gtk_widget_set_size_request (eL2, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eL2), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eL2), 8226); + + eL1 = gtk_entry_new (); + gtk_widget_show (eL1); + gtk_fixed_put (GTK_FIXED (fixed1), eL1, 64, 104); + gtk_widget_set_size_request (eL1, 64, 24); + gtk_entry_set_invisible_char (GTK_ENTRY (eL1), 8226); + + eSelect = gtk_entry_new (); + gtk_widget_show (eSelect); + gtk_fixed_put (GTK_FIXED (fixed1), eSelect, 168, 64); + gtk_widget_set_size_request (eSelect, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eSelect), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eSelect), 8226); + + eStart = gtk_entry_new (); + gtk_widget_show (eStart); + gtk_fixed_put (GTK_FIXED (fixed1), eStart, 280, 64); + gtk_widget_set_size_request (eStart, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eStart), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eStart), 8226); + + eUp = gtk_entry_new (); + gtk_widget_show (eUp); + gtk_fixed_put (GTK_FIXED (fixed1), eUp, 64, 168); + gtk_widget_set_size_request (eUp, 64, 24); + gtk_entry_set_invisible_char (GTK_ENTRY (eUp), 8226); + + eRight = gtk_entry_new (); + gtk_widget_show (eRight); + gtk_fixed_put (GTK_FIXED (fixed1), eRight, 128, 208); + gtk_widget_set_size_request (eRight, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eRight), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eRight), 8226); + + eLeft = gtk_entry_new (); + gtk_widget_show (eLeft); + gtk_fixed_put (GTK_FIXED (fixed1), eLeft, 0, 208); + gtk_widget_set_size_request (eLeft, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eLeft), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eLeft), 8226); + + eDown = gtk_entry_new (); + gtk_widget_show (eDown); + gtk_fixed_put (GTK_FIXED (fixed1), eDown, 64, 256); + gtk_widget_set_size_request (eDown, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eDown), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eDown), 8226); + + eR2 = gtk_entry_new (); + gtk_widget_show (eR2); + gtk_fixed_put (GTK_FIXED (fixed1), eR2, 368, 32); + gtk_widget_set_size_request (eR2, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eR2), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eR2), 8226); + + eR1 = gtk_entry_new (); + gtk_widget_show (eR1); + gtk_fixed_put (GTK_FIXED (fixed1), eR1, 368, 104); + gtk_widget_set_size_request (eR1, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eR1), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eR1), 8226); + + eAnalog = gtk_entry_new (); + gtk_widget_show (eAnalog); + gtk_fixed_put (GTK_FIXED (fixed1), eAnalog, 224, 128); + gtk_widget_set_size_request (eAnalog, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eAnalog), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eAnalog), 8226); + + eSquare = gtk_entry_new (); + gtk_widget_show (eSquare); + gtk_fixed_put (GTK_FIXED (fixed1), eSquare, 304, 208); + gtk_widget_set_size_request (eSquare, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eSquare), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eSquare), 8226); + + eTriangle = gtk_entry_new (); + gtk_widget_show (eTriangle); + gtk_fixed_put (GTK_FIXED (fixed1), eTriangle, 368, 168); + gtk_widget_set_size_request (eTriangle, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eTriangle), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eTriangle), 8226); + + eCircle = gtk_entry_new (); + gtk_widget_show (eCircle); + gtk_fixed_put (GTK_FIXED (fixed1), eCircle, 432, 208); + gtk_widget_set_size_request (eCircle, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eCircle), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eCircle), 8226); + + eCross = gtk_entry_new (); + gtk_widget_show (eCross); + gtk_fixed_put (GTK_FIXED (fixed1), eCross, 368, 256); + gtk_widget_set_size_request (eCross, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eCross), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eCross), 8226); + + eR3 = gtk_entry_new (); + gtk_widget_show (eR3); + gtk_fixed_put (GTK_FIXED (fixed1), eR3, 272, 272); + gtk_widget_set_size_request (eR3, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eR3), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eR3), 8226); + + eL3 = gtk_entry_new (); + gtk_widget_show (eL3); + gtk_fixed_put (GTK_FIXED (fixed1), eL3, 176, 272); + gtk_widget_set_size_request (eL3, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eL3), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eL3), 8226); + + eRx = gtk_entry_new (); + gtk_widget_show (eRx); + gtk_fixed_put (GTK_FIXED (fixed1), eRx, 272, 352); + gtk_widget_set_size_request (eRx, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eRx), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eRx), 8226); + + eLx = gtk_entry_new (); + gtk_widget_show (eLx); + gtk_fixed_put (GTK_FIXED (fixed1), eLx, 176, 352); + gtk_widget_set_size_request (eLx, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eLx), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eLx), 8226); + + eRy = gtk_entry_new (); + gtk_widget_show (eRy); + gtk_fixed_put (GTK_FIXED (fixed1), eRy, 272, 416); + gtk_widget_set_size_request (eRy, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eRy), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eRy), 8226); + + eLy = gtk_entry_new (); + gtk_widget_show (eLy); + gtk_fixed_put (GTK_FIXED (fixed1), eLy, 176, 416); + gtk_widget_set_size_request (eLy, 64, 24); + gtk_editable_set_editable (GTK_EDITABLE (eLy), FALSE); + gtk_entry_set_invisible_char (GTK_ENTRY (eLy), 8226); + + Select = gtk_button_new_with_mnemonic (_("Select")); + gtk_widget_show (Select); + gtk_fixed_put (GTK_FIXED (fixed1), Select, 168, 32); + gtk_widget_set_size_request (Select, 64, 32); + + L1 = gtk_button_new_with_mnemonic (_("L1")); + gtk_widget_show (L1); + gtk_fixed_put (GTK_FIXED (fixed1), L1, 64, 72); + gtk_widget_set_size_request (L1, 64, 32); + + Left = gtk_button_new_with_mnemonic (_("Left")); + gtk_widget_show (Left); + gtk_fixed_put (GTK_FIXED (fixed1), Left, 0, 176); + gtk_widget_set_size_request (Left, 64, 32); + + Down = gtk_button_new_with_mnemonic (_("Down")); + gtk_widget_show (Down); + gtk_fixed_put (GTK_FIXED (fixed1), Down, 64, 224); + gtk_widget_set_size_request (Down, 64, 32); + + Analog = gtk_button_new_with_mnemonic (_("Analog")); + gtk_widget_show (Analog); + gtk_fixed_put (GTK_FIXED (fixed1), Analog, 224, 96); + gtk_widget_set_size_request (Analog, 64, 32); + + R2 = gtk_button_new_with_mnemonic (_("R2")); + gtk_widget_show (R2); + gtk_fixed_put (GTK_FIXED (fixed1), R2, 368, 0); + gtk_widget_set_size_request (R2, 64, 32); + + Start = gtk_button_new_with_mnemonic (_("Start")); + gtk_widget_show (Start); + gtk_fixed_put (GTK_FIXED (fixed1), Start, 280, 32); + gtk_widget_set_size_request (Start, 64, 32); + + R1 = gtk_button_new_with_mnemonic (_("R1")); + gtk_widget_show (R1); + gtk_fixed_put (GTK_FIXED (fixed1), R1, 368, 72); + gtk_widget_set_size_request (R1, 64, 32); + + Cross = gtk_button_new_with_mnemonic (_("Cross")); + gtk_widget_show (Cross); + gtk_fixed_put (GTK_FIXED (fixed1), Cross, 368, 224); + gtk_widget_set_size_request (Cross, 64, 32); + + Triangle = gtk_button_new_with_mnemonic (_("Triangle")); + gtk_widget_show (Triangle); + gtk_fixed_put (GTK_FIXED (fixed1), Triangle, 368, 136); + gtk_widget_set_size_request (Triangle, 64, 32); + + Circle = gtk_button_new_with_mnemonic (_("Circle")); + gtk_widget_show (Circle); + gtk_fixed_put (GTK_FIXED (fixed1), Circle, 432, 176); + gtk_widget_set_size_request (Circle, 64, 32); + + Right = gtk_button_new_with_mnemonic (_("Right")); + gtk_widget_show (Right); + gtk_fixed_put (GTK_FIXED (fixed1), Right, 128, 176); + gtk_widget_set_size_request (Right, 64, 32); + + Square = gtk_button_new_with_mnemonic (_("Square")); + gtk_widget_show (Square); + gtk_fixed_put (GTK_FIXED (fixed1), Square, 304, 176); + gtk_widget_set_size_request (Square, 64, 32); + + R3 = gtk_button_new_with_mnemonic (_("R3")); + gtk_widget_show (R3); + gtk_fixed_put (GTK_FIXED (fixed1), R3, 272, 240); + gtk_widget_set_size_request (R3, 64, 32); + + Lx = gtk_button_new_with_mnemonic (_("Lx")); + gtk_widget_show (Lx); + gtk_fixed_put (GTK_FIXED (fixed1), Lx, 176, 320); + gtk_widget_set_size_request (Lx, 64, 32); + + Rx = gtk_button_new_with_mnemonic (_("Rx")); + gtk_widget_show (Rx); + gtk_fixed_put (GTK_FIXED (fixed1), Rx, 272, 320); + gtk_widget_set_size_request (Rx, 64, 32); + + Ly = gtk_button_new_with_mnemonic (_("Ly")); + gtk_widget_show (Ly); + gtk_fixed_put (GTK_FIXED (fixed1), Ly, 176, 384); + gtk_widget_set_size_request (Ly, 64, 32); + + Ry = gtk_button_new_with_mnemonic (_("Ry")); + gtk_widget_show (Ry); + gtk_fixed_put (GTK_FIXED (fixed1), Ry, 272, 384); + gtk_widget_set_size_request (Ry, 64, 32); + + label3 = gtk_label_new (_("Analog Controls (move mouse or analog joystick to select)")); + gtk_widget_show (label3); + gtk_fixed_put (GTK_FIXED (fixed1), label3, 56, 296); + gtk_widget_set_size_request (label3, 408, 16); + gtk_label_set_single_line_mode (GTK_LABEL (label3), TRUE); + + L3 = gtk_button_new_with_mnemonic (_("L3")); + gtk_widget_show (L3); + gtk_fixed_put (GTK_FIXED (fixed1), L3, 176, 240); + gtk_widget_set_size_request (L3, 64, 32); + + Up = gtk_button_new_with_mnemonic (_("Up")); + gtk_widget_show (Up); + gtk_fixed_put (GTK_FIXED (fixed1), Up, 64, 136); + gtk_widget_set_size_request (Up, 64, 32); + + L2 = gtk_button_new_with_mnemonic (_("L2")); + gtk_widget_show (L2); + gtk_fixed_put (GTK_FIXED (fixed1), L2, 64, 8); + gtk_widget_set_size_request (L2, 64, 32); + + dialog_action_area1 = GTK_DIALOG (Conf)->action_area; + gtk_widget_show (dialog_action_area1); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END); + + cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (cancelbutton1); + gtk_dialog_add_action_widget (GTK_DIALOG (Conf), cancelbutton1, GTK_RESPONSE_CANCEL); + GTK_WIDGET_SET_FLAGS (cancelbutton1, GTK_CAN_DEFAULT); + + okbutton1 = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (okbutton1); + gtk_dialog_add_action_widget (GTK_DIALOG (Conf), okbutton1, GTK_RESPONSE_OK); + GTK_WIDGET_SET_FLAGS (okbutton1, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) PAD1, "clicked", + G_CALLBACK (OnConf_Pad1), + NULL); + g_signal_connect ((gpointer) PAD2, "clicked", + G_CALLBACK (OnConf_Pad2), + NULL); + g_signal_connect ((gpointer) Select, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) L1, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Left, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Down, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Analog, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) R2, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Start, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) R1, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Cross, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Triangle, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Circle, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Right, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Square, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) R3, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Lx, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Rx, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Ly, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Ry, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) L3, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) Up, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) L2, "clicked", + G_CALLBACK (OnConf_Key), + NULL); + g_signal_connect ((gpointer) cancelbutton1, "clicked", + G_CALLBACK (OnConf_Cancel), + NULL); + g_signal_connect ((gpointer) okbutton1, "clicked", + G_CALLBACK (OnConf_Ok), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (Conf, Conf, "Conf"); + GLADE_HOOKUP_OBJECT_NO_REF (Conf, dialog_vbox1, "dialog_vbox1"); + GLADE_HOOKUP_OBJECT (Conf, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT (Conf, frame1, "frame1"); + GLADE_HOOKUP_OBJECT (Conf, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (Conf, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (Conf, PAD1, "PAD1"); + GLADE_HOOKUP_OBJECT (Conf, PAD2, "PAD2"); + GLADE_HOOKUP_OBJECT (Conf, label2, "label2"); + GLADE_HOOKUP_OBJECT (Conf, fixed1, "fixed1"); + GLADE_HOOKUP_OBJECT (Conf, eL2, "eL2"); + GLADE_HOOKUP_OBJECT (Conf, eL1, "eL1"); + GLADE_HOOKUP_OBJECT (Conf, eSelect, "eSelect"); + GLADE_HOOKUP_OBJECT (Conf, eStart, "eStart"); + GLADE_HOOKUP_OBJECT (Conf, eUp, "eUp"); + GLADE_HOOKUP_OBJECT (Conf, eRight, "eRight"); + GLADE_HOOKUP_OBJECT (Conf, eLeft, "eLeft"); + GLADE_HOOKUP_OBJECT (Conf, eDown, "eDown"); + GLADE_HOOKUP_OBJECT (Conf, eR2, "eR2"); + GLADE_HOOKUP_OBJECT (Conf, eR1, "eR1"); + GLADE_HOOKUP_OBJECT (Conf, eAnalog, "eAnalog"); + GLADE_HOOKUP_OBJECT (Conf, eSquare, "eSquare"); + GLADE_HOOKUP_OBJECT (Conf, eTriangle, "eTriangle"); + GLADE_HOOKUP_OBJECT (Conf, eCircle, "eCircle"); + GLADE_HOOKUP_OBJECT (Conf, eCross, "eCross"); + GLADE_HOOKUP_OBJECT (Conf, eR3, "eR3"); + GLADE_HOOKUP_OBJECT (Conf, eL3, "eL3"); + GLADE_HOOKUP_OBJECT (Conf, eRx, "eRx"); + GLADE_HOOKUP_OBJECT (Conf, eLx, "eLx"); + GLADE_HOOKUP_OBJECT (Conf, eRy, "eRy"); + GLADE_HOOKUP_OBJECT (Conf, eLy, "eLy"); + GLADE_HOOKUP_OBJECT (Conf, Select, "Select"); + GLADE_HOOKUP_OBJECT (Conf, L1, "L1"); + GLADE_HOOKUP_OBJECT (Conf, Left, "Left"); + GLADE_HOOKUP_OBJECT (Conf, Down, "Down"); + GLADE_HOOKUP_OBJECT (Conf, Analog, "Analog"); + GLADE_HOOKUP_OBJECT (Conf, R2, "R2"); + GLADE_HOOKUP_OBJECT (Conf, Start, "Start"); + GLADE_HOOKUP_OBJECT (Conf, R1, "R1"); + GLADE_HOOKUP_OBJECT (Conf, Cross, "Cross"); + GLADE_HOOKUP_OBJECT (Conf, Triangle, "Triangle"); + GLADE_HOOKUP_OBJECT (Conf, Circle, "Circle"); + GLADE_HOOKUP_OBJECT (Conf, Right, "Right"); + GLADE_HOOKUP_OBJECT (Conf, Square, "Square"); + GLADE_HOOKUP_OBJECT (Conf, R3, "R3"); + GLADE_HOOKUP_OBJECT (Conf, Lx, "Lx"); + GLADE_HOOKUP_OBJECT (Conf, Rx, "Rx"); + GLADE_HOOKUP_OBJECT (Conf, Ly, "Ly"); + GLADE_HOOKUP_OBJECT (Conf, Ry, "Ry"); + GLADE_HOOKUP_OBJECT (Conf, label3, "label3"); + GLADE_HOOKUP_OBJECT (Conf, L3, "L3"); + GLADE_HOOKUP_OBJECT (Conf, Up, "Up"); + GLADE_HOOKUP_OBJECT (Conf, L2, "L2"); + GLADE_HOOKUP_OBJECT_NO_REF (Conf, dialog_action_area1, "dialog_action_area1"); + GLADE_HOOKUP_OBJECT (Conf, cancelbutton1, "cancelbutton1"); + GLADE_HOOKUP_OBJECT (Conf, okbutton1, "okbutton1"); + + return Conf; +} + diff --git a/plugins/pad/zeropad/interface.h b/plugins/pad/zeropad/interface.h new file mode 100644 index 0000000..3672165 --- /dev/null +++ b/plugins/pad/zeropad/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_About (void); +GtkWidget* create_Conf (void); diff --git a/plugins/pad/zeropad/linux.cpp b/plugins/pad/zeropad/linux.cpp new file mode 100644 index 0000000..e402479 --- /dev/null +++ b/plugins/pad/zeropad/linux.cpp @@ -0,0 +1,370 @@ +/* ZeroPAD + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "zeropad.h" + +extern "C" { +#include "interface.h" +#include "support.h" +#include "callbacks.h" +} + +Display *GSdsp; +static pthread_spinlock_t s_mutexStatus; +static u32 s_keyPress[2], s_keyRelease[2]; +extern u16 status[2]; + +extern string s_strIniPath; + +void SaveConfig() +{ + int i, j; + FILE *f; + char cfg[255]; + + strcpy(cfg, s_strIniPath.c_str()); + f = fopen(cfg,"w"); + if (f == NULL) { + printf("ZeroPAD: failed to save ini %s\n", s_strIniPath.c_str()); + return; + } + + for (j=0; j<2; j++) { + for (i=0; i<16; i++) { + fprintf(f, "[%d][%d] = 0x%lx\n", j, i, conf.keys[j][i]); + } + } + fprintf(f, "log = %d\n", conf.log); + fclose(f); +} + +static char* s_pGuiKeyMap[] = { "L2", "R2", "L1", "R1", + "Triangle", "Circle", "Cross", "Square", + "Select", "L3", "R3", "Start", + "Up", "Right", "Down", "Left", + "Lx", "Rx", "Ly", "Ry" }; + +string GetLabelFromButton(const char* buttonname) +{ + string label = "e"; + label += buttonname; + return label; +} + +void LoadConfig() { + FILE *f; + char str[256]; + char cfg[255]; + int i, j; + + memset(&conf, 0, sizeof(conf)); + conf.keys[0][0] = XK_a; // L2 + conf.keys[0][1] = XK_semicolon; // R2 + conf.keys[0][2] = XK_w; // L1 + conf.keys[0][3] = XK_p; // R1 + conf.keys[0][4] = XK_i; // TRIANGLE + conf.keys[0][5] = XK_l; // CIRCLE + conf.keys[0][6] = XK_k; // CROSS + conf.keys[0][7] = XK_j; // SQUARE + conf.keys[0][8] = XK_v; // SELECT + conf.keys[0][11] = XK_n;// START + conf.keys[0][12] = XK_e; // UP + conf.keys[0][13] = XK_f; // RIGHT + conf.keys[0][14] = XK_d; // DOWN + conf.keys[0][15] = XK_s; // LEFT + conf.log = 0; + + strcpy(cfg, s_strIniPath.c_str()); + f = fopen(cfg, "r"); + if (f == NULL) { + printf("ZeroPAD: failed to load ini %s\n", s_strIniPath.c_str()); + SaveConfig();//save and return + return; + } + + for (j=0; j<2; j++) { + for (i=0; i<16; i++) { + sprintf(str, "[%d][%d] = 0x%%x\n", j, i); + fscanf(f, str, &conf.keys[j][i]); + } + } + fscanf(f, "log = %d\n", &conf.log); + fclose(f); +} + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "GSsoft Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +s32 _PADopen(void *pDsp) +{ + GSdsp = *(Display**)pDsp; + pthread_spin_init(&s_mutexStatus, PTHREAD_PROCESS_PRIVATE); + s_keyPress[0] = s_keyPress[1] = 0; + s_keyRelease[0] = s_keyRelease[1] = 0; + XAutoRepeatOff(GSdsp); + return 0; +} + +void _PADclose() +{ + pthread_spin_destroy(&s_mutexStatus); + XAutoRepeatOn(GSdsp); +} + +void _PADupdate(int pad) +{ + pthread_spin_lock(&s_mutexStatus); + status[pad] |= s_keyRelease[pad]; + status[pad] &= ~s_keyPress[pad]; + s_keyRelease[pad] = 0; + s_keyPress[pad] = 0; + pthread_spin_unlock(&s_mutexStatus); +} + +void CALLBACK PADupdate(int pad) +{ + int i; + XEvent E; + int keyPress=0,keyRelease=0; + KeySym key; + + while (XPending(GSdsp) > 0) { + XNextEvent(GSdsp, &E); + switch (E.type) { + case KeyPress: + //_KeyPress(pad, XLookupKeysym((XKeyEvent *)&E, 0)); break; + key = XLookupKeysym((XKeyEvent *)&E, 0); + for (i=0; itype == GDK_KEY_PRESS) { + *key = ev->key.keyval; + + char* tmp = XKeysymToString(*key); + if (tmp != NULL) + gtk_entry_set_text(GTK_ENTRY(label), tmp); + else + gtk_entry_set_text(GTK_ENTRY(label), "Unknown"); + return; + } + } + } +} + +void OnConf_Pad1(GtkButton *button, gpointer user_data) +{ + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) ) + UpdateConf(0); +} + +void OnConf_Pad2(GtkButton *button, gpointer user_data) +{ + if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) ) + UpdateConf(1); +} + +void OnConf_Ok(GtkButton *button, gpointer user_data) +{ +// conf.analog = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Analog)); + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CALLBACK PADconfigure() { + LoadConfig(); + + Conf = create_Conf(); + +// Analog = lookup_widget(Conf, "GtkCheckButton_Analog"); +// gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Analog), conf.analog); + + UpdateConf(0); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) +{ + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CALLBACK PADabout() { + + About = create_About(); + + gtk_widget_show_all(About); + gtk_main(); +} + +s32 CALLBACK PADtest() { + return 0; +} diff --git a/plugins/pad/zeropad/missing b/plugins/pad/zeropad/missing new file mode 100644 index 0000000..894e786 --- /dev/null +++ b/plugins/pad/zeropad/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2005-06-08.21 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/pad/zeropad/mkinstalldirs b/plugins/pad/zeropad/mkinstalldirs new file mode 100644 index 0000000..259dbfc --- /dev/null +++ b/plugins/pad/zeropad/mkinstalldirs @@ -0,0 +1,158 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2005-06-29.22 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/plugins/pad/zeropad/support.c b/plugins/pad/zeropad/support.c new file mode 100644 index 0000000..00aff29 --- /dev/null +++ b/plugins/pad/zeropad/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/plugins/pad/zeropad/support.h b/plugins/pad/zeropad/support.h new file mode 100644 index 0000000..a32649e --- /dev/null +++ b/plugins/pad/zeropad/support.h @@ -0,0 +1,69 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Standard gettext macros. + */ +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# define Q_(String) g_strip_context ((String), gettext (String)) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define Q_(String) g_strip_context ((String), (String)) +# define N_(String) (String) +#endif + + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/plugins/pad/zeropad/zeropad.cpp b/plugins/pad/zeropad/zeropad.cpp new file mode 100644 index 0000000..1b5a338 --- /dev/null +++ b/plugins/pad/zeropad/zeropad.cpp @@ -0,0 +1,492 @@ +/* ZeroPAD + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "zeropad.h" + +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +#ifdef _DEBUG +char *libraryName = "ZeroPAD (Debug) "; +#else +char *libraryName = "ZeroPAD "; +#endif + +Analog lanalog[2], ranalog[2]; +PADconf conf; + +keyEvent event; + +u16 status[2]; +int pressure; +string s_strIniPath="inis/zeropad.ini"; + +const unsigned char version = PS2E_PAD_VERSION; +const unsigned char revision = 0; +const unsigned char build = 1; // increase that with each version + + +u32 pads=0; +u8 stdpar[2][20] = { {0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; +u8 cmd40[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a}}; +u8 cmd41[2][8] = { {0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a}}; +u8 unk46[2][8] = { {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, + {0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}}; +u8 unk47[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}}; +u8 unk4c[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +u8 unk4d[2][8] = { {0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +u8 cmd4f[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a}}; +u8 stdcfg[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; // 2 & 3 = 0 +u8 stdmode[2][8] = { {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +u8 stdmodel[2][8] = { {0xff, 0x5a, + 0x03, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}, + {0xff, 0x5a, + 0x03, // 03 - dualshock2, 01 - dualshock + 0x02, // number of modes + 0x01, // current mode: 01 - analog, 00 - digital + 0x02, + 0x01, + 0x00}}; + +u8 *buf; +int padID[2]; +int padMode[2]; +int curPad; +int curByte; +int curCmd; +int cmdLen; +int ds2mode = 0; // DS Mode at start +FILE *padLog = NULL; + +int POV(u32 direction, u32 angle){ + if ((direction==0) && (angle>= 0) && (angle< 4500)) return 1;//forward + if ((direction==2) && (angle>= 4500) && (angle<13500)) return 1;//right + if ((direction==1) && (angle>=13500) && (angle<22500)) return 1;//backward + if ((direction==3) && (angle>=22500) && (angle<31500)) return 1;//left + if ((direction==0) && (angle>=31500) && (angle<36000)) return 1;//forward + return 0; +} + +void _KeyPress(int pad, u32 key) +{ + int i; + + for (i=0; i> 8; + stdpar[curPad][3] = status[curPad] & 0xff; + stdpar[curPad][4] = ranalog[curPad].x; + stdpar[curPad][5] = ranalog[curPad].y; + stdpar[curPad][6] = lanalog[curPad].x; + stdpar[curPad][7] = lanalog[curPad].y; + if (padMode[curPad] == 1) cmdLen = 20; + else cmdLen = 4; + button_check2 = stdpar[curPad][2] >> 4; + switch(stdpar[curPad][3]) + { + case 0xBF: // X + stdpar[curPad][14] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][16])); + break; + case 0xDF: // Circle + stdpar[curPad][13] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][17])); + break; + case 0xEF: // Triangle + stdpar[curPad][12] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][19])); + break; + case 0x7F: // Square + stdpar[curPad][15] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][18])); + break; + case 0xFB: // L1 + stdpar[curPad][16] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][26])); + break; + case 0xF7: // R1 + stdpar[curPad][17] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][28])); + break; + case 0xFE: // L2 + stdpar[curPad][18] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][27])); + break; + case 0xFD: // R2 + stdpar[curPad][19] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][29])); + break; + default: + stdpar[curPad][14] = 0x00; // Not pressed + stdpar[curPad][13] = 0x00; // Not pressed + stdpar[curPad][12] = 0x00; // Not pressed + stdpar[curPad][15] = 0x00; // Not pressed + stdpar[curPad][16] = 0x00; // Not pressed + stdpar[curPad][17] = 0x00; // Not pressed + stdpar[curPad][18] = 0x00; // Not pressed + stdpar[curPad][19] = 0x00; // Not pressed + break; + } + switch(button_check2) + { + case 0xE: // UP + stdpar[curPad][10] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][21])); + break; + case 0xB: // DOWN + stdpar[curPad][11] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][22])); + break; + case 0x7: // LEFT + stdpar[curPad][9] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][23])); + break; + case 0xD: // RIGHT + stdpar[curPad][8] = (pressure*255)/100; //0xff/(100/(100-conf.keys[curPad][24])); + break; + default: + stdpar[curPad][8] = 0x00; // Not pressed + stdpar[curPad][9] = 0x00; // Not pressed + stdpar[curPad][10] = 0x00; // Not pressed + stdpar[curPad][11] = 0x00; // Not pressed + break; + } + buf = stdpar[curPad]; + return padID[curPad]; + + case 0x43: // CONFIG_MODE + cmdLen = 8; + buf = stdcfg[curPad]; + if (stdcfg[curPad][3] == 0xff) return 0xf3; + else return padID[curPad]; + + case 0x44: // SET_MODE_AND_LOCK + cmdLen = 8; + buf = stdmode[curPad]; + return 0xf3; + + case 0x45: // QUERY_MODEL_AND_MODE + cmdLen = 8; + buf = stdmodel[curPad]; + buf[4] = padMode[curPad]; + return 0xf3; + + case 0x46: // ?? + cmdLen = 8; + buf = unk46[curPad]; + return 0xf3; + + case 0x47: // ?? + cmdLen = 8; + buf = unk47[curPad]; + return 0xf3; + + case 0x4c: // QUERY_MODE ?? + cmdLen = 8; + buf = unk4c[curPad]; + return 0xf3; + + case 0x4d: + cmdLen = 8; + buf = unk4d[curPad]; + return 0xf3; + + case 0x4f: // SET_DS2_NATIVE_MODE + cmdLen = 8; + padID[curPad] = 0x79; // setting ds2 mode + ds2mode = 1; // Set DS2 Mode + buf = cmd4f[curPad]; + return 0xf3; + + default: +#ifdef PAD_LOG + PAD_LOG("*PADpoll*: unknown cmd %x\n", value); +#endif + break; + } + } + + switch (curCmd) { + case 0x43: + if(curByte == 2) + { + switch(value){ + case 0: + buf[2] = 0; + buf[3] = 0; + break; + case 1: + buf[2] = 0xff; + buf[3] = 0xff; + break; + } + } + break; + + case 0x44: + if (curByte == 2) { + PADsetMode(curPad, value); + } + break; + + case 0x46: + if(curByte == 2) { + switch(value) { + case 0: // default + buf[5] = 0x2; + buf[6] = 0x0; + buf[7] = 0xA; + break; + case 1: // Param std conf change + buf[5] = 0x1; + buf[6] = 0x1; + buf[7] = 0x14; + break; + } + } + break; + + case 0x4c: + if (curByte == 2) { + switch (value) { + case 0: // mode 0 - digital mode + buf[5] = 0x4; + break; + + case 1: // mode 1 - analog mode + buf[5] = 0x7; + break; + } + } + break; + } + + if (curByte >= cmdLen) return 0; + return buf[curByte++]; +} + +u8 CALLBACK PADpoll(u8 value) +{ + u8 ret; + ret = _PADpoll(value); +#ifdef PAD_LOG + PAD_LOG("PADpoll: %x (%d: %x)\n", value, curByte, ret); +#endif + return ret; +} + +// PADkeyEvent is called every vsync (return NULL if no event) +static keyEvent s_event; +keyEvent* CALLBACK PADkeyEvent() +{ + s_event = event; + event.event = 0; + return &s_event; +} diff --git a/plugins/pad/zeropad/zeropad.glade b/plugins/pad/zeropad/zeropad.glade new file mode 100644 index 0000000..d4426a0 --- /dev/null +++ b/plugins/pad/zeropad/zeropad.glade @@ -0,0 +1,1034 @@ + + + + + + + True + False + ZeroPAD + False + Author: zerofrog(@gmail.com) +Thanks to: + linuzappz <linuzappz@hotmail.com> +florin sasu <florinsasu@hotmail.com> +and SSSPSXPad, TwinPad authors + translator-credits + + + + True + ZeroPAD Configuration Dialog + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + PAD1 + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + 0 + False + False + + + + + + True + True + PAD2 + True + GTK_RELIEF_NORMAL + True + False + False + True + PAD1 + + + + 0 + False + False + + + + + + + + + + True + <b>Choose PAD to modify</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 64 + 40 + + + + + + 64 + 24 + True + True + True + True + 0 + + True + + False + + + 64 + 104 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 168 + 64 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 280 + 64 + + + + + + 64 + 24 + True + True + True + True + 0 + + True + + False + + + 64 + 168 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 128 + 208 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 0 + 208 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 64 + 256 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 368 + 32 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 368 + 104 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 224 + 128 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 304 + 208 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 368 + 168 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 432 + 208 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 368 + 256 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 272 + 272 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 176 + 272 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 272 + 352 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 176 + 352 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 272 + 416 + + + + + + 64 + 24 + True + True + False + True + 0 + + True + + False + + + 176 + 416 + + + + + + 64 + 32 + True + True + Select + True + GTK_RELIEF_NORMAL + True + + + + 168 + 32 + + + + + + 64 + 32 + True + True + L1 + True + GTK_RELIEF_NORMAL + True + + + + 64 + 72 + + + + + + 64 + 32 + True + True + Left + True + GTK_RELIEF_NORMAL + True + + + + 0 + 176 + + + + + + 64 + 32 + True + True + Down + True + GTK_RELIEF_NORMAL + True + + + + 64 + 224 + + + + + + 64 + 32 + True + True + Analog + True + GTK_RELIEF_NORMAL + True + + + + 224 + 96 + + + + + + 64 + 32 + True + True + R2 + True + GTK_RELIEF_NORMAL + True + + + + 368 + 0 + + + + + + 64 + 32 + True + True + Start + True + GTK_RELIEF_NORMAL + True + + + + 280 + 32 + + + + + + 64 + 32 + True + True + R1 + True + GTK_RELIEF_NORMAL + True + + + + 368 + 72 + + + + + + 64 + 32 + True + True + Cross + True + GTK_RELIEF_NORMAL + True + + + + 368 + 224 + + + + + + 64 + 32 + True + True + Triangle + True + GTK_RELIEF_NORMAL + True + + + + 368 + 136 + + + + + + 64 + 32 + True + True + Circle + True + GTK_RELIEF_NORMAL + True + + + + 432 + 176 + + + + + + 64 + 32 + True + True + Right + True + GTK_RELIEF_NORMAL + True + + + + 128 + 176 + + + + + + 64 + 32 + True + True + Square + True + GTK_RELIEF_NORMAL + True + + + + 304 + 176 + + + + + + 64 + 32 + True + True + R3 + True + GTK_RELIEF_NORMAL + True + + + + 272 + 240 + + + + + + 64 + 32 + True + True + Lx + True + GTK_RELIEF_NORMAL + True + + + + 176 + 320 + + + + + + 64 + 32 + True + True + Rx + True + GTK_RELIEF_NORMAL + True + + + + 272 + 320 + + + + + + 64 + 32 + True + True + Ly + True + GTK_RELIEF_NORMAL + True + + + + 176 + 384 + + + + + + 64 + 32 + True + True + Ry + True + GTK_RELIEF_NORMAL + True + + + + 272 + 384 + + + + + + 408 + 16 + True + Analog Controls (move mouse or analog joystick to select) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + True + 0 + + + 56 + 296 + + + + + + 64 + 32 + True + True + L3 + True + GTK_RELIEF_NORMAL + True + + + + 176 + 240 + + + + + + 64 + 32 + True + True + Up + True + GTK_RELIEF_NORMAL + True + + + + 64 + 136 + + + + + + 64 + 32 + True + True + L2 + True + GTK_RELIEF_NORMAL + True + + + + 64 + 8 + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + diff --git a/plugins/pad/zeropad/zeropad.h b/plugins/pad/zeropad/zeropad.h new file mode 100644 index 0000000..588fbdf --- /dev/null +++ b/plugins/pad/zeropad/zeropad.h @@ -0,0 +1,115 @@ +/* ZeroPAD + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __PAD_H__ +#define __PAD_H__ + +#define _CRT_SECURE_NO_DEPRECATE +#include +#include + +#ifdef _WIN32 +#include +#include + +#else + +#include +#include +#include + +#endif + +#include +#include +#include +using namespace std; + +#define PADdefs +extern "C" { +#include "PS2Edefs.h" +} + +extern char *libraryName; + +#define PAD_GETKEY(key) (key&0xffff) +#define IS_KEYBOARD(key) (key<0x10000) +#define IS_JOYBUTTONS(key) (key>=0x10000 && key<0x20000) +#define IS_JOYSTICK(key) (key>=0x20000&&key<0x30000) +#define IS_POV(key) (key>=0x30000&&key<0x40000) +#define IS_MOUSE(key) (key>=0x40000&&key<0x50000) + +#define PADKEYS 20 + +typedef struct { + unsigned long keys[2][PADKEYS]; + int log; +} PADconf; + +typedef struct { + u8 x,y; + u8 button; +} Analog; + +extern PADconf conf; + +extern Analog lanalog[2], ranalog[2]; +extern FILE *padLog; +#define PAD_LOG __Log + +#define PAD_LEFT 0x8000 +#define PAD_DOWN 0x4000 +#define PAD_RIGHT 0x2000 +#define PAD_UP 0x1000 +#define PAD_START 0x0800 +#define PAD_R3 0x0400 +#define PAD_L3 0x0200 +#define PAD_SELECT 0x0100 +#define PAD_SQUARE 0x0080 +#define PAD_CROSS 0x0040 +#define PAD_CIRCLE 0x0020 +#define PAD_TRIANGLE 0x0010 +#define PAD_R1 0x0008 +#define PAD_L1 0x0004 +#define PAD_R2 0x0002 +#define PAD_L2 0x0001 + +/* end of pad.h */ + +extern keyEvent event; + +extern u16 status[2]; +extern u32 pads; + +int POV(u32 direction, u32 angle); +s32 _PADopen(void *pDsp); +void _PADclose(); +void _KeyPress(int pad, u32 key); +void _KeyRelease(int pad, u32 key); +void PADsetMode(int pad, int mode); +void _PADupdate(int pad); + +void __Log(char *fmt, ...); +void LoadConfig(); +void SaveConfig(); + +void SysMessage(char *fmt, ...); + +#endif + + diff --git a/plugins/spu2/PeopsSPU2/Filemap.txt b/plugins/spu2/PeopsSPU2/Filemap.txt new file mode 100644 index 0000000..da779e0 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/Filemap.txt @@ -0,0 +1,49 @@ +######################################################################### + +- spu.c / spu.h + main spu handler - generic init and exit funcs + +- adsr.c / adsr.h + adsr handlers + +- dma.c / dma.h + memory transfer funcs + +- registers.c / registers.h / regs.h + spu register handling + +- reverb.c / reverb.h + simple reverb handlers + +- xa.c / xa.h + xa sound handlers + +- cfg.c / cfg.h + configuration dialogs/file reading funcs + +- dsound.c / oss.c / dsoundoss.h + Windows/Linux sound interfaces + +- freeze.c + save state laoding/saving + +- spu2PeopsSound.* + Windows dll related files (including msvc project files) + +- Makefile + Linux makefile... just do a "make" command to build the plugin + +- stdafx.h + main include file + +- externals.h + generic defines/external vars + +- psemuxa.h + psemu pro xa definitions + +- resource.h + Windows resource header + +######################################################################### + diff --git a/plugins/spu2/PeopsSPU2/Makefile b/plugins/spu2/PeopsSPU2/Makefile new file mode 100644 index 0000000..0b5a12f --- /dev/null +++ b/plugins/spu2/PeopsSPU2/Makefile @@ -0,0 +1,75 @@ +############################################################################## +# MAKEFILE FOR THE PEOPS OSS SPU2... just run "make" +############################################################################## + +############################################################################## +# 1. SETS (CCFLAGS3 is used) +############################################################################## +all: spu2PeopsOSS +install: all + +# Set to TRUE to build the ALSA support +USEALSA = FALSE +# Set to TRUE to disable the thread library support - helpful for some Linux distros +NOTHREADLIB = FALSE + +############################################################################## + +CC = gcc +CCFLAGS1 = -fPIC -c -Wall -O3 +CCFLAGS2 = -fPIC -c -Wall -O2 -ffast-math +CCFLAGS3 = -fPIC -c -Wall -O3 -ffast-math -fomit-frame-pointer + +INCLUDE = +LINK = gcc +OBJ = spu.o dma.o freeze.o registers.o +LIB = -lc -lm + +ifeq ($(USEALSA), TRUE) + OBJ+= alsa.o + LIB+= -lasound + LINKFLAGS = -shared -Wl,-soname,libspu2PeopsALSA.so -o libspu2PeopsALSA.so.1.0.3 + CCFLAGS3+= -DUSEALSA +else + OBJ+= oss.o + LINKFLAGS = -shared -Wl,-soname,libspu2PeopsOSS.so.1.6 -fPIC -fomit-frame-pointer -o libspu2PeopsOSS.so.1.6 +endif + +ifeq ($(NOTHREADLIB), TRUE) + CCFLAGS3+= -DNOTHREADLIB +else + LIB+= -lpthread +endif + + + +############################################################################## +# 2. MAIN RULE +############################################################################## + +spu2PeopsOSS : $(OBJ) + $(LINK) $(LINKFLAGS) $(OBJ) $(LIB) + +############################################################################## +# 3. GENERAL RULES +############################################################################## + +%.o : %.c + $(CC) $(CCFLAGS3) $(INCLUDE) $< + +############################################################################## +# 4. SPECIFIC RULES +############################################################################## + +spu.o : spu.c stdafx.h externals.h cfg.h dsoundoss.h regs.h debug.h xa.c reverb.c adsr.c +cfg.o : stdafx.h externals.h +dma.o : dma.c stdafx.h externals.h +freeze.o : freeze.c stdafx.h externals.h registers.h spu.h regs.h +oss.o : oss.c stdafx.h externals.h +alsa.o : alsa.h stdafx.h externals.h +registers.o : registers.c stdafx.h externals.h registers.h regs.h reverb.h + +.PHONY: clean spu2PeopsOSS + +clean: + rm -f *.o *.so.* diff --git a/plugins/spu2/PeopsSPU2/Makefile.win b/plugins/spu2/PeopsSPU2/Makefile.win new file mode 100644 index 0000000..56ef33d --- /dev/null +++ b/plugins/spu2/PeopsSPU2/Makefile.win @@ -0,0 +1,79 @@ +# Project: spu2PeopsSound +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = Release/spu2PeopsSound_private.res +OBJ = Release/adsr.o Release/alsa.o Release/cfg.o Release/debug.o Release/dma.o Release/dsound.o Release/freeze.o Release/oss.o Release/record.o Release/registers.o Release/reverb.o Release/spu.o Release/spu2PeopsSound.o Release/StdAfx.o Release/xa.o $(RES) +LINKOBJ = Release/adsr.o Release/alsa.o Release/cfg.o Release/debug.o Release/dma.o Release/dsound.o Release/freeze.o Release/oss.o Release/record.o Release/registers.o Release/reverb.o Release/spu.o Release/spu2PeopsSound.o Release/StdAfx.o Release/xa.o $(RES) +LIBS = -L"lib" -ldsound -lwinmm -luser32 -lgdi32 -ladvapi32 --add-stdcall-alias +INCS = -I"include" -I"D:/Archivos de programa/Microsoft Visual Studio .NET 2003/SDK/v1.1/include" +CXXINCS = -I"lib/gcc/mingw32/3.4.2/include" -I"include/c++/3.4.2/backward" -I"include/c++/3.4.2/mingw32" -I"include/c++/3.4.2" -I"include" +BIN = ../SPU2PeopsDSound.dll +CXXFLAGS = $(CXXINCS) -D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC -O3 +CFLAGS = $(INCS) -D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC -O3 +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before ../SPU2PeopsDSound.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=../libSPU2PeopsDSound.def +STATICLIB=../libSPU2PeopsDSound.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --driver-name c++ --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +Release/adsr.o: adsr.c + $(CC) -c adsr.c -o Release/adsr.o $(CFLAGS) + +Release/alsa.o: alsa.c + $(CC) -c alsa.c -o Release/alsa.o $(CFLAGS) + +Release/cfg.o: cfg.c + $(CC) -c cfg.c -o Release/cfg.o $(CFLAGS) + +Release/debug.o: debug.c + $(CC) -c debug.c -o Release/debug.o $(CFLAGS) + +Release/dma.o: dma.c + $(CC) -c dma.c -o Release/dma.o $(CFLAGS) + +Release/dsound.o: dsound.c + $(CC) -c dsound.c -o Release/dsound.o $(CFLAGS) + +Release/freeze.o: freeze.c + $(CC) -c freeze.c -o Release/freeze.o $(CFLAGS) + +Release/oss.o: oss.c + $(CC) -c oss.c -o Release/oss.o $(CFLAGS) + +Release/record.o: record.c + $(CC) -c record.c -o Release/record.o $(CFLAGS) + +Release/registers.o: registers.c + $(CC) -c registers.c -o Release/registers.o $(CFLAGS) + +Release/reverb.o: reverb.c + $(CC) -c reverb.c -o Release/reverb.o $(CFLAGS) + +Release/spu.o: spu.c + $(CC) -c spu.c -o Release/spu.o $(CFLAGS) + +Release/spu2PeopsSound.o: spu2PeopsSound.c + $(CC) -c spu2PeopsSound.c -o Release/spu2PeopsSound.o $(CFLAGS) + +Release/StdAfx.o: StdAfx.c + $(CC) -c StdAfx.c -o Release/StdAfx.o $(CFLAGS) + +Release/xa.o: xa.c + $(CC) -c xa.c -o Release/xa.o $(CFLAGS) + +Release/spu2PeopsSound_private.res: spu2PeopsSound_private.rc + $(WINDRES) -i spu2PeopsSound_private.rc --input-format=rc -o Release/spu2PeopsSound_private.res -O coff diff --git a/plugins/spu2/PeopsSPU2/_bsc.txt b/plugins/spu2/PeopsSPU2/_bsc.txt new file mode 100644 index 0000000..eadb98a --- /dev/null +++ b/plugins/spu2/PeopsSPU2/_bsc.txt @@ -0,0 +1,17 @@ +/nologo /o"Release/spu2PeopsSound.bsc" +".\Release\adsr.sbr" +".\Release\alsa.sbr" +".\Release\cfg.sbr" +".\Release\debug.sbr" +".\Release\dma.sbr" +".\Release\dsound.sbr" +".\Release\freeze.sbr" +".\Release\oss.sbr" +".\Release\psemu.sbr" +".\Release\record.sbr" +".\Release\registers.sbr" +".\Release\reverb.sbr" +".\Release\spu.sbr" +".\Release\spu2PeopsSound.sbr" +".\Release\StdAfx.sbr" +".\Release\xa.sbr" diff --git a/plugins/spu2/PeopsSPU2/adsr.c b/plugins/spu2/PeopsSPU2/adsr.c new file mode 100644 index 0000000..c5c01d0 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/adsr.c @@ -0,0 +1,672 @@ +/*************************************************************************** + adsr.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/05/14 - xodnizel +// - removed stopping of reverb on sample end +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_ADSR + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// ADSR func +//////////////////////////////////////////////////////////////////////// + +unsigned long RateTable[160]; + +void InitADSR(void) // INIT ADSR +{ + unsigned long r,rs,rd;int i; + + memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) + + r=3;rs=1;rd=0; + + for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if(r<0x3FFFFFFF) + { + r+=rs; + rd++;if(rd==5) {rd=1;rs*=2;} + } + if(r>0x3FFFFFFF) r=0x3FFFFFFF; + + RateTable[i]=r; + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void StartADSR(int ch) // MIX ADSR +{ + s_chan[ch].ADSRX.lVolume=1; // and init some adsr vars + s_chan[ch].ADSRX.State=0; + s_chan[ch].ADSRX.EnvelopeVol=0; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixADSR(int ch) // MIX ADSR +{ + if(s_chan[ch].bStop) // should be stopped: + { + if(s_chan[ch].bIgnoreLoop==0){ + s_chan[ch].ADSRX.EnvelopeVol=0; + s_chan[ch].bOn=0; + s_chan[ch].pStart= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].pLoop= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].pCurr= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].bStop=1; + s_chan[ch].bIgnoreLoop=0; + return 0; + } + if(s_chan[ch].ADSRX.ReleaseModeExp)// do release + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break; + } + } + else + { + s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.ReleaseRate^0x1F))-0x0C + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0; + s_chan[ch].bOn=0; + s_chan[ch].pStart= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].pLoop= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].pCurr= spuMemC+(s_chan[ch].iStartAdr<<1); + s_chan[ch].bStop=1; + s_chan[ch].bIgnoreLoop=0; + //s_chan[ch].bReverb=0; + //s_chan[ch].bNoise=0; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + else // not stopped yet? + { + if(s_chan[ch].ADSRX.State==0) // -> attack + { + if(s_chan[ch].ADSRX.AttackModeExp) + { + if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + else + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x18 + 32]; + } + else + { + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.AttackRate^0x7F)-0x10 + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + s_chan[ch].ADSRX.State=1; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==1) // -> decay + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[(4*(s_chan[ch].ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) s_chan[ch].ADSRX.EnvelopeVol=0; + if(((s_chan[ch].ADSRX.EnvelopeVol>>27)&0xF) <= s_chan[ch].ADSRX.SustainLevel) + { + s_chan[ch].ADSRX.State=2; + } + + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + //--------------------------------------------------// + if(s_chan[ch].ADSRX.State==2) // -> sustain + { + if(s_chan[ch].ADSRX.SustainIncrease) + { + if(s_chan[ch].ADSRX.SustainModeExp) + { + if(s_chan[ch].ADSRX.EnvelopeVol<0x60000000) + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + else + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x18 + 32]; + } + else + { + s_chan[ch].ADSRX.EnvelopeVol+=RateTable[(s_chan[ch].ADSRX.SustainRate^0x7F)-0x10 + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if(s_chan[ch].ADSRX.SustainModeExp) + { + switch((s_chan[ch].ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break; + case 1: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break; + case 2: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break; + case 3: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break; + case 4: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break; + case 5: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break; + case 6: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break; + case 7: s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break; + } + } + else + { + s_chan[ch].ADSRX.EnvelopeVol-=RateTable[((s_chan[ch].ADSRX.SustainRate^0x7F))-0x0F + 32]; + } + + if(s_chan[ch].ADSRX.EnvelopeVol<0) + { + s_chan[ch].ADSRX.EnvelopeVol=0; + } + } + s_chan[ch].ADSRX.lVolume=s_chan[ch].ADSRX.EnvelopeVol>>21; + return s_chan[ch].ADSRX.lVolume; + } + } + return 0; +} + +#endif + +/* +James Higgs ADSR investigations: + +PSX SPU Envelope Timings +~~~~~~~~~~~~~~~~~~~~~~~~ + +First, here is an extract from doomed's SPU doc, which explains the basics +of the SPU "volume envelope": + +*** doomed doc extract start *** + +-------------------------------------------------------------------------- +Voices. +-------------------------------------------------------------------------- +The SPU has 24 hardware voices. These voices can be used to reproduce sample +data, noise or can be used as frequency modulator on the next voice. +Each voice has it's own programmable ADSR envelope filter. The main volume +can be programmed independently for left and right output. + +The ADSR envelope filter works as follows: +Ar = Attack rate, which specifies the speed at which the volume increases + from zero to it's maximum value, as soon as the note on is given. The + slope can be set to lineair or exponential. +Dr = Decay rate specifies the speed at which the volume decreases to the + sustain level. Decay is always decreasing exponentially. +Sl = Sustain level, base level from which sustain starts. +Sr = Sustain rate is the rate at which the volume of the sustained note + increases or decreases. This can be either lineair or exponential. +Rr = Release rate is the rate at which the volume of the note decreases + as soon as the note off is given. + + lvl | + ^ | /\Dr __ + Sl _| _ / _ \__--- \ + | / ---__ \ Rr + | /Ar Sr \ \ + | / \\ + |/___________________\________ + ->time + +The overal volume can also be set to sweep up or down lineairly or +exponentially from it's current value. This can be done seperately +for left and right. + +Relevant SPU registers: +------------------------------------------------------------- +$1f801xx8 Attack/Decay/Sustain level +bit |0f|0e 0d 0c 0b 0a 09 08|07 06 05 04|03 02 01 00| +desc.|Am| Ar |Dr |Sl | + +Am 0 Attack mode Linear + 1 Exponential + +Ar 0-7f attack rate +Dr 0-f decay rate +Sl 0-f sustain level +------------------------------------------------------------- +$1f801xxa Sustain rate, Release Rate. +bit |0f|0e|0d|0c 0b 0a 09 08 07 06|05|04 03 02 01 00| +desc.|Sm|Sd| 0| Sr |Rm|Rr | + +Sm 0 sustain rate mode linear + 1 exponential +Sd 0 sustain rate mode increase + 1 decrease +Sr 0-7f Sustain Rate +Rm 0 Linear decrease + 1 Exponential decrease +Rr 0-1f Release Rate + +Note: decay mode is always Expontial decrease, and thus cannot +be set. +------------------------------------------------------------- +$1f801xxc Current ADSR volume +bit |0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00| +desc.|ADSRvol | + +ADSRvol Returns the current envelope volume when + read. +-- James' Note: return range: 0 -> 32767 + +*** doomed doc extract end *** + +By using a small PSX proggie to visualise the envelope as it was played, +the following results for envelope timing were obtained: + +1. Attack rate value (linear mode) + + Attack value range: 0 -> 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | | 80 | + ----------------------------------------------------------------- + Frames | 11 | 21 | 42 | 84 | 169| 338| 676| |2890| + + Note: frames is no. of PAL frames to reach full volume (100% + amplitude) + + Hmm, noticing that the time taken to reach full volume doubles + every time we add 4 to our attack value, we know the equation is + of form: + frames = k * 2 ^ (value / 4) + + (You may ponder about envelope generator hardware at this point, + or maybe not... :) + + By substituting some stuff and running some checks, we get: + + k = 0.00257 (close enuf) + + therefore, + frames = 0.00257 * 2 ^ (value / 4) + If you just happen to be writing an emulator, then you can probably + use an equation like: + + %volume_increase_per_tick = 1 / frames + + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*514)/10000 + ------------------------------------ + +2. Decay rate value (only has log mode) + + Decay value range: 0 -> 15 + + Value | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + ------------------------------------------------ + frames | | | | | 6 | 12 | 24 | 47 | + + Note: frames here is no. of PAL frames to decay to 50% volume. + + formula: frames = k * 2 ^ (value) + + Substituting, we get: k = 0.00146 + + Further info on logarithmic nature: + frames to decay to sustain level 3 = 3 * frames to decay to + sustain level 9 + + Also no. of frames to 25% volume = roughly 1.85 * no. of frames to + 50% volume. + + Frag it - just use linear approx. + + ------------------------------------ + Pete: + ms=((1< 127 + + Value | 48 | 52 | 56 | 60 | 64 | 68 | 72 | + ------------------------------------------- + frames | 9 | 19 | 37 | 74 | 147| 293| 587| + + Here, frames = no. of PAL frames for volume amplitude to go from 100% + to 0% (or vice-versa). + + Same formula as for attack value, just a different value for k: + + k = 0.00225 + + ie: frames = 0.00225 * 2 ^ (value / 4) + + For emulation purposes: + + %volume_increase_or_decrease_per_tick = 1 / frames + + ------------------------------------ + Pete: + ms=((1<<(value>>2))*450)/10000 + ------------------------------------ + + +4. Release rate (linear mode) + + Release rate range: 0 -> 31 + + Value | 13 | 14 | 15 | 16 | 17 | + --------------------------------------------------------------- + frames | 18 | 36 | 73 | 146| 292| + + Here, frames = no. of PAL frames to decay from 100% vol to 0% vol + after "note-off" is triggered. + + Formula: frames = k * 2 ^ (value) + + And so: k = 0.00223 + + ------------------------------------ + Pete: + ms=((1< release phase + { + if(s_chan[ch].ADSR.ReleaseVal!=0) // -> release not 0: do release (if 0: stop right now) + { + if(!s_chan[ch].ADSR.ReleaseVol) // --> release just started? set up the release stuff + { + s_chan[ch].ADSR.ReleaseStartTime=s_chan[ch].ADSR.lTime; + s_chan[ch].ADSR.ReleaseVol=s_chan[ch].ADSR.lVolume; + s_chan[ch].ADSR.ReleaseTime = // --> calc how long does it take to reach the wanted sus level + (s_chan[ch].ADSR.ReleaseTime* + s_chan[ch].ADSR.ReleaseVol)/1024; + } + // -> NO release exp mode used (yet) + v=s_chan[ch].ADSR.ReleaseVol; // -> get last volume + lT=s_chan[ch].ADSR.lTime- // -> how much time is past? + s_chan[ch].ADSR.ReleaseStartTime; + l1=s_chan[ch].ADSR.ReleaseTime; + + if(lT we still have to release + { + v=v-((v*lT)/l1); // --> calc new volume + } + else // -> release is over: now really stop that sample + {v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + } + else // -> release IS 0: release at once + { + v=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0; + } + } + else + {//--------------------------------------------------// not in release phase: + v=1024; + lT=s_chan[ch].ADSR.lTime; + l1=s_chan[ch].ADSR.AttackTime; + + if(lT0) + { + if(l3!=0) v2+=((v-v2)*lT)/l3; + else v2=v; + } + else + { + if(l3!=0) v2-=(v2*lT)/l3; + else v2=v; + } + + if(v2>v) v2=v; + if(v2<=0) {v2=0;s_chan[ch].bOn=0;s_chan[ch].ADSR.ReleaseVol=0;s_chan[ch].bNoise=0;} + + v=v2; + } + } + } + + //----------------------------------------------------// + // ok, done for this channel, so increase time + + s_chan[ch].ADSR.lTime+=1; // 1 = 1.020408f ms; + + if(v>1024) v=1024; // adjust volume + if(v<0) v=0; + s_chan[ch].ADSR.lVolume=v; // store act volume + + return v; // return the volume factor +*/ + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +/* +----------------------------------------------------------------------------- +Neill Corlett +Playstation SPU envelope timing notes +----------------------------------------------------------------------------- + +This is preliminary. This may be wrong. But the model described herein fits +all of my experimental data, and it's just simple enough to sound right. + +ADSR envelope level ranges from 0x00000000 to 0x7FFFFFFF internally. +The value returned by channel reg 0xC is (envelope_level>>16). + +Each sample, an increment or decrement value will be added to or +subtracted from this envelope level. + +Create the rate log table. The values double every 4 entries. + entry #0 = 4 + + 4, 5, 6, 7, + 8,10,12,14, + 16,20,24,28, ... + + entry #40 = 4096... + entry #44 = 8192... + entry #48 = 16384... + entry #52 = 32768... + entry #56 = 65536... + +increments and decrements are in terms of ratelogtable[n] +n may exceed the table bounds (plan on n being between -32 and 127). +table values are all clipped between 0x00000000 and 0x3FFFFFFF + +when you "voice on", the envelope is always fully reset. +(yes, it may click. the real thing does this too.) + +envelope level begins at zero. + +each state happens for at least 1 cycle +(transitions are not instantaneous) +this may result in some oddness: if the decay rate is uberfast, it will cut +the envelope from full down to half in one sample, potentially skipping over +the sustain level + +ATTACK +------ +- if the envelope level has overflowed past the max, clip to 0x7FFFFFFF and + proceed to DECAY. + +Linear attack mode: +- line extends upward to 0x7FFFFFFF +- increment per sample is ratelogtable[(Ar^0x7F)-0x10] + +Logarithmic attack mode: +if envelope_level < 0x60000000: + - line extends upward to 0x60000000 + - increment per sample is ratelogtable[(Ar^0x7F)-0x10] +else: + - line extends upward to 0x7FFFFFFF + - increment per sample is ratelogtable[(Ar^0x7F)-0x18] + +DECAY +----- +- if ((envelope_level>>27)&0xF) <= Sl, proceed to SUSTAIN. + Do not clip to the sustain level. +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Dr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Dr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Dr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Dr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Dr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Dr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Dr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Dr^0x1F))-0x18+12] + (note that this is the same as the release rate formula, except that + decay rates 10-1F aren't possible... those would be slower in theory) + +SUSTAIN +------- +- no terminating condition except for voice off +- Sd=0 (increase) behavior is identical to ATTACK for both log and linear. +- Sd=1 (decrease) behavior: +Linear sustain decrease: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(Sr^0x7F)-0x0F] +Logarithmic sustain decrease: +- current line ends at (envelope_level & 0x07FFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(Sr^0x7F)-0x1B+0] + 1: ratelogtable[(Sr^0x7F)-0x1B+4] + 2: ratelogtable[(Sr^0x7F)-0x1B+6] + 3: ratelogtable[(Sr^0x7F)-0x1B+8] + 4: ratelogtable[(Sr^0x7F)-0x1B+9] + 5: ratelogtable[(Sr^0x7F)-0x1B+10] + 6: ratelogtable[(Sr^0x7F)-0x1B+11] + 7: ratelogtable[(Sr^0x7F)-0x1B+12] + +RELEASE +------- +- if the envelope level has overflowed to negative, clip to 0 and QUIT. + +Linear release mode: +- line extends to 0x00000000 +- decrement per sample is ratelogtable[(4*(Rr^0x1F))-0x0C] + +Logarithmic release mode: +- line extends to (envelope_level & 0x0FFFFFFF) +- decrement per sample depends on (envelope_level>>28)&0x7 + 0: ratelogtable[(4*(Rr^0x1F))-0x18+0] + 1: ratelogtable[(4*(Rr^0x1F))-0x18+4] + 2: ratelogtable[(4*(Rr^0x1F))-0x18+6] + 3: ratelogtable[(4*(Rr^0x1F))-0x18+8] + 4: ratelogtable[(4*(Rr^0x1F))-0x18+9] + 5: ratelogtable[(4*(Rr^0x1F))-0x18+10] + 6: ratelogtable[(4*(Rr^0x1F))-0x18+11] + 7: ratelogtable[(4*(Rr^0x1F))-0x18+12] + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/spu2/PeopsSPU2/adsr.h b/plugins/spu2/PeopsSPU2/adsr.h new file mode 100644 index 0000000..777a0d8 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/adsr.h @@ -0,0 +1,28 @@ +/*************************************************************************** + adsr.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +INLINE void StartADSR(int ch); +INLINE int MixADSR(int ch); diff --git a/plugins/spu2/PeopsSPU2/alsa.c b/plugins/spu2/PeopsSPU2/alsa.c new file mode 100644 index 0000000..7bb1661 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/alsa.c @@ -0,0 +1,206 @@ +/*************************************************************************** + alsa.c - description + ------------------- + begin : Sat Mar 01 2003 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/03/02 - linuzappz +// - fixed XRUN behavior +// +// 2003/03/01 - linuzappz +// - created +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_OSS + +#include "externals.h" + +#ifndef _WINDOWS + +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API +#include + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// + +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works +} + +//////////////////////////////////////////////////////////////////////// +// oss globals +//////////////////////////////////////////////////////////////////////// + +#define ALSA_MEM_DEF +#include "alsa.h" +static snd_pcm_t *handle = NULL; +static snd_pcm_uframes_t buffer_size; + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound(void) +{ + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + snd_pcm_status_t *status; + int pspeed; + int pchannels; + int format; + int buffer_time; + int period_time; + int err; + + if(iDisStereo) pchannels=1; + else pchannels=2; + + pspeed=44100; + format=SND_PCM_FORMAT_S16_LE; + buffer_time=500000; + period_time=buffer_time/4; + + if((err=snd_pcm_open(&handle, "default", + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0) + { + printf("Audio open error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_nonblock(handle, 0))<0) + { + printf("Can't set blocking moded: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_hw_params_alloca(&hwparams); + snd_pcm_sw_params_alloca(&swparams); + if((err=snd_pcm_hw_params_any(handle, hwparams))<0) + { + printf("Broken configuration for this PCM: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))<0) + { + printf("Access type not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_format(handle, hwparams, format))<0) + { + printf("Sample format not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_channels(handle, hwparams, pchannels))<0) + { + printf("Channels count not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_rate_near(handle, hwparams, &pspeed, 0))<0) + { + printf("Rate not available: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0))<0) + { + printf("Buffer time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0))<0) + { + printf("Period time error: %s\n", snd_strerror(err)); + return; + } + + if((err=snd_pcm_hw_params(handle, hwparams))<0) + { + printf("Unable to install hw params: %s\n", snd_strerror(err)); + return; + } + + snd_pcm_status_alloca(&status); + if((err=snd_pcm_status(handle, status))<0) + { + printf("Unable to get status: %s\n", snd_strerror(err)); + return; + } + + buffer_size=snd_pcm_status_get_avail(status); +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + if(handle != NULL) + { + snd_pcm_drop(handle); + snd_pcm_close(handle); + handle = NULL; + } +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + unsigned long l; + + if(handle == NULL) // failed to open? + return SOUNDSIZE; + l = snd_pcm_avail_update(handle); + if(l<0) return 0; + if(l no? wait + else l=0; // -> else go on + + return l; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedStreamData(unsigned char* pSound,long lBytes) +{ + if(handle == NULL) return; + + if(snd_pcm_state(handle) == SND_PCM_STATE_XRUN) + snd_pcm_prepare(handle); + snd_pcm_writei(handle,pSound, + iDisStereo == 1 ? lBytes/2 : lBytes/4); +} + +#endif diff --git a/plugins/spu2/PeopsSPU2/alsa.h b/plugins/spu2/PeopsSPU2/alsa.h new file mode 100644 index 0000000..4ea9e21 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/alsa.h @@ -0,0 +1,30 @@ +/*************************************************************************** + alsa.h - description + ------------------- + begin : Sat Mar 01 2003 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef _ALSA_SOUND_H +#define _ALSA_SOUND_H + +#ifdef ALSA_MEM_DEF +#define ALSA_MEM_EXTERN +#else +#define ALSA_MEM_EXTERN extern +#endif + +ALSA_MEM_EXTERN int sound_buffer_size; + +#endif // _ALSA_SOUND_H diff --git a/plugins/spu2/PeopsSPU2/build.sh b/plugins/spu2/PeopsSPU2/build.sh new file mode 100644 index 0000000..68f23fd --- /dev/null +++ b/plugins/spu2/PeopsSPU2/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +curdir=`pwd` + +echo ------------------ +echo Building PeopsSPU2 +echo ------------------ + +make $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cp libspu2Peops*.so* ${PCSX2PLUGINS} diff --git a/plugins/spu2/PeopsSPU2/cfg.c b/plugins/spu2/PeopsSPU2/cfg.c new file mode 100644 index 0000000..0d564f9 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/cfg.c @@ -0,0 +1,266 @@ +/*************************************************************************** + cfg.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/06/07 - Pete +// - added Linux NOTHREADLIB define +// +// 2003/02/28 - Pete +// - added option for kode54's interpolation and linuzappz's mono mode +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2002/08/04 - Pete +// - small linux bug fix: now the cfg file can be in the main emu directory as well +// +// 2002/06/08 - linuzappz +// - Added combo str for SPUasync, and MAXMODE is now defined as 2 +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_CFG + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// WINDOWS CONFIG/ABOUT HANDLING +//////////////////////////////////////////////////////////////////////// + +#include "resource.h" + +//////////////////////////////////////////////////////////////////////// +// simple about dlg handler +//////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_COMMAND: + { + switch(LOWORD(wParam)) + {case IDOK: EndDialog(hW,TRUE);return TRUE;} + } + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// +// READ CONFIG: from win registry +//////////////////////////////////////////////////////////////////////// + +// timer mode 2 (spuupdate sync mode) can be enabled for windows +// by setting MAXMODE to 2. +// Attention: that mode is not much tested, maybe the dsound buffers +// need to get adjusted to use that mode safely. Also please note: +// sync sound updates will _always_ cause glitches, if the system is +// busy by, for example, long lasting cdrom accesses. OK, you have +// be warned :) + +#define MAXMODE 2 +//#define MAXMODE 1 + +void ReadConfig(void) +{ + HKEY myKey; + DWORD temp; + DWORD type; + DWORD size; + // init vars + iVolume=3; + iDebugMode=0; + iRecordMode=0; + iUseReverb=0; + iUseInterpolation=2; + iSPUIRQWait=0; + iUseTimer = 2; + + if(RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\PS2Eplugin\\SPU2\\PeopsSound",0,KEY_ALL_ACCESS,&myKey)==ERROR_SUCCESS) + { + size = 4; + if(RegQueryValueEx(myKey,"Volume",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iVolume=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"DebugMode",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iDebugMode=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"RecordMode",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iRecordMode=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseReverb",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseReverb=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseInterpolation",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseInterpolation=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"SPUIRQWait",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iSPUIRQWait=(int)temp; + size = 4; + if(RegQueryValueEx(myKey,"UseTimer",0,&type,(LPBYTE)&temp,&size)==ERROR_SUCCESS) + iUseTimer=(int)temp; + + + RegCloseKey(myKey); + } + + if(iVolume<1) iVolume=1; + if(iVolume>5) iVolume=5; +} + +//////////////////////////////////////////////////////////////////////// +// WRITE CONFIG: in win registry +//////////////////////////////////////////////////////////////////////// + +void WriteConfig(void) +{ + HKEY myKey; + DWORD myDisp; + DWORD temp; + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\PS2Eplugin\\SPU2\\PeopsSound",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&myKey,&myDisp); + temp=iVolume; + RegSetValueEx(myKey,"Volume",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iDebugMode; + RegSetValueEx(myKey,"DebugMode",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iRecordMode; + RegSetValueEx(myKey,"RecordMode",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseReverb; + RegSetValueEx(myKey,"UseReverb",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseInterpolation; + RegSetValueEx(myKey,"UseInterpolation",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iUseTimer; + RegSetValueEx(myKey,"UseTimer",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + temp=iSPUIRQWait; + RegSetValueEx(myKey,"SPUIRQWait",0,REG_DWORD,(LPBYTE) &temp,sizeof(temp)); + RegCloseKey(myKey); +} + +//////////////////////////////////////////////////////////////////////// +// INIT WIN CFG DIALOG +//////////////////////////////////////////////////////////////////////// + +BOOL OnInitDSoundDialog(HWND hW) +{ + HWND hWC; + + ReadConfig(); + + hWC=GetDlgItem(hW,IDC_VOLUME); + ComboBox_AddString(hWC, "0: Mute"); + ComboBox_AddString(hWC, "1: low"); + ComboBox_AddString(hWC, "2: medium"); + ComboBox_AddString(hWC, "3: loud"); + ComboBox_AddString(hWC, "4: loudest"); + ComboBox_SetCurSel(hWC,5-iVolume); + if(iSPUIRQWait) CheckDlgButton(hW,IDC_SPU2IRQ,TRUE); + if(iDebugMode) CheckDlgButton(hW,IDC_DEBUGMODE,TRUE); + if(iRecordMode) CheckDlgButton(hW,IDC_RECORDMODE,TRUE); + if(iUseTimer==0) CheckDlgButton(hW,IDC_TIMER,TRUE); + + hWC=GetDlgItem(hW,IDC_USEREVERB); + ComboBox_AddString(hWC, "0: No reverb (fastest)"); + ComboBox_AddString(hWC, "1: SPU2 reverb (may be buggy, not tested yet)"); + ComboBox_SetCurSel(hWC,iUseReverb); + + hWC=GetDlgItem(hW,IDC_INTERPOL); + ComboBox_AddString(hWC, "0: None (fastest)"); + ComboBox_AddString(hWC, "1: Simple interpolation"); + ComboBox_AddString(hWC, "2: Gaussian interpolation (good quality)"); + ComboBox_AddString(hWC, "3: Cubic interpolation (better treble)"); + ComboBox_SetCurSel(hWC,iUseInterpolation); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// WIN CFG DLG OK +//////////////////////////////////////////////////////////////////////// + +void OnDSoundOK(HWND hW) +{ + HWND hWC; + + if(IsDlgButtonChecked(hW,IDC_SPU2IRQ)) + iSPUIRQWait=1; else iSPUIRQWait=0; + + if(IsDlgButtonChecked(hW,IDC_TIMER)) + iUseTimer=0; else iUseTimer=2; + + hWC=GetDlgItem(hW,IDC_VOLUME); + iVolume=5-ComboBox_GetCurSel(hWC); + + hWC=GetDlgItem(hW,IDC_USEREVERB); + iUseReverb=ComboBox_GetCurSel(hWC); + + hWC=GetDlgItem(hW,IDC_INTERPOL); + iUseInterpolation=ComboBox_GetCurSel(hWC); + + if(IsDlgButtonChecked(hW,IDC_DEBUGMODE)) + iDebugMode=1; else iDebugMode=0; + + if(IsDlgButtonChecked(hW,IDC_RECORDMODE)) + iRecordMode=1; else iRecordMode=0; + + WriteConfig(); // write registry + + EndDialog(hW,TRUE); +} + +//////////////////////////////////////////////////////////////////////// +// WIN CFG DLG CANCEL +//////////////////////////////////////////////////////////////////////// + +void OnDSoundCancel(HWND hW) +{ + EndDialog(hW,FALSE); +} + +//////////////////////////////////////////////////////////////////////// +// WIN CFG PROC +//////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK DSoundDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + return OnInitDSoundDialog(hW); + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDCANCEL: OnDSoundCancel(hW);return TRUE; + case IDOK: OnDSoundOK(hW); return TRUE; + } + } + } + return FALSE; +} + diff --git a/plugins/spu2/PeopsSPU2/cfg.h b/plugins/spu2/PeopsSPU2/cfg.h new file mode 100644 index 0000000..a5af817 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/cfg.h @@ -0,0 +1,36 @@ +/*************************************************************************** + cfg.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void ReadConfig(void); + + +#ifdef _WINDOWS +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK DSoundDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#else +void StartCfgTool(char * pCmdLine); +#endif diff --git a/plugins/spu2/PeopsSPU2/clean.bat b/plugins/spu2/PeopsSPU2/clean.bat new file mode 100644 index 0000000..cbeb91c --- /dev/null +++ b/plugins/spu2/PeopsSPU2/clean.bat @@ -0,0 +1,3 @@ +del *.o +del *.c~ +del *.h~ \ No newline at end of file diff --git a/plugins/spu2/PeopsSPU2/debug.c b/plugins/spu2/PeopsSPU2/debug.c new file mode 100644 index 0000000..1aa65b3 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/debug.c @@ -0,0 +1,442 @@ +/*************************************************************************** + debug.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/25 - Pete +// - update mute checkboxes if core selection changes +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/01/06 - Pete +// - added Neil's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_DEBUG + +#include "externals.h" + +//////////////////////////////////////////////////////////////////////// +// WINDOWS DEBUG DIALOG HANDLING +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +#include "resource.h" + +//#define SMALLDEBUG +//#include + +//////////////////////////////////////////////////////////////////////// +// display debug infos + +const COLORREF crStreamCol[]={ + RGB( 0, 0, 0), + RGB(255,255,255), + RGB(128, 0,128), + RGB( 0,128, 0), + RGB( 0, 0,255), + RGB(255, 0, 0) + }; + +const COLORREF crAdsrCol[] ={ + RGB( 0, 0, 0), + RGB(255, 0, 0), + RGB( 0,255, 0), + RGB(255, 0,255), + RGB( 0, 0,255), + RGB( 0, 0, 0), + }; + +HBRUSH hBStream[6]; // brushes for stream lines +HPEN hPAdsr[6]; // pens for adsr lines +int iSelChannel=0; // user selected channel +int iCoreOffset=0; + +//////////////////////////////////////////////////////////////////////// +// display the sound data waves: no subclassing used, so the +// area will not be redrawn... but faster that way, and good enuff +// for debugging purposes + +void DisplayStreamInfos(HWND hW) +{ + HWND hWS=GetDlgItem(hW,IDC_SAREA); + HDC hdc;RECT r;HBRUSH hBO;int ch,dy,i,j,id; + + //----------------------------------------------------// + + GetClientRect(hWS,&r); // get size of stream display + hdc=GetDC(hWS); // device context + r.right--; // leave the right border intact + ScrollDC(hdc,-1,0,&r,&r,NULL,NULL); // scroll one pixel to the left + + //----------------------------------------------------// + + hBO=SelectObject(hdc,hBStream[0]); // clean the right border + PatBlt(hdc,r.right-1,0,1,r.bottom,PATCOPY); + + //----------------------------------------------------// + + dy=r.bottom/HLFCHAN; // size of one channel area + + for(ch=0;ch get one channel data (-32k ... 32k) + j=(dy*j)/33768; if(j==0) j=1; // -> adjust to display coords + i=(dy/2)+(ch*r.bottom/HLFCHAN)-j/2; // -> position where to paint it + + + + if (s_chan[ch+iCoreOffset].iMute) id=1; // -> get color id + else if(s_chan[ch+iCoreOffset].bNoise) id=2; + else if(s_chan[ch+iCoreOffset].bFMod==2) id=3; + else if(s_chan[ch+iCoreOffset].bFMod==1) id=4; + else id=5; + + SelectObject(hdc,hBStream[id]); // -> select the brush + PatBlt(hdc,r.right-1,i,1,j,PATCOPY); // -> paint the value line + } + + if(ch) SetPixel(hdc,r.right-1, // -> not first line? + ch*r.bottom/HLFCHAN,RGB(0,0,0)); // --> draw the line (one dot scrolled to the left) + } + + //----------------------------------------------------// + + SelectObject(hdc,hBO); // repair brush + + ReleaseDC(hWS,hdc); // release context +} + +//////////////////////////////////////////////////////////////////////// +// display adsr lines: also no subclassing for repainting used + +void DisplayADSRInfos(HWND hW) +{ + HWND hWS=GetDlgItem(hW,IDC_ADSR); + HDC hdc;RECT r;HBRUSH hBO;char szB[16]; + int ch=iSelChannel+iCoreOffset,dx,dy,dm,dn,ia,id,is,ir; + + //----------------------------------------------------// get display size + + GetClientRect(hWS,&r); + hdc=GetDC(hWS); + + //----------------------------------------------------// clean the area + + hBO=SelectObject(hdc,hBStream[0]); + PatBlt(hdc,0,0,r.right,r.bottom,PATCOPY); + r.left++;r.right-=2;r.top++;r.bottom-=2; // shrink the display rect for better optics + + //----------------------------------------------------// + + ia=min(s_chan[ch].ADSR.AttackTime,10000); // get adsr, but limit it for drawing + id=min(s_chan[ch].ADSR.DecayTime,10000); + is=min(s_chan[ch].ADSR.SustainTime,10000); + ir=min(s_chan[ch].ADSR.ReleaseTime,10000); + + dx=ia+id+is+ir; // get the dx in (limited) adsr units + + // set the real values to the info statics + SetDlgItemInt(hW,IDC_SADSR1,s_chan[ch].ADSRX.AttackRate,FALSE); + SetDlgItemInt(hW,IDC_SADSR2,s_chan[ch].ADSRX.DecayRate,FALSE); + SetDlgItemInt(hW,IDC_SADSR3,s_chan[ch].ADSRX.SustainRate,FALSE); + SetDlgItemInt(hW,IDC_SADSR4,s_chan[ch].ADSRX.ReleaseRate,FALSE); + SetDlgItemInt(hW,IDC_SADSR5,s_chan[ch].ADSRX.SustainLevel,FALSE); + SetDlgItemInt(hW,IDC_SADSR6,s_chan[ch].ADSRX.SustainIncrease,TRUE); + SetDlgItemInt(hW,IDC_SADSR7,s_chan[ch].ADSRX.lVolume,TRUE); + wsprintf(szB,"%08lX",s_chan[ch].ADSRX.EnvelopeVol); + SetDlgItemText(hW,IDC_SADSR8,szB); + + if(dx) // something to draw? + { + HPEN hPO=SelectObject(hdc,hPAdsr[1]); // sel A pen + dn=r.left; + MoveToEx(hdc,dn,r.bottom,NULL); // move to bottom left corner + + dn+=(ia*r.right)/dx; // calc A x line pos + LineTo(hdc,dn,r.top); // line to AxPos,top + + SelectObject(hdc,hPAdsr[2]); // sel D pen + dn+=(id*r.right)/dx; // calc D x line pos + dy=r.top+((1024-s_chan[ch].ADSR.SustainLevel)* // calc the D y pos + r.bottom)/1024; // (our S level is ranged from 0 to 1024) + LineTo(hdc,dn,dy); // line to DxPos,SLevel + + SelectObject(hdc,hPAdsr[3]); // sel S pen + if(s_chan[ch].ADSR.SustainTime>10000) + dm=1; // we have to fake the S values... S will + else // inc/decrease until channel stop... + if(s_chan[ch].ADSR.SustainTime==0) + dm=0; // we dunno here when this will happen, + else + dm=21-(((s_chan[ch].ADSR.SustainTime/500))); // so we do some more or less angled line, + dy=dy-(s_chan[ch].ADSR.SustainModeDec*dm); // roughly depending on the S time + if(dy>r.bottom) dy=r.bottom; + if(dy>1); + SetDlgItemText(hW,IDC_CI10,szB); + if(s_chan[ch].pCurr==(unsigned char *)-1) + SetDlgItemText(hW,IDC_CI11,"FFFFFFFF"); + else + { + wsprintf(szB,"%08lX",((unsigned long)s_chan[ch].pCurr-(unsigned long)spuMemC)>>1); + SetDlgItemText(hW,IDC_CI11,szB); + } + + wsprintf(szB,"%08lX",((unsigned long)s_chan[ch].pLoop-(unsigned long)spuMemC)>>1); + SetDlgItemText(hW,IDC_CI12,szB); + SetDlgItemInt(hW,IDC_CI13,s_chan[ch].iRightVolume,TRUE); + SetDlgItemInt(hW,IDC_CI14,s_chan[ch].iLeftVolume,TRUE); + SetDlgItemInt(hW,IDC_CI15,s_chan[ch].iActFreq,TRUE); + SetDlgItemInt(hW,IDC_CI16,s_chan[ch].iUsedFreq,TRUE); + +// wsprintf(szB,"%04x",s_chan[ch].iRightVolRaw); + wsprintf(szB,"R%d",s_chan[ch].bVolumeR); + SetDlgItemText(hW,IDC_CI17,szB); +// wsprintf(szB,"%04x",s_chan[ch].iLeftVolRaw); + wsprintf(szB,"L%d",s_chan[ch].bVolumeL); + SetDlgItemText(hW,IDC_CI18,szB); + + wsprintf(szB,"%08lX",s_chan[ch].iNextAdr); + SetDlgItemText(hW,IDC_CI19,szB); + + // generic infos + /*if(pSpuIrq[ch]==0) + SetDlgItemText(hW,IDC_STA1,"FFFFFFFF"); + else + {*/ + wsprintf(szB,"%08lX",((unsigned long)pSpuIrq[ch/24]-(unsigned long)spuMemC)>>1); + SetDlgItemText(hW,IDC_STA1,szB); + /*}*/ + + wsprintf(szB,"%04X",spuCtrl2[ch/24]); + SetDlgItemText(hW,IDC_STA2,szB); + wsprintf(szB,"%04X",spuStat2[ch/24]); + SetDlgItemText(hW,IDC_STA3,szB); + + wsprintf(szB,"%08lX",spuAddr2[ch/24]); + SetDlgItemText(hW,IDC_STA4,szB); + } + +//////////////////////////////////////////////////////////////////////// +// display everything (called in dialog timer for value refreshing) + +void DisplayDebugInfos(HWND hW) +{ + DisplayStreamInfos(hW); + DisplayADSRInfos(hW); + DisplayChannelInfos(hW); +} + +EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val); +EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg); + +//////////////////////////////////////////////////////////////////////// +// main debug dlg handler + +char old_buffer[128]; +int iBuffRepeats=0; + +BOOL CALLBACK DebugDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + //--------------------------------------------------// init + case WM_INITDIALOG: + { + int i; + ShowCursor(TRUE); // mmm... who is hiding it? main emu? tsts + iSelChannel=0; // sel first channel + iCoreOffset=0; + CheckRadioButton(hW,IDC_CHAN1,IDC_CHAN24,IDC_CHAN1); + CheckRadioButton(hW,IDC_CORE1,IDC_CORE2,IDC_CORE1); + + memset(old_buffer,0,128); + // create brushes/pens + hBStream[0]=CreateSolidBrush(GetSysColor(COLOR_3DFACE)); + hPAdsr[0]=CreatePen(PS_SOLID,0,GetSysColor(COLOR_3DFACE)); + for(i=1;i<6;i++) + { + hBStream[i]=CreateSolidBrush(crStreamCol[i]); + hPAdsr[i]=CreatePen(PS_SOLID,0,crAdsrCol[i]); + } + SetTimer(hW,999,50,NULL); // now create update timer + return TRUE; + } + //--------------------------------------------------// destroy + case WM_DESTROY: + { + int i; + KillTimer(hW,999); // first kill timer + for(i=0;i<6;i++) // then kill brushes/pens + { + DeleteObject(hBStream[i]); + DeleteObject(hPAdsr[i]); + } + }break; + //--------------------------------------------------// timer + case WM_TIMER: + { + if(wParam==999) DisplayDebugInfos(hW); // update all values + }break; + //--------------------------------------------------// command + case WM_COMMAND: + { + if(wParam==IDCANCEL) iDebugMode=2; // cancel? raise flag for destroying the dialog + + if(wParam>=IDC_CORE1 && wParam<=IDC_CORE2) // core clicked? + { + int i; + + if(IsDlgButtonChecked(hW,IDC_CORE1)) // -> sel correct half of channels + iCoreOffset=0; + else iCoreOffset=24; + + for(i=IDC_MUTE1;i<=IDC_MUTE24;i++) + { + if(s_chan[i-IDC_MUTE1+iCoreOffset].iMute) + CheckDlgButton(hW,i,TRUE); + else CheckDlgButton(hW,i,FALSE); + } + + InvalidateRect(hW,NULL,TRUE); + UpdateWindow(hW); + } + + if(wParam>=IDC_MUTE1 && wParam<=IDC_MUTE24) // mute clicked? + { + if(IsDlgButtonChecked(hW,wParam)) // -> mute/unmute it + s_chan[wParam-IDC_MUTE1+iCoreOffset].iMute=1; + else + s_chan[wParam-IDC_MUTE1+iCoreOffset].iMute=0; + } + // all mute/unmute + if(wParam==IDC_MUTEOFF) SendMessage(hW,WM_MUTE,0,0); + if(wParam==IDC_MUTEON) SendMessage(hW,WM_MUTE,1,0); + + if(wParam>=IDC_CHAN1 && wParam<=IDC_CHAN24) // sel channel + { + if(IsDlgButtonChecked(hW,wParam)) + { + iSelChannel=wParam-IDC_CHAN1; + SetDlgItemInt(hW,IDC_CHANNUM,iSelChannel+1,FALSE); + } + } + }break; + //--------------------------------------------------// mute + case WM_MUTE: + { // will be called by the mute/unmute all button and on savestate load + int i; + for(i=IDC_MUTE1;i<=IDC_MUTE24;i++) + { + CheckDlgButton(hW,i,wParam); + if(wParam) + s_chan[i-IDC_MUTE1+iCoreOffset].iMute=1; + else + s_chan[i-IDC_MUTE1+iCoreOffset].iMute=0; + } + }break; + //--------------------------------------------------// size + case WM_SIZE: + if(wParam==SIZE_MINIMIZED) SetFocus(hWMain); // if we get minimized, set the foxus to the main window + break; + //--------------------------------------------------// setcursor + case WM_SETCURSOR: + { + SetCursor(LoadCursor(NULL,IDC_ARROW)); // force the arrow + return TRUE; + } + //--------------------------------------------------// + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// +#include +extern FILE * LogFile; +void logprintf(LPCTSTR pFormat, ...) +{ + if(iDebugMode!=1) return; + if(!IsWindow(hWDebug)) return; + else + { + va_list list; + + va_start(list,pFormat); + vfprintf(LogFile, pFormat, list); + va_end(list); + } + +} + +#endif + diff --git a/plugins/spu2/PeopsSPU2/debug.h b/plugins/spu2/PeopsSPU2/debug.h new file mode 100644 index 0000000..4999b42 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/debug.h @@ -0,0 +1,34 @@ +/*************************************************************************** + debug.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifdef _WIN32 +BOOL CALLBACK DebugDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +void logprintf(LPCTSTR pFormat, ...); +#else + +#define logprintf 0&& + +#endif diff --git a/plugins/spu2/PeopsSPU2/dma.c b/plugins/spu2/PeopsSPU2/dma.c new file mode 100644 index 0000000..dbb39b7 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/dma.c @@ -0,0 +1,339 @@ +/*************************************************************************** + dma.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" +#include "externals.h" +#include "registers.h" +#include "debug.h" +extern void (CALLBACK *irqCallbackDMA4)(); // func of main emu, called on spu irq +extern void (CALLBACK *irqCallbackDMA7)(); // func of main emu, called on spu irq +extern void (CALLBACK *irqCallbackSPU2)(); // func of main emu, called on spu irq +unsigned short interrupt; +extern int SPUCycles; +int SPUStartCycle[2]; +int SPUTargetCycle[2]; + +unsigned long MemAddr[2]; + +ADMA Adma4; +ADMA Adma7; + +//////////////////////////////////////////////////////////////////////// +// READ DMA (many values) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2readDMA4Mem(unsigned short * pusPSXMem,int iSize) +{ + int i; +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("READDMA4 %X - %X\r\n",spuAddr2[0],iSize); + + if(spuAddr2[0]<=0x1fff) + logprintf("# OUTPUT AREA ACCESS #############\r\n"); + } + +#endif + + for(i=0;i0x1fffff) spuAddr2[0]=0; // wrap + } + + spuAddr2[0]+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + + + iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spuStat2[0]&=~0x80; // DMA complete + //if(regArea[(PS2_C0_ADMAS)>>1] != 1) { + // if((regArea[(PS2_C0_ATTR)>>1] & 0x30)) { + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = iSize; + interrupt |= (1<<1); + // } +//} + //regArea[(PS2_C0_ADMAS)>>1] = 0; +} + +EXPORT_GCC void CALLBACK SPU2readDMA7Mem(unsigned short * pusPSXMem,int iSize) +{ + int i; +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("READDMA7 %X - %X\r\n",spuAddr2[1],iSize); + + if(spuAddr2[1]<=0x1fff) + logprintf("# OUTPUT AREA ACCESS #############\r\n"); + } +#endif + + for(i=0;i0x1fffff) spuAddr2[1]=0; // wrap + } + +spuAddr2[1]+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + + iSpuAsyncWait=0; + + // got from J.F. and Kanodin... is it needed? + spuStat2[1]&=~0x80; // DMA complete + // if(regArea[(PS2_C1_ADMAS)>>1] != 2) { + // if((regArea[(PS2_C1_ATTR)>>1] & 0x30)) { + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = iSize; + interrupt |= (1<<2); + // } + //} + //regArea[(PS2_C1_ADMAS)>>1] = 0; +} + +//////////////////////////////////////////////////////////////////////// +// WRITE DMA (many values) +//////////////////////////////////////////////////////////////////////// + + +// AutoDMA's are used to transfer to the DIRECT INPUT area of the spu2 memory +// Left and Right channels are always interleaved together in the transfer so +// the AutoDMA's deinterleaves them and transfers them. An interrupt is +// generated when half of the buffer (256 short-words for left and 256 +// short-words for right ) has been transferred. Another interrupt occurs at +// the end of the transfer. +int ADMAS4Write() +{ + if(interrupt & 0x2) return 0; + if(Adma4.AmountLeft <= 0) return 1; + +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("ADMAWRITE4 %X - %X\r\n",spuAddr2[0],Adma4.AmountLeft); + if(Adma4.AmountLeft<512) logprintf("FUCK YOU %X\r\n",Adma4.AmountLeft); + } +#endif + + // SPU2 Deinterleaves the Left and Right Channels + memcpy((short*)(spuMem + spuAddr2[0] + 0x2000),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; + memcpy((short*)(spuMem + spuAddr2[0] + 0x2200),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; + spuAddr2[0] = (spuAddr2[0] + 256) & 511; + + //MemAddr[0] += 1024; + Adma4.AmountLeft-=512; + if(Adma4.AmountLeft == 0) + { + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = 1;//512*48000; + spuStat2[0]&=~0x80; + interrupt |= (1<<1); + } + return 0; +} + + +int ADMAS7Write() +{ +if(interrupt & 0x4) return 0; + if(Adma7.AmountLeft <= 0) return 1; + +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("ADMAWRITE7 %X - %X %X\r\n",Adma7.IntPointer,Adma7.AmountLeft,spuAddr2[1]); + } +#endif + + // SPU2 Deinterleaves the Left and Right Channels + memcpy((unsigned char*)(spuMem + spuAddr2[1] + 0x2400),(unsigned char*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + memcpy((unsigned char*)(spuMem + spuAddr2[1] + 0x2600),(unsigned char*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + spuAddr2[1] = (spuAddr2[1] + 256) & 511; + + //MemAddr[1] += 1024; + + Adma7.AmountLeft -= 512; + if(Adma7.AmountLeft <= 0) + { + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = 1;//512*48000; + spuStat2[1]&=~0x80; + interrupt |= (1<<2); + } + return 0; +} + +#include +extern FILE * LogFile; +EXPORT_GCC void CALLBACK SPU2writeDMA4Mem(short * pMem,unsigned int iSize) +{ + //if(Adma4.AmountLeft > 0) return; + if(regArea[PS2_C0_ADMAS] & 0x1 && (spuCtrl2[0] & 0x30) == 0 && iSize) + { + //fwrite(pMem,iSize<<1,1,LogFile); + memset(&Adma4,0,sizeof(ADMA)); + spuAddr2[0] = 0; + Adma4.MemAddr = pMem; + Adma4.AmountLeft = iSize; + ADMAS4Write(); + return; + } + +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("WRITEDMA4 %X - %X\r\n",spuAddr2[0],iSize); + } +#endif + + memcpy((unsigned char*)(spuMem+spuAddr2[0]),(unsigned char*)pMem,iSize<<1); + spuAddr2[0] += iSize; + if(spuCtrl2[0]&0x40 && spuIrq2[0] == spuAddr2[0]){ + regArea[0x7C0] |= 0x4; + irqCallbackSPU2(); + } + if(spuAddr2[0]>0xFFFFE) spuAddr2[0] = 0x2800; + + MemAddr[0] += iSize<<1; + spuStat2[0]&=~0x80; + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = 1;//iSize; + interrupt |= (1<<1); +} + +EXPORT_GCC void CALLBACK SPU2writeDMA7Mem(unsigned short * pMem,int iSize) +{ + // For AutoDMA, the ATTR register's bit 5 and 6 are cleared. + // bit 5 means Data Input Thru Register + // bit 6 means Data Input Thru DMA + //if(Adma7.AmountLeft > 0) return; + + if((regArea[PS2_C1_ADMAS] & 0x2) && (spuCtrl2[1] & 0x30) == 0 && iSize) + { + // fwrite((void*)pMem,iSize<<1,1,LogFile); + memset(&Adma7,0,sizeof(ADMA)); + spuAddr2[1] = 0; + Adma7.MemAddr = pMem; + Adma7.AmountLeft = iSize; + ADMAS7Write(); + return; + } +#ifdef _WINDOWS + if(iDebugMode==1) + { + logprintf("WRITEDMA7 %X - %X\r\n",spuAddr2[1],iSize); + } +#endif + + memcpy((short*)(spuMem+spuAddr2[1]),(short*)pMem,iSize<<1); + spuAddr2[1] += iSize; + if(spuCtrl2[1]&0x40 && spuIrq2[1] == spuAddr2[1]){ + regArea[0x7C0] |= 0x8; + irqCallbackSPU2(); + } + if(spuAddr2[1]>0xFFFFE) spuAddr2[1] = 0x2800; + + MemAddr[1] += iSize<<1; + spuStat2[1]&=~0x80; + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = 1;//iSize; + interrupt |= (1<<2); +} + + +//////////////////////////////////////////////////////////////////////// +// INTERRUPTS +//////////////////////////////////////////////////////////////////////// + +void InterruptDMA4(void) +{ +// taken from linuzappz NULL spu2 +// spu2Rs16(CORE0_ATTR)&= ~0x30; +// spu2Rs16(REG__1B0) = 0; +// spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80; + +#ifdef _WINDOWS + if(iDebugMode==1) logprintf("IRQDMA4\r\n"); +#endif + + spuCtrl2[0]&=~0x30; + spuStat2[0]|=0x80; +} + +EXPORT_GCC void CALLBACK SPU2interruptDMA4(void) +{ + InterruptDMA4(); +} + +void InterruptDMA7(void) +{ +// taken from linuzappz NULL spu2 +// spu2Rs16(CORE1_ATTR)&= ~0x30; +// spu2Rs16(REG__5B0) = 0; +// spu2Rs16(SPU2_STATX_DREQ)|= 0x80; + +#ifdef _WINDOWS + if(iDebugMode==1) logprintf("IRQDMA7\r\n"); +#endif + + spuStat2[1]|=0x80; + spuCtrl2[1]&=~0x30; +} + +EXPORT_GCC void CALLBACK SPU2interruptDMA7(void) +{ + InterruptDMA7(); +} + +EXPORT_GCC void CALLBACK SPU2WriteMemAddr(int core, unsigned long value) +{ + MemAddr[core] = value; +} + +EXPORT_GCC unsigned long CALLBACK SPU2ReadMemAddr(int core) +{ + return MemAddr[core]; +} \ No newline at end of file diff --git a/plugins/spu2/PeopsSPU2/dma.h b/plugins/spu2/PeopsSPU2/dma.h new file mode 100644 index 0000000..4314b60 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/dma.h @@ -0,0 +1,28 @@ +/*************************************************************************** + dma.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +void InterruptDMA4(void); +void InterruptDMA7(void); diff --git a/plugins/spu2/PeopsSPU2/dsound.c b/plugins/spu2/PeopsSPU2/dsound.c new file mode 100644 index 0000000..a35b2d8 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/dsound.c @@ -0,0 +1,268 @@ +/*************************************************************************** + dsound.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2005/08/29 - Pete +// - changed to 48Khz output +// +// 2003/01/12 - Pete +// - added recording funcs +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_DSOUND + +#include "externals.h" + +#ifdef _WINDOWS +#define _LPCWAVEFORMATEX_DEFINED +#include "dsound.h" + +#include "record.h" + +//////////////////////////////////////////////////////////////////////// +// dsound globals +//////////////////////////////////////////////////////////////////////// + +LPDIRECTSOUND lpDS; +LPDIRECTSOUNDBUFFER lpDSBPRIMARY = NULL; +LPDIRECTSOUNDBUFFER lpDSBSECONDARY1 = NULL; +LPDIRECTSOUNDBUFFER lpDSBSECONDARY2 = NULL; +DSBUFFERDESC dsbd; +DSBUFFERDESC dsbdesc; +DSCAPS dscaps; +DSBCAPS dsbcaps; + +unsigned long LastWrite=0xffffffff; +unsigned long LastWriteS=0xffffffff; +unsigned long LastPlay=0; + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound(void) +{ + HRESULT dsval;WAVEFORMATEX pcmwf; + + dsval = DirectSoundCreate(NULL,&lpDS,NULL); + if(dsval!=DS_OK) + { + MessageBox(hWMain,"DirectSoundCreate!","Error",MB_OK); + return; + } + + if(DS_OK!=IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_PRIORITY)) + { + if(DS_OK!=IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_NORMAL)) + { + MessageBox(hWMain,"SetCooperativeLevel!","Error",MB_OK); + return; + } + } + + memset(&dsbd,0,sizeof(DSBUFFERDESC)); + dsbd.dwSize = sizeof(DSBUFFERDESC); // NT4 hack! sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbd.dwBufferBytes = 0; + dsbd.lpwfxFormat = NULL; + + dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbd,&lpDSBPRIMARY,NULL); + if(dsval!=DS_OK) + { + MessageBox(hWMain, "CreateSoundBuffer (Primary)", "Error",MB_OK); + return; + } + + memset(&pcmwf, 0, sizeof(WAVEFORMATEX)); + pcmwf.wFormatTag = WAVE_FORMAT_PCM; + + pcmwf.nChannels = 2; + pcmwf.nBlockAlign = 4; + + pcmwf.nSamplesPerSec = 48000; + + pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; + pcmwf.wBitsPerSample = 16; + + dsval=IDirectSoundBuffer_SetFormat(lpDSBPRIMARY,&pcmwf); + if(dsval!=DS_OK) + { + MessageBox(hWMain, "SetFormat!", "Error",MB_OK); + return; + } + + dscaps.dwSize = sizeof(DSCAPS); + dsbcaps.dwSize = sizeof(DSBCAPS); + IDirectSound_GetCaps(lpDS,&dscaps); + IDirectSoundBuffer_GetCaps(lpDSBPRIMARY,&dsbcaps); + + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); // NT4 hack! sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_LOCHARDWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; + dsbdesc.dwBufferBytes = SOUNDSIZE; + dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; + + dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL); + if(dsval!=DS_OK) + { + dsbdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2; + dsval=IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL); + if(dsval!=DS_OK) + { + MessageBox(hWMain,"CreateSoundBuffer (Secondary1)", "Error",MB_OK); + return; + } + } + + + + dsval=IDirectSoundBuffer_Play(lpDSBPRIMARY,0,0,DSBPLAY_LOOPING); + if(dsval!=DS_OK) + { + MessageBox(hWMain,"Play (Primary)","Error",MB_OK); + return; + } + + dsval=IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING); + if(dsval!=DS_OK) + { + MessageBox(hWMain,"Play (Secondary1)","Error",MB_OK); + return; + } + +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + int iRes; + + if(iDoRecord) RecordStop(); + + if(lpDSBSECONDARY1!=NULL) + { + IDirectSoundBuffer_Stop(lpDSBSECONDARY1); + iRes=IDirectSoundBuffer_Release(lpDSBSECONDARY1); + // FF says such a loop is bad... Demo says it's good... Pete doesn't care + while(iRes!=0) iRes=IDirectSoundBuffer_Release(lpDSBSECONDARY1); + lpDSBSECONDARY1=NULL; + } + + if(lpDSBPRIMARY!=NULL) + { + IDirectSoundBuffer_Stop(lpDSBPRIMARY); + iRes=IDirectSoundBuffer_Release(lpDSBPRIMARY); + // FF says such a loop is bad... Demo says it's good... Pete doesn't care + while(iRes!=0) iRes=IDirectSoundBuffer_Release(lpDSBPRIMARY); + lpDSBPRIMARY=NULL; + } + + if(lpDS!=NULL) + { + iRes=IDirectSound_Release(lpDS); + // FF says such a loop is bad... Demo says it's good... Pete doesn't care + while(iRes!=0) iRes=IDirectSound_Release(lpDS); + lpDS=NULL; + } + +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + unsigned long cplay,cwrite; + + if(LastWrite==0xffffffff) return 0; + + IDirectSoundBuffer_GetCurrentPosition(lpDSBSECONDARY1,&cplay,&cwrite); + + if(cplay>SOUNDSIZE) return SOUNDSIZE; + + if(cplay>2; + + lpSS=(unsigned long *)pSound; + while(dw) {*lpSD++=*lpSS++;dw--;} + + if(lpvPtr2) + { + lpSD=(unsigned long *)lpvPtr2; + dw=dwBytes2>>2; + while(dw) {*lpSD++=*lpSS++;dw--;} + } + + IDirectSoundBuffer_Unlock(lpDSBSECONDARY1,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2); + LastWrite+=lBytes; + if(LastWrite>=SOUNDSIZE) LastWrite-=SOUNDSIZE; + LastPlay=cplay; +} +#endif + + + diff --git a/plugins/spu2/PeopsSPU2/dsound.h b/plugins/spu2/PeopsSPU2/dsound.h new file mode 100644 index 0000000..f03fff1 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/dsound.h @@ -0,0 +1,2357 @@ +/*==========================================================================; + * + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * File: dsound.h + * Content: DirectSound include file + * + **************************************************************************/ + +#define COM_NO_WINDOWS_H +#include +#include + +#ifndef DIRECTSOUND_VERSION +#define DIRECTSOUND_VERSION 0x0900 /* Version 9.0 */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifndef __DSOUND_INCLUDED__ +#define __DSOUND_INCLUDED__ + +/* Type definitions shared with Direct3D */ + +#ifndef DX_SHARED_DEFINES + +typedef float D3DVALUE, *LPD3DVALUE; + +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +#ifndef LPD3DCOLOR_DEFINED +typedef DWORD *LPD3DCOLOR; +#define LPD3DCOLOR_DEFINED +#endif + +#ifndef D3DVECTOR_DEFINED +typedef struct _D3DVECTOR { + float x; + float y; + float z; +} D3DVECTOR; +#define D3DVECTOR_DEFINED +#endif + +#ifndef LPD3DVECTOR_DEFINED +typedef D3DVECTOR *LPD3DVECTOR; +#define LPD3DVECTOR_DEFINED +#endif + +#define DX_SHARED_DEFINES +#endif // DX_SHARED_DEFINES + +#define _FACDS 0x878 /* DirectSound's facility code */ +#define MAKE_DSHRESULT(code) MAKE_HRESULT(1, _FACDS, code) + +// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000} +DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); + +// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B} +DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b); + +// DirectSound Capture Component GUID {B0210780-89CD-11D0-AF08-00A0C925CD16} +DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +// DirectSound 8.0 Capture Component GUID {E4BCAC13-7F99-4908-9A8E-74E3BF24B6E1} +DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1); + +// DirectSound Full Duplex Component GUID {FEA4300C-7959-4147-B26A-2377B9E7A91D} +DEFINE_GUID(CLSID_DirectSoundFullDuplex, 0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d); + + +// DirectSound default playback device GUID {DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default capture device GUID {DEF00001-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default device for voice playback {DEF00002-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultVoicePlayback, 0xdef00002, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default device for voice capture {DEF00003-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xdef00003, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + + +// +// Forward declarations for interfaces. +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +// + +#ifdef __cplusplus +struct IDirectSound; +struct IDirectSoundBuffer; +struct IDirectSound3DListener; +struct IDirectSound3DBuffer; +struct IDirectSoundCapture; +struct IDirectSoundCaptureBuffer; +struct IDirectSoundNotify; +#endif // __cplusplus + + +// +// DirectSound 8.0 interfaces. +// + +#if DIRECTSOUND_VERSION >= 0x0800 + +#ifdef __cplusplus +struct IDirectSound8; +struct IDirectSoundBuffer8; +struct IDirectSoundCaptureBuffer8; +struct IDirectSoundFXGargle; +struct IDirectSoundFXChorus; +struct IDirectSoundFXFlanger; +struct IDirectSoundFXEcho; +struct IDirectSoundFXDistortion; +struct IDirectSoundFXCompressor; +struct IDirectSoundFXParamEq; +struct IDirectSoundFXWavesReverb; +struct IDirectSoundFXI3DL2Reverb; +struct IDirectSoundCaptureFXAec; +struct IDirectSoundCaptureFXNoiseSuppress; +struct IDirectSoundFullDuplex; +#endif // __cplusplus + +// IDirectSound8, IDirectSoundBuffer8 and IDirectSoundCaptureBuffer8 are the +// only DirectSound 7.0 interfaces with changed functionality in version 8.0. +// The other level 8 interfaces as equivalent to their level 7 counterparts: + +#define IDirectSoundCapture8 IDirectSoundCapture +#define IDirectSound3DListener8 IDirectSound3DListener +#define IDirectSound3DBuffer8 IDirectSound3DBuffer +#define IDirectSoundNotify8 IDirectSoundNotify +#define IDirectSoundFXGargle8 IDirectSoundFXGargle +#define IDirectSoundFXChorus8 IDirectSoundFXChorus +#define IDirectSoundFXFlanger8 IDirectSoundFXFlanger +#define IDirectSoundFXEcho8 IDirectSoundFXEcho +#define IDirectSoundFXDistortion8 IDirectSoundFXDistortion +#define IDirectSoundFXCompressor8 IDirectSoundFXCompressor +#define IDirectSoundFXParamEq8 IDirectSoundFXParamEq +#define IDirectSoundFXWavesReverb8 IDirectSoundFXWavesReverb +#define IDirectSoundFXI3DL2Reverb8 IDirectSoundFXI3DL2Reverb +#define IDirectSoundCaptureFXAec8 IDirectSoundCaptureFXAec +#define IDirectSoundCaptureFXNoiseSuppress8 IDirectSoundCaptureFXNoiseSuppress +#define IDirectSoundFullDuplex8 IDirectSoundFullDuplex + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +typedef struct IDirectSound *LPDIRECTSOUND; +typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; +typedef struct IDirectSound3DListener *LPDIRECTSOUND3DLISTENER; +typedef struct IDirectSound3DBuffer *LPDIRECTSOUND3DBUFFER; +typedef struct IDirectSoundCapture *LPDIRECTSOUNDCAPTURE; +typedef struct IDirectSoundCaptureBuffer *LPDIRECTSOUNDCAPTUREBUFFER; +typedef struct IDirectSoundNotify *LPDIRECTSOUNDNOTIFY; + + +#if DIRECTSOUND_VERSION >= 0x0800 + +typedef struct IDirectSoundFXGargle *LPDIRECTSOUNDFXGARGLE; +typedef struct IDirectSoundFXChorus *LPDIRECTSOUNDFXCHORUS; +typedef struct IDirectSoundFXFlanger *LPDIRECTSOUNDFXFLANGER; +typedef struct IDirectSoundFXEcho *LPDIRECTSOUNDFXECHO; +typedef struct IDirectSoundFXDistortion *LPDIRECTSOUNDFXDISTORTION; +typedef struct IDirectSoundFXCompressor *LPDIRECTSOUNDFXCOMPRESSOR; +typedef struct IDirectSoundFXParamEq *LPDIRECTSOUNDFXPARAMEQ; +typedef struct IDirectSoundFXWavesReverb *LPDIRECTSOUNDFXWAVESREVERB; +typedef struct IDirectSoundFXI3DL2Reverb *LPDIRECTSOUNDFXI3DL2REVERB; +typedef struct IDirectSoundCaptureFXAec *LPDIRECTSOUNDCAPTUREFXAEC; +typedef struct IDirectSoundCaptureFXNoiseSuppress *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS; +typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX; + +typedef struct IDirectSound8 *LPDIRECTSOUND8; +typedef struct IDirectSoundBuffer8 *LPDIRECTSOUNDBUFFER8; +typedef struct IDirectSound3DListener8 *LPDIRECTSOUND3DLISTENER8; +typedef struct IDirectSound3DBuffer8 *LPDIRECTSOUND3DBUFFER8; +typedef struct IDirectSoundCapture8 *LPDIRECTSOUNDCAPTURE8; +typedef struct IDirectSoundCaptureBuffer8 *LPDIRECTSOUNDCAPTUREBUFFER8; +typedef struct IDirectSoundNotify8 *LPDIRECTSOUNDNOTIFY8; +typedef struct IDirectSoundFXGargle8 *LPDIRECTSOUNDFXGARGLE8; +typedef struct IDirectSoundFXChorus8 *LPDIRECTSOUNDFXCHORUS8; +typedef struct IDirectSoundFXFlanger8 *LPDIRECTSOUNDFXFLANGER8; +typedef struct IDirectSoundFXEcho8 *LPDIRECTSOUNDFXECHO8; +typedef struct IDirectSoundFXDistortion8 *LPDIRECTSOUNDFXDISTORTION8; +typedef struct IDirectSoundFXCompressor8 *LPDIRECTSOUNDFXCOMPRESSOR8; +typedef struct IDirectSoundFXParamEq8 *LPDIRECTSOUNDFXPARAMEQ8; +typedef struct IDirectSoundFXWavesReverb8 *LPDIRECTSOUNDFXWAVESREVERB8; +typedef struct IDirectSoundFXI3DL2Reverb8 *LPDIRECTSOUNDFXI3DL2REVERB8; +typedef struct IDirectSoundCaptureFXAec8 *LPDIRECTSOUNDCAPTUREFXAEC8; +typedef struct IDirectSoundCaptureFXNoiseSuppress8 *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS8; +typedef struct IDirectSoundFullDuplex8 *LPDIRECTSOUNDFULLDUPLEX8; + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IID definitions for the unchanged DirectSound 8.0 interfaces +// + +#if DIRECTSOUND_VERSION >= 0x0800 + +#define IID_IDirectSoundCapture8 IID_IDirectSoundCapture +#define IID_IDirectSound3DListener8 IID_IDirectSound3DListener +#define IID_IDirectSound3DBuffer8 IID_IDirectSound3DBuffer +#define IID_IDirectSoundNotify8 IID_IDirectSoundNotify +#define IID_IDirectSoundFXGargle8 IID_IDirectSoundFXGargle +#define IID_IDirectSoundFXChorus8 IID_IDirectSoundFXChorus +#define IID_IDirectSoundFXFlanger8 IID_IDirectSoundFXFlanger +#define IID_IDirectSoundFXEcho8 IID_IDirectSoundFXEcho +#define IID_IDirectSoundFXDistortion8 IID_IDirectSoundFXDistortion +#define IID_IDirectSoundFXCompressor8 IID_IDirectSoundFXCompressor +#define IID_IDirectSoundFXParamEq8 IID_IDirectSoundFXParamEq +#define IID_IDirectSoundFXWavesReverb8 IID_IDirectSoundFXWavesReverb +#define IID_IDirectSoundFXI3DL2Reverb8 IID_IDirectSoundFXI3DL2Reverb +#define IID_IDirectSoundCaptureFXAec8 IID_IDirectSoundCaptureFXAec +#define IID_IDirectSoundCaptureFXNoiseSuppress8 IID_IDirectSoundCaptureFXNoiseSuppress +#define IID_IDirectSoundFullDuplex8 IID_IDirectSoundFullDuplex + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Compatibility typedefs +// + +#ifndef _LPCWAVEFORMATEX_DEFINED +#define _LPCWAVEFORMATEX_DEFINED +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#endif // _LPCWAVEFORMATEX_DEFINED + +#ifndef __LPCGUID_DEFINED__ +#define __LPCGUID_DEFINED__ +typedef const GUID *LPCGUID; +#endif // __LPCGUID_DEFINED__ + +typedef LPDIRECTSOUND *LPLPDIRECTSOUND; +typedef LPDIRECTSOUNDBUFFER *LPLPDIRECTSOUNDBUFFER; +typedef LPDIRECTSOUND3DLISTENER *LPLPDIRECTSOUND3DLISTENER; +typedef LPDIRECTSOUND3DBUFFER *LPLPDIRECTSOUND3DBUFFER; +typedef LPDIRECTSOUNDCAPTURE *LPLPDIRECTSOUNDCAPTURE; +typedef LPDIRECTSOUNDCAPTUREBUFFER *LPLPDIRECTSOUNDCAPTUREBUFFER; +typedef LPDIRECTSOUNDNOTIFY *LPLPDIRECTSOUNDNOTIFY; + +#if DIRECTSOUND_VERSION >= 0x0800 +typedef LPDIRECTSOUND8 *LPLPDIRECTSOUND8; +typedef LPDIRECTSOUNDBUFFER8 *LPLPDIRECTSOUNDBUFFER8; +typedef LPDIRECTSOUNDCAPTURE8 *LPLPDIRECTSOUNDCAPTURE8; +typedef LPDIRECTSOUNDCAPTUREBUFFER8 *LPLPDIRECTSOUNDCAPTUREBUFFER8; +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Structures +// + +typedef struct _DSCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwMinSecondarySampleRate; + DWORD dwMaxSecondarySampleRate; + DWORD dwPrimaryBuffers; + DWORD dwMaxHwMixingAllBuffers; + DWORD dwMaxHwMixingStaticBuffers; + DWORD dwMaxHwMixingStreamingBuffers; + DWORD dwFreeHwMixingAllBuffers; + DWORD dwFreeHwMixingStaticBuffers; + DWORD dwFreeHwMixingStreamingBuffers; + DWORD dwMaxHw3DAllBuffers; + DWORD dwMaxHw3DStaticBuffers; + DWORD dwMaxHw3DStreamingBuffers; + DWORD dwFreeHw3DAllBuffers; + DWORD dwFreeHw3DStaticBuffers; + DWORD dwFreeHw3DStreamingBuffers; + DWORD dwTotalHwMemBytes; + DWORD dwFreeHwMemBytes; + DWORD dwMaxContigFreeHwMemBytes; + DWORD dwUnlockTransferRateHwBuffers; + DWORD dwPlayCpuOverheadSwBuffers; + DWORD dwReserved1; + DWORD dwReserved2; +} DSCAPS, *LPDSCAPS; + +typedef const DSCAPS *LPCDSCAPS; + +typedef struct _DSBCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwUnlockTransferRate; + DWORD dwPlayCpuOverhead; +} DSBCAPS, *LPDSBCAPS; + +typedef const DSBCAPS *LPCDSBCAPS; + +#if DIRECTSOUND_VERSION >= 0x0800 + + typedef struct _DSEFFECTDESC + { + DWORD dwSize; + DWORD dwFlags; + GUID guidDSFXClass; + DWORD_PTR dwReserved1; + DWORD_PTR dwReserved2; + } DSEFFECTDESC, *LPDSEFFECTDESC; + typedef const DSEFFECTDESC *LPCDSEFFECTDESC; + + #define DSFX_LOCHARDWARE 0x00000001 + #define DSFX_LOCSOFTWARE 0x00000002 + + enum + { + DSFXR_PRESENT, // 0 + DSFXR_LOCHARDWARE, // 1 + DSFXR_LOCSOFTWARE, // 2 + DSFXR_UNALLOCATED, // 3 + DSFXR_FAILED, // 4 + DSFXR_UNKNOWN, // 5 + DSFXR_SENDLOOP // 6 + }; + + typedef struct _DSCEFFECTDESC + { + DWORD dwSize; + DWORD dwFlags; + GUID guidDSCFXClass; + GUID guidDSCFXInstance; + DWORD dwReserved1; + DWORD dwReserved2; + } DSCEFFECTDESC, *LPDSCEFFECTDESC; + typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC; + + #define DSCFX_LOCHARDWARE 0x00000001 + #define DSCFX_LOCSOFTWARE 0x00000002 + + #define DSCFXR_LOCHARDWARE 0x00000010 + #define DSCFXR_LOCSOFTWARE 0x00000020 + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +typedef struct _DSBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +#if DIRECTSOUND_VERSION >= 0x0700 + GUID guid3DAlgorithm; +#endif +} DSBUFFERDESC, *LPDSBUFFERDESC; + +typedef const DSBUFFERDESC *LPCDSBUFFERDESC; + +// Older version of this structure: + +typedef struct _DSBUFFERDESC1 +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSBUFFERDESC1, *LPDSBUFFERDESC1; + +typedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1; + +typedef struct _DS3DBUFFER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + DWORD dwInsideConeAngle; + DWORD dwOutsideConeAngle; + D3DVECTOR vConeOrientation; + LONG lConeOutsideVolume; + D3DVALUE flMinDistance; + D3DVALUE flMaxDistance; + DWORD dwMode; +} DS3DBUFFER, *LPDS3DBUFFER; + +typedef const DS3DBUFFER *LPCDS3DBUFFER; + +typedef struct _DS3DLISTENER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + D3DVECTOR vOrientFront; + D3DVECTOR vOrientTop; + D3DVALUE flDistanceFactor; + D3DVALUE flRolloffFactor; + D3DVALUE flDopplerFactor; +} DS3DLISTENER, *LPDS3DLISTENER; + +typedef const DS3DLISTENER *LPCDS3DLISTENER; + +typedef struct _DSCCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwFormats; + DWORD dwChannels; +} DSCCAPS, *LPDSCCAPS; + +typedef const DSCCAPS *LPCDSCCAPS; + +typedef struct _DSCBUFFERDESC1 +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSCBUFFERDESC1, *LPDSCBUFFERDESC1; + +typedef struct _DSCBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +#if DIRECTSOUND_VERSION >= 0x0800 + DWORD dwFXCount; + LPDSCEFFECTDESC lpDSCFXDesc; +#endif +} DSCBUFFERDESC, *LPDSCBUFFERDESC; + +typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC; + +typedef struct _DSCBCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; +} DSCBCAPS, *LPDSCBCAPS; + +typedef const DSCBCAPS *LPCDSCBCAPS; + +typedef struct _DSBPOSITIONNOTIFY +{ + DWORD dwOffset; + HANDLE hEventNotify; +} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY; + +typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY; + +// +// DirectSound API +// + +typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID); +typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID); + +extern HRESULT WINAPI DirectSoundCreate(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); +extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); + +extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); +extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); + +#if DIRECTSOUND_VERSION >= 0x0800 +extern HRESULT WINAPI DirectSoundCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice, + LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd, + DWORD dwLevel, LPDIRECTSOUNDFULLDUPLEX* ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, + LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter); +#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate + +extern HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest); +#endif // DIRECTSOUND_VERSION >= 0x0800 + +#ifdef UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKW +#define DirectSoundEnumerate DirectSoundEnumerateW +#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW +#else // UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKA +#define DirectSoundEnumerate DirectSoundEnumerateA +#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA +#endif // UNICODE + +// +// IUnknown +// + +#if !defined(__cplusplus) || defined(CINTERFACE) +#ifndef IUnknown_QueryInterface +#define IUnknown_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#endif // IUnknown_QueryInterface +#ifndef IUnknown_AddRef +#define IUnknown_AddRef(p) (p)->lpVtbl->AddRef(p) +#endif // IUnknown_AddRef +#ifndef IUnknown_Release +#define IUnknown_Release(p) (p)->lpVtbl->Release(p) +#endif // IUnknown_Release +#else // !defined(__cplusplus) || defined(CINTERFACE) +#ifndef IUnknown_QueryInterface +#define IUnknown_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#endif // IUnknown_QueryInterface +#ifndef IUnknown_AddRef +#define IUnknown_AddRef(p) (p)->AddRef() +#endif // IUnknown_AddRef +#ifndef IUnknown_Release +#define IUnknown_Release(p) (p)->Release() +#endif // IUnknown_Release +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#ifndef __IReferenceClock_INTERFACE_DEFINED__ +#define __IReferenceClock_INTERFACE_DEFINED__ + +typedef LONGLONG REFERENCE_TIME; +typedef REFERENCE_TIME *LPREFERENCE_TIME; + +DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); + +#undef INTERFACE +#define INTERFACE IReferenceClock + +DECLARE_INTERFACE_(IReferenceClock, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IReferenceClock methods + STDMETHOD(GetTime) (THIS_ REFERENCE_TIME *pTime) PURE; + STDMETHOD(AdviseTime) (THIS_ REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, + HANDLE hEvent, LPDWORD pdwAdviseCookie) PURE; + STDMETHOD(AdvisePeriodic) (THIS_ REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, + HANDLE hSemaphore, LPDWORD pdwAdviseCookie) PURE; + STDMETHOD(Unadvise) (THIS_ DWORD dwAdviseCookie) PURE; +}; + +#endif // __IReferenceClock_INTERFACE_DEFINED__ + +#ifndef IReferenceClock_QueryInterface + +#define IReferenceClock_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IReferenceClock_AddRef(p) IUnknown_AddRef(p) +#define IReferenceClock_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IReferenceClock_GetTime(p,a) (p)->lpVtbl->GetTime(p,a) +#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->lpVtbl->AdviseTime(p,a,b,c,d) +#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->lpVtbl->AdvisePeriodic(p,a,b,c,d) +#define IReferenceClock_Unadvise(p,a) (p)->lpVtbl->Unadvise(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IReferenceClock_GetTime(p,a) (p)->GetTime(a) +#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->AdviseTime(a,b,c,d) +#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->AdvisePeriodic(a,b,c,d) +#define IReferenceClock_Unadvise(p,a) (p)->Unadvise(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // IReferenceClock_QueryInterface + +// +// IDirectSound +// + +DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound + +DECLARE_INTERFACE_(IDirectSound, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound methods + STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; + STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; + STDMETHOD(Compact) (THIS) PURE; + STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; + STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; +}; + +#define IDirectSound_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) +#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectSound_Compact(p) (p)->Compact() +#define IDirectSound_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->SetSpeakerConfig(b) +#define IDirectSound_Initialize(p,a) (p)->Initialize(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSound8 +// + +DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66); + +#undef INTERFACE +#define INTERFACE IDirectSound8 + +DECLARE_INTERFACE_(IDirectSound8, IDirectSound) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound methods + STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; + STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; + STDMETHOD(Compact) (THIS) PURE; + STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; + STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; + + // IDirectSound8 methods + STDMETHOD(VerifyCertification) (THIS_ LPDWORD pdwCertified) PURE; +}; + +#define IDirectSound8_QueryInterface(p,a,b) IDirectSound_QueryInterface(p,a,b) +#define IDirectSound8_AddRef(p) IDirectSound_AddRef(p) +#define IDirectSound8_Release(p) IDirectSound_Release(p) +#define IDirectSound8_CreateSoundBuffer(p,a,b,c) IDirectSound_CreateSoundBuffer(p,a,b,c) +#define IDirectSound8_GetCaps(p,a) IDirectSound_GetCaps(p,a) +#define IDirectSound8_DuplicateSoundBuffer(p,a,b) IDirectSound_DuplicateSoundBuffer(p,a,b) +#define IDirectSound8_SetCooperativeLevel(p,a,b) IDirectSound_SetCooperativeLevel(p,a,b) +#define IDirectSound8_Compact(p) IDirectSound_Compact(p) +#define IDirectSound8_GetSpeakerConfig(p,a) IDirectSound_GetSpeakerConfig(p,a) +#define IDirectSound8_SetSpeakerConfig(p,a) IDirectSound_SetSpeakerConfig(p,a) +#define IDirectSound8_Initialize(p,a) IDirectSound_Initialize(p,a) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound8_VerifyCertification(p,a) (p)->lpVtbl->VerifyCertification(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound8_VerifyCertification(p,a) (p)->VerifyCertification(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundBuffer +// + +DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer + +DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; + STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; + STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; + STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; + STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; + STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; + STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; + STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + STDMETHOD(Restore) (THIS) PURE; +}; + +#define IDirectSoundBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) +#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->GetVolume(a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->GetPan(a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->GetFrequency(a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->GetStatus(a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->Play(a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->SetFormat(a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->SetVolume(a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->SetPan(a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->SetFrequency(a) +#define IDirectSoundBuffer_Stop(p) (p)->Stop() +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->Restore() +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundBuffer8 +// + +DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825a449, 0x7524, 0x4d82, 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e); + +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer8 + +DECLARE_INTERFACE_(IDirectSoundBuffer8, IDirectSoundBuffer) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; + STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; + STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; + STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; + STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; + STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; + STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; + STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + STDMETHOD(Restore) (THIS) PURE; + + // IDirectSoundBuffer8 methods + STDMETHOD(SetFX) (THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE; + STDMETHOD(AcquireResources) (THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE; + STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; +}; + +// Special GUID meaning "select all objects" for use in GetObjectInPath() +DEFINE_GUID(GUID_All_Objects, 0xaa114de5, 0xc262, 0x4169, 0xa1, 0xc8, 0x23, 0xd6, 0x98, 0xcc, 0x73, 0xb5); + +#define IDirectSoundBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundBuffer8_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundBuffer8_Release(p) IUnknown_Release(p) + +#define IDirectSoundBuffer8_GetCaps(p,a) IDirectSoundBuffer_GetCaps(p,a) +#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) IDirectSoundBuffer_GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer8_GetFormat(p,a,b,c) IDirectSoundBuffer_GetFormat(p,a,b,c) +#define IDirectSoundBuffer8_GetVolume(p,a) IDirectSoundBuffer_GetVolume(p,a) +#define IDirectSoundBuffer8_GetPan(p,a) IDirectSoundBuffer_GetPan(p,a) +#define IDirectSoundBuffer8_GetFrequency(p,a) IDirectSoundBuffer_GetFrequency(p,a) +#define IDirectSoundBuffer8_GetStatus(p,a) IDirectSoundBuffer_GetStatus(p,a) +#define IDirectSoundBuffer8_Initialize(p,a,b) IDirectSoundBuffer_Initialize(p,a,b) +#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer8_Play(p,a,b,c) IDirectSoundBuffer_Play(p,a,b,c) +#define IDirectSoundBuffer8_SetCurrentPosition(p,a) IDirectSoundBuffer_SetCurrentPosition(p,a) +#define IDirectSoundBuffer8_SetFormat(p,a) IDirectSoundBuffer_SetFormat(p,a) +#define IDirectSoundBuffer8_SetVolume(p,a) IDirectSoundBuffer_SetVolume(p,a) +#define IDirectSoundBuffer8_SetPan(p,a) IDirectSoundBuffer_SetPan(p,a) +#define IDirectSoundBuffer8_SetFrequency(p,a) IDirectSoundBuffer_SetFrequency(p,a) +#define IDirectSoundBuffer8_Stop(p) IDirectSoundBuffer_Stop(p) +#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) IDirectSoundBuffer_Unlock(p,a,b,c,d) +#define IDirectSoundBuffer8_Restore(p) IDirectSoundBuffer_Restore(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->lpVtbl->SetFX(p,a,b,c) +#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->lpVtbl->AcquireResources(p,a,b,c) +#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->SetFX(a,b,c) +#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->AcquireResources(a,b,c) +#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSound3DListener +// + +DEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound3DListener + +DECLARE_INTERFACE_(IDirectSound3DListener, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound3DListener methods + STDMETHOD(GetAllParameters) (THIS_ LPDS3DLISTENER pListener) PURE; + STDMETHOD(GetDistanceFactor) (THIS_ D3DVALUE* pflDistanceFactor) PURE; + STDMETHOD(GetDopplerFactor) (THIS_ D3DVALUE* pflDopplerFactor) PURE; + STDMETHOD(GetOrientation) (THIS_ D3DVECTOR* pvOrientFront, D3DVECTOR* pvOrientTop) PURE; + STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; + STDMETHOD(GetRolloffFactor) (THIS_ D3DVALUE* pflRolloffFactor) PURE; + STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; + STDMETHOD(SetAllParameters) (THIS_ LPCDS3DLISTENER pcListener, DWORD dwApply) PURE; + STDMETHOD(SetDistanceFactor) (THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE; + STDMETHOD(SetDopplerFactor) (THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE; + STDMETHOD(SetOrientation) (THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, + D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE; + STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetRolloffFactor) (THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE; + STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(CommitDeferredSettings) (THIS) PURE; +}; + +#define IDirectSound3DListener_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound3DListener_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound3DListener_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->lpVtbl->GetDistanceFactor(p,a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->lpVtbl->GetDopplerFactor(p,a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->lpVtbl->GetOrientation(p,a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->lpVtbl->GetRolloffFactor(p,a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->lpVtbl->SetDistanceFactor(p,a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->lpVtbl->SetDopplerFactor(p,a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->lpVtbl->SetRolloffFactor(p,a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->lpVtbl->CommitDeferredSettings(p) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->GetDistanceFactor(a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->GetDopplerFactor(a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->GetOrientation(a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->GetRolloffFactor(a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->SetDistanceFactor(a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->SetDopplerFactor(a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->SetOrientation(a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->SetRolloffFactor(a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->CommitDeferredSettings() +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSound3DBuffer +// + +DEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound3DBuffer + +DECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound3DBuffer methods + STDMETHOD(GetAllParameters) (THIS_ LPDS3DBUFFER pDs3dBuffer) PURE; + STDMETHOD(GetConeAngles) (THIS_ LPDWORD pdwInsideConeAngle, LPDWORD pdwOutsideConeAngle) PURE; + STDMETHOD(GetConeOrientation) (THIS_ D3DVECTOR* pvOrientation) PURE; + STDMETHOD(GetConeOutsideVolume) (THIS_ LPLONG plConeOutsideVolume) PURE; + STDMETHOD(GetMaxDistance) (THIS_ D3DVALUE* pflMaxDistance) PURE; + STDMETHOD(GetMinDistance) (THIS_ D3DVALUE* pflMinDistance) PURE; + STDMETHOD(GetMode) (THIS_ LPDWORD pdwMode) PURE; + STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; + STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; + STDMETHOD(SetAllParameters) (THIS_ LPCDS3DBUFFER pcDs3dBuffer, DWORD dwApply) PURE; + STDMETHOD(SetConeAngles) (THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE; + STDMETHOD(SetConeOrientation) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetConeOutsideVolume) (THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE; + STDMETHOD(SetMaxDistance) (THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE; + STDMETHOD(SetMinDistance) (THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE; + STDMETHOD(SetMode) (THIS_ DWORD dwMode, DWORD dwApply) PURE; + STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; +}; + +#define IDirectSound3DBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound3DBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound3DBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->lpVtbl->GetConeAngles(p,a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->lpVtbl->GetConeOrientation(p,a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->lpVtbl->GetConeOutsideVolume(p,a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->lpVtbl->GetMinDistance(p,a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->lpVtbl->GetMaxDistance(p,a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->lpVtbl->GetMode(p,a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->lpVtbl->SetConeAngles(p,a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->lpVtbl->SetConeOrientation(p,a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->lpVtbl->SetConeOutsideVolume(p,a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->lpVtbl->SetMinDistance(p,a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->lpVtbl->SetMaxDistance(p,a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->lpVtbl->SetMode(p,a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->GetConeAngles(a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->GetConeOrientation(a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->GetConeOutsideVolume(a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->GetMinDistance(a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->GetMaxDistance(a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->GetMode(a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->SetConeAngles(a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->SetConeOrientation(a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->SetConeOutsideVolume(a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->SetMinDistance(a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->SetMaxDistance(a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->SetMode(a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCapture +// + +DEFINE_GUID(IID_IDirectSoundCapture, 0xb0210781, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundCapture + +DECLARE_INTERFACE_(IDirectSoundCapture, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCapture methods + STDMETHOD(CreateCaptureBuffer) (THIS_ LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCCAPS pDSCCaps) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; +}; + +#define IDirectSoundCapture_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCapture_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCapture_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c) +#define IDirectSoundCapture_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundCapture_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->CreateCaptureBuffer(a,b,c) +#define IDirectSoundCapture_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundCapture_Initialize(p,a) (p)->Initialize(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCaptureBuffer +// + +DEFINE_GUID(IID_IDirectSoundCaptureBuffer, 0xb0210782, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureBuffer + +DECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; +}; + +#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer_Start(p,a) (p)->lpVtbl->Start(p,a) +#define IDirectSoundCaptureBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) +#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) +#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->GetStatus(a) +#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer_Start(p,a) (p)->Start(a) +#define IDirectSoundCaptureBuffer_Stop(p) (p)->Stop() +#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundCaptureBuffer8 +// + +DEFINE_GUID(IID_IDirectSoundCaptureBuffer8, 0x990df4, 0xdbb, 0x4872, 0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6); + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureBuffer8 + +DECLARE_INTERFACE_(IDirectSoundCaptureBuffer8, IDirectSoundCaptureBuffer) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + + // IDirectSoundCaptureBuffer8 methods + STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; + STDMETHOD(GetFXStatus) (DWORD dwFXCount, LPDWORD pdwFXStatus) PURE; +}; + +#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureBuffer8_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureBuffer8_Release(p) IUnknown_Release(p) + +#define IDirectSoundCaptureBuffer8_GetCaps(p,a) IDirectSoundCaptureBuffer_GetCaps(p,a) +#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) +#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) +#define IDirectSoundCaptureBuffer8_GetStatus(p,a) IDirectSoundCaptureBuffer_GetStatus(p,a) +#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) IDirectSoundCaptureBuffer_Initialize(p,a,b) +#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer8_Start(p,a) IDirectSoundCaptureBuffer_Start(p,a) +#define IDirectSoundCaptureBuffer8_Stop(p) IDirectSoundCaptureBuffer_Stop(p)) +#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) +#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->lpVtbl->GetFXStatus(p,a,b) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) +#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->GetFXStatus(a,b) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundNotify +// + +DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundNotify + +DECLARE_INTERFACE_(IDirectSoundNotify, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundNotify methods + STDMETHOD(SetNotificationPositions) (THIS_ DWORD dwPositionNotifies, LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE; +}; + +#define IDirectSoundNotify_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundNotify_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundNotify_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->lpVtbl->SetNotificationPositions(p,a,b) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->SetNotificationPositions(a,b) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IKsPropertySet +// + +#ifndef _IKsPropertySet_ +#define _IKsPropertySet_ + +#ifdef __cplusplus +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +struct IKsPropertySet; +#endif // __cplusplus + +typedef struct IKsPropertySet *LPKSPROPERTYSET; + +#define KSPROPERTY_SUPPORT_GET 0x00000001 +#define KSPROPERTY_SUPPORT_SET 0x00000002 + +DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93); + +#undef INTERFACE +#define INTERFACE IKsPropertySet + +DECLARE_INTERFACE_(IKsPropertySet, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IKsPropertySet methods + STDMETHOD(Get) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, + LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE; + STDMETHOD(Set) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, + LPVOID pPropertyData, ULONG ulDataLength) PURE; + STDMETHOD(QuerySupport) (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE; +}; + +#define IKsPropertySet_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IKsPropertySet_AddRef(p) IUnknown_AddRef(p) +#define IKsPropertySet_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->lpVtbl->Get(p,a,b,c,d,e,f,g) +#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->lpVtbl->Set(p,a,b,c,d,e,f) +#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->lpVtbl->QuerySupport(p,a,b,c) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->Get(a,b,c,d,e,f,g) +#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->Set(a,b,c,d,e,f) +#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->QuerySupport(a,b,c) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // _IKsPropertySet_ + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundFXGargle +// + +DEFINE_GUID(IID_IDirectSoundFXGargle, 0xd616f352, 0xd622, 0x11ce, 0xaa, 0xc5, 0x00, 0x20, 0xaf, 0x0b, 0x99, 0xa3); + +typedef struct _DSFXGargle +{ + DWORD dwRateHz; // Rate of modulation in hz + DWORD dwWaveShape; // DSFXGARGLE_WAVE_xxx +} DSFXGargle, *LPDSFXGargle; + +#define DSFXGARGLE_WAVE_TRIANGLE 0 +#define DSFXGARGLE_WAVE_SQUARE 1 + +typedef const DSFXGargle *LPCDSFXGargle; + +#define DSFXGARGLE_RATEHZ_MIN 1 +#define DSFXGARGLE_RATEHZ_MAX 1000 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXGargle + +DECLARE_INTERFACE_(IDirectSoundFXGargle, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXGargle methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXGargle pcDsFxGargle) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXGargle pDsFxGargle) PURE; +}; + +#define IDirectSoundFXGargle_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXGargle_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXGargle_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXChorus +// + +DEFINE_GUID(IID_IDirectSoundFXChorus, 0x880842e3, 0x145f, 0x43e6, 0xa9, 0x34, 0xa7, 0x18, 0x06, 0xe5, 0x05, 0x47); + +typedef struct _DSFXChorus +{ + FLOAT fWetDryMix; + FLOAT fDepth; + FLOAT fFeedback; + FLOAT fFrequency; + LONG lWaveform; // LFO shape; DSFXCHORUS_WAVE_xxx + FLOAT fDelay; + LONG lPhase; +} DSFXChorus, *LPDSFXChorus; + +typedef const DSFXChorus *LPCDSFXChorus; + +#define DSFXCHORUS_WAVE_TRIANGLE 0 +#define DSFXCHORUS_WAVE_SIN 1 + +#define DSFXCHORUS_WETDRYMIX_MIN 0.0f +#define DSFXCHORUS_WETDRYMIX_MAX 100.0f +#define DSFXCHORUS_DEPTH_MIN 0.0f +#define DSFXCHORUS_DEPTH_MAX 100.0f +#define DSFXCHORUS_FEEDBACK_MIN -99.0f +#define DSFXCHORUS_FEEDBACK_MAX 99.0f +#define DSFXCHORUS_FREQUENCY_MIN 0.0f +#define DSFXCHORUS_FREQUENCY_MAX 10.0f +#define DSFXCHORUS_DELAY_MIN 0.0f +#define DSFXCHORUS_DELAY_MAX 20.0f +#define DSFXCHORUS_PHASE_MIN 0 +#define DSFXCHORUS_PHASE_MAX 4 + +#define DSFXCHORUS_PHASE_NEG_180 0 +#define DSFXCHORUS_PHASE_NEG_90 1 +#define DSFXCHORUS_PHASE_ZERO 2 +#define DSFXCHORUS_PHASE_90 3 +#define DSFXCHORUS_PHASE_180 4 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXChorus + +DECLARE_INTERFACE_(IDirectSoundFXChorus, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXChorus methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXChorus pcDsFxChorus) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXChorus pDsFxChorus) PURE; +}; + +#define IDirectSoundFXChorus_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXChorus_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXChorus_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXFlanger +// + +DEFINE_GUID(IID_IDirectSoundFXFlanger, 0x903e9878, 0x2c92, 0x4072, 0x9b, 0x2c, 0xea, 0x68, 0xf5, 0x39, 0x67, 0x83); + +typedef struct _DSFXFlanger +{ + FLOAT fWetDryMix; + FLOAT fDepth; + FLOAT fFeedback; + FLOAT fFrequency; + LONG lWaveform; + FLOAT fDelay; + LONG lPhase; +} DSFXFlanger, *LPDSFXFlanger; + +typedef const DSFXFlanger *LPCDSFXFlanger; + +#define DSFXFLANGER_WAVE_TRIANGLE 0 +#define DSFXFLANGER_WAVE_SIN 1 + +#define DSFXFLANGER_WETDRYMIX_MIN 0.0f +#define DSFXFLANGER_WETDRYMIX_MAX 100.0f +#define DSFXFLANGER_FREQUENCY_MIN 0.0f +#define DSFXFLANGER_FREQUENCY_MAX 10.0f +#define DSFXFLANGER_DEPTH_MIN 0.0f +#define DSFXFLANGER_DEPTH_MAX 100.0f +#define DSFXFLANGER_PHASE_MIN 0 +#define DSFXFLANGER_PHASE_MAX 4 +#define DSFXFLANGER_FEEDBACK_MIN -99.0f +#define DSFXFLANGER_FEEDBACK_MAX 99.0f +#define DSFXFLANGER_DELAY_MIN 0.0f +#define DSFXFLANGER_DELAY_MAX 4.0f + +#define DSFXFLANGER_PHASE_NEG_180 0 +#define DSFXFLANGER_PHASE_NEG_90 1 +#define DSFXFLANGER_PHASE_ZERO 2 +#define DSFXFLANGER_PHASE_90 3 +#define DSFXFLANGER_PHASE_180 4 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXFlanger + +DECLARE_INTERFACE_(IDirectSoundFXFlanger, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXFlanger methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXFlanger pcDsFxFlanger) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXFlanger pDsFxFlanger) PURE; +}; + +#define IDirectSoundFXFlanger_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXFlanger_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXFlanger_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXEcho +// + +DEFINE_GUID(IID_IDirectSoundFXEcho, 0x8bd28edf, 0x50db, 0x4e92, 0xa2, 0xbd, 0x44, 0x54, 0x88, 0xd1, 0xed, 0x42); + +typedef struct _DSFXEcho +{ + FLOAT fWetDryMix; + FLOAT fFeedback; + FLOAT fLeftDelay; + FLOAT fRightDelay; + LONG lPanDelay; +} DSFXEcho, *LPDSFXEcho; + +typedef const DSFXEcho *LPCDSFXEcho; + +#define DSFXECHO_WETDRYMIX_MIN 0.0f +#define DSFXECHO_WETDRYMIX_MAX 100.0f +#define DSFXECHO_FEEDBACK_MIN 0.0f +#define DSFXECHO_FEEDBACK_MAX 100.0f +#define DSFXECHO_LEFTDELAY_MIN 1.0f +#define DSFXECHO_LEFTDELAY_MAX 2000.0f +#define DSFXECHO_RIGHTDELAY_MIN 1.0f +#define DSFXECHO_RIGHTDELAY_MAX 2000.0f +#define DSFXECHO_PANDELAY_MIN 0 +#define DSFXECHO_PANDELAY_MAX 1 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXEcho + +DECLARE_INTERFACE_(IDirectSoundFXEcho, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXEcho methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXEcho pcDsFxEcho) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXEcho pDsFxEcho) PURE; +}; + +#define IDirectSoundFXEcho_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXEcho_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXEcho_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXDistortion +// + +DEFINE_GUID(IID_IDirectSoundFXDistortion, 0x8ecf4326, 0x455f, 0x4d8b, 0xbd, 0xa9, 0x8d, 0x5d, 0x3e, 0x9e, 0x3e, 0x0b); + +typedef struct _DSFXDistortion +{ + FLOAT fGain; + FLOAT fEdge; + FLOAT fPostEQCenterFrequency; + FLOAT fPostEQBandwidth; + FLOAT fPreLowpassCutoff; +} DSFXDistortion, *LPDSFXDistortion; + +typedef const DSFXDistortion *LPCDSFXDistortion; + +#define DSFXDISTORTION_GAIN_MIN -60.0f +#define DSFXDISTORTION_GAIN_MAX 0.0f +#define DSFXDISTORTION_EDGE_MIN 0.0f +#define DSFXDISTORTION_EDGE_MAX 100.0f +#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN 100.0f +#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX 8000.0f +#define DSFXDISTORTION_POSTEQBANDWIDTH_MIN 100.0f +#define DSFXDISTORTION_POSTEQBANDWIDTH_MAX 8000.0f +#define DSFXDISTORTION_PRELOWPASSCUTOFF_MIN 100.0f +#define DSFXDISTORTION_PRELOWPASSCUTOFF_MAX 8000.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXDistortion + +DECLARE_INTERFACE_(IDirectSoundFXDistortion, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXDistortion methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXDistortion pcDsFxDistortion) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXDistortion pDsFxDistortion) PURE; +}; + +#define IDirectSoundFXDistortion_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXDistortion_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXDistortion_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXCompressor +// + +DEFINE_GUID(IID_IDirectSoundFXCompressor, 0x4bbd1154, 0x62f6, 0x4e2c, 0xa1, 0x5c, 0xd3, 0xb6, 0xc4, 0x17, 0xf7, 0xa0); + +typedef struct _DSFXCompressor +{ + FLOAT fGain; + FLOAT fAttack; + FLOAT fRelease; + FLOAT fThreshold; + FLOAT fRatio; + FLOAT fPredelay; +} DSFXCompressor, *LPDSFXCompressor; + +typedef const DSFXCompressor *LPCDSFXCompressor; + +#define DSFXCOMPRESSOR_GAIN_MIN -60.0f +#define DSFXCOMPRESSOR_GAIN_MAX 60.0f +#define DSFXCOMPRESSOR_ATTACK_MIN 0.01f +#define DSFXCOMPRESSOR_ATTACK_MAX 500.0f +#define DSFXCOMPRESSOR_RELEASE_MIN 50.0f +#define DSFXCOMPRESSOR_RELEASE_MAX 3000.0f +#define DSFXCOMPRESSOR_THRESHOLD_MIN -60.0f +#define DSFXCOMPRESSOR_THRESHOLD_MAX 0.0f +#define DSFXCOMPRESSOR_RATIO_MIN 1.0f +#define DSFXCOMPRESSOR_RATIO_MAX 100.0f +#define DSFXCOMPRESSOR_PREDELAY_MIN 0.0f +#define DSFXCOMPRESSOR_PREDELAY_MAX 4.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXCompressor + +DECLARE_INTERFACE_(IDirectSoundFXCompressor, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXCompressor methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXCompressor pcDsFxCompressor) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXCompressor pDsFxCompressor) PURE; +}; + +#define IDirectSoundFXCompressor_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXCompressor_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXCompressor_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXParamEq +// + +DEFINE_GUID(IID_IDirectSoundFXParamEq, 0xc03ca9fe, 0xfe90, 0x4204, 0x80, 0x78, 0x82, 0x33, 0x4c, 0xd1, 0x77, 0xda); + +typedef struct _DSFXParamEq +{ + FLOAT fCenter; + FLOAT fBandwidth; + FLOAT fGain; +} DSFXParamEq, *LPDSFXParamEq; + +typedef const DSFXParamEq *LPCDSFXParamEq; + +#define DSFXPARAMEQ_CENTER_MIN 80.0f +#define DSFXPARAMEQ_CENTER_MAX 16000.0f +#define DSFXPARAMEQ_BANDWIDTH_MIN 1.0f +#define DSFXPARAMEQ_BANDWIDTH_MAX 36.0f +#define DSFXPARAMEQ_GAIN_MIN -15.0f +#define DSFXPARAMEQ_GAIN_MAX 15.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXParamEq + +DECLARE_INTERFACE_(IDirectSoundFXParamEq, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXParamEq methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXParamEq pcDsFxParamEq) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXParamEq pDsFxParamEq) PURE; +}; + +#define IDirectSoundFXParamEq_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXParamEq_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXParamEq_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXI3DL2Reverb +// + +DEFINE_GUID(IID_IDirectSoundFXI3DL2Reverb, 0x4b166a6a, 0x0d66, 0x43f3, 0x80, 0xe3, 0xee, 0x62, 0x80, 0xde, 0xe1, 0xa4); + +typedef struct _DSFXI3DL2Reverb +{ + LONG lRoom; // [-10000, 0] default: -1000 mB + LONG lRoomHF; // [-10000, 0] default: 0 mB + FLOAT flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 + FLOAT flDecayTime; // [0.1, 20.0] default: 1.49s + FLOAT flDecayHFRatio; // [0.1, 2.0] default: 0.83 + LONG lReflections; // [-10000, 1000] default: -2602 mB + FLOAT flReflectionsDelay; // [0.0, 0.3] default: 0.007 s + LONG lReverb; // [-10000, 2000] default: 200 mB + FLOAT flReverbDelay; // [0.0, 0.1] default: 0.011 s + FLOAT flDiffusion; // [0.0, 100.0] default: 100.0 % + FLOAT flDensity; // [0.0, 100.0] default: 100.0 % + FLOAT flHFReference; // [20.0, 20000.0] default: 5000.0 Hz +} DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb; + +typedef const DSFXI3DL2Reverb *LPCDSFXI3DL2Reverb; + +#define DSFX_I3DL2REVERB_ROOM_MIN (-10000) +#define DSFX_I3DL2REVERB_ROOM_MAX 0 +#define DSFX_I3DL2REVERB_ROOM_DEFAULT (-1000) + +#define DSFX_I3DL2REVERB_ROOMHF_MIN (-10000) +#define DSFX_I3DL2REVERB_ROOMHF_MAX 0 +#define DSFX_I3DL2REVERB_ROOMHF_DEFAULT (-100) + +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN 0.0f +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX 10.0f +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT 0.0f + +#define DSFX_I3DL2REVERB_DECAYTIME_MIN 0.1f +#define DSFX_I3DL2REVERB_DECAYTIME_MAX 20.0f +#define DSFX_I3DL2REVERB_DECAYTIME_DEFAULT 1.49f + +#define DSFX_I3DL2REVERB_DECAYHFRATIO_MIN 0.1f +#define DSFX_I3DL2REVERB_DECAYHFRATIO_MAX 2.0f +#define DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT 0.83f + +#define DSFX_I3DL2REVERB_REFLECTIONS_MIN (-10000) +#define DSFX_I3DL2REVERB_REFLECTIONS_MAX 1000 +#define DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT (-2602) + +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN 0.0f +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX 0.3f +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT 0.007f + +#define DSFX_I3DL2REVERB_REVERB_MIN (-10000) +#define DSFX_I3DL2REVERB_REVERB_MAX 2000 +#define DSFX_I3DL2REVERB_REVERB_DEFAULT (200) + +#define DSFX_I3DL2REVERB_REVERBDELAY_MIN 0.0f +#define DSFX_I3DL2REVERB_REVERBDELAY_MAX 0.1f +#define DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT 0.011f + +#define DSFX_I3DL2REVERB_DIFFUSION_MIN 0.0f +#define DSFX_I3DL2REVERB_DIFFUSION_MAX 100.0f +#define DSFX_I3DL2REVERB_DIFFUSION_DEFAULT 100.0f + +#define DSFX_I3DL2REVERB_DENSITY_MIN 0.0f +#define DSFX_I3DL2REVERB_DENSITY_MAX 100.0f +#define DSFX_I3DL2REVERB_DENSITY_DEFAULT 100.0f + +#define DSFX_I3DL2REVERB_HFREFERENCE_MIN 20.0f +#define DSFX_I3DL2REVERB_HFREFERENCE_MAX 20000.0f +#define DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT 5000.0f + +#define DSFX_I3DL2REVERB_QUALITY_MIN 0 +#define DSFX_I3DL2REVERB_QUALITY_MAX 3 +#define DSFX_I3DL2REVERB_QUALITY_DEFAULT 2 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXI3DL2Reverb + +DECLARE_INTERFACE_(IDirectSoundFXI3DL2Reverb, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXI3DL2Reverb methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXI3DL2Reverb pcDsFxI3DL2Reverb) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXI3DL2Reverb pDsFxI3DL2Reverb) PURE; + STDMETHOD(SetPreset) (THIS_ DWORD dwPreset) PURE; + STDMETHOD(GetPreset) (THIS_ LPDWORD pdwPreset) PURE; + STDMETHOD(SetQuality) (THIS_ LONG lQuality) PURE; + STDMETHOD(GetQuality) (THIS_ LONG *plQuality) PURE; +}; + +#define IDirectSoundFXI3DL2Reverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXI3DL2Reverb_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXI3DL2Reverb_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->lpVtbl->SetPreset(p,a) +#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->lpVtbl->GetPreset(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->SetPreset(a) +#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->GetPreset(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXWavesReverb +// + +DEFINE_GUID(IID_IDirectSoundFXWavesReverb,0x46858c3a,0x0dc6,0x45e3,0xb7,0x60,0xd4,0xee,0xf1,0x6c,0xb3,0x25); + +typedef struct _DSFXWavesReverb +{ + FLOAT fInGain; // [-96.0,0.0] default: 0.0 dB + FLOAT fReverbMix; // [-96.0,0.0] default: 0.0 db + FLOAT fReverbTime; // [0.001,3000.0] default: 1000.0 ms + FLOAT fHighFreqRTRatio; // [0.001,0.999] default: 0.001 +} DSFXWavesReverb, *LPDSFXWavesReverb; + +typedef const DSFXWavesReverb *LPCDSFXWavesReverb; + +#define DSFX_WAVESREVERB_INGAIN_MIN -96.0f +#define DSFX_WAVESREVERB_INGAIN_MAX 0.0f +#define DSFX_WAVESREVERB_INGAIN_DEFAULT 0.0f +#define DSFX_WAVESREVERB_REVERBMIX_MIN -96.0f +#define DSFX_WAVESREVERB_REVERBMIX_MAX 0.0f +#define DSFX_WAVESREVERB_REVERBMIX_DEFAULT 0.0f +#define DSFX_WAVESREVERB_REVERBTIME_MIN 0.001f +#define DSFX_WAVESREVERB_REVERBTIME_MAX 3000.0f +#define DSFX_WAVESREVERB_REVERBTIME_DEFAULT 1000.0f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN 0.001f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX 0.999f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT 0.001f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXWavesReverb + +DECLARE_INTERFACE_(IDirectSoundFXWavesReverb, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXWavesReverb methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXWavesReverb pcDsFxWavesReverb) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXWavesReverb pDsFxWavesReverb) PURE; +}; + +#define IDirectSoundFXWavesReverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXWavesReverb_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXWavesReverb_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCaptureFXAec +// + +DEFINE_GUID(IID_IDirectSoundCaptureFXAec, 0xad74143d, 0x903d, 0x4ab7, 0x80, 0x66, 0x28, 0xd3, 0x63, 0x03, 0x6d, 0x65); + +typedef struct _DSCFXAec +{ + BOOL fEnable; + BOOL fNoiseFill; + DWORD dwMode; +} DSCFXAec, *LPDSCFXAec; + +typedef const DSCFXAec *LPCDSCFXAec; + +// These match the AEC_MODE_* constants in the DDK's ksmedia.h file +#define DSCFX_AEC_MODE_PASS_THROUGH 0x0 +#define DSCFX_AEC_MODE_HALF_DUPLEX 0x1 +#define DSCFX_AEC_MODE_FULL_DUPLEX 0x2 + +// These match the AEC_STATUS_* constants in ksmedia.h +#define DSCFX_AEC_STATUS_HISTORY_UNINITIALIZED 0x0 +#define DSCFX_AEC_STATUS_HISTORY_CONTINUOUSLY_CONVERGED 0x1 +#define DSCFX_AEC_STATUS_HISTORY_PREVIOUSLY_DIVERGED 0x2 +#define DSCFX_AEC_STATUS_CURRENTLY_CONVERGED 0x8 + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureFXAec + +DECLARE_INTERFACE_(IDirectSoundCaptureFXAec, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureFXAec methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXAec pDscFxAec) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSCFXAec pDscFxAec) PURE; + STDMETHOD(GetStatus) (THIS_ PDWORD pdwStatus) PURE; + STDMETHOD(Reset) (THIS) PURE; +}; + +#define IDirectSoundCaptureFXAec_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureFXAec_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureFXAec_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundCaptureFXNoiseSuppress +// + +DEFINE_GUID(IID_IDirectSoundCaptureFXNoiseSuppress, 0xed311e41, 0xfbae, 0x4175, 0x96, 0x25, 0xcd, 0x8, 0x54, 0xf6, 0x93, 0xca); + +typedef struct _DSCFXNoiseSuppress +{ + BOOL fEnable; +} DSCFXNoiseSuppress, *LPDSCFXNoiseSuppress; + +typedef const DSCFXNoiseSuppress *LPCDSCFXNoiseSuppress; + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureFXNoiseSuppress + +DECLARE_INTERFACE_(IDirectSoundCaptureFXNoiseSuppress, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureFXNoiseSuppress methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXNoiseSuppress pcDscFxNoiseSuppress) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSCFXNoiseSuppress pDscFxNoiseSuppress) PURE; + STDMETHOD(Reset) (THIS) PURE; +}; + +#define IDirectSoundCaptureFXNoiseSuppress_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureFXNoiseSuppress_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureFXNoiseSuppress_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundFullDuplex +// + +#ifndef _IDirectSoundFullDuplex_ +#define _IDirectSoundFullDuplex_ + +#ifdef __cplusplus +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +struct IDirectSoundFullDuplex; +#endif // __cplusplus + + +DEFINE_GUID(IID_IDirectSoundFullDuplex, 0xedcb4c7a, 0xdaab, 0x4216, 0xa4, 0x2e, 0x6c, 0x50, 0x59, 0x6d, 0xdc, 0x1d); + +#undef INTERFACE +#define INTERFACE IDirectSoundFullDuplex + +DECLARE_INTERFACE_(IDirectSoundFullDuplex, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFullDuplex methods + STDMETHOD(Initialize) (THIS_ LPCGUID pCaptureGuid, LPCGUID pRenderGuid, LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc, HWND hWnd, DWORD dwLevel, LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE; +}; + +#define IDirectSoundFullDuplex_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFullDuplex_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFullDuplex_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->Initialize(a,b,c,d,e,f,g,h) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // _IDirectSoundFullDuplex_ + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Return Codes +// + +// The function completed successfully +#define DS_OK S_OK + +// The call succeeded, but we had to substitute the 3D algorithm +#define DS_NO_VIRTUALIZATION MAKE_HRESULT(0, _FACDS, 10) + +// The call failed because resources (such as a priority level) +// were already being used by another caller +#define DSERR_ALLOCATED MAKE_DSHRESULT(10) + +// The control (vol, pan, etc.) requested by the caller is not available +#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30) + +// An invalid parameter was passed to the returning function +#define DSERR_INVALIDPARAM E_INVALIDARG + +// This call is not valid for the current state of this object +#define DSERR_INVALIDCALL MAKE_DSHRESULT(50) + +// An undetermined error occurred inside the DirectSound subsystem +#define DSERR_GENERIC E_FAIL + +// The caller does not have the priority level required for the function to +// succeed +#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70) + +// Not enough free memory is available to complete the operation +#define DSERR_OUTOFMEMORY E_OUTOFMEMORY + +// The specified WAVE format is not supported +#define DSERR_BADFORMAT MAKE_DSHRESULT(100) + +// The function called is not supported at this time +#define DSERR_UNSUPPORTED E_NOTIMPL + +// No sound driver is available for use +#define DSERR_NODRIVER MAKE_DSHRESULT(120) + +// This object is already initialized +#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT(130) + +// This object does not support aggregation +#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION + +// The buffer memory has been lost, and must be restored +#define DSERR_BUFFERLOST MAKE_DSHRESULT(150) + +// Another app has a higher priority level, preventing this call from +// succeeding +#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT(160) + +// This object has not been initialized +#define DSERR_UNINITIALIZED MAKE_DSHRESULT(170) + +// The requested COM interface is not available +#define DSERR_NOINTERFACE E_NOINTERFACE + +// Access is denied +#define DSERR_ACCESSDENIED E_ACCESSDENIED + +// Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds +#define DSERR_BUFFERTOOSMALL MAKE_DSHRESULT(180) + +// Attempt to use DirectSound 8 functionality on an older DirectSound object +#define DSERR_DS8_REQUIRED MAKE_DSHRESULT(190) + +// A circular loop of send effects was detected +#define DSERR_SENDLOOP MAKE_DSHRESULT(200) + +// The GUID specified in an audiopath file does not match a valid MIXIN buffer +#define DSERR_BADSENDBUFFERGUID MAKE_DSHRESULT(210) + +// The object requested was not found (numerically equal to DMUS_E_NOT_FOUND) +#define DSERR_OBJECTNOTFOUND MAKE_DSHRESULT(4449) + +// The effects requested could not be found on the system, or they were found +// but in the wrong order, or in the wrong hardware/software locations. +#define DSERR_FXUNAVAILABLE MAKE_DSHRESULT(220) + +// +// Flags +// + +#define DSCAPS_PRIMARYMONO 0x00000001 +#define DSCAPS_PRIMARYSTEREO 0x00000002 +#define DSCAPS_PRIMARY8BIT 0x00000004 +#define DSCAPS_PRIMARY16BIT 0x00000008 +#define DSCAPS_CONTINUOUSRATE 0x00000010 +#define DSCAPS_EMULDRIVER 0x00000020 +#define DSCAPS_CERTIFIED 0x00000040 +#define DSCAPS_SECONDARYMONO 0x00000100 +#define DSCAPS_SECONDARYSTEREO 0x00000200 +#define DSCAPS_SECONDARY8BIT 0x00000400 +#define DSCAPS_SECONDARY16BIT 0x00000800 + +#define DSSCL_NORMAL 0x00000001 +#define DSSCL_PRIORITY 0x00000002 +#define DSSCL_EXCLUSIVE 0x00000003 +#define DSSCL_WRITEPRIMARY 0x00000004 + +#define DSSPEAKER_DIRECTOUT 0x00000000 +#define DSSPEAKER_HEADPHONE 0x00000001 +#define DSSPEAKER_MONO 0x00000002 +#define DSSPEAKER_QUAD 0x00000003 +#define DSSPEAKER_STEREO 0x00000004 +#define DSSPEAKER_SURROUND 0x00000005 +#define DSSPEAKER_5POINT1 0x00000006 +#define DSSPEAKER_7POINT1 0x00000007 + +#define DSSPEAKER_GEOMETRY_MIN 0x00000005 // 5 degrees +#define DSSPEAKER_GEOMETRY_NARROW 0x0000000A // 10 degrees +#define DSSPEAKER_GEOMETRY_WIDE 0x00000014 // 20 degrees +#define DSSPEAKER_GEOMETRY_MAX 0x000000B4 // 180 degrees + +#define DSSPEAKER_COMBINED(c, g) ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16)) +#define DSSPEAKER_CONFIG(a) ((BYTE)(a)) +#define DSSPEAKER_GEOMETRY(a) ((BYTE)(((DWORD)(a) >> 16) & 0x00FF)) + +#define DSBCAPS_PRIMARYBUFFER 0x00000001 +#define DSBCAPS_STATIC 0x00000002 +#define DSBCAPS_LOCHARDWARE 0x00000004 +#define DSBCAPS_LOCSOFTWARE 0x00000008 +#define DSBCAPS_CTRL3D 0x00000010 +#define DSBCAPS_CTRLFREQUENCY 0x00000020 +#define DSBCAPS_CTRLPAN 0x00000040 +#define DSBCAPS_CTRLVOLUME 0x00000080 +#define DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100 +#define DSBCAPS_CTRLFX 0x00000200 +#define DSBCAPS_STICKYFOCUS 0x00004000 +#define DSBCAPS_GLOBALFOCUS 0x00008000 +#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 +#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000 +#define DSBCAPS_LOCDEFER 0x00040000 + +#define DSBPLAY_LOOPING 0x00000001 +#define DSBPLAY_LOCHARDWARE 0x00000002 +#define DSBPLAY_LOCSOFTWARE 0x00000004 +#define DSBPLAY_TERMINATEBY_TIME 0x00000008 +#define DSBPLAY_TERMINATEBY_DISTANCE 0x000000010 +#define DSBPLAY_TERMINATEBY_PRIORITY 0x000000020 + +#define DSBSTATUS_PLAYING 0x00000001 +#define DSBSTATUS_BUFFERLOST 0x00000002 +#define DSBSTATUS_LOOPING 0x00000004 +#define DSBSTATUS_LOCHARDWARE 0x00000008 +#define DSBSTATUS_LOCSOFTWARE 0x00000010 +#define DSBSTATUS_TERMINATED 0x00000020 + +#define DSBLOCK_FROMWRITECURSOR 0x00000001 +#define DSBLOCK_ENTIREBUFFER 0x00000002 + +#define DSBFREQUENCY_ORIGINAL 0 +#define DSBFREQUENCY_MIN 100 +#if DIRECTSOUND_VERSION >= 0x0900 +#define DSBFREQUENCY_MAX 200000 +#else +#define DSBFREQUENCY_MAX 100000 +#endif + +#define DSBPAN_LEFT -10000 +#define DSBPAN_CENTER 0 +#define DSBPAN_RIGHT 10000 + +#define DSBVOLUME_MIN -10000 +#define DSBVOLUME_MAX 0 + +#define DSBSIZE_MIN 4 +#define DSBSIZE_MAX 0x0FFFFFFF +#define DSBSIZE_FX_MIN 150 // NOTE: Milliseconds, not bytes + +#define DS3DMODE_NORMAL 0x00000000 +#define DS3DMODE_HEADRELATIVE 0x00000001 +#define DS3DMODE_DISABLE 0x00000002 + +#define DS3D_IMMEDIATE 0x00000000 +#define DS3D_DEFERRED 0x00000001 + +#define DS3D_MINDISTANCEFACTOR FLT_MIN +#define DS3D_MAXDISTANCEFACTOR FLT_MAX +#define DS3D_DEFAULTDISTANCEFACTOR 1.0f + +#define DS3D_MINROLLOFFFACTOR 0.0f +#define DS3D_MAXROLLOFFFACTOR 10.0f +#define DS3D_DEFAULTROLLOFFFACTOR 1.0f + +#define DS3D_MINDOPPLERFACTOR 0.0f +#define DS3D_MAXDOPPLERFACTOR 10.0f +#define DS3D_DEFAULTDOPPLERFACTOR 1.0f + +#define DS3D_DEFAULTMINDISTANCE 1.0f +#define DS3D_DEFAULTMAXDISTANCE 1000000000.0f + +#define DS3D_MINCONEANGLE 0 +#define DS3D_MAXCONEANGLE 360 +#define DS3D_DEFAULTCONEANGLE 360 + +#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX + +// IDirectSoundCapture attributes + +#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER +#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED +#define DSCCAPS_MULTIPLECAPTURE 0x00000001 + +// IDirectSoundCaptureBuffer attributes + +#define DSCBCAPS_WAVEMAPPED 0x80000000 + +#if DIRECTSOUND_VERSION >= 0x0800 +#define DSCBCAPS_CTRLFX 0x00000200 +#endif + + +#define DSCBLOCK_ENTIREBUFFER 0x00000001 + +#define DSCBSTATUS_CAPTURING 0x00000001 +#define DSCBSTATUS_LOOPING 0x00000002 + +#define DSCBSTART_LOOPING 0x00000001 + +#define DSBPN_OFFSETSTOP 0xFFFFFFFF + +#define DS_CERTIFIED 0x00000000 +#define DS_UNCERTIFIED 0x00000001 + + +// +// Flags for the I3DL2 effects +// + +// +// I3DL2 Material Presets +// + +enum +{ + DSFX_I3DL2_MATERIAL_PRESET_SINGLEWINDOW, + DSFX_I3DL2_MATERIAL_PRESET_DOUBLEWINDOW, + DSFX_I3DL2_MATERIAL_PRESET_THINDOOR, + DSFX_I3DL2_MATERIAL_PRESET_THICKDOOR, + DSFX_I3DL2_MATERIAL_PRESET_WOODWALL, + DSFX_I3DL2_MATERIAL_PRESET_BRICKWALL, + DSFX_I3DL2_MATERIAL_PRESET_STONEWALL, + DSFX_I3DL2_MATERIAL_PRESET_CURTAIN +}; + +#define I3DL2_MATERIAL_PRESET_SINGLEWINDOW -2800,0.71f +#define I3DL2_MATERIAL_PRESET_DOUBLEWINDOW -5000,0.40f +#define I3DL2_MATERIAL_PRESET_THINDOOR -1800,0.66f +#define I3DL2_MATERIAL_PRESET_THICKDOOR -4400,0.64f +#define I3DL2_MATERIAL_PRESET_WOODWALL -4000,0.50f +#define I3DL2_MATERIAL_PRESET_BRICKWALL -5000,0.60f +#define I3DL2_MATERIAL_PRESET_STONEWALL -6000,0.68f +#define I3DL2_MATERIAL_PRESET_CURTAIN -1200,0.15f + +enum +{ + DSFX_I3DL2_ENVIRONMENT_PRESET_DEFAULT, + DSFX_I3DL2_ENVIRONMENT_PRESET_GENERIC, + DSFX_I3DL2_ENVIRONMENT_PRESET_PADDEDCELL, + DSFX_I3DL2_ENVIRONMENT_PRESET_ROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_BATHROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_LIVINGROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_STONEROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM, + DSFX_I3DL2_ENVIRONMENT_PRESET_CONCERTHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_CAVE, + DSFX_I3DL2_ENVIRONMENT_PRESET_ARENA, + DSFX_I3DL2_ENVIRONMENT_PRESET_HANGAR, + DSFX_I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY, + DSFX_I3DL2_ENVIRONMENT_PRESET_HALLWAY, + DSFX_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR, + DSFX_I3DL2_ENVIRONMENT_PRESET_ALLEY, + DSFX_I3DL2_ENVIRONMENT_PRESET_FOREST, + DSFX_I3DL2_ENVIRONMENT_PRESET_CITY, + DSFX_I3DL2_ENVIRONMENT_PRESET_MOUNTAINS, + DSFX_I3DL2_ENVIRONMENT_PRESET_QUARRY, + DSFX_I3DL2_ENVIRONMENT_PRESET_PLAIN, + DSFX_I3DL2_ENVIRONMENT_PRESET_PARKINGLOT, + DSFX_I3DL2_ENVIRONMENT_PRESET_SEWERPIPE, + DSFX_I3DL2_ENVIRONMENT_PRESET_UNDERWATER, + DSFX_I3DL2_ENVIRONMENT_PRESET_SMALLROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_PLATE +}; + +// +// I3DL2 Reverberation Presets Values +// + +#define I3DL2_ENVIRONMENT_PRESET_DEFAULT -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_GENERIC -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PADDEDCELL -1000,-6000, 0.0f, 0.17f, 0.10f, -1204, 0.001f, 207, 0.002f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ROOM -1000, -454, 0.0f, 0.40f, 0.83f, -1646, 0.002f, 53, 0.003f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_BATHROOM -1000,-1200, 0.0f, 1.49f, 0.54f, -370, 0.007f, 1030, 0.011f, 100.0f, 60.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LIVINGROOM -1000,-6000, 0.0f, 0.50f, 0.10f, -1376, 0.003f, -1104, 0.004f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_STONEROOM -1000, -300, 0.0f, 2.31f, 0.64f, -711, 0.012f, 83, 0.017f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_AUDITORIUM -1000, -476, 0.0f, 4.32f, 0.59f, -789, 0.020f, -289, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CONCERTHALL -1000, -500, 0.0f, 3.92f, 0.70f, -1230, 0.020f, -2, 0.029f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CAVE -1000, 0, 0.0f, 2.91f, 1.30f, -602, 0.015f, -302, 0.022f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ARENA -1000, -698, 0.0f, 7.24f, 0.33f, -1166, 0.020f, 16, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_HANGAR -1000,-1000, 0.0f,10.05f, 0.23f, -602, 0.020f, 198, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY -1000,-4000, 0.0f, 0.30f, 0.10f, -1831, 0.002f, -1630, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_HALLWAY -1000, -300, 0.0f, 1.49f, 0.59f, -1219, 0.007f, 441, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR -1000, -237, 0.0f, 2.70f, 0.79f, -1214, 0.013f, 395, 0.020f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ALLEY -1000, -270, 0.0f, 1.49f, 0.86f, -1204, 0.007f, -4, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_FOREST -1000,-3300, 0.0f, 1.49f, 0.54f, -2560, 0.162f, -613, 0.088f, 79.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CITY -1000, -800, 0.0f, 1.49f, 0.67f, -2273, 0.007f, -2217, 0.011f, 50.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MOUNTAINS -1000,-2500, 0.0f, 1.49f, 0.21f, -2780, 0.300f, -2014, 0.100f, 27.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_QUARRY -1000,-1000, 0.0f, 1.49f, 0.83f,-10000, 0.061f, 500, 0.025f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PLAIN -1000,-2000, 0.0f, 1.49f, 0.50f, -2466, 0.179f, -2514, 0.100f, 21.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PARKINGLOT -1000, 0, 0.0f, 1.65f, 1.50f, -1363, 0.008f, -1153, 0.012f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_SEWERPIPE -1000,-1000, 0.0f, 2.81f, 0.14f, 429, 0.014f, 648, 0.021f, 80.0f, 60.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER -1000,-4000, 0.0f, 1.49f, 0.10f, -449, 0.007f, 1700, 0.011f, 100.0f, 100.0f, 5000.0f + +// +// Examples simulating 'musical' reverb presets +// +// Name Decay time Description +// Small Room 1.1s A small size room with a length of 5m or so. +// Medium Room 1.3s A medium size room with a length of 10m or so. +// Large Room 1.5s A large size room suitable for live performances. +// Medium Hall 1.8s A medium size concert hall. +// Large Hall 1.8s A large size concert hall suitable for a full orchestra. +// Plate 1.3s A plate reverb simulation. +// + +#define I3DL2_ENVIRONMENT_PRESET_SMALLROOM -1000, -600, 0.0f, 1.10f, 0.83f, -400, 0.005f, 500, 0.010f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM -1000, -600, 0.0f, 1.30f, 0.83f, -1000, 0.010f, -200, 0.020f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LARGEROOM -1000, -600, 0.0f, 1.50f, 0.83f, -1600, 0.020f, -1000, 0.040f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL -1000, -600, 0.0f, 1.80f, 0.70f, -1300, 0.015f, -800, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LARGEHALL -1000, -600, 0.0f, 1.80f, 0.70f, -2000, 0.030f, -1400, 0.060f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PLATE -1000, -200, 0.0f, 1.30f, 0.90f, 0, 0.002f, 0, 0.010f, 100.0f, 75.0f, 5000.0f + +// +// DirectSound3D Algorithms +// + +// Default DirectSound3D algorithm {00000000-0000-0000-0000-000000000000} +#define DS3DALG_DEFAULT GUID_NULL + +// No virtualization (Pan3D) {C241333F-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_NO_VIRTUALIZATION, 0xc241333f, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + +// High-quality HRTF algorithm {C2413340-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_HRTF_FULL, 0xc2413340, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + +// Lower-quality HRTF algorithm {C2413342-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_HRTF_LIGHT, 0xc2413342, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// DirectSound Internal Effect Algorithms +// + + +// Gargle {DAFD8210-5711-4B91-9FE3-F75B7AE279BF} +DEFINE_GUID(GUID_DSFX_STANDARD_GARGLE, 0xdafd8210, 0x5711, 0x4b91, 0x9f, 0xe3, 0xf7, 0x5b, 0x7a, 0xe2, 0x79, 0xbf); + +// Chorus {EFE6629C-81F7-4281-BD91-C9D604A95AF6} +DEFINE_GUID(GUID_DSFX_STANDARD_CHORUS, 0xefe6629c, 0x81f7, 0x4281, 0xbd, 0x91, 0xc9, 0xd6, 0x04, 0xa9, 0x5a, 0xf6); + +// Flanger {EFCA3D92-DFD8-4672-A603-7420894BAD98} +DEFINE_GUID(GUID_DSFX_STANDARD_FLANGER, 0xefca3d92, 0xdfd8, 0x4672, 0xa6, 0x03, 0x74, 0x20, 0x89, 0x4b, 0xad, 0x98); + +// Echo/Delay {EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D} +DEFINE_GUID(GUID_DSFX_STANDARD_ECHO, 0xef3e932c, 0xd40b, 0x4f51, 0x8c, 0xcf, 0x3f, 0x98, 0xf1, 0xb2, 0x9d, 0x5d); + +// Distortion {EF114C90-CD1D-484E-96E5-09CFAF912A21} +DEFINE_GUID(GUID_DSFX_STANDARD_DISTORTION, 0xef114c90, 0xcd1d, 0x484e, 0x96, 0xe5, 0x09, 0xcf, 0xaf, 0x91, 0x2a, 0x21); + +// Compressor/Limiter {EF011F79-4000-406D-87AF-BFFB3FC39D57} +DEFINE_GUID(GUID_DSFX_STANDARD_COMPRESSOR, 0xef011f79, 0x4000, 0x406d, 0x87, 0xaf, 0xbf, 0xfb, 0x3f, 0xc3, 0x9d, 0x57); + +// Parametric Equalization {120CED89-3BF4-4173-A132-3CB406CF3231} +DEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, 0x3c, 0xb4, 0x06, 0xcf, 0x32, 0x31); + +// I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4} +DEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4); + +// Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C} +DEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c); + +// +// DirectSound Capture Effect Algorithms +// + + +// Acoustic Echo Canceller {BF963D80-C559-11D0-8A2B-00A0C9255AC1} +// Matches KSNODETYPE_ACOUSTIC_ECHO_CANCEL in ksmedia.h +DEFINE_GUID(GUID_DSCFX_CLASS_AEC, 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1); + +// Microsoft AEC {CDEBB919-379A-488a-8765-F53CFD36DE40} +DEFINE_GUID(GUID_DSCFX_MS_AEC, 0xcdebb919, 0x379a, 0x488a, 0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40); + +// System AEC {1C22C56D-9879-4f5b-A389-27996DDC2810} +DEFINE_GUID(GUID_DSCFX_SYSTEM_AEC, 0x1c22c56d, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10); + +// Noise Supression {E07F903F-62FD-4e60-8CDD-DEA7236665B5} +// Matches KSNODETYPE_NOISE_SUPPRESS in post Windows ME DDK's ksmedia.h +DEFINE_GUID(GUID_DSCFX_CLASS_NS, 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5); + +// Microsoft Noise Suppresion {11C5C73B-66E9-4ba1-A0BA-E814C6EED92D} +DEFINE_GUID(GUID_DSCFX_MS_NS, 0x11c5c73b, 0x66e9, 0x4ba1, 0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d); + +// System Noise Suppresion {5AB0882E-7274-4516-877D-4EEE99BA4FD0} +DEFINE_GUID(GUID_DSCFX_SYSTEM_NS, 0x5ab0882e, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0); + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +#endif // __DSOUND_INCLUDED__ + + + +#ifdef __cplusplus +}; +#endif // __cplusplus + + diff --git a/plugins/spu2/PeopsSPU2/dsoundoss.h b/plugins/spu2/PeopsSPU2/dsoundoss.h new file mode 100644 index 0000000..65c22ee --- /dev/null +++ b/plugins/spu2/PeopsSPU2/dsoundoss.h @@ -0,0 +1,36 @@ +/*************************************************************************** + dsoundoss.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void SetupSound(void); +void RemoveSound(void); +unsigned long SoundGetBytesBuffered(void); +void SoundFeedStreamData(unsigned char* pSound,long lBytes); + +#ifndef _WINDOWS +unsigned long timeGetTime(); +#endif + diff --git a/plugins/spu2/PeopsSPU2/externals.h b/plugins/spu2/PeopsSPU2/externals.h new file mode 100644 index 0000000..7282925 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/externals.h @@ -0,0 +1,362 @@ +/*************************************************************************** + externals.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/04/04 - Pete +// - increased channel struct for interpolation +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +///////////////////////////////////////////////////////// +// generic defines +///////////////////////////////////////////////////////// + +//#define PSE_LT_SPU 4 +//#define PSE_SPU_ERR_SUCCESS 0 +//#define PSE_SPU_ERR -60 +//#define PSE_SPU_ERR_NOTCONFIGURED PSE_SPU_ERR - 1 +//#define PSE_SPU_ERR_INIT PSE_SPU_ERR - 2 + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu defines +//////////////////////////////////////////////////////////////////////// + +// sound buffer sizes +// 500 ms complete sound buffer +#define SOUNDSIZE 76800 + +// 200 ms test buffer... if less than that is buffered, a new upload will happen +#define TESTSIZE 26304//13152 + +// num of channels +#define MAXCHAN 48 +#define HLFCHAN 24 + +// ~ 1 ms of data +#define NSSIZE 48 + +/////////////////////////////////////////////////////////// +// struct defines +/////////////////////////////////////////////////////////// +// ADMA Channels +extern EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle); +typedef struct +{ + unsigned short * MemAddr; + long IntPointer; + int Index; + int AmountLeft; + int Enabled; +} ADMA; + +typedef struct +{ + int Left; + int Right; +} DINPUT; + +// ADSR INFOS PER CHANNEL +typedef struct +{ + int AttackModeExp; + long AttackTime; + long DecayTime; + long SustainLevel; + int SustainModeExp; + long SustainModeDec; + long SustainTime; + int ReleaseModeExp; + unsigned long ReleaseVal; + long ReleaseTime; + long ReleaseStartTime; + long ReleaseVol; + long lTime; + long lVolume; +} ADSRInfo; + +typedef struct +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; + long lDummy1; + long lDummy2; +} ADSRInfoEx; + +/////////////////////////////////////////////////////////// + +// Tmp Flags + +// used for debug channel muting +#define FLAG_MUTE 1 + +// used for simple interpolation +#define FLAG_IPOL0 2 +#define FLAG_IPOL1 4 + +/////////////////////////////////////////////////////////// + +// MAIN CHANNEL STRUCT +typedef struct +{ + // no mutexes used anymore... don't need them to sync access + //HANDLE hMutex; + + int bNew; // start flag + + int iSBPos; // mixing stuff + int spos; + int sinc; + int SB[32+32]; // Pete added another 32 dwords in 1.6 ... prevents overflow issues with gaussian/cubic interpolation (thanx xodnizel!), and can be used for even better interpolations, eh? :) + int sval; + + unsigned char * pStart; // start ptr into sound mem + unsigned char * pCurr; // current pos in sound mem + unsigned char * pLoop; // loop ptr in sound mem + + int iStartAdr; + int iLoopAdr; + int iNextAdr; + + int bOn; // is channel active (sample playing?) + int bStop; // is channel stopped (sample _can_ still be playing, ADSR Release phase) + int bEndPoint; // end point reached + int bReverbL; // can we do reverb on this channel? must have ctrl register bit, to get active + int bReverbR; + + int bVolumeL; // Volume on/off + int bVolumeR; + + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + int iLeftVolume; // left volume + int iLeftVolRaw; // left psx volume value + int bIgnoreLoop; // ignore loop bit, if an external loop address is used + int iMute; // mute mode + int iRightVolume; // right volume + int iRightVolRaw; // right psx volume value + int iRawPitch; // raw pitch (0...3fff) + int iIrqDone; // debug irq done flag + int s_1; // last decoding infos + int s_2; + int bRVBActive; // reverb active flag + int bNoise; // noise active flag + int bFMod; // freq mod (0=off, 1=sound channel, 2=freq channel) + int iOldNoise; // old noise val for this channel + ADSRInfo ADSR; // active ADSR settings + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + +} SPUCHAN; + +/////////////////////////////////////////////////////////// + +typedef struct +{ + int StartAddr; // reverb area start addr in samples + int EndAddr; // reverb area end addr in samples + int CurrAddr; // reverb area curr addr in samples + + int VolLeft; + int VolRight; + int iLastRVBLeft; + int iLastRVBRight; + int iRVBLeft; + int iRVBRight; + int iCnt; + + int FB_SRC_A; // (offset) + int FB_SRC_B; // (offset) + int IIR_ALPHA; // (coef.) + int ACC_COEF_A; // (coef.) + int ACC_COEF_B; // (coef.) + int ACC_COEF_C; // (coef.) + int ACC_COEF_D; // (coef.) + int IIR_COEF; // (coef.) + int FB_ALPHA; // (coef.) + int FB_X; // (coef.) + int IIR_DEST_A0; // (offset) + int IIR_DEST_A1; // (offset) + int ACC_SRC_A0; // (offset) + int ACC_SRC_A1; // (offset) + int ACC_SRC_B0; // (offset) + int ACC_SRC_B1; // (offset) + int IIR_SRC_A0; // (offset) + int IIR_SRC_A1; // (offset) + int IIR_DEST_B0; // (offset) + int IIR_DEST_B1; // (offset) + int ACC_SRC_C0; // (offset) + int ACC_SRC_C1; // (offset) + int ACC_SRC_D0; // (offset) + int ACC_SRC_D1; // (offset) + int IIR_SRC_B1; // (offset) + int IIR_SRC_B0; // (offset) + int MIX_DEST_A0; // (offset) + int MIX_DEST_A1; // (offset) + int MIX_DEST_B0; // (offset) + int MIX_DEST_B1; // (offset) + int IN_COEF_L; // (coef.) + int IN_COEF_R; // (coef.) +} REVERBInfo; + +#ifdef _WINDOWS +extern HINSTANCE hInst; +#define WM_MUTE (WM_USER+543) +#endif + +/////////////////////////////////////////////////////////// +// SPU.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_SPU + +// psx buffers / addresses + +extern unsigned short regArea[]; +extern unsigned short spuMem[]; +extern unsigned char * spuMemC; +extern unsigned char * pSpuIrq[]; +extern unsigned char * pSpuBuffer; + +// user settings + +extern int iUseXA; +extern int iVolume; +extern int iXAPitch; +extern int iUseTimer; +extern int iSPUIRQWait; +extern int iDebugMode; +extern int iRecordMode; +extern int iUseReverb; +extern int iUseInterpolation; +extern int iDisStereo; +extern int aSync; +// MISC + +extern SPUCHAN s_chan[]; +extern REVERBInfo rvb[]; + +extern unsigned long dwNoiseVal; +extern unsigned short spuCtrl2[]; +extern unsigned short spuStat2[]; +extern unsigned long spuIrq2[]; +extern unsigned long spuAddr2[]; +extern unsigned long spuRvbAddr2[]; +extern unsigned long spuRvbAEnd2[]; + +extern int bEndThread; +extern int bThreadEnded; +extern int bSpuInit; + +extern int SSumR[]; +extern int SSumL[]; +extern int iCycle; +extern short * pS; +extern unsigned long dwNewChannel2[]; +extern unsigned long dwEndChannel2[]; + +extern int iSpuAsyncWait; + +#ifdef _WINDOWS +extern HWND hWMain; // window handle +extern HWND hWDebug; +#endif + +extern void (CALLBACK *cddavCallback)(unsigned short,unsigned short); + +#endif + +/////////////////////////////////////////////////////////// +// DSOUND.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_DSOUND + +#ifdef _WINDOWS +extern unsigned long LastWrite; +extern unsigned long LastPlay; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// RECORD.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_RECORD + +#ifdef _WINDOWS +extern int iDoRecord; +#endif + +#endif + +/////////////////////////////////////////////////////////// +// XA.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_XA + +extern xa_decode_t * xapGlobal; + +extern unsigned long * XAFeed; +extern unsigned long * XAPlay; +extern unsigned long * XAStart; +extern unsigned long * XAEnd; + +extern unsigned long XARepeat; +extern unsigned long XALastVal; + +extern int iLeftXAVol; +extern int iRightXAVol; + +#endif + +/////////////////////////////////////////////////////////// +// REVERB.C globals +/////////////////////////////////////////////////////////// + +#ifndef _IN_REVERB + +extern int * sRVBPlay[]; +extern int * sRVBEnd[]; +extern int * sRVBStart[]; + +#endif diff --git a/plugins/spu2/PeopsSPU2/freeze.c b/plugins/spu2/PeopsSPU2/freeze.c new file mode 100644 index 0000000..d745944 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/freeze.c @@ -0,0 +1,246 @@ +/*************************************************************************** + freeze.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/12/24 - Pete +// - freeze functions adapted to pcsx2-0.7 +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/03/20 - Pete +// - fix to prevent the new interpolations from crashing when loading a save state +// +// 2003/01/06 - Pete +// - small changes for version 1.3 adsr save state loading +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_FREEZE + +#include "externals.h" +#include "registers.h" +#include "spu.h" +#include "regs.h" +#include "debug.h" +#include "resource.h" + +//////////////////////////////////////////////////////////////////////// +// freeze structs +//////////////////////////////////////////////////////////////////////// + +typedef struct { + int size; + char *data; +} SPUFreeze_t; + +typedef struct +{ + char szSPUName[8]; + unsigned long ulFreezeVersion; + unsigned long ulFreezeSize; + unsigned char cSPUPort[64*1024]; + unsigned char cSPURam[2*1024*1024]; +} SPUFreeze_Ex_t; + +typedef struct +{ + unsigned long spuIrq0; + unsigned long spuIrq1; + unsigned long pSpuIrq0; + unsigned long pSpuIrq1; + unsigned long dummy0; + unsigned long dummy1; + unsigned long dummy2; + unsigned long dummy3; + + SPUCHAN s_chan[MAXCHAN]; + +} SPUOSSFreeze_t; + +//////////////////////////////////////////////////////////////////////// + +void LoadStateV1(SPUFreeze_Ex_t * pF); // newest version +void LoadStateUnknown(SPUFreeze_Ex_t * pF); // unknown format + +//////////////////////////////////////////////////////////////////////// +// SPUFREEZE: called by main emu on savestate load/save +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK SPU2freeze(unsigned long ulFreezeMode,SPUFreeze_t * pFt) +{ + int i;SPUOSSFreeze_t * pFO;SPUFreeze_Ex_t * pF; + + if(!pFt) return 0; // first check + + if(ulFreezeMode) // save? + {//--------------------------------------------------// + pFt->size=sizeof(SPUFreeze_Ex_t)+sizeof(SPUOSSFreeze_t); + + if(ulFreezeMode==2) return 0; // emu just asking for size? bye + + if(!pFt->data) return 0; + + pF=(SPUFreeze_Ex_t *)pFt->data; + + memset(pF,0,pFt->size); + + strcpy(pF->szSPUName,"PBOSS2"); + pF->ulFreezeVersion=1; + pF->ulFreezeSize=pFt->size; + // save mode: + RemoveTimer(); // stop timer + + memcpy(pF->cSPURam,spuMem,2*1024*1024); // copy common infos + memcpy(pF->cSPUPort,regArea,64*1024); + + pFO=(SPUOSSFreeze_t *)(pF+1); // store special stuff + + pFO->spuIrq0=spuIrq2[0]; + if(pSpuIrq[0]) pFO->pSpuIrq0 = (unsigned long)pSpuIrq[0]-(unsigned long)spuMemC; + pFO->spuIrq1=spuIrq2[1]; + if(pSpuIrq[1]) pFO->pSpuIrq1 = (unsigned long)pSpuIrq[1]-(unsigned long)spuMemC; + + for(i=0;is_chan[i],(void *)&s_chan[i],sizeof(SPUCHAN)); + if(pFO->s_chan[i].pStart) + pFO->s_chan[i].pStart-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pCurr) + pFO->s_chan[i].pCurr-=(unsigned long)spuMemC; + if(pFO->s_chan[i].pLoop) + pFO->s_chan[i].pLoop-=(unsigned long)spuMemC; + } + + SetupTimer(); // sound processing on again + + return 1; + //--------------------------------------------------// + } + + // load state: +#ifdef _WINDOWS + if(iDebugMode==1 && IsWindow(hWDebug)) // we have to disbale the debug window, if active + DestroyWindow(hWDebug); + hWDebug=0; + + if(IsBadReadPtr(pFt,sizeof(SPUFreeze_t))) // check bad emu stuff + return 0; +#endif + + if(pFt->size!=sizeof(SPUFreeze_Ex_t)+ // not our stuff? bye + sizeof(SPUOSSFreeze_t)) return 0; + if(!pFt->data) return 0; + + pF=(SPUFreeze_Ex_t *)pFt->data; + + RemoveTimer(); // we stop processing while doing the save! + + memcpy(spuMem,pF->cSPURam,2*1024*1024); // get ram + memcpy(regArea,pF->cSPUPort,64*1024); + + if(!strcmp(pF->szSPUName,"PBOSS2") && + pF->ulFreezeVersion==1) + LoadStateV1(pF); + else LoadStateUnknown(pF); + + // repair some globals + for(i=0x7FFE;i>=0x0000;i-=2) + { + SPU2write(i,regArea[i]); + } + + // fix to prevent new interpolations from crashing + for(i=0;ispuIrq0; + if(pFO->pSpuIrq0) pSpuIrq[0] = pFO->pSpuIrq0+spuMemC; else pSpuIrq[0]=0; + spuIrq2[1] = pFO->spuIrq1; + if(pFO->pSpuIrq1) pSpuIrq[1] = pFO->pSpuIrq1+spuMemC; else pSpuIrq[1]=0; + + for(i=0;is_chan[i],sizeof(SPUCHAN)); + + s_chan[i].pStart+=(unsigned long)spuMemC; + s_chan[i].pCurr+=(unsigned long)spuMemC; + s_chan[i].pLoop+=(unsigned long)spuMemC; + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + } +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStateUnknown(SPUFreeze_Ex_t * pF) +{ + int i; + + for(i=0;i +#define IDC_STATIC -1 diff --git a/plugins/spu2/PeopsSPU2/oss.c b/plugins/spu2/PeopsSPU2/oss.c new file mode 100644 index 0000000..e8360ac --- /dev/null +++ b/plugins/spu2/PeopsSPU2/oss.c @@ -0,0 +1,190 @@ +/*************************************************************************** + oss.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2005/08/29 - Pete +// - changed to 48Khz output +// +// 2003/03/01 - linuzappz +// - added checkings for oss_audio_fd == -1 +// +// 2003/02/08 - linuzappz +// - added iDisStereo stuff +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_OSS + +#include "externals.h" + +#ifndef _WIN32 + +//////////////////////////////////////////////////////////////////////// +// small linux time helper... only used for watchdog +//////////////////////////////////////////////////////////////////////// +#include + +extern unsigned int timeGetTime() +{ + struct timeb t; + ftime(&t); + return (unsigned int)(t.time*1000+t.millitm); +} + +//////////////////////////////////////////////////////////////////////// +// oss globals +//////////////////////////////////////////////////////////////////////// + +#define OSS_MEM_DEF +#include "oss.h" +static int oss_audio_fd = -1; +extern int errno; + +//////////////////////////////////////////////////////////////////////// +// SETUP SOUND +//////////////////////////////////////////////////////////////////////// + +void SetupSound(void) +{ + int pspeed=48000; + int pstereo; + int format; + int fragsize = 0; + int myfrag; + int oss_speed, oss_stereo; + + if(iDisStereo) pstereo=OSS_MODE_MONO; + else pstereo=OSS_MODE_STEREO; + + oss_speed = pspeed; + oss_stereo = pstereo; + + if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1) + { + printf("Sound device not available!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1) + { + printf("Sound reset failed\n"); + return; + } + + // we use 64 fragments with 1024 bytes each + + fragsize=10; + myfrag=(63<<16)|fragsize; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1) + { + printf("Sound set fragment failed!\n"); + return; + } + + format = AFMT_S16_LE; + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1) + { + printf("Sound format not supported!\n"); + return; + } + + if(format!=AFMT_S16_LE) + { + printf("Sound format not supported!\n"); + return; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1) + { + printf("Stereo mode not supported!\n"); + return; + } + + if(oss_stereo!=1) + { + iDisStereo=1; + } + + if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1) + { + printf("Sound frequency not supported\n"); + return; + } + + if(oss_speed!=pspeed) + { + printf("Sound frequency not supported\n"); + return; + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVE SOUND +//////////////////////////////////////////////////////////////////////// + +void RemoveSound(void) +{ + if(oss_audio_fd != -1 ) + { + close(oss_audio_fd); + oss_audio_fd = -1; + } +} + +//////////////////////////////////////////////////////////////////////// +// GET BYTES BUFFERED +//////////////////////////////////////////////////////////////////////// + +unsigned long SoundGetBytesBuffered(void) +{ + audio_buf_info info; + unsigned long l; + + if(oss_audio_fd == -1) return SOUNDSIZE; + if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1) + l=0; + else + { + if(info.fragments<(info.fragstotal>>1)) // can we write in at least the half of fragments? + l=SOUNDSIZE; // -> no? wait + else l=0; // -> else go on + } + + return l; +} + +//////////////////////////////////////////////////////////////////////// +// FEED SOUND DATA +//////////////////////////////////////////////////////////////////////// + +void SoundFeedVoiceData(unsigned char* pSound,long lBytes) +{ + if(oss_audio_fd == -1) return; + write(oss_audio_fd,pSound,lBytes); +} + +#endif diff --git a/plugins/spu2/PeopsSPU2/oss.h b/plugins/spu2/PeopsSPU2/oss.h new file mode 100644 index 0000000..d70b68b --- /dev/null +++ b/plugins/spu2/PeopsSPU2/oss.h @@ -0,0 +1,37 @@ +/*************************************************************************** + oss_sound.h - description + ------------------- + begin : Wed Dec 8 1999 + copyright : (C) 1999 by Marcin "Duddie" Dudar + email : duddie@psemu.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef _OSS_SOUND_H +#define _OSS_SOUND_H + +#ifdef OSS_MEM_DEF +#define OSS_MEM_EXTERN +#else +#define OSS_MEM_EXTERN extern +#endif + +OSS_MEM_EXTERN int sound_buffer_size; + +#define OSS_MODE_STEREO 1 +#define OSS_MODE_MONO 0 + +#define OSS_SPEED_44100 44100 + +void SoundFeedVoiceData(unsigned char* pSound,long lBytes); + +#endif // _OSS_SOUND_H diff --git a/plugins/spu2/PeopsSPU2/psemu.c b/plugins/spu2/PeopsSPU2/psemu.c new file mode 100644 index 0000000..e69de29 diff --git a/plugins/spu2/PeopsSPU2/psemuxa.h b/plugins/spu2/PeopsSPU2/psemuxa.h new file mode 100644 index 0000000..84c6260 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/psemuxa.h @@ -0,0 +1,28 @@ +//============================================ +//=== Audio XA decoding +//=== Kazzuya +//============================================ + +#ifndef DECODEXA_H +#define DECODEXA_H + +typedef struct +{ + long y0, y1; +} ADPCM_Decode_t; + +typedef struct +{ + int freq; + int nbits; + int stereo; + int nsamples; + ADPCM_Decode_t left, right; + short pcm[16384]; +} xa_decode_t; + +long xa_decode_sector( xa_decode_t *xdp, + unsigned char *sectorp, + int is_first_sector ); + +#endif diff --git a/plugins/spu2/PeopsSPU2/record.c b/plugins/spu2/PeopsSPU2/record.c new file mode 100644 index 0000000..2206d38 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/record.c @@ -0,0 +1,184 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Sun Jan 12 2003 + copyright : (C) 2003 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2005/08/29 - Pete +// - changed to 48Khz output +// +// 2003/03/01 - Pete +// - added mono mode +// +// 2003/01/12 - Pete +// - added recording funcs (win version only) +// +//*************************************************************************// + +#include "stdafx.h" + +#ifdef _WINDOWS + +#include +#include "resource.h" +#include "externals.h" + +#define _IN_RECORD + +#include "record.h" + +//////////////////////////////////////////////////////////////////////// + +int iDoRecord=0; +HMMIO hWaveFile=NULL; +MMCKINFO mmckMain; +MMCKINFO mmckData; +char szFileName[256]={"C:\\PEOPS.WAV"}; + +//////////////////////////////////////////////////////////////////////// + +void RecordStart() +{ + WAVEFORMATEX pcmwf; + + // setup header in the same format as our directsound stream + memset(&pcmwf,0,sizeof(WAVEFORMATEX)); + pcmwf.wFormatTag = WAVE_FORMAT_PCM; + + pcmwf.nChannels = 2; + pcmwf.nBlockAlign = 4; + + pcmwf.nSamplesPerSec = 48000; + pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; + pcmwf.wBitsPerSample = 16; + + // create file + hWaveFile=mmioOpen(szFileName,NULL,MMIO_CREATE|MMIO_WRITE|MMIO_EXCLUSIVE | MMIO_ALLOCBUF); + if(!hWaveFile) return; + + // setup WAVE, fmt and data chunks + memset(&mmckMain,0,sizeof(MMCKINFO)); + mmckMain.fccType = mmioFOURCC('W','A','V','E'); + + mmioCreateChunk(hWaveFile,&mmckMain,MMIO_CREATERIFF); + + memset(&mmckData,0,sizeof(MMCKINFO)); + mmckData.ckid = mmioFOURCC('f','m','t',' '); + mmckData.cksize = sizeof(WAVEFORMATEX); + + mmioCreateChunk(hWaveFile,&mmckData,0); + mmioWrite(hWaveFile,(char*)&pcmwf,sizeof(WAVEFORMATEX)); + mmioAscend(hWaveFile,&mmckData,0); + + mmckData.ckid = mmioFOURCC('d','a','t','a'); + mmioCreateChunk(hWaveFile,&mmckData,0); +} + +//////////////////////////////////////////////////////////////////////// + +void RecordStop() +{ + // first some check, if recording is running + iDoRecord=0; + if(!hWaveFile) return; + + // now finish writing & close the wave file + mmioAscend(hWaveFile,&mmckData,0); + mmioAscend(hWaveFile,&mmckMain,0); + mmioClose(hWaveFile,0); + + // init var + hWaveFile=NULL; +} + +//////////////////////////////////////////////////////////////////////// + +void RecordBuffer(unsigned char* pSound,long lBytes) +{ + // write the samples + if(hWaveFile) mmioWrite(hWaveFile,pSound,lBytes); +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +BOOL CALLBACK RecordDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + //--------------------------------------------------// init + case WM_INITDIALOG: + { + SetDlgItemText(hW,IDC_WAVFILE,szFileName); // init filename edit + ShowCursor(TRUE); // mmm... who is hiding it? main emu? tsts + return TRUE; + } + //--------------------------------------------------// destroy + case WM_DESTROY: + { + RecordStop(); + }break; + //--------------------------------------------------// command + case WM_COMMAND: + { + if(wParam==IDCANCEL) iRecordMode=2; // cancel? raise flag for destroying the dialog + + if(wParam==IDC_RECORD) // record start/stop? + { + if(IsWindowEnabled(GetDlgItem(hW,IDC_WAVFILE))) // not started yet (edit is not disabled): + { + GetDlgItemText(hW,IDC_WAVFILE,szFileName,255);// get filename + + RecordStart(); // start recording + + if(hWaveFile) // start was ok? + { // -> disable filename edit, change text, raise flag + EnableWindow(GetDlgItem(hW,IDC_WAVFILE),FALSE); + SetDlgItemText(hW,IDC_RECORD,"Stop recording"); + iDoRecord=1; + } + else MessageBeep(0xFFFFFFFF); // error starting recording? BEEP + } + else // stop recording? + { + RecordStop(); // -> just do it + EnableWindow(GetDlgItem(hW,IDC_WAVFILE),TRUE);// -> enable filename edit again + SetDlgItemText(hW,IDC_RECORD,"Start recording"); + } + SetFocus(hWMain); + } + + }break; + //--------------------------------------------------// size + case WM_SIZE: + if(wParam==SIZE_MINIMIZED) SetFocus(hWMain); // if we get minimized, set the foxus to the main window + break; + //--------------------------------------------------// setcursor + case WM_SETCURSOR: + { + SetCursor(LoadCursor(NULL,IDC_ARROW)); // force the arrow + return TRUE; + } + //--------------------------------------------------// + } + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// +#endif diff --git a/plugins/spu2/PeopsSPU2/record.h b/plugins/spu2/PeopsSPU2/record.h new file mode 100644 index 0000000..24fd34c --- /dev/null +++ b/plugins/spu2/PeopsSPU2/record.h @@ -0,0 +1,12 @@ +#ifndef _RECORD_H_ +#define _RECORD_H_ + +#ifdef _WINDOWS +void RecordStart(); +void RecordBuffer(unsigned char* pSound,long lBytes); +void RecordStop(); +BOOL CALLBACK RecordDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif + +#endif + diff --git a/plugins/spu2/PeopsSPU2/registers.c b/plugins/spu2/PeopsSPU2/registers.c new file mode 100644 index 0000000..c12ac54 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/registers.c @@ -0,0 +1,1230 @@ +/*************************************************************************** + registers.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/02/09 - kode54 +// - removed &0x3fff from reverb volume registers, fixes a few games, +// hopefully won't be breaking anything +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REGISTERS + +#include "externals.h" +#include "registers.h" +#include "regs.h" +#include "reverb.h" +#include "debug.h" + +int MMIXC0 = 0, MMIXC1 = 0; +/* +// adsr time values (in ms) by James Higgs ... see the end of +// the adsr.c source for details + +#define ATTACK_MS 514L +#define DECAYHALF_MS 292L +#define DECAY_MS 584L +#define SUSTAIN_MS 450L +#define RELEASE_MS 446L +*/ + +// we have a timebase of 1.020408f ms, not 1 ms... so adjust adsr defines +#define ATTACK_MS 494L +#define DECAYHALF_MS 286L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L + +extern void (CALLBACK *irqCallbackSPU2)(); // func of main emu, called on spu irq + +static const chanmap[300] = { //Use this for selecting channels + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //23 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, //47 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, //71 + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, //95 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, //119 + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, //143 + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, //167 + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //191 + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, //215 + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, //240 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, //263 + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, //288 + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 //297 + +}; + +//////////////////////////////////////////////////////////////////////// +// WRITE REGISTERS: called by main emu +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val) +{ + long r=reg&0xffff; + +#ifdef _WINDOWS + if(iDebugMode==1) logprintf("W_REG %X - %X\r\n",reg&0xFFFF,val); +#endif + + regArea[r] = val; + + if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? + { + int rx=0; + int ch=0; + if(r>=0x400) { + rx= r - 0x400; + ch=(rx>>4)+24; + } else { + rx= r; + ch=(rx>>4); + } + + switch(rx&0x0f) + { + //------------------------------------------------// r volume + case 0: + SetVolumeL((unsigned char)ch,val); + break; + //------------------------------------------------// l volume + case 2: + SetVolumeR((unsigned char)ch,val); + break; + //------------------------------------------------// pitch + case 4: + SetPitch(ch,val); + break; + //------------------------------------------------// level with pre-calcs + case 6: + { + const unsigned long lval=val;unsigned long lx; + //---------------------------------------------// + s_chan[ch].ADSRX.AttackModeExp=(lval&0x8000)?1:0; + s_chan[ch].ADSRX.AttackRate=(lval>>8) & 0x007f; + s_chan[ch].ADSRX.DecayRate=(lval>>4) & 0x000f; + s_chan[ch].ADSRX.SustainLevel=lval & 0x000f; + //---------------------------------------------// + if(!iDebugMode) break; + //---------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.AttackModeExp=(lval&0x8000)?1:0; //0x007f + + lx=(((lval>>8) & 0x007f)>>2); // attack time to run from 0 to 100% volume + lx=min(31,lx); // no overflow on shift! + if(lx) + { + lx = (1<>4) & 0x000f; // decay: + if(lx) // our const decay value is time it takes from 100% to 0% of volume + { + lx = ((1<<(lx))*DECAY_MS)/10000L; + if(!lx) lx=1; + } + s_chan[ch].ADSR.DecayTime = // so calc how long does it take to run from 100% to the wanted sus level + (lx*(1024-s_chan[ch].ADSR.SustainLevel))/1024; + } + break; + //------------------------------------------------// adsr times with pre-calcs + case 8: + { + const unsigned long lval=val;unsigned long lx; + + //----------------------------------------------// + s_chan[ch].ADSRX.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSRX.SustainIncrease= (lval&0x4000)?0:1; + s_chan[ch].ADSRX.SustainRate = (lval>>6) & 0x007f; + s_chan[ch].ADSRX.ReleaseModeExp = (lval&0x0020)?1:0; + s_chan[ch].ADSRX.ReleaseRate = lval & 0x001f; + //----------------------------------------------// + if(!iDebugMode) break; + //----------------------------------------------// stuff below is only for debug mode + + s_chan[ch].ADSR.SustainModeExp = (lval&0x8000)?1:0; + s_chan[ch].ADSR.ReleaseModeExp = (lval&0x0020)?1:0; + + lx=((((lval>>6) & 0x007f)>>2)); // sustain time... often very high + lx=min(31,lx); // values are used to hold the volume + if(lx) // until a sound stop occurs + { // the highest value we reach (due to + lx = (1<=0x01c0 && r<=0x02E0)||(r>=0x05c0 && r<=0x06E0)) // some channel info? + { + int ch=0;unsigned long rx=r; + if(rx>=0x400) {ch=24;rx-=0x400;} + + ch+=chanmap[rx-0x1c0]; + rx-=(ch%24)*12; + + switch(rx) + { + //------------------------------------------------// + case 0x1C0: + s_chan[ch].iStartAdr=(((unsigned long)val&0x3f)<<16)|(s_chan[ch].iStartAdr&0xFFFF); + s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1); + break; + case 0x1C2: + s_chan[ch].iStartAdr=(s_chan[ch].iStartAdr & 0x3f0000) | (val & 0xFFFF); + s_chan[ch].pStart=spuMemC+(s_chan[ch].iStartAdr<<1); + break; + //------------------------------------------------// + case 0x1C4: + s_chan[ch].iLoopAdr=(((unsigned long)val&0x3f)<<16)|(s_chan[ch].iLoopAdr&0xFFFF); + s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1); + if(s_chan[ch].iLoopAdr)s_chan[ch].bIgnoreLoop=1; + else s_chan[ch].bIgnoreLoop=0; + break; + case 0x1C6: + s_chan[ch].iLoopAdr=(s_chan[ch].iLoopAdr & 0x3f0000) | (val & 0xFFFF); + s_chan[ch].pLoop=spuMemC+(s_chan[ch].iLoopAdr<<1); + if(s_chan[ch].iLoopAdr)s_chan[ch].bIgnoreLoop=1; + else s_chan[ch].bIgnoreLoop=0; + break; + //------------------------------------------------// + case 0x1C8: + // unused... check if it gets written as well + s_chan[ch].iNextAdr=(((unsigned long)val&0x3f)<<16)|(s_chan[ch].iNextAdr&0xFFFF); + break; + case 0x1CA: + // unused... check if it gets written as well + s_chan[ch].iNextAdr=(s_chan[ch].iNextAdr & 0x3f0000) | (val & 0xFFFF); + break; + //------------------------------------------------// + } + + return; + } + + switch(r) + { + case PS2_C0_MVOLL: + regArea[PS2_C0_MVOLL] = val; + break; + case PS2_C0_MVOLR: + regArea[PS2_C0_MVOLR] = val; + break; + + case PS2_C0_BVOLL: + regArea[PS2_C0_BVOLL] = val; + break; + case PS2_C0_BVOLR: + regArea[PS2_C0_BVOLR] = val; + break; + case PS2_C1_BVOLL: + regArea[PS2_C1_BVOLL] = val; + break; + case PS2_C1_BVOLR: + regArea[PS2_C1_BVOLR] = val; + break; + + + case PS2_C0_MMIX: + regArea[PS2_C0_MMIX] = val; + break; + case PS2_C1_MMIX: + regArea[PS2_C1_MMIX] = val; + break; + //-------------------------------------------------// + case PS2_C0_SPUaddr_Hi: + spuAddr2[0] = (((unsigned long)val&0x3f)<<16)|(spuAddr2[0]&0xFFFF); // 6bits + break; + //-------------------------------------------------// + case PS2_C0_SPUaddr_Lo: + spuAddr2[0] = (spuAddr2[0] & 0x3F0000) | (val & 0xFFFF); + break; + //-------------------------------------------------// + case PS2_C1_SPUaddr_Hi: + spuAddr2[1] = (((unsigned long)val&0x3f)<<16)|(spuAddr2[1]&0xFFFF); // 6bits + break; + //-------------------------------------------------// + case PS2_C1_SPUaddr_Lo: + spuAddr2[1] = (spuAddr2[1] & 0x3F0000) | (val & 0xFFFF); + break; + //-------------------------------------------------// + case PS2_C0_SPUdata: + spuMem[spuAddr2[0]] = val; + spuAddr2[0]++; + if(spuCtrl2[0]&0x40 && spuIrq2[0] == spuAddr2[0]){ + regArea[0x7C0] |= 0x4; + irqCallbackSPU2(); + } + if(spuAddr2[0]>0xFFFFE) spuAddr2[0] = 0x2800; + spuStat2[0]&=~0x80; + spuCtrl2[0]&=~0x30; + break; + //-------------------------------------------------// + case PS2_C1_SPUdata: + spuMem[spuAddr2[1]] = val; + spuAddr2[1]++; + if(spuCtrl2[1]&0x40 && spuIrq2[1] == spuAddr2[1]){ + regArea[0x7C0] |= 0x8; + irqCallbackSPU2(); + } + if(spuAddr2[1]>0xFFFFE) spuAddr2[1] = 0x2800; + spuStat2[1]&=~0x80; + spuCtrl2[1]&=~0x30; + break; + //-------------------------------------------------// + case PS2_C0_ATTR: + spuCtrl2[0]=val; + break; + //-------------------------------------------------// + case PS2_C0_ADMAS: + regArea[(PS2_C0_ADMAS)]=val; + ///regArea[(0x344)>>1]&= ~0x80; + //regArea[(0x744)>>1]&= ~0x80; + break; + case PS2_C1_ADMAS: + regArea[(PS2_C1_ADMAS)]=val; + //regArea[(0x344)>>1]&= ~0x80; + //regArea[(0x744)>>1]&= ~0x80; + break; + case PS2_C1_ATTR: + spuCtrl2[1]=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUstat: + spuStat2[0]=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUstat: + spuStat2[1]=val; + break; + //-------------------------------------------------// + case PS2_C0_ReverbAddr_Hi: + spuRvbAddr2[0] = (((unsigned long)val&0x3f)<<16)|(spuRvbAddr2[0]&0xFFFF); + SetReverbAddr(0); + break; + //-------------------------------------------------// + case PS2_C0_ReverbAddr_Lo: + spuRvbAddr2[0] = (spuRvbAddr2[0] & 0x3f0000) | (val & 0xFFFF); + SetReverbAddr(0); + break; + //-------------------------------------------------// + case PS2_C0_ReverbAEnd_Hi: + spuRvbAEnd2[0] = (((unsigned long)val&0x3f)<<16)|(/*spuRvbAEnd2[0]&*/0xFFFF); + rvb[0].EndAddr=spuRvbAEnd2[0]; + break; + //-------------------------------------------------// + case PS2_C1_ReverbAEnd_Hi: + spuRvbAEnd2[1] = (((unsigned long)val&0x3f)<<16)|(/*spuRvbAEnd2[1]&*/0xFFFF); + rvb[1].EndAddr=spuRvbAEnd2[1]; + break; + //-------------------------------------------------// + case PS2_C1_ReverbAddr_Hi: + spuRvbAddr2[1] = (((unsigned long)val&0x3f)<<16)|(spuRvbAddr2[1]&0xFFFF); + SetReverbAddr(1); + break; + //-------------------------------------------------// + case PS2_C1_ReverbAddr_Lo: + spuRvbAddr2[1] = (spuRvbAddr2[1] & 0x3f0000) | (val & 0xFFFF); + SetReverbAddr(1); + break; + //-------------------------------------------------// + case PS2_C0_SPUirqAddr_Hi: + spuIrq2[0] = (((unsigned long)val&0x3f)<<16)|(spuIrq2[0]&0xFFFF); // 6bits + pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1); + break; + //-------------------------------------------------// + case PS2_C0_SPUirqAddr_Lo: + spuIrq2[0] = (spuIrq2[0] & 0x3F0000) | (val & 0xFFFF); + pSpuIrq[0]=spuMemC+(spuIrq2[0]<<1); + break; + //-------------------------------------------------// + case PS2_C1_SPUirqAddr_Hi: + spuIrq2[1] = (((unsigned long)val&0x3f)<<16)|(spuIrq2[1]&0xFFFF); // 6bits + pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1); + break; + //-------------------------------------------------// + case PS2_C1_SPUirqAddr_Lo: + spuIrq2[1] = (spuIrq2[1] & 0x3F0000) | (val & 0xFFFF); + pSpuIrq[1]=spuMemC+(spuIrq2[1]<<1); + break; + //-------------------------------------------------// + case PS2_C0_SPUrvolL: + rvb[0].VolLeft=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUrvolR: + rvb[0].VolRight=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUrvolL: + rvb[1].VolLeft=val; + break; + //-------------------------------------------------// + case PS2_C1_SPUrvolR: + rvb[1].VolRight=val; + break; + //-------------------------------------------------// + case PS2_C0_SPUon1: + SoundOn(0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUon2: + SoundOn(16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUon1: + SoundOn(24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUon2: + SoundOn(40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUoff1: + SoundOff(0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUoff2: + SoundOff(16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUoff1: + SoundOff(24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_SPUoff2: + SoundOff(40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_SPUend1: + dwEndChannel2[0] = 0; // According to manual all bits are cleared by writing an arbitary value + break; + case PS2_C0_SPUend2: + dwEndChannel2[0] = 0; + break; + //-------------------------------------------------// + case PS2_C1_SPUend1: + dwEndChannel2[1] = 0; + break; + case PS2_C1_SPUend2: + dwEndChannel2[1] = 0; + break; + //-------------------------------------------------// + case PS2_C0_FMod1: + FModOn(0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_FMod2: + FModOn(16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_FMod1: + FModOn(24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_FMod2: + FModOn(40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_Noise1: + NoiseOn(0,16,val); + break; + //-------------------------------------------------// + case PS2_C0_Noise2: + NoiseOn(16,24,val); + break; + //-------------------------------------------------// + case PS2_C1_Noise1: + NoiseOn(24,40,val); + break; + //-------------------------------------------------// + case PS2_C1_Noise2: + NoiseOn(40,48,val); + break; + //-------------------------------------------------// + case PS2_C0_DryL1: + VolumeOn(0,16,val,0); + break; + //-------------------------------------------------// + case PS2_C0_DryL2: + VolumeOn(16,24,val,0); + break; + //-------------------------------------------------// + case PS2_C1_DryL1: + VolumeOn(24,40,val,0); + break; + //-------------------------------------------------// + case PS2_C1_DryL2: + VolumeOn(40,48,val,0); + break; + //-------------------------------------------------// + case PS2_C0_DryR1: + VolumeOn(0,16,val,1); + break; + //-------------------------------------------------// + case PS2_C0_DryR2: + VolumeOn(16,24,val,1); + break; + //-------------------------------------------------// + case PS2_C1_DryR1: + VolumeOn(24,40,val,1); + break; + //-------------------------------------------------// + case PS2_C1_DryR2: + VolumeOn(40,48,val,1); + break; + //-------------------------------------------------// + case PS2_C0_RVBon1_L: + ReverbOn(0,16,val,0); + break; + //-------------------------------------------------// + case PS2_C0_RVBon2_L: + ReverbOn(16,24,val,0); + break; + //-------------------------------------------------// + case PS2_C1_RVBon1_L: + ReverbOn(24,40,val,0); + break; + //-------------------------------------------------// + case PS2_C1_RVBon2_L: + ReverbOn(40,48,val,0); + break; + //-------------------------------------------------// + case PS2_C0_RVBon1_R: + ReverbOn(0,16,val,1); + break; + //-------------------------------------------------// + case PS2_C0_RVBon2_R: + ReverbOn(16,24,val,1); + break; + //-------------------------------------------------// + case PS2_C1_RVBon1_R: + ReverbOn(24,40,val,1); + break; + //-------------------------------------------------// + case PS2_C1_RVBon2_R: + ReverbOn(40,48,val,1); + break; + //-------------------------------------------------// + case PS2_C0_Reverb+0: + rvb[0].FB_SRC_A=(((unsigned long)val&0x3f)<<16)|(rvb[0].FB_SRC_A&0xFFFF); + break; + case PS2_C0_Reverb+2: + rvb[0].FB_SRC_A=(rvb[0].FB_SRC_A & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+4: + rvb[0].FB_SRC_B=(((unsigned long)val&0x3f)<<16)|(rvb[0].FB_SRC_B&0xFFFF); + break; + case PS2_C0_Reverb+6: + rvb[0].FB_SRC_B=(rvb[0].FB_SRC_B & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+8: + rvb[0].IIR_DEST_A0=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_DEST_A0&0xFFFF); + break; + case PS2_C0_Reverb+10: + rvb[0].IIR_DEST_A0=(rvb[0].IIR_DEST_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+12: + rvb[0].IIR_DEST_A1=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_DEST_A1&0xFFFF); + break; + case PS2_C0_Reverb+14: + rvb[0].IIR_DEST_A1=(rvb[0].IIR_DEST_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+16: + rvb[0].ACC_SRC_A0=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_A0&0xFFFF); + break; + case PS2_C0_Reverb+18: + rvb[0].ACC_SRC_A0=(rvb[0].ACC_SRC_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+20: + rvb[0].ACC_SRC_A1=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_A1&0xFFFF); + break; + case PS2_C0_Reverb+22: + rvb[0].ACC_SRC_A1=(rvb[0].ACC_SRC_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+24: + rvb[0].ACC_SRC_B0=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_B0&0xFFFF); + break; + case PS2_C0_Reverb+26: + rvb[0].ACC_SRC_B0=(rvb[0].ACC_SRC_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+28: + rvb[0].ACC_SRC_B1=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_B1&0xFFFF); + break; + case PS2_C0_Reverb+30: + rvb[0].ACC_SRC_B1=(rvb[0].ACC_SRC_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+32: + rvb[0].IIR_SRC_A0=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_SRC_A0&0xFFFF); + break; + case PS2_C0_Reverb+34: + rvb[0].IIR_SRC_A0=(rvb[0].IIR_SRC_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+36: + rvb[0].IIR_SRC_A1=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_SRC_A1&0xFFFF); + break; + case PS2_C0_Reverb+38: + rvb[0].IIR_SRC_A1=(rvb[0].IIR_SRC_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+40: + rvb[0].IIR_DEST_B0=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_DEST_B0&0xFFFF); + break; + case PS2_C0_Reverb+42: + rvb[0].IIR_DEST_B0=(rvb[0].IIR_DEST_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+44: + rvb[0].IIR_DEST_B1=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_DEST_B1&0xFFFF); + break; + case PS2_C0_Reverb+46: + rvb[0].IIR_DEST_B1=(rvb[0].IIR_DEST_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+48: + rvb[0].ACC_SRC_C0=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_C0&0xFFFF); + break; + case PS2_C0_Reverb+50: + rvb[0].ACC_SRC_C0=(rvb[0].ACC_SRC_C0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+52: + rvb[0].ACC_SRC_C1=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_C1&0xFFFF); + break; + case PS2_C0_Reverb+54: + rvb[0].ACC_SRC_C1=(rvb[0].ACC_SRC_C1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+56: + rvb[0].ACC_SRC_D0=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_D0&0xFFFF); + break; + case PS2_C0_Reverb+58: + rvb[0].ACC_SRC_D0=(rvb[0].ACC_SRC_D0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+60: + rvb[0].ACC_SRC_D1=(((unsigned long)val&0x3f)<<16)|(rvb[0].ACC_SRC_D1&0xFFFF); + break; + case PS2_C0_Reverb+62: + rvb[0].ACC_SRC_D1=(rvb[0].ACC_SRC_D1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+64: + rvb[0].IIR_SRC_B1=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_SRC_B1&0xFFFF); + break; + case PS2_C0_Reverb+66: + rvb[0].IIR_SRC_B1=(rvb[0].IIR_SRC_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+68: + rvb[0].IIR_SRC_B0=(((unsigned long)val&0x3f)<<16)|(rvb[0].IIR_SRC_B0&0xFFFF); + break; + case PS2_C0_Reverb+70: + rvb[0].IIR_SRC_B0=(rvb[0].IIR_SRC_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+72: + rvb[0].MIX_DEST_A0=(((unsigned long)val&0x3f)<<16)|(rvb[0].MIX_DEST_A0&0xFFFF); + break; + case PS2_C0_Reverb+74: + rvb[0].MIX_DEST_A0=(rvb[0].MIX_DEST_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+76: + rvb[0].MIX_DEST_A1=(((unsigned long)val&0x3f)<<16)|(rvb[0].MIX_DEST_A1&0xFFFF); + break; + case PS2_C0_Reverb+78: + rvb[0].MIX_DEST_A1=(rvb[0].MIX_DEST_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+80: + rvb[0].MIX_DEST_B0=(((unsigned long)val&0x3f)<<16)|(rvb[0].MIX_DEST_B0&0xFFFF); + break; + case PS2_C0_Reverb+82: + rvb[0].MIX_DEST_B0=(rvb[0].MIX_DEST_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_Reverb+84: + rvb[0].MIX_DEST_B1=(((unsigned long)val&0x3f)<<16)|(rvb[0].MIX_DEST_B1&0xFFFF); + break; + case PS2_C0_Reverb+86: + rvb[0].MIX_DEST_B1=(rvb[0].MIX_DEST_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C0_ReverbX+0: rvb[0].IIR_ALPHA=(short)val; break; + case PS2_C0_ReverbX+2: rvb[0].ACC_COEF_A=(short)val; break; + case PS2_C0_ReverbX+4: rvb[0].ACC_COEF_B=(short)val; break; + case PS2_C0_ReverbX+6: rvb[0].ACC_COEF_C=(short)val; break; + case PS2_C0_ReverbX+8: rvb[0].ACC_COEF_D=(short)val; break; + case PS2_C0_ReverbX+10: rvb[0].IIR_COEF=(short)val; break; + case PS2_C0_ReverbX+12: rvb[0].FB_ALPHA=(short)val; break; + case PS2_C0_ReverbX+14: rvb[0].FB_X=(short)val; break; + case PS2_C0_ReverbX+16: rvb[0].IN_COEF_L=(short)val; break; + case PS2_C0_ReverbX+18: rvb[0].IN_COEF_R=(short)val; break; + //-------------------------------------------------// + case PS2_C1_Reverb+0: + rvb[1].FB_SRC_A=(((unsigned long)val&0x3f)<<16)|(rvb[1].FB_SRC_A&0xFFFF); + break; + case PS2_C1_Reverb+2: + rvb[1].FB_SRC_A=(rvb[1].FB_SRC_A & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+4: + rvb[1].FB_SRC_B=(((unsigned long)val&0x3f)<<16)|(rvb[1].FB_SRC_B&0xFFFF); + break; + case PS2_C1_Reverb+6: + rvb[1].FB_SRC_B=(rvb[1].FB_SRC_B & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+8: + rvb[1].IIR_DEST_A0=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_DEST_A0&0xFFFF); + break; + case PS2_C1_Reverb+10: + rvb[1].IIR_DEST_A0=(rvb[1].IIR_DEST_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+12: + rvb[1].IIR_DEST_A1=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_DEST_A1&0xFFFF); + break; + case PS2_C1_Reverb+14: + rvb[1].IIR_DEST_A1=(rvb[1].IIR_DEST_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+16: + rvb[1].ACC_SRC_A0=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_A0&0xFFFF); + break; + case PS2_C1_Reverb+18: + rvb[1].ACC_SRC_A0=(rvb[1].ACC_SRC_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+20: + rvb[1].ACC_SRC_A1=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_A1&0xFFFF); + break; + case PS2_C1_Reverb+22: + rvb[1].ACC_SRC_A1=(rvb[1].ACC_SRC_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+24: + rvb[1].ACC_SRC_B0=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_B0&0xFFFF); + break; + case PS2_C1_Reverb+26: + rvb[1].ACC_SRC_B0=(rvb[1].ACC_SRC_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+28: + rvb[1].ACC_SRC_B1=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_B1&0xFFFF); + break; + case PS2_C1_Reverb+30: + rvb[1].ACC_SRC_B1=(rvb[1].ACC_SRC_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+32: + rvb[1].IIR_SRC_A0=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_SRC_A0&0xFFFF); + break; + case PS2_C1_Reverb+34: + rvb[1].IIR_SRC_A0=(rvb[1].IIR_SRC_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+36: + rvb[1].IIR_SRC_A1=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_SRC_A1&0xFFFF); + break; + case PS2_C1_Reverb+38: + rvb[1].IIR_SRC_A1=(rvb[1].IIR_SRC_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+40: + rvb[1].IIR_DEST_B0=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_DEST_B0&0xFFFF); + break; + case PS2_C1_Reverb+42: + rvb[1].IIR_DEST_B0=(rvb[1].IIR_DEST_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+44: + rvb[1].IIR_DEST_B1=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_DEST_B1&0xFFFF); + break; + case PS2_C1_Reverb+46: + rvb[1].IIR_DEST_B1=(rvb[1].IIR_DEST_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+48: + rvb[1].ACC_SRC_C0=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_C0&0xFFFF); + break; + case PS2_C1_Reverb+50: + rvb[1].ACC_SRC_C0=(rvb[1].ACC_SRC_C0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+52: + rvb[1].ACC_SRC_C1=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_C1&0xFFFF); + break; + case PS2_C1_Reverb+54: + rvb[1].ACC_SRC_C1=(rvb[1].ACC_SRC_C1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+56: + rvb[1].ACC_SRC_D0=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_D0&0xFFFF); + break; + case PS2_C1_Reverb+58: + rvb[1].ACC_SRC_D0=(rvb[1].ACC_SRC_D0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+60: + rvb[1].ACC_SRC_D1=(((unsigned long)val&0x3f)<<16)|(rvb[1].ACC_SRC_D1&0xFFFF); + break; + case PS2_C1_Reverb+62: + rvb[1].ACC_SRC_D1=(rvb[1].ACC_SRC_D1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+64: + rvb[1].IIR_SRC_B1=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_SRC_B1&0xFFFF); + break; + case PS2_C1_Reverb+66: + rvb[1].IIR_SRC_B1=(rvb[1].IIR_SRC_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+68: + rvb[1].IIR_SRC_B0=(((unsigned long)val&0x3f)<<16)|(rvb[1].IIR_SRC_B0&0xFFFF); + break; + case PS2_C1_Reverb+70: + rvb[1].IIR_SRC_B0=(rvb[1].IIR_SRC_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+72: + rvb[1].MIX_DEST_A0=(((unsigned long)val&0x3f)<<16)|(rvb[1].MIX_DEST_A0&0xFFFF); + break; + case PS2_C1_Reverb+74: + rvb[1].MIX_DEST_A0=(rvb[1].MIX_DEST_A0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+76: + rvb[1].MIX_DEST_A1=(((unsigned long)val&0x3f)<<16)|(rvb[1].MIX_DEST_A1&0xFFFF); + break; + case PS2_C1_Reverb+78: + rvb[1].MIX_DEST_A1=(rvb[1].MIX_DEST_A1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+80: + rvb[1].MIX_DEST_B0=(((unsigned long)val&0x3f)<<16)|(rvb[1].MIX_DEST_B0&0xFFFF); + break; + case PS2_C1_Reverb+82: + rvb[1].MIX_DEST_B0=(rvb[1].MIX_DEST_B0 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_Reverb+84: + rvb[1].MIX_DEST_B1=(((unsigned long)val&0x3f)<<16)|(rvb[1].MIX_DEST_B1&0xFFFF); + break; + case PS2_C1_Reverb+86: + rvb[1].MIX_DEST_B1=(rvb[1].MIX_DEST_B1 & 0x3f0000) | ((val) & 0xFFFF); + break; + case PS2_C1_ReverbX+0: rvb[1].IIR_ALPHA=(short)val; break; + case PS2_C1_ReverbX+2: rvb[1].ACC_COEF_A=(short)val; break; + case PS2_C1_ReverbX+4: rvb[1].ACC_COEF_B=(short)val; break; + case PS2_C1_ReverbX+6: rvb[1].ACC_COEF_C=(short)val; break; + case PS2_C1_ReverbX+8: rvb[1].ACC_COEF_D=(short)val; break; + case PS2_C1_ReverbX+10: rvb[1].IIR_COEF=(short)val; break; + case PS2_C1_ReverbX+12: rvb[1].FB_ALPHA=(short)val; break; + case PS2_C1_ReverbX+14: rvb[1].FB_X=(short)val; break; + case PS2_C1_ReverbX+16: rvb[1].IN_COEF_L=(short)val; break; + case PS2_C1_ReverbX+18: rvb[1].IN_COEF_R=(short)val; break; + } + + iSpuAsyncWait=0; + +} + +//////////////////////////////////////////////////////////////////////// +// READ REGISTER: called by main emu +//////////////////////////////////////////////////////////////////////// +EXPORT_GCC unsigned short CALLBACK SPU2read(unsigned long reg) +{ + long r=reg&0xffff; + +#ifdef _WINDOWS + if(iDebugMode==1) logprintf("R_REG %X Val %X\r\n",reg&0xFFFF, regArea[r]); +#endif + + if((r>=0x0000 && r<=0x0180)||(r>=0x0400 && r<=0x0580)) // some channel info? + { + int addr=0; + if(r >= 0x400) addr = (r - 0x400) & 0xfff0; + else addr = r & 0xfff0; + switch(r&0x0f) + { + //------------------------------------------------// env value + case 10: + { + int ch=(addr>>4); + if(r>=0x400) ch+=24; + //if(s_chan[ch].bNew) return 1; // we are started, but not processed? return 1 + /*if(s_chan[ch].ADSRX.lVolume && // same here... we haven't decoded one sample yet, so no envelope yet. return 1 as well + !s_chan[ch].ADSRX.EnvelopeVol) + return 1;*/ + //if(s_chan[ch].bOn==0) return 0; + return (unsigned short)(s_chan[ch].ADSRX.EnvelopeVol>>16); + }break; + } + } + + + if((r>0x01c0 && r<=0x02E0)||(r>0x05c0 && r<=0x06E0)) // some channel info? + { + int ch=0;unsigned long rx=r; + if(rx>=0x400) {ch=24;rx-=0x400;} + + ch+=chanmap[rx-0x1c0]; + rx-=(ch%24)*12; + + + switch(rx) + { + case 0x1C0: + return (((s_chan[ch].pStart-spuMemC)>>17)&0x3F); + break; + case 0x1C2: + return (((s_chan[ch].pStart-spuMemC)>>1)&0xFFFF); + //------------------------------------------------// + case 0x1C4: + return (((s_chan[ch].pLoop-spuMemC)>>17)&0x3F); + break; + case 0x1C6: + return (((s_chan[ch].pLoop-spuMemC)>>1)&0xFFFF); + break; + //------------------------------------------------// + case 0x1C8: + return (((s_chan[ch].pCurr-spuMemC)>>17)&0x3F); + break; + case 0x1CA: + return (((s_chan[ch].pCurr-spuMemC)>>1)&0xFFFF); + break; + default: + return regArea[rx]; + break; + + //------------------------------------------------// + } + } + + switch(r) + { + //--------------------------------------------------// + case PS2_C0_SPUend1: + return (unsigned short)((dwEndChannel2[0]&0xFFFF)); + case PS2_C0_SPUend2: + return (unsigned short)((dwEndChannel2[0]>>16)); + //--------------------------------------------------// + case PS2_C1_SPUend1: + return (unsigned short)((dwEndChannel2[1]&0xFFFF)); + case PS2_C1_SPUend2: + return (unsigned short)((dwEndChannel2[1]>>16)); + //--------------------------------------------------// + case PS2_C0_ATTR: + return spuCtrl2[0]; + break; + //--------------------------------------------------// + case PS2_C1_ATTR: + return spuCtrl2[1]; + break; + //--------------------------------------------------// + case PS2_C0_SPUstat: + return spuStat2[0]; + break; + //--------------------------------------------------// + case PS2_C1_SPUstat: + return spuStat2[1]; + break; + //--------------------------------------------------// + case PS2_C0_SPUdata: + { + unsigned short s=spuMem[spuAddr2[0]]; + spuAddr2[0]++; + if(spuAddr2[0]>0xfffff) spuAddr2[0]=0; + return s; + } + //--------------------------------------------------// + case PS2_C1_SPUdata: + { + unsigned short s=spuMem[spuAddr2[1]]; + spuAddr2[1]++; + if(spuAddr2[1]>0xfffff) spuAddr2[1]=0; + return s; + } + //--------------------------------------------------// + case PS2_C0_SPUaddr_Hi: + return (unsigned short)((spuAddr2[0]>>16)&0x3F); + break; + case PS2_C0_SPUaddr_Lo: + return (unsigned short)((spuAddr2[0]&0xFFFF)); + break; + //--------------------------------------------------// + case PS2_C1_SPUaddr_Hi: + return (unsigned short)((spuAddr2[1]>>16)&0x3F); + break; + case PS2_C1_SPUaddr_Lo: + return (unsigned short)((spuAddr2[1]&0xFFFF)); + break; + case PS2_C0_ADMAS: + return regArea[(PS2_C0_ADMAS)]; + ///regArea[(0x344)>>1]&= ~0x80; + //regArea[(0x744)>>1]&= ~0x80; + break; + case PS2_C1_ADMAS: + return regArea[(PS2_C1_ADMAS)]; + //regArea[(0x344)>>1]&= ~0x80; + //regArea[(0x744)>>1]&= ~0x80; + break; + //--------------------------------------------------// + } + return regArea[r]; +} + +//////////////////////////////////////////////////////////////////////// +// SOUND ON register write +//////////////////////////////////////////////////////////////////////// + +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if((val&1) && s_chan[ch].pStart) // mmm... start has to be set before key on !?! + { + //s_chan[ch].bStop = 0; + s_chan[ch].bNew=1; + dwNewChannel2[ch/24]|=(1<<(ch%24)); // bitfield for faster testing + } + } +} + +//////////////////////////////////////////////////////////////////////// +// SOUND OFF register write +//////////////////////////////////////////////////////////////////////// + +void SoundOff(int start,int end,unsigned short val) // SOUND OFF PSX COMMAND +{ + int ch; + for(ch=start;ch>=1) // loop channels + { + if(val&1) // && s_chan[i].bOn) mmm... + { + s_chan[ch].bStop=1; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FMOD register write +//////////////////////////////////////////////////////////////////////// + +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) + { + s_chan[ch].bFMod=1; // --> sound channel + s_chan[ch-1].bFMod=2; // --> freq channel + } + } + else + { + s_chan[ch].bFMod=0; // --> turn off fmod + } + } +} + +//////////////////////////////////////////////////////////////////////// +// NOISE register write +//////////////////////////////////////////////////////////////////////// + +void NoiseOn(int start,int end,unsigned short val) // NOISE ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> noise on/off + { + s_chan[ch].bNoise=1; + } + else + { + s_chan[ch].bNoise=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// LEFT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +// please note: sweep and phase invert are wrong... but I've never seen +// them used + +void SetVolumeL(unsigned char ch,short vol) // LEFT VOLUME +{ + s_chan[ch].iLeftVolRaw=vol; + + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + s_chan[ch].iLeftVolume=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void SetVolumeR(unsigned char ch,short vol) // RIGHT VOLUME +{ + s_chan[ch].iRightVolRaw=vol; + + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + s_chan[ch].iRightVolume=vol; +} + +//////////////////////////////////////////////////////////////////////// +// PITCH register write +//////////////////////////////////////////////////////////////////////// + +void SetPitch(int ch,unsigned short val) // SET PITCH +{ + int NP; + if(val>0x3fff) NP=0x3fff; // get pitch val + else NP=val; + + s_chan[ch].iRawPitch=NP; + + NP=(48000L*NP)/4096L; // calc frequency(48000Hz) + if(NP<1) NP=1; // some security + s_chan[ch].iActFreq=NP; // store frequency +} + +//////////////////////////////////////////////////////////////////////// +// REVERB register write +//////////////////////////////////////////////////////////////////////// + +void ReverbOn(int start,int end,unsigned short val,int iRight) // REVERB ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + if(iRight) s_chan[ch].bReverbR=1; + else s_chan[ch].bReverbL=1; + } + else + { + if(iRight) s_chan[ch].bReverbR=0; + else s_chan[ch].bReverbL=0; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// REVERB START register write +//////////////////////////////////////////////////////////////////////// + +void SetReverbAddr(int core) +{ + long val=spuRvbAddr2[core]; + + if(rvb[core].StartAddr!=val) + { + if(val<=0x27ff) + { + rvb[core].StartAddr=rvb[core].CurrAddr=0; + } + else + { + rvb[core].StartAddr=val; + rvb[core].CurrAddr=rvb[core].StartAddr; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// DRY LEFT/RIGHT per voice switches +//////////////////////////////////////////////////////////////////////// + +void VolumeOn(int start,int end,unsigned short val,int iRight) // VOLUME ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> reverb on/off + { + if(iRight) s_chan[ch].bVolumeR=1; + else s_chan[ch].bVolumeL=1; + } + else + { + if(iRight) s_chan[ch].bVolumeR=0; + else s_chan[ch].bVolumeL=0; + } + } +} + + diff --git a/plugins/spu2/PeopsSPU2/registers.h b/plugins/spu2/PeopsSPU2/registers.h new file mode 100644 index 0000000..ac84f30 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/registers.h @@ -0,0 +1,806 @@ +/*************************************************************************** + registers.h - description + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - generic cleanup for the Peops release... register values by Kanodin & +// his team +// +//*************************************************************************// + +//########################################################################### + +#define PS2_C0_SPUaddr_Hi (0x1A8) +#define PS2_C0_SPUaddr_Lo (0x1AA) +#define PS2_C1_SPUaddr_Hi (0x5A8) +#define PS2_C1_SPUaddr_Lo (0x5AA) +#define PS2_C0_SPUdata (0x1AC) +#define PS2_C1_SPUdata (0x5AC) + +#define PS2_C0_SPUDMActrl (0x1AE) +#define PS2_C1_SPUDMActrl (0x5AE) + +#define PS2_C0_SPUstat (0x344) +#define PS2_C1_SPUstat (0x744) +#define PS2_C0_ReverbAddr_Hi (0x2E0) +#define PS2_C0_ReverbAddr_Lo (0x2E2) +#define PS2_C1_ReverbAddr_Hi (0x6E0) +#define PS2_C1_ReverbAddr_Lo (0x6E2) + +#define PS2_C0_ReverbAEnd_Hi (0x33C) +#define PS2_C0_ReverbAEnd_Lo (0x33E) +#define PS2_C1_ReverbAEnd_Hi (0x73C) +#define PS2_C1_ReverbAEnd_Lo (0x73E) + +#define PS2_C0_DryL1 (0x188) +#define PS2_C1_DryL1 (0x588) +#define PS2_C0_DryL2 (0x18A) +#define PS2_C1_DryL2 (0x58A) + +#define PS2_C0_DryR1 (0x190) +#define PS2_C1_DryR1 (0x590) +#define PS2_C0_DryR2 (0x192) +#define PS2_C1_DryR2 (0x592) + +#define PS2_C0_ATTR (0x19A) +#define PS2_C1_ATTR (0x59A) +#define PS2_C0_ADMAS (0x1B0) +#define PS2_C1_ADMAS (0x5B0) + +#define PS2_C0_SPUirqAddr_Hi (0x19C) +#define PS2_C0_SPUirqAddr_Lo (0x19D) +#define PS2_C1_SPUirqAddr_Hi (0x59C) +#define PS2_C1_SPUirqAddr_Lo (0x59D) +#define PS2_C0_SPUrvolL (0x764) +#define PS2_C0_SPUrvolR (0x766) +#define PS2_C1_SPUrvolL (0x028 + 0x764) +#define PS2_C1_SPUrvolR (0x028 + 0x766) +#define PS2_C0_SPUon1 (0x1A0) +#define PS2_C0_SPUon2 (0x1A2) +#define PS2_C1_SPUon1 (0x5A0) +#define PS2_C1_SPUon2 (0x5A2) +#define PS2_C0_SPUoff1 (0x1A4) +#define PS2_C0_SPUoff2 (0x1A6) +#define PS2_C1_SPUoff1 (0x5A4) +#define PS2_C1_SPUoff2 (0x5A6) +#define PS2_C0_FMod1 (0x180) +#define PS2_C0_FMod2 (0x182) +#define PS2_C1_FMod1 (0x580) +#define PS2_C1_FMod2 (0x582) +#define PS2_C0_Noise1 (0x184) +#define PS2_C0_Noise2 (0x186) +#define PS2_C1_Noise1 (0x584) +#define PS2_C1_Noise2 (0x586) + +#define PS2_C0_RVBon1_L (0x18C) +#define PS2_C0_RVBon2_L (0x18E) +#define PS2_C0_RVBon1_R (0x194) +#define PS2_C0_RVBon2_R (0x196) + +#define PS2_C1_RVBon1_L (0x58C) +#define PS2_C1_RVBon2_L (0x58E) +#define PS2_C1_RVBon1_R (0x594) +#define PS2_C1_RVBon2_R (0x596) +#define PS2_C0_Reverb (0x2E4) +#define PS2_C1_Reverb (0x6E4) +#define PS2_C0_ReverbX (0x774) +#define PS2_C1_ReverbX (0x028 + 0x774) +#define PS2_C0_SPUend1 (0x340) +#define PS2_C0_SPUend2 (0x342) +#define PS2_C1_SPUend1 (0x740) +#define PS2_C1_SPUend2 (0x742) +#define PS2_C0_BVOLL (0x76C) +#define PS2_C0_BVOLR (0x76E) +#define PS2_C1_BVOLL (0x794) +#define PS2_C1_BVOLR (0x796) +#define PS2_C0_MMIX (0x198) +#define PS2_C1_MMIX (0x598) + +#define PS2_C0_MVOLL (0x760) +#define PS2_C0_MVOLR (0x762) + +//########################################################################### + +/* + Included the info received in Regs.txt list by Neill Corlett - Kanodin + + Voice parameters: + SD_VP_VOLL, SD_VP_VOLR - Volume left/right per voice. Assuming identical to PS1. + SD_VP_PITCH - Pitch scaler 0000-3FFF. Assuming identical to PS1. + SD_VP_ADSR1, SD_VP_ADSR1 - Envelope data. Bitfields are documented as identical to PS1. + SD_VP_ENVX - Current envelope value. Assuming identical to PS1. + SD_VP_VOLXL, SD_VP_VOLXR - Current voice volume left/right. Does not exist on the PS1. + Guessing that this is handy for the increase/decrease modes. + + Voice addresses: + + SD_VA_SSA - Sample start address; assuming identical to PS1 + SD_VA_LSAX - Loop start address; assuming identical to PS1 + SD_VA_NAX - Seems to be documented as the current playing address. + Does not exist on PS1. + + Switches: + + SD_S_PMON - Pitch mod; assuming identical to PS1 + SD_S_NON - Noise; assuming identical to PS1 + SD_S_VMIXL, SD_S_VMIXR - Voice mix L/R. Guessing this is just a separate L/R version + of the "voice enable" bits on the PS1. + SD_S_VMIXEL, SD_S_VMIXER - Voice effect mix L/R. Guessing this is just a separate L/R + version of the "voice reverb enable" bits on the PS1. + SD_S_KON, SD_S_KOFF - Key on/off; assuming identical to PS1 + + + Addresses: + + SD_A_TSA - Transfer start address; assuming identical to PS1 + SD_A_ESA - Effect start address - this is probably analogous to the + PS1's reverb work area start address + SD_A_EEA - Effect end address - this would've been fixed to 0x7FFFF on + the PS1; settable in 128K increments on the PS2. + SD_A_IRQA - IRQ address; assuming identical to PS1 + + Volume parameters: + + SD_P_MVOLL, SD_P_MVOLR - Master volume L/R; assuming identical to PS1 + SD_P_EVOLL, SD_P_EVOLR - Effect volume L/R; assuming analogous to RVOL on the PS1 + SD_P_AVOLL, SD_P_AVOLR - External input volume L/R + This is probably where CORE0 connects to CORE1 + SD_P_BVOLL, SD_P_BVOLR - Sound data input volume - perhaps this is the volume of + the raw PCM auto-DMA input? analogous to CD input volume? + SD_P_MVOLXL, SD_P_MVOLXR - Current master volume L/R; seems self-explanatory + + SD_P_MMIX - Mixer / effect enable bits. + bit 11 = MSNDL = voice output dry L + 10 = MSNDR = voice output dry R + 9 = MSNDEL = voice output wet L + 8 = MSNDER = voice output wet R + 7 = MINL = sound data input dry L + 6 = MINR = sound data input dry R + 5 = MINEL = sound data input wet L + 4 = MINER = sound data input wet R + 3 = SINL = core external input dry L + 2 = SINR = core external input dry R + 1 = SINEL = core external input wet L + 0 = SINER = core external input wet R + +Core attributes (SD_C) + + bit 4..5 - DMA related + bit 6 - IRQ enable + bit 7 - effect enable (reverb enable) + bit 13..8 - noise clock + bit 14 - mute + + - if you READ the two DMA related bits, if either are set, the channel is + considered "busy" by sceSdVoiceTrans + + + +Reverb parameters: + + Same as PS1 reverb (I used the names from my reverb doc). + + +Other PS2 IOP notes + + There's two DMA controllers: + The original one at 1F801080-1F8010FF (channels 0-6) + A new one at 1F801500-1F80157F (channels 7-13) + + They appear to function the same way - 7 channels each. + + SPU CORE0's DMA channel is 4 as per usual + SPU CORE1's DMA channel is 7 + +DMA channel 10 is SIF + + Original INTR controller at 1F801000-1F80107F + + All interrupt handling seems to be done using the old INTR, but + with some new bits defined: + + + + Reading from 1F801078 masks interrupts and returns 1 if they weren't + masked before. Writing 1 to 1F801078 re-enables interrupts. + Writing 0 doesn't. Maybe it was like that on the original PS1 too. + +Six root counters: + + RTC# address sources size prescale interrupt# +0 0x1F801100 sysclock,pixel 16 bit 1 only 4 +1 0x1F801110 sysclock,hline 16 bit 1 only 5 +2 0x1F801120 sysclock 16 bit 1,8 6 +3 0x1F801480 sysclock,hline 32 bit 1 only 14 +4 0x1F801490 sysclock 32 bit 1,8,16,256 15 +5 0x1F8014A0 sysclock 32 bit 1,8,16,256 16 + +Count (0x0) and Compare (0x8) registers work as before, only with more bits +in the new counters. + +Mode (0x4) works like this when written: + + bits 0..2 gate + bit 3 reset on target + bit 4 target interrupt enable + bit 5 overflow interrupt enable + bit 6 master enable (?) + bit 7 ? + bit 8 clock select + bit 9 prescale (OLD) + bit 10..12 ? + bit 13..14 prescale (NEW) + bit 15 ? always set to 1 + +Gate: + TM_NO_GATE 000 + TM_GATE_ON_Count 001 + TM_GATE_ON_ClearStart 011 + TM_GATE_ON_Clear_OFF_Start 101 + TM_GATE_ON_Start 111 + + V-blank ----+ +----------------------------+ +------ + | | | | + | | | | + +----+ +----+ + TM_NO_GATE: + + 0================================>============ + + TM_GATE_ON_Count: + + <---->0==========================><---->0===== + + TM_GATE_ON_ClearStart: + + 0====>0================================>0===== + + TM_GATE_ON_Clear_OFF_Start: + + 0====><-------------------------->0====><----- + + TM_GATE_ON_Start: + + <---->0==========================>============ + + reset on target: if set, counter resets to 0 when Compare value is reached + + target interrupt enable: if set, interrupt when Compare value is reached + overflow interrupt enable: if set, interrupt when counter overflows + + master enable: if this bit is clear, the timer should do nothing. + + clock select: for counters 0, 1, and 3, setting this will select the alternate + counter (pixel or hline) + + prescale (OLD): for counter 2 only. set this to prescale (divide) by 8. + + prescale (NEW): for counters 4 and 5 only: + + 00 = prescale by 1 + 01 = prescale by 8 + 10 = prescale by 16 + 11 = prescale by 256 + +Writing 0x4 also clears the counter. (I think.) + +When 0x4 is read, it becomes Status: + + bit 0..10 ? + bit 11 compare value was reached + bit 12 count overflowed + bit 13..15 ? + +Reading probably clears these bits. + + + + 1F8014B0 (word) - timer-related but otherwise unknown + 1F8014C0 (word) - timer-related but otherwise unknown + + + don't currently know how the interrupts work for DMA ch7 yet + + 1F801060 (word) - address of some kind. + + 1F801450 (word) - + if bit 3 is SET, we're in PS1 mode. + if bit 3 is CLEAR, we're in PS2 IOP mode. + + 1F802070 (byte) - unknown. status byte of some kind? visible to EE? + + 1D000000-1D00007F (?) - SIF related + + 1D000020 (word) - read counter of some sort? + sceSifInit waits for bit 0x10000 of this to be set. + 1D000030 (word) - read counter of some sort? + 1D000040 (word) - read bits 0x20, 0x40 mean something + 1D000060 (word) - used to detect whether the SIF interface exists + read must be 0x1D000060, or the top 20 bits must be zero +*/ + +/* + +// DirectX Audio SPU2 Driver for PCSX2 +// audio.c by J.F. and Kanodin (hooper1@cox.net) +// +// Copyright 2003 J.F. and Kanodin, and distributed under the +// terms of the GNU General Public License, v2 or later. +// http://www.gnu.org/copyleft/gpl.html. + +Included these just in case you need them J.F. - Kanodin + +// Core Start Addresses +#define CORE0 0x1f900000 +#define CORE1 0x1f900400 + + + #define IOP_INT_VBLANK (1<<0) + #define IOP_INT_GM (1<<1) + #define IOP_INT_CDROM (1<<2) + #define IOP_INT_DMA (1<<3) + #define IOP_INT_RTC0 (1<<4) + #define IOP_INT_RTC1 (1<<5) + #define IOP_INT_RTC2 (1<<6) + #define IOP_INT_SIO0 (1<<7) + #define IOP_INT_SIO1 (1<<8) + #define IOP_INT_SPU (1<<9) + #define IOP_INT_PIO (1<<10) + #define IOP_INT_EVBLANK (1<<11) + #define IOP_INT_DVD (1<<12) + #define IOP_INT_PCMCIA (1<<13) + #define IOP_INT_RTC3 (1<<14) + #define IOP_INT_RTC4 (1<<15) + #define IOP_INT_RTC5 (1<<16) + #define IOP_INT_SIO2 (1<<17) + #define IOP_INT_HTR0 (1<<18) + #define IOP_INT_HTR1 (1<<19) + #define IOP_INT_HTR2 (1<<20) + #define IOP_INT_HTR3 (1<<21) + #define IOP_INT_USB (1<<22) + #define IOP_INT_EXTR (1<<23) + #define IOP_INT_FWRE (1<<24) + #define IOP_INT_FDMA (1<<25) + +// CORE0 => +0x000, CORE1 => +0x400 + +// individual voice parameter regs + +#define VP_VOLL(cr, vc) (0x400 * cr + (vc << 4)) // voice volume (left) +#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right) +#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch +#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL) +#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR) +#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value) +#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left) +#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right) + +#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address +#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address +#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address + +// common settings + +#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on +#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on +#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left) +#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left) +#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right) +#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right) +#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below) +#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below) +#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address +#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation) +#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation) +#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address +#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register +#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register +#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status + +#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address + +#define FB_SRC_A(cr) (0x400 * cr + 0x2E4) +#define FB_SRC_B(cr) (0x400 * cr + 0x2E8) +#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC) +#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0) +#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4) +#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8) +#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC) + +#define ACC_SRC_B1(cr) (0x400 * cr + 0x300) +#define IIR_SRC_A0(cr) (0x400 * cr + 0x304) +#define IIR_SRC_A1(cr) (0x400 * cr + 0x308) +#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C) +#define IIR_DEST_B1(cr) (0x400 * cr + 0x310) +#define ACC_SRC_C0(cr) (0x400 * cr + 0x314) +#define ACC_SRC_C1(cr) (0x400 * cr + 0x318) + +#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C) +#define ACC_SRC_D1(cr) (0x400 * cr + 0x320) +#define IIR_SRC_B1(cr) (0x400 * cr + 0x324) +#define IIR_SRC_B0(cr) (0x400 * cr + 0x328) +#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C) +#define MIX_DEST_A1(cr) (0x400 * cr + 0x330) +#define MIX_DEST_B0(cr) (0x400 * cr + 0x334) +#define MIX_DEST_B1(cr) (0x400 * cr + 0x338) + +#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address + +#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status +#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register +#define P_ENDS(cr) (0x400 * cr + 0x346) // ? + +// CORE0 => +0x400, CORE1 => +0x428 + +#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left) +#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right) +#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left) +#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right) +#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left) +#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right) +#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left) +#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right) +#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left) +#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right) + +#define IIR_ALPHA(cr) (0x28 * cr + 0x774) +#define ACC_COEF_A(cr) (0x28 * cr + 0x776) +#define ACC_COEF_B(cr) (0x28 * cr + 0x778) +#define ACC_COEF_C(cr) (0x28 * cr + 0x77A) +#define ACC_COEF_D(cr) (0x28 * cr + 0x77C) +#define IIR_COEF(cr) (0x28 * cr + 0x77E) +#define FB_ALPHA(cr) (0x28 * cr + 0x780) +#define FB_X(cr) (0x28 * cr + 0x782) +#define IN_COEF_L(cr) (0x28 * cr + 0x784) +#define IN_COEF_R(cr) (0x28 * cr + 0x786) + +// CORE1 only => +0x400 + +#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass +#define SPDIF_MODE 0x7C6 +#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD +#define SPDIF_COPY 0x7CA // SPDIF Copy Protection + +// PS1 SPU CORE + +// individual voice settings + +#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch +#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address +#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope +#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address + +// common settings + +#define SPU_P_MVOLL 0xD80 // master volume (left) +#define SPU_P_MVOLR 0xD82 // master volume (right) +#define SPU_P_RVOLL 0xD84 // effect return volume (left) +#define SPU_P_RVOLR 0xD86 // effect return volume (right) +#define SPU_S_KON1 0xD88 // key on +#define SPU_S_KON2 0xD8A // +#define SPU_S_KOFF1 0xD8C // key off +#define SPU_S_KOFF2 0xD8E // +#define SPU_S_PMON1 0xD90 // pitch modulation on +#define SPU_S_PMON2 0xD92 // +#define SPU_S_NON1 0xD94 // noise generator on +#define SPU_S_NON2 0xD96 // +#define SPU_S_RVBON1 0xD98 // effects on +#define SPU_S_RVBON2 0xD9A // +#define SPU_S_MUTE1 0xD9C // voice mute +#define SPU_S_MUTE2 0xD9E // + +#define SPU_A_ESA 0xDA2 // effects work area start +#define SPU_A_IRQA 0xDA4 // IRQ address +#define SPU_A_TSA 0xDA6 // DMA transfer start address +#define SPU_P_DATA 0xDA8 // DMA data register +#define SPU_P_CTRL 0xDAA // DMA control register +#define SPU_P_STAT 0xDAE // DMA status register + +#define SPU_P_CDL 0xDB0 // sound data input volume (left) +#define SPU_P_CDR 0xDB2 // sound data input volume (right) +#define SPU_P_EXTL 0xDB4 // external input volume (left) +#define SPU_P_EXTR 0xDB6 // external input volume (right) + +#define SPU_P_REVERB 0xDC0 // effects control + + +// Individual voice parameter regs CORE 0 +// Only + + +#define VP_VOLL(cr, vc) (0x400 * cr + (vc << 4)) // voice volume (left) +#define VP_VOLR(cr, vc) (0x400 * cr + 0x002 + (vc << 4)) // voice volume (right) +#define VP_PITCH(cr, vc) (0x400 * cr + 0x004 + (vc << 4)) // voice pitch +#define VP_ADSR1(cr, vc) (0x400 * cr + 0x006 + (vc << 4)) // voice envelope (AR, DR, SL) +#define VP_ADSR2(cr, vc) (0x400 * cr + 0x008 + (vc << 4)) // voice envelope (SR, RR) +#define VP_ENVX(cr, vc) (0x400 * cr + 0x00A + (vc << 4)) // voice envelope (current value) +#define VP_VOLXL(cr, vc) (0x400 * cr + 0x00C + (vc << 4)) // voice volume (current value left) +#define VP_VOLXR(cr, vc) (0x400 * cr + 0x00E + (vc << 4)) // voice volume (current value right) + +#define VA_SSA(cr, vc) (0x400 * cr + 0x1C0 + (vc * 12)) // voice waveform data start address +#define VA_LSAX(cr, vc) (0x400 * cr + 0x1C4 + (vc * 12)) // voice waveform data loop address +#define VA_NAX(cr, vc) (0x400 * cr + 0x1C8 + (vc * 12)) // voice waveform data next address + + +// CORE 0 Common Settings + + +#define S_PMON(cr) (0x400 * cr + 0x180) // pitch modulation on +#define S_NON(cr) (0x400 * cr + 0x184) // noise generator on +#define S_VMIXL(cr) (0x400 * cr + 0x188) // voice output mixing (dry left) +#define S_VMIXEL(cr) (0x400 * cr + 0x18C) // voice output mixing (wet left) +#define S_VMIXR(cr) (0x400 * cr + 0x190) // voice output mixing (dry right) +#define S_VMIXER(cr) (0x400 * cr + 0x194) // voice output mixing (wet right) +#define P_MMIX(cr) (0x400 * cr + 0x198) // output type after voice mixing (See paragraph below) +#define P_ATTR(cr) (0x400 * cr + 0x19A) // core attributes (See paragraph below) +#define A_IRQA(cr) (0x400 * cr + 0x19C) // IRQ address +#define S_KON(cr) (0x400 * cr + 0x1A0) // key on (start voice sound generation) +#define S_KOFF(cr) (0x400 * cr + 0x1A4) // key off (end voice sound generation) +#define A_TSA(cr) (0x400 * cr + 0x1A8) // DMA transfer start address +#define P_DATA(cr) (0x400 * cr + 0x1AC) // DMA data register +#define P_CTRL(cr) (0x400 * cr + 0x1AE) // DMA control register +#define P_ADMAS(cr) (0x400 * cr + 0x1B0) // AutoDMA status + +#define A_ESA(cr) (0x400 * cr + 0x2E0) // effects work area start address + + +// Core 0 Reverb Addresses + + +#define FB_SRC_A(cr) (0x400 * cr + 0x2E4) +#define FB_SRC_B(cr) (0x400 * cr + 0x2E8) +#define IIR_DEST_A0(cr) (0x400 * cr + 0x2EC) +#define IIR_DEST_A1(cr) (0x400 * cr + 0x2F0) +#define ACC_SRC_A0(cr) (0x400 * cr + 0x2F4) +#define ACC_SRC_A1(cr) (0x400 * cr + 0x2F8) +#define ACC_SRC_B0(cr) (0x400 * cr + 0x2FC) + +#define ACC_SRC_B1(cr) (0x400 * cr + 0x300) +#define IIR_SRC_A0(cr) (0x400 * cr + 0x304) +#define IIR_SRC_A1(cr) (0x400 * cr + 0x308) +#define IIR_DEST_B0(cr) (0x400 * cr + 0x30C) +#define IIR_DEST_B1(cr) (0x400 * cr + 0x310) +#define ACC_SRC_C0(cr) (0x400 * cr + 0x314) +#define ACC_SRC_C1(cr) (0x400 * cr + 0x318) + +#define ACC_SRC_D0(cr) (0x400 * cr + 0x31C) +#define ACC_SRC_D1(cr) (0x400 * cr + 0x320) +#define IIR_SRC_B1(cr) (0x400 * cr + 0x324) +#define IIR_SRC_B0(cr) (0x400 * cr + 0x328) +#define MIX_DEST_A0(cr) (0x400 * cr + 0x32C) +#define MIX_DEST_A1(cr) (0x400 * cr + 0x330) +#define MIX_DEST_B0(cr) (0x400 * cr + 0x334) +#define MIX_DEST_B1(cr) (0x400 * cr + 0x338) + +#define A_EEA(cr) (0x400 * cr + 0x33C) // effects work area end address + +#define P_ENDX(cr) (0x400 * cr + 0x340) // voice loop end status +#define P_STAT(cr) (0x400 * cr + 0x344) // DMA status register +#define P_ENDS(cr) (0x400 * cr + 0x346) // ? + + +// CORE 0 Specific + + +#define P_MVOLL(cr) (0x28 * cr + 0x760) // master volume (left) +#define P_MVOLR(cr) (0x28 * cr + 0x762) // master volume (right) +#define P_EVOLL(cr) (0x28 * cr + 0x764) // effect return volume (left) +#define P_EVOLR(cr) (0x28 * cr + 0x766) // effect return volume (right) +#define P_AVOLL(cr) (0x28 * cr + 0x768) // core external input volume (left) +#define P_AVOLR(cr) (0x28 * cr + 0x76A) // core external input volume (right) +#define P_BVOLL(cr) (0x28 * cr + 0x76C) // sound data input volume (left) +#define P_BVOLR(cr) (0x28 * cr + 0x76E) // sound data input volume (right) +#define P_MVOLXL(cr) (0x28 * cr + 0x770) // current master volume (left) +#define P_MVOLXR(cr) (0x28 * cr + 0x772) // current master volume (right) + + +// More CORE 0 Reverb + + +#define IIR_ALPHA(cr) (0x28 * cr + 0x774) +#define ACC_COEF_A(cr) (0x28 * cr + 0x776) +#define ACC_COEF_B(cr) (0x28 * cr + 0x778) +#define ACC_COEF_C(cr) (0x28 * cr + 0x77A) +#define ACC_COEF_D(cr) (0x28 * cr + 0x77C) +#define IIR_COEF(cr) (0x28 * cr + 0x77E) +#define FB_ALPHA(cr) (0x28 * cr + 0x780) +#define FB_X(cr) (0x28 * cr + 0x782) +#define IN_COEF_L(cr) (0x28 * cr + 0x784) +#define IN_COEF_R(cr) (0x28 * cr + 0x786) + + +// CORE 1 only + +#define SPDIF_OUT 0x7C0 // SPDIF Out: OFF/'PCM'/Bitstream/Bypass +#define SPDIF_MODE 0x7C6 +#define SPDIF_MEDIA 0x7C8 // SPDIF Media: 'CD'/DVD +#define SPDIF_COPY 0x7CA // SPDIF Copy Protection +*/ + +/* PS1 SPU CORE + +*** The below really isn't needed, only if you *** +*** want to add SPU support to the plugin *** +*** which I see no need to add at this time. *** +*** individual voice settings *** + +#define SPU_VP_PITCH(vc) (0xC04 + (vc << 4)) // voice pitch +#define SPU_VA_SSA(vc) (0xC06 + (vc << 4)) // voice waveform data start address +#define SPU_VP_ADSR(vc) (0xC08 + (vc << 4)) // voice envelope +#define SPU_VA_SSA(vc) (0xC0E + (vc << 4)) // voice waveform data loop address + +// common settings + +#define SPU_P_MVOLL 0xD80 // master volume (left) +#define SPU_P_MVOLR 0xD82 // master volume (right) +#define SPU_P_RVOLL 0xD84 // effect return volume (left) +#define SPU_P_RVOLR 0xD86 // effect return volume (right) +#define SPU_S_KON1 0xD88 // key on +#define SPU_S_KON2 0xD8A // +#define SPU_S_KOFF1 0xD8C // key off +#define SPU_S_KOFF2 0xD8E // +#define SPU_S_PMON1 0xD90 // pitch modulation on +#define SPU_S_PMON2 0xD92 // +#define SPU_S_NON1 0xD94 // noise generator on +#define SPU_S_NON2 0xD96 // +#define SPU_S_RVBON1 0xD98 // effects on +#define SPU_S_RVBON2 0xD9A // +#define SPU_S_MUTE1 0xD9C // voice mute +#define SPU_S_MUTE2 0xD9E // + +#define SPU_A_ESA 0xDA2 // effects work area start +#define SPU_A_IRQA 0xDA4 // IRQ address +#define SPU_A_TSA 0xDA6 // DMA transfer start address +#define SPU_P_DATA 0xDA8 // DMA data register +#define SPU_P_CTRL 0xDAA // DMA control register +#define SPU_P_STAT 0xDAE // DMA status register + +#define SPU_P_CDL 0xDB0 // sound data input volume (left) +#define SPU_P_CDR 0xDB2 // sound data input volume (right) +#define SPU_P_EXTL 0xDB4 // external input volume (left) +#define SPU_P_EXTR 0xDB6 // external input volume (right) + +#define SPU_P_REVERB 0xDC0 // effects control +*/ + +/* +#define H_SPUReverbAddr 0x0da2 +#define H_SPUirqAddr 0x0da4 +#define H_SPUaddr 0x0da6 +#define H_SPUdata 0x0da8 +#define H_SPUctrl 0x0daa +#define H_SPUstat 0x0dae +#define H_SPUmvolL 0x0d80 +#define H_SPUmvolR 0x0d82 +#define H_SPUrvolL 0x0d84 +#define H_SPUrvolR 0x0d86 +#define H_SPUon1 0x0d88 +#define H_SPUon2 0x0d8a +#define H_SPUoff1 0x0d8c +#define H_SPUoff2 0x0d8e +#define H_FMod1 0x0d90 +#define H_FMod2 0x0d92 +#define H_Noise1 0x0d94 +#define H_Noise2 0x0d96 +#define H_RVBon1 0x0d98 +#define H_RVBon2 0x0d9a +#define H_SPUMute1 0x0d9c +#define H_SPUMute2 0x0d9e +#define H_CDLeft 0x0db0 +#define H_CDRight 0x0db2 +#define H_ExtLeft 0x0db4 +#define H_ExtRight 0x0db6 +#define H_Reverb 0x0dc0 +#define H_SPUPitch0 0x0c04 +#define H_SPUPitch1 0x0c14 +#define H_SPUPitch2 0x0c24 +#define H_SPUPitch3 0x0c34 +#define H_SPUPitch4 0x0c44 +#define H_SPUPitch5 0x0c54 +#define H_SPUPitch6 0x0c64 +#define H_SPUPitch7 0x0c74 +#define H_SPUPitch8 0x0c84 +#define H_SPUPitch9 0x0c94 +#define H_SPUPitch10 0x0ca4 +#define H_SPUPitch11 0x0cb4 +#define H_SPUPitch12 0x0cc4 +#define H_SPUPitch13 0x0cd4 +#define H_SPUPitch14 0x0ce4 +#define H_SPUPitch15 0x0cf4 +#define H_SPUPitch16 0x0d04 +#define H_SPUPitch17 0x0d14 +#define H_SPUPitch18 0x0d24 +#define H_SPUPitch19 0x0d34 +#define H_SPUPitch20 0x0d44 +#define H_SPUPitch21 0x0d54 +#define H_SPUPitch22 0x0d64 +#define H_SPUPitch23 0x0d74 + +#define H_SPUStartAdr0 0x0c06 +#define H_SPUStartAdr1 0x0c16 +#define H_SPUStartAdr2 0x0c26 +#define H_SPUStartAdr3 0x0c36 +#define H_SPUStartAdr4 0x0c46 +#define H_SPUStartAdr5 0x0c56 +#define H_SPUStartAdr6 0x0c66 +#define H_SPUStartAdr7 0x0c76 +#define H_SPUStartAdr8 0x0c86 +#define H_SPUStartAdr9 0x0c96 +#define H_SPUStartAdr10 0x0ca6 +#define H_SPUStartAdr11 0x0cb6 +#define H_SPUStartAdr12 0x0cc6 +#define H_SPUStartAdr13 0x0cd6 +#define H_SPUStartAdr14 0x0ce6 +#define H_SPUStartAdr15 0x0cf6 +#define H_SPUStartAdr16 0x0d06 +#define H_SPUStartAdr17 0x0d16 +#define H_SPUStartAdr18 0x0d26 +#define H_SPUStartAdr19 0x0d36 +#define H_SPUStartAdr20 0x0d46 +#define H_SPUStartAdr21 0x0d56 +#define H_SPUStartAdr22 0x0d66 +#define H_SPUStartAdr23 0x0d76 + +#define H_SPULoopAdr0 0x0c0e +#define H_SPULoopAdr1 0x0c1e +#define H_SPULoopAdr2 0x0c2e +#define H_SPULoopAdr3 0x0c3e +#define H_SPULoopAdr4 0x0c4e +#define H_SPULoopAdr5 0x0c5e +#define H_SPULoopAdr6 0x0c6e +#define H_SPULoopAdr7 0x0c7e +#define H_SPULoopAdr8 0x0c8e +#define H_SPULoopAdr9 0x0c9e +#define H_SPULoopAdr10 0x0cae +#define H_SPULoopAdr11 0x0cbe +#define H_SPULoopAdr12 0x0cce +#define H_SPULoopAdr13 0x0cde +#define H_SPULoopAdr14 0x0cee +#define H_SPULoopAdr15 0x0cfe +#define H_SPULoopAdr16 0x0d0e +#define H_SPULoopAdr17 0x0d1e +#define H_SPULoopAdr18 0x0d2e +#define H_SPULoopAdr19 0x0d3e +#define H_SPULoopAdr20 0x0d4e +#define H_SPULoopAdr21 0x0d5e +#define H_SPULoopAdr22 0x0d6e +#define H_SPULoopAdr23 0x0d7e + +#define H_SPU_ADSRLevel0 0x0c08 +#define H_SPU_ADSRLevel1 0x0c18 +#define H_SPU_ADSRLevel2 0x0c28 +#define H_SPU_ADSRLevel3 0x0c38 +#define H_SPU_ADSRLevel4 0x0c48 +#define H_SPU_ADSRLevel5 0x0c58 +#define H_SPU_ADSRLevel6 0x0c68 +#define H_SPU_ADSRLevel7 0x0c78 +#define H_SPU_ADSRLevel8 0x0c88 +#define H_SPU_ADSRLevel9 0x0c98 +#define H_SPU_ADSRLevel10 0x0ca8 +#define H_SPU_ADSRLevel11 0x0cb8 +#define H_SPU_ADSRLevel12 0x0cc8 +#define H_SPU_ADSRLevel13 0x0cd8 +#define H_SPU_ADSRLevel14 0x0ce8 +#define H_SPU_ADSRLevel15 0x0cf8 +#define H_SPU_ADSRLevel16 0x0d08 +#define H_SPU_ADSRLevel17 0x0d18 +#define H_SPU_ADSRLevel18 0x0d28 +#define H_SPU_ADSRLevel19 0x0d38 +#define H_SPU_ADSRLevel20 0x0d48 +#define H_SPU_ADSRLevel21 0x0d58 +#define H_SPU_ADSRLevel22 0x0d68 +#define H_SPU_ADSRLevel23 0x0d78 +*/ diff --git a/plugins/spu2/PeopsSPU2/regs.h b/plugins/spu2/PeopsSPU2/regs.h new file mode 100644 index 0000000..2cacafe --- /dev/null +++ b/plugins/spu2/PeopsSPU2/regs.h @@ -0,0 +1,43 @@ +/*************************************************************************** + regs.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void SoundOn(int start,int end,unsigned short val); +void SoundOff(int start,int end,unsigned short val); +void VolumeOn(int start,int end,unsigned short val,int iRight); +void FModOn(int start,int end,unsigned short val); +void NoiseOn(int start,int end,unsigned short val); +void SetVolumeL(unsigned char ch,short vol); +void SetVolumeR(unsigned char ch,short vol); +void SetPitch(int ch,unsigned short val); +void ReverbOn(int start,int end,unsigned short val,int iRight); +void SetReverbAddr(int core); + +EXPORT_GCC void CALLBACK SPU2write(unsigned long reg, unsigned short val); + diff --git a/plugins/spu2/PeopsSPU2/res/spu2PeopsSound.rc2 b/plugins/spu2/PeopsSPU2/res/spu2PeopsSound.rc2 new file mode 100644 index 0000000..7bfe5d1 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/res/spu2PeopsSound.rc2 @@ -0,0 +1,13 @@ +// +// SPU2PEOPSSOUND.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/spu2/PeopsSPU2/resource.h b/plugins/spu2/PeopsSPU2/resource.h new file mode 100644 index 0000000..5d94c18 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/resource.h @@ -0,0 +1,161 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by spu2PeopsSound.rc +// +#define IDC_SETS1 3 +#define IDC_SETS2 4 +#define IDOK2 5 +#define IDD_DIALOG1 130 +#define IDD_ABOUT 130 +#define IDD_CFGDLG 131 +#define IDD_DEBUG 135 +#define IDB_BITMAP1 136 +#define IDB_BITMAP2 137 +#define IDB_BITMAP3 138 +#define IDB_BITMAP4 139 +#define IDB_BITMAP5 140 +#define IDD_RECORD 141 +#define IDC_XAVOLUME 1004 +#define IDC_ENABXA 1005 +#define IDC_XAPITCH 1006 +#define IDC_XABLOCK 1007 +#define IDC_USETIMER 1007 +#define IDC_TIMER 1007 +#define IDC_CMIXRATE 1008 +#define IDC_USEIRQ 1008 +#define IDC_USEREVERB 1008 +#define IDC_CMODE 1009 +#define IDC_VOLUME 1009 +#define IDC_CFILTER 1010 +#define IDC_IRQWAIT 1010 +#define IDC_CQUALITY 1011 +#define IDC_DEBUGMODE 1011 +#define IDC_CDSOUND 1012 +#define IDC_INTERPOL 1012 +#define IDC_PLAYALWAYS 1013 +#define IDC_RECORDMODE 1013 +#define IDC_IGNOREPITCH 1014 +#define IDC_DISSTEREO 1014 +#define IDC_AMPLIF 1015 +#define IDC_VENVELOPE 1016 +#define IDC_VOL1 1016 +#define IDC_REVERB 1017 +#define IDC_VOL2 1017 +#define IDC_VOL3 1018 +#define IDC_VOL4 1019 +#define IDC_SAREA 1022 +#define IDC_ADSR 1023 +#define IDC_MUTE1 1047 +#define IDC_MUTE2 1048 +#define IDC_MUTE3 1049 +#define IDC_MUTE4 1050 +#define IDC_MUTE5 1051 +#define IDC_MUTE6 1052 +#define IDC_MUTE7 1053 +#define IDC_MUTE8 1054 +#define IDC_MUTE9 1055 +#define IDC_MUTE10 1056 +#define IDC_MUTE11 1057 +#define IDC_MUTE12 1058 +#define IDC_MUTE13 1059 +#define IDC_MUTE14 1060 +#define IDC_MUTE15 1061 +#define IDC_MUTE16 1062 +#define IDC_MUTE17 1063 +#define IDC_MUTE18 1064 +#define IDC_MUTE19 1065 +#define IDC_MUTE20 1066 +#define IDC_MUTE21 1067 +#define IDC_MUTE22 1068 +#define IDC_MUTE23 1069 +#define IDC_MUTE24 1070 +#define IDC_CHAN1 1071 +#define IDC_CHAN2 1072 +#define IDC_CHAN3 1073 +#define IDC_CHAN4 1074 +#define IDC_CHAN5 1075 +#define IDC_CHAN6 1076 +#define IDC_CHAN7 1077 +#define IDC_CHAN8 1078 +#define IDC_CHAN9 1079 +#define IDC_CHAN10 1080 +#define IDC_CHAN11 1081 +#define IDC_CHAN12 1082 +#define IDC_CHAN13 1083 +#define IDC_CHAN14 1084 +#define IDC_CHAN15 1085 +#define IDC_CHAN16 1086 +#define IDC_CHAN17 1087 +#define IDC_CHAN18 1088 +#define IDC_CHAN19 1089 +#define IDC_CHAN20 1090 +#define IDC_CHAN21 1091 +#define IDC_CHAN22 1092 +#define IDC_CHAN23 1093 +#define IDC_CHAN24 1094 +#define IDC_SADSR1 1096 +#define IDC_SADSR2 1097 +#define IDC_SADSR3 1098 +#define IDC_SADSR4 1099 +#define IDC_SADSR5 1100 +#define IDC_SADSR6 1101 +#define IDC_CHANNUM 1102 +#define IDC_MUTEOFF 1103 +#define IDC_MUTEON 1104 +#define IDC_SADSR7 1105 +#define IDC_CI1 1106 +#define IDC_CI2 1107 +#define IDC_CI3 1108 +#define IDC_CI4 1109 +#define IDC_CI5 1110 +#define IDC_CI6 1111 +#define IDC_CI7 1112 +#define IDC_CI8 1113 +#define IDC_CI9 1114 +#define IDC_CI10 1115 +#define IDC_CI11 1116 +#define IDC_CI12 1117 +#define IDC_CI13 1118 +#define IDC_CI14 1119 +#define IDC_CI15 1120 +#define IDC_CI16 1121 +#define IDC_STA1 1122 +#define IDC_SADSR8 1123 +#define IDC_STA2 1124 +#define IDC_STA3 1125 +#define IDC_STA4 1126 +#define IDC_XA1 1127 +#define IDC_XA2 1128 +#define IDC_XA3 1129 +#define IDC_XA4 1130 +#define IDC_CI17 1131 +#define IDC_CI18 1132 +#define IDC_XA 1133 +#define IDC_WAVFILE 1134 +#define IDC_CI19 1134 +#define IDC_XA5 1135 +#define IDC_RECORD 1135 +#define IDC_XA6 1136 +#define IDC_CORE1 1137 +#define IDC_CORE2 1138 +#define IDC_REGWRITE 1139 +#define IDC_REGREAD 1140 +#define IDC_CLEAR 1141 +#define IDC_LOG 1142 +#define IDC_NOLOG 1143 +#define IDC_REGEDIT 1144 +#define IDC_VALEDIT 1145 +#define IDC_COPY 1146 +#define IDC_ASYNC 1147 +#define IDC_SPU2IRQ 1148 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 142 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1149 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/spu2/PeopsSPU2/reverb.c b/plugins/spu2/PeopsSPU2/reverb.c new file mode 100644 index 0000000..c8a23ff --- /dev/null +++ b/plugins/spu2/PeopsSPU2/reverb.c @@ -0,0 +1,420 @@ +/*************************************************************************** + reverb.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed to SPU2 functionality +// +// 2003/01/19 - Pete +// - added Neill's reverb (see at the end of file) +// +// 2002/12/26 - Pete +// - adjusted reverb handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_REVERB + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// REVERB info and timing vars... + +int * sRVBPlay[2]; +int * sRVBEnd[2]; +int * sRVBStart[2]; + +//////////////////////////////////////////////////////////////////////// +// START REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StartREVERB(int ch) +{ + int core=ch/24; + + if((s_chan[ch].bReverbL || s_chan[ch].bReverbR) && (spuCtrl2[core]&0x80)) // reverb possible? + { + if(iUseReverb==1) s_chan[ch].bRVBActive=1; + } + else s_chan[ch].bRVBActive=0; // else -> no reverb +} + +//////////////////////////////////////////////////////////////////////// +// HELPER FOR NEILL'S REVERB: re-inits our reverb mixing buf +//////////////////////////////////////////////////////////////////////// + +INLINE void InitREVERB(void) +{ + if(iUseReverb==1) + { + memset(sRVBStart[0],0,NSSIZE*2*4); + memset(sRVBStart[1],0,NSSIZE*2*4); + } +} + +//////////////////////////////////////////////////////////////////////// +// STORE REVERB +//////////////////////////////////////////////////////////////////////// + +INLINE void StoreREVERB(int ch,int ns) +{ + int core=ch/24; + + if(iUseReverb==0) return; + else + if(iUseReverb==1) // -------------------------------- // Neil's reverb + { + const int iRxl=(s_chan[ch].sval*s_chan[ch].iLeftVolume*s_chan[ch].bReverbL)/0x4000; + const int iRxr=(s_chan[ch].sval*s_chan[ch].iRightVolume*s_chan[ch].bReverbR)/0x4000; + + ns<<=1; + + *(sRVBStart[core]+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer + *(sRVBStart[core]+ns+1)+=iRxr; + } +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int g_buffer(int iOff,int core) // get_buffer content helper: takes care about wraps +{ + short * p=(short *)spuMem; + iOff=(iOff)+rvb[core].CurrAddr; + while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1)); + while(iOffrvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1)); + while(iOff33768L) iVal=33768L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE void s_buffer1(int iOff,int iVal,int core) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +{ + short * p=(short *)spuMem; + iOff=(iOff)+rvb[core].CurrAddr+1; + while(iOff>rvb[core].EndAddr) iOff=rvb[core].StartAddr+(iOff-(rvb[core].EndAddr+1)); + while(iOff33768L) iVal=33768L; + *(p+iOff)=(short)iVal; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBLeft(int ns,int core) +{ + if(iUseReverb==1) + { + if(!rvb[core].StartAddr || !rvb[core].EndAddr || + rvb[core].StartAddr>=rvb[core].EndAddr) // reverb is off + { + rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0; + return 0; + } + + rvb[core].iCnt++; + + if(rvb[core].iCnt&1) // we work on every second left value: downsample to 22 khz + { + if((spuCtrl2[core]&0x80)) // -> reverb on? oki + { + int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; + + const int INPUT_SAMPLE_L=*(sRVBStart[core]+(ns<<1)); + const int INPUT_SAMPLE_R=*(sRVBStart[core]+(ns<<1)+1); + + const int IIR_INPUT_A0 = (g_buffer(rvb[core].IIR_SRC_A0,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/33768L; + const int IIR_INPUT_A1 = (g_buffer(rvb[core].IIR_SRC_A1,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/33768L; + const int IIR_INPUT_B0 = (g_buffer(rvb[core].IIR_SRC_B0,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/33768L; + const int IIR_INPUT_B1 = (g_buffer(rvb[core].IIR_SRC_B1,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/33768L; + + const int IIR_A0 = (IIR_INPUT_A0 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_A0,core) * (33768L - rvb[core].IIR_ALPHA))/33768L; + const int IIR_A1 = (IIR_INPUT_A1 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_A1,core) * (33768L - rvb[core].IIR_ALPHA))/33768L; + const int IIR_B0 = (IIR_INPUT_B0 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_B0,core) * (33768L - rvb[core].IIR_ALPHA))/33768L; + const int IIR_B1 = (IIR_INPUT_B1 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_B1,core) * (33768L - rvb[core].IIR_ALPHA))/33768L; + + s_buffer1(rvb[core].IIR_DEST_A0, IIR_A0,core); + s_buffer1(rvb[core].IIR_DEST_A1, IIR_A1,core); + s_buffer1(rvb[core].IIR_DEST_B0, IIR_B0,core); + s_buffer1(rvb[core].IIR_DEST_B1, IIR_B1,core); + + ACC0 = (g_buffer(rvb[core].ACC_SRC_A0,core) * rvb[core].ACC_COEF_A)/33768L + + (g_buffer(rvb[core].ACC_SRC_B0,core) * rvb[core].ACC_COEF_B)/33768L + + (g_buffer(rvb[core].ACC_SRC_C0,core) * rvb[core].ACC_COEF_C)/33768L + + (g_buffer(rvb[core].ACC_SRC_D0,core) * rvb[core].ACC_COEF_D)/33768L; + ACC1 = (g_buffer(rvb[core].ACC_SRC_A1,core) * rvb[core].ACC_COEF_A)/33768L + + (g_buffer(rvb[core].ACC_SRC_B1,core) * rvb[core].ACC_COEF_B)/33768L + + (g_buffer(rvb[core].ACC_SRC_C1,core) * rvb[core].ACC_COEF_C)/33768L + + (g_buffer(rvb[core].ACC_SRC_D1,core) * rvb[core].ACC_COEF_D)/33768L; + + FB_A0 = g_buffer(rvb[core].MIX_DEST_A0 - rvb[core].FB_SRC_A,core); + FB_A1 = g_buffer(rvb[core].MIX_DEST_A1 - rvb[core].FB_SRC_A,core); + FB_B0 = g_buffer(rvb[core].MIX_DEST_B0 - rvb[core].FB_SRC_B,core); + FB_B1 = g_buffer(rvb[core].MIX_DEST_B1 - rvb[core].FB_SRC_B,core); + + s_buffer(rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * rvb[core].FB_ALPHA)/33768L,core); + s_buffer(rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * rvb[core].FB_ALPHA)/33768L,core); + + s_buffer(rvb[core].MIX_DEST_B0, (rvb[core].FB_ALPHA * ACC0)/33768L - (FB_A0 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/33768L - (FB_B0 * rvb[core].FB_X)/33768L,core); + s_buffer(rvb[core].MIX_DEST_B1, (rvb[core].FB_ALPHA * ACC1)/33768L - (FB_A1 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/33768L - (FB_B1 * rvb[core].FB_X)/33768L,core); + + rvb[core].iLastRVBLeft = rvb[core].iRVBLeft; + rvb[core].iLastRVBRight = rvb[core].iRVBRight; + + rvb[core].iRVBLeft = (g_buffer(rvb[core].MIX_DEST_A0,core)+g_buffer(rvb[core].MIX_DEST_B0,core))/3; + rvb[core].iRVBRight = (g_buffer(rvb[core].MIX_DEST_A1,core)+g_buffer(rvb[core].MIX_DEST_B1,core))/3; + + rvb[core].iRVBLeft = (rvb[core].iRVBLeft * rvb[core].VolLeft) / 0x4000; + rvb[core].iRVBRight = (rvb[core].iRVBRight * rvb[core].VolRight) / 0x4000; + + rvb[core].CurrAddr++; + if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr; + + return rvb[core].iLastRVBLeft+(rvb[core].iRVBLeft-rvb[core].iLastRVBLeft)/2; + } + else // -> reverb off + { + rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0; + } + + rvb[core].CurrAddr++; + if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr; + } + + return rvb[core].iLastRVBLeft; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +INLINE int MixREVERBRight(int core) +{ + if(iUseReverb==1) // Neill's reverb: + { + int i=rvb[core].iLastRVBRight+(rvb[core].iRVBRight-rvb[core].iLastRVBRight)/2; + rvb[core].iLastRVBRight=rvb[core].iRVBRight; + return i; // -> just return the last right reverb val (little bit scaled by the previous right val) + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +/* +----------------------------------------------------------------------------- +PSX reverb hardware notes +by Neill Corlett +----------------------------------------------------------------------------- + +Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway +yadda yadda. + +----------------------------------------------------------------------------- + +Basics +------ + +- The reverb buffer is 22khz 16-bit mono PCM. +- It starts at the reverb address given by 1DA2, extends to + the end of sound RAM, and wraps back to the 1DA2 address. + +Setting the address at 1DA2 resets the current reverb work address. + +This work address ALWAYS increments every 1/22050 sec., regardless of +whether reverb is enabled (bit 7 of 1DAA set). + +And the contents of the reverb buffer ALWAYS play, scaled by the +"reverberation depth left/right" volumes (1D84/1D86). +(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0) + +----------------------------------------------------------------------------- + +Register names +-------------- + +These are probably not their real names. +These are probably not even correct names. +We will use them anyway, because we can. + +1DC0: FB_SRC_A (offset) +1DC2: FB_SRC_B (offset) +1DC4: IIR_ALPHA (coef.) +1DC6: ACC_COEF_A (coef.) +1DC8: ACC_COEF_B (coef.) +1DCA: ACC_COEF_C (coef.) +1DCC: ACC_COEF_D (coef.) +1DCE: IIR_COEF (coef.) +1DD0: FB_ALPHA (coef.) +1DD2: FB_X (coef.) +1DD4: IIR_DEST_A0 (offset) +1DD6: IIR_DEST_A1 (offset) +1DD8: ACC_SRC_A0 (offset) +1DDA: ACC_SRC_A1 (offset) +1DDC: ACC_SRC_B0 (offset) +1DDE: ACC_SRC_B1 (offset) +1DE0: IIR_SRC_A0 (offset) +1DE2: IIR_SRC_A1 (offset) +1DE4: IIR_DEST_B0 (offset) +1DE6: IIR_DEST_B1 (offset) +1DE8: ACC_SRC_C0 (offset) +1DEA: ACC_SRC_C1 (offset) +1DEC: ACC_SRC_D0 (offset) +1DEE: ACC_SRC_D1 (offset) +1DF0: IIR_SRC_B1 (offset) +1DF2: IIR_SRC_B0 (offset) +1DF4: MIX_DEST_A0 (offset) +1DF6: MIX_DEST_A1 (offset) +1DF8: MIX_DEST_B0 (offset) +1DFA: MIX_DEST_B1 (offset) +1DFC: IN_COEF_L (coef.) +1DFE: IN_COEF_R (coef.) + +The coefficients are signed fractional values. +-32768 would be -1.0 + 32768 would be 1.0 (if it were possible... the highest is of course 32767) + +The offsets are (byte/8) offsets into the reverb buffer. +i.e. you multiply them by 8, you get byte offsets. +You can also think of them as (samples/4) offsets. +They appear to be signed. They can be negative. +None of the documented presets make them negative, though. + +Yes, 1DF0 and 1DF2 appear to be backwards. Not a typo. + +----------------------------------------------------------------------------- + +What it does +------------ + +We take all reverb sources: +- regular channels that have the reverb bit on +- cd and external sources, if their reverb bits are on +and mix them into one stereo 44100hz signal. + +Lowpass/downsample that to 22050hz. The PSX uses a proper bandlimiting +algorithm here, but I haven't figured out the hysterically exact specifics. +I use an 8-tap filter with these coefficients, which are nice but probably +not the real ones: + +0.037828187894 +0.157538631280 +0.321159685278 +0.449322115345 +0.449322115345 +0.321159685278 +0.157538631280 +0.037828187894 + +So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz. + +* IN MY EMULATION, I divide these by 2 to make it clip less. + (and of course the L/R output coefficients are adjusted to compensate) + The real thing appears to not do this. + +At every 22050hz tick: +- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb + steady-state algorithm described below +- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer + (This part may not be exactly right and I guessed at the coefs. TODO: check later.) + L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0]) + R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1]) +- Advance the current buffer position by 1 sample + +The wet out L and R are then upsampled to 44100hz and played at the +"reverberation depth left/right" (1D84/1D86) volume, independent of the main +volume. + +----------------------------------------------------------------------------- + +Reverb steady-state +------------------- + +The reverb steady-state algorithm is fairly clever, and of course by +"clever" I mean "batshit insane". + +buffer[x] is relative to the current buffer position, not the beginning of +the buffer. Note that all buffer offsets must wrap around so they're +contained within the reverb work area. + +Clipping is performed at the end... maybe also sooner, but definitely at +the end. + +IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; +IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L; +IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R; + +IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA); +IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA); +IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA); +IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA); + +buffer[IIR_DEST_A0 + 1sample] = IIR_A0; +buffer[IIR_DEST_A1 + 1sample] = IIR_A1; +buffer[IIR_DEST_B0 + 1sample] = IIR_B0; +buffer[IIR_DEST_B1 + 1sample] = IIR_B1; + +ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A + + buffer[ACC_SRC_B0] * ACC_COEF_B + + buffer[ACC_SRC_C0] * ACC_COEF_C + + buffer[ACC_SRC_D0] * ACC_COEF_D; +ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A + + buffer[ACC_SRC_B1] * ACC_COEF_B + + buffer[ACC_SRC_C1] * ACC_COEF_C + + buffer[ACC_SRC_D1] * ACC_COEF_D; + +FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A]; +FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A]; +FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B]; +FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B]; + +buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA; +buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA; +buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X; +buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X; + +----------------------------------------------------------------------------- +*/ + diff --git a/plugins/spu2/PeopsSPU2/reverb.h b/plugins/spu2/PeopsSPU2/reverb.h new file mode 100644 index 0000000..5305030 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/reverb.h @@ -0,0 +1,33 @@ +/*************************************************************************** + reverb.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +INLINE void StartREVERB(int ch); +INLINE void StoreREVERB(int ch,int ns); + diff --git a/plugins/spu2/PeopsSPU2/spu.c b/plugins/spu2/PeopsSPU2/spu.c new file mode 100644 index 0000000..6cb3855 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu.c @@ -0,0 +1,1323 @@ +/*************************************************************************** + spu.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2005/08/29 - Pete +// - changed to 48Khz output +// +// 2004/12/25 - Pete +// - inc'd version for pcsx2-0.7 +// +// 2004/04/18 - Pete +// - changed all kind of things in the plugin +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2003/04/07 - Eric +// - adjusted cubic interpolation algorithm +// +// 2003/03/16 - Eric +// - added cubic interpolation +// +// 2003/03/01 - linuzappz +// - libraryName changes using ALSA +// +// 2003/02/28 - Pete +// - added option for type of interpolation +// - adjusted spu irqs again (Thousant Arms, Valkyrie Profile) +// - added MONO support for MSWindows DirectSound +// +// 2003/02/20 - kode54 +// - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault +// +// 2003/02/19 - kode54 +// - moved SPU IRQ handler and changed sample flag processing +// +// 2003/02/18 - kode54 +// - moved ADSR calculation outside of the sample decode loop, somehow I doubt that +// ADSR timing is relative to the frequency at which a sample is played... I guess +// this remains to be seen, and I don't know whether ADSR is applied to noise channels... +// +// 2003/02/09 - kode54 +// - one-shot samples now process the end block before stopping +// - in light of removing fmod hack, now processing ADSR on frequency channel as well +// +// 2003/02/08 - kode54 +// - replaced easy interpolation with gaussian +// - removed fmod averaging hack +// - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :) +// +// 2003/02/08 - linuzappz +// - small bugfix for one usleep that was 1 instead of 1000 +// - added iDisStereo for no stereo (Linux) +// +// 2003/01/22 - Pete +// - added easy interpolation & small noise adjustments +// +// 2003/01/19 - Pete +// - added Neill's reverb +// +// 2003/01/12 - Pete +// - added recording window handlers +// +// 2003/01/06 - Pete +// - added Neill's ADSR timings +// +// 2002/12/28 - Pete +// - adjusted spu irq handling, fmod handling and loop handling +// +// 2002/08/14 - Pete +// - added extra reverb +// +// 2002/06/08 - linuzappz +// - SPUupdate changed for SPUasync +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_SPU + +#include "externals.h" +#include "cfg.h" +#include "dsoundoss.h" +#include "regs.h" +#include "debug.h" +#include "record.h" +#include "resource.h" +#include "dma.h" +#include "registers.h" + +#if !defined(_WIN32) + +#include + +#if !defined(CALLBACK) +#define CALLBACK +#endif + +#define Sleep(x) sleep((x)*1000) +#endif + +//////////////////////////////////////////////////////////////////////// +// spu version infos/name +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 5; +const unsigned char revision = 1; +const unsigned char build = 6; +#ifdef _DEBUG +static char * libraryName = "P.E.Op.S. SPU2 (Debug) "; +#else +static char * libraryName = "P.E.Op.S. SPU2 "; +#endif +static char * libraryInfo = "P.E.Op.S. SPU2 Driver V1.6\nCoded by Pete Bernert, Saqib and the P.E.Op.S. team\n"; + +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +// psx buffer / addresses + +unsigned short regArea[32*1024]; + short spuMem[2*1024*1024]; + char * spuMemC; +unsigned char * pSpuIrq[2]; +unsigned char * pSpuBuffer; +unsigned char * pSpuStreamBuffer[2]; + +// user settings + +int iVolume=3; +int iDebugMode=0; +int iRecordMode=0; +int iUseReverb=0; +int iUseInterpolation=2; + +// MAIN infos struct for each channel +int iDisStereo; + +SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) +REVERBInfo rvb[2]; + +unsigned long dwNoiseVal=1; // global noise generator +int iSPUIRQWait=1; +unsigned short spuCtrl2[2]; // some vars to store psx reg infos +unsigned short spuStat2[2]; +unsigned long spuIrq2[2]; +unsigned long spuAddr2[2]; // address into spu mem +unsigned long spuRvbAddr2[2]; +unsigned long spuRvbAEnd2[2]; +int bEndThread=0; // thread handlers +int bSpuInit=0; +int bSPUIsOpen=0; +int bThreadEnded=0; +int iUseTimer=2; +int aSyncMode=0; +unsigned long aSyncCounter=0; +unsigned long aSyncWait=0; +DWORD aSyncTimerNew; +DWORD aSyncTimerOld; + +#ifdef _WIN32 +HWND hWMain=0; // window handle +HWND hWDebug=0; +HWND hWRecord=0; + +static HANDLE hMainThread; +#else +#include +static pthread_t hMainThread; +#endif + +unsigned long dwNewChannel2[2]; // flags for faster testing, if new channel starts +unsigned long dwEndChannel2[2]; + +void (CALLBACK *irqCallbackDMA4)()=0; // func of main emu, called on spu irq +void (CALLBACK *irqCallbackDMA7)()=0; // func of main emu, called on spu irq +void (CALLBACK *irqCallbackSPU2)()=0; // func of main emu, called on spu irq + +// certain globals (were local before, but with the new timeproc I need em global) + +const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; +int SSumR[NSSIZE]; +int SSumL[NSSIZE]; + +extern ADMA Adma4; +extern ADMA Adma7; +DINPUT DirectInputC0, DirectInputC1; + +extern unsigned short interrupt; +int SPUCycles; +extern int SPUStartCycle[2]; +extern int SPUTargetCycle[2]; + +int iCycle=0; +short * pS; +short * pS1; + +static int lastch=-1; // last channel processed on spu irq in timer mode +static int lastns=0; // last ns pos +static int iSecureStart=0; // secure start counter + +//////////////////////////////////////////////////////////////////////// +// CODE AREA +//////////////////////////////////////////////////////////////////////// + +// dirty inline func includes + +#include "reverb.c" +#include "adsr.c" + +//////////////////////////////////////////////////////////////////////// +// helpers for simple interpolation + +// +// easy interpolation on upsampling, no special filter, just "Pete's common sense" tm +// +// instead of having n equal sample values in a row like: +// ____ +// |____ +// +// we compare the current delta change with the next delta change. +// +// if curr_delta is positive, +// +// - and next delta is smaller (or changing direction): +// \. +// -__ +// +// - and next delta significant (at least twice) bigger: +// --_ +// \. +// +// - and next delta is nearly same: +// \. +// \. +// +// +// if curr_delta is negative, +// +// - and next delta is smaller (or changing direction): +// _-- +// / +// +// - and next delta significant (at least twice) bigger: +// / +// __- +// +// - and next delta is nearly same: +// / +// / +// + + +INLINE void InterpolateUp(int ch) +{ + if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass + { + const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val + const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) + + s_chan[ch].SB[32]=0; + + if(id1>0) // curr delta positive + { + if(id2id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + } + else + if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + s_chan[ch].SB[32]=0; + + s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; + if(s_chan[ch].sinc<=0x8000) + s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); + else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + s_chan[ch].SB[29]+=s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(int ch) +{ + if(s_chan[ch].sinc>=0x20000) // we would skip at least one val? + { + s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight + if(s_chan[ch].sinc>=0x30000) // we would skip even more vals? + s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(int ch) +{ + dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit + dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit + + StartADSR(ch); + StartREVERB(ch); + + s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start + + s_chan[ch].s_1=0; // init mixing vars + s_chan[ch].s_2=0; + s_chan[ch].iSBPos=28; + + s_chan[ch].bNew=0; // init channel flags + s_chan[ch].bStop=0; + s_chan[ch].bOn=1; + + s_chan[ch].SB[29]=0; // init our interpolation helpers + s_chan[ch].SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding + else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding +} + + +void UpdateMainVolL() // LEFT VOLUME +{ + short vol = regArea[PS2_C0_MVOLL]; + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + regArea[PS2_C0_MVOLL]=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void UpdateMainVolR() // RIGHT VOLUME +{ + short vol = regArea[PS2_C0_MVOLR]; + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + regArea[PS2_C0_MVOLR]=vol; +} +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 +extern unsigned long MemAddr[2]; +//////////////////////////////////////////////////////////////////////// + +int iSpuAsyncWait=0; +extern int MMIXC0, MMIXC1; +extern int ADMAS4Write(); +extern int ADMAS7Write(); + +extern void SoundFeedVoiceData(); + +void CALLBACK MainSPU2Proc(unsigned int nTimerId, unsigned int msg, unsigned int dwUser, + unsigned int dwParam1, unsigned int dwParam2) +{ + int s_1,s_2,fa,ns; + int core = 0; + unsigned char * start; + unsigned int nSample; + int d; + int ch,predict_nr,shift_factor,flags,s; + int gpos,bIRQReturn=0; + + while(!bEndThread) // until we are shutting down + { + //--------------------------------------------------// + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + if (aSyncMode==1) // Async supported? and enabled? + { + if (aSyncCounter<=737280) // If we have 10ms in the buffer, don't wait + { + if (aSyncWait<1000) Sleep(aSyncWait); // Wait a little to be more Synced (No more than 1 sec) + else Sleep (1000); + } + + while (aSyncCounter<=368640 && !bEndThread && aSyncMode==1) + Sleep (1); // bEndThread/aSyncMode are needed, to avoid close problems + + aSyncCounter -= 36864; // 1ms more done (48Hz*768cycles/Hz) + } + else + if(dwNewChannel2[0] || dwNewChannel2[1]) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + + if(iUseTimer) // no-thread mode? + { + return; // -> and done this time (timer mode 1 or 2) + } + // win thread mode: + Sleep(PAUSE_W); // sleep for x ms (win) + + if(dwNewChannel2[0] || dwNewChannel2[1]) + iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + if( s_chan[ch].iSBPos < 28 ) { + goto GOON; // -> directly jump to the continue point + } + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch take it and calc steps + s_chan[ch].sinc = s_chan[ch].iRawPitch<<4; + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag + } + + ns=0; + while(ns=0x10000L) + { + if(s_chan[ch].iSBPos==28) // 28 reached? + { + start=s_chan[ch].pCurr; // set up the current pos + + if (s_chan[ch].bOn==0) goto ENDX; // special "stop" sign + + s_chan[ch].iSBPos=0; + + s_1=s_chan[ch].s_1; + s_2=s_chan[ch].s_2; + + predict_nr = (int)*start; + start++; + flags = (int)*start; + start++; + + shift_factor = predict_nr&0xf; + predict_nr >>= 4; + // -------------------------------------- // + + for (nSample=0;nSample<28;nSample+=2,start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1; + s_1=fa; + s=((d & 0xf0) << 8); + + s_chan[ch].SB[nSample]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1; + s_1=fa; + + s_chan[ch].SB[nSample+1]=fa; + } + + //////////////////////////////////////////// irq check + + if(spuCtrl2[core]&0x40) // some irq active? + { + if(iDebugMode==1) logprintf("IRQ Active ch %x, C%x\r\n", ch, ch/24); + + if((pSpuIrq[core] >= start-16 && // irq address reached? + pSpuIrq[core] <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq[core] >= s_chan[ch].pLoop-16 && + pSpuIrq[core] <= s_chan[ch].pLoop))) + { + s_chan[ch].iIrqDone=1; // -> debug flag + + if(iDebugMode==1) logprintf("Sample End ch %x, C%x\r\n", ch, ch/24); + + regArea[0x7C0] |= 0x4< let's see what is happening if we call our irqs instead ;) + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + if(flags & 0x2) s_chan[ch].bIgnoreLoop=1; // LOOP bit + + if(flags&0x4) s_chan[ch].pLoop=start-16; // LOOP/START bit + + if(flags&0x1) // 1: LOOP/END bit + { + dwEndChannel2[core]|=(1<<(ch%24)); + + if((flags&0xF) != 0x3) // Check if no loop is present + { + s_chan[ch].bIgnoreLoop=0; + s_chan[ch].bStop = 1; + logprintf("Stopping\r\n"); + } + else start = s_chan[ch].pLoop; + } + + s_chan[ch].pCurr=start; // store values for next cycle + s_chan[ch].s_1=s_1; + s_chan[ch].s_2=s_2; + + + //////////////////////////////////////////// + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + if(iUseTimer!=2) + { + DWORD dwWatchTime=timeGetTime()+2500; + + while(iSpuAsyncWait && !bEndThread && + timeGetTime()32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + gpos = s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + s_chan[ch].SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + s_chan[ch].SB[28] = 0; + s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + s_chan[ch].SB[30] = s_chan[ch].SB[31]; + s_chan[ch].SB[31] = fa; + s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else s_chan[ch].SB[29]=fa; // no interpolation + + s_chan[ch].spos -= 0x10000L; + } + + //////////////////////////////////////////////// + // noise handler... just produces some noise data + // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... + // and sometimes the noise will be used as fmod modulation... pfff + + if(s_chan[ch].bNoise) + { + if((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa=((dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[core]&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + s_chan[ch].iOldNoise=fa; + + if(iUseInterpolation<2) // no gauss/cubic interpolation? + s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot + } //---------------------------------------- + else // NO NOISE (NORMAL SAMPLE DATA) HERE + {//------------------------------------------// + if(iUseInterpolation==3) // cubic interpolation + { + long xd; + xd = ((s_chan[ch].spos) >> 1)+1; + gpos = s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + } + //------------------------------------------// + else + if(iUseInterpolation==2) // gauss interpolation + { + int vl, vr; + vl = (s_chan[ch].spos >> 6) & ~3; + gpos = s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; + } + //------------------------------------------// + else + if(iUseInterpolation==1) // simple interpolation + { + if(s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(ch); // --> interpolate up + else InterpolateDown(ch); // --> else down + fa=s_chan[ch].SB[29]; + } + //------------------------------------------// + else fa=s_chan[ch].SB[29]; // no interpolation + } + + s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // add adsr + + if(s_chan[ch].bFMod==2) // fmod freq channel + { + int NP=((32768L+s_chan[ch].sval)*s_chan[ch+1].iRawPitch)>>14; + + if(NP>0x3fff) NP=0x3fff; + else if(NP<0x1) NP=0x1; + + NP=(48000L*NP)>>12; // calc frequency ( 48hz ) + + s_chan[ch+1].iActFreq=NP; + s_chan[ch+1].iUsedFreq=NP; + s_chan[ch+1].sinc=(((NP/10)<<16)/48000); // check , was 4800 + if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1; + if(iUseInterpolation==1) // freq change in sipmle interpolation mode + s_chan[ch+1].SB[32]=1; + + } + else + { + ////////////////////////////////////////////// + // ok, left/right sound volume (ps2 volume goes from 0 ... 0x3fff) + + if(s_chan[ch].iMute) s_chan[ch].sval=0; // debug mute + else + { + if(s_chan[ch].bVolumeL) + SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14; + + if(s_chan[ch].bVolumeR) + SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + s_chan[ch].spos += s_chan[ch].sinc; + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + for(ns=0;ns>16; + if((regArea[PS2_C1_MMIX] & 0x80)) SSumL[ns] += (DirectInputC1.Left*(int)regArea[PS2_C1_BVOLL])>>16; + + UpdateMainVolL(); + + if(iVolume == 5) d = 0; + else d=SSumL[ns]/iVolume; + SSumL[ns]=0; + *pS++=(d<-32767) ? -32767 : ((d>32767) ? 32767 : d); + + SSumR[ns]+=MixREVERBRight(0); + SSumR[ns]+=MixREVERBRight(1); + + if((regArea[PS2_C0_MMIX] & 0x40)) SSumR[ns] += (DirectInputC0.Right*(int)regArea[PS2_C0_BVOLR])>>16; + if((regArea[PS2_C1_MMIX] & 0x40)) SSumR[ns] += (DirectInputC1.Right*(int)regArea[PS2_C1_BVOLR])>>16; + + UpdateMainVolR(); + if(iVolume == 5) d = 0; + else d=SSumR[ns]/iVolume; + SSumR[ns]=0; + *pS++=(d<-32767) ? -32767 : ((d>32767) ? 32767 : d); + } + InitREVERB(); + + ////////////////////////////////////////////////////// + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + + if(iCycle++>16) + { + SoundFeedVoiceData((unsigned char*)pSpuBuffer, + ((unsigned char *)pS)- + ((unsigned char *)pSpuBuffer)); + pS=(short *)pSpuBuffer; + iCycle=0; + } +} + // end of big main loop... + bThreadEnded=1; + return; +} + + +//////////////////////////////////////////////////////////////////////// +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar +//////////////////////////////////////////////////////////////////////// +EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle) +{ + SPUCycles += cycle; + if(interrupt & (1<<2)){ + if(SPUCycles - SPUStartCycle[1] >= SPUTargetCycle[1]){ + interrupt &= ~(1<<2); + irqCallbackDMA7(); + } + + } + + if(interrupt & (1<<1)){ + if(SPUCycles - SPUStartCycle[0] >= SPUTargetCycle[0]){ + interrupt &= ~(1<<1); + irqCallbackDMA4(); + } + } + + if(iSpuAsyncWait) + { + iSpuAsyncWait++; + if(iSpuAsyncWait<=64) return; + iSpuAsyncWait=0; + } + + if(iDebugMode==2) + { +#ifdef _WIN32 + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0; +#endif + iDebugMode=0; + } + if(iRecordMode==2) + { +#ifdef _WIN32 + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0; +#endif + iRecordMode=0; + } + + if(iUseTimer==0) // does the emu support SPUAsync, is it in thread mode, and in Thread Sync ON? + { + aSyncMode=1; // Ten, activate main function Sync system flag + + aSyncTimerOld = aSyncTimerNew; // Recalculate, AsyncWait (ms) + aSyncTimerNew = timeGetTime(); + + aSyncWait =(unsigned int)((aSyncTimerNew - aSyncTimerOld)/2); + + aSyncCounter += cycle ; + + return; + } + if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) + { + //printf("spu2async: calling mainspu2proc\n"); + aSyncMode = 0; + if(!bSpuInit) return; // -> no init, no call + MainSPU2Proc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks + } +} + + +//////////////////////////////////////////////////////////////////////// +// INIT/EXIT STUFF +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUINIT: this func will be called first by the main emu +//////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +static HINSTANCE hIRE = NULL; +#endif + +EXPORT_GCC long CALLBACK SPU2init(void) +{ + spuMemC=(unsigned char *)spuMem; // just small setup + memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset(rvb,0,2*sizeof(REVERBInfo)); + + InitADSR(); + +#ifdef _WIN32 + if(hIRE==NULL) hIRE=LoadLibrary("Riched32.dll "); // needed for debug output +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPTIMER: init of certain buffers and threads/timers +//////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 +DWORD WINAPI MAINThreadEx(LPVOID lpParameter) +{ + MainSPU2Proc(0,0,0,0,0); + return 0; +} +#else +void* MAINThreadEx(void* param) +{ + MainSPU2Proc(0,0,0,0,0); + return NULL; +} +#endif + +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + pS1=(short *)pSpuStreamBuffer[0]; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bSpuInit=1; // flag: we are inited + + bSpuInit=1; // flag: we are inited + +#ifdef _WIN32 + + if(iUseTimer==0) // windows: use thread + { + //_beginthread(MAINThread,0,NULL); + DWORD dw; + hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); + SetThreadPriority(hMainThread, + //THREAD_PRIORITY_TIME_CRITICAL); + THREAD_PRIORITY_HIGHEST); + } +#else + if( pthread_create(&hMainThread, NULL, MAINThreadEx, NULL) != 0 ) { + printf("Failed to create spu2thread\n"); + return; + } +#endif +} + +//////////////////////////////////////////////////////////////////////// +// REMOVETIMER: kill threads/timers +//////////////////////////////////////////////////////////////////////// + +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + + if(iUseTimer!=2) // windows thread? + { + while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended + Sleep(5L); + } + + bSpuInit=0; + + bThreadEnded=0; // no more spu is running +} + +//////////////////////////////////////////////////////////////////////// +// SETUPSTREAMS: init most of the spu buffers +//////////////////////////////////////////////////////////////////////// + +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(38400); // alloc mixing buffer + i=NSSIZE*2; + + sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart[0],0,i*4); + sRVBEnd[0] = sRVBStart[0] + i; + sRVBPlay[0] = sRVBStart[0]; + sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart[1],0,i*4); + sRVBEnd[1] = sRVBStart[1] + i; + sRVBPlay[1] = sRVBStart[1]; + + for(i=0;i init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC+(s_chan[i].iStartAdr<<1); + s_chan[i].pStart=spuMemC+(s_chan[i].iStartAdr<<1); + s_chan[i].pCurr=spuMemC+(s_chan[i].iStartAdr<<1); + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVESTREAMS: free most buffer +//////////////////////////////////////////////////////////////////////// + +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer=NULL; + free(sRVBStart[0]); // free reverb buffer + sRVBStart[0]=0; + free(sRVBStart[1]); // free reverb buffer + sRVBStart[1]=0; +} + + +//////////////////////////////////////////////////////////////////////// +// SPUOPEN: called by main emu after init +//////////////////////////////////////////////////////////////////////// +#include +FILE * LogFile; +EXPORT_GCC long CALLBACK SPU2open(void* pWindow) +{ +#ifdef _WIN32 + HWND hW= pWindow == NULL ? NULL : *(HWND*)pWindow; +#else + Display* dsp = *(Display**)pWindow; +#endif + + if(bSPUIsOpen) return 0; // security for some stupid main emus + LogFile = fopen("logs/spu2.txt","wb"); + iVolume=3; + bEndThread=0; + bThreadEnded=0; + spuMemC=(unsigned char *)spuMem; + memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); + pSpuIrq[0]=spuMemC; + pSpuIrq[1]=spuMemC; + dwNewChannel2[0]=0; + dwNewChannel2[1]=0; + dwEndChannel2[0]=0; + dwEndChannel2[1]=0; + spuCtrl2[0]=0; + spuCtrl2[1]=0; + spuStat2[0]=0; + spuStat2[1]=0; + spuIrq2[0]=0; + spuIrq2[1]=0; + spuAddr2[0]=0x0; + spuAddr2[1]=0x0; + spuRvbAddr2[0]=0; + spuRvbAddr2[1]=0; + spuRvbAEnd2[0]=0; + spuRvbAEnd2[1]=0; + + memset(&Adma4,0,sizeof(ADMA)); + memset(&Adma7,0,sizeof(ADMA)); + + memset(&DirectInputC0,0,sizeof(DINPUT)); + memset(&DirectInputC1,0,sizeof(DINPUT)); + + +#ifdef _WIN32 + LastWrite=0x00000000;LastPlay=0; // init some play vars + + if(!IsWindow(hW)) hW=GetActiveWindow(); + hWMain = hW; // store hwnd + + ReadConfig(); // read user stuff +#endif + + + SetupSound(); // setup midas (before init!) + + SetupStreams(); // prepare streaming + + SetupTimer(); // timer for feeding data + + bSPUIsOpen=1; + +#ifdef _WIN32 + if(iDebugMode) // windows debug dialog + { + hWDebug=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DEBUG), + NULL,(DLGPROC)DebugDlgProc); + SetWindowPos(hWDebug,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWDebug); + SetFocus(hWMain); + } + + if(iRecordMode) // windows recording dialog + { + hWRecord=CreateDialog(hInst,MAKEINTRESOURCE(IDD_RECORD), + NULL,(DLGPROC)RecordDlgProc); + SetWindowPos(hWRecord,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWRecord); + SetFocus(hWMain); + } +#endif + + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +// SPUCLOSE: called before shutdown +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2close(void) +{ + if(!bSPUIsOpen) return; // some security + + bSPUIsOpen=0; // no more open + //fclose(LogFile); +#ifdef _WIN32 + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0; + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0; +#endif + + RemoveTimer(); // no more feeding + + RemoveSound(); // no more sound handling + + RemoveStreams(); // no more streaming +} + +//////////////////////////////////////////////////////////////////////// +// SPUSHUTDOWN: called by main emu on final exit +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2shutdown(void) +{ +#ifdef _WIN32 + if(hIRE!=NULL) {FreeLibrary(hIRE);hIRE=NULL;} +#endif + + return; +} + +//////////////////////////////////////////////////////////////////////// +// SPUTEST: we don't test, we are always fine ;) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK SPU2test(void) +{ + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SPUCONFIGURE: call config dialog +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2configure(void) +{ +#ifdef _WIN32 + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), + GetActiveWindow(),(DLGPROC)DSoundDlgProc); +#else + //StartCfgTool("CFG"); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// SPUABOUT: show about window +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2about(void) +{ +#ifdef _WIN32 + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(),(DLGPROC)AboutDlgProc); +#else + //StartCfgTool("ABOUT"); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *SPU2callback)(int), + void (CALLBACK *DMA4callback)(int), + void (CALLBACK *DMA7callback)(int)) +{ + irqCallbackSPU2 = SPU2callback; + irqCallbackDMA4 = DMA4callback; + irqCallbackDMA7 = DMA7callback; +} + +//////////////////////////////////////////////////////////////////////// +// COMMON PLUGIN INFO FUNCS +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC char * CALLBACK PS2EgetLibName(void) +{ + return libraryName; +} + +#define PS2E_LT_SPU2 0x4 + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType(void) +{ + return PS2E_LT_SPU2; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type) +{ + unsigned char v=version; + + // key hack to fake a lower version: + //if(GetAsyncKeyState(VK_SHIFT)&0x8000) v--; + + // compile hack to set lib version to PCSX2 0.6 standards + //v=2; + + return v<<16|revision<<8|build; +} + +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/spu2/PeopsSPU2/spu.h b/plugins/spu2/PeopsSPU2/spu.h new file mode 100644 index 0000000..48ee32b --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu.h @@ -0,0 +1,33 @@ +/*************************************************************************** + spu.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/04/04 - Pete +// - changed plugin to emulate PS2 spu +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +void SetupTimer(void); +void RemoveTimer(void); +EXPORT_GCC void CALLBACK SPU2playADPCMchannel(xa_decode_t *xap); diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.aps b/plugins/spu2/PeopsSPU2/spu2PeopsSound.aps new file mode 100644 index 0000000000000000000000000000000000000000..506493f19f05ae13374fed073c44cc358a32c15c GIT binary patch literal 51024 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 literal 0 HcmV?d00001 diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.c b/plugins/spu2/PeopsSPU2/spu2PeopsSound.c new file mode 100644 index 0000000..8704dee --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.c @@ -0,0 +1,44 @@ +/*************************************************************************** + spu2PeopsSound.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2004/03/28 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +// spu2PeopsSound.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" + +HINSTANCE hInst=NULL; + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD dwReason, + LPVOID lpReserved + ) +{ + + hInst=(HINSTANCE)hModule; + + return TRUE; +} + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.def b/plugins/spu2/PeopsSPU2/spu2PeopsSound.def new file mode 100644 index 0000000..f577ea5 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.def @@ -0,0 +1,34 @@ +; Declares the module parameters for the DLL. + +LIBRARY "spu2PeopsSound" +DESCRIPTION 'SPU2 PEOPS SOUND' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + SPU2configure @5 + SPU2about @6 + SPU2init @7 + SPU2shutdown @8 + SPU2test @9 + SPU2open @10 + SPU2close @11 + + SPU2write @13 + SPU2read @14 + + SPU2readDMA4Mem @16 + SPU2readDMA7Mem @17 + SPU2writeDMA4Mem @18 + SPU2writeDMA7Mem @19 + SPU2interruptDMA4 @20 + SPU2interruptDMA7 @21 + + SPU2freeze @33 + SPU2async @34 + SPU2irqCallback @36 + + SPU2ReadMemAddr @37 + SPU2WriteMemAddr @38 diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.dev b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dev new file mode 100644 index 0000000..903f2df --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dev @@ -0,0 +1,478 @@ +[Project] +FileName=spu2PeopsSound.dev +Name=spu2PeopsSound +Ver=1 +IsCpp=1 +Type=3 +Compiler=-D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC_@@_ +CppCompiler=-D__GNUWIN32__ -mcpu=pentium -D_M_IX86=500 -W -DWIN32 -DNDEBUG -D_WINDOWS -D_GCC_@@_ +Includes=d:\vs\vc98\MFC\include +Linker=-ldsound -lwinmm -luser32 -lgdi32 -ladvapi32 --add-stdcall-alias_@@_ +Libs= +UnitCount=35 +Folders="Documentation Files","Header Files","Resource Files","Source Files" +ObjFiles= +PrivateResource=spu2PeopsSound_private.rc +ResourceIncludes= +MakeIncludes= +Icon= +ExeOutput=.. +ObjectOutput=Release +OverrideOutput=1 +OverrideOutputName=SPU2PeopsDSound.dll +HostApplication= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000001000000000 + +[Unit1] +FileName=adsr.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=alsa.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=cfg.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=debug.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=dma.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=dsound.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=freeze.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=oss.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=registers.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=reverb.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=spu.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=spu2PeopsSound.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=spu2PeopsSound.def +Folder=Source Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=spu2PeopsSound.rc +Folder=Resource Files +Compile=1 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=StdAfx.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=xa.c +Folder=Source Files +Compile=1 +CompileCpp=0 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=adsr.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=alsa.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=cfg.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=debug.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=dma.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=dsoundoss.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=externals.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=gauss_i.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=psemuxa.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=record.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=registers.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=regs.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=resource.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=reverb.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=spu.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=StdAfx.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=xa.h +Folder=Header Files +Compile=1 +CompileCpp=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=Filemap.txt +Folder=Documentation Files +Compile=0 +CompileCpp=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=License.txt +Folder=Documentation Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=License.txt +Folder=Documentation Files +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=bitmap4.bmp +Folder="Resource Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=bitmap5.bmp +Folder="Resource Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=changelog.txt +Folder="Documentation Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=Filemap.txt +Folder="Documentation Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=License.txt +Folder="Documentation Files" +Compile=0 +CompileCpp=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename=spu2PeopsSound.exe +ProductName=spu2PeopsSound +ProductVersion=0.1 +AutoIncBuildNr=0 + +[Unit36] +FileName=Filemap.txt +Folder=Documentation Files +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=record.c +CompileCpp=0 +Folder=Source Files +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsp b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsp new file mode 100644 index 0000000..d6c71d4 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsp @@ -0,0 +1,282 @@ +# Microsoft Developer Studio Project File - Name="spu2PeopsSound" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=spu2PeopsSound - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "spu2PeopsSound.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "spu2PeopsSound.mak" CFG="spu2PeopsSound - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "spu2PeopsSound - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "spu2PeopsSound - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "spu2PeopsSound - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /G5 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 dsound.lib winmm.lib user32.lib gdi32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=rem copy release\spu2PeopsSound.dll D:\pcsx2\plugins\spu2PeopsDSound.dll +# End Special Build Tool + +!ELSEIF "$(CFG)" == "spu2PeopsSound - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "spu2PeopsSound - Win32 Release" +# Name "spu2PeopsSound - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\adsr.c +# End Source File +# Begin Source File + +SOURCE=.\alsa.c +# End Source File +# Begin Source File + +SOURCE=.\cfg.c +# End Source File +# Begin Source File + +SOURCE=.\debug.c +# End Source File +# Begin Source File + +SOURCE=.\dma.c +# End Source File +# Begin Source File + +SOURCE=.\dsound.c +# End Source File +# Begin Source File + +SOURCE=.\freeze.c +# End Source File +# Begin Source File + +SOURCE=.\oss.c +# End Source File +# Begin Source File + +SOURCE=.\psemu.c +# End Source File +# Begin Source File + +SOURCE=.\record.c +# End Source File +# Begin Source File + +SOURCE=.\registers.c +# End Source File +# Begin Source File + +SOURCE=.\reverb.c +# End Source File +# Begin Source File + +SOURCE=.\spu.c +# End Source File +# Begin Source File + +SOURCE=.\spu2PeopsSound.c +# End Source File +# Begin Source File + +SOURCE=.\spu2PeopsSound.def +# End Source File +# Begin Source File + +SOURCE=.\spu2PeopsSound.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.c +# End Source File +# Begin Source File + +SOURCE=.\xa.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\adsr.h +# End Source File +# Begin Source File + +SOURCE=.\alsa.h +# End Source File +# Begin Source File + +SOURCE=.\cfg.h +# End Source File +# Begin Source File + +SOURCE=.\debug.h +# End Source File +# Begin Source File + +SOURCE=.\dma.h +# End Source File +# Begin Source File + +SOURCE=.\dsoundoss.h +# End Source File +# Begin Source File + +SOURCE=.\externals.h +# End Source File +# Begin Source File + +SOURCE=.\gauss_i.h +# End Source File +# Begin Source File + +SOURCE=.\psemuxa.h +# End Source File +# Begin Source File + +SOURCE=.\record.h +# End Source File +# Begin Source File + +SOURCE=.\registers.h +# End Source File +# Begin Source File + +SOURCE=.\regs.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\reverb.h +# End Source File +# Begin Source File + +SOURCE=.\spu.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\xa.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap2.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap3.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap4.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap5.bmp +# End Source File +# End Group +# Begin Group "Documentation Files" + +# PROP Default_Filter "txt" +# Begin Source File + +SOURCE=.\changelog.txt +# End Source File +# Begin Source File + +SOURCE=.\Filemap.txt +# End Source File +# Begin Source File + +SOURCE=.\License.txt +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsw b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsw new file mode 100644 index 0000000..fe93e6f --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "spu2PeopsSound"=.\spu2PeopsSound.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.layout b/plugins/spu2/PeopsSPU2/spu2PeopsSound.layout new file mode 100644 index 0000000..0b3a784 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.layout @@ -0,0 +1,284 @@ +[Editor_0] +CursorCol=5 +CursorRow=443 +TopLine=431 +LeftChar=1 +Open=1 +Top=0 +[Editor_3] +CursorCol=27 +CursorRow=232 +TopLine=223 +LeftChar=1 +Open=1 +Top=0 +[Editors] +Order=11,9,4,34,2,14,23,29,5,0,3,19,6,7,8,10,12,13 +Focused=14 +[Editor_1] +Open=0 +Top=0 +CursorCol=9 +CursorRow=81 +TopLine=81 +LeftChar=1 +[Editor_2] +Open=1 +Top=0 +CursorCol=1 +CursorRow=312 +TopLine=284 +LeftChar=1 +[Editor_4] +Open=1 +Top=0 +CursorCol=1 +CursorRow=204 +TopLine=186 +LeftChar=1 +[Editor_5] +Open=1 +Top=0 +CursorCol=1 +CursorRow=41 +TopLine=35 +LeftChar=1 +[Editor_6] +Open=1 +Top=0 +CursorCol=27 +CursorRow=90 +TopLine=66 +LeftChar=1 +[Editor_7] +Open=1 +Top=0 +CursorCol=1 +CursorRow=175 +TopLine=151 +LeftChar=1 +[Editor_8] +Open=1 +Top=0 +CursorCol=2 +CursorRow=188 +TopLine=153 +LeftChar=1 +[Editor_9] +Open=1 +Top=0 +CursorCol=6 +CursorRow=989 +TopLine=978 +LeftChar=1 +[Editor_10] +Open=1 +Top=0 +CursorCol=11 +CursorRow=99 +TopLine=88 +LeftChar=1 +[Editor_11] +Open=1 +Top=0 +CursorCol=33 +CursorRow=514 +TopLine=531 +LeftChar=1 +[Editor_12] +Open=1 +Top=0 +CursorCol=15 +CursorRow=36 +TopLine=9 +LeftChar=1 +[Editor_13] +Open=1 +Top=0 +CursorCol=7 +CursorRow=26 +TopLine=1 +LeftChar=1 +[Editor_14] +Open=1 +Top=1 +CursorCol=31 +CursorRow=139 +TopLine=121 +LeftChar=1 +[Editor_15] +Open=0 +Top=0 +CursorCol=7 +CursorRow=251 +TopLine=234 +LeftChar=1 +[Editor_16] +Open=0 +Top=0 +CursorCol=14 +CursorRow=32 +TopLine=154 +LeftChar=1 +[Editor_17] +Open=0 +Top=0 +CursorCol=1 +CursorRow=28 +TopLine=1 +LeftChar=1 +[Editor_18] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_19] +Open=1 +Top=0 +CursorCol=15 +CursorRow=33 +TopLine=8 +LeftChar=1 +[Editor_20] +Open=0 +Top=0 +CursorCol=13 +CursorRow=20 +TopLine=1 +LeftChar=1 +[Editor_21] +Open=0 +Top=0 +CursorCol=1 +CursorRow=29 +TopLine=1 +LeftChar=1 +[Editor_22] +Open=0 +Top=0 +CursorCol=20 +CursorRow=21 +TopLine=1 +LeftChar=1 +[Editor_23] +Open=1 +Top=0 +CursorCol=20 +CursorRow=144 +TopLine=126 +LeftChar=1 +[Editor_24] +Open=0 +Top=0 +CursorCol=3 +CursorRow=344 +TopLine=309 +LeftChar=1 +[Editor_25] +Open=0 +Top=0 +CursorCol=5 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_26] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_27] +Open=0 +Top=0 +CursorCol=1 +CursorRow=57 +TopLine=41 +LeftChar=1 +[Editor_28] +Open=0 +Top=0 +CursorCol=62 +CursorRow=43 +TopLine=8 +LeftChar=1 +[Editor_29] +Open=1 +Top=0 +CursorCol=9 +CursorRow=22 +TopLine=1 +LeftChar=1 +[Editor_30] +Open=0 +Top=0 +CursorCol=1 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_31] +Open=0 +Top=0 +CursorCol=1 +CursorRow=25 +TopLine=1 +LeftChar=1 +[Editor_32] +Open=0 +Top=0 +CursorCol=3 +CursorRow=48 +TopLine=26 +LeftChar=1 +[Editor_33] +Open=0 +Top=0 +CursorCol=16 +CursorRow=29 +TopLine=1 +LeftChar=1 +[Editor_34] +Open=1 +Top=0 +CursorCol=5 +CursorRow=13 +TopLine=1 +LeftChar=1 +[Editor_35] +Open=0 +Top=0 +CursorCol=19 +CursorRow=16 +TopLine=1 +LeftChar=1 +[Editor_36] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_37] +Open=0 +Top=0 +CursorCol=27 +CursorRow=19 +TopLine=1 +LeftChar=1 +[Editor_38] +Open=0 +Top=0 +[Editor_39] +Open=0 +Top=0 +[Editor_40] +Open=0 +Top=0 +[Editor_41] +Open=0 +Top=0 +[Editor_42] +Open=0 +Top=0 diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.opt b/plugins/spu2/PeopsSPU2/spu2PeopsSound.opt new file mode 100644 index 0000000000000000000000000000000000000000..542785eafa1f933aadec54535891a7b4c95a477e GIT binary patch literal 54784 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 J%zo`E@PGV!?63d; literal 0 HcmV?d00001 diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.plg b/plugins/spu2/PeopsSPU2/spu2PeopsSound.plg new file mode 100644 index 0000000..1860a27 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.plg @@ -0,0 +1,81 @@ + + +

+

Build Log

+

+--------------------Configuration: spu2PeopsSound - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3A5.tmp" with contents +[ +/nologo /G5 /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR"Release/" /Fp"Release/spu2PeopsSound.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"C:\Documents and Settings\SAQIB\Desktop\PeopsSpu2_103\src\dma.c" +] +Creating command line "snCl.exe @C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3A5.tmp" +Creating temporary file "C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3A6.tmp" with contents +[ +dsound.lib winmm.lib user32.lib gdi32.lib advapi32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"Release/spu2PeopsSound.pdb" /machine:I386 /def:".\spu2PeopsSound.def" /out:"Release/spu2PeopsSound.dll" /implib:"Release/spu2PeopsSound.lib" +".\Release\adsr.obj" +".\Release\alsa.obj" +".\Release\cfg.obj" +".\Release\debug.obj" +".\Release\dma.obj" +".\Release\dsound.obj" +".\Release\freeze.obj" +".\Release\oss.obj" +".\Release\psemu.obj" +".\Release\record.obj" +".\Release\registers.obj" +".\Release\reverb.obj" +".\Release\spu.obj" +".\Release\spu2PeopsSound.obj" +".\Release\StdAfx.obj" +".\Release\xa.obj" +".\Release\spu2PeopsSound.res" +] +Creating command line "snLink.exe @C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3A6.tmp" +

Output Window

+Compiling... +snCL -- Detected win32 build...passing to cl.exe +dma.c +Linking... +snCL -- Detected win32 build...passing to link.exe + Creating library Release/spu2PeopsSound.lib and object Release/spu2PeopsSound.exp +Creating temporary file "C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3AA.tmp" with contents +[ +/nologo /o"Release/spu2PeopsSound.bsc" +".\Release\adsr.sbr" +".\Release\alsa.sbr" +".\Release\cfg.sbr" +".\Release\debug.sbr" +".\Release\dma.sbr" +".\Release\dsound.sbr" +".\Release\freeze.sbr" +".\Release\oss.sbr" +".\Release\psemu.sbr" +".\Release\record.sbr" +".\Release\registers.sbr" +".\Release\reverb.sbr" +".\Release\spu.sbr" +".\Release\spu2PeopsSound.sbr" +".\Release\StdAfx.sbr" +".\Release\xa.sbr"] +Creating command line "snBsc.exe @C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3AA.tmp" +Creating browse info file... +snCL -- Detected win32 build...passing to bscmake.exe +

Output Window

+Creating temporary file "C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3AB.bat" with contents +[ +@echo off +rem copy release\spu2PeopsSound.dll D:\pcsx2\plugins\spu2PeopsDSound.dll +] +Creating command line "C:\DOCUME~1\SAQIB\LOCALS~1\Temp\RSP3AB.bat" + + + + +

Results

+spu2PeopsSound.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.rc b/plugins/spu2/PeopsSPU2/spu2PeopsSound.rc new file mode 100644 index 0000000..85fbb87 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.rc @@ -0,0 +1,415 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Polish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) +#ifdef _WIN32 +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\spu2PeopsSound.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Polish resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT DIALOGEX 0, 0, 239, 175 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About the P.E.Op.S. SPU2 DSound Audio Driver..." +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,98,155,44,14 + RTEXT "Version :",IDC_STATIC,5,5,74,9 + RTEXT "Release date :",IDC_STATIC,5,16,74,9 + RTEXT "Coded by :",IDC_STATIC,5,27,74,9 + RTEXT "Pete's EMail :",IDC_STATIC,5,40,74,9 + RTEXT "Pete's homepage :",IDC_STATIC,5,51,74,9 + LTEXT "1.03",IDC_STATIC,82,5,154,9 + LTEXT "02.09.2005",IDC_STATIC,81,16,154,9 + LTEXT "Pete Bernert and the P.E.Op.S. team",IDC_STATIC,81,27, + 154,9 + LTEXT "BlackDove@addcom.de",IDC_STATIC,81,40,154,9 + LTEXT "http://www.pbernert.com",IDC_STATIC,81,51,154,9 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,9,107,218,41, + WS_EX_DLGMODALFRAME + RTEXT "Greetings to:",IDC_STATIC,16,116,45,9 + LTEXT "- Kanodin, Elly and zenogais (I wouldn't have started without their sources).\n- Neill Corlett (for his always excellent work)", + IDC_STATIC,65,116,153,27 + RTEXT "P.E.Op.S. homepage :",IDC_STATIC,5,91,74,9 + LTEXT "https://sourceforge.net/projects/peops/",IDC_STATIC,81, + 91,154,9 + RTEXT "linuzappz :",IDC_STATIC,10,63,69,10 + LTEXT "http://www.pcsx.net",IDC_STATIC,81,63,142,10 + RTEXT "kode54 :",IDC_STATIC,10,75,69,10 + LTEXT "http://home.earthlink.net/~kode54/",IDC_STATIC,81,75, + 142,10 +END + +IDD_CFGDLG DIALOGEX 0, 0, 258, 171 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "P.E.Op.S SPU2 Plugin Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + COMBOBOX IDC_VOLUME,55,19,186,62,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_USEREVERB,55,35,186,44,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_INTERPOL,55,51,186,62,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "Enable developer debug mode",IDC_DEBUGMODE,"Button", + BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | WS_TABSTOP,12, + 97,229,10 + CONTROL "Enable sound recording window",IDC_RECORDMODE,"Button", + BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | WS_TABSTOP,12, + 84,229,10 + DEFPUSHBUTTON "OK",IDOK,51,151,45,14 + PUSHBUTTON "Cancel",IDCANCEL,157,151,45,14 + RTEXT "Volume:",IDC_STATIC,23,22,29,10,SS_CENTERIMAGE + GROUPBOX "General settings",IDC_STATIC,7,7,245,63 + GROUPBOX "Misc",IDC_STATIC,7,74,245,70 + RTEXT "Reverb:",IDC_STATIC,23,38,29,10,SS_CENTERIMAGE + RTEXT "Interpolation:",IDC_STATIC,9,54,43,10,SS_CENTERIMAGE + CONTROL "Enable Thread Mode",IDC_TIMER,"Button",BS_AUTOCHECKBOX | + WS_GROUP | WS_TABSTOP,12,111,194,11 + CONTROL "SPU2 Irq",IDC_SPU2IRQ,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,12,124,216,11 +END + +IDD_DEBUG DIALOGEX 0, 0, 398, 314 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "P.E.Op.S. SPU2 sound debug screen" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "Core 0",IDC_CORE1,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,44,2,49,8 + CONTROL "Core 1",IDC_CORE2,"Button",BS_AUTORADIOBUTTON,101,2,49, + 8 + LTEXT "",IDC_SAREA,4,14,150,288,WS_BORDER + CONTROL "",IDC_MUTE1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 14,9,9 + CONTROL "1",IDC_CHAN1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168, + 14,22,9 + CONTROL "",IDC_MUTE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 26,9,9 + CONTROL "2",IDC_CHAN2,"Button",BS_AUTORADIOBUTTON,168,26,22,9 + CONTROL "",IDC_MUTE3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 38,9,9 + CONTROL "3",IDC_CHAN3,"Button",BS_AUTORADIOBUTTON,168,38,22,9 + CONTROL "",IDC_MUTE4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 50,9,9 + CONTROL "4",IDC_CHAN4,"Button",BS_AUTORADIOBUTTON,168,50,22,9 + CONTROL "",IDC_MUTE5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 62,9,9 + CONTROL "5",IDC_CHAN5,"Button",BS_AUTORADIOBUTTON,168,62,22,9 + CONTROL "",IDC_MUTE6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 74,9,9 + CONTROL "6",IDC_CHAN6,"Button",BS_AUTORADIOBUTTON,168,74,22,9 + CONTROL "",IDC_MUTE7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 86,9,9 + CONTROL "7",IDC_CHAN7,"Button",BS_AUTORADIOBUTTON,168,86,22,9 + CONTROL "",IDC_MUTE8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 98,9,9 + CONTROL "8",IDC_CHAN8,"Button",BS_AUTORADIOBUTTON,168,98,22,9 + CONTROL "",IDC_MUTE9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 110,9,9 + CONTROL "9",IDC_CHAN9,"Button",BS_AUTORADIOBUTTON,168,110,22,9 + CONTROL "",IDC_MUTE10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 122,9,9 + CONTROL "10",IDC_CHAN10,"Button",BS_AUTORADIOBUTTON,168,122,22,9 + CONTROL "",IDC_MUTE11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 134,9,9 + CONTROL "11",IDC_CHAN11,"Button",BS_AUTORADIOBUTTON,168,134,22,9 + CONTROL "",IDC_MUTE12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 146,9,9 + CONTROL "12",IDC_CHAN12,"Button",BS_AUTORADIOBUTTON,168,146,22,9 + CONTROL "",IDC_MUTE13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 158,9,9 + CONTROL "13",IDC_CHAN13,"Button",BS_AUTORADIOBUTTON,168,158,22,9 + CONTROL "",IDC_MUTE14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 170,9,9 + CONTROL "14",IDC_CHAN14,"Button",BS_AUTORADIOBUTTON,168,170,22,9 + CONTROL "",IDC_MUTE15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 182,9,9 + CONTROL "15",IDC_CHAN15,"Button",BS_AUTORADIOBUTTON,168,182,22,9 + CONTROL "",IDC_MUTE16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 194,9,9 + CONTROL "16",IDC_CHAN16,"Button",BS_AUTORADIOBUTTON,168,194,22,9 + CONTROL "",IDC_MUTE17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 206,9,9 + CONTROL "17",IDC_CHAN17,"Button",BS_AUTORADIOBUTTON,168,206,22,9 + CONTROL "",IDC_MUTE18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 218,9,9 + CONTROL "18",IDC_CHAN18,"Button",BS_AUTORADIOBUTTON,168,218,22,9 + CONTROL "",IDC_MUTE19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 230,9,9 + CONTROL "19",IDC_CHAN19,"Button",BS_AUTORADIOBUTTON,168,230,22,9 + CONTROL "",IDC_MUTE20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 242,9,9 + CONTROL "20",IDC_CHAN20,"Button",BS_AUTORADIOBUTTON,168,242,22,9 + CONTROL "",IDC_MUTE21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 254,9,9 + CONTROL "21",IDC_CHAN21,"Button",BS_AUTORADIOBUTTON,168,254,22,9 + CONTROL "",IDC_MUTE22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 266,9,9 + CONTROL "22",IDC_CHAN22,"Button",BS_AUTORADIOBUTTON,168,266,22,9 + CONTROL "",IDC_MUTE23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 278,9,9 + CONTROL "23",IDC_CHAN23,"Button",BS_AUTORADIOBUTTON,168,278,22,9 + CONTROL "",IDC_MUTE24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,158, + 290,9,9 + CONTROL "24",IDC_CHAN24,"Button",BS_AUTORADIOBUTTON,168,290,22,9 + LTEXT "Streams",IDC_STATIC,6,2,29,8 + CTEXT "Mute/Select",IDC_STATIC,144,2,55,8 + LTEXT "",IDC_ADSR,208,22,176,55,WS_BORDER + RTEXT "Attack:",IDC_STATIC,221,81,30,9 + RTEXT "Decay:",IDC_STATIC,221,92,30,9 + RTEXT "Sustain:",IDC_STATIC,221,103,30,9 + RTEXT "Release:",IDC_STATIC,221,114,30,9 + LTEXT "---",IDC_SADSR1,254,81,44,9 + LTEXT "---",IDC_SADSR2,254,92,44,9 + LTEXT "---",IDC_SADSR3,254,103,44,9 + LTEXT "---",IDC_SADSR4,254,114,42,9 + RTEXT "Sustain level:",IDC_STATIC,302,81,44,9 + LTEXT "---",IDC_SADSR5,349,81,38,9 + RTEXT "Sustain inc.:",IDC_STATIC,302,92,44,9 + LTEXT "---",IDC_SADSR6,349,92,38,9 + RTEXT "Channel:",IDC_STATIC,204,2,30,8 + GROUPBOX "ADSR channel info",IDC_STATIC,201,11,190,119 + LTEXT "1",IDC_CHANNUM,238,2,33,8 + PUSHBUTTON "M0",IDC_MUTEOFF,157,300,15,10 + PUSHBUTTON "M1",IDC_MUTEON,174,300,15,10 + GROUPBOX "Generic channel info",IDC_STATIC,201,131,190,114 + RTEXT "On:",IDC_STATIC,210,143,41,9 + RTEXT "Stop:",IDC_STATIC,210,154,41,9 + RTEXT "Reverb:",IDC_STATIC,210,187,41,9 + RTEXT "Start pos:",IDC_STATIC,301,143,35,9 + RTEXT "Curr pos:",IDC_STATIC,301,154,35,9 + RTEXT "Loop pos:",IDC_STATIC,301,165,35,9 + RTEXT "Act freq:",IDC_STATIC,300,220,35,9 + RTEXT "Used freq:",IDC_STATIC,300,231,35,9 + RTEXT "Right vol:",IDC_STATIC,300,192,35,9 + RTEXT "Left vol:",IDC_STATIC,300,203,35,9 + RTEXT "Rvb active:",IDC_STATIC,210,198,41,9 + RTEXT "Rvb end:",IDC_STATIC,210,220,41,9 + RTEXT "Rvb cur:",IDC_STATIC,210,231,41,9 + RTEXT "Noise:",IDC_STATIC,210,165,41,9 + RTEXT "FMod:",IDC_STATIC,210,176,41,9 + RTEXT "Rvb start:",IDC_STATIC,210,209,41,9 + RTEXT "Irq addr.:",IDC_STATIC,207,259,35,9 + RTEXT "Curr adsr vol.:",IDC_STATIC,302,103,44,9 + LTEXT "---",IDC_SADSR7,349,103,38,9 + LTEXT "---",IDC_CI1,254,143,39,9 + LTEXT "---",IDC_CI2,254,154,39,9 + LTEXT "---",IDC_CI3,254,165,39,9 + LTEXT "---",IDC_CI4,254,176,39,9 + LTEXT "---",IDC_CI5,254,187,39,9 + LTEXT "---",IDC_CI6,254,198,39,9 + LTEXT "---",IDC_CI7,254,209,39,9 + LTEXT "---",IDC_CI8,254,220,39,9 + LTEXT "---",IDC_CI9,254,231,39,9 + LTEXT "---",IDC_CI10,339,143,46,9 + GROUPBOX "Spu states",IDC_STATIC,202,246,189,61 + LTEXT "---",IDC_CI11,339,154,46,9 + LTEXT "---",IDC_CI12,339,165,46,9 + LTEXT "---",IDC_CI13,339,192,23,9 + LTEXT "---",IDC_CI14,339,203,22,9 + LTEXT "---",IDC_CI15,339,220,46,9 + LTEXT "---",IDC_CI16,339,231,46,9 + LTEXT "---",IDC_STA1,246,259,46,9 + RTEXT "Raw envelope:",IDC_STATIC,296,114,50,9 + LTEXT "---",IDC_SADSR8,349,114,38,9 + RTEXT "Ctrl:",IDC_STATIC,207,270,35,9 + LTEXT "---",IDC_STA2,247,270,46,9 + RTEXT "Stat:",IDC_STATIC,207,281,35,9 + LTEXT "---",IDC_STA3,247,281,46,9 + RTEXT "Spu mem:",IDC_STATIC,207,292,35,9 + LTEXT "---",IDC_STA4,247,292,46,9 + LTEXT "---",IDC_CI17,367,192,18,9 + LTEXT "---",IDC_CI18,367,203,18,9 + RTEXT "Dbg addr:",IDC_STATIC,301,176,35,9 + LTEXT "---",IDC_CI19,339,176,46,9 +END + +IDD_RECORD DIALOGEX 0, 0, 248, 25 +STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "P.E.Op.S. SPU2 sound recording" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + RTEXT "Filename:",IDC_STATIC,3,5,33,9 + EDITTEXT IDC_WAVFILE,41,3,134,12,ES_AUTOHSCROLL + PUSHBUTTON "Start recording",IDC_RECORD,180,3,61,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 236 + TOPMARGIN, 7 + BOTTOMMARGIN, 168 + END + + IDD_CFGDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 251 + TOPMARGIN, 7 + BOTTOMMARGIN, 165 + END + + IDD_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 391 + TOPMARGIN, 7 + BOTTOMMARGIN, 307 + END + + IDD_RECORD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 241 + TOPMARGIN, 7 + BOTTOMMARGIN, 18 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,6,0,0 + PRODUCTVERSION 1,6,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "P.E.Op.S. Sound PS2 SPU Audio driver - coded by Pete Bernert and the P.E.Op.S. team" + VALUE "FileDescription", "spu2PeopsSound" + VALUE "FileVersion", "1, 6, 0, 0" + VALUE "InternalName", "spu2PeopsSound" + VALUE "LegalCopyright", "GPL 2004" + VALUE "LegalTrademarks", "GPL 2004" + VALUE "OriginalFilename", "spu2PeopsSound.DLL" + VALUE "ProductName", "spu2PeopsSound" + VALUE "ProductVersion", "1, 6, 0, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\spu2PeopsSound.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.sln b/plugins/spu2/PeopsSPU2/spu2PeopsSound.sln new file mode 100644 index 0000000..8c8be52 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spu2PeopsSound", "spu2PeopsSound.vcproj", "{F9E64144-301B-48BC-8D35-A2686DBB1982}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound.vcproj b/plugins/spu2/PeopsSPU2/spu2PeopsSound.vcproj new file mode 100644 index 0000000..5643ad1 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound.vcproj @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.sln b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.sln new file mode 100644 index 0000000..0dcb9f7 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spu2PeopsSound", "spu2PeopsSound_2005.vcproj", "{F9E64144-301B-48BC-8D35-A2686DBB1982}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|Win32.ActiveCfg = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|Win32.Build.0 = Debug|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|Win32.ActiveCfg = Release|Win32 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.vcproj b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.vcproj new file mode 100644 index 0000000..9f0e2d9 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005.vcproj @@ -0,0 +1,620 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.sln b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.sln new file mode 100644 index 0000000..222c18f --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spu2PeopsSound", "spu2PeopsSound_2005_x64.vcproj", "{F9E64144-301B-48BC-8D35-A2686DBB1982}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|x64.ActiveCfg = Debug|x64 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Debug|x64.Build.0 = Debug|x64 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|x64.ActiveCfg = Release|x64 + {F9E64144-301B-48BC-8D35-A2686DBB1982}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.vcproj b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.vcproj new file mode 100644 index 0000000..e994074 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_2005_x64.vcproj @@ -0,0 +1,1078 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.h b/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.h new file mode 100644 index 0000000..1571415 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef SPU2PEOPSSOUND_PRIVATE_H +#define SPU2PEOPSSOUND_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "0.1" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "spu2PeopsSound.exe" +#define PRODUCT_NAME "spu2PeopsSound" +#define PRODUCT_VERSION "0.1" + +#endif /*SPU2PEOPSSOUND_PRIVATE_H*/ diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.rc b/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.rc new file mode 100644 index 0000000..d59c33b --- /dev/null +++ b/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.rc @@ -0,0 +1,5 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "spu2PeopsSound.rc" + diff --git a/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.res b/plugins/spu2/PeopsSPU2/spu2PeopsSound_private.res new file mode 100644 index 0000000000000000000000000000000000000000..2542852aa2f4ca5be72aba770dfa14cf1378a7b6 GIT binary patch literal 10492 zcmbtaU2Gl26+U}y2sRK>K%pcg+=M`E@ZWVpfD{6WlaP?V8#^&j5~%-U;@IY1J5Hji zxDvJk1ON2`LMpKDOE$K@MrGWa-+brHnKLtIW_M>436GB(MC`0qT1w?opWd~vW02jA)7SCK;}ZPeCo+v6`P)^0 zz$uTM-p`9v7UAkNe({r#*UD44F5>>v_&tQ*@8h?EzvuA#vYsaKX3a;C@$h=={-<_( z*8R8=v+gglVyXMQ^=^jVJcModfBn)}5q|!%K%|$IkB@CvimYAiu0+0llgQ`(QpQ(_ zTvqFEL^3nuuBPSP%C&lNL4KjX8>LsqWKt$1kN-n5fZw9D$QJzXk#T%?;XjY>qU@J; zoNdNAON>fCt~TPVUxsmqk`m62f}?~o{J;`wiFTn3IeJj4tY^dw%b?m|Uy($`Uiq;! z$wGDK%uEFq>_{Nk+PUH-Xz>T6PHQzY^OSU}zOvdd3hwo(60XdmRGChc8Nq)KtYMA& zaWC&ceX{u}o>e>%1Yu_u!XKA!D4XH9k;K{#QYrjQyLEkVe2(7iUYvw6?2-=T; zX&ekg_zf9Y`CPFRK6)kLqXOEZO$woBihE^IfV)ePYw_KV5^b_}jxtMAWnA6zvI+K- z(8By?Jh8RurTOBDUg<%N!XpRU8d7>T!CyVnCx;PdV;W`m;kqB6KJ`fp&IUpn_+qcD zN%0(lJrnTXdTGVS`LhN0n!z&)EyG#|0{O4Gpp#@+sV#1hya2)!@#5*d? z2x57+gc=Xvyb+O956|XhH?A4;jC%H=63*yPYHGkpz&q4wHuXR{1)ay$!T~v^d@N1t zS%&tO;OoY~vDSwk3Hs3N5zV!Hc28pLJThnOl;h}0*41jjKG^~bS+iC|SqWA?j;lUg zm-Ws7?u_es+Hl%kFZZIw>Z@&Pu{bFw;E8d3PN3d%#ll{cdp=Pv9ph8*)fB86hZSXb z(%Cnc{v9d(hhZyw)$JGuW^1N@cFd#KdAJ1(7Cnd1evHh+RU2C6JGk;%TGc4dQ#`pw zul_CP^p{aHibxqo>@vbQ`pq}C{O@zteDhU}tUx*;vJUgquhGXY)XdC$Pwf-&vgMF% zkblf6YteF_&MDiV~UZaroYR|~aLzt2CXlag> z$JN(E&bBJg5&1KCJ_&d_w7+xIp!m|8#{kW!T=d*Gic77JvX|0;anAItJ!NIYGBZb-J z#*q%qS2*gi=P^H_uXuR=m*ubE|1#j;rC8R(dbiDCtOxB(j#XuN+1I6rQH?!3S*j2E zODM;2Fs=Kis{5aT?sQvHAG0ZHVLQ-cyw?jq4&mI{q|}LeomTEI=H*UW$@bwKN=t3t zp+|Yvuk|y2=4U)xgY30gbF?r+Gx<+qc@Cpk1wP@t!?|F@Xe5_I)8JT)8Z3kVXK*l! z8v|lea~m7skoGFB7FpjHXlddqazB_DH6`$JCSm@@zF>BjV;#Qiew5{0%(52KN1%n- zVjoI3;CxiCErOYo4xt|~b~#5*Y1|*j86%gi$qaJ>SIl!
    Eg4_4#X>#jierdanb zFqgq#hxb8S!UvtGi)GKf@hI=U)=@yv1q z_Ov#_ki}XY48-_SCf@Q}=l|czmvTVviT$rs7@sXh--m25bRP-07$J64;@G=Fekl3q zBF1B`BY8NEljs9=_*@ro5aa6jDlm(2)f!-2ChobGDA(5moN-zGUzH`w)fQmd3BuvI zZc(o50~|5Vm#@k#%2fz3YY4*Ox!RR$Nq{59bG0j1dw_8(2hX)Zxt0dFG}i{@S`%Py zCkTh<;tH@%ZU}J1c)K1@uC)PX9YHueSGRI43vk4Eu5RVJJ;2;S5Dw4Pt6a+i95J4& zSGm>&m^%r=;kibY>&5^_jOQ9vt~&zET?FCqTql$(AK-}bTql(4&Hz)0`=RH0M!8l5 zxHQ)@%5_(ODa30~&-IdWtqgE!u9uW+eSj%oh04Qoom8%y0$iHwq;h>Dz!Wg6rMX^H zu2lgp&Gnjc-5p>G@tWD&^@eiY9N^MiZz$J20j7Y=J8jq7%5_VCOLM)gTpI#R0U2wW z>wV=~9pKVj?`8xu8)!vCO@m!rtG6 zW(eHtu`Df$^MDtDyQ7NRh1`mHODjs)9v$;{J8Vw=Jv@9GC1w(HGS|+;{0VvDa`?=2 za)*Tb7Thz6bEPWoKmxZJnwZ-iudb~<-%tYArI{ibnQgi}%416jEOR-(!|1Twx1pUE zVP_NU+*V89H0y`=z5Ia6w`a8&H!r=`hn2r$HD4Tz4k+iY49+u%kLA_)aH~|V0Y<7!KIgk!euJ!?`YXug zxL4hYOtLRt+gd5+?c7HgGndD0@(J{;fS%oIhs)61nx-kb3c2+j$STNgZDe3^lmA>y zUX10gw72VN*j0+{@@p7dg?xo|v3+Od1*|b#Z11T?plj2!*s1bz_BXB?&DS3DW&$(E zdL!1=9K9enRdtce_HS(U&fPCN9B*^m#mKxz=}Rk3E&Z?gWB%&W&w~&LyxL z(T-f14eChpL{PV;=zIdZA9`&~mqw$9#dU0orW5$i#LDj|Eb_7C@$V(@JHbAv)+Esm zdsf~_`S~c;?0zqTeJgC2b93Oin(CkB>$BJu@$KA+6(hO()aPNloRw1v>~7SHt5B!i z`{FD{RL{8;5zZB6XyXS7jMHo526u)--Az$V`XL^h_`*x_S{ zd;DdT$fKrgmqbY&OAn$P$E3Z%_~FOW7qFjQC!Lw{S5)4WDL9NDL<$3hco5pRsPKkc^CS63;gp)Aa`R|WAvpwT3ttXp|5f;#M+%R zwcB%X{_et9K)wS3pO>Ff`N2&2v|NYsk7ml>(;VxuO!+zG|5m2_yvlnrg0TR zM(QGuq0QW};uDe(cTEb%ERuWAjJ~Ru;&J_qEK6Xyx5V8!<8@=2tHTA@NS_V`b@1}K z=xdN4%9LNDJ{ZoFFH`yB8S*jAL05zSaHjk{m5*e|FUV@m#m6$_^^wWP1G)GA>V&Um z@4-4;b96c}_ie_E!~JJ_`dacWpfT13EPXl}=yX1PF3KS{b^E@|z1@Dc%gTJ4eph~} zoXK&;)=VHu+VptEhlRFGk zmy7UhtzIS-(;+*NCEH>0&+&c^a|mvwxX zhC7+vKt6`=E$~zqB5x0#XFrDD-Le(uJl?9ka1lE6!)u=LxL3bL_)1PLK6gKZ>PSW> zTawS-T)npA%2p_w6vH<$+OWI9-(FpROe6Xu^aZ{TLJx4ipL6ltt--jrCs{?<-;Unv zo}(q-;9+Lw-r%t(Yiup<^!vA6+*=U;@B1Dr)k9`KpTUn}{k$QE-<-=CWY9q6+3$4zvWmsz)+P9fX(0l1S=Lz4#L{@3pq@z3I0APmA2W0) // curr delta positive + { + if(id2id1) + {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} + else + if(id2>(id1<<1)) + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; + else + s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; + } + } + else + if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass + { + s_chan[ch].SB[32]=0; + + s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; + if(s_chan[ch].sinc<=0x8000) + s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); + else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; + } + else // no flags? add bigger val (if possible), calc smaller step, set flag1 + s_chan[ch].SB[29]+=s_chan[ch].SB[28]; +} + +// +// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm +// + +INLINE void InterpolateDown(int ch) +{ + if(s_chan[ch].sinc>=0x20000) // we would skip at least one val? + { + s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight + if(s_chan[ch].sinc>=0x30000) // we would skip even more vals? + s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight + } +} + +//////////////////////////////////////////////////////////////////////// +// helpers for gauss interpolation + +#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) +#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) + +#include "gauss_i.h" + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// START SOUND... called by main thread to setup a new sound on a channel +//////////////////////////////////////////////////////////////////////// + +INLINE void StartSound(int ch) +{ + dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit + dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit + + StartADSR(ch); + StartREVERB(ch); + + s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start + + s_chan[ch].s_1=0; // init mixing vars + s_chan[ch].s_2=0; + s_chan[ch].iSBPos=28; + + s_chan[ch].bNew=0; // init channel flags + s_chan[ch].bStop=0; + s_chan[ch].bOn=1; + + s_chan[ch].SB[29]=0; // init our interpolation helpers + s_chan[ch].SB[30]=0; + + if(iUseInterpolation>=2) // gauss interpolation? + {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding + else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding +} + + +void UpdateMainVolL() // LEFT VOLUME +{ + short vol = regArea[PS2_C0_MVOLL]; + if(vol&0x8000) // sweep? + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + //vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + regArea[PS2_C0_MVOLL]=vol; // store volume +} + +//////////////////////////////////////////////////////////////////////// +// RIGHT VOLUME register write +//////////////////////////////////////////////////////////////////////// + +void UpdateMainVolR() // RIGHT VOLUME +{ + short vol = regArea[PS2_C0_MVOLR]; + if(vol&0x8000) // comments... see above :) + { + short sInc=1; + if(vol&0x2000) sInc=-1; + if(vol&0x1000) vol^=0xffff; + vol=((vol&0x7f)+1)/2; + vol+=vol/(2*sInc); + vol*=128; + } + else + { + if(vol&0x4000) //vol=vol^=0xffff; + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + + regArea[PS2_C0_MVOLR]=vol; +} +//////////////////////////////////////////////////////////////////////// +// MAIN SPU FUNCTION +// here is the main job handler... thread, timer or direct func call +// basically the whole sound processing is done in this fat func! +//////////////////////////////////////////////////////////////////////// + +// 5 ms waiting phase, if buffer is full and no new sound has to get started +// .. can be made smaller (smallest val: 1 ms), but bigger waits give +// better performance + +#define PAUSE_W 5 +#define PAUSE_L 5000 +extern unsigned long MemAddr[2]; +//////////////////////////////////////////////////////////////////////// + +int iSpuAsyncWait=0; +extern int MMIXC0, MMIXC1; + +VOID CALLBACK MAINProc(UINT nTimerId,UINT msg,DWORD dwUser,DWORD dwParam1, DWORD dwParam2) +{ + int s_1,s_2,fa,ns; + int core = 0; + unsigned char * start; + unsigned int nSample; + int d; + int ch,predict_nr,shift_factor,flags,s; + int gpos,bIRQReturn=0; + + while(!bEndThread) // until we are shutting down + { + //--------------------------------------------------// + // ok, at the beginning we are looking if there is + // enuff free place in the dsound/oss buffer to + // fill in new data, or if there is a new channel to start. + // if not, we wait (thread) or return (timer/spuasync) + // until enuff free place is available/a new channel gets + // started + if (aSyncMode==1) // Async supported? and enabled? + { + if (aSyncCounter<=737280) // If we have 10ms in the buffer, don't wait + { + if (aSyncWait<1000) Sleep(aSyncWait); // Wait a little to be more Synced (No more than 1 sec) + else Sleep (1000); + } + + while (aSyncCounter<=368640 && !bEndThread && aSyncMode==1) + Sleep (1); // bEndThread/aSyncMode are needed, to avoid close problems + + aSyncCounter -= 36864; // 1ms more done (48Hz*768cycles/Hz) + } + else + if(dwNewChannel2[0] || dwNewChannel2[1]) // new channel should start immedately? + { // (at least one bit 0 ... MAXCHANNEL is set?) + iSecureStart++; // -> set iSecure + if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) + } + else iSecureStart=0; // 0: no new channel should start + + while(!iSecureStart && !bEndThread && // no new start? no thread end? + (SoundGetBytesBuffered()>TESTSIZE)) // and still enuff data in sound buffer? + { + iSecureStart=0; // reset secure + + if(iUseTimer) // no-thread mode? + { + return; // -> and done this time (timer mode 1 or 2) + } + // win thread mode: + Sleep(PAUSE_W); // sleep for x ms (win) + + if(dwNewChannel2[0] || dwNewChannel2[1]) + iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop + } + //--------------------------------------------------// continue from irq handling in timer mode? + + if(lastch>=0) // will be -1 if no continue is pending + { + ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue + if( s_chan[ch].iSBPos < 28 ) { + goto GOON; // -> directly jump to the continue point + } + } + + //--------------------------------------------------// + //- main channel loop -// + //--------------------------------------------------// + { + for(ch=0;ch take it and calc steps + s_chan[ch].sinc = s_chan[ch].iRawPitch<<4; + if(!s_chan[ch].sinc) s_chan[ch].sinc=1; + if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag + } + + ns=0; + while(ns=0x10000L) + { + if(s_chan[ch].iSBPos==28) // 28 reached? + { + start=s_chan[ch].pCurr; // set up the current pos + + if (s_chan[ch].bOn==0) goto ENDX; // special "stop" sign + + s_chan[ch].iSBPos=0; + + s_1=s_chan[ch].s_1; + s_2=s_chan[ch].s_2; + + predict_nr = (int)*start; + start++; + flags = (int)*start; + start++; + + shift_factor = predict_nr&0xf; + predict_nr >>= 4; + // -------------------------------------- // + + for (nSample=0;nSample<28;nSample+=2,start++) + { + d=(int)*start; + s=((d&0xf)<<12); + if(s&0x8000) s|=0xffff0000; + + fa=(s >> shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1; + s_1=fa; + s=((d & 0xf0) << 8); + + s_chan[ch].SB[nSample]=fa; + + if(s&0x8000) s|=0xffff0000; + fa=(s>>shift_factor); + fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6); + s_2=s_1; + s_1=fa; + + s_chan[ch].SB[nSample+1]=fa; + } + + //////////////////////////////////////////// irq check + + if(spuCtrl2[core]&0x40) // some irq active? + { + if(iDebugMode==1) logprintf("IRQ Active ch %x, C%x\r\n", ch, ch/24); + + if((pSpuIrq[core] >= start-16 && // irq address reached? + pSpuIrq[core] <= start) || + ((flags&1) && // special: irq on looping addr, when stop/loop flag is set + (pSpuIrq[core] >= s_chan[ch].pLoop-16 && + pSpuIrq[core] <= s_chan[ch].pLoop))) + { + s_chan[ch].iIrqDone=1; // -> debug flag + + if(iDebugMode==1) logprintf("Sample End ch %x, C%x\r\n", ch, ch/24); + + regArea[0x7C0] |= 0x4< let's see what is happening if we call our irqs instead ;) + + if(iSPUIRQWait) // -> option: wait after irq for main emu + { + iSpuAsyncWait=1; + bIRQReturn=1; + } + } + } + + //////////////////////////////////////////// flag handler + if(flags & 0x2) s_chan[ch].bIgnoreLoop=1; // LOOP bit + + if(flags&0x4) s_chan[ch].pLoop=start-16; // LOOP/START bit + + if(flags&0x1) // 1: LOOP/END bit + { + dwEndChannel2[core]|=(1<<(ch%24)); + + if((flags&0xF) != 0x3) // Check if no loop is present + { + s_chan[ch].bIgnoreLoop=0; + s_chan[ch].bStop = 1; + logprintf("Stopping\r\n"); + } + else start = s_chan[ch].pLoop; + } + + s_chan[ch].pCurr=start; // store values for next cycle + s_chan[ch].s_1=s_1; + s_chan[ch].s_2=s_2; + + + //////////////////////////////////////////// + + if(bIRQReturn) // special return for "spu irq - wait for cpu action" + { + bIRQReturn=0; + if(iUseTimer!=2) + { + DWORD dwWatchTime=timeGetTime()+2500; + + while(iSpuAsyncWait && !bEndThread && + timeGetTime()32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + } + + if(iUseInterpolation>=2) // gauss/cubic interpolation + { + gpos = s_chan[ch].SB[28]; + gval0 = fa; + gpos = (gpos+1) & 3; + s_chan[ch].SB[28] = gpos; + } + else + if(iUseInterpolation==1) // simple interpolation + { + s_chan[ch].SB[28] = 0; + s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' + s_chan[ch].SB[30] = s_chan[ch].SB[31]; + s_chan[ch].SB[31] = fa; + s_chan[ch].SB[32] = 1; // -> flag: calc new interolation + } + else s_chan[ch].SB[29]=fa; // no interpolation + + s_chan[ch].spos -= 0x10000L; + } + + //////////////////////////////////////////////// + // noise handler... just produces some noise data + // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... + // and sometimes the noise will be used as fmod modulation... pfff + + if(s_chan[ch].bNoise) + { + if((dwNoiseVal<<=1)&0x80000000L) + { + dwNoiseVal^=0x0040001L; + fa=((dwNoiseVal>>2)&0x7fff); + fa=-fa; + } + else fa=(dwNoiseVal>>2)&0x7fff; + + // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val + fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[core]&0x3f00)>>9))+1)); + if(fa>32767L) fa=32767L; + if(fa<-32767L) fa=-32767L; + s_chan[ch].iOldNoise=fa; + + if(iUseInterpolation<2) // no gauss/cubic interpolation? + s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot + } //---------------------------------------- + else // NO NOISE (NORMAL SAMPLE DATA) HERE + {//------------------------------------------// + if(iUseInterpolation==3) // cubic interpolation + { + long xd; + xd = ((s_chan[ch].spos) >> 1)+1; + gpos = s_chan[ch].SB[28]; + + fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; + fa *= (xd - (2<<15)) / 6; + fa >>= 15; + fa += gval(2) - gval(1) - gval(1) + gval0; + fa *= (xd - (1<<15)) >> 1; + fa >>= 15; + fa += gval(1) - gval0; + fa *= xd; + fa >>= 15; + fa = fa + gval0; + } + //------------------------------------------// + else + if(iUseInterpolation==2) // gauss interpolation + { + int vl, vr; + vl = (s_chan[ch].spos >> 6) & ~3; + gpos = s_chan[ch].SB[28]; + vr=(gauss[vl]*gval0)&~2047; + vr+=(gauss[vl+1]*gval(1))&~2047; + vr+=(gauss[vl+2]*gval(2))&~2047; + vr+=(gauss[vl+3]*gval(3))&~2047; + fa = vr>>11; + } + //------------------------------------------// + else + if(iUseInterpolation==1) // simple interpolation + { + if(s_chan[ch].sinc<0x10000L) // -> upsampling? + InterpolateUp(ch); // --> interpolate up + else InterpolateDown(ch); // --> else down + fa=s_chan[ch].SB[29]; + } + //------------------------------------------// + else fa=s_chan[ch].SB[29]; // no interpolation + } + + s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // add adsr + + if(s_chan[ch].bFMod==2) // fmod freq channel + { + int NP=((32768L+s_chan[ch].sval)*s_chan[ch+1].iRawPitch)>>14; + + if(NP>0x3fff) NP=0x3fff; + else if(NP<0x1) NP=0x1; + + NP=(48000L*NP)>>12; // calc frequency ( 48hz ) + + s_chan[ch+1].iActFreq=NP; + s_chan[ch+1].iUsedFreq=NP; + s_chan[ch+1].sinc=(((NP/10)<<16)/48000); // check , was 4800 + if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1; + if(iUseInterpolation==1) // freq change in sipmle interpolation mode + s_chan[ch+1].SB[32]=1; + + } + else + { + ////////////////////////////////////////////// + // ok, left/right sound volume (ps2 volume goes from 0 ... 0x3fff) + + if(s_chan[ch].iMute) s_chan[ch].sval=0; // debug mute + else + { + if(s_chan[ch].bVolumeL) + SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14; + + if(s_chan[ch].bVolumeR) + SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14; + } + + ////////////////////////////////////////////// + // now let us store sound data for reverb + + if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); + } + + //////////////////////////////////////////////// + // ok, go on until 1 ms data of this channel is collected + + ns++; + s_chan[ch].spos += s_chan[ch].sinc; + } +ENDX: ; + } + } + + //---------------------------------------------------// + //- here we have another 1 ms of sound data + //---------------------------------------------------// + /////////////////////////////////////////////////////// + // mix all channels (including reverb) into one buffer + for(ns=0;ns>16; + if((regArea[PS2_C1_MMIX] & 0x80)) SSumL[ns] += (DirectInputC1.Left*(int)regArea[PS2_C1_BVOLL])>>16; + + UpdateMainVolL(); + + d=SSumL[ns]/iVolume; + SSumL[ns]=0; + *pS++=(d<-32767) ? -32767 : ((d>32767) ? 32767 : d); + + SSumR[ns]+=MixREVERBRight(0); + SSumR[ns]+=MixREVERBRight(1); + + if((regArea[PS2_C0_MMIX] & 0x40)) SSumR[ns] += (DirectInputC0.Right*(int)regArea[PS2_C0_BVOLR])>>16; + if((regArea[PS2_C1_MMIX] & 0x40)) SSumR[ns] += (DirectInputC1.Right*(int)regArea[PS2_C1_BVOLR])>>16; + + UpdateMainVolR(); + d=SSumR[ns]/iVolume; + SSumR[ns]=0; + *pS++=(d<-32767) ? -32767 : ((d>32767) ? 32767 : d); + } + InitREVERB(); + + ////////////////////////////////////////////////////// + // feed the sound + // wanna have around 1/60 sec (16.666 ms) updates + + if(iCycle++>16) + { + SoundFeedVoiceData((unsigned char*)pSpuBuffer, + ((unsigned char *)pS)- + ((unsigned char *)pSpuBuffer)); + pS=(short *)pSpuBuffer; + iCycle=0; + } +} + // end of big main loop... + bThreadEnded=1; + return; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +DWORD WINAPI MAINThreadEx(LPVOID lpParameter) +{ + MAINProc(0,0,0,0,0); + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SPU ASYNC... even newer epsxe func +// 1 time every 'cycle' cycles... harhar +//////////////////////////////////////////////////////////////////////// +EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle) +{ + SPUCycles += cycle; + if(interrupt & (1<<2)){ + if(SPUCycles - SPUStartCycle[1] >= SPUTargetCycle[1]){ + interrupt &= ~(1<<2); + irqCallbackDMA7(); + } + + } + + if(interrupt & (1<<1)){ + if(SPUCycles - SPUStartCycle[0] >= SPUTargetCycle[0]){ + interrupt &= ~(1<<1); + irqCallbackDMA4(); + } + } + + if(iSpuAsyncWait) + { + iSpuAsyncWait++; + if(iSpuAsyncWait<=64) return; + iSpuAsyncWait=0; + } + + if(iDebugMode==2) + { + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0;iDebugMode=0; + } + if(iRecordMode==2) + { + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0;iRecordMode=0; + } + + if(iUseTimer==0) // does the emu support SPUAsync, is it in thread mode, and in Thread Sync ON? + { + aSyncMode=1; // Ten, activate main function Sync system flag + + aSyncTimerOld = aSyncTimerNew; // Recalculate, AsyncWait (ms) + aSyncTimerNew = timeGetTime(); + + aSyncWait =(unsigned int)((aSyncTimerNew - aSyncTimerOld)/2); + + aSyncCounter += cycle ; + + return; + } + if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) + { + aSyncMode = 0; + if(!bSpuInit) return; // -> no init, no call + MAINProc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks + } +} + + +//////////////////////////////////////////////////////////////////////// +// INIT/EXIT STUFF +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SPUINIT: this func will be called first by the main emu +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +static HINSTANCE hIRE = NULL; +#endif + +EXPORT_GCC long CALLBACK SPU2init(void) +{ + spuMemC=(unsigned char *)spuMem; // just small setup + memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); + memset(rvb,0,2*sizeof(REVERBInfo)); + + InitADSR(); + + if(hIRE==NULL) hIRE=LoadLibrary("Riched32.dll "); // needed for debug output + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SETUPTIMER: init of certain buffers and threads/timers +//////////////////////////////////////////////////////////////////////// + +void SetupTimer(void) +{ + memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers + memset(SSumL,0,NSSIZE*sizeof(int)); + pS=(short *)pSpuBuffer; // setup soundbuffer pointer + pS1=(short *)pSpuStreamBuffer[0]; // setup soundbuffer pointer + + bEndThread=0; // init thread vars + bSpuInit=1; // flag: we are inited + + bSpuInit=1; // flag: we are inited + +#ifdef _WINDOWS + + if(iUseTimer==0) // windows: use thread + { + //_beginthread(MAINThread,0,NULL); + DWORD dw; + hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); + SetThreadPriority(hMainThread, + //THREAD_PRIORITY_TIME_CRITICAL); + THREAD_PRIORITY_HIGHEST); + } +#endif +} + +//////////////////////////////////////////////////////////////////////// +// REMOVETIMER: kill threads/timers +//////////////////////////////////////////////////////////////////////// + +void RemoveTimer(void) +{ + bEndThread=1; // raise flag to end thread + + if(iUseTimer!=2) // windows thread? + { + while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended + Sleep(5L); + } + + bSpuInit=0; + + bThreadEnded=0; // no more spu is running +} + +//////////////////////////////////////////////////////////////////////// +// SETUPSTREAMS: init most of the spu buffers +//////////////////////////////////////////////////////////////////////// + +void SetupStreams(void) +{ + int i; + + pSpuBuffer=(unsigned char *)malloc(38400); // alloc mixing buffer + i=NSSIZE*2; + + sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart[0],0,i*4); + sRVBEnd[0] = sRVBStart[0] + i; + sRVBPlay[0] = sRVBStart[0]; + sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer + memset(sRVBStart[1],0,i*4); + sRVBEnd[1] = sRVBStart[1] + i; + sRVBPlay[1] = sRVBStart[1]; + + for(i=0;i init sustain + s_chan[i].iMute=0; + s_chan[i].iIrqDone=0; + s_chan[i].pLoop=spuMemC+(s_chan[i].iStartAdr<<1); + s_chan[i].pStart=spuMemC+(s_chan[i].iStartAdr<<1); + s_chan[i].pCurr=spuMemC+(s_chan[i].iStartAdr<<1); + } +} + +//////////////////////////////////////////////////////////////////////// +// REMOVESTREAMS: free most buffer +//////////////////////////////////////////////////////////////////////// + +void RemoveStreams(void) +{ + free(pSpuBuffer); // free mixing buffer + pSpuBuffer=NULL; + free(sRVBStart[0]); // free reverb buffer + sRVBStart[0]=0; + free(sRVBStart[1]); // free reverb buffer + sRVBStart[1]=0; +} + + +//////////////////////////////////////////////////////////////////////// +// SPUOPEN: called by main emu after init +//////////////////////////////////////////////////////////////////////// +#include +FILE * LogFile; +EXPORT_GCC long CALLBACK SPU2open(void* pWindow) +{ +#ifdef _WINDOWS + HWND hW= pWindow == NULL ? NULL : *(HWND*)pWindow; +#endif + + if(bSPUIsOpen) return 0; // security for some stupid main emus + LogFile = fopen("Logs/spu2.txt","wb"); + iVolume=3; + bEndThread=0; + bThreadEnded=0; + spuMemC=(unsigned char *)spuMem; + memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); + pSpuIrq[0]=spuMemC; + pSpuIrq[1]=spuMemC; + dwNewChannel2[0]=0; + dwNewChannel2[1]=0; + dwEndChannel2[0]=0; + dwEndChannel2[1]=0; + spuCtrl2[0]=0; + spuCtrl2[1]=0; + spuStat2[0]=0; + spuStat2[1]=0; + spuIrq2[0]=0; + spuIrq2[1]=0; + spuAddr2[0]=0x0; + spuAddr2[1]=0x0; + spuRvbAddr2[0]=0; + spuRvbAddr2[1]=0; + spuRvbAEnd2[0]=0; + spuRvbAEnd2[1]=0; + + memset(&Adma4,0,sizeof(ADMA)); + memset(&Adma7,0,sizeof(ADMA)); + + memset(&DirectInputC0,0,sizeof(DINPUT)); + memset(&DirectInputC1,0,sizeof(DINPUT)); + + LastWrite=0x00000000;LastPlay=0; // init some play vars + if(!IsWindow(hW)) hW=GetActiveWindow(); + hWMain = hW; // store hwnd + + ReadConfig(); // read user stuff + + SetupSound(); // setup midas (before init!) + + SetupStreams(); // prepare streaming + + SetupTimer(); // timer for feeding data + + bSPUIsOpen=1; + + if(iDebugMode) // windows debug dialog + { + hWDebug=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DEBUG), + NULL,(DLGPROC)DebugDlgProc); + SetWindowPos(hWDebug,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWDebug); + SetFocus(hWMain); + } + + if(iRecordMode) // windows recording dialog + { + hWRecord=CreateDialog(hInst,MAKEINTRESOURCE(IDD_RECORD), + NULL,(DLGPROC)RecordDlgProc); + SetWindowPos(hWRecord,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); + UpdateWindow(hWRecord); + SetFocus(hWMain); + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +// not used yet +#ifndef _WINDOWS +void SPU2setConfigFile(char * pCfg) +{ + pConfigFile=pCfg; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// SPUCLOSE: called before shutdown +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2close(void) +{ + if(!bSPUIsOpen) return; // some security + + bSPUIsOpen=0; // no more open + //fclose(LogFile); +#ifdef _WINDOWS + if(IsWindow(hWDebug)) DestroyWindow(hWDebug); + hWDebug=0; + if(IsWindow(hWRecord)) DestroyWindow(hWRecord); + hWRecord=0; +#endif + + RemoveTimer(); // no more feeding + + RemoveSound(); // no more sound handling + + RemoveStreams(); // no more streaming +} + +//////////////////////////////////////////////////////////////////////// +// SPUSHUTDOWN: called by main emu on final exit +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2shutdown(void) +{ +#ifdef _WINDOWS + if(hIRE!=NULL) {FreeLibrary(hIRE);hIRE=NULL;} +#endif + + return; +} + +//////////////////////////////////////////////////////////////////////// +// SPUTEST: we don't test, we are always fine ;) +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC long CALLBACK SPU2test(void) +{ + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// SPUCONFIGURE: call config dialog +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2configure(void) +{ +#ifdef _WINDOWS + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), + GetActiveWindow(),(DLGPROC)DSoundDlgProc); +#else + StartCfgTool("CFG"); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// SPUABOUT: show about window +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2about(void) +{ +#ifdef _WINDOWS + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(),(DLGPROC)AboutDlgProc); +#else + StartCfgTool("ABOUT"); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// SETUP CALLBACKS +// this functions will be called once, +// passes a callback that should be called on SPU-IRQ/cdda volume change +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *SPU2callback)(int), + void (CALLBACK *DMA4callback)(int), + void (CALLBACK *DMA7callback)(int)) +{ + irqCallbackSPU2 = SPU2callback; + irqCallbackDMA4 = DMA4callback; + irqCallbackDMA7 = DMA7callback; +} + +//////////////////////////////////////////////////////////////////////// +// COMMON PLUGIN INFO FUNCS +//////////////////////////////////////////////////////////////////////// + +EXPORT_GCC char * CALLBACK PS2EgetLibName(void) +{ + return libraryName; +} + +#define PS2E_LT_SPU2 0x4 + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibType(void) +{ + return PS2E_LT_SPU2; +} + +EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type) +{ + unsigned char v=version; + + // key hack to fake a lower version: + //if(GetAsyncKeyState(VK_SHIFT)&0x8000) v--; + + // compile hack to set lib version to PCSX2 0.6 standards + //v=2; + + return v<<16|revision<<8|build; +} + +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/spu2/PeopsSPU2/stdafx.c b/plugins/spu2/PeopsSPU2/stdafx.c new file mode 100644 index 0000000..58a1680 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/stdafx.c @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// spuPeopsSound.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/plugins/spu2/PeopsSPU2/stdafx.h b/plugins/spu2/PeopsSPU2/stdafx.h new file mode 100644 index 0000000..c6c6438 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/stdafx.h @@ -0,0 +1,86 @@ +/*************************************************************************** + StdAfx.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +////////////////////////////////////////////////////////// +// WINDOWS +////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +#ifdef _GCC +#define EXPORT_GCC __declspec (dllexport) +#else +#define EXPORT_GCC +#endif + +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include +#include +#include "mmsystem.h" +#include +#include + +// enable that for auxprintf(); +//#define SMALLDEBUG +//#include +//void auxprintf (LPCTSTR pFormat, ...); + +#define INLINE __inline + +////////////////////////////////////////////////////////// +// LINUX +////////////////////////////////////////////////////////// +#else + +#define EXPORT_GCC + +#include +#include +#include +#include +#include +#include +#include +#ifndef NOTHREADLIB +#include +#endif +#define RRand(range) (random()%range) +#include +#include +#include + +#undef CALLBACK +#define CALLBACK +#define DWORD unsigned long +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) + +#define INLINE inline + +#endif + +#include "psemuxa.h" diff --git a/plugins/spu2/PeopsSPU2/xa.c b/plugins/spu2/PeopsSPU2/xa.c new file mode 100644 index 0000000..fb63ad4 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/xa.c @@ -0,0 +1,363 @@ +/*************************************************************************** + xa.c - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2003/02/18 - kode54 +// - added gaussian interpolation +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#include "stdafx.h" + +#define _IN_XA + +// will be included from spu.c +#ifdef _IN_SPU + +//////////////////////////////////////////////////////////////////////// +// XA GLOBALS +//////////////////////////////////////////////////////////////////////// + +xa_decode_t * xapGlobal=0; + +unsigned long * XAFeed = NULL; +unsigned long * XAPlay = NULL; +unsigned long * XAStart = NULL; +unsigned long * XAEnd = NULL; + +unsigned long XARepeat = 0; +unsigned long XALastVal = 0; + +int iLeftXAVol = 32767; +int iRightXAVol = 32767; + +static int gauss_ptr = 0; +static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +#define gvall0 gauss_window[gauss_ptr] +#define gvall(x) gauss_window[(gauss_ptr+x)&3] +#define gvalr0 gauss_window[4+gauss_ptr] +#define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] + +//////////////////////////////////////////////////////////////////////// +// MIX XA +//////////////////////////////////////////////////////////////////////// + +INLINE void MixXA(void) +{ + int ns; + + for(ns=0;ns>16)&0xffff)) * iRightXAVol)/32767; + } + + if(XAPlay==XAFeed && XARepeat) + { + XARepeat--; + for(;ns>16)&0xffff)) * iRightXAVol)/32767; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// FEED XA +//////////////////////////////////////////////////////////////////////// + +INLINE void FeedXA(xa_decode_t *xap) +{ + int sinc,spos,i,iSize,iPlace,vl,vr; + + if(!bSPUIsOpen) return; + + xapGlobal = xap; // store info for save states + XARepeat = 100; // set up repeat + + iSize=((44100*xap->nsamples)/xap->freq); // get size + if(!iSize) return; // none? bye + + if(XAFeed=10) + { + if(!dwFPS) dwFPS=1; + dw1=1000000/dwFPS; + if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; + else dwL1=dw1; + dw2=(xap->freq*100/xap->nsamples); + if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; + else + { + iLastSize=iSize*dw2/dw1; + if(iLastSize>iPlace) iLastSize=iPlace; + iSize=iLastSize; + } + iFPSCnt=0;dwFPS=0; + } + else + { + if(iLastSize) iSize=iLastSize; + } + } + //----------------------------------------------------// + + spos=0x10000L; + sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size + + if(xap->stereo) + { + unsigned long * pS=(unsigned long *)xap->pcm; + unsigned long l=0; + + if(iXAPitch) + { + long l1,l2;short s; + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + s=(short)LOWORD(l); + l1=s; + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + s=(short)HIWORD(l); + l2=s; + l2=(l2*iPlace)/iSize; + if(l2<-32767) l2=-32767; + if(l2> 32767) l2=32767; + l=(l1&0xffff)|(l2<<16); + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + l = *pS++; + gauss_window[gauss_ptr] = (short)LOWORD(l); + gauss_window[4+gauss_ptr] = (short)HIWORD(l); + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l= (vr >> 11) & 0xffff; + vr=(gauss[vl]*gvalr0)&~2047; + vr+=(gauss[vl+1]*gvalr(1))&~2047; + vr+=(gauss[vl+2]*gvalr(2))&~2047; + vr+=(gauss[vl+3]*gvalr(3))&~2047; + l |= vr << 5; + } + else + { + while(spos>=0x10000L) + { + l = *pS++; + spos -= 0x10000L; + } + } + + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } + else + { + unsigned short * pS=(unsigned short *)xap->pcm; + unsigned long l;short s=0; + + if(iXAPitch) + { + long l1; + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l1=s= vr >> 11; + l1 &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l1=s; + } + + l1=(l1*iPlace)/iSize; + if(l1<-32767) l1=-32767; + if(l1> 32767) l1=32767; + l=(l1&0xffff)|(l1<<16); + *XAFeed++=l; + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + else + { + for(i=0;i=0x10000L) + { + gauss_window[gauss_ptr] = (short)*pS++; + gauss_ptr = (gauss_ptr+1) & 3; + spos -= 0x10000L; + } + vl = (spos >> 6) & ~3; + vr=(gauss[vl]*gvall0)&~2047; + vr+=(gauss[vl+1]*gvall(1))&~2047; + vr+=(gauss[vl+2]*gvall(2))&~2047; + vr+=(gauss[vl+3]*gvall(3))&~2047; + l=s= vr >> 11; + l &= 0xffff; + } + else + { + while(spos>=0x10000L) + { + s = *pS++; + spos -= 0x10000L; + } + l=s; + } + + *XAFeed++=(l|(l<<16)); + + if(XAFeed==XAEnd) XAFeed=XAStart; + if(XAFeed==XAPlay) + { + if(XAPlay!=XAStart) XAFeed=XAPlay-1; + break; + } + + spos += sinc; + } + } + } +} + +#endif + diff --git a/plugins/spu2/PeopsSPU2/xa.h b/plugins/spu2/PeopsSPU2/xa.h new file mode 100644 index 0000000..0430552 --- /dev/null +++ b/plugins/spu2/PeopsSPU2/xa.h @@ -0,0 +1,29 @@ +/*************************************************************************** + xa.h - description + ------------------- + begin : Wed May 15 2002 + copyright : (C) 2002 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2002/05/15 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +INLINE void MixXA(void); +INLINE void FeedXA(xa_decode_t *xap); diff --git a/plugins/spu2/SPU2null/License.txt b/plugins/spu2/SPU2null/License.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/spu2/SPU2null/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/spu2/SPU2null/ReadMe.txt b/plugins/spu2/SPU2null/ReadMe.txt new file mode 100644 index 0000000..0507764 --- /dev/null +++ b/plugins/spu2/SPU2null/ReadMe.txt @@ -0,0 +1,39 @@ +SPU2null v0.4 +------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Usage: +----- + Place the file "SPU2null.dll" (Windows) or "libSPU2null.so" (Linux) + at the Plugins directory of the Emulator to use it. + +Changes: +------- + v0.5 + * added debug logging dialog + about dialog + * linuz did some reg fixes + * Added DEVC++ (4.9.9.2) project files for compiling with mingw32 + v0.4 + * added vsnet2005beta1 project files. 64bit dll should work fine now (not tested!) + * Fixed one more bug in regs stuff + + v0.21 + * more work on regs + + v0.2: + * New functions & regs + + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + + linuzappz + shadow + + diff --git a/plugins/spu2/SPU2null/Src/Changelog.txt b/plugins/spu2/SPU2null/Src/Changelog.txt new file mode 100644 index 0000000..6751a30 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/Changelog.txt @@ -0,0 +1,30 @@ +[ Legend: ] +[ + Added feature ] +[ * Improved/changed feature ] +[ - Bug fixed (we hope) ] +[ ! Attention (Notes) ] + +ChangeLog: + +v0.5 + [+] Added Seperate IRQ Callbacks with AutoDMA check (refraction) + [-] Updated Specs to 0.9 (refraction) + +v0.4 + [+] added vsnet2005beta1 project files. 64bit dll should work fine now (not tested!!) + +v0.2 + +15/06/03 + [*] clear some stuff,made code more readable (shadow) + + +9/06/03 + [+] Added some work on CoRE1_ATTR to get bios work (linuzappz) + +9/06/03 + + [+] Added new SPU2 functions to PS2Edefs.h 0.3.2 version + [+] Added loggin system . IT can be enable in SPU2.H + [*] Update Ps2edefs to 0.3.1 (shadow) + diff --git a/plugins/spu2/SPU2null/Src/Config.cpp b/plugins/spu2/SPU2null/Src/Config.cpp new file mode 100644 index 0000000..46a55c3 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/Config.cpp @@ -0,0 +1,51 @@ +#include + +#include "SPU2.h" + +extern HINSTANCE hInst; +void SaveConfig() +{ + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\spu2null.ini"); + sprintf(szValue,"%u",Conf1->Log); + WritePrivateProfileString("Interface", "Logging",szValue,szIniFile); + +} + +void LoadConfig() { + FILE *fp; + + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\spu2null.ini"); + fp=fopen("inis\\usbnull.ini","rt");//check if usbnull.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.Log = 0;//default value + SaveConfig();//save and return + return ; + } + fclose(fp); + GetPrivateProfileString("Interface", "Logging", NULL, szValue, 20, szIniFile); + Conf1->Log = strtoul(szValue, NULL, 10); + return ; + +} + diff --git a/plugins/spu2/SPU2null/Src/Makefile b/plugins/spu2/SPU2null/Src/Makefile new file mode 100644 index 0000000..ee703e9 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/Makefile @@ -0,0 +1,25 @@ + +CC = gcc + +PLUGIN = libSPU2null.so +CFLAGS+= -fPIC -Wall -O2 -fomit-frame-pointer -D__LINUX__ +OBJS = SPU2.o +DEPS:= $(OBJS:.o=.d) +LIBS = $(shell pkg-config --libs gtk+-2.0) +CFLAGS+= $(shell pkg-config --cflags gtk+-2.0) + +all: plugin +install: all + +plugin: ${OBJS} + rm -f ${PLUGIN} + gcc -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +clean: + rm -f ${OBJS} ${DEPS} + +%.o: %.cpp + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/spu2/SPU2null/Src/Makefile.mingw b/plugins/spu2/SPU2null/Src/Makefile.mingw new file mode 100644 index 0000000..bf3cef4 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/Makefile.mingw @@ -0,0 +1,51 @@ +# +# Makefile for MINGW32 +# + + +all: spu2null + +PLUGIN = SPU2null.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwinmm -lgdi32 -lcomdlg32 #-lintl -lwsock32 +RESOBJ = spu2nullrc.o + +OBJS = SPU2.o Config.o Win32.o + + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I/usr/local/include ${FLAGS} + +spu2null: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} ${LIBS} +# ${CC} -shared -Wl,--kill-at,--output-def,plugin.def ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean spu2null + +clean: + ${RM} ${OBJS} ${DEPS} ${PCSX2} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: SPU2null.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + + \ No newline at end of file diff --git a/plugins/spu2/SPU2null/Src/PS2Edefs.h b/plugins/spu2/SPU2null/Src/PS2Edefs.h new file mode 100644 index 0000000..9b5bcfc --- /dev/null +++ b/plugins/spu2/SPU2null/Src/PS2Edefs.h @@ -0,0 +1,812 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.6.2 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + _WIN32 (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if defined(GSdefs) || defined(PADdefs) || defined(SIOdefs) || \ + defined(SPU2defs) || defined(CDVDdefs) || defined(DEV9defs) || \ + defined(USBdefs) || defined(FWdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 // -=[ OBSOLETE ]=- +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FW 0x40 +#define PS2E_LT_SIO 0x80 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0006 +#define PS2E_PAD_VERSION 0x0002 // -=[ OBSOLETE ]=- +#define PS2E_SPU2_VERSION 0x0005 +#define PS2E_CDVD_VERSION 0x0005 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FW_VERSION 0x0002 +#define PS2E_SIO_VERSION 0x0001 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +// for 64bit compilers +typedef char __keyEvent_Size__[(sizeof(keyEvent) == 8)?1:-1]; + +// plugin types +#define SIO_TYPE_PAD 0x00000001 +#define SIO_TYPE_MTAP 0x00000004 +#define SIO_TYPE_RM 0x00000040 +#define SIO_TYPE_MC 0x00000100 + +typedef int (CALLBACK * SIOchangeSlotCB)(int slot); + +typedef struct { + u8 ctrl:4; // control and mode bits + u8 mode:4; // control and mode bits + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute location on the disc (BCD encoded) + u8 trackS; // current sector location on the disc (BCD encoded) + u8 trackF; // current frame location on the disc (BCD encoded) + u8 pad; // unused + u8 discM; // current minute offset from first track (BCD encoded) + u8 discS; // current sector offset from first track (BCD encoded) + u8 discF; // current frame offset from first track (BCD encoded) +} cdvdSubQ; + +typedef struct { // NOT bcd coded + u32 lsn; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usually 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetDiskType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdTD.type (track types for cds) +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef _WIN32 +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(int field); +void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSgifSoftReset(u32 mask); +void CALLBACK GSreadFIFO(u64 *mem); +void CALLBACK GSreadFIFO2(u64 *mem, int qwc); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSchangeSaveState(int, const char* filename); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSsetBaseMem(void*); +void CALLBACK GSsetGameCRC(int crc, int gameoptions); + +// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done +void CALLBACK GSsetFrameSkip(int frameskip); + +void CALLBACK GSreset(); +void CALLBACK GSwriteCSR(u32 value); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef _WIN32 +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API -=[ OBSOLETE ]=- */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SIO plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SIOdefs + +// basic funcs + +s32 CALLBACK SIOinit(u32 port, u32 slot, SIOchangeSlotCB f); +s32 CALLBACK SIOopen(void *pDsp); +void CALLBACK SIOclose(); +void CALLBACK SIOshutdown(); +u8 CALLBACK SIOstartPoll(u8 value); +u8 CALLBACK SIOpoll(u8 value); +// returns: SIO_TYPE_{PAD,MTAP,RM,MC} +u32 CALLBACK SIOquery(); + +// extended funcs + +void CALLBACK SIOconfigure(); +void CALLBACK SIOabout(); +s32 CALLBACK SIOtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +u32 CALLBACK SPU2ReadMemAddr(int core); +void CALLBACK SPU2WriteMemAddr(int core,u32 value); +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(const char* pTitleFilename); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data) +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetTOC(void* toc); //gets ps2 style toc from disc +s32 CALLBACK CDVDgetDiskType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx +s32 CALLBACK CDVDctrlTrayOpen(); //open disc tray +s32 CALLBACK CDVDctrlTrayClose(); //close disc tray + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); +void CALLBACK CDVDnewDiskCB(void (*callback)()); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif + +/* FW plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FWdefs +// basic funcs + +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +s32 CALLBACK FWinit(); +s32 CALLBACK FWopen(void *pDsp); +void CALLBACK FWclose(); +void CALLBACK FWshutdown(); +u32 CALLBACK FWread32(u32 addr); +void CALLBACK FWwrite32(u32 addr, u32 value); +void CALLBACK FWirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FWfreeze(int mode, freezeData *data); +void CALLBACK FWconfigure(); +void CALLBACK FWabout(); +s32 CALLBACK FWtest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +// NOTE: GSreadFIFOX/GSwriteCSR functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title, int multithread); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(int field); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem, u32 addr); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifSoftReset)(u32 mask); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); +typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSsetBaseMem)(void*); +typedef void (CALLBACK* _GSsetGameCRC)(int, int); +typedef void (CALLBACK* _GSsetFrameSkip)(int frameskip); +typedef void (CALLBACK* _GSreset)(); +typedef void (CALLBACK* _GSwriteCSR)(u32 value); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef _WIN32 +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef void (CALLBACK* _GSmakeSnapshot2)(char *path, int*, int); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SIO +typedef s32 (CALLBACK* _SIOinit)(u32 port, u32 slot, SIOchangeSlotCB f); +typedef s32 (CALLBACK* _SIOopen)(void *pDsp); +typedef void (CALLBACK* _SIOclose)(); +typedef void (CALLBACK* _SIOshutdown)(); +typedef u8 (CALLBACK* _SIOstartPoll)(u8 value); +typedef u8 (CALLBACK* _SIOpoll)(u8 value); +typedef u32 (CALLBACK* _SIOquery)(); + +typedef void (CALLBACK* _SIOconfigure)(); +typedef s32 (CALLBACK* _SIOtest)(); +typedef void (CALLBACK* _SIOabout)(); + +// SPU2 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); +typedef u32 (CALLBACK* _SPU2ReadMemAddr)(int core); +typedef void (CALLBACK* _SPU2WriteMemAddr)(int core,u32 value); +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(const char* pTitleFilename); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDreadSubQ)(u32 lsn, cdvdSubQ* subq); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetTOC)(void* toc); +typedef s32 (CALLBACK* _CDVDgetDiskType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); +typedef s32 (CALLBACK* _CDVDctrlTrayOpen)(); +typedef s32 (CALLBACK* _CDVDctrlTrayClose)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); +typedef void (CALLBACK* _CDVDnewDiskCB)(void (*callback)()); + +// DEV9 +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +// NOTE: The read/write functions CANNOT use XMM/MMX regs +// If you want to use them, need to save and restore current ones +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FW +typedef s32 (CALLBACK* _FWinit)(); +typedef s32 (CALLBACK* _FWopen)(void *pDsp); +typedef void (CALLBACK* _FWclose)(); +typedef void (CALLBACK* _FWshutdown)(); +typedef u32 (CALLBACK* _FWread32)(u32 mem); +typedef void (CALLBACK* _FWwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FWirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FWfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FWconfigure)(); +typedef s32 (CALLBACK* _FWtest)(); +typedef void (CALLBACK* _FWabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSgifSoftReset GSgifSoftReset; +_GSreadFIFO GSreadFIFO; +_GSreadFIFO2 GSreadFIFO2; + +_GSkeyEvent GSkeyEvent; +_GSchangeSaveState GSchangeSaveState; +_GSmakeSnapshot GSmakeSnapshot; +_GSmakeSnapshot2 GSmakeSnapshot2; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSsetBaseMem GSsetBaseMem; +_GSsetGameCRC GSsetGameCRC; +_GSsetFrameSkip GSsetFrameSkip; +_GSreset GSreset; +_GSwriteCSR GSwriteCSR; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef _WIN32 +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SIO[2] +_SIOinit SIOinit[2][9]; +_SIOopen SIOopen[2][9]; +_SIOclose SIOclose[2][9]; +_SIOshutdown SIOshutdown[2][9]; +_SIOstartPoll SIOstartPoll[2][9]; +_SIOpoll SIOpoll[2][9]; +_SIOquery SIOquery[2][9]; + +_SIOconfigure SIOconfigure[2][9]; +_SIOtest SIOtest[2][9]; +_SIOabout SIOabout[2][9]; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2ReadMemAddr SPU2ReadMemAddr; +_SPU2WriteMemAddr SPU2WriteMemAddr; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDreadSubQ CDVDreadSubQ; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetTOC CDVDgetTOC; +_CDVDgetDiskType CDVDgetDiskType; +_CDVDgetTrayStatus CDVDgetTrayStatus; +_CDVDctrlTrayOpen CDVDctrlTrayOpen; +_CDVDctrlTrayClose CDVDctrlTrayClose; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; +_CDVDnewDiskCB CDVDnewDiskCB; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FW +_FWinit FWinit; +_FWopen FWopen; +_FWclose FWclose; +_FWshutdown FWshutdown; +_FWread32 FWread32; +_FWwrite32 FWwrite32; +_FWirqCallback FWirqCallback; + +_FWconfigure FWconfigure; +_FWfreeze FWfreeze; +_FWtest FWtest; +_FWabout FWabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/spu2/SPU2null/Src/PS2Etypes.h b/plugins/spu2/SPU2null/Src/PS2Etypes.h new file mode 100644 index 0000000..34ab5c2 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/PS2Etypes.h @@ -0,0 +1,76 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) +#endif + +#if defined (__linux__) // some distributions are lower case +#define __LINUX__ +#endif + +// Basic types +#if defined(_MSC_VER) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x + +#else + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +#ifdef __LINUX__ +typedef union _LARGE_INTEGER +{ + long long QuadPart; +} LARGE_INTEGER; +#endif + +#if defined(__MINGW32__) +#define PCSX2_ALIGNED16(x) __declspec(align(16)) x +#else +#define PCSX2_ALIGNED16(x) x __attribute((aligned(16))) +#endif + +#ifndef __forceinline +#define __forceinline inline +#endif + +#endif // _MSC_VER + +#if defined(__x86_64__) +typedef u64 uptr; +typedef s64 sptr; +#else +typedef u32 uptr; +typedef s32 sptr; +#endif + +typedef struct { + int size; + s8 *data; +} freezeData; + +/* common defines */ +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/spu2/SPU2null/Src/SPU2.cpp b/plugins/spu2/SPU2null/Src/SPU2.cpp new file mode 100644 index 0000000..8fe4ab0 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2.cpp @@ -0,0 +1,1185 @@ +/* SPU2null + * Copyright (C) 2002-2005 SPU2null Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "SPU2.h" + +#include +#include + +const unsigned char version = PS2E_SPU2_VERSION; +const unsigned char revision = 0; +const unsigned char build = 6; // increase that with each version + +// ADSR constants +#define ATTACK_MS 494L +#define DECAYHALF_MS 286L +#define DECAY_MS 572L +#define SUSTAIN_MS 441L +#define RELEASE_MS 437L + +#ifdef _DEBUG +static char *libraryName = "SPU2null (Debug)"; +#else +static char *libraryName = "SPU2null "; +#endif + +FILE *spu2Log; +Config conf; + +ADMA Adma4; +ADMA Adma7; + +u32 MemAddr[2]; +u32 g_nSpuInit = 0; +unsigned short interrupt = 0; +s8 *spu2regs = NULL; +u16* spu2mem = NULL; +u16* pSpuIrq[2] = {NULL}; +u32 dwEndChannel2[2] = {0}; // keeps track of what channels have ended +unsigned long dwNoiseVal=1; // global noise generator + +int SPUCycles = 0, SPUWorkerCycles = 0; +int SPUStartCycle[2]; +int SPUTargetCycle[2]; + +int ADMAS4Write(); +int ADMAS7Write(); + +void InitADSR(); + +void (*irqCallbackSPU2)(); // func of main emu, called on spu irq +void (*irqCallbackDMA4)()=0; // func of main emu, called on spu irq +void (*irqCallbackDMA7)()=0; // func of main emu, called on spu irq + +const int f[5][2] = { { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } }; + +u32 RateTable[160]; + +// channels and voices +VOICE_PROCESSED voices[SPU_NUMBER_VOICES+1]; // +1 for modulation + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_SPU2; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16)|(revision<<8)|build; +} + +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.Log || spu2Log == NULL) return; + + va_start(list, fmt); + vfprintf(spu2Log, fmt, list); + va_end(list); +} + +s32 CALLBACK SPU2init() { +#ifdef SPU2_LOG + spu2Log = fopen("logs/spu2.txt", "w"); + if (spu2Log) setvbuf(spu2Log, NULL, _IONBF, 0); + SPU2_LOG("Spu2 null version %d,%d\n",revision,build); + SPU2_LOG("SPU2init\n"); +#endif + spu2regs = (s8*)malloc(0x10000); + if (spu2regs == NULL) { + SysMessage("Error allocating Memory\n"); return -1; + } + memset(spu2regs, 0, 0x10000); + + spu2mem = (u16*)malloc(0x200000); // 2Mb + if (spu2mem == NULL) { + SysMessage("Error allocating Memory\n"); return -1; + } + memset(spu2mem, 0, 0x200000); + memset(dwEndChannel2, 0, sizeof(dwEndChannel2)); + + InitADSR(); + + memset(voices, 0, sizeof(voices)); + // last 24 channels have higher mem offset + for(int i = 0; i < 24; ++i) + voices[i+24].memoffset = 0x400; + + // init each channel + for(u32 i = 0; i < ARRAYSIZE(voices); ++i) { + + voices[i].pLoop = voices[i].pStart = voices[i].pCurr = (u8*)spu2mem; + + voices[i].pvoice = (_SPU_VOICE*)((u8*)spu2regs+voices[i].memoffset)+(i%24); + voices[i].ADSRX.SustainLevel = 1024; // -> init sustain + } + + return 0; +} + +s32 CALLBACK SPU2open(void *pDsp) { + LoadConfig(); + SPUCycles = SPUWorkerCycles = 0; + interrupt = 0; + SPUStartCycle[0] = SPUStartCycle[1] = 0; + SPUTargetCycle[0] = SPUTargetCycle[1] = 0; + g_nSpuInit = 1; + return 0; +} + +void CALLBACK SPU2close() { + g_nSpuInit = 0; +} + +void CALLBACK SPU2shutdown() { + free(spu2regs); spu2regs = NULL; + free(spu2mem); spu2mem = NULL; +#ifdef SPU2_LOG + if (spu2Log) fclose(spu2Log); +#endif +} + +// simulate SPU2 for 1ms +void SPU2Worker(); + +#define CYCLES_PER_MS (36864000/1500) + +void CALLBACK SPU2async(u32 cycle) +{ + SPUCycles += cycle; + if(interrupt & (1<<2)){ + if(SPUCycles - SPUStartCycle[1] >= SPUTargetCycle[1]){ + interrupt &= ~(1<<2); + irqCallbackDMA7(); + } + + } + + if(interrupt & (1<<1)){ + if(SPUCycles - SPUStartCycle[0] >= SPUTargetCycle[0]){ + interrupt &= ~(1<<1); + irqCallbackDMA4(); + } + } + + if( g_nSpuInit ) { + + while( SPUCycles-SPUWorkerCycles > 0 && CYCLES_PER_MS < SPUCycles-SPUWorkerCycles ) { + SPU2Worker(); + SPUWorkerCycles += CYCLES_PER_MS; + } + } +} + +void InitADSR() // INIT ADSR +{ + unsigned long r,rs,rd; + int i; + memset(RateTable,0,sizeof(unsigned long)*160); // build the rate table according to Neill's rules (see at bottom of file) + + r=3;rs=1;rd=0; + + for(i=32;i<160;i++) // we start at pos 32 with the real values... everything before is 0 + { + if(r<0x3FFFFFFF) + { + r+=rs; + rd++;if(rd==5) {rd=1;rs*=2;} + } + if(r>0x3FFFFFFF) r=0x3FFFFFFF; + + RateTable[i]=r; + } +} + +int MixADSR(VOICE_PROCESSED* pvoice) // MIX ADSR +{ + if(pvoice->bStop) // should be stopped: + { + if(pvoice->bIgnoreLoop==0){ + pvoice->ADSRX.EnvelopeVol=0; + pvoice->bOn=false; + pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->bStop=true; + pvoice->bIgnoreLoop=false; + return 0; + } + if(pvoice->ADSRX.ReleaseModeExp)// do release + { + switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +0 + 32]; break; + case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +4 + 32]; break; + case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +6 + 32]; break; + case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +8 + 32]; break; + case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +9 + 32]; break; + case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +10+ 32]; break; + case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +11+ 32]; break; + case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x18 +12+ 32]; break; + } + } + else + { + pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.ReleaseRate^0x1F))-0x0C + 32]; + } + + if(pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0; + pvoice->bOn=false; + pvoice->pStart= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pLoop= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->pCurr= (u8*)(spu2mem+pvoice->iStartAddr); + pvoice->bStop=true; + pvoice->bIgnoreLoop=false; + //pvoice->bReverb=0; + //pvoice->bNoise=0; + } + + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + else // not stopped yet? + { + if(pvoice->ADSRX.State==0) // -> attack + { + if(pvoice->ADSRX.AttackModeExp) + { + if(pvoice->ADSRX.EnvelopeVol<0x60000000) + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x10 + 32]; + else + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x18 + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.AttackRate^0x7F)-0x10 + 32]; + } + + if(pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; + pvoice->ADSRX.State=1; + } + + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + //--------------------------------------------------// + if(pvoice->ADSRX.State==1) // -> decay + { + switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+0 + 32]; break; + case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+4 + 32]; break; + case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+6 + 32]; break; + case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+8 + 32]; break; + case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+9 + 32]; break; + case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+10+ 32]; break; + case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+11+ 32]; break; + case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[(4*(pvoice->ADSRX.DecayRate^0x1F))-0x18+12+ 32]; break; + } + + if(pvoice->ADSRX.EnvelopeVol<0) pvoice->ADSRX.EnvelopeVol=0; + if(((pvoice->ADSRX.EnvelopeVol>>27)&0xF) <= pvoice->ADSRX.SustainLevel) + { + pvoice->ADSRX.State=2; + } + + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + //--------------------------------------------------// + if(pvoice->ADSRX.State==2) // -> sustain + { + if(pvoice->ADSRX.SustainIncrease) + { + if(pvoice->ADSRX.SustainModeExp) + { + if(pvoice->ADSRX.EnvelopeVol<0x60000000) + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; + else + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x18 + 32]; + } + else + { + pvoice->ADSRX.EnvelopeVol+=RateTable[(pvoice->ADSRX.SustainRate^0x7F)-0x10 + 32]; + } + + if(pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0x7FFFFFFF; + } + } + else + { + if(pvoice->ADSRX.SustainModeExp) + { + switch((pvoice->ADSRX.EnvelopeVol>>28)&0x7) + { + case 0: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +0 + 32];break; + case 1: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +4 + 32];break; + case 2: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +6 + 32];break; + case 3: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +8 + 32];break; + case 4: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +9 + 32];break; + case 5: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +10+ 32];break; + case 6: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +11+ 32];break; + case 7: pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x1B +12+ 32];break; + } + } + else + { + pvoice->ADSRX.EnvelopeVol-=RateTable[((pvoice->ADSRX.SustainRate^0x7F))-0x0F + 32]; + } + + if(pvoice->ADSRX.EnvelopeVol<0) + { + pvoice->ADSRX.EnvelopeVol=0; + } + } + pvoice->ADSRX.lVolume=pvoice->ADSRX.EnvelopeVol>>21; + return pvoice->ADSRX.lVolume; + } + } + return 0; +} + +// simulate SPU2 for 1ms +void SPU2Worker() +{ + u8* start; + int ch,flags; + + VOICE_PROCESSED* pChannel=voices; + for(ch=0;chbNew) { + pChannel->StartSound(); // start new sound + dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit + } + + if(!pChannel->bOn) + { + // fill buffer with empty data + continue; + } + + if(pChannel->iActFreq!=pChannel->iUsedFreq) // new psx frequency? + pChannel->VoiceChangeFrequency(); + + // loop until 1 ms of data is reached + int ns = 0; + while(nsspos >= 0x10000 ) + { + if(pChannel->iSBPos==28) // 28 reached? + { + start=pChannel->pCurr; // set up the current pos + + // special "stop" sign + if( start == (u8*)-1 ) //!pChannel->bOn + { + pChannel->bOn=false; // -> turn everything off + pChannel->ADSRX.lVolume=0; + pChannel->ADSRX.EnvelopeVol=0; + goto ENDX; // -> and done for this channel + } + + pChannel->iSBPos=0; + + // decode the 16 byte packet + + flags=(int)start[1]; + start += 16; + + // flag handler + if((flags&4) && (!pChannel->bIgnoreLoop)) + pChannel->pLoop=start-16; // loop adress + + if(flags&1) // 1: stop/loop + { + // We play this block out first... + dwEndChannel2[ch/24]|=(1<<(ch%24)); + //if(!(flags&2)) // 1+2: do loop... otherwise: stop + if(flags!=3 || pChannel->pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) + { // and checking if pLoop is set avoids crashes, yeah + start = (u8*)-1; + pChannel->bStop = true; + pChannel->bIgnoreLoop = false; + } + else + { + start = pChannel->pLoop; + } + } + + pChannel->pCurr=start; // store values for next cycle + } + + pChannel->iSBPos++; // get sample data + pChannel->spos -= 0x10000; + } + + MixADSR(pChannel); + + // go to the next packet + ns++; + pChannel->spos += pChannel->sinc; + } +ENDX: + ; + } + + // mix all channels + if( (spu2Ru16(REG_C0_MMIX) & 0xC0) && (spu2Ru16(REG_C0_ADMAS) & 0x1) && !(spu2Ru16(REG_C0_CTRL) & 0x30)) { + for(int ns=0;ns0x0fffff) // wrap at 2Mb + spuaddr=0; // wrap + } + + spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + C0_SPUADDR_SET(spuaddr); + + // got from J.F. and Kanodin... is it needed? + spu2Ru16(REG_C0_SPUSTAT) &=~0x80; // DMA complete + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = size; + interrupt |= (1<<1); +} + +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size) +{ + u32 spuaddr = C1_SPUADDR; + int i; + +#ifdef SPU2_LOG + SPU2_LOG("SPU2 readDMA7Mem size %x, addr: %x\n", size, pMem); +#endif + + for(i=0;i0x0fffff) // wrap at 2Mb + spuaddr=0; // wrap + } + + spuaddr+=19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) + C1_SPUADDR_SET(spuaddr); + + // got from J.F. and Kanodin... is it needed? + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; // DMA complete + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = size; + interrupt |= (1<<2); +} + +// WRITE + +// AutoDMA's are used to transfer to the DIRECT INPUT area of the spu2 memory +// Left and Right channels are always interleaved together in the transfer so +// the AutoDMA's deinterleaves them and transfers them. An interrupt is +// generated when half of the buffer (256 short-words for left and 256 +// short-words for right ) has been transferred. Another interrupt occurs at +// the end of the transfer. +int ADMAS4Write() +{ + u32 spuaddr; + if(interrupt & 0x2) return 0; + if(Adma4.AmountLeft <= 0) return 1; + + spuaddr = C0_SPUADDR; + // SPU2 Deinterleaves the Left and Right Channels + memcpy((short*)(spu2mem + spuaddr + 0x2000),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; + memcpy((short*)(spu2mem + spuaddr + 0x2200),(short*)Adma4.MemAddr,512); + Adma4.MemAddr += 256; + spuaddr = (spuaddr + 256) & 511; + C0_SPUADDR_SET(spuaddr); + + Adma4.AmountLeft-=512; + if(Adma4.AmountLeft == 0) + { + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = 1;//512*48000; + spu2Ru16(REG_C0_SPUSTAT)&=~0x80; + interrupt |= (1<<1); + } + return 0; +} + +int ADMAS7Write() +{ + u32 spuaddr; + if(interrupt & 0x4) return 0; + if(Adma7.AmountLeft <= 0) return 1; + + spuaddr = C1_SPUADDR; + // SPU2 Deinterleaves the Left and Right Channels + memcpy((short*)(spu2mem + spuaddr + 0x2000),(short*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + memcpy((short*)(spu2mem + spuaddr + 0x2200),(short*)Adma7.MemAddr,512); + Adma7.MemAddr += 256; + spuaddr = (spuaddr + 256) & 511; + C1_SPUADDR_SET(spuaddr); + + Adma7.AmountLeft-=512; + if(Adma7.AmountLeft == 0) + { + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = 1;//512*48000; + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + interrupt |= (1<<2); + } + return 0; +} + +void CALLBACK SPU2writeDMA4Mem(u16* pMem, int size) +{ + u32 spuaddr; + +#ifdef SPU2_LOG + SPU2_LOG("SPU2 writeDMA4Mem size %x, addr: %x\n", size, pMem); +#endif + if((spu2Ru16(REG_C0_ADMAS) & 0x1) && (spu2Ru16(REG_C0_CTRL) & 0x30) == 0 && size) + { + //fwrite(pMem,iSize<<1,1,LogFile); + memset(&Adma4,0,sizeof(ADMA)); + C0_SPUADDR_SET(0); + Adma4.MemAddr = pMem; + Adma4.AmountLeft = size; + ADMAS4Write(); + return; + } + + spuaddr = C0_SPUADDR; + memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); + spuaddr += size; + C0_SPUADDR_SET(spuaddr); + + if( (spu2Ru16(REG_C0_CTRL)&0x40) && C0_IRQA == spuaddr){ + spu2Ru16(SPDIF_OUT) |= 0x4; + irqCallbackSPU2(); + } + if(spuaddr>0xFFFFE) + spuaddr = 0x2800; + C0_SPUADDR_SET(spuaddr); + + MemAddr[0] += size<<1; + spu2Ru16(REG_C0_SPUSTAT)&=~0x80; + SPUStartCycle[0] = SPUCycles; + SPUTargetCycle[0] = 1;//iSize; + interrupt |= (1<<1); +} + +void CALLBACK SPU2writeDMA7Mem(u16* pMem, int size) +{ + u32 spuaddr; + +#ifdef SPU2_LOG + SPU2_LOG("SPU2 writeDMA7Mem size %x, addr: %x\n", size, pMem); +#endif + if((spu2Ru16(REG_C1_ADMAS) & 0x1) && (spu2Ru16(REG_C1_CTRL) & 0x30) == 0 && size) + { + //fwrite(pMem,iSize<<1,1,LogFile); + memset(&Adma7,0,sizeof(ADMA)); + C1_SPUADDR_SET(0); + Adma7.MemAddr = pMem; + Adma7.AmountLeft = size; + ADMAS7Write(); + return; + } + + spuaddr = C1_SPUADDR; + memcpy((unsigned char*)(spu2mem + spuaddr),(unsigned char*)pMem,size<<1); + spuaddr += size; + C1_SPUADDR_SET(spuaddr); + + if( (spu2Ru16(REG_C1_CTRL)&0x40) && C1_IRQA == spuaddr){ + spu2Ru16(SPDIF_OUT) |= 0x8; + irqCallbackSPU2(); + } + if(spuaddr>0xFFFFE) + spuaddr = 0x2800; + C1_SPUADDR_SET(spuaddr); + + MemAddr[0] += size<<1; + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + SPUStartCycle[1] = SPUCycles; + SPUTargetCycle[1] = 1;//iSize; + interrupt |= (1<<2); +} + +void CALLBACK SPU2interruptDMA4() +{ +#ifdef SPU2_LOG + SPU2_LOG("SPU2 interruptDMA4\n"); +#endif +// spu2Rs16(REG_C0_CTRL)&= ~0x30; +// spu2Rs16(REG__1B0) = 0; +// spu2Rs16(SPU2_STATX_WRDY_M)|= 0x80; + spu2Rs16(REG_C0_CTRL)&=~0x30; + spu2Ru16(REG_C0_SPUSTAT)|=0x80; +} + +void CALLBACK SPU2interruptDMA7() +{ +#ifdef SPU2_LOG + SPU2_LOG("SPU2 interruptDMA7\n"); +#endif +// spu2Rs16(REG_C1_CTRL)&= ~0x30; +// //spu2Rs16(REG__5B0) = 0; +// spu2Rs16(SPU2_STATX_DREQ)|= 0x80; + spu2Rs16(REG_C1_CTRL)&=~0x30; + spu2Ru16(REG_C1_SPUSTAT)|=0x80; +} + +// turn channels on +void SoundOn(int start,int end,unsigned short val) // SOUND ON PSX COMAND +{ + for(int ch=start;ch>=1) // loop channels + { + if((val&1) && voices[ch].pStart) // mmm... start has to be set before key on !?! + { + voices[ch].bNew=true; + voices[ch].bIgnoreLoop = false; + } + } +} + +// turn channels off +void SoundOff(int start,int end,unsigned short val) // SOUND OFF PSX COMMAND +{ + for(int ch=start;ch>=1) // loop channels + { + if(val&1) // && s_chan[i].bOn) mmm... + voices[ch].bStop=true; + } +} + +void FModOn(int start,int end,unsigned short val) // FMOD ON PSX COMMAND +{ + int ch; + + for(ch=start;ch>=1) // loop channels + { + if(val&1) // -> fmod on/off + { + if(ch>0) { + } + } + else { + // turn fmod off + } + } +} + +void CALLBACK SPU2write(u32 mem, u16 value) +{ + u32 spuaddr; +#ifdef SPU2_LOG + SPU2_LOG("SPU2 write mem %x value %x\n", mem, value); +#endif + + assert( C0_SPUADDR < 0x100000); + assert( C1_SPUADDR < 0x100000); + + spu2Ru16(mem) = value; + u32 r = mem&0xffff; + + // channel info + if((r>=0x0000 && r<0x0180)||(r>=0x0400 && r<0x0580)) // some channel info? + { + int ch=0; + if(r>=0x400) ch=((r-0x400)>>4)+24; + else ch=(r>>4); + + VOICE_PROCESSED* pvoice = &voices[ch]; + + switch(r&0x0f) + { + case 0: + case 2: + pvoice->SetVolume(mem&0x2); + break; + case 4: + { + int NP; + if(value>0x3fff) NP=0x3fff; // get pitch val + else NP=value; + + pvoice->pvoice->pitch = NP; + + NP=(44100L*NP)/4096L; // calc frequency + if(NP<1) NP=1; // some security + pvoice->iActFreq=NP; // store frequency + break; + } + case 6: + { + pvoice->ADSRX.AttackModeExp=(value&0x8000)?1:0; + pvoice->ADSRX.AttackRate = ((value>>8) & 0x007f); + pvoice->ADSRX.DecayRate = (((value>>4) & 0x000f)); + pvoice->ADSRX.SustainLevel = (value & 0x000f); + break; + } + case 8: + pvoice->ADSRX.SustainModeExp = (value&0x8000)?1:0; + pvoice->ADSRX.SustainIncrease= (value&0x4000)?0:1; + pvoice->ADSRX.SustainRate = ((value>>6) & 0x007f); + pvoice->ADSRX.ReleaseModeExp = (value&0x0020)?1:0; + pvoice->ADSRX.ReleaseRate = ((value & 0x001f)); + break; + } + + return; + } + + // more channel info + if((r>=0x01c0 && r<=0x02E0)||(r>=0x05c0 && r<=0x06E0)) + { + int ch=0; + unsigned long rx=r; + if(rx>=0x400) + { + ch=24; + rx-=0x400; + } + + ch+=((rx-0x1c0)/12); + rx-=(ch%24)*12; + VOICE_PROCESSED* pvoice = &voices[ch]; + + switch(rx) + { + case 0x1C0: + pvoice->iStartAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iStartAddr&0xFFFF); + pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); + break; + case 0x1C2: + pvoice->iStartAddr=(pvoice->iStartAddr & 0x3f0000) | (value & 0xFFFF); + pvoice->pStart=(u8*)(spu2mem+pvoice->iStartAddr); + break; + case 0x1C4: + pvoice->iLoopAddr =(((unsigned long)value&0x3f)<<16)|(pvoice->iLoopAddr&0xFFFF); + pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); + pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; + break; + case 0x1C6: + pvoice->iLoopAddr=(pvoice->iLoopAddr& 0x3f0000) | (value & 0xFFFF); + pvoice->pLoop=(u8*)(spu2mem+pvoice->iLoopAddr); + pvoice->bIgnoreLoop=pvoice->iLoopAddr>0; + break; + case 0x1C8: + // unused... check if it gets written as well + pvoice->iNextAddr=(((unsigned long)value&0x3f)<<16)|(pvoice->iNextAddr&0xFFFF); + break; + case 0x1CA: + // unused... check if it gets written as well + pvoice->iNextAddr=(pvoice->iNextAddr & 0x3f0000) | (value & 0xFFFF); + break; + } + + return; + } + + // process non-channel data + switch(mem&0xffff) { + case REG_C0_SPUDATA: + spuaddr = C0_SPUADDR; + spu2mem[spuaddr] = value; + spuaddr++; + if( (spu2Ru16(REG_C0_CTRL)&0x40) && C0_IRQA == spuaddr){ + spu2Ru16(SPDIF_OUT) |= 0x4; + irqCallbackSPU2(); + } + if(spuaddr>0xFFFFE) + spuaddr = 0x2800; + C0_SPUADDR_SET(spuaddr); + spu2Ru16(REG_C0_SPUSTAT)&=~0x80; + spu2Ru16(REG_C0_CTRL)&=~0x30; + break; + case REG_C1_SPUDATA: + spuaddr = C1_SPUADDR; + spu2mem[spuaddr] = value; + spuaddr++; + if( (spu2Ru16(REG_C1_CTRL)&0x40) && C1_IRQA == spuaddr){ + spu2Ru16(SPDIF_OUT) |= 0x8; + irqCallbackSPU2(); + } + if(spuaddr>0xFFFFE) + spuaddr = 0x2800; + C1_SPUADDR_SET(spuaddr); + spu2Ru16(REG_C1_SPUSTAT)&=~0x80; + spu2Ru16(REG_C1_CTRL)&=~0x30; + break; + case REG_C0_IRQA_HI: + case REG_C0_IRQA_LO: + pSpuIrq[0]=spu2mem+(C0_IRQA<<1); + break; + case REG_C1_IRQA_HI: + case REG_C1_IRQA_LO: + pSpuIrq[1]=spu2mem+(C1_IRQA<<1); + break; + + case REG_C0_SPUADDR_HI: + case REG_C1_SPUADDR_HI: + spu2Ru16(mem) = value&0xf; + break; + + case REG_C0_SPUON1: SoundOn(0,16,value); break; + case REG_C0_SPUON2: SoundOn(16,24,value); break; + case REG_C1_SPUON1: SoundOn(24,40,value); break; + case REG_C1_SPUON2: SoundOn(40,48,value); break; + case REG_C0_SPUOFF1: SoundOff(0,16,value); break; + case REG_C0_SPUOFF2: SoundOff(16,24,value); break; + case REG_C1_SPUOFF1: SoundOff(24,40,value); break; + case REG_C1_SPUOFF2: SoundOff(40,48,value); break; + + // According to manual all bits are cleared by writing an arbitary value + case REG_C0_END1: dwEndChannel2[0] = 0; break; + case REG_C0_END2: dwEndChannel2[0] = 0; break; + case REG_C1_END1: dwEndChannel2[1] = 0; break; + case REG_C1_END2: dwEndChannel2[1] = 0; break; + case REG_C0_FMOD1: FModOn(0,16,value); break; + case REG_C0_FMOD2: FModOn(16,24,value); break; + case REG_C1_FMOD1: FModOn(24,40,value); break; + case REG_C1_FMOD2: FModOn(40,48,value); break; + } + + assert( C0_SPUADDR < 0x100000); + assert( C1_SPUADDR < 0x100000); +} + +u16 CALLBACK SPU2read(u32 mem) +{ + u32 spuaddr; + u16 ret; + u32 r = mem&0xffff; + + if((r>=0x0000 && r<=0x0180)||(r>=0x0400 && r<=0x0580)) // some channel info? + { + int ch=0; + if(r>=0x400) ch=((r-0x400)>>4)+24; + else ch=(r>>4); + + VOICE_PROCESSED* pvoice = &voices[ch]; + + switch(r&0x0f) { + case 10: return (unsigned short)(pvoice->ADSRX.EnvelopeVol>>16); + } + } + + if((r>0x01c0 && r<=0x02E0)||(r>0x05c0 && r<=0x06E0)) // some channel info? + { + int ch=0; + unsigned long rx=r; + if(rx>=0x400) + { + ch=24; + rx-=0x400; + } + + ch+=((rx-0x1c0)/12); + rx-=(ch%24)*12; + VOICE_PROCESSED* pvoice = &voices[ch]; + + switch(rx) { + case 0x1C0: return (((pvoice->pStart-(u8*)spu2mem)>>17)&0x3F); + case 0x1C2: return (((pvoice->pStart-(u8*)spu2mem)>>1)&0xFFFF); + case 0x1C4: return (((pvoice->pLoop-(u8*)spu2mem)>>17)&0x3F); + case 0x1C6: return (((pvoice->pLoop-(u8*)spu2mem)>>1)&0xFFFF); + case 0x1C8: return (((pvoice->pCurr-(u8*)spu2mem)>>17)&0x3F); + case 0x1CA: return (((pvoice->pCurr-(u8*)spu2mem)>>1)&0xFFFF); + } + } + + switch(mem&0xffff) { + case REG_C0_SPUDATA: + spuaddr = C0_SPUADDR; + ret =spu2mem[spuaddr]; + spuaddr++; + if(spuaddr>0xfffff) + spuaddr=0; + C0_SPUADDR_SET(spuaddr); + break; + case REG_C1_SPUDATA: + spuaddr = C1_SPUADDR; + ret = spu2mem[spuaddr]; + spuaddr++; + if(spuaddr>0xfffff) + spuaddr=0; + C1_SPUADDR_SET(spuaddr); + break; + + case REG_C0_END1: return (dwEndChannel2[0]&0xffff); + case REG_C0_END2: return (dwEndChannel2[0]>>16); + case REG_C1_END1: return (dwEndChannel2[1]&0xffff); + case REG_C1_END2: return (dwEndChannel2[1]>>16); + + default: + ret = spu2Ru16(mem); + } +#ifdef SPU2_LOG + SPU2_LOG("SPU2 read mem %x: %x\n", mem, ret); +#endif + + return ret; +} + +void CALLBACK SPU2WriteMemAddr(int core, u32 value) +{ + MemAddr[core] = value; +} + +u32 CALLBACK SPU2ReadMemAddr(int core) +{ + return MemAddr[core]; +} + +void CALLBACK SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()) +{ + irqCallbackSPU2 = SPU2callback; + irqCallbackDMA4 = DMA4callback; + irqCallbackDMA7 = DMA7callback; +} + +// VOICE_PROCESSED definitions +SPU_CONTROL_* VOICE_PROCESSED::GetCtrl() +{ + return ((SPU_CONTROL_*)(spu2regs+memoffset+REG_C0_CTRL)); +} + +void VOICE_PROCESSED::SetVolume(int iProcessRight) +{ + u16 vol = iProcessRight ? pvoice->right.word : pvoice->left.word; + + if(vol&0x8000) // sweep not working + { + short sInc=1; // -> sweep up? + if(vol&0x2000) sInc=-1; // -> or down? + if(vol&0x1000) vol^=0xffff; // -> mmm... phase inverted? have to investigate this + vol=((vol&0x7f)+1)/2; // -> sweep: 0..127 -> 0..64 + vol+=vol/(2*sInc); // -> HACK: we don't sweep right now, so we just raise/lower the volume by the half! + vol*=128; + } + else // no sweep: + { + if(vol&0x4000) // -> mmm... phase inverted? have to investigate this + vol=0x3fff-(vol&0x3fff); + } + + vol&=0x3fff; + // set volume + //if( iProcessRight ) right = vol; + //else left = vol; +} + +void VOICE_PROCESSED::StartSound() +{ + ADSRX.lVolume=1; // and init some adsr vars + ADSRX.State=0; + ADSRX.EnvelopeVol=0; + + if(bReverb && GetCtrl()->reverb ) + { + // setup the reverb effects + } + + pCurr=pStart; // set sample start + iSBPos=28; + + bNew=false; // init channel flags + bStop=false; + bOn=true; + spos=0x10000L; +} + +void VOICE_PROCESSED::VoiceChangeFrequency() +{ + iUsedFreq=iActFreq; // -> take it and calc steps + sinc=(u32)pvoice->pitch<<4; + if(!sinc) + sinc=1; +} + +void VOICE_PROCESSED::Stop() +{ +} + +// GUI Routines +s32 CALLBACK SPU2test() { + return 0; +} + +typedef struct { + u8 spu2regs[0x10000]; +} SPU2freezeData; + +s32 CALLBACK SPU2freeze(int mode, freezeData *data){ + SPU2freezeData *spud; + + if (mode == FREEZE_LOAD) { + spud = (SPU2freezeData*)data->data; + memcpy(spu2regs, spud->spu2regs, 0x10000); + } else + if (mode == FREEZE_SAVE) { + spud = (SPU2freezeData*)data->data; + memcpy(spud->spu2regs, spu2regs, 0x10000); + } else + if (mode == FREEZE_SIZE) { + data->size = sizeof(SPU2freezeData); + } + + return 0; +} + +#ifndef _WIN32 + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "SPU2null Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +void CALLBACK SPU2configure() { + SysMessage("Nothing to Configure"); +} + +void CALLBACK SPU2about() { + SysMessage("%s %d.%d", libraryName, version, build); +} + +void LoadConfig() +{ +} + +#endif diff --git a/plugins/spu2/SPU2null/Src/SPU2.h b/plugins/spu2/SPU2null/Src/SPU2.h new file mode 100644 index 0000000..3123491 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2.h @@ -0,0 +1,278 @@ +/* SPU2null + * Copyright (C) 2002-2005 SPU2null Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __SPU2_H__ +#define __SPU2_H__ + +#define _CRT_SECURE_NO_DEPRECATE + +#include +#include + +extern "C" { +#define SPU2defs +#include "PS2Edefs.h" +} + +#ifdef __LINUX__ +#include +#else +#include +#include +#endif + +extern FILE *spu2Log; +#define SPU2_LOG __Log //debug mode + + +typedef struct { + int Log; +} Config; + +extern Config conf; + +void __Log(char *fmt, ...); +void SaveConfig(); +void LoadConfig(); +void SysMessage(char *fmt, ...); + +//////////////////// +// SPU2 Registers // +//////////////////// +#define REG_VP_VOLL 0x0000 +#define REG_VP_VOLR 0x0002 +#define REG_VP_PITCH 0x0004 +#define REG_VP_ADSR1 0x0006 +#define REG_VP_ADSR2 0x0008 +#define REG_VP_ENVX 0x000A +#define REG_VP_VOLXL 0x000C +#define REG_VP_VOLXR 0x000E +#define REG_C0_FMOD1 0x0180 +#define REG_C0_FMOD2 0x0182 +#define REG_C1_FMOD1 0x0580 +#define REG_C1_FMOD2 0x0582 +#define REG_S_NON 0x0184 +#define REG_S_VMIXL 0x0188 +#define REG_S_VMIXEL 0x018C +#define REG_S_VMIXR 0x0190 +#define REG_S_VMIXER 0x0194 +#define REG_C0_MMIX 0x0198 +#define REG_C1_MMIX 0x0598 +#define REG_C0_CTRL 0x019A +#define REG_C0_IRQA_HI 0x019C +#define REG_C0_IRQA_LO 0x019D +#define REG_C1_IRQA_HI 0x059C +#define REG_C1_IRQA_LO 0x059D +#define REG_C0_SPUON1 0x1A0 +#define REG_C0_SPUON2 0x1A2 +#define REG_C1_SPUON1 0x5A0 +#define REG_C1_SPUON2 0x5A2 +#define REG_C0_SPUOFF1 0x1A4 +#define REG_C0_SPUOFF2 0x1A6 +#define REG_C1_SPUOFF1 0x5A4 +#define REG_C1_SPUOFF2 0x5A6 +#define REG_C0_SPUADDR_HI 0x01A8 +#define REG_C0_SPUADDR_LO 0x01AA +#define REG_C1_SPUADDR_HI 0x05A8 +#define REG_C1_SPUADDR_LO 0x05AA +#define REG_C0_SPUDATA 0x01AC +#define REG_C1_SPUDATA 0x05AC +#define REG_C0_DMACTRL 0x01AE +#define REG_C1_DMACTRL 0x05AE +#define REG_C0_ADMAS 0x01B0 +#define REG_VA_SSA 0x01C0 +#define REG_VA_LSAX 0x01C4 +#define REG_VA_NAX 0x01C8 +#define REG_A_ESA 0x02E0 +#define REG_A_EEA 0x033C +#define REG_C0_END1 0x0340 +#define REG_C0_END2 0x0342 +#define REG_C1_END1 0x0740 +#define REG_C1_END2 0x0742 +#define REG_C0_SPUSTAT 0x0344 //not sure! +#define REG_C1_CTRL 0x059A +#define REG_C1_ADMAS 0x05B0 +#define REG_C1_SPUSTAT 0x0744 //not sure! +#define REG_P_MVOLL 0x0760 +#define REG_P_MVOLR 0x0762 +#define REG_P_EVOLL 0x0764 +#define REG_P_EVOLR 0x0766 +#define REG_P_AVOLL 0x0768 +#define REG_P_AVOLR 0x076A +#define REG_P_BVOLL 0x076C +#define REG_P_BVOLR 0x076E +#define REG_P_MVOLXL 0x0770 +#define REG_P_MVOLXR 0x0772 +#define SPDIF_OUT 0x07C0 +#define IRQINFO 0x07C2 +#define SPDIF_MODE 0x07C6 +#define SPDIF_MEDIA 0x07C8 + +#define spu2Rs16(mem) (*(s16*)&spu2regs[(mem) & 0xffff]) +#define spu2Ru16(mem) (*(u16*)&spu2regs[(mem) & 0xffff]) +//#define spu2Rs32(mem) (*(s32*)&spu2regs[(mem) & 0xffff]) +//#define spu2Ru32(mem) (*(u32*)&spu2regs[(mem) & 0xffff]) + +#define SPU2_GET32BIT(lo,hi) (((u32)(spu2Ru16(hi)&0x3f)<<16)|(u32)spu2Ru16(lo)) +#define SPU2_SET32BIT(value, lo, hi) { \ + spu2Ru16(hi) = ((value)>>16)&0x3f; \ + spu2Ru16(lo) = (value)&0xffff; \ + } \ + +#define C0_IRQA SPU2_GET32BIT(REG_C0_IRQA_LO, REG_C0_IRQA_HI) +#define C1_IRQA SPU2_GET32BIT(REG_C1_IRQA_LO, REG_C1_IRQA_HI) + +#define C0_SPUADDR SPU2_GET32BIT(REG_C0_SPUADDR_LO, REG_C0_SPUADDR_HI) +#define C1_SPUADDR SPU2_GET32BIT(REG_C1_SPUADDR_LO, REG_C1_SPUADDR_HI) + +#define C0_SPUADDR_SET(value) SPU2_SET32BIT(value, REG_C0_IRQA_LO, REG_C0_IRQA_HI) +#define C1_SPUADDR_SET(value) SPU2_SET32BIT(value, REG_C1_IRQA_LO, REG_C1_IRQA_HI) + +#define SPU_NUMBER_VOICES 48 + +struct SPU_CONTROL_ +{ + u16 spuon : 1; + u16 spuUnmute : 1; + u16 noiseFreq : 6; + u16 reverb : 1; + u16 irq : 1; + u16 dma : 2; // 1 - no dma, 2 - write, 3 - read + u16 extr : 1; // external reverb + u16 cdreverb : 1; + u16 extAudio : 1; + u16 extCd : 1; +}; + +// the layout of each voice in wSpuRegs +struct _SPU_VOICE +{ + union + { + struct { + u16 Vol : 14; + u16 Inverted : 1; + u16 Sweep0 : 1; + } vol; + struct { + u16 Vol : 7; + u16 res1 : 5; + u16 Inverted : 1; + u16 Decrease : 1; // if 0, increase + u16 ExpSlope : 1; // if 0, linear slope + u16 Sweep1 : 1; // always one + } sweep; + u16 word; + } left, right; + + u16 pitch : 14; // 1000 - no pitch, 2000 - pitch + 1, etc + u16 res0 : 2; + + u16 SustainLvl : 4; + u16 DecayRate : 4; + u16 AttackRate : 7; + u16 AttackExp : 1; // if 0, linear + + u16 ReleaseRate : 5; + u16 ReleaseExp : 1; // if 0, linear + u16 SustainRate : 7; + u16 res1 : 1; + u16 SustainDec : 1; // if 0, inc + u16 SustainExp : 1; // if 0, linear + + u16 AdsrVol; + u16 Address; // add / 8 + u16 RepeatAddr; // gets reset when sample starts +}; + +// ADSR INFOS PER CHANNEL +struct ADSRInfoEx +{ + int State; + int AttackModeExp; + int AttackRate; + int DecayRate; + int SustainLevel; + int SustainModeExp; + int SustainIncrease; + int SustainRate; + int ReleaseModeExp; + int ReleaseRate; + int EnvelopeVol; + long lVolume; +}; + +#define NSSIZE 48 // ~ 1 ms of data +#define NSFRAMES 16 // gather at least NSFRAMES of NSSIZE before submitting +#define NSPACKETS 4 +#define SPU_VOICE_STATE_SIZE (sizeof(VOICE_PROCESSED)-4*sizeof(void*)) + +struct VOICE_PROCESSED +{ + VOICE_PROCESSED() + { + memset(this, 0, sizeof(VOICE_PROCESSED)); + } + ~VOICE_PROCESSED() + { + } + + void SetVolume(int right); + void StartSound(); + void VoiceChangeFrequency(); + void FModChangeFrequency(int ns); + void Stop(); + + SPU_CONTROL_* GetCtrl(); + + // start save state + + int iSBPos; // mixing stuff + int spos; + int sinc; + + int iActFreq; // current psx pitch + int iUsedFreq; // current pc pitch + + int iStartAddr, iLoopAddr, iNextAddr; + + ADSRInfoEx ADSRX; // next ADSR settings (will be moved to active on sample start) + bool bIgnoreLoop, bNew, bNoise, bReverb, bOn, bStop, bVolChanged; + int memoffset; // if first core, 0, if second, 0x400 + + // end save state + + /////////////////// + // Sound Buffers // + /////////////////// + u8* pStart; // start and end addresses + u8* pLoop, *pCurr; + + _SPU_VOICE* pvoice; +}; + +struct ADMA +{ + unsigned short * MemAddr; + long IntPointer; + int Index; + int AmountLeft; + int Enabled; +}; + +#endif /* __SPU2_H__ */ diff --git a/plugins/spu2/SPU2null/Src/SPU2null.def b/plugins/spu2/SPU2null/Src/SPU2null.def new file mode 100644 index 0000000..dd0b459 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2null.def @@ -0,0 +1,31 @@ +; SPU2null.def : Declares the module parameters for the DLL. + +LIBRARY "SPU2null" +DESCRIPTION 'SPU2 Null Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + SPU2init @5 + SPU2shutdown @6 + SPU2open @7 + SPU2close @8 + SPU2write @9 + SPU2read @10 + SPU2readDMA4Mem @11 + SPU2writeDMA4Mem @12 + SPU2readDMA7Mem @13 + SPU2writeDMA7Mem @14 + SPU2async @15 + SPU2interruptDMA4 @16 + SPU2interruptDMA7 @17 + SPU2freeze @18 + SPU2configure @21 + SPU2test @22 + SPU2about @23 + + SPU2ReadMemAddr @24 + SPU2WriteMemAddr @25 + SPU2irqCallback @26 \ No newline at end of file diff --git a/plugins/spu2/SPU2null/Src/SPU2null.ncb b/plugins/spu2/SPU2null/Src/SPU2null.ncb new file mode 100644 index 0000000000000000000000000000000000000000..2c44923ce3d747857754c491187073771c1a1445 GIT binary patch literal 109568 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�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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/SPU2null/Src/SPU2null_2005.sln b/plugins/spu2/SPU2null/Src/SPU2null_2005.sln new file mode 100644 index 0000000..15d0cf7 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2null_2005.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2null", "SPU2null_2005.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|Win32.Build.0 = Debug|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.ActiveCfg = Release|Win32 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/spu2/SPU2null/Src/SPU2null_2005.vcproj b/plugins/spu2/SPU2null/Src/SPU2null_2005.vcproj new file mode 100644 index 0000000..046ad0a --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2null_2005.vcproj @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.sln b/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.sln new file mode 100644 index 0000000..0894e28 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPU2null", "SPU2null_2005_x64.vcproj", "{7F059854-568D-4E08-9D00-1E78E203E4DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|x64.ActiveCfg = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Debug|x64.Build.0 = Debug|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|x64.ActiveCfg = Release|x64 + {7F059854-568D-4E08-9D00-1E78E203E4DC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.vcproj b/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.vcproj new file mode 100644 index 0000000..d5c92f1 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/SPU2null_2005_x64.vcproj @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/spu2/SPU2null/Src/Win32.cpp b/plugins/spu2/SPU2null/Src/Win32.cpp new file mode 100644 index 0000000..95f36c4 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/Win32.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "SPU2.h" +#include "resource.h" + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "SPU2NULL Msg", 0); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + if (conf.Log) CheckDlgButton(hW, IDC_LOGGING, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOGGING)) + conf.Log = 1; + else conf.Log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK SPU2configure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK SPU2about() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/spu2/SPU2null/Src/mingw/Makefile.win b/plugins/spu2/SPU2null/Src/mingw/Makefile.win new file mode 100644 index 0000000..0b88810 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/mingw/Makefile.win @@ -0,0 +1,43 @@ +# Project: SPU2null +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//SPU2null_private.res +OBJ = Obj//Win32.o Obj//Config.o Obj//SPU2.o $(RES) +LINKOBJ = Obj//Win32.o Obj//Config.o Obj//SPU2.o $(RES) +LIBS = -L"C:/Develop/Dev-Cpp/lib" --def plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +INCS = -I"C:/Develop/Dev-Cpp/include" +CXXINCS = -I"C:/Develop/Dev-Cpp/include" +BIN = SPU2null.dll +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32___ +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before SPU2null.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=libSPU2null.def +STATICLIB=libSPU2null.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +Obj//Win32.o: ../Win32.c + $(CC) -c ../Win32.c -o Obj//Win32.o $(CFLAGS) + +Obj//Config.o: ../Config.c + $(CC) -c ../Config.c -o Obj//Config.o $(CFLAGS) + +Obj//SPU2.o: ../SPU2.c + $(CC) -c ../SPU2.c -o Obj//SPU2.o $(CFLAGS) + +Obj//SPU2null_private.res: SPU2null_private.rc ../SPU2null.rc + $(WINDRES) -i SPU2null_private.rc --input-format=rc -o Obj//SPU2null_private.res -O coff --include-dir ../mingw --include-dir ../ diff --git a/plugins/spu2/SPU2null/Src/mingw/SPU2null.dev b/plugins/spu2/SPU2null/Src/mingw/SPU2null.dev new file mode 100644 index 0000000..2a811e6 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/mingw/SPU2null.dev @@ -0,0 +1,148 @@ +[Project] +FileName=SPU2null.dev +Name=SPU2null +UnitCount=10 +Type=3 +Ver=1 +ObjFiles= +Includes= +Libs= +PrivateResource=SPU2null_private.rc +ResourceIncludes=..\mingw;../ +MakeIncludes= +Compiler=-Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32____@@_ +CppCompiler= +Linker=--def ../plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32_@@_ +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=SPU2null.dll +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=afxres.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\Win32.c +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\Config.c +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\PS2Edefs.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\PS2Etypes.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\regs.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\resource.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\SPU2.c +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\SPU2.h +CompileCpp=0 +Folder=SPU2null +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=..\SPU2null.rc +Folder=SPU2null +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/plugins/spu2/SPU2null/Src/mingw/afxres.h b/plugins/spu2/SPU2null/Src/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/spu2/SPU2null/Src/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/spu2/SPU2null/Src/mingw/plugin.def b/plugins/spu2/SPU2null/Src/mingw/plugin.def new file mode 100644 index 0000000..4bf4605 --- /dev/null +++ b/plugins/spu2/SPU2null/Src/mingw/plugin.def @@ -0,0 +1,22 @@ +EXPORTS + PS2EgetLibName = PS2EgetLibName@0 @2 + PS2EgetLibType = PS2EgetLibType@0 @3 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @4 + SPU2about = SPU2about@0 @5 + SPU2async = SPU2async@4 @6 + SPU2close = SPU2close@0 @7 + SPU2configure = SPU2configure@0 @8 + SPU2freeze = SPU2freeze@8 @9 + SPU2init = SPU2init@0 @10 + SPU2interruptDMA4 = SPU2interruptDMA4@0 @11 + SPU2interruptDMA7 = SPU2interruptDMA7@0 @12 + SPU2irqCallback = SPU2irqCallback@4 @13 + SPU2open = SPU2open@4 @14 + SPU2read = SPU2read@4 @15 + SPU2readDMA4Mem = SPU2readDMA4Mem@8 @16 + SPU2readDMA7Mem = SPU2readDMA7Mem@8 @17 + SPU2shutdown = SPU2shutdown@0 @18 + SPU2test = SPU2test@0 @19 + SPU2write = SPU2write@8 @20 + SPU2writeDMA4Mem = SPU2writeDMA4Mem@8 @21 + SPU2writeDMA7Mem = SPU2writeDMA7Mem@8 @22 diff --git a/plugins/spu2/SPU2null/Src/resource.h b/plugins/spu2/SPU2null/Src/resource.h new file mode 100644 index 0000000..150ca1f --- /dev/null +++ b/plugins/spu2/SPU2null/Src/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by SPU2null.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_CHECK1 1007 +#define IDC_LOGGING 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/spu2/SPU2null/build.sh b/plugins/spu2/SPU2null/build.sh new file mode 100644 index 0000000..5360bcd --- /dev/null +++ b/plugins/spu2/SPU2null/build.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +curdir=`pwd` + +echo ----------------- +echo Building SPU2null +echo ----------------- + +cd ${curdir}/Src +make $@ + +cp libSPU2null.so ${PCSX2PLUGINS} diff --git a/plugins/spu2/build.sh b/plugins/spu2/build.sh new file mode 100644 index 0000000..62de434 --- /dev/null +++ b/plugins/spu2/build.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +curdir=`pwd` + +echo ------------------------ +echo Building SPU2 plugins... +echo ------------------------ + +cd ${curdir}/PeopsSPU2 +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +cd ${curdir}/SPU2null +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi \ No newline at end of file diff --git a/plugins/usb/USBlinuz/License.txt b/plugins/usb/USBlinuz/License.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/usb/USBlinuz/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/usb/USBlinuz/Linux/Config.c b/plugins/usb/USBlinuz/Linux/Config.c new file mode 100644 index 0000000..b94952f --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/Config.c @@ -0,0 +1,51 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "USB.h" + +void LoadConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/USBlinuz.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + return; + } + fclose(f); +} + +void SaveConfig() { + FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/USBlinuz.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fclose(f); +} + diff --git a/plugins/usb/USBlinuz/Linux/Config.h b/plugins/usb/USBlinuz/Linux/Config.h new file mode 100644 index 0000000..9eb3647 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/Config.h @@ -0,0 +1,20 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void SaveConf(); +void LoadConf(); diff --git a/plugins/usb/USBlinuz/Linux/Linux.c b/plugins/usb/USBlinuz/Linux/Linux.c new file mode 100644 index 0000000..3c8388e --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/Linux.c @@ -0,0 +1,75 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "USB.h" + +int ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgUSBlinuz"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + strcpy(cfg, "./cfg/cfgUSBlinuz"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + sprintf(cfg, "%s/cfgUSBlinuz", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + printf("cfgUSBlinuz file not found!\n"); + return -1; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", msg); + ExecCfg(cmd); +} + +void USBconfigure() { + ExecCfg("configure"); +} + +void USBabout() { + ExecCfg("about"); +} + diff --git a/plugins/usb/USBlinuz/Linux/Makefile b/plugins/usb/USBlinuz/Linux/Makefile new file mode 100644 index 0000000..8c0ca59 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/Makefile @@ -0,0 +1,33 @@ + +PLUGIN = libUSBlinuz.so +CFG = cfgUSBlinuz +CFLAGS+= -fPIC -Wall -I. -I.. -O3 -fomit-frame-pointer -fno-strict-aliasing +OBJS = ../USB.o +OBJS+= Linux.o Config.o +CFGOBJS = conf.o interface.o support.o Config.o +DEPS:= $(OBJS:.o=.d) +LIBS = -lpthread +CFLAGS+= $(shell gtk-config --cflags) -D__LINUX__ +CFGLIBS = $(shell gtk-config --libs) + +CC = gcc + +all: plugin cfg + +plugin: ${OBJS} + rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} + rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +clean: + rm -f ${OBJS} ${DEPS} ${PLUGIN} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/usb/USBlinuz/Linux/callbacks.c b/plugins/usb/USBlinuz/Linux/callbacks.c new file mode 100644 index 0000000..fa070a7 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/usb/USBlinuz/Linux/callbacks.h b/plugins/usb/USBlinuz/Linux/callbacks.h new file mode 100644 index 0000000..22cf74a --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/usb/USBlinuz/Linux/conf.c b/plugins/usb/USBlinuz/Linux/conf.c new file mode 100644 index 0000000..6eb4191 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/conf.c @@ -0,0 +1,136 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "callbacks.h" +#include "USB.h" +#include "Config.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void cfgSysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_DIALOG); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "USB Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CFGabout() { + About = create_About(); + gtk_widget_show_all(About); + gtk_main(); +} + +GtkWidget *Conf; + +void OnConf_Ok(GtkButton *button, gpointer user_data) { + gchar *str; + + SaveConfig(); + + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CFGconfigure() { + Conf = create_Config(); + + LoadConfig(); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +long CFGmessage(char *msg) { + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(argv[2]); + } + + return 0; +} diff --git a/plugins/usb/USBlinuz/Linux/interface.c b/plugins/usb/USBlinuz/Linux/interface.c new file mode 100644 index 0000000..a73c086 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/interface.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *hbox1; + GtkWidget *label4; + GtkWidget *GtkCombo_Eth; + GtkWidget *combo_entry1; + GtkWidget *frame3; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_Hdd; + GtkWidget *entry1; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "DEV9config"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Ethernet"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + hbox1 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (frame2), hbox1); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label4 = gtk_label_new ("Device:"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (Config), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox1), label4, FALSE, FALSE, 0); + + GtkCombo_Eth = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Eth); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Eth", GtkCombo_Eth, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Eth); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_Eth, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Eth, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_Eth)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + frame3 = gtk_frame_new ("Hdd"); + gtk_widget_ref (frame3); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame3", frame3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (frame3), hbox2); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label5 = gtk_label_new ("Device:"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_Hdd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Hdd); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Hdd", GtkCombo_Hdd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Hdd); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_Hdd, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Hdd, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_Hdd)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "DEV9about"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("DEV9linuz Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Author: linuzappz "); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/usb/USBlinuz/Linux/interface.h b/plugins/usb/USBlinuz/Linux/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/usb/USBlinuz/Linux/support.c b/plugins/usb/USBlinuz/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/usb/USBlinuz/Linux/support.h b/plugins/usb/USBlinuz/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/usb/USBlinuz/Linux/usblinuz.glade b/plugins/usb/USBlinuz/Linux/usblinuz.glade new file mode 100644 index 0000000..715af05 --- /dev/null +++ b/plugins/usb/USBlinuz/Linux/usblinuz.glade @@ -0,0 +1,300 @@ + + + + + DEV9linuz + dev9linuz + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + DEV9config + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox1 + 5 + True + 5 + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Eth + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + + GtkFrame + frame3 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox2 + 5 + True + 5 + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Hdd + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + DEV9about + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/usb/USBlinuz/PS2Edefs.h b/plugins/usb/USBlinuz/PS2Edefs.h new file mode 100644 index 0000000..a52d86a --- /dev/null +++ b/plugins/usb/USBlinuz/PS2Edefs.h @@ -0,0 +1,684 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.5 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0005 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/usb/USBlinuz/PS2Etypes.h b/plugins/usb/USBlinuz/PS2Etypes.h new file mode 100644 index 0000000..443ad45 --- /dev/null +++ b/plugins/usb/USBlinuz/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/usb/USBlinuz/ReadMe.txt b/plugins/usb/USBlinuz/ReadMe.txt new file mode 100644 index 0000000..826f2c8 --- /dev/null +++ b/plugins/usb/USBlinuz/ReadMe.txt @@ -0,0 +1,36 @@ +USBlinuz v0.4 +------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Usage: +----- + Place the file "usblinuz.so" (linux) or "usblinuz.dll" (win32) or usblinuz.dll (win64) + at the Plugin directory of the Emulator to use it. + +Changes: +------- +v0.4 (shadow) +*project files for vs2005 beta1 .64bit dll should work okay (not tested!) + + v0.3: (shadow) + *Up to specifications 0.5.5 + *Added Logging option and ini saving + + v0.2: + *Added partial emulation of Usb + + v0.1: + * First Release + * Tested with Pcsx2 + +Authors: +------- + + linuzappz + shadow + + + diff --git a/plugins/usb/USBlinuz/USB.c b/plugins/usb/USBlinuz/USB.c new file mode 100644 index 0000000..1d4ac34 --- /dev/null +++ b/plugins/usb/USBlinuz/USB.c @@ -0,0 +1,446 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "USB.h" + + +const unsigned char version = PS2E_USB_VERSION; +const unsigned char revision = 0; +const unsigned char build = 4; // increase that with each version + +static char *libraryName = "USBlinuz Driver"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_USB; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.Log) return; + + va_start(list, fmt); + vfprintf(usbLog, fmt, list); + va_end(list); +} + +s32 CALLBACK USBinit() { + LoadConfig(); +#ifdef USB_LOG + usbLog = fopen("logs/usbLog.txt", "w"); + setvbuf(usbLog, NULL, _IONBF, 0); + USB_LOG("usblinuz plugin version %d,%d\n",revision,build); + USB_LOG("USBinit\n"); +#endif + + + usbR = (s8*)malloc(0x10000); + if (usbR == NULL) { + SysMessage("Error allocating memory"); return -1; + } + memset(usbR, 0, 0x10000); + ohci = (struct ohci_regs*)usbR; + ohci->revision = 0x10; + ohci->roothub.a = 0x2; + + return 0; +} + +void CALLBACK USBshutdown() { + free(usbR); +#ifdef USB_LOG + fclose(usbLog); +#endif +} + +s32 CALLBACK USBopen(void *pDsp) { +#ifdef USB_LOG + USB_LOG("USBopen\n"); +#endif + + return 0; +} + +void CALLBACK USBclose() { +} + +u8 CALLBACK USBread8(u32 addr) { + u8 hard; + + switch (addr) { + default: + hard = usbRu8(addr); +#ifdef USB_LOG + USB_LOG("*Unknown 8bit read at address %lx value %x\n", addr, hard); +#endif + return hard; + } + +#ifdef USB_LOG + USB_LOG("*Known 8bit read at address %lx value %x\n", addr, hard); +#endif + return hard; +} + +u16 CALLBACK USBread16(u32 addr) { + u16 hard; + + switch (addr) { + default: + hard = usbRu16(addr); +#ifdef USB_LOG + USB_LOG("*Unknown 16bit read at address %lx value %x\n", addr, hard); +#endif + return hard; + } + +#ifdef USB_LOG + USB_LOG("*Known 16bit read at address %lx value %x\n", addr, hard); +#endif + return hard; +} + +u32 CALLBACK USBread32(u32 addr) { + u32 hard; + int i; + + if (addr >= 0x1f801654 && + addr < 0x1f801690) { + i = (addr - 0x1f801654) / 4; + hard = ohci->roothub.portstatus[i]; +#ifdef USB_LOG + USB_LOG("ohci->roothub.portstatus[%d] read32 %x\n", i, hard); +#endif + return hard; + } + + switch (addr) { +#ifdef USB_LOG + case 0x1f801600: + hard = ohci->revision; + USB_LOG("ohci->revision read32 %x\n", hard); + return hard; +#endif + +#ifdef USB_LOG + case 0x1f801604: + hard = ohci->control; + USB_LOG("ohci->control read32 %x\n", hard); + return hard; +#endif + + case 0x1f801608: + hard = 0; +#ifdef USB_LOG + USB_LOG("ohci->cmdstatus read32 %x\n", hard); +#endif + return hard; + +#ifdef USB_LOG + case 0x1f80160c: + hard = ohci->intrstatus; + USB_LOG("ohci->intrstatus read32 %x\n", hard); + return hard; + + case 0x1f801610: + hard = ohci->intrenable; + USB_LOG("ohci->intrenable read32 %x\n", hard); + return hard; + + case 0x1f801648: + hard = ohci->roothub.a; + USB_LOG("ohci->roothub.a read32 %x\n", hard); + return hard; + + case 0x1f80164C: + hard = ohci->roothub.b; + USB_LOG("ohci->roothub.b read32 %x\n", hard); + return hard; + + case 0x1f801650: + hard = ohci->roothub.status; + USB_LOG("ohci->roothub.status read32 %x\n", hard); + return hard; +#endif + + default: + hard = usbRu32(addr); +#ifdef USB_LOG + USB_LOG("*Unkwnown 32bit read at address %lx: %lx\n", addr, hard); +#endif + return hard; + } + +#ifdef USB_LOG + USB_LOG("*Known 32bit read at address %lx: %lx\n", addr, hard); +#endif + return hard; +} + +void CALLBACK USBwrite8(u32 addr, u8 value) { + switch (addr) { + default: + usbRu8(addr) = value; +#ifdef USB_LOG + USB_LOG("*Unknown 8bit write at address %lx value %x\n", addr, value); +#endif + return; + } + usbRu8(addr) = value; +#ifdef USB_LOG + USB_LOG("*Known 8bit write at address %lx value %x\n", addr, value); +#endif +} + +void CALLBACK USBwrite16(u32 addr, u16 value) { + switch (addr) { + default: + usbRu16(addr) = value; +#ifdef USB_LOG + USB_LOG("*Unknown 16bit write at address %lx value %x\n", addr, value); +#endif + return; + } + usbRu16(addr) = value; +#ifdef USB_LOG + USB_LOG("*Known 16bit write at address %lx value %x\n", addr, value); +#endif +} + +void CALLBACK USBwrite32(u32 addr, u32 value) { + int i; + + if (addr >= 0x1f801654 && + addr < 0x1f801690) { + i = (addr - 0x1f801654) / 4; +// ohci->roothub.portstatus[i] = value; + ohci->intrstatus|= OHCI_INTR_SF; +#ifdef USB_LOG + USB_LOG("ohci->roothub.portstatus[%d] write32 %x\n", i, value); +#endif + return; + } + + switch (addr) { + case 0x1f801600: // ohci->revision (read only) + return; + case 0x1f801604: +#ifdef USB_LOG + USB_LOG("ohci->control write32 %x\n", value); +#endif + ohci->control = value; + if ((ohci->control & OHCI_CTRL_HCFS) == OHCI_USB_OPER) { + USBirq(PSXCLK / 1000000); + ohci->roothub.portstatus[0] = 0x1; + ohci->intrstatus|= OHCI_INTR_RHSC; + } + return; + + case 0x1f80160c: +#ifdef USB_LOG + USB_LOG("ohci->intrstatus write32 %x\n", value); +#endif + ohci->intrstatus&= ~value; + return; + + case 0x1f801610: +#ifdef USB_LOG + USB_LOG("ohci->intrenable write32 %x\n", value); +#endif + for (i=0; i<32; i++) { + if (value & (1<intrenable|= 1<intrdisable write32 %x\n", value); +#endif + for (i=0; i<32; i++) { + if (value & (1<intrenable&= ~(1<hcca = value; + hcca = (struct ohci_hcca*)&ram[ohci->hcca]; + ohci->intrstatus|= OHCI_INTR_SF; +#ifdef USB_LOG + USB_LOG("ohci->hcca write32 %x\n", value); +#endif + return; + +#ifdef USB_LOG + case 0x1f801608: + ohci->cmdstatus = value; + USB_LOG("ohci->cmdstatus write32 %x\n", value); + return; + + case 0x1f801630: + ohci->donehead = value; + USB_LOG("ohci->donehead write32 %x\n", value); + return; + + case 0x1f801634: + ohci->fminterval = value; + USB_LOG("ohci->fminterval write32 %x\n", value); + return; + + case 0x1f801640: + ohci->periodicstart = value; + USB_LOG("ohci->periodicstart write32 %x\n", value); + return; + + case 0x1f801644: + ohci->lsthresh = value; + USB_LOG("ohci->lsthresh write32 %x\n", value); + return; + + case 0x1f801648: + ohci->roothub.a = value; + USB_LOG("ohci->roothub.a write32 %x\n", value); + return; + + case 0x1f80164C: + ohci->roothub.b = value; + USB_LOG("ohci->roothub.b write32 %x\n", value); + return; + + case 0x1f801650: + ohci->roothub.status = value; + USB_LOG("ohci->roothub.status write32 %x\n", value); + return; +#endif + default: + usbRu32(addr) = value; +#ifdef USB_LOG + USB_LOG("*Unknown 32bit write at address %lx write %x\n", addr, value); +#endif + return; + } + usbRu32(addr) = value; +#ifdef USB_LOG + USB_LOG("*Known 32bit write at address %lx value %lx\n", addr, value); +#endif +} + +void CALLBACK USBirqCallback(USBcallback callback) { + USBirq = callback; +} + +int CALLBACK _USBirqHandler(void) { + if ((ohci->control & OHCI_CTRL_HCFS) == OHCI_USB_OPER) { + USBirq(PSXCLK / 1000000); + } + +#ifdef USB_LOG +// USB_LOG("_USBirqHandler: %x\n", ohci->intrenable); +#endif + + if (ohci->fmnumber == 0xffff) { + ohci->fmnumber = 0; + ohci->intrstatus|= OHCI_INTR_FNO; + } else { + ohci->fmnumber++; + } + + if (ohci->intrenable & OHCI_INTR_MIE && + ohci->intrenable & OHCI_INTR_SF && + ohci->intrstatus & OHCI_INTR_SF) { +#ifdef USB_LOG + USB_LOG("_USBirqHandler: SOF\n"); +#endif + + return 1; + } + + if (ohci->intrenable & OHCI_INTR_MIE && + ohci->intrenable & OHCI_INTR_FNO && + ohci->intrstatus & OHCI_INTR_FNO) { +#ifdef USB_LOG + USB_LOG("_USBirqHandler: FNO\n"); +#endif + + return 1; + } + + return 0; +} + +USBhandler CALLBACK USBirqHandler(void) { + return (USBhandler)_USBirqHandler; +} + +void CALLBACK USBsetRAM(void *mem) { + ram = mem; +} + +// extended funcs + +char USBfreezeID[] = "USB STv0"; + +typedef struct { + u8 id[32]; + u8 usbR[0x10000]; + usbStruct usb; +} USBfreezeData; + +s32 CALLBACK USBfreeze(int mode, freezeData *data) { + USBfreezeData *usbd; + + if (mode == FREEZE_LOAD) { + usbd = (USBfreezeData*)data->data; + if (data->size != sizeof(USBfreezeData)) return -1; + if (strcmp(usbd->id, USBfreezeID)) return -1; + memcpy(usbR, usbd->usbR, 0x10000); + memcpy(&usb, &usbd->usb, sizeof(usbStruct)); + } else + if (mode == FREEZE_SAVE) { + data->size = sizeof(USBfreezeData); + data->data = malloc(data->size); + if (data->data == NULL) return -1; + usbd = (USBfreezeData*)data->data; + strcpy(usbd->id, USBfreezeID); + memcpy(usbd->usbR, usbR, 0x10000); + memcpy(&usbd->usb, &usb, sizeof(usbStruct)); + } + + return 0; +} + + +s32 CALLBACK USBtest() { + return 0; +} + diff --git a/plugins/usb/USBlinuz/USB.h b/plugins/usb/USBlinuz/USB.h new file mode 100644 index 0000000..4dd5d93 --- /dev/null +++ b/plugins/usb/USBlinuz/USB.h @@ -0,0 +1,197 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __USB_H__ +#define __USB_H__ + +#include + +#define USBdefs +#include "PS2Edefs.h" + +#ifdef __WIN32__ + +#define usleep(x) Sleep(x / 1000) +#include +#include + +#else + +#include + +#define __inline inline + +#endif + +#define USB_LOG __Log + +typedef struct { + int Log; +} Config; + +Config conf; + +u8 *usbR; +u8 *ram; + +typedef struct { + int unused; +} usbStruct; + +usbStruct usb; + +#define usbRs8(mem) usbR[(mem) & 0xffff] +#define usbRs16(mem) (*(s16*)&usbR[(mem) & 0xffff]) +#define usbRs32(mem) (*(s32*)&usbR[(mem) & 0xffff]) +#define usbRu8(mem) (*(u8*) &usbR[(mem) & 0xffff]) +#define usbRu16(mem) (*(u16*)&usbR[(mem) & 0xffff]) +#define usbRu32(mem) (*(u32*)&usbR[(mem) & 0xffff]) + + +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * usb-ohci.h + */ + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + u32 int_table[NUM_INTS]; /* Interrupt ED table */ + u16 frame_no; /* current frame number */ + u16 pad1; /* set to 0 on each frame_no change */ + u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +}; + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + u32 revision; + u32 control; + u32 cmdstatus; + u32 intrstatus; + u32 intrenable; + u32 intrdisable; + /* memory pointers */ + u32 hcca; + u32 ed_periodcurrent; + u32 ed_controlhead; + u32 ed_controlcurrent; + u32 ed_bulkhead; + u32 ed_bulkcurrent; + u32 donehead; + /* frame counters */ + u32 fminterval; + u32 fmremaining; + u32 fmnumber; + u32 periodicstart; + u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + u32 a; + u32 b; + u32 status; + u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +}; + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + +/**********************/ + +struct ohci_hcca *hcca; +struct ohci_regs *ohci; + +#define PSXCLK 36864000 /* 36.864 Mhz */ + +USBcallback USBirq; + +void SaveConfig(); +void LoadConfig(); + +FILE *usbLog; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#endif diff --git a/plugins/usb/USBlinuz/Win32/Config.c b/plugins/usb/USBlinuz/Win32/Config.c new file mode 100644 index 0000000..c46552a --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/Config.c @@ -0,0 +1,51 @@ +#include + +#include "USB.h" + +extern HINSTANCE hInst; +void SaveConfig() +{ + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\usblinuz.ini"); + sprintf(szValue,"%u",Conf1->Log); + WritePrivateProfileString("Interface", "Logging",szValue,szIniFile); + +} + +void LoadConfig() { + FILE *fp; + + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\usblinuz.ini"); + fp=fopen("inis\\usblinuz.ini","rt");//check if usbnull.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.Log = 0;//default value + SaveConfig();//save and return + return ; + } + fclose(fp); + GetPrivateProfileString("Interface", "Logging", NULL, szValue, 20, szIniFile); + Conf1->Log = strtoul(szValue, NULL, 10); + return ; + +} + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.def b/plugins/usb/USBlinuz/Win32/USBlinuz.def new file mode 100644 index 0000000..7de3002 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.def @@ -0,0 +1,27 @@ +; USBlinuz.def : Declares the module parameters for the DLL. + +LIBRARY "USBlinuz" +DESCRIPTION 'USBlinuz Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + USBinit @5 + USBshutdown @6 + USBopen @7 + USBclose @8 + USBread8 @9 + USBread16 @10 + USBread32 @11 + USBwrite8 @12 + USBwrite16 @13 + USBwrite32 @14 + USBirqCallback @15 + USBirqHandler @16 + USBsetRAM @17 + + USBconfigure @18 + USBtest @19 + USBabout @20 diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.dsp b/plugins/usb/USBlinuz/Win32/USBlinuz.dsp new file mode 100644 index 0000000..293a975 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.dsp @@ -0,0 +1,99 @@ +# Microsoft Developer Studio Project File - Name="USBlinuz" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=USBlinuz - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "USBlinuz.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "USBlinuz.mak" CFG="USBlinuz - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "USBlinuz - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cwcl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USBlinuz_EXPORTS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USBlinuz_EXPORTS" /D "__WIN32__" /D VERSION=0 /D BUILD=2 /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x408 /d "NDEBUG" +# ADD RSC /l 0x408 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=cwlink.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /dll /machine:I386 /nodefaultlib:"msvcrt.lib" +# SUBTRACT LINK32 /nodefaultlib +# Begin Target + +# Name "USBlinuz - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Config.c +# End Source File +# Begin Source File + +SOURCE=..\USB.c +# End Source File +# Begin Source File + +SOURCE=.\USBlinuz.def +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\PS2Edefs.h +# End Source File +# Begin Source File + +SOURCE=..\USB.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\USBlinuz.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.dsw b/plugins/usb/USBlinuz/Win32/USBlinuz.dsw new file mode 100644 index 0000000..4a0da3b --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "USBlinuz"=".\USBlinuz.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.rc b/plugins/usb/USBlinuz/Win32/USBlinuz.rc new file mode 100644 index 0000000..d6255e6 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.rc @@ -0,0 +1,120 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 212, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "USBconfigure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,48,100,50,14 + PUSHBUTTON "Cancel",IDCANCEL,113,100,50,14 + CONTROL "Enable Logging (for develop use only)",IDC_LOGGING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,144,15 +END + +IDD_ABOUT DIALOG 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "USBabout" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "USBlinuz Driver",IDC_NAME,70,10,50,8 + GROUPBOX "",IDC_STATIC,5,35,170,40 + LTEXT "Author: linuzappz ",IDC_STATIC, + 20,20,141,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.sln b/plugins/usb/USBlinuz/Win32/USBlinuz.sln new file mode 100644 index 0000000..d2ff64b --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.sln @@ -0,0 +1,18 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBlinuz", "USBlinuz.vcproj", "{F7181922-7377-4F67-9F50-10997B4613D8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.ActiveCfg = Release|Win32 + {F7181922-7377-4F67-9F50-10997B4613D8}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.suo b/plugins/usb/USBlinuz/Win32/USBlinuz.suo new file mode 100644 index 0000000000000000000000000000000000000000..3e859b804e8d71250e233ed6a5ed1df6e13a30d2 GIT binary patch literal 8704 zcmeHMNo*WN6#ZkzB+g=I4}`6WZ5%?zalFM&SQL+)Mc7I3m^eZ{Fdny^NygKonX$7= z+>nq!9K(r4NJuOqNQe^(QpABAP(qFfA#y-ST*84RkY#wUs%y4*#%;$&80C+CcXd^D z{pw%;zyGV|@}(6&zVqq&t5QJENV(ijSIT`k^*)rzik6F%p}^2z9GilBIp=8*<& zVXh0@HLSp$>%9=X2wVwX3SJCe0$v8L23LW(=Hz=czctV&4t^=Iq+4RRC*%ZH*E_A1 zij2?GMoQ6vi?98%qUkGNIXlsiKnEbvkt4Df(nnD0mgBm?<8`f+`BtGXhvQ0kd`$pf ziuxraNjWM#62UzsFW_opPNqIN#elUyLCU4yc$H7gq<@k2%0UTAuXMSZh%4zStU{;K z%rSR9y7!&eP56GwrB8a5pNrSVkGUqqfo3r4hyg8b+4w)PfEYko)VFzeWlnhw%4@;v z!1se60IvtPg4zFJ+#dly3bw$Hfj59_z-+H`@AbHE1U~`Z1bz~{8N37B0Nw&_1aAeK zd6;_}>b8N~!5!f3VADn&-J`4qu6^+CmK(RK1MgosyXD+V`#yuJrbWL77$s&-w5jSY zdm<9Ht$-6tC7h^ox#~dTL^2hMT77ohNu*TWg04_1L{WF*~NmUN#Vk4Liq@+3pMW^!N5~ zu&O{b5+8CxiD9cR5*uaJ!rgYvPK2U4`4FpTKt8KlG65-Jv`<8R>aaM~1j6h4#lf;!O~`A6Hr}jRLSgm47e_ zc(p(F{lcebQC$8B=#-cQkS#&R{wbSOqHCs!SW(RXdts$xkjgxGz}1B#%)%z8&947x z>E7h8z)=0}aP)T~aROSW^=CcBWX3k^Dh0nH7Of986{XgXfW zF?bG8NOx0LIM!6pcO$DpRQMQHGS*3F`L{l#yXka&S>~wY+;g>MU-#6O(P9_5dK>he z!cuKR`q>Wd05mm;AJ5I;Z78*%wM~^eP-+Ei`O&WtJv&g_iS{-;H^cqf<&2!hwj+qz zs4}>5ISJ64z_Q0-7Tg@2MtP3XgTjm>*X9pEcoI`$&QUB9HNyUg{nN2O`d$rR0+o_) z_F`S|j1+h>YM6olJ&1vxat9;MF`k)k)P6RCFCJC+N6Gr@CzH-SNf`}B?Te^`$$RD3 zK7_~bT>RS)j5~su$XHp-$MfILe|lsF-(QO%UNpm$P7lXn07D3@h4yJ`8eo~H@jC@O z?u0$J!w)q3Vc`te^oyQ8yL#@+oft+QQLt&P4EV6>YBKL%=qHQ624f0 z@23ZIf60Abo%>zieAu$`+WC)vVB4Fh<37@mX~P1aBo_Cg5LN5U%p-)AVEz%$oK1*4 zjnh!l4z(wqP1kQgtUabOo~+#cD*MZo%H8(lbJNj*eHS4Y6fDH-!O{+Sc9utMkUm5( zW`aC*v0*qGZaZZ(+_2%wc*vj@j%5sNsO^9x%SrE_jtuNQEb$d3?E!@Xz8|3&tSn_W? z+yX6<-!r8@+|m-cu1e+dC+@V|a``LM>+ekIMy7N#Q@Z7rmPpzyZN~e%VR=#Ii%GQy zvw=m^i$Xa6^f4!5O!pf9cov85icFTvJeWI6X5Q4UMmy%arOBMXQZ}h{Z{13qysZ40 zjvG@_LqHoFZ04hJwOH1lm9k+5@i+JT?*xwQ*j`F2XCU8?fw#Ng&;11T&Amr%?sKP= zYCArNUY)@1Frp?;N$kw|5ogO2TmFwQoHv%%sX5t>;2r8!p9mbfL|oT2lQRguc{l#& z4FUE1Ci6e2|9`U=KoB;EFOwY=7FU%v;s%6moeOp$uj@v>w-aeu0C}Ka<%X>Yh};=< zgP99= literal 0 HcmV?d00001 diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz.vcproj b/plugins/usb/USBlinuz/Win32/USBlinuz.vcproj new file mode 100644 index 0000000..f655f04 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz.vcproj @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.sln b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.sln new file mode 100644 index 0000000..4b301cc --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBlinuz", "USBlinuz_vc2002.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.ActiveCfg = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.Build.0 = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.ActiveCfg = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.vcproj b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.vcproj new file mode 100644 index 0000000..aa11eec --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2002.vcproj @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.ncb b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.ncb new file mode 100644 index 0000000000000000000000000000000000000000..d3382ad9d93b41163206e3449e55193ccc912c9c GIT binary patch literal 52224 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 HlfeH2*Qqz? literal 0 HcmV?d00001 diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.sln b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.sln new file mode 100644 index 0000000..4299974 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBlinuz", "USBlinuz_vc2003.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.ActiveCfg = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.Build.0 = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.ActiveCfg = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.suo b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.suo new file mode 100644 index 0000000000000000000000000000000000000000..ed9bc2f7b89c18175ad4b2f9b511123dc58b85a7 GIT binary patch literal 8704 zcmeHMOKg-?6h6~ZX+a7UM68M<A2D%dT(~f@Fc1@28d(^ZxbT7U7{BlS|DE^a?*n3!p61Md|9kI$&$;)W z^PO{VuU%dL%ST_d-jE_XBK2}F(6?NM5jkJs9dxhEP2SVs)dZQB2d1;haQKi6Bgx8#){L3tDSQSfH) zW8hZsycOIA-Ui+d-T~eT-UWUJ%)Zas&vraL;OD@5?Yd4pyTIMx z9`HW!esC}N0QewS%gbM@<#Hx7+}85?PYq)O?|m?I#XK>56H7HG`rXSYF@IuQS?e=q zBO$}>jmOf-xT#!jg)fi}aM)ERM@QWL&?zITUf1{{0W&`B9tcO$@gzH}8;u7ers1A2 zg6_e1GO9jrDtKGvjYkvlm=Q~>#x)a>SU7$*mFvFZ#qrS*4%X~7BZ*)>m6RO-L zohUDahJkd904C(bfxUi(KeHG;gi>vC+xSBapg-0A!pa*zwLAJCC8*{+tt3wXkJFHS z3U6w&Y79vETti})Q~AtuHrnGB%O~m@(BTaBBCggrT~&`=kk42`jC3lWaq^`K@)`fQ z@(HX$1RBr|s?iQ);gqYXT3_A9*rVgmLhVUt3}P;(+R;hG zI@%VaehNH=dAbn;8GUEa+r*n6bu$uH^LGR7UqMzdj`~g@{$3#cB>IPd@RMqsG@dDp z7gC<^&I8wh_G)65Q%VD^iGCOPzi4FXS&SCN_RpP)VeS3cn;EsL)lmTU=VGqFC_o#; zqb9NM*DkADW%=i@ro^NQz-vpHkNwkMEBXH@tTYO#%!4hA4dabjSb5rm`P2598#$dn z^Tly{IQn}UGLu+!T7S+{bY^V8uF~);VgY;dH>b@($k)E_RQ?9YCSEQU@gAU<7E)I{ z*8O~M5EVYcO2%f{Q2(V1P@c)`tjk_?eE#xv*Y_jWRlg?gGpNyZ9szj}Ak>dEvqSoj zc(wzkx{!qSqSUS0yeRb{9X)`zc2(1jjqF7~{`Dd0-w!~$C>Kfs{A)6cZP$S3QEv$t z36Dw_&@#7V!Ac)I`0fJ!&O?KKXxfYMdwm!(1W%9JmX&Yw$IzAn9#o4&dl7$lCSV@t z)c)vu@7o4aO};*h`QRC8a5?h8{+n&tPUSy^{?FTk5$Bk5={Z_{HicPFEBvEmD-M^F zE&~5o^VU9CzE@$b8?Qlo{zrjvrx6nwD=YbU;n#(4Tjn8uH-;F{!@ve$oBNclb)wXP zKOeXq^}WhI+f~?Q=p9rwJ*Yi^KAo^!k&e!;?jD@D@_c7kHQ%X|)+OaT`H6PEag_BY zdenkfQ}2wUX9M=1$mF-xyD(Q@#W+mRoQR8RNgj}*UgHK?AxgB4Hi?kL-GRTF6M|H z83WET6Xvax0Wi*)mj@YSzd|~met6nrP|B_R;YHUamwU}c51w@T5HpC2vzUVydh?*n z9bhI{IKxAzsYZms-!^Xl@w2wJp|5_uadBrb+O15v`AVyKr>X7eyP3CdUH$gs0cFTM zWfq@>MQ&FUP^0Ztw*Y?^a{4aTr&{Q?{$KJS<#GD01=)Q5X^iJJQ`urloxu$F;@qMT z?muw@Y@O+y#$VpWQ7@9ta+wG7_Jf%>vti5IneSF7-oH{Va|);O_n>d1jhDxfPg80D z-e!QcJ{GRz^6W}lY@J8^&7Xg<^;D8mslH_%@;fk?SuR1ZB&13`hv7YMc`UK+d~j7FUo^@e9!pT8{FyENWtUdVEmf+QzwzW(_3}@)*T31)?QH2zwshAn zt(J^kq6G{=ml&9L6sB$UR^C^tr8SQe=+zIcLx`BXAu_UeXVjaw)%+hyxL_>Hp7gDL z1mAGhya_MF$$SJ}UbXV8hD9r(lUEs!mTA5#p#RUM|NrGj?m-OZ9V|~pwGfc_Pu$hy aL=WZ!`u@>L|5|;tY(8uCy&vsMS^j_FZ8-G+ literal 0 HcmV?d00001 diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.vcproj b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.vcproj new file mode 100644 index 0000000..c35bec4 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2003.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.sln b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.sln new file mode 100644 index 0000000..411b3fd --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBlinuz", "USBlinuz_vc2005beta1.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + amd64|Win32 = amd64|Win32 + amd64|Win64 (AMD64) = amd64|Win64 (AMD64) + Debug|Win32 = Debug|Win32 + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win32.ActiveCfg = amd64|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win32.Build.0 = amd64|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win64 (AMD64).ActiveCfg = amd64|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win64 (AMD64).Build.0 = amd64|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win32.ActiveCfg = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win32.Build.0 = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win32.ActiveCfg = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win32.Build.0 = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.vcproj b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.vcproj new file mode 100644 index 0000000..c2d54ab --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/USBlinuz_vc2005beta1.vcproj @@ -0,0 +1,566 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBlinuz/Win32/Win32.c b/plugins/usb/USBlinuz/Win32/Win32.c new file mode 100644 index 0000000..8cee478 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/Win32.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "USB.h" +#include "resource.h" + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "USBlinuz Msg", 0); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + if (conf.Log) CheckDlgButton(hW, IDC_LOGGING, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOGGING)) + conf.Log = 1; + else conf.Log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK USBconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK USBabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/usb/USBlinuz/Win32/resource.h b/plugins/usb/USBlinuz/Win32/resource.h new file mode 100644 index 0000000..bf37b53 --- /dev/null +++ b/plugins/usb/USBlinuz/Win32/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by USBlinuz.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_CHECK1 1007 +#define IDC_LOGGING 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/usb/USBnull/License.txt b/plugins/usb/USBnull/License.txt new file mode 100644 index 0000000..bb0a0ce --- /dev/null +++ b/plugins/usb/USBnull/License.txt @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/plugins/usb/USBnull/Linux/Config.c b/plugins/usb/USBnull/Linux/Config.c new file mode 100644 index 0000000..c4abd82 --- /dev/null +++ b/plugins/usb/USBnull/Linux/Config.c @@ -0,0 +1,59 @@ +/* USBnull + * Copyright (C) 2002-2004 USBnull Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "USB.h" + +void LoadConfig() { +/* FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E/CDVDiso.cfg", getenv("HOME")); + f = fopen(cfg, "r"); + if (f == NULL) { + strcpy(IsoFile, DEV_DEF); + strcpy(CdDev, CDDEV_DEF); + return; + } + fscanf(f, "IsoFile = %[^\n]\n", IsoFile); + fscanf(f, "CdDev = %[^\n]\n", CdDev); + if (!strncmp(IsoFile, "CdDev =", 9)) *IsoFile = 0; // quick fix + if (*CdDev == 0) strcpy(CdDev, CDDEV_DEF); + fclose(f);*/ +} + +void SaveConfig() { +/* FILE *f; + char cfg[256]; + + sprintf(cfg, "%s/.PS2E", getenv("HOME")); + mkdir(cfg, 0755); + sprintf(cfg, "%s/.PS2E/CDVDiso.cfg", getenv("HOME")); + f = fopen(cfg, "w"); + if (f == NULL) + return; + fprintf(f, "IsoFile = %s\n", IsoFile); + fprintf(f, "CdDev = %s\n", CdDev); + fclose(f);*/ +} + diff --git a/plugins/usb/USBnull/Linux/Config.h b/plugins/usb/USBnull/Linux/Config.h new file mode 100644 index 0000000..8382b72 --- /dev/null +++ b/plugins/usb/USBnull/Linux/Config.h @@ -0,0 +1,20 @@ +/* USBnull + * Copyright (C) 2002-2004 USBnull Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void SaveConfig(); +void LoadConfig(); diff --git a/plugins/usb/USBnull/Linux/Linux.c b/plugins/usb/USBnull/Linux/Linux.c new file mode 100644 index 0000000..1a07ba1 --- /dev/null +++ b/plugins/usb/USBnull/Linux/Linux.c @@ -0,0 +1,74 @@ +/* USBnull + * Copyright (C) 2002-2004 USBnull Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + + +int ExecCfg(char *arg) { + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgUSBnull"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + strcpy(cfg, "./cfg/cfgUSBnull"); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + sprintf(cfg, "%s/cfgUSBnull", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + sprintf(cfg, "%s %s", cfg, arg); + return system(cfg); + } + + printf("cfgUSBnull file not found!\n"); + return -1; +} + +void SysMessage(char *fmt, ...) { + va_list list; + char msg[512]; + char cmd[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + sprintf(cmd, "message \"%s\"", msg); + ExecCfg(cmd); +} + +void USBconfigure() { + ExecCfg("configure"); +} + +void USBabout() { + ExecCfg("about"); +} + diff --git a/plugins/usb/USBnull/Linux/Makefile b/plugins/usb/USBnull/Linux/Makefile new file mode 100644 index 0000000..24d378a --- /dev/null +++ b/plugins/usb/USBnull/Linux/Makefile @@ -0,0 +1,35 @@ + +PLUGIN = libUSBnull.so +CFG = cfgUSBnull +CFLAGS+= -fPIC -Wall -I. -I.. -O3 -fomit-frame-pointer -fno-strict-aliasing +OBJS = ../USB.o +OBJS+= Config.o Linux.o +CFGOBJS = conf.o interface.o support.o +DEPS:= $(OBJS:.o=.d) +CFGDEPS:= $(CFGOBJS:.o=.d) +LIBS = -lpthread +CFLAGS+= $(shell pkg-config --cflags gtk+-2.0) -D__LINUX__ +CFGLIBS = $(shell pkg-config --libs gtk+-2.0) + +CC = gcc + +all: plugin cfg +install: all + +plugin: ${OBJS} +# rm -f ${PLUGIN} + ${CC} -shared -Wl,-soname,${PLUGIN} ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + strip --strip-unneeded --strip-debug ${PLUGIN} + +cfg: ${CFGOBJS} +# rm -f ${CFG} + ${CC} ${CFLAGS} ${CFGOBJS} -o ${CFG} ${CFGLIBS} + strip ${CFG} + +clean: + rm -f ${OBJS} ${CFGOBJS} ${CFGDEPS} ${PLUGIN} ${CFG} + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +-include ${DEPS} diff --git a/plugins/usb/USBnull/Linux/callbacks.c b/plugins/usb/USBnull/Linux/callbacks.c new file mode 100644 index 0000000..fa070a7 --- /dev/null +++ b/plugins/usb/USBnull/Linux/callbacks.c @@ -0,0 +1,34 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data) +{ + +} + + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data) +{ + +} + diff --git a/plugins/usb/USBnull/Linux/callbacks.h b/plugins/usb/USBnull/Linux/callbacks.h new file mode 100644 index 0000000..22cf74a --- /dev/null +++ b/plugins/usb/USBnull/Linux/callbacks.h @@ -0,0 +1,14 @@ +#include + + +void +OnConf_Ok (GtkButton *button, + gpointer user_data); + +void +OnConf_Cancel (GtkButton *button, + gpointer user_data); + +void +OnAbout_Ok (GtkButton *button, + gpointer user_data); diff --git a/plugins/usb/USBnull/Linux/conf.c b/plugins/usb/USBnull/Linux/conf.c new file mode 100644 index 0000000..74d444b --- /dev/null +++ b/plugins/usb/USBnull/Linux/conf.c @@ -0,0 +1,128 @@ +/* USBnull + * Copyright (C) 2002-2004 USBnull Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "support.h" +#include "callbacks.h" + +GtkWidget *MsgDlg; + +void OnMsg_Ok() { + gtk_widget_destroy(MsgDlg); + gtk_main_quit(); +} + +void cfgSysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "USBnull Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} + +GtkWidget *About; + +void OnAbout_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(About); + gtk_main_quit(); +} + +void CFGabout() { + About = create_About(); + gtk_widget_show_all(About); + gtk_main(); +} + +GtkWidget *Conf; + +void OnConf_Ok(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void OnConf_Cancel(GtkButton *button, gpointer user_data) { + gtk_widget_destroy(Conf); + gtk_main_quit(); +} + +void CFGconfigure() { + Conf = create_Config(); + + gtk_widget_show_all(Conf); + gtk_main(); +} + +long CFGmessage(char *msg) { + cfgSysMessage(msg); + + return 0; +} + +int main(int argc, char *argv[]) { + gtk_init(NULL, NULL); + + if (!strcmp(argv[1], "configure")) { + CFGconfigure(); + } else if (!strcmp(argv[1], "about")) { + CFGabout(); + } else if (!strcmp(argv[1], "message")) { + CFGmessage(argv[2]); + } + + return 0; +} diff --git a/plugins/usb/USBnull/Linux/interface.c b/plugins/usb/USBnull/Linux/interface.c new file mode 100644 index 0000000..a73c086 --- /dev/null +++ b/plugins/usb/USBnull/Linux/interface.c @@ -0,0 +1,219 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +GtkWidget* +create_Config (void) +{ + GtkWidget *Config; + GtkWidget *vbox1; + GtkWidget *frame2; + GtkWidget *hbox1; + GtkWidget *label4; + GtkWidget *GtkCombo_Eth; + GtkWidget *combo_entry1; + GtkWidget *frame3; + GtkWidget *hbox2; + GtkWidget *label5; + GtkWidget *GtkCombo_Hdd; + GtkWidget *entry1; + GtkWidget *hbuttonbox1; + GtkWidget *button1; + GtkWidget *button2; + + Config = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (Config), "Config", Config); + gtk_container_set_border_width (GTK_CONTAINER (Config), 5); + gtk_window_set_title (GTK_WINDOW (Config), "DEV9config"); + gtk_window_set_position (GTK_WINDOW (Config), GTK_WIN_POS_CENTER); + + vbox1 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "vbox1", vbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (Config), vbox1); + gtk_container_set_border_width (GTK_CONTAINER (vbox1), 5); + + frame2 = gtk_frame_new ("Ethernet"); + gtk_widget_ref (frame2); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame2", frame2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0); + + hbox1 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox1", hbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (frame2), hbox1); + gtk_container_set_border_width (GTK_CONTAINER (hbox1), 5); + + label4 = gtk_label_new ("Device:"); + gtk_widget_ref (label4); + gtk_object_set_data_full (GTK_OBJECT (Config), "label4", label4, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox1), label4, FALSE, FALSE, 0); + + GtkCombo_Eth = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Eth); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Eth", GtkCombo_Eth, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Eth); + gtk_box_pack_start (GTK_BOX (hbox1), GtkCombo_Eth, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Eth, 130, -2); + + combo_entry1 = GTK_COMBO (GtkCombo_Eth)->entry; + gtk_widget_ref (combo_entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "combo_entry1", combo_entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (combo_entry1); + + frame3 = gtk_frame_new ("Hdd"); + gtk_widget_ref (frame3); + gtk_object_set_data_full (GTK_OBJECT (Config), "frame3", frame3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (vbox1), frame3, TRUE, TRUE, 0); + + hbox2 = gtk_hbox_new (TRUE, 5); + gtk_widget_ref (hbox2); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbox2", hbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (frame3), hbox2); + gtk_container_set_border_width (GTK_CONTAINER (hbox2), 5); + + label5 = gtk_label_new ("Device:"); + gtk_widget_ref (label5); + gtk_object_set_data_full (GTK_OBJECT (Config), "label5", label5, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label5); + gtk_box_pack_start (GTK_BOX (hbox2), label5, FALSE, FALSE, 0); + + GtkCombo_Hdd = gtk_combo_new (); + gtk_widget_ref (GtkCombo_Hdd); + gtk_object_set_data_full (GTK_OBJECT (Config), "GtkCombo_Hdd", GtkCombo_Hdd, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (GtkCombo_Hdd); + gtk_box_pack_start (GTK_BOX (hbox2), GtkCombo_Hdd, FALSE, FALSE, 0); + gtk_widget_set_usize (GtkCombo_Hdd, 130, -2); + + entry1 = GTK_COMBO (GtkCombo_Hdd)->entry; + gtk_widget_ref (entry1); + gtk_object_set_data_full (GTK_OBJECT (Config), "entry1", entry1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (entry1); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox1); + gtk_object_set_data_full (GTK_OBJECT (Config), "hbuttonbox1", hbuttonbox1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox1), hbuttonbox1, TRUE, TRUE, 0); + + button1 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button1); + gtk_object_set_data_full (GTK_OBJECT (Config), "button1", button1, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button1); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button1); + GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); + + button2 = gtk_button_new_with_label ("Cancel"); + gtk_widget_ref (button2); + gtk_object_set_data_full (GTK_OBJECT (Config), "button2", button2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button2); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button2); + GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button1), "clicked", + GTK_SIGNAL_FUNC (OnConf_Ok), + NULL); + gtk_signal_connect (GTK_OBJECT (button2), "clicked", + GTK_SIGNAL_FUNC (OnConf_Cancel), + NULL); + + return Config; +} + +GtkWidget* +create_About (void) +{ + GtkWidget *About; + GtkWidget *vbox2; + GtkWidget *label2; + GtkWidget *label3; + GtkWidget *hbuttonbox2; + GtkWidget *button3; + + About = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_object_set_data (GTK_OBJECT (About), "About", About); + gtk_container_set_border_width (GTK_CONTAINER (About), 5); + gtk_window_set_title (GTK_WINDOW (About), "DEV9about"); + gtk_window_set_position (GTK_WINDOW (About), GTK_WIN_POS_CENTER); + + vbox2 = gtk_vbox_new (FALSE, 5); + gtk_widget_ref (vbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "vbox2", vbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (About), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + label2 = gtk_label_new ("DEV9linuz Driver"); + gtk_widget_ref (label2); + gtk_object_set_data_full (GTK_OBJECT (About), "label2", label2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label2); + gtk_box_pack_start (GTK_BOX (vbox2), label2, FALSE, FALSE, 0); + + label3 = gtk_label_new ("Author: linuzappz "); + gtk_widget_ref (label3); + gtk_object_set_data_full (GTK_OBJECT (About), "label3", label3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_LEFT); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_ref (hbuttonbox2); + gtk_object_set_data_full (GTK_OBJECT (About), "hbuttonbox2", hbuttonbox2, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox2), hbuttonbox2, TRUE, TRUE, 0); + + button3 = gtk_button_new_with_label ("Ok"); + gtk_widget_ref (button3); + gtk_object_set_data_full (GTK_OBJECT (About), "button3", button3, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_show (button3); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button3); + GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT); + + gtk_signal_connect (GTK_OBJECT (button3), "clicked", + GTK_SIGNAL_FUNC (OnAbout_Ok), + NULL); + + return About; +} + diff --git a/plugins/usb/USBnull/Linux/interface.h b/plugins/usb/USBnull/Linux/interface.h new file mode 100644 index 0000000..ab0cb1a --- /dev/null +++ b/plugins/usb/USBnull/Linux/interface.h @@ -0,0 +1,6 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_Config (void); +GtkWidget* create_About (void); diff --git a/plugins/usb/USBnull/Linux/support.c b/plugins/usb/USBnull/Linux/support.c new file mode 100644 index 0000000..b053ba6 --- /dev/null +++ b/plugins/usb/USBnull/Linux/support.c @@ -0,0 +1,162 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include + +#include "support.h" + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* check_file_exists (const gchar *directory, + const gchar *filename); + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* create_dummy_pixmap (GtkWidget *widget); + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is a dummy pixmap we use when a pixmap can't be found. */ +static char *dummy_pixmap_xpm[] = { +/* columns rows colors chars-per-pixel */ +"1 1 1 1", +" c None", +/* pixels */ +" " +}; + +/* This is an internally used function to create pixmaps. */ +static GtkWidget* +create_dummy_pixmap (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask, + NULL, dummy_pixmap_xpm); + if (gdkpixmap == NULL) + g_error ("Couldn't create replacement pixmap."); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *found_filename = NULL; + GdkColormap *colormap; + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + GList *elem; + + if (!filename || !filename[0]) + return create_dummy_pixmap (widget); + + /* We first try any pixmaps directories set by the application. */ + elem = pixmaps_directories; + while (elem) + { + found_filename = check_file_exists ((gchar*)elem->data, filename); + if (found_filename) + break; + elem = elem->next; + } + + /* If we haven't found the pixmap, try the source directory. */ + if (!found_filename) + { + found_filename = check_file_exists ("pixmaps", filename); + } + + if (!found_filename) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return create_dummy_pixmap (widget); + } + + colormap = gtk_widget_get_colormap (widget); + gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask, + NULL, found_filename); + if (gdkpixmap == NULL) + { + g_warning ("Error loading pixmap file: %s", found_filename); + g_free (found_filename); + return create_dummy_pixmap (widget); + } + g_free (found_filename); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + gdk_pixmap_unref (gdkpixmap); + gdk_bitmap_unref (mask); + return pixmap; +} + +/* This is an internally used function to check if a pixmap file exists. */ +static gchar* +check_file_exists (const gchar *directory, + const gchar *filename) +{ + gchar *full_filename; + struct stat s; + gint status; + + full_filename = (gchar*) g_malloc (strlen (directory) + 1 + + strlen (filename) + 1); + strcpy (full_filename, directory); + strcat (full_filename, G_DIR_SEPARATOR_S); + strcat (full_filename, filename); + + status = stat (full_filename, &s); + if (status == 0 && S_ISREG (s.st_mode)) + return full_filename; + g_free (full_filename); + return NULL; +} + diff --git a/plugins/usb/USBnull/Linux/support.h b/plugins/usb/USBnull/Linux/support.h new file mode 100644 index 0000000..8866159 --- /dev/null +++ b/plugins/usb/USBnull/Linux/support.h @@ -0,0 +1,38 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + +/* get_widget() is deprecated. Use lookup_widget instead. */ +#define get_widget lookup_widget + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + diff --git a/plugins/usb/USBnull/Linux/usbnull.glade b/plugins/usb/USBnull/Linux/usbnull.glade new file mode 100644 index 0000000..6644e52 --- /dev/null +++ b/plugins/usb/USBnull/Linux/usbnull.glade @@ -0,0 +1,300 @@ + + + + + FireWire + dev9linuz + + + pixmaps + C + False + False + False + False + False + + + + GtkWindow + Config + 5 + DEV9config + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox1 + 5 + False + 5 + + + GtkFrame + frame2 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox1 + 5 + True + 5 + + + GtkLabel + label4 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Eth + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + combo-entry1 + True + True + True + 0 + + + + + + + + GtkFrame + frame3 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkHBox + hbox2 + 5 + True + 5 + + + GtkLabel + label5 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkCombo + GtkCombo_Hdd + 130 + False + True + False + True + False + + + 0 + False + False + + + + GtkEntry + GtkCombo:entry + entry1 + True + True + True + 0 + + + + + + + + GtkHButtonBox + hbuttonbox1 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button1 + True + True + + clicked + OnConf_Ok + Sat, 06 Apr 2002 17:07:56 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button2 + True + True + + clicked + OnConf_Cancel + Sat, 06 Apr 2002 17:08:08 GMT + + + GTK_RELIEF_NORMAL + + + + + + + GtkWindow + About + 5 + DEV9about + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + False + True + False + + + GtkVBox + vbox2 + 5 + False + 5 + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkLabel + label3 + + GTK_JUSTIFY_LEFT + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHButtonBox + hbuttonbox2 + GTK_BUTTONBOX_DEFAULT_STYLE + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button3 + True + True + + clicked + OnAbout_Ok + Sun, 07 Apr 2002 03:43:49 GMT + + + GTK_RELIEF_NORMAL + + + + + + diff --git a/plugins/usb/USBnull/PS2Edefs.h b/plugins/usb/USBnull/PS2Edefs.h new file mode 100644 index 0000000..a52d86a --- /dev/null +++ b/plugins/usb/USBnull/PS2Edefs.h @@ -0,0 +1,684 @@ +#ifndef __PS2EDEFS_H__ +#define __PS2EDEFS_H__ + +/* + * PS2E Definitions v0.5.5 (beta) + * + * Author: linuzappz@hotmail.com + * shadowpcsx2@yahoo.gr + * florinsasu@hotmail.com + */ + +/* + Notes: + * Since this is still beta things may change. + + * OSflags: + __LINUX__ (linux OS) + __WIN32__ (win32 OS) + + * common return values (for ie. GSinit): + 0 - success + -1 - error + + * reserved keys: + F1 to F10 are reserved for the emulator + + * plugins should NOT change the current + working directory. + (on win32, add flag OFN_NOCHANGEDIR for + GetOpenFileName) + +*/ + +#include "PS2Etypes.h" + +#ifdef __LINUX__ +#define CALLBACK +#else +#include +#endif + +/* common defines */ + +#if defined(GSdefs) || defined(PADdefs) || \ + defined(SPU2defs)|| defined(CDVDdefs) +#define COMMONdefs +#endif + +// PS2EgetLibType returns (may be OR'd) +#define PS2E_LT_GS 0x01 +#define PS2E_LT_PAD 0x02 +#define PS2E_LT_SPU2 0x04 +#define PS2E_LT_CDVD 0x08 +#define PS2E_LT_DEV9 0x10 +#define PS2E_LT_USB 0x20 +#define PS2E_LT_FIREWIRE 0x40 + +// PS2EgetLibVersion2 (high 16 bits) +#define PS2E_GS_VERSION 0x0005 +#define PS2E_PAD_VERSION 0x0002 +#define PS2E_SPU2_VERSION 0x0004 +#define PS2E_CDVD_VERSION 0x0003 +#define PS2E_DEV9_VERSION 0x0003 +#define PS2E_USB_VERSION 0x0003 +#define PS2E_FIREWIRE_VERSION 0x0002 +#ifdef COMMONdefs + +u32 CALLBACK PS2EgetLibType(void); +u32 CALLBACK PS2EgetLibVersion2(u32 type); +char* CALLBACK PS2EgetLibName(void); + +#endif + +// key values: +/* key values must be OS dependant: + win32: the VK_XXX will be used (WinUser) + linux: the XK_XXX will be used (XFree86) +*/ + +// event values: +#define KEYPRESS 1 +#define KEYRELEASE 2 + +typedef struct { + u32 key; + u32 event; +} keyEvent; + +typedef struct { // NOT bcd coded + u8 minute; + u8 second; + u8 frame; + u8 type; +} cdvdTD; + +typedef struct { + u8 strack; //number of the first track (usualy 1) + u8 etrack; //number of the last track +} cdvdTN; + +// CDVDreadTrack mode values: +#define CDVD_MODE_2352 0 // full 2352 bytes +#define CDVD_MODE_2340 1 // skip sync (12) bytes +#define CDVD_MODE_2328 2 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2048 3 // skip sync+head+sub (24) bytes +#define CDVD_MODE_2368 4 // full 2352 bytes + 16 subq + +// CDVDgetType returns: +#define CDVD_TYPE_ILLEGAL 0xff // Illegal Disc +#define CDVD_TYPE_DVDV 0xfe // DVD Video +#define CDVD_TYPE_CDDA 0xfd // Audio CD +#define CDVD_TYPE_PS2DVD 0x14 // PS2 DVD +#define CDVD_TYPE_PS2CDDA 0x13 // PS2 CD (with audio) +#define CDVD_TYPE_PS2CD 0x12 // PS2 CD +#define CDVD_TYPE_PSCDDA 0x11 // PS CD (with audio) +#define CDVD_TYPE_PSCD 0x10 // PS CD +#define CDVD_TYPE_UNKNOWN 0x05 // Unknown +#define CDVD_TYPE_DETCTDVDD 0x04 // Detecting Dvd Dual Sided +#define CDVD_TYPE_DETCTDVDS 0x03 // Detecting Dvd Single Sided +#define CDVD_TYPE_DETCTCD 0x02 // Detecting Cd +#define CDVD_TYPE_DETCT 0x01 // Detecting +#define CDVD_TYPE_NODISC 0x00 // No Disc + +// CDVDgetTrayStatus returns: +#define CDVD_TRAY_CLOSE 0x00 +#define CDVD_TRAY_OPEN 0x01 + +// cdvdLoc:track type +#define CDVD_AUDIO_TRACK 0x01 +#define CDVD_MODE1_TRACK 0x41 +#define CDVD_MODE2_TRACK 0x61 + +#define CDVD_AUDIO_MASK 0x00 +#define CDVD_DATA_MASK 0x40 +// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel) + +typedef void (*DEV9callback)(int cycles); +typedef int (*DEV9handler)(void); + +typedef void (*USBcallback)(int cycles); +typedef int (*USBhandler)(void); + +// freeze modes: +#define FREEZE_LOAD 0 +#define FREEZE_SAVE 1 +#define FREEZE_SIZE 2 + +typedef struct { + int size; + s8 *data; +} freezeData; + +typedef struct { + char name[8]; + void *common; +} GSdriverInfo; + +#ifdef __WIN32__ +typedef struct { // unsupported values must be set to zero + HWND hWnd; + HMENU hMenu; + HWND hStatusWnd; +} winInfo; +#endif + +/* GS plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef GSdefs + +// basic funcs + +s32 CALLBACK GSinit(); +s32 CALLBACK GSopen(void *pDsp, char *Title); +void CALLBACK GSclose(); +void CALLBACK GSshutdown(); +void CALLBACK GSvsync(); +void CALLBACK GSgifTransfer1(u32 *pMem); +void CALLBACK GSgifTransfer2(u32 *pMem, u32 size); +void CALLBACK GSgifTransfer3(u32 *pMem, u32 size); +void CALLBACK GSwrite32(u32 mem, u32 value); +void CALLBACK GSwrite64(u32 mem, u64 value); +u32 CALLBACK GSread32(u32 mem); +u64 CALLBACK GSread64(u32 mem); +void CALLBACK GSreadFIFO(u64 *mem); + +// extended funcs + +// GSkeyEvent gets called when there is a keyEvent from the PAD plugin +void CALLBACK GSkeyEvent(keyEvent *ev); +void CALLBACK GSmakeSnapshot(char *path); +void CALLBACK GSirqCallback(void (*callback)()); +void CALLBACK GSprintf(int timeout, char *fmt, ...); +void CALLBACK GSgetDriverInfo(GSdriverInfo *info); +#ifdef __WIN32__ +s32 CALLBACK GSsetWindowInfo(winInfo *info); +#endif +s32 CALLBACK GSfreeze(int mode, freezeData *data); +void CALLBACK GSconfigure(); +void CALLBACK GSabout(); +s32 CALLBACK GStest(); + +#endif + +/* PAD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef PADdefs + +// basic funcs + +s32 CALLBACK PADinit(u32 flags); +s32 CALLBACK PADopen(void *pDsp); +void CALLBACK PADclose(); +void CALLBACK PADshutdown(); +// PADkeyEvent is called every vsync (return NULL if no event) +keyEvent* CALLBACK PADkeyEvent(); +u8 CALLBACK PADstartPoll(int pad); +u8 CALLBACK PADpoll(u8 value); +// returns: 1 if supported pad1 +// 2 if supported pad2 +// 3 if both are supported +u32 CALLBACK PADquery(); + +// extended funcs + +void CALLBACK PADgsDriverInfo(GSdriverInfo *info); +void CALLBACK PADconfigure(); +void CALLBACK PADabout(); +s32 CALLBACK PADtest(); + +#endif + +/* SPU2 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef SPU2defs + +// basic funcs + +s32 CALLBACK SPU2init(); +s32 CALLBACK SPU2open(void *pDsp); +void CALLBACK SPU2close(); +void CALLBACK SPU2shutdown(); +void CALLBACK SPU2write(u32 mem, u16 value); +u16 CALLBACK SPU2read(u32 mem); +void CALLBACK SPU2readDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2writeDMA4Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA4(); +void CALLBACK SPU2readDMA7Mem(u16* pMem, int size); +void CALLBACK SPU2writeDMA7Mem(u16 *pMem, int size); +void CALLBACK SPU2interruptDMA7(); +void CALLBACK SPU2irqCallback(void (*callback)()); + +// extended funcs + +void CALLBACK SPU2async(u32 cycles); +s32 CALLBACK SPU2freeze(int mode, freezeData *data); +void CALLBACK SPU2configure(); +void CALLBACK SPU2about(); +s32 CALLBACK SPU2test(); + +#endif + +/* CDVD plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef CDVDdefs + +// basic funcs + +s32 CALLBACK CDVDinit(); +s32 CALLBACK CDVDopen(); +void CALLBACK CDVDclose(); +void CALLBACK CDVDshutdown(); +s32 CALLBACK CDVDreadTrack(u32 lsn, int mode); + +// return can be NULL (for async modes) +u8* CALLBACK CDVDgetBuffer(); + +s32 CALLBACK CDVDgetTN(cdvdTN *Buffer); //disk information +s32 CALLBACK CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type +s32 CALLBACK CDVDgetType(); //CDVD_TYPE_xxxx +s32 CALLBACK CDVDgetTrayStatus(); //CDVD_TRAY_xxxx + +// extended funcs + +void CALLBACK CDVDconfigure(); +void CALLBACK CDVDabout(); +s32 CALLBACK CDVDtest(); + +#endif + +/* DEV9 plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef DEV9defs + +// basic funcs + +s32 CALLBACK DEV9init(); +s32 CALLBACK DEV9open(void *pDsp); +void CALLBACK DEV9close(); +void CALLBACK DEV9shutdown(); +u8 CALLBACK DEV9read8(u32 addr); +u16 CALLBACK DEV9read16(u32 addr); +u32 CALLBACK DEV9read32(u32 addr); +void CALLBACK DEV9write8(u32 addr, u8 value); +void CALLBACK DEV9write16(u32 addr, u16 value); +void CALLBACK DEV9write32(u32 addr, u32 value); +void CALLBACK DEV9readDMA8Mem(u32 *pMem, int size); +void CALLBACK DEV9writeDMA8Mem(u32 *pMem, int size); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK DEV9irqCallback(DEV9callback callback); +DEV9handler CALLBACK DEV9irqHandler(void); + +// extended funcs + +s32 CALLBACK DEV9freeze(int mode, freezeData *data); +void CALLBACK DEV9configure(); +void CALLBACK DEV9about(); +s32 CALLBACK DEV9test(); + +#endif + +/* USB plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef USBdefs + +// basic funcs + +s32 CALLBACK USBinit(); +s32 CALLBACK USBopen(void *pDsp); +void CALLBACK USBclose(); +void CALLBACK USBshutdown(); +u8 CALLBACK USBread8(u32 addr); +u16 CALLBACK USBread16(u32 addr); +u32 CALLBACK USBread32(u32 addr); +void CALLBACK USBwrite8(u32 addr, u8 value); +void CALLBACK USBwrite16(u32 addr, u16 value); +void CALLBACK USBwrite32(u32 addr, u32 value); +// cycles = IOP cycles before calling callback, +// if callback returns 1 the irq is triggered, else not +void CALLBACK USBirqCallback(USBcallback callback); +USBhandler CALLBACK USBirqHandler(void); +void CALLBACK USBsetRAM(void *mem); + +// extended funcs + +s32 CALLBACK USBfreeze(int mode, freezeData *data); +void CALLBACK USBconfigure(); +void CALLBACK USBabout(); +s32 CALLBACK USBtest(); + +#endif +/* Firewire plugin API */ + +// if this file is included with this define +// the next api will not be skipped by the compiler +#ifdef FIREWIREdefs +// basic funcs + +s32 CALLBACK FireWireinit(); +s32 CALLBACK FireWireopen(void *pDsp); +void CALLBACK FireWireclose(); +void CALLBACK FireWireshutdown(); +u32 CALLBACK FireWireread32(u32 addr); +void CALLBACK FireWirewrite32(u32 addr, u32 value); +void CALLBACK FireWireirqCallback(void (*callback)()); + +// extended funcs + +s32 CALLBACK FireWirefreeze(int mode, freezeData *data); +void CALLBACK FireWireconfigure(); +void CALLBACK FireWireabout(); +s32 CALLBACK FireWiretest(); +#endif + +// might be useful for emulators +#ifdef PLUGINtypedefs + +typedef u32 (CALLBACK* _PS2EgetLibType)(void); +typedef u32 (CALLBACK* _PS2EgetLibVersion2)(u32 type); +typedef char*(CALLBACK* _PS2EgetLibName)(void); + +// GS +typedef s32 (CALLBACK* _GSinit)(); +typedef s32 (CALLBACK* _GSopen)(void *pDsp, char *Title); +typedef void (CALLBACK* _GSclose)(); +typedef void (CALLBACK* _GSshutdown)(); +typedef void (CALLBACK* _GSvsync)(); +typedef void (CALLBACK* _GSwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _GSwrite64)(u32 mem, u64 value); +typedef u32 (CALLBACK* _GSread32)(u32 mem); +typedef u64 (CALLBACK* _GSread64)(u32 mem); +typedef void (CALLBACK* _GSgifTransfer1)(u32 *pMem); +typedef void (CALLBACK* _GSgifTransfer2)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSgifTransfer3)(u32 *pMem, u32 size); +typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem); + +typedef void (CALLBACK* _GSkeyEvent)(keyEvent* ev); +typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); +typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); +typedef void (CALLBACK* _GSgetDriverInfo)(GSdriverInfo *info); +#ifdef __WIN32__ +typedef s32 (CALLBACK* _GSsetWindowInfo)(winInfo *info); +#endif +typedef void (CALLBACK* _GSmakeSnapshot)(char *path); +typedef s32 (CALLBACK* _GSfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _GSconfigure)(); +typedef s32 (CALLBACK* _GStest)(); +typedef void (CALLBACK* _GSabout)(); + +// PAD +typedef s32 (CALLBACK* _PADinit)(u32 flags); +typedef s32 (CALLBACK* _PADopen)(void *pDsp); +typedef void (CALLBACK* _PADclose)(); +typedef void (CALLBACK* _PADshutdown)(); +typedef keyEvent* (CALLBACK* _PADkeyEvent)(); +typedef u8 (CALLBACK* _PADstartPoll)(int pad); +typedef u8 (CALLBACK* _PADpoll)(u8 value); +typedef u32 (CALLBACK* _PADquery)(); + +typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info); +typedef void (CALLBACK* _PADconfigure)(); +typedef s32 (CALLBACK* _PADtest)(); +typedef void (CALLBACK* _PADabout)(); + +// SPU2 +typedef s32 (CALLBACK* _SPU2init)(); +typedef s32 (CALLBACK* _SPU2open)(void *pDsp); +typedef void (CALLBACK* _SPU2close)(); +typedef void (CALLBACK* _SPU2shutdown)(); +typedef void (CALLBACK* _SPU2write)(u32 mem, u16 value); +typedef u16 (CALLBACK* _SPU2read)(u32 mem); +typedef void (CALLBACK* _SPU2readDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA4Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA4)(); +typedef void (CALLBACK* _SPU2readDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2writeDMA7Mem)(u16 *pMem, int size); +typedef void (CALLBACK* _SPU2interruptDMA7)(); +typedef void (CALLBACK* _SPU2irqCallback)(void (*callback)()); + +typedef void (CALLBACK* _SPU2async)(u32 cycles); +typedef s32 (CALLBACK* _SPU2freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _SPU2configure)(); +typedef s32 (CALLBACK* _SPU2test)(); +typedef void (CALLBACK* _SPU2about)(); + +// CDVD +typedef s32 (CALLBACK* _CDVDinit)(); +typedef s32 (CALLBACK* _CDVDopen)(); +typedef void (CALLBACK* _CDVDclose)(); +typedef void (CALLBACK* _CDVDshutdown)(); +typedef s32 (CALLBACK* _CDVDreadTrack)(u32 lsn, int mode); +typedef u8* (CALLBACK* _CDVDgetBuffer)(); +typedef s32 (CALLBACK* _CDVDgetTN)(cdvdTN *Buffer); +typedef s32 (CALLBACK* _CDVDgetTD)(u8 Track, cdvdTD *Buffer); +typedef s32 (CALLBACK* _CDVDgetType)(); +typedef s32 (CALLBACK* _CDVDgetTrayStatus)(); + +typedef void (CALLBACK* _CDVDconfigure)(); +typedef s32 (CALLBACK* _CDVDtest)(); +typedef void (CALLBACK* _CDVDabout)(); + +// DEV9 +typedef s32 (CALLBACK* _DEV9init)(); +typedef s32 (CALLBACK* _DEV9open)(void *pDsp); +typedef void (CALLBACK* _DEV9close)(); +typedef void (CALLBACK* _DEV9shutdown)(); +typedef u8 (CALLBACK* _DEV9read8)(u32 mem); +typedef u16 (CALLBACK* _DEV9read16)(u32 mem); +typedef u32 (CALLBACK* _DEV9read32)(u32 mem); +typedef void (CALLBACK* _DEV9write8)(u32 mem, u8 value); +typedef void (CALLBACK* _DEV9write16)(u32 mem, u16 value); +typedef void (CALLBACK* _DEV9write32)(u32 mem, u32 value); +typedef void (CALLBACK* _DEV9readDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9writeDMA8Mem)(u32 *pMem, int size); +typedef void (CALLBACK* _DEV9irqCallback)(DEV9callback callback); +typedef DEV9handler (CALLBACK* _DEV9irqHandler)(void); + +typedef s32 (CALLBACK* _DEV9freeze)(int mode, freezeData *data); +typedef void (CALLBACK* _DEV9configure)(); +typedef s32 (CALLBACK* _DEV9test)(); +typedef void (CALLBACK* _DEV9about)(); + +// USB +typedef s32 (CALLBACK* _USBinit)(); +typedef s32 (CALLBACK* _USBopen)(void *pDsp); +typedef void (CALLBACK* _USBclose)(); +typedef void (CALLBACK* _USBshutdown)(); +typedef u8 (CALLBACK* _USBread8)(u32 mem); +typedef u16 (CALLBACK* _USBread16)(u32 mem); +typedef u32 (CALLBACK* _USBread32)(u32 mem); +typedef void (CALLBACK* _USBwrite8)(u32 mem, u8 value); +typedef void (CALLBACK* _USBwrite16)(u32 mem, u16 value); +typedef void (CALLBACK* _USBwrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _USBirqCallback)(USBcallback callback); +typedef USBhandler (CALLBACK* _USBirqHandler)(void); +typedef void (CALLBACK* _USBsetRAM)(void *mem); + +typedef s32 (CALLBACK* _USBfreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _USBconfigure)(); +typedef s32 (CALLBACK* _USBtest)(); +typedef void (CALLBACK* _USBabout)(); + +//FireWire +typedef s32 (CALLBACK* _FireWireinit)(); +typedef s32 (CALLBACK* _FireWireopen)(void *pDsp); +typedef void (CALLBACK* _FireWireclose)(); +typedef void (CALLBACK* _FireWireshutdown)(); +typedef u32 (CALLBACK* _FireWireread32)(u32 mem); +typedef void (CALLBACK* _FireWirewrite32)(u32 mem, u32 value); +typedef void (CALLBACK* _FireWireirqCallback)(void (*callback)()); + +typedef s32 (CALLBACK* _FireWirefreeze)(int mode, freezeData *data); +typedef void (CALLBACK* _FireWireconfigure)(); +typedef s32 (CALLBACK* _FireWiretest)(); +typedef void (CALLBACK* _FireWireabout)(); + +#endif + +#ifdef PLUGINfuncs + +// GS +_GSinit GSinit; +_GSopen GSopen; +_GSclose GSclose; +_GSshutdown GSshutdown; +_GSvsync GSvsync; +_GSwrite32 GSwrite32; +_GSwrite64 GSwrite64; +_GSread32 GSread32; +_GSread64 GSread64; +_GSgifTransfer1 GSgifTransfer1; +_GSgifTransfer2 GSgifTransfer2; +_GSgifTransfer3 GSgifTransfer3; +_GSreadFIFO GSreadFIFO; + +_GSkeyEvent GSkeyEvent; +_GSmakeSnapshot GSmakeSnapshot; +_GSirqCallback GSirqCallback; +_GSprintf GSprintf; +_GSgetDriverInfo GSgetDriverInfo; +#ifdef __WIN32__ +_GSsetWindowInfo GSsetWindowInfo; +#endif +_GSfreeze GSfreeze; +_GSconfigure GSconfigure; +_GStest GStest; +_GSabout GSabout; + +// PAD1 +_PADinit PAD1init; +_PADopen PAD1open; +_PADclose PAD1close; +_PADshutdown PAD1shutdown; +_PADkeyEvent PAD1keyEvent; +_PADstartPoll PAD1startPoll; +_PADpoll PAD1poll; +_PADquery PAD1query; + +_PADgsDriverInfo PAD1gsDriverInfo; +_PADconfigure PAD1configure; +_PADtest PAD1test; +_PADabout PAD1about; + +// PAD2 +_PADinit PAD2init; +_PADopen PAD2open; +_PADclose PAD2close; +_PADshutdown PAD2shutdown; +_PADkeyEvent PAD2keyEvent; +_PADstartPoll PAD2startPoll; +_PADpoll PAD2poll; +_PADquery PAD2query; + +_PADgsDriverInfo PAD2gsDriverInfo; +_PADconfigure PAD2configure; +_PADtest PAD2test; +_PADabout PAD2about; + +// SPU2 +_SPU2init SPU2init; +_SPU2open SPU2open; +_SPU2close SPU2close; +_SPU2shutdown SPU2shutdown; +_SPU2write SPU2write; +_SPU2read SPU2read; +_SPU2readDMA4Mem SPU2readDMA4Mem; +_SPU2writeDMA4Mem SPU2writeDMA4Mem; +_SPU2interruptDMA4 SPU2interruptDMA4; +_SPU2readDMA7Mem SPU2readDMA7Mem; +_SPU2writeDMA7Mem SPU2writeDMA7Mem; +_SPU2interruptDMA7 SPU2interruptDMA7; +_SPU2irqCallback SPU2irqCallback; + +_SPU2async SPU2async; +_SPU2freeze SPU2freeze; +_SPU2configure SPU2configure; +_SPU2test SPU2test; +_SPU2about SPU2about; + +// CDVD +_CDVDinit CDVDinit; +_CDVDopen CDVDopen; +_CDVDclose CDVDclose; +_CDVDshutdown CDVDshutdown; +_CDVDreadTrack CDVDreadTrack; +_CDVDgetBuffer CDVDgetBuffer; +_CDVDgetTN CDVDgetTN; +_CDVDgetTD CDVDgetTD; +_CDVDgetType CDVDgetType; +_CDVDgetTrayStatus CDVDgetTrayStatus; + +_CDVDconfigure CDVDconfigure; +_CDVDtest CDVDtest; +_CDVDabout CDVDabout; + +// DEV9 +_DEV9init DEV9init; +_DEV9open DEV9open; +_DEV9close DEV9close; +_DEV9shutdown DEV9shutdown; +_DEV9read8 DEV9read8; +_DEV9read16 DEV9read16; +_DEV9read32 DEV9read32; +_DEV9write8 DEV9write8; +_DEV9write16 DEV9write16; +_DEV9write32 DEV9write32; +_DEV9readDMA8Mem DEV9readDMA8Mem; +_DEV9writeDMA8Mem DEV9writeDMA8Mem; +_DEV9irqCallback DEV9irqCallback; +_DEV9irqHandler DEV9irqHandler; + +_DEV9configure DEV9configure; +_DEV9freeze DEV9freeze; +_DEV9test DEV9test; +_DEV9about DEV9about; + +// USB +_USBinit USBinit; +_USBopen USBopen; +_USBclose USBclose; +_USBshutdown USBshutdown; +_USBread8 USBread8; +_USBread16 USBread16; +_USBread32 USBread32; +_USBwrite8 USBwrite8; +_USBwrite16 USBwrite16; +_USBwrite32 USBwrite32; +_USBirqCallback USBirqCallback; +_USBirqHandler USBirqHandler; +_USBsetRAM USBsetRAM; + +_USBconfigure USBconfigure; +_USBfreeze USBfreeze; +_USBtest USBtest; +_USBabout USBabout; + +// FireWire +_FireWireinit FireWireinit; +_FireWireopen FireWireopen; +_FireWireclose FireWireclose; +_FireWireshutdown FireWireshutdown; +_FireWireread32 FireWireread32; +_FireWirewrite32 FireWirewrite32; +_FireWireirqCallback FireWireirqCallback; + +_FireWireconfigure FireWireconfigure; +_FireWirefreeze FireWirefreeze; +_FireWiretest FireWiretest; +_FireWireabout FireWireabout; +#endif + +#endif /* __PS2EDEFS_H__ */ diff --git a/plugins/usb/USBnull/PS2Etypes.h b/plugins/usb/USBnull/PS2Etypes.h new file mode 100644 index 0000000..443ad45 --- /dev/null +++ b/plugins/usb/USBnull/PS2Etypes.h @@ -0,0 +1,31 @@ +#ifndef __PS2ETYPES_H__ +#define __PS2ETYPES_H__ + +// Basic types +#if defined(__WIN32__) + +typedef __int8 s8; +typedef __int16 s16; +typedef __int32 s32; +typedef __int64 s64; + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +#elif defined(__LINUX__) + +typedef char s8; +typedef short s16; +typedef long s32; +typedef long long s64; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef unsigned long long u64; + +#endif + +#endif /* __PS2ETYPES_H__ */ diff --git a/plugins/usb/USBnull/ReadMe.txt b/plugins/usb/USBnull/ReadMe.txt new file mode 100644 index 0000000..f916e59 --- /dev/null +++ b/plugins/usb/USBnull/ReadMe.txt @@ -0,0 +1,34 @@ +USBnull v0.4 +------------- + + This is an extension to use with play station2 emulators + as PCSX2 (only one right now). + The plugin is free open source code. + +Usage: +----- + Place the file "usbnull.dll" (win32) or usbnull.dll (win64) + at the Plugin directory of the Emulator to use it. + +Changes: +------- + v0.4: +*project files for vs2005 beta1 .64bit dll should work okay (not tested!) + + v0.3: + *up to pcsx2 specs 0.5.5 + *added ini and option for logging + *small adds around.. + + v0.2: + * First Release + * Tested with Pcsx2 + +Authors: +------- + +shadow + + + + diff --git a/plugins/usb/USBnull/USB.c b/plugins/usb/USBnull/USB.c new file mode 100644 index 0000000..1f17696 --- /dev/null +++ b/plugins/usb/USBnull/USB.c @@ -0,0 +1,170 @@ +/* USBlinuz + * Copyright (C) 2002-2005 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "USB.h" + + + +const unsigned char version = PS2E_USB_VERSION; +const unsigned char revision = 0; +const unsigned char build = 5; // increase that with each version + +static char *libraryName = "USBnull Driver"; + +u32 CALLBACK PS2EgetLibType() { + return PS2E_LT_USB; +} + +char* CALLBACK PS2EgetLibName() { + return libraryName; +} + +u32 CALLBACK PS2EgetLibVersion2(u32 type) { + return (version<<16) | (revision<<8) | build; +} + +void __Log(char *fmt, ...) { + va_list list; + + if (!conf.Log || usbLog == NULL) return; + + va_start(list, fmt); + vfprintf(usbLog, fmt, list); + va_end(list); +} + +s32 CALLBACK USBinit() { + LoadConfig(); + +#ifdef USB_LOG + usbLog = fopen("logs/usbLog.txt", "w"); + if (usbLog) setvbuf(usbLog, NULL, _IONBF, 0); + USB_LOG("usbnull plugin version %d,%d\n",revision,build); + USB_LOG("USBinit\n"); +#endif + + return 0; +} + +void CALLBACK USBshutdown() { +#ifdef USB_LOG + if (usbLog) fclose(usbLog); +#endif +} + +s32 CALLBACK USBopen(void *pDsp) { +#ifdef USB_LOG + USB_LOG("USBopen\n"); +#endif + +#ifdef _WIN32 +#else + Display* dsp = *(Display**)pDsp; +#endif + + return 0; +} + +void CALLBACK USBclose() { +} + +u8 CALLBACK USBread8(u32 addr) { + + + +#ifdef USB_LOG + USB_LOG("*UnKnown 8bit read at address %lx ", addr); +#endif + return 0; +} + +u16 CALLBACK USBread16(u32 addr) { + + + +#ifdef USB_LOG + USB_LOG("*UnKnown 16bit read at address %lx", addr); +#endif + return 0; +} + +u32 CALLBACK USBread32(u32 addr) { + +#ifdef USB_LOG + USB_LOG("*UnKnown 32bit read at address %lx", addr); +#endif + return 0; +} + +void CALLBACK USBwrite8(u32 addr, u8 value) { + +#ifdef USB_LOG + USB_LOG("*UnKnown 8bit write at address %lx value %x\n", addr, value); +#endif +} + +void CALLBACK USBwrite16(u32 addr, u16 value) { + +#ifdef USB_LOG + USB_LOG("*UnKnown 16bit write at address %lx value %x\n", addr, value); +#endif +} + +void CALLBACK USBwrite32(u32 addr, u32 value) { + +#ifdef USB_LOG + USB_LOG("*UnKnown 32bit write at address %lx value %lx\n", addr, value); +#endif +} + +void CALLBACK USBirqCallback(USBcallback callback) { + USBirq = callback; +} + +int CALLBACK _USBirqHandler(void) { + + return 0; +} + +USBhandler CALLBACK USBirqHandler(void) { + return (USBhandler)_USBirqHandler; +} + +void CALLBACK USBsetRAM(void *mem) { + +} + +// extended funcs + + + +s32 CALLBACK USBfreeze(int mode, freezeData *data) { + + + return 0; +} + + +s32 CALLBACK USBtest() { + return 0; +} + diff --git a/plugins/usb/USBnull/USB.h b/plugins/usb/USBnull/USB.h new file mode 100644 index 0000000..73ab583 --- /dev/null +++ b/plugins/usb/USBnull/USB.h @@ -0,0 +1,66 @@ +/* USBlinuz + * Copyright (C) 2002-2004 USBlinuz Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __USB_H__ +#define __USB_H__ + +#include + +#define USBdefs +#include "PS2Edefs.h" + +#ifdef __WIN32__ + +#define usleep(x) Sleep(x / 1000) +#include +#include + +#else + +#include +#include + +#define __inline inline + +#endif + +#define USB_LOG __Log + +typedef struct { + int Log; +} Config; + +Config conf; + + + + +#define PSXCLK 36864000 /* 36.864 Mhz */ + +USBcallback USBirq; + +void SaveConfig(); +void LoadConfig(); + +FILE *usbLog; +void __Log(char *fmt, ...); + +void SysMessage(char *fmt, ...); + +#endif diff --git a/plugins/usb/USBnull/Win32/Config.c b/plugins/usb/USBnull/Win32/Config.c new file mode 100644 index 0000000..ed953cf --- /dev/null +++ b/plugins/usb/USBnull/Win32/Config.c @@ -0,0 +1,51 @@ +#include + +#include "USB.h" + +extern HINSTANCE hInst; +void SaveConfig() +{ + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return; + strcpy(szTemp, "\\inis\\usbnull.ini"); + sprintf(szValue,"%u",Conf1->Log); + WritePrivateProfileString("Interface", "Logging",szValue,szIniFile); + +} + +void LoadConfig() { + FILE *fp; + + + Config *Conf1 = &conf; + char *szTemp; + char szIniFile[256], szValue[256]; + + GetModuleFileName(GetModuleHandle((LPCSTR)hInst), szIniFile, 256); + szTemp = strrchr(szIniFile, '\\'); + + if(!szTemp) return ; + strcpy(szTemp, "\\inis\\usbnull.ini"); + fp=fopen("inis\\usbnull.ini","rt");//check if usbnull.ini really exists + if (!fp) + { + CreateDirectory("inis",NULL); + memset(&conf, 0, sizeof(conf)); + conf.Log = 0;//default value + SaveConfig();//save and return + return ; + } + fclose(fp); + GetPrivateProfileString("Interface", "Logging", NULL, szValue, 20, szIniFile); + Conf1->Log = strtoul(szValue, NULL, 10); + return ; + +} + diff --git a/plugins/usb/USBnull/Win32/Makefile b/plugins/usb/USBnull/Win32/Makefile new file mode 100644 index 0000000..f4ea125 --- /dev/null +++ b/plugins/usb/USBnull/Win32/Makefile @@ -0,0 +1,53 @@ +# +# USBnull Makefile for MINGW32 +# + + +all: plugin + +CPU = ix86 +PLUGIN = USBnull.dll + +CC = gcc +NASM = nasmw +RM = rm -f +AR = ar +STRIP = strip +RC = windres + +OPTIMIZE = -O2 -fomit-frame-pointer -finline-functions -ffast-math -fno-strict-aliasing -m128bit-long-double +FLAGS = -D__WIN32__ -D__MINGW32__ # -DENABLE_NLS -DPACKAGE=\"pcsx2\" +ASMFLAGS = -D__WIN32__ -i.. -i.# -DENABLE_NLS -DPACKAGE=\"pcsx2\" +RC1FLAGS = -d__MINGW32__ +LIBS = -L./ -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +RESOBJ = res.o + +OBJS = ../USB.o +OBJS+= Config.o Win32.o ${RESOBJ} + +DEPS:= $(OBJS:.o=.d) + +CFLAGS = -Wall ${OPTIMIZE} -I. -I.. -I/usr/local/include ${FLAGS} +ASMFLAGS = -f elf ${FLAGS} -i./ -i../ + +plugin: ${OBJS} + dllwrap --def plugin.def -o ${PLUGIN} ${OBJS} +# ${CC} -shared -Wl,--kill-at ${CFLAGS} ${OBJS} -o ${PLUGIN} ${LIBS} + ${STRIP} ${PLUGIN} + +.PHONY: clean plugin + +clean: + ${RM} ${OBJS} ${DEPS} ${PLUGIN} + +%.o: %.asm + ${NASM} ${ASMFLAGS} -o $@ $< + +%.o: %.c + ${CC} ${CFLAGS} -c -o $@ $< -MD -MF $(patsubst %.o,%.d,$@) + +${RESOBJ}: USBnull.rc + ${RC} -D__MINGW32__ -I rc -O coff -o $@ -i $< + +-include ${DEPS} + diff --git a/plugins/usb/USBnull/Win32/USBnull.def b/plugins/usb/USBnull/Win32/USBnull.def new file mode 100644 index 0000000..9acbd11 --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull.def @@ -0,0 +1,27 @@ +; USBlinuz.def : Declares the module parameters for the DLL. + +LIBRARY "USBnull" +DESCRIPTION 'USBnull Driver' + +EXPORTS + ; Explicit exports can go here + PS2EgetLibType @2 + PS2EgetLibName @3 + PS2EgetLibVersion2 @4 + USBinit @5 + USBshutdown @6 + USBopen @7 + USBclose @8 + USBread8 @9 + USBread16 @10 + USBread32 @11 + USBwrite8 @12 + USBwrite16 @13 + USBwrite32 @14 + USBirqCallback @15 + USBirqHandler @16 + USBsetRAM @17 + + USBconfigure @18 + USBtest @19 + USBabout @20 diff --git a/plugins/usb/USBnull/Win32/USBnull.dsp b/plugins/usb/USBnull/Win32/USBnull.dsp new file mode 100644 index 0000000..b40466a --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull.dsp @@ -0,0 +1,85 @@ +# Microsoft Developer Studio Project File - Name="USBnull" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=USBnull - WIN32 RELEASE +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "USBnull.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "USBnull.mak" CFG="USBnull - WIN32 RELEASE" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "USBnull - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USBnull_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USBnull_EXPORTS" /D "__WIN32__" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x2c0a /d "NDEBUG" +# ADD RSC /l 0x2c0a /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# Begin Target + +# Name "USBnull - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Config.c +# End Source File +# Begin Source File + +SOURCE=..\USB.c +# End Source File +# Begin Source File + +SOURCE=.\Win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\USBnull.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/usb/USBnull/Win32/USBnull.dsw b/plugins/usb/USBnull/Win32/USBnull.dsw new file mode 100644 index 0000000..bf79c96 --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "USBnull"=".\USBnull.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/usb/USBnull/Win32/USBnull.rc b/plugins/usb/USBnull/Win32/USBnull.rc new file mode 100644 index 0000000..3f817c9 --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// + +#include "afxres.h" + + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Argentina) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESS) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIG DIALOGEX 0, 0, 212, 121 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "USBconfigure" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,48,100,50,14 + PUSHBUTTON "Cancel",IDCANCEL,113,100,50,14 + CONTROL "Enable logging(for develop use only)",IDC_LOGGING, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,159,15 +END + +IDD_ABOUT DIALOGEX 0, 0, 177, 106 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "USBabout" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,65,85,50,14 + LTEXT "USBnull Driver",IDC_NAME,70,10,47,8 + GROUPBOX "",IDC_STATIC,5,35,170,40 + LTEXT "Author: shadow@pcsx2.net",IDC_STATIC,20,20,141,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 170 + TOPMARGIN, 7 + BOTTOMMARGIN, 99 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Spanish (Argentina) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/usb/USBnull/Win32/USBnull_vc2003.sln b/plugins/usb/USBnull/Win32/USBnull_vc2003.sln new file mode 100644 index 0000000..490038a --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull_vc2003.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBnull", "USBnull_vc2003.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.ActiveCfg = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug.Build.0 = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.ActiveCfg = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBnull/Win32/USBnull_vc2003.vcproj b/plugins/usb/USBnull/Win32/USBnull_vc2003.vcproj new file mode 100644 index 0000000..b1cdf5b --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull_vc2003.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.sln b/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.sln new file mode 100644 index 0000000..48ee6e2 --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "USBnull", "USBnull_vc2005beta1.vcproj", "{BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + amd64|Win32 = amd64|Win32 + amd64|Win64 (AMD64) = amd64|Win64 (AMD64) + Debug|Win32 = Debug|Win32 + Debug|Win64 (AMD64) = Debug|Win64 (AMD64) + Release|Win32 = Release|Win32 + Release|Win64 (AMD64) = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win32.ActiveCfg = amd64|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win32.Build.0 = amd64|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win64 (AMD64).ActiveCfg = amd64|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.amd64|Win64 (AMD64).Build.0 = amd64|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win32.ActiveCfg = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win32.Build.0 = Debug|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win32.ActiveCfg = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win32.Build.0 = Release|Win32 + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64) + {BF7B81A5-E348-4F7C-A69F-F74C8EEEAD70}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.vcproj b/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.vcproj new file mode 100644 index 0000000..aa819f9 --- /dev/null +++ b/plugins/usb/USBnull/Win32/USBnull_vc2005beta1.vcproj @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/usb/USBnull/Win32/Win32.c b/plugins/usb/USBnull/Win32/Win32.c new file mode 100644 index 0000000..a290a77 --- /dev/null +++ b/plugins/usb/USBnull/Win32/Win32.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#include "USB.h" +#include "resource.h" + +HINSTANCE hInst; + +void SysMessage(char *fmt, ...) { + va_list list; + char tmp[512]; + + va_start(list,fmt); + vsprintf(tmp,fmt,list); + va_end(list); + MessageBox(0, tmp, "USBnull Msg", 0); +} + +BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + switch(uMsg) { + case WM_INITDIALOG: + LoadConfig(); + if (conf.Log) CheckDlgButton(hW, IDC_LOGGING, TRUE); + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hW, TRUE); + return TRUE; + case IDOK: + if (IsDlgButtonChecked(hW, IDC_LOGGING)) + conf.Log = 1; + else conf.Log = 0; + SaveConfig(); + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + EndDialog(hW, FALSE); + return TRUE; + } + } + return FALSE; +} + +void CALLBACK USBconfigure() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_CONFIG), + GetActiveWindow(), + (DLGPROC)ConfigureDlgProc); +} + +void CALLBACK USBabout() { + DialogBox(hInst, + MAKEINTRESOURCE(IDD_ABOUT), + GetActiveWindow(), + (DLGPROC)AboutDlgProc); +} + +BOOL APIENTRY DllMain(HANDLE hModule, // DLL INIT + DWORD dwReason, + LPVOID lpReserved) { + hInst = (HINSTANCE)hModule; + return TRUE; // very quick :) +} + diff --git a/plugins/usb/USBnull/Win32/afxresmw.h b/plugins/usb/USBnull/Win32/afxresmw.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/usb/USBnull/Win32/afxresmw.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/usb/USBnull/Win32/mingw/Makefile.win b/plugins/usb/USBnull/Win32/mingw/Makefile.win new file mode 100644 index 0000000..2fb5ec8 --- /dev/null +++ b/plugins/usb/USBnull/Win32/mingw/Makefile.win @@ -0,0 +1,43 @@ +# Project: USBnull +# Makefile created by Dev-C++ 4.9.9.2 + +CPP = mingw32-g++.exe +CC = mingw32-gcc.exe +WINDRES = windres.exe +RES = Obj//USBnull_private.res +OBJ = Obj//Win32.o Obj//Config.o Obj//USB.o $(RES) +LINKOBJ = Obj//Win32.o Obj//Config.o Obj//USB.o $(RES) +LIBS = -L"C:/Develop/Dev-Cpp/lib" --def ../plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32 +INCS = -I"C:/Develop/Dev-Cpp/include" -I"../" -I"../../" -I"../.." +CXXINCS = -I"C:/Develop/Dev-Cpp/include" -I"../" -I"../../" -I"../.." +BIN = USBnull.dll +CXXFLAGS = $(CXXINCS) +CFLAGS = $(INCS) -Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32__ +RM = rm -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before USBnull.dll all-after + + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +DLLWRAP=dllwrap.exe +DEFFILE=libUSBnull.def +STATICLIB=libUSBnull.a + +$(BIN): $(LINKOBJ) + $(DLLWRAP) --output-def $(DEFFILE) --implib $(STATICLIB) $(LINKOBJ) $(LIBS) -o $(BIN) + +Obj//Win32.o: ../Win32.c + $(CC) -c ../Win32.c -o Obj//Win32.o $(CFLAGS) + +Obj//Config.o: ../Config.c + $(CC) -c ../Config.c -o Obj//Config.o $(CFLAGS) + +Obj//USB.o: ../../USB.c + $(CC) -c ../../USB.c -o Obj//USB.o $(CFLAGS) + +Obj//USBnull_private.res: USBnull_private.rc ../USBnull.rc + $(WINDRES) -i USBnull_private.rc --input-format=rc -o Obj//USBnull_private.res -O coff --include-dir ../mingw --include-dir ../ diff --git a/plugins/usb/USBnull/Win32/mingw/USBnull.dev b/plugins/usb/USBnull/Win32/mingw/USBnull.dev new file mode 100644 index 0000000..9a0830c --- /dev/null +++ b/plugins/usb/USBnull/Win32/mingw/USBnull.dev @@ -0,0 +1,138 @@ +[Project] +FileName=USBnull.dev +Name=USBnull +UnitCount=9 +Type=3 +Ver=1 +ObjFiles= +Includes=../;../../;../.. +Libs= +PrivateResource=USBnull_private.rc +ResourceIncludes=..\mingw;../ +MakeIncludes= +Compiler=-Wall -O2 -fomit-frame-pointer -D__WIN32__ -D__MINGW32___@@_ +CppCompiler= +Linker=--def ../plugin.def -lcomctl32 -lwsock32 -lwinmm -lgdi32 -lcomdlg32_@@_ +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput=Obj/ +OverrideOutput=0 +OverrideOutputName=USBnull.dll +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 + +[Unit1] +FileName=afxres.h +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit2] +FileName=..\Win32.c +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\Config.c +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\resource.h +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\USBnull.rc +Folder=USBnull +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\..\USB.h +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\..\PS2Edefs.h +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=..\..\PS2Etypes.h +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=..\..\USB.c +CompileCpp=0 +Folder=USBnull +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/plugins/usb/USBnull/Win32/mingw/USBnull.layout b/plugins/usb/USBnull/Win32/mingw/USBnull.layout new file mode 100644 index 0000000..c30ca06 --- /dev/null +++ b/plugins/usb/USBnull/Win32/mingw/USBnull.layout @@ -0,0 +1,50 @@ +[Editor_4] +CursorCol=1 +CursorRow=12 +TopLine=1 +LeftChar=1 +Open=0 +Top=0 +[Editors] +Focused=-1 +Order=-1,0 +[Editor_0] +Open=1 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=1 +LeftChar=1 +[Editor_1] +Open=1 +Top=1 +CursorCol=1 +CursorRow=5 +TopLine=1 +LeftChar=1 +[Editor_2] +Open=0 +Top=0 +[Editor_3] +Open=0 +Top=0 +[Editor_5] +Open=0 +Top=0 +CursorCol=1 +CursorRow=1 +TopLine=27 +LeftChar=1 +[Editor_6] +Open=0 +Top=0 +[Editor_7] +Open=0 +Top=0 +[Editor_8] +Open=0 +Top=0 +CursorCol=1 +CursorRow=24 +TopLine=4 +LeftChar=1 diff --git a/plugins/usb/USBnull/Win32/mingw/afxres.h b/plugins/usb/USBnull/Win32/mingw/afxres.h new file mode 100644 index 0000000..8a4b9df --- /dev/null +++ b/plugins/usb/USBnull/Win32/mingw/afxres.h @@ -0,0 +1,5 @@ + +#include +#include + +#define IDC_STATIC (-1) diff --git a/plugins/usb/USBnull/Win32/plugin.def b/plugins/usb/USBnull/Win32/plugin.def new file mode 100644 index 0000000..a995f0f --- /dev/null +++ b/plugins/usb/USBnull/Win32/plugin.def @@ -0,0 +1,22 @@ +EXPORTS + PS2EgetLibName = PS2EgetLibName@0 @5 + PS2EgetLibType = PS2EgetLibType@0 @6 + PS2EgetLibVersion2 = PS2EgetLibVersion2@4 @7 + USBabout = USBabout@0 @10 + USBclose = USBclose@0 @11 + USBconfigure = USBconfigure@0 @12 + USBfreeze = USBfreeze@8 @13 + USBinit = USBinit@0 @14 + USBirq @15 DATA + USBirqCallback = USBirqCallback@4 @16 + USBirqHandler = USBirqHandler@0 @17 + USBopen = USBopen@4 @18 + USBread16 = USBread16@4 @19 + USBread32 = USBread32@4 @20 + USBread8 = USBread8@4 @21 + USBsetRAM = USBsetRAM@4 @22 + USBshutdown = USBshutdown@0 @23 + USBtest = USBtest@0 @24 + USBwrite16 = USBwrite16@8 @25 + USBwrite32 = USBwrite32@8 @26 + USBwrite8 = USBwrite8@8 @27 diff --git a/plugins/usb/USBnull/Win32/resource.h b/plugins/usb/USBnull/Win32/resource.h new file mode 100644 index 0000000..510a606 --- /dev/null +++ b/plugins/usb/USBnull/Win32/resource.h @@ -0,0 +1,21 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by USBnull.rc +// +#define IDD_CONFDLG 101 +#define IDD_CONFIG 101 +#define IDD_ABOUT 103 +#define IDC_NAME 1000 +#define IDC_CHECK1 1007 +#define IDC_LOGGING 1007 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 105 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1008 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/usb/USBnull/build.sh b/plugins/usb/USBnull/build.sh new file mode 100644 index 0000000..98f56bb --- /dev/null +++ b/plugins/usb/USBnull/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +echo ---------------- +echo Building USBnull +echo ---------------- + +curdir=`pwd` + +cd ${curdir}/Linux +make $@ + +if [ $? -ne 0 ] +then +exit 1 +fi + +if [ -s cfgUSBnull ] && [ -s libUSBnull.so ] +then +cp cfgUSBnull libUSBnull.so ${PCSX2PLUGINS} +fi diff --git a/plugins/usb/build.sh b/plugins/usb/build.sh new file mode 100644 index 0000000..a87cf0b --- /dev/null +++ b/plugins/usb/build.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +echo ----------------------- +echo Building USB plugins... +echo ----------------------- + +curdir=`pwd` + +cd ${curdir}/USBnull +sh build.sh $@ + +if [ $? -ne 0 ] +then +exit 1 +fi diff --git a/test.bat b/test.bat new file mode 100644 index 0000000..d830449 --- /dev/null +++ b/test.bat @@ -0,0 +1,3 @@ +set PATH=./testtools;%PATH% +bash --noprofile --norc --login -i test.sh +pause \ No newline at end of file diff --git a/test.cfg b/test.cfg new file mode 100644 index 0000000..eae4c14 --- /dev/null +++ b/test.cfg @@ -0,0 +1,2 @@ +gameid -frame 100 -numimages 15 -loadini type1.ini +somegame2 -frame 100 -numimages 10 -loadini type2.ini diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..e402a85 --- /dev/null +++ b/test.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# main settings +runexe='./pcsx2.exe' + +results=results`date +'%Y%m%d%H%M'` + +echo "Creating results directory ${results}/..." +mkdir $results + +exec 0

H{y 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